@kynver-app/runtime 0.1.108 → 0.1.116
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/bootstrap.d.ts +1 -0
- package/dist/cleanup-git-rev-cache.d.ts +5 -0
- package/dist/cleanup-git-status-cache.d.ts +5 -0
- package/dist/cleanup-guards.d.ts +2 -0
- package/dist/cleanup-index-status.d.ts +8 -1
- package/dist/cleanup-run-liveness.d.ts +8 -1
- package/dist/cli.js +1929 -468
- package/dist/cli.js.map +4 -4
- package/dist/daemon-heartbeat.d.ts +20 -0
- package/dist/daemon-keeper.d.ts +21 -0
- package/dist/daemon-platform-guard.d.ts +2 -0
- package/dist/device-login.d.ts +8 -0
- package/dist/index.js +2636 -1151
- package/dist/index.js.map +4 -4
- package/dist/landing/cli-auth.d.ts +5 -1
- package/dist/landing/land-pr.d.ts +8 -0
- package/dist/provider-evidence/collect.d.ts +18 -0
- package/dist/provider-evidence/exec.d.ts +5 -0
- package/dist/provider-evidence/index.d.ts +7 -0
- package/dist/provider-evidence/recipes-github.d.ts +4 -0
- package/dist/provider-evidence/recipes-vercel.d.ts +2 -0
- package/dist/provider-evidence/registry.d.ts +6 -0
- package/dist/provider-evidence/types.d.ts +48 -0
- package/dist/provider-evidence/wanted-store.d.ts +5 -0
- package/dist/providers/codex.d.ts +7 -2
- package/dist/providers/hermes-codex.d.ts +5 -2
- package/dist/server/cleanup.js +560 -164
- package/dist/server/cleanup.js.map +4 -4
- package/dist/server/default-repo.js +298 -68
- package/dist/server/default-repo.js.map +4 -4
- package/dist/server/memory-cost-enforce.js +11 -1
- package/dist/server/memory-cost-enforce.js.map +3 -3
- package/dist/server/monitor.js +356 -128
- package/dist/server/monitor.js.map +4 -4
- package/dist/server/worker-policy.js +304 -49
- package/dist/server/worker-policy.js.map +4 -4
- package/dist/status.d.ts +18 -0
- package/dist/worker-ops.d.ts +4 -0
- package/package.json +1 -1
package/dist/server/cleanup.js
CHANGED
|
@@ -1,18 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { existsSync as existsSync8 } from "node:fs";
|
|
6
|
-
import { homedir as homedir3 } from "node:os";
|
|
7
|
-
import path6 from "node:path";
|
|
8
|
-
|
|
9
|
-
// src/config.ts
|
|
10
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "node:fs";
|
|
11
|
-
import { homedir as homedir2, totalmem } from "node:os";
|
|
12
|
-
import path5 from "node:path";
|
|
13
|
-
|
|
14
|
-
// src/git.ts
|
|
15
|
-
import { spawnSync } from "node:child_process";
|
|
1
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
2
|
+
var __esm = (fn, res) => function __init() {
|
|
3
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
4
|
+
};
|
|
16
5
|
|
|
17
6
|
// src/util.ts
|
|
18
7
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -21,6 +10,10 @@ function fail(message) {
|
|
|
21
10
|
console.error(message);
|
|
22
11
|
process.exit(1);
|
|
23
12
|
}
|
|
13
|
+
function hiddenSpawnOptions(opts) {
|
|
14
|
+
if (process.platform !== "win32") return opts;
|
|
15
|
+
return { windowsHide: true, ...opts };
|
|
16
|
+
}
|
|
24
17
|
function safeJson(line) {
|
|
25
18
|
try {
|
|
26
19
|
return JSON.parse(line);
|
|
@@ -88,45 +81,61 @@ function latestIso(values) {
|
|
|
88
81
|
function secsAgo(ms) {
|
|
89
82
|
return Math.max(0, Math.round((Date.now() - ms) / 1e3));
|
|
90
83
|
}
|
|
84
|
+
var init_util = __esm({
|
|
85
|
+
"src/util.ts"() {
|
|
86
|
+
"use strict";
|
|
87
|
+
}
|
|
88
|
+
});
|
|
91
89
|
|
|
92
90
|
// src/worker-env.ts
|
|
93
|
-
var FORBIDDEN_WORKER_ENV_KEYS
|
|
94
|
-
|
|
95
|
-
"
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
91
|
+
var FORBIDDEN_WORKER_ENV_KEYS, FORBIDDEN_KEY_SET;
|
|
92
|
+
var init_worker_env = __esm({
|
|
93
|
+
"src/worker-env.ts"() {
|
|
94
|
+
"use strict";
|
|
95
|
+
FORBIDDEN_WORKER_ENV_KEYS = [
|
|
96
|
+
"ANTHROPIC_API_KEY",
|
|
97
|
+
"ANALYST_API_KEY",
|
|
98
|
+
"RECRUITER_API_KEY",
|
|
99
|
+
"AUTH_SECRET",
|
|
100
|
+
"NEXTAUTH_SECRET",
|
|
101
|
+
"DATABASE_URL",
|
|
102
|
+
"PRODUCTION_DATABASE_URL",
|
|
103
|
+
"KYNVER_PRODUCTION_DATABASE_URL",
|
|
104
|
+
"REDIS_URL",
|
|
105
|
+
"GOOGLE_CLIENT_SECRET",
|
|
106
|
+
"GITHUB_CLIENT_SECRET",
|
|
107
|
+
"KYNVER_API_KEY",
|
|
108
|
+
"KYNVER_SERVICE_SECRET",
|
|
109
|
+
"KYNVER_RUNTIME_SECRET",
|
|
110
|
+
"KYNVER_CRON_SECRET",
|
|
111
|
+
"OPENCLAW_CRON_SECRET",
|
|
112
|
+
"QSTASH_TOKEN",
|
|
113
|
+
"QSTASH_CURRENT_SIGNING_KEY",
|
|
114
|
+
"QSTASH_NEXT_SIGNING_KEY",
|
|
115
|
+
"TOOL_SECRETS_KEK",
|
|
116
|
+
"TOOL_EXECUTOR_DISPATCH_SECRET",
|
|
117
|
+
"CLOUDFLARE_API_TOKEN",
|
|
118
|
+
"STRIPE_SECRET_KEY",
|
|
119
|
+
"STRIPE_WEBHOOK_SECRET",
|
|
120
|
+
"STRIPE_IDENTITY_WEBHOOK_SECRET",
|
|
121
|
+
"VOYAGE_API_KEY",
|
|
122
|
+
"PERPLEXITY_API_KEY",
|
|
123
|
+
"FRED_API_KEY",
|
|
124
|
+
"FMP_API_KEY",
|
|
125
|
+
"CURSOR_API_KEY"
|
|
126
|
+
];
|
|
127
|
+
FORBIDDEN_KEY_SET = new Set(FORBIDDEN_WORKER_ENV_KEYS);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
126
130
|
|
|
127
131
|
// src/git.ts
|
|
132
|
+
import { spawnSync } from "node:child_process";
|
|
128
133
|
function git(cwd, args, options = {}) {
|
|
129
|
-
const res = spawnSync(
|
|
134
|
+
const res = spawnSync(
|
|
135
|
+
"git",
|
|
136
|
+
args,
|
|
137
|
+
hiddenSpawnOptions({ cwd, encoding: "utf8" })
|
|
138
|
+
);
|
|
130
139
|
if (res.status !== 0 && !options.allowFailure) {
|
|
131
140
|
const message = `git ${args.join(" ")} failed: ${res.stderr || res.stdout}`;
|
|
132
141
|
if (options.throwError) throw new Error(message);
|
|
@@ -139,7 +148,11 @@ function gitStatusShort(worktreePath) {
|
|
|
139
148
|
}
|
|
140
149
|
function gitCapture(cwd, args) {
|
|
141
150
|
try {
|
|
142
|
-
const res = spawnSync(
|
|
151
|
+
const res = spawnSync(
|
|
152
|
+
"git",
|
|
153
|
+
args,
|
|
154
|
+
hiddenSpawnOptions({ cwd, encoding: "utf8" })
|
|
155
|
+
);
|
|
143
156
|
return {
|
|
144
157
|
status: res.status,
|
|
145
158
|
stdout: res.stdout || "",
|
|
@@ -237,6 +250,13 @@ function unknownAncestry(base, error, head = null) {
|
|
|
237
250
|
error
|
|
238
251
|
};
|
|
239
252
|
}
|
|
253
|
+
var init_git = __esm({
|
|
254
|
+
"src/git.ts"() {
|
|
255
|
+
"use strict";
|
|
256
|
+
init_util();
|
|
257
|
+
init_worker_env();
|
|
258
|
+
}
|
|
259
|
+
});
|
|
240
260
|
|
|
241
261
|
// src/path-values.ts
|
|
242
262
|
import { homedir } from "node:os";
|
|
@@ -251,15 +271,37 @@ function expandHomePath(value) {
|
|
|
251
271
|
function resolveUserPath(value) {
|
|
252
272
|
return path2.resolve(expandHomePath(value));
|
|
253
273
|
}
|
|
274
|
+
var init_path_values = __esm({
|
|
275
|
+
"src/path-values.ts"() {
|
|
276
|
+
"use strict";
|
|
277
|
+
}
|
|
278
|
+
});
|
|
254
279
|
|
|
255
|
-
// src/
|
|
256
|
-
|
|
280
|
+
// src/default-repo-discovery.ts
|
|
281
|
+
var init_default_repo_discovery = __esm({
|
|
282
|
+
"src/default-repo-discovery.ts"() {
|
|
283
|
+
"use strict";
|
|
284
|
+
init_git();
|
|
285
|
+
init_path_values();
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// src/box-identity.ts
|
|
290
|
+
var init_box_identity = __esm({
|
|
291
|
+
"src/box-identity.ts"() {
|
|
292
|
+
"use strict";
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// src/bounded-build/meminfo.ts
|
|
297
|
+
var init_meminfo = __esm({
|
|
298
|
+
"src/bounded-build/meminfo.ts"() {
|
|
299
|
+
"use strict";
|
|
300
|
+
}
|
|
301
|
+
});
|
|
257
302
|
|
|
258
303
|
// src/wsl-host.ts
|
|
259
304
|
import { existsSync as existsSync2, readFileSync as readFileSync2, statfsSync } from "node:fs";
|
|
260
|
-
var DEFAULT_WSL_HOST_WARN_FREE_BYTES = 25 * 1024 * 1024 * 1024;
|
|
261
|
-
var DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES = 12 * 1024 * 1024 * 1024;
|
|
262
|
-
var DEFAULT_WSL_HOST_MOUNT = "/mnt/c";
|
|
263
305
|
function isWslHost() {
|
|
264
306
|
if (process.platform !== "linux") return false;
|
|
265
307
|
for (const probe of ["/proc/sys/kernel/osrelease", "/proc/version"]) {
|
|
@@ -322,12 +364,18 @@ function observeWslHostDisk(options = {}) {
|
|
|
322
364
|
function summarizeWslRecoverySteps() {
|
|
323
365
|
return "Recovery: 1) free Windows C: (empty Recycle Bin / Storage Sense / clear %TEMP%); 2) shut down WSL (`wsl --shutdown`) then compact the VHDX (`Optimize-VHD` or `diskpart compact vdisk`); 3) clear local node_modules / .next / harness worktrees before restarting workers. Full runbook: docs/runbooks/wsl-disk-pressure.md.";
|
|
324
366
|
}
|
|
367
|
+
var DEFAULT_WSL_HOST_WARN_FREE_BYTES, DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES, DEFAULT_WSL_HOST_MOUNT;
|
|
368
|
+
var init_wsl_host = __esm({
|
|
369
|
+
"src/wsl-host.ts"() {
|
|
370
|
+
"use strict";
|
|
371
|
+
DEFAULT_WSL_HOST_WARN_FREE_BYTES = 25 * 1024 * 1024 * 1024;
|
|
372
|
+
DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES = 12 * 1024 * 1024 * 1024;
|
|
373
|
+
DEFAULT_WSL_HOST_MOUNT = "/mnt/c";
|
|
374
|
+
}
|
|
375
|
+
});
|
|
325
376
|
|
|
326
377
|
// src/disk-gate.ts
|
|
327
|
-
|
|
328
|
-
var DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
|
|
329
|
-
var DEFAULT_MAX_USED_PERCENT = 80;
|
|
330
|
-
var DEFAULT_HARD_MAX_USED_PERCENT = 90;
|
|
378
|
+
import { statfsSync as statfsSync2 } from "node:fs";
|
|
331
379
|
function observeRunnerDiskGate(input = {}) {
|
|
332
380
|
const path24 = input.diskPath?.trim() || "/";
|
|
333
381
|
const warnBelowBytes = input.diskFreeWarnBytes ?? DEFAULT_WARN_FREE_BYTES;
|
|
@@ -369,6 +417,17 @@ function observeRunnerDiskGate(input = {}) {
|
|
|
369
417
|
wslHost
|
|
370
418
|
};
|
|
371
419
|
}
|
|
420
|
+
var DEFAULT_WARN_FREE_BYTES, DEFAULT_CRITICAL_FREE_BYTES, DEFAULT_MAX_USED_PERCENT, DEFAULT_HARD_MAX_USED_PERCENT;
|
|
421
|
+
var init_disk_gate = __esm({
|
|
422
|
+
"src/disk-gate.ts"() {
|
|
423
|
+
"use strict";
|
|
424
|
+
init_wsl_host();
|
|
425
|
+
DEFAULT_WARN_FREE_BYTES = 30 * 1024 * 1024 * 1024;
|
|
426
|
+
DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
|
|
427
|
+
DEFAULT_MAX_USED_PERCENT = 80;
|
|
428
|
+
DEFAULT_HARD_MAX_USED_PERCENT = 90;
|
|
429
|
+
}
|
|
430
|
+
});
|
|
372
431
|
|
|
373
432
|
// src/run-store.ts
|
|
374
433
|
import { existsSync as existsSync3, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
|
|
@@ -416,6 +475,13 @@ function runDirectory(id) {
|
|
|
416
475
|
function runDirectoryAt(harnessRoot, id) {
|
|
417
476
|
return runDir(harnessRunsDir(harnessRoot), safeSlug(id));
|
|
418
477
|
}
|
|
478
|
+
var init_run_store = __esm({
|
|
479
|
+
"src/run-store.ts"() {
|
|
480
|
+
"use strict";
|
|
481
|
+
init_paths();
|
|
482
|
+
init_util();
|
|
483
|
+
}
|
|
484
|
+
});
|
|
419
485
|
|
|
420
486
|
// src/run-worker-index.ts
|
|
421
487
|
import { existsSync as existsSync4, readdirSync as readdirSync3 } from "node:fs";
|
|
@@ -433,9 +499,13 @@ function listRunWorkerNames(run) {
|
|
|
433
499
|
}
|
|
434
500
|
return [...names];
|
|
435
501
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
502
|
+
var init_run_worker_index = __esm({
|
|
503
|
+
"src/run-worker-index.ts"() {
|
|
504
|
+
"use strict";
|
|
505
|
+
init_run_store();
|
|
506
|
+
init_util();
|
|
507
|
+
}
|
|
508
|
+
});
|
|
439
509
|
|
|
440
510
|
// src/heartbeat-final-result.ts
|
|
441
511
|
function tryParseJsonObject(text) {
|
|
@@ -486,9 +556,14 @@ function terminalFinalResultFromHeartbeatRow(row) {
|
|
|
486
556
|
if (embedded) return embedded;
|
|
487
557
|
return summary;
|
|
488
558
|
}
|
|
559
|
+
var init_heartbeat_final_result = __esm({
|
|
560
|
+
"src/heartbeat-final-result.ts"() {
|
|
561
|
+
"use strict";
|
|
562
|
+
}
|
|
563
|
+
});
|
|
489
564
|
|
|
490
565
|
// src/heartbeat.ts
|
|
491
|
-
|
|
566
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
492
567
|
function isTerminalHeartbeatPhase(phase) {
|
|
493
568
|
return phase === "complete";
|
|
494
569
|
}
|
|
@@ -551,29 +626,17 @@ function parseHeartbeat(file) {
|
|
|
551
626
|
}
|
|
552
627
|
return result;
|
|
553
628
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
629
|
+
var HEARTBEAT_FUTURE_SKEW_MS;
|
|
630
|
+
var init_heartbeat = __esm({
|
|
631
|
+
"src/heartbeat.ts"() {
|
|
632
|
+
"use strict";
|
|
633
|
+
init_heartbeat_final_result();
|
|
634
|
+
init_util();
|
|
635
|
+
HEARTBEAT_FUTURE_SKEW_MS = 6e4;
|
|
636
|
+
}
|
|
637
|
+
});
|
|
557
638
|
|
|
558
639
|
// src/repo-search.ts
|
|
559
|
-
var RG_BINARIES = /* @__PURE__ */ new Set(["rg", "ripgrep", "grep"]);
|
|
560
|
-
var RG_OPTS_WITH_VALUE = /* @__PURE__ */ new Set([
|
|
561
|
-
"-e",
|
|
562
|
-
"--regexp",
|
|
563
|
-
"-f",
|
|
564
|
-
"--file",
|
|
565
|
-
"-m",
|
|
566
|
-
"--max-count",
|
|
567
|
-
"-A",
|
|
568
|
-
"--after-context",
|
|
569
|
-
"-B",
|
|
570
|
-
"--before-context",
|
|
571
|
-
"-C",
|
|
572
|
-
"--context",
|
|
573
|
-
"-g",
|
|
574
|
-
"--glob",
|
|
575
|
-
"--iglob"
|
|
576
|
-
]);
|
|
577
640
|
function binaryName(token) {
|
|
578
641
|
if (!token) return null;
|
|
579
642
|
const base = token.split("/").pop() ?? token;
|
|
@@ -772,11 +835,32 @@ function diagnoseRepoSearchFailure(input) {
|
|
|
772
835
|
}
|
|
773
836
|
return null;
|
|
774
837
|
}
|
|
838
|
+
var RG_BINARIES, RG_OPTS_WITH_VALUE;
|
|
839
|
+
var init_repo_search = __esm({
|
|
840
|
+
"src/repo-search.ts"() {
|
|
841
|
+
"use strict";
|
|
842
|
+
RG_BINARIES = /* @__PURE__ */ new Set(["rg", "ripgrep", "grep"]);
|
|
843
|
+
RG_OPTS_WITH_VALUE = /* @__PURE__ */ new Set([
|
|
844
|
+
"-e",
|
|
845
|
+
"--regexp",
|
|
846
|
+
"-f",
|
|
847
|
+
"--file",
|
|
848
|
+
"-m",
|
|
849
|
+
"--max-count",
|
|
850
|
+
"-A",
|
|
851
|
+
"--after-context",
|
|
852
|
+
"-B",
|
|
853
|
+
"--before-context",
|
|
854
|
+
"-C",
|
|
855
|
+
"--context",
|
|
856
|
+
"-g",
|
|
857
|
+
"--glob",
|
|
858
|
+
"--iglob"
|
|
859
|
+
]);
|
|
860
|
+
}
|
|
861
|
+
});
|
|
775
862
|
|
|
776
863
|
// src/shell-command-outcome.ts
|
|
777
|
-
var NPM_AUDIT_RE = /\bnpm\s+audit\b/i;
|
|
778
|
-
var RG_CMD_RE = /\b(rg|ripgrep)\b/i;
|
|
779
|
-
var RG_REAL_ERROR_RE = /\b(error|invalid|unknown|panic|not found)\b/i;
|
|
780
864
|
function tidy(text, max = 200) {
|
|
781
865
|
const one = text.replace(/\s+/g, " ").trim();
|
|
782
866
|
return one.length > max ? `${one.slice(0, max - 1)}\u2026` : one;
|
|
@@ -980,8 +1064,19 @@ function classifyShellCommandOutcome(input) {
|
|
|
980
1064
|
summary: `command failed (exit ${input.exitCode}): ${tail}`
|
|
981
1065
|
};
|
|
982
1066
|
}
|
|
1067
|
+
var NPM_AUDIT_RE, RG_CMD_RE, RG_REAL_ERROR_RE;
|
|
1068
|
+
var init_shell_command_outcome = __esm({
|
|
1069
|
+
"src/shell-command-outcome.ts"() {
|
|
1070
|
+
"use strict";
|
|
1071
|
+
init_repo_search();
|
|
1072
|
+
NPM_AUDIT_RE = /\bnpm\s+audit\b/i;
|
|
1073
|
+
RG_CMD_RE = /\b(rg|ripgrep)\b/i;
|
|
1074
|
+
RG_REAL_ERROR_RE = /\b(error|invalid|unknown|panic|not found)\b/i;
|
|
1075
|
+
}
|
|
1076
|
+
});
|
|
983
1077
|
|
|
984
1078
|
// src/stream.ts
|
|
1079
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "node:fs";
|
|
985
1080
|
function eventTimestampIso(event) {
|
|
986
1081
|
const tsMs = event.timestamp_ms;
|
|
987
1082
|
return event.timestamp || event.ts || (tsMs ? new Date(tsMs).toISOString() : void 0);
|
|
@@ -1082,38 +1177,15 @@ function parseHarnessStream(file) {
|
|
|
1082
1177
|
}
|
|
1083
1178
|
return result;
|
|
1084
1179
|
}
|
|
1180
|
+
var init_stream = __esm({
|
|
1181
|
+
"src/stream.ts"() {
|
|
1182
|
+
"use strict";
|
|
1183
|
+
init_shell_command_outcome();
|
|
1184
|
+
init_util();
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1085
1187
|
|
|
1086
1188
|
// src/exit-classify.ts
|
|
1087
|
-
var FAILURE_PATTERNS = [
|
|
1088
|
-
{
|
|
1089
|
-
test: /\b(?:invalid|unknown|unsupported|unrecognized)\b[^.\n]*\bmodel\b/i,
|
|
1090
|
-
label: "provider rejected the requested model"
|
|
1091
|
-
},
|
|
1092
|
-
{
|
|
1093
|
-
test: /\bmodel\b[^.\n]*\b(?:not\s+(?:found|supported|available|recognized|valid)|is\s+not\s+valid|does\s+not\s+exist)/i,
|
|
1094
|
-
label: "provider rejected the requested model"
|
|
1095
|
-
},
|
|
1096
|
-
{
|
|
1097
|
-
test: /\b(?:did you mean|available models|choose (?:a|one of)|supported models)\b/i,
|
|
1098
|
-
label: "provider rejected the requested model"
|
|
1099
|
-
},
|
|
1100
|
-
{
|
|
1101
|
-
test: /model preflight failed/i,
|
|
1102
|
-
label: "model/provider preflight failed"
|
|
1103
|
-
},
|
|
1104
|
-
{
|
|
1105
|
-
test: /\b(?:command not found|ENOENT|is the .*CLI on PATH|executable not found|no such file or directory)\b/i,
|
|
1106
|
-
label: "provider CLI is missing or not on PATH"
|
|
1107
|
-
},
|
|
1108
|
-
{
|
|
1109
|
-
test: /\bfailed to spawn\b/i,
|
|
1110
|
-
label: "provider failed to spawn the worker process"
|
|
1111
|
-
},
|
|
1112
|
-
{
|
|
1113
|
-
test: /\b(?:not logged in|unauthorized|authentication (?:failed|required)|invalid api key|missing api key|401)\b/i,
|
|
1114
|
-
label: "provider authentication failed"
|
|
1115
|
-
}
|
|
1116
|
-
];
|
|
1117
1189
|
function tidy2(errorText, max = 240) {
|
|
1118
1190
|
const oneLine2 = errorText.replace(/\s+/g, " ").trim();
|
|
1119
1191
|
return oneLine2.length > max ? `${oneLine2.slice(0, max - 1)}\u2026` : oneLine2;
|
|
@@ -1128,6 +1200,42 @@ function classifyExitFailure(errorText) {
|
|
|
1128
1200
|
}
|
|
1129
1201
|
return null;
|
|
1130
1202
|
}
|
|
1203
|
+
var FAILURE_PATTERNS;
|
|
1204
|
+
var init_exit_classify = __esm({
|
|
1205
|
+
"src/exit-classify.ts"() {
|
|
1206
|
+
"use strict";
|
|
1207
|
+
FAILURE_PATTERNS = [
|
|
1208
|
+
{
|
|
1209
|
+
test: /\b(?:invalid|unknown|unsupported|unrecognized)\b[^.\n]*\bmodel\b/i,
|
|
1210
|
+
label: "provider rejected the requested model"
|
|
1211
|
+
},
|
|
1212
|
+
{
|
|
1213
|
+
test: /\bmodel\b[^.\n]*\b(?:not\s+(?:found|supported|available|recognized|valid)|is\s+not\s+valid|does\s+not\s+exist)/i,
|
|
1214
|
+
label: "provider rejected the requested model"
|
|
1215
|
+
},
|
|
1216
|
+
{
|
|
1217
|
+
test: /\b(?:did you mean|available models|choose (?:a|one of)|supported models)\b/i,
|
|
1218
|
+
label: "provider rejected the requested model"
|
|
1219
|
+
},
|
|
1220
|
+
{
|
|
1221
|
+
test: /model preflight failed/i,
|
|
1222
|
+
label: "model/provider preflight failed"
|
|
1223
|
+
},
|
|
1224
|
+
{
|
|
1225
|
+
test: /\b(?:command not found|ENOENT|is the .*CLI on PATH|executable not found|no such file or directory)\b/i,
|
|
1226
|
+
label: "provider CLI is missing or not on PATH"
|
|
1227
|
+
},
|
|
1228
|
+
{
|
|
1229
|
+
test: /\bfailed to spawn\b/i,
|
|
1230
|
+
label: "provider failed to spawn the worker process"
|
|
1231
|
+
},
|
|
1232
|
+
{
|
|
1233
|
+
test: /\b(?:not logged in|unauthorized|authentication (?:failed|required)|invalid api key|missing api key|401)\b/i,
|
|
1234
|
+
label: "provider authentication failed"
|
|
1235
|
+
}
|
|
1236
|
+
];
|
|
1237
|
+
}
|
|
1238
|
+
});
|
|
1131
1239
|
|
|
1132
1240
|
// src/exited-salvage.ts
|
|
1133
1241
|
function trimOrNull(value) {
|
|
@@ -1186,6 +1294,11 @@ function assessExitedWorkerSalvage(input) {
|
|
|
1186
1294
|
attentionReason: buildAttentionReason(kind, uncommittedCount, headCommit)
|
|
1187
1295
|
};
|
|
1188
1296
|
}
|
|
1297
|
+
var init_exited_salvage = __esm({
|
|
1298
|
+
"src/exited-salvage.ts"() {
|
|
1299
|
+
"use strict";
|
|
1300
|
+
}
|
|
1301
|
+
});
|
|
1189
1302
|
|
|
1190
1303
|
// src/landing-gate.ts
|
|
1191
1304
|
function trimOrNull2(value) {
|
|
@@ -1231,6 +1344,11 @@ function landingAttentionReason(verdict) {
|
|
|
1231
1344
|
if (!verdict.blocked) return void 0;
|
|
1232
1345
|
return verdict.detail ?? verdict.reason ?? "dirty_worktree_no_pr";
|
|
1233
1346
|
}
|
|
1347
|
+
var init_landing_gate = __esm({
|
|
1348
|
+
"src/landing-gate.ts"() {
|
|
1349
|
+
"use strict";
|
|
1350
|
+
}
|
|
1351
|
+
});
|
|
1234
1352
|
|
|
1235
1353
|
// src/worker-final-result-embed.ts
|
|
1236
1354
|
function tryParseJsonObject2(text) {
|
|
@@ -1280,6 +1398,11 @@ function extractEmbeddedWorkerFinalResultRecord(value) {
|
|
|
1280
1398
|
}
|
|
1281
1399
|
return best;
|
|
1282
1400
|
}
|
|
1401
|
+
var init_worker_final_result_embed = __esm({
|
|
1402
|
+
"src/worker-final-result-embed.ts"() {
|
|
1403
|
+
"use strict";
|
|
1404
|
+
}
|
|
1405
|
+
});
|
|
1283
1406
|
|
|
1284
1407
|
// src/landing-contract-gate.ts
|
|
1285
1408
|
function trimOrNull3(value) {
|
|
@@ -1439,10 +1562,14 @@ function landingContractAttentionReason(verdict) {
|
|
|
1439
1562
|
if (!verdict.blocked) return void 0;
|
|
1440
1563
|
return verdict.detail ?? verdict.reason;
|
|
1441
1564
|
}
|
|
1565
|
+
var init_landing_contract_gate = __esm({
|
|
1566
|
+
"src/landing-contract-gate.ts"() {
|
|
1567
|
+
"use strict";
|
|
1568
|
+
init_worker_final_result_embed();
|
|
1569
|
+
}
|
|
1570
|
+
});
|
|
1442
1571
|
|
|
1443
1572
|
// src/status.ts
|
|
1444
|
-
var NO_START_MS = 18e4;
|
|
1445
|
-
var STALE_MS = 6e5;
|
|
1446
1573
|
function computeAttention(input) {
|
|
1447
1574
|
const now = Date.now();
|
|
1448
1575
|
if (input.completionBlocker && !isSkippedTerminalCompletionBlocker(input.completionBlocker)) {
|
|
@@ -1634,7 +1761,15 @@ function computeWorkerStatus(worker, options = {}) {
|
|
|
1634
1761
|
changedFiles,
|
|
1635
1762
|
gitAncestry,
|
|
1636
1763
|
instructionPolicyFingerprint: worker.instructionPolicyFingerprint ?? null,
|
|
1637
|
-
instructionPolicyEvidence: worker.instructionPolicyEvidence ?? null
|
|
1764
|
+
instructionPolicyEvidence: worker.instructionPolicyEvidence ?? null,
|
|
1765
|
+
model: worker.model ?? worker.orchestrationAudit?.model ?? null,
|
|
1766
|
+
provider: worker.orchestrationAudit?.provider ?? null,
|
|
1767
|
+
boxKind: worker.boxKind ?? null,
|
|
1768
|
+
boxId: worker.boxId ?? null,
|
|
1769
|
+
runtimeId: worker.runtimeId ?? null,
|
|
1770
|
+
personaSlug: worker.personaSlug ?? null,
|
|
1771
|
+
dispatched: worker.dispatched ?? null,
|
|
1772
|
+
localOnly: worker.localOnly ?? null
|
|
1638
1773
|
};
|
|
1639
1774
|
}
|
|
1640
1775
|
function isFinishedWorkerStatus(status) {
|
|
@@ -1647,15 +1782,63 @@ function isLandingBlockedWorkerStatus(status) {
|
|
|
1647
1782
|
if (!status.finalResult) return false;
|
|
1648
1783
|
return status.attention.state === "needs_attention" || status.attention.state === "blocked";
|
|
1649
1784
|
}
|
|
1785
|
+
var NO_START_MS, STALE_MS;
|
|
1786
|
+
var init_status = __esm({
|
|
1787
|
+
"src/status.ts"() {
|
|
1788
|
+
"use strict";
|
|
1789
|
+
init_heartbeat();
|
|
1790
|
+
init_stream();
|
|
1791
|
+
init_exit_classify();
|
|
1792
|
+
init_exited_salvage();
|
|
1793
|
+
init_git();
|
|
1794
|
+
init_landing_gate();
|
|
1795
|
+
init_landing_contract_gate();
|
|
1796
|
+
init_worker_final_result_embed();
|
|
1797
|
+
init_util();
|
|
1798
|
+
NO_START_MS = 18e4;
|
|
1799
|
+
STALE_MS = 6e5;
|
|
1800
|
+
}
|
|
1801
|
+
});
|
|
1802
|
+
|
|
1803
|
+
// src/harness-worker-active.ts
|
|
1804
|
+
var init_harness_worker_active = __esm({
|
|
1805
|
+
"src/harness-worker-active.ts"() {
|
|
1806
|
+
"use strict";
|
|
1807
|
+
init_status();
|
|
1808
|
+
}
|
|
1809
|
+
});
|
|
1650
1810
|
|
|
1651
1811
|
// src/resource-gate.ts
|
|
1652
|
-
var DEFAULT_PER_WORKER_MEM_BYTES
|
|
1653
|
-
var
|
|
1812
|
+
var DEFAULT_PER_WORKER_MEM_BYTES, DEFAULT_MEM_RESERVE_BYTES;
|
|
1813
|
+
var init_resource_gate = __esm({
|
|
1814
|
+
"src/resource-gate.ts"() {
|
|
1815
|
+
"use strict";
|
|
1816
|
+
init_meminfo();
|
|
1817
|
+
init_config();
|
|
1818
|
+
init_box_identity();
|
|
1819
|
+
init_worker_cap_source();
|
|
1820
|
+
init_disk_gate();
|
|
1821
|
+
init_run_store();
|
|
1822
|
+
init_run_worker_index();
|
|
1823
|
+
init_harness_worker_active();
|
|
1824
|
+
init_util();
|
|
1825
|
+
DEFAULT_PER_WORKER_MEM_BYTES = 500 * 1024 * 1024;
|
|
1826
|
+
DEFAULT_MEM_RESERVE_BYTES = 4 * 1024 * 1024 * 1024;
|
|
1827
|
+
}
|
|
1828
|
+
});
|
|
1829
|
+
|
|
1830
|
+
// src/worker-cap-source.ts
|
|
1831
|
+
var init_worker_cap_source = __esm({
|
|
1832
|
+
"src/worker-cap-source.ts"() {
|
|
1833
|
+
"use strict";
|
|
1834
|
+
init_resource_gate();
|
|
1835
|
+
}
|
|
1836
|
+
});
|
|
1654
1837
|
|
|
1655
1838
|
// src/config.ts
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1839
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1840
|
+
import { homedir as homedir2, totalmem } from "node:os";
|
|
1841
|
+
import path5 from "node:path";
|
|
1659
1842
|
function loadUserConfig() {
|
|
1660
1843
|
if (!existsSync7(CONFIG_FILE)) return {};
|
|
1661
1844
|
try {
|
|
@@ -1664,12 +1847,28 @@ function loadUserConfig() {
|
|
|
1664
1847
|
return {};
|
|
1665
1848
|
}
|
|
1666
1849
|
}
|
|
1667
|
-
var
|
|
1668
|
-
var
|
|
1850
|
+
var CONFIG_DIR, CONFIG_FILE, CREDENTIALS_FILE, SETUP_PER_WORKER_MEM_BYTES, SETUP_MEM_RESERVE_BYTES;
|
|
1851
|
+
var init_config = __esm({
|
|
1852
|
+
"src/config.ts"() {
|
|
1853
|
+
"use strict";
|
|
1854
|
+
init_default_repo_discovery();
|
|
1855
|
+
init_path_values();
|
|
1856
|
+
init_util();
|
|
1857
|
+
init_box_identity();
|
|
1858
|
+
init_worker_cap_source();
|
|
1859
|
+
init_disk_gate();
|
|
1860
|
+
CONFIG_DIR = path5.join(homedir2(), ".kynver");
|
|
1861
|
+
CONFIG_FILE = path5.join(CONFIG_DIR, "config.json");
|
|
1862
|
+
CREDENTIALS_FILE = path5.join(CONFIG_DIR, "credentials");
|
|
1863
|
+
SETUP_PER_WORKER_MEM_BYTES = 500 * 1024 * 1024;
|
|
1864
|
+
SETUP_MEM_RESERVE_BYTES = 4 * 1024 * 1024 * 1024;
|
|
1865
|
+
}
|
|
1866
|
+
});
|
|
1669
1867
|
|
|
1670
1868
|
// src/paths.ts
|
|
1671
|
-
|
|
1672
|
-
|
|
1869
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
1870
|
+
import { homedir as homedir3 } from "node:os";
|
|
1871
|
+
import path6 from "node:path";
|
|
1673
1872
|
function normalizeHarnessRoot(root) {
|
|
1674
1873
|
let resolved = path6.resolve(resolveUserPath(root.trim()));
|
|
1675
1874
|
while (HARNESS_LAYOUT_DIR_NAMES.has(path6.basename(resolved))) {
|
|
@@ -1704,10 +1903,30 @@ function getHarnessPaths() {
|
|
|
1704
1903
|
function runDir(runsDir, id) {
|
|
1705
1904
|
return path6.join(runsDir, safeSlug(id));
|
|
1706
1905
|
}
|
|
1906
|
+
var LEGACY_ROOT, HARNESS_LAYOUT_DIR_NAMES;
|
|
1907
|
+
var init_paths = __esm({
|
|
1908
|
+
"src/paths.ts"() {
|
|
1909
|
+
"use strict";
|
|
1910
|
+
init_config();
|
|
1911
|
+
init_path_values();
|
|
1912
|
+
init_util();
|
|
1913
|
+
LEGACY_ROOT = path6.join(homedir3(), ".openclaw", "harness");
|
|
1914
|
+
HARNESS_LAYOUT_DIR_NAMES = /* @__PURE__ */ new Set(["runs", "worktrees"]);
|
|
1915
|
+
}
|
|
1916
|
+
});
|
|
1917
|
+
|
|
1918
|
+
// src/cleanup.ts
|
|
1919
|
+
init_paths();
|
|
1920
|
+
import path23 from "node:path";
|
|
1707
1921
|
|
|
1708
1922
|
// src/cleanup-guards.ts
|
|
1923
|
+
init_landing_gate();
|
|
1709
1924
|
import path8 from "node:path";
|
|
1710
1925
|
|
|
1926
|
+
// src/cleanup-index-status.ts
|
|
1927
|
+
init_git();
|
|
1928
|
+
init_status();
|
|
1929
|
+
|
|
1711
1930
|
// src/cleanup-build-cache-paths.ts
|
|
1712
1931
|
var HARNESS_BUILD_CACHE_RELATIVE_PATHS = [
|
|
1713
1932
|
".next",
|
|
@@ -1735,7 +1954,34 @@ function materialWorktreeChanges(changedFiles) {
|
|
|
1735
1954
|
});
|
|
1736
1955
|
}
|
|
1737
1956
|
|
|
1957
|
+
// src/cleanup-worktree-salvage.ts
|
|
1958
|
+
function prUrlFromFinalResult(finalResult) {
|
|
1959
|
+
if (typeof finalResult === "string") {
|
|
1960
|
+
const match = finalResult.match(/https:\/\/github\.com\/[^\s]+\/pull\/\d+/i);
|
|
1961
|
+
return match?.[0] ?? null;
|
|
1962
|
+
}
|
|
1963
|
+
if (finalResult && typeof finalResult === "object") {
|
|
1964
|
+
const obj = finalResult;
|
|
1965
|
+
for (const key of ["prUrl", "pr_url", "pullRequestUrl"]) {
|
|
1966
|
+
const value = obj[key];
|
|
1967
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
return null;
|
|
1971
|
+
}
|
|
1972
|
+
function isPrOrUnmergedWork(status) {
|
|
1973
|
+
const relation = status.gitAncestry?.relation;
|
|
1974
|
+
if (relation === "merged" || relation === "synced") {
|
|
1975
|
+
return materialWorktreeChanges(status.changedFiles).length > 0;
|
|
1976
|
+
}
|
|
1977
|
+
if (prUrlFromFinalResult(status.finalResult)) return true;
|
|
1978
|
+
if (relation === "ahead" || relation === "diverged") return true;
|
|
1979
|
+
if (status.changedFiles.length > 0 && status.finalResult) return true;
|
|
1980
|
+
return false;
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1738
1983
|
// src/cleanup-index-status.ts
|
|
1984
|
+
init_util();
|
|
1739
1985
|
function indexedWorktreeStatus(entry) {
|
|
1740
1986
|
if (!entry.status) {
|
|
1741
1987
|
entry.status = computeWorkerStatus(entry.worker, {
|
|
@@ -1745,14 +1991,81 @@ function indexedWorktreeStatus(entry) {
|
|
|
1745
1991
|
}
|
|
1746
1992
|
return entry.status;
|
|
1747
1993
|
}
|
|
1748
|
-
function indexedWorktreeHasMaterialChanges(entry) {
|
|
1994
|
+
function indexedWorktreeHasMaterialChanges(entry, gitStatusCache) {
|
|
1749
1995
|
if (entry.status) {
|
|
1750
1996
|
return materialWorktreeChanges(entry.status.changedFiles).length > 0;
|
|
1751
1997
|
}
|
|
1752
|
-
|
|
1998
|
+
const porcelain = gitStatusCache ? gitStatusCache.porcelain(entry.worktreePath) : gitStatusShort(entry.worktreePath);
|
|
1999
|
+
return materialWorktreeChanges(porcelain).length > 0;
|
|
2000
|
+
}
|
|
2001
|
+
function finalResultFromWorkerJson(entry) {
|
|
2002
|
+
const snapshot = entry.worker.completionSnapshot?.finalResult;
|
|
2003
|
+
if (snapshot !== void 0 && snapshot !== null) return snapshot;
|
|
2004
|
+
if (entry.worker.taskPrUrl) {
|
|
2005
|
+
return { prUrl: entry.worker.taskPrUrl };
|
|
2006
|
+
}
|
|
2007
|
+
return null;
|
|
2008
|
+
}
|
|
2009
|
+
function resolveWorktreeGuardStatus(entry, ctx) {
|
|
2010
|
+
if (entry.status) return entry.status;
|
|
2011
|
+
const worker = entry.worker;
|
|
2012
|
+
const completionAcknowledged = typeof worker.completionReportedAt === "string" && worker.completionReportedAt.trim().length > 0;
|
|
2013
|
+
const workerJsonTerminal = Boolean(worker.status && ["done", "exited", "blocked", "failed", "abandoned"].includes(worker.status)) || completionAcknowledged;
|
|
2014
|
+
const finalResult = finalResultFromWorkerJson(entry);
|
|
2015
|
+
if (workerJsonTerminal && !isPidAlive(worker.pid)) {
|
|
2016
|
+
const changedFiles = ctx?.gitStatusCache ? ctx.gitStatusCache.porcelain(entry.worktreePath) : gitStatusShort(entry.worktreePath);
|
|
2017
|
+
const baseLabel = entry.run.baseCommit?.trim() || entry.run.base?.trim() || "origin/main";
|
|
2018
|
+
const ahead = ctx?.gitRevCache?.countAheadOfMain(entry.worktreePath, baseLabel);
|
|
2019
|
+
const gitAncestry = ahead === 0 ? {
|
|
2020
|
+
checked: true,
|
|
2021
|
+
base: baseLabel,
|
|
2022
|
+
relation: "synced"
|
|
2023
|
+
} : computeGitAncestry(entry.worktreePath, {
|
|
2024
|
+
base: entry.run.base,
|
|
2025
|
+
baseCommit: entry.run.baseCommit
|
|
2026
|
+
});
|
|
2027
|
+
const status = {
|
|
2028
|
+
runId: entry.runId,
|
|
2029
|
+
worker: entry.workerName,
|
|
2030
|
+
pid: worker.pid,
|
|
2031
|
+
alive: false,
|
|
2032
|
+
status: worker.status ?? (completionAcknowledged ? "done" : "exited"),
|
|
2033
|
+
attention: { state: completionAcknowledged ? "done" : "stale" },
|
|
2034
|
+
branch: worker.branch,
|
|
2035
|
+
worktreePath: entry.worktreePath,
|
|
2036
|
+
ownedPaths: worker.ownedPaths,
|
|
2037
|
+
stdoutBytes: 0,
|
|
2038
|
+
stderrBytes: 0,
|
|
2039
|
+
heartbeatBytes: 0,
|
|
2040
|
+
firstEventAt: null,
|
|
2041
|
+
lastEventAt: null,
|
|
2042
|
+
lastActivityAt: worker.completionReportedAt ?? null,
|
|
2043
|
+
currentTool: null,
|
|
2044
|
+
heartbeatCount: 0,
|
|
2045
|
+
lastHeartbeatAt: null,
|
|
2046
|
+
lastHeartbeatPhase: null,
|
|
2047
|
+
lastHeartbeatSummary: null,
|
|
2048
|
+
heartbeatBlocker: null,
|
|
2049
|
+
changedFiles,
|
|
2050
|
+
gitAncestry,
|
|
2051
|
+
finalResult,
|
|
2052
|
+
completionBlocker: typeof worker.completionBlocker === "string" ? worker.completionBlocker.trim() || null : null,
|
|
2053
|
+
prUrl: worker.repairTargetPrUrl ?? worker.taskPrUrl ?? prUrlFromFinalResult(finalResult)
|
|
2054
|
+
};
|
|
2055
|
+
entry.status = status;
|
|
2056
|
+
return status;
|
|
2057
|
+
}
|
|
2058
|
+
return indexedWorktreeStatus(entry);
|
|
1753
2059
|
}
|
|
1754
2060
|
|
|
2061
|
+
// src/cleanup-guards.ts
|
|
2062
|
+
init_status();
|
|
2063
|
+
|
|
1755
2064
|
// src/finalize.ts
|
|
2065
|
+
init_run_store();
|
|
2066
|
+
init_run_worker_index();
|
|
2067
|
+
init_status();
|
|
2068
|
+
init_util();
|
|
1756
2069
|
import path7 from "node:path";
|
|
1757
2070
|
var ACTIVE_RUN_STATUSES = /* @__PURE__ */ new Set([
|
|
1758
2071
|
"running",
|
|
@@ -1810,33 +2123,12 @@ function finalizeStaleRuns() {
|
|
|
1810
2123
|
return finalized;
|
|
1811
2124
|
}
|
|
1812
2125
|
|
|
1813
|
-
// src/cleanup-
|
|
1814
|
-
|
|
1815
|
-
if (typeof finalResult === "string") {
|
|
1816
|
-
const match = finalResult.match(/https:\/\/github\.com\/[^\s]+\/pull\/\d+/i);
|
|
1817
|
-
return match?.[0] ?? null;
|
|
1818
|
-
}
|
|
1819
|
-
if (finalResult && typeof finalResult === "object") {
|
|
1820
|
-
const obj = finalResult;
|
|
1821
|
-
for (const key of ["prUrl", "pr_url", "pullRequestUrl"]) {
|
|
1822
|
-
const value = obj[key];
|
|
1823
|
-
if (typeof value === "string" && value.trim()) return value.trim();
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
return null;
|
|
1827
|
-
}
|
|
1828
|
-
function isPrOrUnmergedWork(status) {
|
|
1829
|
-
const relation = status.gitAncestry?.relation;
|
|
1830
|
-
if (relation === "merged" || relation === "synced") {
|
|
1831
|
-
return materialWorktreeChanges(status.changedFiles).length > 0;
|
|
1832
|
-
}
|
|
1833
|
-
if (prUrlFromFinalResult(status.finalResult)) return true;
|
|
1834
|
-
if (relation === "ahead" || relation === "diverged") return true;
|
|
1835
|
-
if (status.changedFiles.length > 0 && status.finalResult) return true;
|
|
1836
|
-
return false;
|
|
1837
|
-
}
|
|
2126
|
+
// src/cleanup-run-liveness.ts
|
|
2127
|
+
init_status();
|
|
1838
2128
|
|
|
1839
2129
|
// src/cleanup-completion-blocker.ts
|
|
2130
|
+
init_landing_gate();
|
|
2131
|
+
init_status();
|
|
1840
2132
|
function completionBlockerBlocksWorktreeRemoval(indexed, status) {
|
|
1841
2133
|
const blocker = typeof indexed.worker.completionBlocker === "string" ? indexed.worker.completionBlocker.trim() : "";
|
|
1842
2134
|
if (!blocker) return false;
|
|
@@ -1856,13 +2148,29 @@ function completionBlockerBlocksWorktreeRemoval(indexed, status) {
|
|
|
1856
2148
|
}
|
|
1857
2149
|
|
|
1858
2150
|
// src/cleanup-run-liveness.ts
|
|
2151
|
+
init_util();
|
|
2152
|
+
var TERMINAL_WORKER_JSON_STATUSES = /* @__PURE__ */ new Set([
|
|
2153
|
+
"done",
|
|
2154
|
+
"exited",
|
|
2155
|
+
"blocked",
|
|
2156
|
+
"failed",
|
|
2157
|
+
"abandoned"
|
|
2158
|
+
]);
|
|
1859
2159
|
function deriveRunTerminal(indexed, ctx) {
|
|
1860
2160
|
if (ctx) return ctx.runTerminalCache.derive(indexed.run);
|
|
1861
2161
|
return deriveTerminalRunStatus(indexed.run);
|
|
1862
2162
|
}
|
|
1863
2163
|
function isWorkerProcessLive(indexed) {
|
|
1864
2164
|
if (isPidAlive(indexed.worker.pid)) return true;
|
|
1865
|
-
if (
|
|
2165
|
+
if (typeof indexed.worker.completionReportedAt === "string" && indexed.worker.completionReportedAt.trim().length > 0) {
|
|
2166
|
+
return false;
|
|
2167
|
+
}
|
|
2168
|
+
const workerStatus = indexed.worker.status;
|
|
2169
|
+
if (workerStatus && TERMINAL_WORKER_JSON_STATUSES.has(workerStatus)) return false;
|
|
2170
|
+
if (!indexed.worker.pid) {
|
|
2171
|
+
if (workerStatus !== "running") return false;
|
|
2172
|
+
return indexedWorktreeStatus(indexed).alive;
|
|
2173
|
+
}
|
|
1866
2174
|
return false;
|
|
1867
2175
|
}
|
|
1868
2176
|
function isRunStaleActive(indexed, ctx) {
|
|
@@ -1871,6 +2179,10 @@ function isRunStaleActive(indexed, ctx) {
|
|
|
1871
2179
|
}
|
|
1872
2180
|
function runBlocksWorktreeRemoval(indexed, ctx) {
|
|
1873
2181
|
if (isWorkerProcessLive(indexed)) return true;
|
|
2182
|
+
const workerStatus = indexed.worker.status;
|
|
2183
|
+
if (workerStatus && TERMINAL_WORKER_JSON_STATUSES.has(workerStatus) && !indexed.worker.completionBlocker) {
|
|
2184
|
+
return false;
|
|
2185
|
+
}
|
|
1874
2186
|
const status = indexedWorktreeStatus(indexed);
|
|
1875
2187
|
if (completionBlockerBlocksWorktreeRemoval(indexed, status)) return true;
|
|
1876
2188
|
if (isFinishedWorkerStatus(status)) return false;
|
|
@@ -1889,7 +2201,7 @@ function effectiveWorktreeAgeMs(input) {
|
|
|
1889
2201
|
if (input.liveness && isRunStaleActive(indexed, input.liveness)) {
|
|
1890
2202
|
return terminalWorktreesAgeMs;
|
|
1891
2203
|
}
|
|
1892
|
-
if (input.liveness && isFinishedWorkerStatus(
|
|
2204
|
+
if (input.liveness && isFinishedWorkerStatus(resolveWorktreeGuardStatus(indexed, input.liveness)) && !isWorkerProcessLive(indexed)) {
|
|
1893
2205
|
return terminalWorktreesAgeMs;
|
|
1894
2206
|
}
|
|
1895
2207
|
return worktreesAgeMs;
|
|
@@ -1903,8 +2215,13 @@ function skipWorktreeRemoval(input) {
|
|
|
1903
2215
|
const ageThresholdMs = effectiveWorktreeAgeMs(input);
|
|
1904
2216
|
if (worktreesAgeMs <= 0 && !includeOrphans && ageThresholdMs <= 0) return "worktrees_disabled";
|
|
1905
2217
|
if (ageThresholdMs > 0 && ageMs < ageThresholdMs) return "below_age_threshold";
|
|
1906
|
-
const status = indexedWorktreeStatus(indexed);
|
|
1907
2218
|
if (isWorkerProcessLive(indexed)) return "active_worker";
|
|
2219
|
+
if (indexedWorktreeHasMaterialChanges(indexed, input.liveness?.gitStatusCache)) {
|
|
2220
|
+
return "dirty_worktree";
|
|
2221
|
+
}
|
|
2222
|
+
const ahead = input.liveness?.gitRevCache?.countAheadOfMain(input.worktreePath);
|
|
2223
|
+
if (ahead !== null && ahead !== void 0 && ahead > 0) return "pr_or_unmerged_commits";
|
|
2224
|
+
const status = resolveWorktreeGuardStatus(indexed, input.liveness);
|
|
1908
2225
|
if (completionBlockerBlocksWorktreeRemoval(indexed, status)) return "completion_blocked";
|
|
1909
2226
|
if (runBlocksWorktreeRemoval(indexed, input.liveness)) return "run_still_active";
|
|
1910
2227
|
if (!isFinishedWorkerStatus(status)) return "run_still_active";
|
|
@@ -1935,7 +2252,9 @@ function skipDependencyCacheRemoval(input) {
|
|
|
1935
2252
|
if (!diskPressure && ageMs < nodeModulesAgeMs) return "below_age_threshold";
|
|
1936
2253
|
if (activeWorktreePaths.has(path8.resolve(worktreePath))) return "active_worker";
|
|
1937
2254
|
if (indexed && isWorkerProcessLive(indexed)) return "active_worker";
|
|
1938
|
-
if (indexed && indexedWorktreeHasMaterialChanges(indexed))
|
|
2255
|
+
if (indexed && indexedWorktreeHasMaterialChanges(indexed, input.gitStatusCache)) {
|
|
2256
|
+
return "dirty_worktree";
|
|
2257
|
+
}
|
|
1939
2258
|
return null;
|
|
1940
2259
|
}
|
|
1941
2260
|
function skipBuildCacheRemoval(input) {
|
|
@@ -1983,6 +2302,8 @@ import { existsSync as existsSync11, readdirSync as readdirSync6, statSync as st
|
|
|
1983
2302
|
import path12 from "node:path";
|
|
1984
2303
|
|
|
1985
2304
|
// src/cleanup-active-worktrees.ts
|
|
2305
|
+
init_run_store();
|
|
2306
|
+
init_paths();
|
|
1986
2307
|
import { existsSync as existsSync10, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
|
|
1987
2308
|
import path11 from "node:path";
|
|
1988
2309
|
|
|
@@ -1990,7 +2311,19 @@ import path11 from "node:path";
|
|
|
1990
2311
|
import { existsSync as existsSync9, readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
|
|
1991
2312
|
import path10 from "node:path";
|
|
1992
2313
|
|
|
2314
|
+
// src/default-repo.ts
|
|
2315
|
+
init_config();
|
|
2316
|
+
init_default_repo_discovery();
|
|
2317
|
+
init_path_values();
|
|
2318
|
+
|
|
2319
|
+
// src/run-metadata-retention.ts
|
|
2320
|
+
init_heartbeat();
|
|
2321
|
+
init_paths();
|
|
2322
|
+
init_run_store();
|
|
2323
|
+
|
|
1993
2324
|
// src/worker-metadata-paths.ts
|
|
2325
|
+
init_paths();
|
|
2326
|
+
init_util();
|
|
1994
2327
|
import path9 from "node:path";
|
|
1995
2328
|
var NESTED_RUNS = `${path9.sep}runs${path9.sep}runs${path9.sep}`;
|
|
1996
2329
|
function workerArtifactPaths(workerDir) {
|
|
@@ -2004,6 +2337,7 @@ function workerArtifactPaths(workerDir) {
|
|
|
2004
2337
|
}
|
|
2005
2338
|
|
|
2006
2339
|
// src/run-metadata-retention.ts
|
|
2340
|
+
init_util();
|
|
2007
2341
|
var RUN_METADATA_ACTIVE_SIGNAL_MS = 15 * 60 * 1e3;
|
|
2008
2342
|
function isHarnessRunMetadataPath(targetPath, harnessRoot) {
|
|
2009
2343
|
const resolved = path10.resolve(targetPath);
|
|
@@ -2075,6 +2409,7 @@ function collectFilesystemLiveRunKeys(harnessRoot, now = Date.now()) {
|
|
|
2075
2409
|
}
|
|
2076
2410
|
|
|
2077
2411
|
// src/cleanup-active-worktrees.ts
|
|
2412
|
+
init_util();
|
|
2078
2413
|
function workerHasRecentHarnessActivity(worker, now) {
|
|
2079
2414
|
const paths = [worker.heartbeatPath, worker.stdoutPath, worker.stderrPath];
|
|
2080
2415
|
for (const target of paths) {
|
|
@@ -2123,6 +2458,7 @@ function isWorktreeOnLiveRun(worktreePath, harnessRoot, runId, liveRunKeys) {
|
|
|
2123
2458
|
}
|
|
2124
2459
|
|
|
2125
2460
|
// src/cleanup-run-directory.ts
|
|
2461
|
+
init_util();
|
|
2126
2462
|
function pathAgeMs(target, now) {
|
|
2127
2463
|
try {
|
|
2128
2464
|
const mtime = statSync5(target).mtimeMs;
|
|
@@ -2185,6 +2521,7 @@ function scanStaleRunDirectoryCandidates(opts) {
|
|
|
2185
2521
|
}
|
|
2186
2522
|
|
|
2187
2523
|
// src/cleanup-execute.ts
|
|
2524
|
+
init_git();
|
|
2188
2525
|
import { existsSync as existsSync14, rmSync as rmSync2 } from "node:fs";
|
|
2189
2526
|
|
|
2190
2527
|
// src/cleanup-dir-size.ts
|
|
@@ -2240,6 +2577,7 @@ function directorySizeBytes(root, maxEntries = 5e4) {
|
|
|
2240
2577
|
|
|
2241
2578
|
// src/cleanup-remove-path.ts
|
|
2242
2579
|
import { existsSync as existsSync13, rmSync } from "node:fs";
|
|
2580
|
+
init_paths();
|
|
2243
2581
|
|
|
2244
2582
|
// src/cleanup-path-ownership.ts
|
|
2245
2583
|
import { lstatSync, readdirSync as readdirSync8 } from "node:fs";
|
|
@@ -2748,6 +3086,7 @@ function scanDependencyCacheCandidates(opts) {
|
|
|
2748
3086
|
}
|
|
2749
3087
|
|
|
2750
3088
|
// src/cleanup-duplicate-worktrees.ts
|
|
3089
|
+
init_git();
|
|
2751
3090
|
import { existsSync as existsSync17, statSync as statSync9 } from "node:fs";
|
|
2752
3091
|
import path18 from "node:path";
|
|
2753
3092
|
function pathAgeMs4(target, now) {
|
|
@@ -2840,6 +3179,8 @@ function scanDuplicateWorktreeCandidates(opts) {
|
|
|
2840
3179
|
}
|
|
2841
3180
|
|
|
2842
3181
|
// src/cleanup-worktree-index.ts
|
|
3182
|
+
init_run_store();
|
|
3183
|
+
init_util();
|
|
2843
3184
|
import path19 from "node:path";
|
|
2844
3185
|
function buildWorktreeIndexAt(harnessRoot) {
|
|
2845
3186
|
const index = /* @__PURE__ */ new Map();
|
|
@@ -2910,6 +3251,7 @@ function resolveHarnessRetention(options = {}) {
|
|
|
2910
3251
|
}
|
|
2911
3252
|
|
|
2912
3253
|
// src/cleanup-orphan-safety.ts
|
|
3254
|
+
init_git();
|
|
2913
3255
|
import { existsSync as existsSync18, statSync as statSync10 } from "node:fs";
|
|
2914
3256
|
import path20 from "node:path";
|
|
2915
3257
|
var DEFAULT_HEARTBEAT_FRESH_MS = 30 * 60 * 1e3;
|
|
@@ -2962,6 +3304,7 @@ function assessOrphanWorktreeSafety(input) {
|
|
|
2962
3304
|
}
|
|
2963
3305
|
|
|
2964
3306
|
// src/harness-storage-snapshot.ts
|
|
3307
|
+
init_paths();
|
|
2965
3308
|
import { existsSync as existsSync19, readdirSync as readdirSync11, statSync as statSync11 } from "node:fs";
|
|
2966
3309
|
import path21 from "node:path";
|
|
2967
3310
|
function harnessStorageSnapshot(opts = {}) {
|
|
@@ -3036,6 +3379,7 @@ function harnessStorageSnapshot(opts = {}) {
|
|
|
3036
3379
|
}
|
|
3037
3380
|
|
|
3038
3381
|
// src/cleanup-harness-roots.ts
|
|
3382
|
+
init_paths();
|
|
3039
3383
|
import { existsSync as existsSync20 } from "node:fs";
|
|
3040
3384
|
import { homedir as homedir4 } from "node:os";
|
|
3041
3385
|
import path22 from "node:path";
|
|
@@ -3071,6 +3415,7 @@ function resolveHarnessScanRoots(options = {}) {
|
|
|
3071
3415
|
}
|
|
3072
3416
|
|
|
3073
3417
|
// src/cleanup-disk-pressure.ts
|
|
3418
|
+
init_disk_gate();
|
|
3074
3419
|
function envFlag2(name) {
|
|
3075
3420
|
const v = process.env[name];
|
|
3076
3421
|
return v === "1" || v === "true" || v === "yes";
|
|
@@ -3119,6 +3464,39 @@ function emitCleanupProgress(phase, detail) {
|
|
|
3119
3464
|
console.error(`[kynver cleanup] ${phase}${suffix}`);
|
|
3120
3465
|
}
|
|
3121
3466
|
|
|
3467
|
+
// src/cleanup-git-rev-cache.ts
|
|
3468
|
+
init_git();
|
|
3469
|
+
var CleanupGitRevCache = class {
|
|
3470
|
+
aheadOfMain = /* @__PURE__ */ new Map();
|
|
3471
|
+
countAheadOfMain(worktreePath, base = "origin/main") {
|
|
3472
|
+
const key = `${worktreePath}\0${base}`;
|
|
3473
|
+
if (this.aheadOfMain.has(key)) return this.aheadOfMain.get(key) ?? null;
|
|
3474
|
+
const result = gitCapture(worktreePath, ["rev-list", "--count", `${base}..HEAD`]);
|
|
3475
|
+
if (result.status !== 0) {
|
|
3476
|
+
this.aheadOfMain.set(key, null);
|
|
3477
|
+
return null;
|
|
3478
|
+
}
|
|
3479
|
+
const count = Number(result.stdout.trim());
|
|
3480
|
+
const parsed = Number.isFinite(count) ? count : null;
|
|
3481
|
+
this.aheadOfMain.set(key, parsed);
|
|
3482
|
+
return parsed;
|
|
3483
|
+
}
|
|
3484
|
+
};
|
|
3485
|
+
|
|
3486
|
+
// src/cleanup-git-status-cache.ts
|
|
3487
|
+
init_git();
|
|
3488
|
+
var CleanupGitStatusCache = class {
|
|
3489
|
+
cache = /* @__PURE__ */ new Map();
|
|
3490
|
+
porcelain(worktreePath) {
|
|
3491
|
+
const resolved = worktreePath;
|
|
3492
|
+
const cached = this.cache.get(resolved);
|
|
3493
|
+
if (cached !== void 0) return cached;
|
|
3494
|
+
const lines = gitStatusShort(resolved);
|
|
3495
|
+
this.cache.set(resolved, lines);
|
|
3496
|
+
return lines;
|
|
3497
|
+
}
|
|
3498
|
+
};
|
|
3499
|
+
|
|
3122
3500
|
// src/cleanup-run-terminal-cache.ts
|
|
3123
3501
|
var CleanupRunTerminalCache = class {
|
|
3124
3502
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -3236,7 +3614,11 @@ function runHarnessCleanup(options = {}) {
|
|
|
3236
3614
|
emitCleanupProgress("index", "building worktree index");
|
|
3237
3615
|
const index = mergeWorktreeIndexes(paths.scanRoots);
|
|
3238
3616
|
emitCleanupProgress("index", `${index.size} indexed worktree(s)`);
|
|
3239
|
-
const liveness = {
|
|
3617
|
+
const liveness = {
|
|
3618
|
+
runTerminalCache: new CleanupRunTerminalCache(),
|
|
3619
|
+
gitStatusCache: new CleanupGitStatusCache(),
|
|
3620
|
+
gitRevCache: new CleanupGitRevCache()
|
|
3621
|
+
};
|
|
3240
3622
|
const skips = [];
|
|
3241
3623
|
const actions = [];
|
|
3242
3624
|
const processedPaths = /* @__PURE__ */ new Set();
|
|
@@ -3256,8 +3638,15 @@ function runHarnessCleanup(options = {}) {
|
|
|
3256
3638
|
index,
|
|
3257
3639
|
now: paths.now
|
|
3258
3640
|
};
|
|
3259
|
-
|
|
3641
|
+
const dependencyCandidates = scanDependencyCacheCandidates(scanOpts);
|
|
3642
|
+
emitCleanupProgress("dependency", `${dependencyCandidates.length} cache candidate(s) at ${harnessRoot}`);
|
|
3643
|
+
let dependencyProcessed = 0;
|
|
3644
|
+
for (const raw of dependencyCandidates) {
|
|
3260
3645
|
if (atSweepCap()) break;
|
|
3646
|
+
dependencyProcessed += 1;
|
|
3647
|
+
if (dependencyProcessed % 50 === 0) {
|
|
3648
|
+
emitCleanupProgress("dependency", `${dependencyProcessed}/${dependencyCandidates.length} evaluated`);
|
|
3649
|
+
}
|
|
3261
3650
|
const resolved = path23.resolve(raw.path);
|
|
3262
3651
|
if (processedPaths.has(resolved)) continue;
|
|
3263
3652
|
processedPaths.add(resolved);
|
|
@@ -3277,7 +3666,8 @@ function runHarnessCleanup(options = {}) {
|
|
|
3277
3666
|
ageMs: candidate.ageMs,
|
|
3278
3667
|
worktreePath,
|
|
3279
3668
|
activeWorktreePaths: activeGuards.activeWorktreePaths,
|
|
3280
|
-
diskPressure: retention.diskPressure
|
|
3669
|
+
diskPressure: retention.diskPressure,
|
|
3670
|
+
gitStatusCache: liveness.gitStatusCache
|
|
3281
3671
|
});
|
|
3282
3672
|
if (guardReason) {
|
|
3283
3673
|
recordSkip(skips, candidate.path, guardReason);
|
|
@@ -3312,7 +3702,8 @@ function runHarnessCleanup(options = {}) {
|
|
|
3312
3702
|
ageMs: candidate.ageMs,
|
|
3313
3703
|
worktreePath,
|
|
3314
3704
|
activeWorktreePaths: activeGuards.activeWorktreePaths,
|
|
3315
|
-
diskPressure: retention.diskPressure
|
|
3705
|
+
diskPressure: retention.diskPressure,
|
|
3706
|
+
gitStatusCache: liveness.gitStatusCache
|
|
3316
3707
|
});
|
|
3317
3708
|
if (guardReason) {
|
|
3318
3709
|
recordSkip(skips, candidate.path, guardReason);
|
|
@@ -3332,8 +3723,13 @@ function runHarnessCleanup(options = {}) {
|
|
|
3332
3723
|
];
|
|
3333
3724
|
emitCleanupProgress("worktrees", `${worktreeCandidates.length} candidate(s) at ${harnessRoot}`);
|
|
3334
3725
|
const worktreeSeen = /* @__PURE__ */ new Set();
|
|
3726
|
+
let worktreeProcessed = 0;
|
|
3335
3727
|
for (const raw of worktreeCandidates) {
|
|
3336
3728
|
if (atSweepCap()) break;
|
|
3729
|
+
worktreeProcessed += 1;
|
|
3730
|
+
if (worktreeProcessed % 50 === 0) {
|
|
3731
|
+
emitCleanupProgress("worktrees", `${worktreeProcessed}/${worktreeCandidates.length} evaluated`);
|
|
3732
|
+
}
|
|
3337
3733
|
const resolved = path23.resolve(raw.path);
|
|
3338
3734
|
if (worktreeSeen.has(resolved)) continue;
|
|
3339
3735
|
worktreeSeen.add(resolved);
|