agentbnb 4.0.2 → 5.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 +31 -2
- package/dist/chunk-AUBHR7HH.js +25 -0
- package/dist/chunk-B5FTAGFN.js +393 -0
- package/dist/{chunk-GGYC5U2Z.js → chunk-BTTL24TZ.js} +29 -91
- package/dist/chunk-C6KPAFCC.js +387 -0
- package/dist/chunk-CRFCWD6V.js +366 -0
- package/dist/chunk-CSATDXZC.js +89 -0
- package/dist/{chunk-T7NS2J2B.js → chunk-DFBX3BBD.js} +84 -1
- package/dist/{chunk-DNWT5FZQ.js → chunk-EANI2N2V.js} +98 -1
- package/dist/{chunk-HH24WMFN.js → chunk-FLY3WIQR.js} +1 -1
- package/dist/chunk-HLUEOLSZ.js +62 -0
- package/dist/chunk-IVOYM3WG.js +25 -0
- package/dist/chunk-LCAIAAG2.js +916 -0
- package/dist/chunk-MLS6IGGG.js +294 -0
- package/dist/{chunk-4P3EMGL4.js → chunk-MNO4COST.js} +5 -3
- package/dist/chunk-NH2FIERR.js +138 -0
- package/dist/chunk-UKT6H7YT.js +29 -0
- package/dist/{chunk-BH6WGYFB.js → chunk-VE3E4AMH.js} +8 -8
- package/dist/{chunk-7NA43XCG.js → chunk-W5BZMKMF.js} +163 -29
- package/dist/{chunk-FF226TIV.js → chunk-ZX5623ER.js} +0 -57
- package/dist/cli/index.js +362 -4631
- package/dist/{conduct-N52JX7RT.js → conduct-KM6ZNJGE.js} +10 -8
- package/dist/{conduct-GZQNFTRP.js → conduct-WGTMQND5.js} +10 -8
- package/dist/{conductor-mode-XUWGR4ZE.js → conductor-mode-OL2FNOYY.js} +6 -4
- package/dist/conductor-mode-VRO7TYW2.js +592 -0
- package/dist/execute-CPFSOOO3.js +13 -0
- package/dist/execute-IP2QHALV.js +10 -0
- package/dist/index.d.ts +19 -8
- package/dist/index.js +190 -37
- package/dist/peers-CJ7T4RJO.js +13 -0
- package/dist/process-guard-CC7CNRQJ.js +176 -0
- package/dist/{request-4GQSSM4B.js → request-YOWPXVLQ.js} +13 -10
- package/dist/schema-7BSSLZ4S.js +8 -0
- package/dist/{serve-skill-TPHZH6BS.js → serve-skill-JHFNR7BW.js} +8 -7
- package/dist/{server-365V3GYD.js → server-HKJJWFRG.js} +10 -8
- package/dist/service-coordinator-5R4LQW6L.js +4917 -0
- package/dist/skills/agentbnb/bootstrap.js +6181 -0
- package/dist/websocket-client-WRN3HO73.js +6 -0
- package/openclaw.plugin.json +54 -0
- package/package.json +11 -2
- package/skills/agentbnb/SKILL.md +87 -70
- package/skills/agentbnb/bootstrap.test.ts +142 -242
- package/skills/agentbnb/bootstrap.ts +88 -95
- package/skills/agentbnb/install.sh +97 -27
- package/dist/execute-PNGQOMYO.js +0 -10
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
// src/relay/websocket-client.ts
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
import { randomUUID } from "crypto";
|
|
4
|
+
|
|
5
|
+
// src/relay/types.ts
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
var RegisterMessageSchema = z.object({
|
|
8
|
+
type: z.literal("register"),
|
|
9
|
+
owner: z.string().min(1),
|
|
10
|
+
token: z.string().min(1),
|
|
11
|
+
card: z.record(z.unknown()),
|
|
12
|
+
// CapabilityCard (validated separately)
|
|
13
|
+
cards: z.array(z.record(z.unknown())).optional()
|
|
14
|
+
// Additional cards (e.g., conductor card)
|
|
15
|
+
});
|
|
16
|
+
var RegisteredMessageSchema = z.object({
|
|
17
|
+
type: z.literal("registered"),
|
|
18
|
+
agent_id: z.string()
|
|
19
|
+
});
|
|
20
|
+
var RelayRequestMessageSchema = z.object({
|
|
21
|
+
type: z.literal("relay_request"),
|
|
22
|
+
id: z.string().uuid(),
|
|
23
|
+
target_owner: z.string().min(1),
|
|
24
|
+
card_id: z.string(),
|
|
25
|
+
skill_id: z.string().optional(),
|
|
26
|
+
params: z.record(z.unknown()).default({}),
|
|
27
|
+
requester: z.string().optional(),
|
|
28
|
+
escrow_receipt: z.record(z.unknown()).optional()
|
|
29
|
+
});
|
|
30
|
+
var IncomingRequestMessageSchema = z.object({
|
|
31
|
+
type: z.literal("incoming_request"),
|
|
32
|
+
id: z.string().uuid(),
|
|
33
|
+
from_owner: z.string().min(1),
|
|
34
|
+
card_id: z.string(),
|
|
35
|
+
skill_id: z.string().optional(),
|
|
36
|
+
params: z.record(z.unknown()).default({}),
|
|
37
|
+
requester: z.string().optional(),
|
|
38
|
+
escrow_receipt: z.record(z.unknown()).optional()
|
|
39
|
+
});
|
|
40
|
+
var RelayResponseMessageSchema = z.object({
|
|
41
|
+
type: z.literal("relay_response"),
|
|
42
|
+
id: z.string().uuid(),
|
|
43
|
+
result: z.unknown().optional(),
|
|
44
|
+
error: z.object({
|
|
45
|
+
code: z.number(),
|
|
46
|
+
message: z.string()
|
|
47
|
+
}).optional()
|
|
48
|
+
});
|
|
49
|
+
var ResponseMessageSchema = z.object({
|
|
50
|
+
type: z.literal("response"),
|
|
51
|
+
id: z.string().uuid(),
|
|
52
|
+
result: z.unknown().optional(),
|
|
53
|
+
error: z.object({
|
|
54
|
+
code: z.number(),
|
|
55
|
+
message: z.string()
|
|
56
|
+
}).optional()
|
|
57
|
+
});
|
|
58
|
+
var ErrorMessageSchema = z.object({
|
|
59
|
+
type: z.literal("error"),
|
|
60
|
+
code: z.string(),
|
|
61
|
+
message: z.string(),
|
|
62
|
+
request_id: z.string().optional()
|
|
63
|
+
});
|
|
64
|
+
var RelayProgressMessageSchema = z.object({
|
|
65
|
+
type: z.literal("relay_progress"),
|
|
66
|
+
id: z.string().uuid(),
|
|
67
|
+
// request ID this progress relates to
|
|
68
|
+
progress: z.number().min(0).max(100).optional(),
|
|
69
|
+
// optional percentage
|
|
70
|
+
message: z.string().optional()
|
|
71
|
+
// optional status message
|
|
72
|
+
});
|
|
73
|
+
var RelayMessageSchema = z.discriminatedUnion("type", [
|
|
74
|
+
RegisterMessageSchema,
|
|
75
|
+
RegisteredMessageSchema,
|
|
76
|
+
RelayRequestMessageSchema,
|
|
77
|
+
IncomingRequestMessageSchema,
|
|
78
|
+
RelayResponseMessageSchema,
|
|
79
|
+
ResponseMessageSchema,
|
|
80
|
+
ErrorMessageSchema,
|
|
81
|
+
RelayProgressMessageSchema
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
// src/relay/websocket-client.ts
|
|
85
|
+
var RelayClient = class {
|
|
86
|
+
ws = null;
|
|
87
|
+
opts;
|
|
88
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
89
|
+
reconnectAttempts = 0;
|
|
90
|
+
reconnectTimer = null;
|
|
91
|
+
intentionalClose = false;
|
|
92
|
+
registered = false;
|
|
93
|
+
pongTimeout = null;
|
|
94
|
+
pingInterval = null;
|
|
95
|
+
constructor(opts) {
|
|
96
|
+
this.opts = opts;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Connect to the registry relay and register.
|
|
100
|
+
* Resolves when registration is acknowledged.
|
|
101
|
+
*/
|
|
102
|
+
async connect() {
|
|
103
|
+
return new Promise((resolve, reject) => {
|
|
104
|
+
this.intentionalClose = false;
|
|
105
|
+
this.registered = false;
|
|
106
|
+
const wsUrl = this.buildWsUrl();
|
|
107
|
+
this.ws = new WebSocket(wsUrl);
|
|
108
|
+
let resolved = false;
|
|
109
|
+
this.ws.on("open", () => {
|
|
110
|
+
this.reconnectAttempts = 0;
|
|
111
|
+
this.startPingInterval();
|
|
112
|
+
this.send({
|
|
113
|
+
type: "register",
|
|
114
|
+
owner: this.opts.owner,
|
|
115
|
+
token: this.opts.token,
|
|
116
|
+
card: this.opts.card,
|
|
117
|
+
...this.opts.cards && this.opts.cards.length > 0 ? { cards: this.opts.cards } : {}
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
this.ws.on("message", (raw) => {
|
|
121
|
+
this.handleMessage(raw, (err) => {
|
|
122
|
+
if (!resolved) {
|
|
123
|
+
resolved = true;
|
|
124
|
+
if (err) reject(err);
|
|
125
|
+
else resolve();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
this.ws.on("close", () => {
|
|
130
|
+
this.cleanup();
|
|
131
|
+
if (!this.intentionalClose) {
|
|
132
|
+
if (!resolved) {
|
|
133
|
+
resolved = true;
|
|
134
|
+
reject(new Error("WebSocket closed before registration"));
|
|
135
|
+
}
|
|
136
|
+
this.scheduleReconnect();
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
this.ws.on("error", (err) => {
|
|
140
|
+
if (!resolved) {
|
|
141
|
+
resolved = true;
|
|
142
|
+
reject(err);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
if (!resolved) {
|
|
147
|
+
resolved = true;
|
|
148
|
+
reject(new Error("Connection timeout"));
|
|
149
|
+
this.ws?.close();
|
|
150
|
+
}
|
|
151
|
+
}, 1e4);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Disconnect from the registry relay.
|
|
156
|
+
*/
|
|
157
|
+
disconnect() {
|
|
158
|
+
this.intentionalClose = true;
|
|
159
|
+
this.cleanup();
|
|
160
|
+
if (this.ws) {
|
|
161
|
+
try {
|
|
162
|
+
this.ws.close(1e3, "Client disconnect");
|
|
163
|
+
} catch {
|
|
164
|
+
}
|
|
165
|
+
this.ws = null;
|
|
166
|
+
}
|
|
167
|
+
for (const [id, pending] of this.pendingRequests) {
|
|
168
|
+
clearTimeout(pending.timeout);
|
|
169
|
+
pending.reject(new Error("Client disconnected"));
|
|
170
|
+
this.pendingRequests.delete(id);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Send a relay request to another agent via the registry.
|
|
175
|
+
* @returns The result from the target agent.
|
|
176
|
+
*/
|
|
177
|
+
async request(opts) {
|
|
178
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN || !this.registered) {
|
|
179
|
+
throw new Error("Not connected to registry relay");
|
|
180
|
+
}
|
|
181
|
+
const id = randomUUID();
|
|
182
|
+
const timeoutMs = opts.timeoutMs ?? 3e5;
|
|
183
|
+
return new Promise((resolve, reject) => {
|
|
184
|
+
const timeout = setTimeout(() => {
|
|
185
|
+
this.pendingRequests.delete(id);
|
|
186
|
+
reject(new Error("Relay request timeout"));
|
|
187
|
+
}, timeoutMs);
|
|
188
|
+
this.pendingRequests.set(id, { resolve, reject, timeout, timeoutMs, onProgress: opts.onProgress });
|
|
189
|
+
this.send({
|
|
190
|
+
type: "relay_request",
|
|
191
|
+
id,
|
|
192
|
+
target_owner: opts.targetOwner,
|
|
193
|
+
card_id: opts.cardId,
|
|
194
|
+
skill_id: opts.skillId,
|
|
195
|
+
params: opts.params,
|
|
196
|
+
requester: opts.requester ?? this.opts.owner,
|
|
197
|
+
escrow_receipt: opts.escrowReceipt
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Send a relay_progress message to the relay server for a given request.
|
|
203
|
+
* Used by the onRequest handler to forward SkillExecutor progress updates
|
|
204
|
+
* to the requesting agent so it can reset its timeout window.
|
|
205
|
+
*
|
|
206
|
+
* @param requestId - The relay request ID to associate progress with.
|
|
207
|
+
* @param info - Progress details (step, total, message).
|
|
208
|
+
*/
|
|
209
|
+
sendProgress(requestId, info) {
|
|
210
|
+
this.send({
|
|
211
|
+
type: "relay_progress",
|
|
212
|
+
id: requestId,
|
|
213
|
+
progress: Math.round(info.step / info.total * 100),
|
|
214
|
+
message: info.message
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/** Whether the client is connected and registered */
|
|
218
|
+
get isConnected() {
|
|
219
|
+
return this.ws !== null && this.ws.readyState === WebSocket.OPEN && this.registered;
|
|
220
|
+
}
|
|
221
|
+
// ── Private methods ─────────────────────────────────────────────────────────
|
|
222
|
+
buildWsUrl() {
|
|
223
|
+
let url = this.opts.registryUrl;
|
|
224
|
+
if (url.startsWith("http://")) {
|
|
225
|
+
url = "ws://" + url.slice(7);
|
|
226
|
+
} else if (url.startsWith("https://")) {
|
|
227
|
+
url = "wss://" + url.slice(8);
|
|
228
|
+
} else if (!url.startsWith("ws://") && !url.startsWith("wss://")) {
|
|
229
|
+
url = "wss://" + url;
|
|
230
|
+
}
|
|
231
|
+
if (!url.endsWith("/ws")) {
|
|
232
|
+
url = url.replace(/\/$/, "") + "/ws";
|
|
233
|
+
}
|
|
234
|
+
return url;
|
|
235
|
+
}
|
|
236
|
+
handleMessage(raw, onRegistered) {
|
|
237
|
+
let data;
|
|
238
|
+
try {
|
|
239
|
+
data = JSON.parse(typeof raw === "string" ? raw : raw.toString("utf-8"));
|
|
240
|
+
} catch {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const parsed = RelayMessageSchema.safeParse(data);
|
|
244
|
+
if (!parsed.success) return;
|
|
245
|
+
const msg = parsed.data;
|
|
246
|
+
switch (msg.type) {
|
|
247
|
+
case "registered":
|
|
248
|
+
this.registered = true;
|
|
249
|
+
if (!this.opts.silent) {
|
|
250
|
+
console.log(` \u2713 Registered with registry (agent_id: ${msg.agent_id})`);
|
|
251
|
+
}
|
|
252
|
+
onRegistered?.();
|
|
253
|
+
break;
|
|
254
|
+
case "incoming_request":
|
|
255
|
+
this.handleIncomingRequest(msg);
|
|
256
|
+
break;
|
|
257
|
+
case "response":
|
|
258
|
+
this.handleResponse(msg);
|
|
259
|
+
break;
|
|
260
|
+
case "error":
|
|
261
|
+
this.handleError(msg);
|
|
262
|
+
break;
|
|
263
|
+
case "relay_progress":
|
|
264
|
+
this.handleProgress(msg);
|
|
265
|
+
break;
|
|
266
|
+
default:
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
async handleIncomingRequest(msg) {
|
|
271
|
+
try {
|
|
272
|
+
const result = await this.opts.onRequest(msg);
|
|
273
|
+
this.send({
|
|
274
|
+
type: "relay_response",
|
|
275
|
+
id: msg.id,
|
|
276
|
+
result: result.result,
|
|
277
|
+
error: result.error
|
|
278
|
+
});
|
|
279
|
+
} catch (err) {
|
|
280
|
+
this.send({
|
|
281
|
+
type: "relay_response",
|
|
282
|
+
id: msg.id,
|
|
283
|
+
error: {
|
|
284
|
+
code: -32603,
|
|
285
|
+
message: err instanceof Error ? err.message : "Internal error"
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
handleResponse(msg) {
|
|
291
|
+
const pending = this.pendingRequests.get(msg.id);
|
|
292
|
+
if (!pending) return;
|
|
293
|
+
clearTimeout(pending.timeout);
|
|
294
|
+
this.pendingRequests.delete(msg.id);
|
|
295
|
+
if (msg.error) {
|
|
296
|
+
pending.reject(new Error(msg.error.message));
|
|
297
|
+
} else {
|
|
298
|
+
pending.resolve(msg.result);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
handleError(msg) {
|
|
302
|
+
if (msg.request_id) {
|
|
303
|
+
const pending = this.pendingRequests.get(msg.request_id);
|
|
304
|
+
if (pending) {
|
|
305
|
+
clearTimeout(pending.timeout);
|
|
306
|
+
this.pendingRequests.delete(msg.request_id);
|
|
307
|
+
pending.reject(new Error(`${msg.code}: ${msg.message}`));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
handleProgress(msg) {
|
|
312
|
+
const pending = this.pendingRequests.get(msg.id);
|
|
313
|
+
if (!pending) return;
|
|
314
|
+
clearTimeout(pending.timeout);
|
|
315
|
+
const newTimeout = setTimeout(() => {
|
|
316
|
+
this.pendingRequests.delete(msg.id);
|
|
317
|
+
pending.reject(new Error("Relay request timeout"));
|
|
318
|
+
}, pending.timeoutMs);
|
|
319
|
+
pending.timeout = newTimeout;
|
|
320
|
+
if (pending.onProgress) {
|
|
321
|
+
pending.onProgress({ id: msg.id, progress: msg.progress, message: msg.message });
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
send(msg) {
|
|
325
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
326
|
+
this.ws.send(JSON.stringify(msg));
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
startPingInterval() {
|
|
330
|
+
this.stopPingInterval();
|
|
331
|
+
this.pingInterval = setInterval(() => {
|
|
332
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
333
|
+
this.ws.ping();
|
|
334
|
+
this.pongTimeout = setTimeout(() => {
|
|
335
|
+
if (!this.opts.silent) {
|
|
336
|
+
console.log(" \u26A0 Registry pong timeout, reconnecting...");
|
|
337
|
+
}
|
|
338
|
+
this.ws?.terminate();
|
|
339
|
+
}, 15e3);
|
|
340
|
+
}
|
|
341
|
+
}, 3e4);
|
|
342
|
+
this.ws?.on("pong", () => {
|
|
343
|
+
if (this.pongTimeout) {
|
|
344
|
+
clearTimeout(this.pongTimeout);
|
|
345
|
+
this.pongTimeout = null;
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
stopPingInterval() {
|
|
350
|
+
if (this.pingInterval) {
|
|
351
|
+
clearInterval(this.pingInterval);
|
|
352
|
+
this.pingInterval = null;
|
|
353
|
+
}
|
|
354
|
+
if (this.pongTimeout) {
|
|
355
|
+
clearTimeout(this.pongTimeout);
|
|
356
|
+
this.pongTimeout = null;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
cleanup() {
|
|
360
|
+
this.stopPingInterval();
|
|
361
|
+
this.registered = false;
|
|
362
|
+
}
|
|
363
|
+
scheduleReconnect() {
|
|
364
|
+
if (this.intentionalClose) return;
|
|
365
|
+
if (this.reconnectTimer) return;
|
|
366
|
+
const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts), 3e4);
|
|
367
|
+
this.reconnectAttempts++;
|
|
368
|
+
if (!this.opts.silent) {
|
|
369
|
+
console.log(` \u21BB Reconnecting to registry in ${delay / 1e3}s...`);
|
|
370
|
+
}
|
|
371
|
+
this.reconnectTimer = setTimeout(async () => {
|
|
372
|
+
this.reconnectTimer = null;
|
|
373
|
+
try {
|
|
374
|
+
await this.connect();
|
|
375
|
+
if (!this.opts.silent) {
|
|
376
|
+
console.log(" \u2713 Reconnected to registry");
|
|
377
|
+
}
|
|
378
|
+
} catch {
|
|
379
|
+
}
|
|
380
|
+
}, delay);
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
export {
|
|
385
|
+
RelayMessageSchema,
|
|
386
|
+
RelayClient
|
|
387
|
+
};
|