@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.
@@ -1513,7 +1513,80 @@ var AgentCapabilities = class {
1513
1513
  }
1514
1514
  };
1515
1515
 
1516
+ // src/agents/CoreExecutor.ts
1517
+ async function loadProvider(providerName) {
1518
+ const ctorName = resolveProviderCtorName(providerName);
1519
+ let core;
1520
+ try {
1521
+ core = await import("@lov3kaizen/agentsea-core");
1522
+ } catch {
1523
+ throw new Error(
1524
+ '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.'
1525
+ );
1526
+ }
1527
+ const Ctor = core[ctorName];
1528
+ return new Ctor();
1529
+ }
1530
+ function resolveProviderCtorName(providerName) {
1531
+ switch ((providerName ?? "").toLowerCase()) {
1532
+ case "anthropic":
1533
+ case "claude":
1534
+ return "AnthropicProvider";
1535
+ case "openai":
1536
+ case "gpt":
1537
+ return "OpenAIProvider";
1538
+ case "gemini":
1539
+ case "google":
1540
+ return "GeminiProvider";
1541
+ case "ollama":
1542
+ return "OllamaProvider";
1543
+ default:
1544
+ throw new Error(
1545
+ `CrewAgent: unsupported provider "${providerName}". Supported providers are: anthropic, openai, gemini, ollama. Pass a custom \`execute\` function to createCrewAgent for any other provider.`
1546
+ );
1547
+ }
1548
+ }
1549
+ function createCoreExecutor(config, options = {}) {
1550
+ let providerPromise;
1551
+ const getProvider = () => {
1552
+ if (!providerPromise) {
1553
+ providerPromise = options.provider ? Promise.resolve(options.provider) : loadProvider(config.provider);
1554
+ }
1555
+ return providerPromise;
1556
+ };
1557
+ return async (input, systemPrompt) => {
1558
+ const provider = await getProvider();
1559
+ const start = Date.now();
1560
+ const response = await provider.generateResponse(
1561
+ [{ role: "user", content: input }],
1562
+ {
1563
+ model: config.model,
1564
+ systemPrompt,
1565
+ temperature: config.temperature,
1566
+ maxTokens: config.maxTokens
1567
+ }
1568
+ );
1569
+ return {
1570
+ output: response.content,
1571
+ tokensUsed: response.usage.inputTokens + response.usage.outputTokens,
1572
+ latencyMs: Date.now() - start,
1573
+ iterations: 1
1574
+ };
1575
+ };
1576
+ }
1577
+
1516
1578
  // src/agents/CrewAgent.ts
1579
+ function modelCostWeight(model) {
1580
+ const m = (model ?? "").toLowerCase();
1581
+ if (m.includes("opus") || m.includes("gpt-5") || m.includes("o3")) return 5;
1582
+ 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")) {
1583
+ return 3;
1584
+ }
1585
+ if (m.includes("haiku") || m.includes("mini") || m.includes("flash") || m.includes("llama") || m.includes("mistral")) {
1586
+ return 1;
1587
+ }
1588
+ return 3;
1589
+ }
1517
1590
  var CrewAgent = class _CrewAgent {
1518
1591
  id;
1519
1592
  name;
@@ -1552,10 +1625,11 @@ var CrewAgent = class _CrewAgent {
1552
1625
  */
1553
1626
  async execute(input) {
1554
1627
  if (!this.executeFunc) {
1628
+ const tokensUsed = 100 + Math.min(input.length, 400);
1555
1629
  const mockResult = {
1556
1630
  output: `[Mock response from ${this.name}]: ${input.slice(0, 100)}...`,
1557
- tokensUsed: Math.floor(Math.random() * 500) + 100,
1558
- latencyMs: Math.floor(Math.random() * 2e3) + 500,
1631
+ tokensUsed,
1632
+ latencyMs: 0,
1559
1633
  iterations: 1
1560
1634
  };
1561
1635
  this.totalTokensUsed += mockResult.tokensUsed;
@@ -1658,16 +1732,27 @@ ${JSON.stringify(task.context, null, 2)}`);
1658
1732
  ) ?? true
1659
1733
  ).map((c) => c.name);
1660
1734
  const estimatedTime = this.estimateTaskTime(task);
1735
+ const estimatedCost = this.estimateTaskCost(estimatedTime);
1661
1736
  const reasoning = this.generateBidReasoning(task, confidence, matchedCaps);
1662
1737
  return Promise.resolve({
1663
1738
  agentName: this.name,
1664
1739
  taskId: task.id ?? "unknown",
1665
1740
  confidence,
1666
1741
  estimatedTime,
1742
+ estimatedCost,
1667
1743
  reasoning,
1668
1744
  capabilities: matchedCaps
1669
1745
  });
1670
1746
  }
1747
+ /**
1748
+ * Estimate a relative cost for handling a task. Combines the agent's model
1749
+ * price tier with the estimated effort so the auction `cheapest` criterion
1750
+ * can distinguish a cheap-but-slower model from an expensive-but-faster one.
1751
+ * The unit is arbitrary and only meaningful relative to other bids.
1752
+ */
1753
+ estimateTaskCost(estimatedTime) {
1754
+ return modelCostWeight(this.model) * Math.max(estimatedTime, 1);
1755
+ }
1671
1756
  /**
1672
1757
  * Check if agent has all required capabilities
1673
1758
  */
@@ -1853,7 +1938,13 @@ Please provide helpful guidance based on your expertise.
1853
1938
  }
1854
1939
  };
1855
1940
  function createCrewAgent(options) {
1856
- return new CrewAgent(options);
1941
+ if (options.execute || options.mock) {
1942
+ return new CrewAgent(options);
1943
+ }
1944
+ return new CrewAgent({
1945
+ ...options,
1946
+ execute: createCoreExecutor(options.config, { provider: options.provider })
1947
+ });
1857
1948
  }
1858
1949
 
1859
1950
  // src/agents/AgentRegistry.ts
@@ -2553,9 +2644,9 @@ var AuctionStrategy = class extends BaseDelegationStrategy {
2553
2644
  }, bids[0]);
2554
2645
  case "cheapest":
2555
2646
  return bids.reduce((best, bid) => {
2556
- const bestTime = best.estimatedTime ?? Infinity;
2557
- const bidTime = bid.estimatedTime ?? Infinity;
2558
- return bidTime < bestTime ? bid : best;
2647
+ const bestCost = best.estimatedCost ?? best.estimatedTime ?? Infinity;
2648
+ const bidCost = bid.estimatedCost ?? bid.estimatedTime ?? Infinity;
2649
+ return bidCost < bestCost ? bid : best;
2559
2650
  }, bids[0]);
2560
2651
  case "confidence":
2561
2652
  default:
@@ -3038,9 +3129,8 @@ var ConsensusStrategy = class extends BaseDelegationStrategy {
3038
3129
  */
3039
3130
  async collectVotes(task, voters, candidates) {
3040
3131
  const votes = [];
3041
- const candidateNames = candidates.map((c) => c.name);
3042
3132
  for (const voter of voters) {
3043
- const vote = await this.getVote(voter, task, candidateNames);
3133
+ const vote = await this.getVote(voter, task, candidates);
3044
3134
  if (vote) {
3045
3135
  votes.push(vote);
3046
3136
  }
@@ -3048,33 +3138,35 @@ var ConsensusStrategy = class extends BaseDelegationStrategy {
3048
3138
  return votes;
3049
3139
  }
3050
3140
  /**
3051
- * Get a vote from an agent
3141
+ * Get a vote from an agent.
3142
+ *
3143
+ * Each voter ranks the candidates by how well their capabilities fit the
3144
+ * task (the same `calculateTaskScore` signal the BestMatch/Auction strategies
3145
+ * use), plus a small self-preference bias so an agent leans toward itself when
3146
+ * candidates are otherwise comparable. This is fully deterministic — given the
3147
+ * same agents and task it always produces the same votes — and explainable,
3148
+ * which is what consensus needs. (A future enhancement could replace this with
3149
+ * an actual LLM deliberation per voter; the tally/agreement logic is unchanged.)
3052
3150
  */
3053
3151
  getVote(voter, task, candidates) {
3054
- const scores = [];
3055
- for (const candidateName of candidates) {
3056
- if (candidateName === voter.name) {
3057
- scores.push({ name: candidateName, score: 0.7 });
3058
- } else {
3059
- const randomFactor = 0.8 + Math.random() * 0.4;
3060
- scores.push({
3061
- name: candidateName,
3062
- score: Math.random() * randomFactor
3063
- });
3152
+ if (candidates.length === 0) return Promise.resolve(null);
3153
+ const SELF_PREFERENCE_BONUS = 0.15;
3154
+ const scores = candidates.map((candidate) => {
3155
+ let score = candidate.calculateTaskScore(task);
3156
+ if (candidate.name === voter.name) {
3157
+ score += SELF_PREFERENCE_BONUS;
3064
3158
  }
3065
- }
3066
- scores.sort((a, b) => b.score - a.score);
3159
+ return { name: candidate.name, score };
3160
+ });
3161
+ scores.sort((a, b) => b.score - a.score || a.name.localeCompare(b.name));
3067
3162
  const selected = scores[0];
3068
3163
  if (!selected) return Promise.resolve(null);
3069
- let weight = 1;
3070
- if (this.weightedVoting) {
3071
- weight = voter.calculateTaskScore(task) || 0.5;
3072
- }
3164
+ const weight = this.weightedVoting ? voter.calculateTaskScore(task) || 0.5 : 1;
3073
3165
  return Promise.resolve({
3074
3166
  voter: voter.name,
3075
3167
  candidate: selected.name,
3076
3168
  weight,
3077
- reasoning: `Selected based on perceived suitability (score: ${selected.score.toFixed(2)})`
3169
+ reasoning: `Ranked "${selected.name}" highest by capability fit for the task (score: ${selected.score.toFixed(2)})`
3078
3170
  });
3079
3171
  }
3080
3172
  /**
@@ -3938,13 +4030,24 @@ var ConflictResolver = class {
3938
4030
  resolved: /* @__PURE__ */ new Date()
3939
4031
  };
3940
4032
  }
4033
+ /**
4034
+ * Normalize response content for equality comparison: trim, collapse runs of
4035
+ * whitespace, and lowercase. This groups textually-equivalent answers (ignoring
4036
+ * incidental formatting) over their FULL content rather than a fragile first-N
4037
+ * characters prefix. Note: this is exact-match-after-normalization, not semantic
4038
+ * similarity — agents that express the same idea with different wording will not
4039
+ * group. Semantic grouping would require embeddings (future enhancement).
4040
+ */
4041
+ normalizeContent(content) {
4042
+ return content.trim().replace(/\s+/g, " ").toLowerCase();
4043
+ }
3941
4044
  /**
3942
4045
  * Resolve by voting
3943
4046
  */
3944
4047
  resolveByVoting(conflict, _context) {
3945
4048
  const votes = /* @__PURE__ */ new Map();
3946
4049
  for (const response of conflict.responses) {
3947
- const key = response.content.substring(0, 100);
4050
+ const key = this.normalizeContent(response.content);
3948
4051
  const current = votes.get(key) ?? 0;
3949
4052
  votes.set(key, current + response.confidence);
3950
4053
  }
@@ -3957,7 +4060,7 @@ var ConflictResolver = class {
3957
4060
  }
3958
4061
  }
3959
4062
  const winner = conflict.responses.find(
3960
- (r) => r.content.substring(0, 100) === winningKey
4063
+ (r) => this.normalizeContent(r.content) === winningKey
3961
4064
  );
3962
4065
  return Promise.resolve({
3963
4066
  conflictId: conflict.id,
@@ -3973,7 +4076,31 @@ var ConflictResolver = class {
3973
4076
  * Resolve by authority
3974
4077
  */
3975
4078
  resolveByAuthority(conflict, _context) {
3976
- return Promise.resolve(this.resolveByConfidence(conflict));
4079
+ const ranked = conflict.responses.map((r) => ({
4080
+ response: r,
4081
+ authority: typeof r.metadata?.authority === "number" ? r.metadata.authority : void 0
4082
+ })).filter(
4083
+ (x) => x.authority !== void 0
4084
+ );
4085
+ if (ranked.length === 0) {
4086
+ return Promise.resolve({
4087
+ ...this.resolveByConfidence(conflict),
4088
+ strategy: "authority",
4089
+ explanation: "No authority metadata provided; fell back to highest confidence"
4090
+ });
4091
+ }
4092
+ const winnerEntry = ranked.reduce(
4093
+ (best, cur) => cur.authority > best.authority ? cur : best
4094
+ );
4095
+ return Promise.resolve({
4096
+ conflictId: conflict.id,
4097
+ strategy: "authority",
4098
+ winner: winnerEntry.response,
4099
+ explanation: `Selected response from highest-authority agent "${winnerEntry.response.agentName}" (authority: ${winnerEntry.authority})`,
4100
+ successful: true,
4101
+ escalated: false,
4102
+ resolved: /* @__PURE__ */ new Date()
4103
+ });
3977
4104
  }
3978
4105
  /**
3979
4106
  * Resolve by consensus
@@ -3981,7 +4108,7 @@ var ConflictResolver = class {
3981
4108
  resolveByConsensus(conflict, _context) {
3982
4109
  const contentGroups = /* @__PURE__ */ new Map();
3983
4110
  for (const response of conflict.responses) {
3984
- const key = response.content.substring(0, 100);
4111
+ const key = this.normalizeContent(response.content);
3985
4112
  const group = contentGroups.get(key) ?? [];
3986
4113
  group.push(response);
3987
4114
  contentGroups.set(key, group);
@@ -4141,7 +4268,12 @@ var Crew = class {
4141
4268
  */
4142
4269
  initializeAgents() {
4143
4270
  for (const agentConfig of this.config.agents) {
4144
- const agent = createCrewAgent({ config: agentConfig });
4271
+ const agent = createCrewAgent({
4272
+ config: agentConfig,
4273
+ execute: this.config.execute,
4274
+ mock: this.config.mock,
4275
+ provider: this.config.provider
4276
+ });
4145
4277
  this.addAgent(agent);
4146
4278
  }
4147
4279
  }
@@ -4,7 +4,7 @@ import {
4
4
  } from "../chunk-4PF73ECN.mjs";
5
5
  import {
6
6
  createCrew
7
- } from "../chunk-QMK3HWFX.mjs";
7
+ } from "../chunk-V6VK6BOL.mjs";
8
8
 
9
9
  // src/nestjs/crews.module.ts
10
10
  var CREWS_MODULE_OPTIONS = "CREWS_MODULE_OPTIONS";
@@ -1428,7 +1428,80 @@ var AgentCapabilities = class {
1428
1428
  }
1429
1429
  };
1430
1430
 
1431
+ // src/agents/CoreExecutor.ts
1432
+ async function loadProvider(providerName) {
1433
+ const ctorName = resolveProviderCtorName(providerName);
1434
+ let core;
1435
+ try {
1436
+ core = await import("@lov3kaizen/agentsea-core");
1437
+ } catch {
1438
+ throw new Error(
1439
+ '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.'
1440
+ );
1441
+ }
1442
+ const Ctor = core[ctorName];
1443
+ return new Ctor();
1444
+ }
1445
+ function resolveProviderCtorName(providerName) {
1446
+ switch ((providerName ?? "").toLowerCase()) {
1447
+ case "anthropic":
1448
+ case "claude":
1449
+ return "AnthropicProvider";
1450
+ case "openai":
1451
+ case "gpt":
1452
+ return "OpenAIProvider";
1453
+ case "gemini":
1454
+ case "google":
1455
+ return "GeminiProvider";
1456
+ case "ollama":
1457
+ return "OllamaProvider";
1458
+ default:
1459
+ throw new Error(
1460
+ `CrewAgent: unsupported provider "${providerName}". Supported providers are: anthropic, openai, gemini, ollama. Pass a custom \`execute\` function to createCrewAgent for any other provider.`
1461
+ );
1462
+ }
1463
+ }
1464
+ function createCoreExecutor(config, options = {}) {
1465
+ let providerPromise;
1466
+ const getProvider = () => {
1467
+ if (!providerPromise) {
1468
+ providerPromise = options.provider ? Promise.resolve(options.provider) : loadProvider(config.provider);
1469
+ }
1470
+ return providerPromise;
1471
+ };
1472
+ return async (input, systemPrompt) => {
1473
+ const provider = await getProvider();
1474
+ const start = Date.now();
1475
+ const response = await provider.generateResponse(
1476
+ [{ role: "user", content: input }],
1477
+ {
1478
+ model: config.model,
1479
+ systemPrompt,
1480
+ temperature: config.temperature,
1481
+ maxTokens: config.maxTokens
1482
+ }
1483
+ );
1484
+ return {
1485
+ output: response.content,
1486
+ tokensUsed: response.usage.inputTokens + response.usage.outputTokens,
1487
+ latencyMs: Date.now() - start,
1488
+ iterations: 1
1489
+ };
1490
+ };
1491
+ }
1492
+
1431
1493
  // src/agents/CrewAgent.ts
1494
+ function modelCostWeight(model) {
1495
+ const m = (model ?? "").toLowerCase();
1496
+ if (m.includes("opus") || m.includes("gpt-5") || m.includes("o3")) return 5;
1497
+ 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")) {
1498
+ return 3;
1499
+ }
1500
+ if (m.includes("haiku") || m.includes("mini") || m.includes("flash") || m.includes("llama") || m.includes("mistral")) {
1501
+ return 1;
1502
+ }
1503
+ return 3;
1504
+ }
1432
1505
  var CrewAgent = class _CrewAgent {
1433
1506
  id;
1434
1507
  name;
@@ -1467,10 +1540,11 @@ var CrewAgent = class _CrewAgent {
1467
1540
  */
1468
1541
  async execute(input) {
1469
1542
  if (!this.executeFunc) {
1543
+ const tokensUsed = 100 + Math.min(input.length, 400);
1470
1544
  const mockResult = {
1471
1545
  output: `[Mock response from ${this.name}]: ${input.slice(0, 100)}...`,
1472
- tokensUsed: Math.floor(Math.random() * 500) + 100,
1473
- latencyMs: Math.floor(Math.random() * 2e3) + 500,
1546
+ tokensUsed,
1547
+ latencyMs: 0,
1474
1548
  iterations: 1
1475
1549
  };
1476
1550
  this.totalTokensUsed += mockResult.tokensUsed;
@@ -1573,16 +1647,27 @@ ${JSON.stringify(task.context, null, 2)}`);
1573
1647
  ) ?? true
1574
1648
  ).map((c) => c.name);
1575
1649
  const estimatedTime = this.estimateTaskTime(task);
1650
+ const estimatedCost = this.estimateTaskCost(estimatedTime);
1576
1651
  const reasoning = this.generateBidReasoning(task, confidence, matchedCaps);
1577
1652
  return Promise.resolve({
1578
1653
  agentName: this.name,
1579
1654
  taskId: task.id ?? "unknown",
1580
1655
  confidence,
1581
1656
  estimatedTime,
1657
+ estimatedCost,
1582
1658
  reasoning,
1583
1659
  capabilities: matchedCaps
1584
1660
  });
1585
1661
  }
1662
+ /**
1663
+ * Estimate a relative cost for handling a task. Combines the agent's model
1664
+ * price tier with the estimated effort so the auction `cheapest` criterion
1665
+ * can distinguish a cheap-but-slower model from an expensive-but-faster one.
1666
+ * The unit is arbitrary and only meaningful relative to other bids.
1667
+ */
1668
+ estimateTaskCost(estimatedTime) {
1669
+ return modelCostWeight(this.model) * Math.max(estimatedTime, 1);
1670
+ }
1586
1671
  /**
1587
1672
  * Check if agent has all required capabilities
1588
1673
  */
@@ -1768,7 +1853,13 @@ Please provide helpful guidance based on your expertise.
1768
1853
  }
1769
1854
  };
1770
1855
  function createCrewAgent(options) {
1771
- return new CrewAgent(options);
1856
+ if (options.execute || options.mock) {
1857
+ return new CrewAgent(options);
1858
+ }
1859
+ return new CrewAgent({
1860
+ ...options,
1861
+ execute: createCoreExecutor(options.config, { provider: options.provider })
1862
+ });
1772
1863
  }
1773
1864
 
1774
1865
  // src/agents/AgentRegistry.ts
@@ -2468,9 +2559,9 @@ var AuctionStrategy = class extends BaseDelegationStrategy {
2468
2559
  }, bids[0]);
2469
2560
  case "cheapest":
2470
2561
  return bids.reduce((best, bid) => {
2471
- const bestTime = best.estimatedTime ?? Infinity;
2472
- const bidTime = bid.estimatedTime ?? Infinity;
2473
- return bidTime < bestTime ? bid : best;
2562
+ const bestCost = best.estimatedCost ?? best.estimatedTime ?? Infinity;
2563
+ const bidCost = bid.estimatedCost ?? bid.estimatedTime ?? Infinity;
2564
+ return bidCost < bestCost ? bid : best;
2474
2565
  }, bids[0]);
2475
2566
  case "confidence":
2476
2567
  default:
@@ -2953,9 +3044,8 @@ var ConsensusStrategy = class extends BaseDelegationStrategy {
2953
3044
  */
2954
3045
  async collectVotes(task, voters, candidates) {
2955
3046
  const votes = [];
2956
- const candidateNames = candidates.map((c) => c.name);
2957
3047
  for (const voter of voters) {
2958
- const vote = await this.getVote(voter, task, candidateNames);
3048
+ const vote = await this.getVote(voter, task, candidates);
2959
3049
  if (vote) {
2960
3050
  votes.push(vote);
2961
3051
  }
@@ -2963,33 +3053,35 @@ var ConsensusStrategy = class extends BaseDelegationStrategy {
2963
3053
  return votes;
2964
3054
  }
2965
3055
  /**
2966
- * Get a vote from an agent
3056
+ * Get a vote from an agent.
3057
+ *
3058
+ * Each voter ranks the candidates by how well their capabilities fit the
3059
+ * task (the same `calculateTaskScore` signal the BestMatch/Auction strategies
3060
+ * use), plus a small self-preference bias so an agent leans toward itself when
3061
+ * candidates are otherwise comparable. This is fully deterministic — given the
3062
+ * same agents and task it always produces the same votes — and explainable,
3063
+ * which is what consensus needs. (A future enhancement could replace this with
3064
+ * an actual LLM deliberation per voter; the tally/agreement logic is unchanged.)
2967
3065
  */
2968
3066
  getVote(voter, task, candidates) {
2969
- const scores = [];
2970
- for (const candidateName of candidates) {
2971
- if (candidateName === voter.name) {
2972
- scores.push({ name: candidateName, score: 0.7 });
2973
- } else {
2974
- const randomFactor = 0.8 + Math.random() * 0.4;
2975
- scores.push({
2976
- name: candidateName,
2977
- score: Math.random() * randomFactor
2978
- });
3067
+ if (candidates.length === 0) return Promise.resolve(null);
3068
+ const SELF_PREFERENCE_BONUS = 0.15;
3069
+ const scores = candidates.map((candidate) => {
3070
+ let score = candidate.calculateTaskScore(task);
3071
+ if (candidate.name === voter.name) {
3072
+ score += SELF_PREFERENCE_BONUS;
2979
3073
  }
2980
- }
2981
- scores.sort((a, b) => b.score - a.score);
3074
+ return { name: candidate.name, score };
3075
+ });
3076
+ scores.sort((a, b) => b.score - a.score || a.name.localeCompare(b.name));
2982
3077
  const selected = scores[0];
2983
3078
  if (!selected) return Promise.resolve(null);
2984
- let weight = 1;
2985
- if (this.weightedVoting) {
2986
- weight = voter.calculateTaskScore(task) || 0.5;
2987
- }
3079
+ const weight = this.weightedVoting ? voter.calculateTaskScore(task) || 0.5 : 1;
2988
3080
  return Promise.resolve({
2989
3081
  voter: voter.name,
2990
3082
  candidate: selected.name,
2991
3083
  weight,
2992
- reasoning: `Selected based on perceived suitability (score: ${selected.score.toFixed(2)})`
3084
+ reasoning: `Ranked "${selected.name}" highest by capability fit for the task (score: ${selected.score.toFixed(2)})`
2993
3085
  });
2994
3086
  }
2995
3087
  /**
@@ -3853,13 +3945,24 @@ var ConflictResolver = class {
3853
3945
  resolved: /* @__PURE__ */ new Date()
3854
3946
  };
3855
3947
  }
3948
+ /**
3949
+ * Normalize response content for equality comparison: trim, collapse runs of
3950
+ * whitespace, and lowercase. This groups textually-equivalent answers (ignoring
3951
+ * incidental formatting) over their FULL content rather than a fragile first-N
3952
+ * characters prefix. Note: this is exact-match-after-normalization, not semantic
3953
+ * similarity — agents that express the same idea with different wording will not
3954
+ * group. Semantic grouping would require embeddings (future enhancement).
3955
+ */
3956
+ normalizeContent(content) {
3957
+ return content.trim().replace(/\s+/g, " ").toLowerCase();
3958
+ }
3856
3959
  /**
3857
3960
  * Resolve by voting
3858
3961
  */
3859
3962
  resolveByVoting(conflict, _context) {
3860
3963
  const votes = /* @__PURE__ */ new Map();
3861
3964
  for (const response of conflict.responses) {
3862
- const key = response.content.substring(0, 100);
3965
+ const key = this.normalizeContent(response.content);
3863
3966
  const current = votes.get(key) ?? 0;
3864
3967
  votes.set(key, current + response.confidence);
3865
3968
  }
@@ -3872,7 +3975,7 @@ var ConflictResolver = class {
3872
3975
  }
3873
3976
  }
3874
3977
  const winner = conflict.responses.find(
3875
- (r) => r.content.substring(0, 100) === winningKey
3978
+ (r) => this.normalizeContent(r.content) === winningKey
3876
3979
  );
3877
3980
  return Promise.resolve({
3878
3981
  conflictId: conflict.id,
@@ -3888,7 +3991,31 @@ var ConflictResolver = class {
3888
3991
  * Resolve by authority
3889
3992
  */
3890
3993
  resolveByAuthority(conflict, _context) {
3891
- return Promise.resolve(this.resolveByConfidence(conflict));
3994
+ const ranked = conflict.responses.map((r) => ({
3995
+ response: r,
3996
+ authority: typeof r.metadata?.authority === "number" ? r.metadata.authority : void 0
3997
+ })).filter(
3998
+ (x) => x.authority !== void 0
3999
+ );
4000
+ if (ranked.length === 0) {
4001
+ return Promise.resolve({
4002
+ ...this.resolveByConfidence(conflict),
4003
+ strategy: "authority",
4004
+ explanation: "No authority metadata provided; fell back to highest confidence"
4005
+ });
4006
+ }
4007
+ const winnerEntry = ranked.reduce(
4008
+ (best, cur) => cur.authority > best.authority ? cur : best
4009
+ );
4010
+ return Promise.resolve({
4011
+ conflictId: conflict.id,
4012
+ strategy: "authority",
4013
+ winner: winnerEntry.response,
4014
+ explanation: `Selected response from highest-authority agent "${winnerEntry.response.agentName}" (authority: ${winnerEntry.authority})`,
4015
+ successful: true,
4016
+ escalated: false,
4017
+ resolved: /* @__PURE__ */ new Date()
4018
+ });
3892
4019
  }
3893
4020
  /**
3894
4021
  * Resolve by consensus
@@ -3896,7 +4023,7 @@ var ConflictResolver = class {
3896
4023
  resolveByConsensus(conflict, _context) {
3897
4024
  const contentGroups = /* @__PURE__ */ new Map();
3898
4025
  for (const response of conflict.responses) {
3899
- const key = response.content.substring(0, 100);
4026
+ const key = this.normalizeContent(response.content);
3900
4027
  const group = contentGroups.get(key) ?? [];
3901
4028
  group.push(response);
3902
4029
  contentGroups.set(key, group);
@@ -4056,7 +4183,12 @@ var Crew = class {
4056
4183
  */
4057
4184
  initializeAgents() {
4058
4185
  for (const agentConfig of this.config.agents) {
4059
- const agent = createCrewAgent({ config: agentConfig });
4186
+ const agent = createCrewAgent({
4187
+ config: agentConfig,
4188
+ execute: this.config.execute,
4189
+ mock: this.config.mock,
4190
+ provider: this.config.provider
4191
+ });
4060
4192
  this.addAgent(agent);
4061
4193
  }
4062
4194
  }
@@ -11,8 +11,8 @@ import {
11
11
  createResearchCrewConfig,
12
12
  createWritingCrew,
13
13
  createWritingCrewConfig
14
- } from "../chunk-TFB7N65B.mjs";
15
- import "../chunk-QMK3HWFX.mjs";
14
+ } from "../chunk-6JLVFEU6.mjs";
15
+ import "../chunk-V6VK6BOL.mjs";
16
16
  export {
17
17
  CodeReviewTasks,
18
18
  CustomerSupportTasks,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lov3kaizen/agentsea-crews",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Multi-agent orchestration framework for AgentSea. Build, compose, and orchestrate agent crews with role-based coordination, task delegation, and workflow automation.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -40,7 +40,7 @@
40
40
  "peerDependencies": {
41
41
  "@nestjs/common": "^10.0.0 || ^11.0.0",
42
42
  "@nestjs/core": "^10.0.0 || ^11.0.0",
43
- "@lov3kaizen/agentsea-core": "1.0.1"
43
+ "@lov3kaizen/agentsea-core": "1.1.0"
44
44
  },
45
45
  "peerDependenciesMeta": {
46
46
  "@nestjs/common": {