@taskless-app/swarm 0.6.60 → 0.6.62
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 +13 -2
- package/dist/overmind.js +165 -61
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -3616,7 +3616,7 @@ var init_package = __esm({
|
|
|
3616
3616
|
"package.json"() {
|
|
3617
3617
|
package_default = {
|
|
3618
3618
|
name: "@taskless-app/swarm",
|
|
3619
|
-
version: "0.6.
|
|
3619
|
+
version: "0.6.62",
|
|
3620
3620
|
type: "module",
|
|
3621
3621
|
description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
3622
3622
|
keywords: [
|
|
@@ -3667,7 +3667,7 @@ var init_package = __esm({
|
|
|
3667
3667
|
execa: "^10.0.0",
|
|
3668
3668
|
zod: "3.25.76"
|
|
3669
3669
|
},
|
|
3670
|
-
gitHead: "
|
|
3670
|
+
gitHead: "e999630218010a25c03a6024e1b71ef34b2359ec"
|
|
3671
3671
|
};
|
|
3672
3672
|
}
|
|
3673
3673
|
});
|
|
@@ -5018,6 +5018,8 @@ function rowToRun(row) {
|
|
|
5018
5018
|
// базовая ветка PR (TASWM-285); null → дефолтная
|
|
5019
5019
|
workspace_id: row.workspace_id ?? null,
|
|
5020
5020
|
// воркспейс задачи прогона (TASWM-288); null → глобальный пин
|
|
5021
|
+
// TASWM-597: repoless-прогон (офлайн-проект, без worktree/PR). null/0 → код-конвейер.
|
|
5022
|
+
repoless: row.repoless === 1,
|
|
5021
5023
|
created_at: row.created_at,
|
|
5022
5024
|
updated_at: row.updated_at
|
|
5023
5025
|
};
|
|
@@ -5089,6 +5091,7 @@ CREATE TABLE IF NOT EXISTS runs (
|
|
|
5089
5091
|
priority INTEGER NOT NULL DEFAULT 0,
|
|
5090
5092
|
base_branch TEXT,
|
|
5091
5093
|
workspace_id TEXT,
|
|
5094
|
+
repoless INTEGER,
|
|
5092
5095
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
5093
5096
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
5094
5097
|
);
|
|
@@ -5186,6 +5189,8 @@ CREATE TABLE IF NOT EXISTS imports (
|
|
|
5186
5189
|
"ALTER TABLE runs ADD COLUMN base_branch TEXT",
|
|
5187
5190
|
// Воркспейс задачи прогона (TASWM-288): им пинятся задачные MCP-вызовы прогона.
|
|
5188
5191
|
"ALTER TABLE runs ADD COLUMN workspace_id TEXT",
|
|
5192
|
+
// TASWM-597: repoless-прогон — задача офлайн-проекта, спавн без worktree/ветки/PR.
|
|
5193
|
+
"ALTER TABLE runs ADD COLUMN repoless INTEGER",
|
|
5189
5194
|
// Чем обошёлся прогон, кроме денег (TASWM-353): токены вход/выход и время работы.
|
|
5190
5195
|
"ALTER TABLE runs ADD COLUMN tokens_in INTEGER NOT NULL DEFAULT 0",
|
|
5191
5196
|
"ALTER TABLE runs ADD COLUMN tokens_out INTEGER NOT NULL DEFAULT 0",
|
|
@@ -5362,6 +5367,7 @@ CREATE TABLE IF NOT EXISTS imports (
|
|
|
5362
5367
|
const arr = v;
|
|
5363
5368
|
return arr && arr.length ? JSON.stringify(arr) : null;
|
|
5364
5369
|
}
|
|
5370
|
+
if (f === "repoless") return v === true ? 1 : v === false ? 0 : null;
|
|
5365
5371
|
if (f === "area" && typeof v === "string") return normalizeZoneLabel(v) || null;
|
|
5366
5372
|
return v;
|
|
5367
5373
|
});
|
|
@@ -9669,6 +9675,7 @@ var SwarmClient = class _SwarmClient {
|
|
|
9669
9675
|
local.return_reason = toReturnReason(pr.returnReason) ?? local.return_reason;
|
|
9670
9676
|
local.review_phase = pr.reviewPhase ?? local.review_phase;
|
|
9671
9677
|
local.repo = this.resolveRepo(pr.repo ?? null);
|
|
9678
|
+
if (typeof pr.repoless === "boolean") local.repoless = pr.repoless;
|
|
9672
9679
|
local.host_id = pr.hostId ?? null;
|
|
9673
9680
|
local.host_name = pr.hostName ?? null;
|
|
9674
9681
|
local.host_pinned = pr.hostPinned === true;
|
|
@@ -12799,6 +12806,10 @@ function makeLauncher(cfg) {
|
|
|
12799
12806
|
SWARM_RUN_KIND: run.kind,
|
|
12800
12807
|
SWARM_RUN_NAME: run.name,
|
|
12801
12808
|
...run.workspace_id ? { SWARM_WORKSPACE_ID: run.workspace_id } : {},
|
|
12809
|
+
// TASWM-598: repoless-прогон той же спавн-фиксацией — гейт done() («сдача отчётом,
|
|
12810
|
+
// не PR») обязан срабатывать и по данным СПАВНА, а не только по строке прогона от
|
|
12811
|
+
// демона (тот же класс граблей, что у SWARM_REVIEWS_RUN_ID в TASWM-375).
|
|
12812
|
+
...run.repoless ? { SWARM_RUN_REPOLESS: "1" } : {},
|
|
12802
12813
|
...run.reviews_run_id != null ? { SWARM_REVIEWS_RUN_ID: String(run.reviews_run_id) } : {},
|
|
12803
12814
|
// TASWM-344: та же роль, что у SWARM_REVIEWS_RUN_ID выше, для верификатора — без неё
|
|
12804
12815
|
// его done() в client-режиме пошёл бы веткой обычной сдачи PR, и вердикт пропал бы.
|
package/dist/overmind.js
CHANGED
|
@@ -4787,8 +4787,8 @@ __export(droneChannel_exports, {
|
|
|
4787
4787
|
verifyLocalCliToken: () => verifyLocalCliToken
|
|
4788
4788
|
});
|
|
4789
4789
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
4790
|
-
import { chmodSync as chmodSync2, mkdirSync as
|
|
4791
|
-
import { dirname as
|
|
4790
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync10, readFileSync as readFileSync19, writeFileSync as writeFileSync12 } from "fs";
|
|
4791
|
+
import { dirname as dirname5 } from "path";
|
|
4792
4792
|
import { serve } from "@hono/node-server";
|
|
4793
4793
|
function loadChannelSecret(path) {
|
|
4794
4794
|
try {
|
|
@@ -4797,7 +4797,7 @@ function loadChannelSecret(path) {
|
|
|
4797
4797
|
} catch {
|
|
4798
4798
|
}
|
|
4799
4799
|
const secret = randomBytes(32).toString("hex");
|
|
4800
|
-
|
|
4800
|
+
mkdirSync10(dirname5(path), { recursive: true });
|
|
4801
4801
|
writeFileSync12(path, secret, { mode: 384 });
|
|
4802
4802
|
try {
|
|
4803
4803
|
chmodSync2(path, 384);
|
|
@@ -5188,7 +5188,7 @@ var init_droneChannel = __esm({
|
|
|
5188
5188
|
|
|
5189
5189
|
// src/attachments.ts
|
|
5190
5190
|
import { mkdir as mkdir3, rm as rm3, writeFile as writeFile3 } from "fs/promises";
|
|
5191
|
-
import { join as
|
|
5191
|
+
import { join as join26 } from "path";
|
|
5192
5192
|
function attachmentsFromDoc(doc, origin) {
|
|
5193
5193
|
const out = [];
|
|
5194
5194
|
const walk2 = (node) => {
|
|
@@ -5279,7 +5279,7 @@ async function materializeAttachments(opts) {
|
|
|
5279
5279
|
};
|
|
5280
5280
|
const result = { files: [], skipped: [] };
|
|
5281
5281
|
if (opts.refs.length === 0) return result;
|
|
5282
|
-
const dir =
|
|
5282
|
+
const dir = join26(opts.worktree, ATTACHMENTS_DIR);
|
|
5283
5283
|
await io.removeDir(dir);
|
|
5284
5284
|
let dirReady = false;
|
|
5285
5285
|
let total = 0;
|
|
@@ -5325,7 +5325,7 @@ async function materializeAttachments(opts) {
|
|
|
5325
5325
|
await io.mkdir(dir);
|
|
5326
5326
|
dirReady = true;
|
|
5327
5327
|
}
|
|
5328
|
-
await io.writeFile(
|
|
5328
|
+
await io.writeFile(join26(dir, name), file.bytes);
|
|
5329
5329
|
} catch (e) {
|
|
5330
5330
|
result.skipped.push(`${label2} \u2014 \u043D\u0435 \u0437\u0430\u043F\u0438\u0441\u0430\u043B\u043E\u0441\u044C \u043D\u0430 \u0434\u0438\u0441\u043A (${errText2(e)})`);
|
|
5331
5331
|
continue;
|
|
@@ -5478,7 +5478,7 @@ var init_attachments = __esm({
|
|
|
5478
5478
|
|
|
5479
5479
|
// src/shotUpload.ts
|
|
5480
5480
|
import { readFile as fsReadFile } from "fs/promises";
|
|
5481
|
-
import { basename as basename4, isAbsolute as isAbsolute4, join as
|
|
5481
|
+
import { basename as basename4, isAbsolute as isAbsolute4, join as join27 } from "path";
|
|
5482
5482
|
function shotMimetype(path) {
|
|
5483
5483
|
const dot = path.lastIndexOf(".");
|
|
5484
5484
|
if (dot < 0) return null;
|
|
@@ -5504,7 +5504,7 @@ async function readShots(paths, opts) {
|
|
|
5504
5504
|
}
|
|
5505
5505
|
let bytes;
|
|
5506
5506
|
try {
|
|
5507
|
-
bytes = await read(isAbsolute4(path) ? path :
|
|
5507
|
+
bytes = await read(isAbsolute4(path) ? path : join27(opts.worktree, path));
|
|
5508
5508
|
} catch (e) {
|
|
5509
5509
|
skipped.push({ path, reason: `\u043D\u0435 \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u043D: ${e instanceof Error ? e.message : String(e)}` });
|
|
5510
5510
|
continue;
|
|
@@ -5586,7 +5586,7 @@ var init_shotUpload = __esm({
|
|
|
5586
5586
|
// src/oauth.ts
|
|
5587
5587
|
import { createHash as createHash3, randomBytes as randomBytes2 } from "crypto";
|
|
5588
5588
|
import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, unlinkSync as unlinkSync4 } from "fs";
|
|
5589
|
-
import { join as
|
|
5589
|
+
import { join as join28 } from "path";
|
|
5590
5590
|
function makePkce() {
|
|
5591
5591
|
const verifier = randomBytes2(48).toString("base64url");
|
|
5592
5592
|
const challenge = createHash3("sha256").update(verifier).digest("base64url");
|
|
@@ -5721,8 +5721,8 @@ var init_oauth = __esm({
|
|
|
5721
5721
|
AUTHORIZE = "/api/oauth/authorize";
|
|
5722
5722
|
TOKEN = "/api/oauth/token";
|
|
5723
5723
|
SCOPE = "openid profile email taskless:full";
|
|
5724
|
-
STORE_PATH2 =
|
|
5725
|
-
CLIENT_PATH =
|
|
5724
|
+
STORE_PATH2 = join28(SWARM_HOME, "oauth.json");
|
|
5725
|
+
CLIENT_PATH = join28(SWARM_HOME, "oauth-client.json");
|
|
5726
5726
|
base2 = (api) => api.replace(/\/$/, "");
|
|
5727
5727
|
}
|
|
5728
5728
|
});
|
|
@@ -5769,7 +5769,7 @@ var init_authState = __esm({
|
|
|
5769
5769
|
|
|
5770
5770
|
// src/workspace.ts
|
|
5771
5771
|
import { readFileSync as readFileSync21, writeFileSync as writeFileSync14, unlinkSync as unlinkSync5 } from "fs";
|
|
5772
|
-
import { join as
|
|
5772
|
+
import { join as join29 } from "path";
|
|
5773
5773
|
function loadWorkspace() {
|
|
5774
5774
|
try {
|
|
5775
5775
|
const w = JSON.parse(readFileSync21(WORKSPACE_PATH, "utf8"));
|
|
@@ -5786,7 +5786,7 @@ var init_workspace = __esm({
|
|
|
5786
5786
|
"src/workspace.ts"() {
|
|
5787
5787
|
"use strict";
|
|
5788
5788
|
init_config();
|
|
5789
|
-
WORKSPACE_PATH =
|
|
5789
|
+
WORKSPACE_PATH = join29(SWARM_HOME, "workspace.json");
|
|
5790
5790
|
}
|
|
5791
5791
|
});
|
|
5792
5792
|
|
|
@@ -6389,7 +6389,7 @@ __export(db_exports, {
|
|
|
6389
6389
|
});
|
|
6390
6390
|
import { createRequire as createRequire2 } from "module";
|
|
6391
6391
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
6392
|
-
import { existsSync as
|
|
6392
|
+
import { existsSync as existsSync16 } from "fs";
|
|
6393
6393
|
import { resolve as resolve4 } from "path";
|
|
6394
6394
|
function rowToQuestion(row) {
|
|
6395
6395
|
return {
|
|
@@ -6471,6 +6471,8 @@ function rowToRun(row) {
|
|
|
6471
6471
|
// базовая ветка PR (TASWM-285); null → дефолтная
|
|
6472
6472
|
workspace_id: row.workspace_id ?? null,
|
|
6473
6473
|
// воркспейс задачи прогона (TASWM-288); null → глобальный пин
|
|
6474
|
+
// TASWM-597: repoless-прогон (офлайн-проект, без worktree/PR). null/0 → код-конвейер.
|
|
6475
|
+
repoless: row.repoless === 1,
|
|
6474
6476
|
created_at: row.created_at,
|
|
6475
6477
|
updated_at: row.updated_at
|
|
6476
6478
|
};
|
|
@@ -6542,6 +6544,7 @@ CREATE TABLE IF NOT EXISTS runs (
|
|
|
6542
6544
|
priority INTEGER NOT NULL DEFAULT 0,
|
|
6543
6545
|
base_branch TEXT,
|
|
6544
6546
|
workspace_id TEXT,
|
|
6547
|
+
repoless INTEGER,
|
|
6545
6548
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
6546
6549
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
6547
6550
|
);
|
|
@@ -6639,6 +6642,8 @@ CREATE TABLE IF NOT EXISTS imports (
|
|
|
6639
6642
|
"ALTER TABLE runs ADD COLUMN base_branch TEXT",
|
|
6640
6643
|
// Воркспейс задачи прогона (TASWM-288): им пинятся задачные MCP-вызовы прогона.
|
|
6641
6644
|
"ALTER TABLE runs ADD COLUMN workspace_id TEXT",
|
|
6645
|
+
// TASWM-597: repoless-прогон — задача офлайн-проекта, спавн без worktree/ветки/PR.
|
|
6646
|
+
"ALTER TABLE runs ADD COLUMN repoless INTEGER",
|
|
6642
6647
|
// Чем обошёлся прогон, кроме денег (TASWM-353): токены вход/выход и время работы.
|
|
6643
6648
|
"ALTER TABLE runs ADD COLUMN tokens_in INTEGER NOT NULL DEFAULT 0",
|
|
6644
6649
|
"ALTER TABLE runs ADD COLUMN tokens_out INTEGER NOT NULL DEFAULT 0",
|
|
@@ -6815,6 +6820,7 @@ CREATE TABLE IF NOT EXISTS imports (
|
|
|
6815
6820
|
const arr = v;
|
|
6816
6821
|
return arr && arr.length ? JSON.stringify(arr) : null;
|
|
6817
6822
|
}
|
|
6823
|
+
if (f === "repoless") return v === true ? 1 : v === false ? 0 : null;
|
|
6818
6824
|
if (f === "area" && typeof v === "string") return normalizeZoneLabel(v) || null;
|
|
6819
6825
|
return v;
|
|
6820
6826
|
});
|
|
@@ -7047,7 +7053,7 @@ CREATE TABLE IF NOT EXISTS imports (
|
|
|
7047
7053
|
const repoN = normalizeRepo(repo);
|
|
7048
7054
|
const already = this.db.prepare("SELECT run_count FROM imports WHERE source = ?").get(abs);
|
|
7049
7055
|
if (already) return { imported: false, runs: already.run_count };
|
|
7050
|
-
if (!
|
|
7056
|
+
if (!existsSync16(abs)) throw new Error(`import-db: \u0444\u0430\u0439\u043B\u0430 \u043D\u0435\u0442: ${abs}`);
|
|
7051
7057
|
const src = new this.databaseCtor(abs);
|
|
7052
7058
|
try {
|
|
7053
7059
|
const runs = src.prepare("SELECT * FROM runs ORDER BY id").all();
|
|
@@ -7417,8 +7423,8 @@ var init_droneStore = __esm({
|
|
|
7417
7423
|
|
|
7418
7424
|
// src/overmind.ts
|
|
7419
7425
|
import { homedir as homedir7 } from "os";
|
|
7420
|
-
import { existsSync as
|
|
7421
|
-
import { basename as basename6, dirname as
|
|
7426
|
+
import { existsSync as existsSync21, readFileSync as readFileSync25, readdirSync as readdirSync14, renameSync as renameSync12, statSync as statSync13 } from "fs";
|
|
7427
|
+
import { basename as basename6, dirname as dirname6, join as join36 } from "path";
|
|
7422
7428
|
import { fileURLToPath as fileURLToPath3, pathToFileURL } from "url";
|
|
7423
7429
|
import { spawn as spawn4 } from "child_process";
|
|
7424
7430
|
|
|
@@ -9917,6 +9923,7 @@ var SwarmClient = class _SwarmClient {
|
|
|
9917
9923
|
local.return_reason = toReturnReason(pr.returnReason) ?? local.return_reason;
|
|
9918
9924
|
local.review_phase = pr.reviewPhase ?? local.review_phase;
|
|
9919
9925
|
local.repo = this.resolveRepo(pr.repo ?? null);
|
|
9926
|
+
if (typeof pr.repoless === "boolean") local.repoless = pr.repoless;
|
|
9920
9927
|
local.host_id = pr.hostId ?? null;
|
|
9921
9928
|
local.host_name = pr.hostName ?? null;
|
|
9922
9929
|
local.host_pinned = pr.hostPinned === true;
|
|
@@ -11425,6 +11432,10 @@ function makeLauncher(cfg) {
|
|
|
11425
11432
|
SWARM_RUN_KIND: run.kind,
|
|
11426
11433
|
SWARM_RUN_NAME: run.name,
|
|
11427
11434
|
...run.workspace_id ? { SWARM_WORKSPACE_ID: run.workspace_id } : {},
|
|
11435
|
+
// TASWM-598: repoless-прогон той же спавн-фиксацией — гейт done() («сдача отчётом,
|
|
11436
|
+
// не PR») обязан срабатывать и по данным СПАВНА, а не только по строке прогона от
|
|
11437
|
+
// демона (тот же класс граблей, что у SWARM_REVIEWS_RUN_ID в TASWM-375).
|
|
11438
|
+
...run.repoless ? { SWARM_RUN_REPOLESS: "1" } : {},
|
|
11428
11439
|
...run.reviews_run_id != null ? { SWARM_REVIEWS_RUN_ID: String(run.reviews_run_id) } : {},
|
|
11429
11440
|
// TASWM-344: та же роль, что у SWARM_REVIEWS_RUN_ID выше, для верификатора — без неё
|
|
11430
11441
|
// его done() в client-режиме пошёл бы веткой обычной сдачи PR, и вердикт пропал бы.
|
|
@@ -12482,6 +12493,11 @@ function depsPromptNotice(report) {
|
|
|
12482
12493
|
|
|
12483
12494
|
// src/orchestrator.ts
|
|
12484
12495
|
init_config();
|
|
12496
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync9, rmSync as rmSync3 } from "fs";
|
|
12497
|
+
import { join as join25, dirname as dirname4 } from "path";
|
|
12498
|
+
function repolessRunDir(worktreesDir, taskSlug) {
|
|
12499
|
+
return join25(dirname4(worktreesDir), "runs", taskSlug);
|
|
12500
|
+
}
|
|
12485
12501
|
var WORKTREE_HELD_STATUSES = /* @__PURE__ */ new Set(["running", "blocked", "review", "paused", "storm_dead"]);
|
|
12486
12502
|
function worktreePathHeldLive(db, path, exceptRunId) {
|
|
12487
12503
|
return db.listRuns().some((r) => r.id !== exceptRunId && r.worktree_path === path && WORKTREE_HELD_STATUSES.has(r.status));
|
|
@@ -12523,6 +12539,24 @@ function healTaskSlug(db, run, task) {
|
|
|
12523
12539
|
return db.updateRun(run.id, { task_slug: slug }) ?? run;
|
|
12524
12540
|
}
|
|
12525
12541
|
async function spawnDrone(deps, run) {
|
|
12542
|
+
if (run.repoless) {
|
|
12543
|
+
const workdir = repolessRunDir(deps.worktreesDir, run.task_slug);
|
|
12544
|
+
if (existsSync15(workdir)) {
|
|
12545
|
+
rmSync3(workdir, { recursive: true, force: true });
|
|
12546
|
+
deps.db.addEvent(run.id, "step", `\u0440\u0435\u043A\u043B\u0435\u0439\u043C \u043E\u0441\u0438\u0440\u043E\u0442\u0435\u0432\u0448\u0435\u0433\u043E \u0441\u043A\u0440\u0430\u0442\u0447-\u043A\u0430\u0442\u0430\u043B\u043E\u0433\u0430 ${workdir} (\u0434\u0435\u0440\u0436\u0430\u043B \u043C\u0451\u0440\u0442\u0432\u044B\u0439 \u043F\u0440\u043E\u0433\u043E\u043D)`);
|
|
12547
|
+
}
|
|
12548
|
+
mkdirSync9(workdir, { recursive: true });
|
|
12549
|
+
if (run.area && deps.db.runningAreas("").includes(run.area)) throw new AreaBusyError(run.area);
|
|
12550
|
+
deps.db.addEvent(run.id, "step", `repoless-\u043F\u0440\u043E\u0433\u043E\u043D: \u0441\u043A\u0440\u0430\u0442\u0447-\u043A\u0430\u0442\u0430\u043B\u043E\u0433 ${workdir} (\u0431\u0435\u0437 worktree/\u0432\u0435\u0442\u043A\u0438/PR \u2014 TASWM-595)`);
|
|
12551
|
+
const built2 = await deps.buildPrompt(run, workdir);
|
|
12552
|
+
const pid2 = deps.launch({ worktree: workdir, run, prompt: built2 });
|
|
12553
|
+
deps.db.addEvent(run.id, "step", `\u0434\u0440\u043E\u043D \u0437\u0430\u043F\u0443\u0449\u0435\u043D \u0432 ${workdir} (pid ${pid2})`);
|
|
12554
|
+
return deps.db.updateRun(run.id, {
|
|
12555
|
+
status: "running",
|
|
12556
|
+
worktree_path: workdir,
|
|
12557
|
+
pid: pid2
|
|
12558
|
+
});
|
|
12559
|
+
}
|
|
12526
12560
|
const repo = normalizeRepo(run.repo || deps.repo || "");
|
|
12527
12561
|
if (!repo) throw new Error(`\u0443 \u043F\u0440\u043E\u0433\u043E\u043D\u0430 #${run.id} (${run.task_slug}) \u043D\u0435\u0442 repo \u0438 \u043D\u0435\u0442 \u0434\u0435\u0444\u043E\u043B\u0442\u0430 SWARM_REPO`);
|
|
12528
12562
|
const conflict = deps.conflicts ? await deps.conflicts(run, repo) : { kind: "unknown" };
|
|
@@ -12726,7 +12760,7 @@ function parkReasonUnretriable(reason) {
|
|
|
12726
12760
|
// package.json
|
|
12727
12761
|
var package_default = {
|
|
12728
12762
|
name: "@taskless-app/swarm",
|
|
12729
|
-
version: "0.6.
|
|
12763
|
+
version: "0.6.62",
|
|
12730
12764
|
type: "module",
|
|
12731
12765
|
description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
12732
12766
|
keywords: [
|
|
@@ -12777,7 +12811,7 @@ var package_default = {
|
|
|
12777
12811
|
execa: "^10.0.0",
|
|
12778
12812
|
zod: "3.25.76"
|
|
12779
12813
|
},
|
|
12780
|
-
gitHead: "
|
|
12814
|
+
gitHead: "e999630218010a25c03a6024e1b71ef34b2359ec"
|
|
12781
12815
|
};
|
|
12782
12816
|
|
|
12783
12817
|
// src/version.ts
|
|
@@ -13566,7 +13600,7 @@ init_git();
|
|
|
13566
13600
|
|
|
13567
13601
|
// src/diff.ts
|
|
13568
13602
|
import { statSync as statSync12 } from "fs";
|
|
13569
|
-
import { join as
|
|
13603
|
+
import { join as join30 } from "path";
|
|
13570
13604
|
import { $ as $4 } from "execa";
|
|
13571
13605
|
var MAX_FILES = 200;
|
|
13572
13606
|
var MAX_LINES_PER_FILE = 1500;
|
|
@@ -13734,7 +13768,7 @@ async function collectRunDiff(worktree, opts = {}) {
|
|
|
13734
13768
|
files.push(pf);
|
|
13735
13769
|
}
|
|
13736
13770
|
}
|
|
13737
|
-
files.sort((a, b) => mtime(
|
|
13771
|
+
files.sort((a, b) => mtime(join30(worktree, b.path)) - mtime(join30(worktree, a.path)));
|
|
13738
13772
|
const truncatedFiles = files.length > MAX_FILES;
|
|
13739
13773
|
if (truncatedFiles) files = files.slice(0, MAX_FILES);
|
|
13740
13774
|
const added = files.reduce((s, f) => s + f.added, 0);
|
|
@@ -14486,6 +14520,45 @@ ${(summary ?? "").trim()}${shots.warning}`,
|
|
|
14486
14520
|
\u26A0\uFE0F \u0412\u0435\u0440\u0434\u0438\u043A\u0442-\u043A\u043E\u043C\u043C\u0435\u043D\u0442 \u0432 \u0437\u0430\u0434\u0430\u0447\u0443 \u041D\u0415 \u0443\u0435\u0445\u0430\u043B (${commentWarning}) \u2014 \u0432\u0435\u0440\u0434\u0438\u043A\u0442 \u0435\u0441\u0442\u044C \u0442\u043E\u043B\u044C\u043A\u043E \u043D\u0430 \u043F\u0440\u043E\u0433\u043E\u043D\u0435. \u041F\u0440\u043E\u0434\u0443\u0431\u043B\u0438\u0440\u0443\u0439 \u0435\u0433\u043E \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u043E\u043C \u0432 PR: \`gh pr comment ${trustedPrUrl} --body "${verdictText} \u2026"\`.` : "";
|
|
14487
14521
|
return { content: [{ type: "text", text: `\u0432\u0435\u0440\u0434\u0438\u043A\u0442 \u0432\u0435\u0440\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u0438 \u0437\u0430\u043F\u0438\u0441\u0430\u043D (${verdictText})${shotsNote(shots)}${commentNote}` }] };
|
|
14488
14522
|
}
|
|
14523
|
+
if (run?.repoless || opts.repoless) {
|
|
14524
|
+
const report = (summary ?? "").trim();
|
|
14525
|
+
if (!report) {
|
|
14526
|
+
return {
|
|
14527
|
+
content: [
|
|
14528
|
+
{
|
|
14529
|
+
type: "text",
|
|
14530
|
+
text: "done() repoless-\u043F\u0440\u043E\u0433\u043E\u043D\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 summary \u2014 \u043E\u043D \u0443\u0445\u043E\u0434\u0438\u0442 \u041E\u0422\u0427\u0401\u0422\u041E\u041C \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u043E\u043C \u0432 \u0437\u0430\u0434\u0430\u0447\u0443: \u0447\u0442\u043E \u0441\u0434\u0435\u043B\u0430\u043D\u043E, \u0447\u0435\u043C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u043E (\u043F\u043E \u043A\u0440\u0438\u0442\u0435\u0440\u0438\u044F\u043C \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438), \u043A\u0430\u043A\u0438\u0435 \u0440\u0435\u0448\u0435\u043D\u0438\u044F \u043F\u0440\u0438\u043D\u044F\u043B \u0438 \u0447\u0442\u043E \u043E\u0441\u0442\u0430\u043B\u043E\u0441\u044C \u0437\u0430 \u0441\u043A\u043E\u0431\u043A\u0430\u043C\u0438. PR \u0443 \u044D\u0442\u043E\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u043D\u0435\u0442 \u2014 \u043E\u0442\u0447\u0451\u0442 \u0438 \u0435\u0441\u0442\u044C \u0441\u0434\u0430\u0447\u0430."
|
|
14531
|
+
}
|
|
14532
|
+
],
|
|
14533
|
+
isError: true
|
|
14534
|
+
};
|
|
14535
|
+
}
|
|
14536
|
+
const shots = await uploadShots();
|
|
14537
|
+
const slug = run && reportSlug(run.task_slug) || opts.expectedTaskSlug;
|
|
14538
|
+
if (slug && opts.taskless) {
|
|
14539
|
+
try {
|
|
14540
|
+
await opts.taskless.addComment(
|
|
14541
|
+
slug,
|
|
14542
|
+
`\u041E\u0442\u0447\u0451\u0442 (\u0437\u0430\u0434\u0430\u0447\u0430 \u0431\u0435\u0437 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F \u2014 \u0440\u0430\u0431\u043E\u0442\u044B \u0432 git \u043D\u0435\u0442):
|
|
14543
|
+
|
|
14544
|
+
${report}${shots.warning}`,
|
|
14545
|
+
{
|
|
14546
|
+
swarmKind: "report",
|
|
14547
|
+
// TASWM-265: имени взять неоткуда при тонкой строке — честная заглушка.
|
|
14548
|
+
swarmDroneName: run?.name ?? "(\u0438\u043C\u044F \u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u043E)"
|
|
14549
|
+
},
|
|
14550
|
+
shots.attachments
|
|
14551
|
+
);
|
|
14552
|
+
} catch (e) {
|
|
14553
|
+
await store.addEvent(null, "step", `\u043E\u0442\u0447\u0451\u0442 \u0432 \u0437\u0430\u0434\u0430\u0447\u0443 ${slug} \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D: ${e instanceof Error ? e.message : String(e)}`);
|
|
14554
|
+
}
|
|
14555
|
+
} else {
|
|
14556
|
+
await store.addEvent(null, "step", `\u043E\u0442\u0447\u0451\u0442 \u0434\u0440\u043E\u043D\u0430 (Taskless \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D${slug ? "" : ", \u0441\u043B\u0430\u0433 \u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043D"}): ${report}`);
|
|
14557
|
+
}
|
|
14558
|
+
await store.updateRun(null, { status: "done" });
|
|
14559
|
+
await store.addEvent(null, "done", "repoless-\u0441\u0434\u0430\u0447\u0430: \u043E\u0442\u0447\u0451\u0442 \u0432 \u0437\u0430\u0434\u0430\u0447\u0435, \u043F\u0440\u0438\u0451\u043C\u043A\u0430 \u0437\u0430 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u043E\u043C (\u0431\u0435\u0437 PR/CI/mergeGate)");
|
|
14560
|
+
return { content: [{ type: "text", text: `\u043F\u0440\u0438\u043D\u044F\u0442\u043E: \u043E\u0442\u0447\u0451\u0442 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D \u0432 \u0437\u0430\u0434\u0430\u0447\u0443${shotsNote(shots)}, \u043F\u0440\u043E\u0433\u043E\u043D \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D. \u041F\u0440\u0438\u0451\u043C\u043A\u0443 \u0434\u0435\u043B\u0430\u0435\u0442 \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u043F\u043E \u043A\u0440\u0438\u0442\u0435\u0440\u0438\u044F\u043C \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438.` }] };
|
|
14561
|
+
}
|
|
14489
14562
|
if (isGithubPrUrl(pr_url)) {
|
|
14490
14563
|
const report = (summary ?? "").trim();
|
|
14491
14564
|
if (!report) {
|
|
@@ -14717,13 +14790,15 @@ async function runDroneServer(runId) {
|
|
|
14717
14790
|
const expectedKind = toRunKind(process.env.SWARM_RUN_KIND);
|
|
14718
14791
|
const spawnReviewsRunId = Number(process.env.SWARM_REVIEWS_RUN_ID);
|
|
14719
14792
|
const spawnVerifiesRunId = Number(process.env.SWARM_VERIFIES_RUN_ID);
|
|
14793
|
+
const spawnRepoless = process.env.SWARM_RUN_REPOLESS === "1";
|
|
14720
14794
|
const common = {
|
|
14721
14795
|
taskless,
|
|
14722
14796
|
runKind: expectedKind,
|
|
14723
14797
|
prHeadBranch,
|
|
14724
14798
|
...expectedTaskSlug ? { expectedTaskSlug } : {},
|
|
14725
14799
|
...Number.isInteger(spawnReviewsRunId) && spawnReviewsRunId > 0 ? { reviewsRunId: spawnReviewsRunId } : {},
|
|
14726
|
-
...Number.isInteger(spawnVerifiesRunId) && spawnVerifiesRunId > 0 ? { verifiesRunId: spawnVerifiesRunId } : {}
|
|
14800
|
+
...Number.isInteger(spawnVerifiesRunId) && spawnVerifiesRunId > 0 ? { verifiesRunId: spawnVerifiesRunId } : {},
|
|
14801
|
+
...spawnRepoless ? { repoless: true } : {}
|
|
14727
14802
|
};
|
|
14728
14803
|
const channelUrl = process.env.SWARM_DRONE_CHANNEL_URL;
|
|
14729
14804
|
const channelToken = process.env.SWARM_DRONE_CHANNEL_TOKEN;
|
|
@@ -15987,22 +16062,22 @@ async function prodClearMergeIntent(runId, deps = {}) {
|
|
|
15987
16062
|
}
|
|
15988
16063
|
|
|
15989
16064
|
// src/envGate.ts
|
|
15990
|
-
import { existsSync as
|
|
15991
|
-
import { join as
|
|
16065
|
+
import { existsSync as existsSync18 } from "fs";
|
|
16066
|
+
import { join as join32 } from "path";
|
|
15992
16067
|
import { createConnection } from "net";
|
|
15993
16068
|
import { execa as execa2 } from "execa";
|
|
15994
16069
|
|
|
15995
16070
|
// src/platform.ts
|
|
15996
|
-
import { existsSync as
|
|
15997
|
-
import { delimiter as delimiter2, join as
|
|
16071
|
+
import { existsSync as existsSync17, readFileSync as readFileSync22 } from "fs";
|
|
16072
|
+
import { delimiter as delimiter2, join as join31 } from "path";
|
|
15998
16073
|
function resolveCommandPath(name, env = process.env, platform = process.platform) {
|
|
15999
|
-
if (name.includes("/") || name.includes("\\")) return
|
|
16074
|
+
if (name.includes("/") || name.includes("\\")) return existsSync17(name) ? name : null;
|
|
16000
16075
|
const dirs = (env.PATH ?? env.Path ?? "").split(delimiter2).filter(Boolean);
|
|
16001
16076
|
const exts = platform === "win32" ? (env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";").filter(Boolean) : [""];
|
|
16002
16077
|
for (const dir of dirs) {
|
|
16003
16078
|
for (const ext of exts) {
|
|
16004
|
-
const candidate =
|
|
16005
|
-
if (
|
|
16079
|
+
const candidate = join31(dir, name + ext);
|
|
16080
|
+
if (existsSync17(candidate)) return candidate;
|
|
16006
16081
|
}
|
|
16007
16082
|
}
|
|
16008
16083
|
return null;
|
|
@@ -16085,8 +16160,8 @@ var COMPOSE_MARKERS = [
|
|
|
16085
16160
|
"compose.yaml"
|
|
16086
16161
|
];
|
|
16087
16162
|
function detectRequirements(repo, io = {}) {
|
|
16088
|
-
const exists = io.exists ??
|
|
16089
|
-
const marker = COMPOSE_MARKERS.find((f) => exists(
|
|
16163
|
+
const exists = io.exists ?? existsSync18;
|
|
16164
|
+
const marker = COMPOSE_MARKERS.find((f) => exists(join32(repo, f)));
|
|
16090
16165
|
return marker ? [{ kind: "docker", raw: `docker (\u0434\u0435\u0442\u0435\u043A\u0442: ${marker})` }] : [];
|
|
16091
16166
|
}
|
|
16092
16167
|
function resolveRequirements(repo, declared, io = {}) {
|
|
@@ -17842,9 +17917,9 @@ function closeWebServer(server) {
|
|
|
17842
17917
|
// src/hostCommands.ts
|
|
17843
17918
|
init_src();
|
|
17844
17919
|
import { readFileSync as readFileSync23, renameSync as renameSync10, writeFileSync as writeFileSync15 } from "fs";
|
|
17845
|
-
import { join as
|
|
17920
|
+
import { join as join33 } from "path";
|
|
17846
17921
|
function hostCommandStatePath(home) {
|
|
17847
|
-
return
|
|
17922
|
+
return join33(home, "host-command.json");
|
|
17848
17923
|
}
|
|
17849
17924
|
function readState(path) {
|
|
17850
17925
|
try {
|
|
@@ -18018,8 +18093,8 @@ async function doRestart(cmd, opts, note) {
|
|
|
18018
18093
|
|
|
18019
18094
|
// src/selfUpdate.ts
|
|
18020
18095
|
init_git();
|
|
18021
|
-
import { existsSync as
|
|
18022
|
-
import { join as
|
|
18096
|
+
import { existsSync as existsSync19 } from "fs";
|
|
18097
|
+
import { join as join34 } from "path";
|
|
18023
18098
|
import { $ as $5 } from "execa";
|
|
18024
18099
|
var DAEMON_PACKAGE = "@taskless-app/swarm";
|
|
18025
18100
|
var defaultRun = async (cmd, args, cwd) => {
|
|
@@ -18032,7 +18107,7 @@ function tail(text, max = 400) {
|
|
|
18032
18107
|
}
|
|
18033
18108
|
async function runSelfUpdate(io) {
|
|
18034
18109
|
const run = io.run ?? defaultRun;
|
|
18035
|
-
const exists = io.exists ??
|
|
18110
|
+
const exists = io.exists ?? existsSync19;
|
|
18036
18111
|
const repo = io.repo;
|
|
18037
18112
|
await io.onStep("fetch", "\u0442\u044F\u043D\u0443 \u0441\u0432\u0435\u0436\u0438\u0439 \u043A\u043E\u0434");
|
|
18038
18113
|
const fetched = await run("git", ["-C", repo, "fetch", "--quiet", "origin"], repo);
|
|
@@ -18061,7 +18136,7 @@ async function runSelfUpdate(io) {
|
|
|
18061
18136
|
};
|
|
18062
18137
|
}
|
|
18063
18138
|
await io.onStep("install", "\u0441\u0442\u0430\u0432\u043B\u044E \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438");
|
|
18064
|
-
if (!exists(
|
|
18139
|
+
if (!exists(join34(repo, "pnpm-lock.yaml"))) {
|
|
18065
18140
|
return { ok: false, step: "install", message: "\u0432 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u0438 \u0434\u0435\u043C\u043E\u043D\u0430 \u043D\u0435\u0442 pnpm-lock.yaml \u2014 \u043E\u0431\u043D\u043E\u0432\u043B\u044F\u0442\u044C \u0435\u0433\u043E \u044D\u0442\u0438\u043C \u043F\u0443\u0442\u0451\u043C \u043D\u0435 \u0431\u0435\u0440\u0443\u0441\u044C" };
|
|
18066
18141
|
}
|
|
18067
18142
|
const installed2 = await run("pnpm", ["install", "--frozen-lockfile"], repo);
|
|
@@ -18226,18 +18301,18 @@ async function fetchExternalStorm(url, opts = {}) {
|
|
|
18226
18301
|
}
|
|
18227
18302
|
|
|
18228
18303
|
// src/anomalyState.ts
|
|
18229
|
-
import { existsSync as
|
|
18230
|
-
import { join as
|
|
18304
|
+
import { existsSync as existsSync20, readFileSync as readFileSync24, renameSync as renameSync11, writeFileSync as writeFileSync16 } from "fs";
|
|
18305
|
+
import { join as join35 } from "path";
|
|
18231
18306
|
var KEY_TTL_MS = 7 * 24 * 60 * 6e4;
|
|
18232
18307
|
var MAX_RESOLVED = 200;
|
|
18233
18308
|
function emptyState() {
|
|
18234
18309
|
return { since: {}, lastFiredAt: {}, fires: {}, resolved: [], stopQuiet: null };
|
|
18235
18310
|
}
|
|
18236
18311
|
function anomalyStatePath(home) {
|
|
18237
|
-
return
|
|
18312
|
+
return join35(home, "anomaly-state.json");
|
|
18238
18313
|
}
|
|
18239
18314
|
function loadAnomalyState(home, now = Date.now(), io = {}) {
|
|
18240
|
-
const exists = io.exists ??
|
|
18315
|
+
const exists = io.exists ?? existsSync20;
|
|
18241
18316
|
const readFile2 = io.readFile ?? ((p) => readFileSync24(p, "utf8"));
|
|
18242
18317
|
const path = anomalyStatePath(home);
|
|
18243
18318
|
if (!exists(path)) return emptyState();
|
|
@@ -19418,8 +19493,36 @@ function buildChangesFixPrompt(args) {
|
|
|
19418
19493
|
}
|
|
19419
19494
|
var HERO_CONTINUE_NUDGE = "\u0422\u0435\u0431\u044F \u0440\u0430\u0437\u0431\u0443\u0434\u0438\u043B\u0438, \u0413\u0435\u0440\u043E\u0439: \u0432 \u043E\u0442\u0440\u044F\u0434\u0435 \u0447\u0442\u043E-\u0442\u043E \u043F\u0440\u043E\u0438\u0437\u043E\u0448\u043B\u043E (\u0434\u0440\u043E\u043D \u0437\u0430\u0434\u0430\u043B \u0432\u043E\u043F\u0440\u043E\u0441, \u0441\u0434\u0430\u043B PR \u0438\u043B\u0438 \u0443\u043C\u0435\u0440) \u2014 \u043B\u0438\u0431\u043E \u0442\u0435\u0431\u044F \u043F\u043E\u0437\u0432\u0430\u043B \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440. \u0422\u044B headless, \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0435\u0448\u044C \u0422\u041E\u0422 \u0416\u0415 \u044D\u043F\u0438\u043A: \u0443\u0441\u0442\u0430\u0432 \u0438 \u0442\u0435\u043B\u043E \u044D\u043F\u0438\u043A\u0430 \u0443\u0436\u0435 \u0432 \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442\u0435 \u043F\u0440\u043E\u0448\u043B\u043E\u0439 \u0441\u0435\u0441\u0441\u0438\u0438. \u0413\u043B\u044F\u043D\u044C \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u043E\u0442\u0440\u044F\u0434\u0430 (squad_status) \u0438 \u0440\u0430\u0437\u0431\u0435\u0440\u0438\u0441\u044C, \u0447\u0442\u043E \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u043E\u0441\u044C: \u0442\u0435\u0445\u043D\u0438\u0447\u0435\u0441\u043A\u0438\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B \u0434\u0440\u043E\u043D\u043E\u0432 \u0437\u0430\u043A\u0440\u044B\u0432\u0430\u0439 answer_drone; \u043F\u0440\u043E\u0434\u0443\u043A\u0442\u043E\u0432\u043E\u0435/\u0434\u0438\u0437\u0430\u0439\u043D/scope \u2014 \u044D\u0441\u043A\u0430\u043B\u0438\u0440\u0443\u0439 \u0447\u0435\u0440\u0435\u0437 ask. \u041A\u043E\u0434 \u043D\u0435 \u043F\u0438\u0448\u0438, PR \u043D\u0435 \u043C\u0435\u0440\u0436\u0438, done \u041D\u0415 \u0437\u043E\u0432\u0438. \u0420\u0430\u0437\u043E\u0431\u0440\u0430\u043B\u0441\u044F \u0441 \u0440\u044B\u0432\u043A\u043E\u043C \u2014 \u0441\u043D\u043E\u0432\u0430 \u0437\u043E\u0432\u0438 rest(summary) \u0438 \u0437\u0430\u043C\u0440\u0438. \u0412\u043E\u043F\u0440\u043E\u0441\u043E\u0432 \u0432 stdout \u043D\u0435 \u0437\u0430\u0434\u0430\u0432\u0430\u0439 \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0435\u0440\u0435\u0437 ask.";
|
|
19420
19495
|
var HEADLESS_BLOCK = "\u26D4 HEADLESS-\u0420\u0415\u0416\u0418\u041C \u2014 \u0416\u0401\u0421\u0422\u041A\u041E. \u0418\u043D\u0442\u0435\u0440\u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0433\u043E \u0447\u0430\u0442\u0430 \u041D\u0415\u0422: \u0442\u0432\u043E\u0439 stdout \u043D\u0438\u043A\u0442\u043E \u043D\u0435 \u0447\u0438\u0442\u0430\u0435\u0442 \u0438 \u043E\u0442\u0432\u0435\u0442\u0438\u0442\u044C \u043D\u0435 \u043C\u043E\u0436\u0435\u0442. \u041D\u0418\u041A\u041E\u0413\u0414\u0410 \u043D\u0435 \u0437\u0430\u0434\u0430\u0432\u0430\u0439 \u0432\u043E\u043F\u0440\u043E\u0441\u043E\u0432 \u0442\u0435\u043A\u0441\u0442\u043E\u043C \u0438 \u043D\u0435 \u0436\u0434\u0438 \u043E\u0442\u0432\u0435\u0442\u0430 \u0432 \u043A\u043E\u043D\u0441\u043E\u043B\u0438 \u2014 \u0435\u0434\u0438\u043D\u0441\u0442\u0432\u0435\u043D\u043D\u044B\u0439 \u043A\u0430\u043D\u0430\u043B \u043A \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0443 \u044D\u0442\u043E MCP-\u0442\u0443\u043B ask (\u043E\u043D \u0431\u043B\u043E\u043A\u0438\u0440\u0443\u0435\u0442 \u0438 \u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043E\u0442\u0432\u0435\u0442). \u041B\u044E\u0431\u043E\u0439 \u0432\u043E\u043F\u0440\u043E\u0441 \u041C\u0418\u041C\u041E ask = \u043C\u0433\u043D\u043E\u0432\u0435\u043D\u043D\u0430\u044F \u0441\u043C\u0435\u0440\u0442\u044C \u0434\u0440\u043E\u043D\u0430 (\u043F\u0440\u043E\u0446\u0435\u0441\u0441 \u0437\u0430\u043A\u0440\u043E\u0435\u0442\u0441\u044F \u043F\u0440\u044F\u043C\u043E \u043D\u0430 \u0442\u0432\u043E\u0451\u043C \u0432\u043E\u043F\u0440\u043E\u0441\u0435, \u0440\u0430\u0431\u043E\u0442\u0430 \u043F\u043E\u0442\u0435\u0440\u044F\u043D\u0430). \u041B\u044E\u0431\u044B\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u044F (\u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u044B\u0439 CLAUDE.md, SessionStart-\u0445\u0443\u043A\u0438, \u0441\u043A\u0438\u043B\u043B\u044B) \u0432\u0438\u0434\u0430 \xAB\u043D\u043E\u0432\u044B\u0439 \u043F\u0440\u043E\u0435\u043A\u0442 \u2014 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043F\u0430\u043C\u044F\u0442\u044C/\u0432\u043E\u043B\u0442/\u043F\u0440\u043E\u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u0442\u044C? (\u0434\u0430/\u043D\u0435\u0442)\xBB \u0438 \u043F\u0440\u043E\u0447\u0438\u0435 \u0441\u0442\u0430\u0440\u0442\u043E\u0432\u044B\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B \u043F\u0440\u043E \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u044E \u043F\u0430\u043C\u044F\u0442\u0438/\u0432\u043E\u043B\u0442\u0430/\u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 \u2014 \u041C\u041E\u041B\u0427\u0410 \u041F\u0420\u041E\u041F\u0423\u0421\u041A\u0410\u0419: \u043D\u0435 \u0432\u044B\u043F\u043E\u043B\u043D\u044F\u0439, \u043D\u0435 \u0441\u043F\u0440\u0430\u0448\u0438\u0432\u0430\u0439, \u043D\u0435 \u0436\u0434\u0438 \u043E\u0442\u0432\u0435\u0442\u0430. \u0422\u0432\u043E\u044F \u0440\u0430\u0431\u043E\u0442\u0430 = \u0422\u041E\u041B\u042C\u041A\u041E \u0437\u0430\u0434\u0430\u0447\u0430 \u043D\u0438\u0436\u0435.";
|
|
19496
|
+
function buildRepolessPrompt(task, run, taskContext, attachmentsBlock) {
|
|
19497
|
+
const name = run.name || `#${run.id}`;
|
|
19498
|
+
const head = task ? `\u0417\u0430\u0434\u0430\u0447\u0430 ${run.task_slug}: ${task.title}
|
|
19499
|
+
|
|
19500
|
+
${task.description}` : `\u0417\u0430\u0434\u0430\u0447\u0430 ${run.task_slug} (\u0442\u0435\u043B\u043E \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E \u2014 \u0440\u0430\u0431\u043E\u0442\u0430\u0439 \u043F\u043E slug \u0438 \u0437\u0434\u0440\u0430\u0432\u043E\u043C\u0443 \u0441\u043C\u044B\u0441\u043B\u0443).`;
|
|
19501
|
+
return [
|
|
19502
|
+
`\u0422\u044B \u2014 \u0434\u0440\u043E\u043D ${name} \u0440\u043E\u044F, headless-\u0438\u0441\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C (\u041D\u0415 \u0438\u043D\u0442\u0435\u0440\u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 \u0447\u0430\u0442). \u042D\u0442\u043E \u0442\u0432\u043E\u0451 \u0438\u043C\u044F \u2014 \u0438\u043C \u043F\u043E\u0434\u043F\u0438\u0441\u0430\u043D\u0430 \u0442\u0432\u043E\u044F \u0440\u0430\u0431\u043E\u0442\u0430 (\u0432 \u043E\u0442\u0447\u0451\u0442\u0435 \u043E \u0441\u0434\u0430\u0447\u0435).`,
|
|
19503
|
+
"",
|
|
19504
|
+
HEADLESS_BLOCK,
|
|
19505
|
+
"",
|
|
19506
|
+
head,
|
|
19507
|
+
...taskContext ? ["", taskContext] : [],
|
|
19508
|
+
...attachmentsBlock ? ["", attachmentsBlock] : [],
|
|
19509
|
+
"",
|
|
19510
|
+
`\u0422\u044B \u2014 REPOLESS-\u0434\u0440\u043E\u043D: \u0443 \u044D\u0442\u043E\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u041D\u0415\u0422 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F \u0438 \u043A\u043E\u0434-\u043A\u043E\u043D\u0432\u0435\u0439\u0435\u0440\u0430. \u0420\u0430\u0431\u043E\u0442\u0430\u0435\u0448\u044C \u0432 \u0441\u043A\u0440\u0430\u0442\u0447-\u043A\u0430\u0442\u0430\u043B\u043E\u0433\u0435 (\u0442\u0432\u043E\u0439 cwd) \u2014 \u044D\u0442\u043E \u0440\u0430\u0431\u043E\u0447\u0430\u044F \u043F\u0430\u043F\u043A\u0430, \u0430 \u043D\u0435 git-worktree: \u041D\u0415 \u043A\u043E\u043C\u043C\u0438\u0442\u044C, \u041D\u0415 \u043F\u0443\u0448\u044C, \u041D\u0415 \u043E\u0442\u043A\u0440\u044B\u0432\u0430\u0439 PR (git \u0437\u0434\u0435\u0441\u044C \u043D\u0435\u0442 \u0432\u043E\u0432\u0441\u0435). \u0410\u0440\u0442\u0435\u0444\u0430\u043A\u0442\u044B \u0440\u0430\u0431\u043E\u0442\u044B (\u0444\u0430\u0439\u043B\u044B, \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u0438, \u0442\u0430\u0431\u043B\u0438\u0446\u044B) \u0441\u043E\u0437\u0434\u0430\u0432\u0430\u0439 \u0432 cwd \u2014 \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u0443\u0432\u0438\u0434\u0438\u0442 \u0438\u0445 \u043F\u0440\u0438 \u0440\u0430\u0437\u0431\u043E\u0440\u0435 \u0441\u0434\u0430\u0447\u0438.`,
|
|
19511
|
+
"\u0418\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u044B overmind (MCP): report_step(text) \u2014 \u043B\u043E\u0433\u0438\u0440\u0443\u0439 \u0445\u043E\u0434 \u0440\u0430\u0431\u043E\u0442\u044B; read_task() \u2014 \u0441\u0432\u0435\u0436\u0438\u0439 \u0441\u043D\u0430\u043F\u0448\u043E\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 (\u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435+\u043A\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438+\u043A\u043E\u043C\u043C\u0435\u043D\u0442\u044B+\u0434\u043E\u043A\u0438) \u0431\u0435\u0437 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043E\u0432, \u0435\u0441\u043B\u0438 \u0442\u0440\u0435\u0431\u043E\u0432\u0430\u043D\u0438\u044F \u043C\u043E\u0433\u043B\u0438 \u0434\u043E\u043F\u0438\u0441\u0430\u0442\u044C \u043F\u043E\u0441\u043B\u0435 \u0441\u0442\u0430\u0440\u0442\u0430; ask(question, options?) \u2014 \u0435\u0441\u043B\u0438 \u0443\u043F\u0451\u0440\u0441\u044F \u0432 \u0420\u0415\u0428\u0415\u041D\u0418\u0415, \u0441\u043F\u0440\u043E\u0441\u0438 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 (\u0434\u0430\u0439 2\u20134 \u0432\u0430\u0440\u0438\u0430\u043D\u0442\u0430 \u0432 options, \u0435\u0441\u043B\u0438 \u0440\u0430\u0437\u0432\u0438\u043B\u043A\u0430 \u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u043D\u0430\u044F) \u0438 \u0434\u043E\u0436\u0434\u0438\u0441\u044C \u043E\u0442\u0432\u0435\u0442\u0430 (\u041D\u0415 \u0443\u0433\u0430\u0434\u044B\u0432\u0430\u0439); report_acceptance_check(id, state, evidence) \u2014 \u0437\u0430\u043A\u0440\u043E\u0439 \u041A\u0410\u0416\u0414\u042B\u0419 \u043F\u0443\u043D\u043A\u0442 \u043A\u0440\u0438\u0442\u0435\u0440\u0438\u0435\u0432 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 (id \u0438\u0437 \u0431\u043B\u043E\u043A\u0430 \xAB\u041A\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438\xBB, state = passed|failed|pending \u043F\u043E \u0444\u0430\u043A\u0442\u0443, evidence \u2014 \u0447\u0442\u043E \u043D\u0430\u0431\u043B\u044E\u0434\u0430\u043B/\u0447\u0435\u043C \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u043B); \u043F\u0440\u043E\u0439\u0434\u0438\u0441\u044C \u043F\u043E \u043D\u0438\u043C \u041F\u0415\u0420\u0415\u0414 done(); return_task(reason, missing, readings, assumed, questions) \u2014 \u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0421\u042B\u0420\u0423\u042E \u0437\u0430\u0434\u0430\u0447\u0443 \u0430\u0432\u0442\u043E\u0440\u0443; note(text) \u2014 \u0437\u0430\u043C\u0435\u0442\u043A\u0430 \xAB\u0437\u0430\u043C\u0435\u0447\u0435\u043D\u043E \u043F\u043E \u043F\u0443\u0442\u0438\xBB \u0411\u0415\u0417 \u0431\u043B\u043E\u043A\u0438\u0440\u043E\u0432\u043A\u0438; report_weight(note) \u2014 \u0440\u0430\u0431\u043E\u0442\u0430 \u0442\u044F\u0436\u0435\u043B\u0435\u0435 \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u0439, \u0441\u043A\u0430\u0436\u0438 \u041F\u041E \u0425\u041E\u0414\u0423.",
|
|
19512
|
+
"\u0421\u042B\u0420\u0423\u042E \u0417\u0410\u0414\u0410\u0427\u0423 \u041D\u0415 \u0412\u042B\u0414\u0423\u041C\u042B\u0412\u0410\u0419 \u2014 \u0412\u0415\u0420\u041D\u0418 \u0410\u0412\u0422\u041E\u0420\u0423 (return_task): \u043D\u0435\u043F\u043E\u043D\u044F\u0442\u043D\u043E, \u0447\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C (unclear_goal), \u043D\u0435\u0447\u0435\u043C \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 (no_acceptance), \u043F\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430 \u043F\u0440\u043E\u0442\u0438\u0432\u043E\u0440\u0435\u0447\u0438\u0442 \u0441\u0430\u043C\u0430 \u0441\u0435\u0431\u0435 (contradiction), \u043D\u0435 \u0437\u0430\u043A\u0440\u044B\u0442\u044C \u0437\u0430 \u043E\u0434\u0438\u043D \u043F\u0440\u043E\u0433\u043E\u043D (too_big). \u0422\u043E\u043B\u043A\u043E\u0432\u0430\u043D\u0438\u0439 \u0434\u0432\u0430 \u0438 \u043E\u0431\u0430 \u043E\u0441\u043C\u044B\u0441\u043B\u0435\u043D\u043D\u044B \u2014 \u0432\u044B\u0431\u0435\u0440\u0438 \u043E\u0447\u0435\u0432\u0438\u0434\u043D\u043E\u0435, \u0441\u0434\u0435\u043B\u0430\u0439 \u0438 \u043D\u0430\u0437\u043E\u0432\u0438 \u0440\u0430\u0437\u0432\u0438\u043B\u043A\u0443 \u0432 \u043E\u0442\u0447\u0451\u0442\u0435.",
|
|
19513
|
+
"",
|
|
19514
|
+
"\u041F\u0420\u041E\u0422\u041E\u041A\u041E\u041B \u0421\u0414\u0410\u0427\u0418 (\u0431\u0435\u0437 PR \u2014 \u043E\u0442\u0447\u0451\u0442 \u0438 \u0435\u0441\u0442\u044C \u0441\u0434\u0430\u0447\u0430):",
|
|
19515
|
+
"0. \u041F\u0435\u0440\u0435\u0437\u0432\u043E\u043D\u0438 read_task() \u2014 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0433 \u0434\u043E\u043F\u0438\u0441\u0430\u0442\u044C \u0442\u0440\u0435\u0431\u043E\u0432\u0430\u043D\u0438\u0435 \u041F\u041E\u0421\u041B\u0415 \u0442\u0432\u043E\u0435\u0433\u043E \u0441\u0442\u0430\u0440\u0442\u0430.",
|
|
19516
|
+
`1. \u041F\u0440\u043E\u0439\u0434\u0438 \u041A\u0410\u0416\u0414\u042B\u0419 \u043F\u0443\u043D\u043A\u0442 \u043A\u0440\u0438\u0442\u0435\u0440\u0438\u0435\u0432 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u0438 \u0437\u0430\u043A\u0440\u043E\u0439 \u0435\u0433\u043E report_acceptance_check(id, state, evidence) \u2014 evidence \u043E\u0431\u044F\u0437\u0430\u043D \u0431\u044B\u0442\u044C \u043D\u0430\u0431\u043B\u044E\u0434\u0430\u0435\u043C\u044B\u043C (\u0447\u0442\u043E \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u043B, \u0447\u0435\u043C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u043B), \u0430 \u043D\u0435 \xAB\u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043E\u043A\xBB.`,
|
|
19517
|
+
`2. \u0410\u0440\u0442\u0435\u0444\u0430\u043A\u0442\u044B \u0441\u043B\u043E\u0436\u0438 \u0432 cwd: \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044C \u0438\u043C\u0435\u043D\u043D\u043E \u044D\u0442\u043E\u0442 \u043A\u0430\u0442\u0430\u043B\u043E\u0433.`,
|
|
19518
|
+
`3. \u0412\u044B\u0437\u043E\u0432\u0438 done(pr_url, summary): pr_url \u2014 \u0441\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 \u0437\u0430\u0434\u0430\u0447\u0443${task?.url ? ` (${task.url})` : " \u0438\u0437 read_task()"}, summary \u2014 \u041E\u0422\u0427\u0401\u0422: \u0447\u0442\u043E \u0441\u0434\u0435\u043B\u0430\u043D\u043E, \u0447\u0435\u043C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u043E \u043F\u043E \u043A\u0430\u0436\u0434\u043E\u043C\u0443 \u043A\u0440\u0438\u0442\u0435\u0440\u0438\u044E, \u043A\u0430\u043A\u0438\u0435 \u0440\u0435\u0448\u0435\u043D\u0438\u044F \u043F\u0440\u0438\u043D\u044F\u043B, \u0447\u0442\u043E \u043E\u0441\u0442\u0430\u043B\u043E\u0441\u044C \u0437\u0430 \u0441\u043A\u043E\u0431\u043A\u0430\u043C\u0438. summary \u0443\u0445\u043E\u0434\u0438\u0442 \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u043E\u043C \u0432 \u0437\u0430\u0434\u0430\u0447\u0443 \u2014 \u0435\u0433\u043E \u0447\u0438\u0442\u0430\u0435\u0442 \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u0438 \u043F\u043E \u043D\u0435\u043C\u0443 \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u0435\u0442 \u0440\u0430\u0431\u043E\u0442\u0443. \u0421\u043A\u0440\u0438\u043D\u044B \u0430\u0440\u0442\u0435\u0444\u0430\u043A\u0442\u043E\u0432 (\u0435\u0441\u043B\u0438 \u0443\u043C\u0435\u0441\u0442\u043D\u044B) \u043F\u0435\u0440\u0435\u0434\u0430\u0439 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043E\u043C screenshots.`,
|
|
19519
|
+
"",
|
|
19520
|
+
"\u{1F4B8} \u0421\u0435\u0441\u0441\u0438\u044F \u043E\u0433\u0440\u0430\u043D\u0438\u0447\u0435\u043D\u0430 \u041F\u041E\u0422\u041E\u041B\u041A\u041E\u041C \u0422\u0420\u0410\u0422: \u0443\u043F\u0440\u0451\u0448\u044C\u0441\u044F \u2014 \u043E\u0441\u0442\u0430\u043D\u043E\u0432\u044F\u0442 \u043F\u043E\u0441\u0440\u0435\u0434\u0438 \u0440\u0430\u0431\u043E\u0442\u044B. \u0427\u0438\u0442\u0430\u0439 \u0442\u043E, \u0447\u0442\u043E \u043D\u0443\u0436\u043D\u043E \u0437\u0430\u0434\u0430\u0447\u0435, \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u043D\u043D\u043E\u0435 \u043D\u0435 \u043F\u0435\u0440\u0435\u0447\u0438\u0442\u044B\u0432\u0430\u0439; \u043F\u0440\u043E\u043C\u0435\u0436\u0443\u0442\u043E\u0447\u043D\u044B\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 \u0441\u043E\u0445\u0440\u0430\u043D\u044F\u0439 \u0444\u0430\u0439\u043B\u0430\u043C\u0438 \u0432 cwd \u043F\u043E \u0445\u043E\u0434\u0443 \u2014 \u0442\u043E\u0433\u0434\u0430 \u043E\u0431\u0440\u044B\u0432 \u043D\u0435 \u043F\u043E\u0442\u0435\u0440\u044F\u0435\u0442 \u0440\u0430\u0431\u043E\u0442\u0443."
|
|
19521
|
+
].join("\n");
|
|
19522
|
+
}
|
|
19421
19523
|
function buildPrompt(task, run, verifyMode = SWARM_VERIFY, taskContext, attachmentsBlock, zoneMemoryBlock) {
|
|
19422
19524
|
const name = run.name || `#${run.id}`;
|
|
19525
|
+
if (run.repoless) return buildRepolessPrompt(task, run, taskContext, attachmentsBlock);
|
|
19423
19526
|
const head = task ? `\u0417\u0430\u0434\u0430\u0447\u0430 ${run.task_slug}: ${task.title}
|
|
19424
19527
|
|
|
19425
19528
|
${task.description}` : `\u0417\u0430\u0434\u0430\u0447\u0430 ${run.task_slug} (\u0442\u0435\u043B\u043E \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E \u2014 \u0440\u0430\u0431\u043E\u0442\u0430\u0439 \u043F\u043E slug \u0438 \u0437\u0434\u0440\u0430\u0432\u043E\u043C\u0443 \u0441\u043C\u044B\u0441\u043B\u0443).`;
|
|
@@ -19513,7 +19616,7 @@ ${task.description}` : `\u0417\u0430\u0434\u0430\u0447\u0430 ${run.task_slug} (\
|
|
|
19513
19616
|
}
|
|
19514
19617
|
return parts.join("\n");
|
|
19515
19618
|
}
|
|
19516
|
-
var HERO_CHARTER_PATH =
|
|
19619
|
+
var HERO_CHARTER_PATH = join36(dirname6(THIS_FILE), "..", "docs", "HERO.md");
|
|
19517
19620
|
function buildHeroPrompt(task, run, taskContext, attachmentsBlock) {
|
|
19518
19621
|
const name = run.name || `#${run.id}`;
|
|
19519
19622
|
const charter = readFileSync25(HERO_CHARTER_PATH, "utf8");
|
|
@@ -19573,7 +19676,7 @@ function ciTrustLine(prUrl, verifyMode) {
|
|
|
19573
19676
|
}
|
|
19574
19677
|
return `\u041D\u0435 \u043F\u0435\u0440\u0435\u0433\u043E\u043D\u044F\u0439 \u0442\u0435\u0441\u0442-\u0441\u044C\u044E\u0442/typecheck \u0437\u0430\u043D\u043E\u0432\u043E \u2014 \u044D\u0442\u043E \u0443\u0436\u0435 \u0441\u0434\u0435\u043B\u0430\u043B CI \u043D\u0430 \u044D\u0442\u043E\u043C \u0436\u0435 \u043A\u043E\u043C\u043C\u0438\u0442\u0435 (\u0434\u0432\u043E\u0439\u043D\u043E\u0439 \u043F\u0440\u043E\u0433\u043E\u043D \u043D\u0430 \u043C\u0430\u0448\u0438\u043D\u0435 \u0432\u043B\u0430\u0434\u0435\u043B\u044C\u0446\u0430 \u043E\u0442\u043C\u0435\u043D\u0451\u043D, TASWM-249). \u041F\u0440\u043E\u0447\u0438\u0442\u0430\u0439 \u0435\u0433\u043E \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 \u0441\u0430\u043C: ${readChecks}. \u0414\u0430\u043B\u044C\u0448\u0435 \u0442\u0440\u0438 \u0440\u0430\u0437\u043D\u044B\u0445 \u0441\u043B\u0443\u0447\u0430\u044F: \u2460 \u0445\u043E\u0442\u044C \u043E\u0434\u0438\u043D \u0447\u0435\u043A \u0435\u0449\u0451 PENDING \u2014 \u0432\u0435\u0440\u0434\u0438\u043A\u0442 \u0432\u043E\u043E\u0431\u0449\u0435 \u043D\u0435 \u0432\u044B\u043D\u043E\u0441\u0438: \u043D\u0435 \u043F\u043E\u0441\u0442\u0438 REQUEST CHANGES, \u043D\u0435 \u0437\u043E\u0432\u0438 done(), \u043F\u0440\u043E\u0441\u0442\u043E \u0437\u0430\u0432\u0435\u0440\u0448\u0438 \u0441\u0435\u0441\u0441\u0438\u044E \u043A\u0430\u043A \u0435\u0441\u0442\u044C \u2014 \u0440\u043E\u0439 \u0441\u0430\u043C \u0437\u0430\u043C\u0435\u0442\u0438\u0442, \u0447\u0442\u043E \u0442\u044B \u0436\u0434\u0451\u0448\u044C CI, \u0438 \u0440\u0430\u0437\u0431\u0443\u0434\u0438\u0442 \u0434\u043E\u0434\u0435\u043B\u0430\u0442\u044C \u0440\u0435\u0432\u044C\u044E, \u043A\u043E\u0433\u0434\u0430 \u0432\u0441\u0435 \u0447\u0435\u043A\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u0441\u044F (\u044D\u0442\u043E \u0448\u0442\u0430\u0442\u043D\u044B\u0439 \u043F\u0443\u0442\u044C, \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u0437\u0432\u0430\u0442\u044C \u043D\u0435 \u043D\u0443\u0436\u043D\u043E). \u2461 \u0432\u0441\u0435 \u0447\u0435\u043A\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0438\u0441\u044C \u0438 \u0435\u0441\u0442\u044C FAIL \u2014 REQUEST CHANGES, \u043D\u0430\u0437\u043E\u0432\u0438 \u043F\u043E\u0438\u043C\u0451\u043D\u043D\u043E, \u0447\u0442\u043E \u0443\u043F\u0430\u043B\u043E. \u2462 \u043D\u0430 \u044D\u0442\u043E\u043C \u043A\u043E\u043C\u043C\u0438\u0442\u0435 \u0447\u0435\u043A\u043E\u0432 \u043D\u0435\u0442 \u0432\u043E\u0432\u0441\u0435 \u2014 \u0442\u043E\u0436\u0435 REQUEST CHANGES: \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C \u043D\u0435\u0447\u0435\u043C (\u0443 \u044D\u0442\u043E\u0433\u043E \u043F\u0440\u043E\u0435\u043A\u0442\u0430 verifyMode=ci, \u0442\u043E \u0435\u0441\u0442\u044C CI \u043E\u0431\u044F\u0437\u0430\u043D \u0431\u044B\u0442\u044C). ${dontTrustAuthor}`;
|
|
19575
19678
|
}
|
|
19576
|
-
var REVIEW_SKILL_PATH =
|
|
19679
|
+
var REVIEW_SKILL_PATH = join36(bundledRoleDir("drone"), "skills", "taskless-review", "SKILL.md");
|
|
19577
19680
|
function reviewDefectClasses(skillPath = REVIEW_SKILL_PATH) {
|
|
19578
19681
|
const text = readFileSync25(skillPath, "utf8");
|
|
19579
19682
|
const m = /^## Классы дефектов\n([\s\S]*?)(?=^## |(?![\s\S]))/m.exec(text);
|
|
@@ -19839,7 +19942,7 @@ async function wakeRun(deps, runId, opts = {}) {
|
|
|
19839
19942
|
if (run.status === "review" && run.pr_url && !needsFixIteration(run) && !stoppedForHuman) {
|
|
19840
19943
|
return { ok: false, why: `\u043F\u0440\u043E\u0433\u043E\u043D #${runId} \u0443\u0436\u0435 \u0441\u0434\u0430\u043D \u043D\u0430 \u0440\u0435\u0432\u044C\u044E (${run.pr_url}) \u2014 \u0431\u0443\u0434\u0438\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E; \u043F\u0440\u0430\u0432\u043A\u0438 \u043F\u043E\u0434\u043D\u0438\u043C\u0435\u0442 \u0440\u043E\u0439 \u043F\u043E \u0432\u0435\u0440\u0434\u0438\u043A\u0442\u0443` };
|
|
19841
19944
|
}
|
|
19842
|
-
const worktreeExists = deps.worktreeExists ??
|
|
19945
|
+
const worktreeExists = deps.worktreeExists ?? existsSync21;
|
|
19843
19946
|
const hasTranscript = deps.hasTranscript ?? executorHasSession;
|
|
19844
19947
|
const wt = run.worktree_path;
|
|
19845
19948
|
const canContinue = !!wt && worktreeExists(wt) && hasTranscript(run);
|
|
@@ -19964,7 +20067,7 @@ function repoHasCi(deps, run) {
|
|
|
19964
20067
|
function repoHasCiWorkflows(worktreePath, repo) {
|
|
19965
20068
|
for (const base3 of [worktreePath, repo]) {
|
|
19966
20069
|
if (!base3) continue;
|
|
19967
|
-
const dir =
|
|
20070
|
+
const dir = join36(base3, ".github", "workflows");
|
|
19968
20071
|
try {
|
|
19969
20072
|
if (readdirSync14(dir).some((f) => f.endsWith(".yml") || f.endsWith(".yaml"))) return true;
|
|
19970
20073
|
} catch {
|
|
@@ -20165,7 +20268,7 @@ async function wakeReviewerOnCiReady(deps, run, over) {
|
|
|
20165
20268
|
return true;
|
|
20166
20269
|
}
|
|
20167
20270
|
function worktreeAndTranscriptAlive(deps, run) {
|
|
20168
|
-
const exists = deps.worktreeExists ??
|
|
20271
|
+
const exists = deps.worktreeExists ?? existsSync21;
|
|
20169
20272
|
const transcript = deps.hasTranscript ?? executorHasSession;
|
|
20170
20273
|
const wt = run.worktree_path;
|
|
20171
20274
|
return !!wt && exists(wt) && transcript(run);
|
|
@@ -20265,7 +20368,7 @@ async function wakeAuthorOnChanges(deps, snapshot, now, droneCap) {
|
|
|
20265
20368
|
}
|
|
20266
20369
|
const wt = run.worktree_path;
|
|
20267
20370
|
const wtPath = wt || (deps.worktreesDir ? droneWorktreePath(deps.worktreesDir, normalizeRepo(run.repo || deps.repoFallback || ""), run.task_slug) : null);
|
|
20268
|
-
const worktreeReady = !!wtPath && (deps.worktreeExists ??
|
|
20371
|
+
const worktreeReady = !!wtPath && (deps.worktreeExists ?? existsSync21)(wtPath);
|
|
20269
20372
|
if (!worktreeReady && !await freshChangesWakeAllowed(deps, run, prUrl, now)) return false;
|
|
20270
20373
|
try {
|
|
20271
20374
|
await deps.respawn(run, "fix");
|
|
@@ -20348,7 +20451,7 @@ async function zoneConflictFor(db, models, activeFiles, run, repo, repoFallback)
|
|
|
20348
20451
|
activeFiles.prune(holders.map((r) => r.id));
|
|
20349
20452
|
const fileExists = (p) => {
|
|
20350
20453
|
try {
|
|
20351
|
-
return statSync13(
|
|
20454
|
+
return statSync13(join36(repo, p), { throwIfNoEntry: false })?.isFile() ?? false;
|
|
20352
20455
|
} catch {
|
|
20353
20456
|
return false;
|
|
20354
20457
|
}
|
|
@@ -20740,7 +20843,7 @@ async function liftReturners(deps, returners, now, droneCap) {
|
|
|
20740
20843
|
deps.returners?.delete(run.id);
|
|
20741
20844
|
continue;
|
|
20742
20845
|
}
|
|
20743
|
-
lifted = await wakeAuthorOnRedCi(deps, run, now, entry.ci, deps.worktreeExists ??
|
|
20846
|
+
lifted = await wakeAuthorOnRedCi(deps, run, now, entry.ci, deps.worktreeExists ?? existsSync21, deps.hasTranscript ?? executorHasSession, droneCap);
|
|
20744
20847
|
}
|
|
20745
20848
|
if (lifted) deps.returners?.delete(run.id);
|
|
20746
20849
|
}
|
|
@@ -20759,7 +20862,7 @@ async function resumeWatchdogParked(deps, droneCap) {
|
|
|
20759
20862
|
}
|
|
20760
20863
|
if (!candidate) return;
|
|
20761
20864
|
if (candidate.pid != null && deps.isAlive(candidate.pid)) return;
|
|
20762
|
-
const worktreeExists = deps.worktreeExists ??
|
|
20865
|
+
const worktreeExists = deps.worktreeExists ?? existsSync21;
|
|
20763
20866
|
const hasTranscript = deps.hasTranscript ?? executorHasSession;
|
|
20764
20867
|
const wt = candidate.worktree_path;
|
|
20765
20868
|
const canContinue = !!wt && worktreeExists(wt) && hasTranscript(candidate);
|
|
@@ -21546,7 +21649,7 @@ function buildEscalationCandidates(db) {
|
|
|
21546
21649
|
}
|
|
21547
21650
|
async function tickOnce(deps) {
|
|
21548
21651
|
const now = deps.now ? deps.now() : Date.now();
|
|
21549
|
-
const worktreeExists = deps.worktreeExists ??
|
|
21652
|
+
const worktreeExists = deps.worktreeExists ?? existsSync21;
|
|
21550
21653
|
const hasTranscript = deps.hasTranscript ?? executorHasSession;
|
|
21551
21654
|
deps.sampleHost?.();
|
|
21552
21655
|
if (deps.rehydrate) {
|
|
@@ -22447,7 +22550,7 @@ async function resolveConflict(deps, reviewRun) {
|
|
|
22447
22550
|
model: reviewRun.model,
|
|
22448
22551
|
review_model: reviewRun.review_model
|
|
22449
22552
|
});
|
|
22450
|
-
const wt =
|
|
22553
|
+
const wt = join36(deps.worktreesDir, basename6(repo), `${reviewRun.task_slug}-resolve-${resolver.id}`);
|
|
22451
22554
|
try {
|
|
22452
22555
|
await deps.git.prepareDetachedWorktree(repo, branch, wt);
|
|
22453
22556
|
await deps.git.setWorktreeIdentity(wt, resolver.name);
|
|
@@ -22527,7 +22630,7 @@ async function spawnReviewer(deps, reviewRun, files) {
|
|
|
22527
22630
|
// (своей у ревьюера нет, TASWM-204), и коммент с вердиктом должен уехать именно туда.
|
|
22528
22631
|
workspace_id: reviewRun.workspace_id
|
|
22529
22632
|
});
|
|
22530
|
-
const wt =
|
|
22633
|
+
const wt = join36(deps.worktreesDir, basename6(repo), `${reviewRun.task_slug}-review-${reviewer.id}`);
|
|
22531
22634
|
try {
|
|
22532
22635
|
await deps.git.prepareDetachedWorktree(repo, branch, wt);
|
|
22533
22636
|
await deps.git.setWorktreeIdentity(wt, reviewer.name);
|
|
@@ -22608,7 +22711,7 @@ async function spawnVerifier(deps, verifiedRun, files) {
|
|
|
22608
22711
|
// штамп цикла: фикс-итерацию проверяет свежий верификатор
|
|
22609
22712
|
workspace_id: verifiedRun.workspace_id
|
|
22610
22713
|
});
|
|
22611
|
-
const wt =
|
|
22714
|
+
const wt = join36(deps.worktreesDir, basename6(repo), `${verifiedRun.task_slug}-verify-${verifier.id}`);
|
|
22612
22715
|
try {
|
|
22613
22716
|
await deps.git.prepareDetachedWorktree(repo, branch, wt);
|
|
22614
22717
|
await deps.git.setWorktreeIdentity(wt, verifier.name);
|
|
@@ -22656,7 +22759,7 @@ async function respawnRun(deps, run, mode, nudge) {
|
|
|
22656
22759
|
]);
|
|
22657
22760
|
const base3 = effectiveBaseBranch(run.base_branch, projectBase);
|
|
22658
22761
|
const runToSpawn = base3 && run.base_branch !== base3 ? deps.db.updateRun(run.id, { base_branch: base3 }) ?? run : run;
|
|
22659
|
-
if (!
|
|
22762
|
+
if (!existsSync21(wt)) {
|
|
22660
22763
|
const branch = runToSpawn.branch || runToSpawn.task_slug;
|
|
22661
22764
|
const source = await addWorktree(repo, wt, branch, {
|
|
22662
22765
|
...base3 ? { base: await remoteBaseRef(repo, base3) } : {},
|
|
@@ -22697,7 +22800,7 @@ function worktreePathPatch(run, wt) {
|
|
|
22697
22800
|
return run.worktree_path === wt ? {} : { worktree_path: wt };
|
|
22698
22801
|
}
|
|
22699
22802
|
async function syncCrashedOnStartup(deps) {
|
|
22700
|
-
const worktreeExists = deps.worktreeExists ??
|
|
22803
|
+
const worktreeExists = deps.worktreeExists ?? existsSync21;
|
|
22701
22804
|
let orphaned = 0;
|
|
22702
22805
|
let merged = 0;
|
|
22703
22806
|
let requeued = 0;
|
|
@@ -22851,7 +22954,7 @@ async function migrateWorktreesAtStartup() {
|
|
|
22851
22954
|
legacyDir: WORKTREES_LEGACY_DIR,
|
|
22852
22955
|
targetDir: WORKTREES_DIR,
|
|
22853
22956
|
envOverride: process.env.SWARM_WORKTREES || "",
|
|
22854
|
-
exists: (d) =>
|
|
22957
|
+
exists: (d) => existsSync21(d),
|
|
22855
22958
|
isNonEmptyDir: (d) => {
|
|
22856
22959
|
try {
|
|
22857
22960
|
return readdirSync14(d).length > 0;
|
|
@@ -22866,7 +22969,7 @@ async function migrateWorktreesAtStartup() {
|
|
|
22866
22969
|
});
|
|
22867
22970
|
} catch (e) {
|
|
22868
22971
|
console.error("[migrate] \u043C\u0438\u0433\u0440\u0430\u0446\u0438\u044F worktrees \u0441\u043E\u0440\u0432\u0430\u043B\u0430\u0441\u044C \u2014 \u0444\u043E\u043B\u0431\u044D\u043A:", e);
|
|
22869
|
-
return
|
|
22972
|
+
return existsSync21(WORKTREES_DIR) ? WORKTREES_DIR : WORKTREES_LEGACY_DIR;
|
|
22870
22973
|
}
|
|
22871
22974
|
}
|
|
22872
22975
|
async function reportWorkspaceAccess(tl, db) {
|
|
@@ -23556,7 +23659,7 @@ async function runDaemon(opts) {
|
|
|
23556
23659
|
isDirty: (p) => worktreeDirty(p),
|
|
23557
23660
|
releaseWorktree: (repo, p) => releaseWorktree(repo || opts.repo, p),
|
|
23558
23661
|
pruneWorktrees: (repo) => pruneWorktrees(repo || opts.repo),
|
|
23559
|
-
worktreeExists:
|
|
23662
|
+
worktreeExists: existsSync21,
|
|
23560
23663
|
liveWorktrees: () => new Set(listDroneProcesses().map((p) => p.worktree)),
|
|
23561
23664
|
narrate: narrator.narrate
|
|
23562
23665
|
});
|
|
@@ -23691,7 +23794,7 @@ async function runDaemon(opts) {
|
|
|
23691
23794
|
mode,
|
|
23692
23795
|
nudge
|
|
23693
23796
|
),
|
|
23694
|
-
worktreeExists: (p) =>
|
|
23797
|
+
worktreeExists: (p) => existsSync21(p),
|
|
23695
23798
|
// TASWM-514: с этого момента считаем попытки спавна — счётчик живёт ровно одну жизнь
|
|
23696
23799
|
// процесса демона и рестарт не переживает (см. preStartAttempts).
|
|
23697
23800
|
startedAt: Date.now(),
|
|
@@ -23902,7 +24005,7 @@ async function runDaemon(opts) {
|
|
|
23902
24005
|
onStep
|
|
23903
24006
|
});
|
|
23904
24007
|
}
|
|
23905
|
-
const repo = await repoRoot(
|
|
24008
|
+
const repo = await repoRoot(dirname6(THIS_FILE)).catch(() => null);
|
|
23906
24009
|
if (!repo) {
|
|
23907
24010
|
return { ok: false, step: "fetch", message: "\u0431\u0435\u0433\u0443 \u0438\u0437 \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u043E\u0432, \u043D\u043E git-\u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F \u043D\u0430\u0434 \u043D\u0438\u043C\u0438 \u043D\u0435\u0442 \u2014 \u043E\u0431\u043D\u043E\u0432\u043B\u044F\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E" };
|
|
23908
24011
|
}
|
|
@@ -24215,6 +24318,7 @@ export {
|
|
|
24215
24318
|
buildCiWakeNudge,
|
|
24216
24319
|
buildHeroPrompt,
|
|
24217
24320
|
buildPrompt,
|
|
24321
|
+
buildRepolessPrompt,
|
|
24218
24322
|
buildResolverPrompt,
|
|
24219
24323
|
buildReviewChecklist,
|
|
24220
24324
|
buildReviewerPrompt,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taskless-app/swarm",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.62",
|
|
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": "e999630218010a25c03a6024e1b71ef34b2359ec",
|
|
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",
|