agent-relay-server 0.8.1 → 0.10.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 +12 -14
- package/package.json +18 -1
- package/public/index.html +979 -2575
- package/public/manifest.webmanifest +6 -6
- package/public/sw.js +16 -10
- package/recipes/code-review.yaml +26 -0
- package/recipes/debug.yaml +20 -0
- package/recipes/feature.yaml +26 -0
- package/recipes/refactor.yaml +20 -0
- package/recipes/test.yaml +20 -0
- package/runner/src/adapter.ts +69 -0
- package/runner/src/config.ts +144 -0
- package/scripts/orchestrator-spawn-smoke.ts +2 -9
- package/src/agent-spawn.ts +2 -94
- package/src/automations.ts +774 -0
- package/src/bus-outbox.ts +75 -0
- package/src/bus.ts +439 -0
- package/src/cli.ts +251 -5
- package/src/commands-db.ts +160 -0
- package/src/config.ts +2 -1
- package/src/connectors.ts +29 -9
- package/src/daemon.ts +1 -0
- package/src/db.ts +363 -36
- package/src/events.ts +33 -0
- package/src/index.ts +100 -5
- package/src/recipe-db.ts +163 -0
- package/src/recipe-loader.ts +100 -0
- package/src/recipe-runner.ts +206 -0
- package/src/recipe-validator.ts +85 -0
- package/src/routes.ts +661 -158
- package/src/security.ts +128 -2
- package/src/sse.ts +45 -28
- package/src/token-db.ts +96 -0
- package/src/types.ts +1 -488
- package/src/upgrade.ts +14 -28
- package/public/dashboard/actions.js +0 -819
- package/public/dashboard/api.js +0 -336
- package/public/dashboard/app.js +0 -34
- package/public/dashboard/charts.js +0 -128
- package/public/dashboard/computed.js +0 -693
- package/public/dashboard/constants.js +0 -28
- package/public/dashboard/display.js +0 -345
- package/public/dashboard/state.js +0 -129
- package/public/dashboard/utils.js +0 -207
package/src/types.ts
CHANGED
|
@@ -1,488 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
export interface AgentCard {
|
|
4
|
-
id: string;
|
|
5
|
-
name: string;
|
|
6
|
-
kind: AgentKind;
|
|
7
|
-
label?: string; // human-friendly alias; acts as a fan-out target ("label:foo")
|
|
8
|
-
tags: string[];
|
|
9
|
-
machine?: string;
|
|
10
|
-
rig?: string;
|
|
11
|
-
capabilities: string[];
|
|
12
|
-
ready: boolean;
|
|
13
|
-
status: "online" | "idle" | "busy" | "offline";
|
|
14
|
-
instanceId?: string;
|
|
15
|
-
epoch: number;
|
|
16
|
-
meta?: Record<string, unknown>;
|
|
17
|
-
lastSeen: number;
|
|
18
|
-
createdAt: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export type MessageKind =
|
|
22
|
-
| "chat"
|
|
23
|
-
| "channel.event"
|
|
24
|
-
| "task"
|
|
25
|
-
| "pair"
|
|
26
|
-
| "control"
|
|
27
|
-
| "system";
|
|
28
|
-
|
|
29
|
-
export interface Message {
|
|
30
|
-
id: number;
|
|
31
|
-
from: string;
|
|
32
|
-
to: string; // agent-id | "tag:<name>" | "broadcast" | "cap:<name>"
|
|
33
|
-
kind: MessageKind;
|
|
34
|
-
channel?: string;
|
|
35
|
-
subject?: string;
|
|
36
|
-
body: string;
|
|
37
|
-
threadId?: number;
|
|
38
|
-
replyTo?: number;
|
|
39
|
-
claimable?: boolean;
|
|
40
|
-
claimedBy?: string;
|
|
41
|
-
claimedAt?: number;
|
|
42
|
-
claimExpiresAt?: number;
|
|
43
|
-
idempotencyKey?: string;
|
|
44
|
-
payload: Record<string, unknown>;
|
|
45
|
-
meta?: Record<string, unknown>;
|
|
46
|
-
readBy: string[];
|
|
47
|
-
createdAt: number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface SendMessageInput {
|
|
51
|
-
from: string;
|
|
52
|
-
to: string;
|
|
53
|
-
kind?: MessageKind;
|
|
54
|
-
channel?: string;
|
|
55
|
-
subject?: string;
|
|
56
|
-
body: string;
|
|
57
|
-
replyTo?: number;
|
|
58
|
-
claimable?: boolean;
|
|
59
|
-
idempotencyKey?: string;
|
|
60
|
-
payload?: Record<string, unknown>;
|
|
61
|
-
meta?: Record<string, unknown>;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export type ConnectorKind = "channel" | "event" | "provider" | "orchestrator";
|
|
65
|
-
export type ConnectorAction = "install" | "uninstall" | "enable" | "disable" | "start" | "stop" | "restart" | "status" | "doctor";
|
|
66
|
-
|
|
67
|
-
export interface ConnectorManifest {
|
|
68
|
-
schema: "agent-relay.connector.v1";
|
|
69
|
-
id: string;
|
|
70
|
-
kind: ConnectorKind;
|
|
71
|
-
packageName?: string;
|
|
72
|
-
binary: string;
|
|
73
|
-
displayName: string;
|
|
74
|
-
description?: string;
|
|
75
|
-
version: string;
|
|
76
|
-
capabilities: string[];
|
|
77
|
-
commands: Partial<Record<ConnectorAction, string[]>>;
|
|
78
|
-
configSchema?: Record<string, unknown>;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
interface ConnectorRuntime {
|
|
82
|
-
installed: boolean;
|
|
83
|
-
enabled?: boolean;
|
|
84
|
-
running?: boolean;
|
|
85
|
-
status?: "ok" | "warn" | "error" | "unknown";
|
|
86
|
-
detail?: string;
|
|
87
|
-
updatedAt?: string;
|
|
88
|
-
raw?: unknown;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export interface ConnectorSummary {
|
|
92
|
-
id: string;
|
|
93
|
-
kind: ConnectorKind;
|
|
94
|
-
displayName: string;
|
|
95
|
-
description?: string;
|
|
96
|
-
version: string;
|
|
97
|
-
packageName?: string;
|
|
98
|
-
binary: string;
|
|
99
|
-
capabilities: string[];
|
|
100
|
-
registryPath: string;
|
|
101
|
-
manifest: ConnectorManifest;
|
|
102
|
-
config?: Record<string, unknown>;
|
|
103
|
-
state?: Record<string, unknown>;
|
|
104
|
-
runtime: ConnectorRuntime;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export interface ConnectorActionResult {
|
|
108
|
-
connectorId: string;
|
|
109
|
-
action: ConnectorAction;
|
|
110
|
-
command?: string[];
|
|
111
|
-
ok: boolean;
|
|
112
|
-
exitCode?: number | null;
|
|
113
|
-
stdout?: string;
|
|
114
|
-
stderr?: string;
|
|
115
|
-
parsed?: unknown;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export type PairStatus = "pending" | "active" | "ended" | "rejected" | "expired";
|
|
119
|
-
|
|
120
|
-
export interface PairSession {
|
|
121
|
-
id: string;
|
|
122
|
-
requesterId: string;
|
|
123
|
-
targetId: string;
|
|
124
|
-
status: PairStatus;
|
|
125
|
-
objective?: string;
|
|
126
|
-
createdAt: number;
|
|
127
|
-
updatedAt: number;
|
|
128
|
-
expiresAt: number;
|
|
129
|
-
acceptedAt?: number;
|
|
130
|
-
endedAt?: number;
|
|
131
|
-
endedBy?: string;
|
|
132
|
-
lastMessageAt?: number;
|
|
133
|
-
meta: Record<string, unknown>;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export interface CreatePairInput {
|
|
137
|
-
from: string;
|
|
138
|
-
target: string;
|
|
139
|
-
objective?: string;
|
|
140
|
-
ttlMs?: number;
|
|
141
|
-
meta?: Record<string, unknown>;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export interface PairActionInput {
|
|
145
|
-
agentId: string;
|
|
146
|
-
reason?: string;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export interface PairMessageInput {
|
|
150
|
-
from: string;
|
|
151
|
-
body: string;
|
|
152
|
-
subject?: string;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export interface PollQuery {
|
|
156
|
-
for: string; // agent-id
|
|
157
|
-
since?: number; // unix ms (createdAt cursor)
|
|
158
|
-
sinceId?: number; // monotonic message id cursor (preferred — avoids same-ms collisions)
|
|
159
|
-
unread?: boolean;
|
|
160
|
-
channel?: string;
|
|
161
|
-
limit?: number;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export interface RegisterAgentInput {
|
|
165
|
-
id: string;
|
|
166
|
-
name: string;
|
|
167
|
-
kind?: AgentKind;
|
|
168
|
-
label?: string | null;
|
|
169
|
-
tags?: string[];
|
|
170
|
-
machine?: string;
|
|
171
|
-
rig?: string;
|
|
172
|
-
capabilities?: string[];
|
|
173
|
-
ready?: boolean;
|
|
174
|
-
status?: AgentCard["status"];
|
|
175
|
-
instanceId?: string;
|
|
176
|
-
meta?: Record<string, unknown>;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export interface AgentSessionGuard {
|
|
180
|
-
instanceId?: string;
|
|
181
|
-
epoch?: number;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export type TaskSeverity = "info" | "warning" | "critical";
|
|
185
|
-
export type TaskStatus =
|
|
186
|
-
| "open"
|
|
187
|
-
| "claimed"
|
|
188
|
-
| "in_progress"
|
|
189
|
-
| "blocked"
|
|
190
|
-
| "done"
|
|
191
|
-
| "failed"
|
|
192
|
-
| "canceled";
|
|
193
|
-
|
|
194
|
-
export interface Task {
|
|
195
|
-
id: number;
|
|
196
|
-
source: string;
|
|
197
|
-
title: string;
|
|
198
|
-
body: string;
|
|
199
|
-
severity: TaskSeverity;
|
|
200
|
-
status: TaskStatus;
|
|
201
|
-
target: string;
|
|
202
|
-
channel?: string;
|
|
203
|
-
dedupeKey?: string;
|
|
204
|
-
externalUrl?: string;
|
|
205
|
-
occurrenceCount: number;
|
|
206
|
-
claimedBy?: string;
|
|
207
|
-
claimedAt?: number;
|
|
208
|
-
claimExpiresAt?: number;
|
|
209
|
-
messageId?: number;
|
|
210
|
-
result?: string;
|
|
211
|
-
metadata: Record<string, unknown>;
|
|
212
|
-
createdAt: number;
|
|
213
|
-
updatedAt: number;
|
|
214
|
-
lastSeenAt: number;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
export interface TaskEvent {
|
|
218
|
-
id: number;
|
|
219
|
-
taskId: number;
|
|
220
|
-
source: string;
|
|
221
|
-
type: string;
|
|
222
|
-
severity: TaskSeverity;
|
|
223
|
-
title: string;
|
|
224
|
-
body: string;
|
|
225
|
-
metadata: Record<string, unknown>;
|
|
226
|
-
createdAt: number;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
export interface IntegrationEventInput {
|
|
230
|
-
source?: string;
|
|
231
|
-
type?: string;
|
|
232
|
-
severity?: TaskSeverity;
|
|
233
|
-
status?: TaskStatus | "resolved";
|
|
234
|
-
title: string;
|
|
235
|
-
body: string;
|
|
236
|
-
target: string;
|
|
237
|
-
channel?: string;
|
|
238
|
-
dedupeKey?: string;
|
|
239
|
-
externalUrl?: string;
|
|
240
|
-
metadata?: Record<string, unknown>;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export interface IntegrationTaskStats {
|
|
244
|
-
source: string;
|
|
245
|
-
tasks: number;
|
|
246
|
-
openTasks: number;
|
|
247
|
-
waitingTasks: number;
|
|
248
|
-
failedTasks: number;
|
|
249
|
-
lastSeenAt?: number;
|
|
250
|
-
lastUpdatedAt?: number;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
export interface IntegrationSummary {
|
|
254
|
-
name: string;
|
|
255
|
-
configured: boolean;
|
|
256
|
-
observed: boolean;
|
|
257
|
-
scopes: string[];
|
|
258
|
-
targets: string[];
|
|
259
|
-
channels: string[];
|
|
260
|
-
callbackHost?: string;
|
|
261
|
-
callbackConfigured: boolean;
|
|
262
|
-
rateLimit: {
|
|
263
|
-
limitPerMinute: number;
|
|
264
|
-
currentWindowCount: number;
|
|
265
|
-
windowStartedAt?: number;
|
|
266
|
-
};
|
|
267
|
-
taskStats: IntegrationTaskStats;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
export type ChannelDirection = "inbound" | "outbound" | "bidirectional";
|
|
271
|
-
|
|
272
|
-
export type ChannelRouteTarget =
|
|
273
|
-
| { type: "agent"; id: string }
|
|
274
|
-
| { type: "label"; id: string }
|
|
275
|
-
| { type: "tag"; id: string }
|
|
276
|
-
| { type: "capability"; id: string }
|
|
277
|
-
| { type: "broadcast" }
|
|
278
|
-
| { type: "orchestrator"; id: string };
|
|
279
|
-
|
|
280
|
-
export type ChannelBindingMode = "exclusive" | "claimable" | "broadcast";
|
|
281
|
-
|
|
282
|
-
export interface ChannelBinding {
|
|
283
|
-
id: string;
|
|
284
|
-
channelId: string;
|
|
285
|
-
conversationId?: string;
|
|
286
|
-
target: ChannelRouteTarget;
|
|
287
|
-
mode: ChannelBindingMode;
|
|
288
|
-
priority: number;
|
|
289
|
-
createdAt: number;
|
|
290
|
-
updatedAt: number;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
export interface ChannelTargetHealth {
|
|
294
|
-
status: "ok" | "warning" | "error";
|
|
295
|
-
detail: string;
|
|
296
|
-
target: ChannelRouteTarget;
|
|
297
|
-
matches: Array<{
|
|
298
|
-
id: string;
|
|
299
|
-
name: string;
|
|
300
|
-
status: AgentCard["status"];
|
|
301
|
-
ready: boolean;
|
|
302
|
-
lastSeen: number;
|
|
303
|
-
label?: string;
|
|
304
|
-
tags: string[];
|
|
305
|
-
capabilities: string[];
|
|
306
|
-
}>;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
export interface ChannelSummary {
|
|
310
|
-
id: string;
|
|
311
|
-
name: string;
|
|
312
|
-
type: string;
|
|
313
|
-
transport: string;
|
|
314
|
-
agentId: string;
|
|
315
|
-
accountId: string;
|
|
316
|
-
status: AgentCard["status"];
|
|
317
|
-
ready: boolean;
|
|
318
|
-
direction: ChannelDirection;
|
|
319
|
-
target?: string;
|
|
320
|
-
binding?: ChannelBinding;
|
|
321
|
-
targetHealth?: ChannelTargetHealth;
|
|
322
|
-
topicChannels: string[];
|
|
323
|
-
capabilities: string[];
|
|
324
|
-
tags: string[];
|
|
325
|
-
lastSeen: number;
|
|
326
|
-
meta?: Record<string, unknown>;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
export interface TaskStatusInput {
|
|
330
|
-
status: TaskStatus;
|
|
331
|
-
agentId?: string;
|
|
332
|
-
instanceId?: string;
|
|
333
|
-
epoch?: number;
|
|
334
|
-
result?: string;
|
|
335
|
-
body?: string;
|
|
336
|
-
metadata?: Record<string, unknown>;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
export interface InboxThreadState {
|
|
340
|
-
operatorId: string;
|
|
341
|
-
peerId: string;
|
|
342
|
-
readCursorMessageId?: number;
|
|
343
|
-
archivedAtMessageId?: number;
|
|
344
|
-
updatedAt: number;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
export interface InboxDraft {
|
|
348
|
-
operatorId: string;
|
|
349
|
-
peerId: string;
|
|
350
|
-
body: string;
|
|
351
|
-
subject?: string;
|
|
352
|
-
channel?: string;
|
|
353
|
-
updatedAt: number;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
export interface InboxState {
|
|
357
|
-
operatorId: string;
|
|
358
|
-
threads: InboxThreadState[];
|
|
359
|
-
drafts: InboxDraft[];
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
export type ActivityKind = "message" | "reply" | "question" | "operator" | "pair" | "task" | "state";
|
|
363
|
-
|
|
364
|
-
export interface ActivityEvent {
|
|
365
|
-
id: number;
|
|
366
|
-
operatorId?: string;
|
|
367
|
-
clientId?: string;
|
|
368
|
-
kind: ActivityKind;
|
|
369
|
-
title: string;
|
|
370
|
-
body?: string;
|
|
371
|
-
meta?: string;
|
|
372
|
-
icon?: string;
|
|
373
|
-
view?: string;
|
|
374
|
-
peer?: string;
|
|
375
|
-
messageId?: number;
|
|
376
|
-
pairId?: string;
|
|
377
|
-
taskId?: number;
|
|
378
|
-
agentId?: string;
|
|
379
|
-
metadata: Record<string, unknown>;
|
|
380
|
-
createdAt: number;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
export interface ActivityEventInput {
|
|
384
|
-
operatorId?: string;
|
|
385
|
-
clientId?: string;
|
|
386
|
-
kind: ActivityKind;
|
|
387
|
-
title: string;
|
|
388
|
-
body?: string;
|
|
389
|
-
meta?: string;
|
|
390
|
-
icon?: string;
|
|
391
|
-
view?: string;
|
|
392
|
-
peer?: string;
|
|
393
|
-
messageId?: number;
|
|
394
|
-
pairId?: string;
|
|
395
|
-
taskId?: number;
|
|
396
|
-
agentId?: string;
|
|
397
|
-
metadata?: Record<string, unknown>;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// --- Orchestrators ---
|
|
401
|
-
|
|
402
|
-
export type OrchestratorStatus = "online" | "offline";
|
|
403
|
-
export type SpawnProvider = "claude" | "codex";
|
|
404
|
-
export type SpawnApprovalMode = "open" | "guarded" | "read-only";
|
|
405
|
-
|
|
406
|
-
export interface Orchestrator {
|
|
407
|
-
id: string;
|
|
408
|
-
hostname: string;
|
|
409
|
-
status: OrchestratorStatus;
|
|
410
|
-
agentId: string; // relay agent id for messaging
|
|
411
|
-
providers: SpawnProvider[];
|
|
412
|
-
baseDir: string;
|
|
413
|
-
envKeys: string[]; // names only, never values
|
|
414
|
-
version?: string;
|
|
415
|
-
protocolVersion?: number;
|
|
416
|
-
gitSha?: string;
|
|
417
|
-
health?: OrchestratorHealth;
|
|
418
|
-
meta: Record<string, unknown>;
|
|
419
|
-
managedAgents: ManagedAgent[];
|
|
420
|
-
lastSeen: number;
|
|
421
|
-
createdAt: number;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
export interface OrchestratorHealth {
|
|
425
|
-
status: "ok" | "warn" | "error";
|
|
426
|
-
restartRequired: boolean;
|
|
427
|
-
issues: Array<{
|
|
428
|
-
code: "missing-version" | "outdated" | "protocol-mismatch" | "restart-required";
|
|
429
|
-
detail: string;
|
|
430
|
-
}>;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
export interface ManagedAgent {
|
|
434
|
-
agentId: string;
|
|
435
|
-
provider: SpawnProvider;
|
|
436
|
-
tmuxSession: string;
|
|
437
|
-
cwd: string;
|
|
438
|
-
label?: string;
|
|
439
|
-
approvalMode: SpawnApprovalMode;
|
|
440
|
-
pid?: number;
|
|
441
|
-
startedAt: number;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
export interface RegisterOrchestratorInput {
|
|
445
|
-
id: string;
|
|
446
|
-
hostname: string;
|
|
447
|
-
providers: SpawnProvider[];
|
|
448
|
-
baseDir: string;
|
|
449
|
-
envKeys?: string[];
|
|
450
|
-
version?: string;
|
|
451
|
-
protocolVersion?: number;
|
|
452
|
-
gitSha?: string;
|
|
453
|
-
meta?: Record<string, unknown>;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
export interface OrchestratorSpawnInput {
|
|
457
|
-
provider: SpawnProvider;
|
|
458
|
-
cwd?: string;
|
|
459
|
-
label?: string;
|
|
460
|
-
approvalMode?: SpawnApprovalMode;
|
|
461
|
-
prompt?: string;
|
|
462
|
-
env?: Record<string, string>;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
export interface OrchestratorSpawnResult {
|
|
466
|
-
orchestratorId: string;
|
|
467
|
-
provider: SpawnProvider;
|
|
468
|
-
tmuxSession: string;
|
|
469
|
-
cwd: string;
|
|
470
|
-
label?: string;
|
|
471
|
-
approvalMode: SpawnApprovalMode;
|
|
472
|
-
pid?: number;
|
|
473
|
-
startedAt: number;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
export interface HealthCheck {
|
|
477
|
-
name: string;
|
|
478
|
-
status: "ok" | "warn" | "error";
|
|
479
|
-
detail?: string;
|
|
480
|
-
count?: number;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
export interface HealthReport {
|
|
484
|
-
status: "ok" | "degraded" | "error";
|
|
485
|
-
version: string;
|
|
486
|
-
generatedAt: number;
|
|
487
|
-
checks: HealthCheck[];
|
|
488
|
-
}
|
|
1
|
+
export * from "agent-relay-sdk/types";
|
package/src/upgrade.ts
CHANGED
|
@@ -28,6 +28,7 @@ export type UpgradeSnapshot = {
|
|
|
28
28
|
targetVersion: string;
|
|
29
29
|
serverPackage?: InstalledPackage;
|
|
30
30
|
codexPackage?: InstalledPackage;
|
|
31
|
+
runnerPackage?: InstalledPackage;
|
|
31
32
|
orchestratorPackage?: InstalledPackage;
|
|
32
33
|
codexCopiedPackage?: InstalledPackage;
|
|
33
34
|
claudePluginInstalls: ClaudePluginInstall[];
|
|
@@ -71,9 +72,9 @@ export async function detectUpgradeSnapshot(options: UpgradeOptions = {}): Promi
|
|
|
71
72
|
const codexCopiedPackage = readPackageVersion(join(homeDir(), ".agent-relay", "codex", "package", "package.json"));
|
|
72
73
|
const claudePluginInstalls = readClaudePluginInstalls(join(homeDir(), ".claude", "plugins", "installed_plugins.json"));
|
|
73
74
|
|
|
74
|
-
const packageManager = bunPackages.has("agent-relay-server") || bunPackages.has("agent-relay-codex") || bunPackages.has("agent-relay-orchestrator")
|
|
75
|
+
const packageManager = bunPackages.has("agent-relay-server") || bunPackages.has("agent-relay-runner") || bunPackages.has("agent-relay-codex") || bunPackages.has("agent-relay-orchestrator")
|
|
75
76
|
? "bun"
|
|
76
|
-
: npmPackages.has("agent-relay-server") || npmPackages.has("agent-relay-codex") || npmPackages.has("agent-relay-orchestrator")
|
|
77
|
+
: npmPackages.has("agent-relay-server") || npmPackages.has("agent-relay-runner") || npmPackages.has("agent-relay-codex") || npmPackages.has("agent-relay-orchestrator")
|
|
77
78
|
? "npm"
|
|
78
79
|
: commandExists("bun")
|
|
79
80
|
? "bun"
|
|
@@ -85,12 +86,13 @@ export async function detectUpgradeSnapshot(options: UpgradeOptions = {}): Promi
|
|
|
85
86
|
targetVersion,
|
|
86
87
|
serverPackage: installedPackage("agent-relay-server", bunPackages, npmPackages),
|
|
87
88
|
codexPackage: installedPackage("agent-relay-codex", bunPackages, npmPackages),
|
|
89
|
+
runnerPackage: installedPackage("agent-relay-runner", bunPackages, npmPackages),
|
|
88
90
|
orchestratorPackage: installedPackage("agent-relay-orchestrator", bunPackages, npmPackages),
|
|
89
91
|
codexCopiedPackage: codexCopiedPackage
|
|
90
92
|
? { version: codexCopiedPackage, source: "copied", path: join(homeDir(), ".agent-relay", "codex", "package") }
|
|
91
93
|
: undefined,
|
|
92
94
|
claudePluginInstalls,
|
|
93
|
-
hasCodexCommand: commandExists("
|
|
95
|
+
hasCodexCommand: commandExists("codex-relay") || commandExists("agent-relay-runner"),
|
|
94
96
|
hasOrchestratorCommand: commandExists("agent-relay-orchestrator"),
|
|
95
97
|
hasClaudeCommand: commandExists("claude"),
|
|
96
98
|
hasSystemdUserService: hasSystemdUserService("agent-relay.service"),
|
|
@@ -108,6 +110,7 @@ export function createUpgradePlan(snapshot: UpgradeSnapshot, options: UpgradeOpt
|
|
|
108
110
|
const codexRequested = providerSet.has("all") || providerSet.has("codex") || (providerSet.has("auto") && isCodexDetected(snapshot));
|
|
109
111
|
const claudeRequested = providerSet.has("all") || providerSet.has("claude") || (providerSet.has("auto") && isClaudeRelayDetected(snapshot));
|
|
110
112
|
const orchestratorRequested = providerSet.has("all") || providerSet.has("orchestrator") || (providerSet.has("auto") && isOrchestratorDetected(snapshot));
|
|
113
|
+
const runnerRequested = codexRequested || claudeRequested;
|
|
111
114
|
const actions: UpgradeAction[] = [];
|
|
112
115
|
const warnings: string[] = [];
|
|
113
116
|
|
|
@@ -115,7 +118,7 @@ export function createUpgradePlan(snapshot: UpgradeSnapshot, options: UpgradeOpt
|
|
|
115
118
|
warnings.push("No supported global package manager found. Install Bun or npm, then rerun `agent-relay upgrade`.");
|
|
116
119
|
} else {
|
|
117
120
|
const packages = [`agent-relay-server@${targetVersion}`];
|
|
118
|
-
if (
|
|
121
|
+
if (runnerRequested) packages.push(`agent-relay-runner@${targetVersion}`);
|
|
119
122
|
if (orchestratorRequested) packages.push(`agent-relay-orchestrator@${targetVersion}`);
|
|
120
123
|
const command = snapshot.packageManager === "bun"
|
|
121
124
|
? ["bun", "add", "-g", ...packages]
|
|
@@ -123,39 +126,21 @@ export function createUpgradePlan(snapshot: UpgradeSnapshot, options: UpgradeOpt
|
|
|
123
126
|
actions.push({
|
|
124
127
|
label: "Upgrade global packages",
|
|
125
128
|
command,
|
|
126
|
-
reason: `Update server${
|
|
129
|
+
reason: `Update server${runnerRequested ? ", provider runner" : ""}${orchestratorRequested ? ", and orchestrator" : ""} packages to ${targetVersion}.`,
|
|
127
130
|
mutates: true,
|
|
128
131
|
});
|
|
129
132
|
}
|
|
130
133
|
|
|
131
|
-
if (codexRequested) {
|
|
132
|
-
actions.push({
|
|
133
|
-
label: "Refresh Codex relay install",
|
|
134
|
-
command: ["agent-relay-codex", "install", "--alias"],
|
|
135
|
-
reason: "Refresh copied Codex package, launcher shims, hooks, and plugin marketplace files.",
|
|
136
|
-
mutates: true,
|
|
137
|
-
});
|
|
138
|
-
} else if (providerSet.has("auto") && !isCodexDetected(snapshot)) {
|
|
134
|
+
if (!codexRequested && providerSet.has("auto") && !isCodexDetected(snapshot)) {
|
|
139
135
|
warnings.push("Codex provider not detected; skipping Codex integration upgrade.");
|
|
140
136
|
}
|
|
141
137
|
|
|
142
138
|
if (claudeRequested) {
|
|
143
|
-
if (snapshot.hasClaudeCommand
|
|
144
|
-
for (const scope of uniqueStrings(snapshot.claudePluginInstalls.map((install) => install.scope || "user"))) {
|
|
145
|
-
actions.push({
|
|
146
|
-
label: `Update Claude plugin (${scope})`,
|
|
147
|
-
command: ["claude", "plugin", "update", "agent-relay@agent-relay", "--scope", scope],
|
|
148
|
-
reason: "Update installed Claude Code Agent Relay plugin.",
|
|
149
|
-
mutates: true,
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
} else if (!snapshot.hasClaudeCommand) {
|
|
139
|
+
if (!snapshot.hasClaudeCommand) {
|
|
153
140
|
warnings.push("Claude Code command not detected; skipping Claude plugin upgrade.");
|
|
154
|
-
} else {
|
|
155
|
-
warnings.push("Claude Code detected, but agent-relay@agent-relay plugin is not installed; skipping Claude plugin upgrade.");
|
|
156
141
|
}
|
|
157
142
|
} else if (providerSet.has("auto") && !isClaudeRelayDetected(snapshot)) {
|
|
158
|
-
warnings.push("Claude
|
|
143
|
+
warnings.push("Claude runner not detected; skipping Claude runner upgrade.");
|
|
159
144
|
}
|
|
160
145
|
|
|
161
146
|
if (!orchestratorRequested && providerSet.has("auto") && !isOrchestratorDetected(snapshot)) {
|
|
@@ -248,6 +233,7 @@ export function formatUpgradePlan(plan: UpgradePlan, options: { dryRun?: boolean
|
|
|
248
233
|
`- server package: ${formatPackage(plan.snapshot.serverPackage)}`,
|
|
249
234
|
`- running server: ${plan.snapshot.runningServerVersion ?? "unknown"}`,
|
|
250
235
|
`- codex package: ${formatPackage(plan.snapshot.codexPackage)}`,
|
|
236
|
+
`- runner package: ${formatPackage(plan.snapshot.runnerPackage)}`,
|
|
251
237
|
`- codex copied package: ${formatPackage(plan.snapshot.codexCopiedPackage)}`,
|
|
252
238
|
`- orchestrator package: ${formatPackage(plan.snapshot.orchestratorPackage)}`,
|
|
253
239
|
`- running orchestrators: ${formatRunningOrchestrators(plan.snapshot.runningOrchestrators)}`,
|
|
@@ -273,11 +259,11 @@ export function formatUpgradePlan(plan: UpgradePlan, options: { dryRun?: boolean
|
|
|
273
259
|
}
|
|
274
260
|
|
|
275
261
|
function isCodexDetected(snapshot: UpgradeSnapshot): boolean {
|
|
276
|
-
return Boolean(snapshot.
|
|
262
|
+
return Boolean(snapshot.runnerPackage || snapshot.codexPackage || snapshot.hasCodexCommand);
|
|
277
263
|
}
|
|
278
264
|
|
|
279
265
|
function isClaudeRelayDetected(snapshot: UpgradeSnapshot): boolean {
|
|
280
|
-
return snapshot.
|
|
266
|
+
return Boolean(snapshot.runnerPackage || snapshot.hasClaudeCommand);
|
|
281
267
|
}
|
|
282
268
|
|
|
283
269
|
function isOrchestratorDetected(snapshot: UpgradeSnapshot): boolean {
|