@rk0429/agentic-relay 0.10.0 → 0.11.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.
Files changed (2) hide show
  1. package/dist/relay.mjs +66 -26
  2. package/package.json +1 -1
package/dist/relay.mjs CHANGED
@@ -55,8 +55,8 @@ var init_recursion_guard = __esm({
55
55
  RecursionGuard = class _RecursionGuard {
56
56
  constructor(config = {
57
57
  maxDepth: 5,
58
- maxCallsPerSession: 20,
59
- timeoutSec: 300
58
+ maxCallsPerSession: 50,
59
+ timeoutSec: 1800
60
60
  }) {
61
61
  this.config = config;
62
62
  }
@@ -110,10 +110,15 @@ var init_recursion_guard = __esm({
110
110
  reason: `Max calls per session exceeded: ${currentCount} >= ${this.config.maxCallsPerSession}`
111
111
  };
112
112
  }
113
- if (this.detectLoop(context.traceId, context.backend, context.promptHash)) {
113
+ if (this.detectLoop(
114
+ context.traceId,
115
+ context.backend,
116
+ context.promptHash,
117
+ context.taskType
118
+ )) {
114
119
  return {
115
120
  allowed: false,
116
- reason: `Loop detected: same (backend=${context.backend}, promptHash=${context.promptHash}) appeared 3+ times in trace ${context.traceId}`
121
+ reason: `Loop detected: same (backend=${context.backend}, taskType=${context.taskType ?? ""}, promptHash=${context.promptHash}) appeared 5+ times in trace ${context.traceId}`
117
122
  };
118
123
  }
119
124
  return { allowed: true };
@@ -127,7 +132,7 @@ var init_recursion_guard = __esm({
127
132
  } else {
128
133
  this.callCounts.set(context.traceId, { count: 1, createdAt: Date.now() });
129
134
  }
130
- const key = `${context.backend}:${context.promptHash}`;
135
+ const key = `${context.backend}:${context.taskType ?? ""}:${context.promptHash}`;
131
136
  const hashEntry = this.promptHashes.get(context.traceId);
132
137
  if (hashEntry) {
133
138
  hashEntry.hashes.push(key);
@@ -135,12 +140,12 @@ var init_recursion_guard = __esm({
135
140
  this.promptHashes.set(context.traceId, { hashes: [key], createdAt: Date.now() });
136
141
  }
137
142
  }
138
- /** Detect if the same (backend + promptHash) combination has appeared 3+ times */
139
- detectLoop(traceId, backend, promptHash) {
140
- const key = `${backend}:${promptHash}`;
143
+ /** Detect if the same (backend + taskType + promptHash) combination has appeared 5+ times */
144
+ detectLoop(traceId, backend, promptHash, taskType) {
145
+ const key = `${backend}:${taskType ?? ""}:${promptHash}`;
141
146
  const hashes = this.promptHashes.get(traceId)?.hashes ?? [];
142
147
  const count = hashes.filter((h) => h === key).length;
143
- return count >= 3;
148
+ return count >= 5;
144
149
  }
145
150
  /** Get current config (for testing/inspection) */
146
151
  getConfig() {
@@ -344,7 +349,8 @@ async function executeSpawnAgent(input, registry2, sessionManager2, guard, hooks
344
349
  traceId: envContext.traceId,
345
350
  depth: envContext.depth,
346
351
  backend: effectiveBackend,
347
- promptHash
352
+ promptHash,
353
+ taskType: input.taskType
348
354
  };
349
355
  const guardResult = guard.canSpawn(context);
350
356
  if (!guardResult.allowed) {
@@ -490,7 +496,34 @@ ${input.prompt}`;
490
496
  _failureReason: "session_continuation_unsupported"
491
497
  };
492
498
  }
493
- return adapter.continueSession(input.resumeSessionId, effectivePrompt);
499
+ let effectiveNativeSessionId;
500
+ if (input.resumeSessionId.startsWith("relay-")) {
501
+ const existingSession = await sessionManager2.get(input.resumeSessionId);
502
+ if (!existingSession) {
503
+ return {
504
+ exitCode: 1,
505
+ stdout: "",
506
+ stderr: `Session not found: ${input.resumeSessionId}`,
507
+ _noSession: true,
508
+ _failureReason: "session_not_found"
509
+ };
510
+ }
511
+ if (!existingSession.nativeSessionId) {
512
+ return {
513
+ exitCode: 1,
514
+ stdout: "",
515
+ stderr: `Session ${input.resumeSessionId} has no native session ID (session may have failed before completing)`,
516
+ _noSession: true,
517
+ _failureReason: "session_not_found"
518
+ };
519
+ }
520
+ effectiveNativeSessionId = existingSession.nativeSessionId;
521
+ } else {
522
+ effectiveNativeSessionId = input.resumeSessionId;
523
+ }
524
+ return adapter.continueSession(effectiveNativeSessionId, effectivePrompt, {
525
+ ...input.maxTurns !== void 0 ? { maxTurns: input.maxTurns } : {}
526
+ });
494
527
  } else {
495
528
  let mcpServers;
496
529
  if (childHttpUrl) {
@@ -550,7 +583,10 @@ ${input.prompt}`;
550
583
  guard.recordSpawn(context);
551
584
  const status = result.exitCode === 0 ? "completed" : "error";
552
585
  const failureReason = result.exitCode !== 0 ? inferFailureReason(result.stderr, result.stdout) : void 0;
553
- await sessionManager2.update(session.relaySessionId, { status });
586
+ await sessionManager2.update(session.relaySessionId, {
587
+ status,
588
+ ...result.nativeSessionId ? { nativeSessionId: result.nativeSessionId } : {}
589
+ });
554
590
  const completedAt = (/* @__PURE__ */ new Date()).toISOString();
555
591
  const metadata = {
556
592
  durationMs: new Date(completedAt).getTime() - new Date(spawnStartedAt).getTime(),
@@ -1115,7 +1151,7 @@ var init_server = __esm({
1115
1151
  this.backendSelector = new BackendSelector();
1116
1152
  this.server = new McpServer({
1117
1153
  name: "agentic-relay",
1118
- version: "0.10.0"
1154
+ version: "0.11.0"
1119
1155
  });
1120
1156
  this.registerTools(this.server);
1121
1157
  }
@@ -1423,7 +1459,7 @@ var init_server = __esm({
1423
1459
  });
1424
1460
  const server = new McpServer({
1425
1461
  name: "agentic-relay",
1426
- version: "0.10.0"
1462
+ version: "0.11.0"
1427
1463
  });
1428
1464
  this.registerTools(server);
1429
1465
  transport.onclose = () => {
@@ -1639,7 +1675,7 @@ var BaseAdapter = class _BaseAdapter {
1639
1675
  }
1640
1676
  return result.stdout.trim();
1641
1677
  }
1642
- async continueSession(_nativeSessionId, _prompt) {
1678
+ async continueSession(_nativeSessionId, _prompt, _options) {
1643
1679
  return {
1644
1680
  exitCode: 1,
1645
1681
  stdout: "",
@@ -1996,31 +2032,33 @@ var ClaudeAdapter = class extends BaseAdapter {
1996
2032
  if (timer !== void 0) clearTimeout(timer);
1997
2033
  }
1998
2034
  }
1999
- async continueSession(nativeSessionId, prompt) {
2035
+ async continueSession(nativeSessionId, prompt, options) {
2000
2036
  const timeoutMs = resolveClaudeSdkTimeoutMs();
2001
2037
  const abortController = new AbortController();
2002
2038
  const timer = timeoutMs !== void 0 ? setTimeout(() => abortController.abort(), timeoutMs) : void 0;
2003
2039
  try {
2004
2040
  const { query } = await loadClaudeSDK();
2005
2041
  const permissionMode = this.getPermissionMode();
2006
- const options = {
2042
+ const queryOptions = {
2007
2043
  abortController,
2008
2044
  resume: nativeSessionId,
2009
- maxTurns: 1,
2045
+ maxTurns: options?.maxTurns ?? 1,
2010
2046
  cwd: process.cwd(),
2011
2047
  strictMcpConfig: true
2012
2048
  };
2013
2049
  if (permissionMode === "bypassPermissions") {
2014
- options.permissionMode = "bypassPermissions";
2015
- options.allowDangerouslySkipPermissions = true;
2050
+ queryOptions.permissionMode = "bypassPermissions";
2051
+ queryOptions.allowDangerouslySkipPermissions = true;
2016
2052
  }
2017
2053
  const q = query({
2018
2054
  prompt,
2019
- options
2055
+ options: queryOptions
2020
2056
  });
2021
2057
  let resultText = "";
2058
+ let sessionId = "";
2022
2059
  for await (const message of q) {
2023
2060
  if (message.type === "result") {
2061
+ sessionId = message.session_id;
2024
2062
  if (message.subtype === "success") {
2025
2063
  resultText = message.result;
2026
2064
  }
@@ -2029,7 +2067,8 @@ var ClaudeAdapter = class extends BaseAdapter {
2029
2067
  return {
2030
2068
  exitCode: 0,
2031
2069
  stdout: resultText,
2032
- stderr: ""
2070
+ stderr: "",
2071
+ ...sessionId ? { nativeSessionId: sessionId } : {}
2033
2072
  };
2034
2073
  } catch (error) {
2035
2074
  if (abortController.signal.aborted) {
@@ -2459,7 +2498,7 @@ ${prompt}`;
2459
2498
  };
2460
2499
  }
2461
2500
  }
2462
- async continueSession(nativeSessionId, prompt) {
2501
+ async continueSession(nativeSessionId, prompt, _options) {
2463
2502
  try {
2464
2503
  const { Codex } = await loadCodexSDK();
2465
2504
  const codex = new Codex();
@@ -2471,7 +2510,8 @@ ${prompt}`;
2471
2510
  return {
2472
2511
  exitCode: 0,
2473
2512
  stdout: result.finalResponse,
2474
- stderr: ""
2513
+ stderr: "",
2514
+ nativeSessionId
2475
2515
  };
2476
2516
  } catch (error) {
2477
2517
  return {
@@ -4371,7 +4411,7 @@ function createVersionCommand(registry2) {
4371
4411
  description: "Show relay and backend versions"
4372
4412
  },
4373
4413
  async run() {
4374
- const relayVersion = "0.10.0";
4414
+ const relayVersion = "0.11.0";
4375
4415
  console.log(`agentic-relay v${relayVersion}`);
4376
4416
  console.log("");
4377
4417
  console.log("Backends:");
@@ -4721,7 +4761,7 @@ void configManager.getConfig().then((config) => {
4721
4761
  var main = defineCommand10({
4722
4762
  meta: {
4723
4763
  name: "relay",
4724
- version: "0.10.0",
4764
+ version: "0.11.0",
4725
4765
  description: "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI"
4726
4766
  },
4727
4767
  subCommands: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rk0429/agentic-relay",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
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",