@kynver-app/runtime 0.1.112 → 0.1.116
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap.d.ts +1 -0
- package/dist/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/index.js
CHANGED
|
@@ -1,51 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
for (
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (parent === dir) break;
|
|
11
|
-
dir = parent;
|
|
12
|
-
}
|
|
13
|
-
throw new Error(`package.json not found above ${dirname(fileURLToPath(moduleUrl))}`);
|
|
14
|
-
}
|
|
15
|
-
function readOwnPackageVersion(moduleUrl = import.meta.url) {
|
|
16
|
-
const pkgPath = join(resolvePackageRoot(moduleUrl), "package.json");
|
|
17
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
18
|
-
if (typeof pkg.version !== "string" || !pkg.version.trim()) {
|
|
19
|
-
throw new Error(`Missing package.json version at ${pkgPath}`);
|
|
20
|
-
}
|
|
21
|
-
return pkg.version;
|
|
22
|
-
}
|
|
23
|
-
var PACKAGE_VERSION = readOwnPackageVersion();
|
|
24
|
-
function wantsCliVersion(argv) {
|
|
25
|
-
return argv.some((arg) => arg === "--version" || arg === "-v");
|
|
26
|
-
}
|
|
27
|
-
function printCliVersionAndExit(version, binName) {
|
|
28
|
-
console.log(binName ? `${binName} ${version}` : version);
|
|
29
|
-
process.exit(0);
|
|
30
|
-
}
|
|
31
|
-
function handleCliVersionFlag(argv, moduleUrl = import.meta.url, binName) {
|
|
32
|
-
if (!wantsCliVersion(argv)) return false;
|
|
33
|
-
printCliVersionAndExit(readOwnPackageVersion(moduleUrl), binName);
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// src/memory-cost-package-version-guard.ts
|
|
38
|
-
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
39
|
-
import path4 from "node:path";
|
|
40
|
-
|
|
41
|
-
// src/default-repo-discovery.ts
|
|
42
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|
|
43
|
-
import { homedir as homedir2 } from "node:os";
|
|
44
|
-
import path3 from "node:path";
|
|
45
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
46
|
-
|
|
47
|
-
// src/git.ts
|
|
48
|
-
import { spawnSync } from "node:child_process";
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
49
10
|
|
|
50
11
|
// src/util.ts
|
|
51
12
|
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -154,42 +115,13 @@ function latestIso(values) {
|
|
|
154
115
|
function secsAgo(ms) {
|
|
155
116
|
return Math.max(0, Math.round((Date.now() - ms) / 1e3));
|
|
156
117
|
}
|
|
118
|
+
var init_util = __esm({
|
|
119
|
+
"src/util.ts"() {
|
|
120
|
+
"use strict";
|
|
121
|
+
}
|
|
122
|
+
});
|
|
157
123
|
|
|
158
124
|
// src/worker-env.ts
|
|
159
|
-
var FORBIDDEN_WORKER_ENV_KEYS = [
|
|
160
|
-
"ANTHROPIC_API_KEY",
|
|
161
|
-
"ANALYST_API_KEY",
|
|
162
|
-
"RECRUITER_API_KEY",
|
|
163
|
-
"AUTH_SECRET",
|
|
164
|
-
"NEXTAUTH_SECRET",
|
|
165
|
-
"DATABASE_URL",
|
|
166
|
-
"PRODUCTION_DATABASE_URL",
|
|
167
|
-
"KYNVER_PRODUCTION_DATABASE_URL",
|
|
168
|
-
"REDIS_URL",
|
|
169
|
-
"GOOGLE_CLIENT_SECRET",
|
|
170
|
-
"GITHUB_CLIENT_SECRET",
|
|
171
|
-
"KYNVER_API_KEY",
|
|
172
|
-
"KYNVER_SERVICE_SECRET",
|
|
173
|
-
"KYNVER_RUNTIME_SECRET",
|
|
174
|
-
"KYNVER_CRON_SECRET",
|
|
175
|
-
"OPENCLAW_CRON_SECRET",
|
|
176
|
-
"QSTASH_TOKEN",
|
|
177
|
-
"QSTASH_CURRENT_SIGNING_KEY",
|
|
178
|
-
"QSTASH_NEXT_SIGNING_KEY",
|
|
179
|
-
"TOOL_SECRETS_KEK",
|
|
180
|
-
"TOOL_EXECUTOR_DISPATCH_SECRET",
|
|
181
|
-
"CLOUDFLARE_API_TOKEN",
|
|
182
|
-
"STRIPE_SECRET_KEY",
|
|
183
|
-
"STRIPE_WEBHOOK_SECRET",
|
|
184
|
-
"STRIPE_IDENTITY_WEBHOOK_SECRET",
|
|
185
|
-
"VOYAGE_API_KEY",
|
|
186
|
-
"PERPLEXITY_API_KEY",
|
|
187
|
-
"FRED_API_KEY",
|
|
188
|
-
"FMP_API_KEY",
|
|
189
|
-
"CURSOR_API_KEY"
|
|
190
|
-
];
|
|
191
|
-
var FORBIDDEN_KEY_SET = new Set(FORBIDDEN_WORKER_ENV_KEYS);
|
|
192
|
-
var FORBIDDEN_SUFFIXES = ["_SECRET", "_API_KEY"];
|
|
193
125
|
function isForbiddenWorkerEnvKey(key) {
|
|
194
126
|
if (FORBIDDEN_KEY_SET.has(key)) return true;
|
|
195
127
|
return FORBIDDEN_SUFFIXES.some((suffix) => key.endsWith(suffix));
|
|
@@ -211,8 +143,49 @@ function auditWorkerEnv(env) {
|
|
|
211
143
|
function scrubClaudeEnv(env) {
|
|
212
144
|
return scrubWorkerEnv(env);
|
|
213
145
|
}
|
|
146
|
+
var FORBIDDEN_WORKER_ENV_KEYS, FORBIDDEN_KEY_SET, FORBIDDEN_SUFFIXES;
|
|
147
|
+
var init_worker_env = __esm({
|
|
148
|
+
"src/worker-env.ts"() {
|
|
149
|
+
"use strict";
|
|
150
|
+
FORBIDDEN_WORKER_ENV_KEYS = [
|
|
151
|
+
"ANTHROPIC_API_KEY",
|
|
152
|
+
"ANALYST_API_KEY",
|
|
153
|
+
"RECRUITER_API_KEY",
|
|
154
|
+
"AUTH_SECRET",
|
|
155
|
+
"NEXTAUTH_SECRET",
|
|
156
|
+
"DATABASE_URL",
|
|
157
|
+
"PRODUCTION_DATABASE_URL",
|
|
158
|
+
"KYNVER_PRODUCTION_DATABASE_URL",
|
|
159
|
+
"REDIS_URL",
|
|
160
|
+
"GOOGLE_CLIENT_SECRET",
|
|
161
|
+
"GITHUB_CLIENT_SECRET",
|
|
162
|
+
"KYNVER_API_KEY",
|
|
163
|
+
"KYNVER_SERVICE_SECRET",
|
|
164
|
+
"KYNVER_RUNTIME_SECRET",
|
|
165
|
+
"KYNVER_CRON_SECRET",
|
|
166
|
+
"OPENCLAW_CRON_SECRET",
|
|
167
|
+
"QSTASH_TOKEN",
|
|
168
|
+
"QSTASH_CURRENT_SIGNING_KEY",
|
|
169
|
+
"QSTASH_NEXT_SIGNING_KEY",
|
|
170
|
+
"TOOL_SECRETS_KEK",
|
|
171
|
+
"TOOL_EXECUTOR_DISPATCH_SECRET",
|
|
172
|
+
"CLOUDFLARE_API_TOKEN",
|
|
173
|
+
"STRIPE_SECRET_KEY",
|
|
174
|
+
"STRIPE_WEBHOOK_SECRET",
|
|
175
|
+
"STRIPE_IDENTITY_WEBHOOK_SECRET",
|
|
176
|
+
"VOYAGE_API_KEY",
|
|
177
|
+
"PERPLEXITY_API_KEY",
|
|
178
|
+
"FRED_API_KEY",
|
|
179
|
+
"FMP_API_KEY",
|
|
180
|
+
"CURSOR_API_KEY"
|
|
181
|
+
];
|
|
182
|
+
FORBIDDEN_KEY_SET = new Set(FORBIDDEN_WORKER_ENV_KEYS);
|
|
183
|
+
FORBIDDEN_SUFFIXES = ["_SECRET", "_API_KEY"];
|
|
184
|
+
}
|
|
185
|
+
});
|
|
214
186
|
|
|
215
187
|
// src/git.ts
|
|
188
|
+
import { spawnSync } from "node:child_process";
|
|
216
189
|
function git(cwd, args, options = {}) {
|
|
217
190
|
const res = spawnSync(
|
|
218
191
|
"git",
|
|
@@ -336,6 +309,13 @@ function unknownAncestry(base, error, head = null) {
|
|
|
336
309
|
error
|
|
337
310
|
};
|
|
338
311
|
}
|
|
312
|
+
var init_git = __esm({
|
|
313
|
+
"src/git.ts"() {
|
|
314
|
+
"use strict";
|
|
315
|
+
init_util();
|
|
316
|
+
init_worker_env();
|
|
317
|
+
}
|
|
318
|
+
});
|
|
339
319
|
|
|
340
320
|
// src/path-values.ts
|
|
341
321
|
import { homedir } from "node:os";
|
|
@@ -365,15 +345,17 @@ function redactHomePath(value) {
|
|
|
365
345
|
function displayUserPath(value) {
|
|
366
346
|
return redactHomePath(value);
|
|
367
347
|
}
|
|
348
|
+
var init_path_values = __esm({
|
|
349
|
+
"src/path-values.ts"() {
|
|
350
|
+
"use strict";
|
|
351
|
+
}
|
|
352
|
+
});
|
|
368
353
|
|
|
369
354
|
// src/default-repo-discovery.ts
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
"code/Kynver",
|
|
375
|
-
"projects/Kynver"
|
|
376
|
-
];
|
|
355
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|
|
356
|
+
import { homedir as homedir2 } from "node:os";
|
|
357
|
+
import path3 from "node:path";
|
|
358
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
377
359
|
function readPackageName(repoRoot) {
|
|
378
360
|
const pkgPath = path3.join(repoRoot, "package.json");
|
|
379
361
|
if (!existsSync3(pkgPath)) return null;
|
|
@@ -438,425 +420,135 @@ function discoverDefaultRepoCandidates(opts) {
|
|
|
438
420
|
function discoverDefaultRepo(opts) {
|
|
439
421
|
return discoverDefaultRepoCandidates(opts)[0] ?? null;
|
|
440
422
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
"@kynver-app/mcp-agent-os": "AgentOS MCP server"
|
|
455
|
-
};
|
|
456
|
-
var REPO_PACKAGE_JSON_RELATIVE = {
|
|
457
|
-
"@kynver-app/runtime": "packages/kynver-runtime/package.json",
|
|
458
|
-
"@kynver-app/openclaw-agent-os": "packages/kynver-openclaw-agent-os/package.json",
|
|
459
|
-
"@kynver-app/mcp-agent-os": "packages/kynver-mcp-agent-os/package.json"
|
|
460
|
-
};
|
|
461
|
-
function parseSemverParts(version) {
|
|
462
|
-
const core = version.trim().split("-")[0]?.split("+")[0];
|
|
463
|
-
if (!core) return null;
|
|
464
|
-
const parts = core.split(".");
|
|
465
|
-
if (parts.length < 1 || parts.length > 3) return null;
|
|
466
|
-
const nums = parts.map((p) => Number.parseInt(p, 10));
|
|
467
|
-
if (nums.some((n) => !Number.isFinite(n) || n < 0)) return null;
|
|
468
|
-
while (nums.length < 3) nums.push(0);
|
|
469
|
-
return [nums[0], nums[1], nums[2]];
|
|
470
|
-
}
|
|
471
|
-
function compareSemver(a, b) {
|
|
472
|
-
const pa = parseSemverParts(a);
|
|
473
|
-
const pb = parseSemverParts(b);
|
|
474
|
-
if (!pa || !pb) return 0;
|
|
475
|
-
for (let i = 0; i < 3; i += 1) {
|
|
476
|
-
if (pa[i] > pb[i]) return 1;
|
|
477
|
-
if (pa[i] < pb[i]) return -1;
|
|
423
|
+
var WELL_KNOWN_REPO_DIRS;
|
|
424
|
+
var init_default_repo_discovery = __esm({
|
|
425
|
+
"src/default-repo-discovery.ts"() {
|
|
426
|
+
"use strict";
|
|
427
|
+
init_git();
|
|
428
|
+
init_path_values();
|
|
429
|
+
WELL_KNOWN_REPO_DIRS = [
|
|
430
|
+
"Kynver",
|
|
431
|
+
"repos/Kynver",
|
|
432
|
+
"repos/kynver-source-main",
|
|
433
|
+
"code/Kynver",
|
|
434
|
+
"projects/Kynver"
|
|
435
|
+
];
|
|
478
436
|
}
|
|
479
|
-
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// src/box-identity.ts
|
|
440
|
+
function normalizeWorkerPoolBoxKind(raw) {
|
|
441
|
+
const kind = (raw ?? "").trim().toLowerCase();
|
|
442
|
+
if (kind === "ghost" || kind === "forge") return kind;
|
|
443
|
+
if (kind.includes("forge")) return "forge";
|
|
444
|
+
if (kind.includes("ghost") || kind.includes("openclaw")) return "ghost";
|
|
445
|
+
return "forge";
|
|
480
446
|
}
|
|
481
|
-
function
|
|
482
|
-
|
|
447
|
+
function trimEnv(env, key) {
|
|
448
|
+
const value = env[key]?.trim();
|
|
449
|
+
return value || null;
|
|
483
450
|
}
|
|
484
|
-
function
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
451
|
+
function resolveBoxIdentity(env = process.env, config = {}) {
|
|
452
|
+
const warnings = [];
|
|
453
|
+
const configKind = config.boxKind?.trim();
|
|
454
|
+
if (configKind) {
|
|
455
|
+
return {
|
|
456
|
+
boxKind: normalizeWorkerPoolBoxKind(configKind),
|
|
457
|
+
source: "config",
|
|
458
|
+
slugInferenceBlocked: false,
|
|
459
|
+
warnings
|
|
460
|
+
};
|
|
488
461
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
462
|
+
const envKind = trimEnv(env, "KYNVER_BOX_KIND");
|
|
463
|
+
if (envKind) {
|
|
464
|
+
return {
|
|
465
|
+
boxKind: normalizeWorkerPoolBoxKind(envKind),
|
|
466
|
+
source: "env",
|
|
467
|
+
slugInferenceBlocked: false,
|
|
468
|
+
warnings
|
|
469
|
+
};
|
|
497
470
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
for (const candidate of candidates) {
|
|
504
|
-
const resolved = path4.resolve(candidate);
|
|
505
|
-
if (existsSync4(path4.join(resolved, "packages/kynver-runtime/package.json")) && existsSync4(path4.join(resolved, "package.json"))) {
|
|
506
|
-
return resolved;
|
|
507
|
-
}
|
|
471
|
+
const agentOsSlug = trimEnv(env, "KYNVER_AGENT_OS_SLUG");
|
|
472
|
+
if (agentOsSlug) {
|
|
473
|
+
warnings.push(
|
|
474
|
+
`KYNVER_AGENT_OS_SLUG=${agentOsSlug} is a workspace slug, not box identity \u2014 set boxKind via \`kynver setup --box-kind forge|ghost\` or KYNVER_BOX_KIND (defaulting box kind to forge)`
|
|
475
|
+
);
|
|
508
476
|
}
|
|
509
|
-
|
|
510
|
-
|
|
477
|
+
return {
|
|
478
|
+
boxKind: "forge",
|
|
479
|
+
source: "default",
|
|
480
|
+
slugInferenceBlocked: Boolean(agentOsSlug),
|
|
481
|
+
warnings
|
|
482
|
+
};
|
|
511
483
|
}
|
|
512
|
-
function
|
|
513
|
-
|
|
514
|
-
const repoRoot = resolveRepoRoot(cwd, input.repoRoot);
|
|
515
|
-
if (!repoRoot) return {};
|
|
516
|
-
const out = {};
|
|
517
|
-
for (const packageName of MEMORY_COST_MANAGED_PACKAGES) {
|
|
518
|
-
const packageJsonPath = path4.join(repoRoot, REPO_PACKAGE_JSON_RELATIVE[packageName]);
|
|
519
|
-
const version = readPackageJsonVersion(packageJsonPath);
|
|
520
|
-
if (!version) continue;
|
|
521
|
-
out[packageName] = { version, source: "repo", path: packageJsonPath };
|
|
522
|
-
}
|
|
523
|
-
return out;
|
|
484
|
+
function resolveBoxKindFromConfig(config = {}, env = process.env) {
|
|
485
|
+
return resolveBoxIdentity(env, config).boxKind;
|
|
524
486
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
487
|
+
var init_box_identity = __esm({
|
|
488
|
+
"src/box-identity.ts"() {
|
|
489
|
+
"use strict";
|
|
528
490
|
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
);
|
|
538
|
-
|
|
539
|
-
return lines;
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
// src/bounded-build/meminfo.ts
|
|
494
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
495
|
+
import os from "node:os";
|
|
496
|
+
function readMemAvailableBytes(meminfoText) {
|
|
497
|
+
if (meminfoText !== void 0) {
|
|
498
|
+
const match = meminfoText.match(/^MemAvailable:\s+(\d+)\s*kB/m);
|
|
499
|
+
if (match) return Number(match[1]) * 1024;
|
|
500
|
+
return os.freemem();
|
|
540
501
|
}
|
|
541
|
-
if (
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
502
|
+
if (process.platform === "linux") {
|
|
503
|
+
try {
|
|
504
|
+
const meminfo = readFileSync5("/proc/meminfo", "utf8");
|
|
505
|
+
const match = meminfo.match(/^MemAvailable:\s+(\d+)\s*kB/m);
|
|
506
|
+
if (match) return Number(match[1]) * 1024;
|
|
507
|
+
} catch {
|
|
508
|
+
}
|
|
547
509
|
}
|
|
548
|
-
|
|
549
|
-
|
|
510
|
+
return os.freemem();
|
|
511
|
+
}
|
|
512
|
+
var init_meminfo = __esm({
|
|
513
|
+
"src/bounded-build/meminfo.ts"() {
|
|
514
|
+
"use strict";
|
|
550
515
|
}
|
|
551
|
-
|
|
552
|
-
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
// src/wsl-host.ts
|
|
519
|
+
import { existsSync as existsSync5, readFileSync as readFileSync6, statfsSync } from "node:fs";
|
|
520
|
+
function isWslHost() {
|
|
521
|
+
if (process.platform !== "linux") return false;
|
|
522
|
+
for (const probe of ["/proc/sys/kernel/osrelease", "/proc/version"]) {
|
|
523
|
+
try {
|
|
524
|
+
if (!existsSync5(probe)) continue;
|
|
525
|
+
const text = readFileSync6(probe, "utf8");
|
|
526
|
+
if (/microsoft|wsl/i.test(text)) return true;
|
|
527
|
+
} catch {
|
|
528
|
+
}
|
|
553
529
|
}
|
|
554
|
-
return
|
|
555
|
-
}
|
|
556
|
-
function pickEffectiveCandidate(candidates) {
|
|
557
|
-
if (candidates.length === 0) return { version: null, source: "unknown" };
|
|
558
|
-
const best = maxSemver(candidates.map((candidate) => candidate.version));
|
|
559
|
-
if (!best) return { version: null, source: "unknown" };
|
|
560
|
-
const winner = candidates.find((candidate) => candidate.version === best) ?? candidates[0];
|
|
561
|
-
return { version: winner.version, source: winner.source };
|
|
562
|
-
}
|
|
563
|
-
function evaluateMemoryCostPackageVersionGuard(input = {}) {
|
|
564
|
-
const normalize2 = (value, fallbackSource) => {
|
|
565
|
-
if (!value) return null;
|
|
566
|
-
if (typeof value === "string") return { version: value, source: fallbackSource };
|
|
567
|
-
return value;
|
|
568
|
-
};
|
|
569
|
-
const packages = MEMORY_COST_MANAGED_PACKAGES.map((packageName) => {
|
|
570
|
-
const minimumVersion = MEMORY_COST_PACKAGE_MIN_VERSIONS[packageName];
|
|
571
|
-
const candidates = [];
|
|
572
|
-
const installed = normalize2(input.installed?.[packageName], "installed");
|
|
573
|
-
const repo = normalize2(input.repo?.[packageName], "repo");
|
|
574
|
-
const self = normalize2(input.self?.[packageName], "self");
|
|
575
|
-
if (installed) candidates.push(installed);
|
|
576
|
-
if (repo) candidates.push(repo);
|
|
577
|
-
if (self) candidates.push(self);
|
|
578
|
-
const { version: effectiveVersion, source: effectiveSource } = pickEffectiveCandidate(candidates);
|
|
579
|
-
const repoVersion = repo?.version ?? null;
|
|
580
|
-
const ok2 = effectiveVersion ? semverAtLeast(effectiveVersion, minimumVersion) : false;
|
|
581
|
-
const remediation = ok2 ? [] : buildRemediation({
|
|
582
|
-
packageName,
|
|
583
|
-
minimumVersion,
|
|
584
|
-
effectiveVersion,
|
|
585
|
-
effectiveSource,
|
|
586
|
-
repoVersion
|
|
587
|
-
});
|
|
588
|
-
const summary2 = ok2 ? `${DISPLAY_NAMES[packageName]} ${effectiveVersion} meets memory-cost minimum ${minimumVersion} (${effectiveSource}).` : `${DISPLAY_NAMES[packageName]} is below memory-cost minimum ${minimumVersion}` + (effectiveVersion ? ` (effective ${effectiveVersion} via ${effectiveSource})` : " (no version detected)") + ".";
|
|
589
|
-
return {
|
|
590
|
-
packageName,
|
|
591
|
-
displayName: DISPLAY_NAMES[packageName],
|
|
592
|
-
minimumVersion,
|
|
593
|
-
effectiveVersion,
|
|
594
|
-
effectiveSource,
|
|
595
|
-
ok: ok2,
|
|
596
|
-
summary: summary2,
|
|
597
|
-
remediation
|
|
598
|
-
};
|
|
599
|
-
});
|
|
600
|
-
const violations = packages.filter((row) => !row.ok);
|
|
601
|
-
const ok = violations.length === 0;
|
|
602
|
-
const summary = ok ? "All managed AgentOS packages meet memory-cost minimum versions." : `Memory-cost package guard blocked ${violations.length} stale package(s): ${violations.map((row) => `${row.packageName} < ${row.minimumVersion}`).join("; ")}.`;
|
|
603
|
-
return { ok, summary, packages };
|
|
604
|
-
}
|
|
605
|
-
var MemoryCostPackageVersionGuardError = class extends Error {
|
|
606
|
-
result;
|
|
607
|
-
constructor(result) {
|
|
608
|
-
const lines = [
|
|
609
|
-
result.summary,
|
|
610
|
-
...result.packages.filter((row) => !row.ok).flatMap((row) => [`- ${row.summary}`, ...row.remediation.map((line) => ` \u2192 ${line}`)])
|
|
611
|
-
];
|
|
612
|
-
super(lines.join("\n"));
|
|
613
|
-
this.name = "MemoryCostPackageVersionGuardError";
|
|
614
|
-
this.result = result;
|
|
615
|
-
}
|
|
616
|
-
};
|
|
617
|
-
function assertMemoryCostPackageVersionGuard(input = {}) {
|
|
618
|
-
const result = evaluateMemoryCostPackageVersionGuard(input);
|
|
619
|
-
if (!result.ok) throw new MemoryCostPackageVersionGuardError(result);
|
|
620
|
-
return result;
|
|
621
|
-
}
|
|
622
|
-
function formatMemoryCostPackageGuardError(result) {
|
|
623
|
-
return new MemoryCostPackageVersionGuardError(result).message;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
// src/installed-package-versions.ts
|
|
627
|
-
import { readFile } from "node:fs/promises";
|
|
628
|
-
import { homedir as homedir3 } from "node:os";
|
|
629
|
-
import path5 from "node:path";
|
|
630
|
-
var MANAGED_PACKAGES = [
|
|
631
|
-
"@kynver-app/runtime",
|
|
632
|
-
"@kynver-app/openclaw-agent-os",
|
|
633
|
-
"@kynver-app/mcp-agent-os"
|
|
634
|
-
];
|
|
635
|
-
function trim(value) {
|
|
636
|
-
const out = value?.trim();
|
|
637
|
-
return out ? out : null;
|
|
638
|
-
}
|
|
639
|
-
function unique(values) {
|
|
640
|
-
return [...new Set(values.filter((value) => Boolean(value)))];
|
|
641
|
-
}
|
|
642
|
-
function moduleRoots() {
|
|
643
|
-
const home = homedir3();
|
|
644
|
-
const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ?? path5.join(home, ".openclaw", "npm");
|
|
645
|
-
const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ? path5.join(trim(process.env.NPM_CONFIG_PREFIX), "lib", "node_modules") : path5.join(home, ".npm-global", "lib", "node_modules"));
|
|
646
|
-
return unique([
|
|
647
|
-
path5.join(openClawPrefix, "lib", "node_modules"),
|
|
648
|
-
path5.join(openClawPrefix, "node_modules"),
|
|
649
|
-
npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot : path5.join(npmGlobalRoot, "lib", "node_modules")
|
|
650
|
-
]);
|
|
651
|
-
}
|
|
652
|
-
async function readVersion(packageJsonPath) {
|
|
653
|
-
try {
|
|
654
|
-
const parsed = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
655
|
-
return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
|
|
656
|
-
} catch {
|
|
657
|
-
return null;
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
function installedPackageJsonCandidates(packageName) {
|
|
661
|
-
const roots = moduleRoots();
|
|
662
|
-
const seen = /* @__PURE__ */ new Set();
|
|
663
|
-
const out = [];
|
|
664
|
-
for (const root of roots) {
|
|
665
|
-
const candidate = path5.join(root, packageName, "package.json");
|
|
666
|
-
if (seen.has(candidate)) continue;
|
|
667
|
-
seen.add(candidate);
|
|
668
|
-
out.push(candidate);
|
|
669
|
-
}
|
|
670
|
-
return out;
|
|
671
|
-
}
|
|
672
|
-
async function collectInstalledPackageVersions(observedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
673
|
-
const out = {};
|
|
674
|
-
for (const packageName of MANAGED_PACKAGES) {
|
|
675
|
-
let best = null;
|
|
676
|
-
for (const packageJsonPath of installedPackageJsonCandidates(packageName)) {
|
|
677
|
-
const version = await readVersion(packageJsonPath);
|
|
678
|
-
if (!version) continue;
|
|
679
|
-
if (!best || compareSemver(version, best.version) > 0) {
|
|
680
|
-
best = { version, path: packageJsonPath };
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
if (best) {
|
|
684
|
-
out[packageName] = { version: best.version, observedAt, path: best.path };
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
return out;
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
// src/memory-cost-package-version-guard-enforce.ts
|
|
691
|
-
function installedVersionMap(observed) {
|
|
692
|
-
const out = {};
|
|
693
|
-
for (const [packageName, row] of Object.entries(observed)) {
|
|
694
|
-
if (!row?.version) continue;
|
|
695
|
-
out[packageName] = {
|
|
696
|
-
version: row.version,
|
|
697
|
-
source: "installed",
|
|
698
|
-
path: row.path
|
|
699
|
-
};
|
|
700
|
-
}
|
|
701
|
-
return out;
|
|
702
|
-
}
|
|
703
|
-
async function buildMemoryCostPackageGuardInput(input = {}) {
|
|
704
|
-
const [installed, repo] = await Promise.all([
|
|
705
|
-
collectInstalledPackageVersions(),
|
|
706
|
-
Promise.resolve(probeRepoPackageVersions({ cwd: input.cwd, repoRoot: input.repoRoot }))
|
|
707
|
-
]);
|
|
708
|
-
const self = {};
|
|
709
|
-
const runtimeSelfVersion = input.selfPackageName === "@kynver-app/runtime" && input.selfVersion ? input.selfVersion : PACKAGE_VERSION;
|
|
710
|
-
self["@kynver-app/runtime"] = { version: runtimeSelfVersion, source: "self" };
|
|
711
|
-
if (input.selfPackageName && input.selfVersion && input.selfPackageName !== "@kynver-app/runtime") {
|
|
712
|
-
self[input.selfPackageName] = { version: input.selfVersion, source: "self" };
|
|
713
|
-
}
|
|
714
|
-
return {
|
|
715
|
-
installed: installedVersionMap(installed),
|
|
716
|
-
repo,
|
|
717
|
-
self
|
|
718
|
-
};
|
|
719
|
-
}
|
|
720
|
-
async function evaluateMemoryCostPackageGuardAtStartup(input = {}) {
|
|
721
|
-
const guardInput = await buildMemoryCostPackageGuardInput(input);
|
|
722
|
-
return evaluateMemoryCostPackageVersionGuard(guardInput);
|
|
723
|
-
}
|
|
724
|
-
async function enforceMemoryCostPackageGuardAtStartup(input = {}) {
|
|
725
|
-
const guardInput = await buildMemoryCostPackageGuardInput(input);
|
|
726
|
-
return assertMemoryCostPackageVersionGuard(guardInput);
|
|
727
|
-
}
|
|
728
|
-
function shouldEnforceMemoryCostPackageGuardCli(scope, action) {
|
|
729
|
-
if (!scope) return false;
|
|
730
|
-
if (scope === "daemon") return true;
|
|
731
|
-
if (scope === "worker") return true;
|
|
732
|
-
if (scope === "monitor") return true;
|
|
733
|
-
if (scope === "run" && (action === "dispatch" || action === "sweep" || action === "reconcile" || action === "unblock")) {
|
|
734
|
-
return true;
|
|
735
|
-
}
|
|
736
|
-
if (scope === "cron" && action === "tick") return true;
|
|
737
|
-
return false;
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
// src/config.ts
|
|
741
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync2, readFileSync as readFileSync10, writeFileSync as writeFileSync2 } from "node:fs";
|
|
742
|
-
import { homedir as homedir5, totalmem } from "node:os";
|
|
743
|
-
import path10 from "node:path";
|
|
744
|
-
|
|
745
|
-
// src/box-identity.ts
|
|
746
|
-
function normalizeWorkerPoolBoxKind(raw) {
|
|
747
|
-
const kind = (raw ?? "").trim().toLowerCase();
|
|
748
|
-
if (kind === "ghost" || kind === "forge") return kind;
|
|
749
|
-
if (kind.includes("forge")) return "forge";
|
|
750
|
-
if (kind.includes("ghost") || kind.includes("openclaw")) return "ghost";
|
|
751
|
-
return "forge";
|
|
752
|
-
}
|
|
753
|
-
function trimEnv(env, key) {
|
|
754
|
-
const value = env[key]?.trim();
|
|
755
|
-
return value || null;
|
|
756
|
-
}
|
|
757
|
-
function resolveBoxIdentity(env = process.env, config = {}) {
|
|
758
|
-
const warnings = [];
|
|
759
|
-
const configKind = config.boxKind?.trim();
|
|
760
|
-
if (configKind) {
|
|
761
|
-
return {
|
|
762
|
-
boxKind: normalizeWorkerPoolBoxKind(configKind),
|
|
763
|
-
source: "config",
|
|
764
|
-
slugInferenceBlocked: false,
|
|
765
|
-
warnings
|
|
766
|
-
};
|
|
767
|
-
}
|
|
768
|
-
const envKind = trimEnv(env, "KYNVER_BOX_KIND");
|
|
769
|
-
if (envKind) {
|
|
770
|
-
return {
|
|
771
|
-
boxKind: normalizeWorkerPoolBoxKind(envKind),
|
|
772
|
-
source: "env",
|
|
773
|
-
slugInferenceBlocked: false,
|
|
774
|
-
warnings
|
|
775
|
-
};
|
|
776
|
-
}
|
|
777
|
-
const agentOsSlug = trimEnv(env, "KYNVER_AGENT_OS_SLUG");
|
|
778
|
-
if (agentOsSlug) {
|
|
779
|
-
warnings.push(
|
|
780
|
-
`KYNVER_AGENT_OS_SLUG=${agentOsSlug} is a workspace slug, not box identity \u2014 set boxKind via \`kynver setup --box-kind forge|ghost\` or KYNVER_BOX_KIND (defaulting box kind to forge)`
|
|
781
|
-
);
|
|
782
|
-
}
|
|
783
|
-
return {
|
|
784
|
-
boxKind: "forge",
|
|
785
|
-
source: "default",
|
|
786
|
-
slugInferenceBlocked: Boolean(agentOsSlug),
|
|
787
|
-
warnings
|
|
788
|
-
};
|
|
789
|
-
}
|
|
790
|
-
function resolveBoxKindFromConfig(config = {}, env = process.env) {
|
|
791
|
-
return resolveBoxIdentity(env, config).boxKind;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
// src/resource-gate.ts
|
|
795
|
-
import os2 from "node:os";
|
|
796
|
-
|
|
797
|
-
// src/bounded-build/meminfo.ts
|
|
798
|
-
import { readFileSync as readFileSync5 } from "node:fs";
|
|
799
|
-
import os from "node:os";
|
|
800
|
-
function readMemAvailableBytes(meminfoText) {
|
|
801
|
-
if (meminfoText !== void 0) {
|
|
802
|
-
const match = meminfoText.match(/^MemAvailable:\s+(\d+)\s*kB/m);
|
|
803
|
-
if (match) return Number(match[1]) * 1024;
|
|
804
|
-
return os.freemem();
|
|
805
|
-
}
|
|
806
|
-
if (process.platform === "linux") {
|
|
807
|
-
try {
|
|
808
|
-
const meminfo = readFileSync5("/proc/meminfo", "utf8");
|
|
809
|
-
const match = meminfo.match(/^MemAvailable:\s+(\d+)\s*kB/m);
|
|
810
|
-
if (match) return Number(match[1]) * 1024;
|
|
811
|
-
} catch {
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
return os.freemem();
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
// src/resource-gate.ts
|
|
818
|
-
import path9 from "node:path";
|
|
819
|
-
|
|
820
|
-
// src/disk-gate.ts
|
|
821
|
-
import { statfsSync as statfsSync2 } from "node:fs";
|
|
822
|
-
|
|
823
|
-
// src/wsl-host.ts
|
|
824
|
-
import { existsSync as existsSync5, readFileSync as readFileSync6, statfsSync } from "node:fs";
|
|
825
|
-
var DEFAULT_WSL_HOST_WARN_FREE_BYTES = 25 * 1024 * 1024 * 1024;
|
|
826
|
-
var DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES = 12 * 1024 * 1024 * 1024;
|
|
827
|
-
var DEFAULT_WSL_HOST_MOUNT = "/mnt/c";
|
|
828
|
-
function isWslHost() {
|
|
829
|
-
if (process.platform !== "linux") return false;
|
|
830
|
-
for (const probe of ["/proc/sys/kernel/osrelease", "/proc/version"]) {
|
|
831
|
-
try {
|
|
832
|
-
if (!existsSync5(probe)) continue;
|
|
833
|
-
const text = readFileSync6(probe, "utf8");
|
|
834
|
-
if (/microsoft|wsl/i.test(text)) return true;
|
|
835
|
-
} catch {
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
return false;
|
|
530
|
+
return false;
|
|
839
531
|
}
|
|
840
532
|
function observeWslHostDisk(options = {}) {
|
|
841
533
|
const wsl = options.forceWsl === void 0 ? isWslHost() : options.forceWsl;
|
|
842
534
|
if (!wsl) return null;
|
|
843
|
-
const
|
|
535
|
+
const path75 = options.wslHostMount?.trim() || process.env.KYNVER_WSL_HOST_MOUNT?.trim() || DEFAULT_WSL_HOST_MOUNT;
|
|
844
536
|
const warnBelowBytes = options.wslHostFreeWarnBytes ?? DEFAULT_WSL_HOST_WARN_FREE_BYTES;
|
|
845
537
|
const criticalBelowBytes = options.wslHostFreeCriticalBytes ?? DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES;
|
|
846
538
|
const statfs = options.statfs ?? statfsSync;
|
|
847
539
|
let stats;
|
|
848
540
|
try {
|
|
849
|
-
stats = statfs(
|
|
541
|
+
stats = statfs(path75);
|
|
850
542
|
} catch (error) {
|
|
851
543
|
return {
|
|
852
544
|
ok: false,
|
|
853
|
-
path:
|
|
545
|
+
path: path75,
|
|
854
546
|
freeBytes: 0,
|
|
855
547
|
totalBytes: 0,
|
|
856
548
|
usedPercent: 100,
|
|
857
549
|
warnBelowBytes,
|
|
858
550
|
criticalBelowBytes,
|
|
859
|
-
reason: `Windows host disk probe failed at ${
|
|
551
|
+
reason: `Windows host disk probe failed at ${path75}: ${error.message}`,
|
|
860
552
|
probeError: error.message
|
|
861
553
|
};
|
|
862
554
|
}
|
|
@@ -870,11 +562,11 @@ function observeWslHostDisk(options = {}) {
|
|
|
870
562
|
let reason = null;
|
|
871
563
|
if (!ok) {
|
|
872
564
|
const tag = criticalFree ? "critical" : "warning";
|
|
873
|
-
reason = `Windows host disk ${
|
|
565
|
+
reason = `Windows host disk ${path75} at ${tag}: ${freeGiB} GiB free (<${(criticalFree ? criticalBelowBytes : warnBelowBytes) / 1024 / 1024 / 1024} GiB); WSL VHDX cannot grow safely. ${summarizeWslRecoverySteps()}`;
|
|
874
566
|
}
|
|
875
567
|
return {
|
|
876
568
|
ok,
|
|
877
|
-
path:
|
|
569
|
+
path: path75,
|
|
878
570
|
freeBytes,
|
|
879
571
|
totalBytes,
|
|
880
572
|
usedPercent,
|
|
@@ -887,19 +579,25 @@ function observeWslHostDisk(options = {}) {
|
|
|
887
579
|
function summarizeWslRecoverySteps() {
|
|
888
580
|
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.";
|
|
889
581
|
}
|
|
582
|
+
var DEFAULT_WSL_HOST_WARN_FREE_BYTES, DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES, DEFAULT_WSL_HOST_MOUNT;
|
|
583
|
+
var init_wsl_host = __esm({
|
|
584
|
+
"src/wsl-host.ts"() {
|
|
585
|
+
"use strict";
|
|
586
|
+
DEFAULT_WSL_HOST_WARN_FREE_BYTES = 25 * 1024 * 1024 * 1024;
|
|
587
|
+
DEFAULT_WSL_HOST_CRITICAL_FREE_BYTES = 12 * 1024 * 1024 * 1024;
|
|
588
|
+
DEFAULT_WSL_HOST_MOUNT = "/mnt/c";
|
|
589
|
+
}
|
|
590
|
+
});
|
|
890
591
|
|
|
891
592
|
// src/disk-gate.ts
|
|
892
|
-
|
|
893
|
-
var DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
|
|
894
|
-
var DEFAULT_MAX_USED_PERCENT = 80;
|
|
895
|
-
var DEFAULT_HARD_MAX_USED_PERCENT = 90;
|
|
593
|
+
import { statfsSync as statfsSync2 } from "node:fs";
|
|
896
594
|
function observeRunnerDiskGate(input = {}) {
|
|
897
|
-
const
|
|
595
|
+
const path75 = input.diskPath?.trim() || "/";
|
|
898
596
|
const warnBelowBytes = input.diskFreeWarnBytes ?? DEFAULT_WARN_FREE_BYTES;
|
|
899
597
|
const criticalBelowBytes = input.diskFreeCriticalBytes ?? DEFAULT_CRITICAL_FREE_BYTES;
|
|
900
598
|
const maxUsedPercent = input.diskMaxUsedPercent ?? DEFAULT_MAX_USED_PERCENT;
|
|
901
599
|
const hardMaxUsedPercent = input.diskHardMaxUsedPercent ?? DEFAULT_HARD_MAX_USED_PERCENT;
|
|
902
|
-
const stats = statfsSync2(
|
|
600
|
+
const stats = statfsSync2(path75);
|
|
903
601
|
const freeBytes = Number(stats.bavail) * Number(stats.bsize);
|
|
904
602
|
const totalBytes = Number(stats.blocks) * Number(stats.bsize);
|
|
905
603
|
const usedPercent = totalBytes > 0 ? (totalBytes - freeBytes) / totalBytes * 100 : 100;
|
|
@@ -922,7 +620,7 @@ function observeRunnerDiskGate(input = {}) {
|
|
|
922
620
|
}
|
|
923
621
|
return {
|
|
924
622
|
ok,
|
|
925
|
-
path:
|
|
623
|
+
path: path75,
|
|
926
624
|
freeBytes,
|
|
927
625
|
totalBytes,
|
|
928
626
|
usedPercent,
|
|
@@ -934,17 +632,22 @@ function observeRunnerDiskGate(input = {}) {
|
|
|
934
632
|
wslHost
|
|
935
633
|
};
|
|
936
634
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
635
|
+
var DEFAULT_WARN_FREE_BYTES, DEFAULT_CRITICAL_FREE_BYTES, DEFAULT_MAX_USED_PERCENT, DEFAULT_HARD_MAX_USED_PERCENT;
|
|
636
|
+
var init_disk_gate = __esm({
|
|
637
|
+
"src/disk-gate.ts"() {
|
|
638
|
+
"use strict";
|
|
639
|
+
init_wsl_host();
|
|
640
|
+
DEFAULT_WARN_FREE_BYTES = 30 * 1024 * 1024 * 1024;
|
|
641
|
+
DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
|
|
642
|
+
DEFAULT_MAX_USED_PERCENT = 80;
|
|
643
|
+
DEFAULT_HARD_MAX_USED_PERCENT = 90;
|
|
644
|
+
}
|
|
645
|
+
});
|
|
941
646
|
|
|
942
647
|
// src/paths.ts
|
|
943
648
|
import { existsSync as existsSync6 } from "node:fs";
|
|
944
649
|
import { homedir as homedir4 } from "node:os";
|
|
945
650
|
import path6 from "node:path";
|
|
946
|
-
var LEGACY_ROOT = path6.join(homedir4(), ".openclaw", "harness");
|
|
947
|
-
var HARNESS_LAYOUT_DIR_NAMES = /* @__PURE__ */ new Set(["runs", "worktrees"]);
|
|
948
651
|
function normalizeHarnessRoot(root) {
|
|
949
652
|
let resolved = path6.resolve(resolveUserPath(root.trim()));
|
|
950
653
|
while (HARNESS_LAYOUT_DIR_NAMES.has(path6.basename(resolved))) {
|
|
@@ -979,8 +682,21 @@ function getHarnessPaths() {
|
|
|
979
682
|
function runDir(runsDir, id) {
|
|
980
683
|
return path6.join(runsDir, safeSlug(id));
|
|
981
684
|
}
|
|
685
|
+
var LEGACY_ROOT, HARNESS_LAYOUT_DIR_NAMES;
|
|
686
|
+
var init_paths = __esm({
|
|
687
|
+
"src/paths.ts"() {
|
|
688
|
+
"use strict";
|
|
689
|
+
init_config();
|
|
690
|
+
init_path_values();
|
|
691
|
+
init_util();
|
|
692
|
+
LEGACY_ROOT = path6.join(homedir4(), ".openclaw", "harness");
|
|
693
|
+
HARNESS_LAYOUT_DIR_NAMES = /* @__PURE__ */ new Set(["runs", "worktrees"]);
|
|
694
|
+
}
|
|
695
|
+
});
|
|
982
696
|
|
|
983
697
|
// src/run-store.ts
|
|
698
|
+
import { existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
|
|
699
|
+
import path7 from "node:path";
|
|
984
700
|
function getPaths() {
|
|
985
701
|
return getHarnessPaths();
|
|
986
702
|
}
|
|
@@ -1038,6 +754,13 @@ function runDirectory(id) {
|
|
|
1038
754
|
function runDirectoryAt(harnessRoot, id) {
|
|
1039
755
|
return runDir(harnessRunsDir(harnessRoot), safeSlug(id));
|
|
1040
756
|
}
|
|
757
|
+
var init_run_store = __esm({
|
|
758
|
+
"src/run-store.ts"() {
|
|
759
|
+
"use strict";
|
|
760
|
+
init_paths();
|
|
761
|
+
init_util();
|
|
762
|
+
}
|
|
763
|
+
});
|
|
1041
764
|
|
|
1042
765
|
// src/run-worker-index.ts
|
|
1043
766
|
import { existsSync as existsSync8, readdirSync as readdirSync3 } from "node:fs";
|
|
@@ -1055,12 +778,13 @@ function listRunWorkerNames(run) {
|
|
|
1055
778
|
}
|
|
1056
779
|
return [...names];
|
|
1057
780
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
781
|
+
var init_run_worker_index = __esm({
|
|
782
|
+
"src/run-worker-index.ts"() {
|
|
783
|
+
"use strict";
|
|
784
|
+
init_run_store();
|
|
785
|
+
init_util();
|
|
786
|
+
}
|
|
787
|
+
});
|
|
1064
788
|
|
|
1065
789
|
// src/heartbeat-final-result.ts
|
|
1066
790
|
function tryParseJsonObject(text) {
|
|
@@ -1111,9 +835,14 @@ function terminalFinalResultFromHeartbeatRow(row) {
|
|
|
1111
835
|
if (embedded) return embedded;
|
|
1112
836
|
return summary;
|
|
1113
837
|
}
|
|
838
|
+
var init_heartbeat_final_result = __esm({
|
|
839
|
+
"src/heartbeat-final-result.ts"() {
|
|
840
|
+
"use strict";
|
|
841
|
+
}
|
|
842
|
+
});
|
|
1114
843
|
|
|
1115
844
|
// src/heartbeat.ts
|
|
1116
|
-
|
|
845
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
|
|
1117
846
|
function isTerminalHeartbeatPhase(phase) {
|
|
1118
847
|
return phase === "complete";
|
|
1119
848
|
}
|
|
@@ -1176,29 +905,17 @@ function parseHeartbeat(file) {
|
|
|
1176
905
|
}
|
|
1177
906
|
return result;
|
|
1178
907
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
908
|
+
var HEARTBEAT_FUTURE_SKEW_MS;
|
|
909
|
+
var init_heartbeat = __esm({
|
|
910
|
+
"src/heartbeat.ts"() {
|
|
911
|
+
"use strict";
|
|
912
|
+
init_heartbeat_final_result();
|
|
913
|
+
init_util();
|
|
914
|
+
HEARTBEAT_FUTURE_SKEW_MS = 6e4;
|
|
915
|
+
}
|
|
916
|
+
});
|
|
1182
917
|
|
|
1183
918
|
// src/repo-search.ts
|
|
1184
|
-
var RG_BINARIES = /* @__PURE__ */ new Set(["rg", "ripgrep", "grep"]);
|
|
1185
|
-
var RG_OPTS_WITH_VALUE = /* @__PURE__ */ new Set([
|
|
1186
|
-
"-e",
|
|
1187
|
-
"--regexp",
|
|
1188
|
-
"-f",
|
|
1189
|
-
"--file",
|
|
1190
|
-
"-m",
|
|
1191
|
-
"--max-count",
|
|
1192
|
-
"-A",
|
|
1193
|
-
"--after-context",
|
|
1194
|
-
"-B",
|
|
1195
|
-
"--before-context",
|
|
1196
|
-
"-C",
|
|
1197
|
-
"--context",
|
|
1198
|
-
"-g",
|
|
1199
|
-
"--glob",
|
|
1200
|
-
"--iglob"
|
|
1201
|
-
]);
|
|
1202
919
|
function binaryName(token) {
|
|
1203
920
|
if (!token) return null;
|
|
1204
921
|
const base = token.split("/").pop() ?? token;
|
|
@@ -1397,11 +1114,32 @@ function diagnoseRepoSearchFailure(input) {
|
|
|
1397
1114
|
}
|
|
1398
1115
|
return null;
|
|
1399
1116
|
}
|
|
1117
|
+
var RG_BINARIES, RG_OPTS_WITH_VALUE;
|
|
1118
|
+
var init_repo_search = __esm({
|
|
1119
|
+
"src/repo-search.ts"() {
|
|
1120
|
+
"use strict";
|
|
1121
|
+
RG_BINARIES = /* @__PURE__ */ new Set(["rg", "ripgrep", "grep"]);
|
|
1122
|
+
RG_OPTS_WITH_VALUE = /* @__PURE__ */ new Set([
|
|
1123
|
+
"-e",
|
|
1124
|
+
"--regexp",
|
|
1125
|
+
"-f",
|
|
1126
|
+
"--file",
|
|
1127
|
+
"-m",
|
|
1128
|
+
"--max-count",
|
|
1129
|
+
"-A",
|
|
1130
|
+
"--after-context",
|
|
1131
|
+
"-B",
|
|
1132
|
+
"--before-context",
|
|
1133
|
+
"-C",
|
|
1134
|
+
"--context",
|
|
1135
|
+
"-g",
|
|
1136
|
+
"--glob",
|
|
1137
|
+
"--iglob"
|
|
1138
|
+
]);
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1400
1141
|
|
|
1401
1142
|
// src/shell-command-outcome.ts
|
|
1402
|
-
var NPM_AUDIT_RE = /\bnpm\s+audit\b/i;
|
|
1403
|
-
var RG_CMD_RE = /\b(rg|ripgrep)\b/i;
|
|
1404
|
-
var RG_REAL_ERROR_RE = /\b(error|invalid|unknown|panic|not found)\b/i;
|
|
1405
1143
|
function tidy(text, max = 200) {
|
|
1406
1144
|
const one = text.replace(/\s+/g, " ").trim();
|
|
1407
1145
|
return one.length > max ? `${one.slice(0, max - 1)}\u2026` : one;
|
|
@@ -1605,8 +1343,19 @@ function classifyShellCommandOutcome(input) {
|
|
|
1605
1343
|
summary: `command failed (exit ${input.exitCode}): ${tail}`
|
|
1606
1344
|
};
|
|
1607
1345
|
}
|
|
1346
|
+
var NPM_AUDIT_RE, RG_CMD_RE, RG_REAL_ERROR_RE;
|
|
1347
|
+
var init_shell_command_outcome = __esm({
|
|
1348
|
+
"src/shell-command-outcome.ts"() {
|
|
1349
|
+
"use strict";
|
|
1350
|
+
init_repo_search();
|
|
1351
|
+
NPM_AUDIT_RE = /\bnpm\s+audit\b/i;
|
|
1352
|
+
RG_CMD_RE = /\b(rg|ripgrep)\b/i;
|
|
1353
|
+
RG_REAL_ERROR_RE = /\b(error|invalid|unknown|panic|not found)\b/i;
|
|
1354
|
+
}
|
|
1355
|
+
});
|
|
1608
1356
|
|
|
1609
1357
|
// src/stream.ts
|
|
1358
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
|
|
1610
1359
|
function eventTimestampIso(event) {
|
|
1611
1360
|
const tsMs = event.timestamp_ms;
|
|
1612
1361
|
return event.timestamp || event.ts || (tsMs ? new Date(tsMs).toISOString() : void 0);
|
|
@@ -1775,38 +1524,15 @@ function summarizeEvent(event) {
|
|
|
1775
1524
|
}
|
|
1776
1525
|
return void 0;
|
|
1777
1526
|
}
|
|
1527
|
+
var init_stream = __esm({
|
|
1528
|
+
"src/stream.ts"() {
|
|
1529
|
+
"use strict";
|
|
1530
|
+
init_shell_command_outcome();
|
|
1531
|
+
init_util();
|
|
1532
|
+
}
|
|
1533
|
+
});
|
|
1778
1534
|
|
|
1779
1535
|
// src/exit-classify.ts
|
|
1780
|
-
var FAILURE_PATTERNS = [
|
|
1781
|
-
{
|
|
1782
|
-
test: /\b(?:invalid|unknown|unsupported|unrecognized)\b[^.\n]*\bmodel\b/i,
|
|
1783
|
-
label: "provider rejected the requested model"
|
|
1784
|
-
},
|
|
1785
|
-
{
|
|
1786
|
-
test: /\bmodel\b[^.\n]*\b(?:not\s+(?:found|supported|available|recognized|valid)|is\s+not\s+valid|does\s+not\s+exist)/i,
|
|
1787
|
-
label: "provider rejected the requested model"
|
|
1788
|
-
},
|
|
1789
|
-
{
|
|
1790
|
-
test: /\b(?:did you mean|available models|choose (?:a|one of)|supported models)\b/i,
|
|
1791
|
-
label: "provider rejected the requested model"
|
|
1792
|
-
},
|
|
1793
|
-
{
|
|
1794
|
-
test: /model preflight failed/i,
|
|
1795
|
-
label: "model/provider preflight failed"
|
|
1796
|
-
},
|
|
1797
|
-
{
|
|
1798
|
-
test: /\b(?:command not found|ENOENT|is the .*CLI on PATH|executable not found|no such file or directory)\b/i,
|
|
1799
|
-
label: "provider CLI is missing or not on PATH"
|
|
1800
|
-
},
|
|
1801
|
-
{
|
|
1802
|
-
test: /\bfailed to spawn\b/i,
|
|
1803
|
-
label: "provider failed to spawn the worker process"
|
|
1804
|
-
},
|
|
1805
|
-
{
|
|
1806
|
-
test: /\b(?:not logged in|unauthorized|authentication (?:failed|required)|invalid api key|missing api key|401)\b/i,
|
|
1807
|
-
label: "provider authentication failed"
|
|
1808
|
-
}
|
|
1809
|
-
];
|
|
1810
1536
|
function tidy2(errorText, max = 240) {
|
|
1811
1537
|
const oneLine2 = errorText.replace(/\s+/g, " ").trim();
|
|
1812
1538
|
return oneLine2.length > max ? `${oneLine2.slice(0, max - 1)}\u2026` : oneLine2;
|
|
@@ -1819,8 +1545,44 @@ function classifyExitFailure(errorText) {
|
|
|
1819
1545
|
return { blocked: true, reason: `${pattern.label}: ${tidy2(text)}` };
|
|
1820
1546
|
}
|
|
1821
1547
|
}
|
|
1822
|
-
return null;
|
|
1823
|
-
}
|
|
1548
|
+
return null;
|
|
1549
|
+
}
|
|
1550
|
+
var FAILURE_PATTERNS;
|
|
1551
|
+
var init_exit_classify = __esm({
|
|
1552
|
+
"src/exit-classify.ts"() {
|
|
1553
|
+
"use strict";
|
|
1554
|
+
FAILURE_PATTERNS = [
|
|
1555
|
+
{
|
|
1556
|
+
test: /\b(?:invalid|unknown|unsupported|unrecognized)\b[^.\n]*\bmodel\b/i,
|
|
1557
|
+
label: "provider rejected the requested model"
|
|
1558
|
+
},
|
|
1559
|
+
{
|
|
1560
|
+
test: /\bmodel\b[^.\n]*\b(?:not\s+(?:found|supported|available|recognized|valid)|is\s+not\s+valid|does\s+not\s+exist)/i,
|
|
1561
|
+
label: "provider rejected the requested model"
|
|
1562
|
+
},
|
|
1563
|
+
{
|
|
1564
|
+
test: /\b(?:did you mean|available models|choose (?:a|one of)|supported models)\b/i,
|
|
1565
|
+
label: "provider rejected the requested model"
|
|
1566
|
+
},
|
|
1567
|
+
{
|
|
1568
|
+
test: /model preflight failed/i,
|
|
1569
|
+
label: "model/provider preflight failed"
|
|
1570
|
+
},
|
|
1571
|
+
{
|
|
1572
|
+
test: /\b(?:command not found|ENOENT|is the .*CLI on PATH|executable not found|no such file or directory)\b/i,
|
|
1573
|
+
label: "provider CLI is missing or not on PATH"
|
|
1574
|
+
},
|
|
1575
|
+
{
|
|
1576
|
+
test: /\bfailed to spawn\b/i,
|
|
1577
|
+
label: "provider failed to spawn the worker process"
|
|
1578
|
+
},
|
|
1579
|
+
{
|
|
1580
|
+
test: /\b(?:not logged in|unauthorized|authentication (?:failed|required)|invalid api key|missing api key|401)\b/i,
|
|
1581
|
+
label: "provider authentication failed"
|
|
1582
|
+
}
|
|
1583
|
+
];
|
|
1584
|
+
}
|
|
1585
|
+
});
|
|
1824
1586
|
|
|
1825
1587
|
// src/exited-salvage.ts
|
|
1826
1588
|
function trimOrNull(value) {
|
|
@@ -1879,6 +1641,11 @@ function assessExitedWorkerSalvage(input) {
|
|
|
1879
1641
|
attentionReason: buildAttentionReason(kind, uncommittedCount, headCommit)
|
|
1880
1642
|
};
|
|
1881
1643
|
}
|
|
1644
|
+
var init_exited_salvage = __esm({
|
|
1645
|
+
"src/exited-salvage.ts"() {
|
|
1646
|
+
"use strict";
|
|
1647
|
+
}
|
|
1648
|
+
});
|
|
1882
1649
|
|
|
1883
1650
|
// src/landing-gate.ts
|
|
1884
1651
|
function trimOrNull2(value) {
|
|
@@ -1924,6 +1691,11 @@ function landingAttentionReason(verdict) {
|
|
|
1924
1691
|
if (!verdict.blocked) return void 0;
|
|
1925
1692
|
return verdict.detail ?? verdict.reason ?? "dirty_worktree_no_pr";
|
|
1926
1693
|
}
|
|
1694
|
+
var init_landing_gate = __esm({
|
|
1695
|
+
"src/landing-gate.ts"() {
|
|
1696
|
+
"use strict";
|
|
1697
|
+
}
|
|
1698
|
+
});
|
|
1927
1699
|
|
|
1928
1700
|
// src/worker-final-result-embed.ts
|
|
1929
1701
|
function tryParseJsonObject2(text) {
|
|
@@ -1973,6 +1745,11 @@ function extractEmbeddedWorkerFinalResultRecord(value) {
|
|
|
1973
1745
|
}
|
|
1974
1746
|
return best;
|
|
1975
1747
|
}
|
|
1748
|
+
var init_worker_final_result_embed = __esm({
|
|
1749
|
+
"src/worker-final-result-embed.ts"() {
|
|
1750
|
+
"use strict";
|
|
1751
|
+
}
|
|
1752
|
+
});
|
|
1976
1753
|
|
|
1977
1754
|
// src/landing-contract-gate.ts
|
|
1978
1755
|
function trimOrNull3(value) {
|
|
@@ -2132,10 +1909,14 @@ function landingContractAttentionReason(verdict) {
|
|
|
2132
1909
|
if (!verdict.blocked) return void 0;
|
|
2133
1910
|
return verdict.detail ?? verdict.reason;
|
|
2134
1911
|
}
|
|
1912
|
+
var init_landing_contract_gate = __esm({
|
|
1913
|
+
"src/landing-contract-gate.ts"() {
|
|
1914
|
+
"use strict";
|
|
1915
|
+
init_worker_final_result_embed();
|
|
1916
|
+
}
|
|
1917
|
+
});
|
|
2135
1918
|
|
|
2136
1919
|
// src/status.ts
|
|
2137
|
-
var NO_START_MS = 18e4;
|
|
2138
|
-
var STALE_MS = 6e5;
|
|
2139
1920
|
function computeAttention(input) {
|
|
2140
1921
|
const now = Date.now();
|
|
2141
1922
|
if (input.completionBlocker && !isSkippedTerminalCompletionBlocker(input.completionBlocker)) {
|
|
@@ -2327,7 +2108,15 @@ function computeWorkerStatus(worker, options = {}) {
|
|
|
2327
2108
|
changedFiles,
|
|
2328
2109
|
gitAncestry,
|
|
2329
2110
|
instructionPolicyFingerprint: worker.instructionPolicyFingerprint ?? null,
|
|
2330
|
-
instructionPolicyEvidence: worker.instructionPolicyEvidence ?? null
|
|
2111
|
+
instructionPolicyEvidence: worker.instructionPolicyEvidence ?? null,
|
|
2112
|
+
model: worker.model ?? worker.orchestrationAudit?.model ?? null,
|
|
2113
|
+
provider: worker.orchestrationAudit?.provider ?? null,
|
|
2114
|
+
boxKind: worker.boxKind ?? null,
|
|
2115
|
+
boxId: worker.boxId ?? null,
|
|
2116
|
+
runtimeId: worker.runtimeId ?? null,
|
|
2117
|
+
personaSlug: worker.personaSlug ?? null,
|
|
2118
|
+
dispatched: worker.dispatched ?? null,
|
|
2119
|
+
localOnly: worker.localOnly ?? null
|
|
2331
2120
|
};
|
|
2332
2121
|
}
|
|
2333
2122
|
function isFinishedWorkerStatus(status) {
|
|
@@ -2349,8 +2138,26 @@ function deriveRunStatus(fallback, workers) {
|
|
|
2349
2138
|
if (workers.some((w) => w.status === "running")) return "running";
|
|
2350
2139
|
return fallback;
|
|
2351
2140
|
}
|
|
2141
|
+
var NO_START_MS, STALE_MS;
|
|
2142
|
+
var init_status = __esm({
|
|
2143
|
+
"src/status.ts"() {
|
|
2144
|
+
"use strict";
|
|
2145
|
+
init_heartbeat();
|
|
2146
|
+
init_stream();
|
|
2147
|
+
init_exit_classify();
|
|
2148
|
+
init_exited_salvage();
|
|
2149
|
+
init_git();
|
|
2150
|
+
init_landing_gate();
|
|
2151
|
+
init_landing_contract_gate();
|
|
2152
|
+
init_worker_final_result_embed();
|
|
2153
|
+
init_util();
|
|
2154
|
+
NO_START_MS = 18e4;
|
|
2155
|
+
STALE_MS = 6e5;
|
|
2156
|
+
}
|
|
2157
|
+
});
|
|
2352
2158
|
|
|
2353
2159
|
// src/harness-worker-active.ts
|
|
2160
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
2354
2161
|
function pidCommandLine(pid) {
|
|
2355
2162
|
if (!pid || process.platform !== "linux") return null;
|
|
2356
2163
|
try {
|
|
@@ -2376,12 +2183,16 @@ function isActiveHarnessWorker(worker) {
|
|
|
2376
2183
|
if (status.alive && !workerProcessMatchesRecord(worker)) return false;
|
|
2377
2184
|
return status.alive && !status.finalResult && status.attention.state !== "done";
|
|
2378
2185
|
}
|
|
2186
|
+
var init_harness_worker_active = __esm({
|
|
2187
|
+
"src/harness-worker-active.ts"() {
|
|
2188
|
+
"use strict";
|
|
2189
|
+
init_status();
|
|
2190
|
+
}
|
|
2191
|
+
});
|
|
2379
2192
|
|
|
2380
2193
|
// src/resource-gate.ts
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
var DEFAULT_MEM_UTILIZATION = 0.85;
|
|
2384
|
-
var AUTO_MAX_WORKERS_CEILING = 64;
|
|
2194
|
+
import os2 from "node:os";
|
|
2195
|
+
import path9 from "node:path";
|
|
2385
2196
|
function positiveInt(value, fallback) {
|
|
2386
2197
|
const n = Number(value);
|
|
2387
2198
|
if (!Number.isFinite(n) || n <= 0) return fallback;
|
|
@@ -2487,6 +2298,25 @@ function observeRunnerResourceGate(input) {
|
|
|
2487
2298
|
...diskGate ? { diskGate } : {}
|
|
2488
2299
|
};
|
|
2489
2300
|
}
|
|
2301
|
+
var DEFAULT_PER_WORKER_MEM_BYTES, DEFAULT_MEM_RESERVE_BYTES, DEFAULT_MEM_UTILIZATION, AUTO_MAX_WORKERS_CEILING;
|
|
2302
|
+
var init_resource_gate = __esm({
|
|
2303
|
+
"src/resource-gate.ts"() {
|
|
2304
|
+
"use strict";
|
|
2305
|
+
init_meminfo();
|
|
2306
|
+
init_config();
|
|
2307
|
+
init_box_identity();
|
|
2308
|
+
init_worker_cap_source();
|
|
2309
|
+
init_disk_gate();
|
|
2310
|
+
init_run_store();
|
|
2311
|
+
init_run_worker_index();
|
|
2312
|
+
init_harness_worker_active();
|
|
2313
|
+
init_util();
|
|
2314
|
+
DEFAULT_PER_WORKER_MEM_BYTES = 500 * 1024 * 1024;
|
|
2315
|
+
DEFAULT_MEM_RESERVE_BYTES = 4 * 1024 * 1024 * 1024;
|
|
2316
|
+
DEFAULT_MEM_UTILIZATION = 0.85;
|
|
2317
|
+
AUTO_MAX_WORKERS_CEILING = 64;
|
|
2318
|
+
}
|
|
2319
|
+
});
|
|
2490
2320
|
|
|
2491
2321
|
// src/worker-cap-source.ts
|
|
2492
2322
|
function positiveInt2(value, fallback) {
|
|
@@ -2534,357 +2364,819 @@ function resolveWorkerCap(input) {
|
|
|
2534
2364
|
workerCapSource: "env"
|
|
2535
2365
|
};
|
|
2536
2366
|
}
|
|
2537
|
-
return {
|
|
2538
|
-
configuredMaxWorkers: null,
|
|
2539
|
-
autoCap,
|
|
2540
|
-
workerCapSource: "auto"
|
|
2541
|
-
};
|
|
2367
|
+
return {
|
|
2368
|
+
configuredMaxWorkers: null,
|
|
2369
|
+
autoCap,
|
|
2370
|
+
workerCapSource: "auto"
|
|
2371
|
+
};
|
|
2372
|
+
}
|
|
2373
|
+
function recommendSetupWorkerCap(input = {}) {
|
|
2374
|
+
const totalMemBytes = input.totalMemBytes ?? 0;
|
|
2375
|
+
const autoCap = computeAutoMaxWorkers(totalMemBytes, {
|
|
2376
|
+
perWorkerMemBytes: positiveInt2(input.config?.perWorkerMemBytes, DEFAULT_PER_WORKER_MEM_BYTES),
|
|
2377
|
+
memReserveBytes: positiveInt2(input.config?.memReserveBytes, DEFAULT_MEM_RESERVE_BYTES),
|
|
2378
|
+
memUtilization: input.config?.memUtilization && Number(input.config.memUtilization) > 0 ? Number(input.config.memUtilization) : DEFAULT_MEM_UTILIZATION
|
|
2379
|
+
});
|
|
2380
|
+
const diskGateOk = input.diskGateOk ?? true;
|
|
2381
|
+
const recommendedMaxWorkers = diskGateOk ? autoCap : Math.max(1, Math.min(autoCap, 4));
|
|
2382
|
+
return {
|
|
2383
|
+
totalMemBytes,
|
|
2384
|
+
autoCap,
|
|
2385
|
+
recommendedMaxWorkers,
|
|
2386
|
+
diskPath: input.diskPath ?? "/",
|
|
2387
|
+
diskGateOk,
|
|
2388
|
+
diskFreeBytes: input.diskFreeBytes ?? null
|
|
2389
|
+
};
|
|
2390
|
+
}
|
|
2391
|
+
var init_worker_cap_source = __esm({
|
|
2392
|
+
"src/worker-cap-source.ts"() {
|
|
2393
|
+
"use strict";
|
|
2394
|
+
init_resource_gate();
|
|
2395
|
+
}
|
|
2396
|
+
});
|
|
2397
|
+
|
|
2398
|
+
// src/device-login.ts
|
|
2399
|
+
var device_login_exports = {};
|
|
2400
|
+
__export(device_login_exports, {
|
|
2401
|
+
runDeviceLogin: () => runDeviceLogin
|
|
2402
|
+
});
|
|
2403
|
+
import os3 from "node:os";
|
|
2404
|
+
function resolveDeviceBaseUrl(args) {
|
|
2405
|
+
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;
|
|
2406
|
+
return raw ? trimTrailingSlash(String(raw)) : void 0;
|
|
2407
|
+
}
|
|
2408
|
+
async function sleep(ms) {
|
|
2409
|
+
await new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
2410
|
+
}
|
|
2411
|
+
async function runDeviceLogin(args) {
|
|
2412
|
+
const base = resolveDeviceBaseUrl(args);
|
|
2413
|
+
if (!base) {
|
|
2414
|
+
console.error(
|
|
2415
|
+
"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."
|
|
2416
|
+
);
|
|
2417
|
+
return { ok: false };
|
|
2418
|
+
}
|
|
2419
|
+
const clientName = `${os3.hostname()} (${os3.platform()})`;
|
|
2420
|
+
let start;
|
|
2421
|
+
try {
|
|
2422
|
+
const res = await fetch(`${base}/api/auth/device/code`, {
|
|
2423
|
+
method: "POST",
|
|
2424
|
+
headers: { "Content-Type": "application/json" },
|
|
2425
|
+
body: JSON.stringify({ clientName })
|
|
2426
|
+
});
|
|
2427
|
+
if (!res.ok) {
|
|
2428
|
+
console.error(`Could not start device authorization (${res.status}).`);
|
|
2429
|
+
return { ok: false };
|
|
2430
|
+
}
|
|
2431
|
+
start = await res.json();
|
|
2432
|
+
} catch (err) {
|
|
2433
|
+
console.error(`Could not reach ${base}: ${err.message}`);
|
|
2434
|
+
return { ok: false };
|
|
2435
|
+
}
|
|
2436
|
+
const verifyUrl = start.verification_uri_complete || start.verification_uri;
|
|
2437
|
+
console.log("");
|
|
2438
|
+
console.log(" Authorize this machine:");
|
|
2439
|
+
console.log(` 1. Open: ${verifyUrl}`);
|
|
2440
|
+
console.log(` 2. Confirm the code: ${start.user_code}`);
|
|
2441
|
+
console.log("");
|
|
2442
|
+
console.log(" Waiting for approval\u2026");
|
|
2443
|
+
const deadline = Date.now() + start.expires_in * 1e3;
|
|
2444
|
+
let intervalMs = Math.max(1, start.interval) * 1e3;
|
|
2445
|
+
while (Date.now() < deadline) {
|
|
2446
|
+
await sleep(intervalMs);
|
|
2447
|
+
let body;
|
|
2448
|
+
try {
|
|
2449
|
+
const res = await fetch(`${base}/api/auth/device/token`, {
|
|
2450
|
+
method: "POST",
|
|
2451
|
+
headers: { "Content-Type": "application/json" },
|
|
2452
|
+
body: JSON.stringify({ device_code: start.device_code })
|
|
2453
|
+
});
|
|
2454
|
+
body = await res.json().catch(() => ({}));
|
|
2455
|
+
} catch {
|
|
2456
|
+
continue;
|
|
2457
|
+
}
|
|
2458
|
+
switch (body.status) {
|
|
2459
|
+
case "approved":
|
|
2460
|
+
if (body.api_key) {
|
|
2461
|
+
saveApiKey(body.api_key);
|
|
2462
|
+
console.log(" Approved \u2014 this machine is now linked to your Kynver account.");
|
|
2463
|
+
return { ok: true, apiKey: body.api_key };
|
|
2464
|
+
}
|
|
2465
|
+
return { ok: false };
|
|
2466
|
+
case "slow_down":
|
|
2467
|
+
intervalMs += 2e3;
|
|
2468
|
+
break;
|
|
2469
|
+
case "authorization_pending":
|
|
2470
|
+
if (typeof body.interval === "number") intervalMs = Math.max(intervalMs, body.interval * 1e3);
|
|
2471
|
+
break;
|
|
2472
|
+
case "access_denied":
|
|
2473
|
+
console.error(" Request was denied in the browser.");
|
|
2474
|
+
return { ok: false };
|
|
2475
|
+
case "expired_token":
|
|
2476
|
+
console.error(" The code expired before it was approved. Run `kynver login` again.");
|
|
2477
|
+
return { ok: false };
|
|
2478
|
+
default:
|
|
2479
|
+
break;
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
console.error(" Timed out waiting for approval. Run `kynver login` again.");
|
|
2483
|
+
return { ok: false };
|
|
2484
|
+
}
|
|
2485
|
+
var init_device_login = __esm({
|
|
2486
|
+
"src/device-login.ts"() {
|
|
2487
|
+
"use strict";
|
|
2488
|
+
init_config();
|
|
2489
|
+
init_util();
|
|
2490
|
+
}
|
|
2491
|
+
});
|
|
2492
|
+
|
|
2493
|
+
// src/config.ts
|
|
2494
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync2, readFileSync as readFileSync10, writeFileSync as writeFileSync2 } from "node:fs";
|
|
2495
|
+
import { homedir as homedir5, totalmem } from "node:os";
|
|
2496
|
+
import path10 from "node:path";
|
|
2497
|
+
import os4 from "node:os";
|
|
2498
|
+
function loadUserConfig() {
|
|
2499
|
+
if (!existsSync11(CONFIG_FILE)) return {};
|
|
2500
|
+
try {
|
|
2501
|
+
return JSON.parse(readFileSync10(CONFIG_FILE, "utf8"));
|
|
2502
|
+
} catch {
|
|
2503
|
+
return {};
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
function saveUserConfig(config) {
|
|
2507
|
+
mkdirSync2(CONFIG_DIR, { recursive: true });
|
|
2508
|
+
writeFileSync2(CONFIG_FILE, `${JSON.stringify(normalizeConfigPaths(config), null, 2)}
|
|
2509
|
+
`, { mode: 384 });
|
|
2510
|
+
}
|
|
2511
|
+
function normalizeConfigPaths(config) {
|
|
2512
|
+
return {
|
|
2513
|
+
...config,
|
|
2514
|
+
...config.harnessRoot?.trim() ? { harnessRoot: redactHomePath(config.harnessRoot.trim()) } : {},
|
|
2515
|
+
...config.defaultRepo?.trim() ? { defaultRepo: redactHomePath(config.defaultRepo.trim()) } : {}
|
|
2516
|
+
};
|
|
2517
|
+
}
|
|
2518
|
+
function presentUserConfig(config) {
|
|
2519
|
+
return normalizeConfigPaths(config);
|
|
2520
|
+
}
|
|
2521
|
+
function inferSetupFields(existing, args) {
|
|
2522
|
+
const creds = loadCredentialsFile();
|
|
2523
|
+
const apiBaseUrl = (typeof args.apiBaseUrl === "string" ? args.apiBaseUrl : void 0) || existing.apiBaseUrl?.trim() || process.env.KYNVER_API_URL?.trim() || process.env.KYNVER_CRON_FIRE_BASE_URL?.trim() || process.env.OPENCLAW_CRON_FIRE_BASE_URL?.trim();
|
|
2524
|
+
const agentOsId = (typeof args.agentOsId === "string" ? args.agentOsId : void 0) || existing.agentOsId?.trim() || process.env.KYNVER_AGENT_OS_ID?.trim() || (creds.runnerToken?.trim().startsWith("krc1.") ? creds.runnerTokenAgentOsId?.trim() : void 0);
|
|
2525
|
+
const explicitRepo = typeof args.repo === "string" ? args.repo : args.discoverRepo === true || args.discoverRepo === "true" ? discoverDefaultRepo()?.repo : void 0;
|
|
2526
|
+
const defaultRepo = explicitRepo || existing.defaultRepo?.trim() || process.env.KYNVER_DEFAULT_REPO?.trim() || process.env.KYNVER_HARNESS_REPO?.trim() || discoverDefaultRepo()?.repo;
|
|
2527
|
+
const harnessRoot = (typeof args.harnessRoot === "string" ? args.harnessRoot : void 0) || existing.harnessRoot?.trim() || process.env.KYNVER_HARNESS_ROOT?.trim() || process.env.OPUS_HARNESS_ROOT?.trim();
|
|
2528
|
+
return {
|
|
2529
|
+
...apiBaseUrl ? { apiBaseUrl: trimTrailingSlash(apiBaseUrl) } : {},
|
|
2530
|
+
...agentOsId ? { agentOsId } : {},
|
|
2531
|
+
...defaultRepo ? { defaultRepo } : {},
|
|
2532
|
+
...harnessRoot ? { harnessRoot } : {},
|
|
2533
|
+
...typeof args.agentOsSlug === "string" ? { agentOsSlug: args.agentOsSlug } : existing.agentOsSlug ? { agentOsSlug: existing.agentOsSlug } : {}
|
|
2534
|
+
};
|
|
2535
|
+
}
|
|
2536
|
+
function resolveSetupWorkerConfig(existing, args, totalMemBytes = totalmem()) {
|
|
2537
|
+
const maxWorkersRaw = typeof args.maxWorkers === "string" ? args.maxWorkers : typeof args.maxConcurrentWorkers === "string" ? args.maxConcurrentWorkers : void 0;
|
|
2538
|
+
const explicitBoxKindArg = typeof args.boxKind === "string" ? args.boxKind : typeof args["box-kind"] === "string" ? String(args["box-kind"]) : void 0;
|
|
2539
|
+
const boxKind = resolveBoxIdentity(process.env, {
|
|
2540
|
+
...existing,
|
|
2541
|
+
...explicitBoxKindArg ? { boxKind: normalizeWorkerPoolBoxKind(explicitBoxKindArg) } : {}
|
|
2542
|
+
}).boxKind;
|
|
2543
|
+
const diskGate = observeRunnerDiskGate({
|
|
2544
|
+
diskPath: typeof args.diskPath === "string" ? args.diskPath : "/"
|
|
2545
|
+
});
|
|
2546
|
+
const capRecommendation = recommendSetupWorkerCap({
|
|
2547
|
+
totalMemBytes,
|
|
2548
|
+
diskPath: diskGate.path,
|
|
2549
|
+
diskGateOk: diskGate.ok,
|
|
2550
|
+
diskFreeBytes: diskGate.freeBytes,
|
|
2551
|
+
config: existing
|
|
2552
|
+
});
|
|
2553
|
+
if (maxWorkersRaw) {
|
|
2554
|
+
return {
|
|
2555
|
+
maxConcurrentWorkers: Math.max(1, Math.floor(Number(maxWorkersRaw))),
|
|
2556
|
+
maxConcurrentWorkersSource: "setup-flag",
|
|
2557
|
+
boxKind
|
|
2558
|
+
};
|
|
2559
|
+
}
|
|
2560
|
+
if (existing.maxConcurrentWorkers !== void 0 && existing.maxConcurrentWorkers !== null) {
|
|
2561
|
+
return {
|
|
2562
|
+
maxConcurrentWorkers: Math.max(1, Math.floor(Number(existing.maxConcurrentWorkers))),
|
|
2563
|
+
maxConcurrentWorkersSource: existing.maxConcurrentWorkersSource ?? "operator",
|
|
2564
|
+
boxKind
|
|
2565
|
+
};
|
|
2566
|
+
}
|
|
2567
|
+
return {
|
|
2568
|
+
maxConcurrentWorkers: capRecommendation.recommendedMaxWorkers,
|
|
2569
|
+
maxConcurrentWorkersSource: "setup-auto",
|
|
2570
|
+
boxKind
|
|
2571
|
+
};
|
|
2572
|
+
}
|
|
2573
|
+
function loadCredentialsFile() {
|
|
2574
|
+
if (!existsSync11(CREDENTIALS_FILE)) return {};
|
|
2575
|
+
try {
|
|
2576
|
+
return JSON.parse(readFileSync10(CREDENTIALS_FILE, "utf8"));
|
|
2577
|
+
} catch {
|
|
2578
|
+
return {};
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
function saveCredentialsFile(parsed) {
|
|
2582
|
+
mkdirSync2(CONFIG_DIR, { recursive: true });
|
|
2583
|
+
writeFileSync2(CREDENTIALS_FILE, `${JSON.stringify(parsed, null, 2)}
|
|
2584
|
+
`, { mode: 384 });
|
|
2585
|
+
}
|
|
2586
|
+
function loadApiKey() {
|
|
2587
|
+
if (process.env.KYNVER_API_KEY) return process.env.KYNVER_API_KEY;
|
|
2588
|
+
return loadCredentialsFile().apiKey;
|
|
2589
|
+
}
|
|
2590
|
+
function saveApiKey(apiKey) {
|
|
2591
|
+
saveCredentialsFile({ ...loadCredentialsFile(), apiKey });
|
|
2592
|
+
}
|
|
2593
|
+
function loadRunnerToken(agentOsId) {
|
|
2594
|
+
const envToken = process.env.KYNVER_RUNNER_TOKEN?.trim();
|
|
2595
|
+
if (envToken) return envToken;
|
|
2596
|
+
const creds = loadCredentialsFile();
|
|
2597
|
+
if (!creds.runnerToken) return void 0;
|
|
2598
|
+
if (agentOsId && creds.runnerTokenAgentOsId && creds.runnerTokenAgentOsId !== agentOsId) {
|
|
2599
|
+
return void 0;
|
|
2600
|
+
}
|
|
2601
|
+
return creds.runnerToken;
|
|
2602
|
+
}
|
|
2603
|
+
function saveRunnerToken(agentOsId, token) {
|
|
2604
|
+
saveCredentialsFile({
|
|
2605
|
+
...loadCredentialsFile(),
|
|
2606
|
+
runnerToken: token,
|
|
2607
|
+
runnerTokenAgentOsId: agentOsId
|
|
2608
|
+
});
|
|
2609
|
+
}
|
|
2610
|
+
function resolveBaseUrl(argsBaseUrl) {
|
|
2611
|
+
const baseUrl = resolveConfiguredBaseUrl(argsBaseUrl);
|
|
2612
|
+
if (!baseUrl) failConfig("requires --base-url, KYNVER_API_URL, KYNVER_CRON_FIRE_BASE_URL, or ~/.kynver/config.json apiBaseUrl");
|
|
2613
|
+
return baseUrl;
|
|
2614
|
+
}
|
|
2615
|
+
function resolveConfiguredBaseUrl(argsBaseUrl) {
|
|
2616
|
+
const baseUrl = argsBaseUrl || process.env.KYNVER_API_URL || process.env.KYNVER_CRON_FIRE_BASE_URL || process.env.OPENCLAW_CRON_FIRE_BASE_URL || loadUserConfig().apiBaseUrl;
|
|
2617
|
+
return baseUrl ? trimTrailingSlash(String(baseUrl)) : void 0;
|
|
2618
|
+
}
|
|
2619
|
+
function resolveConfiguredCallbackSecret(argsSecret, agentOsId) {
|
|
2620
|
+
const scoped = argsSecret || loadRunnerToken(agentOsId) || (agentOsId ? void 0 : loadRunnerToken(loadUserConfig().agentOsId));
|
|
2621
|
+
if (scoped) return String(scoped);
|
|
2622
|
+
const globalSecret = process.env.KYNVER_RUNTIME_SECRET || process.env.KYNVER_CRON_SECRET || process.env.OPENCLAW_CRON_SECRET;
|
|
2623
|
+
if (globalSecret) {
|
|
2624
|
+
console.warn(
|
|
2625
|
+
"[kynver] using deployment-level callback secret; run `kynver runner credential --agent-os-id <id>` for a scoped token"
|
|
2626
|
+
);
|
|
2627
|
+
return String(globalSecret);
|
|
2628
|
+
}
|
|
2629
|
+
return void 0;
|
|
2630
|
+
}
|
|
2631
|
+
function resolveCallbackSecret(argsSecret, agentOsId) {
|
|
2632
|
+
const configured = resolveConfiguredCallbackSecret(argsSecret, agentOsId);
|
|
2633
|
+
if (configured) return configured;
|
|
2634
|
+
failConfig(
|
|
2635
|
+
"requires --secret, KYNVER_RUNNER_TOKEN, a scoped runner token (`kynver runner credential`), ~/.kynver/credentials runnerToken, KYNVER_API_KEY with an API base URL to mint one, or (legacy) KYNVER_RUNTIME_SECRET / KYNVER_CRON_SECRET / OPENCLAW_CRON_SECRET"
|
|
2636
|
+
);
|
|
2637
|
+
}
|
|
2638
|
+
async function resolveCallbackSecretWithMint(argsSecret, agentOsId, opts) {
|
|
2639
|
+
const configured = resolveConfiguredCallbackSecret(argsSecret, agentOsId);
|
|
2640
|
+
if (configured) return configured;
|
|
2641
|
+
const apiKey = loadApiKey();
|
|
2642
|
+
const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
|
|
2643
|
+
if (apiKey && agentOsId && baseUrl) {
|
|
2644
|
+
try {
|
|
2645
|
+
const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
|
|
2646
|
+
saveRunnerToken(agentOsId, token);
|
|
2647
|
+
return token;
|
|
2648
|
+
} catch (error) {
|
|
2649
|
+
failConfig(`runner credential mint failed: ${error.message}`);
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
failConfig(
|
|
2653
|
+
"requires --secret, KYNVER_RUNNER_TOKEN, a scoped runner token (`kynver runner credential`), ~/.kynver/credentials runnerToken, KYNVER_API_KEY with an API base URL to mint one, or (legacy) KYNVER_RUNTIME_SECRET / KYNVER_CRON_SECRET / OPENCLAW_CRON_SECRET"
|
|
2654
|
+
);
|
|
2655
|
+
}
|
|
2656
|
+
async function refreshRunnerToken(agentOsId, opts) {
|
|
2657
|
+
const apiKey = loadApiKey();
|
|
2658
|
+
const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
|
|
2659
|
+
if (!apiKey || !agentOsId || !baseUrl) return null;
|
|
2660
|
+
try {
|
|
2661
|
+
const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
|
|
2662
|
+
saveRunnerToken(agentOsId, token);
|
|
2663
|
+
return token;
|
|
2664
|
+
} catch {
|
|
2665
|
+
return null;
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
async function refreshRunnerTokenForAuthFailure(rejectedSecret, agentOsId, opts) {
|
|
2669
|
+
const apiKey = loadApiKey();
|
|
2670
|
+
const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
|
|
2671
|
+
if (!apiKey) return { ok: false, reason: "KYNVER_API_KEY is required to refresh a rejected runner token" };
|
|
2672
|
+
if (!agentOsId) return { ok: false, reason: "agentOsId is required to refresh a rejected runner token" };
|
|
2673
|
+
if (!baseUrl) return { ok: false, reason: "KYNVER_API_URL or --base-url is required to refresh a rejected runner token" };
|
|
2674
|
+
try {
|
|
2675
|
+
const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
|
|
2676
|
+
if (token && token !== rejectedSecret) {
|
|
2677
|
+
saveRunnerToken(agentOsId, token);
|
|
2678
|
+
return { ok: true, token };
|
|
2679
|
+
}
|
|
2680
|
+
return { ok: false, reason: "runner credential refresh returned the rejected token" };
|
|
2681
|
+
} catch (error) {
|
|
2682
|
+
return { ok: false, reason: error.message };
|
|
2683
|
+
}
|
|
2542
2684
|
}
|
|
2543
|
-
function
|
|
2544
|
-
const
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2685
|
+
async function fetchRunnerCredential(agentOsId, opts) {
|
|
2686
|
+
const apiKey = opts?.apiKey || loadApiKey();
|
|
2687
|
+
if (!apiKey) throw new Error("API key required \u2014 run `kynver login` first");
|
|
2688
|
+
const base = resolveBaseUrl(opts?.baseUrl);
|
|
2689
|
+
const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/runner-credentials`;
|
|
2690
|
+
const res = await fetch(url, {
|
|
2691
|
+
method: "POST",
|
|
2692
|
+
headers: {
|
|
2693
|
+
"Content-Type": "application/json",
|
|
2694
|
+
Authorization: `Bearer ${apiKey}`
|
|
2695
|
+
},
|
|
2696
|
+
body: JSON.stringify({})
|
|
2549
2697
|
});
|
|
2550
|
-
const
|
|
2551
|
-
|
|
2552
|
-
return {
|
|
2553
|
-
totalMemBytes,
|
|
2554
|
-
autoCap,
|
|
2555
|
-
recommendedMaxWorkers,
|
|
2556
|
-
diskPath: input.diskPath ?? "/",
|
|
2557
|
-
diskGateOk,
|
|
2558
|
-
diskFreeBytes: input.diskFreeBytes ?? null
|
|
2559
|
-
};
|
|
2560
|
-
}
|
|
2561
|
-
|
|
2562
|
-
// src/config.ts
|
|
2563
|
-
import os3 from "node:os";
|
|
2564
|
-
var CONFIG_DIR = path10.join(homedir5(), ".kynver");
|
|
2565
|
-
var CONFIG_FILE = path10.join(CONFIG_DIR, "config.json");
|
|
2566
|
-
var CREDENTIALS_FILE = path10.join(CONFIG_DIR, "credentials");
|
|
2567
|
-
function loadUserConfig() {
|
|
2568
|
-
if (!existsSync11(CONFIG_FILE)) return {};
|
|
2698
|
+
const text = await res.text();
|
|
2699
|
+
let parsed = null;
|
|
2569
2700
|
try {
|
|
2570
|
-
|
|
2701
|
+
parsed = JSON.parse(text);
|
|
2571
2702
|
} catch {
|
|
2572
|
-
|
|
2703
|
+
parsed = null;
|
|
2573
2704
|
}
|
|
2705
|
+
if (!res.ok || !parsed?.token) {
|
|
2706
|
+
throw new Error(
|
|
2707
|
+
`runner credential mint failed (${res.status}): ${parsed?.error ?? text.slice(0, 200)}`
|
|
2708
|
+
);
|
|
2709
|
+
}
|
|
2710
|
+
return parsed.token;
|
|
2574
2711
|
}
|
|
2575
|
-
function
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2712
|
+
async function mintRunnerCredential(args) {
|
|
2713
|
+
const agentOsId = (args.agentOsId ? String(args.agentOsId) : loadUserConfig().agentOsId) || "";
|
|
2714
|
+
if (!agentOsId) failConfig("runner credential requires --agent-os-id or agentOsId in ~/.kynver/config.json");
|
|
2715
|
+
try {
|
|
2716
|
+
const token = await fetchRunnerCredential(agentOsId, {
|
|
2717
|
+
baseUrl: args.baseUrl ? String(args.baseUrl) : void 0
|
|
2718
|
+
});
|
|
2719
|
+
saveRunnerToken(agentOsId, token);
|
|
2720
|
+
console.log(
|
|
2721
|
+
JSON.stringify(
|
|
2722
|
+
{
|
|
2723
|
+
ok: true,
|
|
2724
|
+
agentOsId,
|
|
2725
|
+
credentialsPath: displayUserPath(CREDENTIALS_FILE),
|
|
2726
|
+
tokenPrefix: `${token.slice(0, 12)}\u2026`,
|
|
2727
|
+
note: "Scoped runner token saved; callbacks use X-Kynver-Runner-Token."
|
|
2728
|
+
},
|
|
2729
|
+
null,
|
|
2730
|
+
2
|
|
2731
|
+
)
|
|
2732
|
+
);
|
|
2733
|
+
} catch (err) {
|
|
2734
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
2735
|
+
process.exit(1);
|
|
2736
|
+
}
|
|
2586
2737
|
}
|
|
2587
|
-
function
|
|
2588
|
-
|
|
2738
|
+
function failConfig(message) {
|
|
2739
|
+
console.error(message);
|
|
2740
|
+
process.exit(1);
|
|
2589
2741
|
}
|
|
2590
|
-
function
|
|
2591
|
-
const
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2742
|
+
function parseArgs(argv) {
|
|
2743
|
+
const args = {};
|
|
2744
|
+
for (let i = 0; i < argv.length; i++) {
|
|
2745
|
+
const item = argv[i];
|
|
2746
|
+
if (!item.startsWith("--")) continue;
|
|
2747
|
+
const key = item.slice(2).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
2748
|
+
const next = argv[i + 1];
|
|
2749
|
+
if (!next || next.startsWith("--")) args[key] = true;
|
|
2750
|
+
else {
|
|
2751
|
+
args[key] = next;
|
|
2752
|
+
i++;
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
return args;
|
|
2604
2756
|
}
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
function resolveSetupWorkerConfig(existing, args, totalMemBytes = totalmem()) {
|
|
2608
|
-
const maxWorkersRaw = typeof args.maxWorkers === "string" ? args.maxWorkers : typeof args.maxConcurrentWorkers === "string" ? args.maxConcurrentWorkers : void 0;
|
|
2609
|
-
const explicitBoxKindArg = typeof args.boxKind === "string" ? args.boxKind : typeof args["box-kind"] === "string" ? String(args["box-kind"]) : void 0;
|
|
2610
|
-
const boxKind = resolveBoxIdentity(process.env, {
|
|
2611
|
-
...existing,
|
|
2612
|
-
...explicitBoxKindArg ? { boxKind: normalizeWorkerPoolBoxKind(explicitBoxKindArg) } : {}
|
|
2613
|
-
}).boxKind;
|
|
2757
|
+
async function runSetup(args) {
|
|
2758
|
+
const existing = loadUserConfig();
|
|
2614
2759
|
const diskGate = observeRunnerDiskGate({
|
|
2615
2760
|
diskPath: typeof args.diskPath === "string" ? args.diskPath : "/"
|
|
2616
2761
|
});
|
|
2617
2762
|
const capRecommendation = recommendSetupWorkerCap({
|
|
2618
|
-
totalMemBytes,
|
|
2763
|
+
totalMemBytes: os4.totalmem(),
|
|
2619
2764
|
diskPath: diskGate.path,
|
|
2620
2765
|
diskGateOk: diskGate.ok,
|
|
2621
2766
|
diskFreeBytes: diskGate.freeBytes,
|
|
2622
2767
|
config: existing
|
|
2623
2768
|
});
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2769
|
+
const workerConfig = resolveSetupWorkerConfig(existing, args);
|
|
2770
|
+
const config = normalizeConfigPaths({
|
|
2771
|
+
...existing,
|
|
2772
|
+
...inferSetupFields(existing, args),
|
|
2773
|
+
...workerConfig,
|
|
2774
|
+
workerProvider: typeof args.provider === "string" ? args.provider : existing.workerProvider || "cursor"
|
|
2775
|
+
});
|
|
2776
|
+
saveUserConfig(config);
|
|
2777
|
+
const boxIdentity = resolveBoxIdentity(process.env, config);
|
|
2778
|
+
let runnerCredentialNote;
|
|
2779
|
+
const apiKey = loadApiKey();
|
|
2780
|
+
const agentOsId = config.agentOsId;
|
|
2781
|
+
if (apiKey && agentOsId) {
|
|
2782
|
+
try {
|
|
2783
|
+
const token = await fetchRunnerCredential(agentOsId, {
|
|
2784
|
+
baseUrl: typeof args.apiBaseUrl === "string" ? args.apiBaseUrl : config.apiBaseUrl,
|
|
2785
|
+
apiKey
|
|
2786
|
+
});
|
|
2787
|
+
saveRunnerToken(agentOsId, token);
|
|
2788
|
+
runnerCredentialNote = "Scoped runner token minted and saved to ~/.kynver/credentials.";
|
|
2789
|
+
} catch {
|
|
2790
|
+
runnerCredentialNote = "Runner token not minted (server offline or master secret unset). Run `kynver runner credential` after deploy.";
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
console.log(
|
|
2794
|
+
JSON.stringify(
|
|
2795
|
+
{
|
|
2796
|
+
ok: true,
|
|
2797
|
+
configPath: displayUserPath(CONFIG_FILE),
|
|
2798
|
+
config: presentUserConfig(config),
|
|
2799
|
+
boxKind: config.boxKind,
|
|
2800
|
+
boxKindSource: boxIdentity.source,
|
|
2801
|
+
workerCapRecommendation: capRecommendation,
|
|
2802
|
+
...boxIdentity.warnings.length ? { boxIdentityWarnings: boxIdentity.warnings } : {},
|
|
2803
|
+
note: runnerCredentialNote ?? "boxKind and maxConcurrentWorkers persisted; override with --box-kind and --max-workers. Run `kynver login` + `kynver runner credential` for scoped callbacks."
|
|
2804
|
+
},
|
|
2805
|
+
null,
|
|
2806
|
+
2
|
|
2807
|
+
)
|
|
2808
|
+
);
|
|
2809
|
+
}
|
|
2810
|
+
async function runLogin(args) {
|
|
2811
|
+
const apiKey = typeof args.apiKey === "string" ? args.apiKey : process.env.KYNVER_API_KEY;
|
|
2812
|
+
if (apiKey) {
|
|
2813
|
+
saveApiKey(apiKey);
|
|
2814
|
+
console.log(JSON.stringify({ ok: true, credentialsPath: displayUserPath(CREDENTIALS_FILE) }, null, 2));
|
|
2815
|
+
return;
|
|
2816
|
+
}
|
|
2817
|
+
const { runDeviceLogin: runDeviceLogin2 } = await Promise.resolve().then(() => (init_device_login(), device_login_exports));
|
|
2818
|
+
const result = await runDeviceLogin2(args);
|
|
2819
|
+
if (!result.ok) process.exit(1);
|
|
2820
|
+
console.log(JSON.stringify({ ok: true, credentialsPath: displayUserPath(CREDENTIALS_FILE) }, null, 2));
|
|
2821
|
+
}
|
|
2822
|
+
var CONFIG_DIR, CONFIG_FILE, CREDENTIALS_FILE, SETUP_PER_WORKER_MEM_BYTES, SETUP_MEM_RESERVE_BYTES;
|
|
2823
|
+
var init_config = __esm({
|
|
2824
|
+
"src/config.ts"() {
|
|
2825
|
+
"use strict";
|
|
2826
|
+
init_default_repo_discovery();
|
|
2827
|
+
init_path_values();
|
|
2828
|
+
init_util();
|
|
2829
|
+
init_box_identity();
|
|
2830
|
+
init_worker_cap_source();
|
|
2831
|
+
init_disk_gate();
|
|
2832
|
+
CONFIG_DIR = path10.join(homedir5(), ".kynver");
|
|
2833
|
+
CONFIG_FILE = path10.join(CONFIG_DIR, "config.json");
|
|
2834
|
+
CREDENTIALS_FILE = path10.join(CONFIG_DIR, "credentials");
|
|
2835
|
+
SETUP_PER_WORKER_MEM_BYTES = 500 * 1024 * 1024;
|
|
2836
|
+
SETUP_MEM_RESERVE_BYTES = 4 * 1024 * 1024 * 1024;
|
|
2837
|
+
}
|
|
2838
|
+
});
|
|
2839
|
+
|
|
2840
|
+
// src/package-version.ts
|
|
2841
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2842
|
+
import { dirname, join } from "node:path";
|
|
2843
|
+
import { fileURLToPath } from "node:url";
|
|
2844
|
+
function resolvePackageRoot(moduleUrl) {
|
|
2845
|
+
let dir = dirname(fileURLToPath(moduleUrl));
|
|
2846
|
+
for (let depth = 0; depth < 6; depth += 1) {
|
|
2847
|
+
if (existsSync(join(dir, "package.json"))) return dir;
|
|
2848
|
+
const parent = dirname(dir);
|
|
2849
|
+
if (parent === dir) break;
|
|
2850
|
+
dir = parent;
|
|
2851
|
+
}
|
|
2852
|
+
throw new Error(`package.json not found above ${dirname(fileURLToPath(moduleUrl))}`);
|
|
2853
|
+
}
|
|
2854
|
+
function readOwnPackageVersion(moduleUrl = import.meta.url) {
|
|
2855
|
+
const pkgPath = join(resolvePackageRoot(moduleUrl), "package.json");
|
|
2856
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
2857
|
+
if (typeof pkg.version !== "string" || !pkg.version.trim()) {
|
|
2858
|
+
throw new Error(`Missing package.json version at ${pkgPath}`);
|
|
2859
|
+
}
|
|
2860
|
+
return pkg.version;
|
|
2861
|
+
}
|
|
2862
|
+
var PACKAGE_VERSION = readOwnPackageVersion();
|
|
2863
|
+
function wantsCliVersion(argv) {
|
|
2864
|
+
return argv.some((arg) => arg === "--version" || arg === "-v");
|
|
2865
|
+
}
|
|
2866
|
+
function printCliVersionAndExit(version, binName) {
|
|
2867
|
+
console.log(binName ? `${binName} ${version}` : version);
|
|
2868
|
+
process.exit(0);
|
|
2869
|
+
}
|
|
2870
|
+
function handleCliVersionFlag(argv, moduleUrl = import.meta.url, binName) {
|
|
2871
|
+
if (!wantsCliVersion(argv)) return false;
|
|
2872
|
+
printCliVersionAndExit(readOwnPackageVersion(moduleUrl), binName);
|
|
2873
|
+
return true;
|
|
2874
|
+
}
|
|
2875
|
+
|
|
2876
|
+
// src/memory-cost-package-version-guard.ts
|
|
2877
|
+
init_default_repo_discovery();
|
|
2878
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
2879
|
+
import path4 from "node:path";
|
|
2880
|
+
var MEMORY_COST_PACKAGE_MIN_VERSIONS = {
|
|
2881
|
+
"@kynver-app/runtime": "0.1.83",
|
|
2882
|
+
"@kynver-app/openclaw-agent-os": "0.1.43",
|
|
2883
|
+
"@kynver-app/mcp-agent-os": "0.3.34"
|
|
2884
|
+
};
|
|
2885
|
+
var MEMORY_COST_MANAGED_PACKAGES = Object.keys(
|
|
2886
|
+
MEMORY_COST_PACKAGE_MIN_VERSIONS
|
|
2887
|
+
);
|
|
2888
|
+
var DISPLAY_NAMES = {
|
|
2889
|
+
"@kynver-app/runtime": "Kynver runtime",
|
|
2890
|
+
"@kynver-app/openclaw-agent-os": "OpenClaw AgentOS plugin",
|
|
2891
|
+
"@kynver-app/mcp-agent-os": "AgentOS MCP server"
|
|
2892
|
+
};
|
|
2893
|
+
var REPO_PACKAGE_JSON_RELATIVE = {
|
|
2894
|
+
"@kynver-app/runtime": "packages/kynver-runtime/package.json",
|
|
2895
|
+
"@kynver-app/openclaw-agent-os": "packages/kynver-openclaw-agent-os/package.json",
|
|
2896
|
+
"@kynver-app/mcp-agent-os": "packages/kynver-mcp-agent-os/package.json"
|
|
2897
|
+
};
|
|
2898
|
+
function parseSemverParts(version) {
|
|
2899
|
+
const core = version.trim().split("-")[0]?.split("+")[0];
|
|
2900
|
+
if (!core) return null;
|
|
2901
|
+
const parts = core.split(".");
|
|
2902
|
+
if (parts.length < 1 || parts.length > 3) return null;
|
|
2903
|
+
const nums = parts.map((p) => Number.parseInt(p, 10));
|
|
2904
|
+
if (nums.some((n) => !Number.isFinite(n) || n < 0)) return null;
|
|
2905
|
+
while (nums.length < 3) nums.push(0);
|
|
2906
|
+
return [nums[0], nums[1], nums[2]];
|
|
2907
|
+
}
|
|
2908
|
+
function compareSemver(a, b) {
|
|
2909
|
+
const pa = parseSemverParts(a);
|
|
2910
|
+
const pb = parseSemverParts(b);
|
|
2911
|
+
if (!pa || !pb) return 0;
|
|
2912
|
+
for (let i = 0; i < 3; i += 1) {
|
|
2913
|
+
if (pa[i] > pb[i]) return 1;
|
|
2914
|
+
if (pa[i] < pb[i]) return -1;
|
|
2630
2915
|
}
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2916
|
+
return 0;
|
|
2917
|
+
}
|
|
2918
|
+
function semverAtLeast(version, minimum) {
|
|
2919
|
+
return compareSemver(version, minimum) >= 0;
|
|
2920
|
+
}
|
|
2921
|
+
function maxSemver(versions) {
|
|
2922
|
+
let best = null;
|
|
2923
|
+
for (const version of versions) {
|
|
2924
|
+
if (!best || compareSemver(version, best) > 0) best = version;
|
|
2637
2925
|
}
|
|
2638
|
-
return
|
|
2639
|
-
maxConcurrentWorkers: capRecommendation.recommendedMaxWorkers,
|
|
2640
|
-
maxConcurrentWorkersSource: "setup-auto",
|
|
2641
|
-
boxKind
|
|
2642
|
-
};
|
|
2926
|
+
return best;
|
|
2643
2927
|
}
|
|
2644
|
-
function
|
|
2645
|
-
if (!existsSync11(CREDENTIALS_FILE)) return {};
|
|
2928
|
+
function readPackageJsonVersion(packageJsonPath) {
|
|
2646
2929
|
try {
|
|
2647
|
-
|
|
2930
|
+
const parsed = JSON.parse(readFileSync4(packageJsonPath, "utf8"));
|
|
2931
|
+
return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
|
|
2648
2932
|
} catch {
|
|
2649
|
-
return
|
|
2933
|
+
return null;
|
|
2650
2934
|
}
|
|
2651
2935
|
}
|
|
2652
|
-
function
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2936
|
+
function resolveRepoRoot(cwd, explicitRepoRoot) {
|
|
2937
|
+
const candidates = [explicitRepoRoot, process.env.KYNVER_REPO, cwd].filter(
|
|
2938
|
+
(value) => Boolean(value?.trim())
|
|
2939
|
+
);
|
|
2940
|
+
for (const candidate of candidates) {
|
|
2941
|
+
const resolved = path4.resolve(candidate);
|
|
2942
|
+
if (existsSync4(path4.join(resolved, "packages/kynver-runtime/package.json")) && existsSync4(path4.join(resolved, "package.json"))) {
|
|
2943
|
+
return resolved;
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
const discovered = discoverDefaultRepo({ cwd });
|
|
2947
|
+
return discovered?.repo ?? null;
|
|
2660
2948
|
}
|
|
2661
|
-
function
|
|
2662
|
-
|
|
2949
|
+
function probeRepoPackageVersions(input = {}) {
|
|
2950
|
+
const cwd = input.cwd ?? process.cwd();
|
|
2951
|
+
const repoRoot = resolveRepoRoot(cwd, input.repoRoot);
|
|
2952
|
+
if (!repoRoot) return {};
|
|
2953
|
+
const out = {};
|
|
2954
|
+
for (const packageName of MEMORY_COST_MANAGED_PACKAGES) {
|
|
2955
|
+
const packageJsonPath = path4.join(repoRoot, REPO_PACKAGE_JSON_RELATIVE[packageName]);
|
|
2956
|
+
const version = readPackageJsonVersion(packageJsonPath);
|
|
2957
|
+
if (!version) continue;
|
|
2958
|
+
out[packageName] = { version, source: "repo", path: packageJsonPath };
|
|
2959
|
+
}
|
|
2960
|
+
return out;
|
|
2663
2961
|
}
|
|
2664
|
-
function
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
const creds = loadCredentialsFile();
|
|
2668
|
-
if (!creds.runnerToken) return void 0;
|
|
2669
|
-
if (agentOsId && creds.runnerTokenAgentOsId && creds.runnerTokenAgentOsId !== agentOsId) {
|
|
2670
|
-
return void 0;
|
|
2962
|
+
function repoSourceCommands(packageName) {
|
|
2963
|
+
if (packageName === "@kynver-app/runtime") {
|
|
2964
|
+
return ["npm run kynver:build", "npm run kynver"];
|
|
2671
2965
|
}
|
|
2672
|
-
return
|
|
2966
|
+
return [`npm run build -w ${packageName}`];
|
|
2673
2967
|
}
|
|
2674
|
-
function
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2968
|
+
function buildRemediation(input) {
|
|
2969
|
+
const { packageName, minimumVersion, effectiveVersion, effectiveSource, repoVersion } = input;
|
|
2970
|
+
const lines = [];
|
|
2971
|
+
if (repoVersion && semverAtLeast(repoVersion, minimumVersion)) {
|
|
2972
|
+
lines.push(
|
|
2973
|
+
`Use the monorepo checkout (${repoVersion}) instead of a stale npm install: ${repoSourceCommands(packageName).join("; ")}.`
|
|
2974
|
+
);
|
|
2975
|
+
lines.push("Do not publish npm packages or wait on an operator release.");
|
|
2976
|
+
return lines;
|
|
2977
|
+
}
|
|
2978
|
+
if (effectiveVersion) {
|
|
2979
|
+
lines.push(
|
|
2980
|
+
`Upgrade ${packageName} from ${effectiveVersion} to >= ${minimumVersion} (npm install -g ${packageName}@latest or align OpenClaw npm prefix).`
|
|
2981
|
+
);
|
|
2982
|
+
} else {
|
|
2983
|
+
lines.push(`Install ${packageName} >= ${minimumVersion} before running memory-heavy AgentOS paths.`);
|
|
2984
|
+
}
|
|
2985
|
+
if (packageName === "@kynver-app/runtime") {
|
|
2986
|
+
lines.push("Repo-source alternative: npm run kynver:build && npm run kynver");
|
|
2987
|
+
}
|
|
2988
|
+
if (effectiveSource === "installed" && repoVersion) {
|
|
2989
|
+
lines.push(`Repo checkout reports ${repoVersion}; rebuild/link repo source if you develop from the monorepo.`);
|
|
2990
|
+
}
|
|
2991
|
+
return lines;
|
|
2680
2992
|
}
|
|
2681
|
-
function
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
return
|
|
2993
|
+
function pickEffectiveCandidate(candidates) {
|
|
2994
|
+
if (candidates.length === 0) return { version: null, source: "unknown" };
|
|
2995
|
+
const best = maxSemver(candidates.map((candidate) => candidate.version));
|
|
2996
|
+
if (!best) return { version: null, source: "unknown" };
|
|
2997
|
+
const winner = candidates.find((candidate) => candidate.version === best) ?? candidates[0];
|
|
2998
|
+
return { version: winner.version, source: winner.source };
|
|
2685
2999
|
}
|
|
2686
|
-
function
|
|
2687
|
-
const
|
|
2688
|
-
|
|
3000
|
+
function evaluateMemoryCostPackageVersionGuard(input = {}) {
|
|
3001
|
+
const normalize2 = (value, fallbackSource) => {
|
|
3002
|
+
if (!value) return null;
|
|
3003
|
+
if (typeof value === "string") return { version: value, source: fallbackSource };
|
|
3004
|
+
return value;
|
|
3005
|
+
};
|
|
3006
|
+
const packages = MEMORY_COST_MANAGED_PACKAGES.map((packageName) => {
|
|
3007
|
+
const minimumVersion = MEMORY_COST_PACKAGE_MIN_VERSIONS[packageName];
|
|
3008
|
+
const candidates = [];
|
|
3009
|
+
const installed = normalize2(input.installed?.[packageName], "installed");
|
|
3010
|
+
const repo = normalize2(input.repo?.[packageName], "repo");
|
|
3011
|
+
const self = normalize2(input.self?.[packageName], "self");
|
|
3012
|
+
if (installed) candidates.push(installed);
|
|
3013
|
+
if (repo) candidates.push(repo);
|
|
3014
|
+
if (self) candidates.push(self);
|
|
3015
|
+
const { version: effectiveVersion, source: effectiveSource } = pickEffectiveCandidate(candidates);
|
|
3016
|
+
const repoVersion = repo?.version ?? null;
|
|
3017
|
+
const ok2 = effectiveVersion ? semverAtLeast(effectiveVersion, minimumVersion) : false;
|
|
3018
|
+
const remediation = ok2 ? [] : buildRemediation({
|
|
3019
|
+
packageName,
|
|
3020
|
+
minimumVersion,
|
|
3021
|
+
effectiveVersion,
|
|
3022
|
+
effectiveSource,
|
|
3023
|
+
repoVersion
|
|
3024
|
+
});
|
|
3025
|
+
const summary2 = ok2 ? `${DISPLAY_NAMES[packageName]} ${effectiveVersion} meets memory-cost minimum ${minimumVersion} (${effectiveSource}).` : `${DISPLAY_NAMES[packageName]} is below memory-cost minimum ${minimumVersion}` + (effectiveVersion ? ` (effective ${effectiveVersion} via ${effectiveSource})` : " (no version detected)") + ".";
|
|
3026
|
+
return {
|
|
3027
|
+
packageName,
|
|
3028
|
+
displayName: DISPLAY_NAMES[packageName],
|
|
3029
|
+
minimumVersion,
|
|
3030
|
+
effectiveVersion,
|
|
3031
|
+
effectiveSource,
|
|
3032
|
+
ok: ok2,
|
|
3033
|
+
summary: summary2,
|
|
3034
|
+
remediation
|
|
3035
|
+
};
|
|
3036
|
+
});
|
|
3037
|
+
const violations = packages.filter((row) => !row.ok);
|
|
3038
|
+
const ok = violations.length === 0;
|
|
3039
|
+
const summary = ok ? "All managed AgentOS packages meet memory-cost minimum versions." : `Memory-cost package guard blocked ${violations.length} stale package(s): ${violations.map((row) => `${row.packageName} < ${row.minimumVersion}`).join("; ")}.`;
|
|
3040
|
+
return { ok, summary, packages };
|
|
2689
3041
|
}
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
);
|
|
2698
|
-
|
|
3042
|
+
var MemoryCostPackageVersionGuardError = class extends Error {
|
|
3043
|
+
result;
|
|
3044
|
+
constructor(result) {
|
|
3045
|
+
const lines = [
|
|
3046
|
+
result.summary,
|
|
3047
|
+
...result.packages.filter((row) => !row.ok).flatMap((row) => [`- ${row.summary}`, ...row.remediation.map((line) => ` \u2192 ${line}`)])
|
|
3048
|
+
];
|
|
3049
|
+
super(lines.join("\n"));
|
|
3050
|
+
this.name = "MemoryCostPackageVersionGuardError";
|
|
3051
|
+
this.result = result;
|
|
2699
3052
|
}
|
|
2700
|
-
|
|
3053
|
+
};
|
|
3054
|
+
function assertMemoryCostPackageVersionGuard(input = {}) {
|
|
3055
|
+
const result = evaluateMemoryCostPackageVersionGuard(input);
|
|
3056
|
+
if (!result.ok) throw new MemoryCostPackageVersionGuardError(result);
|
|
3057
|
+
return result;
|
|
2701
3058
|
}
|
|
2702
|
-
function
|
|
2703
|
-
|
|
2704
|
-
if (configured) return configured;
|
|
2705
|
-
failConfig(
|
|
2706
|
-
"requires --secret, KYNVER_RUNNER_TOKEN, a scoped runner token (`kynver runner credential`), ~/.kynver/credentials runnerToken, KYNVER_API_KEY with an API base URL to mint one, or (legacy) KYNVER_RUNTIME_SECRET / KYNVER_CRON_SECRET / OPENCLAW_CRON_SECRET"
|
|
2707
|
-
);
|
|
3059
|
+
function formatMemoryCostPackageGuardError(result) {
|
|
3060
|
+
return new MemoryCostPackageVersionGuardError(result).message;
|
|
2708
3061
|
}
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
}
|
|
2723
|
-
failConfig(
|
|
2724
|
-
"requires --secret, KYNVER_RUNNER_TOKEN, a scoped runner token (`kynver runner credential`), ~/.kynver/credentials runnerToken, KYNVER_API_KEY with an API base URL to mint one, or (legacy) KYNVER_RUNTIME_SECRET / KYNVER_CRON_SECRET / OPENCLAW_CRON_SECRET"
|
|
2725
|
-
);
|
|
3062
|
+
|
|
3063
|
+
// src/installed-package-versions.ts
|
|
3064
|
+
import { readFile } from "node:fs/promises";
|
|
3065
|
+
import { homedir as homedir3 } from "node:os";
|
|
3066
|
+
import path5 from "node:path";
|
|
3067
|
+
var MANAGED_PACKAGES = [
|
|
3068
|
+
"@kynver-app/runtime",
|
|
3069
|
+
"@kynver-app/openclaw-agent-os",
|
|
3070
|
+
"@kynver-app/mcp-agent-os"
|
|
3071
|
+
];
|
|
3072
|
+
function trim(value) {
|
|
3073
|
+
const out = value?.trim();
|
|
3074
|
+
return out ? out : null;
|
|
2726
3075
|
}
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
|
|
2730
|
-
if (!apiKey || !agentOsId || !baseUrl) return null;
|
|
2731
|
-
try {
|
|
2732
|
-
const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
|
|
2733
|
-
saveRunnerToken(agentOsId, token);
|
|
2734
|
-
return token;
|
|
2735
|
-
} catch {
|
|
2736
|
-
return null;
|
|
2737
|
-
}
|
|
3076
|
+
function unique(values) {
|
|
3077
|
+
return [...new Set(values.filter((value) => Boolean(value)))];
|
|
2738
3078
|
}
|
|
2739
|
-
|
|
2740
|
-
const
|
|
2741
|
-
const
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
saveRunnerToken(agentOsId, token);
|
|
2749
|
-
return { ok: true, token };
|
|
2750
|
-
}
|
|
2751
|
-
return { ok: false, reason: "runner credential refresh returned the rejected token" };
|
|
2752
|
-
} catch (error) {
|
|
2753
|
-
return { ok: false, reason: error.message };
|
|
2754
|
-
}
|
|
3079
|
+
function moduleRoots() {
|
|
3080
|
+
const home = homedir3();
|
|
3081
|
+
const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ?? path5.join(home, ".openclaw", "npm");
|
|
3082
|
+
const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ? path5.join(trim(process.env.NPM_CONFIG_PREFIX), "lib", "node_modules") : path5.join(home, ".npm-global", "lib", "node_modules"));
|
|
3083
|
+
return unique([
|
|
3084
|
+
path5.join(openClawPrefix, "lib", "node_modules"),
|
|
3085
|
+
path5.join(openClawPrefix, "node_modules"),
|
|
3086
|
+
npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot : path5.join(npmGlobalRoot, "lib", "node_modules")
|
|
3087
|
+
]);
|
|
2755
3088
|
}
|
|
2756
|
-
async function
|
|
2757
|
-
const apiKey = opts?.apiKey || loadApiKey();
|
|
2758
|
-
if (!apiKey) throw new Error("API key required \u2014 run `kynver login` first");
|
|
2759
|
-
const base = resolveBaseUrl(opts?.baseUrl);
|
|
2760
|
-
const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/runner-credentials`;
|
|
2761
|
-
const res = await fetch(url, {
|
|
2762
|
-
method: "POST",
|
|
2763
|
-
headers: {
|
|
2764
|
-
"Content-Type": "application/json",
|
|
2765
|
-
Authorization: `Bearer ${apiKey}`
|
|
2766
|
-
},
|
|
2767
|
-
body: JSON.stringify({})
|
|
2768
|
-
});
|
|
2769
|
-
const text = await res.text();
|
|
2770
|
-
let parsed = null;
|
|
3089
|
+
async function readVersion(packageJsonPath) {
|
|
2771
3090
|
try {
|
|
2772
|
-
parsed = JSON.parse(
|
|
3091
|
+
const parsed = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
3092
|
+
return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
|
|
2773
3093
|
} catch {
|
|
2774
|
-
|
|
2775
|
-
}
|
|
2776
|
-
if (!res.ok || !parsed?.token) {
|
|
2777
|
-
throw new Error(
|
|
2778
|
-
`runner credential mint failed (${res.status}): ${parsed?.error ?? text.slice(0, 200)}`
|
|
2779
|
-
);
|
|
3094
|
+
return null;
|
|
2780
3095
|
}
|
|
2781
|
-
return parsed.token;
|
|
2782
3096
|
}
|
|
2783
|
-
|
|
2784
|
-
const
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
JSON.stringify(
|
|
2793
|
-
{
|
|
2794
|
-
ok: true,
|
|
2795
|
-
agentOsId,
|
|
2796
|
-
credentialsPath: displayUserPath(CREDENTIALS_FILE),
|
|
2797
|
-
tokenPrefix: `${token.slice(0, 12)}\u2026`,
|
|
2798
|
-
note: "Scoped runner token saved; callbacks use X-Kynver-Runner-Token."
|
|
2799
|
-
},
|
|
2800
|
-
null,
|
|
2801
|
-
2
|
|
2802
|
-
)
|
|
2803
|
-
);
|
|
2804
|
-
} catch (err) {
|
|
2805
|
-
console.error(err instanceof Error ? err.message : String(err));
|
|
2806
|
-
process.exit(1);
|
|
3097
|
+
function installedPackageJsonCandidates(packageName) {
|
|
3098
|
+
const roots = moduleRoots();
|
|
3099
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3100
|
+
const out = [];
|
|
3101
|
+
for (const root of roots) {
|
|
3102
|
+
const candidate = path5.join(root, packageName, "package.json");
|
|
3103
|
+
if (seen.has(candidate)) continue;
|
|
3104
|
+
seen.add(candidate);
|
|
3105
|
+
out.push(candidate);
|
|
2807
3106
|
}
|
|
3107
|
+
return out;
|
|
2808
3108
|
}
|
|
2809
|
-
function
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
if (
|
|
2821
|
-
|
|
2822
|
-
args[key] = next;
|
|
2823
|
-
i++;
|
|
3109
|
+
async function collectInstalledPackageVersions(observedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
3110
|
+
const out = {};
|
|
3111
|
+
for (const packageName of MANAGED_PACKAGES) {
|
|
3112
|
+
let best = null;
|
|
3113
|
+
for (const packageJsonPath of installedPackageJsonCandidates(packageName)) {
|
|
3114
|
+
const version = await readVersion(packageJsonPath);
|
|
3115
|
+
if (!version) continue;
|
|
3116
|
+
if (!best || compareSemver(version, best.version) > 0) {
|
|
3117
|
+
best = { version, path: packageJsonPath };
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
if (best) {
|
|
3121
|
+
out[packageName] = { version: best.version, observedAt, path: best.path };
|
|
2824
3122
|
}
|
|
2825
3123
|
}
|
|
2826
|
-
return
|
|
3124
|
+
return out;
|
|
2827
3125
|
}
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
});
|
|
2840
|
-
const workerConfig = resolveSetupWorkerConfig(existing, args);
|
|
2841
|
-
const config = normalizeConfigPaths({
|
|
2842
|
-
...existing,
|
|
2843
|
-
...inferSetupFields(existing, args),
|
|
2844
|
-
...workerConfig,
|
|
2845
|
-
workerProvider: typeof args.provider === "string" ? args.provider : existing.workerProvider || "cursor"
|
|
2846
|
-
});
|
|
2847
|
-
saveUserConfig(config);
|
|
2848
|
-
const boxIdentity = resolveBoxIdentity(process.env, config);
|
|
2849
|
-
let runnerCredentialNote;
|
|
2850
|
-
const apiKey = loadApiKey();
|
|
2851
|
-
const agentOsId = config.agentOsId;
|
|
2852
|
-
if (apiKey && agentOsId) {
|
|
2853
|
-
try {
|
|
2854
|
-
const token = await fetchRunnerCredential(agentOsId, {
|
|
2855
|
-
baseUrl: typeof args.apiBaseUrl === "string" ? args.apiBaseUrl : config.apiBaseUrl,
|
|
2856
|
-
apiKey
|
|
2857
|
-
});
|
|
2858
|
-
saveRunnerToken(agentOsId, token);
|
|
2859
|
-
runnerCredentialNote = "Scoped runner token minted and saved to ~/.kynver/credentials.";
|
|
2860
|
-
} catch {
|
|
2861
|
-
runnerCredentialNote = "Runner token not minted (server offline or master secret unset). Run `kynver runner credential` after deploy.";
|
|
2862
|
-
}
|
|
3126
|
+
|
|
3127
|
+
// src/memory-cost-package-version-guard-enforce.ts
|
|
3128
|
+
function installedVersionMap(observed) {
|
|
3129
|
+
const out = {};
|
|
3130
|
+
for (const [packageName, row] of Object.entries(observed)) {
|
|
3131
|
+
if (!row?.version) continue;
|
|
3132
|
+
out[packageName] = {
|
|
3133
|
+
version: row.version,
|
|
3134
|
+
source: "installed",
|
|
3135
|
+
path: row.path
|
|
3136
|
+
};
|
|
2863
3137
|
}
|
|
2864
|
-
|
|
2865
|
-
JSON.stringify(
|
|
2866
|
-
{
|
|
2867
|
-
ok: true,
|
|
2868
|
-
configPath: displayUserPath(CONFIG_FILE),
|
|
2869
|
-
config: presentUserConfig(config),
|
|
2870
|
-
boxKind: config.boxKind,
|
|
2871
|
-
boxKindSource: boxIdentity.source,
|
|
2872
|
-
workerCapRecommendation: capRecommendation,
|
|
2873
|
-
...boxIdentity.warnings.length ? { boxIdentityWarnings: boxIdentity.warnings } : {},
|
|
2874
|
-
note: runnerCredentialNote ?? "boxKind and maxConcurrentWorkers persisted; override with --box-kind and --max-workers. Run `kynver login` + `kynver runner credential` for scoped callbacks."
|
|
2875
|
-
},
|
|
2876
|
-
null,
|
|
2877
|
-
2
|
|
2878
|
-
)
|
|
2879
|
-
);
|
|
3138
|
+
return out;
|
|
2880
3139
|
}
|
|
2881
|
-
async function
|
|
2882
|
-
const
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
3140
|
+
async function buildMemoryCostPackageGuardInput(input = {}) {
|
|
3141
|
+
const [installed, repo] = await Promise.all([
|
|
3142
|
+
collectInstalledPackageVersions(),
|
|
3143
|
+
Promise.resolve(probeRepoPackageVersions({ cwd: input.cwd, repoRoot: input.repoRoot }))
|
|
3144
|
+
]);
|
|
3145
|
+
const self = {};
|
|
3146
|
+
const runtimeSelfVersion = input.selfPackageName === "@kynver-app/runtime" && input.selfVersion ? input.selfVersion : PACKAGE_VERSION;
|
|
3147
|
+
self["@kynver-app/runtime"] = { version: runtimeSelfVersion, source: "self" };
|
|
3148
|
+
if (input.selfPackageName && input.selfVersion && input.selfPackageName !== "@kynver-app/runtime") {
|
|
3149
|
+
self[input.selfPackageName] = { version: input.selfVersion, source: "self" };
|
|
3150
|
+
}
|
|
3151
|
+
return {
|
|
3152
|
+
installed: installedVersionMap(installed),
|
|
3153
|
+
repo,
|
|
3154
|
+
self
|
|
3155
|
+
};
|
|
3156
|
+
}
|
|
3157
|
+
async function evaluateMemoryCostPackageGuardAtStartup(input = {}) {
|
|
3158
|
+
const guardInput = await buildMemoryCostPackageGuardInput(input);
|
|
3159
|
+
return evaluateMemoryCostPackageVersionGuard(guardInput);
|
|
3160
|
+
}
|
|
3161
|
+
async function enforceMemoryCostPackageGuardAtStartup(input = {}) {
|
|
3162
|
+
const guardInput = await buildMemoryCostPackageGuardInput(input);
|
|
3163
|
+
return assertMemoryCostPackageVersionGuard(guardInput);
|
|
3164
|
+
}
|
|
3165
|
+
function shouldEnforceMemoryCostPackageGuardCli(scope, action) {
|
|
3166
|
+
if (!scope) return false;
|
|
3167
|
+
if (scope === "daemon") return true;
|
|
3168
|
+
if (scope === "worker") return true;
|
|
3169
|
+
if (scope === "monitor") return true;
|
|
3170
|
+
if (scope === "run" && (action === "dispatch" || action === "sweep" || action === "reconcile" || action === "unblock")) {
|
|
3171
|
+
return true;
|
|
3172
|
+
}
|
|
3173
|
+
if (scope === "cron" && action === "tick") return true;
|
|
3174
|
+
return false;
|
|
2886
3175
|
}
|
|
2887
3176
|
|
|
3177
|
+
// src/dispatch.ts
|
|
3178
|
+
init_config();
|
|
3179
|
+
|
|
2888
3180
|
// src/callback-headers.ts
|
|
2889
3181
|
function buildHarnessCallbackHeaders(secret) {
|
|
2890
3182
|
const trimmed = String(secret).trim();
|
|
@@ -2907,6 +3199,7 @@ function buildHarnessCallbackHeaders(secret) {
|
|
|
2907
3199
|
}
|
|
2908
3200
|
|
|
2909
3201
|
// src/callbacks.ts
|
|
3202
|
+
init_config();
|
|
2910
3203
|
function callbackTimeoutMs() {
|
|
2911
3204
|
const parsed = Number(process.env.KYNVER_CALLBACK_TIMEOUT_MS);
|
|
2912
3205
|
if (Number.isFinite(parsed) && parsed > 0) return Math.floor(parsed);
|
|
@@ -3132,6 +3425,12 @@ function resolveDispatchNextLaneFilter(raw) {
|
|
|
3132
3425
|
return normalizeDispatchNextLaneFilter(raw) ?? "any";
|
|
3133
3426
|
}
|
|
3134
3427
|
|
|
3428
|
+
// src/dispatch.ts
|
|
3429
|
+
init_disk_gate();
|
|
3430
|
+
init_resource_gate();
|
|
3431
|
+
init_run_store();
|
|
3432
|
+
init_run_store();
|
|
3433
|
+
|
|
3135
3434
|
// src/model-routing-task-enrich.ts
|
|
3136
3435
|
function taskString(task, key) {
|
|
3137
3436
|
const v = task[key];
|
|
@@ -3181,6 +3480,9 @@ function enrichTaskForModelRouting(task) {
|
|
|
3181
3480
|
return { ...task, roleLane };
|
|
3182
3481
|
}
|
|
3183
3482
|
|
|
3483
|
+
// src/model-routing.ts
|
|
3484
|
+
init_config();
|
|
3485
|
+
|
|
3184
3486
|
// src/worker-provider-policy.ts
|
|
3185
3487
|
var DEFAULT_WORKER_PROVIDER = "cursor";
|
|
3186
3488
|
var CLAUDE_FAMILY = /* @__PURE__ */ new Set(["claude", "opus", "anthropic"]);
|
|
@@ -3864,6 +4166,8 @@ function resolveOrchestrationRouting(input) {
|
|
|
3864
4166
|
}
|
|
3865
4167
|
|
|
3866
4168
|
// src/providers/claude.ts
|
|
4169
|
+
init_worker_env();
|
|
4170
|
+
init_util();
|
|
3867
4171
|
import { closeSync, openSync } from "node:fs";
|
|
3868
4172
|
import { spawn } from "node:child_process";
|
|
3869
4173
|
|
|
@@ -4001,13 +4305,17 @@ var claudeProvider = {
|
|
|
4001
4305
|
};
|
|
4002
4306
|
|
|
4003
4307
|
// src/providers/codex.ts
|
|
4308
|
+
init_worker_env();
|
|
4309
|
+
init_util();
|
|
4004
4310
|
import { closeSync as closeSync3, existsSync as existsSync17, openSync as openSync3 } from "node:fs";
|
|
4005
4311
|
import { spawn as spawn3 } from "node:child_process";
|
|
4006
4312
|
|
|
4007
4313
|
// src/providers/hermes-codex.ts
|
|
4314
|
+
init_worker_env();
|
|
4315
|
+
init_util();
|
|
4008
4316
|
import { closeSync as closeSync2, openSync as openSync2 } from "node:fs";
|
|
4009
4317
|
import { spawn as spawn2 } from "node:child_process";
|
|
4010
|
-
var HERMES_OPENAI_CODEX_DEFAULT_MODEL = "gpt-5.4";
|
|
4318
|
+
var HERMES_OPENAI_CODEX_DEFAULT_MODEL = process.env.KYNVER_CODEX_DEFAULT_MODEL?.trim() || "gpt-5.4";
|
|
4011
4319
|
function hermesWorkerEnv() {
|
|
4012
4320
|
return scrubWorkerEnv({
|
|
4013
4321
|
...process.env,
|
|
@@ -4075,7 +4383,10 @@ var hermesCodexProvider = {
|
|
|
4075
4383
|
};
|
|
4076
4384
|
|
|
4077
4385
|
// src/providers/codex.ts
|
|
4078
|
-
|
|
4386
|
+
function resolveCodexDefaultModel() {
|
|
4387
|
+
return process.env.KYNVER_CODEX_DEFAULT_MODEL?.trim() || "gpt-5.4";
|
|
4388
|
+
}
|
|
4389
|
+
var CODEX_DEFAULT_MODEL = resolveCodexDefaultModel();
|
|
4079
4390
|
function resolveCodexBin() {
|
|
4080
4391
|
return process.env.KYNVER_CODEX_BIN?.trim() || process.env.CODEX_BIN?.trim() || "codex";
|
|
4081
4392
|
}
|
|
@@ -4327,7 +4638,11 @@ function readHarnessRetryLimits() {
|
|
|
4327
4638
|
}
|
|
4328
4639
|
|
|
4329
4640
|
// src/lease-renewal.ts
|
|
4641
|
+
init_config();
|
|
4330
4642
|
import path16 from "node:path";
|
|
4643
|
+
init_run_store();
|
|
4644
|
+
init_status();
|
|
4645
|
+
init_util();
|
|
4331
4646
|
|
|
4332
4647
|
// src/harness-lease-owner.ts
|
|
4333
4648
|
var HARNESS_LEASE_PREFIX = "kynver-harness:";
|
|
@@ -4363,15 +4678,17 @@ function resolveHarnessLeaseOwnerForRenewal(input) {
|
|
|
4363
4678
|
}
|
|
4364
4679
|
|
|
4365
4680
|
// src/runner-identity.ts
|
|
4366
|
-
import
|
|
4681
|
+
import os6 from "node:os";
|
|
4367
4682
|
|
|
4368
4683
|
// src/box-resource-snapshot-shared.ts
|
|
4369
|
-
|
|
4684
|
+
init_box_identity();
|
|
4685
|
+
init_box_identity();
|
|
4686
|
+
import os5 from "node:os";
|
|
4370
4687
|
function resolveBoxKindFromEnv(env = process.env) {
|
|
4371
4688
|
return resolveBoxIdentity(env).boxKind;
|
|
4372
4689
|
}
|
|
4373
4690
|
function defaultBoxId(boxKind, hostLabel) {
|
|
4374
|
-
const host = (hostLabel ??
|
|
4691
|
+
const host = (hostLabel ?? os5.hostname()).trim().toLowerCase().replace(/\s+/g, "-") || "unknown-host";
|
|
4375
4692
|
return `${boxKind}:${host}`;
|
|
4376
4693
|
}
|
|
4377
4694
|
|
|
@@ -4382,10 +4699,10 @@ function trimOrNull5(value) {
|
|
|
4382
4699
|
}
|
|
4383
4700
|
function resolveRunnerPresencePayload(input = {}) {
|
|
4384
4701
|
const env = input.env ?? process.env;
|
|
4385
|
-
const runnerId = trimOrNull5(env.KYNVER_RUNTIME_ID) ?? trimOrNull5(env.OPENCLAW_RUNTIME_ID) ?? trimOrNull5(env.HOSTNAME) ??
|
|
4702
|
+
const runnerId = trimOrNull5(env.KYNVER_RUNTIME_ID) ?? trimOrNull5(env.OPENCLAW_RUNTIME_ID) ?? trimOrNull5(env.HOSTNAME) ?? os6.hostname();
|
|
4386
4703
|
return {
|
|
4387
4704
|
runnerId,
|
|
4388
|
-
hostname: trimOrNull5(env.HOSTNAME) ??
|
|
4705
|
+
hostname: trimOrNull5(env.HOSTNAME) ?? os6.hostname(),
|
|
4389
4706
|
profile: trimOrNull5(env.KYNVER_RUNNER_PROFILE) ?? trimOrNull5(env.OPENCLAW_RUNNER_PROFILE),
|
|
4390
4707
|
harnessRepo: trimOrNull5(env.KYNVER_HARNESS_REPO) ?? trimOrNull5(env.KYNVER_DEFAULT_REPO),
|
|
4391
4708
|
runId: input.runId ?? null
|
|
@@ -4470,6 +4787,9 @@ function hasLiveWorkerForTask(runId, taskId) {
|
|
|
4470
4787
|
}
|
|
4471
4788
|
|
|
4472
4789
|
// src/supervisor.ts
|
|
4790
|
+
init_git();
|
|
4791
|
+
init_run_store();
|
|
4792
|
+
init_run_store();
|
|
4473
4793
|
import { existsSync as existsSync21, mkdirSync as mkdirSync4 } from "node:fs";
|
|
4474
4794
|
import path23 from "node:path";
|
|
4475
4795
|
|
|
@@ -4619,10 +4939,18 @@ function buildPrompt(input) {
|
|
|
4619
4939
|
].join("\n");
|
|
4620
4940
|
}
|
|
4621
4941
|
|
|
4942
|
+
// src/supervisor.ts
|
|
4943
|
+
init_util();
|
|
4944
|
+
|
|
4945
|
+
// src/providers/registry.ts
|
|
4946
|
+
init_config();
|
|
4947
|
+
|
|
4622
4948
|
// src/providers/cursor.ts
|
|
4949
|
+
init_util();
|
|
4950
|
+
init_worker_env();
|
|
4623
4951
|
import { closeSync as closeSync4, existsSync as existsSync19, mkdirSync as mkdirSync3, openSync as openSync4, statSync as statSync4, unlinkSync } from "node:fs";
|
|
4624
4952
|
import { spawn as spawn4 } from "node:child_process";
|
|
4625
|
-
import
|
|
4953
|
+
import os7 from "node:os";
|
|
4626
4954
|
import path18 from "node:path";
|
|
4627
4955
|
|
|
4628
4956
|
// src/providers/cursor-windows.ts
|
|
@@ -4733,7 +5061,7 @@ function positiveIntEnv(name, fallback) {
|
|
|
4733
5061
|
return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : fallback;
|
|
4734
5062
|
}
|
|
4735
5063
|
function cursorStartLockPath() {
|
|
4736
|
-
const root = process.env.KYNVER_CURSOR_START_LOCK_DIR?.trim() || path18.join(
|
|
5064
|
+
const root = process.env.KYNVER_CURSOR_START_LOCK_DIR?.trim() || path18.join(os7.homedir(), ".kynver", "locks");
|
|
4737
5065
|
mkdirSync3(root, { recursive: true });
|
|
4738
5066
|
return path18.join(root, "cursor-agent-start.lock");
|
|
4739
5067
|
}
|
|
@@ -4859,12 +5187,14 @@ function resolveWorkerProvider(name) {
|
|
|
4859
5187
|
}
|
|
4860
5188
|
|
|
4861
5189
|
// src/auto-complete.ts
|
|
5190
|
+
init_util();
|
|
4862
5191
|
import { spawn as spawn5 } from "node:child_process";
|
|
4863
5192
|
import { existsSync as existsSync20, openSync as openSync5, closeSync as closeSync5 } from "node:fs";
|
|
4864
5193
|
import path22 from "node:path";
|
|
4865
5194
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
4866
5195
|
|
|
4867
5196
|
// src/completion-ack.ts
|
|
5197
|
+
init_run_store();
|
|
4868
5198
|
function hasCompletionAck(worker) {
|
|
4869
5199
|
return Boolean(worker.completionReportedAt?.trim());
|
|
4870
5200
|
}
|
|
@@ -4892,7 +5222,12 @@ function hasTerminalCompletionAck(worker) {
|
|
|
4892
5222
|
return hasCompletionAck(worker) && !shouldReplayHarnessCompletion(worker);
|
|
4893
5223
|
}
|
|
4894
5224
|
|
|
5225
|
+
// src/auto-complete.ts
|
|
5226
|
+
init_run_store();
|
|
5227
|
+
init_status();
|
|
5228
|
+
|
|
4895
5229
|
// src/worker-ops.ts
|
|
5230
|
+
init_config();
|
|
4896
5231
|
import path21 from "node:path";
|
|
4897
5232
|
|
|
4898
5233
|
// src/completion-response.ts
|
|
@@ -4934,6 +5269,10 @@ function completionPostSucceeded(summary) {
|
|
|
4934
5269
|
return summary.taskAdvanced;
|
|
4935
5270
|
}
|
|
4936
5271
|
|
|
5272
|
+
// src/worker-ops.ts
|
|
5273
|
+
init_run_store();
|
|
5274
|
+
init_exited_salvage();
|
|
5275
|
+
|
|
4937
5276
|
// src/harness-expert-review.ts
|
|
4938
5277
|
var EXPERT_LANE_REVIEW_REF = "expert-lane-pr-review:";
|
|
4939
5278
|
var PLAN_REVIEW_EXECUTOR_REF = "plan-review-task";
|
|
@@ -5101,6 +5440,7 @@ function normalizeOwnerRepo(value) {
|
|
|
5101
5440
|
}
|
|
5102
5441
|
|
|
5103
5442
|
// src/pr-handoff/pr-handoff-gh.ts
|
|
5443
|
+
init_git();
|
|
5104
5444
|
function capture(bin, cwd, args) {
|
|
5105
5445
|
try {
|
|
5106
5446
|
const res = spawnSync3(bin, args, { cwd, encoding: "utf8" });
|
|
@@ -5471,6 +5811,10 @@ function ensurePrReadyHandoff(input, exec = defaultPrHandoffExec) {
|
|
|
5471
5811
|
};
|
|
5472
5812
|
}
|
|
5473
5813
|
|
|
5814
|
+
// src/worker-ops.ts
|
|
5815
|
+
init_status();
|
|
5816
|
+
init_stream();
|
|
5817
|
+
|
|
5474
5818
|
// src/material-worktree-changes.ts
|
|
5475
5819
|
function materialWorktreeChanges(changedFiles) {
|
|
5476
5820
|
return changedFiles.filter((line) => {
|
|
@@ -5513,8 +5857,8 @@ function dirtyPathsCoveredByDisposableRemoval(changedFiles, removed) {
|
|
|
5513
5857
|
if (removed.length === 0) return false;
|
|
5514
5858
|
const removedSet = new Set(removed.map((p) => normalizeRelativePath(p)));
|
|
5515
5859
|
return material.every((line) => {
|
|
5516
|
-
const
|
|
5517
|
-
return removedSet.has(
|
|
5860
|
+
const path75 = normalizeRelativePath(pathFromGitStatusLine(line));
|
|
5861
|
+
return removedSet.has(path75);
|
|
5518
5862
|
});
|
|
5519
5863
|
}
|
|
5520
5864
|
|
|
@@ -5599,6 +5943,9 @@ function assessWorktreeCompletionHandoff(input) {
|
|
|
5599
5943
|
}
|
|
5600
5944
|
|
|
5601
5945
|
// src/worker-lifecycle.ts
|
|
5946
|
+
init_run_store();
|
|
5947
|
+
init_status();
|
|
5948
|
+
init_util();
|
|
5602
5949
|
import path19 from "node:path";
|
|
5603
5950
|
var TASK_LEFT_RUNNING = /* @__PURE__ */ new Set([
|
|
5604
5951
|
"awaiting_review",
|
|
@@ -5690,7 +6037,11 @@ function syncCompletionAcknowledgedFromOperatorTick(runId, operatorTick) {
|
|
|
5690
6037
|
return synced;
|
|
5691
6038
|
}
|
|
5692
6039
|
|
|
6040
|
+
// src/worker-ops.ts
|
|
6041
|
+
init_util();
|
|
6042
|
+
|
|
5693
6043
|
// src/validate.ts
|
|
6044
|
+
init_util();
|
|
5694
6045
|
import path20 from "node:path";
|
|
5695
6046
|
var RUN_ID_RE = /^[a-z0-9][a-z0-9._-]{0,127}$/i;
|
|
5696
6047
|
var WORKER_NAME_RE = /^[a-z0-9][a-z0-9._-]{0,63}$/i;
|
|
@@ -6477,6 +6828,7 @@ function stopWorker(args) {
|
|
|
6477
6828
|
}
|
|
6478
6829
|
|
|
6479
6830
|
// src/auto-complete.ts
|
|
6831
|
+
init_util();
|
|
6480
6832
|
var DEFAULT_POLL_MS = 5e3;
|
|
6481
6833
|
var DEFAULT_MAX_TOTAL_MS = 6 * 60 * 60 * 1e3;
|
|
6482
6834
|
var DEFAULT_COMPLETE_ATTEMPTS = 3;
|
|
@@ -6661,6 +7013,7 @@ function spawnCompletionSidecar(opts) {
|
|
|
6661
7013
|
}
|
|
6662
7014
|
|
|
6663
7015
|
// src/repair-target-worktree.ts
|
|
7016
|
+
init_git();
|
|
6664
7017
|
function addWorktreeForRepairBranch(repo, worktreePath, branch) {
|
|
6665
7018
|
git(repo, ["fetch", "origin", branch, "--prune"], { allowFailure: true });
|
|
6666
7019
|
const remoteRef = `origin/${branch}`;
|
|
@@ -6674,6 +7027,8 @@ function addWorktreeForRepairBranch(repo, worktreePath, branch) {
|
|
|
6674
7027
|
}
|
|
6675
7028
|
|
|
6676
7029
|
// src/supervisor.ts
|
|
7030
|
+
init_box_identity();
|
|
7031
|
+
init_config();
|
|
6677
7032
|
function spawnWorkerProcess(run, opts) {
|
|
6678
7033
|
const rawName = typeof opts.name === "string" ? opts.name.trim() : "";
|
|
6679
7034
|
if (!rawName || rawName === "undefined" || rawName === "null") {
|
|
@@ -6767,6 +7122,10 @@ function spawnWorkerProcess(run, opts) {
|
|
|
6767
7122
|
else process.env.KYNVER_HARNESS_AGENT_OS_ID = prevHarnessAgentOsId;
|
|
6768
7123
|
}
|
|
6769
7124
|
const model = resolveModelFallback(started.model, launchModel, provider.defaultModel);
|
|
7125
|
+
const config = loadUserConfig();
|
|
7126
|
+
const boxIdentity = resolveBoxIdentity(process.env, config);
|
|
7127
|
+
const runtimeId = resolveRunnerPresencePayload().runnerId;
|
|
7128
|
+
const boxId = defaultBoxId(boxIdentity.boxKind);
|
|
6770
7129
|
const worker = {
|
|
6771
7130
|
name,
|
|
6772
7131
|
runId: run.id,
|
|
@@ -6802,6 +7161,9 @@ function spawnWorkerProcess(run, opts) {
|
|
|
6802
7161
|
...opts.taskPrUrl ? { taskPrUrl: String(opts.taskPrUrl) } : {},
|
|
6803
7162
|
...opts.repairTargetPrUrl ? { repairTargetPrUrl: String(opts.repairTargetPrUrl) } : {},
|
|
6804
7163
|
...opts.repairTargetBranch ? { repairTargetBranch: String(opts.repairTargetBranch) } : {},
|
|
7164
|
+
boxKind: boxIdentity.boxKind,
|
|
7165
|
+
boxId,
|
|
7166
|
+
runtimeId,
|
|
6805
7167
|
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6806
7168
|
};
|
|
6807
7169
|
saveWorker(run.id, worker);
|
|
@@ -6900,6 +7262,9 @@ async function startWorker(args) {
|
|
|
6900
7262
|
}
|
|
6901
7263
|
|
|
6902
7264
|
// src/active-harness-workers.ts
|
|
7265
|
+
init_run_store();
|
|
7266
|
+
init_harness_worker_active();
|
|
7267
|
+
init_util();
|
|
6903
7268
|
import path24 from "node:path";
|
|
6904
7269
|
function workerWriteSetFields(worker) {
|
|
6905
7270
|
const ownedPaths = Array.isArray(worker.ownedPaths) ? worker.ownedPaths.filter((p) => typeof p === "string") : [];
|
|
@@ -6932,6 +7297,9 @@ function collectRunActiveHarnessWorkers(runId) {
|
|
|
6932
7297
|
return out;
|
|
6933
7298
|
}
|
|
6934
7299
|
|
|
7300
|
+
// src/dispatch.ts
|
|
7301
|
+
init_util();
|
|
7302
|
+
|
|
6935
7303
|
// src/plan-persist/body-hash.ts
|
|
6936
7304
|
import { createHash as createHash2 } from "node:crypto";
|
|
6937
7305
|
function hashPlanBody(body) {
|
|
@@ -6945,6 +7313,9 @@ function hashSummary(summary) {
|
|
|
6945
7313
|
return createHash2("sha256").update(trimmed, "utf8").digest("hex");
|
|
6946
7314
|
}
|
|
6947
7315
|
|
|
7316
|
+
// src/plan-persist/agentos-api.ts
|
|
7317
|
+
init_config();
|
|
7318
|
+
|
|
6948
7319
|
// src/plan-persist/errors.ts
|
|
6949
7320
|
var PlanPersistError = class extends Error {
|
|
6950
7321
|
kind;
|
|
@@ -7609,11 +7980,11 @@ function classifyChecks(statusCheckRollup) {
|
|
|
7609
7980
|
continue;
|
|
7610
7981
|
}
|
|
7611
7982
|
if (state && SUCCESSFUL_CHECK_CONCLUSIONS.has(state)) continue;
|
|
7612
|
-
if (state && state !== "PENDING") {
|
|
7983
|
+
if (state && state !== "PENDING" && state !== "EXPECTED") {
|
|
7613
7984
|
failed.push(`${checkName(check3)}=${state}`);
|
|
7614
7985
|
continue;
|
|
7615
7986
|
}
|
|
7616
|
-
if (state === "PENDING") {
|
|
7987
|
+
if (state === "PENDING" || state === "EXPECTED") {
|
|
7617
7988
|
pending.push(`${checkName(check3)}=${state}`);
|
|
7618
7989
|
continue;
|
|
7619
7990
|
}
|
|
@@ -7640,8 +8011,8 @@ var LOCAL_VERIFICATION_RE = /typecheck|npm run (test|build|typecheck)|vitest|tsc
|
|
|
7640
8011
|
var DOCS_TITLE_RE = /^docs[(:]/i;
|
|
7641
8012
|
var DOCS_BODY_RE = /docs[- ]only|documentation only|no[- ]code change|no code changes|low[- ]risk|plan tracker only|markdown only/i;
|
|
7642
8013
|
function runtimeVerificationEvidenceSufficient(input) {
|
|
7643
|
-
const title = typeof input.title === "string" ? input.title : "";
|
|
7644
|
-
const body = typeof input.body === "string" ? input.body : "";
|
|
8014
|
+
const title = typeof input.title === "string" ? input.title.trim() : "";
|
|
8015
|
+
const body = typeof input.body === "string" ? input.body.trim() : "";
|
|
7645
8016
|
const docsLowRisk = DOCS_TITLE_RE.test(title) || DOCS_BODY_RE.test(body);
|
|
7646
8017
|
const structuredSection = STRUCTURED_SECTION_RE.test(body);
|
|
7647
8018
|
const localVerification = LOCAL_VERIFICATION_RE.test(body);
|
|
@@ -7793,40 +8164,56 @@ async function executeLandPrMerge(input) {
|
|
|
7793
8164
|
"--squash"
|
|
7794
8165
|
]);
|
|
7795
8166
|
if (mergeRes.status !== 0) {
|
|
8167
|
+
const raced = viewMergedState(exec, cwd, target, input.repo);
|
|
8168
|
+
if (raced) {
|
|
8169
|
+
return {
|
|
8170
|
+
prUrl: raced.url || before.url || prTarget,
|
|
8171
|
+
outcome: "skipped",
|
|
8172
|
+
mergeCommit: raced.mergeCommit?.oid ?? null,
|
|
8173
|
+
reason: `PR #${before.number} is already merged \u2014 merged by another lane during land_pr (race)`
|
|
8174
|
+
};
|
|
8175
|
+
}
|
|
7796
8176
|
return {
|
|
7797
8177
|
prUrl: before.url || prTarget,
|
|
7798
8178
|
outcome: "blocked",
|
|
7799
8179
|
reason: mergeRes.stderr || mergeRes.stdout || "gh pr merge failed"
|
|
7800
8180
|
};
|
|
7801
8181
|
}
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
return {
|
|
7812
|
-
prUrl: after.url || before.url || prTarget,
|
|
7813
|
-
outcome: "blocked",
|
|
7814
|
-
reason: `PR #${after.number} did not verify as merged after gh pr merge`
|
|
7815
|
-
};
|
|
8182
|
+
let after = viewMergedState(exec, cwd, target, input.repo);
|
|
8183
|
+
if (!after) {
|
|
8184
|
+
after = viewMergedState(exec, cwd, target, input.repo);
|
|
8185
|
+
}
|
|
8186
|
+
try {
|
|
8187
|
+
const repo = resolveRepo(exec, cwd, input.repo);
|
|
8188
|
+
deleteRemoteBranch(exec, cwd, repo, before.headRefName);
|
|
8189
|
+
removeBranchWorktrees(cwd, before.headRefName);
|
|
8190
|
+
} catch {
|
|
7816
8191
|
}
|
|
7817
|
-
const repo = resolveRepo(exec, cwd, input.repo);
|
|
7818
|
-
deleteRemoteBranch(exec, cwd, repo, before.headRefName);
|
|
7819
|
-
removeBranchWorktrees(cwd, before.headRefName);
|
|
7820
|
-
const mergeCommit = after.mergeCommit?.oid ?? null;
|
|
7821
8192
|
return {
|
|
7822
|
-
prUrl: after
|
|
8193
|
+
prUrl: after?.url || before.url || prTarget,
|
|
7823
8194
|
outcome: "merged",
|
|
7824
|
-
mergeCommit,
|
|
7825
|
-
reason: `Daemon land_pr merged PR #${
|
|
8195
|
+
mergeCommit: after?.mergeCommit?.oid ?? null,
|
|
8196
|
+
reason: `Daemon land_pr merged PR #${before.number}${after ? "" : " (post-merge view unavailable \u2014 merge verified by gh exit 0)"}`
|
|
7826
8197
|
};
|
|
7827
8198
|
}
|
|
8199
|
+
function viewMergedState(exec, cwd, target, repo) {
|
|
8200
|
+
try {
|
|
8201
|
+
const view = ghJson(exec, cwd, [
|
|
8202
|
+
"pr",
|
|
8203
|
+
"view",
|
|
8204
|
+
target,
|
|
8205
|
+
...repoArgs(repo),
|
|
8206
|
+
"--json",
|
|
8207
|
+
"number,url,mergedAt,mergeCommit,state"
|
|
8208
|
+
]);
|
|
8209
|
+
return view.state === "MERGED" || view.mergedAt ? view : null;
|
|
8210
|
+
} catch {
|
|
8211
|
+
return null;
|
|
8212
|
+
}
|
|
8213
|
+
}
|
|
7828
8214
|
|
|
7829
8215
|
// src/landing/land-pr-completion-post.ts
|
|
8216
|
+
init_config();
|
|
7830
8217
|
async function postLandPrHarnessCompletion(input) {
|
|
7831
8218
|
const secret = await resolveCallbackSecretWithMint(input.secret, input.agentOsId, {
|
|
7832
8219
|
baseUrl: input.baseUrl
|
|
@@ -8111,6 +8498,15 @@ async function dispatchRun(args) {
|
|
|
8111
8498
|
async function runLandPrClaimed(decision) {
|
|
8112
8499
|
const task = decision.task;
|
|
8113
8500
|
const taskId = String(task.id);
|
|
8501
|
+
if (exactTargetMode && !exactTargetIds.has(taskId)) {
|
|
8502
|
+
return abortClaimedSpawn(
|
|
8503
|
+
task,
|
|
8504
|
+
"exact_target_mismatch: dispatch-next returned a different task than requested",
|
|
8505
|
+
{
|
|
8506
|
+
requestedTargetTaskIds: [...exactTargetIds]
|
|
8507
|
+
}
|
|
8508
|
+
);
|
|
8509
|
+
}
|
|
8114
8510
|
const prUrl = task.prUrl ? String(task.prUrl) : "";
|
|
8115
8511
|
if (!prUrl) {
|
|
8116
8512
|
return abortClaimedSpawn(task, "land_pr task missing prUrl");
|
|
@@ -8372,11 +8768,21 @@ async function dispatchRun(args) {
|
|
|
8372
8768
|
}
|
|
8373
8769
|
}
|
|
8374
8770
|
|
|
8771
|
+
// src/index.ts
|
|
8772
|
+
init_disk_gate();
|
|
8773
|
+
init_wsl_host();
|
|
8774
|
+
init_stream();
|
|
8775
|
+
init_shell_command_outcome();
|
|
8776
|
+
init_repo_search();
|
|
8777
|
+
init_heartbeat();
|
|
8778
|
+
|
|
8375
8779
|
// src/box-resource-snapshot.ts
|
|
8376
|
-
|
|
8780
|
+
init_config();
|
|
8781
|
+
init_box_identity();
|
|
8782
|
+
import os8 from "node:os";
|
|
8377
8783
|
function buildBoxResourceSnapshotFromGate(gate, input = {}) {
|
|
8378
8784
|
const boxKind = (input.boxKind ?? resolveBoxKindFromConfig(loadUserConfig())).trim().toLowerCase() || "forge";
|
|
8379
|
-
const hostLabel = input.hostLabel ??
|
|
8785
|
+
const hostLabel = input.hostLabel ?? os8.hostname();
|
|
8380
8786
|
const boxId = input.boxId ?? defaultBoxId(boxKind, hostLabel);
|
|
8381
8787
|
return {
|
|
8382
8788
|
boxId,
|
|
@@ -8410,6 +8816,10 @@ function formatHeartbeatLine(input) {
|
|
|
8410
8816
|
`;
|
|
8411
8817
|
}
|
|
8412
8818
|
|
|
8819
|
+
// src/index.ts
|
|
8820
|
+
init_status();
|
|
8821
|
+
init_landing_gate();
|
|
8822
|
+
|
|
8413
8823
|
// src/fortress-engagement-gate.ts
|
|
8414
8824
|
function isEngagementRequiredSkip(skip2) {
|
|
8415
8825
|
if (skip2.skipReason === "engagement_required") return true;
|
|
@@ -8417,6 +8827,10 @@ function isEngagementRequiredSkip(skip2) {
|
|
|
8417
8827
|
return reason.includes("engagement_required") || reason.includes("engagement_not_found") || reason.includes("engagement_expired") || reason.includes("engagement_revoked");
|
|
8418
8828
|
}
|
|
8419
8829
|
|
|
8830
|
+
// src/index.ts
|
|
8831
|
+
init_landing_contract_gate();
|
|
8832
|
+
init_exited_salvage();
|
|
8833
|
+
|
|
8420
8834
|
// src/providers/openai-codex-resilience.ts
|
|
8421
8835
|
var OPENAI_CODEX_PROVIDER = "openai-codex";
|
|
8422
8836
|
var TRANSIENT_OPENAI_CODEX_ERROR_CLASSES = /* @__PURE__ */ new Set([
|
|
@@ -8706,6 +9120,9 @@ function redactHarness(text, secret) {
|
|
|
8706
9120
|
return out;
|
|
8707
9121
|
}
|
|
8708
9122
|
|
|
9123
|
+
// src/index.ts
|
|
9124
|
+
init_worker_env();
|
|
9125
|
+
|
|
8709
9126
|
// src/db-credential-env-paths.ts
|
|
8710
9127
|
import * as fs from "node:fs";
|
|
8711
9128
|
import { homedir as homedir12 } from "node:os";
|
|
@@ -8923,10 +9340,14 @@ function applyProductionDatabaseToProcess(options = {}) {
|
|
|
8923
9340
|
}
|
|
8924
9341
|
|
|
8925
9342
|
// src/worktree.ts
|
|
9343
|
+
init_git();
|
|
9344
|
+
init_run_store();
|
|
8926
9345
|
import { existsSync as existsSync29, mkdirSync as mkdirSync6 } from "node:fs";
|
|
8927
9346
|
import path38 from "node:path";
|
|
8928
9347
|
|
|
8929
9348
|
// src/run-list.ts
|
|
9349
|
+
init_run_store();
|
|
9350
|
+
init_run_worker_index();
|
|
8930
9351
|
import { existsSync as existsSync28, readFileSync as readFileSync15 } from "node:fs";
|
|
8931
9352
|
import path37 from "node:path";
|
|
8932
9353
|
|
|
@@ -8934,6 +9355,10 @@ import path37 from "node:path";
|
|
|
8934
9355
|
import path36 from "node:path";
|
|
8935
9356
|
|
|
8936
9357
|
// src/finalize.ts
|
|
9358
|
+
init_run_store();
|
|
9359
|
+
init_run_worker_index();
|
|
9360
|
+
init_status();
|
|
9361
|
+
init_util();
|
|
8937
9362
|
import path30 from "node:path";
|
|
8938
9363
|
var ACTIVE_RUN_STATUSES = /* @__PURE__ */ new Set([
|
|
8939
9364
|
"running",
|
|
@@ -8991,11 +9416,21 @@ function finalizeStaleRuns() {
|
|
|
8991
9416
|
return finalized;
|
|
8992
9417
|
}
|
|
8993
9418
|
|
|
9419
|
+
// src/stale-reconcile.ts
|
|
9420
|
+
init_run_store();
|
|
9421
|
+
init_run_worker_index();
|
|
9422
|
+
init_status();
|
|
9423
|
+
init_util();
|
|
9424
|
+
|
|
8994
9425
|
// src/worker-metadata-reconcile.ts
|
|
9426
|
+
init_heartbeat();
|
|
9427
|
+
init_stream();
|
|
8995
9428
|
import { existsSync as existsSync27, lstatSync, readdirSync as readdirSync7, readlinkSync, renameSync as renameSync2, rmSync } from "node:fs";
|
|
8996
9429
|
import path34 from "node:path";
|
|
8997
9430
|
|
|
8998
9431
|
// src/worker-metadata-paths.ts
|
|
9432
|
+
init_paths();
|
|
9433
|
+
init_util();
|
|
8999
9434
|
import path31 from "node:path";
|
|
9000
9435
|
var NESTED_RUNS = `${path31.sep}runs${path31.sep}runs${path31.sep}`;
|
|
9001
9436
|
function hasNestedRunsSegment(filePath) {
|
|
@@ -9053,6 +9488,9 @@ import { existsSync as existsSync26, readdirSync as readdirSync6, statSync as st
|
|
|
9053
9488
|
import path33 from "node:path";
|
|
9054
9489
|
|
|
9055
9490
|
// src/default-repo.ts
|
|
9491
|
+
init_config();
|
|
9492
|
+
init_default_repo_discovery();
|
|
9493
|
+
init_path_values();
|
|
9056
9494
|
import path32 from "node:path";
|
|
9057
9495
|
function expandConfiguredRepo(value) {
|
|
9058
9496
|
return path32.resolve(resolveUserPath(value.trim()));
|
|
@@ -9122,6 +9560,10 @@ function formatResolvedDefaultRepo(resolved) {
|
|
|
9122
9560
|
}
|
|
9123
9561
|
|
|
9124
9562
|
// src/run-metadata-retention.ts
|
|
9563
|
+
init_heartbeat();
|
|
9564
|
+
init_paths();
|
|
9565
|
+
init_run_store();
|
|
9566
|
+
init_util();
|
|
9125
9567
|
var RUN_METADATA_ACTIVE_SIGNAL_MS = 15 * 60 * 1e3;
|
|
9126
9568
|
function isHarnessRunMetadataPath(targetPath, harnessRoot) {
|
|
9127
9569
|
const resolved = path33.resolve(targetPath);
|
|
@@ -9262,6 +9704,8 @@ function collectFilesystemLiveRunKeys(harnessRoot, now = Date.now()) {
|
|
|
9262
9704
|
}
|
|
9263
9705
|
|
|
9264
9706
|
// src/worker-metadata-reconcile.ts
|
|
9707
|
+
init_run_store();
|
|
9708
|
+
init_util();
|
|
9265
9709
|
function materializeSymlinkedRunDir(harnessRoot, runId) {
|
|
9266
9710
|
const canonical = canonicalRunDir(harnessRoot, runId);
|
|
9267
9711
|
let stat;
|
|
@@ -9567,6 +10011,12 @@ function reconcileWorkerMetadataCli() {
|
|
|
9567
10011
|
}
|
|
9568
10012
|
|
|
9569
10013
|
// src/local-pr-attention-reconcile.ts
|
|
10014
|
+
init_heartbeat();
|
|
10015
|
+
init_worker_final_result_embed();
|
|
10016
|
+
init_status();
|
|
10017
|
+
init_run_store();
|
|
10018
|
+
init_run_worker_index();
|
|
10019
|
+
init_util();
|
|
9570
10020
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
9571
10021
|
import path35 from "node:path";
|
|
9572
10022
|
function normalizePrUrl3(url) {
|
|
@@ -9893,6 +10343,8 @@ function reconcileRunsCli() {
|
|
|
9893
10343
|
}
|
|
9894
10344
|
|
|
9895
10345
|
// src/run-list.ts
|
|
10346
|
+
init_status();
|
|
10347
|
+
init_util();
|
|
9896
10348
|
function heartbeatByteLength(heartbeatPath) {
|
|
9897
10349
|
if (!heartbeatPath || !existsSync28(heartbeatPath)) return 0;
|
|
9898
10350
|
try {
|
|
@@ -10008,6 +10460,7 @@ function listRunsCli() {
|
|
|
10008
10460
|
}
|
|
10009
10461
|
|
|
10010
10462
|
// src/worktree.ts
|
|
10463
|
+
init_util();
|
|
10011
10464
|
function resolveCreateRunRepo(args) {
|
|
10012
10465
|
const explicit = typeof args.repo === "string" ? args.repo.trim() : "";
|
|
10013
10466
|
if (explicit) return explicit;
|
|
@@ -10047,6 +10500,7 @@ function failExists(message) {
|
|
|
10047
10500
|
}
|
|
10048
10501
|
|
|
10049
10502
|
// src/run-resolve.ts
|
|
10503
|
+
init_util();
|
|
10050
10504
|
function resolveHarnessRunByName(runName) {
|
|
10051
10505
|
const name = runName.trim();
|
|
10052
10506
|
if (!name) return null;
|
|
@@ -10070,8 +10524,15 @@ function resolveHarnessRunCli(args) {
|
|
|
10070
10524
|
);
|
|
10071
10525
|
}
|
|
10072
10526
|
|
|
10527
|
+
// src/index.ts
|
|
10528
|
+
init_harness_worker_active();
|
|
10529
|
+
|
|
10073
10530
|
// src/sweep.ts
|
|
10531
|
+
init_config();
|
|
10074
10532
|
import path39 from "node:path";
|
|
10533
|
+
init_run_store();
|
|
10534
|
+
init_status();
|
|
10535
|
+
init_util();
|
|
10075
10536
|
async function sweepRun(args) {
|
|
10076
10537
|
const pipeline = args.pipeline === true || args.pipeline === "true";
|
|
10077
10538
|
try {
|
|
@@ -10131,7 +10592,13 @@ async function sweepRun(args) {
|
|
|
10131
10592
|
}
|
|
10132
10593
|
}
|
|
10133
10594
|
|
|
10595
|
+
// src/index.ts
|
|
10596
|
+
init_config();
|
|
10597
|
+
init_default_repo_discovery();
|
|
10598
|
+
init_paths();
|
|
10599
|
+
|
|
10134
10600
|
// src/harness-storage-snapshot.ts
|
|
10601
|
+
init_paths();
|
|
10135
10602
|
import { existsSync as existsSync31, readdirSync as readdirSync9, statSync as statSync7 } from "node:fs";
|
|
10136
10603
|
import path41 from "node:path";
|
|
10137
10604
|
|
|
@@ -10259,11 +10726,17 @@ function harnessStorageSnapshot(opts = {}) {
|
|
|
10259
10726
|
}
|
|
10260
10727
|
|
|
10261
10728
|
// src/cleanup.ts
|
|
10729
|
+
init_paths();
|
|
10262
10730
|
import path53 from "node:path";
|
|
10263
10731
|
|
|
10264
10732
|
// src/cleanup-guards.ts
|
|
10733
|
+
init_landing_gate();
|
|
10265
10734
|
import path42 from "node:path";
|
|
10266
10735
|
|
|
10736
|
+
// src/cleanup-index-status.ts
|
|
10737
|
+
init_git();
|
|
10738
|
+
init_status();
|
|
10739
|
+
|
|
10267
10740
|
// src/cleanup-build-cache-paths.ts
|
|
10268
10741
|
var HARNESS_BUILD_CACHE_RELATIVE_PATHS = [
|
|
10269
10742
|
".next",
|
|
@@ -10318,6 +10791,7 @@ function isPrOrUnmergedWork(status) {
|
|
|
10318
10791
|
}
|
|
10319
10792
|
|
|
10320
10793
|
// src/cleanup-index-status.ts
|
|
10794
|
+
init_util();
|
|
10321
10795
|
function indexedWorktreeStatus(entry) {
|
|
10322
10796
|
if (!entry.status) {
|
|
10323
10797
|
entry.status = computeWorkerStatus(entry.worker, {
|
|
@@ -10394,7 +10868,15 @@ function resolveWorktreeGuardStatus(entry, ctx) {
|
|
|
10394
10868
|
return indexedWorktreeStatus(entry);
|
|
10395
10869
|
}
|
|
10396
10870
|
|
|
10871
|
+
// src/cleanup-guards.ts
|
|
10872
|
+
init_status();
|
|
10873
|
+
|
|
10874
|
+
// src/cleanup-run-liveness.ts
|
|
10875
|
+
init_status();
|
|
10876
|
+
|
|
10397
10877
|
// src/cleanup-completion-blocker.ts
|
|
10878
|
+
init_landing_gate();
|
|
10879
|
+
init_status();
|
|
10398
10880
|
function completionBlockerBlocksWorktreeRemoval(indexed, status) {
|
|
10399
10881
|
const blocker = typeof indexed.worker.completionBlocker === "string" ? indexed.worker.completionBlocker.trim() : "";
|
|
10400
10882
|
if (!blocker) return false;
|
|
@@ -10414,6 +10896,7 @@ function completionBlockerBlocksWorktreeRemoval(indexed, status) {
|
|
|
10414
10896
|
}
|
|
10415
10897
|
|
|
10416
10898
|
// src/cleanup-run-liveness.ts
|
|
10899
|
+
init_util();
|
|
10417
10900
|
var TERMINAL_WORKER_JSON_STATUSES = /* @__PURE__ */ new Set([
|
|
10418
10901
|
"done",
|
|
10419
10902
|
"exited",
|
|
@@ -10544,11 +11027,11 @@ var LIVE_SKIP_REASONS = /* @__PURE__ */ new Set([
|
|
|
10544
11027
|
function collectPreservedLivePaths(actions, skips) {
|
|
10545
11028
|
const out = [];
|
|
10546
11029
|
const seen = /* @__PURE__ */ new Set();
|
|
10547
|
-
const push = (
|
|
10548
|
-
const key = `${
|
|
11030
|
+
const push = (path75, reason, detail) => {
|
|
11031
|
+
const key = `${path75}\0${reason}`;
|
|
10549
11032
|
if (seen.has(key) || out.length >= MAX_PRESERVED_LIVE_PATH_SAMPLES) return;
|
|
10550
11033
|
seen.add(key);
|
|
10551
|
-
out.push({ path:
|
|
11034
|
+
out.push({ path: path75, reason, ...detail ? { detail } : {} });
|
|
10552
11035
|
};
|
|
10553
11036
|
for (const skip2 of skips) {
|
|
10554
11037
|
if (!LIVE_SKIP_REASONS.has(skip2.reason)) continue;
|
|
@@ -10567,8 +11050,11 @@ import { existsSync as existsSync33, readdirSync as readdirSync11, statSync as s
|
|
|
10567
11050
|
import path44 from "node:path";
|
|
10568
11051
|
|
|
10569
11052
|
// src/cleanup-active-worktrees.ts
|
|
11053
|
+
init_run_store();
|
|
11054
|
+
init_paths();
|
|
10570
11055
|
import { existsSync as existsSync32, readdirSync as readdirSync10, statSync as statSync8 } from "node:fs";
|
|
10571
11056
|
import path43 from "node:path";
|
|
11057
|
+
init_util();
|
|
10572
11058
|
function workerHasRecentHarnessActivity(worker, now) {
|
|
10573
11059
|
const paths = [worker.heartbeatPath, worker.stdoutPath, worker.stderrPath];
|
|
10574
11060
|
for (const target of paths) {
|
|
@@ -10617,6 +11103,7 @@ function isWorktreeOnLiveRun(worktreePath, harnessRoot, runId, liveRunKeys) {
|
|
|
10617
11103
|
}
|
|
10618
11104
|
|
|
10619
11105
|
// src/cleanup-run-directory.ts
|
|
11106
|
+
init_util();
|
|
10620
11107
|
function pathAgeMs(target, now) {
|
|
10621
11108
|
try {
|
|
10622
11109
|
const mtime = statSync9(target).mtimeMs;
|
|
@@ -10679,10 +11166,12 @@ function scanStaleRunDirectoryCandidates(opts) {
|
|
|
10679
11166
|
}
|
|
10680
11167
|
|
|
10681
11168
|
// src/cleanup-execute.ts
|
|
11169
|
+
init_git();
|
|
10682
11170
|
import { existsSync as existsSync35, rmSync as rmSync3 } from "node:fs";
|
|
10683
11171
|
|
|
10684
11172
|
// src/cleanup-remove-path.ts
|
|
10685
11173
|
import { existsSync as existsSync34, rmSync as rmSync2 } from "node:fs";
|
|
11174
|
+
init_paths();
|
|
10686
11175
|
|
|
10687
11176
|
// src/cleanup-path-ownership.ts
|
|
10688
11177
|
import { lstatSync as lstatSync2, readdirSync as readdirSync12 } from "node:fs";
|
|
@@ -11191,6 +11680,7 @@ function scanDependencyCacheCandidates(opts) {
|
|
|
11191
11680
|
}
|
|
11192
11681
|
|
|
11193
11682
|
// src/cleanup-duplicate-worktrees.ts
|
|
11683
|
+
init_git();
|
|
11194
11684
|
import { existsSync as existsSync38, statSync as statSync12 } from "node:fs";
|
|
11195
11685
|
import path49 from "node:path";
|
|
11196
11686
|
function pathAgeMs4(target, now) {
|
|
@@ -11283,6 +11773,8 @@ function scanDuplicateWorktreeCandidates(opts) {
|
|
|
11283
11773
|
}
|
|
11284
11774
|
|
|
11285
11775
|
// src/cleanup-worktree-index.ts
|
|
11776
|
+
init_run_store();
|
|
11777
|
+
init_util();
|
|
11286
11778
|
import path50 from "node:path";
|
|
11287
11779
|
function buildWorktreeIndexAt(harnessRoot) {
|
|
11288
11780
|
const index = /* @__PURE__ */ new Map();
|
|
@@ -11367,6 +11859,7 @@ function resolvePipelineHarnessRetention(runId) {
|
|
|
11367
11859
|
}
|
|
11368
11860
|
|
|
11369
11861
|
// src/cleanup-orphan-safety.ts
|
|
11862
|
+
init_git();
|
|
11370
11863
|
import { existsSync as existsSync39, statSync as statSync13 } from "node:fs";
|
|
11371
11864
|
import path51 from "node:path";
|
|
11372
11865
|
var DEFAULT_HEARTBEAT_FRESH_MS = 30 * 60 * 1e3;
|
|
@@ -11419,6 +11912,7 @@ function assessOrphanWorktreeSafety(input) {
|
|
|
11419
11912
|
}
|
|
11420
11913
|
|
|
11421
11914
|
// src/cleanup-harness-roots.ts
|
|
11915
|
+
init_paths();
|
|
11422
11916
|
import { existsSync as existsSync40 } from "node:fs";
|
|
11423
11917
|
import { homedir as homedir13 } from "node:os";
|
|
11424
11918
|
import path52 from "node:path";
|
|
@@ -11454,6 +11948,7 @@ function resolveHarnessScanRoots(options = {}) {
|
|
|
11454
11948
|
}
|
|
11455
11949
|
|
|
11456
11950
|
// src/cleanup-disk-pressure.ts
|
|
11951
|
+
init_disk_gate();
|
|
11457
11952
|
function envFlag2(name) {
|
|
11458
11953
|
const v = process.env[name];
|
|
11459
11954
|
return v === "1" || v === "true" || v === "yes";
|
|
@@ -11503,6 +11998,7 @@ function emitCleanupProgress(phase, detail) {
|
|
|
11503
11998
|
}
|
|
11504
11999
|
|
|
11505
12000
|
// src/cleanup-git-rev-cache.ts
|
|
12001
|
+
init_git();
|
|
11506
12002
|
var CleanupGitRevCache = class {
|
|
11507
12003
|
aheadOfMain = /* @__PURE__ */ new Map();
|
|
11508
12004
|
countAheadOfMain(worktreePath, base = "origin/main") {
|
|
@@ -11521,6 +12017,7 @@ var CleanupGitRevCache = class {
|
|
|
11521
12017
|
};
|
|
11522
12018
|
|
|
11523
12019
|
// src/cleanup-git-status-cache.ts
|
|
12020
|
+
init_git();
|
|
11524
12021
|
var CleanupGitStatusCache = class {
|
|
11525
12022
|
cache = /* @__PURE__ */ new Map();
|
|
11526
12023
|
porcelain(worktreePath) {
|
|
@@ -11950,10 +12447,79 @@ function isPipelineCleanupEnabled() {
|
|
|
11950
12447
|
}
|
|
11951
12448
|
|
|
11952
12449
|
// src/cli.ts
|
|
11953
|
-
|
|
12450
|
+
init_config();
|
|
12451
|
+
import { mkdirSync as mkdirSync11, realpathSync } from "node:fs";
|
|
11954
12452
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
11955
12453
|
|
|
12454
|
+
// src/bootstrap.ts
|
|
12455
|
+
init_config();
|
|
12456
|
+
init_util();
|
|
12457
|
+
init_device_login();
|
|
12458
|
+
import os9 from "node:os";
|
|
12459
|
+
function resolveBootstrapBaseUrl(args) {
|
|
12460
|
+
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;
|
|
12461
|
+
return raw ? trimTrailingSlash(String(raw)) : void 0;
|
|
12462
|
+
}
|
|
12463
|
+
async function fetchPrimaryAgentOs(base, apiKey) {
|
|
12464
|
+
const res = await fetch(`${base}/api/agent-os`, {
|
|
12465
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
12466
|
+
});
|
|
12467
|
+
if (!res.ok) return null;
|
|
12468
|
+
const body = await res.json().catch(() => null);
|
|
12469
|
+
if (!body?.primarySlug) return null;
|
|
12470
|
+
const match = body.items?.find((it) => it.slug === body.primarySlug);
|
|
12471
|
+
if (match?.id && match.slug) return { id: match.id, slug: match.slug };
|
|
12472
|
+
return { id: "", slug: body.primarySlug };
|
|
12473
|
+
}
|
|
12474
|
+
async function runBootstrap(args) {
|
|
12475
|
+
const base = resolveBootstrapBaseUrl(args);
|
|
12476
|
+
if (!base) {
|
|
12477
|
+
console.error(
|
|
12478
|
+
"kynver bootstrap requires a Kynver URL \u2014 pass --api-base-url https://your-kynver-site or set KYNVER_API_URL."
|
|
12479
|
+
);
|
|
12480
|
+
process.exit(1);
|
|
12481
|
+
}
|
|
12482
|
+
if (!loadApiKey()) {
|
|
12483
|
+
if (typeof args.apiKey === "string") {
|
|
12484
|
+
saveApiKey(args.apiKey);
|
|
12485
|
+
} else {
|
|
12486
|
+
const login = await runDeviceLogin({ ...args, apiBaseUrl: base });
|
|
12487
|
+
if (!login.ok) process.exit(1);
|
|
12488
|
+
}
|
|
12489
|
+
}
|
|
12490
|
+
const apiKey = loadApiKey();
|
|
12491
|
+
if (!apiKey) {
|
|
12492
|
+
console.error("No API key after login \u2014 aborting.");
|
|
12493
|
+
process.exit(1);
|
|
12494
|
+
}
|
|
12495
|
+
const primary = await fetchPrimaryAgentOs(base, apiKey);
|
|
12496
|
+
if (!primary) {
|
|
12497
|
+
console.error(
|
|
12498
|
+
"Could not resolve your AgentOS workspace from the account. Confirm this account has AgentOS access, then retry."
|
|
12499
|
+
);
|
|
12500
|
+
process.exit(1);
|
|
12501
|
+
}
|
|
12502
|
+
const setupArgs = {
|
|
12503
|
+
...args,
|
|
12504
|
+
apiBaseUrl: base,
|
|
12505
|
+
agentOsSlug: primary.slug,
|
|
12506
|
+
...primary.id ? { agentOsId: primary.id } : {},
|
|
12507
|
+
// Best-effort repo discovery unless the caller pinned one.
|
|
12508
|
+
...typeof args.repo === "string" ? {} : { discoverRepo: true }
|
|
12509
|
+
};
|
|
12510
|
+
await runSetup(setupArgs);
|
|
12511
|
+
console.log("");
|
|
12512
|
+
console.log(` Bootstrap complete \u2014 ${os9.hostname()} is linked to workspace "${primary.slug}".`);
|
|
12513
|
+
console.log(" Next: run autonomous work with `kynver daemon --run <RUN_ID> --agent-os-id <AOS_ID> --execute`");
|
|
12514
|
+
console.log(" (create a run first with `kynver run create --repo /path/to/repo`).");
|
|
12515
|
+
}
|
|
12516
|
+
|
|
12517
|
+
// src/cli.ts
|
|
12518
|
+
init_run_store();
|
|
12519
|
+
|
|
11956
12520
|
// src/discard-disposable.ts
|
|
12521
|
+
init_run_store();
|
|
12522
|
+
init_status();
|
|
11957
12523
|
import { existsSync as existsSync41, rmSync as rmSync4 } from "node:fs";
|
|
11958
12524
|
import path54 from "node:path";
|
|
11959
12525
|
function normalizeRelativePath2(value) {
|
|
@@ -12007,8 +12573,14 @@ function discardDisposableCli(args) {
|
|
|
12007
12573
|
if (!result.ok) process.exit(1);
|
|
12008
12574
|
}
|
|
12009
12575
|
|
|
12576
|
+
// src/daemon.ts
|
|
12577
|
+
init_config();
|
|
12578
|
+
|
|
12010
12579
|
// src/daemon-box-identity.ts
|
|
12011
|
-
|
|
12580
|
+
init_config();
|
|
12581
|
+
init_box_identity();
|
|
12582
|
+
init_worker_cap_source();
|
|
12583
|
+
import os10 from "node:os";
|
|
12012
12584
|
function emitDaemonIdentityMessage(level, message) {
|
|
12013
12585
|
console.error(JSON.stringify({ event: "daemon_identity", level, message }));
|
|
12014
12586
|
}
|
|
@@ -12016,7 +12588,7 @@ function validateDaemonInstallIdentity(config = loadUserConfig(), env = process.
|
|
|
12016
12588
|
const box = resolveBoxIdentity(env, config);
|
|
12017
12589
|
const cap = resolveWorkerCap({
|
|
12018
12590
|
config,
|
|
12019
|
-
totalMemBytes:
|
|
12591
|
+
totalMemBytes: os10.totalmem(),
|
|
12020
12592
|
env
|
|
12021
12593
|
});
|
|
12022
12594
|
const warnings = [...box.warnings];
|
|
@@ -12046,6 +12618,47 @@ function validateDaemonInstallIdentity(config = loadUserConfig(), env = process.
|
|
|
12046
12618
|
};
|
|
12047
12619
|
}
|
|
12048
12620
|
|
|
12621
|
+
// src/daemon-heartbeat.ts
|
|
12622
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync16, renameSync as renameSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
12623
|
+
import { homedir as homedir14 } from "node:os";
|
|
12624
|
+
import path55 from "node:path";
|
|
12625
|
+
function daemonHeartbeatPath(agentOsId) {
|
|
12626
|
+
const safe = agentOsId.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
12627
|
+
return path55.join(homedir14(), ".kynver", `daemon-heartbeat-${safe}.json`);
|
|
12628
|
+
}
|
|
12629
|
+
function writeDaemonHeartbeat(input) {
|
|
12630
|
+
try {
|
|
12631
|
+
const file = daemonHeartbeatPath(input.agentOsId);
|
|
12632
|
+
mkdirSync7(path55.dirname(file), { recursive: true });
|
|
12633
|
+
const beat = {
|
|
12634
|
+
observedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
12635
|
+
pid: process.pid,
|
|
12636
|
+
runId: input.runId,
|
|
12637
|
+
agentOsId: input.agentOsId
|
|
12638
|
+
};
|
|
12639
|
+
const tmp = `${file}.tmp-${process.pid}`;
|
|
12640
|
+
writeFileSync4(tmp, JSON.stringify(beat), "utf8");
|
|
12641
|
+
renameSync3(tmp, file);
|
|
12642
|
+
} catch {
|
|
12643
|
+
}
|
|
12644
|
+
}
|
|
12645
|
+
function readDaemonHeartbeat(agentOsId) {
|
|
12646
|
+
try {
|
|
12647
|
+
const raw = readFileSync16(daemonHeartbeatPath(agentOsId), "utf8");
|
|
12648
|
+
const parsed = JSON.parse(raw);
|
|
12649
|
+
if (typeof parsed?.observedAt !== "string") return null;
|
|
12650
|
+
return parsed;
|
|
12651
|
+
} catch {
|
|
12652
|
+
return null;
|
|
12653
|
+
}
|
|
12654
|
+
}
|
|
12655
|
+
function isDaemonHeartbeatStale(beat, stallMs, nowMs = Date.now()) {
|
|
12656
|
+
if (!beat) return false;
|
|
12657
|
+
const observed = Date.parse(beat.observedAt);
|
|
12658
|
+
if (Number.isNaN(observed)) return true;
|
|
12659
|
+
return nowMs - observed > stallMs;
|
|
12660
|
+
}
|
|
12661
|
+
|
|
12049
12662
|
// src/daemon-platform-guard.ts
|
|
12050
12663
|
function envFlag3(name) {
|
|
12051
12664
|
const raw = process.env[name]?.trim().toLowerCase();
|
|
@@ -12065,9 +12678,10 @@ function assertNativeDaemonAllowed() {
|
|
|
12065
12678
|
}
|
|
12066
12679
|
|
|
12067
12680
|
// src/cron/cron-env.ts
|
|
12681
|
+
init_config();
|
|
12068
12682
|
import { existsSync as existsSync42 } from "node:fs";
|
|
12069
|
-
import { homedir as
|
|
12070
|
-
import
|
|
12683
|
+
import { homedir as homedir15 } from "node:os";
|
|
12684
|
+
import path56 from "node:path";
|
|
12071
12685
|
function envFlag4(name, defaultValue) {
|
|
12072
12686
|
const raw = process.env[name]?.trim().toLowerCase();
|
|
12073
12687
|
if (!raw) return defaultValue;
|
|
@@ -12083,7 +12697,7 @@ function envInt(name, fallback, min = 1) {
|
|
|
12083
12697
|
function defaultKynverCronStorePath() {
|
|
12084
12698
|
const explicit = process.env.KYNVER_CRON_STORE_PATH?.trim() || process.env.OPENCLAW_CRON_STORE_PATH?.trim();
|
|
12085
12699
|
if (explicit) return explicit;
|
|
12086
|
-
return
|
|
12700
|
+
return path56.join(homedir15(), ".kynver", "agent-os-cron.json");
|
|
12087
12701
|
}
|
|
12088
12702
|
function defaultKynverCronStatePath(storePath = defaultKynverCronStorePath()) {
|
|
12089
12703
|
const explicit = process.env.KYNVER_CRON_TICK_STATE_PATH?.trim();
|
|
@@ -12156,12 +12770,13 @@ async function fireKynverCronJob(input) {
|
|
|
12156
12770
|
}
|
|
12157
12771
|
|
|
12158
12772
|
// src/cron/cron-lock.ts
|
|
12159
|
-
|
|
12773
|
+
init_util();
|
|
12774
|
+
import { closeSync as closeSync6, existsSync as existsSync43, openSync as openSync6, readFileSync as readFileSync17, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
12160
12775
|
var STALE_LOCK_MS = 10 * 6e4;
|
|
12161
12776
|
function readLockInfo(lockPath) {
|
|
12162
12777
|
if (!existsSync43(lockPath)) return null;
|
|
12163
12778
|
try {
|
|
12164
|
-
const parsed = JSON.parse(
|
|
12779
|
+
const parsed = JSON.parse(readFileSync17(lockPath, "utf8"));
|
|
12165
12780
|
if (typeof parsed.pid === "number" && typeof parsed.at === "string") return parsed;
|
|
12166
12781
|
} catch {
|
|
12167
12782
|
return null;
|
|
@@ -12192,7 +12807,7 @@ function tryAcquireCronTickLock(lockPath) {
|
|
|
12192
12807
|
}
|
|
12193
12808
|
try {
|
|
12194
12809
|
const fd = openSync6(lockPath, "wx");
|
|
12195
|
-
|
|
12810
|
+
writeFileSync5(
|
|
12196
12811
|
fd,
|
|
12197
12812
|
JSON.stringify({ pid: process.pid, at: (/* @__PURE__ */ new Date()).toISOString() }),
|
|
12198
12813
|
"utf8"
|
|
@@ -12325,7 +12940,7 @@ async function loadCronJobs(storePath = defaultKynverCronStorePath()) {
|
|
|
12325
12940
|
// src/cron/cron-tick-state.ts
|
|
12326
12941
|
import { randomBytes } from "node:crypto";
|
|
12327
12942
|
import { promises as fs4 } from "node:fs";
|
|
12328
|
-
import
|
|
12943
|
+
import path57 from "node:path";
|
|
12329
12944
|
var EMPTY = { version: 1, jobs: {} };
|
|
12330
12945
|
async function readFileIfExists2(filePath) {
|
|
12331
12946
|
try {
|
|
@@ -12352,7 +12967,7 @@ async function loadCronTickState(statePath) {
|
|
|
12352
12967
|
return parseCronTickState(raw);
|
|
12353
12968
|
}
|
|
12354
12969
|
async function writeStateAtomic(statePath, state) {
|
|
12355
|
-
await fs4.mkdir(
|
|
12970
|
+
await fs4.mkdir(path57.dirname(statePath), { recursive: true });
|
|
12356
12971
|
const suffix = randomBytes(6).toString("hex");
|
|
12357
12972
|
const tmp = `${statePath}.tmp-${process.pid}-${Date.now()}-${suffix}`;
|
|
12358
12973
|
await fs4.writeFile(tmp, `${JSON.stringify(state, null, 2)}
|
|
@@ -12528,8 +13143,12 @@ async function runKynverCronTick(opts = {}) {
|
|
|
12528
13143
|
}
|
|
12529
13144
|
}
|
|
12530
13145
|
|
|
13146
|
+
// src/daemon.ts
|
|
13147
|
+
init_util();
|
|
13148
|
+
|
|
12531
13149
|
// src/pipeline-tick.ts
|
|
12532
|
-
import
|
|
13150
|
+
import path60 from "node:path";
|
|
13151
|
+
init_config();
|
|
12533
13152
|
|
|
12534
13153
|
// src/pipeline-dispatch.ts
|
|
12535
13154
|
var RESERVED_REVIEW_STARTS = 1;
|
|
@@ -12659,10 +13278,21 @@ function resolvePipelineMaxStarts(resourceGate, operatorTick) {
|
|
|
12659
13278
|
};
|
|
12660
13279
|
}
|
|
12661
13280
|
|
|
13281
|
+
// src/pipeline-tick.ts
|
|
13282
|
+
init_resource_gate();
|
|
13283
|
+
init_run_store();
|
|
13284
|
+
init_exited_salvage();
|
|
13285
|
+
init_status();
|
|
13286
|
+
init_util();
|
|
13287
|
+
|
|
12662
13288
|
// src/plan-progress-daemon-sync.ts
|
|
12663
|
-
|
|
13289
|
+
init_status();
|
|
13290
|
+
init_run_store();
|
|
13291
|
+
init_util();
|
|
13292
|
+
import path58 from "node:path";
|
|
12664
13293
|
|
|
12665
13294
|
// src/plan-progress-sync.ts
|
|
13295
|
+
init_config();
|
|
12666
13296
|
async function syncPlanProgress(args) {
|
|
12667
13297
|
const base = resolveBaseUrl(args.baseUrl);
|
|
12668
13298
|
const secret = await resolveCallbackSecretWithMint(args.secret, args.agentOsId, { baseUrl: base });
|
|
@@ -12684,7 +13314,7 @@ async function syncActiveWorkerPlanProgress(runId, args) {
|
|
|
12684
13314
|
const outcomes = [];
|
|
12685
13315
|
for (const name of Object.keys(run.workers || {})) {
|
|
12686
13316
|
const worker = readJson(
|
|
12687
|
-
|
|
13317
|
+
path58.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
12688
13318
|
void 0
|
|
12689
13319
|
);
|
|
12690
13320
|
if (!worker?.dispatched || !worker.taskId) continue;
|
|
@@ -12712,6 +13342,8 @@ async function syncActiveWorkerPlanProgress(runId, args) {
|
|
|
12712
13342
|
}
|
|
12713
13343
|
|
|
12714
13344
|
// src/workspace-runtime-config.ts
|
|
13345
|
+
init_config();
|
|
13346
|
+
init_box_identity();
|
|
12715
13347
|
function shouldApplyWorkspaceRuntimePreferences(env = process.env) {
|
|
12716
13348
|
const config = loadUserConfig();
|
|
12717
13349
|
return resolveBoxKindFromConfig(config, env) !== "forge";
|
|
@@ -12740,13 +13372,359 @@ async function fetchWorkspaceRuntimePreferences(agentOsId, args) {
|
|
|
12740
13372
|
}
|
|
12741
13373
|
}
|
|
12742
13374
|
|
|
13375
|
+
// src/pipeline-tick.ts
|
|
13376
|
+
init_config();
|
|
13377
|
+
init_box_identity();
|
|
13378
|
+
|
|
13379
|
+
// src/provider-evidence/exec.ts
|
|
13380
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
13381
|
+
var DEFAULT_CLI_TIMEOUT_MS = 1e4;
|
|
13382
|
+
var MAX_CLI_BUFFER_BYTES = 4 * 1024 * 1024;
|
|
13383
|
+
var defaultCliRunner = (cmd, args, opts) => {
|
|
13384
|
+
try {
|
|
13385
|
+
const result = spawnSync8(cmd, args, {
|
|
13386
|
+
encoding: "utf8",
|
|
13387
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
13388
|
+
timeout: opts?.timeoutMs ?? DEFAULT_CLI_TIMEOUT_MS,
|
|
13389
|
+
maxBuffer: MAX_CLI_BUFFER_BYTES
|
|
13390
|
+
});
|
|
13391
|
+
return {
|
|
13392
|
+
ok: result.status === 0,
|
|
13393
|
+
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
13394
|
+
stderr: typeof result.stderr === "string" ? result.stderr : ""
|
|
13395
|
+
};
|
|
13396
|
+
} catch (err) {
|
|
13397
|
+
return { ok: false, stdout: "", stderr: err instanceof Error ? err.message : String(err) };
|
|
13398
|
+
}
|
|
13399
|
+
};
|
|
13400
|
+
function runCliJson(run, cmd, args) {
|
|
13401
|
+
const result = run(cmd, args);
|
|
13402
|
+
if (!result.ok || !result.stdout.trim()) return null;
|
|
13403
|
+
try {
|
|
13404
|
+
return JSON.parse(result.stdout);
|
|
13405
|
+
} catch {
|
|
13406
|
+
return null;
|
|
13407
|
+
}
|
|
13408
|
+
}
|
|
13409
|
+
|
|
13410
|
+
// src/provider-evidence/types.ts
|
|
13411
|
+
function providerEvidenceKey(provider, kind, subject) {
|
|
13412
|
+
return `${provider} ${kind} ${subject}`;
|
|
13413
|
+
}
|
|
13414
|
+
function parseCommitEvidenceSubject(subject) {
|
|
13415
|
+
const at = subject.lastIndexOf("@");
|
|
13416
|
+
if (at <= 0 || at === subject.length - 1) return null;
|
|
13417
|
+
const repo = subject.slice(0, at);
|
|
13418
|
+
const sha = subject.slice(at + 1);
|
|
13419
|
+
if (!/^[^/\s]+\/[^/\s]+$/.test(repo) || !/^[0-9a-f]{7,40}$/i.test(sha)) return null;
|
|
13420
|
+
return { repo, sha };
|
|
13421
|
+
}
|
|
13422
|
+
function parsePrUrlSubject(subject) {
|
|
13423
|
+
const m = subject.trim().match(/[/:]([^/]+\/[^/]+)\/(?:pull|pulls|merge_requests|pull-requests)\/(\d+)/i);
|
|
13424
|
+
if (!m) return null;
|
|
13425
|
+
const number = Number(m[2]);
|
|
13426
|
+
if (!Number.isFinite(number) || number <= 0) return null;
|
|
13427
|
+
return { repo: m[1], number };
|
|
13428
|
+
}
|
|
13429
|
+
|
|
13430
|
+
// src/provider-evidence/recipes-github.ts
|
|
13431
|
+
var MAX_BODY_CHARS = 8e3;
|
|
13432
|
+
var MAX_STATUS_ROWS = 30;
|
|
13433
|
+
var MAX_CHECK_RUNS = 100;
|
|
13434
|
+
var MAX_CHANGED_FILES = 400;
|
|
13435
|
+
function githubCliAvailable(run) {
|
|
13436
|
+
if (process.env.GITHUB_TOKEN?.trim() || process.env.GH_TOKEN?.trim()) return true;
|
|
13437
|
+
return run("gh", ["auth", "token"]).ok;
|
|
13438
|
+
}
|
|
13439
|
+
function asRecord4(value) {
|
|
13440
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
13441
|
+
}
|
|
13442
|
+
function pickStatusRows(value) {
|
|
13443
|
+
if (!Array.isArray(value)) return [];
|
|
13444
|
+
return value.map((raw) => asRecord4(raw)).filter((row) => row !== null).slice(0, MAX_STATUS_ROWS).map((row) => ({
|
|
13445
|
+
context: row.context ?? null,
|
|
13446
|
+
state: row.state ?? null,
|
|
13447
|
+
target_url: row.target_url ?? null,
|
|
13448
|
+
description: row.description ?? null
|
|
13449
|
+
}));
|
|
13450
|
+
}
|
|
13451
|
+
function fetchCombinedStatus(run, repo, sha) {
|
|
13452
|
+
const status = runCliJson(run, "gh", [
|
|
13453
|
+
"api",
|
|
13454
|
+
`repos/${repo}/commits/${sha}/status`
|
|
13455
|
+
]);
|
|
13456
|
+
if (!status) return null;
|
|
13457
|
+
return { state: status.state ?? null, statuses: pickStatusRows(status.statuses) };
|
|
13458
|
+
}
|
|
13459
|
+
var githubPrSnapshotRecipe = {
|
|
13460
|
+
provider: "github",
|
|
13461
|
+
kind: "pr_snapshot",
|
|
13462
|
+
version: "1",
|
|
13463
|
+
isAvailable: githubCliAvailable,
|
|
13464
|
+
collect(subject, run) {
|
|
13465
|
+
const parsed = parsePrUrlSubject(subject);
|
|
13466
|
+
if (!parsed) return null;
|
|
13467
|
+
const pull = runCliJson(run, "gh", [
|
|
13468
|
+
"api",
|
|
13469
|
+
`repos/${parsed.repo}/pulls/${parsed.number}`
|
|
13470
|
+
]);
|
|
13471
|
+
if (!pull) return null;
|
|
13472
|
+
const head = asRecord4(pull.head);
|
|
13473
|
+
const headSha = typeof head?.sha === "string" ? head.sha : null;
|
|
13474
|
+
const user = asRecord4(pull.user);
|
|
13475
|
+
const headRepoOwner = asRecord4(asRecord4(head?.repo)?.owner);
|
|
13476
|
+
const body = typeof pull.body === "string" ? pull.body.slice(0, MAX_BODY_CHARS) : null;
|
|
13477
|
+
let checkRuns = [];
|
|
13478
|
+
let combinedStatus = {
|
|
13479
|
+
state: null,
|
|
13480
|
+
statuses: []
|
|
13481
|
+
};
|
|
13482
|
+
if (headSha) {
|
|
13483
|
+
const runs = runCliJson(run, "gh", [
|
|
13484
|
+
"api",
|
|
13485
|
+
`repos/${parsed.repo}/commits/${headSha}/check-runs?per_page=100`
|
|
13486
|
+
]);
|
|
13487
|
+
if (Array.isArray(runs?.check_runs)) {
|
|
13488
|
+
checkRuns = runs.check_runs.map((raw) => asRecord4(raw)).filter((row) => row !== null).slice(0, MAX_CHECK_RUNS).map((row) => ({
|
|
13489
|
+
name: row.name ?? null,
|
|
13490
|
+
status: row.status ?? null,
|
|
13491
|
+
conclusion: row.conclusion ?? null
|
|
13492
|
+
}));
|
|
13493
|
+
}
|
|
13494
|
+
combinedStatus = fetchCombinedStatus(run, parsed.repo, headSha) ?? combinedStatus;
|
|
13495
|
+
}
|
|
13496
|
+
const filesResult = run("gh", [
|
|
13497
|
+
"api",
|
|
13498
|
+
"--paginate",
|
|
13499
|
+
`repos/${parsed.repo}/pulls/${parsed.number}/files?per_page=100`,
|
|
13500
|
+
"--jq",
|
|
13501
|
+
".[].filename"
|
|
13502
|
+
]);
|
|
13503
|
+
const changedFiles = filesResult.ok ? filesResult.stdout.split("\n").map((line) => line.trim()).filter(Boolean).slice(0, MAX_CHANGED_FILES) : [];
|
|
13504
|
+
return {
|
|
13505
|
+
pull: {
|
|
13506
|
+
html_url: pull.html_url ?? null,
|
|
13507
|
+
title: pull.title ?? null,
|
|
13508
|
+
body,
|
|
13509
|
+
user: { login: user?.login ?? null },
|
|
13510
|
+
state: pull.state ?? null,
|
|
13511
|
+
draft: pull.draft ?? null,
|
|
13512
|
+
merged: pull.merged ?? null,
|
|
13513
|
+
merged_at: pull.merged_at ?? null,
|
|
13514
|
+
merge_commit_sha: pull.merge_commit_sha ?? null,
|
|
13515
|
+
mergeable: pull.mergeable ?? null,
|
|
13516
|
+
mergeable_state: pull.mergeable_state ?? null,
|
|
13517
|
+
head: {
|
|
13518
|
+
sha: headSha,
|
|
13519
|
+
ref: head?.ref ?? null,
|
|
13520
|
+
repo: { owner: { login: headRepoOwner?.login ?? null } }
|
|
13521
|
+
}
|
|
13522
|
+
},
|
|
13523
|
+
checkRuns,
|
|
13524
|
+
combinedStatus,
|
|
13525
|
+
changedFiles
|
|
13526
|
+
};
|
|
13527
|
+
}
|
|
13528
|
+
};
|
|
13529
|
+
var githubCommitStatusRecipe = {
|
|
13530
|
+
provider: "github",
|
|
13531
|
+
kind: "commit_status",
|
|
13532
|
+
version: "1",
|
|
13533
|
+
isAvailable: githubCliAvailable,
|
|
13534
|
+
collect(subject, run) {
|
|
13535
|
+
const parsed = parseCommitEvidenceSubject(subject);
|
|
13536
|
+
if (!parsed) return null;
|
|
13537
|
+
return fetchCombinedStatus(run, parsed.repo, parsed.sha);
|
|
13538
|
+
}
|
|
13539
|
+
};
|
|
13540
|
+
var githubBranchReachabilityRecipe = {
|
|
13541
|
+
provider: "github",
|
|
13542
|
+
kind: "branch_reachability",
|
|
13543
|
+
version: "1",
|
|
13544
|
+
isAvailable: githubCliAvailable,
|
|
13545
|
+
collect(subject, run) {
|
|
13546
|
+
const parsed = parseCommitEvidenceSubject(subject);
|
|
13547
|
+
if (!parsed) return null;
|
|
13548
|
+
const repoMeta = runCliJson(run, "gh", [
|
|
13549
|
+
"api",
|
|
13550
|
+
`repos/${parsed.repo}`
|
|
13551
|
+
]);
|
|
13552
|
+
const defaultBranch = typeof repoMeta?.default_branch === "string" && repoMeta.default_branch.trim() ? repoMeta.default_branch.trim() : null;
|
|
13553
|
+
if (!defaultBranch) return null;
|
|
13554
|
+
const compare = runCliJson(run, "gh", [
|
|
13555
|
+
"api",
|
|
13556
|
+
`repos/${parsed.repo}/compare/${encodeURIComponent(defaultBranch)}...${parsed.sha}`
|
|
13557
|
+
]);
|
|
13558
|
+
if (!compare) return null;
|
|
13559
|
+
const compareStatus = typeof compare.status === "string" ? compare.status : null;
|
|
13560
|
+
return {
|
|
13561
|
+
defaultBranch,
|
|
13562
|
+
compareStatus,
|
|
13563
|
+
reachable: compareStatus === "identical" || compareStatus === "behind"
|
|
13564
|
+
};
|
|
13565
|
+
}
|
|
13566
|
+
};
|
|
13567
|
+
|
|
13568
|
+
// src/provider-evidence/recipes-vercel.ts
|
|
13569
|
+
var MAX_DEPLOYMENT_ROWS = 5;
|
|
13570
|
+
var STATE_PATTERN = /\b(READY|ERROR|BUILDING|QUEUED|CANCELED|INITIALIZING)\b/i;
|
|
13571
|
+
var URL_PATTERN = /https:\/\/[^\s]+/;
|
|
13572
|
+
var vercelDeploymentStatusRecipe = {
|
|
13573
|
+
provider: "vercel",
|
|
13574
|
+
kind: "deployment_status",
|
|
13575
|
+
version: "1",
|
|
13576
|
+
isAvailable(run) {
|
|
13577
|
+
return run("vercel", ["whoami"]).ok;
|
|
13578
|
+
},
|
|
13579
|
+
collect(subject, run) {
|
|
13580
|
+
const parsed = parseCommitEvidenceSubject(subject);
|
|
13581
|
+
if (!parsed) return null;
|
|
13582
|
+
const result = run("vercel", [
|
|
13583
|
+
"list",
|
|
13584
|
+
"--prod",
|
|
13585
|
+
"--meta",
|
|
13586
|
+
`githubCommitSha=${parsed.sha}`
|
|
13587
|
+
]);
|
|
13588
|
+
if (!result.ok) return null;
|
|
13589
|
+
const deployments = [];
|
|
13590
|
+
for (const line of result.stdout.split("\n")) {
|
|
13591
|
+
const url = line.match(URL_PATTERN)?.[0];
|
|
13592
|
+
if (!url) continue;
|
|
13593
|
+
const state = line.match(STATE_PATTERN)?.[1]?.toUpperCase() ?? null;
|
|
13594
|
+
deployments.push({ url, state });
|
|
13595
|
+
if (deployments.length >= MAX_DEPLOYMENT_ROWS) break;
|
|
13596
|
+
}
|
|
13597
|
+
return { found: deployments.length > 0, deployments };
|
|
13598
|
+
}
|
|
13599
|
+
};
|
|
13600
|
+
|
|
13601
|
+
// src/provider-evidence/registry.ts
|
|
13602
|
+
var _recipes = [];
|
|
13603
|
+
function registerEvidenceCollector(recipe) {
|
|
13604
|
+
if (_recipes.some((r) => r.provider === recipe.provider && r.kind === recipe.kind)) return;
|
|
13605
|
+
_recipes.push(recipe);
|
|
13606
|
+
}
|
|
13607
|
+
function getEvidenceCollector(provider, kind) {
|
|
13608
|
+
return _recipes.find((r) => r.provider === provider && r.kind === kind) ?? null;
|
|
13609
|
+
}
|
|
13610
|
+
function registerDefaultEvidenceCollectors() {
|
|
13611
|
+
registerEvidenceCollector(githubPrSnapshotRecipe);
|
|
13612
|
+
registerEvidenceCollector(githubCommitStatusRecipe);
|
|
13613
|
+
registerEvidenceCollector(githubBranchReachabilityRecipe);
|
|
13614
|
+
registerEvidenceCollector(vercelDeploymentStatusRecipe);
|
|
13615
|
+
}
|
|
13616
|
+
|
|
13617
|
+
// src/provider-evidence/collect.ts
|
|
13618
|
+
var DEFAULT_MAX_SUBJECTS_PER_TICK = 8;
|
|
13619
|
+
var DEFAULT_DEADLINE_MS = 25e3;
|
|
13620
|
+
function collectProviderEvidence(wanted, opts = {}) {
|
|
13621
|
+
registerDefaultEvidenceCollectors();
|
|
13622
|
+
const run = opts.run ?? defaultCliRunner;
|
|
13623
|
+
const now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
13624
|
+
const maxSubjects = opts.maxSubjects ?? DEFAULT_MAX_SUBJECTS_PER_TICK;
|
|
13625
|
+
const deadline = Date.now() + (opts.deadlineMs ?? DEFAULT_DEADLINE_MS);
|
|
13626
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13627
|
+
const deduped = wanted.filter((w) => {
|
|
13628
|
+
const key = providerEvidenceKey(w.provider, w.kind, w.subject);
|
|
13629
|
+
if (seen.has(key)) return false;
|
|
13630
|
+
seen.add(key);
|
|
13631
|
+
return true;
|
|
13632
|
+
});
|
|
13633
|
+
const offset = deduped.length > 0 ? Math.floor(now().getTime() / 6e4) % deduped.length : 0;
|
|
13634
|
+
const rotated = deduped.map((_, i) => deduped[(offset + i) % deduped.length]);
|
|
13635
|
+
const window = rotated.slice(0, maxSubjects);
|
|
13636
|
+
const summary = {
|
|
13637
|
+
attempted: 0,
|
|
13638
|
+
collected: 0,
|
|
13639
|
+
items: [],
|
|
13640
|
+
skipped: []
|
|
13641
|
+
};
|
|
13642
|
+
const availability = /* @__PURE__ */ new Map();
|
|
13643
|
+
for (const item of window) {
|
|
13644
|
+
if (Date.now() > deadline) {
|
|
13645
|
+
summary.skipped.push({ ...item, reason: "budget_exhausted" });
|
|
13646
|
+
continue;
|
|
13647
|
+
}
|
|
13648
|
+
const recipe = getEvidenceCollector(item.provider, item.kind);
|
|
13649
|
+
if (!recipe) {
|
|
13650
|
+
summary.skipped.push({ ...item, reason: "no_recipe" });
|
|
13651
|
+
continue;
|
|
13652
|
+
}
|
|
13653
|
+
const availKey = `${recipe.provider} ${recipe.kind}`;
|
|
13654
|
+
let available = availability.get(availKey);
|
|
13655
|
+
if (available === void 0) {
|
|
13656
|
+
available = recipe.isAvailable(run);
|
|
13657
|
+
availability.set(availKey, available);
|
|
13658
|
+
}
|
|
13659
|
+
if (!available) {
|
|
13660
|
+
summary.skipped.push({ ...item, reason: "provider_unavailable" });
|
|
13661
|
+
continue;
|
|
13662
|
+
}
|
|
13663
|
+
summary.attempted += 1;
|
|
13664
|
+
const payload = recipe.collect(item.subject, run);
|
|
13665
|
+
if (payload === null || payload === void 0) {
|
|
13666
|
+
summary.skipped.push({ ...item, reason: "collect_failed" });
|
|
13667
|
+
continue;
|
|
13668
|
+
}
|
|
13669
|
+
summary.collected += 1;
|
|
13670
|
+
summary.items.push({
|
|
13671
|
+
provider: item.provider,
|
|
13672
|
+
kind: item.kind,
|
|
13673
|
+
subject: item.subject,
|
|
13674
|
+
payload,
|
|
13675
|
+
observedAt: now().toISOString(),
|
|
13676
|
+
collectorVersion: recipe.version
|
|
13677
|
+
});
|
|
13678
|
+
}
|
|
13679
|
+
return summary;
|
|
13680
|
+
}
|
|
13681
|
+
|
|
13682
|
+
// src/provider-evidence/wanted-store.ts
|
|
13683
|
+
init_run_store();
|
|
13684
|
+
init_util();
|
|
13685
|
+
import path59 from "node:path";
|
|
13686
|
+
var WANTED_FILE = "provider-evidence-wanted.json";
|
|
13687
|
+
function wantedFilePath(runId) {
|
|
13688
|
+
return path59.join(runDirectory(runId), WANTED_FILE);
|
|
13689
|
+
}
|
|
13690
|
+
function parseWantedItems(value) {
|
|
13691
|
+
if (!Array.isArray(value)) return [];
|
|
13692
|
+
const out = [];
|
|
13693
|
+
for (const raw of value) {
|
|
13694
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
|
|
13695
|
+
const row = raw;
|
|
13696
|
+
const provider = typeof row.provider === "string" ? row.provider.trim() : "";
|
|
13697
|
+
const kind = typeof row.kind === "string" ? row.kind.trim() : "";
|
|
13698
|
+
const subject = typeof row.subject === "string" ? row.subject.trim() : "";
|
|
13699
|
+
if (!provider || !kind || !subject) continue;
|
|
13700
|
+
out.push({ provider, kind, subject });
|
|
13701
|
+
}
|
|
13702
|
+
return out;
|
|
13703
|
+
}
|
|
13704
|
+
function loadPersistedProviderEvidenceWanted(runId) {
|
|
13705
|
+
const persisted = readJson(wantedFilePath(runId), null);
|
|
13706
|
+
return parseWantedItems(persisted?.wanted);
|
|
13707
|
+
}
|
|
13708
|
+
function persistProviderEvidenceWanted(runId, wanted) {
|
|
13709
|
+
writeJson(wantedFilePath(runId), {
|
|
13710
|
+
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13711
|
+
wanted
|
|
13712
|
+
});
|
|
13713
|
+
}
|
|
13714
|
+
function extractProviderEvidenceWanted(tickResponse) {
|
|
13715
|
+
if (!tickResponse || typeof tickResponse !== "object" || Array.isArray(tickResponse)) return null;
|
|
13716
|
+
const wanted = tickResponse.providerEvidenceWanted;
|
|
13717
|
+
if (!Array.isArray(wanted)) return null;
|
|
13718
|
+
return parseWantedItems(wanted);
|
|
13719
|
+
}
|
|
13720
|
+
|
|
12743
13721
|
// src/pipeline-tick.ts
|
|
12744
13722
|
async function completeFinishedWorkers(runId, args) {
|
|
12745
13723
|
const run = loadRun(runId);
|
|
12746
13724
|
const outcomes = [];
|
|
12747
13725
|
for (const name of Object.keys(run.workers || {})) {
|
|
12748
13726
|
const worker = readJson(
|
|
12749
|
-
|
|
13727
|
+
path60.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
12750
13728
|
void 0
|
|
12751
13729
|
);
|
|
12752
13730
|
if (!worker?.taskId || worker.localOnly) continue;
|
|
@@ -12779,6 +13757,13 @@ async function postOperatorTick(agentOsId, runId, resourceGate, args, harnessCle
|
|
|
12779
13757
|
const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/operator/tick`;
|
|
12780
13758
|
const packageVersions = await collectInstalledPackageVersions();
|
|
12781
13759
|
const activeHarnessWorkers = collectRunActiveHarnessWorkers(runId);
|
|
13760
|
+
let evidenceCollection = null;
|
|
13761
|
+
try {
|
|
13762
|
+
const evidenceWanted = loadPersistedProviderEvidenceWanted(runId);
|
|
13763
|
+
evidenceCollection = evidenceWanted.length > 0 ? collectProviderEvidence(evidenceWanted) : null;
|
|
13764
|
+
} catch {
|
|
13765
|
+
evidenceCollection = null;
|
|
13766
|
+
}
|
|
12782
13767
|
const res = await postJson(url, secret, {
|
|
12783
13768
|
agentOsId,
|
|
12784
13769
|
runId,
|
|
@@ -12793,9 +13778,27 @@ async function postOperatorTick(agentOsId, runId, resourceGate, args, harnessCle
|
|
|
12793
13778
|
...harnessCleanup ? { harnessCleanup } : {},
|
|
12794
13779
|
runnerPresence: resolveRunnerPresencePayload({ runId }),
|
|
12795
13780
|
activeHarnessWorkers,
|
|
12796
|
-
...
|
|
13781
|
+
...evidenceCollection && evidenceCollection.items.length > 0 ? { providerEvidence: evidenceCollection.items } : {}
|
|
12797
13782
|
});
|
|
12798
|
-
|
|
13783
|
+
const nextWanted = extractProviderEvidenceWanted(res.response);
|
|
13784
|
+
if (nextWanted) {
|
|
13785
|
+
try {
|
|
13786
|
+
persistProviderEvidenceWanted(runId, nextWanted);
|
|
13787
|
+
} catch {
|
|
13788
|
+
}
|
|
13789
|
+
}
|
|
13790
|
+
return {
|
|
13791
|
+
ok: res.ok,
|
|
13792
|
+
httpStatus: res.status,
|
|
13793
|
+
response: res.response,
|
|
13794
|
+
...evidenceCollection ? {
|
|
13795
|
+
providerEvidence: {
|
|
13796
|
+
attempted: evidenceCollection.attempted,
|
|
13797
|
+
collected: evidenceCollection.collected,
|
|
13798
|
+
skipped: evidenceCollection.skipped.length
|
|
13799
|
+
}
|
|
13800
|
+
} : {}
|
|
13801
|
+
};
|
|
12799
13802
|
}
|
|
12800
13803
|
async function runPipelineTick(args) {
|
|
12801
13804
|
const runId = String(required(String(args.run || ""), "--run"));
|
|
@@ -12943,6 +13946,7 @@ async function runDaemon(args) {
|
|
|
12943
13946
|
const cronEnv = resolveKynverCronEnv();
|
|
12944
13947
|
while (!stopping) {
|
|
12945
13948
|
try {
|
|
13949
|
+
writeDaemonHeartbeat({ agentOsId, runId });
|
|
12946
13950
|
if (cronEnv.tickEnabled) {
|
|
12947
13951
|
const cronTick = await runKynverCronTick({
|
|
12948
13952
|
env: cronEnv,
|
|
@@ -12969,8 +13973,140 @@ async function runDaemon(args) {
|
|
|
12969
13973
|
console.error(JSON.stringify({ event: "daemon_stop", runId, agentOsId }));
|
|
12970
13974
|
}
|
|
12971
13975
|
|
|
13976
|
+
// src/daemon-keeper.ts
|
|
13977
|
+
init_config();
|
|
13978
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
13979
|
+
init_util();
|
|
13980
|
+
var DEFAULT_STALL_MS = 15 * 6e4;
|
|
13981
|
+
var STARTUP_GRACE_MS = 2 * 6e4;
|
|
13982
|
+
var KILL_GRACE_MS = 1e4;
|
|
13983
|
+
var BACKOFF_BASE_MS = 5e3;
|
|
13984
|
+
var BACKOFF_CAP_MS = 5 * 6e4;
|
|
13985
|
+
var HEALTHY_RESET_MS = 30 * 6e4;
|
|
13986
|
+
var POLL_MS = 5e3;
|
|
13987
|
+
function resolveKeeperStallMs(flag, env = process.env) {
|
|
13988
|
+
const fromFlag = typeof flag === "string" ? Number.parseInt(flag, 10) : NaN;
|
|
13989
|
+
if (Number.isFinite(fromFlag) && fromFlag > 0) return fromFlag;
|
|
13990
|
+
const fromEnv = Number.parseInt(env.KYNVER_DAEMON_STALL_MS ?? "", 10);
|
|
13991
|
+
if (Number.isFinite(fromEnv) && fromEnv > 0) return fromEnv;
|
|
13992
|
+
return DEFAULT_STALL_MS;
|
|
13993
|
+
}
|
|
13994
|
+
function shouldRunDaemonKeeper(args, env = process.env) {
|
|
13995
|
+
if (args.keeperChild === true || args.keeperChild === "true") return false;
|
|
13996
|
+
if (args.noSupervise === true || args.noSupervise === "true") return false;
|
|
13997
|
+
if (args.supervised === "false") return false;
|
|
13998
|
+
const envFlag5 = (env.KYNVER_DAEMON_SUPERVISED ?? "").trim().toLowerCase();
|
|
13999
|
+
if (envFlag5 === "0" || envFlag5 === "false" || envFlag5 === "no" || envFlag5 === "off") {
|
|
14000
|
+
return false;
|
|
14001
|
+
}
|
|
14002
|
+
return true;
|
|
14003
|
+
}
|
|
14004
|
+
function nextKeeperBackoffMs(consecutiveFailures, base = BACKOFF_BASE_MS, cap = BACKOFF_CAP_MS) {
|
|
14005
|
+
const exp = Math.min(Math.max(consecutiveFailures, 1) - 1, 10);
|
|
14006
|
+
return Math.min(base * 2 ** exp, cap);
|
|
14007
|
+
}
|
|
14008
|
+
function keeperRunWasHealthy(startedAtMs, endedAtMs, healthyMs = HEALTHY_RESET_MS) {
|
|
14009
|
+
return endedAtMs - startedAtMs >= healthyMs;
|
|
14010
|
+
}
|
|
14011
|
+
function keeperLog(event, detail = {}) {
|
|
14012
|
+
console.error(JSON.stringify({ event: `daemon_keeper_${event}`, ...detail }));
|
|
14013
|
+
}
|
|
14014
|
+
function buildKeeperChildArgv(argv) {
|
|
14015
|
+
const out = [];
|
|
14016
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
14017
|
+
const arg = argv[i];
|
|
14018
|
+
if (arg === "--supervised" || arg === "--no-supervise" || arg === "--keeper-child") continue;
|
|
14019
|
+
if (arg === "--stall-ms") {
|
|
14020
|
+
if (i + 1 < argv.length && !argv[i + 1].startsWith("--")) i += 1;
|
|
14021
|
+
continue;
|
|
14022
|
+
}
|
|
14023
|
+
if (arg.startsWith("--stall-ms=") || arg.startsWith("--supervised=")) continue;
|
|
14024
|
+
out.push(arg);
|
|
14025
|
+
}
|
|
14026
|
+
out.push("--keeper-child");
|
|
14027
|
+
return out;
|
|
14028
|
+
}
|
|
14029
|
+
async function runDaemonKeeper(args, rawArgv = process.argv.slice(2)) {
|
|
14030
|
+
const agentOsId = String(
|
|
14031
|
+
required(String(args.agentOsId || loadUserConfig().agentOsId || ""), "--agent-os-id")
|
|
14032
|
+
);
|
|
14033
|
+
const stallMs = resolveKeeperStallMs(args.stallMs);
|
|
14034
|
+
const childArgv = buildKeeperChildArgv(rawArgv);
|
|
14035
|
+
const cliEntry = process.argv[1];
|
|
14036
|
+
let stopping = false;
|
|
14037
|
+
let child = null;
|
|
14038
|
+
let consecutiveFailures = 0;
|
|
14039
|
+
const stop = (signal) => {
|
|
14040
|
+
stopping = true;
|
|
14041
|
+
keeperLog("stop", { signal });
|
|
14042
|
+
if (child?.pid) child.kill(signal);
|
|
14043
|
+
};
|
|
14044
|
+
process.on("SIGINT", () => stop("SIGINT"));
|
|
14045
|
+
process.on("SIGTERM", () => stop("SIGTERM"));
|
|
14046
|
+
keeperLog("start", { agentOsId, stallMs, childArgv });
|
|
14047
|
+
while (!stopping) {
|
|
14048
|
+
const startedAt = Date.now();
|
|
14049
|
+
let exited = false;
|
|
14050
|
+
let exitCode = null;
|
|
14051
|
+
let exitSignal = null;
|
|
14052
|
+
child = spawn6(process.execPath, [cliEntry, ...childArgv], {
|
|
14053
|
+
stdio: "inherit",
|
|
14054
|
+
env: process.env
|
|
14055
|
+
});
|
|
14056
|
+
keeperLog("child_spawned", { pid: child.pid ?? null });
|
|
14057
|
+
child.on("exit", (code, signal) => {
|
|
14058
|
+
exited = true;
|
|
14059
|
+
exitCode = code;
|
|
14060
|
+
exitSignal = signal;
|
|
14061
|
+
});
|
|
14062
|
+
while (!exited && !stopping) {
|
|
14063
|
+
await sleepMsAsync(POLL_MS);
|
|
14064
|
+
if (exited || stopping) break;
|
|
14065
|
+
if (Date.now() - startedAt < STARTUP_GRACE_MS) continue;
|
|
14066
|
+
const beat = readDaemonHeartbeat(agentOsId);
|
|
14067
|
+
const ownBeat = beat && beat.pid === child.pid ? beat : null;
|
|
14068
|
+
if (ownBeat && isDaemonHeartbeatStale(ownBeat, stallMs)) {
|
|
14069
|
+
keeperLog("stall_detected", {
|
|
14070
|
+
pid: child.pid ?? null,
|
|
14071
|
+
lastBeatAt: ownBeat.observedAt,
|
|
14072
|
+
stallMs
|
|
14073
|
+
});
|
|
14074
|
+
child.kill("SIGTERM");
|
|
14075
|
+
await sleepMsAsync(KILL_GRACE_MS);
|
|
14076
|
+
if (!exited) child.kill("SIGKILL");
|
|
14077
|
+
break;
|
|
14078
|
+
}
|
|
14079
|
+
if (!ownBeat && Date.now() - startedAt > stallMs + STARTUP_GRACE_MS) {
|
|
14080
|
+
keeperLog("no_heartbeat_detected", { pid: child.pid ?? null, stallMs });
|
|
14081
|
+
child.kill("SIGTERM");
|
|
14082
|
+
await sleepMsAsync(KILL_GRACE_MS);
|
|
14083
|
+
if (!exited) child.kill("SIGKILL");
|
|
14084
|
+
break;
|
|
14085
|
+
}
|
|
14086
|
+
}
|
|
14087
|
+
while (!exited && !stopping) {
|
|
14088
|
+
await sleepMsAsync(POLL_MS);
|
|
14089
|
+
}
|
|
14090
|
+
if (stopping) break;
|
|
14091
|
+
const endedAt = Date.now();
|
|
14092
|
+
if (keeperRunWasHealthy(startedAt, endedAt)) consecutiveFailures = 0;
|
|
14093
|
+
consecutiveFailures += 1;
|
|
14094
|
+
const backoff = nextKeeperBackoffMs(consecutiveFailures);
|
|
14095
|
+
keeperLog("child_exited", {
|
|
14096
|
+
code: exitCode,
|
|
14097
|
+
signal: exitSignal,
|
|
14098
|
+
uptimeMs: endedAt - startedAt,
|
|
14099
|
+
consecutiveFailures,
|
|
14100
|
+
respawnInMs: backoff
|
|
14101
|
+
});
|
|
14102
|
+
await sleepMsAsync(backoff);
|
|
14103
|
+
}
|
|
14104
|
+
keeperLog("stopped", { agentOsId });
|
|
14105
|
+
}
|
|
14106
|
+
|
|
12972
14107
|
// src/plan-progress.ts
|
|
12973
|
-
|
|
14108
|
+
init_config();
|
|
14109
|
+
import path64 from "node:path";
|
|
12974
14110
|
|
|
12975
14111
|
// src/bounded-build/constants.ts
|
|
12976
14112
|
var DEFAULT_BUILD_MEM_BUDGET_BYTES = 1536 * 1024 * 1024;
|
|
@@ -12979,6 +14115,9 @@ var DEFAULT_NODE_OLD_SPACE_SIZE_MB = 1024;
|
|
|
12979
14115
|
var DEFAULT_SYSTEMD_MEMORY_MAX = "1.5G";
|
|
12980
14116
|
var DEFAULT_SYSTEMD_MEMORY_SWAP_MAX = "2G";
|
|
12981
14117
|
|
|
14118
|
+
// src/bounded-build/index.ts
|
|
14119
|
+
init_meminfo();
|
|
14120
|
+
|
|
12982
14121
|
// src/bounded-build/node-options.ts
|
|
12983
14122
|
var MAX_OLD_SPACE_RE = /--max-old-space-size=(\d+)/;
|
|
12984
14123
|
function parsePositiveInt(value, fallback) {
|
|
@@ -13008,7 +14147,7 @@ function formatNodeOptionsFlag(mb = resolveNodeOldSpaceSizeMb()) {
|
|
|
13008
14147
|
}
|
|
13009
14148
|
|
|
13010
14149
|
// src/bounded-build/systemd-wrap.ts
|
|
13011
|
-
import { spawnSync as
|
|
14150
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
13012
14151
|
var systemdAvailableCache;
|
|
13013
14152
|
function isSystemdRunAvailable() {
|
|
13014
14153
|
if (process.env.KYNVER_BUILD_SKIP_SYSTEMD === "1" || process.env.KYNVER_BUILD_SKIP_SYSTEMD === "true") {
|
|
@@ -13019,7 +14158,7 @@ function isSystemdRunAvailable() {
|
|
|
13019
14158
|
systemdAvailableCache = false;
|
|
13020
14159
|
return false;
|
|
13021
14160
|
}
|
|
13022
|
-
const res =
|
|
14161
|
+
const res = spawnSync9("systemd-run", ["--version"], { encoding: "utf8", stdio: ["ignore", "ignore", "pipe"] });
|
|
13023
14162
|
systemdAvailableCache = res.status === 0;
|
|
13024
14163
|
return systemdAvailableCache;
|
|
13025
14164
|
}
|
|
@@ -13043,7 +14182,9 @@ function buildSystemdRunArgv(opts) {
|
|
|
13043
14182
|
}
|
|
13044
14183
|
|
|
13045
14184
|
// src/bounded-build/admission.ts
|
|
13046
|
-
|
|
14185
|
+
init_config();
|
|
14186
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
14187
|
+
init_meminfo();
|
|
13047
14188
|
function positiveInt4(value, fallback) {
|
|
13048
14189
|
const n = Number(value);
|
|
13049
14190
|
if (!Number.isFinite(n) || n <= 0) return fallback;
|
|
@@ -13079,7 +14220,7 @@ function assessBuildAdmission(opts = {}) {
|
|
|
13079
14220
|
}
|
|
13080
14221
|
function sleepMs2(ms) {
|
|
13081
14222
|
if (ms <= 0) return;
|
|
13082
|
-
|
|
14223
|
+
spawnSync10(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
|
|
13083
14224
|
stdio: "ignore"
|
|
13084
14225
|
});
|
|
13085
14226
|
}
|
|
@@ -13100,33 +14241,34 @@ function waitForBuildAdmission(timeoutMs, pollMs = 2e3, opts = {}) {
|
|
|
13100
14241
|
}
|
|
13101
14242
|
|
|
13102
14243
|
// src/bounded-build/exec.ts
|
|
13103
|
-
import { spawnSync as
|
|
14244
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
13104
14245
|
|
|
13105
14246
|
// src/heavy-verification/slot.ts
|
|
14247
|
+
init_util();
|
|
13106
14248
|
import {
|
|
13107
14249
|
closeSync as closeSync7,
|
|
13108
14250
|
existsSync as existsSync44,
|
|
13109
|
-
mkdirSync as
|
|
14251
|
+
mkdirSync as mkdirSync9,
|
|
13110
14252
|
openSync as openSync7,
|
|
13111
14253
|
readdirSync as readdirSync15,
|
|
13112
|
-
readFileSync as
|
|
14254
|
+
readFileSync as readFileSync18,
|
|
13113
14255
|
unlinkSync as unlinkSync4,
|
|
13114
|
-
writeFileSync as
|
|
14256
|
+
writeFileSync as writeFileSync6
|
|
13115
14257
|
} from "node:fs";
|
|
13116
|
-
import
|
|
14258
|
+
import path62 from "node:path";
|
|
13117
14259
|
|
|
13118
14260
|
// src/heavy-verification/paths.ts
|
|
13119
|
-
import { mkdirSync as
|
|
13120
|
-
import
|
|
14261
|
+
import { mkdirSync as mkdirSync8 } from "node:fs";
|
|
14262
|
+
import path61 from "node:path";
|
|
13121
14263
|
function resolveHeavyVerificationRoot() {
|
|
13122
|
-
return
|
|
14264
|
+
return path61.join(resolveKynverStateRoot(), "heavy-verification");
|
|
13123
14265
|
}
|
|
13124
14266
|
function heavyVerificationSlotsDir() {
|
|
13125
|
-
return
|
|
14267
|
+
return path61.join(resolveHeavyVerificationRoot(), "slots");
|
|
13126
14268
|
}
|
|
13127
14269
|
function ensureHeavyVerificationDirs() {
|
|
13128
14270
|
const dir = heavyVerificationSlotsDir();
|
|
13129
|
-
|
|
14271
|
+
mkdirSync8(dir, { recursive: true });
|
|
13130
14272
|
return dir;
|
|
13131
14273
|
}
|
|
13132
14274
|
|
|
@@ -13151,12 +14293,12 @@ function indexedSlotId(index) {
|
|
|
13151
14293
|
return `slot-${index}`;
|
|
13152
14294
|
}
|
|
13153
14295
|
function slotFilePath(slotId, slotsDir = heavyVerificationSlotsDir()) {
|
|
13154
|
-
return
|
|
14296
|
+
return path62.join(slotsDir, `${slotId}.json`);
|
|
13155
14297
|
}
|
|
13156
14298
|
function readSlotRecord(filePath) {
|
|
13157
14299
|
if (!existsSync44(filePath)) return null;
|
|
13158
14300
|
try {
|
|
13159
|
-
const parsed = JSON.parse(
|
|
14301
|
+
const parsed = JSON.parse(readFileSync18(filePath, "utf8"));
|
|
13160
14302
|
if (typeof parsed.slotId === "string" && typeof parsed.pid === "number" && typeof parsed.acquiredAt === "string" && typeof parsed.command === "string") {
|
|
13161
14303
|
return parsed;
|
|
13162
14304
|
}
|
|
@@ -13181,7 +14323,7 @@ function reclaimStaleSlot(filePath, staleMs) {
|
|
|
13181
14323
|
}
|
|
13182
14324
|
}
|
|
13183
14325
|
function ensureSlotsDir(slotsDir) {
|
|
13184
|
-
|
|
14326
|
+
mkdirSync9(slotsDir, { recursive: true });
|
|
13185
14327
|
return slotsDir;
|
|
13186
14328
|
}
|
|
13187
14329
|
function reclaimStaleHeavyVerificationSlots(opts = {}) {
|
|
@@ -13190,7 +14332,7 @@ function reclaimStaleHeavyVerificationSlots(opts = {}) {
|
|
|
13190
14332
|
let reclaimed = 0;
|
|
13191
14333
|
for (const name of readdirSync15(slotsDir)) {
|
|
13192
14334
|
if (!name.endsWith(".json")) continue;
|
|
13193
|
-
const filePath =
|
|
14335
|
+
const filePath = path62.join(slotsDir, name);
|
|
13194
14336
|
const before = existsSync44(filePath);
|
|
13195
14337
|
reclaimStaleSlot(filePath, staleMs);
|
|
13196
14338
|
if (before && !existsSync44(filePath)) reclaimed += 1;
|
|
@@ -13204,7 +14346,7 @@ function listActiveHeavyVerificationSlots(opts = {}) {
|
|
|
13204
14346
|
const active = [];
|
|
13205
14347
|
for (const name of readdirSync15(slotsDir)) {
|
|
13206
14348
|
if (!name.endsWith(".json")) continue;
|
|
13207
|
-
const record3 = readSlotRecord(
|
|
14349
|
+
const record3 = readSlotRecord(path62.join(slotsDir, name));
|
|
13208
14350
|
if (record3 && !slotIsStale(record3, staleMs)) active.push(record3);
|
|
13209
14351
|
}
|
|
13210
14352
|
return active;
|
|
@@ -13246,7 +14388,7 @@ function tryAcquireHeavyVerificationSlot(command, opts = {}) {
|
|
|
13246
14388
|
};
|
|
13247
14389
|
try {
|
|
13248
14390
|
const fd = openSync7(filePath, "wx");
|
|
13249
|
-
|
|
14391
|
+
writeFileSync6(fd, JSON.stringify(record3, null, 2), "utf8");
|
|
13250
14392
|
closeSync7(fd);
|
|
13251
14393
|
const activeSlots2 = countActiveHeavyVerificationSlots({ slotsDir, staleMs });
|
|
13252
14394
|
return {
|
|
@@ -13306,10 +14448,10 @@ function assessHeavyVerificationGate(command, opts = {}) {
|
|
|
13306
14448
|
}
|
|
13307
14449
|
|
|
13308
14450
|
// src/heavy-verification/gate.ts
|
|
13309
|
-
import { spawnSync as
|
|
14451
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
13310
14452
|
function sleepMs3(ms) {
|
|
13311
14453
|
if (ms <= 0) return;
|
|
13312
|
-
|
|
14454
|
+
spawnSync11(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
|
|
13313
14455
|
stdio: "ignore"
|
|
13314
14456
|
});
|
|
13315
14457
|
}
|
|
@@ -13324,11 +14466,12 @@ function waitForHeavyVerificationSlot(command, timeoutMs, pollMs = 2e3, opts = {
|
|
|
13324
14466
|
}
|
|
13325
14467
|
|
|
13326
14468
|
// src/harness-worktree-build-guard.ts
|
|
13327
|
-
|
|
14469
|
+
init_paths();
|
|
14470
|
+
import path63 from "node:path";
|
|
13328
14471
|
function isPathUnderHarnessWorktree(cwd) {
|
|
13329
14472
|
const worktreesDir = harnessWorktreesDir(resolveHarnessRoot());
|
|
13330
|
-
const rel =
|
|
13331
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
14473
|
+
const rel = path63.relative(worktreesDir, path63.resolve(cwd));
|
|
14474
|
+
return rel.length > 0 && !rel.startsWith("..") && !path63.isAbsolute(rel);
|
|
13332
14475
|
}
|
|
13333
14476
|
function assessHarnessWorktreeBuildGuard(cwd) {
|
|
13334
14477
|
if (!isPathUnderHarnessWorktree(cwd)) return { ok: true };
|
|
@@ -13352,7 +14495,7 @@ function envArgv(env) {
|
|
|
13352
14495
|
return out;
|
|
13353
14496
|
}
|
|
13354
14497
|
function runSpawn(argv, opts) {
|
|
13355
|
-
const res =
|
|
14498
|
+
const res = spawnSync12(argv[0], argv.slice(1), {
|
|
13356
14499
|
cwd: opts.cwd,
|
|
13357
14500
|
env: opts.env,
|
|
13358
14501
|
encoding: "utf8",
|
|
@@ -13478,6 +14621,7 @@ function runHarnessVerifyCommands(cwd, commands = DEFAULT_HARNESS_VERIFY_COMMAND
|
|
|
13478
14621
|
}
|
|
13479
14622
|
|
|
13480
14623
|
// src/plan-progress.ts
|
|
14624
|
+
init_util();
|
|
13481
14625
|
function parseEvidenceArg(raw) {
|
|
13482
14626
|
const idx = raw.indexOf(":");
|
|
13483
14627
|
if (idx <= 0) throw new Error(`invalid --evidence ${raw} (expected type:value)`);
|
|
@@ -13540,7 +14684,7 @@ async function emitPlanProgress(args) {
|
|
|
13540
14684
|
}
|
|
13541
14685
|
function verifyPlanLocal(args) {
|
|
13542
14686
|
const worktree = required(args.worktree ? String(args.worktree) : void 0, "worktree");
|
|
13543
|
-
const cwd =
|
|
14687
|
+
const cwd = path64.resolve(worktree);
|
|
13544
14688
|
const summary = runHarnessVerifyCommands(cwd);
|
|
13545
14689
|
const emitJson = args.json === true || args.json === "true";
|
|
13546
14690
|
const payload = { passed: summary.passed, worktree: cwd, steps: summary.steps };
|
|
@@ -13589,9 +14733,10 @@ async function verifyPlan(args) {
|
|
|
13589
14733
|
}
|
|
13590
14734
|
|
|
13591
14735
|
// src/harness-verify-cli.ts
|
|
13592
|
-
import
|
|
14736
|
+
import path65 from "node:path";
|
|
14737
|
+
init_util();
|
|
13593
14738
|
function runHarnessVerifyCli(args) {
|
|
13594
|
-
const cwd =
|
|
14739
|
+
const cwd = path65.resolve(required(args.worktree ? String(args.worktree) : void 0, "worktree"));
|
|
13595
14740
|
const emitJson = args.json === true || args.json === "true" || args.emitJson === true || args.emitJson === "true";
|
|
13596
14741
|
const commands = [];
|
|
13597
14742
|
const rawCmd = args.command;
|
|
@@ -13636,7 +14781,9 @@ function runHarnessVerifyCli(args) {
|
|
|
13636
14781
|
}
|
|
13637
14782
|
|
|
13638
14783
|
// src/plan-persist-cli.ts
|
|
13639
|
-
|
|
14784
|
+
init_config();
|
|
14785
|
+
import { readFileSync as readFileSync19 } from "node:fs";
|
|
14786
|
+
init_util();
|
|
13640
14787
|
var OPERATIONS = ["create", "add_version", "update_metadata"];
|
|
13641
14788
|
var FAILURE_KINDS = [
|
|
13642
14789
|
"approval_guard",
|
|
@@ -13648,7 +14795,7 @@ var FAILURE_KINDS = [
|
|
|
13648
14795
|
function readBodyArg(args) {
|
|
13649
14796
|
const bodyFile = args.bodyFile ? String(args.bodyFile) : void 0;
|
|
13650
14797
|
if (bodyFile) {
|
|
13651
|
-
return { body:
|
|
14798
|
+
return { body: readFileSync19(bodyFile, "utf8"), bodyPathHint: bodyFile };
|
|
13652
14799
|
}
|
|
13653
14800
|
const inline = args.body ? String(args.body) : void 0;
|
|
13654
14801
|
if (inline) return { body: inline };
|
|
@@ -14028,9 +15175,14 @@ ${text.slice(0, 800)}`,
|
|
|
14028
15175
|
}
|
|
14029
15176
|
|
|
14030
15177
|
// src/monitor/monitor.service.ts
|
|
14031
|
-
import
|
|
15178
|
+
import path67 from "node:path";
|
|
15179
|
+
init_run_store();
|
|
15180
|
+
init_status();
|
|
15181
|
+
init_util();
|
|
14032
15182
|
|
|
14033
15183
|
// src/monitor/monitor.classify.ts
|
|
15184
|
+
init_status();
|
|
15185
|
+
init_util();
|
|
14034
15186
|
function classifyWorkerHealth(input) {
|
|
14035
15187
|
const { worker, status, taskLease } = input;
|
|
14036
15188
|
const leaseOwner = taskLease?.leaseOwner ?? null;
|
|
@@ -14080,19 +15232,21 @@ function classifyWorkerHealth(input) {
|
|
|
14080
15232
|
}
|
|
14081
15233
|
|
|
14082
15234
|
// src/monitor/monitor.store.ts
|
|
14083
|
-
|
|
14084
|
-
|
|
15235
|
+
init_paths();
|
|
15236
|
+
init_util();
|
|
15237
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync10, readdirSync as readdirSync16, unlinkSync as unlinkSync5 } from "node:fs";
|
|
15238
|
+
import path66 from "node:path";
|
|
14085
15239
|
function monitorsDir() {
|
|
14086
15240
|
const { harnessRoot } = getHarnessPaths();
|
|
14087
|
-
const dir =
|
|
14088
|
-
|
|
15241
|
+
const dir = path66.join(harnessRoot, "monitors");
|
|
15242
|
+
mkdirSync10(dir, { recursive: true });
|
|
14089
15243
|
return dir;
|
|
14090
15244
|
}
|
|
14091
15245
|
function monitorIdFor(runId, workerName) {
|
|
14092
15246
|
return workerName ? `${safeSlug(runId)}--${safeSlug(workerName)}` : safeSlug(runId);
|
|
14093
15247
|
}
|
|
14094
15248
|
function monitorPath(monitorId) {
|
|
14095
|
-
return
|
|
15249
|
+
return path66.join(monitorsDir(), `${monitorId}.json`);
|
|
14096
15250
|
}
|
|
14097
15251
|
function loadMonitorSession(monitorId) {
|
|
14098
15252
|
return readJson(monitorPath(monitorId), void 0);
|
|
@@ -14113,7 +15267,7 @@ function listMonitorSessions() {
|
|
|
14113
15267
|
for (const name of readdirSync16(dir)) {
|
|
14114
15268
|
if (!name.endsWith(".json")) continue;
|
|
14115
15269
|
const session = readJson(
|
|
14116
|
-
|
|
15270
|
+
path66.join(dir, name),
|
|
14117
15271
|
void 0
|
|
14118
15272
|
);
|
|
14119
15273
|
if (!session?.monitorId) continue;
|
|
@@ -14133,6 +15287,7 @@ function listMonitorSessions() {
|
|
|
14133
15287
|
}
|
|
14134
15288
|
|
|
14135
15289
|
// src/monitor/monitor.terminal.ts
|
|
15290
|
+
init_status();
|
|
14136
15291
|
function assessAutoCompleteEligibility(input) {
|
|
14137
15292
|
const { worker, status } = input;
|
|
14138
15293
|
const blockers = [];
|
|
@@ -14176,6 +15331,7 @@ function assessAutoCompleteEligibility(input) {
|
|
|
14176
15331
|
}
|
|
14177
15332
|
|
|
14178
15333
|
// src/monitor/monitor.task-lease.ts
|
|
15334
|
+
init_config();
|
|
14179
15335
|
async function fetchTaskLeasesForWorkers(input) {
|
|
14180
15336
|
const out = /* @__PURE__ */ new Map();
|
|
14181
15337
|
const agentOsId = input.agentOsId?.trim();
|
|
@@ -14204,7 +15360,7 @@ async function fetchTaskLeasesForWorkers(input) {
|
|
|
14204
15360
|
// src/monitor/monitor.service.ts
|
|
14205
15361
|
function workerRecord2(runId, name) {
|
|
14206
15362
|
return readJson(
|
|
14207
|
-
|
|
15363
|
+
path67.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
|
|
14208
15364
|
void 0
|
|
14209
15365
|
);
|
|
14210
15366
|
}
|
|
@@ -14374,6 +15530,7 @@ async function monitorAutoCompleteCli(args) {
|
|
|
14374
15530
|
}
|
|
14375
15531
|
|
|
14376
15532
|
// src/monitor/monitor-loop.ts
|
|
15533
|
+
init_util();
|
|
14377
15534
|
var DEFAULT_POLL_MS2 = 5e3;
|
|
14378
15535
|
var DEFAULT_MAX_TOTAL_MS2 = 6 * 60 * 60 * 1e3;
|
|
14379
15536
|
async function runMonitorLoop(args) {
|
|
@@ -14409,19 +15566,21 @@ async function runMonitorLoop(args) {
|
|
|
14409
15566
|
}
|
|
14410
15567
|
|
|
14411
15568
|
// src/monitor/monitor-spawn.ts
|
|
14412
|
-
|
|
15569
|
+
init_util();
|
|
15570
|
+
init_paths();
|
|
15571
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
14413
15572
|
import { closeSync as closeSync8, existsSync as existsSync46, openSync as openSync8 } from "node:fs";
|
|
14414
|
-
import
|
|
15573
|
+
import path68 from "node:path";
|
|
14415
15574
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
14416
15575
|
function resolveDefaultCliPath2() {
|
|
14417
|
-
return
|
|
15576
|
+
return path68.join(fileURLToPath4(new URL(".", import.meta.url)), "cli.js");
|
|
14418
15577
|
}
|
|
14419
15578
|
function spawnMonitorSidecar(opts) {
|
|
14420
15579
|
const cliPath = opts.cliPath ?? resolveDefaultCliPath2();
|
|
14421
15580
|
if (!existsSync46(cliPath)) return void 0;
|
|
14422
15581
|
const monitorId = monitorIdFor(opts.runId, opts.workerName);
|
|
14423
15582
|
const { harnessRoot } = getHarnessPaths();
|
|
14424
|
-
const logPath =
|
|
15583
|
+
const logPath = path68.join(harnessRoot, "monitors", `${monitorId}.log`);
|
|
14425
15584
|
let logFd;
|
|
14426
15585
|
try {
|
|
14427
15586
|
logFd = openSync8(logPath, "a");
|
|
@@ -14455,7 +15614,7 @@ function spawnMonitorSidecar(opts) {
|
|
|
14455
15614
|
logFd ?? "ignore"
|
|
14456
15615
|
];
|
|
14457
15616
|
try {
|
|
14458
|
-
const child =
|
|
15617
|
+
const child = spawn7(
|
|
14459
15618
|
nodeExecutable,
|
|
14460
15619
|
args,
|
|
14461
15620
|
hiddenSpawnOptions({
|
|
@@ -14490,6 +15649,7 @@ function spawnMonitorSidecar(opts) {
|
|
|
14490
15649
|
}
|
|
14491
15650
|
|
|
14492
15651
|
// src/monitor/monitor-cli.ts
|
|
15652
|
+
init_util();
|
|
14493
15653
|
async function startMonitorCli(args) {
|
|
14494
15654
|
const runId = String(args.run || "");
|
|
14495
15655
|
required(runId, "--run");
|
|
@@ -14541,7 +15701,11 @@ async function monitorTickCli(args) {
|
|
|
14541
15701
|
}
|
|
14542
15702
|
|
|
14543
15703
|
// src/post-restart-unblock.ts
|
|
14544
|
-
|
|
15704
|
+
init_run_store();
|
|
15705
|
+
init_status();
|
|
15706
|
+
init_util();
|
|
15707
|
+
init_config();
|
|
15708
|
+
import path69 from "node:path";
|
|
14545
15709
|
function skip(runId, worker, taskId, agentOsId, leaseOwner, reason) {
|
|
14546
15710
|
return { runId, worker, taskId, agentOsId, leaseOwner, action: "skipped", reason };
|
|
14547
15711
|
}
|
|
@@ -14554,7 +15718,7 @@ async function postRestartUnblock(args) {
|
|
|
14554
15718
|
const errors = [];
|
|
14555
15719
|
for (const run of listRunRecords()) {
|
|
14556
15720
|
for (const name of Object.keys(run.workers ?? {})) {
|
|
14557
|
-
const workerPath =
|
|
15721
|
+
const workerPath = path69.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json");
|
|
14558
15722
|
const worker = readJson(workerPath, void 0);
|
|
14559
15723
|
if (!worker) {
|
|
14560
15724
|
skipped.push(skip(run.id, name, "", "", "", "worker.json missing"));
|
|
@@ -14666,9 +15830,11 @@ async function postRestartUnblockCli(args) {
|
|
|
14666
15830
|
}
|
|
14667
15831
|
|
|
14668
15832
|
// src/default-repo-cli.ts
|
|
14669
|
-
|
|
14670
|
-
|
|
14671
|
-
|
|
15833
|
+
init_path_values();
|
|
15834
|
+
init_config();
|
|
15835
|
+
import path70 from "node:path";
|
|
15836
|
+
import { homedir as homedir16 } from "node:os";
|
|
15837
|
+
var CONFIG_FILE2 = path70.join(homedir16(), ".kynver", "config.json");
|
|
14672
15838
|
function ensureDefaultRepo(opts) {
|
|
14673
15839
|
const existing = loadUserConfig();
|
|
14674
15840
|
const resolved = resolveDefaultRepo({ ...opts, config: existing });
|
|
@@ -14749,16 +15915,19 @@ function summarizeResolvedDefaultRepo(resolved) {
|
|
|
14749
15915
|
}
|
|
14750
15916
|
|
|
14751
15917
|
// src/doctor/runtime-takeover.ts
|
|
14752
|
-
import
|
|
15918
|
+
import path72 from "node:path";
|
|
15919
|
+
init_path_values();
|
|
14753
15920
|
|
|
14754
15921
|
// src/doctor/runtime-takeover.probes.ts
|
|
14755
|
-
|
|
14756
|
-
import {
|
|
14757
|
-
import
|
|
14758
|
-
import
|
|
15922
|
+
init_config();
|
|
15923
|
+
import { accessSync, constants, existsSync as existsSync47, readFileSync as readFileSync20 } from "node:fs";
|
|
15924
|
+
import { homedir as homedir17 } from "node:os";
|
|
15925
|
+
import path71 from "node:path";
|
|
15926
|
+
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
15927
|
+
init_paths();
|
|
14759
15928
|
function captureCommand(bin, args) {
|
|
14760
15929
|
try {
|
|
14761
|
-
const res =
|
|
15930
|
+
const res = spawnSync13(bin, args, { encoding: "utf8" });
|
|
14762
15931
|
const stdout = (res.stdout || "").trim();
|
|
14763
15932
|
const stderr = (res.stderr || "").trim();
|
|
14764
15933
|
const ok = res.status === 0;
|
|
@@ -14796,15 +15965,15 @@ var defaultRuntimeTakeoverProbes = {
|
|
|
14796
15965
|
commandOnPath: (bin) => captureCommand(process.platform === "win32" ? "where" : "which", [bin]),
|
|
14797
15966
|
kynverVersion: (bin) => captureCommand(bin, ["--version"]),
|
|
14798
15967
|
loadConfig: () => loadUserConfig(),
|
|
14799
|
-
configFilePath: () =>
|
|
14800
|
-
credentialsFilePath: () =>
|
|
15968
|
+
configFilePath: () => path71.join(homedir17(), ".kynver", "config.json"),
|
|
15969
|
+
credentialsFilePath: () => path71.join(homedir17(), ".kynver", "credentials"),
|
|
14801
15970
|
readCredentials: () => {
|
|
14802
|
-
const credPath =
|
|
15971
|
+
const credPath = path71.join(homedir17(), ".kynver", "credentials");
|
|
14803
15972
|
if (!existsSync47(credPath)) {
|
|
14804
15973
|
return { hasApiKey: false };
|
|
14805
15974
|
}
|
|
14806
15975
|
try {
|
|
14807
|
-
const parsed = JSON.parse(
|
|
15976
|
+
const parsed = JSON.parse(readFileSync20(credPath, "utf8"));
|
|
14808
15977
|
return {
|
|
14809
15978
|
hasApiKey: Boolean(parsed.apiKey?.trim()),
|
|
14810
15979
|
runnerTokenPrefix: tokenPrefix(parsed.runnerToken),
|
|
@@ -14834,7 +16003,7 @@ var defaultRuntimeTakeoverProbes = {
|
|
|
14834
16003
|
})()
|
|
14835
16004
|
}),
|
|
14836
16005
|
harnessRoot: () => resolveHarnessRoot(),
|
|
14837
|
-
legacyOpenclawHarnessRoot: () =>
|
|
16006
|
+
legacyOpenclawHarnessRoot: () => path71.join(homedir17(), ".openclaw", "harness"),
|
|
14838
16007
|
pathExists: (target) => existsSync47(target),
|
|
14839
16008
|
pathWritable: (target) => isWritable(target)
|
|
14840
16009
|
};
|
|
@@ -15241,8 +16410,8 @@ function assessVercelDeployEvidence(probes) {
|
|
|
15241
16410
|
}
|
|
15242
16411
|
function assessHarnessDirs(probes) {
|
|
15243
16412
|
const harnessRoot = probes.harnessRoot();
|
|
15244
|
-
const runsDir =
|
|
15245
|
-
const worktreesDir =
|
|
16413
|
+
const runsDir = path72.join(harnessRoot, "runs");
|
|
16414
|
+
const worktreesDir = path72.join(harnessRoot, "worktrees");
|
|
15246
16415
|
const displayHarnessRoot = redactHomePath(harnessRoot);
|
|
15247
16416
|
const displayRunsDir = redactHomePath(runsDir);
|
|
15248
16417
|
const displayWorktreesDir = redactHomePath(worktreesDir);
|
|
@@ -15418,6 +16587,7 @@ function runRuntimeTakeoverDoctorCli(args = {}) {
|
|
|
15418
16587
|
}
|
|
15419
16588
|
|
|
15420
16589
|
// src/command-center-contract-cli.ts
|
|
16590
|
+
init_config();
|
|
15421
16591
|
async function runCommandCenterContractCli(args) {
|
|
15422
16592
|
const config = loadUserConfig();
|
|
15423
16593
|
const agentOsId = (args.agentOsId ? String(args.agentOsId) : config.agentOsId) || "";
|
|
@@ -15448,6 +16618,9 @@ async function runCommandCenterContractCli(args) {
|
|
|
15448
16618
|
console.log(JSON.stringify(res.response, null, 2));
|
|
15449
16619
|
}
|
|
15450
16620
|
|
|
16621
|
+
// src/scheduler-cutover-cli.ts
|
|
16622
|
+
init_path_values();
|
|
16623
|
+
|
|
15451
16624
|
// src/scheduler-cutover.ts
|
|
15452
16625
|
var DEPLOYMENT_SCHEDULER_CUTOVER_STEPS = [
|
|
15453
16626
|
"Vercel/hosted: set KYNVER_SCHEDULER_PROVIDER=qstash",
|
|
@@ -15506,9 +16679,10 @@ function applySchedulerCutoverAttestation(config) {
|
|
|
15506
16679
|
}
|
|
15507
16680
|
|
|
15508
16681
|
// src/scheduler-cutover-cli.ts
|
|
15509
|
-
|
|
15510
|
-
import
|
|
15511
|
-
|
|
16682
|
+
init_config();
|
|
16683
|
+
import path73 from "node:path";
|
|
16684
|
+
import { homedir as homedir18 } from "node:os";
|
|
16685
|
+
var CONFIG_FILE3 = path73.join(homedir18(), ".kynver", "config.json");
|
|
15512
16686
|
function runSchedulerCutoverCheckCli(json = false) {
|
|
15513
16687
|
const config = loadUserConfig();
|
|
15514
16688
|
const report = assessSchedulerCutover(config);
|
|
@@ -15646,7 +16820,12 @@ async function runCronTickCli(args) {
|
|
|
15646
16820
|
}
|
|
15647
16821
|
|
|
15648
16822
|
// src/lane/landing-maintainer-tick.ts
|
|
15649
|
-
|
|
16823
|
+
init_config();
|
|
16824
|
+
import os11 from "node:os";
|
|
16825
|
+
init_config();
|
|
16826
|
+
init_box_identity();
|
|
16827
|
+
init_resource_gate();
|
|
16828
|
+
init_util();
|
|
15650
16829
|
|
|
15651
16830
|
// src/lane/lane-spec.ts
|
|
15652
16831
|
var LANDING_MAINTAINER_LANE_SPEC = {
|
|
@@ -15658,10 +16837,10 @@ var LANDING_MAINTAINER_LANE_SPEC = {
|
|
|
15658
16837
|
};
|
|
15659
16838
|
|
|
15660
16839
|
// src/lane/landing-maintainer-local.ts
|
|
15661
|
-
import { spawnSync as
|
|
15662
|
-
import
|
|
16840
|
+
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
16841
|
+
import path74 from "node:path";
|
|
15663
16842
|
function runLandingWrapper(prNumber, repoRoot, execute) {
|
|
15664
|
-
const script =
|
|
16843
|
+
const script = path74.join(repoRoot, LANDING_MAINTAINER_LANE_SPEC.landScript);
|
|
15665
16844
|
const args = [script, String(prNumber), ...LANDING_MAINTAINER_LANE_SPEC.landScriptArgs];
|
|
15666
16845
|
if (!execute) {
|
|
15667
16846
|
return {
|
|
@@ -15672,7 +16851,7 @@ function runLandingWrapper(prNumber, repoRoot, execute) {
|
|
|
15672
16851
|
stderr: ""
|
|
15673
16852
|
};
|
|
15674
16853
|
}
|
|
15675
|
-
const result =
|
|
16854
|
+
const result = spawnSync14("node", args, {
|
|
15676
16855
|
cwd: repoRoot,
|
|
15677
16856
|
encoding: "utf8",
|
|
15678
16857
|
timeout: 10 * 60 * 1e3
|
|
@@ -15687,7 +16866,7 @@ function runLandingWrapper(prNumber, repoRoot, execute) {
|
|
|
15687
16866
|
}
|
|
15688
16867
|
function resolveLandingMaintainerRepoRoot(args) {
|
|
15689
16868
|
const explicit = args.repoPath ? String(args.repoPath).trim() : "";
|
|
15690
|
-
if (explicit) return
|
|
16869
|
+
if (explicit) return path74.resolve(explicit);
|
|
15691
16870
|
const resolved = resolveDefaultRepo();
|
|
15692
16871
|
return resolved?.repo ?? process.cwd();
|
|
15693
16872
|
}
|
|
@@ -15706,7 +16885,7 @@ async function runLandingMaintainerLaneTick(args) {
|
|
|
15706
16885
|
...buildBoxResourceSnapshotFromGate(resourceGate, {
|
|
15707
16886
|
harnessRunId: runId,
|
|
15708
16887
|
boxKind: resolveBoxKindFromConfig(loadUserConfig()),
|
|
15709
|
-
hostLabel:
|
|
16888
|
+
hostLabel: os11.hostname()
|
|
15710
16889
|
}),
|
|
15711
16890
|
providerHealthy: resourceGate.ok,
|
|
15712
16891
|
authorizedForRepair: resourceGate.ok,
|
|
@@ -15810,10 +16989,11 @@ function usage(code = 0) {
|
|
|
15810
16989
|
out(
|
|
15811
16990
|
[
|
|
15812
16991
|
"Usage:",
|
|
15813
|
-
" kynver login --api-key KEY",
|
|
16992
|
+
" kynver login [--api-key KEY] [--api-base-url URL] (omit --api-key to authorize in the browser)",
|
|
16993
|
+
" kynver bootstrap [--api-base-url URL] [--api-key KEY] [--repo PATH] (login + setup + runner credential in one shot)",
|
|
15814
16994
|
" kynver runner credential [--agent-os-id ID] [--base-url URL]",
|
|
15815
16995
|
" 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]",
|
|
15816
|
-
" kynver daemon --run RUN_ID --agent-os-id AOS_ID [--execute] [--interval-ms MS]",
|
|
16996
|
+
" kynver daemon --run RUN_ID --agent-os-id AOS_ID [--execute] [--interval-ms MS] [--stall-ms MS] [--no-supervise]",
|
|
15817
16997
|
" kynver status --run RUN_ID [--blocked] [--running] [--task TASK_ID] [--worker WORKER] [--full] # top-level compact run status",
|
|
15818
16998
|
" kynver run create [--repo /path/repo] [--name name] [--base origin/main]",
|
|
15819
16999
|
" kynver run list",
|
|
@@ -15874,8 +17054,8 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
15874
17054
|
if (action && isHelpFlag(action) || rest.some(isHelpFlag)) return usage(0);
|
|
15875
17055
|
const args = parseArgs(rest);
|
|
15876
17056
|
const { runsDir, worktreesDir } = getPaths();
|
|
15877
|
-
|
|
15878
|
-
|
|
17057
|
+
mkdirSync11(runsDir, { recursive: true });
|
|
17058
|
+
mkdirSync11(worktreesDir, { recursive: true });
|
|
15879
17059
|
if (scope === "daemon") {
|
|
15880
17060
|
assertNativeDaemonAllowed();
|
|
15881
17061
|
}
|
|
@@ -15895,10 +17075,16 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
15895
17075
|
});
|
|
15896
17076
|
}
|
|
15897
17077
|
if (scope === "login") return void await runLogin(args);
|
|
17078
|
+
if (scope === "bootstrap") return void await runBootstrap(args);
|
|
15898
17079
|
if (scope === "status") return runStatus(args);
|
|
15899
17080
|
if (scope === "runner" && action === "credential") return void await mintRunnerCredential(args);
|
|
15900
17081
|
if (scope === "setup") return void await runSetup(args);
|
|
15901
|
-
if (scope === "daemon")
|
|
17082
|
+
if (scope === "daemon") {
|
|
17083
|
+
if (shouldRunDaemonKeeper(args)) {
|
|
17084
|
+
return void await runDaemonKeeper(args);
|
|
17085
|
+
}
|
|
17086
|
+
return void await runDaemon(args);
|
|
17087
|
+
}
|
|
15902
17088
|
if (scope === "plan" && action === "progress") return void await emitPlanProgress(args);
|
|
15903
17089
|
if (scope === "plan" && action === "verify") return void await verifyPlan(args);
|
|
15904
17090
|
if (scope === "harness" && action === "verify") return runHarnessVerifyCli(args);
|