agentbnb 8.2.0 → 8.2.2

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 (40) hide show
  1. package/dist/{chunk-TBJ3FZKZ.js → chunk-4IPJJRTP.js} +1 -1
  2. package/dist/chunk-CKOOVZOI.js +158 -0
  3. package/dist/chunk-CQFBNTGT.js +145 -0
  4. package/dist/{chunk-P4LOYSLA.js → chunk-DYQOFGGI.js} +331 -416
  5. package/dist/{chunk-ALX4WS3A.js → chunk-EG6RS4JC.js} +70 -46
  6. package/dist/{chunk-CUONY5TO.js → chunk-EJKW57ZV.js} +19 -1
  7. package/dist/{chunk-5AAFG2V2.js → chunk-LKLKYXLV.js} +239 -24
  8. package/dist/{chunk-7EF3HYVZ.js → chunk-MCED4GDW.js} +499 -86
  9. package/dist/{chunk-YHY7OG6S.js → chunk-MWOXW7JQ.js} +7 -7
  10. package/dist/{chunk-E2OKP5CY.js → chunk-QCGIG7WW.js} +182 -86
  11. package/dist/{chunk-5GME4KJZ.js → chunk-QHZGOG3O.js} +148 -46
  12. package/dist/{chunk-D6RKW2XG.js → chunk-RYISHSHB.js} +302 -4
  13. package/dist/{chunk-O2OYBAVR.js → chunk-S3V6R3EN.js} +75 -39
  14. package/dist/{chunk-X32NE6V4.js → chunk-WNXXLCV5.js} +1 -1
  15. package/dist/{chunk-C537SFHV.js → chunk-XBGVQMQJ.js} +72 -48
  16. package/dist/{chunk-FTZTEHYG.js → chunk-Z2GEFFDO.js} +135 -8
  17. package/dist/cli/index.js +42 -67
  18. package/dist/{client-HKV3QWZ3.js → client-XOLP5IUZ.js} +4 -2
  19. package/dist/{conduct-W6XF6DJW.js → conduct-AZFLNUX3.js} +10 -11
  20. package/dist/{conduct-YB64OHI6.js → conduct-VPUYTNEA.js} +10 -11
  21. package/dist/{conductor-mode-AKREGDIU.js → conductor-mode-PLTB6MS3.js} +7 -8
  22. package/dist/{conductor-mode-TFCVCQHU.js → conductor-mode-WKB42PYM.js} +6 -3
  23. package/dist/{execute-EPE6MZLT.js → execute-NNDCXTN4.js} +3 -2
  24. package/dist/{execute-AYQWORVH.js → execute-RIRHTIBU.js} +6 -5
  25. package/dist/index.d.ts +8 -8
  26. package/dist/index.js +637 -693
  27. package/dist/{publish-capability-AH2HDW54.js → publish-capability-QDR2QIZ2.js} +2 -2
  28. package/dist/{request-HCCXSKAY.js → request-NX7GSPIG.js} +31 -36
  29. package/dist/{serve-skill-SZAQT5T5.js → serve-skill-E6EJQYAK.js} +10 -9
  30. package/dist/{server-LMY2A3GT.js → server-VBCT32FC.js} +12 -18
  31. package/dist/{service-coordinator-WGH6B2VT.js → service-coordinator-KMSA6BST.js} +137 -69
  32. package/dist/skills/agentbnb/bootstrap.js +561 -247
  33. package/package.json +13 -17
  34. package/skills/agentbnb/bootstrap.test.ts +8 -6
  35. package/skills/agentbnb/bootstrap.ts +21 -13
  36. package/skills/agentbnb/install.sh +0 -0
  37. package/dist/chunk-64AK4FJM.js +0 -84
  38. package/dist/chunk-KF3TZHA5.js +0 -91
  39. package/dist/chunk-LJM7FHPM.js +0 -138
  40. package/dist/chunk-OH7BP5NP.js +0 -96
@@ -1,28 +1,28 @@
1
- import {
2
- RelayClient
3
- } from "./chunk-Z4MCGKTL.js";
4
1
  import {
5
2
  BudgetController,
6
3
  ORCHESTRATION_FEE,
7
4
  decompose,
8
5
  matchSubTasks,
9
6
  orchestrate
10
- } from "./chunk-E2OKP5CY.js";
7
+ } from "./chunk-QCGIG7WW.js";
11
8
  import {
12
9
  BudgetManager
13
- } from "./chunk-5GME4KJZ.js";
10
+ } from "./chunk-QHZGOG3O.js";
14
11
  import {
15
12
  openCreditDb
16
- } from "./chunk-D6RKW2XG.js";
13
+ } from "./chunk-RYISHSHB.js";
17
14
  import {
18
15
  loadPeers
19
16
  } from "./chunk-5AH3CMOX.js";
20
17
  import {
21
18
  loadConfig
22
19
  } from "./chunk-75OC6E4F.js";
20
+ import {
21
+ RelayClient
22
+ } from "./chunk-Z4MCGKTL.js";
23
23
  import {
24
24
  openDatabase
25
- } from "./chunk-O2OYBAVR.js";
25
+ } from "./chunk-S3V6R3EN.js";
26
26
 
27
27
  // src/cli/conduct.ts
28
28
  async function conductAction(task, opts) {
@@ -3,16 +3,15 @@ import {
3
3
  } from "./chunk-3MJT4PZG.js";
4
4
  import {
5
5
  scorePeers
6
- } from "./chunk-5GME4KJZ.js";
7
- import {
8
- fetchRemoteCards
9
- } from "./chunk-KF3TZHA5.js";
6
+ } from "./chunk-QHZGOG3O.js";
10
7
  import {
8
+ fetchRemoteCards,
11
9
  searchCards
12
- } from "./chunk-LJM7FHPM.js";
10
+ } from "./chunk-RYISHSHB.js";
13
11
  import {
14
- requestCapability
15
- } from "./chunk-64AK4FJM.js";
12
+ requestCapability,
13
+ requestCapabilityBatch
14
+ } from "./chunk-CKOOVZOI.js";
16
15
 
17
16
  // src/conductor/decomposition-validator.ts
18
17
  function validateAndNormalizeSubtasks(raw, context) {
@@ -410,6 +409,65 @@ function computeWaves(subtasks) {
410
409
  }
411
410
  return waves;
412
411
  }
412
+ async function executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl) {
413
+ const { taskId, match: m, interpolatedParams, primary, teamId, capabilityType } = pt;
414
+ try {
415
+ let res;
416
+ if (primary.url.startsWith("relay://") && relayClient) {
417
+ const targetOwner = primary.url.replace("relay://", "");
418
+ res = await relayClient.request({
419
+ targetOwner,
420
+ cardId: primary.cardId,
421
+ params: interpolatedParams,
422
+ requester: requesterOwner,
423
+ timeoutMs
424
+ });
425
+ } else {
426
+ res = await requestCapability({
427
+ gatewayUrl: primary.url,
428
+ token: gatewayToken,
429
+ cardId: primary.cardId,
430
+ params: { ...interpolatedParams, requester: requesterOwner },
431
+ timeoutMs
432
+ });
433
+ }
434
+ return { taskId, result: res, credits: m.credits, team_id: teamId, capability_type: capabilityType };
435
+ } catch (primaryErr) {
436
+ if (m.alternatives.length > 0) {
437
+ const alt = m.alternatives[0];
438
+ const altResolved = resolveAgentUrl ? resolveAgentUrl(alt.agent) : { url: `http://${alt.agent}:7700`, cardId: `card-${alt.agent}` };
439
+ try {
440
+ let altRes;
441
+ if (altResolved.url.startsWith("relay://") && relayClient) {
442
+ const targetOwner = altResolved.url.replace("relay://", "");
443
+ altRes = await relayClient.request({
444
+ targetOwner,
445
+ cardId: altResolved.cardId,
446
+ params: interpolatedParams,
447
+ requester: requesterOwner,
448
+ timeoutMs
449
+ });
450
+ } else {
451
+ altRes = await requestCapability({
452
+ gatewayUrl: altResolved.url,
453
+ token: gatewayToken,
454
+ cardId: altResolved.cardId,
455
+ params: { ...interpolatedParams, requester: requesterOwner },
456
+ timeoutMs
457
+ });
458
+ }
459
+ return { taskId, result: altRes, credits: alt.credits, team_id: teamId, capability_type: capabilityType };
460
+ } catch (altErr) {
461
+ throw new Error(
462
+ `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)}`
463
+ );
464
+ }
465
+ }
466
+ throw new Error(
467
+ `Task ${taskId}: ${primaryErr instanceof Error ? primaryErr.message : String(primaryErr)}`
468
+ );
469
+ }
470
+ }
413
471
  async function orchestrate(opts) {
414
472
  const { subtasks, matches, gatewayToken, resolveAgentUrl, timeoutMs = 3e5, maxBudget, relayClient, requesterOwner } = opts;
415
473
  const startTime = Date.now();
@@ -447,89 +505,127 @@ async function orchestrate(opts) {
447
505
  }
448
506
  executableIds.push(taskId);
449
507
  }
450
- const waveResults = await Promise.allSettled(
451
- executableIds.map(async (taskId) => {
452
- const subtask = subtaskMap.get(taskId);
453
- const m = matches.get(taskId);
454
- if (!m) {
455
- throw new Error(`No match found for subtask ${taskId}`);
456
- }
457
- const stepsContext = {};
458
- for (const [id, val] of results) {
459
- stepsContext[id] = val;
460
- }
461
- const interpContext = { steps: stepsContext, prev: void 0 };
462
- if (subtask.depends_on.length > 0) {
463
- const lastDep = subtask.depends_on[subtask.depends_on.length - 1];
464
- interpContext.prev = results.get(lastDep);
465
- }
466
- const interpolatedParams = interpolateObject(
467
- subtask.params,
468
- interpContext
469
- );
470
- const teamMember = teamMemberMap.get(taskId);
471
- const teamId = opts.team?.team_id ?? null;
472
- const taskCapabilityType = teamMember?.capability_type ?? null;
473
- const agentOwner = teamMember?.agent ?? m.selected_agent;
474
- const primary = resolveAgentUrl(agentOwner);
475
- try {
476
- let res;
477
- if (primary.url.startsWith("relay://") && relayClient) {
478
- const targetOwner = primary.url.replace("relay://", "");
479
- res = await relayClient.request({
480
- targetOwner,
481
- cardId: primary.cardId,
482
- params: interpolatedParams,
483
- requester: requesterOwner,
484
- timeoutMs
485
- });
486
- } else {
487
- res = await requestCapability({
488
- gatewayUrl: primary.url,
489
- token: gatewayToken,
490
- cardId: primary.cardId,
491
- params: { ...interpolatedParams, requester: requesterOwner },
492
- timeoutMs
493
- });
494
- }
495
- return { taskId, result: res, credits: m.credits, team_id: teamId, capability_type: taskCapabilityType };
496
- } catch (primaryErr) {
497
- if (m.alternatives.length > 0) {
498
- const alt = m.alternatives[0];
499
- const altAgent = resolveAgentUrl(alt.agent);
508
+ const preparedTasks = [];
509
+ for (const taskId of executableIds) {
510
+ const subtask = subtaskMap.get(taskId);
511
+ const m = matches.get(taskId);
512
+ if (!m) {
513
+ errors.push(`No match found for subtask ${taskId}`);
514
+ continue;
515
+ }
516
+ const stepsContext = {};
517
+ for (const [id, val] of results) stepsContext[id] = val;
518
+ const interpContext = { steps: stepsContext, prev: void 0 };
519
+ if (subtask.depends_on.length > 0) {
520
+ const lastDep = subtask.depends_on[subtask.depends_on.length - 1];
521
+ interpContext.prev = results.get(lastDep);
522
+ }
523
+ const interpolatedParams = interpolateObject(
524
+ subtask.params,
525
+ interpContext
526
+ );
527
+ const teamMember = teamMemberMap.get(taskId);
528
+ const agentOwner = teamMember?.agent ?? m.selected_agent;
529
+ const primary = resolveAgentUrl(agentOwner);
530
+ preparedTasks.push({
531
+ taskId,
532
+ subtask,
533
+ match: m,
534
+ interpolatedParams,
535
+ agentOwner,
536
+ primary,
537
+ teamId: opts.team?.team_id ?? null,
538
+ capabilityType: teamMember?.capability_type ?? null
539
+ });
540
+ }
541
+ const httpGroups = /* @__PURE__ */ new Map();
542
+ const relayTasks = [];
543
+ for (const pt of preparedTasks) {
544
+ if (pt.primary.url.startsWith("relay://") && relayClient) {
545
+ relayTasks.push(pt);
546
+ } else {
547
+ const group = httpGroups.get(pt.primary.url) ?? [];
548
+ group.push(pt);
549
+ httpGroups.set(pt.primary.url, group);
550
+ }
551
+ }
552
+ const batchPromises = [];
553
+ for (const [gatewayUrl, group] of httpGroups) {
554
+ if (group.length >= 2) {
555
+ batchPromises.push(
556
+ (async () => {
557
+ const items = group.map((pt) => ({
558
+ id: pt.taskId,
559
+ cardId: pt.primary.cardId,
560
+ params: { ...pt.interpolatedParams, requester: requesterOwner },
561
+ _pt: pt
562
+ }));
500
563
  try {
501
- let altRes;
502
- if (altAgent.url.startsWith("relay://") && relayClient) {
503
- const targetOwner = altAgent.url.replace("relay://", "");
504
- altRes = await relayClient.request({
505
- targetOwner,
506
- cardId: altAgent.cardId,
507
- params: interpolatedParams,
508
- requester: requesterOwner,
509
- timeoutMs
510
- });
511
- } else {
512
- altRes = await requestCapability({
513
- gatewayUrl: altAgent.url,
514
- token: gatewayToken,
515
- cardId: altAgent.cardId,
516
- params: { ...interpolatedParams, requester: requesterOwner },
517
- timeoutMs
518
- });
519
- }
520
- return { taskId, result: altRes, credits: alt.credits, team_id: teamId, capability_type: taskCapabilityType };
521
- } catch (altErr) {
522
- throw new Error(
523
- `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)}`
564
+ const batchResults = await requestCapabilityBatch(
565
+ gatewayUrl,
566
+ gatewayToken,
567
+ items.map(({ _pt, ...item }) => item),
568
+ { timeoutMs }
524
569
  );
570
+ return items.map((item) => {
571
+ const res = batchResults.get(item.id);
572
+ if (res instanceof Error) {
573
+ return {
574
+ status: "rejected",
575
+ reason: new Error(`Task ${item.id}: ${res.message}`)
576
+ };
577
+ }
578
+ return {
579
+ status: "fulfilled",
580
+ value: {
581
+ taskId: item.id,
582
+ result: res,
583
+ credits: item._pt.match.credits,
584
+ team_id: item._pt.teamId,
585
+ capability_type: item._pt.capabilityType
586
+ }
587
+ };
588
+ });
589
+ } catch (batchErr) {
590
+ return Promise.all(group.map(async (pt) => {
591
+ try {
592
+ const res = await executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl);
593
+ return { status: "fulfilled", value: res };
594
+ } catch (err) {
595
+ return { status: "rejected", reason: err };
596
+ }
597
+ }));
598
+ }
599
+ })()
600
+ );
601
+ } else {
602
+ const pt = group[0];
603
+ batchPromises.push(
604
+ (async () => {
605
+ try {
606
+ const res = await executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl);
607
+ return [{ status: "fulfilled", value: res }];
608
+ } catch (err) {
609
+ return [{ status: "rejected", reason: err }];
525
610
  }
611
+ })()
612
+ );
613
+ }
614
+ }
615
+ for (const pt of relayTasks) {
616
+ batchPromises.push(
617
+ (async () => {
618
+ try {
619
+ const res = await executeSingleTask(pt, gatewayToken, timeoutMs, requesterOwner, relayClient, resolveAgentUrl);
620
+ return [{ status: "fulfilled", value: res }];
621
+ } catch (err) {
622
+ return [{ status: "rejected", reason: err }];
526
623
  }
527
- throw new Error(
528
- `Task ${taskId}: ${primaryErr instanceof Error ? primaryErr.message : String(primaryErr)}`
529
- );
530
- }
531
- })
532
- );
624
+ })()
625
+ );
626
+ }
627
+ const allBatchResults = await Promise.all(batchPromises);
628
+ const waveResults = allBatchResults.flat();
533
629
  for (const settlement of waveResults) {
534
630
  if (settlement.status === "fulfilled") {
535
631
  const { taskId, result, credits, team_id, capability_type } = settlement.value;
@@ -1,23 +1,23 @@
1
- import {
2
- fetchRemoteCards
3
- } from "./chunk-KF3TZHA5.js";
4
1
  import {
5
2
  createPendingRequest,
6
3
  getAutonomyTier,
7
4
  insertAuditEvent
8
5
  } from "./chunk-GKVTD4EZ.js";
9
6
  import {
10
- searchCards
11
- } from "./chunk-LJM7FHPM.js";
7
+ resolveTargetCapability
8
+ } from "./chunk-CQFBNTGT.js";
12
9
  import {
10
+ fetchRemoteCards,
13
11
  getBalance,
14
12
  holdEscrow,
15
13
  releaseEscrow,
14
+ searchCards,
16
15
  settleEscrow
17
- } from "./chunk-D6RKW2XG.js";
16
+ } from "./chunk-RYISHSHB.js";
18
17
  import {
19
- requestCapability
20
- } from "./chunk-64AK4FJM.js";
18
+ requestCapability,
19
+ requestViaRelay
20
+ } from "./chunk-CKOOVZOI.js";
21
21
  import {
22
22
  findPeer
23
23
  } from "./chunk-5AH3CMOX.js";
@@ -68,6 +68,7 @@ var BudgetManager = class {
68
68
  };
69
69
 
70
70
  // src/autonomy/auto-request.ts
71
+ import { randomUUID } from "crypto";
71
72
  function minMaxNormalize(values) {
72
73
  if (values.length === 0) return [];
73
74
  if (values.length === 1) return [1];
@@ -190,88 +191,189 @@ var AutoRequestor = class {
190
191
  }
191
192
  }
192
193
  const scored = scorePeers(candidates, this.owner);
194
+ const resolverOptions = {
195
+ registryDb: this.registryDb,
196
+ registryUrl: this.registryUrl,
197
+ onlineOnly: true
198
+ };
199
+ let resolvedTarget = null;
193
200
  if (scored.length === 0) {
201
+ resolvedTarget = await resolveTargetCapability(need.query, resolverOptions);
202
+ if (!resolvedTarget || resolvedTarget.owner === this.owner || resolvedTarget.credits_per_call > need.maxCostCredits) {
203
+ this.logFailure("auto_request_failed", "system", "none", 3, 0, "none", "No eligible peer found");
204
+ return { status: "no_peer", reason: "No eligible peer found" };
205
+ }
206
+ } else {
207
+ const top = scored[0];
208
+ const targetKey = top.skillId ?? top.card.id;
209
+ resolvedTarget = await resolveTargetCapability(targetKey, resolverOptions) ?? await resolveTargetCapability(need.query, resolverOptions);
210
+ if (!resolvedTarget || resolvedTarget.owner === this.owner) {
211
+ this.logFailure("auto_request_failed", top.card.id, top.skillId ?? "none", 3, top.cost, top.card.owner, "No eligible peer found");
212
+ return { status: "no_peer", reason: "No eligible peer found" };
213
+ }
214
+ }
215
+ if (!resolvedTarget) {
194
216
  this.logFailure("auto_request_failed", "system", "none", 3, 0, "none", "No eligible peer found");
195
217
  return { status: "no_peer", reason: "No eligible peer found" };
196
218
  }
197
- const top = scored[0];
198
- const peerConfig = findPeer(top.card.owner);
199
- if (!peerConfig) {
200
- this.logFailure("auto_request_failed", top.card.id, top.skillId ?? "none", 3, top.cost, top.card.owner, "No gateway config for peer");
201
- return { status: "no_peer", reason: "No gateway config for peer" };
202
- }
203
- const tier = getAutonomyTier(top.cost, this.autonomyConfig);
219
+ const selectedCardId = resolvedTarget.cardId;
220
+ const selectedSkillId = resolvedTarget.skillId;
221
+ const selectedPeer = resolvedTarget.owner;
222
+ const selectedCost = resolvedTarget.credits_per_call;
223
+ const selectedViaRelay = resolvedTarget.via_relay;
224
+ const tier = getAutonomyTier(selectedCost, this.autonomyConfig);
204
225
  if (tier === 3) {
205
226
  createPendingRequest(this.registryDb, {
206
227
  skill_query: need.query,
207
228
  max_cost_credits: need.maxCostCredits,
208
- credits: top.cost,
209
- selected_peer: top.card.owner,
210
- selected_card_id: top.card.id,
211
- selected_skill_id: top.skillId,
229
+ credits: selectedCost,
230
+ selected_peer: selectedPeer,
231
+ selected_card_id: selectedCardId,
232
+ selected_skill_id: selectedSkillId,
212
233
  params: need.params
213
234
  });
214
235
  insertAuditEvent(this.registryDb, {
215
236
  type: "auto_request_pending",
216
- card_id: top.card.id,
217
- skill_id: top.skillId ?? top.card.id,
237
+ card_id: selectedCardId,
238
+ skill_id: selectedSkillId ?? selectedCardId,
218
239
  tier_invoked: 3,
219
- credits: top.cost,
220
- peer: top.card.owner
240
+ credits: selectedCost,
241
+ peer: selectedPeer
221
242
  });
222
243
  return {
223
244
  status: "tier_blocked",
224
245
  reason: "Tier 3: owner approval required",
225
- peer: top.card.owner
246
+ peer: selectedPeer
226
247
  };
227
248
  }
228
- if (!this.budgetManager.canSpend(top.cost)) {
229
- this.logFailure("auto_request_failed", top.card.id, top.skillId ?? "none", tier, top.cost, top.card.owner, "Budget reserve would be breached");
249
+ if (!this.budgetManager.canSpend(selectedCost)) {
250
+ this.logFailure(
251
+ "auto_request_failed",
252
+ selectedCardId,
253
+ selectedSkillId ?? "none",
254
+ tier,
255
+ selectedCost,
256
+ selectedPeer,
257
+ "Budget reserve would be breached"
258
+ );
230
259
  return { status: "budget_blocked", reason: "Insufficient credits \u2014 reserve floor would be breached" };
231
260
  }
232
- const escrowId = holdEscrow(this.creditDb, this.owner, top.cost, top.card.id);
261
+ const escrowId = holdEscrow(this.creditDb, this.owner, selectedCost, selectedCardId);
233
262
  try {
234
- const execResult = await requestCapability({
235
- gatewayUrl: peerConfig.url,
236
- token: peerConfig.token,
237
- cardId: top.card.id,
238
- params: top.skillId ? { skill_id: top.skillId, ...need.params, requester: this.owner } : { ...need.params, requester: this.owner }
239
- });
240
- settleEscrow(this.creditDb, escrowId, top.card.owner);
263
+ const requestParams = selectedSkillId ? { skill_id: selectedSkillId, ...need.params, requester: this.owner } : { ...need.params, requester: this.owner };
264
+ let execResult;
265
+ if (selectedViaRelay) {
266
+ if (!this.registryUrl) {
267
+ this.logFailure(
268
+ "auto_request_failed",
269
+ selectedCardId,
270
+ selectedSkillId ?? "none",
271
+ tier,
272
+ selectedCost,
273
+ selectedPeer,
274
+ "Relay target found but registryUrl is not configured"
275
+ );
276
+ releaseEscrow(this.creditDb, escrowId);
277
+ return { status: "no_peer", reason: "Relay target found but registryUrl is not configured" };
278
+ }
279
+ const relayRequesterOwner = `${this.owner}:req:${randomUUID()}`;
280
+ const { RelayClient } = await import("./websocket-client-QOVARTRN.js");
281
+ const relayClient = new RelayClient({
282
+ registryUrl: this.registryUrl,
283
+ owner: relayRequesterOwner,
284
+ token: "auto-request-token",
285
+ card: {
286
+ spec_version: "1.0",
287
+ id: randomUUID(),
288
+ owner: relayRequesterOwner,
289
+ name: relayRequesterOwner,
290
+ description: "Auto-request requester",
291
+ level: 1,
292
+ inputs: [],
293
+ outputs: [],
294
+ pricing: { credits_per_call: 1 },
295
+ availability: { online: false }
296
+ },
297
+ onRequest: async () => ({ error: { code: -32601, message: "Auto-request relay requester does not serve capabilities" } }),
298
+ silent: true
299
+ });
300
+ try {
301
+ await relayClient.connect();
302
+ execResult = await requestViaRelay(relayClient, {
303
+ targetOwner: selectedPeer,
304
+ cardId: selectedCardId,
305
+ skillId: selectedSkillId,
306
+ params: requestParams,
307
+ requester: this.owner
308
+ });
309
+ } finally {
310
+ relayClient.disconnect();
311
+ }
312
+ } else {
313
+ const peerConfig = findPeer(selectedPeer);
314
+ if (!peerConfig) {
315
+ this.logFailure(
316
+ "auto_request_failed",
317
+ selectedCardId,
318
+ selectedSkillId ?? "none",
319
+ tier,
320
+ selectedCost,
321
+ selectedPeer,
322
+ "No gateway config for peer"
323
+ );
324
+ releaseEscrow(this.creditDb, escrowId);
325
+ return { status: "no_peer", reason: "No gateway config for peer" };
326
+ }
327
+ execResult = await requestCapability({
328
+ gatewayUrl: peerConfig.url,
329
+ token: peerConfig.token,
330
+ cardId: selectedCardId,
331
+ params: requestParams
332
+ });
333
+ }
334
+ settleEscrow(this.creditDb, escrowId, selectedPeer);
241
335
  if (tier === 2) {
242
336
  insertAuditEvent(this.registryDb, {
243
337
  type: "auto_request_notify",
244
- card_id: top.card.id,
245
- skill_id: top.skillId ?? top.card.id,
338
+ card_id: selectedCardId,
339
+ skill_id: selectedSkillId ?? selectedCardId,
246
340
  tier_invoked: 2,
247
- credits: top.cost,
248
- peer: top.card.owner
341
+ credits: selectedCost,
342
+ peer: selectedPeer
249
343
  });
250
344
  } else {
251
345
  insertAuditEvent(this.registryDb, {
252
346
  type: "auto_request",
253
- card_id: top.card.id,
254
- skill_id: top.skillId ?? top.card.id,
347
+ card_id: selectedCardId,
348
+ skill_id: selectedSkillId ?? selectedCardId,
255
349
  tier_invoked: 1,
256
- credits: top.cost,
257
- peer: top.card.owner
350
+ credits: selectedCost,
351
+ peer: selectedPeer
258
352
  });
259
353
  }
260
354
  return {
261
355
  status: "success",
262
356
  result: execResult,
263
357
  escrowId,
264
- peer: top.card.owner,
265
- creditsSpent: top.cost
358
+ peer: selectedPeer,
359
+ creditsSpent: selectedCost
266
360
  };
267
361
  } catch (err) {
268
362
  releaseEscrow(this.creditDb, escrowId);
269
363
  const reason = err instanceof Error ? err.message : String(err);
270
- this.logFailure("auto_request_failed", top.card.id, top.skillId ?? "none", tier, top.cost, top.card.owner, `Execution failed: ${reason}`);
364
+ this.logFailure(
365
+ "auto_request_failed",
366
+ selectedCardId,
367
+ selectedSkillId ?? "none",
368
+ tier,
369
+ selectedCost,
370
+ selectedPeer,
371
+ `Execution failed: ${reason}`
372
+ );
271
373
  return {
272
374
  status: "failed",
273
375
  reason: `Execution failed: ${reason}`,
274
- peer: top.card.owner
376
+ peer: selectedPeer
275
377
  };
276
378
  }
277
379
  }