@kynver-app/runtime 0.1.42 → 0.1.47
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/README.md +15 -0
- package/dist/auto-complete.d.ts +60 -0
- package/dist/bounded-build/admission.d.ts +30 -0
- package/dist/bounded-build/constants.d.ts +10 -0
- package/dist/bounded-build/exec.d.ts +26 -0
- package/dist/bounded-build/index.d.ts +6 -0
- package/dist/bounded-build/meminfo.d.ts +5 -0
- package/dist/bounded-build/node-options.d.ts +9 -0
- package/dist/bounded-build/systemd-wrap.d.ts +17 -0
- package/dist/callback-headers.d.ts +2 -0
- package/dist/callbacks.d.ts +38 -0
- package/dist/cleanup-cli.d.ts +1 -0
- package/dist/cleanup-dir-size.d.ts +4 -0
- package/dist/cleanup-execute.d.ts +4 -0
- package/dist/cleanup-guards.d.ts +18 -0
- package/dist/cleanup-scan.d.ts +14 -0
- package/dist/cleanup-types.d.ts +56 -0
- package/dist/cleanup-worktree-index.d.ts +13 -0
- package/dist/cleanup.d.ts +5 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +789 -74
- package/dist/cli.js.map +4 -4
- package/dist/command-center-contract-cli.d.ts +1 -0
- package/dist/completion-ack.d.ts +10 -0
- package/dist/completion-response.d.ts +15 -0
- package/dist/config.d.ts +61 -0
- package/dist/daemon.d.ts +5 -0
- package/dist/disk-gate.d.ts +9 -0
- package/dist/dispatch.d.ts +16 -0
- package/dist/doctor/doctor.types.d.ts +25 -0
- package/dist/doctor/index.d.ts +4 -0
- package/dist/doctor/runtime-takeover-cli.d.ts +1 -0
- package/dist/doctor/runtime-takeover.d.ts +3 -0
- package/dist/doctor/runtime-takeover.probes.d.ts +37 -0
- package/dist/exit-classify.d.ts +12 -0
- package/dist/exited-salvage.d.ts +22 -0
- package/dist/finalize.d.ts +16 -0
- package/dist/fortress-engagement-gate.d.ts +5 -0
- package/dist/git.d.ts +37 -0
- package/dist/github-repo.d.ts +5 -0
- package/dist/harness-verify-cli.d.ts +1 -0
- package/dist/harness-verify.d.ts +19 -0
- package/dist/heartbeat.d.ts +22 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +829 -78
- package/dist/index.js.map +4 -4
- package/dist/installed-package-versions.d.ts +6 -0
- package/dist/landing-contract-gate.d.ts +24 -0
- package/dist/landing-gate.d.ts +24 -0
- package/dist/lease-renewal.d.ts +15 -0
- package/dist/model-routing-task-enrich.d.ts +8 -0
- package/dist/model-routing.d.ts +29 -0
- package/dist/monitor/index.d.ts +7 -0
- package/dist/monitor/monitor-cli.d.ts +9 -0
- package/dist/monitor/monitor-loop.d.ts +1 -0
- package/dist/monitor/monitor-spawn.d.ts +18 -0
- package/dist/monitor/monitor.classify.d.ts +15 -0
- package/dist/monitor/monitor.service.d.ts +17 -0
- package/dist/monitor/monitor.store.d.ts +6 -0
- package/dist/monitor/monitor.task-lease.d.ts +11 -0
- package/dist/monitor/monitor.terminal.d.ts +11 -0
- package/dist/monitor/monitor.types.d.ts +74 -0
- package/dist/package-version.d.ts +5 -0
- package/dist/path-values.d.ts +5 -0
- package/dist/paths.d.ts +7 -0
- package/dist/pipeline-dispatch.d.ts +7 -0
- package/dist/pipeline-tick.d.ts +45 -0
- package/dist/plan-persist/agentos-api.d.ts +28 -0
- package/dist/plan-persist/body-hash.d.ts +3 -0
- package/dist/plan-persist/drain.d.ts +7 -0
- package/dist/plan-persist/errors.d.ts +9 -0
- package/dist/plan-persist/handoff.d.ts +7 -0
- package/dist/plan-persist/idempotency.d.ts +2 -0
- package/dist/plan-persist/index.d.ts +8 -0
- package/dist/plan-persist/outbox-store.d.ts +18 -0
- package/dist/plan-persist/paths.d.ts +8 -0
- package/dist/plan-persist/persist.d.ts +10 -0
- package/dist/plan-persist/readback.d.ts +17 -0
- package/dist/plan-persist/types.d.ts +91 -0
- package/dist/plan-persist-cli.d.ts +3 -0
- package/dist/plan-progress-daemon-sync.d.ts +7 -0
- package/dist/plan-progress-sync.d.ts +21 -0
- package/dist/plan-progress.d.ts +10 -0
- package/dist/pr-handoff/index.d.ts +4 -0
- package/dist/pr-handoff/pr-handoff-assess.d.ts +26 -0
- package/dist/pr-handoff/pr-handoff-gh.d.ts +44 -0
- package/dist/pr-handoff/pr-handoff.d.ts +8 -0
- package/dist/pr-handoff/pr-handoff.types.d.ts +45 -0
- package/dist/prompt.d.ts +14 -0
- package/dist/providers/claude.d.ts +4 -0
- package/dist/providers/cursor-windows.d.ts +7 -0
- package/dist/providers/cursor.d.ts +11 -0
- package/dist/providers/model-preflight.d.ts +31 -0
- package/dist/providers/registry.d.ts +4 -0
- package/dist/providers/types.d.ts +32 -0
- package/dist/redact.d.ts +1 -0
- package/dist/resource-gate.d.ts +53 -0
- package/dist/retry-limits.d.ts +8 -0
- package/dist/run-store.d.ts +30 -0
- package/dist/shell-command-outcome.d.ts +32 -0
- package/dist/stale-reconcile.d.ts +25 -0
- package/dist/status.d.ts +161 -0
- package/dist/stream.d.ts +20 -0
- package/dist/supervisor.d.ts +25 -0
- package/dist/sweep.d.ts +1 -0
- package/dist/util.d.ts +22 -0
- package/dist/validate.d.ts +5 -0
- package/dist/vercel/index.d.ts +3 -0
- package/dist/vercel/vercel-evidence.d.ts +48 -0
- package/dist/vercel/vercel-github-status.d.ts +19 -0
- package/dist/vercel/vercel-url.d.ts +16 -0
- package/dist/worker-env.d.ts +15 -0
- package/dist/worker-lifecycle.d.ts +28 -0
- package/dist/worker-ops.d.ts +20 -0
- package/dist/workspace-runtime-config.d.ts +8 -0
- package/dist/worktree.d.ts +4 -0
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -508,12 +508,12 @@ var DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
|
|
|
508
508
|
var DEFAULT_MAX_USED_PERCENT = 80;
|
|
509
509
|
var DEFAULT_HARD_MAX_USED_PERCENT = 90;
|
|
510
510
|
function observeRunnerDiskGate(input = {}) {
|
|
511
|
-
const
|
|
511
|
+
const path38 = input.diskPath?.trim() || "/";
|
|
512
512
|
const warnBelowBytes = input.diskFreeWarnBytes ?? DEFAULT_WARN_FREE_BYTES;
|
|
513
513
|
const criticalBelowBytes = input.diskFreeCriticalBytes ?? DEFAULT_CRITICAL_FREE_BYTES;
|
|
514
514
|
const maxUsedPercent = input.diskMaxUsedPercent ?? DEFAULT_MAX_USED_PERCENT;
|
|
515
515
|
const hardMaxUsedPercent = input.diskHardMaxUsedPercent ?? DEFAULT_HARD_MAX_USED_PERCENT;
|
|
516
|
-
const stats = statfsSync(
|
|
516
|
+
const stats = statfsSync(path38);
|
|
517
517
|
const freeBytes = Number(stats.bavail) * Number(stats.bsize);
|
|
518
518
|
const totalBytes = Number(stats.blocks) * Number(stats.bsize);
|
|
519
519
|
const usedPercent = totalBytes > 0 ? (totalBytes - freeBytes) / totalBytes * 100 : 100;
|
|
@@ -533,7 +533,7 @@ function observeRunnerDiskGate(input = {}) {
|
|
|
533
533
|
}
|
|
534
534
|
return {
|
|
535
535
|
ok,
|
|
536
|
-
path:
|
|
536
|
+
path: path38,
|
|
537
537
|
freeBytes,
|
|
538
538
|
totalBytes,
|
|
539
539
|
usedPercent,
|
|
@@ -546,8 +546,29 @@ function observeRunnerDiskGate(input = {}) {
|
|
|
546
546
|
}
|
|
547
547
|
|
|
548
548
|
// src/resource-gate.ts
|
|
549
|
-
import
|
|
549
|
+
import os2 from "node:os";
|
|
550
|
+
|
|
551
|
+
// src/bounded-build/meminfo.ts
|
|
552
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
550
553
|
import os from "node:os";
|
|
554
|
+
function readMemAvailableBytes(meminfoText) {
|
|
555
|
+
if (meminfoText !== void 0) {
|
|
556
|
+
const match = meminfoText.match(/^MemAvailable:\s+(\d+)\s*kB/m);
|
|
557
|
+
if (match) return Number(match[1]) * 1024;
|
|
558
|
+
return os.freemem();
|
|
559
|
+
}
|
|
560
|
+
if (process.platform === "linux") {
|
|
561
|
+
try {
|
|
562
|
+
const meminfo = readFileSync4("/proc/meminfo", "utf8");
|
|
563
|
+
const match = meminfo.match(/^MemAvailable:\s+(\d+)\s*kB/m);
|
|
564
|
+
if (match) return Number(match[1]) * 1024;
|
|
565
|
+
} catch {
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return os.freemem();
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// src/resource-gate.ts
|
|
551
572
|
import path6 from "node:path";
|
|
552
573
|
|
|
553
574
|
// src/run-store.ts
|
|
@@ -623,7 +644,7 @@ function runDirectory(id) {
|
|
|
623
644
|
}
|
|
624
645
|
|
|
625
646
|
// src/heartbeat.ts
|
|
626
|
-
import { existsSync as existsSync6, readFileSync as
|
|
647
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
|
|
627
648
|
var HEARTBEAT_FUTURE_SKEW_MS = 6e4;
|
|
628
649
|
function isTerminalHeartbeatPhase(phase) {
|
|
629
650
|
return phase === "complete";
|
|
@@ -645,7 +666,7 @@ function parseHeartbeat(file) {
|
|
|
645
666
|
if (!existsSync6(file)) return result;
|
|
646
667
|
const maxFutureMs = Date.now() + HEARTBEAT_FUTURE_SKEW_MS;
|
|
647
668
|
const clampedTo = new Date(maxFutureMs).toISOString();
|
|
648
|
-
const lines =
|
|
669
|
+
const lines = readFileSync5(file, "utf8").split("\n").filter(Boolean);
|
|
649
670
|
for (const line of lines) {
|
|
650
671
|
const entry = safeJson(line);
|
|
651
672
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
@@ -672,7 +693,155 @@ function parseHeartbeat(file) {
|
|
|
672
693
|
}
|
|
673
694
|
|
|
674
695
|
// src/stream.ts
|
|
675
|
-
import { existsSync as existsSync7, readFileSync as
|
|
696
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6 } from "node:fs";
|
|
697
|
+
|
|
698
|
+
// src/shell-command-outcome.ts
|
|
699
|
+
var NPM_AUDIT_RE = /\bnpm\s+audit\b/i;
|
|
700
|
+
function tidy(text, max = 200) {
|
|
701
|
+
const one = text.replace(/\s+/g, " ").trim();
|
|
702
|
+
return one.length > max ? `${one.slice(0, max - 1)}\u2026` : one;
|
|
703
|
+
}
|
|
704
|
+
function extractJsonObject(text) {
|
|
705
|
+
const trimmed = text.trim();
|
|
706
|
+
if (!trimmed) return null;
|
|
707
|
+
if (trimmed.startsWith("{")) {
|
|
708
|
+
try {
|
|
709
|
+
return JSON.parse(trimmed);
|
|
710
|
+
} catch {
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
const start = trimmed.indexOf("{");
|
|
714
|
+
const end = trimmed.lastIndexOf("}");
|
|
715
|
+
if (start >= 0 && end > start) {
|
|
716
|
+
try {
|
|
717
|
+
return JSON.parse(trimmed.slice(start, end + 1));
|
|
718
|
+
} catch {
|
|
719
|
+
return null;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return null;
|
|
723
|
+
}
|
|
724
|
+
function isRecord(value) {
|
|
725
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
726
|
+
}
|
|
727
|
+
function summarizeNpmAuditReport(report) {
|
|
728
|
+
const meta = report.metadata;
|
|
729
|
+
if (!isRecord(meta)) return null;
|
|
730
|
+
const vuln = meta.vulnerabilities;
|
|
731
|
+
if (!isRecord(vuln)) return null;
|
|
732
|
+
const num = (key) => typeof vuln[key] === "number" ? vuln[key] : 0;
|
|
733
|
+
const summary = {
|
|
734
|
+
info: num("info"),
|
|
735
|
+
low: num("low"),
|
|
736
|
+
moderate: num("moderate"),
|
|
737
|
+
high: num("high"),
|
|
738
|
+
critical: num("critical"),
|
|
739
|
+
total: num("total")
|
|
740
|
+
};
|
|
741
|
+
if (typeof vuln.total !== "number" && !summary.critical && !summary.high && !summary.moderate && !summary.low && !summary.info) {
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
return summary;
|
|
745
|
+
}
|
|
746
|
+
function formatAuditSummaryLine(audit) {
|
|
747
|
+
const parts = [];
|
|
748
|
+
if (audit.critical) parts.push(`${audit.critical} critical`);
|
|
749
|
+
if (audit.high) parts.push(`${audit.high} high`);
|
|
750
|
+
if (audit.moderate) parts.push(`${audit.moderate} moderate`);
|
|
751
|
+
if (audit.low) parts.push(`${audit.low} low`);
|
|
752
|
+
if (audit.info) parts.push(`${audit.info} info`);
|
|
753
|
+
const breakdown = parts.length ? parts.join(", ") : "see report";
|
|
754
|
+
return `npm audit: ${audit.total} vulnerabilit${audit.total === 1 ? "y" : "ies"} (${breakdown}) \u2014 remediation required`;
|
|
755
|
+
}
|
|
756
|
+
function npmAuditFailureReason(report, stderr) {
|
|
757
|
+
const err = report.error;
|
|
758
|
+
if (isRecord(err)) {
|
|
759
|
+
const summary = typeof err.summary === "string" ? err.summary.trim() : "";
|
|
760
|
+
const code = typeof err.code === "string" ? err.code.trim() : "";
|
|
761
|
+
if (summary) return code ? `${code}: ${summary}` : summary;
|
|
762
|
+
if (code) return code;
|
|
763
|
+
}
|
|
764
|
+
const detail = typeof report.message === "string" ? report.message.trim() : "";
|
|
765
|
+
if (detail) return detail;
|
|
766
|
+
const errTail = stderr.trim();
|
|
767
|
+
if (errTail) return tidy(errTail.split("\n").find(Boolean) ?? errTail, 160);
|
|
768
|
+
return "npm audit failed";
|
|
769
|
+
}
|
|
770
|
+
function classifyNpmAuditOutcome(input) {
|
|
771
|
+
const combined = `${input.stdout}
|
|
772
|
+
${input.stderr}`.trim();
|
|
773
|
+
const parsed = extractJsonObject(combined);
|
|
774
|
+
if (!parsed || !isRecord(parsed)) {
|
|
775
|
+
const tail = tidy(combined || `exit ${input.exitCode}`, 180);
|
|
776
|
+
return {
|
|
777
|
+
kind: "command_failure",
|
|
778
|
+
exitCode: input.exitCode,
|
|
779
|
+
summary: `npm audit failed (invalid or missing JSON): ${tail}`,
|
|
780
|
+
parseError: "invalid_json"
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
if (isRecord(parsed.error)) {
|
|
784
|
+
return {
|
|
785
|
+
kind: "command_failure",
|
|
786
|
+
exitCode: input.exitCode,
|
|
787
|
+
summary: `npm audit command failed: ${npmAuditFailureReason(parsed, input.stderr)}`
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
const audit = summarizeNpmAuditReport(parsed);
|
|
791
|
+
if (!audit) {
|
|
792
|
+
return {
|
|
793
|
+
kind: "command_failure",
|
|
794
|
+
exitCode: input.exitCode,
|
|
795
|
+
summary: "npm audit failed: JSON response missing vulnerability metadata",
|
|
796
|
+
parseError: "missing_metadata"
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
if (input.exitCode === 0 && audit.total === 0) {
|
|
800
|
+
return {
|
|
801
|
+
kind: "success",
|
|
802
|
+
exitCode: 0,
|
|
803
|
+
summary: "npm audit: no vulnerabilities reported",
|
|
804
|
+
audit
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
return {
|
|
808
|
+
kind: "audit_findings",
|
|
809
|
+
exitCode: input.exitCode,
|
|
810
|
+
summary: formatAuditSummaryLine(audit),
|
|
811
|
+
audit
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
function isNpmAuditCommand(command) {
|
|
815
|
+
return NPM_AUDIT_RE.test(command);
|
|
816
|
+
}
|
|
817
|
+
function classifyShellCommandOutcome(input) {
|
|
818
|
+
const stdout = input.stdout ?? "";
|
|
819
|
+
const stderr = input.stderr ?? "";
|
|
820
|
+
const interleaved = input.interleavedOutput ?? "";
|
|
821
|
+
if (isNpmAuditCommand(input.command)) {
|
|
822
|
+
const body = stdout.trim() || interleaved.trim() || stderr.trim();
|
|
823
|
+
return classifyNpmAuditOutcome({
|
|
824
|
+
exitCode: input.exitCode,
|
|
825
|
+
stdout: body,
|
|
826
|
+
stderr
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
if (input.exitCode === 0) {
|
|
830
|
+
return {
|
|
831
|
+
kind: "success",
|
|
832
|
+
exitCode: 0,
|
|
833
|
+
summary: `command succeeded (exit 0)`
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
const tail = tidy(interleaved || stdout || stderr || `exit ${input.exitCode}`, 180);
|
|
837
|
+
return {
|
|
838
|
+
kind: "command_failure",
|
|
839
|
+
exitCode: input.exitCode,
|
|
840
|
+
summary: `command failed (exit ${input.exitCode}): ${tail}`
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// src/stream.ts
|
|
676
845
|
function eventTimestampIso(event) {
|
|
677
846
|
const tsMs = event.timestamp_ms;
|
|
678
847
|
return event.timestamp || event.ts || (tsMs ? new Date(tsMs).toISOString() : void 0);
|
|
@@ -693,16 +862,43 @@ function recordStreamResult(result, event) {
|
|
|
693
862
|
result.error = String(event.result || event.api_error_status || "stream result error");
|
|
694
863
|
}
|
|
695
864
|
}
|
|
865
|
+
function shellPayloadFromCursorEvent(event) {
|
|
866
|
+
if (event.type !== "tool_call" || event.subtype !== "completed") return null;
|
|
867
|
+
const toolCall = event.tool_call && typeof event.tool_call === "object" && !Array.isArray(event.tool_call) ? event.tool_call : null;
|
|
868
|
+
const shell = toolCall?.shellToolCall;
|
|
869
|
+
if (!shell || typeof shell !== "object" || Array.isArray(shell)) return null;
|
|
870
|
+
const shellObj = shell;
|
|
871
|
+
const args = shellObj.args;
|
|
872
|
+
const command = args && typeof args === "object" && !Array.isArray(args) && typeof args.command === "string" ? String(args.command) : "";
|
|
873
|
+
const result = shellObj.result;
|
|
874
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) return null;
|
|
875
|
+
const body = result.success ?? result.failure;
|
|
876
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) return null;
|
|
877
|
+
const row = body;
|
|
878
|
+
const exitCode = typeof row.exitCode === "number" ? row.exitCode : 0;
|
|
879
|
+
return {
|
|
880
|
+
command,
|
|
881
|
+
exitCode,
|
|
882
|
+
stdout: typeof row.stdout === "string" ? row.stdout : "",
|
|
883
|
+
stderr: typeof row.stderr === "string" ? row.stderr : "",
|
|
884
|
+
interleaved: typeof row.interleavedOutput === "string" ? row.interleavedOutput : ""
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
function applyShellOutcome(parsed, outcome) {
|
|
888
|
+
if (outcome.kind === "success") return;
|
|
889
|
+
parsed.lastShellOutcome = outcome;
|
|
890
|
+
}
|
|
696
891
|
function parseHarnessStream(file) {
|
|
697
892
|
const result = {
|
|
698
893
|
firstEventAt: null,
|
|
699
894
|
lastEventAt: null,
|
|
700
895
|
currentTool: null,
|
|
701
896
|
finalResult: null,
|
|
702
|
-
error: null
|
|
897
|
+
error: null,
|
|
898
|
+
lastShellOutcome: null
|
|
703
899
|
};
|
|
704
900
|
if (!existsSync7(file)) return result;
|
|
705
|
-
const lines =
|
|
901
|
+
const lines = readFileSync6(file, "utf8").split("\n").filter(Boolean);
|
|
706
902
|
for (const line of lines) {
|
|
707
903
|
const event = safeJson(line);
|
|
708
904
|
if (!event) continue;
|
|
@@ -727,6 +923,19 @@ function parseHarnessStream(file) {
|
|
|
727
923
|
const name = cursorToolNameFromCall(toolCall);
|
|
728
924
|
if (name) result.currentTool = name;
|
|
729
925
|
}
|
|
926
|
+
const shell = shellPayloadFromCursorEvent(event);
|
|
927
|
+
if (shell) {
|
|
928
|
+
applyShellOutcome(
|
|
929
|
+
result,
|
|
930
|
+
classifyShellCommandOutcome({
|
|
931
|
+
command: shell.command,
|
|
932
|
+
exitCode: shell.exitCode,
|
|
933
|
+
stdout: shell.stdout,
|
|
934
|
+
stderr: shell.stderr,
|
|
935
|
+
interleavedOutput: shell.interleaved
|
|
936
|
+
})
|
|
937
|
+
);
|
|
938
|
+
}
|
|
730
939
|
if (event.type === "result") {
|
|
731
940
|
recordStreamResult(result, event);
|
|
732
941
|
}
|
|
@@ -736,6 +945,25 @@ function parseHarnessStream(file) {
|
|
|
736
945
|
function parseClaudeStream(file) {
|
|
737
946
|
return parseHarnessStream(file);
|
|
738
947
|
}
|
|
948
|
+
function summarizeShellToolCallEvent(event) {
|
|
949
|
+
const shell = shellPayloadFromCursorEvent(event);
|
|
950
|
+
if (!shell) return void 0;
|
|
951
|
+
const outcome = classifyShellCommandOutcome({
|
|
952
|
+
command: shell.command,
|
|
953
|
+
exitCode: shell.exitCode,
|
|
954
|
+
stdout: shell.stdout,
|
|
955
|
+
stderr: shell.stderr,
|
|
956
|
+
interleavedOutput: shell.interleaved
|
|
957
|
+
});
|
|
958
|
+
const cmd = oneLine(shell.command).slice(0, 120);
|
|
959
|
+
if (outcome.kind === "audit_findings") {
|
|
960
|
+
return `[audit:findings] ${outcome.summary}${cmd ? ` \xB7 ${cmd}` : ""}`;
|
|
961
|
+
}
|
|
962
|
+
if (outcome.kind === "command_failure") {
|
|
963
|
+
return `[command:failed] ${outcome.summary}${cmd ? ` \xB7 ${cmd}` : ""}`;
|
|
964
|
+
}
|
|
965
|
+
return `[command:ok] exit 0${cmd ? ` \xB7 ${cmd}` : ""}`;
|
|
966
|
+
}
|
|
739
967
|
function summarizeEvent(event) {
|
|
740
968
|
if (event.type === "system" && event.subtype) {
|
|
741
969
|
return `[system:${event.subtype}] ${String(event.status || event.cwd || "")}`.trim();
|
|
@@ -768,6 +996,8 @@ function summarizeEvent(event) {
|
|
|
768
996
|
}
|
|
769
997
|
if (event.type === "tool_call") {
|
|
770
998
|
const subtype = String(event.subtype || "");
|
|
999
|
+
const shellSummary = subtype === "completed" ? summarizeShellToolCallEvent(event) : void 0;
|
|
1000
|
+
if (shellSummary) return shellSummary;
|
|
771
1001
|
const toolCall = event.tool_call && typeof event.tool_call === "object" && !Array.isArray(event.tool_call) ? event.tool_call : void 0;
|
|
772
1002
|
const name = cursorToolNameFromCall(toolCall) ?? "tool";
|
|
773
1003
|
return `[tool:${subtype}] ${name}`;
|
|
@@ -809,7 +1039,7 @@ var FAILURE_PATTERNS = [
|
|
|
809
1039
|
label: "provider authentication failed"
|
|
810
1040
|
}
|
|
811
1041
|
];
|
|
812
|
-
function
|
|
1042
|
+
function tidy2(errorText, max = 240) {
|
|
813
1043
|
const oneLine2 = errorText.replace(/\s+/g, " ").trim();
|
|
814
1044
|
return oneLine2.length > max ? `${oneLine2.slice(0, max - 1)}\u2026` : oneLine2;
|
|
815
1045
|
}
|
|
@@ -818,7 +1048,7 @@ function classifyExitFailure(errorText) {
|
|
|
818
1048
|
if (!text) return null;
|
|
819
1049
|
for (const pattern of FAILURE_PATTERNS) {
|
|
820
1050
|
if (pattern.test.test(text)) {
|
|
821
|
-
return { blocked: true, reason: `${pattern.label}: ${
|
|
1051
|
+
return { blocked: true, reason: `${pattern.label}: ${tidy2(text)}` };
|
|
822
1052
|
}
|
|
823
1053
|
}
|
|
824
1054
|
return null;
|
|
@@ -884,6 +1114,63 @@ function assessExitedWorkerSalvage(input) {
|
|
|
884
1114
|
|
|
885
1115
|
// src/git.ts
|
|
886
1116
|
import { spawnSync } from "node:child_process";
|
|
1117
|
+
|
|
1118
|
+
// src/worker-env.ts
|
|
1119
|
+
var FORBIDDEN_WORKER_ENV_KEYS = [
|
|
1120
|
+
"ANTHROPIC_API_KEY",
|
|
1121
|
+
"ANALYST_API_KEY",
|
|
1122
|
+
"RECRUITER_API_KEY",
|
|
1123
|
+
"AUTH_SECRET",
|
|
1124
|
+
"NEXTAUTH_SECRET",
|
|
1125
|
+
"DATABASE_URL",
|
|
1126
|
+
"PRODUCTION_DATABASE_URL",
|
|
1127
|
+
"REDIS_URL",
|
|
1128
|
+
"GOOGLE_CLIENT_SECRET",
|
|
1129
|
+
"GITHUB_CLIENT_SECRET",
|
|
1130
|
+
"KYNVER_API_KEY",
|
|
1131
|
+
"KYNVER_SERVICE_SECRET",
|
|
1132
|
+
"KYNVER_RUNTIME_SECRET",
|
|
1133
|
+
"OPENCLAW_CRON_SECRET",
|
|
1134
|
+
"QSTASH_TOKEN",
|
|
1135
|
+
"QSTASH_CURRENT_SIGNING_KEY",
|
|
1136
|
+
"QSTASH_NEXT_SIGNING_KEY",
|
|
1137
|
+
"TOOL_SECRETS_KEK",
|
|
1138
|
+
"TOOL_EXECUTOR_DISPATCH_SECRET",
|
|
1139
|
+
"CLOUDFLARE_API_TOKEN",
|
|
1140
|
+
"STRIPE_SECRET_KEY",
|
|
1141
|
+
"STRIPE_WEBHOOK_SECRET",
|
|
1142
|
+
"STRIPE_IDENTITY_WEBHOOK_SECRET",
|
|
1143
|
+
"VOYAGE_API_KEY",
|
|
1144
|
+
"PERPLEXITY_API_KEY",
|
|
1145
|
+
"FRED_API_KEY",
|
|
1146
|
+
"FMP_API_KEY",
|
|
1147
|
+
"CURSOR_API_KEY"
|
|
1148
|
+
];
|
|
1149
|
+
var FORBIDDEN_KEY_SET = new Set(FORBIDDEN_WORKER_ENV_KEYS);
|
|
1150
|
+
var FORBIDDEN_SUFFIXES = ["_SECRET", "_API_KEY"];
|
|
1151
|
+
function isForbiddenWorkerEnvKey(key) {
|
|
1152
|
+
if (FORBIDDEN_KEY_SET.has(key)) return true;
|
|
1153
|
+
return FORBIDDEN_SUFFIXES.some((suffix) => key.endsWith(suffix));
|
|
1154
|
+
}
|
|
1155
|
+
function listForbiddenWorkerEnvKeys(env) {
|
|
1156
|
+
return Object.keys(env).filter(isForbiddenWorkerEnvKey).sort();
|
|
1157
|
+
}
|
|
1158
|
+
function scrubWorkerEnv(env) {
|
|
1159
|
+
const next = { ...env };
|
|
1160
|
+
for (const key of Object.keys(next)) {
|
|
1161
|
+
if (isForbiddenWorkerEnvKey(key)) delete next[key];
|
|
1162
|
+
}
|
|
1163
|
+
return next;
|
|
1164
|
+
}
|
|
1165
|
+
function auditWorkerEnv(env) {
|
|
1166
|
+
const forbiddenPresent = listForbiddenWorkerEnvKeys(env);
|
|
1167
|
+
return { forbiddenPresent, safe: forbiddenPresent.length === 0 };
|
|
1168
|
+
}
|
|
1169
|
+
function scrubClaudeEnv(env) {
|
|
1170
|
+
return scrubWorkerEnv(env);
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
// src/git.ts
|
|
887
1174
|
function git(cwd, args, options = {}) {
|
|
888
1175
|
const res = spawnSync("git", args, { cwd, encoding: "utf8" });
|
|
889
1176
|
if (res.status !== 0 && !options.allowFailure) {
|
|
@@ -999,11 +1286,6 @@ function unknownAncestry(base, error, head = null) {
|
|
|
999
1286
|
error
|
|
1000
1287
|
};
|
|
1001
1288
|
}
|
|
1002
|
-
function scrubClaudeEnv(env) {
|
|
1003
|
-
const next = { ...env };
|
|
1004
|
-
delete next.ANTHROPIC_API_KEY;
|
|
1005
|
-
return next;
|
|
1006
|
-
}
|
|
1007
1289
|
|
|
1008
1290
|
// src/landing-gate.ts
|
|
1009
1291
|
function trimOrNull2(value) {
|
|
@@ -1353,15 +1635,7 @@ function computeAutoMaxWorkers(totalMemBytes, opts = {}) {
|
|
|
1353
1635
|
return Math.min(raw, AUTO_MAX_WORKERS_CEILING);
|
|
1354
1636
|
}
|
|
1355
1637
|
function readAvailableMemBytes() {
|
|
1356
|
-
|
|
1357
|
-
try {
|
|
1358
|
-
const meminfo = readFileSync6("/proc/meminfo", "utf8");
|
|
1359
|
-
const match = meminfo.match(/^MemAvailable:\s+(\d+)\s*kB/m);
|
|
1360
|
-
if (match) return Number(match[1]) * 1024;
|
|
1361
|
-
} catch {
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
return os.freemem();
|
|
1638
|
+
return readMemAvailableBytes();
|
|
1365
1639
|
}
|
|
1366
1640
|
function isActiveHarnessWorker(worker) {
|
|
1367
1641
|
const status = computeWorkerStatus(worker);
|
|
@@ -1389,7 +1663,7 @@ function observeRunnerResourceGate(input) {
|
|
|
1389
1663
|
input.config,
|
|
1390
1664
|
input.configuredMaxWorkersOverride
|
|
1391
1665
|
);
|
|
1392
|
-
const totalMemBytes = input.totalMemBytes ??
|
|
1666
|
+
const totalMemBytes = input.totalMemBytes ?? os2.totalmem();
|
|
1393
1667
|
const freeMemBytes = input.freeMemBytes ?? readAvailableMemBytes();
|
|
1394
1668
|
const activeWorkers = input.activeWorkers ?? countActiveWorkersGlobal();
|
|
1395
1669
|
const budgetBytes = Math.max(0, Math.floor(totalMemBytes * memUtilization) - memReserveBytes);
|
|
@@ -1598,7 +1872,7 @@ var claudeProvider = {
|
|
|
1598
1872
|
cwd: opts.worktreePath,
|
|
1599
1873
|
detached: true,
|
|
1600
1874
|
stdio,
|
|
1601
|
-
env:
|
|
1875
|
+
env: scrubWorkerEnv(process.env)
|
|
1602
1876
|
})
|
|
1603
1877
|
);
|
|
1604
1878
|
closeSync(stdoutFd);
|
|
@@ -1985,12 +2259,12 @@ function resolveAgentBin() {
|
|
|
1985
2259
|
return "agent";
|
|
1986
2260
|
}
|
|
1987
2261
|
function cursorWorkerEnv(agentBin, spawnTarget) {
|
|
1988
|
-
return {
|
|
2262
|
+
return scrubWorkerEnv({
|
|
1989
2263
|
...process.env,
|
|
1990
2264
|
CI: "1",
|
|
1991
2265
|
NO_COLOR: "1",
|
|
1992
2266
|
...spawnTarget.bundledVersionDir ? { CURSOR_INVOKED_AS: path9.basename(agentBin) || "agent.cmd" } : {}
|
|
1993
|
-
};
|
|
2267
|
+
});
|
|
1994
2268
|
}
|
|
1995
2269
|
var cursorProvider = {
|
|
1996
2270
|
name: "cursor",
|
|
@@ -2083,6 +2357,39 @@ function persistCompletionAck(worker, runId, fields) {
|
|
|
2083
2357
|
// src/worker-ops.ts
|
|
2084
2358
|
import path11 from "node:path";
|
|
2085
2359
|
|
|
2360
|
+
// src/completion-response.ts
|
|
2361
|
+
function asRecord(value) {
|
|
2362
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
2363
|
+
}
|
|
2364
|
+
function asString(value) {
|
|
2365
|
+
if (typeof value !== "string") return null;
|
|
2366
|
+
const trimmed = value.trim();
|
|
2367
|
+
return trimmed.length ? trimmed : null;
|
|
2368
|
+
}
|
|
2369
|
+
var ADVANCED_OUTCOMES = /* @__PURE__ */ new Set([
|
|
2370
|
+
"review_scheduled",
|
|
2371
|
+
"review_already_scheduled"
|
|
2372
|
+
]);
|
|
2373
|
+
function summarizeHarnessCompletionResponse(parsed) {
|
|
2374
|
+
const record = asRecord(parsed);
|
|
2375
|
+
if (!record) {
|
|
2376
|
+
return { routeOutcome: null, taskAdvanced: false, detail: null };
|
|
2377
|
+
}
|
|
2378
|
+
const outcome = asString(record.outcome);
|
|
2379
|
+
const detail = asString(record.detail) ?? asString(record.error);
|
|
2380
|
+
const task = asRecord(record.task);
|
|
2381
|
+
const taskStatus = task ? asString(task.status) : null;
|
|
2382
|
+
const taskAdvanced = outcome !== null && ADVANCED_OUTCOMES.has(outcome) || taskStatus === "awaiting_review" || taskStatus === "done";
|
|
2383
|
+
return {
|
|
2384
|
+
routeOutcome: outcome,
|
|
2385
|
+
taskAdvanced,
|
|
2386
|
+
detail
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
2389
|
+
function completionPostSucceeded(summary) {
|
|
2390
|
+
return summary.taskAdvanced;
|
|
2391
|
+
}
|
|
2392
|
+
|
|
2086
2393
|
// src/pr-handoff/pr-handoff-assess.ts
|
|
2087
2394
|
var REVIEW_LANE_RULE = /^(lane:)?(review|deep_review|planning|landing)(:|$)/i;
|
|
2088
2395
|
function trimOrNull4(value) {
|
|
@@ -2143,6 +2450,36 @@ function buildPrHandoffSnapshotFromStatus(status, extras) {
|
|
|
2143
2450
|
|
|
2144
2451
|
// src/pr-handoff/pr-handoff-gh.ts
|
|
2145
2452
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
2453
|
+
|
|
2454
|
+
// src/github-repo.ts
|
|
2455
|
+
function parseGithubOwnerRepo(remoteUrl) {
|
|
2456
|
+
const trimmed = remoteUrl.trim();
|
|
2457
|
+
if (!trimmed) return null;
|
|
2458
|
+
const ssh = trimmed.match(/^git@github\.com:([^/]+\/[^/\s]+?)(?:\.git)?$/i);
|
|
2459
|
+
if (ssh) return normalizeOwnerRepo(ssh[1]);
|
|
2460
|
+
const scp = trimmed.match(/^ssh:\/\/git@github\.com\/([^/]+\/[^/\s]+?)(?:\.git)?$/i);
|
|
2461
|
+
if (scp) return normalizeOwnerRepo(scp[1]);
|
|
2462
|
+
try {
|
|
2463
|
+
const url = new URL(trimmed.includes("://") ? trimmed : `https://${trimmed}`);
|
|
2464
|
+
if (url.hostname.toLowerCase() !== "github.com") return null;
|
|
2465
|
+
const parts = url.pathname.replace(/^\/+|\/+$/g, "").split("/");
|
|
2466
|
+
if (parts.length < 2) return null;
|
|
2467
|
+
const [owner, repo] = parts;
|
|
2468
|
+
if (!owner || !repo) return null;
|
|
2469
|
+
return `${owner}/${repo.replace(/\.git$/i, "")}`;
|
|
2470
|
+
} catch {
|
|
2471
|
+
return null;
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
function normalizeOwnerRepo(value) {
|
|
2475
|
+
const parts = value.split("/").filter(Boolean);
|
|
2476
|
+
if (parts.length < 2) return null;
|
|
2477
|
+
const owner = parts[0];
|
|
2478
|
+
const repo = parts[1].replace(/\.git$/i, "");
|
|
2479
|
+
return owner && repo ? `${owner}/${repo}` : null;
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2482
|
+
// src/pr-handoff/pr-handoff-gh.ts
|
|
2146
2483
|
function capture(bin, cwd, args) {
|
|
2147
2484
|
try {
|
|
2148
2485
|
const res = spawnSync2(bin, args, { cwd, encoding: "utf8" });
|
|
@@ -2165,21 +2502,13 @@ var defaultPrHandoffExec = {
|
|
|
2165
2502
|
git: (cwd, args) => gitCapture(cwd, args),
|
|
2166
2503
|
gh: (cwd, args) => capture("gh", cwd, args)
|
|
2167
2504
|
};
|
|
2168
|
-
function parseGithubRepo(remoteUrl) {
|
|
2169
|
-
const trimmed = remoteUrl.trim();
|
|
2170
|
-
const ssh = trimmed.match(/git@github\.com:([^/]+\/[^/.]+)(?:\.git)?/i);
|
|
2171
|
-
if (ssh) return ssh[1];
|
|
2172
|
-
const https = trimmed.match(/github\.com[/:]([^/]+\/[^/.]+?)(?:\.git)?/i);
|
|
2173
|
-
if (https) return https[1];
|
|
2174
|
-
return null;
|
|
2175
|
-
}
|
|
2176
2505
|
function firstLine(text) {
|
|
2177
2506
|
return text.split("\n").map((l) => l.trim()).find(Boolean) ?? "";
|
|
2178
2507
|
}
|
|
2179
2508
|
function resolveGithubRepo(worktreePath, exec) {
|
|
2180
2509
|
const remote = exec.git(worktreePath, ["remote", "get-url", "origin"]);
|
|
2181
2510
|
if (remote.status !== 0) return null;
|
|
2182
|
-
return
|
|
2511
|
+
return parseGithubOwnerRepo(remote.stdout);
|
|
2183
2512
|
}
|
|
2184
2513
|
function resolveHeadCommit(worktreePath, exec) {
|
|
2185
2514
|
const head = exec.git(worktreePath, ["rev-parse", "HEAD"]);
|
|
@@ -2513,10 +2842,10 @@ function completionErrorText(parsed) {
|
|
|
2513
2842
|
}
|
|
2514
2843
|
return void 0;
|
|
2515
2844
|
}
|
|
2516
|
-
function
|
|
2845
|
+
function asRecord2(value) {
|
|
2517
2846
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
2518
2847
|
}
|
|
2519
|
-
function
|
|
2848
|
+
function asString2(value) {
|
|
2520
2849
|
if (typeof value !== "string") return null;
|
|
2521
2850
|
const trimmed = value.trim();
|
|
2522
2851
|
return trimmed.length ? trimmed : null;
|
|
@@ -2636,7 +2965,27 @@ async function tryCompleteWorker(args) {
|
|
|
2636
2965
|
}
|
|
2637
2966
|
}
|
|
2638
2967
|
if (result.ok) {
|
|
2968
|
+
const summary = summarizeHarnessCompletionResponse(result.parsed);
|
|
2969
|
+
if (!completionPostSucceeded(summary)) {
|
|
2970
|
+
const detail2 = summary.detail ?? (summary.routeOutcome ? `harness completion returned ${summary.routeOutcome}` : "harness completion did not advance the linked task");
|
|
2971
|
+
const reason2 = `completion acknowledged but board not advanced: ${detail2}`;
|
|
2972
|
+
persistCompletionBlocker(worker, reason2);
|
|
2973
|
+
const ack2 = {
|
|
2974
|
+
completionReportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2975
|
+
completionOutcome: "rejected",
|
|
2976
|
+
completionResponse: result.parsed
|
|
2977
|
+
};
|
|
2978
|
+
persistCompletionAck(worker, worker.runId, ack2);
|
|
2979
|
+
return {
|
|
2980
|
+
ok: false,
|
|
2981
|
+
httpStatus: result.status,
|
|
2982
|
+
response: result.parsed,
|
|
2983
|
+
reason: reason2,
|
|
2984
|
+
completionBlocked: true
|
|
2985
|
+
};
|
|
2986
|
+
}
|
|
2639
2987
|
persistCompletionBlocker(worker, void 0);
|
|
2988
|
+
const routeOutcome = summary.routeOutcome ?? "acknowledged";
|
|
2640
2989
|
const ack = {
|
|
2641
2990
|
completionReportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2642
2991
|
completionOutcome: "acknowledged",
|
|
@@ -2649,6 +2998,7 @@ async function tryCompleteWorker(args) {
|
|
|
2649
2998
|
ok: true,
|
|
2650
2999
|
httpStatus: result.status,
|
|
2651
3000
|
response: result.parsed,
|
|
3001
|
+
reason: routeOutcome,
|
|
2652
3002
|
...prUrl ? { prHandoff: { prUrl } } : {}
|
|
2653
3003
|
};
|
|
2654
3004
|
}
|
|
@@ -2741,13 +3091,13 @@ function buildRunBoard(runId) {
|
|
|
2741
3091
|
const completionBlocker = typeof rawBlocker === "string" && rawBlocker ? rawBlocker : void 0;
|
|
2742
3092
|
const boardStatus = completionBlocker ? "blocked" : status.status;
|
|
2743
3093
|
const boardAttention = completionBlocker ? "blocked" : status.attention.state;
|
|
2744
|
-
const completionResponse =
|
|
2745
|
-
const completionTask =
|
|
2746
|
-
const completionOutcome =
|
|
2747
|
-
const completionRouteStatus =
|
|
3094
|
+
const completionResponse = asRecord2(worker.completionResponse);
|
|
3095
|
+
const completionTask = asRecord2(completionResponse?.task);
|
|
3096
|
+
const completionOutcome = asString2(completionResponse?.outcome);
|
|
3097
|
+
const completionRouteStatus = asString2(completionResponse?.status);
|
|
2748
3098
|
const completionWarnings = Array.isArray(completionResponse?.warnings) ? completionResponse.warnings.filter((w) => typeof w === "string" && w.trim().length > 0) : [];
|
|
2749
|
-
const prUrl =
|
|
2750
|
-
const completionReportedAt =
|
|
3099
|
+
const prUrl = asString2(completionTask?.prUrl) ?? asString2(completionResponse?.prUrl);
|
|
3100
|
+
const completionReportedAt = asString2(worker.completionReportedAt);
|
|
2751
3101
|
const lifecycleStage = deriveLifecycleStage({
|
|
2752
3102
|
finished: isFinishedWorkerStatus(status),
|
|
2753
3103
|
completionBlocker,
|
|
@@ -3938,7 +4288,8 @@ async function dispatchRun(args) {
|
|
|
3938
4288
|
harnessBoardSnapshot: buildRunBoard(run.id),
|
|
3939
4289
|
...args.lane ? { lane: String(args.lane) } : {},
|
|
3940
4290
|
executor: args.executor ? String(args.executor) : "harness",
|
|
3941
|
-
...args.diskPath ? { diskPath: String(args.diskPath) } : {}
|
|
4291
|
+
...args.diskPath ? { diskPath: String(args.diskPath) } : {},
|
|
4292
|
+
...args.targetTaskId ? { targetTaskId: String(args.targetTaskId) } : {}
|
|
3942
4293
|
};
|
|
3943
4294
|
const dispatch = await postJsonWithCredentialRefresh(dispatchUrl, secret, body, { agentOsId, baseUrl: base });
|
|
3944
4295
|
const responseBody = dispatch.response;
|
|
@@ -4117,6 +4468,13 @@ async function dispatchRun(args) {
|
|
|
4117
4468
|
}
|
|
4118
4469
|
}
|
|
4119
4470
|
|
|
4471
|
+
// src/fortress-engagement-gate.ts
|
|
4472
|
+
function isEngagementRequiredSkip(skip) {
|
|
4473
|
+
if (skip.skipReason === "engagement_required") return true;
|
|
4474
|
+
const reason = skip.reason ?? "";
|
|
4475
|
+
return reason.includes("engagement_required") || reason.includes("engagement_not_found") || reason.includes("engagement_expired") || reason.includes("engagement_revoked");
|
|
4476
|
+
}
|
|
4477
|
+
|
|
4120
4478
|
// src/redact.ts
|
|
4121
4479
|
function redactHarness(text, secret) {
|
|
4122
4480
|
let out = text;
|
|
@@ -4262,7 +4620,7 @@ import { mkdirSync as mkdirSync7, realpathSync } from "node:fs";
|
|
|
4262
4620
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
4263
4621
|
|
|
4264
4622
|
// src/pipeline-tick.ts
|
|
4265
|
-
import
|
|
4623
|
+
import path30 from "node:path";
|
|
4266
4624
|
|
|
4267
4625
|
// src/pipeline-dispatch.ts
|
|
4268
4626
|
var RESERVED_REVIEW_STARTS = 1;
|
|
@@ -4968,13 +5326,62 @@ function isPipelineCleanupEnabled() {
|
|
|
4968
5326
|
return process.env.KYNVER_PIPELINE_CLEANUP !== "0";
|
|
4969
5327
|
}
|
|
4970
5328
|
|
|
5329
|
+
// src/installed-package-versions.ts
|
|
5330
|
+
import { readFile } from "node:fs/promises";
|
|
5331
|
+
import { homedir as homedir5 } from "node:os";
|
|
5332
|
+
import path29 from "node:path";
|
|
5333
|
+
var MANAGED_PACKAGES = [
|
|
5334
|
+
"@kynver-app/runtime",
|
|
5335
|
+
"@kynver-app/openclaw-agent-os",
|
|
5336
|
+
"@kynver-app/mcp-agent-os"
|
|
5337
|
+
];
|
|
5338
|
+
function trim(value) {
|
|
5339
|
+
const out = value?.trim();
|
|
5340
|
+
return out ? out : null;
|
|
5341
|
+
}
|
|
5342
|
+
function unique(values) {
|
|
5343
|
+
return [...new Set(values.filter((value) => Boolean(value)))];
|
|
5344
|
+
}
|
|
5345
|
+
function moduleRoots() {
|
|
5346
|
+
const home = homedir5();
|
|
5347
|
+
const openClawPrefix = trim(process.env.KYNVER_OPENCLAW_NPM_ROOT) ?? trim(process.env.OPENCLAW_NPM_ROOT) ?? path29.join(home, ".openclaw", "npm");
|
|
5348
|
+
const npmGlobalRoot = trim(process.env.KYNVER_NPM_GLOBAL_ROOT) ?? trim(process.env.KYNVER_NPM_GLOBAL_MODULES_ROOT) ?? (trim(process.env.NPM_CONFIG_PREFIX) ? path29.join(trim(process.env.NPM_CONFIG_PREFIX), "lib", "node_modules") : path29.join(home, ".npm-global", "lib", "node_modules"));
|
|
5349
|
+
return unique([
|
|
5350
|
+
path29.join(openClawPrefix, "lib", "node_modules"),
|
|
5351
|
+
path29.join(openClawPrefix, "node_modules"),
|
|
5352
|
+
npmGlobalRoot.endsWith("node_modules") ? npmGlobalRoot : path29.join(npmGlobalRoot, "lib", "node_modules")
|
|
5353
|
+
]);
|
|
5354
|
+
}
|
|
5355
|
+
async function readVersion(packageJsonPath) {
|
|
5356
|
+
try {
|
|
5357
|
+
const parsed = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
5358
|
+
return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
|
|
5359
|
+
} catch {
|
|
5360
|
+
return null;
|
|
5361
|
+
}
|
|
5362
|
+
}
|
|
5363
|
+
async function collectInstalledPackageVersions(observedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
5364
|
+
const roots = moduleRoots();
|
|
5365
|
+
const out = {};
|
|
5366
|
+
for (const packageName of MANAGED_PACKAGES) {
|
|
5367
|
+
for (const root of roots) {
|
|
5368
|
+
const packageJsonPath = path29.join(root, packageName, "package.json");
|
|
5369
|
+
const version = await readVersion(packageJsonPath);
|
|
5370
|
+
if (!version) continue;
|
|
5371
|
+
out[packageName] = { version, observedAt, path: packageJsonPath };
|
|
5372
|
+
break;
|
|
5373
|
+
}
|
|
5374
|
+
}
|
|
5375
|
+
return out;
|
|
5376
|
+
}
|
|
5377
|
+
|
|
4971
5378
|
// src/pipeline-tick.ts
|
|
4972
5379
|
async function completeFinishedWorkers(runId, args) {
|
|
4973
5380
|
const run = loadRun(runId);
|
|
4974
5381
|
const outcomes = [];
|
|
4975
5382
|
for (const name of Object.keys(run.workers || {})) {
|
|
4976
5383
|
const worker = readJson(
|
|
4977
|
-
|
|
5384
|
+
path30.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
4978
5385
|
void 0
|
|
4979
5386
|
);
|
|
4980
5387
|
if (!worker?.taskId || worker.localOnly) continue;
|
|
@@ -5005,12 +5412,14 @@ async function postOperatorTick(agentOsId, runId, resourceGate, args) {
|
|
|
5005
5412
|
const base = resolveBaseUrl(args.baseUrl ? String(args.baseUrl) : void 0);
|
|
5006
5413
|
const secret = await resolveCallbackSecretWithMint(args.secret ? String(args.secret) : void 0, agentOsId, { baseUrl: base });
|
|
5007
5414
|
const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/operator/tick`;
|
|
5415
|
+
const packageVersions = await collectInstalledPackageVersions();
|
|
5008
5416
|
const res = await postJson(url, secret, {
|
|
5009
5417
|
agentOsId,
|
|
5010
5418
|
runId,
|
|
5011
5419
|
ingestHarness: true,
|
|
5012
5420
|
harnessBoardSnapshot: buildRunBoard(runId),
|
|
5013
|
-
resourceGate
|
|
5421
|
+
resourceGate,
|
|
5422
|
+
packageVersions
|
|
5014
5423
|
});
|
|
5015
5424
|
return { ok: res.ok, httpStatus: res.status, response: res.response };
|
|
5016
5425
|
}
|
|
@@ -5113,6 +5522,231 @@ async function runDaemon(args) {
|
|
|
5113
5522
|
console.error(JSON.stringify({ event: "daemon_stop", runId, agentOsId }));
|
|
5114
5523
|
}
|
|
5115
5524
|
|
|
5525
|
+
// src/plan-progress.ts
|
|
5526
|
+
import path31 from "node:path";
|
|
5527
|
+
|
|
5528
|
+
// src/bounded-build/constants.ts
|
|
5529
|
+
var DEFAULT_BUILD_MEM_BUDGET_BYTES = 1536 * 1024 * 1024;
|
|
5530
|
+
var DEFAULT_BUILD_MEM_RESERVE_BYTES = 2 * 1024 * 1024 * 1024;
|
|
5531
|
+
var DEFAULT_NODE_OLD_SPACE_SIZE_MB = 1024;
|
|
5532
|
+
var DEFAULT_SYSTEMD_MEMORY_MAX = "1.5G";
|
|
5533
|
+
var DEFAULT_SYSTEMD_MEMORY_SWAP_MAX = "2G";
|
|
5534
|
+
|
|
5535
|
+
// src/bounded-build/node-options.ts
|
|
5536
|
+
var MAX_OLD_SPACE_RE = /--max-old-space-size=(\d+)/;
|
|
5537
|
+
function parsePositiveInt(value, fallback) {
|
|
5538
|
+
const n = Number(value);
|
|
5539
|
+
if (!Number.isFinite(n) || n <= 0) return fallback;
|
|
5540
|
+
return Math.floor(n);
|
|
5541
|
+
}
|
|
5542
|
+
function resolveNodeOldSpaceSizeMb() {
|
|
5543
|
+
return parsePositiveInt(process.env.KYNVER_NODE_OLD_SPACE_SIZE_MB, DEFAULT_NODE_OLD_SPACE_SIZE_MB);
|
|
5544
|
+
}
|
|
5545
|
+
function mergeNodeOptionsForBuildCheck(baseEnv = process.env) {
|
|
5546
|
+
const env = { ...baseEnv };
|
|
5547
|
+
if (process.env.KYNVER_NODE_OLD_SPACE_SIZE_MB === "0") {
|
|
5548
|
+
return env;
|
|
5549
|
+
}
|
|
5550
|
+
const existing = env.NODE_OPTIONS ?? "";
|
|
5551
|
+
if (MAX_OLD_SPACE_RE.test(existing)) {
|
|
5552
|
+
return env;
|
|
5553
|
+
}
|
|
5554
|
+
const mb = resolveNodeOldSpaceSizeMb();
|
|
5555
|
+
const flag = `--max-old-space-size=${mb}`;
|
|
5556
|
+
env.NODE_OPTIONS = existing.trim() ? `${existing.trim()} ${flag}` : flag;
|
|
5557
|
+
return env;
|
|
5558
|
+
}
|
|
5559
|
+
function formatNodeOptionsFlag(mb = resolveNodeOldSpaceSizeMb()) {
|
|
5560
|
+
return `--max-old-space-size=${mb}`;
|
|
5561
|
+
}
|
|
5562
|
+
|
|
5563
|
+
// src/bounded-build/systemd-wrap.ts
|
|
5564
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
5565
|
+
var systemdAvailableCache;
|
|
5566
|
+
function isSystemdRunAvailable() {
|
|
5567
|
+
if (process.env.KYNVER_BUILD_SKIP_SYSTEMD === "1" || process.env.KYNVER_BUILD_SKIP_SYSTEMD === "true") {
|
|
5568
|
+
return false;
|
|
5569
|
+
}
|
|
5570
|
+
if (systemdAvailableCache !== void 0) return systemdAvailableCache;
|
|
5571
|
+
if (process.platform !== "linux") {
|
|
5572
|
+
systemdAvailableCache = false;
|
|
5573
|
+
return false;
|
|
5574
|
+
}
|
|
5575
|
+
const res = spawnSync3("systemd-run", ["--version"], { encoding: "utf8", stdio: ["ignore", "ignore", "pipe"] });
|
|
5576
|
+
systemdAvailableCache = res.status === 0;
|
|
5577
|
+
return systemdAvailableCache;
|
|
5578
|
+
}
|
|
5579
|
+
function buildSystemdRunArgv(opts) {
|
|
5580
|
+
const memoryMax = opts.memoryMax ?? process.env.KYNVER_BUILD_SYSTEMD_MEMORY_MAX ?? DEFAULT_SYSTEMD_MEMORY_MAX;
|
|
5581
|
+
const memorySwapMax = opts.memorySwapMax ?? process.env.KYNVER_BUILD_SYSTEMD_MEMORY_SWAP_MAX ?? DEFAULT_SYSTEMD_MEMORY_SWAP_MAX;
|
|
5582
|
+
const argv = [
|
|
5583
|
+
"systemd-run",
|
|
5584
|
+
"--scope",
|
|
5585
|
+
"--collect",
|
|
5586
|
+
"-p",
|
|
5587
|
+
`MemoryMax=${memoryMax}`,
|
|
5588
|
+
"-p",
|
|
5589
|
+
`MemorySwapMax=${memorySwapMax}`
|
|
5590
|
+
];
|
|
5591
|
+
if (opts.cwd) {
|
|
5592
|
+
argv.push("--working-directory", opts.cwd);
|
|
5593
|
+
}
|
|
5594
|
+
argv.push("--", ...opts.command);
|
|
5595
|
+
return argv;
|
|
5596
|
+
}
|
|
5597
|
+
|
|
5598
|
+
// src/bounded-build/admission.ts
|
|
5599
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
5600
|
+
function positiveInt3(value, fallback) {
|
|
5601
|
+
const n = Number(value);
|
|
5602
|
+
if (!Number.isFinite(n) || n <= 0) return fallback;
|
|
5603
|
+
return Math.floor(n);
|
|
5604
|
+
}
|
|
5605
|
+
function resolveBuildAdmissionConfig(config = loadUserConfig()) {
|
|
5606
|
+
const envBudget = process.env.KYNVER_BUILD_MEM_BUDGET_BYTES ? positiveInt3(process.env.KYNVER_BUILD_MEM_BUDGET_BYTES, DEFAULT_BUILD_MEM_BUDGET_BYTES) : void 0;
|
|
5607
|
+
const envReserve = process.env.KYNVER_BUILD_MEM_RESERVE_BYTES ? positiveInt3(process.env.KYNVER_BUILD_MEM_RESERVE_BYTES, DEFAULT_BUILD_MEM_RESERVE_BYTES) : void 0;
|
|
5608
|
+
return {
|
|
5609
|
+
perBuildBudgetBytes: envBudget ?? positiveInt3(config.perWorkerMemBytes, DEFAULT_BUILD_MEM_BUDGET_BYTES),
|
|
5610
|
+
reserveBytes: envReserve ?? positiveInt3(config.memReserveBytes, DEFAULT_BUILD_MEM_RESERVE_BYTES)
|
|
5611
|
+
};
|
|
5612
|
+
}
|
|
5613
|
+
var activeBuilds = 0;
|
|
5614
|
+
function registerBuildStart() {
|
|
5615
|
+
activeBuilds += 1;
|
|
5616
|
+
}
|
|
5617
|
+
function registerBuildEnd() {
|
|
5618
|
+
activeBuilds = Math.max(0, activeBuilds - 1);
|
|
5619
|
+
}
|
|
5620
|
+
function assessBuildAdmission(opts = {}) {
|
|
5621
|
+
const cfg = { ...resolveBuildAdmissionConfig(), ...opts };
|
|
5622
|
+
const memAvailableBytes = opts.memAvailableBytes ?? readMemAvailableBytes();
|
|
5623
|
+
const requiredBytes = cfg.perBuildBudgetBytes + cfg.reserveBytes;
|
|
5624
|
+
const admitted = memAvailableBytes >= requiredBytes;
|
|
5625
|
+
return {
|
|
5626
|
+
admitted,
|
|
5627
|
+
memAvailableBytes,
|
|
5628
|
+
requiredBytes,
|
|
5629
|
+
activeBuilds,
|
|
5630
|
+
reason: admitted ? null : `insufficient memory: need ${requiredBytes} bytes available (budget ${cfg.perBuildBudgetBytes} + reserve ${cfg.reserveBytes}), have ${memAvailableBytes}`
|
|
5631
|
+
};
|
|
5632
|
+
}
|
|
5633
|
+
function sleepMs2(ms) {
|
|
5634
|
+
if (ms <= 0) return;
|
|
5635
|
+
spawnSync4(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
|
|
5636
|
+
stdio: "ignore"
|
|
5637
|
+
});
|
|
5638
|
+
}
|
|
5639
|
+
function waitForBuildAdmission(timeoutMs, pollMs = 2e3, opts = {}) {
|
|
5640
|
+
const deadline = Date.now() + Math.max(0, timeoutMs);
|
|
5641
|
+
let verdict = assessBuildAdmission({
|
|
5642
|
+
...opts,
|
|
5643
|
+
memAvailableBytes: opts.memAvailableBytes?.()
|
|
5644
|
+
});
|
|
5645
|
+
while (!verdict.admitted && Date.now() < deadline) {
|
|
5646
|
+
sleepMs2(Math.min(pollMs, deadline - Date.now()));
|
|
5647
|
+
verdict = assessBuildAdmission({
|
|
5648
|
+
...opts,
|
|
5649
|
+
memAvailableBytes: opts.memAvailableBytes?.()
|
|
5650
|
+
});
|
|
5651
|
+
}
|
|
5652
|
+
return verdict;
|
|
5653
|
+
}
|
|
5654
|
+
|
|
5655
|
+
// src/bounded-build/exec.ts
|
|
5656
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
5657
|
+
function envArgv(env) {
|
|
5658
|
+
const out = [];
|
|
5659
|
+
for (const [key, value] of Object.entries(env)) {
|
|
5660
|
+
if (value === void 0) continue;
|
|
5661
|
+
out.push(`${key}=${value}`);
|
|
5662
|
+
}
|
|
5663
|
+
return out;
|
|
5664
|
+
}
|
|
5665
|
+
function runSpawn(argv, opts) {
|
|
5666
|
+
const res = spawnSync5(argv[0], argv.slice(1), {
|
|
5667
|
+
cwd: opts.cwd,
|
|
5668
|
+
env: opts.env,
|
|
5669
|
+
encoding: "utf8",
|
|
5670
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
5671
|
+
shell: opts.shell,
|
|
5672
|
+
timeout: opts.timeoutMs
|
|
5673
|
+
});
|
|
5674
|
+
return {
|
|
5675
|
+
exitCode: res.status ?? 1,
|
|
5676
|
+
stdout: (res.stdout ?? "").trim(),
|
|
5677
|
+
stderr: (res.stderr ?? "").trim()
|
|
5678
|
+
};
|
|
5679
|
+
}
|
|
5680
|
+
function runBoundedBuildCheck(input) {
|
|
5681
|
+
const waitMs = input.waitForAdmissionMs ?? 6e5;
|
|
5682
|
+
const admission = waitMs > 0 ? waitForBuildAdmission(waitMs) : assessBuildAdmission();
|
|
5683
|
+
if (!admission.admitted) {
|
|
5684
|
+
return {
|
|
5685
|
+
ok: false,
|
|
5686
|
+
exitCode: 1,
|
|
5687
|
+
stdout: "",
|
|
5688
|
+
stderr: admission.reason ?? "build admission denied",
|
|
5689
|
+
admitted: false,
|
|
5690
|
+
wrappedWithSystemd: false,
|
|
5691
|
+
nodeOptionsFlag: formatNodeOptionsFlag(),
|
|
5692
|
+
admission,
|
|
5693
|
+
command: input.command
|
|
5694
|
+
};
|
|
5695
|
+
}
|
|
5696
|
+
const env = mergeNodeOptionsForBuildCheck({ ...process.env, ...input.env });
|
|
5697
|
+
const nodeOptionsFlag = formatNodeOptionsFlag();
|
|
5698
|
+
const useSystemd = isSystemdRunAvailable();
|
|
5699
|
+
registerBuildStart();
|
|
5700
|
+
try {
|
|
5701
|
+
let result;
|
|
5702
|
+
if (useSystemd) {
|
|
5703
|
+
const argv = buildSystemdRunArgv({
|
|
5704
|
+
cwd: input.cwd,
|
|
5705
|
+
command: ["/usr/bin/env", ...envArgv(env), "/bin/bash", "-lc", input.command]
|
|
5706
|
+
});
|
|
5707
|
+
result = runSpawn(argv, { cwd: input.cwd, env, timeoutMs: input.timeoutMs });
|
|
5708
|
+
} else {
|
|
5709
|
+
result = runSpawn([input.command], {
|
|
5710
|
+
cwd: input.cwd,
|
|
5711
|
+
env,
|
|
5712
|
+
shell: true,
|
|
5713
|
+
timeoutMs: input.timeoutMs
|
|
5714
|
+
});
|
|
5715
|
+
}
|
|
5716
|
+
return {
|
|
5717
|
+
ok: result.exitCode === 0,
|
|
5718
|
+
exitCode: result.exitCode,
|
|
5719
|
+
stdout: result.stdout,
|
|
5720
|
+
stderr: result.stderr,
|
|
5721
|
+
admitted: true,
|
|
5722
|
+
wrappedWithSystemd: useSystemd,
|
|
5723
|
+
nodeOptionsFlag,
|
|
5724
|
+
admission,
|
|
5725
|
+
command: input.command
|
|
5726
|
+
};
|
|
5727
|
+
} finally {
|
|
5728
|
+
registerBuildEnd();
|
|
5729
|
+
}
|
|
5730
|
+
}
|
|
5731
|
+
|
|
5732
|
+
// src/harness-verify.ts
|
|
5733
|
+
var DEFAULT_HARNESS_VERIFY_COMMANDS = ["npm run typecheck", "npm run test"];
|
|
5734
|
+
function runHarnessVerifyCommands(cwd, commands = DEFAULT_HARNESS_VERIFY_COMMANDS, opts = {}) {
|
|
5735
|
+
const steps = [];
|
|
5736
|
+
let passed = true;
|
|
5737
|
+
for (const command of commands) {
|
|
5738
|
+
const result = runBoundedBuildCheck({
|
|
5739
|
+
cwd,
|
|
5740
|
+
command,
|
|
5741
|
+
waitForAdmissionMs: opts.waitForAdmissionMs,
|
|
5742
|
+
timeoutMs: opts.timeoutMs
|
|
5743
|
+
});
|
|
5744
|
+
steps.push({ command, result });
|
|
5745
|
+
if (!result.ok) passed = false;
|
|
5746
|
+
}
|
|
5747
|
+
return { passed, steps };
|
|
5748
|
+
}
|
|
5749
|
+
|
|
5116
5750
|
// src/plan-progress.ts
|
|
5117
5751
|
function parseEvidenceArg(raw) {
|
|
5118
5752
|
const idx = raw.indexOf(":");
|
|
@@ -5173,8 +5807,23 @@ async function emitPlanProgress(args) {
|
|
|
5173
5807
|
}
|
|
5174
5808
|
console.log(JSON.stringify(parsed, null, 2));
|
|
5175
5809
|
}
|
|
5810
|
+
function verifyPlanLocal(args) {
|
|
5811
|
+
const worktree = required(args.worktree ? String(args.worktree) : void 0, "worktree");
|
|
5812
|
+
const cwd = path31.resolve(worktree);
|
|
5813
|
+
const summary = runHarnessVerifyCommands(cwd);
|
|
5814
|
+
const emitJson = args.json === true || args.json === "true";
|
|
5815
|
+
const payload = { passed: summary.passed, worktree: cwd, steps: summary.steps };
|
|
5816
|
+
if (emitJson) console.log(JSON.stringify(payload, null, 2));
|
|
5817
|
+
else console.log(summary.passed ? "local plan verify passed" : "local plan verify failed");
|
|
5818
|
+
if (!summary.passed) process.exit(1);
|
|
5819
|
+
}
|
|
5176
5820
|
async function verifyPlan(args) {
|
|
5177
5821
|
const planId = required(args.plan ? String(args.plan) : void 0, "plan");
|
|
5822
|
+
const localOnly = args.local === true || args.local === "true";
|
|
5823
|
+
if (localOnly) {
|
|
5824
|
+
verifyPlanLocal(args);
|
|
5825
|
+
return;
|
|
5826
|
+
}
|
|
5178
5827
|
const slug = loadUserConfig().agentOsSlug;
|
|
5179
5828
|
if (!slug) {
|
|
5180
5829
|
console.error("requires agentOsSlug in ~/.kynver/config.json for verify (session route)");
|
|
@@ -5208,6 +5857,52 @@ async function verifyPlan(args) {
|
|
|
5208
5857
|
console.log(JSON.stringify(parsed, null, 2));
|
|
5209
5858
|
}
|
|
5210
5859
|
|
|
5860
|
+
// src/harness-verify-cli.ts
|
|
5861
|
+
import path32 from "node:path";
|
|
5862
|
+
function runHarnessVerifyCli(args) {
|
|
5863
|
+
const cwd = path32.resolve(required(args.worktree ? String(args.worktree) : void 0, "worktree"));
|
|
5864
|
+
const emitJson = args.json === true || args.json === "true" || args.emitJson === true || args.emitJson === "true";
|
|
5865
|
+
const commands = [];
|
|
5866
|
+
const rawCmd = args.command;
|
|
5867
|
+
if (Array.isArray(rawCmd)) {
|
|
5868
|
+
for (const c of rawCmd) commands.push(String(c));
|
|
5869
|
+
} else if (typeof rawCmd === "string") {
|
|
5870
|
+
commands.push(rawCmd);
|
|
5871
|
+
}
|
|
5872
|
+
const summary = runHarnessVerifyCommands(
|
|
5873
|
+
cwd,
|
|
5874
|
+
commands.length ? commands : DEFAULT_HARNESS_VERIFY_COMMANDS,
|
|
5875
|
+
{
|
|
5876
|
+
waitForAdmissionMs: args.waitForAdmissionMs ? Number(args.waitForAdmissionMs) : void 0,
|
|
5877
|
+
timeoutMs: args.timeoutMs ? Number(args.timeoutMs) : void 0
|
|
5878
|
+
}
|
|
5879
|
+
);
|
|
5880
|
+
const payload = {
|
|
5881
|
+
passed: summary.passed,
|
|
5882
|
+
worktree: cwd,
|
|
5883
|
+
steps: summary.steps.map((s) => ({
|
|
5884
|
+
command: s.command,
|
|
5885
|
+
ok: s.result.ok,
|
|
5886
|
+
exitCode: s.result.exitCode,
|
|
5887
|
+
admitted: s.result.admitted,
|
|
5888
|
+
wrappedWithSystemd: s.result.wrappedWithSystemd,
|
|
5889
|
+
nodeOptionsFlag: s.result.nodeOptionsFlag,
|
|
5890
|
+
admission: s.result.admission,
|
|
5891
|
+
stderr: s.result.stderr.slice(0, 4e3)
|
|
5892
|
+
}))
|
|
5893
|
+
};
|
|
5894
|
+
if (emitJson) {
|
|
5895
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
5896
|
+
} else {
|
|
5897
|
+
console.log(summary.passed ? "harness verify passed" : "harness verify failed");
|
|
5898
|
+
for (const step of payload.steps) {
|
|
5899
|
+
console.log(` ${step.ok ? "\u2713" : "\u2717"} ${step.command} (exit ${step.exitCode}, systemd=${step.wrappedWithSystemd})`);
|
|
5900
|
+
if (!step.ok && step.stderr) console.log(` ${step.stderr.split("\n")[0]}`);
|
|
5901
|
+
}
|
|
5902
|
+
}
|
|
5903
|
+
process.exit(summary.passed ? 0 : 1);
|
|
5904
|
+
}
|
|
5905
|
+
|
|
5211
5906
|
// src/plan-persist-cli.ts
|
|
5212
5907
|
import { readFileSync as readFileSync8 } from "node:fs";
|
|
5213
5908
|
var OPERATIONS = ["create", "add_version", "update_metadata"];
|
|
@@ -5309,7 +6004,7 @@ function runCleanupCli(args) {
|
|
|
5309
6004
|
}
|
|
5310
6005
|
|
|
5311
6006
|
// src/monitor/monitor.service.ts
|
|
5312
|
-
import
|
|
6007
|
+
import path34 from "node:path";
|
|
5313
6008
|
|
|
5314
6009
|
// src/monitor/monitor.classify.ts
|
|
5315
6010
|
function expectedLeaseOwner(runId) {
|
|
@@ -5366,10 +6061,10 @@ function classifyWorkerHealth(input) {
|
|
|
5366
6061
|
|
|
5367
6062
|
// src/monitor/monitor.store.ts
|
|
5368
6063
|
import { existsSync as existsSync18, mkdirSync as mkdirSync6, readdirSync as readdirSync7, unlinkSync as unlinkSync2 } from "node:fs";
|
|
5369
|
-
import
|
|
6064
|
+
import path33 from "node:path";
|
|
5370
6065
|
function monitorsDir() {
|
|
5371
6066
|
const { harnessRoot } = getHarnessPaths();
|
|
5372
|
-
const dir =
|
|
6067
|
+
const dir = path33.join(harnessRoot, "monitors");
|
|
5373
6068
|
mkdirSync6(dir, { recursive: true });
|
|
5374
6069
|
return dir;
|
|
5375
6070
|
}
|
|
@@ -5377,7 +6072,7 @@ function monitorIdFor(runId, workerName) {
|
|
|
5377
6072
|
return workerName ? `${safeSlug(runId)}--${safeSlug(workerName)}` : safeSlug(runId);
|
|
5378
6073
|
}
|
|
5379
6074
|
function monitorPath(monitorId) {
|
|
5380
|
-
return
|
|
6075
|
+
return path33.join(monitorsDir(), `${monitorId}.json`);
|
|
5381
6076
|
}
|
|
5382
6077
|
function loadMonitorSession(monitorId) {
|
|
5383
6078
|
return readJson(monitorPath(monitorId), void 0);
|
|
@@ -5398,7 +6093,7 @@ function listMonitorSessions() {
|
|
|
5398
6093
|
for (const name of readdirSync7(dir)) {
|
|
5399
6094
|
if (!name.endsWith(".json")) continue;
|
|
5400
6095
|
const session = readJson(
|
|
5401
|
-
|
|
6096
|
+
path33.join(dir, name),
|
|
5402
6097
|
void 0
|
|
5403
6098
|
);
|
|
5404
6099
|
if (!session?.monitorId) continue;
|
|
@@ -5489,7 +6184,7 @@ async function fetchTaskLeasesForWorkers(input) {
|
|
|
5489
6184
|
// src/monitor/monitor.service.ts
|
|
5490
6185
|
function workerRecord2(runId, name) {
|
|
5491
6186
|
return readJson(
|
|
5492
|
-
|
|
6187
|
+
path34.join(runDirectory(runId), "workers", safeSlug(name), "worker.json"),
|
|
5493
6188
|
void 0
|
|
5494
6189
|
);
|
|
5495
6190
|
}
|
|
@@ -5692,17 +6387,17 @@ async function runMonitorLoop(args) {
|
|
|
5692
6387
|
// src/monitor/monitor-spawn.ts
|
|
5693
6388
|
import { spawn as spawn4 } from "node:child_process";
|
|
5694
6389
|
import { closeSync as closeSync4, existsSync as existsSync19, openSync as openSync4 } from "node:fs";
|
|
5695
|
-
import
|
|
6390
|
+
import path35 from "node:path";
|
|
5696
6391
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
5697
6392
|
function resolveDefaultCliPath2() {
|
|
5698
|
-
return
|
|
6393
|
+
return path35.join(fileURLToPath3(new URL(".", import.meta.url)), "..", "cli.js");
|
|
5699
6394
|
}
|
|
5700
6395
|
function spawnMonitorSidecar(opts) {
|
|
5701
6396
|
const cliPath = opts.cliPath ?? resolveDefaultCliPath2();
|
|
5702
6397
|
if (!existsSync19(cliPath)) return void 0;
|
|
5703
6398
|
const monitorId = monitorIdFor(opts.runId, opts.workerName);
|
|
5704
6399
|
const { harnessRoot } = getHarnessPaths();
|
|
5705
|
-
const logPath =
|
|
6400
|
+
const logPath = path35.join(harnessRoot, "monitors", `${monitorId}.log`);
|
|
5706
6401
|
let logFd;
|
|
5707
6402
|
try {
|
|
5708
6403
|
logFd = openSync4(logPath, "a");
|
|
@@ -5822,16 +6517,16 @@ async function monitorTickCli(args) {
|
|
|
5822
6517
|
}
|
|
5823
6518
|
|
|
5824
6519
|
// src/doctor/runtime-takeover.ts
|
|
5825
|
-
import
|
|
6520
|
+
import path37 from "node:path";
|
|
5826
6521
|
|
|
5827
6522
|
// src/doctor/runtime-takeover.probes.ts
|
|
5828
6523
|
import { accessSync, constants, existsSync as existsSync20, readFileSync as readFileSync9 } from "node:fs";
|
|
5829
|
-
import { homedir as
|
|
5830
|
-
import
|
|
5831
|
-
import { spawnSync as
|
|
6524
|
+
import { homedir as homedir6 } from "node:os";
|
|
6525
|
+
import path36 from "node:path";
|
|
6526
|
+
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
5832
6527
|
function captureCommand(bin, args) {
|
|
5833
6528
|
try {
|
|
5834
|
-
const res =
|
|
6529
|
+
const res = spawnSync6(bin, args, { encoding: "utf8" });
|
|
5835
6530
|
const stdout = (res.stdout || "").trim();
|
|
5836
6531
|
const stderr = (res.stderr || "").trim();
|
|
5837
6532
|
const ok = res.status === 0;
|
|
@@ -5869,10 +6564,10 @@ var defaultRuntimeTakeoverProbes = {
|
|
|
5869
6564
|
commandOnPath: (bin) => captureCommand(process.platform === "win32" ? "where" : "which", [bin]),
|
|
5870
6565
|
kynverVersion: (bin) => captureCommand(bin, ["--version"]),
|
|
5871
6566
|
loadConfig: () => loadUserConfig(),
|
|
5872
|
-
configFilePath: () =>
|
|
5873
|
-
credentialsFilePath: () =>
|
|
6567
|
+
configFilePath: () => path36.join(homedir6(), ".kynver", "config.json"),
|
|
6568
|
+
credentialsFilePath: () => path36.join(homedir6(), ".kynver", "credentials"),
|
|
5874
6569
|
readCredentials: () => {
|
|
5875
|
-
const credPath =
|
|
6570
|
+
const credPath = path36.join(homedir6(), ".kynver", "credentials");
|
|
5876
6571
|
if (!existsSync20(credPath)) {
|
|
5877
6572
|
return { hasApiKey: false };
|
|
5878
6573
|
}
|
|
@@ -5898,7 +6593,7 @@ var defaultRuntimeTakeoverProbes = {
|
|
|
5898
6593
|
kynverSchedulerProvider: process.env.KYNVER_SCHEDULER_PROVIDER?.trim() || void 0
|
|
5899
6594
|
}),
|
|
5900
6595
|
harnessRoot: () => resolveHarnessRoot(),
|
|
5901
|
-
legacyOpenclawHarnessRoot: () =>
|
|
6596
|
+
legacyOpenclawHarnessRoot: () => path36.join(homedir6(), ".openclaw", "harness"),
|
|
5902
6597
|
pathExists: (target) => existsSync20(target),
|
|
5903
6598
|
pathWritable: (target) => isWritable(target),
|
|
5904
6599
|
vercelVersion: () => captureCommand("vercel", ["--version"]),
|
|
@@ -6084,8 +6779,8 @@ function assessVercelCli(probes) {
|
|
|
6084
6779
|
}
|
|
6085
6780
|
function assessHarnessDirs(probes) {
|
|
6086
6781
|
const harnessRoot = probes.harnessRoot();
|
|
6087
|
-
const runsDir =
|
|
6088
|
-
const worktreesDir =
|
|
6782
|
+
const runsDir = path37.join(harnessRoot, "runs");
|
|
6783
|
+
const worktreesDir = path37.join(harnessRoot, "worktrees");
|
|
6089
6784
|
const displayHarnessRoot = redactHomePath(harnessRoot);
|
|
6090
6785
|
const displayRunsDir = redactHomePath(runsDir);
|
|
6091
6786
|
const displayWorktreesDir = redactHomePath(worktreesDir);
|
|
@@ -6237,6 +6932,37 @@ function runRuntimeTakeoverDoctorCli() {
|
|
|
6237
6932
|
}
|
|
6238
6933
|
}
|
|
6239
6934
|
|
|
6935
|
+
// src/command-center-contract-cli.ts
|
|
6936
|
+
async function runCommandCenterContractCli(args) {
|
|
6937
|
+
const config = loadUserConfig();
|
|
6938
|
+
const agentOsId = (args.agentOsId ? String(args.agentOsId) : config.agentOsId) || "";
|
|
6939
|
+
if (!agentOsId) {
|
|
6940
|
+
console.error("requires --agent-os-id or agentOsId in ~/.kynver/config.json");
|
|
6941
|
+
process.exit(1);
|
|
6942
|
+
}
|
|
6943
|
+
const base = resolveBaseUrl(args.baseUrl ? String(args.baseUrl) : config.apiBaseUrl);
|
|
6944
|
+
const secret = await resolveCallbackSecretWithMint(
|
|
6945
|
+
args.secret ? String(args.secret) : void 0,
|
|
6946
|
+
agentOsId,
|
|
6947
|
+
{ baseUrl: base }
|
|
6948
|
+
);
|
|
6949
|
+
const qs = new URLSearchParams();
|
|
6950
|
+
if (typeof args.since === "string" && args.since.trim()) qs.set("since", args.since.trim());
|
|
6951
|
+
if (args.limit != null && String(args.limit).trim()) {
|
|
6952
|
+
const n = Number(args.limit);
|
|
6953
|
+
if (Number.isFinite(n) && n > 0) qs.set("limit", String(Math.floor(n)));
|
|
6954
|
+
}
|
|
6955
|
+
const suffix = qs.toString() ? `?${qs.toString()}` : "";
|
|
6956
|
+
const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/command-center/dashboard-contract${suffix}`;
|
|
6957
|
+
const res = await getJson(url, secret);
|
|
6958
|
+
if (!res.ok) {
|
|
6959
|
+
console.error(`dashboard-contract GET failed: HTTP ${res.status}`);
|
|
6960
|
+
if (res.response) console.error(JSON.stringify(res.response, null, 2));
|
|
6961
|
+
process.exit(1);
|
|
6962
|
+
}
|
|
6963
|
+
console.log(JSON.stringify(res.response, null, 2));
|
|
6964
|
+
}
|
|
6965
|
+
|
|
6240
6966
|
// src/cli.ts
|
|
6241
6967
|
function isHelpFlag(arg) {
|
|
6242
6968
|
return arg === "help" || arg === "--help" || arg === "-h";
|
|
@@ -6258,7 +6984,7 @@ function usage(code = 0) {
|
|
|
6258
6984
|
" kynver run create --repo /path/repo [--name name] [--base origin/main]",
|
|
6259
6985
|
" kynver run list",
|
|
6260
6986
|
" kynver run status --run RUN_ID",
|
|
6261
|
-
" kynver run dispatch --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--execute] [--lane any|implementation|review|landing] [--executor harness] [--max-starts 1] [--lease-ms MS] [--owned path[,path]] [--model claude-opus-4-8] [--disk-path /]",
|
|
6987
|
+
" kynver run dispatch --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--execute] [--lane any|implementation|review|landing] [--target-task-id TASK_ID] [--executor harness] [--max-starts 1] [--lease-ms MS] [--owned path[,path]] [--model claude-opus-4-8] [--disk-path /]",
|
|
6262
6988
|
" kynver run sweep --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--grace-ms MS]",
|
|
6263
6989
|
' kynver worker start --run RUN_ID --name worker --task "..." [--owned path[,path]] [--model MODEL] [--provider claude|cursor] [--agent-os-id AOS_ID] [--task-id TASK_ID] [--wait]',
|
|
6264
6990
|
" kynver worker status --run RUN_ID --name worker",
|
|
@@ -6268,7 +6994,8 @@ function usage(code = 0) {
|
|
|
6268
6994
|
" kynver worker auto-complete --run RUN_ID --name worker [--agent-os-id AOS_ID] [--poll-ms 5000] [--max-total-ms 21600000] [--complete-attempts 3] [--complete-backoff-ms 5000] [--base-url URL] [--secret SECRET]",
|
|
6269
6995
|
" kynver run reconcile",
|
|
6270
6996
|
" kynver plan progress --plan PLAN_ID --row ROW_KEY --role ROLE --status STATUS [--task TASK_ID] [--note NOTE] [--evidence type:value] [--agent-os-id AOS_ID]",
|
|
6271
|
-
" kynver plan verify --plan PLAN_ID [--worktree PATH] [--task TASK_ID] [--human-override]",
|
|
6997
|
+
" kynver plan verify --plan PLAN_ID [--worktree PATH] [--task TASK_ID] [--human-override] [--local]",
|
|
6998
|
+
" kynver harness verify --worktree PATH [--command CMD] [--json] [--wait-for-admission-ms MS] [--timeout-ms MS]",
|
|
6272
6999
|
" kynver plan persist --operation create|add_version|update_metadata --title TITLE (--body-file PATH | --body TEXT) [--slug SLUG] [--plan PLAN_ID] [--summary TEXT] [--failure-kind approval_guard|auth|network|server|tool_interruption]",
|
|
6273
7000
|
" kynver plan outbox list",
|
|
6274
7001
|
" kynver plan outbox drain [--max N] [--id OUTBOX_ID]",
|
|
@@ -6280,7 +7007,8 @@ function usage(code = 0) {
|
|
|
6280
7007
|
" kynver monitor tick --run RUN_ID [--name worker] [--agent-os-id AOS_ID] [--auto-complete] [--renew-leases]",
|
|
6281
7008
|
" kynver monitor auto-complete --run RUN_ID --name worker [--agent-os-id AOS_ID] [--base-url URL] [--secret SECRET]",
|
|
6282
7009
|
" kynver monitor run-loop --run RUN_ID --monitor-id ID [--name worker] [--agent-os-id AOS_ID] [--poll-ms MS] [--auto-complete] [--renew-leases]",
|
|
6283
|
-
" kynver doctor runtime-takeover"
|
|
7010
|
+
" kynver doctor runtime-takeover",
|
|
7011
|
+
" kynver board contract [--agent-os-id ID] [--base-url URL] [--since ISO] [--limit N]"
|
|
6284
7012
|
].join("\n")
|
|
6285
7013
|
);
|
|
6286
7014
|
process.exit(code);
|
|
@@ -6291,7 +7019,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
6291
7019
|
const scope = argv.shift();
|
|
6292
7020
|
let action;
|
|
6293
7021
|
let rest;
|
|
6294
|
-
if (scope === "run" || scope === "worker" || scope === "plan" || scope === "runner" || scope === "monitor" || scope === "doctor") {
|
|
7022
|
+
if (scope === "run" || scope === "worker" || scope === "plan" || scope === "runner" || scope === "harness" || scope === "monitor" || scope === "doctor" || scope === "board") {
|
|
6295
7023
|
action = argv.shift();
|
|
6296
7024
|
rest = argv;
|
|
6297
7025
|
} else {
|
|
@@ -6308,6 +7036,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
6308
7036
|
if (scope === "daemon") return void await runDaemon(args);
|
|
6309
7037
|
if (scope === "plan" && action === "progress") return void await emitPlanProgress(args);
|
|
6310
7038
|
if (scope === "plan" && action === "verify") return void await verifyPlan(args);
|
|
7039
|
+
if (scope === "harness" && action === "verify") return runHarnessVerifyCli(args);
|
|
6311
7040
|
if (scope === "plan" && action === "persist") return void await runPlanPersist(args);
|
|
6312
7041
|
if (scope === "plan" && action === "outbox") {
|
|
6313
7042
|
const outboxAction = rest.shift();
|
|
@@ -6317,6 +7046,9 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
6317
7046
|
}
|
|
6318
7047
|
if (scope === "cleanup") return runCleanupCli(args);
|
|
6319
7048
|
if (scope === "doctor" && action === "runtime-takeover") return runRuntimeTakeoverDoctorCli();
|
|
7049
|
+
if (scope === "board" && action === "contract") {
|
|
7050
|
+
return void await runCommandCenterContractCli(args);
|
|
7051
|
+
}
|
|
6320
7052
|
if (scope === "run" && action === "create") return createRun(args);
|
|
6321
7053
|
if (scope === "run" && action === "list") return listRuns();
|
|
6322
7054
|
if (scope === "run" && action === "status") return runStatus(args);
|
|
@@ -6443,10 +7175,10 @@ function pickVercelStatusContext(statuses) {
|
|
|
6443
7175
|
return 1;
|
|
6444
7176
|
};
|
|
6445
7177
|
let best = null;
|
|
6446
|
-
let bestScore =
|
|
7178
|
+
let bestScore = Infinity;
|
|
6447
7179
|
for (const row of vercelRows) {
|
|
6448
7180
|
const rowScore = score(normalizeGitHubStatusState(row.state));
|
|
6449
|
-
if (rowScore
|
|
7181
|
+
if (rowScore < bestScore) {
|
|
6450
7182
|
best = row;
|
|
6451
7183
|
bestScore = rowScore;
|
|
6452
7184
|
}
|
|
@@ -6466,7 +7198,7 @@ function pickVercelStatusContext(statuses) {
|
|
|
6466
7198
|
}
|
|
6467
7199
|
|
|
6468
7200
|
// src/vercel/vercel-evidence.ts
|
|
6469
|
-
import { spawnSync as
|
|
7201
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
6470
7202
|
var DEFAULT_INSPECT_WAIT_SECONDS = 120;
|
|
6471
7203
|
function mapGitHubStateToEvidence(state) {
|
|
6472
7204
|
if (state === "success") return "ready";
|
|
@@ -6532,7 +7264,7 @@ function evidenceFromGitHubVercelStatus(statuses, options = {}) {
|
|
|
6532
7264
|
}
|
|
6533
7265
|
function defaultRunVercelInspect(target, waitSeconds) {
|
|
6534
7266
|
const args = ["inspect", target, "--wait", String(waitSeconds)];
|
|
6535
|
-
const result =
|
|
7267
|
+
const result = spawnSync7("vercel", args, {
|
|
6536
7268
|
encoding: "utf8",
|
|
6537
7269
|
stdio: ["ignore", "pipe", "pipe"]
|
|
6538
7270
|
});
|
|
@@ -6640,16 +7372,23 @@ function collectVercelEvidence(input) {
|
|
|
6640
7372
|
}
|
|
6641
7373
|
export {
|
|
6642
7374
|
DEFAULT_DISPATCH_LEASE_MS,
|
|
7375
|
+
DEFAULT_HARNESS_VERIFY_COMMANDS,
|
|
7376
|
+
FORBIDDEN_WORKER_ENV_KEYS,
|
|
6643
7377
|
PACKAGE_VERSION,
|
|
6644
7378
|
assessAutoCompleteEligibility,
|
|
7379
|
+
assessBuildAdmission,
|
|
6645
7380
|
assessExitedWorkerSalvage,
|
|
6646
7381
|
assessPrHandoffRequirement,
|
|
6647
7382
|
assessWorkerLanding,
|
|
6648
7383
|
assessWorkerLandingContract,
|
|
7384
|
+
auditWorkerEnv,
|
|
6649
7385
|
autoCompleteWorker,
|
|
6650
7386
|
autoCompleteWorkerCli,
|
|
6651
7387
|
buildDispatchTaskText,
|
|
6652
7388
|
buildPrompt,
|
|
7389
|
+
buildSystemdRunArgv,
|
|
7390
|
+
classifyNpmAuditOutcome,
|
|
7391
|
+
classifyShellCommandOutcome,
|
|
6653
7392
|
classifyVercelUrl,
|
|
6654
7393
|
classifyWorkerHealth,
|
|
6655
7394
|
collectVercelEvidence,
|
|
@@ -6669,16 +7408,21 @@ export {
|
|
|
6669
7408
|
getMonitorStatus,
|
|
6670
7409
|
hashPlanBody,
|
|
6671
7410
|
isDashboardVercelUrl,
|
|
7411
|
+
isEngagementRequiredSkip,
|
|
6672
7412
|
isFinishedWorkerStatus,
|
|
7413
|
+
isForbiddenWorkerEnvKey,
|
|
6673
7414
|
isLandingBlockedWorkerStatus,
|
|
7415
|
+
isSystemdRunAvailable,
|
|
6674
7416
|
isTerminalHeartbeatPhase,
|
|
6675
7417
|
isVercelStatusContext,
|
|
6676
7418
|
landingContractAttentionReason,
|
|
7419
|
+
listForbiddenWorkerEnvKeys,
|
|
6677
7420
|
listMonitors,
|
|
6678
7421
|
listOutboxItems,
|
|
6679
7422
|
listRuns,
|
|
6680
7423
|
loadUserConfig,
|
|
6681
7424
|
main,
|
|
7425
|
+
mergeNodeOptionsForBuildCheck,
|
|
6682
7426
|
normalizeCursorModelAlias,
|
|
6683
7427
|
observeRunnerDiskGate,
|
|
6684
7428
|
parseArgs,
|
|
@@ -6689,6 +7433,7 @@ export {
|
|
|
6689
7433
|
pickVercelStatusContext,
|
|
6690
7434
|
postJson,
|
|
6691
7435
|
preflightCursorModel,
|
|
7436
|
+
readMemAvailableBytes,
|
|
6692
7437
|
reconcileRunsCli,
|
|
6693
7438
|
reconcileStaleWorkers,
|
|
6694
7439
|
redactHarness,
|
|
@@ -6697,16 +7442,22 @@ export {
|
|
|
6697
7442
|
resolveCallbackSecretWithMint,
|
|
6698
7443
|
resolveHarnessRoot,
|
|
6699
7444
|
resolveVercelInspectTarget,
|
|
7445
|
+
runBoundedBuildCheck,
|
|
6700
7446
|
runDaemon,
|
|
7447
|
+
runHarnessVerifyCommands,
|
|
6701
7448
|
runMonitorTick,
|
|
6702
7449
|
runStatus,
|
|
6703
7450
|
saveUserConfig,
|
|
7451
|
+
scrubClaudeEnv,
|
|
7452
|
+
scrubWorkerEnv,
|
|
6704
7453
|
spawnCompletionSidecar,
|
|
6705
7454
|
spawnMonitorSidecar,
|
|
6706
7455
|
spawnWorkerProcess,
|
|
6707
7456
|
startWorker,
|
|
6708
7457
|
stopWorker,
|
|
6709
7458
|
summarizeEvent,
|
|
7459
|
+
summarizeNpmAuditReport,
|
|
7460
|
+
summarizeShellToolCallEvent,
|
|
6710
7461
|
sweepRun,
|
|
6711
7462
|
tailWorker,
|
|
6712
7463
|
terminalFinalResultFromHeartbeat,
|