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
@@ -2,6 +2,9 @@ import {
2
2
  ensureReliabilityTable,
3
3
  recordSuccessfulHire
4
4
  } from "./chunk-NWIQJ2CL.js";
5
+ import {
6
+ getFeedbackForProvider
7
+ } from "./chunk-S3V6R3EN.js";
5
8
  import {
6
9
  AgentBnBError
7
10
  } from "./chunk-WVY2W7AA.js";
@@ -149,10 +152,23 @@ function getBalance(db, owner) {
149
152
  const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(owner);
150
153
  return row?.balance ?? 0;
151
154
  }
152
- function getTransactions(db, owner, limit = 100) {
155
+ function getTransactions(db, owner, opts = 100) {
156
+ const page = typeof opts === "number" ? { limit: opts } : opts;
157
+ const limit = page.limit ?? 100;
158
+ const conditions = ["owner = ?"];
159
+ const params = [owner];
160
+ if (page.before) {
161
+ conditions.push("created_at < ?");
162
+ params.push(page.before);
163
+ }
164
+ if (page.after) {
165
+ conditions.push("created_at > ?");
166
+ params.push(page.after);
167
+ }
168
+ params.push(limit);
153
169
  return db.prepare(
154
- "SELECT id, owner, amount, reason, reference_id, created_at FROM credit_transactions WHERE owner = ? ORDER BY created_at DESC LIMIT ?"
155
- ).all(owner, limit);
170
+ `SELECT id, owner, amount, reason, reference_id, created_at FROM credit_transactions WHERE ${conditions.join(" AND ")} ORDER BY created_at DESC LIMIT ?`
171
+ ).all(...params);
156
172
  }
157
173
  function registerProvider(db, owner) {
158
174
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -377,6 +393,282 @@ function confirmEscrowDebit(db, escrowId) {
377
393
  confirm();
378
394
  }
379
395
 
396
+ // src/feedback/reputation.ts
397
+ var QUALITY_SCORES = {
398
+ excellent: 1,
399
+ good: 0.8,
400
+ acceptable: 0.6,
401
+ poor: 0.3,
402
+ failed: 0
403
+ };
404
+ var COST_VALUE_SCORES = {
405
+ great: 1,
406
+ fair: 0.6,
407
+ overpriced: 0.2
408
+ };
409
+ var DECAY_DAYS = 30;
410
+ var WEIGHTS = {
411
+ rating: 0.4,
412
+ quality: 0.3,
413
+ would_reuse: 0.2,
414
+ cost_value: 0.1
415
+ };
416
+ function computeReputation(feedbacks) {
417
+ if (feedbacks.length === 0) return 0.5;
418
+ const now = Date.now();
419
+ let weightedSum = 0;
420
+ let totalWeight = 0;
421
+ for (const fb of feedbacks) {
422
+ const feedbackDate = new Date(fb.timestamp).getTime();
423
+ const ageDays = Math.max(0, (now - feedbackDate) / (1e3 * 60 * 60 * 24));
424
+ const recencyWeight = Math.exp(-ageDays / DECAY_DAYS);
425
+ const ratingScore = (fb.rating - 1) / 4;
426
+ const qualityScore = QUALITY_SCORES[fb.result_quality];
427
+ const reuseScore = fb.would_reuse ? 1 : 0;
428
+ const costScore = COST_VALUE_SCORES[fb.cost_value_ratio];
429
+ const componentScore = WEIGHTS.rating * ratingScore + WEIGHTS.quality * qualityScore + WEIGHTS.would_reuse * reuseScore + WEIGHTS.cost_value * costScore;
430
+ weightedSum += recencyWeight * componentScore;
431
+ totalWeight += recencyWeight;
432
+ }
433
+ if (totalWeight === 0) return 0.5;
434
+ const raw = weightedSum / totalWeight;
435
+ return Math.max(0, Math.min(1, raw));
436
+ }
437
+ function getReputationScore(db, agentId) {
438
+ const feedbacks = getFeedbackForProvider(db, agentId);
439
+ return computeReputation(feedbacks);
440
+ }
441
+
442
+ // src/registry/matcher.ts
443
+ var CACHE_MAX_ENTRIES = 100;
444
+ var CACHE_TTL_MS = 3e4;
445
+ var dbCaches = /* @__PURE__ */ new WeakMap();
446
+ function getDbCache(db) {
447
+ let cache = dbCaches.get(db);
448
+ if (!cache) {
449
+ cache = /* @__PURE__ */ new Map();
450
+ dbCaches.set(db, cache);
451
+ }
452
+ return cache;
453
+ }
454
+ function cacheKey(query, filters) {
455
+ return `${query}|${filters.level ?? ""}|${filters.online ?? ""}|${(filters.apis_used ?? []).join(",")}|${filters.min_reputation ?? ""}`;
456
+ }
457
+ function evictCache(cache) {
458
+ const now = Date.now();
459
+ for (const [key, entry] of cache) {
460
+ if (entry.expiresAt <= now) cache.delete(key);
461
+ }
462
+ while (cache.size > CACHE_MAX_ENTRIES) {
463
+ const firstKey = cache.keys().next().value;
464
+ cache.delete(firstKey);
465
+ }
466
+ }
467
+ function searchCards(db, query, filters = {}) {
468
+ const cache = getDbCache(db);
469
+ const key = cacheKey(query, filters);
470
+ const cached = cache.get(key);
471
+ if (cached && cached.expiresAt > Date.now()) {
472
+ return cached.results;
473
+ }
474
+ const trimmedQuery = query.trim();
475
+ const exactSkillMatches = findCardsByExactSkillId(db, trimmedQuery, filters);
476
+ const words = query.trim().split(/\s+/).map((w) => w.replace(/["*^{}():]/g, "")).filter((w) => w.length > 0);
477
+ if (words.length === 0) {
478
+ return exactSkillMatches;
479
+ }
480
+ const ftsQuery = words.map((w) => `"${w}"`).join(" OR ");
481
+ const conditions = [];
482
+ const params = [ftsQuery];
483
+ if (filters.level !== void 0) {
484
+ conditions.push(`json_extract(cc.data, '$.level') = ?`);
485
+ params.push(filters.level);
486
+ }
487
+ if (filters.online !== void 0) {
488
+ conditions.push(`json_extract(cc.data, '$.availability.online') = ?`);
489
+ params.push(filters.online ? 1 : 0);
490
+ }
491
+ const whereClause = conditions.length > 0 ? `AND ${conditions.join(" AND ")}` : "";
492
+ const sql = `
493
+ SELECT cc.data
494
+ FROM capability_cards cc
495
+ JOIN cards_fts ON cc.rowid = cards_fts.rowid
496
+ WHERE cards_fts MATCH ?
497
+ ${whereClause}
498
+ ORDER BY bm25(cards_fts)
499
+ LIMIT 50
500
+ `;
501
+ const stmt = db.prepare(sql);
502
+ const rows = stmt.all(...params);
503
+ const results = rows.map((row) => JSON.parse(row.data));
504
+ const mergedResults = mergeByCardId(exactSkillMatches, results);
505
+ let filtered = mergedResults;
506
+ if (filters.apis_used && filters.apis_used.length > 0) {
507
+ const requiredApis = filters.apis_used;
508
+ filtered = filtered.filter((card) => {
509
+ const cardApis = card.metadata?.apis_used ?? [];
510
+ return requiredApis.every((api) => cardApis.includes(api));
511
+ });
512
+ }
513
+ if (filters.min_reputation !== void 0 && filters.min_reputation > 0) {
514
+ filtered = applyReputationFilter(db, filtered, filters.min_reputation);
515
+ }
516
+ evictCache(cache);
517
+ cache.set(key, { results: filtered, expiresAt: Date.now() + CACHE_TTL_MS });
518
+ return filtered;
519
+ }
520
+ function mergeByCardId(primary, secondary) {
521
+ const seen = /* @__PURE__ */ new Set();
522
+ const merged = [];
523
+ for (const card of primary) {
524
+ if (seen.has(card.id)) continue;
525
+ seen.add(card.id);
526
+ merged.push(card);
527
+ }
528
+ for (const card of secondary) {
529
+ if (seen.has(card.id)) continue;
530
+ seen.add(card.id);
531
+ merged.push(card);
532
+ }
533
+ return merged;
534
+ }
535
+ function findCardsByExactSkillId(db, query, filters) {
536
+ if (query.length === 0) return [];
537
+ const rows = db.prepare("SELECT data FROM capability_cards").all();
538
+ const cards = rows.map((row) => JSON.parse(row.data));
539
+ return cards.filter((card) => {
540
+ if (filters.level !== void 0 && card.level !== filters.level) return false;
541
+ if (filters.online !== void 0 && card.availability?.online !== filters.online) return false;
542
+ const asRecord = card;
543
+ const skills = asRecord["skills"];
544
+ if (!Array.isArray(skills)) return false;
545
+ return skills.some((skill) => String(skill["id"] ?? "") === query);
546
+ });
547
+ }
548
+ function filterCards(db, filters) {
549
+ const conditions = [];
550
+ const params = [];
551
+ if (filters.level !== void 0) {
552
+ conditions.push(`json_extract(data, '$.level') = ?`);
553
+ params.push(filters.level);
554
+ }
555
+ if (filters.online !== void 0) {
556
+ conditions.push(`json_extract(data, '$.availability.online') = ?`);
557
+ params.push(filters.online ? 1 : 0);
558
+ }
559
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
560
+ const sql = `SELECT data FROM capability_cards ${whereClause}`;
561
+ const stmt = db.prepare(sql);
562
+ const rows = stmt.all(...params);
563
+ let cards = rows.map((row) => JSON.parse(row.data));
564
+ if (filters.min_reputation !== void 0 && filters.min_reputation > 0) {
565
+ cards = applyReputationFilter(db, cards, filters.min_reputation);
566
+ }
567
+ return cards;
568
+ }
569
+ function applyReputationFilter(db, cards, minReputation) {
570
+ const owners = [...new Set(cards.map((c) => c.owner))];
571
+ const reputationMap = /* @__PURE__ */ new Map();
572
+ for (const owner of owners) {
573
+ reputationMap.set(owner, getReputationScore(db, owner));
574
+ }
575
+ return cards.filter((card) => {
576
+ const score = reputationMap.get(card.owner) ?? 0.5;
577
+ return score >= minReputation;
578
+ });
579
+ }
580
+ function buildReputationMap(db, owners) {
581
+ const unique = [...new Set(owners)];
582
+ const map = /* @__PURE__ */ new Map();
583
+ for (const owner of unique) {
584
+ map.set(owner, getReputationScore(db, owner));
585
+ }
586
+ return map;
587
+ }
588
+
589
+ // src/cli/remote-registry.ts
590
+ var RegistryTimeoutError = class extends AgentBnBError {
591
+ constructor(url) {
592
+ super(
593
+ `Registry at ${url} did not respond within 5s. Showing local results only.`,
594
+ "REGISTRY_TIMEOUT"
595
+ );
596
+ this.name = "RegistryTimeoutError";
597
+ }
598
+ };
599
+ var RegistryConnectionError = class extends AgentBnBError {
600
+ constructor(url) {
601
+ super(
602
+ `Cannot reach ${url}. Is the registry running? Showing local results only.`,
603
+ "REGISTRY_CONNECTION"
604
+ );
605
+ this.name = "RegistryConnectionError";
606
+ }
607
+ };
608
+ var RegistryAuthError = class extends AgentBnBError {
609
+ constructor(url) {
610
+ super(
611
+ `Authentication failed for ${url}. Run \`agentbnb config set token <your-token>\`.`,
612
+ "REGISTRY_AUTH"
613
+ );
614
+ this.name = "RegistryAuthError";
615
+ }
616
+ };
617
+ async function fetchRemoteCards(registryUrl, params, timeoutMs = 5e3) {
618
+ let cardsUrl;
619
+ try {
620
+ cardsUrl = new URL("/cards", registryUrl);
621
+ } catch {
622
+ throw new AgentBnBError(`Invalid registry URL: ${registryUrl}`, "INVALID_REGISTRY_URL");
623
+ }
624
+ const searchParams = new URLSearchParams();
625
+ if (params.q !== void 0) searchParams.set("q", params.q);
626
+ if (params.level !== void 0) searchParams.set("level", String(params.level));
627
+ if (params.online !== void 0) searchParams.set("online", String(params.online));
628
+ if (params.tag !== void 0) searchParams.set("tag", params.tag);
629
+ searchParams.set("limit", "100");
630
+ cardsUrl.search = searchParams.toString();
631
+ const controller = new AbortController();
632
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
633
+ let response;
634
+ try {
635
+ response = await fetch(cardsUrl.toString(), { signal: controller.signal });
636
+ } catch (err) {
637
+ clearTimeout(timer);
638
+ const isTimeout = err instanceof Error && err.name === "AbortError";
639
+ if (isTimeout) {
640
+ throw new RegistryTimeoutError(registryUrl);
641
+ }
642
+ throw new RegistryConnectionError(registryUrl);
643
+ } finally {
644
+ clearTimeout(timer);
645
+ }
646
+ if (response.status === 401 || response.status === 403) {
647
+ throw new RegistryAuthError(registryUrl);
648
+ }
649
+ if (!response.ok) {
650
+ throw new RegistryConnectionError(registryUrl);
651
+ }
652
+ const body = await response.json();
653
+ return body.items;
654
+ }
655
+ function mergeResults(localCards, remoteCards, hasQuery) {
656
+ const taggedLocal = localCards.map((c) => ({ ...c, source: "local" }));
657
+ const taggedRemote = remoteCards.map((c) => ({ ...c, source: "remote" }));
658
+ const localIds = new Set(localCards.map((c) => c.id));
659
+ const dedupedRemote = taggedRemote.filter((c) => !localIds.has(c.id));
660
+ if (!hasQuery) {
661
+ return [...taggedLocal, ...dedupedRemote];
662
+ }
663
+ const result = [];
664
+ const maxLen = Math.max(taggedLocal.length, dedupedRemote.length);
665
+ for (let i = 0; i < maxLen; i++) {
666
+ if (i < taggedLocal.length) result.push(taggedLocal[i]);
667
+ if (i < dedupedRemote.length) result.push(dedupedRemote[i]);
668
+ }
669
+ return result;
670
+ }
671
+
380
672
  export {
381
673
  createAgentRecord,
382
674
  lookupAgent,
@@ -391,5 +683,11 @@ export {
391
683
  holdEscrow,
392
684
  settleEscrow,
393
685
  releaseEscrow,
394
- confirmEscrowDebit
686
+ confirmEscrowDebit,
687
+ computeReputation,
688
+ searchCards,
689
+ filterCards,
690
+ buildReputationMap,
691
+ fetchRemoteCards,
692
+ mergeResults
395
693
  };
@@ -315,7 +315,10 @@ var V2_FTS_TRIGGERS = `
315
315
  new.id,
316
316
  new.owner,
317
317
  COALESCE(
318
- (SELECT group_concat(json_extract(value, '$.name'), ' ')
318
+ (SELECT group_concat(
319
+ COALESCE(json_extract(value, '$.id'), '') || ' ' || COALESCE(json_extract(value, '$.name'), ''),
320
+ ' '
321
+ )
319
322
  FROM json_each(json_extract(new.data, '$.skills'))),
320
323
  json_extract(new.data, '$.name'),
321
324
  ''
@@ -355,7 +358,10 @@ var V2_FTS_TRIGGERS = `
355
358
  old.id,
356
359
  old.owner,
357
360
  COALESCE(
358
- (SELECT group_concat(json_extract(value, '$.name'), ' ')
361
+ (SELECT group_concat(
362
+ COALESCE(json_extract(value, '$.id'), '') || ' ' || COALESCE(json_extract(value, '$.name'), ''),
363
+ ' '
364
+ )
359
365
  FROM json_each(json_extract(old.data, '$.skills'))),
360
366
  json_extract(old.data, '$.name'),
361
367
  ''
@@ -391,7 +397,10 @@ var V2_FTS_TRIGGERS = `
391
397
  new.id,
392
398
  new.owner,
393
399
  COALESCE(
394
- (SELECT group_concat(json_extract(value, '$.name'), ' ')
400
+ (SELECT group_concat(
401
+ COALESCE(json_extract(value, '$.id'), '') || ' ' || COALESCE(json_extract(value, '$.name'), ''),
402
+ ' '
403
+ )
395
404
  FROM json_each(json_extract(new.data, '$.skills'))),
396
405
  json_extract(new.data, '$.name'),
397
406
  ''
@@ -431,7 +440,10 @@ var V2_FTS_TRIGGERS = `
431
440
  old.id,
432
441
  old.owner,
433
442
  COALESCE(
434
- (SELECT group_concat(json_extract(value, '$.name'), ' ')
443
+ (SELECT group_concat(
444
+ COALESCE(json_extract(value, '$.id'), '') || ' ' || COALESCE(json_extract(value, '$.name'), ''),
445
+ ' '
446
+ )
435
447
  FROM json_each(json_extract(old.data, '$.skills'))),
436
448
  json_extract(old.data, '$.name'),
437
449
  ''
@@ -498,6 +510,15 @@ function openDatabase(path = ":memory:") {
498
510
  tags,
499
511
  content=""
500
512
  );
513
+
514
+ -- Expression index for capability_type lookups (used by Conductor routing).
515
+ -- Turns json_extract full-table-scan into O(log n) B-tree lookup.
516
+ CREATE INDEX IF NOT EXISTS idx_cards_capability_type
517
+ ON capability_cards(json_extract(data, '$.capability_type'));
518
+
519
+ -- Owner index for listCards(owner) and other owner-scoped queries.
520
+ CREATE INDEX IF NOT EXISTS idx_cards_owner
521
+ ON capability_cards(owner);
501
522
  `);
502
523
  createRequestLogTable(db);
503
524
  initFeedbackTable(db);
@@ -509,6 +530,10 @@ function runMigrations(db) {
509
530
  const version = db.pragma("user_version")[0]?.user_version ?? 0;
510
531
  if (version < 2) {
511
532
  migrateV1toV2(db);
533
+ return;
534
+ }
535
+ if (version < 3) {
536
+ migrateV2toV3(db);
512
537
  }
513
538
  }
514
539
  function migrateV1toV2(db) {
@@ -550,44 +575,55 @@ function migrateV1toV2(db) {
550
575
  );
551
576
  }
552
577
  db.exec(V2_FTS_TRIGGERS);
553
- db.exec(`INSERT INTO cards_fts(cards_fts) VALUES('delete-all')`);
554
- const allRows = db.prepare("SELECT rowid, id, owner, data FROM capability_cards").all();
555
- const ftsInsert = db.prepare(
556
- "INSERT INTO cards_fts(rowid, id, owner, name, description, tags) VALUES (?, ?, ?, ?, ?, ?)"
557
- );
558
- for (const row of allRows) {
559
- const data = JSON.parse(row.data);
560
- const skills = data["skills"] ?? [];
561
- let name;
562
- let description;
563
- let tags;
564
- if (skills.length > 0) {
565
- name = skills.map((s) => String(s["name"] ?? "")).join(" ");
566
- description = skills.map((s) => String(s["description"] ?? "")).join(" ");
567
- tags = [
568
- // tags from metadata.tags[]
569
- ...skills.flatMap((s) => {
570
- const meta = s["metadata"];
571
- return meta?.["tags"] ?? [];
572
- }),
573
- // capability_type (singular)
574
- ...skills.map((s) => s["capability_type"]).filter((v) => typeof v === "string" && v.length > 0),
575
- // capability_types[] (plural)
576
- ...skills.flatMap((s) => s["capability_types"] ?? [])
577
- ].join(" ");
578
- } else {
579
- name = String(data["name"] ?? "");
580
- description = String(data["description"] ?? "");
581
- const meta = data["metadata"];
582
- const rawTags = meta?.["tags"] ?? [];
583
- tags = rawTags.join(" ");
584
- }
585
- ftsInsert.run(row.rowid, row.id, row.owner, name, description, tags);
586
- }
587
- db.pragma("user_version = 2");
578
+ rebuildCardsFts(db);
579
+ db.pragma("user_version = 3");
580
+ });
581
+ migrate();
582
+ }
583
+ function migrateV2toV3(db) {
584
+ const migrate = db.transaction(() => {
585
+ db.exec(V2_FTS_TRIGGERS);
586
+ rebuildCardsFts(db);
587
+ db.pragma("user_version = 3");
588
588
  });
589
589
  migrate();
590
590
  }
591
+ function rebuildCardsFts(db) {
592
+ db.exec(`INSERT INTO cards_fts(cards_fts) VALUES('delete-all')`);
593
+ const allRows = db.prepare("SELECT rowid, id, owner, data FROM capability_cards").all();
594
+ const ftsInsert = db.prepare(
595
+ "INSERT INTO cards_fts(rowid, id, owner, name, description, tags) VALUES (?, ?, ?, ?, ?, ?)"
596
+ );
597
+ for (const row of allRows) {
598
+ const data = JSON.parse(row.data);
599
+ const skills = data["skills"] ?? [];
600
+ let name;
601
+ let description;
602
+ let tags;
603
+ if (skills.length > 0) {
604
+ name = skills.map((s) => `${String(s["id"] ?? "")} ${String(s["name"] ?? "")}`.trim()).join(" ");
605
+ description = skills.map((s) => String(s["description"] ?? "")).join(" ");
606
+ tags = [
607
+ // tags from metadata.tags[]
608
+ ...skills.flatMap((s) => {
609
+ const meta = s["metadata"];
610
+ return meta?.["tags"] ?? [];
611
+ }),
612
+ // capability_type (singular)
613
+ ...skills.map((s) => s["capability_type"]).filter((v) => typeof v === "string" && v.length > 0),
614
+ // capability_types[] (plural)
615
+ ...skills.flatMap((s) => s["capability_types"] ?? [])
616
+ ].join(" ");
617
+ } else {
618
+ name = String(data["name"] ?? "");
619
+ description = String(data["description"] ?? "");
620
+ const meta = data["metadata"];
621
+ const rawTags = meta?.["tags"] ?? [];
622
+ tags = rawTags.join(" ");
623
+ }
624
+ ftsInsert.run(row.rowid, row.id, row.owner, name, description, tags);
625
+ }
626
+ }
591
627
  function insertCard(db, card) {
592
628
  const now = (/* @__PURE__ */ new Date()).toISOString();
593
629
  const withTimestamps = { ...card, created_at: card.created_at ?? now, updated_at: now };
@@ -3,7 +3,7 @@ import {
3
3
  confirmEscrowDebit,
4
4
  recordEarning,
5
5
  releaseEscrow
6
- } from "./chunk-D6RKW2XG.js";
6
+ } from "./chunk-RYISHSHB.js";
7
7
 
8
8
  // src/credit/settlement.ts
9
9
  function settleProviderEarning(providerDb, providerOwner, receipt) {
@@ -1,15 +1,18 @@
1
1
  import {
2
2
  settleProviderEarning
3
- } from "./chunk-X32NE6V4.js";
3
+ } from "./chunk-WNXXLCV5.js";
4
+ import {
5
+ resolveTargetCapability
6
+ } from "./chunk-CQFBNTGT.js";
4
7
  import {
5
8
  getBalance,
6
9
  holdEscrow,
7
10
  releaseEscrow,
8
11
  settleEscrow
9
- } from "./chunk-D6RKW2XG.js";
12
+ } from "./chunk-RYISHSHB.js";
10
13
  import {
11
14
  verifyEscrowReceipt
12
- } from "./chunk-CUONY5TO.js";
15
+ } from "./chunk-EJKW57ZV.js";
13
16
  import {
14
17
  loadConfig
15
18
  } from "./chunk-75OC6E4F.js";
@@ -17,7 +20,7 @@ import {
17
20
  getCard,
18
21
  insertRequestLog,
19
22
  updateReputation
20
- } from "./chunk-O2OYBAVR.js";
23
+ } from "./chunk-S3V6R3EN.js";
21
24
  import {
22
25
  AgentBnBError
23
26
  } from "./chunk-WVY2W7AA.js";
@@ -272,8 +275,12 @@ async function executeCapabilityBatch(options) {
272
275
  };
273
276
  }
274
277
  const executeItem = async (item, index) => {
275
- const card = getCard(registryDb, item.skill_id);
276
- if (!card) {
278
+ const resolved = await resolveTargetCapability(item.skill_id, {
279
+ registryDb,
280
+ registryUrl: options.registryUrl,
281
+ onlineOnly: true
282
+ });
283
+ if (!resolved) {
277
284
  return {
278
285
  request_index: index,
279
286
  status: "failed",
@@ -282,26 +289,11 @@ async function executeCapabilityBatch(options) {
282
289
  error: `Card/skill not found: ${item.skill_id}`
283
290
  };
284
291
  }
285
- const rawCard = card;
286
- let creditsNeeded;
287
- let resolvedSkillId;
288
- if (Array.isArray(rawCard["skills"])) {
289
- const v2card = card;
290
- const skill = v2card.skills[0];
291
- if (!skill) {
292
- return {
293
- request_index: index,
294
- status: "failed",
295
- credits_spent: 0,
296
- credits_refunded: 0,
297
- error: `No skills defined on card: ${item.skill_id}`
298
- };
299
- }
300
- creditsNeeded = skill.pricing.credits_per_call;
301
- resolvedSkillId = skill.id;
302
- } else {
303
- creditsNeeded = card.pricing.credits_per_call;
304
- }
292
+ const localCard = getCard(registryDb, resolved.cardId);
293
+ const localCardRaw = localCard;
294
+ const cardName = typeof localCardRaw?.["name"] === "string" ? localCardRaw["name"] : typeof localCardRaw?.["agent_name"] === "string" ? localCardRaw["agent_name"] : resolved.cardId;
295
+ const creditsNeeded = resolved.credits_per_call;
296
+ const resolvedSkillId = resolved.skillId;
305
297
  if (creditsNeeded > item.max_credits) {
306
298
  return {
307
299
  request_index: index,
@@ -323,7 +315,7 @@ async function executeCapabilityBatch(options) {
323
315
  error: "Insufficient credits"
324
316
  };
325
317
  }
326
- escrowId = holdEscrow(creditDb, owner, creditsNeeded, card.id);
318
+ escrowId = holdEscrow(creditDb, owner, creditsNeeded, resolved.cardId);
327
319
  } catch (err) {
328
320
  const msg = err instanceof AgentBnBError ? err.message : "Failed to hold escrow";
329
321
  return {
@@ -335,30 +327,62 @@ async function executeCapabilityBatch(options) {
335
327
  };
336
328
  }
337
329
  const startMs = Date.now();
338
- const latencyMs = Date.now() - startMs;
339
- settleEscrow(creditDb, escrowId, card.owner);
340
- updateReputation(registryDb, card.id, true, latencyMs);
341
330
  try {
342
- insertRequestLog(registryDb, {
343
- id: randomUUID(),
344
- card_id: card.id,
345
- card_name: card.name,
346
- skill_id: resolvedSkillId,
347
- requester: owner,
331
+ const result = options.dispatchRequest ? await options.dispatchRequest({
332
+ target: resolved,
333
+ params: item.params,
334
+ requester: owner
335
+ }) : { card_id: resolved.cardId, skill_id: resolvedSkillId };
336
+ const latencyMs = Date.now() - startMs;
337
+ settleEscrow(creditDb, escrowId, resolved.owner);
338
+ updateReputation(registryDb, resolved.cardId, true, latencyMs);
339
+ try {
340
+ insertRequestLog(registryDb, {
341
+ id: randomUUID(),
342
+ card_id: resolved.cardId,
343
+ card_name: cardName,
344
+ skill_id: resolvedSkillId,
345
+ requester: owner,
346
+ status: "success",
347
+ latency_ms: latencyMs,
348
+ credits_charged: creditsNeeded,
349
+ created_at: (/* @__PURE__ */ new Date()).toISOString()
350
+ });
351
+ } catch {
352
+ }
353
+ return {
354
+ request_index: index,
348
355
  status: "success",
349
- latency_ms: latencyMs,
350
- credits_charged: creditsNeeded,
351
- created_at: (/* @__PURE__ */ new Date()).toISOString()
352
- });
353
- } catch {
356
+ result,
357
+ credits_spent: creditsNeeded,
358
+ credits_refunded: 0
359
+ };
360
+ } catch (err) {
361
+ releaseEscrow(creditDb, escrowId);
362
+ const latencyMs = Date.now() - startMs;
363
+ try {
364
+ insertRequestLog(registryDb, {
365
+ id: randomUUID(),
366
+ card_id: resolved.cardId,
367
+ card_name: cardName,
368
+ skill_id: resolvedSkillId,
369
+ requester: owner,
370
+ status: "failure",
371
+ latency_ms: latencyMs,
372
+ credits_charged: 0,
373
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
374
+ failure_reason: "not_found"
375
+ });
376
+ } catch {
377
+ }
378
+ return {
379
+ request_index: index,
380
+ status: "failed",
381
+ credits_spent: 0,
382
+ credits_refunded: creditsNeeded,
383
+ error: err instanceof Error ? err.message : String(err)
384
+ };
354
385
  }
355
- return {
356
- request_index: index,
357
- status: "success",
358
- result: { card_id: card.id, skill_id: resolvedSkillId },
359
- credits_spent: creditsNeeded,
360
- credits_refunded: 0
361
- };
362
386
  };
363
387
  let results;
364
388
  if (strategy === "sequential") {