@lov3kaizen/agentsea-crews 1.0.0 → 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/README.md +27 -1
- package/dist/{chunk-G3PAPYOI.mjs → chunk-6JLVFEU6.mjs} +13 -13
- package/dist/{chunk-QMK3HWFX.mjs → chunk-V6VK6BOL.mjs} +164 -31
- package/dist/index.js +193 -56
- package/dist/index.mjs +19 -14
- package/dist/nestjs/index.js +163 -31
- package/dist/nestjs/index.mjs +1 -1
- package/dist/templates/index.js +175 -43
- package/dist/templates/index.mjs +2 -2
- package/package.json +7 -7
package/dist/nestjs/index.js
CHANGED
|
@@ -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
|
|
1558
|
-
latencyMs:
|
|
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
|
-
|
|
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
|
|
2557
|
-
const
|
|
2558
|
-
return
|
|
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,
|
|
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
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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: `
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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({
|
|
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
|
}
|