(
permissionMode?: string,
signal?: AbortSignal,
timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS,
stopHookActive: boolean = false,
subagentId?: AgentId,
toolUseContext?: ToolUseContext,
messages?: Message[],
agentType?: string,
requestPrompt?: (
sourceName: string,
toolInputSummary?: string | null,
) => (request: PromptRequest) => Promise<PromptResponse>,
)
| 3637 | * @returns Async generator that yields progress messages and blocking errors |
| 3638 | */ |
| 3639 | export async function* executeStopHooks( |
| 3640 | permissionMode?: string, |
| 3641 | signal?: AbortSignal, |
| 3642 | timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS, |
| 3643 | stopHookActive: boolean = false, |
| 3644 | subagentId?: AgentId, |
| 3645 | toolUseContext?: ToolUseContext, |
| 3646 | messages?: Message[], |
| 3647 | agentType?: string, |
| 3648 | requestPrompt?: ( |
| 3649 | sourceName: string, |
| 3650 | toolInputSummary?: string | null, |
| 3651 | ) => (request: PromptRequest) => Promise<PromptResponse>, |
| 3652 | ): AsyncGenerator<AggregatedHookResult> { |
| 3653 | const hookEvent = subagentId ? 'SubagentStop' : 'Stop' |
| 3654 | const appState = toolUseContext?.getAppState() |
| 3655 | const sessionId = toolUseContext?.agentId ?? getSessionId() |
| 3656 | if (!hasHookForEvent(hookEvent, appState, sessionId)) { |
| 3657 | return |
| 3658 | } |
| 3659 | |
| 3660 | // Extract text content from the last assistant message so hooks can |
| 3661 | // inspect the final response without reading the transcript file. |
| 3662 | const lastAssistantMessage = messages |
| 3663 | ? getLastAssistantMessage(messages) |
| 3664 | : undefined |
| 3665 | const lastAssistantText = lastAssistantMessage |
| 3666 | ? extractTextContent(lastAssistantMessage.message.content, '\n').trim() || |
| 3667 | undefined |
| 3668 | : undefined |
| 3669 | |
| 3670 | const hookInput: StopHookInput | SubagentStopHookInput = subagentId |
| 3671 | ? { |
| 3672 | ...createBaseHookInput(permissionMode), |
| 3673 | hook_event_name: 'SubagentStop', |
| 3674 | stop_hook_active: stopHookActive, |
| 3675 | agent_id: subagentId, |
| 3676 | agent_transcript_path: getAgentTranscriptPath(subagentId), |
| 3677 | agent_type: agentType ?? '', |
| 3678 | last_assistant_message: lastAssistantText, |
| 3679 | } |
| 3680 | : { |
| 3681 | ...createBaseHookInput(permissionMode), |
| 3682 | hook_event_name: 'Stop', |
| 3683 | stop_hook_active: stopHookActive, |
| 3684 | last_assistant_message: lastAssistantText, |
| 3685 | } |
| 3686 | |
| 3687 | // Trust check is now centralized in executeHooks() |
| 3688 | yield* executeHooks({ |
| 3689 | hookInput, |
| 3690 | toolUseID: randomUUID(), |
| 3691 | signal, |
| 3692 | timeoutMs, |
| 3693 | toolUseContext, |
| 3694 | messages, |
| 3695 | requestPrompt, |
| 3696 | }) |
no test coverage detected