agentbnb 4.0.1 → 4.0.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 (39) hide show
  1. package/README.md +2 -0
  2. package/dist/{card-4XH4AOTE.js → card-RSGDCHCV.js} +1 -1
  3. package/dist/{chunk-MQKYGY5I.js → chunk-4P3EMGL4.js} +3 -3
  4. package/dist/{chunk-DVAS2443.js → chunk-5KFI5X7B.js} +1 -1
  5. package/dist/{chunk-Q7HRI666.js → chunk-7NA43XCG.js} +4 -4
  6. package/dist/{chunk-3UKAVIMC.js → chunk-BH6WGYFB.js} +4 -4
  7. package/dist/{chunk-XQHN6ITI.js → chunk-DNWT5FZQ.js} +22 -2
  8. package/dist/{chunk-QJEOCKVF.js → chunk-FF226TIV.js} +1 -1
  9. package/dist/{chunk-6K5WUVF3.js → chunk-GGYC5U2Z.js} +4 -4
  10. package/dist/{chunk-ODBGCCEH.js → chunk-HH24WMFN.js} +18 -3
  11. package/dist/{chunk-M3G5NR2Z.js → chunk-QITOPASZ.js} +8 -2
  12. package/dist/{chunk-TLU7ALCZ.js → chunk-T7NS2J2B.js} +1 -1
  13. package/dist/{chunk-FNKBHBYK.js → chunk-WGZ5AGOX.js} +37 -3
  14. package/dist/{chunk-KJG2UJV5.js → chunk-XND2DWTZ.js} +3 -2
  15. package/dist/cli/index.d.ts +1 -0
  16. package/dist/cli/index.js +403 -134
  17. package/dist/{client-BTPIFY7E.js → client-T5MTY3CS.js} +3 -3
  18. package/dist/conduct-GZQNFTRP.js +19 -0
  19. package/dist/{conduct-CW62HBPT.js → conduct-N52JX7RT.js} +9 -9
  20. package/dist/{conductor-mode-3JS4VWCR.js → conductor-mode-XUWGR4ZE.js} +7 -7
  21. package/dist/execute-PNGQOMYO.js +10 -0
  22. package/dist/index.d.ts +146 -2
  23. package/dist/index.js +131 -65
  24. package/dist/{request-CNZ3XIVX.js → request-4GQSSM4B.js} +8 -8
  25. package/dist/{serve-skill-SUOGUM7N.js → serve-skill-TPHZH6BS.js} +5 -5
  26. package/dist/{server-2LWHL24P.js → server-365V3GYD.js} +10 -10
  27. package/package.json +3 -6
  28. package/skills/agentbnb/HEARTBEAT.rules.md +47 -0
  29. package/skills/agentbnb/SKILL.md +166 -0
  30. package/skills/agentbnb/auto-request.ts +14 -0
  31. package/skills/agentbnb/auto-share.ts +10 -0
  32. package/skills/agentbnb/bootstrap.test.ts +323 -0
  33. package/skills/agentbnb/bootstrap.ts +126 -0
  34. package/skills/agentbnb/credit-mgr.ts +11 -0
  35. package/skills/agentbnb/gateway.ts +12 -0
  36. package/skills/agentbnb/install.sh +210 -0
  37. package/dist/conduct-FXLVGKD5.js +0 -19
  38. package/dist/execute-EXOITLHN.js +0 -10
  39. package/dist/types-FGBUZ3QV.js +0 -18
package/dist/cli/index.js CHANGED
@@ -2,11 +2,16 @@
2
2
  import {
3
3
  deriveAgentId,
4
4
  ensureIdentity
5
- } from "../chunk-M3G5NR2Z.js";
5
+ } from "../chunk-QITOPASZ.js";
6
6
  import {
7
7
  createLedger,
8
8
  identityAuthPlugin
9
- } from "../chunk-ODBGCCEH.js";
9
+ } from "../chunk-HH24WMFN.js";
10
+ import {
11
+ executeCapabilityRequest,
12
+ releaseRequesterEscrow,
13
+ settleRequesterEscrow
14
+ } from "../chunk-7NA43XCG.js";
10
15
  import {
11
16
  interpolateObject
12
17
  } from "../chunk-3MJT4PZG.js";
@@ -19,16 +24,16 @@ import {
19
24
  insertAuditEvent,
20
25
  listPendingRequests,
21
26
  resolvePendingRequest
22
- } from "../chunk-6K5WUVF3.js";
27
+ } from "../chunk-GGYC5U2Z.js";
23
28
  import {
24
29
  fetchRemoteCards,
25
30
  filterCards,
26
31
  mergeResults,
27
32
  searchCards
28
- } from "../chunk-QJEOCKVF.js";
33
+ } from "../chunk-FF226TIV.js";
29
34
  import {
30
35
  requestCapability
31
- } from "../chunk-KJG2UJV5.js";
36
+ } from "../chunk-XND2DWTZ.js";
32
37
  import {
33
38
  findPeer,
34
39
  loadPeers,
@@ -40,11 +45,6 @@ import {
40
45
  loadConfig,
41
46
  saveConfig
42
47
  } from "../chunk-75OC6E4F.js";
43
- import {
44
- executeCapabilityRequest,
45
- releaseRequesterEscrow,
46
- settleRequesterEscrow
47
- } from "../chunk-Q7HRI666.js";
48
48
  import {
49
49
  getActivityFeed,
50
50
  getCard,
@@ -57,28 +57,29 @@ import {
57
57
  updateCard,
58
58
  updateSkillAvailability,
59
59
  updateSkillIdleRate
60
- } from "../chunk-TLU7ALCZ.js";
60
+ } from "../chunk-T7NS2J2B.js";
61
61
  import {
62
62
  bootstrapAgent,
63
63
  getBalance,
64
64
  getTransactions,
65
65
  holdEscrow,
66
+ migrateOwner,
66
67
  openCreditDb,
67
68
  releaseEscrow,
68
69
  settleEscrow
69
- } from "../chunk-XQHN6ITI.js";
70
+ } from "../chunk-DNWT5FZQ.js";
70
71
  import {
71
72
  generateKeyPair,
72
73
  loadKeyPair,
73
74
  saveKeyPair,
74
75
  signEscrowReceipt,
75
76
  verifyEscrowReceipt
76
- } from "../chunk-DVAS2443.js";
77
+ } from "../chunk-5KFI5X7B.js";
77
78
  import {
78
79
  AgentBnBError,
79
80
  AnyCardSchema,
80
81
  CapabilityCardV2Schema
81
- } from "../chunk-FNKBHBYK.js";
82
+ } from "../chunk-WGZ5AGOX.js";
82
83
  import {
83
84
  RelayMessageSchema
84
85
  } from "../chunk-QT7TEVNV.js";
@@ -87,7 +88,7 @@ import {
87
88
  import { Command } from "commander";
88
89
  import { readFileSync as readFileSync4 } from "fs";
89
90
  import { createRequire } from "module";
90
- import { randomBytes as randomBytes2 } from "crypto";
91
+ import { randomBytes as randomBytes2, randomUUID as randomUUID10 } from "crypto";
91
92
  import { join as join3 } from "path";
92
93
  import { networkInterfaces, homedir } from "os";
93
94
  import { createInterface as createInterface2 } from "readline";
@@ -1432,8 +1433,8 @@ var AgentRuntime = class {
1432
1433
  }
1433
1434
  const modes = /* @__PURE__ */ new Map();
1434
1435
  if (this.conductorEnabled) {
1435
- const { ConductorMode } = await import("../conductor-mode-3JS4VWCR.js");
1436
- const { registerConductorCard, CONDUCTOR_OWNER } = await import("../card-4XH4AOTE.js");
1436
+ const { ConductorMode } = await import("../conductor-mode-XUWGR4ZE.js");
1437
+ const { registerConductorCard, CONDUCTOR_OWNER } = await import("../card-RSGDCHCV.js");
1437
1438
  const { loadPeers: loadPeers2 } = await import("../peers-K7FSHPN3.js");
1438
1439
  registerConductorCard(this.registryDb);
1439
1440
  const resolveAgentUrl = (owner) => {
@@ -1662,14 +1663,27 @@ function lookupCardPrice(registryDb, cardId, skillId) {
1662
1663
  } catch {
1663
1664
  return null;
1664
1665
  }
1665
- if (skillId && Array.isArray(card.skills)) {
1666
+ if (Array.isArray(card.skills) && card.skills.length > 0) {
1666
1667
  const skills = card.skills;
1667
- const skill = skills.find((s) => s.id === skillId);
1668
- if (skill) {
1669
- const skillPricing = skill.pricing;
1670
- if (skillPricing && typeof skillPricing.credits_per_call === "number") {
1671
- return skillPricing.credits_per_call;
1668
+ if (skillId) {
1669
+ const skill = skills.find((s) => s.id === skillId);
1670
+ if (skill) {
1671
+ const skillPricing = skill.pricing;
1672
+ if (skillPricing && typeof skillPricing.credits_per_call === "number") {
1673
+ return skillPricing.credits_per_call;
1674
+ }
1672
1675
  }
1676
+ } else {
1677
+ let minPrice = null;
1678
+ for (const s of skills) {
1679
+ const sp = s.pricing;
1680
+ if (sp && typeof sp.credits_per_call === "number" && sp.credits_per_call > 0) {
1681
+ if (minPrice === null || sp.credits_per_call < minPrice) {
1682
+ minPrice = sp.credits_per_call;
1683
+ }
1684
+ }
1685
+ }
1686
+ if (minPrice !== null) return minPrice;
1673
1687
  }
1674
1688
  }
1675
1689
  const pricing = card.pricing;
@@ -2103,7 +2117,13 @@ function registerWebSocketRelay(server, db, creditDb) {
2103
2117
  }
2104
2118
  }
2105
2119
  connections.set(owner, ws);
2106
- const cardId = upsertCard(card, owner);
2120
+ let cardId;
2121
+ try {
2122
+ cardId = upsertCard(card, owner);
2123
+ } catch (err) {
2124
+ console.error(`[relay] card validation failed for ${owner}:`, err instanceof Error ? err.message : err);
2125
+ cardId = card.id ?? owner;
2126
+ }
2107
2127
  const cardName = card.name ?? card.agent_name ?? owner;
2108
2128
  logAgentJoined(owner, cardName, cardId);
2109
2129
  if (msg.cards && msg.cards.length > 0) {
@@ -2143,12 +2163,13 @@ function registerWebSocketRelay(server, db, creditDb) {
2143
2163
  });
2144
2164
  return;
2145
2165
  }
2166
+ const creditOwner = msg.requester ?? fromOwner;
2146
2167
  let escrowId;
2147
2168
  if (creditDb) {
2148
2169
  try {
2149
2170
  const price = lookupCardPrice(db, msg.card_id, msg.skill_id);
2150
2171
  if (price !== null && price > 0) {
2151
- escrowId = holdForRelay(creditDb, fromOwner, price, msg.card_id);
2172
+ escrowId = holdForRelay(creditDb, creditOwner, price, msg.card_id);
2152
2173
  }
2153
2174
  } catch (err) {
2154
2175
  if (err instanceof AgentBnBError && err.code === "INSUFFICIENT_CREDITS") {
@@ -2178,7 +2199,7 @@ function registerWebSocketRelay(server, db, creditDb) {
2178
2199
  error: { code: -32603, message: "Relay request timeout" }
2179
2200
  });
2180
2201
  }, RELAY_TIMEOUT_MS);
2181
- pendingRequests.set(msg.id, { originOwner: fromOwner, timeout, escrowId, targetOwner: msg.target_owner });
2202
+ pendingRequests.set(msg.id, { originOwner: fromOwner, creditOwner, timeout, escrowId, targetOwner: msg.target_owner });
2182
2203
  sendMessage(targetWs, {
2183
2204
  type: "incoming_request",
2184
2205
  id: msg.id,
@@ -2266,7 +2287,7 @@ function registerWebSocketRelay(server, db, creditDb) {
2266
2287
  conductorFee = calculateConductorFee(totalCredits);
2267
2288
  if (conductorFee > 0) {
2268
2289
  try {
2269
- const feeEscrowId = holdForRelay(creditDb, pending.originOwner, conductorFee, msg.id);
2290
+ const feeEscrowId = holdForRelay(creditDb, pending.creditOwner ?? pending.originOwner, conductorFee, msg.id);
2270
2291
  settleForRelay(creditDb, feeEscrowId, pending.targetOwner);
2271
2292
  } catch (e) {
2272
2293
  console.error("[relay] conductor fee settlement failed (non-fatal):", e);
@@ -2322,60 +2343,62 @@ function registerWebSocketRelay(server, db, creditDb) {
2322
2343
  }
2323
2344
  }
2324
2345
  }
2325
- server.get("/ws", { websocket: true }, (rawSocket, _request) => {
2326
- const socket = rawSocket;
2327
- let registeredOwner;
2328
- socket.on("message", (raw) => {
2329
- void (async () => {
2330
- let data;
2331
- try {
2332
- data = JSON.parse(typeof raw === "string" ? raw : raw.toString("utf-8"));
2333
- } catch {
2334
- sendMessage(socket, { type: "error", code: "invalid_json", message: "Invalid JSON" });
2335
- return;
2336
- }
2337
- const parsed = RelayMessageSchema.safeParse(data);
2338
- if (!parsed.success) {
2339
- sendMessage(socket, {
2340
- type: "error",
2341
- code: "invalid_message",
2342
- message: `Invalid message: ${parsed.error.issues[0]?.message ?? "unknown error"}`
2343
- });
2344
- return;
2345
- }
2346
- const msg = parsed.data;
2347
- switch (msg.type) {
2348
- case "register":
2349
- registeredOwner = msg.owner;
2350
- handleRegister(socket, msg);
2351
- break;
2352
- case "relay_request":
2353
- if (!registeredOwner) {
2354
- sendMessage(socket, {
2355
- type: "error",
2356
- code: "not_registered",
2357
- message: "Must send register message before relay requests"
2358
- });
2359
- return;
2360
- }
2361
- await handleRelayRequest(socket, msg, registeredOwner);
2362
- break;
2363
- case "relay_response":
2364
- handleRelayResponse(msg);
2365
- break;
2366
- case "relay_progress":
2367
- handleRelayProgress(msg);
2368
- break;
2369
- default:
2370
- break;
2371
- }
2372
- })();
2373
- });
2374
- socket.on("close", () => {
2375
- handleDisconnect(registeredOwner);
2376
- });
2377
- socket.on("error", () => {
2378
- handleDisconnect(registeredOwner);
2346
+ void server.register(async (app) => {
2347
+ app.get("/ws", { websocket: true }, (rawSocket, _request) => {
2348
+ const socket = rawSocket;
2349
+ let registeredOwner;
2350
+ socket.on("message", (raw) => {
2351
+ void (async () => {
2352
+ let data;
2353
+ try {
2354
+ data = JSON.parse(typeof raw === "string" ? raw : raw.toString("utf-8"));
2355
+ } catch {
2356
+ sendMessage(socket, { type: "error", code: "invalid_json", message: "Invalid JSON" });
2357
+ return;
2358
+ }
2359
+ const parsed = RelayMessageSchema.safeParse(data);
2360
+ if (!parsed.success) {
2361
+ sendMessage(socket, {
2362
+ type: "error",
2363
+ code: "invalid_message",
2364
+ message: `Invalid message: ${parsed.error.issues[0]?.message ?? "unknown error"}`
2365
+ });
2366
+ return;
2367
+ }
2368
+ const msg = parsed.data;
2369
+ switch (msg.type) {
2370
+ case "register":
2371
+ registeredOwner = msg.owner;
2372
+ handleRegister(socket, msg);
2373
+ break;
2374
+ case "relay_request":
2375
+ if (!registeredOwner) {
2376
+ sendMessage(socket, {
2377
+ type: "error",
2378
+ code: "not_registered",
2379
+ message: "Must send register message before relay requests"
2380
+ });
2381
+ return;
2382
+ }
2383
+ await handleRelayRequest(socket, msg, registeredOwner);
2384
+ break;
2385
+ case "relay_response":
2386
+ handleRelayResponse(msg);
2387
+ break;
2388
+ case "relay_progress":
2389
+ handleRelayProgress(msg);
2390
+ break;
2391
+ default:
2392
+ break;
2393
+ }
2394
+ })();
2395
+ });
2396
+ socket.on("close", () => {
2397
+ handleDisconnect(registeredOwner);
2398
+ });
2399
+ socket.on("error", () => {
2400
+ handleDisconnect(registeredOwner);
2401
+ });
2379
2402
  });
2380
2403
  });
2381
2404
  return {
@@ -2544,9 +2567,14 @@ async function creditRoutesPlugin(fastify, options) {
2544
2567
  creditDb.exec(`
2545
2568
  CREATE TABLE IF NOT EXISTS credit_grants (
2546
2569
  public_key TEXT PRIMARY KEY,
2547
- granted_at TEXT NOT NULL
2570
+ granted_at TEXT NOT NULL,
2571
+ owner TEXT
2548
2572
  )
2549
2573
  `);
2574
+ try {
2575
+ creditDb.exec("ALTER TABLE credit_grants ADD COLUMN owner TEXT");
2576
+ } catch {
2577
+ }
2550
2578
  initFreeTierTable(creditDb);
2551
2579
  await fastify.register(async (scope) => {
2552
2580
  identityAuthPlugin(scope);
@@ -2686,13 +2714,18 @@ async function creditRoutesPlugin(fastify, options) {
2686
2714
  if (!owner) {
2687
2715
  return reply.code(400).send({ error: "owner is required" });
2688
2716
  }
2689
- const existing = creditDb.prepare("SELECT public_key FROM credit_grants WHERE public_key = ?").get(publicKey);
2717
+ const existing = creditDb.prepare("SELECT public_key, owner FROM credit_grants WHERE public_key = ?").get(publicKey);
2690
2718
  if (existing) {
2719
+ if (existing.owner && existing.owner !== owner) {
2720
+ migrateOwner(creditDb, existing.owner, owner);
2721
+ creditDb.prepare("UPDATE credit_grants SET owner = ? WHERE public_key = ?").run(owner, publicKey);
2722
+ return reply.send({ ok: true, granted: 0, reason: "renamed", from: existing.owner, to: owner });
2723
+ }
2691
2724
  return reply.send({ ok: true, granted: 0, reason: "already_granted" });
2692
2725
  }
2693
2726
  const now = (/* @__PURE__ */ new Date()).toISOString();
2694
2727
  bootstrapAgent(creditDb, owner, amount);
2695
- creditDb.prepare("INSERT INTO credit_grants (public_key, granted_at) VALUES (?, ?)").run(publicKey, now);
2728
+ creditDb.prepare("INSERT INTO credit_grants (public_key, granted_at, owner) VALUES (?, ?, ?)").run(publicKey, now, owner);
2696
2729
  return reply.send({ ok: true, granted: amount });
2697
2730
  });
2698
2731
  scope.get("/api/credits/:owner", {
@@ -2733,6 +2766,38 @@ async function creditRoutesPlugin(fastify, options) {
2733
2766
  const transactions = getTransactions(creditDb, owner, limit);
2734
2767
  return reply.send({ transactions, limit });
2735
2768
  });
2769
+ scope.post("/api/credits/rename", {
2770
+ schema: {
2771
+ tags: ["credits"],
2772
+ summary: "Rename owner \u2014 migrate credits from old owner to new owner",
2773
+ security: [{ ed25519Auth: [] }],
2774
+ body: {
2775
+ type: "object",
2776
+ properties: {
2777
+ oldOwner: { type: "string" },
2778
+ newOwner: { type: "string" }
2779
+ },
2780
+ required: ["oldOwner", "newOwner"]
2781
+ },
2782
+ response: {
2783
+ 200: { type: "object", properties: { ok: { type: "boolean" }, migrated: { type: "boolean" } } },
2784
+ 400: { type: "object", properties: { error: { type: "string" } } }
2785
+ }
2786
+ }
2787
+ }, async (request, reply) => {
2788
+ const body = request.body;
2789
+ const oldOwner = typeof body.oldOwner === "string" ? body.oldOwner.trim() : "";
2790
+ const newOwner = typeof body.newOwner === "string" ? body.newOwner.trim() : "";
2791
+ if (!oldOwner || !newOwner || oldOwner === newOwner) {
2792
+ return reply.code(400).send({ error: "oldOwner and newOwner must be different non-empty strings" });
2793
+ }
2794
+ const oldBalance = getBalance(creditDb, oldOwner);
2795
+ if (oldBalance === 0) {
2796
+ return reply.send({ ok: true, migrated: false });
2797
+ }
2798
+ migrateOwner(creditDb, oldOwner, newOwner);
2799
+ return reply.send({ ok: true, migrated: true });
2800
+ });
2736
2801
  });
2737
2802
  }
2738
2803
 
@@ -3525,11 +3590,6 @@ function createRegistryServer(opts) {
3525
3590
  if (tag !== void 0 && tag.length > 0) {
3526
3591
  cards = cards.filter((c) => c.metadata?.tags?.includes(tag));
3527
3592
  }
3528
- if (minSuccessRate !== void 0 && !isNaN(minSuccessRate)) {
3529
- cards = cards.filter(
3530
- (c) => (c.metadata?.success_rate ?? -1) >= minSuccessRate
3531
- );
3532
- }
3533
3593
  if (maxLatencyMs !== void 0 && !isNaN(maxLatencyMs)) {
3534
3594
  cards = cards.filter(
3535
3595
  (c) => (c.metadata?.avg_latency_ms ?? Infinity) <= maxLatencyMs
@@ -3551,6 +3611,46 @@ function createRegistryServer(opts) {
3551
3611
  usesMap.set(row.skill_id, (usesMap.get(row.skill_id) ?? 0) + row.cnt);
3552
3612
  }
3553
3613
  }
3614
+ const ownerTrustMap = /* @__PURE__ */ new Map();
3615
+ const uniqueOwners = [...new Set(cards.map((c) => c.owner))];
3616
+ if (uniqueOwners.length > 0) {
3617
+ const placeholders = uniqueOwners.map(() => "?").join(",");
3618
+ const trustStmt = db.prepare(`
3619
+ SELECT cc.owner,
3620
+ COUNT(rl.id) as total_exec,
3621
+ SUM(CASE WHEN rl.status IN ('success','failure','timeout','refunded') THEN 1 ELSE 0 END) as terminal_exec,
3622
+ SUM(CASE WHEN rl.status = 'success' THEN 1 ELSE 0 END) as success_exec,
3623
+ AVG(CASE WHEN rl.status = 'success' THEN rl.latency_ms END) as avg_latency
3624
+ FROM capability_cards cc
3625
+ LEFT JOIN request_log rl ON rl.card_id = cc.id AND rl.action_type IS NULL
3626
+ WHERE cc.owner IN (${placeholders})
3627
+ GROUP BY cc.owner
3628
+ `);
3629
+ const trustRows = trustStmt.all(...uniqueOwners);
3630
+ for (const row of trustRows) {
3631
+ const terminalExec = row.terminal_exec ?? 0;
3632
+ const successExec = row.success_exec ?? 0;
3633
+ const successRate = terminalExec > 0 ? successExec / terminalExec : 0;
3634
+ let tier = 0;
3635
+ if (row.total_exec > 10) tier = 1;
3636
+ if (row.total_exec > 50 && successRate >= 0.85) tier = 2;
3637
+ ownerTrustMap.set(row.owner, {
3638
+ performance_tier: tier,
3639
+ authority_source: "self",
3640
+ // Phase 1: all self-declared
3641
+ success_rate: successRate,
3642
+ avg_latency_ms: Math.round(row.avg_latency ?? 0),
3643
+ terminal_exec: terminalExec
3644
+ });
3645
+ }
3646
+ }
3647
+ if (minSuccessRate !== void 0 && !isNaN(minSuccessRate)) {
3648
+ cards = cards.filter((c) => {
3649
+ const trust = ownerTrustMap.get(c.owner);
3650
+ if (!trust || trust.terminal_exec === 0) return false;
3651
+ return trust.success_rate >= minSuccessRate;
3652
+ });
3653
+ }
3554
3654
  if (sort === "popular") {
3555
3655
  cards = [...cards].sort((a, b) => {
3556
3656
  const aUses = usesMap.get(a.id) ?? 0;
@@ -3584,7 +3684,22 @@ function createRegistryServer(opts) {
3584
3684
  });
3585
3685
  }
3586
3686
  const total = cards.length;
3587
- const items = cards.slice(offset, offset + limit).map(stripInternal);
3687
+ const pagedCards = cards.slice(offset, offset + limit);
3688
+ const items = pagedCards.map((card) => {
3689
+ const trust = ownerTrustMap.get(card.owner);
3690
+ const stripped = stripInternal(card);
3691
+ return {
3692
+ ...stripped,
3693
+ performance_tier: trust?.performance_tier ?? 0,
3694
+ authority_source: trust?.authority_source ?? "self",
3695
+ // Enrich metadata with live execution-based success_rate if available
3696
+ metadata: trust && trust.terminal_exec > 0 ? {
3697
+ ...stripped.metadata,
3698
+ success_rate: trust.success_rate,
3699
+ avg_latency_ms: trust.avg_latency_ms || stripped.metadata?.avg_latency_ms
3700
+ } : stripped.metadata
3701
+ };
3702
+ });
3588
3703
  const usesThisWeek = {};
3589
3704
  for (const [key, count] of usesMap) {
3590
3705
  if (count > 0) usesThisWeek[key] = count;
@@ -3794,17 +3909,10 @@ function createRegistryServer(opts) {
3794
3909
  api.get("/api/agents/:owner", {
3795
3910
  schema: {
3796
3911
  tags: ["agents"],
3797
- summary: "Get agent profile, skills, and recent activity",
3912
+ summary: "Get agent profile, skills, and recent activity (AgentProfileV2)",
3798
3913
  params: { type: "object", properties: { owner: { type: "string" } }, required: ["owner"] },
3799
3914
  response: {
3800
- 200: {
3801
- type: "object",
3802
- properties: {
3803
- profile: { type: "object", additionalProperties: true },
3804
- skills: { type: "array" },
3805
- recent_activity: { type: "array" }
3806
- }
3807
- },
3915
+ 200: { type: "object", additionalProperties: true },
3808
3916
  404: { type: "object", properties: { error: { type: "string" } } }
3809
3917
  }
3810
3918
  }
@@ -3814,20 +3922,85 @@ function createRegistryServer(opts) {
3814
3922
  if (ownerCards.length === 0) {
3815
3923
  return reply.status(404).send({ error: "Agent not found" });
3816
3924
  }
3817
- const skillCount = ownerCards.reduce((sum, card) => sum + (card.skills?.length ?? 1), 0);
3818
- const successRates = ownerCards.map((c) => c.metadata?.success_rate).filter((r) => r != null);
3819
- const avgSuccessRate = successRates.length > 0 ? successRates.reduce((a, b) => a + b, 0) / successRates.length : null;
3820
- const creditsStmt = db.prepare(`
3821
- SELECT SUM(CASE WHEN rl.status = 'success' THEN rl.credits_charged ELSE 0 END) as credits_earned
3822
- FROM capability_cards cc
3823
- LEFT JOIN request_log rl ON rl.card_id = cc.id
3824
- WHERE cc.owner = ?
3825
- `);
3826
- const creditsRow = creditsStmt.get(owner);
3827
3925
  const memberStmt = db.prepare(
3828
- "SELECT MIN(created_at) as earliest FROM capability_cards WHERE owner = ?"
3926
+ "SELECT MIN(created_at) as earliest, MAX(created_at) as latest FROM capability_cards WHERE owner = ?"
3829
3927
  );
3830
3928
  const memberRow = memberStmt.get(owner);
3929
+ const joinedAt = memberRow?.earliest ?? (/* @__PURE__ */ new Date()).toISOString();
3930
+ const lastActiveStmt = db.prepare(`
3931
+ SELECT MAX(rl.created_at) as last_req
3932
+ FROM request_log rl
3933
+ INNER JOIN capability_cards cc ON rl.card_id = cc.id
3934
+ WHERE cc.owner = ?
3935
+ `);
3936
+ const lastActiveRow = lastActiveStmt.get(owner);
3937
+ const lastActive = lastActiveRow?.last_req ?? memberRow?.latest ?? joinedAt;
3938
+ const metricsStmt = db.prepare(`
3939
+ SELECT
3940
+ COUNT(*) as total,
3941
+ SUM(CASE WHEN rl.status = 'success' THEN 1 ELSE 0 END) as successes,
3942
+ AVG(CASE WHEN rl.status = 'success' THEN rl.latency_ms END) as avg_latency,
3943
+ COUNT(DISTINCT rl.requester) as unique_requesters,
3944
+ COUNT(DISTINCT CASE WHEN rl.status = 'success' THEN rl.requester END) as repeat_success_requesters
3945
+ FROM request_log rl
3946
+ INNER JOIN capability_cards cc ON rl.card_id = cc.id
3947
+ WHERE cc.owner = ? AND rl.action_type IS NULL
3948
+ `);
3949
+ const metricsRow = metricsStmt.get(owner);
3950
+ const totalExec = metricsRow?.total ?? 0;
3951
+ const successExec = metricsRow?.successes ?? 0;
3952
+ const successRate = totalExec > 0 ? successExec / totalExec : 0;
3953
+ const avgLatency = metricsRow?.avg_latency ?? 0;
3954
+ const refundRate = totalExec > 0 ? (totalExec - successExec) / totalExec : 0;
3955
+ const uniqueReq = metricsRow?.unique_requesters ?? 0;
3956
+ const repeatRate = uniqueReq > 0 ? (metricsRow?.repeat_success_requesters ?? 0) / uniqueReq : 0;
3957
+ const trendStmt = db.prepare(`
3958
+ SELECT
3959
+ DATE(rl.created_at) as day,
3960
+ COUNT(*) as count,
3961
+ SUM(CASE WHEN rl.status = 'success' THEN 1 ELSE 0 END) as success
3962
+ FROM request_log rl
3963
+ INNER JOIN capability_cards cc ON rl.card_id = cc.id
3964
+ WHERE cc.owner = ? AND rl.action_type IS NULL
3965
+ AND rl.created_at >= DATE('now', '-7 days')
3966
+ GROUP BY DATE(rl.created_at)
3967
+ ORDER BY day ASC
3968
+ `);
3969
+ const trend_7d = trendStmt.all(owner).map((r) => ({ date: r.day, count: r.count, success: r.success }));
3970
+ let performanceTier = 0;
3971
+ if (totalExec > 10) performanceTier = 1;
3972
+ if (totalExec > 50 && successRate >= 0.85) performanceTier = 2;
3973
+ const proofsStmt = db.prepare(`
3974
+ SELECT rl.card_name, rl.status, rl.latency_ms, rl.id, rl.created_at
3975
+ FROM request_log rl
3976
+ INNER JOIN capability_cards cc ON rl.card_id = cc.id
3977
+ WHERE cc.owner = ? AND rl.action_type IS NULL
3978
+ ORDER BY rl.created_at DESC
3979
+ LIMIT 10
3980
+ `);
3981
+ const proofRows = proofsStmt.all(owner);
3982
+ const statusToOutcomeClass = (s) => {
3983
+ if (s === "success") return "completed";
3984
+ if (s === "timeout") return "cancelled";
3985
+ return "failed";
3986
+ };
3987
+ const executionProofs = proofRows.map((r) => ({
3988
+ action: r.card_name,
3989
+ status: r.status === "timeout" ? "timeout" : r.status,
3990
+ outcome_class: statusToOutcomeClass(r.status),
3991
+ latency_ms: r.latency_ms,
3992
+ receipt_id: r.id,
3993
+ proof_source: "request_log",
3994
+ timestamp: r.created_at
3995
+ }));
3996
+ const v2Card = ownerCards.find((c) => c.spec_version === "2.0");
3997
+ const suitability = v2Card?.suitability;
3998
+ const learning = {
3999
+ known_limitations: v2Card?.learning?.known_limitations ?? [],
4000
+ common_failure_patterns: v2Card?.learning?.common_failure_patterns ?? [],
4001
+ recent_improvements: v2Card?.learning?.recent_improvements ?? [],
4002
+ critiques: v2Card?.learning?.critiques ?? []
4003
+ };
3831
4004
  const activityStmt = db.prepare(`
3832
4005
  SELECT rl.id, rl.card_name, rl.requester, rl.status, rl.credits_charged, rl.created_at
3833
4006
  FROM request_log rl
@@ -3837,17 +4010,53 @@ function createRegistryServer(opts) {
3837
4010
  LIMIT 10
3838
4011
  `);
3839
4012
  const recentActivity = activityStmt.all(owner);
3840
- const profile = {
4013
+ const skillCount = ownerCards.reduce((sum, card) => sum + (card.skills?.length ?? 1), 0);
4014
+ const creditsStmt = db.prepare(`
4015
+ SELECT SUM(CASE WHEN rl.status = 'success' THEN rl.credits_charged ELSE 0 END) as credits_earned
4016
+ FROM capability_cards cc
4017
+ LEFT JOIN request_log rl ON rl.card_id = cc.id
4018
+ WHERE cc.owner = ?
4019
+ `);
4020
+ const creditsRow = creditsStmt.get(owner);
4021
+ const response = {
3841
4022
  owner,
3842
- skill_count: skillCount,
3843
- success_rate: avgSuccessRate,
3844
- total_earned: creditsRow?.credits_earned ?? 0,
3845
- member_since: memberRow?.earliest ?? (/* @__PURE__ */ new Date()).toISOString()
3846
- };
3847
- return reply.send({
3848
- profile,
4023
+ agent_name: v2Card?.agent_name,
4024
+ short_description: v2Card?.short_description,
4025
+ joined_at: joinedAt,
4026
+ last_active: lastActive,
4027
+ performance_tier: performanceTier,
4028
+ verification_badges: [],
4029
+ // Phase 1: no verification mechanism yet
4030
+ authority: {
4031
+ authority_source: "self",
4032
+ verification_status: "none"
4033
+ },
4034
+ suitability,
4035
+ trust_metrics: {
4036
+ total_executions: totalExec,
4037
+ successful_executions: successExec,
4038
+ success_rate: successRate,
4039
+ avg_latency_ms: Math.round(avgLatency),
4040
+ refund_rate: refundRate,
4041
+ repeat_use_rate: repeatRate,
4042
+ trend_7d,
4043
+ snapshot_at: null,
4044
+ aggregation_window: "all"
4045
+ },
4046
+ execution_proofs: executionProofs,
4047
+ learning,
3849
4048
  skills: ownerCards,
3850
4049
  recent_activity: recentActivity
4050
+ };
4051
+ return reply.send({
4052
+ ...response,
4053
+ profile: {
4054
+ owner,
4055
+ skill_count: skillCount,
4056
+ success_rate: successRate > 0 ? successRate : null,
4057
+ total_earned: creditsRow?.credits_earned ?? 0,
4058
+ member_since: joinedAt
4059
+ }
3851
4060
  });
3852
4061
  });
3853
4062
  api.get("/api/activity", {
@@ -3890,7 +4099,9 @@ function createRegistryServer(opts) {
3890
4099
  properties: {
3891
4100
  agents_online: { type: "integer" },
3892
4101
  total_capabilities: { type: "integer" },
3893
- total_exchanges: { type: "integer" }
4102
+ total_exchanges: { type: "integer" },
4103
+ executions_7d: { type: "integer" },
4104
+ verified_providers_count: { type: "integer" }
3894
4105
  }
3895
4106
  }
3896
4107
  }
@@ -3912,13 +4123,20 @@ function createRegistryServer(opts) {
3912
4123
  "SELECT COUNT(*) as count FROM request_log WHERE status = 'success' AND (action_type IS NULL OR action_type = 'auto_share')"
3913
4124
  );
3914
4125
  const exchangeRow = exchangeStmt.get();
4126
+ const exec7dStmt = db.prepare(
4127
+ "SELECT COUNT(*) as count FROM request_log WHERE action_type IS NULL AND created_at >= DATE('now', '-7 days')"
4128
+ );
4129
+ const exec7dRow = exec7dStmt.get();
3915
4130
  return reply.send({
3916
4131
  agents_online: onlineOwners.size,
3917
4132
  total_capabilities: allCards.reduce((sum, card) => {
3918
4133
  const v2 = card;
3919
4134
  return sum + (v2.skills?.length ?? 1);
3920
4135
  }, 0),
3921
- total_exchanges: exchangeRow.count
4136
+ total_exchanges: exchangeRow.count,
4137
+ executions_7d: exec7dRow.count,
4138
+ verified_providers_count: 0
4139
+ // Phase 1: no verification mechanism yet
3922
4140
  });
3923
4141
  });
3924
4142
  api.post("/api/identity/register", {
@@ -3933,7 +4151,8 @@ function createRegistryServer(opts) {
3933
4151
  response: {
3934
4152
  201: { type: "object", additionalProperties: true },
3935
4153
  400: { type: "object", properties: { error: { type: "string" } } },
3936
- 409: { type: "object", properties: { error: { type: "string" } } }
4154
+ 409: { type: "object", properties: { error: { type: "string" } } },
4155
+ 503: { type: "object", properties: { error: { type: "string" } } }
3937
4156
  }
3938
4157
  }
3939
4158
  }, async (request, reply) => {
@@ -3972,7 +4191,8 @@ function createRegistryServer(opts) {
3972
4191
  200: { type: "object", additionalProperties: true },
3973
4192
  400: { type: "object", properties: { error: { type: "string" } } },
3974
4193
  404: { type: "object", properties: { error: { type: "string" } } },
3975
- 409: { type: "object", properties: { error: { type: "string" } } }
4194
+ 409: { type: "object", properties: { error: { type: "string" } } },
4195
+ 503: { type: "object", properties: { error: { type: "string" } } }
3976
4196
  }
3977
4197
  }
3978
4198
  }, async (request, reply) => {
@@ -4013,7 +4233,8 @@ function createRegistryServer(opts) {
4013
4233
  agent_id: { type: "string" },
4014
4234
  guarantor: { oneOf: [{ type: "object", additionalProperties: true }, { type: "null" }] }
4015
4235
  }
4016
- }
4236
+ },
4237
+ 503: { type: "object", properties: { error: { type: "string" } } }
4017
4238
  }
4018
4239
  }
4019
4240
  }, async (request, reply) => {
@@ -4116,6 +4337,7 @@ function createRegistryServer(opts) {
4116
4337
  params: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
4117
4338
  response: {
4118
4339
  200: { type: "object", properties: { ok: { type: "boolean" }, online: { type: "boolean" } } },
4340
+ 403: { type: "object", properties: { error: { type: "string" } } },
4119
4341
  404: { type: "object", properties: { error: { type: "string" } } }
4120
4342
  }
4121
4343
  }
@@ -4647,6 +4869,51 @@ program.command("init").description("Initialize AgentBnB config and create agent
4647
4869
  }
4648
4870
  const identity = ensureIdentity(configDir, owner);
4649
4871
  const creditDb = openCreditDb(creditDbPath);
4872
+ if (existingConfig?.owner && existingConfig.owner !== owner) {
4873
+ migrateOwner(creditDb, existingConfig.owner, owner);
4874
+ const regDb = openDatabase(dbPath);
4875
+ try {
4876
+ const rows = regDb.prepare("SELECT id, owner, data FROM capability_cards WHERE owner != ?").all(owner);
4877
+ for (const row of rows) {
4878
+ try {
4879
+ const card = JSON.parse(row.data);
4880
+ card.owner = owner;
4881
+ regDb.prepare("UPDATE capability_cards SET owner = ?, data = ? WHERE id = ?").run(owner, JSON.stringify(card), row.id);
4882
+ } catch {
4883
+ }
4884
+ }
4885
+ if (!opts.json && rows.length > 0) {
4886
+ console.log(`Migrated ${rows.length} card(s) \u2192 ${owner}`);
4887
+ }
4888
+ } finally {
4889
+ regDb.close();
4890
+ }
4891
+ const allOwners = creditDb.prepare("SELECT owner FROM credit_balances WHERE owner != ?").all(owner);
4892
+ for (const { owner: oldOwner } of allOwners) {
4893
+ migrateOwner(creditDb, oldOwner, owner);
4894
+ }
4895
+ if (existingConfig.registry) {
4896
+ try {
4897
+ const renameAuth = loadIdentityAuth(owner);
4898
+ const renameLedger = createLedger({
4899
+ registryUrl: existingConfig.registry,
4900
+ ownerPublicKey: renameAuth.publicKey,
4901
+ privateKey: renameAuth.privateKey
4902
+ });
4903
+ await renameLedger.rename(existingConfig.owner, owner);
4904
+ if (!opts.json) {
4905
+ console.log(`Migrated Registry credits: ${existingConfig.owner} \u2192 ${owner}`);
4906
+ }
4907
+ } catch (err) {
4908
+ if (!opts.json) {
4909
+ console.warn(`Warning: could not migrate Registry credits: ${err.message}`);
4910
+ }
4911
+ }
4912
+ }
4913
+ if (!opts.json) {
4914
+ console.log(`Migrated local credits: ${existingConfig.owner} \u2192 ${owner}`);
4915
+ }
4916
+ }
4650
4917
  bootstrapAgent(creditDb, owner, 100);
4651
4918
  creditDb.close();
4652
4919
  let registryBalance;
@@ -5366,12 +5633,13 @@ program.command("request [card-id]").description("Request a capability from anot
5366
5633
  };
5367
5634
  const tryViaRelay = async () => {
5368
5635
  const { RelayClient } = await import("../websocket-client-6IIDGXKB.js");
5369
- const { requestViaRelay } = await import("../client-BTPIFY7E.js");
5636
+ const { requestViaRelay } = await import("../client-T5MTY3CS.js");
5637
+ const requesterId = `${config.owner}:req:${randomUUID10()}`;
5370
5638
  const tempRelay = new RelayClient({
5371
5639
  registryUrl: config.registry,
5372
- owner: config.owner,
5640
+ owner: requesterId,
5373
5641
  token: config.token,
5374
- card: { id: config.owner, owner: config.owner },
5642
+ card: { id: randomUUID10(), owner: requesterId, name: requesterId, description: "Requester", level: 1, spec_version: "1.0", inputs: [], outputs: [], pricing: { credits_per_call: 1 }, availability: { online: false } },
5375
5643
  onRequest: async () => ({ error: { code: -32601, message: "Not serving" } }),
5376
5644
  silent: true
5377
5645
  });
@@ -5382,6 +5650,8 @@ program.command("request [card-id]").description("Request a capability from anot
5382
5650
  cardId,
5383
5651
  skillId: opts.skill,
5384
5652
  params: { ...params, ...opts.skill ? { skill_id: opts.skill } : {} },
5653
+ requester: config.owner,
5654
+ // actual owner for credit tracking on relay server
5385
5655
  escrowReceipt
5386
5656
  });
5387
5657
  return result;
@@ -5507,8 +5777,7 @@ program.command("serve").description("Start the AgentBnB gateway server").option
5507
5777
  console.log("Conductor mode enabled \u2014 orchestrate/plan skills available via gateway");
5508
5778
  }
5509
5779
  if (opts.conductor && config.conductor?.public) {
5510
- const { buildConductorCard } = await import("../card-4XH4AOTE.js");
5511
- const { AnyCardSchema: AnyCard } = await import("../types-FGBUZ3QV.js");
5780
+ const { buildConductorCard } = await import("../card-RSGDCHCV.js");
5512
5781
  const conductorCard = buildConductorCard(config.owner);
5513
5782
  const now = (/* @__PURE__ */ new Date()).toISOString();
5514
5783
  const existing = runtime.registryDb.prepare("SELECT id FROM capability_cards WHERE id = ?").get(conductorCard.id);
@@ -5583,10 +5852,10 @@ program.command("serve").description("Start the AgentBnB gateway server").option
5583
5852
  const relayUrl = opts.registry ?? config.registry;
5584
5853
  if (relayUrl && opts.relay !== false) {
5585
5854
  const { RelayClient } = await import("../websocket-client-6IIDGXKB.js");
5586
- const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("../execute-EXOITLHN.js");
5855
+ const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("../execute-PNGQOMYO.js");
5587
5856
  const cards = listCards(runtime.registryDb, config.owner);
5588
5857
  const card = cards[0] ?? {
5589
- id: config.owner,
5858
+ id: randomUUID10(),
5590
5859
  owner: config.owner,
5591
5860
  name: config.owner,
5592
5861
  description: "Agent registered via CLI",
@@ -5594,12 +5863,12 @@ program.command("serve").description("Start the AgentBnB gateway server").option
5594
5863
  level: 1,
5595
5864
  inputs: [],
5596
5865
  outputs: [],
5597
- pricing: { credits_per_call: 0 },
5866
+ pricing: { credits_per_call: 1 },
5598
5867
  availability: { online: true }
5599
5868
  };
5600
5869
  const additionalCards = [];
5601
5870
  if (config.conductor?.public) {
5602
- const { buildConductorCard } = await import("../card-4XH4AOTE.js");
5871
+ const { buildConductorCard } = await import("../card-RSGDCHCV.js");
5603
5872
  const conductorCard = buildConductorCard(config.owner);
5604
5873
  additionalCards.push(conductorCard);
5605
5874
  console.log("Conductor card will be published to registry (conductor.public: true)");
@@ -5887,7 +6156,7 @@ openclaw.command("rules").description("Print HEARTBEAT.md rules block (or inject
5887
6156
  }
5888
6157
  });
5889
6158
  program.command("conduct <task>").description("Orchestrate a complex task across the AgentBnB network").option("--plan-only", "Show execution plan without executing").option("--max-budget <credits>", "Maximum credits to spend", "100").option("--json", "Output as JSON").action(async (task, opts) => {
5890
- const { conductAction } = await import("../conduct-FXLVGKD5.js");
6159
+ const { conductAction } = await import("../conduct-GZQNFTRP.js");
5891
6160
  const result = await conductAction(task, opts);
5892
6161
  if (opts.json) {
5893
6162
  console.log(JSON.stringify(result, null, 2));
@@ -5921,7 +6190,7 @@ Total credits spent: ${result.total_credits ?? 0} cr`);
5921
6190
  }
5922
6191
  });
5923
6192
  program.command("mcp-server").description("Start an MCP (Model Context Protocol) server for IDE integration").action(async () => {
5924
- const { startMcpServer } = await import("../server-2LWHL24P.js");
6193
+ const { startMcpServer } = await import("../server-365V3GYD.js");
5925
6194
  await startMcpServer();
5926
6195
  });
5927
6196
  await program.parseAsync(process.argv);