@taskless-app/swarm 0.6.65 → 0.6.66
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/cli.js +15 -8
- package/dist/overmind.js +39 -16
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -705,16 +705,17 @@ var init_modelPolicy = __esm({
|
|
|
705
705
|
roles: { executor: "glm-5.3", review: "glm-5.3" }
|
|
706
706
|
},
|
|
707
707
|
// Grok CLI. Каталог — живой `grok models` (16.10.2026), целиком и без выдуманных
|
|
708
|
-
// имён: grok-4.7 (дефолт CLI и исполнителя), grok-4.7-build-fast, grok-4.6, grok-4.5
|
|
709
|
-
// TASWM-
|
|
710
|
-
//
|
|
708
|
+
// имён: grok-4.7 (дефолт CLI и исполнителя), grok-4.7-build-fast, grok-4.6, grok-4.5.
|
|
709
|
+
// TASWM-607: исполнитель остаётся на свежей модели. Живой дефолт CLI демон применяет
|
|
710
|
+
// только к роли executor (liveModels.ts). Ревьюер и проверяющий — на облегчённой
|
|
711
|
+
// grok-4.7-build-fast, пока человек не задал свою модель ревьюеров.
|
|
711
712
|
// Тарифа нет: цену пишет CLI.
|
|
712
713
|
{
|
|
713
714
|
id: "xai",
|
|
714
715
|
label: "xAI (Grok)",
|
|
715
716
|
executorId: "grok",
|
|
716
717
|
selectable: true,
|
|
717
|
-
roles: { executor: "grok-4.7", review: "grok-4.7" },
|
|
718
|
+
roles: { executor: "grok-4.7", review: "grok-4.7-build-fast" },
|
|
718
719
|
models: ["grok-4.7", "grok-4.7-build-fast", "grok-4.6", "grok-4.5"]
|
|
719
720
|
},
|
|
720
721
|
// TASWM-565 · шаг 1 из четырёх: провайдер в реестре ЕСТЬ, выбрать его ещё нельзя.
|
|
@@ -1795,7 +1796,9 @@ var init_queuePlan = __esm({
|
|
|
1795
1796
|
init_status();
|
|
1796
1797
|
init_hostPool();
|
|
1797
1798
|
init_hosts();
|
|
1799
|
+
init_modelPolicy();
|
|
1798
1800
|
init_time();
|
|
1801
|
+
init_verifyVerdict();
|
|
1799
1802
|
MIN_MS = 6e4;
|
|
1800
1803
|
QUEUE_NOMINAL_RUN_MS = 25 * MIN_MS;
|
|
1801
1804
|
QUEUE_MIN_TAIL_MS = 3 * MIN_MS;
|
|
@@ -2852,7 +2855,8 @@ var init_liveModels = __esm({
|
|
|
2852
2855
|
|
|
2853
2856
|
// src/swarmModels.ts
|
|
2854
2857
|
function roleDefault(role, providerId) {
|
|
2855
|
-
return liveDefaultModel(providerId) ?? defaultModelFor(role, providerId);
|
|
2858
|
+
if (role === "executor") return liveDefaultModel(providerId) ?? defaultModelFor(role, providerId);
|
|
2859
|
+
return defaultModelFor(role, providerId);
|
|
2856
2860
|
}
|
|
2857
2861
|
function pick2(v) {
|
|
2858
2862
|
const s = typeof v === "string" ? v.trim() : "";
|
|
@@ -3872,7 +3876,7 @@ var init_package = __esm({
|
|
|
3872
3876
|
"package.json"() {
|
|
3873
3877
|
package_default = {
|
|
3874
3878
|
name: "@taskless-app/swarm",
|
|
3875
|
-
version: "0.6.
|
|
3879
|
+
version: "0.6.66",
|
|
3876
3880
|
type: "module",
|
|
3877
3881
|
description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
3878
3882
|
keywords: [
|
|
@@ -3923,7 +3927,7 @@ var init_package = __esm({
|
|
|
3923
3927
|
execa: "^10.0.0",
|
|
3924
3928
|
zod: "3.25.76"
|
|
3925
3929
|
},
|
|
3926
|
-
gitHead: "
|
|
3930
|
+
gitHead: "a6bc0ea303cb5336fd4e130fba73d90365268b6f"
|
|
3927
3931
|
};
|
|
3928
3932
|
}
|
|
3929
3933
|
});
|
|
@@ -9253,6 +9257,8 @@ var SwarmClient = class _SwarmClient {
|
|
|
9253
9257
|
if (!(typeof n === "number" && Number.isFinite(n) && n > 0)) return null;
|
|
9254
9258
|
const str = (v) => typeof v === "string" && v.trim() ? v.trim() : null;
|
|
9255
9259
|
const cost = obj?.swarmSettings?.maxCostUsd;
|
|
9260
|
+
const rawLimit = obj?.swarmSettings?.reviewCycleLimit;
|
|
9261
|
+
const reviewCycleLimit = typeof rawLimit === "number" && Number.isInteger(rawLimit) && rawLimit >= 1 && rawLimit <= 20 ? rawLimit : null;
|
|
9256
9262
|
return {
|
|
9257
9263
|
maxDrones: Math.trunc(n),
|
|
9258
9264
|
// Старый прод (до TASWM-364) поля swarmSettings не отдаёт вовсе — обе модели null,
|
|
@@ -9269,7 +9275,8 @@ var SwarmClient = class _SwarmClient {
|
|
|
9269
9275
|
// значим («гарантия выключена осознанно»), поэтому пропускаем и его, а не только
|
|
9270
9276
|
// положительные: null остаётся ровно за «ручка не задана / старый прод», и только
|
|
9271
9277
|
// он уводит спавн на env-фолбэк и дефолт ядра.
|
|
9272
|
-
maxCostUsd: typeof cost === "number" && Number.isFinite(cost) && cost >= 0 ? cost : null
|
|
9278
|
+
maxCostUsd: typeof cost === "number" && Number.isFinite(cost) && cost >= 0 ? cost : null,
|
|
9279
|
+
reviewCycleLimit
|
|
9273
9280
|
};
|
|
9274
9281
|
}
|
|
9275
9282
|
/**
|
package/dist/overmind.js
CHANGED
|
@@ -702,16 +702,17 @@ var init_modelPolicy = __esm({
|
|
|
702
702
|
roles: { executor: "glm-5.3", review: "glm-5.3" }
|
|
703
703
|
},
|
|
704
704
|
// Grok CLI. Каталог — живой `grok models` (16.10.2026), целиком и без выдуманных
|
|
705
|
-
// имён: grok-4.7 (дефолт CLI и исполнителя), grok-4.7-build-fast, grok-4.6, grok-4.5
|
|
706
|
-
// TASWM-
|
|
707
|
-
//
|
|
705
|
+
// имён: grok-4.7 (дефолт CLI и исполнителя), grok-4.7-build-fast, grok-4.6, grok-4.5.
|
|
706
|
+
// TASWM-607: исполнитель остаётся на свежей модели. Живой дефолт CLI демон применяет
|
|
707
|
+
// только к роли executor (liveModels.ts). Ревьюер и проверяющий — на облегчённой
|
|
708
|
+
// grok-4.7-build-fast, пока человек не задал свою модель ревьюеров.
|
|
708
709
|
// Тарифа нет: цену пишет CLI.
|
|
709
710
|
{
|
|
710
711
|
id: "xai",
|
|
711
712
|
label: "xAI (Grok)",
|
|
712
713
|
executorId: "grok",
|
|
713
714
|
selectable: true,
|
|
714
|
-
roles: { executor: "grok-4.7", review: "grok-4.7" },
|
|
715
|
+
roles: { executor: "grok-4.7", review: "grok-4.7-build-fast" },
|
|
715
716
|
models: ["grok-4.7", "grok-4.7-build-fast", "grok-4.6", "grok-4.5"]
|
|
716
717
|
},
|
|
717
718
|
// TASWM-565 · шаг 1 из четырёх: провайдер в реестре ЕСТЬ, выбрать его ещё нельзя.
|
|
@@ -2026,7 +2027,9 @@ var init_queuePlan = __esm({
|
|
|
2026
2027
|
init_status();
|
|
2027
2028
|
init_hostPool();
|
|
2028
2029
|
init_hosts();
|
|
2030
|
+
init_modelPolicy();
|
|
2029
2031
|
init_time();
|
|
2032
|
+
init_verifyVerdict();
|
|
2030
2033
|
MIN_MS = 6e4;
|
|
2031
2034
|
QUEUE_NOMINAL_RUN_MS = 25 * MIN_MS;
|
|
2032
2035
|
QUEUE_MIN_TAIL_MS = 3 * MIN_MS;
|
|
@@ -3099,7 +3102,8 @@ var init_liveModels = __esm({
|
|
|
3099
3102
|
|
|
3100
3103
|
// src/swarmModels.ts
|
|
3101
3104
|
function roleDefault(role, providerId) {
|
|
3102
|
-
return liveDefaultModel(providerId) ?? defaultModelFor(role, providerId);
|
|
3105
|
+
if (role === "executor") return liveDefaultModel(providerId) ?? defaultModelFor(role, providerId);
|
|
3106
|
+
return defaultModelFor(role, providerId);
|
|
3103
3107
|
}
|
|
3104
3108
|
function pick2(v) {
|
|
3105
3109
|
const s = typeof v === "string" ? v.trim() : "";
|
|
@@ -3135,6 +3139,10 @@ function resolveRunModelRef(run2, swarm, env = process.env) {
|
|
|
3135
3139
|
const providerId = pick2(env.SWARM_MODEL_PROVIDER) ?? DEFAULT_PROVIDER_ID;
|
|
3136
3140
|
return { providerId, model: roleDefault(modelRoleOf(run2.kind), providerId) };
|
|
3137
3141
|
}
|
|
3142
|
+
function modelRefToRecord(run2, ref) {
|
|
3143
|
+
if (!run2 || pick2(run2.model)) return null;
|
|
3144
|
+
return `${ref.providerId}/${ref.model}`;
|
|
3145
|
+
}
|
|
3138
3146
|
function resolveRunEffort(run2, swarm, env = process.env) {
|
|
3139
3147
|
return toEffortLevel(run2.effort) ?? forKind(run2.kind, swarm, toEffortLevel) ?? toEffortLevel(env.SWARM_DRONE_EFFORT) ?? null;
|
|
3140
3148
|
}
|
|
@@ -9525,6 +9533,8 @@ var SwarmClient = class _SwarmClient {
|
|
|
9525
9533
|
if (!(typeof n === "number" && Number.isFinite(n) && n > 0)) return null;
|
|
9526
9534
|
const str2 = (v) => typeof v === "string" && v.trim() ? v.trim() : null;
|
|
9527
9535
|
const cost = obj?.swarmSettings?.maxCostUsd;
|
|
9536
|
+
const rawLimit = obj?.swarmSettings?.reviewCycleLimit;
|
|
9537
|
+
const reviewCycleLimit = typeof rawLimit === "number" && Number.isInteger(rawLimit) && rawLimit >= 1 && rawLimit <= 20 ? rawLimit : null;
|
|
9528
9538
|
return {
|
|
9529
9539
|
maxDrones: Math.trunc(n),
|
|
9530
9540
|
// Старый прод (до TASWM-364) поля swarmSettings не отдаёт вовсе — обе модели null,
|
|
@@ -9541,7 +9551,8 @@ var SwarmClient = class _SwarmClient {
|
|
|
9541
9551
|
// значим («гарантия выключена осознанно»), поэтому пропускаем и его, а не только
|
|
9542
9552
|
// положительные: null остаётся ровно за «ручка не задана / старый прод», и только
|
|
9543
9553
|
// он уводит спавн на env-фолбэк и дефолт ядра.
|
|
9544
|
-
maxCostUsd: typeof cost === "number" && Number.isFinite(cost) && cost >= 0 ? cost : null
|
|
9554
|
+
maxCostUsd: typeof cost === "number" && Number.isFinite(cost) && cost >= 0 ? cost : null,
|
|
9555
|
+
reviewCycleLimit
|
|
9545
9556
|
};
|
|
9546
9557
|
}
|
|
9547
9558
|
/**
|
|
@@ -13056,7 +13067,7 @@ function parkReasonUnretriable(reason) {
|
|
|
13056
13067
|
// package.json
|
|
13057
13068
|
var package_default = {
|
|
13058
13069
|
name: "@taskless-app/swarm",
|
|
13059
|
-
version: "0.6.
|
|
13070
|
+
version: "0.6.66",
|
|
13060
13071
|
type: "module",
|
|
13061
13072
|
description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
13062
13073
|
keywords: [
|
|
@@ -13107,7 +13118,7 @@ var package_default = {
|
|
|
13107
13118
|
execa: "^10.0.0",
|
|
13108
13119
|
zod: "3.25.76"
|
|
13109
13120
|
},
|
|
13110
|
-
gitHead: "
|
|
13121
|
+
gitHead: "a6bc0ea303cb5336fd4e130fba73d90365268b6f"
|
|
13111
13122
|
};
|
|
13112
13123
|
|
|
13113
13124
|
// src/version.ts
|
|
@@ -19123,6 +19134,14 @@ var BASE_NOOP_MARK = "\u0432\u043B\u0438\u0432\u0430\u0442\u044C \u043D\u0435\u0
|
|
|
19123
19134
|
var RESOLVER_RESOLVED_MARK = "\u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442 \u0441 main \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043D \u0440\u0435\u0437\u043E\u043B\u0432\u0435\u0440\u043E\u043C";
|
|
19124
19135
|
var REVIEW_SPAWN_LIMIT = Number(process.env.SWARM_REVIEW_SPAWN_LIMIT) || 3;
|
|
19125
19136
|
var REVIEW_CYCLE_LIMIT = Number(process.env.SWARM_REVIEW_CYCLE_LIMIT) || 3;
|
|
19137
|
+
var REVIEW_CYCLE_LIMIT_CAP = 20;
|
|
19138
|
+
var configuredReviewCycleLimit = null;
|
|
19139
|
+
function configureReviewCycleLimit(n) {
|
|
19140
|
+
configuredReviewCycleLimit = n != null && Number.isInteger(n) && n >= 1 && n <= REVIEW_CYCLE_LIMIT_CAP ? n : null;
|
|
19141
|
+
}
|
|
19142
|
+
function effectiveReviewCycleLimit() {
|
|
19143
|
+
return configuredReviewCycleLimit ?? REVIEW_CYCLE_LIMIT;
|
|
19144
|
+
}
|
|
19126
19145
|
var CI_WAKE_LIMIT = Number(process.env.SWARM_CI_WAKE_LIMIT) || 3;
|
|
19127
19146
|
var CI_WAKE_COOLDOWN_MS = Number(process.env.SWARM_CI_WAKE_COOLDOWN_MS) || 3 * 60 * 1e3;
|
|
19128
19147
|
var CI_CHECK_COOLDOWN_MS = Number(process.env.SWARM_CI_CHECK_COOLDOWN_MS) || 60 * 1e3;
|
|
@@ -19605,11 +19624,13 @@ function relinkUnboundReviewers(deps) {
|
|
|
19605
19624
|
narrate(deps, `${droneLabel(rv)} \u0440\u0430\u0431\u043E\u0442\u0430\u043B \u0431\u0435\u0437 \u043F\u0440\u0438\u0432\u044F\u0437\u043A\u0438 \u043A \u043F\u0440\u043E\u0433\u043E\u043D\u0443 \u2014 \u0441\u0432\u044F\u0437\u0430\u043B \u043F\u043E PR-\u0441\u0441\u044B\u043B\u043A\u0435, \u0432\u0435\u0440\u0434\u0438\u043A\u0442 \u0442\u0435\u043F\u0435\u0440\u044C \u043B\u044F\u0436\u0435\u0442 \u0432 ${parent.task_slug}, \u0430 \u043D\u0435 \u0442\u043E\u043B\u044C\u043A\u043E \u0432 \u043A\u043E\u043C\u043C\u0435\u043D\u0442 GitHub.`);
|
|
19606
19625
|
}
|
|
19607
19626
|
}
|
|
19608
|
-
|
|
19627
|
+
function escalationLimits() {
|
|
19628
|
+
return { reviewSpawn: REVIEW_SPAWN_LIMIT, reviewCycle: effectiveReviewCycleLimit() };
|
|
19629
|
+
}
|
|
19609
19630
|
function deliberateReviewStop(db, run2) {
|
|
19610
19631
|
const texts = db.events(run2.id).map((e) => e.text ?? "");
|
|
19611
19632
|
const hit = findEscalation(texts, run2, "reviewer");
|
|
19612
|
-
return hit?.stopReason?.(run2,
|
|
19633
|
+
return hit?.stopReason?.(run2, escalationLimits()) ?? null;
|
|
19613
19634
|
}
|
|
19614
19635
|
function noteReviewBlocked(deps, run2, reason) {
|
|
19615
19636
|
if (!shouldNoteReason(deps.db, run2.id, reason)) return;
|
|
@@ -20591,7 +20612,7 @@ async function spawnFreshReviewerAfterStall(deps, run2, why) {
|
|
|
20591
20612
|
deps.db.addEvent(run2.id, "step", `\u0441\u0432\u0435\u0436\u0438\u0439 \u0440\u0435\u0432\u044C\u044E\u0435\u0440 \u043D\u0435 \u043D\u0443\u0436\u0435\u043D: ${live2[0].name} \u0435\u0449\u0451 \u0436\u0438\u0432 (${live2[0].stop_reason ?? live2[0].status})`);
|
|
20592
20613
|
return;
|
|
20593
20614
|
}
|
|
20594
|
-
if (run2.review_cycle >=
|
|
20615
|
+
if (run2.review_cycle >= effectiveReviewCycleLimit() || deps.db.reviewerAttemptCountFor(run2.id) >= REVIEW_SPAWN_LIMIT) {
|
|
20595
20616
|
return;
|
|
20596
20617
|
}
|
|
20597
20618
|
const gate = await prGateForReviewer(deps, run2, run2.pr_url, "\u043F\u043E\u043A\u0430 \u0436\u0434\u0430\u043B CI");
|
|
@@ -20615,7 +20636,7 @@ async function wakeAuthorOnChanges(deps, snapshot, now, droneCap) {
|
|
|
20615
20636
|
if (deps.resourcesOk && !deps.resourcesOk()) return false;
|
|
20616
20637
|
if (countActiveDrones(deps.db) >= droneCap) return false;
|
|
20617
20638
|
if (!await projectQuotaGateAllows(deps, run2)) return false;
|
|
20618
|
-
if (run2.review_cycle >=
|
|
20639
|
+
if (run2.review_cycle >= effectiveReviewCycleLimit()) return false;
|
|
20619
20640
|
const prUrl = run2.pr_url;
|
|
20620
20641
|
const events = deps.db.events(run2.id);
|
|
20621
20642
|
const mark = `${CHANGES_WAKE_ESCALATION_MARK} (\u043A\u0440\u0443\u0433 ${run2.review_cycle ?? 0})`;
|
|
@@ -22284,7 +22305,7 @@ async function tickOnce(deps) {
|
|
|
22284
22305
|
// рано, спавнить второго нельзя.
|
|
22285
22306
|
liveOrWaitingReviewers(deps.db, run2.id).length === 0;
|
|
22286
22307
|
if (reviewerGatesOk && deps.spawnReviewer && await projectWantsChecks(deps, run2)) {
|
|
22287
|
-
if (run2.review_cycle >=
|
|
22308
|
+
if (run2.review_cycle >= effectiveReviewCycleLimit()) {
|
|
22288
22309
|
if (!deps.db.events(run2.id).some((e) => e.kind === "step" && (e.text ?? "").includes(REVIEW_CYCLE_ESCALATION_MARK))) {
|
|
22289
22310
|
deps.db.addEvent(run2.id, "step", `${REVIEW_CYCLE_ESCALATION_MARK}: ${run2.review_cycle} \u0446\u0438\u043A\u043B(\u043E\u0432) \u0440\u0435\u0432\u044C\u044E-\u0444\u0438\u043A\u0441\u043E\u0432 \u2014 \u043D\u0443\u0436\u0435\u043D \u0447\u0435\u043B\u043E\u0432\u0435\u043A`);
|
|
22290
22311
|
narrate(deps, `\u0420\u0435-\u0440\u0435\u0432\u044C\u044E ${droneLabel(run2)} \u0437\u0430\u0446\u0438\u043A\u043B\u0438\u043B\u043E\u0441\u044C (${run2.review_cycle} \u0444\u0438\u043A\u0441-\u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439) \u2014 \u043D\u0443\u0436\u0435\u043D \u0447\u0435\u043B\u043E\u0432\u0435\u043A.`);
|
|
@@ -23386,9 +23407,8 @@ async function runDaemon(opts) {
|
|
|
23386
23407
|
recordModelRef: (runId, ref, run2) => {
|
|
23387
23408
|
if (runModelRefPin.size > 4096) runModelRefPin.clear();
|
|
23388
23409
|
runModelRefPin.set(runId, ref);
|
|
23389
|
-
|
|
23390
|
-
|
|
23391
|
-
}
|
|
23410
|
+
const model = modelRefToRecord(run2, ref);
|
|
23411
|
+
if (model) db.updateRun(runId, { model });
|
|
23392
23412
|
},
|
|
23393
23413
|
maxCostUsd: () => lastMaxCostUsd,
|
|
23394
23414
|
// TASWM-535: поднятый потолок тяжёлого прогона живёт в его ленте — спавн читает её
|
|
@@ -23574,6 +23594,7 @@ async function runDaemon(opts) {
|
|
|
23574
23594
|
lastSwarmModels = settings.models;
|
|
23575
23595
|
lastSwarmEfforts = settings.efforts;
|
|
23576
23596
|
lastMaxCostUsd = settings.maxCostUsd;
|
|
23597
|
+
configureReviewCycleLimit(settings.reviewCycleLimit);
|
|
23577
23598
|
}
|
|
23578
23599
|
return settings?.maxDrones ?? null;
|
|
23579
23600
|
},
|
|
@@ -24640,6 +24661,8 @@ export {
|
|
|
24640
24661
|
buildVerifierPrompt,
|
|
24641
24662
|
cancelRun,
|
|
24642
24663
|
capacityProvenance,
|
|
24664
|
+
configureReviewCycleLimit,
|
|
24665
|
+
effectiveReviewCycleLimit,
|
|
24643
24666
|
hasLiveDescendant,
|
|
24644
24667
|
isSubrun,
|
|
24645
24668
|
lastChangesSummary,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taskless-app/swarm",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.66",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
6
6
|
"keywords": [
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"execa": "^10.0.0",
|
|
40
40
|
"zod": "3.25.76"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "a6bc0ea303cb5336fd4e130fba73d90365268b6f",
|
|
43
43
|
"scripts": {
|
|
44
44
|
"overmind": "NODE_OPTIONS=\"${NODE_OPTIONS:-} --conditions=development\" tsx src/overmind.ts",
|
|
45
45
|
"swarm": "NODE_OPTIONS=\"${NODE_OPTIONS:-} --conditions=development\" tsx src/cli.ts",
|