执行单个 hook 命令。源码: hooks.rs:152-205 1. 用 sh -lc 执行 shell 命令 (hooks.rs:239-244) 2. 设环境变量 (hooks.rs:166-172) 3. stdin 管道传 JSON payload (hooks.rs:174, 282-288) 4. 按退出码分类 (hooks.rs:179-196): 0 → Allow, 2 → Deny, 其他 → Warn
(
command: str,
event: HookEvent,
tool_name: str,
tool_input: str,
tool_output: Optional[str],
is_error: bool,
payload: str,
)
| 197 | |
| 198 | @staticmethod |
| 199 | def _run_command( |
| 200 | command: str, |
| 201 | event: HookEvent, |
| 202 | tool_name: str, |
| 203 | tool_input: str, |
| 204 | tool_output: Optional[str], |
| 205 | is_error: bool, |
| 206 | payload: str, |
| 207 | ) -> _HookCommandOutcome: |
| 208 | """执行单个 hook 命令。源码: hooks.rs:152-205 |
| 209 | |
| 210 | 1. 用 sh -lc 执行 shell 命令 (hooks.rs:239-244) |
| 211 | 2. 设环境变量 (hooks.rs:166-172) |
| 212 | 3. stdin 管道传 JSON payload (hooks.rs:174, 282-288) |
| 213 | 4. 按退出码分类 (hooks.rs:179-196): |
| 214 | 0 → Allow, 2 → Deny, 其他 → Warn |
| 215 | """ |
| 216 | # 构建环境变量 — 源码: hooks.rs:166-172 |
| 217 | env = dict(os.environ) |
| 218 | env["HOOK_EVENT"] = event.value |
| 219 | env["HOOK_TOOL_NAME"] = tool_name |
| 220 | env["HOOK_TOOL_INPUT"] = tool_input |
| 221 | env["HOOK_TOOL_IS_ERROR"] = "1" if is_error else "0" |
| 222 | if tool_output is not None: |
| 223 | env["HOOK_TOOL_OUTPUT"] = tool_output |
| 224 | |
| 225 | try: |
| 226 | # sh -lc: login shell 执行命令 — 源码: hooks.rs:239-244 |
| 227 | result = subprocess.run( |
| 228 | ["sh", "-lc", command], |
| 229 | input=payload, |
| 230 | capture_output=True, |
| 231 | text=True, |
| 232 | env=env, |
| 233 | timeout=30, |
| 234 | ) |
| 235 | except FileNotFoundError: |
| 236 | # 命令不存在 → Warn — 源码: hooks.rs:198-204 |
| 237 | return _HookCommandOutcome( |
| 238 | _Outcome.WARN, |
| 239 | f"{event.value} hook `{command}` failed to start for `{tool_name}`: command not found", |
| 240 | ) |
| 241 | except subprocess.TimeoutExpired: |
| 242 | return _HookCommandOutcome( |
| 243 | _Outcome.WARN, |
| 244 | f"{event.value} hook `{command}` timed out for `{tool_name}`", |
| 245 | ) |
| 246 | |
| 247 | stdout = result.stdout.strip() |
| 248 | stderr = result.stderr.strip() |
| 249 | message = stdout if stdout else None |
| 250 | |
| 251 | code = result.returncode |
| 252 | |
| 253 | # 退出码协议 — 源码: hooks.rs:179-196 |
| 254 | if code == 0: |
| 255 | return _HookCommandOutcome(_Outcome.ALLOW, message) |
| 256 |
no test coverage detected