( event: HookEvent, hook: HookCommand, input: string, env: NodeJS.ProcessEnv, )
| 179 | } |
| 180 | |
| 181 | private async runOne( |
| 182 | event: HookEvent, |
| 183 | hook: HookCommand, |
| 184 | input: string, |
| 185 | env: NodeJS.ProcessEnv, |
| 186 | ): Promise<PerHookResult> { |
| 187 | const timeoutMs = (hook.timeout && hook.timeout > 0 ? hook.timeout : DEFAULT_TIMEOUT_S) * 1000 |
| 188 | let raw: RawHookOutput |
| 189 | try { |
| 190 | raw = await execHookCommand(hook.command, input, timeoutMs, this.ctx.cwd, env, this.ctx.getSignal?.()) |
| 191 | } catch (error) { |
| 192 | this.surface(`Hook failed to start: ${(error as Error).message}`, true) |
| 193 | return {} |
| 194 | } |
| 195 | |
| 196 | const { stdout, stderr, code, timedOut } = raw |
| 197 | if (timedOut) { |
| 198 | this.surface(`Hook timed out after ${timeoutMs / 1000}s: ${truncate(hook.command, 80)}`, true) |
| 199 | } |
| 200 | |
| 201 | const { json, plainText } = parseHookOutput(stdout) |
| 202 | const result: PerHookResult = {} |
| 203 | |
| 204 | if (json) { |
| 205 | if (json.continue === false) { |
| 206 | result.stopAll = true |
| 207 | result.stopReason = json.stopReason |
| 208 | } |
| 209 | if (typeof json.systemMessage === "string" && json.systemMessage) { |
| 210 | this.surface(json.systemMessage, false) |
| 211 | } |
| 212 | if (json.decision === "approve") { |
| 213 | result.permissionDecision = "allow" |
| 214 | } else if (json.decision === "block") { |
| 215 | result.blocked = true |
| 216 | result.blockReason = json.reason || "Blocked by hook" |
| 217 | } |
| 218 | |
| 219 | const hso = json.hookSpecificOutput |
| 220 | if (hso && typeof hso === "object") { |
| 221 | const pd = hso.permissionDecision |
| 222 | if (hso.hookEventName === "PreToolUse" && pd) { |
| 223 | if (pd === "allow") { |
| 224 | result.permissionDecision = "allow" |
| 225 | } else if (pd === "deny") { |
| 226 | result.permissionDecision = "deny" |
| 227 | result.blocked = true |
| 228 | result.blockReason = hso.permissionDecisionReason || json.reason || "Blocked by hook" |
| 229 | } else if (pd === "ask") { |
| 230 | result.permissionDecision = "ask" |
| 231 | } |
| 232 | } |
| 233 | if (typeof hso.permissionDecisionReason === "string") { |
| 234 | result.permissionReason = hso.permissionDecisionReason |
| 235 | } |
| 236 | if (hso.updatedInput && typeof hso.updatedInput === "object") { |
| 237 | result.updatedInput = hso.updatedInput |
| 238 | } |
no test coverage detected