@taskless-app/swarm 0.6.22 → 0.6.23
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 +144 -14
- package/dist/overmind.js +187 -63
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1131,8 +1131,8 @@ var init_runGuards = __esm({
|
|
|
1131
1131
|
function hasZoneModel(m) {
|
|
1132
1132
|
return m.tasks > 0 && m.zones.length > 0;
|
|
1133
1133
|
}
|
|
1134
|
-
function testFileFeature(
|
|
1135
|
-
const head =
|
|
1134
|
+
function testFileFeature(basename7) {
|
|
1135
|
+
const head = basename7.replace(/\.(test|spec)\.[a-z]+$/i, "").split(".")[0].toLowerCase();
|
|
1136
1136
|
return head && !GENERIC_DIRS.has(head) ? head : null;
|
|
1137
1137
|
}
|
|
1138
1138
|
function pathZoneCandidate(path) {
|
|
@@ -2393,7 +2393,7 @@ var init_package = __esm({
|
|
|
2393
2393
|
"package.json"() {
|
|
2394
2394
|
package_default = {
|
|
2395
2395
|
name: "@taskless-app/swarm",
|
|
2396
|
-
version: "0.6.
|
|
2396
|
+
version: "0.6.23",
|
|
2397
2397
|
type: "module",
|
|
2398
2398
|
description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
2399
2399
|
keywords: [
|
|
@@ -2443,7 +2443,7 @@ var init_package = __esm({
|
|
|
2443
2443
|
execa: "^10.0.0",
|
|
2444
2444
|
zod: "3.25.76"
|
|
2445
2445
|
},
|
|
2446
|
-
gitHead: "
|
|
2446
|
+
gitHead: "af6c4af0f523891b5db805d9b4583021688ed1f5"
|
|
2447
2447
|
};
|
|
2448
2448
|
}
|
|
2449
2449
|
});
|
|
@@ -5250,7 +5250,7 @@ var init_updateCli = __esm({
|
|
|
5250
5250
|
|
|
5251
5251
|
// src/cli.ts
|
|
5252
5252
|
init_cliIo();
|
|
5253
|
-
import { basename as
|
|
5253
|
+
import { basename as basename6, dirname as dirname4, join as join24 } from "path";
|
|
5254
5254
|
import { existsSync as existsSync16, readFileSync as readFileSync17, writeFileSync as writeFileSync13, mkdirSync as mkdirSync9, readdirSync as readdirSync10, statSync as statSync10, openSync as openSync4, readSync as readSync2, closeSync as closeSync4 } from "fs";
|
|
5255
5255
|
import { setTimeout as sleep2 } from "timers/promises";
|
|
5256
5256
|
|
|
@@ -8322,7 +8322,7 @@ function hostLines(hosts, opts = {}) {
|
|
|
8322
8322
|
// src/web.ts
|
|
8323
8323
|
init_src();
|
|
8324
8324
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
8325
|
-
import { basename as
|
|
8325
|
+
import { basename as basename4 } from "path";
|
|
8326
8326
|
import { serve as serve2 } from "@hono/node-server";
|
|
8327
8327
|
|
|
8328
8328
|
// src/diff.ts
|
|
@@ -8518,7 +8518,123 @@ init_storm();
|
|
|
8518
8518
|
// src/gh.ts
|
|
8519
8519
|
init_src();
|
|
8520
8520
|
import { $ as $4 } from "execa";
|
|
8521
|
-
|
|
8521
|
+
import { basename as basename3 } from "path";
|
|
8522
|
+
|
|
8523
|
+
// src/logNoise.ts
|
|
8524
|
+
var DEFAULT_REMIND_MS = 10 * 6e4;
|
|
8525
|
+
function timesWord(n) {
|
|
8526
|
+
const tens = n % 100;
|
|
8527
|
+
if (tens >= 11 && tens <= 14) return "\u0440\u0430\u0437";
|
|
8528
|
+
return n % 10 >= 2 && n % 10 <= 4 ? "\u0440\u0430\u0437\u0430" : "\u0440\u0430\u0437";
|
|
8529
|
+
}
|
|
8530
|
+
function makeRepeatFilter(opts = {}) {
|
|
8531
|
+
const remindAfterMs = opts.remindAfterMs ?? DEFAULT_REMIND_MS;
|
|
8532
|
+
const streaks = /* @__PURE__ */ new Map();
|
|
8533
|
+
return {
|
|
8534
|
+
say(key, message, now) {
|
|
8535
|
+
const prev = streaks.get(key);
|
|
8536
|
+
if (!prev || prev.message !== message) {
|
|
8537
|
+
const tail = prev && prev.hidden > 0 ? ` (\u0434\u043E \u044D\u0442\u043E\u0433\u043E \u0442\u043E \u0436\u0435 \u0441\u0430\u043C\u043E\u0435 \u043C\u043E\u043B\u0447\u0430 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u043B\u043E\u0441\u044C \u0435\u0449\u0451 ${prev.hidden} ${timesWord(prev.hidden)})` : "";
|
|
8538
|
+
streaks.set(key, { message, since: now, saidAt: now, hidden: 0 });
|
|
8539
|
+
return `${message}${tail}`;
|
|
8540
|
+
}
|
|
8541
|
+
prev.hidden += 1;
|
|
8542
|
+
if (now - prev.saidAt < remindAfterMs) return null;
|
|
8543
|
+
const hidden = prev.hidden;
|
|
8544
|
+
const minutes = Math.max(1, Math.round((now - prev.since) / 6e4));
|
|
8545
|
+
prev.saidAt = now;
|
|
8546
|
+
prev.hidden = 0;
|
|
8547
|
+
return `${message} \u2014 \u0442\u043E \u0436\u0435 \u0441\u0430\u043C\u043E\u0435 ${hidden} ${timesWord(hidden)} \u043F\u043E\u0434\u0440\u044F\u0434, \u0442\u044F\u043D\u0435\u0442\u0441\u044F ${minutes} \u043C\u0438\u043D`;
|
|
8548
|
+
},
|
|
8549
|
+
forget(key) {
|
|
8550
|
+
streaks.delete(key);
|
|
8551
|
+
}
|
|
8552
|
+
};
|
|
8553
|
+
}
|
|
8554
|
+
|
|
8555
|
+
// src/netTimeout.ts
|
|
8556
|
+
import { basename as basename2 } from "path";
|
|
8557
|
+
var GH_CALL_TIMEOUT_MS = 15e3;
|
|
8558
|
+
var GIT_LOCAL_TIMEOUT_MS = 5e3;
|
|
8559
|
+
var HARD_CAP_GRACE_MS = 2e3;
|
|
8560
|
+
var CallTimedOutError = class extends Error {
|
|
8561
|
+
timedOut = true;
|
|
8562
|
+
constructor(call, timeoutMs) {
|
|
8563
|
+
super(`\u0432\u044B\u0437\u043E\u0432 \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u0437\u0430 ${timeoutMs}\u043C\u0441 \u0438 \u043F\u0440\u0435\u0440\u0432\u0430\u043D: ${call}`);
|
|
8564
|
+
this.name = "CallTimedOutError";
|
|
8565
|
+
}
|
|
8566
|
+
};
|
|
8567
|
+
function isTimedOut(outcome) {
|
|
8568
|
+
return typeof outcome === "object" && outcome !== null && outcome.timedOut === true;
|
|
8569
|
+
}
|
|
8570
|
+
function noteTimedOut(scope, call, timeoutMs, outcome, warn = console.warn) {
|
|
8571
|
+
const line = `[${scope}] \u23F1 \u0432\u044B\u0437\u043E\u0432 \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u0437\u0430 ${humanMs(timeoutMs)} \u0438 \u043F\u0440\u0435\u0440\u0432\u0430\u043D: ${call} \u2014 \u0440\u0435\u043A\u043E\u043D\u0441\u0430\u0439\u043B \u0438\u0434\u0451\u0442 \u0434\u0430\u043B\u044C\u0448\u0435`;
|
|
8572
|
+
if (!isTimedOut(outcome)) {
|
|
8573
|
+
timeoutNoise.forget(noiseKey(scope, call));
|
|
8574
|
+
return false;
|
|
8575
|
+
}
|
|
8576
|
+
const say = timeoutNoise.say(noiseKey(scope, call), line, Date.now());
|
|
8577
|
+
if (say) warn(say);
|
|
8578
|
+
return true;
|
|
8579
|
+
}
|
|
8580
|
+
function noiseKey(scope, call) {
|
|
8581
|
+
return `timeout:${scope}:${call}`;
|
|
8582
|
+
}
|
|
8583
|
+
var timeoutNoise = makeRepeatFilter();
|
|
8584
|
+
function humanMs(ms) {
|
|
8585
|
+
return ms >= 1e3 ? `${Math.round(ms / 1e3)}\u0441` : `${ms}\u043C\u0441`;
|
|
8586
|
+
}
|
|
8587
|
+
function destroyPipes(child) {
|
|
8588
|
+
for (const pipe of [child.stdout, child.stderr, child.stdin]) {
|
|
8589
|
+
try {
|
|
8590
|
+
pipe?.destroy?.();
|
|
8591
|
+
} catch {
|
|
8592
|
+
}
|
|
8593
|
+
}
|
|
8594
|
+
}
|
|
8595
|
+
async function withHardTimeout(child, scope, call, timeoutMs, warn = console.warn) {
|
|
8596
|
+
let timer;
|
|
8597
|
+
const capped = new Promise((_, reject) => {
|
|
8598
|
+
timer = setTimeout(() => {
|
|
8599
|
+
child.kill("SIGKILL");
|
|
8600
|
+
destroyPipes(child);
|
|
8601
|
+
reject(new CallTimedOutError(call, timeoutMs));
|
|
8602
|
+
}, timeoutMs + HARD_CAP_GRACE_MS);
|
|
8603
|
+
timer.unref?.();
|
|
8604
|
+
});
|
|
8605
|
+
try {
|
|
8606
|
+
const res = await Promise.race([child, capped]);
|
|
8607
|
+
noteTimedOut(scope, call, timeoutMs, res, warn);
|
|
8608
|
+
return res;
|
|
8609
|
+
} catch (e) {
|
|
8610
|
+
noteTimedOut(scope, call, timeoutMs, e, warn);
|
|
8611
|
+
throw e;
|
|
8612
|
+
} finally {
|
|
8613
|
+
if (timer) clearTimeout(timer);
|
|
8614
|
+
}
|
|
8615
|
+
}
|
|
8616
|
+
function callLabel(cmd2, args, head = 4) {
|
|
8617
|
+
const shown = args.slice(0, head).join(" ");
|
|
8618
|
+
return `${cmd2} ${shown}${args.length > head ? " \u2026" : ""}`.trim();
|
|
8619
|
+
}
|
|
8620
|
+
function gitCallLabel(repo, args) {
|
|
8621
|
+
return `git -C ${basename2(repo) || repo} ${args.join(" ")}`;
|
|
8622
|
+
}
|
|
8623
|
+
|
|
8624
|
+
// src/gh.ts
|
|
8625
|
+
async function runGh(args, timeoutMs, cwd) {
|
|
8626
|
+
const label2 = callLabel("gh", args) + (cwd ? ` (repo ${basename3(cwd)})` : "");
|
|
8627
|
+
const child = cwd ? $4({ cwd, timeout: timeoutMs })`gh ${args}` : $4({ timeout: timeoutMs })`gh ${args}`;
|
|
8628
|
+
return (await withHardTimeout(child, "gh", label2, timeoutMs)).stdout;
|
|
8629
|
+
}
|
|
8630
|
+
function ghRunner(timeoutMs = GH_CALL_TIMEOUT_MS) {
|
|
8631
|
+
return (args) => runGh(args, timeoutMs);
|
|
8632
|
+
}
|
|
8633
|
+
function ghRepoRunner(timeoutMs = GH_CALL_TIMEOUT_MS) {
|
|
8634
|
+
return (args, cwd) => runGh(args, timeoutMs, cwd);
|
|
8635
|
+
}
|
|
8636
|
+
var realRunner = ghRunner();
|
|
8637
|
+
var realRepoRunner = ghRepoRunner();
|
|
8522
8638
|
async function openPrsForBranch(branch, repoDir, run = realRepoRunner) {
|
|
8523
8639
|
if (!branch || !repoDir) return [];
|
|
8524
8640
|
try {
|
|
@@ -8543,7 +8659,12 @@ function firstLine(s) {
|
|
|
8543
8659
|
return s.split("\n").map((l) => l.trim()).find((l) => l.length > 0) ?? "gh \u0432\u0435\u0440\u043D\u0443\u043B 403";
|
|
8544
8660
|
}
|
|
8545
8661
|
var realChecksRunner = async (pr) => {
|
|
8546
|
-
const r = await
|
|
8662
|
+
const r = await withHardTimeout(
|
|
8663
|
+
$4({ reject: false, timeout: 15e3 })`gh pr checks ${pr} --json state,name,bucket,link`,
|
|
8664
|
+
"gh",
|
|
8665
|
+
callLabel("gh", ["pr", "checks", pr]),
|
|
8666
|
+
15e3
|
|
8667
|
+
);
|
|
8547
8668
|
const stdout = r.stdout ?? "";
|
|
8548
8669
|
const stderr = r.stderr ?? "";
|
|
8549
8670
|
if (!stdout.trim() && NO_CHECKS_STDERR.test(stderr)) return "[]";
|
|
@@ -9105,7 +9226,7 @@ function timelineState(db2, now = Date.now(), overmindLog = []) {
|
|
|
9105
9226
|
id: r.id,
|
|
9106
9227
|
name: r.name,
|
|
9107
9228
|
slug: r.task_slug,
|
|
9108
|
-
repo:
|
|
9229
|
+
repo: basename4(r.repo || "") || "?",
|
|
9109
9230
|
status: r.status,
|
|
9110
9231
|
area: r.area,
|
|
9111
9232
|
start: sqliteIso(r.created_at),
|
|
@@ -10882,6 +11003,14 @@ import { appendFile, chmod, mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
|
10882
11003
|
import { isAbsolute, join as join13, sep as sep2 } from "path";
|
|
10883
11004
|
import { $ as $5 } from "execa";
|
|
10884
11005
|
init_swarmFiles();
|
|
11006
|
+
function gitNet(repo, args, timeoutMs) {
|
|
11007
|
+
return withHardTimeout(
|
|
11008
|
+
$5({ reject: false, timeout: timeoutMs })`git -C ${repo} ${args}`,
|
|
11009
|
+
"git",
|
|
11010
|
+
gitCallLabel(repo, args),
|
|
11011
|
+
timeoutMs
|
|
11012
|
+
).catch(() => null);
|
|
11013
|
+
}
|
|
10885
11014
|
var WorktreeBusyError = class extends Error {
|
|
10886
11015
|
constructor(branch, worktreePath) {
|
|
10887
11016
|
super(`worktree \u0437\u0430\u043D\u044F\u0442: ${worktreePath} (\u0432\u0435\u0442\u043A\u0430 ${branch}) \u2014 \u043F\u0440\u0438\u0431\u0435\u0440\u0438 worktree \u0438\u043B\u0438 \u043E\u0442\u043C\u0435\u043D\u0438 \u043F\u0440\u043E\u0433\u043E\u043D (swarm cancel ${branch})`);
|
|
@@ -11086,8 +11215,9 @@ async function remoteMainRef(repo) {
|
|
|
11086
11215
|
throw new Error(`\u043D\u0435 \u043D\u0430\u0448\u0451\u043B \u0434\u0435\u0444\u043E\u043B\u0442-\u0432\u0435\u0442\u043A\u0443 origin \u0432 ${repo} (\u043D\u0435\u0442 origin/HEAD, origin/main, origin/master)`);
|
|
11087
11216
|
}
|
|
11088
11217
|
var GITHUB_REMOTE_RE = /github\.com[:/]([^/]+\/[^/]+?)(?:\.git)?\/?$/i;
|
|
11089
|
-
async function remoteRepoFullName(repo) {
|
|
11090
|
-
const
|
|
11218
|
+
async function remoteRepoFullName(repo, timeoutMs = GIT_LOCAL_TIMEOUT_MS) {
|
|
11219
|
+
const res = await gitNet(repo, ["remote", "get-url", "origin"], timeoutMs);
|
|
11220
|
+
const url = res?.stdout.trim() ?? "";
|
|
11091
11221
|
const m = url.match(GITHUB_REMOTE_RE);
|
|
11092
11222
|
return m ? m[1] : null;
|
|
11093
11223
|
}
|
|
@@ -11114,7 +11244,7 @@ var KNOWN_EXT = /* @__PURE__ */ new Set([...IMAGE_EXT, ...DOC_EXT, ...TEXT_EXT])
|
|
|
11114
11244
|
|
|
11115
11245
|
// src/shotUpload.ts
|
|
11116
11246
|
import { readFile as fsReadFile } from "fs/promises";
|
|
11117
|
-
import { basename as
|
|
11247
|
+
import { basename as basename5, isAbsolute as isAbsolute2, join as join15 } from "path";
|
|
11118
11248
|
var SHOT_MAX_FILE_BYTES = 10 * 1024 * 1024;
|
|
11119
11249
|
|
|
11120
11250
|
// src/taskless.ts
|
|
@@ -12214,7 +12344,7 @@ var thisHost = loadHostIdentity({ home: SWARM_HOME, envHostId: process.env.SWARM
|
|
|
12214
12344
|
function fmtRun(r, opts = {}) {
|
|
12215
12345
|
const mark = STATUS_MARK[r.status] ?? "?";
|
|
12216
12346
|
const area = r.area ? ` [${r.area}]` : "";
|
|
12217
|
-
const repo = r.repo ? ` (${
|
|
12347
|
+
const repo = r.repo ? ` (${basename6(r.repo)})` : "";
|
|
12218
12348
|
const q = r.status === "blocked" ? " \u2190 \u0436\u0434\u0451\u0442 \u043E\u0442\u0432\u0435\u0442\u0430" : "";
|
|
12219
12349
|
const why = r.status === "stopped" && r.stop_reason ? ` \u2014 ${r.stop_reason}` : "";
|
|
12220
12350
|
const priority = r.priority ? ` \u2691${r.priority > 0 ? "+" : ""}${r.priority}` : "";
|
|
@@ -12972,7 +13102,7 @@ switch (cmd) {
|
|
|
12972
13102
|
process.exit(1);
|
|
12973
13103
|
}
|
|
12974
13104
|
const run = db.getRun(runId);
|
|
12975
|
-
if (run) console.log(`#${run.id} ${run.name} ${run.task_slug}${run.repo ? ` (${
|
|
13105
|
+
if (run) console.log(`#${run.id} ${run.name} ${run.task_slug}${run.repo ? ` (${basename6(run.repo)})` : ""}`);
|
|
12976
13106
|
const events = db.events(runId);
|
|
12977
13107
|
if (events.length === 0) console.log("\u0441\u043E\u0431\u044B\u0442\u0438\u0439 \u043D\u0435\u0442");
|
|
12978
13108
|
else events.forEach((e) => console.log(`${e.at} ${e.kind}${e.text ? " " + e.text : ""}`));
|
package/dist/overmind.js
CHANGED
|
@@ -1212,8 +1212,8 @@ var init_runGuards = __esm({
|
|
|
1212
1212
|
function hasZoneModel(m) {
|
|
1213
1213
|
return m.tasks > 0 && m.zones.length > 0;
|
|
1214
1214
|
}
|
|
1215
|
-
function testFileFeature(
|
|
1216
|
-
const head =
|
|
1215
|
+
function testFileFeature(basename7) {
|
|
1216
|
+
const head = basename7.replace(/\.(test|spec)\.[a-z]+$/i, "").split(".")[0].toLowerCase();
|
|
1217
1217
|
return head && !GENERIC_DIRS.has(head) ? head : null;
|
|
1218
1218
|
}
|
|
1219
1219
|
function pathZoneCandidate(path) {
|
|
@@ -2907,6 +2907,44 @@ var init_heartbeat = __esm({
|
|
|
2907
2907
|
}
|
|
2908
2908
|
});
|
|
2909
2909
|
|
|
2910
|
+
// src/logNoise.ts
|
|
2911
|
+
function timesWord(n) {
|
|
2912
|
+
const tens = n % 100;
|
|
2913
|
+
if (tens >= 11 && tens <= 14) return "\u0440\u0430\u0437";
|
|
2914
|
+
return n % 10 >= 2 && n % 10 <= 4 ? "\u0440\u0430\u0437\u0430" : "\u0440\u0430\u0437";
|
|
2915
|
+
}
|
|
2916
|
+
function makeRepeatFilter(opts = {}) {
|
|
2917
|
+
const remindAfterMs = opts.remindAfterMs ?? DEFAULT_REMIND_MS;
|
|
2918
|
+
const streaks = /* @__PURE__ */ new Map();
|
|
2919
|
+
return {
|
|
2920
|
+
say(key, message, now) {
|
|
2921
|
+
const prev = streaks.get(key);
|
|
2922
|
+
if (!prev || prev.message !== message) {
|
|
2923
|
+
const tail2 = prev && prev.hidden > 0 ? ` (\u0434\u043E \u044D\u0442\u043E\u0433\u043E \u0442\u043E \u0436\u0435 \u0441\u0430\u043C\u043E\u0435 \u043C\u043E\u043B\u0447\u0430 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u043B\u043E\u0441\u044C \u0435\u0449\u0451 ${prev.hidden} ${timesWord(prev.hidden)})` : "";
|
|
2924
|
+
streaks.set(key, { message, since: now, saidAt: now, hidden: 0 });
|
|
2925
|
+
return `${message}${tail2}`;
|
|
2926
|
+
}
|
|
2927
|
+
prev.hidden += 1;
|
|
2928
|
+
if (now - prev.saidAt < remindAfterMs) return null;
|
|
2929
|
+
const hidden = prev.hidden;
|
|
2930
|
+
const minutes = Math.max(1, Math.round((now - prev.since) / 6e4));
|
|
2931
|
+
prev.saidAt = now;
|
|
2932
|
+
prev.hidden = 0;
|
|
2933
|
+
return `${message} \u2014 \u0442\u043E \u0436\u0435 \u0441\u0430\u043C\u043E\u0435 ${hidden} ${timesWord(hidden)} \u043F\u043E\u0434\u0440\u044F\u0434, \u0442\u044F\u043D\u0435\u0442\u0441\u044F ${minutes} \u043C\u0438\u043D`;
|
|
2934
|
+
},
|
|
2935
|
+
forget(key) {
|
|
2936
|
+
streaks.delete(key);
|
|
2937
|
+
}
|
|
2938
|
+
};
|
|
2939
|
+
}
|
|
2940
|
+
var DEFAULT_REMIND_MS;
|
|
2941
|
+
var init_logNoise = __esm({
|
|
2942
|
+
"src/logNoise.ts"() {
|
|
2943
|
+
"use strict";
|
|
2944
|
+
DEFAULT_REMIND_MS = 10 * 6e4;
|
|
2945
|
+
}
|
|
2946
|
+
});
|
|
2947
|
+
|
|
2910
2948
|
// src/agentToken.ts
|
|
2911
2949
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, unlinkSync as unlinkSync3 } from "fs";
|
|
2912
2950
|
import { join as join8 } from "path";
|
|
@@ -3324,11 +3362,100 @@ var init_procCleanup = __esm({
|
|
|
3324
3362
|
}
|
|
3325
3363
|
});
|
|
3326
3364
|
|
|
3365
|
+
// src/netTimeout.ts
|
|
3366
|
+
import { basename as basename2 } from "path";
|
|
3367
|
+
function isTimedOut(outcome) {
|
|
3368
|
+
return typeof outcome === "object" && outcome !== null && outcome.timedOut === true;
|
|
3369
|
+
}
|
|
3370
|
+
function noteTimedOut(scope, call, timeoutMs, outcome, warn = console.warn) {
|
|
3371
|
+
const line = `[${scope}] \u23F1 \u0432\u044B\u0437\u043E\u0432 \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u0437\u0430 ${humanMs(timeoutMs)} \u0438 \u043F\u0440\u0435\u0440\u0432\u0430\u043D: ${call} \u2014 \u0440\u0435\u043A\u043E\u043D\u0441\u0430\u0439\u043B \u0438\u0434\u0451\u0442 \u0434\u0430\u043B\u044C\u0448\u0435`;
|
|
3372
|
+
if (!isTimedOut(outcome)) {
|
|
3373
|
+
timeoutNoise.forget(noiseKey(scope, call));
|
|
3374
|
+
return false;
|
|
3375
|
+
}
|
|
3376
|
+
const say = timeoutNoise.say(noiseKey(scope, call), line, Date.now());
|
|
3377
|
+
if (say) warn(say);
|
|
3378
|
+
return true;
|
|
3379
|
+
}
|
|
3380
|
+
function noiseKey(scope, call) {
|
|
3381
|
+
return `timeout:${scope}:${call}`;
|
|
3382
|
+
}
|
|
3383
|
+
function humanMs(ms) {
|
|
3384
|
+
return ms >= 1e3 ? `${Math.round(ms / 1e3)}\u0441` : `${ms}\u043C\u0441`;
|
|
3385
|
+
}
|
|
3386
|
+
function destroyPipes(child) {
|
|
3387
|
+
for (const pipe of [child.stdout, child.stderr, child.stdin]) {
|
|
3388
|
+
try {
|
|
3389
|
+
pipe?.destroy?.();
|
|
3390
|
+
} catch {
|
|
3391
|
+
}
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3394
|
+
async function withHardTimeout(child, scope, call, timeoutMs, warn = console.warn) {
|
|
3395
|
+
let timer;
|
|
3396
|
+
const capped = new Promise((_, reject) => {
|
|
3397
|
+
timer = setTimeout(() => {
|
|
3398
|
+
child.kill("SIGKILL");
|
|
3399
|
+
destroyPipes(child);
|
|
3400
|
+
reject(new CallTimedOutError(call, timeoutMs));
|
|
3401
|
+
}, timeoutMs + HARD_CAP_GRACE_MS);
|
|
3402
|
+
timer.unref?.();
|
|
3403
|
+
});
|
|
3404
|
+
try {
|
|
3405
|
+
const res = await Promise.race([child, capped]);
|
|
3406
|
+
noteTimedOut(scope, call, timeoutMs, res, warn);
|
|
3407
|
+
return res;
|
|
3408
|
+
} catch (e) {
|
|
3409
|
+
noteTimedOut(scope, call, timeoutMs, e, warn);
|
|
3410
|
+
throw e;
|
|
3411
|
+
} finally {
|
|
3412
|
+
if (timer) clearTimeout(timer);
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
function callLabel(cmd, args, head = 4) {
|
|
3416
|
+
const shown = args.slice(0, head).join(" ");
|
|
3417
|
+
return `${cmd} ${shown}${args.length > head ? " \u2026" : ""}`.trim();
|
|
3418
|
+
}
|
|
3419
|
+
function gitCallLabel(repo, args) {
|
|
3420
|
+
return `git -C ${basename2(repo) || repo} ${args.join(" ")}`;
|
|
3421
|
+
}
|
|
3422
|
+
var GH_CALL_TIMEOUT_MS, GIT_NET_TIMEOUT_MS, GIT_LOCAL_TIMEOUT_MS, GIT_HEAVY_NET_TIMEOUT_MS, HARD_CAP_GRACE_MS, CallTimedOutError, timeoutNoise;
|
|
3423
|
+
var init_netTimeout = __esm({
|
|
3424
|
+
"src/netTimeout.ts"() {
|
|
3425
|
+
"use strict";
|
|
3426
|
+
init_logNoise();
|
|
3427
|
+
GH_CALL_TIMEOUT_MS = 15e3;
|
|
3428
|
+
GIT_NET_TIMEOUT_MS = 15e3;
|
|
3429
|
+
GIT_LOCAL_TIMEOUT_MS = 5e3;
|
|
3430
|
+
GIT_HEAVY_NET_TIMEOUT_MS = 6e4;
|
|
3431
|
+
HARD_CAP_GRACE_MS = 2e3;
|
|
3432
|
+
CallTimedOutError = class extends Error {
|
|
3433
|
+
timedOut = true;
|
|
3434
|
+
constructor(call, timeoutMs) {
|
|
3435
|
+
super(`\u0432\u044B\u0437\u043E\u0432 \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u0437\u0430 ${timeoutMs}\u043C\u0441 \u0438 \u043F\u0440\u0435\u0440\u0432\u0430\u043D: ${call}`);
|
|
3436
|
+
this.name = "CallTimedOutError";
|
|
3437
|
+
}
|
|
3438
|
+
};
|
|
3439
|
+
timeoutNoise = makeRepeatFilter();
|
|
3440
|
+
}
|
|
3441
|
+
});
|
|
3442
|
+
|
|
3327
3443
|
// src/git.ts
|
|
3328
3444
|
import { existsSync as existsSync10, readdirSync as readdirSync11, statSync as statSync8 } from "fs";
|
|
3329
3445
|
import { appendFile, chmod, mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
3330
3446
|
import { isAbsolute as isAbsolute2, join as join17, sep as sep2 } from "path";
|
|
3331
3447
|
import { $ as $2 } from "execa";
|
|
3448
|
+
function gitNet(repo, args, timeoutMs) {
|
|
3449
|
+
return withHardTimeout(
|
|
3450
|
+
$2({ reject: false, timeout: timeoutMs })`git -C ${repo} ${args}`,
|
|
3451
|
+
"git",
|
|
3452
|
+
gitCallLabel(repo, args),
|
|
3453
|
+
timeoutMs
|
|
3454
|
+
).catch(() => null);
|
|
3455
|
+
}
|
|
3456
|
+
function gitNetStrict(repo, args, timeoutMs) {
|
|
3457
|
+
return withHardTimeout($2({ timeout: timeoutMs })`git -C ${repo} ${args}`, "git", gitCallLabel(repo, args), timeoutMs);
|
|
3458
|
+
}
|
|
3332
3459
|
function isUnrecoverableRefError(e) {
|
|
3333
3460
|
if (e instanceof MissingRefError) return true;
|
|
3334
3461
|
const msg = e instanceof Error ? `${e.name}: ${e.message}` : String(e);
|
|
@@ -3553,26 +3680,27 @@ async function remoteMainRef(repo) {
|
|
|
3553
3680
|
throw new Error(`\u043D\u0435 \u043D\u0430\u0448\u0451\u043B \u0434\u0435\u0444\u043E\u043B\u0442-\u0432\u0435\u0442\u043A\u0443 origin \u0432 ${repo} (\u043D\u0435\u0442 origin/HEAD, origin/main, origin/master)`);
|
|
3554
3681
|
}
|
|
3555
3682
|
async function remoteBranchExists(repo, branch) {
|
|
3556
|
-
const res = await
|
|
3557
|
-
if (res.exitCode !== 0) return null;
|
|
3683
|
+
const res = await gitNet(repo, ["ls-remote", "--heads", "origin", `refs/heads/${branch}`], 5e3);
|
|
3684
|
+
if (!res || res.exitCode !== 0) return null;
|
|
3558
3685
|
return res.stdout.trim().length > 0;
|
|
3559
3686
|
}
|
|
3560
|
-
async function remoteBaseRef(repo, branch) {
|
|
3561
|
-
await
|
|
3687
|
+
async function remoteBaseRef(repo, branch, timeoutMs = GIT_NET_TIMEOUT_MS) {
|
|
3688
|
+
await gitNet(repo, ["fetch", "--quiet", "origin", branch], timeoutMs);
|
|
3562
3689
|
return `origin/${branch}`;
|
|
3563
3690
|
}
|
|
3564
|
-
async function remoteRepoFullName(repo) {
|
|
3565
|
-
const
|
|
3691
|
+
async function remoteRepoFullName(repo, timeoutMs = GIT_LOCAL_TIMEOUT_MS) {
|
|
3692
|
+
const res = await gitNet(repo, ["remote", "get-url", "origin"], timeoutMs);
|
|
3693
|
+
const url = res?.stdout.trim() ?? "";
|
|
3566
3694
|
const m = url.match(GITHUB_REMOTE_RE);
|
|
3567
3695
|
return m ? m[1] : null;
|
|
3568
3696
|
}
|
|
3569
3697
|
async function journalForBranch(repo, branch, slug) {
|
|
3570
|
-
await
|
|
3698
|
+
await gitNet(repo, ["fetch", "--quiet", "origin", branch], GIT_NET_TIMEOUT_MS);
|
|
3571
3699
|
const out = await $2({ reject: false })`git -C ${repo} show ${`origin/${branch}:journal/${slug}.md`}`;
|
|
3572
3700
|
return out.exitCode === 0 && out.stdout ? out.stdout : null;
|
|
3573
3701
|
}
|
|
3574
3702
|
async function prepareDetachedWorktree(repo, branch, worktree) {
|
|
3575
|
-
await
|
|
3703
|
+
await gitNetStrict(repo, ["fetch", "--quiet", "origin"], GIT_HEAVY_NET_TIMEOUT_MS);
|
|
3576
3704
|
const ref = `origin/${branch}`;
|
|
3577
3705
|
if (!await revParse(repo, `${ref}^{commit}`)) throw new MissingRefError(ref, repo);
|
|
3578
3706
|
await $2`git -C ${repo} worktree add --detach --force ${worktree} ${ref}`;
|
|
@@ -3589,7 +3717,7 @@ async function mergeRef(worktree, ref) {
|
|
|
3589
3717
|
return { clean: false, conflicts: u ? u.split("\n") : [], changed: false };
|
|
3590
3718
|
}
|
|
3591
3719
|
async function pushHeadTo(worktree, branch) {
|
|
3592
|
-
await
|
|
3720
|
+
await gitNetStrict(worktree, ["push", "origin", `HEAD:${branch}`], GIT_HEAVY_NET_TIMEOUT_MS);
|
|
3593
3721
|
}
|
|
3594
3722
|
async function snapshotWorktree(worktree, message) {
|
|
3595
3723
|
try {
|
|
@@ -3598,7 +3726,7 @@ async function snapshotWorktree(worktree, message) {
|
|
|
3598
3726
|
await $2({ reject: false })`git -C ${worktree} add -A`;
|
|
3599
3727
|
const commit = await $2({ reject: false })`git -C ${worktree} commit --no-verify -m ${message}`;
|
|
3600
3728
|
if (commit.exitCode !== 0) return false;
|
|
3601
|
-
await
|
|
3729
|
+
await gitNet(worktree, ["push"], GIT_NET_TIMEOUT_MS);
|
|
3602
3730
|
return true;
|
|
3603
3731
|
} catch {
|
|
3604
3732
|
return false;
|
|
@@ -3614,6 +3742,7 @@ var init_git = __esm({
|
|
|
3614
3742
|
"src/git.ts"() {
|
|
3615
3743
|
"use strict";
|
|
3616
3744
|
init_procCleanup();
|
|
3745
|
+
init_netTimeout();
|
|
3617
3746
|
init_swarmFiles();
|
|
3618
3747
|
WorktreeBusyError = class extends Error {
|
|
3619
3748
|
constructor(branch, worktreePath) {
|
|
@@ -4301,7 +4430,7 @@ var init_attachments = __esm({
|
|
|
4301
4430
|
|
|
4302
4431
|
// src/shotUpload.ts
|
|
4303
4432
|
import { readFile as fsReadFile } from "fs/promises";
|
|
4304
|
-
import { basename as
|
|
4433
|
+
import { basename as basename4, isAbsolute as isAbsolute3, join as join21 } from "path";
|
|
4305
4434
|
function shotMimetype(path) {
|
|
4306
4435
|
const dot = path.lastIndexOf(".");
|
|
4307
4436
|
if (dot < 0) return null;
|
|
@@ -4340,7 +4469,7 @@ async function readShots(paths, opts) {
|
|
|
4340
4469
|
skipped.push({ path, reason: `${(bytes.byteLength / 1024 / 1024).toFixed(1)} \u041C\u0411 \u2014 \u0431\u043E\u043B\u044C\u0448\u0435 \u043B\u0438\u043C\u0438\u0442\u0430 ${maxBytes / 1024 / 1024} \u041C\u0411` });
|
|
4341
4470
|
continue;
|
|
4342
4471
|
}
|
|
4343
|
-
files.push({ path, fileName:
|
|
4472
|
+
files.push({ path, fileName: basename4(path), mimetype, bytes });
|
|
4344
4473
|
}
|
|
4345
4474
|
return { files, skipped };
|
|
4346
4475
|
}
|
|
@@ -6237,7 +6366,7 @@ var init_droneStore = __esm({
|
|
|
6237
6366
|
// src/overmind.ts
|
|
6238
6367
|
import { homedir as homedir5 } from "os";
|
|
6239
6368
|
import { existsSync as existsSync17, readFileSync as readFileSync20, readdirSync as readdirSync13, renameSync as renameSync11 } from "fs";
|
|
6240
|
-
import { basename as
|
|
6369
|
+
import { basename as basename6, dirname as dirname4, join as join30 } from "path";
|
|
6241
6370
|
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
|
|
6242
6371
|
import { spawn as spawn3 } from "child_process";
|
|
6243
6372
|
|
|
@@ -8940,39 +9069,8 @@ function installLogStamps(now = () => /* @__PURE__ */ new Date()) {
|
|
|
8940
9069
|
};
|
|
8941
9070
|
}
|
|
8942
9071
|
|
|
8943
|
-
// src/logNoise.ts
|
|
8944
|
-
var DEFAULT_REMIND_MS = 10 * 6e4;
|
|
8945
|
-
function timesWord(n) {
|
|
8946
|
-
const tens = n % 100;
|
|
8947
|
-
if (tens >= 11 && tens <= 14) return "\u0440\u0430\u0437";
|
|
8948
|
-
return n % 10 >= 2 && n % 10 <= 4 ? "\u0440\u0430\u0437\u0430" : "\u0440\u0430\u0437";
|
|
8949
|
-
}
|
|
8950
|
-
function makeRepeatFilter(opts = {}) {
|
|
8951
|
-
const remindAfterMs = opts.remindAfterMs ?? DEFAULT_REMIND_MS;
|
|
8952
|
-
const streaks = /* @__PURE__ */ new Map();
|
|
8953
|
-
return {
|
|
8954
|
-
say(key, message, now) {
|
|
8955
|
-
const prev = streaks.get(key);
|
|
8956
|
-
if (!prev || prev.message !== message) {
|
|
8957
|
-
const tail2 = prev && prev.hidden > 0 ? ` (\u0434\u043E \u044D\u0442\u043E\u0433\u043E \u0442\u043E \u0436\u0435 \u0441\u0430\u043C\u043E\u0435 \u043C\u043E\u043B\u0447\u0430 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u043B\u043E\u0441\u044C \u0435\u0449\u0451 ${prev.hidden} ${timesWord(prev.hidden)})` : "";
|
|
8958
|
-
streaks.set(key, { message, since: now, saidAt: now, hidden: 0 });
|
|
8959
|
-
return `${message}${tail2}`;
|
|
8960
|
-
}
|
|
8961
|
-
prev.hidden += 1;
|
|
8962
|
-
if (now - prev.saidAt < remindAfterMs) return null;
|
|
8963
|
-
const hidden = prev.hidden;
|
|
8964
|
-
const minutes = Math.max(1, Math.round((now - prev.since) / 6e4));
|
|
8965
|
-
prev.saidAt = now;
|
|
8966
|
-
prev.hidden = 0;
|
|
8967
|
-
return `${message} \u2014 \u0442\u043E \u0436\u0435 \u0441\u0430\u043C\u043E\u0435 ${hidden} ${timesWord(hidden)} \u043F\u043E\u0434\u0440\u044F\u0434, \u0442\u044F\u043D\u0435\u0442\u0441\u044F ${minutes} \u043C\u0438\u043D`;
|
|
8968
|
-
},
|
|
8969
|
-
forget(key) {
|
|
8970
|
-
streaks.delete(key);
|
|
8971
|
-
}
|
|
8972
|
-
};
|
|
8973
|
-
}
|
|
8974
|
-
|
|
8975
9072
|
// src/overmind.ts
|
|
9073
|
+
init_logNoise();
|
|
8976
9074
|
init_linkFailure();
|
|
8977
9075
|
|
|
8978
9076
|
// src/repoRegistry.ts
|
|
@@ -10830,9 +10928,22 @@ init_git();
|
|
|
10830
10928
|
|
|
10831
10929
|
// src/gh.ts
|
|
10832
10930
|
init_src();
|
|
10931
|
+
init_netTimeout();
|
|
10833
10932
|
import { $ as $3 } from "execa";
|
|
10834
|
-
|
|
10835
|
-
|
|
10933
|
+
import { basename as basename3 } from "path";
|
|
10934
|
+
async function runGh(args, timeoutMs, cwd) {
|
|
10935
|
+
const label2 = callLabel("gh", args) + (cwd ? ` (repo ${basename3(cwd)})` : "");
|
|
10936
|
+
const child = cwd ? $3({ cwd, timeout: timeoutMs })`gh ${args}` : $3({ timeout: timeoutMs })`gh ${args}`;
|
|
10937
|
+
return (await withHardTimeout(child, "gh", label2, timeoutMs)).stdout;
|
|
10938
|
+
}
|
|
10939
|
+
function ghRunner(timeoutMs = GH_CALL_TIMEOUT_MS) {
|
|
10940
|
+
return (args) => runGh(args, timeoutMs);
|
|
10941
|
+
}
|
|
10942
|
+
function ghRepoRunner(timeoutMs = GH_CALL_TIMEOUT_MS) {
|
|
10943
|
+
return (args, cwd) => runGh(args, timeoutMs, cwd);
|
|
10944
|
+
}
|
|
10945
|
+
var realRunner = ghRunner();
|
|
10946
|
+
var realRepoRunner = ghRepoRunner();
|
|
10836
10947
|
var GH_PR_RE = /^(?:https?:\/\/)?(?:www\.)?github\.com\/[^/\s]+\/[^/\s]+\/pull\/\d+(?:[/?#].*)?$/i;
|
|
10837
10948
|
function isGithubPrUrl(url) {
|
|
10838
10949
|
return GH_PR_RE.test(url.trim());
|
|
@@ -10922,7 +11033,7 @@ async function closePR(prUrl, run = realRunner) {
|
|
|
10922
11033
|
async function postPrComment(prUrl, body, run = realRunner) {
|
|
10923
11034
|
await run(["pr", "comment", prUrl, "--body", body]);
|
|
10924
11035
|
}
|
|
10925
|
-
var realCommentsRunner =
|
|
11036
|
+
var realCommentsRunner = (prUrl) => runGh(["pr", "view", prUrl, "--json", "comments"], GH_CALL_TIMEOUT_MS);
|
|
10926
11037
|
var VERDICT_RE = /^[^A-Za-z]*(APPROVED?|LGTM|(?:REQUEST(?:ED)?\s+)?CHANGES(?:\s+REQUESTED)?)\b/i;
|
|
10927
11038
|
var APPROVE_RE = /^(APPROVE|LGTM)/i;
|
|
10928
11039
|
function verdictLabel(verdict) {
|
|
@@ -10964,7 +11075,7 @@ async function scanPrComments(prUrl, sinceIso, run, pick3) {
|
|
|
10964
11075
|
async function latestVerifyVerdictComment(prUrl, sinceIso, run = realCommentsRunner) {
|
|
10965
11076
|
return scanPrComments(prUrl, sinceIso, run, (body) => parseVerifyVerdictComment(body));
|
|
10966
11077
|
}
|
|
10967
|
-
var realPrCommitsRunner =
|
|
11078
|
+
var realPrCommitsRunner = (prUrl) => runGh(["pr", "view", prUrl, "--json", "commits"], GH_CALL_TIMEOUT_MS);
|
|
10968
11079
|
async function prHasCommitsSince(prUrl, sinceIso, run = realPrCommitsRunner) {
|
|
10969
11080
|
if (!isGithubPrUrl(prUrl)) return false;
|
|
10970
11081
|
let out;
|
|
@@ -10988,7 +11099,7 @@ async function prHasCommitsSince(prUrl, sinceIso, run = realPrCommitsRunner) {
|
|
|
10988
11099
|
return Number.isFinite(ms) && (!Number.isFinite(sinceMs) || ms >= sinceMs);
|
|
10989
11100
|
});
|
|
10990
11101
|
}
|
|
10991
|
-
var realPrCommitTitlesRunner =
|
|
11102
|
+
var realPrCommitTitlesRunner = (prUrl) => runGh(["pr", "view", prUrl, "--json", "commits"], GH_CALL_TIMEOUT_MS);
|
|
10992
11103
|
async function prCommitTitles(prUrl, run = realPrCommitTitlesRunner) {
|
|
10993
11104
|
if (!isGithubPrUrl(prUrl)) return [];
|
|
10994
11105
|
let out;
|
|
@@ -11027,7 +11138,12 @@ function firstLine(s) {
|
|
|
11027
11138
|
return s.split("\n").map((l) => l.trim()).find((l) => l.length > 0) ?? "gh \u0432\u0435\u0440\u043D\u0443\u043B 403";
|
|
11028
11139
|
}
|
|
11029
11140
|
var realChecksRunner = async (pr) => {
|
|
11030
|
-
const r = await
|
|
11141
|
+
const r = await withHardTimeout(
|
|
11142
|
+
$3({ reject: false, timeout: 15e3 })`gh pr checks ${pr} --json state,name,bucket,link`,
|
|
11143
|
+
"gh",
|
|
11144
|
+
callLabel("gh", ["pr", "checks", pr]),
|
|
11145
|
+
15e3
|
|
11146
|
+
);
|
|
11031
11147
|
const stdout = r.stdout ?? "";
|
|
11032
11148
|
const stderr = r.stderr ?? "";
|
|
11033
11149
|
if (!stdout.trim() && NO_CHECKS_STDERR.test(stderr)) return "[]";
|
|
@@ -11096,7 +11212,15 @@ async function prCiStatus(pr, run = realChecksRunner) {
|
|
|
11096
11212
|
if (rows.some((r) => r.bucket === "pending")) return { bucket: "pending", failing: [], failingRunIds: [], ...counts };
|
|
11097
11213
|
return { bucket: "pass", failing: [], failingRunIds: [], ...counts };
|
|
11098
11214
|
}
|
|
11099
|
-
var realRunLogRunner = async (runId) =>
|
|
11215
|
+
var realRunLogRunner = async (runId) => {
|
|
11216
|
+
const r = await withHardTimeout(
|
|
11217
|
+
$3({ reject: false, timeout: 3e4, maxBuffer: 10 * 1024 * 1024 })`gh run view ${runId} --log-failed`,
|
|
11218
|
+
"gh",
|
|
11219
|
+
callLabel("gh", ["run", "view", runId]),
|
|
11220
|
+
3e4
|
|
11221
|
+
);
|
|
11222
|
+
return r.stdout;
|
|
11223
|
+
};
|
|
11100
11224
|
var CI_SUMMARY_LOG_CHARS = 4e3;
|
|
11101
11225
|
var CI_SUMMARY_MAX_RUNS = 2;
|
|
11102
11226
|
async function ciFailureSummary(failing, failingRunIds, logRun = realRunLogRunner) {
|
|
@@ -13371,7 +13495,7 @@ function makeEnvGate(opts) {
|
|
|
13371
13495
|
// src/web.ts
|
|
13372
13496
|
init_src();
|
|
13373
13497
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
13374
|
-
import { basename as
|
|
13498
|
+
import { basename as basename5 } from "path";
|
|
13375
13499
|
import { serve as serve2 } from "@hono/node-server";
|
|
13376
13500
|
|
|
13377
13501
|
// src/diff.ts
|
|
@@ -13577,7 +13701,7 @@ async function changedPaths(worktree, opts = {}) {
|
|
|
13577
13701
|
// package.json
|
|
13578
13702
|
var package_default = {
|
|
13579
13703
|
name: "@taskless-app/swarm",
|
|
13580
|
-
version: "0.6.
|
|
13704
|
+
version: "0.6.23",
|
|
13581
13705
|
type: "module",
|
|
13582
13706
|
description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
13583
13707
|
keywords: [
|
|
@@ -13627,7 +13751,7 @@ var package_default = {
|
|
|
13627
13751
|
execa: "^10.0.0",
|
|
13628
13752
|
zod: "3.25.76"
|
|
13629
13753
|
},
|
|
13630
|
-
gitHead: "
|
|
13754
|
+
gitHead: "af6c4af0f523891b5db805d9b4583021688ed1f5"
|
|
13631
13755
|
};
|
|
13632
13756
|
|
|
13633
13757
|
// src/version.ts
|
|
@@ -13841,7 +13965,7 @@ function timelineState(db, now = Date.now(), overmindLog = []) {
|
|
|
13841
13965
|
id: r.id,
|
|
13842
13966
|
name: r.name,
|
|
13843
13967
|
slug: r.task_slug,
|
|
13844
|
-
repo:
|
|
13968
|
+
repo: basename5(r.repo || "") || "?",
|
|
13845
13969
|
status: r.status,
|
|
13846
13970
|
area: r.area,
|
|
13847
13971
|
start: sqliteIso(r.created_at),
|
|
@@ -18045,7 +18169,7 @@ async function buildReliefCostCandidatesFor(deps, now, droneCap) {
|
|
|
18045
18169
|
if (deps.exclusiveProject && await deps.exclusiveProject(repo)) continue;
|
|
18046
18170
|
} catch {
|
|
18047
18171
|
}
|
|
18048
|
-
exclusiveRepos.push(
|
|
18172
|
+
exclusiveRepos.push(basename6(repo));
|
|
18049
18173
|
}
|
|
18050
18174
|
const otherHosts = [
|
|
18051
18175
|
...new Set(
|
|
@@ -19016,7 +19140,7 @@ async function resolveConflict(deps, reviewRun) {
|
|
|
19016
19140
|
model: reviewRun.model,
|
|
19017
19141
|
review_model: reviewRun.review_model
|
|
19018
19142
|
});
|
|
19019
|
-
const wt = join30(deps.worktreesDir,
|
|
19143
|
+
const wt = join30(deps.worktreesDir, basename6(repo), `${reviewRun.task_slug}-resolve-${resolver.id}`);
|
|
19020
19144
|
try {
|
|
19021
19145
|
await deps.git.prepareDetachedWorktree(repo, branch, wt);
|
|
19022
19146
|
await deps.git.setWorktreeIdentity(wt, resolver.name);
|
|
@@ -19073,7 +19197,7 @@ async function spawnReviewer(deps, reviewRun, files) {
|
|
|
19073
19197
|
// (своей у ревьюера нет, TASWM-204), и коммент с вердиктом должен уехать именно туда.
|
|
19074
19198
|
workspace_id: reviewRun.workspace_id
|
|
19075
19199
|
});
|
|
19076
|
-
const wt = join30(deps.worktreesDir,
|
|
19200
|
+
const wt = join30(deps.worktreesDir, basename6(repo), `${reviewRun.task_slug}-review-${reviewer.id}`);
|
|
19077
19201
|
try {
|
|
19078
19202
|
await deps.git.prepareDetachedWorktree(repo, branch, wt);
|
|
19079
19203
|
await deps.git.setWorktreeIdentity(wt, reviewer.name);
|
|
@@ -19149,7 +19273,7 @@ async function spawnVerifier(deps, verifiedRun, files) {
|
|
|
19149
19273
|
// штамп цикла: фикс-итерацию проверяет свежий верификатор
|
|
19150
19274
|
workspace_id: verifiedRun.workspace_id
|
|
19151
19275
|
});
|
|
19152
|
-
const wt = join30(deps.worktreesDir,
|
|
19276
|
+
const wt = join30(deps.worktreesDir, basename6(repo), `${verifiedRun.task_slug}-verify-${verifier.id}`);
|
|
19153
19277
|
try {
|
|
19154
19278
|
await deps.git.prepareDetachedWorktree(repo, branch, wt);
|
|
19155
19279
|
await deps.git.setWorktreeIdentity(wt, verifier.name);
|
|
@@ -20017,7 +20141,7 @@ async function runDaemon(opts) {
|
|
|
20017
20141
|
worktreesDir,
|
|
20018
20142
|
activeWorktreePaths: new Set(runsWithWorktree.filter((r) => !isTerminalStatus(r.status)).map((r) => r.worktree_path)),
|
|
20019
20143
|
containerRunPrefixes: runsWithWorktree.map((r) => ({
|
|
20020
|
-
prefix: composeProjectPrefix(
|
|
20144
|
+
prefix: composeProjectPrefix(basename6(r.worktree_path)),
|
|
20021
20145
|
active: !isTerminalStatus(r.status)
|
|
20022
20146
|
}))
|
|
20023
20147
|
}).then(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taskless-app/swarm",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.23",
|
|
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": [
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"execa": "^10.0.0",
|
|
39
39
|
"zod": "3.25.76"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "af6c4af0f523891b5db805d9b4583021688ed1f5",
|
|
42
42
|
"scripts": {
|
|
43
43
|
"overmind": "NODE_OPTIONS=\"${NODE_OPTIONS:-} --conditions=development\" tsx src/overmind.ts",
|
|
44
44
|
"swarm": "NODE_OPTIONS=\"${NODE_OPTIONS:-} --conditions=development\" tsx src/cli.ts",
|