@rk0429/agentic-relay 0.8.0 → 0.9.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.
- package/dist/relay.mjs +161 -58
- package/package.json +1 -1
package/dist/relay.mjs
CHANGED
|
@@ -18,6 +18,9 @@ function resolveLogLevel() {
|
|
|
18
18
|
}
|
|
19
19
|
return 3;
|
|
20
20
|
}
|
|
21
|
+
function redirectToStderr() {
|
|
22
|
+
logger.options.stdout = process.stderr;
|
|
23
|
+
}
|
|
21
24
|
var LOG_LEVEL_MAP, logger;
|
|
22
25
|
var init_logger = __esm({
|
|
23
26
|
"src/infrastructure/logger.ts"() {
|
|
@@ -307,6 +310,12 @@ function buildChildMcpServers(parentMcpServers, childHttpUrl) {
|
|
|
307
310
|
}
|
|
308
311
|
return result;
|
|
309
312
|
}
|
|
313
|
+
function inferFailureReason(stderr, stdout) {
|
|
314
|
+
const combined = `${stderr} ${stdout}`.toLowerCase();
|
|
315
|
+
if (combined.includes("timed out") || combined.includes("timeout")) return "timeout";
|
|
316
|
+
if (combined.includes("max turns") || combined.includes("max_turns") || combined.includes("turn limit")) return "max_turns_exhausted";
|
|
317
|
+
return "adapter_error";
|
|
318
|
+
}
|
|
310
319
|
function buildContextFromEnv() {
|
|
311
320
|
const traceId = process.env["RELAY_TRACE_ID"] ?? `trace-${nanoid2()}`;
|
|
312
321
|
const parentSessionId = process.env["RELAY_PARENT_SESSION_ID"] ?? null;
|
|
@@ -344,7 +353,8 @@ async function executeSpawnAgent(input, registry2, sessionManager2, guard, hooks
|
|
|
344
353
|
sessionId: "",
|
|
345
354
|
exitCode: 1,
|
|
346
355
|
stdout: "",
|
|
347
|
-
stderr: `Spawn blocked: ${guardResult.reason}
|
|
356
|
+
stderr: `Spawn blocked: ${guardResult.reason}`,
|
|
357
|
+
failureReason: "recursion_blocked"
|
|
348
358
|
};
|
|
349
359
|
}
|
|
350
360
|
const adapter = registry2.get(effectiveBackend);
|
|
@@ -354,7 +364,8 @@ async function executeSpawnAgent(input, registry2, sessionManager2, guard, hooks
|
|
|
354
364
|
sessionId: "",
|
|
355
365
|
exitCode: 1,
|
|
356
366
|
stdout: "",
|
|
357
|
-
stderr: `Backend "${effectiveBackend}" is not available. Use list_available_backends to see available options
|
|
367
|
+
stderr: `Backend "${effectiveBackend}" is not available. Use list_available_backends to see available options.`,
|
|
368
|
+
failureReason: "backend_unavailable"
|
|
358
369
|
};
|
|
359
370
|
}
|
|
360
371
|
const spawnStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -446,7 +457,8 @@ ${wrapped}` : wrapped;
|
|
|
446
457
|
sessionId: "",
|
|
447
458
|
exitCode: 1,
|
|
448
459
|
stdout: "",
|
|
449
|
-
stderr: `Task instruction file not found: ${input.taskInstructionPath}
|
|
460
|
+
stderr: `Task instruction file not found: ${input.taskInstructionPath}`,
|
|
461
|
+
failureReason: "instruction_file_error"
|
|
450
462
|
};
|
|
451
463
|
}
|
|
452
464
|
const instructionContent = readFileSync(safePath, "utf-8");
|
|
@@ -459,7 +471,8 @@ ${input.prompt}`;
|
|
|
459
471
|
sessionId: "",
|
|
460
472
|
exitCode: 1,
|
|
461
473
|
stdout: "",
|
|
462
|
-
stderr: `Failed to read task instruction file: ${message}
|
|
474
|
+
stderr: `Failed to read task instruction file: ${message}`,
|
|
475
|
+
failureReason: "instruction_file_error"
|
|
463
476
|
};
|
|
464
477
|
}
|
|
465
478
|
}
|
|
@@ -473,7 +486,8 @@ ${input.prompt}`;
|
|
|
473
486
|
exitCode: 1,
|
|
474
487
|
stdout: "",
|
|
475
488
|
stderr: `Backend "${effectiveBackend}" does not support session continuation (continueSession).`,
|
|
476
|
-
_noSession: true
|
|
489
|
+
_noSession: true,
|
|
490
|
+
_failureReason: "session_continuation_unsupported"
|
|
477
491
|
};
|
|
478
492
|
}
|
|
479
493
|
return adapter.continueSession(input.resumeSessionId, effectivePrompt);
|
|
@@ -497,7 +511,8 @@ ${input.prompt}`;
|
|
|
497
511
|
maxDepth: guard.getConfig().maxDepth,
|
|
498
512
|
traceId: envContext.traceId
|
|
499
513
|
},
|
|
500
|
-
...mcpServers ? { mcpServers } : {}
|
|
514
|
+
...mcpServers ? { mcpServers } : {},
|
|
515
|
+
...input.timeoutMs ? { timeoutMs: input.timeoutMs } : {}
|
|
501
516
|
});
|
|
502
517
|
}
|
|
503
518
|
})();
|
|
@@ -517,7 +532,8 @@ ${input.prompt}`;
|
|
|
517
532
|
sessionId: session.relaySessionId,
|
|
518
533
|
exitCode: result.exitCode,
|
|
519
534
|
stdout: result.stdout,
|
|
520
|
-
stderr: result.stderr
|
|
535
|
+
stderr: result.stderr,
|
|
536
|
+
..."_failureReason" in result ? { failureReason: result._failureReason } : {}
|
|
521
537
|
};
|
|
522
538
|
}
|
|
523
539
|
onProgress?.({ stage: "executing", percent: 50 });
|
|
@@ -533,6 +549,7 @@ ${input.prompt}`;
|
|
|
533
549
|
}
|
|
534
550
|
guard.recordSpawn(context);
|
|
535
551
|
const status = result.exitCode === 0 ? "completed" : "error";
|
|
552
|
+
const failureReason = result.exitCode !== 0 ? inferFailureReason(result.stderr, result.stdout) : void 0;
|
|
536
553
|
await sessionManager2.update(session.relaySessionId, { status });
|
|
537
554
|
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
538
555
|
const metadata = {
|
|
@@ -541,7 +558,8 @@ ${input.prompt}`;
|
|
|
541
558
|
...input.preferredBackend ? { requestedBackend: input.preferredBackend } : {},
|
|
542
559
|
selectionReason,
|
|
543
560
|
startedAt: spawnStartedAt,
|
|
544
|
-
completedAt
|
|
561
|
+
completedAt,
|
|
562
|
+
...result.tokenUsage ? { tokenUsage: result.tokenUsage } : {}
|
|
545
563
|
};
|
|
546
564
|
onProgress?.({ stage: "completed", percent: 100 });
|
|
547
565
|
if (hooksEngine2) {
|
|
@@ -581,16 +599,19 @@ ${input.prompt}`;
|
|
|
581
599
|
stdout: result.stdout,
|
|
582
600
|
stderr: result.stderr,
|
|
583
601
|
nativeSessionId: result.nativeSessionId,
|
|
584
|
-
metadata
|
|
602
|
+
metadata,
|
|
603
|
+
...failureReason ? { failureReason } : {}
|
|
585
604
|
};
|
|
586
605
|
} catch (error) {
|
|
587
606
|
await sessionManager2.update(session.relaySessionId, { status: "error" });
|
|
588
607
|
const message = error instanceof Error ? error.message : String(error);
|
|
608
|
+
const catchFailureReason = message.toLowerCase().includes("timed out") || message.toLowerCase().includes("timeout") ? "timeout" : "unknown";
|
|
589
609
|
return {
|
|
590
610
|
sessionId: session.relaySessionId,
|
|
591
611
|
exitCode: 1,
|
|
592
612
|
stdout: "",
|
|
593
|
-
stderr: message
|
|
613
|
+
stderr: message,
|
|
614
|
+
failureReason: catchFailureReason
|
|
594
615
|
};
|
|
595
616
|
}
|
|
596
617
|
}
|
|
@@ -620,7 +641,8 @@ var init_spawn_agent = __esm({
|
|
|
620
641
|
timeoutMs: z2.number().optional().describe("Timeout in milliseconds for agent execution. Default: no timeout."),
|
|
621
642
|
taskInstructionPath: z2.string().optional().describe(
|
|
622
643
|
"Path to a file containing task instructions. Content is prepended to the prompt. Path is resolved relative to the project root and validated against path traversal."
|
|
623
|
-
)
|
|
644
|
+
),
|
|
645
|
+
label: z2.string().optional().describe("Human-readable label for identifying this agent in parallel results")
|
|
624
646
|
});
|
|
625
647
|
}
|
|
626
648
|
});
|
|
@@ -723,13 +745,15 @@ async function executeSpawnAgentsParallel(agents, registry2, sessionManager2, gu
|
|
|
723
745
|
const reason = `Max depth exceeded: ${envContext.depth} >= ${guard.getConfig().maxDepth}`;
|
|
724
746
|
logger.warn(`Batch spawn blocked by RecursionGuard: ${reason}`);
|
|
725
747
|
return {
|
|
726
|
-
results: agents.map((
|
|
748
|
+
results: agents.map((agent, index) => ({
|
|
727
749
|
index,
|
|
728
750
|
sessionId: "",
|
|
729
751
|
exitCode: 1,
|
|
730
752
|
stdout: "",
|
|
731
753
|
stderr: `Batch spawn blocked: ${reason}`,
|
|
732
|
-
error: reason
|
|
754
|
+
error: reason,
|
|
755
|
+
failureReason: "recursion_blocked",
|
|
756
|
+
...agent.label ? { label: agent.label } : {}
|
|
733
757
|
})),
|
|
734
758
|
totalCount: agents.length,
|
|
735
759
|
successCount: 0,
|
|
@@ -742,13 +766,15 @@ async function executeSpawnAgentsParallel(agents, registry2, sessionManager2, gu
|
|
|
742
766
|
const reason = `Batch would exceed max calls per session: ${currentCount} + ${agents.length} > ${maxCalls}`;
|
|
743
767
|
logger.warn(`Batch spawn blocked by RecursionGuard: ${reason}`);
|
|
744
768
|
return {
|
|
745
|
-
results: agents.map((
|
|
769
|
+
results: agents.map((agent, index) => ({
|
|
746
770
|
index,
|
|
747
771
|
sessionId: "",
|
|
748
772
|
exitCode: 1,
|
|
749
773
|
stdout: "",
|
|
750
774
|
stderr: `Batch spawn blocked: ${reason}`,
|
|
751
|
-
error: reason
|
|
775
|
+
error: reason,
|
|
776
|
+
failureReason: "recursion_blocked",
|
|
777
|
+
...agent.label ? { label: agent.label } : {}
|
|
752
778
|
})),
|
|
753
779
|
totalCount: agents.length,
|
|
754
780
|
successCount: 0,
|
|
@@ -790,7 +816,9 @@ async function executeSpawnAgentsParallel(agents, registry2, sessionManager2, gu
|
|
|
790
816
|
stdout: r.stdout,
|
|
791
817
|
stderr: r.stderr,
|
|
792
818
|
...r.nativeSessionId ? { nativeSessionId: r.nativeSessionId } : {},
|
|
793
|
-
...r.metadata ? { metadata: r.metadata } : {}
|
|
819
|
+
...r.metadata ? { metadata: r.metadata } : {},
|
|
820
|
+
...r.failureReason ? { failureReason: r.failureReason } : {},
|
|
821
|
+
...agents[index]?.label ? { label: agents[index].label } : {}
|
|
794
822
|
};
|
|
795
823
|
if (r.exitCode !== 0) {
|
|
796
824
|
base.originalInput = agents[index];
|
|
@@ -805,7 +833,9 @@ async function executeSpawnAgentsParallel(agents, registry2, sessionManager2, gu
|
|
|
805
833
|
stdout: "",
|
|
806
834
|
stderr: errorMessage,
|
|
807
835
|
error: errorMessage,
|
|
808
|
-
originalInput: agents[index]
|
|
836
|
+
originalInput: agents[index],
|
|
837
|
+
failureReason: "unknown",
|
|
838
|
+
...agents[index]?.label ? { label: agents[index].label } : {}
|
|
809
839
|
};
|
|
810
840
|
});
|
|
811
841
|
const successCount = results.filter((r) => r.exitCode === 0).length;
|
|
@@ -979,6 +1009,70 @@ var init_backend_selector = __esm({
|
|
|
979
1009
|
}
|
|
980
1010
|
});
|
|
981
1011
|
|
|
1012
|
+
// src/mcp-server/response-formatter.ts
|
|
1013
|
+
function formatSpawnAgentResponse(result) {
|
|
1014
|
+
const isError = result.exitCode !== 0;
|
|
1015
|
+
let text;
|
|
1016
|
+
if (isError) {
|
|
1017
|
+
const reasonPart = result.failureReason ? `, reason: ${result.failureReason}` : "";
|
|
1018
|
+
text = `FAILED (exit ${result.exitCode}${reasonPart})`;
|
|
1019
|
+
if (result.stderr) {
|
|
1020
|
+
text += `
|
|
1021
|
+
${result.stderr}`;
|
|
1022
|
+
}
|
|
1023
|
+
} else {
|
|
1024
|
+
text = `Session: ${result.sessionId}
|
|
1025
|
+
|
|
1026
|
+
${result.stdout}`;
|
|
1027
|
+
}
|
|
1028
|
+
if (result.metadata) {
|
|
1029
|
+
text += `
|
|
1030
|
+
|
|
1031
|
+
<metadata>
|
|
1032
|
+
${JSON.stringify(result.metadata, null, 2)}
|
|
1033
|
+
</metadata>`;
|
|
1034
|
+
}
|
|
1035
|
+
return { text, isError };
|
|
1036
|
+
}
|
|
1037
|
+
function formatParallelResponse(result) {
|
|
1038
|
+
const isError = result.failureCount === result.totalCount;
|
|
1039
|
+
const parts = [];
|
|
1040
|
+
if (result.hasConflicts && result.conflicts) {
|
|
1041
|
+
parts.push(`\u26A0 FILE CONFLICTS DETECTED: Multiple agents modified the same files.`);
|
|
1042
|
+
parts.push(`Conflicting files: ${result.conflicts.map((c) => c.path).join(", ")}
|
|
1043
|
+
`);
|
|
1044
|
+
}
|
|
1045
|
+
const durations = result.results.map((r) => r.metadata?.durationMs).filter((d) => d !== void 0);
|
|
1046
|
+
const avgDuration = durations.length > 0 ? (durations.reduce((a, b) => a + b, 0) / durations.length / 1e3).toFixed(1) : "?";
|
|
1047
|
+
parts.push(
|
|
1048
|
+
`${result.totalCount} agents: ${result.successCount} succeeded, ${result.failureCount} failed (avg ${avgDuration}s)
|
|
1049
|
+
`
|
|
1050
|
+
);
|
|
1051
|
+
for (const r of result.results) {
|
|
1052
|
+
const labelPart = r.label ? ` [${r.label}]` : "";
|
|
1053
|
+
const backend = r.metadata?.selectedBackend ?? "?";
|
|
1054
|
+
const duration = r.metadata?.durationMs !== void 0 ? `${(r.metadata.durationMs / 1e3).toFixed(1)}s` : "?s";
|
|
1055
|
+
if (r.exitCode === 0) {
|
|
1056
|
+
parts.push(`--- Agent ${r.index}${labelPart} (${backend}, ${duration}) SUCCESS ---`);
|
|
1057
|
+
parts.push(r.stdout || "(no output)");
|
|
1058
|
+
} else {
|
|
1059
|
+
const reasonPart = r.failureReason ? `, reason: ${r.failureReason}` : "";
|
|
1060
|
+
parts.push(`--- Agent ${r.index}${labelPart} FAILED (${backend}, ${duration}${reasonPart}) ---`);
|
|
1061
|
+
parts.push(r.stderr || r.error || "(no output)");
|
|
1062
|
+
}
|
|
1063
|
+
parts.push("");
|
|
1064
|
+
}
|
|
1065
|
+
parts.push(`<metadata>
|
|
1066
|
+
${JSON.stringify(result, null, 2)}
|
|
1067
|
+
</metadata>`);
|
|
1068
|
+
return { text: parts.join("\n"), isError };
|
|
1069
|
+
}
|
|
1070
|
+
var init_response_formatter = __esm({
|
|
1071
|
+
"src/mcp-server/response-formatter.ts"() {
|
|
1072
|
+
"use strict";
|
|
1073
|
+
}
|
|
1074
|
+
});
|
|
1075
|
+
|
|
982
1076
|
// src/mcp-server/server.ts
|
|
983
1077
|
var server_exports = {};
|
|
984
1078
|
__export(server_exports, {
|
|
@@ -1002,6 +1096,7 @@ var init_server = __esm({
|
|
|
1002
1096
|
init_list_available_backends();
|
|
1003
1097
|
init_backend_selector();
|
|
1004
1098
|
init_logger();
|
|
1099
|
+
init_response_formatter();
|
|
1005
1100
|
spawnAgentsParallelInputShape = {
|
|
1006
1101
|
agents: z5.array(spawnAgentInputSchema).min(1).max(10).describe(
|
|
1007
1102
|
"Array of agent configurations to execute in parallel (1-10 agents)"
|
|
@@ -1018,7 +1113,7 @@ var init_server = __esm({
|
|
|
1018
1113
|
this.backendSelector = new BackendSelector();
|
|
1019
1114
|
this.server = new McpServer({
|
|
1020
1115
|
name: "agentic-relay",
|
|
1021
|
-
version: "0.
|
|
1116
|
+
version: "0.9.1"
|
|
1022
1117
|
});
|
|
1023
1118
|
this.registerTools(this.server);
|
|
1024
1119
|
}
|
|
@@ -1067,17 +1162,7 @@ var init_server = __esm({
|
|
|
1067
1162
|
this._childHttpUrl,
|
|
1068
1163
|
onProgress
|
|
1069
1164
|
);
|
|
1070
|
-
const isError = result
|
|
1071
|
-
let text = isError ? `Error (exit ${result.exitCode}): ${result.stderr || result.stdout}` : `Session: ${result.sessionId}
|
|
1072
|
-
|
|
1073
|
-
${result.stdout}`;
|
|
1074
|
-
if (result.metadata) {
|
|
1075
|
-
text += `
|
|
1076
|
-
|
|
1077
|
-
<metadata>
|
|
1078
|
-
${JSON.stringify(result.metadata, null, 2)}
|
|
1079
|
-
</metadata>`;
|
|
1080
|
-
}
|
|
1165
|
+
const { text, isError } = formatSpawnAgentResponse(result);
|
|
1081
1166
|
return {
|
|
1082
1167
|
content: [{ type: "text", text }],
|
|
1083
1168
|
isError
|
|
@@ -1122,15 +1207,7 @@ ${JSON.stringify(result.metadata, null, 2)}
|
|
|
1122
1207
|
this._childHttpUrl,
|
|
1123
1208
|
onProgress
|
|
1124
1209
|
);
|
|
1125
|
-
const isError = result
|
|
1126
|
-
let text = "";
|
|
1127
|
-
if (result.hasConflicts) {
|
|
1128
|
-
text += "\u26A0 FILE CONFLICTS DETECTED: Multiple agents modified the same files.\n";
|
|
1129
|
-
text += `Conflicting files: ${result.conflicts.map((c) => c.path).join(", ")}
|
|
1130
|
-
|
|
1131
|
-
`;
|
|
1132
|
-
}
|
|
1133
|
-
text += JSON.stringify(result, null, 2);
|
|
1210
|
+
const { text, isError } = formatParallelResponse(result);
|
|
1134
1211
|
return {
|
|
1135
1212
|
content: [{ type: "text", text }],
|
|
1136
1213
|
isError
|
|
@@ -1151,11 +1228,24 @@ ${JSON.stringify(result.metadata, null, 2)}
|
|
|
1151
1228
|
failedResults: z5.array(z5.object({
|
|
1152
1229
|
index: z5.number(),
|
|
1153
1230
|
originalInput: spawnAgentInputSchema
|
|
1154
|
-
})).min(1).describe("Array of failed results with their original input configurations")
|
|
1231
|
+
})).min(1).describe("Array of failed results with their original input configurations"),
|
|
1232
|
+
overrides: z5.object({
|
|
1233
|
+
maxTurns: z5.number().optional(),
|
|
1234
|
+
timeoutMs: z5.number().optional(),
|
|
1235
|
+
preferredBackend: z5.enum(["claude", "codex", "gemini"]).optional()
|
|
1236
|
+
}).optional().describe("Parameter overrides applied to all retried agents")
|
|
1155
1237
|
},
|
|
1156
1238
|
async (params) => {
|
|
1157
1239
|
try {
|
|
1158
|
-
const agents = params.failedResults.map((r) =>
|
|
1240
|
+
const agents = params.failedResults.map((r) => {
|
|
1241
|
+
const input = { ...r.originalInput };
|
|
1242
|
+
if (params.overrides) {
|
|
1243
|
+
if (params.overrides.maxTurns !== void 0) input.maxTurns = params.overrides.maxTurns;
|
|
1244
|
+
if (params.overrides.timeoutMs !== void 0) input.timeoutMs = params.overrides.timeoutMs;
|
|
1245
|
+
if (params.overrides.preferredBackend !== void 0) input.preferredBackend = params.overrides.preferredBackend;
|
|
1246
|
+
}
|
|
1247
|
+
return input;
|
|
1248
|
+
});
|
|
1159
1249
|
const result = await executeSpawnAgentsParallel(
|
|
1160
1250
|
agents,
|
|
1161
1251
|
this.registry,
|
|
@@ -1166,8 +1256,7 @@ ${JSON.stringify(result.metadata, null, 2)}
|
|
|
1166
1256
|
this.backendSelector,
|
|
1167
1257
|
this._childHttpUrl
|
|
1168
1258
|
);
|
|
1169
|
-
const isError = result
|
|
1170
|
-
const text = JSON.stringify(result, null, 2);
|
|
1259
|
+
const { text, isError } = formatParallelResponse(result);
|
|
1171
1260
|
return {
|
|
1172
1261
|
content: [{ type: "text", text }],
|
|
1173
1262
|
isError
|
|
@@ -1269,6 +1358,7 @@ ${JSON.stringify(result.metadata, null, 2)}
|
|
|
1269
1358
|
async start(options) {
|
|
1270
1359
|
const transportType = options?.transport ?? "stdio";
|
|
1271
1360
|
if (transportType === "stdio") {
|
|
1361
|
+
redirectToStderr();
|
|
1272
1362
|
logger.info("Starting agentic-relay MCP server (stdio transport)...");
|
|
1273
1363
|
const transport = new StdioServerTransport();
|
|
1274
1364
|
await this.server.connect(transport);
|
|
@@ -1331,7 +1421,7 @@ ${JSON.stringify(result.metadata, null, 2)}
|
|
|
1331
1421
|
});
|
|
1332
1422
|
const server = new McpServer({
|
|
1333
1423
|
name: "agentic-relay",
|
|
1334
|
-
version: "0.
|
|
1424
|
+
version: "0.9.1"
|
|
1335
1425
|
});
|
|
1336
1426
|
this.registerTools(server);
|
|
1337
1427
|
transport.onclose = () => {
|
|
@@ -1695,8 +1785,10 @@ var CLAUDE_NESTING_ENV_VARS = [
|
|
|
1695
1785
|
"CLAUDE_CODE_SSE_PORT",
|
|
1696
1786
|
"CLAUDE_CODE_ENTRYPOINT"
|
|
1697
1787
|
];
|
|
1698
|
-
|
|
1699
|
-
|
|
1788
|
+
function resolveClaudeSdkTimeoutMs(flagsTimeoutMs) {
|
|
1789
|
+
if (flagsTimeoutMs !== void 0 && flagsTimeoutMs > 0) {
|
|
1790
|
+
return flagsTimeoutMs;
|
|
1791
|
+
}
|
|
1700
1792
|
const envVal = process.env["RELAY_CLAUDE_TIMEOUT_MS"];
|
|
1701
1793
|
if (envVal) {
|
|
1702
1794
|
const parsed = Number(envVal);
|
|
@@ -1704,7 +1796,7 @@ function getClaudeSdkTimeoutMs() {
|
|
|
1704
1796
|
return parsed;
|
|
1705
1797
|
}
|
|
1706
1798
|
}
|
|
1707
|
-
return
|
|
1799
|
+
return void 0;
|
|
1708
1800
|
}
|
|
1709
1801
|
var ClaudeAdapter = class extends BaseAdapter {
|
|
1710
1802
|
id = "claude";
|
|
@@ -1743,9 +1835,9 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
1743
1835
|
}
|
|
1744
1836
|
const env = this.buildCleanEnv(flags);
|
|
1745
1837
|
const permissionMode = this.getPermissionMode();
|
|
1746
|
-
const timeoutMs =
|
|
1838
|
+
const timeoutMs = resolveClaudeSdkTimeoutMs(flags.timeoutMs);
|
|
1747
1839
|
const abortController = new AbortController();
|
|
1748
|
-
const timer = setTimeout(() => abortController.abort(), timeoutMs);
|
|
1840
|
+
const timer = timeoutMs !== void 0 ? setTimeout(() => abortController.abort(), timeoutMs) : void 0;
|
|
1749
1841
|
try {
|
|
1750
1842
|
const { query } = await loadClaudeSDK();
|
|
1751
1843
|
const options = {
|
|
@@ -1770,7 +1862,16 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
1770
1862
|
let sessionId = "";
|
|
1771
1863
|
let isError = false;
|
|
1772
1864
|
let errorMessages = [];
|
|
1865
|
+
let totalInputTokens = 0;
|
|
1866
|
+
let totalOutputTokens = 0;
|
|
1773
1867
|
for await (const message of q) {
|
|
1868
|
+
if (message.type === "assistant") {
|
|
1869
|
+
const betaMessage = message.message;
|
|
1870
|
+
if (betaMessage?.usage) {
|
|
1871
|
+
totalInputTokens += betaMessage.usage.input_tokens ?? 0;
|
|
1872
|
+
totalOutputTokens += betaMessage.usage.output_tokens ?? 0;
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1774
1875
|
if (message.type === "result") {
|
|
1775
1876
|
sessionId = message.session_id;
|
|
1776
1877
|
if (message.subtype === "success") {
|
|
@@ -1782,11 +1883,13 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
1782
1883
|
}
|
|
1783
1884
|
}
|
|
1784
1885
|
logger.debug(`Claude SDK session: ${sessionId}`);
|
|
1886
|
+
const hasTokenUsage = totalInputTokens > 0 || totalOutputTokens > 0;
|
|
1785
1887
|
return {
|
|
1786
1888
|
exitCode: isError ? 1 : 0,
|
|
1787
1889
|
stdout: resultText,
|
|
1788
1890
|
stderr: errorMessages.join("\n"),
|
|
1789
|
-
...sessionId ? { nativeSessionId: sessionId } : {}
|
|
1891
|
+
...sessionId ? { nativeSessionId: sessionId } : {},
|
|
1892
|
+
...hasTokenUsage ? { tokenUsage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens } } : {}
|
|
1790
1893
|
};
|
|
1791
1894
|
} catch (error) {
|
|
1792
1895
|
if (abortController.signal.aborted) {
|
|
@@ -1802,7 +1905,7 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
1802
1905
|
stderr: error instanceof Error ? error.message : String(error)
|
|
1803
1906
|
};
|
|
1804
1907
|
} finally {
|
|
1805
|
-
clearTimeout(timer);
|
|
1908
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
1806
1909
|
}
|
|
1807
1910
|
}
|
|
1808
1911
|
async *executeStreaming(flags) {
|
|
@@ -1811,9 +1914,9 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
1811
1914
|
}
|
|
1812
1915
|
const env = this.buildCleanEnv(flags);
|
|
1813
1916
|
const permissionMode = this.getPermissionMode();
|
|
1814
|
-
const timeoutMs =
|
|
1917
|
+
const timeoutMs = resolveClaudeSdkTimeoutMs(flags.timeoutMs);
|
|
1815
1918
|
const abortController = new AbortController();
|
|
1816
|
-
const timer = setTimeout(() => abortController.abort(), timeoutMs);
|
|
1919
|
+
const timer = timeoutMs !== void 0 ? setTimeout(() => abortController.abort(), timeoutMs) : void 0;
|
|
1817
1920
|
try {
|
|
1818
1921
|
const { query } = await loadClaudeSDK();
|
|
1819
1922
|
const options = {
|
|
@@ -1888,13 +1991,13 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
1888
1991
|
result: { exitCode: 1, stdout: "", stderr: errorMessage }
|
|
1889
1992
|
};
|
|
1890
1993
|
} finally {
|
|
1891
|
-
clearTimeout(timer);
|
|
1994
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
1892
1995
|
}
|
|
1893
1996
|
}
|
|
1894
1997
|
async continueSession(nativeSessionId, prompt) {
|
|
1895
|
-
const timeoutMs =
|
|
1998
|
+
const timeoutMs = resolveClaudeSdkTimeoutMs();
|
|
1896
1999
|
const abortController = new AbortController();
|
|
1897
|
-
const timer = setTimeout(() => abortController.abort(), timeoutMs);
|
|
2000
|
+
const timer = timeoutMs !== void 0 ? setTimeout(() => abortController.abort(), timeoutMs) : void 0;
|
|
1898
2001
|
try {
|
|
1899
2002
|
const { query } = await loadClaudeSDK();
|
|
1900
2003
|
const permissionMode = this.getPermissionMode();
|
|
@@ -1940,7 +2043,7 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
1940
2043
|
stderr: error instanceof Error ? error.message : String(error)
|
|
1941
2044
|
};
|
|
1942
2045
|
} finally {
|
|
1943
|
-
clearTimeout(timer);
|
|
2046
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
1944
2047
|
}
|
|
1945
2048
|
}
|
|
1946
2049
|
async resumeSession(sessionId, flags) {
|
|
@@ -4266,7 +4369,7 @@ function createVersionCommand(registry2) {
|
|
|
4266
4369
|
description: "Show relay and backend versions"
|
|
4267
4370
|
},
|
|
4268
4371
|
async run() {
|
|
4269
|
-
const relayVersion = "0.
|
|
4372
|
+
const relayVersion = "0.9.1";
|
|
4270
4373
|
console.log(`agentic-relay v${relayVersion}`);
|
|
4271
4374
|
console.log("");
|
|
4272
4375
|
console.log("Backends:");
|
|
@@ -4616,7 +4719,7 @@ void configManager.getConfig().then((config) => {
|
|
|
4616
4719
|
var main = defineCommand10({
|
|
4617
4720
|
meta: {
|
|
4618
4721
|
name: "relay",
|
|
4619
|
-
version: "0.
|
|
4722
|
+
version: "0.9.1",
|
|
4620
4723
|
description: "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI"
|
|
4621
4724
|
},
|
|
4622
4725
|
subCommands: {
|
package/package.json
CHANGED