claudeSdkOptions.ts ×4

Frontier kind: Code frontier

unlabeled · c_2d09a4bb172d

211 tests · 3915 LOC · 27 files · introduces 0 tests · 145 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
4 ranges145 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
513 ranges3915 lines · 27 files · Browse complete extent
All tests (intent)
211 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.

1 file ranked by introduced lines: 145 introduced LOC across 4 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/agentHost/node/claude/claudeSdkOptions.ts 145 introduced LOC · 4 ranges

Open complete file

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,
151 };
152 }
154 > /**
155 > * Consume the diff (clears its dirty bit) and build the in-process MCP
156 > * server config from the resulting tool snapshot. Resolves to
157 > * `undefined` when the snapshot is empty so `Options.mcpServers` is
158 > * omitted entirely and the SDK keeps its default.
159 > *
160 > * On builder throw the caller is responsible for re-marking the diff
161 > * dirty (the diff has already been consumed). See
162 > * {@link SessionClientToolsDiff.markDirty}.
163 > */
164 export async function buildClientMcpServers(
165 toolDiff: SessionClientToolsDiff,
174 return { client: server };
175 }
177 > /**
178 > * Build a minimal {@link Options} bag for an ephemeral model-enumeration
179 > * query (Phase 19, native transport). No workspace (`cwd = os.tmpdir()`), no
180 > * proxy env, and the user's `ANTHROPIC_API_KEY` preserved so the SDK can
181 > * authenticate. Reads the user's real `~/.claude` config so subscription
182 > * models (e.g. Opus) surface; verified not to write any session transcript
183 > * because the enumeration never iterates a turn. The caller (`_fetchNativeModels`)
184 > * aborts the returned `abortController` during teardown, alongside `query.close()`.
185 > */
186 > export function buildModelEnumerationOptions(): Options {
187 return {
188 cwd: tmpdir(),
198 };
199 }
201 > /**
202 > * Build the {@link Options.env} payload for the Claude subprocess.
203 > *
204 > * SDK >= 0.3 **replaces** the subprocess environment with `Options.env` — it is
205 > * NOT merged with `process.env` (sdk.d.ts:1402-1405: "this value REPLACES the
206 > * subprocess environment entirely … Spread `process.env` yourself"). Keys whose
207 > * value is `undefined` are dropped from the spawned env.
208 > *
209 > * Two modes, gated by `proxied`:
210 > *
211 > * - **Proxied (Copilot-routed), `true` (default):** a *sparse* env. Credentials
212 > * reach the CLI via `settings.env` (the per-session proxy bearer), so the
213 > * subprocess env stays minimal and the user's personal `ANTHROPIC_API_KEY`
214 > * must not leak to the Copilot proxy (stripped). `PATH` for ripgrep is
215 > * supplied through `settings.env`, not here.
216 > *
217 > * - **Native (BYO-Anthropic), `false`:** inherit the real `process.env` so the
218 > * user's own credentials (`CLAUDE_CODE_OAUTH_TOKEN` from `claude setup-token`,
219 > * or `ANTHROPIC_API_KEY`) and `PATH` actually reach the `claude` subprocess.
220 > * Without this spread, replace semantics wipe the inherited token and the CLI
221 > * reports "Not logged in".
222 > *
223 > * In both modes the agent host's own `NODE_OPTIONS`, `ELECTRON_*`, and
224 > * `VSCODE_*` variables are stripped (they break the Electron-node subprocess),
225 > * `ELECTRON_RUN_AS_NODE=1` is set, and `AI_AGENT` is pinned so the sparse
226 > * proxied env still announces the originating VS Code surface. Mirror of the
227 > * strip pattern in `CopilotAgent._ensureClient()`.
228 > *
229 > * Exported for unit testing as a pure function over `process.env`.
230 > */
231 > export function buildSubprocessEnv(proxied: boolean = true): Record<string, string | undefined> {
232 // Proxy mode: a sparse env (creds arrive via settings.env), and the user's
233 // personal ANTHROPIC_API_KEY must not leak to the Copilot proxy.