agentbnb 8.2.3 → 8.3.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 (62) hide show
  1. package/dist/{card-EX2EYGCZ.js → card-BN643ZOY.js} +6 -2
  2. package/dist/card-T2XJZA5A.js +92 -0
  3. package/dist/{chunk-3LWBH7P3.js → chunk-4NFJ3VYZ.js} +20 -1
  4. package/dist/chunk-5AIYALBX.js +857 -0
  5. package/dist/chunk-6QMDJVMS.js +238 -0
  6. package/dist/{chunk-LKLKYXLV.js → chunk-74LZDEDT.js} +6 -4
  7. package/dist/{chunk-GKVTD4EZ.js → chunk-77KGEDH4.js} +1 -1
  8. package/dist/{chunk-QCGIG7WW.js → chunk-7IQE34QK.js} +14 -7
  9. package/dist/{chunk-QHZGOG3O.js → chunk-D242QZCR.js} +168 -41
  10. package/dist/chunk-EE3V3DXK.js +60 -0
  11. package/dist/{chunk-RYISHSHB.js → chunk-F3KIEVJ2.js} +207 -265
  12. package/dist/{chunk-XBGVQMQJ.js → chunk-FELGHDCA.js} +16 -39
  13. package/dist/{chunk-EJKW57ZV.js → chunk-GIEJVKZZ.js} +1 -1
  14. package/dist/{chunk-WVY2W7AA.js → chunk-I7KWA7OB.js} +20 -0
  15. package/dist/{chunk-4IPJJRTP.js → chunk-IGQNP3ZO.js} +5 -2
  16. package/dist/chunk-NQANA6WH.js +797 -0
  17. package/dist/{chunk-Z4MCGKTL.js → chunk-NX27AFPA.js} +15 -2
  18. package/dist/{chunk-Z2GEFFDO.js → chunk-O4Q7BRG6.js} +2 -2
  19. package/dist/{chunk-SSK653A6.js → chunk-PQIP7EXY.js} +6 -0
  20. package/dist/{chunk-EG6RS4JC.js → chunk-QFPXZITP.js} +20 -65
  21. package/dist/chunk-R4F4XII4.js +264 -0
  22. package/dist/{chunk-DYQOFGGI.js → chunk-RVBW2QXU.js} +178 -49
  23. package/dist/{chunk-CQFBNTGT.js → chunk-S7DZHKCG.js} +25 -12
  24. package/dist/chunk-U6LP4KWN.js +238 -0
  25. package/dist/{chunk-MWOXW7JQ.js → chunk-VJ7XBEY6.js} +24 -16
  26. package/dist/chunk-WTHMHNKC.js +129 -0
  27. package/dist/{chunk-OCSU2S6W.js → chunk-WX3GZVFG.js} +2 -1
  28. package/dist/{chunk-CKOOVZOI.js → chunk-YKMBFQC2.js} +37 -5
  29. package/dist/{chunk-S3V6R3EN.js → chunk-ZU2TP7CN.js} +70 -27
  30. package/dist/cli/index.js +203 -237
  31. package/dist/client-OKJJ3UP2.js +19 -0
  32. package/dist/client-UQBGCIPA.js +20 -0
  33. package/dist/conduct-4JDMWBQD.js +22 -0
  34. package/dist/{conduct-AZFLNUX3.js → conduct-VYYBCPHA.js} +14 -13
  35. package/dist/{conductor-mode-WKB42PYM.js → conductor-mode-OPGQJFLA.js} +12 -8
  36. package/dist/{conductor-mode-PLTB6MS3.js → conductor-mode-SBDCRIX6.js} +16 -11
  37. package/dist/execute-FZLQGIXB.js +14 -0
  38. package/dist/execute-TEZPQ5WP.js +15 -0
  39. package/dist/index.d.ts +172 -11
  40. package/dist/index.js +1529 -433
  41. package/dist/{process-guard-GH5LRNWO.js → process-guard-TNSUNHSR.js} +1 -1
  42. package/dist/{publish-capability-QDR2QIZ2.js → publish-capability-HVYILTPR.js} +4 -3
  43. package/dist/{reliability-metrics-QG7WC5QK.js → reliability-metrics-G7LPUYJD.js} +3 -1
  44. package/dist/reliability-metrics-RRUKJ4ME.js +20 -0
  45. package/dist/{request-OERS5BE7.js → request-KJNKR27T.js} +76 -71
  46. package/dist/{serve-skill-E6EJQYAK.js → serve-skill-GC6NIQ5T.js} +10 -11
  47. package/dist/{server-46VEG2W7.js → server-YV3XPTX5.js} +11 -10
  48. package/dist/{service-coordinator-KMSA6BST.js → service-coordinator-RY5AKUZS.js} +420 -171
  49. package/dist/{skill-config-FETXPNVP.js → skill-config-5O2VR546.js} +1 -1
  50. package/dist/skills/agentbnb/bootstrap.js +528 -253
  51. package/dist/websocket-client-3U27WJUU.js +7 -0
  52. package/dist/{websocket-client-4Z5P54RU.js → websocket-client-SNDF3B6N.js} +1 -1
  53. package/package.json +1 -1
  54. package/dist/chunk-MCED4GDW.js +0 -1572
  55. package/dist/chunk-NWIQJ2CL.js +0 -108
  56. package/dist/chunk-TUCEDQGM.js +0 -44
  57. package/dist/chunk-WNXXLCV5.js +0 -32
  58. package/dist/client-XOLP5IUZ.js +0 -12
  59. package/dist/conduct-VPUYTNEA.js +0 -21
  60. package/dist/execute-NNDCXTN4.js +0 -13
  61. package/dist/execute-RIRHTIBU.js +0 -16
  62. package/dist/websocket-client-QOVARTRN.js +0 -7
@@ -0,0 +1,60 @@
1
+ // src/identity/agent-identity.ts
2
+ var AGENTS_SCHEMA = `
3
+ CREATE TABLE IF NOT EXISTS agents (
4
+ agent_id TEXT PRIMARY KEY,
5
+ display_name TEXT NOT NULL,
6
+ public_key TEXT NOT NULL,
7
+ operator_id TEXT,
8
+ server_id TEXT,
9
+ legacy_owner TEXT,
10
+ created_at TEXT NOT NULL,
11
+ updated_at TEXT NOT NULL
12
+ );
13
+
14
+ CREATE INDEX IF NOT EXISTS idx_agents_operator ON agents(operator_id);
15
+ CREATE INDEX IF NOT EXISTS idx_agents_legacy_owner ON agents(legacy_owner);
16
+ `;
17
+ function ensureAgentsTable(db) {
18
+ db.exec(AGENTS_SCHEMA);
19
+ }
20
+ function lookupAgent(db, agentId) {
21
+ return db.prepare("SELECT * FROM agents WHERE agent_id = ?").get(agentId) ?? null;
22
+ }
23
+ function lookupAgentByOwner(db, owner) {
24
+ return db.prepare("SELECT * FROM agents WHERE legacy_owner = ?").get(owner) ?? null;
25
+ }
26
+ function resolveCanonicalIdentity(db, identifier) {
27
+ ensureAgentsTable(db);
28
+ if (/^[a-f0-9]{16}$/.test(identifier)) {
29
+ const byAgentId = lookupAgent(db, identifier);
30
+ if (byAgentId) {
31
+ return {
32
+ agent_id: byAgentId.agent_id,
33
+ legacy_owner: byAgentId.legacy_owner,
34
+ resolved: true,
35
+ source: "agent_id"
36
+ };
37
+ }
38
+ }
39
+ const byOwner = lookupAgentByOwner(db, identifier);
40
+ if (byOwner) {
41
+ return {
42
+ agent_id: byOwner.agent_id,
43
+ legacy_owner: byOwner.legacy_owner,
44
+ resolved: true,
45
+ source: "legacy_owner"
46
+ };
47
+ }
48
+ return {
49
+ agent_id: identifier,
50
+ legacy_owner: null,
51
+ resolved: false,
52
+ source: "unresolved"
53
+ };
54
+ }
55
+
56
+ export {
57
+ ensureAgentsTable,
58
+ lookupAgent,
59
+ resolveCanonicalIdentity
60
+ };
@@ -1,79 +1,22 @@
1
1
  import {
2
+ canonicalizeCreditOwner,
2
3
  ensureReliabilityTable,
4
+ migrateCreditOwnerData,
3
5
  recordSuccessfulHire
4
- } from "./chunk-NWIQJ2CL.js";
6
+ } from "./chunk-U6LP4KWN.js";
5
7
  import {
6
8
  getFeedbackForProvider
7
- } from "./chunk-S3V6R3EN.js";
9
+ } from "./chunk-5AIYALBX.js";
10
+ import {
11
+ ensureAgentsTable
12
+ } from "./chunk-WTHMHNKC.js";
8
13
  import {
9
14
  AgentBnBError
10
- } from "./chunk-WVY2W7AA.js";
15
+ } from "./chunk-I7KWA7OB.js";
11
16
 
12
17
  // src/credit/ledger.ts
13
18
  import Database from "better-sqlite3";
14
19
  import { randomUUID } from "crypto";
15
-
16
- // src/identity/agent-identity.ts
17
- var AGENTS_SCHEMA = `
18
- CREATE TABLE IF NOT EXISTS agents (
19
- agent_id TEXT PRIMARY KEY,
20
- display_name TEXT NOT NULL,
21
- public_key TEXT NOT NULL,
22
- operator_id TEXT,
23
- server_id TEXT,
24
- legacy_owner TEXT,
25
- created_at TEXT NOT NULL,
26
- updated_at TEXT NOT NULL
27
- );
28
-
29
- CREATE INDEX IF NOT EXISTS idx_agents_operator ON agents(operator_id);
30
- CREATE INDEX IF NOT EXISTS idx_agents_legacy_owner ON agents(legacy_owner);
31
- `;
32
- function ensureAgentsTable(db) {
33
- db.exec(AGENTS_SCHEMA);
34
- }
35
- function createAgentRecord(db, agent) {
36
- const now = (/* @__PURE__ */ new Date()).toISOString();
37
- const record = {
38
- agent_id: agent.agent_id,
39
- display_name: agent.display_name,
40
- public_key: agent.public_key,
41
- operator_id: agent.operator_id ?? null,
42
- server_id: agent.server_id ?? null,
43
- legacy_owner: agent.legacy_owner ?? null,
44
- created_at: now,
45
- updated_at: now
46
- };
47
- const result = db.prepare(
48
- `INSERT OR IGNORE INTO agents
49
- (agent_id, display_name, public_key, operator_id, server_id, legacy_owner, created_at, updated_at)
50
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
51
- ).run(
52
- record.agent_id,
53
- record.display_name,
54
- record.public_key,
55
- record.operator_id,
56
- record.server_id,
57
- record.legacy_owner,
58
- record.created_at,
59
- record.updated_at
60
- );
61
- if (result.changes === 0) {
62
- throw new AgentBnBError(
63
- "AGENT_EXISTS",
64
- `Agent ${agent.agent_id} already exists`
65
- );
66
- }
67
- return record;
68
- }
69
- function lookupAgent(db, agentId) {
70
- return db.prepare("SELECT * FROM agents WHERE agent_id = ?").get(agentId) ?? null;
71
- }
72
- function lookupAgentByOwner(db, owner) {
73
- return db.prepare("SELECT * FROM agents WHERE legacy_owner = ?").get(owner) ?? null;
74
- }
75
-
76
- // src/credit/ledger.ts
77
20
  var CREDIT_SCHEMA = `
78
21
  CREATE TABLE IF NOT EXISTS credit_balances (
79
22
  owner TEXT PRIMARY KEY,
@@ -133,30 +76,33 @@ function openCreditDb(path = ":memory:") {
133
76
  return db;
134
77
  }
135
78
  function bootstrapAgent(db, owner, amount = 100) {
79
+ const canonicalOwner = canonicalizeCreditOwner(db, owner);
136
80
  const now = (/* @__PURE__ */ new Date()).toISOString();
137
81
  let isNew = false;
138
82
  db.transaction(() => {
139
- const result = db.prepare("INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, ?, ?)").run(owner, amount, now);
83
+ const result = db.prepare("INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, ?, ?)").run(canonicalOwner, amount, now);
140
84
  if (result.changes > 0) {
141
85
  isNew = true;
142
86
  db.prepare(
143
87
  "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
144
- ).run(randomUUID(), owner, amount, "bootstrap", null, now);
88
+ ).run(randomUUID(), canonicalOwner, amount, "bootstrap", null, now);
145
89
  }
146
90
  })();
147
91
  if (isNew) {
148
- issueVoucher(db, owner, 50, 30);
92
+ issueVoucher(db, canonicalOwner, 50, 30);
149
93
  }
150
94
  }
151
95
  function getBalance(db, owner) {
152
- const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(owner);
96
+ const canonicalOwner = canonicalizeCreditOwner(db, owner);
97
+ const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(canonicalOwner);
153
98
  return row?.balance ?? 0;
154
99
  }
155
100
  function getTransactions(db, owner, opts = 100) {
101
+ const canonicalOwner = canonicalizeCreditOwner(db, owner);
156
102
  const page = typeof opts === "number" ? { limit: opts } : opts;
157
103
  const limit = page.limit ?? 100;
158
104
  const conditions = ["owner = ?"];
159
- const params = [owner];
105
+ const params = [canonicalOwner];
160
106
  if (page.before) {
161
107
  conditions.push("created_at < ?");
162
108
  params.push(page.before);
@@ -171,15 +117,17 @@ function getTransactions(db, owner, opts = 100) {
171
117
  ).all(...params);
172
118
  }
173
119
  function registerProvider(db, owner) {
120
+ const canonicalOwner = canonicalizeCreditOwner(db, owner);
174
121
  const now = (/* @__PURE__ */ new Date()).toISOString();
175
122
  const maxRow = db.prepare("SELECT MAX(provider_number) as maxNum FROM provider_registry").get();
176
123
  const nextNum = (maxRow?.maxNum ?? 0) + 1;
177
- db.prepare("INSERT OR IGNORE INTO provider_registry (owner, provider_number, registered_at) VALUES (?, ?, ?)").run(owner, nextNum, now);
178
- const row = db.prepare("SELECT provider_number FROM provider_registry WHERE owner = ?").get(owner);
124
+ db.prepare("INSERT OR IGNORE INTO provider_registry (owner, provider_number, registered_at) VALUES (?, ?, ?)").run(canonicalOwner, nextNum, now);
125
+ const row = db.prepare("SELECT provider_number FROM provider_registry WHERE owner = ?").get(canonicalOwner);
179
126
  return row.provider_number;
180
127
  }
181
128
  function getProviderNumber(db, owner) {
182
- const row = db.prepare("SELECT provider_number FROM provider_registry WHERE owner = ?").get(owner);
129
+ const canonicalOwner = canonicalizeCreditOwner(db, owner);
130
+ const row = db.prepare("SELECT provider_number FROM provider_registry WHERE owner = ?").get(canonicalOwner);
183
131
  return row?.provider_number ?? null;
184
132
  }
185
133
  function getProviderBonus(providerNumber) {
@@ -188,19 +136,21 @@ function getProviderBonus(providerNumber) {
188
136
  return 1;
189
137
  }
190
138
  function issueVoucher(db, owner, amount = 50, daysValid = 30) {
139
+ const canonicalOwner = canonicalizeCreditOwner(db, owner);
191
140
  const id = randomUUID();
192
141
  const now = /* @__PURE__ */ new Date();
193
142
  const expiresAt = new Date(now.getTime() + daysValid * 24 * 60 * 60 * 1e3);
194
143
  db.prepare(
195
144
  "INSERT INTO demand_vouchers (id, owner, amount, remaining, created_at, expires_at, is_active) VALUES (?, ?, ?, ?, ?, ?, 1)"
196
- ).run(id, owner, amount, amount, now.toISOString(), expiresAt.toISOString());
145
+ ).run(id, canonicalOwner, amount, amount, now.toISOString(), expiresAt.toISOString());
197
146
  return id;
198
147
  }
199
148
  function getActiveVoucher(db, owner) {
149
+ const canonicalOwner = canonicalizeCreditOwner(db, owner);
200
150
  const now = (/* @__PURE__ */ new Date()).toISOString();
201
151
  const row = db.prepare(
202
152
  "SELECT id, remaining, expires_at FROM demand_vouchers WHERE owner = ? AND is_active = 1 AND remaining > 0 AND expires_at > ? ORDER BY created_at ASC LIMIT 1"
203
- ).get(owner, now);
153
+ ).get(canonicalOwner, now);
204
154
  return row ?? null;
205
155
  }
206
156
  function consumeVoucher(db, voucherId, amount) {
@@ -208,189 +158,10 @@ function consumeVoucher(db, voucherId, amount) {
208
158
  "UPDATE demand_vouchers SET remaining = remaining - ? WHERE id = ? AND remaining >= ?"
209
159
  ).run(amount, voucherId, amount);
210
160
  }
211
- function recordEarning(db, owner, amount, _cardId, receiptNonce) {
212
- const now = (/* @__PURE__ */ new Date()).toISOString();
213
- db.transaction(() => {
214
- const existing = db.prepare(
215
- "SELECT id FROM credit_transactions WHERE reference_id = ? AND reason = 'remote_earning'"
216
- ).get(receiptNonce);
217
- if (existing) return;
218
- db.prepare(
219
- "INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, 0, ?)"
220
- ).run(owner, now);
221
- db.prepare(
222
- "UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
223
- ).run(amount, now, owner);
224
- db.prepare(
225
- "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
226
- ).run(randomUUID(), owner, amount, "remote_earning", receiptNonce, now);
227
- })();
228
- }
229
161
  function migrateOwner(db, oldOwner, newOwner) {
230
162
  if (oldOwner === newOwner) return;
231
- const now = (/* @__PURE__ */ new Date()).toISOString();
232
- db.transaction(() => {
233
- const oldRow = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(oldOwner);
234
- if (!oldRow) return;
235
- const newRow = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(newOwner);
236
- if (newRow) {
237
- db.prepare("UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?").run(oldRow.balance, now, newOwner);
238
- } else {
239
- db.prepare("UPDATE credit_balances SET owner = ?, updated_at = ? WHERE owner = ?").run(newOwner, now, oldOwner);
240
- }
241
- if (newRow) {
242
- db.prepare("DELETE FROM credit_balances WHERE owner = ?").run(oldOwner);
243
- }
244
- db.prepare("UPDATE credit_transactions SET owner = ? WHERE owner = ?").run(newOwner, oldOwner);
245
- db.prepare("UPDATE credit_escrow SET owner = ? WHERE owner = ?").run(newOwner, oldOwner);
246
- })();
247
- }
248
-
249
- // src/credit/escrow.ts
250
- import { randomUUID as randomUUID2 } from "crypto";
251
- var NETWORK_FEE_RATE = 0.05;
252
- function holdEscrow(db, owner, amount, cardId) {
253
- const escrowId = randomUUID2();
254
- const now = (/* @__PURE__ */ new Date()).toISOString();
255
- const hold = db.transaction(() => {
256
- const voucher = getActiveVoucher(db, owner);
257
- if (voucher && voucher.remaining >= amount) {
258
- consumeVoucher(db, voucher.id, amount);
259
- db.prepare(
260
- "INSERT INTO credit_escrow (id, owner, amount, card_id, status, created_at, funding_source) VALUES (?, ?, ?, ?, ?, ?, ?)"
261
- ).run(escrowId, owner, amount, cardId, "held", now, "voucher");
262
- db.prepare(
263
- "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
264
- ).run(randomUUID2(), owner, -amount, "voucher_hold", escrowId, now);
265
- } else {
266
- const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(owner);
267
- if (!row || row.balance < amount) {
268
- throw new AgentBnBError("Insufficient credits", "INSUFFICIENT_CREDITS");
269
- }
270
- db.prepare(
271
- "UPDATE credit_balances SET balance = balance - ?, updated_at = ? WHERE owner = ? AND balance >= ?"
272
- ).run(amount, now, owner, amount);
273
- db.prepare(
274
- "INSERT INTO credit_escrow (id, owner, amount, card_id, status, created_at, funding_source) VALUES (?, ?, ?, ?, ?, ?, ?)"
275
- ).run(escrowId, owner, amount, cardId, "held", now, "balance");
276
- db.prepare(
277
- "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
278
- ).run(randomUUID2(), owner, -amount, "escrow_hold", escrowId, now);
279
- }
280
- });
281
- hold();
282
- return escrowId;
283
- }
284
- function settleEscrow(db, escrowId, recipientOwner) {
285
- const now = (/* @__PURE__ */ new Date()).toISOString();
286
- const settle = db.transaction(() => {
287
- const escrow = db.prepare("SELECT id, owner, amount, status, funding_source FROM credit_escrow WHERE id = ?").get(escrowId);
288
- if (!escrow) {
289
- throw new AgentBnBError(`Escrow not found: ${escrowId}`, "ESCROW_NOT_FOUND");
290
- }
291
- if (escrow.status !== "held") {
292
- throw new AgentBnBError(
293
- `Escrow ${escrowId} is already ${escrow.status}`,
294
- "ESCROW_ALREADY_SETTLED"
295
- );
296
- }
297
- const feeAmount = Math.floor(escrow.amount * NETWORK_FEE_RATE);
298
- const providerAmount = escrow.amount - feeAmount;
299
- db.prepare(
300
- "INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, 0, ?)"
301
- ).run(recipientOwner, now);
302
- db.prepare(
303
- "UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
304
- ).run(providerAmount, now, recipientOwner);
305
- if (feeAmount > 0) {
306
- db.prepare(
307
- "INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, 0, ?)"
308
- ).run("platform_treasury", now);
309
- db.prepare(
310
- "UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
311
- ).run(feeAmount, now, "platform_treasury");
312
- db.prepare(
313
- "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
314
- ).run(randomUUID2(), "platform_treasury", feeAmount, "network_fee", escrowId, now);
315
- }
316
- db.prepare(
317
- "UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?"
318
- ).run("settled", now, escrowId);
319
- db.prepare(
320
- "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
321
- ).run(randomUUID2(), recipientOwner, providerAmount, "settlement", escrowId, now);
322
- let providerNum = getProviderNumber(db, recipientOwner);
323
- if (providerNum === null) {
324
- providerNum = registerProvider(db, recipientOwner);
325
- }
326
- const bonus = getProviderBonus(providerNum);
327
- if (bonus > 1) {
328
- const bonusAmount = Math.floor(providerAmount * (bonus - 1));
329
- if (bonusAmount > 0) {
330
- db.prepare(
331
- "INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, 0, ?)"
332
- ).run("platform_treasury", now);
333
- db.prepare(
334
- "UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
335
- ).run(bonusAmount, now, recipientOwner);
336
- db.prepare(
337
- "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
338
- ).run(randomUUID2(), recipientOwner, bonusAmount, "provider_bonus", escrowId, now);
339
- }
340
- }
341
- try {
342
- recordSuccessfulHire(db, recipientOwner, escrow.owner);
343
- } catch {
344
- }
345
- });
346
- settle();
347
- }
348
- function releaseEscrow(db, escrowId) {
349
- const now = (/* @__PURE__ */ new Date()).toISOString();
350
- const release = db.transaction(() => {
351
- const escrow = db.prepare("SELECT id, owner, amount, status, funding_source FROM credit_escrow WHERE id = ?").get(escrowId);
352
- if (!escrow) {
353
- throw new AgentBnBError(`Escrow not found: ${escrowId}`, "ESCROW_NOT_FOUND");
354
- }
355
- if (escrow.status !== "held") {
356
- throw new AgentBnBError(
357
- `Escrow ${escrowId} is already ${escrow.status}`,
358
- "ESCROW_ALREADY_SETTLED"
359
- );
360
- }
361
- db.prepare(
362
- "UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
363
- ).run(escrow.amount, now, escrow.owner);
364
- db.prepare(
365
- "UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?"
366
- ).run("released", now, escrowId);
367
- db.prepare(
368
- "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
369
- ).run(randomUUID2(), escrow.owner, escrow.amount, "refund", escrowId, now);
370
- });
371
- release();
372
- }
373
- function confirmEscrowDebit(db, escrowId) {
374
- const now = (/* @__PURE__ */ new Date()).toISOString();
375
- const confirm = db.transaction(() => {
376
- const escrow = db.prepare("SELECT id, owner, amount, status, funding_source FROM credit_escrow WHERE id = ?").get(escrowId);
377
- if (!escrow) {
378
- throw new AgentBnBError(`Escrow not found: ${escrowId}`, "ESCROW_NOT_FOUND");
379
- }
380
- if (escrow.status !== "held") {
381
- throw new AgentBnBError(
382
- `Escrow ${escrowId} is already ${escrow.status}`,
383
- "ESCROW_ALREADY_SETTLED"
384
- );
385
- }
386
- db.prepare(
387
- "UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?"
388
- ).run("settled", now, escrowId);
389
- db.prepare(
390
- "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
391
- ).run(randomUUID2(), escrow.owner, 0, "remote_settlement_confirmed", escrowId, now);
392
- });
393
- confirm();
163
+ const canonicalNewOwner = canonicalizeCreditOwner(db, newOwner);
164
+ migrateCreditOwnerData(db, oldOwner, canonicalNewOwner);
394
165
  }
395
166
 
396
167
  // src/feedback/reputation.ts
@@ -586,6 +357,180 @@ function buildReputationMap(db, owners) {
586
357
  return map;
587
358
  }
588
359
 
360
+ // src/credit/escrow.ts
361
+ import { randomUUID as randomUUID2 } from "crypto";
362
+ var NETWORK_FEE_RATE = 0.05;
363
+ var FINALIZABLE_ESCROW_STATUSES = /* @__PURE__ */ new Set([
364
+ "held",
365
+ "started",
366
+ "progressing",
367
+ "abandoned"
368
+ ]);
369
+ var TERMINAL_ESCROW_STATUSES = /* @__PURE__ */ new Set(["settled", "released"]);
370
+ function getEscrowForMutation(db, escrowId) {
371
+ const escrow = db.prepare("SELECT id, owner, amount, status, funding_source FROM credit_escrow WHERE id = ?").get(escrowId);
372
+ if (!escrow) {
373
+ throw new AgentBnBError(`Escrow not found: ${escrowId}`, "ESCROW_NOT_FOUND");
374
+ }
375
+ return {
376
+ ...escrow,
377
+ owner: canonicalizeCreditOwner(db, escrow.owner)
378
+ };
379
+ }
380
+ function updateEscrowStatus(db, escrowId, fromStatuses, toStatus) {
381
+ const now = (/* @__PURE__ */ new Date()).toISOString();
382
+ const transition = db.transaction(() => {
383
+ const escrow = getEscrowForMutation(db, escrowId);
384
+ const current = escrow.status;
385
+ if (!fromStatuses.includes(current)) {
386
+ throw new AgentBnBError(
387
+ `Invalid escrow transition for ${escrowId}: ${current} -> ${toStatus}`,
388
+ "ESCROW_INVALID_TRANSITION"
389
+ );
390
+ }
391
+ if (current === toStatus) return;
392
+ const settledAt = TERMINAL_ESCROW_STATUSES.has(toStatus) ? now : null;
393
+ db.prepare("UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?").run(
394
+ toStatus,
395
+ settledAt,
396
+ escrowId
397
+ );
398
+ });
399
+ transition();
400
+ }
401
+ function assertEscrowCanFinalize(escrow) {
402
+ const status = escrow.status;
403
+ if (FINALIZABLE_ESCROW_STATUSES.has(status)) {
404
+ return;
405
+ }
406
+ if (TERMINAL_ESCROW_STATUSES.has(status)) {
407
+ throw new AgentBnBError(
408
+ `Escrow ${escrow.id} is already ${status}`,
409
+ "ESCROW_ALREADY_SETTLED"
410
+ );
411
+ }
412
+ throw new AgentBnBError(
413
+ `Escrow ${escrow.id} has invalid lifecycle status: ${escrow.status}`,
414
+ "ESCROW_INVALID_TRANSITION"
415
+ );
416
+ }
417
+ function holdEscrow(db, owner, amount, cardId) {
418
+ const canonicalOwner = canonicalizeCreditOwner(db, owner);
419
+ const escrowId = randomUUID2();
420
+ const now = (/* @__PURE__ */ new Date()).toISOString();
421
+ const hold = db.transaction(() => {
422
+ const voucher = getActiveVoucher(db, canonicalOwner);
423
+ if (voucher && voucher.remaining >= amount) {
424
+ consumeVoucher(db, voucher.id, amount);
425
+ db.prepare(
426
+ "INSERT INTO credit_escrow (id, owner, amount, card_id, status, created_at, funding_source) VALUES (?, ?, ?, ?, ?, ?, ?)"
427
+ ).run(escrowId, canonicalOwner, amount, cardId, "held", now, "voucher");
428
+ db.prepare(
429
+ "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
430
+ ).run(randomUUID2(), canonicalOwner, -amount, "voucher_hold", escrowId, now);
431
+ } else {
432
+ const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(canonicalOwner);
433
+ if (!row || row.balance < amount) {
434
+ throw new AgentBnBError("Insufficient credits", "INSUFFICIENT_CREDITS");
435
+ }
436
+ db.prepare(
437
+ "UPDATE credit_balances SET balance = balance - ?, updated_at = ? WHERE owner = ? AND balance >= ?"
438
+ ).run(amount, now, canonicalOwner, amount);
439
+ db.prepare(
440
+ "INSERT INTO credit_escrow (id, owner, amount, card_id, status, created_at, funding_source) VALUES (?, ?, ?, ?, ?, ?, ?)"
441
+ ).run(escrowId, canonicalOwner, amount, cardId, "held", now, "balance");
442
+ db.prepare(
443
+ "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
444
+ ).run(randomUUID2(), canonicalOwner, -amount, "escrow_hold", escrowId, now);
445
+ }
446
+ });
447
+ hold();
448
+ return escrowId;
449
+ }
450
+ function markEscrowStarted(db, escrowId) {
451
+ updateEscrowStatus(db, escrowId, ["held", "started"], "started");
452
+ }
453
+ function markEscrowProgressing(db, escrowId) {
454
+ updateEscrowStatus(db, escrowId, ["held", "started", "progressing"], "progressing");
455
+ }
456
+ function markEscrowAbandoned(db, escrowId) {
457
+ updateEscrowStatus(db, escrowId, ["started", "progressing", "abandoned"], "abandoned");
458
+ }
459
+ function settleEscrow(db, escrowId, recipientOwner) {
460
+ const canonicalRecipientOwner = canonicalizeCreditOwner(db, recipientOwner);
461
+ const now = (/* @__PURE__ */ new Date()).toISOString();
462
+ const settle = db.transaction(() => {
463
+ const escrow = getEscrowForMutation(db, escrowId);
464
+ assertEscrowCanFinalize(escrow);
465
+ const feeAmount = Math.floor(escrow.amount * NETWORK_FEE_RATE);
466
+ const providerAmount = escrow.amount - feeAmount;
467
+ db.prepare(
468
+ "INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, 0, ?)"
469
+ ).run(canonicalRecipientOwner, now);
470
+ db.prepare(
471
+ "UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
472
+ ).run(providerAmount, now, canonicalRecipientOwner);
473
+ if (feeAmount > 0) {
474
+ db.prepare(
475
+ "INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, 0, ?)"
476
+ ).run("platform_treasury", now);
477
+ db.prepare(
478
+ "UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
479
+ ).run(feeAmount, now, "platform_treasury");
480
+ db.prepare(
481
+ "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
482
+ ).run(randomUUID2(), "platform_treasury", feeAmount, "network_fee", escrowId, now);
483
+ }
484
+ db.prepare(
485
+ "UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?"
486
+ ).run("settled", now, escrowId);
487
+ db.prepare(
488
+ "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
489
+ ).run(randomUUID2(), canonicalRecipientOwner, providerAmount, "settlement", escrowId, now);
490
+ let providerNum = getProviderNumber(db, canonicalRecipientOwner);
491
+ if (providerNum === null) {
492
+ providerNum = registerProvider(db, canonicalRecipientOwner);
493
+ }
494
+ const bonus = getProviderBonus(providerNum);
495
+ if (bonus > 1) {
496
+ const bonusAmount = Math.floor(providerAmount * (bonus - 1));
497
+ if (bonusAmount > 0) {
498
+ db.prepare(
499
+ "INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, 0, ?)"
500
+ ).run("platform_treasury", now);
501
+ db.prepare(
502
+ "UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
503
+ ).run(bonusAmount, now, canonicalRecipientOwner);
504
+ db.prepare(
505
+ "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
506
+ ).run(randomUUID2(), canonicalRecipientOwner, bonusAmount, "provider_bonus", escrowId, now);
507
+ }
508
+ }
509
+ try {
510
+ recordSuccessfulHire(db, canonicalRecipientOwner, escrow.owner);
511
+ } catch {
512
+ }
513
+ });
514
+ settle();
515
+ }
516
+ function releaseEscrow(db, escrowId) {
517
+ const now = (/* @__PURE__ */ new Date()).toISOString();
518
+ const release = db.transaction(() => {
519
+ const escrow = getEscrowForMutation(db, escrowId);
520
+ assertEscrowCanFinalize(escrow);
521
+ db.prepare(
522
+ "UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
523
+ ).run(escrow.amount, now, escrow.owner);
524
+ db.prepare(
525
+ "UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?"
526
+ ).run("released", now, escrowId);
527
+ db.prepare(
528
+ "INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
529
+ ).run(randomUUID2(), escrow.owner, escrow.amount, "refund", escrowId, now);
530
+ });
531
+ release();
532
+ }
533
+
589
534
  // src/cli/remote-registry.ts
590
535
  var RegistryTimeoutError = class extends AgentBnBError {
591
536
  constructor(url) {
@@ -670,24 +615,21 @@ function mergeResults(localCards, remoteCards, hasQuery) {
670
615
  }
671
616
 
672
617
  export {
673
- createAgentRecord,
674
- lookupAgent,
675
- lookupAgentByOwner,
676
618
  openCreditDb,
677
619
  bootstrapAgent,
678
620
  getBalance,
679
621
  getTransactions,
680
- recordEarning,
681
622
  migrateOwner,
682
- NETWORK_FEE_RATE,
683
- holdEscrow,
684
- settleEscrow,
685
- releaseEscrow,
686
- confirmEscrowDebit,
687
623
  computeReputation,
688
624
  searchCards,
689
625
  filterCards,
690
626
  buildReputationMap,
627
+ holdEscrow,
628
+ markEscrowStarted,
629
+ markEscrowProgressing,
630
+ markEscrowAbandoned,
631
+ settleEscrow,
632
+ releaseEscrow,
691
633
  fetchRemoteCards,
692
634
  mergeResults
693
635
  };