copilotSessionWrapper.ts ×51

Frontier kind: Code frontier

unlabeled · c_46d00987ab8d

421 tests · 30258 LOC · 151 files · introduces 0 tests · 456 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
71 ranges456 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
2524 ranges30258 lines · 151 files · Browse complete extent
All tests (intent)
421 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 456 introduced LOC across 71 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/agentHost/node/copilot/copilotSessionLauncher.ts 286 introduced LOC · 20 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- copilotSessionLauncher.ts
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 { CopilotClient, ExitPlanModeRequest, ExitPlanModeResult, NamedProviderConfig, PermissionRequestResult, ProviderModelConfig, ResumeSessionConfig, SessionConfig, Tool } from '@github/copilot-sdk';
7 > import { coalesce } from '../../../../base/common/arrays.js';
8 > import { Schemas } from '../../../../base/common/network.js';
9 > import { URI } from '../../../../base/common/uri.js';
10 > import { IFileService } from '../../../files/common/files.js';
11 > import { ILogService, LogLevel } from '../../../log/common/log.js';
12 > import { CopilotCliConfigKey, applyModelFamilyAlias, copilotCliConfigSchema } from '../../common/copilotCliConfig.js';
13 > import { agentHostModelSupportsToolSearch, CLIENT_TOOL_SEARCH_REFERENCE_NAME } from './toolSearchDeferral.js';
14 > import { AgentHostSessionSyncEnabledConfigKey, platformRootSchema, type AgentHostMcpServers } from '../../common/agentHostSchema.js';
15 > import { AgentHostSandboxConfigKey, sandboxConfigSchema } from '../../common/sandboxConfigSchema.js';
16 > import { IAgentConfigurationService } from '../agentConfigurationService.js';
17 > import { IAgentHostTerminalManager } from '../agentHostTerminalManager.js';
18 > import { IByokLmBridgeRegistry } from '../byokLmBridgeRegistry.js';
19 > import { IByokLmProxyService, type IByokLmProxyHandle } from './byokLmProxyService.js';
20 > import type { IByokLmModelInfo } from '../../common/agentHostByokLm.js';
21 > import type { ModelSelection, ToolDefinition } from '../../common/state/protocol/state.js';
22 > import type { ActiveClientToolSet } from '../activeClientState.js';
23 > import { CopilotSessionWrapper } from './copilotSessionWrapper.js';
24 > import { ShellManager, createShellTools, type IUnsandboxedCommandConfirmationRequest } from './copilotShellTools.js';
25 > import { toSdkHooks, toSdkInstructionDirectories, toSdkMcpServers, toSdkMcpServersFromConfigMap, toSdkSessionCustomAgents, toSdkSkillDirectories } from './copilotPluginConverters.js';
26 > import { buildSandboxConfigForSdk, type ISdkSandboxConfig } from './sandboxConfigForSdk.js';
27 > import type { ITypedPermissionRequest } from './copilotToolDisplay.js';
28 > import type { ICopilotPluginInfo } from './copilotAgent.js';
29 > import { agentHostPromptRegistry, type IAgentHostPromptContext } from './prompts/promptRegistry.js';
30 > import { describeSystemMessageConfig } from './prompts/systemMessage.js';
31 > import './prompts/allPrompts.js';
32 > import { StopWatch } from '../../../../base/common/stopwatch.js';
33 >
34 > export const ThinkingLevelConfigKey = 'thinkingLevel';
35 > /**
36 > * Config key for the numeric "Context Size" selection (a context-window token count). Mapped to the
37 > * SDK's two-valued {@link SessionConfig.contextTier} by {@link getCopilotContextTier}.
38 > */
39 > export const ContextSizeConfigKey = 'contextSize';
40 > /**
41 > * @deprecated Legacy config key that stored the resolved tier string (`'default'` / `'long_context'`)
42 > * directly. Replaced by the numeric {@link ContextSizeConfigKey}; still read from persisted sessions
43 > * for backward compatibility.
44 > */
45 > export const ContextTierConfigKey = 'contextTier';
46 >
47 > const ReasoningEfforts = ['low', 'medium', 'high', 'xhigh'] as const;
48 > type ReasoningEffort = NonNullable<SessionConfig['reasoningEffort']>;
49 >
50 > const ContextTiers = ['default', 'long_context'] as const;
51 > type ContextTier = NonNullable<SessionConfig['contextTier']>;
52 > const AGENT_HOST_COPILOT_CLIENT_NAME = 'vscode-agent-host';
53 >
54 > type UserInputHandler = NonNullable<SessionConfig['onUserInputRequest']>;
55 > type UserInputRequest = Parameters<UserInputHandler>[0];
56 > type UserInputInvocation = Parameters<UserInputHandler>[1];
57 > type UserInputResponse = Awaited<ReturnType<UserInputHandler>>;
58 > type ElicitationHandler = NonNullable<SessionConfig['onElicitationRequest']>;
59 > type ElicitationContext = Parameters<ElicitationHandler>[0];
60 > type ElicitationResult = Awaited<ReturnType<ElicitationHandler>>;
61 > type McpAuthHandler = NonNullable<SessionConfig['onMcpAuthRequest']>;
62 > type McpAuthRequest = Parameters<McpAuthHandler>[0];
63 > type McpAuthContext = Parameters<McpAuthHandler>[1];
64 > type McpAuthResponse = Awaited<ReturnType<McpAuthHandler>>;
65 > type SessionHooks = NonNullable<SessionConfig['hooks']>;
66 > type PreToolUseHookInput = Parameters<NonNullable<SessionHooks['onPreToolUse']>>[0];
67 > type PostToolUseHookInput = Parameters<NonNullable<SessionHooks['onPostToolUse']>>[0];
68 > type CopilotSessionLaunchConfig = ResumeSessionConfig & {
69 > readonly pluginDirectories?: string[];
70 > readonly remoteSession?: 'export';
71 > };
72 >
73 > /**
74 > * Immutable snapshot of the active client's structural contributions at
75 > * session creation time. Used to detect when the session needs to be
76 > * refreshed. Root MCP servers participate in restart detection because they
77 > * are merged into the SDK session config. The owning `clientId`s are
78 > * deliberately NOT part of this snapshot: client identity is tracked live via
79 > * {@link ActiveClientToolSet} so a window
80 > * reload (new `clientId`, identical tools/plugins) does not force a restart.
81 > */
82 > export interface IActiveClientSnapshot {
83 > readonly tools: readonly ToolDefinition[];
84 > readonly plugins: readonly ICopilotPluginInfo[];
85 > readonly mcpServers: AgentHostMcpServers;
86 > }
87 >
88 > /**
89 > * The set of client-tool names the agent sees for a snapshot — each tool's
90 > * `ToolDefinition.name` (the camelCase `toolReferenceName`). Used both to gate
91 > * tool-specific prompt sections at launch and to route client tool calls during
92 > * the session, so the two stay derived from one definition.
93 > */
94 > export function clientToolNamesFromSnapshot(snapshot: IActiveClientSnapshot): ReadonlySet<string> {
95 return new Set(snapshot.tools.map(tool => tool.name));
96 }
98 > export interface ICopilotSessionRuntime {
99 > handlePermissionRequest(request: ITypedPermissionRequest): Promise<PermissionRequestResult>;
100 > handleExitPlanModeRequest(request: ExitPlanModeRequest, invocation: { sessionId: string }): Promise<ExitPlanModeResult>;
101 > handleUserInputRequest(request: UserInputRequest, invocation: UserInputInvocation): Promise<UserInputResponse>;
102 > handleElicitationRequest(context: ElicitationContext): Promise<ElicitationResult>;
103 > handleMcpAuthRequest(request: McpAuthRequest, context: McpAuthContext): Promise<McpAuthResponse>;
104 > requestUnsandboxedCommandConfirmation(request: IUnsandboxedCommandConfirmationRequest): Promise<boolean>;
105 > handlePreToolUse(input: PreToolUseHookInput): Promise<void>;
106 > handlePostToolUse(input: PostToolUseHookInput): Promise<void>;
107 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
108 > createClientSdkTools(): Tool<any>[];
109 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
110 > createServerSdkTools(): Tool<any>[];
111 > }
112 >
113 > export interface ICopilotSessionLauncher {
114 > /**
115 > * Creates an unowned SDK session wrapper. The caller is responsible for
116 > * registering or disposing the returned wrapper.
117 > */
118 > launch(plan: CopilotSessionLaunchPlan, runtime: ICopilotSessionRuntime): Promise<CopilotSessionWrapper>;
119 > }
120 >
121 > type CopilotSessionClient = Pick<CopilotClient, 'createSession' | 'resumeSession'>;
122 >
123 > interface ICopilotSessionLaunchBase {
124 > readonly client: CopilotSessionClient;
125 > readonly sessionId: string;
126 > readonly workingDirectory: URI | undefined;
127 > readonly resolvedAgentName: string | undefined;
128 > readonly snapshot: IActiveClientSnapshot;
129 > /**
130 > * Live, long-lived registry of every active client's tool contributions.
131 > * Read at tool-call stamp time so a window reload (new `clientId`,
132 > * identical tools) stamps subsequent client tool calls with the current
133 > * owning id rather than the one frozen into {@link snapshot} at creation,
134 > * and so a tool call is attributed to whichever client contributed it.
135 > */
136 > readonly activeClientToolSet: ActiveClientToolSet;
137 > readonly shellManager: ShellManager | undefined;
138 > readonly githubToken: string | undefined;
139 >
140 > /**
141 > * Whether this is a workspace-less session. Threaded into the
142 > * prompt context so the resolved system message gets the scratch/repoless
143 > * variant. Named to match the `workspaceless` marker used throughout the AH
144 > * layer (session `_meta`, stored metadata) that this value flows from.
145 > */
146 > readonly workspaceless?: boolean;
147 > }
148 >
149 > export interface ICopilotCreateSessionLaunchPlan extends ICopilotSessionLaunchBase {
150 > readonly kind: 'create';
151 > readonly model: ModelSelection | undefined;
152 > readonly longContextWindow?: number;
153 > readonly freeLongContext?: boolean;
154 > }
155 >
156 > export interface ICopilotResumeSessionLaunchPlan extends ICopilotSessionLaunchBase {
157 > readonly kind: 'resume';
158 > readonly workingDirectory: URI;
159 > readonly fallback: {
160 > readonly model: ModelSelection | undefined;
161 > readonly longContextWindow?: number;
162 > readonly freeLongContext?: boolean;
163 > };
164 > }
165 >
166 > export type CopilotSessionLaunchPlan = ICopilotCreateSessionLaunchPlan | ICopilotResumeSessionLaunchPlan;
167 >
168 function isReasoningEffort(value: unknown): value is ReasoningEffort {
169 return ReasoningEfforts.some(reasoningEffort => reasoningEffort === value);
170 }
172 function isContextTier(value: unknown): value is ContextTier {
173 return ContextTiers.some(contextTier => contextTier === value);
174 }
176 function getCopilotSdkErrorCode(err: unknown): number | undefined {
177 if (typeof err !== 'object' || err === null) {
181 return typeof code === 'number' ? code : undefined;
182 }
184 function getErrorMessage(err: unknown): string {
185 if (err instanceof Error) {
194 return String(err);
195 }
197 > /**
198 > * Decide whether a Copilot SDK `resumeSession` failure should fall back to
199 > * `createSession({ sessionId })`. We want to preserve the original
200 > * recovery for empty / truncated sessions (e.g. after the user invoked
201 > * "Start Over", which calls `truncateSession` and leaves the on-disk
202 > * session with zero events - the SDK then refuses to resume it), but we
203 > * must NOT silently swallow corruption / schema-validation / parse
204 > * failures: those should surface so the user sees the real error and the
205 > * original session contents are not masked by a fresh empty session.
206 > *
207 > * Heuristic: any `-32603` Internal Error is treated as the empty-session
208 > * case UNLESS the message clearly indicates corruption, schema
209 > * validation, parse failure, or malformed input.
210 > */
211 function shouldCreateEmptySessionAfterResumeError(err: unknown): boolean {
212 if (getCopilotSdkErrorCode(err) !== -32603) {
217 return !/\b(corrupt|corrupted|invalid|validation|schema|must be|parse|malformed|unexpected token)\b/i.test(message);
218 }
220 function isCustomAgentNotFoundError(err: unknown): boolean {
221 return getCopilotSdkErrorCode(err) === -32603 && /\bCustom agent '.+' not found\b/i.test(getErrorMessage(err));
222 }
224 > /**
225 > * Resolves the reasoning effort: a recognized override level wins over the
226 > * model picker's thinking level; an unrecognized override is ignored (degrades
227 > * to the picker). Validation is against the known effort levels only — the
228 > * caller/operator is responsible for choosing a level the model supports.
229 > */
230 > export function getCopilotReasoningEffort(model: ModelSelection | undefined, effortOverride?: string): SessionConfig['reasoningEffort'] {
231 if (isReasoningEffort(effortOverride)) {
232 return effortOverride;
235 return isReasoningEffort(thinkingLevel) ? thinkingLevel : undefined;
236 }
238 > /**
239 > * Resolves the reasoning effort, applying the host-level override and logging
240 > * whether it applied. Shared by the launcher (create) and
241 > * `CopilotAgent._changeModel` (mid-session model change) for consistency.
242 > */
243 > export function resolveCopilotReasoningEffort(model: ModelSelection | undefined, configurationService: IAgentConfigurationService, logService: ILogService, sessionId: string): SessionConfig['reasoningEffort'] {
244 const rawOverride = configurationService.getRootValue(copilotCliConfigSchema, CopilotCliConfigKey.ReasoningEffortOverride);
245 // '' is the schema's unset marker, so an unset override reads as `undefined`.
254 return getCopilotReasoningEffort(model, override);
255 }
257 > export function getCopilotContextTier(model: ModelSelection | undefined, longContextWindow?: number, freeLongContext?: boolean): SessionConfig['contextTier'] {
258 // Legacy persisted selections stored the resolved tier string directly under the deprecated key.
259 const legacyTier = model?.config?.[ContextTierConfigKey];
279 return selectedWindow >= longContextWindow ? 'long_context' : 'default';
280 }
282 > /**
283 > * Resolve the BYOK provider/model session config for `sessionId` from the
284 > * renderer's active bridge. Returns empty — the session launches without BYOK
285 > * models — when BYOK is gated off (no active bridge), when the renderer reports
286 > * no BYOK models, or when enumeration fails; `startProxy` is invoked only once
287 > * at least one model is present.
288 > *
289 > * Each vendor maps to one `type: 'openai'` / `wireApi: 'completions'` provider
290 > * whose `baseUrl` points at the proxy and authenticates with the session-scoped
291 > * `Bearer <nonce>.<sessionId>`; each model is surfaced under the
292 > * provider-qualified selection id `vendor/id`, matching what the renderer's
293 > * `AgentHostByokLmHandler` resolves.
294 > *
295 > * Extracted from {@link CopilotSessionLauncher} so the synthesis and gating are
296 > * unit-testable without instantiating the launcher; the launcher passes a
297 > * `startProxy` thunk that memoizes the single shared proxy handle.
298 > */
299 export async function resolveByokSessionConfig(
300 sessionId: string,
356 return { providers, models };
357 }
359 > export class CopilotSessionLauncher implements ICopilotSessionLauncher {
360 >
361 > /**
362 > * Memoized handle for the single shared BYOK loopback proxy, started lazily
363 > * on the first session launch that surfaces BYOK models (see
364 > * {@link _resolveByokSessionConfig}). Held as a promise so concurrent
365 > * launches share one bind. Released and cleared by
366 > * {@link disposeByokProxyHandle} when the owning Copilot client/runtime is
367 > * stopped, so the next start mints a fresh nonce.
368 > */
369 > private _byokProxyHandle: Promise<IByokLmProxyHandle> | undefined;
370 >
371 > constructor(
372 @IAgentConfigurationService private readonly _configurationService: IAgentConfigurationService,
373 @IAgentHostTerminalManager private readonly _terminalManager: IAgentHostTerminalManager,
377 @IByokLmBridgeRegistry private readonly _byokLmBridgeRegistry: IByokLmBridgeRegistry,
378 ) { }
380 > async launch(plan: CopilotSessionLaunchPlan, runtime: ICopilotSessionRuntime): Promise<CopilotSessionWrapper> {
381 const config = await this._buildSessionConfig(plan, runtime);
382 const sandboxConfig = this._computeSandboxConfig();
431 }
432 }
434 > private async _createSession(plan: ICopilotCreateSessionLaunchPlan, config: CopilotSessionLaunchConfig, sandboxConfig: ISdkSandboxConfig | undefined): Promise<CopilotSessionWrapper> {
435 const raw = await plan.client.createSession({
436 ...config,
446 return new CopilotSessionWrapper(raw);
447 }
449 > /**
450 > * Compute the SDK-shaped sandbox policy to push to the runtime for the
451 > * SDK's built-in shell tool.
452 > *
453 > * Returns `undefined` when {@link CopilotCliConfigKey.EnableCustomTerminalTool}
454 > * is ON — in that case the AgentHost provides its own shell tools, which
455 > * wrap commands via the host terminal sandbox engine, so no SDK-side
456 > * sandbox policy is needed. Otherwise the policy is derived from the
457 > * host's `sandbox` config bag (forwarded from the workbench's
458 > * `chat.agent.sandbox.*` settings), mirroring what
459 > * `buildSandboxConfigForCLI` does for the Copilot extension's CLI path.
460 > */
461 > private _computeSandboxConfig(): ISdkSandboxConfig | undefined {
462 const enableCustomTerminalTool = this._configurationService.getRootValue(copilotCliConfigSchema, CopilotCliConfigKey.EnableCustomTerminalTool) === true;
463 if (enableCustomTerminalTool) {
466 return buildSandboxConfigForSdk(process.platform, this._configurationService.getRootValue(sandboxConfigSchema, AgentHostSandboxConfigKey.Sandbox));
467 }
469 > /**
470 > * Forward the SDK-shaped sandbox policy to the runtime via
471 > * `session.options.update`, immediately after the session is created or
472 > * resumed. `SessionUpdateOptionsParams.sandboxConfig` is now typed by the
473 > * SDK (as `SandboxConfig`), and our {@link ISdkSandboxConfig} shape is
474 > * structurally assignable to it, so we forward it directly.
475 > *
476 > * No-op when {@link _computeSandboxConfig} returned `undefined` (custom
477 > * terminal tool enabled, or the host sandbox config evaluates to disabled).
478 > */
479 > private async _applySandboxConfig(session: CopilotSessionWrapper['session'], sandboxConfig: ISdkSandboxConfig | undefined, sessionId: string): Promise<void> {
480 if (!sandboxConfig) {
481 return;
488 }
489 }
491 > /**
492 > * Launcher-bound wrapper over {@link resolveByokSessionConfig}: supplies the
493 > * active bridge registry and a `startProxy` thunk that memoizes the single
494 > * shared proxy handle for this launcher (started lazily on first use).
495 > */
496 > private _resolveByokSessionConfig(sessionId: string): Promise<{ providers?: NamedProviderConfig[]; models?: ProviderModelConfig[] }> {
497 return resolveByokSessionConfig(sessionId, this._byokLmBridgeRegistry, () => {
498 if (!this._byokProxyHandle) {
502 }, this._logService);
503 }
505 > /**
506 > * Release the memoized BYOK loopback proxy handle (if any) and clear it so
507 > * the next session launch mints a fresh nonce. Idempotent.
508 > *
509 > * **Ownership invariant.** The caller MUST stop the Copilot client/runtime
510 > * subprocess before invoking this: disposing the handle drops the proxy's
511 > * refcount and may rebind it on a different port/nonce, so a still-running
512 > * subprocess would silently lose its endpoint — see {@link IByokLmProxyHandle}.
513 > * Invoked from `CopilotAgent._stopClient` / `CopilotAgent.shutdown` after the
514 > * client has stopped.
515 > */
516 > async disposeByokProxyHandle(): Promise<void> {
517 const handle = this._byokProxyHandle;
518 this._byokProxyHandle = undefined;
526 }
527 }
529 > private async _buildSessionConfig(plan: CopilotSessionLaunchPlan, runtime: ICopilotSessionRuntime): Promise<CopilotSessionLaunchConfig> {
530 const plugins = plan.snapshot.plugins;
531 // Synthesize BYOK provider/model config (empty when BYOK is gated off or the
src/vs/platform/agentHost/node/copilot/copilotSessionWrapper.ts 170 introduced LOC · 51 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- copilotSessionWrapper.ts
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 { CopilotSession, SessionEvent, SessionEventPayload, SessionEventType } from '@github/copilot-sdk';
7 > import { Emitter, Event } from '../../../../base/common/event.js';
8 > import { Disposable, toDisposable } from '../../../../base/common/lifecycle.js';
9 >
10 > /**
11 > * Thin wrapper around {@link CopilotSession} that exposes each SDK event as a
12 > * proper VS Code `Event<T>`. All subscriptions and the underlying SDK session
13 > * are cleaned up on dispose.
14 > */
15 > export class CopilotSessionWrapper extends Disposable {
16 >
17 > private readonly _handledEventTypes = new Set<SessionEventType>();
18 > private readonly _onUnhandledEvent = this._register(new Emitter<SessionEvent>());
19 > readonly onUnhandledEvent = this._onUnhandledEvent.event;
20 >
21 > constructor(readonly session: CopilotSession) {
22 super();
23 const unsubscribeAll = session.on(event => {
31 }));
32 }
34 > get sessionId(): string { return this.session.sessionId; }
35 >
36 > private _onMessageDelta: Event<SessionEventPayload<'assistant.message_delta'>> | undefined;
37 > get onMessageDelta(): Event<SessionEventPayload<'assistant.message_delta'>> {
38 return this._onMessageDelta ??= this._sdkEvent('assistant.message_delta');
39 }
41 > private _onMessage: Event<SessionEventPayload<'assistant.message'>> | undefined;
42 > get onMessage(): Event<SessionEventPayload<'assistant.message'>> {
43 return this._onMessage ??= this._sdkEvent('assistant.message');
44 }
46 > private _onToolStart: Event<SessionEventPayload<'tool.execution_start'>> | undefined;
47 > get onToolStart(): Event<SessionEventPayload<'tool.execution_start'>> {
48 return this._onToolStart ??= this._sdkEvent('tool.execution_start');
49 }
51 > private _onToolComplete: Event<SessionEventPayload<'tool.execution_complete'>> | undefined;
52 > get onToolComplete(): Event<SessionEventPayload<'tool.execution_complete'>> {
53 return this._onToolComplete ??= this._sdkEvent('tool.execution_complete');
54 }
56 > private _onPermissionRequested: Event<SessionEventPayload<'permission.requested'>> | undefined;
57 > get onPermissionRequested(): Event<SessionEventPayload<'permission.requested'>> {
58 return this._onPermissionRequested ??= this._sdkEvent('permission.requested');
59 }
61 > private _onIdle: Event<SessionEventPayload<'session.idle'>> | undefined;
62 > get onIdle(): Event<SessionEventPayload<'session.idle'>> {
63 return this._onIdle ??= this._sdkEvent('session.idle');
64 }
66 > private _onSessionStart: Event<SessionEventPayload<'session.start'>> | undefined;
67 > get onSessionStart(): Event<SessionEventPayload<'session.start'>> {
68 return this._onSessionStart ??= this._sdkEvent('session.start');
69 }
71 > private _onSessionResume: Event<SessionEventPayload<'session.resume'>> | undefined;
72 > get onSessionResume(): Event<SessionEventPayload<'session.resume'>> {
73 return this._onSessionResume ??= this._sdkEvent('session.resume');
74 }
76 > private _onSessionError: Event<SessionEventPayload<'session.error'>> | undefined;
77 > get onSessionError(): Event<SessionEventPayload<'session.error'>> {
78 return this._onSessionError ??= this._sdkEvent('session.error');
79 }
81 > private _onSessionInfo: Event<SessionEventPayload<'session.info'>> | undefined;
82 > get onSessionInfo(): Event<SessionEventPayload<'session.info'>> {
83 return this._onSessionInfo ??= this._sdkEvent('session.info');
84 }
86 > private _onSessionWarning: Event<SessionEventPayload<'session.warning'>> | undefined;
87 > get onSessionWarning(): Event<SessionEventPayload<'session.warning'>> {
88 return this._onSessionWarning ??= this._sdkEvent('session.warning');
89 }
91 > private _onSessionModelChange: Event<SessionEventPayload<'session.model_change'>> | undefined;
92 > get onSessionModelChange(): Event<SessionEventPayload<'session.model_change'>> {
93 return this._onSessionModelChange ??= this._sdkEvent('session.model_change');
94 }
96 > private _onAutoModeResolved: Event<SessionEventPayload<'session.auto_mode_resolved'>> | undefined;
97 > get onAutoModeResolved(): Event<SessionEventPayload<'session.auto_mode_resolved'>> {
98 return this._onAutoModeResolved ??= this._sdkEvent('session.auto_mode_resolved');
99 }
101 > private _onManagedSettingsResolved: Event<SessionEventPayload<'session.managed_settings_resolved'>> | undefined;
102 > get onManagedSettingsResolved(): Event<SessionEventPayload<'session.managed_settings_resolved'>> {
103 return this._onManagedSettingsResolved ??= this._sdkEvent('session.managed_settings_resolved');
104 }
106 > private _onManagedSettingsEnforced: Event<SessionEventPayload<'session.managed_settings_enforced'>> | undefined;
107 > get onManagedSettingsEnforced(): Event<SessionEventPayload<'session.managed_settings_enforced'>> {
108 return this._onManagedSettingsEnforced ??= this._sdkEvent('session.managed_settings_enforced');
109 }
111 > private _onSessionHandoff: Event<SessionEventPayload<'session.handoff'>> | undefined;
112 > get onSessionHandoff(): Event<SessionEventPayload<'session.handoff'>> {
113 return this._onSessionHandoff ??= this._sdkEvent('session.handoff');
114 }
116 > private _onSessionTruncation: Event<SessionEventPayload<'session.truncation'>> | undefined;
117 > get onSessionTruncation(): Event<SessionEventPayload<'session.truncation'>> {
118 return this._onSessionTruncation ??= this._sdkEvent('session.truncation');
119 }
121 > private _onSessionSnapshotRewind: Event<SessionEventPayload<'session.snapshot_rewind'>> | undefined;
122 > get onSessionSnapshotRewind(): Event<SessionEventPayload<'session.snapshot_rewind'>> {
123 return this._onSessionSnapshotRewind ??= this._sdkEvent('session.snapshot_rewind');
124 }
126 > private _onSessionShutdown: Event<SessionEventPayload<'session.shutdown'>> | undefined;
127 > get onSessionShutdown(): Event<SessionEventPayload<'session.shutdown'>> {
128 return this._onSessionShutdown ??= this._sdkEvent('session.shutdown');
129 }
131 > private _onSessionUsageInfo: Event<SessionEventPayload<'session.usage_info'>> | undefined;
132 > get onSessionUsageInfo(): Event<SessionEventPayload<'session.usage_info'>> {
133 return this._onSessionUsageInfo ??= this._sdkEvent('session.usage_info');
134 }
136 > private _onSessionCompactionStart: Event<SessionEventPayload<'session.compaction_start'>> | undefined;
137 > get onSessionCompactionStart(): Event<SessionEventPayload<'session.compaction_start'>> {
138 return this._onSessionCompactionStart ??= this._sdkEvent('session.compaction_start');
139 }
141 > private _onSessionCompactionComplete: Event<SessionEventPayload<'session.compaction_complete'>> | undefined;
142 > get onSessionCompactionComplete(): Event<SessionEventPayload<'session.compaction_complete'>> {
143 return this._onSessionCompactionComplete ??= this._sdkEvent('session.compaction_complete');
144 }
146 > private _onUserMessage: Event<SessionEventPayload<'user.message'>> | undefined;
147 > get onUserMessage(): Event<SessionEventPayload<'user.message'>> {
148 return this._onUserMessage ??= this._sdkEvent('user.message');
149 }
151 > private _onPendingMessagesModified: Event<SessionEventPayload<'pending_messages.modified'>> | undefined;
152 > get onPendingMessagesModified(): Event<SessionEventPayload<'pending_messages.modified'>> {
153 return this._onPendingMessagesModified ??= this._sdkEvent('pending_messages.modified');
154 }
156 > private _onTurnStart: Event<SessionEventPayload<'assistant.turn_start'>> | undefined;
157 > get onTurnStart(): Event<SessionEventPayload<'assistant.turn_start'>> {
158 return this._onTurnStart ??= this._sdkEvent('assistant.turn_start');
159 }
161 > private _onIntent: Event<SessionEventPayload<'assistant.intent'>> | undefined;
162 > get onIntent(): Event<SessionEventPayload<'assistant.intent'>> {
163 return this._onIntent ??= this._sdkEvent('assistant.intent');
164 }
166 > private _onReasoning: Event<SessionEventPayload<'assistant.reasoning'>> | undefined;
167 > get onReasoning(): Event<SessionEventPayload<'assistant.reasoning'>> {
168 return this._onReasoning ??= this._sdkEvent('assistant.reasoning');
169 }
171 > private _onReasoningDelta: Event<SessionEventPayload<'assistant.reasoning_delta'>> | undefined;
172 > get onReasoningDelta(): Event<SessionEventPayload<'assistant.reasoning_delta'>> {
173 return this._onReasoningDelta ??= this._sdkEvent('assistant.reasoning_delta');
174 }
176 > private _onTurnEnd: Event<SessionEventPayload<'assistant.turn_end'>> | undefined;
177 > get onTurnEnd(): Event<SessionEventPayload<'assistant.turn_end'>> {
178 return this._onTurnEnd ??= this._sdkEvent('assistant.turn_end');
179 }
181 > private _onUsage: Event<SessionEventPayload<'assistant.usage'>> | undefined;
182 > get onUsage(): Event<SessionEventPayload<'assistant.usage'>> {
183 return this._onUsage ??= this._sdkEvent('assistant.usage');
184 }
186 > private _onAbort: Event<SessionEventPayload<'abort'>> | undefined;
187 > get onAbort(): Event<SessionEventPayload<'abort'>> {
188 return this._onAbort ??= this._sdkEvent('abort');
189 }
191 > private _onToolUserRequested: Event<SessionEventPayload<'tool.user_requested'>> | undefined;
192 > get onToolUserRequested(): Event<SessionEventPayload<'tool.user_requested'>> {
193 return this._onToolUserRequested ??= this._sdkEvent('tool.user_requested');
194 }
196 > private _onToolPartialResult: Event<SessionEventPayload<'tool.execution_partial_result'>> | undefined;
197 > get onToolPartialResult(): Event<SessionEventPayload<'tool.execution_partial_result'>> {
198 return this._onToolPartialResult ??= this._sdkEvent('tool.execution_partial_result');
199 }
201 > private _onToolProgress: Event<SessionEventPayload<'tool.execution_progress'>> | undefined;
202 > get onToolProgress(): Event<SessionEventPayload<'tool.execution_progress'>> {
203 return this._onToolProgress ??= this._sdkEvent('tool.execution_progress');
204 }
206 > private _onSkillInvoked: Event<SessionEventPayload<'skill.invoked'>> | undefined;
207 > get onSkillInvoked(): Event<SessionEventPayload<'skill.invoked'>> {
208 return this._onSkillInvoked ??= this._sdkEvent('skill.invoked');
209 }
211 > private _onSubagentStarted: Event<SessionEventPayload<'subagent.started'>> | undefined;
212 > get onSubagentStarted(): Event<SessionEventPayload<'subagent.started'>> {
213 return this._onSubagentStarted ??= this._sdkEvent('subagent.started');
214 }
216 > private _onSubagentCompleted: Event<SessionEventPayload<'subagent.completed'>> | undefined;
217 > get onSubagentCompleted(): Event<SessionEventPayload<'subagent.completed'>> {
218 return this._onSubagentCompleted ??= this._sdkEvent('subagent.completed');
219 }
221 > private _onSubagentFailed: Event<SessionEventPayload<'subagent.failed'>> | undefined;
222 > get onSubagentFailed(): Event<SessionEventPayload<'subagent.failed'>> {
223 return this._onSubagentFailed ??= this._sdkEvent('subagent.failed');
224 }
226 > private _onSubagentSelected: Event<SessionEventPayload<'subagent.selected'>> | undefined;
227 > get onSubagentSelected(): Event<SessionEventPayload<'subagent.selected'>> {
228 return this._onSubagentSelected ??= this._sdkEvent('subagent.selected');
229 }
231 > private _onHookStart: Event<SessionEventPayload<'hook.start'>> | undefined;
232 > get onHookStart(): Event<SessionEventPayload<'hook.start'>> {
233 return this._onHookStart ??= this._sdkEvent('hook.start');
234 }
236 > private _onHookEnd: Event<SessionEventPayload<'hook.end'>> | undefined;
237 > get onHookEnd(): Event<SessionEventPayload<'hook.end'>> {
238 return this._onHookEnd ??= this._sdkEvent('hook.end');
239 }
241 > private _onSystemMessage: Event<SessionEventPayload<'system.message'>> | undefined;
242 > get onSystemMessage(): Event<SessionEventPayload<'system.message'>> {
243 return this._onSystemMessage ??= this._sdkEvent('system.message');
244 }
246 > private _onSystemNotification: Event<SessionEventPayload<'system.notification'>> | undefined;
247 > get onSystemNotification(): Event<SessionEventPayload<'system.notification'>> {
248 return this._onSystemNotification ??= this._sdkEvent('system.notification');
249 }
251 > private _onSessionModeChanged: Event<SessionEventPayload<'session.mode_changed'>> | undefined;
252 > get onSessionModeChanged(): Event<SessionEventPayload<'session.mode_changed'>> {
253 return this._onSessionModeChanged ??= this._sdkEvent('session.mode_changed');
254 }
256 > private _onMcpServersLoaded: Event<SessionEventPayload<'session.mcp_servers_loaded'>> | undefined;
257 > get onMcpServersLoaded(): Event<SessionEventPayload<'session.mcp_servers_loaded'>> {
258 return this._onMcpServersLoaded ??= this._sdkEvent('session.mcp_servers_loaded');
259 }
261 > private _onMcpServerStatusChanged: Event<SessionEventPayload<'session.mcp_server_status_changed'>> | undefined;
262 > get onMcpServerStatusChanged(): Event<SessionEventPayload<'session.mcp_server_status_changed'>> {
263 return this._onMcpServerStatusChanged ??= this._sdkEvent('session.mcp_server_status_changed');
264 }
266 > private _onToolsUpdated: Event<SessionEventPayload<'session.tools_updated'>> | undefined;
267 > get onToolsUpdated(): Event<SessionEventPayload<'session.tools_updated'>> {
268 return this._onToolsUpdated ??= this._sdkEvent('session.tools_updated');
269 }
271 > private _onCommandsChanged: Event<SessionEventPayload<'commands.changed'>> | undefined;
272 > get onCommandsChanged(): Event<SessionEventPayload<'commands.changed'>> {
273 return this._onCommandsChanged ??= this._sdkEvent('commands.changed');
274 }
276 > private _sdkEvent<K extends SessionEventType>(eventType: K): Event<SessionEventPayload<K>> {
277 const emitter = this._register(new Emitter<SessionEventPayload<K>>({
278 onDidAddFirstListener: () => this._handledEventTypes.add(eventType),