agentbnb 8.2.0 → 8.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-TBJ3FZKZ.js → chunk-7Q2XUXSA.js} +1 -1
- package/dist/{chunk-LJM7FHPM.js → chunk-BZOJ7HBT.js} +33 -1
- package/dist/{chunk-FTZTEHYG.js → chunk-DEWY7OQK.js} +135 -8
- package/dist/{chunk-CUONY5TO.js → chunk-EJKW57ZV.js} +19 -1
- package/dist/chunk-EZVOG7QS.js +161 -0
- package/dist/{chunk-E2OKP5CY.js → chunk-GJETGML6.js} +181 -83
- package/dist/{chunk-YHY7OG6S.js → chunk-GWMMYVLL.js} +4 -4
- package/dist/{chunk-D6RKW2XG.js → chunk-JLNHMNES.js} +16 -3
- package/dist/{chunk-5AAFG2V2.js → chunk-KBQNTUTN.js} +239 -24
- package/dist/{chunk-C537SFHV.js → chunk-LOUEJI6X.js} +4 -4
- package/dist/{chunk-ALX4WS3A.js → chunk-NP55V7RQ.js} +1 -1
- package/dist/{chunk-X32NE6V4.js → chunk-RBXTWWUH.js} +1 -1
- package/dist/{chunk-O2OYBAVR.js → chunk-SRBVKO2V.js} +9 -0
- package/dist/{chunk-7EF3HYVZ.js → chunk-STJLWMXH.js} +48 -4
- package/dist/{chunk-5GME4KJZ.js → chunk-UYCD3JBZ.js} +3 -3
- package/dist/{chunk-P4LOYSLA.js → chunk-WKWJWKX7.js} +286 -81
- package/dist/cli/index.js +35 -57
- package/dist/{client-HKV3QWZ3.js → client-66TFS7RS.js} +4 -2
- package/dist/{conduct-W6XF6DJW.js → conduct-A6COHLHY.js} +8 -8
- package/dist/{conduct-YB64OHI6.js → conduct-IUVAXUAV.js} +8 -8
- package/dist/{conductor-mode-TFCVCQHU.js → conductor-mode-D5TFQW5L.js} +2 -2
- package/dist/{conductor-mode-AKREGDIU.js → conductor-mode-L2MB44BW.js} +7 -7
- package/dist/{execute-AYQWORVH.js → execute-5AWLARB5.js} +5 -5
- package/dist/{execute-EPE6MZLT.js → execute-WOS457HW.js} +2 -2
- package/dist/index.js +438 -92
- package/dist/{publish-capability-AH2HDW54.js → publish-capability-JJCBBMSX.js} +2 -2
- package/dist/{request-HCCXSKAY.js → request-6YQLA7K3.js} +13 -8
- package/dist/{serve-skill-SZAQT5T5.js → serve-skill-X7TZSILV.js} +5 -5
- package/dist/{server-LMY2A3GT.js → server-5TSP4DBX.js} +10 -12
- package/dist/{service-coordinator-WGH6B2VT.js → service-coordinator-WTUSMPY6.js} +69 -46
- package/dist/skills/agentbnb/bootstrap.js +459 -189
- package/package.json +13 -17
- package/skills/agentbnb/bootstrap.test.ts +8 -6
- package/skills/agentbnb/bootstrap.ts +21 -13
- package/skills/agentbnb/install.sh +0 -0
- package/dist/chunk-64AK4FJM.js +0 -84
- package/dist/chunk-OH7BP5NP.js +0 -96
- package/dist/index.d.ts +0 -5069
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
requestViaRelay,
|
|
22
22
|
resolvePendingRequest,
|
|
23
23
|
searchCards
|
|
24
|
-
} from "../../chunk-
|
|
24
|
+
} from "../../chunk-WKWJWKX7.js";
|
|
25
25
|
import {
|
|
26
26
|
loadPeers
|
|
27
27
|
} from "../../chunk-HLUEOLSZ.js";
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
executeCapabilityRequest,
|
|
31
31
|
releaseRequesterEscrow,
|
|
32
32
|
settleRequesterEscrow
|
|
33
|
-
} from "../../chunk-
|
|
33
|
+
} from "../../chunk-NP55V7RQ.js";
|
|
34
34
|
import {
|
|
35
35
|
bootstrapAgent,
|
|
36
36
|
generateKeyPair,
|
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
insertRequestLog,
|
|
53
53
|
listCards,
|
|
54
54
|
loadKeyPair,
|
|
55
|
+
lookupAgent,
|
|
55
56
|
migrateOwner,
|
|
56
57
|
openCreditDb,
|
|
57
58
|
openDatabase,
|
|
@@ -63,7 +64,7 @@ import {
|
|
|
63
64
|
updateSkillAvailability,
|
|
64
65
|
updateSkillIdleRate,
|
|
65
66
|
verifyEscrowReceipt
|
|
66
|
-
} from "../../chunk-
|
|
67
|
+
} from "../../chunk-STJLWMXH.js";
|
|
67
68
|
import "../../chunk-NWIQJ2CL.js";
|
|
68
69
|
import {
|
|
69
70
|
getConfigDir,
|
|
@@ -79,9 +80,9 @@ import {
|
|
|
79
80
|
} from "../../chunk-3LWBH7P3.js";
|
|
80
81
|
|
|
81
82
|
// skills/agentbnb/bootstrap.ts
|
|
82
|
-
import { join as
|
|
83
|
-
import { homedir as
|
|
84
|
-
import {
|
|
83
|
+
import { join as join7, basename as basename2, dirname as dirname3 } from "path";
|
|
84
|
+
import { homedir as homedir4 } from "os";
|
|
85
|
+
import { exec } from "child_process";
|
|
85
86
|
import { promisify as promisify2 } from "util";
|
|
86
87
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
87
88
|
|
|
@@ -1271,7 +1272,7 @@ var AgentRuntime = class {
|
|
|
1271
1272
|
}
|
|
1272
1273
|
const modes = /* @__PURE__ */ new Map();
|
|
1273
1274
|
if (this.conductorEnabled) {
|
|
1274
|
-
const { ConductorMode } = await import("../../conductor-mode-
|
|
1275
|
+
const { ConductorMode } = await import("../../conductor-mode-D5TFQW5L.js");
|
|
1275
1276
|
const { registerConductorCard, CONDUCTOR_OWNER } = await import("../../card-EX2EYGCZ.js");
|
|
1276
1277
|
const { loadPeers: loadPeers2 } = await import("../../peers-CJ7T4RJO.js");
|
|
1277
1278
|
registerConductorCard(this.registryDb);
|
|
@@ -1435,7 +1436,54 @@ function createGatewayServer(opts) {
|
|
|
1435
1436
|
return { status: "ok", version: VERSION, uptime: process.uptime() };
|
|
1436
1437
|
});
|
|
1437
1438
|
fastify.post("/rpc", async (request, reply) => {
|
|
1438
|
-
const
|
|
1439
|
+
const rawBody = request.body;
|
|
1440
|
+
if (Array.isArray(rawBody)) {
|
|
1441
|
+
const responses = await Promise.all(
|
|
1442
|
+
rawBody.map(async (single) => {
|
|
1443
|
+
if (single.jsonrpc !== "2.0" || !single.method) {
|
|
1444
|
+
return { jsonrpc: "2.0", id: single.id ?? null, error: { code: -32600, message: "Invalid Request" } };
|
|
1445
|
+
}
|
|
1446
|
+
if (single.method !== "capability.execute") {
|
|
1447
|
+
return { jsonrpc: "2.0", id: single.id ?? null, error: { code: -32601, message: "Method not found" } };
|
|
1448
|
+
}
|
|
1449
|
+
const params2 = single.params ?? {};
|
|
1450
|
+
const cardId2 = params2.card_id;
|
|
1451
|
+
if (!cardId2) {
|
|
1452
|
+
return { jsonrpc: "2.0", id: single.id ?? null, error: { code: -32602, message: "Invalid params: card_id required" } };
|
|
1453
|
+
}
|
|
1454
|
+
const requester2 = params2.requester ?? "unknown";
|
|
1455
|
+
const receipt2 = params2.escrow_receipt;
|
|
1456
|
+
const batchSkillId = params2.skill_id;
|
|
1457
|
+
const trackKey2 = batchSkillId ?? cardId2;
|
|
1458
|
+
inFlight.set(trackKey2, (inFlight.get(trackKey2) ?? 0) + 1);
|
|
1459
|
+
try {
|
|
1460
|
+
const result2 = await executeCapabilityRequest({
|
|
1461
|
+
registryDb,
|
|
1462
|
+
creditDb,
|
|
1463
|
+
cardId: cardId2,
|
|
1464
|
+
skillId: batchSkillId,
|
|
1465
|
+
params: params2,
|
|
1466
|
+
requester: requester2,
|
|
1467
|
+
escrowReceipt: receipt2,
|
|
1468
|
+
skillExecutor,
|
|
1469
|
+
handlerUrl,
|
|
1470
|
+
timeoutMs
|
|
1471
|
+
});
|
|
1472
|
+
if (result2.success) {
|
|
1473
|
+
return { jsonrpc: "2.0", id: single.id ?? null, result: result2.result };
|
|
1474
|
+
} else {
|
|
1475
|
+
return { jsonrpc: "2.0", id: single.id ?? null, error: result2.error };
|
|
1476
|
+
}
|
|
1477
|
+
} finally {
|
|
1478
|
+
const next = (inFlight.get(trackKey2) ?? 1) - 1;
|
|
1479
|
+
if (next <= 0) inFlight.delete(trackKey2);
|
|
1480
|
+
else inFlight.set(trackKey2, next);
|
|
1481
|
+
}
|
|
1482
|
+
})
|
|
1483
|
+
);
|
|
1484
|
+
return reply.send(responses);
|
|
1485
|
+
}
|
|
1486
|
+
const body = rawBody;
|
|
1439
1487
|
if (body.jsonrpc !== "2.0" || !body.method) {
|
|
1440
1488
|
return reply.status(400).send({
|
|
1441
1489
|
jsonrpc: "2.0",
|
|
@@ -1655,13 +1703,190 @@ var LocalCreditLedger = class {
|
|
|
1655
1703
|
}
|
|
1656
1704
|
};
|
|
1657
1705
|
|
|
1706
|
+
// src/identity/identity.ts
|
|
1707
|
+
import { z as z2 } from "zod";
|
|
1708
|
+
import { createHash, createPrivateKey, createPublicKey } from "crypto";
|
|
1709
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
1710
|
+
import { join as join2 } from "path";
|
|
1711
|
+
var AgentIdentitySchema = z2.object({
|
|
1712
|
+
/** Deterministic ID derived from public key: sha256(hex).slice(0, 16). */
|
|
1713
|
+
agent_id: z2.string().min(1),
|
|
1714
|
+
/** Human-readable owner name (from config or init). */
|
|
1715
|
+
owner: z2.string().min(1),
|
|
1716
|
+
/** Hex-encoded Ed25519 public key. */
|
|
1717
|
+
public_key: z2.string().min(1),
|
|
1718
|
+
/** ISO 8601 timestamp of identity creation. */
|
|
1719
|
+
created_at: z2.string().datetime(),
|
|
1720
|
+
/** Optional guarantor info if linked to a human. */
|
|
1721
|
+
guarantor: z2.object({
|
|
1722
|
+
github_login: z2.string().min(1),
|
|
1723
|
+
verified_at: z2.string().datetime()
|
|
1724
|
+
}).optional()
|
|
1725
|
+
});
|
|
1726
|
+
var AgentCertificateSchema = z2.object({
|
|
1727
|
+
identity: AgentIdentitySchema,
|
|
1728
|
+
/** ISO 8601 timestamp of certificate issuance. */
|
|
1729
|
+
issued_at: z2.string().datetime(),
|
|
1730
|
+
/** ISO 8601 timestamp of certificate expiry. */
|
|
1731
|
+
expires_at: z2.string().datetime(),
|
|
1732
|
+
/** Hex-encoded public key of the issuer (same as identity for self-signed). */
|
|
1733
|
+
issuer_public_key: z2.string().min(1),
|
|
1734
|
+
/** Base64url Ed25519 signature over { identity, issued_at, expires_at, issuer_public_key }. */
|
|
1735
|
+
signature: z2.string().min(1)
|
|
1736
|
+
});
|
|
1737
|
+
var IDENTITY_FILENAME = "identity.json";
|
|
1738
|
+
var PRIVATE_KEY_FILENAME = "private.key";
|
|
1739
|
+
var PUBLIC_KEY_FILENAME = "public.key";
|
|
1740
|
+
function derivePublicKeyFromPrivate(privateKey) {
|
|
1741
|
+
const privateKeyObject = createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
|
1742
|
+
const publicKeyObject = createPublicKey(privateKeyObject);
|
|
1743
|
+
const publicKey = publicKeyObject.export({ format: "der", type: "spki" });
|
|
1744
|
+
return Buffer.from(publicKey);
|
|
1745
|
+
}
|
|
1746
|
+
function buildIdentityFromPublicKey(publicKey, owner, createdAt) {
|
|
1747
|
+
const publicKeyHex = publicKey.toString("hex");
|
|
1748
|
+
return {
|
|
1749
|
+
agent_id: deriveAgentId(publicKeyHex),
|
|
1750
|
+
owner,
|
|
1751
|
+
public_key: publicKeyHex,
|
|
1752
|
+
created_at: createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
function generateFreshIdentity(configDir, owner) {
|
|
1756
|
+
const keys = generateKeyPair();
|
|
1757
|
+
saveKeyPair(configDir, keys);
|
|
1758
|
+
const identity = buildIdentityFromPublicKey(keys.publicKey, owner);
|
|
1759
|
+
saveIdentity(configDir, identity);
|
|
1760
|
+
return { identity, keys, status: "generated" };
|
|
1761
|
+
}
|
|
1762
|
+
function deriveAgentId(publicKeyHex) {
|
|
1763
|
+
return createHash("sha256").update(publicKeyHex, "hex").digest("hex").slice(0, 16);
|
|
1764
|
+
}
|
|
1765
|
+
function loadIdentity(configDir) {
|
|
1766
|
+
const filePath = join2(configDir, IDENTITY_FILENAME);
|
|
1767
|
+
if (!existsSync3(filePath)) return null;
|
|
1768
|
+
try {
|
|
1769
|
+
const raw = readFileSync3(filePath, "utf-8");
|
|
1770
|
+
return AgentIdentitySchema.parse(JSON.parse(raw));
|
|
1771
|
+
} catch {
|
|
1772
|
+
return null;
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
function saveIdentity(configDir, identity) {
|
|
1776
|
+
if (!existsSync3(configDir)) {
|
|
1777
|
+
mkdirSync2(configDir, { recursive: true });
|
|
1778
|
+
}
|
|
1779
|
+
const filePath = join2(configDir, IDENTITY_FILENAME);
|
|
1780
|
+
writeFileSync2(filePath, JSON.stringify(identity, null, 2), "utf-8");
|
|
1781
|
+
}
|
|
1782
|
+
function loadOrRepairIdentity(configDir, ownerHint) {
|
|
1783
|
+
if (!existsSync3(configDir)) {
|
|
1784
|
+
mkdirSync2(configDir, { recursive: true });
|
|
1785
|
+
}
|
|
1786
|
+
const identityPath = join2(configDir, IDENTITY_FILENAME);
|
|
1787
|
+
const privateKeyPath = join2(configDir, PRIVATE_KEY_FILENAME);
|
|
1788
|
+
const publicKeyPath = join2(configDir, PUBLIC_KEY_FILENAME);
|
|
1789
|
+
const hasIdentity = existsSync3(identityPath);
|
|
1790
|
+
const hasPrivateKey = existsSync3(privateKeyPath);
|
|
1791
|
+
const hasPublicKey = existsSync3(publicKeyPath);
|
|
1792
|
+
if (!hasIdentity || !hasPrivateKey || !hasPublicKey) {
|
|
1793
|
+
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
1794
|
+
}
|
|
1795
|
+
let keys;
|
|
1796
|
+
try {
|
|
1797
|
+
keys = loadKeyPair(configDir);
|
|
1798
|
+
} catch {
|
|
1799
|
+
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
1800
|
+
}
|
|
1801
|
+
let derivedPublicKey;
|
|
1802
|
+
try {
|
|
1803
|
+
derivedPublicKey = derivePublicKeyFromPrivate(keys.privateKey);
|
|
1804
|
+
} catch {
|
|
1805
|
+
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
1806
|
+
}
|
|
1807
|
+
let keypairRepaired = false;
|
|
1808
|
+
if (!keys.publicKey.equals(derivedPublicKey)) {
|
|
1809
|
+
keypairRepaired = true;
|
|
1810
|
+
keys = { privateKey: keys.privateKey, publicKey: derivedPublicKey };
|
|
1811
|
+
saveKeyPair(configDir, keys);
|
|
1812
|
+
}
|
|
1813
|
+
const loadedIdentity = loadIdentity(configDir);
|
|
1814
|
+
const expectedAgentId = deriveAgentId(derivedPublicKey.toString("hex"));
|
|
1815
|
+
const expectedPublicKeyHex = derivedPublicKey.toString("hex");
|
|
1816
|
+
const identityMismatch = !loadedIdentity || loadedIdentity.public_key !== expectedPublicKeyHex || loadedIdentity.agent_id !== expectedAgentId;
|
|
1817
|
+
if (identityMismatch) {
|
|
1818
|
+
const repairedIdentity = buildIdentityFromPublicKey(
|
|
1819
|
+
derivedPublicKey,
|
|
1820
|
+
loadedIdentity?.owner ?? ownerHint ?? "agent",
|
|
1821
|
+
loadedIdentity?.created_at
|
|
1822
|
+
);
|
|
1823
|
+
saveIdentity(configDir, repairedIdentity);
|
|
1824
|
+
return { identity: repairedIdentity, keys, status: "repaired" };
|
|
1825
|
+
}
|
|
1826
|
+
if (ownerHint && loadedIdentity.owner !== ownerHint) {
|
|
1827
|
+
const updatedIdentity = { ...loadedIdentity, owner: ownerHint };
|
|
1828
|
+
saveIdentity(configDir, updatedIdentity);
|
|
1829
|
+
return { identity: updatedIdentity, keys, status: "repaired" };
|
|
1830
|
+
}
|
|
1831
|
+
return { identity: loadedIdentity, keys, status: keypairRepaired ? "repaired" : "existing" };
|
|
1832
|
+
}
|
|
1833
|
+
function ensureIdentity(configDir, owner) {
|
|
1834
|
+
return loadOrRepairIdentity(configDir, owner).identity;
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1658
1837
|
// src/registry/identity-auth.ts
|
|
1659
1838
|
var MAX_REQUEST_AGE_MS = 5 * 60 * 1e3;
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1839
|
+
function normalizeSignedParams(body) {
|
|
1840
|
+
return body === void 0 ? null : body;
|
|
1841
|
+
}
|
|
1842
|
+
function buildIdentityPayload(method, path, timestamp, publicKeyHex, agentId, params) {
|
|
1843
|
+
return {
|
|
1844
|
+
method,
|
|
1845
|
+
path,
|
|
1846
|
+
timestamp,
|
|
1847
|
+
publicKey: publicKeyHex,
|
|
1848
|
+
agentId,
|
|
1849
|
+
params: normalizeSignedParams(params)
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1852
|
+
function extractClaimedRequester(request) {
|
|
1853
|
+
const extractFromObject = (obj) => {
|
|
1854
|
+
const directOwner = typeof obj.owner === "string" ? obj.owner.trim() : "";
|
|
1855
|
+
if (directOwner) return directOwner;
|
|
1856
|
+
const directRequester = typeof obj.requester === "string" ? obj.requester.trim() : "";
|
|
1857
|
+
if (directRequester) return directRequester;
|
|
1858
|
+
const oldOwner = typeof obj.oldOwner === "string" ? obj.oldOwner.trim() : "";
|
|
1859
|
+
if (oldOwner) return oldOwner;
|
|
1860
|
+
const nestedParams = obj.params;
|
|
1861
|
+
if (nestedParams && typeof nestedParams === "object" && !Array.isArray(nestedParams)) {
|
|
1862
|
+
const nested = nestedParams;
|
|
1863
|
+
const nestedOwner = typeof nested.owner === "string" ? nested.owner.trim() : "";
|
|
1864
|
+
if (nestedOwner) return nestedOwner;
|
|
1865
|
+
const nestedRequester = typeof nested.requester === "string" ? nested.requester.trim() : "";
|
|
1866
|
+
if (nestedRequester) return nestedRequester;
|
|
1867
|
+
}
|
|
1868
|
+
return null;
|
|
1869
|
+
};
|
|
1870
|
+
if (request.body && typeof request.body === "object" && !Array.isArray(request.body)) {
|
|
1871
|
+
const claimed = extractFromObject(request.body);
|
|
1872
|
+
if (claimed) return claimed;
|
|
1873
|
+
}
|
|
1874
|
+
if (request.params && typeof request.params === "object" && !Array.isArray(request.params)) {
|
|
1875
|
+
const claimed = extractFromObject(request.params);
|
|
1876
|
+
if (claimed) return claimed;
|
|
1877
|
+
}
|
|
1878
|
+
return null;
|
|
1879
|
+
}
|
|
1880
|
+
async function verifyIdentity(request, reply, options) {
|
|
1881
|
+
const agentIdHeader = request.headers["x-agent-id"];
|
|
1882
|
+
const publicKeyHeader = request.headers["x-agent-publickey"];
|
|
1883
|
+
const signatureHeader = request.headers["x-agent-signature"];
|
|
1884
|
+
const timestampHeader = request.headers["x-agent-timestamp"];
|
|
1885
|
+
const agentId = agentIdHeader?.trim();
|
|
1886
|
+
const publicKeyHex = publicKeyHeader?.trim();
|
|
1887
|
+
const signature = signatureHeader?.trim();
|
|
1888
|
+
const timestamp = timestampHeader?.trim();
|
|
1889
|
+
if (!agentId || !publicKeyHex || !signature || !timestamp) {
|
|
1665
1890
|
await reply.code(401).send({ error: "Missing identity headers" });
|
|
1666
1891
|
return false;
|
|
1667
1892
|
}
|
|
@@ -1670,12 +1895,21 @@ async function verifyIdentity(request, reply) {
|
|
|
1670
1895
|
await reply.code(401).send({ error: "Request expired" });
|
|
1671
1896
|
return false;
|
|
1672
1897
|
}
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1898
|
+
if (!/^[0-9a-fA-F]+$/.test(publicKeyHex) || publicKeyHex.length % 2 !== 0) {
|
|
1899
|
+
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
1900
|
+
return false;
|
|
1901
|
+
}
|
|
1902
|
+
let expectedAgentId;
|
|
1903
|
+
try {
|
|
1904
|
+
expectedAgentId = deriveAgentId(publicKeyHex);
|
|
1905
|
+
} catch {
|
|
1906
|
+
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
1907
|
+
return false;
|
|
1908
|
+
}
|
|
1909
|
+
if (agentId !== expectedAgentId) {
|
|
1910
|
+
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
1911
|
+
return false;
|
|
1912
|
+
}
|
|
1679
1913
|
let publicKeyBuffer;
|
|
1680
1914
|
try {
|
|
1681
1915
|
publicKeyBuffer = Buffer.from(publicKeyHex, "hex");
|
|
@@ -1683,30 +1917,52 @@ async function verifyIdentity(request, reply) {
|
|
|
1683
1917
|
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
1684
1918
|
return false;
|
|
1685
1919
|
}
|
|
1920
|
+
const knownAgent = options.agentDb ? lookupAgent(options.agentDb, agentId) : null;
|
|
1921
|
+
if (knownAgent && knownAgent.public_key.toLowerCase() !== publicKeyHex.toLowerCase()) {
|
|
1922
|
+
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
1923
|
+
return false;
|
|
1924
|
+
}
|
|
1925
|
+
const payload = buildIdentityPayload(
|
|
1926
|
+
request.method,
|
|
1927
|
+
request.url,
|
|
1928
|
+
timestamp,
|
|
1929
|
+
publicKeyHex,
|
|
1930
|
+
agentId,
|
|
1931
|
+
request.body
|
|
1932
|
+
);
|
|
1686
1933
|
const valid = verifyEscrowReceipt(payload, signature, publicKeyBuffer);
|
|
1687
1934
|
if (!valid) {
|
|
1688
1935
|
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
1689
1936
|
return false;
|
|
1690
1937
|
}
|
|
1938
|
+
const claimedRequester = extractClaimedRequester(request);
|
|
1939
|
+
if (claimedRequester) {
|
|
1940
|
+
const matchesAgentId = claimedRequester === agentId;
|
|
1941
|
+
const matchesLegacyOwner = knownAgent?.legacy_owner === claimedRequester;
|
|
1942
|
+
if (!matchesAgentId && !matchesLegacyOwner) {
|
|
1943
|
+
await reply.code(401).send({ error: "Identity does not match requester" });
|
|
1944
|
+
return false;
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1691
1947
|
request.agentPublicKey = publicKeyHex;
|
|
1948
|
+
request.agentId = agentId;
|
|
1692
1949
|
return true;
|
|
1693
1950
|
}
|
|
1694
|
-
function identityAuthPlugin(fastify) {
|
|
1695
|
-
fastify.addHook("
|
|
1696
|
-
await verifyIdentity(request, reply);
|
|
1951
|
+
function identityAuthPlugin(fastify, options = {}) {
|
|
1952
|
+
fastify.addHook("preHandler", async (request, reply) => {
|
|
1953
|
+
const ok = await verifyIdentity(request, reply, options);
|
|
1954
|
+
if (!ok) {
|
|
1955
|
+
return reply;
|
|
1956
|
+
}
|
|
1697
1957
|
});
|
|
1698
1958
|
}
|
|
1699
|
-
function signRequest(method, path, body, privateKey, publicKeyHex) {
|
|
1959
|
+
function signRequest(method, path, body, privateKey, publicKeyHex, agentIdOverride) {
|
|
1700
1960
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1701
|
-
const
|
|
1702
|
-
|
|
1703
|
-
path,
|
|
1704
|
-
timestamp,
|
|
1705
|
-
publicKey: publicKeyHex
|
|
1706
|
-
};
|
|
1707
|
-
void body;
|
|
1961
|
+
const agentId = agentIdOverride ?? deriveAgentId(publicKeyHex);
|
|
1962
|
+
const payload = buildIdentityPayload(method, path, timestamp, publicKeyHex, agentId, body);
|
|
1708
1963
|
const signature = signEscrowReceipt(payload, privateKey);
|
|
1709
1964
|
return {
|
|
1965
|
+
"X-Agent-Id": agentId,
|
|
1710
1966
|
"X-Agent-PublicKey": publicKeyHex,
|
|
1711
1967
|
"X-Agent-Signature": signature,
|
|
1712
1968
|
"X-Agent-Timestamp": timestamp
|
|
@@ -2290,92 +2546,6 @@ function getJobsByRelayOwner(db, relayOwner) {
|
|
|
2290
2546
|
).all(relayOwner, "queued");
|
|
2291
2547
|
}
|
|
2292
2548
|
|
|
2293
|
-
// src/identity/identity.ts
|
|
2294
|
-
import { z as z2 } from "zod";
|
|
2295
|
-
import { createHash } from "crypto";
|
|
2296
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
2297
|
-
import { join as join2 } from "path";
|
|
2298
|
-
var AgentIdentitySchema = z2.object({
|
|
2299
|
-
/** Deterministic ID derived from public key: sha256(hex).slice(0, 16). */
|
|
2300
|
-
agent_id: z2.string().min(1),
|
|
2301
|
-
/** Human-readable owner name (from config or init). */
|
|
2302
|
-
owner: z2.string().min(1),
|
|
2303
|
-
/** Hex-encoded Ed25519 public key. */
|
|
2304
|
-
public_key: z2.string().min(1),
|
|
2305
|
-
/** ISO 8601 timestamp of identity creation. */
|
|
2306
|
-
created_at: z2.string().datetime(),
|
|
2307
|
-
/** Optional guarantor info if linked to a human. */
|
|
2308
|
-
guarantor: z2.object({
|
|
2309
|
-
github_login: z2.string().min(1),
|
|
2310
|
-
verified_at: z2.string().datetime()
|
|
2311
|
-
}).optional()
|
|
2312
|
-
});
|
|
2313
|
-
var AgentCertificateSchema = z2.object({
|
|
2314
|
-
identity: AgentIdentitySchema,
|
|
2315
|
-
/** ISO 8601 timestamp of certificate issuance. */
|
|
2316
|
-
issued_at: z2.string().datetime(),
|
|
2317
|
-
/** ISO 8601 timestamp of certificate expiry. */
|
|
2318
|
-
expires_at: z2.string().datetime(),
|
|
2319
|
-
/** Hex-encoded public key of the issuer (same as identity for self-signed). */
|
|
2320
|
-
issuer_public_key: z2.string().min(1),
|
|
2321
|
-
/** Base64url Ed25519 signature over { identity, issued_at, expires_at, issuer_public_key }. */
|
|
2322
|
-
signature: z2.string().min(1)
|
|
2323
|
-
});
|
|
2324
|
-
var IDENTITY_FILENAME = "identity.json";
|
|
2325
|
-
function deriveAgentId(publicKeyHex) {
|
|
2326
|
-
return createHash("sha256").update(publicKeyHex, "hex").digest("hex").slice(0, 16);
|
|
2327
|
-
}
|
|
2328
|
-
function createIdentity(configDir, owner) {
|
|
2329
|
-
if (!existsSync3(configDir)) {
|
|
2330
|
-
mkdirSync2(configDir, { recursive: true });
|
|
2331
|
-
}
|
|
2332
|
-
let keys;
|
|
2333
|
-
try {
|
|
2334
|
-
keys = loadKeyPair(configDir);
|
|
2335
|
-
} catch {
|
|
2336
|
-
keys = generateKeyPair();
|
|
2337
|
-
saveKeyPair(configDir, keys);
|
|
2338
|
-
}
|
|
2339
|
-
const publicKeyHex = keys.publicKey.toString("hex");
|
|
2340
|
-
const agentId = deriveAgentId(publicKeyHex);
|
|
2341
|
-
const identity = {
|
|
2342
|
-
agent_id: agentId,
|
|
2343
|
-
owner,
|
|
2344
|
-
public_key: publicKeyHex,
|
|
2345
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2346
|
-
};
|
|
2347
|
-
saveIdentity(configDir, identity);
|
|
2348
|
-
return identity;
|
|
2349
|
-
}
|
|
2350
|
-
function loadIdentity(configDir) {
|
|
2351
|
-
const filePath = join2(configDir, IDENTITY_FILENAME);
|
|
2352
|
-
if (!existsSync3(filePath)) return null;
|
|
2353
|
-
try {
|
|
2354
|
-
const raw = readFileSync3(filePath, "utf-8");
|
|
2355
|
-
return AgentIdentitySchema.parse(JSON.parse(raw));
|
|
2356
|
-
} catch {
|
|
2357
|
-
return null;
|
|
2358
|
-
}
|
|
2359
|
-
}
|
|
2360
|
-
function saveIdentity(configDir, identity) {
|
|
2361
|
-
if (!existsSync3(configDir)) {
|
|
2362
|
-
mkdirSync2(configDir, { recursive: true });
|
|
2363
|
-
}
|
|
2364
|
-
const filePath = join2(configDir, IDENTITY_FILENAME);
|
|
2365
|
-
writeFileSync2(filePath, JSON.stringify(identity, null, 2), "utf-8");
|
|
2366
|
-
}
|
|
2367
|
-
function ensureIdentity(configDir, owner) {
|
|
2368
|
-
const existing = loadIdentity(configDir);
|
|
2369
|
-
if (existing) {
|
|
2370
|
-
if (existing.owner !== owner) {
|
|
2371
|
-
existing.owner = owner;
|
|
2372
|
-
saveIdentity(configDir, existing);
|
|
2373
|
-
}
|
|
2374
|
-
return existing;
|
|
2375
|
-
}
|
|
2376
|
-
return createIdentity(configDir, owner);
|
|
2377
|
-
}
|
|
2378
|
-
|
|
2379
2549
|
// src/hub-agent/crypto.ts
|
|
2380
2550
|
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
2381
2551
|
function getMasterKey() {
|
|
@@ -3313,7 +3483,7 @@ async function creditRoutesPlugin(fastify, options) {
|
|
|
3313
3483
|
}
|
|
3314
3484
|
initFreeTierTable(creditDb);
|
|
3315
3485
|
await fastify.register(async (scope) => {
|
|
3316
|
-
identityAuthPlugin(scope);
|
|
3486
|
+
identityAuthPlugin(scope, { agentDb: creditDb });
|
|
3317
3487
|
scope.post("/api/credits/hold", {
|
|
3318
3488
|
schema: {
|
|
3319
3489
|
tags: ["credits"],
|
|
@@ -4473,7 +4643,7 @@ function createRegistryServer(opts) {
|
|
|
4473
4643
|
type: "apiKey",
|
|
4474
4644
|
in: "header",
|
|
4475
4645
|
name: "X-Agent-PublicKey",
|
|
4476
|
-
description: "Ed25519 public key (hex). Also requires X-Agent-Signature and X-Agent-Timestamp headers."
|
|
4646
|
+
description: "Ed25519 public key (hex). Also requires X-Agent-Id, X-Agent-Signature, and X-Agent-Timestamp headers."
|
|
4477
4647
|
}
|
|
4478
4648
|
}
|
|
4479
4649
|
}
|
|
@@ -4486,7 +4656,7 @@ function createRegistryServer(opts) {
|
|
|
4486
4656
|
void server.register(cors, {
|
|
4487
4657
|
origin: true,
|
|
4488
4658
|
methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
|
|
4489
|
-
allowedHeaders: ["Content-Type", "Authorization", "X-Agent-PublicKey", "X-Agent-Signature", "X-Agent-Timestamp"]
|
|
4659
|
+
allowedHeaders: ["Content-Type", "Authorization", "X-Agent-Id", "X-Agent-PublicKey", "X-Agent-Signature", "X-Agent-Timestamp"]
|
|
4490
4660
|
});
|
|
4491
4661
|
void server.register(fastifyWebsocket);
|
|
4492
4662
|
let relayState = null;
|
|
@@ -5826,12 +5996,133 @@ async function stopAnnouncement() {
|
|
|
5826
5996
|
});
|
|
5827
5997
|
}
|
|
5828
5998
|
|
|
5999
|
+
// src/runtime/resolve-self-cli.ts
|
|
6000
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
6001
|
+
import { existsSync as existsSync5, realpathSync } from "fs";
|
|
6002
|
+
import { createRequire } from "module";
|
|
6003
|
+
import { homedir as homedir2 } from "os";
|
|
6004
|
+
import { basename, isAbsolute, join as join4, resolve } from "path";
|
|
6005
|
+
function resolveSelfCli() {
|
|
6006
|
+
const require2 = createRequire(import.meta.url);
|
|
6007
|
+
return resolveSelfCliWithDeps({
|
|
6008
|
+
argv1: process.argv[1],
|
|
6009
|
+
cwd: process.cwd(),
|
|
6010
|
+
platform: process.platform,
|
|
6011
|
+
homeDir: homedir2(),
|
|
6012
|
+
envPath: process.env["PATH"],
|
|
6013
|
+
exists: existsSync5,
|
|
6014
|
+
realpath: realpathSync,
|
|
6015
|
+
runWhich: (pathEnv) => execFileSync2("which", ["agentbnb"], {
|
|
6016
|
+
encoding: "utf8",
|
|
6017
|
+
env: { ...process.env, PATH: pathEnv }
|
|
6018
|
+
}).trim(),
|
|
6019
|
+
requireResolve: (id) => require2.resolve(id)
|
|
6020
|
+
});
|
|
6021
|
+
}
|
|
6022
|
+
function resolveSelfCliWithDeps(deps) {
|
|
6023
|
+
const tried = [];
|
|
6024
|
+
const tryCandidate = (rawPath, label, requireCliShape = false) => {
|
|
6025
|
+
if (!rawPath || rawPath.trim().length === 0) {
|
|
6026
|
+
tried.push(`${label}: <empty>`);
|
|
6027
|
+
return null;
|
|
6028
|
+
}
|
|
6029
|
+
const maybeAbsolute = isAbsolute(rawPath) ? rawPath : resolve(deps.cwd, rawPath);
|
|
6030
|
+
tried.push(`${label}: ${maybeAbsolute}`);
|
|
6031
|
+
if (!deps.exists(maybeAbsolute)) return null;
|
|
6032
|
+
const resolvedPath = safeRealpath(deps.realpath, maybeAbsolute);
|
|
6033
|
+
if (requireCliShape && !looksLikeAgentbnbCli(resolvedPath)) return null;
|
|
6034
|
+
return resolvedPath;
|
|
6035
|
+
};
|
|
6036
|
+
const argvPath = tryCandidate(deps.argv1, "process.argv[1]", true);
|
|
6037
|
+
if (argvPath) return argvPath;
|
|
6038
|
+
const fullPathEnv = buildFullPathEnv(deps.envPath, deps.homeDir);
|
|
6039
|
+
tried.push(`which agentbnb PATH=${fullPathEnv}`);
|
|
6040
|
+
try {
|
|
6041
|
+
const whichPath = tryCandidate(deps.runWhich(fullPathEnv), "which agentbnb");
|
|
6042
|
+
if (whichPath) return whichPath;
|
|
6043
|
+
} catch (err) {
|
|
6044
|
+
tried.push(`which agentbnb failed: ${extractErrorMessage(err)}`);
|
|
6045
|
+
}
|
|
6046
|
+
const npmGlobalCandidates = ["/usr/local/bin/agentbnb", "/opt/homebrew/bin/agentbnb"];
|
|
6047
|
+
for (const candidate of npmGlobalCandidates) {
|
|
6048
|
+
const resolvedPath = tryCandidate(candidate, "npm-global");
|
|
6049
|
+
if (resolvedPath) return resolvedPath;
|
|
6050
|
+
}
|
|
6051
|
+
const pnpmCandidates = getPnpmGlobalCandidates(deps.platform, deps.homeDir);
|
|
6052
|
+
for (const candidate of pnpmCandidates) {
|
|
6053
|
+
const resolvedPath = tryCandidate(candidate, "pnpm-global");
|
|
6054
|
+
if (resolvedPath) return resolvedPath;
|
|
6055
|
+
}
|
|
6056
|
+
try {
|
|
6057
|
+
const requireResolved = deps.requireResolve("agentbnb/dist/cli/index.js");
|
|
6058
|
+
const resolvedPath = tryCandidate(requireResolved, "require.resolve(agentbnb/dist/cli/index.js)");
|
|
6059
|
+
if (resolvedPath) return resolvedPath;
|
|
6060
|
+
} catch (err) {
|
|
6061
|
+
tried.push(`require.resolve(agentbnb/dist/cli/index.js) failed: ${extractErrorMessage(err)}`);
|
|
6062
|
+
}
|
|
6063
|
+
throw new AgentBnBError(
|
|
6064
|
+
`Unable to resolve absolute path to agentbnb CLI.
|
|
6065
|
+
Paths tried:
|
|
6066
|
+
${tried.map((item) => `- ${item}`).join("\n")}`,
|
|
6067
|
+
"CLI_ENTRY_NOT_FOUND"
|
|
6068
|
+
);
|
|
6069
|
+
}
|
|
6070
|
+
function buildFullPathEnv(pathEnv, homeDir) {
|
|
6071
|
+
const values = /* @__PURE__ */ new Set();
|
|
6072
|
+
for (const item of (pathEnv ?? "").split(":")) {
|
|
6073
|
+
if (item.trim()) values.add(item.trim());
|
|
6074
|
+
}
|
|
6075
|
+
for (const extra of [
|
|
6076
|
+
"/usr/local/bin",
|
|
6077
|
+
"/opt/homebrew/bin",
|
|
6078
|
+
"/usr/bin",
|
|
6079
|
+
"/bin",
|
|
6080
|
+
"/usr/sbin",
|
|
6081
|
+
"/sbin",
|
|
6082
|
+
join4(homeDir, ".local", "bin"),
|
|
6083
|
+
join4(homeDir, "Library", "pnpm"),
|
|
6084
|
+
join4(homeDir, ".local", "share", "pnpm")
|
|
6085
|
+
]) {
|
|
6086
|
+
values.add(extra);
|
|
6087
|
+
}
|
|
6088
|
+
return [...values].join(":");
|
|
6089
|
+
}
|
|
6090
|
+
function safeRealpath(realpath, path) {
|
|
6091
|
+
try {
|
|
6092
|
+
return realpath(path);
|
|
6093
|
+
} catch {
|
|
6094
|
+
return path;
|
|
6095
|
+
}
|
|
6096
|
+
}
|
|
6097
|
+
function getPnpmGlobalCandidates(platform, homeDir) {
|
|
6098
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
6099
|
+
if (platform === "darwin") {
|
|
6100
|
+
candidates.add(join4(homeDir, "Library", "pnpm", "agentbnb"));
|
|
6101
|
+
}
|
|
6102
|
+
if (platform === "linux") {
|
|
6103
|
+
candidates.add(join4(homeDir, ".local", "share", "pnpm", "agentbnb"));
|
|
6104
|
+
}
|
|
6105
|
+
candidates.add(join4(homeDir, "Library", "pnpm", "agentbnb"));
|
|
6106
|
+
candidates.add(join4(homeDir, ".local", "share", "pnpm", "agentbnb"));
|
|
6107
|
+
return [...candidates];
|
|
6108
|
+
}
|
|
6109
|
+
function looksLikeAgentbnbCli(path) {
|
|
6110
|
+
const normalized = path.replace(/\\/g, "/").toLowerCase();
|
|
6111
|
+
const fileName = basename(normalized);
|
|
6112
|
+
if (fileName === "agentbnb" || fileName === "agentbnb.cmd" || fileName === "agentbnb.exe") {
|
|
6113
|
+
return true;
|
|
6114
|
+
}
|
|
6115
|
+
return normalized.includes("/agentbnb/dist/cli/index.") || normalized.endsWith("/dist/cli/index.js") || normalized.endsWith("/dist/cli/index.mjs") || normalized.endsWith("/dist/cli/index.cjs");
|
|
6116
|
+
}
|
|
6117
|
+
function extractErrorMessage(err) {
|
|
6118
|
+
if (err instanceof Error && err.message) return err.message;
|
|
6119
|
+
return String(err);
|
|
6120
|
+
}
|
|
6121
|
+
|
|
5829
6122
|
// src/runtime/service-coordinator.ts
|
|
5830
6123
|
import { spawn as spawn2 } from "child_process";
|
|
5831
|
-
import {
|
|
5832
|
-
import {
|
|
5833
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5834
|
-
import { dirname as dirname3, join as join4, resolve } from "path";
|
|
6124
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
|
|
6125
|
+
import { join as join5 } from "path";
|
|
5835
6126
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
5836
6127
|
var ServiceCoordinator = class {
|
|
5837
6128
|
config;
|
|
@@ -5952,7 +6243,7 @@ var ServiceCoordinator = class {
|
|
|
5952
6243
|
return {
|
|
5953
6244
|
port: opts?.port ?? this.config.gateway_port,
|
|
5954
6245
|
handlerUrl: opts?.handlerUrl ?? "http://localhost:8080",
|
|
5955
|
-
skillsYamlPath: opts?.skillsYamlPath ??
|
|
6246
|
+
skillsYamlPath: opts?.skillsYamlPath ?? join5(getConfigDir(), "skills.yaml"),
|
|
5956
6247
|
registryPort: opts?.registryPort ?? 7701,
|
|
5957
6248
|
registryUrl: opts?.registryUrl ?? this.config.registry ?? "",
|
|
5958
6249
|
relay: opts?.relay ?? true,
|
|
@@ -6035,7 +6326,7 @@ var ServiceCoordinator = class {
|
|
|
6035
6326
|
}
|
|
6036
6327
|
if (opts.registryUrl && opts.relay) {
|
|
6037
6328
|
const { RelayClient: RelayClient2 } = await import("../../websocket-client-4Z5P54RU.js");
|
|
6038
|
-
const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("../../execute-
|
|
6329
|
+
const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("../../execute-WOS457HW.js");
|
|
6039
6330
|
const cards = listCards(this.runtime.registryDb, this.config.owner);
|
|
6040
6331
|
const card = cards[0] ?? {
|
|
6041
6332
|
id: randomUUID7(),
|
|
@@ -6142,7 +6433,8 @@ var ServiceCoordinator = class {
|
|
|
6142
6433
|
spawnManagedProcess(opts) {
|
|
6143
6434
|
const runtime = loadPersistedRuntime(getConfigDir());
|
|
6144
6435
|
const nodeExec = resolveNodeExecutable(runtime);
|
|
6145
|
-
const
|
|
6436
|
+
const cliPath = resolveSelfCli();
|
|
6437
|
+
const cliArgs = [cliPath, "serve", ...this.buildServeArgs(opts)];
|
|
6146
6438
|
const child = spawn2(nodeExec, cliArgs, {
|
|
6147
6439
|
detached: true,
|
|
6148
6440
|
stdio: "ignore",
|
|
@@ -6303,8 +6595,8 @@ var ServiceCoordinator = class {
|
|
|
6303
6595
|
};
|
|
6304
6596
|
};
|
|
6305
6597
|
function loadPersistedRuntime(configDir) {
|
|
6306
|
-
const runtimePath =
|
|
6307
|
-
if (!
|
|
6598
|
+
const runtimePath = join5(configDir, "runtime.json");
|
|
6599
|
+
if (!existsSync6(runtimePath)) return null;
|
|
6308
6600
|
try {
|
|
6309
6601
|
const raw = readFileSync4(runtimePath, "utf8");
|
|
6310
6602
|
const parsed = JSON.parse(raw);
|
|
@@ -6328,28 +6620,6 @@ function resolveNodeExecutable(runtime) {
|
|
|
6328
6620
|
}
|
|
6329
6621
|
return process.execPath;
|
|
6330
6622
|
}
|
|
6331
|
-
function resolveCliLaunchArgs(serveArgs) {
|
|
6332
|
-
const require2 = createRequire(import.meta.url);
|
|
6333
|
-
try {
|
|
6334
|
-
const distCli2 = require2.resolve("agentbnb/dist/cli/index.js");
|
|
6335
|
-
return [distCli2, "serve", ...serveArgs];
|
|
6336
|
-
} catch {
|
|
6337
|
-
}
|
|
6338
|
-
const projectRoot = resolve(dirname3(fileURLToPath2(import.meta.url)), "..", "..");
|
|
6339
|
-
const distCli = join4(projectRoot, "dist", "cli", "index.js");
|
|
6340
|
-
if (existsSync5(distCli)) {
|
|
6341
|
-
return [distCli, "serve", ...serveArgs];
|
|
6342
|
-
}
|
|
6343
|
-
const srcCli = join4(projectRoot, "src", "cli", "index.ts");
|
|
6344
|
-
if (existsSync5(srcCli)) {
|
|
6345
|
-
const tsxCli = require2.resolve("tsx/dist/cli.mjs");
|
|
6346
|
-
return [tsxCli, srcCli, "serve", ...serveArgs];
|
|
6347
|
-
}
|
|
6348
|
-
throw new AgentBnBError(
|
|
6349
|
-
"Unable to locate AgentBnB CLI entry (dist/cli/index.js or src/cli/index.ts)",
|
|
6350
|
-
"CLI_ENTRY_NOT_FOUND"
|
|
6351
|
-
);
|
|
6352
|
-
}
|
|
6353
6623
|
function isPidAlive(pid) {
|
|
6354
6624
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
6355
6625
|
try {
|
|
@@ -6458,7 +6728,7 @@ var AgentBnBService = class {
|
|
|
6458
6728
|
const creditDb = openCreditDb(this.config.credit_db_path);
|
|
6459
6729
|
creditDb.pragma("busy_timeout = 5000");
|
|
6460
6730
|
try {
|
|
6461
|
-
const keys = this.
|
|
6731
|
+
const { keys } = loadOrRepairIdentity(getConfigDir(), this.config.owner);
|
|
6462
6732
|
const { escrowId, receipt } = createSignedEscrowReceipt(
|
|
6463
6733
|
creditDb,
|
|
6464
6734
|
keys.privateKey,
|
|
@@ -6667,20 +6937,9 @@ var AgentBnBService = class {
|
|
|
6667
6937
|
tempRelay.disconnect();
|
|
6668
6938
|
}
|
|
6669
6939
|
}
|
|
6670
|
-
getOrCreateKeyPair() {
|
|
6671
|
-
const configDir = getConfigDir();
|
|
6672
|
-
try {
|
|
6673
|
-
return loadKeyPair(configDir);
|
|
6674
|
-
} catch {
|
|
6675
|
-
const keys = generateKeyPair();
|
|
6676
|
-
saveKeyPair(configDir, keys);
|
|
6677
|
-
return keys;
|
|
6678
|
-
}
|
|
6679
|
-
}
|
|
6680
6940
|
loadIdentityAuth() {
|
|
6681
6941
|
const configDir = getConfigDir();
|
|
6682
|
-
const identity =
|
|
6683
|
-
const keys = this.getOrCreateKeyPair();
|
|
6942
|
+
const { identity, keys } = loadOrRepairIdentity(configDir, this.config.owner);
|
|
6684
6943
|
return {
|
|
6685
6944
|
agentId: identity.agent_id,
|
|
6686
6945
|
publicKey: identity.public_key,
|
|
@@ -6748,9 +7007,9 @@ function isNetworkError(err) {
|
|
|
6748
7007
|
}
|
|
6749
7008
|
|
|
6750
7009
|
// skills/agentbnb/openclaw-tools.ts
|
|
6751
|
-
import { readFileSync as readFileSync5, existsSync as
|
|
6752
|
-
import { join as
|
|
6753
|
-
import { homedir as
|
|
7010
|
+
import { readFileSync as readFileSync5, existsSync as existsSync7 } from "fs";
|
|
7011
|
+
import { join as join6 } from "path";
|
|
7012
|
+
import { homedir as homedir3 } from "os";
|
|
6754
7013
|
|
|
6755
7014
|
// src/mcp/tools/discover.ts
|
|
6756
7015
|
import { z as z9 } from "zod";
|
|
@@ -6917,7 +7176,12 @@ async function handleRequest(args, ctx) {
|
|
|
6917
7176
|
gatewayUrl,
|
|
6918
7177
|
token: "",
|
|
6919
7178
|
cardId,
|
|
6920
|
-
params: { ...args.params ?? {}, ...args.skill_id ? { skill_id: args.skill_id } : {}, requester: ctx.config.owner }
|
|
7179
|
+
params: { ...args.params ?? {}, ...args.skill_id ? { skill_id: args.skill_id } : {}, requester: ctx.config.owner },
|
|
7180
|
+
identity: {
|
|
7181
|
+
agentId: ctx.identity.agent_id,
|
|
7182
|
+
publicKey: ctx.identity.public_key,
|
|
7183
|
+
privateKey: keys.privateKey
|
|
7184
|
+
}
|
|
6921
7185
|
});
|
|
6922
7186
|
await ledger.settle(escrowId, targetOwner ?? "unknown");
|
|
6923
7187
|
return {
|
|
@@ -7257,19 +7521,19 @@ async function handlePublish(args, ctx) {
|
|
|
7257
7521
|
var contextCache = /* @__PURE__ */ new Map();
|
|
7258
7522
|
function resolveConfigDir(toolCtx) {
|
|
7259
7523
|
if (toolCtx.agentDir) {
|
|
7260
|
-
return toolCtx.agentDir.endsWith(".agentbnb") ? toolCtx.agentDir :
|
|
7524
|
+
return toolCtx.agentDir.endsWith(".agentbnb") ? toolCtx.agentDir : join6(toolCtx.agentDir, ".agentbnb");
|
|
7261
7525
|
}
|
|
7262
7526
|
if (toolCtx.workspaceDir) {
|
|
7263
|
-
return
|
|
7527
|
+
return join6(toolCtx.workspaceDir, ".agentbnb");
|
|
7264
7528
|
}
|
|
7265
|
-
return
|
|
7529
|
+
return join6(homedir3(), ".agentbnb");
|
|
7266
7530
|
}
|
|
7267
7531
|
function buildMcpContext(toolCtx) {
|
|
7268
7532
|
const configDir = resolveConfigDir(toolCtx);
|
|
7269
7533
|
const cached = contextCache.get(configDir);
|
|
7270
7534
|
if (cached) return cached;
|
|
7271
|
-
const configPath =
|
|
7272
|
-
if (!
|
|
7535
|
+
const configPath = join6(configDir, "config.json");
|
|
7536
|
+
if (!existsSync7(configPath)) {
|
|
7273
7537
|
throw new Error(
|
|
7274
7538
|
`AgentBnB not initialized at ${configDir}. Run \`agentbnb init\` or activate the plugin first.`
|
|
7275
7539
|
);
|
|
@@ -7434,18 +7698,18 @@ function resolveWorkspaceDir() {
|
|
|
7434
7698
|
if (process.env["AGENTBNB_DIR"]) {
|
|
7435
7699
|
return process.env["AGENTBNB_DIR"];
|
|
7436
7700
|
}
|
|
7437
|
-
const openclawAgentsDir =
|
|
7701
|
+
const openclawAgentsDir = join7(homedir4(), ".openclaw", "agents");
|
|
7438
7702
|
const cwd = process.cwd();
|
|
7439
7703
|
if (cwd.startsWith(openclawAgentsDir + "/")) {
|
|
7440
7704
|
const relative = cwd.slice(openclawAgentsDir.length + 1);
|
|
7441
7705
|
const agentName = relative.split("/")[0];
|
|
7442
|
-
return
|
|
7706
|
+
return join7(openclawAgentsDir, agentName, ".agentbnb");
|
|
7443
7707
|
}
|
|
7444
|
-
return
|
|
7708
|
+
return join7(homedir4(), ".agentbnb");
|
|
7445
7709
|
}
|
|
7446
7710
|
function registerDecomposerCard(configDir, owner) {
|
|
7447
7711
|
try {
|
|
7448
|
-
const db = openDatabase(
|
|
7712
|
+
const db = openDatabase(join7(configDir, "registry.db"));
|
|
7449
7713
|
const existing = db.prepare(
|
|
7450
7714
|
"SELECT id FROM capability_cards WHERE owner = ? AND json_extract(data, '$.capability_type') = ?"
|
|
7451
7715
|
).get(owner, "task_decomposition");
|
|
@@ -7503,37 +7767,40 @@ function registerDecomposerCard(configDir, owner) {
|
|
|
7503
7767
|
}
|
|
7504
7768
|
}
|
|
7505
7769
|
function findCli() {
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7770
|
+
try {
|
|
7771
|
+
return resolveSelfCli();
|
|
7772
|
+
} catch {
|
|
7773
|
+
return null;
|
|
7509
7774
|
}
|
|
7510
|
-
return null;
|
|
7511
7775
|
}
|
|
7512
7776
|
async function runCommand(cmd, env) {
|
|
7513
7777
|
return execAsync(cmd, { env });
|
|
7514
7778
|
}
|
|
7515
7779
|
function deriveAgentName(configDir) {
|
|
7516
|
-
const parent =
|
|
7517
|
-
if (parent && parent !== "." && parent !== ".agentbnb" && parent !==
|
|
7780
|
+
const parent = basename2(dirname3(configDir));
|
|
7781
|
+
if (parent && parent !== "." && parent !== ".agentbnb" && parent !== homedir4().split("/").pop()) {
|
|
7518
7782
|
return parent;
|
|
7519
7783
|
}
|
|
7520
7784
|
return `agent-${randomUUID10().slice(0, 8)}`;
|
|
7521
7785
|
}
|
|
7522
|
-
var defaultDeps = {
|
|
7786
|
+
var defaultDeps = { resolveSelfCli, runCommand };
|
|
7523
7787
|
async function autoOnboard(configDir, deps = defaultDeps) {
|
|
7524
7788
|
process.stderr.write("[agentbnb] First-time setup: initializing agent identity...\n");
|
|
7525
|
-
|
|
7526
|
-
|
|
7789
|
+
let cliPath;
|
|
7790
|
+
try {
|
|
7791
|
+
cliPath = deps.resolveSelfCli();
|
|
7792
|
+
} catch {
|
|
7527
7793
|
process.stderr.write("[agentbnb] CLI not found. Run: npm install -g agentbnb\n");
|
|
7528
7794
|
throw new AgentBnBError(
|
|
7529
7795
|
"agentbnb CLI not found in PATH. Install with: npm install -g agentbnb",
|
|
7530
7796
|
"INIT_FAILED"
|
|
7531
7797
|
);
|
|
7532
7798
|
}
|
|
7799
|
+
const quotedCliPath = quoteShellArg(cliPath);
|
|
7533
7800
|
const env = { ...process.env, AGENTBNB_DIR: configDir };
|
|
7534
7801
|
const agentName = deriveAgentName(configDir);
|
|
7535
7802
|
try {
|
|
7536
|
-
await deps.runCommand(
|
|
7803
|
+
await deps.runCommand(`${quotedCliPath} init --owner "${agentName}" --yes --no-detect`, env);
|
|
7537
7804
|
process.stderr.write(`[agentbnb] Agent "${agentName}" initialized.
|
|
7538
7805
|
`);
|
|
7539
7806
|
} catch (err) {
|
|
@@ -7541,7 +7808,7 @@ async function autoOnboard(configDir, deps = defaultDeps) {
|
|
|
7541
7808
|
throw new AgentBnBError(`Auto-init failed: ${msg}`, "INIT_FAILED");
|
|
7542
7809
|
}
|
|
7543
7810
|
try {
|
|
7544
|
-
await deps.runCommand(
|
|
7811
|
+
await deps.runCommand(`${quotedCliPath} openclaw sync`, env);
|
|
7545
7812
|
process.stderr.write("[agentbnb] Capabilities published from SOUL.md.\n");
|
|
7546
7813
|
} catch {
|
|
7547
7814
|
process.stderr.write("[agentbnb] Note: openclaw sync skipped (SOUL.md may not exist yet).\n");
|
|
@@ -7553,6 +7820,9 @@ async function autoOnboard(configDir, deps = defaultDeps) {
|
|
|
7553
7820
|
process.stderr.write("[agentbnb] Agent initialized and published to AgentBnB network.\n");
|
|
7554
7821
|
return config;
|
|
7555
7822
|
}
|
|
7823
|
+
function quoteShellArg(input) {
|
|
7824
|
+
return `'${input.replace(/'/g, `'\\''`)}'`;
|
|
7825
|
+
}
|
|
7556
7826
|
async function activate(config = {}, _onboardDeps) {
|
|
7557
7827
|
if (config.agentDir) {
|
|
7558
7828
|
process.env["AGENTBNB_DIR"] = config.agentDir;
|
|
@@ -7561,7 +7831,7 @@ async function activate(config = {}, _onboardDeps) {
|
|
|
7561
7831
|
`
|
|
7562
7832
|
);
|
|
7563
7833
|
} else if (config.workspaceDir) {
|
|
7564
|
-
const derived =
|
|
7834
|
+
const derived = join7(config.workspaceDir, ".agentbnb");
|
|
7565
7835
|
process.env["AGENTBNB_DIR"] = derived;
|
|
7566
7836
|
process.stderr.write(
|
|
7567
7837
|
`[agentbnb] AGENTBNB_DIR derived from config.workspaceDir: ${derived}
|
|
@@ -7590,7 +7860,7 @@ async function activate(config = {}, _onboardDeps) {
|
|
|
7590
7860
|
`[agentbnb] activate: owner=${agentConfig.owner} config=${configDir}/config.json
|
|
7591
7861
|
`
|
|
7592
7862
|
);
|
|
7593
|
-
const guard = new ProcessGuard(
|
|
7863
|
+
const guard = new ProcessGuard(join7(configDir, ".pid"));
|
|
7594
7864
|
const coordinator = new ServiceCoordinator(agentConfig, guard);
|
|
7595
7865
|
const service = new AgentBnBService(coordinator, agentConfig);
|
|
7596
7866
|
const opts = {
|