agent-relay 3.2.21 → 4.0.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 (157) hide show
  1. package/bin/agent-relay-broker-darwin-arm64 +0 -0
  2. package/bin/agent-relay-broker-darwin-x64 +0 -0
  3. package/bin/agent-relay-broker-linux-arm64 +0 -0
  4. package/bin/agent-relay-broker-linux-x64 +0 -0
  5. package/dist/index.cjs +5065 -1422
  6. package/dist/src/cli/bootstrap.d.ts.map +1 -1
  7. package/dist/src/cli/bootstrap.js +2 -0
  8. package/dist/src/cli/bootstrap.js.map +1 -1
  9. package/dist/src/cli/commands/agent-management.d.ts.map +1 -1
  10. package/dist/src/cli/commands/agent-management.js +14 -4
  11. package/dist/src/cli/commands/agent-management.js.map +1 -1
  12. package/dist/src/cli/commands/core.d.ts +2 -6
  13. package/dist/src/cli/commands/core.d.ts.map +1 -1
  14. package/dist/src/cli/commands/core.js +30 -12
  15. package/dist/src/cli/commands/core.js.map +1 -1
  16. package/dist/src/cli/commands/messaging.d.ts.map +1 -1
  17. package/dist/src/cli/commands/messaging.js +10 -3
  18. package/dist/src/cli/commands/messaging.js.map +1 -1
  19. package/dist/src/cli/commands/monitoring.d.ts +2 -2
  20. package/dist/src/cli/commands/monitoring.d.ts.map +1 -1
  21. package/dist/src/cli/commands/monitoring.js +15 -6
  22. package/dist/src/cli/commands/monitoring.js.map +1 -1
  23. package/dist/src/cli/commands/on/dotfiles.d.ts +35 -0
  24. package/dist/src/cli/commands/on/dotfiles.d.ts.map +1 -0
  25. package/dist/src/cli/commands/on/dotfiles.js +157 -0
  26. package/dist/src/cli/commands/on/dotfiles.js.map +1 -0
  27. package/dist/src/cli/commands/on/prereqs.d.ts +15 -0
  28. package/dist/src/cli/commands/on/prereqs.d.ts.map +1 -0
  29. package/dist/src/cli/commands/on/prereqs.js +103 -0
  30. package/dist/src/cli/commands/on/prereqs.js.map +1 -0
  31. package/dist/src/cli/commands/on/provision.d.ts +22 -0
  32. package/dist/src/cli/commands/on/provision.d.ts.map +1 -0
  33. package/dist/src/cli/commands/on/provision.js +157 -0
  34. package/dist/src/cli/commands/on/provision.js.map +1 -0
  35. package/dist/src/cli/commands/on/scan.d.ts +8 -0
  36. package/dist/src/cli/commands/on/scan.d.ts.map +1 -0
  37. package/dist/src/cli/commands/on/scan.js +59 -0
  38. package/dist/src/cli/commands/on/scan.js.map +1 -0
  39. package/dist/src/cli/commands/on/services.d.ts +17 -0
  40. package/dist/src/cli/commands/on/services.d.ts.map +1 -0
  41. package/dist/src/cli/commands/on/services.js +328 -0
  42. package/dist/src/cli/commands/on/services.js.map +1 -0
  43. package/dist/src/cli/commands/on/start.d.ts +61 -0
  44. package/dist/src/cli/commands/on/start.d.ts.map +1 -0
  45. package/dist/src/cli/commands/on/start.js +1071 -0
  46. package/dist/src/cli/commands/on/start.js.map +1 -0
  47. package/dist/src/cli/commands/on/stop.d.ts +4 -0
  48. package/dist/src/cli/commands/on/stop.d.ts.map +1 -0
  49. package/dist/src/cli/commands/on/stop.js +11 -0
  50. package/dist/src/cli/commands/on/stop.js.map +1 -0
  51. package/dist/src/cli/commands/on/token.d.ts +8 -0
  52. package/dist/src/cli/commands/on/token.d.ts.map +1 -0
  53. package/dist/src/cli/commands/on/token.js +26 -0
  54. package/dist/src/cli/commands/on/token.js.map +1 -0
  55. package/dist/src/cli/commands/on/workspace.d.ts +4 -0
  56. package/dist/src/cli/commands/on/workspace.d.ts.map +1 -0
  57. package/dist/src/cli/commands/on/workspace.js +241 -0
  58. package/dist/src/cli/commands/on/workspace.js.map +1 -0
  59. package/dist/src/cli/commands/on.d.ts +10 -0
  60. package/dist/src/cli/commands/on.d.ts.map +1 -0
  61. package/dist/src/cli/commands/on.js +52 -0
  62. package/dist/src/cli/commands/on.js.map +1 -0
  63. package/dist/src/cli/commands/setup.d.ts.map +1 -1
  64. package/dist/src/cli/commands/setup.js +10 -21
  65. package/dist/src/cli/commands/setup.js.map +1 -1
  66. package/dist/src/cli/lib/bridge.js +1 -1
  67. package/dist/src/cli/lib/bridge.js.map +1 -1
  68. package/dist/src/cli/lib/broker-lifecycle.d.ts +14 -4
  69. package/dist/src/cli/lib/broker-lifecycle.d.ts.map +1 -1
  70. package/dist/src/cli/lib/broker-lifecycle.js +82 -120
  71. package/dist/src/cli/lib/broker-lifecycle.js.map +1 -1
  72. package/dist/src/cli/lib/client-factory.d.ts +2 -2
  73. package/dist/src/cli/lib/client-factory.d.ts.map +1 -1
  74. package/dist/src/cli/lib/client-factory.js +14 -11
  75. package/dist/src/cli/lib/client-factory.js.map +1 -1
  76. package/dist/src/cli/lib/core-maintenance.d.ts.map +1 -1
  77. package/dist/src/cli/lib/core-maintenance.js +11 -22
  78. package/dist/src/cli/lib/core-maintenance.js.map +1 -1
  79. package/package.json +14 -11
  80. package/packages/acp-bridge/package.json +2 -2
  81. package/packages/brand/package.json +1 -1
  82. package/packages/cloud/package.json +2 -2
  83. package/packages/config/package.json +1 -1
  84. package/packages/hooks/package.json +4 -4
  85. package/packages/memory/package.json +2 -2
  86. package/packages/openclaw/package.json +2 -2
  87. package/packages/policy/package.json +2 -2
  88. package/packages/sdk/README.md +10 -3
  89. package/packages/sdk/dist/client.d.ts +108 -196
  90. package/packages/sdk/dist/client.d.ts.map +1 -1
  91. package/packages/sdk/dist/client.js +336 -824
  92. package/packages/sdk/dist/client.js.map +1 -1
  93. package/packages/sdk/dist/examples/example.js +2 -5
  94. package/packages/sdk/dist/examples/example.js.map +1 -1
  95. package/packages/sdk/dist/index.d.ts +3 -1
  96. package/packages/sdk/dist/index.d.ts.map +1 -1
  97. package/packages/sdk/dist/index.js +3 -1
  98. package/packages/sdk/dist/index.js.map +1 -1
  99. package/packages/sdk/dist/relay-adapter.d.ts +9 -26
  100. package/packages/sdk/dist/relay-adapter.d.ts.map +1 -1
  101. package/packages/sdk/dist/relay-adapter.js +75 -47
  102. package/packages/sdk/dist/relay-adapter.js.map +1 -1
  103. package/packages/sdk/dist/relay.d.ts +24 -5
  104. package/packages/sdk/dist/relay.d.ts.map +1 -1
  105. package/packages/sdk/dist/relay.js +213 -43
  106. package/packages/sdk/dist/relay.js.map +1 -1
  107. package/packages/sdk/dist/transport.d.ts +58 -0
  108. package/packages/sdk/dist/transport.d.ts.map +1 -0
  109. package/packages/sdk/dist/transport.js +184 -0
  110. package/packages/sdk/dist/transport.js.map +1 -0
  111. package/packages/sdk/dist/types.d.ts +69 -0
  112. package/packages/sdk/dist/types.d.ts.map +1 -0
  113. package/packages/sdk/dist/types.js +5 -0
  114. package/packages/sdk/dist/types.js.map +1 -0
  115. package/packages/sdk/dist/workflows/cli.js +46 -2
  116. package/packages/sdk/dist/workflows/cli.js.map +1 -1
  117. package/packages/sdk/dist/workflows/file-db.d.ts +2 -0
  118. package/packages/sdk/dist/workflows/file-db.d.ts.map +1 -1
  119. package/packages/sdk/dist/workflows/file-db.js +20 -3
  120. package/packages/sdk/dist/workflows/file-db.js.map +1 -1
  121. package/packages/sdk/dist/workflows/runner.d.ts +6 -1
  122. package/packages/sdk/dist/workflows/runner.d.ts.map +1 -1
  123. package/packages/sdk/dist/workflows/runner.js +157 -11
  124. package/packages/sdk/dist/workflows/runner.js.map +1 -1
  125. package/packages/sdk/dist/workflows/validator.d.ts.map +1 -1
  126. package/packages/sdk/dist/workflows/validator.js +17 -2
  127. package/packages/sdk/dist/workflows/validator.js.map +1 -1
  128. package/packages/sdk/package.json +2 -2
  129. package/packages/sdk/src/__tests__/resume-fallback.test.ts +415 -0
  130. package/packages/sdk/src/__tests__/unit.test.ts +100 -1
  131. package/packages/sdk/src/client.ts +422 -1072
  132. package/packages/sdk/src/examples/example.ts +2 -5
  133. package/packages/sdk/src/index.ts +8 -1
  134. package/packages/sdk/src/relay-adapter.ts +75 -55
  135. package/packages/sdk/src/relay.ts +260 -57
  136. package/packages/sdk/src/transport.ts +216 -0
  137. package/packages/sdk/src/types.ts +75 -0
  138. package/packages/sdk/src/workflows/cli.ts +53 -2
  139. package/packages/sdk/src/workflows/file-db.ts +22 -3
  140. package/packages/sdk/src/workflows/runner.ts +178 -11
  141. package/packages/sdk/src/workflows/validator.ts +20 -2
  142. package/packages/sdk-py/pyproject.toml +1 -1
  143. package/packages/sdk-py/src/agent_relay/__init__.py +0 -8
  144. package/packages/sdk-py/src/agent_relay/client.py +329 -522
  145. package/packages/sdk-py/src/agent_relay/protocol.py +2 -96
  146. package/packages/sdk-py/src/agent_relay/relay.py +1 -4
  147. package/packages/sdk-py/tests/test_wait_for_api_url.py +92 -0
  148. package/packages/sdk-py/uv.lock +5388 -0
  149. package/packages/telemetry/dist/client.d.ts.map +1 -1
  150. package/packages/telemetry/dist/client.js +1 -1
  151. package/packages/telemetry/dist/client.js.map +1 -1
  152. package/packages/telemetry/package.json +1 -1
  153. package/packages/telemetry/src/client.ts +3 -10
  154. package/packages/trajectory/package.json +2 -2
  155. package/packages/user-directory/package.json +2 -2
  156. package/packages/utils/package.json +2 -2
  157. package/scripts/postinstall.js +121 -1
@@ -21,16 +21,14 @@ async function main(): Promise<void> {
21
21
  const xName = process.env.AGENT_X_NAME ?? "CodexX";
22
22
  const oName = process.env.AGENT_O_NAME ?? "CodexO";
23
23
 
24
- const client = await AgentRelayClient.start({
24
+ const client = await AgentRelayClient.spawn({
25
25
  channels: [channel],
26
+ onStderr: (line) => console.log(`[${now()}] broker:stderr ${line}`),
26
27
  });
27
28
 
28
29
  const stopLogging = client.onEvent((event) => {
29
30
  console.log(`[${now()}] event`, JSON.stringify(event));
30
31
  });
31
- const stopStderrLogging = client.onBrokerStderr((line) => {
32
- console.log(`[${now()}] broker:stderr ${line}`);
33
- });
34
32
 
35
33
  const cleanup = async () => {
36
34
  console.log(`[${now()}] cleaning up agents + broker`);
@@ -46,7 +44,6 @@ async function main(): Promise<void> {
46
44
  }
47
45
  await client.shutdown();
48
46
  stopLogging();
49
- stopStderrLogging();
50
47
  };
51
48
 
52
49
  process.on("SIGINT", async () => {
@@ -1,5 +1,12 @@
1
1
  export * from './protocol.js';
2
- export * from './client.js';
2
+ export * from './types.js';
3
+ export { BrokerTransport, type BrokerTransportOptions, AgentRelayProtocolError } from './transport.js';
4
+ export {
5
+ AgentRelayClient,
6
+ type AgentRelayClientOptions,
7
+ type AgentRelaySpawnOptions,
8
+ type SessionInfo,
9
+ } from './client.js';
3
10
  export * from './models.js';
4
11
  export { RelayCast, RelayError, AgentClient } from '@relaycast/sdk';
5
12
  export type { RelayCastOptions, ClientOptions } from '@relaycast/sdk';
@@ -19,13 +19,8 @@
19
19
  * await relay.shutdown();
20
20
  */
21
21
 
22
- import {
23
- AgentRelayClient,
24
- type AgentRelayClientOptions,
25
- type SpawnPtyInput,
26
- type SendMessageInput,
27
- type ListAgent,
28
- } from './client.js';
22
+ import { AgentRelayClient, type AgentRelaySpawnOptions } from './client.js';
23
+ import type { SpawnPtyInput, SendMessageInput } from './types.js';
29
24
  import type { BrokerEvent, BrokerStats, BrokerStatus, CrashInsightsResponse } from './protocol.js';
30
25
 
31
26
  const WORKFLOW_BOOTSTRAP_TASK =
@@ -42,7 +37,11 @@ const WORKFLOW_CONVENTIONS = [
42
37
 
43
38
  function hasWorkflowConventions(task: string): boolean {
44
39
  const lower = task.toLowerCase();
45
- return lower.includes('mcp__relaycast__message_dm_send(') || lower.includes('relay_send(') || (lower.includes('ack:') && lower.includes('done:'));
40
+ return (
41
+ lower.includes('mcp__relaycast__message_dm_send(') ||
42
+ lower.includes('relay_send(') ||
43
+ (lower.includes('ack:') && lower.includes('done:'))
44
+ );
46
45
  }
47
46
 
48
47
  function buildSpawnTask(
@@ -77,8 +76,6 @@ export interface RelayAdapterOptions {
77
76
  channels?: string[];
78
77
  /** Environment variables forwarded to the broker process. */
79
78
  env?: NodeJS.ProcessEnv;
80
- /** Client name reported in the hello handshake. */
81
- clientName?: string;
82
79
  }
83
80
 
84
81
  export interface RelaySpawnRequest {
@@ -124,32 +121,66 @@ export interface RelayReleaseResult {
124
121
  // ── Adapter ─────────────────────────────────────────────────────────
125
122
 
126
123
  export class RelayAdapter {
127
- private client: AgentRelayClient;
124
+ private client: AgentRelayClient | null = null;
128
125
  private started = false;
126
+ private startPromise: Promise<void> | null = null;
127
+ private readonly spawnOpts: AgentRelaySpawnOptions;
128
+ private readonly stderrListeners = new Set<(line: string) => void>();
129
+ private readonly pendingEventListeners: Array<(event: BrokerEvent) => void> = [];
129
130
 
130
131
  constructor(opts: RelayAdapterOptions) {
131
- const clientOpts: AgentRelayClientOptions = {
132
+ this.spawnOpts = {
132
133
  binaryPath: opts.binaryPath,
133
134
  channels: opts.channels ?? ['general'],
134
135
  cwd: opts.cwd,
135
136
  env: opts.env,
136
- clientName: opts.clientName ?? 'relay-adapter',
137
137
  };
138
- this.client = new AgentRelayClient(clientOpts);
138
+ }
139
+
140
+ private ensureClient(): AgentRelayClient {
141
+ if (!this.client) throw new Error('RelayAdapter not started — call start() first');
142
+ return this.client;
139
143
  }
140
144
 
141
145
  // ── Lifecycle ───────────────────────────────────────────────────
142
146
 
143
- /** Start the broker process. Idempotent. */
147
+ /** Start the broker process. Idempotent — concurrent calls share one spawn. */
144
148
  async start(): Promise<void> {
145
149
  if (this.started) return;
146
- await this.client.start();
150
+ if (this.startPromise) return this.startPromise;
151
+ this.startPromise = this.doStart();
152
+ try {
153
+ await this.startPromise;
154
+ } finally {
155
+ this.startPromise = null;
156
+ }
157
+ }
158
+
159
+ private async doStart(): Promise<void> {
160
+ this.client = await AgentRelayClient.spawn({
161
+ ...this.spawnOpts,
162
+ onStderr: (line) => {
163
+ for (const listener of this.stderrListeners) {
164
+ try {
165
+ listener(line);
166
+ } catch {
167
+ /* ignore */
168
+ }
169
+ }
170
+ },
171
+ });
172
+ // Wire any event listeners that were registered before start()
173
+ for (const listener of this.pendingEventListeners) {
174
+ this.client.onEvent(listener);
175
+ }
176
+ this.pendingEventListeners.length = 0;
147
177
  this.started = true;
148
178
  }
149
179
 
150
180
  /** Shut down the broker and all spawned agents. */
151
181
  async shutdown(): Promise<void> {
152
- await this.client.shutdown();
182
+ await this.ensureClient().shutdown();
183
+ this.client = null;
153
184
  this.started = false;
154
185
  }
155
186
 
@@ -158,6 +189,7 @@ export class RelayAdapter {
158
189
  /** Spawn an agent via the broker's PTY runtime. */
159
190
  async spawn(req: RelaySpawnRequest): Promise<RelaySpawnResult> {
160
191
  await this.start();
192
+ const client = this.ensureClient();
161
193
  try {
162
194
  const input: SpawnPtyInput = {
163
195
  name: req.name,
@@ -170,15 +202,14 @@ export class RelayAdapter {
170
202
  shadowOf: req.shadowOf,
171
203
  shadowMode: req.shadowMode,
172
204
  };
173
- const result = await this.client.spawnPty(input);
205
+ const result = await client.spawnPty(input);
174
206
 
175
- // Try to get PID from agent list
176
207
  let pid: number | undefined;
177
208
  try {
178
- const agents = await this.client.listAgents();
209
+ const agents = await client.listAgents();
179
210
  pid = agents.find((a) => a.name === req.name)?.pid;
180
211
  } catch {
181
- // Non-fatal — PID is informational
212
+ // Non-fatal
182
213
  }
183
214
 
184
215
  return { success: true, name: result.name, pid };
@@ -191,7 +222,7 @@ export class RelayAdapter {
191
222
  async release(name: string, reason?: string): Promise<RelayReleaseResult> {
192
223
  await this.start();
193
224
  try {
194
- await this.client.release(name, reason);
225
+ await this.ensureClient().release(name, reason);
195
226
  return { success: true, name };
196
227
  } catch (err: any) {
197
228
  return { success: false, name, error: err?.message ?? String(err) };
@@ -203,10 +234,10 @@ export class RelayAdapter {
203
234
  /** List all agents managed by this broker instance. */
204
235
  async listAgents(): Promise<RelayAgentInfo[]> {
205
236
  await this.start();
206
- const agents = await this.client.listAgents();
237
+ const agents = await this.ensureClient().listAgents();
207
238
  return agents.map((a) => ({
208
239
  name: a.name,
209
- cli: undefined, // Rust binary doesn't track CLI in list_agents response
240
+ cli: undefined,
210
241
  pid: a.pid,
211
242
  channels: a.channels,
212
243
  parent: a.parent,
@@ -223,7 +254,7 @@ export class RelayAdapter {
223
254
  /** Get broker status (agent count, pending deliveries). */
224
255
  async getStatus(): Promise<BrokerStatus> {
225
256
  await this.start();
226
- return this.client.getStatus();
257
+ return this.ensureClient().getStatus();
227
258
  }
228
259
 
229
260
  // ── Messaging ───────────────────────────────────────────────────
@@ -231,24 +262,16 @@ export class RelayAdapter {
231
262
  /** Send a message to an agent or channel. */
232
263
  async sendMessage(input: SendMessageInput): Promise<{ event_id: string; targets: string[] }> {
233
264
  await this.start();
234
- return this.client.sendMessage(input);
265
+ return this.ensureClient().sendMessage(input);
235
266
  }
236
267
 
237
268
  // ── PTY Input ───────────────────────────────────────────────────
238
269
 
239
- /**
240
- * Send raw input to an agent's PTY stdin.
241
- * Useful for interrupts (ESC sequences), confirmations, etc.
242
- */
243
270
  async sendInput(name: string, data: string): Promise<void> {
244
271
  await this.start();
245
- await this.client.sendInput(name, data);
272
+ await this.ensureClient().sendInput(name, data);
246
273
  }
247
274
 
248
- /**
249
- * Send an interrupt (ESC ESC) to an agent.
250
- * Convenience wrapper around sendInput.
251
- */
252
275
  async interruptAgent(name: string): Promise<boolean> {
253
276
  try {
254
277
  await this.sendInput(name, '\x1b\x1b');
@@ -260,57 +283,54 @@ export class RelayAdapter {
260
283
 
261
284
  // ── Model ───────────────────────────────────────────────────────
262
285
 
263
- /** Switch an agent's model at runtime. */
264
286
  async setModel(
265
287
  name: string,
266
288
  model: string,
267
289
  opts?: { timeoutMs?: number }
268
290
  ): Promise<{ success: boolean; name: string; model: string }> {
269
291
  await this.start();
270
- return this.client.setModel(name, model, opts);
292
+ return this.ensureClient().setModel(name, model, opts);
271
293
  }
272
294
 
273
295
  // ── Metrics ─────────────────────────────────────────────────────
274
296
 
275
- /** Get resource metrics for agents (memory, uptime) and broker stats. */
276
297
  async getMetrics(agent?: string): Promise<{
277
298
  agents: Array<{ name: string; pid: number; memory_bytes: number; uptime_secs: number }>;
278
299
  broker?: BrokerStats;
279
300
  }> {
280
301
  await this.start();
281
- return this.client.getMetrics(agent);
302
+ return this.ensureClient().getMetrics(agent);
282
303
  }
283
304
 
284
- /** Get crash insights: recent crashes, patterns, and health score. */
285
305
  async getCrashInsights(): Promise<CrashInsightsResponse> {
286
306
  await this.start();
287
- return this.client.getCrashInsights();
307
+ return this.ensureClient().getCrashInsights();
288
308
  }
289
309
 
290
310
  // ── Events ──────────────────────────────────────────────────────
291
311
 
292
- /**
293
- * Subscribe to broker events (agent_spawned, agent_released,
294
- * relay_inbound, worker_stream, etc.).
295
- *
296
- * Returns an unsubscribe function.
297
- */
298
312
  onEvent(listener: (event: BrokerEvent) => void): () => void {
299
- return this.client.onEvent(listener);
313
+ if (this.client) {
314
+ return this.client.onEvent(listener);
315
+ }
316
+ // Queue listener — will be wired after start()
317
+ this.pendingEventListeners.push(listener);
318
+ return () => {
319
+ const idx = this.pendingEventListeners.indexOf(listener);
320
+ if (idx >= 0) this.pendingEventListeners.splice(idx, 1);
321
+ };
300
322
  }
301
323
 
302
- /**
303
- * Subscribe to broker stderr output (debug logs from the Rust binary).
304
- * Returns an unsubscribe function.
305
- */
306
324
  onStderr(listener: (line: string) => void): () => void {
307
- return this.client.onBrokerStderr(listener);
325
+ this.stderrListeners.add(listener);
326
+ return () => {
327
+ this.stderrListeners.delete(listener);
328
+ };
308
329
  }
309
330
 
310
331
  // ── Underlying client (escape hatch) ────────────────────────────
311
332
 
312
- /** Access the underlying AgentRelayClient for advanced operations. */
313
333
  get raw(): AgentRelayClient {
314
- return this.client;
334
+ return this.ensureClient();
315
335
  }
316
336
  }