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