agentbnb 5.1.11 → 6.0.0

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 (48) hide show
  1. package/dist/{card-RSGDCHCV.js → card-REW7BSWW.js} +1 -1
  2. package/dist/{chunk-EPIWHNB2.js → chunk-2TLZ6G2B.js} +446 -373
  3. package/dist/{chunk-WGZ5AGOX.js → chunk-3CIMVISQ.js} +24 -1
  4. package/dist/{chunk-NH2FIERR.js → chunk-574W3HHE.js} +1 -1
  5. package/dist/{chunk-B5FTAGFN.js → chunk-7XHDSWRD.js} +75 -75
  6. package/dist/{chunk-NLAWT4DT.js → chunk-7YLFLC5C.js} +6 -6
  7. package/dist/chunk-BP3L2TET.js +148 -0
  8. package/dist/{chunk-EGUOAHCW.js → chunk-C2T4BMRW.js} +12 -12
  9. package/dist/{chunk-5KFI5X7B.js → chunk-F53QQIM2.js} +1 -1
  10. package/dist/chunk-JR6TJDIF.js +425 -0
  11. package/dist/{chunk-DFBX3BBD.js → chunk-KA2VIEGM.js} +211 -16
  12. package/dist/chunk-NQTE577Q.js +159 -0
  13. package/dist/{chunk-WTXRY7R2.js → chunk-NYV3NE5Z.js} +157 -9
  14. package/dist/{chunk-UKT6H7YT.js → chunk-OZXCRLP3.js} +1 -1
  15. package/dist/{chunk-QITOPASZ.js → chunk-PSQHUZ7X.js} +1 -1
  16. package/dist/{chunk-EANI2N2V.js → chunk-RVYQSC6L.js} +2 -99
  17. package/dist/{chunk-MLS6IGGG.js → chunk-TQDV254A.js} +1 -1
  18. package/dist/{chunk-QQFBFV4V.js → chunk-TR6UZDNX.js} +57 -18
  19. package/dist/{chunk-ZX5623ER.js → chunk-VMH2YS2I.js} +1 -1
  20. package/dist/{chunk-XND2DWTZ.js → chunk-VPQ44XKE.js} +2 -2
  21. package/dist/{chunk-CSATDXZC.js → chunk-Y7T6IMM3.js} +1 -1
  22. package/dist/{chunk-FLY3WIQR.js → chunk-YRRVFTDR.js} +3 -3
  23. package/dist/cli/index.js +261 -125
  24. package/dist/{client-T5MTY3CS.js → client-HRYRJKSA.js} +3 -3
  25. package/dist/{conduct-WU3VEXB6.js → conduct-LF6FYPLD.js} +11 -11
  26. package/dist/conduct-QAFZIEY6.js +21 -0
  27. package/dist/{conductor-mode-ZMTFZGJP.js → conductor-mode-NUDQLZFM.js} +309 -13
  28. package/dist/conductor-mode-YQ6QSPPT.js +275 -0
  29. package/dist/{execute-4D4ITQCL.js → execute-ITHIYYOX.js} +4 -3
  30. package/dist/execute-PNJFABVJ.js +14 -0
  31. package/dist/index.d.ts +555 -0
  32. package/dist/index.js +592 -83
  33. package/dist/{process-guard-CC7CNRQJ.js → process-guard-QCCBGILS.js} +1 -1
  34. package/dist/publish-capability-TS6CNR5G.js +12 -0
  35. package/dist/{request-VOXBFUOG.js → request-P6QCTCCG.js} +14 -14
  36. package/dist/{serve-skill-IH7UAJNR.js → serve-skill-EZOL7UYN.js} +10 -9
  37. package/dist/{server-JVQW2TID.js → server-3G6ZTASA.js} +16 -16
  38. package/dist/{service-coordinator-EYRDTHL5.js → service-coordinator-CRSE4GWC.js} +174 -242
  39. package/dist/skill-config-4W5W5O6T.js +22 -0
  40. package/dist/skills/agentbnb/bootstrap.js +227 -67
  41. package/package.json +1 -1
  42. package/skills/agentbnb/SKILL.md +35 -0
  43. package/skills/agentbnb/bootstrap.ts +126 -8
  44. package/skills/agentbnb/install.sh +49 -9
  45. package/dist/chunk-CRFCWD6V.js +0 -366
  46. package/dist/conduct-6LKIJJKQ.js +0 -21
  47. package/dist/conductor-mode-Q4IIDY5E.js +0 -123
  48. package/dist/execute-T7Y6RKSW.js +0 -13
@@ -3,16 +3,154 @@ import {
3
3
  interpolateObject,
4
4
  requestCapability,
5
5
  searchCards
6
- } from "./chunk-B5FTAGFN.js";
6
+ } from "./chunk-7XHDSWRD.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-2TLZ6G2B.js";
13
+ import "./chunk-IVOYM3WG.js";
14
+ import "./chunk-3CIMVISQ.js";
13
15
 
14
16
  // src/conductor/task-decomposer.ts
15
17
  import { randomUUID } from "crypto";
18
+
19
+ // src/conductor/decomposition-validator.ts
20
+ function validateAndNormalizeSubtasks(raw, context) {
21
+ try {
22
+ return _validate(raw, context);
23
+ } catch {
24
+ return { valid: [], errors: ["internal validation error"] };
25
+ }
26
+ }
27
+ function _validate(raw, context) {
28
+ if (!Array.isArray(raw)) {
29
+ return { valid: [], errors: ["decomposition output must be an array"] };
30
+ }
31
+ if (raw.length === 0) {
32
+ return { valid: [], errors: [] };
33
+ }
34
+ const errors = [];
35
+ const validItems = [];
36
+ const validIds = [];
37
+ for (let i = 0; i < raw.length; i++) {
38
+ const item = raw[i];
39
+ if (typeof item !== "object" || item === null || Array.isArray(item)) {
40
+ errors.push(`subtask[${i}]: must be an object`);
41
+ continue;
42
+ }
43
+ const obj = item;
44
+ let itemValid = true;
45
+ const id = obj["id"];
46
+ if (typeof id !== "string" || id.length === 0) {
47
+ errors.push(`subtask[${i}]: id must be a non-empty string`);
48
+ itemValid = false;
49
+ }
50
+ const description = obj["description"];
51
+ if (typeof description !== "string" || description.length === 0) {
52
+ errors.push(`subtask[${i}]: description must be a non-empty string`);
53
+ itemValid = false;
54
+ }
55
+ const required_capability = obj["required_capability"];
56
+ if (typeof required_capability !== "string" || required_capability.length === 0) {
57
+ errors.push(`subtask[${i}]: required_capability must be a non-empty string`);
58
+ itemValid = false;
59
+ }
60
+ const estimated_credits = obj["estimated_credits"];
61
+ if (estimated_credits !== void 0) {
62
+ if (typeof estimated_credits !== "number" || estimated_credits <= 0) {
63
+ errors.push(`subtask[${i}]: estimated_credits must be a positive number`);
64
+ itemValid = false;
65
+ } else if (estimated_credits > context.max_credits) {
66
+ errors.push(
67
+ `subtask[${i}]: estimated_credits ${estimated_credits} exceeds max_credits ${context.max_credits}`
68
+ );
69
+ itemValid = false;
70
+ }
71
+ }
72
+ if (itemValid) {
73
+ validItems.push(obj);
74
+ validIds.push(id);
75
+ }
76
+ }
77
+ const idSet = /* @__PURE__ */ new Set();
78
+ for (const id of validIds) {
79
+ if (idSet.has(id)) {
80
+ errors.push(`duplicate subtask id: ${id}`);
81
+ } else {
82
+ idSet.add(id);
83
+ }
84
+ }
85
+ for (let i = 0; i < validItems.length; i++) {
86
+ const item = validItems[i];
87
+ const depends_on = item["depends_on"];
88
+ if (!Array.isArray(depends_on)) continue;
89
+ for (const dep of depends_on) {
90
+ if (typeof dep === "string" && !idSet.has(dep)) {
91
+ errors.push(`subtask[${i}]: depends_on references unknown id '${dep}'`);
92
+ }
93
+ }
94
+ }
95
+ if (errors.length === 0 && validItems.length > 0) {
96
+ const inDegree = /* @__PURE__ */ new Map();
97
+ const adjList = /* @__PURE__ */ new Map();
98
+ for (const id of validIds) {
99
+ inDegree.set(id, 0);
100
+ adjList.set(id, []);
101
+ }
102
+ for (const item of validItems) {
103
+ const depends_on = item["depends_on"];
104
+ if (!Array.isArray(depends_on)) continue;
105
+ for (const dep of depends_on) {
106
+ if (typeof dep !== "string" || !idSet.has(dep)) continue;
107
+ adjList.get(dep)?.push(item["id"]);
108
+ inDegree.set(item["id"], (inDegree.get(item["id"]) ?? 0) + 1);
109
+ }
110
+ }
111
+ const queue = [];
112
+ for (const [id, deg] of inDegree) {
113
+ if (deg === 0) queue.push(id);
114
+ }
115
+ let processed = 0;
116
+ while (queue.length > 0) {
117
+ const current = queue.shift();
118
+ processed++;
119
+ for (const neighbor of adjList.get(current) ?? []) {
120
+ const newDeg = (inDegree.get(neighbor) ?? 0) - 1;
121
+ inDegree.set(neighbor, newDeg);
122
+ if (newDeg === 0) queue.push(neighbor);
123
+ }
124
+ }
125
+ if (processed < validItems.length) {
126
+ for (const [id, deg] of inDegree) {
127
+ if (deg > 0) {
128
+ errors.push(`circular dependency detected involving subtask id: ${id}`);
129
+ break;
130
+ }
131
+ }
132
+ }
133
+ }
134
+ if (errors.length > 0) {
135
+ return { valid: [], errors };
136
+ }
137
+ const normalized = validItems.map((item) => {
138
+ const depends_on = Array.isArray(item["depends_on"]) ? item["depends_on"].filter((x) => typeof x === "string") : [];
139
+ const params = typeof item["params"] === "object" && item["params"] !== null && !Array.isArray(item["params"]) ? item["params"] : {};
140
+ const estimated_credits = typeof item["estimated_credits"] === "number" ? item["estimated_credits"] : 0;
141
+ return {
142
+ id: item["id"],
143
+ description: item["description"],
144
+ required_capability: item["required_capability"],
145
+ params,
146
+ depends_on,
147
+ estimated_credits
148
+ };
149
+ });
150
+ return { valid: normalized, errors: [] };
151
+ }
152
+
153
+ // src/conductor/task-decomposer.ts
16
154
  var TEMPLATES = {
17
155
  "video-production": {
18
156
  keywords: ["video", "demo", "clip", "animation"],
@@ -362,6 +500,12 @@ function computeWaves(subtasks) {
362
500
  async function orchestrate(opts) {
363
501
  const { subtasks, matches, gatewayToken, resolveAgentUrl, timeoutMs = 3e5, maxBudget, relayClient, requesterOwner } = opts;
364
502
  const startTime = Date.now();
503
+ const teamMemberMap = /* @__PURE__ */ new Map();
504
+ if (opts.team) {
505
+ for (const member of opts.team.matched) {
506
+ teamMemberMap.set(member.subtask.id, member);
507
+ }
508
+ }
365
509
  if (subtasks.length === 0) {
366
510
  return {
367
511
  success: true,
@@ -373,6 +517,7 @@ async function orchestrate(opts) {
373
517
  const results = /* @__PURE__ */ new Map();
374
518
  const errors = [];
375
519
  let totalCredits = 0;
520
+ const traceContext = /* @__PURE__ */ new Map();
376
521
  const waves = computeWaves(subtasks);
377
522
  const subtaskMap = new Map(subtasks.map((s) => [s.id, s]));
378
523
  for (const wave of waves) {
@@ -409,7 +554,11 @@ async function orchestrate(opts) {
409
554
  subtask.params,
410
555
  interpContext
411
556
  );
412
- const primary = resolveAgentUrl(m.selected_agent);
557
+ const teamMember = teamMemberMap.get(taskId);
558
+ const teamId = opts.team?.team_id ?? null;
559
+ const taskCapabilityType = teamMember?.capability_type ?? null;
560
+ const agentOwner = teamMember?.agent ?? m.selected_agent;
561
+ const primary = resolveAgentUrl(agentOwner);
413
562
  try {
414
563
  let res;
415
564
  if (primary.url.startsWith("relay://") && relayClient) {
@@ -430,7 +579,7 @@ async function orchestrate(opts) {
430
579
  timeoutMs
431
580
  });
432
581
  }
433
- return { taskId, result: res, credits: m.credits };
582
+ return { taskId, result: res, credits: m.credits, team_id: teamId, capability_type: taskCapabilityType };
434
583
  } catch (primaryErr) {
435
584
  if (m.alternatives.length > 0) {
436
585
  const alt = m.alternatives[0];
@@ -455,7 +604,7 @@ async function orchestrate(opts) {
455
604
  timeoutMs
456
605
  });
457
606
  }
458
- return { taskId, result: altRes, credits: alt.credits };
607
+ return { taskId, result: altRes, credits: alt.credits, team_id: teamId, capability_type: taskCapabilityType };
459
608
  } catch (altErr) {
460
609
  throw new Error(
461
610
  `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 +619,10 @@ async function orchestrate(opts) {
470
619
  );
471
620
  for (const settlement of waveResults) {
472
621
  if (settlement.status === "fulfilled") {
473
- const { taskId, result, credits } = settlement.value;
622
+ const { taskId, result, credits, team_id, capability_type } = settlement.value;
474
623
  results.set(taskId, result);
475
624
  totalCredits += credits;
625
+ traceContext.set(taskId, { team_id: team_id ?? null, capability_type: capability_type ?? null });
476
626
  } else {
477
627
  errors.push(settlement.reason instanceof Error ? settlement.reason.message : String(settlement.reason));
478
628
  }
@@ -483,10 +633,101 @@ async function orchestrate(opts) {
483
633
  results,
484
634
  total_credits: totalCredits,
485
635
  latency_ms: Date.now() - startTime,
486
- errors: errors.length > 0 ? errors : void 0
636
+ errors: errors.length > 0 ? errors : void 0,
637
+ trace: traceContext.size > 0 ? traceContext : void 0
487
638
  };
488
639
  }
489
640
 
641
+ // src/conductor/team-formation.ts
642
+ import { randomUUID as randomUUID2 } from "crypto";
643
+ function selectByStrategy(matches, strategy) {
644
+ if (matches.length === 0) return void 0;
645
+ if (strategy === "balanced") {
646
+ return matches[0];
647
+ }
648
+ if (strategy === "quality_optimized") {
649
+ return matches.reduce((best, m) => m.score > best.score ? m : best, matches[0]);
650
+ }
651
+ return matches.reduce((best, m) => {
652
+ if (m.credits < best.credits) return m;
653
+ if (m.credits === best.credits && m.score > best.score) return m;
654
+ return best;
655
+ }, matches[0]);
656
+ }
657
+ async function formTeam(opts) {
658
+ const { subtasks, strategy, db, conductorOwner, registryUrl } = opts;
659
+ const team_id = randomUUID2();
660
+ if (subtasks.length === 0) {
661
+ return { team_id, strategy, matched: [], unrouted: [] };
662
+ }
663
+ const matched = [];
664
+ const unrouted = [];
665
+ for (const subtask of subtasks) {
666
+ const skillCards = getCardsBySkillCapability(db, subtask.required_capability).filter((c) => c.owner !== conductorOwner);
667
+ if (skillCards.length > 0) {
668
+ const candidates = skillCards.map((card) => {
669
+ const skills = card.skills ?? [];
670
+ const matchingSkill = skills.find(
671
+ (s) => s.capability_type === subtask.required_capability || (s.capability_types ?? []).includes(subtask.required_capability)
672
+ );
673
+ return {
674
+ subtask_id: subtask.id,
675
+ selected_agent: card.owner,
676
+ selected_skill: matchingSkill?.id ?? "",
677
+ selected_card_id: card.id,
678
+ score: 1,
679
+ credits: matchingSkill?.pricing.credits_per_call ?? 0,
680
+ alternatives: []
681
+ };
682
+ });
683
+ const selected2 = selectByStrategy(candidates, strategy);
684
+ matched.push({
685
+ subtask,
686
+ capability_type: subtask.required_capability,
687
+ agent: selected2.selected_agent,
688
+ skill: selected2.selected_skill,
689
+ card_id: selected2.selected_card_id,
690
+ credits: selected2.credits,
691
+ score: selected2.score
692
+ });
693
+ continue;
694
+ }
695
+ const matchResults = await matchSubTasks({
696
+ db,
697
+ subtasks: [subtask],
698
+ conductorOwner,
699
+ registryUrl
700
+ });
701
+ const m = matchResults[0];
702
+ if (!m || m.selected_agent === "") {
703
+ unrouted.push(subtask);
704
+ continue;
705
+ }
706
+ const allCandidates = [
707
+ m,
708
+ ...m.alternatives.map((alt) => ({
709
+ subtask_id: m.subtask_id,
710
+ selected_agent: alt.agent,
711
+ selected_skill: alt.skill,
712
+ score: alt.score,
713
+ credits: alt.credits,
714
+ alternatives: []
715
+ }))
716
+ ];
717
+ const selected = selectByStrategy(allCandidates, strategy);
718
+ matched.push({
719
+ subtask,
720
+ capability_type: subtask.required_capability,
721
+ agent: selected.selected_agent,
722
+ skill: selected.selected_skill,
723
+ card_id: selected === m ? m.selected_card_id : void 0,
724
+ credits: selected.credits,
725
+ score: selected.score
726
+ });
727
+ }
728
+ return { team_id, strategy, matched, unrouted };
729
+ }
730
+
490
731
  // src/conductor/conductor-mode.ts
491
732
  var ConductorMode = class {
492
733
  db;
@@ -525,7 +766,48 @@ var ConductorMode = class {
525
766
  error: 'Missing or empty "task" parameter'
526
767
  };
527
768
  }
528
- const subtasks = decompose(task);
769
+ const orchestrationDepth = typeof params.orchestration_depth === "number" ? params.orchestration_depth : 0;
770
+ const decompositionDepth = typeof params.decomposition_depth === "number" ? params.decomposition_depth : 0;
771
+ if (orchestrationDepth >= 2) {
772
+ return {
773
+ success: false,
774
+ error: "orchestration_depth limit exceeded: max 1 nested orchestration"
775
+ };
776
+ }
777
+ let subtasks = [];
778
+ if (decompositionDepth === 0) {
779
+ const allDecomposers = getCardsByCapabilityType(this.db, "task_decomposition");
780
+ const externalDecomposers = allDecomposers.filter((c) => c.owner !== this.conductorOwner);
781
+ if (externalDecomposers.length > 0) {
782
+ const provider = externalDecomposers[0];
783
+ try {
784
+ const providerUrl = this.resolveAgentUrl(provider.owner);
785
+ const response = await requestCapability({
786
+ gatewayUrl: providerUrl.url,
787
+ token: this.gatewayToken,
788
+ cardId: provider.id,
789
+ params: {
790
+ task,
791
+ decomposition_depth: decompositionDepth + 1,
792
+ orchestration_depth: orchestrationDepth + 1
793
+ },
794
+ timeoutMs: 3e4
795
+ });
796
+ if (Array.isArray(response)) {
797
+ const validation = validateAndNormalizeSubtasks(response, {
798
+ max_credits: this.maxBudget
799
+ });
800
+ if (validation.errors.length === 0) {
801
+ subtasks = validation.valid;
802
+ }
803
+ }
804
+ } catch {
805
+ }
806
+ }
807
+ }
808
+ if (subtasks.length === 0) {
809
+ subtasks = decompose(task);
810
+ }
529
811
  if (subtasks.length === 0) {
530
812
  return {
531
813
  success: false,
@@ -539,6 +821,17 @@ var ConductorMode = class {
539
821
  conductorOwner: this.conductorOwner
540
822
  });
541
823
  onProgress?.({ step: 2, total: 5, message: `Matched ${matchResults.length} sub-tasks to agents` });
824
+ let team;
825
+ if (conductorSkill === "orchestrate") {
826
+ const strategy = typeof params.formation_strategy === "string" && ["cost_optimized", "quality_optimized", "balanced"].includes(params.formation_strategy) ? params.formation_strategy : "balanced";
827
+ team = await formTeam({
828
+ subtasks,
829
+ strategy,
830
+ db: this.db,
831
+ conductorOwner: this.conductorOwner
832
+ });
833
+ onProgress?.({ step: 2, total: 5, message: `Formed team: ${team.matched.length} members, ${team.unrouted.length} unrouted` });
834
+ }
542
835
  const budgetManager = new BudgetManager(this.creditDb, this.conductorOwner);
543
836
  const budgetController = new BudgetController(budgetManager, this.maxBudget);
544
837
  const executionBudget = budgetController.calculateBudget(matchResults);
@@ -555,7 +848,9 @@ var ConductorMode = class {
555
848
  result: {
556
849
  subtasks,
557
850
  matches: matchResults,
558
- budget: executionBudget
851
+ budget: executionBudget,
852
+ team
853
+ // undefined when no role hints
559
854
  }
560
855
  };
561
856
  }
@@ -567,7 +862,8 @@ var ConductorMode = class {
567
862
  matches: matchMap,
568
863
  gatewayToken: this.gatewayToken,
569
864
  resolveAgentUrl: this.resolveAgentUrl,
570
- maxBudget: this.maxBudget
865
+ maxBudget: this.maxBudget,
866
+ team
571
867
  });
572
868
  onProgress?.({ step: 4, total: 5, message: "Pipeline execution complete" });
573
869
  const resultObj = {};
@@ -0,0 +1,275 @@
1
+ import {
2
+ BudgetController,
3
+ decompose,
4
+ matchSubTasks,
5
+ orchestrate,
6
+ validateAndNormalizeSubtasks
7
+ } from "./chunk-NYV3NE5Z.js";
8
+ import "./chunk-3MJT4PZG.js";
9
+ import {
10
+ BudgetManager
11
+ } from "./chunk-C2T4BMRW.js";
12
+ import "./chunk-VMH2YS2I.js";
13
+ import "./chunk-Y7T6IMM3.js";
14
+ import "./chunk-574W3HHE.js";
15
+ import "./chunk-RVYQSC6L.js";
16
+ import {
17
+ requestCapability
18
+ } from "./chunk-VPQ44XKE.js";
19
+ import "./chunk-F53QQIM2.js";
20
+ import "./chunk-5AH3CMOX.js";
21
+ import "./chunk-75OC6E4F.js";
22
+ import {
23
+ getCardsByCapabilityType,
24
+ getCardsBySkillCapability
25
+ } from "./chunk-KA2VIEGM.js";
26
+ import "./chunk-3CIMVISQ.js";
27
+
28
+ // src/conductor/team-formation.ts
29
+ import { randomUUID } from "crypto";
30
+ function selectByStrategy(matches, strategy) {
31
+ if (matches.length === 0) return void 0;
32
+ if (strategy === "balanced") {
33
+ return matches[0];
34
+ }
35
+ if (strategy === "quality_optimized") {
36
+ return matches.reduce((best, m) => m.score > best.score ? m : best, matches[0]);
37
+ }
38
+ return matches.reduce((best, m) => {
39
+ if (m.credits < best.credits) return m;
40
+ if (m.credits === best.credits && m.score > best.score) return m;
41
+ return best;
42
+ }, matches[0]);
43
+ }
44
+ async function formTeam(opts) {
45
+ const { subtasks, strategy, db, conductorOwner, registryUrl } = opts;
46
+ const team_id = randomUUID();
47
+ if (subtasks.length === 0) {
48
+ return { team_id, strategy, matched: [], unrouted: [] };
49
+ }
50
+ const matched = [];
51
+ const unrouted = [];
52
+ for (const subtask of subtasks) {
53
+ const skillCards = getCardsBySkillCapability(db, subtask.required_capability).filter((c) => c.owner !== conductorOwner);
54
+ if (skillCards.length > 0) {
55
+ const candidates = skillCards.map((card) => {
56
+ const skills = card.skills ?? [];
57
+ const matchingSkill = skills.find(
58
+ (s) => s.capability_type === subtask.required_capability || (s.capability_types ?? []).includes(subtask.required_capability)
59
+ );
60
+ return {
61
+ subtask_id: subtask.id,
62
+ selected_agent: card.owner,
63
+ selected_skill: matchingSkill?.id ?? "",
64
+ selected_card_id: card.id,
65
+ score: 1,
66
+ credits: matchingSkill?.pricing.credits_per_call ?? 0,
67
+ alternatives: []
68
+ };
69
+ });
70
+ const selected2 = selectByStrategy(candidates, strategy);
71
+ matched.push({
72
+ subtask,
73
+ capability_type: subtask.required_capability,
74
+ agent: selected2.selected_agent,
75
+ skill: selected2.selected_skill,
76
+ card_id: selected2.selected_card_id,
77
+ credits: selected2.credits,
78
+ score: selected2.score
79
+ });
80
+ continue;
81
+ }
82
+ const matchResults = await matchSubTasks({
83
+ db,
84
+ subtasks: [subtask],
85
+ conductorOwner,
86
+ registryUrl
87
+ });
88
+ const m = matchResults[0];
89
+ if (!m || m.selected_agent === "") {
90
+ unrouted.push(subtask);
91
+ continue;
92
+ }
93
+ const allCandidates = [
94
+ m,
95
+ ...m.alternatives.map((alt) => ({
96
+ subtask_id: m.subtask_id,
97
+ selected_agent: alt.agent,
98
+ selected_skill: alt.skill,
99
+ score: alt.score,
100
+ credits: alt.credits,
101
+ alternatives: []
102
+ }))
103
+ ];
104
+ const selected = selectByStrategy(allCandidates, strategy);
105
+ matched.push({
106
+ subtask,
107
+ capability_type: subtask.required_capability,
108
+ agent: selected.selected_agent,
109
+ skill: selected.selected_skill,
110
+ card_id: selected === m ? m.selected_card_id : void 0,
111
+ credits: selected.credits,
112
+ score: selected.score
113
+ });
114
+ }
115
+ return { team_id, strategy, matched, unrouted };
116
+ }
117
+
118
+ // src/conductor/conductor-mode.ts
119
+ var ConductorMode = class {
120
+ db;
121
+ creditDb;
122
+ conductorOwner;
123
+ gatewayToken;
124
+ resolveAgentUrl;
125
+ maxBudget;
126
+ constructor(opts) {
127
+ this.db = opts.db;
128
+ this.creditDb = opts.creditDb;
129
+ this.conductorOwner = opts.conductorOwner;
130
+ this.gatewayToken = opts.gatewayToken;
131
+ this.resolveAgentUrl = opts.resolveAgentUrl;
132
+ this.maxBudget = opts.maxBudget ?? 100;
133
+ }
134
+ /**
135
+ * Execute a conductor skill with the given config and params.
136
+ *
137
+ * @param config - SkillConfig with type 'conductor' and conductor_skill field.
138
+ * @param params - Must include `task` string.
139
+ * @returns Execution result without latency_ms (added by SkillExecutor).
140
+ */
141
+ async execute(config, params, onProgress) {
142
+ const conductorSkill = config.conductor_skill;
143
+ if (conductorSkill !== "orchestrate" && conductorSkill !== "plan") {
144
+ return {
145
+ success: false,
146
+ error: `Unknown conductor skill: "${conductorSkill}"`
147
+ };
148
+ }
149
+ const task = params.task;
150
+ if (typeof task !== "string" || task.length === 0) {
151
+ return {
152
+ success: false,
153
+ error: 'Missing or empty "task" parameter'
154
+ };
155
+ }
156
+ const orchestrationDepth = typeof params.orchestration_depth === "number" ? params.orchestration_depth : 0;
157
+ const decompositionDepth = typeof params.decomposition_depth === "number" ? params.decomposition_depth : 0;
158
+ if (orchestrationDepth >= 2) {
159
+ return {
160
+ success: false,
161
+ error: "orchestration_depth limit exceeded: max 1 nested orchestration"
162
+ };
163
+ }
164
+ let subtasks = [];
165
+ if (decompositionDepth === 0) {
166
+ const allDecomposers = getCardsByCapabilityType(this.db, "task_decomposition");
167
+ const externalDecomposers = allDecomposers.filter((c) => c.owner !== this.conductorOwner);
168
+ if (externalDecomposers.length > 0) {
169
+ const provider = externalDecomposers[0];
170
+ try {
171
+ const providerUrl = this.resolveAgentUrl(provider.owner);
172
+ const response = await requestCapability({
173
+ gatewayUrl: providerUrl.url,
174
+ token: this.gatewayToken,
175
+ cardId: provider.id,
176
+ params: {
177
+ task,
178
+ decomposition_depth: decompositionDepth + 1,
179
+ orchestration_depth: orchestrationDepth + 1
180
+ },
181
+ timeoutMs: 3e4
182
+ });
183
+ if (Array.isArray(response)) {
184
+ const validation = validateAndNormalizeSubtasks(response, {
185
+ max_credits: this.maxBudget
186
+ });
187
+ if (validation.errors.length === 0) {
188
+ subtasks = validation.valid;
189
+ }
190
+ }
191
+ } catch {
192
+ }
193
+ }
194
+ }
195
+ if (subtasks.length === 0) {
196
+ subtasks = decompose(task);
197
+ }
198
+ if (subtasks.length === 0) {
199
+ return {
200
+ success: false,
201
+ error: "No template matches task"
202
+ };
203
+ }
204
+ onProgress?.({ step: 1, total: 5, message: `Decomposed into ${subtasks.length} sub-tasks` });
205
+ const matchResults = await matchSubTasks({
206
+ db: this.db,
207
+ subtasks,
208
+ conductorOwner: this.conductorOwner
209
+ });
210
+ onProgress?.({ step: 2, total: 5, message: `Matched ${matchResults.length} sub-tasks to agents` });
211
+ let team;
212
+ if (conductorSkill === "orchestrate") {
213
+ const strategy = typeof params.formation_strategy === "string" && ["cost_optimized", "quality_optimized", "balanced"].includes(params.formation_strategy) ? params.formation_strategy : "balanced";
214
+ team = await formTeam({
215
+ subtasks,
216
+ strategy,
217
+ db: this.db,
218
+ conductorOwner: this.conductorOwner
219
+ });
220
+ onProgress?.({ step: 2, total: 5, message: `Formed team: ${team.matched.length} members, ${team.unrouted.length} unrouted` });
221
+ }
222
+ const budgetManager = new BudgetManager(this.creditDb, this.conductorOwner);
223
+ const budgetController = new BudgetController(budgetManager, this.maxBudget);
224
+ const executionBudget = budgetController.calculateBudget(matchResults);
225
+ if (!budgetController.canExecute(executionBudget)) {
226
+ return {
227
+ success: false,
228
+ error: `Budget exceeded: estimated ${executionBudget.estimated_total} cr, max ${this.maxBudget} cr`
229
+ };
230
+ }
231
+ onProgress?.({ step: 3, total: 5, message: `Budget approved: ${executionBudget.estimated_total} cr` });
232
+ if (conductorSkill === "plan") {
233
+ return {
234
+ success: true,
235
+ result: {
236
+ subtasks,
237
+ matches: matchResults,
238
+ budget: executionBudget,
239
+ team
240
+ // undefined when no role hints
241
+ }
242
+ };
243
+ }
244
+ const matchMap = new Map(
245
+ matchResults.map((m) => [m.subtask_id, m])
246
+ );
247
+ const orchResult = await orchestrate({
248
+ subtasks,
249
+ matches: matchMap,
250
+ gatewayToken: this.gatewayToken,
251
+ resolveAgentUrl: this.resolveAgentUrl,
252
+ maxBudget: this.maxBudget,
253
+ team
254
+ });
255
+ onProgress?.({ step: 4, total: 5, message: "Pipeline execution complete" });
256
+ const resultObj = {};
257
+ for (const [key, value] of orchResult.results) {
258
+ resultObj[key] = value;
259
+ }
260
+ return {
261
+ success: orchResult.success,
262
+ result: {
263
+ plan: subtasks,
264
+ execution: resultObj,
265
+ total_credits: orchResult.total_credits,
266
+ latency_ms: orchResult.latency_ms,
267
+ errors: orchResult.errors
268
+ },
269
+ error: orchResult.success ? void 0 : orchResult.errors?.join("; ")
270
+ };
271
+ }
272
+ };
273
+ export {
274
+ ConductorMode
275
+ };
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  executeCapabilityBatch,
3
3
  executeCapabilityRequest
4
- } from "./chunk-EPIWHNB2.js";
5
- import "./chunk-CRFCWD6V.js";
6
- import "./chunk-WGZ5AGOX.js";
4
+ } from "./chunk-JR6TJDIF.js";
5
+ import "./chunk-2TLZ6G2B.js";
6
+ import "./chunk-IVOYM3WG.js";
7
+ import "./chunk-3CIMVISQ.js";
7
8
  export {
8
9
  executeCapabilityBatch,
9
10
  executeCapabilityRequest