@kynver-app/runtime 0.1.92 → 0.1.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +294 -250
- package/dist/cli.js.map +4 -4
- package/dist/doctor/runtime-takeover.probes.d.ts +0 -2
- package/dist/index.js +562 -484
- package/dist/index.js.map +4 -4
- package/dist/installed-package-versions.d.ts +2 -0
- package/dist/vercel/index.d.ts +2 -1
- package/dist/vercel/vercel-api.d.ts +17 -0
- package/dist/vercel/vercel-evidence.d.ts +15 -15
- package/dist/vercel/vercel-url.d.ts +3 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -315,7 +315,13 @@ function displayUserPath(value) {
|
|
|
315
315
|
}
|
|
316
316
|
|
|
317
317
|
// src/default-repo-discovery.ts
|
|
318
|
-
var WELL_KNOWN_REPO_DIRS = [
|
|
318
|
+
var WELL_KNOWN_REPO_DIRS = [
|
|
319
|
+
"Kynver",
|
|
320
|
+
"repos/Kynver",
|
|
321
|
+
"repos/kynver-source-main",
|
|
322
|
+
"code/Kynver",
|
|
323
|
+
"projects/Kynver"
|
|
324
|
+
];
|
|
319
325
|
function readPackageName(repoRoot) {
|
|
320
326
|
const pkgPath = path3.join(repoRoot, "package.json");
|
|
321
327
|
if (!existsSync2(pkgPath)) return null;
|
|
@@ -4069,14 +4075,15 @@ function buildPrompt(input) {
|
|
|
4069
4075
|
input.planId ? `Active planId: ${input.planId}${input.taskId ? ` \xB7 taskId: ${input.taskId}` : ""}` : "No planId on this worker \u2014 still emit progress when you touch plan-scoped work."
|
|
4070
4076
|
];
|
|
4071
4077
|
const mergeGateLines = compact ? [
|
|
4072
|
-
"Merge-gate cost control: do not use Vercel previews/builds for PR verification. Run `node scripts/agent-os-pr-merge-gate.mjs --pr <url> --agent-os-id <id>` (or `verify-pr-local.mjs --from-pr` + POST pr-merge-gate/refresh) before any GitHub Actions run; request merge-gate only via refresh then POST pr-merge-gate/request-run (one Actions run per PR head unless human approves extra)."
|
|
4078
|
+
"Merge-gate cost control: do not use Vercel previews/builds for PR verification. Run `node scripts/agent-os-pr-merge-gate.mjs --pr <url> --agent-os-id <id>` (or `verify-pr-local.mjs --from-pr` + POST pr-merge-gate/refresh) before any GitHub Actions run; request merge-gate only via refresh then POST pr-merge-gate/request-run (one Actions run per PR head unless human approves extra). Per-PR Vercel preview builds are off by default \u2014 production deploy runs via release batch after merge."
|
|
4073
4079
|
] : [
|
|
4074
4080
|
"GitHub Actions merge-gate cost control (Kynver/Hermes PRs):",
|
|
4075
4081
|
"- Prefer local cached package verification (`node scripts/verify-pr-local.mjs --emit-json`) before GitHub Actions. Do not use Vercel previews/builds as PR evidence.",
|
|
4076
4082
|
"- Do not push empty commits to re-trigger CI. One budgeted merge-gate Actions run per PR candidate (head SHA) unless a human approves extra.",
|
|
4077
4083
|
"- Record evidence: POST `/api/agent-os/by-id/<agentOsId>/pr-merge-gate/refresh` with prUrl + local payloads.",
|
|
4078
4084
|
"- Request the final Actions run only when local verification is green: POST `.../pr-merge-gate/request-run` (applies `merge-gate` label).",
|
|
4079
|
-
"- Empty failed Actions jobs (no runner/steps/logs) are infra/quota \u2014 do not enter repair loops; escalate to operator."
|
|
4085
|
+
"- Empty failed Actions jobs (no runner/steps/logs) are infra/quota \u2014 do not enter repair loops; escalate to operator.",
|
|
4086
|
+
"- After merge, landed PRs accumulate into a release batch; run batch verification then manual Vercel production deploy from Command Center (release train). PR landing completes with: verification complete, awaiting release batch/deploy."
|
|
4080
4087
|
];
|
|
4081
4088
|
const planArtifactLines = compact ? [
|
|
4082
4089
|
"Plan artifacts: when authoring/revising docs/superpowers/plans/, open a GitHub PR early and iterate from that PR branch; do not leave the canonical plan only in the harness worktree."
|
|
@@ -7027,7 +7034,7 @@ async function dispatchRun(args) {
|
|
|
7027
7034
|
runnerPresence,
|
|
7028
7035
|
harnessBoardSnapshot: buildRunBoard(run.id),
|
|
7029
7036
|
...args.lane ? { lane: resolveDispatchNextLaneFilter(String(args.lane)) } : {},
|
|
7030
|
-
|
|
7037
|
+
...args.executor ? { executor: String(args.executor) } : {},
|
|
7031
7038
|
...args.diskPath ? { diskPath: String(args.diskPath) } : {},
|
|
7032
7039
|
...args.targetTaskId ? { targetTaskId: String(args.targetTaskId) } : {},
|
|
7033
7040
|
...!args.targetTaskId && args.targetTaskIds ? {
|
|
@@ -8793,7 +8800,7 @@ async function runKynverCronTick(opts = {}) {
|
|
|
8793
8800
|
}
|
|
8794
8801
|
|
|
8795
8802
|
// src/pipeline-tick.ts
|
|
8796
|
-
import
|
|
8803
|
+
import path55 from "node:path";
|
|
8797
8804
|
|
|
8798
8805
|
// src/pipeline-dispatch.ts
|
|
8799
8806
|
var RESERVED_REVIEW_STARTS = 1;
|
|
@@ -10683,7 +10690,192 @@ function isPipelineCleanupEnabled() {
|
|
|
10683
10690
|
// src/installed-package-versions.ts
|
|
10684
10691
|
import { readFile } from "node:fs/promises";
|
|
10685
10692
|
import { homedir as homedir13 } from "node:os";
|
|
10693
|
+
import path54 from "node:path";
|
|
10694
|
+
|
|
10695
|
+
// src/memory-cost-package-version-guard.ts
|
|
10696
|
+
import { existsSync as existsSync40, readFileSync as readFileSync12 } from "node:fs";
|
|
10686
10697
|
import path53 from "node:path";
|
|
10698
|
+
var MEMORY_COST_PACKAGE_MIN_VERSIONS = {
|
|
10699
|
+
"@kynver-app/runtime": "0.1.83",
|
|
10700
|
+
"@kynver-app/openclaw-agent-os": "0.1.43",
|
|
10701
|
+
"@kynver-app/mcp-agent-os": "0.3.34"
|
|
10702
|
+
};
|
|
10703
|
+
var MEMORY_COST_MANAGED_PACKAGES = Object.keys(
|
|
10704
|
+
MEMORY_COST_PACKAGE_MIN_VERSIONS
|
|
10705
|
+
);
|
|
10706
|
+
var DISPLAY_NAMES = {
|
|
10707
|
+
"@kynver-app/runtime": "Kynver runtime",
|
|
10708
|
+
"@kynver-app/openclaw-agent-os": "OpenClaw AgentOS plugin",
|
|
10709
|
+
"@kynver-app/mcp-agent-os": "AgentOS MCP server"
|
|
10710
|
+
};
|
|
10711
|
+
var REPO_PACKAGE_JSON_RELATIVE = {
|
|
10712
|
+
"@kynver-app/runtime": "packages/kynver-runtime/package.json",
|
|
10713
|
+
"@kynver-app/openclaw-agent-os": "packages/kynver-openclaw-agent-os/package.json",
|
|
10714
|
+
"@kynver-app/mcp-agent-os": "packages/kynver-mcp-agent-os/package.json"
|
|
10715
|
+
};
|
|
10716
|
+
function parseSemverParts(version) {
|
|
10717
|
+
const core = version.trim().split("-")[0]?.split("+")[0];
|
|
10718
|
+
if (!core) return null;
|
|
10719
|
+
const parts = core.split(".");
|
|
10720
|
+
if (parts.length < 1 || parts.length > 3) return null;
|
|
10721
|
+
const nums = parts.map((p) => Number.parseInt(p, 10));
|
|
10722
|
+
if (nums.some((n) => !Number.isFinite(n) || n < 0)) return null;
|
|
10723
|
+
while (nums.length < 3) nums.push(0);
|
|
10724
|
+
return [nums[0], nums[1], nums[2]];
|
|
10725
|
+
}
|
|
10726
|
+
function compareSemver(a, b) {
|
|
10727
|
+
const pa = parseSemverParts(a);
|
|
10728
|
+
const pb = parseSemverParts(b);
|
|
10729
|
+
if (!pa || !pb) return 0;
|
|
10730
|
+
for (let i = 0; i < 3; i += 1) {
|
|
10731
|
+
if (pa[i] > pb[i]) return 1;
|
|
10732
|
+
if (pa[i] < pb[i]) return -1;
|
|
10733
|
+
}
|
|
10734
|
+
return 0;
|
|
10735
|
+
}
|
|
10736
|
+
function semverAtLeast(version, minimum) {
|
|
10737
|
+
return compareSemver(version, minimum) >= 0;
|
|
10738
|
+
}
|
|
10739
|
+
function maxSemver(versions) {
|
|
10740
|
+
let best = null;
|
|
10741
|
+
for (const version of versions) {
|
|
10742
|
+
if (!best || compareSemver(version, best) > 0) best = version;
|
|
10743
|
+
}
|
|
10744
|
+
return best;
|
|
10745
|
+
}
|
|
10746
|
+
function readPackageJsonVersion(packageJsonPath) {
|
|
10747
|
+
try {
|
|
10748
|
+
const parsed = JSON.parse(readFileSync12(packageJsonPath, "utf8"));
|
|
10749
|
+
return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
|
|
10750
|
+
} catch {
|
|
10751
|
+
return null;
|
|
10752
|
+
}
|
|
10753
|
+
}
|
|
10754
|
+
function resolveRepoRoot(cwd, explicitRepoRoot) {
|
|
10755
|
+
const candidates = [explicitRepoRoot, process.env.KYNVER_REPO, cwd].filter(
|
|
10756
|
+
(value) => Boolean(value?.trim())
|
|
10757
|
+
);
|
|
10758
|
+
for (const candidate of candidates) {
|
|
10759
|
+
const resolved = path53.resolve(candidate);
|
|
10760
|
+
if (existsSync40(path53.join(resolved, "packages/kynver-runtime/package.json")) && existsSync40(path53.join(resolved, "package.json"))) {
|
|
10761
|
+
return resolved;
|
|
10762
|
+
}
|
|
10763
|
+
}
|
|
10764
|
+
const discovered = discoverDefaultRepo({ cwd });
|
|
10765
|
+
return discovered?.repo ?? null;
|
|
10766
|
+
}
|
|
10767
|
+
function probeRepoPackageVersions(input = {}) {
|
|
10768
|
+
const cwd = input.cwd ?? process.cwd();
|
|
10769
|
+
const repoRoot = resolveRepoRoot(cwd, input.repoRoot);
|
|
10770
|
+
if (!repoRoot) return {};
|
|
10771
|
+
const out = {};
|
|
10772
|
+
for (const packageName of MEMORY_COST_MANAGED_PACKAGES) {
|
|
10773
|
+
const packageJsonPath = path53.join(repoRoot, REPO_PACKAGE_JSON_RELATIVE[packageName]);
|
|
10774
|
+
const version = readPackageJsonVersion(packageJsonPath);
|
|
10775
|
+
if (!version) continue;
|
|
10776
|
+
out[packageName] = { version, source: "repo", path: packageJsonPath };
|
|
10777
|
+
}
|
|
10778
|
+
return out;
|
|
10779
|
+
}
|
|
10780
|
+
function repoSourceCommands(packageName) {
|
|
10781
|
+
if (packageName === "@kynver-app/runtime") {
|
|
10782
|
+
return ["npm run kynver:build", "npm run kynver"];
|
|
10783
|
+
}
|
|
10784
|
+
return [`npm run build -w ${packageName}`];
|
|
10785
|
+
}
|
|
10786
|
+
function buildRemediation(input) {
|
|
10787
|
+
const { packageName, minimumVersion, effectiveVersion, effectiveSource, repoVersion } = input;
|
|
10788
|
+
const lines = [];
|
|
10789
|
+
if (repoVersion && semverAtLeast(repoVersion, minimumVersion)) {
|
|
10790
|
+
lines.push(
|
|
10791
|
+
`Use the monorepo checkout (${repoVersion}) instead of a stale npm install: ${repoSourceCommands(packageName).join("; ")}.`
|
|
10792
|
+
);
|
|
10793
|
+
lines.push("Do not publish npm packages or wait on an operator release.");
|
|
10794
|
+
return lines;
|
|
10795
|
+
}
|
|
10796
|
+
if (effectiveVersion) {
|
|
10797
|
+
lines.push(
|
|
10798
|
+
`Upgrade ${packageName} from ${effectiveVersion} to >= ${minimumVersion} (npm install -g ${packageName}@latest or align OpenClaw npm prefix).`
|
|
10799
|
+
);
|
|
10800
|
+
} else {
|
|
10801
|
+
lines.push(`Install ${packageName} >= ${minimumVersion} before running memory-heavy AgentOS paths.`);
|
|
10802
|
+
}
|
|
10803
|
+
if (packageName === "@kynver-app/runtime") {
|
|
10804
|
+
lines.push("Repo-source alternative: npm run kynver:build && npm run kynver");
|
|
10805
|
+
}
|
|
10806
|
+
if (effectiveSource === "installed" && repoVersion) {
|
|
10807
|
+
lines.push(`Repo checkout reports ${repoVersion}; rebuild/link repo source if you develop from the monorepo.`);
|
|
10808
|
+
}
|
|
10809
|
+
return lines;
|
|
10810
|
+
}
|
|
10811
|
+
function pickEffectiveCandidate(candidates) {
|
|
10812
|
+
if (candidates.length === 0) return { version: null, source: "unknown" };
|
|
10813
|
+
const best = maxSemver(candidates.map((candidate) => candidate.version));
|
|
10814
|
+
if (!best) return { version: null, source: "unknown" };
|
|
10815
|
+
const winner = candidates.find((candidate) => candidate.version === best) ?? candidates[0];
|
|
10816
|
+
return { version: winner.version, source: winner.source };
|
|
10817
|
+
}
|
|
10818
|
+
function evaluateMemoryCostPackageVersionGuard(input = {}) {
|
|
10819
|
+
const normalize2 = (value, fallbackSource) => {
|
|
10820
|
+
if (!value) return null;
|
|
10821
|
+
if (typeof value === "string") return { version: value, source: fallbackSource };
|
|
10822
|
+
return value;
|
|
10823
|
+
};
|
|
10824
|
+
const packages = MEMORY_COST_MANAGED_PACKAGES.map((packageName) => {
|
|
10825
|
+
const minimumVersion = MEMORY_COST_PACKAGE_MIN_VERSIONS[packageName];
|
|
10826
|
+
const candidates = [];
|
|
10827
|
+
const installed = normalize2(input.installed?.[packageName], "installed");
|
|
10828
|
+
const repo = normalize2(input.repo?.[packageName], "repo");
|
|
10829
|
+
const self = normalize2(input.self?.[packageName], "self");
|
|
10830
|
+
if (installed) candidates.push(installed);
|
|
10831
|
+
if (repo) candidates.push(repo);
|
|
10832
|
+
if (self) candidates.push(self);
|
|
10833
|
+
const { version: effectiveVersion, source: effectiveSource } = pickEffectiveCandidate(candidates);
|
|
10834
|
+
const repoVersion = repo?.version ?? null;
|
|
10835
|
+
const ok2 = effectiveVersion ? semverAtLeast(effectiveVersion, minimumVersion) : false;
|
|
10836
|
+
const remediation = ok2 ? [] : buildRemediation({
|
|
10837
|
+
packageName,
|
|
10838
|
+
minimumVersion,
|
|
10839
|
+
effectiveVersion,
|
|
10840
|
+
effectiveSource,
|
|
10841
|
+
repoVersion
|
|
10842
|
+
});
|
|
10843
|
+
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)") + ".";
|
|
10844
|
+
return {
|
|
10845
|
+
packageName,
|
|
10846
|
+
displayName: DISPLAY_NAMES[packageName],
|
|
10847
|
+
minimumVersion,
|
|
10848
|
+
effectiveVersion,
|
|
10849
|
+
effectiveSource,
|
|
10850
|
+
ok: ok2,
|
|
10851
|
+
summary: summary2,
|
|
10852
|
+
remediation
|
|
10853
|
+
};
|
|
10854
|
+
});
|
|
10855
|
+
const violations = packages.filter((row) => !row.ok);
|
|
10856
|
+
const ok = violations.length === 0;
|
|
10857
|
+
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("; ")}.`;
|
|
10858
|
+
return { ok, summary, packages };
|
|
10859
|
+
}
|
|
10860
|
+
var MemoryCostPackageVersionGuardError = class extends Error {
|
|
10861
|
+
result;
|
|
10862
|
+
constructor(result) {
|
|
10863
|
+
const lines = [
|
|
10864
|
+
result.summary,
|
|
10865
|
+
...result.packages.filter((row) => !row.ok).flatMap((row) => [`- ${row.summary}`, ...row.remediation.map((line) => ` \u2192 ${line}`)])
|
|
10866
|
+
];
|
|
10867
|
+
super(lines.join("\n"));
|
|
10868
|
+
this.name = "MemoryCostPackageVersionGuardError";
|
|
10869
|
+
this.result = result;
|
|
10870
|
+
}
|
|
10871
|
+
};
|
|
10872
|
+
function assertMemoryCostPackageVersionGuard(input = {}) {
|
|
10873
|
+
const result = evaluateMemoryCostPackageVersionGuard(input);
|
|
10874
|
+
if (!result.ok) throw new MemoryCostPackageVersionGuardError(result);
|
|
10875
|
+
return result;
|
|
10876
|
+
}
|
|
10877
|
+
|
|
10878
|
+
// src/installed-package-versions.ts
|
|
10687
10879
|
var MANAGED_PACKAGES = [
|
|
10688
10880
|
"@kynver-app/runtime",
|
|
10689
10881
|
"@kynver-app/openclaw-agent-os",
|
|
@@ -10698,12 +10890,12 @@ function unique(values) {
|
|
|
10698
10890
|
}
|
|
10699
10891
|
function moduleRoots() {
|
|
10700
10892
|
const home = homedir13();
|
|
10701
|
-
const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ??
|
|
10702
|
-
const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ?
|
|
10893
|
+
const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ?? path54.join(home, ".openclaw", "npm");
|
|
10894
|
+
const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ? path54.join(trim(process.env.NPM_CONFIG_PREFIX), "lib", "node_modules") : path54.join(home, ".npm-global", "lib", "node_modules"));
|
|
10703
10895
|
return unique([
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot :
|
|
10896
|
+
path54.join(openClawPrefix, "lib", "node_modules"),
|
|
10897
|
+
path54.join(openClawPrefix, "node_modules"),
|
|
10898
|
+
npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot : path54.join(npmGlobalRoot, "lib", "node_modules")
|
|
10707
10899
|
]);
|
|
10708
10900
|
}
|
|
10709
10901
|
async function readVersion(packageJsonPath) {
|
|
@@ -10714,16 +10906,31 @@ async function readVersion(packageJsonPath) {
|
|
|
10714
10906
|
return null;
|
|
10715
10907
|
}
|
|
10716
10908
|
}
|
|
10717
|
-
|
|
10909
|
+
function installedPackageJsonCandidates(packageName) {
|
|
10718
10910
|
const roots = moduleRoots();
|
|
10911
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10912
|
+
const out = [];
|
|
10913
|
+
for (const root of roots) {
|
|
10914
|
+
const candidate = path54.join(root, packageName, "package.json");
|
|
10915
|
+
if (seen.has(candidate)) continue;
|
|
10916
|
+
seen.add(candidate);
|
|
10917
|
+
out.push(candidate);
|
|
10918
|
+
}
|
|
10919
|
+
return out;
|
|
10920
|
+
}
|
|
10921
|
+
async function collectInstalledPackageVersions(observedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
10719
10922
|
const out = {};
|
|
10720
10923
|
for (const packageName of MANAGED_PACKAGES) {
|
|
10721
|
-
|
|
10722
|
-
|
|
10924
|
+
let best = null;
|
|
10925
|
+
for (const packageJsonPath of installedPackageJsonCandidates(packageName)) {
|
|
10723
10926
|
const version = await readVersion(packageJsonPath);
|
|
10724
10927
|
if (!version) continue;
|
|
10725
|
-
|
|
10726
|
-
|
|
10928
|
+
if (!best || compareSemver(version, best.version) > 0) {
|
|
10929
|
+
best = { version, path: packageJsonPath };
|
|
10930
|
+
}
|
|
10931
|
+
}
|
|
10932
|
+
if (best) {
|
|
10933
|
+
out[packageName] = { version: best.version, observedAt, path: best.path };
|
|
10727
10934
|
}
|
|
10728
10935
|
}
|
|
10729
10936
|
return out;
|
|
@@ -10735,7 +10942,7 @@ async function completeFinishedWorkers(runId, args) {
|
|
|
10735
10942
|
const outcomes = [];
|
|
10736
10943
|
for (const name of Object.keys(run.workers || {})) {
|
|
10737
10944
|
const worker = readJson(
|
|
10738
|
-
|
|
10945
|
+
path55.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
10739
10946
|
void 0
|
|
10740
10947
|
);
|
|
10741
10948
|
if (!worker?.taskId || worker.localOnly) continue;
|
|
@@ -10949,7 +11156,7 @@ async function runDaemon(args) {
|
|
|
10949
11156
|
}
|
|
10950
11157
|
|
|
10951
11158
|
// src/plan-progress.ts
|
|
10952
|
-
import
|
|
11159
|
+
import path57 from "node:path";
|
|
10953
11160
|
|
|
10954
11161
|
// src/bounded-build/constants.ts
|
|
10955
11162
|
var DEFAULT_BUILD_MEM_BUDGET_BYTES = 1536 * 1024 * 1024;
|
|
@@ -11082,11 +11289,11 @@ function waitForBuildAdmission(timeoutMs, pollMs = 2e3, opts = {}) {
|
|
|
11082
11289
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
11083
11290
|
|
|
11084
11291
|
// src/harness-worktree-build-guard.ts
|
|
11085
|
-
import
|
|
11292
|
+
import path56 from "node:path";
|
|
11086
11293
|
function isPathUnderHarnessWorktree(cwd) {
|
|
11087
11294
|
const worktreesDir = harnessWorktreesDir(resolveHarnessRoot());
|
|
11088
|
-
const rel =
|
|
11089
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
11295
|
+
const rel = path56.relative(worktreesDir, path56.resolve(cwd));
|
|
11296
|
+
return rel.length > 0 && !rel.startsWith("..") && !path56.isAbsolute(rel);
|
|
11090
11297
|
}
|
|
11091
11298
|
function assessHarnessWorktreeBuildGuard(cwd) {
|
|
11092
11299
|
if (!isPathUnderHarnessWorktree(cwd)) return { ok: true };
|
|
@@ -11271,7 +11478,7 @@ async function emitPlanProgress(args) {
|
|
|
11271
11478
|
}
|
|
11272
11479
|
function verifyPlanLocal(args) {
|
|
11273
11480
|
const worktree = required(args.worktree ? String(args.worktree) : void 0, "worktree");
|
|
11274
|
-
const cwd =
|
|
11481
|
+
const cwd = path57.resolve(worktree);
|
|
11275
11482
|
const summary = runHarnessVerifyCommands(cwd);
|
|
11276
11483
|
const emitJson = args.json === true || args.json === "true";
|
|
11277
11484
|
const payload = { passed: summary.passed, worktree: cwd, steps: summary.steps };
|
|
@@ -11320,9 +11527,9 @@ async function verifyPlan(args) {
|
|
|
11320
11527
|
}
|
|
11321
11528
|
|
|
11322
11529
|
// src/harness-verify-cli.ts
|
|
11323
|
-
import
|
|
11530
|
+
import path58 from "node:path";
|
|
11324
11531
|
function runHarnessVerifyCli(args) {
|
|
11325
|
-
const cwd =
|
|
11532
|
+
const cwd = path58.resolve(required(args.worktree ? String(args.worktree) : void 0, "worktree"));
|
|
11326
11533
|
const emitJson = args.json === true || args.json === "true" || args.emitJson === true || args.emitJson === "true";
|
|
11327
11534
|
const commands = [];
|
|
11328
11535
|
const rawCmd = args.command;
|
|
@@ -11366,7 +11573,7 @@ function runHarnessVerifyCli(args) {
|
|
|
11366
11573
|
}
|
|
11367
11574
|
|
|
11368
11575
|
// src/plan-persist-cli.ts
|
|
11369
|
-
import { readFileSync as
|
|
11576
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
11370
11577
|
var OPERATIONS = ["create", "add_version", "update_metadata"];
|
|
11371
11578
|
var FAILURE_KINDS = [
|
|
11372
11579
|
"approval_guard",
|
|
@@ -11378,7 +11585,7 @@ var FAILURE_KINDS = [
|
|
|
11378
11585
|
function readBodyArg(args) {
|
|
11379
11586
|
const bodyFile = args.bodyFile ? String(args.bodyFile) : void 0;
|
|
11380
11587
|
if (bodyFile) {
|
|
11381
|
-
return { body:
|
|
11588
|
+
return { body: readFileSync13(bodyFile, "utf8"), bodyPathHint: bodyFile };
|
|
11382
11589
|
}
|
|
11383
11590
|
const inline = args.body ? String(args.body) : void 0;
|
|
11384
11591
|
if (inline) return { body: inline };
|
|
@@ -11529,7 +11736,7 @@ function formatMonitorTickNotice(tick) {
|
|
|
11529
11736
|
}
|
|
11530
11737
|
|
|
11531
11738
|
// src/monitor/monitor.service.ts
|
|
11532
|
-
import
|
|
11739
|
+
import path60 from "node:path";
|
|
11533
11740
|
|
|
11534
11741
|
// src/monitor/monitor.classify.ts
|
|
11535
11742
|
function classifyWorkerHealth(input) {
|
|
@@ -11581,11 +11788,11 @@ function classifyWorkerHealth(input) {
|
|
|
11581
11788
|
}
|
|
11582
11789
|
|
|
11583
11790
|
// src/monitor/monitor.store.ts
|
|
11584
|
-
import { existsSync as
|
|
11585
|
-
import
|
|
11791
|
+
import { existsSync as existsSync41, mkdirSync as mkdirSync7, readdirSync as readdirSync15, unlinkSync as unlinkSync4 } from "node:fs";
|
|
11792
|
+
import path59 from "node:path";
|
|
11586
11793
|
function monitorsDir() {
|
|
11587
11794
|
const { harnessRoot } = getHarnessPaths();
|
|
11588
|
-
const dir =
|
|
11795
|
+
const dir = path59.join(harnessRoot, "monitors");
|
|
11589
11796
|
mkdirSync7(dir, { recursive: true });
|
|
11590
11797
|
return dir;
|
|
11591
11798
|
}
|
|
@@ -11593,7 +11800,7 @@ function monitorIdFor(runId, workerName) {
|
|
|
11593
11800
|
return workerName ? `${safeSlug(runId)}--${safeSlug(workerName)}` : safeSlug(runId);
|
|
11594
11801
|
}
|
|
11595
11802
|
function monitorPath(monitorId) {
|
|
11596
|
-
return
|
|
11803
|
+
return path59.join(monitorsDir(), `${monitorId}.json`);
|
|
11597
11804
|
}
|
|
11598
11805
|
function loadMonitorSession(monitorId) {
|
|
11599
11806
|
return readJson(monitorPath(monitorId), void 0);
|
|
@@ -11603,18 +11810,18 @@ function saveMonitorSession(session) {
|
|
|
11603
11810
|
}
|
|
11604
11811
|
function deleteMonitorSession(monitorId) {
|
|
11605
11812
|
const file = monitorPath(monitorId);
|
|
11606
|
-
if (!
|
|
11813
|
+
if (!existsSync41(file)) return false;
|
|
11607
11814
|
unlinkSync4(file);
|
|
11608
11815
|
return true;
|
|
11609
11816
|
}
|
|
11610
11817
|
function listMonitorSessions() {
|
|
11611
11818
|
const dir = monitorsDir();
|
|
11612
|
-
if (!
|
|
11819
|
+
if (!existsSync41(dir)) return [];
|
|
11613
11820
|
const entries = [];
|
|
11614
11821
|
for (const name of readdirSync15(dir)) {
|
|
11615
11822
|
if (!name.endsWith(".json")) continue;
|
|
11616
11823
|
const session = readJson(
|
|
11617
|
-
|
|
11824
|
+
path59.join(dir, name),
|
|
11618
11825
|
void 0
|
|
11619
11826
|
);
|
|
11620
11827
|
if (!session?.monitorId) continue;
|
|
@@ -11705,7 +11912,7 @@ async function fetchTaskLeasesForWorkers(input) {
|
|
|
11705
11912
|
// src/monitor/monitor.service.ts
|
|
11706
11913
|
function workerRecord2(runId, name) {
|
|
11707
11914
|
return readJson(
|
|
11708
|
-
|
|
11915
|
+
path60.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
|
|
11709
11916
|
void 0
|
|
11710
11917
|
);
|
|
11711
11918
|
}
|
|
@@ -11911,18 +12118,18 @@ async function runMonitorLoop(args) {
|
|
|
11911
12118
|
|
|
11912
12119
|
// src/monitor/monitor-spawn.ts
|
|
11913
12120
|
import { spawn as spawn6 } from "node:child_process";
|
|
11914
|
-
import { closeSync as closeSync7, existsSync as
|
|
11915
|
-
import
|
|
12121
|
+
import { closeSync as closeSync7, existsSync as existsSync42, openSync as openSync7 } from "node:fs";
|
|
12122
|
+
import path61 from "node:path";
|
|
11916
12123
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
11917
12124
|
function resolveDefaultCliPath2() {
|
|
11918
|
-
return
|
|
12125
|
+
return path61.join(fileURLToPath3(new URL(".", import.meta.url)), "cli.js");
|
|
11919
12126
|
}
|
|
11920
12127
|
function spawnMonitorSidecar(opts) {
|
|
11921
12128
|
const cliPath = opts.cliPath ?? resolveDefaultCliPath2();
|
|
11922
|
-
if (!
|
|
12129
|
+
if (!existsSync42(cliPath)) return void 0;
|
|
11923
12130
|
const monitorId = monitorIdFor(opts.runId, opts.workerName);
|
|
11924
12131
|
const { harnessRoot } = getHarnessPaths();
|
|
11925
|
-
const logPath =
|
|
12132
|
+
const logPath = path61.join(harnessRoot, "monitors", `${monitorId}.log`);
|
|
11926
12133
|
let logFd;
|
|
11927
12134
|
try {
|
|
11928
12135
|
logFd = openSync7(logPath, "a");
|
|
@@ -12042,13 +12249,13 @@ async function monitorTickCli(args) {
|
|
|
12042
12249
|
}
|
|
12043
12250
|
|
|
12044
12251
|
// src/package-version.ts
|
|
12045
|
-
import { existsSync as
|
|
12252
|
+
import { existsSync as existsSync43, readFileSync as readFileSync14 } from "node:fs";
|
|
12046
12253
|
import { dirname, join } from "node:path";
|
|
12047
12254
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
12048
12255
|
function resolvePackageRoot(moduleUrl) {
|
|
12049
12256
|
let dir = dirname(fileURLToPath4(moduleUrl));
|
|
12050
12257
|
for (let depth = 0; depth < 6; depth += 1) {
|
|
12051
|
-
if (
|
|
12258
|
+
if (existsSync43(join(dir, "package.json"))) return dir;
|
|
12052
12259
|
const parent = dirname(dir);
|
|
12053
12260
|
if (parent === dir) break;
|
|
12054
12261
|
dir = parent;
|
|
@@ -12057,7 +12264,7 @@ function resolvePackageRoot(moduleUrl) {
|
|
|
12057
12264
|
}
|
|
12058
12265
|
function readOwnPackageVersion(moduleUrl = import.meta.url) {
|
|
12059
12266
|
const pkgPath = join(resolvePackageRoot(moduleUrl), "package.json");
|
|
12060
|
-
const pkg = JSON.parse(
|
|
12267
|
+
const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
|
|
12061
12268
|
if (typeof pkg.version !== "string" || !pkg.version.trim()) {
|
|
12062
12269
|
throw new Error(`Missing package.json version at ${pkgPath}`);
|
|
12063
12270
|
}
|
|
@@ -12077,188 +12284,6 @@ function handleCliVersionFlag(argv, moduleUrl = import.meta.url, binName) {
|
|
|
12077
12284
|
return true;
|
|
12078
12285
|
}
|
|
12079
12286
|
|
|
12080
|
-
// src/memory-cost-package-version-guard.ts
|
|
12081
|
-
import { existsSync as existsSync43, readFileSync as readFileSync14 } from "node:fs";
|
|
12082
|
-
import path61 from "node:path";
|
|
12083
|
-
var MEMORY_COST_PACKAGE_MIN_VERSIONS = {
|
|
12084
|
-
"@kynver-app/runtime": "0.1.83",
|
|
12085
|
-
"@kynver-app/openclaw-agent-os": "0.1.43",
|
|
12086
|
-
"@kynver-app/mcp-agent-os": "0.3.34"
|
|
12087
|
-
};
|
|
12088
|
-
var MEMORY_COST_MANAGED_PACKAGES = Object.keys(
|
|
12089
|
-
MEMORY_COST_PACKAGE_MIN_VERSIONS
|
|
12090
|
-
);
|
|
12091
|
-
var DISPLAY_NAMES = {
|
|
12092
|
-
"@kynver-app/runtime": "Kynver runtime",
|
|
12093
|
-
"@kynver-app/openclaw-agent-os": "OpenClaw AgentOS plugin",
|
|
12094
|
-
"@kynver-app/mcp-agent-os": "AgentOS MCP server"
|
|
12095
|
-
};
|
|
12096
|
-
var REPO_PACKAGE_JSON_RELATIVE = {
|
|
12097
|
-
"@kynver-app/runtime": "packages/kynver-runtime/package.json",
|
|
12098
|
-
"@kynver-app/openclaw-agent-os": "packages/kynver-openclaw-agent-os/package.json",
|
|
12099
|
-
"@kynver-app/mcp-agent-os": "packages/kynver-mcp-agent-os/package.json"
|
|
12100
|
-
};
|
|
12101
|
-
function parseSemverParts(version) {
|
|
12102
|
-
const core = version.trim().split("-")[0]?.split("+")[0];
|
|
12103
|
-
if (!core) return null;
|
|
12104
|
-
const parts = core.split(".");
|
|
12105
|
-
if (parts.length < 1 || parts.length > 3) return null;
|
|
12106
|
-
const nums = parts.map((p) => Number.parseInt(p, 10));
|
|
12107
|
-
if (nums.some((n) => !Number.isFinite(n) || n < 0)) return null;
|
|
12108
|
-
while (nums.length < 3) nums.push(0);
|
|
12109
|
-
return [nums[0], nums[1], nums[2]];
|
|
12110
|
-
}
|
|
12111
|
-
function compareSemver(a, b) {
|
|
12112
|
-
const pa = parseSemverParts(a);
|
|
12113
|
-
const pb = parseSemverParts(b);
|
|
12114
|
-
if (!pa || !pb) return 0;
|
|
12115
|
-
for (let i = 0; i < 3; i += 1) {
|
|
12116
|
-
if (pa[i] > pb[i]) return 1;
|
|
12117
|
-
if (pa[i] < pb[i]) return -1;
|
|
12118
|
-
}
|
|
12119
|
-
return 0;
|
|
12120
|
-
}
|
|
12121
|
-
function semverAtLeast(version, minimum) {
|
|
12122
|
-
return compareSemver(version, minimum) >= 0;
|
|
12123
|
-
}
|
|
12124
|
-
function maxSemver(versions) {
|
|
12125
|
-
let best = null;
|
|
12126
|
-
for (const version of versions) {
|
|
12127
|
-
if (!best || compareSemver(version, best) > 0) best = version;
|
|
12128
|
-
}
|
|
12129
|
-
return best;
|
|
12130
|
-
}
|
|
12131
|
-
function readPackageJsonVersion(packageJsonPath) {
|
|
12132
|
-
try {
|
|
12133
|
-
const parsed = JSON.parse(readFileSync14(packageJsonPath, "utf8"));
|
|
12134
|
-
return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
|
|
12135
|
-
} catch {
|
|
12136
|
-
return null;
|
|
12137
|
-
}
|
|
12138
|
-
}
|
|
12139
|
-
function resolveRepoRoot(cwd, explicitRepoRoot) {
|
|
12140
|
-
const candidates = [explicitRepoRoot, process.env.KYNVER_REPO, cwd].filter(
|
|
12141
|
-
(value) => Boolean(value?.trim())
|
|
12142
|
-
);
|
|
12143
|
-
for (const candidate of candidates) {
|
|
12144
|
-
const resolved = path61.resolve(candidate);
|
|
12145
|
-
if (existsSync43(path61.join(resolved, "packages/kynver-runtime/package.json")) && existsSync43(path61.join(resolved, "package.json"))) {
|
|
12146
|
-
return resolved;
|
|
12147
|
-
}
|
|
12148
|
-
}
|
|
12149
|
-
return null;
|
|
12150
|
-
}
|
|
12151
|
-
function probeRepoPackageVersions(input = {}) {
|
|
12152
|
-
const cwd = input.cwd ?? process.cwd();
|
|
12153
|
-
const repoRoot = resolveRepoRoot(cwd, input.repoRoot);
|
|
12154
|
-
if (!repoRoot) return {};
|
|
12155
|
-
const out = {};
|
|
12156
|
-
for (const packageName of MEMORY_COST_MANAGED_PACKAGES) {
|
|
12157
|
-
const packageJsonPath = path61.join(repoRoot, REPO_PACKAGE_JSON_RELATIVE[packageName]);
|
|
12158
|
-
const version = readPackageJsonVersion(packageJsonPath);
|
|
12159
|
-
if (!version) continue;
|
|
12160
|
-
out[packageName] = { version, source: "repo", path: packageJsonPath };
|
|
12161
|
-
}
|
|
12162
|
-
return out;
|
|
12163
|
-
}
|
|
12164
|
-
function repoSourceCommands(packageName) {
|
|
12165
|
-
if (packageName === "@kynver-app/runtime") {
|
|
12166
|
-
return ["npm run kynver:build", "npm run kynver"];
|
|
12167
|
-
}
|
|
12168
|
-
return [`npm run build -w ${packageName}`];
|
|
12169
|
-
}
|
|
12170
|
-
function buildRemediation(input) {
|
|
12171
|
-
const { packageName, minimumVersion, effectiveVersion, effectiveSource, repoVersion } = input;
|
|
12172
|
-
const lines = [];
|
|
12173
|
-
if (repoVersion && semverAtLeast(repoVersion, minimumVersion)) {
|
|
12174
|
-
lines.push(
|
|
12175
|
-
`Use the monorepo checkout (${repoVersion}) instead of a stale npm install: ${repoSourceCommands(packageName).join("; ")}.`
|
|
12176
|
-
);
|
|
12177
|
-
lines.push("Do not publish npm packages or wait on an operator release.");
|
|
12178
|
-
return lines;
|
|
12179
|
-
}
|
|
12180
|
-
if (effectiveVersion) {
|
|
12181
|
-
lines.push(
|
|
12182
|
-
`Upgrade ${packageName} from ${effectiveVersion} to >= ${minimumVersion} (npm install -g ${packageName}@latest or align OpenClaw npm prefix).`
|
|
12183
|
-
);
|
|
12184
|
-
} else {
|
|
12185
|
-
lines.push(`Install ${packageName} >= ${minimumVersion} before running memory-heavy AgentOS paths.`);
|
|
12186
|
-
}
|
|
12187
|
-
if (packageName === "@kynver-app/runtime") {
|
|
12188
|
-
lines.push("Repo-source alternative: npm run kynver:build && npm run kynver");
|
|
12189
|
-
}
|
|
12190
|
-
if (effectiveSource === "installed" && repoVersion) {
|
|
12191
|
-
lines.push(`Repo checkout reports ${repoVersion}; rebuild/link repo source if you develop from the monorepo.`);
|
|
12192
|
-
}
|
|
12193
|
-
return lines;
|
|
12194
|
-
}
|
|
12195
|
-
function pickEffectiveCandidate(candidates) {
|
|
12196
|
-
if (candidates.length === 0) return { version: null, source: "unknown" };
|
|
12197
|
-
const best = maxSemver(candidates.map((candidate) => candidate.version));
|
|
12198
|
-
if (!best) return { version: null, source: "unknown" };
|
|
12199
|
-
const winner = candidates.find((candidate) => candidate.version === best) ?? candidates[0];
|
|
12200
|
-
return { version: winner.version, source: winner.source };
|
|
12201
|
-
}
|
|
12202
|
-
function evaluateMemoryCostPackageVersionGuard(input = {}) {
|
|
12203
|
-
const normalize2 = (value, fallbackSource) => {
|
|
12204
|
-
if (!value) return null;
|
|
12205
|
-
if (typeof value === "string") return { version: value, source: fallbackSource };
|
|
12206
|
-
return value;
|
|
12207
|
-
};
|
|
12208
|
-
const packages = MEMORY_COST_MANAGED_PACKAGES.map((packageName) => {
|
|
12209
|
-
const minimumVersion = MEMORY_COST_PACKAGE_MIN_VERSIONS[packageName];
|
|
12210
|
-
const candidates = [];
|
|
12211
|
-
const installed = normalize2(input.installed?.[packageName], "installed");
|
|
12212
|
-
const repo = normalize2(input.repo?.[packageName], "repo");
|
|
12213
|
-
const self = normalize2(input.self?.[packageName], "self");
|
|
12214
|
-
if (installed) candidates.push(installed);
|
|
12215
|
-
if (repo) candidates.push(repo);
|
|
12216
|
-
if (self) candidates.push(self);
|
|
12217
|
-
const { version: effectiveVersion, source: effectiveSource } = pickEffectiveCandidate(candidates);
|
|
12218
|
-
const repoVersion = repo?.version ?? null;
|
|
12219
|
-
const ok2 = effectiveVersion ? semverAtLeast(effectiveVersion, minimumVersion) : false;
|
|
12220
|
-
const remediation = ok2 ? [] : buildRemediation({
|
|
12221
|
-
packageName,
|
|
12222
|
-
minimumVersion,
|
|
12223
|
-
effectiveVersion,
|
|
12224
|
-
effectiveSource,
|
|
12225
|
-
repoVersion
|
|
12226
|
-
});
|
|
12227
|
-
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)") + ".";
|
|
12228
|
-
return {
|
|
12229
|
-
packageName,
|
|
12230
|
-
displayName: DISPLAY_NAMES[packageName],
|
|
12231
|
-
minimumVersion,
|
|
12232
|
-
effectiveVersion,
|
|
12233
|
-
effectiveSource,
|
|
12234
|
-
ok: ok2,
|
|
12235
|
-
summary: summary2,
|
|
12236
|
-
remediation
|
|
12237
|
-
};
|
|
12238
|
-
});
|
|
12239
|
-
const violations = packages.filter((row) => !row.ok);
|
|
12240
|
-
const ok = violations.length === 0;
|
|
12241
|
-
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("; ")}.`;
|
|
12242
|
-
return { ok, summary, packages };
|
|
12243
|
-
}
|
|
12244
|
-
var MemoryCostPackageVersionGuardError = class extends Error {
|
|
12245
|
-
result;
|
|
12246
|
-
constructor(result) {
|
|
12247
|
-
const lines = [
|
|
12248
|
-
result.summary,
|
|
12249
|
-
...result.packages.filter((row) => !row.ok).flatMap((row) => [`- ${row.summary}`, ...row.remediation.map((line) => ` \u2192 ${line}`)])
|
|
12250
|
-
];
|
|
12251
|
-
super(lines.join("\n"));
|
|
12252
|
-
this.name = "MemoryCostPackageVersionGuardError";
|
|
12253
|
-
this.result = result;
|
|
12254
|
-
}
|
|
12255
|
-
};
|
|
12256
|
-
function assertMemoryCostPackageVersionGuard(input = {}) {
|
|
12257
|
-
const result = evaluateMemoryCostPackageVersionGuard(input);
|
|
12258
|
-
if (!result.ok) throw new MemoryCostPackageVersionGuardError(result);
|
|
12259
|
-
return result;
|
|
12260
|
-
}
|
|
12261
|
-
|
|
12262
12287
|
// src/memory-cost-package-version-guard-enforce.ts
|
|
12263
12288
|
function installedVersionMap(observed) {
|
|
12264
12289
|
const out = {};
|
|
@@ -12278,10 +12303,10 @@ async function buildMemoryCostPackageGuardInput(input = {}) {
|
|
|
12278
12303
|
Promise.resolve(probeRepoPackageVersions({ cwd: input.cwd, repoRoot: input.repoRoot }))
|
|
12279
12304
|
]);
|
|
12280
12305
|
const self = {};
|
|
12281
|
-
|
|
12306
|
+
const runtimeSelfVersion = input.selfPackageName === "@kynver-app/runtime" && input.selfVersion ? input.selfVersion : PACKAGE_VERSION;
|
|
12307
|
+
self["@kynver-app/runtime"] = { version: runtimeSelfVersion, source: "self" };
|
|
12308
|
+
if (input.selfPackageName && input.selfVersion && input.selfPackageName !== "@kynver-app/runtime") {
|
|
12282
12309
|
self[input.selfPackageName] = { version: input.selfVersion, source: "self" };
|
|
12283
|
-
} else {
|
|
12284
|
-
self["@kynver-app/runtime"] = { version: PACKAGE_VERSION, source: "self" };
|
|
12285
12310
|
}
|
|
12286
12311
|
return {
|
|
12287
12312
|
installed: installedVersionMap(installed),
|
|
@@ -12601,9 +12626,7 @@ var defaultRuntimeTakeoverProbes = {
|
|
|
12601
12626
|
harnessRoot: () => resolveHarnessRoot(),
|
|
12602
12627
|
legacyOpenclawHarnessRoot: () => path64.join(homedir15(), ".openclaw", "harness"),
|
|
12603
12628
|
pathExists: (target) => existsSync44(target),
|
|
12604
|
-
pathWritable: (target) => isWritable(target)
|
|
12605
|
-
vercelVersion: () => captureCommand("vercel", ["--version"]),
|
|
12606
|
-
vercelWhoami: () => captureCommand("vercel", ["whoami"])
|
|
12629
|
+
pathWritable: (target) => isWritable(target)
|
|
12607
12630
|
};
|
|
12608
12631
|
|
|
12609
12632
|
// src/doctor/runtime-takeover-scheduler.ts
|
|
@@ -12970,29 +12993,38 @@ function assessRunnerToken(probes) {
|
|
|
12970
12993
|
];
|
|
12971
12994
|
return { id: "runner_token", label: "Runner token readiness", checks };
|
|
12972
12995
|
}
|
|
12973
|
-
function
|
|
12974
|
-
const
|
|
12975
|
-
const
|
|
12976
|
-
const
|
|
12996
|
+
function assessVercelDeployEvidence(probes) {
|
|
12997
|
+
const globalCli = probes.commandOnPath("vercel");
|
|
12998
|
+
const cliInstalled = globalCli.ok;
|
|
12999
|
+
const githubToken = Boolean(
|
|
13000
|
+
process.env.GITHUB_TOKEN?.trim() || process.env.GH_TOKEN?.trim()
|
|
13001
|
+
);
|
|
13002
|
+
const vercelToken = Boolean(process.env.VERCEL_TOKEN?.trim());
|
|
12977
13003
|
return {
|
|
12978
|
-
id: "
|
|
12979
|
-
label: "Vercel
|
|
13004
|
+
id: "vercel_deploy_evidence",
|
|
13005
|
+
label: "Vercel deploy evidence",
|
|
12980
13006
|
checks: [
|
|
12981
13007
|
check2({
|
|
12982
|
-
id: "
|
|
12983
|
-
label: "Vercel CLI installed",
|
|
12984
|
-
status:
|
|
12985
|
-
summary:
|
|
12986
|
-
remediation:
|
|
12987
|
-
details: {
|
|
13008
|
+
id: "vercel_global_cli_absent",
|
|
13009
|
+
label: "Global Vercel CLI not installed",
|
|
13010
|
+
status: cliInstalled ? "warn" : "pass",
|
|
13011
|
+
summary: cliInstalled ? `Global Vercel CLI found (${globalCli.stdout || "on PATH"}) \u2014 uninstall after operator approval` : "No global Vercel CLI on PATH",
|
|
13012
|
+
remediation: cliInstalled ? "Uninstall global Vercel CLI (`npm uninstall -g vercel`) \u2014 use GitHub commit status or scoped VERCEL_TOKEN + REST API instead." : void 0,
|
|
13013
|
+
details: { path: cliInstalled ? globalCli.stdout || null : null }
|
|
13014
|
+
}),
|
|
13015
|
+
check2({
|
|
13016
|
+
id: "github_token_for_vercel_status",
|
|
13017
|
+
label: "GitHub token for Vercel status",
|
|
13018
|
+
status: githubToken ? "pass" : "warn",
|
|
13019
|
+
summary: githubToken ? "GITHUB_TOKEN/GH_TOKEN present for GitHub Vercel StatusContext evidence" : "No GITHUB_TOKEN \u2014 merge-gate Vercel evidence requires GitHub commit status API",
|
|
13020
|
+
remediation: githubToken ? void 0 : "Export GITHUB_TOKEN (or GH_TOKEN) for PR head commit status lookups."
|
|
12988
13021
|
}),
|
|
12989
13022
|
check2({
|
|
12990
|
-
id: "
|
|
12991
|
-
label: "Vercel
|
|
12992
|
-
status:
|
|
12993
|
-
summary:
|
|
12994
|
-
remediation:
|
|
12995
|
-
details: { account: whoami.ok ? whoami.stdout : null }
|
|
13023
|
+
id: "vercel_api_token_optional",
|
|
13024
|
+
label: "Vercel API token (optional fallback)",
|
|
13025
|
+
status: vercelToken ? "pass" : "warn",
|
|
13026
|
+
summary: vercelToken ? "VERCEL_TOKEN configured for optional REST API deployment lookup" : "VERCEL_TOKEN unset \u2014 GitHub status is the default path; API fallback disabled",
|
|
13027
|
+
remediation: vercelToken ? void 0 : "Set ephemeral/scoped VERCEL_TOKEN only when GitHub status is insufficient; avoid persistent ~/.vercel auth on runner hosts."
|
|
12996
13028
|
})
|
|
12997
13029
|
]
|
|
12998
13030
|
};
|
|
@@ -13131,7 +13163,7 @@ function assessRuntimeTakeoverReadiness(probes = defaultRuntimeTakeoverProbes) {
|
|
|
13131
13163
|
assessCliPackage(probes),
|
|
13132
13164
|
assessUserConfig(probes),
|
|
13133
13165
|
assessRunnerToken(probes),
|
|
13134
|
-
|
|
13166
|
+
assessVercelDeployEvidence(probes),
|
|
13135
13167
|
assessHarnessDirs(probes),
|
|
13136
13168
|
assessCallbackAuth(probes),
|
|
13137
13169
|
assessOpenclawHotspots(probes)
|
|
@@ -13481,7 +13513,19 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
13481
13513
|
mkdirSync8(runsDir, { recursive: true });
|
|
13482
13514
|
mkdirSync8(worktreesDir, { recursive: true });
|
|
13483
13515
|
if (shouldEnforceMemoryCostPackageGuardCli(scope, action)) {
|
|
13484
|
-
|
|
13516
|
+
let repoRoot;
|
|
13517
|
+
const runId = args.run ? String(args.run).trim() : "";
|
|
13518
|
+
if (runId) {
|
|
13519
|
+
try {
|
|
13520
|
+
repoRoot = loadRun(runId).repo;
|
|
13521
|
+
} catch {
|
|
13522
|
+
repoRoot = void 0;
|
|
13523
|
+
}
|
|
13524
|
+
}
|
|
13525
|
+
await enforceMemoryCostPackageGuardAtStartup({
|
|
13526
|
+
repoRoot,
|
|
13527
|
+
cwd: repoRoot
|
|
13528
|
+
});
|
|
13485
13529
|
}
|
|
13486
13530
|
if (scope === "login") return void await runLogin(args);
|
|
13487
13531
|
if (scope === "runner" && action === "credential") return void await mintRunnerCredential(args);
|