@agentclientprotocol/claude-agent-acp 0.29.2 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { Agent, AgentSideConnection, AuthenticateRequest, CancelNotification, ClientCapabilities, ForkSessionRequest, ForkSessionResponse, InitializeRequest, InitializeResponse, ListSessionsRequest, ListSessionsResponse, LoadSessionRequest, LoadSessionResponse, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, ReadTextFileRequest, ReadTextFileResponse, ResumeSessionRequest, ResumeSessionResponse, SessionConfigOption, SessionModelState, SessionModeState, SessionNotification, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse, SetSessionModelRequest, SetSessionModelResponse, SetSessionModeRequest, SetSessionModeResponse, CloseSessionRequest, CloseSessionResponse, TerminalHandle, TerminalOutputResponse, WriteTextFileRequest, WriteTextFileResponse } from "@agentclientprotocol/sdk";
2
- import { CanUseTool, Options, PermissionMode, Query, SDKPartialAssistantMessage, SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
2
+ import { CanUseTool, ModelInfo, Options, PermissionMode, PermissionUpdate, Query, SDKPartialAssistantMessage, SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
3
3
  import { ContentBlockParam } from "@anthropic-ai/sdk/resources";
4
4
  import { BetaContentBlock, BetaRawContentBlockDelta } from "@anthropic-ai/sdk/resources/beta.mjs";
5
5
  import { SettingsManager } from "./settings.js";
@@ -30,6 +30,7 @@ type Session = {
30
30
  accumulatedUsage: AccumulatedUsage;
31
31
  modes: SessionModeState;
32
32
  models: SessionModelState;
33
+ modelInfos: ModelInfo[];
33
34
  configOptions: SessionConfigOption[];
34
35
  promptRunning: boolean;
35
36
  pendingMessages: Map<string, {
@@ -135,7 +136,22 @@ export type ToolUseCache = {
135
136
  };
136
137
  };
137
138
  export declare function claudeCliPath(): Promise<string>;
139
+ /**
140
+ * Return user-message content with local-command marker tags removed, or
141
+ * `null` if nothing meaningful remains (caller should skip the message).
142
+ * Preserves real prose that's mixed in alongside the markers — e.g. a
143
+ * message like `<command-name>…</command-name>hi` becomes `hi`.
144
+ */
145
+ export declare function stripLocalCommandMetadata(content: unknown): unknown | null;
146
+ export declare function isLocalCommandMetadata(content: unknown): boolean;
138
147
  export declare function resolvePermissionMode(defaultMode?: unknown): PermissionMode;
148
+ /**
149
+ * Builds the label for the "Always Allow" permission option so the user can see
150
+ * the exact scope they are committing to. Uses the SDK-provided suggestions
151
+ * when available (e.g. `Bash(npm test:*)`) and falls back to naming the whole
152
+ * tool so "Always Allow" is never a blank check without disclosure.
153
+ */
154
+ export declare function describeAlwaysAllow(suggestions: PermissionUpdate[] | undefined, toolName: string): string;
139
155
  export declare class ClaudeAcpAgent implements Agent {
140
156
  sessions: {
141
157
  [key: string]: Session;
@@ -152,7 +168,7 @@ export declare class ClaudeAcpAgent implements Agent {
152
168
  initialize(request: InitializeRequest): Promise<InitializeResponse>;
153
169
  newSession(params: NewSessionRequest): Promise<NewSessionResponse>;
154
170
  unstable_forkSession(params: ForkSessionRequest): Promise<ForkSessionResponse>;
155
- unstable_resumeSession(params: ResumeSessionRequest): Promise<ResumeSessionResponse>;
171
+ resumeSession(params: ResumeSessionRequest): Promise<ResumeSessionResponse>;
156
172
  loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse>;
157
173
  listSessions(params: ListSessionsRequest): Promise<ListSessionsResponse>;
158
174
  authenticate(_params: AuthenticateRequest): Promise<void>;
@@ -163,7 +179,7 @@ export declare class ClaudeAcpAgent implements Agent {
163
179
  private teardownSession;
164
180
  /** Tear down all active sessions. Called when the ACP connection closes. */
165
181
  dispose(): Promise<void>;
166
- unstable_closeSession(params: CloseSessionRequest): Promise<CloseSessionResponse>;
182
+ closeSession(params: CloseSessionRequest): Promise<CloseSessionResponse>;
167
183
  unstable_setSessionModel(params: SetSessionModelRequest): Promise<SetSessionModelResponse | void>;
168
184
  setSessionMode(params: SetSessionModeRequest): Promise<SetSessionModeResponse>;
169
185
  setSessionConfigOption(params: SetSessionConfigOptionRequest): Promise<SetSessionConfigOptionResponse>;
@@ -174,7 +190,7 @@ export declare class ClaudeAcpAgent implements Agent {
174
190
  canUseTool(sessionId: string): CanUseTool;
175
191
  private sendAvailableCommandsUpdate;
176
192
  private updateConfigOption;
177
- private syncSessionConfigState;
193
+ private applyConfigOptionValue;
178
194
  private getOrCreateSession;
179
195
  private createSession;
180
196
  }
@@ -1 +1 @@
1
- {"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"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"}
package/dist/acp-agent.js CHANGED
@@ -35,13 +35,32 @@ function computeSessionFingerprint(params) {
35
35
  const servers = [...(params.mcpServers ?? [])].sort((a, b) => a.name.localeCompare(b.name));
36
36
  return JSON.stringify({ cwd: params.cwd, mcpServers: servers });
37
37
  }
38
- function isStaticBinary() {
39
- return process.env.CLAUDE_AGENT_ACP_IS_SINGLE_FILE_BUN !== undefined;
40
- }
41
38
  export async function claudeCliPath() {
42
- return isStaticBinary()
43
- ? (await import("@anthropic-ai/claude-agent-sdk/embed")).default
44
- : import.meta.resolve("@anthropic-ai/claude-agent-sdk").replace("sdk.mjs", "cli.js");
39
+ if (process.env.CLAUDE_CODE_EXECUTABLE) {
40
+ return process.env.CLAUDE_CODE_EXECUTABLE;
41
+ }
42
+ // The SDK's CLI is a native binary shipped as a platform-specific optional
43
+ // dependency of @anthropic-ai/claude-agent-sdk. Resolve via a require bound
44
+ // to the SDK so nested installs are found even when npm doesn't hoist.
45
+ const { createRequire } = await import("node:module");
46
+ const req = createRequire(import.meta.resolve("@anthropic-ai/claude-agent-sdk"));
47
+ const ext = process.platform === "win32" ? ".exe" : "";
48
+ const candidates = process.platform === "linux"
49
+ ? [
50
+ `@anthropic-ai/claude-agent-sdk-linux-${process.arch}-musl/claude${ext}`,
51
+ `@anthropic-ai/claude-agent-sdk-linux-${process.arch}/claude${ext}`,
52
+ ]
53
+ : [`@anthropic-ai/claude-agent-sdk-${process.platform}-${process.arch}/claude${ext}`];
54
+ for (const candidate of candidates) {
55
+ try {
56
+ return req.resolve(candidate);
57
+ }
58
+ catch {
59
+ // try next candidate
60
+ }
61
+ }
62
+ throw new Error(`Claude native binary not found for ${process.platform}-${process.arch}. ` +
63
+ `Reinstall @anthropic-ai/claude-agent-sdk without --omit=optional, or set CLAUDE_CODE_EXECUTABLE.`);
45
64
  }
46
65
  function shouldHideClaudeAuth() {
47
66
  return process.argv.includes("--hide-claude-auth");
@@ -52,6 +71,52 @@ const ALLOW_BYPASS = !IS_ROOT || !!process.env.IS_SANDBOX;
52
71
  // Slash commands that the SDK handles locally without replaying the user
53
72
  // message and without invoking the model.
54
73
  const LOCAL_ONLY_COMMANDS = new Set(["/context", "/heapdump", "/extra-usage"]);
74
+ // The Claude SDK persists local slash command invocations (e.g. `/model`) and
75
+ // their output as user messages in the session transcript, wrapping the
76
+ // payload in these XML-like markers that the CLI uses for its own display.
77
+ // The live prompt loop drops them; replay must strip them too or they leak
78
+ // into the UI on session/load.
79
+ const LOCAL_COMMAND_TAG_PATTERN = /<(command-name|command-message|command-args|local-command-stdout|local-command-stderr)>[\s\S]*?<\/\1>/g;
80
+ function stripMarkerTags(text) {
81
+ return text.replace(LOCAL_COMMAND_TAG_PATTERN, "");
82
+ }
83
+ /**
84
+ * Return user-message content with local-command marker tags removed, or
85
+ * `null` if nothing meaningful remains (caller should skip the message).
86
+ * Preserves real prose that's mixed in alongside the markers — e.g. a
87
+ * message like `<command-name>…</command-name>hi` becomes `hi`.
88
+ */
89
+ export function stripLocalCommandMetadata(content) {
90
+ if (typeof content === "string") {
91
+ const stripped = stripMarkerTags(content);
92
+ return stripped.trim() === "" ? null : stripped;
93
+ }
94
+ if (!Array.isArray(content))
95
+ return content;
96
+ const kept = [];
97
+ for (const block of content) {
98
+ if (block &&
99
+ typeof block === "object" &&
100
+ "type" in block &&
101
+ block.type === "text" &&
102
+ "text" in block &&
103
+ typeof block.text === "string") {
104
+ const stripped = stripMarkerTags(block.text);
105
+ if (stripped.trim() === "")
106
+ continue;
107
+ kept.push({ ...block, text: stripped });
108
+ }
109
+ else {
110
+ kept.push(block);
111
+ }
112
+ }
113
+ if (kept.length === 0)
114
+ return null;
115
+ return kept;
116
+ }
117
+ export function isLocalCommandMetadata(content) {
118
+ return stripLocalCommandMetadata(content) === null;
119
+ }
55
120
  const PERMISSION_MODE_ALIASES = {
56
121
  auto: "auto",
57
122
  default: "default",
@@ -81,6 +146,40 @@ export function resolvePermissionMode(defaultMode) {
81
146
  }
82
147
  return mapped;
83
148
  }
149
+ /**
150
+ * Builds the label for the "Always Allow" permission option so the user can see
151
+ * the exact scope they are committing to. Uses the SDK-provided suggestions
152
+ * when available (e.g. `Bash(npm test:*)`) and falls back to naming the whole
153
+ * tool so "Always Allow" is never a blank check without disclosure.
154
+ */
155
+ export function describeAlwaysAllow(suggestions, toolName) {
156
+ if (!suggestions || suggestions.length === 0) {
157
+ return `Always Allow all ${toolName}`;
158
+ }
159
+ const ruleLabels = [];
160
+ const directories = [];
161
+ for (const update of suggestions) {
162
+ if (update.type === "addRules" && update.behavior === "allow") {
163
+ for (const rule of update.rules) {
164
+ ruleLabels.push(rule.ruleContent ? `${rule.toolName}(${rule.ruleContent})` : `all ${rule.toolName}`);
165
+ }
166
+ }
167
+ else if (update.type === "addDirectories") {
168
+ directories.push(...update.directories);
169
+ }
170
+ }
171
+ const parts = [];
172
+ if (ruleLabels.length > 0) {
173
+ parts.push(ruleLabels.join(", "));
174
+ }
175
+ if (directories.length > 0) {
176
+ parts.push(`access to ${directories.join(", ")}`);
177
+ }
178
+ if (parts.length === 0) {
179
+ return `Always Allow all ${toolName}`;
180
+ }
181
+ return `Always Allow ${parts.join(" and ")}`;
182
+ }
84
183
  // Implement the ACP Agent interface
85
184
  export class ClaudeAcpAgent {
86
185
  constructor(client, logger) {
@@ -235,7 +334,7 @@ export class ClaudeAcpAgent {
235
334
  }, 0);
236
335
  return response;
237
336
  }
238
- async unstable_resumeSession(params) {
337
+ async resumeSession(params) {
239
338
  const result = await this.getOrCreateSession(params);
240
339
  // Needs to happen after we return the session
241
340
  setTimeout(() => {
@@ -291,6 +390,13 @@ export class ClaudeAcpAgent {
291
390
  let lastAssistantTotalUsage = null;
292
391
  let lastAssistantUsage = null;
293
392
  let lastAssistantModel = null;
393
+ // When the Claude SDK classifies a turn as failed (e.g. rate limit, auth
394
+ // problem, billing), it sets a categorical `error` field on the
395
+ // `SDKAssistantMessage` that precedes the final `result` message. We
396
+ // capture it here so the subsequent `RequestError.internalError` can
397
+ // forward it to clients as structured `data`, sparing them from
398
+ // pattern-matching on the human-readable message text.
399
+ let lastAssistantError;
294
400
  const userMessage = promptToClaude(params);
295
401
  const promptUuid = randomUUID();
296
402
  userMessage.uuid = promptUuid;
@@ -408,6 +514,7 @@ export class ClaudeAcpAgent {
408
514
  case "memory_recall":
409
515
  case "notification":
410
516
  case "api_retry":
517
+ case "mirror_error":
411
518
  // Todo: process via status api: https://docs.claude.com/en/docs/claude-code/hooks#hook-output
412
519
  break;
413
520
  default:
@@ -460,7 +567,7 @@ export class ClaudeAcpAgent {
460
567
  break;
461
568
  }
462
569
  if (message.is_error) {
463
- throw RequestError.internalError(undefined, message.result);
570
+ throw RequestError.internalError(errorKindData(lastAssistantError), message.result);
464
571
  }
465
572
  // For local-only commands (no model invocation), the result
466
573
  // text is the command output — forward it to the client.
@@ -477,7 +584,7 @@ export class ClaudeAcpAgent {
477
584
  break;
478
585
  }
479
586
  if (message.is_error) {
480
- throw RequestError.internalError(undefined, message.errors.join(", ") || message.subtype);
587
+ throw RequestError.internalError(errorKindData(lastAssistantError), message.errors.join(", ") || message.subtype);
481
588
  }
482
589
  stopReason = "end_turn";
483
590
  break;
@@ -486,7 +593,7 @@ export class ClaudeAcpAgent {
486
593
  case "error_max_turns":
487
594
  case "error_max_structured_output_retries":
488
595
  if (message.is_error) {
489
- throw RequestError.internalError(undefined, message.errors.join(", ") || message.subtype);
596
+ throw RequestError.internalError(errorKindData(lastAssistantError), message.errors.join(", ") || message.subtype);
490
597
  }
491
598
  stopReason = "max_turn_requests";
492
599
  break;
@@ -586,6 +693,9 @@ export class ClaudeAcpAgent {
586
693
  if (message.message.model && message.message.model !== "<synthetic>") {
587
694
  lastAssistantModel = message.message.model;
588
695
  }
696
+ if (message.error) {
697
+ lastAssistantError = message.error;
698
+ }
589
699
  }
590
700
  // Slash commands like /compact can generate invalid output... doesn't match
591
701
  // their own docs: https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-slash-commands#%2Fcompact-compact-conversation-history
@@ -704,7 +814,7 @@ export class ClaudeAcpAgent {
704
814
  async dispose() {
705
815
  await Promise.all(Object.keys(this.sessions).map((id) => this.teardownSession(id)));
706
816
  }
707
- async unstable_closeSession(params) {
817
+ async closeSession(params) {
708
818
  if (!this.sessions[params.sessionId]) {
709
819
  throw new Error("Session not found");
710
820
  }
@@ -712,11 +822,17 @@ export class ClaudeAcpAgent {
712
822
  return {};
713
823
  }
714
824
  async unstable_setSessionModel(params) {
715
- if (!this.sessions[params.sessionId]) {
825
+ const session = this.sessions[params.sessionId];
826
+ if (!session) {
716
827
  throw new Error("Session not found");
717
828
  }
718
- await this.sessions[params.sessionId].query.setModel(params.modelId);
719
- await this.updateConfigOption(params.sessionId, "model", params.modelId);
829
+ // Resolve aliases (e.g. "opus", "opus[1m]") to canonical model IDs so
830
+ // downstream lookups in modelInfos succeed and the effort option isn't
831
+ // silently dropped.
832
+ const resolved = resolveModelPreference(session.modelInfos, params.modelId);
833
+ const modelId = resolved?.value ?? params.modelId;
834
+ await session.query.setModel(modelId);
835
+ await this.updateConfigOption(params.sessionId, "model", modelId);
720
836
  }
721
837
  async setSessionMode(params) {
722
838
  if (!this.sessions[params.sessionId]) {
@@ -775,10 +891,10 @@ export class ClaudeAcpAgent {
775
891
  else if (params.configId === "model") {
776
892
  await this.sessions[params.sessionId].query.setModel(resolvedValue);
777
893
  }
778
- this.syncSessionConfigState(session, params.configId, params.value);
779
- session.configOptions = session.configOptions.map((o) => o.id === params.configId && typeof o.currentValue === "string"
780
- ? { ...o, currentValue: resolvedValue }
781
- : o);
894
+ // Effort SDK sync is handled inside applyConfigOptionValue so that direct
895
+ // effort changes and effort changes induced by a model switch go through
896
+ // the same path.
897
+ await this.applyConfigOptionValue(session, params.configId, resolvedValue);
782
898
  return { configOptions: session.configOptions };
783
899
  }
784
900
  async applySessionMode(sessionId, modeId) {
@@ -813,9 +929,17 @@ export class ClaudeAcpAgent {
813
929
  const toolUseCache = {};
814
930
  const messages = await getSessionMessages(sessionId);
815
931
  for (const message of messages) {
932
+ // @ts-expect-error - untyped in SDK but we handle all of these
933
+ let content = message.message.content;
934
+ // @ts-expect-error - untyped in SDK but we handle all of these
935
+ if (message.message.role === "user") {
936
+ content = stripLocalCommandMetadata(content);
937
+ if (content === null)
938
+ continue;
939
+ }
816
940
  for (const notification of toAcpNotifications(
817
941
  // @ts-expect-error - untyped in SDK but we handle all of these
818
- message.message.content,
942
+ content,
819
943
  // @ts-expect-error - untyped in SDK but we handle all of these
820
944
  message.message.role, sessionId, toolUseCache, this.client, this.logger, {
821
945
  registerHooks: false,
@@ -836,6 +960,7 @@ export class ClaudeAcpAgent {
836
960
  }
837
961
  canUseTool(sessionId) {
838
962
  return async (toolName, toolInput, { signal, suggestions, toolUseID }) => {
963
+ const alwaysAllowLabel = describeAlwaysAllow(suggestions, toolName);
839
964
  const supportsTerminalOutput = this.clientCapabilities?._meta?.["terminal_output"] === true;
840
965
  const session = this.sessions[sessionId];
841
966
  if (!session) {
@@ -915,7 +1040,7 @@ export class ClaudeAcpAgent {
915
1040
  options: [
916
1041
  {
917
1042
  kind: "allow_always",
918
- name: "Always Allow",
1043
+ name: alwaysAllowLabel,
919
1044
  optionId: "allow_always",
920
1045
  },
921
1046
  { kind: "allow_once", name: "Allow", optionId: "allow" },
@@ -978,8 +1103,7 @@ export class ClaudeAcpAgent {
978
1103
  const session = this.sessions[sessionId];
979
1104
  if (!session)
980
1105
  return;
981
- this.syncSessionConfigState(session, configId, value);
982
- session.configOptions = session.configOptions.map((o) => o.id === configId && typeof o.currentValue === "string" ? { ...o, currentValue: value } : o);
1106
+ await this.applyConfigOptionValue(session, configId, value);
983
1107
  await this.client.sessionUpdate({
984
1108
  sessionId,
985
1109
  update: {
@@ -988,7 +1112,8 @@ export class ClaudeAcpAgent {
988
1112
  },
989
1113
  });
990
1114
  }
991
- syncSessionConfigState(session, configId, value) {
1115
+ async applyConfigOptionValue(session, configId, value) {
1116
+ // Sync top-level session state
992
1117
  if (configId === "mode") {
993
1118
  session.modes = { ...session.modes, currentModeId: value };
994
1119
  }
@@ -1002,6 +1127,29 @@ export class ClaudeAcpAgent {
1002
1127
  }
1003
1128
  session.models = { ...session.models, currentModelId: value };
1004
1129
  }
1130
+ // Update configOptions
1131
+ if (configId === "model") {
1132
+ // Rebuild config options since effort levels depend on the selected model
1133
+ const effortOpt = session.configOptions.find((o) => o.id === "effort");
1134
+ const currentEffort = typeof effortOpt?.currentValue === "string" ? effortOpt.currentValue : undefined;
1135
+ session.configOptions = buildConfigOptions(session.modes, session.models, session.modelInfos, currentEffort);
1136
+ // Sync effort with the SDK if it changed after the model switch
1137
+ const newEffortOpt = session.configOptions.find((o) => o.id === "effort");
1138
+ const newEffort = typeof newEffortOpt?.currentValue === "string" ? newEffortOpt.currentValue : undefined;
1139
+ if (newEffort !== currentEffort) {
1140
+ await session.query.applyFlagSettings({
1141
+ effortLevel: newEffort,
1142
+ });
1143
+ }
1144
+ }
1145
+ else {
1146
+ session.configOptions = session.configOptions.map((o) => o.id === configId && typeof o.currentValue === "string" ? { ...o, currentValue: value } : o);
1147
+ if (configId === "effort") {
1148
+ await session.query.applyFlagSettings({
1149
+ effortLevel: value,
1150
+ });
1151
+ }
1152
+ }
1005
1153
  }
1006
1154
  async getOrCreateSession(params) {
1007
1155
  const existingSession = this.sessions[params.sessionId];
@@ -1085,9 +1233,15 @@ export class ClaudeAcpAgent {
1085
1233
  systemPrompt = customPrompt;
1086
1234
  }
1087
1235
  else if (typeof customPrompt === "object" &&
1088
- "append" in customPrompt &&
1089
- typeof customPrompt.append === "string") {
1090
- systemPrompt.append = customPrompt.append;
1236
+ customPrompt !== null &&
1237
+ !Array.isArray(customPrompt)) {
1238
+ // Forward all preset options (append, excludeDynamicSections, and
1239
+ // anything the SDK adds later) while locking type/preset.
1240
+ systemPrompt = {
1241
+ ...customPrompt,
1242
+ type: "preset",
1243
+ preset: "claude_code",
1244
+ };
1091
1245
  }
1092
1246
  }
1093
1247
  const permissionMode = resolvePermissionMode(settingsManager.getSettings().permissions?.defaultMode);
@@ -1098,6 +1252,8 @@ export class ClaudeAcpAgent {
1098
1252
  const maxThinkingTokens = process.env.MAX_THINKING_TOKENS
1099
1253
  ? parseInt(process.env.MAX_THINKING_TOKENS, 10)
1100
1254
  : undefined;
1255
+ // Parse model configuration from environment (e.g. Bedrock model overrides)
1256
+ const modelConfig = parseModelConfig(process.env.CLAUDE_MODEL_CONFIG);
1101
1257
  // Disable this for now, not a great way to expose this over ACP at the moment (in progress work so we can revisit)
1102
1258
  const disallowedTools = ["AskUserQuestion"];
1103
1259
  // Resolve which built-in tools to expose.
@@ -1112,6 +1268,17 @@ export class ClaudeAcpAgent {
1112
1268
  settingSources: ["user", "project", "local"],
1113
1269
  ...(maxThinkingTokens !== undefined && { maxThinkingTokens }),
1114
1270
  ...userProvidedOptions,
1271
+ // CLAUDE_MODEL_CONFIG env var is a fallback for model
1272
+ // configuration (e.g. Bedrock model ID overrides). When the caller
1273
+ // provides settings via _meta, we intentionally ignore the env var —
1274
+ // the caller is assumed to have full control over model configuration.
1275
+ ...(!userProvidedOptions?.settings &&
1276
+ modelConfig && {
1277
+ settings: {
1278
+ ...(modelConfig.modelOverrides && { modelOverrides: modelConfig.modelOverrides }),
1279
+ ...(modelConfig.availableModels && { availableModels: modelConfig.availableModels }),
1280
+ },
1281
+ }),
1115
1282
  env: {
1116
1283
  ...process.env,
1117
1284
  ...userProvidedOptions?.env,
@@ -1128,14 +1295,7 @@ export class ClaudeAcpAgent {
1128
1295
  allowDangerouslySkipPermissions: ALLOW_BYPASS,
1129
1296
  permissionMode,
1130
1297
  canUseTool: this.canUseTool(sessionId),
1131
- // note: although not documented by the types, passing an absolute path
1132
- // here works to find zed's managed node version.
1133
- executable: isStaticBinary() ? undefined : process.execPath,
1134
- ...(process.env.CLAUDE_CODE_EXECUTABLE
1135
- ? { pathToClaudeCodeExecutable: process.env.CLAUDE_CODE_EXECUTABLE }
1136
- : isStaticBinary()
1137
- ? { pathToClaudeCodeExecutable: await claudeCliPath() }
1138
- : {}),
1298
+ pathToClaudeCodeExecutable: process.env.CLAUDE_CODE_EXECUTABLE,
1139
1299
  extraArgs: {
1140
1300
  ...userProvidedOptions?.extraArgs,
1141
1301
  "replay-user-messages": "",
@@ -1241,7 +1401,14 @@ export class ClaudeAcpAgent {
1241
1401
  currentModeId: permissionMode,
1242
1402
  availableModes,
1243
1403
  };
1244
- const configOptions = buildConfigOptions(modes, models);
1404
+ const configOptions = buildConfigOptions(modes, models, initializationResult.models, settingsManager.getSettings().effortLevel);
1405
+ // Apply the initial effort level to the SDK so it matches the UI default
1406
+ const initialEffort = configOptions.find((o) => o.id === "effort");
1407
+ if (initialEffort && typeof initialEffort.currentValue === "string") {
1408
+ await q.applyFlagSettings({
1409
+ effortLevel: initialEffort.currentValue,
1410
+ });
1411
+ }
1245
1412
  this.sessions[sessionId] = {
1246
1413
  query: q,
1247
1414
  input: input,
@@ -1257,6 +1424,7 @@ export class ClaudeAcpAgent {
1257
1424
  },
1258
1425
  modes,
1259
1426
  models,
1427
+ modelInfos: initializationResult.models,
1260
1428
  configOptions,
1261
1429
  promptRunning: false,
1262
1430
  pendingMessages: new Map(),
@@ -1302,6 +1470,19 @@ function totalTokens(usage) {
1302
1470
  usage.cache_read_input_tokens +
1303
1471
  usage.cache_creation_input_tokens);
1304
1472
  }
1473
+ /**
1474
+ * Build the `data` payload attached to a `RequestError.internalError` when we
1475
+ * have a categorical error from the Claude SDK. Returns `undefined` when no
1476
+ * categorical error is available, matching the previous behavior of passing
1477
+ * `undefined` to `RequestError.internalError`.
1478
+ *
1479
+ * The `errorKind` field is a convention for ACP clients to dispatch on
1480
+ * without having to pattern-match the human-readable message text. Clients
1481
+ * that don't understand it fall back to the existing message-based rendering.
1482
+ */
1483
+ function errorKindData(errorKind) {
1484
+ return errorKind ? { errorKind } : undefined;
1485
+ }
1305
1486
  /** Project a nullable API usage object into our non-null snapshot shape.
1306
1487
  * Both SDK message_start and assistant message `usage` have `number | null`
1307
1488
  * cache fields; we coerce absent values to 0 so `totalTokens` never hits
@@ -1330,8 +1511,8 @@ function createEnvForGateway(gatewayMeta) {
1330
1511
  ANTHROPIC_AUTH_TOKEN: "", // Must be specified to bypass claude login requirement
1331
1512
  };
1332
1513
  }
1333
- function buildConfigOptions(modes, models) {
1334
- return [
1514
+ function buildConfigOptions(modes, models, modelInfos, currentEffortLevel) {
1515
+ const options = [
1335
1516
  {
1336
1517
  id: "mode",
1337
1518
  name: "Mode",
@@ -1359,6 +1540,40 @@ function buildConfigOptions(modes, models) {
1359
1540
  })),
1360
1541
  },
1361
1542
  ];
1543
+ // Add effort level option based on the currently selected model
1544
+ const currentModelInfo = modelInfos.find((m) => m.value === models.currentModelId);
1545
+ const supportedLevels = currentModelInfo?.supportsEffort
1546
+ ? (currentModelInfo.supportedEffortLevels ?? [])
1547
+ : [];
1548
+ if (supportedLevels.length > 0) {
1549
+ const effortOptions = supportedLevels.map((level) => ({
1550
+ value: level,
1551
+ name: level
1552
+ .split(/[_-]/)
1553
+ .map((part) => (part ? part.charAt(0).toUpperCase() + part.slice(1) : part))
1554
+ .join(" "),
1555
+ }));
1556
+ // Keep the current level if valid, otherwise prefer xhigh (Claude Code's
1557
+ // recommended default for capable models), then high (the API default).
1558
+ const includes = (l) => supportedLevels.includes(l);
1559
+ const validEffort = currentEffortLevel && includes(currentEffortLevel)
1560
+ ? currentEffortLevel
1561
+ : includes("xhigh")
1562
+ ? "xhigh"
1563
+ : includes("high")
1564
+ ? "high"
1565
+ : supportedLevels[0];
1566
+ options.push({
1567
+ id: "effort",
1568
+ name: "Effort",
1569
+ description: "Available effort levels for this model",
1570
+ category: "effort",
1571
+ type: "select",
1572
+ currentValue: validEffort,
1573
+ options: effortOptions,
1574
+ });
1575
+ }
1576
+ return options;
1362
1577
  }
1363
1578
  // Claude Code CLI persists display strings like "opus[1m]" in settings,
1364
1579
  // but the SDK model list uses IDs like "claude-opus-4-6-1m".
@@ -1864,6 +2079,20 @@ function inferContextWindowFromModel(model) {
1864
2079
  return 1_000_000;
1865
2080
  return null;
1866
2081
  }
2082
+ function parseModelConfig(raw) {
2083
+ if (!raw)
2084
+ return undefined;
2085
+ const parsed = JSON.parse(raw);
2086
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
2087
+ throw new Error("CLAUDE_MODEL_CONFIG must be a JSON object");
2088
+ }
2089
+ const result = {};
2090
+ if (parsed.modelOverrides !== undefined)
2091
+ result.modelOverrides = parsed.modelOverrides;
2092
+ if (parsed.availableModels !== undefined)
2093
+ result.availableModels = parsed.availableModels;
2094
+ return Object.keys(result).length > 0 ? result : undefined;
2095
+ }
1867
2096
  function getMatchingModelUsage(modelUsage, currentModel) {
1868
2097
  let bestKey = null;
1869
2098
  let bestLen = 0;
package/dist/index.js CHANGED
@@ -3,8 +3,34 @@
3
3
  import { loadManagedSettings, applyEnvironmentSettings } from "./utils.js";
4
4
  import { claudeCliPath, runAcp } from "./acp-agent.js";
5
5
  if (process.argv.includes("--cli")) {
6
- process.argv = process.argv.filter((arg) => arg !== "--cli");
7
- await import(await claudeCliPath());
6
+ const { spawn } = await import("node:child_process");
7
+ const args = process.argv.slice(2).filter((arg) => arg !== "--cli");
8
+ const child = spawn(await claudeCliPath(), args, { stdio: "inherit" });
9
+ const signals = process.platform === "win32"
10
+ ? ["SIGINT", "SIGTERM"]
11
+ : ["SIGINT", "SIGTERM", "SIGHUP"];
12
+ for (const sig of signals) {
13
+ process.on(sig, () => {
14
+ if (!child.killed)
15
+ child.kill(sig);
16
+ });
17
+ }
18
+ child.on("exit", (code, signal) => {
19
+ if (signal && process.platform !== "win32") {
20
+ // Remove our listener so re-raising actually terminates instead of
21
+ // re-entering the no-op handler, which would let us exit with code 0
22
+ // instead of the signal's conventional 128+N.
23
+ process.removeAllListeners(signal);
24
+ process.kill(process.pid, signal);
25
+ }
26
+ else {
27
+ process.exit(code ?? 1);
28
+ }
29
+ });
30
+ child.on("error", (err) => {
31
+ console.error(err);
32
+ process.exit(1);
33
+ });
8
34
  }
9
35
  else {
10
36
  const managedSettings = loadManagedSettings();
package/dist/lib.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { ClaudeAcpAgent, runAcp, toAcpNotifications, streamEventToAcpNotifications, type ToolUpdateMeta, type NewSessionMeta, type SDKMessageFilter, } from "./acp-agent.js";
1
+ export { ClaudeAcpAgent, isLocalCommandMetadata, stripLocalCommandMetadata, runAcp, toAcpNotifications, streamEventToAcpNotifications, type ToolUpdateMeta, type NewSessionMeta, type SDKMessageFilter, } from "./acp-agent.js";
2
2
  export { loadManagedSettings, applyEnvironmentSettings, nodeToWebReadable, nodeToWebWritable, Pushable, unreachable, } from "./utils.js";
3
3
  export { toolInfoFromToolUse, toDisplayPath, planEntries, toolUpdateFromToolResult, } from "./tools.js";
4
4
  export { SettingsManager, type ClaudeCodeSettings, type SettingsManagerOptions, } from "./settings.js";
package/dist/lib.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,MAAM,EACN,kBAAkB,EAClB,6BAA6B,EAC7B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,wBAAwB,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,GAC5B,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EACzB,MAAM,EACN,kBAAkB,EAClB,6BAA6B,EAC7B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,wBAAwB,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,GAC5B,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
package/dist/lib.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Export the main agent class and utilities for library usage
2
- export { ClaudeAcpAgent, runAcp, toAcpNotifications, streamEventToAcpNotifications, } from "./acp-agent.js";
2
+ export { ClaudeAcpAgent, isLocalCommandMetadata, stripLocalCommandMetadata, runAcp, toAcpNotifications, streamEventToAcpNotifications, } from "./acp-agent.js";
3
3
  export { loadManagedSettings, applyEnvironmentSettings, nodeToWebReadable, nodeToWebWritable, Pushable, unreachable, } from "./utils.js";
4
4
  export { toolInfoFromToolUse, toDisplayPath, planEntries, toolUpdateFromToolResult, } from "./tools.js";
5
5
  export { SettingsManager, } from "./settings.js";
@@ -16,6 +16,7 @@ export interface ClaudeCodeSettings {
16
16
  permissions?: PermissionSettings;
17
17
  env?: Record<string, string>;
18
18
  model?: string;
19
+ effortLevel?: string;
19
20
  }
20
21
  /**
21
22
  * Gets the enterprise settings path based on the current platform
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA2BD;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAW/C;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;QAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7E;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,kBAAkB,CAA0B;IACpD,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,QAAQ,CAAC,CAAa;IAC9B,OAAO,CAAC,MAAM,CAAqE;IACnF,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,WAAW,CAA8B;gBAErC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB;IAMzD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAI9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;YACW,eAAe;IAgB7B;;;;OAIG;IACH,OAAO,CAAC,aAAa;IA8BrB;;OAEG;IACH,OAAO,CAAC,aAAa;IAkCrB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;IACH,WAAW,IAAI,kBAAkB;IAIjC;;OAEG;IACH,MAAM,IAAI,MAAM;IAIhB;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxC;;OAEG;IACH,OAAO,IAAI,IAAI;CAehB"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA2BD;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAW/C;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;QAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7E;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,kBAAkB,CAA0B;IACpD,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,QAAQ,CAAC,CAAa;IAC9B,OAAO,CAAC,MAAM,CAAqE;IACnF,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,WAAW,CAA8B;gBAErC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB;IAMzD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAI9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;YACW,eAAe;IAgB7B;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAkCrB;;OAEG;IACH,OAAO,CAAC,aAAa;IAkCrB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;IACH,WAAW,IAAI,kBAAkB;IAIjC;;OAEG;IACH,MAAM,IAAI,MAAM;IAIhB;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxC;;OAEG;IACH,OAAO,IAAI,IAAI;CAehB"}
package/dist/settings.js CHANGED
@@ -138,6 +138,9 @@ export class SettingsManager {
138
138
  if (settings.model) {
139
139
  merged.model = settings.model;
140
140
  }
141
+ if (settings.effortLevel !== undefined) {
142
+ merged.effortLevel = settings.effortLevel;
143
+ }
141
144
  if (settings.permissions?.defaultMode !== undefined) {
142
145
  merged.permissions = {
143
146
  ...merged.permissions,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.29.2",
6
+ "version": "0.31.0",
7
7
  "description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
8
8
  "main": "dist/lib.js",
9
9
  "types": "dist/lib.d.ts",
@@ -60,22 +60,22 @@
60
60
  "author": "Zed Industries",
61
61
  "license": "Apache-2.0",
62
62
  "dependencies": {
63
- "@agentclientprotocol/sdk": "0.19.0",
64
- "@anthropic-ai/claude-agent-sdk": "0.2.112",
63
+ "@agentclientprotocol/sdk": "0.20.0",
64
+ "@anthropic-ai/claude-agent-sdk": "0.2.119",
65
65
  "zod": "^3.25.0 || ^4.0.0"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@anthropic-ai/sdk": "0.89.0",
69
69
  "@eslint/js": "10.0.1",
70
70
  "@types/node": "25.6.0",
71
- "@typescript-eslint/eslint-plugin": "8.58.2",
72
- "@typescript-eslint/parser": "8.58.2",
73
- "eslint": "10.2.0",
71
+ "@typescript-eslint/eslint-plugin": "8.59.0",
72
+ "@typescript-eslint/parser": "8.59.0",
73
+ "eslint": "10.2.1",
74
74
  "eslint-config-prettier": "10.1.8",
75
75
  "globals": "17.5.0",
76
76
  "prettier": "3.8.3",
77
77
  "ts-node": "10.9.2",
78
78
  "typescript": "6.0.3",
79
- "vitest": "4.1.4"
79
+ "vitest": "4.1.5"
80
80
  }
81
81
  }