agentbnb 4.0.0 → 4.0.1

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 (36) hide show
  1. package/dist/{card-IE5UV5QX.js → card-4XH4AOTE.js} +11 -4
  2. package/dist/chunk-3MJT4PZG.js +50 -0
  3. package/dist/{conduct-IQYAT6ZU.js → chunk-3UKAVIMC.js} +70 -33
  4. package/dist/chunk-5AH3CMOX.js +62 -0
  5. package/dist/{chunk-UJWYE7VL.js → chunk-6K5WUVF3.js} +28 -111
  6. package/dist/chunk-75OC6E4F.js +33 -0
  7. package/dist/{chunk-QO67IGCW.js → chunk-DVAS2443.js} +1 -1
  8. package/dist/{chunk-XA63SD4T.js → chunk-FNKBHBYK.js} +3 -0
  9. package/dist/{websocket-client-5TIQDYQ4.js → chunk-JOY533UH.js} +38 -4
  10. package/dist/{chunk-RSX4SCPN.js → chunk-KJG2UJV5.js} +3 -3
  11. package/dist/chunk-M3G5NR2Z.js +90 -0
  12. package/dist/{chunk-HEVXCYCY.js → chunk-MQKYGY5I.js} +61 -24
  13. package/dist/chunk-ODBGCCEH.js +358 -0
  14. package/dist/{chunk-CUVIWPQO.js → chunk-Q7HRI666.js} +7 -6
  15. package/dist/chunk-QJEOCKVF.js +148 -0
  16. package/dist/{chunk-3Y36WQDV.js → chunk-QT7TEVNV.js} +14 -2
  17. package/dist/{chunk-UOGDK2S2.js → chunk-TLU7ALCZ.js} +1 -1
  18. package/dist/{chunk-QVV2P3FN.js → chunk-XQHN6ITI.js} +1 -1
  19. package/dist/cli/index.js +2665 -845
  20. package/dist/{client-IOTK6GOS.js → client-BTPIFY7E.js} +3 -3
  21. package/dist/conduct-CW62HBPT.js +52 -0
  22. package/dist/conduct-FXLVGKD5.js +19 -0
  23. package/dist/{conductor-mode-XU7ONJWC.js → conductor-mode-3JS4VWCR.js} +16 -9
  24. package/dist/execute-EXOITLHN.js +10 -0
  25. package/dist/index.d.ts +1005 -916
  26. package/dist/index.js +516 -120
  27. package/dist/{peers-G36URZYB.js → peers-K7FSHPN3.js} +2 -1
  28. package/dist/request-CNZ3XIVX.js +196 -0
  29. package/dist/serve-skill-SUOGUM7N.js +104 -0
  30. package/dist/server-2LWHL24P.js +295 -0
  31. package/dist/types-FGBUZ3QV.js +18 -0
  32. package/dist/websocket-client-6IIDGXKB.js +7 -0
  33. package/package.json +1 -1
  34. package/dist/chunk-BEI5MTNZ.js +0 -91
  35. package/dist/cli/index.d.ts +0 -1
  36. package/dist/execute-GDGBU6DJ.js +0 -10
@@ -1,15 +1,22 @@
1
1
  import {
2
2
  CapabilityCardV2Schema
3
- } from "./chunk-XA63SD4T.js";
3
+ } from "./chunk-FNKBHBYK.js";
4
4
 
5
5
  // src/conductor/card.ts
6
+ import { createHash } from "crypto";
6
7
  var CONDUCTOR_OWNER = "agentbnb-conductor";
7
8
  var CONDUCTOR_CARD_ID = "00000000-0000-4000-8000-000000000001";
8
- function buildConductorCard() {
9
+ function ownerToCardId(owner) {
10
+ const hash = createHash("sha256").update(owner).digest("hex").slice(0, 32);
11
+ return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-8${hash.slice(17, 20)}-${hash.slice(20, 32)}`;
12
+ }
13
+ function buildConductorCard(owner) {
14
+ const cardOwner = owner ?? CONDUCTOR_OWNER;
15
+ const cardId = owner ? ownerToCardId(owner) : CONDUCTOR_CARD_ID;
9
16
  const card = {
10
17
  spec_version: "2.0",
11
- id: CONDUCTOR_CARD_ID,
12
- owner: CONDUCTOR_OWNER,
18
+ id: cardId,
19
+ owner: cardOwner,
13
20
  agent_name: "AgentBnB Conductor",
14
21
  skills: [
15
22
  {
@@ -0,0 +1,50 @@
1
+ // src/utils/interpolation.ts
2
+ function resolvePath(obj, path) {
3
+ const segments = path.replace(/\[(\d+)\]/g, ".$1").split(".").filter((s) => s.length > 0);
4
+ let current = obj;
5
+ for (const segment of segments) {
6
+ if (current === null || current === void 0) {
7
+ return void 0;
8
+ }
9
+ if (typeof current !== "object") {
10
+ return void 0;
11
+ }
12
+ current = current[segment];
13
+ }
14
+ return current;
15
+ }
16
+ function interpolate(template, context) {
17
+ return template.replace(/\$\{([^}]+)\}/g, (_match, expression) => {
18
+ const resolved = resolvePath(context, expression.trim());
19
+ if (resolved === void 0 || resolved === null) {
20
+ return "";
21
+ }
22
+ if (typeof resolved === "object") {
23
+ return JSON.stringify(resolved);
24
+ }
25
+ return String(resolved);
26
+ });
27
+ }
28
+ function interpolateObject(obj, context) {
29
+ const result = {};
30
+ for (const [key, value] of Object.entries(obj)) {
31
+ result[key] = interpolateValue(value, context);
32
+ }
33
+ return result;
34
+ }
35
+ function interpolateValue(value, context) {
36
+ if (typeof value === "string") {
37
+ return interpolate(value, context);
38
+ }
39
+ if (Array.isArray(value)) {
40
+ return value.map((item) => interpolateValue(item, context));
41
+ }
42
+ if (value !== null && typeof value === "object") {
43
+ return interpolateObject(value, context);
44
+ }
45
+ return value;
46
+ }
47
+
48
+ export {
49
+ interpolateObject
50
+ };
@@ -4,23 +4,25 @@ import {
4
4
  decompose,
5
5
  matchSubTasks,
6
6
  orchestrate
7
- } from "./chunk-HEVXCYCY.js";
7
+ } from "./chunk-MQKYGY5I.js";
8
8
  import {
9
9
  BudgetManager
10
- } from "./chunk-UJWYE7VL.js";
11
- import "./chunk-RSX4SCPN.js";
10
+ } from "./chunk-6K5WUVF3.js";
12
11
  import {
13
- loadConfig,
14
12
  loadPeers
15
- } from "./chunk-BEI5MTNZ.js";
13
+ } from "./chunk-5AH3CMOX.js";
14
+ import {
15
+ loadConfig
16
+ } from "./chunk-75OC6E4F.js";
16
17
  import {
17
18
  openDatabase
18
- } from "./chunk-UOGDK2S2.js";
19
+ } from "./chunk-TLU7ALCZ.js";
19
20
  import {
20
21
  openCreditDb
21
- } from "./chunk-QVV2P3FN.js";
22
- import "./chunk-QO67IGCW.js";
23
- import "./chunk-XA63SD4T.js";
22
+ } from "./chunk-XQHN6ITI.js";
23
+ import {
24
+ RelayClient
25
+ } from "./chunk-JOY533UH.js";
24
26
 
25
27
  // src/cli/conduct.ts
26
28
  async function conductAction(task, opts) {
@@ -36,10 +38,11 @@ async function conductAction(task, opts) {
36
38
  const db = openDatabase(config.db_path);
37
39
  let matchResults;
38
40
  try {
39
- matchResults = matchSubTasks({
41
+ matchResults = await matchSubTasks({
40
42
  db,
41
43
  subtasks,
42
- conductorOwner: config.owner
44
+ conductorOwner: config.owner,
45
+ registryUrl: config.registry
43
46
  });
44
47
  } finally {
45
48
  db.close();
@@ -74,33 +77,66 @@ async function conductAction(task, opts) {
74
77
  return { success: true, plan: planOutput };
75
78
  }
76
79
  const peers = loadPeers();
80
+ const matchMap = new Map(
81
+ matchResults.map((m) => [m.subtask_id, m])
82
+ );
77
83
  const resolveAgentUrl = (owner) => {
78
84
  const peer = peers.find((p) => p.name.toLowerCase() === owner.toLowerCase());
79
- if (!peer) {
80
- throw new Error(
81
- `Unknown peer "${owner}". Add with: agentbnb peers add ${owner} <url> <token>`
82
- );
85
+ if (peer) {
86
+ const execDb = openDatabase(config.db_path);
87
+ try {
88
+ const stmt = execDb.prepare("SELECT id FROM capability_cards WHERE owner = ? LIMIT 1");
89
+ const row = stmt.get(owner);
90
+ return { url: peer.url, cardId: row?.id ?? owner };
91
+ } finally {
92
+ execDb.close();
93
+ }
83
94
  }
84
- const execDb = openDatabase(config.db_path);
85
- try {
86
- const stmt = execDb.prepare("SELECT id FROM capability_cards WHERE owner = ? LIMIT 1");
87
- const row = stmt.get(owner);
88
- return { url: peer.url, cardId: row?.id ?? owner };
89
- } finally {
90
- execDb.close();
95
+ if (config.registry) {
96
+ let cardId = owner;
97
+ for (const m of matchMap.values()) {
98
+ if (m.selected_agent === owner && m.selected_card_id) {
99
+ cardId = m.selected_card_id;
100
+ break;
101
+ }
102
+ }
103
+ return { url: `relay://${owner}`, cardId };
91
104
  }
105
+ throw new Error(
106
+ `Unknown peer "${owner}". Add with: agentbnb peers add ${owner} <url> <token>`
107
+ );
92
108
  };
93
- const matchMap = new Map(
94
- matchResults.map((m) => [m.subtask_id, m])
95
- );
96
- const orchResult = await orchestrate({
97
- subtasks,
98
- matches: matchMap,
99
- gatewayToken: config.token ?? "",
100
- resolveAgentUrl,
101
- timeoutMs: 3e4,
102
- maxBudget
103
- });
109
+ let relay;
110
+ if (config.registry) {
111
+ relay = new RelayClient({
112
+ registryUrl: config.registry,
113
+ owner: config.owner,
114
+ token: config.token ?? "",
115
+ card: { id: config.owner, owner: config.owner, name: "conductor" },
116
+ onRequest: async () => ({ error: { code: -32601, message: "Conductor does not accept requests" } }),
117
+ silent: true
118
+ });
119
+ try {
120
+ await relay.connect();
121
+ } catch {
122
+ relay = void 0;
123
+ }
124
+ }
125
+ let orchResult;
126
+ try {
127
+ orchResult = await orchestrate({
128
+ subtasks,
129
+ matches: matchMap,
130
+ gatewayToken: config.token ?? "",
131
+ resolveAgentUrl,
132
+ timeoutMs: 3e5,
133
+ maxBudget,
134
+ relayClient: relay,
135
+ requesterOwner: config.owner
136
+ });
137
+ } finally {
138
+ relay?.disconnect();
139
+ }
104
140
  const resultObj = {};
105
141
  for (const [key, value] of orchResult.results) {
106
142
  resultObj[key] = value;
@@ -114,6 +150,7 @@ async function conductAction(task, opts) {
114
150
  errors: orchResult.errors
115
151
  };
116
152
  }
153
+
117
154
  export {
118
155
  conductAction
119
156
  };
@@ -0,0 +1,62 @@
1
+ import {
2
+ getConfigDir
3
+ } from "./chunk-75OC6E4F.js";
4
+
5
+ // src/cli/peers.ts
6
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
7
+ import { join } from "path";
8
+ function getPeersPath() {
9
+ return join(getConfigDir(), "peers.json");
10
+ }
11
+ function loadPeers() {
12
+ const peersPath = getPeersPath();
13
+ if (!existsSync(peersPath)) {
14
+ return [];
15
+ }
16
+ try {
17
+ const raw = readFileSync(peersPath, "utf-8");
18
+ return JSON.parse(raw);
19
+ } catch {
20
+ return [];
21
+ }
22
+ }
23
+ function writePeers(peers) {
24
+ const dir = getConfigDir();
25
+ if (!existsSync(dir)) {
26
+ mkdirSync(dir, { recursive: true });
27
+ }
28
+ writeFileSync(getPeersPath(), JSON.stringify(peers, null, 2), "utf-8");
29
+ }
30
+ function savePeer(peer) {
31
+ const peers = loadPeers();
32
+ const lowerName = peer.name.toLowerCase();
33
+ const existing = peers.findIndex((p) => p.name.toLowerCase() === lowerName);
34
+ if (existing >= 0) {
35
+ peers[existing] = peer;
36
+ } else {
37
+ peers.push(peer);
38
+ }
39
+ writePeers(peers);
40
+ }
41
+ function removePeer(name) {
42
+ const peers = loadPeers();
43
+ const lowerName = name.toLowerCase();
44
+ const filtered = peers.filter((p) => p.name.toLowerCase() !== lowerName);
45
+ if (filtered.length === peers.length) {
46
+ return false;
47
+ }
48
+ writePeers(filtered);
49
+ return true;
50
+ }
51
+ function findPeer(name) {
52
+ const peers = loadPeers();
53
+ const lowerName = name.toLowerCase();
54
+ return peers.find((p) => p.name.toLowerCase() === lowerName) ?? null;
55
+ }
56
+
57
+ export {
58
+ loadPeers,
59
+ savePeer,
60
+ removePeer,
61
+ findPeer
62
+ };
@@ -1,18 +1,22 @@
1
+ import {
2
+ fetchRemoteCards,
3
+ searchCards
4
+ } from "./chunk-QJEOCKVF.js";
1
5
  import {
2
6
  requestCapability
3
- } from "./chunk-RSX4SCPN.js";
7
+ } from "./chunk-KJG2UJV5.js";
4
8
  import {
5
9
  findPeer
6
- } from "./chunk-BEI5MTNZ.js";
10
+ } from "./chunk-5AH3CMOX.js";
7
11
  import {
8
12
  getBalance,
9
13
  holdEscrow,
10
14
  releaseEscrow,
11
15
  settleEscrow
12
- } from "./chunk-QVV2P3FN.js";
16
+ } from "./chunk-XQHN6ITI.js";
13
17
  import {
14
18
  AgentBnBError
15
- } from "./chunk-XA63SD4T.js";
19
+ } from "./chunk-FNKBHBYK.js";
16
20
 
17
21
  // src/autonomy/tiers.ts
18
22
  import { randomUUID } from "crypto";
@@ -95,61 +99,6 @@ var BudgetManager = class {
95
99
  }
96
100
  };
97
101
 
98
- // src/registry/matcher.ts
99
- function searchCards(db, query, filters = {}) {
100
- const words = query.trim().split(/\s+/).map((w) => w.replace(/["*^{}():]/g, "")).filter((w) => w.length > 0);
101
- if (words.length === 0) return [];
102
- const ftsQuery = words.map((w) => `"${w}"`).join(" OR ");
103
- const conditions = [];
104
- const params = [ftsQuery];
105
- if (filters.level !== void 0) {
106
- conditions.push(`json_extract(cc.data, '$.level') = ?`);
107
- params.push(filters.level);
108
- }
109
- if (filters.online !== void 0) {
110
- conditions.push(`json_extract(cc.data, '$.availability.online') = ?`);
111
- params.push(filters.online ? 1 : 0);
112
- }
113
- const whereClause = conditions.length > 0 ? `AND ${conditions.join(" AND ")}` : "";
114
- const sql = `
115
- SELECT cc.data
116
- FROM capability_cards cc
117
- JOIN cards_fts ON cc.rowid = cards_fts.rowid
118
- WHERE cards_fts MATCH ?
119
- ${whereClause}
120
- ORDER BY bm25(cards_fts)
121
- LIMIT 50
122
- `;
123
- const stmt = db.prepare(sql);
124
- const rows = stmt.all(...params);
125
- const results = rows.map((row) => JSON.parse(row.data));
126
- if (filters.apis_used && filters.apis_used.length > 0) {
127
- const requiredApis = filters.apis_used;
128
- return results.filter((card) => {
129
- const cardApis = card.metadata?.apis_used ?? [];
130
- return requiredApis.every((api) => cardApis.includes(api));
131
- });
132
- }
133
- return results;
134
- }
135
- function filterCards(db, filters) {
136
- const conditions = [];
137
- const params = [];
138
- if (filters.level !== void 0) {
139
- conditions.push(`json_extract(data, '$.level') = ?`);
140
- params.push(filters.level);
141
- }
142
- if (filters.online !== void 0) {
143
- conditions.push(`json_extract(data, '$.availability.online') = ?`);
144
- params.push(filters.online ? 1 : 0);
145
- }
146
- const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
147
- const sql = `SELECT data FROM capability_cards ${whereClause}`;
148
- const stmt = db.prepare(sql);
149
- const rows = stmt.all(...params);
150
- return rows.map((row) => JSON.parse(row.data));
151
- }
152
-
153
102
  // src/autonomy/pending-requests.ts
154
103
  import { randomUUID as randomUUID2 } from "crypto";
155
104
  function createPendingRequest(db, opts) {
@@ -228,6 +177,7 @@ var AutoRequestor = class {
228
177
  creditDb;
229
178
  autonomyConfig;
230
179
  budgetManager;
180
+ registryUrl;
231
181
  /**
232
182
  * Creates a new AutoRequestor.
233
183
  *
@@ -239,6 +189,7 @@ var AutoRequestor = class {
239
189
  this.creditDb = opts.creditDb;
240
190
  this.autonomyConfig = opts.autonomyConfig;
241
191
  this.budgetManager = opts.budgetManager;
192
+ this.registryUrl = opts.registryUrl;
242
193
  }
243
194
  /**
244
195
  * Executes an autonomous capability request.
@@ -259,7 +210,23 @@ var AutoRequestor = class {
259
210
  * @returns The result of the auto-request attempt.
260
211
  */
261
212
  async requestWithAutonomy(need) {
262
- const cards = searchCards(this.registryDb, need.query, { online: true });
213
+ let cards = searchCards(this.registryDb, need.query, { online: true });
214
+ if (cards.length === 0 && this.registryUrl) {
215
+ try {
216
+ cards = await fetchRemoteCards(this.registryUrl, { q: need.query, online: true });
217
+ } catch {
218
+ insertAuditEvent(this.registryDb, {
219
+ type: "auto_request_failed",
220
+ card_id: "none",
221
+ skill_id: "none",
222
+ tier_invoked: 3,
223
+ credits: 0,
224
+ peer: "none",
225
+ reason: `Remote registry fallback failed for query "${need.query}"`
226
+ });
227
+ cards = [];
228
+ }
229
+ }
263
230
  const candidates = [];
264
231
  for (const card of cards) {
265
232
  const cardAsV2 = card;
@@ -380,64 +347,14 @@ var AutoRequestor = class {
380
347
  }
381
348
  };
382
349
 
383
- // src/utils/interpolation.ts
384
- function resolvePath(obj, path) {
385
- const segments = path.replace(/\[(\d+)\]/g, ".$1").split(".").filter((s) => s.length > 0);
386
- let current = obj;
387
- for (const segment of segments) {
388
- if (current === null || current === void 0) {
389
- return void 0;
390
- }
391
- if (typeof current !== "object") {
392
- return void 0;
393
- }
394
- current = current[segment];
395
- }
396
- return current;
397
- }
398
- function interpolate(template, context) {
399
- return template.replace(/\$\{([^}]+)\}/g, (_match, expression) => {
400
- const resolved = resolvePath(context, expression.trim());
401
- if (resolved === void 0 || resolved === null) {
402
- return "";
403
- }
404
- if (typeof resolved === "object") {
405
- return JSON.stringify(resolved);
406
- }
407
- return String(resolved);
408
- });
409
- }
410
- function interpolateObject(obj, context) {
411
- const result = {};
412
- for (const [key, value] of Object.entries(obj)) {
413
- result[key] = interpolateValue(value, context);
414
- }
415
- return result;
416
- }
417
- function interpolateValue(value, context) {
418
- if (typeof value === "string") {
419
- return interpolate(value, context);
420
- }
421
- if (Array.isArray(value)) {
422
- return value.map((item) => interpolateValue(item, context));
423
- }
424
- if (value !== null && typeof value === "object") {
425
- return interpolateObject(value, context);
426
- }
427
- return value;
428
- }
429
-
430
350
  export {
431
351
  DEFAULT_AUTONOMY_CONFIG,
432
352
  getAutonomyTier,
433
353
  insertAuditEvent,
434
354
  DEFAULT_BUDGET_CONFIG,
435
355
  BudgetManager,
436
- searchCards,
437
- filterCards,
438
356
  listPendingRequests,
439
357
  resolvePendingRequest,
440
358
  scorePeers,
441
- AutoRequestor,
442
- interpolateObject
359
+ AutoRequestor
443
360
  };
@@ -0,0 +1,33 @@
1
+ // src/cli/config.ts
2
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
3
+ import { homedir } from "os";
4
+ import { join } from "path";
5
+ function getConfigDir() {
6
+ return process.env["AGENTBNB_DIR"] ?? join(homedir(), ".agentbnb");
7
+ }
8
+ function getConfigPath() {
9
+ return join(getConfigDir(), "config.json");
10
+ }
11
+ function loadConfig() {
12
+ const configPath = getConfigPath();
13
+ if (!existsSync(configPath)) return null;
14
+ try {
15
+ const raw = readFileSync(configPath, "utf-8");
16
+ return JSON.parse(raw);
17
+ } catch {
18
+ return null;
19
+ }
20
+ }
21
+ function saveConfig(config) {
22
+ const dir = getConfigDir();
23
+ if (!existsSync(dir)) {
24
+ mkdirSync(dir, { recursive: true });
25
+ }
26
+ writeFileSync(getConfigPath(), JSON.stringify(config, null, 2), "utf-8");
27
+ }
28
+
29
+ export {
30
+ getConfigDir,
31
+ loadConfig,
32
+ saveConfig
33
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AgentBnBError
3
- } from "./chunk-XA63SD4T.js";
3
+ } from "./chunk-FNKBHBYK.js";
4
4
 
5
5
  // src/credit/signing.ts
6
6
  import { generateKeyPairSync, sign, verify, createPublicKey, createPrivateKey } from "crypto";
@@ -123,7 +123,10 @@ var AgentBnBError = class extends Error {
123
123
  };
124
124
 
125
125
  export {
126
+ IOSchemaSchema,
127
+ PoweredBySchema,
126
128
  CapabilityCardSchema,
129
+ SkillSchema,
127
130
  CapabilityCardV2Schema,
128
131
  AnyCardSchema,
129
132
  AgentBnBError
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  RelayMessageSchema
3
- } from "./chunk-3Y36WQDV.js";
3
+ } from "./chunk-QT7TEVNV.js";
4
4
 
5
5
  // src/relay/websocket-client.ts
6
6
  import WebSocket from "ws";
@@ -36,7 +36,8 @@ var RelayClient = class {
36
36
  type: "register",
37
37
  owner: this.opts.owner,
38
38
  token: this.opts.token,
39
- card: this.opts.card
39
+ card: this.opts.card,
40
+ ...this.opts.cards && this.opts.cards.length > 0 ? { cards: this.opts.cards } : {}
40
41
  });
41
42
  });
42
43
  this.ws.on("message", (raw) => {
@@ -101,13 +102,13 @@ var RelayClient = class {
101
102
  throw new Error("Not connected to registry relay");
102
103
  }
103
104
  const id = randomUUID();
104
- const timeoutMs = opts.timeoutMs ?? 3e4;
105
+ const timeoutMs = opts.timeoutMs ?? 3e5;
105
106
  return new Promise((resolve, reject) => {
106
107
  const timeout = setTimeout(() => {
107
108
  this.pendingRequests.delete(id);
108
109
  reject(new Error("Relay request timeout"));
109
110
  }, timeoutMs);
110
- this.pendingRequests.set(id, { resolve, reject, timeout });
111
+ this.pendingRequests.set(id, { resolve, reject, timeout, timeoutMs, onProgress: opts.onProgress });
111
112
  this.send({
112
113
  type: "relay_request",
113
114
  id,
@@ -120,6 +121,22 @@ var RelayClient = class {
120
121
  });
121
122
  });
122
123
  }
124
+ /**
125
+ * Send a relay_progress message to the relay server for a given request.
126
+ * Used by the onRequest handler to forward SkillExecutor progress updates
127
+ * to the requesting agent so it can reset its timeout window.
128
+ *
129
+ * @param requestId - The relay request ID to associate progress with.
130
+ * @param info - Progress details (step, total, message).
131
+ */
132
+ sendProgress(requestId, info) {
133
+ this.send({
134
+ type: "relay_progress",
135
+ id: requestId,
136
+ progress: Math.round(info.step / info.total * 100),
137
+ message: info.message
138
+ });
139
+ }
123
140
  /** Whether the client is connected and registered */
124
141
  get isConnected() {
125
142
  return this.ws !== null && this.ws.readyState === WebSocket.OPEN && this.registered;
@@ -166,6 +183,9 @@ var RelayClient = class {
166
183
  case "error":
167
184
  this.handleError(msg);
168
185
  break;
186
+ case "relay_progress":
187
+ this.handleProgress(msg);
188
+ break;
169
189
  default:
170
190
  break;
171
191
  }
@@ -211,6 +231,19 @@ var RelayClient = class {
211
231
  }
212
232
  }
213
233
  }
234
+ handleProgress(msg) {
235
+ const pending = this.pendingRequests.get(msg.id);
236
+ if (!pending) return;
237
+ clearTimeout(pending.timeout);
238
+ const newTimeout = setTimeout(() => {
239
+ this.pendingRequests.delete(msg.id);
240
+ pending.reject(new Error("Relay request timeout"));
241
+ }, pending.timeoutMs);
242
+ pending.timeout = newTimeout;
243
+ if (pending.onProgress) {
244
+ pending.onProgress({ id: msg.id, progress: msg.progress, message: msg.message });
245
+ }
246
+ }
214
247
  send(msg) {
215
248
  if (this.ws && this.ws.readyState === WebSocket.OPEN) {
216
249
  this.ws.send(JSON.stringify(msg));
@@ -270,6 +303,7 @@ var RelayClient = class {
270
303
  }, delay);
271
304
  }
272
305
  };
306
+
273
307
  export {
274
308
  RelayClient
275
309
  };
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  signEscrowReceipt
3
- } from "./chunk-QO67IGCW.js";
3
+ } from "./chunk-DVAS2443.js";
4
4
  import {
5
5
  AgentBnBError
6
- } from "./chunk-XA63SD4T.js";
6
+ } from "./chunk-FNKBHBYK.js";
7
7
 
8
8
  // src/gateway/client.ts
9
9
  import { randomUUID } from "crypto";
10
10
  async function requestCapability(opts) {
11
- const { gatewayUrl, token, cardId, params = {}, timeoutMs = 3e4, escrowReceipt, identity } = opts;
11
+ const { gatewayUrl, token, cardId, params = {}, timeoutMs = 3e5, escrowReceipt, identity } = opts;
12
12
  const id = randomUUID();
13
13
  const payload = {
14
14
  jsonrpc: "2.0",