@kynver-app/runtime 0.1.11 → 0.1.13
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 +114 -36
- package/dist/cli.js.map +4 -4
- package/dist/index.js +114 -36
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -380,12 +380,12 @@ var DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
|
|
|
380
380
|
var DEFAULT_MAX_USED_PERCENT = 80;
|
|
381
381
|
var DEFAULT_HARD_MAX_USED_PERCENT = 90;
|
|
382
382
|
function observeRunnerDiskGate(input = {}) {
|
|
383
|
-
const
|
|
383
|
+
const path15 = input.diskPath?.trim() || "/";
|
|
384
384
|
const warnBelowBytes = input.diskFreeWarnBytes ?? DEFAULT_WARN_FREE_BYTES;
|
|
385
385
|
const criticalBelowBytes = input.diskFreeCriticalBytes ?? DEFAULT_CRITICAL_FREE_BYTES;
|
|
386
386
|
const maxUsedPercent = input.diskMaxUsedPercent ?? DEFAULT_MAX_USED_PERCENT;
|
|
387
387
|
const hardMaxUsedPercent = input.diskHardMaxUsedPercent ?? DEFAULT_HARD_MAX_USED_PERCENT;
|
|
388
|
-
const stats = statfsSync(
|
|
388
|
+
const stats = statfsSync(path15);
|
|
389
389
|
const freeBytes = Number(stats.bavail) * Number(stats.bsize);
|
|
390
390
|
const totalBytes = Number(stats.blocks) * Number(stats.bsize);
|
|
391
391
|
const usedPercent = totalBytes > 0 ? (totalBytes - freeBytes) / totalBytes * 100 : 100;
|
|
@@ -405,7 +405,7 @@ function observeRunnerDiskGate(input = {}) {
|
|
|
405
405
|
}
|
|
406
406
|
return {
|
|
407
407
|
ok,
|
|
408
|
-
path:
|
|
408
|
+
path: path15,
|
|
409
409
|
freeBytes,
|
|
410
410
|
totalBytes,
|
|
411
411
|
usedPercent,
|
|
@@ -418,10 +418,12 @@ function observeRunnerDiskGate(input = {}) {
|
|
|
418
418
|
}
|
|
419
419
|
|
|
420
420
|
// src/resource-gate.ts
|
|
421
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
421
422
|
import os from "node:os";
|
|
422
423
|
import path5 from "node:path";
|
|
423
424
|
|
|
424
425
|
// src/run-store.ts
|
|
426
|
+
import { existsSync as existsSync4, readdirSync as readdirSync2 } from "node:fs";
|
|
425
427
|
import path4 from "node:path";
|
|
426
428
|
|
|
427
429
|
// src/paths.ts
|
|
@@ -457,6 +459,20 @@ function loadRun(id) {
|
|
|
457
459
|
const { runsDir } = getPaths();
|
|
458
460
|
return readJson(path4.join(runDir(runsDir, safeSlug(id)), "run.json"));
|
|
459
461
|
}
|
|
462
|
+
function listRunRecords() {
|
|
463
|
+
const { runsDir } = getPaths();
|
|
464
|
+
if (!existsSync4(runsDir)) return [];
|
|
465
|
+
const runs = [];
|
|
466
|
+
for (const entry of readdirSync2(runsDir, { withFileTypes: true })) {
|
|
467
|
+
if (!entry.isDirectory()) continue;
|
|
468
|
+
const run = readJson(
|
|
469
|
+
path4.join(runsDir, entry.name, "run.json"),
|
|
470
|
+
void 0
|
|
471
|
+
);
|
|
472
|
+
if (run?.id) runs.push(run);
|
|
473
|
+
}
|
|
474
|
+
return runs;
|
|
475
|
+
}
|
|
460
476
|
function loadWorker(runId, name) {
|
|
461
477
|
const { runsDir } = getPaths();
|
|
462
478
|
return readJson(
|
|
@@ -477,7 +493,7 @@ function runDirectory(id) {
|
|
|
477
493
|
}
|
|
478
494
|
|
|
479
495
|
// src/heartbeat.ts
|
|
480
|
-
import { existsSync as
|
|
496
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
481
497
|
function parseHeartbeat(file) {
|
|
482
498
|
const result = {
|
|
483
499
|
heartbeatCount: 0,
|
|
@@ -486,7 +502,7 @@ function parseHeartbeat(file) {
|
|
|
486
502
|
lastHeartbeatSummary: null,
|
|
487
503
|
heartbeatBlocker: null
|
|
488
504
|
};
|
|
489
|
-
if (!
|
|
505
|
+
if (!existsSync5(file)) return result;
|
|
490
506
|
const lines = readFileSync3(file, "utf8").split("\n").filter(Boolean);
|
|
491
507
|
for (const line of lines) {
|
|
492
508
|
const entry = safeJson(line);
|
|
@@ -502,7 +518,7 @@ function parseHeartbeat(file) {
|
|
|
502
518
|
}
|
|
503
519
|
|
|
504
520
|
// src/stream.ts
|
|
505
|
-
import { existsSync as
|
|
521
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "node:fs";
|
|
506
522
|
function parseClaudeStream(file) {
|
|
507
523
|
const result = {
|
|
508
524
|
firstEventAt: null,
|
|
@@ -511,7 +527,7 @@ function parseClaudeStream(file) {
|
|
|
511
527
|
finalResult: null,
|
|
512
528
|
error: null
|
|
513
529
|
};
|
|
514
|
-
if (!
|
|
530
|
+
if (!existsSync6(file)) return result;
|
|
515
531
|
const lines = readFileSync4(file, "utf8").split("\n").filter(Boolean);
|
|
516
532
|
for (const line of lines) {
|
|
517
533
|
const event = safeJson(line);
|
|
@@ -804,13 +820,23 @@ function computeAutoMaxWorkers(totalMemBytes, opts = {}) {
|
|
|
804
820
|
const raw = Math.max(1, Math.floor(budgetBytes / perWorkerMemBytes));
|
|
805
821
|
return Math.min(raw, AUTO_MAX_WORKERS_CEILING);
|
|
806
822
|
}
|
|
807
|
-
function
|
|
808
|
-
|
|
823
|
+
function readAvailableMemBytes() {
|
|
824
|
+
if (process.platform === "linux") {
|
|
825
|
+
try {
|
|
826
|
+
const meminfo = readFileSync5("/proc/meminfo", "utf8");
|
|
827
|
+
const match = meminfo.match(/^MemAvailable:\s+(\d+)\s*kB/m);
|
|
828
|
+
if (match) return Number(match[1]) * 1024;
|
|
829
|
+
} catch {
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
return os.freemem();
|
|
833
|
+
}
|
|
834
|
+
function countActiveWorkersForRun(run) {
|
|
809
835
|
let active = 0;
|
|
810
836
|
for (const name of Object.keys(run.workers || {})) {
|
|
811
837
|
const worker = readJson(
|
|
812
838
|
path5.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
813
|
-
|
|
839
|
+
void 0
|
|
814
840
|
);
|
|
815
841
|
if (!worker) continue;
|
|
816
842
|
const status = computeWorkerStatus(worker);
|
|
@@ -820,14 +846,19 @@ function countActiveWorkers(runId) {
|
|
|
820
846
|
}
|
|
821
847
|
return active;
|
|
822
848
|
}
|
|
849
|
+
function countActiveWorkersGlobal() {
|
|
850
|
+
let active = 0;
|
|
851
|
+
for (const run of listRunRecords()) active += countActiveWorkersForRun(run);
|
|
852
|
+
return active;
|
|
853
|
+
}
|
|
823
854
|
function observeRunnerResourceGate(input) {
|
|
824
855
|
const { perWorkerMemBytes, memReserveBytes, memUtilization, configuredMaxWorkers } = resolveResourceConfig(
|
|
825
856
|
input.config,
|
|
826
857
|
input.configuredMaxWorkersOverride
|
|
827
858
|
);
|
|
828
859
|
const totalMemBytes = input.totalMemBytes ?? os.totalmem();
|
|
829
|
-
const freeMemBytes = input.freeMemBytes ??
|
|
830
|
-
const activeWorkers = input.activeWorkers ??
|
|
860
|
+
const freeMemBytes = input.freeMemBytes ?? readAvailableMemBytes();
|
|
861
|
+
const activeWorkers = input.activeWorkers ?? countActiveWorkersGlobal();
|
|
831
862
|
const budgetBytes = Math.max(0, Math.floor(totalMemBytes * memUtilization) - memReserveBytes);
|
|
832
863
|
const capacityFromTotal = Math.max(0, Math.floor(budgetBytes / perWorkerMemBytes));
|
|
833
864
|
const capacityFromFree = Math.max(0, Math.floor(Math.max(0, freeMemBytes - memReserveBytes) / perWorkerMemBytes));
|
|
@@ -835,13 +866,13 @@ function observeRunnerResourceGate(input) {
|
|
|
835
866
|
const targetCap = configuredMaxWorkers ?? autoCap;
|
|
836
867
|
const maxConcurrentWorkers = Math.max(0, Math.min(targetCap, capacityFromTotal));
|
|
837
868
|
const slotsByCapacity = Math.max(0, maxConcurrentWorkers - activeWorkers);
|
|
838
|
-
const slotsByFreeMem =
|
|
869
|
+
const slotsByFreeMem = capacityFromFree;
|
|
839
870
|
const slotsAvailable = Math.min(slotsByCapacity, slotsByFreeMem);
|
|
840
871
|
let reason = null;
|
|
841
872
|
if (slotsAvailable <= 0) {
|
|
842
873
|
if (activeWorkers >= maxConcurrentWorkers) {
|
|
843
874
|
reason = `at worker limit (${activeWorkers}/${maxConcurrentWorkers} running)`;
|
|
844
|
-
} else if (capacityFromFree <=
|
|
875
|
+
} else if (capacityFromFree <= 0) {
|
|
845
876
|
reason = "insufficient free memory \u2014 waiting for workers to finish";
|
|
846
877
|
} else {
|
|
847
878
|
reason = "no worker slots available";
|
|
@@ -864,7 +895,7 @@ function observeRunnerResourceGate(input) {
|
|
|
864
895
|
}
|
|
865
896
|
|
|
866
897
|
// src/supervisor.ts
|
|
867
|
-
import { existsSync as
|
|
898
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3 } from "node:fs";
|
|
868
899
|
import path7 from "node:path";
|
|
869
900
|
|
|
870
901
|
// src/prompt.ts
|
|
@@ -937,19 +968,19 @@ var claudeProvider = {
|
|
|
937
968
|
};
|
|
938
969
|
|
|
939
970
|
// src/providers/cursor.ts
|
|
940
|
-
import { closeSync as closeSync2, existsSync as
|
|
971
|
+
import { closeSync as closeSync2, existsSync as existsSync7, openSync as openSync2, readdirSync as readdirSync3 } from "node:fs";
|
|
941
972
|
import { spawn as spawn2 } from "node:child_process";
|
|
942
973
|
import path6 from "node:path";
|
|
943
974
|
var DEFAULT_CURSOR_MODEL = "composer-2.5";
|
|
944
975
|
function latestVersionDir(versionsRoot) {
|
|
945
|
-
if (!
|
|
946
|
-
const versions =
|
|
976
|
+
if (!existsSync7(versionsRoot)) return null;
|
|
977
|
+
const versions = readdirSync3(versionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && /^\d{4}\.\d/.test(entry.name)).map((entry) => entry.name).sort((a, b) => b.localeCompare(a));
|
|
947
978
|
return versions[0] ? path6.join(versionsRoot, versions[0]) : null;
|
|
948
979
|
}
|
|
949
980
|
function resolveBundledCursor(versionDir) {
|
|
950
981
|
const nodeExe = path6.join(versionDir, "node.exe");
|
|
951
982
|
const indexJs = path6.join(versionDir, "index.js");
|
|
952
|
-
if (!
|
|
983
|
+
if (!existsSync7(nodeExe) || !existsSync7(indexJs)) return null;
|
|
953
984
|
return { executable: nodeExe, prefixArgs: [indexJs], shell: false, detached: true };
|
|
954
985
|
}
|
|
955
986
|
function resolveWindowsCursorSpawn(agentBin) {
|
|
@@ -972,7 +1003,7 @@ function resolveAgentBin() {
|
|
|
972
1003
|
if (configured) return configured;
|
|
973
1004
|
if (process.platform === "win32") {
|
|
974
1005
|
const localAgent = path6.join(process.env.LOCALAPPDATA || "", "cursor-agent", "agent.cmd");
|
|
975
|
-
if (
|
|
1006
|
+
if (existsSync7(localAgent)) return localAgent;
|
|
976
1007
|
}
|
|
977
1008
|
return "agent";
|
|
978
1009
|
}
|
|
@@ -1041,8 +1072,11 @@ function resolveWorkerProvider(name) {
|
|
|
1041
1072
|
|
|
1042
1073
|
// src/supervisor.ts
|
|
1043
1074
|
function spawnWorkerProcess(run, opts) {
|
|
1044
|
-
const
|
|
1045
|
-
if (!
|
|
1075
|
+
const rawName = typeof opts.name === "string" ? opts.name.trim() : "";
|
|
1076
|
+
if (!rawName || rawName === "undefined" || rawName === "null") {
|
|
1077
|
+
throw new Error(`worker name is required and must be a real identifier (got: ${JSON.stringify(opts.name)})`);
|
|
1078
|
+
}
|
|
1079
|
+
const name = safeSlug(rawName);
|
|
1046
1080
|
if (run.workers?.[name]) throw new Error(`worker already exists in run ${run.id}: ${name}`);
|
|
1047
1081
|
if (!opts.task) throw new Error(`missing task text for worker ${name}`);
|
|
1048
1082
|
const { worktreesDir } = getPaths();
|
|
@@ -1050,7 +1084,7 @@ function spawnWorkerProcess(run, opts) {
|
|
|
1050
1084
|
mkdirSync3(workerDir, { recursive: true });
|
|
1051
1085
|
const worktreePath = path7.join(worktreesDir, run.id, name);
|
|
1052
1086
|
const branch = opts.branch || `agent/${run.id}/${name}`;
|
|
1053
|
-
if (
|
|
1087
|
+
if (existsSync8(worktreePath)) throw new Error(`worktree path already exists: ${worktreePath}`);
|
|
1054
1088
|
git(run.repo, ["fetch", "origin", "--prune"], { allowFailure: true });
|
|
1055
1089
|
git(run.repo, ["worktree", "add", "-b", branch, worktreePath, run.baseCommit], { throwError: true });
|
|
1056
1090
|
const stdoutPath = path7.join(workerDir, "stdout.jsonl");
|
|
@@ -1112,6 +1146,11 @@ function spawnWorkerProcess(run, opts) {
|
|
|
1112
1146
|
}
|
|
1113
1147
|
function startWorker(args) {
|
|
1114
1148
|
const run = loadRun(String(args.run));
|
|
1149
|
+
const name = typeof args.name === "string" ? args.name.trim() : "";
|
|
1150
|
+
if (!name) {
|
|
1151
|
+
console.error("worker start failed: --name is required");
|
|
1152
|
+
process.exit(1);
|
|
1153
|
+
}
|
|
1115
1154
|
const task = args.task ? String(args.task) : readMaybeFile(args.taskFile ? String(args.taskFile) : void 0);
|
|
1116
1155
|
if (!task) {
|
|
1117
1156
|
console.error("missing --task or --task-file");
|
|
@@ -1119,7 +1158,7 @@ function startWorker(args) {
|
|
|
1119
1158
|
}
|
|
1120
1159
|
try {
|
|
1121
1160
|
const worker = spawnWorkerProcess(run, {
|
|
1122
|
-
name
|
|
1161
|
+
name,
|
|
1123
1162
|
task,
|
|
1124
1163
|
ownedPaths: args.owned ? String(args.owned).split(",").map((s) => s.trim()).filter(Boolean) : [],
|
|
1125
1164
|
model: args.model ? String(args.model) : void 0,
|
|
@@ -1316,7 +1355,7 @@ async function sweepRun(args) {
|
|
|
1316
1355
|
for (const name of Object.keys(run.workers || {})) {
|
|
1317
1356
|
const worker = readJson(
|
|
1318
1357
|
path8.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
1319
|
-
|
|
1358
|
+
void 0
|
|
1320
1359
|
);
|
|
1321
1360
|
if (!worker || !worker.dispatched || !worker.taskId) continue;
|
|
1322
1361
|
const status = computeWorkerStatus(worker);
|
|
@@ -1358,7 +1397,7 @@ async function sweepRun(args) {
|
|
|
1358
1397
|
}
|
|
1359
1398
|
|
|
1360
1399
|
// src/worktree.ts
|
|
1361
|
-
import { existsSync as
|
|
1400
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync4 } from "node:fs";
|
|
1362
1401
|
import path10 from "node:path";
|
|
1363
1402
|
|
|
1364
1403
|
// src/validate.ts
|
|
@@ -1381,7 +1420,7 @@ function createRun(args) {
|
|
|
1381
1420
|
ensureGitRepo(repo);
|
|
1382
1421
|
const id = args.id ? validateRunId(String(args.id)) : timestampSlug(String(args.name || "run"));
|
|
1383
1422
|
const dir = runDirectory(id);
|
|
1384
|
-
if (
|
|
1423
|
+
if (existsSync9(dir)) failExists(`run already exists: ${id}`);
|
|
1385
1424
|
mkdirSync4(dir, { recursive: true });
|
|
1386
1425
|
const base = String(args.base || "origin/main");
|
|
1387
1426
|
const baseCommit = git(repo, ["rev-parse", base]).trim();
|
|
@@ -1400,7 +1439,7 @@ function createRun(args) {
|
|
|
1400
1439
|
}
|
|
1401
1440
|
function listRuns() {
|
|
1402
1441
|
const { runsDir } = getPaths();
|
|
1403
|
-
const rows = listRunIds(runsDir).map((id) => readJson(path10.join(runDirectory(id), "run.json"),
|
|
1442
|
+
const rows = listRunIds(runsDir).map((id) => readJson(path10.join(runDirectory(id), "run.json"), void 0)).filter(Boolean).map((run) => ({
|
|
1404
1443
|
id: run.id,
|
|
1405
1444
|
name: run.name,
|
|
1406
1445
|
status: run.status,
|
|
@@ -1513,7 +1552,7 @@ function runStatus(args) {
|
|
|
1513
1552
|
const workers = names.map((name) => {
|
|
1514
1553
|
const worker = readJson(
|
|
1515
1554
|
path11.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
1516
|
-
|
|
1555
|
+
void 0
|
|
1517
1556
|
);
|
|
1518
1557
|
if (!worker) {
|
|
1519
1558
|
return { worker: name, status: "missing", attention: "needs_attention", attentionReason: "worker.json not found" };
|
|
@@ -1579,10 +1618,48 @@ function stopWorker(args) {
|
|
|
1579
1618
|
}
|
|
1580
1619
|
|
|
1581
1620
|
// src/pipeline-tick.ts
|
|
1582
|
-
import
|
|
1621
|
+
import path14 from "node:path";
|
|
1583
1622
|
|
|
1584
|
-
// src/
|
|
1623
|
+
// src/finalize.ts
|
|
1585
1624
|
import path12 from "node:path";
|
|
1625
|
+
var ACTIVE_RUN_STATUSES = /* @__PURE__ */ new Set(["running", "dispatching", "pending", "queued"]);
|
|
1626
|
+
function terminalStatusFor(run) {
|
|
1627
|
+
const names = Object.keys(run.workers || {});
|
|
1628
|
+
if (names.length === 0) return "failed";
|
|
1629
|
+
let anyAlive = false;
|
|
1630
|
+
let anyResult = false;
|
|
1631
|
+
for (const name of names) {
|
|
1632
|
+
const worker = readJson(
|
|
1633
|
+
path12.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
1634
|
+
void 0
|
|
1635
|
+
);
|
|
1636
|
+
if (!worker) continue;
|
|
1637
|
+
const status = computeWorkerStatus(worker);
|
|
1638
|
+
if (status.alive && !status.finalResult) {
|
|
1639
|
+
anyAlive = true;
|
|
1640
|
+
break;
|
|
1641
|
+
}
|
|
1642
|
+
if (status.finalResult) anyResult = true;
|
|
1643
|
+
}
|
|
1644
|
+
if (anyAlive) return null;
|
|
1645
|
+
return anyResult ? "completed" : "failed";
|
|
1646
|
+
}
|
|
1647
|
+
function finalizeStaleRuns() {
|
|
1648
|
+
const finalized = [];
|
|
1649
|
+
for (const run of listRunRecords()) {
|
|
1650
|
+
if (!ACTIVE_RUN_STATUSES.has(run.status)) continue;
|
|
1651
|
+
const next = terminalStatusFor(run);
|
|
1652
|
+
if (!next || next === run.status) continue;
|
|
1653
|
+
const from = run.status;
|
|
1654
|
+
run.status = next;
|
|
1655
|
+
saveRun(run);
|
|
1656
|
+
finalized.push({ runId: run.id, from, to: next });
|
|
1657
|
+
}
|
|
1658
|
+
return finalized;
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
// src/plan-progress-daemon-sync.ts
|
|
1662
|
+
import path13 from "node:path";
|
|
1586
1663
|
|
|
1587
1664
|
// src/plan-progress-sync.ts
|
|
1588
1665
|
async function syncPlanProgress(args) {
|
|
@@ -1606,8 +1683,8 @@ async function syncActiveWorkerPlanProgress(runId, args) {
|
|
|
1606
1683
|
const outcomes = [];
|
|
1607
1684
|
for (const name of Object.keys(run.workers || {})) {
|
|
1608
1685
|
const worker = readJson(
|
|
1609
|
-
|
|
1610
|
-
|
|
1686
|
+
path13.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
1687
|
+
void 0
|
|
1611
1688
|
);
|
|
1612
1689
|
if (!worker?.dispatched || !worker.taskId) continue;
|
|
1613
1690
|
const status = computeWorkerStatus(worker);
|
|
@@ -1660,13 +1737,12 @@ async function completeFinishedWorkers(runId, args) {
|
|
|
1660
1737
|
const outcomes = [];
|
|
1661
1738
|
for (const name of Object.keys(run.workers || {})) {
|
|
1662
1739
|
const worker = readJson(
|
|
1663
|
-
|
|
1664
|
-
|
|
1740
|
+
path14.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
1741
|
+
void 0
|
|
1665
1742
|
);
|
|
1666
1743
|
if (!worker?.dispatched || !worker.taskId) continue;
|
|
1667
1744
|
const status = computeWorkerStatus(worker);
|
|
1668
1745
|
if (!isFinishedWorkerStatus(status)) continue;
|
|
1669
|
-
if (!status.finalResult) continue;
|
|
1670
1746
|
const result = await tryCompleteWorker({
|
|
1671
1747
|
run: runId,
|
|
1672
1748
|
name,
|
|
@@ -1694,6 +1770,7 @@ async function runPipelineTick(args) {
|
|
|
1694
1770
|
const agentOsId = String(required(String(args.agentOsId || ""), "--agent-os-id"));
|
|
1695
1771
|
const execute = args.execute !== false && args.execute !== "false";
|
|
1696
1772
|
runStatus({ run: runId });
|
|
1773
|
+
const finalizedStaleRuns = finalizeStaleRuns();
|
|
1697
1774
|
const completedWorkers = await completeFinishedWorkers(runId, args);
|
|
1698
1775
|
const planProgressSync = await syncActiveWorkerPlanProgress(runId, args);
|
|
1699
1776
|
const workspacePrefs = await fetchWorkspaceRuntimePreferences(agentOsId, args);
|
|
@@ -1735,6 +1812,7 @@ async function runPipelineTick(args) {
|
|
|
1735
1812
|
execute,
|
|
1736
1813
|
resourceGate,
|
|
1737
1814
|
completedWorkers,
|
|
1815
|
+
finalizedStaleRuns,
|
|
1738
1816
|
planProgressSync,
|
|
1739
1817
|
operatorTick,
|
|
1740
1818
|
sweep,
|