Hooks
Hook 文件位置
~/.omp/agent/hooks/pre/*.ts # global pre-hooks
~/.omp/agent/hooks/post/*.ts # global post-hooks
.omp/hooks/pre/*.ts # project pre-hooks
.omp/hooks/post/*.ts # project post-hooks发现是非递归的:更深层目录的文件会被忽略。CLI 可通过 --hook <path> 显式加载文件,它与 --extension 使用同一加载机制。
Hook 能做什么
| 场景 | 事件 | 返回约定 |
|---|---|---|
| 工具调用门 | tool_call | |
返回 { block: true, reason } 可拒绝调用;reason 会作为工具错误提供给模型。第一个阻止结果生效。 |
| | 工具结果改写 | tool_result |
返回 { content?, details?, isError? } 可修改模型接收到的内容;处理器会按链路依次执行。
| | 每次调用的消息改写 | context |
返回 { messages } 可替换即将发送给模型的消息数组;处理器会按链路依次执行。
| | 上下文压缩门 | session_before_compact |
返回 { cancel: true } 可取消压缩。同样的返回形式适用于 session_before_branch、session_before_switch、session_before_tree。
| | 会话生命周期 |
session_start, session_shutdown, turn_start, turn_end, message_*, tool_execution_*
| 仅用于观测,返回值会被忽略。 |
完整事件列表请查阅 HookAPI 类型。HookAPI 仅提供事件处理能力;ExtensionAPI 是其超集,还能注册命令、工具和渲染器,需要更多能力时应使用 ExtensionAPI.on。
块 rm -rf 在bash中
下面的前置 bash Hook 会在执行前拦截一些危险命令。处理器返回 { block: true, reason },Agent 会把 reason 作为工具错误处理。
// ~/.omp/agent/hooks/pre/guard-rm.ts
import type { HookAPI } from "@oh-my-pi/pi-coding-agent/extensibility/hooks";
const DANGER =
/\brm\s+(-[a-zA-Z]*r[a-zA-Z]*f[a-zA-Z]*|-[a-zA-Z]*f[a-zA-Z]*r[a-zA-Z]*)\s+(\/|~|\$HOME)(\s|$)/;
export default function (pi: HookAPI) {
pi.on("tool_call", (event) => {
if (event.toolName !== "bash") return;
const cmd = String(event.input.command ?? "");
if (DANGER.test(cmd)) {
return { block: true, reason: `Refused: ${cmd.slice(0, 80)}` };
}
});
}多个 Hook 同时阻止时,以第一个
block为准。文件系统的加载顺序是稳定的,但正则表达式应只是最后一道防线,而非唯一的安全措施。
编辑工具输出中的秘密
下面的后置 read Hook 会在模型看到结果前清除其中的 API Key。
// ~/.omp/agent/hooks/post/redact-keys.ts
import type { HookAPI } from "@oh-my-pi/pi-coding-agent/extensibility/hooks";
export default function (pi: HookAPI) {
pi.on("tool_result", (event) => {
if (event.toolName !== "read" || event.isError) return;
const content = event.content.map((c) =>
c.type === "text"
? { ...c, text: c.text.replaceAll(/API_KEY=\S+/g, "API_KEY=[REDACTED]") }
: c,
);
return { content };
});
}调试 Hook
运行 omp -p '/extensions' 可确认 Hook 是否加载及其来源路径。若缺失,说明该文件不在已发现目录中:将其移到 ~/.omp/agent/hooks/pre/ 或 .omp/hooks/pre/,或通过 --hook /path/to/file.ts 显式加载。相关定制能力请参阅提示词模板和 Skills;如需每回合注入静态规则而不是动态拦截,请使用上下文文件。