agentbnb 8.2.1 → 8.2.3

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/{chunk-7Q2XUXSA.js → chunk-4IPJJRTP.js} +1 -1
  2. package/dist/{chunk-EZVOG7QS.js → chunk-CKOOVZOI.js} +15 -18
  3. package/dist/chunk-CQFBNTGT.js +145 -0
  4. package/dist/{chunk-WKWJWKX7.js → chunk-DYQOFGGI.js} +155 -445
  5. package/dist/{chunk-NP55V7RQ.js → chunk-EG6RS4JC.js} +70 -46
  6. package/dist/{chunk-KBQNTUTN.js → chunk-LKLKYXLV.js} +1 -1
  7. package/dist/{chunk-STJLWMXH.js → chunk-MCED4GDW.js} +467 -98
  8. package/dist/{chunk-GWMMYVLL.js → chunk-MWOXW7JQ.js} +7 -7
  9. package/dist/{chunk-GJETGML6.js → chunk-QCGIG7WW.js} +4 -6
  10. package/dist/{chunk-UYCD3JBZ.js → chunk-QHZGOG3O.js} +148 -46
  11. package/dist/{chunk-JLNHMNES.js → chunk-RYISHSHB.js} +286 -1
  12. package/dist/{chunk-SRBVKO2V.js → chunk-S3V6R3EN.js} +66 -39
  13. package/dist/chunk-TUCEDQGM.js +44 -0
  14. package/dist/{chunk-RBXTWWUH.js → chunk-WNXXLCV5.js} +1 -1
  15. package/dist/{chunk-LOUEJI6X.js → chunk-XBGVQMQJ.js} +71 -47
  16. package/dist/{chunk-DEWY7OQK.js → chunk-Z2GEFFDO.js} +1 -1
  17. package/dist/cli/index.js +38 -74
  18. package/dist/{client-66TFS7RS.js → client-XOLP5IUZ.js} +1 -1
  19. package/dist/{conduct-A6COHLHY.js → conduct-AZFLNUX3.js} +9 -10
  20. package/dist/{conduct-IUVAXUAV.js → conduct-VPUYTNEA.js} +9 -10
  21. package/dist/{conductor-mode-L2MB44BW.js → conductor-mode-PLTB6MS3.js} +6 -7
  22. package/dist/{conductor-mode-D5TFQW5L.js → conductor-mode-WKB42PYM.js} +6 -3
  23. package/dist/{execute-WOS457HW.js → execute-NNDCXTN4.js} +3 -2
  24. package/dist/{execute-5AWLARB5.js → execute-RIRHTIBU.js} +5 -4
  25. package/dist/index.d.ts +5069 -0
  26. package/dist/index.js +208 -610
  27. package/dist/{publish-capability-JJCBBMSX.js → publish-capability-QDR2QIZ2.js} +2 -2
  28. package/dist/{request-6YQLA7K3.js → request-OERS5BE7.js} +71 -33
  29. package/dist/{serve-skill-X7TZSILV.js → serve-skill-E6EJQYAK.js} +9 -8
  30. package/dist/{server-5TSP4DBX.js → server-46VEG2W7.js} +10 -14
  31. package/dist/{service-coordinator-WTUSMPY6.js → service-coordinator-KMSA6BST.js} +77 -32
  32. package/dist/skills/agentbnb/bootstrap.js +150 -62
  33. package/package.json +18 -12
  34. package/skills/agentbnb/install.sh +0 -0
  35. package/dist/chunk-BZOJ7HBT.js +0 -170
  36. package/dist/chunk-KF3TZHA5.js +0 -91
@@ -319,7 +319,10 @@ var V2_FTS_TRIGGERS = `
319
319
  new.id,
320
320
  new.owner,
321
321
  COALESCE(
322
- (SELECT group_concat(json_extract(value, '$.name'), ' ')
322
+ (SELECT group_concat(
323
+ COALESCE(json_extract(value, '$.id'), '') || ' ' || COALESCE(json_extract(value, '$.name'), ''),
324
+ ' '
325
+ )
323
326
  FROM json_each(json_extract(new.data, '$.skills'))),
324
327
  json_extract(new.data, '$.name'),
325
328
  ''
@@ -359,7 +362,10 @@ var V2_FTS_TRIGGERS = `
359
362
  old.id,
360
363
  old.owner,
361
364
  COALESCE(
362
- (SELECT group_concat(json_extract(value, '$.name'), ' ')
365
+ (SELECT group_concat(
366
+ COALESCE(json_extract(value, '$.id'), '') || ' ' || COALESCE(json_extract(value, '$.name'), ''),
367
+ ' '
368
+ )
363
369
  FROM json_each(json_extract(old.data, '$.skills'))),
364
370
  json_extract(old.data, '$.name'),
365
371
  ''
@@ -395,7 +401,10 @@ var V2_FTS_TRIGGERS = `
395
401
  new.id,
396
402
  new.owner,
397
403
  COALESCE(
398
- (SELECT group_concat(json_extract(value, '$.name'), ' ')
404
+ (SELECT group_concat(
405
+ COALESCE(json_extract(value, '$.id'), '') || ' ' || COALESCE(json_extract(value, '$.name'), ''),
406
+ ' '
407
+ )
399
408
  FROM json_each(json_extract(new.data, '$.skills'))),
400
409
  json_extract(new.data, '$.name'),
401
410
  ''
@@ -435,7 +444,10 @@ var V2_FTS_TRIGGERS = `
435
444
  old.id,
436
445
  old.owner,
437
446
  COALESCE(
438
- (SELECT group_concat(json_extract(value, '$.name'), ' ')
447
+ (SELECT group_concat(
448
+ COALESCE(json_extract(value, '$.id'), '') || ' ' || COALESCE(json_extract(value, '$.name'), ''),
449
+ ' '
450
+ )
439
451
  FROM json_each(json_extract(old.data, '$.skills'))),
440
452
  json_extract(old.data, '$.name'),
441
453
  ''
@@ -522,6 +534,10 @@ function runMigrations(db) {
522
534
  const version = db.pragma("user_version")[0]?.user_version ?? 0;
523
535
  if (version < 2) {
524
536
  migrateV1toV2(db);
537
+ return;
538
+ }
539
+ if (version < 3) {
540
+ migrateV2toV3(db);
525
541
  }
526
542
  }
527
543
  function migrateV1toV2(db) {
@@ -563,44 +579,55 @@ function migrateV1toV2(db) {
563
579
  );
564
580
  }
565
581
  db.exec(V2_FTS_TRIGGERS);
566
- db.exec(`INSERT INTO cards_fts(cards_fts) VALUES('delete-all')`);
567
- const allRows = db.prepare("SELECT rowid, id, owner, data FROM capability_cards").all();
568
- const ftsInsert = db.prepare(
569
- "INSERT INTO cards_fts(rowid, id, owner, name, description, tags) VALUES (?, ?, ?, ?, ?, ?)"
570
- );
571
- for (const row of allRows) {
572
- const data = JSON.parse(row.data);
573
- const skills = data["skills"] ?? [];
574
- let name;
575
- let description;
576
- let tags;
577
- if (skills.length > 0) {
578
- name = skills.map((s) => String(s["name"] ?? "")).join(" ");
579
- description = skills.map((s) => String(s["description"] ?? "")).join(" ");
580
- tags = [
581
- // tags from metadata.tags[]
582
- ...skills.flatMap((s) => {
583
- const meta = s["metadata"];
584
- return meta?.["tags"] ?? [];
585
- }),
586
- // capability_type (singular)
587
- ...skills.map((s) => s["capability_type"]).filter((v) => typeof v === "string" && v.length > 0),
588
- // capability_types[] (plural)
589
- ...skills.flatMap((s) => s["capability_types"] ?? [])
590
- ].join(" ");
591
- } else {
592
- name = String(data["name"] ?? "");
593
- description = String(data["description"] ?? "");
594
- const meta = data["metadata"];
595
- const rawTags = meta?.["tags"] ?? [];
596
- tags = rawTags.join(" ");
597
- }
598
- ftsInsert.run(row.rowid, row.id, row.owner, name, description, tags);
599
- }
600
- db.pragma("user_version = 2");
582
+ rebuildCardsFts(db);
583
+ db.pragma("user_version = 3");
601
584
  });
602
585
  migrate();
603
586
  }
587
+ function migrateV2toV3(db) {
588
+ const migrate = db.transaction(() => {
589
+ db.exec(V2_FTS_TRIGGERS);
590
+ rebuildCardsFts(db);
591
+ db.pragma("user_version = 3");
592
+ });
593
+ migrate();
594
+ }
595
+ function rebuildCardsFts(db) {
596
+ db.exec(`INSERT INTO cards_fts(cards_fts) VALUES('delete-all')`);
597
+ const allRows = db.prepare("SELECT rowid, id, owner, data FROM capability_cards").all();
598
+ const ftsInsert = db.prepare(
599
+ "INSERT INTO cards_fts(rowid, id, owner, name, description, tags) VALUES (?, ?, ?, ?, ?, ?)"
600
+ );
601
+ for (const row of allRows) {
602
+ const data = JSON.parse(row.data);
603
+ const skills = data["skills"] ?? [];
604
+ let name;
605
+ let description;
606
+ let tags;
607
+ if (skills.length > 0) {
608
+ name = skills.map((s) => `${String(s["id"] ?? "")} ${String(s["name"] ?? "")}`.trim()).join(" ");
609
+ description = skills.map((s) => String(s["description"] ?? "")).join(" ");
610
+ tags = [
611
+ // tags from metadata.tags[]
612
+ ...skills.flatMap((s) => {
613
+ const meta = s["metadata"];
614
+ return meta?.["tags"] ?? [];
615
+ }),
616
+ // capability_type (singular)
617
+ ...skills.map((s) => s["capability_type"]).filter((v) => typeof v === "string" && v.length > 0),
618
+ // capability_types[] (plural)
619
+ ...skills.flatMap((s) => s["capability_types"] ?? [])
620
+ ].join(" ");
621
+ } else {
622
+ name = String(data["name"] ?? "");
623
+ description = String(data["description"] ?? "");
624
+ const meta = data["metadata"];
625
+ const rawTags = meta?.["tags"] ?? [];
626
+ tags = rawTags.join(" ");
627
+ }
628
+ ftsInsert.run(row.rowid, row.id, row.owner, name, description, tags);
629
+ }
630
+ }
604
631
  function insertCard(db, card) {
605
632
  const now = (/* @__PURE__ */ new Date()).toISOString();
606
633
  const withTimestamps = { ...card, created_at: card.created_at ?? now, updated_at: now };
@@ -1092,74 +1119,414 @@ function confirmEscrowDebit(db, escrowId) {
1092
1119
  confirm();
1093
1120
  }
1094
1121
 
1095
- // src/credit/signing.ts
1096
- import { generateKeyPairSync, sign, verify, createPublicKey, createPrivateKey } from "crypto";
1097
- import { writeFileSync, readFileSync, existsSync, chmodSync } from "fs";
1098
- import { join } from "path";
1099
- function generateKeyPair() {
1100
- const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
1101
- publicKeyEncoding: { type: "spki", format: "der" },
1102
- privateKeyEncoding: { type: "pkcs8", format: "der" }
1122
+ // src/feedback/reputation.ts
1123
+ var QUALITY_SCORES = {
1124
+ excellent: 1,
1125
+ good: 0.8,
1126
+ acceptable: 0.6,
1127
+ poor: 0.3,
1128
+ failed: 0
1129
+ };
1130
+ var COST_VALUE_SCORES = {
1131
+ great: 1,
1132
+ fair: 0.6,
1133
+ overpriced: 0.2
1134
+ };
1135
+ var DECAY_DAYS = 30;
1136
+ var WEIGHTS = {
1137
+ rating: 0.4,
1138
+ quality: 0.3,
1139
+ would_reuse: 0.2,
1140
+ cost_value: 0.1
1141
+ };
1142
+ function computeReputation(feedbacks) {
1143
+ if (feedbacks.length === 0) return 0.5;
1144
+ const now = Date.now();
1145
+ let weightedSum = 0;
1146
+ let totalWeight = 0;
1147
+ for (const fb of feedbacks) {
1148
+ const feedbackDate = new Date(fb.timestamp).getTime();
1149
+ const ageDays = Math.max(0, (now - feedbackDate) / (1e3 * 60 * 60 * 24));
1150
+ const recencyWeight = Math.exp(-ageDays / DECAY_DAYS);
1151
+ const ratingScore = (fb.rating - 1) / 4;
1152
+ const qualityScore = QUALITY_SCORES[fb.result_quality];
1153
+ const reuseScore = fb.would_reuse ? 1 : 0;
1154
+ const costScore = COST_VALUE_SCORES[fb.cost_value_ratio];
1155
+ const componentScore = WEIGHTS.rating * ratingScore + WEIGHTS.quality * qualityScore + WEIGHTS.would_reuse * reuseScore + WEIGHTS.cost_value * costScore;
1156
+ weightedSum += recencyWeight * componentScore;
1157
+ totalWeight += recencyWeight;
1158
+ }
1159
+ if (totalWeight === 0) return 0.5;
1160
+ const raw = weightedSum / totalWeight;
1161
+ return Math.max(0, Math.min(1, raw));
1162
+ }
1163
+ function getReputationScore(db, agentId) {
1164
+ const feedbacks = getFeedbackForProvider(db, agentId);
1165
+ return computeReputation(feedbacks);
1166
+ }
1167
+
1168
+ // src/registry/matcher.ts
1169
+ var CACHE_MAX_ENTRIES = 100;
1170
+ var CACHE_TTL_MS = 3e4;
1171
+ var dbCaches = /* @__PURE__ */ new WeakMap();
1172
+ function getDbCache(db) {
1173
+ let cache = dbCaches.get(db);
1174
+ if (!cache) {
1175
+ cache = /* @__PURE__ */ new Map();
1176
+ dbCaches.set(db, cache);
1177
+ }
1178
+ return cache;
1179
+ }
1180
+ function cacheKey(query, filters) {
1181
+ return `${query}|${filters.level ?? ""}|${filters.online ?? ""}|${(filters.apis_used ?? []).join(",")}|${filters.min_reputation ?? ""}`;
1182
+ }
1183
+ function evictCache(cache) {
1184
+ const now = Date.now();
1185
+ for (const [key, entry] of cache) {
1186
+ if (entry.expiresAt <= now) cache.delete(key);
1187
+ }
1188
+ while (cache.size > CACHE_MAX_ENTRIES) {
1189
+ const firstKey = cache.keys().next().value;
1190
+ cache.delete(firstKey);
1191
+ }
1192
+ }
1193
+ function searchCards(db, query, filters = {}) {
1194
+ const cache = getDbCache(db);
1195
+ const key = cacheKey(query, filters);
1196
+ const cached = cache.get(key);
1197
+ if (cached && cached.expiresAt > Date.now()) {
1198
+ return cached.results;
1199
+ }
1200
+ const trimmedQuery = query.trim();
1201
+ const exactSkillMatches = findCardsByExactSkillId(db, trimmedQuery, filters);
1202
+ const words = query.trim().split(/\s+/).map((w) => w.replace(/["*^{}():]/g, "")).filter((w) => w.length > 0);
1203
+ if (words.length === 0) {
1204
+ return exactSkillMatches;
1205
+ }
1206
+ const ftsQuery = words.map((w) => `"${w}"`).join(" OR ");
1207
+ const conditions = [];
1208
+ const params = [ftsQuery];
1209
+ if (filters.level !== void 0) {
1210
+ conditions.push(`json_extract(cc.data, '$.level') = ?`);
1211
+ params.push(filters.level);
1212
+ }
1213
+ if (filters.online !== void 0) {
1214
+ conditions.push(`json_extract(cc.data, '$.availability.online') = ?`);
1215
+ params.push(filters.online ? 1 : 0);
1216
+ }
1217
+ const whereClause = conditions.length > 0 ? `AND ${conditions.join(" AND ")}` : "";
1218
+ const sql = `
1219
+ SELECT cc.data
1220
+ FROM capability_cards cc
1221
+ JOIN cards_fts ON cc.rowid = cards_fts.rowid
1222
+ WHERE cards_fts MATCH ?
1223
+ ${whereClause}
1224
+ ORDER BY bm25(cards_fts)
1225
+ LIMIT 50
1226
+ `;
1227
+ const stmt = db.prepare(sql);
1228
+ const rows = stmt.all(...params);
1229
+ const results = rows.map((row) => JSON.parse(row.data));
1230
+ const mergedResults = mergeByCardId(exactSkillMatches, results);
1231
+ let filtered = mergedResults;
1232
+ if (filters.apis_used && filters.apis_used.length > 0) {
1233
+ const requiredApis = filters.apis_used;
1234
+ filtered = filtered.filter((card) => {
1235
+ const cardApis = card.metadata?.apis_used ?? [];
1236
+ return requiredApis.every((api) => cardApis.includes(api));
1237
+ });
1238
+ }
1239
+ if (filters.min_reputation !== void 0 && filters.min_reputation > 0) {
1240
+ filtered = applyReputationFilter(db, filtered, filters.min_reputation);
1241
+ }
1242
+ evictCache(cache);
1243
+ cache.set(key, { results: filtered, expiresAt: Date.now() + CACHE_TTL_MS });
1244
+ return filtered;
1245
+ }
1246
+ function mergeByCardId(primary, secondary) {
1247
+ const seen = /* @__PURE__ */ new Set();
1248
+ const merged = [];
1249
+ for (const card of primary) {
1250
+ if (seen.has(card.id)) continue;
1251
+ seen.add(card.id);
1252
+ merged.push(card);
1253
+ }
1254
+ for (const card of secondary) {
1255
+ if (seen.has(card.id)) continue;
1256
+ seen.add(card.id);
1257
+ merged.push(card);
1258
+ }
1259
+ return merged;
1260
+ }
1261
+ function findCardsByExactSkillId(db, query, filters) {
1262
+ if (query.length === 0) return [];
1263
+ const rows = db.prepare("SELECT data FROM capability_cards").all();
1264
+ const cards = rows.map((row) => JSON.parse(row.data));
1265
+ return cards.filter((card) => {
1266
+ if (filters.level !== void 0 && card.level !== filters.level) return false;
1267
+ if (filters.online !== void 0 && card.availability?.online !== filters.online) return false;
1268
+ const asRecord = card;
1269
+ const skills = asRecord["skills"];
1270
+ if (!Array.isArray(skills)) return false;
1271
+ return skills.some((skill) => String(skill["id"] ?? "") === query);
1103
1272
  });
1104
- return {
1105
- publicKey: Buffer.from(publicKey),
1106
- privateKey: Buffer.from(privateKey)
1107
- };
1108
1273
  }
1109
- function saveKeyPair(configDir, keys) {
1110
- const privatePath = join(configDir, "private.key");
1111
- const publicPath = join(configDir, "public.key");
1112
- writeFileSync(privatePath, keys.privateKey);
1113
- chmodSync(privatePath, 384);
1114
- writeFileSync(publicPath, keys.publicKey);
1115
- }
1116
- function loadKeyPair(configDir) {
1117
- const privatePath = join(configDir, "private.key");
1118
- const publicPath = join(configDir, "public.key");
1119
- if (!existsSync(privatePath) || !existsSync(publicPath)) {
1120
- throw new AgentBnBError("Keypair not found. Run `agentbnb init` to generate one.", "KEYPAIR_NOT_FOUND");
1274
+ function filterCards(db, filters) {
1275
+ const conditions = [];
1276
+ const params = [];
1277
+ if (filters.level !== void 0) {
1278
+ conditions.push(`json_extract(data, '$.level') = ?`);
1279
+ params.push(filters.level);
1280
+ }
1281
+ if (filters.online !== void 0) {
1282
+ conditions.push(`json_extract(data, '$.availability.online') = ?`);
1283
+ params.push(filters.online ? 1 : 0);
1284
+ }
1285
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
1286
+ const sql = `SELECT data FROM capability_cards ${whereClause}`;
1287
+ const stmt = db.prepare(sql);
1288
+ const rows = stmt.all(...params);
1289
+ let cards = rows.map((row) => JSON.parse(row.data));
1290
+ if (filters.min_reputation !== void 0 && filters.min_reputation > 0) {
1291
+ cards = applyReputationFilter(db, cards, filters.min_reputation);
1292
+ }
1293
+ return cards;
1294
+ }
1295
+ function applyReputationFilter(db, cards, minReputation) {
1296
+ const owners = [...new Set(cards.map((c) => c.owner))];
1297
+ const reputationMap = /* @__PURE__ */ new Map();
1298
+ for (const owner of owners) {
1299
+ reputationMap.set(owner, getReputationScore(db, owner));
1300
+ }
1301
+ return cards.filter((card) => {
1302
+ const score = reputationMap.get(card.owner) ?? 0.5;
1303
+ return score >= minReputation;
1304
+ });
1305
+ }
1306
+ function buildReputationMap(db, owners) {
1307
+ const unique = [...new Set(owners)];
1308
+ const map = /* @__PURE__ */ new Map();
1309
+ for (const owner of unique) {
1310
+ map.set(owner, getReputationScore(db, owner));
1311
+ }
1312
+ return map;
1313
+ }
1314
+
1315
+ // src/cli/remote-registry.ts
1316
+ var RegistryTimeoutError = class extends AgentBnBError {
1317
+ constructor(url) {
1318
+ super(
1319
+ `Registry at ${url} did not respond within 5s. Showing local results only.`,
1320
+ "REGISTRY_TIMEOUT"
1321
+ );
1322
+ this.name = "RegistryTimeoutError";
1323
+ }
1324
+ };
1325
+ var RegistryConnectionError = class extends AgentBnBError {
1326
+ constructor(url) {
1327
+ super(
1328
+ `Cannot reach ${url}. Is the registry running? Showing local results only.`,
1329
+ "REGISTRY_CONNECTION"
1330
+ );
1331
+ this.name = "RegistryConnectionError";
1332
+ }
1333
+ };
1334
+ var RegistryAuthError = class extends AgentBnBError {
1335
+ constructor(url) {
1336
+ super(
1337
+ `Authentication failed for ${url}. Run \`agentbnb config set token <your-token>\`.`,
1338
+ "REGISTRY_AUTH"
1339
+ );
1340
+ this.name = "RegistryAuthError";
1341
+ }
1342
+ };
1343
+ async function fetchRemoteCards(registryUrl, params, timeoutMs = 5e3) {
1344
+ let cardsUrl;
1345
+ try {
1346
+ cardsUrl = new URL("/cards", registryUrl);
1347
+ } catch {
1348
+ throw new AgentBnBError(`Invalid registry URL: ${registryUrl}`, "INVALID_REGISTRY_URL");
1349
+ }
1350
+ const searchParams = new URLSearchParams();
1351
+ if (params.q !== void 0) searchParams.set("q", params.q);
1352
+ if (params.level !== void 0) searchParams.set("level", String(params.level));
1353
+ if (params.online !== void 0) searchParams.set("online", String(params.online));
1354
+ if (params.tag !== void 0) searchParams.set("tag", params.tag);
1355
+ searchParams.set("limit", "100");
1356
+ cardsUrl.search = searchParams.toString();
1357
+ const controller = new AbortController();
1358
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
1359
+ let response;
1360
+ try {
1361
+ response = await fetch(cardsUrl.toString(), { signal: controller.signal });
1362
+ } catch (err) {
1363
+ clearTimeout(timer);
1364
+ const isTimeout = err instanceof Error && err.name === "AbortError";
1365
+ if (isTimeout) {
1366
+ throw new RegistryTimeoutError(registryUrl);
1367
+ }
1368
+ throw new RegistryConnectionError(registryUrl);
1369
+ } finally {
1370
+ clearTimeout(timer);
1371
+ }
1372
+ if (response.status === 401 || response.status === 403) {
1373
+ throw new RegistryAuthError(registryUrl);
1374
+ }
1375
+ if (!response.ok) {
1376
+ throw new RegistryConnectionError(registryUrl);
1377
+ }
1378
+ const body = await response.json();
1379
+ return body.items;
1380
+ }
1381
+ function mergeResults(localCards, remoteCards, hasQuery) {
1382
+ const taggedLocal = localCards.map((c) => ({ ...c, source: "local" }));
1383
+ const taggedRemote = remoteCards.map((c) => ({ ...c, source: "remote" }));
1384
+ const localIds = new Set(localCards.map((c) => c.id));
1385
+ const dedupedRemote = taggedRemote.filter((c) => !localIds.has(c.id));
1386
+ if (!hasQuery) {
1387
+ return [...taggedLocal, ...dedupedRemote];
1388
+ }
1389
+ const result = [];
1390
+ const maxLen = Math.max(taggedLocal.length, dedupedRemote.length);
1391
+ for (let i = 0; i < maxLen; i++) {
1392
+ if (i < taggedLocal.length) result.push(taggedLocal[i]);
1393
+ if (i < dedupedRemote.length) result.push(dedupedRemote[i]);
1394
+ }
1395
+ return result;
1396
+ }
1397
+
1398
+ // src/gateway/resolve-target-capability.ts
1399
+ function canQueryLocalDb(db) {
1400
+ return Boolean(db) && typeof db.prepare === "function";
1401
+ }
1402
+ function getGatewayUrl(card) {
1403
+ if (typeof card.gateway_url === "string" && card.gateway_url.length > 0) {
1404
+ return card.gateway_url;
1121
1405
  }
1406
+ const internal = card._internal;
1407
+ const internalGateway = internal?.["gateway_url"];
1408
+ return typeof internalGateway === "string" ? internalGateway : "";
1409
+ }
1410
+ function isOnline(card) {
1411
+ return card.availability?.online !== false;
1412
+ }
1413
+ function scoreSkill(skill, query) {
1414
+ const q = query.toLowerCase();
1415
+ if (skill.id.toLowerCase() === q) return 100;
1416
+ let score = 0;
1417
+ if (skill.id.toLowerCase().includes(q)) score += 40;
1418
+ if (skill.name.toLowerCase().includes(q)) score += 20;
1419
+ if (skill.description.toLowerCase().includes(q)) score += 10;
1420
+ return score;
1421
+ }
1422
+ function pickSkill(card, queryOrId) {
1423
+ const skills = Array.isArray(card.skills) ? card.skills : [];
1424
+ if (skills.length === 0) return void 0;
1425
+ const exact = skills.find((s) => s.id === queryOrId);
1426
+ if (exact) return exact;
1427
+ const scored = skills.map((skill) => ({ skill, score: scoreSkill(skill, queryOrId) })).sort((a, b) => b.score - a.score);
1428
+ if ((scored[0]?.score ?? 0) > 0) return scored[0]?.skill;
1429
+ return skills[0];
1430
+ }
1431
+ function toResolved(card, queryOrId, source) {
1432
+ const skill = pickSkill(card, queryOrId);
1433
+ const gatewayUrl = getGatewayUrl(card);
1434
+ const viaRelay = source === "local" ? false : gatewayUrl.length === 0;
1435
+ const resolvedSource = viaRelay ? "relay" : source;
1122
1436
  return {
1123
- publicKey: readFileSync(publicPath),
1124
- privateKey: readFileSync(privatePath)
1437
+ cardId: card.id,
1438
+ skillId: skill?.id,
1439
+ owner: card.owner,
1440
+ gateway_url: gatewayUrl,
1441
+ via_relay: viaRelay,
1442
+ credits_per_call: skill?.pricing.credits_per_call ?? card.pricing.credits_per_call,
1443
+ source: resolvedSource
1125
1444
  };
1126
1445
  }
1127
- function canonicalJson(data) {
1128
- return JSON.stringify(sortForCanonicalJson(data));
1446
+ function findLocalBySkillId(db, skillId, onlineOnly) {
1447
+ const rows = db.prepare("SELECT data FROM capability_cards").all();
1448
+ for (const row of rows) {
1449
+ const card = JSON.parse(row.data);
1450
+ if (onlineOnly && !isOnline(card)) continue;
1451
+ const skills = Array.isArray(card.skills) ? card.skills : [];
1452
+ if (skills.some((s) => s.id === skillId)) {
1453
+ return card;
1454
+ }
1455
+ }
1456
+ return null;
1457
+ }
1458
+ function findRemoteBySkillId(cards, skillId) {
1459
+ for (const card of cards) {
1460
+ const skills = Array.isArray(card.skills) ? card.skills : [];
1461
+ if (skills.some((s) => s.id === skillId)) return card;
1462
+ }
1463
+ return null;
1464
+ }
1465
+ function looksLikeCardId(value) {
1466
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
1129
1467
  }
1130
- function sortForCanonicalJson(value) {
1131
- if (Array.isArray(value)) {
1132
- return value.map((item) => sortForCanonicalJson(item));
1468
+ async function resolveTargetCapability(queryOrId, options) {
1469
+ const { registryDb, registryUrl, onlineOnly = true } = options;
1470
+ const needle = queryOrId.trim();
1471
+ if (needle.length === 0) return null;
1472
+ if (canQueryLocalDb(registryDb)) {
1473
+ const byCardId = getCard(registryDb, needle);
1474
+ if (byCardId && (!onlineOnly || isOnline(byCardId))) {
1475
+ return toResolved(byCardId, needle, "local");
1476
+ }
1477
+ const bySkillId = findLocalBySkillId(registryDb, needle, onlineOnly);
1478
+ if (bySkillId) {
1479
+ return toResolved(bySkillId, needle, "local");
1480
+ }
1481
+ const localMatches = searchCards(registryDb, needle, { online: onlineOnly ? true : void 0 });
1482
+ if (localMatches.length > 0) {
1483
+ return toResolved(localMatches[0], needle, "local");
1484
+ }
1133
1485
  }
1134
- if (value !== null && typeof value === "object") {
1135
- const proto = Object.getPrototypeOf(value);
1136
- if (proto === Object.prototype || proto === null) {
1137
- const input = value;
1138
- const output = {};
1139
- const sortedKeys = Object.keys(input).sort();
1140
- for (const key of sortedKeys) {
1141
- output[key] = sortForCanonicalJson(input[key]);
1486
+ if (!registryUrl) return null;
1487
+ if (looksLikeCardId(needle)) {
1488
+ try {
1489
+ const cardResp = await fetch(`${registryUrl.replace(/\/$/, "")}/cards/${encodeURIComponent(needle)}`);
1490
+ if (cardResp.ok) {
1491
+ const remoteCard = await cardResp.json();
1492
+ if (!onlineOnly || isOnline(remoteCard)) {
1493
+ return toResolved(remoteCard, needle, "remote");
1494
+ }
1142
1495
  }
1143
- return output;
1496
+ } catch {
1144
1497
  }
1145
1498
  }
1146
- return value;
1147
- }
1148
- function signEscrowReceipt(data, privateKey) {
1149
- const message = Buffer.from(canonicalJson(data), "utf-8");
1150
- const keyObject = createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
1151
- const signature = sign(null, message, keyObject);
1152
- return signature.toString("base64url");
1153
- }
1154
- function verifyEscrowReceipt(data, signature, publicKey) {
1155
1499
  try {
1156
- const message = Buffer.from(canonicalJson(data), "utf-8");
1157
- const keyObject = createPublicKey({ key: publicKey, format: "der", type: "spki" });
1158
- const sigBuffer = Buffer.from(signature, "base64url");
1159
- return verify(null, message, keyObject, sigBuffer);
1500
+ const remoteMatches = await fetchRemoteCards(registryUrl, {
1501
+ q: needle,
1502
+ ...onlineOnly ? { online: true } : {}
1503
+ });
1504
+ if (remoteMatches.length > 0) {
1505
+ const exactSkill = findRemoteBySkillId(remoteMatches, needle);
1506
+ if (exactSkill) return toResolved(exactSkill, needle, "remote");
1507
+ return toResolved(remoteMatches[0], needle, "remote");
1508
+ }
1509
+ } catch {
1510
+ }
1511
+ try {
1512
+ const onlineCards = await fetchRemoteCards(registryUrl, {
1513
+ ...onlineOnly ? { online: true } : {}
1514
+ });
1515
+ const exactSkill = findRemoteBySkillId(onlineCards, needle);
1516
+ if (exactSkill) return toResolved(exactSkill, needle, "relay");
1517
+ const tokens = needle.toLowerCase().split(/\s+/).filter((t) => t.length > 0);
1518
+ const fuzzy = onlineCards.find((card) => {
1519
+ const text = [
1520
+ card.name,
1521
+ card.description,
1522
+ ...Array.isArray(card.skills) ? card.skills.map((s) => `${s.id} ${s.name} ${s.description}`) : []
1523
+ ].join(" ").toLowerCase();
1524
+ return tokens.some((token) => text.includes(token));
1525
+ });
1526
+ if (fuzzy) return toResolved(fuzzy, needle, "relay");
1160
1527
  } catch {
1161
- return false;
1162
1528
  }
1529
+ return null;
1163
1530
  }
1164
1531
 
1165
1532
  export {
@@ -1195,9 +1562,11 @@ export {
1195
1562
  settleEscrow,
1196
1563
  releaseEscrow,
1197
1564
  confirmEscrowDebit,
1198
- generateKeyPair,
1199
- saveKeyPair,
1200
- loadKeyPair,
1201
- signEscrowReceipt,
1202
- verifyEscrowReceipt
1565
+ computeReputation,
1566
+ searchCards,
1567
+ filterCards,
1568
+ buildReputationMap,
1569
+ fetchRemoteCards,
1570
+ mergeResults,
1571
+ resolveTargetCapability
1203
1572
  };
@@ -1,28 +1,28 @@
1
- import {
2
- RelayClient
3
- } from "./chunk-Z4MCGKTL.js";
4
1
  import {
5
2
  BudgetController,
6
3
  ORCHESTRATION_FEE,
7
4
  decompose,
8
5
  matchSubTasks,
9
6
  orchestrate
10
- } from "./chunk-GJETGML6.js";
7
+ } from "./chunk-QCGIG7WW.js";
11
8
  import {
12
9
  BudgetManager
13
- } from "./chunk-UYCD3JBZ.js";
10
+ } from "./chunk-QHZGOG3O.js";
14
11
  import {
15
12
  openCreditDb
16
- } from "./chunk-JLNHMNES.js";
13
+ } from "./chunk-RYISHSHB.js";
17
14
  import {
18
15
  loadPeers
19
16
  } from "./chunk-5AH3CMOX.js";
20
17
  import {
21
18
  loadConfig
22
19
  } from "./chunk-75OC6E4F.js";
20
+ import {
21
+ RelayClient
22
+ } from "./chunk-Z4MCGKTL.js";
23
23
  import {
24
24
  openDatabase
25
- } from "./chunk-SRBVKO2V.js";
25
+ } from "./chunk-S3V6R3EN.js";
26
26
 
27
27
  // src/cli/conduct.ts
28
28
  async function conductAction(task, opts) {
@@ -3,17 +3,15 @@ import {
3
3
  } from "./chunk-3MJT4PZG.js";
4
4
  import {
5
5
  scorePeers
6
- } from "./chunk-UYCD3JBZ.js";
7
- import {
8
- fetchRemoteCards
9
- } from "./chunk-KF3TZHA5.js";
6
+ } from "./chunk-QHZGOG3O.js";
10
7
  import {
8
+ fetchRemoteCards,
11
9
  searchCards
12
- } from "./chunk-BZOJ7HBT.js";
10
+ } from "./chunk-RYISHSHB.js";
13
11
  import {
14
12
  requestCapability,
15
13
  requestCapabilityBatch
16
- } from "./chunk-EZVOG7QS.js";
14
+ } from "./chunk-CKOOVZOI.js";
17
15
 
18
16
  // src/conductor/decomposition-validator.ts
19
17
  function validateAndNormalizeSubtasks(raw, context) {