@rk0429/agentic-relay 0.16.3 → 1.1.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 +53 -156
  2. package/package.json +1 -1
package/dist/relay.mjs CHANGED
@@ -817,13 +817,7 @@ var init_spawn_agent = __esm({
817
817
  taskInstructionPath: z2.string().optional().describe(
818
818
  "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."
819
819
  ),
820
- label: z2.string().optional().describe("Human-readable label for identifying this agent in parallel results and logs."),
821
- maxResponseLength: z2.number().int().positive().optional().describe(
822
- "Maximum response length in characters. When exceeded, response is truncated or summarized based on responseMode."
823
- ),
824
- responseMode: z2.enum(["truncate", "summarize"]).optional().describe(
825
- "How to handle responses exceeding maxResponseLength. 'truncate' (default) cuts at limit with file save. 'summarize' uses AI to condense."
826
- )
820
+ label: z2.string().optional().describe("Human-readable label for identifying this agent in parallel results and logs.")
827
821
  });
828
822
  }
829
823
  });
@@ -1213,83 +1207,23 @@ var init_types = __esm({
1213
1207
  }
1214
1208
  });
1215
1209
 
1216
- // src/mcp-server/response-summarizer.ts
1217
- async function loadClaudeSDK2() {
1218
- return await import("@anthropic-ai/claude-agent-sdk");
1219
- }
1220
- function buildCleanEnv() {
1221
- const env = {};
1222
- for (const [key, value] of Object.entries(process.env)) {
1223
- if (value !== void 0 && !CLAUDE_NESTING_ENV_VARS2.includes(key)) {
1224
- env[key] = value;
1225
- }
1226
- }
1227
- return env;
1228
- }
1229
- async function summarizeResponse(text, targetLength) {
1230
- const { query } = await loadClaudeSDK2();
1231
- const prompt = `Summarize the following text in ${targetLength} characters or less. Prioritize:
1232
- 1. Key deliverables, artifacts, and file changes
1233
- 2. Important decisions and conclusions
1234
- 3. Action items and next steps
1235
-
1236
- Preserve technical details (file paths, function names, error messages) when possible.
1237
-
1238
- <text>
1239
- ${text}
1240
- </text>`;
1241
- const q = query({
1242
- prompt,
1243
- options: {
1244
- model: "haiku",
1245
- maxTurns: 1,
1246
- env: buildCleanEnv(),
1247
- cwd: process.cwd(),
1248
- permissionMode: "bypassPermissions",
1249
- allowDangerouslySkipPermissions: true
1250
- }
1251
- });
1252
- let resultText = "";
1253
- for await (const message of q) {
1254
- if (message.type === "result") {
1255
- if (message.subtype === "success") {
1256
- resultText = message.result;
1257
- } else {
1258
- const errors = message.errors;
1259
- throw new Error(`Summarization failed: ${errors?.join("; ") ?? "unknown error"}`);
1260
- }
1261
- }
1262
- }
1263
- if (!resultText) {
1264
- throw new Error("No result from summarization");
1265
- }
1266
- return resultText;
1267
- }
1268
- var CLAUDE_NESTING_ENV_VARS2;
1269
- var init_response_summarizer = __esm({
1270
- "src/mcp-server/response-summarizer.ts"() {
1271
- "use strict";
1272
- CLAUDE_NESTING_ENV_VARS2 = [
1273
- "CLAUDECODE",
1274
- "CLAUDE_CODE_SSE_PORT",
1275
- "CLAUDE_CODE_ENTRYPOINT"
1276
- ];
1277
- }
1278
- });
1279
-
1280
1210
  // src/mcp-server/response-formatter.ts
1281
1211
  import * as fs from "fs";
1282
1212
  import * as path from "path";
1283
- import * as os from "os";
1284
- function saveFullResponse(content, sessionId) {
1213
+ function resolveResponseDir(dir) {
1214
+ const target = dir ?? DEFAULT_RESPONSE_OUTPUT_DIR;
1215
+ return path.isAbsolute(target) ? target : path.resolve(process.cwd(), target);
1216
+ }
1217
+ function saveFullResponse(content, sessionId, responseOutputDir) {
1285
1218
  try {
1286
- const dir = sessionId ? path.join(RESPONSE_DIR, sessionId) : path.join(RESPONSE_DIR, `anonymous-${Date.now()}`);
1219
+ const baseDir = resolveResponseDir(responseOutputDir);
1220
+ const dir = sessionId ? path.join(baseDir, sessionId) : path.join(baseDir, `anonymous-${Date.now()}`);
1287
1221
  fs.mkdirSync(dir, { recursive: true });
1288
1222
  const filePath = path.join(dir, "response.txt");
1289
1223
  fs.writeFileSync(filePath, content, "utf-8");
1290
1224
  try {
1291
- const entries = fs.readdirSync(RESPONSE_DIR).map((name) => {
1292
- const fullPath = path.join(RESPONSE_DIR, name);
1225
+ const entries = fs.readdirSync(baseDir).map((name) => {
1226
+ const fullPath = path.join(baseDir, name);
1293
1227
  try {
1294
1228
  const stat = fs.statSync(fullPath);
1295
1229
  return { name, fullPath, mtimeMs: stat.mtimeMs };
@@ -1311,28 +1245,17 @@ function saveFullResponse(content, sessionId) {
1311
1245
  }
1312
1246
  }
1313
1247
  async function processStdout(stdout, options) {
1314
- const maxLength = options?.maxLength ?? STDOUT_DEFAULT_MAX_LENGTH;
1315
- const mode = options?.mode ?? "truncate";
1316
- if (stdout.length <= maxLength) {
1248
+ const inlineSummaryLength = options?.inlineSummaryLength ?? DEFAULT_INLINE_SUMMARY_LENGTH;
1249
+ if (stdout.length <= inlineSummaryLength) {
1317
1250
  return { text: stdout, truncated: false };
1318
1251
  }
1319
- const savedFilePath = saveFullResponse(stdout, options?.sessionId);
1320
- const savedInfo = savedFilePath ? ` Full response saved to: ${savedFilePath}` : "";
1321
- if (mode === "summarize") {
1322
- try {
1323
- const summary = await summarizeResponse(stdout, maxLength);
1324
- const footer2 = `
1252
+ const savedFilePath = saveFullResponse(stdout, options?.sessionId, options?.responseOutputDir);
1253
+ const summary = stdout.slice(0, inlineSummaryLength);
1254
+ const fileRef = savedFilePath ?? "(file save failed)";
1255
+ const footer = `...
1325
1256
 
1326
- [RESPONSE SUMMARIZED: original ${stdout.length} chars exceeded limit ${maxLength} chars.${savedInfo}]`;
1327
- return { text: summary + footer2, truncated: true, savedFilePath };
1328
- } catch {
1329
- }
1330
- }
1331
- const truncated = stdout.slice(0, maxLength);
1332
- const footer = `
1333
-
1334
- [RESPONSE TRUNCATED: original ${stdout.length} chars exceeded limit ${maxLength} chars.${savedInfo}]`;
1335
- return { text: truncated + footer, truncated: true, savedFilePath };
1257
+ [FULL RESPONSE: ${stdout.length} chars \u2192 ${fileRef}]`;
1258
+ return { text: summary + footer, truncated: true, savedFilePath };
1336
1259
  }
1337
1260
  function truncateStderr(stderr) {
1338
1261
  if (!stderr) return stderr;
@@ -1388,7 +1311,7 @@ ${JSON.stringify(result.metadata, null, 2)}
1388
1311
  }
1389
1312
  return { text, isError };
1390
1313
  }
1391
- async function formatParallelResponse(result, options, perAgentOptions) {
1314
+ async function formatParallelResponse(result, options) {
1392
1315
  const isError = result.failureCount === result.totalCount;
1393
1316
  const parts = [];
1394
1317
  if (result.hasConflicts && result.conflicts) {
@@ -1408,7 +1331,7 @@ async function formatParallelResponse(result, options, perAgentOptions) {
1408
1331
  const duration = r.metadata?.durationMs !== void 0 ? `${(r.metadata.durationMs / 1e3).toFixed(1)}s` : "?s";
1409
1332
  if (r.exitCode === 0) {
1410
1333
  parts.push(`--- Agent ${r.index}${labelPart} (${backend}, ${duration}) SUCCESS ---`);
1411
- const agentOptions = perAgentOptions?.get(r.index) ?? options;
1334
+ const agentOptions = { ...options, sessionId: r.sessionId };
1412
1335
  const processed = await processStdout(r.stdout || "", agentOptions);
1413
1336
  parts.push(processed.text || "(no output)");
1414
1337
  } else {
@@ -1427,15 +1350,14 @@ ${JSON.stringify(sanitizedResult, null, 2)}
1427
1350
  </metadata>`);
1428
1351
  return { text: parts.join("\n"), isError };
1429
1352
  }
1430
- var STDERR_MAX_LENGTH, STDOUT_DEFAULT_MAX_LENGTH, MAX_SAVED_RESPONSES, RESPONSE_DIR;
1353
+ var STDERR_MAX_LENGTH, DEFAULT_INLINE_SUMMARY_LENGTH, MAX_SAVED_RESPONSES, DEFAULT_RESPONSE_OUTPUT_DIR;
1431
1354
  var init_response_formatter = __esm({
1432
1355
  "src/mcp-server/response-formatter.ts"() {
1433
1356
  "use strict";
1434
- init_response_summarizer();
1435
1357
  STDERR_MAX_LENGTH = 2e3;
1436
- STDOUT_DEFAULT_MAX_LENGTH = 2e4;
1358
+ DEFAULT_INLINE_SUMMARY_LENGTH = 500;
1437
1359
  MAX_SAVED_RESPONSES = 100;
1438
- RESPONSE_DIR = path.join(os.tmpdir(), "agentic-relay-responses");
1360
+ DEFAULT_RESPONSE_OUTPUT_DIR = ".relay/responses";
1439
1361
  }
1440
1362
  });
1441
1363
 
@@ -1482,16 +1404,17 @@ var init_server = __esm({
1482
1404
  };
1483
1405
  MAX_CHILD_HTTP_SESSIONS = 100;
1484
1406
  RelayMCPServer = class {
1485
- constructor(registry2, sessionManager2, guardConfig, hooksEngine2, contextMonitor2, defaultMaxResponseLength) {
1407
+ constructor(registry2, sessionManager2, guardConfig, hooksEngine2, contextMonitor2, inlineSummaryLength, responseOutputDir) {
1486
1408
  this.registry = registry2;
1487
1409
  this.sessionManager = sessionManager2;
1488
1410
  this.hooksEngine = hooksEngine2;
1489
1411
  this.contextMonitor = contextMonitor2;
1490
- this.defaultMaxResponseLength = defaultMaxResponseLength;
1412
+ this.inlineSummaryLength = inlineSummaryLength;
1413
+ this.responseOutputDir = responseOutputDir;
1491
1414
  this.guard = new RecursionGuard(guardConfig);
1492
1415
  this.backendSelector = new BackendSelector();
1493
1416
  this.server = new McpServer(
1494
- { name: "agentic-relay", version: "0.16.3" },
1417
+ { name: "agentic-relay", version: "1.1.0" },
1495
1418
  createMcpServerOptions()
1496
1419
  );
1497
1420
  this.registerTools(this.server);
@@ -1527,9 +1450,9 @@ var init_server = __esm({
1527
1450
  this._childHttpUrl
1528
1451
  );
1529
1452
  const controlOptions = {
1530
- maxLength: params.maxResponseLength ?? this.defaultMaxResponseLength ?? STDOUT_DEFAULT_MAX_LENGTH,
1531
- mode: params.responseMode ?? "truncate",
1532
- sessionId: result.sessionId
1453
+ inlineSummaryLength: this.inlineSummaryLength ?? DEFAULT_INLINE_SUMMARY_LENGTH,
1454
+ sessionId: result.sessionId,
1455
+ responseOutputDir: this.responseOutputDir
1533
1456
  };
1534
1457
  const { text, isError } = await formatSpawnAgentResponse(result, controlOptions);
1535
1458
  const callToolResult = {
@@ -1579,25 +1502,10 @@ var init_server = __esm({
1579
1502
  this._childHttpUrl
1580
1503
  );
1581
1504
  const controlOptions = {
1582
- maxLength: this.defaultMaxResponseLength ?? STDOUT_DEFAULT_MAX_LENGTH,
1583
- mode: "truncate"
1505
+ inlineSummaryLength: this.inlineSummaryLength ?? DEFAULT_INLINE_SUMMARY_LENGTH,
1506
+ responseOutputDir: this.responseOutputDir
1584
1507
  };
1585
- const perAgentOptions = /* @__PURE__ */ new Map();
1586
- for (let i = 0; i < agents.length; i++) {
1587
- const agent = agents[i];
1588
- if (agent.maxResponseLength !== void 0 || agent.responseMode !== void 0) {
1589
- perAgentOptions.set(i, {
1590
- maxLength: agent.maxResponseLength ?? controlOptions.maxLength,
1591
- mode: agent.responseMode ?? controlOptions.mode,
1592
- sessionId: result.results[i]?.sessionId
1593
- });
1594
- }
1595
- }
1596
- const { text, isError } = await formatParallelResponse(
1597
- result,
1598
- controlOptions,
1599
- perAgentOptions.size > 0 ? perAgentOptions : void 0
1600
- );
1508
+ const { text, isError } = await formatParallelResponse(result, controlOptions);
1601
1509
  const callToolResult = {
1602
1510
  content: [{ type: "text", text }],
1603
1511
  isError
@@ -1714,25 +1622,10 @@ var init_server = __esm({
1714
1622
  this._childHttpUrl
1715
1623
  );
1716
1624
  const controlOptions = {
1717
- maxLength: this.defaultMaxResponseLength ?? STDOUT_DEFAULT_MAX_LENGTH,
1718
- mode: "truncate"
1625
+ inlineSummaryLength: this.inlineSummaryLength ?? DEFAULT_INLINE_SUMMARY_LENGTH,
1626
+ responseOutputDir: this.responseOutputDir
1719
1627
  };
1720
- const perAgentOptions = /* @__PURE__ */ new Map();
1721
- for (let i = 0; i < agents.length; i++) {
1722
- const agent = agents[i];
1723
- if (agent.maxResponseLength !== void 0 || agent.responseMode !== void 0) {
1724
- perAgentOptions.set(i, {
1725
- maxLength: agent.maxResponseLength ?? controlOptions.maxLength,
1726
- mode: agent.responseMode ?? controlOptions.mode,
1727
- sessionId: result.results[i]?.sessionId
1728
- });
1729
- }
1730
- }
1731
- const { text, isError } = await formatParallelResponse(
1732
- result,
1733
- controlOptions,
1734
- perAgentOptions.size > 0 ? perAgentOptions : void 0
1735
- );
1628
+ const { text, isError } = await formatParallelResponse(result, controlOptions);
1736
1629
  return {
1737
1630
  content: [{ type: "text", text }],
1738
1631
  isError
@@ -1859,14 +1752,14 @@ var init_server = __esm({
1859
1752
  });
1860
1753
  this._httpServer = httpServer;
1861
1754
  await this.server.connect(httpTransport);
1862
- await new Promise((resolve2) => {
1755
+ await new Promise((resolve3) => {
1863
1756
  httpServer.listen(port, "127.0.0.1", () => {
1864
1757
  logger.info(`MCP server listening on http://localhost:${port}/mcp`);
1865
- resolve2();
1758
+ resolve3();
1866
1759
  });
1867
1760
  });
1868
- await new Promise((resolve2) => {
1869
- httpServer.on("close", resolve2);
1761
+ await new Promise((resolve3) => {
1762
+ httpServer.on("close", resolve3);
1870
1763
  });
1871
1764
  }
1872
1765
  /**
@@ -1896,7 +1789,7 @@ var init_server = __esm({
1896
1789
  sessionIdGenerator: () => randomUUID()
1897
1790
  });
1898
1791
  const server = new McpServer(
1899
- { name: "agentic-relay", version: "0.16.3" },
1792
+ { name: "agentic-relay", version: "1.1.0" },
1900
1793
  createMcpServerOptions()
1901
1794
  );
1902
1795
  this.registerTools(server);
@@ -1932,12 +1825,12 @@ var init_server = __esm({
1932
1825
  }
1933
1826
  });
1934
1827
  this._childHttpServer = httpServer;
1935
- await new Promise((resolve2) => {
1828
+ await new Promise((resolve3) => {
1936
1829
  httpServer.listen(0, "127.0.0.1", () => {
1937
1830
  const addr = httpServer.address();
1938
1831
  this._childHttpUrl = `http://127.0.0.1:${addr.port}/mcp`;
1939
1832
  logger.info(`Child MCP server listening on ${this._childHttpUrl}`);
1940
- resolve2();
1833
+ resolve3();
1941
1834
  });
1942
1835
  });
1943
1836
  }
@@ -3497,7 +3390,8 @@ var relayConfigSchema = z.object({
3497
3390
  maxDepth: z.number().int().positive(),
3498
3391
  maxCallsPerSession: z.number().int().positive(),
3499
3392
  timeoutSec: z.number().positive(),
3500
- maxResponseLength: z.number().int().positive().optional()
3393
+ inlineSummaryLength: z.number().int().positive().optional(),
3394
+ responseOutputDir: z.string().optional()
3501
3395
  }).optional(),
3502
3396
  telemetry: z.object({
3503
3397
  enabled: z.boolean()
@@ -4728,7 +4622,8 @@ function createMCPCommand(configManager2, registry2, sessionManager2, hooksEngin
4728
4622
  return;
4729
4623
  }
4730
4624
  let guardConfig;
4731
- let defaultMaxResponseLength;
4625
+ let inlineSummaryLength;
4626
+ let responseOutputDir;
4732
4627
  try {
4733
4628
  const config = await configManager2.getConfig();
4734
4629
  if (config.mcpServerMode) {
@@ -4737,7 +4632,8 @@ function createMCPCommand(configManager2, registry2, sessionManager2, hooksEngin
4737
4632
  maxCallsPerSession: config.mcpServerMode.maxCallsPerSession ?? 20,
4738
4633
  timeoutSec: config.mcpServerMode.timeoutSec ?? 86400
4739
4634
  };
4740
- defaultMaxResponseLength = config.mcpServerMode.maxResponseLength;
4635
+ inlineSummaryLength = config.mcpServerMode.inlineSummaryLength;
4636
+ responseOutputDir = config.mcpServerMode.responseOutputDir;
4741
4637
  }
4742
4638
  } catch {
4743
4639
  }
@@ -4749,7 +4645,8 @@ function createMCPCommand(configManager2, registry2, sessionManager2, hooksEngin
4749
4645
  guardConfig,
4750
4646
  hooksEngine2,
4751
4647
  contextMonitor2,
4752
- defaultMaxResponseLength
4648
+ inlineSummaryLength,
4649
+ responseOutputDir
4753
4650
  );
4754
4651
  await server.start({ transport, port });
4755
4652
  }
@@ -4911,7 +4808,7 @@ function createVersionCommand(registry2) {
4911
4808
  description: "Show relay and backend versions"
4912
4809
  },
4913
4810
  async run() {
4914
- const relayVersion = "0.16.3";
4811
+ const relayVersion = "1.1.0";
4915
4812
  console.log(`agentic-relay v${relayVersion}`);
4916
4813
  console.log("");
4917
4814
  console.log("Backends:");
@@ -5261,7 +5158,7 @@ void configManager.getConfig().then((config) => {
5261
5158
  var main = defineCommand10({
5262
5159
  meta: {
5263
5160
  name: "relay",
5264
- version: "0.16.3",
5161
+ version: "1.1.0",
5265
5162
  description: "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI"
5266
5163
  },
5267
5164
  subCommands: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rk0429/agentic-relay",
3
- "version": "0.16.3",
3
+ "version": "1.1.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",