(
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>,
)
| 3728 | * @returns Async generator that yields progress messages and blocking errors |
| 3729 | */ |
| 3730 | export async function* executeStopHooks( |
| 3731 | permissionMode?: string, |
| 3732 | signal?: AbortSignal, |
| 3733 | timeoutMs: number = TOOL_HOOK_EXECUTION_TIMEOUT_MS, |
| 3734 | stopHookActive: boolean = false, |
| 3735 | subagentId?: AgentId, |
| 3736 | toolUseContext?: ToolUseContext, |
| 3737 | messages?: Message[], |
| 3738 | agentType?: string, |
| 3739 | requestPrompt?: ( |
| 3740 | sourceName: string, |
| 3741 | toolInputSummary?: string | null, |
| 3742 | ) => (request: PromptRequest) => Promise<PromptResponse>, |
| 3743 | ): AsyncGenerator<AggregatedHookResult> { |
| 3744 | const hookEvent = subagentId ? 'SubagentStop' : 'Stop' |
| 3745 | const appState = toolUseContext?.getAppState() |
| 3746 | const sessionId = toolUseContext?.agentId ?? getSessionId() |
| 3747 | if (!hasHookForEvent(hookEvent, appState, sessionId)) { |
| 3748 | return |
| 3749 | } |
| 3750 | |
| 3751 | // Extract text content from the last assistant message so hooks can |
| 3752 | // inspect the final response without reading the transcript file. |
| 3753 | const lastAssistantMessage = messages |
| 3754 | ? getLastAssistantMessage(messages) |
| 3755 | : undefined |
| 3756 | const lastAssistantContent = lastAssistantMessage?.message?.content |
| 3757 | const lastAssistantText = lastAssistantMessage |
| 3758 | ? (Array.isArray(lastAssistantContent) |
| 3759 | ? extractTextContent(lastAssistantContent as readonly { readonly type: string }[], '\n').trim() |
| 3760 | : typeof lastAssistantContent === 'string' |
| 3761 | ? lastAssistantContent.trim() |
| 3762 | : '') || undefined |
| 3763 | : undefined |
| 3764 | |
| 3765 | const hookInput: StopHookInput | SubagentStopHookInput = subagentId |
| 3766 | ? { |
| 3767 | ...createBaseHookInput(permissionMode), |
| 3768 | hook_event_name: 'SubagentStop', |
| 3769 | stop_hook_active: stopHookActive, |
| 3770 | agent_id: subagentId, |
| 3771 | agent_transcript_path: getAgentTranscriptPath(subagentId), |
| 3772 | agent_type: agentType ?? '', |
| 3773 | last_assistant_message: lastAssistantText, |
| 3774 | } |
| 3775 | : { |
| 3776 | ...createBaseHookInput(permissionMode), |
| 3777 | hook_event_name: 'Stop', |
| 3778 | stop_hook_active: stopHookActive, |
| 3779 | last_assistant_message: lastAssistantText, |
| 3780 | } |
| 3781 | |
| 3782 | // Trust check is now centralized in executeHooks() |
| 3783 | yield* executeHooks({ |
| 3784 | hookInput, |
| 3785 | toolUseID: randomUUID(), |
| 3786 | signal, |
| 3787 | timeoutMs, |
no test coverage detected