agentbnb 9.1.0 → 9.2.0

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 (49) hide show
  1. package/README.md +29 -4
  2. package/dist/{card-VVT3XBOI.js → card-U2HQRPYN.js} +2 -1
  3. package/dist/{card-NQHAGTQQ.js → card-VVXNKHDX.js} +2 -1
  4. package/dist/{chunk-3Y76PHEY.js → chunk-53Q2HHHH.js} +154 -88
  5. package/dist/{chunk-5CC6O6SO.js → chunk-AA25Z6FW.js} +1 -1
  6. package/dist/{chunk-PIO2FMX4.js → chunk-B6AKTLXB.js} +5 -5
  7. package/dist/{chunk-VJ2Q33AP.js → chunk-BPPFY72X.js} +4 -0
  8. package/dist/{chunk-JKD6QRUD.js → chunk-C56X7EFJ.js} +4 -0
  9. package/dist/{chunk-PYZGF5QH.js → chunk-CMGJ52SX.js} +215 -98
  10. package/dist/{chunk-4DBSSFHG.js → chunk-EC6DIVE5.js} +3 -3
  11. package/dist/{chunk-4M6IAIVK.js → chunk-FK54LVDR.js} +2 -2
  12. package/dist/{chunk-JJHQAZWE.js → chunk-GGRH5PCD.js} +10 -10
  13. package/dist/chunk-GZUTU6IZ.js +153 -0
  14. package/dist/{chunk-W6LOCBWQ.js → chunk-IWAK4WHK.js} +1 -1
  15. package/dist/{chunk-ZYOMPJGG.js → chunk-KKFP5Y2Z.js} +2 -2
  16. package/dist/{chunk-XL5XD3IG.js → chunk-MPS4RE7T.js} +7 -7
  17. package/dist/{chunk-DBO2335D.js → chunk-MQIT2F5V.js} +8 -8
  18. package/dist/{chunk-GAZCZCAZ.js → chunk-RNALIVRR.js} +1 -1
  19. package/dist/{chunk-4UIUIHST.js → chunk-UPWAXWY2.js} +1 -1
  20. package/dist/{chunk-UXL7DV7P.js → chunk-V5TJXK3F.js} +3 -3
  21. package/dist/{chunk-AR7Z3EQB.js → chunk-WEZ7PSOE.js} +14 -14
  22. package/dist/{chunk-LENX5NUW.js → chunk-Z7XWQ63B.js} +55 -2
  23. package/dist/cli/index.js +76 -61
  24. package/dist/{client-XOSXFC7Q.js → client-KL67WZVJ.js} +2 -2
  25. package/dist/{conduct-VSSHJHVH.js → conduct-JRLLA4PB.js} +12 -11
  26. package/dist/{conduct-6C6JWZKZ.js → conduct-QLWXU2ZU.js} +12 -11
  27. package/dist/{conductor-mode-KKPSNN7V.js → conductor-mode-66IITI4I.js} +13 -12
  28. package/dist/{conductor-mode-NKHIZG4N.js → conductor-mode-PFO2VLH6.js} +14 -13
  29. package/dist/{credits-action-N3WB4WSI.js → credits-action-XERUEDF3.js} +6 -6
  30. package/dist/{did-action-3PNFYLX2.js → did-action-ODWTBVXL.js} +3 -3
  31. package/dist/{execute-QHP4KUV2.js → execute-NOQVN7ZG.js} +10 -9
  32. package/dist/{execute-IEQ3RV7I.js → execute-YBNCDAOX.js} +8 -7
  33. package/dist/index.js +350 -147
  34. package/dist/{openclaw-setup-PKGFB4IH.js → openclaw-setup-4RIZRMXA.js} +12 -11
  35. package/dist/{openclaw-skills-5VJDA6SX.js → openclaw-skills-TQ2JVBRM.js} +2 -2
  36. package/dist/provider-events-GTTJPYHS.js +13 -0
  37. package/dist/{publish-capability-CHMPZ6W3.js → publish-capability-2FMD3K6Z.js} +3 -2
  38. package/dist/{request-6TBVP3GR.js → request-EYN4CVXC.js} +12 -11
  39. package/dist/{serve-skill-BRUHUDRA.js → serve-skill-NWERGVH5.js} +13 -12
  40. package/dist/{server-N4BJW4TS.js → server-UPOPLZ24.js} +17 -16
  41. package/dist/{service-coordinator-M2CBDEUQ.js → service-coordinator-ZOZTW2U6.js} +419 -58
  42. package/dist/{session-action-67J57636.js → session-action-OSBZB4TX.js} +3 -3
  43. package/dist/signing-AQTKYJDB.js +16 -0
  44. package/dist/skills/agentbnb/bootstrap.js +426 -65
  45. package/dist/{store-A4YPEHDV.js → store-74EWU77V.js} +2 -1
  46. package/dist/{vc-action-TSAIABUM.js → vc-action-A6VBKERF.js} +3 -3
  47. package/package.json +3 -1
  48. package/dist/{chunk-YNBZLXYS.js → chunk-65GNX2KC.js} +0 -0
  49. package/dist/{daemon-OM2K3U7J.js → daemon-ETXXE4IS.js} +1 -1
@@ -8,34 +8,37 @@ import {
8
8
  releaseEscrow,
9
9
  resolveTargetCapability,
10
10
  settleEscrow
11
- } from "./chunk-XL5XD3IG.js";
11
+ } from "./chunk-MPS4RE7T.js";
12
+ import {
13
+ getCard,
14
+ updateReputation
15
+ } from "./chunk-BPPFY72X.js";
16
+ import {
17
+ insertRequestLog
18
+ } from "./chunk-4XTYT4JW.js";
19
+ import {
20
+ emitProviderEvent
21
+ } from "./chunk-GZUTU6IZ.js";
12
22
  import {
13
23
  canonicalizeCreditOwner
14
24
  } from "./chunk-6QMDJVMS.js";
25
+ import {
26
+ lookupAgent
27
+ } from "./chunk-EE3V3DXK.js";
15
28
  import {
16
29
  generateKeyPair,
17
30
  loadKeyPair,
18
31
  saveKeyPair,
19
32
  signEscrowReceipt,
20
33
  verifyEscrowReceipt
21
- } from "./chunk-YNBZLXYS.js";
34
+ } from "./chunk-65GNX2KC.js";
35
+ import {
36
+ AgentBnBError
37
+ } from "./chunk-UVCNMRPS.js";
22
38
  import {
23
39
  getConfigDir,
24
40
  loadConfig
25
41
  } from "./chunk-IVOYM3WG.js";
26
- import {
27
- getCard,
28
- updateReputation
29
- } from "./chunk-VJ2Q33AP.js";
30
- import {
31
- insertRequestLog
32
- } from "./chunk-4XTYT4JW.js";
33
- import {
34
- lookupAgent
35
- } from "./chunk-EE3V3DXK.js";
36
- import {
37
- AgentBnBError
38
- } from "./chunk-UVCNMRPS.js";
39
42
 
40
43
  // src/gateway/execute.ts
41
44
  import { randomUUID } from "crypto";
@@ -388,6 +391,58 @@ function signRequest(method, path, body, privateKey, publicKeyHex, agentIdOverri
388
391
  "X-Agent-Timestamp": timestamp
389
392
  };
390
393
  }
394
+ async function tryVerifyIdentity(request, options = {}) {
395
+ const agentIdHeader = request.headers["x-agent-id"];
396
+ const publicKeyHeader = request.headers["x-agent-publickey"];
397
+ const signatureHeader = request.headers["x-agent-signature"];
398
+ const timestampHeader = request.headers["x-agent-timestamp"];
399
+ const agentId = agentIdHeader?.trim();
400
+ const publicKeyHex = publicKeyHeader?.trim();
401
+ const signature = signatureHeader?.trim();
402
+ const timestamp = timestampHeader?.trim();
403
+ if (!agentId || !publicKeyHex || !signature || !timestamp) {
404
+ return { valid: false, reason: "missing_headers" };
405
+ }
406
+ const requestTime = new Date(timestamp).getTime();
407
+ if (isNaN(requestTime) || Math.abs(Date.now() - requestTime) > MAX_REQUEST_AGE_MS) {
408
+ return { valid: false, reason: "expired" };
409
+ }
410
+ if (!/^[0-9a-fA-F]+$/.test(publicKeyHex) || publicKeyHex.length % 2 !== 0) {
411
+ return { valid: false, reason: "invalid_key" };
412
+ }
413
+ let expectedAgentId;
414
+ try {
415
+ expectedAgentId = deriveAgentId(publicKeyHex);
416
+ } catch {
417
+ return { valid: false, reason: "invalid_key" };
418
+ }
419
+ if (agentId !== expectedAgentId) {
420
+ return { valid: false, reason: "agent_id_mismatch" };
421
+ }
422
+ let publicKeyBuffer;
423
+ try {
424
+ publicKeyBuffer = Buffer.from(publicKeyHex, "hex");
425
+ } catch {
426
+ return { valid: false, reason: "invalid_key" };
427
+ }
428
+ const knownAgent = options.agentDb ? lookupAgent(options.agentDb, agentId) : null;
429
+ if (knownAgent && knownAgent.public_key.toLowerCase() !== publicKeyHex.toLowerCase()) {
430
+ return { valid: false, reason: "key_drift" };
431
+ }
432
+ const payload = buildIdentityPayload(
433
+ request.method,
434
+ request.url,
435
+ timestamp,
436
+ publicKeyHex,
437
+ agentId,
438
+ request.body
439
+ );
440
+ const valid = verifyEscrowReceipt(payload, signature, publicKeyBuffer);
441
+ if (!valid) {
442
+ return { valid: false, reason: "invalid_signature" };
443
+ }
444
+ return { valid: true, agentId, publicKey: publicKeyHex };
445
+ }
391
446
 
392
447
  // src/credit/registry-credit-ledger.ts
393
448
  var HTTP_TIMEOUT_MS = 1e4;
@@ -654,72 +709,133 @@ async function syncCreditsFromRegistry(config, localDb) {
654
709
  }
655
710
  }
656
711
 
657
- // src/gateway/execute.ts
658
- async function notifyTelegramSkillExecuted(opts) {
659
- const cfg = loadConfig();
660
- if (!cfg?.telegram_notifications) return;
661
- const token = cfg.telegram_bot_token ?? process.env["TELEGRAM_BOT_TOKEN"];
662
- const chatId = cfg.telegram_chat_id ?? process.env["TELEGRAM_CHAT_ID"];
663
- if (!token || !chatId) return;
664
- const balance = getBalance(opts.creditDb, opts.owner);
665
- const skillLabel = opts.skillId ? `${opts.skillName} (${opts.skillId})` : opts.skillName;
666
- const text = [
667
- "[AgentBnB] Skill executed",
668
- `Skill: ${skillLabel}`,
669
- `Requester: ${opts.requester}`,
670
- `Earned: +${opts.creditsEarned} credits`,
671
- `Balance: ${balance} credits`,
672
- `Latency: ${opts.latencyMs}ms`
673
- ].join("\n");
674
- await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
675
- method: "POST",
676
- headers: { "Content-Type": "application/json" },
677
- body: JSON.stringify({ chat_id: chatId, text })
678
- });
679
- }
680
- async function notifyTelegramSkillFailed(opts) {
681
- const cfg = loadConfig();
682
- if (!cfg?.telegram_notifications) return;
683
- const token = cfg.telegram_bot_token ?? process.env["TELEGRAM_BOT_TOKEN"];
684
- const chatId = cfg.telegram_chat_id ?? process.env["TELEGRAM_CHAT_ID"];
685
- if (!token || !chatId) return;
686
- const balance = getBalance(opts.creditDb, opts.owner);
687
- const skillLabel = opts.skillId ? `${opts.skillName} (${opts.skillId})` : opts.skillName;
688
- const text = [
689
- "[AgentBnB] Skill failed",
690
- `Skill: ${skillLabel}`,
691
- `Requester: ${opts.requester}`,
692
- `Reason: ${opts.failureReason}`,
693
- `Error: ${opts.message}`,
694
- `Balance: ${balance} credits`,
695
- `Latency: ${opts.latencyMs}ms`
696
- ].join("\n");
697
- await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
698
- method: "POST",
699
- headers: { "Content-Type": "application/json" },
700
- body: JSON.stringify({ chat_id: chatId, text })
701
- });
712
+ // src/gateway/provider-notifier.ts
713
+ var EVENT_EMOJI = {
714
+ "skill.received": "\u{1F4E5}",
715
+ "skill.executed": "\u2705",
716
+ "skill.failed": "\u274C",
717
+ "skill.rejected": "\u{1F6AB}",
718
+ "session.opened": "\u{1F517}",
719
+ "session.message": "\u{1F4AC}",
720
+ "session.ended": "\u{1F3C1}",
721
+ "session.failed": "\u{1F4A5}"
722
+ };
723
+ function formatEventMessage(event, balance) {
724
+ const emoji = EVENT_EMOJI[event.event_type] ?? "\u{1F4CB}";
725
+ const meta = event.metadata ?? {};
726
+ const skillLabel = event.skill_id ?? "unknown";
727
+ switch (event.event_type) {
728
+ case "skill.received":
729
+ return [
730
+ `${emoji} [AgentBnB] Incoming request`,
731
+ `Skill: ${skillLabel}`,
732
+ `Requester: ${event.requester}`,
733
+ `Cost: ${event.credits} credits`,
734
+ `Status: Executing...`
735
+ ].join("\n");
736
+ case "skill.executed":
737
+ return [
738
+ `${emoji} [AgentBnB] Skill executed`,
739
+ `Skill: ${skillLabel}`,
740
+ `Requester: ${event.requester}`,
741
+ `Earned: +${event.credits} credits`,
742
+ ...balance !== void 0 ? [`Balance: ${balance} credits`] : [],
743
+ `Latency: ${event.duration_ms}ms`
744
+ ].join("\n");
745
+ case "skill.failed":
746
+ return [
747
+ `${emoji} [AgentBnB] Skill failed`,
748
+ `Skill: ${skillLabel}`,
749
+ `Requester: ${event.requester}`,
750
+ `Reason: ${meta["failure_reason"] ?? "unknown"}`,
751
+ ...meta["error"] ? [`Error: ${String(meta["error"]).slice(0, 200)}`] : [],
752
+ ...balance !== void 0 ? [`Balance: ${balance} credits`] : [],
753
+ `Latency: ${event.duration_ms}ms`
754
+ ].join("\n");
755
+ case "skill.rejected":
756
+ return [
757
+ `${emoji} [AgentBnB] Request rejected`,
758
+ `Skill: ${skillLabel}`,
759
+ `Requester: ${event.requester}`,
760
+ `Reason: ${meta["reason"] ?? "unknown"}`
761
+ ].join("\n");
762
+ case "session.opened":
763
+ return [
764
+ `${emoji} [AgentBnB] Session opened`,
765
+ `Session: ${event.session_id?.slice(0, 8)}...`,
766
+ `Requester: ${event.requester}`,
767
+ `Skill: ${skillLabel}`,
768
+ `Pricing: ${meta["pricing_model"] ?? "unknown"}`,
769
+ `Budget: ${event.credits} credits`
770
+ ].join("\n");
771
+ case "session.message": {
772
+ const msgCount = meta["message_count"] ?? "?";
773
+ const runningCost = meta["running_cost"] ?? event.credits;
774
+ return [
775
+ `${emoji} [AgentBnB] Session message #${msgCount}`,
776
+ `Session: ${event.session_id?.slice(0, 8)}...`,
777
+ `Running cost: ${runningCost} credits`
778
+ ].join("\n");
779
+ }
780
+ case "session.ended": {
781
+ const totalMsgs = meta["total_messages"] ?? "?";
782
+ const durationMin = Math.round(event.duration_ms / 6e4);
783
+ const refunded = Number(meta["refunded"] ?? 0);
784
+ return [
785
+ `${emoji} [AgentBnB] Session ended`,
786
+ `Session: ${event.session_id?.slice(0, 8)}...`,
787
+ `Total: ${totalMsgs} messages, ${event.credits} credits`,
788
+ `Duration: ${durationMin} minutes`,
789
+ ...refunded > 0 ? [`Refunded: ${refunded} credits`] : []
790
+ ].join("\n");
791
+ }
792
+ case "session.failed": {
793
+ const lastMsgs = Array.isArray(meta["last_messages"]) ? meta["last_messages"] : [];
794
+ const lines = [
795
+ `${emoji} [AgentBnB] Session failed`,
796
+ `Session: ${event.session_id?.slice(0, 8)}...`,
797
+ `Reason: ${meta["reason"] ?? "error"}`,
798
+ `Cost: ${event.credits} credits`
799
+ ];
800
+ if (lastMsgs.length > 0) {
801
+ lines.push("", "Last messages:");
802
+ for (const m of lastMsgs) {
803
+ lines.push(` ${m.sender}: ${m.content.slice(0, 100)}`);
804
+ }
805
+ }
806
+ return lines.join("\n");
807
+ }
808
+ default:
809
+ return `${emoji} [AgentBnB] ${event.event_type}: ${skillLabel}`;
810
+ }
702
811
  }
703
- async function notifyTelegramSkillReceived(opts) {
812
+ async function notifyProviderEvent(event, creditDb, owner) {
704
813
  const cfg = loadConfig();
705
- if (cfg?.provider_gate !== "notify") return;
814
+ if (!cfg) return;
815
+ const telegramEnabled = cfg.telegram_notifications === true;
816
+ const gateNotify = cfg.provider_gate === "notify";
817
+ if (!telegramEnabled && !gateNotify) return;
818
+ const filters = cfg.notification_filters ?? ["session.message"];
819
+ if (filters.includes(event.event_type)) return;
706
820
  const token = cfg.telegram_bot_token ?? process.env["TELEGRAM_BOT_TOKEN"];
707
821
  const chatId = cfg.telegram_chat_id ?? process.env["TELEGRAM_CHAT_ID"];
708
822
  if (!token || !chatId) return;
709
- const skillLabel = opts.skillId ? `${opts.skillName} (${opts.skillId})` : opts.skillName;
710
- const text = [
711
- "\u{1F4E5} [AgentBnB] Incoming rental request",
712
- `Skill: ${skillLabel}`,
713
- `Requester: ${opts.requester}`,
714
- `Cost: ${opts.cost} credits`,
715
- `Status: Executing...`
716
- ].join("\n");
823
+ let balance;
824
+ if (creditDb && owner && (event.event_type === "skill.executed" || event.event_type === "skill.failed")) {
825
+ try {
826
+ balance = getBalance(creditDb, owner);
827
+ } catch {
828
+ }
829
+ }
830
+ const text = formatEventMessage(event, balance);
717
831
  await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
718
832
  method: "POST",
719
833
  headers: { "Content-Type": "application/json" },
720
834
  body: JSON.stringify({ chat_id: chatId, text })
721
835
  });
722
836
  }
837
+
838
+ // src/gateway/execute.ts
723
839
  async function executeCapabilityRequest(opts) {
724
840
  const {
725
841
  registryDb,
@@ -822,6 +938,10 @@ async function executeCapabilityRequest(opts) {
822
938
  const blacklist = providerCfg?.provider_blacklist ?? [];
823
939
  if (blacklist.includes(requester)) {
824
940
  if (escrowId) releaseEscrow(creditDb, escrowId);
941
+ try {
942
+ emitProviderEvent(registryDb, { event_type: "skill.rejected", skill_id: resolvedSkillId ?? null, session_id: null, requester, credits: 0, duration_ms: 0, metadata: { reason: "blacklisted" } });
943
+ } catch {
944
+ }
825
945
  return { success: false, error: { code: -32097, message: "Requester is blocked by provider" } };
826
946
  }
827
947
  }
@@ -832,6 +952,10 @@ async function executeCapabilityRequest(opts) {
832
952
  const todayCount = countTodayExecutions(registryDb);
833
953
  if (todayCount >= dailyLimit) {
834
954
  if (escrowId) releaseEscrow(creditDb, escrowId);
955
+ try {
956
+ emitProviderEvent(registryDb, { event_type: "skill.rejected", skill_id: resolvedSkillId ?? null, session_id: null, requester, credits: 0, duration_ms: 0, metadata: { reason: "daily_limit", limit: dailyLimit } });
957
+ } catch {
958
+ }
835
959
  return {
836
960
  success: false,
837
961
  error: { code: -32099, message: `Provider daily execution limit reached (${dailyLimit}/day)` }
@@ -839,13 +963,13 @@ async function executeCapabilityRequest(opts) {
839
963
  }
840
964
  }
841
965
  }
842
- notifyTelegramSkillReceived({
843
- skillName: cardName,
844
- skillId: resolvedSkillId ?? null,
845
- requester,
846
- cost: creditsNeeded
847
- }).catch(() => {
848
- });
966
+ const receivedEvent = { event_type: "skill.received", skill_id: resolvedSkillId ?? null, session_id: null, requester, credits: creditsNeeded, duration_ms: 0, metadata: { gate_mode: providerCfg?.provider_gate ?? "auto" } };
967
+ try {
968
+ const emitted = emitProviderEvent(registryDb, receivedEvent);
969
+ notifyProviderEvent(emitted, creditDb, card.owner).catch(() => {
970
+ });
971
+ } catch {
972
+ }
849
973
  const startMs = Date.now();
850
974
  const handleFailure = (status, latencyMs, message, failureReason = "bad_execution") => {
851
975
  if (escrowId) releaseEscrow(creditDb, escrowId);
@@ -867,17 +991,12 @@ async function executeCapabilityRequest(opts) {
867
991
  });
868
992
  } catch {
869
993
  }
870
- notifyTelegramSkillFailed({
871
- creditDb,
872
- owner: card.owner,
873
- skillName: cardName,
874
- skillId: resolvedSkillId ?? null,
875
- requester,
876
- latencyMs,
877
- failureReason,
878
- message
879
- }).catch(() => {
880
- });
994
+ try {
995
+ const emitted = emitProviderEvent(registryDb, { event_type: "skill.failed", skill_id: resolvedSkillId ?? null, session_id: null, requester, credits: 0, duration_ms: latencyMs, metadata: { failure_reason: failureReason, error: message } });
996
+ notifyProviderEvent(emitted, creditDb, card.owner).catch(() => {
997
+ });
998
+ } catch {
999
+ }
881
1000
  return { success: false, error: { code: -32603, message } };
882
1001
  };
883
1002
  const handleSuccess = (result, latencyMs) => {
@@ -899,16 +1018,12 @@ async function executeCapabilityRequest(opts) {
899
1018
  });
900
1019
  } catch {
901
1020
  }
902
- notifyTelegramSkillExecuted({
903
- creditDb,
904
- owner: card.owner,
905
- skillName: cardName,
906
- skillId: resolvedSkillId ?? null,
907
- requester,
908
- creditsEarned: creditsNeeded,
909
- latencyMs
910
- }).catch(() => {
911
- });
1021
+ try {
1022
+ const emitted = emitProviderEvent(registryDb, { event_type: "skill.executed", skill_id: resolvedSkillId ?? null, session_id: null, requester, credits: creditsNeeded, duration_ms: latencyMs, metadata: null });
1023
+ notifyProviderEvent(emitted, creditDb, card.owner).catch(() => {
1024
+ });
1025
+ } catch {
1026
+ }
912
1027
  return { success: true, result };
913
1028
  };
914
1029
  if (skillExecutor) {
@@ -1145,8 +1260,10 @@ export {
1145
1260
  loadOrRepairIdentity,
1146
1261
  ensureIdentity,
1147
1262
  identityAuthPlugin,
1263
+ tryVerifyIdentity,
1148
1264
  createLedger,
1149
1265
  syncCreditsFromRegistry,
1266
+ notifyProviderEvent,
1150
1267
  executeCapabilityRequest,
1151
1268
  executeCapabilityBatch
1152
1269
  };
@@ -1,9 +1,9 @@
1
+ import {
2
+ getFeedbackForProvider
3
+ } from "./chunk-C56X7EFJ.js";
1
4
  import {
2
5
  loadCoreConfig
3
6
  } from "./chunk-QXRNW4OJ.js";
4
- import {
5
- getFeedbackForProvider
6
- } from "./chunk-JKD6QRUD.js";
7
7
 
8
8
  // src/feedback/reputation.ts
9
9
  var coreReputation = loadCoreConfig("reputation");
@@ -3,10 +3,10 @@ import {
3
3
  } from "./chunk-ELFGYC22.js";
4
4
  import {
5
5
  searchCards
6
- } from "./chunk-4DBSSFHG.js";
6
+ } from "./chunk-EC6DIVE5.js";
7
7
  import {
8
8
  getCard
9
- } from "./chunk-JKD6QRUD.js";
9
+ } from "./chunk-C56X7EFJ.js";
10
10
  import {
11
11
  resolveCanonicalIdentity
12
12
  } from "./chunk-J4RFJVXI.js";
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  createPendingRequest
3
3
  } from "./chunk-5PV5YCSN.js";
4
- import {
5
- getAutonomyTier,
6
- insertAuditEvent
7
- } from "./chunk-G5WKW3ED.js";
8
4
  import {
9
5
  resolveTargetCapability
10
- } from "./chunk-4M6IAIVK.js";
6
+ } from "./chunk-FK54LVDR.js";
11
7
  import {
12
8
  fetchRemoteCards
13
9
  } from "./chunk-ELFGYC22.js";
10
+ import {
11
+ getAutonomyTier,
12
+ insertAuditEvent
13
+ } from "./chunk-G5WKW3ED.js";
14
14
  import {
15
15
  searchCards
16
- } from "./chunk-4DBSSFHG.js";
16
+ } from "./chunk-EC6DIVE5.js";
17
17
  import {
18
18
  holdEscrow,
19
19
  releaseEscrow,
@@ -25,16 +25,16 @@ import {
25
25
  import {
26
26
  requestCapability,
27
27
  requestViaRelay
28
- } from "./chunk-W6LOCBWQ.js";
29
- import {
30
- findPeer
31
- } from "./chunk-3YQ73ZM6.js";
28
+ } from "./chunk-IWAK4WHK.js";
32
29
  import {
33
30
  resolveCanonicalIdentity
34
31
  } from "./chunk-J4RFJVXI.js";
35
32
  import {
36
33
  AgentBnBError
37
34
  } from "./chunk-UVCNMRPS.js";
35
+ import {
36
+ findPeer
37
+ } from "./chunk-3YQ73ZM6.js";
38
38
 
39
39
  // src/gateway/relay-dispatch.ts
40
40
  import { randomUUID } from "crypto";
@@ -0,0 +1,153 @@
1
+ // src/registry/provider-events.ts
2
+ import { randomUUID } from "crypto";
3
+ var PROVIDER_EVENTS_SCHEMA = `
4
+ CREATE TABLE IF NOT EXISTS provider_events (
5
+ id TEXT PRIMARY KEY,
6
+ event_type TEXT NOT NULL,
7
+ skill_id TEXT,
8
+ session_id TEXT,
9
+ requester TEXT,
10
+ credits INTEGER DEFAULT 0,
11
+ duration_ms INTEGER DEFAULT 0,
12
+ metadata TEXT,
13
+ created_at TEXT NOT NULL
14
+ );
15
+
16
+ CREATE INDEX IF NOT EXISTS idx_provider_events_type
17
+ ON provider_events(event_type);
18
+ CREATE INDEX IF NOT EXISTS idx_provider_events_created
19
+ ON provider_events(created_at DESC);
20
+ `;
21
+ function ensureProviderEventsTable(db) {
22
+ db.exec(PROVIDER_EVENTS_SCHEMA);
23
+ }
24
+ function emitProviderEvent(db, event) {
25
+ const id = randomUUID();
26
+ const created_at = (/* @__PURE__ */ new Date()).toISOString();
27
+ const metadataJson = event.metadata ? JSON.stringify(event.metadata) : null;
28
+ db.prepare(`
29
+ INSERT INTO provider_events (id, event_type, skill_id, session_id, requester, credits, duration_ms, metadata, created_at)
30
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
31
+ `).run(id, event.event_type, event.skill_id, event.session_id, event.requester, event.credits, event.duration_ms, metadataJson, created_at);
32
+ return { ...event, id, created_at };
33
+ }
34
+ function getProviderEvents(db, opts = {}) {
35
+ const limit = Math.min(opts.limit ?? 50, 200);
36
+ const conditions = [];
37
+ const params = [];
38
+ if (opts.since) {
39
+ conditions.push("created_at > ?");
40
+ params.push(opts.since);
41
+ }
42
+ if (opts.event_type) {
43
+ conditions.push("event_type = ?");
44
+ params.push(opts.event_type);
45
+ }
46
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
47
+ const sql = `SELECT * FROM provider_events ${where} ORDER BY created_at DESC LIMIT ?`;
48
+ params.push(limit);
49
+ const rows = db.prepare(sql).all(...params);
50
+ return rows.map(parseEventRow);
51
+ }
52
+ var PERIOD_MS = {
53
+ "24h": 24 * 60 * 60 * 1e3,
54
+ "7d": 7 * 24 * 60 * 60 * 1e3,
55
+ "30d": 30 * 24 * 60 * 60 * 1e3
56
+ };
57
+ function getProviderStats(db, period = "7d") {
58
+ const cutoff = new Date(Date.now() - (PERIOD_MS[period] ?? PERIOD_MS["7d"])).toISOString();
59
+ const summary = db.prepare(`
60
+ SELECT
61
+ COALESCE(SUM(CASE WHEN event_type = 'skill.executed' THEN credits ELSE 0 END), 0) as total_earnings,
62
+ COUNT(CASE WHEN event_type IN ('skill.executed', 'skill.failed') THEN 1 END) as total_executions,
63
+ COUNT(CASE WHEN event_type = 'skill.executed' THEN 1 END) as success_count,
64
+ COUNT(CASE WHEN event_type = 'skill.failed' THEN 1 END) as failure_count
65
+ FROM provider_events
66
+ WHERE created_at >= ?
67
+ `).get(cutoff);
68
+ const activeSessions = db.prepare(`
69
+ SELECT COUNT(DISTINCT session_id) as cnt
70
+ FROM provider_events
71
+ WHERE event_type = 'session.opened'
72
+ AND session_id NOT IN (
73
+ SELECT DISTINCT session_id FROM provider_events
74
+ WHERE event_type IN ('session.ended', 'session.failed')
75
+ AND session_id IS NOT NULL
76
+ )
77
+ AND session_id IS NOT NULL
78
+ `).get();
79
+ const topSkills = db.prepare(`
80
+ SELECT skill_id, COUNT(*) as count, COALESCE(SUM(credits), 0) as earnings
81
+ FROM provider_events
82
+ WHERE event_type = 'skill.executed' AND created_at >= ? AND skill_id IS NOT NULL
83
+ GROUP BY skill_id
84
+ ORDER BY count DESC
85
+ LIMIT 10
86
+ `).all(cutoff);
87
+ const topRequesters = db.prepare(`
88
+ SELECT requester, COUNT(*) as count
89
+ FROM provider_events
90
+ WHERE event_type IN ('skill.executed', 'session.opened') AND created_at >= ? AND requester IS NOT NULL
91
+ GROUP BY requester
92
+ ORDER BY count DESC
93
+ LIMIT 10
94
+ `).all(cutoff);
95
+ const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1e3).toISOString();
96
+ const timelineRows = db.prepare(`
97
+ SELECT DATE(created_at) as date, COALESCE(SUM(credits), 0) as earnings
98
+ FROM provider_events
99
+ WHERE event_type = 'skill.executed' AND created_at >= ?
100
+ GROUP BY DATE(created_at)
101
+ ORDER BY date ASC
102
+ `).all(sevenDaysAgo);
103
+ const timelineMap = new Map(timelineRows.map((r) => [r.date, r.earnings]));
104
+ const earnings_timeline = [];
105
+ for (let i = 6; i >= 0; i--) {
106
+ const d = new Date(Date.now() - i * 24 * 60 * 60 * 1e3);
107
+ const dateStr = d.toISOString().slice(0, 10);
108
+ earnings_timeline.push({ date: dateStr, earnings: timelineMap.get(dateStr) ?? 0 });
109
+ }
110
+ const successRate = summary.total_executions > 0 ? summary.success_count / summary.total_executions : 1;
111
+ return {
112
+ total_earnings: summary.total_earnings,
113
+ total_spending: 0,
114
+ // Filled by API layer (reads credit_transactions)
115
+ net_pnl: summary.total_earnings,
116
+ total_executions: summary.total_executions,
117
+ success_count: summary.success_count,
118
+ failure_count: summary.failure_count,
119
+ success_rate: Math.round(successRate * 1e3) / 1e3,
120
+ active_sessions: activeSessions.cnt,
121
+ top_skills: topSkills,
122
+ top_requesters: topRequesters,
123
+ earnings_timeline
124
+ };
125
+ }
126
+ function parseEventRow(row) {
127
+ let metadata = null;
128
+ if (typeof row["metadata"] === "string") {
129
+ try {
130
+ metadata = JSON.parse(row["metadata"]);
131
+ } catch {
132
+ metadata = null;
133
+ }
134
+ }
135
+ return {
136
+ id: row["id"],
137
+ event_type: row["event_type"],
138
+ skill_id: row["skill_id"] ?? null,
139
+ session_id: row["session_id"] ?? null,
140
+ requester: row["requester"] ?? null,
141
+ credits: row["credits"] ?? 0,
142
+ duration_ms: row["duration_ms"] ?? 0,
143
+ metadata,
144
+ created_at: row["created_at"]
145
+ };
146
+ }
147
+
148
+ export {
149
+ ensureProviderEventsTable,
150
+ emitProviderEvent,
151
+ getProviderEvents,
152
+ getProviderStats
153
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  signEscrowReceipt
3
- } from "./chunk-YNBZLXYS.js";
3
+ } from "./chunk-65GNX2KC.js";
4
4
  import {
5
5
  AgentBnBError
6
6
  } from "./chunk-UVCNMRPS.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createLedger
3
- } from "./chunk-LENX5NUW.js";
3
+ } from "./chunk-Z7XWQ63B.js";
4
4
  import {
5
5
  loadOrRepairIdentity
6
- } from "./chunk-5CC6O6SO.js";
6
+ } from "./chunk-AA25Z6FW.js";
7
7
  import {
8
8
  getBalance
9
9
  } from "./chunk-D7NH6YLM.js";
@@ -1,16 +1,13 @@
1
+ import {
2
+ getCard,
3
+ getFeedbackForProvider
4
+ } from "./chunk-BPPFY72X.js";
1
5
  import {
2
6
  canonicalizeCreditOwner,
3
7
  ensureReliabilityTable,
4
8
  migrateCreditOwnerData,
5
9
  recordSuccessfulHire
6
10
  } from "./chunk-6QMDJVMS.js";
7
- import {
8
- loadCoreConfig
9
- } from "./chunk-QXRNW4OJ.js";
10
- import {
11
- getCard,
12
- getFeedbackForProvider
13
- } from "./chunk-VJ2Q33AP.js";
14
11
  import {
15
12
  ensureAgentsTable,
16
13
  resolveCanonicalIdentity
@@ -18,6 +15,9 @@ import {
18
15
  import {
19
16
  AgentBnBError
20
17
  } from "./chunk-UVCNMRPS.js";
18
+ import {
19
+ loadCoreConfig
20
+ } from "./chunk-QXRNW4OJ.js";
21
21
 
22
22
  // src/credit/ledger.ts
23
23
  import Database from "better-sqlite3";