agentbnb 8.2.0 → 8.2.2

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 (40) hide show
  1. package/dist/{chunk-TBJ3FZKZ.js → chunk-4IPJJRTP.js} +1 -1
  2. package/dist/chunk-CKOOVZOI.js +158 -0
  3. package/dist/chunk-CQFBNTGT.js +145 -0
  4. package/dist/{chunk-P4LOYSLA.js → chunk-DYQOFGGI.js} +331 -416
  5. package/dist/{chunk-ALX4WS3A.js → chunk-EG6RS4JC.js} +70 -46
  6. package/dist/{chunk-CUONY5TO.js → chunk-EJKW57ZV.js} +19 -1
  7. package/dist/{chunk-5AAFG2V2.js → chunk-LKLKYXLV.js} +239 -24
  8. package/dist/{chunk-7EF3HYVZ.js → chunk-MCED4GDW.js} +499 -86
  9. package/dist/{chunk-YHY7OG6S.js → chunk-MWOXW7JQ.js} +7 -7
  10. package/dist/{chunk-E2OKP5CY.js → chunk-QCGIG7WW.js} +182 -86
  11. package/dist/{chunk-5GME4KJZ.js → chunk-QHZGOG3O.js} +148 -46
  12. package/dist/{chunk-D6RKW2XG.js → chunk-RYISHSHB.js} +302 -4
  13. package/dist/{chunk-O2OYBAVR.js → chunk-S3V6R3EN.js} +75 -39
  14. package/dist/{chunk-X32NE6V4.js → chunk-WNXXLCV5.js} +1 -1
  15. package/dist/{chunk-C537SFHV.js → chunk-XBGVQMQJ.js} +72 -48
  16. package/dist/{chunk-FTZTEHYG.js → chunk-Z2GEFFDO.js} +135 -8
  17. package/dist/cli/index.js +42 -67
  18. package/dist/{client-HKV3QWZ3.js → client-XOLP5IUZ.js} +4 -2
  19. package/dist/{conduct-W6XF6DJW.js → conduct-AZFLNUX3.js} +10 -11
  20. package/dist/{conduct-YB64OHI6.js → conduct-VPUYTNEA.js} +10 -11
  21. package/dist/{conductor-mode-AKREGDIU.js → conductor-mode-PLTB6MS3.js} +7 -8
  22. package/dist/{conductor-mode-TFCVCQHU.js → conductor-mode-WKB42PYM.js} +6 -3
  23. package/dist/{execute-EPE6MZLT.js → execute-NNDCXTN4.js} +3 -2
  24. package/dist/{execute-AYQWORVH.js → execute-RIRHTIBU.js} +6 -5
  25. package/dist/index.d.ts +8 -8
  26. package/dist/index.js +637 -693
  27. package/dist/{publish-capability-AH2HDW54.js → publish-capability-QDR2QIZ2.js} +2 -2
  28. package/dist/{request-HCCXSKAY.js → request-NX7GSPIG.js} +31 -36
  29. package/dist/{serve-skill-SZAQT5T5.js → serve-skill-E6EJQYAK.js} +10 -9
  30. package/dist/{server-LMY2A3GT.js → server-VBCT32FC.js} +12 -18
  31. package/dist/{service-coordinator-WGH6B2VT.js → service-coordinator-KMSA6BST.js} +137 -69
  32. package/dist/skills/agentbnb/bootstrap.js +561 -247
  33. package/package.json +13 -17
  34. package/skills/agentbnb/bootstrap.test.ts +8 -6
  35. package/skills/agentbnb/bootstrap.ts +21 -13
  36. package/skills/agentbnb/install.sh +0 -0
  37. package/dist/chunk-64AK4FJM.js +0 -84
  38. package/dist/chunk-KF3TZHA5.js +0 -91
  39. package/dist/chunk-LJM7FHPM.js +0 -138
  40. package/dist/chunk-OH7BP5NP.js +0 -96
@@ -1,14 +1,20 @@
1
+ import {
2
+ requestCapability,
3
+ requestCapabilityBatch,
4
+ requestViaRelay
5
+ } from "./chunk-CKOOVZOI.js";
1
6
  import {
2
7
  findPeer
3
8
  } from "./chunk-HLUEOLSZ.js";
4
9
  import {
10
+ fetchRemoteCards,
5
11
  getBalance,
6
- getFeedbackForProvider,
7
12
  holdEscrow,
8
13
  releaseEscrow,
9
- settleEscrow,
10
- signEscrowReceipt
11
- } from "./chunk-7EF3HYVZ.js";
14
+ resolveTargetCapability,
15
+ searchCards,
16
+ settleEscrow
17
+ } from "./chunk-MCED4GDW.js";
12
18
  import {
13
19
  AgentBnBError
14
20
  } from "./chunk-WVY2W7AA.js";
@@ -256,209 +262,11 @@ function decompose(task, _availableCapabilities) {
256
262
  return [];
257
263
  }
258
264
 
259
- // src/gateway/client.ts
260
- import { randomUUID as randomUUID2 } from "crypto";
261
- async function requestCapability(opts) {
262
- const { gatewayUrl, token, cardId, params = {}, timeoutMs = 3e5, escrowReceipt, identity } = opts;
263
- const id = randomUUID2();
264
- const payload = {
265
- jsonrpc: "2.0",
266
- id,
267
- method: "capability.execute",
268
- params: {
269
- card_id: cardId,
270
- ...params,
271
- ...escrowReceipt ? { escrow_receipt: escrowReceipt } : {}
272
- }
273
- };
274
- const headers = { "Content-Type": "application/json" };
275
- if (identity) {
276
- const signature = signEscrowReceipt(payload, identity.privateKey);
277
- headers["X-Agent-Id"] = identity.agentId;
278
- headers["X-Agent-Public-Key"] = identity.publicKey;
279
- headers["X-Agent-Signature"] = signature;
280
- } else if (token) {
281
- headers["Authorization"] = `Bearer ${token}`;
282
- }
283
- const controller = new AbortController();
284
- const timer = setTimeout(() => controller.abort(), timeoutMs);
285
- let response;
286
- try {
287
- response = await fetch(`${gatewayUrl}/rpc`, {
288
- method: "POST",
289
- headers,
290
- body: JSON.stringify(payload),
291
- signal: controller.signal
292
- });
293
- } catch (err) {
294
- clearTimeout(timer);
295
- const isTimeout = err instanceof Error && err.name === "AbortError";
296
- throw new AgentBnBError(
297
- isTimeout ? "Request timed out" : `Network error: ${String(err)}`,
298
- isTimeout ? "TIMEOUT" : "NETWORK_ERROR"
299
- );
300
- } finally {
301
- clearTimeout(timer);
302
- }
303
- const body = await response.json();
304
- if (body.error) {
305
- throw new AgentBnBError(body.error.message, `RPC_ERROR_${body.error.code}`);
306
- }
307
- return body.result;
308
- }
309
- async function requestViaRelay(relay, opts) {
310
- try {
311
- return await relay.request({
312
- targetOwner: opts.targetOwner,
313
- cardId: opts.cardId,
314
- skillId: opts.skillId,
315
- params: opts.params ?? {},
316
- requester: opts.requester,
317
- escrowReceipt: opts.escrowReceipt,
318
- timeoutMs: opts.timeoutMs
319
- });
320
- } catch (err) {
321
- const message = err instanceof Error ? err.message : String(err);
322
- if (message.includes("timeout")) {
323
- throw new AgentBnBError(message, "TIMEOUT");
324
- }
325
- if (message.includes("offline")) {
326
- throw new AgentBnBError(message, "AGENT_OFFLINE");
327
- }
328
- throw new AgentBnBError(message, "RELAY_ERROR");
329
- }
330
- }
331
-
332
- // src/feedback/reputation.ts
333
- var QUALITY_SCORES = {
334
- excellent: 1,
335
- good: 0.8,
336
- acceptable: 0.6,
337
- poor: 0.3,
338
- failed: 0
339
- };
340
- var COST_VALUE_SCORES = {
341
- great: 1,
342
- fair: 0.6,
343
- overpriced: 0.2
344
- };
345
- var DECAY_DAYS = 30;
346
- var WEIGHTS = {
347
- rating: 0.4,
348
- quality: 0.3,
349
- would_reuse: 0.2,
350
- cost_value: 0.1
351
- };
352
- function computeReputation(feedbacks) {
353
- if (feedbacks.length === 0) return 0.5;
354
- const now = Date.now();
355
- let weightedSum = 0;
356
- let totalWeight = 0;
357
- for (const fb of feedbacks) {
358
- const feedbackDate = new Date(fb.timestamp).getTime();
359
- const ageDays = Math.max(0, (now - feedbackDate) / (1e3 * 60 * 60 * 24));
360
- const recencyWeight = Math.exp(-ageDays / DECAY_DAYS);
361
- const ratingScore = (fb.rating - 1) / 4;
362
- const qualityScore = QUALITY_SCORES[fb.result_quality];
363
- const reuseScore = fb.would_reuse ? 1 : 0;
364
- const costScore = COST_VALUE_SCORES[fb.cost_value_ratio];
365
- const componentScore = WEIGHTS.rating * ratingScore + WEIGHTS.quality * qualityScore + WEIGHTS.would_reuse * reuseScore + WEIGHTS.cost_value * costScore;
366
- weightedSum += recencyWeight * componentScore;
367
- totalWeight += recencyWeight;
368
- }
369
- if (totalWeight === 0) return 0.5;
370
- const raw = weightedSum / totalWeight;
371
- return Math.max(0, Math.min(1, raw));
372
- }
373
- function getReputationScore(db, agentId) {
374
- const feedbacks = getFeedbackForProvider(db, agentId);
375
- return computeReputation(feedbacks);
376
- }
377
-
378
- // src/registry/matcher.ts
379
- function searchCards(db, query, filters = {}) {
380
- const words = query.trim().split(/\s+/).map((w) => w.replace(/["*^{}():]/g, "")).filter((w) => w.length > 0);
381
- if (words.length === 0) return [];
382
- const ftsQuery = words.map((w) => `"${w}"`).join(" OR ");
383
- const conditions = [];
384
- const params = [ftsQuery];
385
- if (filters.level !== void 0) {
386
- conditions.push(`json_extract(cc.data, '$.level') = ?`);
387
- params.push(filters.level);
388
- }
389
- if (filters.online !== void 0) {
390
- conditions.push(`json_extract(cc.data, '$.availability.online') = ?`);
391
- params.push(filters.online ? 1 : 0);
392
- }
393
- const whereClause = conditions.length > 0 ? `AND ${conditions.join(" AND ")}` : "";
394
- const sql = `
395
- SELECT cc.data
396
- FROM capability_cards cc
397
- JOIN cards_fts ON cc.rowid = cards_fts.rowid
398
- WHERE cards_fts MATCH ?
399
- ${whereClause}
400
- ORDER BY bm25(cards_fts)
401
- LIMIT 50
402
- `;
403
- const stmt = db.prepare(sql);
404
- const rows = stmt.all(...params);
405
- const results = rows.map((row) => JSON.parse(row.data));
406
- let filtered = results;
407
- if (filters.apis_used && filters.apis_used.length > 0) {
408
- const requiredApis = filters.apis_used;
409
- filtered = filtered.filter((card) => {
410
- const cardApis = card.metadata?.apis_used ?? [];
411
- return requiredApis.every((api) => cardApis.includes(api));
412
- });
413
- }
414
- if (filters.min_reputation !== void 0 && filters.min_reputation > 0) {
415
- filtered = applyReputationFilter(db, filtered, filters.min_reputation);
416
- }
417
- return filtered;
418
- }
419
- function filterCards(db, filters) {
420
- const conditions = [];
421
- const params = [];
422
- if (filters.level !== void 0) {
423
- conditions.push(`json_extract(data, '$.level') = ?`);
424
- params.push(filters.level);
425
- }
426
- if (filters.online !== void 0) {
427
- conditions.push(`json_extract(data, '$.availability.online') = ?`);
428
- params.push(filters.online ? 1 : 0);
429
- }
430
- const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
431
- const sql = `SELECT data FROM capability_cards ${whereClause}`;
432
- const stmt = db.prepare(sql);
433
- const rows = stmt.all(...params);
434
- let cards = rows.map((row) => JSON.parse(row.data));
435
- if (filters.min_reputation !== void 0 && filters.min_reputation > 0) {
436
- cards = applyReputationFilter(db, cards, filters.min_reputation);
437
- }
438
- return cards;
439
- }
440
- function applyReputationFilter(db, cards, minReputation) {
441
- const owners = [...new Set(cards.map((c) => c.owner))];
442
- const reputationMap = /* @__PURE__ */ new Map();
443
- for (const owner of owners) {
444
- reputationMap.set(owner, getReputationScore(db, owner));
445
- }
446
- return cards.filter((card) => {
447
- const score = reputationMap.get(card.owner) ?? 0.5;
448
- return score >= minReputation;
449
- });
450
- }
451
- function buildReputationMap(db, owners) {
452
- const unique = [...new Set(owners)];
453
- const map = /* @__PURE__ */ new Map();
454
- for (const owner of unique) {
455
- map.set(owner, getReputationScore(db, owner));
456
- }
457
- return map;
458
- }
265
+ // src/autonomy/auto-request.ts
266
+ import { randomUUID as randomUUID4 } from "crypto";
459
267
 
460
268
  // src/autonomy/tiers.ts
461
- import { randomUUID as randomUUID3 } from "crypto";
269
+ import { randomUUID as randomUUID2 } from "crypto";
462
270
  var DEFAULT_AUTONOMY_CONFIG = {
463
271
  tier1_max_credits: 0,
464
272
  tier2_max_credits: 0
@@ -479,7 +287,7 @@ function insertAuditEvent(db, event) {
479
287
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
480
288
  `);
481
289
  stmt.run(
482
- randomUUID3(),
290
+ randomUUID2(),
483
291
  cardId,
484
292
  "autonomy-audit",
485
293
  "self",
@@ -494,9 +302,9 @@ function insertAuditEvent(db, event) {
494
302
  }
495
303
 
496
304
  // src/autonomy/pending-requests.ts
497
- import { randomUUID as randomUUID4 } from "crypto";
305
+ import { randomUUID as randomUUID3 } from "crypto";
498
306
  function createPendingRequest(db, opts) {
499
- const id = randomUUID4();
307
+ const id = randomUUID3();
500
308
  const now = (/* @__PURE__ */ new Date()).toISOString();
501
309
  const paramsJson = opts.params !== void 0 ? JSON.stringify(opts.params) : null;
502
310
  db.prepare(`
@@ -534,89 +342,6 @@ function resolvePendingRequest(db, id, resolution) {
534
342
  }
535
343
  }
536
344
 
537
- // src/cli/remote-registry.ts
538
- var RegistryTimeoutError = class extends AgentBnBError {
539
- constructor(url) {
540
- super(
541
- `Registry at ${url} did not respond within 5s. Showing local results only.`,
542
- "REGISTRY_TIMEOUT"
543
- );
544
- this.name = "RegistryTimeoutError";
545
- }
546
- };
547
- var RegistryConnectionError = class extends AgentBnBError {
548
- constructor(url) {
549
- super(
550
- `Cannot reach ${url}. Is the registry running? Showing local results only.`,
551
- "REGISTRY_CONNECTION"
552
- );
553
- this.name = "RegistryConnectionError";
554
- }
555
- };
556
- var RegistryAuthError = class extends AgentBnBError {
557
- constructor(url) {
558
- super(
559
- `Authentication failed for ${url}. Run \`agentbnb config set token <your-token>\`.`,
560
- "REGISTRY_AUTH"
561
- );
562
- this.name = "RegistryAuthError";
563
- }
564
- };
565
- async function fetchRemoteCards(registryUrl, params, timeoutMs = 5e3) {
566
- let cardsUrl;
567
- try {
568
- cardsUrl = new URL("/cards", registryUrl);
569
- } catch {
570
- throw new AgentBnBError(`Invalid registry URL: ${registryUrl}`, "INVALID_REGISTRY_URL");
571
- }
572
- const searchParams = new URLSearchParams();
573
- if (params.q !== void 0) searchParams.set("q", params.q);
574
- if (params.level !== void 0) searchParams.set("level", String(params.level));
575
- if (params.online !== void 0) searchParams.set("online", String(params.online));
576
- if (params.tag !== void 0) searchParams.set("tag", params.tag);
577
- searchParams.set("limit", "100");
578
- cardsUrl.search = searchParams.toString();
579
- const controller = new AbortController();
580
- const timer = setTimeout(() => controller.abort(), timeoutMs);
581
- let response;
582
- try {
583
- response = await fetch(cardsUrl.toString(), { signal: controller.signal });
584
- } catch (err) {
585
- clearTimeout(timer);
586
- const isTimeout = err instanceof Error && err.name === "AbortError";
587
- if (isTimeout) {
588
- throw new RegistryTimeoutError(registryUrl);
589
- }
590
- throw new RegistryConnectionError(registryUrl);
591
- } finally {
592
- clearTimeout(timer);
593
- }
594
- if (response.status === 401 || response.status === 403) {
595
- throw new RegistryAuthError(registryUrl);
596
- }
597
- if (!response.ok) {
598
- throw new RegistryConnectionError(registryUrl);
599
- }
600
- const body = await response.json();
601
- return body.items;
602
- }
603
- function mergeResults(localCards, remoteCards, hasQuery) {
604
- const taggedLocal = localCards.map((c) => ({ ...c, source: "local" }));
605
- const taggedRemote = remoteCards.map((c) => ({ ...c, source: "remote" }));
606
- const localIds = new Set(localCards.map((c) => c.id));
607
- const dedupedRemote = taggedRemote.filter((c) => !localIds.has(c.id));
608
- if (!hasQuery) {
609
- return [...taggedLocal, ...dedupedRemote];
610
- }
611
- const result = [];
612
- const maxLen = Math.max(taggedLocal.length, dedupedRemote.length);
613
- for (let i = 0; i < maxLen; i++) {
614
- if (i < taggedLocal.length) result.push(taggedLocal[i]);
615
- if (i < dedupedRemote.length) result.push(dedupedRemote[i]);
616
- }
617
- return result;
618
- }
619
-
620
345
  // src/autonomy/auto-request.ts
621
346
  function minMaxNormalize(values) {
622
347
  if (values.length === 0) return [];
@@ -740,88 +465,189 @@ var AutoRequestor = class {
740
465
  }
741
466
  }
742
467
  const scored = scorePeers(candidates, this.owner);
468
+ const resolverOptions = {
469
+ registryDb: this.registryDb,
470
+ registryUrl: this.registryUrl,
471
+ onlineOnly: true
472
+ };
473
+ let resolvedTarget = null;
743
474
  if (scored.length === 0) {
475
+ resolvedTarget = await resolveTargetCapability(need.query, resolverOptions);
476
+ if (!resolvedTarget || resolvedTarget.owner === this.owner || resolvedTarget.credits_per_call > need.maxCostCredits) {
477
+ this.logFailure("auto_request_failed", "system", "none", 3, 0, "none", "No eligible peer found");
478
+ return { status: "no_peer", reason: "No eligible peer found" };
479
+ }
480
+ } else {
481
+ const top = scored[0];
482
+ const targetKey = top.skillId ?? top.card.id;
483
+ resolvedTarget = await resolveTargetCapability(targetKey, resolverOptions) ?? await resolveTargetCapability(need.query, resolverOptions);
484
+ if (!resolvedTarget || resolvedTarget.owner === this.owner) {
485
+ this.logFailure("auto_request_failed", top.card.id, top.skillId ?? "none", 3, top.cost, top.card.owner, "No eligible peer found");
486
+ return { status: "no_peer", reason: "No eligible peer found" };
487
+ }
488
+ }
489
+ if (!resolvedTarget) {
744
490
  this.logFailure("auto_request_failed", "system", "none", 3, 0, "none", "No eligible peer found");
745
491
  return { status: "no_peer", reason: "No eligible peer found" };
746
492
  }
747
- const top = scored[0];
748
- const peerConfig = findPeer(top.card.owner);
749
- if (!peerConfig) {
750
- this.logFailure("auto_request_failed", top.card.id, top.skillId ?? "none", 3, top.cost, top.card.owner, "No gateway config for peer");
751
- return { status: "no_peer", reason: "No gateway config for peer" };
752
- }
753
- const tier = getAutonomyTier(top.cost, this.autonomyConfig);
493
+ const selectedCardId = resolvedTarget.cardId;
494
+ const selectedSkillId = resolvedTarget.skillId;
495
+ const selectedPeer = resolvedTarget.owner;
496
+ const selectedCost = resolvedTarget.credits_per_call;
497
+ const selectedViaRelay = resolvedTarget.via_relay;
498
+ const tier = getAutonomyTier(selectedCost, this.autonomyConfig);
754
499
  if (tier === 3) {
755
500
  createPendingRequest(this.registryDb, {
756
501
  skill_query: need.query,
757
502
  max_cost_credits: need.maxCostCredits,
758
- credits: top.cost,
759
- selected_peer: top.card.owner,
760
- selected_card_id: top.card.id,
761
- selected_skill_id: top.skillId,
503
+ credits: selectedCost,
504
+ selected_peer: selectedPeer,
505
+ selected_card_id: selectedCardId,
506
+ selected_skill_id: selectedSkillId,
762
507
  params: need.params
763
508
  });
764
509
  insertAuditEvent(this.registryDb, {
765
510
  type: "auto_request_pending",
766
- card_id: top.card.id,
767
- skill_id: top.skillId ?? top.card.id,
511
+ card_id: selectedCardId,
512
+ skill_id: selectedSkillId ?? selectedCardId,
768
513
  tier_invoked: 3,
769
- credits: top.cost,
770
- peer: top.card.owner
514
+ credits: selectedCost,
515
+ peer: selectedPeer
771
516
  });
772
517
  return {
773
518
  status: "tier_blocked",
774
519
  reason: "Tier 3: owner approval required",
775
- peer: top.card.owner
520
+ peer: selectedPeer
776
521
  };
777
522
  }
778
- if (!this.budgetManager.canSpend(top.cost)) {
779
- this.logFailure("auto_request_failed", top.card.id, top.skillId ?? "none", tier, top.cost, top.card.owner, "Budget reserve would be breached");
523
+ if (!this.budgetManager.canSpend(selectedCost)) {
524
+ this.logFailure(
525
+ "auto_request_failed",
526
+ selectedCardId,
527
+ selectedSkillId ?? "none",
528
+ tier,
529
+ selectedCost,
530
+ selectedPeer,
531
+ "Budget reserve would be breached"
532
+ );
780
533
  return { status: "budget_blocked", reason: "Insufficient credits \u2014 reserve floor would be breached" };
781
534
  }
782
- const escrowId = holdEscrow(this.creditDb, this.owner, top.cost, top.card.id);
535
+ const escrowId = holdEscrow(this.creditDb, this.owner, selectedCost, selectedCardId);
783
536
  try {
784
- const execResult = await requestCapability({
785
- gatewayUrl: peerConfig.url,
786
- token: peerConfig.token,
787
- cardId: top.card.id,
788
- params: top.skillId ? { skill_id: top.skillId, ...need.params, requester: this.owner } : { ...need.params, requester: this.owner }
789
- });
790
- settleEscrow(this.creditDb, escrowId, top.card.owner);
537
+ const requestParams = selectedSkillId ? { skill_id: selectedSkillId, ...need.params, requester: this.owner } : { ...need.params, requester: this.owner };
538
+ let execResult;
539
+ if (selectedViaRelay) {
540
+ if (!this.registryUrl) {
541
+ this.logFailure(
542
+ "auto_request_failed",
543
+ selectedCardId,
544
+ selectedSkillId ?? "none",
545
+ tier,
546
+ selectedCost,
547
+ selectedPeer,
548
+ "Relay target found but registryUrl is not configured"
549
+ );
550
+ releaseEscrow(this.creditDb, escrowId);
551
+ return { status: "no_peer", reason: "Relay target found but registryUrl is not configured" };
552
+ }
553
+ const relayRequesterOwner = `${this.owner}:req:${randomUUID4()}`;
554
+ const { RelayClient } = await import("./websocket-client-4Z5P54RU.js");
555
+ const relayClient = new RelayClient({
556
+ registryUrl: this.registryUrl,
557
+ owner: relayRequesterOwner,
558
+ token: "auto-request-token",
559
+ card: {
560
+ spec_version: "1.0",
561
+ id: randomUUID4(),
562
+ owner: relayRequesterOwner,
563
+ name: relayRequesterOwner,
564
+ description: "Auto-request requester",
565
+ level: 1,
566
+ inputs: [],
567
+ outputs: [],
568
+ pricing: { credits_per_call: 1 },
569
+ availability: { online: false }
570
+ },
571
+ onRequest: async () => ({ error: { code: -32601, message: "Auto-request relay requester does not serve capabilities" } }),
572
+ silent: true
573
+ });
574
+ try {
575
+ await relayClient.connect();
576
+ execResult = await requestViaRelay(relayClient, {
577
+ targetOwner: selectedPeer,
578
+ cardId: selectedCardId,
579
+ skillId: selectedSkillId,
580
+ params: requestParams,
581
+ requester: this.owner
582
+ });
583
+ } finally {
584
+ relayClient.disconnect();
585
+ }
586
+ } else {
587
+ const peerConfig = findPeer(selectedPeer);
588
+ if (!peerConfig) {
589
+ this.logFailure(
590
+ "auto_request_failed",
591
+ selectedCardId,
592
+ selectedSkillId ?? "none",
593
+ tier,
594
+ selectedCost,
595
+ selectedPeer,
596
+ "No gateway config for peer"
597
+ );
598
+ releaseEscrow(this.creditDb, escrowId);
599
+ return { status: "no_peer", reason: "No gateway config for peer" };
600
+ }
601
+ execResult = await requestCapability({
602
+ gatewayUrl: peerConfig.url,
603
+ token: peerConfig.token,
604
+ cardId: selectedCardId,
605
+ params: requestParams
606
+ });
607
+ }
608
+ settleEscrow(this.creditDb, escrowId, selectedPeer);
791
609
  if (tier === 2) {
792
610
  insertAuditEvent(this.registryDb, {
793
611
  type: "auto_request_notify",
794
- card_id: top.card.id,
795
- skill_id: top.skillId ?? top.card.id,
612
+ card_id: selectedCardId,
613
+ skill_id: selectedSkillId ?? selectedCardId,
796
614
  tier_invoked: 2,
797
- credits: top.cost,
798
- peer: top.card.owner
615
+ credits: selectedCost,
616
+ peer: selectedPeer
799
617
  });
800
618
  } else {
801
619
  insertAuditEvent(this.registryDb, {
802
620
  type: "auto_request",
803
- card_id: top.card.id,
804
- skill_id: top.skillId ?? top.card.id,
621
+ card_id: selectedCardId,
622
+ skill_id: selectedSkillId ?? selectedCardId,
805
623
  tier_invoked: 1,
806
- credits: top.cost,
807
- peer: top.card.owner
624
+ credits: selectedCost,
625
+ peer: selectedPeer
808
626
  });
809
627
  }
810
628
  return {
811
629
  status: "success",
812
630
  result: execResult,
813
631
  escrowId,
814
- peer: top.card.owner,
815
- creditsSpent: top.cost
632
+ peer: selectedPeer,
633
+ creditsSpent: selectedCost
816
634
  };
817
635
  } catch (err) {
818
636
  releaseEscrow(this.creditDb, escrowId);
819
637
  const reason = err instanceof Error ? err.message : String(err);
820
- this.logFailure("auto_request_failed", top.card.id, top.skillId ?? "none", tier, top.cost, top.card.owner, `Execution failed: ${reason}`);
638
+ this.logFailure(
639
+ "auto_request_failed",
640
+ selectedCardId,
641
+ selectedSkillId ?? "none",
642
+ tier,
643
+ selectedCost,
644
+ selectedPeer,
645
+ `Execution failed: ${reason}`
646
+ );
821
647
  return {
822
648
  status: "failed",
823
649
  reason: `Execution failed: ${reason}`,
824
- peer: top.card.owner
650
+ peer: selectedPeer
825
651
  };
826
652
  }
827
653
  }
@@ -1087,6 +913,65 @@ function computeWaves(subtasks) {
1087
913
  }
1088
914
  return waves;
1089
915
  }
916
+ async function executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl) {
917
+ const { taskId, match: m, interpolatedParams, primary, teamId, capabilityType } = pt;
918
+ try {
919
+ let res;
920
+ if (primary.url.startsWith("relay://") && relayClient) {
921
+ const targetOwner = primary.url.replace("relay://", "");
922
+ res = await relayClient.request({
923
+ targetOwner,
924
+ cardId: primary.cardId,
925
+ params: interpolatedParams,
926
+ requester: requesterOwner,
927
+ timeoutMs
928
+ });
929
+ } else {
930
+ res = await requestCapability({
931
+ gatewayUrl: primary.url,
932
+ token: gatewayToken,
933
+ cardId: primary.cardId,
934
+ params: { ...interpolatedParams, requester: requesterOwner },
935
+ timeoutMs
936
+ });
937
+ }
938
+ return { taskId, result: res, credits: m.credits, team_id: teamId, capability_type: capabilityType };
939
+ } catch (primaryErr) {
940
+ if (m.alternatives.length > 0) {
941
+ const alt = m.alternatives[0];
942
+ const altResolved = resolveAgentUrl ? resolveAgentUrl(alt.agent) : { url: `http://${alt.agent}:7700`, cardId: `card-${alt.agent}` };
943
+ try {
944
+ let altRes;
945
+ if (altResolved.url.startsWith("relay://") && relayClient) {
946
+ const targetOwner = altResolved.url.replace("relay://", "");
947
+ altRes = await relayClient.request({
948
+ targetOwner,
949
+ cardId: altResolved.cardId,
950
+ params: interpolatedParams,
951
+ requester: requesterOwner,
952
+ timeoutMs
953
+ });
954
+ } else {
955
+ altRes = await requestCapability({
956
+ gatewayUrl: altResolved.url,
957
+ token: gatewayToken,
958
+ cardId: altResolved.cardId,
959
+ params: { ...interpolatedParams, requester: requesterOwner },
960
+ timeoutMs
961
+ });
962
+ }
963
+ return { taskId, result: altRes, credits: alt.credits, team_id: teamId, capability_type: capabilityType };
964
+ } catch (altErr) {
965
+ throw new Error(
966
+ `Task ${taskId}: primary (${m.selected_agent}) failed: ${primaryErr instanceof Error ? primaryErr.message : String(primaryErr)}; alternative (${alt.agent}) failed: ${altErr instanceof Error ? altErr.message : String(altErr)}`
967
+ );
968
+ }
969
+ }
970
+ throw new Error(
971
+ `Task ${taskId}: ${primaryErr instanceof Error ? primaryErr.message : String(primaryErr)}`
972
+ );
973
+ }
974
+ }
1090
975
  async function orchestrate(opts) {
1091
976
  const { subtasks, matches, gatewayToken, resolveAgentUrl, timeoutMs = 3e5, maxBudget, relayClient, requesterOwner } = opts;
1092
977
  const startTime = Date.now();
@@ -1124,89 +1009,127 @@ async function orchestrate(opts) {
1124
1009
  }
1125
1010
  executableIds.push(taskId);
1126
1011
  }
1127
- const waveResults = await Promise.allSettled(
1128
- executableIds.map(async (taskId) => {
1129
- const subtask = subtaskMap.get(taskId);
1130
- const m = matches.get(taskId);
1131
- if (!m) {
1132
- throw new Error(`No match found for subtask ${taskId}`);
1133
- }
1134
- const stepsContext = {};
1135
- for (const [id, val] of results) {
1136
- stepsContext[id] = val;
1137
- }
1138
- const interpContext = { steps: stepsContext, prev: void 0 };
1139
- if (subtask.depends_on.length > 0) {
1140
- const lastDep = subtask.depends_on[subtask.depends_on.length - 1];
1141
- interpContext.prev = results.get(lastDep);
1142
- }
1143
- const interpolatedParams = interpolateObject(
1144
- subtask.params,
1145
- interpContext
1146
- );
1147
- const teamMember = teamMemberMap.get(taskId);
1148
- const teamId = opts.team?.team_id ?? null;
1149
- const taskCapabilityType = teamMember?.capability_type ?? null;
1150
- const agentOwner = teamMember?.agent ?? m.selected_agent;
1151
- const primary = resolveAgentUrl(agentOwner);
1152
- try {
1153
- let res;
1154
- if (primary.url.startsWith("relay://") && relayClient) {
1155
- const targetOwner = primary.url.replace("relay://", "");
1156
- res = await relayClient.request({
1157
- targetOwner,
1158
- cardId: primary.cardId,
1159
- params: interpolatedParams,
1160
- requester: requesterOwner,
1161
- timeoutMs
1162
- });
1163
- } else {
1164
- res = await requestCapability({
1165
- gatewayUrl: primary.url,
1166
- token: gatewayToken,
1167
- cardId: primary.cardId,
1168
- params: { ...interpolatedParams, requester: requesterOwner },
1169
- timeoutMs
1170
- });
1171
- }
1172
- return { taskId, result: res, credits: m.credits, team_id: teamId, capability_type: taskCapabilityType };
1173
- } catch (primaryErr) {
1174
- if (m.alternatives.length > 0) {
1175
- const alt = m.alternatives[0];
1176
- const altAgent = resolveAgentUrl(alt.agent);
1012
+ const preparedTasks = [];
1013
+ for (const taskId of executableIds) {
1014
+ const subtask = subtaskMap.get(taskId);
1015
+ const m = matches.get(taskId);
1016
+ if (!m) {
1017
+ errors.push(`No match found for subtask ${taskId}`);
1018
+ continue;
1019
+ }
1020
+ const stepsContext = {};
1021
+ for (const [id, val] of results) stepsContext[id] = val;
1022
+ const interpContext = { steps: stepsContext, prev: void 0 };
1023
+ if (subtask.depends_on.length > 0) {
1024
+ const lastDep = subtask.depends_on[subtask.depends_on.length - 1];
1025
+ interpContext.prev = results.get(lastDep);
1026
+ }
1027
+ const interpolatedParams = interpolateObject(
1028
+ subtask.params,
1029
+ interpContext
1030
+ );
1031
+ const teamMember = teamMemberMap.get(taskId);
1032
+ const agentOwner = teamMember?.agent ?? m.selected_agent;
1033
+ const primary = resolveAgentUrl(agentOwner);
1034
+ preparedTasks.push({
1035
+ taskId,
1036
+ subtask,
1037
+ match: m,
1038
+ interpolatedParams,
1039
+ agentOwner,
1040
+ primary,
1041
+ teamId: opts.team?.team_id ?? null,
1042
+ capabilityType: teamMember?.capability_type ?? null
1043
+ });
1044
+ }
1045
+ const httpGroups = /* @__PURE__ */ new Map();
1046
+ const relayTasks = [];
1047
+ for (const pt of preparedTasks) {
1048
+ if (pt.primary.url.startsWith("relay://") && relayClient) {
1049
+ relayTasks.push(pt);
1050
+ } else {
1051
+ const group = httpGroups.get(pt.primary.url) ?? [];
1052
+ group.push(pt);
1053
+ httpGroups.set(pt.primary.url, group);
1054
+ }
1055
+ }
1056
+ const batchPromises = [];
1057
+ for (const [gatewayUrl, group] of httpGroups) {
1058
+ if (group.length >= 2) {
1059
+ batchPromises.push(
1060
+ (async () => {
1061
+ const items = group.map((pt) => ({
1062
+ id: pt.taskId,
1063
+ cardId: pt.primary.cardId,
1064
+ params: { ...pt.interpolatedParams, requester: requesterOwner },
1065
+ _pt: pt
1066
+ }));
1177
1067
  try {
1178
- let altRes;
1179
- if (altAgent.url.startsWith("relay://") && relayClient) {
1180
- const targetOwner = altAgent.url.replace("relay://", "");
1181
- altRes = await relayClient.request({
1182
- targetOwner,
1183
- cardId: altAgent.cardId,
1184
- params: interpolatedParams,
1185
- requester: requesterOwner,
1186
- timeoutMs
1187
- });
1188
- } else {
1189
- altRes = await requestCapability({
1190
- gatewayUrl: altAgent.url,
1191
- token: gatewayToken,
1192
- cardId: altAgent.cardId,
1193
- params: { ...interpolatedParams, requester: requesterOwner },
1194
- timeoutMs
1195
- });
1196
- }
1197
- return { taskId, result: altRes, credits: alt.credits, team_id: teamId, capability_type: taskCapabilityType };
1198
- } catch (altErr) {
1199
- throw new Error(
1200
- `Task ${taskId}: primary (${m.selected_agent}) failed: ${primaryErr instanceof Error ? primaryErr.message : String(primaryErr)}; alternative (${alt.agent}) failed: ${altErr instanceof Error ? altErr.message : String(altErr)}`
1068
+ const batchResults = await requestCapabilityBatch(
1069
+ gatewayUrl,
1070
+ gatewayToken,
1071
+ items.map(({ _pt, ...item }) => item),
1072
+ { timeoutMs }
1201
1073
  );
1074
+ return items.map((item) => {
1075
+ const res = batchResults.get(item.id);
1076
+ if (res instanceof Error) {
1077
+ return {
1078
+ status: "rejected",
1079
+ reason: new Error(`Task ${item.id}: ${res.message}`)
1080
+ };
1081
+ }
1082
+ return {
1083
+ status: "fulfilled",
1084
+ value: {
1085
+ taskId: item.id,
1086
+ result: res,
1087
+ credits: item._pt.match.credits,
1088
+ team_id: item._pt.teamId,
1089
+ capability_type: item._pt.capabilityType
1090
+ }
1091
+ };
1092
+ });
1093
+ } catch (batchErr) {
1094
+ return Promise.all(group.map(async (pt) => {
1095
+ try {
1096
+ const res = await executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl);
1097
+ return { status: "fulfilled", value: res };
1098
+ } catch (err) {
1099
+ return { status: "rejected", reason: err };
1100
+ }
1101
+ }));
1202
1102
  }
1103
+ })()
1104
+ );
1105
+ } else {
1106
+ const pt = group[0];
1107
+ batchPromises.push(
1108
+ (async () => {
1109
+ try {
1110
+ const res = await executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl);
1111
+ return [{ status: "fulfilled", value: res }];
1112
+ } catch (err) {
1113
+ return [{ status: "rejected", reason: err }];
1114
+ }
1115
+ })()
1116
+ );
1117
+ }
1118
+ }
1119
+ for (const pt of relayTasks) {
1120
+ batchPromises.push(
1121
+ (async () => {
1122
+ try {
1123
+ const res = await executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl);
1124
+ return [{ status: "fulfilled", value: res }];
1125
+ } catch (err) {
1126
+ return [{ status: "rejected", reason: err }];
1203
1127
  }
1204
- throw new Error(
1205
- `Task ${taskId}: ${primaryErr instanceof Error ? primaryErr.message : String(primaryErr)}`
1206
- );
1207
- }
1208
- })
1209
- );
1128
+ })()
1129
+ );
1130
+ }
1131
+ const allBatchResults = await Promise.all(batchPromises);
1132
+ const waveResults = allBatchResults.flat();
1210
1133
  for (const settlement of waveResults) {
1211
1134
  if (settlement.status === "fulfilled") {
1212
1135
  const { taskId, result, credits, team_id, capability_type } = settlement.value;
@@ -1232,19 +1155,11 @@ export {
1232
1155
  interpolateObject,
1233
1156
  validateAndNormalizeSubtasks,
1234
1157
  decompose,
1235
- computeReputation,
1236
- searchCards,
1237
- filterCards,
1238
- buildReputationMap,
1239
- requestCapability,
1240
- requestViaRelay,
1241
1158
  DEFAULT_AUTONOMY_CONFIG,
1242
1159
  getAutonomyTier,
1243
1160
  insertAuditEvent,
1244
1161
  listPendingRequests,
1245
1162
  resolvePendingRequest,
1246
- fetchRemoteCards,
1247
- mergeResults,
1248
1163
  AutoRequestor,
1249
1164
  matchSubTasks,
1250
1165
  ORCHESTRATION_FEE,