@rk0429/agentic-relay 0.13.0 → 0.14.1

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.
Files changed (2) hide show
  1. package/dist/relay.mjs +69 -18
  2. package/package.json +1 -1
package/dist/relay.mjs CHANGED
@@ -438,7 +438,11 @@ function buildChildMcpServers(parentMcpServers, childHttpUrl) {
438
438
  }
439
439
  return result;
440
440
  }
441
- function inferFailureReason(stderr, stdout) {
441
+ function inferFailureReason(stderr, stdout, sdkErrorMetadata) {
442
+ if (sdkErrorMetadata) {
443
+ if (sdkErrorMetadata.subtype === "error_max_turns") return "max_turns_exhausted";
444
+ return "adapter_error";
445
+ }
442
446
  const combined = `${stderr} ${stdout}`.toLowerCase();
443
447
  if (combined.includes("timed out") || combined.includes("timeout")) return "timeout";
444
448
  if (combined.includes("max turns") || combined.includes("max_turns") || combined.includes("turn limit")) return "max_turns_exhausted";
@@ -452,8 +456,8 @@ function buildContextFromEnv() {
452
456
  }
453
457
  async function executeSpawnAgent(input, registry2, sessionManager2, guard, hooksEngine2, contextMonitor2, backendSelector, childHttpUrl, onProgress) {
454
458
  onProgress?.({ stage: "initializing", percent: 0 });
455
- let effectiveBackend = input.backend;
456
- let selectionReason = "direct";
459
+ let effectiveBackend;
460
+ let selectionReason;
457
461
  if (backendSelector) {
458
462
  const availableBackends = registry2.listIds();
459
463
  const selectionContext = {
@@ -465,6 +469,12 @@ async function executeSpawnAgent(input, registry2, sessionManager2, guard, hooks
465
469
  const selectionResult = backendSelector.selectBackendWithReason(selectionContext);
466
470
  effectiveBackend = selectionResult.backend;
467
471
  selectionReason = selectionResult.reason;
472
+ } else if (input.fallbackBackend) {
473
+ effectiveBackend = input.fallbackBackend;
474
+ selectionReason = "fallbackBackend";
475
+ } else {
476
+ effectiveBackend = "claude";
477
+ selectionReason = "default(no-selector)";
468
478
  }
469
479
  const envContext = buildContextFromEnv();
470
480
  const promptHash = RecursionGuard.hashPrompt(input.prompt);
@@ -694,7 +704,7 @@ ${input.prompt}`;
694
704
  }
695
705
  guard.recordSpawn(context);
696
706
  const status = result.exitCode === 0 ? "completed" : "error";
697
- const failureReason = result.exitCode !== 0 ? inferFailureReason(result.stderr, result.stdout) : void 0;
707
+ const failureReason = result.exitCode !== 0 ? inferFailureReason(result.stderr, result.stdout, result.sdkErrorMetadata) : void 0;
698
708
  await sessionManager2.update(session.relaySessionId, {
699
709
  status,
700
710
  ...result.nativeSessionId ? { nativeSessionId: result.nativeSessionId } : {}
@@ -770,8 +780,8 @@ var init_spawn_agent = __esm({
770
780
  init_recursion_guard();
771
781
  init_logger();
772
782
  spawnAgentInputSchema = z2.object({
773
- backend: z2.enum(["claude", "codex", "gemini"]).describe(
774
- "Required fallback backend. Overridden by automatic selection when BackendSelector is active (priority: preferredBackend > agentType mapping > taskType mapping > default)."
783
+ fallbackBackend: z2.enum(["claude", "codex", "gemini"]).optional().describe(
784
+ "Optional fallback backend. Used only when BackendSelector is not active or cannot determine a backend. When BackendSelector is active, backend is auto-selected by priority: preferredBackend > agentType mapping > taskType mapping > default (claude)."
775
785
  ),
776
786
  prompt: z2.string().describe(
777
787
  "The task instruction for the sub-agent. Be specific and include all necessary context for autonomous execution."
@@ -1312,7 +1322,7 @@ var init_server = __esm({
1312
1322
  this.guard = new RecursionGuard(guardConfig);
1313
1323
  this.backendSelector = new BackendSelector();
1314
1324
  this.server = new McpServer(
1315
- { name: "agentic-relay", version: "0.13.0" },
1325
+ { name: "agentic-relay", version: "0.14.1" },
1316
1326
  createMcpServerOptions()
1317
1327
  );
1318
1328
  this.registerTools(this.server);
@@ -1674,7 +1684,7 @@ var init_server = __esm({
1674
1684
  sessionIdGenerator: () => randomUUID()
1675
1685
  });
1676
1686
  const server = new McpServer(
1677
- { name: "agentic-relay", version: "0.13.0" },
1687
+ { name: "agentic-relay", version: "0.14.1" },
1678
1688
  createMcpServerOptions()
1679
1689
  );
1680
1690
  this.registerTools(server);
@@ -2115,6 +2125,7 @@ var ClaudeAdapter = class extends BaseAdapter {
2115
2125
  let errorMessages = [];
2116
2126
  let totalInputTokens = 0;
2117
2127
  let totalOutputTokens = 0;
2128
+ let sdkError = null;
2118
2129
  for await (const message of q) {
2119
2130
  if (message.type === "assistant") {
2120
2131
  const betaMessage = message.message;
@@ -2129,18 +2140,32 @@ var ClaudeAdapter = class extends BaseAdapter {
2129
2140
  resultText = message.result;
2130
2141
  } else {
2131
2142
  isError = true;
2132
- errorMessages = message.errors;
2143
+ sdkError = message;
2144
+ errorMessages = sdkError.errors;
2133
2145
  }
2134
2146
  }
2135
2147
  }
2136
2148
  logger.debug(`Claude SDK session: ${sessionId}`);
2149
+ if (sdkError) {
2150
+ logger.warn(
2151
+ `Claude SDK error: subtype=${sdkError.subtype} stop_reason=${sdkError.stop_reason} num_turns=${sdkError.num_turns} errors=[${sdkError.errors.join("; ")}]`
2152
+ );
2153
+ }
2137
2154
  const hasTokenUsage = totalInputTokens > 0 || totalOutputTokens > 0;
2138
2155
  return {
2139
2156
  exitCode: isError ? 1 : 0,
2140
2157
  stdout: resultText,
2141
2158
  stderr: errorMessages.join("\n"),
2142
2159
  ...sessionId ? { nativeSessionId: sessionId } : {},
2143
- ...hasTokenUsage ? { tokenUsage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens } } : {}
2160
+ ...hasTokenUsage ? { tokenUsage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens } } : {},
2161
+ ...sdkError ? {
2162
+ sdkErrorMetadata: {
2163
+ subtype: sdkError.subtype,
2164
+ numTurns: sdkError.num_turns,
2165
+ stopReason: sdkError.stop_reason,
2166
+ totalCostUsd: sdkError.total_cost_usd
2167
+ }
2168
+ } : {}
2144
2169
  };
2145
2170
  } catch (error) {
2146
2171
  if (abortController.signal.aborted) {
@@ -2221,13 +2246,23 @@ var ClaudeAdapter = class extends BaseAdapter {
2221
2246
  nativeSessionId
2222
2247
  };
2223
2248
  } else {
2224
- const errors = message.errors;
2249
+ const sdkError = message;
2250
+ const errors = sdkError.errors;
2251
+ logger.warn(
2252
+ `Claude SDK error: subtype=${sdkError.subtype} stop_reason=${sdkError.stop_reason} num_turns=${sdkError.num_turns} errors=[${sdkError.errors.join("; ")}]`
2253
+ );
2225
2254
  yield {
2226
2255
  type: "done",
2227
2256
  result: {
2228
2257
  exitCode: 1,
2229
2258
  stdout: "",
2230
- stderr: errors.join("\n")
2259
+ stderr: errors.join("\n"),
2260
+ sdkErrorMetadata: {
2261
+ subtype: sdkError.subtype,
2262
+ numTurns: sdkError.num_turns,
2263
+ stopReason: sdkError.stop_reason,
2264
+ totalCostUsd: sdkError.total_cost_usd
2265
+ }
2231
2266
  },
2232
2267
  nativeSessionId
2233
2268
  };
@@ -2833,9 +2868,8 @@ var GeminiAdapter = class extends BaseAdapter {
2833
2868
  const authenticated = hasApiKey || hasGoogleAdc;
2834
2869
  if (!authenticated) {
2835
2870
  return {
2836
- // Optimistic fallback: Gemini may still authenticate via ADC at runtime.
2837
- authenticated: true,
2838
- message: "Gemini authentication status unknown - ADC may be available at runtime"
2871
+ authenticated: false,
2872
+ message: "Gemini authentication not configured. Set GEMINI_API_KEY or configure Google ADC."
2839
2873
  };
2840
2874
  }
2841
2875
  return { authenticated };
@@ -2883,6 +2917,20 @@ ${prompt}`;
2883
2917
  }
2884
2918
  return prompt;
2885
2919
  }
2920
+ buildEnv(flags) {
2921
+ const env = {};
2922
+ for (const [key, value] of Object.entries(process.env)) {
2923
+ if (value !== void 0) {
2924
+ env[key] = value;
2925
+ }
2926
+ }
2927
+ if (flags.mcpContext) {
2928
+ env.RELAY_TRACE_ID = flags.mcpContext.traceId;
2929
+ env.RELAY_PARENT_SESSION_ID = flags.mcpContext.parentSessionId;
2930
+ env.RELAY_DEPTH = String(flags.mcpContext.depth);
2931
+ }
2932
+ return env;
2933
+ }
2886
2934
  async execute(flags) {
2887
2935
  if (!flags.prompt) {
2888
2936
  throw new Error("execute requires a prompt (-p flag)");
@@ -2899,7 +2947,10 @@ ${prompt}`;
2899
2947
  args.push("--verbose");
2900
2948
  }
2901
2949
  args.push("-p", effectivePrompt);
2902
- return this.processManager.execute(this.command, args);
2950
+ return this.processManager.execute(this.command, args, {
2951
+ stdinMode: "ignore",
2952
+ env: this.buildEnv(flags)
2953
+ });
2903
2954
  }
2904
2955
  async resumeSession(sessionId, flags) {
2905
2956
  const args = [];
@@ -4623,7 +4674,7 @@ function createVersionCommand(registry2) {
4623
4674
  description: "Show relay and backend versions"
4624
4675
  },
4625
4676
  async run() {
4626
- const relayVersion = "0.13.0";
4677
+ const relayVersion = "0.14.1";
4627
4678
  console.log(`agentic-relay v${relayVersion}`);
4628
4679
  console.log("");
4629
4680
  console.log("Backends:");
@@ -4973,7 +5024,7 @@ void configManager.getConfig().then((config) => {
4973
5024
  var main = defineCommand10({
4974
5025
  meta: {
4975
5026
  name: "relay",
4976
- version: "0.13.0",
5027
+ version: "0.14.1",
4977
5028
  description: "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI"
4978
5029
  },
4979
5030
  subCommands: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rk0429/agentic-relay",
3
- "version": "0.13.0",
3
+ "version": "0.14.1",
4
4
  "description": "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI with MCP-based multi-layer sub-agent orchestration",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",