@kynver-app/runtime 0.1.2 → 0.1.4
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 +176 -37
- package/dist/cli.js.map +4 -4
- package/dist/index.js +179 -40
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -236,12 +236,12 @@ var DEFAULT_CRITICAL_FREE_BYTES = 15 * 1024 * 1024 * 1024;
|
|
|
236
236
|
var DEFAULT_MAX_USED_PERCENT = 80;
|
|
237
237
|
var DEFAULT_HARD_MAX_USED_PERCENT = 90;
|
|
238
238
|
function observeRunnerDiskGate(input = {}) {
|
|
239
|
-
const
|
|
239
|
+
const path14 = input.diskPath?.trim() || "/";
|
|
240
240
|
const warnBelowBytes = input.diskFreeWarnBytes ?? DEFAULT_WARN_FREE_BYTES;
|
|
241
241
|
const criticalBelowBytes = input.diskFreeCriticalBytes ?? DEFAULT_CRITICAL_FREE_BYTES;
|
|
242
242
|
const maxUsedPercent = input.diskMaxUsedPercent ?? DEFAULT_MAX_USED_PERCENT;
|
|
243
243
|
const hardMaxUsedPercent = input.diskHardMaxUsedPercent ?? DEFAULT_HARD_MAX_USED_PERCENT;
|
|
244
|
-
const stats = statfsSync(
|
|
244
|
+
const stats = statfsSync(path14);
|
|
245
245
|
const freeBytes = Number(stats.bavail) * Number(stats.bsize);
|
|
246
246
|
const totalBytes = Number(stats.blocks) * Number(stats.bsize);
|
|
247
247
|
const usedPercent = totalBytes > 0 ? (totalBytes - freeBytes) / totalBytes * 100 : 100;
|
|
@@ -261,7 +261,7 @@ function observeRunnerDiskGate(input = {}) {
|
|
|
261
261
|
}
|
|
262
262
|
return {
|
|
263
263
|
ok,
|
|
264
|
-
path:
|
|
264
|
+
path: path14,
|
|
265
265
|
freeBytes,
|
|
266
266
|
totalBytes,
|
|
267
267
|
usedPercent,
|
|
@@ -372,7 +372,8 @@ function parseClaudeStream(file) {
|
|
|
372
372
|
for (const line of lines) {
|
|
373
373
|
const event = safeJson(line);
|
|
374
374
|
if (!event) continue;
|
|
375
|
-
const
|
|
375
|
+
const tsMs = event.timestamp_ms;
|
|
376
|
+
const ts = event.timestamp || event.ts || (tsMs ? new Date(tsMs).toISOString() : void 0);
|
|
376
377
|
if (ts) {
|
|
377
378
|
result.firstEventAt ||= ts;
|
|
378
379
|
result.lastEventAt = ts;
|
|
@@ -631,8 +632,8 @@ function observeRunnerResourceGate(input) {
|
|
|
631
632
|
}
|
|
632
633
|
|
|
633
634
|
// src/supervisor.ts
|
|
634
|
-
import { existsSync as
|
|
635
|
-
import
|
|
635
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync3 } from "node:fs";
|
|
636
|
+
import path7 from "node:path";
|
|
636
637
|
|
|
637
638
|
// src/prompt.ts
|
|
638
639
|
function buildPrompt(input) {
|
|
@@ -692,11 +693,44 @@ var claudeProvider = {
|
|
|
692
693
|
};
|
|
693
694
|
|
|
694
695
|
// src/providers/cursor.ts
|
|
695
|
-
import { closeSync as closeSync2, openSync as openSync2 } from "node:fs";
|
|
696
|
+
import { closeSync as closeSync2, existsSync as existsSync6, openSync as openSync2, readdirSync as readdirSync2 } from "node:fs";
|
|
696
697
|
import { spawn as spawn2 } from "node:child_process";
|
|
698
|
+
import path6 from "node:path";
|
|
697
699
|
var DEFAULT_CURSOR_MODEL = "composer-2.5";
|
|
700
|
+
function latestVersionDir(versionsRoot) {
|
|
701
|
+
if (!existsSync6(versionsRoot)) return null;
|
|
702
|
+
const versions = readdirSync2(versionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && /^\d{4}\.\d/.test(entry.name)).map((entry) => entry.name).sort((a, b) => b.localeCompare(a));
|
|
703
|
+
return versions[0] ? path6.join(versionsRoot, versions[0]) : null;
|
|
704
|
+
}
|
|
705
|
+
function resolveBundledCursor(versionDir) {
|
|
706
|
+
const nodeExe = path6.join(versionDir, "node.exe");
|
|
707
|
+
const indexJs = path6.join(versionDir, "index.js");
|
|
708
|
+
if (!existsSync6(nodeExe) || !existsSync6(indexJs)) return null;
|
|
709
|
+
return { executable: nodeExe, prefixArgs: [indexJs], shell: false, detached: true };
|
|
710
|
+
}
|
|
711
|
+
function resolveWindowsCursorSpawn(agentBin) {
|
|
712
|
+
const agentRoot = path6.dirname(agentBin);
|
|
713
|
+
const direct = resolveBundledCursor(agentRoot);
|
|
714
|
+
if (direct) return direct;
|
|
715
|
+
const versionDir = latestVersionDir(path6.join(agentRoot, "versions"));
|
|
716
|
+
return versionDir ? resolveBundledCursor(versionDir) : null;
|
|
717
|
+
}
|
|
718
|
+
function resolveCursorSpawn(agentBin) {
|
|
719
|
+
if (process.platform === "win32" && /\.(cmd|bat)$/i.test(agentBin)) {
|
|
720
|
+
const bundled = resolveWindowsCursorSpawn(agentBin);
|
|
721
|
+
if (bundled) return bundled;
|
|
722
|
+
return { executable: agentBin, prefixArgs: [], shell: true, detached: false };
|
|
723
|
+
}
|
|
724
|
+
return { executable: agentBin, prefixArgs: [], shell: false, detached: true };
|
|
725
|
+
}
|
|
698
726
|
function resolveAgentBin() {
|
|
699
|
-
|
|
727
|
+
const configured = process.env.KYNVER_CURSOR_AGENT_BIN?.trim() || process.env.CURSOR_AGENT_BIN?.trim();
|
|
728
|
+
if (configured) return configured;
|
|
729
|
+
if (process.platform === "win32") {
|
|
730
|
+
const localAgent = path6.join(process.env.LOCALAPPDATA || "", "cursor-agent", "agent.cmd");
|
|
731
|
+
if (existsSync6(localAgent)) return localAgent;
|
|
732
|
+
}
|
|
733
|
+
return "agent";
|
|
700
734
|
}
|
|
701
735
|
var cursorProvider = {
|
|
702
736
|
name: "cursor",
|
|
@@ -705,9 +739,11 @@ var cursorProvider = {
|
|
|
705
739
|
const stdoutFd = openSync2(opts.stdoutPath, "a");
|
|
706
740
|
const stderrFd = openSync2(opts.stderrPath, "a");
|
|
707
741
|
const agentBin = resolveAgentBin();
|
|
742
|
+
const spawnTarget = resolveCursorSpawn(agentBin);
|
|
708
743
|
const child = spawn2(
|
|
709
|
-
|
|
744
|
+
spawnTarget.executable,
|
|
710
745
|
[
|
|
746
|
+
...spawnTarget.prefixArgs,
|
|
711
747
|
"-p",
|
|
712
748
|
"--force",
|
|
713
749
|
"--trust",
|
|
@@ -722,9 +758,13 @@ var cursorProvider = {
|
|
|
722
758
|
],
|
|
723
759
|
{
|
|
724
760
|
cwd: opts.worktreePath,
|
|
725
|
-
detached:
|
|
761
|
+
detached: spawnTarget.detached,
|
|
762
|
+
shell: spawnTarget.shell,
|
|
726
763
|
stdio: ["ignore", stdoutFd, stderrFd],
|
|
727
|
-
env:
|
|
764
|
+
env: {
|
|
765
|
+
...process.env,
|
|
766
|
+
...spawnTarget.prefixArgs.length > 0 ? { CURSOR_INVOKED_AS: path6.basename(agentBin) } : {}
|
|
767
|
+
}
|
|
728
768
|
}
|
|
729
769
|
);
|
|
730
770
|
closeSync2(stdoutFd);
|
|
@@ -762,16 +802,16 @@ function spawnWorkerProcess(run, opts) {
|
|
|
762
802
|
if (run.workers?.[name]) throw new Error(`worker already exists in run ${run.id}: ${name}`);
|
|
763
803
|
if (!opts.task) throw new Error(`missing task text for worker ${name}`);
|
|
764
804
|
const { worktreesDir } = getPaths();
|
|
765
|
-
const workerDir =
|
|
805
|
+
const workerDir = path7.join(runDirectory(run.id), "workers", name);
|
|
766
806
|
mkdirSync3(workerDir, { recursive: true });
|
|
767
|
-
const worktreePath =
|
|
807
|
+
const worktreePath = path7.join(worktreesDir, run.id, name);
|
|
768
808
|
const branch = opts.branch || `agent/${run.id}/${name}`;
|
|
769
|
-
if (
|
|
809
|
+
if (existsSync7(worktreePath)) throw new Error(`worktree path already exists: ${worktreePath}`);
|
|
770
810
|
git(run.repo, ["fetch", "origin", "--prune"], { allowFailure: true });
|
|
771
811
|
git(run.repo, ["worktree", "add", "-b", branch, worktreePath, run.baseCommit], { throwError: true });
|
|
772
|
-
const stdoutPath =
|
|
773
|
-
const stderrPath =
|
|
774
|
-
const heartbeatPath =
|
|
812
|
+
const stdoutPath = path7.join(workerDir, "stdout.jsonl");
|
|
813
|
+
const stderrPath = path7.join(workerDir, "stderr.log");
|
|
814
|
+
const heartbeatPath = path7.join(workerDir, "heartbeat.jsonl");
|
|
775
815
|
const prompt = buildPrompt({
|
|
776
816
|
task: opts.task,
|
|
777
817
|
ownedPaths: opts.ownedPaths || [],
|
|
@@ -820,7 +860,7 @@ function spawnWorkerProcess(run, opts) {
|
|
|
820
860
|
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
821
861
|
};
|
|
822
862
|
saveWorker(run.id, worker);
|
|
823
|
-
run.workers = { ...run.workers || {}, [name]: { workerDir, statusPath:
|
|
863
|
+
run.workers = { ...run.workers || {}, [name]: { workerDir, statusPath: path7.join(workerDir, "worker.json") } };
|
|
824
864
|
run.status = "running";
|
|
825
865
|
saveRun(run);
|
|
826
866
|
return worker;
|
|
@@ -1025,7 +1065,7 @@ function redactHarness(text, secret) {
|
|
|
1025
1065
|
}
|
|
1026
1066
|
|
|
1027
1067
|
// src/validate.ts
|
|
1028
|
-
import
|
|
1068
|
+
import path8 from "node:path";
|
|
1029
1069
|
var RUN_ID_RE = /^[a-z0-9][a-z0-9._-]{0,127}$/i;
|
|
1030
1070
|
var WORKER_NAME_RE = /^[a-z0-9][a-z0-9._-]{0,63}$/i;
|
|
1031
1071
|
function validateRunId(runId) {
|
|
@@ -1039,15 +1079,15 @@ function validateWorkerName(name) {
|
|
|
1039
1079
|
return trimmed;
|
|
1040
1080
|
}
|
|
1041
1081
|
function validateRepo(repo) {
|
|
1042
|
-
const resolved =
|
|
1082
|
+
const resolved = path8.resolve(repo);
|
|
1043
1083
|
if (resolved.includes("..")) throw new Error("repo path must not contain .. segments");
|
|
1044
1084
|
return resolved;
|
|
1045
1085
|
}
|
|
1046
1086
|
function validateOwnedPaths(repoRoot, ownedPaths) {
|
|
1047
1087
|
return ownedPaths.map((owned) => {
|
|
1048
|
-
const resolved =
|
|
1049
|
-
const rel =
|
|
1050
|
-
if (rel.startsWith("..") ||
|
|
1088
|
+
const resolved = path8.resolve(repoRoot, owned);
|
|
1089
|
+
const rel = path8.relative(repoRoot, resolved);
|
|
1090
|
+
if (rel.startsWith("..") || path8.isAbsolute(rel)) {
|
|
1051
1091
|
throw new Error(`owned path escapes repo: ${owned}`);
|
|
1052
1092
|
}
|
|
1053
1093
|
return resolved;
|
|
@@ -1059,14 +1099,14 @@ function validateTailLines(lines) {
|
|
|
1059
1099
|
}
|
|
1060
1100
|
|
|
1061
1101
|
// src/worktree.ts
|
|
1062
|
-
import { existsSync as
|
|
1063
|
-
import
|
|
1102
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync4 } from "node:fs";
|
|
1103
|
+
import path9 from "node:path";
|
|
1064
1104
|
function createRun(args) {
|
|
1065
1105
|
const repo = validateRepo(required(String(args.repo || ""), "--repo"));
|
|
1066
1106
|
ensureGitRepo(repo);
|
|
1067
1107
|
const id = args.id ? validateRunId(String(args.id)) : timestampSlug(String(args.name || "run"));
|
|
1068
1108
|
const dir = runDirectory(id);
|
|
1069
|
-
if (
|
|
1109
|
+
if (existsSync8(dir)) failExists(`run already exists: ${id}`);
|
|
1070
1110
|
mkdirSync4(dir, { recursive: true });
|
|
1071
1111
|
const base = String(args.base || "origin/main");
|
|
1072
1112
|
const baseCommit = git(repo, ["rev-parse", base]).trim();
|
|
@@ -1080,12 +1120,12 @@ function createRun(args) {
|
|
|
1080
1120
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1081
1121
|
workers: {}
|
|
1082
1122
|
};
|
|
1083
|
-
writeJson(
|
|
1123
|
+
writeJson(path9.join(dir, "run.json"), run);
|
|
1084
1124
|
console.log(JSON.stringify({ runId: id, runDir: dir, repo, base, baseCommit }, null, 2));
|
|
1085
1125
|
}
|
|
1086
1126
|
function listRuns() {
|
|
1087
1127
|
const { runsDir } = getPaths();
|
|
1088
|
-
const rows = listRunIds(runsDir).map((id) => readJson(
|
|
1128
|
+
const rows = listRunIds(runsDir).map((id) => readJson(path9.join(runDirectory(id), "run.json"), null)).filter(Boolean).map((run) => ({
|
|
1089
1129
|
id: run.id,
|
|
1090
1130
|
name: run.name,
|
|
1091
1131
|
status: run.status,
|
|
@@ -1100,7 +1140,7 @@ function failExists(message) {
|
|
|
1100
1140
|
}
|
|
1101
1141
|
|
|
1102
1142
|
// src/sweep.ts
|
|
1103
|
-
import
|
|
1143
|
+
import path10 from "node:path";
|
|
1104
1144
|
async function sweepRun(args) {
|
|
1105
1145
|
const pipeline = args.pipeline === true || args.pipeline === "true";
|
|
1106
1146
|
try {
|
|
@@ -1112,7 +1152,7 @@ async function sweepRun(args) {
|
|
|
1112
1152
|
const releasedLocalOrphans = [];
|
|
1113
1153
|
for (const name of Object.keys(run.workers || {})) {
|
|
1114
1154
|
const worker = readJson(
|
|
1115
|
-
|
|
1155
|
+
path10.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
1116
1156
|
null
|
|
1117
1157
|
);
|
|
1118
1158
|
if (!worker || !worker.dispatched || !worker.taskId) continue;
|
|
@@ -1155,7 +1195,7 @@ async function sweepRun(args) {
|
|
|
1155
1195
|
}
|
|
1156
1196
|
|
|
1157
1197
|
// src/worker-ops.ts
|
|
1158
|
-
import
|
|
1198
|
+
import path11 from "node:path";
|
|
1159
1199
|
async function tryCompleteWorker(args) {
|
|
1160
1200
|
const worker = loadWorker(String(args.run), String(args.name));
|
|
1161
1201
|
const status = computeWorkerStatus(worker);
|
|
@@ -1248,7 +1288,7 @@ async function completeWorker(args) {
|
|
|
1248
1288
|
function workerStatus(args) {
|
|
1249
1289
|
const worker = loadWorker(String(args.run), String(args.name));
|
|
1250
1290
|
const status = computeWorkerStatus(worker);
|
|
1251
|
-
writeJson(
|
|
1291
|
+
writeJson(path11.join(worker.workerDir, "last-status.json"), status);
|
|
1252
1292
|
console.log(JSON.stringify(status, null, 2));
|
|
1253
1293
|
}
|
|
1254
1294
|
function runStatus(args) {
|
|
@@ -1256,7 +1296,7 @@ function runStatus(args) {
|
|
|
1256
1296
|
const names = Object.keys(run.workers || {});
|
|
1257
1297
|
const workers = names.map((name) => {
|
|
1258
1298
|
const worker = readJson(
|
|
1259
|
-
|
|
1299
|
+
path11.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
1260
1300
|
null
|
|
1261
1301
|
);
|
|
1262
1302
|
if (!worker) {
|
|
@@ -1288,7 +1328,7 @@ function runStatus(args) {
|
|
|
1288
1328
|
needsAttention: workers.filter((w) => w.attention && w.attention !== "ok" && w.attention !== "done").map((w) => w.worker),
|
|
1289
1329
|
workers
|
|
1290
1330
|
};
|
|
1291
|
-
writeJson(
|
|
1331
|
+
writeJson(path11.join(runDirectory(run.id), "last-board.json"), board);
|
|
1292
1332
|
console.log(JSON.stringify(board, null, 2));
|
|
1293
1333
|
}
|
|
1294
1334
|
function tailWorker(args) {
|
|
@@ -1322,11 +1362,11 @@ function stopWorker(args) {
|
|
|
1322
1362
|
|
|
1323
1363
|
// src/cli.ts
|
|
1324
1364
|
import { mkdirSync as mkdirSync5 } from "node:fs";
|
|
1325
|
-
import
|
|
1365
|
+
import path13 from "node:path";
|
|
1326
1366
|
import { fileURLToPath } from "node:url";
|
|
1327
1367
|
|
|
1328
1368
|
// src/pipeline-tick.ts
|
|
1329
|
-
import
|
|
1369
|
+
import path12 from "node:path";
|
|
1330
1370
|
|
|
1331
1371
|
// src/workspace-runtime-config.ts
|
|
1332
1372
|
async function fetchWorkspaceRuntimePreferences(agentOsId, args) {
|
|
@@ -1355,7 +1395,7 @@ async function completeFinishedWorkers(runId, args) {
|
|
|
1355
1395
|
const outcomes = [];
|
|
1356
1396
|
for (const name of Object.keys(run.workers || {})) {
|
|
1357
1397
|
const worker = readJson(
|
|
1358
|
-
|
|
1398
|
+
path12.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
1359
1399
|
null
|
|
1360
1400
|
);
|
|
1361
1401
|
if (!worker?.dispatched || !worker.taskId) continue;
|
|
@@ -1473,6 +1513,101 @@ async function runDaemon(args) {
|
|
|
1473
1513
|
console.error(JSON.stringify({ event: "daemon_stop", runId, agentOsId }));
|
|
1474
1514
|
}
|
|
1475
1515
|
|
|
1516
|
+
// src/plan-progress.ts
|
|
1517
|
+
function parseEvidenceArg(raw) {
|
|
1518
|
+
const idx = raw.indexOf(":");
|
|
1519
|
+
if (idx <= 0) throw new Error(`invalid --evidence ${raw} (expected type:value)`);
|
|
1520
|
+
return { type: raw.slice(0, idx), value: raw.slice(idx + 1) };
|
|
1521
|
+
}
|
|
1522
|
+
async function emitPlanProgress(args) {
|
|
1523
|
+
const planId = required(args, "plan");
|
|
1524
|
+
const agentOsId = (args.agentOsId ? String(args.agentOsId) : loadUserConfig().agentOsId) || "";
|
|
1525
|
+
if (!agentOsId) {
|
|
1526
|
+
console.error("requires --agent-os-id or agentOsId in ~/.kynver/config.json");
|
|
1527
|
+
process.exit(1);
|
|
1528
|
+
}
|
|
1529
|
+
const roleLane = required(args, "role");
|
|
1530
|
+
const status = required(args, "status");
|
|
1531
|
+
const evidence = [];
|
|
1532
|
+
const rawEvidence = args.evidence;
|
|
1533
|
+
if (Array.isArray(rawEvidence)) {
|
|
1534
|
+
for (const item of rawEvidence) evidence.push(parseEvidenceArg(String(item)));
|
|
1535
|
+
} else if (typeof rawEvidence === "string") {
|
|
1536
|
+
evidence.push(parseEvidenceArg(rawEvidence));
|
|
1537
|
+
}
|
|
1538
|
+
const base = resolveBaseUrl(args.baseUrl ? String(args.baseUrl) : void 0);
|
|
1539
|
+
const secret = resolveCallbackSecret(args.secret ? String(args.secret) : void 0);
|
|
1540
|
+
const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/plans/${encodeURIComponent(planId)}/progress-events`;
|
|
1541
|
+
const body = {
|
|
1542
|
+
rowKey: args.row ? String(args.row) : void 0,
|
|
1543
|
+
rowId: args.rowId ? String(args.rowId) : void 0,
|
|
1544
|
+
taskId: args.task ? String(args.task) : void 0,
|
|
1545
|
+
reviewTaskId: args.reviewTask ? String(args.reviewTask) : void 0,
|
|
1546
|
+
roleLane,
|
|
1547
|
+
status,
|
|
1548
|
+
note: args.note ? String(args.note) : void 0,
|
|
1549
|
+
remainingWork: args.remaining ? String(args.remaining) : void 0,
|
|
1550
|
+
evidence: evidence.length ? evidence : void 0,
|
|
1551
|
+
proposed: args.proposed === true || args.proposed === "true",
|
|
1552
|
+
executorRef: args.executorRef ? String(args.executorRef) : void 0
|
|
1553
|
+
};
|
|
1554
|
+
const res = await fetch(url, {
|
|
1555
|
+
method: "POST",
|
|
1556
|
+
headers: {
|
|
1557
|
+
"Content-Type": "application/json",
|
|
1558
|
+
"X-OpenClaw-Cron-Secret": secret,
|
|
1559
|
+
"X-Kynver-Runtime-Secret": secret
|
|
1560
|
+
},
|
|
1561
|
+
body: JSON.stringify(body)
|
|
1562
|
+
});
|
|
1563
|
+
const text = await res.text();
|
|
1564
|
+
let parsed = null;
|
|
1565
|
+
try {
|
|
1566
|
+
parsed = JSON.parse(text);
|
|
1567
|
+
} catch {
|
|
1568
|
+
parsed = text;
|
|
1569
|
+
}
|
|
1570
|
+
if (!res.ok) {
|
|
1571
|
+
console.error(JSON.stringify({ httpStatus: res.status, response: parsed }, null, 2));
|
|
1572
|
+
process.exit(1);
|
|
1573
|
+
}
|
|
1574
|
+
console.log(JSON.stringify(parsed, null, 2));
|
|
1575
|
+
}
|
|
1576
|
+
async function verifyPlan(args) {
|
|
1577
|
+
const planId = required(args, "plan");
|
|
1578
|
+
const slug = loadUserConfig().agentOsSlug;
|
|
1579
|
+
if (!slug) {
|
|
1580
|
+
console.error("requires agentOsSlug in ~/.kynver/config.json for verify (session route)");
|
|
1581
|
+
process.exit(1);
|
|
1582
|
+
}
|
|
1583
|
+
const base = resolveBaseUrl(args.baseUrl ? String(args.baseUrl) : void 0);
|
|
1584
|
+
const apiKey = process.env.KYNVER_API_KEY;
|
|
1585
|
+
const headers = { "Content-Type": "application/json" };
|
|
1586
|
+
if (apiKey) headers.Authorization = `Bearer ${apiKey}`;
|
|
1587
|
+
const url = `${base}/api/agent-os/${encodeURIComponent(slug)}/plans/${encodeURIComponent(planId)}/verify`;
|
|
1588
|
+
const res = await fetch(url, {
|
|
1589
|
+
method: "POST",
|
|
1590
|
+
headers,
|
|
1591
|
+
body: JSON.stringify({
|
|
1592
|
+
worktreePath: args.worktree ? String(args.worktree) : void 0,
|
|
1593
|
+
taskId: args.task ? String(args.task) : void 0,
|
|
1594
|
+
humanOverride: args.humanOverride === true || args.humanOverride === "true"
|
|
1595
|
+
})
|
|
1596
|
+
});
|
|
1597
|
+
const text = await res.text();
|
|
1598
|
+
let parsed = null;
|
|
1599
|
+
try {
|
|
1600
|
+
parsed = JSON.parse(text);
|
|
1601
|
+
} catch {
|
|
1602
|
+
parsed = text;
|
|
1603
|
+
}
|
|
1604
|
+
if (!res.ok) {
|
|
1605
|
+
console.error(JSON.stringify({ httpStatus: res.status, response: parsed }, null, 2));
|
|
1606
|
+
process.exit(1);
|
|
1607
|
+
}
|
|
1608
|
+
console.log(JSON.stringify(parsed, null, 2));
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1476
1611
|
// src/cli.ts
|
|
1477
1612
|
function isHelpFlag(arg) {
|
|
1478
1613
|
return arg === "help" || arg === "--help" || arg === "-h";
|
|
@@ -1499,7 +1634,9 @@ function usage(code = 0) {
|
|
|
1499
1634
|
" kynver worker status --run RUN_ID --name worker",
|
|
1500
1635
|
" kynver worker tail --run RUN_ID --name worker [--lines 40] [--raw]",
|
|
1501
1636
|
" kynver worker stop --run RUN_ID --name worker",
|
|
1502
|
-
" kynver worker complete --run RUN_ID --name worker [--agent-os-id AOS_ID] [--task-id TASK_ID] [--base-url URL] [--secret SECRET]"
|
|
1637
|
+
" kynver worker complete --run RUN_ID --name worker [--agent-os-id AOS_ID] [--task-id TASK_ID] [--base-url URL] [--secret SECRET]",
|
|
1638
|
+
" 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]",
|
|
1639
|
+
" kynver plan verify --plan PLAN_ID [--worktree PATH] [--task TASK_ID] [--human-override]"
|
|
1503
1640
|
].join("\n")
|
|
1504
1641
|
);
|
|
1505
1642
|
process.exit(code);
|
|
@@ -1509,7 +1646,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
1509
1646
|
const scope = argv.shift();
|
|
1510
1647
|
let action;
|
|
1511
1648
|
let rest;
|
|
1512
|
-
if (scope === "run" || scope === "worker") {
|
|
1649
|
+
if (scope === "run" || scope === "worker" || scope === "plan") {
|
|
1513
1650
|
action = argv.shift();
|
|
1514
1651
|
rest = argv;
|
|
1515
1652
|
} else {
|
|
@@ -1522,6 +1659,8 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
1522
1659
|
if (scope === "login") return void await runLogin(args);
|
|
1523
1660
|
if (scope === "setup") return void await runSetup(args);
|
|
1524
1661
|
if (scope === "daemon") return void await runDaemon(args);
|
|
1662
|
+
if (scope === "plan" && action === "progress") return void await emitPlanProgress(args);
|
|
1663
|
+
if (scope === "plan" && action === "verify") return void await verifyPlan(args);
|
|
1525
1664
|
if (scope === "run" && action === "create") return createRun(args);
|
|
1526
1665
|
if (scope === "run" && action === "list") return listRuns();
|
|
1527
1666
|
if (scope === "run" && action === "status") return runStatus(args);
|
|
@@ -1534,7 +1673,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
1534
1673
|
if (scope === "worker" && action === "complete") return void await completeWorker(args);
|
|
1535
1674
|
unknownCommand(scope, action);
|
|
1536
1675
|
}
|
|
1537
|
-
var isCliEntry = process.argv[1] &&
|
|
1676
|
+
var isCliEntry = process.argv[1] && path13.resolve(process.argv[1]) === path13.resolve(fileURLToPath(import.meta.url));
|
|
1538
1677
|
if (isCliEntry) {
|
|
1539
1678
|
void main().catch((error) => {
|
|
1540
1679
|
console.error(error);
|