agentbnb 8.2.1 → 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.
- package/dist/{chunk-7Q2XUXSA.js → chunk-4IPJJRTP.js} +1 -1
- package/dist/{chunk-EZVOG7QS.js → chunk-CKOOVZOI.js} +15 -18
- package/dist/chunk-CQFBNTGT.js +145 -0
- package/dist/{chunk-WKWJWKX7.js → chunk-DYQOFGGI.js} +155 -445
- package/dist/{chunk-NP55V7RQ.js → chunk-EG6RS4JC.js} +70 -46
- package/dist/{chunk-KBQNTUTN.js → chunk-LKLKYXLV.js} +1 -1
- package/dist/{chunk-STJLWMXH.js → chunk-MCED4GDW.js} +467 -98
- package/dist/{chunk-GWMMYVLL.js → chunk-MWOXW7JQ.js} +7 -7
- package/dist/{chunk-GJETGML6.js → chunk-QCGIG7WW.js} +4 -6
- package/dist/{chunk-UYCD3JBZ.js → chunk-QHZGOG3O.js} +148 -46
- package/dist/{chunk-JLNHMNES.js → chunk-RYISHSHB.js} +286 -1
- package/dist/{chunk-SRBVKO2V.js → chunk-S3V6R3EN.js} +66 -39
- package/dist/{chunk-RBXTWWUH.js → chunk-WNXXLCV5.js} +1 -1
- package/dist/{chunk-LOUEJI6X.js → chunk-XBGVQMQJ.js} +71 -47
- package/dist/{chunk-DEWY7OQK.js → chunk-Z2GEFFDO.js} +1 -1
- package/dist/cli/index.js +25 -28
- package/dist/{client-66TFS7RS.js → client-XOLP5IUZ.js} +1 -1
- package/dist/{conduct-A6COHLHY.js → conduct-AZFLNUX3.js} +9 -10
- package/dist/{conduct-IUVAXUAV.js → conduct-VPUYTNEA.js} +9 -10
- package/dist/{conductor-mode-L2MB44BW.js → conductor-mode-PLTB6MS3.js} +6 -7
- package/dist/{conductor-mode-D5TFQW5L.js → conductor-mode-WKB42PYM.js} +6 -3
- package/dist/{execute-WOS457HW.js → execute-NNDCXTN4.js} +3 -2
- package/dist/{execute-5AWLARB5.js → execute-RIRHTIBU.js} +5 -4
- package/dist/index.d.ts +5069 -0
- package/dist/index.js +208 -610
- package/dist/{publish-capability-JJCBBMSX.js → publish-capability-QDR2QIZ2.js} +2 -2
- package/dist/{request-6YQLA7K3.js → request-NX7GSPIG.js} +30 -40
- package/dist/{serve-skill-X7TZSILV.js → serve-skill-E6EJQYAK.js} +9 -8
- package/dist/{server-5TSP4DBX.js → server-VBCT32FC.js} +10 -14
- package/dist/{service-coordinator-WTUSMPY6.js → service-coordinator-KMSA6BST.js} +77 -32
- package/dist/skills/agentbnb/bootstrap.js +113 -69
- package/package.json +1 -1
- package/dist/chunk-BZOJ7HBT.js +0 -170
- package/dist/chunk-KF3TZHA5.js +0 -91
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
fetchRemoteCards
|
|
3
|
-
} from "./chunk-KF3TZHA5.js";
|
|
4
1
|
import {
|
|
5
2
|
createPendingRequest,
|
|
6
3
|
getAutonomyTier,
|
|
7
4
|
insertAuditEvent
|
|
8
5
|
} from "./chunk-GKVTD4EZ.js";
|
|
9
6
|
import {
|
|
10
|
-
|
|
11
|
-
} from "./chunk-
|
|
7
|
+
resolveTargetCapability
|
|
8
|
+
} from "./chunk-CQFBNTGT.js";
|
|
12
9
|
import {
|
|
10
|
+
fetchRemoteCards,
|
|
13
11
|
getBalance,
|
|
14
12
|
holdEscrow,
|
|
15
13
|
releaseEscrow,
|
|
14
|
+
searchCards,
|
|
16
15
|
settleEscrow
|
|
17
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-RYISHSHB.js";
|
|
18
17
|
import {
|
|
19
|
-
requestCapability
|
|
20
|
-
|
|
18
|
+
requestCapability,
|
|
19
|
+
requestViaRelay
|
|
20
|
+
} from "./chunk-CKOOVZOI.js";
|
|
21
21
|
import {
|
|
22
22
|
findPeer
|
|
23
23
|
} from "./chunk-5AH3CMOX.js";
|
|
@@ -68,6 +68,7 @@ var BudgetManager = class {
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
// src/autonomy/auto-request.ts
|
|
71
|
+
import { randomUUID } from "crypto";
|
|
71
72
|
function minMaxNormalize(values) {
|
|
72
73
|
if (values.length === 0) return [];
|
|
73
74
|
if (values.length === 1) return [1];
|
|
@@ -190,88 +191,189 @@ var AutoRequestor = class {
|
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
const scored = scorePeers(candidates, this.owner);
|
|
194
|
+
const resolverOptions = {
|
|
195
|
+
registryDb: this.registryDb,
|
|
196
|
+
registryUrl: this.registryUrl,
|
|
197
|
+
onlineOnly: true
|
|
198
|
+
};
|
|
199
|
+
let resolvedTarget = null;
|
|
193
200
|
if (scored.length === 0) {
|
|
201
|
+
resolvedTarget = await resolveTargetCapability(need.query, resolverOptions);
|
|
202
|
+
if (!resolvedTarget || resolvedTarget.owner === this.owner || resolvedTarget.credits_per_call > need.maxCostCredits) {
|
|
203
|
+
this.logFailure("auto_request_failed", "system", "none", 3, 0, "none", "No eligible peer found");
|
|
204
|
+
return { status: "no_peer", reason: "No eligible peer found" };
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
const top = scored[0];
|
|
208
|
+
const targetKey = top.skillId ?? top.card.id;
|
|
209
|
+
resolvedTarget = await resolveTargetCapability(targetKey, resolverOptions) ?? await resolveTargetCapability(need.query, resolverOptions);
|
|
210
|
+
if (!resolvedTarget || resolvedTarget.owner === this.owner) {
|
|
211
|
+
this.logFailure("auto_request_failed", top.card.id, top.skillId ?? "none", 3, top.cost, top.card.owner, "No eligible peer found");
|
|
212
|
+
return { status: "no_peer", reason: "No eligible peer found" };
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (!resolvedTarget) {
|
|
194
216
|
this.logFailure("auto_request_failed", "system", "none", 3, 0, "none", "No eligible peer found");
|
|
195
217
|
return { status: "no_peer", reason: "No eligible peer found" };
|
|
196
218
|
}
|
|
197
|
-
const
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const tier = getAutonomyTier(top.cost, this.autonomyConfig);
|
|
219
|
+
const selectedCardId = resolvedTarget.cardId;
|
|
220
|
+
const selectedSkillId = resolvedTarget.skillId;
|
|
221
|
+
const selectedPeer = resolvedTarget.owner;
|
|
222
|
+
const selectedCost = resolvedTarget.credits_per_call;
|
|
223
|
+
const selectedViaRelay = resolvedTarget.via_relay;
|
|
224
|
+
const tier = getAutonomyTier(selectedCost, this.autonomyConfig);
|
|
204
225
|
if (tier === 3) {
|
|
205
226
|
createPendingRequest(this.registryDb, {
|
|
206
227
|
skill_query: need.query,
|
|
207
228
|
max_cost_credits: need.maxCostCredits,
|
|
208
|
-
credits:
|
|
209
|
-
selected_peer:
|
|
210
|
-
selected_card_id:
|
|
211
|
-
selected_skill_id:
|
|
229
|
+
credits: selectedCost,
|
|
230
|
+
selected_peer: selectedPeer,
|
|
231
|
+
selected_card_id: selectedCardId,
|
|
232
|
+
selected_skill_id: selectedSkillId,
|
|
212
233
|
params: need.params
|
|
213
234
|
});
|
|
214
235
|
insertAuditEvent(this.registryDb, {
|
|
215
236
|
type: "auto_request_pending",
|
|
216
|
-
card_id:
|
|
217
|
-
skill_id:
|
|
237
|
+
card_id: selectedCardId,
|
|
238
|
+
skill_id: selectedSkillId ?? selectedCardId,
|
|
218
239
|
tier_invoked: 3,
|
|
219
|
-
credits:
|
|
220
|
-
peer:
|
|
240
|
+
credits: selectedCost,
|
|
241
|
+
peer: selectedPeer
|
|
221
242
|
});
|
|
222
243
|
return {
|
|
223
244
|
status: "tier_blocked",
|
|
224
245
|
reason: "Tier 3: owner approval required",
|
|
225
|
-
peer:
|
|
246
|
+
peer: selectedPeer
|
|
226
247
|
};
|
|
227
248
|
}
|
|
228
|
-
if (!this.budgetManager.canSpend(
|
|
229
|
-
this.logFailure(
|
|
249
|
+
if (!this.budgetManager.canSpend(selectedCost)) {
|
|
250
|
+
this.logFailure(
|
|
251
|
+
"auto_request_failed",
|
|
252
|
+
selectedCardId,
|
|
253
|
+
selectedSkillId ?? "none",
|
|
254
|
+
tier,
|
|
255
|
+
selectedCost,
|
|
256
|
+
selectedPeer,
|
|
257
|
+
"Budget reserve would be breached"
|
|
258
|
+
);
|
|
230
259
|
return { status: "budget_blocked", reason: "Insufficient credits \u2014 reserve floor would be breached" };
|
|
231
260
|
}
|
|
232
|
-
const escrowId = holdEscrow(this.creditDb, this.owner,
|
|
261
|
+
const escrowId = holdEscrow(this.creditDb, this.owner, selectedCost, selectedCardId);
|
|
233
262
|
try {
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
263
|
+
const requestParams = selectedSkillId ? { skill_id: selectedSkillId, ...need.params, requester: this.owner } : { ...need.params, requester: this.owner };
|
|
264
|
+
let execResult;
|
|
265
|
+
if (selectedViaRelay) {
|
|
266
|
+
if (!this.registryUrl) {
|
|
267
|
+
this.logFailure(
|
|
268
|
+
"auto_request_failed",
|
|
269
|
+
selectedCardId,
|
|
270
|
+
selectedSkillId ?? "none",
|
|
271
|
+
tier,
|
|
272
|
+
selectedCost,
|
|
273
|
+
selectedPeer,
|
|
274
|
+
"Relay target found but registryUrl is not configured"
|
|
275
|
+
);
|
|
276
|
+
releaseEscrow(this.creditDb, escrowId);
|
|
277
|
+
return { status: "no_peer", reason: "Relay target found but registryUrl is not configured" };
|
|
278
|
+
}
|
|
279
|
+
const relayRequesterOwner = `${this.owner}:req:${randomUUID()}`;
|
|
280
|
+
const { RelayClient } = await import("./websocket-client-QOVARTRN.js");
|
|
281
|
+
const relayClient = new RelayClient({
|
|
282
|
+
registryUrl: this.registryUrl,
|
|
283
|
+
owner: relayRequesterOwner,
|
|
284
|
+
token: "auto-request-token",
|
|
285
|
+
card: {
|
|
286
|
+
spec_version: "1.0",
|
|
287
|
+
id: randomUUID(),
|
|
288
|
+
owner: relayRequesterOwner,
|
|
289
|
+
name: relayRequesterOwner,
|
|
290
|
+
description: "Auto-request requester",
|
|
291
|
+
level: 1,
|
|
292
|
+
inputs: [],
|
|
293
|
+
outputs: [],
|
|
294
|
+
pricing: { credits_per_call: 1 },
|
|
295
|
+
availability: { online: false }
|
|
296
|
+
},
|
|
297
|
+
onRequest: async () => ({ error: { code: -32601, message: "Auto-request relay requester does not serve capabilities" } }),
|
|
298
|
+
silent: true
|
|
299
|
+
});
|
|
300
|
+
try {
|
|
301
|
+
await relayClient.connect();
|
|
302
|
+
execResult = await requestViaRelay(relayClient, {
|
|
303
|
+
targetOwner: selectedPeer,
|
|
304
|
+
cardId: selectedCardId,
|
|
305
|
+
skillId: selectedSkillId,
|
|
306
|
+
params: requestParams,
|
|
307
|
+
requester: this.owner
|
|
308
|
+
});
|
|
309
|
+
} finally {
|
|
310
|
+
relayClient.disconnect();
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
const peerConfig = findPeer(selectedPeer);
|
|
314
|
+
if (!peerConfig) {
|
|
315
|
+
this.logFailure(
|
|
316
|
+
"auto_request_failed",
|
|
317
|
+
selectedCardId,
|
|
318
|
+
selectedSkillId ?? "none",
|
|
319
|
+
tier,
|
|
320
|
+
selectedCost,
|
|
321
|
+
selectedPeer,
|
|
322
|
+
"No gateway config for peer"
|
|
323
|
+
);
|
|
324
|
+
releaseEscrow(this.creditDb, escrowId);
|
|
325
|
+
return { status: "no_peer", reason: "No gateway config for peer" };
|
|
326
|
+
}
|
|
327
|
+
execResult = await requestCapability({
|
|
328
|
+
gatewayUrl: peerConfig.url,
|
|
329
|
+
token: peerConfig.token,
|
|
330
|
+
cardId: selectedCardId,
|
|
331
|
+
params: requestParams
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
settleEscrow(this.creditDb, escrowId, selectedPeer);
|
|
241
335
|
if (tier === 2) {
|
|
242
336
|
insertAuditEvent(this.registryDb, {
|
|
243
337
|
type: "auto_request_notify",
|
|
244
|
-
card_id:
|
|
245
|
-
skill_id:
|
|
338
|
+
card_id: selectedCardId,
|
|
339
|
+
skill_id: selectedSkillId ?? selectedCardId,
|
|
246
340
|
tier_invoked: 2,
|
|
247
|
-
credits:
|
|
248
|
-
peer:
|
|
341
|
+
credits: selectedCost,
|
|
342
|
+
peer: selectedPeer
|
|
249
343
|
});
|
|
250
344
|
} else {
|
|
251
345
|
insertAuditEvent(this.registryDb, {
|
|
252
346
|
type: "auto_request",
|
|
253
|
-
card_id:
|
|
254
|
-
skill_id:
|
|
347
|
+
card_id: selectedCardId,
|
|
348
|
+
skill_id: selectedSkillId ?? selectedCardId,
|
|
255
349
|
tier_invoked: 1,
|
|
256
|
-
credits:
|
|
257
|
-
peer:
|
|
350
|
+
credits: selectedCost,
|
|
351
|
+
peer: selectedPeer
|
|
258
352
|
});
|
|
259
353
|
}
|
|
260
354
|
return {
|
|
261
355
|
status: "success",
|
|
262
356
|
result: execResult,
|
|
263
357
|
escrowId,
|
|
264
|
-
peer:
|
|
265
|
-
creditsSpent:
|
|
358
|
+
peer: selectedPeer,
|
|
359
|
+
creditsSpent: selectedCost
|
|
266
360
|
};
|
|
267
361
|
} catch (err) {
|
|
268
362
|
releaseEscrow(this.creditDb, escrowId);
|
|
269
363
|
const reason = err instanceof Error ? err.message : String(err);
|
|
270
|
-
this.logFailure(
|
|
364
|
+
this.logFailure(
|
|
365
|
+
"auto_request_failed",
|
|
366
|
+
selectedCardId,
|
|
367
|
+
selectedSkillId ?? "none",
|
|
368
|
+
tier,
|
|
369
|
+
selectedCost,
|
|
370
|
+
selectedPeer,
|
|
371
|
+
`Execution failed: ${reason}`
|
|
372
|
+
);
|
|
271
373
|
return {
|
|
272
374
|
status: "failed",
|
|
273
375
|
reason: `Execution failed: ${reason}`,
|
|
274
|
-
peer:
|
|
376
|
+
peer: selectedPeer
|
|
275
377
|
};
|
|
276
378
|
}
|
|
277
379
|
}
|
|
@@ -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";
|
|
@@ -390,6 +393,282 @@ function confirmEscrowDebit(db, escrowId) {
|
|
|
390
393
|
confirm();
|
|
391
394
|
}
|
|
392
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
|
+
|
|
393
672
|
export {
|
|
394
673
|
createAgentRecord,
|
|
395
674
|
lookupAgent,
|
|
@@ -404,5 +683,11 @@ export {
|
|
|
404
683
|
holdEscrow,
|
|
405
684
|
settleEscrow,
|
|
406
685
|
releaseEscrow,
|
|
407
|
-
confirmEscrowDebit
|
|
686
|
+
confirmEscrowDebit,
|
|
687
|
+
computeReputation,
|
|
688
|
+
searchCards,
|
|
689
|
+
filterCards,
|
|
690
|
+
buildReputationMap,
|
|
691
|
+
fetchRemoteCards,
|
|
692
|
+
mergeResults
|
|
408
693
|
};
|