agentbnb 9.0.3 → 9.1.1

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 (75) hide show
  1. package/README.md +29 -4
  2. package/dist/{card-6KL6L4GF.js → card-U2HQRPYN.js} +4 -1
  3. package/dist/{card-NKQFB3HD.js → card-UF465O7O.js} +4 -1
  4. package/dist/{chunk-77HAL2ZL.js → chunk-2HH2F3DM.js} +189 -68
  5. package/dist/chunk-3RG5ZIWI.js +10 -0
  6. package/dist/chunk-4HLGFR72.js +155 -0
  7. package/dist/chunk-4XTYT4JW.js +147 -0
  8. package/dist/{chunk-NLQCHO7N.js → chunk-7VZ4M4CT.js} +7 -134
  9. package/dist/{chunk-UQCQ2JCG.js → chunk-AMABG5SI.js} +7 -7
  10. package/dist/{chunk-N3TXLBGK.js → chunk-AW4VSROG.js} +1 -1
  11. package/dist/{chunk-PG3CLSAH.js → chunk-BPPFY72X.js} +7 -134
  12. package/dist/{chunk-Z4IDXMSP.js → chunk-D7NH6YLM.js} +6 -1
  13. package/dist/{chunk-SLZBE2I5.js → chunk-F2CIPAN2.js} +19 -14
  14. package/dist/{chunk-FUGWPKXN.js → chunk-G4TF4LB4.js} +1 -1
  15. package/dist/chunk-GZUTU6IZ.js +153 -0
  16. package/dist/{chunk-QEDVPJKP.js → chunk-I4E5ERDN.js} +20 -16
  17. package/dist/{chunk-74OZGLIT.js → chunk-LENX5NUW.js} +1 -1
  18. package/dist/{chunk-BNS76U6K.js → chunk-MPS4RE7T.js} +26 -20
  19. package/dist/{chunk-ERT77HKY.js → chunk-O44N3KR7.js} +2 -2
  20. package/dist/chunk-Q5OFZ2JR.js +292 -0
  21. package/dist/{chunk-YJ3RGKPU.js → chunk-QG2LLVXP.js} +6 -2
  22. package/dist/chunk-QXRNW4OJ.js +35 -0
  23. package/dist/{chunk-76YORWFJ.js → chunk-RVOZHVM7.js} +186 -63
  24. package/dist/{chunk-2SOHHB2O.js → chunk-TCA63C42.js} +39 -16
  25. package/dist/{chunk-UR3MISL2.js → chunk-UPNREF4L.js} +1 -1
  26. package/dist/{chunk-SMQDT7CT.js → chunk-WARYO57F.js} +7 -3
  27. package/dist/{chunk-DYJ7YGBM.js → chunk-WOVESOQ7.js} +237 -124
  28. package/dist/{chunk-I3RRMAAD.js → chunk-Y7CO3VLF.js} +8 -8
  29. package/dist/{chunk-FMKBCO2Q.js → chunk-ZYOMPJGG.js} +2 -2
  30. package/dist/cli/index.js +147 -63
  31. package/dist/{client-YB3IYO3S.js → client-XOSXFC7Q.js} +1 -0
  32. package/dist/conduct-MALC6HEK.js +30 -0
  33. package/dist/{conduct-URYWMA5T.js → conduct-UT6ZYSJD.js} +16 -12
  34. package/dist/{conductor-mode-2UFN6BUL.js → conductor-mode-3WLLERB4.js} +23 -19
  35. package/dist/{conductor-mode-NRSVP2AU.js → conductor-mode-UJKMO2GW.js} +15 -11
  36. package/dist/{config-IRWLG6IW.js → config-ZFWBAGDU.js} +1 -0
  37. package/dist/{credits-action-24EPLUHG.js → credits-action-KOUJNR36.js} +7 -5
  38. package/dist/{daemon-A7DXZIQW.js → daemon-ETXXE4IS.js} +2 -1
  39. package/dist/{did-action-MQLDT4RF.js → did-action-UHUYMA4Y.js} +2 -1
  40. package/dist/{execute-DNRNU3HM.js → execute-3RADNI74.js} +9 -5
  41. package/dist/{execute-2Z3XIUHR.js → execute-UFMGTXET.js} +12 -8
  42. package/dist/index.d.ts +412 -275
  43. package/dist/index.js +1198 -391
  44. package/dist/{openclaw-setup-WA625DZA.js → openclaw-setup-HEWZZOY7.js} +21 -17
  45. package/dist/{openclaw-skills-76ZWXHFM.js → openclaw-skills-5XLQFRWT.js} +7 -6
  46. package/dist/{peers-F2EWUMVQ.js → peers-7BMU2775.js} +1 -0
  47. package/dist/{peers-CJ7T4RJO.js → peers-IOVCBWAI.js} +1 -0
  48. package/dist/{process-guard-QDBIOLY4.js → process-guard-6324CZDC.js} +1 -0
  49. package/dist/provider-events-GTTJPYHS.js +13 -0
  50. package/dist/{publish-capability-FOCHYNYE.js → publish-capability-LM4RSQXX.js} +5 -2
  51. package/dist/{reliability-metrics-JSOY3PNW.js → reliability-metrics-22JTZGB4.js} +1 -0
  52. package/dist/{reliability-metrics-KKUFFVB6.js → reliability-metrics-MIJ3TJWL.js} +1 -0
  53. package/dist/{request-KPKWBL5W.js → request-LID2N42Y.js} +17 -13
  54. package/dist/request-log-2D253WML.js +17 -0
  55. package/dist/request-log-SIGTGOFA.js +16 -0
  56. package/dist/{scanner-GP4AOCW6.js → scanner-EFU6NBEJ.js} +1 -0
  57. package/dist/{schema-7BSSLZ4S.js → schema-FABVZKSI.js} +1 -0
  58. package/dist/{serve-skill-QSUIK3ZF.js → serve-skill-CDNSHTEE.js} +17 -13
  59. package/dist/{server-OCCAVVDF.js → server-QIAO3YSK.js} +23 -15
  60. package/dist/{service-coordinator-4JAUUNUL.js → service-coordinator-FB44QL7L.js} +721 -69
  61. package/dist/session-5AIRM7YF.js +144 -0
  62. package/dist/session-action-GYITLYOE.js +131 -0
  63. package/dist/{skill-config-5O2VR546.js → skill-config-VYNF7BCY.js} +1 -0
  64. package/dist/{skill-wrap-YLCJMFEJ.js → skill-wrap-IAZHOYM4.js} +1 -0
  65. package/dist/skills/agentbnb/bootstrap.js +750 -98
  66. package/dist/{store-S22F3I7G.js → store-C4DLIXYM.js} +4 -1
  67. package/dist/{vc-action-SUD7TMN2.js → vc-action-BWGNQ77Y.js} +2 -1
  68. package/dist/websocket-client-FCPZOE4S.js +9 -0
  69. package/dist/websocket-client-RT4KLJL4.js +8 -0
  70. package/dist/{writer-4QJ3U3WE.js → writer-V7JBWKKZ.js} +1 -0
  71. package/package.json +3 -1
  72. package/dist/chunk-3466S65P.js +0 -179
  73. package/dist/conduct-UAEEMVFD.js +0 -26
  74. package/dist/websocket-client-5CRE36Z5.js +0 -7
  75. package/dist/websocket-client-WHEHIYIZ.js +0 -6
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # AgentBnB
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/agentbnb.svg)](https://www.npmjs.com/package/agentbnb)
4
- [![Tests](https://img.shields.io/badge/tests-1%2C700%2B%20passing-brightgreen.svg)](https://github.com/Xiaoher-C/agentbnb)
4
+ [![Tests](https://img.shields.io/badge/tests-1%2C800%2B%20passing-brightgreen.svg)](https://github.com/Xiaoher-C/agentbnb)
5
5
  [![Node.js](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](https://nodejs.org/)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
7
  [![Relay](https://img.shields.io/badge/relay-agentbnb.fly.dev-blue.svg)](https://agentbnb.fly.dev)
@@ -13,7 +13,7 @@
13
13
  <h3 align="center"><strong>Your AI agent doesn't need to do everything itself. It can hire another AI agent.</strong></h3>
14
14
  <p align="center">Agents discover, hire, form teams, and settle payment — with cryptographic identity, relay-enforced escrow, and portable reputation.</p>
15
15
 
16
- <p align="center"><code>v9.0 · 1,700+ tests · DID + UCAN + Verifiable Credentials · relay-only settlement · 5% network fee · MIT</code></p>
16
+ <p align="center"><code>v9.1 · 1,800+ tests · DID + UCAN + VCs · Sessions · Provider Dashboard · relay-only settlement · 5% network fee · MIT</code></p>
17
17
 
18
18
  ---
19
19
 
@@ -257,7 +257,7 @@ The agent is the user, not the human. Agents hold their own Ed25519 keypairs, ea
257
257
  | **Hub** | Discover agents and capabilities across the network |
258
258
  | **Team Formation** | Decompose tasks, match providers, form execution teams |
259
259
  | **Conductor** | Orchestrate multi-agent DAG workflows with dependency resolution |
260
- | **Execution** | 5 modes: API, Command, Proxy, MCP, OpenClaw plugin |
260
+ | **Execution** | 5 skill modes (API, Command, Pipeline, OpenClaw, Conductor) + interactive Sessions |
261
261
  | **Routing** | Multi-factor scoring (trust × cost × availability) |
262
262
  | **Reputation** | Feedback-driven trust with failure classification (overload ≠ bad work) |
263
263
  | **Escrow** | Ed25519 signed, relay-enforced credit settlement |
@@ -267,6 +267,31 @@ The agent is the user, not the human. Agents hold their own Ed25519 keypairs, ea
267
267
  | **Identity** | W3C DID (did:key + did:agentbnb) · UCAN scoped delegation · Verifiable Credentials · Key rotation · EVM bridge |
268
268
  | **Framework Adapters** | LangChain, CrewAI, AutoGen |
269
269
 
270
+ ### New in v9.1
271
+
272
+ | Feature | What It Does |
273
+ |---------|-------------|
274
+ | **Agent-to-Agent Sessions** | Interactive turn-based conversations between agents. Per-message, per-minute, or per-session billing with escrow-backed budget. `agentbnb session open` / `send` / `end`. |
275
+ | **Provider Dashboard** | Real-time web UI at `/#/dashboard` — see earnings, active sessions, skill performance, and event feed. Polling-based, no setup needed. |
276
+ | **Provider Event Stream** | Unified `provider_events` SQLite table with 7 dot-notation event types. Powers both Telegram notifications and the Dashboard. |
277
+ | **Provider Gate** | Control who can rent your skills: `provider-accepting` (on/off), `provider-blacklist`, `provider-whitelist`, `provider-daily-limit`. Natural-language control via OpenClaw Telegram bot. |
278
+ | **Telegram Notifications** | Real-time alerts when skills are rented: incoming request, execution result, session lifecycle. Configurable `notification-filters` to suppress noisy events. |
279
+ | **OpenClaw Provider Bridge** | OpenClaw agents can now serve as AgentBnB providers. `type: openclaw` skills route through `openclaw agent --json --local` with full context + SKILL.md instructions. |
280
+ | **Core Config Loader** | Algorithm parameters (reputation weights, network fees, rate limits) load from `@agentbnb/core` if installed, with built-in defaults for open-source users. |
281
+
282
+ ### Provider Gate (new)
283
+
284
+ Protect your API keys from unauthorized rental usage:
285
+
286
+ ```bash
287
+ agentbnb config set provider-gate notify # Telegram alert before execution
288
+ agentbnb config set provider-daily-limit 20 # Max 20 executions per day
289
+ agentbnb config set provider-blacklist agent-xxx # Block specific agents
290
+ agentbnb config set provider-accepting false # Stop accepting all requests
291
+ ```
292
+
293
+ Whitelisted agents bypass all gates: `agentbnb config set provider-whitelist agent-trusted`
294
+
270
295
  ---
271
296
 
272
297
  ## Credit System
@@ -397,7 +422,7 @@ Read the full spec: [ADR-020: UCAN Token Specification](./docs/adr/020-ucan-toke
397
422
 
398
423
  ```bash
399
424
  pnpm install # Install dependencies
400
- pnpm test:run # Run all tests (1,700+ tests)
425
+ pnpm test:run # Run all tests (1,800+ tests)
401
426
  pnpm typecheck # Type check
402
427
  pnpm build:all # Build everything
403
428
  ```
@@ -1,10 +1,13 @@
1
1
  import {
2
2
  attachCanonicalAgentId
3
- } from "./chunk-PG3CLSAH.js";
3
+ } from "./chunk-BPPFY72X.js";
4
+ import "./chunk-4XTYT4JW.js";
5
+ import "./chunk-GZUTU6IZ.js";
4
6
  import "./chunk-EE3V3DXK.js";
5
7
  import {
6
8
  CapabilityCardV2Schema
7
9
  } from "./chunk-UVCNMRPS.js";
10
+ import "./chunk-3RG5ZIWI.js";
8
11
 
9
12
  // src/conductor/card.ts
10
13
  import { createHash } from "crypto";
@@ -1,10 +1,13 @@
1
1
  import {
2
2
  attachCanonicalAgentId
3
- } from "./chunk-NLQCHO7N.js";
3
+ } from "./chunk-7VZ4M4CT.js";
4
4
  import "./chunk-J4RFJVXI.js";
5
5
  import {
6
6
  CapabilityCardV2Schema
7
7
  } from "./chunk-UVCNMRPS.js";
8
+ import "./chunk-4XTYT4JW.js";
9
+ import "./chunk-GZUTU6IZ.js";
10
+ import "./chunk-3RG5ZIWI.js";
8
11
 
9
12
  // src/conductor/card.ts
10
13
  import { createHash } from "crypto";
@@ -8,10 +8,23 @@ import {
8
8
  releaseEscrow,
9
9
  resolveTargetCapability,
10
10
  settleEscrow
11
- } from "./chunk-BNS76U6K.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,
@@ -19,21 +32,13 @@ import {
19
32
  signEscrowReceipt,
20
33
  verifyEscrowReceipt
21
34
  } from "./chunk-YNBZLXYS.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
- insertRequestLog,
29
- updateReputation
30
- } from "./chunk-PG3CLSAH.js";
31
- import {
32
- lookupAgent
33
- } from "./chunk-EE3V3DXK.js";
34
- import {
35
- AgentBnBError
36
- } from "./chunk-UVCNMRPS.js";
37
42
 
38
43
  // src/gateway/execute.ts
39
44
  import { randomUUID } from "crypto";
@@ -652,52 +657,133 @@ async function syncCreditsFromRegistry(config, localDb) {
652
657
  }
653
658
  }
654
659
 
655
- // src/gateway/execute.ts
656
- async function notifyTelegramSkillExecuted(opts) {
657
- const cfg = loadConfig();
658
- if (!cfg?.telegram_notifications) return;
659
- const token = cfg.telegram_bot_token ?? process.env["TELEGRAM_BOT_TOKEN"];
660
- const chatId = cfg.telegram_chat_id ?? process.env["TELEGRAM_CHAT_ID"];
661
- if (!token || !chatId) return;
662
- const balance = getBalance(opts.creditDb, opts.owner);
663
- const skillLabel = opts.skillId ? `${opts.skillName} (${opts.skillId})` : opts.skillName;
664
- const text = [
665
- "[AgentBnB] Skill executed",
666
- `Skill: ${skillLabel}`,
667
- `Requester: ${opts.requester}`,
668
- `Earned: +${opts.creditsEarned} credits`,
669
- `Balance: ${balance} credits`,
670
- `Latency: ${opts.latencyMs}ms`
671
- ].join("\n");
672
- await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
673
- method: "POST",
674
- headers: { "Content-Type": "application/json" },
675
- body: JSON.stringify({ chat_id: chatId, text })
676
- });
660
+ // src/gateway/provider-notifier.ts
661
+ var EVENT_EMOJI = {
662
+ "skill.received": "\u{1F4E5}",
663
+ "skill.executed": "\u2705",
664
+ "skill.failed": "\u274C",
665
+ "skill.rejected": "\u{1F6AB}",
666
+ "session.opened": "\u{1F517}",
667
+ "session.message": "\u{1F4AC}",
668
+ "session.ended": "\u{1F3C1}",
669
+ "session.failed": "\u{1F4A5}"
670
+ };
671
+ function formatEventMessage(event, balance) {
672
+ const emoji = EVENT_EMOJI[event.event_type] ?? "\u{1F4CB}";
673
+ const meta = event.metadata ?? {};
674
+ const skillLabel = event.skill_id ?? "unknown";
675
+ switch (event.event_type) {
676
+ case "skill.received":
677
+ return [
678
+ `${emoji} [AgentBnB] Incoming request`,
679
+ `Skill: ${skillLabel}`,
680
+ `Requester: ${event.requester}`,
681
+ `Cost: ${event.credits} credits`,
682
+ `Status: Executing...`
683
+ ].join("\n");
684
+ case "skill.executed":
685
+ return [
686
+ `${emoji} [AgentBnB] Skill executed`,
687
+ `Skill: ${skillLabel}`,
688
+ `Requester: ${event.requester}`,
689
+ `Earned: +${event.credits} credits`,
690
+ ...balance !== void 0 ? [`Balance: ${balance} credits`] : [],
691
+ `Latency: ${event.duration_ms}ms`
692
+ ].join("\n");
693
+ case "skill.failed":
694
+ return [
695
+ `${emoji} [AgentBnB] Skill failed`,
696
+ `Skill: ${skillLabel}`,
697
+ `Requester: ${event.requester}`,
698
+ `Reason: ${meta["failure_reason"] ?? "unknown"}`,
699
+ ...meta["error"] ? [`Error: ${String(meta["error"]).slice(0, 200)}`] : [],
700
+ ...balance !== void 0 ? [`Balance: ${balance} credits`] : [],
701
+ `Latency: ${event.duration_ms}ms`
702
+ ].join("\n");
703
+ case "skill.rejected":
704
+ return [
705
+ `${emoji} [AgentBnB] Request rejected`,
706
+ `Skill: ${skillLabel}`,
707
+ `Requester: ${event.requester}`,
708
+ `Reason: ${meta["reason"] ?? "unknown"}`
709
+ ].join("\n");
710
+ case "session.opened":
711
+ return [
712
+ `${emoji} [AgentBnB] Session opened`,
713
+ `Session: ${event.session_id?.slice(0, 8)}...`,
714
+ `Requester: ${event.requester}`,
715
+ `Skill: ${skillLabel}`,
716
+ `Pricing: ${meta["pricing_model"] ?? "unknown"}`,
717
+ `Budget: ${event.credits} credits`
718
+ ].join("\n");
719
+ case "session.message": {
720
+ const msgCount = meta["message_count"] ?? "?";
721
+ const runningCost = meta["running_cost"] ?? event.credits;
722
+ return [
723
+ `${emoji} [AgentBnB] Session message #${msgCount}`,
724
+ `Session: ${event.session_id?.slice(0, 8)}...`,
725
+ `Running cost: ${runningCost} credits`
726
+ ].join("\n");
727
+ }
728
+ case "session.ended": {
729
+ const totalMsgs = meta["total_messages"] ?? "?";
730
+ const durationMin = Math.round(event.duration_ms / 6e4);
731
+ const refunded = Number(meta["refunded"] ?? 0);
732
+ return [
733
+ `${emoji} [AgentBnB] Session ended`,
734
+ `Session: ${event.session_id?.slice(0, 8)}...`,
735
+ `Total: ${totalMsgs} messages, ${event.credits} credits`,
736
+ `Duration: ${durationMin} minutes`,
737
+ ...refunded > 0 ? [`Refunded: ${refunded} credits`] : []
738
+ ].join("\n");
739
+ }
740
+ case "session.failed": {
741
+ const lastMsgs = Array.isArray(meta["last_messages"]) ? meta["last_messages"] : [];
742
+ const lines = [
743
+ `${emoji} [AgentBnB] Session failed`,
744
+ `Session: ${event.session_id?.slice(0, 8)}...`,
745
+ `Reason: ${meta["reason"] ?? "error"}`,
746
+ `Cost: ${event.credits} credits`
747
+ ];
748
+ if (lastMsgs.length > 0) {
749
+ lines.push("", "Last messages:");
750
+ for (const m of lastMsgs) {
751
+ lines.push(` ${m.sender}: ${m.content.slice(0, 100)}`);
752
+ }
753
+ }
754
+ return lines.join("\n");
755
+ }
756
+ default:
757
+ return `${emoji} [AgentBnB] ${event.event_type}: ${skillLabel}`;
758
+ }
677
759
  }
678
- async function notifyTelegramSkillFailed(opts) {
760
+ async function notifyProviderEvent(event, creditDb, owner) {
679
761
  const cfg = loadConfig();
680
- if (!cfg?.telegram_notifications) return;
762
+ if (!cfg) return;
763
+ const telegramEnabled = cfg.telegram_notifications === true;
764
+ const gateNotify = cfg.provider_gate === "notify";
765
+ if (!telegramEnabled && !gateNotify) return;
766
+ const filters = cfg.notification_filters ?? ["session.message"];
767
+ if (filters.includes(event.event_type)) return;
681
768
  const token = cfg.telegram_bot_token ?? process.env["TELEGRAM_BOT_TOKEN"];
682
769
  const chatId = cfg.telegram_chat_id ?? process.env["TELEGRAM_CHAT_ID"];
683
770
  if (!token || !chatId) return;
684
- const balance = getBalance(opts.creditDb, opts.owner);
685
- const skillLabel = opts.skillId ? `${opts.skillName} (${opts.skillId})` : opts.skillName;
686
- const text = [
687
- "[AgentBnB] Skill failed",
688
- `Skill: ${skillLabel}`,
689
- `Requester: ${opts.requester}`,
690
- `Reason: ${opts.failureReason}`,
691
- `Error: ${opts.message}`,
692
- `Balance: ${balance} credits`,
693
- `Latency: ${opts.latencyMs}ms`
694
- ].join("\n");
771
+ let balance;
772
+ if (creditDb && owner && (event.event_type === "skill.executed" || event.event_type === "skill.failed")) {
773
+ try {
774
+ balance = getBalance(creditDb, owner);
775
+ } catch {
776
+ }
777
+ }
778
+ const text = formatEventMessage(event, balance);
695
779
  await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
696
780
  method: "POST",
697
781
  headers: { "Content-Type": "application/json" },
698
782
  body: JSON.stringify({ chat_id: chatId, text })
699
783
  });
700
784
  }
785
+
786
+ // src/gateway/execute.ts
701
787
  async function executeCapabilityRequest(opts) {
702
788
  const {
703
789
  registryDb,
@@ -789,6 +875,49 @@ async function executeCapabilityRequest(opts) {
789
875
  return { success: false, error: { code: -32603, message: msg } };
790
876
  }
791
877
  }
878
+ const providerCfg = loadConfig();
879
+ const providerWhitelist = providerCfg?.provider_whitelist ?? [];
880
+ const isWhitelisted = providerWhitelist.includes(requester);
881
+ if (providerCfg?.provider_accepting === false && !isWhitelisted) {
882
+ if (escrowId) releaseEscrow(creditDb, escrowId);
883
+ return { success: false, error: { code: -32098, message: "Provider is not accepting requests" } };
884
+ }
885
+ if (!isWhitelisted) {
886
+ const blacklist = providerCfg?.provider_blacklist ?? [];
887
+ if (blacklist.includes(requester)) {
888
+ if (escrowId) releaseEscrow(creditDb, escrowId);
889
+ try {
890
+ emitProviderEvent(registryDb, { event_type: "skill.rejected", skill_id: resolvedSkillId ?? null, session_id: null, requester, credits: 0, duration_ms: 0, metadata: { reason: "blacklisted" } });
891
+ } catch {
892
+ }
893
+ return { success: false, error: { code: -32097, message: "Requester is blocked by provider" } };
894
+ }
895
+ }
896
+ if (!isWhitelisted) {
897
+ const dailyLimit = providerCfg?.provider_daily_limit ?? 0;
898
+ if (dailyLimit > 0) {
899
+ const { countTodayExecutions } = await import("./request-log-2D253WML.js");
900
+ const todayCount = countTodayExecutions(registryDb);
901
+ if (todayCount >= dailyLimit) {
902
+ if (escrowId) releaseEscrow(creditDb, escrowId);
903
+ try {
904
+ 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 } });
905
+ } catch {
906
+ }
907
+ return {
908
+ success: false,
909
+ error: { code: -32099, message: `Provider daily execution limit reached (${dailyLimit}/day)` }
910
+ };
911
+ }
912
+ }
913
+ }
914
+ 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" } };
915
+ try {
916
+ const emitted = emitProviderEvent(registryDb, receivedEvent);
917
+ notifyProviderEvent(emitted, creditDb, card.owner).catch(() => {
918
+ });
919
+ } catch {
920
+ }
792
921
  const startMs = Date.now();
793
922
  const handleFailure = (status, latencyMs, message, failureReason = "bad_execution") => {
794
923
  if (escrowId) releaseEscrow(creditDb, escrowId);
@@ -810,17 +939,12 @@ async function executeCapabilityRequest(opts) {
810
939
  });
811
940
  } catch {
812
941
  }
813
- notifyTelegramSkillFailed({
814
- creditDb,
815
- owner: card.owner,
816
- skillName: cardName,
817
- skillId: resolvedSkillId ?? null,
818
- requester,
819
- latencyMs,
820
- failureReason,
821
- message
822
- }).catch(() => {
823
- });
942
+ try {
943
+ 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 } });
944
+ notifyProviderEvent(emitted, creditDb, card.owner).catch(() => {
945
+ });
946
+ } catch {
947
+ }
824
948
  return { success: false, error: { code: -32603, message } };
825
949
  };
826
950
  const handleSuccess = (result, latencyMs) => {
@@ -842,16 +966,12 @@ async function executeCapabilityRequest(opts) {
842
966
  });
843
967
  } catch {
844
968
  }
845
- notifyTelegramSkillExecuted({
846
- creditDb,
847
- owner: card.owner,
848
- skillName: cardName,
849
- skillId: resolvedSkillId ?? null,
850
- requester,
851
- creditsEarned: creditsNeeded,
852
- latencyMs
853
- }).catch(() => {
854
- });
969
+ try {
970
+ const emitted = emitProviderEvent(registryDb, { event_type: "skill.executed", skill_id: resolvedSkillId ?? null, session_id: null, requester, credits: creditsNeeded, duration_ms: latencyMs, metadata: null });
971
+ notifyProviderEvent(emitted, creditDb, card.owner).catch(() => {
972
+ });
973
+ } catch {
974
+ }
855
975
  return { success: true, result };
856
976
  };
857
977
  if (skillExecutor) {
@@ -1090,6 +1210,7 @@ export {
1090
1210
  identityAuthPlugin,
1091
1211
  createLedger,
1092
1212
  syncCreditsFromRegistry,
1213
+ notifyProviderEvent,
1093
1214
  executeCapabilityRequest,
1094
1215
  executeCapabilityBatch
1095
1216
  };
@@ -0,0 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ export {
9
+ __require
10
+ };
@@ -0,0 +1,155 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/registry/request-log.ts
9
+ var SINCE_MS = {
10
+ "24h": 864e5,
11
+ "7d": 6048e5,
12
+ "30d": 2592e6
13
+ };
14
+ function createRequestLogTable(db) {
15
+ db.exec(`
16
+ CREATE TABLE IF NOT EXISTS request_log (
17
+ id TEXT PRIMARY KEY,
18
+ card_id TEXT NOT NULL,
19
+ card_name TEXT NOT NULL,
20
+ requester TEXT NOT NULL,
21
+ status TEXT NOT NULL CHECK(status IN ('success', 'failure', 'timeout')),
22
+ latency_ms INTEGER NOT NULL,
23
+ credits_charged INTEGER NOT NULL,
24
+ created_at TEXT NOT NULL
25
+ );
26
+
27
+ CREATE INDEX IF NOT EXISTS request_log_created_at_idx
28
+ ON request_log (created_at DESC);
29
+ `);
30
+ try {
31
+ db.exec("ALTER TABLE request_log ADD COLUMN skill_id TEXT");
32
+ } catch {
33
+ }
34
+ try {
35
+ db.exec("ALTER TABLE request_log ADD COLUMN action_type TEXT");
36
+ } catch {
37
+ }
38
+ try {
39
+ db.exec("ALTER TABLE request_log ADD COLUMN tier_invoked INTEGER");
40
+ } catch {
41
+ }
42
+ try {
43
+ db.exec("ALTER TABLE request_log ADD COLUMN failure_reason TEXT");
44
+ } catch {
45
+ }
46
+ try {
47
+ db.exec("ALTER TABLE request_log ADD COLUMN team_id TEXT");
48
+ } catch {
49
+ }
50
+ try {
51
+ db.exec("ALTER TABLE request_log ADD COLUMN role TEXT");
52
+ } catch {
53
+ }
54
+ try {
55
+ db.exec("ALTER TABLE request_log ADD COLUMN capability_type TEXT");
56
+ } catch {
57
+ }
58
+ }
59
+ function insertRequestLog(db, entry) {
60
+ const stmt = db.prepare(`
61
+ INSERT INTO request_log (id, card_id, card_name, requester, status, latency_ms, credits_charged, created_at, skill_id, action_type, tier_invoked, failure_reason, team_id, role, capability_type)
62
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
63
+ `);
64
+ stmt.run(
65
+ entry.id,
66
+ entry.card_id,
67
+ entry.card_name,
68
+ entry.requester,
69
+ entry.status,
70
+ entry.latency_ms,
71
+ entry.credits_charged,
72
+ entry.created_at,
73
+ entry.skill_id ?? null,
74
+ entry.action_type ?? null,
75
+ entry.tier_invoked ?? null,
76
+ entry.failure_reason ?? null,
77
+ entry.team_id ?? null,
78
+ entry.role ?? null,
79
+ entry.capability_type ?? null
80
+ );
81
+ }
82
+ function getSkillRequestCount(db, skillId, windowMs) {
83
+ const cutoff = new Date(Date.now() - windowMs).toISOString();
84
+ const stmt = db.prepare(
85
+ `SELECT COUNT(*) as cnt FROM request_log
86
+ WHERE skill_id = ? AND created_at >= ? AND status = 'success' AND action_type IS NULL`
87
+ );
88
+ const row = stmt.get(skillId, cutoff);
89
+ return row.cnt;
90
+ }
91
+ function getActivityFeed(db, limit = 20, since) {
92
+ const effectiveLimit = Math.min(limit, 100);
93
+ if (since !== void 0) {
94
+ const stmt2 = db.prepare(`
95
+ SELECT r.id, r.card_name, r.requester, c.owner AS provider,
96
+ r.status, r.credits_charged, r.latency_ms, r.created_at, r.action_type
97
+ FROM request_log r
98
+ LEFT JOIN capability_cards c ON r.card_id = c.id
99
+ WHERE (r.action_type IS NULL OR r.action_type IN ('auto_share', 'agent_joined'))
100
+ AND r.created_at > ?
101
+ ORDER BY r.created_at DESC
102
+ LIMIT ?
103
+ `);
104
+ return stmt2.all(since, effectiveLimit);
105
+ }
106
+ const stmt = db.prepare(`
107
+ SELECT r.id, r.card_name, r.requester, c.owner AS provider,
108
+ r.status, r.credits_charged, r.latency_ms, r.created_at, r.action_type
109
+ FROM request_log r
110
+ LEFT JOIN capability_cards c ON r.card_id = c.id
111
+ WHERE (r.action_type IS NULL OR r.action_type IN ('auto_share', 'agent_joined'))
112
+ ORDER BY r.created_at DESC
113
+ LIMIT ?
114
+ `);
115
+ return stmt.all(effectiveLimit);
116
+ }
117
+ function countTodayExecutions(db) {
118
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
119
+ const stmt = db.prepare(
120
+ `SELECT COUNT(*) as cnt FROM request_log
121
+ WHERE created_at >= ? AND action_type IS NULL`
122
+ );
123
+ const row = stmt.get(today + "T00:00:00.000Z");
124
+ return row.cnt;
125
+ }
126
+ function getRequestLog(db, limit = 10, since) {
127
+ if (since !== void 0) {
128
+ const cutoff = new Date(Date.now() - SINCE_MS[since]).toISOString();
129
+ const stmt2 = db.prepare(`
130
+ SELECT id, card_id, card_name, requester, status, latency_ms, credits_charged, created_at, skill_id, action_type, tier_invoked, failure_reason, team_id, role, capability_type
131
+ FROM request_log
132
+ WHERE created_at >= ?
133
+ ORDER BY created_at DESC
134
+ LIMIT ?
135
+ `);
136
+ return stmt2.all(cutoff, limit);
137
+ }
138
+ const stmt = db.prepare(`
139
+ SELECT id, card_id, card_name, requester, status, latency_ms, credits_charged, created_at, skill_id, action_type, tier_invoked, failure_reason, team_id, role
140
+ FROM request_log
141
+ ORDER BY created_at DESC
142
+ LIMIT ?
143
+ `);
144
+ return stmt.all(limit);
145
+ }
146
+
147
+ export {
148
+ __require,
149
+ createRequestLogTable,
150
+ insertRequestLog,
151
+ getSkillRequestCount,
152
+ getActivityFeed,
153
+ countTodayExecutions,
154
+ getRequestLog
155
+ };