agentbnb 5.1.11 → 7.0.0-beta.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 (60) hide show
  1. package/README.md +245 -39
  2. package/dist/{card-RSGDCHCV.js → card-REW7BSWW.js} +1 -1
  3. package/dist/{chunk-FLY3WIQR.js → chunk-2HSUPCBT.js} +3 -3
  4. package/dist/{chunk-WGZ5AGOX.js → chunk-3CIMVISQ.js} +24 -1
  5. package/dist/{chunk-NH2FIERR.js → chunk-574W3HHE.js} +1 -1
  6. package/dist/{chunk-WTXRY7R2.js → chunk-APEG4QIN.js} +157 -9
  7. package/dist/chunk-BP3L2TET.js +148 -0
  8. package/dist/{chunk-NLAWT4DT.js → chunk-CWYPTQRQ.js} +7 -7
  9. package/dist/{chunk-UKT6H7YT.js → chunk-DUW6RX6I.js} +5 -2
  10. package/dist/chunk-EAD4A4KG.js +430 -0
  11. package/dist/{chunk-QT7TEVNV.js → chunk-EHSHB7TY.js} +23 -1
  12. package/dist/{chunk-B5FTAGFN.js → chunk-ETGOKDFR.js} +75 -75
  13. package/dist/{chunk-5KFI5X7B.js → chunk-F53QQIM2.js} +1 -1
  14. package/dist/{chunk-MLS6IGGG.js → chunk-FK2MDNTB.js} +117 -117
  15. package/dist/{chunk-EGUOAHCW.js → chunk-GO4FVRVN.js} +15 -13
  16. package/dist/{chunk-CRFCWD6V.js → chunk-J2K5S5MX.js} +136 -173
  17. package/dist/chunk-K5FO42YF.js +1136 -0
  18. package/dist/{chunk-DFBX3BBD.js → chunk-KA2VIEGM.js} +211 -16
  19. package/dist/chunk-NWIQJ2CL.js +108 -0
  20. package/dist/chunk-OCSU2S6W.js +168 -0
  21. package/dist/{chunk-QQFBFV4V.js → chunk-PGDBUUGR.js} +60 -19
  22. package/dist/{chunk-QITOPASZ.js → chunk-PSQHUZ7X.js} +1 -1
  23. package/dist/{chunk-C6KPAFCC.js → chunk-PU7LXOQ3.js} +23 -1
  24. package/dist/{chunk-JOY533UH.js → chunk-TW65F5EU.js} +1 -1
  25. package/dist/{chunk-ZX5623ER.js → chunk-VMH2YS2I.js} +1 -1
  26. package/dist/{chunk-XND2DWTZ.js → chunk-VPQ44XKE.js} +2 -2
  27. package/dist/{chunk-CSATDXZC.js → chunk-Y7T6IMM3.js} +1 -1
  28. package/dist/cli/index.js +755 -379
  29. package/dist/{client-T5MTY3CS.js → client-HRYRJKSA.js} +3 -3
  30. package/dist/{conduct-WU3VEXB6.js → conduct-JNYJCDHQ.js} +14 -13
  31. package/dist/conduct-KJUD2RTB.js +22 -0
  32. package/dist/{conductor-mode-ZMTFZGJP.js → conductor-mode-2VVFMKVE.js} +313 -14
  33. package/dist/conductor-mode-VGUU54QI.js +276 -0
  34. package/dist/execute-I4PKSNJM.js +12 -0
  35. package/dist/execute-MOXSSA3Q.js +15 -0
  36. package/dist/index.d.ts +795 -2
  37. package/dist/index.js +861 -111
  38. package/dist/{process-guard-CC7CNRQJ.js → process-guard-QCCBGILS.js} +1 -1
  39. package/dist/publish-capability-TS6CNR5G.js +12 -0
  40. package/dist/reliability-metrics-QG7WC5QK.js +18 -0
  41. package/dist/{request-VOXBFUOG.js → request-E7TA7COA.js} +19 -18
  42. package/dist/{serve-skill-IH7UAJNR.js → serve-skill-HIOWYKRU.js} +13 -11
  43. package/dist/{server-JVQW2TID.js → server-I63CXFX3.js} +17 -16
  44. package/dist/{service-coordinator-EYRDTHL5.js → service-coordinator-XBNT3SMU.js} +369 -260
  45. package/dist/skill-config-FETXPNVP.js +22 -0
  46. package/dist/skills/agentbnb/bootstrap.js +430 -84
  47. package/dist/websocket-client-5MH6QRJK.js +7 -0
  48. package/dist/{websocket-client-WRN3HO73.js → websocket-client-PFGVTXNE.js} +1 -1
  49. package/openclaw.plugin.json +2 -2
  50. package/package.json +2 -1
  51. package/skills/agentbnb/SKILL.md +35 -0
  52. package/skills/agentbnb/bootstrap.ts +126 -8
  53. package/skills/agentbnb/install.sh +49 -9
  54. package/dist/chunk-EANI2N2V.js +0 -309
  55. package/dist/chunk-EPIWHNB2.js +0 -946
  56. package/dist/conduct-6LKIJJKQ.js +0 -21
  57. package/dist/conductor-mode-Q4IIDY5E.js +0 -123
  58. package/dist/execute-4D4ITQCL.js +0 -10
  59. package/dist/execute-T7Y6RKSW.js +0 -13
  60. package/dist/websocket-client-6IIDGXKB.js +0 -7
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  requestCapability,
3
3
  requestViaRelay
4
- } from "./chunk-XND2DWTZ.js";
5
- import "./chunk-5KFI5X7B.js";
6
- import "./chunk-WGZ5AGOX.js";
4
+ } from "./chunk-VPQ44XKE.js";
5
+ import "./chunk-F53QQIM2.js";
6
+ import "./chunk-3CIMVISQ.js";
7
7
  export {
8
8
  requestCapability,
9
9
  requestViaRelay
@@ -1,21 +1,22 @@
1
1
  import {
2
2
  conductAction
3
- } from "./chunk-NLAWT4DT.js";
4
- import "./chunk-JOY533UH.js";
5
- import "./chunk-QT7TEVNV.js";
6
- import "./chunk-WTXRY7R2.js";
3
+ } from "./chunk-CWYPTQRQ.js";
4
+ import "./chunk-TW65F5EU.js";
5
+ import "./chunk-EHSHB7TY.js";
6
+ import "./chunk-APEG4QIN.js";
7
7
  import "./chunk-3MJT4PZG.js";
8
- import "./chunk-EGUOAHCW.js";
9
- import "./chunk-CSATDXZC.js";
10
- import "./chunk-ZX5623ER.js";
11
- import "./chunk-NH2FIERR.js";
12
- import "./chunk-XND2DWTZ.js";
8
+ import "./chunk-GO4FVRVN.js";
9
+ import "./chunk-VMH2YS2I.js";
10
+ import "./chunk-Y7T6IMM3.js";
11
+ import "./chunk-574W3HHE.js";
12
+ import "./chunk-J2K5S5MX.js";
13
+ import "./chunk-NWIQJ2CL.js";
14
+ import "./chunk-VPQ44XKE.js";
15
+ import "./chunk-F53QQIM2.js";
13
16
  import "./chunk-5AH3CMOX.js";
14
17
  import "./chunk-75OC6E4F.js";
15
- import "./chunk-DFBX3BBD.js";
16
- import "./chunk-EANI2N2V.js";
17
- import "./chunk-5KFI5X7B.js";
18
- import "./chunk-WGZ5AGOX.js";
18
+ import "./chunk-KA2VIEGM.js";
19
+ import "./chunk-3CIMVISQ.js";
19
20
 
20
21
  // src/mcp/tools/conduct.ts
21
22
  import { z } from "zod";
@@ -0,0 +1,22 @@
1
+ import {
2
+ conductAction
3
+ } from "./chunk-CWYPTQRQ.js";
4
+ import "./chunk-TW65F5EU.js";
5
+ import "./chunk-EHSHB7TY.js";
6
+ import "./chunk-APEG4QIN.js";
7
+ import "./chunk-3MJT4PZG.js";
8
+ import "./chunk-GO4FVRVN.js";
9
+ import "./chunk-VMH2YS2I.js";
10
+ import "./chunk-Y7T6IMM3.js";
11
+ import "./chunk-574W3HHE.js";
12
+ import "./chunk-J2K5S5MX.js";
13
+ import "./chunk-NWIQJ2CL.js";
14
+ import "./chunk-VPQ44XKE.js";
15
+ import "./chunk-F53QQIM2.js";
16
+ import "./chunk-5AH3CMOX.js";
17
+ import "./chunk-75OC6E4F.js";
18
+ import "./chunk-KA2VIEGM.js";
19
+ import "./chunk-3CIMVISQ.js";
20
+ export {
21
+ conductAction
22
+ };
@@ -3,16 +3,155 @@ import {
3
3
  interpolateObject,
4
4
  requestCapability,
5
5
  searchCards
6
- } from "./chunk-B5FTAGFN.js";
6
+ } from "./chunk-ETGOKDFR.js";
7
7
  import "./chunk-HLUEOLSZ.js";
8
- import "./chunk-IVOYM3WG.js";
9
8
  import {
10
- getBalance
11
- } from "./chunk-CRFCWD6V.js";
12
- import "./chunk-WGZ5AGOX.js";
9
+ getBalance,
10
+ getCardsByCapabilityType,
11
+ getCardsBySkillCapability
12
+ } from "./chunk-K5FO42YF.js";
13
+ import "./chunk-NWIQJ2CL.js";
14
+ import "./chunk-IVOYM3WG.js";
15
+ import "./chunk-3CIMVISQ.js";
13
16
 
14
17
  // src/conductor/task-decomposer.ts
15
18
  import { randomUUID } from "crypto";
19
+
20
+ // src/conductor/decomposition-validator.ts
21
+ function validateAndNormalizeSubtasks(raw, context) {
22
+ try {
23
+ return _validate(raw, context);
24
+ } catch {
25
+ return { valid: [], errors: ["internal validation error"] };
26
+ }
27
+ }
28
+ function _validate(raw, context) {
29
+ if (!Array.isArray(raw)) {
30
+ return { valid: [], errors: ["decomposition output must be an array"] };
31
+ }
32
+ if (raw.length === 0) {
33
+ return { valid: [], errors: [] };
34
+ }
35
+ const errors = [];
36
+ const validItems = [];
37
+ const validIds = [];
38
+ for (let i = 0; i < raw.length; i++) {
39
+ const item = raw[i];
40
+ if (typeof item !== "object" || item === null || Array.isArray(item)) {
41
+ errors.push(`subtask[${i}]: must be an object`);
42
+ continue;
43
+ }
44
+ const obj = item;
45
+ let itemValid = true;
46
+ const id = obj["id"];
47
+ if (typeof id !== "string" || id.length === 0) {
48
+ errors.push(`subtask[${i}]: id must be a non-empty string`);
49
+ itemValid = false;
50
+ }
51
+ const description = obj["description"];
52
+ if (typeof description !== "string" || description.length === 0) {
53
+ errors.push(`subtask[${i}]: description must be a non-empty string`);
54
+ itemValid = false;
55
+ }
56
+ const required_capability = obj["required_capability"];
57
+ if (typeof required_capability !== "string" || required_capability.length === 0) {
58
+ errors.push(`subtask[${i}]: required_capability must be a non-empty string`);
59
+ itemValid = false;
60
+ }
61
+ const estimated_credits = obj["estimated_credits"];
62
+ if (estimated_credits !== void 0) {
63
+ if (typeof estimated_credits !== "number" || estimated_credits <= 0) {
64
+ errors.push(`subtask[${i}]: estimated_credits must be a positive number`);
65
+ itemValid = false;
66
+ } else if (estimated_credits > context.max_credits) {
67
+ errors.push(
68
+ `subtask[${i}]: estimated_credits ${estimated_credits} exceeds max_credits ${context.max_credits}`
69
+ );
70
+ itemValid = false;
71
+ }
72
+ }
73
+ if (itemValid) {
74
+ validItems.push(obj);
75
+ validIds.push(id);
76
+ }
77
+ }
78
+ const idSet = /* @__PURE__ */ new Set();
79
+ for (const id of validIds) {
80
+ if (idSet.has(id)) {
81
+ errors.push(`duplicate subtask id: ${id}`);
82
+ } else {
83
+ idSet.add(id);
84
+ }
85
+ }
86
+ for (let i = 0; i < validItems.length; i++) {
87
+ const item = validItems[i];
88
+ const depends_on = item["depends_on"];
89
+ if (!Array.isArray(depends_on)) continue;
90
+ for (const dep of depends_on) {
91
+ if (typeof dep === "string" && !idSet.has(dep)) {
92
+ errors.push(`subtask[${i}]: depends_on references unknown id '${dep}'`);
93
+ }
94
+ }
95
+ }
96
+ if (errors.length === 0 && validItems.length > 0) {
97
+ const inDegree = /* @__PURE__ */ new Map();
98
+ const adjList = /* @__PURE__ */ new Map();
99
+ for (const id of validIds) {
100
+ inDegree.set(id, 0);
101
+ adjList.set(id, []);
102
+ }
103
+ for (const item of validItems) {
104
+ const depends_on = item["depends_on"];
105
+ if (!Array.isArray(depends_on)) continue;
106
+ for (const dep of depends_on) {
107
+ if (typeof dep !== "string" || !idSet.has(dep)) continue;
108
+ adjList.get(dep)?.push(item["id"]);
109
+ inDegree.set(item["id"], (inDegree.get(item["id"]) ?? 0) + 1);
110
+ }
111
+ }
112
+ const queue = [];
113
+ for (const [id, deg] of inDegree) {
114
+ if (deg === 0) queue.push(id);
115
+ }
116
+ let processed = 0;
117
+ while (queue.length > 0) {
118
+ const current = queue.shift();
119
+ processed++;
120
+ for (const neighbor of adjList.get(current) ?? []) {
121
+ const newDeg = (inDegree.get(neighbor) ?? 0) - 1;
122
+ inDegree.set(neighbor, newDeg);
123
+ if (newDeg === 0) queue.push(neighbor);
124
+ }
125
+ }
126
+ if (processed < validItems.length) {
127
+ for (const [id, deg] of inDegree) {
128
+ if (deg > 0) {
129
+ errors.push(`circular dependency detected involving subtask id: ${id}`);
130
+ break;
131
+ }
132
+ }
133
+ }
134
+ }
135
+ if (errors.length > 0) {
136
+ return { valid: [], errors };
137
+ }
138
+ const normalized = validItems.map((item) => {
139
+ const depends_on = Array.isArray(item["depends_on"]) ? item["depends_on"].filter((x) => typeof x === "string") : [];
140
+ const params = typeof item["params"] === "object" && item["params"] !== null && !Array.isArray(item["params"]) ? item["params"] : {};
141
+ const estimated_credits = typeof item["estimated_credits"] === "number" ? item["estimated_credits"] : 0;
142
+ return {
143
+ id: item["id"],
144
+ description: item["description"],
145
+ required_capability: item["required_capability"],
146
+ params,
147
+ depends_on,
148
+ estimated_credits
149
+ };
150
+ });
151
+ return { valid: normalized, errors: [] };
152
+ }
153
+
154
+ // src/conductor/task-decomposer.ts
16
155
  var TEMPLATES = {
17
156
  "video-production": {
18
157
  keywords: ["video", "demo", "clip", "animation"],
@@ -150,12 +289,14 @@ function scorePeers(candidates, selfOwner) {
150
289
  const idleRate = internal?.["idle_rate"];
151
290
  return typeof idleRate === "number" ? idleRate : 1;
152
291
  });
292
+ const loadFactors = eligible.map((c) => c.loadFactor ?? 1);
153
293
  const normSuccess = minMaxNormalize(successRates);
154
294
  const normCost = minMaxNormalize(costEfficiencies);
155
295
  const normIdle = minMaxNormalize(idleRates);
296
+ const normLoad = minMaxNormalize(loadFactors);
156
297
  const scored = eligible.map((c, i) => ({
157
298
  ...c,
158
- rawScore: (normSuccess[i] ?? 0) * (normCost[i] ?? 0) * (normIdle[i] ?? 0)
299
+ rawScore: (normSuccess[i] ?? 0) * (normCost[i] ?? 0) * (normIdle[i] ?? 0) * (normLoad[i] ?? 0)
159
300
  }));
160
301
  scored.sort((a, b) => b.rawScore - a.rawScore);
161
302
  return scored;
@@ -362,6 +503,12 @@ function computeWaves(subtasks) {
362
503
  async function orchestrate(opts) {
363
504
  const { subtasks, matches, gatewayToken, resolveAgentUrl, timeoutMs = 3e5, maxBudget, relayClient, requesterOwner } = opts;
364
505
  const startTime = Date.now();
506
+ const teamMemberMap = /* @__PURE__ */ new Map();
507
+ if (opts.team) {
508
+ for (const member of opts.team.matched) {
509
+ teamMemberMap.set(member.subtask.id, member);
510
+ }
511
+ }
365
512
  if (subtasks.length === 0) {
366
513
  return {
367
514
  success: true,
@@ -373,6 +520,7 @@ async function orchestrate(opts) {
373
520
  const results = /* @__PURE__ */ new Map();
374
521
  const errors = [];
375
522
  let totalCredits = 0;
523
+ const traceContext = /* @__PURE__ */ new Map();
376
524
  const waves = computeWaves(subtasks);
377
525
  const subtaskMap = new Map(subtasks.map((s) => [s.id, s]));
378
526
  for (const wave of waves) {
@@ -409,7 +557,11 @@ async function orchestrate(opts) {
409
557
  subtask.params,
410
558
  interpContext
411
559
  );
412
- const primary = resolveAgentUrl(m.selected_agent);
560
+ const teamMember = teamMemberMap.get(taskId);
561
+ const teamId = opts.team?.team_id ?? null;
562
+ const taskCapabilityType = teamMember?.capability_type ?? null;
563
+ const agentOwner = teamMember?.agent ?? m.selected_agent;
564
+ const primary = resolveAgentUrl(agentOwner);
413
565
  try {
414
566
  let res;
415
567
  if (primary.url.startsWith("relay://") && relayClient) {
@@ -430,7 +582,7 @@ async function orchestrate(opts) {
430
582
  timeoutMs
431
583
  });
432
584
  }
433
- return { taskId, result: res, credits: m.credits };
585
+ return { taskId, result: res, credits: m.credits, team_id: teamId, capability_type: taskCapabilityType };
434
586
  } catch (primaryErr) {
435
587
  if (m.alternatives.length > 0) {
436
588
  const alt = m.alternatives[0];
@@ -455,7 +607,7 @@ async function orchestrate(opts) {
455
607
  timeoutMs
456
608
  });
457
609
  }
458
- return { taskId, result: altRes, credits: alt.credits };
610
+ return { taskId, result: altRes, credits: alt.credits, team_id: teamId, capability_type: taskCapabilityType };
459
611
  } catch (altErr) {
460
612
  throw new Error(
461
613
  `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)}`
@@ -470,9 +622,10 @@ async function orchestrate(opts) {
470
622
  );
471
623
  for (const settlement of waveResults) {
472
624
  if (settlement.status === "fulfilled") {
473
- const { taskId, result, credits } = settlement.value;
625
+ const { taskId, result, credits, team_id, capability_type } = settlement.value;
474
626
  results.set(taskId, result);
475
627
  totalCredits += credits;
628
+ traceContext.set(taskId, { team_id: team_id ?? null, capability_type: capability_type ?? null });
476
629
  } else {
477
630
  errors.push(settlement.reason instanceof Error ? settlement.reason.message : String(settlement.reason));
478
631
  }
@@ -483,10 +636,101 @@ async function orchestrate(opts) {
483
636
  results,
484
637
  total_credits: totalCredits,
485
638
  latency_ms: Date.now() - startTime,
486
- errors: errors.length > 0 ? errors : void 0
639
+ errors: errors.length > 0 ? errors : void 0,
640
+ trace: traceContext.size > 0 ? traceContext : void 0
487
641
  };
488
642
  }
489
643
 
644
+ // src/conductor/team-formation.ts
645
+ import { randomUUID as randomUUID2 } from "crypto";
646
+ function selectByStrategy(matches, strategy) {
647
+ if (matches.length === 0) return void 0;
648
+ if (strategy === "balanced") {
649
+ return matches[0];
650
+ }
651
+ if (strategy === "quality_optimized") {
652
+ return matches.reduce((best, m) => m.score > best.score ? m : best, matches[0]);
653
+ }
654
+ return matches.reduce((best, m) => {
655
+ if (m.credits < best.credits) return m;
656
+ if (m.credits === best.credits && m.score > best.score) return m;
657
+ return best;
658
+ }, matches[0]);
659
+ }
660
+ async function formTeam(opts) {
661
+ const { subtasks, strategy, db, conductorOwner, registryUrl } = opts;
662
+ const team_id = randomUUID2();
663
+ if (subtasks.length === 0) {
664
+ return { team_id, strategy, matched: [], unrouted: [] };
665
+ }
666
+ const matched = [];
667
+ const unrouted = [];
668
+ for (const subtask of subtasks) {
669
+ const skillCards = getCardsBySkillCapability(db, subtask.required_capability).filter((c) => c.owner !== conductorOwner);
670
+ if (skillCards.length > 0) {
671
+ const candidates = skillCards.map((card) => {
672
+ const skills = card.skills ?? [];
673
+ const matchingSkill = skills.find(
674
+ (s) => s.capability_type === subtask.required_capability || (s.capability_types ?? []).includes(subtask.required_capability)
675
+ );
676
+ return {
677
+ subtask_id: subtask.id,
678
+ selected_agent: card.owner,
679
+ selected_skill: matchingSkill?.id ?? "",
680
+ selected_card_id: card.id,
681
+ score: 1,
682
+ credits: matchingSkill?.pricing.credits_per_call ?? 0,
683
+ alternatives: []
684
+ };
685
+ });
686
+ const selected2 = selectByStrategy(candidates, strategy);
687
+ matched.push({
688
+ subtask,
689
+ capability_type: subtask.required_capability,
690
+ agent: selected2.selected_agent,
691
+ skill: selected2.selected_skill,
692
+ card_id: selected2.selected_card_id,
693
+ credits: selected2.credits,
694
+ score: selected2.score
695
+ });
696
+ continue;
697
+ }
698
+ const matchResults = await matchSubTasks({
699
+ db,
700
+ subtasks: [subtask],
701
+ conductorOwner,
702
+ registryUrl
703
+ });
704
+ const m = matchResults[0];
705
+ if (!m || m.selected_agent === "") {
706
+ unrouted.push(subtask);
707
+ continue;
708
+ }
709
+ const allCandidates = [
710
+ m,
711
+ ...m.alternatives.map((alt) => ({
712
+ subtask_id: m.subtask_id,
713
+ selected_agent: alt.agent,
714
+ selected_skill: alt.skill,
715
+ score: alt.score,
716
+ credits: alt.credits,
717
+ alternatives: []
718
+ }))
719
+ ];
720
+ const selected = selectByStrategy(allCandidates, strategy);
721
+ matched.push({
722
+ subtask,
723
+ capability_type: subtask.required_capability,
724
+ agent: selected.selected_agent,
725
+ skill: selected.selected_skill,
726
+ card_id: selected === m ? m.selected_card_id : void 0,
727
+ credits: selected.credits,
728
+ score: selected.score
729
+ });
730
+ }
731
+ return { team_id, strategy, matched, unrouted };
732
+ }
733
+
490
734
  // src/conductor/conductor-mode.ts
491
735
  var ConductorMode = class {
492
736
  db;
@@ -525,7 +769,48 @@ var ConductorMode = class {
525
769
  error: 'Missing or empty "task" parameter'
526
770
  };
527
771
  }
528
- const subtasks = decompose(task);
772
+ const orchestrationDepth = typeof params.orchestration_depth === "number" ? params.orchestration_depth : 0;
773
+ const decompositionDepth = typeof params.decomposition_depth === "number" ? params.decomposition_depth : 0;
774
+ if (orchestrationDepth >= 2) {
775
+ return {
776
+ success: false,
777
+ error: "orchestration_depth limit exceeded: max 1 nested orchestration"
778
+ };
779
+ }
780
+ let subtasks = [];
781
+ if (decompositionDepth === 0) {
782
+ const allDecomposers = getCardsByCapabilityType(this.db, "task_decomposition");
783
+ const externalDecomposers = allDecomposers.filter((c) => c.owner !== this.conductorOwner);
784
+ if (externalDecomposers.length > 0) {
785
+ const provider = externalDecomposers[0];
786
+ try {
787
+ const providerUrl = this.resolveAgentUrl(provider.owner);
788
+ const response = await requestCapability({
789
+ gatewayUrl: providerUrl.url,
790
+ token: this.gatewayToken,
791
+ cardId: provider.id,
792
+ params: {
793
+ task,
794
+ decomposition_depth: decompositionDepth + 1,
795
+ orchestration_depth: orchestrationDepth + 1
796
+ },
797
+ timeoutMs: 3e4
798
+ });
799
+ if (Array.isArray(response)) {
800
+ const validation = validateAndNormalizeSubtasks(response, {
801
+ max_credits: this.maxBudget
802
+ });
803
+ if (validation.errors.length === 0) {
804
+ subtasks = validation.valid;
805
+ }
806
+ }
807
+ } catch {
808
+ }
809
+ }
810
+ }
811
+ if (subtasks.length === 0) {
812
+ subtasks = decompose(task);
813
+ }
529
814
  if (subtasks.length === 0) {
530
815
  return {
531
816
  success: false,
@@ -539,6 +824,17 @@ var ConductorMode = class {
539
824
  conductorOwner: this.conductorOwner
540
825
  });
541
826
  onProgress?.({ step: 2, total: 5, message: `Matched ${matchResults.length} sub-tasks to agents` });
827
+ let team;
828
+ if (conductorSkill === "orchestrate") {
829
+ const strategy = typeof params.formation_strategy === "string" && ["cost_optimized", "quality_optimized", "balanced"].includes(params.formation_strategy) ? params.formation_strategy : "balanced";
830
+ team = await formTeam({
831
+ subtasks,
832
+ strategy,
833
+ db: this.db,
834
+ conductorOwner: this.conductorOwner
835
+ });
836
+ onProgress?.({ step: 2, total: 5, message: `Formed team: ${team.matched.length} members, ${team.unrouted.length} unrouted` });
837
+ }
542
838
  const budgetManager = new BudgetManager(this.creditDb, this.conductorOwner);
543
839
  const budgetController = new BudgetController(budgetManager, this.maxBudget);
544
840
  const executionBudget = budgetController.calculateBudget(matchResults);
@@ -555,7 +851,9 @@ var ConductorMode = class {
555
851
  result: {
556
852
  subtasks,
557
853
  matches: matchResults,
558
- budget: executionBudget
854
+ budget: executionBudget,
855
+ team
856
+ // undefined when no role hints
559
857
  }
560
858
  };
561
859
  }
@@ -567,7 +865,8 @@ var ConductorMode = class {
567
865
  matches: matchMap,
568
866
  gatewayToken: this.gatewayToken,
569
867
  resolveAgentUrl: this.resolveAgentUrl,
570
- maxBudget: this.maxBudget
868
+ maxBudget: this.maxBudget,
869
+ team
571
870
  });
572
871
  onProgress?.({ step: 4, total: 5, message: "Pipeline execution complete" });
573
872
  const resultObj = {};