@mrciphersmith/keryx 0.2.120 → 0.2.122
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 +1012 -220
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -29500,6 +29500,7 @@ async function runAgentTurnCore(io, deps, history, userLine, options = {}) {
|
|
|
29500
29500
|
const spawnConcurrencyCandidates = calls.filter((call) => call.name === "spawn_subagent" && reservationByCallId.get(call.id)?.ok === true);
|
|
29501
29501
|
const untrustedGateBlocksSpawns = untrustedContentSeen || batchContainsUntrustedWeb;
|
|
29502
29502
|
const concurrentSpawnResults = spawnConcurrencyCandidates.length >= 2 && !untrustedGateBlocksSpawns && maxToolCalls === undefined ? await runConcurrentSpawnBatch(spawnConcurrencyCandidates, toolByName, io, deps, hasInvocationCapacity, reserveInvocation) : undefined;
|
|
29503
|
+
const answeredToolIds = new Set;
|
|
29503
29504
|
let anchorsToAnnounce;
|
|
29504
29505
|
let repeatedFailureHint;
|
|
29505
29506
|
for (const call of calls) {
|
|
@@ -29507,6 +29508,26 @@ async function runAgentTurnCore(io, deps, history, userLine, options = {}) {
|
|
|
29507
29508
|
system(`
|
|
29508
29509
|
[stopped] Model turn interrupted by user.
|
|
29509
29510
|
`);
|
|
29511
|
+
if (concurrentSpawnResults !== undefined) {
|
|
29512
|
+
for (const spawnCall of spawnConcurrencyCandidates) {
|
|
29513
|
+
if (answeredToolIds.has(spawnCall.id)) {
|
|
29514
|
+
continue;
|
|
29515
|
+
}
|
|
29516
|
+
const settled = concurrentSpawnResults.get(spawnCall.id);
|
|
29517
|
+
if (settled === undefined) {
|
|
29518
|
+
continue;
|
|
29519
|
+
}
|
|
29520
|
+
io.onToolResult?.(spawnCall.name, settled);
|
|
29521
|
+
history.push({
|
|
29522
|
+
role: "tool",
|
|
29523
|
+
content: redactSensitiveText(settled.output),
|
|
29524
|
+
provenance: "tool",
|
|
29525
|
+
toolCallId: spawnCall.id,
|
|
29526
|
+
ts: now()
|
|
29527
|
+
});
|
|
29528
|
+
io.onHistoryChange?.("tool");
|
|
29529
|
+
}
|
|
29530
|
+
}
|
|
29510
29531
|
return {};
|
|
29511
29532
|
}
|
|
29512
29533
|
if (deps.unattended === true && call.name === "ask_user") {
|
|
@@ -29549,6 +29570,7 @@ ${modelOutput}` : modelOutput,
|
|
|
29549
29570
|
ts: now()
|
|
29550
29571
|
});
|
|
29551
29572
|
io.onHistoryChange?.("tool");
|
|
29573
|
+
answeredToolIds.add(call.id);
|
|
29552
29574
|
if (untrusted) {
|
|
29553
29575
|
untrustedContentSeen = true;
|
|
29554
29576
|
}
|
|
@@ -42958,6 +42980,103 @@ async function startStdioTransport(server) {
|
|
|
42958
42980
|
await server.connect(transport);
|
|
42959
42981
|
}
|
|
42960
42982
|
|
|
42983
|
+
// src/tui/debug-log.ts
|
|
42984
|
+
import path192 from "path";
|
|
42985
|
+
function isDebugEnabled() {
|
|
42986
|
+
return activeRun !== undefined;
|
|
42987
|
+
}
|
|
42988
|
+
function currentDebugRun() {
|
|
42989
|
+
return activeRun;
|
|
42990
|
+
}
|
|
42991
|
+
function debugEvent(kind, data = {}) {
|
|
42992
|
+
const run = activeRun;
|
|
42993
|
+
if (run === undefined) {
|
|
42994
|
+
return;
|
|
42995
|
+
}
|
|
42996
|
+
seq += 1;
|
|
42997
|
+
try {
|
|
42998
|
+
appendOwnerOnlyLine(run.shellLog, safeStringify({ ts: new Date().toISOString(), seq, pid: process.pid, kind, ...data }));
|
|
42999
|
+
} catch {}
|
|
43000
|
+
}
|
|
43001
|
+
function callerStack() {
|
|
43002
|
+
const raw = new Error("stack").stack ?? "";
|
|
43003
|
+
return raw.split(`
|
|
43004
|
+
`).slice(1).filter((line) => !line.includes("debug-log.ts")).slice(0, 14).map((line) => line.trim()).join(" | ");
|
|
43005
|
+
}
|
|
43006
|
+
function startDebugRun(opts = {}) {
|
|
43007
|
+
const stamp = (opts.now ?? new Date).toISOString().replace(/[:.]/g, "-");
|
|
43008
|
+
const name = `${stamp}-${process.pid}`;
|
|
43009
|
+
const dir = ensureKeryxSubdir(["debug", name], opts.configDir);
|
|
43010
|
+
const run = {
|
|
43011
|
+
dir,
|
|
43012
|
+
shellLog: path192.join(dir, "shell.ndjson"),
|
|
43013
|
+
watcherLog: path192.join(dir, "watcher.ndjson")
|
|
43014
|
+
};
|
|
43015
|
+
try {
|
|
43016
|
+
writeOwnerOnlyFile(path192.join(path192.dirname(dir), "latest.txt"), `${dir}
|
|
43017
|
+
`);
|
|
43018
|
+
} catch {}
|
|
43019
|
+
activeRun = run;
|
|
43020
|
+
seq = 0;
|
|
43021
|
+
return run;
|
|
43022
|
+
}
|
|
43023
|
+
function summarizeInputChunk(chunk) {
|
|
43024
|
+
const buf = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
|
|
43025
|
+
const text = buf.toString("utf8");
|
|
43026
|
+
let printable = 0;
|
|
43027
|
+
let control = 0;
|
|
43028
|
+
const sequences = [];
|
|
43029
|
+
for (let i = 0;i < text.length; i++) {
|
|
43030
|
+
const ch = text[i] ?? "";
|
|
43031
|
+
const code = ch.charCodeAt(0);
|
|
43032
|
+
if (ch === "\x1B") {
|
|
43033
|
+
let j = i + 1;
|
|
43034
|
+
while (j < text.length && j - i < 48) {
|
|
43035
|
+
const c = text.charCodeAt(j);
|
|
43036
|
+
if (j > i + 1 && c >= 64 && c <= 126 && text[j] !== "[" && text[j] !== "<" && text[j] !== ";") {
|
|
43037
|
+
break;
|
|
43038
|
+
}
|
|
43039
|
+
j++;
|
|
43040
|
+
}
|
|
43041
|
+
if (sequences.length < 12) {
|
|
43042
|
+
sequences.push(Buffer.from(text.slice(i, j + 1)).toString("hex"));
|
|
43043
|
+
}
|
|
43044
|
+
control++;
|
|
43045
|
+
i = j;
|
|
43046
|
+
} else if (code < 32 || code === 127) {
|
|
43047
|
+
control++;
|
|
43048
|
+
if (sequences.length < 12) {
|
|
43049
|
+
sequences.push(Buffer.from(ch).toString("hex"));
|
|
43050
|
+
}
|
|
43051
|
+
} else {
|
|
43052
|
+
printable++;
|
|
43053
|
+
}
|
|
43054
|
+
}
|
|
43055
|
+
return { bytes: buf.length, printable, control, sequences };
|
|
43056
|
+
}
|
|
43057
|
+
function safeStringify(value) {
|
|
43058
|
+
const seen = new WeakSet;
|
|
43059
|
+
return JSON.stringify(value, (_key, v) => {
|
|
43060
|
+
if (typeof v === "bigint") {
|
|
43061
|
+
return v.toString();
|
|
43062
|
+
}
|
|
43063
|
+
if (v instanceof Error) {
|
|
43064
|
+
return { name: v.name, message: v.message, stack: v.stack };
|
|
43065
|
+
}
|
|
43066
|
+
if (v !== null && typeof v === "object") {
|
|
43067
|
+
if (seen.has(v)) {
|
|
43068
|
+
return "[circular]";
|
|
43069
|
+
}
|
|
43070
|
+
seen.add(v);
|
|
43071
|
+
}
|
|
43072
|
+
return v;
|
|
43073
|
+
});
|
|
43074
|
+
}
|
|
43075
|
+
var activeRun, seq = 0;
|
|
43076
|
+
var init_debug_log = __esm(() => {
|
|
43077
|
+
init_config_dir();
|
|
43078
|
+
});
|
|
43079
|
+
|
|
42961
43080
|
// src/lib/oauth/device-code.ts
|
|
42962
43081
|
function requestInit(base, signal) {
|
|
42963
43082
|
return signal === undefined ? base : { ...base, signal };
|
|
@@ -43450,6 +43569,259 @@ var init_login = __esm(() => {
|
|
|
43450
43569
|
SESSION_REFRESHED_GRANTS = ["grok", "github-copilot"];
|
|
43451
43570
|
});
|
|
43452
43571
|
|
|
43572
|
+
// src/tui/debug-watcher.ts
|
|
43573
|
+
import { spawn as spawn6, spawnSync as spawnSync3 } from "child_process";
|
|
43574
|
+
import { closeSync as closeSync3, constants as constants2, openSync as openSync3, readdirSync as readdirSync3, readFileSync as readFileSync9, readlinkSync, statSync as statSync6 } from "fs";
|
|
43575
|
+
import path195 from "path";
|
|
43576
|
+
function parseEpollFdinfo(text) {
|
|
43577
|
+
const out = [];
|
|
43578
|
+
for (const line of text.split(`
|
|
43579
|
+
`)) {
|
|
43580
|
+
const match = /^tfd:\s*(\d+)\s+events:\s*([0-9a-fA-F]+)/.exec(line.trim());
|
|
43581
|
+
if (match?.[1] !== undefined && match[2] !== undefined) {
|
|
43582
|
+
out.push({ tfd: Number(match[1]), events: Number.parseInt(match[2], 16) });
|
|
43583
|
+
}
|
|
43584
|
+
}
|
|
43585
|
+
return out;
|
|
43586
|
+
}
|
|
43587
|
+
function ttyReaderArmed(ttyFds, epoll) {
|
|
43588
|
+
if (ttyFds.length === 0) {
|
|
43589
|
+
return;
|
|
43590
|
+
}
|
|
43591
|
+
return epoll.some((entry) => ttyFds.includes(entry.tfd) && (entry.events & EPOLLIN) !== 0);
|
|
43592
|
+
}
|
|
43593
|
+
function detectStall(history, window = 3) {
|
|
43594
|
+
if (history.length < window) {
|
|
43595
|
+
return;
|
|
43596
|
+
}
|
|
43597
|
+
const recent = history.slice(-window);
|
|
43598
|
+
if (recent.every((s) => s.alive && s.readerArmed === false)) {
|
|
43599
|
+
return "reader-not-polled";
|
|
43600
|
+
}
|
|
43601
|
+
if (recent.every((s) => s.alive && (s.pending ?? 0) > 0) && recent.every((s, i) => i === 0 || (s.pending ?? 0) >= (recent[i - 1]?.pending ?? 0))) {
|
|
43602
|
+
return "input-not-drained";
|
|
43603
|
+
}
|
|
43604
|
+
if (recent.every((s) => s.alive && (s.heartbeatAgeMs ?? 0) > 5000)) {
|
|
43605
|
+
return "event-loop-silent";
|
|
43606
|
+
}
|
|
43607
|
+
return;
|
|
43608
|
+
}
|
|
43609
|
+
function isAlive(pid) {
|
|
43610
|
+
try {
|
|
43611
|
+
process.kill(pid, 0);
|
|
43612
|
+
return true;
|
|
43613
|
+
} catch {
|
|
43614
|
+
return false;
|
|
43615
|
+
}
|
|
43616
|
+
}
|
|
43617
|
+
function readText(file) {
|
|
43618
|
+
try {
|
|
43619
|
+
return readFileSync9(file, "utf8");
|
|
43620
|
+
} catch {
|
|
43621
|
+
return;
|
|
43622
|
+
}
|
|
43623
|
+
}
|
|
43624
|
+
function listFds(pid) {
|
|
43625
|
+
const out = [];
|
|
43626
|
+
let entries;
|
|
43627
|
+
try {
|
|
43628
|
+
entries = readdirSync3(`/proc/${pid}/fd`);
|
|
43629
|
+
} catch {
|
|
43630
|
+
return out;
|
|
43631
|
+
}
|
|
43632
|
+
for (const name of entries) {
|
|
43633
|
+
const fd = Number(name);
|
|
43634
|
+
let link;
|
|
43635
|
+
try {
|
|
43636
|
+
link = readlinkSync(`/proc/${pid}/fd/${name}`);
|
|
43637
|
+
} catch {
|
|
43638
|
+
continue;
|
|
43639
|
+
}
|
|
43640
|
+
const flags = /flags:\s*(\S+)/.exec(readText(`/proc/${pid}/fdinfo/${name}`) ?? "")?.[1];
|
|
43641
|
+
out.push({ fd, link, flags });
|
|
43642
|
+
}
|
|
43643
|
+
return out;
|
|
43644
|
+
}
|
|
43645
|
+
function epollEntries(pid, fds) {
|
|
43646
|
+
return fds.filter((f) => f.link === "anon_inode:[eventpoll]").map((f) => ({ epfd: f.fd, entries: parseEpollFdinfo(readText(`/proc/${pid}/fdinfo/${f.fd}`) ?? "") }));
|
|
43647
|
+
}
|
|
43648
|
+
function threads(pid) {
|
|
43649
|
+
let tids;
|
|
43650
|
+
try {
|
|
43651
|
+
tids = readdirSync3(`/proc/${pid}/task`);
|
|
43652
|
+
} catch {
|
|
43653
|
+
return [];
|
|
43654
|
+
}
|
|
43655
|
+
return tids.map((tid) => {
|
|
43656
|
+
const base = `/proc/${pid}/task/${tid}`;
|
|
43657
|
+
const stat = readText(`${base}/stat`) ?? "";
|
|
43658
|
+
const state = /\)\s+(\S)/.exec(stat)?.[1] ?? "?";
|
|
43659
|
+
return { tid, comm: (readText(`${base}/comm`) ?? "").trim(), wchan: (readText(`${base}/wchan`) ?? "").trim(), state };
|
|
43660
|
+
});
|
|
43661
|
+
}
|
|
43662
|
+
async function makePendingReader() {
|
|
43663
|
+
if (process.platform !== "linux") {
|
|
43664
|
+
return () => {
|
|
43665
|
+
return;
|
|
43666
|
+
};
|
|
43667
|
+
}
|
|
43668
|
+
try {
|
|
43669
|
+
const ffi = await import("bun:ffi");
|
|
43670
|
+
const libc = ffi.dlopen("libc.so.6", {
|
|
43671
|
+
ioctl: { args: [ffi.FFIType.i32, ffi.FFIType.u64, ffi.FFIType.ptr], returns: ffi.FFIType.i32 }
|
|
43672
|
+
});
|
|
43673
|
+
return (fd) => {
|
|
43674
|
+
const out = new Int32Array(1);
|
|
43675
|
+
const rc = libc.symbols.ioctl(fd, FIONREAD, ffi.ptr(out));
|
|
43676
|
+
return rc === 0 ? out[0] ?? 0 : undefined;
|
|
43677
|
+
};
|
|
43678
|
+
} catch {
|
|
43679
|
+
return () => {
|
|
43680
|
+
return;
|
|
43681
|
+
};
|
|
43682
|
+
}
|
|
43683
|
+
}
|
|
43684
|
+
function spawnDebugWatcher(run) {
|
|
43685
|
+
const entry = process.argv[1];
|
|
43686
|
+
const args = [
|
|
43687
|
+
...entry !== undefined ? [entry] : [],
|
|
43688
|
+
"shell",
|
|
43689
|
+
"--debug-watcher",
|
|
43690
|
+
"--pid",
|
|
43691
|
+
String(process.pid),
|
|
43692
|
+
"--dir",
|
|
43693
|
+
run.dir
|
|
43694
|
+
];
|
|
43695
|
+
try {
|
|
43696
|
+
const child = spawn6(process.execPath, args, { detached: true, stdio: "ignore", env: process.env });
|
|
43697
|
+
child.unref();
|
|
43698
|
+
return child.pid;
|
|
43699
|
+
} catch {
|
|
43700
|
+
return;
|
|
43701
|
+
}
|
|
43702
|
+
}
|
|
43703
|
+
async function runDebugWatcher(argv) {
|
|
43704
|
+
const pidArg = argv[argv.indexOf("--pid") + 1];
|
|
43705
|
+
const dirArg = argv[argv.indexOf("--dir") + 1];
|
|
43706
|
+
const pid = Number(pidArg);
|
|
43707
|
+
if (!Number.isInteger(pid) || pid <= 0 || dirArg === undefined || !argv.includes("--dir")) {
|
|
43708
|
+
process.stderr.write(`usage: keryx shell --debug-watcher --pid <pid> --dir <debug run dir>
|
|
43709
|
+
`);
|
|
43710
|
+
process.exitCode = 2;
|
|
43711
|
+
return;
|
|
43712
|
+
}
|
|
43713
|
+
const logFile = path195.join(dirArg, "watcher.ndjson");
|
|
43714
|
+
const shellLog = path195.join(dirArg, "shell.ndjson");
|
|
43715
|
+
const log = (kind, data = {}) => {
|
|
43716
|
+
try {
|
|
43717
|
+
appendOwnerOnlyLine(logFile, JSON.stringify({ ts: new Date().toISOString(), watcher: process.pid, target: pid, kind, ...data }));
|
|
43718
|
+
} catch {}
|
|
43719
|
+
};
|
|
43720
|
+
const linux = process.platform === "linux" && isAlive(pid) && readText(`/proc/${pid}/stat`) !== undefined;
|
|
43721
|
+
const pendingOf = await makePendingReader();
|
|
43722
|
+
let ttyPath;
|
|
43723
|
+
let ttyFd;
|
|
43724
|
+
if (linux) {
|
|
43725
|
+
try {
|
|
43726
|
+
ttyPath = readlinkSync(`/proc/${pid}/fd/0`);
|
|
43727
|
+
if (isTtyLink(ttyPath)) {
|
|
43728
|
+
ttyFd = openSync3(ttyPath, constants2.O_RDONLY | constants2.O_NONBLOCK | constants2.O_NOCTTY);
|
|
43729
|
+
}
|
|
43730
|
+
} catch (error) {
|
|
43731
|
+
log("tty.open-failed", { error: String(error) });
|
|
43732
|
+
}
|
|
43733
|
+
}
|
|
43734
|
+
log("watcher.start", { linux, ttyPath, fionread: ttyFd !== undefined && pendingOf(ttyFd) !== undefined });
|
|
43735
|
+
const history = [];
|
|
43736
|
+
let lastLogged = "";
|
|
43737
|
+
let lastPeriodic = 0;
|
|
43738
|
+
let lastSignal = 0;
|
|
43739
|
+
const fullSnapshot = () => {
|
|
43740
|
+
const fds = listFds(pid);
|
|
43741
|
+
let stty;
|
|
43742
|
+
if (ttyPath !== undefined) {
|
|
43743
|
+
const res = spawnSync3("stty", ["-a", "-F", ttyPath], { encoding: "utf8", timeout: 2000 });
|
|
43744
|
+
stty = (res.stdout ?? "").trim() || (res.stderr ?? "").trim();
|
|
43745
|
+
}
|
|
43746
|
+
return {
|
|
43747
|
+
stat: (readText(`/proc/${pid}/stat`) ?? "").trim(),
|
|
43748
|
+
status: (readText(`/proc/${pid}/status`) ?? "").split(`
|
|
43749
|
+
`).filter((l) => /^(State|Threads|SigBlk|SigIgn|SigCgt|VmRSS):/.test(l)),
|
|
43750
|
+
fds,
|
|
43751
|
+
epoll: epollEntries(pid, fds),
|
|
43752
|
+
threads: threads(pid),
|
|
43753
|
+
stty
|
|
43754
|
+
};
|
|
43755
|
+
};
|
|
43756
|
+
const tick = () => {
|
|
43757
|
+
const alive = isAlive(pid);
|
|
43758
|
+
const sample = { alive };
|
|
43759
|
+
if (alive && linux) {
|
|
43760
|
+
const fds = listFds(pid);
|
|
43761
|
+
const ttyFds = fds.filter((f) => isTtyLink(f.link)).map((f) => f.fd);
|
|
43762
|
+
const entries = epollEntries(pid, fds).flatMap((e) => e.entries);
|
|
43763
|
+
sample.readerArmed = ttyReaderArmed(ttyFds, entries);
|
|
43764
|
+
}
|
|
43765
|
+
if (alive && ttyFd !== undefined) {
|
|
43766
|
+
sample.pending = pendingOf(ttyFd);
|
|
43767
|
+
}
|
|
43768
|
+
try {
|
|
43769
|
+
sample.heartbeatAgeMs = Date.now() - statSync6(shellLog).mtimeMs;
|
|
43770
|
+
} catch {
|
|
43771
|
+
sample.heartbeatAgeMs = undefined;
|
|
43772
|
+
}
|
|
43773
|
+
history.push(sample);
|
|
43774
|
+
if (history.length > 30)
|
|
43775
|
+
history.shift();
|
|
43776
|
+
if (!alive) {
|
|
43777
|
+
log("target.exit");
|
|
43778
|
+
return false;
|
|
43779
|
+
}
|
|
43780
|
+
const key = JSON.stringify({ a: sample.readerArmed, p: (sample.pending ?? 0) > 0 });
|
|
43781
|
+
const now = Date.now();
|
|
43782
|
+
if (key !== lastLogged || now - lastPeriodic > 1e4) {
|
|
43783
|
+
log("sample", { ...sample });
|
|
43784
|
+
lastLogged = key;
|
|
43785
|
+
lastPeriodic = now;
|
|
43786
|
+
}
|
|
43787
|
+
const stall = detectStall(history);
|
|
43788
|
+
if (stall !== undefined && now - lastSignal > 15000) {
|
|
43789
|
+
lastSignal = now;
|
|
43790
|
+
log("stall.detected", { reason: stall, recent: history.slice(-5), snapshot: linux ? fullSnapshot() : {} });
|
|
43791
|
+
if (stall !== "event-loop-silent" && process.platform !== "win32") {
|
|
43792
|
+
try {
|
|
43793
|
+
process.kill(pid, "SIGUSR2");
|
|
43794
|
+
log("recover.signal-sent", { signal: "SIGUSR2" });
|
|
43795
|
+
} catch (error) {
|
|
43796
|
+
log("recover.signal-failed", { error: String(error) });
|
|
43797
|
+
}
|
|
43798
|
+
setTimeout(() => {
|
|
43799
|
+
log("recover.after", { snapshot: linux ? fullSnapshot() : {}, pending: ttyFd !== undefined ? pendingOf(ttyFd) : undefined });
|
|
43800
|
+
}, 2000);
|
|
43801
|
+
}
|
|
43802
|
+
}
|
|
43803
|
+
return true;
|
|
43804
|
+
};
|
|
43805
|
+
await new Promise((resolve) => {
|
|
43806
|
+
const timer = setInterval(() => {
|
|
43807
|
+
if (!tick()) {
|
|
43808
|
+
clearInterval(timer);
|
|
43809
|
+
resolve();
|
|
43810
|
+
}
|
|
43811
|
+
}, 1000);
|
|
43812
|
+
});
|
|
43813
|
+
if (ttyFd !== undefined) {
|
|
43814
|
+
try {
|
|
43815
|
+
closeSync3(ttyFd);
|
|
43816
|
+
} catch {}
|
|
43817
|
+
}
|
|
43818
|
+
log("watcher.stop");
|
|
43819
|
+
}
|
|
43820
|
+
var EPOLLIN = 1, FIONREAD = 21531, isTtyLink = (link) => link.startsWith("/dev/pts/") || /^\/dev\/tty/.test(link);
|
|
43821
|
+
var init_debug_watcher = __esm(() => {
|
|
43822
|
+
init_config_dir();
|
|
43823
|
+
});
|
|
43824
|
+
|
|
43453
43825
|
// src/cli.ts
|
|
43454
43826
|
init_single_turn();
|
|
43455
43827
|
init_model_turn_port();
|
|
@@ -50252,7 +50624,7 @@ import path47 from "path";
|
|
|
50252
50624
|
// package.json
|
|
50253
50625
|
var package_default = {
|
|
50254
50626
|
name: "@mrciphersmith/keryx",
|
|
50255
|
-
version: "0.2.
|
|
50627
|
+
version: "0.2.122",
|
|
50256
50628
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
50257
50629
|
private: false,
|
|
50258
50630
|
publishConfig: {
|
|
@@ -90528,6 +90900,9 @@ function classifyBusyDispatch(params) {
|
|
|
90528
90900
|
return "not-a-command";
|
|
90529
90901
|
}
|
|
90530
90902
|
|
|
90903
|
+
// src/tui/tui-shell.ts
|
|
90904
|
+
init_debug_log();
|
|
90905
|
+
|
|
90531
90906
|
// src/tui/boot-animation.ts
|
|
90532
90907
|
var DEFAULT_BOOT_DURATION_MS = 350;
|
|
90533
90908
|
var WORDMARK = ["========================", " K E R Y X ", "========================"];
|
|
@@ -94028,10 +94403,10 @@ function describeElicitationPrompt(tool, inputJson) {
|
|
|
94028
94403
|
// src/lib/permission-mode-config.ts
|
|
94029
94404
|
init_permission_mode();
|
|
94030
94405
|
init_config_dir();
|
|
94031
|
-
import
|
|
94406
|
+
import path193 from "path";
|
|
94032
94407
|
var EMPTY3 = { schemaVersion: 1, projects: {} };
|
|
94033
94408
|
function permissionModeConfigPath(dir) {
|
|
94034
|
-
return
|
|
94409
|
+
return path193.join(keryxConfigDir(dir), "permission-mode.json");
|
|
94035
94410
|
}
|
|
94036
94411
|
function withRegistryLock2(dir, fn) {
|
|
94037
94412
|
return withFileLock2(`${permissionModeConfigPath(dir)}.lock`, fn, {
|
|
@@ -94275,6 +94650,7 @@ function createForegroundAgentIoFacade(owner, token, io) {
|
|
|
94275
94650
|
}
|
|
94276
94651
|
|
|
94277
94652
|
// src/tui/herdr-report.ts
|
|
94653
|
+
init_debug_log();
|
|
94278
94654
|
import net from "net";
|
|
94279
94655
|
var SOURCE = "herdr:keryx";
|
|
94280
94656
|
var AGENT = "keryx";
|
|
@@ -94314,6 +94690,7 @@ function createHerdrReporter(clock = () => Date.now(), connect = writeOnce) {
|
|
|
94314
94690
|
if (state === last)
|
|
94315
94691
|
return;
|
|
94316
94692
|
last = state;
|
|
94693
|
+
debugEvent("herdr.report", { state });
|
|
94317
94694
|
send("pane.report_agent", { state });
|
|
94318
94695
|
},
|
|
94319
94696
|
release() {
|
|
@@ -94349,6 +94726,14 @@ function writeOnce(socketPath, request) {
|
|
|
94349
94726
|
}
|
|
94350
94727
|
|
|
94351
94728
|
// src/tui/composer-choice.ts
|
|
94729
|
+
init_debug_log();
|
|
94730
|
+
var DEFAULT_ACCEPT_DELAY_MS = 400;
|
|
94731
|
+
function resolveAcceptDelay(request) {
|
|
94732
|
+
if (request.acceptDelayMs !== undefined) {
|
|
94733
|
+
return Math.max(0, request.acceptDelayMs);
|
|
94734
|
+
}
|
|
94735
|
+
return DEFAULT_ACCEPT_DELAY_MS;
|
|
94736
|
+
}
|
|
94352
94737
|
var MAX_SUBTITLE_CHARS = 8000;
|
|
94353
94738
|
var MAX_SUBTITLE_ROWS = 10;
|
|
94354
94739
|
var SUBTITLE_INLINE_MAX_CHARS = 76;
|
|
@@ -94358,8 +94743,55 @@ function onKeypress2(r, handler) {
|
|
|
94358
94743
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
94359
94744
|
return () => r._internalKeyInput.offInternal("keypress", handler);
|
|
94360
94745
|
}
|
|
94361
|
-
|
|
94746
|
+
var dockChain = new WeakMap;
|
|
94747
|
+
var dockDepth = new WeakMap;
|
|
94748
|
+
function dockBusy(dock) {
|
|
94749
|
+
return (dockDepth.get(dock) ?? 0) > 0;
|
|
94750
|
+
}
|
|
94751
|
+
function lockDock(dock) {
|
|
94752
|
+
dockDepth.set(dock, (dockDepth.get(dock) ?? 0) + 1);
|
|
94753
|
+
const prev = dockChain.get(dock) ?? Promise.resolve();
|
|
94754
|
+
let release;
|
|
94755
|
+
const mine = new Promise((resolve) => {
|
|
94756
|
+
release = resolve;
|
|
94757
|
+
});
|
|
94758
|
+
dockChain.set(dock, prev.then(() => mine));
|
|
94759
|
+
return prev.then(() => {
|
|
94760
|
+
return () => {
|
|
94761
|
+
const n = (dockDepth.get(dock) ?? 1) - 1;
|
|
94762
|
+
if (n <= 0) {
|
|
94763
|
+
dockDepth.delete(dock);
|
|
94764
|
+
} else {
|
|
94765
|
+
dockDepth.set(dock, n);
|
|
94766
|
+
}
|
|
94767
|
+
release();
|
|
94768
|
+
};
|
|
94769
|
+
});
|
|
94770
|
+
}
|
|
94771
|
+
async function showComposerChoice(otui, r, dock, request) {
|
|
94772
|
+
const enqueue = request.enqueue !== false;
|
|
94773
|
+
if (!enqueue && dockBusy(dock)) {
|
|
94774
|
+
debugEvent("choice.busy-cancel", { title: request.title });
|
|
94775
|
+
request.onBusy?.();
|
|
94776
|
+
return request.cancelId;
|
|
94777
|
+
}
|
|
94778
|
+
const queuedAt = Date.now();
|
|
94779
|
+
debugEvent("choice.request", { title: request.title, waitingBehind: dockDepth.get(dock) ?? 0 });
|
|
94780
|
+
const unlock = await lockDock(dock);
|
|
94781
|
+
debugEvent("choice.lock-acquired", { title: request.title, waitedMs: Date.now() - queuedAt });
|
|
94782
|
+
try {
|
|
94783
|
+
if (request.signal?.aborted === true) {
|
|
94784
|
+
debugEvent("choice.aborted-before-open", { title: request.title });
|
|
94785
|
+
return request.cancelId;
|
|
94786
|
+
}
|
|
94787
|
+
return await presentComposerChoice(otui, r, dock, request);
|
|
94788
|
+
} finally {
|
|
94789
|
+
unlock();
|
|
94790
|
+
}
|
|
94791
|
+
}
|
|
94792
|
+
function presentComposerChoice(otui, r, dock, request) {
|
|
94362
94793
|
if (dock.visible === true) {
|
|
94794
|
+
debugEvent("choice.dock-already-visible", { title: request.title });
|
|
94363
94795
|
request.onBusy?.();
|
|
94364
94796
|
return Promise.resolve(request.cancelId);
|
|
94365
94797
|
}
|
|
@@ -94371,6 +94803,10 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
94371
94803
|
const recommendedIdx = options.findIndex((o) => o.recommended === true);
|
|
94372
94804
|
let selected = recommendedIdx >= 0 ? recommendedIdx : 0;
|
|
94373
94805
|
dock.visible = true;
|
|
94806
|
+
const openedAt = Date.now();
|
|
94807
|
+
const acceptDelayMs = resolveAcceptDelay(request);
|
|
94808
|
+
let lastTypedAt = 0;
|
|
94809
|
+
request.onOpen?.();
|
|
94374
94810
|
const theme = getTheme();
|
|
94375
94811
|
const rawSubtitle = request.subtitle !== undefined && request.subtitle.length > 0 ? request.subtitle : undefined;
|
|
94376
94812
|
const subtitleText = rawSubtitle !== undefined && rawSubtitle.length > MAX_SUBTITLE_CHARS ? `${rawSubtitle.slice(0, MAX_SUBTITLE_CHARS)}
|
|
@@ -94435,7 +94871,16 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
94435
94871
|
}
|
|
94436
94872
|
}
|
|
94437
94873
|
};
|
|
94438
|
-
|
|
94874
|
+
let settled = false;
|
|
94875
|
+
const onAbort = () => {
|
|
94876
|
+
finish(request.cancelId, "abort");
|
|
94877
|
+
};
|
|
94878
|
+
const finish = (id, via = "key") => {
|
|
94879
|
+
if (settled) {
|
|
94880
|
+
return;
|
|
94881
|
+
}
|
|
94882
|
+
settled = true;
|
|
94883
|
+
debugEvent("choice.finish", { title: request.title, id, via, openMs: Date.now() - openedAt });
|
|
94439
94884
|
cleanup();
|
|
94440
94885
|
resolve(id);
|
|
94441
94886
|
};
|
|
@@ -94446,7 +94891,7 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
94446
94891
|
width: "100%",
|
|
94447
94892
|
flexDirection: "column",
|
|
94448
94893
|
onMouseDown: () => {
|
|
94449
|
-
finish(o.id);
|
|
94894
|
+
finish(o.id, "click");
|
|
94450
94895
|
}
|
|
94451
94896
|
});
|
|
94452
94897
|
const label = new otui.TextRenderable(r, { id: `ch-opt-l-${i}-${Date.now()}`, content: o.displayLabel });
|
|
@@ -94487,6 +94932,7 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
94487
94932
|
function cleanup() {
|
|
94488
94933
|
closed = true;
|
|
94489
94934
|
unsub();
|
|
94935
|
+
request.signal?.removeEventListener("abort", onAbort);
|
|
94490
94936
|
try {
|
|
94491
94937
|
dock.remove(title);
|
|
94492
94938
|
if (subtitleScroll !== undefined) {
|
|
@@ -94503,8 +94949,11 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
94503
94949
|
dock.visible = false;
|
|
94504
94950
|
}
|
|
94505
94951
|
const onKey = (key) => {
|
|
94952
|
+
if (!key.ctrl && typeof key.sequence === "string" && key.sequence.length === 1 && key.sequence >= " ") {
|
|
94953
|
+
lastTypedAt = Date.now();
|
|
94954
|
+
}
|
|
94506
94955
|
if (key.name === "escape") {
|
|
94507
|
-
finish(request.cancelId);
|
|
94956
|
+
finish(request.cancelId, "escape");
|
|
94508
94957
|
key.preventDefault();
|
|
94509
94958
|
key.stopPropagation();
|
|
94510
94959
|
return;
|
|
@@ -94523,7 +94972,7 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
94523
94972
|
}
|
|
94524
94973
|
const focused = r.currentFocusedRenderable;
|
|
94525
94974
|
const inScroll = subtitleScroll !== undefined && focused !== null && containsNode(subtitleScroll, focused);
|
|
94526
|
-
if (inScroll) {
|
|
94975
|
+
if (inScroll && key.name !== "return" && key.name !== "linefeed" && key.name !== "kpenter") {
|
|
94527
94976
|
return;
|
|
94528
94977
|
}
|
|
94529
94978
|
if (key.name === "up") {
|
|
@@ -94541,6 +94990,17 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
94541
94990
|
return;
|
|
94542
94991
|
}
|
|
94543
94992
|
if (key.name === "return" || key.name === "linefeed" || key.name === "kpenter") {
|
|
94993
|
+
const now = Date.now();
|
|
94994
|
+
if (now - openedAt < acceptDelayMs || now - lastTypedAt < acceptDelayMs) {
|
|
94995
|
+
debugEvent("choice.enter-ignored", {
|
|
94996
|
+
title: request.title,
|
|
94997
|
+
sinceOpenMs: now - openedAt,
|
|
94998
|
+
sinceTypingMs: lastTypedAt === 0 ? undefined : now - lastTypedAt
|
|
94999
|
+
});
|
|
95000
|
+
key.preventDefault();
|
|
95001
|
+
key.stopPropagation();
|
|
95002
|
+
return;
|
|
95003
|
+
}
|
|
94544
95004
|
const chosen = options[selected];
|
|
94545
95005
|
if (chosen !== undefined) {
|
|
94546
95006
|
finish(chosen.id);
|
|
@@ -94550,14 +95010,24 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
94550
95010
|
}
|
|
94551
95011
|
};
|
|
94552
95012
|
const unsub = onKeypress2(r, onKey);
|
|
95013
|
+
if (request.signal !== undefined) {
|
|
95014
|
+
request.signal.addEventListener("abort", onAbort, { once: true });
|
|
95015
|
+
}
|
|
94553
95016
|
optionsScroll.focus();
|
|
95017
|
+
debugEvent("choice.open", {
|
|
95018
|
+
title: request.title,
|
|
95019
|
+
options: options.map((o) => o.id),
|
|
95020
|
+
selected: options[selected]?.id,
|
|
95021
|
+
scrollableSubtitle: hasScrollableSubtitle,
|
|
95022
|
+
acceptDelayMs
|
|
95023
|
+
});
|
|
94554
95024
|
});
|
|
94555
95025
|
}
|
|
94556
95026
|
|
|
94557
95027
|
// src/lib/version-check.ts
|
|
94558
95028
|
init_config_dir();
|
|
94559
95029
|
init_fs();
|
|
94560
|
-
import
|
|
95030
|
+
import path194 from "path";
|
|
94561
95031
|
var REGISTRY_URL = "https://registry.npmjs.org/@mrciphersmith%2Fkeryx/latest";
|
|
94562
95032
|
var FIXED_INSTALL_COMMAND = "npm install -g @mrciphersmith/keryx@latest";
|
|
94563
95033
|
var RESPONSE_BODY_LIMIT_BYTES = 64 * 1024;
|
|
@@ -94759,7 +95229,7 @@ async function checkVersion(options) {
|
|
|
94759
95229
|
const now = options.now ?? Date.now;
|
|
94760
95230
|
const timestamp = now();
|
|
94761
95231
|
const configDir = ensureKeryxConfigDir(options.cacheDir);
|
|
94762
|
-
const cacheFile =
|
|
95232
|
+
const cacheFile = path194.join(configDir, "version-check.json");
|
|
94763
95233
|
const cache = parseCache(cacheFile);
|
|
94764
95234
|
if (cache?.latestVersion !== undefined && cache.successAt !== undefined && timestamp - cache.successAt >= 0 && timestamp - cache.successAt < SUCCESS_CACHE_TTL_MS) {
|
|
94765
95235
|
return resultFor(options.currentVersion, current, cache.latestVersion, "cache");
|
|
@@ -94827,6 +95297,236 @@ async function checkVersion(options) {
|
|
|
94827
95297
|
return resultFor(options.currentVersion, current, latestVersion, "registry");
|
|
94828
95298
|
}
|
|
94829
95299
|
|
|
95300
|
+
// src/tui/shell-chrome.ts
|
|
95301
|
+
init_debug_log();
|
|
95302
|
+
|
|
95303
|
+
// src/tui/renderer-debug.ts
|
|
95304
|
+
init_debug_log();
|
|
95305
|
+
|
|
95306
|
+
// src/tui/stdin-guard.ts
|
|
95307
|
+
init_debug_log();
|
|
95308
|
+
var rendererListener;
|
|
95309
|
+
function stdinSnapshot(stdin) {
|
|
95310
|
+
const safe = (read) => {
|
|
95311
|
+
try {
|
|
95312
|
+
return read();
|
|
95313
|
+
} catch (error) {
|
|
95314
|
+
return `error: ${error instanceof Error ? error.message : String(error)}`;
|
|
95315
|
+
}
|
|
95316
|
+
};
|
|
95317
|
+
return {
|
|
95318
|
+
isTTY: safe(() => stdin.isTTY === true),
|
|
95319
|
+
isRaw: safe(() => stdin.isRaw),
|
|
95320
|
+
paused: safe(() => stdin.isPaused()),
|
|
95321
|
+
flowing: safe(() => stdin.readableFlowing),
|
|
95322
|
+
ended: safe(() => stdin.readableEnded),
|
|
95323
|
+
destroyed: safe(() => stdin.destroyed),
|
|
95324
|
+
buffered: safe(() => stdin.readableLength),
|
|
95325
|
+
dataListeners: safe(() => stdin.listenerCount("data")),
|
|
95326
|
+
readableListeners: safe(() => stdin.listenerCount("readable")),
|
|
95327
|
+
rendererAttached: safe(() => rendererListener === undefined ? undefined : stdin.listeners("data").includes(rendererListener))
|
|
95328
|
+
};
|
|
95329
|
+
}
|
|
95330
|
+
function stdinLooksStalled(snapshot) {
|
|
95331
|
+
return snapshot.paused === true || snapshot.flowing === false || snapshot.ended === true || snapshot.destroyed === true || snapshot.dataListeners === 0 || snapshot.rendererAttached === false || snapshot.isTTY === true && snapshot.isRaw === false;
|
|
95332
|
+
}
|
|
95333
|
+
function registerRendererInputListener(listener) {
|
|
95334
|
+
rendererListener = listener;
|
|
95335
|
+
}
|
|
95336
|
+
function recoverStdin(stdin, opts = {}) {
|
|
95337
|
+
const actions = [];
|
|
95338
|
+
const listener = opts.listener ?? rendererListener;
|
|
95339
|
+
const step = (name, run) => {
|
|
95340
|
+
try {
|
|
95341
|
+
run();
|
|
95342
|
+
actions.push(name);
|
|
95343
|
+
} catch (error) {
|
|
95344
|
+
actions.push(`${name} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
95345
|
+
}
|
|
95346
|
+
};
|
|
95347
|
+
if (stdin.isTTY === true && typeof stdin.setRawMode === "function" && stdin.isRaw !== true) {
|
|
95348
|
+
step("setRawMode(true)", () => stdin.setRawMode?.(true));
|
|
95349
|
+
}
|
|
95350
|
+
if (listener !== undefined && !stdin.listeners("data").includes(listener)) {
|
|
95351
|
+
step("re-attach renderer data listener", () => stdin.on("data", listener));
|
|
95352
|
+
}
|
|
95353
|
+
if (opts.cycle === true) {
|
|
95354
|
+
step("pause()", () => stdin.pause());
|
|
95355
|
+
}
|
|
95356
|
+
step("resume()", () => stdin.resume());
|
|
95357
|
+
return actions;
|
|
95358
|
+
}
|
|
95359
|
+
function instrumentStdin(stdin) {
|
|
95360
|
+
const target = stdin;
|
|
95361
|
+
const restores = [];
|
|
95362
|
+
const wrap = (method, describe = () => ({})) => {
|
|
95363
|
+
const original = target[method];
|
|
95364
|
+
if (typeof original !== "function") {
|
|
95365
|
+
return;
|
|
95366
|
+
}
|
|
95367
|
+
const fn = original;
|
|
95368
|
+
target[method] = function(...args) {
|
|
95369
|
+
debugEvent(`stdin.${method}`, { ...describe(args), before: stdinSnapshot(stdin), stack: callerStack() });
|
|
95370
|
+
return fn.apply(this, args);
|
|
95371
|
+
};
|
|
95372
|
+
restores.push(() => {
|
|
95373
|
+
target[method] = original;
|
|
95374
|
+
});
|
|
95375
|
+
};
|
|
95376
|
+
const eventName = (args) => ({ event: String(args[0]) });
|
|
95377
|
+
wrap("pause");
|
|
95378
|
+
wrap("resume");
|
|
95379
|
+
wrap("setRawMode", (args) => ({ mode: args[0] }));
|
|
95380
|
+
wrap("removeListener", eventName);
|
|
95381
|
+
wrap("off", eventName);
|
|
95382
|
+
wrap("removeAllListeners", eventName);
|
|
95383
|
+
wrap("destroy");
|
|
95384
|
+
wrap("unref");
|
|
95385
|
+
wrap("unpipe");
|
|
95386
|
+
wrap("setEncoding", (args) => ({ encoding: args[0] }));
|
|
95387
|
+
const lifecycle = [];
|
|
95388
|
+
for (const event of ["end", "close", "error", "pause", "resume"]) {
|
|
95389
|
+
const handler = (...args) => {
|
|
95390
|
+
debugEvent(`stdin.event.${event}`, { args: args.map((a) => a instanceof Error ? a : String(a)), state: stdinSnapshot(stdin) });
|
|
95391
|
+
};
|
|
95392
|
+
lifecycle.push([event, handler]);
|
|
95393
|
+
}
|
|
95394
|
+
const onData = (chunk) => {
|
|
95395
|
+
debugEvent("stdin.data", summarizeInputChunk(chunk));
|
|
95396
|
+
};
|
|
95397
|
+
lifecycle.push(["data", onData]);
|
|
95398
|
+
for (const [event, handler] of lifecycle) {
|
|
95399
|
+
if (event === "error" && stdin.listenerCount("error") === 0) {
|
|
95400
|
+
continue;
|
|
95401
|
+
}
|
|
95402
|
+
stdin.on(event, handler);
|
|
95403
|
+
}
|
|
95404
|
+
debugEvent("stdin.instrumented", { state: stdinSnapshot(stdin) });
|
|
95405
|
+
return () => {
|
|
95406
|
+
for (const restore of restores)
|
|
95407
|
+
restore();
|
|
95408
|
+
for (const [event, handler] of lifecycle)
|
|
95409
|
+
stdin.off?.(event, handler);
|
|
95410
|
+
};
|
|
95411
|
+
}
|
|
95412
|
+
function startStdinHeartbeat(stdin, opts = {}) {
|
|
95413
|
+
const intervalMs = opts.intervalMs ?? 1000;
|
|
95414
|
+
const cooldownMs = opts.cooldownMs ?? 1e4;
|
|
95415
|
+
let lastRecovery = 0;
|
|
95416
|
+
const timer = setInterval(() => {
|
|
95417
|
+
const state = stdinSnapshot(stdin);
|
|
95418
|
+
const stalled = stdinLooksStalled(state);
|
|
95419
|
+
debugEvent("heartbeat", { stdin: state, stalled, ...opts.extra?.() ?? {} });
|
|
95420
|
+
if (stalled && (opts.shouldRecover?.() ?? true) && Date.now() - lastRecovery > cooldownMs) {
|
|
95421
|
+
lastRecovery = Date.now();
|
|
95422
|
+
const actions = recoverStdin(stdin, { cycle: true });
|
|
95423
|
+
debugEvent("stdin.stall.recovered-in-process", { before: state, actions, after: stdinSnapshot(stdin) });
|
|
95424
|
+
}
|
|
95425
|
+
}, intervalMs);
|
|
95426
|
+
timer.unref?.();
|
|
95427
|
+
return () => clearInterval(timer);
|
|
95428
|
+
}
|
|
95429
|
+
function installInputRecoverySignal(stdin, onRecovered, shouldRecover = () => true) {
|
|
95430
|
+
if (process.platform === "win32") {
|
|
95431
|
+
return () => {};
|
|
95432
|
+
}
|
|
95433
|
+
const handler = () => {
|
|
95434
|
+
if (!shouldRecover()) {
|
|
95435
|
+
debugEvent("signal.SIGUSR2.skipped", { reason: "renderer suspended or destroyed", stdin: stdinSnapshot(stdin) });
|
|
95436
|
+
return;
|
|
95437
|
+
}
|
|
95438
|
+
const before = stdinSnapshot(stdin);
|
|
95439
|
+
const actions = recoverStdin(stdin, { cycle: true });
|
|
95440
|
+
const after = stdinSnapshot(stdin);
|
|
95441
|
+
debugEvent("signal.SIGUSR2.recover", { before, actions, after, debug: isDebugEnabled() });
|
|
95442
|
+
try {
|
|
95443
|
+
onRecovered?.(actions);
|
|
95444
|
+
} catch {}
|
|
95445
|
+
};
|
|
95446
|
+
process.on("SIGUSR2", handler);
|
|
95447
|
+
return () => {
|
|
95448
|
+
process.off("SIGUSR2", handler);
|
|
95449
|
+
};
|
|
95450
|
+
}
|
|
95451
|
+
|
|
95452
|
+
// src/tui/renderer-debug.ts
|
|
95453
|
+
function attachRendererGuards(r, stdin = process.stdin) {
|
|
95454
|
+
const internals = r;
|
|
95455
|
+
registerRendererInputListener(internals.stdinListener);
|
|
95456
|
+
const shouldRecover = () => !r.isDestroyed && internals.controlState !== "explicit_suspended";
|
|
95457
|
+
const teardown = [];
|
|
95458
|
+
teardown.push(installInputRecoverySignal(stdin, () => {
|
|
95459
|
+
r.requestRender();
|
|
95460
|
+
}, shouldRecover));
|
|
95461
|
+
teardown.push(() => registerRendererInputListener(undefined));
|
|
95462
|
+
if (!isDebugEnabled()) {
|
|
95463
|
+
return () => {
|
|
95464
|
+
for (const fn of teardown.splice(0))
|
|
95465
|
+
fn();
|
|
95466
|
+
};
|
|
95467
|
+
}
|
|
95468
|
+
debugEvent("renderer.created", {
|
|
95469
|
+
controlState: internals.controlState,
|
|
95470
|
+
width: r.width,
|
|
95471
|
+
height: r.height,
|
|
95472
|
+
hasStdinListener: internals.stdinListener !== undefined
|
|
95473
|
+
});
|
|
95474
|
+
teardown.push(instrumentStdin(stdin));
|
|
95475
|
+
teardown.push(startStdinHeartbeat(stdin, {
|
|
95476
|
+
shouldRecover,
|
|
95477
|
+
extra: () => ({
|
|
95478
|
+
controlState: internals.controlState,
|
|
95479
|
+
focused: internals.currentFocusedRenderable?.id
|
|
95480
|
+
})
|
|
95481
|
+
}));
|
|
95482
|
+
const onKey = (key) => {
|
|
95483
|
+
const printable = key.sequence.length === 1 && key.sequence >= " " && !key.ctrl && !key.meta;
|
|
95484
|
+
queueMicrotask(() => {
|
|
95485
|
+
debugEvent("key", {
|
|
95486
|
+
name: printable ? "<printable>" : key.name,
|
|
95487
|
+
ctrl: key.ctrl,
|
|
95488
|
+
meta: key.meta,
|
|
95489
|
+
shift: key.shift,
|
|
95490
|
+
prevented: key.defaultPrevented,
|
|
95491
|
+
stopped: key.propagationStopped,
|
|
95492
|
+
focused: internals.currentFocusedRenderable?.id
|
|
95493
|
+
});
|
|
95494
|
+
});
|
|
95495
|
+
};
|
|
95496
|
+
internals._internalKeyInput?.onInternal("keypress", onKey);
|
|
95497
|
+
teardown.push(() => internals._internalKeyInput?.offInternal("keypress", onKey));
|
|
95498
|
+
const emitter = r;
|
|
95499
|
+
for (const event of ["resize", "focus", "blur", "capabilities"]) {
|
|
95500
|
+
const fn = (...args) => {
|
|
95501
|
+
debugEvent(`renderer.${event}`, event === "capabilities" ? {} : { args: args.map(String) });
|
|
95502
|
+
};
|
|
95503
|
+
emitter.on?.(event, fn);
|
|
95504
|
+
teardown.push(() => emitter.off?.(event, fn));
|
|
95505
|
+
}
|
|
95506
|
+
const target = r;
|
|
95507
|
+
for (const method of ["suspend", "resume", "pause", "stop", "destroy"]) {
|
|
95508
|
+
const original = target[method];
|
|
95509
|
+
if (typeof original !== "function")
|
|
95510
|
+
continue;
|
|
95511
|
+
const fn = original;
|
|
95512
|
+
target[method] = function(...args) {
|
|
95513
|
+
debugEvent(`renderer.${method}`, { controlState: internals.controlState, stack: callerStack() });
|
|
95514
|
+
return fn.apply(this, args);
|
|
95515
|
+
};
|
|
95516
|
+
teardown.push(() => {
|
|
95517
|
+
target[method] = original;
|
|
95518
|
+
});
|
|
95519
|
+
}
|
|
95520
|
+
return () => {
|
|
95521
|
+
debugEvent("renderer.teardown");
|
|
95522
|
+
for (const fn of teardown.splice(0)) {
|
|
95523
|
+
try {
|
|
95524
|
+
fn();
|
|
95525
|
+
} catch {}
|
|
95526
|
+
}
|
|
95527
|
+
};
|
|
95528
|
+
}
|
|
95529
|
+
|
|
94830
95530
|
// src/tui/shell-chrome.ts
|
|
94831
95531
|
function onKeypress3(r, handler) {
|
|
94832
95532
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
@@ -94932,14 +95632,20 @@ function prefixFilter(commands, query) {
|
|
|
94932
95632
|
return commands.filter((c) => c.name.slice(1).toLowerCase().startsWith(needle));
|
|
94933
95633
|
}
|
|
94934
95634
|
async function createShellRenderer(otui, opts = {}) {
|
|
94935
|
-
|
|
95635
|
+
const guards = {};
|
|
95636
|
+
const renderer = await otui.createCliRenderer({
|
|
94936
95637
|
exitOnCtrlC: true,
|
|
94937
95638
|
screenMode: "alternate-screen",
|
|
94938
95639
|
clearOnShutdown: true,
|
|
94939
95640
|
useMouse: true,
|
|
94940
95641
|
backgroundColor: getTheme().bg,
|
|
94941
|
-
|
|
95642
|
+
onDestroy: () => {
|
|
95643
|
+
guards.detach?.();
|
|
95644
|
+
opts.onDestroy?.();
|
|
95645
|
+
}
|
|
94942
95646
|
});
|
|
95647
|
+
guards.detach = attachRendererGuards(renderer);
|
|
95648
|
+
return renderer;
|
|
94943
95649
|
}
|
|
94944
95650
|
async function createShellChrome(otui, renderer, opts) {
|
|
94945
95651
|
const r = renderer;
|
|
@@ -95102,10 +95808,12 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
95102
95808
|
};
|
|
95103
95809
|
const withOverlay = async (run) => {
|
|
95104
95810
|
overlayDepth += 1;
|
|
95811
|
+
debugEvent("overlay.enter", { depth: overlayDepth, dockVisible: dock.visible });
|
|
95105
95812
|
try {
|
|
95106
95813
|
return await run();
|
|
95107
95814
|
} finally {
|
|
95108
95815
|
overlayDepth -= 1;
|
|
95816
|
+
debugEvent("overlay.exit", { depth: overlayDepth, dockVisible: dock.visible });
|
|
95109
95817
|
}
|
|
95110
95818
|
};
|
|
95111
95819
|
const addOverlaySource = (isActive) => {
|
|
@@ -95353,7 +96061,12 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
95353
96061
|
}
|
|
95354
96062
|
});
|
|
95355
96063
|
textarea.onSubmit = () => {
|
|
96064
|
+
if (overlayActive()) {
|
|
96065
|
+
debugEvent("composer.submit-blocked", { reason: "overlay active", dockVisible: dock.visible, overlayDepth });
|
|
96066
|
+
return;
|
|
96067
|
+
}
|
|
95356
96068
|
const line = input.value.trim();
|
|
96069
|
+
debugEvent("composer.submit", { chars: line.length, slash: line.startsWith("/") });
|
|
95357
96070
|
input.value = "";
|
|
95358
96071
|
hideMenu();
|
|
95359
96072
|
syncComposerHeight();
|
|
@@ -95471,6 +96184,15 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
95471
96184
|
appliedTheme = theme;
|
|
95472
96185
|
};
|
|
95473
96186
|
const unsubTheme = onThemeChange((theme) => applyTheme(theme));
|
|
96187
|
+
{
|
|
96188
|
+
const run = currentDebugRun();
|
|
96189
|
+
if (run !== undefined) {
|
|
96190
|
+
setTimeout(() => {
|
|
96191
|
+
if (alive)
|
|
96192
|
+
showToast(`debug log: ${run.dir}`);
|
|
96193
|
+
}, 0);
|
|
96194
|
+
}
|
|
96195
|
+
}
|
|
95474
96196
|
return {
|
|
95475
96197
|
renderer: r,
|
|
95476
96198
|
root: rootRow,
|
|
@@ -98035,6 +98757,7 @@ function attachBlockIo(io, addBlock, chrome = {}, thinkDisplay = () => "auto") {
|
|
|
98035
98757
|
});
|
|
98036
98758
|
};
|
|
98037
98759
|
io.onToolCall = (name, input) => {
|
|
98760
|
+
debugEvent("tool.call", { name, inputChars: input.length });
|
|
98038
98761
|
chrome.onToolCall?.(name, input);
|
|
98039
98762
|
const args = summarizeToolArgs(input);
|
|
98040
98763
|
addBlock({
|
|
@@ -98046,6 +98769,7 @@ function attachBlockIo(io, addBlock, chrome = {}, thinkDisplay = () => "auto") {
|
|
|
98046
98769
|
}, { hint: "ctrl+o", tone: "cyan" });
|
|
98047
98770
|
};
|
|
98048
98771
|
io.onToolResult = (name, result) => {
|
|
98772
|
+
debugEvent("tool.result", { name, isError: result.isError === true, outputChars: result.output.length });
|
|
98049
98773
|
chrome.onToolResult?.(name, result);
|
|
98050
98774
|
const { summary, lineCount, hidden } = collapseToolOutput(result.output);
|
|
98051
98775
|
const more = hidden > 0 ? ` \xB7 +${hidden} more` : "";
|
|
@@ -98148,7 +98872,7 @@ function createApprovalContextLoader(cwd) {
|
|
|
98148
98872
|
return buildApprovalContext(port, command);
|
|
98149
98873
|
};
|
|
98150
98874
|
}
|
|
98151
|
-
async function pickShellApproval(otui, r, dock, command, loadContext, destructive = false, credentials = false) {
|
|
98875
|
+
async function pickShellApproval(otui, r, dock, command, loadContext, destructive = false, credentials = false, ui = {}) {
|
|
98152
98876
|
let context;
|
|
98153
98877
|
try {
|
|
98154
98878
|
context = loadContext(command);
|
|
@@ -98188,7 +98912,9 @@ async function pickShellApproval(otui, r, dock, command, loadContext, destructiv
|
|
|
98188
98912
|
subtitle: command,
|
|
98189
98913
|
...context !== undefined ? { context } : {},
|
|
98190
98914
|
cancelId: "deny",
|
|
98191
|
-
options
|
|
98915
|
+
options,
|
|
98916
|
+
...ui.onOpen !== undefined ? { onOpen: ui.onOpen } : {},
|
|
98917
|
+
...ui.signal !== undefined ? { signal: ui.signal } : {}
|
|
98192
98918
|
});
|
|
98193
98919
|
if (id === "once" || id === "always-exact" || id === "always-prefix" || id === "deny") {
|
|
98194
98920
|
return id;
|
|
@@ -98211,6 +98937,9 @@ async function applyRuntimeSwitchToSlate(params) {
|
|
|
98211
98937
|
params.onHistoryChange?.("tool");
|
|
98212
98938
|
return true;
|
|
98213
98939
|
}
|
|
98940
|
+
function freshSlateSessionRef(sessionDir, cwd) {
|
|
98941
|
+
return { dir: sessionDir, cwd, opened: false };
|
|
98942
|
+
}
|
|
98214
98943
|
function fmtTokens(n) {
|
|
98215
98944
|
return n >= 1000 ? `${(n / 1000).toFixed(1)}K` : String(n);
|
|
98216
98945
|
}
|
|
@@ -99351,6 +100080,7 @@ async function launchTuiAgentShell(opts) {
|
|
|
99351
100080
|
let busyStartedAt = 0;
|
|
99352
100081
|
const setBusyPhase = (phase) => {
|
|
99353
100082
|
busyPhase = phase;
|
|
100083
|
+
debugEvent("busy.phase", { phase });
|
|
99354
100084
|
chrome.setBusyPhase(phase);
|
|
99355
100085
|
};
|
|
99356
100086
|
const startBusy = (phase = "waiting for model") => {
|
|
@@ -99533,10 +100263,12 @@ async function launchTuiAgentShell(opts) {
|
|
|
99533
100263
|
chrome.hideMenu();
|
|
99534
100264
|
setMainAgent("blocked", "approval");
|
|
99535
100265
|
const preview = request.task.length > 80 ? `${request.task.slice(0, 77)}\u2026` : request.task;
|
|
99536
|
-
const id = await showComposerChoice(otui, r, chrome.dock, {
|
|
100266
|
+
const id = await chrome.withOverlay(() => showComposerChoice(otui, r, chrome.dock, {
|
|
99537
100267
|
title: `Run the external agent ${request.agentId}?`,
|
|
99538
100268
|
subtitle: preview,
|
|
99539
100269
|
cancelId: "deny",
|
|
100270
|
+
onOpen: () => chrome.blurComposer(),
|
|
100271
|
+
signal: foregroundOperation.signal,
|
|
99540
100272
|
options: [
|
|
99541
100273
|
{
|
|
99542
100274
|
id: "allow",
|
|
@@ -99545,7 +100277,7 @@ async function launchTuiAgentShell(opts) {
|
|
|
99545
100277
|
},
|
|
99546
100278
|
{ id: "deny", label: "Deny", description: "Do not start the external agent" }
|
|
99547
100279
|
]
|
|
99548
|
-
});
|
|
100280
|
+
}));
|
|
99549
100281
|
input.focus();
|
|
99550
100282
|
setMainAgent("running", id === "allow" ? "external" : "denied");
|
|
99551
100283
|
return id === "allow" ? { ok: true } : { ok: false, reason: `you declined the external spawn of ${request.agentId}` };
|
|
@@ -99571,6 +100303,7 @@ async function launchTuiAgentShell(opts) {
|
|
|
99571
100303
|
})();
|
|
99572
100304
|
};
|
|
99573
100305
|
const setMainAgent = (status, detail) => {
|
|
100306
|
+
debugEvent("main-agent", { status, detail });
|
|
99574
100307
|
fleet.upsert({
|
|
99575
100308
|
id: MAIN_AGENT_ID,
|
|
99576
100309
|
label: "main",
|
|
@@ -99716,10 +100449,12 @@ async function launchTuiAgentShell(opts) {
|
|
|
99716
100449
|
}
|
|
99717
100450
|
chrome.hideMenu();
|
|
99718
100451
|
setMainAgent("blocked", "approval");
|
|
99719
|
-
const id = await showComposerChoice(otui, r, chrome.dock, {
|
|
100452
|
+
const id = await chrome.withOverlay(() => showComposerChoice(otui, r, chrome.dock, {
|
|
99720
100453
|
title: "Spawn general subagent?",
|
|
99721
100454
|
subtitle: taskPreview,
|
|
99722
100455
|
cancelId: "deny",
|
|
100456
|
+
onOpen: () => chrome.blurComposer(),
|
|
100457
|
+
signal: foregroundOperation.signal,
|
|
99723
100458
|
options: [
|
|
99724
100459
|
{
|
|
99725
100460
|
id: "allow",
|
|
@@ -99729,7 +100464,7 @@ async function launchTuiAgentShell(opts) {
|
|
|
99729
100464
|
},
|
|
99730
100465
|
{ id: "deny", label: "Deny", description: "Do not spawn" }
|
|
99731
100466
|
]
|
|
99732
|
-
});
|
|
100467
|
+
}));
|
|
99733
100468
|
input.focus();
|
|
99734
100469
|
setMainAgent("running", id === "allow" ? "subagent" : "denied");
|
|
99735
100470
|
transcript.add(new otui.TextRenderable(r, {
|
|
@@ -99758,15 +100493,17 @@ async function launchTuiAgentShell(opts) {
|
|
|
99758
100493
|
}
|
|
99759
100494
|
chrome.hideMenu();
|
|
99760
100495
|
setMainAgent("blocked", "approval");
|
|
99761
|
-
const id = await showComposerChoice(otui, r, chrome.dock, {
|
|
100496
|
+
const id = await chrome.withOverlay(() => showComposerChoice(otui, r, chrome.dock, {
|
|
99762
100497
|
title: "Approve apply_patch?",
|
|
99763
100498
|
subtitle: "Diff shown above \xB7 Esc denies",
|
|
99764
100499
|
cancelId: "deny",
|
|
100500
|
+
onOpen: () => chrome.blurComposer(),
|
|
100501
|
+
signal: foregroundOperation.signal,
|
|
99765
100502
|
options: [
|
|
99766
100503
|
{ id: "allow", label: "Approve", description: "Write the patch to disk", recommended: true },
|
|
99767
100504
|
{ id: "deny", label: "Deny", description: "Do not write anything" }
|
|
99768
100505
|
]
|
|
99769
|
-
});
|
|
100506
|
+
}));
|
|
99770
100507
|
input.focus();
|
|
99771
100508
|
setMainAgent("running", id === "allow" ? "write" : "denied");
|
|
99772
100509
|
transcript.add(new otui.TextRenderable(r, {
|
|
@@ -99792,15 +100529,17 @@ async function launchTuiAgentShell(opts) {
|
|
|
99792
100529
|
}
|
|
99793
100530
|
chrome.hideMenu();
|
|
99794
100531
|
setMainAgent("blocked", "approval");
|
|
99795
|
-
const id = await showComposerChoice(otui, r, chrome.dock, {
|
|
100532
|
+
const id = await chrome.withOverlay(() => showComposerChoice(otui, r, chrome.dock, {
|
|
99796
100533
|
title: described.title,
|
|
99797
100534
|
subtitle: summariseUseToolApproval(described),
|
|
99798
100535
|
cancelId: "deny",
|
|
100536
|
+
onOpen: () => chrome.blurComposer(),
|
|
100537
|
+
signal: foregroundOperation.signal,
|
|
99799
100538
|
options: [
|
|
99800
100539
|
{ id: APPROVAL_ALLOW_ID, label: "Approve", description: `run ${described.tool} on ${described.server}` },
|
|
99801
100540
|
{ id: "deny", label: "Deny", description: "the tool call is refused", recommended: true }
|
|
99802
100541
|
]
|
|
99803
|
-
});
|
|
100542
|
+
}));
|
|
99804
100543
|
input.focus();
|
|
99805
100544
|
const allowed = isDockApproval(id);
|
|
99806
100545
|
setMainAgent("running", allowed ? "write" : "denied");
|
|
@@ -99838,15 +100577,17 @@ async function launchTuiAgentShell(opts) {
|
|
|
99838
100577
|
chrome.hideMenu();
|
|
99839
100578
|
setMainAgent("blocked", "approval");
|
|
99840
100579
|
const elicitationSubtitle = described.message.length > 80 ? `${described.message.slice(0, 77)}\u2026` : described.message;
|
|
99841
|
-
const id = await showComposerChoice(otui, r, chrome.dock, {
|
|
100580
|
+
const id = await chrome.withOverlay(() => showComposerChoice(otui, r, chrome.dock, {
|
|
99842
100581
|
title: "Approve codex elicitation?",
|
|
99843
100582
|
subtitle: elicitationSubtitle,
|
|
99844
100583
|
cancelId: "deny",
|
|
100584
|
+
onOpen: () => chrome.blurComposer(),
|
|
100585
|
+
signal: foregroundOperation.signal,
|
|
99845
100586
|
options: [
|
|
99846
100587
|
{ id: "allow", label: "Approve", description: "codex proceeds with this action", recommended: true },
|
|
99847
100588
|
{ id: "deny", label: "Deny", description: "codex's action is refused" }
|
|
99848
100589
|
]
|
|
99849
|
-
});
|
|
100590
|
+
}));
|
|
99850
100591
|
input.focus();
|
|
99851
100592
|
setMainAgent("running", id === "allow" ? "write" : "denied");
|
|
99852
100593
|
transcript.add(new otui.TextRenderable(r, {
|
|
@@ -99901,7 +100642,10 @@ async function launchTuiAgentShell(opts) {
|
|
|
99901
100642
|
setMainAgent("blocked", "approval");
|
|
99902
100643
|
setBusyPhase("waiting for your approval (menu above input)");
|
|
99903
100644
|
chrome.hideMenu();
|
|
99904
|
-
const choice = await pickShellApproval(otui, r, chrome.dock, cmd, approvalContext, destructive, meta?.credentials === true
|
|
100645
|
+
const choice = await chrome.withOverlay(() => pickShellApproval(otui, r, chrome.dock, cmd, approvalContext, destructive, meta?.credentials === true, {
|
|
100646
|
+
onOpen: () => chrome.blurComposer(),
|
|
100647
|
+
signal: foregroundOperation.signal
|
|
100648
|
+
}));
|
|
99905
100649
|
input.focus();
|
|
99906
100650
|
if (choice === "deny") {
|
|
99907
100651
|
transcript.add(new otui.TextRenderable(r, {
|
|
@@ -99945,17 +100689,19 @@ async function launchTuiAgentShell(opts) {
|
|
|
99945
100689
|
id: `ask${uid++}`,
|
|
99946
100690
|
content: otui.t`${otui.yellow("? ")} ${otui.dim(qShort)}`
|
|
99947
100691
|
}));
|
|
99948
|
-
const chosen = await showComposerChoice(otui, r, chrome.dock, {
|
|
100692
|
+
const chosen = await chrome.withOverlay(() => showComposerChoice(otui, r, chrome.dock, {
|
|
99949
100693
|
title: req.question.length > 72 ? `${req.question.slice(0, 69)}\u2026` : req.question,
|
|
99950
100694
|
subtitle: "Pick an option \xB7 Esc cancels",
|
|
99951
100695
|
cancelId: "__cancel__",
|
|
100696
|
+
onOpen: () => chrome.blurComposer(),
|
|
100697
|
+
signal: foregroundOperation.signal,
|
|
99952
100698
|
options: req.options.map((o) => ({
|
|
99953
100699
|
id: o.id,
|
|
99954
100700
|
label: o.label,
|
|
99955
100701
|
description: o.description.length > 0 ? o.description : " ",
|
|
99956
100702
|
...o.recommended === true ? { recommended: true } : {}
|
|
99957
100703
|
}))
|
|
99958
|
-
});
|
|
100704
|
+
}));
|
|
99959
100705
|
input.focus();
|
|
99960
100706
|
if (chosen !== "__cancel__") {
|
|
99961
100707
|
const picked = req.options.find((o) => o.id === chosen);
|
|
@@ -100003,6 +100749,9 @@ async function launchTuiAgentShell(opts) {
|
|
|
100003
100749
|
let nextArchiveIndex = 0;
|
|
100004
100750
|
let sessionPersistTimer;
|
|
100005
100751
|
let slateSession;
|
|
100752
|
+
const bindSlateToLiveSession = () => {
|
|
100753
|
+
slateSession = freshSlateSessionRef(liveSession.dir, sessionCwd);
|
|
100754
|
+
};
|
|
100006
100755
|
const onContextCompaction = (r) => {
|
|
100007
100756
|
const persisted = persistCompacted(liveSession, r.context, archive, {
|
|
100008
100757
|
provider: currentSel.provider,
|
|
@@ -100136,7 +100885,7 @@ async function launchTuiAgentShell(opts) {
|
|
|
100136
100885
|
model: currentSel.model
|
|
100137
100886
|
}));
|
|
100138
100887
|
}
|
|
100139
|
-
|
|
100888
|
+
bindSlateToLiveSession();
|
|
100140
100889
|
if (history.length === 0) {
|
|
100141
100890
|
removeSplash = mountEmptyTranscriptSplash(otui, r, transcript);
|
|
100142
100891
|
}
|
|
@@ -100237,6 +100986,8 @@ Staying in the current session.
|
|
|
100237
100986
|
return;
|
|
100238
100987
|
}
|
|
100239
100988
|
applyOpened(opened, true);
|
|
100989
|
+
bindSlateToLiveSession();
|
|
100990
|
+
refreshWorkspaceSidebar();
|
|
100240
100991
|
paintSessionHeader();
|
|
100241
100992
|
if (opened.archiveDegraded !== undefined) {
|
|
100242
100993
|
io.onSystem?.(`Archive unavailable \u2014 resumed from the active context (${opened.archiveDegraded})
|
|
@@ -100417,14 +101168,15 @@ Staying in the current session.
|
|
|
100417
101168
|
title: "Switch to auto mode?",
|
|
100418
101169
|
subtitle: "Skips confirmation for EVERY action, including destructive commands. Only credential-touching commands still ask.",
|
|
100419
101170
|
cancelId: "cancel",
|
|
100420
|
-
|
|
100421
|
-
{ id: "confirm", label: "Confirm", description: "I understand the risk" },
|
|
100422
|
-
{ id: "cancel", label: "Cancel", description: "Keep the current mode", recommended: true }
|
|
100423
|
-
],
|
|
101171
|
+
enqueue: false,
|
|
100424
101172
|
onBusy: () => {
|
|
100425
101173
|
blockedByOpenDialog = true;
|
|
100426
101174
|
chrome.showToast("Answer the open approval first, then retry /mode.");
|
|
100427
|
-
}
|
|
101175
|
+
},
|
|
101176
|
+
options: [
|
|
101177
|
+
{ id: "confirm", label: "Confirm", description: "I understand the risk" },
|
|
101178
|
+
{ id: "cancel", label: "Cancel", description: "Keep the current mode", recommended: true }
|
|
101179
|
+
]
|
|
100428
101180
|
}));
|
|
100429
101181
|
input.focus();
|
|
100430
101182
|
if (blockedByOpenDialog) {
|
|
@@ -100465,16 +101217,17 @@ Staying in the current session.
|
|
|
100465
101217
|
title: `Permission mode (current: ${permissionMode})`,
|
|
100466
101218
|
subtitle: stored !== undefined ? `Project default: ${stored}` : "No project default set.",
|
|
100467
101219
|
cancelId: permissionMode,
|
|
101220
|
+
enqueue: false,
|
|
101221
|
+
onBusy: () => {
|
|
101222
|
+
blockedByOpenDialog = true;
|
|
101223
|
+
chrome.showToast("Answer the open approval first, then retry /mode.");
|
|
101224
|
+
},
|
|
100468
101225
|
options: PERMISSION_MODES.map((m) => ({
|
|
100469
101226
|
id: m,
|
|
100470
101227
|
label: m,
|
|
100471
101228
|
description: MODE_PICKER_DESCRIPTIONS[m],
|
|
100472
101229
|
recommended: m === permissionMode
|
|
100473
|
-
}))
|
|
100474
|
-
onBusy: () => {
|
|
100475
|
-
blockedByOpenDialog = true;
|
|
100476
|
-
chrome.showToast("Answer the open approval first, then retry /mode.");
|
|
100477
|
-
}
|
|
101230
|
+
}))
|
|
100478
101231
|
}));
|
|
100479
101232
|
input.focus();
|
|
100480
101233
|
if (blockedByOpenDialog) {
|
|
@@ -101067,6 +101820,7 @@ Staying in the current session.
|
|
|
101067
101820
|
{ id: "side", label: "Side-1", description: "read-only answer, outside main history (as before)" }
|
|
101068
101821
|
],
|
|
101069
101822
|
cancelId: "side",
|
|
101823
|
+
enqueue: false,
|
|
101070
101824
|
onBusy: () => {
|
|
101071
101825
|
blockedByOpenDialog = true;
|
|
101072
101826
|
chrome.showToast("Answer the open approval first, then resend.");
|
|
@@ -101132,7 +101886,7 @@ Staying in the current session.
|
|
|
101132
101886
|
(async () => {
|
|
101133
101887
|
await closeSlateSession(slateSession, mintTimestampAttemptId);
|
|
101134
101888
|
startNewSession();
|
|
101135
|
-
|
|
101889
|
+
bindSlateToLiveSession();
|
|
101136
101890
|
refreshWorkspaceSidebar();
|
|
101137
101891
|
refreshReviewSidebar();
|
|
101138
101892
|
sessions.clear();
|
|
@@ -103564,6 +104318,7 @@ function parseShellCliFlags(args) {
|
|
|
103564
104318
|
let printPromptArg;
|
|
103565
104319
|
let eventsFile;
|
|
103566
104320
|
let eventsMaxField;
|
|
104321
|
+
let debug;
|
|
103567
104322
|
for (let i = 0;i < args.length; i++) {
|
|
103568
104323
|
const arg = args[i];
|
|
103569
104324
|
if (arg === "--provider") {
|
|
@@ -103614,6 +104369,8 @@ function parseShellCliFlags(args) {
|
|
|
103614
104369
|
i += 1;
|
|
103615
104370
|
} else if (arg === "--events-file") {
|
|
103616
104371
|
eventsFile = valueAfter(i++);
|
|
104372
|
+
} else if (arg === "--debug") {
|
|
104373
|
+
debug = true;
|
|
103617
104374
|
} else if (arg === "--events-max-field") {
|
|
103618
104375
|
const raw = valueAfter(i++);
|
|
103619
104376
|
const parsed = Number(raw);
|
|
@@ -103643,7 +104400,8 @@ function parseShellCliFlags(args) {
|
|
|
103643
104400
|
...denyTools !== undefined ? { denyTools } : {},
|
|
103644
104401
|
...printPromptArg !== undefined ? { printPrompt: printPromptArg } : {},
|
|
103645
104402
|
...eventsFile !== undefined ? { eventsFile } : {},
|
|
103646
|
-
...eventsMaxField !== undefined ? { eventsMaxField } : {}
|
|
104403
|
+
...eventsMaxField !== undefined ? { eventsMaxField } : {},
|
|
104404
|
+
...debug === true ? { debug: true } : {}
|
|
103647
104405
|
};
|
|
103648
104406
|
}
|
|
103649
104407
|
function chooseShellSurface(flags, isTty) {
|
|
@@ -103656,6 +104414,11 @@ function chooseShellSurface(flags, isTty) {
|
|
|
103656
104414
|
return flags.modeFlag === false ? "tui-chat" : "tui-agent";
|
|
103657
104415
|
}
|
|
103658
104416
|
async function shellCommand(args, runtime = {}) {
|
|
104417
|
+
if (args[0] === "--debug-watcher") {
|
|
104418
|
+
await Promise.resolve().then(() => init_debug_watcher());
|
|
104419
|
+
await runDebugWatcher(args.slice(1));
|
|
104420
|
+
return;
|
|
104421
|
+
}
|
|
103659
104422
|
const flags = parseShellCliFlags(args);
|
|
103660
104423
|
if (flags.help) {
|
|
103661
104424
|
console.log(`Usage: keryx shell [options]
|
|
@@ -103674,13 +104437,42 @@ async function shellCommand(args, runtime = {}) {
|
|
|
103674
104437
|
--print, -p <prompt> Run one agent turn on this prompt and exit
|
|
103675
104438
|
--events-file <path> Append an NDJSON transcript (turns, tools, usage)
|
|
103676
104439
|
--events-max-field <n> Per-field character cap in that transcript (default 4000)
|
|
104440
|
+
--debug Log the session (input, keys, dialogs, tools) and start a watcher
|
|
104441
|
+
that re-arms terminal input if it stops; see debug/latest.txt
|
|
103677
104442
|
|
|
103678
104443
|
Session continuation and resume are mutually exclusive. Permission flags
|
|
103679
104444
|
are ignored in chat mode. Without a TTY, resume without an ID uses the latest session.
|
|
103680
104445
|
|
|
104446
|
+
A shell that stops reacting to keys can be recovered from another terminal
|
|
104447
|
+
with: kill -USR2 <keryx pid>
|
|
104448
|
+
|
|
103681
104449
|
Example: keryx shell --provider ollama --model llama3.1:latest`);
|
|
103682
104450
|
return;
|
|
103683
104451
|
}
|
|
104452
|
+
if (flags.debug === true) {
|
|
104453
|
+
await Promise.resolve().then(() => init_debug_log());
|
|
104454
|
+
await Promise.resolve().then(() => init_debug_watcher());
|
|
104455
|
+
const run = startDebugRun(runtime.cacheDir !== undefined ? { configDir: runtime.cacheDir } : {});
|
|
104456
|
+
const watcherPid = spawnDebugWatcher(run);
|
|
104457
|
+
debugEvent("session.start", {
|
|
104458
|
+
version: package_default.version,
|
|
104459
|
+
argv: args,
|
|
104460
|
+
bun: typeof Bun !== "undefined" ? Bun.version : undefined,
|
|
104461
|
+
platform: process.platform,
|
|
104462
|
+
execPath: process.execPath,
|
|
104463
|
+
cwd: process.cwd(),
|
|
104464
|
+
stdinTTY: process.stdin.isTTY === true,
|
|
104465
|
+
stdoutTTY: process.stdout.isTTY === true,
|
|
104466
|
+
env: Object.fromEntries(["TERM", "TERM_PROGRAM", "COLORTERM", "TMUX", "HERDR_ENV", "HERDR_PANE_ID", "SSH_TTY", "LANG"].map((k) => [k, process.env[k]])),
|
|
104467
|
+
watcherPid,
|
|
104468
|
+
dir: run.dir
|
|
104469
|
+
});
|
|
104470
|
+
process.on("exit", (code) => {
|
|
104471
|
+
debugEvent("session.exit", { code });
|
|
104472
|
+
process.stderr.write(`keryx debug log: ${run.dir}
|
|
104473
|
+
`);
|
|
104474
|
+
});
|
|
104475
|
+
}
|
|
103684
104476
|
const versionCheck = (runtime.checkVersion ?? (() => checkVersion({
|
|
103685
104477
|
currentVersion: package_default.version,
|
|
103686
104478
|
...runtime.cacheDir !== undefined ? { cacheDir: runtime.cacheDir } : {}
|
|
@@ -104201,7 +104993,7 @@ Shell:
|
|
|
104201
104993
|
init_fs();
|
|
104202
104994
|
import { readFile as readFile99 } from "fs/promises";
|
|
104203
104995
|
import { stdin } from "process";
|
|
104204
|
-
import
|
|
104996
|
+
import path196 from "path";
|
|
104205
104997
|
var MODULES = [
|
|
104206
104998
|
{ name: "gdgraph", flag: "--no-gdgraph", desc: "code graph, symbols, affected context", defaultEnabled: true },
|
|
104207
104999
|
{ name: "gdctx", flag: "--no-gdctx", desc: "token-aware command/read output", defaultEnabled: true },
|
|
@@ -104247,8 +105039,8 @@ async function modulesCommand(args = []) {
|
|
|
104247
105039
|
return;
|
|
104248
105040
|
}
|
|
104249
105041
|
const wantsJson = args.includes("--json") && (sub === undefined || sub === "status" || sub === "list" || sub === "--json");
|
|
104250
|
-
const metaprojectRoot =
|
|
104251
|
-
const manifestPath =
|
|
105042
|
+
const metaprojectRoot = path196.join(process.cwd(), ".metaproject");
|
|
105043
|
+
const manifestPath = path196.join(metaprojectRoot, "metaproject.json");
|
|
104252
105044
|
if (!await pathExists(manifestPath)) {
|
|
104253
105045
|
if (wantsJson) {
|
|
104254
105046
|
console.log(JSON.stringify({ schemaVersion: 1, error: "not-initialized", modules: [] }, null, 2));
|
|
@@ -104370,18 +105162,18 @@ init_config_dir();
|
|
|
104370
105162
|
import { createHash as createHash44, randomBytes as randomBytes5, randomUUID as randomUUID30 } from "crypto";
|
|
104371
105163
|
import {
|
|
104372
105164
|
chmodSync as chmodSync4,
|
|
104373
|
-
closeSync as
|
|
105165
|
+
closeSync as closeSync4,
|
|
104374
105166
|
existsSync as existsSync34,
|
|
104375
105167
|
fsyncSync as fsyncSync2,
|
|
104376
|
-
openSync as
|
|
105168
|
+
openSync as openSync4,
|
|
104377
105169
|
renameSync as renameSync4,
|
|
104378
|
-
statSync as
|
|
105170
|
+
statSync as statSync7,
|
|
104379
105171
|
unlinkSync as unlinkSync3,
|
|
104380
105172
|
writeFileSync as writeFileSync9
|
|
104381
105173
|
} from "fs";
|
|
104382
|
-
import
|
|
105174
|
+
import path197 from "path";
|
|
104383
105175
|
function serveCredentialPath(dir) {
|
|
104384
|
-
return
|
|
105176
|
+
return path197.join(keryxConfigDir(dir), "serve-credentials.json");
|
|
104385
105177
|
}
|
|
104386
105178
|
function constantTimeEqual(a, b) {
|
|
104387
105179
|
const width = Math.max(a.length, b.length);
|
|
@@ -104410,7 +105202,7 @@ function isGroupOrOtherAccessible(file) {
|
|
|
104410
105202
|
if (process.platform === "win32") {
|
|
104411
105203
|
return false;
|
|
104412
105204
|
}
|
|
104413
|
-
const mode =
|
|
105205
|
+
const mode = statSync7(file, { throwIfNoEntry: false })?.mode;
|
|
104414
105206
|
return mode !== undefined && (mode & 63) !== 0;
|
|
104415
105207
|
}
|
|
104416
105208
|
function readServeCredential(dir) {
|
|
@@ -104454,13 +105246,13 @@ function writeStore(store, dir) {
|
|
|
104454
105246
|
const temp = `${file}.${randomUUID30()}.tmp`;
|
|
104455
105247
|
try {
|
|
104456
105248
|
ensureKeryxConfigDir(dir);
|
|
104457
|
-
const handle =
|
|
105249
|
+
const handle = openSync4(temp, "wx", 384);
|
|
104458
105250
|
try {
|
|
104459
105251
|
writeFileSync9(handle, `${JSON.stringify(store, null, 2)}
|
|
104460
105252
|
`, { encoding: "utf8" });
|
|
104461
105253
|
fsyncSync2(handle);
|
|
104462
105254
|
} finally {
|
|
104463
|
-
|
|
105255
|
+
closeSync4(handle);
|
|
104464
105256
|
}
|
|
104465
105257
|
renameSync4(temp, file);
|
|
104466
105258
|
tighten2(file, 384);
|
|
@@ -104614,23 +105406,23 @@ class AuthFailureThrottle {
|
|
|
104614
105406
|
// src/lib/serve-turn-store.ts
|
|
104615
105407
|
init_config_dir();
|
|
104616
105408
|
import { createHash as createHash45 } from "crypto";
|
|
104617
|
-
import { existsSync as existsSync35, readdirSync as
|
|
104618
|
-
import
|
|
105409
|
+
import { existsSync as existsSync35, readdirSync as readdirSync4, rmSync as rmSync2 } from "fs";
|
|
105410
|
+
import path198 from "path";
|
|
104619
105411
|
var MAX_TURN_EVENTS = 1e4;
|
|
104620
105412
|
function turnsRoot(dir) {
|
|
104621
|
-
return
|
|
105413
|
+
return path198.join(keryxConfigDir(dir), "turns");
|
|
104622
105414
|
}
|
|
104623
105415
|
function turnDir(turnId, dir) {
|
|
104624
|
-
return
|
|
105416
|
+
return path198.join(turnsRoot(dir), turnId);
|
|
104625
105417
|
}
|
|
104626
105418
|
function keyPath(project, idempotencyKey, dir) {
|
|
104627
105419
|
const projectBytes = Buffer.byteLength(project, "utf8");
|
|
104628
105420
|
const digest = createHash45("sha256").update(`${projectBytes}:${project}\x00${idempotencyKey}`, "utf8").digest("hex");
|
|
104629
|
-
return
|
|
105421
|
+
return path198.join(turnsRoot(dir), "keys", `${digest}.json`);
|
|
104630
105422
|
}
|
|
104631
105423
|
function legacyKeyPath(idempotencyKey, dir) {
|
|
104632
105424
|
const digest = createHash45("sha256").update(idempotencyKey, "utf8").digest("hex");
|
|
104633
|
-
return
|
|
105425
|
+
return path198.join(turnsRoot(dir), "keys", `${digest}.json`);
|
|
104634
105426
|
}
|
|
104635
105427
|
function adoptLegacyClaim(project, idempotencyKey, dir) {
|
|
104636
105428
|
const legacy = legacyKeyPath(idempotencyKey, dir);
|
|
@@ -104694,7 +105486,7 @@ function ensureTurnDir(turnId, dir) {
|
|
|
104694
105486
|
}
|
|
104695
105487
|
function createTurnRecord(record, dir) {
|
|
104696
105488
|
ensureTurnDir(record.turnId, dir);
|
|
104697
|
-
writeOwnerOnlyFile(
|
|
105489
|
+
writeOwnerOnlyFile(path198.join(turnDir(record.turnId, dir), "turn.json"), `${JSON.stringify(record, null, 2)}
|
|
104698
105490
|
`);
|
|
104699
105491
|
}
|
|
104700
105492
|
function appendTurnEvent(event, dir, opts) {
|
|
@@ -104703,12 +105495,12 @@ function appendTurnEvent(event, dir, opts) {
|
|
|
104703
105495
|
}
|
|
104704
105496
|
const line = JSON.stringify(event);
|
|
104705
105497
|
try {
|
|
104706
|
-
appendOwnerOnlyLine(
|
|
105498
|
+
appendOwnerOnlyLine(path198.join(turnDir(event.turnId, dir), "events.jsonl"), line);
|
|
104707
105499
|
} catch (error) {
|
|
104708
105500
|
if (error?.code !== "ENOENT") {
|
|
104709
105501
|
throw error;
|
|
104710
105502
|
}
|
|
104711
|
-
appendOwnerOnlyLine(
|
|
105503
|
+
appendOwnerOnlyLine(path198.join(ensureTurnDir(event.turnId, dir), "events.jsonl"), line);
|
|
104712
105504
|
}
|
|
104713
105505
|
return true;
|
|
104714
105506
|
}
|
|
@@ -104716,7 +105508,7 @@ function readTurnEvents(turnId, after = -1, dir) {
|
|
|
104716
105508
|
if (!isTurnId(turnId)) {
|
|
104717
105509
|
return { ok: false, reason: "not-a-turn-id" };
|
|
104718
105510
|
}
|
|
104719
|
-
const read = readTurnFile(
|
|
105511
|
+
const read = readTurnFile(path198.join(turnDir(turnId, dir), "events.jsonl"));
|
|
104720
105512
|
if (!read.ok) {
|
|
104721
105513
|
if (isDefiniteAbsence2(read.reason)) {
|
|
104722
105514
|
return { ok: true, value: [] };
|
|
@@ -104744,7 +105536,7 @@ function readTurnRecord(turnId, dir) {
|
|
|
104744
105536
|
if (!isTurnId(turnId)) {
|
|
104745
105537
|
return { ok: false, reason: "not-a-turn-id" };
|
|
104746
105538
|
}
|
|
104747
|
-
const read = readTurnFile(
|
|
105539
|
+
const read = readTurnFile(path198.join(turnDir(turnId, dir), "turn.json"));
|
|
104748
105540
|
if (!read.ok) {
|
|
104749
105541
|
return { ok: false, reason: read.reason };
|
|
104750
105542
|
}
|
|
@@ -104763,7 +105555,7 @@ function finishTurn(turnId, result, dir) {
|
|
|
104763
105555
|
if (!record.ok) {
|
|
104764
105556
|
return false;
|
|
104765
105557
|
}
|
|
104766
|
-
writeOwnerOnlyFile(
|
|
105558
|
+
writeOwnerOnlyFile(path198.join(turnDir(turnId, dir), "turn.json"), `${JSON.stringify({ ...record.value, result }, null, 2)}
|
|
104767
105559
|
`);
|
|
104768
105560
|
return true;
|
|
104769
105561
|
}
|
|
@@ -104809,7 +105601,7 @@ function releaseIdempotencyKey(project, idempotencyKey, turnId, dir) {
|
|
|
104809
105601
|
|
|
104810
105602
|
// src/lib/serve-turn.ts
|
|
104811
105603
|
import { randomUUID as randomUUID31 } from "crypto";
|
|
104812
|
-
import
|
|
105604
|
+
import path199 from "path";
|
|
104813
105605
|
init_service();
|
|
104814
105606
|
var REMOTE_ORIGIN = "remote:http";
|
|
104815
105607
|
var MAX_PROMPT_CHARS = 32000;
|
|
@@ -104878,9 +105670,9 @@ function isUuid(value) {
|
|
|
104878
105670
|
return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(value);
|
|
104879
105671
|
}
|
|
104880
105672
|
function resolveProject(declared, dir) {
|
|
104881
|
-
const wanted =
|
|
105673
|
+
const wanted = path199.resolve(declared);
|
|
104882
105674
|
for (const entry of listProjects(dir, () => {})) {
|
|
104883
|
-
if (
|
|
105675
|
+
if (path199.resolve(entry.path) === wanted) {
|
|
104884
105676
|
return { ok: true, project: entry.path };
|
|
104885
105677
|
}
|
|
104886
105678
|
}
|
|
@@ -105913,10 +106705,10 @@ function printHelp19() {
|
|
|
105913
106705
|
}
|
|
105914
106706
|
|
|
105915
106707
|
// src/commands/update.ts
|
|
105916
|
-
import { spawn as
|
|
106708
|
+
import { spawn as spawn7 } from "child_process";
|
|
105917
106709
|
import { chmod as chmod4, mkdir as mkdir63, readFile as readFile100, readdir as readdir37, writeFile as writeFile54 } from "fs/promises";
|
|
105918
|
-
import { access as access4, constants as
|
|
105919
|
-
import
|
|
106710
|
+
import { access as access4, constants as constants3, existsSync as existsSync36 } from "fs";
|
|
106711
|
+
import path200 from "path";
|
|
105920
106712
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
105921
106713
|
init_config2();
|
|
105922
106714
|
init_config();
|
|
@@ -105933,8 +106725,8 @@ async function updateCommand(args = []) {
|
|
|
105933
106725
|
return;
|
|
105934
106726
|
}
|
|
105935
106727
|
const projectRoot = process.cwd();
|
|
105936
|
-
const metaprojectRoot =
|
|
105937
|
-
banner("keryx update", `Refreshing the .metaproject workspace in ${
|
|
106728
|
+
const metaprojectRoot = path200.join(projectRoot, ".metaproject");
|
|
106729
|
+
banner("keryx update", `Refreshing the .metaproject workspace in ${path200.basename(projectRoot)}/`);
|
|
105938
106730
|
if (!await pathExists(metaprojectRoot)) {
|
|
105939
106731
|
console.log(` ${style.red(symbols.cross)} Metaproject is not initialized.`);
|
|
105940
106732
|
console.log(` ${style.cyan(symbols.arrow)} Run ${style.cyan("keryx init")} first.`);
|
|
@@ -106007,7 +106799,7 @@ async function updateCommand(args = []) {
|
|
|
106007
106799
|
nextSteps(steps);
|
|
106008
106800
|
}
|
|
106009
106801
|
async function previewServiceFiles(projectRoot, options) {
|
|
106010
|
-
const metaprojectRoot =
|
|
106802
|
+
const metaprojectRoot = path200.join(projectRoot, ".metaproject");
|
|
106011
106803
|
const manifestState = await readManifest5(metaprojectRoot);
|
|
106012
106804
|
const manifest = manifestState.manifest;
|
|
106013
106805
|
const enableTasks = moduleEnabled2(manifest, "tasks") || !options.noTasks;
|
|
@@ -106036,12 +106828,12 @@ async function previewServiceFiles(projectRoot, options) {
|
|
|
106036
106828
|
});
|
|
106037
106829
|
}
|
|
106038
106830
|
async function refreshServiceFiles(projectRoot, options) {
|
|
106039
|
-
const metaprojectRoot =
|
|
106831
|
+
const metaprojectRoot = path200.join(projectRoot, ".metaproject");
|
|
106040
106832
|
const manifestState = await readManifest5(metaprojectRoot);
|
|
106041
106833
|
const manifest = manifestState.manifest;
|
|
106042
106834
|
const recoveredManifest = !manifestState.exists || !manifestState.valid;
|
|
106043
106835
|
if (manifestState.migrated) {
|
|
106044
|
-
await writeFile54(
|
|
106836
|
+
await writeFile54(path200.join(metaprojectRoot, "metaproject.json"), `${JSON.stringify(manifest, null, 2)}
|
|
106045
106837
|
`, "utf8");
|
|
106046
106838
|
}
|
|
106047
106839
|
const enableGdgraph = moduleEnabled2(manifest, "gdgraph");
|
|
@@ -106078,9 +106870,9 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
106078
106870
|
enableSecurity,
|
|
106079
106871
|
enableSac
|
|
106080
106872
|
});
|
|
106081
|
-
await writeTextIfChanged4(
|
|
106082
|
-
await writeTextIfChanged4(
|
|
106083
|
-
await writeTextIfChanged4(
|
|
106873
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "core", "README.md"), renderMetaprojectCoreReadme());
|
|
106874
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "hooks", "README.md"), renderHooksReadme());
|
|
106875
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "project-rules", "README.md"), renderProjectRulesSkillReadme({ sources: ruleSources }));
|
|
106084
106876
|
await writeRoutingEntrypointPair(metaprojectRoot, {
|
|
106085
106877
|
enableGdgraph,
|
|
106086
106878
|
enableGdctx,
|
|
@@ -106103,7 +106895,7 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
106103
106895
|
}
|
|
106104
106896
|
}
|
|
106105
106897
|
});
|
|
106106
|
-
await writeTextIfChanged4(
|
|
106898
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "keryx-dashboard.html"), renderMetaprojectDashboardHtml({
|
|
106107
106899
|
enableGdgraph,
|
|
106108
106900
|
enableGdctx,
|
|
106109
106901
|
enableGdwiki,
|
|
@@ -106115,7 +106907,7 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
106115
106907
|
enableSecurity,
|
|
106116
106908
|
data: dashboardData
|
|
106117
106909
|
}));
|
|
106118
|
-
await writeTextIfMissing4(
|
|
106910
|
+
await writeTextIfMissing4(path200.join(metaprojectRoot, "README.md"), renderMetaprojectReadme({
|
|
106119
106911
|
enableGdgraph,
|
|
106120
106912
|
enableGdctx,
|
|
106121
106913
|
enableGdwiki,
|
|
@@ -106128,31 +106920,31 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
106128
106920
|
}));
|
|
106129
106921
|
if (enableGdgraph) {
|
|
106130
106922
|
await installGdgraphCoreScripts2(metaprojectRoot);
|
|
106131
|
-
await writeTextIfChanged4(
|
|
106132
|
-
await writeTextIfChanged4(
|
|
106133
|
-
await writeTextIfChanged4(
|
|
106923
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "modules", "gdgraph.md"), renderGdgraphManifest());
|
|
106924
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "core", "gdgraph", "README.md"), renderGdgraphCoreReadme());
|
|
106925
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "gdgraph", "SKILL.md"), renderGdgraphSkillReadme());
|
|
106134
106926
|
await seedAssetsLock(metaprojectRoot);
|
|
106135
106927
|
if (manifest.modules?.gdgraph?.hooks?.gitPostCommit) {
|
|
106136
106928
|
await installManagedHook2(projectRoot, "post-commit", "gdgraph-post-commit", renderGdgraphPostCommitHook());
|
|
106137
106929
|
}
|
|
106138
106930
|
}
|
|
106139
106931
|
if (enableGdctx) {
|
|
106140
|
-
await writeTextIfMissing4(
|
|
106141
|
-
await writeTextIfChanged4(
|
|
106142
|
-
await writeTextIfChanged4(
|
|
106143
|
-
await writeTextIfChanged4(
|
|
106932
|
+
await writeTextIfMissing4(path200.join(metaprojectRoot, "gdctx.config.json"), renderGdctxConfig());
|
|
106933
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "modules", "gdctx.md"), renderGdctxManifest());
|
|
106934
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "core", "gdctx", "README.md"), renderGdctxCoreReadme());
|
|
106935
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "gdctx", "SKILL.md"), renderGdctxSkillReadme());
|
|
106144
106936
|
}
|
|
106145
106937
|
if (enableGdwiki) {
|
|
106146
|
-
await writeTextIfMissing4(
|
|
106147
|
-
await writeTextIfChanged4(
|
|
106148
|
-
await writeTextIfChanged4(
|
|
106938
|
+
await writeTextIfMissing4(path200.join(metaprojectRoot, "wiki", "templates", "page.md"), renderWikiPageTemplate());
|
|
106939
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "modules", "gdwiki.md"), renderGdwikiManifest());
|
|
106940
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "gdwiki", "SKILL.md"), renderGdwikiSkillReadme());
|
|
106149
106941
|
if (manifest.modules?.gdgraph?.hooks?.gitPostCommit) {
|
|
106150
106942
|
await installManagedHook2(projectRoot, "post-commit", "gdwiki-post-commit", renderGdwikiPostCommitHook());
|
|
106151
106943
|
}
|
|
106152
106944
|
}
|
|
106153
106945
|
if (enableSac) {
|
|
106154
|
-
await writeTextIfMissing4(
|
|
106155
|
-
await writeTextIfChanged4(
|
|
106946
|
+
await writeTextIfMissing4(path200.join(metaprojectRoot, "modules", "sac.md"), renderSacManifest());
|
|
106947
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "sac", "SKILL.md"), renderSacSkillReadme());
|
|
106156
106948
|
}
|
|
106157
106949
|
let gdskillsWarnings = [];
|
|
106158
106950
|
let gdskillsNotices = [];
|
|
@@ -106165,25 +106957,25 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
106165
106957
|
}
|
|
106166
106958
|
}
|
|
106167
106959
|
if (enableHealth) {
|
|
106168
|
-
await writeTextIfMissing4(
|
|
106169
|
-
await writeTextIfChanged4(
|
|
106170
|
-
await writeTextIfChanged4(
|
|
106171
|
-
await writeTextIfChanged4(
|
|
106960
|
+
await writeTextIfMissing4(path200.join(metaprojectRoot, "health.config.json"), renderHealthConfig());
|
|
106961
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "modules", "health.md"), renderHealthManifest());
|
|
106962
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "core", "health", "README.md"), renderHealthCoreReadme());
|
|
106963
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "health", "SKILL.md"), renderHealthSkillReadme());
|
|
106172
106964
|
if (manifest.modules?.health?.hooks?.gitPostCommit) {
|
|
106173
106965
|
await installManagedHook2(projectRoot, "post-commit", "health-post-commit", renderHealthPostCommitHook());
|
|
106174
106966
|
}
|
|
106175
106967
|
}
|
|
106176
106968
|
if (enableTesting) {
|
|
106177
|
-
await writeTextIfMissing4(
|
|
106969
|
+
await writeTextIfMissing4(path200.join(metaprojectRoot, "testing.config.json"), renderTestingConfig({
|
|
106178
106970
|
postCommitRefresh: Boolean(manifest.modules?.testing?.hooks?.gitPostCommit),
|
|
106179
106971
|
prePushGate: Boolean(manifest.modules?.testing?.hooks?.prePush)
|
|
106180
106972
|
}));
|
|
106181
|
-
await writeTextIfChanged4(
|
|
106182
|
-
await writeTextIfChanged4(
|
|
106183
|
-
await writeTextIfChanged4(
|
|
106973
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "modules", "testing.md"), renderTestingManifest());
|
|
106974
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "core", "testing", "README.md"), renderTestingCoreReadme());
|
|
106975
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "testing", "SKILL.md"), renderTestingSkillReadme());
|
|
106184
106976
|
if (enableGdwiki) {
|
|
106185
|
-
await writeTextIfMissing4(
|
|
106186
|
-
await writeTextIfMissing4(
|
|
106977
|
+
await writeTextIfMissing4(path200.join(metaprojectRoot, "wiki", "testing", "README.md"), renderTestingWikiReadme());
|
|
106978
|
+
await writeTextIfMissing4(path200.join(metaprojectRoot, "wiki", "testing", "conventions.md"), renderTestingWikiConventions());
|
|
106187
106979
|
}
|
|
106188
106980
|
if (manifest.modules?.testing?.hooks?.gitPostCommit) {
|
|
106189
106981
|
await installManagedHook2(projectRoot, "post-commit", "testing-post-commit", renderTestingPostCommitHook());
|
|
@@ -106196,24 +106988,24 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
106196
106988
|
await installManagedHook2(projectRoot, "post-commit", "metaproject-dashboard-post-commit", renderMetaprojectDashboardPostCommitHook());
|
|
106197
106989
|
}
|
|
106198
106990
|
if (enableMemory) {
|
|
106199
|
-
await writeTextIfMissing4(
|
|
106200
|
-
await writeTextIfMissing4(
|
|
106201
|
-
await writeTextIfChanged4(
|
|
106202
|
-
await writeTextIfChanged4(
|
|
106203
|
-
await writeTextIfChanged4(
|
|
106991
|
+
await writeTextIfMissing4(path200.join(metaprojectRoot, "memory.config.json"), renderMemoryConfig());
|
|
106992
|
+
await writeTextIfMissing4(path200.join(metaprojectRoot, "memory", "templates", "entry.md"), renderMemoryEntryTemplate());
|
|
106993
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "modules", "memory.md"), renderMemoryManifest());
|
|
106994
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "core", "memory", "README.md"), renderMemoryCoreReadme());
|
|
106995
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "memory", "SKILL.md"), renderMemorySkillReadme());
|
|
106204
106996
|
}
|
|
106205
106997
|
if (enableTasks) {
|
|
106206
|
-
await writeTextIfChanged4(
|
|
106207
|
-
await writeTextIfChanged4(
|
|
106208
|
-
await writeTextIfChanged4(
|
|
106209
|
-
await writeTextIfChanged4(
|
|
106210
|
-
await writeTextIfChanged4(
|
|
106211
|
-
await writeTextIfChanged4(
|
|
106998
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "flows", "README.md"), renderFlowsReadme());
|
|
106999
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "modules", "tasks.md"), renderTasksManifest());
|
|
107000
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "flow", "SKILL.md"), renderFlowSkillRouter());
|
|
107001
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "flow", "init.md"), renderFlowInitSkill());
|
|
107002
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "flow", "manage.md"), renderFlowManageSkill());
|
|
107003
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "skills", "flow", "complete.md"), renderFlowCompleteSkill());
|
|
106212
107004
|
}
|
|
106213
107005
|
if (enableSecurity) {
|
|
106214
|
-
await writeTextIfMissing4(
|
|
106215
|
-
await writeTextIfChanged4(
|
|
106216
|
-
await writeTextIfChanged4(
|
|
107006
|
+
await writeTextIfMissing4(path200.join(metaprojectRoot, "security.config.json"), renderSecurityConfig());
|
|
107007
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "modules", "security.md"), renderSecurityManifest());
|
|
107008
|
+
await writeTextIfChanged4(path200.join(metaprojectRoot, "core", "security", "README.md"), renderSecurityCoreReadme());
|
|
106217
107009
|
if (manifest.modules?.security?.hooks?.prePush) {
|
|
106218
107010
|
await installManagedHook2(projectRoot, "pre-push", "security-pre-push", renderSecurityPrePushHook());
|
|
106219
107011
|
}
|
|
@@ -106266,13 +107058,13 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
106266
107058
|
};
|
|
106267
107059
|
}
|
|
106268
107060
|
async function buildDashboard(projectRoot = process.cwd()) {
|
|
106269
|
-
const metaprojectRoot =
|
|
107061
|
+
const metaprojectRoot = path200.join(projectRoot, ".metaproject");
|
|
106270
107062
|
if (!await pathExists(metaprojectRoot)) {
|
|
106271
107063
|
throw new Error("Metaproject is not initialized. Run: keryx init");
|
|
106272
107064
|
}
|
|
106273
107065
|
const manifest = (await readManifest5(metaprojectRoot)).manifest;
|
|
106274
107066
|
const data = await collectDashboardData(metaprojectRoot);
|
|
106275
|
-
const dashboardPath =
|
|
107067
|
+
const dashboardPath = path200.join(metaprojectRoot, "keryx-dashboard.html");
|
|
106276
107068
|
await writeTextIfChanged4(dashboardPath, renderMetaprojectDashboardHtml({
|
|
106277
107069
|
enableGdgraph: moduleEnabled2(manifest, "gdgraph"),
|
|
106278
107070
|
enableGdctx: moduleEnabled2(manifest, "gdctx"),
|
|
@@ -106292,7 +107084,7 @@ async function shouldInstallDashboardPostCommitHook(projectRoot, manifest) {
|
|
|
106292
107084
|
if (Object.values(modules).some((module) => Boolean(module.hooks?.gitPostCommit))) {
|
|
106293
107085
|
return true;
|
|
106294
107086
|
}
|
|
106295
|
-
const hookPath =
|
|
107087
|
+
const hookPath = path200.join(projectRoot, ".git", "hooks", "post-commit");
|
|
106296
107088
|
if (!await pathExists(hookPath)) {
|
|
106297
107089
|
return false;
|
|
106298
107090
|
}
|
|
@@ -106312,11 +107104,11 @@ async function collectDashboardData(metaprojectRoot) {
|
|
|
106312
107104
|
if (testing) {
|
|
106313
107105
|
data.testing = testing;
|
|
106314
107106
|
}
|
|
106315
|
-
const wiki = await collectMarkdownPages(
|
|
107107
|
+
const wiki = await collectMarkdownPages(path200.join(metaprojectRoot, "wiki"), "wiki");
|
|
106316
107108
|
if (wiki.length > 0) {
|
|
106317
107109
|
data.wiki = { pages: wiki };
|
|
106318
107110
|
}
|
|
106319
|
-
const memory = await collectMarkdownPages(
|
|
107111
|
+
const memory = await collectMarkdownPages(path200.join(metaprojectRoot, "memory"), "memory");
|
|
106320
107112
|
if (memory.length > 0) {
|
|
106321
107113
|
data.memory = { entries: memory };
|
|
106322
107114
|
}
|
|
@@ -106331,7 +107123,7 @@ async function collectDashboardData(metaprojectRoot) {
|
|
|
106331
107123
|
return data;
|
|
106332
107124
|
}
|
|
106333
107125
|
async function collectTasksDashboardData(metaprojectRoot) {
|
|
106334
|
-
const flowsRoot =
|
|
107126
|
+
const flowsRoot = path200.join(metaprojectRoot, "flows");
|
|
106335
107127
|
if (!await pathExists(flowsRoot)) {
|
|
106336
107128
|
return null;
|
|
106337
107129
|
}
|
|
@@ -106343,7 +107135,7 @@ async function collectTasksDashboardData(metaprojectRoot) {
|
|
|
106343
107135
|
}
|
|
106344
107136
|
const flows = [];
|
|
106345
107137
|
for (const dir of dirEntries) {
|
|
106346
|
-
const flowPath =
|
|
107138
|
+
const flowPath = path200.join(flowsRoot, dir, "flow.json");
|
|
106347
107139
|
if (!await pathExists(flowPath)) {
|
|
106348
107140
|
continue;
|
|
106349
107141
|
}
|
|
@@ -106351,7 +107143,7 @@ async function collectTasksDashboardData(metaprojectRoot) {
|
|
|
106351
107143
|
const flow = JSON.parse(await readFile100(flowPath, "utf8"));
|
|
106352
107144
|
const tasks = Array.isArray(flow.tasks) ? flow.tasks : [];
|
|
106353
107145
|
let acTotal = 0;
|
|
106354
|
-
const acPath =
|
|
107146
|
+
const acPath = path200.join(flowsRoot, dir, "acceptance-criteria.md");
|
|
106355
107147
|
if (await pathExists(acPath)) {
|
|
106356
107148
|
const acContent = await readFile100(acPath, "utf8");
|
|
106357
107149
|
acTotal = (acContent.match(/^- AC\d+:/gm) ?? []).length;
|
|
@@ -106405,7 +107197,7 @@ async function collectDashboardDocs(metaprojectRoot, wiki, memory) {
|
|
|
106405
107197
|
"data/testing/context.md"
|
|
106406
107198
|
];
|
|
106407
107199
|
for (const href of staticHrefs) {
|
|
106408
|
-
const filePath =
|
|
107200
|
+
const filePath = path200.join(metaprojectRoot, ...href.split("/"));
|
|
106409
107201
|
if (!await pathExists(filePath)) {
|
|
106410
107202
|
continue;
|
|
106411
107203
|
}
|
|
@@ -106422,7 +107214,7 @@ async function collectDashboardDocs(metaprojectRoot, wiki, memory) {
|
|
|
106422
107214
|
return docs;
|
|
106423
107215
|
}
|
|
106424
107216
|
async function collectHealthDashboardData(metaprojectRoot) {
|
|
106425
|
-
const reportPath =
|
|
107217
|
+
const reportPath = path200.join(metaprojectRoot, "data", "health", "artifacts", "latest.json");
|
|
106426
107218
|
if (!await pathExists(reportPath)) {
|
|
106427
107219
|
return;
|
|
106428
107220
|
}
|
|
@@ -106531,8 +107323,8 @@ function metricToScope(metric) {
|
|
|
106531
107323
|
};
|
|
106532
107324
|
}
|
|
106533
107325
|
async function collectGraphDashboardData(metaprojectRoot) {
|
|
106534
|
-
const nodesPath =
|
|
106535
|
-
const edgesPath =
|
|
107326
|
+
const nodesPath = path200.join(metaprojectRoot, "data", "gdgraph", "storage", "nodes.jsonl");
|
|
107327
|
+
const edgesPath = path200.join(metaprojectRoot, "data", "gdgraph", "storage", "edges.jsonl");
|
|
106536
107328
|
if (!await pathExists(nodesPath) || !await pathExists(edgesPath)) {
|
|
106537
107329
|
return;
|
|
106538
107330
|
}
|
|
@@ -106583,8 +107375,8 @@ async function collectGraphDashboardData(metaprojectRoot) {
|
|
|
106583
107375
|
};
|
|
106584
107376
|
}
|
|
106585
107377
|
async function collectTestingDashboardData(metaprojectRoot) {
|
|
106586
|
-
const reportPath =
|
|
106587
|
-
const contextPath =
|
|
107378
|
+
const reportPath = path200.join(metaprojectRoot, "data", "testing", "artifacts", "latest.json");
|
|
107379
|
+
const contextPath = path200.join(metaprojectRoot, "data", "testing", "context.md");
|
|
106588
107380
|
if (await pathExists(reportPath)) {
|
|
106589
107381
|
const report = JSON.parse(await readFile100(reportPath, "utf8"));
|
|
106590
107382
|
const totalTests = numberOrUndefined(report.total);
|
|
@@ -106613,7 +107405,7 @@ async function collectMarkdownPages(root, hrefPrefix) {
|
|
|
106613
107405
|
const files = await listMarkdownFiles(root);
|
|
106614
107406
|
const pages = [];
|
|
106615
107407
|
for (const filePath of files.slice(0, 40)) {
|
|
106616
|
-
const relativePath =
|
|
107408
|
+
const relativePath = path200.relative(root, filePath).split(path200.sep).join("/");
|
|
106617
107409
|
if (relativePath === "index.md" || relativePath.startsWith("templates/")) {
|
|
106618
107410
|
continue;
|
|
106619
107411
|
}
|
|
@@ -106634,7 +107426,7 @@ async function listMarkdownFiles(root) {
|
|
|
106634
107426
|
const entries = await readdir37(root, { withFileTypes: true });
|
|
106635
107427
|
const files = [];
|
|
106636
107428
|
for (const entry of entries) {
|
|
106637
|
-
const fullPath =
|
|
107429
|
+
const fullPath = path200.join(root, entry.name);
|
|
106638
107430
|
if (entry.isDirectory()) {
|
|
106639
107431
|
files.push(...await listMarkdownFiles(fullPath));
|
|
106640
107432
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -106682,7 +107474,7 @@ async function writeRecoveredManifest(metaprojectRoot, modules) {
|
|
|
106682
107474
|
const manifest = {
|
|
106683
107475
|
schemaVersion: 1,
|
|
106684
107476
|
standardVersion: STANDARD_VERSION,
|
|
106685
|
-
name: `${
|
|
107477
|
+
name: `${path200.basename(path200.dirname(metaprojectRoot))}-metaproject`,
|
|
106686
107478
|
createdBy: "keryx",
|
|
106687
107479
|
profiles: computeProfiles(enabledModuleKeys),
|
|
106688
107480
|
paths: {
|
|
@@ -106772,11 +107564,11 @@ async function writeRecoveredManifest(metaprojectRoot, modules) {
|
|
|
106772
107564
|
metaproject: ".metaproject/index.md"
|
|
106773
107565
|
}
|
|
106774
107566
|
};
|
|
106775
|
-
await writeFile54(
|
|
107567
|
+
await writeFile54(path200.join(metaprojectRoot, "metaproject.json"), `${JSON.stringify(manifest, null, 2)}
|
|
106776
107568
|
`, "utf8");
|
|
106777
107569
|
}
|
|
106778
107570
|
async function enableTasksInManifest(metaprojectRoot) {
|
|
106779
|
-
const manifestPath =
|
|
107571
|
+
const manifestPath = path200.join(metaprojectRoot, "metaproject.json");
|
|
106780
107572
|
if (!await pathExists(manifestPath)) {
|
|
106781
107573
|
return;
|
|
106782
107574
|
}
|
|
@@ -106799,7 +107591,7 @@ async function enableTasksInManifest(metaprojectRoot) {
|
|
|
106799
107591
|
`, "utf8");
|
|
106800
107592
|
}
|
|
106801
107593
|
async function updateManifestAgentEntrypoints(metaprojectRoot, ruleSources) {
|
|
106802
|
-
const manifestPath =
|
|
107594
|
+
const manifestPath = path200.join(metaprojectRoot, "metaproject.json");
|
|
106803
107595
|
if (!await pathExists(manifestPath)) {
|
|
106804
107596
|
return;
|
|
106805
107597
|
}
|
|
@@ -106835,72 +107627,72 @@ async function updateRuntime(projectRoot) {
|
|
|
106835
107627
|
}
|
|
106836
107628
|
}
|
|
106837
107629
|
async function findRuntimeRoot(projectRoot) {
|
|
106838
|
-
const projectRuntime =
|
|
106839
|
-
if (await pathExists(
|
|
107630
|
+
const projectRuntime = path200.join(projectRoot, ".metaproject", "runtime", "keryx");
|
|
107631
|
+
if (await pathExists(path200.join(projectRuntime, ".git"))) {
|
|
106840
107632
|
return projectRuntime;
|
|
106841
107633
|
}
|
|
106842
107634
|
const home = process.env.HOME;
|
|
106843
107635
|
if (!home) {
|
|
106844
107636
|
return null;
|
|
106845
107637
|
}
|
|
106846
|
-
const globalRuntime =
|
|
106847
|
-
if (await pathExists(
|
|
107638
|
+
const globalRuntime = path200.join(home, ".keryx", "keryx");
|
|
107639
|
+
if (await pathExists(path200.join(globalRuntime, ".git"))) {
|
|
106848
107640
|
return globalRuntime;
|
|
106849
107641
|
}
|
|
106850
107642
|
return null;
|
|
106851
107643
|
}
|
|
106852
107644
|
async function createServiceDirs(metaprojectRoot, modules) {
|
|
106853
107645
|
const dirs = [
|
|
106854
|
-
|
|
106855
|
-
|
|
106856
|
-
|
|
106857
|
-
|
|
106858
|
-
|
|
107646
|
+
path200.join(metaprojectRoot, "core"),
|
|
107647
|
+
path200.join(metaprojectRoot, "hooks", "post-update.d"),
|
|
107648
|
+
path200.join(metaprojectRoot, "modules"),
|
|
107649
|
+
path200.join(metaprojectRoot, "rules"),
|
|
107650
|
+
path200.join(metaprojectRoot, "skills", "project-rules"),
|
|
106859
107651
|
...modules.enableGdgraph ? [
|
|
106860
|
-
|
|
106861
|
-
|
|
107652
|
+
path200.join(metaprojectRoot, "core", "gdgraph"),
|
|
107653
|
+
path200.join(metaprojectRoot, "skills", "gdgraph")
|
|
106862
107654
|
] : [],
|
|
106863
107655
|
...modules.enableGdctx ? [
|
|
106864
|
-
|
|
106865
|
-
|
|
107656
|
+
path200.join(metaprojectRoot, "core", "gdctx"),
|
|
107657
|
+
path200.join(metaprojectRoot, "skills", "gdctx")
|
|
106866
107658
|
] : [],
|
|
106867
107659
|
...modules.enableGdwiki ? [
|
|
106868
|
-
|
|
106869
|
-
|
|
107660
|
+
path200.join(metaprojectRoot, "skills", "gdwiki"),
|
|
107661
|
+
path200.join(metaprojectRoot, "wiki", "templates")
|
|
106870
107662
|
] : [],
|
|
106871
107663
|
...modules.enableHealth ? [
|
|
106872
|
-
|
|
106873
|
-
|
|
107664
|
+
path200.join(metaprojectRoot, "core", "health"),
|
|
107665
|
+
path200.join(metaprojectRoot, "skills", "health")
|
|
106874
107666
|
] : [],
|
|
106875
107667
|
...modules.enableTesting ? [
|
|
106876
|
-
|
|
106877
|
-
|
|
107668
|
+
path200.join(metaprojectRoot, "core", "testing"),
|
|
107669
|
+
path200.join(metaprojectRoot, "skills", "testing")
|
|
106878
107670
|
] : [],
|
|
106879
107671
|
...modules.enableMemory ? [
|
|
106880
|
-
|
|
106881
|
-
|
|
106882
|
-
|
|
107672
|
+
path200.join(metaprojectRoot, "core", "memory"),
|
|
107673
|
+
path200.join(metaprojectRoot, "skills", "memory"),
|
|
107674
|
+
path200.join(metaprojectRoot, "memory", "templates")
|
|
106883
107675
|
] : [],
|
|
106884
107676
|
...modules.enableTasks ? [
|
|
106885
|
-
|
|
106886
|
-
|
|
107677
|
+
path200.join(metaprojectRoot, "flows"),
|
|
107678
|
+
path200.join(metaprojectRoot, "skills", "flow")
|
|
106887
107679
|
] : [],
|
|
106888
107680
|
...modules.enableSecurity ? [
|
|
106889
|
-
|
|
107681
|
+
path200.join(metaprojectRoot, "core", "security")
|
|
106890
107682
|
] : [],
|
|
106891
107683
|
...modules.enableSac ? [
|
|
106892
|
-
|
|
107684
|
+
path200.join(metaprojectRoot, "skills", "sac")
|
|
106893
107685
|
] : []
|
|
106894
107686
|
];
|
|
106895
107687
|
await Promise.all(dirs.map((dir) => mkdir63(dir, { recursive: true })));
|
|
106896
107688
|
}
|
|
106897
107689
|
async function installGdgraphCoreScripts2(metaprojectRoot) {
|
|
106898
|
-
const gdgraphCoreRoot =
|
|
107690
|
+
const gdgraphCoreRoot = path200.join(metaprojectRoot, "core", "gdgraph");
|
|
106899
107691
|
await mkdir63(gdgraphCoreRoot, { recursive: true });
|
|
106900
107692
|
for (const file of GDGRAPH_CORE_SOURCES) {
|
|
106901
|
-
await copyFileIfChanged2(runtimeSourcePath2(`../gdgraph/${file}`),
|
|
107693
|
+
await copyFileIfChanged2(runtimeSourcePath2(`../gdgraph/${file}`), path200.join(gdgraphCoreRoot, file));
|
|
106902
107694
|
}
|
|
106903
|
-
await writeTextIfChanged4(
|
|
107695
|
+
await writeTextIfChanged4(path200.join(gdgraphCoreRoot, "cli.ts"), renderGdgraphCoreCli());
|
|
106904
107696
|
}
|
|
106905
107697
|
async function installManagedHook2(projectRoot, hookName, blockId, content) {
|
|
106906
107698
|
const hooksRoot = await resolveGitHooksRoot(projectRoot);
|
|
@@ -106908,7 +107700,7 @@ async function installManagedHook2(projectRoot, hookName, blockId, content) {
|
|
|
106908
107700
|
return;
|
|
106909
107701
|
}
|
|
106910
107702
|
await mkdir63(hooksRoot, { recursive: true });
|
|
106911
|
-
const hookPath =
|
|
107703
|
+
const hookPath = path200.join(hooksRoot, hookName);
|
|
106912
107704
|
const blockStart = `# keryx:${blockId}:begin`;
|
|
106913
107705
|
const blockEnd = `# keryx:${blockId}:end`;
|
|
106914
107706
|
const managedBlock = `${blockStart}
|
|
@@ -106929,7 +107721,7 @@ async function removeManagedHook2(projectRoot, hookName, blockId) {
|
|
|
106929
107721
|
if (!hooksRoot) {
|
|
106930
107722
|
return;
|
|
106931
107723
|
}
|
|
106932
|
-
const hookPath =
|
|
107724
|
+
const hookPath = path200.join(hooksRoot, hookName);
|
|
106933
107725
|
if (!await pathExists(hookPath)) {
|
|
106934
107726
|
return;
|
|
106935
107727
|
}
|
|
@@ -106951,7 +107743,7 @@ async function prePushHasSecurityBlock2(projectRoot) {
|
|
|
106951
107743
|
if (!hooksRoot) {
|
|
106952
107744
|
return false;
|
|
106953
107745
|
}
|
|
106954
|
-
const hookPath =
|
|
107746
|
+
const hookPath = path200.join(hooksRoot, "pre-push");
|
|
106955
107747
|
if (!await pathExists(hookPath)) {
|
|
106956
107748
|
return false;
|
|
106957
107749
|
}
|
|
@@ -106966,7 +107758,7 @@ async function agentSettingsHasSecuritySentinel2(projectRoot) {
|
|
|
106966
107758
|
return (await readFile100(file, "utf8")).includes(AGENT_HOOKS_SENTINEL);
|
|
106967
107759
|
}
|
|
106968
107760
|
async function readManifest5(metaprojectRoot) {
|
|
106969
|
-
const manifestPath =
|
|
107761
|
+
const manifestPath = path200.join(metaprojectRoot, "metaproject.json");
|
|
106970
107762
|
if (!await pathExists(manifestPath)) {
|
|
106971
107763
|
return {
|
|
106972
107764
|
exists: false,
|
|
@@ -107035,7 +107827,7 @@ async function inferManifestFromExistingMetaproject(metaprojectRoot) {
|
|
|
107035
107827
|
}
|
|
107036
107828
|
async function anyPathExists(root, candidates) {
|
|
107037
107829
|
for (const candidate of candidates) {
|
|
107038
|
-
if (await pathExists(
|
|
107830
|
+
if (await pathExists(path200.join(root, candidate))) {
|
|
107039
107831
|
return true;
|
|
107040
107832
|
}
|
|
107041
107833
|
}
|
|
@@ -107058,13 +107850,13 @@ function parseUpdateArgs(args) {
|
|
|
107058
107850
|
};
|
|
107059
107851
|
}
|
|
107060
107852
|
async function runPostUpdateHooks(projectRoot) {
|
|
107061
|
-
const hooksDir =
|
|
107853
|
+
const hooksDir = path200.join(projectRoot, ".metaproject", "hooks", "post-update.d");
|
|
107062
107854
|
if (!await pathExists(hooksDir)) {
|
|
107063
107855
|
return;
|
|
107064
107856
|
}
|
|
107065
107857
|
const entries = (await readdir37(hooksDir)).sort();
|
|
107066
107858
|
for (const entry of entries) {
|
|
107067
|
-
const hookPath =
|
|
107859
|
+
const hookPath = path200.join(hooksDir, entry);
|
|
107068
107860
|
try {
|
|
107069
107861
|
await accessExecutable(hookPath);
|
|
107070
107862
|
} catch {
|
|
@@ -107076,7 +107868,7 @@ async function runPostUpdateHooks(projectRoot) {
|
|
|
107076
107868
|
}
|
|
107077
107869
|
async function accessExecutable(filePath) {
|
|
107078
107870
|
await new Promise((resolve, reject) => {
|
|
107079
|
-
access4(filePath,
|
|
107871
|
+
access4(filePath, constants3.X_OK, (error) => {
|
|
107080
107872
|
if (error) {
|
|
107081
107873
|
reject(error);
|
|
107082
107874
|
return;
|
|
@@ -107087,7 +107879,7 @@ async function accessExecutable(filePath) {
|
|
|
107087
107879
|
}
|
|
107088
107880
|
async function run(command, args, cwd) {
|
|
107089
107881
|
await new Promise((resolve, reject) => {
|
|
107090
|
-
const child =
|
|
107882
|
+
const child = spawn7(command, args, {
|
|
107091
107883
|
cwd,
|
|
107092
107884
|
stdio: "inherit"
|
|
107093
107885
|
});
|
|
@@ -107105,14 +107897,14 @@ async function writeTextIfChanged4(filePath, content) {
|
|
|
107105
107897
|
if (await pathExists(filePath) && await readFile100(filePath, "utf8") === content) {
|
|
107106
107898
|
return;
|
|
107107
107899
|
}
|
|
107108
|
-
await mkdir63(
|
|
107900
|
+
await mkdir63(path200.dirname(filePath), { recursive: true });
|
|
107109
107901
|
await writeFile54(filePath, content, "utf8");
|
|
107110
107902
|
}
|
|
107111
107903
|
async function writeTextIfMissing4(filePath, content) {
|
|
107112
107904
|
if (await pathExists(filePath)) {
|
|
107113
107905
|
return;
|
|
107114
107906
|
}
|
|
107115
|
-
await mkdir63(
|
|
107907
|
+
await mkdir63(path200.dirname(filePath), { recursive: true });
|
|
107116
107908
|
await writeFile54(filePath, content, "utf8");
|
|
107117
107909
|
}
|
|
107118
107910
|
async function copyFileIfChanged2(from, to) {
|
|
@@ -107120,7 +107912,7 @@ async function copyFileIfChanged2(from, to) {
|
|
|
107120
107912
|
if (await pathExists(to) && await readFile100(to, "utf8") === next) {
|
|
107121
107913
|
return;
|
|
107122
107914
|
}
|
|
107123
|
-
await mkdir63(
|
|
107915
|
+
await mkdir63(path200.dirname(to), { recursive: true });
|
|
107124
107916
|
await writeFile54(to, next, "utf8");
|
|
107125
107917
|
}
|
|
107126
107918
|
function runtimeSourcePath2(relativePath) {
|
|
@@ -107129,7 +107921,7 @@ function runtimeSourcePath2(relativePath) {
|
|
|
107129
107921
|
return directPath;
|
|
107130
107922
|
}
|
|
107131
107923
|
if (relativePath.startsWith("../")) {
|
|
107132
|
-
const packagedSourcePath =
|
|
107924
|
+
const packagedSourcePath = path200.join(path200.dirname(fileURLToPath8(import.meta.url)), "..", "src", relativePath.slice(3));
|
|
107133
107925
|
if (existsSync36(packagedSourcePath)) {
|
|
107134
107926
|
return packagedSourcePath;
|
|
107135
107927
|
}
|
|
@@ -107163,8 +107955,8 @@ function printHelp20() {
|
|
|
107163
107955
|
}
|
|
107164
107956
|
|
|
107165
107957
|
// src/commands/dashboard.ts
|
|
107166
|
-
import { spawn as
|
|
107167
|
-
import
|
|
107958
|
+
import { spawn as spawn8 } from "child_process";
|
|
107959
|
+
import path201 from "path";
|
|
107168
107960
|
init_args();
|
|
107169
107961
|
async function dashboardCommand(args = []) {
|
|
107170
107962
|
const options = parseOptions(args);
|
|
@@ -107175,7 +107967,7 @@ async function dashboardCommand(args = []) {
|
|
|
107175
107967
|
}
|
|
107176
107968
|
if (subcommand === "build") {
|
|
107177
107969
|
const result = await buildDashboard();
|
|
107178
|
-
const rel =
|
|
107970
|
+
const rel = path201.relative(process.cwd(), result.path);
|
|
107179
107971
|
console.log(` ${style.green(symbols.ok)} Dashboard built ${style.cyan(symbols.arrow)} ${style.cyan(rel)}`);
|
|
107180
107972
|
note(`Open it: keryx dashboard open`);
|
|
107181
107973
|
return;
|
|
@@ -107183,7 +107975,7 @@ async function dashboardCommand(args = []) {
|
|
|
107183
107975
|
if (subcommand === "open") {
|
|
107184
107976
|
const result = await buildDashboard();
|
|
107185
107977
|
await openFile(result.path);
|
|
107186
|
-
const rel =
|
|
107978
|
+
const rel = path201.relative(process.cwd(), result.path);
|
|
107187
107979
|
console.log(` ${style.green(symbols.ok)} Opened ${style.cyan(rel)}`);
|
|
107188
107980
|
return;
|
|
107189
107981
|
}
|
|
@@ -107202,7 +107994,7 @@ async function openFile(filePath) {
|
|
|
107202
107994
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
107203
107995
|
const args = process.platform === "win32" ? ["/c", "start", "", filePath] : [filePath];
|
|
107204
107996
|
await new Promise((resolve, reject) => {
|
|
107205
|
-
const child =
|
|
107997
|
+
const child = spawn8(command, args, { stdio: "ignore", detached: true });
|
|
107206
107998
|
child.on("error", reject);
|
|
107207
107999
|
child.on("close", (code) => {
|
|
107208
108000
|
if (code === 0) {
|
|
@@ -107227,12 +108019,12 @@ function printHelp21() {
|
|
|
107227
108019
|
}
|
|
107228
108020
|
|
|
107229
108021
|
// src/commands/agents.ts
|
|
107230
|
-
import { readFileSync as
|
|
108022
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
107231
108023
|
|
|
107232
108024
|
// src/agents/bootstrap.ts
|
|
107233
108025
|
import { mkdir as mkdir64, readFile as readFile101, writeFile as writeFile55 } from "fs/promises";
|
|
107234
108026
|
import { homedir as homedir10 } from "os";
|
|
107235
|
-
import
|
|
108027
|
+
import path202 from "path";
|
|
107236
108028
|
init_fs();
|
|
107237
108029
|
var AGENT_BOOTSTRAP_START = "<!-- keryx:global-bootstrap -->";
|
|
107238
108030
|
var AGENT_BOOTSTRAP_END = "<!-- /keryx:global-bootstrap -->";
|
|
@@ -107242,35 +108034,35 @@ var AGENT_BOOTSTRAP_RUNTIMES = [
|
|
|
107242
108034
|
aliases: ["claude-code"],
|
|
107243
108035
|
label: "Claude Code",
|
|
107244
108036
|
fileName: "CLAUDE.md",
|
|
107245
|
-
filePath: (homeRoot) =>
|
|
108037
|
+
filePath: (homeRoot) => path202.join(homeRoot, ".claude", "CLAUDE.md")
|
|
107246
108038
|
},
|
|
107247
108039
|
{
|
|
107248
108040
|
id: "opencode",
|
|
107249
108041
|
aliases: ["open-code"],
|
|
107250
108042
|
label: "OpenCode",
|
|
107251
108043
|
fileName: "AGENTS.md",
|
|
107252
|
-
filePath: (homeRoot) =>
|
|
108044
|
+
filePath: (homeRoot) => path202.join(homeRoot, ".config", "opencode", "AGENTS.md")
|
|
107253
108045
|
},
|
|
107254
108046
|
{
|
|
107255
108047
|
id: "zcode",
|
|
107256
108048
|
aliases: ["zed", "zed-code"],
|
|
107257
108049
|
label: "ZCode",
|
|
107258
108050
|
fileName: "AGENTS.md",
|
|
107259
|
-
filePath: (homeRoot) =>
|
|
108051
|
+
filePath: (homeRoot) => path202.join(homeRoot, ".zcode", "AGENTS.md")
|
|
107260
108052
|
},
|
|
107261
108053
|
{
|
|
107262
108054
|
id: "codex",
|
|
107263
108055
|
aliases: [],
|
|
107264
108056
|
label: "Codex",
|
|
107265
108057
|
fileName: "AGENTS.md",
|
|
107266
|
-
filePath: (homeRoot) =>
|
|
108058
|
+
filePath: (homeRoot) => path202.join(homeRoot, ".codex", "AGENTS.md")
|
|
107267
108059
|
},
|
|
107268
108060
|
{
|
|
107269
108061
|
id: "antigravity",
|
|
107270
108062
|
aliases: ["antigravuty", "antigravity-code"],
|
|
107271
108063
|
label: "Antigravity",
|
|
107272
108064
|
fileName: "AGENTS.md",
|
|
107273
|
-
filePath: (homeRoot) =>
|
|
108065
|
+
filePath: (homeRoot) => path202.join(homeRoot, ".config", "antigravity", "AGENTS.md")
|
|
107274
108066
|
}
|
|
107275
108067
|
];
|
|
107276
108068
|
function agentBootstrapRuntimeIds() {
|
|
@@ -107318,7 +108110,7 @@ async function installAgentBootstrap(runtime, options = {}) {
|
|
|
107318
108110
|
const dryRun = options.dryRun === true;
|
|
107319
108111
|
const wrote = next !== current;
|
|
107320
108112
|
if (wrote && !dryRun) {
|
|
107321
|
-
await mkdir64(
|
|
108113
|
+
await mkdir64(path202.dirname(filePath), { recursive: true });
|
|
107322
108114
|
await writeFile55(filePath, next, "utf8");
|
|
107323
108115
|
}
|
|
107324
108116
|
const status = dryRun ? statusFromContent(runtime, filePath, exists, next) : await agentBootstrapStatus(runtime, homeRoot);
|
|
@@ -107728,7 +108520,7 @@ function monitorCommand(args) {
|
|
|
107728
108520
|
}
|
|
107729
108521
|
let events;
|
|
107730
108522
|
try {
|
|
107731
|
-
events = parseAgentEvents(
|
|
108523
|
+
events = parseAgentEvents(readFileSync10(source, "utf8"));
|
|
107732
108524
|
} catch (error) {
|
|
107733
108525
|
console.error(`Failed to read/parse agent-event source "${source}": ${error.message}`);
|
|
107734
108526
|
process.exitCode = 1;
|
|
@@ -107855,7 +108647,7 @@ function printBootstrapHelp() {
|
|
|
107855
108647
|
// src/commands/metrics.ts
|
|
107856
108648
|
init_args();
|
|
107857
108649
|
import { readFile as readFile102 } from "fs/promises";
|
|
107858
|
-
import
|
|
108650
|
+
import path204 from "path";
|
|
107859
108651
|
|
|
107860
108652
|
// src/metrics/benchmark.ts
|
|
107861
108653
|
var RELIABILITIES2 = new Set(["exact", "estimated", "unknown"]);
|
|
@@ -108672,7 +109464,7 @@ function buildContainmentManifest(inputs, options = {}) {
|
|
|
108672
109464
|
|
|
108673
109465
|
// src/metrics/oracle-runner.ts
|
|
108674
109466
|
import { mkdir as mkdir65, writeFile as writeFile56 } from "fs/promises";
|
|
108675
|
-
import
|
|
109467
|
+
import path203 from "path";
|
|
108676
109468
|
|
|
108677
109469
|
// src/metrics/ir.ts
|
|
108678
109470
|
function toIdSet(ids) {
|
|
@@ -109118,9 +109910,9 @@ function buildEvidenceBundle(input, options = {}) {
|
|
|
109118
109910
|
async function persistEvidenceBundle(outDir, bundle, ladder = "metastore") {
|
|
109119
109911
|
const safeTarget = bundle.target.replace(/[^A-Za-z0-9._/-]/g, "_");
|
|
109120
109912
|
const safeCase = bundle.caseId.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
109121
|
-
const dir =
|
|
109913
|
+
const dir = path203.join(outDir, "bench", ladder, safeTarget, safeCase, bundle.variant, String(bundle.seed));
|
|
109122
109914
|
await mkdir65(dir, { recursive: true });
|
|
109123
|
-
const write = (name, value) => writeFile56(
|
|
109915
|
+
const write = (name, value) => writeFile56(path203.join(dir, name), `${JSON.stringify(value, null, 2)}
|
|
109124
109916
|
`, "utf8");
|
|
109125
109917
|
await Promise.all([
|
|
109126
109918
|
write("inputs.json", bundle.inputs),
|
|
@@ -109160,7 +109952,7 @@ async function metricsCommand(args = [], projectRoot = process.cwd()) {
|
|
|
109160
109952
|
console.log("# metrics status");
|
|
109161
109953
|
console.log("");
|
|
109162
109954
|
console.log(`root: ${root}`);
|
|
109163
|
-
console.log(`enabled: ${await Bun.file(
|
|
109955
|
+
console.log(`enabled: ${await Bun.file(path204.join(projectRoot, ".metaproject", "metaproject.json")).exists() ? "yes" : "no"}`);
|
|
109164
109956
|
const latest = await readLatestPointer(root);
|
|
109165
109957
|
console.log(`latest: ${latest.status}`);
|
|
109166
109958
|
return;
|
|
@@ -109172,7 +109964,7 @@ async function metricsCommand(args = [], projectRoot = process.cwd()) {
|
|
|
109172
109964
|
process.exitCode = 1;
|
|
109173
109965
|
return;
|
|
109174
109966
|
}
|
|
109175
|
-
const record = JSON.parse(await readFile102(
|
|
109967
|
+
const record = JSON.parse(await readFile102(path204.resolve(projectRoot, file), "utf8"));
|
|
109176
109968
|
const result = validateRunRecord(record);
|
|
109177
109969
|
console.log(result.valid ? "valid: yes" : "valid: no");
|
|
109178
109970
|
for (const error of result.errors)
|
|
@@ -109197,7 +109989,7 @@ async function metricsCommand(args = [], projectRoot = process.cwd()) {
|
|
|
109197
109989
|
process.exitCode = 1;
|
|
109198
109990
|
return;
|
|
109199
109991
|
}
|
|
109200
|
-
const file =
|
|
109992
|
+
const file = path204.join(metricsRoot(projectRoot), "runs", `${runId}.json`);
|
|
109201
109993
|
if (!await Bun.file(file).exists()) {
|
|
109202
109994
|
console.error(`Run not found: ${runId}`);
|
|
109203
109995
|
process.exitCode = 1;
|
|
@@ -109214,8 +110006,8 @@ async function metricsCommand(args = [], projectRoot = process.cwd()) {
|
|
|
109214
110006
|
process.exitCode = 1;
|
|
109215
110007
|
return;
|
|
109216
110008
|
}
|
|
109217
|
-
const a = JSON.parse(await readFile102(
|
|
109218
|
-
const b = JSON.parse(await readFile102(
|
|
110009
|
+
const a = JSON.parse(await readFile102(path204.join(metricsRoot(projectRoot), "runs", `${runA}.json`), "utf8"));
|
|
110010
|
+
const b = JSON.parse(await readFile102(path204.join(metricsRoot(projectRoot), "runs", `${runB}.json`), "utf8"));
|
|
109219
110011
|
const comparison = compareExecutionRuns(a, b);
|
|
109220
110012
|
console.log(stableJson(comparison));
|
|
109221
110013
|
return;
|
|
@@ -109249,8 +110041,8 @@ async function metricsCommand(args = [], projectRoot = process.cwd()) {
|
|
|
109249
110041
|
return;
|
|
109250
110042
|
}
|
|
109251
110043
|
const template = createPairedBenchmarkTemplate(taskIds);
|
|
109252
|
-
await Bun.write(
|
|
109253
|
-
console.log(`manifest: ${
|
|
110044
|
+
await Bun.write(path204.resolve(projectRoot, out), stableJson(template));
|
|
110045
|
+
console.log(`manifest: ${path204.relative(projectRoot, path204.resolve(projectRoot, out))}`);
|
|
109254
110046
|
return;
|
|
109255
110047
|
}
|
|
109256
110048
|
if (subcommand === "benchmark" && args[1] === "run") {
|
|
@@ -109264,7 +110056,7 @@ async function metricsCommand(args = [], projectRoot = process.cwd()) {
|
|
|
109264
110056
|
process.exitCode = 1;
|
|
109265
110057
|
return;
|
|
109266
110058
|
}
|
|
109267
|
-
const raw = JSON.parse(await readFile102(
|
|
110059
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, file), "utf8"));
|
|
109268
110060
|
const input = Array.isArray(raw) ? raw : raw.runs ?? [];
|
|
109269
110061
|
const result = validatePairedBenchmark(input);
|
|
109270
110062
|
console.log(stableJson(result));
|
|
@@ -109276,7 +110068,7 @@ async function metricsCommand(args = [], projectRoot = process.cwd()) {
|
|
|
109276
110068
|
process.exitCode = 1;
|
|
109277
110069
|
}
|
|
109278
110070
|
async function loadAffectedSets(projectRoot, file) {
|
|
109279
|
-
const raw = JSON.parse(await readFile102(
|
|
110071
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, file), "utf8"));
|
|
109280
110072
|
const map = new Map;
|
|
109281
110073
|
for (const entry of raw.targets ?? []) {
|
|
109282
110074
|
if (typeof entry.target === "string")
|
|
@@ -109347,7 +110139,7 @@ async function runHarnessLayer(projectRoot, args, ladder) {
|
|
|
109347
110139
|
let tasks;
|
|
109348
110140
|
let model;
|
|
109349
110141
|
try {
|
|
109350
|
-
const raw = JSON.parse(await readFile102(
|
|
110142
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, resultsPath), "utf8"));
|
|
109351
110143
|
tasks = raw.tasks ?? [];
|
|
109352
110144
|
model = raw.model;
|
|
109353
110145
|
} catch (error) {
|
|
@@ -109378,7 +110170,7 @@ async function runSafetyCompletionHonestyLayer(projectRoot, args, ladder) {
|
|
|
109378
110170
|
let cases;
|
|
109379
110171
|
let model;
|
|
109380
110172
|
try {
|
|
109381
|
-
const raw = JSON.parse(await readFile102(
|
|
110173
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, resultsPath), "utf8"));
|
|
109382
110174
|
cases = raw.cases ?? [];
|
|
109383
110175
|
model = raw.model;
|
|
109384
110176
|
} catch (error) {
|
|
@@ -109403,7 +110195,7 @@ async function runSafetyFalsePremiseLayer(projectRoot, args, ladder) {
|
|
|
109403
110195
|
let cases;
|
|
109404
110196
|
let model;
|
|
109405
110197
|
try {
|
|
109406
|
-
const raw = JSON.parse(await readFile102(
|
|
110198
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, resultsPath), "utf8"));
|
|
109407
110199
|
cases = raw.cases ?? [];
|
|
109408
110200
|
model = raw.model;
|
|
109409
110201
|
} catch (error) {
|
|
@@ -109428,7 +110220,7 @@ async function runSafetyContainmentLayer(projectRoot, args, ladder, caseClass) {
|
|
|
109428
110220
|
let cases;
|
|
109429
110221
|
let model;
|
|
109430
110222
|
try {
|
|
109431
|
-
const raw = JSON.parse(await readFile102(
|
|
110223
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, resultsPath), "utf8"));
|
|
109432
110224
|
cases = raw.cases ?? [];
|
|
109433
110225
|
model = raw.model;
|
|
109434
110226
|
} catch (error) {
|
|
@@ -109490,12 +110282,12 @@ async function runGdgraphLayer(projectRoot, args, ladder) {
|
|
|
109490
110282
|
}
|
|
109491
110283
|
const manifests = buildOracleManifestsByGold(inputs, { ladder });
|
|
109492
110284
|
if (outDir) {
|
|
109493
|
-
const resolvedOut =
|
|
110285
|
+
const resolvedOut = path204.resolve(projectRoot, outDir);
|
|
109494
110286
|
for (const input of inputs) {
|
|
109495
110287
|
for (const named of input.golds) {
|
|
109496
110288
|
const bundle = buildEvidenceBundle({ target: input.target, system: input.system, gold: named.gold }, { ladder, goldReference: goldPathFor(named.kind), timestamp: new Date().toISOString() });
|
|
109497
|
-
const dir = await persistEvidenceBundle(
|
|
109498
|
-
console.error(`bundle[${named.kind}]: ${
|
|
110289
|
+
const dir = await persistEvidenceBundle(path204.join(resolvedOut, named.kind), bundle, ladder);
|
|
110290
|
+
console.error(`bundle[${named.kind}]: ${path204.relative(projectRoot, dir)}`);
|
|
109499
110291
|
}
|
|
109500
110292
|
}
|
|
109501
110293
|
}
|
|
@@ -109519,7 +110311,7 @@ async function runGdgraphLayer(projectRoot, args, ladder) {
|
|
|
109519
110311
|
return allValid;
|
|
109520
110312
|
}
|
|
109521
110313
|
async function loadCoverageMap2(projectRoot, file) {
|
|
109522
|
-
const raw = JSON.parse(await readFile102(
|
|
110314
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, file), "utf8"));
|
|
109523
110315
|
return raw.coverageMap ?? {};
|
|
109524
110316
|
}
|
|
109525
110317
|
async function runTestingLayer(projectRoot, args, ladder) {
|
|
@@ -109556,7 +110348,7 @@ async function runTestingLayer(projectRoot, args, ladder) {
|
|
|
109556
110348
|
return result.valid;
|
|
109557
110349
|
}
|
|
109558
110350
|
async function loadMemoryGoldK(projectRoot, file) {
|
|
109559
|
-
const raw = JSON.parse(await readFile102(
|
|
110351
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, file), "utf8"));
|
|
109560
110352
|
return typeof raw.k === "number" && raw.k > 0 ? raw.k : 3;
|
|
109561
110353
|
}
|
|
109562
110354
|
async function runMemoryLayer(projectRoot, args, ladder) {
|
|
@@ -109593,11 +110385,11 @@ async function runMemoryLayer(projectRoot, args, ladder) {
|
|
|
109593
110385
|
return result.valid;
|
|
109594
110386
|
}
|
|
109595
110387
|
async function loadWikiGoldK(projectRoot, file) {
|
|
109596
|
-
const raw = JSON.parse(await readFile102(
|
|
110388
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, file), "utf8"));
|
|
109597
110389
|
return typeof raw.k === "number" && raw.k > 0 ? raw.k : 5;
|
|
109598
110390
|
}
|
|
109599
110391
|
async function loadWikiGroundedness(projectRoot, file) {
|
|
109600
|
-
const raw = JSON.parse(await readFile102(
|
|
110392
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, file), "utf8"));
|
|
109601
110393
|
const map = new Map;
|
|
109602
110394
|
for (const entry of raw.targets ?? []) {
|
|
109603
110395
|
if (typeof entry.target !== "string" || !Array.isArray(entry.scores) || entry.scores.length !== 3)
|
|
@@ -109653,7 +110445,7 @@ async function runWikiLayer(projectRoot, args, ladder) {
|
|
|
109653
110445
|
return result.valid;
|
|
109654
110446
|
}
|
|
109655
110447
|
async function loadGdctxFacts(projectRoot, file) {
|
|
109656
|
-
const raw = JSON.parse(await readFile102(
|
|
110448
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, file), "utf8"));
|
|
109657
110449
|
const inputs = [];
|
|
109658
110450
|
for (const entry of raw.inputs ?? []) {
|
|
109659
110451
|
if (typeof entry.input === "string") {
|
|
@@ -109691,7 +110483,7 @@ async function collect(projectRoot, args) {
|
|
|
109691
110483
|
process.exitCode = 1;
|
|
109692
110484
|
return;
|
|
109693
110485
|
}
|
|
109694
|
-
const raw = JSON.parse(await readFile102(
|
|
110486
|
+
const raw = JSON.parse(await readFile102(path204.resolve(projectRoot, eventFile), "utf8"));
|
|
109695
110487
|
const events = Array.isArray(raw) ? raw : raw.events;
|
|
109696
110488
|
const startedAt = optionValue(args, "--started-at") ?? events[0]?.timestamp_utc ?? new Date().toISOString();
|
|
109697
110489
|
const finishedAt = optionValue(args, "--finished-at") ?? events.at(-1)?.timestamp_utc ?? startedAt;
|
|
@@ -109707,11 +110499,11 @@ async function collect(projectRoot, args) {
|
|
|
109707
110499
|
parentRunId: optionValue(args, "--parent-run-id") ?? null
|
|
109708
110500
|
});
|
|
109709
110501
|
const result = await writeRunArtifacts(metricsRoot(projectRoot), record, { cwd: projectRoot });
|
|
109710
|
-
console.log(`json: ${
|
|
109711
|
-
console.log(`markdown: ${
|
|
110502
|
+
console.log(`json: ${path204.relative(projectRoot, result.jsonPath)}`);
|
|
110503
|
+
console.log(`markdown: ${path204.relative(projectRoot, result.markdownPath)}`);
|
|
109712
110504
|
}
|
|
109713
110505
|
function metricsRoot(projectRoot) {
|
|
109714
|
-
return
|
|
110506
|
+
return path204.join(projectRoot, ".metaproject", "data", "metrics");
|
|
109715
110507
|
}
|
|
109716
110508
|
function printMetricsHelp() {
|
|
109717
110509
|
console.log(`keryx metrics
|