1
>
/*---------------------------------------------------------------------------------------------
claudeSdkOptions.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 { McpSdkServerConfigWithInstance, OnElicitation, Options } from '@anthropic-ai/claude-agent-sdk';
7
>
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
8
>
import { tmpdir } from 'os';
9
>
import { delimiter, dirname } from '../../../../base/common/path.js';
10
>
import { URI } from '../../../../base/common/uri.js';
11
>
import { rgDiskPath } from '../../../../base/node/ripgrep.js';
12
>
import { AiAgentEnvValue, AiAgentEnvVar } from '../../../chat/common/aiAgentEnv.js';
13
>
import { ClaudePermissionMode } from '../../common/claudeSessionConfigKeys.js';
14
>
import { resolveClaudeEffort } from '../../common/claudeModelConfig.js';
15
>
import { PendingRequestRegistry } from '../../common/pendingRequestRegistry.js';
16
>
import type { ModelSelection } from '../../common/state/protocol/state.js';
17
>
import { IClaudeAgentSdkService } from './claudeAgentSdkService.js';
18
>
import { buildClientToolMcpServer } from './clientTools/claudeClientToolMcpServer.js';
19
>
import { toSdkModelId } from './claudeModelId.js';
20
>
import type { ClaudeTransport } from './claudeProxyService.js';
21
>
import { SessionClientToolsDiff } from './clientTools/claudeSessionClientToolsModel.js';
22
>
23
>
/**
24
>
* Inputs to {@link buildOptions} that vary per startup. Pure-data: no
25
>
* services, no live event subscribers. The function is a deterministic
26
>
* projection from this bag plus a {@link IClaudeProxyHandle} onto the
27
>
* SDK's {@link Options} discriminated union.
28
>
*/
29
>
export interface IBuildOptionsInput {
30
>
readonly sessionId: string;
31
>
readonly workingDirectory: URI;
32
>
readonly model: ModelSelection | undefined;
33
>
readonly abortController: AbortController;
34
>
readonly permissionMode: ClaudePermissionMode;
35
>
readonly canUseTool: NonNullable<Options['canUseTool']>;
36
>
readonly onElicitation: OnElicitation;
37
>
readonly isResume: boolean;
38
>
/**
39
>
* One-shot SDK assistant-message uuid to resume *up to and including*
40
>
* (the SDK's `Options.resumeSessionAt`). Only meaningful with
41
>
* {@link isResume}; truncates the loaded transcript to this anchor so
42
>
* the next turn continues from the restored point on the same session
43
>
* id. Omitted in the non-resume (`sessionId`) branch and on ordinary
44
>
* resumes. Set by `truncateSession` for the rebuild that immediately
45
>
* precedes the post-restore turn.
46
>
*/
47
>
readonly resumeSessionAt?: string;
48
>
readonly mcpServers: Record<string, McpSdkServerConfigWithInstance> | undefined;
49
>
/**
50
>
* SDK-prefixed tool names to auto-approve without prompting (projected
51
>
* onto `Options.allowedTools`). Used for the agent host's feedback server
52
>
* tools, which only touch the session's annotations channel and are always
53
>
* safe. Omitted from the returned options when empty so the SDK keeps its
54
>
* default.
55
>
*/
56
>
readonly allowedTools?: readonly string[];
57
>
/**
58
>
* Local plugin directories to load at SDK startup. Projected onto
59
>
* `Options.plugins` as `{ type: 'local', path }`. Omitted from the
60
>
* returned options entirely when empty so the SDK keeps its default
61
>
* (no plugins). Built per-session from
62
>
* {@link SessionClientCustomizationsDiff.consume}.
63
>
*/
64
>
readonly plugins?: readonly URI[];
65
>
/**
66
>
* Resolved SDK agent name (matches a key in `Options.agents`, or an
67
>
* agent loaded from `~/.claude/agents/**`). Projected onto
68
>
* `Options.agent` — the SDK's `--agent` flag. The plugin URI captured
69
>
* at startup is the only path the SDK consults, so any `changeAgent`
70
>
* after materialize triggers a yield-restart through the rematerializer.
71
>
* Omit when no custom agent is selected (SDK default behavior).
72
>
*/
73
>
readonly agent?: string;
74
>
}
75
>
76
>
/**
77
>
* Build the SDK {@link Options} bag for a Claude session startup.
78
>
* Deterministic over its declared inputs plus three ambient reads:
79
>
* 1. `process.env.PATH` (composed into `Options.settings.env.PATH`
80
>
* so ripgrep wins over any system install),
81
>
* 2. `process.env` keys via {@link buildSubprocessEnv} (used to
82
>
* strip `VSCODE_*` / `ELECTRON_*` / `NODE_OPTIONS` /
83
>
* `ANTHROPIC_API_KEY` from the spawn env),
84
>
* 3. the memoized `rgDiskPath()` lookup.
85
>
* The returned options carry the caller-supplied `abortController` so a
86
>
* racing dispose unwinds `sdk.startup()` cleanly.
87
>
*
88
>
* Used by both the initial materialize and the yield-restart rematerialize
89
>
* — both call sites pass a freshly-built `mcpServers` snapshot consumed
90
>
* from the session's {@link SessionClientToolsDiff}.
91
>
*/
92
export async function buildOptions(
93
input: IBuildOptionsInput,