Path: blob/main/extensions/copilot/src/platform/chat/common/chatHookService.ts
13401 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import type * as vscode from 'vscode';6import { createServiceIdentifier } from '../../../util/common/services';78export const IChatHookService = createServiceIdentifier<IChatHookService>('IChatHookService');910export interface IChatHookService {11readonly _serviceBrand: undefined;1213/**14* Log telemetry about which hook types are configured for a request.15* Should be called once per request to report hook configuration.16*17* @param hooks The resolved hook commands for the session (from request.hooks).18*/19logConfiguredHooks(hooks: vscode.ChatRequestHooks | undefined): void;2021/**22* Execute all hooks of the specified type for the current chat session.23* Hooks are sourced from the resolved hook commands on the chat request.24*25* If a `sessionId` is provided, the session transcript is flushed to disk26* before the hook runs so that hook scripts see up-to-date content.27*28* @param hookType The type of hook to execute.29* @param hooks The resolved hook commands for the session (from request.hooks).30* @param input Input data to pass to the hook via stdin (will be JSON-serialized).31* @param sessionId Optional session ID — when provided the transcript is flushed first.32* @param token Optional cancellation token.33* @returns A promise that resolves to an array of hook execution results.34*/35executeHook(hookType: vscode.ChatHookType, hooks: vscode.ChatRequestHooks | undefined, input: unknown, sessionId?: string, token?: vscode.CancellationToken): Promise<vscode.ChatHookResult[]>;3637/**38* Execute the preToolUse hook and collapse results from all hooks into a single result.39*40* Multiple hooks' decisions are collapsed using the most restrictive rule: deny > ask > allow.41* `updatedInput` uses the last hook's value. `additionalContext` is collected from all hooks.42*43* @param toolName The name of the tool being invoked.44* @param toolInput The input parameters for the tool.45* @param toolCallId The unique ID for this tool call.46* @param hooks The resolved hook commands for the session (from request.hooks).47* @param sessionId Optional session ID — when provided the transcript is flushed first.48* @param token Optional cancellation token.49* @param outputStream Optional output stream for displaying hook warnings/errors.50* @returns The collapsed hook result, or undefined if no hooks are registered or none returned a result.51*/52executePreToolUseHook(toolName: string, toolInput: unknown, toolCallId: string, hooks: vscode.ChatRequestHooks | undefined, sessionId?: string, token?: vscode.CancellationToken, outputStream?: vscode.ChatResponseStream): Promise<IPreToolUseHookResult | undefined>;5354/**55* Execute the postToolUse hook and collapse results from all hooks into a single result.56*57* Called after a tool completes successfully. If any hook returns a 'block' decision,58* the block is included in the result. `additionalContext` is collected from all hooks.59*60* @param toolName The name of the tool that was invoked.61* @param toolInput The input parameters that were passed to the tool.62* @param toolResponseText The text representation of the tool's output.63* @param toolCallId The unique ID for this tool call.64* @param hooks The resolved hook commands for the session (from request.hooks).65* @param sessionId Optional session ID — when provided the transcript is flushed first.66* @param token Optional cancellation token.67* @param outputStream Optional output stream for displaying hook warnings/errors.68* @returns The collapsed hook result, or undefined if no hooks are registered or none returned a result.69*/70executePostToolUseHook(toolName: string, toolInput: unknown, toolResponseText: string, toolCallId: string, hooks: vscode.ChatRequestHooks | undefined, sessionId?: string, token?: vscode.CancellationToken, outputStream?: vscode.ChatResponseStream): Promise<IPostToolUseHookResult | undefined>;71}7273/**74* Collapsed result from all preToolUse hooks.75*/76export interface IPreToolUseHookResult {77permissionDecision?: 'allow' | 'deny' | 'ask';78permissionDecisionReason?: string;79updatedInput?: object;80additionalContext?: string[];81}8283/**84* Collapsed result from all postToolUse hooks.85*/86export interface IPostToolUseHookResult {87decision?: 'block';88reason?: string;89additionalContext?: string[];90}9192//#region Hook Input/Output Types9394/**95* Input passed to the UserPromptSubmit hook.96*/97export interface UserPromptSubmitHookInput {98/**99* The user's prompt text.100*/101readonly prompt: string;102}103104/**105* Output from the UserPromptSubmit hook.106*/107export interface UserPromptSubmitHookOutput {108/**109* Set to "block" to prevent the user prompt from being submitted to the agent.110*/111readonly decision?: 'block';112/**113* Tells the agent why it should continue.114*/115readonly reason?: string;116/**117* Hook-specific output from the UserPromptSubmit hook.118* This is nested under `hookSpecificOutput` to match the JSON contract used119* by other hook types.120*/121readonly hookSpecificOutput?: {122readonly hookEventName?: string;123/**124* Additional context to add to the agent's context.125* When multiple sources provide context (SessionStart/SubagentStart/UserPromptSubmit),126* they are concatenated.127*/128readonly additionalContext?: string;129};130}131132/**133* Input passed to the Stop hook.134*/135export interface StopHookInput {136/**137* True when the agent is already continuing as a result of a stop hook.138* Check this value or process the transcript to prevent the agent from running indefinitely.139*/140readonly stop_hook_active: boolean;141}142143/**144* Output from the Stop hook.145*/146export interface StopHookOutput {147/**148* Hook-specific output from the Stop hook.149* This is nested under `hookSpecificOutput` to match the JSON contract used150* by other hook types.151*/152readonly hookSpecificOutput?: {153readonly hookEventName?: string;154/**155* Set to "block" to prevent the agent from stopping.156* Omit or set to undefined to allow the agent to stop.157*/158readonly decision?: 'block';159/**160* Required when decision is "block". Tells the agent why it should continue.161*/162readonly reason?: string;163};164}165166/**167* Input passed to the SessionStart hook.168*/169export interface SessionStartHookInput {170/**171* The source of the session start. Always "new".172*/173readonly source: 'new';174/**175* The model identifier (e.g. "claude-sonnet-4-6").176*/177readonly model: string;178/**179* The agent or mode name, if applicable.180*/181readonly agent_type?: string;182}183184/**185* Output from the SessionStart hook.186*/187export interface SessionStartHookOutput {188/**189* Hook-specific output from the SessionStart hook.190* This is nested under `hookSpecificOutput` to match the JSON contract used191* by other hook types.192*/193readonly hookSpecificOutput?: {194readonly hookEventName?: string;195/**196* Additional context to add to the agent's context.197* Multiple hooks' values are concatenated.198*/199readonly additionalContext?: string;200};201}202203/**204* Input passed to the SubagentStart hook.205*/206export interface SubagentStartHookInput {207/**208* The unique identifier for the subagent.209*/210readonly agent_id: string;211/**212* The agent name (built-in agents like "Plan" or custom agent names).213*/214readonly agent_type: string;215}216217/**218* Output from the SubagentStart hook.219*/220export interface SubagentStartHookOutput {221/**222* Hook-specific output from the SubagentStart hook.223* This is nested under `hookSpecificOutput` to match the JSON contract used224* by other hook types.225*/226readonly hookSpecificOutput?: {227readonly hookEventName?: string;228/**229* Additional context to add to the subagent's context.230*/231readonly additionalContext?: string;232};233}234235/**236* Input passed to the SubagentStop hook.237*/238export interface SubagentStopHookInput {239/**240* The unique identifier for the subagent.241*/242readonly agent_id: string;243/**244* The agent name (built-in agents like "Plan" or custom agent names).245*/246readonly agent_type: string;247/**248* True when the agent is already continuing as a result of a stop hook.249* Check this value or process the transcript to prevent the agent from running indefinitely.250*/251readonly stop_hook_active: boolean;252}253254/**255* Output from the SubagentStop hook.256*/257export interface SubagentStopHookOutput {258/**259* Hook-specific output from the SubagentStop hook.260* This is nested under `hookSpecificOutput` to match the JSON contract used261* by other hook types.262*/263readonly hookSpecificOutput?: {264readonly hookEventName?: string;265/**266* Set to "block" to prevent the agent from stopping.267* Omit or set to undefined to allow the agent to stop.268*/269readonly decision?: 'block';270/**271* Required when decision is "block". Tells the agent why it should continue.272*/273readonly reason?: string;274};275}276277/**278* Input passed to the PreCompact hook.279*/280export interface PreCompactHookInput {281/**282* How the compaction was triggered.283* "auto" when the conversation is too long for the prompt budget.284*/285readonly trigger: 'auto';286/**287* Custom instructions for the compaction, if any.288*/289readonly custom_instructions?: string;290}291292//#endregion293294295