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.
Files changed (38) hide show
  1. package/dist/{chunk-TBJ3FZKZ.js → chunk-7Q2XUXSA.js} +1 -1
  2. package/dist/{chunk-LJM7FHPM.js → chunk-BZOJ7HBT.js} +33 -1
  3. package/dist/{chunk-FTZTEHYG.js → chunk-DEWY7OQK.js} +135 -8
  4. package/dist/{chunk-CUONY5TO.js → chunk-EJKW57ZV.js} +19 -1
  5. package/dist/chunk-EZVOG7QS.js +161 -0
  6. package/dist/{chunk-E2OKP5CY.js → chunk-GJETGML6.js} +181 -83
  7. package/dist/{chunk-YHY7OG6S.js → chunk-GWMMYVLL.js} +4 -4
  8. package/dist/{chunk-D6RKW2XG.js → chunk-JLNHMNES.js} +16 -3
  9. package/dist/{chunk-5AAFG2V2.js → chunk-KBQNTUTN.js} +239 -24
  10. package/dist/{chunk-C537SFHV.js → chunk-LOUEJI6X.js} +4 -4
  11. package/dist/{chunk-ALX4WS3A.js → chunk-NP55V7RQ.js} +1 -1
  12. package/dist/{chunk-X32NE6V4.js → chunk-RBXTWWUH.js} +1 -1
  13. package/dist/{chunk-O2OYBAVR.js → chunk-SRBVKO2V.js} +9 -0
  14. package/dist/{chunk-7EF3HYVZ.js → chunk-STJLWMXH.js} +48 -4
  15. package/dist/{chunk-5GME4KJZ.js → chunk-UYCD3JBZ.js} +3 -3
  16. package/dist/{chunk-P4LOYSLA.js → chunk-WKWJWKX7.js} +286 -81
  17. package/dist/cli/index.js +35 -57
  18. package/dist/{client-HKV3QWZ3.js → client-66TFS7RS.js} +4 -2
  19. package/dist/{conduct-W6XF6DJW.js → conduct-A6COHLHY.js} +8 -8
  20. package/dist/{conduct-YB64OHI6.js → conduct-IUVAXUAV.js} +8 -8
  21. package/dist/{conductor-mode-TFCVCQHU.js → conductor-mode-D5TFQW5L.js} +2 -2
  22. package/dist/{conductor-mode-AKREGDIU.js → conductor-mode-L2MB44BW.js} +7 -7
  23. package/dist/{execute-AYQWORVH.js → execute-5AWLARB5.js} +5 -5
  24. package/dist/{execute-EPE6MZLT.js → execute-WOS457HW.js} +2 -2
  25. package/dist/index.js +438 -92
  26. package/dist/{publish-capability-AH2HDW54.js → publish-capability-JJCBBMSX.js} +2 -2
  27. package/dist/{request-HCCXSKAY.js → request-6YQLA7K3.js} +13 -8
  28. package/dist/{serve-skill-SZAQT5T5.js → serve-skill-X7TZSILV.js} +5 -5
  29. package/dist/{server-LMY2A3GT.js → server-5TSP4DBX.js} +10 -12
  30. package/dist/{service-coordinator-WGH6B2VT.js → service-coordinator-WTUSMPY6.js} +69 -46
  31. package/dist/skills/agentbnb/bootstrap.js +459 -189
  32. package/package.json +13 -17
  33. package/skills/agentbnb/bootstrap.test.ts +8 -6
  34. package/skills/agentbnb/bootstrap.ts +21 -13
  35. package/skills/agentbnb/install.sh +0 -0
  36. package/dist/chunk-64AK4FJM.js +0 -84
  37. package/dist/chunk-OH7BP5NP.js +0 -96
  38. 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(data, Object.keys(data).sort());
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 body = request.body;
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 waveResults = await Promise.allSettled(
3306
- executableIds.map(async (taskId) => {
3307
- const subtask = subtaskMap.get(taskId);
3308
- const m = matches.get(taskId);
3309
- if (!m) {
3310
- throw new Error(`No match found for subtask ${taskId}`);
3311
- }
3312
- const stepsContext = {};
3313
- for (const [id, val] of results) {
3314
- stepsContext[id] = val;
3315
- }
3316
- const interpContext = { steps: stepsContext, prev: void 0 };
3317
- if (subtask.depends_on.length > 0) {
3318
- const lastDep = subtask.depends_on[subtask.depends_on.length - 1];
3319
- interpContext.prev = results.get(lastDep);
3320
- }
3321
- const interpolatedParams = interpolateObject(
3322
- subtask.params,
3323
- interpContext
3324
- );
3325
- const teamMember = teamMemberMap.get(taskId);
3326
- const teamId = opts.team?.team_id ?? null;
3327
- const taskCapabilityType = teamMember?.capability_type ?? null;
3328
- const agentOwner = teamMember?.agent ?? m.selected_agent;
3329
- const primary = resolveAgentUrl(agentOwner);
3330
- try {
3331
- let res;
3332
- if (primary.url.startsWith("relay://") && relayClient) {
3333
- const targetOwner = primary.url.replace("relay://", "");
3334
- res = await relayClient.request({
3335
- targetOwner,
3336
- cardId: primary.cardId,
3337
- params: interpolatedParams,
3338
- requester: requesterOwner,
3339
- timeoutMs
3340
- });
3341
- } else {
3342
- res = await requestCapability({
3343
- gatewayUrl: primary.url,
3344
- token: gatewayToken,
3345
- cardId: primary.cardId,
3346
- params: { ...interpolatedParams, requester: requesterOwner },
3347
- timeoutMs
3348
- });
3349
- }
3350
- return { taskId, result: res, credits: m.credits, team_id: teamId, capability_type: taskCapabilityType };
3351
- } catch (primaryErr) {
3352
- if (m.alternatives.length > 0) {
3353
- const alt = m.alternatives[0];
3354
- const altAgent = resolveAgentUrl(alt.agent);
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
- let altRes;
3357
- if (altAgent.url.startsWith("relay://") && relayClient) {
3358
- const targetOwner = altAgent.url.replace("relay://", "");
3359
- altRes = await relayClient.request({
3360
- targetOwner,
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
- throw new Error(
3383
- `Task ${taskId}: ${primaryErr instanceof Error ? primaryErr.message : String(primaryErr)}`
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
- const existing = loadIdentity(configDir);
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
@@ -2,8 +2,8 @@ import {
2
2
  parseSoulMd,
3
3
  publishFromSoul,
4
4
  skillConfigToSkill
5
- } from "./chunk-TBJ3FZKZ.js";
6
- import "./chunk-O2OYBAVR.js";
5
+ } from "./chunk-7Q2XUXSA.js";
6
+ import "./chunk-SRBVKO2V.js";
7
7
  import "./chunk-WVY2W7AA.js";
8
8
  export {
9
9
  parseSoulMd,