| 1 | import type { DocsHooksDict } from "../types"; |
| 2 | |
| 3 | /** 「在事件发生时运行命令」页的简体中文词典;与 `en/docs-hooks.ts` 逐段对应。 */ |
| 4 | export const docsHooks: DocsHooksDict = { |
| 5 | metaTitle: "在事件发生时运行命令 · Codewhale 文档", |
| 6 | metaDescription: |
| 7 | "在会话开始、工具调用之前、回合结束或 Codewhale 等你回应时运行你自己的脚本——用来补充上下文、执行规则或接收通知。", |
| 8 | bodyClassName: "text-ink-soft leading-[1.9] tracking-wide", |
| 9 | title: "在事件发生时运行命令", |
| 10 | lede: |
| 11 | "钩子会在 Codewhale 会话的特定时刻运行你指定的命令。可以用它拦下危险的命令、给消息补充上下文、记录发生了什么,或者在 Codewhale 等你回应时提醒你。", |
| 12 | sections: [ |
| 13 | { |
| 14 | id: "first-hook", |
| 15 | title: "添加第一个钩子", |
| 16 | blocks: [ |
| 17 | { p: "钩子写在 `~/.codewhale/config.toml` 中。下面这个钩子会在每次会话开始时打印一行文字:" }, |
| 18 | { |
| 19 | code: `[hooks] |
| 20 | enabled = true |
| 21 | |
| 22 | [[hooks.hooks]] |
| 23 | name = "announce" |
| 24 | event = "session_start" |
| 25 | command = "echo 'Codewhale session started'"`, |
| 26 | lang: "config.toml", |
| 27 | }, |
| 28 | { |
| 29 | p: "启动一个会话,运行 `/hooks`,就能看到所有已配置的钩子、钩子总开关是否打开,以及被拒绝加载的条目。`/hooks events` 会列出所有事件名称。", |
| 30 | }, |
| 31 | ], |
| 32 | }, |
| 33 | { |
| 34 | id: "gate", |
| 35 | title: "在命令执行前拦下它", |
| 36 | blocks: [ |
| 37 | { |
| 38 | p: "`tool_call_before` 钩子会在每次工具调用执行之前看到它,并可以放行、拒绝,或强制弹出审批提示。下面这个钩子会拒绝强制推送。保存脚本并赋予可执行权限:", |
| 39 | }, |
| 40 | { |
| 41 | code: `#!/bin/sh |
| 42 | # ~/.codewhale/hooks/no-force-push.sh |
| 43 | case "$DEEPSEEK_TOOL_ARGS" in |
| 44 | *"push --force"*|*"push -f"*) |
| 45 | echo '{"decision": "deny", "reason": "Force-push is blocked by a hook."}' ;; |
| 46 | esac |
| 47 | exit 0`, |
| 48 | lang: "no-force-push.sh", |
| 49 | }, |
| 50 | { |
| 51 | code: `[[hooks.hooks]] |
| 52 | name = "no-force-push" |
| 53 | event = "tool_call_before" |
| 54 | command = "~/.codewhale/hooks/no-force-push.sh" |
| 55 | condition = { type = "tool_name", name = "bash" }`, |
| 56 | lang: "config.toml", |
| 57 | }, |
| 58 | { |
| 59 | p: "钩子从环境变量中读取这次调用,并在标准输出上用 JSON 作答:`allow`、`deny` 或 `ask`,还可以附带 `reason`、改写后的输入(`updatedInput`)或给模型的补充上下文(`additionalContext`)。退出码 2 一律表示拒绝。多个钩子同时作答时,拒绝优先于询问,询问优先于放行。", |
| 60 | }, |
| 61 | { |
| 62 | note: "在 Ask 和 Auto-Review 下,`ask` 会强制弹出提示。Full Access 从不显示审批提示,因此在那里 `ask` 不会新增提示。", |
| 63 | }, |
| 64 | ], |
| 65 | }, |
| 66 | { |
| 67 | id: "events", |
| 68 | title: "选择触发时机", |
| 69 | blocks: [ |
| 70 | { |
| 71 | p: "有三个事件能改变接下来发生的事,其余事件只做观察:它们的输出会被忽略,失败也只会产生警告。", |
| 72 | }, |
| 73 | { |
| 74 | rows: [ |
| 75 | ["message_submit", "在你的消息发给模型之前。可以替换文本,或阻止发送。"], |
| 76 | ["tool_call_before", "在每次工具调用之前。可以放行、拒绝、询问、改写输入或补充上下文。"], |
| 77 | ["shell_env", "在每条 shell 命令运行之前。可以添加环境变量。"], |
| 78 | ["session_start / session_end", "会话打开时,或正常关闭时。"], |
| 79 | ["turn_end", "回合结束后,附带状态、耗时和 token 用量。"], |
| 80 | ["tool_call_after", "每个工具结果返回之后,有退出码时会附带退出码。"], |
| 81 | ["waiting_for_user", "Codewhale 开始等待你的审批、回答或暂停中的目标时。"], |
| 82 | ["session_idle / session_busy", "会话闲下来,或重新开始工作时。"], |
| 83 | ["session_error / on_error", "回合最终失败时,或发生任何错误、工具失败时。"], |
| 84 | ["mode_change", "在 Plan、Work、Operate 之间切换时。"], |
| 85 | ["subagent_spawn / subagent_complete", "子智能体启动或结束时。"], |
| 86 | ], |
| 87 | codeTerms: true, |
| 88 | }, |
| 89 | { |
| 90 | p: "`condition` 可以缩小钩子的触发范围:按工具名(支持 `*` 通配)、工具类别、模式或退出码,也可以用 `all` 和 `any` 组合。永远不可能与所属事件匹配的条件,会在加载配置时直接被拒绝——这样你以为已经生效的拦截规则,不会悄无声息地失效。", |
| 91 | }, |
| 92 | ], |
| 93 | }, |
| 94 | { |
| 95 | id: "options", |
| 96 | title: "设置超时与失败行为", |
| 97 | blocks: [ |
| 98 | { |
| 99 | rows: [ |
| 100 | ["timeout_secs", "钩子最长可运行多久。默认 30 秒。"], |
| 101 | ["continue_on_error", "`true`(默认):钩子失败只发出警告。`false`:失败即阻止。"], |
| 102 | ["background", "`true` 表示只作为观察者运行,不能阻止或改写。"], |
| 103 | ["working_dir", "写在 `[hooks]` 下:钩子的运行目录。默认是会话的工作区。"], |
| 104 | ], |
| 105 | codeTerms: true, |
| 106 | }, |
| 107 | { |
| 108 | note: "`[hooks] default_timeout_secs` 会替换每个钩子自己的 `timeout_secs`,而不只是补上未设置的那些。如果想让各钩子使用各自的超时,请不要设置它。", |
| 109 | }, |
| 110 | ], |
| 111 | }, |
| 112 | { |
| 113 | id: "project", |
| 114 | title: "使用仓库自带的钩子", |
| 115 | blocks: [ |
| 116 | { |
| 117 | p: "仓库可以在 `.codewhale/hooks.toml` 中附带钩子。由于它们会在你的机器上运行命令,只有在你信任该工作区,并且批准了这份文件的确切内容之后,才会加载:", |
| 118 | }, |
| 119 | { code: "/hooks review\n/hooks approve <digest>\n/hooks revoke", lang: "Codewhale" }, |
| 120 | { |
| 121 | p: "`/hooks review` 会显示其中的命令以及文件摘要;批准该摘要后,从下一次会话起启用这份确切的内容。文件有任何改动都需要重新批准。命令调用的脚本也请一并审阅。", |
| 122 | }, |
| 123 | ], |
| 124 | }, |
| 125 | { |
| 126 | id: "headless", |
| 127 | title: "在脚本和 CI 中使用钩子", |
| 128 | blocks: [ |
| 129 | { |
| 130 | p: "钩子在交互式会话中运行。`codewhale exec` 默认不触发任何钩子;加上 `--hooks` 后会触发 `tool_call_before` 和 `shell_env`。由于没有人可以回应,`ask` 会被当作拒绝。", |
| 131 | }, |
| 132 | { code: 'codewhale exec --auto --hooks "run the test suite and fix the first failure"', lang: "终端" }, |
| 133 | ], |
| 134 | }, |
| 135 | ], |
| 136 | next: [ |
| 137 | { |
| 138 | href: "/docs/modes", |
| 139 | label: "设置模式与审批", |
| 140 | note: "钩子的决定如何与 Ask、Auto-Review 和 Full Access 共同起作用。", |
| 141 | }, |
| 142 | { |
| 143 | href: "/docs/mcp", |
| 144 | label: "用 MCP 连接工具", |
| 145 | note: "用同样的 `tool_call_before` 钩子管控 MCP 工具。", |
| 146 | }, |
| 147 | { |
| 148 | href: "/docs/configuration", |
| 149 | label: "修改设置", |
| 150 | note: "`config.toml` 在哪里,以及项目可以覆盖哪些设置。", |
| 151 | }, |
| 152 | ], |
| 153 | sourceNote: "来源文档:docs/HOOKS.md(权威)、docs/CONFIGURATION.md · 修改时同步更新 docs-map.ts。", |
| 154 | }; |
| 155 |