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.
- package/README.md +181 -200
- package/dist/chunk-5SIGMKOD.js +1086 -0
- package/dist/{chunk-6FZ4WYQL.js → chunk-JDAFLPR7.js} +15 -0
- package/dist/{chunk-J46N2TCC.js → chunk-OPRCWXD5.js} +1 -1
- package/dist/chunk-RF4A5X5U.js +62 -0
- package/dist/cli/index.js +79 -33
- package/dist/{conductor-mode-PXTMYGK5.js → conductor-mode-2F5OP7Q4.js} +3 -2
- package/dist/{execute-UP46R7KS.js → execute-6EJSVBFB.js} +4 -1
- package/dist/{execute-UAD5T3BQ.js → execute-VRTABQ6F.js} +2 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +973 -532
- package/dist/{openclaw-setup-LVSGMXDF.js → openclaw-setup-5ZWWRVF3.js} +2 -2
- package/dist/{serve-skill-6RKMVDMK.js → serve-skill-UD7TLSRN.js} +4 -1
- package/dist/{server-ZUUJT5QC.js → server-XWTGBJHV.js} +20 -17
- package/dist/{service-coordinator-2HDVHDFD.js → service-coordinator-RN7GOLLC.js} +129 -25
- package/dist/skills/agentbnb/bootstrap.js +305 -756
- package/package.json +18 -12
- package/skills/agentbnb/SKILL.md +114 -183
- package/skills/agentbnb/install.sh +0 -0
- package/dist/chunk-PMRTQ2RL.js +0 -443
- package/dist/chunk-R4F4XII4.js +0 -264
- package/dist/client-OKJJ3UP2.js +0 -19
- package/dist/{chunk-PCQEHIGF.js → chunk-UNXCKETK.js} +3 -3
package/dist/index.js
CHANGED
|
@@ -1251,11 +1251,47 @@ function openCreditDb(path = ":memory:") {
|
|
|
1251
1251
|
ensureAgentsTable(db);
|
|
1252
1252
|
return db;
|
|
1253
1253
|
}
|
|
1254
|
+
function bootstrapAgent(db, owner, amount = 100) {
|
|
1255
|
+
const canonicalOwner = canonicalizeCreditOwner(db, owner);
|
|
1256
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1257
|
+
let isNew = false;
|
|
1258
|
+
db.transaction(() => {
|
|
1259
|
+
const result = db.prepare("INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, ?, ?)").run(canonicalOwner, amount, now);
|
|
1260
|
+
if (result.changes > 0) {
|
|
1261
|
+
isNew = true;
|
|
1262
|
+
db.prepare(
|
|
1263
|
+
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
1264
|
+
).run(randomUUID3(), canonicalOwner, amount, "bootstrap", null, now);
|
|
1265
|
+
}
|
|
1266
|
+
})();
|
|
1267
|
+
if (isNew) {
|
|
1268
|
+
issueVoucher(db, canonicalOwner, 50, 30);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1254
1271
|
function getBalance(db, owner) {
|
|
1255
1272
|
const canonicalOwner = canonicalizeCreditOwner(db, owner);
|
|
1256
1273
|
const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(canonicalOwner);
|
|
1257
1274
|
return row?.balance ?? 0;
|
|
1258
1275
|
}
|
|
1276
|
+
function getTransactions(db, owner, opts = 100) {
|
|
1277
|
+
const canonicalOwner = canonicalizeCreditOwner(db, owner);
|
|
1278
|
+
const page = typeof opts === "number" ? { limit: opts } : opts;
|
|
1279
|
+
const limit = page.limit ?? 100;
|
|
1280
|
+
const conditions = ["owner = ?"];
|
|
1281
|
+
const params = [canonicalOwner];
|
|
1282
|
+
if (page.before) {
|
|
1283
|
+
conditions.push("created_at < ?");
|
|
1284
|
+
params.push(page.before);
|
|
1285
|
+
}
|
|
1286
|
+
if (page.after) {
|
|
1287
|
+
conditions.push("created_at > ?");
|
|
1288
|
+
params.push(page.after);
|
|
1289
|
+
}
|
|
1290
|
+
params.push(limit);
|
|
1291
|
+
return db.prepare(
|
|
1292
|
+
`SELECT id, owner, amount, reason, reference_id, created_at FROM credit_transactions WHERE ${conditions.join(" AND ")} ORDER BY created_at DESC LIMIT ?`
|
|
1293
|
+
).all(...params);
|
|
1294
|
+
}
|
|
1259
1295
|
function registerProvider(db, owner) {
|
|
1260
1296
|
const canonicalOwner = canonicalizeCreditOwner(db, owner);
|
|
1261
1297
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1275,6 +1311,16 @@ function getProviderBonus(providerNumber) {
|
|
|
1275
1311
|
if (providerNumber <= 200) return 1.5;
|
|
1276
1312
|
return 1;
|
|
1277
1313
|
}
|
|
1314
|
+
function issueVoucher(db, owner, amount = 50, daysValid = 30) {
|
|
1315
|
+
const canonicalOwner = canonicalizeCreditOwner(db, owner);
|
|
1316
|
+
const id = randomUUID3();
|
|
1317
|
+
const now = /* @__PURE__ */ new Date();
|
|
1318
|
+
const expiresAt = new Date(now.getTime() + daysValid * 24 * 60 * 60 * 1e3);
|
|
1319
|
+
db.prepare(
|
|
1320
|
+
"INSERT INTO demand_vouchers (id, owner, amount, remaining, created_at, expires_at, is_active) VALUES (?, ?, ?, ?, ?, ?, 1)"
|
|
1321
|
+
).run(id, canonicalOwner, amount, amount, now.toISOString(), expiresAt.toISOString());
|
|
1322
|
+
return id;
|
|
1323
|
+
}
|
|
1278
1324
|
function getActiveVoucher(db, owner) {
|
|
1279
1325
|
const canonicalOwner = canonicalizeCreditOwner(db, owner);
|
|
1280
1326
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1307,6 +1353,11 @@ function recordEarning(db, owner, amount, _cardId, receiptNonce) {
|
|
|
1307
1353
|
).run(randomUUID3(), canonicalOwner, amount, "remote_earning", receiptNonce, now);
|
|
1308
1354
|
})();
|
|
1309
1355
|
}
|
|
1356
|
+
function migrateOwner(db, oldOwner, newOwner) {
|
|
1357
|
+
if (oldOwner === newOwner) return;
|
|
1358
|
+
const canonicalNewOwner = canonicalizeCreditOwner(db, newOwner);
|
|
1359
|
+
migrateCreditOwnerData(db, oldOwner, canonicalNewOwner);
|
|
1360
|
+
}
|
|
1310
1361
|
|
|
1311
1362
|
// src/gateway/server.ts
|
|
1312
1363
|
import Fastify from "fastify";
|
|
@@ -1524,6 +1575,629 @@ function loadConfig() {
|
|
|
1524
1575
|
}
|
|
1525
1576
|
}
|
|
1526
1577
|
|
|
1578
|
+
// src/identity/identity.ts
|
|
1579
|
+
import { z as z2 } from "zod";
|
|
1580
|
+
import { createHash, createPrivateKey as createPrivateKey2, createPublicKey as createPublicKey2 } from "crypto";
|
|
1581
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
1582
|
+
import { join as join3 } from "path";
|
|
1583
|
+
|
|
1584
|
+
// src/credit/signing.ts
|
|
1585
|
+
import { generateKeyPairSync, sign, verify, createPublicKey, createPrivateKey } from "crypto";
|
|
1586
|
+
import { writeFileSync as writeFileSync2, readFileSync as readFileSync2, existsSync as existsSync2, chmodSync } from "fs";
|
|
1587
|
+
import { join as join2 } from "path";
|
|
1588
|
+
function generateKeyPair() {
|
|
1589
|
+
const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
|
|
1590
|
+
publicKeyEncoding: { type: "spki", format: "der" },
|
|
1591
|
+
privateKeyEncoding: { type: "pkcs8", format: "der" }
|
|
1592
|
+
});
|
|
1593
|
+
return {
|
|
1594
|
+
publicKey: Buffer.from(publicKey),
|
|
1595
|
+
privateKey: Buffer.from(privateKey)
|
|
1596
|
+
};
|
|
1597
|
+
}
|
|
1598
|
+
function saveKeyPair(configDir, keys) {
|
|
1599
|
+
const privatePath = join2(configDir, "private.key");
|
|
1600
|
+
const publicPath = join2(configDir, "public.key");
|
|
1601
|
+
writeFileSync2(privatePath, keys.privateKey);
|
|
1602
|
+
chmodSync(privatePath, 384);
|
|
1603
|
+
writeFileSync2(publicPath, keys.publicKey);
|
|
1604
|
+
}
|
|
1605
|
+
function loadKeyPair(configDir) {
|
|
1606
|
+
const privatePath = join2(configDir, "private.key");
|
|
1607
|
+
const publicPath = join2(configDir, "public.key");
|
|
1608
|
+
if (!existsSync2(privatePath) || !existsSync2(publicPath)) {
|
|
1609
|
+
throw new AgentBnBError("Keypair not found. Run `agentbnb init` to generate one.", "KEYPAIR_NOT_FOUND");
|
|
1610
|
+
}
|
|
1611
|
+
return {
|
|
1612
|
+
publicKey: readFileSync2(publicPath),
|
|
1613
|
+
privateKey: readFileSync2(privatePath)
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
function canonicalJson(data) {
|
|
1617
|
+
return JSON.stringify(sortForCanonicalJson(data));
|
|
1618
|
+
}
|
|
1619
|
+
function sortForCanonicalJson(value) {
|
|
1620
|
+
if (Array.isArray(value)) {
|
|
1621
|
+
return value.map((item) => sortForCanonicalJson(item));
|
|
1622
|
+
}
|
|
1623
|
+
if (value !== null && typeof value === "object") {
|
|
1624
|
+
const proto = Object.getPrototypeOf(value);
|
|
1625
|
+
if (proto === Object.prototype || proto === null) {
|
|
1626
|
+
const input = value;
|
|
1627
|
+
const output = {};
|
|
1628
|
+
const sortedKeys = Object.keys(input).sort();
|
|
1629
|
+
for (const key of sortedKeys) {
|
|
1630
|
+
output[key] = sortForCanonicalJson(input[key]);
|
|
1631
|
+
}
|
|
1632
|
+
return output;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
return value;
|
|
1636
|
+
}
|
|
1637
|
+
function signEscrowReceipt(data, privateKey) {
|
|
1638
|
+
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
1639
|
+
const keyObject = createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
|
1640
|
+
const signature = sign(null, message, keyObject);
|
|
1641
|
+
return signature.toString("base64url");
|
|
1642
|
+
}
|
|
1643
|
+
function verifyEscrowReceipt(data, signature, publicKey) {
|
|
1644
|
+
try {
|
|
1645
|
+
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
1646
|
+
const keyObject = createPublicKey({ key: publicKey, format: "der", type: "spki" });
|
|
1647
|
+
const sigBuffer = Buffer.from(signature, "base64url");
|
|
1648
|
+
return verify(null, message, keyObject, sigBuffer);
|
|
1649
|
+
} catch {
|
|
1650
|
+
return false;
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
// src/identity/identity.ts
|
|
1655
|
+
var AgentIdentitySchema = z2.object({
|
|
1656
|
+
/** Deterministic ID derived from public key: sha256(hex).slice(0, 16). */
|
|
1657
|
+
agent_id: z2.string().min(1),
|
|
1658
|
+
/** Human-readable owner name (from config or init). */
|
|
1659
|
+
owner: z2.string().min(1),
|
|
1660
|
+
/** Hex-encoded Ed25519 public key. */
|
|
1661
|
+
public_key: z2.string().min(1),
|
|
1662
|
+
/** ISO 8601 timestamp of identity creation. */
|
|
1663
|
+
created_at: z2.string().datetime(),
|
|
1664
|
+
/** Optional guarantor info if linked to a human. */
|
|
1665
|
+
guarantor: z2.object({
|
|
1666
|
+
github_login: z2.string().min(1),
|
|
1667
|
+
verified_at: z2.string().datetime()
|
|
1668
|
+
}).optional()
|
|
1669
|
+
});
|
|
1670
|
+
var AgentCertificateSchema = z2.object({
|
|
1671
|
+
identity: AgentIdentitySchema,
|
|
1672
|
+
/** ISO 8601 timestamp of certificate issuance. */
|
|
1673
|
+
issued_at: z2.string().datetime(),
|
|
1674
|
+
/** ISO 8601 timestamp of certificate expiry. */
|
|
1675
|
+
expires_at: z2.string().datetime(),
|
|
1676
|
+
/** Hex-encoded public key of the issuer (same as identity for self-signed). */
|
|
1677
|
+
issuer_public_key: z2.string().min(1),
|
|
1678
|
+
/** Base64url Ed25519 signature over { identity, issued_at, expires_at, issuer_public_key }. */
|
|
1679
|
+
signature: z2.string().min(1)
|
|
1680
|
+
});
|
|
1681
|
+
var IDENTITY_FILENAME = "identity.json";
|
|
1682
|
+
var PRIVATE_KEY_FILENAME = "private.key";
|
|
1683
|
+
var PUBLIC_KEY_FILENAME = "public.key";
|
|
1684
|
+
function derivePublicKeyFromPrivate(privateKey) {
|
|
1685
|
+
const privateKeyObject = createPrivateKey2({ key: privateKey, format: "der", type: "pkcs8" });
|
|
1686
|
+
const publicKeyObject = createPublicKey2(privateKeyObject);
|
|
1687
|
+
const publicKey = publicKeyObject.export({ format: "der", type: "spki" });
|
|
1688
|
+
return Buffer.from(publicKey);
|
|
1689
|
+
}
|
|
1690
|
+
function buildIdentityFromPublicKey(publicKey, owner, createdAt) {
|
|
1691
|
+
const publicKeyHex = publicKey.toString("hex");
|
|
1692
|
+
return {
|
|
1693
|
+
agent_id: deriveAgentId(publicKeyHex),
|
|
1694
|
+
owner,
|
|
1695
|
+
public_key: publicKeyHex,
|
|
1696
|
+
created_at: createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
function generateFreshIdentity(configDir, owner) {
|
|
1700
|
+
const keys = generateKeyPair();
|
|
1701
|
+
saveKeyPair(configDir, keys);
|
|
1702
|
+
const identity = buildIdentityFromPublicKey(keys.publicKey, owner);
|
|
1703
|
+
saveIdentity(configDir, identity);
|
|
1704
|
+
return { identity, keys, status: "generated" };
|
|
1705
|
+
}
|
|
1706
|
+
function deriveAgentId(publicKeyHex) {
|
|
1707
|
+
return createHash("sha256").update(publicKeyHex, "hex").digest("hex").slice(0, 16);
|
|
1708
|
+
}
|
|
1709
|
+
function createIdentity(configDir, owner) {
|
|
1710
|
+
if (!existsSync3(configDir)) {
|
|
1711
|
+
mkdirSync2(configDir, { recursive: true });
|
|
1712
|
+
}
|
|
1713
|
+
let keys;
|
|
1714
|
+
try {
|
|
1715
|
+
keys = loadKeyPair(configDir);
|
|
1716
|
+
} catch {
|
|
1717
|
+
keys = generateKeyPair();
|
|
1718
|
+
saveKeyPair(configDir, keys);
|
|
1719
|
+
}
|
|
1720
|
+
const publicKeyHex = keys.publicKey.toString("hex");
|
|
1721
|
+
const agentId = deriveAgentId(publicKeyHex);
|
|
1722
|
+
const identity = {
|
|
1723
|
+
agent_id: agentId,
|
|
1724
|
+
owner,
|
|
1725
|
+
public_key: publicKeyHex,
|
|
1726
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1727
|
+
};
|
|
1728
|
+
saveIdentity(configDir, identity);
|
|
1729
|
+
return identity;
|
|
1730
|
+
}
|
|
1731
|
+
function loadIdentity(configDir) {
|
|
1732
|
+
const filePath = join3(configDir, IDENTITY_FILENAME);
|
|
1733
|
+
if (!existsSync3(filePath)) return null;
|
|
1734
|
+
try {
|
|
1735
|
+
const raw = readFileSync3(filePath, "utf-8");
|
|
1736
|
+
return AgentIdentitySchema.parse(JSON.parse(raw));
|
|
1737
|
+
} catch {
|
|
1738
|
+
return null;
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
function saveIdentity(configDir, identity) {
|
|
1742
|
+
if (!existsSync3(configDir)) {
|
|
1743
|
+
mkdirSync2(configDir, { recursive: true });
|
|
1744
|
+
}
|
|
1745
|
+
const filePath = join3(configDir, IDENTITY_FILENAME);
|
|
1746
|
+
writeFileSync3(filePath, JSON.stringify(identity, null, 2), "utf-8");
|
|
1747
|
+
}
|
|
1748
|
+
function loadOrRepairIdentity(configDir, ownerHint) {
|
|
1749
|
+
if (!existsSync3(configDir)) {
|
|
1750
|
+
mkdirSync2(configDir, { recursive: true });
|
|
1751
|
+
}
|
|
1752
|
+
const identityPath = join3(configDir, IDENTITY_FILENAME);
|
|
1753
|
+
const privateKeyPath = join3(configDir, PRIVATE_KEY_FILENAME);
|
|
1754
|
+
const publicKeyPath = join3(configDir, PUBLIC_KEY_FILENAME);
|
|
1755
|
+
const hasIdentity = existsSync3(identityPath);
|
|
1756
|
+
const hasPrivateKey = existsSync3(privateKeyPath);
|
|
1757
|
+
const hasPublicKey = existsSync3(publicKeyPath);
|
|
1758
|
+
if (!hasIdentity || !hasPrivateKey || !hasPublicKey) {
|
|
1759
|
+
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
1760
|
+
}
|
|
1761
|
+
let keys;
|
|
1762
|
+
try {
|
|
1763
|
+
keys = loadKeyPair(configDir);
|
|
1764
|
+
} catch {
|
|
1765
|
+
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
1766
|
+
}
|
|
1767
|
+
let derivedPublicKey;
|
|
1768
|
+
try {
|
|
1769
|
+
derivedPublicKey = derivePublicKeyFromPrivate(keys.privateKey);
|
|
1770
|
+
} catch {
|
|
1771
|
+
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
1772
|
+
}
|
|
1773
|
+
let keypairRepaired = false;
|
|
1774
|
+
if (!keys.publicKey.equals(derivedPublicKey)) {
|
|
1775
|
+
keypairRepaired = true;
|
|
1776
|
+
keys = { privateKey: keys.privateKey, publicKey: derivedPublicKey };
|
|
1777
|
+
saveKeyPair(configDir, keys);
|
|
1778
|
+
}
|
|
1779
|
+
const loadedIdentity = loadIdentity(configDir);
|
|
1780
|
+
const expectedAgentId = deriveAgentId(derivedPublicKey.toString("hex"));
|
|
1781
|
+
const expectedPublicKeyHex = derivedPublicKey.toString("hex");
|
|
1782
|
+
const identityMismatch = !loadedIdentity || loadedIdentity.public_key !== expectedPublicKeyHex || loadedIdentity.agent_id !== expectedAgentId;
|
|
1783
|
+
if (identityMismatch) {
|
|
1784
|
+
const repairedIdentity = buildIdentityFromPublicKey(
|
|
1785
|
+
derivedPublicKey,
|
|
1786
|
+
loadedIdentity?.owner ?? ownerHint ?? "agent",
|
|
1787
|
+
loadedIdentity?.created_at
|
|
1788
|
+
);
|
|
1789
|
+
saveIdentity(configDir, repairedIdentity);
|
|
1790
|
+
return { identity: repairedIdentity, keys, status: "repaired" };
|
|
1791
|
+
}
|
|
1792
|
+
if (ownerHint && loadedIdentity.owner !== ownerHint) {
|
|
1793
|
+
const updatedIdentity = { ...loadedIdentity, owner: ownerHint };
|
|
1794
|
+
saveIdentity(configDir, updatedIdentity);
|
|
1795
|
+
return { identity: updatedIdentity, keys, status: "repaired" };
|
|
1796
|
+
}
|
|
1797
|
+
return { identity: loadedIdentity, keys, status: keypairRepaired ? "repaired" : "existing" };
|
|
1798
|
+
}
|
|
1799
|
+
function issueAgentCertificate(identity, privateKey) {
|
|
1800
|
+
const issuedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1801
|
+
const expiresAt = new Date(Date.now() + 365 * 24 * 60 * 60 * 1e3).toISOString();
|
|
1802
|
+
const payload = {
|
|
1803
|
+
identity,
|
|
1804
|
+
issued_at: issuedAt,
|
|
1805
|
+
expires_at: expiresAt,
|
|
1806
|
+
issuer_public_key: identity.public_key
|
|
1807
|
+
};
|
|
1808
|
+
const signature = signEscrowReceipt(payload, privateKey);
|
|
1809
|
+
return {
|
|
1810
|
+
identity,
|
|
1811
|
+
issued_at: issuedAt,
|
|
1812
|
+
expires_at: expiresAt,
|
|
1813
|
+
issuer_public_key: identity.public_key,
|
|
1814
|
+
signature
|
|
1815
|
+
};
|
|
1816
|
+
}
|
|
1817
|
+
function verifyAgentCertificate(cert) {
|
|
1818
|
+
if (new Date(cert.expires_at) < /* @__PURE__ */ new Date()) {
|
|
1819
|
+
return false;
|
|
1820
|
+
}
|
|
1821
|
+
const publicKeyHex = cert.issuer_public_key;
|
|
1822
|
+
const publicKeyBuf = Buffer.from(publicKeyHex, "hex");
|
|
1823
|
+
const payload = {
|
|
1824
|
+
identity: cert.identity,
|
|
1825
|
+
issued_at: cert.issued_at,
|
|
1826
|
+
expires_at: cert.expires_at,
|
|
1827
|
+
issuer_public_key: cert.issuer_public_key
|
|
1828
|
+
};
|
|
1829
|
+
return verifyEscrowReceipt(payload, cert.signature, publicKeyBuf);
|
|
1830
|
+
}
|
|
1831
|
+
function ensureIdentity(configDir, owner) {
|
|
1832
|
+
return loadOrRepairIdentity(configDir, owner).identity;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
// src/credit/local-credit-ledger.ts
|
|
1836
|
+
var LocalCreditLedger = class {
|
|
1837
|
+
constructor(db) {
|
|
1838
|
+
this.db = db;
|
|
1839
|
+
}
|
|
1840
|
+
/**
|
|
1841
|
+
* Holds credits in escrow during capability execution.
|
|
1842
|
+
*
|
|
1843
|
+
* @param owner - Agent identifier (requester).
|
|
1844
|
+
* @param amount - Number of credits to hold.
|
|
1845
|
+
* @param cardId - Capability Card ID being requested.
|
|
1846
|
+
* @returns EscrowResult with the new escrowId.
|
|
1847
|
+
* @throws {AgentBnBError} with code 'INSUFFICIENT_CREDITS' if balance < amount.
|
|
1848
|
+
*/
|
|
1849
|
+
async hold(owner, amount, cardId) {
|
|
1850
|
+
const escrowId = holdEscrow(this.db, owner, amount, cardId);
|
|
1851
|
+
return { escrowId };
|
|
1852
|
+
}
|
|
1853
|
+
/**
|
|
1854
|
+
* Settles an escrow — transfers held credits to the capability provider.
|
|
1855
|
+
*
|
|
1856
|
+
* @param escrowId - The escrow ID to settle.
|
|
1857
|
+
* @param recipientOwner - Agent identifier who will receive the credits.
|
|
1858
|
+
* @throws {AgentBnBError} with code 'ESCROW_NOT_FOUND' if escrow does not exist.
|
|
1859
|
+
* @throws {AgentBnBError} with code 'ESCROW_ALREADY_SETTLED' if escrow is not in 'held' status.
|
|
1860
|
+
*/
|
|
1861
|
+
async settle(escrowId, recipientOwner) {
|
|
1862
|
+
settleEscrow(this.db, escrowId, recipientOwner);
|
|
1863
|
+
}
|
|
1864
|
+
/**
|
|
1865
|
+
* Releases an escrow — refunds credits back to the requester.
|
|
1866
|
+
*
|
|
1867
|
+
* @param escrowId - The escrow ID to release.
|
|
1868
|
+
* @throws {AgentBnBError} with code 'ESCROW_NOT_FOUND' if escrow does not exist.
|
|
1869
|
+
* @throws {AgentBnBError} with code 'ESCROW_ALREADY_SETTLED' if escrow is not in 'held' status.
|
|
1870
|
+
*/
|
|
1871
|
+
async release(escrowId) {
|
|
1872
|
+
releaseEscrow(this.db, escrowId);
|
|
1873
|
+
}
|
|
1874
|
+
/**
|
|
1875
|
+
* Returns the current credit balance for an agent.
|
|
1876
|
+
*
|
|
1877
|
+
* @param owner - Agent identifier.
|
|
1878
|
+
* @returns Current balance in credits (0 if agent is unknown).
|
|
1879
|
+
*/
|
|
1880
|
+
async getBalance(owner) {
|
|
1881
|
+
return getBalance(this.db, owner);
|
|
1882
|
+
}
|
|
1883
|
+
/**
|
|
1884
|
+
* Returns the transaction history for an agent, newest first.
|
|
1885
|
+
*
|
|
1886
|
+
* @param owner - Agent identifier.
|
|
1887
|
+
* @param limit - Maximum number of transactions to return. Defaults to 100.
|
|
1888
|
+
* @returns Array of credit transactions ordered newest first.
|
|
1889
|
+
*/
|
|
1890
|
+
async getHistory(owner, limit) {
|
|
1891
|
+
return getTransactions(this.db, owner, limit);
|
|
1892
|
+
}
|
|
1893
|
+
/**
|
|
1894
|
+
* Grants initial credits to an agent (bootstrap grant).
|
|
1895
|
+
* Idempotent — calling multiple times has no additional effect on balance.
|
|
1896
|
+
*
|
|
1897
|
+
* @param owner - Agent identifier.
|
|
1898
|
+
* @param amount - Number of credits to grant. Defaults to 100.
|
|
1899
|
+
*/
|
|
1900
|
+
async grant(owner, amount) {
|
|
1901
|
+
bootstrapAgent(this.db, owner, amount);
|
|
1902
|
+
}
|
|
1903
|
+
async rename(oldOwner, newOwner) {
|
|
1904
|
+
migrateOwner(this.db, oldOwner, newOwner);
|
|
1905
|
+
}
|
|
1906
|
+
};
|
|
1907
|
+
|
|
1908
|
+
// src/registry/identity-auth.ts
|
|
1909
|
+
var MAX_REQUEST_AGE_MS = 5 * 60 * 1e3;
|
|
1910
|
+
function normalizeSignedParams(body) {
|
|
1911
|
+
return body === void 0 ? null : body;
|
|
1912
|
+
}
|
|
1913
|
+
function buildIdentityPayload(method, path, timestamp, publicKeyHex, agentId, params) {
|
|
1914
|
+
return {
|
|
1915
|
+
method,
|
|
1916
|
+
path,
|
|
1917
|
+
timestamp,
|
|
1918
|
+
publicKey: publicKeyHex,
|
|
1919
|
+
agentId,
|
|
1920
|
+
params: normalizeSignedParams(params)
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
function signRequest(method, path, body, privateKey, publicKeyHex, agentIdOverride) {
|
|
1924
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1925
|
+
const agentId = agentIdOverride ?? deriveAgentId(publicKeyHex);
|
|
1926
|
+
const payload = buildIdentityPayload(method, path, timestamp, publicKeyHex, agentId, body);
|
|
1927
|
+
const signature = signEscrowReceipt(payload, privateKey);
|
|
1928
|
+
return {
|
|
1929
|
+
"X-Agent-Id": agentId,
|
|
1930
|
+
"X-Agent-PublicKey": publicKeyHex,
|
|
1931
|
+
"X-Agent-Signature": signature,
|
|
1932
|
+
"X-Agent-Timestamp": timestamp
|
|
1933
|
+
};
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
// src/credit/registry-credit-ledger.ts
|
|
1937
|
+
var HTTP_TIMEOUT_MS = 1e4;
|
|
1938
|
+
var RegistryCreditLedger = class {
|
|
1939
|
+
config;
|
|
1940
|
+
constructor(config) {
|
|
1941
|
+
this.config = config;
|
|
1942
|
+
}
|
|
1943
|
+
/**
|
|
1944
|
+
* Holds credits in escrow during capability execution.
|
|
1945
|
+
*
|
|
1946
|
+
* @param owner - Agent identifier (requester).
|
|
1947
|
+
* @param amount - Number of credits to hold.
|
|
1948
|
+
* @param cardId - Capability Card ID being requested.
|
|
1949
|
+
* @returns EscrowResult with the new escrowId.
|
|
1950
|
+
* @throws {AgentBnBError} with code 'INSUFFICIENT_CREDITS' if balance < amount.
|
|
1951
|
+
*/
|
|
1952
|
+
async hold(owner, amount, cardId) {
|
|
1953
|
+
if (this.config.mode === "direct") {
|
|
1954
|
+
const escrowId = holdEscrow(this.config.db, owner, amount, cardId);
|
|
1955
|
+
return { escrowId };
|
|
1956
|
+
}
|
|
1957
|
+
const data = await this.post("/api/credits/hold", owner, {
|
|
1958
|
+
owner,
|
|
1959
|
+
amount,
|
|
1960
|
+
cardId
|
|
1961
|
+
});
|
|
1962
|
+
return { escrowId: data.escrowId };
|
|
1963
|
+
}
|
|
1964
|
+
/**
|
|
1965
|
+
* Settles an escrow — transfers held credits to the capability provider.
|
|
1966
|
+
*
|
|
1967
|
+
* @param escrowId - The escrow ID to settle.
|
|
1968
|
+
* @param recipientOwner - Agent identifier who will receive the credits.
|
|
1969
|
+
* @throws {AgentBnBError} with code 'ESCROW_NOT_FOUND' if escrow does not exist.
|
|
1970
|
+
* @throws {AgentBnBError} with code 'ESCROW_ALREADY_SETTLED' if escrow is not in 'held' status.
|
|
1971
|
+
*/
|
|
1972
|
+
async settle(escrowId, recipientOwner) {
|
|
1973
|
+
if (this.config.mode === "direct") {
|
|
1974
|
+
settleEscrow(this.config.db, escrowId, recipientOwner);
|
|
1975
|
+
return;
|
|
1976
|
+
}
|
|
1977
|
+
await this.post("/api/credits/settle", null, { escrowId, recipientOwner });
|
|
1978
|
+
}
|
|
1979
|
+
/**
|
|
1980
|
+
* Releases an escrow — refunds credits back to the requester.
|
|
1981
|
+
*
|
|
1982
|
+
* @param escrowId - The escrow ID to release.
|
|
1983
|
+
* @throws {AgentBnBError} with code 'ESCROW_NOT_FOUND' if escrow does not exist.
|
|
1984
|
+
* @throws {AgentBnBError} with code 'ESCROW_ALREADY_SETTLED' if escrow is not in 'held' status.
|
|
1985
|
+
*/
|
|
1986
|
+
async release(escrowId) {
|
|
1987
|
+
if (this.config.mode === "direct") {
|
|
1988
|
+
releaseEscrow(this.config.db, escrowId);
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
await this.post("/api/credits/release", null, { escrowId });
|
|
1992
|
+
}
|
|
1993
|
+
/**
|
|
1994
|
+
* Returns the current credit balance for an agent.
|
|
1995
|
+
*
|
|
1996
|
+
* @param owner - Agent identifier.
|
|
1997
|
+
* @returns Current balance in credits (0 if agent is unknown).
|
|
1998
|
+
*/
|
|
1999
|
+
async getBalance(owner) {
|
|
2000
|
+
if (this.config.mode === "direct") {
|
|
2001
|
+
return getBalance(this.config.db, owner);
|
|
2002
|
+
}
|
|
2003
|
+
const data = await this.get(`/api/credits/${owner}`, owner);
|
|
2004
|
+
return data.balance;
|
|
2005
|
+
}
|
|
2006
|
+
/**
|
|
2007
|
+
* Returns the transaction history for an agent, newest first.
|
|
2008
|
+
*
|
|
2009
|
+
* @param owner - Agent identifier.
|
|
2010
|
+
* @param limit - Maximum number of transactions to return. Defaults to 100.
|
|
2011
|
+
* @returns Array of credit transactions ordered newest first.
|
|
2012
|
+
*/
|
|
2013
|
+
async getHistory(owner, limit = 100) {
|
|
2014
|
+
if (this.config.mode === "direct") {
|
|
2015
|
+
return getTransactions(this.config.db, owner, limit);
|
|
2016
|
+
}
|
|
2017
|
+
const data = await this.get(
|
|
2018
|
+
`/api/credits/${owner}/history?limit=${limit}`,
|
|
2019
|
+
owner
|
|
2020
|
+
);
|
|
2021
|
+
return data.transactions;
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* Grants initial credits to an agent (bootstrap grant).
|
|
2025
|
+
* Idempotent — calling multiple times has no additional effect on balance.
|
|
2026
|
+
*
|
|
2027
|
+
* @param owner - Agent identifier.
|
|
2028
|
+
* @param amount - Number of credits to grant. Defaults to 100.
|
|
2029
|
+
*/
|
|
2030
|
+
async grant(owner, amount = 100) {
|
|
2031
|
+
if (this.config.mode === "direct") {
|
|
2032
|
+
bootstrapAgent(this.config.db, owner, amount);
|
|
2033
|
+
return;
|
|
2034
|
+
}
|
|
2035
|
+
await this.post("/api/credits/grant", owner, { owner, amount });
|
|
2036
|
+
}
|
|
2037
|
+
/**
|
|
2038
|
+
* Renames an owner — migrates balance, transactions, and escrows.
|
|
2039
|
+
*/
|
|
2040
|
+
async rename(oldOwner, newOwner) {
|
|
2041
|
+
if (oldOwner === newOwner) return;
|
|
2042
|
+
if (this.config.mode === "direct") {
|
|
2043
|
+
migrateOwner(this.config.db, oldOwner, newOwner);
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
2046
|
+
await this.post("/api/credits/rename", null, { oldOwner, newOwner });
|
|
2047
|
+
}
|
|
2048
|
+
// ─── Private HTTP helpers ─────────────────────────────────────────────────
|
|
2049
|
+
/**
|
|
2050
|
+
* Makes an authenticated POST request to the Registry HTTP API.
|
|
2051
|
+
* Includes a 10s timeout via AbortController.
|
|
2052
|
+
*
|
|
2053
|
+
* @param path - API path (e.g., '/api/credits/hold').
|
|
2054
|
+
* @param ownerForHeader - Agent owner identifier for X-Agent-Owner header, or null to omit.
|
|
2055
|
+
* @param body - JSON body to send.
|
|
2056
|
+
* @returns Parsed JSON response body.
|
|
2057
|
+
* @throws {AgentBnBError} on non-2xx responses or network errors.
|
|
2058
|
+
*/
|
|
2059
|
+
async post(path, ownerForHeader, body) {
|
|
2060
|
+
const cfg = this.config;
|
|
2061
|
+
const controller = new AbortController();
|
|
2062
|
+
const timeoutId = setTimeout(() => controller.abort(), HTTP_TIMEOUT_MS);
|
|
2063
|
+
try {
|
|
2064
|
+
const authHeaders = signRequest("POST", path, body, cfg.privateKey, cfg.ownerPublicKey);
|
|
2065
|
+
const headers = {
|
|
2066
|
+
"Content-Type": "application/json",
|
|
2067
|
+
...authHeaders
|
|
2068
|
+
};
|
|
2069
|
+
void ownerForHeader;
|
|
2070
|
+
const res = await fetch(`${cfg.registryUrl}${path}`, {
|
|
2071
|
+
method: "POST",
|
|
2072
|
+
headers,
|
|
2073
|
+
body: JSON.stringify(body),
|
|
2074
|
+
signal: controller.signal
|
|
2075
|
+
});
|
|
2076
|
+
return await this.handleResponse(res);
|
|
2077
|
+
} catch (err) {
|
|
2078
|
+
if (err instanceof AgentBnBError) throw err;
|
|
2079
|
+
throw new AgentBnBError(
|
|
2080
|
+
`Registry unreachable: ${err.message}`,
|
|
2081
|
+
"REGISTRY_UNREACHABLE"
|
|
2082
|
+
);
|
|
2083
|
+
} finally {
|
|
2084
|
+
clearTimeout(timeoutId);
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
/**
|
|
2088
|
+
* Makes an authenticated GET request to the Registry HTTP API.
|
|
2089
|
+
* Includes a 10s timeout via AbortController.
|
|
2090
|
+
*
|
|
2091
|
+
* @param path - API path (e.g., '/api/credits/owner-id').
|
|
2092
|
+
* @param owner - Agent owner identifier for X-Agent-Owner header.
|
|
2093
|
+
* @returns Parsed JSON response body.
|
|
2094
|
+
* @throws {AgentBnBError} on non-2xx responses or network errors.
|
|
2095
|
+
*/
|
|
2096
|
+
async get(path, owner) {
|
|
2097
|
+
const cfg = this.config;
|
|
2098
|
+
const controller = new AbortController();
|
|
2099
|
+
const timeoutId = setTimeout(() => controller.abort(), HTTP_TIMEOUT_MS);
|
|
2100
|
+
try {
|
|
2101
|
+
const authHeaders = signRequest("GET", path, null, cfg.privateKey, cfg.ownerPublicKey);
|
|
2102
|
+
void owner;
|
|
2103
|
+
const res = await fetch(`${cfg.registryUrl}${path}`, {
|
|
2104
|
+
method: "GET",
|
|
2105
|
+
headers: {
|
|
2106
|
+
"Content-Type": "application/json",
|
|
2107
|
+
...authHeaders
|
|
2108
|
+
},
|
|
2109
|
+
signal: controller.signal
|
|
2110
|
+
});
|
|
2111
|
+
return await this.handleResponse(res);
|
|
2112
|
+
} catch (err) {
|
|
2113
|
+
if (err instanceof AgentBnBError) throw err;
|
|
2114
|
+
throw new AgentBnBError(
|
|
2115
|
+
`Registry unreachable: ${err.message}`,
|
|
2116
|
+
"REGISTRY_UNREACHABLE"
|
|
2117
|
+
);
|
|
2118
|
+
} finally {
|
|
2119
|
+
clearTimeout(timeoutId);
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
/**
|
|
2123
|
+
* Handles an HTTP response — returns parsed JSON on 2xx, throws AgentBnBError on error.
|
|
2124
|
+
*/
|
|
2125
|
+
async handleResponse(res) {
|
|
2126
|
+
const json = await res.json();
|
|
2127
|
+
if (!res.ok) {
|
|
2128
|
+
const code = typeof json["code"] === "string" ? json["code"] : "REGISTRY_ERROR";
|
|
2129
|
+
const message = typeof json["error"] === "string" ? json["error"] : `HTTP ${res.status}`;
|
|
2130
|
+
throw new AgentBnBError(message, code);
|
|
2131
|
+
}
|
|
2132
|
+
return json;
|
|
2133
|
+
}
|
|
2134
|
+
};
|
|
2135
|
+
|
|
2136
|
+
// src/credit/create-ledger.ts
|
|
2137
|
+
function createLedger(opts) {
|
|
2138
|
+
if ("registryUrl" in opts && opts.registryUrl !== void 0) {
|
|
2139
|
+
return new RegistryCreditLedger({
|
|
2140
|
+
mode: "http",
|
|
2141
|
+
registryUrl: opts.registryUrl,
|
|
2142
|
+
ownerPublicKey: opts.ownerPublicKey,
|
|
2143
|
+
privateKey: opts.privateKey
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2146
|
+
if ("db" in opts && opts.db !== void 0) {
|
|
2147
|
+
return new RegistryCreditLedger({
|
|
2148
|
+
mode: "direct",
|
|
2149
|
+
db: opts.db
|
|
2150
|
+
});
|
|
2151
|
+
}
|
|
2152
|
+
const db = openCreditDb(opts.creditDbPath);
|
|
2153
|
+
return new LocalCreditLedger(db);
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
// src/credit/registry-sync.ts
|
|
2157
|
+
async function syncCreditsFromRegistry(config, localDb) {
|
|
2158
|
+
if (!config.registry) {
|
|
2159
|
+
return { synced: false, error: "no registry configured" };
|
|
2160
|
+
}
|
|
2161
|
+
try {
|
|
2162
|
+
const configDir = getConfigDir();
|
|
2163
|
+
const { identity, keys } = loadOrRepairIdentity(configDir, config.owner);
|
|
2164
|
+
const ledger = createLedger({
|
|
2165
|
+
registryUrl: config.registry,
|
|
2166
|
+
ownerPublicKey: identity.public_key,
|
|
2167
|
+
privateKey: keys.privateKey
|
|
2168
|
+
});
|
|
2169
|
+
const [remoteBalance, remoteHistory] = await Promise.all([
|
|
2170
|
+
ledger.getBalance(config.owner),
|
|
2171
|
+
ledger.getHistory(config.owner, 50)
|
|
2172
|
+
]);
|
|
2173
|
+
const localWas = getBalance(localDb, config.owner);
|
|
2174
|
+
localDb.transaction(() => {
|
|
2175
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2176
|
+
const canonicalOwner = canonicalizeCreditOwner(localDb, config.owner);
|
|
2177
|
+
localDb.prepare(
|
|
2178
|
+
"INSERT OR REPLACE INTO credit_balances (owner, balance, updated_at) VALUES (?, ?, ?)"
|
|
2179
|
+
).run(canonicalOwner, remoteBalance, now);
|
|
2180
|
+
const insertTxn = localDb.prepare(
|
|
2181
|
+
"INSERT OR IGNORE INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
2182
|
+
);
|
|
2183
|
+
for (const txn of remoteHistory) {
|
|
2184
|
+
insertTxn.run(
|
|
2185
|
+
txn.id,
|
|
2186
|
+
txn.owner,
|
|
2187
|
+
txn.amount,
|
|
2188
|
+
txn.reason,
|
|
2189
|
+
txn.reference_id,
|
|
2190
|
+
txn.created_at
|
|
2191
|
+
);
|
|
2192
|
+
}
|
|
2193
|
+
})();
|
|
2194
|
+
return { synced: true, remoteBalance, localWas };
|
|
2195
|
+
} catch (err) {
|
|
2196
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2197
|
+
return { synced: false, error: message };
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
|
|
1527
2201
|
// src/cli/remote-registry.ts
|
|
1528
2202
|
var RegistryTimeoutError = class extends AgentBnBError {
|
|
1529
2203
|
constructor(url) {
|
|
@@ -1705,6 +2379,18 @@ async function executeCapabilityRequest(opts) {
|
|
|
1705
2379
|
};
|
|
1706
2380
|
}
|
|
1707
2381
|
} else {
|
|
2382
|
+
const cfg = loadConfig();
|
|
2383
|
+
if (cfg?.registry) {
|
|
2384
|
+
try {
|
|
2385
|
+
await Promise.race([
|
|
2386
|
+
syncCreditsFromRegistry(cfg, creditDb),
|
|
2387
|
+
new Promise(
|
|
2388
|
+
(_, reject) => setTimeout(() => reject(new Error("sync timeout")), 2e3)
|
|
2389
|
+
)
|
|
2390
|
+
]);
|
|
2391
|
+
} catch {
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
1708
2394
|
try {
|
|
1709
2395
|
const balance = getBalance(creditDb, requester);
|
|
1710
2396
|
if (balance < creditsNeeded) {
|
|
@@ -1785,125 +2471,55 @@ async function executeCapabilityRequest(opts) {
|
|
|
1785
2471
|
let targetSkillId = resolvedSkillId ?? skillId;
|
|
1786
2472
|
if (!targetSkillId) {
|
|
1787
2473
|
const available = skillExecutor.listSkills();
|
|
1788
|
-
if (available.length > 0) {
|
|
1789
|
-
targetSkillId = available[0];
|
|
1790
|
-
} else {
|
|
1791
|
-
return handleFailure(
|
|
1792
|
-
"failure",
|
|
1793
|
-
Date.now() - startMs,
|
|
1794
|
-
"No skill_id specified and no skills registered on this provider.",
|
|
1795
|
-
"not_found"
|
|
1796
|
-
);
|
|
1797
|
-
}
|
|
1798
|
-
}
|
|
1799
|
-
try {
|
|
1800
|
-
const execResult = await skillExecutor.execute(targetSkillId, params, onProgress);
|
|
1801
|
-
if (!execResult.success) {
|
|
1802
|
-
return handleFailure("failure", execResult.latency_ms, execResult.error ?? "Execution failed", "bad_execution");
|
|
1803
|
-
}
|
|
1804
|
-
return handleSuccess(execResult.result, execResult.latency_ms);
|
|
1805
|
-
} catch (err) {
|
|
1806
|
-
const message = err instanceof Error ? err.message : "Execution error";
|
|
1807
|
-
return handleFailure("failure", Date.now() - startMs, message, "bad_execution");
|
|
1808
|
-
}
|
|
1809
|
-
}
|
|
1810
|
-
if (!handlerUrl) {
|
|
1811
|
-
return handleFailure("failure", Date.now() - startMs, "No skill executor or handler URL configured", "bad_execution");
|
|
1812
|
-
}
|
|
1813
|
-
const controller = new AbortController();
|
|
1814
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
1815
|
-
try {
|
|
1816
|
-
const response = await fetch(handlerUrl, {
|
|
1817
|
-
method: "POST",
|
|
1818
|
-
headers: { "Content-Type": "application/json" },
|
|
1819
|
-
body: JSON.stringify({ card_id: cardId, skill_id: resolvedSkillId, params }),
|
|
1820
|
-
signal: controller.signal
|
|
1821
|
-
});
|
|
1822
|
-
clearTimeout(timer);
|
|
1823
|
-
if (!response.ok) {
|
|
1824
|
-
return handleFailure("failure", Date.now() - startMs, `Handler returned ${response.status}`, "bad_execution");
|
|
1825
|
-
}
|
|
1826
|
-
const result = await response.json();
|
|
1827
|
-
return handleSuccess(result, Date.now() - startMs);
|
|
1828
|
-
} catch (err) {
|
|
1829
|
-
clearTimeout(timer);
|
|
1830
|
-
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
1831
|
-
return handleFailure(
|
|
1832
|
-
isTimeout ? "timeout" : "failure",
|
|
1833
|
-
Date.now() - startMs,
|
|
1834
|
-
isTimeout ? "Execution timeout" : "Handler error",
|
|
1835
|
-
isTimeout ? "timeout" : "bad_execution"
|
|
1836
|
-
);
|
|
1837
|
-
}
|
|
1838
|
-
}
|
|
1839
|
-
|
|
1840
|
-
// src/credit/signing.ts
|
|
1841
|
-
import { generateKeyPairSync, sign, verify, createPublicKey, createPrivateKey } from "crypto";
|
|
1842
|
-
import { writeFileSync as writeFileSync2, readFileSync as readFileSync2, existsSync as existsSync2, chmodSync } from "fs";
|
|
1843
|
-
import { join as join2 } from "path";
|
|
1844
|
-
function generateKeyPair() {
|
|
1845
|
-
const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
|
|
1846
|
-
publicKeyEncoding: { type: "spki", format: "der" },
|
|
1847
|
-
privateKeyEncoding: { type: "pkcs8", format: "der" }
|
|
1848
|
-
});
|
|
1849
|
-
return {
|
|
1850
|
-
publicKey: Buffer.from(publicKey),
|
|
1851
|
-
privateKey: Buffer.from(privateKey)
|
|
1852
|
-
};
|
|
1853
|
-
}
|
|
1854
|
-
function saveKeyPair(configDir, keys) {
|
|
1855
|
-
const privatePath = join2(configDir, "private.key");
|
|
1856
|
-
const publicPath = join2(configDir, "public.key");
|
|
1857
|
-
writeFileSync2(privatePath, keys.privateKey);
|
|
1858
|
-
chmodSync(privatePath, 384);
|
|
1859
|
-
writeFileSync2(publicPath, keys.publicKey);
|
|
1860
|
-
}
|
|
1861
|
-
function loadKeyPair(configDir) {
|
|
1862
|
-
const privatePath = join2(configDir, "private.key");
|
|
1863
|
-
const publicPath = join2(configDir, "public.key");
|
|
1864
|
-
if (!existsSync2(privatePath) || !existsSync2(publicPath)) {
|
|
1865
|
-
throw new AgentBnBError("Keypair not found. Run `agentbnb init` to generate one.", "KEYPAIR_NOT_FOUND");
|
|
1866
|
-
}
|
|
1867
|
-
return {
|
|
1868
|
-
publicKey: readFileSync2(publicPath),
|
|
1869
|
-
privateKey: readFileSync2(privatePath)
|
|
1870
|
-
};
|
|
1871
|
-
}
|
|
1872
|
-
function canonicalJson(data) {
|
|
1873
|
-
return JSON.stringify(sortForCanonicalJson(data));
|
|
1874
|
-
}
|
|
1875
|
-
function sortForCanonicalJson(value) {
|
|
1876
|
-
if (Array.isArray(value)) {
|
|
1877
|
-
return value.map((item) => sortForCanonicalJson(item));
|
|
1878
|
-
}
|
|
1879
|
-
if (value !== null && typeof value === "object") {
|
|
1880
|
-
const proto = Object.getPrototypeOf(value);
|
|
1881
|
-
if (proto === Object.prototype || proto === null) {
|
|
1882
|
-
const input = value;
|
|
1883
|
-
const output = {};
|
|
1884
|
-
const sortedKeys = Object.keys(input).sort();
|
|
1885
|
-
for (const key of sortedKeys) {
|
|
1886
|
-
output[key] = sortForCanonicalJson(input[key]);
|
|
2474
|
+
if (available.length > 0) {
|
|
2475
|
+
targetSkillId = available[0];
|
|
2476
|
+
} else {
|
|
2477
|
+
return handleFailure(
|
|
2478
|
+
"failure",
|
|
2479
|
+
Date.now() - startMs,
|
|
2480
|
+
"No skill_id specified and no skills registered on this provider.",
|
|
2481
|
+
"not_found"
|
|
2482
|
+
);
|
|
1887
2483
|
}
|
|
1888
|
-
|
|
2484
|
+
}
|
|
2485
|
+
try {
|
|
2486
|
+
const execResult = await skillExecutor.execute(targetSkillId, params, onProgress);
|
|
2487
|
+
if (!execResult.success) {
|
|
2488
|
+
return handleFailure("failure", execResult.latency_ms, execResult.error ?? "Execution failed", "bad_execution");
|
|
2489
|
+
}
|
|
2490
|
+
return handleSuccess(execResult.result, execResult.latency_ms);
|
|
2491
|
+
} catch (err) {
|
|
2492
|
+
const message = err instanceof Error ? err.message : "Execution error";
|
|
2493
|
+
return handleFailure("failure", Date.now() - startMs, message, "bad_execution");
|
|
1889
2494
|
}
|
|
1890
2495
|
}
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
const
|
|
1895
|
-
const
|
|
1896
|
-
const signature = sign(null, message, keyObject);
|
|
1897
|
-
return signature.toString("base64url");
|
|
1898
|
-
}
|
|
1899
|
-
function verifyEscrowReceipt(data, signature, publicKey) {
|
|
2496
|
+
if (!handlerUrl) {
|
|
2497
|
+
return handleFailure("failure", Date.now() - startMs, "No skill executor or handler URL configured", "bad_execution");
|
|
2498
|
+
}
|
|
2499
|
+
const controller = new AbortController();
|
|
2500
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
1900
2501
|
try {
|
|
1901
|
-
const
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
2502
|
+
const response = await fetch(handlerUrl, {
|
|
2503
|
+
method: "POST",
|
|
2504
|
+
headers: { "Content-Type": "application/json" },
|
|
2505
|
+
body: JSON.stringify({ card_id: cardId, skill_id: resolvedSkillId, params }),
|
|
2506
|
+
signal: controller.signal
|
|
2507
|
+
});
|
|
2508
|
+
clearTimeout(timer);
|
|
2509
|
+
if (!response.ok) {
|
|
2510
|
+
return handleFailure("failure", Date.now() - startMs, `Handler returned ${response.status}`, "bad_execution");
|
|
2511
|
+
}
|
|
2512
|
+
const result = await response.json();
|
|
2513
|
+
return handleSuccess(result, Date.now() - startMs);
|
|
2514
|
+
} catch (err) {
|
|
2515
|
+
clearTimeout(timer);
|
|
2516
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
2517
|
+
return handleFailure(
|
|
2518
|
+
isTimeout ? "timeout" : "failure",
|
|
2519
|
+
Date.now() - startMs,
|
|
2520
|
+
isTimeout ? "Execution timeout" : "Handler error",
|
|
2521
|
+
isTimeout ? "timeout" : "bad_execution"
|
|
2522
|
+
);
|
|
1907
2523
|
}
|
|
1908
2524
|
}
|
|
1909
2525
|
|
|
@@ -2217,127 +2833,127 @@ function createSkillExecutor(configs, modes, concurrencyGuard) {
|
|
|
2217
2833
|
}
|
|
2218
2834
|
|
|
2219
2835
|
// src/skills/skill-config.ts
|
|
2220
|
-
import { z as
|
|
2836
|
+
import { z as z3 } from "zod";
|
|
2221
2837
|
import yaml from "js-yaml";
|
|
2222
|
-
var CapacitySchema =
|
|
2223
|
-
max_concurrent:
|
|
2838
|
+
var CapacitySchema = z3.object({
|
|
2839
|
+
max_concurrent: z3.number().positive().int().optional()
|
|
2224
2840
|
}).optional();
|
|
2225
|
-
var PricingSchema =
|
|
2226
|
-
credits_per_call:
|
|
2227
|
-
credits_per_minute:
|
|
2228
|
-
free_tier:
|
|
2841
|
+
var PricingSchema = z3.object({
|
|
2842
|
+
credits_per_call: z3.number().nonnegative(),
|
|
2843
|
+
credits_per_minute: z3.number().nonnegative().optional(),
|
|
2844
|
+
free_tier: z3.number().nonnegative().optional()
|
|
2229
2845
|
});
|
|
2230
|
-
var ApiAuthSchema =
|
|
2231
|
-
|
|
2232
|
-
type:
|
|
2233
|
-
token:
|
|
2846
|
+
var ApiAuthSchema = z3.discriminatedUnion("type", [
|
|
2847
|
+
z3.object({
|
|
2848
|
+
type: z3.literal("bearer"),
|
|
2849
|
+
token: z3.string()
|
|
2234
2850
|
}),
|
|
2235
|
-
|
|
2236
|
-
type:
|
|
2237
|
-
header:
|
|
2238
|
-
key:
|
|
2851
|
+
z3.object({
|
|
2852
|
+
type: z3.literal("apikey"),
|
|
2853
|
+
header: z3.string().default("X-API-Key"),
|
|
2854
|
+
key: z3.string()
|
|
2239
2855
|
}),
|
|
2240
|
-
|
|
2241
|
-
type:
|
|
2242
|
-
username:
|
|
2243
|
-
password:
|
|
2856
|
+
z3.object({
|
|
2857
|
+
type: z3.literal("basic"),
|
|
2858
|
+
username: z3.string(),
|
|
2859
|
+
password: z3.string()
|
|
2244
2860
|
})
|
|
2245
2861
|
]);
|
|
2246
2862
|
var CapabilityDeclarationSchema = {
|
|
2247
|
-
description:
|
|
2248
|
-
capability_types:
|
|
2249
|
-
requires_capabilities:
|
|
2250
|
-
visibility:
|
|
2251
|
-
expected_duration_ms:
|
|
2863
|
+
description: z3.string().optional(),
|
|
2864
|
+
capability_types: z3.array(z3.string()).optional(),
|
|
2865
|
+
requires_capabilities: z3.array(z3.string()).optional(),
|
|
2866
|
+
visibility: z3.enum(["public", "private"]).optional(),
|
|
2867
|
+
expected_duration_ms: z3.number().positive().optional()
|
|
2252
2868
|
};
|
|
2253
|
-
var ApiSkillConfigSchema =
|
|
2254
|
-
id:
|
|
2255
|
-
type:
|
|
2256
|
-
name:
|
|
2257
|
-
endpoint:
|
|
2258
|
-
method:
|
|
2869
|
+
var ApiSkillConfigSchema = z3.object({
|
|
2870
|
+
id: z3.string().min(1),
|
|
2871
|
+
type: z3.literal("api"),
|
|
2872
|
+
name: z3.string().min(1),
|
|
2873
|
+
endpoint: z3.string().min(1),
|
|
2874
|
+
method: z3.enum(["GET", "POST", "PUT", "DELETE"]),
|
|
2259
2875
|
auth: ApiAuthSchema.optional(),
|
|
2260
|
-
input_mapping:
|
|
2261
|
-
output_mapping:
|
|
2876
|
+
input_mapping: z3.record(z3.string()).default({}),
|
|
2877
|
+
output_mapping: z3.record(z3.string()).default({}),
|
|
2262
2878
|
pricing: PricingSchema,
|
|
2263
|
-
timeout_ms:
|
|
2264
|
-
retries:
|
|
2265
|
-
provider:
|
|
2879
|
+
timeout_ms: z3.number().positive().default(3e4),
|
|
2880
|
+
retries: z3.number().nonnegative().int().default(0),
|
|
2881
|
+
provider: z3.string().optional(),
|
|
2266
2882
|
capacity: CapacitySchema,
|
|
2267
2883
|
...CapabilityDeclarationSchema
|
|
2268
2884
|
});
|
|
2269
|
-
var PipelineStepSchema =
|
|
2270
|
-
|
|
2271
|
-
skill_id:
|
|
2272
|
-
input_mapping:
|
|
2885
|
+
var PipelineStepSchema = z3.union([
|
|
2886
|
+
z3.object({
|
|
2887
|
+
skill_id: z3.string().min(1),
|
|
2888
|
+
input_mapping: z3.record(z3.string()).default({})
|
|
2273
2889
|
}),
|
|
2274
|
-
|
|
2275
|
-
command:
|
|
2276
|
-
input_mapping:
|
|
2890
|
+
z3.object({
|
|
2891
|
+
command: z3.string().min(1),
|
|
2892
|
+
input_mapping: z3.record(z3.string()).default({})
|
|
2277
2893
|
})
|
|
2278
2894
|
]);
|
|
2279
|
-
var PipelineSkillConfigSchema =
|
|
2280
|
-
id:
|
|
2281
|
-
type:
|
|
2282
|
-
name:
|
|
2283
|
-
steps:
|
|
2895
|
+
var PipelineSkillConfigSchema = z3.object({
|
|
2896
|
+
id: z3.string().min(1),
|
|
2897
|
+
type: z3.literal("pipeline"),
|
|
2898
|
+
name: z3.string().min(1),
|
|
2899
|
+
steps: z3.array(PipelineStepSchema).min(1),
|
|
2284
2900
|
pricing: PricingSchema,
|
|
2285
|
-
timeout_ms:
|
|
2901
|
+
timeout_ms: z3.number().positive().optional(),
|
|
2286
2902
|
capacity: CapacitySchema,
|
|
2287
2903
|
...CapabilityDeclarationSchema
|
|
2288
2904
|
});
|
|
2289
|
-
var OpenClawSkillConfigSchema =
|
|
2290
|
-
id:
|
|
2291
|
-
type:
|
|
2292
|
-
name:
|
|
2293
|
-
agent_name:
|
|
2294
|
-
channel:
|
|
2905
|
+
var OpenClawSkillConfigSchema = z3.object({
|
|
2906
|
+
id: z3.string().min(1),
|
|
2907
|
+
type: z3.literal("openclaw"),
|
|
2908
|
+
name: z3.string().min(1),
|
|
2909
|
+
agent_name: z3.string().min(1),
|
|
2910
|
+
channel: z3.enum(["telegram", "webhook", "process"]),
|
|
2295
2911
|
pricing: PricingSchema,
|
|
2296
|
-
timeout_ms:
|
|
2912
|
+
timeout_ms: z3.number().positive().optional(),
|
|
2297
2913
|
capacity: CapacitySchema,
|
|
2298
2914
|
...CapabilityDeclarationSchema
|
|
2299
2915
|
});
|
|
2300
|
-
var ClaudeCodeConfigSchema =
|
|
2916
|
+
var ClaudeCodeConfigSchema = z3.object({
|
|
2301
2917
|
/** Optional system prompt passed via `-p` flag. */
|
|
2302
|
-
system_prompt:
|
|
2918
|
+
system_prompt: z3.string().optional(),
|
|
2303
2919
|
/** Model to use (e.g. 'claude-opus-4-6', 'claude-sonnet-4-6'). */
|
|
2304
|
-
model:
|
|
2920
|
+
model: z3.string().optional(),
|
|
2305
2921
|
/** When true, passes `--dangerously-skip-permissions` to claude CLI. */
|
|
2306
|
-
auto_mode:
|
|
2922
|
+
auto_mode: z3.boolean().default(false)
|
|
2307
2923
|
});
|
|
2308
|
-
var CommandSkillConfigSchema =
|
|
2309
|
-
id:
|
|
2310
|
-
type:
|
|
2311
|
-
name:
|
|
2312
|
-
command:
|
|
2313
|
-
output_type:
|
|
2314
|
-
allowed_commands:
|
|
2315
|
-
working_dir:
|
|
2924
|
+
var CommandSkillConfigSchema = z3.object({
|
|
2925
|
+
id: z3.string().min(1),
|
|
2926
|
+
type: z3.literal("command"),
|
|
2927
|
+
name: z3.string().min(1),
|
|
2928
|
+
command: z3.string().min(1),
|
|
2929
|
+
output_type: z3.enum(["json", "text", "file"]),
|
|
2930
|
+
allowed_commands: z3.array(z3.string()).optional(),
|
|
2931
|
+
working_dir: z3.string().optional(),
|
|
2316
2932
|
claude_code: ClaudeCodeConfigSchema.optional(),
|
|
2317
|
-
timeout_ms:
|
|
2933
|
+
timeout_ms: z3.number().positive().default(3e4),
|
|
2318
2934
|
pricing: PricingSchema,
|
|
2319
2935
|
capacity: CapacitySchema,
|
|
2320
2936
|
...CapabilityDeclarationSchema
|
|
2321
2937
|
});
|
|
2322
|
-
var ConductorSkillConfigSchema =
|
|
2323
|
-
id:
|
|
2324
|
-
type:
|
|
2325
|
-
name:
|
|
2326
|
-
conductor_skill:
|
|
2938
|
+
var ConductorSkillConfigSchema = z3.object({
|
|
2939
|
+
id: z3.string().min(1),
|
|
2940
|
+
type: z3.literal("conductor"),
|
|
2941
|
+
name: z3.string().min(1),
|
|
2942
|
+
conductor_skill: z3.enum(["orchestrate", "plan"]),
|
|
2327
2943
|
pricing: PricingSchema,
|
|
2328
|
-
timeout_ms:
|
|
2944
|
+
timeout_ms: z3.number().positive().optional(),
|
|
2329
2945
|
capacity: CapacitySchema,
|
|
2330
2946
|
...CapabilityDeclarationSchema
|
|
2331
2947
|
});
|
|
2332
|
-
var SkillConfigSchema =
|
|
2948
|
+
var SkillConfigSchema = z3.discriminatedUnion("type", [
|
|
2333
2949
|
ApiSkillConfigSchema,
|
|
2334
2950
|
PipelineSkillConfigSchema,
|
|
2335
2951
|
OpenClawSkillConfigSchema,
|
|
2336
2952
|
CommandSkillConfigSchema,
|
|
2337
2953
|
ConductorSkillConfigSchema
|
|
2338
2954
|
]);
|
|
2339
|
-
var SkillsFileSchema =
|
|
2340
|
-
skills:
|
|
2955
|
+
var SkillsFileSchema = z3.object({
|
|
2956
|
+
skills: z3.array(SkillConfigSchema)
|
|
2341
2957
|
});
|
|
2342
2958
|
function expandEnvVars(value) {
|
|
2343
2959
|
return value.replace(/\$\{([^}]+)\}/g, (_match, varName) => {
|
|
@@ -2916,27 +3532,37 @@ var KILL_GRACE_MS = 5e3;
|
|
|
2916
3532
|
function shellEscape2(value) {
|
|
2917
3533
|
return "'" + value.replace(/'/g, "'\\''") + "'";
|
|
2918
3534
|
}
|
|
2919
|
-
function
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
current = current[parseInt(bracketMatch[2], 10)];
|
|
2930
|
-
} else {
|
|
2931
|
-
return "";
|
|
2932
|
-
}
|
|
3535
|
+
function resolveExpression(expr, context) {
|
|
3536
|
+
const parts = expr.split(".");
|
|
3537
|
+
let current = context;
|
|
3538
|
+
for (const part of parts) {
|
|
3539
|
+
if (current === null || typeof current !== "object") return void 0;
|
|
3540
|
+
const bracketMatch = part.match(/^(\w+)\[(\d+)\]$/);
|
|
3541
|
+
if (bracketMatch) {
|
|
3542
|
+
current = current[bracketMatch[1]];
|
|
3543
|
+
if (Array.isArray(current)) {
|
|
3544
|
+
current = current[parseInt(bracketMatch[2], 10)];
|
|
2933
3545
|
} else {
|
|
2934
|
-
|
|
3546
|
+
return void 0;
|
|
3547
|
+
}
|
|
3548
|
+
} else {
|
|
3549
|
+
current = current[part];
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3552
|
+
return current;
|
|
3553
|
+
}
|
|
3554
|
+
function safeInterpolateCommand2(template, context) {
|
|
3555
|
+
const result = template.replace(
|
|
3556
|
+
/(--[\w-]+\s+)?\$\{([^}]+)\}/g,
|
|
3557
|
+
(_match, flagPrefix, expr) => {
|
|
3558
|
+
const value = resolveExpression(expr, context);
|
|
3559
|
+
if (value === void 0 || value === null) {
|
|
3560
|
+
return "";
|
|
2935
3561
|
}
|
|
3562
|
+
return (flagPrefix ?? "") + shellEscape2(String(value));
|
|
2936
3563
|
}
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
});
|
|
3564
|
+
);
|
|
3565
|
+
return result.replace(/ +/g, " ").trim();
|
|
2940
3566
|
}
|
|
2941
3567
|
function spawnWithKill(command, options, registry) {
|
|
2942
3568
|
return new Promise((resolve, reject) => {
|
|
@@ -3598,159 +4224,159 @@ import WebSocket from "ws";
|
|
|
3598
4224
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
3599
4225
|
|
|
3600
4226
|
// src/relay/types.ts
|
|
3601
|
-
import { z as
|
|
3602
|
-
var RegisterMessageSchema =
|
|
3603
|
-
type:
|
|
3604
|
-
owner:
|
|
4227
|
+
import { z as z4 } from "zod";
|
|
4228
|
+
var RegisterMessageSchema = z4.object({
|
|
4229
|
+
type: z4.literal("register"),
|
|
4230
|
+
owner: z4.string().min(1),
|
|
3605
4231
|
/** V8: Cryptographic agent identity. When present, used as the canonical key. */
|
|
3606
|
-
agent_id:
|
|
4232
|
+
agent_id: z4.string().optional(),
|
|
3607
4233
|
/** V8 Phase 3: Server identifier for multi-agent delegation. */
|
|
3608
|
-
server_id:
|
|
3609
|
-
token:
|
|
3610
|
-
card:
|
|
4234
|
+
server_id: z4.string().optional(),
|
|
4235
|
+
token: z4.string().min(1),
|
|
4236
|
+
card: z4.record(z4.unknown()),
|
|
3611
4237
|
// CapabilityCard (validated separately)
|
|
3612
|
-
cards:
|
|
4238
|
+
cards: z4.array(z4.record(z4.unknown())).optional(),
|
|
3613
4239
|
// Additional cards (e.g., conductor card)
|
|
3614
4240
|
/** V8 Phase 3: Additional agents served by this server (multi-agent registration). */
|
|
3615
|
-
agents:
|
|
3616
|
-
agent_id:
|
|
3617
|
-
display_name:
|
|
3618
|
-
cards:
|
|
3619
|
-
delegation_token:
|
|
4241
|
+
agents: z4.array(z4.object({
|
|
4242
|
+
agent_id: z4.string().min(1),
|
|
4243
|
+
display_name: z4.string().min(1),
|
|
4244
|
+
cards: z4.array(z4.record(z4.unknown())),
|
|
4245
|
+
delegation_token: z4.record(z4.unknown()).optional()
|
|
3620
4246
|
})).optional()
|
|
3621
4247
|
});
|
|
3622
|
-
var RegisteredMessageSchema =
|
|
3623
|
-
type:
|
|
3624
|
-
agent_id:
|
|
4248
|
+
var RegisteredMessageSchema = z4.object({
|
|
4249
|
+
type: z4.literal("registered"),
|
|
4250
|
+
agent_id: z4.string()
|
|
3625
4251
|
});
|
|
3626
|
-
var RelayRequestMessageSchema =
|
|
3627
|
-
type:
|
|
3628
|
-
id:
|
|
3629
|
-
target_owner:
|
|
4252
|
+
var RelayRequestMessageSchema = z4.object({
|
|
4253
|
+
type: z4.literal("relay_request"),
|
|
4254
|
+
id: z4.string().uuid(),
|
|
4255
|
+
target_owner: z4.string().min(1),
|
|
3630
4256
|
/** V8: Target agent's cryptographic identity. Preferred over target_owner. */
|
|
3631
|
-
target_agent_id:
|
|
3632
|
-
card_id:
|
|
3633
|
-
skill_id:
|
|
3634
|
-
params:
|
|
3635
|
-
requester:
|
|
3636
|
-
escrow_receipt:
|
|
4257
|
+
target_agent_id: z4.string().optional(),
|
|
4258
|
+
card_id: z4.string(),
|
|
4259
|
+
skill_id: z4.string().optional(),
|
|
4260
|
+
params: z4.record(z4.unknown()).default({}),
|
|
4261
|
+
requester: z4.string().optional(),
|
|
4262
|
+
escrow_receipt: z4.record(z4.unknown()).optional()
|
|
3637
4263
|
});
|
|
3638
|
-
var IncomingRequestMessageSchema =
|
|
3639
|
-
type:
|
|
3640
|
-
id:
|
|
3641
|
-
from_owner:
|
|
3642
|
-
card_id:
|
|
3643
|
-
skill_id:
|
|
3644
|
-
params:
|
|
3645
|
-
requester:
|
|
3646
|
-
escrow_receipt:
|
|
4264
|
+
var IncomingRequestMessageSchema = z4.object({
|
|
4265
|
+
type: z4.literal("incoming_request"),
|
|
4266
|
+
id: z4.string().uuid(),
|
|
4267
|
+
from_owner: z4.string().min(1),
|
|
4268
|
+
card_id: z4.string(),
|
|
4269
|
+
skill_id: z4.string().optional(),
|
|
4270
|
+
params: z4.record(z4.unknown()).default({}),
|
|
4271
|
+
requester: z4.string().optional(),
|
|
4272
|
+
escrow_receipt: z4.record(z4.unknown()).optional()
|
|
3647
4273
|
});
|
|
3648
|
-
var RelayResponseMessageSchema =
|
|
3649
|
-
type:
|
|
3650
|
-
id:
|
|
3651
|
-
result:
|
|
3652
|
-
error:
|
|
3653
|
-
code:
|
|
3654
|
-
message:
|
|
4274
|
+
var RelayResponseMessageSchema = z4.object({
|
|
4275
|
+
type: z4.literal("relay_response"),
|
|
4276
|
+
id: z4.string().uuid(),
|
|
4277
|
+
result: z4.unknown().optional(),
|
|
4278
|
+
error: z4.object({
|
|
4279
|
+
code: z4.number(),
|
|
4280
|
+
message: z4.string()
|
|
3655
4281
|
}).optional()
|
|
3656
4282
|
});
|
|
3657
|
-
var ResponseMessageSchema =
|
|
3658
|
-
type:
|
|
3659
|
-
id:
|
|
3660
|
-
result:
|
|
3661
|
-
error:
|
|
3662
|
-
code:
|
|
3663
|
-
message:
|
|
4283
|
+
var ResponseMessageSchema = z4.object({
|
|
4284
|
+
type: z4.literal("response"),
|
|
4285
|
+
id: z4.string().uuid(),
|
|
4286
|
+
result: z4.unknown().optional(),
|
|
4287
|
+
error: z4.object({
|
|
4288
|
+
code: z4.number(),
|
|
4289
|
+
message: z4.string()
|
|
3664
4290
|
}).optional()
|
|
3665
4291
|
});
|
|
3666
|
-
var ErrorMessageSchema =
|
|
3667
|
-
type:
|
|
3668
|
-
code:
|
|
3669
|
-
message:
|
|
3670
|
-
request_id:
|
|
4292
|
+
var ErrorMessageSchema = z4.object({
|
|
4293
|
+
type: z4.literal("error"),
|
|
4294
|
+
code: z4.string(),
|
|
4295
|
+
message: z4.string(),
|
|
4296
|
+
request_id: z4.string().optional()
|
|
3671
4297
|
});
|
|
3672
|
-
var RelayProgressMessageSchema =
|
|
3673
|
-
type:
|
|
3674
|
-
id:
|
|
4298
|
+
var RelayProgressMessageSchema = z4.object({
|
|
4299
|
+
type: z4.literal("relay_progress"),
|
|
4300
|
+
id: z4.string().uuid(),
|
|
3675
4301
|
// request ID this progress relates to
|
|
3676
|
-
progress:
|
|
4302
|
+
progress: z4.number().min(0).max(100).optional(),
|
|
3677
4303
|
// optional percentage
|
|
3678
|
-
message:
|
|
4304
|
+
message: z4.string().optional()
|
|
3679
4305
|
// optional status message
|
|
3680
4306
|
});
|
|
3681
|
-
var RelayStartedMessageSchema =
|
|
3682
|
-
type:
|
|
3683
|
-
id:
|
|
3684
|
-
message:
|
|
4307
|
+
var RelayStartedMessageSchema = z4.object({
|
|
4308
|
+
type: z4.literal("relay_started"),
|
|
4309
|
+
id: z4.string().uuid(),
|
|
4310
|
+
message: z4.string().optional()
|
|
3685
4311
|
});
|
|
3686
|
-
var HeartbeatMessageSchema =
|
|
3687
|
-
type:
|
|
3688
|
-
owner:
|
|
3689
|
-
capacity:
|
|
3690
|
-
current_load:
|
|
3691
|
-
max_concurrent:
|
|
3692
|
-
queue_depth:
|
|
4312
|
+
var HeartbeatMessageSchema = z4.object({
|
|
4313
|
+
type: z4.literal("heartbeat"),
|
|
4314
|
+
owner: z4.string().min(1),
|
|
4315
|
+
capacity: z4.object({
|
|
4316
|
+
current_load: z4.number(),
|
|
4317
|
+
max_concurrent: z4.number(),
|
|
4318
|
+
queue_depth: z4.number()
|
|
3693
4319
|
}),
|
|
3694
|
-
self_summary:
|
|
3695
|
-
capabilities:
|
|
3696
|
-
success_rate:
|
|
3697
|
-
credit_balance:
|
|
3698
|
-
total_completed:
|
|
3699
|
-
provider_number:
|
|
3700
|
-
reliability:
|
|
3701
|
-
current_streak:
|
|
3702
|
-
repeat_hire_rate:
|
|
3703
|
-
avg_feedback:
|
|
4320
|
+
self_summary: z4.object({
|
|
4321
|
+
capabilities: z4.array(z4.string()),
|
|
4322
|
+
success_rate: z4.number(),
|
|
4323
|
+
credit_balance: z4.number(),
|
|
4324
|
+
total_completed: z4.number(),
|
|
4325
|
+
provider_number: z4.number(),
|
|
4326
|
+
reliability: z4.object({
|
|
4327
|
+
current_streak: z4.number(),
|
|
4328
|
+
repeat_hire_rate: z4.number(),
|
|
4329
|
+
avg_feedback: z4.number()
|
|
3704
4330
|
})
|
|
3705
4331
|
})
|
|
3706
4332
|
});
|
|
3707
|
-
var EscrowHoldMessageSchema =
|
|
3708
|
-
type:
|
|
3709
|
-
consumer_agent_id:
|
|
3710
|
-
provider_agent_id:
|
|
3711
|
-
skill_id:
|
|
3712
|
-
amount:
|
|
3713
|
-
request_id:
|
|
3714
|
-
signature:
|
|
3715
|
-
public_key:
|
|
4333
|
+
var EscrowHoldMessageSchema = z4.object({
|
|
4334
|
+
type: z4.literal("escrow_hold"),
|
|
4335
|
+
consumer_agent_id: z4.string().min(1),
|
|
4336
|
+
provider_agent_id: z4.string().min(1),
|
|
4337
|
+
skill_id: z4.string().min(1),
|
|
4338
|
+
amount: z4.number().positive(),
|
|
4339
|
+
request_id: z4.string().uuid(),
|
|
4340
|
+
signature: z4.string().optional(),
|
|
4341
|
+
public_key: z4.string().optional()
|
|
3716
4342
|
});
|
|
3717
|
-
var EscrowHoldConfirmedMessageSchema =
|
|
3718
|
-
type:
|
|
3719
|
-
request_id:
|
|
3720
|
-
escrow_id:
|
|
3721
|
-
hold_amount:
|
|
3722
|
-
consumer_remaining:
|
|
4343
|
+
var EscrowHoldConfirmedMessageSchema = z4.object({
|
|
4344
|
+
type: z4.literal("escrow_hold_confirmed"),
|
|
4345
|
+
request_id: z4.string(),
|
|
4346
|
+
escrow_id: z4.string(),
|
|
4347
|
+
hold_amount: z4.number(),
|
|
4348
|
+
consumer_remaining: z4.number()
|
|
3723
4349
|
});
|
|
3724
|
-
var EscrowSettleMessageSchema =
|
|
3725
|
-
type:
|
|
3726
|
-
escrow_id:
|
|
3727
|
-
request_id:
|
|
3728
|
-
success:
|
|
3729
|
-
failure_reason:
|
|
3730
|
-
result_hash:
|
|
3731
|
-
signature:
|
|
3732
|
-
public_key:
|
|
3733
|
-
consumer_agent_id:
|
|
4350
|
+
var EscrowSettleMessageSchema = z4.object({
|
|
4351
|
+
type: z4.literal("escrow_settle"),
|
|
4352
|
+
escrow_id: z4.string().min(1),
|
|
4353
|
+
request_id: z4.string().uuid(),
|
|
4354
|
+
success: z4.boolean(),
|
|
4355
|
+
failure_reason: z4.enum(["bad_execution", "overload", "timeout", "auth_error", "not_found"]).optional(),
|
|
4356
|
+
result_hash: z4.string().optional(),
|
|
4357
|
+
signature: z4.string().optional(),
|
|
4358
|
+
public_key: z4.string().optional(),
|
|
4359
|
+
consumer_agent_id: z4.string().optional()
|
|
3734
4360
|
});
|
|
3735
|
-
var EscrowSettledMessageSchema =
|
|
3736
|
-
type:
|
|
3737
|
-
escrow_id:
|
|
3738
|
-
request_id:
|
|
3739
|
-
provider_earned:
|
|
3740
|
-
network_fee:
|
|
3741
|
-
consumer_remaining:
|
|
3742
|
-
provider_balance:
|
|
4361
|
+
var EscrowSettledMessageSchema = z4.object({
|
|
4362
|
+
type: z4.literal("escrow_settled"),
|
|
4363
|
+
escrow_id: z4.string(),
|
|
4364
|
+
request_id: z4.string(),
|
|
4365
|
+
provider_earned: z4.number(),
|
|
4366
|
+
network_fee: z4.number(),
|
|
4367
|
+
consumer_remaining: z4.number(),
|
|
4368
|
+
provider_balance: z4.number()
|
|
3743
4369
|
});
|
|
3744
|
-
var BalanceSyncMessageSchema =
|
|
3745
|
-
type:
|
|
3746
|
-
agent_id:
|
|
4370
|
+
var BalanceSyncMessageSchema = z4.object({
|
|
4371
|
+
type: z4.literal("balance_sync"),
|
|
4372
|
+
agent_id: z4.string().min(1)
|
|
3747
4373
|
});
|
|
3748
|
-
var BalanceSyncResponseMessageSchema =
|
|
3749
|
-
type:
|
|
3750
|
-
agent_id:
|
|
3751
|
-
balance:
|
|
4374
|
+
var BalanceSyncResponseMessageSchema = z4.object({
|
|
4375
|
+
type: z4.literal("balance_sync_response"),
|
|
4376
|
+
agent_id: z4.string(),
|
|
4377
|
+
balance: z4.number()
|
|
3752
4378
|
});
|
|
3753
|
-
var RelayMessageSchema =
|
|
4379
|
+
var RelayMessageSchema = z4.discriminatedUnion("type", [
|
|
3754
4380
|
RegisterMessageSchema,
|
|
3755
4381
|
RegisteredMessageSchema,
|
|
3756
4382
|
RelayRequestMessageSchema,
|
|
@@ -4153,8 +4779,8 @@ import { randomUUID as randomUUID11 } from "crypto";
|
|
|
4153
4779
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
4154
4780
|
|
|
4155
4781
|
// src/cli/peers.ts
|
|
4156
|
-
import { readFileSync as
|
|
4157
|
-
import { join as
|
|
4782
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
4783
|
+
import { join as join4 } from "path";
|
|
4158
4784
|
|
|
4159
4785
|
// src/autonomy/auto-request.ts
|
|
4160
4786
|
function minMaxNormalize(values) {
|
|
@@ -4338,11 +4964,11 @@ var BudgetController = class {
|
|
|
4338
4964
|
};
|
|
4339
4965
|
|
|
4340
4966
|
// src/conductor/card.ts
|
|
4341
|
-
import { createHash } from "crypto";
|
|
4967
|
+
import { createHash as createHash2 } from "crypto";
|
|
4342
4968
|
var CONDUCTOR_OWNER = "agentbnb-conductor";
|
|
4343
4969
|
var CONDUCTOR_CARD_ID = "00000000-0000-4000-8000-000000000001";
|
|
4344
4970
|
function ownerToCardId(owner) {
|
|
4345
|
-
const hash =
|
|
4971
|
+
const hash = createHash2("sha256").update(owner).digest("hex").slice(0, 32);
|
|
4346
4972
|
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-8${hash.slice(17, 20)}-${hash.slice(20, 32)}`;
|
|
4347
4973
|
}
|
|
4348
4974
|
function buildConductorCard(owner) {
|
|
@@ -4980,18 +5606,18 @@ var ConductorMode = class {
|
|
|
4980
5606
|
};
|
|
4981
5607
|
|
|
4982
5608
|
// src/credit/escrow-receipt.ts
|
|
4983
|
-
import { z as
|
|
5609
|
+
import { z as z5 } from "zod";
|
|
4984
5610
|
import { randomUUID as randomUUID14 } from "crypto";
|
|
4985
|
-
var EscrowReceiptSchema =
|
|
4986
|
-
requester_owner:
|
|
4987
|
-
requester_agent_id:
|
|
4988
|
-
requester_public_key:
|
|
4989
|
-
amount:
|
|
4990
|
-
card_id:
|
|
4991
|
-
skill_id:
|
|
4992
|
-
timestamp:
|
|
4993
|
-
nonce:
|
|
4994
|
-
signature:
|
|
5611
|
+
var EscrowReceiptSchema = z5.object({
|
|
5612
|
+
requester_owner: z5.string().min(1),
|
|
5613
|
+
requester_agent_id: z5.string().optional(),
|
|
5614
|
+
requester_public_key: z5.string().min(1),
|
|
5615
|
+
amount: z5.number().positive(),
|
|
5616
|
+
card_id: z5.string().min(1),
|
|
5617
|
+
skill_id: z5.string().optional(),
|
|
5618
|
+
timestamp: z5.string(),
|
|
5619
|
+
nonce: z5.string().uuid(),
|
|
5620
|
+
signature: z5.string().min(1)
|
|
4995
5621
|
});
|
|
4996
5622
|
function createSignedEscrowReceipt(db, privateKey, publicKey, opts) {
|
|
4997
5623
|
const escrowId = holdEscrow(db, opts.owner, opts.amount, opts.cardId);
|
|
@@ -5033,191 +5659,6 @@ function releaseRequesterEscrow(requesterDb, escrowId) {
|
|
|
5033
5659
|
releaseEscrow(requesterDb, escrowId);
|
|
5034
5660
|
}
|
|
5035
5661
|
|
|
5036
|
-
// src/identity/identity.ts
|
|
5037
|
-
import { z as z5 } from "zod";
|
|
5038
|
-
import { createHash as createHash2, createPrivateKey as createPrivateKey2, createPublicKey as createPublicKey2 } from "crypto";
|
|
5039
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
5040
|
-
import { join as join4 } from "path";
|
|
5041
|
-
var AgentIdentitySchema = z5.object({
|
|
5042
|
-
/** Deterministic ID derived from public key: sha256(hex).slice(0, 16). */
|
|
5043
|
-
agent_id: z5.string().min(1),
|
|
5044
|
-
/** Human-readable owner name (from config or init). */
|
|
5045
|
-
owner: z5.string().min(1),
|
|
5046
|
-
/** Hex-encoded Ed25519 public key. */
|
|
5047
|
-
public_key: z5.string().min(1),
|
|
5048
|
-
/** ISO 8601 timestamp of identity creation. */
|
|
5049
|
-
created_at: z5.string().datetime(),
|
|
5050
|
-
/** Optional guarantor info if linked to a human. */
|
|
5051
|
-
guarantor: z5.object({
|
|
5052
|
-
github_login: z5.string().min(1),
|
|
5053
|
-
verified_at: z5.string().datetime()
|
|
5054
|
-
}).optional()
|
|
5055
|
-
});
|
|
5056
|
-
var AgentCertificateSchema = z5.object({
|
|
5057
|
-
identity: AgentIdentitySchema,
|
|
5058
|
-
/** ISO 8601 timestamp of certificate issuance. */
|
|
5059
|
-
issued_at: z5.string().datetime(),
|
|
5060
|
-
/** ISO 8601 timestamp of certificate expiry. */
|
|
5061
|
-
expires_at: z5.string().datetime(),
|
|
5062
|
-
/** Hex-encoded public key of the issuer (same as identity for self-signed). */
|
|
5063
|
-
issuer_public_key: z5.string().min(1),
|
|
5064
|
-
/** Base64url Ed25519 signature over { identity, issued_at, expires_at, issuer_public_key }. */
|
|
5065
|
-
signature: z5.string().min(1)
|
|
5066
|
-
});
|
|
5067
|
-
var IDENTITY_FILENAME = "identity.json";
|
|
5068
|
-
var PRIVATE_KEY_FILENAME = "private.key";
|
|
5069
|
-
var PUBLIC_KEY_FILENAME = "public.key";
|
|
5070
|
-
function derivePublicKeyFromPrivate(privateKey) {
|
|
5071
|
-
const privateKeyObject = createPrivateKey2({ key: privateKey, format: "der", type: "pkcs8" });
|
|
5072
|
-
const publicKeyObject = createPublicKey2(privateKeyObject);
|
|
5073
|
-
const publicKey = publicKeyObject.export({ format: "der", type: "spki" });
|
|
5074
|
-
return Buffer.from(publicKey);
|
|
5075
|
-
}
|
|
5076
|
-
function buildIdentityFromPublicKey(publicKey, owner, createdAt) {
|
|
5077
|
-
const publicKeyHex = publicKey.toString("hex");
|
|
5078
|
-
return {
|
|
5079
|
-
agent_id: deriveAgentId(publicKeyHex),
|
|
5080
|
-
owner,
|
|
5081
|
-
public_key: publicKeyHex,
|
|
5082
|
-
created_at: createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
5083
|
-
};
|
|
5084
|
-
}
|
|
5085
|
-
function generateFreshIdentity(configDir, owner) {
|
|
5086
|
-
const keys = generateKeyPair();
|
|
5087
|
-
saveKeyPair(configDir, keys);
|
|
5088
|
-
const identity = buildIdentityFromPublicKey(keys.publicKey, owner);
|
|
5089
|
-
saveIdentity(configDir, identity);
|
|
5090
|
-
return { identity, keys, status: "generated" };
|
|
5091
|
-
}
|
|
5092
|
-
function deriveAgentId(publicKeyHex) {
|
|
5093
|
-
return createHash2("sha256").update(publicKeyHex, "hex").digest("hex").slice(0, 16);
|
|
5094
|
-
}
|
|
5095
|
-
function createIdentity(configDir, owner) {
|
|
5096
|
-
if (!existsSync4(configDir)) {
|
|
5097
|
-
mkdirSync3(configDir, { recursive: true });
|
|
5098
|
-
}
|
|
5099
|
-
let keys;
|
|
5100
|
-
try {
|
|
5101
|
-
keys = loadKeyPair(configDir);
|
|
5102
|
-
} catch {
|
|
5103
|
-
keys = generateKeyPair();
|
|
5104
|
-
saveKeyPair(configDir, keys);
|
|
5105
|
-
}
|
|
5106
|
-
const publicKeyHex = keys.publicKey.toString("hex");
|
|
5107
|
-
const agentId = deriveAgentId(publicKeyHex);
|
|
5108
|
-
const identity = {
|
|
5109
|
-
agent_id: agentId,
|
|
5110
|
-
owner,
|
|
5111
|
-
public_key: publicKeyHex,
|
|
5112
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
5113
|
-
};
|
|
5114
|
-
saveIdentity(configDir, identity);
|
|
5115
|
-
return identity;
|
|
5116
|
-
}
|
|
5117
|
-
function loadIdentity(configDir) {
|
|
5118
|
-
const filePath = join4(configDir, IDENTITY_FILENAME);
|
|
5119
|
-
if (!existsSync4(filePath)) return null;
|
|
5120
|
-
try {
|
|
5121
|
-
const raw = readFileSync4(filePath, "utf-8");
|
|
5122
|
-
return AgentIdentitySchema.parse(JSON.parse(raw));
|
|
5123
|
-
} catch {
|
|
5124
|
-
return null;
|
|
5125
|
-
}
|
|
5126
|
-
}
|
|
5127
|
-
function saveIdentity(configDir, identity) {
|
|
5128
|
-
if (!existsSync4(configDir)) {
|
|
5129
|
-
mkdirSync3(configDir, { recursive: true });
|
|
5130
|
-
}
|
|
5131
|
-
const filePath = join4(configDir, IDENTITY_FILENAME);
|
|
5132
|
-
writeFileSync4(filePath, JSON.stringify(identity, null, 2), "utf-8");
|
|
5133
|
-
}
|
|
5134
|
-
function loadOrRepairIdentity(configDir, ownerHint) {
|
|
5135
|
-
if (!existsSync4(configDir)) {
|
|
5136
|
-
mkdirSync3(configDir, { recursive: true });
|
|
5137
|
-
}
|
|
5138
|
-
const identityPath = join4(configDir, IDENTITY_FILENAME);
|
|
5139
|
-
const privateKeyPath = join4(configDir, PRIVATE_KEY_FILENAME);
|
|
5140
|
-
const publicKeyPath = join4(configDir, PUBLIC_KEY_FILENAME);
|
|
5141
|
-
const hasIdentity = existsSync4(identityPath);
|
|
5142
|
-
const hasPrivateKey = existsSync4(privateKeyPath);
|
|
5143
|
-
const hasPublicKey = existsSync4(publicKeyPath);
|
|
5144
|
-
if (!hasIdentity || !hasPrivateKey || !hasPublicKey) {
|
|
5145
|
-
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
5146
|
-
}
|
|
5147
|
-
let keys;
|
|
5148
|
-
try {
|
|
5149
|
-
keys = loadKeyPair(configDir);
|
|
5150
|
-
} catch {
|
|
5151
|
-
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
5152
|
-
}
|
|
5153
|
-
let derivedPublicKey;
|
|
5154
|
-
try {
|
|
5155
|
-
derivedPublicKey = derivePublicKeyFromPrivate(keys.privateKey);
|
|
5156
|
-
} catch {
|
|
5157
|
-
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
5158
|
-
}
|
|
5159
|
-
let keypairRepaired = false;
|
|
5160
|
-
if (!keys.publicKey.equals(derivedPublicKey)) {
|
|
5161
|
-
keypairRepaired = true;
|
|
5162
|
-
keys = { privateKey: keys.privateKey, publicKey: derivedPublicKey };
|
|
5163
|
-
saveKeyPair(configDir, keys);
|
|
5164
|
-
}
|
|
5165
|
-
const loadedIdentity = loadIdentity(configDir);
|
|
5166
|
-
const expectedAgentId = deriveAgentId(derivedPublicKey.toString("hex"));
|
|
5167
|
-
const expectedPublicKeyHex = derivedPublicKey.toString("hex");
|
|
5168
|
-
const identityMismatch = !loadedIdentity || loadedIdentity.public_key !== expectedPublicKeyHex || loadedIdentity.agent_id !== expectedAgentId;
|
|
5169
|
-
if (identityMismatch) {
|
|
5170
|
-
const repairedIdentity = buildIdentityFromPublicKey(
|
|
5171
|
-
derivedPublicKey,
|
|
5172
|
-
loadedIdentity?.owner ?? ownerHint ?? "agent",
|
|
5173
|
-
loadedIdentity?.created_at
|
|
5174
|
-
);
|
|
5175
|
-
saveIdentity(configDir, repairedIdentity);
|
|
5176
|
-
return { identity: repairedIdentity, keys, status: "repaired" };
|
|
5177
|
-
}
|
|
5178
|
-
if (ownerHint && loadedIdentity.owner !== ownerHint) {
|
|
5179
|
-
const updatedIdentity = { ...loadedIdentity, owner: ownerHint };
|
|
5180
|
-
saveIdentity(configDir, updatedIdentity);
|
|
5181
|
-
return { identity: updatedIdentity, keys, status: "repaired" };
|
|
5182
|
-
}
|
|
5183
|
-
return { identity: loadedIdentity, keys, status: keypairRepaired ? "repaired" : "existing" };
|
|
5184
|
-
}
|
|
5185
|
-
function issueAgentCertificate(identity, privateKey) {
|
|
5186
|
-
const issuedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5187
|
-
const expiresAt = new Date(Date.now() + 365 * 24 * 60 * 60 * 1e3).toISOString();
|
|
5188
|
-
const payload = {
|
|
5189
|
-
identity,
|
|
5190
|
-
issued_at: issuedAt,
|
|
5191
|
-
expires_at: expiresAt,
|
|
5192
|
-
issuer_public_key: identity.public_key
|
|
5193
|
-
};
|
|
5194
|
-
const signature = signEscrowReceipt(payload, privateKey);
|
|
5195
|
-
return {
|
|
5196
|
-
identity,
|
|
5197
|
-
issued_at: issuedAt,
|
|
5198
|
-
expires_at: expiresAt,
|
|
5199
|
-
issuer_public_key: identity.public_key,
|
|
5200
|
-
signature
|
|
5201
|
-
};
|
|
5202
|
-
}
|
|
5203
|
-
function verifyAgentCertificate(cert) {
|
|
5204
|
-
if (new Date(cert.expires_at) < /* @__PURE__ */ new Date()) {
|
|
5205
|
-
return false;
|
|
5206
|
-
}
|
|
5207
|
-
const publicKeyHex = cert.issuer_public_key;
|
|
5208
|
-
const publicKeyBuf = Buffer.from(publicKeyHex, "hex");
|
|
5209
|
-
const payload = {
|
|
5210
|
-
identity: cert.identity,
|
|
5211
|
-
issued_at: cert.issued_at,
|
|
5212
|
-
expires_at: cert.expires_at,
|
|
5213
|
-
issuer_public_key: cert.issuer_public_key
|
|
5214
|
-
};
|
|
5215
|
-
return verifyEscrowReceipt(payload, cert.signature, publicKeyBuf);
|
|
5216
|
-
}
|
|
5217
|
-
function ensureIdentity(configDir, owner) {
|
|
5218
|
-
return loadOrRepairIdentity(configDir, owner).identity;
|
|
5219
|
-
}
|
|
5220
|
-
|
|
5221
5662
|
// src/sdk/consumer.ts
|
|
5222
5663
|
var AgentBnBConsumer = class {
|
|
5223
5664
|
configDir;
|