@lov3kaizen/agentsea-crews 1.0.1 → 1.1.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.
package/dist/index.js CHANGED
@@ -77,6 +77,7 @@ __export(index_exports, {
77
77
  createConflictResolver: () => createConflictResolver,
78
78
  createConsensusStrategy: () => createConsensusStrategy,
79
79
  createConversationHistory: () => createConversationHistory,
80
+ createCoreExecutor: () => createCoreExecutor,
80
81
  createCrew: () => createCrew,
81
82
  createCrewAgent: () => createCrewAgent,
82
83
  createCustomerSupportCrew: () => createCustomerSupportCrew,
@@ -1515,7 +1516,80 @@ var AgentCapabilities = class {
1515
1516
  }
1516
1517
  };
1517
1518
 
1519
+ // src/agents/CoreExecutor.ts
1520
+ async function loadProvider(providerName) {
1521
+ const ctorName = resolveProviderCtorName(providerName);
1522
+ let core;
1523
+ try {
1524
+ core = await import("@lov3kaizen/agentsea-core");
1525
+ } catch {
1526
+ throw new Error(
1527
+ 'CrewAgent requires "@lov3kaizen/agentsea-core" to execute against a real LLM. Install it, or pass a custom `execute` function (or `mock: true`) to createCrewAgent / createCrew.'
1528
+ );
1529
+ }
1530
+ const Ctor = core[ctorName];
1531
+ return new Ctor();
1532
+ }
1533
+ function resolveProviderCtorName(providerName) {
1534
+ switch ((providerName ?? "").toLowerCase()) {
1535
+ case "anthropic":
1536
+ case "claude":
1537
+ return "AnthropicProvider";
1538
+ case "openai":
1539
+ case "gpt":
1540
+ return "OpenAIProvider";
1541
+ case "gemini":
1542
+ case "google":
1543
+ return "GeminiProvider";
1544
+ case "ollama":
1545
+ return "OllamaProvider";
1546
+ default:
1547
+ throw new Error(
1548
+ `CrewAgent: unsupported provider "${providerName}". Supported providers are: anthropic, openai, gemini, ollama. Pass a custom \`execute\` function to createCrewAgent for any other provider.`
1549
+ );
1550
+ }
1551
+ }
1552
+ function createCoreExecutor(config, options = {}) {
1553
+ let providerPromise;
1554
+ const getProvider = () => {
1555
+ if (!providerPromise) {
1556
+ providerPromise = options.provider ? Promise.resolve(options.provider) : loadProvider(config.provider);
1557
+ }
1558
+ return providerPromise;
1559
+ };
1560
+ return async (input, systemPrompt) => {
1561
+ const provider = await getProvider();
1562
+ const start = Date.now();
1563
+ const response = await provider.generateResponse(
1564
+ [{ role: "user", content: input }],
1565
+ {
1566
+ model: config.model,
1567
+ systemPrompt,
1568
+ temperature: config.temperature,
1569
+ maxTokens: config.maxTokens
1570
+ }
1571
+ );
1572
+ return {
1573
+ output: response.content,
1574
+ tokensUsed: response.usage.inputTokens + response.usage.outputTokens,
1575
+ latencyMs: Date.now() - start,
1576
+ iterations: 1
1577
+ };
1578
+ };
1579
+ }
1580
+
1518
1581
  // src/agents/CrewAgent.ts
1582
+ function modelCostWeight(model) {
1583
+ const m = (model ?? "").toLowerCase();
1584
+ if (m.includes("opus") || m.includes("gpt-5") || m.includes("o3")) return 5;
1585
+ if (m.includes("sonnet") || m.includes("gpt-4.1") || m.includes("gpt-4") && !m.includes("mini") || m.includes("gemini-1.5-pro") || m.includes("gemini-2.5-pro")) {
1586
+ return 3;
1587
+ }
1588
+ if (m.includes("haiku") || m.includes("mini") || m.includes("flash") || m.includes("llama") || m.includes("mistral")) {
1589
+ return 1;
1590
+ }
1591
+ return 3;
1592
+ }
1519
1593
  var CrewAgent = class _CrewAgent {
1520
1594
  id;
1521
1595
  name;
@@ -1554,10 +1628,11 @@ var CrewAgent = class _CrewAgent {
1554
1628
  */
1555
1629
  async execute(input) {
1556
1630
  if (!this.executeFunc) {
1631
+ const tokensUsed = 100 + Math.min(input.length, 400);
1557
1632
  const mockResult = {
1558
1633
  output: `[Mock response from ${this.name}]: ${input.slice(0, 100)}...`,
1559
- tokensUsed: Math.floor(Math.random() * 500) + 100,
1560
- latencyMs: Math.floor(Math.random() * 2e3) + 500,
1634
+ tokensUsed,
1635
+ latencyMs: 0,
1561
1636
  iterations: 1
1562
1637
  };
1563
1638
  this.totalTokensUsed += mockResult.tokensUsed;
@@ -1660,16 +1735,27 @@ ${JSON.stringify(task.context, null, 2)}`);
1660
1735
  ) ?? true
1661
1736
  ).map((c) => c.name);
1662
1737
  const estimatedTime = this.estimateTaskTime(task);
1738
+ const estimatedCost = this.estimateTaskCost(estimatedTime);
1663
1739
  const reasoning = this.generateBidReasoning(task, confidence, matchedCaps);
1664
1740
  return Promise.resolve({
1665
1741
  agentName: this.name,
1666
1742
  taskId: task.id ?? "unknown",
1667
1743
  confidence,
1668
1744
  estimatedTime,
1745
+ estimatedCost,
1669
1746
  reasoning,
1670
1747
  capabilities: matchedCaps
1671
1748
  });
1672
1749
  }
1750
+ /**
1751
+ * Estimate a relative cost for handling a task. Combines the agent's model
1752
+ * price tier with the estimated effort so the auction `cheapest` criterion
1753
+ * can distinguish a cheap-but-slower model from an expensive-but-faster one.
1754
+ * The unit is arbitrary and only meaningful relative to other bids.
1755
+ */
1756
+ estimateTaskCost(estimatedTime) {
1757
+ return modelCostWeight(this.model) * Math.max(estimatedTime, 1);
1758
+ }
1673
1759
  /**
1674
1760
  * Check if agent has all required capabilities
1675
1761
  */
@@ -1855,7 +1941,13 @@ Please provide helpful guidance based on your expertise.
1855
1941
  }
1856
1942
  };
1857
1943
  function createCrewAgent(options) {
1858
- return new CrewAgent(options);
1944
+ if (options.execute || options.mock) {
1945
+ return new CrewAgent(options);
1946
+ }
1947
+ return new CrewAgent({
1948
+ ...options,
1949
+ execute: createCoreExecutor(options.config, { provider: options.provider })
1950
+ });
1859
1951
  }
1860
1952
 
1861
1953
  // src/agents/AgentRegistry.ts
@@ -2564,9 +2656,9 @@ var AuctionStrategy = class extends BaseDelegationStrategy {
2564
2656
  }, bids[0]);
2565
2657
  case "cheapest":
2566
2658
  return bids.reduce((best, bid) => {
2567
- const bestTime = best.estimatedTime ?? Infinity;
2568
- const bidTime = bid.estimatedTime ?? Infinity;
2569
- return bidTime < bestTime ? bid : best;
2659
+ const bestCost = best.estimatedCost ?? best.estimatedTime ?? Infinity;
2660
+ const bidCost = bid.estimatedCost ?? bid.estimatedTime ?? Infinity;
2661
+ return bidCost < bestCost ? bid : best;
2570
2662
  }, bids[0]);
2571
2663
  case "confidence":
2572
2664
  default:
@@ -3055,9 +3147,8 @@ var ConsensusStrategy = class extends BaseDelegationStrategy {
3055
3147
  */
3056
3148
  async collectVotes(task, voters, candidates) {
3057
3149
  const votes = [];
3058
- const candidateNames = candidates.map((c) => c.name);
3059
3150
  for (const voter of voters) {
3060
- const vote = await this.getVote(voter, task, candidateNames);
3151
+ const vote = await this.getVote(voter, task, candidates);
3061
3152
  if (vote) {
3062
3153
  votes.push(vote);
3063
3154
  }
@@ -3065,33 +3156,35 @@ var ConsensusStrategy = class extends BaseDelegationStrategy {
3065
3156
  return votes;
3066
3157
  }
3067
3158
  /**
3068
- * Get a vote from an agent
3159
+ * Get a vote from an agent.
3160
+ *
3161
+ * Each voter ranks the candidates by how well their capabilities fit the
3162
+ * task (the same `calculateTaskScore` signal the BestMatch/Auction strategies
3163
+ * use), plus a small self-preference bias so an agent leans toward itself when
3164
+ * candidates are otherwise comparable. This is fully deterministic — given the
3165
+ * same agents and task it always produces the same votes — and explainable,
3166
+ * which is what consensus needs. (A future enhancement could replace this with
3167
+ * an actual LLM deliberation per voter; the tally/agreement logic is unchanged.)
3069
3168
  */
3070
3169
  getVote(voter, task, candidates) {
3071
- const scores = [];
3072
- for (const candidateName of candidates) {
3073
- if (candidateName === voter.name) {
3074
- scores.push({ name: candidateName, score: 0.7 });
3075
- } else {
3076
- const randomFactor = 0.8 + Math.random() * 0.4;
3077
- scores.push({
3078
- name: candidateName,
3079
- score: Math.random() * randomFactor
3080
- });
3081
- }
3082
- }
3083
- scores.sort((a, b) => b.score - a.score);
3170
+ if (candidates.length === 0) return Promise.resolve(null);
3171
+ const SELF_PREFERENCE_BONUS = 0.15;
3172
+ const scores = candidates.map((candidate) => {
3173
+ let score = candidate.calculateTaskScore(task);
3174
+ if (candidate.name === voter.name) {
3175
+ score += SELF_PREFERENCE_BONUS;
3176
+ }
3177
+ return { name: candidate.name, score };
3178
+ });
3179
+ scores.sort((a, b) => b.score - a.score || a.name.localeCompare(b.name));
3084
3180
  const selected = scores[0];
3085
3181
  if (!selected) return Promise.resolve(null);
3086
- let weight = 1;
3087
- if (this.weightedVoting) {
3088
- weight = voter.calculateTaskScore(task) || 0.5;
3089
- }
3182
+ const weight = this.weightedVoting ? voter.calculateTaskScore(task) || 0.5 : 1;
3090
3183
  return Promise.resolve({
3091
3184
  voter: voter.name,
3092
3185
  candidate: selected.name,
3093
3186
  weight,
3094
- reasoning: `Selected based on perceived suitability (score: ${selected.score.toFixed(2)})`
3187
+ reasoning: `Ranked "${selected.name}" highest by capability fit for the task (score: ${selected.score.toFixed(2)})`
3095
3188
  });
3096
3189
  }
3097
3190
  /**
@@ -3964,13 +4057,24 @@ var ConflictResolver = class {
3964
4057
  resolved: /* @__PURE__ */ new Date()
3965
4058
  };
3966
4059
  }
4060
+ /**
4061
+ * Normalize response content for equality comparison: trim, collapse runs of
4062
+ * whitespace, and lowercase. This groups textually-equivalent answers (ignoring
4063
+ * incidental formatting) over their FULL content rather than a fragile first-N
4064
+ * characters prefix. Note: this is exact-match-after-normalization, not semantic
4065
+ * similarity — agents that express the same idea with different wording will not
4066
+ * group. Semantic grouping would require embeddings (future enhancement).
4067
+ */
4068
+ normalizeContent(content) {
4069
+ return content.trim().replace(/\s+/g, " ").toLowerCase();
4070
+ }
3967
4071
  /**
3968
4072
  * Resolve by voting
3969
4073
  */
3970
4074
  resolveByVoting(conflict, _context) {
3971
4075
  const votes = /* @__PURE__ */ new Map();
3972
4076
  for (const response of conflict.responses) {
3973
- const key = response.content.substring(0, 100);
4077
+ const key = this.normalizeContent(response.content);
3974
4078
  const current = votes.get(key) ?? 0;
3975
4079
  votes.set(key, current + response.confidence);
3976
4080
  }
@@ -3983,7 +4087,7 @@ var ConflictResolver = class {
3983
4087
  }
3984
4088
  }
3985
4089
  const winner = conflict.responses.find(
3986
- (r) => r.content.substring(0, 100) === winningKey
4090
+ (r) => this.normalizeContent(r.content) === winningKey
3987
4091
  );
3988
4092
  return Promise.resolve({
3989
4093
  conflictId: conflict.id,
@@ -3999,7 +4103,31 @@ var ConflictResolver = class {
3999
4103
  * Resolve by authority
4000
4104
  */
4001
4105
  resolveByAuthority(conflict, _context) {
4002
- return Promise.resolve(this.resolveByConfidence(conflict));
4106
+ const ranked = conflict.responses.map((r) => ({
4107
+ response: r,
4108
+ authority: typeof r.metadata?.authority === "number" ? r.metadata.authority : void 0
4109
+ })).filter(
4110
+ (x) => x.authority !== void 0
4111
+ );
4112
+ if (ranked.length === 0) {
4113
+ return Promise.resolve({
4114
+ ...this.resolveByConfidence(conflict),
4115
+ strategy: "authority",
4116
+ explanation: "No authority metadata provided; fell back to highest confidence"
4117
+ });
4118
+ }
4119
+ const winnerEntry = ranked.reduce(
4120
+ (best, cur) => cur.authority > best.authority ? cur : best
4121
+ );
4122
+ return Promise.resolve({
4123
+ conflictId: conflict.id,
4124
+ strategy: "authority",
4125
+ winner: winnerEntry.response,
4126
+ explanation: `Selected response from highest-authority agent "${winnerEntry.response.agentName}" (authority: ${winnerEntry.authority})`,
4127
+ successful: true,
4128
+ escalated: false,
4129
+ resolved: /* @__PURE__ */ new Date()
4130
+ });
4003
4131
  }
4004
4132
  /**
4005
4133
  * Resolve by consensus
@@ -4007,7 +4135,7 @@ var ConflictResolver = class {
4007
4135
  resolveByConsensus(conflict, _context) {
4008
4136
  const contentGroups = /* @__PURE__ */ new Map();
4009
4137
  for (const response of conflict.responses) {
4010
- const key = response.content.substring(0, 100);
4138
+ const key = this.normalizeContent(response.content);
4011
4139
  const group = contentGroups.get(key) ?? [];
4012
4140
  group.push(response);
4013
4141
  contentGroups.set(key, group);
@@ -4170,7 +4298,12 @@ var Crew = class {
4170
4298
  */
4171
4299
  initializeAgents() {
4172
4300
  for (const agentConfig of this.config.agents) {
4173
- const agent = createCrewAgent({ config: agentConfig });
4301
+ const agent = createCrewAgent({
4302
+ config: agentConfig,
4303
+ execute: this.config.execute,
4304
+ mock: this.config.mock,
4305
+ provider: this.config.provider
4306
+ });
4174
4307
  this.addAgent(agent);
4175
4308
  }
4176
4309
  }
@@ -5427,22 +5560,25 @@ var DAGExecutor = class {
5427
5560
  }
5428
5561
  };
5429
5562
  function createDAGFromSteps(steps, _handlers) {
5430
- const nodes = [];
5431
- const previousNodeIds = [];
5563
+ const nodeIds = steps.map(() => (0, import_nanoid6.nanoid)());
5564
+ const nameToId = /* @__PURE__ */ new Map();
5432
5565
  for (let i = 0; i < steps.length; i++) {
5433
- const step = steps[i];
5434
- const nodeId = (0, import_nanoid6.nanoid)();
5435
- const node = {
5436
- id: nodeId,
5566
+ nameToId.set(steps[i].name, nodeIds[i]);
5567
+ }
5568
+ const nodes = steps.map((step, i) => {
5569
+ let dependencies;
5570
+ if (step.dependsOn && step.dependsOn.length > 0) {
5571
+ dependencies = step.dependsOn.map((name) => nameToId.get(name)).filter((id) => id !== void 0);
5572
+ } else {
5573
+ dependencies = i > 0 ? [nodeIds[i - 1]] : [];
5574
+ }
5575
+ return {
5576
+ id: nodeIds[i],
5437
5577
  name: step.name,
5438
5578
  stepConfig: step,
5439
- dependencies: [...previousNodeIds]
5440
- // Sequential by default
5579
+ dependencies
5441
5580
  };
5442
- nodes.push(node);
5443
- previousNodeIds.length = 0;
5444
- previousNodeIds.push(nodeId);
5445
- }
5581
+ });
5446
5582
  return {
5447
5583
  id: (0, import_nanoid6.nanoid)(),
5448
5584
  nodes,
@@ -8734,6 +8870,7 @@ Resolution: ${resolution}`,
8734
8870
  createConflictResolver,
8735
8871
  createConsensusStrategy,
8736
8872
  createConversationHistory,
8873
+ createCoreExecutor,
8737
8874
  createCrew,
8738
8875
  createCrewAgent,
8739
8876
  createCustomerSupportCrew,
package/dist/index.mjs CHANGED
@@ -1,9 +1,3 @@
1
- import {
2
- CrewDashboard,
3
- DebugMode,
4
- createDashboard,
5
- createDebugMode
6
- } from "./chunk-4PF73ECN.mjs";
7
1
  import {
8
2
  CodeReviewTasks,
9
3
  CustomerSupportTasks,
@@ -17,7 +11,13 @@ import {
17
11
  createResearchCrewConfig,
18
12
  createWritingCrew,
19
13
  createWritingCrewConfig
20
- } from "./chunk-TFB7N65B.mjs";
14
+ } from "./chunk-6JLVFEU6.mjs";
15
+ import {
16
+ CrewDashboard,
17
+ DebugMode,
18
+ createDashboard,
19
+ createDebugMode
20
+ } from "./chunk-4PF73ECN.mjs";
21
21
  import {
22
22
  AgentCapabilities,
23
23
  AgentRegistry,
@@ -44,6 +44,7 @@ import {
44
44
  createCollaborationManager,
45
45
  createConflictResolver,
46
46
  createConsensusStrategy,
47
+ createCoreExecutor,
47
48
  createCrew,
48
49
  createCrewAgent,
49
50
  createDelegationCoordinator,
@@ -54,7 +55,7 @@ import {
54
55
  createStrategy,
55
56
  createTask,
56
57
  createTaskQueue
57
- } from "./chunk-QMK3HWFX.mjs";
58
+ } from "./chunk-V6VK6BOL.mjs";
58
59
 
59
60
  // src/types/role.types.ts
60
61
  var PROFICIENCY_WEIGHTS = {
@@ -828,22 +829,25 @@ var DAGExecutor = class {
828
829
  }
829
830
  };
830
831
  function createDAGFromSteps(steps, _handlers) {
831
- const nodes = [];
832
- const previousNodeIds = [];
832
+ const nodeIds = steps.map(() => nanoid2());
833
+ const nameToId = /* @__PURE__ */ new Map();
833
834
  for (let i = 0; i < steps.length; i++) {
834
- const step = steps[i];
835
- const nodeId = nanoid2();
836
- const node = {
837
- id: nodeId,
835
+ nameToId.set(steps[i].name, nodeIds[i]);
836
+ }
837
+ const nodes = steps.map((step, i) => {
838
+ let dependencies;
839
+ if (step.dependsOn && step.dependsOn.length > 0) {
840
+ dependencies = step.dependsOn.map((name) => nameToId.get(name)).filter((id) => id !== void 0);
841
+ } else {
842
+ dependencies = i > 0 ? [nodeIds[i - 1]] : [];
843
+ }
844
+ return {
845
+ id: nodeIds[i],
838
846
  name: step.name,
839
847
  stepConfig: step,
840
- dependencies: [...previousNodeIds]
841
- // Sequential by default
848
+ dependencies
842
849
  };
843
- nodes.push(node);
844
- previousNodeIds.length = 0;
845
- previousNodeIds.push(nodeId);
846
- }
850
+ });
847
851
  return {
848
852
  id: nanoid2(),
849
853
  nodes,
@@ -2501,6 +2505,7 @@ export {
2501
2505
  createConflictResolver,
2502
2506
  createConsensusStrategy,
2503
2507
  createConversationHistory,
2508
+ createCoreExecutor,
2504
2509
  createCrew,
2505
2510
  createCrewAgent,
2506
2511
  createCustomerSupportCrew,