@rk0429/agentic-relay 1.4.2 → 1.6.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 +57 -41
  2. package/package.json +1 -1
package/dist/relay.mjs CHANGED
@@ -104,7 +104,7 @@ function validateMetadataValue(value, path2, depth) {
104
104
  }
105
105
  function validateMetadata(raw) {
106
106
  if (raw === void 0 || raw === null) {
107
- return {};
107
+ return { taskId: "TASK-000" };
108
108
  }
109
109
  if (!isPlainObject(raw)) {
110
110
  throw new Error("metadata must be a plain object");
@@ -127,10 +127,13 @@ function validateMetadata(raw) {
127
127
  validateMetadataValue(value, key, 1);
128
128
  }
129
129
  const typed = raw;
130
- if (typed.taskId !== void 0 && typeof typed.taskId !== "string") {
130
+ if (typed.taskId === void 0) {
131
+ typed.taskId = "TASK-000";
132
+ }
133
+ if (typeof typed.taskId !== "string") {
131
134
  throw new Error("metadata.taskId must be a string");
132
135
  }
133
- if (typed.taskId !== void 0 && typeof typed.taskId === "string" && !TASK_ID_PATTERN.test(typed.taskId)) {
136
+ if (!TASK_ID_PATTERN.test(typed.taskId)) {
134
137
  throw new Error("metadata.taskId must match ^(TASK|GOAL)-\\d{3,}$");
135
138
  }
136
139
  if (typed.agentType !== void 0 && typeof typed.agentType !== "string") {
@@ -1012,6 +1015,13 @@ function buildChildMcpServers(parentMcpServers, childHttpUrl) {
1012
1015
  return result;
1013
1016
  }
1014
1017
  function resolveValidatedSessionMetadata(input) {
1018
+ if (input.metadata === void 0 || input.metadata === null) {
1019
+ throw new Error("metadata is required");
1020
+ }
1021
+ const rawTaskId = input.metadata.taskId;
1022
+ if (typeof rawTaskId !== "string" || rawTaskId.trim().length === 0) {
1023
+ throw new Error("metadata.taskId is required");
1024
+ }
1015
1025
  const validated = validateMetadata(input.metadata);
1016
1026
  const mergedMetadata = { ...validated };
1017
1027
  if (mergedMetadata.agentType === void 0 && input.agent !== void 0) {
@@ -1076,16 +1086,12 @@ async function executeSpawnAgent(input, registry2, sessionManager2, guard, hooks
1076
1086
  const availableBackends = registry2.listIds();
1077
1087
  const selectionContext = {
1078
1088
  availableBackends,
1079
- preferredBackend: input.preferredBackend,
1080
1089
  agentType: input.agent,
1081
1090
  taskType: input.taskType
1082
1091
  };
1083
1092
  const selectionResult = backendSelector.selectBackendWithReason(selectionContext);
1084
1093
  effectiveBackend = selectionResult.backend;
1085
1094
  selectionReason = selectionResult.reason;
1086
- } else if (input.fallbackBackend) {
1087
- effectiveBackend = input.fallbackBackend;
1088
- selectionReason = "fallbackBackend";
1089
1095
  } else {
1090
1096
  effectiveBackend = "claude";
1091
1097
  selectionReason = "default(no-selector)";
@@ -1227,6 +1233,24 @@ ${skillText}
1227
1233
 
1228
1234
  ${wrapped}` : wrapped;
1229
1235
  }
1236
+ } else {
1237
+ const autoSkillPaths = [
1238
+ `.agents/skills/${input.agent}`,
1239
+ `.claude/skills/${input.agent}`
1240
+ ];
1241
+ for (const skillPath of autoSkillPaths) {
1242
+ const skillText = readSkillContext({ skillPath });
1243
+ if (!skillText) {
1244
+ continue;
1245
+ }
1246
+ const wrapped = `<skill-context path="${skillPath}">
1247
+ ${skillText}
1248
+ </skill-context>`;
1249
+ enhancedSystemPrompt = enhancedSystemPrompt ? `${enhancedSystemPrompt}
1250
+
1251
+ ${wrapped}` : wrapped;
1252
+ break;
1253
+ }
1230
1254
  }
1231
1255
  if (input.agentDefinition) {
1232
1256
  const defText = readAgentDefinition(input.agentDefinition.definitionPath);
@@ -1236,6 +1260,17 @@ ${defText}
1236
1260
  </agent-definition>`;
1237
1261
  enhancedSystemPrompt = enhancedSystemPrompt ? `${enhancedSystemPrompt}
1238
1262
 
1263
+ ${wrapped}` : wrapped;
1264
+ }
1265
+ } else {
1266
+ const autoDefinitionPath = `.agents/agents/${input.agent}.md`;
1267
+ const defText = readAgentDefinition(autoDefinitionPath);
1268
+ if (defText) {
1269
+ const wrapped = `<agent-definition source="${autoDefinitionPath}">
1270
+ ${defText}
1271
+ </agent-definition>`;
1272
+ enhancedSystemPrompt = enhancedSystemPrompt ? `${enhancedSystemPrompt}
1273
+
1239
1274
  ${wrapped}` : wrapped;
1240
1275
  }
1241
1276
  }
@@ -1395,7 +1430,6 @@ ${input.prompt}`;
1395
1430
  const metadata = {
1396
1431
  durationMs: new Date(completedAt).getTime() - new Date(spawnStartedAt).getTime(),
1397
1432
  selectedBackend: effectiveBackend,
1398
- ...input.preferredBackend ? { requestedBackend: input.preferredBackend } : {},
1399
1433
  selectionReason,
1400
1434
  startedAt: spawnStartedAt,
1401
1435
  completedAt,
@@ -1634,13 +1668,10 @@ var init_spawn_agent = __esm({
1634
1668
  init_logger();
1635
1669
  init_metadata_validation();
1636
1670
  spawnAgentInputSchema = z2.object({
1637
- fallbackBackend: z2.enum(["claude", "codex", "gemini"]).optional().describe(
1638
- "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)."
1639
- ),
1640
1671
  prompt: z2.string().describe(
1641
1672
  "The task instruction for the sub-agent. Be specific and include all necessary context for autonomous execution."
1642
1673
  ),
1643
- agent: z2.string().optional().describe(
1674
+ agent: z2.string().describe(
1644
1675
  "Agent type identifier (e.g., 'coder', 'researcher', 'documenter', 'software-engineer'). Affects backend auto-selection: coder/researcher/software-engineer/devops-engineer\u2192codex, documenter\u2192claude. Also used to resolve agentDefinition files from .agents/agents/<agent>.md."
1645
1676
  ),
1646
1677
  systemPrompt: z2.string().optional().describe(
@@ -1659,23 +1690,20 @@ var init_spawn_agent = __esm({
1659
1690
  agentDefinition: z2.object({
1660
1691
  definitionPath: z2.string().describe("Path to the agent definition .md file (e.g., '.agents/agents/coder.md')")
1661
1692
  }).optional().describe("Agent definition file to inject into the sub-agent's system prompt as <agent-definition> context."),
1662
- preferredBackend: z2.enum(["claude", "codex", "gemini"]).optional().describe(
1663
- "Preferred backend override. Takes highest priority in backend selection. Use when the automatic agentType/taskType mapping does not match your needs."
1664
- ),
1665
1693
  taskType: z2.enum(["code-writing", "code-review", "document-writing", "document-review", "research", "mixed"]).optional().describe(
1666
- "Task type hint for automatic backend selection (priority 3, after preferredBackend and agentType). Mapping: code-writing\u2192codex, code-review\u2192claude, document-writing\u2192claude, document-review\u2192codex, research\u2192codex, mixed\u2192claude."
1694
+ "Task type hint for automatic backend selection (priority 2, after agentType). Mapping: code-writing\u2192codex, code-review\u2192claude, document-writing\u2192claude, document-review\u2192codex, research\u2192codex, mixed\u2192claude."
1667
1695
  ),
1668
1696
  taskInstructionPath: z2.string().optional().describe(
1669
1697
  "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."
1670
1698
  ),
1671
1699
  label: z2.string().optional().describe("Human-readable label for identifying this agent in parallel results and logs."),
1672
1700
  metadata: z2.object({
1673
- taskId: z2.string().regex(TASK_ID_PATTERN).optional(),
1701
+ taskId: z2.string().regex(TASK_ID_PATTERN),
1674
1702
  agentType: z2.string().optional(),
1675
1703
  label: z2.string().optional(),
1676
1704
  parentTaskId: z2.string().optional(),
1677
1705
  tags: z2.array(z2.string()).optional()
1678
- }).catchall(z2.unknown()).optional().describe("Session metadata for task linkage and orchestration context.")
1706
+ }).catchall(z2.unknown()).describe("Session metadata for task linkage and orchestration context.")
1679
1707
  });
1680
1708
  }
1681
1709
  });
@@ -2129,13 +2157,10 @@ var init_backend_selector = __esm({
2129
2157
  return this.selectBackendWithReason(context).backend;
2130
2158
  }
2131
2159
  selectBackendWithReason(context) {
2132
- const { availableBackends, preferredBackend, agentType, taskType } = context;
2160
+ const { availableBackends, agentType, taskType } = context;
2133
2161
  if (availableBackends.length === 0) {
2134
2162
  throw new Error("No backends available");
2135
2163
  }
2136
- if (preferredBackend && availableBackends.includes(preferredBackend)) {
2137
- return { backend: preferredBackend, reason: "preferredBackend" };
2138
- }
2139
2164
  if (agentType) {
2140
2165
  const mapped = this.agentToBackendMap[agentType];
2141
2166
  if (mapped && availableBackends.includes(mapped)) {
@@ -2420,7 +2445,7 @@ var init_server = __esm({
2420
2445
  this.agentEventStore
2421
2446
  );
2422
2447
  this.server = new McpServer(
2423
- { name: "agentic-relay", version: "1.4.2" },
2448
+ { name: "agentic-relay", version: "1.6.0" },
2424
2449
  createMcpServerOptions()
2425
2450
  );
2426
2451
  this.registerTools(this.server);
@@ -2558,7 +2583,7 @@ var init_server = __esm({
2558
2583
  server.experimental.tasks.registerToolTask(
2559
2584
  "spawn_agent",
2560
2585
  {
2561
- description: "Spawn a sub-agent on a backend CLI (Claude Code, Codex CLI, or Gemini CLI). The agent executes the given prompt in non-interactive mode and returns the result. Backend is auto-selected by priority: preferredBackend > agentType mapping (coder/researcher\u2192codex, documenter\u2192claude) > taskType mapping > default (claude). Use 'agentDefinition' to inject an agent .md file, 'skillContext' for a SKILL.md, or 'systemPrompt' for custom instructions.",
2586
+ description: "Spawn a sub-agent on a backend CLI (Claude Code, Codex CLI, or Gemini CLI). The agent executes the given prompt in non-interactive mode and returns the result. Backend is auto-selected by priority: agentType mapping (coder/researcher\u2192codex, documenter\u2192claude) > taskType mapping > default (claude). metadata with metadata.taskId is required for task-first delegation. Use 'agentDefinition' to inject an agent .md file, 'skillContext' for a SKILL.md, or 'systemPrompt' for custom instructions.",
2562
2587
  inputSchema: spawnAgentInputSchema.shape,
2563
2588
  execution: { taskSupport: "optional" }
2564
2589
  },
@@ -2614,20 +2639,11 @@ var init_server = __esm({
2614
2639
  failedResults: z7.array(z7.object({
2615
2640
  index: z7.number(),
2616
2641
  originalInput: spawnAgentInputSchema
2617
- })).min(1).describe("Array of failed results with their original input configurations"),
2618
- overrides: z7.object({
2619
- preferredBackend: z7.enum(["claude", "codex", "gemini"]).optional()
2620
- }).optional().describe("Parameter overrides applied to all retried agents")
2642
+ })).min(1).describe("Array of failed results with their original input configurations")
2621
2643
  },
2622
2644
  async (params) => {
2623
2645
  try {
2624
- const agents = params.failedResults.map((r) => {
2625
- const input = { ...r.originalInput };
2626
- if (params.overrides) {
2627
- if (params.overrides.preferredBackend !== void 0) input.preferredBackend = params.overrides.preferredBackend;
2628
- }
2629
- return input;
2630
- });
2646
+ const agents = params.failedResults.map((r) => ({ ...r.originalInput }));
2631
2647
  const result = await executeSpawnAgentsParallel(
2632
2648
  agents,
2633
2649
  this.registry,
@@ -2908,7 +2924,7 @@ var init_server = __esm({
2908
2924
  sessionIdGenerator: () => randomUUID()
2909
2925
  });
2910
2926
  const server = new McpServer(
2911
- { name: "agentic-relay", version: "1.4.2" },
2927
+ { name: "agentic-relay", version: "1.6.0" },
2912
2928
  createMcpServerOptions()
2913
2929
  );
2914
2930
  this.registerTools(server);
@@ -5591,7 +5607,7 @@ function fromSessionData(data) {
5591
5607
  updatedAt,
5592
5608
  lastHeartbeatAt: Number.isNaN(lastHeartbeatAt.getTime()) ? updatedAt : lastHeartbeatAt,
5593
5609
  staleNotifiedAt: staleNotifiedAt && !Number.isNaN(staleNotifiedAt.getTime()) ? staleNotifiedAt : null,
5594
- metadata: data.metadata && typeof data.metadata === "object" ? data.metadata : {}
5610
+ metadata: data.metadata && typeof data.metadata === "object" ? data.metadata : { taskId: "TASK-000" }
5595
5611
  };
5596
5612
  }
5597
5613
  var SessionManager = class _SessionManager {
@@ -6660,7 +6676,7 @@ var ContextMonitor = class {
6660
6676
  sessionId,
6661
6677
  backendId,
6662
6678
  parentSessionId: void 0,
6663
- metadata: sessionMetadata ?? {},
6679
+ metadata: sessionMetadata ?? { taskId: "TASK-000" },
6664
6680
  data: {
6665
6681
  usagePercent,
6666
6682
  currentTokens,
@@ -7347,7 +7363,7 @@ function createMCPCommand(configManager2, registry2, sessionManager2, hooksEngin
7347
7363
  responseOutputDir,
7348
7364
  relayConfig
7349
7365
  );
7350
- await server.start({ transport, port, currentVersion: "1.4.2" });
7366
+ await server.start({ transport, port, currentVersion: "1.6.0" });
7351
7367
  }
7352
7368
  })
7353
7369
  },
@@ -7507,7 +7523,7 @@ function createVersionCommand(registry2) {
7507
7523
  description: "Show relay and backend versions"
7508
7524
  },
7509
7525
  async run() {
7510
- const relayVersion = "1.4.2";
7526
+ const relayVersion = "1.6.0";
7511
7527
  console.log(`agentic-relay v${relayVersion}`);
7512
7528
  console.log("");
7513
7529
  console.log("Backends:");
@@ -7904,7 +7920,7 @@ var subCommandNames = /* @__PURE__ */ new Set(["claude", "codex", "gemini", "upd
7904
7920
  var main = defineCommand11({
7905
7921
  meta: {
7906
7922
  name: "relay",
7907
- version: "1.4.2",
7923
+ version: "1.6.0",
7908
7924
  description: "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI"
7909
7925
  },
7910
7926
  args: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rk0429/agentic-relay",
3
- "version": "1.4.2",
3
+ "version": "1.6.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",