agentbnb 8.2.3 → 8.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{card-EX2EYGCZ.js → card-BN643ZOY.js} +6 -2
- package/dist/card-T2XJZA5A.js +92 -0
- package/dist/{chunk-3LWBH7P3.js → chunk-4NFJ3VYZ.js} +20 -1
- package/dist/chunk-5AIYALBX.js +857 -0
- package/dist/chunk-6QMDJVMS.js +238 -0
- package/dist/{chunk-GKVTD4EZ.js → chunk-77KGEDH4.js} +1 -1
- package/dist/{chunk-QCGIG7WW.js → chunk-7IQE34QK.js} +14 -7
- package/dist/{chunk-LKLKYXLV.js → chunk-BARHNIKG.js} +10 -7
- package/dist/{chunk-QHZGOG3O.js → chunk-D242QZCR.js} +168 -41
- package/dist/chunk-EE3V3DXK.js +60 -0
- package/dist/{chunk-RYISHSHB.js → chunk-F3KIEVJ2.js} +207 -265
- package/dist/{chunk-XBGVQMQJ.js → chunk-FELGHDCA.js} +16 -39
- package/dist/{chunk-EJKW57ZV.js → chunk-GIEJVKZZ.js} +1 -1
- package/dist/{chunk-WVY2W7AA.js → chunk-I7KWA7OB.js} +20 -0
- package/dist/{chunk-4IPJJRTP.js → chunk-IGQNP3ZO.js} +5 -2
- package/dist/chunk-NQANA6WH.js +797 -0
- package/dist/{chunk-Z4MCGKTL.js → chunk-NX27AFPA.js} +15 -2
- package/dist/{chunk-Z2GEFFDO.js → chunk-O4Q7BRG6.js} +2 -2
- package/dist/{chunk-SSK653A6.js → chunk-PQIP7EXY.js} +6 -0
- package/dist/{chunk-EG6RS4JC.js → chunk-QFPXZITP.js} +20 -65
- package/dist/chunk-R4F4XII4.js +264 -0
- package/dist/{chunk-DYQOFGGI.js → chunk-RVBW2QXU.js} +178 -49
- package/dist/{chunk-CQFBNTGT.js → chunk-S7DZHKCG.js} +25 -12
- package/dist/chunk-U6LP4KWN.js +238 -0
- package/dist/{chunk-MWOXW7JQ.js → chunk-VJ7XBEY6.js} +24 -16
- package/dist/chunk-WTHMHNKC.js +129 -0
- package/dist/{chunk-OCSU2S6W.js → chunk-WX3GZVFG.js} +2 -1
- package/dist/{chunk-CKOOVZOI.js → chunk-YKMBFQC2.js} +37 -5
- package/dist/{chunk-S3V6R3EN.js → chunk-ZU2TP7CN.js} +70 -27
- package/dist/cli/index.js +203 -237
- package/dist/client-OKJJ3UP2.js +19 -0
- package/dist/client-UQBGCIPA.js +20 -0
- package/dist/conduct-4JDMWBQD.js +22 -0
- package/dist/{conduct-AZFLNUX3.js → conduct-VYYBCPHA.js} +14 -13
- package/dist/{conductor-mode-WKB42PYM.js → conductor-mode-OPGQJFLA.js} +12 -8
- package/dist/{conductor-mode-PLTB6MS3.js → conductor-mode-SBDCRIX6.js} +16 -11
- package/dist/execute-FZLQGIXB.js +14 -0
- package/dist/execute-TEZPQ5WP.js +15 -0
- package/dist/index.d.ts +172 -11
- package/dist/index.js +1529 -433
- package/dist/{process-guard-GH5LRNWO.js → process-guard-TNSUNHSR.js} +1 -1
- package/dist/{publish-capability-QDR2QIZ2.js → publish-capability-HVYILTPR.js} +4 -3
- package/dist/{reliability-metrics-QG7WC5QK.js → reliability-metrics-G7LPUYJD.js} +3 -1
- package/dist/reliability-metrics-RRUKJ4ME.js +20 -0
- package/dist/{request-OERS5BE7.js → request-KJNKR27T.js} +76 -71
- package/dist/{serve-skill-E6EJQYAK.js → serve-skill-GC6NIQ5T.js} +10 -11
- package/dist/{server-46VEG2W7.js → server-YVLMQ2BO.js} +11 -10
- package/dist/{service-coordinator-KMSA6BST.js → service-coordinator-SCP2YIFT.js} +420 -171
- package/dist/{skill-config-FETXPNVP.js → skill-config-5O2VR546.js} +1 -1
- package/dist/skills/agentbnb/bootstrap.js +532 -256
- package/dist/websocket-client-3U27WJUU.js +7 -0
- package/dist/{websocket-client-4Z5P54RU.js → websocket-client-SNDF3B6N.js} +1 -1
- package/package.json +1 -1
- package/dist/chunk-MCED4GDW.js +0 -1572
- package/dist/chunk-NWIQJ2CL.js +0 -108
- package/dist/chunk-TUCEDQGM.js +0 -44
- package/dist/chunk-WNXXLCV5.js +0 -32
- package/dist/client-XOLP5IUZ.js +0 -12
- package/dist/conduct-VPUYTNEA.js +0 -21
- package/dist/execute-NNDCXTN4.js +0 -13
- package/dist/execute-RIRHTIBU.js +0 -16
- package/dist/websocket-client-QOVARTRN.js +0 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
RelayMessageSchema
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PQIP7EXY.js";
|
|
4
4
|
|
|
5
5
|
// src/relay/websocket-client.ts
|
|
6
6
|
import WebSocket from "ws";
|
|
@@ -125,10 +125,23 @@ var RelayClient = class {
|
|
|
125
125
|
});
|
|
126
126
|
});
|
|
127
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Send a relay_started message to acknowledge that provider has started work.
|
|
130
|
+
*
|
|
131
|
+
* @param requestId - The relay request ID being processed.
|
|
132
|
+
* @param message - Optional status message.
|
|
133
|
+
*/
|
|
134
|
+
sendStarted(requestId, message) {
|
|
135
|
+
this.send({
|
|
136
|
+
type: "relay_started",
|
|
137
|
+
id: requestId,
|
|
138
|
+
...message ? { message } : {}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
128
141
|
/**
|
|
129
142
|
* Send a relay_progress message to the relay server for a given request.
|
|
130
143
|
* Used by the onRequest handler to forward SkillExecutor progress updates
|
|
131
|
-
* to the requesting agent
|
|
144
|
+
* to the requesting agent while work is in-flight.
|
|
132
145
|
*
|
|
133
146
|
* @param requestId - The relay request ID to associate progress with.
|
|
134
147
|
* @param info - Progress details (step, total, message).
|
|
@@ -79,6 +79,11 @@ var RelayProgressMessageSchema = z.object({
|
|
|
79
79
|
message: z.string().optional()
|
|
80
80
|
// optional status message
|
|
81
81
|
});
|
|
82
|
+
var RelayStartedMessageSchema = z.object({
|
|
83
|
+
type: z.literal("relay_started"),
|
|
84
|
+
id: z.string().uuid(),
|
|
85
|
+
message: z.string().optional()
|
|
86
|
+
});
|
|
82
87
|
var HeartbeatMessageSchema = z.object({
|
|
83
88
|
type: z.literal("heartbeat"),
|
|
84
89
|
owner: z.string().min(1),
|
|
@@ -155,6 +160,7 @@ var RelayMessageSchema = z.discriminatedUnion("type", [
|
|
|
155
160
|
ResponseMessageSchema,
|
|
156
161
|
ErrorMessageSchema,
|
|
157
162
|
RelayProgressMessageSchema,
|
|
163
|
+
RelayStartedMessageSchema,
|
|
158
164
|
HeartbeatMessageSchema,
|
|
159
165
|
EscrowHoldMessageSchema,
|
|
160
166
|
EscrowHoldConfirmedMessageSchema,
|
|
@@ -1,50 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
|
-
NETWORK_FEE_RATE,
|
|
3
|
-
confirmEscrowDebit,
|
|
4
2
|
getBalance,
|
|
5
|
-
getCard,
|
|
6
3
|
holdEscrow,
|
|
7
|
-
insertRequestLog,
|
|
8
|
-
recordEarning,
|
|
9
4
|
releaseEscrow,
|
|
10
5
|
resolveTargetCapability,
|
|
11
|
-
settleEscrow
|
|
12
|
-
|
|
13
|
-
} from "./chunk-MCED4GDW.js";
|
|
14
|
-
import {
|
|
15
|
-
verifyEscrowReceipt
|
|
16
|
-
} from "./chunk-EJKW57ZV.js";
|
|
6
|
+
settleEscrow
|
|
7
|
+
} from "./chunk-NQANA6WH.js";
|
|
17
8
|
import {
|
|
18
9
|
loadConfig
|
|
19
10
|
} from "./chunk-IVOYM3WG.js";
|
|
11
|
+
import {
|
|
12
|
+
getCard,
|
|
13
|
+
insertRequestLog,
|
|
14
|
+
updateReputation
|
|
15
|
+
} from "./chunk-ZU2TP7CN.js";
|
|
20
16
|
import {
|
|
21
17
|
AgentBnBError
|
|
22
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-I7KWA7OB.js";
|
|
23
19
|
|
|
24
20
|
// src/gateway/execute.ts
|
|
25
21
|
import { randomUUID } from "crypto";
|
|
26
|
-
|
|
27
|
-
// src/credit/settlement.ts
|
|
28
|
-
function settleProviderEarning(providerDb, providerOwner, receipt) {
|
|
29
|
-
const feeAmount = Math.floor(receipt.amount * NETWORK_FEE_RATE);
|
|
30
|
-
const providerAmount = receipt.amount - feeAmount;
|
|
31
|
-
recordEarning(
|
|
32
|
-
providerDb,
|
|
33
|
-
providerOwner,
|
|
34
|
-
providerAmount,
|
|
35
|
-
receipt.card_id,
|
|
36
|
-
receipt.nonce
|
|
37
|
-
);
|
|
38
|
-
return { settled: true };
|
|
39
|
-
}
|
|
40
|
-
function settleRequesterEscrow(requesterDb, escrowId) {
|
|
41
|
-
confirmEscrowDebit(requesterDb, escrowId);
|
|
42
|
-
}
|
|
43
|
-
function releaseRequesterEscrow(requesterDb, escrowId) {
|
|
44
|
-
releaseEscrow(requesterDb, escrowId);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// src/gateway/execute.ts
|
|
48
22
|
async function notifyTelegramSkillExecuted(opts) {
|
|
49
23
|
const cfg = loadConfig();
|
|
50
24
|
if (!cfg?.telegram_notifications) return;
|
|
@@ -123,23 +97,17 @@ async function executeCapabilityRequest(opts) {
|
|
|
123
97
|
cardName = card.name;
|
|
124
98
|
}
|
|
125
99
|
let escrowId = null;
|
|
126
|
-
let isRemoteEscrow = false;
|
|
127
100
|
if (relayAuthorized) {
|
|
128
101
|
} else if (receipt) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
const receiptAge = Date.now() - new Date(receipt.timestamp).getTime();
|
|
139
|
-
if (receiptAge > 5 * 60 * 1e3) {
|
|
140
|
-
return { success: false, error: { code: -32603, message: "Escrow receipt expired" } };
|
|
102
|
+
if (creditsNeeded > 0) {
|
|
103
|
+
return {
|
|
104
|
+
success: false,
|
|
105
|
+
error: {
|
|
106
|
+
code: -32603,
|
|
107
|
+
message: "Direct HTTP paid remote settlement is disabled. Route paid requests through relay."
|
|
108
|
+
}
|
|
109
|
+
};
|
|
141
110
|
}
|
|
142
|
-
isRemoteEscrow = true;
|
|
143
111
|
} else {
|
|
144
112
|
try {
|
|
145
113
|
const balance = getBalance(creditDb, requester);
|
|
@@ -153,9 +121,8 @@ async function executeCapabilityRequest(opts) {
|
|
|
153
121
|
}
|
|
154
122
|
}
|
|
155
123
|
const startMs = Date.now();
|
|
156
|
-
const receiptData = isRemoteEscrow ? { receipt_released: true } : void 0;
|
|
157
124
|
const handleFailure = (status, latencyMs, message, failureReason = "bad_execution") => {
|
|
158
|
-
if (
|
|
125
|
+
if (escrowId) releaseEscrow(creditDb, escrowId);
|
|
159
126
|
if (failureReason === "bad_execution" || failureReason === "auth_error") {
|
|
160
127
|
updateReputation(registryDb, cardId, false, latencyMs);
|
|
161
128
|
}
|
|
@@ -174,15 +141,10 @@ async function executeCapabilityRequest(opts) {
|
|
|
174
141
|
});
|
|
175
142
|
} catch {
|
|
176
143
|
}
|
|
177
|
-
return {
|
|
178
|
-
success: false,
|
|
179
|
-
error: { code: -32603, message, ...receiptData ? { data: receiptData } : {} }
|
|
180
|
-
};
|
|
144
|
+
return { success: false, error: { code: -32603, message } };
|
|
181
145
|
};
|
|
182
146
|
const handleSuccess = (result, latencyMs) => {
|
|
183
|
-
if (
|
|
184
|
-
settleProviderEarning(creditDb, card.owner, receipt);
|
|
185
|
-
} else if (escrowId) {
|
|
147
|
+
if (escrowId) {
|
|
186
148
|
settleEscrow(creditDb, escrowId, card.owner);
|
|
187
149
|
}
|
|
188
150
|
updateReputation(registryDb, cardId, true, latencyMs);
|
|
@@ -210,12 +172,7 @@ async function executeCapabilityRequest(opts) {
|
|
|
210
172
|
latencyMs
|
|
211
173
|
}).catch(() => {
|
|
212
174
|
});
|
|
213
|
-
|
|
214
|
-
...typeof result === "object" && result !== null ? result : { data: result },
|
|
215
|
-
receipt_settled: true,
|
|
216
|
-
receipt_nonce: receipt.nonce
|
|
217
|
-
} : result;
|
|
218
|
-
return { success: true, result: successResult };
|
|
175
|
+
return { success: true, result };
|
|
219
176
|
};
|
|
220
177
|
if (skillExecutor) {
|
|
221
178
|
let targetSkillId = resolvedSkillId ?? skillId;
|
|
@@ -447,8 +404,6 @@ async function executeCapabilityBatch(options) {
|
|
|
447
404
|
}
|
|
448
405
|
|
|
449
406
|
export {
|
|
450
|
-
settleRequesterEscrow,
|
|
451
|
-
releaseRequesterEscrow,
|
|
452
407
|
executeCapabilityRequest,
|
|
453
408
|
executeCapabilityBatch
|
|
454
409
|
};
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentBnBError
|
|
3
|
+
} from "./chunk-I7KWA7OB.js";
|
|
4
|
+
|
|
5
|
+
// src/gateway/client.ts
|
|
6
|
+
import { randomUUID } from "crypto";
|
|
7
|
+
import { Agent } from "undici";
|
|
8
|
+
|
|
9
|
+
// src/credit/signing.ts
|
|
10
|
+
import { generateKeyPairSync, sign, verify, createPublicKey, createPrivateKey } from "crypto";
|
|
11
|
+
import { writeFileSync, readFileSync, existsSync, chmodSync } from "fs";
|
|
12
|
+
import { join } from "path";
|
|
13
|
+
function generateKeyPair() {
|
|
14
|
+
const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
|
|
15
|
+
publicKeyEncoding: { type: "spki", format: "der" },
|
|
16
|
+
privateKeyEncoding: { type: "pkcs8", format: "der" }
|
|
17
|
+
});
|
|
18
|
+
return {
|
|
19
|
+
publicKey: Buffer.from(publicKey),
|
|
20
|
+
privateKey: Buffer.from(privateKey)
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function saveKeyPair(configDir, keys) {
|
|
24
|
+
const privatePath = join(configDir, "private.key");
|
|
25
|
+
const publicPath = join(configDir, "public.key");
|
|
26
|
+
writeFileSync(privatePath, keys.privateKey);
|
|
27
|
+
chmodSync(privatePath, 384);
|
|
28
|
+
writeFileSync(publicPath, keys.publicKey);
|
|
29
|
+
}
|
|
30
|
+
function loadKeyPair(configDir) {
|
|
31
|
+
const privatePath = join(configDir, "private.key");
|
|
32
|
+
const publicPath = join(configDir, "public.key");
|
|
33
|
+
if (!existsSync(privatePath) || !existsSync(publicPath)) {
|
|
34
|
+
throw new AgentBnBError("Keypair not found. Run `agentbnb init` to generate one.", "KEYPAIR_NOT_FOUND");
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
publicKey: readFileSync(publicPath),
|
|
38
|
+
privateKey: readFileSync(privatePath)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function canonicalJson(data) {
|
|
42
|
+
return JSON.stringify(sortForCanonicalJson(data));
|
|
43
|
+
}
|
|
44
|
+
function sortForCanonicalJson(value) {
|
|
45
|
+
if (Array.isArray(value)) {
|
|
46
|
+
return value.map((item) => sortForCanonicalJson(item));
|
|
47
|
+
}
|
|
48
|
+
if (value !== null && typeof value === "object") {
|
|
49
|
+
const proto = Object.getPrototypeOf(value);
|
|
50
|
+
if (proto === Object.prototype || proto === null) {
|
|
51
|
+
const input = value;
|
|
52
|
+
const output = {};
|
|
53
|
+
const sortedKeys = Object.keys(input).sort();
|
|
54
|
+
for (const key of sortedKeys) {
|
|
55
|
+
output[key] = sortForCanonicalJson(input[key]);
|
|
56
|
+
}
|
|
57
|
+
return output;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
function signEscrowReceipt(data, privateKey) {
|
|
63
|
+
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
64
|
+
const keyObject = createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
|
65
|
+
const signature = sign(null, message, keyObject);
|
|
66
|
+
return signature.toString("base64url");
|
|
67
|
+
}
|
|
68
|
+
function verifyEscrowReceipt(data, signature, publicKey) {
|
|
69
|
+
try {
|
|
70
|
+
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
71
|
+
const keyObject = createPublicKey({ key: publicKey, format: "der", type: "spki" });
|
|
72
|
+
const sigBuffer = Buffer.from(signature, "base64url");
|
|
73
|
+
return verify(null, message, keyObject, sigBuffer);
|
|
74
|
+
} catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/gateway/client.ts
|
|
80
|
+
var REQUEST_TIMEOUT_FALLBACK_MS = 3e5;
|
|
81
|
+
var REQUEST_TIMEOUT_GRACE_MS = 3e4;
|
|
82
|
+
var REQUEST_TIMEOUT_EXPECTED_MULTIPLIER = 1.5;
|
|
83
|
+
var gatewayAgent = new Agent({
|
|
84
|
+
keepAliveTimeout: 3e4,
|
|
85
|
+
keepAliveMaxTimeout: 6e4,
|
|
86
|
+
connections: 10,
|
|
87
|
+
pipelining: 1
|
|
88
|
+
});
|
|
89
|
+
function deriveRequestTimeoutMs(hint) {
|
|
90
|
+
const expectedDurationMs = hint?.expected_duration_ms;
|
|
91
|
+
if (typeof expectedDurationMs === "number" && expectedDurationMs > 0) {
|
|
92
|
+
return Math.ceil(expectedDurationMs * REQUEST_TIMEOUT_EXPECTED_MULTIPLIER) + REQUEST_TIMEOUT_GRACE_MS;
|
|
93
|
+
}
|
|
94
|
+
const hardTimeoutMs = hint?.hard_timeout_ms;
|
|
95
|
+
if (typeof hardTimeoutMs === "number" && hardTimeoutMs > 0) {
|
|
96
|
+
return Math.ceil(hardTimeoutMs) + REQUEST_TIMEOUT_GRACE_MS;
|
|
97
|
+
}
|
|
98
|
+
return REQUEST_TIMEOUT_FALLBACK_MS;
|
|
99
|
+
}
|
|
100
|
+
function buildGatewayAuthHeaders(payload, token, identity) {
|
|
101
|
+
const headers = { "Content-Type": "application/json" };
|
|
102
|
+
if (identity) {
|
|
103
|
+
const signature = signEscrowReceipt(payload, identity.privateKey);
|
|
104
|
+
headers["X-Agent-Id"] = identity.agentId;
|
|
105
|
+
headers["X-Agent-Public-Key"] = identity.publicKey;
|
|
106
|
+
headers["X-Agent-Signature"] = signature;
|
|
107
|
+
}
|
|
108
|
+
if (token) {
|
|
109
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
110
|
+
}
|
|
111
|
+
return headers;
|
|
112
|
+
}
|
|
113
|
+
async function requestCapability(opts) {
|
|
114
|
+
const {
|
|
115
|
+
gatewayUrl,
|
|
116
|
+
token,
|
|
117
|
+
cardId,
|
|
118
|
+
params = {},
|
|
119
|
+
timeoutMs: timeoutOverrideMs,
|
|
120
|
+
timeoutHint,
|
|
121
|
+
escrowReceipt,
|
|
122
|
+
identity
|
|
123
|
+
} = opts;
|
|
124
|
+
const timeoutMs = timeoutOverrideMs ?? deriveRequestTimeoutMs(timeoutHint);
|
|
125
|
+
const id = randomUUID();
|
|
126
|
+
const payload = {
|
|
127
|
+
jsonrpc: "2.0",
|
|
128
|
+
id,
|
|
129
|
+
method: "capability.execute",
|
|
130
|
+
params: {
|
|
131
|
+
card_id: cardId,
|
|
132
|
+
...params,
|
|
133
|
+
...escrowReceipt ? { escrow_receipt: escrowReceipt } : {}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const headers = buildGatewayAuthHeaders(payload, token, identity);
|
|
137
|
+
const controller = new AbortController();
|
|
138
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
139
|
+
let response;
|
|
140
|
+
try {
|
|
141
|
+
response = await fetch(`${gatewayUrl}/rpc`, {
|
|
142
|
+
method: "POST",
|
|
143
|
+
headers,
|
|
144
|
+
body: JSON.stringify(payload),
|
|
145
|
+
signal: controller.signal,
|
|
146
|
+
// undici dispatcher for connection pooling (Node.js 20+)
|
|
147
|
+
dispatcher: gatewayAgent
|
|
148
|
+
});
|
|
149
|
+
} catch (err) {
|
|
150
|
+
clearTimeout(timer);
|
|
151
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
152
|
+
throw new AgentBnBError(
|
|
153
|
+
isTimeout ? "Request timed out" : `Network error: ${String(err)}`,
|
|
154
|
+
isTimeout ? "TIMEOUT" : "NETWORK_ERROR"
|
|
155
|
+
);
|
|
156
|
+
} finally {
|
|
157
|
+
clearTimeout(timer);
|
|
158
|
+
}
|
|
159
|
+
const body = await response.json();
|
|
160
|
+
if (body.error) {
|
|
161
|
+
throw new AgentBnBError(body.error.message, `RPC_ERROR_${body.error.code}`);
|
|
162
|
+
}
|
|
163
|
+
return body.result;
|
|
164
|
+
}
|
|
165
|
+
async function requestCapabilityBatch(gatewayUrl, token, items, opts = {}) {
|
|
166
|
+
if (items.length === 0) return /* @__PURE__ */ new Map();
|
|
167
|
+
if (items.length === 1) {
|
|
168
|
+
const item = items[0];
|
|
169
|
+
const result = await requestCapability({
|
|
170
|
+
gatewayUrl,
|
|
171
|
+
token,
|
|
172
|
+
cardId: item.cardId,
|
|
173
|
+
params: item.params,
|
|
174
|
+
escrowReceipt: item.escrowReceipt,
|
|
175
|
+
timeoutMs: opts.timeoutMs,
|
|
176
|
+
timeoutHint: opts.timeoutHint,
|
|
177
|
+
identity: opts.identity
|
|
178
|
+
});
|
|
179
|
+
return /* @__PURE__ */ new Map([[item.id, result]]);
|
|
180
|
+
}
|
|
181
|
+
const { timeoutMs: timeoutOverrideMs, timeoutHint, identity } = opts;
|
|
182
|
+
const timeoutMs = timeoutOverrideMs ?? deriveRequestTimeoutMs(timeoutHint);
|
|
183
|
+
const batchPayload = items.map((item) => ({
|
|
184
|
+
jsonrpc: "2.0",
|
|
185
|
+
id: item.id,
|
|
186
|
+
method: "capability.execute",
|
|
187
|
+
params: {
|
|
188
|
+
card_id: item.cardId,
|
|
189
|
+
...item.params,
|
|
190
|
+
...item.escrowReceipt ? { escrow_receipt: item.escrowReceipt } : {}
|
|
191
|
+
}
|
|
192
|
+
}));
|
|
193
|
+
const headers = buildGatewayAuthHeaders(batchPayload, token, identity);
|
|
194
|
+
const controller = new AbortController();
|
|
195
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
196
|
+
let response;
|
|
197
|
+
try {
|
|
198
|
+
response = await fetch(`${gatewayUrl}/rpc`, {
|
|
199
|
+
method: "POST",
|
|
200
|
+
headers,
|
|
201
|
+
body: JSON.stringify(batchPayload),
|
|
202
|
+
signal: controller.signal,
|
|
203
|
+
dispatcher: gatewayAgent
|
|
204
|
+
});
|
|
205
|
+
} catch (err) {
|
|
206
|
+
clearTimeout(timer);
|
|
207
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
208
|
+
throw new AgentBnBError(
|
|
209
|
+
isTimeout ? "Batch request timed out" : `Network error: ${String(err)}`,
|
|
210
|
+
isTimeout ? "TIMEOUT" : "NETWORK_ERROR"
|
|
211
|
+
);
|
|
212
|
+
} finally {
|
|
213
|
+
clearTimeout(timer);
|
|
214
|
+
}
|
|
215
|
+
const body = await response.json();
|
|
216
|
+
const results = /* @__PURE__ */ new Map();
|
|
217
|
+
for (const resp of body) {
|
|
218
|
+
if (resp.error) {
|
|
219
|
+
results.set(resp.id, new AgentBnBError(resp.error.message, `RPC_ERROR_${resp.error.code}`));
|
|
220
|
+
} else {
|
|
221
|
+
results.set(resp.id, resp.result);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return results;
|
|
225
|
+
}
|
|
226
|
+
async function requestViaRelay(relay, opts) {
|
|
227
|
+
const timeoutMs = opts.timeoutMs ?? deriveRequestTimeoutMs(opts.timeoutHint);
|
|
228
|
+
try {
|
|
229
|
+
return await relay.request({
|
|
230
|
+
targetOwner: opts.targetOwner,
|
|
231
|
+
targetAgentId: opts.targetAgentId,
|
|
232
|
+
cardId: opts.cardId,
|
|
233
|
+
skillId: opts.skillId,
|
|
234
|
+
params: opts.params ?? {},
|
|
235
|
+
requester: opts.requester,
|
|
236
|
+
escrowReceipt: opts.escrowReceipt,
|
|
237
|
+
timeoutMs
|
|
238
|
+
});
|
|
239
|
+
} catch (err) {
|
|
240
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
241
|
+
if (message.includes("timeout")) {
|
|
242
|
+
throw new AgentBnBError(message, "TIMEOUT");
|
|
243
|
+
}
|
|
244
|
+
if (message.includes("offline")) {
|
|
245
|
+
throw new AgentBnBError(message, "AGENT_OFFLINE");
|
|
246
|
+
}
|
|
247
|
+
throw new AgentBnBError(message, "RELAY_ERROR");
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export {
|
|
252
|
+
generateKeyPair,
|
|
253
|
+
saveKeyPair,
|
|
254
|
+
loadKeyPair,
|
|
255
|
+
signEscrowReceipt,
|
|
256
|
+
verifyEscrowReceipt,
|
|
257
|
+
REQUEST_TIMEOUT_FALLBACK_MS,
|
|
258
|
+
REQUEST_TIMEOUT_GRACE_MS,
|
|
259
|
+
REQUEST_TIMEOUT_EXPECTED_MULTIPLIER,
|
|
260
|
+
deriveRequestTimeoutMs,
|
|
261
|
+
requestCapability,
|
|
262
|
+
requestCapabilityBatch,
|
|
263
|
+
requestViaRelay
|
|
264
|
+
};
|