@taskless-app/swarm 0.6.67 → 0.6.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +202 -39
- package/dist/overmind.js +299 -42
- package/package.json +3 -2
package/dist/overmind.js
CHANGED
|
@@ -4092,7 +4092,7 @@ var init_linkFailure = __esm({
|
|
|
4092
4092
|
"use strict";
|
|
4093
4093
|
init_agentToken();
|
|
4094
4094
|
UNKNOWN_LINK_REASON = "\u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u044F \u043D\u0435\u0442, \u0430 \u043F\u0440\u0438\u0447\u0438\u043D\u0443 \u043A\u043E\u043D\u043D\u0435\u043A\u0442\u043E\u0440 \u043D\u0435 \u043D\u0430\u0437\u0432\u0430\u043B";
|
|
4095
|
-
OFFLINE_RE = /fetch failed|econnreset|econnrefused|econnaborted|enotfound|eai_again|etimedout|ehostunreach|enetunreach|epipe|socket hang up|und_err|network error|connection (?:closed|refused|reset|error)|connect timeout/i;
|
|
4095
|
+
OFFLINE_RE = /fetch failed|econnreset|econnrefused|econnaborted|enotfound|eai_again|etimedout|ehostunreach|enetunreach|epipe|socket hang up|und_err|network error|connection (?:closed|refused|reset|error)|connect timeout|request timed out|-32001\b/i;
|
|
4096
4096
|
MISSING_TOOL_RE = /tool[^.]{0,40}not found|unknown tool|tool_not_found|method not found|-32601\b/i;
|
|
4097
4097
|
}
|
|
4098
4098
|
});
|
|
@@ -6024,6 +6024,47 @@ var init_oauth = __esm({
|
|
|
6024
6024
|
}
|
|
6025
6025
|
});
|
|
6026
6026
|
|
|
6027
|
+
// src/prodHttp.ts
|
|
6028
|
+
import { Agent, fetch as undiciFetch } from "undici";
|
|
6029
|
+
function prodDispatcher() {
|
|
6030
|
+
agent ??= new Agent({
|
|
6031
|
+
keepAliveTimeout: PROD_KEEPALIVE_MS,
|
|
6032
|
+
keepAliveMaxTimeout: PROD_KEEPALIVE_MS,
|
|
6033
|
+
headersTimeout: PROD_SOCKET_TIMEOUT_MS,
|
|
6034
|
+
bodyTimeout: PROD_SOCKET_TIMEOUT_MS,
|
|
6035
|
+
connect: { timeout: PROD_CONNECT_TIMEOUT_MS }
|
|
6036
|
+
});
|
|
6037
|
+
return agent;
|
|
6038
|
+
}
|
|
6039
|
+
function isProdTimeout(e) {
|
|
6040
|
+
for (let cur = e, depth = 0; cur != null && depth < 4; cur = cur.cause, depth++) {
|
|
6041
|
+
const code = cur.code;
|
|
6042
|
+
const name = cur.name;
|
|
6043
|
+
const msg = cur instanceof Error ? cur.message : String(cur);
|
|
6044
|
+
if (code === -32001 || code === "UND_ERR_HEADERS_TIMEOUT" || code === "UND_ERR_BODY_TIMEOUT") return true;
|
|
6045
|
+
if (name === "TimeoutError" || /request timed out/i.test(msg)) return true;
|
|
6046
|
+
}
|
|
6047
|
+
return false;
|
|
6048
|
+
}
|
|
6049
|
+
var PROD_CALL_TIMEOUT_MS, FETCH_GRACE_MS, PROD_KEEPALIVE_MS, PROD_SOCKET_TIMEOUT_MS, PROD_CONNECT_TIMEOUT_MS, agent, prodFetch;
|
|
6050
|
+
var init_prodHttp = __esm({
|
|
6051
|
+
"src/prodHttp.ts"() {
|
|
6052
|
+
"use strict";
|
|
6053
|
+
PROD_CALL_TIMEOUT_MS = 15e3;
|
|
6054
|
+
FETCH_GRACE_MS = 5e3;
|
|
6055
|
+
PROD_KEEPALIVE_MS = 1e4;
|
|
6056
|
+
PROD_SOCKET_TIMEOUT_MS = 3e4;
|
|
6057
|
+
PROD_CONNECT_TIMEOUT_MS = 1e4;
|
|
6058
|
+
agent = null;
|
|
6059
|
+
prodFetch = (url, init) => {
|
|
6060
|
+
const method = (init?.method ?? "GET").toUpperCase();
|
|
6061
|
+
const deadline = method === "GET" ? null : AbortSignal.timeout(PROD_CALL_TIMEOUT_MS + FETCH_GRACE_MS);
|
|
6062
|
+
const signal = deadline && init?.signal ? AbortSignal.any([init.signal, deadline]) : deadline ?? init?.signal ?? void 0;
|
|
6063
|
+
return undiciFetch(url, { ...init, ...signal ? { signal } : {}, dispatcher: prodDispatcher() });
|
|
6064
|
+
};
|
|
6065
|
+
}
|
|
6066
|
+
});
|
|
6067
|
+
|
|
6027
6068
|
// src/authState.ts
|
|
6028
6069
|
function noteTokenRejected(nowMs = Date.now()) {
|
|
6029
6070
|
if (!denial) {
|
|
@@ -6512,8 +6553,8 @@ function escapeRegExp(s) {
|
|
|
6512
6553
|
}
|
|
6513
6554
|
async function resolveApiToken(api, explicit) {
|
|
6514
6555
|
if (explicit) return explicit;
|
|
6515
|
-
const
|
|
6516
|
-
if (
|
|
6556
|
+
const agent2 = loadAgentToken();
|
|
6557
|
+
if (agent2?.token) return agent2.token;
|
|
6517
6558
|
const store = loadStore();
|
|
6518
6559
|
if (store) {
|
|
6519
6560
|
const r = await ensureAccess(store, { api });
|
|
@@ -6538,9 +6579,9 @@ function resetLegacyTokenWarning() {
|
|
|
6538
6579
|
async function preflightAuth(opts = {}) {
|
|
6539
6580
|
const api = opts.api ?? TASKLESS_API;
|
|
6540
6581
|
const out = opts.out ?? ((s) => console.error(s));
|
|
6541
|
-
const
|
|
6542
|
-
if (!
|
|
6543
|
-
const probe = await probeAgentToken({ api, token:
|
|
6582
|
+
const agent2 = loadAgentToken();
|
|
6583
|
+
if (!agent2?.token) return true;
|
|
6584
|
+
const probe = await probeAgentToken({ api, token: agent2.token }, opts.fetchFn ?? fetch);
|
|
6544
6585
|
if (probe === "revoked") {
|
|
6545
6586
|
out(noteTokenRejected() ?? revokedTokenComplaint());
|
|
6546
6587
|
return false;
|
|
@@ -6560,7 +6601,8 @@ async function connectTaskless(cfg) {
|
|
|
6560
6601
|
if (!token) return null;
|
|
6561
6602
|
const url = new URL(mcpEndpoint(api));
|
|
6562
6603
|
const transport = new StreamableHTTPClientTransport(url, {
|
|
6563
|
-
requestInit: { headers: { Authorization: `Bearer ${token}` } }
|
|
6604
|
+
requestInit: { headers: { Authorization: `Bearer ${token}` } },
|
|
6605
|
+
fetch: prodFetch
|
|
6564
6606
|
});
|
|
6565
6607
|
const client = new Client({ name: "taskless-swarm", version: "0.1.0" }, { capabilities: {} });
|
|
6566
6608
|
try {
|
|
@@ -6575,7 +6617,14 @@ async function connectTaskless(cfg) {
|
|
|
6575
6617
|
return null;
|
|
6576
6618
|
}
|
|
6577
6619
|
noteTokenAccepted();
|
|
6578
|
-
const call = async (name, args) =>
|
|
6620
|
+
const call = async (name, args) => {
|
|
6621
|
+
try {
|
|
6622
|
+
return await client.callTool({ name, arguments: args }, void 0, { timeout: PROD_CALL_TIMEOUT_MS });
|
|
6623
|
+
} catch (e) {
|
|
6624
|
+
if (isProdTimeout(e)) console.warn(prodTimeoutLine("Taskless", name, PROD_CALL_TIMEOUT_MS));
|
|
6625
|
+
throw e;
|
|
6626
|
+
}
|
|
6627
|
+
};
|
|
6579
6628
|
return makeTasklessClient(
|
|
6580
6629
|
call,
|
|
6581
6630
|
workspace || void 0,
|
|
@@ -6593,7 +6642,9 @@ async function connectSwarmMcp(cfg) {
|
|
|
6593
6642
|
}
|
|
6594
6643
|
const url = new URL(mcpEndpoint(api));
|
|
6595
6644
|
const transport = new StreamableHTTPClientTransport(url, {
|
|
6596
|
-
requestInit: { headers: { Authorization: `Bearer ${token}` } }
|
|
6645
|
+
requestInit: { headers: { Authorization: `Bearer ${token}` } },
|
|
6646
|
+
fetch: prodFetch
|
|
6647
|
+
// TASWM-611
|
|
6597
6648
|
});
|
|
6598
6649
|
const client = new Client({ name: "taskless-swarm-client", version: "0.1.0" }, { capabilities: {} });
|
|
6599
6650
|
try {
|
|
@@ -6612,12 +6663,31 @@ async function connectSwarmMcp(cfg) {
|
|
|
6612
6663
|
}
|
|
6613
6664
|
swarmConnectFailure = null;
|
|
6614
6665
|
noteTokenAccepted();
|
|
6615
|
-
|
|
6666
|
+
const timeout = cfg?.callTimeoutMs ?? PROD_CALL_TIMEOUT_MS;
|
|
6667
|
+
return async (name, args) => {
|
|
6668
|
+
try {
|
|
6669
|
+
return await client.callTool({ name, arguments: swarmToolArgs(name, args, workspace) }, void 0, { timeout });
|
|
6670
|
+
} catch (e) {
|
|
6671
|
+
if (isProdTimeout(e)) {
|
|
6672
|
+
console.warn(`${prodTimeoutLine("Swarm MCP", name, timeout)} \u2014 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u0441\u0431\u0440\u043E\u0448\u0435\u043D\u043E, \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0432\u044B\u0437\u043E\u0432 \u043F\u0435\u0440\u0435\u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0438\u0442\u0441\u044F`);
|
|
6673
|
+
}
|
|
6674
|
+
void client.close().catch(() => {
|
|
6675
|
+
});
|
|
6676
|
+
throw e;
|
|
6677
|
+
}
|
|
6678
|
+
};
|
|
6679
|
+
}
|
|
6680
|
+
function prodTimeoutLine(scope, tool, timeoutMs) {
|
|
6681
|
+
return `[${scope}] \u23F1 ${tool}: \u043F\u0440\u043E\u0434 \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u0437\u0430 ${Math.round(timeoutMs / 100) / 10}\u0441, \u0432\u044B\u0437\u043E\u0432 \u043F\u0440\u0435\u0440\u0432\u0430\u043D`;
|
|
6616
6682
|
}
|
|
6617
6683
|
function lastSwarmConnectFailure() {
|
|
6618
6684
|
return swarmConnectFailure;
|
|
6619
6685
|
}
|
|
6620
6686
|
function swarmToolArgs(name, args, workspace) {
|
|
6687
|
+
if ("workspaceId" in args && args.workspaceId == null) {
|
|
6688
|
+
const { workspaceId: _drop, ...rest } = args;
|
|
6689
|
+
return rest;
|
|
6690
|
+
}
|
|
6621
6691
|
if (!WS_SCOPED_SWARM_TOOLS.has(name) || !workspace) return args;
|
|
6622
6692
|
return { workspaceId: workspace, ...args };
|
|
6623
6693
|
}
|
|
@@ -6632,6 +6702,7 @@ var init_taskless = __esm({
|
|
|
6632
6702
|
init_oauth();
|
|
6633
6703
|
init_agentToken();
|
|
6634
6704
|
init_linkFailure();
|
|
6705
|
+
init_prodHttp();
|
|
6635
6706
|
init_toolFailure();
|
|
6636
6707
|
init_authState();
|
|
6637
6708
|
init_workspace();
|
|
@@ -10340,7 +10411,7 @@ var SwarmClient = class _SwarmClient {
|
|
|
10340
10411
|
// 14.07/18.07, TASWM-201 — общий карантин; здесь — конкретный источник). Резолвим
|
|
10341
10412
|
// слаг→cuid через get_task (кэш — taskIdCache) ПЕРЕД тем как слать create.
|
|
10342
10413
|
taskIdCache = /* @__PURE__ */ new Map();
|
|
10343
|
-
// task_slug → cuid прода
|
|
10414
|
+
// task_slug → cuid прода и воркспейс задачи
|
|
10344
10415
|
// Create для этого runKey резолвился окончательно неудачно (задача не найдена/
|
|
10345
10416
|
// недоступна) — событие/вопросы того же прогона тоже никогда не получат prod-id,
|
|
10346
10417
|
// без карантина они бы бросали «нет prod-id» на каждом флаше и СНОВА вставали
|
|
@@ -10355,12 +10426,20 @@ var SwarmClient = class _SwarmClient {
|
|
|
10355
10426
|
const cacheKey = `${taskRef}\0${repoFullName ?? ""}\0${workspaceId ?? ""}`;
|
|
10356
10427
|
const cached = this.taskIdCache.get(cacheKey);
|
|
10357
10428
|
if (cached) return cached;
|
|
10429
|
+
const first = await this.readTaskRef(taskRef, repoFullName, workspaceId);
|
|
10430
|
+
const res = first === null && repoFullName && !workspaceId ? await this.readTaskRef(taskRef, repoFullName, null) : first;
|
|
10431
|
+
if (res && res !== "transient") this.taskIdCache.set(cacheKey, res);
|
|
10432
|
+
return res;
|
|
10433
|
+
}
|
|
10434
|
+
/** Один get_task: cuid задачи и её воркспейс; null — прод ответил «нет такой». */
|
|
10435
|
+
async readTaskRef(taskRef, repoFullName, workspaceId) {
|
|
10358
10436
|
let res;
|
|
10359
10437
|
try {
|
|
10360
10438
|
res = await this.call("get_task", {
|
|
10361
10439
|
id: taskRef,
|
|
10362
10440
|
...repoFullName ? { repoFullName } : {},
|
|
10363
|
-
|
|
10441
|
+
// null — «без пина демона» (см. swarmToolArgs), undefined — пин по умолчанию.
|
|
10442
|
+
...workspaceId ? { workspaceId } : workspaceId === null ? { workspaceId: null } : {}
|
|
10364
10443
|
});
|
|
10365
10444
|
} catch {
|
|
10366
10445
|
return "transient";
|
|
@@ -10370,10 +10449,9 @@ var SwarmClient = class _SwarmClient {
|
|
|
10370
10449
|
const text = (res.content ?? []).map((c) => c.text ?? "").join(" ");
|
|
10371
10450
|
return /not_found/i.test(text) ? null : "transient";
|
|
10372
10451
|
}
|
|
10373
|
-
const
|
|
10374
|
-
if (!id) return null;
|
|
10375
|
-
|
|
10376
|
-
return id;
|
|
10452
|
+
const task = res.structuredContent?.task;
|
|
10453
|
+
if (!task?.id) return null;
|
|
10454
|
+
return { id: task.id, workspaceId: typeof task.workspaceId === "string" ? task.workspaceId : null };
|
|
10377
10455
|
}
|
|
10378
10456
|
// MCP-31: привести repo прогона к owner/repo-форме для подсказки резолверу
|
|
10379
10457
|
// задачи. Прод сматчит подсказку с ProjectRepo.repoFullName → воркспейс. repo
|
|
@@ -10412,18 +10490,19 @@ var SwarmClient = class _SwarmClient {
|
|
|
10412
10490
|
this.poisonedRunKeys.add(e.runKey);
|
|
10413
10491
|
return "skip";
|
|
10414
10492
|
}
|
|
10415
|
-
const
|
|
10416
|
-
if (
|
|
10493
|
+
const task = await this.resolveTaskCuid(e.taskRef, this.repoFullNameFor(fields.repo), e.workspaceId);
|
|
10494
|
+
if (task === "transient") {
|
|
10417
10495
|
throw new Error(`slug\u2192cuid \u0434\u043B\u044F \xAB${e.taskRef}\xBB \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D (\u043F\u0440\u043E\u0434 \u043C\u043E\u0440\u0433\u043D\u0443\u043B) \u2014 retry`);
|
|
10418
10496
|
}
|
|
10419
|
-
if (!
|
|
10497
|
+
if (!task) {
|
|
10420
10498
|
console.error(
|
|
10421
10499
|
`[swarm-client] create-\u0444\u043B\u0430\u0448 \u043F\u0440\u043E\u043F\u0443\u0449\u0435\u043D: \u043F\u0440\u043E\u0434 \u043D\u0435 \u0437\u043D\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \xAB${e.taskRef}\xBB (runKey=${e.runKey}) \u2014 \u0437\u0430\u043F\u0438\u0441\u044C \u0432\u044B\u0431\u0440\u043E\u0448\u0435\u043D\u0430 \u0438\u0437 outbox`
|
|
10422
10500
|
);
|
|
10423
10501
|
this.poisonedRunKeys.add(e.runKey);
|
|
10424
10502
|
return "skip";
|
|
10425
10503
|
}
|
|
10426
|
-
|
|
10504
|
+
const workspaceId = e.workspaceId || task.workspaceId;
|
|
10505
|
+
return { tool: "swarm_run_upsert", args: { taskId: task.id, ...workspaceId ? { workspaceId } : {}, ...fields } };
|
|
10427
10506
|
}
|
|
10428
10507
|
if (this.poisonedRunKeys.has(e.runKey)) {
|
|
10429
10508
|
console.error(`[swarm-client] ${e.t}-\u0444\u043B\u0430\u0448 \u043F\u0440\u043E\u043F\u0443\u0449\u0435\u043D: create \u043F\u0440\u043E\u0433\u043E\u043D\u0430 runKey=${e.runKey} \u043D\u0435 \u0440\u0435\u0437\u043E\u043B\u0432\u0438\u043B\u0441\u044F \u0440\u0430\u043D\u0435\u0435 \u2014 \u0437\u0430\u043F\u0438\u0441\u044C \u0432\u044B\u0431\u0440\u043E\u0448\u0435\u043D\u0430 \u0438\u0437 outbox`);
|
|
@@ -10475,6 +10554,7 @@ var SwarmClient = class _SwarmClient {
|
|
|
10475
10554
|
} catch {
|
|
10476
10555
|
break;
|
|
10477
10556
|
}
|
|
10557
|
+
if (res?.isError && res.unavailable) break;
|
|
10478
10558
|
if (res?.isError) {
|
|
10479
10559
|
const reason = (res.content ?? []).map((c) => c.text).filter(Boolean).join(" ").trim() || "\u0431\u0435\u0437 \u043E\u0431\u044A\u044F\u0441\u043D\u0435\u043D\u0438\u044F";
|
|
10480
10560
|
const tries = (this.rejected.get(e.seq) ?? 0) + 1;
|
|
@@ -10597,8 +10677,39 @@ function tickPulse(health, now, intervalMs) {
|
|
|
10597
10677
|
return { seq: health.seq, ageMs: tickAgeMs(health, now), intervalMs };
|
|
10598
10678
|
}
|
|
10599
10679
|
|
|
10680
|
+
// src/tickSteps.ts
|
|
10681
|
+
var SLOW_PASS_MS = 3e4;
|
|
10682
|
+
function makeStepClock(now = Date.now) {
|
|
10683
|
+
const startedAt = now();
|
|
10684
|
+
const spent = /* @__PURE__ */ new Map();
|
|
10685
|
+
let current = "\u043D\u0430\u0447\u0430\u043B\u043E \u043F\u0440\u043E\u0445\u043E\u0434\u0430";
|
|
10686
|
+
let since = startedAt;
|
|
10687
|
+
const close = () => {
|
|
10688
|
+
const t = now();
|
|
10689
|
+
spent.set(current, (spent.get(current) ?? 0) + (t - since));
|
|
10690
|
+
since = t;
|
|
10691
|
+
};
|
|
10692
|
+
return {
|
|
10693
|
+
mark(step) {
|
|
10694
|
+
close();
|
|
10695
|
+
current = step;
|
|
10696
|
+
},
|
|
10697
|
+
finish() {
|
|
10698
|
+
close();
|
|
10699
|
+
const steps = [...spent].map(([step, ms]) => ({ step, ms })).sort((a, b) => b.ms - a.ms);
|
|
10700
|
+
return { totalMs: since - startedAt, steps };
|
|
10701
|
+
}
|
|
10702
|
+
};
|
|
10703
|
+
}
|
|
10704
|
+
function slowPassLine(seq, done, thresholdMs = SLOW_PASS_MS) {
|
|
10705
|
+
if (done.totalMs <= thresholdMs) return null;
|
|
10706
|
+
const sec = (ms) => `${Math.round(ms / 100) / 10}\u0441`;
|
|
10707
|
+
const top = done.steps.slice(0, 3).map((s) => `${s.step} ${sec(s.ms)}`).join(", ");
|
|
10708
|
+
return `[overmind] \u23F1 \u043F\u0440\u043E\u0445\u043E\u0434 \u0442\u0438\u043A\u0430 #${seq} \u0434\u043B\u0438\u043B\u0441\u044F ${sec(done.totalMs)} (\u043F\u043E\u0440\u043E\u0433 ${sec(thresholdMs)}); \u0434\u043E\u043B\u044C\u0448\u0435 \u0432\u0441\u0435\u0433\u043E: ${top}`;
|
|
10709
|
+
}
|
|
10710
|
+
|
|
10600
10711
|
// src/logRotate.ts
|
|
10601
|
-
import { copyFileSync as copyFileSync4, renameSync as renameSync5, statSync as statSync7, fstatSync, truncateSync, unlinkSync as unlinkSync3, existsSync as existsSync9 } from "fs";
|
|
10712
|
+
import { copyFileSync as copyFileSync4, renameSync as renameSync5, statSync as statSync7, fstatSync, truncateSync, unlinkSync as unlinkSync3, existsSync as existsSync9, openSync as openSync2, writeSync, closeSync as closeSync2 } from "fs";
|
|
10602
10713
|
var realIo = {
|
|
10603
10714
|
size: (path) => {
|
|
10604
10715
|
try {
|
|
@@ -10632,6 +10743,7 @@ var realOwnerIo = {
|
|
|
10632
10743
|
}
|
|
10633
10744
|
};
|
|
10634
10745
|
function stdoutGoesTo(path, io = realOwnerIo) {
|
|
10746
|
+
if (teedTo === path) return true;
|
|
10635
10747
|
const out = io.statFd(1);
|
|
10636
10748
|
if (!out || !out.isFile) return false;
|
|
10637
10749
|
const file = io.statPath(path);
|
|
@@ -10656,13 +10768,14 @@ function rotateDaemonLog(path, opts, io = realIo) {
|
|
|
10656
10768
|
io.truncate(path);
|
|
10657
10769
|
return "rotated";
|
|
10658
10770
|
}
|
|
10771
|
+
var teedTo = null;
|
|
10659
10772
|
|
|
10660
10773
|
// src/daemonLaunch.ts
|
|
10661
|
-
import { openSync as
|
|
10774
|
+
import { openSync as openSync3, closeSync as closeSync3, readFileSync as readFileSync9 } from "fs";
|
|
10662
10775
|
import { spawn } from "child_process";
|
|
10663
10776
|
var realRespawnIo = {
|
|
10664
10777
|
isTty: () => process.stdout.isTTY === true,
|
|
10665
|
-
open: (path) =>
|
|
10778
|
+
open: (path) => openSync3(path, "a")
|
|
10666
10779
|
};
|
|
10667
10780
|
function respawnStdio(logPath, io = realRespawnIo) {
|
|
10668
10781
|
if (io.isTty()) return "inherit";
|
|
@@ -11464,7 +11577,7 @@ function buildReliefCostCandidates(cost, t, sustainMs, build) {
|
|
|
11464
11577
|
|
|
11465
11578
|
// src/launcher.ts
|
|
11466
11579
|
import { spawn as spawn2 } from "child_process";
|
|
11467
|
-
import { closeSync as
|
|
11580
|
+
import { closeSync as closeSync4, existsSync as existsSync12, mkdirSync as mkdirSync9, openSync as openSync4, readdirSync as readdirSync10 } from "fs";
|
|
11468
11581
|
import { createRequire } from "module";
|
|
11469
11582
|
import { homedir as homedir6 } from "os";
|
|
11470
11583
|
import { dirname as dirname3, join as join18 } from "path";
|
|
@@ -11673,14 +11786,14 @@ function openNextRunLog(runLogsDir, runLogKeys) {
|
|
|
11673
11786
|
const path = nextRunLogPath(runLogsDir, runLogKeys);
|
|
11674
11787
|
let out;
|
|
11675
11788
|
try {
|
|
11676
|
-
out =
|
|
11789
|
+
out = openSync4(path, "wx");
|
|
11677
11790
|
} catch (e) {
|
|
11678
11791
|
if (e.code !== "EEXIST") throw e;
|
|
11679
11792
|
continue;
|
|
11680
11793
|
}
|
|
11681
11794
|
let err = null;
|
|
11682
11795
|
try {
|
|
11683
|
-
err =
|
|
11796
|
+
err = openSync4(`${path.slice(0, -".json".length)}.err.log`, "w");
|
|
11684
11797
|
} catch {
|
|
11685
11798
|
err = null;
|
|
11686
11799
|
}
|
|
@@ -11810,8 +11923,8 @@ function makeLauncher(cfg) {
|
|
|
11810
11923
|
// они про его собственное состояние, и перебивать их ройным нечем.
|
|
11811
11924
|
env: { ...droneEnv(worktree, process.env, home ? { droneHome: home, realHome } : void 0, cfg.droneCap?.() ?? null), ...plan.env }
|
|
11812
11925
|
});
|
|
11813
|
-
if (outFd !== void 0)
|
|
11814
|
-
if (errFd !== void 0)
|
|
11926
|
+
if (outFd !== void 0) closeSync4(outFd);
|
|
11927
|
+
if (errFd !== void 0) closeSync4(errFd);
|
|
11815
11928
|
child.unref();
|
|
11816
11929
|
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)");
|
|
11817
11930
|
return child.pid;
|
|
@@ -12092,7 +12205,7 @@ import { execa } from "execa";
|
|
|
12092
12205
|
|
|
12093
12206
|
// src/prepareLock.ts
|
|
12094
12207
|
import { createHash } from "crypto";
|
|
12095
|
-
import { closeSync as
|
|
12208
|
+
import { closeSync as closeSync5, openSync as openSync5, rmSync as rmSync2, statSync as statSync12, writeSync as writeSync2 } from "fs";
|
|
12096
12209
|
import { join as join23 } from "path";
|
|
12097
12210
|
import { tmpdir } from "os";
|
|
12098
12211
|
var WAIT_TIMEOUT_MS = 5 * 6e4;
|
|
@@ -12103,11 +12216,11 @@ function machineLockPath(key, dir = tmpdir()) {
|
|
|
12103
12216
|
}
|
|
12104
12217
|
function defaultTryCreate(path, content) {
|
|
12105
12218
|
try {
|
|
12106
|
-
const fd =
|
|
12219
|
+
const fd = openSync5(path, "wx");
|
|
12107
12220
|
try {
|
|
12108
|
-
|
|
12221
|
+
writeSync2(fd, content);
|
|
12109
12222
|
} finally {
|
|
12110
|
-
|
|
12223
|
+
closeSync5(fd);
|
|
12111
12224
|
}
|
|
12112
12225
|
return true;
|
|
12113
12226
|
} catch {
|
|
@@ -12846,6 +12959,18 @@ var FileOverlapError = class extends SpawnDeferredError {
|
|
|
12846
12959
|
}
|
|
12847
12960
|
blockedByRunId;
|
|
12848
12961
|
};
|
|
12962
|
+
var SpawnAbandonedError = class extends Error {
|
|
12963
|
+
constructor(status) {
|
|
12964
|
+
super(`\u043F\u0440\u043E\u0433\u043E\u043D \u0441\u043D\u044F\u0442 (${status}), \u043F\u043E\u043A\u0430 \u0433\u043E\u0442\u043E\u0432\u0438\u043B\u0430\u0441\u044C \u0440\u0430\u0431\u043E\u0447\u0430\u044F \u043A\u043E\u043F\u0438\u044F \u2014 \u0434\u0440\u043E\u043D\u0430 \u043D\u0435 \u043F\u043E\u0434\u043D\u0438\u043C\u0430\u044E`);
|
|
12965
|
+
this.status = status;
|
|
12966
|
+
this.name = "SpawnAbandonedError";
|
|
12967
|
+
}
|
|
12968
|
+
status;
|
|
12969
|
+
};
|
|
12970
|
+
function assertStillWanted(db, runId) {
|
|
12971
|
+
const fresh = db.getRun(runId);
|
|
12972
|
+
if (fresh && isTerminalStatus(fresh.status)) throw new SpawnAbandonedError(fresh.status);
|
|
12973
|
+
}
|
|
12849
12974
|
function healTaskSlug(db, run2, task) {
|
|
12850
12975
|
const slug = task?.slug;
|
|
12851
12976
|
if (!slug || slug === run2.task_slug || !isTaskSlug(slug) || isTaskSlug(run2.task_slug)) return run2;
|
|
@@ -12863,6 +12988,7 @@ async function spawnDrone(deps, run2) {
|
|
|
12863
12988
|
if (run2.area && deps.db.runningAreas("").includes(run2.area)) throw new AreaBusyError(run2.area);
|
|
12864
12989
|
deps.db.addEvent(run2.id, "step", `repoless-\u043F\u0440\u043E\u0433\u043E\u043D: \u0441\u043A\u0440\u0430\u0442\u0447-\u043A\u0430\u0442\u0430\u043B\u043E\u0433 ${workdir} (\u0431\u0435\u0437 worktree/\u0432\u0435\u0442\u043A\u0438/PR \u2014 TASWM-595)`);
|
|
12865
12990
|
const built2 = await deps.buildPrompt(run2, workdir);
|
|
12991
|
+
assertStillWanted(deps.db, run2.id);
|
|
12866
12992
|
const pid2 = deps.launch({ worktree: workdir, run: run2, prompt: built2 });
|
|
12867
12993
|
deps.db.addEvent(run2.id, "step", `\u0434\u0440\u043E\u043D \u0437\u0430\u043F\u0443\u0449\u0435\u043D \u0432 ${workdir} (pid ${pid2})`);
|
|
12868
12994
|
return deps.db.updateRun(run2.id, {
|
|
@@ -12898,6 +13024,7 @@ async function spawnDrone(deps, run2) {
|
|
|
12898
13024
|
const prompt = notice ? `${built}
|
|
12899
13025
|
|
|
12900
13026
|
${notice}` : built;
|
|
13027
|
+
assertStillWanted(deps.db, run2.id);
|
|
12901
13028
|
const pid = deps.launch({ worktree, run: run2, prompt });
|
|
12902
13029
|
deps.db.addEvent(run2.id, "step", `\u0434\u0440\u043E\u043D \u0437\u0430\u043F\u0443\u0449\u0435\u043D \u0432 ${worktree} (pid ${pid})`);
|
|
12903
13030
|
return deps.db.updateRun(run2.id, {
|
|
@@ -13074,7 +13201,7 @@ function parkReasonUnretriable(reason) {
|
|
|
13074
13201
|
// package.json
|
|
13075
13202
|
var package_default = {
|
|
13076
13203
|
name: "@taskless-app/swarm",
|
|
13077
|
-
version: "0.6.
|
|
13204
|
+
version: "0.6.68",
|
|
13078
13205
|
type: "module",
|
|
13079
13206
|
description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
|
|
13080
13207
|
keywords: [
|
|
@@ -13123,9 +13250,10 @@ var package_default = {
|
|
|
13123
13250
|
"@hono/node-server": "^2.0.12",
|
|
13124
13251
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
13125
13252
|
execa: "^10.0.0",
|
|
13253
|
+
undici: "^7.25.0",
|
|
13126
13254
|
zod: "3.25.76"
|
|
13127
13255
|
},
|
|
13128
|
-
gitHead: "
|
|
13256
|
+
gitHead: "4bfd78926aa37ef7de8ea06a6763d7e84a2fded6"
|
|
13129
13257
|
};
|
|
13130
13258
|
|
|
13131
13259
|
// src/version.ts
|
|
@@ -15798,11 +15926,17 @@ init_procList();
|
|
|
15798
15926
|
// src/mcpResilient.ts
|
|
15799
15927
|
init_linkFailure();
|
|
15800
15928
|
init_taskless();
|
|
15929
|
+
init_prodHttp();
|
|
15801
15930
|
var DEFAULT_BACKOFF_MS = [5e3, 15e3, 3e4, 6e4];
|
|
15802
15931
|
var DEFAULT_DOWN_AFTER_MS = 5 * 6e4;
|
|
15803
15932
|
var DEFAULT_RETRY_DELAYS_MS = [200, 800];
|
|
15804
|
-
|
|
15805
|
-
|
|
15933
|
+
var PROD_PASS_BUDGET_MS = 2e4;
|
|
15934
|
+
function errorResult(reason, unavailable) {
|
|
15935
|
+
return {
|
|
15936
|
+
isError: true,
|
|
15937
|
+
...unavailable ? { unavailable: true } : {},
|
|
15938
|
+
content: [{ type: "text", text: `Swarm MCP \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D: ${reason}` }]
|
|
15939
|
+
};
|
|
15806
15940
|
}
|
|
15807
15941
|
function resilientSwarmMcp(opts = {}) {
|
|
15808
15942
|
const connect = opts.connect ?? (() => connectSwarmMcp());
|
|
@@ -15810,6 +15944,13 @@ function resilientSwarmMcp(opts = {}) {
|
|
|
15810
15944
|
const downAfterMs = opts.downAfterMs ?? DEFAULT_DOWN_AFTER_MS;
|
|
15811
15945
|
const retryDelays = opts.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS;
|
|
15812
15946
|
const sleep2 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
15947
|
+
const clock = opts.now ?? Date.now;
|
|
15948
|
+
const passBudgetMs = opts.passBudgetMs ?? PROD_PASS_BUDGET_MS;
|
|
15949
|
+
let passSpentMs = null;
|
|
15950
|
+
let budgetNoted = false;
|
|
15951
|
+
const spend = (since) => {
|
|
15952
|
+
if (passSpentMs !== null) passSpentMs += Math.max(0, clock() - since);
|
|
15953
|
+
};
|
|
15813
15954
|
let caller = null;
|
|
15814
15955
|
let lastTryAt = 0;
|
|
15815
15956
|
let failures = 0;
|
|
@@ -15832,6 +15973,7 @@ function resilientSwarmMcp(opts = {}) {
|
|
|
15832
15973
|
if (!force && lastTryAt !== 0 && now - lastTryAt < wait) return null;
|
|
15833
15974
|
if (!force) lastTryAt = now;
|
|
15834
15975
|
let fresh = null;
|
|
15976
|
+
const connectStart = clock();
|
|
15835
15977
|
try {
|
|
15836
15978
|
fresh = await connect();
|
|
15837
15979
|
if (!fresh) lastConnectReason = lastSwarmConnectFailure() ?? UNKNOWN_LINK_REASON;
|
|
@@ -15848,17 +15990,30 @@ function resilientSwarmMcp(opts = {}) {
|
|
|
15848
15990
|
downReported = false;
|
|
15849
15991
|
return caller;
|
|
15850
15992
|
}
|
|
15993
|
+
spend(connectStart);
|
|
15851
15994
|
if (!force) failures += 1;
|
|
15852
15995
|
if (downSince === null) downSince = now;
|
|
15853
15996
|
return null;
|
|
15854
15997
|
}
|
|
15855
15998
|
const call = async (name, args) => {
|
|
15856
15999
|
for (let attempt = 0; ; attempt++) {
|
|
16000
|
+
if (passSpentMs !== null && passSpentMs >= passBudgetMs) {
|
|
16001
|
+
if (!budgetNoted) {
|
|
16002
|
+
budgetNoted = true;
|
|
16003
|
+
opts.onBudgetSpent?.({ spentMs: passSpentMs, budgetMs: passBudgetMs });
|
|
16004
|
+
}
|
|
16005
|
+
maybeReportDown();
|
|
16006
|
+
return errorResult(
|
|
16007
|
+
`\u043F\u0440\u043E\u0434 \u043D\u0435 \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442, \u0431\u044E\u0434\u0436\u0435\u0442 \u043F\u0440\u043E\u0445\u043E\u0434\u0430 \u043D\u0430 \u0441\u0435\u0442\u044C (${Math.round(passBudgetMs / 1e3)}\u0441) \u0438\u0441\u0447\u0435\u0440\u043F\u0430\u043D \u2014 \u0434\u043E \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0433\u043E \u043F\u0440\u043E\u0445\u043E\u0434\u0430 \u0431\u0435\u0437 \u0441\u0435\u0442\u0438${lastCallReason ?? lastConnectReason ? ` (\u043F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u043F\u0440\u0438\u0447\u0438\u043D\u0430: ${lastCallReason ?? lastConnectReason})` : ""}`,
|
|
16008
|
+
true
|
|
16009
|
+
);
|
|
16010
|
+
}
|
|
15857
16011
|
const active = await ensureCaller(attempt > 0);
|
|
15858
16012
|
if (!active) {
|
|
15859
16013
|
maybeReportDown();
|
|
15860
|
-
return errorResult(lastConnectReason ?? UNKNOWN_LINK_REASON);
|
|
16014
|
+
return errorResult(lastConnectReason ?? UNKNOWN_LINK_REASON, true);
|
|
15861
16015
|
}
|
|
16016
|
+
const callStart = clock();
|
|
15862
16017
|
try {
|
|
15863
16018
|
const res = await active(name, args);
|
|
15864
16019
|
lastOkAt = Date.now();
|
|
@@ -15866,13 +16021,14 @@ function resilientSwarmMcp(opts = {}) {
|
|
|
15866
16021
|
return res;
|
|
15867
16022
|
} catch (e) {
|
|
15868
16023
|
caller = null;
|
|
16024
|
+
spend(callStart);
|
|
15869
16025
|
if (downSince === null) downSince = Date.now();
|
|
15870
16026
|
const { kind, detail: reason } = explainLinkFailure(e);
|
|
15871
16027
|
lastCallReason = reason;
|
|
15872
16028
|
const delay = retryDelays[attempt];
|
|
15873
|
-
if (delay === void 0 || kind !== "offline") {
|
|
16029
|
+
if (delay === void 0 || kind !== "offline" || isProdTimeout(e)) {
|
|
15874
16030
|
maybeReportDown();
|
|
15875
|
-
return errorResult(reason);
|
|
16031
|
+
return errorResult(reason, kind === "offline" || kind === "unknown" || kind === "unauthorized" || isProdTimeout(e));
|
|
15876
16032
|
}
|
|
15877
16033
|
opts.onRetry?.({ tool: name, attempt: attempt + 1, reason });
|
|
15878
16034
|
await sleep2(delay);
|
|
@@ -15880,6 +16036,10 @@ function resilientSwarmMcp(opts = {}) {
|
|
|
15880
16036
|
}
|
|
15881
16037
|
};
|
|
15882
16038
|
return Object.assign(call, {
|
|
16039
|
+
beginPass: () => {
|
|
16040
|
+
passSpentMs = 0;
|
|
16041
|
+
budgetNoted = false;
|
|
16042
|
+
},
|
|
15883
16043
|
// Причина — ТА ЖЕ, что уехала в лог: сначала свежий отказ вызова, иначе отказ
|
|
15884
16044
|
// подключения. Своего разбора здесь нет намеренно (см. lastCallReason выше).
|
|
15885
16045
|
link: () => ({ connected: caller !== null, downSince, lastOkAt, lastError: caller !== null ? null : lastCallReason ?? lastConnectReason })
|
|
@@ -19470,8 +19630,19 @@ function countInFlight(db) {
|
|
|
19470
19630
|
return db.listRuns().filter((r) => r.kind !== "hero" && IN_FLIGHT_STATUSES.has(r.status)).length;
|
|
19471
19631
|
}
|
|
19472
19632
|
function countActiveDrones(db) {
|
|
19473
|
-
|
|
19633
|
+
const preparing = preparingRuns(db);
|
|
19634
|
+
return db.listRuns().filter((r) => r.kind !== "hero" && (ACTIVE_DRONE_STATUSES.has(r.status) || preparing.has(r.id))).length;
|
|
19635
|
+
}
|
|
19636
|
+
var preparingByStore = /* @__PURE__ */ new WeakMap();
|
|
19637
|
+
function preparingRuns(db) {
|
|
19638
|
+
let map = preparingByStore.get(db);
|
|
19639
|
+
if (!map) preparingByStore.set(db, map = /* @__PURE__ */ new Map());
|
|
19640
|
+
return map;
|
|
19474
19641
|
}
|
|
19642
|
+
function hasPreparingRuns(db) {
|
|
19643
|
+
return preparingRuns(db).size > 0;
|
|
19644
|
+
}
|
|
19645
|
+
var SPAWN_INLINE_WAIT_MS = 2e3;
|
|
19475
19646
|
function countActiveReviewers(db) {
|
|
19476
19647
|
return db.listRuns().filter((r) => r.kind === "reviewer" && ACTIVE_DRONE_STATUSES.has(r.status)).length;
|
|
19477
19648
|
}
|
|
@@ -21092,6 +21263,7 @@ function noteStormStall(deps) {
|
|
|
21092
21263
|
for (const run2 of waiting) deferSpawn(deps, run2, reason, { quiet: true });
|
|
21093
21264
|
}
|
|
21094
21265
|
async function trySpawnQueuedRun(deps, run2) {
|
|
21266
|
+
if (preparingRuns(deps.db).has(run2.id)) return "skipped";
|
|
21095
21267
|
if (deps.control?.paused) {
|
|
21096
21268
|
const why = deps.control.state?.reason;
|
|
21097
21269
|
return deferSpawn(deps, run2, `\u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440 \u043E\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u043B \u043F\u0440\u0438\u0451\u043C \u043D\u043E\u0432\u043E\u0439 \u0440\u0430\u0431\u043E\u0442\u044B \u043D\u0430 \u044D\u0442\u043E\u0439 \u043C\u0430\u0448\u0438\u043D\u0435${why ? ` \u2014 ${why}` : ""} (\u043F\u0430\u0443\u0437\u0430)`, {
|
|
@@ -21186,12 +21358,55 @@ async function trySpawnQueuedRun(deps, run2) {
|
|
|
21186
21358
|
await fillSuggestedArea(deps, run2);
|
|
21187
21359
|
const repoGap = unresolvedRepoReason(run2.repo, deps.reposServed ? deps.reposServed() : []);
|
|
21188
21360
|
if (repoGap) return await failBeforeStart(deps, run2, repoGap);
|
|
21361
|
+
return await spawnOrPrepareInBackground(deps, run2);
|
|
21362
|
+
}
|
|
21363
|
+
async function spawnOrPrepareInBackground(deps, run2) {
|
|
21364
|
+
const preparing = preparingRuns(deps.db);
|
|
21365
|
+
const repoKey = normalizeRepo(run2.repo || deps.repoFallback || "");
|
|
21366
|
+
for (const [otherId, otherRepo] of preparing) {
|
|
21367
|
+
if (otherId !== run2.id && otherRepo === repoKey) {
|
|
21368
|
+
return deferSpawn(deps, run2, `\u0432 \u044D\u0442\u043E\u043C \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u0438 \u0435\u0449\u0451 \u0433\u043E\u0442\u043E\u0432\u0438\u0442\u0441\u044F \u0440\u0430\u0431\u043E\u0447\u0430\u044F \u043A\u043E\u043F\u0438\u044F \u043F\u0440\u043E\u0433\u043E\u043D\u0430 #${otherId} \u2014 \u0436\u0434\u0443 \u0435\u0451, \u0447\u0442\u043E\u0431\u044B \u043D\u0435 \u043F\u043E\u0434\u043D\u044F\u0442\u044C \u0434\u0432\u0435 \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0438 \u0440\u0430\u0437\u043E\u043C (TASWM-611)`);
|
|
21369
|
+
}
|
|
21370
|
+
}
|
|
21371
|
+
preparing.set(run2.id, repoKey);
|
|
21372
|
+
const attempt = spawnQueuedRun(deps, run2);
|
|
21373
|
+
const release = () => {
|
|
21374
|
+
preparing.delete(run2.id);
|
|
21375
|
+
};
|
|
21376
|
+
void attempt.then(release, release);
|
|
21377
|
+
let timer;
|
|
21378
|
+
const background = /* @__PURE__ */ Symbol("background");
|
|
21379
|
+
const waited = new Promise((resolve5) => {
|
|
21380
|
+
timer = setTimeout(() => resolve5(background), SPAWN_INLINE_WAIT_MS);
|
|
21381
|
+
});
|
|
21382
|
+
try {
|
|
21383
|
+
const first = await Promise.race([attempt, waited]);
|
|
21384
|
+
if (first !== background) return first;
|
|
21385
|
+
} finally {
|
|
21386
|
+
clearTimeout(timer);
|
|
21387
|
+
}
|
|
21388
|
+
deps.db.addEvent(run2.id, "step", "\u0433\u043E\u0442\u043E\u0432\u0438\u0442\u0441\u044F: \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0430 \u0440\u0430\u0431\u043E\u0447\u0435\u0439 \u043A\u043E\u043F\u0438\u0438 \u0438\u0434\u0451\u0442 \u0444\u043E\u043D\u043E\u043C, \u0442\u0438\u043A \u0435\u0451 \u043D\u0435 \u0436\u0434\u0451\u0442 (TASWM-611)");
|
|
21389
|
+
console.log(`[overmind] ${droneLabel(run2)} (${run2.task_slug}) \u0433\u043E\u0442\u043E\u0432\u0438\u0442\u0441\u044F \u0444\u043E\u043D\u043E\u043C \u2014 \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0430 \u0434\u043E\u043B\u044C\u0448\u0435 ${SPAWN_INLINE_WAIT_MS / 1e3}\u0441, \u0442\u0438\u043A \u0438\u0434\u0451\u0442 \u0434\u0430\u043B\u044C\u0448\u0435`);
|
|
21390
|
+
void attempt.then(
|
|
21391
|
+
(outcome) => {
|
|
21392
|
+
if (outcome !== "spawned") console.warn(`[overmind] \u0444\u043E\u043D\u043E\u0432\u0430\u044F \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0430 ${run2.task_slug} \u043A\u043E\u043D\u0447\u0438\u043B\u0430\u0441\u044C \u0431\u0435\u0437 \u0434\u0440\u043E\u043D\u0430: ${outcome}`);
|
|
21393
|
+
},
|
|
21394
|
+
(e) => console.error(`[overmind] \u0444\u043E\u043D\u043E\u0432\u0430\u044F \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0430 ${run2.task_slug} \u0441\u043E\u0440\u0432\u0430\u043B\u0430\u0441\u044C: ${describeTickError(e)}`)
|
|
21395
|
+
);
|
|
21396
|
+
return "spawned";
|
|
21397
|
+
}
|
|
21398
|
+
async function spawnQueuedRun(deps, run2) {
|
|
21189
21399
|
try {
|
|
21190
21400
|
await deps.spawn(run2);
|
|
21191
21401
|
if (deps.spawnDefer) clearDefer(deps.spawnDefer, `run:${run2.id}`);
|
|
21192
21402
|
narrate(deps, `\u0411\u0435\u0440\u0443 ${run2.task_slug} \u0438\u0437 \u043E\u0447\u0435\u0440\u0435\u0434\u0438 \u2014 \u0441\u043F\u0430\u0432\u043D\u044E ${droneLabel(run2)}.`);
|
|
21193
21403
|
return "spawned";
|
|
21194
21404
|
} catch (e) {
|
|
21405
|
+
if (e instanceof SpawnAbandonedError) {
|
|
21406
|
+
deps.db.addEvent(run2.id, "step", e.message);
|
|
21407
|
+
console.log(`[overmind] ${run2.task_slug}: ${e.message}`);
|
|
21408
|
+
return "closed";
|
|
21409
|
+
}
|
|
21195
21410
|
if (e instanceof FileOverlapError) {
|
|
21196
21411
|
const logged = deps.overlapLogged ??= /* @__PURE__ */ new Map();
|
|
21197
21412
|
if (logged.get(run2.id) !== e.message) {
|
|
@@ -22165,7 +22380,9 @@ async function tickOnce(deps) {
|
|
|
22165
22380
|
const now = deps.now ? deps.now() : Date.now();
|
|
22166
22381
|
const worktreeExists = deps.worktreeExists ?? existsSync22;
|
|
22167
22382
|
const hasTranscript = deps.hasTranscript ?? executorHasSession;
|
|
22383
|
+
deps.stepClock?.mark("0 \u0437\u0430\u043C\u0435\u0440 \u0445\u043E\u0441\u0442\u0430");
|
|
22168
22384
|
deps.sampleHost?.();
|
|
22385
|
+
deps.stepClock?.mark("0a re-hydrate \u0437\u0435\u0440\u043A\u0430\u043B\u0430");
|
|
22169
22386
|
if (deps.rehydrate) {
|
|
22170
22387
|
const rh = deps.rehydrate;
|
|
22171
22388
|
const sinceLast = rh.lastAt == null ? Infinity : now - rh.lastAt;
|
|
@@ -22178,6 +22395,7 @@ async function tickOnce(deps) {
|
|
|
22178
22395
|
}
|
|
22179
22396
|
}
|
|
22180
22397
|
}
|
|
22398
|
+
deps.stepClock?.mark("0a1 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438 \u043E\u0447\u0435\u0440\u0435\u0434\u0438");
|
|
22181
22399
|
if (deps.db.refreshDeps) {
|
|
22182
22400
|
const waiting = deps.db.listRuns("queued").flatMap((r) => r.depends_on ?? []);
|
|
22183
22401
|
if (waiting.length) {
|
|
@@ -22188,6 +22406,7 @@ async function tickOnce(deps) {
|
|
|
22188
22406
|
}
|
|
22189
22407
|
}
|
|
22190
22408
|
}
|
|
22409
|
+
deps.stepClock?.mark("0a2b \u043C\u043E\u0441\u0442 \xABsqlite \u0434\u0440\u043E\u043D\u0430 \u2192 \u0437\u0435\u0440\u043A\u0430\u043B\u043E \u2192 \u043F\u0440\u043E\u0434\xBB");
|
|
22191
22410
|
if (deps.droneBridge) {
|
|
22192
22411
|
const br = deps.droneBridge;
|
|
22193
22412
|
const sinceLast = br.lastAt == null ? Infinity : now - br.lastAt;
|
|
@@ -22200,6 +22419,7 @@ async function tickOnce(deps) {
|
|
|
22200
22419
|
}
|
|
22201
22420
|
}
|
|
22202
22421
|
}
|
|
22422
|
+
deps.stepClock?.mark("0a3 \u0441\u0432\u0435\u0440\u043A\u0430 \u043A\u043E\u0434\u0430 \u0434\u0435\u043C\u043E\u043D\u0430 \u0441 main");
|
|
22203
22423
|
if (deps.daemonVersion) {
|
|
22204
22424
|
const dv = deps.daemonVersion;
|
|
22205
22425
|
const sinceLast = dv.lastAt == null ? Infinity : now - dv.lastAt;
|
|
@@ -22208,6 +22428,7 @@ async function tickOnce(deps) {
|
|
|
22208
22428
|
await dv.run();
|
|
22209
22429
|
}
|
|
22210
22430
|
}
|
|
22431
|
+
deps.stepClock?.mark("0a4 \u043A\u0430\u0440\u0442\u0430 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u0435\u0432 \u043C\u0430\u0448\u0438\u043D\u044B");
|
|
22211
22432
|
if (deps.repoMap) {
|
|
22212
22433
|
const rm4 = deps.repoMap;
|
|
22213
22434
|
const sinceLast = rm4.lastAt == null ? Infinity : now - rm4.lastAt;
|
|
@@ -22220,6 +22441,7 @@ async function tickOnce(deps) {
|
|
|
22220
22441
|
}
|
|
22221
22442
|
}
|
|
22222
22443
|
}
|
|
22444
|
+
deps.stepClock?.mark("0b reap \u0432\u043D\u0435\u0448\u043D\u0435-\u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D\u043D\u044B\u0445");
|
|
22223
22445
|
if (deps.rehydrate && deps.kill) {
|
|
22224
22446
|
const kill = deps.kill;
|
|
22225
22447
|
for (const run2 of deps.db.listRuns()) {
|
|
@@ -22233,6 +22455,7 @@ async function tickOnce(deps) {
|
|
|
22233
22455
|
});
|
|
22234
22456
|
}
|
|
22235
22457
|
}
|
|
22458
|
+
deps.stepClock?.mark("0c \u0437\u0430\u0449\u0438\u0442\u043D\u044B\u0439 sweep \u043E\u0441\u0438\u0440\u043E\u0442\u0435\u0432\u0448\u0438\u0445 \u043F\u0440\u043E\u0446\u0435\u0441\u0441\u043E\u0432/doc");
|
|
22236
22459
|
if (deps.sweep) {
|
|
22237
22460
|
const sw = deps.sweep;
|
|
22238
22461
|
const sinceLast = sw.lastAt == null ? Infinity : now - sw.lastAt;
|
|
@@ -22245,6 +22468,7 @@ async function tickOnce(deps) {
|
|
|
22245
22468
|
}
|
|
22246
22469
|
}
|
|
22247
22470
|
}
|
|
22471
|
+
deps.stepClock?.mark("0c2 \u0436\u043D\u0435\u0446 worktree");
|
|
22248
22472
|
if (deps.reapWorktrees) {
|
|
22249
22473
|
const rw = deps.reapWorktrees;
|
|
22250
22474
|
const sinceLast = rw.lastAt == null ? Infinity : now - rw.lastAt;
|
|
@@ -22257,6 +22481,7 @@ async function tickOnce(deps) {
|
|
|
22257
22481
|
}
|
|
22258
22482
|
}
|
|
22259
22483
|
}
|
|
22484
|
+
deps.stepClock?.mark("0d \u0445\u043E\u0437\u044F\u0439\u0441\u0442\u0432\u043E \u0434\u043E\u043B\u0433\u043E\u0436\u0438\u0432\u0443\u0449\u0435\u0433\u043E \u043F\u0440\u043E\u0446\u0435\u0441\u0441\u0430");
|
|
22260
22485
|
if (deps.logRotate) {
|
|
22261
22486
|
const lr = deps.logRotate;
|
|
22262
22487
|
const sinceLast = lr.lastAt == null ? Infinity : now - lr.lastAt;
|
|
@@ -22270,6 +22495,7 @@ async function tickOnce(deps) {
|
|
|
22270
22495
|
}
|
|
22271
22496
|
}
|
|
22272
22497
|
pruneGateLogs(deps);
|
|
22498
|
+
deps.stepClock?.mark("0 \u0448\u0442\u043E\u0440\u043C");
|
|
22273
22499
|
let stormActive = false;
|
|
22274
22500
|
if (deps.storm) {
|
|
22275
22501
|
for (const run2 of deps.db.listRuns("running")) {
|
|
@@ -22287,7 +22513,9 @@ async function tickOnce(deps) {
|
|
|
22287
22513
|
stormActive = await manageStorm(deps, now, worktreeExists, hasTranscript);
|
|
22288
22514
|
}
|
|
22289
22515
|
const droneCap = deps.maxDrones ? await deps.maxDrones() : Infinity;
|
|
22516
|
+
deps.stepClock?.mark("1 \u043F\u043E\u0434\u043D\u044F\u0442\u044C \u043E\u0447\u0435\u0440\u0435\u0434\u044C");
|
|
22290
22517
|
if (stormActive) noteStormStall(deps);
|
|
22518
|
+
deps.stepClock?.mark("0b \u0432\u0435\u0441 \u0437\u0430\u0434\u0430\u0447\u0438");
|
|
22291
22519
|
try {
|
|
22292
22520
|
await manageWeight(deps);
|
|
22293
22521
|
} catch (e) {
|
|
@@ -22298,14 +22526,17 @@ async function tickOnce(deps) {
|
|
|
22298
22526
|
} else if (!stormActive) {
|
|
22299
22527
|
await batchSpawnQueue(deps, droneCap, now);
|
|
22300
22528
|
}
|
|
22529
|
+
deps.stepClock?.mark("1b \u0432\u043E\u0437\u0432\u0440\u0430\u0442 \u0437\u0430\u043F\u0430\u0440\u043A\u043E\u0432\u0430\u043D\u043D\u044B\u0445 \u0441\u0442\u043E\u0440\u043E\u0436\u0435\u043C \u043F\u0440\u043E\u0433\u0440\u0435\u0441\u0441\u0430");
|
|
22301
22530
|
if (!stormActive) {
|
|
22302
22531
|
await resumeWatchdogParked(deps, droneCap);
|
|
22303
22532
|
}
|
|
22533
|
+
deps.stepClock?.mark("1c \u043F\u043E\u0432\u0442\u043E\u0440 \u043E\u0442\u043B\u043E\u0436\u0435\u043D\u043D\u043E\u0433\u043E \u0441\u043F\u0430\u0432\u043D\u0430");
|
|
22304
22534
|
try {
|
|
22305
22535
|
await retryDeferredSpawns(deps, now, droneCap, stormActive);
|
|
22306
22536
|
} catch (e) {
|
|
22307
22537
|
console.error("[overmind] \u043F\u043E\u0432\u0442\u043E\u0440 \u043E\u0442\u043B\u043E\u0436\u0435\u043D\u043D\u043E\u0433\u043E \u0441\u043F\u0430\u0432\u043D\u0430 \u0441\u043E\u0440\u0432\u0430\u043B\u0441\u044F:", e);
|
|
22308
22538
|
}
|
|
22539
|
+
deps.stepClock?.mark("2 review \u2192 \u0441\u043C\u0435\u0440\u0436\u0435\u043D? \u0437\u0430\u043A\u0440\u044B\u0442\u044C");
|
|
22309
22540
|
for (let run2 of deps.db.listRuns("review")) {
|
|
22310
22541
|
try {
|
|
22311
22542
|
if (run2.resolves_run_id != null) {
|
|
@@ -22555,12 +22786,19 @@ async function tickOnce(deps) {
|
|
|
22555
22786
|
console.error(`[overmind] \u0440\u0435\u043A\u043E\u043D\u0441\u0430\u0439\u043B review-\u043F\u0440\u043E\u0433\u043E\u043D\u0430 #${run2.id} (${run2.task_slug}) \u0441\u043E\u0440\u0432\u0430\u043B\u0441\u044F:`, e);
|
|
22556
22787
|
}
|
|
22557
22788
|
}
|
|
22789
|
+
deps.stepClock?.mark("2b \u0434\u0443\u0431\u043B\u0438-\u0440\u0430\u043D\u044B \u0437\u0430\u0434\u0430\u0447\u0438");
|
|
22558
22790
|
await closeMergedTaskRuns(deps);
|
|
22791
|
+
deps.stepClock?.mark("2b1 \u0430\u0432\u0442\u043E\u043F\u043E\u0434\u044A\u0451\u043C \u043F\u0440\u043E\u0432\u0435\u0440\u044F\u044E\u0449\u0435\u0433\u043E");
|
|
22559
22792
|
await rescueReviewlessPrs(deps, stormActive, now);
|
|
22793
|
+
deps.stepClock?.mark("2b1a \u0440\u0435\u0432\u044C\u044E\u0435\u0440 \u0431\u0435\u0437 \u043F\u0440\u0438\u0432\u044F\u0437\u043A\u0438");
|
|
22560
22794
|
relinkUnboundReviewers(deps);
|
|
22795
|
+
deps.stepClock?.mark("2b2 \u0440\u0435\u0432\u044C\u044E\u0435\u0440\u044B-\u0441\u0438\u0440\u043E\u0442\u044B");
|
|
22561
22796
|
await closeOrphanedReviewers(deps);
|
|
22797
|
+
deps.stepClock?.mark("2b3 \u0432\u0435\u0440\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F");
|
|
22562
22798
|
await spawnVerifiersForOpenPrs(deps, stormActive);
|
|
22799
|
+
deps.stepClock?.mark("2c \u0432\u044B\u0447\u0438\u0441\u043B\u044F\u0435\u043C\u0430\u044F \u0444\u0430\u0437\u0430 \u0440\u0435\u0432\u044C\u044E");
|
|
22563
22800
|
await refreshReviewPhases(deps);
|
|
22801
|
+
deps.stepClock?.mark("3 liveness/stall/\u0430\u0432\u0442\u043E-\u043E\u0436\u0438\u0432\u043B\u0435\u043D\u0438\u0435");
|
|
22564
22802
|
let liveChildPpids;
|
|
22565
22803
|
try {
|
|
22566
22804
|
liveChildPpids = deps.livePpids?.() ?? null;
|
|
@@ -22820,6 +23058,7 @@ async function tickOnce(deps) {
|
|
|
22820
23058
|
});
|
|
22821
23059
|
}
|
|
22822
23060
|
}
|
|
23061
|
+
deps.stepClock?.mark("3b \u043F\u043E\u043B \u0441\u043D\u0438\u0437\u0443");
|
|
22823
23062
|
for (const run2 of deps.db.listRuns("paused")) {
|
|
22824
23063
|
if (run2.kind === "hero") continue;
|
|
22825
23064
|
if (run2.stop_reason === AWAITING_CI_REASON || isReliefPause(run2.stop_reason)) continue;
|
|
@@ -22834,7 +23073,9 @@ async function tickOnce(deps) {
|
|
|
22834
23073
|
deps.db.addEvent(run2.id, "stalled", reason);
|
|
22835
23074
|
narrate(deps, `${droneLabel(run2)} \u0432\u0438\u0441\u0435\u043B paused \u0431\u0435\u0437 \u0434\u0432\u0438\u0436\u0435\u043D\u0438\u044F ${Math.round(STALL_FLOOR_MS / 6e4)} \u043C\u0438\u043D \u2014 \u043F\u043E\u043C\u0435\u0447\u0430\u044E \u0437\u0430\u0432\u0438\u0441\u0448\u0438\u043C (TASWM-275).`);
|
|
22836
23075
|
}
|
|
23076
|
+
deps.stepClock?.mark("3c \u043F\u0440\u0435\u0434\u0435\u043B \u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044F \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F ci");
|
|
22837
23077
|
await escalateStaleCiWaits(deps, now);
|
|
23078
|
+
deps.stepClock?.mark("4 \u043F\u0440\u043E\u0431\u0443\u0436\u0434\u0435\u043D\u0438\u0435 \u0437\u0430\u043C\u0435\u0440\u0448\u0438\u0445");
|
|
22838
23079
|
if (deps.respawn && !stormActive) {
|
|
22839
23080
|
for (const run2 of deps.db.listRuns("paused")) {
|
|
22840
23081
|
if (run2.kind === "hero") continue;
|
|
@@ -22864,9 +23105,11 @@ async function tickOnce(deps) {
|
|
|
22864
23105
|
}
|
|
22865
23106
|
}
|
|
22866
23107
|
}
|
|
23108
|
+
deps.stepClock?.mark("4c \u0433\u0435\u0439\u0442-\u0443\u0432\u0430\u0436\u0430\u044E\u0449\u0438\u0439 \u043F\u043E\u0434\u044A\u0451\u043C \u043E\u0441\u0442\u0430\u0432\u0448\u0438\u0445\u0441\u044F storm_d");
|
|
22867
23109
|
if (deps.respawn && deps.resourcesOk && !stormActive) {
|
|
22868
23110
|
await resurrectStormDead(deps, worktreeExists, hasTranscript, { gateOpen: deps.resourcesOk(), cap: droneCap });
|
|
22869
23111
|
}
|
|
23112
|
+
deps.stepClock?.mark("4d \u043E\u0441\u0438\u0440\u043E\u0442\u0435\u0432\u0448\u0438\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B");
|
|
22870
23113
|
try {
|
|
22871
23114
|
const reaped = reapOrphanedQuestions(deps.db, now);
|
|
22872
23115
|
if (reaped.withdrawn > 0) {
|
|
@@ -22877,11 +23120,13 @@ async function tickOnce(deps) {
|
|
|
22877
23120
|
} catch (e) {
|
|
22878
23121
|
console.error("[overmind] \u0443\u0431\u043E\u0440\u043A\u0430 \u043E\u0441\u0438\u0440\u043E\u0442\u0435\u0432\u0448\u0438\u0445 \u0432\u043E\u043F\u0440\u043E\u0441\u043E\u0432 \u0441\u043E\u0440\u0432\u0430\u043B\u0430\u0441\u044C:", e);
|
|
22879
23122
|
}
|
|
23123
|
+
deps.stepClock?.mark("4e \u043E\u0442\u0432\u0435\u0442 \u043D\u0430 \u0432\u043E\u043F\u0440\u043E\u0441 \u043E \u0431\u044E\u0434\u0436\u0435\u0442\u0435");
|
|
22880
23124
|
try {
|
|
22881
23125
|
await answerBudgetQuestions(deps, { stormActive, droneCap });
|
|
22882
23126
|
} catch (e) {
|
|
22883
23127
|
console.error("[overmind] \u0440\u0430\u0437\u0431\u043E\u0440 \u043E\u0442\u0432\u0435\u0442\u043E\u0432 \u043E \u0431\u044E\u0434\u0436\u0435\u0442\u0435 \u0441\u043E\u0440\u0432\u0430\u043B\u0441\u044F:", e);
|
|
22884
23128
|
}
|
|
23129
|
+
deps.stepClock?.mark("4b \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0439 \u043D\u0430\u0434\u0437\u043E\u0440");
|
|
22885
23130
|
if (deps.anomalies && !deps.control?.paused) {
|
|
22886
23131
|
const az = deps.anomalies;
|
|
22887
23132
|
let ready = [];
|
|
@@ -22958,6 +23203,7 @@ async function tickOnce(deps) {
|
|
|
22958
23203
|
}
|
|
22959
23204
|
}
|
|
22960
23205
|
}
|
|
23206
|
+
deps.stepClock?.mark("4c \u0441\u0442\u043E\u0440\u043E\u0436 \u043F\u0440\u043E\u0433\u0440\u0435\u0441\u0441\u0430");
|
|
22961
23207
|
if (deps.watchdog) {
|
|
22962
23208
|
try {
|
|
22963
23209
|
const action = decideWatchdogAction(deps.db, now, deps.watchdog.state, deps.watchdog.thresholds, droneCap, { exists: worktreeExists, hasTranscript }, await projectQuotaBlockedRunIds(deps));
|
|
@@ -22966,6 +23212,7 @@ async function tickOnce(deps) {
|
|
|
22966
23212
|
console.error("[overmind] \u0441\u0442\u043E\u0440\u043E\u0436 \u043F\u0440\u043E\u0433\u0440\u0435\u0441\u0441\u0430: \u0442\u0438\u043A \u0441\u043E\u0440\u0432\u0430\u043B\u0441\u044F:", e);
|
|
22967
23213
|
}
|
|
22968
23214
|
}
|
|
23215
|
+
deps.stepClock?.mark("5 \u0430\u0432\u0442\u043E-\u0438\u043D\u0442\u0435\u0439\u043A");
|
|
22969
23216
|
const heavyInFlight = heavyRunsInFlight(deps);
|
|
22970
23217
|
if (heavyInFlight.length && deps.intake) {
|
|
22971
23218
|
const d = noteDefer(deps.spawnDefer ??= /* @__PURE__ */ new Map(), "weight-intake-hold", intakeHoldReason(heavyInFlight.map(droneLabel).join(", ")), GATE_LOG_HEARTBEAT_TICKS);
|
|
@@ -23404,7 +23651,11 @@ async function makeStore(repo, worktreesDir, repoFlag) {
|
|
|
23404
23651
|
// Ретрай не молчит: обрыв, переигранный в том же вызове, всё равно виден.
|
|
23405
23652
|
// Без этой строки самолечение связи — единственный путь, о котором в логе
|
|
23406
23653
|
// ни слова, и разбор «почему тик подтормозил» упирается в тишину.
|
|
23407
|
-
onRetry: ({ tool, attempt, reason }) => console.warn(`[overmind] \u043F\u0440\u043E\u0434-MCP: ${tool} \u043E\u0431\u043E\u0440\u0432\u0430\u043B\u0441\u044F (${reason}) \u2014 \u043F\u043E\u0432\u0442\u043E\u0440 ${attempt}.`)
|
|
23654
|
+
onRetry: ({ tool, attempt, reason }) => console.warn(`[overmind] \u043F\u0440\u043E\u0434-MCP: ${tool} \u043E\u0431\u043E\u0440\u0432\u0430\u043B\u0441\u044F (${reason}) \u2014 \u043F\u043E\u0432\u0442\u043E\u0440 ${attempt}.`),
|
|
23655
|
+
// TASWM-611: молчащий прод больше не держит проход минутами — остаток идёт без сети.
|
|
23656
|
+
onBudgetSpent: ({ spentMs, budgetMs }) => console.warn(
|
|
23657
|
+
`[overmind] \u043F\u0440\u043E\u0434-MCP \u043D\u0435 \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442: \u043F\u0440\u043E\u0445\u043E\u0434 \u0443\u0436\u0435 \u043F\u043E\u0442\u0440\u0430\u0442\u0438\u043B \u043D\u0430 \u043D\u0435\u0433\u043E ${Math.round(spentMs / 1e3)}\u0441 (\u0431\u044E\u0434\u0436\u0435\u0442 ${Math.round(budgetMs / 1e3)}\u0441) \u2014 \u0434\u043E \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0433\u043E \u043F\u0440\u043E\u0445\u043E\u0434\u0430 \u0440\u0430\u0431\u043E\u0442\u0430\u044E \u0431\u0435\u0437 \u0441\u0435\u0442\u0438, \u0437\u0430\u043F\u0438\u0441\u0438 \u0436\u0434\u0443\u0442 \u0432 outbox.`
|
|
23658
|
+
)
|
|
23408
23659
|
});
|
|
23409
23660
|
const explicitRegistry = await buildRepoRegistry(repoPaths);
|
|
23410
23661
|
if (repoPaths.length > 0 && explicitRegistry.length < repoPaths.length) {
|
|
@@ -24774,12 +25025,14 @@ async function runDaemon(opts) {
|
|
|
24774
25025
|
tickHealth.startedAt = Date.now();
|
|
24775
25026
|
for (; ; ) {
|
|
24776
25027
|
let tickError;
|
|
25028
|
+
prodMcp?.beginPass?.();
|
|
25029
|
+
deps.stepClock = makeStepClock();
|
|
24777
25030
|
try {
|
|
24778
25031
|
writeHeartbeat(HEARTBEAT_PATH, Date.now());
|
|
24779
25032
|
await tickOnce(deps);
|
|
24780
25033
|
if (restart.phase === "waiting") {
|
|
24781
25034
|
const live2 = liveSessionIds(db, pidAlive);
|
|
24782
|
-
if (live2.length === 0) performRestart([], restart.intent);
|
|
25035
|
+
if (live2.length === 0 && !hasPreparingRuns(db)) performRestart([], restart.intent);
|
|
24783
25036
|
else onRestartStillWaiting?.(live2.length);
|
|
24784
25037
|
}
|
|
24785
25038
|
} catch (e) {
|
|
@@ -24787,6 +25040,8 @@ async function runDaemon(opts) {
|
|
|
24787
25040
|
console.error(`[overmind] \u0442\u0438\u043A \u0443\u043F\u0430\u043B: ${describeTickError(e)} \u2014 \u0446\u0438\u043A\u043B \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0435\u0442 \u0440\u0430\u0431\u043E\u0442\u0443`, e);
|
|
24788
25041
|
}
|
|
24789
25042
|
markTickDone(tickHealth, Date.now(), tickError);
|
|
25043
|
+
const slow = slowPassLine(tickHealth.seq, deps.stepClock.finish());
|
|
25044
|
+
if (slow) console.warn(slow);
|
|
24790
25045
|
await new Promise((r) => setTimeout(r, interval));
|
|
24791
25046
|
}
|
|
24792
25047
|
}
|
|
@@ -24864,6 +25119,7 @@ export {
|
|
|
24864
25119
|
REVIEW_SPAWN_LIMIT,
|
|
24865
25120
|
REVIEW_UNRECOVERABLE_MARK,
|
|
24866
25121
|
SELF_REFERENCE_MARK,
|
|
25122
|
+
SPAWN_INLINE_WAIT_MS,
|
|
24867
25123
|
STALL_FLOOR_MS,
|
|
24868
25124
|
STALL_MS,
|
|
24869
25125
|
STORM_DEAD_LIMIT,
|
|
@@ -24891,6 +25147,7 @@ export {
|
|
|
24891
25147
|
cycleCapHolder,
|
|
24892
25148
|
effectiveReviewCycleLimit,
|
|
24893
25149
|
hasLiveDescendant,
|
|
25150
|
+
hasPreparingRuns,
|
|
24894
25151
|
isSubrun,
|
|
24895
25152
|
lastChangesSummary,
|
|
24896
25153
|
lastVerifySummary,
|