agent-relay 2.0.33 → 2.0.35
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 +44 -0
- package/dist/index.cjs +10323 -15012
- package/package.json +26 -19
- package/packages/api-types/.trajectories/active/traj_xbsvuzogscey.json +15 -0
- package/packages/api-types/.trajectories/index.json +12 -0
- package/packages/api-types/package.json +1 -1
- package/packages/benchmark/package.json +4 -4
- package/packages/bridge/dist/spawner.d.ts.map +1 -1
- package/packages/bridge/dist/spawner.js +127 -0
- package/packages/bridge/dist/spawner.js.map +1 -1
- package/packages/bridge/package.json +8 -8
- package/packages/bridge/src/spawner.ts +137 -0
- package/packages/cli-tester/package.json +1 -1
- package/packages/config/package.json +2 -2
- package/packages/continuity/package.json +1 -1
- package/packages/daemon/package.json +12 -12
- package/packages/hooks/package.json +4 -4
- package/packages/mcp/package.json +3 -3
- package/packages/memory/package.json +2 -2
- package/packages/policy/package.json +2 -2
- package/packages/protocol/package.json +1 -1
- package/packages/resiliency/package.json +1 -1
- package/packages/sdk/package.json +2 -2
- package/packages/spawner/package.json +1 -1
- package/packages/state/package.json +1 -1
- package/packages/storage/package.json +2 -2
- 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/packages/wrapper/dist/base-wrapper.d.ts.map +1 -1
- package/packages/wrapper/dist/base-wrapper.js +27 -7
- package/packages/wrapper/dist/base-wrapper.js.map +1 -1
- package/packages/wrapper/dist/client.d.ts +27 -0
- package/packages/wrapper/dist/client.d.ts.map +1 -1
- package/packages/wrapper/dist/client.js +116 -0
- package/packages/wrapper/dist/client.js.map +1 -1
- package/packages/wrapper/dist/index.d.ts +3 -0
- package/packages/wrapper/dist/index.d.ts.map +1 -1
- package/packages/wrapper/dist/index.js +6 -0
- package/packages/wrapper/dist/index.js.map +1 -1
- package/packages/wrapper/dist/opencode-api.d.ts +106 -0
- package/packages/wrapper/dist/opencode-api.d.ts.map +1 -0
- package/packages/wrapper/dist/opencode-api.js +219 -0
- package/packages/wrapper/dist/opencode-api.js.map +1 -0
- package/packages/wrapper/dist/opencode-wrapper.d.ts +157 -0
- package/packages/wrapper/dist/opencode-wrapper.d.ts.map +1 -0
- package/packages/wrapper/dist/opencode-wrapper.js +414 -0
- package/packages/wrapper/dist/opencode-wrapper.js.map +1 -0
- package/packages/wrapper/dist/relay-pty-orchestrator.d.ts.map +1 -1
- package/packages/wrapper/dist/relay-pty-orchestrator.js +18 -0
- package/packages/wrapper/dist/relay-pty-orchestrator.js.map +1 -1
- package/packages/wrapper/dist/wrapper-events.d.ts +489 -0
- package/packages/wrapper/dist/wrapper-events.d.ts.map +1 -0
- package/packages/wrapper/dist/wrapper-events.js +252 -0
- package/packages/wrapper/dist/wrapper-events.js.map +1 -0
- package/packages/wrapper/package.json +7 -6
- package/packages/wrapper/src/base-wrapper.ts +23 -7
- package/packages/wrapper/src/client.test.ts +92 -3
- package/packages/wrapper/src/client.ts +163 -0
- package/packages/wrapper/src/index.ts +29 -0
- package/packages/wrapper/src/opencode-api.test.ts +292 -0
- package/packages/wrapper/src/opencode-api.ts +285 -0
- package/packages/wrapper/src/opencode-wrapper.ts +513 -0
- package/packages/wrapper/src/relay-pty-orchestrator.test.ts +176 -0
- package/packages/wrapper/src/relay-pty-orchestrator.ts +20 -0
- package/packages/wrapper/src/wrapper-events.ts +395 -0
|
@@ -57,6 +57,13 @@ import {
|
|
|
57
57
|
|
|
58
58
|
const MAX_SOCKET_PATH_LENGTH = 107;
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Maximum size for output buffers (rawBuffer, outputBuffer) in bytes.
|
|
62
|
+
* Prevents RangeError: Invalid string length when agents produce lots of output.
|
|
63
|
+
* Set to 10MB - enough to capture context but won't exhaust memory.
|
|
64
|
+
*/
|
|
65
|
+
const MAX_OUTPUT_BUFFER_SIZE = 10 * 1024 * 1024; // 10MB
|
|
66
|
+
|
|
60
67
|
function hashWorkspaceId(workspaceId: string): string {
|
|
61
68
|
return createHash('sha256').update(workspaceId).digest('hex').slice(0, 12);
|
|
62
69
|
}
|
|
@@ -956,6 +963,19 @@ export class RelayPtyOrchestrator extends BaseWrapper {
|
|
|
956
963
|
this.outputBuffer += data;
|
|
957
964
|
this.hasReceivedOutput = true;
|
|
958
965
|
|
|
966
|
+
// Trim buffers if they exceed max size to prevent RangeError: Invalid string length
|
|
967
|
+
// Keep the most recent output (tail) as it's more relevant for pattern matching
|
|
968
|
+
if (this.rawBuffer.length > MAX_OUTPUT_BUFFER_SIZE) {
|
|
969
|
+
const trimAmount = this.rawBuffer.length - MAX_OUTPUT_BUFFER_SIZE;
|
|
970
|
+
this.rawBuffer = this.rawBuffer.slice(-MAX_OUTPUT_BUFFER_SIZE);
|
|
971
|
+
// Adjust lastParsedLength to stay in sync with the trimmed buffer
|
|
972
|
+
// This ensures parseRelayCommands() doesn't skip content or re-parse old content
|
|
973
|
+
this.lastParsedLength = Math.max(0, this.lastParsedLength - trimAmount);
|
|
974
|
+
}
|
|
975
|
+
if (this.outputBuffer.length > MAX_OUTPUT_BUFFER_SIZE) {
|
|
976
|
+
this.outputBuffer = this.outputBuffer.slice(-MAX_OUTPUT_BUFFER_SIZE);
|
|
977
|
+
}
|
|
978
|
+
|
|
959
979
|
// Feed to idle detector
|
|
960
980
|
this.feedIdleDetectorOutput(data);
|
|
961
981
|
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed Event Definitions for Agent Relay Wrapper
|
|
3
|
+
*
|
|
4
|
+
* Inspired by opencode's BusEvent pattern, this provides type-safe event
|
|
5
|
+
* definitions with Zod schema validation. Events can be used for:
|
|
6
|
+
* - Wrapper internal notifications
|
|
7
|
+
* - SDK client subscriptions
|
|
8
|
+
* - OpenAPI spec generation
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { RelayEvent, emitEvent, onEvent } from './wrapper-events.js';
|
|
13
|
+
*
|
|
14
|
+
* // Subscribe to events
|
|
15
|
+
* onEvent(RelayEvent.AgentConnected, (event) => {
|
|
16
|
+
* console.log(`Agent ${event.properties.agentName} connected`);
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Emit events
|
|
20
|
+
* emitEvent(RelayEvent.AgentConnected, {
|
|
21
|
+
* agentName: 'MyAgent',
|
|
22
|
+
* connectionId: 'abc123',
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { z } from 'zod';
|
|
28
|
+
import { EventEmitter } from 'node:events';
|
|
29
|
+
|
|
30
|
+
// =========================================================================
|
|
31
|
+
// Event Definition Factory
|
|
32
|
+
// =========================================================================
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Event definition with type and schema
|
|
36
|
+
*/
|
|
37
|
+
export interface EventDefinition<
|
|
38
|
+
Type extends string = string,
|
|
39
|
+
Schema extends z.ZodType = z.ZodType
|
|
40
|
+
> {
|
|
41
|
+
type: Type;
|
|
42
|
+
schema: Schema;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Define a typed event with Zod schema validation
|
|
47
|
+
*/
|
|
48
|
+
export function defineEvent<Type extends string, Schema extends z.ZodType>(
|
|
49
|
+
type: Type,
|
|
50
|
+
schema: Schema
|
|
51
|
+
): EventDefinition<Type, Schema> {
|
|
52
|
+
return { type, schema };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Infer the properties type from an event definition
|
|
57
|
+
*/
|
|
58
|
+
export type EventProperties<E extends EventDefinition> = z.infer<E['schema']>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Event payload with type and properties
|
|
62
|
+
*/
|
|
63
|
+
export interface EventPayload<E extends EventDefinition = EventDefinition> {
|
|
64
|
+
type: E['type'];
|
|
65
|
+
properties: EventProperties<E>;
|
|
66
|
+
timestamp: number;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// =========================================================================
|
|
70
|
+
// Daemon Event Definitions
|
|
71
|
+
// =========================================================================
|
|
72
|
+
|
|
73
|
+
export namespace RelayEvent {
|
|
74
|
+
// --- Agent Lifecycle Events ---
|
|
75
|
+
|
|
76
|
+
export const AgentConnected = defineEvent(
|
|
77
|
+
'daemon.agent.connected',
|
|
78
|
+
z.object({
|
|
79
|
+
agentName: z.string(),
|
|
80
|
+
connectionId: z.string(),
|
|
81
|
+
cli: z.string().optional(),
|
|
82
|
+
task: z.string().optional(),
|
|
83
|
+
workingDirectory: z.string().optional(),
|
|
84
|
+
})
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
export const AgentDisconnected = defineEvent(
|
|
88
|
+
'daemon.agent.disconnected',
|
|
89
|
+
z.object({
|
|
90
|
+
agentName: z.string(),
|
|
91
|
+
connectionId: z.string(),
|
|
92
|
+
reason: z.enum(['clean', 'error', 'timeout', 'replaced']).optional(),
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
export const AgentSpawned = defineEvent(
|
|
97
|
+
'daemon.agent.spawned',
|
|
98
|
+
z.object({
|
|
99
|
+
agentName: z.string(),
|
|
100
|
+
parentAgent: z.string(),
|
|
101
|
+
cli: z.string(),
|
|
102
|
+
task: z.string(),
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
export const AgentReleased = defineEvent(
|
|
107
|
+
'daemon.agent.released',
|
|
108
|
+
z.object({
|
|
109
|
+
agentName: z.string(),
|
|
110
|
+
releasedBy: z.string(),
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// --- Message Events ---
|
|
115
|
+
|
|
116
|
+
export const MessageRouted = defineEvent(
|
|
117
|
+
'daemon.message.routed',
|
|
118
|
+
z.object({
|
|
119
|
+
messageId: z.string(),
|
|
120
|
+
from: z.string(),
|
|
121
|
+
to: z.string(),
|
|
122
|
+
kind: z.string().optional(),
|
|
123
|
+
bodyPreview: z.string().optional(),
|
|
124
|
+
})
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
export const MessageDelivered = defineEvent(
|
|
128
|
+
'daemon.message.delivered',
|
|
129
|
+
z.object({
|
|
130
|
+
messageId: z.string(),
|
|
131
|
+
to: z.string(),
|
|
132
|
+
deliverySeq: z.number(),
|
|
133
|
+
})
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
export const MessageFailed = defineEvent(
|
|
137
|
+
'daemon.message.failed',
|
|
138
|
+
z.object({
|
|
139
|
+
messageId: z.string(),
|
|
140
|
+
to: z.string(),
|
|
141
|
+
error: z.string(),
|
|
142
|
+
})
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// --- Channel Events ---
|
|
146
|
+
|
|
147
|
+
export const ChannelJoined = defineEvent(
|
|
148
|
+
'daemon.channel.joined',
|
|
149
|
+
z.object({
|
|
150
|
+
channel: z.string(),
|
|
151
|
+
member: z.string(),
|
|
152
|
+
})
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
export const ChannelLeft = defineEvent(
|
|
156
|
+
'daemon.channel.left',
|
|
157
|
+
z.object({
|
|
158
|
+
channel: z.string(),
|
|
159
|
+
member: z.string(),
|
|
160
|
+
})
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
export const ChannelMessage = defineEvent(
|
|
164
|
+
'daemon.channel.message',
|
|
165
|
+
z.object({
|
|
166
|
+
channel: z.string(),
|
|
167
|
+
from: z.string(),
|
|
168
|
+
bodyPreview: z.string().optional(),
|
|
169
|
+
})
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
// --- Processing State Events ---
|
|
173
|
+
|
|
174
|
+
export const AgentProcessingStarted = defineEvent(
|
|
175
|
+
'daemon.agent.processing.started',
|
|
176
|
+
z.object({
|
|
177
|
+
agentName: z.string(),
|
|
178
|
+
messageId: z.string(),
|
|
179
|
+
})
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
export const AgentProcessingEnded = defineEvent(
|
|
183
|
+
'daemon.agent.processing.ended',
|
|
184
|
+
z.object({
|
|
185
|
+
agentName: z.string(),
|
|
186
|
+
durationMs: z.number().optional(),
|
|
187
|
+
})
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
// --- Shadow Events ---
|
|
191
|
+
|
|
192
|
+
export const ShadowBound = defineEvent(
|
|
193
|
+
'daemon.shadow.bound',
|
|
194
|
+
z.object({
|
|
195
|
+
shadowAgent: z.string(),
|
|
196
|
+
primaryAgent: z.string(),
|
|
197
|
+
speakOn: z.array(z.string()),
|
|
198
|
+
})
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
export const ShadowUnbound = defineEvent(
|
|
202
|
+
'daemon.shadow.unbound',
|
|
203
|
+
z.object({
|
|
204
|
+
shadowAgent: z.string(),
|
|
205
|
+
primaryAgent: z.string(),
|
|
206
|
+
})
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
// --- System Events ---
|
|
210
|
+
|
|
211
|
+
export const DaemonStarted = defineEvent(
|
|
212
|
+
'daemon.system.started',
|
|
213
|
+
z.object({
|
|
214
|
+
socketPath: z.string(),
|
|
215
|
+
version: z.string().optional(),
|
|
216
|
+
})
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
export const DaemonStopped = defineEvent(
|
|
220
|
+
'daemon.system.stopped',
|
|
221
|
+
z.object({
|
|
222
|
+
reason: z.string().optional(),
|
|
223
|
+
})
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
export const RateLimitExceeded = defineEvent(
|
|
227
|
+
'daemon.system.rate_limit_exceeded',
|
|
228
|
+
z.object({
|
|
229
|
+
agentName: z.string(),
|
|
230
|
+
})
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
// --- All event definitions for iteration ---
|
|
234
|
+
|
|
235
|
+
export const all = [
|
|
236
|
+
AgentConnected,
|
|
237
|
+
AgentDisconnected,
|
|
238
|
+
AgentSpawned,
|
|
239
|
+
AgentReleased,
|
|
240
|
+
MessageRouted,
|
|
241
|
+
MessageDelivered,
|
|
242
|
+
MessageFailed,
|
|
243
|
+
ChannelJoined,
|
|
244
|
+
ChannelLeft,
|
|
245
|
+
ChannelMessage,
|
|
246
|
+
AgentProcessingStarted,
|
|
247
|
+
AgentProcessingEnded,
|
|
248
|
+
ShadowBound,
|
|
249
|
+
ShadowUnbound,
|
|
250
|
+
DaemonStarted,
|
|
251
|
+
DaemonStopped,
|
|
252
|
+
RateLimitExceeded,
|
|
253
|
+
] as const;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// =========================================================================
|
|
257
|
+
// Event Bus
|
|
258
|
+
// =========================================================================
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Type-safe event bus for daemon events
|
|
262
|
+
*/
|
|
263
|
+
class RelayEventBus extends EventEmitter {
|
|
264
|
+
private static instance: RelayEventBus;
|
|
265
|
+
|
|
266
|
+
private constructor() {
|
|
267
|
+
super();
|
|
268
|
+
this.setMaxListeners(100); // Allow many subscribers
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
static getInstance(): RelayEventBus {
|
|
272
|
+
if (!RelayEventBus.instance) {
|
|
273
|
+
RelayEventBus.instance = new RelayEventBus();
|
|
274
|
+
}
|
|
275
|
+
return RelayEventBus.instance;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Emit a typed event
|
|
280
|
+
*/
|
|
281
|
+
emitEvent<E extends EventDefinition>(
|
|
282
|
+
definition: E,
|
|
283
|
+
properties: EventProperties<E>
|
|
284
|
+
): void {
|
|
285
|
+
const payload: EventPayload<E> = {
|
|
286
|
+
type: definition.type,
|
|
287
|
+
properties,
|
|
288
|
+
timestamp: Date.now(),
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// Validate properties against schema
|
|
292
|
+
const result = definition.schema.safeParse(properties);
|
|
293
|
+
if (!result.success) {
|
|
294
|
+
console.error(`[RelayEventBus] Invalid event properties for ${definition.type}:`, result.error);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Emit to specific subscribers and wildcard subscribers
|
|
299
|
+
this.emit(definition.type, payload);
|
|
300
|
+
this.emit('*', payload);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Subscribe to a typed event
|
|
305
|
+
*/
|
|
306
|
+
onEvent<E extends EventDefinition>(
|
|
307
|
+
definition: E,
|
|
308
|
+
callback: (event: EventPayload<E>) => void
|
|
309
|
+
): () => void {
|
|
310
|
+
this.on(definition.type, callback);
|
|
311
|
+
return () => this.off(definition.type, callback);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Subscribe to all events (wildcard)
|
|
316
|
+
*/
|
|
317
|
+
onAnyEvent(callback: (event: EventPayload) => void): () => void {
|
|
318
|
+
this.on('*', callback);
|
|
319
|
+
return () => this.off('*', callback);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Subscribe to an event once
|
|
324
|
+
*/
|
|
325
|
+
onceEvent<E extends EventDefinition>(
|
|
326
|
+
definition: E,
|
|
327
|
+
callback: (event: EventPayload<E>) => void
|
|
328
|
+
): void {
|
|
329
|
+
this.once(definition.type, callback);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// =========================================================================
|
|
334
|
+
// Exports
|
|
335
|
+
// =========================================================================
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Global daemon event bus instance
|
|
339
|
+
*/
|
|
340
|
+
export const relayEventBus = RelayEventBus.getInstance();
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Emit a daemon event
|
|
344
|
+
*/
|
|
345
|
+
export function emitEvent<E extends EventDefinition>(
|
|
346
|
+
definition: E,
|
|
347
|
+
properties: EventProperties<E>
|
|
348
|
+
): void {
|
|
349
|
+
relayEventBus.emitEvent(definition, properties);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Subscribe to a daemon event
|
|
354
|
+
*/
|
|
355
|
+
export function onEvent<E extends EventDefinition>(
|
|
356
|
+
definition: E,
|
|
357
|
+
callback: (event: EventPayload<E>) => void
|
|
358
|
+
): () => void {
|
|
359
|
+
return relayEventBus.onEvent(definition, callback);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Subscribe to all daemon events
|
|
364
|
+
*/
|
|
365
|
+
export function onAnyEvent(callback: (event: EventPayload) => void): () => void {
|
|
366
|
+
return relayEventBus.onAnyEvent(callback);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// =========================================================================
|
|
370
|
+
// OpenAPI Schema Generation
|
|
371
|
+
// =========================================================================
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Generate OpenAPI-compatible schema for all daemon events
|
|
375
|
+
* This can be used to auto-generate SDK types
|
|
376
|
+
*/
|
|
377
|
+
export function generateEventSchemas(): Record<string, unknown> {
|
|
378
|
+
const schemas: Record<string, unknown> = {};
|
|
379
|
+
|
|
380
|
+
for (const definition of RelayEvent.all) {
|
|
381
|
+
// Extract JSON Schema from Zod schema
|
|
382
|
+
// Note: This is a simplified version - production use should use zod-to-json-schema
|
|
383
|
+
schemas[definition.type] = {
|
|
384
|
+
type: 'object',
|
|
385
|
+
properties: {
|
|
386
|
+
type: { type: 'string', const: definition.type },
|
|
387
|
+
properties: definition.schema._def, // Simplified - use zod-to-json-schema for production
|
|
388
|
+
timestamp: { type: 'number' },
|
|
389
|
+
},
|
|
390
|
+
required: ['type', 'properties', 'timestamp'],
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return schemas;
|
|
395
|
+
}
|