逐个运行 hook 命令。 重要:如果任何一个 hook 返回"拒绝"(exit code 2), 后续的 hook 不再运行,直接返回拒绝结果。 对应源码: hooks.rs:95-150
(
self,
event: HookEvent,
commands: list[str],
tool_name: str,
tool_input: str,
tool_output: Optional[str],
is_error: bool,
)
| 158 | ) |
| 159 | |
| 160 | def _run_commands( |
| 161 | self, |
| 162 | event: HookEvent, |
| 163 | commands: list[str], |
| 164 | tool_name: str, |
| 165 | tool_input: str, |
| 166 | tool_output: Optional[str], |
| 167 | is_error: bool, |
| 168 | ) -> HookRunResult: |
| 169 | """ |
| 170 | 逐个运行 hook 命令。 |
| 171 | |
| 172 | 重要:如果任何一个 hook 返回"拒绝"(exit code 2), |
| 173 | 后续的 hook 不再运行,直接返回拒绝结果。 |
| 174 | |
| 175 | 对应源码: hooks.rs:95-150 |
| 176 | """ |
| 177 | if not commands: |
| 178 | return HookRunResult.allow() |
| 179 | |
| 180 | messages = [] |
| 181 | |
| 182 | for command in commands: |
| 183 | outcome, message = self._run_one_command( |
| 184 | command=command, |
| 185 | event=event, |
| 186 | tool_name=tool_name, |
| 187 | tool_input=tool_input, |
| 188 | tool_output=tool_output, |
| 189 | is_error=is_error, |
| 190 | ) |
| 191 | |
| 192 | if outcome == HookOutcome.ALLOW: |
| 193 | if message: |
| 194 | messages.append(message) |
| 195 | |
| 196 | elif outcome == HookOutcome.DENY: |
| 197 | # 一个 hook 拒绝了 → 立刻返回,不再运行后续 hook |
| 198 | deny_message = message or f"{event.value} hook denied tool `{tool_name}`" |
| 199 | messages.append(deny_message) |
| 200 | return HookRunResult(denied=True, messages=messages) |
| 201 | |
| 202 | elif outcome == HookOutcome.WARN: |
| 203 | messages.append(message) |
| 204 | |
| 205 | return HookRunResult.allow(messages) |
| 206 | |
| 207 | def _run_one_command( |
| 208 | self, |
no test coverage detected