agentbnb 8.2.0 → 8.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-TBJ3FZKZ.js → chunk-7Q2XUXSA.js} +1 -1
- package/dist/{chunk-LJM7FHPM.js → chunk-BZOJ7HBT.js} +33 -1
- package/dist/{chunk-FTZTEHYG.js → chunk-DEWY7OQK.js} +135 -8
- package/dist/{chunk-CUONY5TO.js → chunk-EJKW57ZV.js} +19 -1
- package/dist/chunk-EZVOG7QS.js +161 -0
- package/dist/{chunk-E2OKP5CY.js → chunk-GJETGML6.js} +181 -83
- package/dist/{chunk-YHY7OG6S.js → chunk-GWMMYVLL.js} +4 -4
- package/dist/{chunk-D6RKW2XG.js → chunk-JLNHMNES.js} +16 -3
- package/dist/{chunk-5AAFG2V2.js → chunk-KBQNTUTN.js} +239 -24
- package/dist/{chunk-C537SFHV.js → chunk-LOUEJI6X.js} +4 -4
- package/dist/{chunk-ALX4WS3A.js → chunk-NP55V7RQ.js} +1 -1
- package/dist/{chunk-X32NE6V4.js → chunk-RBXTWWUH.js} +1 -1
- package/dist/{chunk-O2OYBAVR.js → chunk-SRBVKO2V.js} +9 -0
- package/dist/{chunk-7EF3HYVZ.js → chunk-STJLWMXH.js} +48 -4
- package/dist/{chunk-5GME4KJZ.js → chunk-UYCD3JBZ.js} +3 -3
- package/dist/{chunk-P4LOYSLA.js → chunk-WKWJWKX7.js} +286 -81
- package/dist/cli/index.js +35 -57
- package/dist/{client-HKV3QWZ3.js → client-66TFS7RS.js} +4 -2
- package/dist/{conduct-W6XF6DJW.js → conduct-A6COHLHY.js} +8 -8
- package/dist/{conduct-YB64OHI6.js → conduct-IUVAXUAV.js} +8 -8
- package/dist/{conductor-mode-TFCVCQHU.js → conductor-mode-D5TFQW5L.js} +2 -2
- package/dist/{conductor-mode-AKREGDIU.js → conductor-mode-L2MB44BW.js} +7 -7
- package/dist/{execute-AYQWORVH.js → execute-5AWLARB5.js} +5 -5
- package/dist/{execute-EPE6MZLT.js → execute-WOS457HW.js} +2 -2
- package/dist/index.js +438 -92
- package/dist/{publish-capability-AH2HDW54.js → publish-capability-JJCBBMSX.js} +2 -2
- package/dist/{request-HCCXSKAY.js → request-6YQLA7K3.js} +13 -8
- package/dist/{serve-skill-SZAQT5T5.js → serve-skill-X7TZSILV.js} +5 -5
- package/dist/{server-LMY2A3GT.js → server-5TSP4DBX.js} +10 -12
- package/dist/{service-coordinator-WGH6B2VT.js → service-coordinator-WTUSMPY6.js} +69 -46
- package/dist/skills/agentbnb/bootstrap.js +459 -189
- package/package.json +13 -17
- package/skills/agentbnb/bootstrap.test.ts +8 -6
- package/skills/agentbnb/bootstrap.ts +21 -13
- package/skills/agentbnb/install.sh +0 -0
- package/dist/chunk-64AK4FJM.js +0 -84
- package/dist/chunk-OH7BP5NP.js +0 -96
- package/dist/index.d.ts +0 -5069
package/dist/index.js
CHANGED
|
@@ -534,6 +534,15 @@ function openDatabase(path = ":memory:") {
|
|
|
534
534
|
tags,
|
|
535
535
|
content=""
|
|
536
536
|
);
|
|
537
|
+
|
|
538
|
+
-- Expression index for capability_type lookups (used by Conductor routing).
|
|
539
|
+
-- Turns json_extract full-table-scan into O(log n) B-tree lookup.
|
|
540
|
+
CREATE INDEX IF NOT EXISTS idx_cards_capability_type
|
|
541
|
+
ON capability_cards(json_extract(data, '$.capability_type'));
|
|
542
|
+
|
|
543
|
+
-- Owner index for listCards(owner) and other owner-scoped queries.
|
|
544
|
+
CREATE INDEX IF NOT EXISTS idx_cards_owner
|
|
545
|
+
ON capability_cards(owner);
|
|
537
546
|
`);
|
|
538
547
|
createRequestLogTable(db);
|
|
539
548
|
initFeedbackTable(db);
|
|
@@ -753,7 +762,37 @@ function getReputationScore(db, agentId) {
|
|
|
753
762
|
}
|
|
754
763
|
|
|
755
764
|
// src/registry/matcher.ts
|
|
765
|
+
var CACHE_MAX_ENTRIES = 100;
|
|
766
|
+
var CACHE_TTL_MS = 3e4;
|
|
767
|
+
var dbCaches = /* @__PURE__ */ new WeakMap();
|
|
768
|
+
function getDbCache(db) {
|
|
769
|
+
let cache = dbCaches.get(db);
|
|
770
|
+
if (!cache) {
|
|
771
|
+
cache = /* @__PURE__ */ new Map();
|
|
772
|
+
dbCaches.set(db, cache);
|
|
773
|
+
}
|
|
774
|
+
return cache;
|
|
775
|
+
}
|
|
776
|
+
function cacheKey(query, filters) {
|
|
777
|
+
return `${query}|${filters.level ?? ""}|${filters.online ?? ""}|${(filters.apis_used ?? []).join(",")}|${filters.min_reputation ?? ""}`;
|
|
778
|
+
}
|
|
779
|
+
function evictCache(cache) {
|
|
780
|
+
const now = Date.now();
|
|
781
|
+
for (const [key, entry] of cache) {
|
|
782
|
+
if (entry.expiresAt <= now) cache.delete(key);
|
|
783
|
+
}
|
|
784
|
+
while (cache.size > CACHE_MAX_ENTRIES) {
|
|
785
|
+
const firstKey = cache.keys().next().value;
|
|
786
|
+
cache.delete(firstKey);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
756
789
|
function searchCards(db, query, filters = {}) {
|
|
790
|
+
const cache = getDbCache(db);
|
|
791
|
+
const key = cacheKey(query, filters);
|
|
792
|
+
const cached = cache.get(key);
|
|
793
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
794
|
+
return cached.results;
|
|
795
|
+
}
|
|
757
796
|
const words = query.trim().split(/\s+/).map((w) => w.replace(/["*^{}():]/g, "")).filter((w) => w.length > 0);
|
|
758
797
|
if (words.length === 0) return [];
|
|
759
798
|
const ftsQuery = words.map((w) => `"${w}"`).join(" OR ");
|
|
@@ -791,6 +830,8 @@ function searchCards(db, query, filters = {}) {
|
|
|
791
830
|
if (filters.min_reputation !== void 0 && filters.min_reputation > 0) {
|
|
792
831
|
filtered = applyReputationFilter(db, filtered, filters.min_reputation);
|
|
793
832
|
}
|
|
833
|
+
evictCache(cache);
|
|
834
|
+
cache.set(key, { results: filtered, expiresAt: Date.now() + CACHE_TTL_MS });
|
|
794
835
|
return filtered;
|
|
795
836
|
}
|
|
796
837
|
function applyReputationFilter(db, cards, minReputation) {
|
|
@@ -1178,7 +1219,25 @@ function loadKeyPair(configDir) {
|
|
|
1178
1219
|
};
|
|
1179
1220
|
}
|
|
1180
1221
|
function canonicalJson(data) {
|
|
1181
|
-
return JSON.stringify(
|
|
1222
|
+
return JSON.stringify(sortForCanonicalJson(data));
|
|
1223
|
+
}
|
|
1224
|
+
function sortForCanonicalJson(value) {
|
|
1225
|
+
if (Array.isArray(value)) {
|
|
1226
|
+
return value.map((item) => sortForCanonicalJson(item));
|
|
1227
|
+
}
|
|
1228
|
+
if (value !== null && typeof value === "object") {
|
|
1229
|
+
const proto = Object.getPrototypeOf(value);
|
|
1230
|
+
if (proto === Object.prototype || proto === null) {
|
|
1231
|
+
const input = value;
|
|
1232
|
+
const output = {};
|
|
1233
|
+
const sortedKeys = Object.keys(input).sort();
|
|
1234
|
+
for (const key of sortedKeys) {
|
|
1235
|
+
output[key] = sortForCanonicalJson(input[key]);
|
|
1236
|
+
}
|
|
1237
|
+
return output;
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
return value;
|
|
1182
1241
|
}
|
|
1183
1242
|
function signEscrowReceipt(data, privateKey) {
|
|
1184
1243
|
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
@@ -1520,7 +1579,54 @@ function createGatewayServer(opts) {
|
|
|
1520
1579
|
return { status: "ok", version: VERSION, uptime: process.uptime() };
|
|
1521
1580
|
});
|
|
1522
1581
|
fastify.post("/rpc", async (request, reply) => {
|
|
1523
|
-
const
|
|
1582
|
+
const rawBody = request.body;
|
|
1583
|
+
if (Array.isArray(rawBody)) {
|
|
1584
|
+
const responses = await Promise.all(
|
|
1585
|
+
rawBody.map(async (single) => {
|
|
1586
|
+
if (single.jsonrpc !== "2.0" || !single.method) {
|
|
1587
|
+
return { jsonrpc: "2.0", id: single.id ?? null, error: { code: -32600, message: "Invalid Request" } };
|
|
1588
|
+
}
|
|
1589
|
+
if (single.method !== "capability.execute") {
|
|
1590
|
+
return { jsonrpc: "2.0", id: single.id ?? null, error: { code: -32601, message: "Method not found" } };
|
|
1591
|
+
}
|
|
1592
|
+
const params2 = single.params ?? {};
|
|
1593
|
+
const cardId2 = params2.card_id;
|
|
1594
|
+
if (!cardId2) {
|
|
1595
|
+
return { jsonrpc: "2.0", id: single.id ?? null, error: { code: -32602, message: "Invalid params: card_id required" } };
|
|
1596
|
+
}
|
|
1597
|
+
const requester2 = params2.requester ?? "unknown";
|
|
1598
|
+
const receipt2 = params2.escrow_receipt;
|
|
1599
|
+
const batchSkillId = params2.skill_id;
|
|
1600
|
+
const trackKey2 = batchSkillId ?? cardId2;
|
|
1601
|
+
inFlight.set(trackKey2, (inFlight.get(trackKey2) ?? 0) + 1);
|
|
1602
|
+
try {
|
|
1603
|
+
const result2 = await executeCapabilityRequest({
|
|
1604
|
+
registryDb,
|
|
1605
|
+
creditDb,
|
|
1606
|
+
cardId: cardId2,
|
|
1607
|
+
skillId: batchSkillId,
|
|
1608
|
+
params: params2,
|
|
1609
|
+
requester: requester2,
|
|
1610
|
+
escrowReceipt: receipt2,
|
|
1611
|
+
skillExecutor,
|
|
1612
|
+
handlerUrl,
|
|
1613
|
+
timeoutMs
|
|
1614
|
+
});
|
|
1615
|
+
if (result2.success) {
|
|
1616
|
+
return { jsonrpc: "2.0", id: single.id ?? null, result: result2.result };
|
|
1617
|
+
} else {
|
|
1618
|
+
return { jsonrpc: "2.0", id: single.id ?? null, error: result2.error };
|
|
1619
|
+
}
|
|
1620
|
+
} finally {
|
|
1621
|
+
const next = (inFlight.get(trackKey2) ?? 1) - 1;
|
|
1622
|
+
if (next <= 0) inFlight.delete(trackKey2);
|
|
1623
|
+
else inFlight.set(trackKey2, next);
|
|
1624
|
+
}
|
|
1625
|
+
})
|
|
1626
|
+
);
|
|
1627
|
+
return reply.send(responses);
|
|
1628
|
+
}
|
|
1629
|
+
const body = rawBody;
|
|
1524
1630
|
if (body.jsonrpc !== "2.0" || !body.method) {
|
|
1525
1631
|
return reply.status(400).send({
|
|
1526
1632
|
jsonrpc: "2.0",
|
|
@@ -2841,6 +2947,13 @@ function decompose(task, _availableCapabilities) {
|
|
|
2841
2947
|
|
|
2842
2948
|
// src/gateway/client.ts
|
|
2843
2949
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
2950
|
+
import { Agent } from "undici";
|
|
2951
|
+
var gatewayAgent = new Agent({
|
|
2952
|
+
keepAliveTimeout: 3e4,
|
|
2953
|
+
keepAliveMaxTimeout: 6e4,
|
|
2954
|
+
connections: 10,
|
|
2955
|
+
pipelining: 1
|
|
2956
|
+
});
|
|
2844
2957
|
async function requestCapability(opts) {
|
|
2845
2958
|
const { gatewayUrl, token, cardId, params = {}, timeoutMs = 3e5, escrowReceipt, identity } = opts;
|
|
2846
2959
|
const id = randomUUID8();
|
|
@@ -2871,7 +2984,9 @@ async function requestCapability(opts) {
|
|
|
2871
2984
|
method: "POST",
|
|
2872
2985
|
headers,
|
|
2873
2986
|
body: JSON.stringify(payload),
|
|
2874
|
-
signal: controller.signal
|
|
2987
|
+
signal: controller.signal,
|
|
2988
|
+
// undici dispatcher for connection pooling (Node.js 20+)
|
|
2989
|
+
dispatcher: gatewayAgent
|
|
2875
2990
|
});
|
|
2876
2991
|
} catch (err) {
|
|
2877
2992
|
clearTimeout(timer);
|
|
@@ -2889,6 +3004,73 @@ async function requestCapability(opts) {
|
|
|
2889
3004
|
}
|
|
2890
3005
|
return body.result;
|
|
2891
3006
|
}
|
|
3007
|
+
async function requestCapabilityBatch(gatewayUrl, token, items, opts = {}) {
|
|
3008
|
+
if (items.length === 0) return /* @__PURE__ */ new Map();
|
|
3009
|
+
if (items.length === 1) {
|
|
3010
|
+
const item = items[0];
|
|
3011
|
+
const result = await requestCapability({
|
|
3012
|
+
gatewayUrl,
|
|
3013
|
+
token,
|
|
3014
|
+
cardId: item.cardId,
|
|
3015
|
+
params: item.params,
|
|
3016
|
+
escrowReceipt: item.escrowReceipt,
|
|
3017
|
+
timeoutMs: opts.timeoutMs,
|
|
3018
|
+
identity: opts.identity
|
|
3019
|
+
});
|
|
3020
|
+
return /* @__PURE__ */ new Map([[item.id, result]]);
|
|
3021
|
+
}
|
|
3022
|
+
const { timeoutMs = 3e5, identity } = opts;
|
|
3023
|
+
const batchPayload = items.map((item) => ({
|
|
3024
|
+
jsonrpc: "2.0",
|
|
3025
|
+
id: item.id,
|
|
3026
|
+
method: "capability.execute",
|
|
3027
|
+
params: {
|
|
3028
|
+
card_id: item.cardId,
|
|
3029
|
+
...item.params,
|
|
3030
|
+
...item.escrowReceipt ? { escrow_receipt: item.escrowReceipt } : {}
|
|
3031
|
+
}
|
|
3032
|
+
}));
|
|
3033
|
+
const headers = { "Content-Type": "application/json" };
|
|
3034
|
+
if (identity) {
|
|
3035
|
+
const signature = signEscrowReceipt(batchPayload, identity.privateKey);
|
|
3036
|
+
headers["X-Agent-Id"] = identity.agentId;
|
|
3037
|
+
headers["X-Agent-Public-Key"] = identity.publicKey;
|
|
3038
|
+
headers["X-Agent-Signature"] = signature;
|
|
3039
|
+
} else if (token) {
|
|
3040
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
3041
|
+
}
|
|
3042
|
+
const controller = new AbortController();
|
|
3043
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
3044
|
+
let response;
|
|
3045
|
+
try {
|
|
3046
|
+
response = await fetch(`${gatewayUrl}/rpc`, {
|
|
3047
|
+
method: "POST",
|
|
3048
|
+
headers,
|
|
3049
|
+
body: JSON.stringify(batchPayload),
|
|
3050
|
+
signal: controller.signal,
|
|
3051
|
+
dispatcher: gatewayAgent
|
|
3052
|
+
});
|
|
3053
|
+
} catch (err) {
|
|
3054
|
+
clearTimeout(timer);
|
|
3055
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
3056
|
+
throw new AgentBnBError(
|
|
3057
|
+
isTimeout ? "Batch request timed out" : `Network error: ${String(err)}`,
|
|
3058
|
+
isTimeout ? "TIMEOUT" : "NETWORK_ERROR"
|
|
3059
|
+
);
|
|
3060
|
+
} finally {
|
|
3061
|
+
clearTimeout(timer);
|
|
3062
|
+
}
|
|
3063
|
+
const body = await response.json();
|
|
3064
|
+
const results = /* @__PURE__ */ new Map();
|
|
3065
|
+
for (const resp of body) {
|
|
3066
|
+
if (resp.error) {
|
|
3067
|
+
results.set(resp.id, new AgentBnBError(resp.error.message, `RPC_ERROR_${resp.error.code}`));
|
|
3068
|
+
} else {
|
|
3069
|
+
results.set(resp.id, resp.result);
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
return results;
|
|
3073
|
+
}
|
|
2892
3074
|
async function requestViaRelay(relay, opts) {
|
|
2893
3075
|
try {
|
|
2894
3076
|
return await relay.request({
|
|
@@ -3265,6 +3447,65 @@ function computeWaves(subtasks) {
|
|
|
3265
3447
|
}
|
|
3266
3448
|
return waves;
|
|
3267
3449
|
}
|
|
3450
|
+
async function executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl) {
|
|
3451
|
+
const { taskId, match: m, interpolatedParams, primary, teamId, capabilityType } = pt;
|
|
3452
|
+
try {
|
|
3453
|
+
let res;
|
|
3454
|
+
if (primary.url.startsWith("relay://") && relayClient) {
|
|
3455
|
+
const targetOwner = primary.url.replace("relay://", "");
|
|
3456
|
+
res = await relayClient.request({
|
|
3457
|
+
targetOwner,
|
|
3458
|
+
cardId: primary.cardId,
|
|
3459
|
+
params: interpolatedParams,
|
|
3460
|
+
requester: requesterOwner,
|
|
3461
|
+
timeoutMs
|
|
3462
|
+
});
|
|
3463
|
+
} else {
|
|
3464
|
+
res = await requestCapability({
|
|
3465
|
+
gatewayUrl: primary.url,
|
|
3466
|
+
token: gatewayToken,
|
|
3467
|
+
cardId: primary.cardId,
|
|
3468
|
+
params: { ...interpolatedParams, requester: requesterOwner },
|
|
3469
|
+
timeoutMs
|
|
3470
|
+
});
|
|
3471
|
+
}
|
|
3472
|
+
return { taskId, result: res, credits: m.credits, team_id: teamId, capability_type: capabilityType };
|
|
3473
|
+
} catch (primaryErr) {
|
|
3474
|
+
if (m.alternatives.length > 0) {
|
|
3475
|
+
const alt = m.alternatives[0];
|
|
3476
|
+
const altResolved = resolveAgentUrl ? resolveAgentUrl(alt.agent) : { url: `http://${alt.agent}:7700`, cardId: `card-${alt.agent}` };
|
|
3477
|
+
try {
|
|
3478
|
+
let altRes;
|
|
3479
|
+
if (altResolved.url.startsWith("relay://") && relayClient) {
|
|
3480
|
+
const targetOwner = altResolved.url.replace("relay://", "");
|
|
3481
|
+
altRes = await relayClient.request({
|
|
3482
|
+
targetOwner,
|
|
3483
|
+
cardId: altResolved.cardId,
|
|
3484
|
+
params: interpolatedParams,
|
|
3485
|
+
requester: requesterOwner,
|
|
3486
|
+
timeoutMs
|
|
3487
|
+
});
|
|
3488
|
+
} else {
|
|
3489
|
+
altRes = await requestCapability({
|
|
3490
|
+
gatewayUrl: altResolved.url,
|
|
3491
|
+
token: gatewayToken,
|
|
3492
|
+
cardId: altResolved.cardId,
|
|
3493
|
+
params: { ...interpolatedParams, requester: requesterOwner },
|
|
3494
|
+
timeoutMs
|
|
3495
|
+
});
|
|
3496
|
+
}
|
|
3497
|
+
return { taskId, result: altRes, credits: alt.credits, team_id: teamId, capability_type: capabilityType };
|
|
3498
|
+
} catch (altErr) {
|
|
3499
|
+
throw new Error(
|
|
3500
|
+
`Task ${taskId}: primary (${m.selected_agent}) failed: ${primaryErr instanceof Error ? primaryErr.message : String(primaryErr)}; alternative (${alt.agent}) failed: ${altErr instanceof Error ? altErr.message : String(altErr)}`
|
|
3501
|
+
);
|
|
3502
|
+
}
|
|
3503
|
+
}
|
|
3504
|
+
throw new Error(
|
|
3505
|
+
`Task ${taskId}: ${primaryErr instanceof Error ? primaryErr.message : String(primaryErr)}`
|
|
3506
|
+
);
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3268
3509
|
async function orchestrate(opts) {
|
|
3269
3510
|
const { subtasks, matches, gatewayToken, resolveAgentUrl, timeoutMs = 3e5, maxBudget, relayClient, requesterOwner } = opts;
|
|
3270
3511
|
const startTime = Date.now();
|
|
@@ -3302,89 +3543,127 @@ async function orchestrate(opts) {
|
|
|
3302
3543
|
}
|
|
3303
3544
|
executableIds.push(taskId);
|
|
3304
3545
|
}
|
|
3305
|
-
const
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
const
|
|
3546
|
+
const preparedTasks = [];
|
|
3547
|
+
for (const taskId of executableIds) {
|
|
3548
|
+
const subtask = subtaskMap.get(taskId);
|
|
3549
|
+
const m = matches.get(taskId);
|
|
3550
|
+
if (!m) {
|
|
3551
|
+
errors.push(`No match found for subtask ${taskId}`);
|
|
3552
|
+
continue;
|
|
3553
|
+
}
|
|
3554
|
+
const stepsContext = {};
|
|
3555
|
+
for (const [id, val] of results) stepsContext[id] = val;
|
|
3556
|
+
const interpContext = { steps: stepsContext, prev: void 0 };
|
|
3557
|
+
if (subtask.depends_on.length > 0) {
|
|
3558
|
+
const lastDep = subtask.depends_on[subtask.depends_on.length - 1];
|
|
3559
|
+
interpContext.prev = results.get(lastDep);
|
|
3560
|
+
}
|
|
3561
|
+
const interpolatedParams = interpolateObject(
|
|
3562
|
+
subtask.params,
|
|
3563
|
+
interpContext
|
|
3564
|
+
);
|
|
3565
|
+
const teamMember = teamMemberMap.get(taskId);
|
|
3566
|
+
const agentOwner = teamMember?.agent ?? m.selected_agent;
|
|
3567
|
+
const primary = resolveAgentUrl(agentOwner);
|
|
3568
|
+
preparedTasks.push({
|
|
3569
|
+
taskId,
|
|
3570
|
+
subtask,
|
|
3571
|
+
match: m,
|
|
3572
|
+
interpolatedParams,
|
|
3573
|
+
agentOwner,
|
|
3574
|
+
primary,
|
|
3575
|
+
teamId: opts.team?.team_id ?? null,
|
|
3576
|
+
capabilityType: teamMember?.capability_type ?? null
|
|
3577
|
+
});
|
|
3578
|
+
}
|
|
3579
|
+
const httpGroups = /* @__PURE__ */ new Map();
|
|
3580
|
+
const relayTasks = [];
|
|
3581
|
+
for (const pt of preparedTasks) {
|
|
3582
|
+
if (pt.primary.url.startsWith("relay://") && relayClient) {
|
|
3583
|
+
relayTasks.push(pt);
|
|
3584
|
+
} else {
|
|
3585
|
+
const group = httpGroups.get(pt.primary.url) ?? [];
|
|
3586
|
+
group.push(pt);
|
|
3587
|
+
httpGroups.set(pt.primary.url, group);
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3590
|
+
const batchPromises = [];
|
|
3591
|
+
for (const [gatewayUrl, group] of httpGroups) {
|
|
3592
|
+
if (group.length >= 2) {
|
|
3593
|
+
batchPromises.push(
|
|
3594
|
+
(async () => {
|
|
3595
|
+
const items = group.map((pt) => ({
|
|
3596
|
+
id: pt.taskId,
|
|
3597
|
+
cardId: pt.primary.cardId,
|
|
3598
|
+
params: { ...pt.interpolatedParams, requester: requesterOwner },
|
|
3599
|
+
_pt: pt
|
|
3600
|
+
}));
|
|
3355
3601
|
try {
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
cardId: altAgent.cardId,
|
|
3362
|
-
params: interpolatedParams,
|
|
3363
|
-
requester: requesterOwner,
|
|
3364
|
-
timeoutMs
|
|
3365
|
-
});
|
|
3366
|
-
} else {
|
|
3367
|
-
altRes = await requestCapability({
|
|
3368
|
-
gatewayUrl: altAgent.url,
|
|
3369
|
-
token: gatewayToken,
|
|
3370
|
-
cardId: altAgent.cardId,
|
|
3371
|
-
params: { ...interpolatedParams, requester: requesterOwner },
|
|
3372
|
-
timeoutMs
|
|
3373
|
-
});
|
|
3374
|
-
}
|
|
3375
|
-
return { taskId, result: altRes, credits: alt.credits, team_id: teamId, capability_type: taskCapabilityType };
|
|
3376
|
-
} catch (altErr) {
|
|
3377
|
-
throw new Error(
|
|
3378
|
-
`Task ${taskId}: primary (${m.selected_agent}) failed: ${primaryErr instanceof Error ? primaryErr.message : String(primaryErr)}; alternative (${alt.agent}) failed: ${altErr instanceof Error ? altErr.message : String(altErr)}`
|
|
3602
|
+
const batchResults = await requestCapabilityBatch(
|
|
3603
|
+
gatewayUrl,
|
|
3604
|
+
gatewayToken,
|
|
3605
|
+
items.map(({ _pt, ...item }) => item),
|
|
3606
|
+
{ timeoutMs }
|
|
3379
3607
|
);
|
|
3608
|
+
return items.map((item) => {
|
|
3609
|
+
const res = batchResults.get(item.id);
|
|
3610
|
+
if (res instanceof Error) {
|
|
3611
|
+
return {
|
|
3612
|
+
status: "rejected",
|
|
3613
|
+
reason: new Error(`Task ${item.id}: ${res.message}`)
|
|
3614
|
+
};
|
|
3615
|
+
}
|
|
3616
|
+
return {
|
|
3617
|
+
status: "fulfilled",
|
|
3618
|
+
value: {
|
|
3619
|
+
taskId: item.id,
|
|
3620
|
+
result: res,
|
|
3621
|
+
credits: item._pt.match.credits,
|
|
3622
|
+
team_id: item._pt.teamId,
|
|
3623
|
+
capability_type: item._pt.capabilityType
|
|
3624
|
+
}
|
|
3625
|
+
};
|
|
3626
|
+
});
|
|
3627
|
+
} catch (batchErr) {
|
|
3628
|
+
return Promise.all(group.map(async (pt) => {
|
|
3629
|
+
try {
|
|
3630
|
+
const res = await executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl);
|
|
3631
|
+
return { status: "fulfilled", value: res };
|
|
3632
|
+
} catch (err) {
|
|
3633
|
+
return { status: "rejected", reason: err };
|
|
3634
|
+
}
|
|
3635
|
+
}));
|
|
3636
|
+
}
|
|
3637
|
+
})()
|
|
3638
|
+
);
|
|
3639
|
+
} else {
|
|
3640
|
+
const pt = group[0];
|
|
3641
|
+
batchPromises.push(
|
|
3642
|
+
(async () => {
|
|
3643
|
+
try {
|
|
3644
|
+
const res = await executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl);
|
|
3645
|
+
return [{ status: "fulfilled", value: res }];
|
|
3646
|
+
} catch (err) {
|
|
3647
|
+
return [{ status: "rejected", reason: err }];
|
|
3380
3648
|
}
|
|
3649
|
+
})()
|
|
3650
|
+
);
|
|
3651
|
+
}
|
|
3652
|
+
}
|
|
3653
|
+
for (const pt of relayTasks) {
|
|
3654
|
+
batchPromises.push(
|
|
3655
|
+
(async () => {
|
|
3656
|
+
try {
|
|
3657
|
+
const res = await executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl);
|
|
3658
|
+
return [{ status: "fulfilled", value: res }];
|
|
3659
|
+
} catch (err) {
|
|
3660
|
+
return [{ status: "rejected", reason: err }];
|
|
3381
3661
|
}
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
);
|
|
3662
|
+
})()
|
|
3663
|
+
);
|
|
3664
|
+
}
|
|
3665
|
+
const allBatchResults = await Promise.all(batchPromises);
|
|
3666
|
+
const waveResults = allBatchResults.flat();
|
|
3388
3667
|
for (const settlement of waveResults) {
|
|
3389
3668
|
if (settlement.status === "fulfilled") {
|
|
3390
3669
|
const { taskId, result, credits, team_id, capability_type } = settlement.value;
|
|
@@ -3733,7 +4012,7 @@ function createSignedEscrowReceipt(db, privateKey, publicKey, opts) {
|
|
|
3733
4012
|
|
|
3734
4013
|
// src/identity/identity.ts
|
|
3735
4014
|
import { z as z4 } from "zod";
|
|
3736
|
-
import { createHash as createHash2 } from "crypto";
|
|
4015
|
+
import { createHash as createHash2, createPrivateKey as createPrivateKey2, createPublicKey as createPublicKey2 } from "crypto";
|
|
3737
4016
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
3738
4017
|
import { join as join4 } from "path";
|
|
3739
4018
|
var AgentIdentitySchema = z4.object({
|
|
@@ -3763,6 +4042,30 @@ var AgentCertificateSchema = z4.object({
|
|
|
3763
4042
|
signature: z4.string().min(1)
|
|
3764
4043
|
});
|
|
3765
4044
|
var IDENTITY_FILENAME = "identity.json";
|
|
4045
|
+
var PRIVATE_KEY_FILENAME = "private.key";
|
|
4046
|
+
var PUBLIC_KEY_FILENAME = "public.key";
|
|
4047
|
+
function derivePublicKeyFromPrivate(privateKey) {
|
|
4048
|
+
const privateKeyObject = createPrivateKey2({ key: privateKey, format: "der", type: "pkcs8" });
|
|
4049
|
+
const publicKeyObject = createPublicKey2(privateKeyObject);
|
|
4050
|
+
const publicKey = publicKeyObject.export({ format: "der", type: "spki" });
|
|
4051
|
+
return Buffer.from(publicKey);
|
|
4052
|
+
}
|
|
4053
|
+
function buildIdentityFromPublicKey(publicKey, owner, createdAt) {
|
|
4054
|
+
const publicKeyHex = publicKey.toString("hex");
|
|
4055
|
+
return {
|
|
4056
|
+
agent_id: deriveAgentId(publicKeyHex),
|
|
4057
|
+
owner,
|
|
4058
|
+
public_key: publicKeyHex,
|
|
4059
|
+
created_at: createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
4060
|
+
};
|
|
4061
|
+
}
|
|
4062
|
+
function generateFreshIdentity(configDir, owner) {
|
|
4063
|
+
const keys = generateKeyPair();
|
|
4064
|
+
saveKeyPair(configDir, keys);
|
|
4065
|
+
const identity = buildIdentityFromPublicKey(keys.publicKey, owner);
|
|
4066
|
+
saveIdentity(configDir, identity);
|
|
4067
|
+
return { identity, keys, status: "generated" };
|
|
4068
|
+
}
|
|
3766
4069
|
function deriveAgentId(publicKeyHex) {
|
|
3767
4070
|
return createHash2("sha256").update(publicKeyHex, "hex").digest("hex").slice(0, 16);
|
|
3768
4071
|
}
|
|
@@ -3805,6 +4108,57 @@ function saveIdentity(configDir, identity) {
|
|
|
3805
4108
|
const filePath = join4(configDir, IDENTITY_FILENAME);
|
|
3806
4109
|
writeFileSync4(filePath, JSON.stringify(identity, null, 2), "utf-8");
|
|
3807
4110
|
}
|
|
4111
|
+
function loadOrRepairIdentity(configDir, ownerHint) {
|
|
4112
|
+
if (!existsSync4(configDir)) {
|
|
4113
|
+
mkdirSync3(configDir, { recursive: true });
|
|
4114
|
+
}
|
|
4115
|
+
const identityPath = join4(configDir, IDENTITY_FILENAME);
|
|
4116
|
+
const privateKeyPath = join4(configDir, PRIVATE_KEY_FILENAME);
|
|
4117
|
+
const publicKeyPath = join4(configDir, PUBLIC_KEY_FILENAME);
|
|
4118
|
+
const hasIdentity = existsSync4(identityPath);
|
|
4119
|
+
const hasPrivateKey = existsSync4(privateKeyPath);
|
|
4120
|
+
const hasPublicKey = existsSync4(publicKeyPath);
|
|
4121
|
+
if (!hasIdentity || !hasPrivateKey || !hasPublicKey) {
|
|
4122
|
+
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
4123
|
+
}
|
|
4124
|
+
let keys;
|
|
4125
|
+
try {
|
|
4126
|
+
keys = loadKeyPair(configDir);
|
|
4127
|
+
} catch {
|
|
4128
|
+
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
4129
|
+
}
|
|
4130
|
+
let derivedPublicKey;
|
|
4131
|
+
try {
|
|
4132
|
+
derivedPublicKey = derivePublicKeyFromPrivate(keys.privateKey);
|
|
4133
|
+
} catch {
|
|
4134
|
+
return generateFreshIdentity(configDir, ownerHint ?? "agent");
|
|
4135
|
+
}
|
|
4136
|
+
let keypairRepaired = false;
|
|
4137
|
+
if (!keys.publicKey.equals(derivedPublicKey)) {
|
|
4138
|
+
keypairRepaired = true;
|
|
4139
|
+
keys = { privateKey: keys.privateKey, publicKey: derivedPublicKey };
|
|
4140
|
+
saveKeyPair(configDir, keys);
|
|
4141
|
+
}
|
|
4142
|
+
const loadedIdentity = loadIdentity(configDir);
|
|
4143
|
+
const expectedAgentId = deriveAgentId(derivedPublicKey.toString("hex"));
|
|
4144
|
+
const expectedPublicKeyHex = derivedPublicKey.toString("hex");
|
|
4145
|
+
const identityMismatch = !loadedIdentity || loadedIdentity.public_key !== expectedPublicKeyHex || loadedIdentity.agent_id !== expectedAgentId;
|
|
4146
|
+
if (identityMismatch) {
|
|
4147
|
+
const repairedIdentity = buildIdentityFromPublicKey(
|
|
4148
|
+
derivedPublicKey,
|
|
4149
|
+
loadedIdentity?.owner ?? ownerHint ?? "agent",
|
|
4150
|
+
loadedIdentity?.created_at
|
|
4151
|
+
);
|
|
4152
|
+
saveIdentity(configDir, repairedIdentity);
|
|
4153
|
+
return { identity: repairedIdentity, keys, status: "repaired" };
|
|
4154
|
+
}
|
|
4155
|
+
if (ownerHint && loadedIdentity.owner !== ownerHint) {
|
|
4156
|
+
const updatedIdentity = { ...loadedIdentity, owner: ownerHint };
|
|
4157
|
+
saveIdentity(configDir, updatedIdentity);
|
|
4158
|
+
return { identity: updatedIdentity, keys, status: "repaired" };
|
|
4159
|
+
}
|
|
4160
|
+
return { identity: loadedIdentity, keys, status: keypairRepaired ? "repaired" : "existing" };
|
|
4161
|
+
}
|
|
3808
4162
|
function issueAgentCertificate(identity, privateKey) {
|
|
3809
4163
|
const issuedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3810
4164
|
const expiresAt = new Date(Date.now() + 365 * 24 * 60 * 60 * 1e3).toISOString();
|
|
@@ -3838,15 +4192,7 @@ function verifyAgentCertificate(cert) {
|
|
|
3838
4192
|
return verifyEscrowReceipt(payload, cert.signature, publicKeyBuf);
|
|
3839
4193
|
}
|
|
3840
4194
|
function ensureIdentity(configDir, owner) {
|
|
3841
|
-
|
|
3842
|
-
if (existing) {
|
|
3843
|
-
if (existing.owner !== owner) {
|
|
3844
|
-
existing.owner = owner;
|
|
3845
|
-
saveIdentity(configDir, existing);
|
|
3846
|
-
}
|
|
3847
|
-
return existing;
|
|
3848
|
-
}
|
|
3849
|
-
return createIdentity(configDir, owner);
|
|
4195
|
+
return loadOrRepairIdentity(configDir, owner).identity;
|
|
3850
4196
|
}
|
|
3851
4197
|
|
|
3852
4198
|
// src/sdk/consumer.ts
|