@rk0429/agentic-relay 0.6.4 → 0.7.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 +146 -4
  2. package/package.json +1 -1
package/dist/relay.mjs CHANGED
@@ -542,6 +542,97 @@ var init_spawn_agent = __esm({
542
542
  }
543
543
  });
544
544
 
545
+ // src/mcp-server/tools/spawn-agents-parallel.ts
546
+ async function executeSpawnAgentsParallel(agents, registry2, sessionManager2, guard, hooksEngine2, contextMonitor2, backendSelector, childHttpUrl) {
547
+ const envContext = buildContextFromEnv();
548
+ if (envContext.depth >= guard.getConfig().maxDepth) {
549
+ const reason = `Max depth exceeded: ${envContext.depth} >= ${guard.getConfig().maxDepth}`;
550
+ logger.warn(`Batch spawn blocked by RecursionGuard: ${reason}`);
551
+ return {
552
+ results: agents.map((_, index) => ({
553
+ index,
554
+ sessionId: "",
555
+ exitCode: 1,
556
+ stdout: "",
557
+ stderr: `Batch spawn blocked: ${reason}`,
558
+ error: reason
559
+ })),
560
+ totalCount: agents.length,
561
+ successCount: 0,
562
+ failureCount: agents.length
563
+ };
564
+ }
565
+ const currentCount = guard.getCallCount(envContext.traceId);
566
+ const maxCalls = guard.getConfig().maxCallsPerSession;
567
+ if (currentCount + agents.length > maxCalls) {
568
+ const reason = `Batch would exceed max calls per session: ${currentCount} + ${agents.length} > ${maxCalls}`;
569
+ logger.warn(`Batch spawn blocked by RecursionGuard: ${reason}`);
570
+ return {
571
+ results: agents.map((_, index) => ({
572
+ index,
573
+ sessionId: "",
574
+ exitCode: 1,
575
+ stdout: "",
576
+ stderr: `Batch spawn blocked: ${reason}`,
577
+ error: reason
578
+ })),
579
+ totalCount: agents.length,
580
+ successCount: 0,
581
+ failureCount: agents.length
582
+ };
583
+ }
584
+ const settled = await Promise.allSettled(
585
+ agents.map(
586
+ (agent) => executeSpawnAgent(
587
+ agent,
588
+ registry2,
589
+ sessionManager2,
590
+ guard,
591
+ hooksEngine2,
592
+ contextMonitor2,
593
+ backendSelector,
594
+ childHttpUrl
595
+ )
596
+ )
597
+ );
598
+ const results = settled.map((outcome, index) => {
599
+ if (outcome.status === "fulfilled") {
600
+ const r = outcome.value;
601
+ return {
602
+ index,
603
+ sessionId: r.sessionId,
604
+ exitCode: r.exitCode,
605
+ stdout: r.stdout,
606
+ stderr: r.stderr,
607
+ ...r.nativeSessionId ? { nativeSessionId: r.nativeSessionId } : {}
608
+ };
609
+ }
610
+ const errorMessage = outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason);
611
+ return {
612
+ index,
613
+ sessionId: "",
614
+ exitCode: 1,
615
+ stdout: "",
616
+ stderr: errorMessage,
617
+ error: errorMessage
618
+ };
619
+ });
620
+ const successCount = results.filter((r) => r.exitCode === 0).length;
621
+ return {
622
+ results,
623
+ totalCount: agents.length,
624
+ successCount,
625
+ failureCount: agents.length - successCount
626
+ };
627
+ }
628
+ var init_spawn_agents_parallel = __esm({
629
+ "src/mcp-server/tools/spawn-agents-parallel.ts"() {
630
+ "use strict";
631
+ init_spawn_agent();
632
+ init_logger();
633
+ }
634
+ });
635
+
545
636
  // src/mcp-server/tools/list-sessions.ts
546
637
  import { z as z3 } from "zod";
547
638
  async function executeListSessions(input, sessionManager2) {
@@ -702,6 +793,7 @@ var init_server = __esm({
702
793
  "use strict";
703
794
  init_recursion_guard();
704
795
  init_spawn_agent();
796
+ init_spawn_agents_parallel();
705
797
  init_list_sessions();
706
798
  init_get_context_status();
707
799
  init_list_available_backends();
@@ -717,7 +809,7 @@ var init_server = __esm({
717
809
  this.backendSelector = new BackendSelector();
718
810
  this.server = new McpServer({
719
811
  name: "agentic-relay",
720
- version: "0.6.4"
812
+ version: "0.7.0"
721
813
  });
722
814
  this.registerTools(this.server);
723
815
  }
@@ -787,6 +879,56 @@ ${result.stdout}`;
787
879
  }
788
880
  }
789
881
  );
882
+ server.tool(
883
+ "spawn_agents_parallel",
884
+ "Spawn multiple sub-agents in parallel across available backends. Each agent entry accepts the same parameters as spawn_agent. All agents are executed concurrently via Promise.allSettled, and results are returned as an array with per-agent status. RecursionGuard batch pre-validation ensures the entire batch fits within call limits before execution begins.",
885
+ {
886
+ agents: z5.array(z5.object({
887
+ backend: z5.enum(["claude", "codex", "gemini"]),
888
+ prompt: z5.string(),
889
+ agent: z5.string().optional().describe("Named agent configuration (Claude only)"),
890
+ systemPrompt: z5.string().optional().describe("System prompt / role instructions for the sub-agent (all backends)"),
891
+ resumeSessionId: z5.string().optional(),
892
+ model: z5.string().optional(),
893
+ maxTurns: z5.number().optional(),
894
+ skillContext: z5.object({
895
+ skillPath: z5.string().describe("Path to the skill directory"),
896
+ subskill: z5.string().optional().describe("Specific subskill to activate")
897
+ }).optional().describe("Skill context to inject into the sub-agent's system prompt"),
898
+ agentDefinition: z5.object({
899
+ definitionPath: z5.string().describe("Path to the agent definition file")
900
+ }).optional().describe("Agent definition file to inject into the sub-agent's system prompt"),
901
+ preferredBackend: z5.enum(["claude", "codex", "gemini"]).optional().describe("Preferred backend override."),
902
+ taskType: z5.enum(["code", "document", "analysis", "mixed"]).optional().describe("Task type hint for automatic backend selection.")
903
+ })).min(1).max(10).describe("Array of agent configurations to execute in parallel (1-10 agents)")
904
+ },
905
+ async (params) => {
906
+ try {
907
+ const result = await executeSpawnAgentsParallel(
908
+ params.agents,
909
+ this.registry,
910
+ this.sessionManager,
911
+ this.guard,
912
+ this.hooksEngine,
913
+ this.contextMonitor,
914
+ this.backendSelector,
915
+ this._childHttpUrl
916
+ );
917
+ const isError = result.failureCount === result.totalCount;
918
+ const text = JSON.stringify(result, null, 2);
919
+ return {
920
+ content: [{ type: "text", text }],
921
+ isError
922
+ };
923
+ } catch (error) {
924
+ const message = error instanceof Error ? error.message : String(error);
925
+ return {
926
+ content: [{ type: "text", text: `Error: ${message}` }],
927
+ isError: true
928
+ };
929
+ }
930
+ }
931
+ );
790
932
  server.tool(
791
933
  "list_sessions",
792
934
  "List relay sessions, optionally filtered by backend.",
@@ -937,7 +1079,7 @@ ${result.stdout}`;
937
1079
  });
938
1080
  const server = new McpServer({
939
1081
  name: "agentic-relay",
940
- version: "0.6.4"
1082
+ version: "0.7.0"
941
1083
  });
942
1084
  this.registerTools(server);
943
1085
  transport.onclose = () => {
@@ -3919,7 +4061,7 @@ function createVersionCommand(registry2) {
3919
4061
  description: "Show relay and backend versions"
3920
4062
  },
3921
4063
  async run() {
3922
- const relayVersion = "0.6.4";
4064
+ const relayVersion = "0.7.0";
3923
4065
  console.log(`agentic-relay v${relayVersion}`);
3924
4066
  console.log("");
3925
4067
  console.log("Backends:");
@@ -4269,7 +4411,7 @@ void configManager.getConfig().then((config) => {
4269
4411
  var main = defineCommand10({
4270
4412
  meta: {
4271
4413
  name: "relay",
4272
- version: "0.6.4",
4414
+ version: "0.7.0",
4273
4415
  description: "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI"
4274
4416
  },
4275
4417
  subCommands: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rk0429/agentic-relay",
3
- "version": "0.6.4",
3
+ "version": "0.7.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",