agentbnb 8.2.0 → 8.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/{chunk-TBJ3FZKZ.js → chunk-4IPJJRTP.js} +1 -1
  2. package/dist/chunk-CKOOVZOI.js +158 -0
  3. package/dist/chunk-CQFBNTGT.js +145 -0
  4. package/dist/{chunk-P4LOYSLA.js → chunk-DYQOFGGI.js} +331 -416
  5. package/dist/{chunk-ALX4WS3A.js → chunk-EG6RS4JC.js} +70 -46
  6. package/dist/{chunk-CUONY5TO.js → chunk-EJKW57ZV.js} +19 -1
  7. package/dist/{chunk-5AAFG2V2.js → chunk-LKLKYXLV.js} +239 -24
  8. package/dist/{chunk-7EF3HYVZ.js → chunk-MCED4GDW.js} +499 -86
  9. package/dist/{chunk-YHY7OG6S.js → chunk-MWOXW7JQ.js} +7 -7
  10. package/dist/{chunk-E2OKP5CY.js → chunk-QCGIG7WW.js} +182 -86
  11. package/dist/{chunk-5GME4KJZ.js → chunk-QHZGOG3O.js} +148 -46
  12. package/dist/{chunk-D6RKW2XG.js → chunk-RYISHSHB.js} +302 -4
  13. package/dist/{chunk-O2OYBAVR.js → chunk-S3V6R3EN.js} +75 -39
  14. package/dist/{chunk-X32NE6V4.js → chunk-WNXXLCV5.js} +1 -1
  15. package/dist/{chunk-C537SFHV.js → chunk-XBGVQMQJ.js} +72 -48
  16. package/dist/{chunk-FTZTEHYG.js → chunk-Z2GEFFDO.js} +135 -8
  17. package/dist/cli/index.js +42 -67
  18. package/dist/{client-HKV3QWZ3.js → client-XOLP5IUZ.js} +4 -2
  19. package/dist/{conduct-W6XF6DJW.js → conduct-AZFLNUX3.js} +10 -11
  20. package/dist/{conduct-YB64OHI6.js → conduct-VPUYTNEA.js} +10 -11
  21. package/dist/{conductor-mode-AKREGDIU.js → conductor-mode-PLTB6MS3.js} +7 -8
  22. package/dist/{conductor-mode-TFCVCQHU.js → conductor-mode-WKB42PYM.js} +6 -3
  23. package/dist/{execute-EPE6MZLT.js → execute-NNDCXTN4.js} +3 -2
  24. package/dist/{execute-AYQWORVH.js → execute-RIRHTIBU.js} +6 -5
  25. package/dist/index.d.ts +8 -8
  26. package/dist/index.js +637 -693
  27. package/dist/{publish-capability-AH2HDW54.js → publish-capability-QDR2QIZ2.js} +2 -2
  28. package/dist/{request-HCCXSKAY.js → request-NX7GSPIG.js} +31 -36
  29. package/dist/{serve-skill-SZAQT5T5.js → serve-skill-E6EJQYAK.js} +10 -9
  30. package/dist/{server-LMY2A3GT.js → server-VBCT32FC.js} +12 -18
  31. package/dist/{service-coordinator-WGH6B2VT.js → service-coordinator-KMSA6BST.js} +137 -69
  32. package/dist/skills/agentbnb/bootstrap.js +561 -247
  33. package/package.json +13 -17
  34. package/skills/agentbnb/bootstrap.test.ts +8 -6
  35. package/skills/agentbnb/bootstrap.ts +21 -13
  36. package/skills/agentbnb/install.sh +0 -0
  37. package/dist/chunk-64AK4FJM.js +0 -84
  38. package/dist/chunk-KF3TZHA5.js +0 -91
  39. package/dist/chunk-LJM7FHPM.js +0 -138
  40. package/dist/chunk-OH7BP5NP.js +0 -96
@@ -7,10 +7,13 @@ import {
7
7
  insertRequestLog,
8
8
  recordEarning,
9
9
  releaseEscrow,
10
+ resolveTargetCapability,
10
11
  settleEscrow,
11
- updateReputation,
12
+ updateReputation
13
+ } from "./chunk-MCED4GDW.js";
14
+ import {
12
15
  verifyEscrowReceipt
13
- } from "./chunk-7EF3HYVZ.js";
16
+ } from "./chunk-EJKW57ZV.js";
14
17
  import {
15
18
  loadConfig
16
19
  } from "./chunk-IVOYM3WG.js";
@@ -290,8 +293,12 @@ async function executeCapabilityBatch(options) {
290
293
  };
291
294
  }
292
295
  const executeItem = async (item, index) => {
293
- const card = getCard(registryDb, item.skill_id);
294
- if (!card) {
296
+ const resolved = await resolveTargetCapability(item.skill_id, {
297
+ registryDb,
298
+ registryUrl: options.registryUrl,
299
+ onlineOnly: true
300
+ });
301
+ if (!resolved) {
295
302
  return {
296
303
  request_index: index,
297
304
  status: "failed",
@@ -300,26 +307,11 @@ async function executeCapabilityBatch(options) {
300
307
  error: `Card/skill not found: ${item.skill_id}`
301
308
  };
302
309
  }
303
- const rawCard = card;
304
- let creditsNeeded;
305
- let resolvedSkillId;
306
- if (Array.isArray(rawCard["skills"])) {
307
- const v2card = card;
308
- const skill = v2card.skills[0];
309
- if (!skill) {
310
- return {
311
- request_index: index,
312
- status: "failed",
313
- credits_spent: 0,
314
- credits_refunded: 0,
315
- error: `No skills defined on card: ${item.skill_id}`
316
- };
317
- }
318
- creditsNeeded = skill.pricing.credits_per_call;
319
- resolvedSkillId = skill.id;
320
- } else {
321
- creditsNeeded = card.pricing.credits_per_call;
322
- }
310
+ const localCard = getCard(registryDb, resolved.cardId);
311
+ const localCardRaw = localCard;
312
+ const cardName = typeof localCardRaw?.["name"] === "string" ? localCardRaw["name"] : typeof localCardRaw?.["agent_name"] === "string" ? localCardRaw["agent_name"] : resolved.cardId;
313
+ const creditsNeeded = resolved.credits_per_call;
314
+ const resolvedSkillId = resolved.skillId;
323
315
  if (creditsNeeded > item.max_credits) {
324
316
  return {
325
317
  request_index: index,
@@ -341,7 +333,7 @@ async function executeCapabilityBatch(options) {
341
333
  error: "Insufficient credits"
342
334
  };
343
335
  }
344
- escrowId = holdEscrow(creditDb, owner, creditsNeeded, card.id);
336
+ escrowId = holdEscrow(creditDb, owner, creditsNeeded, resolved.cardId);
345
337
  } catch (err) {
346
338
  const msg = err instanceof AgentBnBError ? err.message : "Failed to hold escrow";
347
339
  return {
@@ -353,30 +345,62 @@ async function executeCapabilityBatch(options) {
353
345
  };
354
346
  }
355
347
  const startMs = Date.now();
356
- const latencyMs = Date.now() - startMs;
357
- settleEscrow(creditDb, escrowId, card.owner);
358
- updateReputation(registryDb, card.id, true, latencyMs);
359
348
  try {
360
- insertRequestLog(registryDb, {
361
- id: randomUUID(),
362
- card_id: card.id,
363
- card_name: card.name,
364
- skill_id: resolvedSkillId,
365
- requester: owner,
349
+ const result = options.dispatchRequest ? await options.dispatchRequest({
350
+ target: resolved,
351
+ params: item.params,
352
+ requester: owner
353
+ }) : { card_id: resolved.cardId, skill_id: resolvedSkillId };
354
+ const latencyMs = Date.now() - startMs;
355
+ settleEscrow(creditDb, escrowId, resolved.owner);
356
+ updateReputation(registryDb, resolved.cardId, true, latencyMs);
357
+ try {
358
+ insertRequestLog(registryDb, {
359
+ id: randomUUID(),
360
+ card_id: resolved.cardId,
361
+ card_name: cardName,
362
+ skill_id: resolvedSkillId,
363
+ requester: owner,
364
+ status: "success",
365
+ latency_ms: latencyMs,
366
+ credits_charged: creditsNeeded,
367
+ created_at: (/* @__PURE__ */ new Date()).toISOString()
368
+ });
369
+ } catch {
370
+ }
371
+ return {
372
+ request_index: index,
366
373
  status: "success",
367
- latency_ms: latencyMs,
368
- credits_charged: creditsNeeded,
369
- created_at: (/* @__PURE__ */ new Date()).toISOString()
370
- });
371
- } catch {
374
+ result,
375
+ credits_spent: creditsNeeded,
376
+ credits_refunded: 0
377
+ };
378
+ } catch (err) {
379
+ releaseEscrow(creditDb, escrowId);
380
+ const latencyMs = Date.now() - startMs;
381
+ try {
382
+ insertRequestLog(registryDb, {
383
+ id: randomUUID(),
384
+ card_id: resolved.cardId,
385
+ card_name: cardName,
386
+ skill_id: resolvedSkillId,
387
+ requester: owner,
388
+ status: "failure",
389
+ latency_ms: latencyMs,
390
+ credits_charged: 0,
391
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
392
+ failure_reason: "not_found"
393
+ });
394
+ } catch {
395
+ }
396
+ return {
397
+ request_index: index,
398
+ status: "failed",
399
+ credits_spent: 0,
400
+ credits_refunded: creditsNeeded,
401
+ error: err instanceof Error ? err.message : String(err)
402
+ };
372
403
  }
373
- return {
374
- request_index: index,
375
- status: "success",
376
- result: { card_id: card.id, skill_id: resolvedSkillId },
377
- credits_spent: creditsNeeded,
378
- credits_refunded: 0
379
- };
380
404
  };
381
405
  let results;
382
406
  if (strategy === "sequential") {
@@ -35,7 +35,25 @@ function loadKeyPair(configDir) {
35
35
  };
36
36
  }
37
37
  function canonicalJson(data) {
38
- return JSON.stringify(data, Object.keys(data).sort());
38
+ return JSON.stringify(sortForCanonicalJson(data));
39
+ }
40
+ function sortForCanonicalJson(value) {
41
+ if (Array.isArray(value)) {
42
+ return value.map((item) => sortForCanonicalJson(item));
43
+ }
44
+ if (value !== null && typeof value === "object") {
45
+ const proto = Object.getPrototypeOf(value);
46
+ if (proto === Object.prototype || proto === null) {
47
+ const input = value;
48
+ const output = {};
49
+ const sortedKeys = Object.keys(input).sort();
50
+ for (const key of sortedKeys) {
51
+ output[key] = sortForCanonicalJson(input[key]);
52
+ }
53
+ return output;
54
+ }
55
+ }
56
+ return value;
39
57
  }
40
58
  function signEscrowReceipt(data, privateKey) {
41
59
  const message = Buffer.from(canonicalJson(data), "utf-8");
@@ -3,19 +3,154 @@ import {
3
3
  getBalance,
4
4
  getTransactions,
5
5
  holdEscrow,
6
+ lookupAgent,
6
7
  migrateOwner,
7
8
  openCreditDb,
8
9
  releaseEscrow,
9
10
  settleEscrow
10
- } from "./chunk-D6RKW2XG.js";
11
+ } from "./chunk-RYISHSHB.js";
11
12
  import {
13
+ generateKeyPair,
14
+ loadKeyPair,
15
+ saveKeyPair,
12
16
  signEscrowReceipt,
13
17
  verifyEscrowReceipt
14
- } from "./chunk-CUONY5TO.js";
18
+ } from "./chunk-EJKW57ZV.js";
15
19
  import {
16
20
  AgentBnBError
17
21
  } from "./chunk-WVY2W7AA.js";
18
22
 
23
+ // src/identity/identity.ts
24
+ import { z } from "zod";
25
+ import { createHash, createPrivateKey, createPublicKey } from "crypto";
26
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
27
+ import { join } from "path";
28
+ var AgentIdentitySchema = z.object({
29
+ /** Deterministic ID derived from public key: sha256(hex).slice(0, 16). */
30
+ agent_id: z.string().min(1),
31
+ /** Human-readable owner name (from config or init). */
32
+ owner: z.string().min(1),
33
+ /** Hex-encoded Ed25519 public key. */
34
+ public_key: z.string().min(1),
35
+ /** ISO 8601 timestamp of identity creation. */
36
+ created_at: z.string().datetime(),
37
+ /** Optional guarantor info if linked to a human. */
38
+ guarantor: z.object({
39
+ github_login: z.string().min(1),
40
+ verified_at: z.string().datetime()
41
+ }).optional()
42
+ });
43
+ var AgentCertificateSchema = z.object({
44
+ identity: AgentIdentitySchema,
45
+ /** ISO 8601 timestamp of certificate issuance. */
46
+ issued_at: z.string().datetime(),
47
+ /** ISO 8601 timestamp of certificate expiry. */
48
+ expires_at: z.string().datetime(),
49
+ /** Hex-encoded public key of the issuer (same as identity for self-signed). */
50
+ issuer_public_key: z.string().min(1),
51
+ /** Base64url Ed25519 signature over { identity, issued_at, expires_at, issuer_public_key }. */
52
+ signature: z.string().min(1)
53
+ });
54
+ var IDENTITY_FILENAME = "identity.json";
55
+ var PRIVATE_KEY_FILENAME = "private.key";
56
+ var PUBLIC_KEY_FILENAME = "public.key";
57
+ function derivePublicKeyFromPrivate(privateKey) {
58
+ const privateKeyObject = createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
59
+ const publicKeyObject = createPublicKey(privateKeyObject);
60
+ const publicKey = publicKeyObject.export({ format: "der", type: "spki" });
61
+ return Buffer.from(publicKey);
62
+ }
63
+ function buildIdentityFromPublicKey(publicKey, owner, createdAt) {
64
+ const publicKeyHex = publicKey.toString("hex");
65
+ return {
66
+ agent_id: deriveAgentId(publicKeyHex),
67
+ owner,
68
+ public_key: publicKeyHex,
69
+ created_at: createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
70
+ };
71
+ }
72
+ function generateFreshIdentity(configDir, owner) {
73
+ const keys = generateKeyPair();
74
+ saveKeyPair(configDir, keys);
75
+ const identity = buildIdentityFromPublicKey(keys.publicKey, owner);
76
+ saveIdentity(configDir, identity);
77
+ return { identity, keys, status: "generated" };
78
+ }
79
+ function deriveAgentId(publicKeyHex) {
80
+ return createHash("sha256").update(publicKeyHex, "hex").digest("hex").slice(0, 16);
81
+ }
82
+ function loadIdentity(configDir) {
83
+ const filePath = join(configDir, IDENTITY_FILENAME);
84
+ if (!existsSync(filePath)) return null;
85
+ try {
86
+ const raw = readFileSync(filePath, "utf-8");
87
+ return AgentIdentitySchema.parse(JSON.parse(raw));
88
+ } catch {
89
+ return null;
90
+ }
91
+ }
92
+ function saveIdentity(configDir, identity) {
93
+ if (!existsSync(configDir)) {
94
+ mkdirSync(configDir, { recursive: true });
95
+ }
96
+ const filePath = join(configDir, IDENTITY_FILENAME);
97
+ writeFileSync(filePath, JSON.stringify(identity, null, 2), "utf-8");
98
+ }
99
+ function loadOrRepairIdentity(configDir, ownerHint) {
100
+ if (!existsSync(configDir)) {
101
+ mkdirSync(configDir, { recursive: true });
102
+ }
103
+ const identityPath = join(configDir, IDENTITY_FILENAME);
104
+ const privateKeyPath = join(configDir, PRIVATE_KEY_FILENAME);
105
+ const publicKeyPath = join(configDir, PUBLIC_KEY_FILENAME);
106
+ const hasIdentity = existsSync(identityPath);
107
+ const hasPrivateKey = existsSync(privateKeyPath);
108
+ const hasPublicKey = existsSync(publicKeyPath);
109
+ if (!hasIdentity || !hasPrivateKey || !hasPublicKey) {
110
+ return generateFreshIdentity(configDir, ownerHint ?? "agent");
111
+ }
112
+ let keys;
113
+ try {
114
+ keys = loadKeyPair(configDir);
115
+ } catch {
116
+ return generateFreshIdentity(configDir, ownerHint ?? "agent");
117
+ }
118
+ let derivedPublicKey;
119
+ try {
120
+ derivedPublicKey = derivePublicKeyFromPrivate(keys.privateKey);
121
+ } catch {
122
+ return generateFreshIdentity(configDir, ownerHint ?? "agent");
123
+ }
124
+ let keypairRepaired = false;
125
+ if (!keys.publicKey.equals(derivedPublicKey)) {
126
+ keypairRepaired = true;
127
+ keys = { privateKey: keys.privateKey, publicKey: derivedPublicKey };
128
+ saveKeyPair(configDir, keys);
129
+ }
130
+ const loadedIdentity = loadIdentity(configDir);
131
+ const expectedAgentId = deriveAgentId(derivedPublicKey.toString("hex"));
132
+ const expectedPublicKeyHex = derivedPublicKey.toString("hex");
133
+ const identityMismatch = !loadedIdentity || loadedIdentity.public_key !== expectedPublicKeyHex || loadedIdentity.agent_id !== expectedAgentId;
134
+ if (identityMismatch) {
135
+ const repairedIdentity = buildIdentityFromPublicKey(
136
+ derivedPublicKey,
137
+ loadedIdentity?.owner ?? ownerHint ?? "agent",
138
+ loadedIdentity?.created_at
139
+ );
140
+ saveIdentity(configDir, repairedIdentity);
141
+ return { identity: repairedIdentity, keys, status: "repaired" };
142
+ }
143
+ if (ownerHint && loadedIdentity.owner !== ownerHint) {
144
+ const updatedIdentity = { ...loadedIdentity, owner: ownerHint };
145
+ saveIdentity(configDir, updatedIdentity);
146
+ return { identity: updatedIdentity, keys, status: "repaired" };
147
+ }
148
+ return { identity: loadedIdentity, keys, status: keypairRepaired ? "repaired" : "existing" };
149
+ }
150
+ function ensureIdentity(configDir, owner) {
151
+ return loadOrRepairIdentity(configDir, owner).identity;
152
+ }
153
+
19
154
  // src/credit/local-credit-ledger.ts
20
155
  var LocalCreditLedger = class {
21
156
  constructor(db) {
@@ -91,11 +226,57 @@ var LocalCreditLedger = class {
91
226
 
92
227
  // src/registry/identity-auth.ts
93
228
  var MAX_REQUEST_AGE_MS = 5 * 60 * 1e3;
94
- async function verifyIdentity(request, reply) {
95
- const publicKeyHex = request.headers["x-agent-publickey"];
96
- const signature = request.headers["x-agent-signature"];
97
- const timestamp = request.headers["x-agent-timestamp"];
98
- if (!publicKeyHex || !signature || !timestamp) {
229
+ function normalizeSignedParams(body) {
230
+ return body === void 0 ? null : body;
231
+ }
232
+ function buildIdentityPayload(method, path, timestamp, publicKeyHex, agentId, params) {
233
+ return {
234
+ method,
235
+ path,
236
+ timestamp,
237
+ publicKey: publicKeyHex,
238
+ agentId,
239
+ params: normalizeSignedParams(params)
240
+ };
241
+ }
242
+ function extractClaimedRequester(request) {
243
+ const extractFromObject = (obj) => {
244
+ const directOwner = typeof obj.owner === "string" ? obj.owner.trim() : "";
245
+ if (directOwner) return directOwner;
246
+ const directRequester = typeof obj.requester === "string" ? obj.requester.trim() : "";
247
+ if (directRequester) return directRequester;
248
+ const oldOwner = typeof obj.oldOwner === "string" ? obj.oldOwner.trim() : "";
249
+ if (oldOwner) return oldOwner;
250
+ const nestedParams = obj.params;
251
+ if (nestedParams && typeof nestedParams === "object" && !Array.isArray(nestedParams)) {
252
+ const nested = nestedParams;
253
+ const nestedOwner = typeof nested.owner === "string" ? nested.owner.trim() : "";
254
+ if (nestedOwner) return nestedOwner;
255
+ const nestedRequester = typeof nested.requester === "string" ? nested.requester.trim() : "";
256
+ if (nestedRequester) return nestedRequester;
257
+ }
258
+ return null;
259
+ };
260
+ if (request.body && typeof request.body === "object" && !Array.isArray(request.body)) {
261
+ const claimed = extractFromObject(request.body);
262
+ if (claimed) return claimed;
263
+ }
264
+ if (request.params && typeof request.params === "object" && !Array.isArray(request.params)) {
265
+ const claimed = extractFromObject(request.params);
266
+ if (claimed) return claimed;
267
+ }
268
+ return null;
269
+ }
270
+ async function verifyIdentity(request, reply, options) {
271
+ const agentIdHeader = request.headers["x-agent-id"];
272
+ const publicKeyHeader = request.headers["x-agent-publickey"];
273
+ const signatureHeader = request.headers["x-agent-signature"];
274
+ const timestampHeader = request.headers["x-agent-timestamp"];
275
+ const agentId = agentIdHeader?.trim();
276
+ const publicKeyHex = publicKeyHeader?.trim();
277
+ const signature = signatureHeader?.trim();
278
+ const timestamp = timestampHeader?.trim();
279
+ if (!agentId || !publicKeyHex || !signature || !timestamp) {
99
280
  await reply.code(401).send({ error: "Missing identity headers" });
100
281
  return false;
101
282
  }
@@ -104,12 +285,21 @@ async function verifyIdentity(request, reply) {
104
285
  await reply.code(401).send({ error: "Request expired" });
105
286
  return false;
106
287
  }
107
- const payload = {
108
- method: request.method,
109
- path: request.url,
110
- timestamp,
111
- publicKey: publicKeyHex
112
- };
288
+ if (!/^[0-9a-fA-F]+$/.test(publicKeyHex) || publicKeyHex.length % 2 !== 0) {
289
+ await reply.code(401).send({ error: "Invalid identity signature" });
290
+ return false;
291
+ }
292
+ let expectedAgentId;
293
+ try {
294
+ expectedAgentId = deriveAgentId(publicKeyHex);
295
+ } catch {
296
+ await reply.code(401).send({ error: "Invalid identity signature" });
297
+ return false;
298
+ }
299
+ if (agentId !== expectedAgentId) {
300
+ await reply.code(401).send({ error: "Invalid identity signature" });
301
+ return false;
302
+ }
113
303
  let publicKeyBuffer;
114
304
  try {
115
305
  publicKeyBuffer = Buffer.from(publicKeyHex, "hex");
@@ -117,30 +307,52 @@ async function verifyIdentity(request, reply) {
117
307
  await reply.code(401).send({ error: "Invalid identity signature" });
118
308
  return false;
119
309
  }
310
+ const knownAgent = options.agentDb ? lookupAgent(options.agentDb, agentId) : null;
311
+ if (knownAgent && knownAgent.public_key.toLowerCase() !== publicKeyHex.toLowerCase()) {
312
+ await reply.code(401).send({ error: "Invalid identity signature" });
313
+ return false;
314
+ }
315
+ const payload = buildIdentityPayload(
316
+ request.method,
317
+ request.url,
318
+ timestamp,
319
+ publicKeyHex,
320
+ agentId,
321
+ request.body
322
+ );
120
323
  const valid = verifyEscrowReceipt(payload, signature, publicKeyBuffer);
121
324
  if (!valid) {
122
325
  await reply.code(401).send({ error: "Invalid identity signature" });
123
326
  return false;
124
327
  }
328
+ const claimedRequester = extractClaimedRequester(request);
329
+ if (claimedRequester) {
330
+ const matchesAgentId = claimedRequester === agentId;
331
+ const matchesLegacyOwner = knownAgent?.legacy_owner === claimedRequester;
332
+ if (!matchesAgentId && !matchesLegacyOwner) {
333
+ await reply.code(401).send({ error: "Identity does not match requester" });
334
+ return false;
335
+ }
336
+ }
125
337
  request.agentPublicKey = publicKeyHex;
338
+ request.agentId = agentId;
126
339
  return true;
127
340
  }
128
- function identityAuthPlugin(fastify) {
129
- fastify.addHook("onRequest", async (request, reply) => {
130
- await verifyIdentity(request, reply);
341
+ function identityAuthPlugin(fastify, options = {}) {
342
+ fastify.addHook("preHandler", async (request, reply) => {
343
+ const ok = await verifyIdentity(request, reply, options);
344
+ if (!ok) {
345
+ return reply;
346
+ }
131
347
  });
132
348
  }
133
- function signRequest(method, path, body, privateKey, publicKeyHex) {
349
+ function signRequest(method, path, body, privateKey, publicKeyHex, agentIdOverride) {
134
350
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
135
- const payload = {
136
- method,
137
- path,
138
- timestamp,
139
- publicKey: publicKeyHex
140
- };
141
- void body;
351
+ const agentId = agentIdOverride ?? deriveAgentId(publicKeyHex);
352
+ const payload = buildIdentityPayload(method, path, timestamp, publicKeyHex, agentId, body);
142
353
  const signature = signEscrowReceipt(payload, privateKey);
143
354
  return {
355
+ "X-Agent-Id": agentId,
144
356
  "X-Agent-PublicKey": publicKeyHex,
145
357
  "X-Agent-Signature": signature,
146
358
  "X-Agent-Timestamp": timestamp
@@ -368,6 +580,9 @@ function createLedger(opts) {
368
580
  }
369
581
 
370
582
  export {
583
+ deriveAgentId,
584
+ loadOrRepairIdentity,
585
+ ensureIdentity,
371
586
  identityAuthPlugin,
372
587
  createLedger
373
588
  };