agent-relay 2.3.2 → 2.3.4

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 (62) hide show
  1. package/dist/index.cjs +1 -1
  2. package/package.json +18 -18
  3. package/packages/acp-bridge/package.json +2 -2
  4. package/packages/api-types/package.json +1 -1
  5. package/packages/benchmark/package.json +5 -5
  6. package/packages/bridge/package.json +7 -7
  7. package/packages/cli-tester/package.json +1 -1
  8. package/packages/config/dist/cloud-config.d.ts +1 -1
  9. package/packages/config/dist/cloud-config.d.ts.map +1 -1
  10. package/packages/config/dist/cloud-config.js.map +1 -1
  11. package/packages/config/dist/schemas.d.ts +5 -5
  12. package/packages/config/dist/schemas.js +1 -1
  13. package/packages/config/dist/schemas.js.map +1 -1
  14. package/packages/config/package.json +2 -2
  15. package/packages/config/src/cloud-config.ts +2 -2
  16. package/packages/config/src/schemas.test.ts +48 -0
  17. package/packages/config/src/schemas.ts +1 -1
  18. package/packages/continuity/package.json +2 -2
  19. package/packages/daemon/package.json +12 -12
  20. package/packages/hooks/package.json +4 -4
  21. package/packages/mcp/package.json +5 -5
  22. package/packages/memory/package.json +2 -2
  23. package/packages/policy/package.json +2 -2
  24. package/packages/protocol/package.json +1 -1
  25. package/packages/resiliency/package.json +1 -1
  26. package/packages/sdk/package.json +3 -3
  27. package/packages/sdk-ts/dist/__tests__/facade.test.d.ts +2 -0
  28. package/packages/sdk-ts/dist/__tests__/facade.test.d.ts.map +1 -0
  29. package/packages/sdk-ts/dist/__tests__/facade.test.js +257 -0
  30. package/packages/sdk-ts/dist/__tests__/facade.test.js.map +1 -0
  31. package/packages/sdk-ts/dist/__tests__/unit.test.d.ts +2 -0
  32. package/packages/sdk-ts/dist/__tests__/unit.test.d.ts.map +1 -0
  33. package/packages/sdk-ts/dist/__tests__/unit.test.js +124 -0
  34. package/packages/sdk-ts/dist/__tests__/unit.test.js.map +1 -0
  35. package/packages/sdk-ts/dist/client.d.ts +2 -0
  36. package/packages/sdk-ts/dist/client.d.ts.map +1 -1
  37. package/packages/sdk-ts/dist/client.js +2 -0
  38. package/packages/sdk-ts/dist/client.js.map +1 -1
  39. package/packages/sdk-ts/dist/protocol.d.ts +1 -0
  40. package/packages/sdk-ts/dist/protocol.d.ts.map +1 -1
  41. package/packages/sdk-ts/dist/relay.d.ts +44 -0
  42. package/packages/sdk-ts/dist/relay.d.ts.map +1 -1
  43. package/packages/sdk-ts/dist/relay.js +89 -11
  44. package/packages/sdk-ts/dist/relay.js.map +1 -1
  45. package/packages/sdk-ts/dist/relaycast.js +2 -2
  46. package/packages/sdk-ts/dist/relaycast.js.map +1 -1
  47. package/packages/sdk-ts/package.json +3 -3
  48. package/packages/sdk-ts/src/__tests__/facade.test.ts +296 -0
  49. package/packages/sdk-ts/src/__tests__/unit.test.ts +152 -0
  50. package/packages/sdk-ts/src/client.ts +4 -0
  51. package/packages/sdk-ts/src/protocol.ts +1 -1
  52. package/packages/sdk-ts/src/relay.ts +112 -11
  53. package/packages/sdk-ts/src/relaycast.ts +2 -2
  54. package/packages/spawner/package.json +1 -1
  55. package/packages/state/package.json +1 -1
  56. package/packages/storage/package.json +2 -2
  57. package/packages/telemetry/package.json +1 -1
  58. package/packages/trajectory/package.json +2 -2
  59. package/packages/user-directory/package.json +2 -2
  60. package/packages/utils/package.json +3 -3
  61. package/packages/wrapper/package.json +6 -6
  62. package/scripts/postinstall.js +106 -2
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Unit tests — no broker binary or RELAY_API_KEY required.
3
+ *
4
+ * Run:
5
+ * npm run build && node --test dist/__tests__/unit.test.js
6
+ */
7
+ import assert from "node:assert/strict";
8
+ import { join, sep } from "node:path";
9
+ import { mkdtemp, writeFile, rm } from "node:fs/promises";
10
+ import { tmpdir } from "node:os";
11
+ import test from "node:test";
12
+
13
+ import { AgentRelay, type Agent } from "../relay.js";
14
+ import { getLogs, listLoggedAgents } from "../logs.js";
15
+
16
+ // ── waitForAny ──────────────────────────────────────────────────────────────
17
+
18
+ function makeFakeAgent(
19
+ name: string,
20
+ exitAfterMs?: number,
21
+ ): Agent {
22
+ let resolveExit: ((reason: "exited" | "released") => void) | undefined;
23
+ const exitPromise = new Promise<"exited" | "released">((resolve) => {
24
+ resolveExit = resolve;
25
+ });
26
+
27
+ if (exitAfterMs !== undefined) {
28
+ setTimeout(() => resolveExit?.("exited"), exitAfterMs);
29
+ }
30
+
31
+ return {
32
+ name,
33
+ runtime: "pty",
34
+ channels: ["general"],
35
+ exitCode: undefined,
36
+ exitSignal: undefined,
37
+ async release() {
38
+ resolveExit?.("released");
39
+ },
40
+ waitForExit(timeoutMs?: number) {
41
+ if (timeoutMs === 0) return Promise.resolve("timeout" as const);
42
+ if (timeoutMs !== undefined) {
43
+ return Promise.race([
44
+ exitPromise,
45
+ new Promise<"timeout">((resolve) =>
46
+ setTimeout(() => resolve("timeout"), timeoutMs),
47
+ ),
48
+ ]);
49
+ }
50
+ return exitPromise;
51
+ },
52
+ async sendMessage() {
53
+ return { eventId: "fake", from: name, to: "", text: "" };
54
+ },
55
+ };
56
+ }
57
+
58
+ test("waitForAny: returns first agent to exit", async () => {
59
+ const fast = makeFakeAgent("fast", 50);
60
+ const slow = makeFakeAgent("slow", 5_000);
61
+
62
+ const { agent, result } = await AgentRelay.waitForAny([fast, slow], 3_000);
63
+ assert.equal(agent.name, "fast");
64
+ assert.equal(result, "exited");
65
+ });
66
+
67
+ test("waitForAny: returns timeout when no agent exits", async () => {
68
+ const a = makeFakeAgent("a");
69
+ const b = makeFakeAgent("b");
70
+
71
+ const { result } = await AgentRelay.waitForAny([a, b], 100);
72
+ assert.equal(result, "timeout");
73
+ });
74
+
75
+ test("waitForAny: handles released agent", async () => {
76
+ const agent = makeFakeAgent("releasable");
77
+
78
+ // Release after 50ms
79
+ setTimeout(() => agent.release(), 50);
80
+
81
+ const { agent: resolved, result } = await AgentRelay.waitForAny([agent], 3_000);
82
+ assert.equal(resolved.name, "releasable");
83
+ assert.equal(result, "released");
84
+ });
85
+
86
+ test("waitForAny: throws on empty agents array", async () => {
87
+ await assert.rejects(
88
+ () => AgentRelay.waitForAny([]),
89
+ { message: "waitForAny requires at least one agent" },
90
+ );
91
+ });
92
+
93
+ // ── getLogs ──────────────────────────────────────────────────────────────────
94
+
95
+ test("getLogs: rejects path traversal", async () => {
96
+ const result = await getLogs("../../etc/passwd", {
97
+ logsDir: "/tmp/test-logs",
98
+ });
99
+ assert.equal(result.found, false);
100
+ assert.equal(result.content, "");
101
+ });
102
+
103
+ test("getLogs: returns not found for missing agent", async () => {
104
+ const dir = await mkdtemp(join(tmpdir(), "relay-test-logs-"));
105
+
106
+ try {
107
+ const result = await getLogs("nonexistent", { logsDir: dir });
108
+ assert.equal(result.found, false);
109
+ assert.equal(result.content, "");
110
+ } finally {
111
+ await rm(dir, { recursive: true, force: true });
112
+ }
113
+ });
114
+
115
+ test("getLogs: reads content from log file", async () => {
116
+ const dir = await mkdtemp(join(tmpdir(), "relay-test-logs-"));
117
+
118
+ try {
119
+ const logContent = "line1\nline2\nline3\n";
120
+ await writeFile(join(dir, "TestAgent.log"), logContent);
121
+
122
+ const result = await getLogs("TestAgent", { logsDir: dir, lines: 2 });
123
+ assert.equal(result.found, true);
124
+ assert.equal(result.content, "line2\nline3");
125
+ assert.equal(result.lineCount, 2);
126
+ } finally {
127
+ await rm(dir, { recursive: true, force: true });
128
+ }
129
+ });
130
+
131
+ test("listLoggedAgents: lists agent names from log files", async () => {
132
+ const dir = await mkdtemp(join(tmpdir(), "relay-test-logs-"));
133
+
134
+ try {
135
+ await writeFile(join(dir, "Alice.log"), "hello\n");
136
+ await writeFile(join(dir, "Bob.log"), "world\n");
137
+ await writeFile(join(dir, "not-a-log.txt"), "skip\n");
138
+
139
+ const agents = await listLoggedAgents(dir);
140
+ assert.ok(agents.includes("Alice"));
141
+ assert.ok(agents.includes("Bob"));
142
+ assert.ok(!agents.includes("not-a-log"));
143
+ } finally {
144
+ await rm(dir, { recursive: true, force: true });
145
+ }
146
+ });
147
+
148
+ test("listLoggedAgents: returns empty for missing directory", async () => {
149
+ const agents = await listLoggedAgents("/tmp/definitely-nonexistent-dir");
150
+ assert.deepEqual(agents, []);
151
+ });
152
+
@@ -34,12 +34,14 @@ export interface SpawnPtyInput {
34
34
  cli: string;
35
35
  args?: string[];
36
36
  channels?: string[];
37
+ task?: string;
37
38
  }
38
39
 
39
40
  export interface SpawnHeadlessClaudeInput {
40
41
  name: string;
41
42
  args?: string[];
42
43
  channels?: string[];
44
+ task?: string;
43
45
  }
44
46
 
45
47
  export interface SendMessageInput {
@@ -167,6 +169,7 @@ export class AgentRelayClient {
167
169
  };
168
170
  const result = await this.requestOk<{ name: string; runtime: AgentRuntime }>("spawn_agent", {
169
171
  agent,
172
+ ...(input.task != null ? { initial_task: input.task } : {}),
170
173
  });
171
174
  return result;
172
175
  }
@@ -183,6 +186,7 @@ export class AgentRelayClient {
183
186
  };
184
187
  const result = await this.requestOk<{ name: string; runtime: AgentRuntime }>("spawn_agent", {
185
188
  agent,
189
+ ...(input.task != null ? { initial_task: input.task } : {}),
186
190
  });
187
191
  return result;
188
192
  }
@@ -34,7 +34,7 @@ export type SdkToBroker =
34
34
  }
35
35
  | {
36
36
  type: "spawn_agent";
37
- payload: { agent: AgentSpec };
37
+ payload: { agent: AgentSpec; initial_task?: string };
38
38
  }
39
39
  | {
40
40
  type: "send_message";
@@ -34,6 +34,7 @@ import {
34
34
  } from "./client.js";
35
35
  import type { AgentRuntime, BrokerEvent, BrokerStatus } from "./protocol.js";
36
36
  import { RelaycastApi } from "./relaycast.js";
37
+ import { getLogs as getLogsFromFile, listLoggedAgents as listLoggedAgentsFromFile, type LogsResult, type GetLogsOptions } from "./logs.js";
37
38
 
38
39
  function isUnsupportedOperation(error: unknown): error is AgentRelayProtocolError {
39
40
  return error instanceof AgentRelayProtocolError && error.code === "unsupported_operation";
@@ -66,6 +67,10 @@ export interface Agent {
66
67
  readonly name: string;
67
68
  readonly runtime: AgentRuntime;
68
69
  readonly channels: string[];
70
+ /** Set when the agent exits. Available after `onAgentExited` fires. */
71
+ exitCode?: number;
72
+ /** Set when the agent exits via signal. Available after `onAgentExited` fires. */
73
+ exitSignal?: string;
69
74
  release(): Promise<void>;
70
75
  /** Wait for the agent process to exit on its own.
71
76
  * @param timeoutMs — optional timeout in ms. Resolves with `"timeout"` if exceeded,
@@ -94,6 +99,7 @@ export interface AgentSpawner {
94
99
  name?: string;
95
100
  args?: string[];
96
101
  channels?: string[];
102
+ task?: string;
97
103
  }): Promise<Agent>;
98
104
  }
99
105
 
@@ -119,6 +125,7 @@ export class AgentRelay {
119
125
  onAgentSpawned: EventHook<Agent> = null;
120
126
  onAgentReleased: EventHook<Agent> = null;
121
127
  onAgentExited: EventHook<Agent> = null;
128
+ onAgentReady: EventHook<Agent> = null;
122
129
  onWorkerOutput: EventHook<{ name: string; stream: string; chunk: string }> = null;
123
130
  onDeliveryUpdate: EventHook<BrokerEvent> = null;
124
131
 
@@ -133,7 +140,11 @@ export class AgentRelay {
133
140
  private startPromise?: Promise<AgentRelayClient>;
134
141
  private unsubEvent?: () => void;
135
142
  private readonly knownAgents = new Map<string, Agent>();
136
- private readonly exitResolvers = new Map<string, (reason: "exited" | "released") => void>();
143
+ private readonly exitResolvers = new Map<
144
+ string,
145
+ { resolve: (reason: "exited" | "released") => void; token: number }
146
+ >();
147
+ private exitResolverSeq = 0;
137
148
  private readonly relaycastByName = new Map<string, RelaycastApi>();
138
149
 
139
150
  constructor(options: AgentRelayOptions = {}) {
@@ -164,6 +175,7 @@ export class AgentRelay {
164
175
  cli: input.cli,
165
176
  args: input.args,
166
177
  channels,
178
+ task: input.task,
167
179
  });
168
180
  const agent = this.makeAgent(result.name, result.runtime, channels);
169
181
  this.knownAgents.set(agent.name, agent);
@@ -211,6 +223,21 @@ export class AgentRelay {
211
223
  };
212
224
  }
213
225
 
226
+ // ── Messaging ─────────────────────────────────────────────────────────
227
+
228
+ /**
229
+ * Broadcast a message to all connected agents.
230
+ * @param text — the message body
231
+ * @param options — optional sender name (defaults to "human:orchestrator")
232
+ */
233
+ async broadcast(
234
+ text: string,
235
+ options?: { from?: string },
236
+ ): Promise<Message> {
237
+ const from = options?.from ?? "human:orchestrator";
238
+ return this.human({ name: from }).sendMessage({ to: "*", text });
239
+ }
240
+
214
241
  // ── Listing ─────────────────────────────────────────────────────────────
215
242
 
216
243
  async listAgents(): Promise<Agent[]> {
@@ -232,6 +259,57 @@ export class AgentRelay {
232
259
  return client.getStatus();
233
260
  }
234
261
 
262
+ // ── Logs ──────────────────────────────────────────────────────────────
263
+
264
+ /**
265
+ * Read the last N lines of an agent's log file.
266
+ *
267
+ * @example
268
+ * ```ts
269
+ * const logs = await relay.getLogs("Worker1", { lines: 100 });
270
+ * if (logs.found) console.log(logs.content);
271
+ * ```
272
+ */
273
+ async getLogs(agentName: string, options?: { lines?: number }): Promise<LogsResult> {
274
+ const cwd = this.clientOptions.cwd ?? process.cwd();
275
+ const logsDir = path.join(cwd, ".agent-relay", "worker-logs");
276
+ return getLogsFromFile(agentName, { logsDir, lines: options?.lines });
277
+ }
278
+
279
+ /** List all agents that have log files. */
280
+ async listLoggedAgents(): Promise<string[]> {
281
+ const cwd = this.clientOptions.cwd ?? process.cwd();
282
+ const logsDir = path.join(cwd, ".agent-relay", "worker-logs");
283
+ return listLoggedAgentsFromFile(logsDir);
284
+ }
285
+
286
+ // ── Wait helpers ──────────────────────────────────────────────────────
287
+
288
+ /**
289
+ * Wait for any one of the given agents to exit. Returns the first agent
290
+ * that exits along with its exit reason.
291
+ *
292
+ * @example
293
+ * ```ts
294
+ * const { agent, result } = await AgentRelay.waitForAny([worker1, worker2], 60_000);
295
+ * console.log(`${agent.name} finished: ${result}`);
296
+ * ```
297
+ */
298
+ static async waitForAny(
299
+ agents: Agent[],
300
+ timeoutMs?: number,
301
+ ): Promise<{ agent: Agent; result: "exited" | "timeout" | "released" }> {
302
+ if (agents.length === 0) {
303
+ throw new Error("waitForAny requires at least one agent");
304
+ }
305
+ return Promise.race(
306
+ agents.map(async (agent) => {
307
+ const result = await agent.waitForExit(timeoutMs);
308
+ return { agent, result };
309
+ }),
310
+ );
311
+ }
312
+
235
313
  // ── Lifecycle ───────────────────────────────────────────────────────────
236
314
 
237
315
  async shutdown(): Promise<void> {
@@ -244,8 +322,8 @@ export class AgentRelay {
244
322
  this.client = undefined;
245
323
  }
246
324
  this.knownAgents.clear();
247
- for (const resolve of this.exitResolvers.values()) {
248
- resolve("released");
325
+ for (const entry of this.exitResolvers.values()) {
326
+ entry.resolve("released");
249
327
  }
250
328
  this.exitResolvers.clear();
251
329
  }
@@ -323,7 +401,7 @@ export class AgentRelay {
323
401
  this.makeAgent(event.name, "pty", []);
324
402
  this.onAgentReleased?.(agent);
325
403
  this.knownAgents.delete(event.name);
326
- this.exitResolvers.get(event.name)?.("released");
404
+ this.exitResolvers.get(event.name)?.resolve("released");
327
405
  this.exitResolvers.delete(event.name);
328
406
  break;
329
407
  }
@@ -331,12 +409,24 @@ export class AgentRelay {
331
409
  const agent =
332
410
  this.knownAgents.get(event.name) ??
333
411
  this.makeAgent(event.name, "pty", []);
412
+ // Populate exit info before firing the hook
413
+ (agent as { exitCode?: number }).exitCode = event.code;
414
+ (agent as { exitSignal?: string }).exitSignal = event.signal;
334
415
  this.onAgentExited?.(agent);
335
416
  this.knownAgents.delete(event.name);
336
- this.exitResolvers.get(event.name)?.("exited");
417
+ this.exitResolvers.get(event.name)?.resolve("exited");
337
418
  this.exitResolvers.delete(event.name);
338
419
  break;
339
420
  }
421
+ case "worker_ready": {
422
+ let agent = this.knownAgents.get(event.name);
423
+ if (!agent) {
424
+ agent = this.makeAgent(event.name, event.runtime, []);
425
+ this.knownAgents.set(event.name, agent);
426
+ }
427
+ this.onAgentReady?.(agent);
428
+ break;
429
+ }
340
430
  case "worker_stream": {
341
431
  this.onWorkerOutput?.({
342
432
  name: event.name,
@@ -362,6 +452,8 @@ export class AgentRelay {
362
452
  name,
363
453
  runtime,
364
454
  channels,
455
+ exitCode: undefined,
456
+ exitSignal: undefined,
365
457
  async release() {
366
458
  const client = await relay.ensureStarted();
367
459
  await client.release(name);
@@ -379,13 +471,21 @@ export class AgentRelay {
379
471
  return;
380
472
  }
381
473
  let timer: ReturnType<typeof setTimeout> | undefined;
382
- relay.exitResolvers.set(name, (reason) => {
383
- if (timer) clearTimeout(timer);
384
- resolve(reason);
474
+ const token = ++relay.exitResolverSeq;
475
+ relay.exitResolvers.set(name, {
476
+ resolve(reason) {
477
+ if (timer) clearTimeout(timer);
478
+ resolve(reason);
479
+ },
480
+ token,
385
481
  });
386
482
  if (timeoutMs !== undefined) {
387
483
  timer = setTimeout(() => {
388
- relay.exitResolvers.delete(name);
484
+ // Only delete if this is still our resolver (not one from a later call)
485
+ const current = relay.exitResolvers.get(name);
486
+ if (current?.token === token) {
487
+ relay.exitResolvers.delete(name);
488
+ }
389
489
  resolve("timeout");
390
490
  }, timeoutMs);
391
491
  }
@@ -438,11 +538,12 @@ export class AgentRelay {
438
538
  const channels = options?.channels ?? ["general"];
439
539
  const args = options?.args ?? [];
440
540
 
541
+ const task = options?.task;
441
542
  let result: { name: string; runtime: AgentRuntime };
442
543
  if (runtime === "headless_claude") {
443
- result = await client.spawnHeadlessClaude({ name, args, channels });
544
+ result = await client.spawnHeadlessClaude({ name, args, channels, task });
444
545
  } else {
445
- result = await client.spawnPty({ name, cli, args, channels });
546
+ result = await client.spawnPty({ name, cli, args, channels, task });
446
547
  }
447
548
 
448
549
  const agent = relay.makeAgent(result.name, result.runtime, channels);
@@ -2,7 +2,7 @@ import { randomBytes } from "node:crypto";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { homedir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { Relay, RelayError, type AgentClient } from "@relaycast/sdk";
5
+ import { RelayCast, RelayError, type AgentClient } from "@relaycast/sdk";
6
6
 
7
7
  export interface RelaycastCredentials {
8
8
  workspace_id: string;
@@ -85,7 +85,7 @@ export class RelaycastApi {
85
85
  if (this.agentClient) return this.agentClient;
86
86
 
87
87
  const apiKey = await this.resolveApiKey();
88
- const relay = new Relay({ apiKey, baseUrl: this.baseUrl });
88
+ const relay = new RelayCast({ apiKey, baseUrl: this.baseUrl });
89
89
 
90
90
  // Register — retry with a suffixed name on 409 conflict.
91
91
  let name = this.agentName;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/spawner",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "Agent spawning types and utilities for Agent Relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/state",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "Agent state persistence for non-hook CLIs (Codex, Gemini, etc.)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/storage",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "Storage adapters and interfaces for Relay message/session persistence",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -56,7 +56,7 @@
56
56
  }
57
57
  },
58
58
  "dependencies": {
59
- "@agent-relay/protocol": "2.3.2"
59
+ "@agent-relay/protocol": "2.3.4"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/node": "^22.19.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/telemetry",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "Anonymous telemetry for Agent Relay usage analytics",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/trajectory",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "Trajectory integration utilities (trail/PDERO) for Relay",
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": "2.3.2"
25
+ "@agent-relay/config": "2.3.4"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.19.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/user-directory",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "User directory service for agent-relay (per-user credential storage)",
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/resiliency": "2.3.2"
25
+ "@agent-relay/resiliency": "2.3.4"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.19.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/utils",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "Shared utilities for agent-relay: logging, name generation, command resolution, update checking",
5
5
  "type": "module",
6
6
  "main": "dist/cjs/index.js",
@@ -112,8 +112,8 @@
112
112
  "vitest": "^3.2.4"
113
113
  },
114
114
  "dependencies": {
115
- "@agent-relay/config": "2.3.2",
116
- "@agent-relay/protocol": "2.3.2",
115
+ "@agent-relay/config": "2.3.4",
116
+ "@agent-relay/protocol": "2.3.4",
117
117
  "compare-versions": "^6.1.1"
118
118
  },
119
119
  "publishConfig": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/wrapper",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "CLI agent wrappers for Agent Relay - tmux, pty integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -30,11 +30,11 @@
30
30
  "clean": "rm -rf dist"
31
31
  },
32
32
  "dependencies": {
33
- "@agent-relay/api-types": "2.3.2",
34
- "@agent-relay/protocol": "2.3.2",
35
- "@agent-relay/config": "2.3.2",
36
- "@agent-relay/continuity": "2.3.2",
37
- "@agent-relay/resiliency": "2.3.2",
33
+ "@agent-relay/api-types": "2.3.4",
34
+ "@agent-relay/protocol": "2.3.4",
35
+ "@agent-relay/config": "2.3.4",
36
+ "@agent-relay/continuity": "2.3.4",
37
+ "@agent-relay/resiliency": "2.3.4",
38
38
  "zod": "^3.23.8"
39
39
  },
40
40
  "devDependencies": {