agentbnb 8.4.4 → 8.4.7

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.
@@ -11,13 +11,13 @@ import {
11
11
  import {
12
12
  performInit,
13
13
  publishFromSoulV2
14
- } from "./chunk-PCQEHIGF.js";
14
+ } from "./chunk-UNXCKETK.js";
15
15
  import "./chunk-AZKVGC5T.js";
16
16
  import {
17
17
  getPricingStats
18
18
  } from "./chunk-CFHCG5FE.js";
19
- import "./chunk-WK2QSO4E.js";
20
19
  import "./chunk-G5WKW3ED.js";
20
+ import "./chunk-WK2QSO4E.js";
21
21
  import "./chunk-HU46M4JA.js";
22
22
  import "./chunk-GIEJVKZZ.js";
23
23
  import "./chunk-U6LP4KWN.js";
@@ -1,6 +1,8 @@
1
1
  import {
2
2
  executeCapabilityRequest
3
- } from "./chunk-6FZ4WYQL.js";
3
+ } from "./chunk-JDAFLPR7.js";
4
+ import "./chunk-RF4A5X5U.js";
5
+ import "./chunk-WK2QSO4E.js";
4
6
  import "./chunk-2PP5MQPD.js";
5
7
  import "./chunk-PIPCGRCR.js";
6
8
  import {
@@ -10,6 +12,7 @@ import {
10
12
  RelayClient
11
13
  } from "./chunk-NX27AFPA.js";
12
14
  import "./chunk-PQIP7EXY.js";
15
+ import "./chunk-GIEJVKZZ.js";
13
16
  import "./chunk-U6LP4KWN.js";
14
17
  import "./chunk-3XPBFF6H.js";
15
18
  import {
@@ -107,10 +107,22 @@ import { z as z2 } from "zod";
107
107
  var statusInputSchema = {
108
108
  _unused: z2.string().optional().describe("No parameters needed")
109
109
  };
110
+ function readLocalBalance(creditDbPath, creditKey) {
111
+ const creditDb = openCreditDb(creditDbPath);
112
+ try {
113
+ return getBalance(creditDb, creditKey);
114
+ } catch {
115
+ return 0;
116
+ } finally {
117
+ creditDb.close();
118
+ }
119
+ }
110
120
  async function handleStatus(ctx) {
111
121
  try {
112
- let balance = 0;
113
122
  const creditKey = ctx.identity.agent_id ?? ctx.identity.owner;
123
+ const local_balance = readLocalBalance(ctx.config.credit_db_path, creditKey);
124
+ let registry_balance = null;
125
+ let sync_needed = false;
114
126
  if (ctx.config.registry) {
115
127
  try {
116
128
  const keys = loadKeyPair(ctx.configDir);
@@ -119,28 +131,19 @@ async function handleStatus(ctx) {
119
131
  ownerPublicKey: ctx.identity.public_key,
120
132
  privateKey: keys.privateKey
121
133
  });
122
- balance = await ledger.getBalance(creditKey);
134
+ registry_balance = await ledger.getBalance(creditKey);
135
+ sync_needed = Math.abs(registry_balance - local_balance) > 1;
123
136
  } catch {
124
- const creditDb = openCreditDb(ctx.config.credit_db_path);
125
- try {
126
- balance = getBalance(creditDb, creditKey);
127
- } finally {
128
- creditDb.close();
129
- }
130
- }
131
- } else {
132
- const creditDb = openCreditDb(ctx.config.credit_db_path);
133
- try {
134
- balance = getBalance(creditDb, creditKey);
135
- } finally {
136
- creditDb.close();
137
137
  }
138
138
  }
139
+ const balance = registry_balance ?? local_balance;
139
140
  const result = {
140
141
  agent_id: ctx.identity.agent_id,
141
142
  owner: ctx.identity.owner,
142
143
  public_key: ctx.identity.public_key,
143
144
  balance,
145
+ local_balance,
146
+ ...ctx.config.registry ? { registry_balance, sync_needed } : {},
144
147
  registry_url: ctx.config.registry ?? null,
145
148
  config_dir: ctx.configDir
146
149
  };
@@ -251,7 +254,7 @@ function registerPublishTool(server, ctx) {
251
254
  }
252
255
 
253
256
  // src/mcp/server.ts
254
- var VERSION = true ? "8.4.4" : "0.0.0-dev";
257
+ var VERSION = true ? "8.4.7" : "0.0.0-dev";
255
258
  async function startMcpServer() {
256
259
  const config = loadConfig();
257
260
  if (!config) {
@@ -274,7 +277,7 @@ async function startMcpServer() {
274
277
  registerPublishTool(server, ctx);
275
278
  const { registerRequestTool } = await import("./request-XWEOIVB3.js");
276
279
  const { registerConductTool } = await import("./conduct-TE4YAXKR.js");
277
- const { registerServeSkillTool } = await import("./serve-skill-6RKMVDMK.js");
280
+ const { registerServeSkillTool } = await import("./serve-skill-UD7TLSRN.js");
278
281
  registerRequestTool(server, ctx);
279
282
  registerConductTool(server, ctx);
280
283
  registerServeSkillTool(server, ctx);
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  executeCapabilityBatch,
10
10
  executeCapabilityRequest
11
- } from "./chunk-6FZ4WYQL.js";
11
+ } from "./chunk-JDAFLPR7.js";
12
12
  import {
13
13
  StructuredFeedbackSchema
14
14
  } from "./chunk-AUBHR7HH.js";
@@ -23,11 +23,6 @@ import {
23
23
  detectApiKeys,
24
24
  getPricingStats
25
25
  } from "./chunk-CFHCG5FE.js";
26
- import {
27
- createLedger,
28
- deriveAgentId,
29
- identityAuthPlugin
30
- } from "./chunk-WK2QSO4E.js";
31
26
  import {
32
27
  listPendingRequests,
33
28
  resolvePendingRequest
@@ -37,6 +32,14 @@ import {
37
32
  getAutonomyTier,
38
33
  insertAuditEvent
39
34
  } from "./chunk-G5WKW3ED.js";
35
+ import {
36
+ syncCreditsFromRegistry
37
+ } from "./chunk-RF4A5X5U.js";
38
+ import {
39
+ createLedger,
40
+ deriveAgentId,
41
+ identityAuthPlugin
42
+ } from "./chunk-WK2QSO4E.js";
40
43
  import "./chunk-2PP5MQPD.js";
41
44
  import "./chunk-PIPCGRCR.js";
42
45
  import {
@@ -705,27 +708,37 @@ var KILL_GRACE_MS = 5e3;
705
708
  function shellEscape2(value) {
706
709
  return "'" + value.replace(/'/g, "'\\''") + "'";
707
710
  }
708
- function safeInterpolateCommand2(template, context) {
709
- return template.replace(/\$\{([^}]+)\}/g, (_match, expr) => {
710
- const parts = expr.split(".");
711
- let current = context;
712
- for (const part of parts) {
713
- if (current === null || typeof current !== "object") return "";
714
- const bracketMatch = part.match(/^(\w+)\[(\d+)\]$/);
715
- if (bracketMatch) {
716
- current = current[bracketMatch[1]];
717
- if (Array.isArray(current)) {
718
- current = current[parseInt(bracketMatch[2], 10)];
719
- } else {
720
- return "";
721
- }
711
+ function resolveExpression(expr, context) {
712
+ const parts = expr.split(".");
713
+ let current = context;
714
+ for (const part of parts) {
715
+ if (current === null || typeof current !== "object") return void 0;
716
+ const bracketMatch = part.match(/^(\w+)\[(\d+)\]$/);
717
+ if (bracketMatch) {
718
+ current = current[bracketMatch[1]];
719
+ if (Array.isArray(current)) {
720
+ current = current[parseInt(bracketMatch[2], 10)];
722
721
  } else {
723
- current = current[part];
722
+ return void 0;
724
723
  }
724
+ } else {
725
+ current = current[part];
725
726
  }
726
- if (current === void 0 || current === null) return "";
727
- return shellEscape2(String(current));
728
- });
727
+ }
728
+ return current;
729
+ }
730
+ function safeInterpolateCommand2(template, context) {
731
+ const result = template.replace(
732
+ /(--[\w-]+\s+)?\$\{([^}]+)\}/g,
733
+ (_match, flagPrefix, expr) => {
734
+ const value = resolveExpression(expr, context);
735
+ if (value === void 0 || value === null) {
736
+ return "";
737
+ }
738
+ return (flagPrefix ?? "") + shellEscape2(String(value));
739
+ }
740
+ );
741
+ return result.replace(/ +/g, " ").trim();
729
742
  }
730
743
  function spawnWithKill(command, options, registry) {
731
744
  return new Promise((resolve, reject) => {
@@ -2655,6 +2668,75 @@ async function creditRoutesPlugin(fastify, options) {
2655
2668
  } catch {
2656
2669
  }
2657
2670
  initFreeTierTable(creditDb);
2671
+ if (!process.env.ADMIN_TOKEN) {
2672
+ console.warn("[agentbnb] ADMIN_TOKEN not set \u2014 POST /api/credits/grant will return 401 for admin override grants");
2673
+ }
2674
+ fastify.get("/api/credits/balance", {
2675
+ schema: {
2676
+ tags: ["credits"],
2677
+ summary: "Get credit balance by owner query param (public, no auth required)",
2678
+ querystring: {
2679
+ type: "object",
2680
+ properties: { owner: { type: "string", description: "Agent owner name" } },
2681
+ required: ["owner"]
2682
+ },
2683
+ response: {
2684
+ 200: {
2685
+ type: "object",
2686
+ properties: {
2687
+ owner: { type: "string" },
2688
+ balance: { type: "number" }
2689
+ }
2690
+ },
2691
+ 400: { type: "object", properties: { error: { type: "string" } } }
2692
+ }
2693
+ }
2694
+ }, async (request, reply) => {
2695
+ const query = request.query;
2696
+ const owner = typeof query.owner === "string" ? query.owner.trim() : "";
2697
+ if (!owner) {
2698
+ return reply.code(400).send({ error: "owner query param required" });
2699
+ }
2700
+ const balance = getBalance(creditDb, owner);
2701
+ return reply.send({ owner, balance });
2702
+ });
2703
+ fastify.get("/api/credits/transactions", {
2704
+ schema: {
2705
+ tags: ["credits"],
2706
+ summary: "Get transaction history by query params (public, no auth required)",
2707
+ querystring: {
2708
+ type: "object",
2709
+ properties: {
2710
+ owner: { type: "string", description: "Agent owner name" },
2711
+ since: { type: "string", description: "ISO 8601 timestamp \u2014 only return transactions after this time" },
2712
+ limit: { type: "integer", description: "Max entries (default 50, max 100)" }
2713
+ },
2714
+ required: ["owner"]
2715
+ },
2716
+ response: {
2717
+ 200: {
2718
+ type: "object",
2719
+ properties: {
2720
+ owner: { type: "string" },
2721
+ transactions: { type: "array" },
2722
+ limit: { type: "integer" }
2723
+ }
2724
+ },
2725
+ 400: { type: "object", properties: { error: { type: "string" } } }
2726
+ }
2727
+ }
2728
+ }, async (request, reply) => {
2729
+ const query = request.query;
2730
+ const owner = typeof query.owner === "string" ? query.owner.trim() : "";
2731
+ if (!owner) {
2732
+ return reply.code(400).send({ error: "owner query param required" });
2733
+ }
2734
+ const rawLimit = query.limit !== void 0 ? parseInt(query.limit, 10) : 50;
2735
+ const limit = Math.min(isNaN(rawLimit) || rawLimit < 1 ? 50 : rawLimit, 100);
2736
+ const since = typeof query.since === "string" && query.since.trim() ? query.since.trim() : void 0;
2737
+ const transactions = getTransactions(creditDb, owner, { limit, after: since });
2738
+ return reply.send({ owner, transactions, limit });
2739
+ });
2658
2740
  await fastify.register(async (scope) => {
2659
2741
  identityAuthPlugin(scope, { agentDb: creditDb });
2660
2742
  scope.post("/api/credits/hold", {
@@ -5155,6 +5237,7 @@ import { spawn as spawn2 } from "child_process";
5155
5237
  import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
5156
5238
  import { join as join2 } from "path";
5157
5239
  import { randomUUID as randomUUID7 } from "crypto";
5240
+ import { Cron as Cron2 } from "croner";
5158
5241
  function buildFallbackRelayCard(owner) {
5159
5242
  return {
5160
5243
  id: randomUUID7(),
@@ -5192,6 +5275,7 @@ var ServiceCoordinator = class {
5192
5275
  inProcessStartup = false;
5193
5276
  shutdownPromise = null;
5194
5277
  signalHandlersRegistered = false;
5278
+ creditSyncJob = null;
5195
5279
  constructor(config, guard) {
5196
5280
  this.config = config;
5197
5281
  this.guard = guard;
@@ -5356,6 +5440,22 @@ var ServiceCoordinator = class {
5356
5440
  const idleJob = idleMonitor.start();
5357
5441
  this.runtime.registerJob(idleJob);
5358
5442
  console.log("IdleMonitor started (60s poll interval, 70% idle threshold)");
5443
+ if (this.config.registry) {
5444
+ const startupSync = await syncCreditsFromRegistry(this.config, this.runtime.creditDb);
5445
+ if (startupSync.synced) {
5446
+ console.log(`[agentbnb] credits synced: ${startupSync.remoteBalance} (was ${startupSync.localWas})`);
5447
+ } else {
5448
+ console.warn(`[agentbnb] credit sync skipped: ${startupSync.error}`);
5449
+ }
5450
+ this.creditSyncJob = new Cron2("*/5 * * * *", async () => {
5451
+ const result = await syncCreditsFromRegistry(this.config, this.runtime.creditDb);
5452
+ if (result.synced) {
5453
+ console.log(`[agentbnb] credits synced: ${result.remoteBalance} (was ${result.localWas})`);
5454
+ } else {
5455
+ console.warn(`[agentbnb] credit sync failed: ${result.error}`);
5456
+ }
5457
+ });
5458
+ }
5359
5459
  this.gateway = createGatewayServer({
5360
5460
  port: opts.port,
5361
5461
  registryDb: this.runtime.registryDb,
@@ -5386,7 +5486,7 @@ var ServiceCoordinator = class {
5386
5486
  }
5387
5487
  if (opts.registryUrl && opts.relay) {
5388
5488
  const { RelayClient } = await import("./websocket-client-3U27WJUU.js");
5389
- const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("./execute-UP46R7KS.js");
5489
+ const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("./execute-6EJSVBFB.js");
5390
5490
  const localCards = listCards(this.runtime.registryDb, this.config.owner);
5391
5491
  const { primaryCard, additionalCards } = buildRelayRegistrationCards(this.config.owner, localCards);
5392
5492
  if (this.config.conductor?.public) {
@@ -5445,6 +5545,10 @@ var ServiceCoordinator = class {
5445
5545
  return;
5446
5546
  }
5447
5547
  this.shutdownPromise = (async () => {
5548
+ if (this.creditSyncJob) {
5549
+ this.creditSyncJob.stop();
5550
+ this.creditSyncJob = null;
5551
+ }
5448
5552
  if (this.relayClient) {
5449
5553
  this.relayClient.disconnect();
5450
5554
  this.relayClient = null;