@mrciphersmith/keryx 0.2.17 → 0.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/cli.js +686 -279
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -55,9 +55,12 @@ import {
|
|
|
55
55
|
chmodSync,
|
|
56
56
|
mkdirSync,
|
|
57
57
|
readFileSync,
|
|
58
|
+
renameSync,
|
|
58
59
|
statSync,
|
|
60
|
+
unlinkSync,
|
|
59
61
|
writeFileSync
|
|
60
62
|
} from "fs";
|
|
63
|
+
import { randomUUID } from "crypto";
|
|
61
64
|
import { homedir } from "os";
|
|
62
65
|
import path from "path";
|
|
63
66
|
function keryxConfigDir(dir) {
|
|
@@ -146,6 +149,21 @@ function writeOwnerOnlyFile(file, body) {
|
|
|
146
149
|
chmodSync(file, 384);
|
|
147
150
|
} catch {}
|
|
148
151
|
}
|
|
152
|
+
function writeOwnerOnlyFileAtomic(file, body) {
|
|
153
|
+
const temporary = `${file}.${process.pid}.${randomUUID()}.tmp`;
|
|
154
|
+
try {
|
|
155
|
+
writeFileSync(temporary, body, { encoding: "utf8", mode: 384 });
|
|
156
|
+
if (process.platform !== "win32") {
|
|
157
|
+
chmodSync(temporary, 384);
|
|
158
|
+
}
|
|
159
|
+
renameSync(temporary, file);
|
|
160
|
+
} catch (cause) {
|
|
161
|
+
try {
|
|
162
|
+
unlinkSync(temporary);
|
|
163
|
+
} catch {}
|
|
164
|
+
throw cause;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
149
167
|
function ensureKeryxConfigDir(dir) {
|
|
150
168
|
const base = keryxConfigDir(dir);
|
|
151
169
|
try {
|
|
@@ -174,7 +192,7 @@ __export(exports_fs, {
|
|
|
174
192
|
pathExists: () => pathExists,
|
|
175
193
|
isPathInside: () => isPathInside
|
|
176
194
|
});
|
|
177
|
-
import { randomUUID as
|
|
195
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
178
196
|
import { access, mkdir, rename, rm, stat, writeFile } from "fs/promises";
|
|
179
197
|
import path5 from "path";
|
|
180
198
|
async function pathExists(filePath) {
|
|
@@ -195,7 +213,7 @@ function isPathInside(root, candidate) {
|
|
|
195
213
|
async function writeFileAtomic(filePath, content) {
|
|
196
214
|
const dir = path5.dirname(filePath);
|
|
197
215
|
await mkdir(dir, { recursive: true });
|
|
198
|
-
const tmp = path5.join(dir, `.${path5.basename(filePath)}.${process.pid}.${Date.now()}.${
|
|
216
|
+
const tmp = path5.join(dir, `.${path5.basename(filePath)}.${process.pid}.${Date.now()}.${randomUUID4()}.tmp`);
|
|
199
217
|
try {
|
|
200
218
|
await writeFile(tmp, content, "utf8");
|
|
201
219
|
await rename(tmp, filePath);
|
|
@@ -11146,7 +11164,7 @@ var init_search = __esm(() => {
|
|
|
11146
11164
|
});
|
|
11147
11165
|
|
|
11148
11166
|
// src/memory/report.ts
|
|
11149
|
-
import { randomUUID as
|
|
11167
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
11150
11168
|
import { access as access2, mkdir as mkdir27, readdir as readdir7, rename as rename3, rm as rm5, stat as stat4, writeFile as writeFile30 } from "fs/promises";
|
|
11151
11169
|
import path71 from "path";
|
|
11152
11170
|
function runtimeRoot(cwd) {
|
|
@@ -11306,7 +11324,7 @@ class MemoryReportStore {
|
|
|
11306
11324
|
nextRunId;
|
|
11307
11325
|
constructor(dependencies = {}) {
|
|
11308
11326
|
this.clock = dependencies.clock ?? (() => new Date);
|
|
11309
|
-
this.nextRunId = dependencies.runId ?? (() =>
|
|
11327
|
+
this.nextRunId = dependencies.runId ?? (() => randomUUID6());
|
|
11310
11328
|
}
|
|
11311
11329
|
async writeReport(input2) {
|
|
11312
11330
|
const runId = input2.runId ?? this.nextRunId();
|
|
@@ -11327,7 +11345,7 @@ class MemoryReportStore {
|
|
|
11327
11345
|
if ((await stat4(candidate)).mtimeMs <= staleBefore)
|
|
11328
11346
|
await rm5(candidate, { recursive: true, force: true });
|
|
11329
11347
|
}
|
|
11330
|
-
const staging = path71.join(tempRoot, `${runId}.${
|
|
11348
|
+
const staging = path71.join(tempRoot, `${runId}.${randomUUID6()}`);
|
|
11331
11349
|
try {
|
|
11332
11350
|
await mkdir27(staging);
|
|
11333
11351
|
await Promise.all([
|
|
@@ -12714,17 +12732,17 @@ import {
|
|
|
12714
12732
|
fsyncSync,
|
|
12715
12733
|
openSync as openSync2,
|
|
12716
12734
|
realpathSync,
|
|
12717
|
-
renameSync,
|
|
12735
|
+
renameSync as renameSync2,
|
|
12718
12736
|
statSync as statSync3,
|
|
12719
|
-
unlinkSync,
|
|
12737
|
+
unlinkSync as unlinkSync2,
|
|
12720
12738
|
writeFileSync as writeFileSync3
|
|
12721
12739
|
} from "fs";
|
|
12722
12740
|
import path3 from "path";
|
|
12723
|
-
import { randomUUID as
|
|
12741
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
12724
12742
|
|
|
12725
12743
|
// src/lib/file-lock.ts
|
|
12726
12744
|
import { closeSync, mkdirSync as mkdirSync2, openSync, readFileSync as readFileSync2, rmSync, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
12727
|
-
import { randomUUID } from "crypto";
|
|
12745
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
12728
12746
|
import path2 from "path";
|
|
12729
12747
|
var LOCK_STALE_MS = 1e4;
|
|
12730
12748
|
var LOCK_TIMEOUT_MS = 15000;
|
|
@@ -12743,7 +12761,7 @@ function withFileLock(lockPath, fn, options = {}) {
|
|
|
12743
12761
|
} catch {
|
|
12744
12762
|
return null;
|
|
12745
12763
|
}
|
|
12746
|
-
const nonce =
|
|
12764
|
+
const nonce = randomUUID2();
|
|
12747
12765
|
const started = Date.now();
|
|
12748
12766
|
const deadline = started + LOCK_TIMEOUT_MS;
|
|
12749
12767
|
let handle = null;
|
|
@@ -12925,7 +12943,7 @@ function quarantineDamagedRegistry(dir, onWarn) {
|
|
|
12925
12943
|
}
|
|
12926
12944
|
function saveProjectRegistry(registry, dir, onWarn) {
|
|
12927
12945
|
const file = projectRegistryPath(dir);
|
|
12928
|
-
const temp = `${file}.${
|
|
12946
|
+
const temp = `${file}.${randomUUID3()}.tmp`;
|
|
12929
12947
|
try {
|
|
12930
12948
|
ensureKeryxConfigDir(dir);
|
|
12931
12949
|
const sorted = {
|
|
@@ -12940,11 +12958,11 @@ function saveProjectRegistry(registry, dir, onWarn) {
|
|
|
12940
12958
|
} finally {
|
|
12941
12959
|
closeSync2(handle);
|
|
12942
12960
|
}
|
|
12943
|
-
|
|
12961
|
+
renameSync2(temp, file);
|
|
12944
12962
|
return true;
|
|
12945
12963
|
} catch {
|
|
12946
12964
|
try {
|
|
12947
|
-
|
|
12965
|
+
unlinkSync2(temp);
|
|
12948
12966
|
} catch {}
|
|
12949
12967
|
return false;
|
|
12950
12968
|
}
|
|
@@ -12981,7 +12999,7 @@ function registerProject(projectPath, options = {}) {
|
|
|
12981
12999
|
return { ok: true, entry: existing, created: false };
|
|
12982
13000
|
}
|
|
12983
13001
|
const entry = {
|
|
12984
|
-
projectId:
|
|
13002
|
+
projectId: randomUUID3(),
|
|
12985
13003
|
path: absolute,
|
|
12986
13004
|
displayName: options.displayName ?? path3.basename(absolute),
|
|
12987
13005
|
state: "active",
|
|
@@ -13694,7 +13712,7 @@ function sessionDir(projectPath, sessionId, dataDir) {
|
|
|
13694
13712
|
|
|
13695
13713
|
// src/harness/process/sandbox/network-run.ts
|
|
13696
13714
|
import { Worker } from "worker_threads";
|
|
13697
|
-
import { randomUUID as
|
|
13715
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
13698
13716
|
import { existsSync as existsSync3 } from "fs";
|
|
13699
13717
|
import { rm as rm2, writeFile as writeFile3 } from "fs/promises";
|
|
13700
13718
|
import { fileURLToPath } from "url";
|
|
@@ -13789,7 +13807,7 @@ async function setupNetworkRun(profile, options = {}) {
|
|
|
13789
13807
|
for (const cred of options.masks ?? []) {
|
|
13790
13808
|
if (cred.realValue.length === 0)
|
|
13791
13809
|
continue;
|
|
13792
|
-
const sentinel = `keryx-sentinel-${
|
|
13810
|
+
const sentinel = `keryx-sentinel-${randomUUID5()}`;
|
|
13793
13811
|
maskedEnv[cred.name] = sentinel;
|
|
13794
13812
|
proxyMasks.push({ sentinel, realValue: cred.realValue, injectHosts: cred.injectHosts });
|
|
13795
13813
|
}
|
|
@@ -13799,7 +13817,7 @@ async function setupNetworkRun(profile, options = {}) {
|
|
|
13799
13817
|
const trustEnv = {};
|
|
13800
13818
|
let caPemPath;
|
|
13801
13819
|
if (tlsTerminate && caCertPem) {
|
|
13802
|
-
caPemPath = path9.join(tmpdir(), `keryx-run-ca-${
|
|
13820
|
+
caPemPath = path9.join(tmpdir(), `keryx-run-ca-${randomUUID5()}.pem`);
|
|
13803
13821
|
await writeFile3(caPemPath, caCertPem, { mode: 420 });
|
|
13804
13822
|
trustEnv.SSL_CERT_FILE = caPemPath;
|
|
13805
13823
|
trustEnv.CURL_CA_BUNDLE = caPemPath;
|
|
@@ -17192,7 +17210,8 @@ function renderIndexMarkdown({
|
|
|
17192
17210
|
"First choose the capability: graph/navigation, compact context, wiki/domain knowledge, memory, testing, health, security, skills/orchestration, or flow lifecycle.",
|
|
17193
17211
|
"If the same capability is available through MCP tools/resources, prefer MCP because it preserves structured inputs and outputs. If MCP is unavailable, use the module skill and `keryx` CLI fallback.",
|
|
17194
17212
|
"Load the narrowest relevant skill/rule before reading broad source files. Do not ask the user which internal command to run unless multiple user-level outcomes are genuinely possible.",
|
|
17195
|
-
"When reporting results, name the Metaproject sources used at a high level (for example: graph, wiki, memory, health), not every internal command."
|
|
17213
|
+
"When reporting results, name the Metaproject sources used at a high level (for example: graph, wiki, memory, health), not every internal command.",
|
|
17214
|
+
"Once per session, run `keryx version check --json`. Notify the user only when the result is `update-available`; this is an advisory and never installs anything. A timeout, offline registry, `unavailable`, or `unknown-command` result is non-blocking: never block project work on the check."
|
|
17196
17215
|
].map((item) => `- ${item}`).join(`
|
|
17197
17216
|
`);
|
|
17198
17217
|
const intentRows = [
|
|
@@ -32023,6 +32042,15 @@ var COMMAND_DESCRIPTORS = [
|
|
|
32023
32042
|
args: [{ name: "json", type: "bool", required: false, desc: "structured module state" }],
|
|
32024
32043
|
json: true,
|
|
32025
32044
|
read: true
|
|
32045
|
+
},
|
|
32046
|
+
{
|
|
32047
|
+
module: "core",
|
|
32048
|
+
command: "version check",
|
|
32049
|
+
summary: "Check the fixed npm latest endpoint for a newer Keryx release.",
|
|
32050
|
+
intent: ["check keryx version", "check for update", "\u043F\u0440\u043E\u0432\u0435\u0440\u044C \u0432\u0435\u0440\u0441\u0438\u044E keryx"],
|
|
32051
|
+
args: [{ name: "json", type: "bool", required: false, desc: "typed structured result" }],
|
|
32052
|
+
json: true,
|
|
32053
|
+
read: true
|
|
32026
32054
|
}
|
|
32027
32055
|
];
|
|
32028
32056
|
function sortKey(descriptor) {
|
|
@@ -34743,7 +34771,7 @@ Reports the workspace root and one enabled/disabled line per module. Use
|
|
|
34743
34771
|
// src/commands/harness.ts
|
|
34744
34772
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
34745
34773
|
import path118 from "path";
|
|
34746
|
-
import { randomUUID as
|
|
34774
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
34747
34775
|
|
|
34748
34776
|
// src/security/harness-scan.ts
|
|
34749
34777
|
init_guard();
|
|
@@ -37093,7 +37121,7 @@ function resolveRuntime(deps) {
|
|
|
37093
37121
|
const env = deps?.env ?? process.env;
|
|
37094
37122
|
const clock = deps?.clock ?? (() => new Date().toISOString());
|
|
37095
37123
|
let idCounter = 0;
|
|
37096
|
-
const idSeq = deps?.idSeq ?? (() => `${
|
|
37124
|
+
const idSeq = deps?.idSeq ?? (() => `${randomUUID7()}-${idCounter++}`);
|
|
37097
37125
|
return { env, clock, idSeq };
|
|
37098
37126
|
}
|
|
37099
37127
|
function shellAllowProfile() {
|
|
@@ -37184,7 +37212,7 @@ async function harnessCommand(args, deps) {
|
|
|
37184
37212
|
const env = deps?.env ?? process.env;
|
|
37185
37213
|
const clock = deps?.clock ?? (() => new Date().toISOString());
|
|
37186
37214
|
let idCounter = 0;
|
|
37187
|
-
const idSeq = deps?.idSeq ?? (() => `${
|
|
37215
|
+
const idSeq = deps?.idSeq ?? (() => `${randomUUID7()}-${idCounter++}`);
|
|
37188
37216
|
const fetchImpl = deps?.fetch ?? globalThis.fetch;
|
|
37189
37217
|
if (provider === "anthropic") {
|
|
37190
37218
|
const apiKey = env.ANTHROPIC_API_KEY;
|
|
@@ -37301,7 +37329,7 @@ function harnessReplay(args, deps) {
|
|
|
37301
37329
|
}
|
|
37302
37330
|
const clock = deps?.clock ?? (() => new Date().toISOString());
|
|
37303
37331
|
let idCounter = 0;
|
|
37304
|
-
const idSeq = deps?.idSeq ?? (() => `${
|
|
37332
|
+
const idSeq = deps?.idSeq ?? (() => `${randomUUID7()}-${idCounter++}`);
|
|
37305
37333
|
const fixture = (() => {
|
|
37306
37334
|
if (parsed.fixture === undefined || parsed.fixture.length === 0) {
|
|
37307
37335
|
return { ok: true, value: buildReplayFixture(run, { idSeq }), built: true };
|
|
@@ -37741,7 +37769,7 @@ function harnessWave(args, deps) {
|
|
|
37741
37769
|
// src/commands/shell.ts
|
|
37742
37770
|
init_make_provider();
|
|
37743
37771
|
init_orient();
|
|
37744
|
-
import { randomUUID as
|
|
37772
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
37745
37773
|
import * as readline2 from "readline";
|
|
37746
37774
|
|
|
37747
37775
|
// src/harness/tool/builtin/ask-user-tool.ts
|
|
@@ -38385,7 +38413,7 @@ function shellExecTool(root, run = makeCommandRunner(root)) {
|
|
|
38385
38413
|
}
|
|
38386
38414
|
|
|
38387
38415
|
// src/harness/tool/builtin/spawn-subagent-tool.ts
|
|
38388
|
-
import { createHash as createHash17, randomUUID as
|
|
38416
|
+
import { createHash as createHash17, randomUUID as randomUUID8 } from "crypto";
|
|
38389
38417
|
|
|
38390
38418
|
// src/harness/child/ledger.ts
|
|
38391
38419
|
function decrement(remaining, reservation) {
|
|
@@ -39501,7 +39529,7 @@ function sha2565(text) {
|
|
|
39501
39529
|
var parentShellPolicy = shellParentProfile;
|
|
39502
39530
|
var childReadOnlyPolicy = shellChildReadOnlyProfile;
|
|
39503
39531
|
function createSpawnSubagentTool(deps) {
|
|
39504
|
-
const idSeq = deps.idSeq ?? (() =>
|
|
39532
|
+
const idSeq = deps.idSeq ?? (() => randomUUID8());
|
|
39505
39533
|
const clock = deps.clock ?? (() => new Date().toISOString());
|
|
39506
39534
|
const parentRunId = deps.parentRunId ?? idSeq();
|
|
39507
39535
|
const parentSessionId = deps.parentSessionId ?? idSeq();
|
|
@@ -40350,11 +40378,11 @@ import {
|
|
|
40350
40378
|
existsSync as existsSync23,
|
|
40351
40379
|
mkdirSync as mkdirSync6,
|
|
40352
40380
|
readdirSync,
|
|
40353
|
-
renameSync as
|
|
40381
|
+
renameSync as renameSync3,
|
|
40354
40382
|
writeFileSync as writeFileSync7
|
|
40355
40383
|
} from "fs";
|
|
40356
40384
|
import path120 from "path";
|
|
40357
|
-
import { randomUUID as
|
|
40385
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
40358
40386
|
var SESSION_SCHEMA_VERSION = 1;
|
|
40359
40387
|
function nowIso() {
|
|
40360
40388
|
return new Date().toISOString();
|
|
@@ -40393,7 +40421,7 @@ function tighten(target) {
|
|
|
40393
40421
|
function atomicWriteText(file, body) {
|
|
40394
40422
|
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
40395
40423
|
writeFileSync7(tmp, body, { encoding: "utf8", mode: 384 });
|
|
40396
|
-
|
|
40424
|
+
renameSync3(tmp, file);
|
|
40397
40425
|
}
|
|
40398
40426
|
function atomicWriteJson(file, value) {
|
|
40399
40427
|
atomicWriteText(file, `${JSON.stringify(value, null, 2)}
|
|
@@ -40501,7 +40529,7 @@ function readJsonl2(file) {
|
|
|
40501
40529
|
function createSession(opts) {
|
|
40502
40530
|
const projectPath = resolveProjectRoot(opts.cwd);
|
|
40503
40531
|
const projectKey2 = projectKeyFromPath(projectPath);
|
|
40504
|
-
const id = opts.id ??
|
|
40532
|
+
const id = opts.id ?? randomUUID9();
|
|
40505
40533
|
const dir = sessionDir(projectPath, id, opts.dataDir);
|
|
40506
40534
|
ensureDir(dir, opts.dataDir);
|
|
40507
40535
|
const ts = nowIso();
|
|
@@ -40944,6 +40972,279 @@ function showComposerChoice(otui, r, dock, request) {
|
|
|
40944
40972
|
});
|
|
40945
40973
|
}
|
|
40946
40974
|
|
|
40975
|
+
// src/lib/version-check.ts
|
|
40976
|
+
init_config_dir();
|
|
40977
|
+
init_fs();
|
|
40978
|
+
import path121 from "path";
|
|
40979
|
+
var REGISTRY_URL = "https://registry.npmjs.org/@mrciphersmith%2Fkeryx/latest";
|
|
40980
|
+
var FIXED_INSTALL_COMMAND = "npm install -g @mrciphersmith/keryx@latest";
|
|
40981
|
+
var RESPONSE_BODY_LIMIT_BYTES = 64 * 1024;
|
|
40982
|
+
var VERSION_STRING_LIMIT_CHARS = 64;
|
|
40983
|
+
var REQUEST_TIMEOUT_MS = 2000;
|
|
40984
|
+
var SUCCESS_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
40985
|
+
var FAILURE_BACKOFF_MS = 15 * 60 * 1000;
|
|
40986
|
+
var CACHE_LOCK_TIMEOUT_MS = 250;
|
|
40987
|
+
var CACHE_LOCK_RETRY_MS = 10;
|
|
40988
|
+
var CACHE_LOCK_STALE_MS = 5000;
|
|
40989
|
+
var SYSTEM_TIMER = {
|
|
40990
|
+
schedule: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
40991
|
+
cancel: (handle) => clearTimeout(handle)
|
|
40992
|
+
};
|
|
40993
|
+
function formatVersionUpdateAdvisory(result) {
|
|
40994
|
+
if (result.status !== "update-available")
|
|
40995
|
+
return;
|
|
40996
|
+
return `Keryx update ${result.currentVersion} \u2192 ${result.latestVersion}
|
|
40997
|
+
${result.installCommand}`;
|
|
40998
|
+
}
|
|
40999
|
+
var STRICT_SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
|
|
41000
|
+
function parseSemVer(value) {
|
|
41001
|
+
if (value.length > VERSION_STRING_LIMIT_CHARS)
|
|
41002
|
+
return;
|
|
41003
|
+
const match = STRICT_SEMVER.exec(value);
|
|
41004
|
+
if (match === null)
|
|
41005
|
+
return;
|
|
41006
|
+
const prereleaseText = match[4];
|
|
41007
|
+
const prerelease = [];
|
|
41008
|
+
if (prereleaseText !== undefined) {
|
|
41009
|
+
for (const identifier of prereleaseText.split(".")) {
|
|
41010
|
+
if (/^\d+$/.test(identifier)) {
|
|
41011
|
+
if (identifier.length > 1 && identifier.startsWith("0"))
|
|
41012
|
+
return;
|
|
41013
|
+
prerelease.push(BigInt(identifier));
|
|
41014
|
+
} else {
|
|
41015
|
+
prerelease.push(identifier);
|
|
41016
|
+
}
|
|
41017
|
+
}
|
|
41018
|
+
}
|
|
41019
|
+
return {
|
|
41020
|
+
major: BigInt(match[1]),
|
|
41021
|
+
minor: BigInt(match[2]),
|
|
41022
|
+
patch: BigInt(match[3]),
|
|
41023
|
+
prerelease
|
|
41024
|
+
};
|
|
41025
|
+
}
|
|
41026
|
+
function compareSemVer(left, right) {
|
|
41027
|
+
for (const key of ["major", "minor", "patch"]) {
|
|
41028
|
+
if (left[key] < right[key])
|
|
41029
|
+
return -1;
|
|
41030
|
+
if (left[key] > right[key])
|
|
41031
|
+
return 1;
|
|
41032
|
+
}
|
|
41033
|
+
if (left.prerelease.length === 0 || right.prerelease.length === 0) {
|
|
41034
|
+
if (left.prerelease.length === right.prerelease.length)
|
|
41035
|
+
return 0;
|
|
41036
|
+
return left.prerelease.length === 0 ? 1 : -1;
|
|
41037
|
+
}
|
|
41038
|
+
const length = Math.max(left.prerelease.length, right.prerelease.length);
|
|
41039
|
+
for (let index = 0;index < length; index += 1) {
|
|
41040
|
+
const a = left.prerelease[index];
|
|
41041
|
+
const b = right.prerelease[index];
|
|
41042
|
+
if (a === undefined || b === undefined) {
|
|
41043
|
+
if (a === b)
|
|
41044
|
+
return 0;
|
|
41045
|
+
return a === undefined ? -1 : 1;
|
|
41046
|
+
}
|
|
41047
|
+
if (typeof a === "bigint" && typeof b === "bigint") {
|
|
41048
|
+
if (a < b)
|
|
41049
|
+
return -1;
|
|
41050
|
+
if (a > b)
|
|
41051
|
+
return 1;
|
|
41052
|
+
} else if (typeof a === "bigint") {
|
|
41053
|
+
return -1;
|
|
41054
|
+
} else if (typeof b === "bigint") {
|
|
41055
|
+
return 1;
|
|
41056
|
+
} else if (a !== b) {
|
|
41057
|
+
return a < b ? -1 : 1;
|
|
41058
|
+
}
|
|
41059
|
+
}
|
|
41060
|
+
return 0;
|
|
41061
|
+
}
|
|
41062
|
+
function parseCache(file) {
|
|
41063
|
+
const read = readConfigFile(file);
|
|
41064
|
+
if (!read.ok)
|
|
41065
|
+
return;
|
|
41066
|
+
try {
|
|
41067
|
+
const value = JSON.parse(read.text);
|
|
41068
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
41069
|
+
return;
|
|
41070
|
+
const record = value;
|
|
41071
|
+
const cache = {};
|
|
41072
|
+
if (typeof record.latestVersion === "string" && parseSemVer(record.latestVersion) !== undefined) {
|
|
41073
|
+
cache.latestVersion = record.latestVersion;
|
|
41074
|
+
}
|
|
41075
|
+
if (typeof record.successAt === "number" && Number.isFinite(record.successAt))
|
|
41076
|
+
cache.successAt = record.successAt;
|
|
41077
|
+
if (typeof record.failureAt === "number" && Number.isFinite(record.failureAt))
|
|
41078
|
+
cache.failureAt = record.failureAt;
|
|
41079
|
+
return cache;
|
|
41080
|
+
} catch {
|
|
41081
|
+
return;
|
|
41082
|
+
}
|
|
41083
|
+
}
|
|
41084
|
+
function resultFor(currentVersion, current, latestVersion, source) {
|
|
41085
|
+
const latest2 = parseSemVer(latestVersion);
|
|
41086
|
+
return compareSemVer(current, latest2) < 0 ? { status: "update-available", currentVersion, latestVersion, installCommand: FIXED_INSTALL_COMMAND, source } : { status: "up-to-date", currentVersion, latestVersion, source };
|
|
41087
|
+
}
|
|
41088
|
+
function cancelWithoutWaiting(cancel) {
|
|
41089
|
+
try {
|
|
41090
|
+
cancel().catch(() => {});
|
|
41091
|
+
} catch {}
|
|
41092
|
+
}
|
|
41093
|
+
async function boundedResponseText(response) {
|
|
41094
|
+
const declared = response.headers.get("content-length");
|
|
41095
|
+
if (declared !== null && /^\d+$/.test(declared) && BigInt(declared) > BigInt(RESPONSE_BODY_LIMIT_BYTES)) {
|
|
41096
|
+
if (response.body !== null) {
|
|
41097
|
+
cancelWithoutWaiting(() => response.body.cancel());
|
|
41098
|
+
}
|
|
41099
|
+
return;
|
|
41100
|
+
}
|
|
41101
|
+
if (response.body === null)
|
|
41102
|
+
return "";
|
|
41103
|
+
const reader = response.body.getReader();
|
|
41104
|
+
const decoder = new TextDecoder;
|
|
41105
|
+
let size = 0;
|
|
41106
|
+
let text = "";
|
|
41107
|
+
try {
|
|
41108
|
+
for (;; ) {
|
|
41109
|
+
const chunk = await reader.read();
|
|
41110
|
+
if (chunk.done)
|
|
41111
|
+
break;
|
|
41112
|
+
size += chunk.value.byteLength;
|
|
41113
|
+
if (size > RESPONSE_BODY_LIMIT_BYTES) {
|
|
41114
|
+
cancelWithoutWaiting(() => reader.cancel());
|
|
41115
|
+
return;
|
|
41116
|
+
}
|
|
41117
|
+
text += decoder.decode(chunk.value, { stream: true });
|
|
41118
|
+
}
|
|
41119
|
+
return text + decoder.decode();
|
|
41120
|
+
} finally {
|
|
41121
|
+
reader.releaseLock();
|
|
41122
|
+
}
|
|
41123
|
+
}
|
|
41124
|
+
function unavailable(currentVersion, reason, cache) {
|
|
41125
|
+
return {
|
|
41126
|
+
status: "unavailable",
|
|
41127
|
+
currentVersion,
|
|
41128
|
+
reason,
|
|
41129
|
+
...cache?.latestVersion !== undefined ? { cachedLatestVersion: cache.latestVersion } : {}
|
|
41130
|
+
};
|
|
41131
|
+
}
|
|
41132
|
+
function saveCache(file, cache) {
|
|
41133
|
+
try {
|
|
41134
|
+
writeOwnerOnlyFileAtomic(file, `${JSON.stringify(cache, null, 2)}
|
|
41135
|
+
`);
|
|
41136
|
+
return true;
|
|
41137
|
+
} catch {
|
|
41138
|
+
return false;
|
|
41139
|
+
}
|
|
41140
|
+
}
|
|
41141
|
+
function mergeSuccessfulCache(committed, latestVersion, successAt) {
|
|
41142
|
+
if (committed.latestVersion === undefined || committed.successAt === undefined) {
|
|
41143
|
+
return { latestVersion, successAt };
|
|
41144
|
+
}
|
|
41145
|
+
if (committed.successAt > successAt)
|
|
41146
|
+
return committed;
|
|
41147
|
+
if (committed.successAt < successAt)
|
|
41148
|
+
return { latestVersion, successAt };
|
|
41149
|
+
const committedVersion = parseSemVer(committed.latestVersion);
|
|
41150
|
+
const candidateVersion = parseSemVer(latestVersion);
|
|
41151
|
+
if (committedVersion !== undefined && candidateVersion !== undefined) {
|
|
41152
|
+
const precedence = compareSemVer(committedVersion, candidateVersion);
|
|
41153
|
+
if (precedence > 0)
|
|
41154
|
+
return committed;
|
|
41155
|
+
if (precedence < 0)
|
|
41156
|
+
return { latestVersion, successAt };
|
|
41157
|
+
if (committed.latestVersion >= latestVersion)
|
|
41158
|
+
return committed;
|
|
41159
|
+
}
|
|
41160
|
+
return { latestVersion, successAt };
|
|
41161
|
+
}
|
|
41162
|
+
async function updateCache(file, update) {
|
|
41163
|
+
try {
|
|
41164
|
+
return await withFileLock2(`${file}.lock`, async () => saveCache(file, update(parseCache(file) ?? {})), {
|
|
41165
|
+
timeoutMs: CACHE_LOCK_TIMEOUT_MS,
|
|
41166
|
+
retryMs: CACHE_LOCK_RETRY_MS,
|
|
41167
|
+
staleMs: CACHE_LOCK_STALE_MS
|
|
41168
|
+
});
|
|
41169
|
+
} catch {
|
|
41170
|
+
return false;
|
|
41171
|
+
}
|
|
41172
|
+
}
|
|
41173
|
+
async function checkVersion(options) {
|
|
41174
|
+
const current = parseSemVer(options.currentVersion);
|
|
41175
|
+
if (current === undefined)
|
|
41176
|
+
return unavailable(options.currentVersion, "invalid-current-version");
|
|
41177
|
+
const now = options.now ?? Date.now;
|
|
41178
|
+
const timestamp = now();
|
|
41179
|
+
const configDir = ensureKeryxConfigDir(options.cacheDir);
|
|
41180
|
+
const cacheFile = path121.join(configDir, "version-check.json");
|
|
41181
|
+
const cache = parseCache(cacheFile);
|
|
41182
|
+
if (cache?.latestVersion !== undefined && cache.successAt !== undefined && timestamp - cache.successAt >= 0 && timestamp - cache.successAt < SUCCESS_CACHE_TTL_MS) {
|
|
41183
|
+
return resultFor(options.currentVersion, current, cache.latestVersion, "cache");
|
|
41184
|
+
}
|
|
41185
|
+
if (cache?.failureAt !== undefined && timestamp - cache.failureAt >= 0 && timestamp - cache.failureAt < FAILURE_BACKOFF_MS) {
|
|
41186
|
+
return unavailable(options.currentVersion, "suppressed", cache);
|
|
41187
|
+
}
|
|
41188
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
41189
|
+
const controller = new AbortController;
|
|
41190
|
+
const timer = options.timer ?? SYSTEM_TIMER;
|
|
41191
|
+
let timeout;
|
|
41192
|
+
let timeoutScheduled = false;
|
|
41193
|
+
let failure;
|
|
41194
|
+
let latestVersion;
|
|
41195
|
+
try {
|
|
41196
|
+
timeout = timer.schedule(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
41197
|
+
timeoutScheduled = true;
|
|
41198
|
+
const response = await fetchImpl(REGISTRY_URL, {
|
|
41199
|
+
method: "GET",
|
|
41200
|
+
headers: { accept: "application/json" },
|
|
41201
|
+
signal: controller.signal,
|
|
41202
|
+
credentials: "omit"
|
|
41203
|
+
});
|
|
41204
|
+
if (!response.ok) {
|
|
41205
|
+
failure = "http";
|
|
41206
|
+
} else {
|
|
41207
|
+
const body = await boundedResponseText(response);
|
|
41208
|
+
if (body === undefined) {
|
|
41209
|
+
failure = "response-too-large";
|
|
41210
|
+
} else {
|
|
41211
|
+
let parsed;
|
|
41212
|
+
try {
|
|
41213
|
+
parsed = JSON.parse(body);
|
|
41214
|
+
} catch {
|
|
41215
|
+
parsed = undefined;
|
|
41216
|
+
}
|
|
41217
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
41218
|
+
failure = "malformed-response";
|
|
41219
|
+
} else {
|
|
41220
|
+
const record = parsed;
|
|
41221
|
+
if (record.name !== "@mrciphersmith/keryx" || typeof record.version !== "string") {
|
|
41222
|
+
failure = "malformed-response";
|
|
41223
|
+
} else if (parseSemVer(record.version) === undefined) {
|
|
41224
|
+
failure = "invalid-latest-version";
|
|
41225
|
+
} else {
|
|
41226
|
+
latestVersion = record.version;
|
|
41227
|
+
}
|
|
41228
|
+
}
|
|
41229
|
+
}
|
|
41230
|
+
}
|
|
41231
|
+
} catch {
|
|
41232
|
+
failure = controller.signal.aborted ? "timeout" : "network";
|
|
41233
|
+
} finally {
|
|
41234
|
+
if (timeoutScheduled) {
|
|
41235
|
+
try {
|
|
41236
|
+
timer.cancel(timeout);
|
|
41237
|
+
} catch {}
|
|
41238
|
+
}
|
|
41239
|
+
}
|
|
41240
|
+
if (latestVersion === undefined) {
|
|
41241
|
+
await updateCache(cacheFile, (committed) => ({ ...committed, failureAt: timestamp }));
|
|
41242
|
+
return unavailable(options.currentVersion, failure ?? "network", cache);
|
|
41243
|
+
}
|
|
41244
|
+
await updateCache(cacheFile, (committed) => mergeSuccessfulCache(committed, latestVersion, timestamp));
|
|
41245
|
+
return resultFor(options.currentVersion, current, latestVersion, "registry");
|
|
41246
|
+
}
|
|
41247
|
+
|
|
40947
41248
|
// src/tui/shell-chrome.ts
|
|
40948
41249
|
function onKeypress2(r, handler) {
|
|
40949
41250
|
r._internalKeyInput.onInternal("keypress", handler);
|
|
@@ -40957,6 +41258,14 @@ var SIDEBAR_BORDER_LEFT = 1;
|
|
|
40957
41258
|
var SIDEBAR_PADDING_LEFT = 2;
|
|
40958
41259
|
var SIDEBAR_PADDING_RIGHT = 1;
|
|
40959
41260
|
var SIDEBAR_TEXT_WIDTH = SIDEBAR_WIDTH - SIDEBAR_BORDER_LEFT - SIDEBAR_PADDING_LEFT - SIDEBAR_PADDING_RIGHT;
|
|
41261
|
+
function formatSidebarVersionUpdateAdvisory(result) {
|
|
41262
|
+
const advisory = formatVersionUpdateAdvisory(result);
|
|
41263
|
+
if (advisory === undefined || result.status !== "update-available")
|
|
41264
|
+
return;
|
|
41265
|
+
const split = Math.ceil(result.installCommand.length / 2);
|
|
41266
|
+
return advisory.replace(result.installCommand, `${result.installCommand.slice(0, split)}
|
|
41267
|
+
${result.installCommand.slice(split)}`);
|
|
41268
|
+
}
|
|
40960
41269
|
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
40961
41270
|
var SPINNER_MS = 120;
|
|
40962
41271
|
var TOAST_MS = 5000;
|
|
@@ -40986,6 +41295,7 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
40986
41295
|
const toastMs = opts.toastMs ?? TOAST_MS;
|
|
40987
41296
|
const filter = opts.filterCommands ?? ((query) => prefixFilter(opts.commands, query));
|
|
40988
41297
|
let uid = 0;
|
|
41298
|
+
let alive = true;
|
|
40989
41299
|
const rootRow = new otui.BoxRenderable(r, { id: "root-row", flexGrow: 1, flexDirection: "row" });
|
|
40990
41300
|
r.root.add(rootRow);
|
|
40991
41301
|
const main = new otui.BoxRenderable(r, { id: "main", flexGrow: 1, minWidth: 0, flexDirection: "column" });
|
|
@@ -41004,6 +41314,21 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
41004
41314
|
rootRow.add(sidebar);
|
|
41005
41315
|
const sidebarTop = new otui.BoxRenderable(r, { id: "sb-top", flexShrink: 0, flexDirection: "column" });
|
|
41006
41316
|
sidebar.add(sidebarTop);
|
|
41317
|
+
if (opts.versionCheck !== undefined) {
|
|
41318
|
+
const versionNotice = new otui.TextRenderable(r, {
|
|
41319
|
+
id: `sb-version-${uid++}`,
|
|
41320
|
+
content: ""
|
|
41321
|
+
});
|
|
41322
|
+
sidebarTop.add(versionNotice);
|
|
41323
|
+
opts.versionCheck.then((result) => {
|
|
41324
|
+
const advisory = formatSidebarVersionUpdateAdvisory(result);
|
|
41325
|
+
if (!alive || advisory === undefined)
|
|
41326
|
+
return;
|
|
41327
|
+
try {
|
|
41328
|
+
versionNotice.content = otui.t`${otui.yellow(advisory)}`;
|
|
41329
|
+
} catch {}
|
|
41330
|
+
}, () => {});
|
|
41331
|
+
}
|
|
41007
41332
|
const sidebarSpacer = new otui.BoxRenderable(r, { id: "sb-spacer", flexGrow: 1 });
|
|
41008
41333
|
sidebar.add(sidebarSpacer);
|
|
41009
41334
|
const toastText = new otui.TextRenderable(r, { id: "sb-toast", content: "" });
|
|
@@ -41384,6 +41709,7 @@ async function createShellChrome(otui, renderer, opts) {
|
|
|
41384
41709
|
};
|
|
41385
41710
|
},
|
|
41386
41711
|
destroy: () => {
|
|
41712
|
+
alive = false;
|
|
41387
41713
|
clearBusyTimer();
|
|
41388
41714
|
clearToastTimer();
|
|
41389
41715
|
unsubscribeMenuKeys();
|
|
@@ -42847,7 +43173,8 @@ async function launchTuiAgentShell(opts) {
|
|
|
42847
43173
|
placeholder: "type a task or / for commands \xB7 Enter send \xB7 Shift+Enter newline",
|
|
42848
43174
|
commands: commandsForMode("agent"),
|
|
42849
43175
|
headerMeta: "\u21910 \u21930",
|
|
42850
|
-
filterCommands: (query) => filterCommands(query, "agent")
|
|
43176
|
+
filterCommands: (query) => filterCommands(query, "agent"),
|
|
43177
|
+
...opts.versionCheck !== undefined ? { versionCheck: opts.versionCheck } : {}
|
|
42851
43178
|
});
|
|
42852
43179
|
mountedChrome = chrome;
|
|
42853
43180
|
const transcript = chrome.transcript;
|
|
@@ -43905,7 +44232,8 @@ async function mountChatShell(otui, renderer, opts) {
|
|
|
43905
44232
|
placeholder: "type a message or / for commands \xB7 Enter send \xB7 Shift+Enter newline",
|
|
43906
44233
|
commands: commandsForMode("chat"),
|
|
43907
44234
|
headerMeta: "~0",
|
|
43908
|
-
filterCommands: (query) => filterCommands(query, "chat")
|
|
44235
|
+
filterCommands: (query) => filterCommands(query, "chat"),
|
|
44236
|
+
...opts.versionCheck !== undefined ? { versionCheck: opts.versionCheck } : {}
|
|
43909
44237
|
});
|
|
43910
44238
|
let uid = 0;
|
|
43911
44239
|
const transcript = chrome.transcript;
|
|
@@ -44057,7 +44385,8 @@ async function launchTuiChatShell(opts) {
|
|
|
44057
44385
|
},
|
|
44058
44386
|
onExit: () => {
|
|
44059
44387
|
r.destroy();
|
|
44060
|
-
}
|
|
44388
|
+
},
|
|
44389
|
+
...opts.versionCheck !== undefined ? { versionCheck: opts.versionCheck } : {}
|
|
44061
44390
|
});
|
|
44062
44391
|
await Promise.race([exited, handle.done]);
|
|
44063
44392
|
return true;
|
|
@@ -44072,6 +44401,76 @@ async function launchTuiChatShell(opts) {
|
|
|
44072
44401
|
|
|
44073
44402
|
// src/commands/shell.ts
|
|
44074
44403
|
init_shell_config();
|
|
44404
|
+
// package.json
|
|
44405
|
+
var package_default = {
|
|
44406
|
+
name: "@mrciphersmith/keryx",
|
|
44407
|
+
version: "0.2.18",
|
|
44408
|
+
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
44409
|
+
private: false,
|
|
44410
|
+
publishConfig: {
|
|
44411
|
+
access: "public"
|
|
44412
|
+
},
|
|
44413
|
+
license: "MIT",
|
|
44414
|
+
type: "module",
|
|
44415
|
+
repository: {
|
|
44416
|
+
type: "git",
|
|
44417
|
+
url: "git+ssh://git@github.com/MrCipherSmith/keryx.git"
|
|
44418
|
+
},
|
|
44419
|
+
keywords: [
|
|
44420
|
+
"ai-agents",
|
|
44421
|
+
"coding-agents",
|
|
44422
|
+
"agent-harness",
|
|
44423
|
+
"agent-context",
|
|
44424
|
+
"repository-context",
|
|
44425
|
+
"code-graph",
|
|
44426
|
+
"project-memory",
|
|
44427
|
+
"test-impact-analysis",
|
|
44428
|
+
"developer-tools",
|
|
44429
|
+
"model-context-protocol",
|
|
44430
|
+
"mcp",
|
|
44431
|
+
"claude-code",
|
|
44432
|
+
"cursor",
|
|
44433
|
+
"codex",
|
|
44434
|
+
"cli",
|
|
44435
|
+
"bun"
|
|
44436
|
+
],
|
|
44437
|
+
bin: {
|
|
44438
|
+
keryx: "./dist/cli.js"
|
|
44439
|
+
},
|
|
44440
|
+
scripts: {
|
|
44441
|
+
keryx: "bun ./src/cli.ts",
|
|
44442
|
+
build: "bun build ./src/cli.ts --outdir ./dist --target bun --external @modelcontextprotocol/sdk --external web-tree-sitter --external @opentui/core && bun build ./src/harness/process/sandbox/proxy-worker.ts --outdir ./dist --target bun --external @modelcontextprotocol/sdk --external web-tree-sitter --external @opentui/core",
|
|
44443
|
+
prepare: "bun run build",
|
|
44444
|
+
typecheck: "tsc --noEmit",
|
|
44445
|
+
test: "bun test",
|
|
44446
|
+
check: "tsc --noEmit && bun test",
|
|
44447
|
+
"check:doc-links": "bun scripts/check-doc-links.ts",
|
|
44448
|
+
"test:guards": "bun test src/lib/config-dir.ast.test.ts src/lib/config-dir.readers.test.ts src/lib/production-graph.test.ts src/harness/policy/profiles.test.ts src/lib/serve-server.test.ts"
|
|
44449
|
+
},
|
|
44450
|
+
files: [
|
|
44451
|
+
"dist",
|
|
44452
|
+
"src/gdgraph",
|
|
44453
|
+
"src/gdskills/bundled",
|
|
44454
|
+
"src/gdskills/contracts",
|
|
44455
|
+
"LICENSE",
|
|
44456
|
+
"README.md",
|
|
44457
|
+
"package.json"
|
|
44458
|
+
],
|
|
44459
|
+
dependencies: {},
|
|
44460
|
+
optionalDependencies: {
|
|
44461
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
44462
|
+
"@opentui/core": "^0.4.5",
|
|
44463
|
+
"web-tree-sitter": "^0.22.0"
|
|
44464
|
+
},
|
|
44465
|
+
devDependencies: {
|
|
44466
|
+
"@types/bun": "latest",
|
|
44467
|
+
"bun-types": "latest",
|
|
44468
|
+
typescript: "^5"
|
|
44469
|
+
},
|
|
44470
|
+
engines: {
|
|
44471
|
+
bun: ">=1.1.0"
|
|
44472
|
+
}
|
|
44473
|
+
};
|
|
44075
44474
|
|
|
44076
44475
|
// src/commands/select.ts
|
|
44077
44476
|
init_guard2();
|
|
@@ -44380,6 +44779,7 @@ Starting a new session.
|
|
|
44380
44779
|
provider = makeActive();
|
|
44381
44780
|
};
|
|
44382
44781
|
for await (const line of io.lines) {
|
|
44782
|
+
io.onSafeBoundary?.();
|
|
44383
44783
|
if (line.startsWith("/")) {
|
|
44384
44784
|
const parts = line.trim().split(/\s+/);
|
|
44385
44785
|
const command = parts[0] ?? "";
|
|
@@ -44528,6 +44928,7 @@ Starting a new session.
|
|
|
44528
44928
|
} else {
|
|
44529
44929
|
history.pop();
|
|
44530
44930
|
}
|
|
44931
|
+
io.onSafeBoundary?.();
|
|
44531
44932
|
io.write(`
|
|
44532
44933
|
|
|
44533
44934
|
`);
|
|
@@ -44609,7 +45010,32 @@ function countRows(text, columns) {
|
|
|
44609
45010
|
}
|
|
44610
45011
|
return rows;
|
|
44611
45012
|
}
|
|
44612
|
-
function
|
|
45013
|
+
function createVersionAdvisoryBoundary(versionCheck) {
|
|
45014
|
+
let active = true;
|
|
45015
|
+
let pending;
|
|
45016
|
+
let shown = false;
|
|
45017
|
+
versionCheck.then((result) => {
|
|
45018
|
+
if (active)
|
|
45019
|
+
pending = formatVersionUpdateAdvisory(result);
|
|
45020
|
+
}, () => {});
|
|
45021
|
+
return {
|
|
45022
|
+
flush: (write) => {
|
|
45023
|
+
if (!active || shown || pending === undefined)
|
|
45024
|
+
return;
|
|
45025
|
+
shown = true;
|
|
45026
|
+
const advisory = pending;
|
|
45027
|
+
pending = undefined;
|
|
45028
|
+
write(`
|
|
45029
|
+
${advisory}
|
|
45030
|
+
`);
|
|
45031
|
+
},
|
|
45032
|
+
destroy: () => {
|
|
45033
|
+
active = false;
|
|
45034
|
+
pending = undefined;
|
|
45035
|
+
}
|
|
45036
|
+
};
|
|
45037
|
+
}
|
|
45038
|
+
function createRichIo(lines, versionCheck) {
|
|
44613
45039
|
const stdout2 = process.stdout;
|
|
44614
45040
|
const rich = colorEnabled() && Boolean(stdout2.isTTY);
|
|
44615
45041
|
const out = (s) => {
|
|
@@ -44619,6 +45045,7 @@ function createRichIo(lines) {
|
|
|
44619
45045
|
let frame = 0;
|
|
44620
45046
|
let awaitingFirstToken = false;
|
|
44621
45047
|
let raw = "";
|
|
45048
|
+
const advisory = createVersionAdvisoryBoundary(versionCheck);
|
|
44622
45049
|
const stopSpinner = () => {
|
|
44623
45050
|
if (spinner !== undefined) {
|
|
44624
45051
|
clearInterval(spinner);
|
|
@@ -44702,10 +45129,18 @@ ${GUTTER}${style.cyan("\u25C6")} ${style.bold(title)} ${style.dim(subtitle)}
|
|
|
44702
45129
|
|
|
44703
45130
|
`);
|
|
44704
45131
|
}
|
|
45132
|
+
advisory.flush(emitSystem);
|
|
44705
45133
|
printPrompt();
|
|
44706
45134
|
};
|
|
44707
|
-
const io = {
|
|
44708
|
-
|
|
45135
|
+
const io = {
|
|
45136
|
+
lines,
|
|
45137
|
+
write,
|
|
45138
|
+
onTurnStart,
|
|
45139
|
+
onTurnEnd,
|
|
45140
|
+
onSystem: emitSystem,
|
|
45141
|
+
onSafeBoundary: () => advisory.flush(emitSystem)
|
|
45142
|
+
};
|
|
45143
|
+
return { io, emitSystem, printHeader, printPrompt, destroy: advisory.destroy };
|
|
44709
45144
|
}
|
|
44710
45145
|
function turnSeparator() {
|
|
44711
45146
|
return style.dim("\u2500".repeat(24));
|
|
@@ -44926,6 +45361,7 @@ New session ${shortSessionId(live.summary.id)}.
|
|
|
44926
45361
|
if (line === undefined) {
|
|
44927
45362
|
return;
|
|
44928
45363
|
}
|
|
45364
|
+
rich.safeBoundary?.();
|
|
44929
45365
|
if (line.startsWith("/")) {
|
|
44930
45366
|
const parts = line.trim().split(/\s+/);
|
|
44931
45367
|
const command = parts[0] ?? "";
|
|
@@ -45022,6 +45458,7 @@ ${GUTTER}${usageLine}
|
|
|
45022
45458
|
${GUTTER}${turnSeparator()}
|
|
45023
45459
|
|
|
45024
45460
|
`);
|
|
45461
|
+
rich.safeBoundary?.();
|
|
45025
45462
|
rich.printPrompt();
|
|
45026
45463
|
}
|
|
45027
45464
|
}
|
|
@@ -45100,13 +45537,17 @@ function chooseShellSurface(flags, isTty) {
|
|
|
45100
45537
|
}
|
|
45101
45538
|
return flags.modeFlag === false ? "tui-chat" : "tui-agent";
|
|
45102
45539
|
}
|
|
45103
|
-
async function shellCommand(args2) {
|
|
45540
|
+
async function shellCommand(args2, runtime = {}) {
|
|
45541
|
+
const versionCheck = (runtime.checkVersion ?? (() => checkVersion({
|
|
45542
|
+
currentVersion: package_default.version,
|
|
45543
|
+
...runtime.cacheDir !== undefined ? { cacheDir: runtime.cacheDir } : {}
|
|
45544
|
+
})))();
|
|
45104
45545
|
const flags = parseShellCliFlags(args2);
|
|
45105
45546
|
let providerArg = flags.providerArg;
|
|
45106
45547
|
let modelArg = flags.modelArg;
|
|
45107
45548
|
let baseUrl = flags.baseUrl;
|
|
45108
45549
|
let modeFlag = flags.modeFlag;
|
|
45109
|
-
const surface = chooseShellSurface(flags, process.stdout.isTTY === true);
|
|
45550
|
+
const surface = chooseShellSurface(flags, runtime.isTty ?? process.stdout.isTTY === true);
|
|
45110
45551
|
if (surface !== "readline") {
|
|
45111
45552
|
const cwd = process.cwd();
|
|
45112
45553
|
const tuiProviderFactory = realMakeProvider(() => {});
|
|
@@ -45151,7 +45592,7 @@ async function shellCommand(args2) {
|
|
|
45151
45592
|
modelId: sel.model
|
|
45152
45593
|
}),
|
|
45153
45594
|
maxToolCalls: resolveAgentMaxToolCalls(),
|
|
45154
|
-
idSeq: () =>
|
|
45595
|
+
idSeq: () => randomUUID10()
|
|
45155
45596
|
};
|
|
45156
45597
|
};
|
|
45157
45598
|
const redetect = () => detectProviders({
|
|
@@ -45163,7 +45604,8 @@ async function shellCommand(args2) {
|
|
|
45163
45604
|
providerArg,
|
|
45164
45605
|
modelArg,
|
|
45165
45606
|
baseUrl,
|
|
45166
|
-
detect: redetect
|
|
45607
|
+
detect: redetect,
|
|
45608
|
+
...runtime.cacheDir !== undefined ? { configDir: runtime.cacheDir } : {}
|
|
45167
45609
|
});
|
|
45168
45610
|
const tuiInitial = startup.initial;
|
|
45169
45611
|
const tuiDetected = startup.detected;
|
|
@@ -45173,7 +45615,7 @@ async function shellCommand(args2) {
|
|
|
45173
45615
|
if (flags.resumePick === true && chatResumeId === undefined) {
|
|
45174
45616
|
chatResumeId = latestSession(cwd)?.id;
|
|
45175
45617
|
}
|
|
45176
|
-
if (await launchTuiChatShell({
|
|
45618
|
+
if (await (runtime.launchChat ?? launchTuiChatShell)({
|
|
45177
45619
|
detected: tuiDetected,
|
|
45178
45620
|
redetect,
|
|
45179
45621
|
...tuiInitial !== undefined ? { initial: tuiInitial } : {},
|
|
@@ -45181,18 +45623,19 @@ async function shellCommand(args2) {
|
|
|
45181
45623
|
makeShellDeps: (sel) => ({
|
|
45182
45624
|
makeProvider: chatFactory,
|
|
45183
45625
|
clock: () => new Date().toISOString(),
|
|
45184
|
-
idSeq: () =>
|
|
45626
|
+
idSeq: () => randomUUID10(),
|
|
45185
45627
|
initial: sel,
|
|
45186
45628
|
session: {
|
|
45187
45629
|
cwd,
|
|
45188
45630
|
...flags.continueLast === true ? { continueLast: true } : {},
|
|
45189
45631
|
...chatResumeId !== undefined ? { resumeId: chatResumeId } : {}
|
|
45190
45632
|
}
|
|
45191
|
-
})
|
|
45633
|
+
}),
|
|
45634
|
+
versionCheck
|
|
45192
45635
|
})) {
|
|
45193
45636
|
return;
|
|
45194
45637
|
}
|
|
45195
|
-
} else if (await launchTuiAgentShell({
|
|
45638
|
+
} else if (await (runtime.launchAgent ?? launchTuiAgentShell)({
|
|
45196
45639
|
detected: tuiDetected,
|
|
45197
45640
|
makeAgentDeps,
|
|
45198
45641
|
redetect,
|
|
@@ -45202,7 +45645,8 @@ async function shellCommand(args2) {
|
|
|
45202
45645
|
...flags.continueLast === true ? { continueLast: true } : {},
|
|
45203
45646
|
...flags.resumeId !== undefined ? { resumeId: flags.resumeId } : {},
|
|
45204
45647
|
...flags.resumePick === true ? { pickOnStart: true } : {}
|
|
45205
|
-
}
|
|
45648
|
+
},
|
|
45649
|
+
versionCheck
|
|
45206
45650
|
})) {
|
|
45207
45651
|
return;
|
|
45208
45652
|
}
|
|
@@ -45210,7 +45654,7 @@ async function shellCommand(args2) {
|
|
|
45210
45654
|
const rl = readline2.createInterface({ input: process.stdin });
|
|
45211
45655
|
const lineIterator = rl[Symbol.asyncIterator]();
|
|
45212
45656
|
const sharedLines = { [Symbol.asyncIterator]: () => lineIterator };
|
|
45213
|
-
const { io, emitSystem, printHeader, printPrompt } = createRichIo(sharedLines);
|
|
45657
|
+
const { io, emitSystem, printHeader, printPrompt, destroy } = createRichIo(sharedLines, versionCheck);
|
|
45214
45658
|
let provider;
|
|
45215
45659
|
let model;
|
|
45216
45660
|
try {
|
|
@@ -45249,7 +45693,7 @@ async function shellCommand(args2) {
|
|
|
45249
45693
|
const deps = {
|
|
45250
45694
|
makeProvider: baseFactory,
|
|
45251
45695
|
clock: () => new Date().toISOString(),
|
|
45252
|
-
idSeq: () =>
|
|
45696
|
+
idSeq: () => randomUUID10(),
|
|
45253
45697
|
initial: baseUrl === undefined ? { provider, model } : { provider, model, baseUrl },
|
|
45254
45698
|
selectProviderModel: realSelectProviderModel(baseUrl)
|
|
45255
45699
|
};
|
|
@@ -45293,13 +45737,13 @@ async function shellCommand(args2) {
|
|
|
45293
45737
|
modelId: model
|
|
45294
45738
|
}),
|
|
45295
45739
|
maxToolCalls: resolveAgentMaxToolCalls(),
|
|
45296
|
-
idSeq: () =>
|
|
45740
|
+
idSeq: () => randomUUID10()
|
|
45297
45741
|
};
|
|
45298
45742
|
let resumeId = flags.resumeId;
|
|
45299
45743
|
if (flags.resumePick === true && resumeId === undefined) {
|
|
45300
45744
|
resumeId = latestSession(process.cwd())?.id;
|
|
45301
45745
|
}
|
|
45302
|
-
await runAgentRepl(sharedLines, { printPrompt }, agentDeps, metaprojectPort, {
|
|
45746
|
+
await runAgentRepl(sharedLines, { printPrompt, safeBoundary: io.onSafeBoundary }, agentDeps, metaprojectPort, {
|
|
45303
45747
|
cwd: process.cwd(),
|
|
45304
45748
|
...flags.continueLast === true ? { continueLast: true } : {},
|
|
45305
45749
|
...resumeId !== undefined ? { resumeId } : {}
|
|
@@ -45319,6 +45763,7 @@ async function shellCommand(args2) {
|
|
|
45319
45763
|
});
|
|
45320
45764
|
}
|
|
45321
45765
|
} finally {
|
|
45766
|
+
destroy();
|
|
45322
45767
|
rl.close();
|
|
45323
45768
|
}
|
|
45324
45769
|
}
|
|
@@ -45463,7 +45908,7 @@ Shell:
|
|
|
45463
45908
|
init_fs();
|
|
45464
45909
|
import { readFile as readFile63 } from "fs/promises";
|
|
45465
45910
|
import { stdin } from "process";
|
|
45466
|
-
import
|
|
45911
|
+
import path122 from "path";
|
|
45467
45912
|
var MODULES = [
|
|
45468
45913
|
{ name: "gdgraph", flag: "--no-gdgraph", desc: "code graph, symbols, affected context", defaultEnabled: true },
|
|
45469
45914
|
{ name: "gdctx", flag: "--no-gdctx", desc: "token-aware command/read output", defaultEnabled: true },
|
|
@@ -45502,8 +45947,8 @@ async function modulesCommand(args2 = []) {
|
|
|
45502
45947
|
return;
|
|
45503
45948
|
}
|
|
45504
45949
|
const wantsJson = args2.includes("--json") && (sub === undefined || sub === "status" || sub === "list" || sub === "--json");
|
|
45505
|
-
const metaprojectRoot =
|
|
45506
|
-
const manifestPath =
|
|
45950
|
+
const metaprojectRoot = path122.join(process.cwd(), ".metaproject");
|
|
45951
|
+
const manifestPath = path122.join(metaprojectRoot, "metaproject.json");
|
|
45507
45952
|
if (!await pathExists(manifestPath)) {
|
|
45508
45953
|
if (wantsJson) {
|
|
45509
45954
|
console.log(JSON.stringify({ schemaVersion: 1, error: "not-initialized", modules: [] }, null, 2));
|
|
@@ -45617,18 +46062,18 @@ function printHelp16() {
|
|
|
45617
46062
|
}
|
|
45618
46063
|
|
|
45619
46064
|
// src/commands/serve.ts
|
|
45620
|
-
import { randomUUID as
|
|
46065
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
45621
46066
|
|
|
45622
46067
|
// src/lib/serve-config.ts
|
|
45623
46068
|
init_config_dir();
|
|
45624
46069
|
import { existsSync as existsSync24 } from "fs";
|
|
45625
|
-
import
|
|
46070
|
+
import path123 from "path";
|
|
45626
46071
|
var SERVE_CONFIG_SCHEMA_VERSION = "1.0.0";
|
|
45627
46072
|
var DEFAULT_SERVE_BIND_ADDRESS = "127.0.0.1";
|
|
45628
46073
|
var DEFAULT_SERVE_PORT = 7377;
|
|
45629
46074
|
var DEFAULT_SERVE_PROFILE = "remote-restricted";
|
|
45630
46075
|
function serveConfigPath(dir) {
|
|
45631
|
-
return
|
|
46076
|
+
return path123.join(keryxConfigDir(dir), "serve.json");
|
|
45632
46077
|
}
|
|
45633
46078
|
function parseIpv4(value) {
|
|
45634
46079
|
const parts = value.split(".");
|
|
@@ -45944,21 +46389,21 @@ function saveServeConfig(config, dir, onWarn) {
|
|
|
45944
46389
|
|
|
45945
46390
|
// src/lib/serve-credential.ts
|
|
45946
46391
|
init_config_dir();
|
|
45947
|
-
import { createHash as createHash19, randomBytes as randomBytes2, randomUUID as
|
|
46392
|
+
import { createHash as createHash19, randomBytes as randomBytes2, randomUUID as randomUUID11 } from "crypto";
|
|
45948
46393
|
import {
|
|
45949
46394
|
chmodSync as chmodSync4,
|
|
45950
46395
|
closeSync as closeSync3,
|
|
45951
46396
|
existsSync as existsSync25,
|
|
45952
46397
|
fsyncSync as fsyncSync2,
|
|
45953
46398
|
openSync as openSync3,
|
|
45954
|
-
renameSync as
|
|
46399
|
+
renameSync as renameSync4,
|
|
45955
46400
|
statSync as statSync5,
|
|
45956
|
-
unlinkSync as
|
|
46401
|
+
unlinkSync as unlinkSync3,
|
|
45957
46402
|
writeFileSync as writeFileSync8
|
|
45958
46403
|
} from "fs";
|
|
45959
|
-
import
|
|
46404
|
+
import path124 from "path";
|
|
45960
46405
|
function serveCredentialPath(dir) {
|
|
45961
|
-
return
|
|
46406
|
+
return path124.join(keryxConfigDir(dir), "serve-credentials.json");
|
|
45962
46407
|
}
|
|
45963
46408
|
function constantTimeEqual(a, b) {
|
|
45964
46409
|
const width = Math.max(a.length, b.length);
|
|
@@ -46028,7 +46473,7 @@ function readServeCredential(dir) {
|
|
|
46028
46473
|
}
|
|
46029
46474
|
function writeStore(store, dir) {
|
|
46030
46475
|
const file = serveCredentialPath(dir);
|
|
46031
|
-
const temp = `${file}.${
|
|
46476
|
+
const temp = `${file}.${randomUUID11()}.tmp`;
|
|
46032
46477
|
try {
|
|
46033
46478
|
ensureKeryxConfigDir(dir);
|
|
46034
46479
|
const handle = openSync3(temp, "wx", 384);
|
|
@@ -46039,12 +46484,12 @@ function writeStore(store, dir) {
|
|
|
46039
46484
|
} finally {
|
|
46040
46485
|
closeSync3(handle);
|
|
46041
46486
|
}
|
|
46042
|
-
|
|
46487
|
+
renameSync4(temp, file);
|
|
46043
46488
|
tighten2(file, 384);
|
|
46044
46489
|
return true;
|
|
46045
46490
|
} catch {
|
|
46046
46491
|
try {
|
|
46047
|
-
|
|
46492
|
+
unlinkSync3(temp);
|
|
46048
46493
|
} catch {}
|
|
46049
46494
|
return false;
|
|
46050
46495
|
}
|
|
@@ -46068,7 +46513,7 @@ function mintRecord(now) {
|
|
|
46068
46513
|
const salt = randomBytes2(32).toString("hex");
|
|
46069
46514
|
return {
|
|
46070
46515
|
token,
|
|
46071
|
-
record: { id:
|
|
46516
|
+
record: { id: randomUUID11(), algorithm: "sha256", salt, hash: hashToken(salt, token), createdAt: now }
|
|
46072
46517
|
};
|
|
46073
46518
|
}
|
|
46074
46519
|
function issueServeToken(dir, now = () => new Date().toISOString(), onWaiting) {
|
|
@@ -46189,22 +46634,22 @@ class AuthFailureThrottle {
|
|
|
46189
46634
|
init_config_dir();
|
|
46190
46635
|
import { createHash as createHash20 } from "crypto";
|
|
46191
46636
|
import { existsSync as existsSync26, readdirSync as readdirSync2, rmSync as rmSync2 } from "fs";
|
|
46192
|
-
import
|
|
46637
|
+
import path125 from "path";
|
|
46193
46638
|
var MAX_TURN_EVENTS = 1e4;
|
|
46194
46639
|
function turnsRoot(dir) {
|
|
46195
|
-
return
|
|
46640
|
+
return path125.join(keryxConfigDir(dir), "turns");
|
|
46196
46641
|
}
|
|
46197
46642
|
function turnDir(turnId, dir) {
|
|
46198
|
-
return
|
|
46643
|
+
return path125.join(turnsRoot(dir), turnId);
|
|
46199
46644
|
}
|
|
46200
46645
|
function keyPath(project, idempotencyKey, dir) {
|
|
46201
46646
|
const projectBytes = Buffer.byteLength(project, "utf8");
|
|
46202
46647
|
const digest = createHash20("sha256").update(`${projectBytes}:${project}\x00${idempotencyKey}`, "utf8").digest("hex");
|
|
46203
|
-
return
|
|
46648
|
+
return path125.join(turnsRoot(dir), "keys", `${digest}.json`);
|
|
46204
46649
|
}
|
|
46205
46650
|
function legacyKeyPath(idempotencyKey, dir) {
|
|
46206
46651
|
const digest = createHash20("sha256").update(idempotencyKey, "utf8").digest("hex");
|
|
46207
|
-
return
|
|
46652
|
+
return path125.join(turnsRoot(dir), "keys", `${digest}.json`);
|
|
46208
46653
|
}
|
|
46209
46654
|
function adoptLegacyClaim(project, idempotencyKey, dir) {
|
|
46210
46655
|
const legacy = legacyKeyPath(idempotencyKey, dir);
|
|
@@ -46268,7 +46713,7 @@ function ensureTurnDir(turnId, dir) {
|
|
|
46268
46713
|
}
|
|
46269
46714
|
function createTurnRecord(record, dir) {
|
|
46270
46715
|
ensureTurnDir(record.turnId, dir);
|
|
46271
|
-
writeOwnerOnlyFile(
|
|
46716
|
+
writeOwnerOnlyFile(path125.join(turnDir(record.turnId, dir), "turn.json"), `${JSON.stringify(record, null, 2)}
|
|
46272
46717
|
`);
|
|
46273
46718
|
}
|
|
46274
46719
|
function appendTurnEvent(event, dir, opts) {
|
|
@@ -46277,12 +46722,12 @@ function appendTurnEvent(event, dir, opts) {
|
|
|
46277
46722
|
}
|
|
46278
46723
|
const line = JSON.stringify(event);
|
|
46279
46724
|
try {
|
|
46280
|
-
appendOwnerOnlyLine(
|
|
46725
|
+
appendOwnerOnlyLine(path125.join(turnDir(event.turnId, dir), "events.jsonl"), line);
|
|
46281
46726
|
} catch (error) {
|
|
46282
46727
|
if (error?.code !== "ENOENT") {
|
|
46283
46728
|
throw error;
|
|
46284
46729
|
}
|
|
46285
|
-
appendOwnerOnlyLine(
|
|
46730
|
+
appendOwnerOnlyLine(path125.join(ensureTurnDir(event.turnId, dir), "events.jsonl"), line);
|
|
46286
46731
|
}
|
|
46287
46732
|
return true;
|
|
46288
46733
|
}
|
|
@@ -46290,7 +46735,7 @@ function readTurnEvents(turnId, after = -1, dir) {
|
|
|
46290
46735
|
if (!isTurnId(turnId)) {
|
|
46291
46736
|
return { ok: false, reason: "not-a-turn-id" };
|
|
46292
46737
|
}
|
|
46293
|
-
const read = readTurnFile(
|
|
46738
|
+
const read = readTurnFile(path125.join(turnDir(turnId, dir), "events.jsonl"));
|
|
46294
46739
|
if (!read.ok) {
|
|
46295
46740
|
if (isDefiniteAbsence2(read.reason)) {
|
|
46296
46741
|
return { ok: true, value: [] };
|
|
@@ -46318,7 +46763,7 @@ function readTurnRecord(turnId, dir) {
|
|
|
46318
46763
|
if (!isTurnId(turnId)) {
|
|
46319
46764
|
return { ok: false, reason: "not-a-turn-id" };
|
|
46320
46765
|
}
|
|
46321
|
-
const read = readTurnFile(
|
|
46766
|
+
const read = readTurnFile(path125.join(turnDir(turnId, dir), "turn.json"));
|
|
46322
46767
|
if (!read.ok) {
|
|
46323
46768
|
return { ok: false, reason: read.reason };
|
|
46324
46769
|
}
|
|
@@ -46337,7 +46782,7 @@ function finishTurn(turnId, result, dir) {
|
|
|
46337
46782
|
if (!record.ok) {
|
|
46338
46783
|
return false;
|
|
46339
46784
|
}
|
|
46340
|
-
writeOwnerOnlyFile(
|
|
46785
|
+
writeOwnerOnlyFile(path125.join(turnDir(turnId, dir), "turn.json"), `${JSON.stringify({ ...record.value, result }, null, 2)}
|
|
46341
46786
|
`);
|
|
46342
46787
|
return true;
|
|
46343
46788
|
}
|
|
@@ -46382,8 +46827,8 @@ function releaseIdempotencyKey(project, idempotencyKey, turnId, dir) {
|
|
|
46382
46827
|
}
|
|
46383
46828
|
|
|
46384
46829
|
// src/lib/serve-turn.ts
|
|
46385
|
-
import { randomUUID as
|
|
46386
|
-
import
|
|
46830
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
46831
|
+
import path126 from "path";
|
|
46387
46832
|
init_service();
|
|
46388
46833
|
var REMOTE_ORIGIN = "remote:http";
|
|
46389
46834
|
var MAX_PROMPT_CHARS = 32000;
|
|
@@ -46452,9 +46897,9 @@ function isUuid(value) {
|
|
|
46452
46897
|
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);
|
|
46453
46898
|
}
|
|
46454
46899
|
function resolveProject(declared, dir) {
|
|
46455
|
-
const wanted =
|
|
46900
|
+
const wanted = path126.resolve(declared);
|
|
46456
46901
|
for (const entry of listProjects(dir, () => {})) {
|
|
46457
|
-
if (
|
|
46902
|
+
if (path126.resolve(entry.path) === wanted) {
|
|
46458
46903
|
return { ok: true, project: entry.path };
|
|
46459
46904
|
}
|
|
46460
46905
|
}
|
|
@@ -46501,7 +46946,7 @@ async function redactOut(security, text) {
|
|
|
46501
46946
|
async function runRemoteTurn(input2) {
|
|
46502
46947
|
const scanRoot = input2.scanRoot;
|
|
46503
46948
|
const security = createSecurityService(scanRoot);
|
|
46504
|
-
const newId = input2.newId ?? (() =>
|
|
46949
|
+
const newId = input2.newId ?? (() => randomUUID12());
|
|
46505
46950
|
const clock = input2.clock ?? (() => new Date().toISOString());
|
|
46506
46951
|
const turnId = input2.turnId ?? newId();
|
|
46507
46952
|
const sessionId = input2.request.sessionId ?? newId();
|
|
@@ -46644,7 +47089,7 @@ function outcomeOf(status, gate, unresolvedBlockerIds) {
|
|
|
46644
47089
|
}
|
|
46645
47090
|
function createSubmitTurn(deps) {
|
|
46646
47091
|
return async (request, project) => {
|
|
46647
|
-
const turnId = (deps.newId ?? (() =>
|
|
47092
|
+
const turnId = (deps.newId ?? (() => randomUUID12()))();
|
|
46648
47093
|
const scanned = await scanPrompt(deps.dir, request.prompt);
|
|
46649
47094
|
if (scanned.rejected) {
|
|
46650
47095
|
return { kind: "rejected" };
|
|
@@ -47331,7 +47776,7 @@ function runConfig(args2) {
|
|
|
47331
47776
|
return;
|
|
47332
47777
|
}
|
|
47333
47778
|
const credential = readServeCredential();
|
|
47334
|
-
const credentialId = credential.status === "ok" ? credential.record.id :
|
|
47779
|
+
const credentialId = credential.status === "ok" ? credential.record.id : randomUUID13();
|
|
47335
47780
|
const config = defaultServeConfig(credentialId, {
|
|
47336
47781
|
address: parsed.parsed.values.get("--bind") ?? DEFAULT_SERVE_BIND_ADDRESS,
|
|
47337
47782
|
port: port ?? DEFAULT_SERVE_PORT,
|
|
@@ -47489,7 +47934,7 @@ function printHelp17() {
|
|
|
47489
47934
|
import { spawn as spawn5 } from "child_process";
|
|
47490
47935
|
import { chmod as chmod4, mkdir as mkdir45, readFile as readFile64, readdir as readdir20, writeFile as writeFile42 } from "fs/promises";
|
|
47491
47936
|
import { access as access3, constants, existsSync as existsSync27 } from "fs";
|
|
47492
|
-
import
|
|
47937
|
+
import path127 from "path";
|
|
47493
47938
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
47494
47939
|
init_config();
|
|
47495
47940
|
init_config2();
|
|
@@ -47504,8 +47949,8 @@ async function updateCommand(args2 = []) {
|
|
|
47504
47949
|
return;
|
|
47505
47950
|
}
|
|
47506
47951
|
const projectRoot = process.cwd();
|
|
47507
|
-
const metaprojectRoot =
|
|
47508
|
-
banner("keryx update", `Refreshing the .metaproject workspace in ${
|
|
47952
|
+
const metaprojectRoot = path127.join(projectRoot, ".metaproject");
|
|
47953
|
+
banner("keryx update", `Refreshing the .metaproject workspace in ${path127.basename(projectRoot)}/`);
|
|
47509
47954
|
if (!await pathExists(metaprojectRoot)) {
|
|
47510
47955
|
console.log(` ${style.red(symbols.cross)} Metaproject is not initialized.`);
|
|
47511
47956
|
console.log(` ${style.cyan(symbols.arrow)} Run ${style.cyan("keryx init")} first.`);
|
|
@@ -47548,12 +47993,12 @@ async function updateCommand(args2 = []) {
|
|
|
47548
47993
|
nextSteps(steps);
|
|
47549
47994
|
}
|
|
47550
47995
|
async function refreshServiceFiles(projectRoot, options) {
|
|
47551
|
-
const metaprojectRoot =
|
|
47996
|
+
const metaprojectRoot = path127.join(projectRoot, ".metaproject");
|
|
47552
47997
|
const manifestState = await readManifest5(metaprojectRoot);
|
|
47553
47998
|
const manifest = manifestState.manifest;
|
|
47554
47999
|
const recoveredManifest = !manifestState.exists || !manifestState.valid;
|
|
47555
48000
|
if (manifestState.migrated) {
|
|
47556
|
-
await writeFile42(
|
|
48001
|
+
await writeFile42(path127.join(metaprojectRoot, "metaproject.json"), `${JSON.stringify(manifest, null, 2)}
|
|
47557
48002
|
`, "utf8");
|
|
47558
48003
|
}
|
|
47559
48004
|
const enableGdgraph = moduleEnabled2(manifest, "gdgraph");
|
|
@@ -47588,11 +48033,11 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
47588
48033
|
enableTasks,
|
|
47589
48034
|
enableSecurity
|
|
47590
48035
|
});
|
|
47591
|
-
await writeTextIfChanged4(
|
|
47592
|
-
await writeTextIfChanged4(
|
|
47593
|
-
await writeTextIfChanged4(
|
|
47594
|
-
await writeTextIfChanged4(
|
|
47595
|
-
await writeTextIfChanged4(
|
|
48036
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "core", "README.md"), renderMetaprojectCoreReadme());
|
|
48037
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "hooks", "README.md"), renderHooksReadme());
|
|
48038
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "rules", "README.md"), renderProjectRulesReadme());
|
|
48039
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "skills", "project-rules", "README.md"), renderProjectRulesSkillReadme({ sources: ruleSources }));
|
|
48040
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "index.md"), renderIndexMarkdown({
|
|
47596
48041
|
enableGdgraph,
|
|
47597
48042
|
enableGdctx,
|
|
47598
48043
|
enableGdwiki,
|
|
@@ -47605,7 +48050,7 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
47605
48050
|
ruleSources,
|
|
47606
48051
|
hasDistilledEntrypoints: await hasDistilledEntrypoints(metaprojectRoot)
|
|
47607
48052
|
}));
|
|
47608
|
-
await writeTextIfChanged4(
|
|
48053
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "keryx-dashboard.html"), renderMetaprojectDashboardHtml({
|
|
47609
48054
|
enableGdgraph,
|
|
47610
48055
|
enableGdctx,
|
|
47611
48056
|
enableGdwiki,
|
|
@@ -47617,7 +48062,7 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
47617
48062
|
enableSecurity,
|
|
47618
48063
|
data: dashboardData
|
|
47619
48064
|
}));
|
|
47620
|
-
await writeTextIfMissing4(
|
|
48065
|
+
await writeTextIfMissing4(path127.join(metaprojectRoot, "README.md"), renderMetaprojectReadme({
|
|
47621
48066
|
enableGdgraph,
|
|
47622
48067
|
enableGdctx,
|
|
47623
48068
|
enableGdwiki,
|
|
@@ -47630,24 +48075,24 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
47630
48075
|
}));
|
|
47631
48076
|
if (enableGdgraph) {
|
|
47632
48077
|
await installGdgraphCoreScripts2(metaprojectRoot);
|
|
47633
|
-
await writeTextIfChanged4(
|
|
47634
|
-
await writeTextIfChanged4(
|
|
47635
|
-
await writeTextIfChanged4(
|
|
48078
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "modules", "gdgraph.md"), renderGdgraphManifest());
|
|
48079
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "core", "gdgraph", "README.md"), renderGdgraphCoreReadme());
|
|
48080
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "skills", "gdgraph", "SKILL.md"), renderGdgraphSkillReadme());
|
|
47636
48081
|
await seedAssetsLock(metaprojectRoot);
|
|
47637
48082
|
if (manifest.modules?.gdgraph?.hooks?.gitPostCommit) {
|
|
47638
48083
|
await installManagedHook2(projectRoot, "post-commit", "gdgraph-post-commit", renderGdgraphPostCommitHook());
|
|
47639
48084
|
}
|
|
47640
48085
|
}
|
|
47641
48086
|
if (enableGdctx) {
|
|
47642
|
-
await writeTextIfMissing4(
|
|
47643
|
-
await writeTextIfChanged4(
|
|
47644
|
-
await writeTextIfChanged4(
|
|
47645
|
-
await writeTextIfChanged4(
|
|
48087
|
+
await writeTextIfMissing4(path127.join(metaprojectRoot, "gdctx.config.json"), renderGdctxConfig());
|
|
48088
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "modules", "gdctx.md"), renderGdctxManifest());
|
|
48089
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "core", "gdctx", "README.md"), renderGdctxCoreReadme());
|
|
48090
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "skills", "gdctx", "SKILL.md"), renderGdctxSkillReadme());
|
|
47646
48091
|
}
|
|
47647
48092
|
if (enableGdwiki) {
|
|
47648
|
-
await writeTextIfMissing4(
|
|
47649
|
-
await writeTextIfChanged4(
|
|
47650
|
-
await writeTextIfChanged4(
|
|
48093
|
+
await writeTextIfMissing4(path127.join(metaprojectRoot, "wiki", "templates", "page.md"), renderWikiPageTemplate());
|
|
48094
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "modules", "gdwiki.md"), renderGdwikiManifest());
|
|
48095
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "skills", "gdwiki", "SKILL.md"), renderGdwikiSkillReadme());
|
|
47651
48096
|
if (manifest.modules?.gdgraph?.hooks?.gitPostCommit) {
|
|
47652
48097
|
await installManagedHook2(projectRoot, "post-commit", "gdwiki-post-commit", renderGdwikiPostCommitHook());
|
|
47653
48098
|
}
|
|
@@ -47659,25 +48104,25 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
47659
48104
|
}
|
|
47660
48105
|
}
|
|
47661
48106
|
if (enableHealth) {
|
|
47662
|
-
await writeTextIfMissing4(
|
|
47663
|
-
await writeTextIfChanged4(
|
|
47664
|
-
await writeTextIfChanged4(
|
|
47665
|
-
await writeTextIfChanged4(
|
|
48107
|
+
await writeTextIfMissing4(path127.join(metaprojectRoot, "health.config.json"), renderHealthConfig());
|
|
48108
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "modules", "health.md"), renderHealthManifest());
|
|
48109
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "core", "health", "README.md"), renderHealthCoreReadme());
|
|
48110
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "skills", "health", "SKILL.md"), renderHealthSkillReadme());
|
|
47666
48111
|
if (manifest.modules?.health?.hooks?.gitPostCommit) {
|
|
47667
48112
|
await installManagedHook2(projectRoot, "post-commit", "health-post-commit", renderHealthPostCommitHook());
|
|
47668
48113
|
}
|
|
47669
48114
|
}
|
|
47670
48115
|
if (enableTesting) {
|
|
47671
|
-
await writeTextIfMissing4(
|
|
48116
|
+
await writeTextIfMissing4(path127.join(metaprojectRoot, "testing.config.json"), renderTestingConfig({
|
|
47672
48117
|
postCommitRefresh: Boolean(manifest.modules?.testing?.hooks?.gitPostCommit),
|
|
47673
48118
|
prePushGate: Boolean(manifest.modules?.testing?.hooks?.prePush)
|
|
47674
48119
|
}));
|
|
47675
|
-
await writeTextIfChanged4(
|
|
47676
|
-
await writeTextIfChanged4(
|
|
47677
|
-
await writeTextIfChanged4(
|
|
48120
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "modules", "testing.md"), renderTestingManifest());
|
|
48121
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "core", "testing", "README.md"), renderTestingCoreReadme());
|
|
48122
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "skills", "testing", "SKILL.md"), renderTestingSkillReadme());
|
|
47678
48123
|
if (enableGdwiki) {
|
|
47679
|
-
await writeTextIfMissing4(
|
|
47680
|
-
await writeTextIfMissing4(
|
|
48124
|
+
await writeTextIfMissing4(path127.join(metaprojectRoot, "wiki", "testing", "README.md"), renderTestingWikiReadme());
|
|
48125
|
+
await writeTextIfMissing4(path127.join(metaprojectRoot, "wiki", "testing", "conventions.md"), renderTestingWikiConventions());
|
|
47681
48126
|
}
|
|
47682
48127
|
if (manifest.modules?.testing?.hooks?.gitPostCommit) {
|
|
47683
48128
|
await installManagedHook2(projectRoot, "post-commit", "testing-post-commit", renderTestingPostCommitHook());
|
|
@@ -47690,24 +48135,24 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
47690
48135
|
await installManagedHook2(projectRoot, "post-commit", "metaproject-dashboard-post-commit", renderMetaprojectDashboardPostCommitHook());
|
|
47691
48136
|
}
|
|
47692
48137
|
if (enableMemory) {
|
|
47693
|
-
await writeTextIfMissing4(
|
|
47694
|
-
await writeTextIfMissing4(
|
|
47695
|
-
await writeTextIfChanged4(
|
|
47696
|
-
await writeTextIfChanged4(
|
|
47697
|
-
await writeTextIfChanged4(
|
|
48138
|
+
await writeTextIfMissing4(path127.join(metaprojectRoot, "memory.config.json"), renderMemoryConfig());
|
|
48139
|
+
await writeTextIfMissing4(path127.join(metaprojectRoot, "memory", "templates", "entry.md"), renderMemoryEntryTemplate());
|
|
48140
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "modules", "memory.md"), renderMemoryManifest());
|
|
48141
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "core", "memory", "README.md"), renderMemoryCoreReadme());
|
|
48142
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "skills", "memory", "SKILL.md"), renderMemorySkillReadme());
|
|
47698
48143
|
}
|
|
47699
48144
|
if (enableTasks) {
|
|
47700
|
-
await writeTextIfChanged4(
|
|
47701
|
-
await writeTextIfChanged4(
|
|
47702
|
-
await writeTextIfChanged4(
|
|
47703
|
-
await writeTextIfChanged4(
|
|
47704
|
-
await writeTextIfChanged4(
|
|
47705
|
-
await writeTextIfChanged4(
|
|
48145
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "flows", "README.md"), renderFlowsReadme());
|
|
48146
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "modules", "tasks.md"), renderTasksManifest());
|
|
48147
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "skills", "flow", "SKILL.md"), renderFlowSkillRouter());
|
|
48148
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "skills", "flow", "init.md"), renderFlowInitSkill());
|
|
48149
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "skills", "flow", "manage.md"), renderFlowManageSkill());
|
|
48150
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "skills", "flow", "complete.md"), renderFlowCompleteSkill());
|
|
47706
48151
|
}
|
|
47707
48152
|
if (enableSecurity) {
|
|
47708
|
-
await writeTextIfMissing4(
|
|
47709
|
-
await writeTextIfChanged4(
|
|
47710
|
-
await writeTextIfChanged4(
|
|
48153
|
+
await writeTextIfMissing4(path127.join(metaprojectRoot, "security.config.json"), renderSecurityConfig());
|
|
48154
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "modules", "security.md"), renderSecurityManifest());
|
|
48155
|
+
await writeTextIfChanged4(path127.join(metaprojectRoot, "core", "security", "README.md"), renderSecurityCoreReadme());
|
|
47711
48156
|
if (manifest.modules?.security?.hooks?.prePush) {
|
|
47712
48157
|
await installManagedHook2(projectRoot, "pre-push", "security-pre-push", renderSecurityPrePushHook());
|
|
47713
48158
|
}
|
|
@@ -47756,13 +48201,13 @@ async function refreshServiceFiles(projectRoot, options) {
|
|
|
47756
48201
|
};
|
|
47757
48202
|
}
|
|
47758
48203
|
async function buildDashboard(projectRoot = process.cwd()) {
|
|
47759
|
-
const metaprojectRoot =
|
|
48204
|
+
const metaprojectRoot = path127.join(projectRoot, ".metaproject");
|
|
47760
48205
|
if (!await pathExists(metaprojectRoot)) {
|
|
47761
48206
|
throw new Error("Metaproject is not initialized. Run: keryx init");
|
|
47762
48207
|
}
|
|
47763
48208
|
const manifest = (await readManifest5(metaprojectRoot)).manifest;
|
|
47764
48209
|
const data = await collectDashboardData(metaprojectRoot);
|
|
47765
|
-
const dashboardPath =
|
|
48210
|
+
const dashboardPath = path127.join(metaprojectRoot, "keryx-dashboard.html");
|
|
47766
48211
|
await writeTextIfChanged4(dashboardPath, renderMetaprojectDashboardHtml({
|
|
47767
48212
|
enableGdgraph: moduleEnabled2(manifest, "gdgraph"),
|
|
47768
48213
|
enableGdctx: moduleEnabled2(manifest, "gdctx"),
|
|
@@ -47782,7 +48227,7 @@ async function shouldInstallDashboardPostCommitHook(projectRoot, manifest) {
|
|
|
47782
48227
|
if (Object.values(modules).some((module) => Boolean(module.hooks?.gitPostCommit))) {
|
|
47783
48228
|
return true;
|
|
47784
48229
|
}
|
|
47785
|
-
const hookPath =
|
|
48230
|
+
const hookPath = path127.join(projectRoot, ".git", "hooks", "post-commit");
|
|
47786
48231
|
if (!await pathExists(hookPath)) {
|
|
47787
48232
|
return false;
|
|
47788
48233
|
}
|
|
@@ -47802,11 +48247,11 @@ async function collectDashboardData(metaprojectRoot) {
|
|
|
47802
48247
|
if (testing) {
|
|
47803
48248
|
data.testing = testing;
|
|
47804
48249
|
}
|
|
47805
|
-
const wiki = await collectMarkdownPages(
|
|
48250
|
+
const wiki = await collectMarkdownPages(path127.join(metaprojectRoot, "wiki"), "wiki");
|
|
47806
48251
|
if (wiki.length > 0) {
|
|
47807
48252
|
data.wiki = { pages: wiki };
|
|
47808
48253
|
}
|
|
47809
|
-
const memory = await collectMarkdownPages(
|
|
48254
|
+
const memory = await collectMarkdownPages(path127.join(metaprojectRoot, "memory"), "memory");
|
|
47810
48255
|
if (memory.length > 0) {
|
|
47811
48256
|
data.memory = { entries: memory };
|
|
47812
48257
|
}
|
|
@@ -47821,7 +48266,7 @@ async function collectDashboardData(metaprojectRoot) {
|
|
|
47821
48266
|
return data;
|
|
47822
48267
|
}
|
|
47823
48268
|
async function collectTasksDashboardData(metaprojectRoot) {
|
|
47824
|
-
const flowsRoot2 =
|
|
48269
|
+
const flowsRoot2 = path127.join(metaprojectRoot, "flows");
|
|
47825
48270
|
if (!await pathExists(flowsRoot2)) {
|
|
47826
48271
|
return null;
|
|
47827
48272
|
}
|
|
@@ -47833,7 +48278,7 @@ async function collectTasksDashboardData(metaprojectRoot) {
|
|
|
47833
48278
|
}
|
|
47834
48279
|
const flows = [];
|
|
47835
48280
|
for (const dir of dirEntries) {
|
|
47836
|
-
const flowPath =
|
|
48281
|
+
const flowPath = path127.join(flowsRoot2, dir, "flow.json");
|
|
47837
48282
|
if (!await pathExists(flowPath)) {
|
|
47838
48283
|
continue;
|
|
47839
48284
|
}
|
|
@@ -47841,7 +48286,7 @@ async function collectTasksDashboardData(metaprojectRoot) {
|
|
|
47841
48286
|
const flow = JSON.parse(await readFile64(flowPath, "utf8"));
|
|
47842
48287
|
const tasks = Array.isArray(flow.tasks) ? flow.tasks : [];
|
|
47843
48288
|
let acTotal = 0;
|
|
47844
|
-
const acPath2 =
|
|
48289
|
+
const acPath2 = path127.join(flowsRoot2, dir, "acceptance-criteria.md");
|
|
47845
48290
|
if (await pathExists(acPath2)) {
|
|
47846
48291
|
const acContent = await readFile64(acPath2, "utf8");
|
|
47847
48292
|
acTotal = (acContent.match(/^- AC\d+:/gm) ?? []).length;
|
|
@@ -47894,7 +48339,7 @@ async function collectDashboardDocs(metaprojectRoot, wiki, memory) {
|
|
|
47894
48339
|
"data/testing/context.md"
|
|
47895
48340
|
];
|
|
47896
48341
|
for (const href of staticHrefs) {
|
|
47897
|
-
const filePath =
|
|
48342
|
+
const filePath = path127.join(metaprojectRoot, ...href.split("/"));
|
|
47898
48343
|
if (!await pathExists(filePath)) {
|
|
47899
48344
|
continue;
|
|
47900
48345
|
}
|
|
@@ -47911,7 +48356,7 @@ async function collectDashboardDocs(metaprojectRoot, wiki, memory) {
|
|
|
47911
48356
|
return docs;
|
|
47912
48357
|
}
|
|
47913
48358
|
async function collectHealthDashboardData(metaprojectRoot) {
|
|
47914
|
-
const reportPath2 =
|
|
48359
|
+
const reportPath2 = path127.join(metaprojectRoot, "data", "health", "artifacts", "latest.json");
|
|
47915
48360
|
if (!await pathExists(reportPath2)) {
|
|
47916
48361
|
return;
|
|
47917
48362
|
}
|
|
@@ -48020,8 +48465,8 @@ function metricToScope(metric) {
|
|
|
48020
48465
|
};
|
|
48021
48466
|
}
|
|
48022
48467
|
async function collectGraphDashboardData(metaprojectRoot) {
|
|
48023
|
-
const nodesPath =
|
|
48024
|
-
const edgesPath =
|
|
48468
|
+
const nodesPath = path127.join(metaprojectRoot, "data", "gdgraph", "storage", "nodes.jsonl");
|
|
48469
|
+
const edgesPath = path127.join(metaprojectRoot, "data", "gdgraph", "storage", "edges.jsonl");
|
|
48025
48470
|
if (!await pathExists(nodesPath) || !await pathExists(edgesPath)) {
|
|
48026
48471
|
return;
|
|
48027
48472
|
}
|
|
@@ -48072,8 +48517,8 @@ async function collectGraphDashboardData(metaprojectRoot) {
|
|
|
48072
48517
|
};
|
|
48073
48518
|
}
|
|
48074
48519
|
async function collectTestingDashboardData(metaprojectRoot) {
|
|
48075
|
-
const reportPath2 =
|
|
48076
|
-
const contextPath =
|
|
48520
|
+
const reportPath2 = path127.join(metaprojectRoot, "data", "testing", "artifacts", "latest.json");
|
|
48521
|
+
const contextPath = path127.join(metaprojectRoot, "data", "testing", "context.md");
|
|
48077
48522
|
if (await pathExists(reportPath2)) {
|
|
48078
48523
|
const report = JSON.parse(await readFile64(reportPath2, "utf8"));
|
|
48079
48524
|
const totalTests = numberOrUndefined(report.total);
|
|
@@ -48102,7 +48547,7 @@ async function collectMarkdownPages(root, hrefPrefix) {
|
|
|
48102
48547
|
const files = await listMarkdownFiles(root);
|
|
48103
48548
|
const pages = [];
|
|
48104
48549
|
for (const filePath of files.slice(0, 40)) {
|
|
48105
|
-
const relativePath =
|
|
48550
|
+
const relativePath = path127.relative(root, filePath).split(path127.sep).join("/");
|
|
48106
48551
|
if (relativePath === "index.md" || relativePath.startsWith("templates/")) {
|
|
48107
48552
|
continue;
|
|
48108
48553
|
}
|
|
@@ -48123,7 +48568,7 @@ async function listMarkdownFiles(root) {
|
|
|
48123
48568
|
const entries = await readdir20(root, { withFileTypes: true });
|
|
48124
48569
|
const files = [];
|
|
48125
48570
|
for (const entry of entries) {
|
|
48126
|
-
const fullPath =
|
|
48571
|
+
const fullPath = path127.join(root, entry.name);
|
|
48127
48572
|
if (entry.isDirectory()) {
|
|
48128
48573
|
files.push(...await listMarkdownFiles(fullPath));
|
|
48129
48574
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -48171,7 +48616,7 @@ async function writeRecoveredManifest(metaprojectRoot, modules) {
|
|
|
48171
48616
|
const manifest = {
|
|
48172
48617
|
schemaVersion: 1,
|
|
48173
48618
|
standardVersion: STANDARD_VERSION,
|
|
48174
|
-
name: `${
|
|
48619
|
+
name: `${path127.basename(path127.dirname(metaprojectRoot))}-metaproject`,
|
|
48175
48620
|
createdBy: "keryx",
|
|
48176
48621
|
profiles: computeProfiles(enabledModuleKeys2),
|
|
48177
48622
|
paths: {
|
|
@@ -48254,11 +48699,11 @@ async function writeRecoveredManifest(metaprojectRoot, modules) {
|
|
|
48254
48699
|
metaproject: ".metaproject/index.md"
|
|
48255
48700
|
}
|
|
48256
48701
|
};
|
|
48257
|
-
await writeFile42(
|
|
48702
|
+
await writeFile42(path127.join(metaprojectRoot, "metaproject.json"), `${JSON.stringify(manifest, null, 2)}
|
|
48258
48703
|
`, "utf8");
|
|
48259
48704
|
}
|
|
48260
48705
|
async function enableTasksInManifest(metaprojectRoot) {
|
|
48261
|
-
const manifestPath =
|
|
48706
|
+
const manifestPath = path127.join(metaprojectRoot, "metaproject.json");
|
|
48262
48707
|
if (!await pathExists(manifestPath)) {
|
|
48263
48708
|
return;
|
|
48264
48709
|
}
|
|
@@ -48281,7 +48726,7 @@ async function enableTasksInManifest(metaprojectRoot) {
|
|
|
48281
48726
|
`, "utf8");
|
|
48282
48727
|
}
|
|
48283
48728
|
async function updateManifestAgentEntrypoints(metaprojectRoot, ruleSources) {
|
|
48284
|
-
const manifestPath =
|
|
48729
|
+
const manifestPath = path127.join(metaprojectRoot, "metaproject.json");
|
|
48285
48730
|
if (!await pathExists(manifestPath)) {
|
|
48286
48731
|
return;
|
|
48287
48732
|
}
|
|
@@ -48317,69 +48762,69 @@ async function updateRuntime(projectRoot) {
|
|
|
48317
48762
|
}
|
|
48318
48763
|
}
|
|
48319
48764
|
async function findRuntimeRoot(projectRoot) {
|
|
48320
|
-
const projectRuntime =
|
|
48321
|
-
if (await pathExists(
|
|
48765
|
+
const projectRuntime = path127.join(projectRoot, ".metaproject", "runtime", "keryx");
|
|
48766
|
+
if (await pathExists(path127.join(projectRuntime, ".git"))) {
|
|
48322
48767
|
return projectRuntime;
|
|
48323
48768
|
}
|
|
48324
48769
|
const home = process.env.HOME;
|
|
48325
48770
|
if (!home) {
|
|
48326
48771
|
return null;
|
|
48327
48772
|
}
|
|
48328
|
-
const globalRuntime =
|
|
48329
|
-
if (await pathExists(
|
|
48773
|
+
const globalRuntime = path127.join(home, ".keryx", "keryx");
|
|
48774
|
+
if (await pathExists(path127.join(globalRuntime, ".git"))) {
|
|
48330
48775
|
return globalRuntime;
|
|
48331
48776
|
}
|
|
48332
48777
|
return null;
|
|
48333
48778
|
}
|
|
48334
48779
|
async function createServiceDirs(metaprojectRoot, modules) {
|
|
48335
48780
|
const dirs = [
|
|
48336
|
-
|
|
48337
|
-
|
|
48338
|
-
|
|
48339
|
-
|
|
48340
|
-
|
|
48781
|
+
path127.join(metaprojectRoot, "core"),
|
|
48782
|
+
path127.join(metaprojectRoot, "hooks", "post-update.d"),
|
|
48783
|
+
path127.join(metaprojectRoot, "modules"),
|
|
48784
|
+
path127.join(metaprojectRoot, "rules"),
|
|
48785
|
+
path127.join(metaprojectRoot, "skills", "project-rules"),
|
|
48341
48786
|
...modules.enableGdgraph ? [
|
|
48342
|
-
|
|
48343
|
-
|
|
48787
|
+
path127.join(metaprojectRoot, "core", "gdgraph"),
|
|
48788
|
+
path127.join(metaprojectRoot, "skills", "gdgraph")
|
|
48344
48789
|
] : [],
|
|
48345
48790
|
...modules.enableGdctx ? [
|
|
48346
|
-
|
|
48347
|
-
|
|
48791
|
+
path127.join(metaprojectRoot, "core", "gdctx"),
|
|
48792
|
+
path127.join(metaprojectRoot, "skills", "gdctx")
|
|
48348
48793
|
] : [],
|
|
48349
48794
|
...modules.enableGdwiki ? [
|
|
48350
|
-
|
|
48351
|
-
|
|
48795
|
+
path127.join(metaprojectRoot, "skills", "gdwiki"),
|
|
48796
|
+
path127.join(metaprojectRoot, "wiki", "templates")
|
|
48352
48797
|
] : [],
|
|
48353
48798
|
...modules.enableHealth ? [
|
|
48354
|
-
|
|
48355
|
-
|
|
48799
|
+
path127.join(metaprojectRoot, "core", "health"),
|
|
48800
|
+
path127.join(metaprojectRoot, "skills", "health")
|
|
48356
48801
|
] : [],
|
|
48357
48802
|
...modules.enableTesting ? [
|
|
48358
|
-
|
|
48359
|
-
|
|
48803
|
+
path127.join(metaprojectRoot, "core", "testing"),
|
|
48804
|
+
path127.join(metaprojectRoot, "skills", "testing")
|
|
48360
48805
|
] : [],
|
|
48361
48806
|
...modules.enableMemory ? [
|
|
48362
|
-
|
|
48363
|
-
|
|
48364
|
-
|
|
48807
|
+
path127.join(metaprojectRoot, "core", "memory"),
|
|
48808
|
+
path127.join(metaprojectRoot, "skills", "memory"),
|
|
48809
|
+
path127.join(metaprojectRoot, "memory", "templates")
|
|
48365
48810
|
] : [],
|
|
48366
48811
|
...modules.enableTasks ? [
|
|
48367
|
-
|
|
48368
|
-
|
|
48812
|
+
path127.join(metaprojectRoot, "flows"),
|
|
48813
|
+
path127.join(metaprojectRoot, "skills", "flow")
|
|
48369
48814
|
] : [],
|
|
48370
48815
|
...modules.enableSecurity ? [
|
|
48371
|
-
|
|
48816
|
+
path127.join(metaprojectRoot, "core", "security")
|
|
48372
48817
|
] : []
|
|
48373
48818
|
];
|
|
48374
48819
|
await Promise.all(dirs.map((dir) => mkdir45(dir, { recursive: true })));
|
|
48375
48820
|
}
|
|
48376
48821
|
async function installGdgraphCoreScripts2(metaprojectRoot) {
|
|
48377
|
-
const gdgraphCoreRoot =
|
|
48822
|
+
const gdgraphCoreRoot = path127.join(metaprojectRoot, "core", "gdgraph");
|
|
48378
48823
|
await mkdir45(gdgraphCoreRoot, { recursive: true });
|
|
48379
48824
|
for (const file of GDGRAPH_CORE_SOURCES) {
|
|
48380
|
-
await copyFileIfChanged2(runtimeSourcePath2(`../gdgraph/${file}`),
|
|
48825
|
+
await copyFileIfChanged2(runtimeSourcePath2(`../gdgraph/${file}`), path127.join(gdgraphCoreRoot, file));
|
|
48381
48826
|
}
|
|
48382
|
-
await writeTextIfChanged4(
|
|
48827
|
+
await writeTextIfChanged4(path127.join(gdgraphCoreRoot, "cli.ts"), renderGdgraphCoreCli());
|
|
48383
48828
|
}
|
|
48384
48829
|
async function installManagedHook2(projectRoot, hookName, blockId, content) {
|
|
48385
48830
|
const hooksRoot = await resolveGitHooksRoot(projectRoot);
|
|
@@ -48387,7 +48832,7 @@ async function installManagedHook2(projectRoot, hookName, blockId, content) {
|
|
|
48387
48832
|
return;
|
|
48388
48833
|
}
|
|
48389
48834
|
await mkdir45(hooksRoot, { recursive: true });
|
|
48390
|
-
const hookPath =
|
|
48835
|
+
const hookPath = path127.join(hooksRoot, hookName);
|
|
48391
48836
|
const blockStart = `# keryx:${blockId}:begin`;
|
|
48392
48837
|
const blockEnd = `# keryx:${blockId}:end`;
|
|
48393
48838
|
const managedBlock = `${blockStart}
|
|
@@ -48408,7 +48853,7 @@ async function removeManagedHook2(projectRoot, hookName, blockId) {
|
|
|
48408
48853
|
if (!hooksRoot) {
|
|
48409
48854
|
return;
|
|
48410
48855
|
}
|
|
48411
|
-
const hookPath =
|
|
48856
|
+
const hookPath = path127.join(hooksRoot, hookName);
|
|
48412
48857
|
if (!await pathExists(hookPath)) {
|
|
48413
48858
|
return;
|
|
48414
48859
|
}
|
|
@@ -48430,7 +48875,7 @@ async function prePushHasSecurityBlock2(projectRoot) {
|
|
|
48430
48875
|
if (!hooksRoot) {
|
|
48431
48876
|
return false;
|
|
48432
48877
|
}
|
|
48433
|
-
const hookPath =
|
|
48878
|
+
const hookPath = path127.join(hooksRoot, "pre-push");
|
|
48434
48879
|
if (!await pathExists(hookPath)) {
|
|
48435
48880
|
return false;
|
|
48436
48881
|
}
|
|
@@ -48445,7 +48890,7 @@ async function agentSettingsHasSecuritySentinel2(projectRoot) {
|
|
|
48445
48890
|
return (await readFile64(file, "utf8")).includes(AGENT_HOOKS_SENTINEL);
|
|
48446
48891
|
}
|
|
48447
48892
|
async function readManifest5(metaprojectRoot) {
|
|
48448
|
-
const manifestPath =
|
|
48893
|
+
const manifestPath = path127.join(metaprojectRoot, "metaproject.json");
|
|
48449
48894
|
if (!await pathExists(manifestPath)) {
|
|
48450
48895
|
return {
|
|
48451
48896
|
exists: false,
|
|
@@ -48513,7 +48958,7 @@ async function inferManifestFromExistingMetaproject(metaprojectRoot) {
|
|
|
48513
48958
|
}
|
|
48514
48959
|
async function anyPathExists(root, candidates) {
|
|
48515
48960
|
for (const candidate of candidates) {
|
|
48516
|
-
if (await pathExists(
|
|
48961
|
+
if (await pathExists(path127.join(root, candidate))) {
|
|
48517
48962
|
return true;
|
|
48518
48963
|
}
|
|
48519
48964
|
}
|
|
@@ -48534,13 +48979,13 @@ function parseUpdateArgs(args2) {
|
|
|
48534
48979
|
};
|
|
48535
48980
|
}
|
|
48536
48981
|
async function runPostUpdateHooks(projectRoot) {
|
|
48537
|
-
const hooksDir =
|
|
48982
|
+
const hooksDir = path127.join(projectRoot, ".metaproject", "hooks", "post-update.d");
|
|
48538
48983
|
if (!await pathExists(hooksDir)) {
|
|
48539
48984
|
return;
|
|
48540
48985
|
}
|
|
48541
48986
|
const entries = (await readdir20(hooksDir)).sort();
|
|
48542
48987
|
for (const entry of entries) {
|
|
48543
|
-
const hookPath =
|
|
48988
|
+
const hookPath = path127.join(hooksDir, entry);
|
|
48544
48989
|
try {
|
|
48545
48990
|
await accessExecutable(hookPath);
|
|
48546
48991
|
} catch {
|
|
@@ -48581,14 +49026,14 @@ async function writeTextIfChanged4(filePath, content) {
|
|
|
48581
49026
|
if (await pathExists(filePath) && await readFile64(filePath, "utf8") === content) {
|
|
48582
49027
|
return;
|
|
48583
49028
|
}
|
|
48584
|
-
await mkdir45(
|
|
49029
|
+
await mkdir45(path127.dirname(filePath), { recursive: true });
|
|
48585
49030
|
await writeFile42(filePath, content, "utf8");
|
|
48586
49031
|
}
|
|
48587
49032
|
async function writeTextIfMissing4(filePath, content) {
|
|
48588
49033
|
if (await pathExists(filePath)) {
|
|
48589
49034
|
return;
|
|
48590
49035
|
}
|
|
48591
|
-
await mkdir45(
|
|
49036
|
+
await mkdir45(path127.dirname(filePath), { recursive: true });
|
|
48592
49037
|
await writeFile42(filePath, content, "utf8");
|
|
48593
49038
|
}
|
|
48594
49039
|
async function copyFileIfChanged2(from, to) {
|
|
@@ -48596,7 +49041,7 @@ async function copyFileIfChanged2(from, to) {
|
|
|
48596
49041
|
if (await pathExists(to) && await readFile64(to, "utf8") === next) {
|
|
48597
49042
|
return;
|
|
48598
49043
|
}
|
|
48599
|
-
await mkdir45(
|
|
49044
|
+
await mkdir45(path127.dirname(to), { recursive: true });
|
|
48600
49045
|
await writeFile42(to, next, "utf8");
|
|
48601
49046
|
}
|
|
48602
49047
|
function runtimeSourcePath2(relativePath) {
|
|
@@ -48605,7 +49050,7 @@ function runtimeSourcePath2(relativePath) {
|
|
|
48605
49050
|
return directPath;
|
|
48606
49051
|
}
|
|
48607
49052
|
if (relativePath.startsWith("../")) {
|
|
48608
|
-
const packagedSourcePath =
|
|
49053
|
+
const packagedSourcePath = path127.join(path127.dirname(fileURLToPath6(import.meta.url)), "..", "src", relativePath.slice(3));
|
|
48609
49054
|
if (existsSync27(packagedSourcePath)) {
|
|
48610
49055
|
return packagedSourcePath;
|
|
48611
49056
|
}
|
|
@@ -48637,7 +49082,7 @@ function printHelp18() {
|
|
|
48637
49082
|
|
|
48638
49083
|
// src/commands/dashboard.ts
|
|
48639
49084
|
import { spawn as spawn6 } from "child_process";
|
|
48640
|
-
import
|
|
49085
|
+
import path128 from "path";
|
|
48641
49086
|
init_args();
|
|
48642
49087
|
async function dashboardCommand(args2 = []) {
|
|
48643
49088
|
const options = parseOptions(args2);
|
|
@@ -48648,7 +49093,7 @@ async function dashboardCommand(args2 = []) {
|
|
|
48648
49093
|
}
|
|
48649
49094
|
if (subcommand === "build") {
|
|
48650
49095
|
const result = await buildDashboard();
|
|
48651
|
-
const rel =
|
|
49096
|
+
const rel = path128.relative(process.cwd(), result.path);
|
|
48652
49097
|
console.log(` ${style.green(symbols.ok)} Dashboard built ${style.cyan(symbols.arrow)} ${style.cyan(rel)}`);
|
|
48653
49098
|
note(`Open it: keryx dashboard open`);
|
|
48654
49099
|
return;
|
|
@@ -48656,7 +49101,7 @@ async function dashboardCommand(args2 = []) {
|
|
|
48656
49101
|
if (subcommand === "open") {
|
|
48657
49102
|
const result = await buildDashboard();
|
|
48658
49103
|
await openFile(result.path);
|
|
48659
|
-
const rel =
|
|
49104
|
+
const rel = path128.relative(process.cwd(), result.path);
|
|
48660
49105
|
console.log(` ${style.green(symbols.ok)} Opened ${style.cyan(rel)}`);
|
|
48661
49106
|
return;
|
|
48662
49107
|
}
|
|
@@ -48705,7 +49150,7 @@ import { readFileSync as readFileSync10 } from "fs";
|
|
|
48705
49150
|
// src/agents/bootstrap.ts
|
|
48706
49151
|
import { mkdir as mkdir46, readFile as readFile65, writeFile as writeFile43 } from "fs/promises";
|
|
48707
49152
|
import { homedir as homedir6 } from "os";
|
|
48708
|
-
import
|
|
49153
|
+
import path129 from "path";
|
|
48709
49154
|
init_fs();
|
|
48710
49155
|
var AGENT_BOOTSTRAP_START = "<!-- keryx:global-bootstrap -->";
|
|
48711
49156
|
var AGENT_BOOTSTRAP_END = "<!-- /keryx:global-bootstrap -->";
|
|
@@ -48715,35 +49160,35 @@ var AGENT_BOOTSTRAP_RUNTIMES = [
|
|
|
48715
49160
|
aliases: ["claude-code"],
|
|
48716
49161
|
label: "Claude Code",
|
|
48717
49162
|
fileName: "CLAUDE.md",
|
|
48718
|
-
filePath: (homeRoot) =>
|
|
49163
|
+
filePath: (homeRoot) => path129.join(homeRoot, ".claude", "CLAUDE.md")
|
|
48719
49164
|
},
|
|
48720
49165
|
{
|
|
48721
49166
|
id: "opencode",
|
|
48722
49167
|
aliases: ["open-code"],
|
|
48723
49168
|
label: "OpenCode",
|
|
48724
49169
|
fileName: "AGENTS.md",
|
|
48725
|
-
filePath: (homeRoot) =>
|
|
49170
|
+
filePath: (homeRoot) => path129.join(homeRoot, ".config", "opencode", "AGENTS.md")
|
|
48726
49171
|
},
|
|
48727
49172
|
{
|
|
48728
49173
|
id: "zcode",
|
|
48729
49174
|
aliases: ["zed", "zed-code"],
|
|
48730
49175
|
label: "ZCode",
|
|
48731
49176
|
fileName: "AGENTS.md",
|
|
48732
|
-
filePath: (homeRoot) =>
|
|
49177
|
+
filePath: (homeRoot) => path129.join(homeRoot, ".zcode", "AGENTS.md")
|
|
48733
49178
|
},
|
|
48734
49179
|
{
|
|
48735
49180
|
id: "codex",
|
|
48736
49181
|
aliases: [],
|
|
48737
49182
|
label: "Codex",
|
|
48738
49183
|
fileName: "AGENTS.md",
|
|
48739
|
-
filePath: (homeRoot) =>
|
|
49184
|
+
filePath: (homeRoot) => path129.join(homeRoot, ".codex", "AGENTS.md")
|
|
48740
49185
|
},
|
|
48741
49186
|
{
|
|
48742
49187
|
id: "antigravity",
|
|
48743
49188
|
aliases: ["antigravuty", "antigravity-code"],
|
|
48744
49189
|
label: "Antigravity",
|
|
48745
49190
|
fileName: "AGENTS.md",
|
|
48746
|
-
filePath: (homeRoot) =>
|
|
49191
|
+
filePath: (homeRoot) => path129.join(homeRoot, ".config", "antigravity", "AGENTS.md")
|
|
48747
49192
|
}
|
|
48748
49193
|
];
|
|
48749
49194
|
function agentBootstrapRuntimeIds() {
|
|
@@ -48791,7 +49236,7 @@ async function installAgentBootstrap(runtime, options = {}) {
|
|
|
48791
49236
|
const dryRun = options.dryRun === true;
|
|
48792
49237
|
const wrote = next !== current;
|
|
48793
49238
|
if (wrote && !dryRun) {
|
|
48794
|
-
await mkdir46(
|
|
49239
|
+
await mkdir46(path129.dirname(filePath), { recursive: true });
|
|
48795
49240
|
await writeFile43(filePath, next, "utf8");
|
|
48796
49241
|
}
|
|
48797
49242
|
const status = dryRun ? statusFromContent(runtime, filePath, exists2, next) : await agentBootstrapStatus(runtime, homeRoot);
|
|
@@ -49139,7 +49584,7 @@ function printBootstrapHelp() {
|
|
|
49139
49584
|
// src/commands/metrics.ts
|
|
49140
49585
|
init_args();
|
|
49141
49586
|
import { readFile as readFile66 } from "fs/promises";
|
|
49142
|
-
import
|
|
49587
|
+
import path130 from "path";
|
|
49143
49588
|
|
|
49144
49589
|
// src/metrics/benchmark.ts
|
|
49145
49590
|
function createPairedBenchmarkTemplate(taskIds) {
|
|
@@ -49367,7 +49812,7 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
49367
49812
|
console.log("# metrics status");
|
|
49368
49813
|
console.log("");
|
|
49369
49814
|
console.log(`root: ${root}`);
|
|
49370
|
-
console.log(`enabled: ${await Bun.file(
|
|
49815
|
+
console.log(`enabled: ${await Bun.file(path130.join(projectRoot, ".metaproject", "metaproject.json")).exists() ? "yes" : "no"}`);
|
|
49371
49816
|
const latest2 = await readLatestPointer(root);
|
|
49372
49817
|
console.log(`latest: ${latest2.status}`);
|
|
49373
49818
|
return;
|
|
@@ -49379,7 +49824,7 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
49379
49824
|
process.exitCode = 1;
|
|
49380
49825
|
return;
|
|
49381
49826
|
}
|
|
49382
|
-
const record2 = JSON.parse(await readFile66(
|
|
49827
|
+
const record2 = JSON.parse(await readFile66(path130.resolve(projectRoot, file), "utf8"));
|
|
49383
49828
|
const result = validateRunRecord(record2);
|
|
49384
49829
|
console.log(result.valid ? "valid: yes" : "valid: no");
|
|
49385
49830
|
for (const error of result.errors)
|
|
@@ -49404,7 +49849,7 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
49404
49849
|
process.exitCode = 1;
|
|
49405
49850
|
return;
|
|
49406
49851
|
}
|
|
49407
|
-
const file =
|
|
49852
|
+
const file = path130.join(metricsRoot(projectRoot), "runs", `${runId}.json`);
|
|
49408
49853
|
if (!await Bun.file(file).exists()) {
|
|
49409
49854
|
console.error(`Run not found: ${runId}`);
|
|
49410
49855
|
process.exitCode = 1;
|
|
@@ -49421,8 +49866,8 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
49421
49866
|
process.exitCode = 1;
|
|
49422
49867
|
return;
|
|
49423
49868
|
}
|
|
49424
|
-
const a = JSON.parse(await readFile66(
|
|
49425
|
-
const b = JSON.parse(await readFile66(
|
|
49869
|
+
const a = JSON.parse(await readFile66(path130.join(metricsRoot(projectRoot), "runs", `${runA}.json`), "utf8"));
|
|
49870
|
+
const b = JSON.parse(await readFile66(path130.join(metricsRoot(projectRoot), "runs", `${runB}.json`), "utf8"));
|
|
49426
49871
|
const comparison = compareExecutionRuns(a, b);
|
|
49427
49872
|
console.log(stableJson(comparison));
|
|
49428
49873
|
return;
|
|
@@ -49456,8 +49901,8 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
49456
49901
|
return;
|
|
49457
49902
|
}
|
|
49458
49903
|
const template = createPairedBenchmarkTemplate(taskIds);
|
|
49459
|
-
await Bun.write(
|
|
49460
|
-
console.log(`manifest: ${
|
|
49904
|
+
await Bun.write(path130.resolve(projectRoot, out), stableJson(template));
|
|
49905
|
+
console.log(`manifest: ${path130.relative(projectRoot, path130.resolve(projectRoot, out))}`);
|
|
49461
49906
|
return;
|
|
49462
49907
|
}
|
|
49463
49908
|
if (subcommand === "benchmark" && args2[1] === "validate") {
|
|
@@ -49467,7 +49912,7 @@ async function metricsCommand(args2 = [], projectRoot = process.cwd()) {
|
|
|
49467
49912
|
process.exitCode = 1;
|
|
49468
49913
|
return;
|
|
49469
49914
|
}
|
|
49470
|
-
const raw = JSON.parse(await readFile66(
|
|
49915
|
+
const raw = JSON.parse(await readFile66(path130.resolve(projectRoot, file), "utf8"));
|
|
49471
49916
|
const input2 = Array.isArray(raw) ? raw : raw.runs ?? [];
|
|
49472
49917
|
const result = validatePairedBenchmark(input2);
|
|
49473
49918
|
console.log(stableJson(result));
|
|
@@ -49485,7 +49930,7 @@ async function collect(projectRoot, args2) {
|
|
|
49485
49930
|
process.exitCode = 1;
|
|
49486
49931
|
return;
|
|
49487
49932
|
}
|
|
49488
|
-
const raw = JSON.parse(await readFile66(
|
|
49933
|
+
const raw = JSON.parse(await readFile66(path130.resolve(projectRoot, eventFile), "utf8"));
|
|
49489
49934
|
const events2 = Array.isArray(raw) ? raw : raw.events;
|
|
49490
49935
|
const startedAt = optionValue(args2, "--started-at") ?? events2[0]?.timestamp_utc ?? new Date().toISOString();
|
|
49491
49936
|
const finishedAt = optionValue(args2, "--finished-at") ?? events2.at(-1)?.timestamp_utc ?? startedAt;
|
|
@@ -49501,11 +49946,11 @@ async function collect(projectRoot, args2) {
|
|
|
49501
49946
|
parentRunId: optionValue(args2, "--parent-run-id") ?? null
|
|
49502
49947
|
});
|
|
49503
49948
|
const result = await writeRunArtifacts(metricsRoot(projectRoot), record2, { cwd: projectRoot });
|
|
49504
|
-
console.log(`json: ${
|
|
49505
|
-
console.log(`markdown: ${
|
|
49949
|
+
console.log(`json: ${path130.relative(projectRoot, result.jsonPath)}`);
|
|
49950
|
+
console.log(`markdown: ${path130.relative(projectRoot, result.markdownPath)}`);
|
|
49506
49951
|
}
|
|
49507
49952
|
function metricsRoot(projectRoot) {
|
|
49508
|
-
return
|
|
49953
|
+
return path130.join(projectRoot, ".metaproject", "data", "metrics");
|
|
49509
49954
|
}
|
|
49510
49955
|
function printMetricsHelp() {
|
|
49511
49956
|
console.log(`keryx metrics
|
|
@@ -49523,76 +49968,35 @@ Usage:
|
|
|
49523
49968
|
keryx metrics benchmark validate <manifest.json>
|
|
49524
49969
|
`);
|
|
49525
49970
|
}
|
|
49526
|
-
|
|
49527
|
-
|
|
49528
|
-
|
|
49529
|
-
|
|
49530
|
-
|
|
49531
|
-
|
|
49532
|
-
|
|
49533
|
-
|
|
49534
|
-
},
|
|
49535
|
-
license: "MIT",
|
|
49536
|
-
type: "module",
|
|
49537
|
-
repository: {
|
|
49538
|
-
type: "git",
|
|
49539
|
-
url: "git+ssh://git@github.com/MrCipherSmith/keryx.git"
|
|
49540
|
-
},
|
|
49541
|
-
keywords: [
|
|
49542
|
-
"ai-agents",
|
|
49543
|
-
"coding-agents",
|
|
49544
|
-
"agent-harness",
|
|
49545
|
-
"agent-context",
|
|
49546
|
-
"repository-context",
|
|
49547
|
-
"code-graph",
|
|
49548
|
-
"project-memory",
|
|
49549
|
-
"test-impact-analysis",
|
|
49550
|
-
"developer-tools",
|
|
49551
|
-
"model-context-protocol",
|
|
49552
|
-
"mcp",
|
|
49553
|
-
"claude-code",
|
|
49554
|
-
"cursor",
|
|
49555
|
-
"codex",
|
|
49556
|
-
"cli",
|
|
49557
|
-
"bun"
|
|
49558
|
-
],
|
|
49559
|
-
bin: {
|
|
49560
|
-
keryx: "./dist/cli.js"
|
|
49561
|
-
},
|
|
49562
|
-
scripts: {
|
|
49563
|
-
keryx: "bun ./src/cli.ts",
|
|
49564
|
-
build: "bun build ./src/cli.ts --outdir ./dist --target bun --external @modelcontextprotocol/sdk --external web-tree-sitter --external @opentui/core && bun build ./src/harness/process/sandbox/proxy-worker.ts --outdir ./dist --target bun --external @modelcontextprotocol/sdk --external web-tree-sitter --external @opentui/core",
|
|
49565
|
-
prepare: "bun run build",
|
|
49566
|
-
typecheck: "tsc --noEmit",
|
|
49567
|
-
test: "bun test",
|
|
49568
|
-
check: "tsc --noEmit && bun test",
|
|
49569
|
-
"check:doc-links": "bun scripts/check-doc-links.ts",
|
|
49570
|
-
"test:guards": "bun test src/lib/config-dir.ast.test.ts src/lib/config-dir.readers.test.ts src/lib/production-graph.test.ts src/harness/policy/profiles.test.ts src/lib/serve-server.test.ts"
|
|
49571
|
-
},
|
|
49572
|
-
files: [
|
|
49573
|
-
"dist",
|
|
49574
|
-
"src/gdgraph",
|
|
49575
|
-
"src/gdskills/bundled",
|
|
49576
|
-
"src/gdskills/contracts",
|
|
49577
|
-
"LICENSE",
|
|
49578
|
-
"README.md",
|
|
49579
|
-
"package.json"
|
|
49580
|
-
],
|
|
49581
|
-
dependencies: {},
|
|
49582
|
-
optionalDependencies: {
|
|
49583
|
-
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
49584
|
-
"@opentui/core": "^0.4.5",
|
|
49585
|
-
"web-tree-sitter": "^0.22.0"
|
|
49586
|
-
},
|
|
49587
|
-
devDependencies: {
|
|
49588
|
-
"@types/bun": "latest",
|
|
49589
|
-
"bun-types": "latest",
|
|
49590
|
-
typescript: "^5"
|
|
49591
|
-
},
|
|
49592
|
-
engines: {
|
|
49593
|
-
bun: ">=1.1.0"
|
|
49971
|
+
|
|
49972
|
+
// src/commands/version.ts
|
|
49973
|
+
async function versionCommand(args2, deps = {}) {
|
|
49974
|
+
const json = args2.length === 2 && args2[1] === "--json";
|
|
49975
|
+
if (args2[0] !== "check" || args2.length !== 1 && !json) {
|
|
49976
|
+
console.error("Usage: keryx version check [--json]");
|
|
49977
|
+
process.exitCode = 1;
|
|
49978
|
+
return;
|
|
49594
49979
|
}
|
|
49595
|
-
|
|
49980
|
+
const options = {
|
|
49981
|
+
currentVersion: deps.currentVersion ?? package_default.version,
|
|
49982
|
+
...deps.fetch !== undefined ? { fetch: deps.fetch } : {},
|
|
49983
|
+
...deps.cacheDir !== undefined ? { cacheDir: deps.cacheDir } : {},
|
|
49984
|
+
...deps.now !== undefined ? { now: deps.now } : {}
|
|
49985
|
+
};
|
|
49986
|
+
const result = await (deps.check ?? checkVersion)(options);
|
|
49987
|
+
if (json) {
|
|
49988
|
+
console.log(JSON.stringify(result));
|
|
49989
|
+
return;
|
|
49990
|
+
}
|
|
49991
|
+
if (result.status === "update-available") {
|
|
49992
|
+
console.log(`Keryx ${result.currentVersion} \u2192 ${result.latestVersion}`);
|
|
49993
|
+
console.log(result.installCommand);
|
|
49994
|
+
} else if (result.status === "up-to-date") {
|
|
49995
|
+
console.log(`Keryx ${result.currentVersion} is up to date.`);
|
|
49996
|
+
} else {
|
|
49997
|
+
console.log(`Keryx version check unavailable (${result.reason}).`);
|
|
49998
|
+
}
|
|
49999
|
+
}
|
|
49596
50000
|
|
|
49597
50001
|
// src/cli.ts
|
|
49598
50002
|
var VERSION2 = package_default.version;
|
|
@@ -49627,7 +50031,8 @@ var CLI_ROUTES = {
|
|
|
49627
50031
|
harness: harnessCommand,
|
|
49628
50032
|
shell: shellCommand,
|
|
49629
50033
|
sessions: sessionsCommand,
|
|
49630
|
-
session: sessionsCommand
|
|
50034
|
+
session: sessionsCommand,
|
|
50035
|
+
version: versionCommand
|
|
49631
50036
|
};
|
|
49632
50037
|
async function main() {
|
|
49633
50038
|
const args2 = process.argv.slice(2);
|
|
@@ -49658,6 +50063,7 @@ Usage:
|
|
|
49658
50063
|
Start TUI agent shell (sessions are per-project)
|
|
49659
50064
|
keryx sessions list|fork <id>|export <id>|path
|
|
49660
50065
|
List / branch / export sessions for the current project
|
|
50066
|
+
keryx version check [--json] Check npm latest (advisory; never installs)
|
|
49661
50067
|
keryx harness run --provider <fake|anthropic|ollama> --model <m> [--base-url <url>] [--record <path>] "<prompt>"
|
|
49662
50068
|
keryx harness exec [--allow-env KEY]... [--max-runtime-ms N] [--allow-real-subprocess]
|
|
49663
50069
|
[--allowed-domains a,b] [--mask-env NAME@host] [--tls-terminate] [--mask-mode auto|manual|off] [--auto-mask] -- <path> [args...]
|
|
@@ -49741,6 +50147,7 @@ Commands:
|
|
|
49741
50147
|
shell Start the interactive TUI agent harness. Use --no-tui or --chat to opt out.
|
|
49742
50148
|
Sessions: -c continue last in this project, -r [id] resume (per-project).
|
|
49743
50149
|
sessions List or export per-project shell sessions
|
|
50150
|
+
version Check whether a newer npm release is available
|
|
49744
50151
|
harness Run a single provider turn (harness run) and print structured events
|
|
49745
50152
|
init Initialize .metaproject in the current project
|
|
49746
50153
|
status Show local Metaproject status
|