agent-relay 3.0.1 → 3.0.2

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 (39) hide show
  1. package/README.md +32 -247
  2. package/bin/agent-relay-broker-darwin-arm64 +0 -0
  3. package/bin/agent-relay-broker-darwin-x64 +0 -0
  4. package/bin/agent-relay-broker-linux-arm64 +0 -0
  5. package/bin/agent-relay-broker-linux-x64 +0 -0
  6. package/dist/index.cjs +74 -9
  7. package/package.json +9 -8
  8. package/packages/acp-bridge/package.json +2 -2
  9. package/packages/config/package.json +1 -1
  10. package/packages/hooks/package.json +4 -4
  11. package/packages/memory/package.json +2 -2
  12. package/packages/policy/package.json +2 -2
  13. package/packages/sdk/dist/__tests__/facade.test.js +48 -0
  14. package/packages/sdk/dist/__tests__/facade.test.js.map +1 -1
  15. package/packages/sdk/dist/__tests__/integration.test.js +6 -1
  16. package/packages/sdk/dist/__tests__/integration.test.js.map +1 -1
  17. package/packages/sdk/dist/__tests__/unit.test.js +36 -0
  18. package/packages/sdk/dist/__tests__/unit.test.js.map +1 -1
  19. package/packages/sdk/dist/client.d.ts +2 -0
  20. package/packages/sdk/dist/client.d.ts.map +1 -1
  21. package/packages/sdk/dist/client.js +27 -4
  22. package/packages/sdk/dist/client.js.map +1 -1
  23. package/packages/sdk/dist/relay.d.ts +27 -0
  24. package/packages/sdk/dist/relay.d.ts.map +1 -1
  25. package/packages/sdk/dist/relay.js +61 -4
  26. package/packages/sdk/dist/relay.js.map +1 -1
  27. package/packages/sdk/package.json +2 -2
  28. package/packages/sdk/src/__tests__/facade.test.ts +68 -0
  29. package/packages/sdk/src/__tests__/integration.test.ts +6 -1
  30. package/packages/sdk/src/__tests__/unit.test.ts +44 -0
  31. package/packages/sdk/src/client.ts +30 -6
  32. package/packages/sdk/src/relay.ts +75 -4
  33. package/packages/sdk-py/pyproject.toml +2 -2
  34. package/packages/telemetry/package.json +1 -1
  35. package/packages/trajectory/package.json +2 -2
  36. package/packages/user-directory/package.json +2 -2
  37. package/packages/utils/package.json +2 -2
  38. package/scripts/postinstall.js +35 -162
  39. package/packages/sdk/bin/agent-relay-broker +0 -0
package/README.md CHANGED
@@ -1,275 +1,60 @@
1
1
  # agent-relay
2
2
 
3
- > Real-time messaging between AI agents. Sub-5ms latency, any CLI, any language.
3
+ > Real-time messaging between AI agents.
4
4
 
5
- [![npm](https://img.shields.io/npm/v/agent-relay)](https://www.npmjs.com/package/agent-relay)
5
+ [![npm](https://img.shields.io/npm/v/@agent-relay/sdk)](https://www.npmjs.com/package/@agent-relay/sdk)
6
6
  [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
7
7
 
8
8
  ---
9
9
 
10
10
  ## Install
11
11
 
12
- ```bash
13
- curl -fsSL https://raw.githubusercontent.com/AgentWorkforce/relay/main/install.sh | bash
14
- ```
15
-
16
- Or via npm (requires Node.js 18+):
17
-
18
- ```bash
19
- npm install -g agent-relay
20
- ```
21
-
22
- ## Quick Start
23
-
24
- ```bash
25
- agent-relay up --dashboard
26
- ```
27
-
28
- Open **http://localhost:3888** to spawn agents, view real-time status, and stream logs.
29
-
30
- ---
31
-
32
- ## CLI Reference
33
-
34
- | Command | Description |
35
- | --------------------------------------- | ------------------------ |
36
- | `agent-relay up` | Start broker + dashboard |
37
- | `agent-relay down` | Stop broker |
38
- | `agent-relay spawn <name> <cli> "task"` | Spawn a worker agent |
39
- | `agent-relay status` | Check broker status |
40
- | `agent-relay run workflow.yaml` | Run a YAML workflow |
41
- | `agent-relay run --template feature-dev`| Run a built-in template |
42
-
43
- ---
44
-
45
- ## Workflows
46
-
47
- Define multi-agent workflows in YAML, TypeScript, or Python. Run locally or queue to the cloud for 24/7 execution:
48
-
49
- ```bash
50
- # Run locally
51
- agent-relay run workflow.yaml --task "Add OAuth2 support"
52
-
53
- # Queue to cloud — durable, scalable, runs in sandboxes
54
- agent-relay run workflow.yaml --cloud --task "Add OAuth2 support"
55
-
56
- # Use built-in templates
57
- agent-relay run --template feature-dev --task "Add user dashboard"
58
- ```
59
-
60
- ### relay.yaml
61
-
62
- Blueprint-style workflows combine **agent steps** (LLM-powered) with **deterministic steps** (shell commands) for faster, cheaper, more reliable execution:
63
-
64
- ```yaml
65
- version: "1.0"
66
- name: ship-feature
67
-
68
- agents:
69
- - name: planner
70
- cli: claude
71
- model: opus
72
- - name: developer
73
- cli: codex
74
-
75
- workflows:
76
- - name: default
77
- preflight:
78
- - command: git status --porcelain
79
- failIf: non-empty
80
- steps:
81
- - name: plan
82
- agent: planner
83
- task: "Create implementation plan for: {{task}}"
84
- - name: create-branch
85
- type: deterministic
86
- command: git checkout -b feature/{{branch-name}}
87
- dependsOn: [plan]
88
- - name: implement
89
- agent: developer
90
- task: "Implement: {{steps.plan.output}}"
91
- dependsOn: [create-branch]
92
- - name: test
93
- type: deterministic
94
- command: npm test
95
- dependsOn: [implement]
96
- - name: commit
97
- type: deterministic
98
- command: git add -A && git commit -m "feat: {{task}}"
99
- dependsOn: [test]
100
- ```
101
-
102
- **Benefits:** Deterministic steps run instantly ($0 LLM cost), catch issues early with preflight checks, and git commands can't hallucinate.
103
-
104
- Also available as fluent builders in [TypeScript SDK](https://www.npmjs.com/package/@agent-relay/sdk) and [Python SDK](https://pypi.org/project/agent-relay/).
105
-
106
- ### Built-in Templates
107
-
108
- All templates use blueprint-style hybrid workflows with deterministic quality gates.
109
-
110
- | Template | Pattern | Description |
111
- | ---------------- | ------------ | ------------------------------------------------ |
112
- | `feature-dev` | hub-spoke | Plan, implement, review, and finalize a feature |
113
- | `bug-fix` | hub-spoke | Investigate, patch, validate, and document |
114
- | `code-review` | fan-out | Parallel multi-reviewer assessment |
115
- | `security-audit` | pipeline | Scan, triage, remediate, and verify |
116
- | `refactor` | hierarchical | Analyze, plan, execute, and validate |
117
- | `documentation` | handoff | Research, draft, review, and publish |
118
-
119
- ---
120
-
121
- ## SDK Usage
122
-
123
12
  ```bash
124
13
  npm install @agent-relay/sdk
125
14
  ```
126
15
 
127
- ### Agent-to-Agent Messaging
16
+ ## Usage
128
17
 
129
18
  ```typescript
130
- import { AgentRelay, Models } from '@agent-relay/sdk';
19
+ import { AgentRelay, Models } from "@agent-relay/sdk";
131
20
 
132
21
  const relay = new AgentRelay();
133
22
 
134
- // Spawn agents with different CLIs and models
135
- const planner = await relay.claude.spawn({
136
- name: 'Planner',
137
- model: Models.Claude.OPUS
138
- });
23
+ relay.onMessageReceived = (msg) =>
24
+ console.log(`[${msg.from} ${msg.to}]: ${msg.text}`);
25
+
26
+ const channel = ["tic-tac-toe"];
139
27
 
140
- const coder = await relay.codex.spawn({
141
- name: 'Coder',
142
- model: Models.Codex.CODEX_5_3
28
+ const x = await relay.claude.spawn({
29
+ name: "PlayerX",
30
+ model: Models.Claude.SONNET,
31
+ channels: channel,
32
+ task: "Play tic-tac-toe as X against PlayerO. You go first.",
33
+ });
34
+ const o = await relay.codex.spawn({
35
+ name: "PlayerO",
36
+ model: Models.Codex.GPT_5_3_CODEX_SPARK,
37
+ channels: channel,
38
+ task: "Play tic-tac-toe as O against PlayerX.",
143
39
  });
144
40
 
145
- // Send messages between agents
146
- await planner.sendMessage({ to: 'Coder', text: 'Implement the auth module' });
41
+ console.log("Waiting for agents to be ready...");
42
+ await Promise.all([
43
+ relay.waitForAgentReady("PlayerX"),
44
+ relay.waitForAgentReady("PlayerO"),
45
+ ]);
46
+ console.log("Both ready. Starting game.");
147
47
 
148
- // Listen for messages
149
- relay.onMessageReceived = (msg) => {
150
- console.log(`${msg.from} → ${msg.to}: ${msg.text}`);
151
- };
48
+ relay.system().sendMessage({ to: "PlayerX", text: "Start." });
152
49
 
50
+ const FIVE_MINUTES = 5 * 60 * 1000;
51
+ await AgentRelay.waitForAny([x, o], FIVE_MINUTES);
153
52
  await relay.shutdown();
154
53
  ```
155
54
 
156
- ### Multi-Agent Workflows
157
-
158
- Build workflows with different swarm patterns:
159
-
160
- ```typescript
161
- import { workflow, Models, SwarmPatterns } from '@agent-relay/sdk/workflows';
162
-
163
- // Hub-spoke: Lead coordinates workers
164
- const result = await workflow('feature-build')
165
- .pattern(SwarmPatterns.HUB_SPOKE)
166
- .agent('lead', { cli: 'claude', model: Models.Claude.OPUS, role: 'Coordinator' })
167
- .agent('dev1', { cli: 'codex', model: Models.Codex.CODEX_5_3, role: 'Developer' })
168
- .agent('dev2', { cli: 'cursor', model: Models.Cursor.CLAUDE_SONNET, role: 'Developer' })
169
- .step('plan', { agent: 'lead', task: 'Break down the feature into tasks' })
170
- .step('impl1', { agent: 'dev1', task: 'Implement backend', dependsOn: ['plan'] })
171
- .step('impl2', { agent: 'dev2', task: 'Implement frontend', dependsOn: ['plan'] })
172
- .step('review', { agent: 'lead', task: 'Review and merge', dependsOn: ['impl1', 'impl2'] })
173
- .run();
174
- ```
175
-
176
- **Swarm Patterns:**
177
-
178
- | Category | Patterns |
179
- | --------------- | ----------------------------------------------------------- |
180
- | **Core** | `dag`, `fan-out`, `pipeline`, `hub-spoke`, `consensus`, `mesh` |
181
- | **Data** | `map-reduce`, `scatter-gather` |
182
- | **Quality** | `supervisor`, `reflection`, `verifier` |
183
- | **Adversarial** | `red-team`, `auction` |
184
- | **Resilience** | `escalation`, `saga`, `circuit-breaker` |
185
-
186
- Auto-pattern selection: define agents with roles like `mapper`, `reducer`, `tier-1`, `attacker`, `defender` and the pattern is auto-selected.
187
-
188
- ---
189
-
190
- ## Cloud
191
-
192
- Scale to teams and automate with [Agent Relay Cloud](https://agent-relay.com):
193
-
194
- ```bash
195
- agent-relay cloud link # Link your machine
196
- agent-relay cloud agents # List agents across machines
197
- agent-relay cloud send AgentName "Your message"
198
- ```
199
-
200
- ### Multi-Agent Orchestration
201
-
202
- Spawn agent teams in the cloud — each agent runs in its own isolated sandbox but can communicate with teammates:
203
-
204
- - **Isolated Sandboxes**: Each agent gets a secure container with full dev environment
205
- - **Cross-Sandbox Messaging**: Agents collaborate via relay channels despite isolation
206
- - **24/7 Durable Workflows**: Queue workflows to run continuously, survive restarts
207
- - **Auto-Scaling**: Workspaces scale up/down based on agent load
208
-
209
- ```bash
210
- # Queue a workflow to run in the cloud
211
- agent-relay run workflow.yaml --cloud --task "Refactor auth module"
212
-
213
- # Workflows persist, scale, and run even when you're offline
214
- ```
215
-
216
- ### Integrations
217
-
218
- | Integration | Capabilities |
219
- | ----------- | ------------ |
220
- | **GitHub** | CI auto-fix, @mentions in PRs, issue assignment triggers |
221
- | **Linear** | Issue assignment spawns agents, status sync |
222
- | **Slack** | Chat with agents, trigger workflows from Slack commands |
223
-
224
- ### CI Auto-Fix
225
-
226
- Install the [Agent Relay GitHub App](https://github.com/apps/agent-relay):
227
-
228
- ```
229
- 1. CI fails on PR #123
230
- 2. Agent Relay: "🔴 CI Failure Detected, spawning @ci-fix agent..."
231
- 3. Agent analyzes logs, fixes issue, pushes commit
232
- 4. Agent Relay: "✅ CI Fix Applied — please re-run checks"
233
- ```
234
-
235
- ---
236
-
237
- ## Architecture
238
-
239
- Agent Relay is built from modular components that work together:
240
-
241
- ```
242
- ┌─────────────────────────────────────────────────────────────────┐
243
- │ Your Application │
244
- ├─────────────────────────────────────────────────────────────────┤
245
- │ agent-relay CLI │ @agent-relay/sdk │ relay.yaml │
246
- ├─────────────────────────────────────────────────────────────────┤
247
- │ Relay Broker │
248
- │ • Agent lifecycle • Message routing • PTY management │
249
- ├─────────────────────────────────────────────────────────────────┤
250
- │ Relaycast │
251
- │ • REST API • WebSocket events • Channels & threads │
252
- ├─────────────────────────────────────────────────────────────────┤
253
- │ Claude │ Codex │ Gemini │ Cursor │ Aider │ Goose │
254
- └─────────────────────────────────────────────────────────────────┘
255
- ```
256
-
257
- ### Components
258
-
259
- | Component | Description |
260
- | --------- | ----------- |
261
- | **Relay Broker** | Core message router with sub-5ms latency. Manages agent lifecycle, PTY sessions, and message delivery. |
262
- | **Relaycast** | Communication layer with REST API and WebSocket. Provides channels, threads, reactions, and file attachments. Framework-agnostic — works with CrewAI, LangGraph, AutoGen, or raw API calls. |
263
- | **Relay Dashboard** | Real-time monitoring UI. View agent status, stream logs, and manage workflows from the browser. |
264
- | **Relay Cloud** | Multi-tenant cloud platform with auto-scaling, billing, and webhook integrations for GitHub/Linear/Slack. |
265
- | **Trajectories** | Decision capture system. Records the "why" behind code changes — decisions, challenges, and confidence scores — as searchable institutional memory. |
266
-
267
- ### How It Works
268
-
269
- 1. **Zero modification**: Agents run unmodified CLI tools (Claude Code, Codex, etc.) in PTY sessions
270
- 2. **MCP protocol**: Agents communicate via standard MCP tools — no custom SDK required inside agents
271
- 3. **Mix AI providers**: Combine Claude, GPT, and Gemini agents in a single workflow — each using their strengths
272
- 4. **Workflow engine**: YAML workflows parsed and executed with dependency resolution, retries, and verification
55
+ ## Supported CLI’s
56
+ - Claude
57
+ - Codex
273
58
 
274
59
  ---
275
60
 
@@ -279,4 +64,4 @@ Apache-2.0 — Copyright 2026 Agent Workforce Incorporated
279
64
 
280
65
  ---
281
66
 
282
- **Links:** [Documentation](https://docs.agent-relay.com/) · [Issues](https://github.com/AgentWorkforce/relay/issues) · [Cloud](https://agent-relay.com) · [Discord](https://discord.gg/6E6CTxM8um)
67
+ **Links:** [Documentation](https://docs.agent-relay.com/) · [Issues](https://github.com/AgentWorkforce/relay/issues) · [Discord](https://discord.gg/6E6CTxM8um)
Binary file
Binary file
Binary file
Binary file
package/dist/index.cjs CHANGED
@@ -8989,6 +8989,8 @@ var AgentRelayClient = class _AgentRelayClient {
8989
8989
  eventBuffer = [];
8990
8990
  maxBufferSize = 1e3;
8991
8991
  exitPromise;
8992
+ /** The workspace key returned by the broker in its hello_ack response. */
8993
+ workspaceKey;
8992
8994
  constructor(options = {}) {
8993
8995
  this.options = {
8994
8996
  binaryPath: options.binaryPath ?? resolveDefaultBinaryPath(),
@@ -9250,8 +9252,11 @@ var AgentRelayClient = class _AgentRelayClient {
9250
9252
  resolve3();
9251
9253
  });
9252
9254
  });
9253
- await this.requestHello();
9255
+ const helloAck = await this.requestHello();
9254
9256
  console.log("[broker] Broker ready (hello handshake complete)");
9257
+ if (helloAck.workspace_key) {
9258
+ this.workspaceKey = helloAck.workspace_key;
9259
+ }
9255
9260
  }
9256
9261
  disposeProcessHandles() {
9257
9262
  this.stdoutRl?.close();
@@ -9367,12 +9372,16 @@ var AgentRelayClient = class _AgentRelayClient {
9367
9372
  }
9368
9373
  };
9369
9374
  var CLI_MODEL_FLAG_CLIS = /* @__PURE__ */ new Set(["claude", "codex", "gemini", "goose", "aider"]);
9375
+ var CLI_DEFAULT_ARGS = {
9376
+ codex: ["-c", "check_for_update_on_startup=false"]
9377
+ };
9370
9378
  function buildPtyArgsWithModel(cli, args, model) {
9371
- const baseArgs = [...args];
9379
+ const cliName = cli.split(":")[0].trim().toLowerCase();
9380
+ const defaultArgs = CLI_DEFAULT_ARGS[cliName] ?? [];
9381
+ const baseArgs = [...defaultArgs, ...args];
9372
9382
  if (!model) {
9373
9383
  return baseArgs;
9374
9384
  }
9375
- const cliName = cli.split(":")[0].trim().toLowerCase();
9376
9385
  if (!CLI_MODEL_FLAG_CLIS.has(cliName)) {
9377
9386
  return baseArgs;
9378
9387
  }
@@ -9410,7 +9419,19 @@ function resolveDefaultBinaryPath() {
9410
9419
  if (import_node_fs.default.existsSync(workspaceRelease)) {
9411
9420
  return workspaceRelease;
9412
9421
  }
9413
- const bundled = import_node_path.default.resolve(moduleDir, "..", "bin", brokerExe);
9422
+ const binDir = import_node_path.default.resolve(moduleDir, "..", "bin");
9423
+ const platformMap = {
9424
+ darwin: { arm64: "darwin-arm64", x64: "darwin-x64" },
9425
+ linux: { arm64: "linux-arm64", x64: "linux-x64" }
9426
+ };
9427
+ const suffix = platformMap[process.platform]?.[process.arch];
9428
+ if (suffix) {
9429
+ const platformBinary = import_node_path.default.join(binDir, `agent-relay-broker-${suffix}`);
9430
+ if (import_node_fs.default.existsSync(platformBinary)) {
9431
+ return platformBinary;
9432
+ }
9433
+ }
9434
+ const bundled = import_node_path.default.join(binDir, brokerExe);
9414
9435
  if (import_node_fs.default.existsSync(bundled)) {
9415
9436
  return bundled;
9416
9437
  }
@@ -15176,7 +15197,7 @@ var DefaultModels = {
15176
15197
  };
15177
15198
 
15178
15199
  // node_modules/@relaycast/sdk/dist/version.js
15179
- var SDK_VERSION = "0.4.0";
15200
+ var SDK_VERSION = "0.4.2";
15180
15201
 
15181
15202
  // node_modules/@relaycast/types/node_modules/zod/v4/classic/external.js
15182
15203
  var external_exports2 = {};
@@ -45021,12 +45042,26 @@ var AgentRelay = class {
45021
45042
  onDeliveryUpdate = null;
45022
45043
  onAgentExitRequested = null;
45023
45044
  onAgentIdle = null;
45045
+ // ── Public accessors ────────────────────────────────────────────────────
45046
+ /** The resolved Relaycast workspace API key (available after first spawn). */
45047
+ get workspaceKey() {
45048
+ return this.relayApiKey;
45049
+ }
45050
+ /** Observer URL for the auto-created workspace (available after first spawn). */
45051
+ get observerUrl() {
45052
+ if (!this.relayApiKey)
45053
+ return void 0;
45054
+ return `https://observer.relaycast.dev/?key=${this.relayApiKey}`;
45055
+ }
45024
45056
  // Shorthand spawners
45025
45057
  codex;
45026
45058
  claude;
45027
45059
  gemini;
45028
45060
  clientOptions;
45029
45061
  defaultChannels;
45062
+ workspaceName;
45063
+ relaycastBaseUrl;
45064
+ relayApiKey;
45030
45065
  client;
45031
45066
  startPromise;
45032
45067
  unsubEvent;
@@ -45043,6 +45078,8 @@ var AgentRelay = class {
45043
45078
  idleResolverSeq = 0;
45044
45079
  constructor(options = {}) {
45045
45080
  this.defaultChannels = options.channels ?? ["general"];
45081
+ this.workspaceName = options.workspaceName;
45082
+ this.relaycastBaseUrl = options.relaycastBaseUrl;
45046
45083
  this.clientOptions = {
45047
45084
  binaryPath: options.binaryPath,
45048
45085
  binaryArgs: options.binaryArgs,
@@ -45128,7 +45165,7 @@ var AgentRelay = class {
45128
45165
  if (waitForMessage) {
45129
45166
  return this.waitForAgentMessage(name, timeoutMs ?? 6e4);
45130
45167
  }
45131
- return this.waitForAgentReady(name, timeoutMs ?? 3e4);
45168
+ return this.waitForAgentReady(name, timeoutMs ?? 6e4);
45132
45169
  }
45133
45170
  // ── Human source ────────────────────────────────────────────────────────
45134
45171
  human(opts) {
@@ -45318,7 +45355,7 @@ var AgentRelay = class {
45318
45355
  * The agent's CLI may not yet be ready to receive messages.
45319
45356
  * Use `waitForAgentMessage()` for full readiness.
45320
45357
  */
45321
- async waitForAgentReady(name, timeoutMs = 3e4) {
45358
+ async waitForAgentReady(name, timeoutMs = 6e4) {
45322
45359
  const client = await this.ensureStarted();
45323
45360
  const existing = this.knownAgents.get(name);
45324
45361
  if (existing && this.readyAgents.has(name)) {
@@ -45492,14 +45529,42 @@ var AgentRelay = class {
45492
45529
  }
45493
45530
  }
45494
45531
  }
45532
+ /**
45533
+ * Ensure a Relaycast workspace API key is available.
45534
+ * Resolution order:
45535
+ * 1. Already resolved (cached from a previous call)
45536
+ * 2. RELAY_API_KEY in options.env
45537
+ * 3. RELAY_API_KEY in process.env
45538
+ * 4. Auto-create a fresh workspace via the Relaycast REST API
45539
+ */
45540
+ async ensureRelaycastApiKey() {
45541
+ if (this.relayApiKey)
45542
+ return;
45543
+ const envKey = this.clientOptions.env?.RELAY_API_KEY ?? process.env.RELAY_API_KEY;
45544
+ if (envKey) {
45545
+ this.relayApiKey = envKey;
45546
+ if (!this.clientOptions.env) {
45547
+ this.clientOptions.env = { ...process.env, RELAY_API_KEY: envKey };
45548
+ } else if (!this.clientOptions.env.RELAY_API_KEY) {
45549
+ this.clientOptions.env.RELAY_API_KEY = envKey;
45550
+ }
45551
+ return;
45552
+ }
45553
+ if (!this.clientOptions.env) {
45554
+ this.clientOptions.env = { ...process.env };
45555
+ }
45556
+ }
45495
45557
  async ensureStarted() {
45496
45558
  if (this.client)
45497
45559
  return this.client;
45498
45560
  if (this.startPromise)
45499
45561
  return this.startPromise;
45500
- this.startPromise = AgentRelayClient.start(this.clientOptions).then((c) => {
45562
+ this.startPromise = this.ensureRelaycastApiKey().then(() => AgentRelayClient.start(this.clientOptions)).then((c) => {
45501
45563
  this.client = c;
45502
45564
  this.startPromise = void 0;
45565
+ if (c.workspaceKey) {
45566
+ this.relayApiKey = c.workspaceKey;
45567
+ }
45503
45568
  this.wireEvents(c);
45504
45569
  return c;
45505
45570
  }).catch((err) => {
@@ -45648,7 +45713,7 @@ var AgentRelay = class {
45648
45713
  const client = await relay.ensureStarted();
45649
45714
  await client.release(name, reason);
45650
45715
  },
45651
- async waitForReady(timeoutMs = 3e4) {
45716
+ async waitForReady(timeoutMs = 6e4) {
45652
45717
  await relay.waitForAgentReady(name, timeoutMs);
45653
45718
  },
45654
45719
  waitForExit(timeoutMs) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "Real-time agent-to-agent communication system",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -103,6 +103,7 @@
103
103
  "postbuild": "chmod +x dist/src/cli/bootstrap.js dist/src/cli/index.js && npm run build:cjs",
104
104
  "prepack": "if [ -d node_modules ]; then npm run build; else echo '⚠ node_modules not found, skipping prepack build'; fi",
105
105
  "dev:watch": "tsc -w",
106
+ "docs": "cd ./docs && npx mintlify dev",
106
107
  "watch:start": "npm run build && concurrently -k \"npm run dev:watch\" \"node --watch dist/src/cli/bootstrap.js start dashboard.js claude\"",
107
108
  "watch:start:cli-tools": "npm run build && bash ./scripts/watch-cli-tools.sh",
108
109
  "watch:start:claude": "npm run watch:start:cli-tools -- --tool=claude",
@@ -173,13 +174,13 @@
173
174
  },
174
175
  "homepage": "https://github.com/AgentWorkforce/relay#readme",
175
176
  "dependencies": {
176
- "@agent-relay/config": "3.0.1",
177
- "@agent-relay/hooks": "3.0.1",
178
- "@agent-relay/sdk": "3.0.1",
179
- "@agent-relay/telemetry": "3.0.1",
180
- "@agent-relay/trajectory": "3.0.1",
181
- "@agent-relay/user-directory": "3.0.1",
182
- "@agent-relay/utils": "3.0.1",
177
+ "@agent-relay/config": "3.0.2",
178
+ "@agent-relay/hooks": "3.0.2",
179
+ "@agent-relay/sdk": "3.0.2",
180
+ "@agent-relay/telemetry": "3.0.2",
181
+ "@agent-relay/trajectory": "3.0.2",
182
+ "@agent-relay/user-directory": "3.0.2",
183
+ "@agent-relay/utils": "3.0.2",
183
184
  "@modelcontextprotocol/sdk": "^1.0.0",
184
185
  "@relaycast/sdk": "^0.4.0",
185
186
  "chokidar": "^5.0.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/acp-bridge",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "ACP (Agent Client Protocol) bridge for Agent Relay - expose relay agents to ACP-compatible editors like Zed",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -46,7 +46,7 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@agent-relay/sdk": "3.0.1",
49
+ "@agent-relay/sdk": "3.0.2",
50
50
  "@agentclientprotocol/sdk": "^0.12.0"
51
51
  },
52
52
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/config",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "Shared configuration schemas and loaders for Agent Relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/hooks",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "Hook emitter, registry, and trajectory hooks for Agent Relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -37,9 +37,9 @@
37
37
  "test:watch": "vitest"
38
38
  },
39
39
  "dependencies": {
40
- "@agent-relay/config": "3.0.1",
41
- "@agent-relay/trajectory": "3.0.1",
42
- "@agent-relay/sdk": "3.0.1"
40
+ "@agent-relay/config": "3.0.2",
41
+ "@agent-relay/trajectory": "3.0.2",
42
+ "@agent-relay/sdk": "3.0.2"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/node": "^22.19.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/memory",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "Semantic memory storage and retrieval system for agent-relay with multiple backend support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "test:watch": "vitest"
23
23
  },
24
24
  "dependencies": {
25
- "@agent-relay/hooks": "3.0.1"
25
+ "@agent-relay/hooks": "3.0.2"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.19.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/policy",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "Agent policy management with multi-level fallback (repo, local PRPM, cloud workspace)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "test:watch": "vitest"
23
23
  },
24
24
  "dependencies": {
25
- "@agent-relay/config": "3.0.1"
25
+ "@agent-relay/config": "3.0.2"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.19.3",
@@ -254,4 +254,52 @@ test("facade: listLoggedAgents returns array", async (t) => {
254
254
  await relay.shutdown();
255
255
  }
256
256
  });
257
+ // ── workspaceKey / observerUrl from hello_ack ────────────────────────────────
258
+ test("facade: workspaceKey is populated from broker hello_ack after startup", async (t) => {
259
+ const bin = requireBinary(t);
260
+ if (!bin)
261
+ return;
262
+ // Create relay WITHOUT passing RELAY_API_KEY in env — broker creates its own
263
+ // workspace and returns the key via hello_ack. This tests the fix for the
264
+ // "dual workspace" bug where SDK and broker used different workspace keys.
265
+ const envWithoutKey = { ...process.env };
266
+ delete envWithoutKey.RELAY_API_KEY;
267
+ const relay = new AgentRelay({
268
+ binaryPath: bin,
269
+ requestTimeoutMs: 15_000,
270
+ env: envWithoutKey,
271
+ });
272
+ try {
273
+ await relay.getStatus();
274
+ // After startup, workspaceKey MUST be set from the broker's hello_ack.
275
+ assert.ok(relay.workspaceKey, "workspaceKey must be set after broker startup (read from hello_ack workspace_key field)");
276
+ assert.match(relay.workspaceKey, /^rk_live_/, "workspaceKey must be a valid workspace key (rk_live_ prefix)");
277
+ // observerUrl must be correctly formatted.
278
+ assert.ok(relay.observerUrl, "observerUrl must be defined when workspaceKey is set");
279
+ assert.ok(relay.observerUrl.includes(relay.workspaceKey), "observerUrl must contain the workspace key");
280
+ }
281
+ finally {
282
+ await relay.shutdown();
283
+ }
284
+ });
285
+ test("facade: workspaceKey from env matches broker hello_ack when valid", async (t) => {
286
+ if (!requireRelaycast(t))
287
+ return;
288
+ const bin = requireBinary(t);
289
+ if (!bin)
290
+ return;
291
+ // When RELAY_API_KEY is valid, the broker uses it and returns the same key
292
+ // in hello_ack. SDK and broker must be on the same workspace.
293
+ const relay = makeRelay(bin);
294
+ try {
295
+ await relay.getStatus();
296
+ assert.ok(relay.workspaceKey, "workspaceKey must be set after startup");
297
+ // The workspace key returned by broker must match what we passed in.
298
+ assert.equal(relay.workspaceKey, process.env.RELAY_API_KEY, "broker hello_ack workspace_key must match the RELAY_API_KEY we passed — " +
299
+ "a mismatch means broker and SDK are on different workspaces, breaking MCP auth");
300
+ }
301
+ finally {
302
+ await relay.shutdown();
303
+ }
304
+ });
257
305
  //# sourceMappingURL=facade.test.js.map