@lov3kaizen/agentsea-crews 1.0.1 → 1.1.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.
- package/README.md +56 -0
- package/dist/Crew-BnvVjN7A.d.mts +1060 -0
- package/dist/Crew-BnvVjN7A.d.ts +1060 -0
- package/dist/DebugMode-CbYgA7Yw.d.mts +190 -0
- package/dist/DebugMode-o5e9gmQ7.d.ts +190 -0
- package/dist/{chunk-TFB7N65B.mjs → chunk-3NMVWRVW.mjs} +1 -1
- package/dist/{chunk-QMK3HWFX.mjs → chunk-J5KQSOGT.mjs} +306 -61
- package/dist/index.d.mts +975 -0
- package/dist/index.d.ts +975 -0
- package/dist/index.js +335 -96
- package/dist/index.mjs +26 -25
- package/dist/nestjs/index.d.mts +98 -0
- package/dist/nestjs/index.d.ts +98 -0
- package/dist/nestjs/index.js +305 -66
- package/dist/nestjs/index.mjs +1 -1
- package/dist/templates/index.d.mts +78 -0
- package/dist/templates/index.d.ts +78 -0
- package/dist/templates/index.js +305 -66
- package/dist/templates/index.mjs +2 -2
- package/package.json +6 -6
|
@@ -211,8 +211,37 @@ function createRole(config) {
|
|
|
211
211
|
return new Role(config);
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
+
// ../../node_modules/.pnpm/nanoid@5.1.6/node_modules/nanoid/index.js
|
|
215
|
+
import { webcrypto as crypto } from "crypto";
|
|
216
|
+
|
|
217
|
+
// ../../node_modules/.pnpm/nanoid@5.1.6/node_modules/nanoid/url-alphabet/index.js
|
|
218
|
+
var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
|
219
|
+
|
|
220
|
+
// ../../node_modules/.pnpm/nanoid@5.1.6/node_modules/nanoid/index.js
|
|
221
|
+
var POOL_SIZE_MULTIPLIER = 128;
|
|
222
|
+
var pool;
|
|
223
|
+
var poolOffset;
|
|
224
|
+
function fillPool(bytes) {
|
|
225
|
+
if (!pool || pool.length < bytes) {
|
|
226
|
+
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
|
|
227
|
+
crypto.getRandomValues(pool);
|
|
228
|
+
poolOffset = 0;
|
|
229
|
+
} else if (poolOffset + bytes > pool.length) {
|
|
230
|
+
crypto.getRandomValues(pool);
|
|
231
|
+
poolOffset = 0;
|
|
232
|
+
}
|
|
233
|
+
poolOffset += bytes;
|
|
234
|
+
}
|
|
235
|
+
function nanoid(size = 21) {
|
|
236
|
+
fillPool(size |= 0);
|
|
237
|
+
let id = "";
|
|
238
|
+
for (let i = poolOffset - size; i < poolOffset; i++) {
|
|
239
|
+
id += urlAlphabet[pool[i] & 63];
|
|
240
|
+
}
|
|
241
|
+
return id;
|
|
242
|
+
}
|
|
243
|
+
|
|
214
244
|
// src/core/Task.ts
|
|
215
|
-
import { nanoid } from "nanoid";
|
|
216
245
|
var Task = class _Task {
|
|
217
246
|
id;
|
|
218
247
|
description;
|
|
@@ -844,7 +873,6 @@ function createTaskQueue(config) {
|
|
|
844
873
|
|
|
845
874
|
// src/core/ExecutionContext.ts
|
|
846
875
|
import EventEmitter from "eventemitter3";
|
|
847
|
-
import { nanoid as nanoid2 } from "nanoid";
|
|
848
876
|
var ExecutionContext = class {
|
|
849
877
|
crewId;
|
|
850
878
|
crewName;
|
|
@@ -861,7 +889,7 @@ var ExecutionContext = class {
|
|
|
861
889
|
startTime;
|
|
862
890
|
endTime;
|
|
863
891
|
constructor(config) {
|
|
864
|
-
this.crewId = config.crewId ??
|
|
892
|
+
this.crewId = config.crewId ?? nanoid();
|
|
865
893
|
this.crewName = config.crewName;
|
|
866
894
|
this.state = /* @__PURE__ */ new Map();
|
|
867
895
|
this.completedTasks = /* @__PURE__ */ new Map();
|
|
@@ -1107,7 +1135,7 @@ var ExecutionContext = class {
|
|
|
1107
1135
|
*/
|
|
1108
1136
|
createCheckpoint() {
|
|
1109
1137
|
return {
|
|
1110
|
-
id:
|
|
1138
|
+
id: nanoid(),
|
|
1111
1139
|
timestamp: /* @__PURE__ */ new Date(),
|
|
1112
1140
|
crewId: this.crewId,
|
|
1113
1141
|
crewName: this.crewName,
|
|
@@ -1387,8 +1415,80 @@ var AgentCapabilities = class {
|
|
|
1387
1415
|
}
|
|
1388
1416
|
};
|
|
1389
1417
|
|
|
1418
|
+
// src/agents/CoreExecutor.ts
|
|
1419
|
+
async function loadProvider(providerName) {
|
|
1420
|
+
const ctorName = resolveProviderCtorName(providerName);
|
|
1421
|
+
let core;
|
|
1422
|
+
try {
|
|
1423
|
+
core = await import("@lov3kaizen/agentsea-core");
|
|
1424
|
+
} catch {
|
|
1425
|
+
throw new Error(
|
|
1426
|
+
'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.'
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
const Ctor = core[ctorName];
|
|
1430
|
+
return new Ctor();
|
|
1431
|
+
}
|
|
1432
|
+
function resolveProviderCtorName(providerName) {
|
|
1433
|
+
switch ((providerName ?? "").toLowerCase()) {
|
|
1434
|
+
case "anthropic":
|
|
1435
|
+
case "claude":
|
|
1436
|
+
return "AnthropicProvider";
|
|
1437
|
+
case "openai":
|
|
1438
|
+
case "gpt":
|
|
1439
|
+
return "OpenAIProvider";
|
|
1440
|
+
case "gemini":
|
|
1441
|
+
case "google":
|
|
1442
|
+
return "GeminiProvider";
|
|
1443
|
+
case "ollama":
|
|
1444
|
+
return "OllamaProvider";
|
|
1445
|
+
default:
|
|
1446
|
+
throw new Error(
|
|
1447
|
+
`CrewAgent: unsupported provider "${providerName}". Supported providers are: anthropic, openai, gemini, ollama. Pass a custom \`execute\` function to createCrewAgent for any other provider.`
|
|
1448
|
+
);
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
function createCoreExecutor(config, options = {}) {
|
|
1452
|
+
let providerPromise;
|
|
1453
|
+
const getProvider = () => {
|
|
1454
|
+
if (!providerPromise) {
|
|
1455
|
+
providerPromise = options.provider ? Promise.resolve(options.provider) : loadProvider(config.provider);
|
|
1456
|
+
}
|
|
1457
|
+
return providerPromise;
|
|
1458
|
+
};
|
|
1459
|
+
return async (input, systemPrompt) => {
|
|
1460
|
+
const provider = await getProvider();
|
|
1461
|
+
const start = Date.now();
|
|
1462
|
+
const response = await provider.generateResponse(
|
|
1463
|
+
[{ role: "user", content: input }],
|
|
1464
|
+
{
|
|
1465
|
+
model: config.model,
|
|
1466
|
+
systemPrompt,
|
|
1467
|
+
temperature: config.temperature,
|
|
1468
|
+
maxTokens: config.maxTokens
|
|
1469
|
+
}
|
|
1470
|
+
);
|
|
1471
|
+
return {
|
|
1472
|
+
output: response.content,
|
|
1473
|
+
tokensUsed: response.usage.inputTokens + response.usage.outputTokens,
|
|
1474
|
+
latencyMs: Date.now() - start,
|
|
1475
|
+
iterations: 1
|
|
1476
|
+
};
|
|
1477
|
+
};
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1390
1480
|
// src/agents/CrewAgent.ts
|
|
1391
|
-
|
|
1481
|
+
function modelCostWeight(model) {
|
|
1482
|
+
const m = (model ?? "").toLowerCase();
|
|
1483
|
+
if (m.includes("opus") || m.includes("gpt-5") || m.includes("o3")) return 5;
|
|
1484
|
+
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")) {
|
|
1485
|
+
return 3;
|
|
1486
|
+
}
|
|
1487
|
+
if (m.includes("haiku") || m.includes("mini") || m.includes("flash") || m.includes("llama") || m.includes("mistral")) {
|
|
1488
|
+
return 1;
|
|
1489
|
+
}
|
|
1490
|
+
return 3;
|
|
1491
|
+
}
|
|
1392
1492
|
var CrewAgent = class _CrewAgent {
|
|
1393
1493
|
id;
|
|
1394
1494
|
name;
|
|
@@ -1408,7 +1508,7 @@ var CrewAgent = class _CrewAgent {
|
|
|
1408
1508
|
totalTokensUsed = 0;
|
|
1409
1509
|
constructor(options) {
|
|
1410
1510
|
const { config, execute } = options;
|
|
1411
|
-
this.id =
|
|
1511
|
+
this.id = nanoid();
|
|
1412
1512
|
this.name = config.name;
|
|
1413
1513
|
this.role = new Role(config.role);
|
|
1414
1514
|
this.capabilities = config.role.capabilities;
|
|
@@ -1427,10 +1527,11 @@ var CrewAgent = class _CrewAgent {
|
|
|
1427
1527
|
*/
|
|
1428
1528
|
async execute(input) {
|
|
1429
1529
|
if (!this.executeFunc) {
|
|
1530
|
+
const tokensUsed = 100 + Math.min(input.length, 400);
|
|
1430
1531
|
const mockResult = {
|
|
1431
1532
|
output: `[Mock response from ${this.name}]: ${input.slice(0, 100)}...`,
|
|
1432
|
-
tokensUsed
|
|
1433
|
-
latencyMs:
|
|
1533
|
+
tokensUsed,
|
|
1534
|
+
latencyMs: 0,
|
|
1434
1535
|
iterations: 1
|
|
1435
1536
|
};
|
|
1436
1537
|
this.totalTokensUsed += mockResult.tokensUsed;
|
|
@@ -1533,16 +1634,27 @@ ${JSON.stringify(task.context, null, 2)}`);
|
|
|
1533
1634
|
) ?? true
|
|
1534
1635
|
).map((c) => c.name);
|
|
1535
1636
|
const estimatedTime = this.estimateTaskTime(task);
|
|
1637
|
+
const estimatedCost = this.estimateTaskCost(estimatedTime);
|
|
1536
1638
|
const reasoning = this.generateBidReasoning(task, confidence, matchedCaps);
|
|
1537
1639
|
return Promise.resolve({
|
|
1538
1640
|
agentName: this.name,
|
|
1539
1641
|
taskId: task.id ?? "unknown",
|
|
1540
1642
|
confidence,
|
|
1541
1643
|
estimatedTime,
|
|
1644
|
+
estimatedCost,
|
|
1542
1645
|
reasoning,
|
|
1543
1646
|
capabilities: matchedCaps
|
|
1544
1647
|
});
|
|
1545
1648
|
}
|
|
1649
|
+
/**
|
|
1650
|
+
* Estimate a relative cost for handling a task. Combines the agent's model
|
|
1651
|
+
* price tier with the estimated effort so the auction `cheapest` criterion
|
|
1652
|
+
* can distinguish a cheap-but-slower model from an expensive-but-faster one.
|
|
1653
|
+
* The unit is arbitrary and only meaningful relative to other bids.
|
|
1654
|
+
*/
|
|
1655
|
+
estimateTaskCost(estimatedTime) {
|
|
1656
|
+
return modelCostWeight(this.model) * Math.max(estimatedTime, 1);
|
|
1657
|
+
}
|
|
1546
1658
|
/**
|
|
1547
1659
|
* Check if agent has all required capabilities
|
|
1548
1660
|
*/
|
|
@@ -1593,7 +1705,7 @@ ${JSON.stringify(task.context, null, 2)}`);
|
|
|
1593
1705
|
*/
|
|
1594
1706
|
createHelpRequest(taskId, request) {
|
|
1595
1707
|
return {
|
|
1596
|
-
requestId:
|
|
1708
|
+
requestId: nanoid(),
|
|
1597
1709
|
fromAgent: this.name,
|
|
1598
1710
|
taskId,
|
|
1599
1711
|
request
|
|
@@ -1728,7 +1840,13 @@ Please provide helpful guidance based on your expertise.
|
|
|
1728
1840
|
}
|
|
1729
1841
|
};
|
|
1730
1842
|
function createCrewAgent(options) {
|
|
1731
|
-
|
|
1843
|
+
if (options.execute || options.mock) {
|
|
1844
|
+
return new CrewAgent(options);
|
|
1845
|
+
}
|
|
1846
|
+
return new CrewAgent({
|
|
1847
|
+
...options,
|
|
1848
|
+
execute: createCoreExecutor(options.config, { provider: options.provider })
|
|
1849
|
+
});
|
|
1732
1850
|
}
|
|
1733
1851
|
|
|
1734
1852
|
// src/agents/AgentRegistry.ts
|
|
@@ -2437,9 +2555,9 @@ var AuctionStrategy = class extends BaseDelegationStrategy {
|
|
|
2437
2555
|
}, bids[0]);
|
|
2438
2556
|
case "cheapest":
|
|
2439
2557
|
return bids.reduce((best, bid) => {
|
|
2440
|
-
const
|
|
2441
|
-
const
|
|
2442
|
-
return
|
|
2558
|
+
const bestCost = best.estimatedCost ?? best.estimatedTime ?? Infinity;
|
|
2559
|
+
const bidCost = bid.estimatedCost ?? bid.estimatedTime ?? Infinity;
|
|
2560
|
+
return bidCost < bestCost ? bid : best;
|
|
2443
2561
|
}, bids[0]);
|
|
2444
2562
|
case "confidence":
|
|
2445
2563
|
default:
|
|
@@ -2928,9 +3046,8 @@ var ConsensusStrategy = class extends BaseDelegationStrategy {
|
|
|
2928
3046
|
*/
|
|
2929
3047
|
async collectVotes(task, voters, candidates) {
|
|
2930
3048
|
const votes = [];
|
|
2931
|
-
const candidateNames = candidates.map((c) => c.name);
|
|
2932
3049
|
for (const voter of voters) {
|
|
2933
|
-
const vote = await this.getVote(voter, task,
|
|
3050
|
+
const vote = await this.getVote(voter, task, candidates);
|
|
2934
3051
|
if (vote) {
|
|
2935
3052
|
votes.push(vote);
|
|
2936
3053
|
}
|
|
@@ -2938,33 +3055,35 @@ var ConsensusStrategy = class extends BaseDelegationStrategy {
|
|
|
2938
3055
|
return votes;
|
|
2939
3056
|
}
|
|
2940
3057
|
/**
|
|
2941
|
-
* Get a vote from an agent
|
|
3058
|
+
* Get a vote from an agent.
|
|
3059
|
+
*
|
|
3060
|
+
* Each voter ranks the candidates by how well their capabilities fit the
|
|
3061
|
+
* task (the same `calculateTaskScore` signal the BestMatch/Auction strategies
|
|
3062
|
+
* use), plus a small self-preference bias so an agent leans toward itself when
|
|
3063
|
+
* candidates are otherwise comparable. This is fully deterministic — given the
|
|
3064
|
+
* same agents and task it always produces the same votes — and explainable,
|
|
3065
|
+
* which is what consensus needs. (A future enhancement could replace this with
|
|
3066
|
+
* an actual LLM deliberation per voter; the tally/agreement logic is unchanged.)
|
|
2942
3067
|
*/
|
|
2943
3068
|
getVote(voter, task, candidates) {
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
scores.push({
|
|
2951
|
-
name: candidateName,
|
|
2952
|
-
score: Math.random() * randomFactor
|
|
2953
|
-
});
|
|
3069
|
+
if (candidates.length === 0) return Promise.resolve(null);
|
|
3070
|
+
const SELF_PREFERENCE_BONUS = 0.15;
|
|
3071
|
+
const scores = candidates.map((candidate) => {
|
|
3072
|
+
let score = candidate.calculateTaskScore(task);
|
|
3073
|
+
if (candidate.name === voter.name) {
|
|
3074
|
+
score += SELF_PREFERENCE_BONUS;
|
|
2954
3075
|
}
|
|
2955
|
-
|
|
2956
|
-
|
|
3076
|
+
return { name: candidate.name, score };
|
|
3077
|
+
});
|
|
3078
|
+
scores.sort((a, b) => b.score - a.score || a.name.localeCompare(b.name));
|
|
2957
3079
|
const selected = scores[0];
|
|
2958
3080
|
if (!selected) return Promise.resolve(null);
|
|
2959
|
-
|
|
2960
|
-
if (this.weightedVoting) {
|
|
2961
|
-
weight = voter.calculateTaskScore(task) || 0.5;
|
|
2962
|
-
}
|
|
3081
|
+
const weight = this.weightedVoting ? voter.calculateTaskScore(task) || 0.5 : 1;
|
|
2963
3082
|
return Promise.resolve({
|
|
2964
3083
|
voter: voter.name,
|
|
2965
3084
|
candidate: selected.name,
|
|
2966
3085
|
weight,
|
|
2967
|
-
reasoning: `
|
|
3086
|
+
reasoning: `Ranked "${selected.name}" highest by capability fit for the task (score: ${selected.score.toFixed(2)})`
|
|
2968
3087
|
});
|
|
2969
3088
|
}
|
|
2970
3089
|
/**
|
|
@@ -3837,13 +3956,24 @@ var ConflictResolver = class {
|
|
|
3837
3956
|
resolved: /* @__PURE__ */ new Date()
|
|
3838
3957
|
};
|
|
3839
3958
|
}
|
|
3959
|
+
/**
|
|
3960
|
+
* Normalize response content for equality comparison: trim, collapse runs of
|
|
3961
|
+
* whitespace, and lowercase. This groups textually-equivalent answers (ignoring
|
|
3962
|
+
* incidental formatting) over their FULL content rather than a fragile first-N
|
|
3963
|
+
* characters prefix. Note: this is exact-match-after-normalization, not semantic
|
|
3964
|
+
* similarity — agents that express the same idea with different wording will not
|
|
3965
|
+
* group. Semantic grouping would require embeddings (future enhancement).
|
|
3966
|
+
*/
|
|
3967
|
+
normalizeContent(content) {
|
|
3968
|
+
return content.trim().replace(/\s+/g, " ").toLowerCase();
|
|
3969
|
+
}
|
|
3840
3970
|
/**
|
|
3841
3971
|
* Resolve by voting
|
|
3842
3972
|
*/
|
|
3843
3973
|
resolveByVoting(conflict, _context) {
|
|
3844
3974
|
const votes = /* @__PURE__ */ new Map();
|
|
3845
3975
|
for (const response of conflict.responses) {
|
|
3846
|
-
const key = response.content
|
|
3976
|
+
const key = this.normalizeContent(response.content);
|
|
3847
3977
|
const current = votes.get(key) ?? 0;
|
|
3848
3978
|
votes.set(key, current + response.confidence);
|
|
3849
3979
|
}
|
|
@@ -3856,7 +3986,7 @@ var ConflictResolver = class {
|
|
|
3856
3986
|
}
|
|
3857
3987
|
}
|
|
3858
3988
|
const winner = conflict.responses.find(
|
|
3859
|
-
(r) => r.content
|
|
3989
|
+
(r) => this.normalizeContent(r.content) === winningKey
|
|
3860
3990
|
);
|
|
3861
3991
|
return Promise.resolve({
|
|
3862
3992
|
conflictId: conflict.id,
|
|
@@ -3872,7 +4002,31 @@ var ConflictResolver = class {
|
|
|
3872
4002
|
* Resolve by authority
|
|
3873
4003
|
*/
|
|
3874
4004
|
resolveByAuthority(conflict, _context) {
|
|
3875
|
-
|
|
4005
|
+
const ranked = conflict.responses.map((r) => ({
|
|
4006
|
+
response: r,
|
|
4007
|
+
authority: typeof r.metadata?.authority === "number" ? r.metadata.authority : void 0
|
|
4008
|
+
})).filter(
|
|
4009
|
+
(x) => x.authority !== void 0
|
|
4010
|
+
);
|
|
4011
|
+
if (ranked.length === 0) {
|
|
4012
|
+
return Promise.resolve({
|
|
4013
|
+
...this.resolveByConfidence(conflict),
|
|
4014
|
+
strategy: "authority",
|
|
4015
|
+
explanation: "No authority metadata provided; fell back to highest confidence"
|
|
4016
|
+
});
|
|
4017
|
+
}
|
|
4018
|
+
const winnerEntry = ranked.reduce(
|
|
4019
|
+
(best, cur) => cur.authority > best.authority ? cur : best
|
|
4020
|
+
);
|
|
4021
|
+
return Promise.resolve({
|
|
4022
|
+
conflictId: conflict.id,
|
|
4023
|
+
strategy: "authority",
|
|
4024
|
+
winner: winnerEntry.response,
|
|
4025
|
+
explanation: `Selected response from highest-authority agent "${winnerEntry.response.agentName}" (authority: ${winnerEntry.authority})`,
|
|
4026
|
+
successful: true,
|
|
4027
|
+
escalated: false,
|
|
4028
|
+
resolved: /* @__PURE__ */ new Date()
|
|
4029
|
+
});
|
|
3876
4030
|
}
|
|
3877
4031
|
/**
|
|
3878
4032
|
* Resolve by consensus
|
|
@@ -3880,7 +4034,7 @@ var ConflictResolver = class {
|
|
|
3880
4034
|
resolveByConsensus(conflict, _context) {
|
|
3881
4035
|
const contentGroups = /* @__PURE__ */ new Map();
|
|
3882
4036
|
for (const response of conflict.responses) {
|
|
3883
|
-
const key = response.content
|
|
4037
|
+
const key = this.normalizeContent(response.content);
|
|
3884
4038
|
const group = contentGroups.get(key) ?? [];
|
|
3885
4039
|
group.push(response);
|
|
3886
4040
|
contentGroups.set(key, group);
|
|
@@ -4004,7 +4158,6 @@ function createConflictResolver(config) {
|
|
|
4004
4158
|
}
|
|
4005
4159
|
|
|
4006
4160
|
// src/core/Crew.ts
|
|
4007
|
-
import { nanoid as nanoid4 } from "nanoid";
|
|
4008
4161
|
var Crew = class {
|
|
4009
4162
|
id;
|
|
4010
4163
|
name;
|
|
@@ -4024,7 +4177,7 @@ var Crew = class {
|
|
|
4024
4177
|
timeline = [];
|
|
4025
4178
|
results = /* @__PURE__ */ new Map();
|
|
4026
4179
|
constructor(config) {
|
|
4027
|
-
this.id =
|
|
4180
|
+
this.id = nanoid();
|
|
4028
4181
|
this.name = config.name;
|
|
4029
4182
|
this.description = config.description;
|
|
4030
4183
|
this.config = config;
|
|
@@ -4044,7 +4197,12 @@ var Crew = class {
|
|
|
4044
4197
|
*/
|
|
4045
4198
|
initializeAgents() {
|
|
4046
4199
|
for (const agentConfig of this.config.agents) {
|
|
4047
|
-
const agent = createCrewAgent({
|
|
4200
|
+
const agent = createCrewAgent({
|
|
4201
|
+
config: agentConfig,
|
|
4202
|
+
execute: this.config.execute,
|
|
4203
|
+
mock: this.config.mock,
|
|
4204
|
+
provider: this.config.provider
|
|
4205
|
+
});
|
|
4048
4206
|
this.addAgent(agent);
|
|
4049
4207
|
}
|
|
4050
4208
|
}
|
|
@@ -4168,27 +4326,40 @@ var Crew = class {
|
|
|
4168
4326
|
await this.sleep(100);
|
|
4169
4327
|
continue;
|
|
4170
4328
|
}
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4329
|
+
const concurrency = Math.max(
|
|
4330
|
+
1,
|
|
4331
|
+
options.maxConcurrentTasks ?? this.config.maxConcurrentTasks ?? 1
|
|
4332
|
+
);
|
|
4333
|
+
if (concurrency === 1) {
|
|
4334
|
+
for (const task of readyTasks) {
|
|
4335
|
+
if (this.state !== "running") break;
|
|
4336
|
+
const delegationResult = await this.delegateTask(task, options);
|
|
4337
|
+
yield this.createEvent({
|
|
4338
|
+
type: "task:assigned",
|
|
4339
|
+
taskId: task.id,
|
|
4340
|
+
agentName: delegationResult.selectedAgent,
|
|
4341
|
+
reason: delegationResult.reason,
|
|
4342
|
+
strategy: this.config.delegationStrategy
|
|
4343
|
+
});
|
|
4344
|
+
const taskResult = await this.executeTask(task, delegationResult);
|
|
4345
|
+
yield this.createEvent({
|
|
4346
|
+
type: "task:completed",
|
|
4347
|
+
taskId: task.id,
|
|
4348
|
+
result: taskResult,
|
|
4349
|
+
agentName: delegationResult.selectedAgent,
|
|
4350
|
+
durationMs: taskResult.latencyMs ?? 0
|
|
4351
|
+
});
|
|
4352
|
+
while (eventQueue.length > 0) {
|
|
4353
|
+
yield eventQueue.shift();
|
|
4354
|
+
}
|
|
4191
4355
|
}
|
|
4356
|
+
} else {
|
|
4357
|
+
yield* this.processReadyTasksConcurrently(
|
|
4358
|
+
readyTasks,
|
|
4359
|
+
options,
|
|
4360
|
+
eventQueue,
|
|
4361
|
+
concurrency
|
|
4362
|
+
);
|
|
4192
4363
|
}
|
|
4193
4364
|
while (this.state === "paused") {
|
|
4194
4365
|
await this.sleep(100);
|
|
@@ -4231,6 +4402,78 @@ var Crew = class {
|
|
|
4231
4402
|
});
|
|
4232
4403
|
this.addTimelineEntry("crew_completed", this.name);
|
|
4233
4404
|
}
|
|
4405
|
+
/**
|
|
4406
|
+
* Execute a batch of ready tasks concurrently with a bounded worker pool.
|
|
4407
|
+
*
|
|
4408
|
+
* Each task still emits its `task:assigned` and `task:completed` events in
|
|
4409
|
+
* order relative to itself, but events across tasks are interleaved as the
|
|
4410
|
+
* workers settle. At most `concurrency` tasks run at once. If any task throws
|
|
4411
|
+
* (after exhausting retries), no further tasks are started, in-flight tasks
|
|
4412
|
+
* are allowed to settle, and the first error is rethrown so the caller's
|
|
4413
|
+
* error handling (crew:error) behaves identically to the sequential path.
|
|
4414
|
+
*/
|
|
4415
|
+
async *processReadyTasksConcurrently(readyTasks, options, eventQueue, concurrency) {
|
|
4416
|
+
let nextIndex = 0;
|
|
4417
|
+
let firstError;
|
|
4418
|
+
const buffer = [];
|
|
4419
|
+
const inFlight = /* @__PURE__ */ new Set();
|
|
4420
|
+
const launch = (task) => {
|
|
4421
|
+
const worker = (async () => {
|
|
4422
|
+
const delegationResult = await this.delegateTask(task, options);
|
|
4423
|
+
buffer.push(
|
|
4424
|
+
this.createEvent({
|
|
4425
|
+
type: "task:assigned",
|
|
4426
|
+
taskId: task.id,
|
|
4427
|
+
agentName: delegationResult.selectedAgent,
|
|
4428
|
+
reason: delegationResult.reason,
|
|
4429
|
+
strategy: this.config.delegationStrategy
|
|
4430
|
+
})
|
|
4431
|
+
);
|
|
4432
|
+
const taskResult = await this.executeTask(task, delegationResult);
|
|
4433
|
+
buffer.push(
|
|
4434
|
+
this.createEvent({
|
|
4435
|
+
type: "task:completed",
|
|
4436
|
+
taskId: task.id,
|
|
4437
|
+
result: taskResult,
|
|
4438
|
+
agentName: delegationResult.selectedAgent,
|
|
4439
|
+
durationMs: taskResult.latencyMs ?? 0
|
|
4440
|
+
})
|
|
4441
|
+
);
|
|
4442
|
+
})().catch((error) => {
|
|
4443
|
+
if (firstError === void 0) {
|
|
4444
|
+
firstError = error;
|
|
4445
|
+
}
|
|
4446
|
+
}).finally(() => {
|
|
4447
|
+
inFlight.delete(worker);
|
|
4448
|
+
});
|
|
4449
|
+
inFlight.add(worker);
|
|
4450
|
+
};
|
|
4451
|
+
const fill = () => {
|
|
4452
|
+
while (inFlight.size < concurrency && nextIndex < readyTasks.length && this.state === "running" && firstError === void 0) {
|
|
4453
|
+
launch(readyTasks[nextIndex++]);
|
|
4454
|
+
}
|
|
4455
|
+
};
|
|
4456
|
+
fill();
|
|
4457
|
+
while (inFlight.size > 0) {
|
|
4458
|
+
await Promise.race(inFlight);
|
|
4459
|
+
while (buffer.length > 0) {
|
|
4460
|
+
yield buffer.shift();
|
|
4461
|
+
}
|
|
4462
|
+
while (eventQueue.length > 0) {
|
|
4463
|
+
yield eventQueue.shift();
|
|
4464
|
+
}
|
|
4465
|
+
fill();
|
|
4466
|
+
}
|
|
4467
|
+
while (buffer.length > 0) {
|
|
4468
|
+
yield buffer.shift();
|
|
4469
|
+
}
|
|
4470
|
+
while (eventQueue.length > 0) {
|
|
4471
|
+
yield eventQueue.shift();
|
|
4472
|
+
}
|
|
4473
|
+
if (firstError !== void 0) {
|
|
4474
|
+
throw firstError;
|
|
4475
|
+
}
|
|
4476
|
+
}
|
|
4234
4477
|
/**
|
|
4235
4478
|
* Delegate a task to an agent
|
|
4236
4479
|
*/
|
|
@@ -4450,7 +4693,7 @@ ${r.output}`).join("\n\n---\n\n");
|
|
|
4450
4693
|
*/
|
|
4451
4694
|
createCheckpoint() {
|
|
4452
4695
|
return {
|
|
4453
|
-
id:
|
|
4696
|
+
id: nanoid(),
|
|
4454
4697
|
crewId: this.id,
|
|
4455
4698
|
crewName: this.name,
|
|
4456
4699
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -4548,6 +4791,7 @@ function createCrew(config) {
|
|
|
4548
4791
|
export {
|
|
4549
4792
|
Role,
|
|
4550
4793
|
createRole,
|
|
4794
|
+
nanoid,
|
|
4551
4795
|
Task,
|
|
4552
4796
|
createTask,
|
|
4553
4797
|
TaskQueue,
|
|
@@ -4555,6 +4799,7 @@ export {
|
|
|
4555
4799
|
ExecutionContext,
|
|
4556
4800
|
createExecutionContext,
|
|
4557
4801
|
AgentCapabilities,
|
|
4802
|
+
createCoreExecutor,
|
|
4558
4803
|
CrewAgent,
|
|
4559
4804
|
createCrewAgent,
|
|
4560
4805
|
AgentRegistry,
|