@ycodium-ai/agent-claude 0.2.2596 → 0.2.2658

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.
package/dist/index.js CHANGED
@@ -19650,7 +19650,11 @@ function HU(e, t) {
19650
19650
  }
19651
19651
 
19652
19652
  // src/claudeInstance.ts
19653
- import { mergeLaunchEnv as mergeLaunchEnv2 } from "@ycodium-ai/plugin-api/executor";
19653
+ import {
19654
+ describeExecutorSpawnFailure,
19655
+ ExecutorSpawnRefusedError,
19656
+ mergeLaunchEnv as mergeLaunchEnv2
19657
+ } from "@ycodium-ai/plugin-api/executor";
19654
19658
 
19655
19659
  // src/claudeAccount.ts
19656
19660
  import * as NodeFS from "node:fs";
@@ -19854,6 +19858,34 @@ function makeClaudeEnvironment(config, baseEnv) {
19854
19858
  if (Object.keys(variables).length === 0) return resolvedBaseEnv;
19855
19859
  return { ...resolvedBaseEnv, ...variables };
19856
19860
  }
19861
+ var quoteLiteral = (value) => JSON.stringify(value);
19862
+ function claudeSignedOutMessage(input) {
19863
+ const variables = [];
19864
+ const configDir = input.configDir?.trim() ?? "";
19865
+ if (configDir.length > 0) {
19866
+ variables.push(
19867
+ `CLAUDE_CONFIG_DIR set to ${quoteLiteral(NodePath4.resolve(input.cwd, configDir))}`
19868
+ );
19869
+ }
19870
+ const credentialsDir = input.credentialsDir?.trim() ?? "";
19871
+ if (credentialsDir.length > 0) {
19872
+ variables.push(
19873
+ `${CLAUDE_CREDENTIALS_DIR_ENVIRONMENT_VARIABLE} set to ${quoteLiteral(NodePath4.resolve(input.cwd, credentialsDir))}`
19874
+ );
19875
+ }
19876
+ const withVariables = variables.length > 0 ? `, with ${variables.join(" and ")}` : "";
19877
+ return `Claude could not authenticate. For subscription login, run \`claude auth login\` on this machine${withVariables}, then start a new thread. For API-key authentication, check this instance's configured credentials.`;
19878
+ }
19879
+ function claudeFailureHint(input) {
19880
+ if (input.authenticationFailed) {
19881
+ return claudeSignedOutMessage({
19882
+ configDir: input.environment.CLAUDE_CONFIG_DIR,
19883
+ credentialsDir: input.environment[CLAUDE_CREDENTIALS_DIR_ENVIRONMENT_VARIABLE],
19884
+ cwd: input.cwd
19885
+ });
19886
+ }
19887
+ return void 0;
19888
+ }
19857
19889
 
19858
19890
  // src/claudeSignIn.ts
19859
19891
  var POSIX_BARE_VALUE = /^[A-Za-z0-9_@%+=:,./-]+$/;
@@ -20135,8 +20167,8 @@ var EventBus = class {
20135
20167
  const queued = this.#queued.shift();
20136
20168
  if (queued !== void 0) return Promise.resolve({ done: false, value: queued });
20137
20169
  if (this.#closed) return Promise.resolve({ done: true, value: void 0 });
20138
- return new Promise((resolve2) => {
20139
- this.#waiters.push(resolve2);
20170
+ return new Promise((resolve3) => {
20171
+ this.#waiters.push(resolve3);
20140
20172
  });
20141
20173
  }
20142
20174
  };
@@ -20323,9 +20355,9 @@ var claudeCatalogFromSdk = (models) => {
20323
20355
  };
20324
20356
  var silentPrompt = (signal) => ({
20325
20357
  [Symbol.asyncIterator]: () => ({
20326
- next: () => new Promise((resolve2) => {
20327
- if (signal.aborted) resolve2({ done: true, value: void 0 });
20328
- signal.addEventListener("abort", () => resolve2({ done: true, value: void 0 }), {
20358
+ next: () => new Promise((resolve3) => {
20359
+ if (signal.aborted) resolve3({ done: true, value: void 0 });
20360
+ signal.addEventListener("abort", () => resolve3({ done: true, value: void 0 }), {
20329
20361
  once: true
20330
20362
  });
20331
20363
  }),
@@ -20369,6 +20401,14 @@ var readClaudeSdkModels = async (input) => {
20369
20401
  }
20370
20402
  }
20371
20403
  };
20404
+ function claudeModelProbeEnvironment(environment) {
20405
+ return {
20406
+ ...environment,
20407
+ FORCE_CODE_TERMINAL: void 0,
20408
+ CLAUDE_CODE_AUTO_CONNECT_IDE: "0",
20409
+ CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL: "1"
20410
+ };
20411
+ }
20372
20412
  var claudeSdkModelsCwd = () => NodeOS5.tmpdir();
20373
20413
 
20374
20414
  // src/util.ts
@@ -20912,7 +20952,7 @@ function isClaudeInterruptedCause(cause) {
20912
20952
  function resultErrorsText(result) {
20913
20953
  return "errors" in result && Array.isArray(result.errors) ? result.errors.join(" ").toLowerCase() : "";
20914
20954
  }
20915
- function resultUserFacingError(result) {
20955
+ function resultListedError(result) {
20916
20956
  if (result.subtype === "success") {
20917
20957
  return result.is_error ? result.result : void 0;
20918
20958
  }
@@ -20921,6 +20961,37 @@ function resultUserFacingError(result) {
20921
20961
  }
20922
20962
  return result.errors.find((error) => !error.startsWith("[ede_diagnostic]"));
20923
20963
  }
20964
+ function terminalResultError(reason, failureHint) {
20965
+ switch (reason) {
20966
+ case "api_error":
20967
+ return failureHint ?? "Claude gave up after repeated API errors.";
20968
+ case "malformed_tool_use_exhausted":
20969
+ return "Claude gave up after repeated malformed tool calls.";
20970
+ case "budget_exhausted":
20971
+ return "Claude stopped: the turn's token budget was exhausted.";
20972
+ case "structured_output_retry_exhausted":
20973
+ return "Claude could not produce the requested structured output.";
20974
+ case "tool_deferred_unavailable":
20975
+ return "Claude could not resume a deferred tool call: the tool is no longer available.";
20976
+ case "turn_setup_failed":
20977
+ return "Claude could not start the turn.";
20978
+ case "blocking_limit":
20979
+ return "Claude stopped: a usage limit blocked the request.";
20980
+ case "rapid_refill_breaker":
20981
+ return "Claude stopped: the context refilled too quickly after compaction.";
20982
+ case "prompt_too_long":
20983
+ return "Claude stopped: the prompt exceeds the model's context window.";
20984
+ case "image_error":
20985
+ return "Claude stopped: an image in the conversation could not be processed.";
20986
+ case "model_error":
20987
+ return "Claude stopped: the model returned an error.";
20988
+ default:
20989
+ return void 0;
20990
+ }
20991
+ }
20992
+ function isOverloadedResult(result) {
20993
+ return result.subtype === "success" && result.api_error_status === 529;
20994
+ }
20924
20995
  function isInterruptedResult(result) {
20925
20996
  if (result.terminal_reason === "aborted_tools" || result.terminal_reason === "aborted_streaming") {
20926
20997
  return true;
@@ -20931,18 +21002,19 @@ function isInterruptedResult(result) {
20931
21002
  }
20932
21003
  return result.subtype === "error_during_execution" && result.is_error === false && (errors.includes("request was aborted") || errors.includes("interrupted by user") || errors.includes("aborted"));
20933
21004
  }
20934
- function turnStatusFromResult(result) {
21005
+ function resultOutcome(result, failureHint) {
21006
+ const structuredError = isOverloadedResult(result) ? "Claude API is overloaded (529). Try again shortly." : terminalResultError(result.terminal_reason, failureHint);
21007
+ const successTaggedFailure = result.subtype === "success" && result.is_error;
21008
+ const errorMessage = (successTaggedFailure ? failureHint : void 0) ?? resultListedError(result) ?? structuredError;
21009
+ if (structuredError !== void 0) return { status: "failed", errorMessage };
20935
21010
  if (result.subtype === "success" && !result.is_error) {
20936
- return "completed";
20937
- }
20938
- const errors = resultErrorsText(result);
20939
- if (isInterruptedResult(result)) {
20940
- return "interrupted";
21011
+ return { status: "completed", errorMessage };
20941
21012
  }
20942
- if (errors.includes("cancel")) {
20943
- return "cancelled";
20944
- }
20945
- return "failed";
21013
+ if (isInterruptedResult(result)) return { status: "interrupted", errorMessage };
21014
+ return {
21015
+ status: resultErrorsText(result).includes("cancel") ? "cancelled" : "failed",
21016
+ errorMessage
21017
+ };
20946
21018
  }
20947
21019
  function streamKindFromDeltaType(deltaType) {
20948
21020
  return deltaType.includes("thinking") ? "reasoning_text" : "assistant_text";
@@ -23111,9 +23183,9 @@ var PromptQueue = class {
23111
23183
  const queued = this.#queued.shift();
23112
23184
  if (queued !== void 0) return Promise.resolve(queued);
23113
23185
  if (this.#closed) return Promise.resolve(void 0);
23114
- return new Promise((resolve2) => {
23186
+ return new Promise((resolve3) => {
23115
23187
  this.#waiters.push((result) => {
23116
- resolve2(result.done ? void 0 : result.value);
23188
+ resolve3(result.done ? void 0 : result.value);
23117
23189
  });
23118
23190
  });
23119
23191
  }
@@ -23257,6 +23329,7 @@ function toClaudeMcpServers(entries) {
23257
23329
  }
23258
23330
  return servers;
23259
23331
  }
23332
+ var CLAUDE_PROGRAM_NOT_CONFIGURED = "Claude program path is not configured";
23260
23333
  function createClaudeAdapter(recipe, host, options) {
23261
23334
  const boundInstanceId = options?.instanceId ?? host.instanceId ?? "claudeAgent";
23262
23335
  const claudeHomeEnvironment = makeClaudeEnvironment(recipe, options?.environment);
@@ -23264,10 +23337,14 @@ function createClaudeAdapter(recipe, host, options) {
23264
23337
  recipe.binaryPath,
23265
23338
  claudeHomeEnvironment
23266
23339
  );
23267
- const createQuery = options?.createQuery ?? ((input) => XAe({
23340
+ const sdkCreateQuery = options?.createQuery ?? ((input) => XAe({
23268
23341
  prompt: input.prompt,
23269
23342
  options: input.options
23270
23343
  }));
23344
+ const createQuery = (input) => {
23345
+ if (recipe.binaryPath.length === 0) throw new Error(CLAUDE_PROGRAM_NOT_CONFIGURED);
23346
+ return sdkCreateQuery(input);
23347
+ };
23271
23348
  const buildLaunchEnvironment = () => mergeLaunchEnv2({
23272
23349
  inherited: { ...process.env, ...options?.environment },
23273
23350
  instanceTable: recipe.environment,
@@ -23293,7 +23370,7 @@ function createClaudeAdapter(recipe, host, options) {
23293
23370
  cwd: claudeSdkModelsCwd(),
23294
23371
  pathToClaudeCodeExecutable: claudeSdkExecutablePath,
23295
23372
  settingSources: [...CLAUDE_SETTING_SOURCES],
23296
- env: compactEnv(buildLaunchEnvironment()),
23373
+ env: compactEnv(claudeModelProbeEnvironment(buildLaunchEnvironment())),
23297
23374
  ...Object.keys(extraArgs).length > 0 ? { extraArgs } : {}
23298
23375
  }
23299
23376
  });
@@ -23660,6 +23737,7 @@ function createClaudeAdapter(recipe, host, options) {
23660
23737
  latestAssistantUsage: void 0,
23661
23738
  compactedSinceLatestAssistantUsage: false,
23662
23739
  retrying: false,
23740
+ authenticationFailed: false,
23663
23741
  nextSyntheticAssistantBlockIndex: -1
23664
23742
  };
23665
23743
  context.session = {
@@ -24248,6 +24326,9 @@ function createClaudeAdapter(recipe, host, options) {
24248
24326
  return;
24249
24327
  }
24250
24328
  if (isClaudeSyntheticApiErrorMessage(message)) {
24329
+ if (context.turnState && message.error === "authentication_failed") {
24330
+ context.turnState.authenticationFailed = true;
24331
+ }
24251
24332
  context.lastAssistantUuid = message.uuid;
24252
24333
  await updateResumeCursor(context);
24253
24334
  return;
@@ -24315,8 +24396,14 @@ function createClaudeAdapter(recipe, host, options) {
24315
24396
  return;
24316
24397
  }
24317
24398
  context.compactionInProgress = false;
24318
- const status = turnStatusFromResult(message);
24319
- const errorMessage = resultUserFacingError(message);
24399
+ const { status, errorMessage } = resultOutcome(
24400
+ message,
24401
+ claudeFailureHint({
24402
+ authenticationFailed: context.turnState?.authenticationFailed === true,
24403
+ environment: buildLaunchEnvironment(),
24404
+ cwd: NodePath8.resolve(context.session.cwd ?? ".")
24405
+ })
24406
+ );
24320
24407
  if (status === "failed") {
24321
24408
  await emitRuntimeError(context, errorMessage ?? "Claude turn failed.");
24322
24409
  }
@@ -24399,11 +24486,28 @@ function createClaudeAdapter(recipe, host, options) {
24399
24486
  payload: message
24400
24487
  }
24401
24488
  };
24402
- switch (message.subtype) {
24489
+ const subtype = message.subtype;
24490
+ const record = message;
24491
+ switch (subtype) {
24403
24492
  case "background_tasks_changed":
24404
24493
  case "vcs_state_changed":
24405
24494
  case "code_change_published":
24495
+ case "control_request_progress":
24496
+ case "worker_shutting_down":
24497
+ case "conversation_reset":
24498
+ return;
24499
+ case "informational":
24500
+ if (record.level === "warning" && typeof record.content === "string") {
24501
+ await emitRuntimeWarning(context, record.content, message);
24502
+ }
24503
+ return;
24504
+ case "model_refusal_no_fallback": {
24505
+ const explanation = typeof record.api_refusal_explanation === "string" ? record.api_refusal_explanation.trim() : "";
24506
+ const content = typeof record.content === "string" ? record.content : "";
24507
+ const text = explanation || content;
24508
+ if (text.length > 0) await emitRuntimeWarning(context, text, message);
24406
24509
  return;
24510
+ }
24407
24511
  }
24408
24512
  switch (message.subtype) {
24409
24513
  case "init":
@@ -24829,6 +24933,9 @@ function createClaudeAdapter(recipe, host, options) {
24829
24933
  if (sdkMessageType(message) === "command_lifecycle") {
24830
24934
  return;
24831
24935
  }
24936
+ if (sdkMessageType(message) === "conversation_reset") {
24937
+ return;
24938
+ }
24832
24939
  switch (message.type) {
24833
24940
  case "stream_event":
24834
24941
  await handleStreamEvent(context, message);
@@ -24964,7 +25071,7 @@ function createClaudeAdapter(recipe, host, options) {
24964
25071
  if (streamFiber) {
24965
25072
  await Promise.race([
24966
25073
  streamFiber.catch(() => void 0),
24967
- new Promise((resolve2) => setTimeout(resolve2, 1e3))
25074
+ new Promise((resolve3) => setTimeout(resolve3, 1e3))
24968
25075
  ]);
24969
25076
  }
24970
25077
  const updatedAt = nowIso();
@@ -25074,7 +25181,14 @@ function createClaudeAdapter(recipe, host, options) {
25074
25181
  return withProcessGeneration(context.session, context);
25075
25182
  };
25076
25183
  const startSession = async (input) => {
25077
- const extraArgs = parseCliArgs(recipe.launchArgs).flags;
25184
+ if (recipe.binaryPath.length === 0) throw new Error(CLAUDE_PROGRAM_NOT_CONFIGURED);
25185
+ const {
25186
+ "permission-mode": launchArgPermissionMode,
25187
+ "dangerously-skip-permissions": launchArgSkipPermissions,
25188
+ ...extraArgs
25189
+ } = parseCliArgs(recipe.launchArgs, {
25190
+ booleanFlags: ["dangerously-skip-permissions"]
25191
+ }).flags;
25078
25192
  const modelSelection = boundModelSelection(input.modelSelection, boundInstanceId);
25079
25193
  await modelCatalogRead;
25080
25194
  const caps = claudeModelCapabilities(
@@ -25103,6 +25217,21 @@ function createClaudeAdapter(recipe, host, options) {
25103
25217
  const ultracode = isClaudeUltracodeEffort(effort);
25104
25218
  const effectiveEffort = getEffectiveClaudeAgentEffort(effort);
25105
25219
  const permissionMode = claudePermissionModeFor(input.runtimeMode, input.nativeModeId);
25220
+ if (launchArgPermissionMode !== void 0) {
25221
+ (options?.log ?? host.log).warn("claude.launchArgs.permissionModeIgnored", {
25222
+ threadId: input.threadId,
25223
+ launchArgValue: launchArgPermissionMode,
25224
+ seatMode: permissionMode,
25225
+ reason: "permission mode follows the permission seat; the launch argument was removed"
25226
+ });
25227
+ }
25228
+ if (launchArgSkipPermissions !== void 0) {
25229
+ (options?.log ?? host.log).warn("claude.launchArgs.skipPermissionsIgnored", {
25230
+ threadId: input.threadId,
25231
+ seatMode: permissionMode,
25232
+ reason: "permission mode follows the permission seat; --dangerously-skip-permissions was removed"
25233
+ });
25234
+ }
25106
25235
  const settings = buildClaudeSessionSettings({
25107
25236
  thinking,
25108
25237
  fastMode,
@@ -25153,7 +25282,7 @@ function createClaudeAdapter(recipe, host, options) {
25153
25282
  return await Promise.race([
25154
25283
  contextDeferred.promise,
25155
25284
  new Promise(
25156
- (resolve2) => setTimeout(() => resolve2(void 0), CLAUDE_SESSION_CONTEXT_WAIT_MS)
25285
+ (resolve3) => setTimeout(() => resolve3(void 0), CLAUDE_SESSION_CONTEXT_WAIT_MS)
25157
25286
  )
25158
25287
  ]);
25159
25288
  } catch {
@@ -25687,6 +25816,7 @@ function createClaudeAdapter(recipe, host, options) {
25687
25816
  latestAssistantUsage: void 0,
25688
25817
  compactedSinceLatestAssistantUsage: false,
25689
25818
  retrying: false,
25819
+ authenticationFailed: false,
25690
25820
  nextSyntheticAssistantBlockIndex: -1
25691
25821
  };
25692
25822
  const updatedAt = nowIso();
@@ -25740,7 +25870,7 @@ function createClaudeAdapter(recipe, host, options) {
25740
25870
  context.query.interrupt().then(() => settled.promise).then(() => {
25741
25871
  acknowledged = true;
25742
25872
  }),
25743
- new Promise((resolve2) => setTimeout(resolve2, CLAUDE_INTERRUPT_GRACE_MS))
25873
+ new Promise((resolve3) => setTimeout(resolve3, CLAUDE_INTERRUPT_GRACE_MS))
25744
25874
  ]);
25745
25875
  } catch (cause) {
25746
25876
  throw toRequestError(threadId, "turn/interrupt", cause);
@@ -25913,19 +26043,32 @@ function createClaudeInstance(config, host, attachments, overrides) {
25913
26043
  return {
25914
26044
  installed: false,
25915
26045
  version: null,
25916
- readiness: "error",
26046
+ readiness: "not-installed",
25917
26047
  auth: { status: "unknown" },
25918
- detail: "Claude program path is not configured"
26048
+ detail: CLAUDE_PROGRAM_NOT_CONFIGURED
25919
26049
  };
25920
26050
  }
25921
26051
  if (signal?.aborted) {
25922
26052
  throw new Error("aborted");
25923
26053
  }
25924
- const handle = await host.process.spawn({
25925
- program: recipe.binaryPath,
25926
- args: ["--version"],
25927
- owner: { bindingId: host.bindingId }
25928
- });
26054
+ let handle;
26055
+ try {
26056
+ handle = await host.process.spawn({
26057
+ program: recipe.binaryPath,
26058
+ args: ["--version"],
26059
+ owner: { bindingId: host.bindingId }
26060
+ });
26061
+ } catch (error) {
26062
+ if (error instanceof ExecutorSpawnRefusedError) throw error;
26063
+ const failure = describeExecutorSpawnFailure(error);
26064
+ return {
26065
+ installed: false,
26066
+ version: null,
26067
+ readiness: failure.readiness,
26068
+ auth: { status: "unknown" },
26069
+ detail: failure.detail
26070
+ };
26071
+ }
25929
26072
  const [stdout, stderr, exitCode] = await Promise.all([
25930
26073
  collectProcessText(handle.stdout),
25931
26074
  collectProcessText(handle.stderr),
package/locales/en.json CHANGED
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "launchArgs": {
24
24
  "title": "Launch arguments",
25
- "description": "Additional CLI arguments passed on session start.",
25
+ "description": "Additional CLI arguments passed on session start. --permission-mode and --dangerously-skip-permissions are ignored here; choose the permission mode in the chat input.",
26
26
  "placeholder": "e.g. --chrome"
27
27
  }
28
28
  }
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "launchArgs": {
24
24
  "title": "启动参数",
25
- "description": "会话启动时传入的额外命令行参数。",
25
+ "description": "会话启动时传入的额外命令行参数。其中的 --permission-mode 与 --dangerously-skip-permissions 会被忽略,权限模式请在输入区选择。",
26
26
  "placeholder": "例如 --chrome"
27
27
  }
28
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-claude",
3
- "version": "0.2.2596",
3
+ "version": "0.2.2658",
4
4
  "description": "Claude executor: Claude Code CLI via @anthropic-ai/claude-agent-sdk.",
5
5
  "keywords": [
6
6
  "ycodium",
@@ -24,9 +24,9 @@
24
24
  "@types/node": "24.12.4",
25
25
  "esbuild": "0.28.1",
26
26
  "vite-plus": "0.2.2",
27
- "ycodium-executor-testing": "0.0.0",
28
- "@ycodium-ai/plugin-api": "0.2.2596",
29
- "ycodium-jsonl-stream": "0.0.0"
27
+ "@ycodium-ai/plugin-api": "0.2.2658",
28
+ "ycodium-jsonl-stream": "0.0.0",
29
+ "ycodium-executor-testing": "0.0.0"
30
30
  },
31
31
  "ycodium": {
32
32
  "plugin": "./dist/index.js",