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