@kynver-app/runtime 0.1.112 → 0.1.117
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/cli.js +1559 -397
- 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/device-login.d.ts +8 -0
- package/dist/index.js +2185 -999
- package/dist/index.js.map +4 -4
- 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 +376 -127
- package/dist/server/cleanup.js.map +4 -4
- package/dist/server/default-repo.js +288 -68
- package/dist/server/default-repo.js.map +4 -4
- package/dist/server/monitor.js +342 -126
- 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/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,22 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// src/default-repo-discovery.ts
|
|
13
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
14
|
-
import { homedir as homedir2 } from "node:os";
|
|
15
|
-
import path3 from "node:path";
|
|
16
|
-
import { fileURLToPath } from "node:url";
|
|
17
|
-
|
|
18
|
-
// src/git.ts
|
|
19
|
-
import { spawnSync } from "node:child_process";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
20
11
|
|
|
21
12
|
// src/util.ts
|
|
22
13
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -125,42 +116,13 @@ function latestIso(values) {
|
|
|
125
116
|
function secsAgo(ms) {
|
|
126
117
|
return Math.max(0, Math.round((Date.now() - ms) / 1e3));
|
|
127
118
|
}
|
|
119
|
+
var init_util = __esm({
|
|
120
|
+
"src/util.ts"() {
|
|
121
|
+
"use strict";
|
|
122
|
+
}
|
|
123
|
+
});
|
|
128
124
|
|
|
129
125
|
// src/worker-env.ts
|
|
130
|
-
var FORBIDDEN_WORKER_ENV_KEYS = [
|
|
131
|
-
"ANTHROPIC_API_KEY",
|
|
132
|
-
"ANALYST_API_KEY",
|
|
133
|
-
"RECRUITER_API_KEY",
|
|
134
|
-
"AUTH_SECRET",
|
|
135
|
-
"NEXTAUTH_SECRET",
|
|
136
|
-
"DATABASE_URL",
|
|
137
|
-
"PRODUCTION_DATABASE_URL",
|
|
138
|
-
"KYNVER_PRODUCTION_DATABASE_URL",
|
|
139
|
-
"REDIS_URL",
|
|
140
|
-
"GOOGLE_CLIENT_SECRET",
|
|
141
|
-
"GITHUB_CLIENT_SECRET",
|
|
142
|
-
"KYNVER_API_KEY",
|
|
143
|
-
"KYNVER_SERVICE_SECRET",
|
|
144
|
-
"KYNVER_RUNTIME_SECRET",
|
|
145
|
-
"KYNVER_CRON_SECRET",
|
|
146
|
-
"OPENCLAW_CRON_SECRET",
|
|
147
|
-
"QSTASH_TOKEN",
|
|
148
|
-
"QSTASH_CURRENT_SIGNING_KEY",
|
|
149
|
-
"QSTASH_NEXT_SIGNING_KEY",
|
|
150
|
-
"TOOL_SECRETS_KEK",
|
|
151
|
-
"TOOL_EXECUTOR_DISPATCH_SECRET",
|
|
152
|
-
"CLOUDFLARE_API_TOKEN",
|
|
153
|
-
"STRIPE_SECRET_KEY",
|
|
154
|
-
"STRIPE_WEBHOOK_SECRET",
|
|
155
|
-
"STRIPE_IDENTITY_WEBHOOK_SECRET",
|
|
156
|
-
"VOYAGE_API_KEY",
|
|
157
|
-
"PERPLEXITY_API_KEY",
|
|
158
|
-
"FRED_API_KEY",
|
|
159
|
-
"FMP_API_KEY",
|
|
160
|
-
"CURSOR_API_KEY"
|
|
161
|
-
];
|
|
162
|
-
var FORBIDDEN_KEY_SET = new Set(FORBIDDEN_WORKER_ENV_KEYS);
|
|
163
|
-
var FORBIDDEN_SUFFIXES = ["_SECRET", "_API_KEY"];
|
|
164
126
|
function isForbiddenWorkerEnvKey(key) {
|
|
165
127
|
if (FORBIDDEN_KEY_SET.has(key)) return true;
|
|
166
128
|
return FORBIDDEN_SUFFIXES.some((suffix) => key.endsWith(suffix));
|
|
@@ -172,8 +134,49 @@ function scrubWorkerEnv(env) {
|
|
|
172
134
|
}
|
|
173
135
|
return next;
|
|
174
136
|
}
|
|
137
|
+
var FORBIDDEN_WORKER_ENV_KEYS, FORBIDDEN_KEY_SET, FORBIDDEN_SUFFIXES;
|
|
138
|
+
var init_worker_env = __esm({
|
|
139
|
+
"src/worker-env.ts"() {
|
|
140
|
+
"use strict";
|
|
141
|
+
FORBIDDEN_WORKER_ENV_KEYS = [
|
|
142
|
+
"ANTHROPIC_API_KEY",
|
|
143
|
+
"ANALYST_API_KEY",
|
|
144
|
+
"RECRUITER_API_KEY",
|
|
145
|
+
"AUTH_SECRET",
|
|
146
|
+
"NEXTAUTH_SECRET",
|
|
147
|
+
"DATABASE_URL",
|
|
148
|
+
"PRODUCTION_DATABASE_URL",
|
|
149
|
+
"KYNVER_PRODUCTION_DATABASE_URL",
|
|
150
|
+
"REDIS_URL",
|
|
151
|
+
"GOOGLE_CLIENT_SECRET",
|
|
152
|
+
"GITHUB_CLIENT_SECRET",
|
|
153
|
+
"KYNVER_API_KEY",
|
|
154
|
+
"KYNVER_SERVICE_SECRET",
|
|
155
|
+
"KYNVER_RUNTIME_SECRET",
|
|
156
|
+
"KYNVER_CRON_SECRET",
|
|
157
|
+
"OPENCLAW_CRON_SECRET",
|
|
158
|
+
"QSTASH_TOKEN",
|
|
159
|
+
"QSTASH_CURRENT_SIGNING_KEY",
|
|
160
|
+
"QSTASH_NEXT_SIGNING_KEY",
|
|
161
|
+
"TOOL_SECRETS_KEK",
|
|
162
|
+
"TOOL_EXECUTOR_DISPATCH_SECRET",
|
|
163
|
+
"CLOUDFLARE_API_TOKEN",
|
|
164
|
+
"STRIPE_SECRET_KEY",
|
|
165
|
+
"STRIPE_WEBHOOK_SECRET",
|
|
166
|
+
"STRIPE_IDENTITY_WEBHOOK_SECRET",
|
|
167
|
+
"VOYAGE_API_KEY",
|
|
168
|
+
"PERPLEXITY_API_KEY",
|
|
169
|
+
"FRED_API_KEY",
|
|
170
|
+
"FMP_API_KEY",
|
|
171
|
+
"CURSOR_API_KEY"
|
|
172
|
+
];
|
|
173
|
+
FORBIDDEN_KEY_SET = new Set(FORBIDDEN_WORKER_ENV_KEYS);
|
|
174
|
+
FORBIDDEN_SUFFIXES = ["_SECRET", "_API_KEY"];
|
|
175
|
+
}
|
|
176
|
+
});
|
|
175
177
|
|
|
176
178
|
// src/git.ts
|
|
179
|
+
import { spawnSync } from "node:child_process";
|
|
177
180
|
function git(cwd, args, options = {}) {
|
|
178
181
|
const res = spawnSync(
|
|
179
182
|
"git",
|
|
@@ -297,6 +300,13 @@ function unknownAncestry(base, error, head = null) {
|
|
|
297
300
|
error
|
|
298
301
|
};
|
|
299
302
|
}
|
|
303
|
+
var init_git = __esm({
|
|
304
|
+
"src/git.ts"() {
|
|
305
|
+
"use strict";
|
|
306
|
+
init_util();
|
|
307
|
+
init_worker_env();
|
|
308
|
+
}
|
|
309
|
+
});
|
|
300
310
|
|
|
301
311
|
// src/path-values.ts
|
|
302
312
|
import { homedir } from "node:os";
|
|
@@ -326,15 +336,17 @@ function redactHomePath(value) {
|
|
|
326
336
|
function displayUserPath(value) {
|
|
327
337
|
return redactHomePath(value);
|
|
328
338
|
}
|
|
339
|
+
var init_path_values = __esm({
|
|
340
|
+
"src/path-values.ts"() {
|
|
341
|
+
"use strict";
|
|
342
|
+
}
|
|
343
|
+
});
|
|
329
344
|
|
|
330
345
|
// src/default-repo-discovery.ts
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
"code/Kynver",
|
|
336
|
-
"projects/Kynver"
|
|
337
|
-
];
|
|
346
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
347
|
+
import { homedir as homedir2 } from "node:os";
|
|
348
|
+
import path3 from "node:path";
|
|
349
|
+
import { fileURLToPath } from "node:url";
|
|
338
350
|
function readPackageName(repoRoot) {
|
|
339
351
|
const pkgPath = path3.join(repoRoot, "package.json");
|
|
340
352
|
if (!existsSync2(pkgPath)) return null;
|
|
@@ -399,6 +411,21 @@ function discoverDefaultRepoCandidates(opts) {
|
|
|
399
411
|
function discoverDefaultRepo(opts) {
|
|
400
412
|
return discoverDefaultRepoCandidates(opts)[0] ?? null;
|
|
401
413
|
}
|
|
414
|
+
var WELL_KNOWN_REPO_DIRS;
|
|
415
|
+
var init_default_repo_discovery = __esm({
|
|
416
|
+
"src/default-repo-discovery.ts"() {
|
|
417
|
+
"use strict";
|
|
418
|
+
init_git();
|
|
419
|
+
init_path_values();
|
|
420
|
+
WELL_KNOWN_REPO_DIRS = [
|
|
421
|
+
"Kynver",
|
|
422
|
+
"repos/Kynver",
|
|
423
|
+
"repos/kynver-source-main",
|
|
424
|
+
"code/Kynver",
|
|
425
|
+
"projects/Kynver"
|
|
426
|
+
];
|
|
427
|
+
}
|
|
428
|
+
});
|
|
402
429
|
|
|
403
430
|
// src/box-identity.ts
|
|
404
431
|
function normalizeWorkerPoolBoxKind(raw) {
|
|
@@ -448,9 +475,11 @@ function resolveBoxIdentity(env = process.env, config = {}) {
|
|
|
448
475
|
function resolveBoxKindFromConfig(config = {}, env = process.env) {
|
|
449
476
|
return resolveBoxIdentity(env, config).boxKind;
|
|
450
477
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
478
|
+
var init_box_identity = __esm({
|
|
479
|
+
"src/box-identity.ts"() {
|
|
480
|
+
"use strict";
|
|
481
|
+
}
|
|
482
|
+
});
|
|
454
483
|
|
|
455
484
|
// src/bounded-build/meminfo.ts
|
|
456
485
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
@@ -471,18 +500,14 @@ function readMemAvailableBytes(meminfoText) {
|
|
|
471
500
|
}
|
|
472
501
|
return os.freemem();
|
|
473
502
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
import { statfsSync as statfsSync2 } from "node:fs";
|
|
503
|
+
var init_meminfo = __esm({
|
|
504
|
+
"src/bounded-build/meminfo.ts"() {
|
|
505
|
+
"use strict";
|
|
506
|
+
}
|
|
507
|
+
});
|
|
480
508
|
|
|
481
509
|
// src/wsl-host.ts
|
|
482
510
|
import { existsSync as existsSync3, readFileSync as readFileSync4, statfsSync } from "node:fs";
|
|
483
|
-
var DEFAULT_WSL_HOST_WARN_FREE_BYTES = 25 * 1024 * 1024 * 1024;
|
|
484
|
-
var DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES = 12 * 1024 * 1024 * 1024;
|
|
485
|
-
var DEFAULT_WSL_HOST_MOUNT = "/mnt/c";
|
|
486
511
|
function isWslHost() {
|
|
487
512
|
if (process.platform !== "linux") return false;
|
|
488
513
|
for (const probe of ["/proc/sys/kernel/osrelease", "/proc/version"]) {
|
|
@@ -498,23 +523,23 @@ function isWslHost() {
|
|
|
498
523
|
function observeWslHostDisk(options = {}) {
|
|
499
524
|
const wsl = options.forceWsl === void 0 ? isWslHost() : options.forceWsl;
|
|
500
525
|
if (!wsl) return null;
|
|
501
|
-
const
|
|
526
|
+
const path73 = options.wslHostMount?.trim() || process.env.KYNVER_WSL_HOST_MOUNT?.trim() || DEFAULT_WSL_HOST_MOUNT;
|
|
502
527
|
const warnBelowBytes = options.wslHostFreeWarnBytes ?? DEFAULT_WSL_HOST_WARN_FREE_BYTES;
|
|
503
528
|
const criticalBelowBytes = options.wslHostFreeCriticalBytes ?? DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES;
|
|
504
529
|
const statfs = options.statfs ?? statfsSync;
|
|
505
530
|
let stats;
|
|
506
531
|
try {
|
|
507
|
-
stats = statfs(
|
|
532
|
+
stats = statfs(path73);
|
|
508
533
|
} catch (error) {
|
|
509
534
|
return {
|
|
510
535
|
ok: false,
|
|
511
|
-
path:
|
|
536
|
+
path: path73,
|
|
512
537
|
freeBytes: 0,
|
|
513
538
|
totalBytes: 0,
|
|
514
539
|
usedPercent: 100,
|
|
515
540
|
warnBelowBytes,
|
|
516
541
|
criticalBelowBytes,
|
|
517
|
-
reason: `Windows host disk probe failed at ${
|
|
542
|
+
reason: `Windows host disk probe failed at ${path73}: ${error.message}`,
|
|
518
543
|
probeError: error.message
|
|
519
544
|
};
|
|
520
545
|
}
|
|
@@ -528,11 +553,11 @@ function observeWslHostDisk(options = {}) {
|
|
|
528
553
|
let reason = null;
|
|
529
554
|
if (!ok) {
|
|
530
555
|
const tag = criticalFree ? "critical" : "warning";
|
|
531
|
-
reason = `Windows host disk ${
|
|
556
|
+
reason = `Windows host disk ${path73} at ${tag}: ${freeGiB} GiB free (<${(criticalFree ? criticalBelowBytes : warnBelowBytes) / 1024 / 1024 / 1024} GiB); WSL VHDX cannot grow safely. ${summarizeWslRecoverySteps()}`;
|
|
532
557
|
}
|
|
533
558
|
return {
|
|
534
559
|
ok,
|
|
535
|
-
path:
|
|
560
|
+
path: path73,
|
|
536
561
|
freeBytes,
|
|
537
562
|
totalBytes,
|
|
538
563
|
usedPercent,
|
|
@@ -545,19 +570,25 @@ function observeWslHostDisk(options = {}) {
|
|
|
545
570
|
function summarizeWslRecoverySteps() {
|
|
546
571
|
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.";
|
|
547
572
|
}
|
|
573
|
+
var DEFAULT_WSL_HOST_WARN_FREE_BYTES, DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES, DEFAULT_WSL_HOST_MOUNT;
|
|
574
|
+
var init_wsl_host = __esm({
|
|
575
|
+
"src/wsl-host.ts"() {
|
|
576
|
+
"use strict";
|
|
577
|
+
DEFAULT_WSL_HOST_WARN_FREE_BYTES = 25 * 1024 * 1024 * 1024;
|
|
578
|
+
DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES = 12 * 1024 * 1024 * 1024;
|
|
579
|
+
DEFAULT_WSL_HOST_MOUNT = "/mnt/c";
|
|
580
|
+
}
|
|
581
|
+
});
|
|
548
582
|
|
|
549
583
|
// src/disk-gate.ts
|
|
550
|
-
|
|
551
|
-
var DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
|
|
552
|
-
var DEFAULT_MAX_USED_PERCENT = 80;
|
|
553
|
-
var DEFAULT_HARD_MAX_USED_PERCENT = 90;
|
|
584
|
+
import { statfsSync as statfsSync2 } from "node:fs";
|
|
554
585
|
function observeRunnerDiskGate(input = {}) {
|
|
555
|
-
const
|
|
586
|
+
const path73 = input.diskPath?.trim() || "/";
|
|
556
587
|
const warnBelowBytes = input.diskFreeWarnBytes ?? DEFAULT_WARN_FREE_BYTES;
|
|
557
588
|
const criticalBelowBytes = input.diskFreeCriticalBytes ?? DEFAULT_CRITICAL_FREE_BYTES;
|
|
558
589
|
const maxUsedPercent = input.diskMaxUsedPercent ?? DEFAULT_MAX_USED_PERCENT;
|
|
559
590
|
const hardMaxUsedPercent = input.diskHardMaxUsedPercent ?? DEFAULT_HARD_MAX_USED_PERCENT;
|
|
560
|
-
const stats = statfsSync2(
|
|
591
|
+
const stats = statfsSync2(path73);
|
|
561
592
|
const freeBytes = Number(stats.bavail) * Number(stats.bsize);
|
|
562
593
|
const totalBytes = Number(stats.blocks) * Number(stats.bsize);
|
|
563
594
|
const usedPercent = totalBytes > 0 ? (totalBytes - freeBytes) / totalBytes * 100 : 100;
|
|
@@ -580,7 +611,7 @@ function observeRunnerDiskGate(input = {}) {
|
|
|
580
611
|
}
|
|
581
612
|
return {
|
|
582
613
|
ok,
|
|
583
|
-
path:
|
|
614
|
+
path: path73,
|
|
584
615
|
freeBytes,
|
|
585
616
|
totalBytes,
|
|
586
617
|
usedPercent,
|
|
@@ -592,17 +623,22 @@ function observeRunnerDiskGate(input = {}) {
|
|
|
592
623
|
wslHost
|
|
593
624
|
};
|
|
594
625
|
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
626
|
+
var DEFAULT_WARN_FREE_BYTES, DEFAULT_CRITICAL_FREE_BYTES, DEFAULT_MAX_USED_PERCENT, DEFAULT_HARD_MAX_USED_PERCENT;
|
|
627
|
+
var init_disk_gate = __esm({
|
|
628
|
+
"src/disk-gate.ts"() {
|
|
629
|
+
"use strict";
|
|
630
|
+
init_wsl_host();
|
|
631
|
+
DEFAULT_WARN_FREE_BYTES = 30 * 1024 * 1024 * 1024;
|
|
632
|
+
DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
|
|
633
|
+
DEFAULT_MAX_USED_PERCENT = 80;
|
|
634
|
+
DEFAULT_HARD_MAX_USED_PERCENT = 90;
|
|
635
|
+
}
|
|
636
|
+
});
|
|
599
637
|
|
|
600
638
|
// src/paths.ts
|
|
601
639
|
import { existsSync as existsSync4 } from "node:fs";
|
|
602
640
|
import { homedir as homedir3 } from "node:os";
|
|
603
641
|
import path4 from "node:path";
|
|
604
|
-
var LEGACY_ROOT = path4.join(homedir3(), ".openclaw", "harness");
|
|
605
|
-
var HARNESS_LAYOUT_DIR_NAMES = /* @__PURE__ */ new Set(["runs", "worktrees"]);
|
|
606
642
|
function normalizeHarnessRoot(root) {
|
|
607
643
|
let resolved = path4.resolve(resolveUserPath(root.trim()));
|
|
608
644
|
while (HARNESS_LAYOUT_DIR_NAMES.has(path4.basename(resolved))) {
|
|
@@ -637,8 +673,21 @@ function getHarnessPaths() {
|
|
|
637
673
|
function runDir(runsDir, id) {
|
|
638
674
|
return path4.join(runsDir, safeSlug(id));
|
|
639
675
|
}
|
|
676
|
+
var LEGACY_ROOT, HARNESS_LAYOUT_DIR_NAMES;
|
|
677
|
+
var init_paths = __esm({
|
|
678
|
+
"src/paths.ts"() {
|
|
679
|
+
"use strict";
|
|
680
|
+
init_config();
|
|
681
|
+
init_path_values();
|
|
682
|
+
init_util();
|
|
683
|
+
LEGACY_ROOT = path4.join(homedir3(), ".openclaw", "harness");
|
|
684
|
+
HARNESS_LAYOUT_DIR_NAMES = /* @__PURE__ */ new Set(["runs", "worktrees"]);
|
|
685
|
+
}
|
|
686
|
+
});
|
|
640
687
|
|
|
641
688
|
// src/run-store.ts
|
|
689
|
+
import { existsSync as existsSync5, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
|
|
690
|
+
import path5 from "node:path";
|
|
642
691
|
function getPaths() {
|
|
643
692
|
return getHarnessPaths();
|
|
644
693
|
}
|
|
@@ -696,6 +745,13 @@ function runDirectory(id) {
|
|
|
696
745
|
function runDirectoryAt(harnessRoot, id) {
|
|
697
746
|
return runDir(harnessRunsDir(harnessRoot), safeSlug(id));
|
|
698
747
|
}
|
|
748
|
+
var init_run_store = __esm({
|
|
749
|
+
"src/run-store.ts"() {
|
|
750
|
+
"use strict";
|
|
751
|
+
init_paths();
|
|
752
|
+
init_util();
|
|
753
|
+
}
|
|
754
|
+
});
|
|
699
755
|
|
|
700
756
|
// src/run-worker-index.ts
|
|
701
757
|
import { existsSync as existsSync6, readdirSync as readdirSync3 } from "node:fs";
|
|
@@ -713,12 +769,13 @@ function listRunWorkerNames(run) {
|
|
|
713
769
|
}
|
|
714
770
|
return [...names];
|
|
715
771
|
}
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
772
|
+
var init_run_worker_index = __esm({
|
|
773
|
+
"src/run-worker-index.ts"() {
|
|
774
|
+
"use strict";
|
|
775
|
+
init_run_store();
|
|
776
|
+
init_util();
|
|
777
|
+
}
|
|
778
|
+
});
|
|
722
779
|
|
|
723
780
|
// src/heartbeat-final-result.ts
|
|
724
781
|
function tryParseJsonObject(text) {
|
|
@@ -769,9 +826,14 @@ function terminalFinalResultFromHeartbeatRow(row) {
|
|
|
769
826
|
if (embedded) return embedded;
|
|
770
827
|
return summary;
|
|
771
828
|
}
|
|
829
|
+
var init_heartbeat_final_result = __esm({
|
|
830
|
+
"src/heartbeat-final-result.ts"() {
|
|
831
|
+
"use strict";
|
|
832
|
+
}
|
|
833
|
+
});
|
|
772
834
|
|
|
773
835
|
// src/heartbeat.ts
|
|
774
|
-
|
|
836
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
|
|
775
837
|
function isTerminalHeartbeatPhase(phase) {
|
|
776
838
|
return phase === "complete";
|
|
777
839
|
}
|
|
@@ -834,29 +896,17 @@ function parseHeartbeat(file) {
|
|
|
834
896
|
}
|
|
835
897
|
return result;
|
|
836
898
|
}
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
899
|
+
var HEARTBEAT_FUTURE_SKEW_MS;
|
|
900
|
+
var init_heartbeat = __esm({
|
|
901
|
+
"src/heartbeat.ts"() {
|
|
902
|
+
"use strict";
|
|
903
|
+
init_heartbeat_final_result();
|
|
904
|
+
init_util();
|
|
905
|
+
HEARTBEAT_FUTURE_SKEW_MS = 6e4;
|
|
906
|
+
}
|
|
907
|
+
});
|
|
840
908
|
|
|
841
909
|
// src/repo-search.ts
|
|
842
|
-
var RG_BINARIES = /* @__PURE__ */ new Set(["rg", "ripgrep", "grep"]);
|
|
843
|
-
var 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
910
|
function binaryName(token) {
|
|
861
911
|
if (!token) return null;
|
|
862
912
|
const base = token.split("/").pop() ?? token;
|
|
@@ -1055,11 +1105,32 @@ function diagnoseRepoSearchFailure(input) {
|
|
|
1055
1105
|
}
|
|
1056
1106
|
return null;
|
|
1057
1107
|
}
|
|
1108
|
+
var RG_BINARIES, RG_OPTS_WITH_VALUE;
|
|
1109
|
+
var init_repo_search = __esm({
|
|
1110
|
+
"src/repo-search.ts"() {
|
|
1111
|
+
"use strict";
|
|
1112
|
+
RG_BINARIES = /* @__PURE__ */ new Set(["rg", "ripgrep", "grep"]);
|
|
1113
|
+
RG_OPTS_WITH_VALUE = /* @__PURE__ */ new Set([
|
|
1114
|
+
"-e",
|
|
1115
|
+
"--regexp",
|
|
1116
|
+
"-f",
|
|
1117
|
+
"--file",
|
|
1118
|
+
"-m",
|
|
1119
|
+
"--max-count",
|
|
1120
|
+
"-A",
|
|
1121
|
+
"--after-context",
|
|
1122
|
+
"-B",
|
|
1123
|
+
"--before-context",
|
|
1124
|
+
"-C",
|
|
1125
|
+
"--context",
|
|
1126
|
+
"-g",
|
|
1127
|
+
"--glob",
|
|
1128
|
+
"--iglob"
|
|
1129
|
+
]);
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1058
1132
|
|
|
1059
1133
|
// src/shell-command-outcome.ts
|
|
1060
|
-
var NPM_AUDIT_RE = /\bnpm\s+audit\b/i;
|
|
1061
|
-
var RG_CMD_RE = /\b(rg|ripgrep)\b/i;
|
|
1062
|
-
var RG_REAL_ERROR_RE = /\b(error|invalid|unknown|panic|not found)\b/i;
|
|
1063
1134
|
function tidy(text, max = 200) {
|
|
1064
1135
|
const one = text.replace(/\s+/g, " ").trim();
|
|
1065
1136
|
return one.length > max ? `${one.slice(0, max - 1)}\u2026` : one;
|
|
@@ -1263,8 +1334,19 @@ function classifyShellCommandOutcome(input) {
|
|
|
1263
1334
|
summary: `command failed (exit ${input.exitCode}): ${tail}`
|
|
1264
1335
|
};
|
|
1265
1336
|
}
|
|
1337
|
+
var NPM_AUDIT_RE, RG_CMD_RE, RG_REAL_ERROR_RE;
|
|
1338
|
+
var init_shell_command_outcome = __esm({
|
|
1339
|
+
"src/shell-command-outcome.ts"() {
|
|
1340
|
+
"use strict";
|
|
1341
|
+
init_repo_search();
|
|
1342
|
+
NPM_AUDIT_RE = /\bnpm\s+audit\b/i;
|
|
1343
|
+
RG_CMD_RE = /\b(rg|ripgrep)\b/i;
|
|
1344
|
+
RG_REAL_ERROR_RE = /\b(error|invalid|unknown|panic|not found)\b/i;
|
|
1345
|
+
}
|
|
1346
|
+
});
|
|
1266
1347
|
|
|
1267
1348
|
// src/stream.ts
|
|
1349
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "node:fs";
|
|
1268
1350
|
function eventTimestampIso(event) {
|
|
1269
1351
|
const tsMs = event.timestamp_ms;
|
|
1270
1352
|
return event.timestamp || event.ts || (tsMs ? new Date(tsMs).toISOString() : void 0);
|
|
@@ -1430,38 +1512,15 @@ function summarizeEvent(event) {
|
|
|
1430
1512
|
}
|
|
1431
1513
|
return void 0;
|
|
1432
1514
|
}
|
|
1515
|
+
var init_stream = __esm({
|
|
1516
|
+
"src/stream.ts"() {
|
|
1517
|
+
"use strict";
|
|
1518
|
+
init_shell_command_outcome();
|
|
1519
|
+
init_util();
|
|
1520
|
+
}
|
|
1521
|
+
});
|
|
1433
1522
|
|
|
1434
1523
|
// src/exit-classify.ts
|
|
1435
|
-
var FAILURE_PATTERNS = [
|
|
1436
|
-
{
|
|
1437
|
-
test: /\b(?:invalid|unknown|unsupported|unrecognized)\b[^.\n]*\bmodel\b/i,
|
|
1438
|
-
label: "provider rejected the requested model"
|
|
1439
|
-
},
|
|
1440
|
-
{
|
|
1441
|
-
test: /\bmodel\b[^.\n]*\b(?:not\s+(?:found|supported|available|recognized|valid)|is\s+not\s+valid|does\s+not\s+exist)/i,
|
|
1442
|
-
label: "provider rejected the requested model"
|
|
1443
|
-
},
|
|
1444
|
-
{
|
|
1445
|
-
test: /\b(?:did you mean|available models|choose (?:a|one of)|supported models)\b/i,
|
|
1446
|
-
label: "provider rejected the requested model"
|
|
1447
|
-
},
|
|
1448
|
-
{
|
|
1449
|
-
test: /model preflight failed/i,
|
|
1450
|
-
label: "model/provider preflight failed"
|
|
1451
|
-
},
|
|
1452
|
-
{
|
|
1453
|
-
test: /\b(?:command not found|ENOENT|is the .*CLI on PATH|executable not found|no such file or directory)\b/i,
|
|
1454
|
-
label: "provider CLI is missing or not on PATH"
|
|
1455
|
-
},
|
|
1456
|
-
{
|
|
1457
|
-
test: /\bfailed to spawn\b/i,
|
|
1458
|
-
label: "provider failed to spawn the worker process"
|
|
1459
|
-
},
|
|
1460
|
-
{
|
|
1461
|
-
test: /\b(?:not logged in|unauthorized|authentication (?:failed|required)|invalid api key|missing api key|401)\b/i,
|
|
1462
|
-
label: "provider authentication failed"
|
|
1463
|
-
}
|
|
1464
|
-
];
|
|
1465
1524
|
function tidy2(errorText, max = 240) {
|
|
1466
1525
|
const oneLine2 = errorText.replace(/\s+/g, " ").trim();
|
|
1467
1526
|
return oneLine2.length > max ? `${oneLine2.slice(0, max - 1)}\u2026` : oneLine2;
|
|
@@ -1476,6 +1535,42 @@ function classifyExitFailure(errorText) {
|
|
|
1476
1535
|
}
|
|
1477
1536
|
return null;
|
|
1478
1537
|
}
|
|
1538
|
+
var FAILURE_PATTERNS;
|
|
1539
|
+
var init_exit_classify = __esm({
|
|
1540
|
+
"src/exit-classify.ts"() {
|
|
1541
|
+
"use strict";
|
|
1542
|
+
FAILURE_PATTERNS = [
|
|
1543
|
+
{
|
|
1544
|
+
test: /\b(?:invalid|unknown|unsupported|unrecognized)\b[^.\n]*\bmodel\b/i,
|
|
1545
|
+
label: "provider rejected the requested model"
|
|
1546
|
+
},
|
|
1547
|
+
{
|
|
1548
|
+
test: /\bmodel\b[^.\n]*\b(?:not\s+(?:found|supported|available|recognized|valid)|is\s+not\s+valid|does\s+not\s+exist)/i,
|
|
1549
|
+
label: "provider rejected the requested model"
|
|
1550
|
+
},
|
|
1551
|
+
{
|
|
1552
|
+
test: /\b(?:did you mean|available models|choose (?:a|one of)|supported models)\b/i,
|
|
1553
|
+
label: "provider rejected the requested model"
|
|
1554
|
+
},
|
|
1555
|
+
{
|
|
1556
|
+
test: /model preflight failed/i,
|
|
1557
|
+
label: "model/provider preflight failed"
|
|
1558
|
+
},
|
|
1559
|
+
{
|
|
1560
|
+
test: /\b(?:command not found|ENOENT|is the .*CLI on PATH|executable not found|no such file or directory)\b/i,
|
|
1561
|
+
label: "provider CLI is missing or not on PATH"
|
|
1562
|
+
},
|
|
1563
|
+
{
|
|
1564
|
+
test: /\bfailed to spawn\b/i,
|
|
1565
|
+
label: "provider failed to spawn the worker process"
|
|
1566
|
+
},
|
|
1567
|
+
{
|
|
1568
|
+
test: /\b(?:not logged in|unauthorized|authentication (?:failed|required)|invalid api key|missing api key|401)\b/i,
|
|
1569
|
+
label: "provider authentication failed"
|
|
1570
|
+
}
|
|
1571
|
+
];
|
|
1572
|
+
}
|
|
1573
|
+
});
|
|
1479
1574
|
|
|
1480
1575
|
// src/exited-salvage.ts
|
|
1481
1576
|
function trimOrNull(value) {
|
|
@@ -1534,6 +1629,11 @@ function assessExitedWorkerSalvage(input) {
|
|
|
1534
1629
|
attentionReason: buildAttentionReason(kind, uncommittedCount, headCommit)
|
|
1535
1630
|
};
|
|
1536
1631
|
}
|
|
1632
|
+
var init_exited_salvage = __esm({
|
|
1633
|
+
"src/exited-salvage.ts"() {
|
|
1634
|
+
"use strict";
|
|
1635
|
+
}
|
|
1636
|
+
});
|
|
1537
1637
|
|
|
1538
1638
|
// src/landing-gate.ts
|
|
1539
1639
|
function trimOrNull2(value) {
|
|
@@ -1579,6 +1679,11 @@ function landingAttentionReason(verdict) {
|
|
|
1579
1679
|
if (!verdict.blocked) return void 0;
|
|
1580
1680
|
return verdict.detail ?? verdict.reason ?? "dirty_worktree_no_pr";
|
|
1581
1681
|
}
|
|
1682
|
+
var init_landing_gate = __esm({
|
|
1683
|
+
"src/landing-gate.ts"() {
|
|
1684
|
+
"use strict";
|
|
1685
|
+
}
|
|
1686
|
+
});
|
|
1582
1687
|
|
|
1583
1688
|
// src/worker-final-result-embed.ts
|
|
1584
1689
|
function tryParseJsonObject2(text) {
|
|
@@ -1628,6 +1733,11 @@ function extractEmbeddedWorkerFinalResultRecord(value) {
|
|
|
1628
1733
|
}
|
|
1629
1734
|
return best;
|
|
1630
1735
|
}
|
|
1736
|
+
var init_worker_final_result_embed = __esm({
|
|
1737
|
+
"src/worker-final-result-embed.ts"() {
|
|
1738
|
+
"use strict";
|
|
1739
|
+
}
|
|
1740
|
+
});
|
|
1631
1741
|
|
|
1632
1742
|
// src/landing-contract-gate.ts
|
|
1633
1743
|
function trimOrNull3(value) {
|
|
@@ -1787,10 +1897,14 @@ function landingContractAttentionReason(verdict) {
|
|
|
1787
1897
|
if (!verdict.blocked) return void 0;
|
|
1788
1898
|
return verdict.detail ?? verdict.reason;
|
|
1789
1899
|
}
|
|
1900
|
+
var init_landing_contract_gate = __esm({
|
|
1901
|
+
"src/landing-contract-gate.ts"() {
|
|
1902
|
+
"use strict";
|
|
1903
|
+
init_worker_final_result_embed();
|
|
1904
|
+
}
|
|
1905
|
+
});
|
|
1790
1906
|
|
|
1791
1907
|
// src/status.ts
|
|
1792
|
-
var NO_START_MS = 18e4;
|
|
1793
|
-
var STALE_MS = 6e5;
|
|
1794
1908
|
function computeAttention(input) {
|
|
1795
1909
|
const now = Date.now();
|
|
1796
1910
|
if (input.completionBlocker && !isSkippedTerminalCompletionBlocker(input.completionBlocker)) {
|
|
@@ -1982,7 +2096,15 @@ function computeWorkerStatus(worker, options = {}) {
|
|
|
1982
2096
|
changedFiles,
|
|
1983
2097
|
gitAncestry,
|
|
1984
2098
|
instructionPolicyFingerprint: worker.instructionPolicyFingerprint ?? null,
|
|
1985
|
-
instructionPolicyEvidence: worker.instructionPolicyEvidence ?? null
|
|
2099
|
+
instructionPolicyEvidence: worker.instructionPolicyEvidence ?? null,
|
|
2100
|
+
model: worker.model ?? worker.orchestrationAudit?.model ?? null,
|
|
2101
|
+
provider: worker.orchestrationAudit?.provider ?? null,
|
|
2102
|
+
boxKind: worker.boxKind ?? null,
|
|
2103
|
+
boxId: worker.boxId ?? null,
|
|
2104
|
+
runtimeId: worker.runtimeId ?? null,
|
|
2105
|
+
personaSlug: worker.personaSlug ?? null,
|
|
2106
|
+
dispatched: worker.dispatched ?? null,
|
|
2107
|
+
localOnly: worker.localOnly ?? null
|
|
1986
2108
|
};
|
|
1987
2109
|
}
|
|
1988
2110
|
function isFinishedWorkerStatus(status) {
|
|
@@ -2004,8 +2126,26 @@ function deriveRunStatus(fallback, workers) {
|
|
|
2004
2126
|
if (workers.some((w) => w.status === "running")) return "running";
|
|
2005
2127
|
return fallback;
|
|
2006
2128
|
}
|
|
2129
|
+
var NO_START_MS, STALE_MS;
|
|
2130
|
+
var init_status = __esm({
|
|
2131
|
+
"src/status.ts"() {
|
|
2132
|
+
"use strict";
|
|
2133
|
+
init_heartbeat();
|
|
2134
|
+
init_stream();
|
|
2135
|
+
init_exit_classify();
|
|
2136
|
+
init_exited_salvage();
|
|
2137
|
+
init_git();
|
|
2138
|
+
init_landing_gate();
|
|
2139
|
+
init_landing_contract_gate();
|
|
2140
|
+
init_worker_final_result_embed();
|
|
2141
|
+
init_util();
|
|
2142
|
+
NO_START_MS = 18e4;
|
|
2143
|
+
STALE_MS = 6e5;
|
|
2144
|
+
}
|
|
2145
|
+
});
|
|
2007
2146
|
|
|
2008
2147
|
// src/harness-worker-active.ts
|
|
2148
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
2009
2149
|
function pidCommandLine(pid) {
|
|
2010
2150
|
if (!pid || process.platform !== "linux") return null;
|
|
2011
2151
|
try {
|
|
@@ -2031,12 +2171,16 @@ function isActiveHarnessWorker(worker) {
|
|
|
2031
2171
|
if (status.alive && !workerProcessMatchesRecord(worker)) return false;
|
|
2032
2172
|
return status.alive && !status.finalResult && status.attention.state !== "done";
|
|
2033
2173
|
}
|
|
2174
|
+
var init_harness_worker_active = __esm({
|
|
2175
|
+
"src/harness-worker-active.ts"() {
|
|
2176
|
+
"use strict";
|
|
2177
|
+
init_status();
|
|
2178
|
+
}
|
|
2179
|
+
});
|
|
2034
2180
|
|
|
2035
2181
|
// src/resource-gate.ts
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
var DEFAULT_MEM_UTILIZATION = 0.85;
|
|
2039
|
-
var AUTO_MAX_WORKERS_CEILING = 64;
|
|
2182
|
+
import os2 from "node:os";
|
|
2183
|
+
import path7 from "node:path";
|
|
2040
2184
|
function positiveInt(value, fallback) {
|
|
2041
2185
|
const n = Number(value);
|
|
2042
2186
|
if (!Number.isFinite(n) || n <= 0) return fallback;
|
|
@@ -2142,6 +2286,25 @@ function observeRunnerResourceGate(input) {
|
|
|
2142
2286
|
...diskGate ? { diskGate } : {}
|
|
2143
2287
|
};
|
|
2144
2288
|
}
|
|
2289
|
+
var DEFAULT_PER_WORKER_MEM_BYTES, DEFAULT_MEM_RESERVE_BYTES, DEFAULT_MEM_UTILIZATION, AUTO_MAX_WORKERS_CEILING;
|
|
2290
|
+
var init_resource_gate = __esm({
|
|
2291
|
+
"src/resource-gate.ts"() {
|
|
2292
|
+
"use strict";
|
|
2293
|
+
init_meminfo();
|
|
2294
|
+
init_config();
|
|
2295
|
+
init_box_identity();
|
|
2296
|
+
init_worker_cap_source();
|
|
2297
|
+
init_disk_gate();
|
|
2298
|
+
init_run_store();
|
|
2299
|
+
init_run_worker_index();
|
|
2300
|
+
init_harness_worker_active();
|
|
2301
|
+
init_util();
|
|
2302
|
+
DEFAULT_PER_WORKER_MEM_BYTES = 500 * 1024 * 1024;
|
|
2303
|
+
DEFAULT_MEM_RESERVE_BYTES = 4 * 1024 * 1024 * 1024;
|
|
2304
|
+
DEFAULT_MEM_UTILIZATION = 0.85;
|
|
2305
|
+
AUTO_MAX_WORKERS_CEILING = 64;
|
|
2306
|
+
}
|
|
2307
|
+
});
|
|
2145
2308
|
|
|
2146
2309
|
// src/worker-cap-source.ts
|
|
2147
2310
|
function positiveInt2(value, fallback) {
|
|
@@ -2213,12 +2376,113 @@ function recommendSetupWorkerCap(input = {}) {
|
|
|
2213
2376
|
diskFreeBytes: input.diskFreeBytes ?? null
|
|
2214
2377
|
};
|
|
2215
2378
|
}
|
|
2379
|
+
var init_worker_cap_source = __esm({
|
|
2380
|
+
"src/worker-cap-source.ts"() {
|
|
2381
|
+
"use strict";
|
|
2382
|
+
init_resource_gate();
|
|
2383
|
+
}
|
|
2384
|
+
});
|
|
2216
2385
|
|
|
2217
|
-
// src/
|
|
2386
|
+
// src/device-login.ts
|
|
2387
|
+
var device_login_exports = {};
|
|
2388
|
+
__export(device_login_exports, {
|
|
2389
|
+
runDeviceLogin: () => runDeviceLogin
|
|
2390
|
+
});
|
|
2218
2391
|
import os3 from "node:os";
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2392
|
+
function resolveDeviceBaseUrl(args) {
|
|
2393
|
+
const raw = (typeof args.apiBaseUrl === "string" ? args.apiBaseUrl : void 0) || (typeof args.baseUrl === "string" ? args.baseUrl : void 0) || process.env.KYNVER_API_URL || loadUserConfig().apiBaseUrl;
|
|
2394
|
+
return raw ? trimTrailingSlash(String(raw)) : void 0;
|
|
2395
|
+
}
|
|
2396
|
+
async function sleep(ms) {
|
|
2397
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
2398
|
+
}
|
|
2399
|
+
async function runDeviceLogin(args) {
|
|
2400
|
+
const base = resolveDeviceBaseUrl(args);
|
|
2401
|
+
if (!base) {
|
|
2402
|
+
console.error(
|
|
2403
|
+
"kynver login (device flow) requires a Kynver URL \u2014 pass --api-base-url https://your-kynver-site, set KYNVER_API_URL, or run `kynver setup` first."
|
|
2404
|
+
);
|
|
2405
|
+
return { ok: false };
|
|
2406
|
+
}
|
|
2407
|
+
const clientName = `${os3.hostname()} (${os3.platform()})`;
|
|
2408
|
+
let start;
|
|
2409
|
+
try {
|
|
2410
|
+
const res = await fetch(`${base}/api/auth/device/code`, {
|
|
2411
|
+
method: "POST",
|
|
2412
|
+
headers: { "Content-Type": "application/json" },
|
|
2413
|
+
body: JSON.stringify({ clientName })
|
|
2414
|
+
});
|
|
2415
|
+
if (!res.ok) {
|
|
2416
|
+
console.error(`Could not start device authorization (${res.status}).`);
|
|
2417
|
+
return { ok: false };
|
|
2418
|
+
}
|
|
2419
|
+
start = await res.json();
|
|
2420
|
+
} catch (err) {
|
|
2421
|
+
console.error(`Could not reach ${base}: ${err.message}`);
|
|
2422
|
+
return { ok: false };
|
|
2423
|
+
}
|
|
2424
|
+
const verifyUrl = start.verification_uri_complete || start.verification_uri;
|
|
2425
|
+
console.log("");
|
|
2426
|
+
console.log(" Authorize this machine:");
|
|
2427
|
+
console.log(` 1. Open: ${verifyUrl}`);
|
|
2428
|
+
console.log(` 2. Confirm the code: ${start.user_code}`);
|
|
2429
|
+
console.log("");
|
|
2430
|
+
console.log(" Waiting for approval\u2026");
|
|
2431
|
+
const deadline = Date.now() + start.expires_in * 1e3;
|
|
2432
|
+
let intervalMs = Math.max(1, start.interval) * 1e3;
|
|
2433
|
+
while (Date.now() < deadline) {
|
|
2434
|
+
await sleep(intervalMs);
|
|
2435
|
+
let body;
|
|
2436
|
+
try {
|
|
2437
|
+
const res = await fetch(`${base}/api/auth/device/token`, {
|
|
2438
|
+
method: "POST",
|
|
2439
|
+
headers: { "Content-Type": "application/json" },
|
|
2440
|
+
body: JSON.stringify({ device_code: start.device_code })
|
|
2441
|
+
});
|
|
2442
|
+
body = await res.json().catch(() => ({}));
|
|
2443
|
+
} catch {
|
|
2444
|
+
continue;
|
|
2445
|
+
}
|
|
2446
|
+
switch (body.status) {
|
|
2447
|
+
case "approved":
|
|
2448
|
+
if (body.api_key) {
|
|
2449
|
+
saveApiKey(body.api_key);
|
|
2450
|
+
console.log(" Approved \u2014 this machine is now linked to your Kynver account.");
|
|
2451
|
+
return { ok: true, apiKey: body.api_key };
|
|
2452
|
+
}
|
|
2453
|
+
return { ok: false };
|
|
2454
|
+
case "slow_down":
|
|
2455
|
+
intervalMs += 2e3;
|
|
2456
|
+
break;
|
|
2457
|
+
case "authorization_pending":
|
|
2458
|
+
if (typeof body.interval === "number") intervalMs = Math.max(intervalMs, body.interval * 1e3);
|
|
2459
|
+
break;
|
|
2460
|
+
case "access_denied":
|
|
2461
|
+
console.error(" Request was denied in the browser.");
|
|
2462
|
+
return { ok: false };
|
|
2463
|
+
case "expired_token":
|
|
2464
|
+
console.error(" The code expired before it was approved. Run `kynver login` again.");
|
|
2465
|
+
return { ok: false };
|
|
2466
|
+
default:
|
|
2467
|
+
break;
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
console.error(" Timed out waiting for approval. Run `kynver login` again.");
|
|
2471
|
+
return { ok: false };
|
|
2472
|
+
}
|
|
2473
|
+
var init_device_login = __esm({
|
|
2474
|
+
"src/device-login.ts"() {
|
|
2475
|
+
"use strict";
|
|
2476
|
+
init_config();
|
|
2477
|
+
init_util();
|
|
2478
|
+
}
|
|
2479
|
+
});
|
|
2480
|
+
|
|
2481
|
+
// src/config.ts
|
|
2482
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync2, readFileSync as readFileSync8, writeFileSync as writeFileSync2 } from "node:fs";
|
|
2483
|
+
import { homedir as homedir4, totalmem } from "node:os";
|
|
2484
|
+
import path8 from "node:path";
|
|
2485
|
+
import os4 from "node:os";
|
|
2222
2486
|
function loadUserConfig() {
|
|
2223
2487
|
if (!existsSync9(CONFIG_FILE)) return {};
|
|
2224
2488
|
try {
|
|
@@ -2257,8 +2521,6 @@ function inferSetupFields(existing, args) {
|
|
|
2257
2521
|
...typeof args.agentOsSlug === "string" ? { agentOsSlug: args.agentOsSlug } : existing.agentOsSlug ? { agentOsSlug: existing.agentOsSlug } : {}
|
|
2258
2522
|
};
|
|
2259
2523
|
}
|
|
2260
|
-
var SETUP_PER_WORKER_MEM_BYTES = 500 * 1024 * 1024;
|
|
2261
|
-
var SETUP_MEM_RESERVE_BYTES = 4 * 1024 * 1024 * 1024;
|
|
2262
2524
|
function resolveSetupWorkerConfig(existing, args, totalMemBytes = totalmem()) {
|
|
2263
2525
|
const maxWorkersRaw = typeof args.maxWorkers === "string" ? args.maxWorkers : typeof args.maxConcurrentWorkers === "string" ? args.maxConcurrentWorkers : void 0;
|
|
2264
2526
|
const explicitBoxKindArg = typeof args.boxKind === "string" ? args.boxKind : typeof args["box-kind"] === "string" ? String(args["box-kind"]) : void 0;
|
|
@@ -2479,7 +2741,7 @@ async function runSetup(args) {
|
|
|
2479
2741
|
diskPath: typeof args.diskPath === "string" ? args.diskPath : "/"
|
|
2480
2742
|
});
|
|
2481
2743
|
const capRecommendation = recommendSetupWorkerCap({
|
|
2482
|
-
totalMemBytes:
|
|
2744
|
+
totalMemBytes: os4.totalmem(),
|
|
2483
2745
|
diskPath: diskGate.path,
|
|
2484
2746
|
diskGateOk: diskGate.ok,
|
|
2485
2747
|
diskFreeBytes: diskGate.freeBytes,
|
|
@@ -2528,10 +2790,104 @@ async function runSetup(args) {
|
|
|
2528
2790
|
}
|
|
2529
2791
|
async function runLogin(args) {
|
|
2530
2792
|
const apiKey = typeof args.apiKey === "string" ? args.apiKey : process.env.KYNVER_API_KEY;
|
|
2531
|
-
if (
|
|
2532
|
-
|
|
2793
|
+
if (apiKey) {
|
|
2794
|
+
saveApiKey(apiKey);
|
|
2795
|
+
console.log(JSON.stringify({ ok: true, credentialsPath: displayUserPath(CREDENTIALS_FILE) }, null, 2));
|
|
2796
|
+
return;
|
|
2797
|
+
}
|
|
2798
|
+
const { runDeviceLogin: runDeviceLogin2 } = await Promise.resolve().then(() => (init_device_login(), device_login_exports));
|
|
2799
|
+
const result = await runDeviceLogin2(args);
|
|
2800
|
+
if (!result.ok) process.exit(1);
|
|
2533
2801
|
console.log(JSON.stringify({ ok: true, credentialsPath: displayUserPath(CREDENTIALS_FILE) }, null, 2));
|
|
2534
2802
|
}
|
|
2803
|
+
var CONFIG_DIR, CONFIG_FILE, CREDENTIALS_FILE, SETUP_PER_WORKER_MEM_BYTES, SETUP_MEM_RESERVE_BYTES;
|
|
2804
|
+
var init_config = __esm({
|
|
2805
|
+
"src/config.ts"() {
|
|
2806
|
+
"use strict";
|
|
2807
|
+
init_default_repo_discovery();
|
|
2808
|
+
init_path_values();
|
|
2809
|
+
init_util();
|
|
2810
|
+
init_box_identity();
|
|
2811
|
+
init_worker_cap_source();
|
|
2812
|
+
init_disk_gate();
|
|
2813
|
+
CONFIG_DIR = path8.join(homedir4(), ".kynver");
|
|
2814
|
+
CONFIG_FILE = path8.join(CONFIG_DIR, "config.json");
|
|
2815
|
+
CREDENTIALS_FILE = path8.join(CONFIG_DIR, "credentials");
|
|
2816
|
+
SETUP_PER_WORKER_MEM_BYTES = 500 * 1024 * 1024;
|
|
2817
|
+
SETUP_MEM_RESERVE_BYTES = 4 * 1024 * 1024 * 1024;
|
|
2818
|
+
}
|
|
2819
|
+
});
|
|
2820
|
+
|
|
2821
|
+
// src/cli.ts
|
|
2822
|
+
init_config();
|
|
2823
|
+
import { mkdirSync as mkdirSync11, realpathSync } from "node:fs";
|
|
2824
|
+
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
2825
|
+
|
|
2826
|
+
// src/bootstrap.ts
|
|
2827
|
+
init_config();
|
|
2828
|
+
init_util();
|
|
2829
|
+
init_device_login();
|
|
2830
|
+
import os5 from "node:os";
|
|
2831
|
+
function resolveBootstrapBaseUrl(args) {
|
|
2832
|
+
const raw = (typeof args.apiBaseUrl === "string" ? args.apiBaseUrl : void 0) || (typeof args.baseUrl === "string" ? args.baseUrl : void 0) || process.env.KYNVER_API_URL || loadUserConfig().apiBaseUrl;
|
|
2833
|
+
return raw ? trimTrailingSlash(String(raw)) : void 0;
|
|
2834
|
+
}
|
|
2835
|
+
async function fetchPrimaryAgentOs(base, apiKey) {
|
|
2836
|
+
const res = await fetch(`${base}/api/agent-os`, {
|
|
2837
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
2838
|
+
});
|
|
2839
|
+
if (!res.ok) return null;
|
|
2840
|
+
const body = await res.json().catch(() => null);
|
|
2841
|
+
if (!body?.primarySlug) return null;
|
|
2842
|
+
const match = body.items?.find((it) => it.slug === body.primarySlug);
|
|
2843
|
+
if (match?.id && match.slug) return { id: match.id, slug: match.slug };
|
|
2844
|
+
return { id: "", slug: body.primarySlug };
|
|
2845
|
+
}
|
|
2846
|
+
async function runBootstrap(args) {
|
|
2847
|
+
const base = resolveBootstrapBaseUrl(args);
|
|
2848
|
+
if (!base) {
|
|
2849
|
+
console.error(
|
|
2850
|
+
"kynver bootstrap requires a Kynver URL \u2014 pass --api-base-url https://your-kynver-site or set KYNVER_API_URL."
|
|
2851
|
+
);
|
|
2852
|
+
process.exit(1);
|
|
2853
|
+
}
|
|
2854
|
+
if (!loadApiKey()) {
|
|
2855
|
+
if (typeof args.apiKey === "string") {
|
|
2856
|
+
saveApiKey(args.apiKey);
|
|
2857
|
+
} else {
|
|
2858
|
+
const login = await runDeviceLogin({ ...args, apiBaseUrl: base });
|
|
2859
|
+
if (!login.ok) process.exit(1);
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2862
|
+
const apiKey = loadApiKey();
|
|
2863
|
+
if (!apiKey) {
|
|
2864
|
+
console.error("No API key after login \u2014 aborting.");
|
|
2865
|
+
process.exit(1);
|
|
2866
|
+
}
|
|
2867
|
+
const primary = await fetchPrimaryAgentOs(base, apiKey);
|
|
2868
|
+
if (!primary) {
|
|
2869
|
+
console.error(
|
|
2870
|
+
"Could not resolve your AgentOS workspace from the account. Confirm this account has AgentOS access, then retry."
|
|
2871
|
+
);
|
|
2872
|
+
process.exit(1);
|
|
2873
|
+
}
|
|
2874
|
+
const setupArgs = {
|
|
2875
|
+
...args,
|
|
2876
|
+
apiBaseUrl: base,
|
|
2877
|
+
agentOsSlug: primary.slug,
|
|
2878
|
+
...primary.id ? { agentOsId: primary.id } : {},
|
|
2879
|
+
// Best-effort repo discovery unless the caller pinned one.
|
|
2880
|
+
...typeof args.repo === "string" ? {} : { discoverRepo: true }
|
|
2881
|
+
};
|
|
2882
|
+
await runSetup(setupArgs);
|
|
2883
|
+
console.log("");
|
|
2884
|
+
console.log(` Bootstrap complete \u2014 ${os5.hostname()} is linked to workspace "${primary.slug}".`);
|
|
2885
|
+
console.log(" Next: run autonomous work with `kynver daemon --run <RUN_ID> --agent-os-id <AOS_ID> --execute`");
|
|
2886
|
+
console.log(" (create a run first with `kynver run create --repo /path/to/repo`).");
|
|
2887
|
+
}
|
|
2888
|
+
|
|
2889
|
+
// src/dispatch.ts
|
|
2890
|
+
init_config();
|
|
2535
2891
|
|
|
2536
2892
|
// src/callback-headers.ts
|
|
2537
2893
|
function buildHarnessCallbackHeaders(secret) {
|
|
@@ -2555,6 +2911,7 @@ function buildHarnessCallbackHeaders(secret) {
|
|
|
2555
2911
|
}
|
|
2556
2912
|
|
|
2557
2913
|
// src/callbacks.ts
|
|
2914
|
+
init_config();
|
|
2558
2915
|
function callbackTimeoutMs() {
|
|
2559
2916
|
const parsed = Number(process.env.KYNVER_CALLBACK_TIMEOUT_MS);
|
|
2560
2917
|
if (Number.isFinite(parsed) && parsed > 0) return Math.floor(parsed);
|
|
@@ -2768,6 +3125,12 @@ function resolveDispatchNextLaneFilter(raw) {
|
|
|
2768
3125
|
return normalizeDispatchNextLaneFilter(raw) ?? "any";
|
|
2769
3126
|
}
|
|
2770
3127
|
|
|
3128
|
+
// src/dispatch.ts
|
|
3129
|
+
init_disk_gate();
|
|
3130
|
+
init_resource_gate();
|
|
3131
|
+
init_run_store();
|
|
3132
|
+
init_run_store();
|
|
3133
|
+
|
|
2771
3134
|
// src/model-routing-task-enrich.ts
|
|
2772
3135
|
function taskString(task, key) {
|
|
2773
3136
|
const v = task[key];
|
|
@@ -2817,6 +3180,9 @@ function enrichTaskForModelRouting(task) {
|
|
|
2817
3180
|
return { ...task, roleLane };
|
|
2818
3181
|
}
|
|
2819
3182
|
|
|
3183
|
+
// src/model-routing.ts
|
|
3184
|
+
init_config();
|
|
3185
|
+
|
|
2820
3186
|
// src/worker-provider-policy.ts
|
|
2821
3187
|
var DEFAULT_WORKER_PROVIDER = "cursor";
|
|
2822
3188
|
var CLAUDE_FAMILY = /* @__PURE__ */ new Set(["claude", "opus", "anthropic"]);
|
|
@@ -3480,6 +3846,8 @@ function resolveOrchestrationRouting(input) {
|
|
|
3480
3846
|
}
|
|
3481
3847
|
|
|
3482
3848
|
// src/providers/claude.ts
|
|
3849
|
+
init_worker_env();
|
|
3850
|
+
init_util();
|
|
3483
3851
|
import { closeSync, openSync } from "node:fs";
|
|
3484
3852
|
import { spawn } from "node:child_process";
|
|
3485
3853
|
|
|
@@ -3617,13 +3985,17 @@ var claudeProvider = {
|
|
|
3617
3985
|
};
|
|
3618
3986
|
|
|
3619
3987
|
// src/providers/codex.ts
|
|
3988
|
+
init_worker_env();
|
|
3989
|
+
init_util();
|
|
3620
3990
|
import { closeSync as closeSync3, existsSync as existsSync15, openSync as openSync3 } from "node:fs";
|
|
3621
3991
|
import { spawn as spawn3 } from "node:child_process";
|
|
3622
3992
|
|
|
3623
3993
|
// src/providers/hermes-codex.ts
|
|
3994
|
+
init_worker_env();
|
|
3995
|
+
init_util();
|
|
3624
3996
|
import { closeSync as closeSync2, openSync as openSync2 } from "node:fs";
|
|
3625
3997
|
import { spawn as spawn2 } from "node:child_process";
|
|
3626
|
-
var HERMES_OPENAI_CODEX_DEFAULT_MODEL = "gpt-5.4";
|
|
3998
|
+
var HERMES_OPENAI_CODEX_DEFAULT_MODEL = process.env.KYNVER_CODEX_DEFAULT_MODEL?.trim() || "gpt-5.4";
|
|
3627
3999
|
function hermesWorkerEnv() {
|
|
3628
4000
|
return scrubWorkerEnv({
|
|
3629
4001
|
...process.env,
|
|
@@ -3691,7 +4063,10 @@ var hermesCodexProvider = {
|
|
|
3691
4063
|
};
|
|
3692
4064
|
|
|
3693
4065
|
// src/providers/codex.ts
|
|
3694
|
-
|
|
4066
|
+
function resolveCodexDefaultModel() {
|
|
4067
|
+
return process.env.KYNVER_CODEX_DEFAULT_MODEL?.trim() || "gpt-5.4";
|
|
4068
|
+
}
|
|
4069
|
+
var CODEX_DEFAULT_MODEL = resolveCodexDefaultModel();
|
|
3695
4070
|
function resolveCodexBin() {
|
|
3696
4071
|
return process.env.KYNVER_CODEX_BIN?.trim() || process.env.CODEX_BIN?.trim() || "codex";
|
|
3697
4072
|
}
|
|
@@ -3943,7 +4318,11 @@ function readHarnessRetryLimits() {
|
|
|
3943
4318
|
}
|
|
3944
4319
|
|
|
3945
4320
|
// src/lease-renewal.ts
|
|
4321
|
+
init_config();
|
|
3946
4322
|
import path14 from "node:path";
|
|
4323
|
+
init_run_store();
|
|
4324
|
+
init_status();
|
|
4325
|
+
init_util();
|
|
3947
4326
|
|
|
3948
4327
|
// src/harness-lease-owner.ts
|
|
3949
4328
|
var HARNESS_LEASE_PREFIX = "kynver-harness:";
|
|
@@ -3979,12 +4358,14 @@ function resolveHarnessLeaseOwnerForRenewal(input) {
|
|
|
3979
4358
|
}
|
|
3980
4359
|
|
|
3981
4360
|
// src/runner-identity.ts
|
|
3982
|
-
import
|
|
4361
|
+
import os7 from "node:os";
|
|
3983
4362
|
|
|
3984
4363
|
// src/box-resource-snapshot-shared.ts
|
|
3985
|
-
|
|
4364
|
+
init_box_identity();
|
|
4365
|
+
init_box_identity();
|
|
4366
|
+
import os6 from "node:os";
|
|
3986
4367
|
function defaultBoxId(boxKind, hostLabel) {
|
|
3987
|
-
const host = (hostLabel ??
|
|
4368
|
+
const host = (hostLabel ?? os6.hostname()).trim().toLowerCase().replace(/\s+/g, "-") || "unknown-host";
|
|
3988
4369
|
return `${boxKind}:${host}`;
|
|
3989
4370
|
}
|
|
3990
4371
|
|
|
@@ -3995,10 +4376,10 @@ function trimOrNull5(value) {
|
|
|
3995
4376
|
}
|
|
3996
4377
|
function resolveRunnerPresencePayload(input = {}) {
|
|
3997
4378
|
const env = input.env ?? process.env;
|
|
3998
|
-
const runnerId = trimOrNull5(env.KYNVER_RUNTIME_ID) ?? trimOrNull5(env.OPENCLAW_RUNTIME_ID) ?? trimOrNull5(env.HOSTNAME) ??
|
|
4379
|
+
const runnerId = trimOrNull5(env.KYNVER_RUNTIME_ID) ?? trimOrNull5(env.OPENCLAW_RUNTIME_ID) ?? trimOrNull5(env.HOSTNAME) ?? os7.hostname();
|
|
3999
4380
|
return {
|
|
4000
4381
|
runnerId,
|
|
4001
|
-
hostname: trimOrNull5(env.HOSTNAME) ??
|
|
4382
|
+
hostname: trimOrNull5(env.HOSTNAME) ?? os7.hostname(),
|
|
4002
4383
|
profile: trimOrNull5(env.KYNVER_RUNNER_PROFILE) ?? trimOrNull5(env.OPENCLAW_RUNNER_PROFILE),
|
|
4003
4384
|
harnessRepo: trimOrNull5(env.KYNVER_HARNESS_REPO) ?? trimOrNull5(env.KYNVER_DEFAULT_REPO),
|
|
4004
4385
|
runId: input.runId ?? null
|
|
@@ -4083,6 +4464,9 @@ function hasLiveWorkerForTask(runId, taskId) {
|
|
|
4083
4464
|
}
|
|
4084
4465
|
|
|
4085
4466
|
// src/supervisor.ts
|
|
4467
|
+
init_git();
|
|
4468
|
+
init_run_store();
|
|
4469
|
+
init_run_store();
|
|
4086
4470
|
import { existsSync as existsSync19, mkdirSync as mkdirSync4 } from "node:fs";
|
|
4087
4471
|
import path21 from "node:path";
|
|
4088
4472
|
|
|
@@ -4232,10 +4616,18 @@ function buildPrompt(input) {
|
|
|
4232
4616
|
].join("\n");
|
|
4233
4617
|
}
|
|
4234
4618
|
|
|
4619
|
+
// src/supervisor.ts
|
|
4620
|
+
init_util();
|
|
4621
|
+
|
|
4622
|
+
// src/providers/registry.ts
|
|
4623
|
+
init_config();
|
|
4624
|
+
|
|
4235
4625
|
// src/providers/cursor.ts
|
|
4626
|
+
init_util();
|
|
4627
|
+
init_worker_env();
|
|
4236
4628
|
import { closeSync as closeSync4, existsSync as existsSync17, mkdirSync as mkdirSync3, openSync as openSync4, statSync as statSync4, unlinkSync } from "node:fs";
|
|
4237
4629
|
import { spawn as spawn4 } from "node:child_process";
|
|
4238
|
-
import
|
|
4630
|
+
import os8 from "node:os";
|
|
4239
4631
|
import path16 from "node:path";
|
|
4240
4632
|
|
|
4241
4633
|
// src/providers/cursor-windows.ts
|
|
@@ -4346,7 +4738,7 @@ function positiveIntEnv(name, fallback) {
|
|
|
4346
4738
|
return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : fallback;
|
|
4347
4739
|
}
|
|
4348
4740
|
function cursorStartLockPath() {
|
|
4349
|
-
const root = process.env.KYNVER_CURSOR_START_LOCK_DIR?.trim() || path16.join(
|
|
4741
|
+
const root = process.env.KYNVER_CURSOR_START_LOCK_DIR?.trim() || path16.join(os8.homedir(), ".kynver", "locks");
|
|
4350
4742
|
mkdirSync3(root, { recursive: true });
|
|
4351
4743
|
return path16.join(root, "cursor-agent-start.lock");
|
|
4352
4744
|
}
|
|
@@ -4472,12 +4864,14 @@ function resolveWorkerProvider(name) {
|
|
|
4472
4864
|
}
|
|
4473
4865
|
|
|
4474
4866
|
// src/auto-complete.ts
|
|
4867
|
+
init_util();
|
|
4475
4868
|
import { spawn as spawn5 } from "node:child_process";
|
|
4476
4869
|
import { existsSync as existsSync18, openSync as openSync5, closeSync as closeSync5 } from "node:fs";
|
|
4477
4870
|
import path20 from "node:path";
|
|
4478
4871
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
4479
4872
|
|
|
4480
4873
|
// src/completion-ack.ts
|
|
4874
|
+
init_run_store();
|
|
4481
4875
|
function hasCompletionAck(worker) {
|
|
4482
4876
|
return Boolean(worker.completionReportedAt?.trim());
|
|
4483
4877
|
}
|
|
@@ -4505,7 +4899,12 @@ function hasTerminalCompletionAck(worker) {
|
|
|
4505
4899
|
return hasCompletionAck(worker) && !shouldReplayHarnessCompletion(worker);
|
|
4506
4900
|
}
|
|
4507
4901
|
|
|
4902
|
+
// src/auto-complete.ts
|
|
4903
|
+
init_run_store();
|
|
4904
|
+
init_status();
|
|
4905
|
+
|
|
4508
4906
|
// src/worker-ops.ts
|
|
4907
|
+
init_config();
|
|
4509
4908
|
import path19 from "node:path";
|
|
4510
4909
|
|
|
4511
4910
|
// src/completion-response.ts
|
|
@@ -4547,6 +4946,10 @@ function completionPostSucceeded(summary) {
|
|
|
4547
4946
|
return summary.taskAdvanced;
|
|
4548
4947
|
}
|
|
4549
4948
|
|
|
4949
|
+
// src/worker-ops.ts
|
|
4950
|
+
init_run_store();
|
|
4951
|
+
init_exited_salvage();
|
|
4952
|
+
|
|
4550
4953
|
// src/harness-expert-review.ts
|
|
4551
4954
|
var EXPERT_LANE_REVIEW_REF = "expert-lane-pr-review:";
|
|
4552
4955
|
var PLAN_REVIEW_EXECUTOR_REF = "plan-review-task";
|
|
@@ -4714,6 +5117,7 @@ function normalizeOwnerRepo(value) {
|
|
|
4714
5117
|
}
|
|
4715
5118
|
|
|
4716
5119
|
// src/pr-handoff/pr-handoff-gh.ts
|
|
5120
|
+
init_git();
|
|
4717
5121
|
function capture(bin, cwd, args) {
|
|
4718
5122
|
try {
|
|
4719
5123
|
const res = spawnSync3(bin, args, { cwd, encoding: "utf8" });
|
|
@@ -5084,6 +5488,10 @@ function ensurePrReadyHandoff(input, exec = defaultPrHandoffExec) {
|
|
|
5084
5488
|
};
|
|
5085
5489
|
}
|
|
5086
5490
|
|
|
5491
|
+
// src/worker-ops.ts
|
|
5492
|
+
init_status();
|
|
5493
|
+
init_stream();
|
|
5494
|
+
|
|
5087
5495
|
// src/material-worktree-changes.ts
|
|
5088
5496
|
function materialWorktreeChanges(changedFiles) {
|
|
5089
5497
|
return changedFiles.filter((line) => {
|
|
@@ -5126,8 +5534,8 @@ function dirtyPathsCoveredByDisposableRemoval(changedFiles, removed) {
|
|
|
5126
5534
|
if (removed.length === 0) return false;
|
|
5127
5535
|
const removedSet = new Set(removed.map((p) => normalizeRelativePath(p)));
|
|
5128
5536
|
return material.every((line) => {
|
|
5129
|
-
const
|
|
5130
|
-
return removedSet.has(
|
|
5537
|
+
const path73 = normalizeRelativePath(pathFromGitStatusLine(line));
|
|
5538
|
+
return removedSet.has(path73);
|
|
5131
5539
|
});
|
|
5132
5540
|
}
|
|
5133
5541
|
|
|
@@ -5212,6 +5620,9 @@ function assessWorktreeCompletionHandoff(input) {
|
|
|
5212
5620
|
}
|
|
5213
5621
|
|
|
5214
5622
|
// src/worker-lifecycle.ts
|
|
5623
|
+
init_run_store();
|
|
5624
|
+
init_status();
|
|
5625
|
+
init_util();
|
|
5215
5626
|
import path17 from "node:path";
|
|
5216
5627
|
var TASK_LEFT_RUNNING = /* @__PURE__ */ new Set([
|
|
5217
5628
|
"awaiting_review",
|
|
@@ -5303,7 +5714,11 @@ function syncCompletionAcknowledgedFromOperatorTick(runId, operatorTick) {
|
|
|
5303
5714
|
return synced;
|
|
5304
5715
|
}
|
|
5305
5716
|
|
|
5717
|
+
// src/worker-ops.ts
|
|
5718
|
+
init_util();
|
|
5719
|
+
|
|
5306
5720
|
// src/validate.ts
|
|
5721
|
+
init_util();
|
|
5307
5722
|
import path18 from "node:path";
|
|
5308
5723
|
var RUN_ID_RE = /^[a-z0-9][a-z0-9._-]{0,127}$/i;
|
|
5309
5724
|
var WORKER_NAME_RE = /^[a-z0-9][a-z0-9._-]{0,63}$/i;
|
|
@@ -6076,6 +6491,7 @@ function stopWorker(args) {
|
|
|
6076
6491
|
}
|
|
6077
6492
|
|
|
6078
6493
|
// src/auto-complete.ts
|
|
6494
|
+
init_util();
|
|
6079
6495
|
var DEFAULT_POLL_MS = 5e3;
|
|
6080
6496
|
var DEFAULT_MAX_TOTAL_MS = 6 * 60 * 60 * 1e3;
|
|
6081
6497
|
var DEFAULT_COMPLETE_ATTEMPTS = 3;
|
|
@@ -6260,6 +6676,7 @@ function spawnCompletionSidecar(opts) {
|
|
|
6260
6676
|
}
|
|
6261
6677
|
|
|
6262
6678
|
// src/repair-target-worktree.ts
|
|
6679
|
+
init_git();
|
|
6263
6680
|
function addWorktreeForRepairBranch(repo, worktreePath, branch) {
|
|
6264
6681
|
git(repo, ["fetch", "origin", branch, "--prune"], { allowFailure: true });
|
|
6265
6682
|
const remoteRef = `origin/${branch}`;
|
|
@@ -6273,6 +6690,8 @@ function addWorktreeForRepairBranch(repo, worktreePath, branch) {
|
|
|
6273
6690
|
}
|
|
6274
6691
|
|
|
6275
6692
|
// src/supervisor.ts
|
|
6693
|
+
init_box_identity();
|
|
6694
|
+
init_config();
|
|
6276
6695
|
function spawnWorkerProcess(run, opts) {
|
|
6277
6696
|
const rawName = typeof opts.name === "string" ? opts.name.trim() : "";
|
|
6278
6697
|
if (!rawName || rawName === "undefined" || rawName === "null") {
|
|
@@ -6366,6 +6785,10 @@ function spawnWorkerProcess(run, opts) {
|
|
|
6366
6785
|
else process.env.KYNVER_HARNESS_AGENT_OS_ID = prevHarnessAgentOsId;
|
|
6367
6786
|
}
|
|
6368
6787
|
const model = resolveModelFallback(started.model, launchModel, provider.defaultModel);
|
|
6788
|
+
const config = loadUserConfig();
|
|
6789
|
+
const boxIdentity = resolveBoxIdentity(process.env, config);
|
|
6790
|
+
const runtimeId = resolveRunnerPresencePayload().runnerId;
|
|
6791
|
+
const boxId = defaultBoxId(boxIdentity.boxKind);
|
|
6369
6792
|
const worker = {
|
|
6370
6793
|
name,
|
|
6371
6794
|
runId: run.id,
|
|
@@ -6401,6 +6824,9 @@ function spawnWorkerProcess(run, opts) {
|
|
|
6401
6824
|
...opts.taskPrUrl ? { taskPrUrl: String(opts.taskPrUrl) } : {},
|
|
6402
6825
|
...opts.repairTargetPrUrl ? { repairTargetPrUrl: String(opts.repairTargetPrUrl) } : {},
|
|
6403
6826
|
...opts.repairTargetBranch ? { repairTargetBranch: String(opts.repairTargetBranch) } : {},
|
|
6827
|
+
boxKind: boxIdentity.boxKind,
|
|
6828
|
+
boxId,
|
|
6829
|
+
runtimeId,
|
|
6404
6830
|
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6405
6831
|
};
|
|
6406
6832
|
saveWorker(run.id, worker);
|
|
@@ -6499,6 +6925,9 @@ async function startWorker(args) {
|
|
|
6499
6925
|
}
|
|
6500
6926
|
|
|
6501
6927
|
// src/active-harness-workers.ts
|
|
6928
|
+
init_run_store();
|
|
6929
|
+
init_harness_worker_active();
|
|
6930
|
+
init_util();
|
|
6502
6931
|
import path22 from "node:path";
|
|
6503
6932
|
function workerWriteSetFields(worker) {
|
|
6504
6933
|
const ownedPaths = Array.isArray(worker.ownedPaths) ? worker.ownedPaths.filter((p) => typeof p === "string") : [];
|
|
@@ -6531,6 +6960,9 @@ function collectRunActiveHarnessWorkers(runId) {
|
|
|
6531
6960
|
return out;
|
|
6532
6961
|
}
|
|
6533
6962
|
|
|
6963
|
+
// src/dispatch.ts
|
|
6964
|
+
init_util();
|
|
6965
|
+
|
|
6534
6966
|
// src/plan-persist/body-hash.ts
|
|
6535
6967
|
import { createHash as createHash2 } from "node:crypto";
|
|
6536
6968
|
function hashPlanBody(body) {
|
|
@@ -6544,6 +6976,9 @@ function hashSummary(summary) {
|
|
|
6544
6976
|
return createHash2("sha256").update(trimmed, "utf8").digest("hex");
|
|
6545
6977
|
}
|
|
6546
6978
|
|
|
6979
|
+
// src/plan-persist/agentos-api.ts
|
|
6980
|
+
init_config();
|
|
6981
|
+
|
|
6547
6982
|
// src/plan-persist/errors.ts
|
|
6548
6983
|
var PlanPersistError = class extends Error {
|
|
6549
6984
|
kind;
|
|
@@ -7208,11 +7643,11 @@ function classifyChecks(statusCheckRollup) {
|
|
|
7208
7643
|
continue;
|
|
7209
7644
|
}
|
|
7210
7645
|
if (state && SUCCESSFUL_CHECK_CONCLUSIONS.has(state)) continue;
|
|
7211
|
-
if (state && state !== "PENDING") {
|
|
7646
|
+
if (state && state !== "PENDING" && state !== "EXPECTED") {
|
|
7212
7647
|
failed.push(`${checkName(check3)}=${state}`);
|
|
7213
7648
|
continue;
|
|
7214
7649
|
}
|
|
7215
|
-
if (state === "PENDING") {
|
|
7650
|
+
if (state === "PENDING" || state === "EXPECTED") {
|
|
7216
7651
|
pending.push(`${checkName(check3)}=${state}`);
|
|
7217
7652
|
continue;
|
|
7218
7653
|
}
|
|
@@ -7239,8 +7674,8 @@ var LOCAL_VERIFICATION_RE = /typecheck|npm run (test|build|typecheck)|vitest|tsc
|
|
|
7239
7674
|
var DOCS_TITLE_RE = /^docs[(:]/i;
|
|
7240
7675
|
var DOCS_BODY_RE = /docs[- ]only|documentation only|no[- ]code change|no code changes|low[- ]risk|plan tracker only|markdown only/i;
|
|
7241
7676
|
function runtimeVerificationEvidenceSufficient(input) {
|
|
7242
|
-
const title = typeof input.title === "string" ? input.title : "";
|
|
7243
|
-
const body = typeof input.body === "string" ? input.body : "";
|
|
7677
|
+
const title = typeof input.title === "string" ? input.title.trim() : "";
|
|
7678
|
+
const body = typeof input.body === "string" ? input.body.trim() : "";
|
|
7244
7679
|
const docsLowRisk = DOCS_TITLE_RE.test(title) || DOCS_BODY_RE.test(body);
|
|
7245
7680
|
const structuredSection = STRUCTURED_SECTION_RE.test(body);
|
|
7246
7681
|
const localVerification = LOCAL_VERIFICATION_RE.test(body);
|
|
@@ -7392,40 +7827,56 @@ async function executeLandPrMerge(input) {
|
|
|
7392
7827
|
"--squash"
|
|
7393
7828
|
]);
|
|
7394
7829
|
if (mergeRes.status !== 0) {
|
|
7830
|
+
const raced = viewMergedState(exec, cwd, target, input.repo);
|
|
7831
|
+
if (raced) {
|
|
7832
|
+
return {
|
|
7833
|
+
prUrl: raced.url || before.url || prTarget,
|
|
7834
|
+
outcome: "skipped",
|
|
7835
|
+
mergeCommit: raced.mergeCommit?.oid ?? null,
|
|
7836
|
+
reason: `PR #${before.number} is already merged \u2014 merged by another lane during land_pr (race)`
|
|
7837
|
+
};
|
|
7838
|
+
}
|
|
7395
7839
|
return {
|
|
7396
7840
|
prUrl: before.url || prTarget,
|
|
7397
7841
|
outcome: "blocked",
|
|
7398
7842
|
reason: mergeRes.stderr || mergeRes.stdout || "gh pr merge failed"
|
|
7399
7843
|
};
|
|
7400
7844
|
}
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
return {
|
|
7411
|
-
prUrl: after.url || before.url || prTarget,
|
|
7412
|
-
outcome: "blocked",
|
|
7413
|
-
reason: `PR #${after.number} did not verify as merged after gh pr merge`
|
|
7414
|
-
};
|
|
7845
|
+
let after = viewMergedState(exec, cwd, target, input.repo);
|
|
7846
|
+
if (!after) {
|
|
7847
|
+
after = viewMergedState(exec, cwd, target, input.repo);
|
|
7848
|
+
}
|
|
7849
|
+
try {
|
|
7850
|
+
const repo = resolveRepo(exec, cwd, input.repo);
|
|
7851
|
+
deleteRemoteBranch(exec, cwd, repo, before.headRefName);
|
|
7852
|
+
removeBranchWorktrees(cwd, before.headRefName);
|
|
7853
|
+
} catch {
|
|
7415
7854
|
}
|
|
7416
|
-
const repo = resolveRepo(exec, cwd, input.repo);
|
|
7417
|
-
deleteRemoteBranch(exec, cwd, repo, before.headRefName);
|
|
7418
|
-
removeBranchWorktrees(cwd, before.headRefName);
|
|
7419
|
-
const mergeCommit = after.mergeCommit?.oid ?? null;
|
|
7420
7855
|
return {
|
|
7421
|
-
prUrl: after
|
|
7856
|
+
prUrl: after?.url || before.url || prTarget,
|
|
7422
7857
|
outcome: "merged",
|
|
7423
|
-
mergeCommit,
|
|
7424
|
-
reason: `Daemon land_pr merged PR #${
|
|
7858
|
+
mergeCommit: after?.mergeCommit?.oid ?? null,
|
|
7859
|
+
reason: `Daemon land_pr merged PR #${before.number}${after ? "" : " (post-merge view unavailable \u2014 merge verified by gh exit 0)"}`
|
|
7425
7860
|
};
|
|
7426
7861
|
}
|
|
7862
|
+
function viewMergedState(exec, cwd, target, repo) {
|
|
7863
|
+
try {
|
|
7864
|
+
const view = ghJson(exec, cwd, [
|
|
7865
|
+
"pr",
|
|
7866
|
+
"view",
|
|
7867
|
+
target,
|
|
7868
|
+
...repoArgs(repo),
|
|
7869
|
+
"--json",
|
|
7870
|
+
"number,url,mergedAt,mergeCommit,state"
|
|
7871
|
+
]);
|
|
7872
|
+
return view.state === "MERGED" || view.mergedAt ? view : null;
|
|
7873
|
+
} catch {
|
|
7874
|
+
return null;
|
|
7875
|
+
}
|
|
7876
|
+
}
|
|
7427
7877
|
|
|
7428
7878
|
// src/landing/land-pr-completion-post.ts
|
|
7879
|
+
init_config();
|
|
7429
7880
|
async function postLandPrHarnessCompletion(input) {
|
|
7430
7881
|
const secret = await resolveCallbackSecretWithMint(input.secret, input.agentOsId, {
|
|
7431
7882
|
baseUrl: input.baseUrl
|
|
@@ -7710,6 +8161,15 @@ async function dispatchRun(args) {
|
|
|
7710
8161
|
async function runLandPrClaimed(decision) {
|
|
7711
8162
|
const task = decision.task;
|
|
7712
8163
|
const taskId = String(task.id);
|
|
8164
|
+
if (exactTargetMode && !exactTargetIds.has(taskId)) {
|
|
8165
|
+
return abortClaimedSpawn(
|
|
8166
|
+
task,
|
|
8167
|
+
"exact_target_mismatch: dispatch-next returned a different task than requested",
|
|
8168
|
+
{
|
|
8169
|
+
requestedTargetTaskIds: [...exactTargetIds]
|
|
8170
|
+
}
|
|
8171
|
+
);
|
|
8172
|
+
}
|
|
7713
8173
|
const prUrl = task.prUrl ? String(task.prUrl) : "";
|
|
7714
8174
|
if (!prUrl) {
|
|
7715
8175
|
return abortClaimedSpawn(task, "land_pr task missing prUrl");
|
|
@@ -7971,8 +8431,15 @@ async function dispatchRun(args) {
|
|
|
7971
8431
|
}
|
|
7972
8432
|
}
|
|
7973
8433
|
|
|
8434
|
+
// src/cli.ts
|
|
8435
|
+
init_run_store();
|
|
8436
|
+
|
|
7974
8437
|
// src/sweep.ts
|
|
8438
|
+
init_config();
|
|
7975
8439
|
import path26 from "node:path";
|
|
8440
|
+
init_run_store();
|
|
8441
|
+
init_status();
|
|
8442
|
+
init_util();
|
|
7976
8443
|
async function sweepRun(args) {
|
|
7977
8444
|
const pipeline = args.pipeline === true || args.pipeline === "true";
|
|
7978
8445
|
try {
|
|
@@ -8033,10 +8500,14 @@ async function sweepRun(args) {
|
|
|
8033
8500
|
}
|
|
8034
8501
|
|
|
8035
8502
|
// src/worktree.ts
|
|
8503
|
+
init_git();
|
|
8504
|
+
init_run_store();
|
|
8036
8505
|
import { existsSync as existsSync25, mkdirSync as mkdirSync6 } from "node:fs";
|
|
8037
8506
|
import path35 from "node:path";
|
|
8038
8507
|
|
|
8039
8508
|
// src/run-list.ts
|
|
8509
|
+
init_run_store();
|
|
8510
|
+
init_run_worker_index();
|
|
8040
8511
|
import { existsSync as existsSync24, readFileSync as readFileSync11 } from "node:fs";
|
|
8041
8512
|
import path34 from "node:path";
|
|
8042
8513
|
|
|
@@ -8044,6 +8515,10 @@ import path34 from "node:path";
|
|
|
8044
8515
|
import path33 from "node:path";
|
|
8045
8516
|
|
|
8046
8517
|
// src/finalize.ts
|
|
8518
|
+
init_run_store();
|
|
8519
|
+
init_run_worker_index();
|
|
8520
|
+
init_status();
|
|
8521
|
+
init_util();
|
|
8047
8522
|
import path27 from "node:path";
|
|
8048
8523
|
var ACTIVE_RUN_STATUSES = /* @__PURE__ */ new Set([
|
|
8049
8524
|
"running",
|
|
@@ -8101,11 +8576,21 @@ function finalizeStaleRuns() {
|
|
|
8101
8576
|
return finalized;
|
|
8102
8577
|
}
|
|
8103
8578
|
|
|
8579
|
+
// src/stale-reconcile.ts
|
|
8580
|
+
init_run_store();
|
|
8581
|
+
init_run_worker_index();
|
|
8582
|
+
init_status();
|
|
8583
|
+
init_util();
|
|
8584
|
+
|
|
8104
8585
|
// src/worker-metadata-reconcile.ts
|
|
8586
|
+
init_heartbeat();
|
|
8587
|
+
init_stream();
|
|
8105
8588
|
import { existsSync as existsSync23, lstatSync, readdirSync as readdirSync7, readlinkSync, renameSync as renameSync2, rmSync } from "node:fs";
|
|
8106
8589
|
import path31 from "node:path";
|
|
8107
8590
|
|
|
8108
8591
|
// src/worker-metadata-paths.ts
|
|
8592
|
+
init_paths();
|
|
8593
|
+
init_util();
|
|
8109
8594
|
import path28 from "node:path";
|
|
8110
8595
|
var NESTED_RUNS = `${path28.sep}runs${path28.sep}runs${path28.sep}`;
|
|
8111
8596
|
function hasNestedRunsSegment(filePath) {
|
|
@@ -8153,6 +8638,9 @@ import { existsSync as existsSync22, readdirSync as readdirSync6, statSync as st
|
|
|
8153
8638
|
import path30 from "node:path";
|
|
8154
8639
|
|
|
8155
8640
|
// src/default-repo.ts
|
|
8641
|
+
init_config();
|
|
8642
|
+
init_default_repo_discovery();
|
|
8643
|
+
init_path_values();
|
|
8156
8644
|
import path29 from "node:path";
|
|
8157
8645
|
function expandConfiguredRepo(value) {
|
|
8158
8646
|
return path29.resolve(resolveUserPath(value.trim()));
|
|
@@ -8203,6 +8691,10 @@ function formatResolvedDefaultRepo(resolved) {
|
|
|
8203
8691
|
}
|
|
8204
8692
|
|
|
8205
8693
|
// src/run-metadata-retention.ts
|
|
8694
|
+
init_heartbeat();
|
|
8695
|
+
init_paths();
|
|
8696
|
+
init_run_store();
|
|
8697
|
+
init_util();
|
|
8206
8698
|
var RUN_METADATA_ACTIVE_SIGNAL_MS = 15 * 60 * 1e3;
|
|
8207
8699
|
function isHarnessRunMetadataPath(targetPath, harnessRoot) {
|
|
8208
8700
|
const resolved = path30.resolve(targetPath);
|
|
@@ -8343,6 +8835,8 @@ function collectFilesystemLiveRunKeys(harnessRoot, now = Date.now()) {
|
|
|
8343
8835
|
}
|
|
8344
8836
|
|
|
8345
8837
|
// src/worker-metadata-reconcile.ts
|
|
8838
|
+
init_run_store();
|
|
8839
|
+
init_util();
|
|
8346
8840
|
function materializeSymlinkedRunDir(harnessRoot, runId) {
|
|
8347
8841
|
const canonical = canonicalRunDir(harnessRoot, runId);
|
|
8348
8842
|
let stat;
|
|
@@ -8625,6 +9119,12 @@ function reconcileWorkerMetadata() {
|
|
|
8625
9119
|
}
|
|
8626
9120
|
|
|
8627
9121
|
// src/local-pr-attention-reconcile.ts
|
|
9122
|
+
init_heartbeat();
|
|
9123
|
+
init_worker_final_result_embed();
|
|
9124
|
+
init_status();
|
|
9125
|
+
init_run_store();
|
|
9126
|
+
init_run_worker_index();
|
|
9127
|
+
init_util();
|
|
8628
9128
|
import { execFileSync } from "node:child_process";
|
|
8629
9129
|
import path32 from "node:path";
|
|
8630
9130
|
function normalizePrUrl3(url) {
|
|
@@ -8951,6 +9451,8 @@ function reconcileRunsCli() {
|
|
|
8951
9451
|
}
|
|
8952
9452
|
|
|
8953
9453
|
// src/run-list.ts
|
|
9454
|
+
init_status();
|
|
9455
|
+
init_util();
|
|
8954
9456
|
function heartbeatByteLength(heartbeatPath) {
|
|
8955
9457
|
if (!heartbeatPath || !existsSync24(heartbeatPath)) return 0;
|
|
8956
9458
|
try {
|
|
@@ -9066,6 +9568,7 @@ function listRunsCli() {
|
|
|
9066
9568
|
}
|
|
9067
9569
|
|
|
9068
9570
|
// src/worktree.ts
|
|
9571
|
+
init_util();
|
|
9069
9572
|
function resolveCreateRunRepo(args) {
|
|
9070
9573
|
const explicit = typeof args.repo === "string" ? args.repo.trim() : "";
|
|
9071
9574
|
if (explicit) return explicit;
|
|
@@ -9105,6 +9608,8 @@ function failExists(message) {
|
|
|
9105
9608
|
}
|
|
9106
9609
|
|
|
9107
9610
|
// src/discard-disposable.ts
|
|
9611
|
+
init_run_store();
|
|
9612
|
+
init_status();
|
|
9108
9613
|
import { existsSync as existsSync26, rmSync as rmSync2 } from "node:fs";
|
|
9109
9614
|
import path36 from "node:path";
|
|
9110
9615
|
function normalizeRelativePath2(value) {
|
|
@@ -9158,8 +9663,14 @@ function discardDisposableCli(args) {
|
|
|
9158
9663
|
if (!result.ok) process.exit(1);
|
|
9159
9664
|
}
|
|
9160
9665
|
|
|
9666
|
+
// src/daemon.ts
|
|
9667
|
+
init_config();
|
|
9668
|
+
|
|
9161
9669
|
// src/daemon-box-identity.ts
|
|
9162
|
-
|
|
9670
|
+
init_config();
|
|
9671
|
+
init_box_identity();
|
|
9672
|
+
init_worker_cap_source();
|
|
9673
|
+
import os9 from "node:os";
|
|
9163
9674
|
function emitDaemonIdentityMessage(level, message) {
|
|
9164
9675
|
console.error(JSON.stringify({ event: "daemon_identity", level, message }));
|
|
9165
9676
|
}
|
|
@@ -9167,7 +9678,7 @@ function validateDaemonInstallIdentity(config = loadUserConfig(), env = process.
|
|
|
9167
9678
|
const box = resolveBoxIdentity(env, config);
|
|
9168
9679
|
const cap = resolveWorkerCap({
|
|
9169
9680
|
config,
|
|
9170
|
-
totalMemBytes:
|
|
9681
|
+
totalMemBytes: os9.totalmem(),
|
|
9171
9682
|
env
|
|
9172
9683
|
});
|
|
9173
9684
|
const warnings = [...box.warnings];
|
|
@@ -9197,6 +9708,47 @@ function validateDaemonInstallIdentity(config = loadUserConfig(), env = process.
|
|
|
9197
9708
|
};
|
|
9198
9709
|
}
|
|
9199
9710
|
|
|
9711
|
+
// src/daemon-heartbeat.ts
|
|
9712
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync12, renameSync as renameSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
9713
|
+
import { homedir as homedir11 } from "node:os";
|
|
9714
|
+
import path37 from "node:path";
|
|
9715
|
+
function daemonHeartbeatPath(agentOsId) {
|
|
9716
|
+
const safe = agentOsId.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
9717
|
+
return path37.join(homedir11(), ".kynver", `daemon-heartbeat-${safe}.json`);
|
|
9718
|
+
}
|
|
9719
|
+
function writeDaemonHeartbeat(input) {
|
|
9720
|
+
try {
|
|
9721
|
+
const file = daemonHeartbeatPath(input.agentOsId);
|
|
9722
|
+
mkdirSync7(path37.dirname(file), { recursive: true });
|
|
9723
|
+
const beat = {
|
|
9724
|
+
observedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
9725
|
+
pid: process.pid,
|
|
9726
|
+
runId: input.runId,
|
|
9727
|
+
agentOsId: input.agentOsId
|
|
9728
|
+
};
|
|
9729
|
+
const tmp = `${file}.tmp-${process.pid}`;
|
|
9730
|
+
writeFileSync4(tmp, JSON.stringify(beat), "utf8");
|
|
9731
|
+
renameSync3(tmp, file);
|
|
9732
|
+
} catch {
|
|
9733
|
+
}
|
|
9734
|
+
}
|
|
9735
|
+
function readDaemonHeartbeat(agentOsId) {
|
|
9736
|
+
try {
|
|
9737
|
+
const raw = readFileSync12(daemonHeartbeatPath(agentOsId), "utf8");
|
|
9738
|
+
const parsed = JSON.parse(raw);
|
|
9739
|
+
if (typeof parsed?.observedAt !== "string") return null;
|
|
9740
|
+
return parsed;
|
|
9741
|
+
} catch {
|
|
9742
|
+
return null;
|
|
9743
|
+
}
|
|
9744
|
+
}
|
|
9745
|
+
function isDaemonHeartbeatStale(beat, stallMs, nowMs = Date.now()) {
|
|
9746
|
+
if (!beat) return false;
|
|
9747
|
+
const observed = Date.parse(beat.observedAt);
|
|
9748
|
+
if (Number.isNaN(observed)) return true;
|
|
9749
|
+
return nowMs - observed > stallMs;
|
|
9750
|
+
}
|
|
9751
|
+
|
|
9200
9752
|
// src/daemon-platform-guard.ts
|
|
9201
9753
|
function envFlag(name) {
|
|
9202
9754
|
const raw = process.env[name]?.trim().toLowerCase();
|
|
@@ -9216,9 +9768,10 @@ function assertNativeDaemonAllowed() {
|
|
|
9216
9768
|
}
|
|
9217
9769
|
|
|
9218
9770
|
// src/cron/cron-env.ts
|
|
9771
|
+
init_config();
|
|
9219
9772
|
import { existsSync as existsSync27 } from "node:fs";
|
|
9220
|
-
import { homedir as
|
|
9221
|
-
import
|
|
9773
|
+
import { homedir as homedir12 } from "node:os";
|
|
9774
|
+
import path38 from "node:path";
|
|
9222
9775
|
function envFlag2(name, defaultValue) {
|
|
9223
9776
|
const raw = process.env[name]?.trim().toLowerCase();
|
|
9224
9777
|
if (!raw) return defaultValue;
|
|
@@ -9234,7 +9787,7 @@ function envInt(name, fallback, min = 1) {
|
|
|
9234
9787
|
function defaultKynverCronStorePath() {
|
|
9235
9788
|
const explicit = process.env.KYNVER_CRON_STORE_PATH?.trim() || process.env.OPENCLAW_CRON_STORE_PATH?.trim();
|
|
9236
9789
|
if (explicit) return explicit;
|
|
9237
|
-
return
|
|
9790
|
+
return path38.join(homedir12(), ".kynver", "agent-os-cron.json");
|
|
9238
9791
|
}
|
|
9239
9792
|
function defaultKynverCronStatePath(storePath = defaultKynverCronStorePath()) {
|
|
9240
9793
|
const explicit = process.env.KYNVER_CRON_TICK_STATE_PATH?.trim();
|
|
@@ -9307,12 +9860,13 @@ async function fireKynverCronJob(input) {
|
|
|
9307
9860
|
}
|
|
9308
9861
|
|
|
9309
9862
|
// src/cron/cron-lock.ts
|
|
9310
|
-
|
|
9863
|
+
init_util();
|
|
9864
|
+
import { closeSync as closeSync6, existsSync as existsSync28, openSync as openSync6, readFileSync as readFileSync13, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
9311
9865
|
var STALE_LOCK_MS = 10 * 6e4;
|
|
9312
9866
|
function readLockInfo(lockPath) {
|
|
9313
9867
|
if (!existsSync28(lockPath)) return null;
|
|
9314
9868
|
try {
|
|
9315
|
-
const parsed = JSON.parse(
|
|
9869
|
+
const parsed = JSON.parse(readFileSync13(lockPath, "utf8"));
|
|
9316
9870
|
if (typeof parsed.pid === "number" && typeof parsed.at === "string") return parsed;
|
|
9317
9871
|
} catch {
|
|
9318
9872
|
return null;
|
|
@@ -9343,7 +9897,7 @@ function tryAcquireCronTickLock(lockPath) {
|
|
|
9343
9897
|
}
|
|
9344
9898
|
try {
|
|
9345
9899
|
const fd = openSync6(lockPath, "wx");
|
|
9346
|
-
|
|
9900
|
+
writeFileSync5(
|
|
9347
9901
|
fd,
|
|
9348
9902
|
JSON.stringify({ pid: process.pid, at: (/* @__PURE__ */ new Date()).toISOString() }),
|
|
9349
9903
|
"utf8"
|
|
@@ -9476,7 +10030,7 @@ async function loadCronJobs(storePath = defaultKynverCronStorePath()) {
|
|
|
9476
10030
|
// src/cron/cron-tick-state.ts
|
|
9477
10031
|
import { randomBytes } from "node:crypto";
|
|
9478
10032
|
import { promises as fs2 } from "node:fs";
|
|
9479
|
-
import
|
|
10033
|
+
import path39 from "node:path";
|
|
9480
10034
|
var EMPTY = { version: 1, jobs: {} };
|
|
9481
10035
|
async function readFileIfExists2(filePath) {
|
|
9482
10036
|
try {
|
|
@@ -9503,7 +10057,7 @@ async function loadCronTickState(statePath) {
|
|
|
9503
10057
|
return parseCronTickState(raw);
|
|
9504
10058
|
}
|
|
9505
10059
|
async function writeStateAtomic(statePath, state) {
|
|
9506
|
-
await fs2.mkdir(
|
|
10060
|
+
await fs2.mkdir(path39.dirname(statePath), { recursive: true });
|
|
9507
10061
|
const suffix = randomBytes(6).toString("hex");
|
|
9508
10062
|
const tmp = `${statePath}.tmp-${process.pid}-${Date.now()}-${suffix}`;
|
|
9509
10063
|
await fs2.writeFile(tmp, `${JSON.stringify(state, null, 2)}
|
|
@@ -9679,8 +10233,12 @@ async function runKynverCronTick(opts = {}) {
|
|
|
9679
10233
|
}
|
|
9680
10234
|
}
|
|
9681
10235
|
|
|
10236
|
+
// src/daemon.ts
|
|
10237
|
+
init_util();
|
|
10238
|
+
|
|
9682
10239
|
// src/pipeline-tick.ts
|
|
9683
|
-
import
|
|
10240
|
+
import path58 from "node:path";
|
|
10241
|
+
init_config();
|
|
9684
10242
|
|
|
9685
10243
|
// src/pipeline-dispatch.ts
|
|
9686
10244
|
var RESERVED_REVIEW_STARTS = 1;
|
|
@@ -9810,11 +10368,16 @@ function resolvePipelineMaxStarts(resourceGate, operatorTick) {
|
|
|
9810
10368
|
};
|
|
9811
10369
|
}
|
|
9812
10370
|
|
|
10371
|
+
// src/pipeline-tick.ts
|
|
10372
|
+
init_resource_gate();
|
|
10373
|
+
|
|
9813
10374
|
// src/box-resource-snapshot.ts
|
|
9814
|
-
|
|
10375
|
+
init_config();
|
|
10376
|
+
init_box_identity();
|
|
10377
|
+
import os10 from "node:os";
|
|
9815
10378
|
function buildBoxResourceSnapshotFromGate(gate, input = {}) {
|
|
9816
10379
|
const boxKind = (input.boxKind ?? resolveBoxKindFromConfig(loadUserConfig())).trim().toLowerCase() || "forge";
|
|
9817
|
-
const hostLabel = input.hostLabel ??
|
|
10380
|
+
const hostLabel = input.hostLabel ?? os10.hostname();
|
|
9818
10381
|
const boxId = input.boxId ?? defaultBoxId(boxKind, hostLabel);
|
|
9819
10382
|
return {
|
|
9820
10383
|
boxId,
|
|
@@ -9835,10 +10398,20 @@ function buildBoxResourceSnapshotFromGate(gate, input = {}) {
|
|
|
9835
10398
|
};
|
|
9836
10399
|
}
|
|
9837
10400
|
|
|
10401
|
+
// src/pipeline-tick.ts
|
|
10402
|
+
init_run_store();
|
|
10403
|
+
init_exited_salvage();
|
|
10404
|
+
init_status();
|
|
10405
|
+
init_util();
|
|
10406
|
+
|
|
9838
10407
|
// src/plan-progress-daemon-sync.ts
|
|
9839
|
-
|
|
10408
|
+
init_status();
|
|
10409
|
+
init_run_store();
|
|
10410
|
+
init_util();
|
|
10411
|
+
import path40 from "node:path";
|
|
9840
10412
|
|
|
9841
10413
|
// src/plan-progress-sync.ts
|
|
10414
|
+
init_config();
|
|
9842
10415
|
async function syncPlanProgress(args) {
|
|
9843
10416
|
const base = resolveBaseUrl(args.baseUrl);
|
|
9844
10417
|
const secret = await resolveCallbackSecretWithMint(args.secret, args.agentOsId, { baseUrl: base });
|
|
@@ -9860,7 +10433,7 @@ async function syncActiveWorkerPlanProgress(runId, args) {
|
|
|
9860
10433
|
const outcomes = [];
|
|
9861
10434
|
for (const name of Object.keys(run.workers || {})) {
|
|
9862
10435
|
const worker = readJson(
|
|
9863
|
-
|
|
10436
|
+
path40.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
9864
10437
|
void 0
|
|
9865
10438
|
);
|
|
9866
10439
|
if (!worker?.dispatched || !worker.taskId) continue;
|
|
@@ -9888,6 +10461,8 @@ async function syncActiveWorkerPlanProgress(runId, args) {
|
|
|
9888
10461
|
}
|
|
9889
10462
|
|
|
9890
10463
|
// src/workspace-runtime-config.ts
|
|
10464
|
+
init_config();
|
|
10465
|
+
init_box_identity();
|
|
9891
10466
|
function shouldApplyWorkspaceRuntimePreferences(env = process.env) {
|
|
9892
10467
|
const config = loadUserConfig();
|
|
9893
10468
|
return resolveBoxKindFromConfig(config, env) !== "forge";
|
|
@@ -9916,11 +10491,21 @@ async function fetchWorkspaceRuntimePreferences(agentOsId, args) {
|
|
|
9916
10491
|
}
|
|
9917
10492
|
}
|
|
9918
10493
|
|
|
10494
|
+
// src/pipeline-tick.ts
|
|
10495
|
+
init_config();
|
|
10496
|
+
init_box_identity();
|
|
10497
|
+
|
|
9919
10498
|
// src/cleanup.ts
|
|
9920
|
-
|
|
10499
|
+
init_paths();
|
|
10500
|
+
import path54 from "node:path";
|
|
9921
10501
|
|
|
9922
10502
|
// src/cleanup-guards.ts
|
|
9923
|
-
|
|
10503
|
+
init_landing_gate();
|
|
10504
|
+
import path41 from "node:path";
|
|
10505
|
+
|
|
10506
|
+
// src/cleanup-index-status.ts
|
|
10507
|
+
init_git();
|
|
10508
|
+
init_status();
|
|
9924
10509
|
|
|
9925
10510
|
// src/cleanup-build-cache-paths.ts
|
|
9926
10511
|
var HARNESS_BUILD_CACHE_RELATIVE_PATHS = [
|
|
@@ -9976,6 +10561,7 @@ function isPrOrUnmergedWork(status) {
|
|
|
9976
10561
|
}
|
|
9977
10562
|
|
|
9978
10563
|
// src/cleanup-index-status.ts
|
|
10564
|
+
init_util();
|
|
9979
10565
|
function indexedWorktreeStatus(entry) {
|
|
9980
10566
|
if (!entry.status) {
|
|
9981
10567
|
entry.status = computeWorkerStatus(entry.worker, {
|
|
@@ -10052,7 +10638,15 @@ function resolveWorktreeGuardStatus(entry, ctx) {
|
|
|
10052
10638
|
return indexedWorktreeStatus(entry);
|
|
10053
10639
|
}
|
|
10054
10640
|
|
|
10641
|
+
// src/cleanup-guards.ts
|
|
10642
|
+
init_status();
|
|
10643
|
+
|
|
10644
|
+
// src/cleanup-run-liveness.ts
|
|
10645
|
+
init_status();
|
|
10646
|
+
|
|
10055
10647
|
// src/cleanup-completion-blocker.ts
|
|
10648
|
+
init_landing_gate();
|
|
10649
|
+
init_status();
|
|
10056
10650
|
function completionBlockerBlocksWorktreeRemoval(indexed, status) {
|
|
10057
10651
|
const blocker = typeof indexed.worker.completionBlocker === "string" ? indexed.worker.completionBlocker.trim() : "";
|
|
10058
10652
|
if (!blocker) return false;
|
|
@@ -10072,6 +10666,7 @@ function completionBlockerBlocksWorktreeRemoval(indexed, status) {
|
|
|
10072
10666
|
}
|
|
10073
10667
|
|
|
10074
10668
|
// src/cleanup-run-liveness.ts
|
|
10669
|
+
init_util();
|
|
10075
10670
|
var TERMINAL_WORKER_JSON_STATUSES = /* @__PURE__ */ new Set([
|
|
10076
10671
|
"done",
|
|
10077
10672
|
"exited",
|
|
@@ -10173,7 +10768,7 @@ function skipWorktreeRemoval(input) {
|
|
|
10173
10768
|
function skipDependencyCacheRemoval(input) {
|
|
10174
10769
|
const { indexed, nodeModulesAgeMs, ageMs, worktreePath, activeWorktreePaths, diskPressure } = input;
|
|
10175
10770
|
if (!diskPressure && ageMs < nodeModulesAgeMs) return "below_age_threshold";
|
|
10176
|
-
if (activeWorktreePaths.has(
|
|
10771
|
+
if (activeWorktreePaths.has(path41.resolve(worktreePath))) return "active_worker";
|
|
10177
10772
|
if (indexed && isWorkerProcessLive(indexed)) return "active_worker";
|
|
10178
10773
|
if (indexed && indexedWorktreeHasMaterialChanges(indexed, input.gitStatusCache)) {
|
|
10179
10774
|
return "dirty_worktree";
|
|
@@ -10202,11 +10797,11 @@ var LIVE_SKIP_REASONS = /* @__PURE__ */ new Set([
|
|
|
10202
10797
|
function collectPreservedLivePaths(actions, skips) {
|
|
10203
10798
|
const out = [];
|
|
10204
10799
|
const seen = /* @__PURE__ */ new Set();
|
|
10205
|
-
const push = (
|
|
10206
|
-
const key = `${
|
|
10800
|
+
const push = (path73, reason, detail) => {
|
|
10801
|
+
const key = `${path73}\0${reason}`;
|
|
10207
10802
|
if (seen.has(key) || out.length >= MAX_PRESERVED_LIVE_PATH_SAMPLES) return;
|
|
10208
10803
|
seen.add(key);
|
|
10209
|
-
out.push({ path:
|
|
10804
|
+
out.push({ path: path73, reason, ...detail ? { detail } : {} });
|
|
10210
10805
|
};
|
|
10211
10806
|
for (const skip2 of skips) {
|
|
10212
10807
|
if (!LIVE_SKIP_REASONS.has(skip2.reason)) continue;
|
|
@@ -10222,11 +10817,14 @@ function collectPreservedLivePaths(actions, skips) {
|
|
|
10222
10817
|
|
|
10223
10818
|
// src/cleanup-run-directory.ts
|
|
10224
10819
|
import { existsSync as existsSync30, readdirSync as readdirSync9, statSync as statSync7 } from "node:fs";
|
|
10225
|
-
import
|
|
10820
|
+
import path43 from "node:path";
|
|
10226
10821
|
|
|
10227
10822
|
// src/cleanup-active-worktrees.ts
|
|
10823
|
+
init_run_store();
|
|
10824
|
+
init_paths();
|
|
10228
10825
|
import { existsSync as existsSync29, readdirSync as readdirSync8, statSync as statSync6 } from "node:fs";
|
|
10229
|
-
import
|
|
10826
|
+
import path42 from "node:path";
|
|
10827
|
+
init_util();
|
|
10230
10828
|
function workerHasRecentHarnessActivity(worker, now) {
|
|
10231
10829
|
const paths = [worker.heartbeatPath, worker.stdoutPath, worker.stderrPath];
|
|
10232
10830
|
for (const target of paths) {
|
|
@@ -10252,11 +10850,11 @@ function collectActiveWorktreeGuards(harnessRoots, now = Date.now()) {
|
|
|
10252
10850
|
let runHasLive = false;
|
|
10253
10851
|
for (const name of Object.keys(run.workers || {})) {
|
|
10254
10852
|
const worker = readJson(
|
|
10255
|
-
|
|
10853
|
+
path42.join(runDirectoryAt(harnessRoot, run.id), "workers", safeSlug(name), "worker.json"),
|
|
10256
10854
|
void 0
|
|
10257
10855
|
);
|
|
10258
10856
|
if (!worker?.worktreePath) continue;
|
|
10259
|
-
const worktreePath =
|
|
10857
|
+
const worktreePath = path42.resolve(worker.worktreePath);
|
|
10260
10858
|
if (!isActiveHarnessWorker2(worker, now)) continue;
|
|
10261
10859
|
runHasLive = true;
|
|
10262
10860
|
activeWorktreePaths.add(worktreePath);
|
|
@@ -10275,6 +10873,7 @@ function isWorktreeOnLiveRun(worktreePath, harnessRoot, runId, liveRunKeys) {
|
|
|
10275
10873
|
}
|
|
10276
10874
|
|
|
10277
10875
|
// src/cleanup-run-directory.ts
|
|
10876
|
+
init_util();
|
|
10278
10877
|
function pathAgeMs(target, now) {
|
|
10279
10878
|
try {
|
|
10280
10879
|
const mtime = statSync7(target).mtimeMs;
|
|
@@ -10284,7 +10883,7 @@ function pathAgeMs(target, now) {
|
|
|
10284
10883
|
}
|
|
10285
10884
|
}
|
|
10286
10885
|
function loadRunStatus(harnessRoot, runId) {
|
|
10287
|
-
const runPath =
|
|
10886
|
+
const runPath = path43.join(harnessRoot, "runs", runId, "run.json");
|
|
10288
10887
|
if (!existsSync30(runPath)) return null;
|
|
10289
10888
|
return readJson(runPath, null);
|
|
10290
10889
|
}
|
|
@@ -10322,7 +10921,7 @@ function scanStaleRunDirectoryCandidates(opts) {
|
|
|
10322
10921
|
if (!runEntry.isDirectory()) continue;
|
|
10323
10922
|
const runId = runEntry.name;
|
|
10324
10923
|
if (opts.runIdFilter && runId !== opts.runIdFilter) continue;
|
|
10325
|
-
const runPath =
|
|
10924
|
+
const runPath = path43.join(opts.worktreesDir, runId);
|
|
10326
10925
|
if (!runDirectoryIsEmpty(runPath)) continue;
|
|
10327
10926
|
candidates.push({
|
|
10328
10927
|
kind: "remove_run_directory",
|
|
@@ -10337,12 +10936,13 @@ function scanStaleRunDirectoryCandidates(opts) {
|
|
|
10337
10936
|
}
|
|
10338
10937
|
|
|
10339
10938
|
// src/cleanup-execute.ts
|
|
10939
|
+
init_git();
|
|
10340
10940
|
import { existsSync as existsSync33, rmSync as rmSync4 } from "node:fs";
|
|
10341
10941
|
|
|
10342
10942
|
// src/cleanup-dir-size.ts
|
|
10343
10943
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
10344
10944
|
import { existsSync as existsSync31, readdirSync as readdirSync10, statSync as statSync8 } from "node:fs";
|
|
10345
|
-
import
|
|
10945
|
+
import path44 from "node:path";
|
|
10346
10946
|
var DEFAULT_DU_TIMEOUT_MS = 2500;
|
|
10347
10947
|
function directorySizeBytesDu(root, timeoutMs = DEFAULT_DU_TIMEOUT_MS) {
|
|
10348
10948
|
if (!existsSync31(root)) return 0;
|
|
@@ -10376,7 +10976,7 @@ function directorySizeBytes(root, maxEntries = 5e4) {
|
|
|
10376
10976
|
}
|
|
10377
10977
|
for (const name of entries) {
|
|
10378
10978
|
if (seen++ > maxEntries) return null;
|
|
10379
|
-
const full =
|
|
10979
|
+
const full = path44.join(current, name);
|
|
10380
10980
|
let st;
|
|
10381
10981
|
try {
|
|
10382
10982
|
st = statSync8(full);
|
|
@@ -10392,6 +10992,7 @@ function directorySizeBytes(root, maxEntries = 5e4) {
|
|
|
10392
10992
|
|
|
10393
10993
|
// src/cleanup-remove-path.ts
|
|
10394
10994
|
import { existsSync as existsSync32, rmSync as rmSync3 } from "node:fs";
|
|
10995
|
+
init_paths();
|
|
10395
10996
|
|
|
10396
10997
|
// src/cleanup-path-ownership.ts
|
|
10397
10998
|
import { lstatSync as lstatSync2, readdirSync as readdirSync11 } from "node:fs";
|
|
@@ -10427,20 +11028,20 @@ function pathHasForeignOwnedEntry(targetPath, maxEntries = 32) {
|
|
|
10427
11028
|
|
|
10428
11029
|
// src/cleanup-privileged-remove.ts
|
|
10429
11030
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
10430
|
-
import
|
|
11031
|
+
import path46 from "node:path";
|
|
10431
11032
|
|
|
10432
11033
|
// src/cleanup-harness-path-validate.ts
|
|
10433
|
-
import
|
|
11034
|
+
import path45 from "node:path";
|
|
10434
11035
|
function isHarnessDependencyCachePath(targetPath, harnessRoot, worktreesDir, cacheDirName) {
|
|
10435
|
-
const resolved =
|
|
10436
|
-
const suffix = `${
|
|
11036
|
+
const resolved = path45.resolve(targetPath);
|
|
11037
|
+
const suffix = `${path45.sep}${cacheDirName}`;
|
|
10437
11038
|
const cachePath = resolved.endsWith(suffix) ? resolved : null;
|
|
10438
11039
|
if (!cachePath) return "path_outside_harness";
|
|
10439
|
-
const rel =
|
|
10440
|
-
if (rel.startsWith("..") ||
|
|
10441
|
-
const parts = rel.split(
|
|
11040
|
+
const rel = path45.relative(worktreesDir, cachePath);
|
|
11041
|
+
if (rel.startsWith("..") || path45.isAbsolute(rel)) return "path_outside_harness";
|
|
11042
|
+
const parts = rel.split(path45.sep);
|
|
10442
11043
|
if (parts.length < 3 || parts[parts.length - 1] !== cacheDirName) return "path_outside_harness";
|
|
10443
|
-
if (!resolved.startsWith(
|
|
11044
|
+
if (!resolved.startsWith(path45.resolve(harnessRoot))) return "path_outside_harness";
|
|
10444
11045
|
return null;
|
|
10445
11046
|
}
|
|
10446
11047
|
function isHarnessNodeModulesPath(targetPath, harnessRoot, worktreesDir) {
|
|
@@ -10450,16 +11051,16 @@ function isHarnessNextCachePath(targetPath, harnessRoot, worktreesDir) {
|
|
|
10450
11051
|
return isHarnessDependencyCachePath(targetPath, harnessRoot, worktreesDir, ".next");
|
|
10451
11052
|
}
|
|
10452
11053
|
function isHarnessBuildCachePath(targetPath, harnessRoot, worktreesDir) {
|
|
10453
|
-
const resolved =
|
|
10454
|
-
const relToWt =
|
|
10455
|
-
if (relToWt.startsWith("..") ||
|
|
10456
|
-
const parts = relToWt.split(
|
|
11054
|
+
const resolved = path45.resolve(targetPath);
|
|
11055
|
+
const relToWt = path45.relative(worktreesDir, resolved);
|
|
11056
|
+
if (relToWt.startsWith("..") || path45.isAbsolute(relToWt)) return "path_outside_harness";
|
|
11057
|
+
const parts = relToWt.split(path45.sep);
|
|
10457
11058
|
if (parts.length < 3) return "path_outside_harness";
|
|
10458
|
-
if (!resolved.startsWith(
|
|
11059
|
+
if (!resolved.startsWith(path45.resolve(harnessRoot))) return "path_outside_harness";
|
|
10459
11060
|
return null;
|
|
10460
11061
|
}
|
|
10461
11062
|
function isHarnessGeneratedCachePath(targetPath, harnessRoot, worktreesDir) {
|
|
10462
|
-
const resolved =
|
|
11063
|
+
const resolved = path45.resolve(targetPath);
|
|
10463
11064
|
return isHarnessNodeModulesPath(resolved, harnessRoot, worktreesDir) === null || isHarnessNextCachePath(resolved, harnessRoot, worktreesDir) === null || isHarnessBuildCachePath(resolved, harnessRoot, worktreesDir) === null;
|
|
10464
11065
|
}
|
|
10465
11066
|
|
|
@@ -10493,12 +11094,12 @@ function tryPrivilegedReclaimHarnessCache(targetPath, harnessRoot, worktreesDir)
|
|
|
10493
11094
|
"chown",
|
|
10494
11095
|
"-R",
|
|
10495
11096
|
`${effectiveUid}:${effectiveGid}`,
|
|
10496
|
-
|
|
11097
|
+
path46.resolve(targetPath)
|
|
10497
11098
|
]);
|
|
10498
11099
|
if (chown.ok) {
|
|
10499
11100
|
return { ok: true, method: "chown_then_rm" };
|
|
10500
11101
|
}
|
|
10501
|
-
const rm = runSudoNonInteractive(["rm", "-rf",
|
|
11102
|
+
const rm = runSudoNonInteractive(["rm", "-rf", path46.resolve(targetPath)]);
|
|
10502
11103
|
if (rm.ok) {
|
|
10503
11104
|
return { ok: true, method: "sudo_rm" };
|
|
10504
11105
|
}
|
|
@@ -10700,7 +11301,7 @@ function removeWorktree(candidate, execute) {
|
|
|
10700
11301
|
|
|
10701
11302
|
// src/cleanup-scan.ts
|
|
10702
11303
|
import { existsSync as existsSync34, readdirSync as readdirSync12, statSync as statSync9 } from "node:fs";
|
|
10703
|
-
import
|
|
11304
|
+
import path47 from "node:path";
|
|
10704
11305
|
function pathAgeMs2(target, now) {
|
|
10705
11306
|
try {
|
|
10706
11307
|
const mtime = statSync9(target).mtimeMs;
|
|
@@ -10710,16 +11311,16 @@ function pathAgeMs2(target, now) {
|
|
|
10710
11311
|
}
|
|
10711
11312
|
}
|
|
10712
11313
|
function isPathInside(child, parent) {
|
|
10713
|
-
const rel =
|
|
10714
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
11314
|
+
const rel = path47.relative(parent, child);
|
|
11315
|
+
return rel === "" || !rel.startsWith("..") && !path47.isAbsolute(rel);
|
|
10715
11316
|
}
|
|
10716
11317
|
function collectBuildCacheForWorktree(worktreePath, opts, seen, meta) {
|
|
10717
11318
|
const out = [];
|
|
10718
11319
|
for (const rel of HARNESS_BUILD_CACHE_RELATIVE_PATHS) {
|
|
10719
11320
|
if (rel === ".next") continue;
|
|
10720
|
-
const target =
|
|
11321
|
+
const target = path47.join(worktreePath, rel);
|
|
10721
11322
|
if (!existsSync34(target)) continue;
|
|
10722
|
-
const resolved =
|
|
11323
|
+
const resolved = path47.resolve(target);
|
|
10723
11324
|
if (seen.has(resolved)) continue;
|
|
10724
11325
|
if (!isPathInside(resolved, opts.harnessRoot)) continue;
|
|
10725
11326
|
seen.add(resolved);
|
|
@@ -10751,10 +11352,10 @@ function scanBuildCacheCandidates(opts) {
|
|
|
10751
11352
|
if (!opts.includeOrphans || !existsSync34(opts.worktreesDir)) return candidates;
|
|
10752
11353
|
for (const runEntry of readdirSync12(opts.worktreesDir, { withFileTypes: true })) {
|
|
10753
11354
|
if (!runEntry.isDirectory()) continue;
|
|
10754
|
-
const runPath =
|
|
11355
|
+
const runPath = path47.join(opts.worktreesDir, runEntry.name);
|
|
10755
11356
|
for (const workerEntry of readdirSync12(runPath, { withFileTypes: true })) {
|
|
10756
11357
|
if (!workerEntry.isDirectory()) continue;
|
|
10757
|
-
const worktreePath =
|
|
11358
|
+
const worktreePath = path47.join(runPath, workerEntry.name);
|
|
10758
11359
|
candidates.push(
|
|
10759
11360
|
...collectBuildCacheForWorktree(worktreePath, opts, seen, {
|
|
10760
11361
|
runId: runEntry.name,
|
|
@@ -10792,12 +11393,12 @@ function scanWorktreeCandidates(opts) {
|
|
|
10792
11393
|
if (!orphanEnabled || !existsSync34(opts.worktreesDir)) return candidates;
|
|
10793
11394
|
const indexedPaths = /* @__PURE__ */ new Set();
|
|
10794
11395
|
for (const entry of opts.index.values()) {
|
|
10795
|
-
indexedPaths.add(
|
|
11396
|
+
indexedPaths.add(path47.resolve(entry.worktreePath));
|
|
10796
11397
|
}
|
|
10797
11398
|
for (const runEntry of readdirSync12(opts.worktreesDir, { withFileTypes: true })) {
|
|
10798
11399
|
if (!runEntry.isDirectory()) continue;
|
|
10799
11400
|
if (opts.runIdFilter && runEntry.name !== opts.runIdFilter) continue;
|
|
10800
|
-
const runPath =
|
|
11401
|
+
const runPath = path47.join(opts.worktreesDir, runEntry.name);
|
|
10801
11402
|
let workerEntries;
|
|
10802
11403
|
try {
|
|
10803
11404
|
workerEntries = readdirSync12(runPath, { withFileTypes: true });
|
|
@@ -10806,7 +11407,7 @@ function scanWorktreeCandidates(opts) {
|
|
|
10806
11407
|
}
|
|
10807
11408
|
for (const workerEntry of workerEntries) {
|
|
10808
11409
|
if (!workerEntry.isDirectory()) continue;
|
|
10809
|
-
const worktreePath =
|
|
11410
|
+
const worktreePath = path47.resolve(path47.join(runPath, workerEntry.name));
|
|
10810
11411
|
if (seen.has(worktreePath)) continue;
|
|
10811
11412
|
if (indexedPaths.has(worktreePath)) continue;
|
|
10812
11413
|
if (!isPathInside(worktreePath, opts.harnessRoot)) continue;
|
|
@@ -10826,7 +11427,7 @@ function scanWorktreeCandidates(opts) {
|
|
|
10826
11427
|
|
|
10827
11428
|
// src/cleanup-dependency-scan.ts
|
|
10828
11429
|
import { existsSync as existsSync35, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
|
|
10829
|
-
import
|
|
11430
|
+
import path48 from "node:path";
|
|
10830
11431
|
var DEPENDENCY_CACHE_DIRS = [
|
|
10831
11432
|
{ dirName: "node_modules", kind: "remove_node_modules" },
|
|
10832
11433
|
{ dirName: ".next", kind: "remove_next_cache" }
|
|
@@ -10840,12 +11441,12 @@ function pathAgeMs3(target, now) {
|
|
|
10840
11441
|
}
|
|
10841
11442
|
}
|
|
10842
11443
|
function isPathInside2(child, parent) {
|
|
10843
|
-
const rel =
|
|
10844
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
11444
|
+
const rel = path48.relative(parent, child);
|
|
11445
|
+
return rel === "" || !rel.startsWith("..") && !path48.isAbsolute(rel);
|
|
10845
11446
|
}
|
|
10846
11447
|
function pushCandidate2(candidates, seen, opts, targetPath, kind, meta) {
|
|
10847
11448
|
if (!existsSync35(targetPath)) return;
|
|
10848
|
-
const resolved =
|
|
11449
|
+
const resolved = path48.resolve(targetPath);
|
|
10849
11450
|
if (seen.has(resolved)) return;
|
|
10850
11451
|
if (!isPathInside2(resolved, opts.harnessRoot)) return;
|
|
10851
11452
|
seen.add(resolved);
|
|
@@ -10862,7 +11463,7 @@ function pushCandidate2(candidates, seen, opts, targetPath, kind, meta) {
|
|
|
10862
11463
|
}
|
|
10863
11464
|
function scanWorktreeDependencyCaches(candidates, seen, opts, worktreePath, meta) {
|
|
10864
11465
|
for (const entry of DEPENDENCY_CACHE_DIRS) {
|
|
10865
|
-
pushCandidate2(candidates, seen, opts,
|
|
11466
|
+
pushCandidate2(candidates, seen, opts, path48.join(worktreePath, entry.dirName), entry.kind, meta);
|
|
10866
11467
|
}
|
|
10867
11468
|
}
|
|
10868
11469
|
function scanDependencyCacheCandidates(opts) {
|
|
@@ -10880,7 +11481,7 @@ function scanDependencyCacheCandidates(opts) {
|
|
|
10880
11481
|
for (const runEntry of readdirSync13(opts.worktreesDir, { withFileTypes: true })) {
|
|
10881
11482
|
if (!runEntry.isDirectory()) continue;
|
|
10882
11483
|
if (opts.runIdFilter && runEntry.name !== opts.runIdFilter) continue;
|
|
10883
|
-
const runPath =
|
|
11484
|
+
const runPath = path48.join(opts.worktreesDir, runEntry.name);
|
|
10884
11485
|
let workerEntries;
|
|
10885
11486
|
try {
|
|
10886
11487
|
workerEntries = readdirSync13(runPath, { withFileTypes: true });
|
|
@@ -10889,7 +11490,7 @@ function scanDependencyCacheCandidates(opts) {
|
|
|
10889
11490
|
}
|
|
10890
11491
|
for (const workerEntry of workerEntries) {
|
|
10891
11492
|
if (!workerEntry.isDirectory()) continue;
|
|
10892
|
-
const worktreePath =
|
|
11493
|
+
const worktreePath = path48.join(runPath, workerEntry.name);
|
|
10893
11494
|
scanWorktreeDependencyCaches(candidates, seen, opts, worktreePath, {
|
|
10894
11495
|
runId: runEntry.name,
|
|
10895
11496
|
worker: workerEntry.name
|
|
@@ -10900,8 +11501,9 @@ function scanDependencyCacheCandidates(opts) {
|
|
|
10900
11501
|
}
|
|
10901
11502
|
|
|
10902
11503
|
// src/cleanup-duplicate-worktrees.ts
|
|
11504
|
+
init_git();
|
|
10903
11505
|
import { existsSync as existsSync36, statSync as statSync11 } from "node:fs";
|
|
10904
|
-
import
|
|
11506
|
+
import path49 from "node:path";
|
|
10905
11507
|
function pathAgeMs4(target, now) {
|
|
10906
11508
|
try {
|
|
10907
11509
|
const mtime = statSync11(target).mtimeMs;
|
|
@@ -10931,8 +11533,8 @@ function parseWorktreePorcelain(output) {
|
|
|
10931
11533
|
return records;
|
|
10932
11534
|
}
|
|
10933
11535
|
function isUnderWorktreesDir(worktreePath, worktreesDir) {
|
|
10934
|
-
const rel =
|
|
10935
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
11536
|
+
const rel = path49.relative(path49.resolve(worktreesDir), path49.resolve(worktreePath));
|
|
11537
|
+
return rel !== "" && !rel.startsWith("..") && !path49.isAbsolute(rel);
|
|
10936
11538
|
}
|
|
10937
11539
|
function isCleanWorktree(worktreePath, repoRoot) {
|
|
10938
11540
|
try {
|
|
@@ -10948,11 +11550,11 @@ function scanDuplicateWorktreeCandidates(opts) {
|
|
|
10948
11550
|
if (!opts.includeOrphans || !existsSync36(opts.worktreesDir)) return [];
|
|
10949
11551
|
const repos = /* @__PURE__ */ new Set();
|
|
10950
11552
|
for (const entry of opts.index.values()) {
|
|
10951
|
-
if (entry.run.repo) repos.add(
|
|
11553
|
+
if (entry.run.repo) repos.add(path49.resolve(entry.run.repo));
|
|
10952
11554
|
}
|
|
10953
11555
|
const indexedPaths = /* @__PURE__ */ new Set();
|
|
10954
11556
|
for (const entry of opts.index.values()) {
|
|
10955
|
-
indexedPaths.add(
|
|
11557
|
+
indexedPaths.add(path49.resolve(entry.worktreePath));
|
|
10956
11558
|
}
|
|
10957
11559
|
const candidates = [];
|
|
10958
11560
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -10965,15 +11567,15 @@ function scanDuplicateWorktreeCandidates(opts) {
|
|
|
10965
11567
|
}
|
|
10966
11568
|
const worktrees = parseWorktreePorcelain(porcelain);
|
|
10967
11569
|
for (const wt of worktrees) {
|
|
10968
|
-
const resolved =
|
|
10969
|
-
if (resolved ===
|
|
11570
|
+
const resolved = path49.resolve(wt.path);
|
|
11571
|
+
if (resolved === path49.resolve(repoRoot)) continue;
|
|
10970
11572
|
if (!isUnderWorktreesDir(resolved, opts.worktreesDir)) continue;
|
|
10971
11573
|
if (indexedPaths.has(resolved)) continue;
|
|
10972
11574
|
if (seen.has(resolved)) continue;
|
|
10973
11575
|
if (!existsSync36(resolved)) continue;
|
|
10974
11576
|
if (!isCleanWorktree(resolved, repoRoot)) continue;
|
|
10975
|
-
const rel =
|
|
10976
|
-
const parts = rel.split(
|
|
11577
|
+
const rel = path49.relative(opts.worktreesDir, resolved);
|
|
11578
|
+
const parts = rel.split(path49.sep);
|
|
10977
11579
|
const runId = parts[0];
|
|
10978
11580
|
const worker = parts[1] ?? "unknown";
|
|
10979
11581
|
seen.add(resolved);
|
|
@@ -10992,12 +11594,14 @@ function scanDuplicateWorktreeCandidates(opts) {
|
|
|
10992
11594
|
}
|
|
10993
11595
|
|
|
10994
11596
|
// src/cleanup-worktree-index.ts
|
|
10995
|
-
|
|
11597
|
+
init_run_store();
|
|
11598
|
+
init_util();
|
|
11599
|
+
import path50 from "node:path";
|
|
10996
11600
|
function buildWorktreeIndexAt(harnessRoot) {
|
|
10997
11601
|
const index = /* @__PURE__ */ new Map();
|
|
10998
11602
|
for (const run of listRunRecordsForHarnessRoot(harnessRoot)) {
|
|
10999
11603
|
for (const name of Object.keys(run.workers || {})) {
|
|
11000
|
-
const workerPath =
|
|
11604
|
+
const workerPath = path50.join(
|
|
11001
11605
|
runDirectoryAt(harnessRoot, run.id),
|
|
11002
11606
|
"workers",
|
|
11003
11607
|
safeSlug(name),
|
|
@@ -11005,9 +11609,9 @@ function buildWorktreeIndexAt(harnessRoot) {
|
|
|
11005
11609
|
);
|
|
11006
11610
|
const worker = readJson(workerPath, void 0);
|
|
11007
11611
|
if (!worker?.worktreePath) continue;
|
|
11008
|
-
index.set(
|
|
11612
|
+
index.set(path50.resolve(worker.worktreePath), {
|
|
11009
11613
|
harnessRoot,
|
|
11010
|
-
worktreePath:
|
|
11614
|
+
worktreePath: path50.resolve(worker.worktreePath),
|
|
11011
11615
|
runId: run.id,
|
|
11012
11616
|
workerName: name,
|
|
11013
11617
|
run,
|
|
@@ -11076,15 +11680,16 @@ function resolvePipelineHarnessRetention(runId) {
|
|
|
11076
11680
|
}
|
|
11077
11681
|
|
|
11078
11682
|
// src/cleanup-orphan-safety.ts
|
|
11683
|
+
init_git();
|
|
11079
11684
|
import { existsSync as existsSync37, statSync as statSync12 } from "node:fs";
|
|
11080
|
-
import
|
|
11685
|
+
import path51 from "node:path";
|
|
11081
11686
|
var DEFAULT_HEARTBEAT_FRESH_MS = 30 * 60 * 1e3;
|
|
11082
11687
|
function assessOrphanWorktreeSafety(input) {
|
|
11083
11688
|
const now = input.now ?? Date.now();
|
|
11084
11689
|
const heartbeatFreshMs = input.heartbeatFreshMs ?? DEFAULT_HEARTBEAT_FRESH_MS;
|
|
11085
11690
|
if (!existsSync37(input.worktreePath)) return null;
|
|
11086
11691
|
if (input.runId && input.workerName) {
|
|
11087
|
-
const heartbeatPath =
|
|
11692
|
+
const heartbeatPath = path51.join(
|
|
11088
11693
|
input.harnessRoot,
|
|
11089
11694
|
"runs",
|
|
11090
11695
|
input.runId,
|
|
@@ -11098,7 +11703,7 @@ function assessOrphanWorktreeSafety(input) {
|
|
|
11098
11703
|
} catch {
|
|
11099
11704
|
}
|
|
11100
11705
|
}
|
|
11101
|
-
const gitDir =
|
|
11706
|
+
const gitDir = path51.join(input.worktreePath, ".git");
|
|
11102
11707
|
if (!existsSync37(gitDir)) return null;
|
|
11103
11708
|
const porcelain = gitCapture(input.worktreePath, ["status", "--porcelain"]);
|
|
11104
11709
|
if (porcelain.status !== 0) return "pr_or_unmerged_commits";
|
|
@@ -11128,8 +11733,9 @@ function assessOrphanWorktreeSafety(input) {
|
|
|
11128
11733
|
}
|
|
11129
11734
|
|
|
11130
11735
|
// src/harness-storage-snapshot.ts
|
|
11736
|
+
init_paths();
|
|
11131
11737
|
import { existsSync as existsSync38, readdirSync as readdirSync14, statSync as statSync13 } from "node:fs";
|
|
11132
|
-
import
|
|
11738
|
+
import path52 from "node:path";
|
|
11133
11739
|
function harnessStorageSnapshot(opts = {}) {
|
|
11134
11740
|
const harnessRoot = normalizeHarnessRoot(opts.harnessRoot ?? resolveHarnessRoot());
|
|
11135
11741
|
const worktreesDir = harnessWorktreesDir(harnessRoot);
|
|
@@ -11167,7 +11773,7 @@ function harnessStorageSnapshot(opts = {}) {
|
|
|
11167
11773
|
for (const runEntry of entries) {
|
|
11168
11774
|
if (!runEntry.isDirectory()) continue;
|
|
11169
11775
|
runCount += 1;
|
|
11170
|
-
const runPath =
|
|
11776
|
+
const runPath = path52.join(worktreesDir, runEntry.name);
|
|
11171
11777
|
try {
|
|
11172
11778
|
const st = statSync13(runPath);
|
|
11173
11779
|
oldestMs = oldestMs === null ? st.mtimeMs : Math.min(oldestMs, st.mtimeMs);
|
|
@@ -11202,12 +11808,13 @@ function harnessStorageSnapshot(opts = {}) {
|
|
|
11202
11808
|
}
|
|
11203
11809
|
|
|
11204
11810
|
// src/cleanup-harness-roots.ts
|
|
11811
|
+
init_paths();
|
|
11205
11812
|
import { existsSync as existsSync39 } from "node:fs";
|
|
11206
|
-
import { homedir as
|
|
11207
|
-
import
|
|
11813
|
+
import { homedir as homedir13 } from "node:os";
|
|
11814
|
+
import path53 from "node:path";
|
|
11208
11815
|
var WELL_KNOWN_HARNESS_SCAN_ROOTS = [
|
|
11209
11816
|
"/var/tmp/kynver-harness",
|
|
11210
|
-
|
|
11817
|
+
path53.join(homedir13(), ".openclaw", "harness")
|
|
11211
11818
|
];
|
|
11212
11819
|
function addRoot(seen, roots, candidate) {
|
|
11213
11820
|
if (!candidate?.trim()) return;
|
|
@@ -11229,7 +11836,7 @@ function resolveHarnessScanRoots(options = {}) {
|
|
|
11229
11836
|
for (const candidate of extra ?? []) addRoot(seen, roots, candidate);
|
|
11230
11837
|
if (shouldScanWellKnownRoots(options)) {
|
|
11231
11838
|
for (const candidate of WELL_KNOWN_HARNESS_SCAN_ROOTS) {
|
|
11232
|
-
const resolved =
|
|
11839
|
+
const resolved = path53.resolve(candidate);
|
|
11233
11840
|
if (!seen.has(resolved) && existsSync39(resolved)) addRoot(seen, roots, resolved);
|
|
11234
11841
|
}
|
|
11235
11842
|
}
|
|
@@ -11237,6 +11844,7 @@ function resolveHarnessScanRoots(options = {}) {
|
|
|
11237
11844
|
}
|
|
11238
11845
|
|
|
11239
11846
|
// src/cleanup-disk-pressure.ts
|
|
11847
|
+
init_disk_gate();
|
|
11240
11848
|
function envFlag4(name) {
|
|
11241
11849
|
const v = process.env[name];
|
|
11242
11850
|
return v === "1" || v === "true" || v === "yes";
|
|
@@ -11286,6 +11894,7 @@ function emitCleanupProgress(phase, detail) {
|
|
|
11286
11894
|
}
|
|
11287
11895
|
|
|
11288
11896
|
// src/cleanup-git-rev-cache.ts
|
|
11897
|
+
init_git();
|
|
11289
11898
|
var CleanupGitRevCache = class {
|
|
11290
11899
|
aheadOfMain = /* @__PURE__ */ new Map();
|
|
11291
11900
|
countAheadOfMain(worktreePath, base = "origin/main") {
|
|
@@ -11304,6 +11913,7 @@ var CleanupGitRevCache = class {
|
|
|
11304
11913
|
};
|
|
11305
11914
|
|
|
11306
11915
|
// src/cleanup-git-status-cache.ts
|
|
11916
|
+
init_git();
|
|
11307
11917
|
var CleanupGitStatusCache = class {
|
|
11308
11918
|
cache = /* @__PURE__ */ new Map();
|
|
11309
11919
|
porcelain(worktreePath) {
|
|
@@ -11415,9 +12025,9 @@ function mergeWorktreeIndexes(scanRoots) {
|
|
|
11415
12025
|
}
|
|
11416
12026
|
function worktreePathForCandidate(candidate, worktreesDir) {
|
|
11417
12027
|
if (candidate.runId && candidate.worker) {
|
|
11418
|
-
return
|
|
12028
|
+
return path54.join(worktreesDir, candidate.runId, candidate.worker);
|
|
11419
12029
|
}
|
|
11420
|
-
return
|
|
12030
|
+
return path54.resolve(candidate.path, "..");
|
|
11421
12031
|
}
|
|
11422
12032
|
function runHarnessCleanup(options = {}) {
|
|
11423
12033
|
let retention = resolveHarnessRetention(options);
|
|
@@ -11446,7 +12056,7 @@ function runHarnessCleanup(options = {}) {
|
|
|
11446
12056
|
for (const harnessRoot of paths.scanRoots) {
|
|
11447
12057
|
if (atSweepCap()) break;
|
|
11448
12058
|
emitCleanupProgress("root", harnessRoot);
|
|
11449
|
-
const worktreesDir =
|
|
12059
|
+
const worktreesDir = path54.join(harnessRoot, "worktrees");
|
|
11450
12060
|
const scanOpts = {
|
|
11451
12061
|
harnessRoot,
|
|
11452
12062
|
worktreesDir,
|
|
@@ -11466,7 +12076,7 @@ function runHarnessCleanup(options = {}) {
|
|
|
11466
12076
|
if (dependencyProcessed % 50 === 0) {
|
|
11467
12077
|
emitCleanupProgress("dependency", `${dependencyProcessed}/${dependencyCandidates.length} evaluated`);
|
|
11468
12078
|
}
|
|
11469
|
-
const resolved =
|
|
12079
|
+
const resolved = path54.resolve(raw.path);
|
|
11470
12080
|
if (processedPaths.has(resolved)) continue;
|
|
11471
12081
|
processedPaths.add(resolved);
|
|
11472
12082
|
const candidate = { ...raw, path: resolved };
|
|
@@ -11477,7 +12087,7 @@ function runHarnessCleanup(options = {}) {
|
|
|
11477
12087
|
continue;
|
|
11478
12088
|
}
|
|
11479
12089
|
const worktreePath = worktreePathForCandidate(candidate, worktreesDir);
|
|
11480
|
-
const indexed = index.get(
|
|
12090
|
+
const indexed = index.get(path54.resolve(worktreePath)) ?? null;
|
|
11481
12091
|
const guardReason = skipDependencyCacheRemoval({
|
|
11482
12092
|
indexed,
|
|
11483
12093
|
includeOrphans: true,
|
|
@@ -11502,7 +12112,7 @@ function runHarnessCleanup(options = {}) {
|
|
|
11502
12112
|
}
|
|
11503
12113
|
for (const raw of scanBuildCacheCandidates(scanOpts)) {
|
|
11504
12114
|
if (atSweepCap()) break;
|
|
11505
|
-
const resolved =
|
|
12115
|
+
const resolved = path54.resolve(raw.path);
|
|
11506
12116
|
if (processedPaths.has(resolved)) continue;
|
|
11507
12117
|
processedPaths.add(resolved);
|
|
11508
12118
|
const candidate = { ...raw, path: resolved };
|
|
@@ -11513,7 +12123,7 @@ function runHarnessCleanup(options = {}) {
|
|
|
11513
12123
|
continue;
|
|
11514
12124
|
}
|
|
11515
12125
|
const worktreePath = worktreePathForCandidate(candidate, worktreesDir);
|
|
11516
|
-
const indexed = index.get(
|
|
12126
|
+
const indexed = index.get(path54.resolve(worktreePath)) ?? null;
|
|
11517
12127
|
const guardReason = skipBuildCacheRemoval({
|
|
11518
12128
|
indexed,
|
|
11519
12129
|
includeOrphans: true,
|
|
@@ -11549,11 +12159,11 @@ function runHarnessCleanup(options = {}) {
|
|
|
11549
12159
|
if (worktreeProcessed % 50 === 0) {
|
|
11550
12160
|
emitCleanupProgress("worktrees", `${worktreeProcessed}/${worktreeCandidates.length} evaluated`);
|
|
11551
12161
|
}
|
|
11552
|
-
const resolved =
|
|
12162
|
+
const resolved = path54.resolve(raw.path);
|
|
11553
12163
|
if (worktreeSeen.has(resolved)) continue;
|
|
11554
12164
|
worktreeSeen.add(resolved);
|
|
11555
12165
|
const candidate = { ...raw, path: resolved };
|
|
11556
|
-
const indexed = index.get(
|
|
12166
|
+
const indexed = index.get(path54.resolve(candidate.path)) ?? null;
|
|
11557
12167
|
const orphanSafety = indexed ? null : assessOrphanWorktreeSafety({
|
|
11558
12168
|
worktreePath: candidate.path,
|
|
11559
12169
|
harnessRoot,
|
|
@@ -11563,7 +12173,7 @@ function runHarnessCleanup(options = {}) {
|
|
|
11563
12173
|
});
|
|
11564
12174
|
const guardSkip = skipWorktreeRemoval({
|
|
11565
12175
|
indexed,
|
|
11566
|
-
worktreePath:
|
|
12176
|
+
worktreePath: path54.resolve(candidate.path),
|
|
11567
12177
|
includeOrphans: retention.includeOrphans,
|
|
11568
12178
|
worktreesAgeMs: retention.worktreesAgeMs,
|
|
11569
12179
|
terminalWorktreesAgeMs: retention.terminalWorktreesAgeMs,
|
|
@@ -11595,11 +12205,11 @@ function runHarnessCleanup(options = {}) {
|
|
|
11595
12205
|
now: paths.now
|
|
11596
12206
|
})) {
|
|
11597
12207
|
if (atSweepCap()) break;
|
|
11598
|
-
const resolved =
|
|
12208
|
+
const resolved = path54.resolve(raw.path);
|
|
11599
12209
|
if (processedPaths.has(resolved)) continue;
|
|
11600
12210
|
processedPaths.add(resolved);
|
|
11601
12211
|
const candidate = { ...raw, path: resolved };
|
|
11602
|
-
const runId = candidate.runId ??
|
|
12212
|
+
const runId = candidate.runId ?? path54.basename(resolved);
|
|
11603
12213
|
const dirSkip = skipRunDirectoryRemoval({
|
|
11604
12214
|
harnessRoot,
|
|
11605
12215
|
runId,
|
|
@@ -11734,12 +12344,13 @@ function isPipelineCleanupEnabled() {
|
|
|
11734
12344
|
|
|
11735
12345
|
// src/installed-package-versions.ts
|
|
11736
12346
|
import { readFile } from "node:fs/promises";
|
|
11737
|
-
import { homedir as
|
|
11738
|
-
import
|
|
12347
|
+
import { homedir as homedir14 } from "node:os";
|
|
12348
|
+
import path56 from "node:path";
|
|
11739
12349
|
|
|
11740
12350
|
// src/memory-cost-package-version-guard.ts
|
|
11741
|
-
|
|
11742
|
-
import
|
|
12351
|
+
init_default_repo_discovery();
|
|
12352
|
+
import { existsSync as existsSync40, readFileSync as readFileSync14 } from "node:fs";
|
|
12353
|
+
import path55 from "node:path";
|
|
11743
12354
|
var MEMORY_COST_PACKAGE_MIN_VERSIONS = {
|
|
11744
12355
|
"@kynver-app/runtime": "0.1.83",
|
|
11745
12356
|
"@kynver-app/openclaw-agent-os": "0.1.43",
|
|
@@ -11790,7 +12401,7 @@ function maxSemver(versions) {
|
|
|
11790
12401
|
}
|
|
11791
12402
|
function readPackageJsonVersion(packageJsonPath) {
|
|
11792
12403
|
try {
|
|
11793
|
-
const parsed = JSON.parse(
|
|
12404
|
+
const parsed = JSON.parse(readFileSync14(packageJsonPath, "utf8"));
|
|
11794
12405
|
return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
|
|
11795
12406
|
} catch {
|
|
11796
12407
|
return null;
|
|
@@ -11801,8 +12412,8 @@ function resolveRepoRoot(cwd, explicitRepoRoot) {
|
|
|
11801
12412
|
(value) => Boolean(value?.trim())
|
|
11802
12413
|
);
|
|
11803
12414
|
for (const candidate of candidates) {
|
|
11804
|
-
const resolved =
|
|
11805
|
-
if (existsSync40(
|
|
12415
|
+
const resolved = path55.resolve(candidate);
|
|
12416
|
+
if (existsSync40(path55.join(resolved, "packages/kynver-runtime/package.json")) && existsSync40(path55.join(resolved, "package.json"))) {
|
|
11806
12417
|
return resolved;
|
|
11807
12418
|
}
|
|
11808
12419
|
}
|
|
@@ -11815,7 +12426,7 @@ function probeRepoPackageVersions(input = {}) {
|
|
|
11815
12426
|
if (!repoRoot) return {};
|
|
11816
12427
|
const out = {};
|
|
11817
12428
|
for (const packageName of MEMORY_COST_MANAGED_PACKAGES) {
|
|
11818
|
-
const packageJsonPath =
|
|
12429
|
+
const packageJsonPath = path55.join(repoRoot, REPO_PACKAGE_JSON_RELATIVE[packageName]);
|
|
11819
12430
|
const version = readPackageJsonVersion(packageJsonPath);
|
|
11820
12431
|
if (!version) continue;
|
|
11821
12432
|
out[packageName] = { version, source: "repo", path: packageJsonPath };
|
|
@@ -11934,13 +12545,13 @@ function unique(values) {
|
|
|
11934
12545
|
return [...new Set(values.filter((value) => Boolean(value)))];
|
|
11935
12546
|
}
|
|
11936
12547
|
function moduleRoots() {
|
|
11937
|
-
const home =
|
|
11938
|
-
const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ??
|
|
11939
|
-
const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ?
|
|
12548
|
+
const home = homedir14();
|
|
12549
|
+
const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ?? path56.join(home, ".openclaw", "npm");
|
|
12550
|
+
const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ? path56.join(trim(process.env.NPM_CONFIG_PREFIX), "lib", "node_modules") : path56.join(home, ".npm-global", "lib", "node_modules"));
|
|
11940
12551
|
return unique([
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot :
|
|
12552
|
+
path56.join(openClawPrefix, "lib", "node_modules"),
|
|
12553
|
+
path56.join(openClawPrefix, "node_modules"),
|
|
12554
|
+
npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot : path56.join(npmGlobalRoot, "lib", "node_modules")
|
|
11944
12555
|
]);
|
|
11945
12556
|
}
|
|
11946
12557
|
async function readVersion(packageJsonPath) {
|
|
@@ -11956,7 +12567,7 @@ function installedPackageJsonCandidates(packageName) {
|
|
|
11956
12567
|
const seen = /* @__PURE__ */ new Set();
|
|
11957
12568
|
const out = [];
|
|
11958
12569
|
for (const root of roots) {
|
|
11959
|
-
const candidate =
|
|
12570
|
+
const candidate = path56.join(root, packageName, "package.json");
|
|
11960
12571
|
if (seen.has(candidate)) continue;
|
|
11961
12572
|
seen.add(candidate);
|
|
11962
12573
|
out.push(candidate);
|
|
@@ -11981,13 +12592,355 @@ async function collectInstalledPackageVersions(observedAt = (/* @__PURE__ */ new
|
|
|
11981
12592
|
return out;
|
|
11982
12593
|
}
|
|
11983
12594
|
|
|
12595
|
+
// src/provider-evidence/exec.ts
|
|
12596
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
12597
|
+
var DEFAULT_CLI_TIMEOUT_MS = 1e4;
|
|
12598
|
+
var MAX_CLI_BUFFER_BYTES = 4 * 1024 * 1024;
|
|
12599
|
+
var defaultCliRunner = (cmd, args, opts) => {
|
|
12600
|
+
try {
|
|
12601
|
+
const result = spawnSync7(cmd, args, {
|
|
12602
|
+
encoding: "utf8",
|
|
12603
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
12604
|
+
timeout: opts?.timeoutMs ?? DEFAULT_CLI_TIMEOUT_MS,
|
|
12605
|
+
maxBuffer: MAX_CLI_BUFFER_BYTES
|
|
12606
|
+
});
|
|
12607
|
+
return {
|
|
12608
|
+
ok: result.status === 0,
|
|
12609
|
+
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
12610
|
+
stderr: typeof result.stderr === "string" ? result.stderr : ""
|
|
12611
|
+
};
|
|
12612
|
+
} catch (err) {
|
|
12613
|
+
return { ok: false, stdout: "", stderr: err instanceof Error ? err.message : String(err) };
|
|
12614
|
+
}
|
|
12615
|
+
};
|
|
12616
|
+
function runCliJson(run, cmd, args) {
|
|
12617
|
+
const result = run(cmd, args);
|
|
12618
|
+
if (!result.ok || !result.stdout.trim()) return null;
|
|
12619
|
+
try {
|
|
12620
|
+
return JSON.parse(result.stdout);
|
|
12621
|
+
} catch {
|
|
12622
|
+
return null;
|
|
12623
|
+
}
|
|
12624
|
+
}
|
|
12625
|
+
|
|
12626
|
+
// src/provider-evidence/types.ts
|
|
12627
|
+
function providerEvidenceKey(provider, kind, subject) {
|
|
12628
|
+
return `${provider} ${kind} ${subject}`;
|
|
12629
|
+
}
|
|
12630
|
+
function parseCommitEvidenceSubject(subject) {
|
|
12631
|
+
const at = subject.lastIndexOf("@");
|
|
12632
|
+
if (at <= 0 || at === subject.length - 1) return null;
|
|
12633
|
+
const repo = subject.slice(0, at);
|
|
12634
|
+
const sha = subject.slice(at + 1);
|
|
12635
|
+
if (!/^[^/\s]+\/[^/\s]+$/.test(repo) || !/^[0-9a-f]{7,40}$/i.test(sha)) return null;
|
|
12636
|
+
return { repo, sha };
|
|
12637
|
+
}
|
|
12638
|
+
function parsePrUrlSubject(subject) {
|
|
12639
|
+
const m = subject.trim().match(/[/:]([^/]+\/[^/]+)\/(?:pull|pulls|merge_requests|pull-requests)\/(\d+)/i);
|
|
12640
|
+
if (!m) return null;
|
|
12641
|
+
const number = Number(m[2]);
|
|
12642
|
+
if (!Number.isFinite(number) || number <= 0) return null;
|
|
12643
|
+
return { repo: m[1], number };
|
|
12644
|
+
}
|
|
12645
|
+
|
|
12646
|
+
// src/provider-evidence/recipes-github.ts
|
|
12647
|
+
var MAX_BODY_CHARS = 8e3;
|
|
12648
|
+
var MAX_STATUS_ROWS = 30;
|
|
12649
|
+
var MAX_CHECK_RUNS = 100;
|
|
12650
|
+
var MAX_CHANGED_FILES = 400;
|
|
12651
|
+
function githubCliAvailable(run) {
|
|
12652
|
+
if (process.env.GITHUB_TOKEN?.trim() || process.env.GH_TOKEN?.trim()) return true;
|
|
12653
|
+
return run("gh", ["auth", "token"]).ok;
|
|
12654
|
+
}
|
|
12655
|
+
function asRecord4(value) {
|
|
12656
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
12657
|
+
}
|
|
12658
|
+
function pickStatusRows(value) {
|
|
12659
|
+
if (!Array.isArray(value)) return [];
|
|
12660
|
+
return value.map((raw) => asRecord4(raw)).filter((row) => row !== null).slice(0, MAX_STATUS_ROWS).map((row) => ({
|
|
12661
|
+
context: row.context ?? null,
|
|
12662
|
+
state: row.state ?? null,
|
|
12663
|
+
target_url: row.target_url ?? null,
|
|
12664
|
+
description: row.description ?? null
|
|
12665
|
+
}));
|
|
12666
|
+
}
|
|
12667
|
+
function fetchCombinedStatus(run, repo, sha) {
|
|
12668
|
+
const status = runCliJson(run, "gh", [
|
|
12669
|
+
"api",
|
|
12670
|
+
`repos/${repo}/commits/${sha}/status`
|
|
12671
|
+
]);
|
|
12672
|
+
if (!status) return null;
|
|
12673
|
+
return { state: status.state ?? null, statuses: pickStatusRows(status.statuses) };
|
|
12674
|
+
}
|
|
12675
|
+
var githubPrSnapshotRecipe = {
|
|
12676
|
+
provider: "github",
|
|
12677
|
+
kind: "pr_snapshot",
|
|
12678
|
+
version: "1",
|
|
12679
|
+
isAvailable: githubCliAvailable,
|
|
12680
|
+
collect(subject, run) {
|
|
12681
|
+
const parsed = parsePrUrlSubject(subject);
|
|
12682
|
+
if (!parsed) return null;
|
|
12683
|
+
const pull = runCliJson(run, "gh", [
|
|
12684
|
+
"api",
|
|
12685
|
+
`repos/${parsed.repo}/pulls/${parsed.number}`
|
|
12686
|
+
]);
|
|
12687
|
+
if (!pull) return null;
|
|
12688
|
+
const head = asRecord4(pull.head);
|
|
12689
|
+
const headSha = typeof head?.sha === "string" ? head.sha : null;
|
|
12690
|
+
const user = asRecord4(pull.user);
|
|
12691
|
+
const headRepoOwner = asRecord4(asRecord4(head?.repo)?.owner);
|
|
12692
|
+
const body = typeof pull.body === "string" ? pull.body.slice(0, MAX_BODY_CHARS) : null;
|
|
12693
|
+
let checkRuns = [];
|
|
12694
|
+
let combinedStatus = {
|
|
12695
|
+
state: null,
|
|
12696
|
+
statuses: []
|
|
12697
|
+
};
|
|
12698
|
+
if (headSha) {
|
|
12699
|
+
const runs = runCliJson(run, "gh", [
|
|
12700
|
+
"api",
|
|
12701
|
+
`repos/${parsed.repo}/commits/${headSha}/check-runs?per_page=100`
|
|
12702
|
+
]);
|
|
12703
|
+
if (Array.isArray(runs?.check_runs)) {
|
|
12704
|
+
checkRuns = runs.check_runs.map((raw) => asRecord4(raw)).filter((row) => row !== null).slice(0, MAX_CHECK_RUNS).map((row) => ({
|
|
12705
|
+
name: row.name ?? null,
|
|
12706
|
+
status: row.status ?? null,
|
|
12707
|
+
conclusion: row.conclusion ?? null
|
|
12708
|
+
}));
|
|
12709
|
+
}
|
|
12710
|
+
combinedStatus = fetchCombinedStatus(run, parsed.repo, headSha) ?? combinedStatus;
|
|
12711
|
+
}
|
|
12712
|
+
const filesResult = run("gh", [
|
|
12713
|
+
"api",
|
|
12714
|
+
"--paginate",
|
|
12715
|
+
`repos/${parsed.repo}/pulls/${parsed.number}/files?per_page=100`,
|
|
12716
|
+
"--jq",
|
|
12717
|
+
".[].filename"
|
|
12718
|
+
]);
|
|
12719
|
+
const changedFiles = filesResult.ok ? filesResult.stdout.split("\n").map((line) => line.trim()).filter(Boolean).slice(0, MAX_CHANGED_FILES) : [];
|
|
12720
|
+
return {
|
|
12721
|
+
pull: {
|
|
12722
|
+
html_url: pull.html_url ?? null,
|
|
12723
|
+
title: pull.title ?? null,
|
|
12724
|
+
body,
|
|
12725
|
+
user: { login: user?.login ?? null },
|
|
12726
|
+
state: pull.state ?? null,
|
|
12727
|
+
draft: pull.draft ?? null,
|
|
12728
|
+
merged: pull.merged ?? null,
|
|
12729
|
+
merged_at: pull.merged_at ?? null,
|
|
12730
|
+
merge_commit_sha: pull.merge_commit_sha ?? null,
|
|
12731
|
+
mergeable: pull.mergeable ?? null,
|
|
12732
|
+
mergeable_state: pull.mergeable_state ?? null,
|
|
12733
|
+
head: {
|
|
12734
|
+
sha: headSha,
|
|
12735
|
+
ref: head?.ref ?? null,
|
|
12736
|
+
repo: { owner: { login: headRepoOwner?.login ?? null } }
|
|
12737
|
+
}
|
|
12738
|
+
},
|
|
12739
|
+
checkRuns,
|
|
12740
|
+
combinedStatus,
|
|
12741
|
+
changedFiles
|
|
12742
|
+
};
|
|
12743
|
+
}
|
|
12744
|
+
};
|
|
12745
|
+
var githubCommitStatusRecipe = {
|
|
12746
|
+
provider: "github",
|
|
12747
|
+
kind: "commit_status",
|
|
12748
|
+
version: "1",
|
|
12749
|
+
isAvailable: githubCliAvailable,
|
|
12750
|
+
collect(subject, run) {
|
|
12751
|
+
const parsed = parseCommitEvidenceSubject(subject);
|
|
12752
|
+
if (!parsed) return null;
|
|
12753
|
+
return fetchCombinedStatus(run, parsed.repo, parsed.sha);
|
|
12754
|
+
}
|
|
12755
|
+
};
|
|
12756
|
+
var githubBranchReachabilityRecipe = {
|
|
12757
|
+
provider: "github",
|
|
12758
|
+
kind: "branch_reachability",
|
|
12759
|
+
version: "1",
|
|
12760
|
+
isAvailable: githubCliAvailable,
|
|
12761
|
+
collect(subject, run) {
|
|
12762
|
+
const parsed = parseCommitEvidenceSubject(subject);
|
|
12763
|
+
if (!parsed) return null;
|
|
12764
|
+
const repoMeta = runCliJson(run, "gh", [
|
|
12765
|
+
"api",
|
|
12766
|
+
`repos/${parsed.repo}`
|
|
12767
|
+
]);
|
|
12768
|
+
const defaultBranch = typeof repoMeta?.default_branch === "string" && repoMeta.default_branch.trim() ? repoMeta.default_branch.trim() : null;
|
|
12769
|
+
if (!defaultBranch) return null;
|
|
12770
|
+
const compare = runCliJson(run, "gh", [
|
|
12771
|
+
"api",
|
|
12772
|
+
`repos/${parsed.repo}/compare/${encodeURIComponent(defaultBranch)}...${parsed.sha}`
|
|
12773
|
+
]);
|
|
12774
|
+
if (!compare) return null;
|
|
12775
|
+
const compareStatus = typeof compare.status === "string" ? compare.status : null;
|
|
12776
|
+
return {
|
|
12777
|
+
defaultBranch,
|
|
12778
|
+
compareStatus,
|
|
12779
|
+
reachable: compareStatus === "identical" || compareStatus === "behind"
|
|
12780
|
+
};
|
|
12781
|
+
}
|
|
12782
|
+
};
|
|
12783
|
+
|
|
12784
|
+
// src/provider-evidence/recipes-vercel.ts
|
|
12785
|
+
var MAX_DEPLOYMENT_ROWS = 5;
|
|
12786
|
+
var STATE_PATTERN = /\b(READY|ERROR|BUILDING|QUEUED|CANCELED|INITIALIZING)\b/i;
|
|
12787
|
+
var URL_PATTERN = /https:\/\/[^\s]+/;
|
|
12788
|
+
var vercelDeploymentStatusRecipe = {
|
|
12789
|
+
provider: "vercel",
|
|
12790
|
+
kind: "deployment_status",
|
|
12791
|
+
version: "1",
|
|
12792
|
+
isAvailable(run) {
|
|
12793
|
+
return run("vercel", ["whoami"]).ok;
|
|
12794
|
+
},
|
|
12795
|
+
collect(subject, run) {
|
|
12796
|
+
const parsed = parseCommitEvidenceSubject(subject);
|
|
12797
|
+
if (!parsed) return null;
|
|
12798
|
+
const result = run("vercel", [
|
|
12799
|
+
"list",
|
|
12800
|
+
"--prod",
|
|
12801
|
+
"--meta",
|
|
12802
|
+
`githubCommitSha=${parsed.sha}`
|
|
12803
|
+
]);
|
|
12804
|
+
if (!result.ok) return null;
|
|
12805
|
+
const deployments = [];
|
|
12806
|
+
for (const line of result.stdout.split("\n")) {
|
|
12807
|
+
const url = line.match(URL_PATTERN)?.[0];
|
|
12808
|
+
if (!url) continue;
|
|
12809
|
+
const state = line.match(STATE_PATTERN)?.[1]?.toUpperCase() ?? null;
|
|
12810
|
+
deployments.push({ url, state });
|
|
12811
|
+
if (deployments.length >= MAX_DEPLOYMENT_ROWS) break;
|
|
12812
|
+
}
|
|
12813
|
+
return { found: deployments.length > 0, deployments };
|
|
12814
|
+
}
|
|
12815
|
+
};
|
|
12816
|
+
|
|
12817
|
+
// src/provider-evidence/registry.ts
|
|
12818
|
+
var _recipes = [];
|
|
12819
|
+
function registerEvidenceCollector(recipe) {
|
|
12820
|
+
if (_recipes.some((r) => r.provider === recipe.provider && r.kind === recipe.kind)) return;
|
|
12821
|
+
_recipes.push(recipe);
|
|
12822
|
+
}
|
|
12823
|
+
function getEvidenceCollector(provider, kind) {
|
|
12824
|
+
return _recipes.find((r) => r.provider === provider && r.kind === kind) ?? null;
|
|
12825
|
+
}
|
|
12826
|
+
function registerDefaultEvidenceCollectors() {
|
|
12827
|
+
registerEvidenceCollector(githubPrSnapshotRecipe);
|
|
12828
|
+
registerEvidenceCollector(githubCommitStatusRecipe);
|
|
12829
|
+
registerEvidenceCollector(githubBranchReachabilityRecipe);
|
|
12830
|
+
registerEvidenceCollector(vercelDeploymentStatusRecipe);
|
|
12831
|
+
}
|
|
12832
|
+
|
|
12833
|
+
// src/provider-evidence/collect.ts
|
|
12834
|
+
var DEFAULT_MAX_SUBJECTS_PER_TICK = 8;
|
|
12835
|
+
var DEFAULT_DEADLINE_MS = 25e3;
|
|
12836
|
+
function collectProviderEvidence(wanted, opts = {}) {
|
|
12837
|
+
registerDefaultEvidenceCollectors();
|
|
12838
|
+
const run = opts.run ?? defaultCliRunner;
|
|
12839
|
+
const now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
12840
|
+
const maxSubjects = opts.maxSubjects ?? DEFAULT_MAX_SUBJECTS_PER_TICK;
|
|
12841
|
+
const deadline = Date.now() + (opts.deadlineMs ?? DEFAULT_DEADLINE_MS);
|
|
12842
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12843
|
+
const deduped = wanted.filter((w) => {
|
|
12844
|
+
const key = providerEvidenceKey(w.provider, w.kind, w.subject);
|
|
12845
|
+
if (seen.has(key)) return false;
|
|
12846
|
+
seen.add(key);
|
|
12847
|
+
return true;
|
|
12848
|
+
});
|
|
12849
|
+
const offset = deduped.length > 0 ? Math.floor(now().getTime() / 6e4) % deduped.length : 0;
|
|
12850
|
+
const rotated = deduped.map((_, i) => deduped[(offset + i) % deduped.length]);
|
|
12851
|
+
const window = rotated.slice(0, maxSubjects);
|
|
12852
|
+
const summary = {
|
|
12853
|
+
attempted: 0,
|
|
12854
|
+
collected: 0,
|
|
12855
|
+
items: [],
|
|
12856
|
+
skipped: []
|
|
12857
|
+
};
|
|
12858
|
+
const availability = /* @__PURE__ */ new Map();
|
|
12859
|
+
for (const item of window) {
|
|
12860
|
+
if (Date.now() > deadline) {
|
|
12861
|
+
summary.skipped.push({ ...item, reason: "budget_exhausted" });
|
|
12862
|
+
continue;
|
|
12863
|
+
}
|
|
12864
|
+
const recipe = getEvidenceCollector(item.provider, item.kind);
|
|
12865
|
+
if (!recipe) {
|
|
12866
|
+
summary.skipped.push({ ...item, reason: "no_recipe" });
|
|
12867
|
+
continue;
|
|
12868
|
+
}
|
|
12869
|
+
const availKey = `${recipe.provider} ${recipe.kind}`;
|
|
12870
|
+
let available = availability.get(availKey);
|
|
12871
|
+
if (available === void 0) {
|
|
12872
|
+
available = recipe.isAvailable(run);
|
|
12873
|
+
availability.set(availKey, available);
|
|
12874
|
+
}
|
|
12875
|
+
if (!available) {
|
|
12876
|
+
summary.skipped.push({ ...item, reason: "provider_unavailable" });
|
|
12877
|
+
continue;
|
|
12878
|
+
}
|
|
12879
|
+
summary.attempted += 1;
|
|
12880
|
+
const payload = recipe.collect(item.subject, run);
|
|
12881
|
+
if (payload === null || payload === void 0) {
|
|
12882
|
+
summary.skipped.push({ ...item, reason: "collect_failed" });
|
|
12883
|
+
continue;
|
|
12884
|
+
}
|
|
12885
|
+
summary.collected += 1;
|
|
12886
|
+
summary.items.push({
|
|
12887
|
+
provider: item.provider,
|
|
12888
|
+
kind: item.kind,
|
|
12889
|
+
subject: item.subject,
|
|
12890
|
+
payload,
|
|
12891
|
+
observedAt: now().toISOString(),
|
|
12892
|
+
collectorVersion: recipe.version
|
|
12893
|
+
});
|
|
12894
|
+
}
|
|
12895
|
+
return summary;
|
|
12896
|
+
}
|
|
12897
|
+
|
|
12898
|
+
// src/provider-evidence/wanted-store.ts
|
|
12899
|
+
init_run_store();
|
|
12900
|
+
init_util();
|
|
12901
|
+
import path57 from "node:path";
|
|
12902
|
+
var WANTED_FILE = "provider-evidence-wanted.json";
|
|
12903
|
+
function wantedFilePath(runId) {
|
|
12904
|
+
return path57.join(runDirectory(runId), WANTED_FILE);
|
|
12905
|
+
}
|
|
12906
|
+
function parseWantedItems(value) {
|
|
12907
|
+
if (!Array.isArray(value)) return [];
|
|
12908
|
+
const out = [];
|
|
12909
|
+
for (const raw of value) {
|
|
12910
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
|
|
12911
|
+
const row = raw;
|
|
12912
|
+
const provider = typeof row.provider === "string" ? row.provider.trim() : "";
|
|
12913
|
+
const kind = typeof row.kind === "string" ? row.kind.trim() : "";
|
|
12914
|
+
const subject = typeof row.subject === "string" ? row.subject.trim() : "";
|
|
12915
|
+
if (!provider || !kind || !subject) continue;
|
|
12916
|
+
out.push({ provider, kind, subject });
|
|
12917
|
+
}
|
|
12918
|
+
return out;
|
|
12919
|
+
}
|
|
12920
|
+
function loadPersistedProviderEvidenceWanted(runId) {
|
|
12921
|
+
const persisted = readJson(wantedFilePath(runId), null);
|
|
12922
|
+
return parseWantedItems(persisted?.wanted);
|
|
12923
|
+
}
|
|
12924
|
+
function persistProviderEvidenceWanted(runId, wanted) {
|
|
12925
|
+
writeJson(wantedFilePath(runId), {
|
|
12926
|
+
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12927
|
+
wanted
|
|
12928
|
+
});
|
|
12929
|
+
}
|
|
12930
|
+
function extractProviderEvidenceWanted(tickResponse) {
|
|
12931
|
+
if (!tickResponse || typeof tickResponse !== "object" || Array.isArray(tickResponse)) return null;
|
|
12932
|
+
const wanted = tickResponse.providerEvidenceWanted;
|
|
12933
|
+
if (!Array.isArray(wanted)) return null;
|
|
12934
|
+
return parseWantedItems(wanted);
|
|
12935
|
+
}
|
|
12936
|
+
|
|
11984
12937
|
// src/pipeline-tick.ts
|
|
11985
12938
|
async function completeFinishedWorkers(runId, args) {
|
|
11986
12939
|
const run = loadRun(runId);
|
|
11987
12940
|
const outcomes = [];
|
|
11988
12941
|
for (const name of Object.keys(run.workers || {})) {
|
|
11989
12942
|
const worker = readJson(
|
|
11990
|
-
|
|
12943
|
+
path58.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
11991
12944
|
void 0
|
|
11992
12945
|
);
|
|
11993
12946
|
if (!worker?.taskId || worker.localOnly) continue;
|
|
@@ -12020,6 +12973,13 @@ async function postOperatorTick(agentOsId, runId, resourceGate, args, harnessCle
|
|
|
12020
12973
|
const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/operator/tick`;
|
|
12021
12974
|
const packageVersions = await collectInstalledPackageVersions();
|
|
12022
12975
|
const activeHarnessWorkers = collectRunActiveHarnessWorkers(runId);
|
|
12976
|
+
let evidenceCollection = null;
|
|
12977
|
+
try {
|
|
12978
|
+
const evidenceWanted = loadPersistedProviderEvidenceWanted(runId);
|
|
12979
|
+
evidenceCollection = evidenceWanted.length > 0 ? collectProviderEvidence(evidenceWanted) : null;
|
|
12980
|
+
} catch {
|
|
12981
|
+
evidenceCollection = null;
|
|
12982
|
+
}
|
|
12023
12983
|
const res = await postJson(url, secret, {
|
|
12024
12984
|
agentOsId,
|
|
12025
12985
|
runId,
|
|
@@ -12034,9 +12994,27 @@ async function postOperatorTick(agentOsId, runId, resourceGate, args, harnessCle
|
|
|
12034
12994
|
...harnessCleanup ? { harnessCleanup } : {},
|
|
12035
12995
|
runnerPresence: resolveRunnerPresencePayload({ runId }),
|
|
12036
12996
|
activeHarnessWorkers,
|
|
12037
|
-
...
|
|
12997
|
+
...evidenceCollection && evidenceCollection.items.length > 0 ? { providerEvidence: evidenceCollection.items } : {}
|
|
12038
12998
|
});
|
|
12039
|
-
|
|
12999
|
+
const nextWanted = extractProviderEvidenceWanted(res.response);
|
|
13000
|
+
if (nextWanted) {
|
|
13001
|
+
try {
|
|
13002
|
+
persistProviderEvidenceWanted(runId, nextWanted);
|
|
13003
|
+
} catch {
|
|
13004
|
+
}
|
|
13005
|
+
}
|
|
13006
|
+
return {
|
|
13007
|
+
ok: res.ok,
|
|
13008
|
+
httpStatus: res.status,
|
|
13009
|
+
response: res.response,
|
|
13010
|
+
...evidenceCollection ? {
|
|
13011
|
+
providerEvidence: {
|
|
13012
|
+
attempted: evidenceCollection.attempted,
|
|
13013
|
+
collected: evidenceCollection.collected,
|
|
13014
|
+
skipped: evidenceCollection.skipped.length
|
|
13015
|
+
}
|
|
13016
|
+
} : {}
|
|
13017
|
+
};
|
|
12040
13018
|
}
|
|
12041
13019
|
async function runPipelineTick(args) {
|
|
12042
13020
|
const runId = String(required(String(args.run || ""), "--run"));
|
|
@@ -12184,6 +13162,7 @@ async function runDaemon(args) {
|
|
|
12184
13162
|
const cronEnv = resolveKynverCronEnv();
|
|
12185
13163
|
while (!stopping) {
|
|
12186
13164
|
try {
|
|
13165
|
+
writeDaemonHeartbeat({ agentOsId, runId });
|
|
12187
13166
|
if (cronEnv.tickEnabled) {
|
|
12188
13167
|
const cronTick = await runKynverCronTick({
|
|
12189
13168
|
env: cronEnv,
|
|
@@ -12210,8 +13189,140 @@ async function runDaemon(args) {
|
|
|
12210
13189
|
console.error(JSON.stringify({ event: "daemon_stop", runId, agentOsId }));
|
|
12211
13190
|
}
|
|
12212
13191
|
|
|
13192
|
+
// src/daemon-keeper.ts
|
|
13193
|
+
init_config();
|
|
13194
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
13195
|
+
init_util();
|
|
13196
|
+
var DEFAULT_STALL_MS = 15 * 6e4;
|
|
13197
|
+
var STARTUP_GRACE_MS = 2 * 6e4;
|
|
13198
|
+
var KILL_GRACE_MS = 1e4;
|
|
13199
|
+
var BACKOFF_BASE_MS = 5e3;
|
|
13200
|
+
var BACKOFF_CAP_MS = 5 * 6e4;
|
|
13201
|
+
var HEALTHY_RESET_MS = 30 * 6e4;
|
|
13202
|
+
var POLL_MS = 5e3;
|
|
13203
|
+
function resolveKeeperStallMs(flag, env = process.env) {
|
|
13204
|
+
const fromFlag = typeof flag === "string" ? Number.parseInt(flag, 10) : NaN;
|
|
13205
|
+
if (Number.isFinite(fromFlag) && fromFlag > 0) return fromFlag;
|
|
13206
|
+
const fromEnv = Number.parseInt(env.KYNVER_DAEMON_STALL_MS ?? "", 10);
|
|
13207
|
+
if (Number.isFinite(fromEnv) && fromEnv > 0) return fromEnv;
|
|
13208
|
+
return DEFAULT_STALL_MS;
|
|
13209
|
+
}
|
|
13210
|
+
function shouldRunDaemonKeeper(args, env = process.env) {
|
|
13211
|
+
if (args.keeperChild === true || args.keeperChild === "true") return false;
|
|
13212
|
+
if (args.noSupervise === true || args.noSupervise === "true") return false;
|
|
13213
|
+
if (args.supervised === "false") return false;
|
|
13214
|
+
const envFlag5 = (env.KYNVER_DAEMON_SUPERVISED ?? "").trim().toLowerCase();
|
|
13215
|
+
if (envFlag5 === "0" || envFlag5 === "false" || envFlag5 === "no" || envFlag5 === "off") {
|
|
13216
|
+
return false;
|
|
13217
|
+
}
|
|
13218
|
+
return true;
|
|
13219
|
+
}
|
|
13220
|
+
function nextKeeperBackoffMs(consecutiveFailures, base = BACKOFF_BASE_MS, cap = BACKOFF_CAP_MS) {
|
|
13221
|
+
const exp = Math.min(Math.max(consecutiveFailures, 1) - 1, 10);
|
|
13222
|
+
return Math.min(base * 2 ** exp, cap);
|
|
13223
|
+
}
|
|
13224
|
+
function keeperRunWasHealthy(startedAtMs, endedAtMs, healthyMs = HEALTHY_RESET_MS) {
|
|
13225
|
+
return endedAtMs - startedAtMs >= healthyMs;
|
|
13226
|
+
}
|
|
13227
|
+
function keeperLog(event, detail = {}) {
|
|
13228
|
+
console.error(JSON.stringify({ event: `daemon_keeper_${event}`, ...detail }));
|
|
13229
|
+
}
|
|
13230
|
+
function buildKeeperChildArgv(argv) {
|
|
13231
|
+
const out = [];
|
|
13232
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
13233
|
+
const arg = argv[i];
|
|
13234
|
+
if (arg === "--supervised" || arg === "--no-supervise" || arg === "--keeper-child") continue;
|
|
13235
|
+
if (arg === "--stall-ms") {
|
|
13236
|
+
if (i + 1 < argv.length && !argv[i + 1].startsWith("--")) i += 1;
|
|
13237
|
+
continue;
|
|
13238
|
+
}
|
|
13239
|
+
if (arg.startsWith("--stall-ms=") || arg.startsWith("--supervised=")) continue;
|
|
13240
|
+
out.push(arg);
|
|
13241
|
+
}
|
|
13242
|
+
out.push("--keeper-child");
|
|
13243
|
+
return out;
|
|
13244
|
+
}
|
|
13245
|
+
async function runDaemonKeeper(args, rawArgv = process.argv.slice(2)) {
|
|
13246
|
+
const agentOsId = String(
|
|
13247
|
+
required(String(args.agentOsId || loadUserConfig().agentOsId || ""), "--agent-os-id")
|
|
13248
|
+
);
|
|
13249
|
+
const stallMs = resolveKeeperStallMs(args.stallMs);
|
|
13250
|
+
const childArgv = buildKeeperChildArgv(rawArgv);
|
|
13251
|
+
const cliEntry = process.argv[1];
|
|
13252
|
+
let stopping = false;
|
|
13253
|
+
let child = null;
|
|
13254
|
+
let consecutiveFailures = 0;
|
|
13255
|
+
const stop = (signal) => {
|
|
13256
|
+
stopping = true;
|
|
13257
|
+
keeperLog("stop", { signal });
|
|
13258
|
+
if (child?.pid) child.kill(signal);
|
|
13259
|
+
};
|
|
13260
|
+
process.on("SIGINT", () => stop("SIGINT"));
|
|
13261
|
+
process.on("SIGTERM", () => stop("SIGTERM"));
|
|
13262
|
+
keeperLog("start", { agentOsId, stallMs, childArgv });
|
|
13263
|
+
while (!stopping) {
|
|
13264
|
+
const startedAt = Date.now();
|
|
13265
|
+
let exited = false;
|
|
13266
|
+
let exitCode = null;
|
|
13267
|
+
let exitSignal = null;
|
|
13268
|
+
child = spawn6(process.execPath, [cliEntry, ...childArgv], {
|
|
13269
|
+
stdio: "inherit",
|
|
13270
|
+
env: process.env
|
|
13271
|
+
});
|
|
13272
|
+
keeperLog("child_spawned", { pid: child.pid ?? null });
|
|
13273
|
+
child.on("exit", (code, signal) => {
|
|
13274
|
+
exited = true;
|
|
13275
|
+
exitCode = code;
|
|
13276
|
+
exitSignal = signal;
|
|
13277
|
+
});
|
|
13278
|
+
while (!exited && !stopping) {
|
|
13279
|
+
await sleepMsAsync(POLL_MS);
|
|
13280
|
+
if (exited || stopping) break;
|
|
13281
|
+
if (Date.now() - startedAt < STARTUP_GRACE_MS) continue;
|
|
13282
|
+
const beat = readDaemonHeartbeat(agentOsId);
|
|
13283
|
+
const ownBeat = beat && beat.pid === child.pid ? beat : null;
|
|
13284
|
+
if (ownBeat && isDaemonHeartbeatStale(ownBeat, stallMs)) {
|
|
13285
|
+
keeperLog("stall_detected", {
|
|
13286
|
+
pid: child.pid ?? null,
|
|
13287
|
+
lastBeatAt: ownBeat.observedAt,
|
|
13288
|
+
stallMs
|
|
13289
|
+
});
|
|
13290
|
+
child.kill("SIGTERM");
|
|
13291
|
+
await sleepMsAsync(KILL_GRACE_MS);
|
|
13292
|
+
if (!exited) child.kill("SIGKILL");
|
|
13293
|
+
break;
|
|
13294
|
+
}
|
|
13295
|
+
if (!ownBeat && Date.now() - startedAt > stallMs + STARTUP_GRACE_MS) {
|
|
13296
|
+
keeperLog("no_heartbeat_detected", { pid: child.pid ?? null, stallMs });
|
|
13297
|
+
child.kill("SIGTERM");
|
|
13298
|
+
await sleepMsAsync(KILL_GRACE_MS);
|
|
13299
|
+
if (!exited) child.kill("SIGKILL");
|
|
13300
|
+
break;
|
|
13301
|
+
}
|
|
13302
|
+
}
|
|
13303
|
+
while (!exited && !stopping) {
|
|
13304
|
+
await sleepMsAsync(POLL_MS);
|
|
13305
|
+
}
|
|
13306
|
+
if (stopping) break;
|
|
13307
|
+
const endedAt = Date.now();
|
|
13308
|
+
if (keeperRunWasHealthy(startedAt, endedAt)) consecutiveFailures = 0;
|
|
13309
|
+
consecutiveFailures += 1;
|
|
13310
|
+
const backoff = nextKeeperBackoffMs(consecutiveFailures);
|
|
13311
|
+
keeperLog("child_exited", {
|
|
13312
|
+
code: exitCode,
|
|
13313
|
+
signal: exitSignal,
|
|
13314
|
+
uptimeMs: endedAt - startedAt,
|
|
13315
|
+
consecutiveFailures,
|
|
13316
|
+
respawnInMs: backoff
|
|
13317
|
+
});
|
|
13318
|
+
await sleepMsAsync(backoff);
|
|
13319
|
+
}
|
|
13320
|
+
keeperLog("stopped", { agentOsId });
|
|
13321
|
+
}
|
|
13322
|
+
|
|
12213
13323
|
// src/plan-progress.ts
|
|
12214
|
-
|
|
13324
|
+
init_config();
|
|
13325
|
+
import path62 from "node:path";
|
|
12215
13326
|
|
|
12216
13327
|
// src/bounded-build/constants.ts
|
|
12217
13328
|
var DEFAULT_BUILD_MEM_BUDGET_BYTES = 1536 * 1024 * 1024;
|
|
@@ -12220,6 +13331,9 @@ var DEFAULT_NODE_OLD_SPACE_SIZE_MB = 1024;
|
|
|
12220
13331
|
var DEFAULT_SYSTEMD_MEMORY_MAX = "1.5G";
|
|
12221
13332
|
var DEFAULT_SYSTEMD_MEMORY_SWAP_MAX = "2G";
|
|
12222
13333
|
|
|
13334
|
+
// src/bounded-build/index.ts
|
|
13335
|
+
init_meminfo();
|
|
13336
|
+
|
|
12223
13337
|
// src/bounded-build/node-options.ts
|
|
12224
13338
|
var MAX_OLD_SPACE_RE = /--max-old-space-size=(\d+)/;
|
|
12225
13339
|
function parsePositiveInt(value, fallback) {
|
|
@@ -12249,7 +13363,7 @@ function formatNodeOptionsFlag(mb = resolveNodeOldSpaceSizeMb()) {
|
|
|
12249
13363
|
}
|
|
12250
13364
|
|
|
12251
13365
|
// src/bounded-build/systemd-wrap.ts
|
|
12252
|
-
import { spawnSync as
|
|
13366
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
12253
13367
|
var systemdAvailableCache;
|
|
12254
13368
|
function isSystemdRunAvailable() {
|
|
12255
13369
|
if (process.env.KYNVER_BUILD_SKIP_SYSTEMD === "1" || process.env.KYNVER_BUILD_SKIP_SYSTEMD === "true") {
|
|
@@ -12260,7 +13374,7 @@ function isSystemdRunAvailable() {
|
|
|
12260
13374
|
systemdAvailableCache = false;
|
|
12261
13375
|
return false;
|
|
12262
13376
|
}
|
|
12263
|
-
const res =
|
|
13377
|
+
const res = spawnSync8("systemd-run", ["--version"], { encoding: "utf8", stdio: ["ignore", "ignore", "pipe"] });
|
|
12264
13378
|
systemdAvailableCache = res.status === 0;
|
|
12265
13379
|
return systemdAvailableCache;
|
|
12266
13380
|
}
|
|
@@ -12284,7 +13398,9 @@ function buildSystemdRunArgv(opts) {
|
|
|
12284
13398
|
}
|
|
12285
13399
|
|
|
12286
13400
|
// src/bounded-build/admission.ts
|
|
12287
|
-
|
|
13401
|
+
init_config();
|
|
13402
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
13403
|
+
init_meminfo();
|
|
12288
13404
|
function positiveInt4(value, fallback) {
|
|
12289
13405
|
const n = Number(value);
|
|
12290
13406
|
if (!Number.isFinite(n) || n <= 0) return fallback;
|
|
@@ -12320,7 +13436,7 @@ function assessBuildAdmission(opts = {}) {
|
|
|
12320
13436
|
}
|
|
12321
13437
|
function sleepMs2(ms) {
|
|
12322
13438
|
if (ms <= 0) return;
|
|
12323
|
-
|
|
13439
|
+
spawnSync9(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
|
|
12324
13440
|
stdio: "ignore"
|
|
12325
13441
|
});
|
|
12326
13442
|
}
|
|
@@ -12341,33 +13457,34 @@ function waitForBuildAdmission(timeoutMs, pollMs = 2e3, opts = {}) {
|
|
|
12341
13457
|
}
|
|
12342
13458
|
|
|
12343
13459
|
// src/bounded-build/exec.ts
|
|
12344
|
-
import { spawnSync as
|
|
13460
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
12345
13461
|
|
|
12346
13462
|
// src/heavy-verification/slot.ts
|
|
13463
|
+
init_util();
|
|
12347
13464
|
import {
|
|
12348
13465
|
closeSync as closeSync7,
|
|
12349
13466
|
existsSync as existsSync41,
|
|
12350
|
-
mkdirSync as
|
|
13467
|
+
mkdirSync as mkdirSync9,
|
|
12351
13468
|
openSync as openSync7,
|
|
12352
13469
|
readdirSync as readdirSync15,
|
|
12353
|
-
readFileSync as
|
|
13470
|
+
readFileSync as readFileSync15,
|
|
12354
13471
|
unlinkSync as unlinkSync4,
|
|
12355
|
-
writeFileSync as
|
|
13472
|
+
writeFileSync as writeFileSync6
|
|
12356
13473
|
} from "node:fs";
|
|
12357
|
-
import
|
|
13474
|
+
import path60 from "node:path";
|
|
12358
13475
|
|
|
12359
13476
|
// src/heavy-verification/paths.ts
|
|
12360
|
-
import { mkdirSync as
|
|
12361
|
-
import
|
|
13477
|
+
import { mkdirSync as mkdirSync8 } from "node:fs";
|
|
13478
|
+
import path59 from "node:path";
|
|
12362
13479
|
function resolveHeavyVerificationRoot() {
|
|
12363
|
-
return
|
|
13480
|
+
return path59.join(resolveKynverStateRoot(), "heavy-verification");
|
|
12364
13481
|
}
|
|
12365
13482
|
function heavyVerificationSlotsDir() {
|
|
12366
|
-
return
|
|
13483
|
+
return path59.join(resolveHeavyVerificationRoot(), "slots");
|
|
12367
13484
|
}
|
|
12368
13485
|
function ensureHeavyVerificationDirs() {
|
|
12369
13486
|
const dir = heavyVerificationSlotsDir();
|
|
12370
|
-
|
|
13487
|
+
mkdirSync8(dir, { recursive: true });
|
|
12371
13488
|
return dir;
|
|
12372
13489
|
}
|
|
12373
13490
|
|
|
@@ -12392,12 +13509,12 @@ function indexedSlotId(index) {
|
|
|
12392
13509
|
return `slot-${index}`;
|
|
12393
13510
|
}
|
|
12394
13511
|
function slotFilePath(slotId, slotsDir = heavyVerificationSlotsDir()) {
|
|
12395
|
-
return
|
|
13512
|
+
return path60.join(slotsDir, `${slotId}.json`);
|
|
12396
13513
|
}
|
|
12397
13514
|
function readSlotRecord(filePath) {
|
|
12398
13515
|
if (!existsSync41(filePath)) return null;
|
|
12399
13516
|
try {
|
|
12400
|
-
const parsed = JSON.parse(
|
|
13517
|
+
const parsed = JSON.parse(readFileSync15(filePath, "utf8"));
|
|
12401
13518
|
if (typeof parsed.slotId === "string" && typeof parsed.pid === "number" && typeof parsed.acquiredAt === "string" && typeof parsed.command === "string") {
|
|
12402
13519
|
return parsed;
|
|
12403
13520
|
}
|
|
@@ -12422,7 +13539,7 @@ function reclaimStaleSlot(filePath, staleMs) {
|
|
|
12422
13539
|
}
|
|
12423
13540
|
}
|
|
12424
13541
|
function ensureSlotsDir(slotsDir) {
|
|
12425
|
-
|
|
13542
|
+
mkdirSync9(slotsDir, { recursive: true });
|
|
12426
13543
|
return slotsDir;
|
|
12427
13544
|
}
|
|
12428
13545
|
function reclaimStaleHeavyVerificationSlots(opts = {}) {
|
|
@@ -12431,7 +13548,7 @@ function reclaimStaleHeavyVerificationSlots(opts = {}) {
|
|
|
12431
13548
|
let reclaimed = 0;
|
|
12432
13549
|
for (const name of readdirSync15(slotsDir)) {
|
|
12433
13550
|
if (!name.endsWith(".json")) continue;
|
|
12434
|
-
const filePath =
|
|
13551
|
+
const filePath = path60.join(slotsDir, name);
|
|
12435
13552
|
const before = existsSync41(filePath);
|
|
12436
13553
|
reclaimStaleSlot(filePath, staleMs);
|
|
12437
13554
|
if (before && !existsSync41(filePath)) reclaimed += 1;
|
|
@@ -12445,7 +13562,7 @@ function listActiveHeavyVerificationSlots(opts = {}) {
|
|
|
12445
13562
|
const active = [];
|
|
12446
13563
|
for (const name of readdirSync15(slotsDir)) {
|
|
12447
13564
|
if (!name.endsWith(".json")) continue;
|
|
12448
|
-
const record = readSlotRecord(
|
|
13565
|
+
const record = readSlotRecord(path60.join(slotsDir, name));
|
|
12449
13566
|
if (record && !slotIsStale(record, staleMs)) active.push(record);
|
|
12450
13567
|
}
|
|
12451
13568
|
return active;
|
|
@@ -12487,7 +13604,7 @@ function tryAcquireHeavyVerificationSlot(command, opts = {}) {
|
|
|
12487
13604
|
};
|
|
12488
13605
|
try {
|
|
12489
13606
|
const fd = openSync7(filePath, "wx");
|
|
12490
|
-
|
|
13607
|
+
writeFileSync6(fd, JSON.stringify(record, null, 2), "utf8");
|
|
12491
13608
|
closeSync7(fd);
|
|
12492
13609
|
const activeSlots2 = countActiveHeavyVerificationSlots({ slotsDir, staleMs });
|
|
12493
13610
|
return {
|
|
@@ -12547,10 +13664,10 @@ function assessHeavyVerificationGate(command, opts = {}) {
|
|
|
12547
13664
|
}
|
|
12548
13665
|
|
|
12549
13666
|
// src/heavy-verification/gate.ts
|
|
12550
|
-
import { spawnSync as
|
|
13667
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
12551
13668
|
function sleepMs3(ms) {
|
|
12552
13669
|
if (ms <= 0) return;
|
|
12553
|
-
|
|
13670
|
+
spawnSync10(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
|
|
12554
13671
|
stdio: "ignore"
|
|
12555
13672
|
});
|
|
12556
13673
|
}
|
|
@@ -12565,11 +13682,12 @@ function waitForHeavyVerificationSlot(command, timeoutMs, pollMs = 2e3, opts = {
|
|
|
12565
13682
|
}
|
|
12566
13683
|
|
|
12567
13684
|
// src/harness-worktree-build-guard.ts
|
|
12568
|
-
|
|
13685
|
+
init_paths();
|
|
13686
|
+
import path61 from "node:path";
|
|
12569
13687
|
function isPathUnderHarnessWorktree(cwd) {
|
|
12570
13688
|
const worktreesDir = harnessWorktreesDir(resolveHarnessRoot());
|
|
12571
|
-
const rel =
|
|
12572
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
13689
|
+
const rel = path61.relative(worktreesDir, path61.resolve(cwd));
|
|
13690
|
+
return rel.length > 0 && !rel.startsWith("..") && !path61.isAbsolute(rel);
|
|
12573
13691
|
}
|
|
12574
13692
|
function assessHarnessWorktreeBuildGuard(cwd) {
|
|
12575
13693
|
if (!isPathUnderHarnessWorktree(cwd)) return { ok: true };
|
|
@@ -12593,7 +13711,7 @@ function envArgv(env) {
|
|
|
12593
13711
|
return out;
|
|
12594
13712
|
}
|
|
12595
13713
|
function runSpawn(argv, opts) {
|
|
12596
|
-
const res =
|
|
13714
|
+
const res = spawnSync11(argv[0], argv.slice(1), {
|
|
12597
13715
|
cwd: opts.cwd,
|
|
12598
13716
|
env: opts.env,
|
|
12599
13717
|
encoding: "utf8",
|
|
@@ -12719,6 +13837,7 @@ function runHarnessVerifyCommands(cwd, commands = DEFAULT_HARNESS_VERIFY_COMMAND
|
|
|
12719
13837
|
}
|
|
12720
13838
|
|
|
12721
13839
|
// src/plan-progress.ts
|
|
13840
|
+
init_util();
|
|
12722
13841
|
function parseEvidenceArg(raw) {
|
|
12723
13842
|
const idx = raw.indexOf(":");
|
|
12724
13843
|
if (idx <= 0) throw new Error(`invalid --evidence ${raw} (expected type:value)`);
|
|
@@ -12781,7 +13900,7 @@ async function emitPlanProgress(args) {
|
|
|
12781
13900
|
}
|
|
12782
13901
|
function verifyPlanLocal(args) {
|
|
12783
13902
|
const worktree = required(args.worktree ? String(args.worktree) : void 0, "worktree");
|
|
12784
|
-
const cwd =
|
|
13903
|
+
const cwd = path62.resolve(worktree);
|
|
12785
13904
|
const summary = runHarnessVerifyCommands(cwd);
|
|
12786
13905
|
const emitJson = args.json === true || args.json === "true";
|
|
12787
13906
|
const payload = { passed: summary.passed, worktree: cwd, steps: summary.steps };
|
|
@@ -12830,9 +13949,10 @@ async function verifyPlan(args) {
|
|
|
12830
13949
|
}
|
|
12831
13950
|
|
|
12832
13951
|
// src/harness-verify-cli.ts
|
|
12833
|
-
import
|
|
13952
|
+
import path63 from "node:path";
|
|
13953
|
+
init_util();
|
|
12834
13954
|
function runHarnessVerifyCli(args) {
|
|
12835
|
-
const cwd =
|
|
13955
|
+
const cwd = path63.resolve(required(args.worktree ? String(args.worktree) : void 0, "worktree"));
|
|
12836
13956
|
const emitJson = args.json === true || args.json === "true" || args.emitJson === true || args.emitJson === "true";
|
|
12837
13957
|
const commands = [];
|
|
12838
13958
|
const rawCmd = args.command;
|
|
@@ -12877,7 +13997,9 @@ function runHarnessVerifyCli(args) {
|
|
|
12877
13997
|
}
|
|
12878
13998
|
|
|
12879
13999
|
// src/plan-persist-cli.ts
|
|
12880
|
-
|
|
14000
|
+
init_config();
|
|
14001
|
+
import { readFileSync as readFileSync16 } from "node:fs";
|
|
14002
|
+
init_util();
|
|
12881
14003
|
var OPERATIONS = ["create", "add_version", "update_metadata"];
|
|
12882
14004
|
var FAILURE_KINDS = [
|
|
12883
14005
|
"approval_guard",
|
|
@@ -12889,7 +14011,7 @@ var FAILURE_KINDS = [
|
|
|
12889
14011
|
function readBodyArg(args) {
|
|
12890
14012
|
const bodyFile = args.bodyFile ? String(args.bodyFile) : void 0;
|
|
12891
14013
|
if (bodyFile) {
|
|
12892
|
-
return { body:
|
|
14014
|
+
return { body: readFileSync16(bodyFile, "utf8"), bodyPathHint: bodyFile };
|
|
12893
14015
|
}
|
|
12894
14016
|
const inline = args.body ? String(args.body) : void 0;
|
|
12895
14017
|
if (inline) return { body: inline };
|
|
@@ -13040,9 +14162,14 @@ function formatMonitorTickNotice(tick) {
|
|
|
13040
14162
|
}
|
|
13041
14163
|
|
|
13042
14164
|
// src/monitor/monitor.service.ts
|
|
13043
|
-
import
|
|
14165
|
+
import path65 from "node:path";
|
|
14166
|
+
init_run_store();
|
|
14167
|
+
init_status();
|
|
14168
|
+
init_util();
|
|
13044
14169
|
|
|
13045
14170
|
// src/monitor/monitor.classify.ts
|
|
14171
|
+
init_status();
|
|
14172
|
+
init_util();
|
|
13046
14173
|
function classifyWorkerHealth(input) {
|
|
13047
14174
|
const { worker, status, taskLease } = input;
|
|
13048
14175
|
const leaseOwner = taskLease?.leaseOwner ?? null;
|
|
@@ -13092,19 +14219,21 @@ function classifyWorkerHealth(input) {
|
|
|
13092
14219
|
}
|
|
13093
14220
|
|
|
13094
14221
|
// src/monitor/monitor.store.ts
|
|
13095
|
-
|
|
13096
|
-
|
|
14222
|
+
init_paths();
|
|
14223
|
+
init_util();
|
|
14224
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync10, readdirSync as readdirSync16, unlinkSync as unlinkSync5 } from "node:fs";
|
|
14225
|
+
import path64 from "node:path";
|
|
13097
14226
|
function monitorsDir() {
|
|
13098
14227
|
const { harnessRoot } = getHarnessPaths();
|
|
13099
|
-
const dir =
|
|
13100
|
-
|
|
14228
|
+
const dir = path64.join(harnessRoot, "monitors");
|
|
14229
|
+
mkdirSync10(dir, { recursive: true });
|
|
13101
14230
|
return dir;
|
|
13102
14231
|
}
|
|
13103
14232
|
function monitorIdFor(runId, workerName) {
|
|
13104
14233
|
return workerName ? `${safeSlug(runId)}--${safeSlug(workerName)}` : safeSlug(runId);
|
|
13105
14234
|
}
|
|
13106
14235
|
function monitorPath(monitorId) {
|
|
13107
|
-
return
|
|
14236
|
+
return path64.join(monitorsDir(), `${monitorId}.json`);
|
|
13108
14237
|
}
|
|
13109
14238
|
function loadMonitorSession(monitorId) {
|
|
13110
14239
|
return readJson(monitorPath(monitorId), void 0);
|
|
@@ -13125,7 +14254,7 @@ function listMonitorSessions() {
|
|
|
13125
14254
|
for (const name of readdirSync16(dir)) {
|
|
13126
14255
|
if (!name.endsWith(".json")) continue;
|
|
13127
14256
|
const session = readJson(
|
|
13128
|
-
|
|
14257
|
+
path64.join(dir, name),
|
|
13129
14258
|
void 0
|
|
13130
14259
|
);
|
|
13131
14260
|
if (!session?.monitorId) continue;
|
|
@@ -13145,6 +14274,7 @@ function listMonitorSessions() {
|
|
|
13145
14274
|
}
|
|
13146
14275
|
|
|
13147
14276
|
// src/monitor/monitor.terminal.ts
|
|
14277
|
+
init_status();
|
|
13148
14278
|
function assessAutoCompleteEligibility(input) {
|
|
13149
14279
|
const { worker, status } = input;
|
|
13150
14280
|
const blockers = [];
|
|
@@ -13188,6 +14318,7 @@ function assessAutoCompleteEligibility(input) {
|
|
|
13188
14318
|
}
|
|
13189
14319
|
|
|
13190
14320
|
// src/monitor/monitor.task-lease.ts
|
|
14321
|
+
init_config();
|
|
13191
14322
|
async function fetchTaskLeasesForWorkers(input) {
|
|
13192
14323
|
const out = /* @__PURE__ */ new Map();
|
|
13193
14324
|
const agentOsId = input.agentOsId?.trim();
|
|
@@ -13216,7 +14347,7 @@ async function fetchTaskLeasesForWorkers(input) {
|
|
|
13216
14347
|
// src/monitor/monitor.service.ts
|
|
13217
14348
|
function workerRecord2(runId, name) {
|
|
13218
14349
|
return readJson(
|
|
13219
|
-
|
|
14350
|
+
path65.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
|
|
13220
14351
|
void 0
|
|
13221
14352
|
);
|
|
13222
14353
|
}
|
|
@@ -13386,6 +14517,7 @@ async function monitorAutoCompleteCli(args) {
|
|
|
13386
14517
|
}
|
|
13387
14518
|
|
|
13388
14519
|
// src/monitor/monitor-loop.ts
|
|
14520
|
+
init_util();
|
|
13389
14521
|
var DEFAULT_POLL_MS2 = 5e3;
|
|
13390
14522
|
var DEFAULT_MAX_TOTAL_MS2 = 6 * 60 * 60 * 1e3;
|
|
13391
14523
|
async function runMonitorLoop(args) {
|
|
@@ -13421,19 +14553,21 @@ async function runMonitorLoop(args) {
|
|
|
13421
14553
|
}
|
|
13422
14554
|
|
|
13423
14555
|
// src/monitor/monitor-spawn.ts
|
|
13424
|
-
|
|
14556
|
+
init_util();
|
|
14557
|
+
init_paths();
|
|
14558
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
13425
14559
|
import { closeSync as closeSync8, existsSync as existsSync43, openSync as openSync8 } from "node:fs";
|
|
13426
|
-
import
|
|
14560
|
+
import path66 from "node:path";
|
|
13427
14561
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
13428
14562
|
function resolveDefaultCliPath2() {
|
|
13429
|
-
return
|
|
14563
|
+
return path66.join(fileURLToPath3(new URL(".", import.meta.url)), "cli.js");
|
|
13430
14564
|
}
|
|
13431
14565
|
function spawnMonitorSidecar(opts) {
|
|
13432
14566
|
const cliPath = opts.cliPath ?? resolveDefaultCliPath2();
|
|
13433
14567
|
if (!existsSync43(cliPath)) return void 0;
|
|
13434
14568
|
const monitorId = monitorIdFor(opts.runId, opts.workerName);
|
|
13435
14569
|
const { harnessRoot } = getHarnessPaths();
|
|
13436
|
-
const logPath =
|
|
14570
|
+
const logPath = path66.join(harnessRoot, "monitors", `${monitorId}.log`);
|
|
13437
14571
|
let logFd;
|
|
13438
14572
|
try {
|
|
13439
14573
|
logFd = openSync8(logPath, "a");
|
|
@@ -13467,7 +14601,7 @@ function spawnMonitorSidecar(opts) {
|
|
|
13467
14601
|
logFd ?? "ignore"
|
|
13468
14602
|
];
|
|
13469
14603
|
try {
|
|
13470
|
-
const child =
|
|
14604
|
+
const child = spawn7(
|
|
13471
14605
|
nodeExecutable,
|
|
13472
14606
|
args,
|
|
13473
14607
|
hiddenSpawnOptions({
|
|
@@ -13502,6 +14636,7 @@ function spawnMonitorSidecar(opts) {
|
|
|
13502
14636
|
}
|
|
13503
14637
|
|
|
13504
14638
|
// src/monitor/monitor-cli.ts
|
|
14639
|
+
init_util();
|
|
13505
14640
|
async function startMonitorCli(args) {
|
|
13506
14641
|
const runId = String(args.run || "");
|
|
13507
14642
|
required(runId, "--run");
|
|
@@ -13553,7 +14688,7 @@ async function monitorTickCli(args) {
|
|
|
13553
14688
|
}
|
|
13554
14689
|
|
|
13555
14690
|
// src/package-version.ts
|
|
13556
|
-
import { existsSync as existsSync44, readFileSync as
|
|
14691
|
+
import { existsSync as existsSync44, readFileSync as readFileSync17 } from "node:fs";
|
|
13557
14692
|
import { dirname, join } from "node:path";
|
|
13558
14693
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
13559
14694
|
function resolvePackageRoot(moduleUrl) {
|
|
@@ -13568,7 +14703,7 @@ function resolvePackageRoot(moduleUrl) {
|
|
|
13568
14703
|
}
|
|
13569
14704
|
function readOwnPackageVersion(moduleUrl = import.meta.url) {
|
|
13570
14705
|
const pkgPath = join(resolvePackageRoot(moduleUrl), "package.json");
|
|
13571
|
-
const pkg = JSON.parse(
|
|
14706
|
+
const pkg = JSON.parse(readFileSync17(pkgPath, "utf8"));
|
|
13572
14707
|
if (typeof pkg.version !== "string" || !pkg.version.trim()) {
|
|
13573
14708
|
throw new Error(`Missing package.json version at ${pkgPath}`);
|
|
13574
14709
|
}
|
|
@@ -13635,6 +14770,7 @@ function shouldEnforceMemoryCostPackageGuardCli(scope, action) {
|
|
|
13635
14770
|
}
|
|
13636
14771
|
|
|
13637
14772
|
// src/run-resolve.ts
|
|
14773
|
+
init_util();
|
|
13638
14774
|
function resolveHarnessRunByName(runName) {
|
|
13639
14775
|
const name = runName.trim();
|
|
13640
14776
|
if (!name) return null;
|
|
@@ -13659,7 +14795,11 @@ function resolveHarnessRunCli(args) {
|
|
|
13659
14795
|
}
|
|
13660
14796
|
|
|
13661
14797
|
// src/post-restart-unblock.ts
|
|
13662
|
-
|
|
14798
|
+
init_run_store();
|
|
14799
|
+
init_status();
|
|
14800
|
+
init_util();
|
|
14801
|
+
init_config();
|
|
14802
|
+
import path67 from "node:path";
|
|
13663
14803
|
function skip(runId, worker, taskId, agentOsId, leaseOwner, reason) {
|
|
13664
14804
|
return { runId, worker, taskId, agentOsId, leaseOwner, action: "skipped", reason };
|
|
13665
14805
|
}
|
|
@@ -13672,7 +14812,7 @@ async function postRestartUnblock(args) {
|
|
|
13672
14812
|
const errors = [];
|
|
13673
14813
|
for (const run of listRunRecords()) {
|
|
13674
14814
|
for (const name of Object.keys(run.workers ?? {})) {
|
|
13675
|
-
const workerPath =
|
|
14815
|
+
const workerPath = path67.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json");
|
|
13676
14816
|
const worker = readJson(workerPath, void 0);
|
|
13677
14817
|
if (!worker) {
|
|
13678
14818
|
skipped.push(skip(run.id, name, "", "", "", "worker.json missing"));
|
|
@@ -13784,9 +14924,11 @@ async function postRestartUnblockCli(args) {
|
|
|
13784
14924
|
}
|
|
13785
14925
|
|
|
13786
14926
|
// src/default-repo-cli.ts
|
|
13787
|
-
|
|
13788
|
-
|
|
13789
|
-
|
|
14927
|
+
init_path_values();
|
|
14928
|
+
init_config();
|
|
14929
|
+
import path68 from "node:path";
|
|
14930
|
+
import { homedir as homedir15 } from "node:os";
|
|
14931
|
+
var CONFIG_FILE2 = path68.join(homedir15(), ".kynver", "config.json");
|
|
13790
14932
|
function ensureDefaultRepo(opts) {
|
|
13791
14933
|
const existing = loadUserConfig();
|
|
13792
14934
|
const resolved = resolveDefaultRepo({ ...opts, config: existing });
|
|
@@ -13867,16 +15009,19 @@ function summarizeResolvedDefaultRepo(resolved) {
|
|
|
13867
15009
|
}
|
|
13868
15010
|
|
|
13869
15011
|
// src/doctor/runtime-takeover.ts
|
|
13870
|
-
import
|
|
15012
|
+
import path70 from "node:path";
|
|
15013
|
+
init_path_values();
|
|
13871
15014
|
|
|
13872
15015
|
// src/doctor/runtime-takeover.probes.ts
|
|
13873
|
-
|
|
13874
|
-
import {
|
|
13875
|
-
import
|
|
13876
|
-
import
|
|
15016
|
+
init_config();
|
|
15017
|
+
import { accessSync, constants, existsSync as existsSync45, readFileSync as readFileSync18 } from "node:fs";
|
|
15018
|
+
import { homedir as homedir16 } from "node:os";
|
|
15019
|
+
import path69 from "node:path";
|
|
15020
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
15021
|
+
init_paths();
|
|
13877
15022
|
function captureCommand(bin, args) {
|
|
13878
15023
|
try {
|
|
13879
|
-
const res =
|
|
15024
|
+
const res = spawnSync12(bin, args, { encoding: "utf8" });
|
|
13880
15025
|
const stdout = (res.stdout || "").trim();
|
|
13881
15026
|
const stderr = (res.stderr || "").trim();
|
|
13882
15027
|
const ok = res.status === 0;
|
|
@@ -13914,15 +15059,15 @@ var defaultRuntimeTakeoverProbes = {
|
|
|
13914
15059
|
commandOnPath: (bin) => captureCommand(process.platform === "win32" ? "where" : "which", [bin]),
|
|
13915
15060
|
kynverVersion: (bin) => captureCommand(bin, ["--version"]),
|
|
13916
15061
|
loadConfig: () => loadUserConfig(),
|
|
13917
|
-
configFilePath: () =>
|
|
13918
|
-
credentialsFilePath: () =>
|
|
15062
|
+
configFilePath: () => path69.join(homedir16(), ".kynver", "config.json"),
|
|
15063
|
+
credentialsFilePath: () => path69.join(homedir16(), ".kynver", "credentials"),
|
|
13919
15064
|
readCredentials: () => {
|
|
13920
|
-
const credPath =
|
|
15065
|
+
const credPath = path69.join(homedir16(), ".kynver", "credentials");
|
|
13921
15066
|
if (!existsSync45(credPath)) {
|
|
13922
15067
|
return { hasApiKey: false };
|
|
13923
15068
|
}
|
|
13924
15069
|
try {
|
|
13925
|
-
const parsed = JSON.parse(
|
|
15070
|
+
const parsed = JSON.parse(readFileSync18(credPath, "utf8"));
|
|
13926
15071
|
return {
|
|
13927
15072
|
hasApiKey: Boolean(parsed.apiKey?.trim()),
|
|
13928
15073
|
runnerTokenPrefix: tokenPrefix(parsed.runnerToken),
|
|
@@ -13952,7 +15097,7 @@ var defaultRuntimeTakeoverProbes = {
|
|
|
13952
15097
|
})()
|
|
13953
15098
|
}),
|
|
13954
15099
|
harnessRoot: () => resolveHarnessRoot(),
|
|
13955
|
-
legacyOpenclawHarnessRoot: () =>
|
|
15100
|
+
legacyOpenclawHarnessRoot: () => path69.join(homedir16(), ".openclaw", "harness"),
|
|
13956
15101
|
pathExists: (target) => existsSync45(target),
|
|
13957
15102
|
pathWritable: (target) => isWritable(target)
|
|
13958
15103
|
};
|
|
@@ -14359,8 +15504,8 @@ function assessVercelDeployEvidence(probes) {
|
|
|
14359
15504
|
}
|
|
14360
15505
|
function assessHarnessDirs(probes) {
|
|
14361
15506
|
const harnessRoot = probes.harnessRoot();
|
|
14362
|
-
const runsDir =
|
|
14363
|
-
const worktreesDir =
|
|
15507
|
+
const runsDir = path70.join(harnessRoot, "runs");
|
|
15508
|
+
const worktreesDir = path70.join(harnessRoot, "worktrees");
|
|
14364
15509
|
const displayHarnessRoot = redactHomePath(harnessRoot);
|
|
14365
15510
|
const displayRunsDir = redactHomePath(runsDir);
|
|
14366
15511
|
const displayWorktreesDir = redactHomePath(worktreesDir);
|
|
@@ -14536,6 +15681,7 @@ function runRuntimeTakeoverDoctorCli(args = {}) {
|
|
|
14536
15681
|
}
|
|
14537
15682
|
|
|
14538
15683
|
// src/command-center-contract-cli.ts
|
|
15684
|
+
init_config();
|
|
14539
15685
|
async function runCommandCenterContractCli(args) {
|
|
14540
15686
|
const config = loadUserConfig();
|
|
14541
15687
|
const agentOsId = (args.agentOsId ? String(args.agentOsId) : config.agentOsId) || "";
|
|
@@ -14566,6 +15712,9 @@ async function runCommandCenterContractCli(args) {
|
|
|
14566
15712
|
console.log(JSON.stringify(res.response, null, 2));
|
|
14567
15713
|
}
|
|
14568
15714
|
|
|
15715
|
+
// src/scheduler-cutover-cli.ts
|
|
15716
|
+
init_path_values();
|
|
15717
|
+
|
|
14569
15718
|
// src/scheduler-cutover.ts
|
|
14570
15719
|
var DEPLOYMENT_SCHEDULER_CUTOVER_STEPS = [
|
|
14571
15720
|
"Vercel/hosted: set KYNVER_SCHEDULER_PROVIDER=qstash",
|
|
@@ -14624,9 +15773,10 @@ function applySchedulerCutoverAttestation(config) {
|
|
|
14624
15773
|
}
|
|
14625
15774
|
|
|
14626
15775
|
// src/scheduler-cutover-cli.ts
|
|
14627
|
-
|
|
14628
|
-
import
|
|
14629
|
-
|
|
15776
|
+
init_config();
|
|
15777
|
+
import path71 from "node:path";
|
|
15778
|
+
import { homedir as homedir17 } from "node:os";
|
|
15779
|
+
var CONFIG_FILE3 = path71.join(homedir17(), ".kynver", "config.json");
|
|
14630
15780
|
function runSchedulerCutoverCheckCli(json = false) {
|
|
14631
15781
|
const config = loadUserConfig();
|
|
14632
15782
|
const report = assessSchedulerCutover(config);
|
|
@@ -14764,7 +15914,12 @@ async function runCronTickCli(args) {
|
|
|
14764
15914
|
}
|
|
14765
15915
|
|
|
14766
15916
|
// src/lane/landing-maintainer-tick.ts
|
|
14767
|
-
|
|
15917
|
+
init_config();
|
|
15918
|
+
import os11 from "node:os";
|
|
15919
|
+
init_config();
|
|
15920
|
+
init_box_identity();
|
|
15921
|
+
init_resource_gate();
|
|
15922
|
+
init_util();
|
|
14768
15923
|
|
|
14769
15924
|
// src/lane/lane-spec.ts
|
|
14770
15925
|
var LANDING_MAINTAINER_LANE_SPEC = {
|
|
@@ -14776,10 +15931,10 @@ var LANDING_MAINTAINER_LANE_SPEC = {
|
|
|
14776
15931
|
};
|
|
14777
15932
|
|
|
14778
15933
|
// src/lane/landing-maintainer-local.ts
|
|
14779
|
-
import { spawnSync as
|
|
14780
|
-
import
|
|
15934
|
+
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
15935
|
+
import path72 from "node:path";
|
|
14781
15936
|
function runLandingWrapper(prNumber, repoRoot, execute) {
|
|
14782
|
-
const script =
|
|
15937
|
+
const script = path72.join(repoRoot, LANDING_MAINTAINER_LANE_SPEC.landScript);
|
|
14783
15938
|
const args = [script, String(prNumber), ...LANDING_MAINTAINER_LANE_SPEC.landScriptArgs];
|
|
14784
15939
|
if (!execute) {
|
|
14785
15940
|
return {
|
|
@@ -14790,7 +15945,7 @@ function runLandingWrapper(prNumber, repoRoot, execute) {
|
|
|
14790
15945
|
stderr: ""
|
|
14791
15946
|
};
|
|
14792
15947
|
}
|
|
14793
|
-
const result =
|
|
15948
|
+
const result = spawnSync13("node", args, {
|
|
14794
15949
|
cwd: repoRoot,
|
|
14795
15950
|
encoding: "utf8",
|
|
14796
15951
|
timeout: 10 * 60 * 1e3
|
|
@@ -14805,7 +15960,7 @@ function runLandingWrapper(prNumber, repoRoot, execute) {
|
|
|
14805
15960
|
}
|
|
14806
15961
|
function resolveLandingMaintainerRepoRoot(args) {
|
|
14807
15962
|
const explicit = args.repoPath ? String(args.repoPath).trim() : "";
|
|
14808
|
-
if (explicit) return
|
|
15963
|
+
if (explicit) return path72.resolve(explicit);
|
|
14809
15964
|
const resolved = resolveDefaultRepo();
|
|
14810
15965
|
return resolved?.repo ?? process.cwd();
|
|
14811
15966
|
}
|
|
@@ -14824,7 +15979,7 @@ async function runLandingMaintainerLaneTick(args) {
|
|
|
14824
15979
|
...buildBoxResourceSnapshotFromGate(resourceGate, {
|
|
14825
15980
|
harnessRunId: runId,
|
|
14826
15981
|
boxKind: resolveBoxKindFromConfig(loadUserConfig()),
|
|
14827
|
-
hostLabel:
|
|
15982
|
+
hostLabel: os11.hostname()
|
|
14828
15983
|
}),
|
|
14829
15984
|
providerHealthy: resourceGate.ok,
|
|
14830
15985
|
authorizedForRepair: resourceGate.ok,
|
|
@@ -14928,10 +16083,11 @@ function usage(code = 0) {
|
|
|
14928
16083
|
out(
|
|
14929
16084
|
[
|
|
14930
16085
|
"Usage:",
|
|
14931
|
-
" kynver login --api-key KEY",
|
|
16086
|
+
" kynver login [--api-key KEY] [--api-base-url URL] (omit --api-key to authorize in the browser)",
|
|
16087
|
+
" kynver bootstrap [--api-base-url URL] [--api-key KEY] [--repo PATH] (login + setup + runner credential in one shot)",
|
|
14932
16088
|
" kynver runner credential [--agent-os-id ID] [--base-url URL]",
|
|
14933
16089
|
" kynver setup [--api-base-url URL] [--agent-os-id ID] [--agent-os-slug SLUG] [--box-kind forge|ghost] [--repo PATH] [--discover-repo] [--max-workers N] [--provider claude|cursor]",
|
|
14934
|
-
" kynver daemon --run RUN_ID --agent-os-id AOS_ID [--execute] [--interval-ms MS]",
|
|
16090
|
+
" kynver daemon --run RUN_ID --agent-os-id AOS_ID [--execute] [--interval-ms MS] [--stall-ms MS] [--no-supervise]",
|
|
14935
16091
|
" kynver status --run RUN_ID [--blocked] [--running] [--task TASK_ID] [--worker WORKER] [--full] # top-level compact run status",
|
|
14936
16092
|
" kynver run create [--repo /path/repo] [--name name] [--base origin/main]",
|
|
14937
16093
|
" kynver run list",
|
|
@@ -14992,8 +16148,8 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
14992
16148
|
if (action && isHelpFlag(action) || rest.some(isHelpFlag)) return usage(0);
|
|
14993
16149
|
const args = parseArgs(rest);
|
|
14994
16150
|
const { runsDir, worktreesDir } = getPaths();
|
|
14995
|
-
|
|
14996
|
-
|
|
16151
|
+
mkdirSync11(runsDir, { recursive: true });
|
|
16152
|
+
mkdirSync11(worktreesDir, { recursive: true });
|
|
14997
16153
|
if (scope === "daemon") {
|
|
14998
16154
|
assertNativeDaemonAllowed();
|
|
14999
16155
|
}
|
|
@@ -15013,10 +16169,16 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
15013
16169
|
});
|
|
15014
16170
|
}
|
|
15015
16171
|
if (scope === "login") return void await runLogin(args);
|
|
16172
|
+
if (scope === "bootstrap") return void await runBootstrap(args);
|
|
15016
16173
|
if (scope === "status") return runStatus(args);
|
|
15017
16174
|
if (scope === "runner" && action === "credential") return void await mintRunnerCredential(args);
|
|
15018
16175
|
if (scope === "setup") return void await runSetup(args);
|
|
15019
|
-
if (scope === "daemon")
|
|
16176
|
+
if (scope === "daemon") {
|
|
16177
|
+
if (shouldRunDaemonKeeper(args)) {
|
|
16178
|
+
return void await runDaemonKeeper(args);
|
|
16179
|
+
}
|
|
16180
|
+
return void await runDaemon(args);
|
|
16181
|
+
}
|
|
15020
16182
|
if (scope === "plan" && action === "progress") return void await emitPlanProgress(args);
|
|
15021
16183
|
if (scope === "plan" && action === "verify") return void await verifyPlan(args);
|
|
15022
16184
|
if (scope === "harness" && action === "verify") return runHarnessVerifyCli(args);
|