agent-relay 2.2.23 → 2.3.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 (133) hide show
  1. package/dist/index.cjs +199 -3
  2. package/package.json +64 -21
  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/package.json +2 -2
  9. package/packages/continuity/package.json +2 -2
  10. package/packages/daemon/dist/cloud-sync.d.ts +13 -1
  11. package/packages/daemon/dist/cloud-sync.d.ts.map +1 -1
  12. package/packages/daemon/dist/cloud-sync.js +169 -5
  13. package/packages/daemon/dist/cloud-sync.js.map +1 -1
  14. package/packages/daemon/dist/server.d.ts +5 -0
  15. package/packages/daemon/dist/server.d.ts.map +1 -1
  16. package/packages/daemon/dist/server.js +50 -0
  17. package/packages/daemon/dist/server.js.map +1 -1
  18. package/packages/daemon/package.json +12 -12
  19. package/packages/daemon/src/cloud-sync.ts +201 -5
  20. package/packages/daemon/src/server.ts +61 -0
  21. package/packages/hooks/package.json +4 -4
  22. package/packages/mcp/package.json +5 -5
  23. package/packages/memory/package.json +2 -2
  24. package/packages/policy/package.json +2 -2
  25. package/packages/protocol/package.json +1 -1
  26. package/packages/resiliency/package.json +1 -1
  27. package/packages/sdk/dist/client.d.ts +1 -1
  28. package/packages/sdk/dist/client.js +2 -2
  29. package/packages/sdk/package.json +3 -3
  30. package/packages/sdk/src/client.ts +2 -2
  31. package/packages/sdk-ts/README.md +65 -0
  32. package/packages/sdk-ts/dist/__tests__/integration.test.d.ts +2 -0
  33. package/packages/sdk-ts/dist/__tests__/integration.test.d.ts.map +1 -0
  34. package/packages/sdk-ts/dist/__tests__/integration.test.js +139 -0
  35. package/packages/sdk-ts/dist/__tests__/integration.test.js.map +1 -0
  36. package/packages/sdk-ts/dist/__tests__/quickstart.test.d.ts +2 -0
  37. package/packages/sdk-ts/dist/__tests__/quickstart.test.d.ts.map +1 -0
  38. package/packages/sdk-ts/dist/__tests__/quickstart.test.js +176 -0
  39. package/packages/sdk-ts/dist/__tests__/quickstart.test.js.map +1 -0
  40. package/packages/sdk-ts/dist/browser.d.ts +16 -0
  41. package/packages/sdk-ts/dist/browser.d.ts.map +1 -0
  42. package/packages/sdk-ts/dist/browser.js +19 -0
  43. package/packages/sdk-ts/dist/browser.js.map +1 -0
  44. package/packages/sdk-ts/dist/client.d.ts +91 -0
  45. package/packages/sdk-ts/dist/client.d.ts.map +1 -0
  46. package/packages/sdk-ts/dist/client.js +360 -0
  47. package/packages/sdk-ts/dist/client.js.map +1 -0
  48. package/packages/sdk-ts/dist/consensus-helpers.d.ts +103 -0
  49. package/packages/sdk-ts/dist/consensus-helpers.d.ts.map +1 -0
  50. package/packages/sdk-ts/dist/consensus-helpers.js +147 -0
  51. package/packages/sdk-ts/dist/consensus-helpers.js.map +1 -0
  52. package/packages/sdk-ts/dist/consensus.d.ts +72 -0
  53. package/packages/sdk-ts/dist/consensus.d.ts.map +1 -0
  54. package/packages/sdk-ts/dist/consensus.js +378 -0
  55. package/packages/sdk-ts/dist/consensus.js.map +1 -0
  56. package/packages/sdk-ts/dist/examples/demo.d.ts +2 -0
  57. package/packages/sdk-ts/dist/examples/demo.d.ts.map +1 -0
  58. package/packages/sdk-ts/dist/examples/demo.js +63 -0
  59. package/packages/sdk-ts/dist/examples/demo.js.map +1 -0
  60. package/packages/sdk-ts/dist/examples/example.d.ts +2 -0
  61. package/packages/sdk-ts/dist/examples/example.d.ts.map +1 -0
  62. package/packages/sdk-ts/dist/examples/example.js +80 -0
  63. package/packages/sdk-ts/dist/examples/example.js.map +1 -0
  64. package/packages/sdk-ts/dist/examples/quickstart.d.ts +2 -0
  65. package/packages/sdk-ts/dist/examples/quickstart.d.ts.map +1 -0
  66. package/packages/sdk-ts/dist/examples/quickstart.js +56 -0
  67. package/packages/sdk-ts/dist/examples/quickstart.js.map +1 -0
  68. package/packages/sdk-ts/dist/examples/ralph-loop.d.ts +2 -0
  69. package/packages/sdk-ts/dist/examples/ralph-loop.d.ts.map +1 -0
  70. package/packages/sdk-ts/dist/examples/ralph-loop.js +281 -0
  71. package/packages/sdk-ts/dist/examples/ralph-loop.js.map +1 -0
  72. package/packages/sdk-ts/dist/index.d.ts +9 -0
  73. package/packages/sdk-ts/dist/index.d.ts.map +1 -0
  74. package/packages/sdk-ts/dist/index.js +9 -0
  75. package/packages/sdk-ts/dist/index.js.map +1 -0
  76. package/packages/sdk-ts/dist/logs.d.ts +47 -0
  77. package/packages/sdk-ts/dist/logs.d.ts.map +1 -0
  78. package/packages/sdk-ts/dist/logs.js +137 -0
  79. package/packages/sdk-ts/dist/logs.js.map +1 -0
  80. package/packages/sdk-ts/dist/protocol.d.ts +249 -0
  81. package/packages/sdk-ts/dist/protocol.d.ts.map +1 -0
  82. package/packages/sdk-ts/dist/protocol.js +2 -0
  83. package/packages/sdk-ts/dist/protocol.js.map +1 -0
  84. package/packages/sdk-ts/dist/pty.d.ts +8 -0
  85. package/packages/sdk-ts/dist/pty.d.ts.map +1 -0
  86. package/packages/sdk-ts/dist/pty.js +14 -0
  87. package/packages/sdk-ts/dist/pty.js.map +1 -0
  88. package/packages/sdk-ts/dist/relay.d.ts +118 -0
  89. package/packages/sdk-ts/dist/relay.d.ts.map +1 -0
  90. package/packages/sdk-ts/dist/relay.js +355 -0
  91. package/packages/sdk-ts/dist/relay.js.map +1 -0
  92. package/packages/sdk-ts/dist/relaycast.d.ts +57 -0
  93. package/packages/sdk-ts/dist/relaycast.d.ts.map +1 -0
  94. package/packages/sdk-ts/dist/relaycast.js +110 -0
  95. package/packages/sdk-ts/dist/relaycast.js.map +1 -0
  96. package/packages/sdk-ts/dist/shadow.d.ts +100 -0
  97. package/packages/sdk-ts/dist/shadow.d.ts.map +1 -0
  98. package/packages/sdk-ts/dist/shadow.js +174 -0
  99. package/packages/sdk-ts/dist/shadow.js.map +1 -0
  100. package/packages/sdk-ts/package.json +75 -0
  101. package/packages/sdk-ts/scripts/bundle-agent-relay.mjs +53 -0
  102. package/packages/sdk-ts/src/__tests__/integration.test.ts +170 -0
  103. package/packages/sdk-ts/src/__tests__/quickstart.test.ts +198 -0
  104. package/packages/sdk-ts/src/browser.ts +57 -0
  105. package/packages/sdk-ts/src/client.ts +491 -0
  106. package/packages/sdk-ts/src/consensus-helpers.ts +253 -0
  107. package/packages/sdk-ts/src/consensus.ts +506 -0
  108. package/packages/sdk-ts/src/examples/demo.ts +88 -0
  109. package/packages/sdk-ts/src/examples/example.ts +91 -0
  110. package/packages/sdk-ts/src/examples/quickstart.ts +72 -0
  111. package/packages/sdk-ts/src/examples/ralph-loop.ts +352 -0
  112. package/packages/sdk-ts/src/examples/sample-prd.json +37 -0
  113. package/packages/sdk-ts/src/index.ts +8 -0
  114. package/packages/sdk-ts/src/logs.ts +163 -0
  115. package/packages/sdk-ts/src/protocol.ts +266 -0
  116. package/packages/sdk-ts/src/pty.ts +16 -0
  117. package/packages/sdk-ts/src/relay.ts +454 -0
  118. package/packages/sdk-ts/src/relaycast.ts +143 -0
  119. package/packages/sdk-ts/src/shadow.ts +230 -0
  120. package/packages/sdk-ts/tsconfig.json +16 -0
  121. package/packages/spawner/package.json +1 -1
  122. package/packages/state/package.json +1 -1
  123. package/packages/storage/package.json +2 -2
  124. package/packages/telemetry/package.json +1 -1
  125. package/packages/trajectory/package.json +2 -2
  126. package/packages/user-directory/package.json +2 -2
  127. package/packages/utils/package.json +3 -3
  128. package/packages/wrapper/dist/client.js +1 -1
  129. package/packages/wrapper/package.json +6 -6
  130. package/packages/wrapper/src/client.test.ts +1 -1
  131. package/packages/wrapper/src/client.ts +1 -1
  132. package/packages/mcp/SPEC.md +0 -1922
  133. package/packages/mcp/STAFFING_PLAN.md +0 -294
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Shadow agent support for the broker SDK.
3
+ *
4
+ * A shadow agent monitors all messages to/from a primary agent.
5
+ * Implemented SDK-side using the event hook system — no broker
6
+ * protocol extension required.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { AgentRelay, ShadowManager } from "agent-relay/broker";
11
+ *
12
+ * const relay = new AgentRelay();
13
+ * const shadows = new ShadowManager();
14
+ *
15
+ * // Bind "Reviewer" as shadow of "Worker1"
16
+ * shadows.bind("Reviewer", "Worker1");
17
+ *
18
+ * // Wire into relay events
19
+ * relay.onMessageReceived = (msg) => {
20
+ * const copies = shadows.intercept(msg.from, msg.to, msg);
21
+ * for (const copy of copies) {
22
+ * // Forward shadow copies to the shadow agent
23
+ * relay.human({ name: "system" }).sendMessage({
24
+ * to: copy.shadowAgent,
25
+ * text: `[Shadow of ${copy.primaryAgent}] ${msg.text}`,
26
+ * });
27
+ * }
28
+ * };
29
+ * ```
30
+ */
31
+
32
+ // ── Types ────────────────────────────────────────────────────────────────────
33
+
34
+ export type SpeakOnTrigger =
35
+ | "ALL_MESSAGES"
36
+ | "EXPLICIT_ASK"
37
+ | "SESSION_END"
38
+ | "CODE_WRITTEN"
39
+ | "REVIEW_REQUEST";
40
+
41
+ export interface ShadowConfig {
42
+ primaryAgent: string;
43
+ speakOn: SpeakOnTrigger[];
44
+ receiveIncoming: boolean;
45
+ receiveOutgoing: boolean;
46
+ }
47
+
48
+ export interface ShadowRelationship extends ShadowConfig {
49
+ shadowAgent: string;
50
+ }
51
+
52
+ export interface ShadowCopy {
53
+ shadowAgent: string;
54
+ primaryAgent: string;
55
+ direction: "incoming" | "outgoing";
56
+ }
57
+
58
+ // ── Manager ──────────────────────────────────────────────────────────────────
59
+
60
+ export class ShadowManager {
61
+ /** primaryAgent → list of shadow relationships */
62
+ private shadowsByPrimary = new Map<string, ShadowRelationship[]>();
63
+ /** shadowAgent → primaryAgent (reverse lookup) */
64
+ private primaryByShadow = new Map<string, string>();
65
+
66
+ /**
67
+ * Bind a shadow agent to monitor a primary agent.
68
+ */
69
+ bind(
70
+ shadowAgent: string,
71
+ primaryAgent: string,
72
+ options: {
73
+ speakOn?: SpeakOnTrigger[];
74
+ receiveIncoming?: boolean;
75
+ receiveOutgoing?: boolean;
76
+ } = {},
77
+ ): void {
78
+ // Clean up any existing binding for this shadow
79
+ this.unbind(shadowAgent);
80
+
81
+ const relationship: ShadowRelationship = {
82
+ shadowAgent,
83
+ primaryAgent,
84
+ speakOn: options.speakOn ?? ["EXPLICIT_ASK"],
85
+ receiveIncoming: options.receiveIncoming ?? true,
86
+ receiveOutgoing: options.receiveOutgoing ?? true,
87
+ };
88
+
89
+ let shadows = this.shadowsByPrimary.get(primaryAgent);
90
+ if (!shadows) {
91
+ shadows = [];
92
+ this.shadowsByPrimary.set(primaryAgent, shadows);
93
+ }
94
+ shadows.push(relationship);
95
+ this.primaryByShadow.set(shadowAgent, primaryAgent);
96
+ }
97
+
98
+ /**
99
+ * Unbind a shadow from its primary.
100
+ */
101
+ unbind(shadowAgent: string): void {
102
+ const primaryAgent = this.primaryByShadow.get(shadowAgent);
103
+ if (!primaryAgent) return;
104
+
105
+ const shadows = this.shadowsByPrimary.get(primaryAgent);
106
+ if (shadows) {
107
+ const updated = shadows.filter((s) => s.shadowAgent !== shadowAgent);
108
+ if (updated.length === 0) {
109
+ this.shadowsByPrimary.delete(primaryAgent);
110
+ } else {
111
+ this.shadowsByPrimary.set(primaryAgent, updated);
112
+ }
113
+ }
114
+ this.primaryByShadow.delete(shadowAgent);
115
+ }
116
+
117
+ /**
118
+ * Get all shadows for a primary agent.
119
+ */
120
+ getShadowsFor(primaryAgent: string): ShadowRelationship[] {
121
+ return this.shadowsByPrimary.get(primaryAgent) ?? [];
122
+ }
123
+
124
+ /**
125
+ * Get the primary agent a shadow is bound to.
126
+ */
127
+ getPrimaryFor(shadowAgent: string): string | undefined {
128
+ return this.primaryByShadow.get(shadowAgent);
129
+ }
130
+
131
+ /**
132
+ * Check whether a shadow should speak for a given trigger.
133
+ */
134
+ shouldSpeak(shadowAgent: string, trigger: SpeakOnTrigger): boolean {
135
+ const primary = this.primaryByShadow.get(shadowAgent);
136
+ if (!primary) return true; // not a shadow, always speaks
137
+
138
+ const shadows = this.shadowsByPrimary.get(primary);
139
+ if (!shadows) return true;
140
+
141
+ const rel = shadows.find((s) => s.shadowAgent === shadowAgent);
142
+ if (!rel) return true;
143
+
144
+ return (
145
+ rel.speakOn.includes(trigger) || rel.speakOn.includes("ALL_MESSAGES")
146
+ );
147
+ }
148
+
149
+ /**
150
+ * Determine which shadows should receive a copy of a message
151
+ * between `from` and `to`. Returns a list of shadow copies to deliver.
152
+ *
153
+ * Call this from your `onMessageReceived` / `onMessageSent` hooks
154
+ * to fan out shadow copies.
155
+ */
156
+ intercept(from: string, to: string): ShadowCopy[] {
157
+ const copies: ShadowCopy[] = [];
158
+
159
+ // Outgoing shadows of the sender
160
+ const senderShadows = this.shadowsByPrimary.get(from);
161
+ if (senderShadows) {
162
+ for (const s of senderShadows) {
163
+ if (s.receiveOutgoing && s.shadowAgent !== to) {
164
+ copies.push({
165
+ shadowAgent: s.shadowAgent,
166
+ primaryAgent: from,
167
+ direction: "outgoing",
168
+ });
169
+ }
170
+ }
171
+ }
172
+
173
+ // Incoming shadows of the recipient
174
+ if (to && to !== "*") {
175
+ const recipientShadows = this.shadowsByPrimary.get(to);
176
+ if (recipientShadows) {
177
+ for (const s of recipientShadows) {
178
+ if (s.receiveIncoming && s.shadowAgent !== from) {
179
+ copies.push({
180
+ shadowAgent: s.shadowAgent,
181
+ primaryAgent: to,
182
+ direction: "incoming",
183
+ });
184
+ }
185
+ }
186
+ }
187
+ }
188
+
189
+ return copies;
190
+ }
191
+
192
+ /**
193
+ * Emit a trigger event and return shadow agents that should be notified.
194
+ *
195
+ * Use this to implement `speakOn` behavior — when a trigger fires
196
+ * (e.g. CODE_WRITTEN, REVIEW_REQUEST), call this to find which
197
+ * shadows should receive a notification.
198
+ */
199
+ emitTrigger(
200
+ primaryAgent: string,
201
+ trigger: SpeakOnTrigger,
202
+ ): string[] {
203
+ const shadows = this.shadowsByPrimary.get(primaryAgent) ?? [];
204
+ return shadows
205
+ .filter(
206
+ (s) =>
207
+ s.speakOn.includes(trigger) || s.speakOn.includes("ALL_MESSAGES"),
208
+ )
209
+ .map((s) => s.shadowAgent);
210
+ }
211
+
212
+ /**
213
+ * List all current shadow bindings.
214
+ */
215
+ listBindings(): ShadowRelationship[] {
216
+ const all: ShadowRelationship[] = [];
217
+ for (const shadows of this.shadowsByPrimary.values()) {
218
+ all.push(...shadows);
219
+ }
220
+ return all;
221
+ }
222
+
223
+ /**
224
+ * Remove all bindings (for shutdown).
225
+ */
226
+ clear(): void {
227
+ this.shadowsByPrimary.clear();
228
+ this.primaryByShadow.clear();
229
+ }
230
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "moduleResolution": "Bundler",
6
+ "strict": true,
7
+ "declaration": true,
8
+ "declarationMap": true,
9
+ "sourceMap": true,
10
+ "outDir": "dist",
11
+ "rootDir": "src",
12
+ "types": ["node"],
13
+ "skipLibCheck": true
14
+ },
15
+ "include": ["src/**/*.ts"]
16
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/spawner",
3
- "version": "2.2.23",
3
+ "version": "2.3.0",
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.2.23",
3
+ "version": "2.3.0",
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.2.23",
3
+ "version": "2.3.0",
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.2.23"
59
+ "@agent-relay/protocol": "2.3.0"
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.2.23",
3
+ "version": "2.3.0",
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.2.23",
3
+ "version": "2.3.0",
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.2.23"
25
+ "@agent-relay/config": "2.3.0"
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.2.23",
3
+ "version": "2.3.0",
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.2.23"
25
+ "@agent-relay/resiliency": "2.3.0"
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.2.23",
3
+ "version": "2.3.0",
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.2.23",
116
- "@agent-relay/protocol": "2.2.23",
115
+ "@agent-relay/config": "2.3.0",
116
+ "@agent-relay/protocol": "2.3.0",
117
117
  "compare-versions": "^6.1.1"
118
118
  },
119
119
  "publishConfig": {
@@ -568,7 +568,7 @@ export class RelayClient {
568
568
  shadowTriggers: options.shadowTriggers,
569
569
  shadowSpeakOn: options.shadowSpeakOn,
570
570
  };
571
- const result = await this.requestResponse('SPAWN', payload, 30000 // 30 second timeout for spawn
571
+ const result = await this.requestResponse('SPAWN', payload, 60000 // 60 second timeout for spawn
572
572
  );
573
573
  return toSpawnResult(result);
574
574
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/wrapper",
3
- "version": "2.2.23",
3
+ "version": "2.3.0",
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.2.23",
34
- "@agent-relay/protocol": "2.2.23",
35
- "@agent-relay/config": "2.2.23",
36
- "@agent-relay/continuity": "2.2.23",
37
- "@agent-relay/resiliency": "2.2.23",
33
+ "@agent-relay/api-types": "2.3.0",
34
+ "@agent-relay/protocol": "2.3.0",
35
+ "@agent-relay/config": "2.3.0",
36
+ "@agent-relay/continuity": "2.3.0",
37
+ "@agent-relay/resiliency": "2.3.0",
38
38
  "zod": "^3.23.8"
39
39
  },
40
40
  "devDependencies": {
@@ -290,7 +290,7 @@ describe('RelayClient', () => {
290
290
  model: 'opus',
291
291
  cwd: '/test/path',
292
292
  }),
293
- 30000
293
+ 60000
294
294
  );
295
295
  expect(result.success).toBe(true);
296
296
  });
@@ -750,7 +750,7 @@ export class RelayClient {
750
750
  const result = await this.requestResponse<SpawnResultPayload>(
751
751
  'SPAWN',
752
752
  payload as unknown as Record<string, unknown>,
753
- 30000 // 30 second timeout for spawn
753
+ 60000 // 60 second timeout for spawn
754
754
  );
755
755
 
756
756
  return toSpawnResult(result);