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