agentbnb 3.1.1 → 3.1.3
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/{card-EWIXC377.js → card-IE5UV5QX.js} +1 -1
- package/dist/{chunk-VCW7IDJM.js → chunk-7OACGAFD.js} +1 -1
- package/dist/{chunk-2ETVQXP7.js → chunk-IZZ4FP45.js} +15 -8
- package/dist/{chunk-MZCNJ5PY.js → chunk-QHQPXO67.js} +58 -1
- package/dist/{chunk-MGHI67GR.js → chunk-QSPWE5AE.js} +5 -60
- package/dist/{chunk-QAY6XTT7.js → chunk-UOGDK2S2.js} +1 -1
- package/dist/{chunk-7RU5INZI.js → chunk-XA63SD4T.js} +4 -0
- package/dist/cli/index.js +180 -37
- package/dist/{conduct-5T3LGXMF.js → conduct-IEQ567ET.js} +5 -5
- package/dist/{conductor-mode-GPLAM2XO.js → conductor-mode-IO45PWMI.js} +4 -4
- package/dist/execute-SWWEHV2K.js +9 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +35 -20
- package/package.json +1 -1
- package/dist/execute-NZXTSSVV.js +0 -9
|
@@ -5,11 +5,12 @@ import {
|
|
|
5
5
|
getBalance,
|
|
6
6
|
holdEscrow,
|
|
7
7
|
releaseEscrow,
|
|
8
|
-
settleEscrow
|
|
9
|
-
|
|
8
|
+
settleEscrow,
|
|
9
|
+
signEscrowReceipt
|
|
10
|
+
} from "./chunk-QHQPXO67.js";
|
|
10
11
|
import {
|
|
11
12
|
AgentBnBError
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XA63SD4T.js";
|
|
13
14
|
|
|
14
15
|
// src/autonomy/tiers.ts
|
|
15
16
|
import { randomUUID } from "crypto";
|
|
@@ -150,7 +151,7 @@ function filterCards(db, filters) {
|
|
|
150
151
|
// src/gateway/client.ts
|
|
151
152
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
152
153
|
async function requestCapability(opts) {
|
|
153
|
-
const { gatewayUrl, token, cardId, params = {}, timeoutMs = 3e4, escrowReceipt } = opts;
|
|
154
|
+
const { gatewayUrl, token, cardId, params = {}, timeoutMs = 3e4, escrowReceipt, identity } = opts;
|
|
154
155
|
const id = randomUUID2();
|
|
155
156
|
const payload = {
|
|
156
157
|
jsonrpc: "2.0",
|
|
@@ -162,16 +163,22 @@ async function requestCapability(opts) {
|
|
|
162
163
|
...escrowReceipt ? { escrow_receipt: escrowReceipt } : {}
|
|
163
164
|
}
|
|
164
165
|
};
|
|
166
|
+
const headers = { "Content-Type": "application/json" };
|
|
167
|
+
if (identity) {
|
|
168
|
+
const signature = signEscrowReceipt(payload, identity.privateKey);
|
|
169
|
+
headers["X-Agent-Id"] = identity.agentId;
|
|
170
|
+
headers["X-Agent-Public-Key"] = identity.publicKey;
|
|
171
|
+
headers["X-Agent-Signature"] = signature;
|
|
172
|
+
} else if (token) {
|
|
173
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
174
|
+
}
|
|
165
175
|
const controller = new AbortController();
|
|
166
176
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
167
177
|
let response;
|
|
168
178
|
try {
|
|
169
179
|
response = await fetch(`${gatewayUrl}/rpc`, {
|
|
170
180
|
method: "POST",
|
|
171
|
-
headers
|
|
172
|
-
"Content-Type": "application/json",
|
|
173
|
-
Authorization: `Bearer ${token}`
|
|
174
|
-
},
|
|
181
|
+
headers,
|
|
175
182
|
body: JSON.stringify(payload),
|
|
176
183
|
signal: controller.signal
|
|
177
184
|
});
|
|
@@ -1,6 +1,58 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AgentBnBError
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XA63SD4T.js";
|
|
4
|
+
|
|
5
|
+
// src/credit/signing.ts
|
|
6
|
+
import { generateKeyPairSync, sign, verify, createPublicKey, createPrivateKey } from "crypto";
|
|
7
|
+
import { writeFileSync, readFileSync, existsSync, chmodSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
function generateKeyPair() {
|
|
10
|
+
const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
|
|
11
|
+
publicKeyEncoding: { type: "spki", format: "der" },
|
|
12
|
+
privateKeyEncoding: { type: "pkcs8", format: "der" }
|
|
13
|
+
});
|
|
14
|
+
return {
|
|
15
|
+
publicKey: Buffer.from(publicKey),
|
|
16
|
+
privateKey: Buffer.from(privateKey)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function saveKeyPair(configDir, keys) {
|
|
20
|
+
const privatePath = join(configDir, "private.key");
|
|
21
|
+
const publicPath = join(configDir, "public.key");
|
|
22
|
+
writeFileSync(privatePath, keys.privateKey);
|
|
23
|
+
chmodSync(privatePath, 384);
|
|
24
|
+
writeFileSync(publicPath, keys.publicKey);
|
|
25
|
+
}
|
|
26
|
+
function loadKeyPair(configDir) {
|
|
27
|
+
const privatePath = join(configDir, "private.key");
|
|
28
|
+
const publicPath = join(configDir, "public.key");
|
|
29
|
+
if (!existsSync(privatePath) || !existsSync(publicPath)) {
|
|
30
|
+
throw new AgentBnBError("Keypair not found. Run `agentbnb init` to generate one.", "KEYPAIR_NOT_FOUND");
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
publicKey: readFileSync(publicPath),
|
|
34
|
+
privateKey: readFileSync(privatePath)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function canonicalJson(data) {
|
|
38
|
+
return JSON.stringify(data, Object.keys(data).sort());
|
|
39
|
+
}
|
|
40
|
+
function signEscrowReceipt(data, privateKey) {
|
|
41
|
+
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
42
|
+
const keyObject = createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
|
43
|
+
const signature = sign(null, message, keyObject);
|
|
44
|
+
return signature.toString("base64url");
|
|
45
|
+
}
|
|
46
|
+
function verifyEscrowReceipt(data, signature, publicKey) {
|
|
47
|
+
try {
|
|
48
|
+
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
49
|
+
const keyObject = createPublicKey({ key: publicKey, format: "der", type: "spki" });
|
|
50
|
+
const sigBuffer = Buffer.from(signature, "base64url");
|
|
51
|
+
return verify(null, message, keyObject, sigBuffer);
|
|
52
|
+
} catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
4
56
|
|
|
5
57
|
// src/credit/escrow.ts
|
|
6
58
|
import { randomUUID } from "crypto";
|
|
@@ -180,6 +232,11 @@ function recordEarning(db, owner, amount, _cardId, receiptNonce) {
|
|
|
180
232
|
}
|
|
181
233
|
|
|
182
234
|
export {
|
|
235
|
+
generateKeyPair,
|
|
236
|
+
saveKeyPair,
|
|
237
|
+
loadKeyPair,
|
|
238
|
+
signEscrowReceipt,
|
|
239
|
+
verifyEscrowReceipt,
|
|
183
240
|
holdEscrow,
|
|
184
241
|
settleEscrow,
|
|
185
242
|
releaseEscrow,
|
|
@@ -2,74 +2,23 @@ import {
|
|
|
2
2
|
getCard,
|
|
3
3
|
insertRequestLog,
|
|
4
4
|
updateReputation
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-UOGDK2S2.js";
|
|
6
6
|
import {
|
|
7
7
|
confirmEscrowDebit,
|
|
8
8
|
getBalance,
|
|
9
9
|
holdEscrow,
|
|
10
10
|
recordEarning,
|
|
11
11
|
releaseEscrow,
|
|
12
|
-
settleEscrow
|
|
13
|
-
|
|
12
|
+
settleEscrow,
|
|
13
|
+
verifyEscrowReceipt
|
|
14
|
+
} from "./chunk-QHQPXO67.js";
|
|
14
15
|
import {
|
|
15
16
|
AgentBnBError
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-XA63SD4T.js";
|
|
17
18
|
|
|
18
19
|
// src/gateway/execute.ts
|
|
19
20
|
import { randomUUID } from "crypto";
|
|
20
21
|
|
|
21
|
-
// src/credit/signing.ts
|
|
22
|
-
import { generateKeyPairSync, sign, verify, createPublicKey, createPrivateKey } from "crypto";
|
|
23
|
-
import { writeFileSync, readFileSync, existsSync, chmodSync } from "fs";
|
|
24
|
-
import { join } from "path";
|
|
25
|
-
function generateKeyPair() {
|
|
26
|
-
const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
|
|
27
|
-
publicKeyEncoding: { type: "spki", format: "der" },
|
|
28
|
-
privateKeyEncoding: { type: "pkcs8", format: "der" }
|
|
29
|
-
});
|
|
30
|
-
return {
|
|
31
|
-
publicKey: Buffer.from(publicKey),
|
|
32
|
-
privateKey: Buffer.from(privateKey)
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
function saveKeyPair(configDir, keys) {
|
|
36
|
-
const privatePath = join(configDir, "private.key");
|
|
37
|
-
const publicPath = join(configDir, "public.key");
|
|
38
|
-
writeFileSync(privatePath, keys.privateKey);
|
|
39
|
-
chmodSync(privatePath, 384);
|
|
40
|
-
writeFileSync(publicPath, keys.publicKey);
|
|
41
|
-
}
|
|
42
|
-
function loadKeyPair(configDir) {
|
|
43
|
-
const privatePath = join(configDir, "private.key");
|
|
44
|
-
const publicPath = join(configDir, "public.key");
|
|
45
|
-
if (!existsSync(privatePath) || !existsSync(publicPath)) {
|
|
46
|
-
throw new AgentBnBError("Keypair not found. Run `agentbnb init` to generate one.", "KEYPAIR_NOT_FOUND");
|
|
47
|
-
}
|
|
48
|
-
return {
|
|
49
|
-
publicKey: readFileSync(publicPath),
|
|
50
|
-
privateKey: readFileSync(privatePath)
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function canonicalJson(data) {
|
|
54
|
-
return JSON.stringify(data, Object.keys(data).sort());
|
|
55
|
-
}
|
|
56
|
-
function signEscrowReceipt(data, privateKey) {
|
|
57
|
-
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
58
|
-
const keyObject = createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
|
59
|
-
const signature = sign(null, message, keyObject);
|
|
60
|
-
return signature.toString("base64url");
|
|
61
|
-
}
|
|
62
|
-
function verifyEscrowReceipt(data, signature, publicKey) {
|
|
63
|
-
try {
|
|
64
|
-
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
65
|
-
const keyObject = createPublicKey({ key: publicKey, format: "der", type: "spki" });
|
|
66
|
-
const sigBuffer = Buffer.from(signature, "base64url");
|
|
67
|
-
return verify(null, message, keyObject, sigBuffer);
|
|
68
|
-
} catch {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
22
|
// src/credit/settlement.ts
|
|
74
23
|
function settleProviderEarning(providerDb, providerOwner, receipt) {
|
|
75
24
|
recordEarning(
|
|
@@ -247,10 +196,6 @@ async function executeCapabilityRequest(opts) {
|
|
|
247
196
|
}
|
|
248
197
|
|
|
249
198
|
export {
|
|
250
|
-
generateKeyPair,
|
|
251
|
-
saveKeyPair,
|
|
252
|
-
loadKeyPair,
|
|
253
|
-
signEscrowReceipt,
|
|
254
199
|
settleRequesterEscrow,
|
|
255
200
|
releaseRequesterEscrow,
|
|
256
201
|
executeCapabilityRequest
|
|
@@ -39,6 +39,8 @@ var CapabilityCardSchema = z.object({
|
|
|
39
39
|
* never transmitted beyond the local store.
|
|
40
40
|
*/
|
|
41
41
|
_internal: z.record(z.unknown()).optional(),
|
|
42
|
+
/** Public gateway URL where this agent accepts requests. Populated on remote publish. */
|
|
43
|
+
gateway_url: z.string().url().optional(),
|
|
42
44
|
metadata: z.object({
|
|
43
45
|
apis_used: z.array(z.string()).optional(),
|
|
44
46
|
avg_latency_ms: z.number().nonnegative().optional(),
|
|
@@ -103,6 +105,8 @@ var CapabilityCardV2Schema = z.object({
|
|
|
103
105
|
* never transmitted beyond the local store.
|
|
104
106
|
*/
|
|
105
107
|
_internal: z.record(z.unknown()).optional(),
|
|
108
|
+
/** Public gateway URL where this agent accepts requests. Populated on remote publish. */
|
|
109
|
+
gateway_url: z.string().url().optional(),
|
|
106
110
|
created_at: z.string().datetime().optional(),
|
|
107
111
|
updated_at: z.string().datetime().optional()
|
|
108
112
|
});
|
package/dist/cli/index.js
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
executeCapabilityRequest,
|
|
4
|
-
generateKeyPair,
|
|
5
|
-
loadKeyPair,
|
|
6
4
|
releaseRequesterEscrow,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
signEscrowReceipt
|
|
10
|
-
} from "../chunk-MGHI67GR.js";
|
|
5
|
+
settleRequesterEscrow
|
|
6
|
+
} from "../chunk-QSPWE5AE.js";
|
|
11
7
|
import {
|
|
12
8
|
RelayMessageSchema
|
|
13
9
|
} from "../chunk-3Y36WQDV.js";
|
|
@@ -24,7 +20,7 @@ import {
|
|
|
24
20
|
requestCapability,
|
|
25
21
|
resolvePendingRequest,
|
|
26
22
|
searchCards
|
|
27
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-IZZ4FP45.js";
|
|
28
24
|
import {
|
|
29
25
|
findPeer,
|
|
30
26
|
getConfigDir,
|
|
@@ -46,20 +42,25 @@ import {
|
|
|
46
42
|
updateCard,
|
|
47
43
|
updateSkillAvailability,
|
|
48
44
|
updateSkillIdleRate
|
|
49
|
-
} from "../chunk-
|
|
45
|
+
} from "../chunk-UOGDK2S2.js";
|
|
50
46
|
import {
|
|
51
47
|
bootstrapAgent,
|
|
48
|
+
generateKeyPair,
|
|
52
49
|
getBalance,
|
|
53
50
|
getTransactions,
|
|
54
51
|
holdEscrow,
|
|
52
|
+
loadKeyPair,
|
|
55
53
|
openCreditDb,
|
|
56
|
-
releaseEscrow
|
|
57
|
-
|
|
54
|
+
releaseEscrow,
|
|
55
|
+
saveKeyPair,
|
|
56
|
+
signEscrowReceipt,
|
|
57
|
+
verifyEscrowReceipt
|
|
58
|
+
} from "../chunk-QHQPXO67.js";
|
|
58
59
|
import {
|
|
59
60
|
AgentBnBError,
|
|
60
61
|
AnyCardSchema,
|
|
61
62
|
CapabilityCardV2Schema
|
|
62
|
-
} from "../chunk-
|
|
63
|
+
} from "../chunk-XA63SD4T.js";
|
|
63
64
|
|
|
64
65
|
// src/cli/index.ts
|
|
65
66
|
import { Command } from "commander";
|
|
@@ -1525,8 +1526,8 @@ var AgentRuntime = class {
|
|
|
1525
1526
|
}
|
|
1526
1527
|
const modes = /* @__PURE__ */ new Map();
|
|
1527
1528
|
if (this.conductorEnabled) {
|
|
1528
|
-
const { ConductorMode } = await import("../conductor-mode-
|
|
1529
|
-
const { registerConductorCard, CONDUCTOR_OWNER } = await import("../card-
|
|
1529
|
+
const { ConductorMode } = await import("../conductor-mode-IO45PWMI.js");
|
|
1530
|
+
const { registerConductorCard, CONDUCTOR_OWNER } = await import("../card-IE5UV5QX.js");
|
|
1530
1531
|
const { loadPeers: loadPeers2 } = await import("../peers-G36URZYB.js");
|
|
1531
1532
|
registerConductorCard(this.registryDb);
|
|
1532
1533
|
const resolveAgentUrl = (owner) => {
|
|
@@ -1648,22 +1649,27 @@ function createGatewayServer(opts) {
|
|
|
1648
1649
|
fastify.addHook("onRequest", async (request, reply) => {
|
|
1649
1650
|
if (request.method === "GET" && request.url === "/health") return;
|
|
1650
1651
|
const auth = request.headers.authorization;
|
|
1651
|
-
if (
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
}
|
|
1652
|
+
if (auth && auth.startsWith("Bearer ")) {
|
|
1653
|
+
const token = auth.slice("Bearer ".length).trim();
|
|
1654
|
+
if (tokenSet.has(token)) return;
|
|
1655
|
+
}
|
|
1656
|
+
const agentId = request.headers["x-agent-id"];
|
|
1657
|
+
const publicKeyHex = request.headers["x-agent-public-key"];
|
|
1658
|
+
const signature = request.headers["x-agent-signature"];
|
|
1659
|
+
if (agentId && publicKeyHex && signature) {
|
|
1660
|
+
try {
|
|
1661
|
+
const publicKeyBuf = Buffer.from(publicKeyHex, "hex");
|
|
1662
|
+
const body = request.body;
|
|
1663
|
+
const valid = verifyEscrowReceipt(body, signature, publicKeyBuf);
|
|
1664
|
+
if (valid) return;
|
|
1665
|
+
} catch {
|
|
1666
|
+
}
|
|
1666
1667
|
}
|
|
1668
|
+
await reply.status(401).send({
|
|
1669
|
+
jsonrpc: "2.0",
|
|
1670
|
+
id: null,
|
|
1671
|
+
error: { code: -32e3, message: "Unauthorized: provide Bearer token or X-Agent-Id/Signature headers" }
|
|
1672
|
+
});
|
|
1667
1673
|
});
|
|
1668
1674
|
fastify.get("/health", async () => {
|
|
1669
1675
|
return { status: "ok", version: VERSION, uptime: process.uptime() };
|
|
@@ -3161,11 +3167,12 @@ program.command("publish <card.json>").description("Publish a Capability Card to
|
|
|
3161
3167
|
let remoteSuccess = false;
|
|
3162
3168
|
if (registryUrl) {
|
|
3163
3169
|
const url = `${registryUrl.replace(/\/$/, "")}/cards`;
|
|
3170
|
+
const remoteCard = { ...card, gateway_url: config.gateway_url };
|
|
3164
3171
|
try {
|
|
3165
3172
|
const response = await fetch(url, {
|
|
3166
3173
|
method: "POST",
|
|
3167
3174
|
headers: { "Content-Type": "application/json" },
|
|
3168
|
-
body: JSON.stringify(
|
|
3175
|
+
body: JSON.stringify(remoteCard)
|
|
3169
3176
|
});
|
|
3170
3177
|
if (!response.ok) {
|
|
3171
3178
|
const body = await response.text();
|
|
@@ -3190,6 +3197,77 @@ program.command("publish <card.json>").description("Publish a Capability Card to
|
|
|
3190
3197
|
} else if (!registryUrl) {
|
|
3191
3198
|
}
|
|
3192
3199
|
});
|
|
3200
|
+
program.command("sync").description("Push all local capability cards to the configured remote registry").option("--registry <url>", "Remote registry URL (overrides config.registry)").option("--json", "Output as JSON").action(async (opts) => {
|
|
3201
|
+
const config = loadConfig();
|
|
3202
|
+
if (!config) {
|
|
3203
|
+
console.error("Error: not initialized. Run `agentbnb init` first.");
|
|
3204
|
+
process.exit(1);
|
|
3205
|
+
}
|
|
3206
|
+
const registryUrl = opts.registry ?? config.registry;
|
|
3207
|
+
if (!registryUrl) {
|
|
3208
|
+
console.error("Error: no remote registry configured.");
|
|
3209
|
+
console.error("Set one with: agentbnb config set registry <url>");
|
|
3210
|
+
process.exit(1);
|
|
3211
|
+
}
|
|
3212
|
+
const db = openDatabase(config.db_path);
|
|
3213
|
+
let localCards;
|
|
3214
|
+
try {
|
|
3215
|
+
localCards = listCards(db);
|
|
3216
|
+
} finally {
|
|
3217
|
+
db.close();
|
|
3218
|
+
}
|
|
3219
|
+
if (localCards.length === 0) {
|
|
3220
|
+
if (opts.json) {
|
|
3221
|
+
console.log(JSON.stringify({ synced: 0, failed: 0, registry: registryUrl }));
|
|
3222
|
+
} else {
|
|
3223
|
+
console.log("No local cards to sync.");
|
|
3224
|
+
}
|
|
3225
|
+
return;
|
|
3226
|
+
}
|
|
3227
|
+
const url = `${registryUrl.replace(/\/$/, "")}/cards`;
|
|
3228
|
+
let synced = 0;
|
|
3229
|
+
let failed = 0;
|
|
3230
|
+
const results = [];
|
|
3231
|
+
for (const card of localCards) {
|
|
3232
|
+
const { _internal: _, ...publicCard } = card;
|
|
3233
|
+
const remoteCard = { ...publicCard, gateway_url: config.gateway_url };
|
|
3234
|
+
const displayName = card.name ?? card.agent_name ?? card.id;
|
|
3235
|
+
try {
|
|
3236
|
+
const response = await fetch(url, {
|
|
3237
|
+
method: "POST",
|
|
3238
|
+
headers: { "Content-Type": "application/json" },
|
|
3239
|
+
body: JSON.stringify(remoteCard)
|
|
3240
|
+
});
|
|
3241
|
+
if (response.ok) {
|
|
3242
|
+
synced++;
|
|
3243
|
+
results.push({ id: card.id, name: displayName, ok: true });
|
|
3244
|
+
if (!opts.json) {
|
|
3245
|
+
console.log(` Synced: ${displayName} (${card.id.slice(0, 8)}...)`);
|
|
3246
|
+
}
|
|
3247
|
+
} else {
|
|
3248
|
+
const body = await response.text();
|
|
3249
|
+
failed++;
|
|
3250
|
+
results.push({ id: card.id, name: displayName, ok: false, error: `${response.status}: ${body}` });
|
|
3251
|
+
if (!opts.json) {
|
|
3252
|
+
console.error(` Failed: ${displayName} \u2014 ${response.status}`);
|
|
3253
|
+
}
|
|
3254
|
+
}
|
|
3255
|
+
} catch (err) {
|
|
3256
|
+
failed++;
|
|
3257
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
3258
|
+
results.push({ id: card.id, name: displayName, ok: false, error: msg });
|
|
3259
|
+
if (!opts.json) {
|
|
3260
|
+
console.error(` Failed: ${displayName} \u2014 ${msg}`);
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
if (opts.json) {
|
|
3265
|
+
console.log(JSON.stringify({ synced, failed, registry: registryUrl, results }, null, 2));
|
|
3266
|
+
} else {
|
|
3267
|
+
console.log(`
|
|
3268
|
+
Synced ${synced}/${localCards.length} cards to ${registryUrl}${failed > 0 ? ` (${failed} failed)` : ""}`);
|
|
3269
|
+
}
|
|
3270
|
+
});
|
|
3193
3271
|
program.command("discover [query]").description("Search available capabilities in the registry").option("--level <level>", "Filter by level (1, 2, or 3)").option("--online", "Only show online capabilities").option("--local", "Browse for agents on the local network via mDNS").option("--registry <url>", "Remote registry URL to query (e.g., http://host:7701)").option("--tag <tag>", "Filter by metadata tag").option("--json", "Output as JSON").action(async (query, opts) => {
|
|
3194
3272
|
if (opts.local) {
|
|
3195
3273
|
const discovered = [];
|
|
@@ -3361,7 +3439,8 @@ program.command("request [card-id]").description("Request a capability from anot
|
|
|
3361
3439
|
}
|
|
3362
3440
|
let gatewayUrl;
|
|
3363
3441
|
let token;
|
|
3364
|
-
|
|
3442
|
+
let isRemoteRequest = false;
|
|
3443
|
+
let identityAuth;
|
|
3365
3444
|
if (opts.peer) {
|
|
3366
3445
|
const peer = findPeer(opts.peer);
|
|
3367
3446
|
if (!peer) {
|
|
@@ -3370,13 +3449,76 @@ program.command("request [card-id]").description("Request a capability from anot
|
|
|
3370
3449
|
}
|
|
3371
3450
|
gatewayUrl = peer.url;
|
|
3372
3451
|
token = peer.token;
|
|
3452
|
+
isRemoteRequest = true;
|
|
3453
|
+
const configDir = getConfigDir();
|
|
3454
|
+
const agentIdentity = loadIdentity(configDir);
|
|
3455
|
+
if (agentIdentity) {
|
|
3456
|
+
const keys = loadKeyPair(configDir);
|
|
3457
|
+
identityAuth = {
|
|
3458
|
+
agentId: agentIdentity.agent_id,
|
|
3459
|
+
publicKey: agentIdentity.public_key,
|
|
3460
|
+
privateKey: keys.privateKey
|
|
3461
|
+
};
|
|
3462
|
+
}
|
|
3373
3463
|
} else {
|
|
3374
|
-
|
|
3375
|
-
|
|
3464
|
+
const db = openDatabase(config.db_path);
|
|
3465
|
+
let localCard;
|
|
3466
|
+
try {
|
|
3467
|
+
localCard = db.prepare("SELECT data FROM capability_cards WHERE id = ?").get(cardId) ? JSON.parse(db.prepare("SELECT data FROM capability_cards WHERE id = ?").get(cardId).data) : void 0;
|
|
3468
|
+
} finally {
|
|
3469
|
+
db.close();
|
|
3470
|
+
}
|
|
3471
|
+
if (localCard) {
|
|
3472
|
+
gatewayUrl = config.gateway_url;
|
|
3473
|
+
token = config.token;
|
|
3474
|
+
} else {
|
|
3475
|
+
const registryUrl = config.registry;
|
|
3476
|
+
if (!registryUrl) {
|
|
3477
|
+
console.error("Error: card not found locally and no remote registry configured.");
|
|
3478
|
+
console.error("Set one with: agentbnb config set registry <url>");
|
|
3479
|
+
process.exit(1);
|
|
3480
|
+
}
|
|
3481
|
+
const cardUrl = `${registryUrl.replace(/\/$/, "")}/cards/${cardId}`;
|
|
3482
|
+
let remoteCard;
|
|
3483
|
+
try {
|
|
3484
|
+
const resp = await fetch(cardUrl);
|
|
3485
|
+
if (!resp.ok) {
|
|
3486
|
+
console.error(`Error: card ${cardId} not found on remote registry (${resp.status}).`);
|
|
3487
|
+
process.exit(1);
|
|
3488
|
+
}
|
|
3489
|
+
remoteCard = await resp.json();
|
|
3490
|
+
} catch (err) {
|
|
3491
|
+
console.error(`Error: cannot reach registry: ${err.message}`);
|
|
3492
|
+
process.exit(1);
|
|
3493
|
+
}
|
|
3494
|
+
if (!remoteCard.gateway_url || typeof remoteCard.gateway_url !== "string") {
|
|
3495
|
+
console.error("Error: remote card has no gateway_url. The provider needs to re-publish with `agentbnb sync`.");
|
|
3496
|
+
process.exit(1);
|
|
3497
|
+
}
|
|
3498
|
+
gatewayUrl = remoteCard.gateway_url;
|
|
3499
|
+
token = "";
|
|
3500
|
+
isRemoteRequest = true;
|
|
3501
|
+
const configDir = getConfigDir();
|
|
3502
|
+
const agentIdentity = loadIdentity(configDir);
|
|
3503
|
+
if (!agentIdentity) {
|
|
3504
|
+
console.error("Error: no agent identity found. Run `agentbnb init` first.");
|
|
3505
|
+
process.exit(1);
|
|
3506
|
+
}
|
|
3507
|
+
const keys = loadKeyPair(configDir);
|
|
3508
|
+
identityAuth = {
|
|
3509
|
+
agentId: agentIdentity.agent_id,
|
|
3510
|
+
publicKey: agentIdentity.public_key,
|
|
3511
|
+
privateKey: keys.privateKey
|
|
3512
|
+
};
|
|
3513
|
+
if (!opts.json) {
|
|
3514
|
+
const displayName = remoteCard.name ?? remoteCard.agent_name ?? cardId;
|
|
3515
|
+
console.log(`Found remote card: ${displayName} @ ${gatewayUrl}`);
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3376
3518
|
}
|
|
3377
|
-
const useReceipt =
|
|
3519
|
+
const useReceipt = isRemoteRequest && opts.receipt !== false;
|
|
3378
3520
|
if (useReceipt && !opts.cost) {
|
|
3379
|
-
console.error("Error: --cost <credits> is required for
|
|
3521
|
+
console.error("Error: --cost <credits> is required for remote requests. Specify the credits to commit.");
|
|
3380
3522
|
process.exit(1);
|
|
3381
3523
|
}
|
|
3382
3524
|
let escrowId;
|
|
@@ -3420,7 +3562,8 @@ program.command("request [card-id]").description("Request a capability from anot
|
|
|
3420
3562
|
token,
|
|
3421
3563
|
cardId,
|
|
3422
3564
|
params: { ...params, ...opts.skill ? { skill_id: opts.skill } : {} },
|
|
3423
|
-
escrowReceipt
|
|
3565
|
+
escrowReceipt,
|
|
3566
|
+
identity: identityAuth
|
|
3424
3567
|
});
|
|
3425
3568
|
if (useReceipt && escrowId) {
|
|
3426
3569
|
const configDir = getConfigDir();
|
|
@@ -3591,7 +3734,7 @@ program.command("serve").description("Start the AgentBnB gateway server").option
|
|
|
3591
3734
|
}
|
|
3592
3735
|
if (opts.registry) {
|
|
3593
3736
|
const { RelayClient } = await import("../websocket-client-5TIQDYQ4.js");
|
|
3594
|
-
const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("../execute-
|
|
3737
|
+
const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("../execute-SWWEHV2K.js");
|
|
3595
3738
|
const cards = listCards(runtime.registryDb, config.owner);
|
|
3596
3739
|
const card = cards[0] ?? {
|
|
3597
3740
|
id: config.owner,
|
|
@@ -3860,7 +4003,7 @@ openclaw.command("rules").description("Print HEARTBEAT.md rules block (or inject
|
|
|
3860
4003
|
}
|
|
3861
4004
|
});
|
|
3862
4005
|
program.command("conduct <task>").description("Orchestrate a complex task across the AgentBnB network").option("--plan-only", "Show execution plan without executing").option("--max-budget <credits>", "Maximum credits to spend", "100").option("--json", "Output as JSON").action(async (task, opts) => {
|
|
3863
|
-
const { conductAction } = await import("../conduct-
|
|
4006
|
+
const { conductAction } = await import("../conduct-IEQ567ET.js");
|
|
3864
4007
|
const result = await conductAction(task, opts);
|
|
3865
4008
|
if (opts.json) {
|
|
3866
4009
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -4,21 +4,21 @@ import {
|
|
|
4
4
|
decompose,
|
|
5
5
|
matchSubTasks,
|
|
6
6
|
orchestrate
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-7OACGAFD.js";
|
|
8
8
|
import {
|
|
9
9
|
BudgetManager
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IZZ4FP45.js";
|
|
11
11
|
import {
|
|
12
12
|
loadConfig,
|
|
13
13
|
loadPeers
|
|
14
14
|
} from "./chunk-BEI5MTNZ.js";
|
|
15
15
|
import {
|
|
16
16
|
openDatabase
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-UOGDK2S2.js";
|
|
18
18
|
import {
|
|
19
19
|
openCreditDb
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-QHQPXO67.js";
|
|
21
|
+
import "./chunk-XA63SD4T.js";
|
|
22
22
|
|
|
23
23
|
// src/cli/conduct.ts
|
|
24
24
|
async function conductAction(task, opts) {
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
decompose,
|
|
4
4
|
matchSubTasks,
|
|
5
5
|
orchestrate
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7OACGAFD.js";
|
|
7
7
|
import {
|
|
8
8
|
BudgetManager
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-IZZ4FP45.js";
|
|
10
10
|
import "./chunk-BEI5MTNZ.js";
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-QHQPXO67.js";
|
|
12
|
+
import "./chunk-XA63SD4T.js";
|
|
13
13
|
|
|
14
14
|
// src/conductor/conductor-mode.ts
|
|
15
15
|
var ConductorMode = class {
|
package/dist/index.d.ts
CHANGED
|
@@ -96,6 +96,8 @@ declare const CapabilityCardSchema: z.ZodObject<{
|
|
|
96
96
|
* never transmitted beyond the local store.
|
|
97
97
|
*/
|
|
98
98
|
_internal: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
99
|
+
/** Public gateway URL where this agent accepts requests. Populated on remote publish. */
|
|
100
|
+
gateway_url: z.ZodOptional<z.ZodString>;
|
|
99
101
|
metadata: z.ZodOptional<z.ZodObject<{
|
|
100
102
|
apis_used: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
101
103
|
avg_latency_ms: z.ZodOptional<z.ZodNumber>;
|
|
@@ -150,6 +152,7 @@ declare const CapabilityCardSchema: z.ZodObject<{
|
|
|
150
152
|
tier?: string | undefined;
|
|
151
153
|
}[] | undefined;
|
|
152
154
|
_internal?: Record<string, unknown> | undefined;
|
|
155
|
+
gateway_url?: string | undefined;
|
|
153
156
|
metadata?: {
|
|
154
157
|
apis_used?: string[] | undefined;
|
|
155
158
|
avg_latency_ms?: number | undefined;
|
|
@@ -194,6 +197,7 @@ declare const CapabilityCardSchema: z.ZodObject<{
|
|
|
194
197
|
tier?: string | undefined;
|
|
195
198
|
}[] | undefined;
|
|
196
199
|
_internal?: Record<string, unknown> | undefined;
|
|
200
|
+
gateway_url?: string | undefined;
|
|
197
201
|
metadata?: {
|
|
198
202
|
apis_used?: string[] | undefined;
|
|
199
203
|
avg_latency_ms?: number | undefined;
|
|
@@ -444,6 +448,8 @@ declare const CapabilityCardV2Schema: z.ZodObject<{
|
|
|
444
448
|
* never transmitted beyond the local store.
|
|
445
449
|
*/
|
|
446
450
|
_internal: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
451
|
+
/** Public gateway URL where this agent accepts requests. Populated on remote publish. */
|
|
452
|
+
gateway_url: z.ZodOptional<z.ZodString>;
|
|
447
453
|
created_at: z.ZodOptional<z.ZodString>;
|
|
448
454
|
updated_at: z.ZodOptional<z.ZodString>;
|
|
449
455
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -500,6 +506,7 @@ declare const CapabilityCardV2Schema: z.ZodObject<{
|
|
|
500
506
|
category?: string | undefined;
|
|
501
507
|
}[];
|
|
502
508
|
_internal?: Record<string, unknown> | undefined;
|
|
509
|
+
gateway_url?: string | undefined;
|
|
503
510
|
created_at?: string | undefined;
|
|
504
511
|
updated_at?: string | undefined;
|
|
505
512
|
environment?: {
|
|
@@ -560,6 +567,7 @@ declare const CapabilityCardV2Schema: z.ZodObject<{
|
|
|
560
567
|
category?: string | undefined;
|
|
561
568
|
}[];
|
|
562
569
|
_internal?: Record<string, unknown> | undefined;
|
|
570
|
+
gateway_url?: string | undefined;
|
|
563
571
|
created_at?: string | undefined;
|
|
564
572
|
updated_at?: string | undefined;
|
|
565
573
|
environment?: {
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,8 @@ var CapabilityCardSchema = z.object({
|
|
|
39
39
|
* never transmitted beyond the local store.
|
|
40
40
|
*/
|
|
41
41
|
_internal: z.record(z.unknown()).optional(),
|
|
42
|
+
/** Public gateway URL where this agent accepts requests. Populated on remote publish. */
|
|
43
|
+
gateway_url: z.string().url().optional(),
|
|
42
44
|
metadata: z.object({
|
|
43
45
|
apis_used: z.array(z.string()).optional(),
|
|
44
46
|
avg_latency_ms: z.number().nonnegative().optional(),
|
|
@@ -103,6 +105,8 @@ var CapabilityCardV2Schema = z.object({
|
|
|
103
105
|
* never transmitted beyond the local store.
|
|
104
106
|
*/
|
|
105
107
|
_internal: z.record(z.unknown()).optional(),
|
|
108
|
+
/** Public gateway URL where this agent accepts requests. Populated on remote publish. */
|
|
109
|
+
gateway_url: z.string().url().optional(),
|
|
106
110
|
created_at: z.string().datetime().optional(),
|
|
107
111
|
updated_at: z.string().datetime().optional()
|
|
108
112
|
});
|
|
@@ -942,22 +946,27 @@ function createGatewayServer(opts) {
|
|
|
942
946
|
fastify.addHook("onRequest", async (request, reply) => {
|
|
943
947
|
if (request.method === "GET" && request.url === "/health") return;
|
|
944
948
|
const auth = request.headers.authorization;
|
|
945
|
-
if (
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
}
|
|
949
|
+
if (auth && auth.startsWith("Bearer ")) {
|
|
950
|
+
const token = auth.slice("Bearer ".length).trim();
|
|
951
|
+
if (tokenSet.has(token)) return;
|
|
952
|
+
}
|
|
953
|
+
const agentId = request.headers["x-agent-id"];
|
|
954
|
+
const publicKeyHex = request.headers["x-agent-public-key"];
|
|
955
|
+
const signature = request.headers["x-agent-signature"];
|
|
956
|
+
if (agentId && publicKeyHex && signature) {
|
|
957
|
+
try {
|
|
958
|
+
const publicKeyBuf = Buffer.from(publicKeyHex, "hex");
|
|
959
|
+
const body = request.body;
|
|
960
|
+
const valid = verifyEscrowReceipt(body, signature, publicKeyBuf);
|
|
961
|
+
if (valid) return;
|
|
962
|
+
} catch {
|
|
963
|
+
}
|
|
960
964
|
}
|
|
965
|
+
await reply.status(401).send({
|
|
966
|
+
jsonrpc: "2.0",
|
|
967
|
+
id: null,
|
|
968
|
+
error: { code: -32e3, message: "Unauthorized: provide Bearer token or X-Agent-Id/Signature headers" }
|
|
969
|
+
});
|
|
961
970
|
});
|
|
962
971
|
fastify.get("/health", async () => {
|
|
963
972
|
return { status: "ok", version: VERSION, uptime: process.uptime() };
|
|
@@ -1913,7 +1922,7 @@ function decompose(task, _availableCapabilities) {
|
|
|
1913
1922
|
// src/gateway/client.ts
|
|
1914
1923
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
1915
1924
|
async function requestCapability(opts) {
|
|
1916
|
-
const { gatewayUrl, token, cardId, params = {}, timeoutMs = 3e4, escrowReceipt } = opts;
|
|
1925
|
+
const { gatewayUrl, token, cardId, params = {}, timeoutMs = 3e4, escrowReceipt, identity } = opts;
|
|
1917
1926
|
const id = randomUUID5();
|
|
1918
1927
|
const payload = {
|
|
1919
1928
|
jsonrpc: "2.0",
|
|
@@ -1925,16 +1934,22 @@ async function requestCapability(opts) {
|
|
|
1925
1934
|
...escrowReceipt ? { escrow_receipt: escrowReceipt } : {}
|
|
1926
1935
|
}
|
|
1927
1936
|
};
|
|
1937
|
+
const headers = { "Content-Type": "application/json" };
|
|
1938
|
+
if (identity) {
|
|
1939
|
+
const signature = signEscrowReceipt(payload, identity.privateKey);
|
|
1940
|
+
headers["X-Agent-Id"] = identity.agentId;
|
|
1941
|
+
headers["X-Agent-Public-Key"] = identity.publicKey;
|
|
1942
|
+
headers["X-Agent-Signature"] = signature;
|
|
1943
|
+
} else if (token) {
|
|
1944
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
1945
|
+
}
|
|
1928
1946
|
const controller = new AbortController();
|
|
1929
1947
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
1930
1948
|
let response;
|
|
1931
1949
|
try {
|
|
1932
1950
|
response = await fetch(`${gatewayUrl}/rpc`, {
|
|
1933
1951
|
method: "POST",
|
|
1934
|
-
headers
|
|
1935
|
-
"Content-Type": "application/json",
|
|
1936
|
-
Authorization: `Bearer ${token}`
|
|
1937
|
-
},
|
|
1952
|
+
headers,
|
|
1938
1953
|
body: JSON.stringify(payload),
|
|
1939
1954
|
signal: controller.signal
|
|
1940
1955
|
});
|
package/package.json
CHANGED