agentbnb 8.4.3 → 8.4.5
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-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 +904 -473
- 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-QG3FKU5Q.js → server-GSG5T2TZ.js} +20 -17
- package/dist/{service-coordinator-2HDVHDFD.js → service-coordinator-ZO7QHQ6U.js} +101 -7
- package/dist/skills/agentbnb/bootstrap.js +277 -738
- 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
|
@@ -14,16 +14,11 @@ import {
|
|
|
14
14
|
orchestrate,
|
|
15
15
|
requestViaTemporaryRelay,
|
|
16
16
|
resolvePendingRequest
|
|
17
|
-
} from "../../chunk-
|
|
17
|
+
} from "../../chunk-OPRCWXD5.js";
|
|
18
18
|
import {
|
|
19
|
-
generateKeyPair,
|
|
20
|
-
loadKeyPair,
|
|
21
19
|
requestCapability,
|
|
22
|
-
requestViaRelay
|
|
23
|
-
|
|
24
|
-
signEscrowReceipt,
|
|
25
|
-
verifyEscrowReceipt
|
|
26
|
-
} from "../../chunk-R4F4XII4.js";
|
|
20
|
+
requestViaRelay
|
|
21
|
+
} from "../../chunk-YKMBFQC2.js";
|
|
27
22
|
import {
|
|
28
23
|
RelayClient,
|
|
29
24
|
RelayMessageSchema
|
|
@@ -32,9 +27,15 @@ import {
|
|
|
32
27
|
loadPeers
|
|
33
28
|
} from "../../chunk-HLUEOLSZ.js";
|
|
34
29
|
import {
|
|
30
|
+
createLedger,
|
|
31
|
+
deriveAgentId,
|
|
32
|
+
ensureIdentity,
|
|
35
33
|
executeCapabilityBatch,
|
|
36
|
-
executeCapabilityRequest
|
|
37
|
-
|
|
34
|
+
executeCapabilityRequest,
|
|
35
|
+
identityAuthPlugin,
|
|
36
|
+
loadOrRepairIdentity,
|
|
37
|
+
syncCreditsFromRegistry
|
|
38
|
+
} from "../../chunk-5SIGMKOD.js";
|
|
38
39
|
import {
|
|
39
40
|
bootstrapAgent,
|
|
40
41
|
buildReputationMap,
|
|
@@ -56,6 +57,12 @@ import {
|
|
|
56
57
|
settleEscrow
|
|
57
58
|
} from "../../chunk-NQANA6WH.js";
|
|
58
59
|
import "../../chunk-6QMDJVMS.js";
|
|
60
|
+
import {
|
|
61
|
+
generateKeyPair,
|
|
62
|
+
loadKeyPair,
|
|
63
|
+
signEscrowReceipt,
|
|
64
|
+
verifyEscrowReceipt
|
|
65
|
+
} from "../../chunk-GIEJVKZZ.js";
|
|
59
66
|
import {
|
|
60
67
|
getConfigDir,
|
|
61
68
|
loadConfig
|
|
@@ -81,17 +88,15 @@ import {
|
|
|
81
88
|
updateSkillAvailability,
|
|
82
89
|
updateSkillIdleRate
|
|
83
90
|
} from "../../chunk-ZU2TP7CN.js";
|
|
84
|
-
import
|
|
85
|
-
lookupAgent
|
|
86
|
-
} from "../../chunk-EE3V3DXK.js";
|
|
91
|
+
import "../../chunk-EE3V3DXK.js";
|
|
87
92
|
import {
|
|
88
93
|
AgentBnBError,
|
|
89
94
|
AnyCardSchema
|
|
90
95
|
} from "../../chunk-I7KWA7OB.js";
|
|
91
96
|
|
|
92
97
|
// skills/agentbnb/bootstrap.ts
|
|
93
|
-
import { join as
|
|
94
|
-
import { existsSync as
|
|
98
|
+
import { join as join6, basename as basename2, dirname as dirname4 } from "path";
|
|
99
|
+
import { existsSync as existsSync7, writeFileSync as writeFileSync2 } from "fs";
|
|
95
100
|
import { homedir as homedir4 } from "os";
|
|
96
101
|
import { exec } from "child_process";
|
|
97
102
|
import { promisify as promisify2 } from "util";
|
|
@@ -1373,7 +1378,7 @@ var AgentRuntime = class {
|
|
|
1373
1378
|
}
|
|
1374
1379
|
const modes = /* @__PURE__ */ new Map();
|
|
1375
1380
|
if (this.conductorEnabled) {
|
|
1376
|
-
const { ConductorMode } = await import("../../conductor-mode-
|
|
1381
|
+
const { ConductorMode } = await import("../../conductor-mode-2F5OP7Q4.js");
|
|
1377
1382
|
const { registerConductorCard, CONDUCTOR_OWNER } = await import("../../card-BN643ZOY.js");
|
|
1378
1383
|
const { loadPeers: loadPeers2 } = await import("../../peers-CJ7T4RJO.js");
|
|
1379
1384
|
registerConductorCard(this.registryDb);
|
|
@@ -1690,11 +1695,11 @@ import swagger from "@fastify/swagger";
|
|
|
1690
1695
|
import swaggerUi from "@fastify/swagger-ui";
|
|
1691
1696
|
import fastifyStatic from "@fastify/static";
|
|
1692
1697
|
import fastifyWebsocket from "@fastify/websocket";
|
|
1693
|
-
import { join as
|
|
1698
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
1694
1699
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
1695
1700
|
import { fileURLToPath } from "url";
|
|
1696
|
-
import { existsSync as
|
|
1697
|
-
import { z as
|
|
1701
|
+
import { existsSync as existsSync3 } from "fs";
|
|
1702
|
+
import { z as z6 } from "zod";
|
|
1698
1703
|
|
|
1699
1704
|
// src/registry/pricing.ts
|
|
1700
1705
|
function getPricingStats(db, query) {
|
|
@@ -1737,566 +1742,6 @@ function computeMedian(sorted) {
|
|
|
1737
1742
|
return (sorted[mid - 1] + sorted[mid]) / 2;
|
|
1738
1743
|
}
|
|
1739
1744
|
|
|
1740
|
-
// src/credit/local-credit-ledger.ts
|
|
1741
|
-
var LocalCreditLedger = class {
|
|
1742
|
-
constructor(db) {
|
|
1743
|
-
this.db = db;
|
|
1744
|
-
}
|
|
1745
|
-
/**
|
|
1746
|
-
* Holds credits in escrow during capability execution.
|
|
1747
|
-
*
|
|
1748
|
-
* @param owner - Agent identifier (requester).
|
|
1749
|
-
* @param amount - Number of credits to hold.
|
|
1750
|
-
* @param cardId - Capability Card ID being requested.
|
|
1751
|
-
* @returns EscrowResult with the new escrowId.
|
|
1752
|
-
* @throws {AgentBnBError} with code 'INSUFFICIENT_CREDITS' if balance < amount.
|
|
1753
|
-
*/
|
|
1754
|
-
async hold(owner, amount, cardId) {
|
|
1755
|
-
const escrowId = holdEscrow(this.db, owner, amount, cardId);
|
|
1756
|
-
return { escrowId };
|
|
1757
|
-
}
|
|
1758
|
-
/**
|
|
1759
|
-
* Settles an escrow — transfers held credits to the capability provider.
|
|
1760
|
-
*
|
|
1761
|
-
* @param escrowId - The escrow ID to settle.
|
|
1762
|
-
* @param recipientOwner - Agent identifier who will receive the credits.
|
|
1763
|
-
* @throws {AgentBnBError} with code 'ESCROW_NOT_FOUND' if escrow does not exist.
|
|
1764
|
-
* @throws {AgentBnBError} with code 'ESCROW_ALREADY_SETTLED' if escrow is not in 'held' status.
|
|
1765
|
-
*/
|
|
1766
|
-
async settle(escrowId, recipientOwner) {
|
|
1767
|
-
settleEscrow(this.db, escrowId, recipientOwner);
|
|
1768
|
-
}
|
|
1769
|
-
/**
|
|
1770
|
-
* Releases an escrow — refunds credits back to the requester.
|
|
1771
|
-
*
|
|
1772
|
-
* @param escrowId - The escrow ID to release.
|
|
1773
|
-
* @throws {AgentBnBError} with code 'ESCROW_NOT_FOUND' if escrow does not exist.
|
|
1774
|
-
* @throws {AgentBnBError} with code 'ESCROW_ALREADY_SETTLED' if escrow is not in 'held' status.
|
|
1775
|
-
*/
|
|
1776
|
-
async release(escrowId) {
|
|
1777
|
-
releaseEscrow(this.db, escrowId);
|
|
1778
|
-
}
|
|
1779
|
-
/**
|
|
1780
|
-
* Returns the current credit balance for an agent.
|
|
1781
|
-
*
|
|
1782
|
-
* @param owner - Agent identifier.
|
|
1783
|
-
* @returns Current balance in credits (0 if agent is unknown).
|
|
1784
|
-
*/
|
|
1785
|
-
async getBalance(owner) {
|
|
1786
|
-
return getBalance(this.db, owner);
|
|
1787
|
-
}
|
|
1788
|
-
/**
|
|
1789
|
-
* Returns the transaction history for an agent, newest first.
|
|
1790
|
-
*
|
|
1791
|
-
* @param owner - Agent identifier.
|
|
1792
|
-
* @param limit - Maximum number of transactions to return. Defaults to 100.
|
|
1793
|
-
* @returns Array of credit transactions ordered newest first.
|
|
1794
|
-
*/
|
|
1795
|
-
async getHistory(owner, limit) {
|
|
1796
|
-
return getTransactions(this.db, owner, limit);
|
|
1797
|
-
}
|
|
1798
|
-
/**
|
|
1799
|
-
* Grants initial credits to an agent (bootstrap grant).
|
|
1800
|
-
* Idempotent — calling multiple times has no additional effect on balance.
|
|
1801
|
-
*
|
|
1802
|
-
* @param owner - Agent identifier.
|
|
1803
|
-
* @param amount - Number of credits to grant. Defaults to 100.
|
|
1804
|
-
*/
|
|
1805
|
-
async grant(owner, amount) {
|
|
1806
|
-
bootstrapAgent(this.db, owner, amount);
|
|
1807
|
-
}
|
|
1808
|
-
async rename(oldOwner, newOwner) {
|
|
1809
|
-
migrateOwner(this.db, oldOwner, newOwner);
|
|
1810
|
-
}
|
|
1811
|
-
};
|
|
1812
|
-
|
|
1813
|
-
// src/identity/identity.ts
|
|
1814
|
-
import { z as z2 } from "zod";
|
|
1815
|
-
import { createHash, createPrivateKey, createPublicKey } from "crypto";
|
|
1816
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
1817
|
-
import { join as join2 } from "path";
|
|
1818
|
-
var AgentIdentitySchema = z2.object({
|
|
1819
|
-
/** Deterministic ID derived from public key: sha256(hex).slice(0, 16). */
|
|
1820
|
-
agent_id: z2.string().min(1),
|
|
1821
|
-
/** Human-readable owner name (from config or init). */
|
|
1822
|
-
owner: z2.string().min(1),
|
|
1823
|
-
/** Hex-encoded Ed25519 public key. */
|
|
1824
|
-
public_key: z2.string().min(1),
|
|
1825
|
-
/** ISO 8601 timestamp of identity creation. */
|
|
1826
|
-
created_at: z2.string().datetime(),
|
|
1827
|
-
/** Optional guarantor info if linked to a human. */
|
|
1828
|
-
guarantor: z2.object({
|
|
1829
|
-
github_login: z2.string().min(1),
|
|
1830
|
-
verified_at: z2.string().datetime()
|
|
1831
|
-
}).optional()
|
|
1832
|
-
});
|
|
1833
|
-
var AgentCertificateSchema = z2.object({
|
|
1834
|
-
identity: AgentIdentitySchema,
|
|
1835
|
-
/** ISO 8601 timestamp of certificate issuance. */
|
|
1836
|
-
issued_at: z2.string().datetime(),
|
|
1837
|
-
/** ISO 8601 timestamp of certificate expiry. */
|
|
1838
|
-
expires_at: z2.string().datetime(),
|
|
1839
|
-
/** Hex-encoded public key of the issuer (same as identity for self-signed). */
|
|
1840
|
-
issuer_public_key: z2.string().min(1),
|
|
1841
|
-
/** Base64url Ed25519 signature over { identity, issued_at, expires_at, issuer_public_key }. */
|
|
1842
|
-
signature: z2.string().min(1)
|
|
1843
|
-
});
|
|
1844
|
-
var IDENTITY_FILENAME = "identity.json";
|
|
1845
|
-
var PRIVATE_KEY_FILENAME = "private.key";
|
|
1846
|
-
var PUBLIC_KEY_FILENAME = "public.key";
|
|
1847
|
-
function derivePublicKeyFromPrivate(privateKey) {
|
|
1848
|
-
const privateKeyObject = createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
|
1849
|
-
const publicKeyObject = createPublicKey(privateKeyObject);
|
|
1850
|
-
const publicKey = publicKeyObject.export({ format: "der", type: "spki" });
|
|
1851
|
-
return Buffer.from(publicKey);
|
|
1852
|
-
}
|
|
1853
|
-
function buildIdentityFromPublicKey(publicKey, owner, createdAt) {
|
|
1854
|
-
const publicKeyHex = publicKey.toString("hex");
|
|
1855
|
-
return {
|
|
1856
|
-
agent_id: deriveAgentId(publicKeyHex),
|
|
1857
|
-
owner,
|
|
1858
|
-
public_key: publicKeyHex,
|
|
1859
|
-
created_at: createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
1860
|
-
};
|
|
1861
|
-
}
|
|
1862
|
-
function generateFreshIdentity(configDir, owner) {
|
|
1863
|
-
const keys = generateKeyPair();
|
|
1864
|
-
saveKeyPair(configDir, keys);
|
|
1865
|
-
const identity = buildIdentityFromPublicKey(keys.publicKey, owner);
|
|
1866
|
-
saveIdentity(configDir, identity);
|
|
1867
|
-
return { identity, keys, status: "generated" };
|
|
1868
|
-
}
|
|
1869
|
-
function deriveAgentId(publicKeyHex) {
|
|
1870
|
-
return createHash("sha256").update(publicKeyHex, "hex").digest("hex").slice(0, 16);
|
|
1871
|
-
}
|
|
1872
|
-
function loadIdentity(configDir) {
|
|
1873
|
-
const filePath = join2(configDir, IDENTITY_FILENAME);
|
|
1874
|
-
if (!existsSync3(filePath)) return null;
|
|
1875
|
-
try {
|
|
1876
|
-
const raw = readFileSync3(filePath, "utf-8");
|
|
1877
|
-
return AgentIdentitySchema.parse(JSON.parse(raw));
|
|
1878
|
-
} catch {
|
|
1879
|
-
return null;
|
|
1880
|
-
}
|
|
1881
|
-
}
|
|
1882
|
-
function saveIdentity(configDir, identity) {
|
|
1883
|
-
if (!existsSync3(configDir)) {
|
|
1884
|
-
mkdirSync2(configDir, { recursive: true });
|
|
1885
|
-
}
|
|
1886
|
-
const filePath = join2(configDir, IDENTITY_FILENAME);
|
|
1887
|
-
writeFileSync2(filePath, JSON.stringify(identity, null, 2), "utf-8");
|
|
1888
|
-
}
|
|
1889
|
-
function loadOrRepairIdentity(configDir, ownerHint) {
|
|
1890
|
-
if (!existsSync3(configDir)) {
|
|
1891
|
-
mkdirSync2(configDir, { recursive: true });
|
|
1892
|
-
}
|
|
1893
|
-
const identityPath = join2(configDir, IDENTITY_FILENAME);
|
|
1894
|
-
const privateKeyPath = join2(configDir, PRIVATE_KEY_FILENAME);
|
|
1895
|
-
const publicKeyPath = join2(configDir, PUBLIC_KEY_FILENAME);
|
|
1896
|
-
const hasIdentity = existsSync3(identityPath);
|
|
1897
|
-
const hasPrivateKey = existsSync3(privateKeyPath);
|
|
1898
|
-
const hasPublicKey = existsSync3(publicKeyPath);
|
|
1899
|
-
if (!hasIdentity || !hasPrivateKey || !hasPublicKey) {
|
|
1900
|
-
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
1901
|
-
}
|
|
1902
|
-
let keys;
|
|
1903
|
-
try {
|
|
1904
|
-
keys = loadKeyPair(configDir);
|
|
1905
|
-
} catch {
|
|
1906
|
-
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
1907
|
-
}
|
|
1908
|
-
let derivedPublicKey;
|
|
1909
|
-
try {
|
|
1910
|
-
derivedPublicKey = derivePublicKeyFromPrivate(keys.privateKey);
|
|
1911
|
-
} catch {
|
|
1912
|
-
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
1913
|
-
}
|
|
1914
|
-
let keypairRepaired = false;
|
|
1915
|
-
if (!keys.publicKey.equals(derivedPublicKey)) {
|
|
1916
|
-
keypairRepaired = true;
|
|
1917
|
-
keys = { privateKey: keys.privateKey, publicKey: derivedPublicKey };
|
|
1918
|
-
saveKeyPair(configDir, keys);
|
|
1919
|
-
}
|
|
1920
|
-
const loadedIdentity = loadIdentity(configDir);
|
|
1921
|
-
const expectedAgentId = deriveAgentId(derivedPublicKey.toString("hex"));
|
|
1922
|
-
const expectedPublicKeyHex = derivedPublicKey.toString("hex");
|
|
1923
|
-
const identityMismatch = !loadedIdentity || loadedIdentity.public_key !== expectedPublicKeyHex || loadedIdentity.agent_id !== expectedAgentId;
|
|
1924
|
-
if (identityMismatch) {
|
|
1925
|
-
const repairedIdentity = buildIdentityFromPublicKey(
|
|
1926
|
-
derivedPublicKey,
|
|
1927
|
-
loadedIdentity?.owner ?? ownerHint ?? "agent",
|
|
1928
|
-
loadedIdentity?.created_at
|
|
1929
|
-
);
|
|
1930
|
-
saveIdentity(configDir, repairedIdentity);
|
|
1931
|
-
return { identity: repairedIdentity, keys, status: "repaired" };
|
|
1932
|
-
}
|
|
1933
|
-
if (ownerHint && loadedIdentity.owner !== ownerHint) {
|
|
1934
|
-
const updatedIdentity = { ...loadedIdentity, owner: ownerHint };
|
|
1935
|
-
saveIdentity(configDir, updatedIdentity);
|
|
1936
|
-
return { identity: updatedIdentity, keys, status: "repaired" };
|
|
1937
|
-
}
|
|
1938
|
-
return { identity: loadedIdentity, keys, status: keypairRepaired ? "repaired" : "existing" };
|
|
1939
|
-
}
|
|
1940
|
-
function ensureIdentity(configDir, owner) {
|
|
1941
|
-
return loadOrRepairIdentity(configDir, owner).identity;
|
|
1942
|
-
}
|
|
1943
|
-
|
|
1944
|
-
// src/registry/identity-auth.ts
|
|
1945
|
-
var MAX_REQUEST_AGE_MS = 5 * 60 * 1e3;
|
|
1946
|
-
function normalizeSignedParams(body) {
|
|
1947
|
-
return body === void 0 ? null : body;
|
|
1948
|
-
}
|
|
1949
|
-
function buildIdentityPayload(method, path, timestamp, publicKeyHex, agentId, params) {
|
|
1950
|
-
return {
|
|
1951
|
-
method,
|
|
1952
|
-
path,
|
|
1953
|
-
timestamp,
|
|
1954
|
-
publicKey: publicKeyHex,
|
|
1955
|
-
agentId,
|
|
1956
|
-
params: normalizeSignedParams(params)
|
|
1957
|
-
};
|
|
1958
|
-
}
|
|
1959
|
-
function extractClaimedRequester(request) {
|
|
1960
|
-
const extractFromObject = (obj) => {
|
|
1961
|
-
const directOwner = typeof obj.owner === "string" ? obj.owner.trim() : "";
|
|
1962
|
-
if (directOwner) return directOwner;
|
|
1963
|
-
const directRequester = typeof obj.requester === "string" ? obj.requester.trim() : "";
|
|
1964
|
-
if (directRequester) return directRequester;
|
|
1965
|
-
const oldOwner = typeof obj.oldOwner === "string" ? obj.oldOwner.trim() : "";
|
|
1966
|
-
if (oldOwner) return oldOwner;
|
|
1967
|
-
const nestedParams = obj.params;
|
|
1968
|
-
if (nestedParams && typeof nestedParams === "object" && !Array.isArray(nestedParams)) {
|
|
1969
|
-
const nested = nestedParams;
|
|
1970
|
-
const nestedOwner = typeof nested.owner === "string" ? nested.owner.trim() : "";
|
|
1971
|
-
if (nestedOwner) return nestedOwner;
|
|
1972
|
-
const nestedRequester = typeof nested.requester === "string" ? nested.requester.trim() : "";
|
|
1973
|
-
if (nestedRequester) return nestedRequester;
|
|
1974
|
-
}
|
|
1975
|
-
return null;
|
|
1976
|
-
};
|
|
1977
|
-
if (request.body && typeof request.body === "object" && !Array.isArray(request.body)) {
|
|
1978
|
-
const claimed = extractFromObject(request.body);
|
|
1979
|
-
if (claimed) return claimed;
|
|
1980
|
-
}
|
|
1981
|
-
if (request.params && typeof request.params === "object" && !Array.isArray(request.params)) {
|
|
1982
|
-
const claimed = extractFromObject(request.params);
|
|
1983
|
-
if (claimed) return claimed;
|
|
1984
|
-
}
|
|
1985
|
-
return null;
|
|
1986
|
-
}
|
|
1987
|
-
async function verifyIdentity(request, reply, options) {
|
|
1988
|
-
const agentIdHeader = request.headers["x-agent-id"];
|
|
1989
|
-
const publicKeyHeader = request.headers["x-agent-publickey"];
|
|
1990
|
-
const signatureHeader = request.headers["x-agent-signature"];
|
|
1991
|
-
const timestampHeader = request.headers["x-agent-timestamp"];
|
|
1992
|
-
const agentId = agentIdHeader?.trim();
|
|
1993
|
-
const publicKeyHex = publicKeyHeader?.trim();
|
|
1994
|
-
const signature = signatureHeader?.trim();
|
|
1995
|
-
const timestamp = timestampHeader?.trim();
|
|
1996
|
-
if (!agentId || !publicKeyHex || !signature || !timestamp) {
|
|
1997
|
-
await reply.code(401).send({ error: "Missing identity headers" });
|
|
1998
|
-
return false;
|
|
1999
|
-
}
|
|
2000
|
-
const requestTime = new Date(timestamp).getTime();
|
|
2001
|
-
if (isNaN(requestTime) || Math.abs(Date.now() - requestTime) > MAX_REQUEST_AGE_MS) {
|
|
2002
|
-
await reply.code(401).send({ error: "Request expired" });
|
|
2003
|
-
return false;
|
|
2004
|
-
}
|
|
2005
|
-
if (!/^[0-9a-fA-F]+$/.test(publicKeyHex) || publicKeyHex.length % 2 !== 0) {
|
|
2006
|
-
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
2007
|
-
return false;
|
|
2008
|
-
}
|
|
2009
|
-
let expectedAgentId;
|
|
2010
|
-
try {
|
|
2011
|
-
expectedAgentId = deriveAgentId(publicKeyHex);
|
|
2012
|
-
} catch {
|
|
2013
|
-
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
2014
|
-
return false;
|
|
2015
|
-
}
|
|
2016
|
-
if (agentId !== expectedAgentId) {
|
|
2017
|
-
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
2018
|
-
return false;
|
|
2019
|
-
}
|
|
2020
|
-
let publicKeyBuffer;
|
|
2021
|
-
try {
|
|
2022
|
-
publicKeyBuffer = Buffer.from(publicKeyHex, "hex");
|
|
2023
|
-
} catch {
|
|
2024
|
-
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
2025
|
-
return false;
|
|
2026
|
-
}
|
|
2027
|
-
const knownAgent = options.agentDb ? lookupAgent(options.agentDb, agentId) : null;
|
|
2028
|
-
if (knownAgent && knownAgent.public_key.toLowerCase() !== publicKeyHex.toLowerCase()) {
|
|
2029
|
-
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
2030
|
-
return false;
|
|
2031
|
-
}
|
|
2032
|
-
const payload = buildIdentityPayload(
|
|
2033
|
-
request.method,
|
|
2034
|
-
request.url,
|
|
2035
|
-
timestamp,
|
|
2036
|
-
publicKeyHex,
|
|
2037
|
-
agentId,
|
|
2038
|
-
request.body
|
|
2039
|
-
);
|
|
2040
|
-
const valid = verifyEscrowReceipt(payload, signature, publicKeyBuffer);
|
|
2041
|
-
if (!valid) {
|
|
2042
|
-
await reply.code(401).send({ error: "Invalid identity signature" });
|
|
2043
|
-
return false;
|
|
2044
|
-
}
|
|
2045
|
-
const claimedRequester = extractClaimedRequester(request);
|
|
2046
|
-
if (claimedRequester && knownAgent !== null) {
|
|
2047
|
-
const matchesAgentId = claimedRequester === agentId;
|
|
2048
|
-
const matchesDisplayName = knownAgent.display_name === claimedRequester;
|
|
2049
|
-
const matchesLegacyOwner = knownAgent.legacy_owner === claimedRequester;
|
|
2050
|
-
if (!matchesAgentId && !matchesDisplayName && !matchesLegacyOwner) {
|
|
2051
|
-
await reply.code(401).send({ error: "Identity does not match requester" });
|
|
2052
|
-
return false;
|
|
2053
|
-
}
|
|
2054
|
-
}
|
|
2055
|
-
request.agentPublicKey = publicKeyHex;
|
|
2056
|
-
request.agentId = agentId;
|
|
2057
|
-
return true;
|
|
2058
|
-
}
|
|
2059
|
-
function identityAuthPlugin(fastify, options = {}) {
|
|
2060
|
-
fastify.addHook("preHandler", async (request, reply) => {
|
|
2061
|
-
const ok = await verifyIdentity(request, reply, options);
|
|
2062
|
-
if (!ok) {
|
|
2063
|
-
return reply;
|
|
2064
|
-
}
|
|
2065
|
-
});
|
|
2066
|
-
}
|
|
2067
|
-
function signRequest(method, path, body, privateKey, publicKeyHex, agentIdOverride) {
|
|
2068
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2069
|
-
const agentId = agentIdOverride ?? deriveAgentId(publicKeyHex);
|
|
2070
|
-
const payload = buildIdentityPayload(method, path, timestamp, publicKeyHex, agentId, body);
|
|
2071
|
-
const signature = signEscrowReceipt(payload, privateKey);
|
|
2072
|
-
return {
|
|
2073
|
-
"X-Agent-Id": agentId,
|
|
2074
|
-
"X-Agent-PublicKey": publicKeyHex,
|
|
2075
|
-
"X-Agent-Signature": signature,
|
|
2076
|
-
"X-Agent-Timestamp": timestamp
|
|
2077
|
-
};
|
|
2078
|
-
}
|
|
2079
|
-
|
|
2080
|
-
// src/credit/registry-credit-ledger.ts
|
|
2081
|
-
var HTTP_TIMEOUT_MS = 1e4;
|
|
2082
|
-
var RegistryCreditLedger = class {
|
|
2083
|
-
config;
|
|
2084
|
-
constructor(config) {
|
|
2085
|
-
this.config = config;
|
|
2086
|
-
}
|
|
2087
|
-
/**
|
|
2088
|
-
* Holds credits in escrow during capability execution.
|
|
2089
|
-
*
|
|
2090
|
-
* @param owner - Agent identifier (requester).
|
|
2091
|
-
* @param amount - Number of credits to hold.
|
|
2092
|
-
* @param cardId - Capability Card ID being requested.
|
|
2093
|
-
* @returns EscrowResult with the new escrowId.
|
|
2094
|
-
* @throws {AgentBnBError} with code 'INSUFFICIENT_CREDITS' if balance < amount.
|
|
2095
|
-
*/
|
|
2096
|
-
async hold(owner, amount, cardId) {
|
|
2097
|
-
if (this.config.mode === "direct") {
|
|
2098
|
-
const escrowId = holdEscrow(this.config.db, owner, amount, cardId);
|
|
2099
|
-
return { escrowId };
|
|
2100
|
-
}
|
|
2101
|
-
const data = await this.post("/api/credits/hold", owner, {
|
|
2102
|
-
owner,
|
|
2103
|
-
amount,
|
|
2104
|
-
cardId
|
|
2105
|
-
});
|
|
2106
|
-
return { escrowId: data.escrowId };
|
|
2107
|
-
}
|
|
2108
|
-
/**
|
|
2109
|
-
* Settles an escrow — transfers held credits to the capability provider.
|
|
2110
|
-
*
|
|
2111
|
-
* @param escrowId - The escrow ID to settle.
|
|
2112
|
-
* @param recipientOwner - Agent identifier who will receive the credits.
|
|
2113
|
-
* @throws {AgentBnBError} with code 'ESCROW_NOT_FOUND' if escrow does not exist.
|
|
2114
|
-
* @throws {AgentBnBError} with code 'ESCROW_ALREADY_SETTLED' if escrow is not in 'held' status.
|
|
2115
|
-
*/
|
|
2116
|
-
async settle(escrowId, recipientOwner) {
|
|
2117
|
-
if (this.config.mode === "direct") {
|
|
2118
|
-
settleEscrow(this.config.db, escrowId, recipientOwner);
|
|
2119
|
-
return;
|
|
2120
|
-
}
|
|
2121
|
-
await this.post("/api/credits/settle", null, { escrowId, recipientOwner });
|
|
2122
|
-
}
|
|
2123
|
-
/**
|
|
2124
|
-
* Releases an escrow — refunds credits back to the requester.
|
|
2125
|
-
*
|
|
2126
|
-
* @param escrowId - The escrow ID to release.
|
|
2127
|
-
* @throws {AgentBnBError} with code 'ESCROW_NOT_FOUND' if escrow does not exist.
|
|
2128
|
-
* @throws {AgentBnBError} with code 'ESCROW_ALREADY_SETTLED' if escrow is not in 'held' status.
|
|
2129
|
-
*/
|
|
2130
|
-
async release(escrowId) {
|
|
2131
|
-
if (this.config.mode === "direct") {
|
|
2132
|
-
releaseEscrow(this.config.db, escrowId);
|
|
2133
|
-
return;
|
|
2134
|
-
}
|
|
2135
|
-
await this.post("/api/credits/release", null, { escrowId });
|
|
2136
|
-
}
|
|
2137
|
-
/**
|
|
2138
|
-
* Returns the current credit balance for an agent.
|
|
2139
|
-
*
|
|
2140
|
-
* @param owner - Agent identifier.
|
|
2141
|
-
* @returns Current balance in credits (0 if agent is unknown).
|
|
2142
|
-
*/
|
|
2143
|
-
async getBalance(owner) {
|
|
2144
|
-
if (this.config.mode === "direct") {
|
|
2145
|
-
return getBalance(this.config.db, owner);
|
|
2146
|
-
}
|
|
2147
|
-
const data = await this.get(`/api/credits/${owner}`, owner);
|
|
2148
|
-
return data.balance;
|
|
2149
|
-
}
|
|
2150
|
-
/**
|
|
2151
|
-
* Returns the transaction history for an agent, newest first.
|
|
2152
|
-
*
|
|
2153
|
-
* @param owner - Agent identifier.
|
|
2154
|
-
* @param limit - Maximum number of transactions to return. Defaults to 100.
|
|
2155
|
-
* @returns Array of credit transactions ordered newest first.
|
|
2156
|
-
*/
|
|
2157
|
-
async getHistory(owner, limit = 100) {
|
|
2158
|
-
if (this.config.mode === "direct") {
|
|
2159
|
-
return getTransactions(this.config.db, owner, limit);
|
|
2160
|
-
}
|
|
2161
|
-
const data = await this.get(
|
|
2162
|
-
`/api/credits/${owner}/history?limit=${limit}`,
|
|
2163
|
-
owner
|
|
2164
|
-
);
|
|
2165
|
-
return data.transactions;
|
|
2166
|
-
}
|
|
2167
|
-
/**
|
|
2168
|
-
* Grants initial credits to an agent (bootstrap grant).
|
|
2169
|
-
* Idempotent — calling multiple times has no additional effect on balance.
|
|
2170
|
-
*
|
|
2171
|
-
* @param owner - Agent identifier.
|
|
2172
|
-
* @param amount - Number of credits to grant. Defaults to 100.
|
|
2173
|
-
*/
|
|
2174
|
-
async grant(owner, amount = 100) {
|
|
2175
|
-
if (this.config.mode === "direct") {
|
|
2176
|
-
bootstrapAgent(this.config.db, owner, amount);
|
|
2177
|
-
return;
|
|
2178
|
-
}
|
|
2179
|
-
await this.post("/api/credits/grant", owner, { owner, amount });
|
|
2180
|
-
}
|
|
2181
|
-
/**
|
|
2182
|
-
* Renames an owner — migrates balance, transactions, and escrows.
|
|
2183
|
-
*/
|
|
2184
|
-
async rename(oldOwner, newOwner) {
|
|
2185
|
-
if (oldOwner === newOwner) return;
|
|
2186
|
-
if (this.config.mode === "direct") {
|
|
2187
|
-
migrateOwner(this.config.db, oldOwner, newOwner);
|
|
2188
|
-
return;
|
|
2189
|
-
}
|
|
2190
|
-
await this.post("/api/credits/rename", null, { oldOwner, newOwner });
|
|
2191
|
-
}
|
|
2192
|
-
// ─── Private HTTP helpers ─────────────────────────────────────────────────
|
|
2193
|
-
/**
|
|
2194
|
-
* Makes an authenticated POST request to the Registry HTTP API.
|
|
2195
|
-
* Includes a 10s timeout via AbortController.
|
|
2196
|
-
*
|
|
2197
|
-
* @param path - API path (e.g., '/api/credits/hold').
|
|
2198
|
-
* @param ownerForHeader - Agent owner identifier for X-Agent-Owner header, or null to omit.
|
|
2199
|
-
* @param body - JSON body to send.
|
|
2200
|
-
* @returns Parsed JSON response body.
|
|
2201
|
-
* @throws {AgentBnBError} on non-2xx responses or network errors.
|
|
2202
|
-
*/
|
|
2203
|
-
async post(path, ownerForHeader, body) {
|
|
2204
|
-
const cfg = this.config;
|
|
2205
|
-
const controller = new AbortController();
|
|
2206
|
-
const timeoutId = setTimeout(() => controller.abort(), HTTP_TIMEOUT_MS);
|
|
2207
|
-
try {
|
|
2208
|
-
const authHeaders = signRequest("POST", path, body, cfg.privateKey, cfg.ownerPublicKey);
|
|
2209
|
-
const headers = {
|
|
2210
|
-
"Content-Type": "application/json",
|
|
2211
|
-
...authHeaders
|
|
2212
|
-
};
|
|
2213
|
-
void ownerForHeader;
|
|
2214
|
-
const res = await fetch(`${cfg.registryUrl}${path}`, {
|
|
2215
|
-
method: "POST",
|
|
2216
|
-
headers,
|
|
2217
|
-
body: JSON.stringify(body),
|
|
2218
|
-
signal: controller.signal
|
|
2219
|
-
});
|
|
2220
|
-
return await this.handleResponse(res);
|
|
2221
|
-
} catch (err) {
|
|
2222
|
-
if (err instanceof AgentBnBError) throw err;
|
|
2223
|
-
throw new AgentBnBError(
|
|
2224
|
-
`Registry unreachable: ${err.message}`,
|
|
2225
|
-
"REGISTRY_UNREACHABLE"
|
|
2226
|
-
);
|
|
2227
|
-
} finally {
|
|
2228
|
-
clearTimeout(timeoutId);
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
/**
|
|
2232
|
-
* Makes an authenticated GET request to the Registry HTTP API.
|
|
2233
|
-
* Includes a 10s timeout via AbortController.
|
|
2234
|
-
*
|
|
2235
|
-
* @param path - API path (e.g., '/api/credits/owner-id').
|
|
2236
|
-
* @param owner - Agent owner identifier for X-Agent-Owner header.
|
|
2237
|
-
* @returns Parsed JSON response body.
|
|
2238
|
-
* @throws {AgentBnBError} on non-2xx responses or network errors.
|
|
2239
|
-
*/
|
|
2240
|
-
async get(path, owner) {
|
|
2241
|
-
const cfg = this.config;
|
|
2242
|
-
const controller = new AbortController();
|
|
2243
|
-
const timeoutId = setTimeout(() => controller.abort(), HTTP_TIMEOUT_MS);
|
|
2244
|
-
try {
|
|
2245
|
-
const authHeaders = signRequest("GET", path, null, cfg.privateKey, cfg.ownerPublicKey);
|
|
2246
|
-
void owner;
|
|
2247
|
-
const res = await fetch(`${cfg.registryUrl}${path}`, {
|
|
2248
|
-
method: "GET",
|
|
2249
|
-
headers: {
|
|
2250
|
-
"Content-Type": "application/json",
|
|
2251
|
-
...authHeaders
|
|
2252
|
-
},
|
|
2253
|
-
signal: controller.signal
|
|
2254
|
-
});
|
|
2255
|
-
return await this.handleResponse(res);
|
|
2256
|
-
} catch (err) {
|
|
2257
|
-
if (err instanceof AgentBnBError) throw err;
|
|
2258
|
-
throw new AgentBnBError(
|
|
2259
|
-
`Registry unreachable: ${err.message}`,
|
|
2260
|
-
"REGISTRY_UNREACHABLE"
|
|
2261
|
-
);
|
|
2262
|
-
} finally {
|
|
2263
|
-
clearTimeout(timeoutId);
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
/**
|
|
2267
|
-
* Handles an HTTP response — returns parsed JSON on 2xx, throws AgentBnBError on error.
|
|
2268
|
-
*/
|
|
2269
|
-
async handleResponse(res) {
|
|
2270
|
-
const json = await res.json();
|
|
2271
|
-
if (!res.ok) {
|
|
2272
|
-
const code = typeof json["code"] === "string" ? json["code"] : "REGISTRY_ERROR";
|
|
2273
|
-
const message = typeof json["error"] === "string" ? json["error"] : `HTTP ${res.status}`;
|
|
2274
|
-
throw new AgentBnBError(message, code);
|
|
2275
|
-
}
|
|
2276
|
-
return json;
|
|
2277
|
-
}
|
|
2278
|
-
};
|
|
2279
|
-
|
|
2280
|
-
// src/credit/create-ledger.ts
|
|
2281
|
-
function createLedger(opts) {
|
|
2282
|
-
if ("registryUrl" in opts && opts.registryUrl !== void 0) {
|
|
2283
|
-
return new RegistryCreditLedger({
|
|
2284
|
-
mode: "http",
|
|
2285
|
-
registryUrl: opts.registryUrl,
|
|
2286
|
-
ownerPublicKey: opts.ownerPublicKey,
|
|
2287
|
-
privateKey: opts.privateKey
|
|
2288
|
-
});
|
|
2289
|
-
}
|
|
2290
|
-
if ("db" in opts && opts.db !== void 0) {
|
|
2291
|
-
return new RegistryCreditLedger({
|
|
2292
|
-
mode: "direct",
|
|
2293
|
-
db: opts.db
|
|
2294
|
-
});
|
|
2295
|
-
}
|
|
2296
|
-
const db = openCreditDb(opts.creditDbPath);
|
|
2297
|
-
return new LocalCreditLedger(db);
|
|
2298
|
-
}
|
|
2299
|
-
|
|
2300
1745
|
// src/cli/onboarding.ts
|
|
2301
1746
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2302
1747
|
import { createConnection } from "net";
|
|
@@ -3586,16 +3031,16 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
3586
3031
|
}
|
|
3587
3032
|
|
|
3588
3033
|
// src/identity/guarantor.ts
|
|
3589
|
-
import { z as
|
|
3034
|
+
import { z as z2 } from "zod";
|
|
3590
3035
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
3591
3036
|
var MAX_AGENTS_PER_GUARANTOR = 10;
|
|
3592
3037
|
var GUARANTOR_CREDIT_POOL = 50;
|
|
3593
|
-
var GuarantorRecordSchema =
|
|
3594
|
-
id:
|
|
3595
|
-
github_login:
|
|
3596
|
-
agent_count:
|
|
3597
|
-
credit_pool:
|
|
3598
|
-
created_at:
|
|
3038
|
+
var GuarantorRecordSchema = z2.object({
|
|
3039
|
+
id: z2.string().uuid(),
|
|
3040
|
+
github_login: z2.string().min(1),
|
|
3041
|
+
agent_count: z2.number().int().nonnegative(),
|
|
3042
|
+
credit_pool: z2.number().int().nonnegative(),
|
|
3043
|
+
created_at: z2.string().datetime()
|
|
3599
3044
|
});
|
|
3600
3045
|
var GUARANTOR_SCHEMA = `
|
|
3601
3046
|
CREATE TABLE IF NOT EXISTS guarantors (
|
|
@@ -3732,6 +3177,75 @@ async function creditRoutesPlugin(fastify, options) {
|
|
|
3732
3177
|
} catch {
|
|
3733
3178
|
}
|
|
3734
3179
|
initFreeTierTable(creditDb);
|
|
3180
|
+
if (!process.env.ADMIN_TOKEN) {
|
|
3181
|
+
console.warn("[agentbnb] ADMIN_TOKEN not set \u2014 POST /api/credits/grant will return 401 for admin override grants");
|
|
3182
|
+
}
|
|
3183
|
+
fastify.get("/api/credits/balance", {
|
|
3184
|
+
schema: {
|
|
3185
|
+
tags: ["credits"],
|
|
3186
|
+
summary: "Get credit balance by owner query param (public, no auth required)",
|
|
3187
|
+
querystring: {
|
|
3188
|
+
type: "object",
|
|
3189
|
+
properties: { owner: { type: "string", description: "Agent owner name" } },
|
|
3190
|
+
required: ["owner"]
|
|
3191
|
+
},
|
|
3192
|
+
response: {
|
|
3193
|
+
200: {
|
|
3194
|
+
type: "object",
|
|
3195
|
+
properties: {
|
|
3196
|
+
owner: { type: "string" },
|
|
3197
|
+
balance: { type: "number" }
|
|
3198
|
+
}
|
|
3199
|
+
},
|
|
3200
|
+
400: { type: "object", properties: { error: { type: "string" } } }
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
}, async (request, reply) => {
|
|
3204
|
+
const query = request.query;
|
|
3205
|
+
const owner = typeof query.owner === "string" ? query.owner.trim() : "";
|
|
3206
|
+
if (!owner) {
|
|
3207
|
+
return reply.code(400).send({ error: "owner query param required" });
|
|
3208
|
+
}
|
|
3209
|
+
const balance = getBalance(creditDb, owner);
|
|
3210
|
+
return reply.send({ owner, balance });
|
|
3211
|
+
});
|
|
3212
|
+
fastify.get("/api/credits/transactions", {
|
|
3213
|
+
schema: {
|
|
3214
|
+
tags: ["credits"],
|
|
3215
|
+
summary: "Get transaction history by query params (public, no auth required)",
|
|
3216
|
+
querystring: {
|
|
3217
|
+
type: "object",
|
|
3218
|
+
properties: {
|
|
3219
|
+
owner: { type: "string", description: "Agent owner name" },
|
|
3220
|
+
since: { type: "string", description: "ISO 8601 timestamp \u2014 only return transactions after this time" },
|
|
3221
|
+
limit: { type: "integer", description: "Max entries (default 50, max 100)" }
|
|
3222
|
+
},
|
|
3223
|
+
required: ["owner"]
|
|
3224
|
+
},
|
|
3225
|
+
response: {
|
|
3226
|
+
200: {
|
|
3227
|
+
type: "object",
|
|
3228
|
+
properties: {
|
|
3229
|
+
owner: { type: "string" },
|
|
3230
|
+
transactions: { type: "array" },
|
|
3231
|
+
limit: { type: "integer" }
|
|
3232
|
+
}
|
|
3233
|
+
},
|
|
3234
|
+
400: { type: "object", properties: { error: { type: "string" } } }
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
}, async (request, reply) => {
|
|
3238
|
+
const query = request.query;
|
|
3239
|
+
const owner = typeof query.owner === "string" ? query.owner.trim() : "";
|
|
3240
|
+
if (!owner) {
|
|
3241
|
+
return reply.code(400).send({ error: "owner query param required" });
|
|
3242
|
+
}
|
|
3243
|
+
const rawLimit = query.limit !== void 0 ? parseInt(query.limit, 10) : 50;
|
|
3244
|
+
const limit = Math.min(isNaN(rawLimit) || rawLimit < 1 ? 50 : rawLimit, 100);
|
|
3245
|
+
const since = typeof query.since === "string" && query.since.trim() ? query.since.trim() : void 0;
|
|
3246
|
+
const transactions = getTransactions(creditDb, owner, { limit, after: since });
|
|
3247
|
+
return reply.send({ owner, transactions, limit });
|
|
3248
|
+
});
|
|
3735
3249
|
await fastify.register(async (scope) => {
|
|
3736
3250
|
identityAuthPlugin(scope, { agentDb: creditDb });
|
|
3737
3251
|
scope.post("/api/credits/hold", {
|
|
@@ -4127,38 +3641,38 @@ var HubAgentExecutor = class {
|
|
|
4127
3641
|
};
|
|
4128
3642
|
|
|
4129
3643
|
// src/hub-agent/types.ts
|
|
4130
|
-
import { z as
|
|
4131
|
-
var SkillRouteSchema =
|
|
4132
|
-
|
|
4133
|
-
skill_id:
|
|
4134
|
-
mode:
|
|
3644
|
+
import { z as z3 } from "zod";
|
|
3645
|
+
var SkillRouteSchema = z3.discriminatedUnion("mode", [
|
|
3646
|
+
z3.object({
|
|
3647
|
+
skill_id: z3.string().min(1),
|
|
3648
|
+
mode: z3.literal("direct_api"),
|
|
4135
3649
|
config: ApiSkillConfigSchema
|
|
4136
3650
|
}),
|
|
4137
|
-
|
|
4138
|
-
skill_id:
|
|
4139
|
-
mode:
|
|
4140
|
-
config:
|
|
3651
|
+
z3.object({
|
|
3652
|
+
skill_id: z3.string().min(1),
|
|
3653
|
+
mode: z3.literal("relay"),
|
|
3654
|
+
config: z3.object({ relay_owner: z3.string().min(1) })
|
|
4141
3655
|
}),
|
|
4142
|
-
|
|
4143
|
-
skill_id:
|
|
4144
|
-
mode:
|
|
4145
|
-
config:
|
|
3656
|
+
z3.object({
|
|
3657
|
+
skill_id: z3.string().min(1),
|
|
3658
|
+
mode: z3.literal("queue"),
|
|
3659
|
+
config: z3.object({ relay_owner: z3.string().min(1) }).passthrough()
|
|
4146
3660
|
})
|
|
4147
3661
|
]);
|
|
4148
|
-
var HubAgentSchema =
|
|
4149
|
-
agent_id:
|
|
4150
|
-
name:
|
|
4151
|
-
owner_public_key:
|
|
4152
|
-
public_key:
|
|
4153
|
-
skill_routes:
|
|
4154
|
-
status:
|
|
4155
|
-
created_at:
|
|
4156
|
-
updated_at:
|
|
3662
|
+
var HubAgentSchema = z3.object({
|
|
3663
|
+
agent_id: z3.string().min(1),
|
|
3664
|
+
name: z3.string().min(1),
|
|
3665
|
+
owner_public_key: z3.string().min(1),
|
|
3666
|
+
public_key: z3.string().min(1),
|
|
3667
|
+
skill_routes: z3.array(SkillRouteSchema),
|
|
3668
|
+
status: z3.enum(["active", "paused"]),
|
|
3669
|
+
created_at: z3.string(),
|
|
3670
|
+
updated_at: z3.string()
|
|
4157
3671
|
});
|
|
4158
|
-
var CreateAgentRequestSchema =
|
|
4159
|
-
name:
|
|
4160
|
-
skill_routes:
|
|
4161
|
-
secrets:
|
|
3672
|
+
var CreateAgentRequestSchema = z3.object({
|
|
3673
|
+
name: z3.string().min(1),
|
|
3674
|
+
skill_routes: z3.array(SkillRouteSchema),
|
|
3675
|
+
secrets: z3.record(z3.string()).optional()
|
|
4162
3676
|
});
|
|
4163
3677
|
|
|
4164
3678
|
// src/hub-agent/routes.ts
|
|
@@ -4586,24 +4100,24 @@ function deriveOperationId(method, path) {
|
|
|
4586
4100
|
}
|
|
4587
4101
|
|
|
4588
4102
|
// src/feedback/schema.ts
|
|
4589
|
-
import { z as
|
|
4590
|
-
var StructuredFeedbackSchema =
|
|
4591
|
-
transaction_id:
|
|
4103
|
+
import { z as z4 } from "zod";
|
|
4104
|
+
var StructuredFeedbackSchema = z4.object({
|
|
4105
|
+
transaction_id: z4.string().uuid(),
|
|
4592
4106
|
// must match a request_log entry id
|
|
4593
|
-
provider_agent:
|
|
4594
|
-
skill_id:
|
|
4595
|
-
requester_agent:
|
|
4596
|
-
rating:
|
|
4597
|
-
latency_ms:
|
|
4598
|
-
result_quality:
|
|
4599
|
-
quality_details:
|
|
4600
|
-
would_reuse:
|
|
4601
|
-
cost_value_ratio:
|
|
4602
|
-
timestamp:
|
|
4107
|
+
provider_agent: z4.string().min(1),
|
|
4108
|
+
skill_id: z4.string().min(1),
|
|
4109
|
+
requester_agent: z4.string().min(1),
|
|
4110
|
+
rating: z4.number().int().min(1).max(5),
|
|
4111
|
+
latency_ms: z4.number().int().min(0),
|
|
4112
|
+
result_quality: z4.enum(["excellent", "good", "acceptable", "poor", "failed"]),
|
|
4113
|
+
quality_details: z4.string().max(500).optional(),
|
|
4114
|
+
would_reuse: z4.boolean(),
|
|
4115
|
+
cost_value_ratio: z4.enum(["great", "fair", "overpriced"]),
|
|
4116
|
+
timestamp: z4.string().datetime()
|
|
4603
4117
|
});
|
|
4604
|
-
var FeedbackResponseSchema =
|
|
4605
|
-
feedback_id:
|
|
4606
|
-
received_at:
|
|
4118
|
+
var FeedbackResponseSchema = z4.object({
|
|
4119
|
+
feedback_id: z4.string().uuid(),
|
|
4120
|
+
received_at: z4.string().datetime()
|
|
4607
4121
|
});
|
|
4608
4122
|
|
|
4609
4123
|
// src/feedback/api.ts
|
|
@@ -4726,28 +4240,28 @@ var feedbackPlugin = async (fastify, opts) => {
|
|
|
4726
4240
|
var api_default = feedbackPlugin;
|
|
4727
4241
|
|
|
4728
4242
|
// src/evolution/schema.ts
|
|
4729
|
-
import { z as
|
|
4730
|
-
var CoreMemoryEntrySchema =
|
|
4731
|
-
category:
|
|
4732
|
-
importance:
|
|
4733
|
-
content:
|
|
4734
|
-
scope:
|
|
4243
|
+
import { z as z5 } from "zod";
|
|
4244
|
+
var CoreMemoryEntrySchema = z5.object({
|
|
4245
|
+
category: z5.string(),
|
|
4246
|
+
importance: z5.number().min(0).max(1),
|
|
4247
|
+
content: z5.string(),
|
|
4248
|
+
scope: z5.string().optional()
|
|
4735
4249
|
});
|
|
4736
|
-
var TemplateEvolutionSchema =
|
|
4250
|
+
var TemplateEvolutionSchema = z5.object({
|
|
4737
4251
|
/** e.g. "genesis-template" */
|
|
4738
|
-
template_name:
|
|
4252
|
+
template_name: z5.string().min(1),
|
|
4739
4253
|
/** Semantic version string, e.g. "1.2.3" */
|
|
4740
|
-
template_version:
|
|
4254
|
+
template_version: z5.string().regex(/^\d+\.\d+\.\d+$/, "Must be a valid semver string (e.g. 1.2.3)"),
|
|
4741
4255
|
/** Identifier of the agent publishing this evolution */
|
|
4742
|
-
publisher_agent:
|
|
4256
|
+
publisher_agent: z5.string().min(1),
|
|
4743
4257
|
/** Human-readable description of what changed in this evolution */
|
|
4744
|
-
changelog:
|
|
4258
|
+
changelog: z5.string().max(1e3),
|
|
4745
4259
|
/** Snapshot of the agent's core memory at the time of evolution (max 50 entries) */
|
|
4746
|
-
core_memory_snapshot:
|
|
4260
|
+
core_memory_snapshot: z5.array(CoreMemoryEntrySchema).max(50),
|
|
4747
4261
|
/** Delta in fitness score from before evolution (range -1 to 1) */
|
|
4748
|
-
fitness_improvement:
|
|
4262
|
+
fitness_improvement: z5.number().min(-1).max(1),
|
|
4749
4263
|
/** ISO 8601 datetime string */
|
|
4750
|
-
timestamp:
|
|
4264
|
+
timestamp: z5.string().datetime()
|
|
4751
4265
|
});
|
|
4752
4266
|
|
|
4753
4267
|
// src/evolution/api.ts
|
|
@@ -4935,14 +4449,14 @@ function createRegistryServer(opts) {
|
|
|
4935
4449
|
const __filename = fileURLToPath(import.meta.url);
|
|
4936
4450
|
const __dirname = dirname2(__filename);
|
|
4937
4451
|
const hubDistCandidates = [
|
|
4938
|
-
|
|
4452
|
+
join2(__dirname, "../hub/dist"),
|
|
4939
4453
|
// When in dist/ (tsup chunk, e.g. dist/server-XYZ.js)
|
|
4940
|
-
|
|
4454
|
+
join2(__dirname, "../../hub/dist"),
|
|
4941
4455
|
// When in dist/registry/ or dist/cli/
|
|
4942
|
-
|
|
4456
|
+
join2(__dirname, "../../../hub/dist")
|
|
4943
4457
|
// Fallback for alternative layouts
|
|
4944
4458
|
];
|
|
4945
|
-
const hubDistDir = hubDistCandidates.find((p) =>
|
|
4459
|
+
const hubDistDir = hubDistCandidates.find((p) => existsSync3(p));
|
|
4946
4460
|
if (hubDistDir) {
|
|
4947
4461
|
void server.register(fastifyStatic, {
|
|
4948
4462
|
root: hubDistDir,
|
|
@@ -5738,16 +5252,16 @@ function createRegistryServer(opts) {
|
|
|
5738
5252
|
const gptActions = convertToGptActions(openapiSpec, serverUrl);
|
|
5739
5253
|
return reply.send(gptActions);
|
|
5740
5254
|
});
|
|
5741
|
-
const BatchRequestBodySchema =
|
|
5742
|
-
requests:
|
|
5743
|
-
|
|
5744
|
-
skill_id:
|
|
5745
|
-
params:
|
|
5746
|
-
max_credits:
|
|
5255
|
+
const BatchRequestBodySchema = z6.object({
|
|
5256
|
+
requests: z6.array(
|
|
5257
|
+
z6.object({
|
|
5258
|
+
skill_id: z6.string().min(1),
|
|
5259
|
+
params: z6.record(z6.unknown()).default({}),
|
|
5260
|
+
max_credits: z6.number().positive()
|
|
5747
5261
|
})
|
|
5748
5262
|
).min(1),
|
|
5749
|
-
strategy:
|
|
5750
|
-
total_budget:
|
|
5263
|
+
strategy: z6.enum(["parallel", "sequential", "best_effort"]),
|
|
5264
|
+
total_budget: z6.number().positive()
|
|
5751
5265
|
});
|
|
5752
5266
|
api.post("/api/request/batch", {
|
|
5753
5267
|
schema: {
|
|
@@ -5818,7 +5332,7 @@ function createRegistryServer(opts) {
|
|
|
5818
5332
|
});
|
|
5819
5333
|
await relayClient.connect();
|
|
5820
5334
|
}
|
|
5821
|
-
const { requestViaRelay: requestViaRelay2 } = await import("../../client-
|
|
5335
|
+
const { requestViaRelay: requestViaRelay2 } = await import("../../client-UQBGCIPA.js");
|
|
5822
5336
|
return requestViaRelay2(relayClient, {
|
|
5823
5337
|
targetOwner: target.owner,
|
|
5824
5338
|
cardId: target.cardId,
|
|
@@ -6287,10 +5801,10 @@ async function stopAnnouncement() {
|
|
|
6287
5801
|
|
|
6288
5802
|
// src/runtime/resolve-self-cli.ts
|
|
6289
5803
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
6290
|
-
import { existsSync as
|
|
5804
|
+
import { existsSync as existsSync4, realpathSync } from "fs";
|
|
6291
5805
|
import { createRequire } from "module";
|
|
6292
5806
|
import { homedir as homedir2 } from "os";
|
|
6293
|
-
import { basename, dirname as dirname3, isAbsolute, join as
|
|
5807
|
+
import { basename, dirname as dirname3, isAbsolute, join as join3, resolve } from "path";
|
|
6294
5808
|
function resolveSelfCli() {
|
|
6295
5809
|
const require2 = createRequire(import.meta.url);
|
|
6296
5810
|
return resolveSelfCliWithDeps({
|
|
@@ -6300,7 +5814,7 @@ function resolveSelfCli() {
|
|
|
6300
5814
|
homeDir: homedir2(),
|
|
6301
5815
|
envPath: process.env["PATH"],
|
|
6302
5816
|
nodeExecDir: dirname3(process.execPath),
|
|
6303
|
-
exists:
|
|
5817
|
+
exists: existsSync4,
|
|
6304
5818
|
realpath: realpathSync,
|
|
6305
5819
|
runWhich: (pathEnv) => execFileSync2("which", ["agentbnb"], {
|
|
6306
5820
|
encoding: "utf8",
|
|
@@ -6345,7 +5859,7 @@ function resolveSelfCliWithDeps(deps) {
|
|
|
6345
5859
|
}
|
|
6346
5860
|
if (deps.nodeExecDir) {
|
|
6347
5861
|
const execDirCandidate = tryCandidate(
|
|
6348
|
-
|
|
5862
|
+
join3(deps.nodeExecDir, "agentbnb"),
|
|
6349
5863
|
"node-execpath-dir"
|
|
6350
5864
|
);
|
|
6351
5865
|
if (execDirCandidate) return execDirCandidate;
|
|
@@ -6376,9 +5890,9 @@ function buildFullPathEnv(pathEnv, homeDir, nodeExecDir) {
|
|
|
6376
5890
|
"/bin",
|
|
6377
5891
|
"/usr/sbin",
|
|
6378
5892
|
"/sbin",
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
5893
|
+
join3(homeDir, ".local", "bin"),
|
|
5894
|
+
join3(homeDir, "Library", "pnpm"),
|
|
5895
|
+
join3(homeDir, ".local", "share", "pnpm")
|
|
6382
5896
|
]) {
|
|
6383
5897
|
values.add(extra);
|
|
6384
5898
|
}
|
|
@@ -6397,13 +5911,13 @@ function safeRealpath(realpath, path) {
|
|
|
6397
5911
|
function getPnpmGlobalCandidates(platform, homeDir) {
|
|
6398
5912
|
const candidates = /* @__PURE__ */ new Set();
|
|
6399
5913
|
if (platform === "darwin") {
|
|
6400
|
-
candidates.add(
|
|
5914
|
+
candidates.add(join3(homeDir, "Library", "pnpm", "agentbnb"));
|
|
6401
5915
|
}
|
|
6402
5916
|
if (platform === "linux") {
|
|
6403
|
-
candidates.add(
|
|
5917
|
+
candidates.add(join3(homeDir, ".local", "share", "pnpm", "agentbnb"));
|
|
6404
5918
|
}
|
|
6405
|
-
candidates.add(
|
|
6406
|
-
candidates.add(
|
|
5919
|
+
candidates.add(join3(homeDir, "Library", "pnpm", "agentbnb"));
|
|
5920
|
+
candidates.add(join3(homeDir, ".local", "share", "pnpm", "agentbnb"));
|
|
6407
5921
|
return [...candidates];
|
|
6408
5922
|
}
|
|
6409
5923
|
function looksLikeAgentbnbCli(path) {
|
|
@@ -6421,9 +5935,10 @@ function extractErrorMessage(err) {
|
|
|
6421
5935
|
|
|
6422
5936
|
// src/runtime/service-coordinator.ts
|
|
6423
5937
|
import { spawn as spawn2 } from "child_process";
|
|
6424
|
-
import { existsSync as
|
|
6425
|
-
import { join as
|
|
5938
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
5939
|
+
import { join as join4 } from "path";
|
|
6426
5940
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
5941
|
+
import { Cron as Cron2 } from "croner";
|
|
6427
5942
|
function buildFallbackRelayCard(owner) {
|
|
6428
5943
|
return {
|
|
6429
5944
|
id: randomUUID8(),
|
|
@@ -6461,6 +5976,7 @@ var ServiceCoordinator = class {
|
|
|
6461
5976
|
inProcessStartup = false;
|
|
6462
5977
|
shutdownPromise = null;
|
|
6463
5978
|
signalHandlersRegistered = false;
|
|
5979
|
+
creditSyncJob = null;
|
|
6464
5980
|
constructor(config, guard) {
|
|
6465
5981
|
this.config = config;
|
|
6466
5982
|
this.guard = guard;
|
|
@@ -6569,7 +6085,7 @@ var ServiceCoordinator = class {
|
|
|
6569
6085
|
return {
|
|
6570
6086
|
port: opts?.port ?? this.config.gateway_port,
|
|
6571
6087
|
handlerUrl: opts?.handlerUrl ?? "http://localhost:8080",
|
|
6572
|
-
skillsYamlPath: opts?.skillsYamlPath ??
|
|
6088
|
+
skillsYamlPath: opts?.skillsYamlPath ?? join4(getConfigDir(), "skills.yaml"),
|
|
6573
6089
|
registryPort: opts?.registryPort ?? 7701,
|
|
6574
6090
|
registryUrl: opts?.registryUrl ?? this.config.registry ?? "",
|
|
6575
6091
|
relay: opts?.relay ?? true,
|
|
@@ -6625,6 +6141,22 @@ var ServiceCoordinator = class {
|
|
|
6625
6141
|
const idleJob = idleMonitor.start();
|
|
6626
6142
|
this.runtime.registerJob(idleJob);
|
|
6627
6143
|
console.log("IdleMonitor started (60s poll interval, 70% idle threshold)");
|
|
6144
|
+
if (this.config.registry) {
|
|
6145
|
+
const startupSync = await syncCreditsFromRegistry(this.config, this.runtime.creditDb);
|
|
6146
|
+
if (startupSync.synced) {
|
|
6147
|
+
console.log(`[agentbnb] credits synced: ${startupSync.remoteBalance} (was ${startupSync.localWas})`);
|
|
6148
|
+
} else {
|
|
6149
|
+
console.warn(`[agentbnb] credit sync skipped: ${startupSync.error}`);
|
|
6150
|
+
}
|
|
6151
|
+
this.creditSyncJob = new Cron2("*/5 * * * *", async () => {
|
|
6152
|
+
const result = await syncCreditsFromRegistry(this.config, this.runtime.creditDb);
|
|
6153
|
+
if (result.synced) {
|
|
6154
|
+
console.log(`[agentbnb] credits synced: ${result.remoteBalance} (was ${result.localWas})`);
|
|
6155
|
+
} else {
|
|
6156
|
+
console.warn(`[agentbnb] credit sync failed: ${result.error}`);
|
|
6157
|
+
}
|
|
6158
|
+
});
|
|
6159
|
+
}
|
|
6628
6160
|
this.gateway = createGatewayServer({
|
|
6629
6161
|
port: opts.port,
|
|
6630
6162
|
registryDb: this.runtime.registryDb,
|
|
@@ -6655,7 +6187,7 @@ var ServiceCoordinator = class {
|
|
|
6655
6187
|
}
|
|
6656
6188
|
if (opts.registryUrl && opts.relay) {
|
|
6657
6189
|
const { RelayClient: RelayClient2 } = await import("../../websocket-client-SNDF3B6N.js");
|
|
6658
|
-
const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("../../execute-
|
|
6190
|
+
const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("../../execute-VRTABQ6F.js");
|
|
6659
6191
|
const localCards = listCards(this.runtime.registryDb, this.config.owner);
|
|
6660
6192
|
const { primaryCard, additionalCards } = buildRelayRegistrationCards(this.config.owner, localCards);
|
|
6661
6193
|
if (this.config.conductor?.public) {
|
|
@@ -6714,6 +6246,10 @@ var ServiceCoordinator = class {
|
|
|
6714
6246
|
return;
|
|
6715
6247
|
}
|
|
6716
6248
|
this.shutdownPromise = (async () => {
|
|
6249
|
+
if (this.creditSyncJob) {
|
|
6250
|
+
this.creditSyncJob.stop();
|
|
6251
|
+
this.creditSyncJob = null;
|
|
6252
|
+
}
|
|
6717
6253
|
if (this.relayClient) {
|
|
6718
6254
|
this.relayClient.disconnect();
|
|
6719
6255
|
this.relayClient = null;
|
|
@@ -6909,10 +6445,10 @@ var ServiceCoordinator = class {
|
|
|
6909
6445
|
};
|
|
6910
6446
|
};
|
|
6911
6447
|
function loadPersistedRuntime(configDir) {
|
|
6912
|
-
const runtimePath =
|
|
6913
|
-
if (!
|
|
6448
|
+
const runtimePath = join4(configDir, "runtime.json");
|
|
6449
|
+
if (!existsSync5(runtimePath)) return null;
|
|
6914
6450
|
try {
|
|
6915
|
-
const raw =
|
|
6451
|
+
const raw = readFileSync3(runtimePath, "utf8");
|
|
6916
6452
|
const parsed = JSON.parse(raw);
|
|
6917
6453
|
const nodeExec = parsed["node_exec"];
|
|
6918
6454
|
if (typeof nodeExec !== "string" || nodeExec.trim().length === 0) {
|
|
@@ -6952,18 +6488,18 @@ function sleep2(ms) {
|
|
|
6952
6488
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
6953
6489
|
|
|
6954
6490
|
// src/credit/escrow-receipt.ts
|
|
6955
|
-
import { z as
|
|
6491
|
+
import { z as z7 } from "zod";
|
|
6956
6492
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
6957
|
-
var EscrowReceiptSchema =
|
|
6958
|
-
requester_owner:
|
|
6959
|
-
requester_agent_id:
|
|
6960
|
-
requester_public_key:
|
|
6961
|
-
amount:
|
|
6962
|
-
card_id:
|
|
6963
|
-
skill_id:
|
|
6964
|
-
timestamp:
|
|
6965
|
-
nonce:
|
|
6966
|
-
signature:
|
|
6493
|
+
var EscrowReceiptSchema = z7.object({
|
|
6494
|
+
requester_owner: z7.string().min(1),
|
|
6495
|
+
requester_agent_id: z7.string().optional(),
|
|
6496
|
+
requester_public_key: z7.string().min(1),
|
|
6497
|
+
amount: z7.number().positive(),
|
|
6498
|
+
card_id: z7.string().min(1),
|
|
6499
|
+
skill_id: z7.string().optional(),
|
|
6500
|
+
timestamp: z7.string(),
|
|
6501
|
+
nonce: z7.string().uuid(),
|
|
6502
|
+
signature: z7.string().min(1)
|
|
6967
6503
|
});
|
|
6968
6504
|
function createSignedEscrowReceipt(db, privateKey, publicKey, opts) {
|
|
6969
6505
|
const escrowId = holdEscrow(db, opts.owner, opts.amount, opts.cardId);
|
|
@@ -7329,16 +6865,16 @@ function isNetworkError(err) {
|
|
|
7329
6865
|
}
|
|
7330
6866
|
|
|
7331
6867
|
// skills/agentbnb/openclaw-tools.ts
|
|
7332
|
-
import { readFileSync as
|
|
7333
|
-
import { join as
|
|
6868
|
+
import { readFileSync as readFileSync4, existsSync as existsSync6 } from "fs";
|
|
6869
|
+
import { join as join5 } from "path";
|
|
7334
6870
|
import { homedir as homedir3 } from "os";
|
|
7335
6871
|
|
|
7336
6872
|
// src/mcp/tools/discover.ts
|
|
7337
|
-
import { z as
|
|
6873
|
+
import { z as z8 } from "zod";
|
|
7338
6874
|
var discoverInputSchema = {
|
|
7339
|
-
query:
|
|
7340
|
-
level:
|
|
7341
|
-
online_only:
|
|
6875
|
+
query: z8.string().describe("Natural language search query"),
|
|
6876
|
+
level: z8.number().optional().describe("Filter by capability level (1=Atomic, 2=Pipeline, 3=Environment)"),
|
|
6877
|
+
online_only: z8.boolean().optional().describe("Only show online agents")
|
|
7342
6878
|
};
|
|
7343
6879
|
async function handleDiscover(args, ctx) {
|
|
7344
6880
|
try {
|
|
@@ -7396,14 +6932,14 @@ async function handleDiscover(args, ctx) {
|
|
|
7396
6932
|
}
|
|
7397
6933
|
|
|
7398
6934
|
// src/mcp/tools/request.ts
|
|
7399
|
-
import { z as
|
|
6935
|
+
import { z as z9 } from "zod";
|
|
7400
6936
|
var requestInputSchema = {
|
|
7401
|
-
query:
|
|
7402
|
-
card_id:
|
|
7403
|
-
skill_id:
|
|
7404
|
-
params:
|
|
7405
|
-
max_cost:
|
|
7406
|
-
timeout_ms:
|
|
6937
|
+
query: z9.string().optional().describe("Search query to find a matching capability (auto-request mode)"),
|
|
6938
|
+
card_id: z9.string().optional().describe("Direct card ID to request (skips search)"),
|
|
6939
|
+
skill_id: z9.string().optional().describe("Specific skill within a v2.0 card"),
|
|
6940
|
+
params: z9.record(z9.unknown()).optional().describe("Input parameters for the capability"),
|
|
6941
|
+
max_cost: z9.number().optional().default(50).describe("Maximum credits to spend"),
|
|
6942
|
+
timeout_ms: z9.number().positive().optional().describe("Requester timeout override in milliseconds")
|
|
7407
6943
|
};
|
|
7408
6944
|
function parsePositiveNumber(value) {
|
|
7409
6945
|
return typeof value === "number" && value > 0 ? value : void 0;
|
|
@@ -7603,7 +7139,7 @@ async function handleRequest(args, ctx) {
|
|
|
7603
7139
|
}
|
|
7604
7140
|
|
|
7605
7141
|
// src/mcp/tools/conduct.ts
|
|
7606
|
-
import { z as
|
|
7142
|
+
import { z as z10 } from "zod";
|
|
7607
7143
|
|
|
7608
7144
|
// src/cli/conduct.ts
|
|
7609
7145
|
async function conductAction(task, opts) {
|
|
@@ -7741,9 +7277,9 @@ async function conductAction(task, opts) {
|
|
|
7741
7277
|
|
|
7742
7278
|
// src/mcp/tools/conduct.ts
|
|
7743
7279
|
var conductInputSchema = {
|
|
7744
|
-
task:
|
|
7745
|
-
plan_only:
|
|
7746
|
-
max_budget:
|
|
7280
|
+
task: z10.string().describe("Natural language task description"),
|
|
7281
|
+
plan_only: z10.boolean().optional().default(false).describe("If true, return execution plan without executing"),
|
|
7282
|
+
max_budget: z10.number().optional().default(100).describe("Maximum credits to spend")
|
|
7747
7283
|
};
|
|
7748
7284
|
async function handleConduct(args, _ctx) {
|
|
7749
7285
|
try {
|
|
@@ -7763,14 +7299,26 @@ async function handleConduct(args, _ctx) {
|
|
|
7763
7299
|
}
|
|
7764
7300
|
|
|
7765
7301
|
// src/mcp/tools/status.ts
|
|
7766
|
-
import { z as
|
|
7302
|
+
import { z as z11 } from "zod";
|
|
7767
7303
|
var statusInputSchema = {
|
|
7768
|
-
_unused:
|
|
7304
|
+
_unused: z11.string().optional().describe("No parameters needed")
|
|
7769
7305
|
};
|
|
7306
|
+
function readLocalBalance(creditDbPath, creditKey) {
|
|
7307
|
+
const creditDb = openCreditDb(creditDbPath);
|
|
7308
|
+
try {
|
|
7309
|
+
return getBalance(creditDb, creditKey);
|
|
7310
|
+
} catch {
|
|
7311
|
+
return 0;
|
|
7312
|
+
} finally {
|
|
7313
|
+
creditDb.close();
|
|
7314
|
+
}
|
|
7315
|
+
}
|
|
7770
7316
|
async function handleStatus(ctx) {
|
|
7771
7317
|
try {
|
|
7772
|
-
let balance = 0;
|
|
7773
7318
|
const creditKey = ctx.identity.agent_id ?? ctx.identity.owner;
|
|
7319
|
+
const local_balance = readLocalBalance(ctx.config.credit_db_path, creditKey);
|
|
7320
|
+
let registry_balance = null;
|
|
7321
|
+
let sync_needed = false;
|
|
7774
7322
|
if (ctx.config.registry) {
|
|
7775
7323
|
try {
|
|
7776
7324
|
const keys = loadKeyPair(ctx.configDir);
|
|
@@ -7779,28 +7327,19 @@ async function handleStatus(ctx) {
|
|
|
7779
7327
|
ownerPublicKey: ctx.identity.public_key,
|
|
7780
7328
|
privateKey: keys.privateKey
|
|
7781
7329
|
});
|
|
7782
|
-
|
|
7330
|
+
registry_balance = await ledger.getBalance(creditKey);
|
|
7331
|
+
sync_needed = Math.abs(registry_balance - local_balance) > 1;
|
|
7783
7332
|
} catch {
|
|
7784
|
-
const creditDb = openCreditDb(ctx.config.credit_db_path);
|
|
7785
|
-
try {
|
|
7786
|
-
balance = getBalance(creditDb, creditKey);
|
|
7787
|
-
} finally {
|
|
7788
|
-
creditDb.close();
|
|
7789
|
-
}
|
|
7790
|
-
}
|
|
7791
|
-
} else {
|
|
7792
|
-
const creditDb = openCreditDb(ctx.config.credit_db_path);
|
|
7793
|
-
try {
|
|
7794
|
-
balance = getBalance(creditDb, creditKey);
|
|
7795
|
-
} finally {
|
|
7796
|
-
creditDb.close();
|
|
7797
7333
|
}
|
|
7798
7334
|
}
|
|
7335
|
+
const balance = registry_balance ?? local_balance;
|
|
7799
7336
|
const result = {
|
|
7800
7337
|
agent_id: ctx.identity.agent_id,
|
|
7801
7338
|
owner: ctx.identity.owner,
|
|
7802
7339
|
public_key: ctx.identity.public_key,
|
|
7803
7340
|
balance,
|
|
7341
|
+
local_balance,
|
|
7342
|
+
...ctx.config.registry ? { registry_balance, sync_needed } : {},
|
|
7804
7343
|
registry_url: ctx.config.registry ?? null,
|
|
7805
7344
|
config_dir: ctx.configDir
|
|
7806
7345
|
};
|
|
@@ -7816,9 +7355,9 @@ async function handleStatus(ctx) {
|
|
|
7816
7355
|
}
|
|
7817
7356
|
|
|
7818
7357
|
// src/mcp/tools/publish.ts
|
|
7819
|
-
import { z as
|
|
7358
|
+
import { z as z12 } from "zod";
|
|
7820
7359
|
var publishInputSchema = {
|
|
7821
|
-
card_json:
|
|
7360
|
+
card_json: z12.string().describe("JSON string of the capability card to publish")
|
|
7822
7361
|
};
|
|
7823
7362
|
async function handlePublish(args, ctx) {
|
|
7824
7363
|
try {
|
|
@@ -7898,24 +7437,24 @@ async function handlePublish(args, ctx) {
|
|
|
7898
7437
|
var contextCache = /* @__PURE__ */ new Map();
|
|
7899
7438
|
function resolveConfigDir(toolCtx) {
|
|
7900
7439
|
if (toolCtx.agentDir) {
|
|
7901
|
-
return toolCtx.agentDir.endsWith(".agentbnb") ? toolCtx.agentDir :
|
|
7440
|
+
return toolCtx.agentDir.endsWith(".agentbnb") ? toolCtx.agentDir : join5(toolCtx.agentDir, ".agentbnb");
|
|
7902
7441
|
}
|
|
7903
7442
|
if (toolCtx.workspaceDir) {
|
|
7904
|
-
return
|
|
7443
|
+
return join5(toolCtx.workspaceDir, ".agentbnb");
|
|
7905
7444
|
}
|
|
7906
|
-
return
|
|
7445
|
+
return join5(homedir3(), ".agentbnb");
|
|
7907
7446
|
}
|
|
7908
7447
|
function buildMcpContext(toolCtx) {
|
|
7909
7448
|
const configDir = resolveConfigDir(toolCtx);
|
|
7910
7449
|
const cached = contextCache.get(configDir);
|
|
7911
7450
|
if (cached) return cached;
|
|
7912
|
-
const configPath =
|
|
7913
|
-
if (!
|
|
7451
|
+
const configPath = join5(configDir, "config.json");
|
|
7452
|
+
if (!existsSync6(configPath)) {
|
|
7914
7453
|
throw new Error(
|
|
7915
7454
|
`AgentBnB not initialized at ${configDir}. Run \`agentbnb init\` or activate the plugin first.`
|
|
7916
7455
|
);
|
|
7917
7456
|
}
|
|
7918
|
-
const config = JSON.parse(
|
|
7457
|
+
const config = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
7919
7458
|
const identity = ensureIdentity(configDir, config.owner);
|
|
7920
7459
|
const ctx = { configDir, config, identity };
|
|
7921
7460
|
contextCache.set(configDir, ctx);
|
|
@@ -8075,18 +7614,18 @@ function resolveWorkspaceDir() {
|
|
|
8075
7614
|
if (process.env["AGENTBNB_DIR"]) {
|
|
8076
7615
|
return process.env["AGENTBNB_DIR"];
|
|
8077
7616
|
}
|
|
8078
|
-
const openclawAgentsDir =
|
|
7617
|
+
const openclawAgentsDir = join6(homedir4(), ".openclaw", "agents");
|
|
8079
7618
|
const cwd = process.cwd();
|
|
8080
7619
|
if (cwd.startsWith(openclawAgentsDir + "/")) {
|
|
8081
7620
|
const relative = cwd.slice(openclawAgentsDir.length + 1);
|
|
8082
7621
|
const agentName = relative.split("/")[0];
|
|
8083
|
-
return
|
|
7622
|
+
return join6(openclawAgentsDir, agentName, ".agentbnb");
|
|
8084
7623
|
}
|
|
8085
|
-
return
|
|
7624
|
+
return join6(homedir4(), ".agentbnb");
|
|
8086
7625
|
}
|
|
8087
7626
|
function registerDecomposerCard(configDir, owner) {
|
|
8088
7627
|
try {
|
|
8089
|
-
const db = openDatabase(
|
|
7628
|
+
const db = openDatabase(join6(configDir, "registry.db"));
|
|
8090
7629
|
const existing = db.prepare(
|
|
8091
7630
|
"SELECT id FROM capability_cards WHERE owner = ? AND json_extract(data, '$.capability_type') = ?"
|
|
8092
7631
|
).get(owner, "task_decomposition");
|
|
@@ -8216,7 +7755,7 @@ function writeBootstrapMd(bootstrapPath, configDir) {
|
|
|
8216
7755
|
"---",
|
|
8217
7756
|
"_Generated by AgentBnB bootstrap on first install._"
|
|
8218
7757
|
].join("\n");
|
|
8219
|
-
|
|
7758
|
+
writeFileSync2(bootstrapPath, content, "utf-8");
|
|
8220
7759
|
}
|
|
8221
7760
|
async function activate(config = {}, _onboardDeps) {
|
|
8222
7761
|
const debug = process.env["AGENTBNB_DEBUG"] === "1";
|
|
@@ -8225,7 +7764,7 @@ async function activate(config = {}, _onboardDeps) {
|
|
|
8225
7764
|
if (debug) process.stderr.write(`[agentbnb] AGENTBNB_DIR set from config.agentDir: ${config.agentDir}
|
|
8226
7765
|
`);
|
|
8227
7766
|
} else if (config.workspaceDir) {
|
|
8228
|
-
const derived =
|
|
7767
|
+
const derived = join6(config.workspaceDir, ".agentbnb");
|
|
8229
7768
|
process.env["AGENTBNB_DIR"] = derived;
|
|
8230
7769
|
if (debug) process.stderr.write(`[agentbnb] AGENTBNB_DIR derived from config.workspaceDir: ${derived}
|
|
8231
7770
|
`);
|
|
@@ -8245,11 +7784,11 @@ async function activate(config = {}, _onboardDeps) {
|
|
|
8245
7784
|
let agentConfig = loadConfig();
|
|
8246
7785
|
if (!agentConfig) {
|
|
8247
7786
|
const agentName = deriveAgentName(configDir);
|
|
8248
|
-
const brainsDir =
|
|
8249
|
-
const brainDir =
|
|
8250
|
-
if (
|
|
8251
|
-
const bootstrapPath =
|
|
8252
|
-
if (!
|
|
7787
|
+
const brainsDir = join6(homedir4(), ".openclaw", "workspace", "brains");
|
|
7788
|
+
const brainDir = join6(brainsDir, agentName);
|
|
7789
|
+
if (existsSync7(brainDir)) {
|
|
7790
|
+
const bootstrapPath = join6(brainDir, "BOOTSTRAP.md");
|
|
7791
|
+
if (!existsSync7(bootstrapPath)) {
|
|
8253
7792
|
try {
|
|
8254
7793
|
writeBootstrapMd(bootstrapPath, configDir);
|
|
8255
7794
|
if (debug) process.stderr.write("[agentbnb] Created BOOTSTRAP.md for first-run setup\n");
|
|
@@ -8265,7 +7804,7 @@ async function activate(config = {}, _onboardDeps) {
|
|
|
8265
7804
|
`
|
|
8266
7805
|
);
|
|
8267
7806
|
}
|
|
8268
|
-
const guard = new ProcessGuard(
|
|
7807
|
+
const guard = new ProcessGuard(join6(configDir, ".pid"));
|
|
8269
7808
|
const coordinator = new ServiceCoordinator(agentConfig, guard);
|
|
8270
7809
|
const service = new AgentBnBService(coordinator, agentConfig);
|
|
8271
7810
|
const opts = {
|