@taskless-app/swarm 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -5
- package/dist/cli.js +285 -70
- package/dist/overmind.js +27 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,10 +28,20 @@ npx @taskless-app/swarm start --repo <путь к репо> # поднят
|
|
|
28
28
|
```bash
|
|
29
29
|
npm i -g @taskless-app/swarm
|
|
30
30
|
swarm login --workspace <slug>
|
|
31
|
-
swarm start --repo <путь к репо> #
|
|
31
|
+
swarm start --repo <путь к репо> # поднять рой: уходит в фон, терминал остаётся вам
|
|
32
32
|
swarm --help # список остальных команд (spawn/ls/questions/answer/…)
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
**Демон открепляется от терминала.** `swarm start` не занимает окно: процесс уходит
|
|
36
|
+
в фон, а весь вывод пишется в `~/.taskless-swarm/overmind.log` — тот самый файл, из
|
|
37
|
+
которого агент читает хвост лога удалённо. Посмотреть: `swarm logs -f`. Нужен вывод
|
|
38
|
+
прямо в терминале (отладка, systemd, docker, где фоном занимается супервизор) —
|
|
39
|
+
`swarm start --foreground` (он же `-f`, `--attach`).
|
|
40
|
+
|
|
41
|
+
Команда не отчитывается о запуске раньше времени: она ждёт, пока демон реально
|
|
42
|
+
поднимется, и только тогда говорит «поднят». Не поднялся — покажет хвост лога с
|
|
43
|
+
настоящей причиной (занятый порт, отсутствующий токен) и завершится с ошибкой.
|
|
44
|
+
|
|
35
45
|
Полный гайд по настройке и запуску роя — на [taskless.ru](https://taskless.ru).
|
|
36
46
|
|
|
37
47
|
## Остановить, приостановить, отключить машину
|
|
@@ -138,14 +148,19 @@ swarm_daemon_log(hostId, lines) # хвост лога самого демона
|
|
|
138
148
|
трекера лог не оседает, строка обмена умирает на чтении. Чужие логи недоступны —
|
|
139
149
|
и запрос, и доставка скоупятся владельцем машины.
|
|
140
150
|
|
|
141
|
-
Лог самого демона
|
|
142
|
-
|
|
151
|
+
Лог самого демона заводится сам: фоновый `swarm start` пишет в
|
|
152
|
+
`~/.taskless-swarm/overmind.log` и ротирует его при старте (прошлый — `.1`). Свой
|
|
153
|
+
путь — `SWARM_DAEMON_LOG`. Смотреть на месте:
|
|
143
154
|
|
|
144
155
|
```bash
|
|
145
|
-
swarm
|
|
146
|
-
|
|
156
|
+
swarm logs # хвост лога демона (по умолчанию 200 строк)
|
|
157
|
+
swarm logs -n 50 -f # следить за новыми строками
|
|
158
|
+
swarm log <runId> # это ДРУГОЕ: лог конкретного прогона
|
|
147
159
|
```
|
|
148
160
|
|
|
161
|
+
Запустили с `--foreground` — вывод идёт в терминал, и файла не будет: тогда за него
|
|
162
|
+
отвечает тот, кто перенаправил (systemd, docker, `tee`).
|
|
163
|
+
|
|
149
164
|
## Правообладатель и лицензия
|
|
150
165
|
|
|
151
166
|
© 2026 Ilya Smurov. Проприетарное коммерческое ПО — см. [LICENSE](./LICENSE).
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { basename as basename4 } from "path";
|
|
5
|
-
import { existsSync as existsSync9, readdirSync as readdirSync6 } from "fs";
|
|
5
|
+
import { existsSync as existsSync9, readdirSync as readdirSync6, statSync as statSync7, openSync as openSync4, readSync as readSync2, closeSync as closeSync4 } from "fs";
|
|
6
6
|
import { createInterface } from "readline/promises";
|
|
7
7
|
import { setTimeout as sleep2 } from "timers/promises";
|
|
8
8
|
|
|
@@ -1464,7 +1464,19 @@ import { randomUUID } from "crypto";
|
|
|
1464
1464
|
|
|
1465
1465
|
// src/resources.ts
|
|
1466
1466
|
import os from "os";
|
|
1467
|
+
|
|
1468
|
+
// src/quietExec.ts
|
|
1467
1469
|
import { execFileSync } from "child_process";
|
|
1470
|
+
function execQuiet(file, args = [], opts = {}) {
|
|
1471
|
+
return execFileSync(file, args, {
|
|
1472
|
+
encoding: "utf8",
|
|
1473
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1474
|
+
...opts.maxBuffer ? { maxBuffer: opts.maxBuffer } : {}
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
var PROC_SNAPSHOT_MAX_BUFFER = 16 * 1024 * 1024;
|
|
1478
|
+
|
|
1479
|
+
// src/resources.ts
|
|
1468
1480
|
import { readFileSync as readFileSync2, statfsSync } from "fs";
|
|
1469
1481
|
function isTransientResourceError(e) {
|
|
1470
1482
|
const code = e?.code;
|
|
@@ -1489,7 +1501,7 @@ function parseVmStatAvailableBytes(vmStatOut) {
|
|
|
1489
1501
|
function availableMemBytes() {
|
|
1490
1502
|
if (process.platform === "darwin") {
|
|
1491
1503
|
try {
|
|
1492
|
-
const bytes = parseVmStatAvailableBytes(
|
|
1504
|
+
const bytes = parseVmStatAvailableBytes(execQuiet("vm_stat"));
|
|
1493
1505
|
if (bytes > 0) return bytes;
|
|
1494
1506
|
} catch (e) {
|
|
1495
1507
|
logTransientSpawnError("vm_stat", e);
|
|
@@ -1503,7 +1515,7 @@ function parseSysctlInt(out) {
|
|
|
1503
1515
|
}
|
|
1504
1516
|
function readSysctlPair(nameA, nameB) {
|
|
1505
1517
|
try {
|
|
1506
|
-
const lines =
|
|
1518
|
+
const lines = execQuiet("sysctl", ["-n", nameA, nameB]).trim().split("\n");
|
|
1507
1519
|
return [parseSysctlInt(lines[0] ?? ""), parseSysctlInt(lines[1] ?? "")];
|
|
1508
1520
|
} catch (e) {
|
|
1509
1521
|
logTransientSpawnError(`sysctl ${nameA}/${nameB}`, e);
|
|
@@ -3285,11 +3297,86 @@ function parseDecision(v) {
|
|
|
3285
3297
|
}
|
|
3286
3298
|
}
|
|
3287
3299
|
|
|
3288
|
-
// src/
|
|
3289
|
-
import {
|
|
3300
|
+
// src/daemonLaunch.ts
|
|
3301
|
+
import { openSync as openSync2, closeSync as closeSync2, renameSync as renameSync2, statSync as statSync2, writeFileSync as writeFileSync3, readFileSync as readFileSync4 } from "fs";
|
|
3302
|
+
import { spawn } from "child_process";
|
|
3303
|
+
var FOREGROUND_FLAGS = /* @__PURE__ */ new Set(["--foreground", "-f", "--attach"]);
|
|
3304
|
+
function parseStartMode(argv) {
|
|
3305
|
+
const rest = argv.filter((a) => !FOREGROUND_FLAGS.has(a));
|
|
3306
|
+
return { foreground: rest.length !== argv.length, rest };
|
|
3307
|
+
}
|
|
3308
|
+
function childStartArgv(rest) {
|
|
3309
|
+
return ["start", ...rest.filter((a) => !FOREGROUND_FLAGS.has(a)), "--foreground"];
|
|
3310
|
+
}
|
|
3311
|
+
function rotateDaemonLog(path, maxBytes) {
|
|
3312
|
+
let size;
|
|
3313
|
+
try {
|
|
3314
|
+
size = statSync2(path).size;
|
|
3315
|
+
} catch {
|
|
3316
|
+
return "missing";
|
|
3317
|
+
}
|
|
3318
|
+
if (size <= maxBytes) return "kept";
|
|
3319
|
+
renameSync2(path, `${path}.1`);
|
|
3320
|
+
writeFileSync3(path, "");
|
|
3321
|
+
return "rotated";
|
|
3322
|
+
}
|
|
3323
|
+
function tailText(text, lines) {
|
|
3324
|
+
const rows = text.split("\n");
|
|
3325
|
+
if (rows[rows.length - 1] === "") rows.pop();
|
|
3326
|
+
return rows.slice(-lines).join("\n");
|
|
3327
|
+
}
|
|
3328
|
+
async function waitForReady(opts) {
|
|
3329
|
+
const now = opts.now ?? Date.now;
|
|
3330
|
+
const sleep3 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
3331
|
+
const started = now();
|
|
3332
|
+
for (; ; ) {
|
|
3333
|
+
if (await opts.probe()) return "ready";
|
|
3334
|
+
if (!opts.alive()) return "died";
|
|
3335
|
+
if (now() - started >= opts.timeoutMs) return "timeout";
|
|
3336
|
+
await sleep3(opts.pollMs);
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
function launchDetached(opts) {
|
|
3340
|
+
const fd = openSync2(opts.logPath, "a");
|
|
3341
|
+
try {
|
|
3342
|
+
const child = spawn(opts.execPath, [...opts.execArgv, opts.entry, ...opts.args], {
|
|
3343
|
+
detached: true,
|
|
3344
|
+
stdio: ["ignore", fd, fd],
|
|
3345
|
+
env: opts.env
|
|
3346
|
+
});
|
|
3347
|
+
child.unref();
|
|
3348
|
+
let exited = false;
|
|
3349
|
+
child.once("exit", () => {
|
|
3350
|
+
exited = true;
|
|
3351
|
+
});
|
|
3352
|
+
return {
|
|
3353
|
+
pid: child.pid ?? -1,
|
|
3354
|
+
// Не `child.killed` (он про посланный сигнал) и не exit-код: после unref событие
|
|
3355
|
+
// может не прийти вовсе — спрашиваем ядро сигналом 0, это и есть «процесс есть».
|
|
3356
|
+
alive: () => {
|
|
3357
|
+
if (exited) return false;
|
|
3358
|
+
if (!child.pid) return false;
|
|
3359
|
+
try {
|
|
3360
|
+
process.kill(child.pid, 0);
|
|
3361
|
+
return true;
|
|
3362
|
+
} catch {
|
|
3363
|
+
return false;
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
};
|
|
3367
|
+
} finally {
|
|
3368
|
+
closeSync2(fd);
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
function tailFile(path, lines) {
|
|
3372
|
+
try {
|
|
3373
|
+
return tailText(readFileSync4(path, "utf8"), lines);
|
|
3374
|
+
} catch {
|
|
3375
|
+
return "";
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3290
3378
|
|
|
3291
3379
|
// src/procList.ts
|
|
3292
|
-
import { execFileSync as execFileSync2 } from "child_process";
|
|
3293
3380
|
function parsePsRows(out) {
|
|
3294
3381
|
const rows = [];
|
|
3295
3382
|
for (const line of out.split("\n")) {
|
|
@@ -3325,7 +3412,7 @@ function parseWinProcRows(out) {
|
|
|
3325
3412
|
}
|
|
3326
3413
|
var WIN_PS_COMMAND = "Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,CommandLine | ConvertTo-Json -Depth 2 -Compress";
|
|
3327
3414
|
function realExec(file, args) {
|
|
3328
|
-
return
|
|
3415
|
+
return execQuiet(file, args, { maxBuffer: PROC_SNAPSHOT_MAX_BUFFER });
|
|
3329
3416
|
}
|
|
3330
3417
|
function listProcs(opts = {}) {
|
|
3331
3418
|
const platform = opts.platform ?? process.platform;
|
|
@@ -3393,7 +3480,7 @@ function pidsWithCwdUnder(dir, opts = {}) {
|
|
|
3393
3480
|
if ((opts.platform ?? process.platform) === "win32") return winProcsUnder(dir, opts.procs ?? listProcs);
|
|
3394
3481
|
let out;
|
|
3395
3482
|
try {
|
|
3396
|
-
out =
|
|
3483
|
+
out = execQuiet("lsof", ["-w", "-a", "-d", "cwd", "-F", "pn"], { maxBuffer: PROC_SNAPSHOT_MAX_BUFFER });
|
|
3397
3484
|
} catch (e) {
|
|
3398
3485
|
logTransientSpawnError("lsof", e);
|
|
3399
3486
|
return [];
|
|
@@ -3476,7 +3563,7 @@ function containerBelongsToPrefix(name, prefix) {
|
|
|
3476
3563
|
}
|
|
3477
3564
|
function dockerContainerNames() {
|
|
3478
3565
|
try {
|
|
3479
|
-
return
|
|
3566
|
+
return execQuiet("docker", ["ps", "-a", "--format", "{{.Names}}"]).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
3480
3567
|
} catch (e) {
|
|
3481
3568
|
logTransientSpawnError("docker ps", e);
|
|
3482
3569
|
return [];
|
|
@@ -3486,7 +3573,7 @@ function removeContainers(names) {
|
|
|
3486
3573
|
const removed = [];
|
|
3487
3574
|
for (const name of names) {
|
|
3488
3575
|
try {
|
|
3489
|
-
|
|
3576
|
+
execQuiet("docker", ["rm", "-f", name]);
|
|
3490
3577
|
removed.push(name);
|
|
3491
3578
|
} catch (e) {
|
|
3492
3579
|
console.warn(`[procCleanup] docker rm -f ${name} \u0441\u043E\u0440\u0432\u0430\u043B\u0441\u044F: ${String(e)}`);
|
|
@@ -3546,7 +3633,7 @@ async function buildRepoRegistry(paths) {
|
|
|
3546
3633
|
|
|
3547
3634
|
// src/hostIdentity.ts
|
|
3548
3635
|
import { hostname } from "os";
|
|
3549
|
-
import { existsSync as existsSync4, readFileSync as
|
|
3636
|
+
import { existsSync as existsSync4, readFileSync as readFileSync5, renameSync as renameSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
3550
3637
|
import { join as join3 } from "path";
|
|
3551
3638
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
3552
3639
|
function hostIdentityPath(home) {
|
|
@@ -3554,10 +3641,10 @@ function hostIdentityPath(home) {
|
|
|
3554
3641
|
}
|
|
3555
3642
|
function loadHostIdentity(deps) {
|
|
3556
3643
|
const exists = deps.exists ?? existsSync4;
|
|
3557
|
-
const readFile2 = deps.readFile ?? ((p) =>
|
|
3644
|
+
const readFile2 = deps.readFile ?? ((p) => readFileSync5(p, "utf8"));
|
|
3558
3645
|
const writeFile2 = deps.writeFile ?? ((p, data) => {
|
|
3559
|
-
|
|
3560
|
-
|
|
3646
|
+
writeFileSync4(`${p}.tmp`, data);
|
|
3647
|
+
renameSync3(`${p}.tmp`, p);
|
|
3561
3648
|
});
|
|
3562
3649
|
const host = deps.hostname ?? hostname;
|
|
3563
3650
|
const newId = deps.newId ?? randomUUID2;
|
|
@@ -3665,7 +3752,7 @@ import { basename as basename2 } from "path";
|
|
|
3665
3752
|
import { serve as serve2 } from "@hono/node-server";
|
|
3666
3753
|
|
|
3667
3754
|
// src/diff.ts
|
|
3668
|
-
import { statSync as
|
|
3755
|
+
import { statSync as statSync3 } from "fs";
|
|
3669
3756
|
import { join as join4 } from "path";
|
|
3670
3757
|
import { $ as $2 } from "execa";
|
|
3671
3758
|
var MAX_FILES = 200;
|
|
@@ -3809,7 +3896,7 @@ async function resolveBase(wt, baseBranch) {
|
|
|
3809
3896
|
}
|
|
3810
3897
|
function mtime(path) {
|
|
3811
3898
|
try {
|
|
3812
|
-
return
|
|
3899
|
+
return statSync3(path).mtimeMs;
|
|
3813
3900
|
} catch {
|
|
3814
3901
|
return 0;
|
|
3815
3902
|
}
|
|
@@ -3853,7 +3940,7 @@ async function collectRunDiff(worktree, opts = {}) {
|
|
|
3853
3940
|
// package.json
|
|
3854
3941
|
var package_default = {
|
|
3855
3942
|
name: "@taskless-app/swarm",
|
|
3856
|
-
version: "0.4.
|
|
3943
|
+
version: "0.4.4",
|
|
3857
3944
|
type: "module",
|
|
3858
3945
|
description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
3859
3946
|
keywords: [
|
|
@@ -3956,18 +4043,18 @@ async function ghChecks(pr, run = realChecksRunner) {
|
|
|
3956
4043
|
|
|
3957
4044
|
// src/droneChannel.ts
|
|
3958
4045
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
3959
|
-
import { chmodSync, mkdirSync as mkdirSync3, readFileSync as
|
|
4046
|
+
import { chmodSync, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
3960
4047
|
import { dirname as dirname2 } from "path";
|
|
3961
4048
|
import { serve } from "@hono/node-server";
|
|
3962
4049
|
function loadChannelSecret(path) {
|
|
3963
4050
|
try {
|
|
3964
|
-
const s =
|
|
4051
|
+
const s = readFileSync6(path, "utf8").trim();
|
|
3965
4052
|
if (s.length >= 32) return s;
|
|
3966
4053
|
} catch {
|
|
3967
4054
|
}
|
|
3968
4055
|
const secret = randomBytes(32).toString("hex");
|
|
3969
4056
|
mkdirSync3(dirname2(path), { recursive: true });
|
|
3970
|
-
|
|
4057
|
+
writeFileSync5(path, secret, { mode: 384 });
|
|
3971
4058
|
try {
|
|
3972
4059
|
chmodSync(path, 384);
|
|
3973
4060
|
} catch {
|
|
@@ -4001,7 +4088,7 @@ var EVENT_KIND_SET = new Set(EVENT_KINDS);
|
|
|
4001
4088
|
|
|
4002
4089
|
// src/oauth.ts
|
|
4003
4090
|
import { createHash, randomBytes as randomBytes2 } from "crypto";
|
|
4004
|
-
import { readFileSync as
|
|
4091
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, unlinkSync } from "fs";
|
|
4005
4092
|
import { join as join5 } from "path";
|
|
4006
4093
|
var REGISTER = "/api/oauth/register";
|
|
4007
4094
|
var AUTHORIZE = "/api/oauth/authorize";
|
|
@@ -4093,13 +4180,13 @@ function toStore(clientId, t, now) {
|
|
|
4093
4180
|
}
|
|
4094
4181
|
function loadStore() {
|
|
4095
4182
|
try {
|
|
4096
|
-
return JSON.parse(
|
|
4183
|
+
return JSON.parse(readFileSync7(STORE_PATH, "utf8"));
|
|
4097
4184
|
} catch {
|
|
4098
4185
|
return null;
|
|
4099
4186
|
}
|
|
4100
4187
|
}
|
|
4101
4188
|
function saveStore(s) {
|
|
4102
|
-
|
|
4189
|
+
writeFileSync6(STORE_PATH, JSON.stringify(s, null, 2), { mode: 384 });
|
|
4103
4190
|
}
|
|
4104
4191
|
function clearStore() {
|
|
4105
4192
|
try {
|
|
@@ -4109,7 +4196,7 @@ function clearStore() {
|
|
|
4109
4196
|
}
|
|
4110
4197
|
function loadClientId() {
|
|
4111
4198
|
try {
|
|
4112
|
-
return JSON.parse(
|
|
4199
|
+
return JSON.parse(readFileSync7(CLIENT_PATH, "utf8")).clientId;
|
|
4113
4200
|
} catch {
|
|
4114
4201
|
return null;
|
|
4115
4202
|
}
|
|
@@ -4118,7 +4205,7 @@ async function ensureClientId(api, redirectUri, fetchFn = fetch) {
|
|
|
4118
4205
|
const existing = loadClientId();
|
|
4119
4206
|
if (existing) return existing;
|
|
4120
4207
|
const clientId = await registerClient({ api, redirectUri }, fetchFn);
|
|
4121
|
-
|
|
4208
|
+
writeFileSync6(CLIENT_PATH, JSON.stringify({ clientId }, null, 2), { mode: 384 });
|
|
4122
4209
|
return clientId;
|
|
4123
4210
|
}
|
|
4124
4211
|
async function ensureAccess(store, opts = {}) {
|
|
@@ -5697,8 +5784,8 @@ function startWeb(deps, port = WEB_PORT) {
|
|
|
5697
5784
|
import { cancelRun, respawnRun, runDaemon, wakeRun, OVERMIND_ENTRY, listDroneProcesses } from "./overmind.js";
|
|
5698
5785
|
|
|
5699
5786
|
// src/launcher.ts
|
|
5700
|
-
import { spawn } from "child_process";
|
|
5701
|
-
import { closeSync as
|
|
5787
|
+
import { spawn as spawn2 } from "child_process";
|
|
5788
|
+
import { closeSync as closeSync3, existsSync as existsSync6, mkdirSync as mkdirSync5, openSync as openSync3, readdirSync as readdirSync4, statSync as statSync5, writeFileSync as writeFileSync7 } from "fs";
|
|
5702
5789
|
import { createRequire as createRequire2 } from "module";
|
|
5703
5790
|
import { homedir as homedir2 } from "os";
|
|
5704
5791
|
import { dirname as dirname3, join as join7 } from "path";
|
|
@@ -5777,7 +5864,7 @@ function resolveClaudeBin(opts = {}) {
|
|
|
5777
5864
|
}
|
|
5778
5865
|
|
|
5779
5866
|
// src/droneHome.ts
|
|
5780
|
-
import { lstatSync, mkdirSync as mkdirSync4, readdirSync as readdirSync3, rmSync, statSync as
|
|
5867
|
+
import { lstatSync, mkdirSync as mkdirSync4, readdirSync as readdirSync3, rmSync, statSync as statSync4, symlinkSync } from "fs";
|
|
5781
5868
|
import { join as join6, relative, sep } from "path";
|
|
5782
5869
|
var DRONE_HOME_DENY_DEFAULT = [".taskless-swarm", ".bash_history", ".zsh_history"];
|
|
5783
5870
|
function droneHomeDeny(env = process.env) {
|
|
@@ -5818,7 +5905,7 @@ function buildDroneHome(opts) {
|
|
|
5818
5905
|
const target = join6(realHome, name);
|
|
5819
5906
|
let isDir;
|
|
5820
5907
|
try {
|
|
5821
|
-
isDir =
|
|
5908
|
+
isDir = statSync4(target).isDirectory();
|
|
5822
5909
|
} catch {
|
|
5823
5910
|
continue;
|
|
5824
5911
|
}
|
|
@@ -5984,14 +6071,14 @@ function openNextRunLog(runLogsDir, runId) {
|
|
|
5984
6071
|
const path = nextRunLogPath(runLogsDir, runId);
|
|
5985
6072
|
let out;
|
|
5986
6073
|
try {
|
|
5987
|
-
out =
|
|
6074
|
+
out = openSync3(path, "wx");
|
|
5988
6075
|
} catch (e) {
|
|
5989
6076
|
if (e.code !== "EEXIST") throw e;
|
|
5990
6077
|
continue;
|
|
5991
6078
|
}
|
|
5992
6079
|
let err = null;
|
|
5993
6080
|
try {
|
|
5994
|
-
err =
|
|
6081
|
+
err = openSync3(`${path.slice(0, -".json".length)}.err.log`, "w");
|
|
5995
6082
|
} catch {
|
|
5996
6083
|
err = null;
|
|
5997
6084
|
}
|
|
@@ -6052,7 +6139,7 @@ function makeLauncher(cfg) {
|
|
|
6052
6139
|
}
|
|
6053
6140
|
};
|
|
6054
6141
|
const cfgPath = join7(worktree, ".swarm-mcp.json");
|
|
6055
|
-
|
|
6142
|
+
writeFileSync7(cfgPath, JSON.stringify(mcpConfig, null, 2));
|
|
6056
6143
|
const model = run.model ?? process.env.SWARM_DRONE_MODEL ?? void 0;
|
|
6057
6144
|
const pluginDirs = roleDirs(worktree, run.kind);
|
|
6058
6145
|
const realHome = cfg.droneIsolation?.realHome ?? homedir2();
|
|
@@ -6072,7 +6159,7 @@ function makeLauncher(cfg) {
|
|
|
6072
6159
|
errFd = fds.err ?? void 0;
|
|
6073
6160
|
stdio = ["ignore", outFd, errFd ?? "ignore"];
|
|
6074
6161
|
}
|
|
6075
|
-
const child =
|
|
6162
|
+
const child = spawn2(cfg.claudeBin ?? resolveClaudeBin(), claudeArgs(cfgPath, prompt, continueSession, model, pluginDirs, settings), {
|
|
6076
6163
|
cwd: worktree,
|
|
6077
6164
|
detached: true,
|
|
6078
6165
|
stdio,
|
|
@@ -6082,8 +6169,8 @@ function makeLauncher(cfg) {
|
|
|
6082
6169
|
// Остальной env демона наследуется, как раньше.
|
|
6083
6170
|
env: droneEnv(worktree, process.env, home ? { droneHome: home, realHome } : void 0, cfg.droneCap?.() ?? null)
|
|
6084
6171
|
});
|
|
6085
|
-
if (outFd !== void 0)
|
|
6086
|
-
if (errFd !== void 0)
|
|
6172
|
+
if (outFd !== void 0) closeSync3(outFd);
|
|
6173
|
+
if (errFd !== void 0) closeSync3(errFd);
|
|
6087
6174
|
child.unref();
|
|
6088
6175
|
if (child.pid == null) throw new Error("\u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u0434\u0440\u043E\u043D\u0430 (\u043D\u0435\u0442 pid)");
|
|
6089
6176
|
return child.pid;
|
|
@@ -6091,13 +6178,13 @@ function makeLauncher(cfg) {
|
|
|
6091
6178
|
}
|
|
6092
6179
|
|
|
6093
6180
|
// src/git.ts
|
|
6094
|
-
import { existsSync as existsSync7, readdirSync as readdirSync5, statSync as
|
|
6181
|
+
import { existsSync as existsSync7, readdirSync as readdirSync5, statSync as statSync6 } from "fs";
|
|
6095
6182
|
import { appendFile, mkdir, readFile, rm } from "fs/promises";
|
|
6096
6183
|
import { isAbsolute, join as join8 } from "path";
|
|
6097
6184
|
import { $ as $4 } from "execa";
|
|
6098
6185
|
function isLinkedWorktree(dir) {
|
|
6099
6186
|
try {
|
|
6100
|
-
return
|
|
6187
|
+
return statSync6(join8(dir, ".git")).isFile();
|
|
6101
6188
|
} catch {
|
|
6102
6189
|
return false;
|
|
6103
6190
|
}
|
|
@@ -6137,20 +6224,20 @@ async function removeWorktree(repo, path) {
|
|
|
6137
6224
|
}
|
|
6138
6225
|
|
|
6139
6226
|
// src/agentToken.ts
|
|
6140
|
-
import { readFileSync as
|
|
6227
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync8, unlinkSync as unlinkSync2 } from "fs";
|
|
6141
6228
|
import { join as join9 } from "path";
|
|
6142
6229
|
var STORE_PATH2 = join9(SWARM_HOME, "agent.json");
|
|
6143
6230
|
var base2 = (api) => api.replace(/\/$/, "");
|
|
6144
6231
|
function loadAgentToken() {
|
|
6145
6232
|
try {
|
|
6146
|
-
const s = JSON.parse(
|
|
6233
|
+
const s = JSON.parse(readFileSync8(STORE_PATH2, "utf8"));
|
|
6147
6234
|
return s.token ? s : null;
|
|
6148
6235
|
} catch {
|
|
6149
6236
|
return null;
|
|
6150
6237
|
}
|
|
6151
6238
|
}
|
|
6152
6239
|
function saveAgentToken(s) {
|
|
6153
|
-
|
|
6240
|
+
writeFileSync8(STORE_PATH2, JSON.stringify(s, null, 2), { mode: 384 });
|
|
6154
6241
|
}
|
|
6155
6242
|
function clearAgentToken() {
|
|
6156
6243
|
try {
|
|
@@ -6202,19 +6289,19 @@ import { basename as basename3, isAbsolute as isAbsolute2, join as join11 } from
|
|
|
6202
6289
|
var SHOT_MAX_FILE_BYTES = 10 * 1024 * 1024;
|
|
6203
6290
|
|
|
6204
6291
|
// src/workspace.ts
|
|
6205
|
-
import { readFileSync as
|
|
6292
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync9, unlinkSync as unlinkSync3 } from "fs";
|
|
6206
6293
|
import { join as join12 } from "path";
|
|
6207
6294
|
var WORKSPACE_PATH = join12(SWARM_HOME, "workspace.json");
|
|
6208
6295
|
function loadWorkspace() {
|
|
6209
6296
|
try {
|
|
6210
|
-
const w = JSON.parse(
|
|
6297
|
+
const w = JSON.parse(readFileSync9(WORKSPACE_PATH, "utf8"));
|
|
6211
6298
|
return w && typeof w.id === "string" && w.id ? w : null;
|
|
6212
6299
|
} catch {
|
|
6213
6300
|
return null;
|
|
6214
6301
|
}
|
|
6215
6302
|
}
|
|
6216
6303
|
function saveWorkspace(w) {
|
|
6217
|
-
|
|
6304
|
+
writeFileSync9(WORKSPACE_PATH, JSON.stringify(w, null, 2), { mode: 384 });
|
|
6218
6305
|
}
|
|
6219
6306
|
function clearWorkspace() {
|
|
6220
6307
|
try {
|
|
@@ -6695,7 +6782,7 @@ async function daemonStatus2() {
|
|
|
6695
6782
|
var NO_DAEMON_NOTE = `\u0434\u0435\u043C\u043E\u043D \u043D\u0435 \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442 (\u043C\u043E\u0440\u0434\u0430 127.0.0.1:${WEB_PORT}) \u2014 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u044E \u041B\u041E\u041A\u0410\u041B\u042C\u041D\u042B\u0419 \u0441\u0442\u043E\u0440 \u044D\u0442\u043E\u0439 \u043C\u0430\u0448\u0438\u043D\u044B, \u043E\u043D \u043C\u043E\u0436\u0435\u0442 \u0440\u0430\u0441\u0445\u043E\u0434\u0438\u0442\u044C\u0441\u044F \u0441 \u0434\u0430\u0448\u0431\u043E\u0440\u0434\u043E\u043C. \u041F\u043E\u0434\u043D\u0438\u043C\u0438 \u0434\u0435\u043C\u043E\u043D\u0430: swarm start`;
|
|
6696
6783
|
|
|
6697
6784
|
// src/pauseState.ts
|
|
6698
|
-
import { existsSync as existsSync8, readFileSync as
|
|
6785
|
+
import { existsSync as existsSync8, readFileSync as readFileSync10, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
|
|
6699
6786
|
import { join as join13 } from "path";
|
|
6700
6787
|
function pauseStatePath(home) {
|
|
6701
6788
|
return join13(home, "pause.json");
|
|
@@ -6703,7 +6790,7 @@ function pauseStatePath(home) {
|
|
|
6703
6790
|
var ACTIVE = { paused: false, at: "", source: "cli" };
|
|
6704
6791
|
function loadPauseState(home, io = {}) {
|
|
6705
6792
|
const exists = io.exists ?? existsSync8;
|
|
6706
|
-
const readFile2 = io.readFile ?? ((p) =>
|
|
6793
|
+
const readFile2 = io.readFile ?? ((p) => readFileSync10(p, "utf8"));
|
|
6707
6794
|
const path = pauseStatePath(home);
|
|
6708
6795
|
if (!exists(path)) return ACTIVE;
|
|
6709
6796
|
try {
|
|
@@ -6727,8 +6814,8 @@ function savePauseState(home, state, io = {}) {
|
|
|
6727
6814
|
return;
|
|
6728
6815
|
}
|
|
6729
6816
|
const writeFile2 = io.writeFile ?? ((p, data) => {
|
|
6730
|
-
|
|
6731
|
-
|
|
6817
|
+
writeFileSync10(`${p}.tmp`, data);
|
|
6818
|
+
renameSync4(`${p}.tmp`, p);
|
|
6732
6819
|
});
|
|
6733
6820
|
writeFile2(path, JSON.stringify(state, null, 2));
|
|
6734
6821
|
}
|
|
@@ -6757,10 +6844,10 @@ function sinceText(at, now) {
|
|
|
6757
6844
|
}
|
|
6758
6845
|
|
|
6759
6846
|
// src/heartbeat.ts
|
|
6760
|
-
import { readFileSync as
|
|
6847
|
+
import { readFileSync as readFileSync11, renameSync as renameSync5, writeFileSync as writeFileSync11 } from "fs";
|
|
6761
6848
|
function readHeartbeat(path) {
|
|
6762
6849
|
try {
|
|
6763
|
-
const ms = Number(
|
|
6850
|
+
const ms = Number(readFileSync11(path, "utf8").trim());
|
|
6764
6851
|
return Number.isFinite(ms) ? ms : null;
|
|
6765
6852
|
} catch {
|
|
6766
6853
|
return null;
|
|
@@ -6948,6 +7035,98 @@ async function waitDaemonDown(opts) {
|
|
|
6948
7035
|
await sleep2(pollMs);
|
|
6949
7036
|
}
|
|
6950
7037
|
}
|
|
7038
|
+
var MAX_DAEMON_LOG_BYTES = 16 * 1024 * 1024;
|
|
7039
|
+
var START_READY_TIMEOUT_MS = 45e3;
|
|
7040
|
+
async function runStartDetached(args) {
|
|
7041
|
+
const already = await daemonStatus2();
|
|
7042
|
+
if (already) {
|
|
7043
|
+
console.log(`\u0434\u0435\u043C\u043E\u043D \u0443\u0436\u0435 \u043F\u043E\u0434\u043D\u044F\u0442 (v${already.version})${already.hostName ? `, \u043C\u0430\u0448\u0438\u043D\u0430 \xAB${already.hostName}\xBB` : ""} \u2014 \u0432\u0442\u043E\u0440\u043E\u0433\u043E \u043D\u0435 \u043D\u0443\u0436\u043D\u043E.`);
|
|
7044
|
+
console.log("\u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435: swarm status \xB7 \u043B\u043E\u0433: swarm logs -f \xB7 \u043F\u043E\u0433\u0430\u0441\u0438\u0442\u044C: swarm stop");
|
|
7045
|
+
return 0;
|
|
7046
|
+
}
|
|
7047
|
+
const rotated = rotateDaemonLog(DAEMON_LOG_PATH, MAX_DAEMON_LOG_BYTES);
|
|
7048
|
+
const entry = process.argv[1];
|
|
7049
|
+
if (!entry) {
|
|
7050
|
+
console.error("\u043D\u0435\u0447\u0435\u043C \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u0441\u0435\u0431\u044F \u0444\u043E\u043D\u043E\u043C (\u043F\u0443\u0441\u0442\u043E\u0439 argv[1]) \u2014 \u043F\u043E\u0434\u043D\u0438\u043C\u0438 \u0432 \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B\u0435: swarm start --foreground");
|
|
7051
|
+
return 1;
|
|
7052
|
+
}
|
|
7053
|
+
let launch;
|
|
7054
|
+
try {
|
|
7055
|
+
launch = launchDetached({
|
|
7056
|
+
execPath: process.execPath,
|
|
7057
|
+
// execArgv тащим за собой намеренно: в монорепе CLI запускают через tsx-loader, и
|
|
7058
|
+
// без него ребёнок не прочитает .ts-исходник, с которого сам же и стартовал.
|
|
7059
|
+
execArgv: process.execArgv,
|
|
7060
|
+
entry,
|
|
7061
|
+
args: childStartArgv(args),
|
|
7062
|
+
logPath: DAEMON_LOG_PATH,
|
|
7063
|
+
env: process.env
|
|
7064
|
+
});
|
|
7065
|
+
} catch (e) {
|
|
7066
|
+
console.error(`\u043D\u0435 \u0441\u043C\u043E\u0433 \u043E\u0442\u0434\u0435\u043B\u0438\u0442\u044C \u0434\u0435\u043C\u043E\u043D\u0430 \u043E\u0442 \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B\u0430: ${e instanceof Error ? e.message : e}`);
|
|
7067
|
+
console.error("\u043F\u043E\u0434\u043D\u0438\u043C\u0438 \u0432 \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B\u0435: swarm start --foreground");
|
|
7068
|
+
return 1;
|
|
7069
|
+
}
|
|
7070
|
+
console.log(`\u043F\u043E\u0434\u043D\u0438\u043C\u0430\u044E \u0440\u043E\u0439 \u0444\u043E\u043D\u043E\u043C (pid ${launch.pid}), \u043B\u043E\u0433: ${DAEMON_LOG_PATH}${rotated === "rotated" ? " (\u043F\u0440\u043E\u0448\u043B\u044B\u0439 \u0443\u0435\u0445\u0430\u043B \u0432 .1)" : ""}`);
|
|
7071
|
+
const verdict = await waitForReady({
|
|
7072
|
+
probe: async () => await daemonStatus2() != null,
|
|
7073
|
+
alive: launch.alive,
|
|
7074
|
+
timeoutMs: START_READY_TIMEOUT_MS,
|
|
7075
|
+
pollMs: 500
|
|
7076
|
+
});
|
|
7077
|
+
if (verdict === "ready") {
|
|
7078
|
+
console.log("\u0440\u043E\u0439 \u043F\u043E\u0434\u043D\u044F\u0442, \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B \u0441\u0432\u043E\u0431\u043E\u0434\u0435\u043D. \u0421\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435: swarm status \xB7 \u043B\u043E\u0433: swarm logs -f \xB7 \u043F\u043E\u0433\u0430\u0441\u0438\u0442\u044C: swarm stop");
|
|
7079
|
+
return 0;
|
|
7080
|
+
}
|
|
7081
|
+
console.error(
|
|
7082
|
+
verdict === "died" ? "\u0434\u0435\u043C\u043E\u043D \u041D\u0415 \u043F\u043E\u0434\u043D\u044F\u043B\u0441\u044F \u2014 \u043F\u0440\u043E\u0446\u0435\u0441\u0441 \u0432\u044B\u0448\u0435\u043B \u0441\u0440\u0430\u0437\u0443. \u041F\u0440\u0438\u0447\u0438\u043D\u0430 \u0432 \u0445\u0432\u043E\u0441\u0442\u0435 \u043B\u043E\u0433\u0430:" : `\u0434\u0435\u043C\u043E\u043D \u043D\u0435 \u043E\u0442\u043E\u0437\u0432\u0430\u043B\u0441\u044F \u0437\u0430 ${Math.round(START_READY_TIMEOUT_MS / 1e3)}\u0441 (\u043F\u0440\u043E\u0446\u0435\u0441\u0441 \u0435\u0449\u0451 \u0436\u0438\u0432, pid ${launch.pid}). \u0425\u0432\u043E\u0441\u0442 \u043B\u043E\u0433\u0430:`
|
|
7083
|
+
);
|
|
7084
|
+
console.error(tailFile(DAEMON_LOG_PATH, 20) || `(\u043B\u043E\u0433 \u043F\u0443\u0441\u0442: ${DAEMON_LOG_PATH})`);
|
|
7085
|
+
return 1;
|
|
7086
|
+
}
|
|
7087
|
+
async function runDaemonLogs(argv) {
|
|
7088
|
+
const follow = argv.includes("-f") || argv.includes("--follow");
|
|
7089
|
+
const nAt = argv.findIndex((a) => a === "-n" || a === "--lines");
|
|
7090
|
+
const lines = nAt >= 0 ? Number(argv[nAt + 1]) : 200;
|
|
7091
|
+
if (!Number.isFinite(lines) || lines <= 0) {
|
|
7092
|
+
console.error("\u043D\u0443\u0436\u043D\u043E \u0447\u0438\u0441\u043B\u043E \u0441\u0442\u0440\u043E\u043A: swarm logs -n 200");
|
|
7093
|
+
return 1;
|
|
7094
|
+
}
|
|
7095
|
+
const stray = argv.find((a, i) => /^\d+$/.test(a) && i !== nAt + 1);
|
|
7096
|
+
if (stray) {
|
|
7097
|
+
console.error(`\u043B\u043E\u0433 \u041F\u0420\u041E\u0413\u041E\u041D\u0410 \u2014 \u044D\u0442\u043E \xABswarm log ${stray}\xBB (\u0431\u0435\u0437 s). \xABswarm logs\xBB \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442 \u043B\u043E\u0433 \u0434\u0435\u043C\u043E\u043D\u0430; \u0447\u0438\u0441\u043B\u043E \u0441\u0442\u0440\u043E\u043A \u2014 \xABswarm logs -n 200\xBB.`);
|
|
7098
|
+
return 1;
|
|
7099
|
+
}
|
|
7100
|
+
if (!existsSync9(DAEMON_LOG_PATH)) {
|
|
7101
|
+
console.error(`\u043B\u043E\u0433\u0430 \u0434\u0435\u043C\u043E\u043D\u0430 \u043D\u0435\u0442: ${DAEMON_LOG_PATH}`);
|
|
7102
|
+
console.error("\u043E\u043D \u043F\u0438\u0448\u0435\u0442\u0441\u044F \u043F\u0440\u0438 \u0444\u043E\u043D\u043E\u0432\u043E\u043C \u0437\u0430\u043F\u0443\u0441\u043A\u0435 (swarm start). \u0414\u0435\u043C\u043E\u043D \u043F\u043E\u0434\u043D\u044F\u0442 \u0432 \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B\u0435 (--foreground) \u2014 \u0432\u044B\u0432\u043E\u0434 \u0438\u0434\u0451\u0442 \u0442\u0443\u0434\u0430.");
|
|
7103
|
+
return 1;
|
|
7104
|
+
}
|
|
7105
|
+
const head = tailFile(DAEMON_LOG_PATH, lines);
|
|
7106
|
+
if (head) console.log(head);
|
|
7107
|
+
if (!follow) return 0;
|
|
7108
|
+
let pos = statSync7(DAEMON_LOG_PATH).size;
|
|
7109
|
+
for (; ; ) {
|
|
7110
|
+
await sleep2(500);
|
|
7111
|
+
let size;
|
|
7112
|
+
try {
|
|
7113
|
+
size = statSync7(DAEMON_LOG_PATH).size;
|
|
7114
|
+
} catch {
|
|
7115
|
+
continue;
|
|
7116
|
+
}
|
|
7117
|
+
if (size < pos) pos = 0;
|
|
7118
|
+
if (size === pos) continue;
|
|
7119
|
+
const fd = openSync4(DAEMON_LOG_PATH, "r");
|
|
7120
|
+
try {
|
|
7121
|
+
const buf = Buffer.alloc(size - pos);
|
|
7122
|
+
const read = readSync2(fd, buf, 0, buf.length, pos);
|
|
7123
|
+
process.stdout.write(buf.subarray(0, read).toString("utf8"));
|
|
7124
|
+
pos += read;
|
|
7125
|
+
} finally {
|
|
7126
|
+
closeSync4(fd);
|
|
7127
|
+
}
|
|
7128
|
+
}
|
|
7129
|
+
}
|
|
6951
7130
|
async function runStop(argv) {
|
|
6952
7131
|
const force = argv.includes("--force");
|
|
6953
7132
|
const wait = argv.includes("--wait");
|
|
@@ -7092,33 +7271,62 @@ function printRuns(runs, view) {
|
|
|
7092
7271
|
}).forEach((l) => console.log(l));
|
|
7093
7272
|
}
|
|
7094
7273
|
function usage() {
|
|
7095
|
-
console.log(`swarm \u2014 \u0440\u043E\u0439
|
|
7274
|
+
console.log(`swarm \u2014 \u0440\u043E\u0439 AI-\u0434\u0440\u043E\u043D\u043E\u0432 (v${PACKAGE_VERSION2})
|
|
7096
7275
|
|
|
7097
|
-
|
|
7098
|
-
swarm
|
|
7276
|
+
\u041D\u0410\u0427\u0410\u0422\u042C
|
|
7277
|
+
swarm login [--workspace <slug|id>] [--no-open]
|
|
7278
|
+
\u0432\u043E\u0439\u0442\u0438 \u0432 Taskless \u0438 \u0432\u044B\u0431\u0440\u0430\u0442\u044C \u0432\u043E\u0440\u043A\u0441\u043F\u0435\u0439\u0441
|
|
7279
|
+
swarm start [--repo <path>] [--foreground]
|
|
7280
|
+
\u043F\u043E\u0434\u043D\u044F\u0442\u044C \u0440\u043E\u0439 \u043D\u0430 \u044D\u0442\u043E\u0439 \u043C\u0430\u0448\u0438\u043D\u0435: \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u0442 \u043E\u0447\u0435\u0440\u0435\u0434\u044C, \u0441\u043F\u0430\u0432\u043D\u0438\u0442 \u0438 \u0431\u0443\u0434\u0438\u0442 \u0434\u0440\u043E\u043D\u043E\u0432
|
|
7099
7281
|
swarm status \u0436\u0438\u0432 \u043B\u0438 \u0434\u0435\u043C\u043E\u043D, \u043D\u0430 \u043F\u0430\u0443\u0437\u0435 \u043B\u0438 \u0440\u043E\u0439, \u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0434\u0440\u043E\u043D\u043E\u0432 \u0432 \u0440\u0430\u0431\u043E\u0442\u0435
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
swarm
|
|
7103
|
-
\
|
|
7104
|
-
swarm
|
|
7105
|
-
swarm
|
|
7106
|
-
swarm
|
|
7107
|
-
|
|
7108
|
-
swarm spawn <slug> --hero [--name HYDRA] [--repo <path>] [--after <s1,s2>] [--priority <n>] \u0413\u0435\u0440\u043E\u0439-\u043B\u0435\u0439\u0442\u0435\u043D\u0430\u043D\u0442 \u044D\u043F\u0438\u043A\u0430
|
|
7109
|
-
swarm wake <runId> \u0440\u0430\u0437\u0431\u0443\u0434\u0438\u0442\u044C \u043F\u0440\u043E\u0433\u043E\u043D (id \u0438\u0437 swarm ls) \u2014 \u0447\u0435\u0440\u0435\u0437 \u0436\u0438\u0432\u043E\u0433\u043E \u0434\u0435\u043C\u043E\u043D\u0430; \u043D\u0435\u0447\u0435\u0433\u043E \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0442\u044C \u2192 \u0441\u0442\u0430\u0440\u0442 \u0441 \u043D\u0443\u043B\u044F
|
|
7282
|
+
|
|
7283
|
+
\u0414\u0410\u0422\u042C \u0420\u041E\u042E \u0420\u0410\u0411\u041E\u0422\u0423
|
|
7284
|
+
swarm spawn <slug> [area] [\u0444\u043B\u0430\u0433\u0438 \u043D\u0438\u0436\u0435]
|
|
7285
|
+
\u043F\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 \u043E\u0447\u0435\u0440\u0435\u0434\u044C
|
|
7286
|
+
swarm ls [\u0441\u0442\u0430\u0442\u0443\u0441] \u043F\u0440\u043E\u0433\u043E\u043D\u044B \u0436\u0438\u0432\u043E\u0433\u043E \u0434\u0435\u043C\u043E\u043D\u0430 \u2014 \u0440\u043E\u0432\u043D\u043E \u0442\u0435, \u0447\u0442\u043E \u0432 \u0434\u0430\u0448\u0431\u043E\u0440\u0434\u0435
|
|
7287
|
+
swarm wake <runId> \u0440\u0430\u0437\u0431\u0443\u0434\u0438\u0442\u044C \u043F\u0440\u043E\u0433\u043E\u043D (id \u0438\u0437 swarm ls); \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E \u2192 \u043D\u0430\u0447\u043D\u0451\u0442 \u0441 \u043D\u0443\u043B\u044F
|
|
7288
|
+
swarm cancel <slug> <\u043F\u0440\u0438\u0447\u0438\u043D\u0430\u2026>
|
|
7289
|
+
\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u0434\u0440\u043E\u043D\u0430: \u0441\u0442\u0430\u0442\u0443\u0441 \xAB\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\xBB \u0441 \u043F\u0440\u0438\u0447\u0438\u043D\u043E\u0439, \u0432 \u0438\u0441\u0442\u043E\u0440\u0438\u0438 \u043E\u0441\u0442\u0430\u043D\u0435\u0442\u0441\u044F
|
|
7110
7290
|
swarm questions \u043E\u0442\u043A\u0440\u044B\u0442\u044B\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B \u0434\u0440\u043E\u043D\u043E\u0432
|
|
7111
|
-
swarm answer <qid>
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
swarm
|
|
7291
|
+
swarm answer <qid> <\u0442\u0435\u043A\u0441\u0442\u2026>
|
|
7292
|
+
\u043E\u0442\u0432\u0435\u0442\u0438\u0442\u044C \u043D\u0430 \u0432\u043E\u043F\u0440\u043E\u0441 \u0438 \u0440\u0430\u0437\u0431\u0443\u0434\u0438\u0442\u044C \u0434\u0440\u043E\u043D\u0430
|
|
7293
|
+
|
|
7294
|
+
\u0423\u041F\u0420\u0410\u0412\u041B\u042F\u0422\u042C \u041C\u0410\u0428\u0418\u041D\u041E\u0419
|
|
7295
|
+
swarm pause [\u043F\u0440\u0438\u0447\u0438\u043D\u0430\u2026] \u043D\u0435 \u0431\u0440\u0430\u0442\u044C \u043D\u043E\u0432\u0443\u044E \u0440\u0430\u0431\u043E\u0442\u0443; \u0436\u0438\u0432\u044B\u0435 \u0434\u0440\u043E\u043D\u044B \u0434\u043E\u0440\u0430\u0431\u043E\u0442\u0430\u044E\u0442. \u041F\u0435\u0440\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0435\u0441\u0442\u0430\u0440\u0442
|
|
7296
|
+
swarm resume \u0441\u043D\u043E\u0432\u0430 \u0431\u0440\u0430\u0442\u044C \u0440\u0430\u0431\u043E\u0442\u0443
|
|
7297
|
+
swarm stop [--wait|--force]
|
|
7298
|
+
\u043F\u043E\u0433\u0430\u0441\u0438\u0442\u044C \u0434\u0435\u043C\u043E\u043D\u0430 \u043D\u0430 \u044D\u0442\u043E\u0439 \u043C\u0430\u0448\u0438\u043D\u0435
|
|
7299
|
+
swarm remove [--yes] [--wait|--force]
|
|
7300
|
+
\u043E\u0442\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u043C\u0430\u0448\u0438\u043D\u0443 \u043E\u0442 \u0440\u043E\u044F: \u043F\u043E\u0433\u0430\u0441\u0438\u0442\u044C, \u0443\u0431\u0440\u0430\u0442\u044C \u0438\u0437 \u043F\u0430\u0440\u043A\u0430, \u0441\u0442\u0435\u0440\u0435\u0442\u044C \u0442\u043E\u043A\u0435\u043D\u044B
|
|
7301
|
+
swarm hosts \u043C\u0430\u0448\u0438\u043D\u044B \u0440\u043E\u044F: \u0438\u043C\u044F, \u043F\u0443\u043B\u044C\u0441, \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u0438, id (\u0438\u043C\u044F \u0433\u043E\u0434\u0438\u0442\u0441\u044F \u0434\u043B\u044F --host)
|
|
7302
|
+
|
|
7303
|
+
\u0421\u041C\u041E\u0422\u0420\u0415\u0422\u042C, \u0427\u0422\u041E \u041F\u0420\u041E\u0418\u0421\u0425\u041E\u0414\u0418\u0422
|
|
7304
|
+
swarm logs [-n 200] [-f] \u043B\u043E\u0433 \u0414\u0415\u041C\u041E\u041D\u0410 (~/.taskless-swarm/overmind.log)
|
|
7305
|
+
swarm log <runId> \u043B\u043E\u0433 \u043E\u0434\u043D\u043E\u0433\u043E \u041F\u0420\u041E\u0413\u041E\u041D\u0410 \u2014 \u043D\u0435 \u043F\u0443\u0442\u0430\u0442\u044C \u0441 \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0435\u0439
|
|
7306
|
+
swarm web \u0432\u0435\u0431-\u043C\u043E\u0440\u0434\u0430 \u0440\u043E\u044F \u043D\u0430 127.0.0.1:${WEB_PORT}
|
|
7307
|
+
|
|
7308
|
+
\u041F\u0420\u041E\u0427\u0415\u0415
|
|
7116
7309
|
swarm whoami \u043A\u0442\u043E \u0432\u043E\u0448\u0451\u043B \u0438 \u0432 \u043A\u0430\u043A\u043E\u043C \u0432\u043E\u0440\u043A\u0441\u043F\u0435\u0439\u0441\u0435
|
|
7117
|
-
swarm
|
|
7310
|
+
swarm logout \u0437\u0430\u0431\u044B\u0442\u044C \u0442\u043E\u043A\u0435\u043D\u044B \u0438 \u0432\u044B\u0431\u043E\u0440 \u0432\u043E\u0440\u043A\u0441\u043F\u0435\u0439\u0441\u0430
|
|
7118
7311
|
swarm shot <url> <out-prefix> [--timeout <ms>] [--storage-state <path>]
|
|
7119
|
-
headless-\u0441\u043A\u0440\u0438\u043D desktop+mobile \
|
|
7312
|
+
headless-\u0441\u043A\u0440\u0438\u043D\u044B desktop+mobile \u043E\u0434\u043D\u043E\u0439 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439:
|
|
7120
7313
|
<out-prefix>-desktop.png, <out-prefix>-mobile.png
|
|
7314
|
+
swarm import-db <path> --repo <path>
|
|
7315
|
+
\u0438\u043C\u043F\u043E\u0440\u0442 \u0438\u0441\u0442\u043E\u0440\u0438\u0438 \u043F\u0440\u043E\u0433\u043E\u043D\u043E\u0432 \u0438\u0437 \u0434\u0440\u0443\u0433\u043E\u0439 \u0411\u0414 (\u0438\u0434\u0435\u043C\u043F\u043E\u0442\u0435\u043D\u0442\u043D\u043E)
|
|
7121
7316
|
swarm --version \u0432\u0435\u0440\u0441\u0438\u044F \u043F\u0430\u043A\u0435\u0442\u0430
|
|
7317
|
+
|
|
7318
|
+
\u0424\u041B\u0410\u0413\u0418, \u041A\u041E\u0422\u041E\u0420\u042B\u0415 \u0421\u0422\u041E\u0418\u0422 \u0417\u041D\u0410\u0422\u042C
|
|
7319
|
+
start \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u0434\u0435\u043C\u043E\u043D \u041E\u0422\u041A\u0420\u0415\u041F\u041B\u042F\u0415\u0422\u0421\u042F: \u0443\u0445\u043E\u0434\u0438\u0442 \u0432 \u0444\u043E\u043D, \u043F\u0438\u0448\u0435\u0442 \u0432 ~/.taskless-swarm/overmind.log,
|
|
7320
|
+
\u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B \u0441\u0432\u043E\u0431\u043E\u0434\u0435\u043D. --foreground (\u043E\u043D \u0436\u0435 -f, --attach) \u0434\u0435\u0440\u0436\u0438\u0442 \u0435\u0433\u043E \u0432 \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B\u0435 \u2014
|
|
7321
|
+
\u0434\u043B\u044F \u043E\u0442\u043B\u0430\u0434\u043A\u0438 \u0438 \u0442\u0430\u043C, \u0433\u0434\u0435 \u0444\u043E\u043D\u043E\u043C \u0437\u0430\u043D\u0438\u043C\u0430\u0435\u0442\u0441\u044F \u0441\u0443\u043F\u0435\u0440\u0432\u0438\u0437\u043E\u0440 (systemd, docker)
|
|
7322
|
+
spawn --repo <path> \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u0439 \u043F\u0440\u043E\u0433\u043E\u043D\u0430, \u0435\u0441\u043B\u0438 \u043D\u0435 \u0434\u0435\u0444\u043E\u043B\u0442\u043D\u044B\u0439
|
|
7323
|
+
--after <s1,s2> \u0436\u0434\u0430\u0442\u044C, \u043F\u043E\u043A\u0430 \u043F\u0435\u0440\u0435\u0447\u0438\u0441\u043B\u0435\u043D\u043D\u044B\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043D\u0435 \u0431\u0443\u0434\u0443\u0442 done
|
|
7324
|
+
--priority <n> \u0432\u044B\u0448\u0435 \u0447\u0438\u0441\u043B\u043E \u2014 \u0440\u0430\u043D\u044C\u0448\u0435 \u0432\u043E\u0437\u044C\u043C\u0443\u0442 \u0438\u0437 \u043E\u0447\u0435\u0440\u0435\u0434\u0438
|
|
7325
|
+
--base <\u0432\u0435\u0442\u043A\u0430> PR \u043D\u0435 \u0432 \u0434\u0435\u0444\u043E\u043B\u0442\u043D\u0443\u044E \u0432\u0435\u0442\u043A\u0443, \u0430 \u0432 \u044D\u0442\u0443
|
|
7326
|
+
--host <\u043C\u0430\u0448\u0438\u043D\u0430|any> \u043D\u0430 \u043A\u0430\u043A\u043E\u0439 \u043C\u0430\u0448\u0438\u043D\u0435 \u0440\u0430\u0431\u043E\u0442\u0430\u0442\u044C; \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u044D\u0442\u0430, \xABany\xBB \u2014 \u043B\u044E\u0431\u0430\u044F \u0441\u0432\u043E\u0431\u043E\u0434\u043D\u0430\u044F
|
|
7327
|
+
--hero [--name HYDRA] \u0413\u0435\u0440\u043E\u0439-\u043B\u0435\u0439\u0442\u0435\u043D\u0430\u043D\u0442 \u044D\u043F\u0438\u043A\u0430 \u0432\u043C\u0435\u0441\u0442\u043E \u043E\u0431\u044B\u0447\u043D\u043E\u0433\u043E \u0434\u0440\u043E\u043D\u0430
|
|
7328
|
+
stop \u0431\u0435\u0437 \u0444\u043B\u0430\u0433\u043E\u0432 \u043F\u0440\u0438 \u0436\u0438\u0432\u044B\u0445 \u0434\u0440\u043E\u043D\u0430\u0445 \u041D\u0415 \u0433\u0430\u0441\u0438\u0442, \u0430 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442, \u043A\u0442\u043E \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442: \u0438\u0445 \u043D\u0435\u0437\u0430\u043F\u0443\u0448\u0435\u043D\u043D\u043E\u0435
|
|
7329
|
+
\u0443\u043C\u0440\u0451\u0442 \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 \u043D\u0438\u043C\u0438. --wait \u2014 \u0434\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F, \u043F\u043E\u043A\u0430 \u0434\u043E\u0440\u0430\u0431\u043E\u0442\u0430\u044E\u0442; --force \u2014 \u043E\u0431\u043E\u0440\u0432\u0430\u0442\u044C \u0441\u0435\u0439\u0447\u0430\u0441
|
|
7122
7330
|
`);
|
|
7123
7331
|
}
|
|
7124
7332
|
var effectiveWorktreesDirMemo;
|
|
@@ -7208,14 +7416,18 @@ if (cmd === "import-db") {
|
|
|
7208
7416
|
process.exit(0);
|
|
7209
7417
|
}
|
|
7210
7418
|
if (cmd === "start") {
|
|
7419
|
+
const { foreground, rest: startArgs } = parseStartMode(rawArgs);
|
|
7211
7420
|
if (SWARM_BACKEND !== "client") {
|
|
7212
7421
|
console.warn("SWARM_BACKEND=client \u043D\u0435 \u0437\u0430\u0434\u0430\u043D \u2014 \u0434\u0435\u043C\u043E\u043D \u043F\u043E\u0434\u043D\u0438\u043C\u0435\u0442\u0441\u044F \u0432 \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u043E\u043C sqlite-\u0440\u0435\u0436\u0438\u043C\u0435, \u0411\u0415\u0417 \u0441\u0432\u044F\u0437\u0438 \u0441 \u0432\u043E\u0440\u043A\u0441\u043F\u0435\u0439\u0441\u043E\u043C Taskless (\u043D\u0435 \u0443\u0432\u0438\u0434\u0438\u0442 \u0437\u0430\u0434\u0430\u0447\u0438, \u043D\u0435 \u043F\u043E\u0448\u043B\u0451\u0442 \u043F\u0443\u043B\u044C\u0441).");
|
|
7213
7422
|
}
|
|
7214
|
-
const { repo: repoFlag } = takeRepo(
|
|
7423
|
+
const { repo: repoFlag } = takeRepo(startArgs);
|
|
7215
7424
|
const repo = repoFlag ?? SWARM_REPO;
|
|
7216
7425
|
if (!repo) {
|
|
7217
7426
|
console.warn("SWARM_REPO \u043D\u0435 \u0437\u0430\u0434\u0430\u043D \u2014 \u043F\u0440\u043E\u0433\u043E\u043D\u044B \u0431\u0435\u0437 \u044F\u0432\u043D\u043E\u0433\u043E repo \u043D\u0435 \u0437\u0430\u043F\u0443\u0441\u0442\u044F\u0442\u0441\u044F (\u043D\u0443\u0436\u0435\u043D spawn --repo).");
|
|
7218
7427
|
}
|
|
7428
|
+
if (!foreground) {
|
|
7429
|
+
process.exit(await runStartDetached(startArgs));
|
|
7430
|
+
}
|
|
7219
7431
|
try {
|
|
7220
7432
|
await runDaemon({ repo });
|
|
7221
7433
|
} catch (e) {
|
|
@@ -7224,6 +7436,9 @@ if (cmd === "start") {
|
|
|
7224
7436
|
}
|
|
7225
7437
|
process.exit(0);
|
|
7226
7438
|
}
|
|
7439
|
+
if (cmd === "logs") {
|
|
7440
|
+
process.exit(await runDaemonLogs(rawArgs));
|
|
7441
|
+
}
|
|
7227
7442
|
if (cmd === "ls") {
|
|
7228
7443
|
const snap = await daemonRuns(rawArgs[0]);
|
|
7229
7444
|
if (snap) {
|
package/dist/overmind.js
CHANGED
|
@@ -1910,9 +1910,25 @@ CREATE TABLE IF NOT EXISTS imports (
|
|
|
1910
1910
|
}
|
|
1911
1911
|
});
|
|
1912
1912
|
|
|
1913
|
+
// src/quietExec.ts
|
|
1914
|
+
import { execFileSync } from "child_process";
|
|
1915
|
+
function execQuiet(file, args = [], opts = {}) {
|
|
1916
|
+
return execFileSync(file, args, {
|
|
1917
|
+
encoding: "utf8",
|
|
1918
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1919
|
+
...opts.maxBuffer ? { maxBuffer: opts.maxBuffer } : {}
|
|
1920
|
+
});
|
|
1921
|
+
}
|
|
1922
|
+
var PROC_SNAPSHOT_MAX_BUFFER;
|
|
1923
|
+
var init_quietExec = __esm({
|
|
1924
|
+
"src/quietExec.ts"() {
|
|
1925
|
+
"use strict";
|
|
1926
|
+
PROC_SNAPSHOT_MAX_BUFFER = 16 * 1024 * 1024;
|
|
1927
|
+
}
|
|
1928
|
+
});
|
|
1929
|
+
|
|
1913
1930
|
// src/resources.ts
|
|
1914
1931
|
import os from "os";
|
|
1915
|
-
import { execFileSync } from "child_process";
|
|
1916
1932
|
import { readFileSync as readFileSync3, statfsSync } from "fs";
|
|
1917
1933
|
function isTransientResourceError(e) {
|
|
1918
1934
|
const code = e?.code;
|
|
@@ -1943,7 +1959,7 @@ function parseVmStatAvailableBytes(vmStatOut) {
|
|
|
1943
1959
|
function availableMemBytes() {
|
|
1944
1960
|
if (process.platform === "darwin") {
|
|
1945
1961
|
try {
|
|
1946
|
-
const bytes = parseVmStatAvailableBytes(
|
|
1962
|
+
const bytes = parseVmStatAvailableBytes(execQuiet("vm_stat"));
|
|
1947
1963
|
if (bytes > 0) return bytes;
|
|
1948
1964
|
} catch (e) {
|
|
1949
1965
|
logTransientSpawnError("vm_stat", e);
|
|
@@ -1957,7 +1973,7 @@ function parseSysctlInt(out) {
|
|
|
1957
1973
|
}
|
|
1958
1974
|
function readSysctlPair(nameA, nameB) {
|
|
1959
1975
|
try {
|
|
1960
|
-
const lines =
|
|
1976
|
+
const lines = execQuiet("sysctl", ["-n", nameA, nameB]).trim().split("\n");
|
|
1961
1977
|
return [parseSysctlInt(lines[0] ?? ""), parseSysctlInt(lines[1] ?? "")];
|
|
1962
1978
|
} catch (e) {
|
|
1963
1979
|
logTransientSpawnError(`sysctl ${nameA}/${nameB}`, e);
|
|
@@ -2099,6 +2115,7 @@ var prevCpuTicks, RESOURCES_CACHE_MS, readingCache;
|
|
|
2099
2115
|
var init_resources = __esm({
|
|
2100
2116
|
"src/resources.ts"() {
|
|
2101
2117
|
"use strict";
|
|
2118
|
+
init_quietExec();
|
|
2102
2119
|
init_config();
|
|
2103
2120
|
prevCpuTicks = null;
|
|
2104
2121
|
RESOURCES_CACHE_MS = 250;
|
|
@@ -2133,7 +2150,6 @@ var init_heartbeat = __esm({
|
|
|
2133
2150
|
});
|
|
2134
2151
|
|
|
2135
2152
|
// src/procList.ts
|
|
2136
|
-
import { execFileSync as execFileSync2 } from "child_process";
|
|
2137
2153
|
function parsePsRows(out) {
|
|
2138
2154
|
const rows = [];
|
|
2139
2155
|
for (const line of out.split("\n")) {
|
|
@@ -2168,7 +2184,7 @@ function parseWinProcRows(out) {
|
|
|
2168
2184
|
return rows;
|
|
2169
2185
|
}
|
|
2170
2186
|
function realExec(file, args) {
|
|
2171
|
-
return
|
|
2187
|
+
return execQuiet(file, args, { maxBuffer: PROC_SNAPSHOT_MAX_BUFFER });
|
|
2172
2188
|
}
|
|
2173
2189
|
function listProcs(opts = {}) {
|
|
2174
2190
|
const platform = opts.platform ?? process.platform;
|
|
@@ -2226,13 +2242,13 @@ var WIN_PS_COMMAND;
|
|
|
2226
2242
|
var init_procList = __esm({
|
|
2227
2243
|
"src/procList.ts"() {
|
|
2228
2244
|
"use strict";
|
|
2245
|
+
init_quietExec();
|
|
2229
2246
|
init_resources();
|
|
2230
2247
|
WIN_PS_COMMAND = "Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,CommandLine | ConvertTo-Json -Depth 2 -Compress";
|
|
2231
2248
|
}
|
|
2232
2249
|
});
|
|
2233
2250
|
|
|
2234
2251
|
// src/procCleanup.ts
|
|
2235
|
-
import { execFileSync as execFileSync3 } from "child_process";
|
|
2236
2252
|
function sleep(ms) {
|
|
2237
2253
|
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
2238
2254
|
}
|
|
@@ -2262,7 +2278,7 @@ function pidsWithCwdUnder(dir, opts = {}) {
|
|
|
2262
2278
|
if ((opts.platform ?? process.platform) === "win32") return winProcsUnder(dir, opts.procs ?? listProcs);
|
|
2263
2279
|
let out;
|
|
2264
2280
|
try {
|
|
2265
|
-
out =
|
|
2281
|
+
out = execQuiet("lsof", ["-w", "-a", "-d", "cwd", "-F", "pn"], { maxBuffer: PROC_SNAPSHOT_MAX_BUFFER });
|
|
2266
2282
|
} catch (e) {
|
|
2267
2283
|
logTransientSpawnError("lsof", e);
|
|
2268
2284
|
return [];
|
|
@@ -2373,7 +2389,7 @@ function findOrphanContainers(containerNames, runs) {
|
|
|
2373
2389
|
}
|
|
2374
2390
|
function dockerContainerNames() {
|
|
2375
2391
|
try {
|
|
2376
|
-
return
|
|
2392
|
+
return execQuiet("docker", ["ps", "-a", "--format", "{{.Names}}"]).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
2377
2393
|
} catch (e) {
|
|
2378
2394
|
logTransientSpawnError("docker ps", e);
|
|
2379
2395
|
return [];
|
|
@@ -2383,7 +2399,7 @@ function removeContainers(names) {
|
|
|
2383
2399
|
const removed = [];
|
|
2384
2400
|
for (const name of names) {
|
|
2385
2401
|
try {
|
|
2386
|
-
|
|
2402
|
+
execQuiet("docker", ["rm", "-f", name]);
|
|
2387
2403
|
removed.push(name);
|
|
2388
2404
|
} catch (e) {
|
|
2389
2405
|
console.warn(`[procCleanup] docker rm -f ${name} \u0441\u043E\u0440\u0432\u0430\u043B\u0441\u044F: ${String(e)}`);
|
|
@@ -2445,6 +2461,7 @@ async function sweepOrphans(params) {
|
|
|
2445
2461
|
var init_procCleanup = __esm({
|
|
2446
2462
|
"src/procCleanup.ts"() {
|
|
2447
2463
|
"use strict";
|
|
2464
|
+
init_quietExec();
|
|
2448
2465
|
init_resources();
|
|
2449
2466
|
init_procList();
|
|
2450
2467
|
}
|
|
@@ -9035,7 +9052,7 @@ async function collectRunDiff(worktree, opts = {}) {
|
|
|
9035
9052
|
// package.json
|
|
9036
9053
|
var package_default = {
|
|
9037
9054
|
name: "@taskless-app/swarm",
|
|
9038
|
-
version: "0.4.
|
|
9055
|
+
version: "0.4.4",
|
|
9039
9056
|
type: "module",
|
|
9040
9057
|
description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
9041
9058
|
keywords: [
|
package/package.json
CHANGED