@taskless-app/swarm 0.4.2 → 0.4.3
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 +268 -61
- package/dist/overmind.js +1 -1
- 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
|
|
|
@@ -3285,6 +3285,85 @@ function parseDecision(v) {
|
|
|
3285
3285
|
}
|
|
3286
3286
|
}
|
|
3287
3287
|
|
|
3288
|
+
// src/daemonLaunch.ts
|
|
3289
|
+
import { openSync as openSync2, closeSync as closeSync2, renameSync as renameSync2, statSync as statSync2, writeFileSync as writeFileSync3, readFileSync as readFileSync4 } from "fs";
|
|
3290
|
+
import { spawn } from "child_process";
|
|
3291
|
+
var FOREGROUND_FLAGS = /* @__PURE__ */ new Set(["--foreground", "-f", "--attach"]);
|
|
3292
|
+
function parseStartMode(argv) {
|
|
3293
|
+
const rest = argv.filter((a) => !FOREGROUND_FLAGS.has(a));
|
|
3294
|
+
return { foreground: rest.length !== argv.length, rest };
|
|
3295
|
+
}
|
|
3296
|
+
function childStartArgv(rest) {
|
|
3297
|
+
return ["start", ...rest.filter((a) => !FOREGROUND_FLAGS.has(a)), "--foreground"];
|
|
3298
|
+
}
|
|
3299
|
+
function rotateDaemonLog(path, maxBytes) {
|
|
3300
|
+
let size;
|
|
3301
|
+
try {
|
|
3302
|
+
size = statSync2(path).size;
|
|
3303
|
+
} catch {
|
|
3304
|
+
return "missing";
|
|
3305
|
+
}
|
|
3306
|
+
if (size <= maxBytes) return "kept";
|
|
3307
|
+
renameSync2(path, `${path}.1`);
|
|
3308
|
+
writeFileSync3(path, "");
|
|
3309
|
+
return "rotated";
|
|
3310
|
+
}
|
|
3311
|
+
function tailText(text, lines) {
|
|
3312
|
+
const rows = text.split("\n");
|
|
3313
|
+
if (rows[rows.length - 1] === "") rows.pop();
|
|
3314
|
+
return rows.slice(-lines).join("\n");
|
|
3315
|
+
}
|
|
3316
|
+
async function waitForReady(opts) {
|
|
3317
|
+
const now = opts.now ?? Date.now;
|
|
3318
|
+
const sleep3 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
3319
|
+
const started = now();
|
|
3320
|
+
for (; ; ) {
|
|
3321
|
+
if (await opts.probe()) return "ready";
|
|
3322
|
+
if (!opts.alive()) return "died";
|
|
3323
|
+
if (now() - started >= opts.timeoutMs) return "timeout";
|
|
3324
|
+
await sleep3(opts.pollMs);
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
function launchDetached(opts) {
|
|
3328
|
+
const fd = openSync2(opts.logPath, "a");
|
|
3329
|
+
try {
|
|
3330
|
+
const child = spawn(opts.execPath, [...opts.execArgv, opts.entry, ...opts.args], {
|
|
3331
|
+
detached: true,
|
|
3332
|
+
stdio: ["ignore", fd, fd],
|
|
3333
|
+
env: opts.env
|
|
3334
|
+
});
|
|
3335
|
+
child.unref();
|
|
3336
|
+
let exited = false;
|
|
3337
|
+
child.once("exit", () => {
|
|
3338
|
+
exited = true;
|
|
3339
|
+
});
|
|
3340
|
+
return {
|
|
3341
|
+
pid: child.pid ?? -1,
|
|
3342
|
+
// Не `child.killed` (он про посланный сигнал) и не exit-код: после unref событие
|
|
3343
|
+
// может не прийти вовсе — спрашиваем ядро сигналом 0, это и есть «процесс есть».
|
|
3344
|
+
alive: () => {
|
|
3345
|
+
if (exited) return false;
|
|
3346
|
+
if (!child.pid) return false;
|
|
3347
|
+
try {
|
|
3348
|
+
process.kill(child.pid, 0);
|
|
3349
|
+
return true;
|
|
3350
|
+
} catch {
|
|
3351
|
+
return false;
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
};
|
|
3355
|
+
} finally {
|
|
3356
|
+
closeSync2(fd);
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
function tailFile(path, lines) {
|
|
3360
|
+
try {
|
|
3361
|
+
return tailText(readFileSync4(path, "utf8"), lines);
|
|
3362
|
+
} catch {
|
|
3363
|
+
return "";
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
|
|
3288
3367
|
// src/procCleanup.ts
|
|
3289
3368
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
3290
3369
|
|
|
@@ -3546,7 +3625,7 @@ async function buildRepoRegistry(paths) {
|
|
|
3546
3625
|
|
|
3547
3626
|
// src/hostIdentity.ts
|
|
3548
3627
|
import { hostname } from "os";
|
|
3549
|
-
import { existsSync as existsSync4, readFileSync as
|
|
3628
|
+
import { existsSync as existsSync4, readFileSync as readFileSync5, renameSync as renameSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
3550
3629
|
import { join as join3 } from "path";
|
|
3551
3630
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
3552
3631
|
function hostIdentityPath(home) {
|
|
@@ -3554,10 +3633,10 @@ function hostIdentityPath(home) {
|
|
|
3554
3633
|
}
|
|
3555
3634
|
function loadHostIdentity(deps) {
|
|
3556
3635
|
const exists = deps.exists ?? existsSync4;
|
|
3557
|
-
const readFile2 = deps.readFile ?? ((p) =>
|
|
3636
|
+
const readFile2 = deps.readFile ?? ((p) => readFileSync5(p, "utf8"));
|
|
3558
3637
|
const writeFile2 = deps.writeFile ?? ((p, data) => {
|
|
3559
|
-
|
|
3560
|
-
|
|
3638
|
+
writeFileSync4(`${p}.tmp`, data);
|
|
3639
|
+
renameSync3(`${p}.tmp`, p);
|
|
3561
3640
|
});
|
|
3562
3641
|
const host = deps.hostname ?? hostname;
|
|
3563
3642
|
const newId = deps.newId ?? randomUUID2;
|
|
@@ -3665,7 +3744,7 @@ import { basename as basename2 } from "path";
|
|
|
3665
3744
|
import { serve as serve2 } from "@hono/node-server";
|
|
3666
3745
|
|
|
3667
3746
|
// src/diff.ts
|
|
3668
|
-
import { statSync as
|
|
3747
|
+
import { statSync as statSync3 } from "fs";
|
|
3669
3748
|
import { join as join4 } from "path";
|
|
3670
3749
|
import { $ as $2 } from "execa";
|
|
3671
3750
|
var MAX_FILES = 200;
|
|
@@ -3809,7 +3888,7 @@ async function resolveBase(wt, baseBranch) {
|
|
|
3809
3888
|
}
|
|
3810
3889
|
function mtime(path) {
|
|
3811
3890
|
try {
|
|
3812
|
-
return
|
|
3891
|
+
return statSync3(path).mtimeMs;
|
|
3813
3892
|
} catch {
|
|
3814
3893
|
return 0;
|
|
3815
3894
|
}
|
|
@@ -3853,7 +3932,7 @@ async function collectRunDiff(worktree, opts = {}) {
|
|
|
3853
3932
|
// package.json
|
|
3854
3933
|
var package_default = {
|
|
3855
3934
|
name: "@taskless-app/swarm",
|
|
3856
|
-
version: "0.4.
|
|
3935
|
+
version: "0.4.3",
|
|
3857
3936
|
type: "module",
|
|
3858
3937
|
description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
3859
3938
|
keywords: [
|
|
@@ -3956,18 +4035,18 @@ async function ghChecks(pr, run = realChecksRunner) {
|
|
|
3956
4035
|
|
|
3957
4036
|
// src/droneChannel.ts
|
|
3958
4037
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
3959
|
-
import { chmodSync, mkdirSync as mkdirSync3, readFileSync as
|
|
4038
|
+
import { chmodSync, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
3960
4039
|
import { dirname as dirname2 } from "path";
|
|
3961
4040
|
import { serve } from "@hono/node-server";
|
|
3962
4041
|
function loadChannelSecret(path) {
|
|
3963
4042
|
try {
|
|
3964
|
-
const s =
|
|
4043
|
+
const s = readFileSync6(path, "utf8").trim();
|
|
3965
4044
|
if (s.length >= 32) return s;
|
|
3966
4045
|
} catch {
|
|
3967
4046
|
}
|
|
3968
4047
|
const secret = randomBytes(32).toString("hex");
|
|
3969
4048
|
mkdirSync3(dirname2(path), { recursive: true });
|
|
3970
|
-
|
|
4049
|
+
writeFileSync5(path, secret, { mode: 384 });
|
|
3971
4050
|
try {
|
|
3972
4051
|
chmodSync(path, 384);
|
|
3973
4052
|
} catch {
|
|
@@ -4001,7 +4080,7 @@ var EVENT_KIND_SET = new Set(EVENT_KINDS);
|
|
|
4001
4080
|
|
|
4002
4081
|
// src/oauth.ts
|
|
4003
4082
|
import { createHash, randomBytes as randomBytes2 } from "crypto";
|
|
4004
|
-
import { readFileSync as
|
|
4083
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, unlinkSync } from "fs";
|
|
4005
4084
|
import { join as join5 } from "path";
|
|
4006
4085
|
var REGISTER = "/api/oauth/register";
|
|
4007
4086
|
var AUTHORIZE = "/api/oauth/authorize";
|
|
@@ -4093,13 +4172,13 @@ function toStore(clientId, t, now) {
|
|
|
4093
4172
|
}
|
|
4094
4173
|
function loadStore() {
|
|
4095
4174
|
try {
|
|
4096
|
-
return JSON.parse(
|
|
4175
|
+
return JSON.parse(readFileSync7(STORE_PATH, "utf8"));
|
|
4097
4176
|
} catch {
|
|
4098
4177
|
return null;
|
|
4099
4178
|
}
|
|
4100
4179
|
}
|
|
4101
4180
|
function saveStore(s) {
|
|
4102
|
-
|
|
4181
|
+
writeFileSync6(STORE_PATH, JSON.stringify(s, null, 2), { mode: 384 });
|
|
4103
4182
|
}
|
|
4104
4183
|
function clearStore() {
|
|
4105
4184
|
try {
|
|
@@ -4109,7 +4188,7 @@ function clearStore() {
|
|
|
4109
4188
|
}
|
|
4110
4189
|
function loadClientId() {
|
|
4111
4190
|
try {
|
|
4112
|
-
return JSON.parse(
|
|
4191
|
+
return JSON.parse(readFileSync7(CLIENT_PATH, "utf8")).clientId;
|
|
4113
4192
|
} catch {
|
|
4114
4193
|
return null;
|
|
4115
4194
|
}
|
|
@@ -4118,7 +4197,7 @@ async function ensureClientId(api, redirectUri, fetchFn = fetch) {
|
|
|
4118
4197
|
const existing = loadClientId();
|
|
4119
4198
|
if (existing) return existing;
|
|
4120
4199
|
const clientId = await registerClient({ api, redirectUri }, fetchFn);
|
|
4121
|
-
|
|
4200
|
+
writeFileSync6(CLIENT_PATH, JSON.stringify({ clientId }, null, 2), { mode: 384 });
|
|
4122
4201
|
return clientId;
|
|
4123
4202
|
}
|
|
4124
4203
|
async function ensureAccess(store, opts = {}) {
|
|
@@ -5697,8 +5776,8 @@ function startWeb(deps, port = WEB_PORT) {
|
|
|
5697
5776
|
import { cancelRun, respawnRun, runDaemon, wakeRun, OVERMIND_ENTRY, listDroneProcesses } from "./overmind.js";
|
|
5698
5777
|
|
|
5699
5778
|
// src/launcher.ts
|
|
5700
|
-
import { spawn } from "child_process";
|
|
5701
|
-
import { closeSync as
|
|
5779
|
+
import { spawn as spawn2 } from "child_process";
|
|
5780
|
+
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
5781
|
import { createRequire as createRequire2 } from "module";
|
|
5703
5782
|
import { homedir as homedir2 } from "os";
|
|
5704
5783
|
import { dirname as dirname3, join as join7 } from "path";
|
|
@@ -5777,7 +5856,7 @@ function resolveClaudeBin(opts = {}) {
|
|
|
5777
5856
|
}
|
|
5778
5857
|
|
|
5779
5858
|
// src/droneHome.ts
|
|
5780
|
-
import { lstatSync, mkdirSync as mkdirSync4, readdirSync as readdirSync3, rmSync, statSync as
|
|
5859
|
+
import { lstatSync, mkdirSync as mkdirSync4, readdirSync as readdirSync3, rmSync, statSync as statSync4, symlinkSync } from "fs";
|
|
5781
5860
|
import { join as join6, relative, sep } from "path";
|
|
5782
5861
|
var DRONE_HOME_DENY_DEFAULT = [".taskless-swarm", ".bash_history", ".zsh_history"];
|
|
5783
5862
|
function droneHomeDeny(env = process.env) {
|
|
@@ -5818,7 +5897,7 @@ function buildDroneHome(opts) {
|
|
|
5818
5897
|
const target = join6(realHome, name);
|
|
5819
5898
|
let isDir;
|
|
5820
5899
|
try {
|
|
5821
|
-
isDir =
|
|
5900
|
+
isDir = statSync4(target).isDirectory();
|
|
5822
5901
|
} catch {
|
|
5823
5902
|
continue;
|
|
5824
5903
|
}
|
|
@@ -5984,14 +6063,14 @@ function openNextRunLog(runLogsDir, runId) {
|
|
|
5984
6063
|
const path = nextRunLogPath(runLogsDir, runId);
|
|
5985
6064
|
let out;
|
|
5986
6065
|
try {
|
|
5987
|
-
out =
|
|
6066
|
+
out = openSync3(path, "wx");
|
|
5988
6067
|
} catch (e) {
|
|
5989
6068
|
if (e.code !== "EEXIST") throw e;
|
|
5990
6069
|
continue;
|
|
5991
6070
|
}
|
|
5992
6071
|
let err = null;
|
|
5993
6072
|
try {
|
|
5994
|
-
err =
|
|
6073
|
+
err = openSync3(`${path.slice(0, -".json".length)}.err.log`, "w");
|
|
5995
6074
|
} catch {
|
|
5996
6075
|
err = null;
|
|
5997
6076
|
}
|
|
@@ -6052,7 +6131,7 @@ function makeLauncher(cfg) {
|
|
|
6052
6131
|
}
|
|
6053
6132
|
};
|
|
6054
6133
|
const cfgPath = join7(worktree, ".swarm-mcp.json");
|
|
6055
|
-
|
|
6134
|
+
writeFileSync7(cfgPath, JSON.stringify(mcpConfig, null, 2));
|
|
6056
6135
|
const model = run.model ?? process.env.SWARM_DRONE_MODEL ?? void 0;
|
|
6057
6136
|
const pluginDirs = roleDirs(worktree, run.kind);
|
|
6058
6137
|
const realHome = cfg.droneIsolation?.realHome ?? homedir2();
|
|
@@ -6072,7 +6151,7 @@ function makeLauncher(cfg) {
|
|
|
6072
6151
|
errFd = fds.err ?? void 0;
|
|
6073
6152
|
stdio = ["ignore", outFd, errFd ?? "ignore"];
|
|
6074
6153
|
}
|
|
6075
|
-
const child =
|
|
6154
|
+
const child = spawn2(cfg.claudeBin ?? resolveClaudeBin(), claudeArgs(cfgPath, prompt, continueSession, model, pluginDirs, settings), {
|
|
6076
6155
|
cwd: worktree,
|
|
6077
6156
|
detached: true,
|
|
6078
6157
|
stdio,
|
|
@@ -6082,8 +6161,8 @@ function makeLauncher(cfg) {
|
|
|
6082
6161
|
// Остальной env демона наследуется, как раньше.
|
|
6083
6162
|
env: droneEnv(worktree, process.env, home ? { droneHome: home, realHome } : void 0, cfg.droneCap?.() ?? null)
|
|
6084
6163
|
});
|
|
6085
|
-
if (outFd !== void 0)
|
|
6086
|
-
if (errFd !== void 0)
|
|
6164
|
+
if (outFd !== void 0) closeSync3(outFd);
|
|
6165
|
+
if (errFd !== void 0) closeSync3(errFd);
|
|
6087
6166
|
child.unref();
|
|
6088
6167
|
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
6168
|
return child.pid;
|
|
@@ -6091,13 +6170,13 @@ function makeLauncher(cfg) {
|
|
|
6091
6170
|
}
|
|
6092
6171
|
|
|
6093
6172
|
// src/git.ts
|
|
6094
|
-
import { existsSync as existsSync7, readdirSync as readdirSync5, statSync as
|
|
6173
|
+
import { existsSync as existsSync7, readdirSync as readdirSync5, statSync as statSync6 } from "fs";
|
|
6095
6174
|
import { appendFile, mkdir, readFile, rm } from "fs/promises";
|
|
6096
6175
|
import { isAbsolute, join as join8 } from "path";
|
|
6097
6176
|
import { $ as $4 } from "execa";
|
|
6098
6177
|
function isLinkedWorktree(dir) {
|
|
6099
6178
|
try {
|
|
6100
|
-
return
|
|
6179
|
+
return statSync6(join8(dir, ".git")).isFile();
|
|
6101
6180
|
} catch {
|
|
6102
6181
|
return false;
|
|
6103
6182
|
}
|
|
@@ -6137,20 +6216,20 @@ async function removeWorktree(repo, path) {
|
|
|
6137
6216
|
}
|
|
6138
6217
|
|
|
6139
6218
|
// src/agentToken.ts
|
|
6140
|
-
import { readFileSync as
|
|
6219
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync8, unlinkSync as unlinkSync2 } from "fs";
|
|
6141
6220
|
import { join as join9 } from "path";
|
|
6142
6221
|
var STORE_PATH2 = join9(SWARM_HOME, "agent.json");
|
|
6143
6222
|
var base2 = (api) => api.replace(/\/$/, "");
|
|
6144
6223
|
function loadAgentToken() {
|
|
6145
6224
|
try {
|
|
6146
|
-
const s = JSON.parse(
|
|
6225
|
+
const s = JSON.parse(readFileSync8(STORE_PATH2, "utf8"));
|
|
6147
6226
|
return s.token ? s : null;
|
|
6148
6227
|
} catch {
|
|
6149
6228
|
return null;
|
|
6150
6229
|
}
|
|
6151
6230
|
}
|
|
6152
6231
|
function saveAgentToken(s) {
|
|
6153
|
-
|
|
6232
|
+
writeFileSync8(STORE_PATH2, JSON.stringify(s, null, 2), { mode: 384 });
|
|
6154
6233
|
}
|
|
6155
6234
|
function clearAgentToken() {
|
|
6156
6235
|
try {
|
|
@@ -6202,19 +6281,19 @@ import { basename as basename3, isAbsolute as isAbsolute2, join as join11 } from
|
|
|
6202
6281
|
var SHOT_MAX_FILE_BYTES = 10 * 1024 * 1024;
|
|
6203
6282
|
|
|
6204
6283
|
// src/workspace.ts
|
|
6205
|
-
import { readFileSync as
|
|
6284
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync9, unlinkSync as unlinkSync3 } from "fs";
|
|
6206
6285
|
import { join as join12 } from "path";
|
|
6207
6286
|
var WORKSPACE_PATH = join12(SWARM_HOME, "workspace.json");
|
|
6208
6287
|
function loadWorkspace() {
|
|
6209
6288
|
try {
|
|
6210
|
-
const w = JSON.parse(
|
|
6289
|
+
const w = JSON.parse(readFileSync9(WORKSPACE_PATH, "utf8"));
|
|
6211
6290
|
return w && typeof w.id === "string" && w.id ? w : null;
|
|
6212
6291
|
} catch {
|
|
6213
6292
|
return null;
|
|
6214
6293
|
}
|
|
6215
6294
|
}
|
|
6216
6295
|
function saveWorkspace(w) {
|
|
6217
|
-
|
|
6296
|
+
writeFileSync9(WORKSPACE_PATH, JSON.stringify(w, null, 2), { mode: 384 });
|
|
6218
6297
|
}
|
|
6219
6298
|
function clearWorkspace() {
|
|
6220
6299
|
try {
|
|
@@ -6695,7 +6774,7 @@ async function daemonStatus2() {
|
|
|
6695
6774
|
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
6775
|
|
|
6697
6776
|
// src/pauseState.ts
|
|
6698
|
-
import { existsSync as existsSync8, readFileSync as
|
|
6777
|
+
import { existsSync as existsSync8, readFileSync as readFileSync10, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
|
|
6699
6778
|
import { join as join13 } from "path";
|
|
6700
6779
|
function pauseStatePath(home) {
|
|
6701
6780
|
return join13(home, "pause.json");
|
|
@@ -6703,7 +6782,7 @@ function pauseStatePath(home) {
|
|
|
6703
6782
|
var ACTIVE = { paused: false, at: "", source: "cli" };
|
|
6704
6783
|
function loadPauseState(home, io = {}) {
|
|
6705
6784
|
const exists = io.exists ?? existsSync8;
|
|
6706
|
-
const readFile2 = io.readFile ?? ((p) =>
|
|
6785
|
+
const readFile2 = io.readFile ?? ((p) => readFileSync10(p, "utf8"));
|
|
6707
6786
|
const path = pauseStatePath(home);
|
|
6708
6787
|
if (!exists(path)) return ACTIVE;
|
|
6709
6788
|
try {
|
|
@@ -6727,8 +6806,8 @@ function savePauseState(home, state, io = {}) {
|
|
|
6727
6806
|
return;
|
|
6728
6807
|
}
|
|
6729
6808
|
const writeFile2 = io.writeFile ?? ((p, data) => {
|
|
6730
|
-
|
|
6731
|
-
|
|
6809
|
+
writeFileSync10(`${p}.tmp`, data);
|
|
6810
|
+
renameSync4(`${p}.tmp`, p);
|
|
6732
6811
|
});
|
|
6733
6812
|
writeFile2(path, JSON.stringify(state, null, 2));
|
|
6734
6813
|
}
|
|
@@ -6757,10 +6836,10 @@ function sinceText(at, now) {
|
|
|
6757
6836
|
}
|
|
6758
6837
|
|
|
6759
6838
|
// src/heartbeat.ts
|
|
6760
|
-
import { readFileSync as
|
|
6839
|
+
import { readFileSync as readFileSync11, renameSync as renameSync5, writeFileSync as writeFileSync11 } from "fs";
|
|
6761
6840
|
function readHeartbeat(path) {
|
|
6762
6841
|
try {
|
|
6763
|
-
const ms = Number(
|
|
6842
|
+
const ms = Number(readFileSync11(path, "utf8").trim());
|
|
6764
6843
|
return Number.isFinite(ms) ? ms : null;
|
|
6765
6844
|
} catch {
|
|
6766
6845
|
return null;
|
|
@@ -6948,6 +7027,98 @@ async function waitDaemonDown(opts) {
|
|
|
6948
7027
|
await sleep2(pollMs);
|
|
6949
7028
|
}
|
|
6950
7029
|
}
|
|
7030
|
+
var MAX_DAEMON_LOG_BYTES = 16 * 1024 * 1024;
|
|
7031
|
+
var START_READY_TIMEOUT_MS = 45e3;
|
|
7032
|
+
async function runStartDetached(args) {
|
|
7033
|
+
const already = await daemonStatus2();
|
|
7034
|
+
if (already) {
|
|
7035
|
+
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.`);
|
|
7036
|
+
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");
|
|
7037
|
+
return 0;
|
|
7038
|
+
}
|
|
7039
|
+
const rotated = rotateDaemonLog(DAEMON_LOG_PATH, MAX_DAEMON_LOG_BYTES);
|
|
7040
|
+
const entry = process.argv[1];
|
|
7041
|
+
if (!entry) {
|
|
7042
|
+
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");
|
|
7043
|
+
return 1;
|
|
7044
|
+
}
|
|
7045
|
+
let launch;
|
|
7046
|
+
try {
|
|
7047
|
+
launch = launchDetached({
|
|
7048
|
+
execPath: process.execPath,
|
|
7049
|
+
// execArgv тащим за собой намеренно: в монорепе CLI запускают через tsx-loader, и
|
|
7050
|
+
// без него ребёнок не прочитает .ts-исходник, с которого сам же и стартовал.
|
|
7051
|
+
execArgv: process.execArgv,
|
|
7052
|
+
entry,
|
|
7053
|
+
args: childStartArgv(args),
|
|
7054
|
+
logPath: DAEMON_LOG_PATH,
|
|
7055
|
+
env: process.env
|
|
7056
|
+
});
|
|
7057
|
+
} catch (e) {
|
|
7058
|
+
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}`);
|
|
7059
|
+
console.error("\u043F\u043E\u0434\u043D\u0438\u043C\u0438 \u0432 \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B\u0435: swarm start --foreground");
|
|
7060
|
+
return 1;
|
|
7061
|
+
}
|
|
7062
|
+
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)" : ""}`);
|
|
7063
|
+
const verdict = await waitForReady({
|
|
7064
|
+
probe: async () => await daemonStatus2() != null,
|
|
7065
|
+
alive: launch.alive,
|
|
7066
|
+
timeoutMs: START_READY_TIMEOUT_MS,
|
|
7067
|
+
pollMs: 500
|
|
7068
|
+
});
|
|
7069
|
+
if (verdict === "ready") {
|
|
7070
|
+
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");
|
|
7071
|
+
return 0;
|
|
7072
|
+
}
|
|
7073
|
+
console.error(
|
|
7074
|
+
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:`
|
|
7075
|
+
);
|
|
7076
|
+
console.error(tailFile(DAEMON_LOG_PATH, 20) || `(\u043B\u043E\u0433 \u043F\u0443\u0441\u0442: ${DAEMON_LOG_PATH})`);
|
|
7077
|
+
return 1;
|
|
7078
|
+
}
|
|
7079
|
+
async function runDaemonLogs(argv) {
|
|
7080
|
+
const follow = argv.includes("-f") || argv.includes("--follow");
|
|
7081
|
+
const nAt = argv.findIndex((a) => a === "-n" || a === "--lines");
|
|
7082
|
+
const lines = nAt >= 0 ? Number(argv[nAt + 1]) : 200;
|
|
7083
|
+
if (!Number.isFinite(lines) || lines <= 0) {
|
|
7084
|
+
console.error("\u043D\u0443\u0436\u043D\u043E \u0447\u0438\u0441\u043B\u043E \u0441\u0442\u0440\u043E\u043A: swarm logs -n 200");
|
|
7085
|
+
return 1;
|
|
7086
|
+
}
|
|
7087
|
+
const stray = argv.find((a, i) => /^\d+$/.test(a) && i !== nAt + 1);
|
|
7088
|
+
if (stray) {
|
|
7089
|
+
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.`);
|
|
7090
|
+
return 1;
|
|
7091
|
+
}
|
|
7092
|
+
if (!existsSync9(DAEMON_LOG_PATH)) {
|
|
7093
|
+
console.error(`\u043B\u043E\u0433\u0430 \u0434\u0435\u043C\u043E\u043D\u0430 \u043D\u0435\u0442: ${DAEMON_LOG_PATH}`);
|
|
7094
|
+
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.");
|
|
7095
|
+
return 1;
|
|
7096
|
+
}
|
|
7097
|
+
const head = tailFile(DAEMON_LOG_PATH, lines);
|
|
7098
|
+
if (head) console.log(head);
|
|
7099
|
+
if (!follow) return 0;
|
|
7100
|
+
let pos = statSync7(DAEMON_LOG_PATH).size;
|
|
7101
|
+
for (; ; ) {
|
|
7102
|
+
await sleep2(500);
|
|
7103
|
+
let size;
|
|
7104
|
+
try {
|
|
7105
|
+
size = statSync7(DAEMON_LOG_PATH).size;
|
|
7106
|
+
} catch {
|
|
7107
|
+
continue;
|
|
7108
|
+
}
|
|
7109
|
+
if (size < pos) pos = 0;
|
|
7110
|
+
if (size === pos) continue;
|
|
7111
|
+
const fd = openSync4(DAEMON_LOG_PATH, "r");
|
|
7112
|
+
try {
|
|
7113
|
+
const buf = Buffer.alloc(size - pos);
|
|
7114
|
+
const read = readSync2(fd, buf, 0, buf.length, pos);
|
|
7115
|
+
process.stdout.write(buf.subarray(0, read).toString("utf8"));
|
|
7116
|
+
pos += read;
|
|
7117
|
+
} finally {
|
|
7118
|
+
closeSync4(fd);
|
|
7119
|
+
}
|
|
7120
|
+
}
|
|
7121
|
+
}
|
|
6951
7122
|
async function runStop(argv) {
|
|
6952
7123
|
const force = argv.includes("--force");
|
|
6953
7124
|
const wait = argv.includes("--wait");
|
|
@@ -7092,33 +7263,62 @@ function printRuns(runs, view) {
|
|
|
7092
7263
|
}).forEach((l) => console.log(l));
|
|
7093
7264
|
}
|
|
7094
7265
|
function usage() {
|
|
7095
|
-
console.log(`swarm \u2014 \u0440\u043E\u0439
|
|
7266
|
+
console.log(`swarm \u2014 \u0440\u043E\u0439 AI-\u0434\u0440\u043E\u043D\u043E\u0432 (v${PACKAGE_VERSION2})
|
|
7096
7267
|
|
|
7097
|
-
|
|
7098
|
-
swarm
|
|
7268
|
+
\u041D\u0410\u0427\u0410\u0422\u042C
|
|
7269
|
+
swarm login [--workspace <slug|id>] [--no-open]
|
|
7270
|
+
\u0432\u043E\u0439\u0442\u0438 \u0432 Taskless \u0438 \u0432\u044B\u0431\u0440\u0430\u0442\u044C \u0432\u043E\u0440\u043A\u0441\u043F\u0435\u0439\u0441
|
|
7271
|
+
swarm start [--repo <path>] [--foreground]
|
|
7272
|
+
\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
7273
|
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
|
|
7274
|
+
|
|
7275
|
+
\u0414\u0410\u0422\u042C \u0420\u041E\u042E \u0420\u0410\u0411\u041E\u0422\u0423
|
|
7276
|
+
swarm spawn <slug> [area] [\u0444\u043B\u0430\u0433\u0438 \u043D\u0438\u0436\u0435]
|
|
7277
|
+
\u043F\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 \u043E\u0447\u0435\u0440\u0435\u0434\u044C
|
|
7278
|
+
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
|
|
7279
|
+
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
|
|
7280
|
+
swarm cancel <slug> <\u043F\u0440\u0438\u0447\u0438\u043D\u0430\u2026>
|
|
7281
|
+
\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
7282
|
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
|
|
7283
|
+
swarm answer <qid> <\u0442\u0435\u043A\u0441\u0442\u2026>
|
|
7284
|
+
\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
|
|
7285
|
+
|
|
7286
|
+
\u0423\u041F\u0420\u0410\u0412\u041B\u042F\u0422\u042C \u041C\u0410\u0428\u0418\u041D\u041E\u0419
|
|
7287
|
+
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
|
|
7288
|
+
swarm resume \u0441\u043D\u043E\u0432\u0430 \u0431\u0440\u0430\u0442\u044C \u0440\u0430\u0431\u043E\u0442\u0443
|
|
7289
|
+
swarm stop [--wait|--force]
|
|
7290
|
+
\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
|
|
7291
|
+
swarm remove [--yes] [--wait|--force]
|
|
7292
|
+
\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
|
|
7293
|
+
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)
|
|
7294
|
+
|
|
7295
|
+
\u0421\u041C\u041E\u0422\u0420\u0415\u0422\u042C, \u0427\u0422\u041E \u041F\u0420\u041E\u0418\u0421\u0425\u041E\u0414\u0418\u0422
|
|
7296
|
+
swarm logs [-n 200] [-f] \u043B\u043E\u0433 \u0414\u0415\u041C\u041E\u041D\u0410 (~/.taskless-swarm/overmind.log)
|
|
7297
|
+
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
|
|
7298
|
+
swarm web \u0432\u0435\u0431-\u043C\u043E\u0440\u0434\u0430 \u0440\u043E\u044F \u043D\u0430 127.0.0.1:${WEB_PORT}
|
|
7299
|
+
|
|
7300
|
+
\u041F\u0420\u041E\u0427\u0415\u0415
|
|
7116
7301
|
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
|
|
7302
|
+
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
7303
|
swarm shot <url> <out-prefix> [--timeout <ms>] [--storage-state <path>]
|
|
7119
|
-
headless-\u0441\u043A\u0440\u0438\u043D desktop+mobile \
|
|
7304
|
+
headless-\u0441\u043A\u0440\u0438\u043D\u044B desktop+mobile \u043E\u0434\u043D\u043E\u0439 \u043A\u043E\u043C\u0430\u043D\u0434\u043E\u0439:
|
|
7120
7305
|
<out-prefix>-desktop.png, <out-prefix>-mobile.png
|
|
7306
|
+
swarm import-db <path> --repo <path>
|
|
7307
|
+
\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
7308
|
swarm --version \u0432\u0435\u0440\u0441\u0438\u044F \u043F\u0430\u043A\u0435\u0442\u0430
|
|
7309
|
+
|
|
7310
|
+
\u0424\u041B\u0410\u0413\u0418, \u041A\u041E\u0422\u041E\u0420\u042B\u0415 \u0421\u0422\u041E\u0418\u0422 \u0417\u041D\u0410\u0422\u042C
|
|
7311
|
+
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,
|
|
7312
|
+
\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
|
|
7313
|
+
\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)
|
|
7314
|
+
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
|
|
7315
|
+
--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
|
|
7316
|
+
--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
|
|
7317
|
+
--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
|
|
7318
|
+
--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
|
|
7319
|
+
--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
|
|
7320
|
+
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
|
|
7321
|
+
\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
7322
|
`);
|
|
7123
7323
|
}
|
|
7124
7324
|
var effectiveWorktreesDirMemo;
|
|
@@ -7208,14 +7408,18 @@ if (cmd === "import-db") {
|
|
|
7208
7408
|
process.exit(0);
|
|
7209
7409
|
}
|
|
7210
7410
|
if (cmd === "start") {
|
|
7411
|
+
const { foreground, rest: startArgs } = parseStartMode(rawArgs);
|
|
7211
7412
|
if (SWARM_BACKEND !== "client") {
|
|
7212
7413
|
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
7414
|
}
|
|
7214
|
-
const { repo: repoFlag } = takeRepo(
|
|
7415
|
+
const { repo: repoFlag } = takeRepo(startArgs);
|
|
7215
7416
|
const repo = repoFlag ?? SWARM_REPO;
|
|
7216
7417
|
if (!repo) {
|
|
7217
7418
|
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
7419
|
}
|
|
7420
|
+
if (!foreground) {
|
|
7421
|
+
process.exit(await runStartDetached(startArgs));
|
|
7422
|
+
}
|
|
7219
7423
|
try {
|
|
7220
7424
|
await runDaemon({ repo });
|
|
7221
7425
|
} catch (e) {
|
|
@@ -7224,6 +7428,9 @@ if (cmd === "start") {
|
|
|
7224
7428
|
}
|
|
7225
7429
|
process.exit(0);
|
|
7226
7430
|
}
|
|
7431
|
+
if (cmd === "logs") {
|
|
7432
|
+
process.exit(await runDaemonLogs(rawArgs));
|
|
7433
|
+
}
|
|
7227
7434
|
if (cmd === "ls") {
|
|
7228
7435
|
const snap = await daemonRuns(rawArgs[0]);
|
|
7229
7436
|
if (snap) {
|
package/dist/overmind.js
CHANGED
|
@@ -9035,7 +9035,7 @@ async function collectRunDiff(worktree, opts = {}) {
|
|
|
9035
9035
|
// package.json
|
|
9036
9036
|
var package_default = {
|
|
9037
9037
|
name: "@taskless-app/swarm",
|
|
9038
|
-
version: "0.4.
|
|
9038
|
+
version: "0.4.3",
|
|
9039
9039
|
type: "module",
|
|
9040
9040
|
description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
9041
9041
|
keywords: [
|
package/package.json
CHANGED