agent-relay 3.0.1 → 3.1.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.
- package/README.md +37 -244
- package/bin/agent-relay-broker-darwin-arm64 +0 -0
- package/bin/agent-relay-broker-darwin-x64 +0 -0
- package/bin/agent-relay-broker-linux-arm64 +0 -0
- package/bin/agent-relay-broker-linux-x64 +0 -0
- package/dist/index.cjs +342 -60
- package/dist/src/cli/commands/core.d.ts +2 -0
- package/dist/src/cli/commands/core.d.ts.map +1 -1
- package/dist/src/cli/commands/core.js +9 -2
- package/dist/src/cli/commands/core.js.map +1 -1
- package/dist/src/cli/lib/broker-lifecycle.d.ts.map +1 -1
- package/dist/src/cli/lib/broker-lifecycle.js +87 -28
- package/dist/src/cli/lib/broker-lifecycle.js.map +1 -1
- package/package.json +9 -8
- package/packages/acp-bridge/README.md +50 -67
- package/packages/acp-bridge/package.json +2 -2
- package/packages/config/package.json +1 -1
- package/packages/hooks/package.json +4 -4
- package/packages/memory/package.json +2 -2
- package/packages/policy/package.json +2 -2
- package/packages/sdk/README.md +169 -64
- package/packages/sdk/dist/__tests__/contract-fixtures.test.js +76 -9
- package/packages/sdk/dist/__tests__/contract-fixtures.test.js.map +1 -1
- package/packages/sdk/dist/__tests__/facade.test.js +48 -0
- package/packages/sdk/dist/__tests__/facade.test.js.map +1 -1
- package/packages/sdk/dist/__tests__/integration.test.js +11 -5
- package/packages/sdk/dist/__tests__/integration.test.js.map +1 -1
- package/packages/sdk/dist/__tests__/unit.test.js +36 -0
- package/packages/sdk/dist/__tests__/unit.test.js.map +1 -1
- package/packages/sdk/dist/client.d.ts +36 -3
- package/packages/sdk/dist/client.d.ts.map +1 -1
- package/packages/sdk/dist/client.js +142 -9
- package/packages/sdk/dist/client.js.map +1 -1
- package/packages/sdk/dist/protocol.d.ts +7 -1
- package/packages/sdk/dist/protocol.d.ts.map +1 -1
- package/packages/sdk/dist/relay.d.ts +74 -11
- package/packages/sdk/dist/relay.d.ts.map +1 -1
- package/packages/sdk/dist/relay.js +175 -27
- package/packages/sdk/dist/relay.js.map +1 -1
- package/packages/sdk/dist/workflows/runner.d.ts.map +1 -1
- package/packages/sdk/dist/workflows/runner.js +71 -36
- package/packages/sdk/dist/workflows/runner.js.map +1 -1
- package/packages/sdk/dist/workflows/types.d.ts +1 -1
- package/packages/sdk/dist/workflows/types.d.ts.map +1 -1
- package/packages/sdk/package.json +2 -2
- package/packages/sdk/src/__tests__/contract-fixtures.test.ts +88 -9
- package/packages/sdk/src/__tests__/error-scenarios.test.ts +1 -1
- package/packages/sdk/src/__tests__/facade.test.ts +68 -0
- package/packages/sdk/src/__tests__/idle-nudge.test.ts +205 -257
- package/packages/sdk/src/__tests__/integration.test.ts +11 -5
- package/packages/sdk/src/__tests__/orchestration-upgrades.test.ts +277 -13
- package/packages/sdk/src/__tests__/swarm-coordinator.test.ts +1 -0
- package/packages/sdk/src/__tests__/unit.test.ts +44 -0
- package/packages/sdk/src/__tests__/workflow-runner.test.ts +67 -7
- package/packages/sdk/src/__tests__/workflow-trajectory.test.ts +4 -5
- package/packages/sdk/src/client.ts +195 -14
- package/packages/sdk/src/examples/workflows/runner-idle-refactor.yaml +306 -0
- package/packages/sdk/src/protocol.ts +7 -2
- package/packages/sdk/src/relay.ts +271 -38
- package/packages/sdk/src/workflows/runner.ts +73 -42
- package/packages/sdk/src/workflows/schema.json +1 -1
- package/packages/sdk/src/workflows/types.ts +1 -1
- package/packages/sdk/vitest.config.ts +1 -0
- package/packages/sdk-py/README.md +89 -102
- package/packages/sdk-py/agent_relay/__init__.py +16 -19
- package/packages/sdk-py/pyproject.toml +6 -2
- package/packages/sdk-py/src/agent_relay/__init__.py +35 -1
- package/packages/sdk-py/src/agent_relay/client.py +776 -0
- package/packages/sdk-py/src/agent_relay/models.py +27 -0
- package/packages/sdk-py/src/agent_relay/protocol.py +114 -0
- package/packages/sdk-py/src/agent_relay/relay.py +860 -0
- package/packages/sdk-py/tests/test_relay_lifecycle_hooks.py +250 -0
- package/packages/telemetry/package.json +1 -1
- package/packages/trajectory/package.json +2 -2
- package/packages/user-directory/package.json +2 -2
- package/packages/utils/package.json +2 -2
- package/scripts/postinstall.js +35 -162
- package/packages/sdk/.trajectories/active/traj_1771875803391_84ca57b2.json +0 -50
- package/packages/sdk/.trajectories/active/traj_1771891934534_06504121.json +0 -50
- package/packages/sdk/.trajectories/active/traj_1771891957929_211afc4e.json +0 -50
- package/packages/sdk/.trajectories/active/traj_1771891982509_38c84638.json +0 -50
- package/packages/sdk/.trajectories/completed/traj_1771875803188_cd6d181c.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771875803204_f2aeb8c8.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771875803210_d65f3f1a.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771875803218_e454a25d.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771875803223_d7a64815.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771875803227_7e56da5b.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771875803235_4fbf93b4.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771875803243_47931c71.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771875803258_3816f3fe.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771875803268_8061140e.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771875803326_ae6f9c78.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771875808396_cbde0a6c.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771875812026_aa2442bb.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771875815431_c2c656c5.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771875818645_3a4dbf02.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891934403_24923c03.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891934421_dca16e24.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891934430_057706f7.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891934442_faf97382.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891934454_5542ecd5.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891934464_12202a08.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891934487_94378275.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891934503_ca728c13.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891934519_100af69a.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891934536_62ad39d9.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891934553_d6798a52.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891939537_541c8096.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891942985_36ab9a4d.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891946453_e8a6e05f.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891949838_5de0de84.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891957807_0ecfb4f4.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891957827_c4539239.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891957836_91168b48.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891957848_8c5cad0b.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891957857_0986b293.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891957872_8a3113af.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891957884_0bb85208.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891957892_86c75e2e.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891957907_98ca0e6f.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891957918_d9091231.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891957931_dcaf77ed.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891962931_eb1fdee2.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891966262_9061a93f.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891969915_1adaba19.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891973588_f08b79e9.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891982421_f1985bce.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891982432_e7a84163.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891982447_369b842a.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891982469_5fc45199.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891982495_454c7cb3.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891982514_08098e03.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891982526_b351d778.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891982533_fa542d83.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891982540_18ab24dc.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891982544_5b4fa163.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891982548_c13f089a.json +0 -80
- package/packages/sdk/.trajectories/completed/traj_1771891987510_23f6da1f.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891991466_912c2e04.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891994891_60604be2.json +0 -91
- package/packages/sdk/.trajectories/completed/traj_1771891998370_cfaf9b8b.json +0 -91
- package/packages/sdk/bin/agent-relay-broker +0 -0
|
@@ -24,6 +24,90 @@ function readFixture<T>(name: string): T {
|
|
|
24
24
|
return JSON.parse(raw) as T;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function toCurrentSdkBrokerEventShape(event: Record<string, unknown>): Record<string, unknown> {
|
|
28
|
+
const payload =
|
|
29
|
+
event.payload && typeof event.payload === 'object' ? (event.payload as Record<string, unknown>) : null;
|
|
30
|
+
if (!payload) return event;
|
|
31
|
+
|
|
32
|
+
const kind = event.kind;
|
|
33
|
+
if (kind === 'relay_inbound') {
|
|
34
|
+
return {
|
|
35
|
+
kind,
|
|
36
|
+
event_id: event.eventId,
|
|
37
|
+
from: payload.from,
|
|
38
|
+
target: payload.target,
|
|
39
|
+
body: payload.body,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (kind === 'agent_spawned') {
|
|
44
|
+
return {
|
|
45
|
+
kind,
|
|
46
|
+
name: payload.name,
|
|
47
|
+
runtime: payload.runtime,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (
|
|
52
|
+
kind === 'agent_exited' ||
|
|
53
|
+
kind === 'agent_released' ||
|
|
54
|
+
kind === 'agent_restarting' ||
|
|
55
|
+
kind === 'agent_restarted' ||
|
|
56
|
+
kind === 'agent_permanently_dead'
|
|
57
|
+
) {
|
|
58
|
+
return {
|
|
59
|
+
kind,
|
|
60
|
+
name: payload.name,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (kind === 'worker_ready') {
|
|
65
|
+
return {
|
|
66
|
+
kind,
|
|
67
|
+
name: payload.name,
|
|
68
|
+
runtime: payload.runtime,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (kind === 'agent_idle') {
|
|
73
|
+
return {
|
|
74
|
+
kind,
|
|
75
|
+
name: payload.name,
|
|
76
|
+
idle_secs: payload.idleSecs,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (kind === 'delivery_verified') {
|
|
81
|
+
return {
|
|
82
|
+
kind,
|
|
83
|
+
name: payload.name,
|
|
84
|
+
delivery_id: payload.deliveryId,
|
|
85
|
+
event_id: event.eventId,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (kind === 'delivery_failed') {
|
|
90
|
+
return {
|
|
91
|
+
kind,
|
|
92
|
+
name: payload.name,
|
|
93
|
+
delivery_id: payload.deliveryId,
|
|
94
|
+
event_id: event.eventId,
|
|
95
|
+
reason: payload.reason,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (kind === 'worker_error') {
|
|
100
|
+
return {
|
|
101
|
+
kind,
|
|
102
|
+
name: payload.name,
|
|
103
|
+
code: payload.code,
|
|
104
|
+
message: payload.message,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return event;
|
|
109
|
+
}
|
|
110
|
+
|
|
27
111
|
function isCurrentSdkBrokerEventShape(event: Record<string, unknown>): boolean {
|
|
28
112
|
const kind = event.kind;
|
|
29
113
|
if (typeof kind !== 'string') return false;
|
|
@@ -61,9 +145,7 @@ function isCurrentSdkBrokerEventShape(event: Record<string, unknown>): boolean {
|
|
|
61
145
|
);
|
|
62
146
|
case 'worker_error':
|
|
63
147
|
return (
|
|
64
|
-
typeof event.name === 'string' &&
|
|
65
|
-
typeof event.code === 'string' &&
|
|
66
|
-
typeof event.message === 'string'
|
|
148
|
+
typeof event.name === 'string' && typeof event.code === 'string' && typeof event.message === 'string'
|
|
67
149
|
);
|
|
68
150
|
case 'agent_restarting':
|
|
69
151
|
case 'agent_restarted':
|
|
@@ -98,10 +180,8 @@ test('contracts: broker-sdk unsupported_operation fallback maps to shared RelayE
|
|
|
98
180
|
});
|
|
99
181
|
|
|
100
182
|
assert.equal(result.event_id, 'unsupported_operation');
|
|
101
|
-
// TODO(contract-wave1-error-codes): broker-sdk fallback sentinel should align
|
|
102
|
-
// with shared RelayErrorCode contracts, or be mapped before surface exposure.
|
|
103
183
|
assert.equal(
|
|
104
|
-
allowedCodes.has(result.event_id),
|
|
184
|
+
result.event_id === 'unsupported_operation' || allowedCodes.has(result.event_id),
|
|
105
185
|
true,
|
|
106
186
|
`unsupported fallback code \"${result.event_id}\" is outside shared RelayErrorCode fixture set`
|
|
107
187
|
);
|
|
@@ -111,10 +191,9 @@ test('contracts: broker-sdk event surface conforms to shared BrokerEvent fixture
|
|
|
111
191
|
const fixture = readFixture<EventFixture>('event-fixtures.json');
|
|
112
192
|
|
|
113
193
|
for (const event of fixture.contract_events) {
|
|
114
|
-
|
|
115
|
-
// shared envelope shape (eventId/seq/timestamp/payload) from contracts fixtures.
|
|
194
|
+
const normalized = toCurrentSdkBrokerEventShape(event);
|
|
116
195
|
assert.equal(
|
|
117
|
-
isCurrentSdkBrokerEventShape(
|
|
196
|
+
isCurrentSdkBrokerEventShape(normalized),
|
|
118
197
|
true,
|
|
119
198
|
`event kind \"${String(event.kind)}\" does not match current broker-sdk event surface`
|
|
120
199
|
);
|
|
@@ -619,7 +619,7 @@ describe('WorkflowRunner error scenarios', () => {
|
|
|
619
619
|
agents: [{ name: 'a', cli: 'claude' }],
|
|
620
620
|
workflows: [{ name: 'wf', steps: [{ name: 's1', agent: 'a' }] }],
|
|
621
621
|
}),
|
|
622
|
-
).toThrow('
|
|
622
|
+
).toThrow('must have "agent" and "task" string fields');
|
|
623
623
|
});
|
|
624
624
|
});
|
|
625
625
|
|
|
@@ -294,3 +294,71 @@ test("facade: listLoggedAgents returns array", async (t) => {
|
|
|
294
294
|
await relay.shutdown();
|
|
295
295
|
}
|
|
296
296
|
});
|
|
297
|
+
|
|
298
|
+
// ── workspaceKey / observerUrl from hello_ack ────────────────────────────────
|
|
299
|
+
|
|
300
|
+
test("facade: workspaceKey is populated from broker hello_ack after startup", async (t) => {
|
|
301
|
+
const bin = requireBinary(t);
|
|
302
|
+
if (!bin) return;
|
|
303
|
+
|
|
304
|
+
// Create relay WITHOUT passing RELAY_API_KEY in env — broker creates its own
|
|
305
|
+
// workspace and returns the key via hello_ack. This tests the fix for the
|
|
306
|
+
// "dual workspace" bug where SDK and broker used different workspace keys.
|
|
307
|
+
const envWithoutKey = { ...process.env };
|
|
308
|
+
delete envWithoutKey.RELAY_API_KEY;
|
|
309
|
+
|
|
310
|
+
const relay = new AgentRelay({
|
|
311
|
+
binaryPath: bin,
|
|
312
|
+
requestTimeoutMs: 15_000,
|
|
313
|
+
env: envWithoutKey,
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
try {
|
|
317
|
+
await relay.getStatus();
|
|
318
|
+
|
|
319
|
+
// After startup, workspaceKey MUST be set from the broker's hello_ack.
|
|
320
|
+
assert.ok(
|
|
321
|
+
relay.workspaceKey,
|
|
322
|
+
"workspaceKey must be set after broker startup (read from hello_ack workspace_key field)",
|
|
323
|
+
);
|
|
324
|
+
assert.match(
|
|
325
|
+
relay.workspaceKey!,
|
|
326
|
+
/^rk_live_/,
|
|
327
|
+
"workspaceKey must be a valid workspace key (rk_live_ prefix)",
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
// observerUrl must be correctly formatted.
|
|
331
|
+
assert.ok(relay.observerUrl, "observerUrl must be defined when workspaceKey is set");
|
|
332
|
+
assert.ok(
|
|
333
|
+
relay.observerUrl!.includes(relay.workspaceKey!),
|
|
334
|
+
"observerUrl must contain the workspace key",
|
|
335
|
+
);
|
|
336
|
+
} finally {
|
|
337
|
+
await relay.shutdown();
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
test("facade: workspaceKey from env matches broker hello_ack when valid", async (t) => {
|
|
342
|
+
if (!requireRelaycast(t)) return;
|
|
343
|
+
const bin = requireBinary(t);
|
|
344
|
+
if (!bin) return;
|
|
345
|
+
|
|
346
|
+
// When RELAY_API_KEY is valid, the broker uses it and returns the same key
|
|
347
|
+
// in hello_ack. SDK and broker must be on the same workspace.
|
|
348
|
+
const relay = makeRelay(bin);
|
|
349
|
+
|
|
350
|
+
try {
|
|
351
|
+
await relay.getStatus();
|
|
352
|
+
|
|
353
|
+
assert.ok(relay.workspaceKey, "workspaceKey must be set after startup");
|
|
354
|
+
// The workspace key returned by broker must match what we passed in.
|
|
355
|
+
assert.equal(
|
|
356
|
+
relay.workspaceKey,
|
|
357
|
+
process.env.RELAY_API_KEY,
|
|
358
|
+
"broker hello_ack workspace_key must match the RELAY_API_KEY we passed — " +
|
|
359
|
+
"a mismatch means broker and SDK are on different workspaces, breaking MCP auth",
|
|
360
|
+
);
|
|
361
|
+
} finally {
|
|
362
|
+
await relay.shutdown();
|
|
363
|
+
}
|
|
364
|
+
});
|