agent-relay-server 0.34.0 → 0.35.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/package.json +1 -1
  2. package/src/mcp.ts +13 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay-server",
3
- "version": "0.34.0",
3
+ "version": "0.35.0",
4
4
  "description": "Lightweight HTTP message relay for inter-agent communication across machines",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",
package/src/mcp.ts CHANGED
@@ -46,11 +46,11 @@ import {
46
46
  isComponentAuthorizedFor,
47
47
  isIntegrationAllowed,
48
48
  } from "./security";
49
- import type { ActivityKind, AgentCard, ArtifactKind, ArtifactSensitivity, AttachmentRef, Command, SendMessageInput, Message, SpawnApprovalMode, SpawnProvider, WorkspaceMergeStrategy, WorkspaceRecord } from "./types";
49
+ import type { ActivityKind, AgentCard, ArtifactKind, ArtifactSensitivity, AttachmentRef, Command, SendMessageInput, Message, SpawnApprovalMode, SpawnProvider, WorkspaceMergeStrategy, WorkspaceMode, WorkspaceRecord } from "./types";
50
50
  import { LAND_STRATEGIES, applyWorkspaceAction, waitForWorkspaceStatus, type WorkspaceAction } from "./workspace-actions";
51
51
  import { describeWorkspacePhase, landReceipt, readyContract, worktreeMcpInstructions } from "./workspace-phase";
52
52
  import { type ProviderEffort } from "agent-relay-sdk/provider-catalog";
53
- import { errMessage, isRecord, SPAWN_PROVIDERS, APPROVAL_MODES, VALID_EFFORTS } from "agent-relay-sdk";
53
+ import { errMessage, isRecord, SPAWN_PROVIDERS, APPROVAL_MODES, VALID_EFFORTS, VALID_WORKSPACE_MODES } from "agent-relay-sdk";
54
54
  import { runnerRuntimeTokenEnv } from "./runtime-tokens";
55
55
 
56
56
  type JsonRpcId = string | number | null;
@@ -270,6 +270,7 @@ const TOOLS: ToolDefinition[] = [
270
270
  providerArgs: { type: "array", items: { type: "string" } },
271
271
  policyName: { type: "string" },
272
272
  spawnRequestId: { type: "string" },
273
+ workspaceMode: { type: "string", enum: VALID_WORKSPACE_MODES, description: "Git workspace for the worker. `isolated` = its own worktree on an `agent/session-*` branch off main that auto-lands when ready (delegate a unit of work, get a branch worker). `shared` = edits your live checkout (a sidecar). `inherit` = let the orchestrator decide. DEFAULT for agent-initiated spawns is `isolated` so a delegated worker lands to main instead of editing your tree; pass `shared`/`inherit` to override." },
273
274
  waitForRegistrationMs: { type: "integer", minimum: 0, maximum: 30000, description: "How long to wait for the spawned agent to register before returning, so the response carries its resolved agent id (default 8000; 0 = return immediately with just spawnRequestId)." },
274
275
  },
275
276
  required: ["provider"],
@@ -804,6 +805,11 @@ async function relaySpawnAgent(auth: McpAuthContext, args: Record<string, unknow
804
805
  const label = optionalString(args.label, "label", 120);
805
806
  const policyName = optionalString(args.policyName, "policyName", 120);
806
807
  const profile = optionalString(args.profile, "profile", 120);
808
+ // #324 — expose the workspace knob on the MCP spawn surface (payload home always supported it; the
809
+ // handler just never passed it → orchestrator fell back to `inherit`→`shared`, so a worker edited the
810
+ // CALLER's live tree). Agent-initiated spawns (real caller behind the token) default to `isolated` (a
811
+ // branch worker that auto-lands); non-agent callers (admin/server) keep `inherit`. Explicit wins.
812
+ const workspaceMode = (optionalEnum(args.workspaceMode, "workspaceMode", VALID_WORKSPACE_MODES) as WorkspaceMode | undefined) ?? (callerId ? "isolated" : undefined);
807
813
 
808
814
  // #221 runtime gate (belt; the coarse `command:spawn` scope is enforced in callTool, and is
809
815
  // granted only to agents whose profile sets maxSpawnedAgents>0 and never to children).
@@ -820,10 +826,10 @@ async function relaySpawnAgent(auth: McpAuthContext, args: Record<string, unknow
820
826
  }
821
827
  }
822
828
 
823
- assertComponentResourceAllowed(auth, {
824
- scope: "agent:write",
825
- resource: { orchestratorId: orchestrator.id, cwd: resolvedCwd, policyName, spawnRequestId },
826
- });
829
+ // #323 — gate child spawn only on `orchestrators` (the parent's legit bound), NOT its self-scoping
830
+ // spawnRequestIds/cwdPrefixes/policies: those describe the child, not parent-owned resources, so
831
+ // gating on them makes maxSpawnedAgents unreachable for every component token (cwd checked above).
832
+ assertComponentResourceAllowed(auth, { scope: "agent:write", resource: { orchestratorId: orchestrator.id } });
827
833
 
828
834
  // Child runner token: a normal long-living agent that is NOT itself spawn-capable
829
835
  // (canSpawn:false → no grandchildren), stamped with authoritative lineage so it registers
@@ -848,6 +854,7 @@ async function relaySpawnAgent(auth: McpAuthContext, args: Record<string, unknow
848
854
  provider,
849
855
  modelParams: selection,
850
856
  cwd: resolvedCwd,
857
+ ...(workspaceMode ? { workspaceMode } : {}),
851
858
  label,
852
859
  profile: profile || undefined,
853
860
  tags: optionalStringArray(args.tags, "tags") ?? [],