Add hooks for interrupted turns (#40511)

## What changed

- Add an `Interrupt` hook event that runs for an active top-level turn before its
  interrupted abort event is emitted.
- Flush the turn transcript before invoking the hook and provide the session,
  turn, transcript, working directory, model, and permission mode in its input.
- Support command and MCP handlers, including asynchronous commands, with a
  one-second default timeout and a three-second maximum.
- Expose the event through hook configuration, managed requirements, app-server
  notifications, generated schemas, analytics, and the TUI hook views.

## Testing

- Cover handler discovery, timeout normalization, output parsing, protocol
  compatibility, TUI rendering, and interrupt execution ordering.

GitOrigin-RevId: 163fa7c098d94ac2775f6d137f8e916f8ea9b6eb
This commit is contained in:
Andrei Eternal
2026-08-25 01:27:18 +00:00
committed by copyberry
parent 9b2ef38f54
commit cbfd999db7
49 changed files with 1393 additions and 48 deletions
@@ -2098,7 +2098,8 @@
"userPromptSubmit",
"subagentStart",
"subagentStop",
"stop"
"stop",
"interrupt"
],
"type": "string"
},
@@ -12463,7 +12463,8 @@
"userPromptSubmit",
"subagentStart",
"subagentStop",
"stop"
"stop",
"interrupt"
],
"type": "string"
},
@@ -13586,6 +13587,13 @@
},
"ManagedHooksRequirements": {
"properties": {
"Interrupt": {
"default": [],
"items": {
"$ref": "#/definitions/v2/ConfiguredHookMatcherGroup"
},
"type": "array"
},
"PermissionRequest": {
"items": {
"$ref": "#/definitions/v2/ConfiguredHookMatcherGroup"
@@ -8552,7 +8552,8 @@
"userPromptSubmit",
"subagentStart",
"subagentStop",
"stop"
"stop",
"interrupt"
],
"type": "string"
},
@@ -9736,6 +9737,13 @@
},
"ManagedHooksRequirements": {
"properties": {
"Interrupt": {
"default": [],
"items": {
"$ref": "#/definitions/ConfiguredHookMatcherGroup"
},
"type": "array"
},
"PermissionRequest": {
"items": {
"$ref": "#/definitions/ConfiguredHookMatcherGroup"
@@ -720,6 +720,13 @@
},
"ManagedHooksRequirements": {
"properties": {
"Interrupt": {
"default": [],
"items": {
"$ref": "#/definitions/ConfiguredHookMatcherGroup"
},
"type": "array"
},
"PermissionRequest": {
"items": {
"$ref": "#/definitions/ConfiguredHookMatcherGroup"
@@ -17,7 +17,8 @@
"userPromptSubmit",
"subagentStart",
"subagentStop",
"stop"
"stop",
"interrupt"
],
"type": "string"
},
@@ -17,7 +17,8 @@
"userPromptSubmit",
"subagentStart",
"subagentStop",
"stop"
"stop",
"interrupt"
],
"type": "string"
},
@@ -32,7 +32,8 @@
"userPromptSubmit",
"subagentStart",
"subagentStop",
"stop"
"stop",
"interrupt"
],
"type": "string"
},
@@ -120,7 +120,8 @@
"userPromptSubmit",
"subagentStart",
"subagentStop",
"stop"
"stop",
"interrupt"
],
"type": "string"
},
@@ -2,4 +2,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type HookEventName = "preToolUse" | "permissionRequest" | "postToolUse" | "preCompact" | "postCompact" | "sessionStart" | "sessionEnd" | "userPromptSubmit" | "subagentStart" | "subagentStop" | "stop";
export type HookEventName = "preToolUse" | "permissionRequest" | "postToolUse" | "preCompact" | "postCompact" | "sessionStart" | "sessionEnd" | "userPromptSubmit" | "subagentStart" | "subagentStop" | "stop" | "interrupt";
@@ -3,4 +3,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ConfiguredHookMatcherGroup } from "./ConfiguredHookMatcherGroup";
export type ManagedHooksRequirements = { managedDir: string | null, windowsManagedDir: string | null, PreToolUse: Array<ConfiguredHookMatcherGroup>, PermissionRequest: Array<ConfiguredHookMatcherGroup>, PostToolUse: Array<ConfiguredHookMatcherGroup>, PreCompact: Array<ConfiguredHookMatcherGroup>, PostCompact: Array<ConfiguredHookMatcherGroup>, SessionStart: Array<ConfiguredHookMatcherGroup>, SessionEnd: Array<ConfiguredHookMatcherGroup>, UserPromptSubmit: Array<ConfiguredHookMatcherGroup>, SubagentStart: Array<ConfiguredHookMatcherGroup>, SubagentStop: Array<ConfiguredHookMatcherGroup>, Stop: Array<ConfiguredHookMatcherGroup>, };
export type ManagedHooksRequirements = { managedDir: string | null, windowsManagedDir: string | null, PreToolUse: Array<ConfiguredHookMatcherGroup>, PermissionRequest: Array<ConfiguredHookMatcherGroup>, PostToolUse: Array<ConfiguredHookMatcherGroup>, PreCompact: Array<ConfiguredHookMatcherGroup>, PostCompact: Array<ConfiguredHookMatcherGroup>, SessionStart: Array<ConfiguredHookMatcherGroup>, SessionEnd: Array<ConfiguredHookMatcherGroup>, UserPromptSubmit: Array<ConfiguredHookMatcherGroup>, SubagentStart: Array<ConfiguredHookMatcherGroup>, SubagentStop: Array<ConfiguredHookMatcherGroup>, Stop: Array<ConfiguredHookMatcherGroup>, Interrupt: Array<ConfiguredHookMatcherGroup>, };