zelari-code 2.11.1 → 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/headless.js +16 -5
- package/dist/cli/headless.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +17 -4
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/kraken/completionProof.js +176 -0
- package/dist/cli/kraken/completionProof.js.map +1 -0
- package/dist/cli/kraken/nativeVerification.js +12 -5
- package/dist/cli/kraken/nativeVerification.js.map +1 -1
- package/dist/cli/kraken/planner.js +24 -11
- package/dist/cli/kraken/planner.js.map +1 -1
- package/dist/cli/kraken/scriptPlanner.js +18 -6
- package/dist/cli/kraken/scriptPlanner.js.map +1 -1
- package/dist/cli/kraken/verificationBridge.js +5 -1
- package/dist/cli/kraken/verificationBridge.js.map +1 -1
- package/dist/cli/kraken/verifierLifecycle.js +72 -8
- package/dist/cli/kraken/verifierLifecycle.js.map +1 -1
- package/dist/cli/main.bundled.js +983 -402
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/orchestration/policy.js +88 -0
- package/dist/cli/orchestration/policy.js.map +1 -0
- package/dist/cli/runHeadless.js +49 -0
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/safety/policyEngine.js +280 -0
- package/dist/cli/safety/policyEngine.js.map +1 -0
- package/dist/cli/safety/toolPermissions.js +38 -0
- package/dist/cli/safety/toolPermissions.js.map +1 -1
- package/dist/cli/toolRegistry.js +59 -12
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/tools/krakenModel.js +93 -0
- package/dist/cli/tools/krakenModel.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -3288,10 +3288,10 @@ function mergeDefs(...defs) {
|
|
|
3288
3288
|
function cloneDef(schema) {
|
|
3289
3289
|
return mergeDefs(schema._zod.def);
|
|
3290
3290
|
}
|
|
3291
|
-
function getElementAtPath(obj,
|
|
3292
|
-
if (!
|
|
3291
|
+
function getElementAtPath(obj, path74) {
|
|
3292
|
+
if (!path74)
|
|
3293
3293
|
return obj;
|
|
3294
|
-
return
|
|
3294
|
+
return path74.reduce((acc, key) => acc?.[key], obj);
|
|
3295
3295
|
}
|
|
3296
3296
|
function promiseAllObject(promisesObj) {
|
|
3297
3297
|
const keys = Object.keys(promisesObj);
|
|
@@ -3619,11 +3619,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
3619
3619
|
}
|
|
3620
3620
|
return false;
|
|
3621
3621
|
}
|
|
3622
|
-
function prefixIssues(
|
|
3622
|
+
function prefixIssues(path74, issues) {
|
|
3623
3623
|
return issues.map((iss) => {
|
|
3624
3624
|
var _a3;
|
|
3625
3625
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
3626
|
-
iss.path.unshift(
|
|
3626
|
+
iss.path.unshift(path74);
|
|
3627
3627
|
return iss;
|
|
3628
3628
|
});
|
|
3629
3629
|
}
|
|
@@ -3841,16 +3841,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
3841
3841
|
}
|
|
3842
3842
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
3843
3843
|
const fieldErrors = { _errors: [] };
|
|
3844
|
-
const processError = (error52,
|
|
3844
|
+
const processError = (error52, path74 = []) => {
|
|
3845
3845
|
for (const issue2 of error52.issues) {
|
|
3846
3846
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
3847
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
3847
|
+
issue2.errors.map((issues) => processError({ issues }, [...path74, ...issue2.path]));
|
|
3848
3848
|
} else if (issue2.code === "invalid_key") {
|
|
3849
|
-
processError({ issues: issue2.issues }, [...
|
|
3849
|
+
processError({ issues: issue2.issues }, [...path74, ...issue2.path]);
|
|
3850
3850
|
} else if (issue2.code === "invalid_element") {
|
|
3851
|
-
processError({ issues: issue2.issues }, [...
|
|
3851
|
+
processError({ issues: issue2.issues }, [...path74, ...issue2.path]);
|
|
3852
3852
|
} else {
|
|
3853
|
-
const fullpath = [...
|
|
3853
|
+
const fullpath = [...path74, ...issue2.path];
|
|
3854
3854
|
if (fullpath.length === 0) {
|
|
3855
3855
|
fieldErrors._errors.push(mapper(issue2));
|
|
3856
3856
|
} else {
|
|
@@ -3877,17 +3877,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
3877
3877
|
}
|
|
3878
3878
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
3879
3879
|
const result = { errors: [] };
|
|
3880
|
-
const processError = (error52,
|
|
3880
|
+
const processError = (error52, path74 = []) => {
|
|
3881
3881
|
var _a3, _b;
|
|
3882
3882
|
for (const issue2 of error52.issues) {
|
|
3883
3883
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
3884
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
3884
|
+
issue2.errors.map((issues) => processError({ issues }, [...path74, ...issue2.path]));
|
|
3885
3885
|
} else if (issue2.code === "invalid_key") {
|
|
3886
|
-
processError({ issues: issue2.issues }, [...
|
|
3886
|
+
processError({ issues: issue2.issues }, [...path74, ...issue2.path]);
|
|
3887
3887
|
} else if (issue2.code === "invalid_element") {
|
|
3888
|
-
processError({ issues: issue2.issues }, [...
|
|
3888
|
+
processError({ issues: issue2.issues }, [...path74, ...issue2.path]);
|
|
3889
3889
|
} else {
|
|
3890
|
-
const fullpath = [...
|
|
3890
|
+
const fullpath = [...path74, ...issue2.path];
|
|
3891
3891
|
if (fullpath.length === 0) {
|
|
3892
3892
|
result.errors.push(mapper(issue2));
|
|
3893
3893
|
continue;
|
|
@@ -3919,8 +3919,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
3919
3919
|
}
|
|
3920
3920
|
function toDotPath(_path) {
|
|
3921
3921
|
const segs = [];
|
|
3922
|
-
const
|
|
3923
|
-
for (const seg of
|
|
3922
|
+
const path74 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
3923
|
+
for (const seg of path74) {
|
|
3924
3924
|
if (typeof seg === "number")
|
|
3925
3925
|
segs.push(`[${seg}]`);
|
|
3926
3926
|
else if (typeof seg === "symbol")
|
|
@@ -17423,13 +17423,13 @@ function resolveRef(ref, ctx) {
|
|
|
17423
17423
|
if (!ref.startsWith("#")) {
|
|
17424
17424
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
17425
17425
|
}
|
|
17426
|
-
const
|
|
17427
|
-
if (
|
|
17426
|
+
const path74 = ref.slice(1).split("/").filter(Boolean);
|
|
17427
|
+
if (path74.length === 0) {
|
|
17428
17428
|
return ctx.rootSchema;
|
|
17429
17429
|
}
|
|
17430
17430
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
17431
|
-
if (
|
|
17432
|
-
const key =
|
|
17431
|
+
if (path74[0] === defsKey) {
|
|
17432
|
+
const key = path74[1];
|
|
17433
17433
|
if (!key || !ctx.defs[key]) {
|
|
17434
17434
|
throw new Error(`Reference not found: ${ref}`);
|
|
17435
17435
|
}
|
|
@@ -19765,11 +19765,11 @@ var init_tools = __esm({
|
|
|
19765
19765
|
if (!ctx.addDocument)
|
|
19766
19766
|
return "Knowledge vault tool not available.";
|
|
19767
19767
|
const title = args["title"] || "New Document";
|
|
19768
|
-
const
|
|
19768
|
+
const path74 = args["path"] || `notes/${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
|
|
19769
19769
|
const content = args["content"] || "";
|
|
19770
19770
|
const tags = args["tags"] || [];
|
|
19771
19771
|
ctx.addDocument({
|
|
19772
|
-
path:
|
|
19772
|
+
path: path74,
|
|
19773
19773
|
title,
|
|
19774
19774
|
content,
|
|
19775
19775
|
format: "markdown",
|
|
@@ -19778,7 +19778,7 @@ var init_tools = __esm({
|
|
|
19778
19778
|
workspaceId: ctx.workspaceId
|
|
19779
19779
|
});
|
|
19780
19780
|
ctx.addActivity("vault", "created document", title);
|
|
19781
|
-
return `Document "${title}" created at "${
|
|
19781
|
+
return `Document "${title}" created at "${path74}".`;
|
|
19782
19782
|
}
|
|
19783
19783
|
}
|
|
19784
19784
|
];
|
|
@@ -25734,11 +25734,11 @@ var init_synthesisAudit = __esm({
|
|
|
25734
25734
|
import { existsSync as existsSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "node:fs";
|
|
25735
25735
|
import { join as join4 } from "node:path";
|
|
25736
25736
|
function loadNfrSpec(zelariRoot) {
|
|
25737
|
-
const
|
|
25738
|
-
if (!existsSync7(
|
|
25737
|
+
const path74 = join4(zelariRoot, "nfr-spec.json");
|
|
25738
|
+
if (!existsSync7(path74))
|
|
25739
25739
|
return null;
|
|
25740
25740
|
try {
|
|
25741
|
-
const raw = JSON.parse(readFileSync7(
|
|
25741
|
+
const raw = JSON.parse(readFileSync7(path74, "utf8"));
|
|
25742
25742
|
if (raw.version !== 1 || !Array.isArray(raw.targets))
|
|
25743
25743
|
return null;
|
|
25744
25744
|
return raw;
|
|
@@ -28044,9 +28044,9 @@ var init_types5 = __esm({
|
|
|
28044
28044
|
import { readFileSync as readFileSync12 } from "node:fs";
|
|
28045
28045
|
import { join as join10 } from "node:path";
|
|
28046
28046
|
function readLessonsDeduped(zelariRoot) {
|
|
28047
|
-
const
|
|
28047
|
+
const path74 = join10(zelariRoot, LESSONS_FILE);
|
|
28048
28048
|
try {
|
|
28049
|
-
const raw = readFileSync12(
|
|
28049
|
+
const raw = readFileSync12(path74, "utf8");
|
|
28050
28050
|
const byId = /* @__PURE__ */ new Map();
|
|
28051
28051
|
for (const line of raw.split(/\r?\n/)) {
|
|
28052
28052
|
if (!line.trim())
|
|
@@ -28147,8 +28147,8 @@ function keywordsFrom(check2, signature) {
|
|
|
28147
28147
|
return [.../* @__PURE__ */ new Set([...fromId, ...words])].slice(0, 12);
|
|
28148
28148
|
}
|
|
28149
28149
|
function writeLesson(zelariRoot, lesson) {
|
|
28150
|
-
const
|
|
28151
|
-
appendFileSync(
|
|
28150
|
+
const path74 = join11(zelariRoot, LESSONS_FILE);
|
|
28151
|
+
appendFileSync(path74, `${JSON.stringify(lesson)}
|
|
28152
28152
|
`, "utf8");
|
|
28153
28153
|
}
|
|
28154
28154
|
function findSimilar(lessons, signature) {
|
|
@@ -30111,9 +30111,9 @@ function findCycle(nodes) {
|
|
|
30111
30111
|
if (color.get(start) !== WHITE)
|
|
30112
30112
|
continue;
|
|
30113
30113
|
const stack = [[start, 0]];
|
|
30114
|
-
const
|
|
30114
|
+
const path74 = [];
|
|
30115
30115
|
color.set(start, GRAY);
|
|
30116
|
-
|
|
30116
|
+
path74.push(start);
|
|
30117
30117
|
while (stack.length > 0) {
|
|
30118
30118
|
const top = stack[stack.length - 1];
|
|
30119
30119
|
const [id3, idx] = top;
|
|
@@ -30126,17 +30126,17 @@ function findCycle(nodes) {
|
|
|
30126
30126
|
continue;
|
|
30127
30127
|
const c = color.get(dep);
|
|
30128
30128
|
if (c === GRAY) {
|
|
30129
|
-
const at =
|
|
30130
|
-
return [...
|
|
30129
|
+
const at = path74.indexOf(dep);
|
|
30130
|
+
return [...path74.slice(at), dep];
|
|
30131
30131
|
}
|
|
30132
30132
|
if (c === WHITE) {
|
|
30133
30133
|
color.set(dep, GRAY);
|
|
30134
|
-
|
|
30134
|
+
path74.push(dep);
|
|
30135
30135
|
stack.push([dep, 0]);
|
|
30136
30136
|
}
|
|
30137
30137
|
} else {
|
|
30138
30138
|
color.set(id3, BLACK);
|
|
30139
|
-
|
|
30139
|
+
path74.pop();
|
|
30140
30140
|
stack.pop();
|
|
30141
30141
|
}
|
|
30142
30142
|
}
|
|
@@ -31056,8 +31056,8 @@ var init_runner = __esm({
|
|
|
31056
31056
|
failed: [...this.tentaclesById.values()].filter((r) => r.status === "error"),
|
|
31057
31057
|
pending: []
|
|
31058
31058
|
};
|
|
31059
|
-
const
|
|
31060
|
-
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${
|
|
31059
|
+
const path74 = await this.host.saveSnapshot(snapshot, ".zelari/kraken/snapshots");
|
|
31060
|
+
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${path74}`);
|
|
31061
31061
|
return snapshot;
|
|
31062
31062
|
}
|
|
31063
31063
|
callLog(msg, data) {
|
|
@@ -33499,16 +33499,16 @@ function runRetentionFromEnv() {
|
|
|
33499
33499
|
maxTotalBytes: Number.isFinite(parseMb) && parseMb > 0 ? Math.round(parseMb * 1024 * 1024) : DEFAULT_RUN_RETENTION_MAX_MB * 1024 * 1024
|
|
33500
33500
|
};
|
|
33501
33501
|
}
|
|
33502
|
-
async function dirSize(
|
|
33502
|
+
async function dirSize(path74) {
|
|
33503
33503
|
let total = 0;
|
|
33504
33504
|
let entries;
|
|
33505
33505
|
try {
|
|
33506
|
-
entries = await readdir(
|
|
33506
|
+
entries = await readdir(path74, { withFileTypes: true });
|
|
33507
33507
|
} catch {
|
|
33508
33508
|
return 0;
|
|
33509
33509
|
}
|
|
33510
33510
|
for (const entry of entries) {
|
|
33511
|
-
const child = join13(
|
|
33511
|
+
const child = join13(path74, entry.name);
|
|
33512
33512
|
if (entry.isDirectory())
|
|
33513
33513
|
total += await dirSize(child);
|
|
33514
33514
|
else {
|
|
@@ -33535,19 +33535,19 @@ async function enforceRunRetention(runsDir, options = {}) {
|
|
|
33535
33535
|
for (const entry of entries) {
|
|
33536
33536
|
if (!entry.isDirectory())
|
|
33537
33537
|
continue;
|
|
33538
|
-
const
|
|
33538
|
+
const path74 = join13(runsDir, entry.name);
|
|
33539
33539
|
let startedAt = 0;
|
|
33540
33540
|
let endedAt;
|
|
33541
33541
|
let completed = false;
|
|
33542
33542
|
try {
|
|
33543
|
-
const manifest = JSON.parse(await readFile(join13(
|
|
33543
|
+
const manifest = JSON.parse(await readFile(join13(path74, "manifest.json"), "utf8"));
|
|
33544
33544
|
startedAt = manifest.startedAt ?? 0;
|
|
33545
33545
|
endedAt = manifest.endedAt;
|
|
33546
33546
|
completed = Boolean(endedAt) && manifest.status !== "running";
|
|
33547
33547
|
} catch {
|
|
33548
33548
|
completed = false;
|
|
33549
33549
|
}
|
|
33550
|
-
infos.push({ name: entry.name, path:
|
|
33550
|
+
infos.push({ name: entry.name, path: path74, startedAt, endedAt, completed, bytes: await dirSize(path74) });
|
|
33551
33551
|
}
|
|
33552
33552
|
const remove = async (info) => {
|
|
33553
33553
|
await rm(info.path, { recursive: true, force: true });
|
|
@@ -34319,12 +34319,12 @@ var init_engine = __esm({
|
|
|
34319
34319
|
* content digest) and the returned ref carries the event seq when the
|
|
34320
34320
|
* emitter resolved one.
|
|
34321
34321
|
*/
|
|
34322
|
-
async fsEvidence(observation,
|
|
34322
|
+
async fsEvidence(observation, path74, sha256, content, extra = {}) {
|
|
34323
34323
|
const digest = sha256 && content !== void 0 ? sha256(content) : void 0;
|
|
34324
|
-
const seq = await this.emitEvidence({ observation, path:
|
|
34324
|
+
const seq = await this.emitEvidence({ observation, path: path74, ...extra, ...digest ? { digest } : {} });
|
|
34325
34325
|
return {
|
|
34326
34326
|
tier: "fs-observation",
|
|
34327
|
-
ref:
|
|
34327
|
+
ref: path74,
|
|
34328
34328
|
capturedAt: Date.now(),
|
|
34329
34329
|
...digest ? { digest } : {},
|
|
34330
34330
|
...seq !== void 0 ? { seq } : {}
|
|
@@ -34706,7 +34706,8 @@ var init_verifier = __esm({
|
|
|
34706
34706
|
});
|
|
34707
34707
|
VERIFIER_SYSTEM_PROMPT = [
|
|
34708
34708
|
"You are an independent completion verifier.",
|
|
34709
|
-
"You receive a
|
|
34709
|
+
"You receive the original task, a git diff summary, a test output excerpt,",
|
|
34710
|
+
"and deterministic verification results \u2014 never the builder narration.",
|
|
34710
34711
|
"Answer with a single JSON object and nothing else:",
|
|
34711
34712
|
'{"verdict":"confirmed|rejected|unknown","score":0..1,"rationale":"..."}',
|
|
34712
34713
|
"Rules: never confirm when a required deterministic check failed or is unknown;",
|
|
@@ -34741,8 +34742,14 @@ var init_verifier = __esm({
|
|
|
34741
34742
|
try {
|
|
34742
34743
|
response = await this.deps.callModel({
|
|
34743
34744
|
system: VERIFIER_SYSTEM_PROMPT,
|
|
34745
|
+
// Blind review payload: evidence only (task, diff summary, test output
|
|
34746
|
+
// excerpt, deterministic results). Builder narration/reasoning is
|
|
34747
|
+
// structurally excluded — undefined keys are omitted.
|
|
34744
34748
|
user: JSON.stringify({
|
|
34749
|
+
...request.task === void 0 ? {} : { task: request.task },
|
|
34745
34750
|
summary: request.summary,
|
|
34751
|
+
...request.diffSummary === void 0 ? {} : { diffSummary: request.diffSummary },
|
|
34752
|
+
...request.testOutputExcerpt === void 0 ? {} : { testOutputExcerpt: request.testOutputExcerpt },
|
|
34746
34753
|
deterministicResults: request.results.map((r) => ({
|
|
34747
34754
|
criterionId: r.criterionId,
|
|
34748
34755
|
status: r.status,
|
|
@@ -37457,9 +37464,9 @@ function spillToolOutput(fullText, meta3) {
|
|
|
37457
37464
|
const rnd = randomBytes3(3).toString("hex");
|
|
37458
37465
|
const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
|
|
37459
37466
|
const file2 = `${stamp}-${safeTool}-${hash3}-${rnd}.txt`;
|
|
37460
|
-
const
|
|
37461
|
-
writeFileSync11(
|
|
37462
|
-
return
|
|
37467
|
+
const path74 = join14(dir, file2);
|
|
37468
|
+
writeFileSync11(path74, fullText, "utf8");
|
|
37469
|
+
return path74;
|
|
37463
37470
|
} catch {
|
|
37464
37471
|
return null;
|
|
37465
37472
|
}
|
|
@@ -37505,10 +37512,10 @@ function truncateToolResult(text, capOrOpts = TOOL_RESULT_LINE_CAP) {
|
|
|
37505
37512
|
${tail2}`;
|
|
37506
37513
|
}
|
|
37507
37514
|
if (doSpill) {
|
|
37508
|
-
const
|
|
37509
|
-
if (
|
|
37515
|
+
const path74 = spillToolOutput(text, { toolName: opts.toolName });
|
|
37516
|
+
if (path74) {
|
|
37510
37517
|
const spillNote = `
|
|
37511
|
-
\u2026 [full output spilled to: ${
|
|
37518
|
+
\u2026 [full output spilled to: ${path74} \u2014 re-read with read_file if you need the complete text] \u2026`;
|
|
37512
37519
|
if (preview.includes("] \u2026\n")) {
|
|
37513
37520
|
preview = preview.replace("] \u2026\n", `] \u2026${spillNote}
|
|
37514
37521
|
`);
|
|
@@ -40340,28 +40347,28 @@ var init_storage = __esm({
|
|
|
40340
40347
|
VALID_SCALARS = /^(true|false|null|~)$/i;
|
|
40341
40348
|
Storage = class {
|
|
40342
40349
|
/** Read a Markdown file with frontmatter. Throws if not found. */
|
|
40343
|
-
read(
|
|
40344
|
-
if (!existsSync19(
|
|
40345
|
-
throw new Error(`File not found: ${
|
|
40350
|
+
read(path74) {
|
|
40351
|
+
if (!existsSync19(path74)) {
|
|
40352
|
+
throw new Error(`File not found: ${path74}`);
|
|
40346
40353
|
}
|
|
40347
|
-
const md = readFileSync16(
|
|
40354
|
+
const md = readFileSync16(path74, "utf8");
|
|
40348
40355
|
return parseFrontmatter(md);
|
|
40349
40356
|
}
|
|
40350
40357
|
/** Read a Markdown file; returns null if not found. */
|
|
40351
|
-
readIfExists(
|
|
40352
|
-
if (!existsSync19(
|
|
40353
|
-
return this.read(
|
|
40358
|
+
readIfExists(path74) {
|
|
40359
|
+
if (!existsSync19(path74)) return null;
|
|
40360
|
+
return this.read(path74);
|
|
40354
40361
|
}
|
|
40355
40362
|
/**
|
|
40356
40363
|
* Write a Markdown file atomically (tmp + rename). Creates parent dirs.
|
|
40357
40364
|
* The meta object is serialized as YAML frontmatter; body as Markdown.
|
|
40358
40365
|
*/
|
|
40359
|
-
write(
|
|
40360
|
-
mkdirSync10(dirname2(
|
|
40361
|
-
const tmp =
|
|
40366
|
+
write(path74, meta3, body) {
|
|
40367
|
+
mkdirSync10(dirname2(path74), { recursive: true });
|
|
40368
|
+
const tmp = path74 + ".tmp-" + process.pid;
|
|
40362
40369
|
const md = serializeFrontmatter(meta3, body);
|
|
40363
40370
|
writeFileSync13(tmp, md, "utf8");
|
|
40364
|
-
renameSync(tmp,
|
|
40371
|
+
renameSync(tmp, path74);
|
|
40365
40372
|
}
|
|
40366
40373
|
/** List all .md files in a directory (non-recursive). */
|
|
40367
40374
|
listMarkdown(dir) {
|
|
@@ -40423,8 +40430,8 @@ function nextPlanTaskId(store6) {
|
|
|
40423
40430
|
return `t${store6.counter}`;
|
|
40424
40431
|
}
|
|
40425
40432
|
function writePlanTaskArtifact(rootDir, task) {
|
|
40426
|
-
const
|
|
40427
|
-
mkdirSync11(dirname3(
|
|
40433
|
+
const path74 = join18(rootDir, "plan-tasks", `${task.id}.md`);
|
|
40434
|
+
mkdirSync11(dirname3(path74), { recursive: true });
|
|
40428
40435
|
const meta3 = {
|
|
40429
40436
|
kind: "task",
|
|
40430
40437
|
id: task.id,
|
|
@@ -40445,7 +40452,7 @@ function writePlanTaskArtifact(rootDir, task) {
|
|
|
40445
40452
|
task.notes?.trim() ? task.notes.trim() : "_(no notes)_",
|
|
40446
40453
|
""
|
|
40447
40454
|
].filter((l) => l !== null).join("\n");
|
|
40448
|
-
new Storage().write(
|
|
40455
|
+
new Storage().write(path74, meta3, body);
|
|
40449
40456
|
}
|
|
40450
40457
|
function loadHandle(rootDir) {
|
|
40451
40458
|
const jsonPath = join18(rootDir, "plan.json");
|
|
@@ -43733,21 +43740,21 @@ function normalizeAuth(auth) {
|
|
|
43733
43740
|
return "agent";
|
|
43734
43741
|
}
|
|
43735
43742
|
function readSecrets() {
|
|
43736
|
-
const
|
|
43737
|
-
if (!existsSync23(
|
|
43743
|
+
const path74 = getSshSecretsPath();
|
|
43744
|
+
if (!existsSync23(path74)) return {};
|
|
43738
43745
|
try {
|
|
43739
|
-
return JSON.parse(readFileSync20(
|
|
43746
|
+
return JSON.parse(readFileSync20(path74, "utf8"));
|
|
43740
43747
|
} catch {
|
|
43741
43748
|
return {};
|
|
43742
43749
|
}
|
|
43743
43750
|
}
|
|
43744
43751
|
function writeSecrets(data) {
|
|
43745
|
-
const
|
|
43746
|
-
mkdirSync12(dirname4(
|
|
43747
|
-
writeFileSync15(
|
|
43752
|
+
const path74 = getSshSecretsPath();
|
|
43753
|
+
mkdirSync12(dirname4(path74), { recursive: true });
|
|
43754
|
+
writeFileSync15(path74, `${JSON.stringify(data, null, 2)}
|
|
43748
43755
|
`, "utf8");
|
|
43749
43756
|
try {
|
|
43750
|
-
chmodSync(
|
|
43757
|
+
chmodSync(path74, 384);
|
|
43751
43758
|
} catch {
|
|
43752
43759
|
}
|
|
43753
43760
|
}
|
|
@@ -43776,10 +43783,10 @@ function deleteSshPassword(id3) {
|
|
|
43776
43783
|
writeSecrets({ passwords });
|
|
43777
43784
|
}
|
|
43778
43785
|
function readStore2() {
|
|
43779
|
-
const
|
|
43780
|
-
if (!existsSync23(
|
|
43786
|
+
const path74 = getSshTargetsPath();
|
|
43787
|
+
if (!existsSync23(path74)) return [];
|
|
43781
43788
|
try {
|
|
43782
|
-
const parsed = JSON.parse(readFileSync20(
|
|
43789
|
+
const parsed = JSON.parse(readFileSync20(path74, "utf8"));
|
|
43783
43790
|
const list = Array.isArray(parsed.targets) ? parsed.targets : [];
|
|
43784
43791
|
return list.filter(
|
|
43785
43792
|
(t) => t && typeof t.id === "string" && typeof t.host === "string" && typeof t.user === "string"
|
|
@@ -43794,11 +43801,11 @@ function readStore2() {
|
|
|
43794
43801
|
}
|
|
43795
43802
|
}
|
|
43796
43803
|
function writeStore2(targets) {
|
|
43797
|
-
const
|
|
43798
|
-
mkdirSync12(dirname4(
|
|
43804
|
+
const path74 = getSshTargetsPath();
|
|
43805
|
+
mkdirSync12(dirname4(path74), { recursive: true });
|
|
43799
43806
|
const clean = targets.map(({ hasPassword: _hp, ...t }) => t);
|
|
43800
43807
|
writeFileSync15(
|
|
43801
|
-
|
|
43808
|
+
path74,
|
|
43802
43809
|
`${JSON.stringify({ targets: clean }, null, 2)}
|
|
43803
43810
|
`,
|
|
43804
43811
|
"utf8"
|
|
@@ -44044,11 +44051,11 @@ function formatSshTargetsForPrompt() {
|
|
|
44044
44051
|
];
|
|
44045
44052
|
for (const t of targets) {
|
|
44046
44053
|
const tags = t.tags?.length ? ` tags=[${t.tags.join(",")}]` : "";
|
|
44047
|
-
const
|
|
44054
|
+
const path74 = t.defaultRemotePath ? ` remotePath=${t.defaultRemotePath}` : "";
|
|
44048
44055
|
const allow = t.allowedCommands?.length ? ` allowed=${t.allowedCommands.join("|")}` : " allowed=status-only";
|
|
44049
44056
|
const auth = t.auth === "password" ? " auth=password" : t.auth === "keyPath" ? " auth=key" : " auth=agent";
|
|
44050
44057
|
lines.push(
|
|
44051
|
-
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${
|
|
44058
|
+
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${path74}${tags}${allow}`
|
|
44052
44059
|
);
|
|
44053
44060
|
}
|
|
44054
44061
|
return lines.join("\n");
|
|
@@ -45048,6 +45055,19 @@ function defaultPermissionPolicy(overrides) {
|
|
|
45048
45055
|
...overrides
|
|
45049
45056
|
};
|
|
45050
45057
|
}
|
|
45058
|
+
function moreRestrictive(a, b) {
|
|
45059
|
+
return ACTION_RANK2[a] >= ACTION_RANK2[b] ? a : b;
|
|
45060
|
+
}
|
|
45061
|
+
function intersectPermissionPolicy(parent, child) {
|
|
45062
|
+
return {
|
|
45063
|
+
read: moreRestrictive(parent.read, child.read),
|
|
45064
|
+
write: moreRestrictive(parent.write, child.write),
|
|
45065
|
+
execute: moreRestrictive(parent.execute, child.execute),
|
|
45066
|
+
network: moreRestrictive(parent.network, child.network),
|
|
45067
|
+
ui: moreRestrictive(parent.ui, child.ui),
|
|
45068
|
+
auto: parent.auto && child.auto
|
|
45069
|
+
};
|
|
45070
|
+
}
|
|
45051
45071
|
function resolveToolPermission(toolName, required2, policy) {
|
|
45052
45072
|
if (!required2.length) {
|
|
45053
45073
|
return { action: "allow", reason: "", categories: [] };
|
|
@@ -45083,12 +45103,13 @@ function resolveToolPermission(toolName, required2, policy) {
|
|
|
45083
45103
|
categories: hit
|
|
45084
45104
|
};
|
|
45085
45105
|
}
|
|
45086
|
-
var sessionToolGrants, sessionCategoryGrants;
|
|
45106
|
+
var sessionToolGrants, sessionCategoryGrants, ACTION_RANK2;
|
|
45087
45107
|
var init_toolPermissions = __esm({
|
|
45088
45108
|
"src/cli/safety/toolPermissions.ts"() {
|
|
45089
45109
|
"use strict";
|
|
45090
45110
|
sessionToolGrants = /* @__PURE__ */ new Set();
|
|
45091
45111
|
sessionCategoryGrants = /* @__PURE__ */ new Set();
|
|
45112
|
+
ACTION_RANK2 = { allow: 0, ask: 1, deny: 2 };
|
|
45092
45113
|
}
|
|
45093
45114
|
});
|
|
45094
45115
|
|
|
@@ -45265,10 +45286,194 @@ var init_lifecycleHooks = __esm({
|
|
|
45265
45286
|
}
|
|
45266
45287
|
});
|
|
45267
45288
|
|
|
45289
|
+
// src/cli/safety/policyEngine.ts
|
|
45290
|
+
import { readFileSync as readFileSync22 } from "node:fs";
|
|
45291
|
+
import { homedir as homedir10 } from "node:os";
|
|
45292
|
+
import path40 from "node:path";
|
|
45293
|
+
function emptyPolicySet() {
|
|
45294
|
+
return { agents: /* @__PURE__ */ new Map(), warnings: [] };
|
|
45295
|
+
}
|
|
45296
|
+
function agentRulesFor(set2, agent) {
|
|
45297
|
+
return set2.agents.get(agent) ?? EMPTY_POLICY_RULE_SET;
|
|
45298
|
+
}
|
|
45299
|
+
function globToRegExp(pattern) {
|
|
45300
|
+
let src = "^";
|
|
45301
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
45302
|
+
const ch = pattern[i];
|
|
45303
|
+
if (ch === "*") {
|
|
45304
|
+
while (pattern[i + 1] === "*") i++;
|
|
45305
|
+
src += ".*";
|
|
45306
|
+
} else if ("\\^$.|?+()[]{}".includes(ch)) {
|
|
45307
|
+
src += "\\" + ch;
|
|
45308
|
+
} else {
|
|
45309
|
+
src += ch;
|
|
45310
|
+
}
|
|
45311
|
+
}
|
|
45312
|
+
return new RegExp(src + "$");
|
|
45313
|
+
}
|
|
45314
|
+
function normalizeForMatch(value) {
|
|
45315
|
+
return value.replace(/\\/g, "/");
|
|
45316
|
+
}
|
|
45317
|
+
function resolvePolicyRule(rules, value) {
|
|
45318
|
+
const v = normalizeForMatch(value);
|
|
45319
|
+
for (const rule of rules) {
|
|
45320
|
+
if (globToRegExp(normalizeForMatch(rule.match)).test(v)) return rule;
|
|
45321
|
+
}
|
|
45322
|
+
return null;
|
|
45323
|
+
}
|
|
45324
|
+
function mergeRuleEffect(base2, rule) {
|
|
45325
|
+
if (!rule) return base2;
|
|
45326
|
+
return EFFECT_RANK[rule.effect] > EFFECT_RANK[base2] ? rule.effect : base2;
|
|
45327
|
+
}
|
|
45328
|
+
function pathCandidates(value, root) {
|
|
45329
|
+
const norm = normalizeForMatch(value);
|
|
45330
|
+
if (!root) return [norm];
|
|
45331
|
+
const prefix = normalizeForMatch(root).replace(/\/+$/, "") + "/";
|
|
45332
|
+
const stripped = norm.toLowerCase().startsWith(prefix.toLowerCase()) ? norm.slice(prefix.length) : null;
|
|
45333
|
+
return stripped !== null ? [stripped, norm] : [norm];
|
|
45334
|
+
}
|
|
45335
|
+
function matchAgentPolicyRule(rules, required2, args, root) {
|
|
45336
|
+
if (!rules) return null;
|
|
45337
|
+
const a = args !== null && typeof args === "object" ? args : {};
|
|
45338
|
+
if (required2.includes("execute")) {
|
|
45339
|
+
const cmd = a["command"];
|
|
45340
|
+
if (typeof cmd === "string" && cmd !== "") {
|
|
45341
|
+
const hit = resolvePolicyRule(rules.shell, cmd);
|
|
45342
|
+
if (hit) return hit;
|
|
45343
|
+
}
|
|
45344
|
+
}
|
|
45345
|
+
if (required2.includes("write")) {
|
|
45346
|
+
const p3 = typeof a["path"] === "string" ? a["path"] : typeof a["file_path"] === "string" ? a["file_path"] : "";
|
|
45347
|
+
if (p3 !== "") {
|
|
45348
|
+
for (const candidate of pathCandidates(p3, root)) {
|
|
45349
|
+
const hit = resolvePolicyRule(rules.edit, candidate);
|
|
45350
|
+
if (hit) return hit;
|
|
45351
|
+
}
|
|
45352
|
+
}
|
|
45353
|
+
}
|
|
45354
|
+
return null;
|
|
45355
|
+
}
|
|
45356
|
+
function isPolicyEngineDisabled() {
|
|
45357
|
+
const v = process.env.ZELARI_POLICY?.trim().toLowerCase();
|
|
45358
|
+
return v === "0" || v === "false" || v === "no" || v === "off";
|
|
45359
|
+
}
|
|
45360
|
+
function isPlainObject2(v) {
|
|
45361
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
45362
|
+
}
|
|
45363
|
+
function parseRuleList(raw, origin, warnings) {
|
|
45364
|
+
if (raw === void 0) return [];
|
|
45365
|
+
if (!Array.isArray(raw)) {
|
|
45366
|
+
warnings.push(`${origin}: expected an array of rules, got ${typeof raw} \u2014 section ignored.`);
|
|
45367
|
+
return [];
|
|
45368
|
+
}
|
|
45369
|
+
const out = [];
|
|
45370
|
+
raw.forEach((item, i) => {
|
|
45371
|
+
const where = `${origin}[${i}]`;
|
|
45372
|
+
if (!isPlainObject2(item)) {
|
|
45373
|
+
warnings.push(`${where}: rule is not an object \u2014 skipped.`);
|
|
45374
|
+
return;
|
|
45375
|
+
}
|
|
45376
|
+
const match = item["match"];
|
|
45377
|
+
const effect = item["effect"];
|
|
45378
|
+
const reason = item["reason"];
|
|
45379
|
+
if (typeof match !== "string" || match.trim() === "") {
|
|
45380
|
+
warnings.push(`${where}: missing or empty "match" \u2014 skipped.`);
|
|
45381
|
+
return;
|
|
45382
|
+
}
|
|
45383
|
+
if (effect !== "allow" && effect !== "ask" && effect !== "deny") {
|
|
45384
|
+
warnings.push(`${where} ("${match}"): "effect" must be allow|ask|deny \u2014 skipped.`);
|
|
45385
|
+
return;
|
|
45386
|
+
}
|
|
45387
|
+
out.push(
|
|
45388
|
+
typeof reason === "string" && reason.trim() !== "" ? { match, effect, reason } : { match, effect }
|
|
45389
|
+
);
|
|
45390
|
+
});
|
|
45391
|
+
return out;
|
|
45392
|
+
}
|
|
45393
|
+
function parsePolicyFile(raw, origin, warnings) {
|
|
45394
|
+
if (!isPlainObject2(raw)) {
|
|
45395
|
+
warnings.push(`${origin}: policy file is not a JSON object \u2014 file ignored.`);
|
|
45396
|
+
return null;
|
|
45397
|
+
}
|
|
45398
|
+
const version2 = raw["version"];
|
|
45399
|
+
if (version2 !== void 0 && version2 !== 1) {
|
|
45400
|
+
warnings.push(`${origin}: unsupported "version" ${JSON.stringify(version2)} (expected 1) \u2014 file ignored.`);
|
|
45401
|
+
return null;
|
|
45402
|
+
}
|
|
45403
|
+
const agentsRaw = raw["agents"];
|
|
45404
|
+
if (agentsRaw === void 0) {
|
|
45405
|
+
warnings.push(`${origin}: no "agents" key \u2014 file ignored.`);
|
|
45406
|
+
return null;
|
|
45407
|
+
}
|
|
45408
|
+
if (!isPlainObject2(agentsRaw)) {
|
|
45409
|
+
warnings.push(`${origin}: "agents" is not an object \u2014 file ignored.`);
|
|
45410
|
+
return null;
|
|
45411
|
+
}
|
|
45412
|
+
const out = /* @__PURE__ */ new Map();
|
|
45413
|
+
for (const [key, val] of Object.entries(agentsRaw)) {
|
|
45414
|
+
const agent = key.trim().toLowerCase();
|
|
45415
|
+
if (!KNOWN_AGENTS.has(agent)) {
|
|
45416
|
+
warnings.push(`${origin}: unknown agent "${key}" (known: ${POLICY_AGENTS.join(" | ")}) \u2014 ignored.`);
|
|
45417
|
+
continue;
|
|
45418
|
+
}
|
|
45419
|
+
if (!isPlainObject2(val)) {
|
|
45420
|
+
warnings.push(`${origin}: agents.${key} is not an object \u2014 ignored.`);
|
|
45421
|
+
continue;
|
|
45422
|
+
}
|
|
45423
|
+
const shell = parseRuleList(val["shell"], `${origin} agents.${key}.shell`, warnings);
|
|
45424
|
+
const edit = parseRuleList(val["edit"], `${origin} agents.${key}.edit`, warnings);
|
|
45425
|
+
out.set(agent, { shell, edit });
|
|
45426
|
+
}
|
|
45427
|
+
return out;
|
|
45428
|
+
}
|
|
45429
|
+
function readPolicyFile(file2, warnings) {
|
|
45430
|
+
let text;
|
|
45431
|
+
try {
|
|
45432
|
+
text = readFileSync22(file2, "utf8");
|
|
45433
|
+
} catch {
|
|
45434
|
+
return /* @__PURE__ */ new Map();
|
|
45435
|
+
}
|
|
45436
|
+
let parsed;
|
|
45437
|
+
try {
|
|
45438
|
+
parsed = JSON.parse(text);
|
|
45439
|
+
} catch (err) {
|
|
45440
|
+
warnings.push(
|
|
45441
|
+
`${file2}: invalid JSON (${err instanceof Error ? err.message : String(err)}) \u2014 file ignored.`
|
|
45442
|
+
);
|
|
45443
|
+
return /* @__PURE__ */ new Map();
|
|
45444
|
+
}
|
|
45445
|
+
return parsePolicyFile(parsed, file2, warnings) ?? /* @__PURE__ */ new Map();
|
|
45446
|
+
}
|
|
45447
|
+
function loadPolicySet(root, opts = {}) {
|
|
45448
|
+
if (isPolicyEngineDisabled()) return emptyPolicySet();
|
|
45449
|
+
const warnings = [];
|
|
45450
|
+
const project = readPolicyFile(path40.join(root, ".zelari", "policy.json"), warnings);
|
|
45451
|
+
const global = readPolicyFile(path40.join(opts.homeDir ?? homedir10(), ".zelari", "policy.json"), warnings);
|
|
45452
|
+
const agents = /* @__PURE__ */ new Map();
|
|
45453
|
+
for (const [agent, g] of global) {
|
|
45454
|
+
agents.set(agent, { shell: [...g.shell], edit: [...g.edit] });
|
|
45455
|
+
}
|
|
45456
|
+
for (const [agent, p3] of project) {
|
|
45457
|
+
const g = agents.get(agent) ?? EMPTY_POLICY_RULE_SET;
|
|
45458
|
+
agents.set(agent, { shell: [...p3.shell, ...g.shell], edit: [...p3.edit, ...g.edit] });
|
|
45459
|
+
}
|
|
45460
|
+
return { agents, warnings };
|
|
45461
|
+
}
|
|
45462
|
+
var POLICY_AGENTS, KNOWN_AGENTS, EMPTY_POLICY_RULE_SET, EFFECT_RANK;
|
|
45463
|
+
var init_policyEngine = __esm({
|
|
45464
|
+
"src/cli/safety/policyEngine.ts"() {
|
|
45465
|
+
"use strict";
|
|
45466
|
+
POLICY_AGENTS = ["lead", "explore", "general", "verify"];
|
|
45467
|
+
KNOWN_AGENTS = new Set(POLICY_AGENTS);
|
|
45468
|
+
EMPTY_POLICY_RULE_SET = { shell: [], edit: [] };
|
|
45469
|
+
EFFECT_RANK = { allow: 0, ask: 1, deny: 2 };
|
|
45470
|
+
}
|
|
45471
|
+
});
|
|
45472
|
+
|
|
45268
45473
|
// src/cli/toolResultCache.ts
|
|
45269
45474
|
import { createHash as createHash13 } from "node:crypto";
|
|
45270
45475
|
import { promises as fs19 } from "node:fs";
|
|
45271
|
-
import
|
|
45476
|
+
import path41 from "node:path";
|
|
45272
45477
|
function isToolCacheEnabled() {
|
|
45273
45478
|
const raw = process.env.ZELARI_TOOL_CACHE;
|
|
45274
45479
|
return raw !== "0" && raw !== "false" && raw !== "off";
|
|
@@ -45353,7 +45558,7 @@ async function statKey(toolName, input, ctx) {
|
|
|
45353
45558
|
if (!input || typeof input !== "object") return null;
|
|
45354
45559
|
const rawPath = input.path;
|
|
45355
45560
|
if (typeof rawPath !== "string" || rawPath.length === 0) return null;
|
|
45356
|
-
const abs =
|
|
45561
|
+
const abs = path41.isAbsolute(rawPath) ? rawPath : path41.join(ctx.cwd, rawPath);
|
|
45357
45562
|
try {
|
|
45358
45563
|
const st = await fs19.stat(abs);
|
|
45359
45564
|
return hashKey({
|
|
@@ -45402,9 +45607,13 @@ var init_toolResultCache = __esm({
|
|
|
45402
45607
|
// src/cli/tools/krakenModel.ts
|
|
45403
45608
|
var krakenModel_exports = {};
|
|
45404
45609
|
__export(krakenModel_exports, {
|
|
45610
|
+
inferModelFamily: () => inferModelFamily,
|
|
45405
45611
|
isCheapModelId: () => isCheapModelId,
|
|
45406
45612
|
isKrakenAutoModelEnabled: () => isKrakenAutoModelEnabled,
|
|
45613
|
+
parseQualifiedModelRef: () => parseQualifiedModelRef,
|
|
45407
45614
|
pickCheapModel: () => pickCheapModel,
|
|
45615
|
+
pickDifferentFamily: () => pickDifferentFamily,
|
|
45616
|
+
resolveCrossModelVerifier: () => resolveCrossModelVerifier,
|
|
45408
45617
|
resolveKrakenPlannerModel: () => resolveKrakenPlannerModel,
|
|
45409
45618
|
resolveKrakenSubModel: () => resolveKrakenSubModel,
|
|
45410
45619
|
resolveKrakenSubModelAsync: () => resolveKrakenSubModelAsync,
|
|
@@ -45440,6 +45649,53 @@ function isKrakenAutoModelEnabled(env = process.env) {
|
|
|
45440
45649
|
if (v === "0" || v === "false" || v === "no" || v === "off") return false;
|
|
45441
45650
|
return true;
|
|
45442
45651
|
}
|
|
45652
|
+
function parseQualifiedModelRef(ref) {
|
|
45653
|
+
const s = ref?.trim() ?? "";
|
|
45654
|
+
const slash = s.indexOf("/");
|
|
45655
|
+
if (slash <= 0 || slash === s.length - 1) return null;
|
|
45656
|
+
const provider = s.slice(0, slash).trim();
|
|
45657
|
+
const model = s.slice(slash + 1).trim();
|
|
45658
|
+
if (!provider || !model) return null;
|
|
45659
|
+
return { provider, model };
|
|
45660
|
+
}
|
|
45661
|
+
function inferModelFamily(provider, model) {
|
|
45662
|
+
const p3 = (provider ?? "").trim().toLowerCase();
|
|
45663
|
+
const m = (model ?? "").trim().toLowerCase();
|
|
45664
|
+
const hay = `${p3} ${m}`.trim();
|
|
45665
|
+
if (!hay) return "other";
|
|
45666
|
+
if (/\b(zhipu|glm)\b/.test(hay)) return "zhipu";
|
|
45667
|
+
if (/\b(google|gemini)\b/.test(hay)) return "google";
|
|
45668
|
+
if (/\b(xai|grok)\b/.test(hay)) return "xai";
|
|
45669
|
+
if (/\b(anthropic|claude)\b/.test(hay)) return "anthropic";
|
|
45670
|
+
if (/\b(openai|chatgpt|codex)\b/.test(hay) || /\bgpt\b/.test(hay) || /(^|\s)o[134]($|[-_.])/.test(hay)) {
|
|
45671
|
+
return "openai";
|
|
45672
|
+
}
|
|
45673
|
+
return p3 || "other";
|
|
45674
|
+
}
|
|
45675
|
+
function pickDifferentFamily(builder, candidates) {
|
|
45676
|
+
const builderFamily = inferModelFamily(builder.provider, builder.model);
|
|
45677
|
+
for (const c of candidates) {
|
|
45678
|
+
const provider = c.provider?.trim() ?? "";
|
|
45679
|
+
const model = c.model?.trim() ?? "";
|
|
45680
|
+
if (!provider || !model) continue;
|
|
45681
|
+
if (inferModelFamily(provider, model) !== builderFamily) {
|
|
45682
|
+
return { provider, model };
|
|
45683
|
+
}
|
|
45684
|
+
}
|
|
45685
|
+
return null;
|
|
45686
|
+
}
|
|
45687
|
+
function resolveCrossModelVerifier(builder, candidates, env = process.env) {
|
|
45688
|
+
const cross = (env.ZELARI_KRAKEN_CROSS_MODEL ?? "").trim().toLowerCase();
|
|
45689
|
+
if (cross === "0" || cross === "false" || cross === "off") return null;
|
|
45690
|
+
const specific = env.ZELARI_KRAKEN_VERIFY_MODEL?.trim();
|
|
45691
|
+
if (specific) {
|
|
45692
|
+
const qualified = parseQualifiedModelRef(specific);
|
|
45693
|
+
if (qualified) return qualified;
|
|
45694
|
+
const provider = builder.provider?.trim();
|
|
45695
|
+
return provider ? { provider, model: specific } : null;
|
|
45696
|
+
}
|
|
45697
|
+
return pickDifferentFamily(builder, candidates);
|
|
45698
|
+
}
|
|
45443
45699
|
function resolveKrakenSubModel(agent, parentModel, env = process.env, opts = {}) {
|
|
45444
45700
|
const kindKey = agent === "explore" ? "ZELARI_KRAKEN_EXPLORE_MODEL" : agent === "verify" ? "ZELARI_KRAKEN_VERIFY_MODEL" : "ZELARI_KRAKEN_GENERAL_MODEL";
|
|
45445
45701
|
const specific = env[kindKey]?.trim();
|
|
@@ -45452,6 +45708,13 @@ function resolveKrakenSubModel(agent, parentModel, env = process.env, opts = {})
|
|
|
45452
45708
|
}
|
|
45453
45709
|
return shared2;
|
|
45454
45710
|
}
|
|
45711
|
+
if (agent === "verify" && opts.familyCandidates && opts.familyCandidates.length > 0) {
|
|
45712
|
+
const picked = pickDifferentFamily(
|
|
45713
|
+
{ provider: opts.provider ?? "", model: parentModel },
|
|
45714
|
+
opts.familyCandidates
|
|
45715
|
+
);
|
|
45716
|
+
if (picked) return `${picked.provider}/${picked.model}`;
|
|
45717
|
+
}
|
|
45455
45718
|
if ((agent === "explore" || agent === "verify") && isKrakenAutoModelEnabled(env) && opts.candidates && opts.candidates.length > 0) {
|
|
45456
45719
|
const picked = pickCheapModel(parentModel, opts.candidates);
|
|
45457
45720
|
if (picked) return picked;
|
|
@@ -45547,7 +45810,11 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
45547
45810
|
const allowMutators = !readOnly && !verifyMode && !gauntletParent;
|
|
45548
45811
|
const allowBash = (allowMutators || verifyMode) && !gauntletParent;
|
|
45549
45812
|
const permPolicy = options.permissionPolicy ?? defaultPermissionPolicy();
|
|
45550
|
-
const
|
|
45813
|
+
const agentPolicyRules = agentRulesFor(
|
|
45814
|
+
loadPolicySet(root),
|
|
45815
|
+
options.policyAgent ?? "lead"
|
|
45816
|
+
);
|
|
45817
|
+
const withPerm = (t) => wrapWithPermissions(t, permPolicy, options.onPermissionAsk, agentPolicyRules, root);
|
|
45551
45818
|
registry4.register(withPerm(safeReadFile));
|
|
45552
45819
|
registry4.register(withPerm(safeGrepContent));
|
|
45553
45820
|
registry4.register(withPerm(safeListFiles));
|
|
@@ -45681,6 +45948,10 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
45681
45948
|
root,
|
|
45682
45949
|
audit,
|
|
45683
45950
|
sessionId: sessionId2,
|
|
45951
|
+
// P0.4 capability inheritance: tentacles intersect THIS
|
|
45952
|
+
// registry's own policy (permPolicy above) — they can never
|
|
45953
|
+
// exceed it.
|
|
45954
|
+
parentPolicy: permPolicy,
|
|
45684
45955
|
...options.subAgentProvider ? { provider: options.subAgentProvider } : {},
|
|
45685
45956
|
...options.subAgentModel ? { model: options.subAgentModel } : {}
|
|
45686
45957
|
}),
|
|
@@ -45758,15 +46029,30 @@ function taskAgentToProfile(agent) {
|
|
|
45758
46029
|
return "explore";
|
|
45759
46030
|
}
|
|
45760
46031
|
function createKrakenSubAgentContextFactory(opts) {
|
|
45761
|
-
const { root, audit, sessionId: sessionId2, provider: providerOverride, model: modelOverride } = opts;
|
|
46032
|
+
const { root, audit, sessionId: sessionId2, provider: providerOverride, model: modelOverride, parentPolicy } = opts;
|
|
45762
46033
|
return async ({ agent, cwd: subCwd }) => {
|
|
45763
46034
|
const cfg = providerOverride ? await providerConfigFor(providerOverride) : await providerFromEnv();
|
|
45764
46035
|
if (!cfg) return null;
|
|
45765
|
-
const { resolveKrakenSubModel: resolveKrakenSubModel2 } = await Promise.resolve().then(() => (init_krakenModel(), krakenModel_exports));
|
|
45766
|
-
const
|
|
45767
|
-
|
|
46036
|
+
const { resolveKrakenSubModel: resolveKrakenSubModel2, parseQualifiedModelRef: parseQualifiedModelRef2 } = await Promise.resolve().then(() => (init_krakenModel(), krakenModel_exports));
|
|
46037
|
+
const resolvedModel = resolveKrakenSubModel2(agent, modelOverride || cfg.model);
|
|
46038
|
+
let effCfg = cfg;
|
|
46039
|
+
let model = resolvedModel;
|
|
46040
|
+
const ref = parseQualifiedModelRef2(resolvedModel);
|
|
46041
|
+
if (ref) {
|
|
46042
|
+
const cross = ref.provider === cfg.providerId ? cfg : await providerConfigFor(ref.provider);
|
|
46043
|
+
if (cross) {
|
|
46044
|
+
effCfg = cross;
|
|
46045
|
+
model = ref.model;
|
|
46046
|
+
}
|
|
46047
|
+
}
|
|
46048
|
+
const subCfg = { ...effCfg, model };
|
|
45768
46049
|
const subProfile = taskAgentToProfile(agent);
|
|
45769
46050
|
const subRoot = subCwd || root;
|
|
46051
|
+
const agentPolicyForSubProfile = defaultPermissionPolicy({ auto: true });
|
|
46052
|
+
const effectiveSubPolicy = intersectPermissionPolicy(
|
|
46053
|
+
parentPolicy ?? agentPolicyForSubProfile,
|
|
46054
|
+
agentPolicyForSubProfile
|
|
46055
|
+
);
|
|
45770
46056
|
const { registry: subRegistry } = createBuiltinToolRegistry({
|
|
45771
46057
|
root: subRoot,
|
|
45772
46058
|
audit,
|
|
@@ -45776,7 +46062,9 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
45776
46062
|
enableSkill: agent === "general",
|
|
45777
46063
|
diagnostics: false,
|
|
45778
46064
|
lspProvider: null,
|
|
45779
|
-
permissionPolicy:
|
|
46065
|
+
permissionPolicy: effectiveSubPolicy,
|
|
46066
|
+
// P0.5: the tentacle's agent identity drives per-agent policy rules.
|
|
46067
|
+
policyAgent: agent
|
|
45780
46068
|
});
|
|
45781
46069
|
return {
|
|
45782
46070
|
providerStream: buildProviderStream(subCfg),
|
|
@@ -45793,7 +46081,7 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
45793
46081
|
};
|
|
45794
46082
|
};
|
|
45795
46083
|
}
|
|
45796
|
-
function wrapWithPermissions(original, policy, onAsk) {
|
|
46084
|
+
function wrapWithPermissions(original, policy, onAsk, agentRules, root) {
|
|
45797
46085
|
const required2 = original.permissions ?? [];
|
|
45798
46086
|
const decisionProbe = resolveToolPermission(original.name, required2, policy);
|
|
45799
46087
|
if (decisionProbe.action === "allow" && !required2.includes("write") && !required2.includes("execute")) {
|
|
@@ -45802,13 +46090,21 @@ function wrapWithPermissions(original, policy, onAsk) {
|
|
|
45802
46090
|
...original,
|
|
45803
46091
|
execute: async (input, ctx) => {
|
|
45804
46092
|
const decision = resolveToolPermission(original.name, required2, policy);
|
|
45805
|
-
|
|
45806
|
-
|
|
45807
|
-
|
|
45808
|
-
|
|
46093
|
+
const rule = agentRules ? matchAgentPolicyRule(
|
|
46094
|
+
agentRules,
|
|
46095
|
+
required2,
|
|
46096
|
+
input ?? {},
|
|
46097
|
+
root ?? process.cwd()
|
|
46098
|
+
) : null;
|
|
46099
|
+
const action = mergeRuleEffect(decision.action, rule);
|
|
46100
|
+
const rulePrefix = rule ? `[policy] rule '${rule.match}'${rule.reason ? ` \u2014 ${rule.reason}` : ""}` : "";
|
|
46101
|
+
if (action === "deny") {
|
|
46102
|
+
return typedErr(`[permission] ${rulePrefix || decision.reason}`);
|
|
46103
|
+
}
|
|
46104
|
+
if (action === "ask") {
|
|
45809
46105
|
if (!onAsk) {
|
|
45810
46106
|
return typedErr(
|
|
45811
|
-
`[permission] ${decision.reason} No interactive approval available (set ZELARI_AUTO=1 to auto-allow, or configure onPermissionAsk).`
|
|
46107
|
+
`[permission] ${rulePrefix ? `${rulePrefix} ` : ""}${decision.reason} No interactive approval available (set ZELARI_AUTO=1 to auto-allow, or configure onPermissionAsk).`
|
|
45812
46108
|
);
|
|
45813
46109
|
}
|
|
45814
46110
|
try {
|
|
@@ -46024,6 +46320,7 @@ var init_toolRegistry = __esm({
|
|
|
46024
46320
|
init_providerConfig();
|
|
46025
46321
|
init_toolPermissions();
|
|
46026
46322
|
init_lifecycleHooks();
|
|
46323
|
+
init_policyEngine();
|
|
46027
46324
|
init_toolResultCache();
|
|
46028
46325
|
init_toolTypes();
|
|
46029
46326
|
init_skills2();
|
|
@@ -46044,7 +46341,7 @@ var init_toolRegistry = __esm({
|
|
|
46044
46341
|
|
|
46045
46342
|
// src/cli/metrics.ts
|
|
46046
46343
|
import { promises as fs20, existsSync as existsSync25, statSync as statSync4, renameSync as renameSync3, appendFileSync as appendFileSync3, mkdirSync as mkdirSync14 } from "node:fs";
|
|
46047
|
-
import
|
|
46344
|
+
import path42 from "node:path";
|
|
46048
46345
|
import os9 from "node:os";
|
|
46049
46346
|
async function readMetrics(file2) {
|
|
46050
46347
|
let raw = "";
|
|
@@ -46093,8 +46390,8 @@ var init_metrics3 = __esm({
|
|
|
46093
46390
|
file;
|
|
46094
46391
|
writeQueue = Promise.resolve();
|
|
46095
46392
|
constructor(file2) {
|
|
46096
|
-
this.file = file2 ?? process.env.ANATHEMA_METRICS_FILE ??
|
|
46097
|
-
mkdirSync14(
|
|
46393
|
+
this.file = file2 ?? process.env.ANATHEMA_METRICS_FILE ?? path42.join(os9.homedir(), ".tmp", "zelari-code", "metrics.jsonl");
|
|
46394
|
+
mkdirSync14(path42.dirname(this.file), { recursive: true });
|
|
46098
46395
|
}
|
|
46099
46396
|
/** Metrics file path — doctor/summary readers use this. */
|
|
46100
46397
|
get filePath() {
|
|
@@ -46226,12 +46523,12 @@ Current policy: **lead only**.
|
|
|
46226
46523
|
// src/cli/state/fileStateStore.ts
|
|
46227
46524
|
import { createHash as createHash15, randomUUID as randomUUID3 } from "node:crypto";
|
|
46228
46525
|
import { promises as fs21 } from "node:fs";
|
|
46229
|
-
import * as
|
|
46526
|
+
import * as path45 from "node:path";
|
|
46230
46527
|
function shortId() {
|
|
46231
46528
|
return randomUUID3().replace(/-/g, "").slice(0, 12);
|
|
46232
46529
|
}
|
|
46233
46530
|
async function writeJsonAtomic(filePath, data) {
|
|
46234
|
-
await fs21.mkdir(
|
|
46531
|
+
await fs21.mkdir(path45.dirname(filePath), { recursive: true });
|
|
46235
46532
|
const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
46236
46533
|
await fs21.writeFile(tmp, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
46237
46534
|
await fs21.rename(tmp, filePath);
|
|
@@ -46292,11 +46589,11 @@ var init_fileStateStore = __esm({
|
|
|
46292
46589
|
indexPath = "";
|
|
46293
46590
|
async init(projectRoot) {
|
|
46294
46591
|
this.root = projectRoot;
|
|
46295
|
-
this.stateDir =
|
|
46296
|
-
this.commitsDir =
|
|
46297
|
-
this.artifactsDir =
|
|
46298
|
-
this.headPath =
|
|
46299
|
-
this.indexPath =
|
|
46592
|
+
this.stateDir = path45.join(projectRoot, ".zelari", "state");
|
|
46593
|
+
this.commitsDir = path45.join(this.stateDir, "commits");
|
|
46594
|
+
this.artifactsDir = path45.join(this.stateDir, "artifacts");
|
|
46595
|
+
this.headPath = path45.join(this.stateDir, "HEAD.json");
|
|
46596
|
+
this.indexPath = path45.join(this.stateDir, "index.jsonl");
|
|
46300
46597
|
await fs21.mkdir(this.commitsDir, { recursive: true });
|
|
46301
46598
|
await fs21.mkdir(this.artifactsDir, { recursive: true });
|
|
46302
46599
|
}
|
|
@@ -46309,13 +46606,13 @@ var init_fileStateStore = __esm({
|
|
|
46309
46606
|
const discoveries = input.discoveries ?? [];
|
|
46310
46607
|
const parent = await this.head();
|
|
46311
46608
|
const id3 = shortId();
|
|
46312
|
-
const artifactRel =
|
|
46313
|
-
const artifactAbs =
|
|
46609
|
+
const artifactRel = path45.join("artifacts", id3);
|
|
46610
|
+
const artifactAbs = path45.join(this.artifactsDir, id3);
|
|
46314
46611
|
await fs21.mkdir(artifactAbs, { recursive: true });
|
|
46315
46612
|
const summary = defaultSummary(input, discoveries);
|
|
46316
|
-
await fs21.writeFile(
|
|
46317
|
-
await writeJsonAtomic(
|
|
46318
|
-
await writeJsonAtomic(
|
|
46613
|
+
await fs21.writeFile(path45.join(artifactAbs, "summary.md"), summary + "\n", "utf8");
|
|
46614
|
+
await writeJsonAtomic(path45.join(artifactAbs, "discoveries.json"), discoveries);
|
|
46615
|
+
await writeJsonAtomic(path45.join(artifactAbs, "verification.json"), input.verification);
|
|
46319
46616
|
const meta3 = {
|
|
46320
46617
|
id: id3,
|
|
46321
46618
|
parentId: parent?.id ?? null,
|
|
@@ -46327,14 +46624,14 @@ var init_fileStateStore = __esm({
|
|
|
46327
46624
|
workspaceCheckpointId: input.workspaceCheckpointId,
|
|
46328
46625
|
verification: {
|
|
46329
46626
|
...input.verification,
|
|
46330
|
-
reportPath: input.verification.reportPath ??
|
|
46627
|
+
reportPath: input.verification.reportPath ?? path45.join(".zelari", "state", artifactRel, "verification.json").replace(/\\/g, "/")
|
|
46331
46628
|
},
|
|
46332
46629
|
changedPaths: input.changedPaths ?? [],
|
|
46333
46630
|
stablePromptHash: input.stablePromptHash,
|
|
46334
46631
|
discoveryCount: discoveries.length,
|
|
46335
46632
|
artifactDir: artifactRel.replace(/\\/g, "/")
|
|
46336
46633
|
};
|
|
46337
|
-
await writeJsonAtomic(
|
|
46634
|
+
await writeJsonAtomic(path45.join(this.commitsDir, `${id3}.json`), meta3);
|
|
46338
46635
|
await writeJsonAtomic(this.headPath, { id: id3, updatedAt: meta3.createdAt });
|
|
46339
46636
|
await fs21.appendFile(this.indexPath, JSON.stringify({ id: id3, createdAt: meta3.createdAt, label: meta3.label }) + "\n", "utf8");
|
|
46340
46637
|
return stripStored(meta3);
|
|
@@ -46345,7 +46642,7 @@ var init_fileStateStore = __esm({
|
|
|
46345
46642
|
return this.get(head.id);
|
|
46346
46643
|
}
|
|
46347
46644
|
async get(id3) {
|
|
46348
|
-
const stored = await readJsonFile(
|
|
46645
|
+
const stored = await readJsonFile(path45.join(this.commitsDir, `${id3}.json`));
|
|
46349
46646
|
return stored ? stripStored(stored) : null;
|
|
46350
46647
|
}
|
|
46351
46648
|
async list(limit = 20) {
|
|
@@ -46384,9 +46681,9 @@ var init_fileStateStore = __esm({
|
|
|
46384
46681
|
async loadDiscoveries(id3) {
|
|
46385
46682
|
const meta3 = id3 ? await this.get(id3) : await this.head();
|
|
46386
46683
|
if (!meta3) return [];
|
|
46387
|
-
const stored = await readJsonFile(
|
|
46684
|
+
const stored = await readJsonFile(path45.join(this.commitsDir, `${meta3.id}.json`));
|
|
46388
46685
|
if (!stored?.artifactDir) return [];
|
|
46389
|
-
const discPath =
|
|
46686
|
+
const discPath = path45.join(this.stateDir, stored.artifactDir, "discoveries.json");
|
|
46390
46687
|
return await readJsonFile(discPath) ?? [];
|
|
46391
46688
|
}
|
|
46392
46689
|
async materializeContext(id3, maxChars = DEFAULT_MATERIALIZE_CHARS) {
|
|
@@ -47337,7 +47634,7 @@ var init_mode = __esm({
|
|
|
47337
47634
|
});
|
|
47338
47635
|
|
|
47339
47636
|
// src/cli/headless.ts
|
|
47340
|
-
import { readFileSync as
|
|
47637
|
+
import { readFileSync as readFileSync23 } from "node:fs";
|
|
47341
47638
|
function defaultProfileForMode(mode) {
|
|
47342
47639
|
switch (mode) {
|
|
47343
47640
|
case "council":
|
|
@@ -47358,6 +47655,7 @@ function parseHeadlessFlags(argv) {
|
|
|
47358
47655
|
let phase2 = "build";
|
|
47359
47656
|
let modeExplicit = false;
|
|
47360
47657
|
let councilFlag = false;
|
|
47658
|
+
let sawModeAuto = false;
|
|
47361
47659
|
let provider;
|
|
47362
47660
|
let model;
|
|
47363
47661
|
let history2;
|
|
@@ -47392,7 +47690,7 @@ function parseHeadlessFlags(argv) {
|
|
|
47392
47690
|
const next = argv[i + 1];
|
|
47393
47691
|
if (next) {
|
|
47394
47692
|
try {
|
|
47395
|
-
const fromFile =
|
|
47693
|
+
const fromFile = readFileSync23(next, "utf-8");
|
|
47396
47694
|
if (fromFile.trim()) task = fromFile;
|
|
47397
47695
|
} catch {
|
|
47398
47696
|
}
|
|
@@ -47402,11 +47700,17 @@ function parseHeadlessFlags(argv) {
|
|
|
47402
47700
|
councilFlag = true;
|
|
47403
47701
|
} else if (arg === "--mode") {
|
|
47404
47702
|
const next = argv[i + 1];
|
|
47703
|
+
if (next !== void 0 && next.trim().toLowerCase() === "auto") {
|
|
47704
|
+
sawModeAuto = true;
|
|
47705
|
+
modeExplicit = true;
|
|
47706
|
+
i++;
|
|
47707
|
+
continue;
|
|
47708
|
+
}
|
|
47405
47709
|
const parsed = next ? parseMode(next) : null;
|
|
47406
47710
|
if (!parsed) {
|
|
47407
47711
|
return {
|
|
47408
47712
|
options: null,
|
|
47409
|
-
error: `--mode requires 'kraken', 'council', or '
|
|
47713
|
+
error: `--mode requires 'kraken', 'council', 'zelari', or 'auto' (agent=alias), got '${next ?? "(missing)"}'`
|
|
47410
47714
|
};
|
|
47411
47715
|
}
|
|
47412
47716
|
mode = parsed;
|
|
@@ -47435,7 +47739,7 @@ function parseHeadlessFlags(argv) {
|
|
|
47435
47739
|
let raw = null;
|
|
47436
47740
|
if (arg === "--history-file") {
|
|
47437
47741
|
try {
|
|
47438
|
-
raw =
|
|
47742
|
+
raw = readFileSync23(next, "utf-8");
|
|
47439
47743
|
} catch {
|
|
47440
47744
|
raw = null;
|
|
47441
47745
|
}
|
|
@@ -47530,7 +47834,7 @@ function parseHeadlessFlags(argv) {
|
|
|
47530
47834
|
const next = argv[i + 1];
|
|
47531
47835
|
if (next) {
|
|
47532
47836
|
try {
|
|
47533
|
-
const fromFile =
|
|
47837
|
+
const fromFile = readFileSync23(next, "utf-8");
|
|
47534
47838
|
if (fromFile.trim()) krakenGraph = fromFile;
|
|
47535
47839
|
} catch {
|
|
47536
47840
|
}
|
|
@@ -47568,6 +47872,7 @@ function parseHeadlessFlags(argv) {
|
|
|
47568
47872
|
mode,
|
|
47569
47873
|
phase: phase2,
|
|
47570
47874
|
useCouncil: mode === "council",
|
|
47875
|
+
...sawModeAuto ? { orchestrationAuto: true } : {},
|
|
47571
47876
|
provider,
|
|
47572
47877
|
model,
|
|
47573
47878
|
...history2 && history2.length > 0 ? { history: history2 } : {},
|
|
@@ -48095,7 +48400,7 @@ var init_claudeProvider = __esm({
|
|
|
48095
48400
|
// src/cli/memory/legacyImport.ts
|
|
48096
48401
|
import { createHash as createHash16 } from "node:crypto";
|
|
48097
48402
|
import { promises as fs22 } from "node:fs";
|
|
48098
|
-
import * as
|
|
48403
|
+
import * as path46 from "node:path";
|
|
48099
48404
|
function sourceId(fact, line) {
|
|
48100
48405
|
return `jsonl:${fact.id ?? createHash16("sha256").update(line).digest("hex")}`;
|
|
48101
48406
|
}
|
|
@@ -48113,7 +48418,7 @@ function timestamp(value) {
|
|
|
48113
48418
|
}
|
|
48114
48419
|
async function importLegacyMemoryLog(backend, service) {
|
|
48115
48420
|
const result = { found: 0, imported: 0, skipped: 0, corrupt: 0 };
|
|
48116
|
-
const logPath =
|
|
48421
|
+
const logPath = path46.join(path46.dirname(backend.databasePath), "log.jsonl");
|
|
48117
48422
|
let raw;
|
|
48118
48423
|
try {
|
|
48119
48424
|
raw = await fs22.readFile(logPath, "utf8");
|
|
@@ -48296,7 +48601,7 @@ var init_sqliteCodec = __esm({
|
|
|
48296
48601
|
// src/cli/memory/sqliteRpc.ts
|
|
48297
48602
|
import { existsSync as existsSync27 } from "node:fs";
|
|
48298
48603
|
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
48299
|
-
import * as
|
|
48604
|
+
import * as path47 from "node:path";
|
|
48300
48605
|
import { Worker } from "node:worker_threads";
|
|
48301
48606
|
function isBusy(error51) {
|
|
48302
48607
|
const candidate = error51;
|
|
@@ -48305,10 +48610,10 @@ function isBusy(error51) {
|
|
|
48305
48610
|
);
|
|
48306
48611
|
}
|
|
48307
48612
|
function resolveWorkerUrl() {
|
|
48308
|
-
const here =
|
|
48309
|
-
const direct =
|
|
48613
|
+
const here = path47.dirname(fileURLToPath2(import.meta.url));
|
|
48614
|
+
const direct = path47.join(here, "sqliteWorker.mjs");
|
|
48310
48615
|
if (existsSync27(direct)) return pathToFileURL2(direct);
|
|
48311
|
-
return pathToFileURL2(
|
|
48616
|
+
return pathToFileURL2(path47.join(here, "memory", "sqliteWorker.mjs"));
|
|
48312
48617
|
}
|
|
48313
48618
|
var SqliteWorkerRpc;
|
|
48314
48619
|
var init_sqliteRpc = __esm({
|
|
@@ -48597,7 +48902,7 @@ WHERE NOT EXISTS (SELECT 1 FROM memory_fts f WHERE f.node_id = n.id);
|
|
|
48597
48902
|
// src/cli/memory/sqliteBackend.ts
|
|
48598
48903
|
import { createHash as createHash17, randomUUID as randomUUID4 } from "node:crypto";
|
|
48599
48904
|
import { promises as fs23 } from "node:fs";
|
|
48600
|
-
import * as
|
|
48905
|
+
import * as path48 from "node:path";
|
|
48601
48906
|
function boundedLimit(value, fallback = 50) {
|
|
48602
48907
|
return Math.max(1, Math.min(Math.floor(value ?? fallback), 1e5));
|
|
48603
48908
|
}
|
|
@@ -48659,16 +48964,16 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
48659
48964
|
try {
|
|
48660
48965
|
resolved = await fs23.realpath(projectRoot);
|
|
48661
48966
|
} catch {
|
|
48662
|
-
resolved =
|
|
48967
|
+
resolved = path48.resolve(projectRoot);
|
|
48663
48968
|
}
|
|
48664
48969
|
if (this.initialized && resolved === this.projectRoot) return;
|
|
48665
48970
|
if (this.initialized) await this.close();
|
|
48666
48971
|
const filename = this.options.filename ?? "memory.db";
|
|
48667
|
-
if (
|
|
48972
|
+
if (path48.basename(filename) !== filename || filename === "." || filename === "..") {
|
|
48668
48973
|
throw new Error("SQLite memory filename must not contain a path.");
|
|
48669
48974
|
}
|
|
48670
|
-
const zelariDirectory =
|
|
48671
|
-
const directory =
|
|
48975
|
+
const zelariDirectory = path48.join(resolved, ".zelari");
|
|
48976
|
+
const directory = path48.join(zelariDirectory, "memory");
|
|
48672
48977
|
for (const candidate of [zelariDirectory, directory]) {
|
|
48673
48978
|
let stat2;
|
|
48674
48979
|
try {
|
|
@@ -48687,12 +48992,12 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
48687
48992
|
}
|
|
48688
48993
|
}
|
|
48689
48994
|
const canonicalDirectory = await fs23.realpath(directory);
|
|
48690
|
-
const relativeDirectory =
|
|
48691
|
-
if (relativeDirectory.startsWith("..") ||
|
|
48995
|
+
const relativeDirectory = path48.relative(resolved, canonicalDirectory);
|
|
48996
|
+
if (relativeDirectory.startsWith("..") || path48.isAbsolute(relativeDirectory)) {
|
|
48692
48997
|
throw new Error("SQLite memory directory resolves outside the active project.");
|
|
48693
48998
|
}
|
|
48694
48999
|
this.projectRoot = resolved;
|
|
48695
|
-
this.databasePath =
|
|
49000
|
+
this.databasePath = path48.join(canonicalDirectory, filename);
|
|
48696
49001
|
const opened = await this.rpc.open({
|
|
48697
49002
|
dbPath: this.databasePath,
|
|
48698
49003
|
schemaSql: SQLITE_MEMORY_BASE_SCHEMA,
|
|
@@ -49225,7 +49530,7 @@ __export(serviceFactory_exports, {
|
|
|
49225
49530
|
});
|
|
49226
49531
|
import { createHash as createHash18 } from "node:crypto";
|
|
49227
49532
|
import { promises as fs24 } from "node:fs";
|
|
49228
|
-
import * as
|
|
49533
|
+
import * as path49 from "node:path";
|
|
49229
49534
|
function isMemoryV2Enabled(env = process.env) {
|
|
49230
49535
|
if (env.ZELARI_MEMORY === "0") return false;
|
|
49231
49536
|
if (env.ZELARI_MEMORY_BACKEND === "file" || env.ZELARI_MEMORY_BACKEND === "jsonl") return false;
|
|
@@ -49246,7 +49551,7 @@ async function canonicalProjectId(projectRoot) {
|
|
|
49246
49551
|
try {
|
|
49247
49552
|
canonical = await fs24.realpath(projectRoot);
|
|
49248
49553
|
} catch {
|
|
49249
|
-
canonical =
|
|
49554
|
+
canonical = path49.resolve(projectRoot);
|
|
49250
49555
|
}
|
|
49251
49556
|
canonical = canonical.replace(/\\/g, "/").replace(/\/$/, "");
|
|
49252
49557
|
if (process.platform === "win32") canonical = canonical.toLocaleLowerCase("en-US");
|
|
@@ -49314,14 +49619,14 @@ var init_serviceFactory = __esm({
|
|
|
49314
49619
|
});
|
|
49315
49620
|
|
|
49316
49621
|
// src/cli/workspace/projectInstructions.ts
|
|
49317
|
-
import { existsSync as existsSync28, readFileSync as
|
|
49622
|
+
import { existsSync as existsSync28, readFileSync as readFileSync24 } from "node:fs";
|
|
49318
49623
|
import { join as join26 } from "node:path";
|
|
49319
49624
|
function loadProjectInstructions(projectRoot = process.cwd(), maxChars = MAX_CHARS) {
|
|
49320
49625
|
for (const name of CANDIDATES) {
|
|
49321
49626
|
const full = join26(projectRoot, name);
|
|
49322
49627
|
if (!existsSync28(full)) continue;
|
|
49323
49628
|
try {
|
|
49324
|
-
let raw =
|
|
49629
|
+
let raw = readFileSync24(full, "utf8");
|
|
49325
49630
|
raw = raw.replace(/\r\n/g, "\n").trim();
|
|
49326
49631
|
if (!raw) continue;
|
|
49327
49632
|
if (raw.length <= maxChars) {
|
|
@@ -49365,7 +49670,7 @@ __export(workspaceSummary_exports, {
|
|
|
49365
49670
|
buildWorkspaceSummary: () => buildWorkspaceSummary,
|
|
49366
49671
|
buildZelariReadHint: () => buildZelariReadHint
|
|
49367
49672
|
});
|
|
49368
|
-
import { existsSync as existsSync29, readFileSync as
|
|
49673
|
+
import { existsSync as existsSync29, readFileSync as readFileSync25, readdirSync as readdirSync6, statSync as statSync5 } from "node:fs";
|
|
49369
49674
|
import { join as join27, relative as relative2 } from "node:path";
|
|
49370
49675
|
function buildWorkspaceSummary(projectRoot = process.cwd(), options = {}) {
|
|
49371
49676
|
const { maxEntries = 30, maxChars = 3500, maxDeps = 24, maxScripts = 16 } = options;
|
|
@@ -49403,7 +49708,7 @@ function buildPlanSummary(projectRoot = process.cwd(), options) {
|
|
|
49403
49708
|
if (!existsSync29(planPath)) return null;
|
|
49404
49709
|
let plan;
|
|
49405
49710
|
try {
|
|
49406
|
-
plan = JSON.parse(
|
|
49711
|
+
plan = JSON.parse(readFileSync25(planPath, "utf8"));
|
|
49407
49712
|
} catch {
|
|
49408
49713
|
return null;
|
|
49409
49714
|
}
|
|
@@ -49561,7 +49866,7 @@ function readPackageJson(projectRoot) {
|
|
|
49561
49866
|
const p3 = join27(projectRoot, "package.json");
|
|
49562
49867
|
if (!existsSync29(p3)) return null;
|
|
49563
49868
|
try {
|
|
49564
|
-
return JSON.parse(
|
|
49869
|
+
return JSON.parse(readFileSync25(p3, "utf8"));
|
|
49565
49870
|
} catch {
|
|
49566
49871
|
return null;
|
|
49567
49872
|
}
|
|
@@ -49689,7 +49994,7 @@ var composeContext_exports = {};
|
|
|
49689
49994
|
__export(composeContext_exports, {
|
|
49690
49995
|
composeProjectContext: () => composeProjectContext
|
|
49691
49996
|
});
|
|
49692
|
-
import { existsSync as existsSync31, readdirSync as readdirSync7, readFileSync as
|
|
49997
|
+
import { existsSync as existsSync31, readdirSync as readdirSync7, readFileSync as readFileSync26 } from "node:fs";
|
|
49693
49998
|
import { join as join29 } from "node:path";
|
|
49694
49999
|
function cap2(text, max, label) {
|
|
49695
50000
|
if (!text || text.length <= max) return { text: text || "", truncated: false };
|
|
@@ -49830,15 +50135,15 @@ function readDurableHeadSync(projectRoot) {
|
|
|
49830
50135
|
try {
|
|
49831
50136
|
const headPath = join29(projectRoot, ".zelari", "state", "HEAD.json");
|
|
49832
50137
|
if (!existsSync31(headPath)) return "";
|
|
49833
|
-
const head = JSON.parse(
|
|
50138
|
+
const head = JSON.parse(readFileSync26(headPath, "utf8"));
|
|
49834
50139
|
if (!head?.id) return "";
|
|
49835
50140
|
const metaPath = join29(projectRoot, ".zelari", "state", "commits", `${head.id}.json`);
|
|
49836
50141
|
if (!existsSync31(metaPath)) return "";
|
|
49837
|
-
const meta3 = JSON.parse(
|
|
50142
|
+
const meta3 = JSON.parse(readFileSync26(metaPath, "utf8"));
|
|
49838
50143
|
const discPath = meta3.artifactDir ? join29(projectRoot, ".zelari", "state", meta3.artifactDir, "discoveries.json") : join29(projectRoot, ".zelari", "state", "artifacts", head.id, "discoveries.json");
|
|
49839
50144
|
let discoveries = [];
|
|
49840
50145
|
if (existsSync31(discPath)) {
|
|
49841
|
-
discoveries = JSON.parse(
|
|
50146
|
+
discoveries = JSON.parse(readFileSync26(discPath, "utf8"));
|
|
49842
50147
|
}
|
|
49843
50148
|
const reusable = discoveries.filter((d) => d.reusable !== false);
|
|
49844
50149
|
const lines = [
|
|
@@ -49871,13 +50176,13 @@ var planDetect_exports = {};
|
|
|
49871
50176
|
__export(planDetect_exports, {
|
|
49872
50177
|
hasWorkspacePlan: () => hasWorkspacePlan
|
|
49873
50178
|
});
|
|
49874
|
-
import { existsSync as existsSync32, readFileSync as
|
|
50179
|
+
import { existsSync as existsSync32, readFileSync as readFileSync27 } from "node:fs";
|
|
49875
50180
|
import { join as join30 } from "node:path";
|
|
49876
50181
|
function hasWorkspacePlan(projectRoot = process.cwd()) {
|
|
49877
50182
|
const planPath = join30(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
49878
50183
|
if (!existsSync32(planPath)) return false;
|
|
49879
50184
|
try {
|
|
49880
|
-
const parsed = JSON.parse(
|
|
50185
|
+
const parsed = JSON.parse(readFileSync27(planPath, "utf8"));
|
|
49881
50186
|
return Array.isArray(parsed.phases) && parsed.phases.length > 0;
|
|
49882
50187
|
} catch {
|
|
49883
50188
|
return false;
|
|
@@ -49939,7 +50244,7 @@ import {
|
|
|
49939
50244
|
existsSync as existsSync33,
|
|
49940
50245
|
readdirSync as readdirSync8,
|
|
49941
50246
|
writeFileSync as writeFileSync17,
|
|
49942
|
-
readFileSync as
|
|
50247
|
+
readFileSync as readFileSync28,
|
|
49943
50248
|
mkdirSync as mkdirSync15,
|
|
49944
50249
|
renameSync as renameSync4
|
|
49945
50250
|
} from "node:fs";
|
|
@@ -49960,7 +50265,7 @@ function readPlan(ctx) {
|
|
|
49960
50265
|
if (existsSync33(jsonPath)) {
|
|
49961
50266
|
try {
|
|
49962
50267
|
const parsed = JSON.parse(
|
|
49963
|
-
|
|
50268
|
+
readFileSync28(jsonPath, "utf8")
|
|
49964
50269
|
);
|
|
49965
50270
|
const { phases, tasks, milestones, ...root } = parsed;
|
|
49966
50271
|
return {
|
|
@@ -49972,8 +50277,8 @@ function readPlan(ctx) {
|
|
|
49972
50277
|
} catch {
|
|
49973
50278
|
}
|
|
49974
50279
|
}
|
|
49975
|
-
const
|
|
49976
|
-
const doc = ctx.storage.readIfExists(
|
|
50280
|
+
const path74 = workspaceFile(ctx.rootDir, "plan");
|
|
50281
|
+
const doc = ctx.storage.readIfExists(path74);
|
|
49977
50282
|
if (!doc) return { phases: [], tasks: [], milestones: [] };
|
|
49978
50283
|
const meta3 = doc.meta;
|
|
49979
50284
|
return {
|
|
@@ -50151,7 +50456,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
50151
50456
|
dueDate: input.dueDate,
|
|
50152
50457
|
targetVersion: version2
|
|
50153
50458
|
});
|
|
50154
|
-
const
|
|
50459
|
+
const path74 = join31(ctx.rootDir, "milestones", `${id3}.md`);
|
|
50155
50460
|
const meta3 = {
|
|
50156
50461
|
kind: "milestone",
|
|
50157
50462
|
id: id3,
|
|
@@ -50168,7 +50473,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
50168
50473
|
`Target version: ${version2}`,
|
|
50169
50474
|
""
|
|
50170
50475
|
].join("\n");
|
|
50171
|
-
ctx.storage.write(
|
|
50476
|
+
ctx.storage.write(path74, meta3, body);
|
|
50172
50477
|
return { id: id3, created: true };
|
|
50173
50478
|
}
|
|
50174
50479
|
function readPlanSummary(ctx) {
|
|
@@ -50372,7 +50677,7 @@ function addIdeaStub(ctx) {
|
|
|
50372
50677
|
const tags = args["tags"] ?? [];
|
|
50373
50678
|
const category = args["category"] ?? "General";
|
|
50374
50679
|
const id3 = `${nextAdrId(ctx)}-${slugify3(title)}`;
|
|
50375
|
-
const
|
|
50680
|
+
const path74 = workspaceArtifact(ctx.rootDir, "decisions", id3);
|
|
50376
50681
|
const meta3 = {
|
|
50377
50682
|
kind: "adr",
|
|
50378
50683
|
status: "proposed",
|
|
@@ -50398,7 +50703,7 @@ function addIdeaStub(ctx) {
|
|
|
50398
50703
|
...consequences.map((c) => `- ${c}`),
|
|
50399
50704
|
""
|
|
50400
50705
|
].join("\n");
|
|
50401
|
-
ctx.storage.write(
|
|
50706
|
+
ctx.storage.write(path74, meta3, body);
|
|
50402
50707
|
return `ADR ${id3} created: "${title}". Status: proposed. Promote to accepted via /update ADR or manual edit.`;
|
|
50403
50708
|
});
|
|
50404
50709
|
}
|
|
@@ -50480,14 +50785,14 @@ function createDocumentStub(ctx) {
|
|
|
50480
50785
|
ctx.storage.write(risksPath, riskMeta, content);
|
|
50481
50786
|
return `Document "${title}" created at risks.md (workspace root).`;
|
|
50482
50787
|
}
|
|
50483
|
-
const
|
|
50788
|
+
const path74 = workspaceArtifact(ctx.rootDir, "docs", slug);
|
|
50484
50789
|
const meta3 = {
|
|
50485
50790
|
kind: "doc",
|
|
50486
50791
|
id: slug,
|
|
50487
50792
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
50488
50793
|
tags
|
|
50489
50794
|
};
|
|
50490
|
-
ctx.storage.write(
|
|
50795
|
+
ctx.storage.write(path74, meta3, content);
|
|
50491
50796
|
return `Document "${title}" created at docs/${slug}.md.`;
|
|
50492
50797
|
});
|
|
50493
50798
|
}
|
|
@@ -50524,7 +50829,7 @@ function searchDocumentsStub(ctx) {
|
|
|
50524
50829
|
const results = [];
|
|
50525
50830
|
for (const file2 of files) {
|
|
50526
50831
|
if (!existsSync33(file2)) continue;
|
|
50527
|
-
const raw =
|
|
50832
|
+
const raw = readFileSync28(file2, "utf8");
|
|
50528
50833
|
const content = raw.toLowerCase();
|
|
50529
50834
|
let idx = -1;
|
|
50530
50835
|
let matchLen = 0;
|
|
@@ -50863,21 +51168,21 @@ var init_mcpClient = __esm({
|
|
|
50863
51168
|
import {
|
|
50864
51169
|
existsSync as existsSync34,
|
|
50865
51170
|
mkdirSync as mkdirSync16,
|
|
50866
|
-
readFileSync as
|
|
51171
|
+
readFileSync as readFileSync29,
|
|
50867
51172
|
writeFileSync as writeFileSync18
|
|
50868
51173
|
} from "node:fs";
|
|
50869
51174
|
import { dirname as dirname9, join as join32 } from "node:path";
|
|
50870
|
-
import { homedir as
|
|
51175
|
+
import { homedir as homedir11 } from "node:os";
|
|
50871
51176
|
function getUserMcpPath() {
|
|
50872
|
-
return join32(
|
|
51177
|
+
return join32(homedir11(), ".zelari-code", "mcp.json");
|
|
50873
51178
|
}
|
|
50874
51179
|
function getProjectMcpPath(projectRoot) {
|
|
50875
51180
|
return join32(projectRoot, ".zelari", "mcp.json");
|
|
50876
51181
|
}
|
|
50877
|
-
function readFile4(
|
|
50878
|
-
if (!existsSync34(
|
|
51182
|
+
function readFile4(path74) {
|
|
51183
|
+
if (!existsSync34(path74)) return {};
|
|
50879
51184
|
try {
|
|
50880
|
-
const parsed = JSON.parse(
|
|
51185
|
+
const parsed = JSON.parse(readFileSync29(path74, "utf8"));
|
|
50881
51186
|
const out = {};
|
|
50882
51187
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
50883
51188
|
if (!cfg || typeof cfg.command !== "string" || !cfg.command.trim()) continue;
|
|
@@ -50893,10 +51198,10 @@ function readFile4(path72) {
|
|
|
50893
51198
|
return {};
|
|
50894
51199
|
}
|
|
50895
51200
|
}
|
|
50896
|
-
function
|
|
50897
|
-
mkdirSync16(dirname9(
|
|
51201
|
+
function writeFile3(path74, servers) {
|
|
51202
|
+
mkdirSync16(dirname9(path74), { recursive: true });
|
|
50898
51203
|
const body = { mcpServers: servers };
|
|
50899
|
-
writeFileSync18(
|
|
51204
|
+
writeFileSync18(path74, `${JSON.stringify(body, null, 2)}
|
|
50900
51205
|
`, "utf8");
|
|
50901
51206
|
}
|
|
50902
51207
|
function listMcpServers(projectRoot) {
|
|
@@ -50929,9 +51234,9 @@ function upsertMcpServer(opts) {
|
|
|
50929
51234
|
if (!opts.config.command?.trim()) {
|
|
50930
51235
|
return { ok: false, error: "command is required" };
|
|
50931
51236
|
}
|
|
50932
|
-
let
|
|
51237
|
+
let path74;
|
|
50933
51238
|
if (opts.scope === "user") {
|
|
50934
|
-
|
|
51239
|
+
path74 = getUserMcpPath();
|
|
50935
51240
|
} else {
|
|
50936
51241
|
const root = opts.projectRoot?.trim();
|
|
50937
51242
|
if (!root) {
|
|
@@ -50940,30 +51245,30 @@ function upsertMcpServer(opts) {
|
|
|
50940
51245
|
error: "projectRoot required for project scope (Open Folder first)"
|
|
50941
51246
|
};
|
|
50942
51247
|
}
|
|
50943
|
-
|
|
51248
|
+
path74 = getProjectMcpPath(root);
|
|
50944
51249
|
}
|
|
50945
|
-
const current = readFile4(
|
|
51250
|
+
const current = readFile4(path74);
|
|
50946
51251
|
current[name] = {
|
|
50947
51252
|
command: opts.config.command.trim(),
|
|
50948
51253
|
args: opts.config.args,
|
|
50949
51254
|
env: opts.config.env,
|
|
50950
51255
|
enabled: opts.config.enabled !== false
|
|
50951
51256
|
};
|
|
50952
|
-
|
|
50953
|
-
return { ok: true, path:
|
|
51257
|
+
writeFile3(path74, current);
|
|
51258
|
+
return { ok: true, path: path74 };
|
|
50954
51259
|
}
|
|
50955
51260
|
function removeMcpServer(opts) {
|
|
50956
|
-
const
|
|
50957
|
-
if (!
|
|
51261
|
+
const path74 = opts.scope === "user" ? getUserMcpPath() : opts.projectRoot ? getProjectMcpPath(opts.projectRoot) : null;
|
|
51262
|
+
if (!path74) {
|
|
50958
51263
|
return { ok: false, error: "projectRoot required for project scope" };
|
|
50959
51264
|
}
|
|
50960
|
-
const current = readFile4(
|
|
51265
|
+
const current = readFile4(path74);
|
|
50961
51266
|
if (!(opts.name in current)) {
|
|
50962
|
-
return { ok: false, error: `Server "${opts.name}" not found in ${
|
|
51267
|
+
return { ok: false, error: `Server "${opts.name}" not found in ${path74}` };
|
|
50963
51268
|
}
|
|
50964
51269
|
delete current[opts.name];
|
|
50965
|
-
|
|
50966
|
-
return { ok: true, path:
|
|
51270
|
+
writeFile3(path74, current);
|
|
51271
|
+
return { ok: true, path: path74 };
|
|
50967
51272
|
}
|
|
50968
51273
|
var init_mcpConfigIo = __esm({
|
|
50969
51274
|
"src/cli/mcp/mcpConfigIo.ts"() {
|
|
@@ -51105,14 +51410,14 @@ __export(mcpManager_exports, {
|
|
|
51105
51410
|
readMcpConfig: () => readMcpConfig,
|
|
51106
51411
|
registerMcpTools: () => registerMcpTools
|
|
51107
51412
|
});
|
|
51108
|
-
import { existsSync as existsSync35, readFileSync as
|
|
51413
|
+
import { existsSync as existsSync35, readFileSync as readFileSync30 } from "node:fs";
|
|
51109
51414
|
import { join as join33 } from "node:path";
|
|
51110
|
-
import { homedir as
|
|
51415
|
+
import { homedir as homedir12 } from "node:os";
|
|
51111
51416
|
function readMcpConfig(projectRoot = process.cwd(), opts) {
|
|
51112
51417
|
const merged = {};
|
|
51113
51418
|
const paths = [];
|
|
51114
51419
|
if (process.env["ZELARI_MCP_USER"] !== "0") {
|
|
51115
|
-
paths.push(join33(
|
|
51420
|
+
paths.push(join33(homedir12(), ".zelari-code", "mcp.json"));
|
|
51116
51421
|
}
|
|
51117
51422
|
if (!opts?.skipProjectMcp) {
|
|
51118
51423
|
paths.push(join33(projectRoot, ".zelari", "mcp.json"));
|
|
@@ -51120,7 +51425,7 @@ function readMcpConfig(projectRoot = process.cwd(), opts) {
|
|
|
51120
51425
|
for (const p3 of paths) {
|
|
51121
51426
|
if (!existsSync35(p3)) continue;
|
|
51122
51427
|
try {
|
|
51123
|
-
const parsed = JSON.parse(
|
|
51428
|
+
const parsed = JSON.parse(readFileSync30(p3, "utf8"));
|
|
51124
51429
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
51125
51430
|
if (!cfg || typeof cfg.command !== "string" || cfg.command.length === 0) continue;
|
|
51126
51431
|
merged[name] = cfg;
|
|
@@ -51359,15 +51664,15 @@ __export(agentsMd_exports, {
|
|
|
51359
51664
|
serializeAgentsMd: () => serializeAgentsMd,
|
|
51360
51665
|
updateAgentsMd: () => updateAgentsMd
|
|
51361
51666
|
});
|
|
51362
|
-
import { existsSync as existsSync36, readFileSync as
|
|
51667
|
+
import { existsSync as existsSync36, readFileSync as readFileSync31, writeFileSync as writeFileSync19 } from "node:fs";
|
|
51363
51668
|
import { createHash as createHash19 } from "node:crypto";
|
|
51364
51669
|
import { join as join34 } from "node:path";
|
|
51365
51670
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
51366
51671
|
async function readPackageJson2(projectRoot) {
|
|
51367
|
-
const
|
|
51368
|
-
if (!existsSync36(
|
|
51672
|
+
const path74 = join34(projectRoot, "package.json");
|
|
51673
|
+
if (!existsSync36(path74)) return null;
|
|
51369
51674
|
try {
|
|
51370
|
-
return JSON.parse(await readFile5(
|
|
51675
|
+
return JSON.parse(await readFile5(path74, "utf8"));
|
|
51371
51676
|
} catch {
|
|
51372
51677
|
return null;
|
|
51373
51678
|
}
|
|
@@ -51417,7 +51722,7 @@ async function genConventions(ctx) {
|
|
|
51417
51722
|
const lines = [];
|
|
51418
51723
|
const claudeMd = join34(ctx.projectRoot, "CLAUDE.MD");
|
|
51419
51724
|
if (existsSync36(claudeMd)) {
|
|
51420
|
-
const content =
|
|
51725
|
+
const content = readFileSync31(claudeMd, "utf8");
|
|
51421
51726
|
const match = content.match(/## Architecture rules[\s\S]+?(?=\n## |\n*$)/);
|
|
51422
51727
|
if (match) {
|
|
51423
51728
|
lines.push('<!-- Extracted from CLAUDE.MD "Architecture rules" -->');
|
|
@@ -51449,9 +51754,9 @@ async function genBuild(ctx) {
|
|
|
51449
51754
|
].join("\n");
|
|
51450
51755
|
}
|
|
51451
51756
|
async function genOpenQuestions(ctx) {
|
|
51452
|
-
const
|
|
51453
|
-
if (!existsSync36(
|
|
51454
|
-
const content =
|
|
51757
|
+
const path74 = join34(ctx.rootDir, "risks.md");
|
|
51758
|
+
if (!existsSync36(path74)) return "_No open questions._";
|
|
51759
|
+
const content = readFileSync31(path74, "utf8");
|
|
51455
51760
|
const lines = content.split("\n");
|
|
51456
51761
|
const questions = [];
|
|
51457
51762
|
let currentTitle = "";
|
|
@@ -51527,7 +51832,7 @@ function titleCase(id3) {
|
|
|
51527
51832
|
async function updateAgentsMd(ctx, projectRoot) {
|
|
51528
51833
|
const agentsPath = join34(projectRoot, "AGENTS.MD");
|
|
51529
51834
|
if (existsSync36(agentsPath)) {
|
|
51530
|
-
const content =
|
|
51835
|
+
const content = readFileSync31(agentsPath, "utf8");
|
|
51531
51836
|
const hasAnyMarker = AUTO_SECTIONS.some((id3) => content.includes(MARKER_OPEN(id3)));
|
|
51532
51837
|
if (!hasAnyMarker) {
|
|
51533
51838
|
return {
|
|
@@ -51543,7 +51848,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
51543
51848
|
}
|
|
51544
51849
|
let manualContent = "";
|
|
51545
51850
|
if (existsSync36(agentsPath)) {
|
|
51546
|
-
const { manualBlocks } = parseAgentsMd(
|
|
51851
|
+
const { manualBlocks } = parseAgentsMd(readFileSync31(agentsPath, "utf8"));
|
|
51547
51852
|
manualContent = manualBlocks.after;
|
|
51548
51853
|
} else {
|
|
51549
51854
|
const projectName2 = projectName(projectRoot);
|
|
@@ -51559,7 +51864,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
51559
51864
|
""
|
|
51560
51865
|
].join("\n");
|
|
51561
51866
|
}
|
|
51562
|
-
const oldContent = existsSync36(agentsPath) ?
|
|
51867
|
+
const oldContent = existsSync36(agentsPath) ? readFileSync31(agentsPath, "utf8") : "";
|
|
51563
51868
|
const { sections: oldSections } = parseAgentsMd(oldContent);
|
|
51564
51869
|
const changedSections = [];
|
|
51565
51870
|
for (const id3 of AUTO_SECTIONS) {
|
|
@@ -51696,7 +52001,7 @@ var init_completeDesign = __esm({
|
|
|
51696
52001
|
});
|
|
51697
52002
|
|
|
51698
52003
|
// src/cli/workspace/planDriftCheck.ts
|
|
51699
|
-
import { existsSync as existsSync37, readFileSync as
|
|
52004
|
+
import { existsSync as existsSync37, readFileSync as readFileSync32, readdirSync as readdirSync9, statSync as statSync6, writeFileSync as writeFileSync20 } from "node:fs";
|
|
51700
52005
|
import { join as join35 } from "node:path";
|
|
51701
52006
|
function findCanonicalDoc(rootDir) {
|
|
51702
52007
|
const docsDir = join35(rootDir, "docs");
|
|
@@ -51725,9 +52030,9 @@ function versionKey(value) {
|
|
|
51725
52030
|
function firstString2(v) {
|
|
51726
52031
|
return typeof v === "string" && v.trim().length > 0 ? v : null;
|
|
51727
52032
|
}
|
|
51728
|
-
function readFileSyncSafe(
|
|
52033
|
+
function readFileSyncSafe(path74) {
|
|
51729
52034
|
try {
|
|
51730
|
-
return
|
|
52035
|
+
return readFileSync32(path74, "utf8");
|
|
51731
52036
|
} catch {
|
|
51732
52037
|
return null;
|
|
51733
52038
|
}
|
|
@@ -51742,7 +52047,7 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
51742
52047
|
}
|
|
51743
52048
|
let plan;
|
|
51744
52049
|
try {
|
|
51745
|
-
plan = JSON.parse(
|
|
52050
|
+
plan = JSON.parse(readFileSync32(planPath, "utf8"));
|
|
51746
52051
|
} catch {
|
|
51747
52052
|
return { ran: false, reason: ".zelari/plan.json corrupt" };
|
|
51748
52053
|
}
|
|
@@ -51868,7 +52173,7 @@ var init_planDriftCheck = __esm({
|
|
|
51868
52173
|
|
|
51869
52174
|
// src/cli/workspace/projectSmoke.ts
|
|
51870
52175
|
import { spawn as spawn14 } from "node:child_process";
|
|
51871
|
-
import { existsSync as existsSync38, readFileSync as
|
|
52176
|
+
import { existsSync as existsSync38, readFileSync as readFileSync33 } from "node:fs";
|
|
51872
52177
|
import { join as join36 } from "node:path";
|
|
51873
52178
|
function pickSmokeScript(scripts) {
|
|
51874
52179
|
if (!scripts) return null;
|
|
@@ -51887,7 +52192,7 @@ async function runProjectSmoke(projectRoot, timeoutMs2 = DEFAULT_TIMEOUT_MS3) {
|
|
|
51887
52192
|
}
|
|
51888
52193
|
let scripts = {};
|
|
51889
52194
|
try {
|
|
51890
|
-
const pkg = JSON.parse(
|
|
52195
|
+
const pkg = JSON.parse(readFileSync33(pkgPath, "utf8"));
|
|
51891
52196
|
scripts = pkg.scripts ?? {};
|
|
51892
52197
|
} catch {
|
|
51893
52198
|
return { ran: false, reason: "package.json unreadable (skipped)" };
|
|
@@ -51975,7 +52280,7 @@ __export(postCouncilHook_exports, {
|
|
|
51975
52280
|
runPostCouncilHook: () => runPostCouncilHook
|
|
51976
52281
|
});
|
|
51977
52282
|
import { spawn as spawn15 } from "node:child_process";
|
|
51978
|
-
import { existsSync as existsSync39, readFileSync as
|
|
52283
|
+
import { existsSync as existsSync39, readFileSync as readFileSync34 } from "node:fs";
|
|
51979
52284
|
import { join as join37 } from "node:path";
|
|
51980
52285
|
async function runCompleteDesignPostProcessor(ctx, options) {
|
|
51981
52286
|
if (options?.runMode === "implementation") {
|
|
@@ -51997,7 +52302,7 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
51997
52302
|
}
|
|
51998
52303
|
let phaseCount = 0;
|
|
51999
52304
|
try {
|
|
52000
|
-
const parsed = JSON.parse(
|
|
52305
|
+
const parsed = JSON.parse(readFileSync34(planJsonPath2, "utf8"));
|
|
52001
52306
|
phaseCount = Array.isArray(parsed.phases) ? parsed.phases.length : 0;
|
|
52002
52307
|
} catch {
|
|
52003
52308
|
return { ran: false, reason: ".zelari/plan.json corrupt" };
|
|
@@ -52190,8 +52495,8 @@ async function runPostCouncilHook(ctx, options) {
|
|
|
52190
52495
|
sources: scope.sources
|
|
52191
52496
|
} : void 0
|
|
52192
52497
|
});
|
|
52193
|
-
const
|
|
52194
|
-
completionHook = { ran: true, path:
|
|
52498
|
+
const path74 = writeCouncilCompletion(ctx.rootDir, completion);
|
|
52499
|
+
completionHook = { ran: true, path: path74, completion };
|
|
52195
52500
|
} catch (err) {
|
|
52196
52501
|
completionHook = {
|
|
52197
52502
|
ran: true,
|
|
@@ -52232,11 +52537,11 @@ __export(councilFeedback_exports, {
|
|
|
52232
52537
|
import {
|
|
52233
52538
|
promises as fs25,
|
|
52234
52539
|
existsSync as existsSync40,
|
|
52235
|
-
readFileSync as
|
|
52540
|
+
readFileSync as readFileSync35,
|
|
52236
52541
|
writeFileSync as writeFileSync21,
|
|
52237
52542
|
mkdirSync as mkdirSync17
|
|
52238
52543
|
} from "node:fs";
|
|
52239
|
-
import
|
|
52544
|
+
import path50 from "node:path";
|
|
52240
52545
|
import os10 from "node:os";
|
|
52241
52546
|
var FeedbackStore;
|
|
52242
52547
|
var init_councilFeedback = __esm({
|
|
@@ -52247,7 +52552,7 @@ var init_councilFeedback = __esm({
|
|
|
52247
52552
|
now;
|
|
52248
52553
|
entries = [];
|
|
52249
52554
|
constructor(options = {}) {
|
|
52250
|
-
this.file = options.file ?? (process.env.ANATHEMA_COUNCIL_FEEDBACK_FILE ??
|
|
52555
|
+
this.file = options.file ?? (process.env.ANATHEMA_COUNCIL_FEEDBACK_FILE ?? path50.join(os10.homedir(), ".tmp", "zelari-code", "council-feedback.json"));
|
|
52251
52556
|
this.now = options.now ?? Date.now;
|
|
52252
52557
|
this.load();
|
|
52253
52558
|
}
|
|
@@ -52342,7 +52647,7 @@ var init_councilFeedback = __esm({
|
|
|
52342
52647
|
load() {
|
|
52343
52648
|
if (!existsSync40(this.file)) return;
|
|
52344
52649
|
try {
|
|
52345
|
-
const raw =
|
|
52650
|
+
const raw = readFileSync35(this.file, "utf-8");
|
|
52346
52651
|
const parsed = JSON.parse(raw);
|
|
52347
52652
|
if (parsed && Array.isArray(parsed.entries)) {
|
|
52348
52653
|
this.entries = parsed.entries.filter(
|
|
@@ -52353,7 +52658,7 @@ var init_councilFeedback = __esm({
|
|
|
52353
52658
|
}
|
|
52354
52659
|
}
|
|
52355
52660
|
save() {
|
|
52356
|
-
mkdirSync17(
|
|
52661
|
+
mkdirSync17(path50.dirname(this.file), { recursive: true });
|
|
52357
52662
|
writeFileSync21(
|
|
52358
52663
|
this.file,
|
|
52359
52664
|
JSON.stringify({ entries: this.entries }, null, 2),
|
|
@@ -52421,7 +52726,7 @@ import { execFile as execFile3 } from "node:child_process";
|
|
|
52421
52726
|
import { promisify as promisify2 } from "node:util";
|
|
52422
52727
|
import { mkdtempSync, rmSync as rmSync2 } from "node:fs";
|
|
52423
52728
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
52424
|
-
import
|
|
52729
|
+
import path51 from "node:path";
|
|
52425
52730
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
52426
52731
|
async function git3(cwd, args, env) {
|
|
52427
52732
|
const { stdout } = await execFileAsync2("git", ["-C", cwd, ...args], {
|
|
@@ -52441,8 +52746,8 @@ async function isGitRepo(cwd) {
|
|
|
52441
52746
|
return await gitSafe(cwd, ["rev-parse", "--is-inside-work-tree"]) === "true";
|
|
52442
52747
|
}
|
|
52443
52748
|
async function withTempIndex(fn) {
|
|
52444
|
-
const dir = mkdtempSync(
|
|
52445
|
-
const indexFile =
|
|
52749
|
+
const dir = mkdtempSync(path51.join(tmpdir2(), "zelari-ckpt-"));
|
|
52750
|
+
const indexFile = path51.join(dir, "index");
|
|
52446
52751
|
try {
|
|
52447
52752
|
return await fn(indexFile);
|
|
52448
52753
|
} finally {
|
|
@@ -52533,7 +52838,7 @@ async function restoreCheckpoint(cwd, id3) {
|
|
|
52533
52838
|
const deleted = [];
|
|
52534
52839
|
for (const rel2 of added) {
|
|
52535
52840
|
try {
|
|
52536
|
-
rmSync2(
|
|
52841
|
+
rmSync2(path51.join(cwd, rel2), { force: true });
|
|
52537
52842
|
deleted.push(rel2);
|
|
52538
52843
|
} catch {
|
|
52539
52844
|
}
|
|
@@ -52634,7 +52939,7 @@ __export(fileBackend_exports, {
|
|
|
52634
52939
|
});
|
|
52635
52940
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
52636
52941
|
import { promises as fs26 } from "node:fs";
|
|
52637
|
-
import * as
|
|
52942
|
+
import * as path52 from "node:path";
|
|
52638
52943
|
function tokenize(text) {
|
|
52639
52944
|
return text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 3);
|
|
52640
52945
|
}
|
|
@@ -52685,8 +52990,8 @@ var init_fileBackend = __esm({
|
|
|
52685
52990
|
logPath = "";
|
|
52686
52991
|
memoryDir = "";
|
|
52687
52992
|
async init(projectRoot) {
|
|
52688
|
-
this.memoryDir =
|
|
52689
|
-
this.logPath =
|
|
52993
|
+
this.memoryDir = path52.join(projectRoot, ".zelari", "memory");
|
|
52994
|
+
this.logPath = path52.join(this.memoryDir, "log.jsonl");
|
|
52690
52995
|
await fs26.mkdir(this.memoryDir, { recursive: true });
|
|
52691
52996
|
}
|
|
52692
52997
|
async add(content, metadata2 = {}, graph) {
|
|
@@ -52759,12 +53064,12 @@ var init_fileBackend = __esm({
|
|
|
52759
53064
|
|
|
52760
53065
|
// src/cli/traceStore.ts
|
|
52761
53066
|
import { promises as fs27 } from "node:fs";
|
|
52762
|
-
import * as
|
|
53067
|
+
import * as path53 from "node:path";
|
|
52763
53068
|
function traceDir(projectRoot) {
|
|
52764
|
-
return
|
|
53069
|
+
return path53.join(projectRoot, ".zelari", "trace");
|
|
52765
53070
|
}
|
|
52766
53071
|
function tracePath(projectRoot, missionId) {
|
|
52767
|
-
return
|
|
53072
|
+
return path53.join(traceDir(projectRoot), `${missionId}.json`);
|
|
52768
53073
|
}
|
|
52769
53074
|
async function saveTrace(projectRoot, missionId, entries) {
|
|
52770
53075
|
const dir = traceDir(projectRoot);
|
|
@@ -52801,7 +53106,7 @@ __export(zelariMission_exports, {
|
|
|
52801
53106
|
});
|
|
52802
53107
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
52803
53108
|
import { promises as fs28 } from "node:fs";
|
|
52804
|
-
import * as
|
|
53109
|
+
import * as path54 from "node:path";
|
|
52805
53110
|
function resolveMaxIterations(env = process.env) {
|
|
52806
53111
|
const raw = env.ZELARI_MISSION_MAX_ITER;
|
|
52807
53112
|
const n = raw ? Number.parseInt(raw, 10) : DEFAULT_MAX_ITER;
|
|
@@ -52844,10 +53149,10 @@ function isMissionAutoStart(env = process.env) {
|
|
|
52844
53149
|
return env.ZELARI_MISSION_AUTO === "1";
|
|
52845
53150
|
}
|
|
52846
53151
|
async function writeMissionState(projectRoot, state3) {
|
|
52847
|
-
const dir =
|
|
53152
|
+
const dir = path54.join(projectRoot, ".zelari");
|
|
52848
53153
|
await fs28.mkdir(dir, { recursive: true });
|
|
52849
53154
|
await fs28.writeFile(
|
|
52850
|
-
|
|
53155
|
+
path54.join(dir, "mission-state.json"),
|
|
52851
53156
|
JSON.stringify(state3, null, 2) + "\n",
|
|
52852
53157
|
"utf8"
|
|
52853
53158
|
);
|
|
@@ -53522,7 +53827,7 @@ function safeSocketPath(socketPath) {
|
|
|
53522
53827
|
return socketPath.trim();
|
|
53523
53828
|
}
|
|
53524
53829
|
function startPermissionBroker(socketPath, handlers, opts) {
|
|
53525
|
-
const
|
|
53830
|
+
const path74 = safeSocketPath(socketPath);
|
|
53526
53831
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
53527
53832
|
const sockets = /* @__PURE__ */ new Set();
|
|
53528
53833
|
const server = createServer2((socket) => {
|
|
@@ -53622,10 +53927,10 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
53622
53927
|
return new Promise((resolve7, reject) => {
|
|
53623
53928
|
const onError = (err) => reject(err);
|
|
53624
53929
|
server.once("error", onError);
|
|
53625
|
-
server.listen(
|
|
53930
|
+
server.listen(path74, () => {
|
|
53626
53931
|
server.removeListener("error", onError);
|
|
53627
53932
|
resolve7({
|
|
53628
|
-
socketPath:
|
|
53933
|
+
socketPath: path74,
|
|
53629
53934
|
stop: () => new Promise((res) => {
|
|
53630
53935
|
for (const s of sockets) s.destroy();
|
|
53631
53936
|
sockets.clear();
|
|
@@ -53636,7 +53941,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
53636
53941
|
if (done) return;
|
|
53637
53942
|
done = true;
|
|
53638
53943
|
if (process.platform !== "win32") {
|
|
53639
|
-
unlink(
|
|
53944
|
+
unlink(path74, () => res());
|
|
53640
53945
|
} else {
|
|
53641
53946
|
res();
|
|
53642
53947
|
}
|
|
@@ -53649,11 +53954,11 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
53649
53954
|
});
|
|
53650
53955
|
}
|
|
53651
53956
|
function requestBrokerAsk(socketPath, ask, opts) {
|
|
53652
|
-
const
|
|
53957
|
+
const path74 = safeSocketPath(socketPath);
|
|
53653
53958
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
53654
53959
|
const connectTimeoutMs = opts?.connectTimeoutMs ?? PERMISSION_BROKER_DEFAULT_CONNECT_TIMEOUT_MS;
|
|
53655
53960
|
return new Promise((resolve7, reject) => {
|
|
53656
|
-
const socket = connect(
|
|
53961
|
+
const socket = connect(path74);
|
|
53657
53962
|
let buffer = "";
|
|
53658
53963
|
let settled = false;
|
|
53659
53964
|
const settle = (fn) => {
|
|
@@ -53668,7 +53973,7 @@ function requestBrokerAsk(socketPath, ask, opts) {
|
|
|
53668
53973
|
settle(
|
|
53669
53974
|
() => reject(
|
|
53670
53975
|
new Error(
|
|
53671
|
-
`permission broker unavailable at "${
|
|
53976
|
+
`permission broker unavailable at "${path74}" (connect timed out after ${connectTimeoutMs}ms)`
|
|
53672
53977
|
)
|
|
53673
53978
|
)
|
|
53674
53979
|
);
|
|
@@ -54060,7 +54365,17 @@ function stripTrailingCommas(s) {
|
|
|
54060
54365
|
return out;
|
|
54061
54366
|
}
|
|
54062
54367
|
async function resolveLlm(opts) {
|
|
54063
|
-
|
|
54368
|
+
let active = opts.provider?.trim() || getProviderConfig().activeProviderId;
|
|
54369
|
+
const parent = opts.model?.trim() || getModelForProvider(active) || process.env.ZELARI_MODEL || "";
|
|
54370
|
+
let model = resolveKrakenPlannerModel(parent);
|
|
54371
|
+
const ref = parseQualifiedModelRef(model);
|
|
54372
|
+
if (ref) {
|
|
54373
|
+
const crossKey = await resolveApiKeyWithMeta(ref.provider);
|
|
54374
|
+
if (crossKey?.apiKey && resolveBaseUrl(ref.provider)) {
|
|
54375
|
+
active = ref.provider;
|
|
54376
|
+
}
|
|
54377
|
+
if (active === ref.provider) model = ref.model;
|
|
54378
|
+
}
|
|
54064
54379
|
const meta3 = await resolveApiKeyWithMeta(active);
|
|
54065
54380
|
if (!meta3?.apiKey) {
|
|
54066
54381
|
throw new Error(`No API key for provider '${active}'. Save a key in Settings \u2192 Provider.`);
|
|
@@ -54069,8 +54384,6 @@ async function resolveLlm(opts) {
|
|
|
54069
54384
|
if (!baseUrl) {
|
|
54070
54385
|
throw new Error(`No base URL for provider '${active}'. Set a custom endpoint in Settings.`);
|
|
54071
54386
|
}
|
|
54072
|
-
const parent = opts.model?.trim() || getModelForProvider(active) || process.env.ZELARI_MODEL || "";
|
|
54073
|
-
const model = resolveKrakenPlannerModel(parent);
|
|
54074
54387
|
if (!model) {
|
|
54075
54388
|
throw new Error(`No model selected for provider '${active}'`);
|
|
54076
54389
|
}
|
|
@@ -54403,9 +54716,9 @@ __export(graphMemory_exports, {
|
|
|
54403
54716
|
toGraphSnapshot: () => toGraphSnapshot
|
|
54404
54717
|
});
|
|
54405
54718
|
import { promises as fs31 } from "node:fs";
|
|
54406
|
-
import
|
|
54719
|
+
import path58 from "node:path";
|
|
54407
54720
|
function snapshotPath(cwd) {
|
|
54408
|
-
return
|
|
54721
|
+
return path58.join(cwd, SNAPSHOT_DIR, SNAPSHOT_FILE);
|
|
54409
54722
|
}
|
|
54410
54723
|
function toGraphSnapshot(graph, opts) {
|
|
54411
54724
|
const unresolved = (opts.unresolvedFindings ?? []).map((u) => ({
|
|
@@ -54432,7 +54745,7 @@ async function saveGraphSnapshot(cwd, snapshot) {
|
|
|
54432
54745
|
try {
|
|
54433
54746
|
await fs31.access(cwd);
|
|
54434
54747
|
const file2 = snapshotPath(cwd);
|
|
54435
|
-
await fs31.mkdir(
|
|
54748
|
+
await fs31.mkdir(path58.dirname(file2), { recursive: true });
|
|
54436
54749
|
await fs31.writeFile(file2, JSON.stringify(snapshot, null, 2) + "\n", "utf8");
|
|
54437
54750
|
} catch {
|
|
54438
54751
|
}
|
|
@@ -54499,7 +54812,7 @@ var SNAPSHOT_DIR, SNAPSHOT_FILE, MAX_SNAPSHOT_FINDINGS_CHARS;
|
|
|
54499
54812
|
var init_graphMemory = __esm({
|
|
54500
54813
|
"src/cli/kraken/graphMemory.ts"() {
|
|
54501
54814
|
"use strict";
|
|
54502
|
-
SNAPSHOT_DIR =
|
|
54815
|
+
SNAPSHOT_DIR = path58.join(".zelari", "kraken");
|
|
54503
54816
|
SNAPSHOT_FILE = "last-graph.json";
|
|
54504
54817
|
MAX_SNAPSHOT_FINDINGS_CHARS = 400;
|
|
54505
54818
|
}
|
|
@@ -54515,14 +54828,14 @@ var init_tentacle = __esm({
|
|
|
54515
54828
|
|
|
54516
54829
|
// src/cli/kraken/workbench.ts
|
|
54517
54830
|
import { promises as fs32 } from "node:fs";
|
|
54518
|
-
import
|
|
54831
|
+
import path59 from "node:path";
|
|
54519
54832
|
function isWorkbenchEnabled(env = process.env) {
|
|
54520
54833
|
const v = (env.ZELARI_KRAKEN_WORKBENCH ?? "1").trim().toLowerCase();
|
|
54521
54834
|
if (v === "0" || v === "false" || v === "no" || v === "off") return false;
|
|
54522
54835
|
return true;
|
|
54523
54836
|
}
|
|
54524
54837
|
function workbenchPath(cwd, graphId) {
|
|
54525
|
-
return
|
|
54838
|
+
return path59.join(cwd, ".zelari", "radio", `workbench-${graphId}.md`);
|
|
54526
54839
|
}
|
|
54527
54840
|
function countByStatus2(nodes) {
|
|
54528
54841
|
const out = { pending: 0, running: 0, done: 0, error: 0, skipped: 0 };
|
|
@@ -54685,7 +54998,7 @@ var init_workbench = __esm({
|
|
|
54685
54998
|
if (!this.enabled) return null;
|
|
54686
54999
|
if (!this.dirty && this.lastWrite) return this.lastWrite;
|
|
54687
55000
|
const out = workbenchPath(this.cwd, this.graphId);
|
|
54688
|
-
await fs32.mkdir(
|
|
55001
|
+
await fs32.mkdir(path59.dirname(out), { recursive: true });
|
|
54689
55002
|
const body = this.render();
|
|
54690
55003
|
const tmp = `${out}.${process.pid}.${Date.now()}.tmp`;
|
|
54691
55004
|
await fs32.writeFile(tmp, body, "utf8");
|
|
@@ -54882,7 +55195,7 @@ __export(executor_exports, {
|
|
|
54882
55195
|
thoroughnessForKind: () => thoroughnessForKind
|
|
54883
55196
|
});
|
|
54884
55197
|
import { existsSync as existsSync41 } from "node:fs";
|
|
54885
|
-
import
|
|
55198
|
+
import path60 from "node:path";
|
|
54886
55199
|
function resolveMaxParallel(env = process.env) {
|
|
54887
55200
|
const raw = env.ZELARI_KRAKEN_MAX_PARALLEL;
|
|
54888
55201
|
if (raw === void 0 || raw === "") return DEFAULT_MAX_PARALLEL;
|
|
@@ -54940,7 +55253,7 @@ function isWorldModelGateEnabled(cwd, env = process.env, checksExists = defaultC
|
|
|
54940
55253
|
}
|
|
54941
55254
|
function defaultChecksExists(cwd) {
|
|
54942
55255
|
try {
|
|
54943
|
-
return existsSync41(
|
|
55256
|
+
return existsSync41(path60.join(cwd, ".zelari", "world", "checks.json"));
|
|
54944
55257
|
} catch {
|
|
54945
55258
|
return false;
|
|
54946
55259
|
}
|
|
@@ -56336,17 +56649,17 @@ var init_prereqChecks = __esm({
|
|
|
56336
56649
|
});
|
|
56337
56650
|
|
|
56338
56651
|
// src/cli/plugins/prefs.ts
|
|
56339
|
-
import { existsSync as existsSync43, readFileSync as
|
|
56340
|
-
import
|
|
56652
|
+
import { existsSync as existsSync43, readFileSync as readFileSync36, writeFileSync as writeFileSync22, mkdirSync as mkdirSync18 } from "node:fs";
|
|
56653
|
+
import path63 from "node:path";
|
|
56341
56654
|
import os11 from "node:os";
|
|
56342
56655
|
function getPluginPrefsPath() {
|
|
56343
|
-
return process.env.ZELARI_PLUGINS_PREFS_FILE ??
|
|
56656
|
+
return process.env.ZELARI_PLUGINS_PREFS_FILE ?? path63.join(os11.homedir(), ".tmp", "zelari-code", "plugins.json");
|
|
56344
56657
|
}
|
|
56345
56658
|
function getPluginPrefs() {
|
|
56346
56659
|
const file2 = getPluginPrefsPath();
|
|
56347
56660
|
try {
|
|
56348
56661
|
if (!existsSync43(file2)) return { ...DEFAULTS2, dontAskAgain: {} };
|
|
56349
|
-
const raw =
|
|
56662
|
+
const raw = readFileSync36(file2, "utf-8");
|
|
56350
56663
|
const parsed = JSON.parse(raw);
|
|
56351
56664
|
if (parsed && typeof parsed === "object" && parsed.dontAskAgain && typeof parsed.dontAskAgain === "object") {
|
|
56352
56665
|
const clean = {};
|
|
@@ -56361,7 +56674,7 @@ function getPluginPrefs() {
|
|
|
56361
56674
|
}
|
|
56362
56675
|
function writePluginPrefs(prefs) {
|
|
56363
56676
|
const file2 = getPluginPrefsPath();
|
|
56364
|
-
mkdirSync18(
|
|
56677
|
+
mkdirSync18(path63.dirname(file2), { recursive: true });
|
|
56365
56678
|
writeFileSync22(file2, JSON.stringify(prefs, null, 2), {
|
|
56366
56679
|
encoding: "utf-8",
|
|
56367
56680
|
mode: 384
|
|
@@ -56398,7 +56711,7 @@ __export(registry_exports, {
|
|
|
56398
56711
|
isBinaryOnPath: () => isBinaryOnPath
|
|
56399
56712
|
});
|
|
56400
56713
|
import { existsSync as existsSync44 } from "node:fs";
|
|
56401
|
-
import
|
|
56714
|
+
import path64 from "node:path";
|
|
56402
56715
|
function detectLocalBin(bin) {
|
|
56403
56716
|
return (cwd) => {
|
|
56404
56717
|
try {
|
|
@@ -56416,7 +56729,7 @@ function isBinaryOnPath(bin, opts = {}) {
|
|
|
56416
56729
|
const platform = opts.platform ?? process.platform;
|
|
56417
56730
|
const exists = opts.exists ?? existsSync44;
|
|
56418
56731
|
const pathEnv = opts.pathEnv ?? process.env.PATH ?? "";
|
|
56419
|
-
const pathMod = platform === "win32" ?
|
|
56732
|
+
const pathMod = platform === "win32" ? path64.win32 : path64.posix;
|
|
56420
56733
|
const sep4 = platform === "win32" ? ";" : ":";
|
|
56421
56734
|
const dirs = pathEnv.split(sep4).filter((d) => d.length > 0);
|
|
56422
56735
|
const candidates = [bin];
|
|
@@ -57148,7 +57461,7 @@ __export(atMentions_exports, {
|
|
|
57148
57461
|
extractAtMentions: () => extractAtMentions,
|
|
57149
57462
|
hasAtMentions: () => hasAtMentions
|
|
57150
57463
|
});
|
|
57151
|
-
import { existsSync as existsSync47, readFileSync as
|
|
57464
|
+
import { existsSync as existsSync47, readFileSync as readFileSync38, statSync as statSync9 } from "node:fs";
|
|
57152
57465
|
import { basename as basename4, isAbsolute as isAbsolute4, relative as relative5, resolve as resolve5, sep as sep2 } from "node:path";
|
|
57153
57466
|
function isImagePath(abs) {
|
|
57154
57467
|
const ext = abs.split(".").pop()?.toLowerCase() ?? "";
|
|
@@ -57254,7 +57567,7 @@ function resolveMention(token, cwd) {
|
|
|
57254
57567
|
note: `image too large (${Math.round(st.size / 1024)} KB) \u2014 path only`
|
|
57255
57568
|
};
|
|
57256
57569
|
}
|
|
57257
|
-
const dataBase64 =
|
|
57570
|
+
const dataBase64 = readFileSync38(abs).toString("base64");
|
|
57258
57571
|
return {
|
|
57259
57572
|
raw: token,
|
|
57260
57573
|
path: rel2,
|
|
@@ -57265,7 +57578,7 @@ function resolveMention(token, cwd) {
|
|
|
57265
57578
|
};
|
|
57266
57579
|
}
|
|
57267
57580
|
try {
|
|
57268
|
-
const buf =
|
|
57581
|
+
const buf = readFileSync38(abs);
|
|
57269
57582
|
const head = buf.subarray(0, 800).toString("utf8");
|
|
57270
57583
|
if (!isProbablyText(abs, head)) {
|
|
57271
57584
|
return {
|
|
@@ -58250,9 +58563,9 @@ __export(triggerLock_exports, {
|
|
|
58250
58563
|
releaseLock: () => releaseLock
|
|
58251
58564
|
});
|
|
58252
58565
|
import { promises as fs40 } from "node:fs";
|
|
58253
|
-
import * as
|
|
58566
|
+
import * as path69 from "node:path";
|
|
58254
58567
|
function lockPath(projectRoot) {
|
|
58255
|
-
return
|
|
58568
|
+
return path69.join(projectRoot, ".zelari", "trigger.lock");
|
|
58256
58569
|
}
|
|
58257
58570
|
function isPidAlive(pid) {
|
|
58258
58571
|
try {
|
|
@@ -58265,7 +58578,7 @@ function isPidAlive(pid) {
|
|
|
58265
58578
|
}
|
|
58266
58579
|
async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date()) {
|
|
58267
58580
|
const lp = lockPath(projectRoot);
|
|
58268
|
-
const dir =
|
|
58581
|
+
const dir = path69.dirname(lp);
|
|
58269
58582
|
await fs40.mkdir(dir, { recursive: true });
|
|
58270
58583
|
try {
|
|
58271
58584
|
const raw = await fs40.readFile(lp, "utf8");
|
|
@@ -58693,12 +59006,12 @@ import {
|
|
|
58693
59006
|
existsSync as existsSync49,
|
|
58694
59007
|
mkdirSync as mkdirSync21,
|
|
58695
59008
|
readdirSync as readdirSync10,
|
|
58696
|
-
readFileSync as
|
|
59009
|
+
readFileSync as readFileSync39,
|
|
58697
59010
|
rmSync as rmSync4,
|
|
58698
59011
|
writeFileSync as writeFileSync24
|
|
58699
59012
|
} from "node:fs";
|
|
58700
59013
|
import { dirname as dirname13, join as join45 } from "node:path";
|
|
58701
|
-
import { homedir as
|
|
59014
|
+
import { homedir as homedir13 } from "node:os";
|
|
58702
59015
|
function ensureBuiltinSkillsLoadedSync() {
|
|
58703
59016
|
if (builtinsLoaded) return;
|
|
58704
59017
|
for (const spec of BUILTIN_SKILL_MODULES) {
|
|
@@ -58709,7 +59022,7 @@ function ensureBuiltinSkillsLoadedSync() {
|
|
|
58709
59022
|
}
|
|
58710
59023
|
}
|
|
58711
59024
|
function getUserSkillsDir() {
|
|
58712
|
-
return join45(
|
|
59025
|
+
return join45(homedir13(), ".zelari-code", "skills");
|
|
58713
59026
|
}
|
|
58714
59027
|
function getProjectSkillsDir(projectRoot) {
|
|
58715
59028
|
return join45(projectRoot, ".zelari", "skills");
|
|
@@ -58775,7 +59088,7 @@ function scanSkillsDir(dir, projectRoot, seen, out) {
|
|
|
58775
59088
|
const skillPath = skillFilePath(dir, entry);
|
|
58776
59089
|
if (!existsSync49(skillPath)) continue;
|
|
58777
59090
|
try {
|
|
58778
|
-
const parsed = parseSkillMd(
|
|
59091
|
+
const parsed = parseSkillMd(readFileSync39(skillPath, "utf8"), skillPath);
|
|
58779
59092
|
if (!parsed) continue;
|
|
58780
59093
|
if (seen.has(parsed.name)) continue;
|
|
58781
59094
|
seen.add(parsed.name);
|
|
@@ -58859,7 +59172,7 @@ function upsertSkill(opts) {
|
|
|
58859
59172
|
}
|
|
58860
59173
|
dir = getProjectSkillsDir(root);
|
|
58861
59174
|
}
|
|
58862
|
-
const
|
|
59175
|
+
const path74 = skillFilePath(dir, name);
|
|
58863
59176
|
const content = serializeSkillMd({
|
|
58864
59177
|
name,
|
|
58865
59178
|
description,
|
|
@@ -58868,13 +59181,13 @@ function upsertSkill(opts) {
|
|
|
58868
59181
|
tools: opts.tools,
|
|
58869
59182
|
cost: opts.cost
|
|
58870
59183
|
});
|
|
58871
|
-
const parsed = parseSkillMd(content,
|
|
59184
|
+
const parsed = parseSkillMd(content, path74);
|
|
58872
59185
|
if (!parsed) {
|
|
58873
59186
|
return { ok: false, error: "Generated SKILL.md failed validation" };
|
|
58874
59187
|
}
|
|
58875
|
-
mkdirSync21(dirname13(
|
|
58876
|
-
writeFileSync24(
|
|
58877
|
-
return { ok: true, path:
|
|
59188
|
+
mkdirSync21(dirname13(path74), { recursive: true });
|
|
59189
|
+
writeFileSync24(path74, content, "utf8");
|
|
59190
|
+
return { ok: true, path: path74 };
|
|
58878
59191
|
}
|
|
58879
59192
|
function removeSkill(opts) {
|
|
58880
59193
|
const name = opts.name.trim().toLowerCase();
|
|
@@ -58892,8 +59205,8 @@ function removeSkill(opts) {
|
|
|
58892
59205
|
dir = getProjectSkillsDir(root);
|
|
58893
59206
|
}
|
|
58894
59207
|
const skillDir = join45(dir, name);
|
|
58895
|
-
const
|
|
58896
|
-
if (!existsSync49(
|
|
59208
|
+
const path74 = skillFilePath(dir, name);
|
|
59209
|
+
if (!existsSync49(path74) && !existsSync49(skillDir)) {
|
|
58897
59210
|
return { ok: false, error: `Skill "${name}" not found in ${dir}` };
|
|
58898
59211
|
}
|
|
58899
59212
|
try {
|
|
@@ -58904,7 +59217,7 @@ function removeSkill(opts) {
|
|
|
58904
59217
|
error: err instanceof Error ? err.message : String(err)
|
|
58905
59218
|
};
|
|
58906
59219
|
}
|
|
58907
|
-
return { ok: true, path:
|
|
59220
|
+
return { ok: true, path: path74 };
|
|
58908
59221
|
}
|
|
58909
59222
|
var NAME_RE, BUILTIN_SKILL_MODULES, builtinsLoaded;
|
|
58910
59223
|
var init_skillConfigIo = __esm({
|
|
@@ -59023,7 +59336,7 @@ var init_jsonApi = __esm({
|
|
|
59023
59336
|
});
|
|
59024
59337
|
|
|
59025
59338
|
// src/cli/memory/mcpAdapter.ts
|
|
59026
|
-
import * as
|
|
59339
|
+
import * as path71 from "node:path";
|
|
59027
59340
|
var id2, projectId, source, SearchSchema, AddSchema, LinkSchema, RetractSchema, MEMORY_MCP_TOOLS, MemoryMcpAdapter;
|
|
59028
59341
|
var init_mcpAdapter = __esm({
|
|
59029
59342
|
"src/cli/memory/mcpAdapter.ts"() {
|
|
@@ -59193,8 +59506,8 @@ var init_mcpAdapter = __esm({
|
|
|
59193
59506
|
this.takeWrite();
|
|
59194
59507
|
const externalFile = args.source?.file;
|
|
59195
59508
|
if (externalFile) {
|
|
59196
|
-
const normalized =
|
|
59197
|
-
if (
|
|
59509
|
+
const normalized = path71.normalize(externalFile);
|
|
59510
|
+
if (path71.isAbsolute(normalized) || normalized === ".." || normalized.startsWith(`..${path71.sep}`)) {
|
|
59198
59511
|
throw new Error("source.file must be project-relative and cannot escape the project");
|
|
59199
59512
|
}
|
|
59200
59513
|
}
|
|
@@ -59700,14 +60013,14 @@ var init_permissionCli = __esm({
|
|
|
59700
60013
|
import {
|
|
59701
60014
|
existsSync as existsSync50,
|
|
59702
60015
|
mkdirSync as mkdirSync22,
|
|
59703
|
-
readFileSync as
|
|
60016
|
+
readFileSync as readFileSync40,
|
|
59704
60017
|
writeFileSync as writeFileSync25
|
|
59705
60018
|
} from "node:fs";
|
|
59706
60019
|
import { join as join46 } from "node:path";
|
|
59707
|
-
import { homedir as
|
|
60020
|
+
import { homedir as homedir14 } from "node:os";
|
|
59708
60021
|
import { createHash as createHash20, randomBytes as randomBytes6, timingSafeEqual } from "node:crypto";
|
|
59709
60022
|
function getZelariHome() {
|
|
59710
|
-
return join46(
|
|
60023
|
+
return join46(homedir14(), ".zelari-code");
|
|
59711
60024
|
}
|
|
59712
60025
|
function getCompanionConfigPath() {
|
|
59713
60026
|
return join46(getZelariHome(), "companion.json");
|
|
@@ -59722,12 +60035,12 @@ function ensureHome() {
|
|
|
59722
60035
|
}
|
|
59723
60036
|
}
|
|
59724
60037
|
function loadCompanionConfig() {
|
|
59725
|
-
const
|
|
59726
|
-
if (!existsSync50(
|
|
60038
|
+
const path74 = getCompanionConfigPath();
|
|
60039
|
+
if (!existsSync50(path74)) {
|
|
59727
60040
|
return { projects: [] };
|
|
59728
60041
|
}
|
|
59729
60042
|
try {
|
|
59730
|
-
const raw = JSON.parse(
|
|
60043
|
+
const raw = JSON.parse(readFileSync40(path74, "utf8"));
|
|
59731
60044
|
const projects = Array.isArray(raw.projects) ? raw.projects.filter(
|
|
59732
60045
|
(p3) => p3 && typeof p3.path === "string" && p3.path.trim() && typeof (p3.id ?? p3.name) === "string"
|
|
59733
60046
|
).map((p3) => ({
|
|
@@ -59765,16 +60078,16 @@ function loadOrCreateToken(explicit) {
|
|
|
59765
60078
|
return { token: explicit.trim(), created: false };
|
|
59766
60079
|
}
|
|
59767
60080
|
ensureHome();
|
|
59768
|
-
const
|
|
59769
|
-
if (existsSync50(
|
|
59770
|
-
const t =
|
|
60081
|
+
const path74 = getCompanionTokenPath();
|
|
60082
|
+
if (existsSync50(path74)) {
|
|
60083
|
+
const t = readFileSync40(path74, "utf8").trim();
|
|
59771
60084
|
if (t) return { token: t, created: false };
|
|
59772
60085
|
}
|
|
59773
60086
|
const token = randomBytes6(24).toString("base64url");
|
|
59774
|
-
writeFileSync25(
|
|
60087
|
+
writeFileSync25(path74, token + "\n", "utf8");
|
|
59775
60088
|
try {
|
|
59776
60089
|
const fs42 = __require("node:fs");
|
|
59777
|
-
fs42.chmodSync?.(
|
|
60090
|
+
fs42.chmodSync?.(path74, 384);
|
|
59778
60091
|
} catch {
|
|
59779
60092
|
}
|
|
59780
60093
|
return { token, created: true };
|
|
@@ -59799,17 +60112,17 @@ function mergeProjects(cfg, extraPaths) {
|
|
|
59799
60112
|
byId.set(p3.id, p3);
|
|
59800
60113
|
}
|
|
59801
60114
|
for (const raw of extraPaths) {
|
|
59802
|
-
const
|
|
59803
|
-
if (!
|
|
59804
|
-
let id3 = slugFromPath(
|
|
60115
|
+
const path74 = raw.trim();
|
|
60116
|
+
if (!path74) continue;
|
|
60117
|
+
let id3 = slugFromPath(path74);
|
|
59805
60118
|
let n = 2;
|
|
59806
|
-
while (byId.has(id3) && byId.get(id3).path !==
|
|
59807
|
-
id3 = `${slugFromPath(
|
|
60119
|
+
while (byId.has(id3) && byId.get(id3).path !== path74) {
|
|
60120
|
+
id3 = `${slugFromPath(path74)}-${n++}`;
|
|
59808
60121
|
}
|
|
59809
60122
|
byId.set(id3, {
|
|
59810
60123
|
id: id3,
|
|
59811
|
-
name: slugFromPath(
|
|
59812
|
-
path:
|
|
60124
|
+
name: slugFromPath(path74),
|
|
60125
|
+
path: path74
|
|
59813
60126
|
});
|
|
59814
60127
|
}
|
|
59815
60128
|
return [...byId.values()];
|
|
@@ -60186,9 +60499,9 @@ async function runCompanionServe(opts = {}) {
|
|
|
60186
60499
|
return;
|
|
60187
60500
|
}
|
|
60188
60501
|
const url2 = parseUrl(req);
|
|
60189
|
-
const
|
|
60502
|
+
const path74 = url2.pathname.replace(/\/+$/, "") || "/";
|
|
60190
60503
|
try {
|
|
60191
|
-
if (req.method === "GET" && (
|
|
60504
|
+
if (req.method === "GET" && (path74 === "/health" || path74 === "/v1/health")) {
|
|
60192
60505
|
sendJson2(res, 200, {
|
|
60193
60506
|
ok: true,
|
|
60194
60507
|
service: "zelari-companion",
|
|
@@ -60200,18 +60513,18 @@ async function runCompanionServe(opts = {}) {
|
|
|
60200
60513
|
});
|
|
60201
60514
|
return;
|
|
60202
60515
|
}
|
|
60203
|
-
if (
|
|
60516
|
+
if (path74.startsWith("/v1")) {
|
|
60204
60517
|
if (!tokenMatches(token, getBearer(req))) {
|
|
60205
60518
|
sendJson2(res, 401, { ok: false, error: "unauthorized" });
|
|
60206
60519
|
return;
|
|
60207
60520
|
}
|
|
60208
60521
|
}
|
|
60209
|
-
if (req.method === "GET" &&
|
|
60522
|
+
if (req.method === "GET" && path74 === "/v1/config") {
|
|
60210
60523
|
const snap = buildDesktopConfigSnapshot();
|
|
60211
60524
|
sendJson2(res, 200, { ok: true, ...snap });
|
|
60212
60525
|
return;
|
|
60213
60526
|
}
|
|
60214
|
-
if (req.method === "GET" &&
|
|
60527
|
+
if (req.method === "GET" && path74 === "/v1/projects") {
|
|
60215
60528
|
sendJson2(res, 200, {
|
|
60216
60529
|
ok: true,
|
|
60217
60530
|
projects: projects.map((p3) => ({
|
|
@@ -60222,7 +60535,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
60222
60535
|
});
|
|
60223
60536
|
return;
|
|
60224
60537
|
}
|
|
60225
|
-
if (req.method === "GET" &&
|
|
60538
|
+
if (req.method === "GET" && path74 === "/v1/runs") {
|
|
60226
60539
|
sendJson2(res, 200, {
|
|
60227
60540
|
ok: true,
|
|
60228
60541
|
active: runs.getActive(),
|
|
@@ -60240,7 +60553,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
60240
60553
|
});
|
|
60241
60554
|
return;
|
|
60242
60555
|
}
|
|
60243
|
-
if (req.method === "POST" &&
|
|
60556
|
+
if (req.method === "POST" && path74 === "/v1/runs") {
|
|
60244
60557
|
const raw = await readBody(req);
|
|
60245
60558
|
let body = {};
|
|
60246
60559
|
try {
|
|
@@ -60287,7 +60600,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
60287
60600
|
});
|
|
60288
60601
|
return;
|
|
60289
60602
|
}
|
|
60290
|
-
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(
|
|
60603
|
+
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path74);
|
|
60291
60604
|
if (req.method === "GET" && eventsMatch) {
|
|
60292
60605
|
const runId = eventsMatch[1];
|
|
60293
60606
|
const run = runs.getRun(runId);
|
|
@@ -60352,7 +60665,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
60352
60665
|
}, 500);
|
|
60353
60666
|
return;
|
|
60354
60667
|
}
|
|
60355
|
-
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(
|
|
60668
|
+
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path74);
|
|
60356
60669
|
if (req.method === "POST" && cancelMatch) {
|
|
60357
60670
|
const runId = cancelMatch[1];
|
|
60358
60671
|
const result = runs.cancel(runId);
|
|
@@ -60502,26 +60815,26 @@ __export(doctor_exports, {
|
|
|
60502
60815
|
runDoctor: () => runDoctor
|
|
60503
60816
|
});
|
|
60504
60817
|
import { execSync as execSync2 } from "node:child_process";
|
|
60505
|
-
import { existsSync as existsSync52, readFileSync as
|
|
60818
|
+
import { existsSync as existsSync52, readFileSync as readFileSync41, readlinkSync, statSync as statSync10 } from "node:fs";
|
|
60506
60819
|
import { createRequire as createRequire3 } from "node:module";
|
|
60507
60820
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
60508
|
-
import
|
|
60821
|
+
import path72 from "node:path";
|
|
60509
60822
|
function findPackageRoot(start) {
|
|
60510
60823
|
let dir = start;
|
|
60511
60824
|
for (let i = 0; i < 6; i += 1) {
|
|
60512
|
-
const candidate =
|
|
60825
|
+
const candidate = path72.join(dir, "package.json");
|
|
60513
60826
|
if (existsSync52(candidate)) {
|
|
60514
60827
|
try {
|
|
60515
|
-
const pkg = JSON.parse(
|
|
60828
|
+
const pkg = JSON.parse(readFileSync41(candidate, "utf8"));
|
|
60516
60829
|
if (pkg.name === "zelari-code") return dir;
|
|
60517
60830
|
} catch {
|
|
60518
60831
|
}
|
|
60519
60832
|
}
|
|
60520
|
-
const parent =
|
|
60833
|
+
const parent = path72.dirname(dir);
|
|
60521
60834
|
if (parent === dir) break;
|
|
60522
60835
|
dir = parent;
|
|
60523
60836
|
}
|
|
60524
|
-
return
|
|
60837
|
+
return path72.resolve(__dirname3, "..", "..", "..");
|
|
60525
60838
|
}
|
|
60526
60839
|
function tryExec(cmd) {
|
|
60527
60840
|
try {
|
|
@@ -60535,8 +60848,8 @@ function tryExec(cmd) {
|
|
|
60535
60848
|
}
|
|
60536
60849
|
function readPackageJson3() {
|
|
60537
60850
|
try {
|
|
60538
|
-
const pkgPath =
|
|
60539
|
-
return JSON.parse(
|
|
60851
|
+
const pkgPath = path72.join(packageRoot, "package.json");
|
|
60852
|
+
return JSON.parse(readFileSync41(pkgPath, "utf8"));
|
|
60540
60853
|
} catch {
|
|
60541
60854
|
return null;
|
|
60542
60855
|
}
|
|
@@ -60551,7 +60864,7 @@ function checkShim(pkgName) {
|
|
|
60551
60864
|
}
|
|
60552
60865
|
const isWin = process.platform === "win32";
|
|
60553
60866
|
const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
|
|
60554
|
-
const shimPath =
|
|
60867
|
+
const shimPath = path72.join(prefix, shimName);
|
|
60555
60868
|
if (!existsSync52(shimPath)) {
|
|
60556
60869
|
return FAIL(
|
|
60557
60870
|
`shim not found at ${shimPath}
|
|
@@ -60561,7 +60874,7 @@ function checkShim(pkgName) {
|
|
|
60561
60874
|
try {
|
|
60562
60875
|
const st = statSync10(shimPath);
|
|
60563
60876
|
if (isWin) {
|
|
60564
|
-
const content =
|
|
60877
|
+
const content = readFileSync41(shimPath, "utf8");
|
|
60565
60878
|
if (content.includes(`${pkgName}\\bin\\`) || content.includes(`${pkgName}/bin/`)) {
|
|
60566
60879
|
return OK(`shim OK at ${shimPath} (${st.size} bytes)`);
|
|
60567
60880
|
}
|
|
@@ -60579,8 +60892,8 @@ function checkShim(pkgName) {
|
|
|
60579
60892
|
fix: npm install -g ${pkgName}@latest --force`
|
|
60580
60893
|
);
|
|
60581
60894
|
}
|
|
60582
|
-
const resolved =
|
|
60583
|
-
const expected =
|
|
60895
|
+
const resolved = path72.resolve(path72.dirname(shimPath), target);
|
|
60896
|
+
const expected = path72.join(
|
|
60584
60897
|
prefix,
|
|
60585
60898
|
"node_modules",
|
|
60586
60899
|
pkgName,
|
|
@@ -60619,7 +60932,7 @@ function checkNode(pkg) {
|
|
|
60619
60932
|
return OK(`node ${raw}`);
|
|
60620
60933
|
}
|
|
60621
60934
|
function checkBundle() {
|
|
60622
|
-
const bundle =
|
|
60935
|
+
const bundle = path72.join(packageRoot, "dist", "cli", "main.bundled.js");
|
|
60623
60936
|
if (!existsSync52(bundle)) {
|
|
60624
60937
|
return FAIL(
|
|
60625
60938
|
`dist/cli/main.bundled.js missing at ${bundle}
|
|
@@ -60640,7 +60953,7 @@ function checkRuntimeDeps() {
|
|
|
60640
60953
|
const missing = [];
|
|
60641
60954
|
for (const dep of required2) {
|
|
60642
60955
|
try {
|
|
60643
|
-
const localReq = createRequire3(
|
|
60956
|
+
const localReq = createRequire3(path72.join(packageRoot, "package.json"));
|
|
60644
60957
|
localReq.resolve(dep);
|
|
60645
60958
|
} catch {
|
|
60646
60959
|
missing.push(dep);
|
|
@@ -60840,7 +61153,7 @@ var init_doctor = __esm({
|
|
|
60840
61153
|
init_metrics3();
|
|
60841
61154
|
init_contextGrowthSummary();
|
|
60842
61155
|
require3 = createRequire3(import.meta.url);
|
|
60843
|
-
__dirname3 =
|
|
61156
|
+
__dirname3 = path72.dirname(fileURLToPath3(import.meta.url));
|
|
60844
61157
|
packageRoot = findPackageRoot(__dirname3);
|
|
60845
61158
|
OK = (message) => ({
|
|
60846
61159
|
ok: true,
|
|
@@ -61024,15 +61337,15 @@ __export(inspect_exports, {
|
|
|
61024
61337
|
collectInspectReport: () => collectInspectReport,
|
|
61025
61338
|
runInspect: () => runInspect
|
|
61026
61339
|
});
|
|
61027
|
-
import
|
|
61028
|
-
import { existsSync as existsSync53, readFileSync as
|
|
61029
|
-
import { homedir as
|
|
61340
|
+
import path73 from "node:path";
|
|
61341
|
+
import { existsSync as existsSync53, readFileSync as readFileSync42, readdirSync as readdirSync11 } from "node:fs";
|
|
61342
|
+
import { homedir as homedir15 } from "node:os";
|
|
61030
61343
|
async function collectInspectReport(cwd = process.cwd()) {
|
|
61031
61344
|
ensureBuiltinSkillsLoadedSync();
|
|
61032
61345
|
const snap = listSkillsSnapshot(cwd);
|
|
61033
61346
|
const mcp = listMcpServers(cwd);
|
|
61034
|
-
const userMcpPath =
|
|
61035
|
-
const projectMcpPath =
|
|
61347
|
+
const userMcpPath = path73.join(homedir15(), ".zelari-code", "mcp.json");
|
|
61348
|
+
const projectMcpPath = path73.join(cwd, ".zelari", "mcp.json");
|
|
61036
61349
|
const globalHooks = globalHooksDir();
|
|
61037
61350
|
const projectHooks = projectHooksDir(cwd);
|
|
61038
61351
|
const projectTrusted = isFolderTrusted(cwd);
|
|
@@ -61060,9 +61373,9 @@ async function collectInspectReport(cwd = process.cwd()) {
|
|
|
61060
61373
|
configSources: [
|
|
61061
61374
|
{ path: userMcpPath, exists: existsSync53(userMcpPath) },
|
|
61062
61375
|
{ path: projectMcpPath, exists: existsSync53(projectMcpPath) },
|
|
61063
|
-
{ path:
|
|
61064
|
-
{ path:
|
|
61065
|
-
{ path:
|
|
61376
|
+
{ path: path73.join(homedir15(), ".zelari-code", "provider.json"), exists: existsSync53(path73.join(homedir15(), ".zelari-code", "provider.json")) },
|
|
61377
|
+
{ path: path73.join(cwd, ".zelari", "AGENTS.md"), exists: existsSync53(path73.join(cwd, ".zelari", "AGENTS.md")) },
|
|
61378
|
+
{ path: path73.join(cwd, "AGENTS.md"), exists: existsSync53(path73.join(cwd, "AGENTS.md")) }
|
|
61066
61379
|
],
|
|
61067
61380
|
skills: {
|
|
61068
61381
|
total: snap.skills.length,
|
|
@@ -61102,14 +61415,14 @@ function listJsonFiles(dir) {
|
|
|
61102
61415
|
}
|
|
61103
61416
|
function findAgentsMd(cwd) {
|
|
61104
61417
|
const candidates = [
|
|
61105
|
-
|
|
61106
|
-
|
|
61418
|
+
path73.join(cwd, "AGENTS.md"),
|
|
61419
|
+
path73.join(cwd, ".zelari", "AGENTS.md")
|
|
61107
61420
|
];
|
|
61108
61421
|
const found = [];
|
|
61109
61422
|
for (const c of candidates) {
|
|
61110
61423
|
if (existsSync53(c)) {
|
|
61111
61424
|
try {
|
|
61112
|
-
const text =
|
|
61425
|
+
const text = readFileSync42(c, "utf8");
|
|
61113
61426
|
found.push(`${c} (${text.length} bytes)`);
|
|
61114
61427
|
} catch {
|
|
61115
61428
|
found.push(`${c} (unreadable)`);
|
|
@@ -64403,10 +64716,11 @@ import { createHash as createHash14 } from "node:crypto";
|
|
|
64403
64716
|
init_runtime2();
|
|
64404
64717
|
init_verification2();
|
|
64405
64718
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
64406
|
-
import
|
|
64719
|
+
import path43 from "node:path";
|
|
64407
64720
|
function nativePackEnabled(env = process.env) {
|
|
64408
64721
|
const v = env.ZELARI_VERIFY_PACK?.toLowerCase();
|
|
64409
|
-
|
|
64722
|
+
if (v === "0" || v === "off" || v === "false") return false;
|
|
64723
|
+
return true;
|
|
64410
64724
|
}
|
|
64411
64725
|
function resolvePackCommands(env, scripts) {
|
|
64412
64726
|
const pick2 = (override, scriptName) => {
|
|
@@ -64430,7 +64744,7 @@ function packTimeoutMs(env = process.env) {
|
|
|
64430
64744
|
}
|
|
64431
64745
|
async function readPackageScripts(cwd = process.cwd()) {
|
|
64432
64746
|
try {
|
|
64433
|
-
const raw = await readFile3(
|
|
64747
|
+
const raw = await readFile3(path43.join(cwd, "package.json"), "utf-8");
|
|
64434
64748
|
const parsed = JSON.parse(raw);
|
|
64435
64749
|
if (parsed && typeof parsed === "object" && typeof parsed.scripts === "object") {
|
|
64436
64750
|
return parsed.scripts;
|
|
@@ -64469,7 +64783,8 @@ function strictDoneEnabled(surface = "kraken") {
|
|
|
64469
64783
|
return true;
|
|
64470
64784
|
}
|
|
64471
64785
|
const v = process.env.ZELARI_STRICT_DONE;
|
|
64472
|
-
|
|
64786
|
+
if (v === "0" || v === "false") return false;
|
|
64787
|
+
return true;
|
|
64473
64788
|
}
|
|
64474
64789
|
function criterionId(check2, index) {
|
|
64475
64790
|
const slug = check2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
@@ -64706,6 +65021,145 @@ function strictGateEventPayload(evaluation) {
|
|
|
64706
65021
|
};
|
|
64707
65022
|
}
|
|
64708
65023
|
|
|
65024
|
+
// src/cli/kraken/completionProof.ts
|
|
65025
|
+
import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
|
|
65026
|
+
import path44 from "node:path";
|
|
65027
|
+
function verdictOf(evaluation) {
|
|
65028
|
+
return evaluation.evaluation?.verdict ?? (evaluation.blocked ? "BLOCKED" : "PASS");
|
|
65029
|
+
}
|
|
65030
|
+
function cell(text, max = 200) {
|
|
65031
|
+
const flat = text.replace(/\r?\n/g, " ").replace(/\|/g, "\\|").trim();
|
|
65032
|
+
return flat.length > max ? `${flat.slice(0, max - 1)}\u2026` : flat;
|
|
65033
|
+
}
|
|
65034
|
+
function evidenceCell(result) {
|
|
65035
|
+
if (!result || result.evidence.length === 0) return "\u2014";
|
|
65036
|
+
return result.evidence.map((e) => {
|
|
65037
|
+
const parts = [e.tier];
|
|
65038
|
+
if (e.seq !== void 0) parts.push(`seq ${e.seq}`);
|
|
65039
|
+
if (e.digest) parts.push(`digest ${e.digest.slice(0, 8)}\u2026`);
|
|
65040
|
+
return parts.join(" \xB7 ");
|
|
65041
|
+
}).join("; ");
|
|
65042
|
+
}
|
|
65043
|
+
function proofRows(evaluation) {
|
|
65044
|
+
const nativeById = new Map(
|
|
65045
|
+
(evaluation.native?.criteria ?? []).map((c) => [c.id, c])
|
|
65046
|
+
);
|
|
65047
|
+
const rows = /* @__PURE__ */ new Map();
|
|
65048
|
+
for (const result of evaluation.results ?? []) {
|
|
65049
|
+
const criterion = nativeById.get(result.criterionId);
|
|
65050
|
+
rows.set(result.criterionId, {
|
|
65051
|
+
id: result.criterionId,
|
|
65052
|
+
text: criterion?.text ?? null,
|
|
65053
|
+
required: criterion ? criterion.required : true,
|
|
65054
|
+
status: result.status,
|
|
65055
|
+
result
|
|
65056
|
+
});
|
|
65057
|
+
}
|
|
65058
|
+
for (const unsatisfied of evaluation.evaluation?.unsatisfied ?? []) {
|
|
65059
|
+
if (rows.has(unsatisfied.id)) continue;
|
|
65060
|
+
const criterion = nativeById.get(unsatisfied.id);
|
|
65061
|
+
rows.set(unsatisfied.id, {
|
|
65062
|
+
id: unsatisfied.id,
|
|
65063
|
+
text: criterion?.text ?? null,
|
|
65064
|
+
required: true,
|
|
65065
|
+
// satisfied/unsatisfied lists cover required criteria only
|
|
65066
|
+
status: unsatisfied.status,
|
|
65067
|
+
result: null
|
|
65068
|
+
});
|
|
65069
|
+
}
|
|
65070
|
+
return [...rows.values()];
|
|
65071
|
+
}
|
|
65072
|
+
function renderMarkdown(evaluation, meta3) {
|
|
65073
|
+
const lines = [
|
|
65074
|
+
"# Completion Proof",
|
|
65075
|
+
"",
|
|
65076
|
+
"Strict build-gate proof-of-work (ADR-0023). The machine-readable twin of",
|
|
65077
|
+
"this document \u2014 `completion-proof.json` \u2014 is the exact `verification.run`",
|
|
65078
|
+
"payload sent to the session spine.",
|
|
65079
|
+
"",
|
|
65080
|
+
`- **Verdict**: **${verdictOf(evaluation)}**`,
|
|
65081
|
+
`- **Strict gate**: ${evaluation.strict ? "on" : "off"}`,
|
|
65082
|
+
`- **Turn blocked**: ${evaluation.blocked ? "yes" : "no"}`,
|
|
65083
|
+
`- **Summary**: ${cell(evaluation.summary, 400)}`,
|
|
65084
|
+
`- **Legacy selection gate**: ${evaluation.gate.passed}/${evaluation.gate.total} passed` + (evaluation.gate.failedChecks.length > 0 ? `; failed: ${evaluation.gate.failedChecks.length}` : "") + (evaluation.gate.unknownChecks.length > 0 ? `; unknown: ${evaluation.gate.unknownChecks.length}` : "")
|
|
65085
|
+
];
|
|
65086
|
+
if (meta3.surface) lines.push(`- **Surface**: ${meta3.surface}`);
|
|
65087
|
+
if (meta3.sessionId) lines.push(`- **Session**: ${meta3.sessionId} (session spine)`);
|
|
65088
|
+
if (meta3.generatedAt !== void 0) {
|
|
65089
|
+
lines.push(`- **Generated**: ${new Date(meta3.generatedAt).toISOString()}`);
|
|
65090
|
+
}
|
|
65091
|
+
const rows = proofRows(evaluation);
|
|
65092
|
+
lines.push("", "## Criteria", "", "| Criterion | Required | Status | Evidence |", "| --- | --- | --- | --- |");
|
|
65093
|
+
if (rows.length === 0) {
|
|
65094
|
+
lines.push("| _none \u2014 no criteria joined this evaluation_ | \u2014 | \u2014 | \u2014 |");
|
|
65095
|
+
}
|
|
65096
|
+
for (const row of rows) {
|
|
65097
|
+
const label = row.text ? `\`${row.id}\` \u2014 ${cell(row.text)}` : `\`${row.id}\``;
|
|
65098
|
+
lines.push(`| ${label} | ${row.required ? "yes" : "no"} | ${row.status} | ${evidenceCell(row.result)} |`);
|
|
65099
|
+
}
|
|
65100
|
+
const unsatisfied = evaluation.evaluation?.unsatisfied ?? [];
|
|
65101
|
+
if (unsatisfied.length > 0) {
|
|
65102
|
+
lines.push("", "### Unsatisfied", "");
|
|
65103
|
+
for (const u of unsatisfied) lines.push(`- \`${u.id}\`: **${u.status}** \u2014 ${cell(u.reason, 300)}`);
|
|
65104
|
+
}
|
|
65105
|
+
const native = evaluation.native;
|
|
65106
|
+
if (native) {
|
|
65107
|
+
lines.push(
|
|
65108
|
+
"",
|
|
65109
|
+
`## Native criteria pack \u2014 ${native.packId}`,
|
|
65110
|
+
"",
|
|
65111
|
+
"| Criterion | Command | Status | Detail |",
|
|
65112
|
+
"| --- | --- | --- | --- |"
|
|
65113
|
+
);
|
|
65114
|
+
for (const result of native.results) {
|
|
65115
|
+
const criterion = native.criteria.find((c) => c.id === result.criterionId);
|
|
65116
|
+
const check2 = criterion?.check;
|
|
65117
|
+
const command = check2?.kind === "command" ? check2.command : "\u2014";
|
|
65118
|
+
const label = criterion?.text ? `\`${result.criterionId}\` \u2014 ${cell(criterion.text, 120)}` : `\`${result.criterionId}\``;
|
|
65119
|
+
lines.push(`| ${label} | \`${cell(command, 120)}\` | ${result.status} | ${cell(result.detail ?? "\u2014")} |`);
|
|
65120
|
+
}
|
|
65121
|
+
}
|
|
65122
|
+
const review = evaluation.review;
|
|
65123
|
+
if (review) {
|
|
65124
|
+
lines.push(
|
|
65125
|
+
"",
|
|
65126
|
+
"## Advisory verifier review",
|
|
65127
|
+
"",
|
|
65128
|
+
"_Advisory only \u2014 this review cannot change the gate verdict above._",
|
|
65129
|
+
"",
|
|
65130
|
+
`- **Verdict**: ${review.verdict}`
|
|
65131
|
+
);
|
|
65132
|
+
if (review.score !== void 0) lines.push(`- **Score**: ${review.score}`);
|
|
65133
|
+
const model = review.effectiveModel.model ?? review.effectiveModel.provider ?? review.effectiveModel.mode;
|
|
65134
|
+
lines.push(`- **Model**: ${model}${review.usedLogprobs ? " (logprobs)" : ""}`);
|
|
65135
|
+
if (review.fallback) lines.push(`- **Fallback**: ${review.fallback}`);
|
|
65136
|
+
if (review.rationale) lines.push(`- **Rationale**: ${cell(review.rationale, 400)}`);
|
|
65137
|
+
}
|
|
65138
|
+
lines.push("", "---", "", "Machine record: `completion-proof.json` (same directory).");
|
|
65139
|
+
return `${lines.join("\n")}
|
|
65140
|
+
`;
|
|
65141
|
+
}
|
|
65142
|
+
function renderCompletionProof(evaluation, meta3 = {}) {
|
|
65143
|
+
return {
|
|
65144
|
+
markdown: renderMarkdown(evaluation, meta3),
|
|
65145
|
+
json: JSON.stringify(strictGateEventPayload(evaluation), null, 2)
|
|
65146
|
+
};
|
|
65147
|
+
}
|
|
65148
|
+
async function writeCompletionProof(evaluation, options = {}) {
|
|
65149
|
+
try {
|
|
65150
|
+
const dir = path44.join(options.baseDir ?? process.cwd(), ".zelari");
|
|
65151
|
+
await mkdir2(dir, { recursive: true });
|
|
65152
|
+
const { markdown, json: json3 } = renderCompletionProof(evaluation, options.meta);
|
|
65153
|
+
const markdownPath = path44.join(dir, "completion-proof.md");
|
|
65154
|
+
const jsonPath = path44.join(dir, "completion-proof.json");
|
|
65155
|
+
await writeFile2(markdownPath, markdown, "utf8");
|
|
65156
|
+
await writeFile2(jsonPath, json3, "utf8");
|
|
65157
|
+
return { markdownPath, jsonPath };
|
|
65158
|
+
} catch {
|
|
65159
|
+
return null;
|
|
65160
|
+
}
|
|
65161
|
+
}
|
|
65162
|
+
|
|
64709
65163
|
// src/cli/hooks/permissionPicker.ts
|
|
64710
65164
|
init_toolPermissions();
|
|
64711
65165
|
|
|
@@ -65746,10 +66200,15 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
65746
66200
|
if (event.type === "agent_end") {
|
|
65747
66201
|
let krakenSuppressFinish = false;
|
|
65748
66202
|
const krakenSpineEmit = (input) => writerRef.current?.spine?.appendEvent(input) ?? Promise.resolve(null);
|
|
66203
|
+
const writeProofSafe2 = (gate) => writeCompletionProof(gate, { meta: { surface: "kraken", sessionId: sessionId2 } }).then(
|
|
66204
|
+
() => void 0,
|
|
66205
|
+
() => void 0
|
|
66206
|
+
);
|
|
65749
66207
|
if (event.reason === "completed" && !krakenRepairEnqueued && (isKrakenSelectionEnabled() || nativePackEnabled()) && workPhase === "build") {
|
|
65750
66208
|
const strictGate = await evaluateStrictBuildGate("build", { emit: krakenSpineEmit });
|
|
65751
66209
|
const krakenGate = strictGate.gate;
|
|
65752
66210
|
writerRef.current?.spine?.verificationRun(strictGateEventPayload(strictGate));
|
|
66211
|
+
await writeProofSafe2(strictGate);
|
|
65753
66212
|
if (krakenGate.blocked) {
|
|
65754
66213
|
krakenRepairEnqueued = true;
|
|
65755
66214
|
markRepairTriggered();
|
|
@@ -65763,10 +66222,13 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
65763
66222
|
krakenSuppressFinish = true;
|
|
65764
66223
|
}
|
|
65765
66224
|
}
|
|
65766
|
-
|
|
66225
|
+
const repairCheck = event.reason === "completed" && krakenRepairEnqueued ? await evaluateStrictBuildGate("build", { emit: krakenSpineEmit }) : null;
|
|
66226
|
+
if (repairCheck) await writeProofSafe2(repairCheck);
|
|
66227
|
+
if (repairCheck && !repairCheck.blocked) {
|
|
65767
66228
|
markRepairSucceeded();
|
|
65768
66229
|
} else if (event.reason === "completed" && krakenRepairEnqueued) {
|
|
65769
66230
|
const still = await evaluateStrictBuildGate("build", { emit: krakenSpineEmit });
|
|
66231
|
+
await writeProofSafe2(still);
|
|
65770
66232
|
if (still.blocked) {
|
|
65771
66233
|
appendSystem(
|
|
65772
66234
|
setMessages,
|
|
@@ -67882,7 +68344,7 @@ init_sessionManager();
|
|
|
67882
68344
|
// src/cli/gitOps.ts
|
|
67883
68345
|
import { execFile as execFile4 } from "node:child_process";
|
|
67884
68346
|
import { promisify as promisify3 } from "node:util";
|
|
67885
|
-
import
|
|
68347
|
+
import path55 from "node:path";
|
|
67886
68348
|
var execFileAsync3 = promisify3(execFile4);
|
|
67887
68349
|
async function git4(cwd, args) {
|
|
67888
68350
|
try {
|
|
@@ -67928,7 +68390,7 @@ async function undoWorkingChanges(opts = {}) {
|
|
|
67928
68390
|
};
|
|
67929
68391
|
}
|
|
67930
68392
|
function defaultProjectRoot() {
|
|
67931
|
-
return
|
|
68393
|
+
return path55.resolve(__dirname, "..", "..", "..");
|
|
67932
68394
|
}
|
|
67933
68395
|
|
|
67934
68396
|
// src/cli/slashHandlers/git.ts
|
|
@@ -68215,11 +68677,11 @@ function handleCacheStats(ctx) {
|
|
|
68215
68677
|
init_messageHelpers();
|
|
68216
68678
|
init_serviceFactory();
|
|
68217
68679
|
import { promises as fs30 } from "node:fs";
|
|
68218
|
-
import * as
|
|
68680
|
+
import * as path57 from "node:path";
|
|
68219
68681
|
|
|
68220
68682
|
// src/cli/memory/promotion.ts
|
|
68221
68683
|
import { promises as fs29 } from "node:fs";
|
|
68222
|
-
import * as
|
|
68684
|
+
import * as path56 from "node:path";
|
|
68223
68685
|
var START = "<!-- zelari:memory-promotions:start -->";
|
|
68224
68686
|
var END = "<!-- zelari:memory-promotions:end -->";
|
|
68225
68687
|
var DURABLE_KINDS = /* @__PURE__ */ new Set(["fact", "decision", "constraint", "preference", "procedure"]);
|
|
@@ -68230,13 +68692,13 @@ function lineFor(node) {
|
|
|
68230
68692
|
}
|
|
68231
68693
|
async function promoteMemoryToAgentsMd(projectRoot, node) {
|
|
68232
68694
|
if (node.status !== "active") {
|
|
68233
|
-
return { added: false, path:
|
|
68695
|
+
return { added: false, path: path56.join(projectRoot, "AGENTS.md"), reason: `memory is ${node.status}` };
|
|
68234
68696
|
}
|
|
68235
68697
|
if (!DURABLE_KINDS.has(node.kind)) {
|
|
68236
|
-
return { added: false, path:
|
|
68698
|
+
return { added: false, path: path56.join(projectRoot, "AGENTS.md"), reason: `${node.kind} is not a durable instruction kind` };
|
|
68237
68699
|
}
|
|
68238
|
-
const root = await fs29.realpath(projectRoot).catch(() =>
|
|
68239
|
-
const target =
|
|
68700
|
+
const root = await fs29.realpath(projectRoot).catch(() => path56.resolve(projectRoot));
|
|
68701
|
+
const target = path56.join(root, "AGENTS.md");
|
|
68240
68702
|
try {
|
|
68241
68703
|
const stat2 = await fs29.lstat(target);
|
|
68242
68704
|
if (stat2.isSymbolicLink() || !stat2.isFile()) throw new Error("AGENTS.md must be a regular project file.");
|
|
@@ -68301,22 +68763,22 @@ function sourceLine(source2) {
|
|
|
68301
68763
|
return entries.length ? entries.map(([key, value]) => `${key}=${value}`).join(" \xB7 ") : "unknown";
|
|
68302
68764
|
}
|
|
68303
68765
|
function isInside(root, target) {
|
|
68304
|
-
const relative6 =
|
|
68305
|
-
return relative6 === "" || !relative6.startsWith("..") && !
|
|
68766
|
+
const relative6 = path57.relative(root, target);
|
|
68767
|
+
return relative6 === "" || !relative6.startsWith("..") && !path57.isAbsolute(relative6);
|
|
68306
68768
|
}
|
|
68307
68769
|
async function safeExportPath(cwd, requested) {
|
|
68308
|
-
const lexicalRoot =
|
|
68770
|
+
const lexicalRoot = path57.resolve(cwd);
|
|
68309
68771
|
const root = await fs30.realpath(lexicalRoot).catch(() => lexicalRoot);
|
|
68310
|
-
const fallback =
|
|
68311
|
-
const target = requested?.trim() ?
|
|
68772
|
+
const fallback = path57.join(root, ".zelari", "memory", `export-${Date.now()}.json`);
|
|
68773
|
+
const target = requested?.trim() ? path57.resolve(root, requested.trim()) : fallback;
|
|
68312
68774
|
if (!isInside(root, target)) {
|
|
68313
68775
|
throw new Error("Export path must stay inside the active project.");
|
|
68314
68776
|
}
|
|
68315
|
-
const parent =
|
|
68316
|
-
const relativeParent =
|
|
68777
|
+
const parent = path57.dirname(target);
|
|
68778
|
+
const relativeParent = path57.relative(root, parent);
|
|
68317
68779
|
let cursor = root;
|
|
68318
|
-
for (const segment of relativeParent.split(
|
|
68319
|
-
cursor =
|
|
68780
|
+
for (const segment of relativeParent.split(path57.sep).filter(Boolean)) {
|
|
68781
|
+
cursor = path57.join(cursor, segment);
|
|
68320
68782
|
try {
|
|
68321
68783
|
const stat2 = await fs30.lstat(cursor);
|
|
68322
68784
|
if (stat2.isSymbolicLink()) {
|
|
@@ -68488,9 +68950,9 @@ ${message}` : message
|
|
|
68488
68950
|
}
|
|
68489
68951
|
case "export": {
|
|
68490
68952
|
const target = await safeExportPath(ctx.cwd, args.join(" ").trim() || void 0);
|
|
68491
|
-
await fs30.mkdir(
|
|
68492
|
-
const root = await fs30.realpath(ctx.cwd).catch(() =>
|
|
68493
|
-
const realParent = await fs30.realpath(
|
|
68953
|
+
await fs30.mkdir(path57.dirname(target), { recursive: true });
|
|
68954
|
+
const root = await fs30.realpath(ctx.cwd).catch(() => path57.resolve(ctx.cwd));
|
|
68955
|
+
const realParent = await fs30.realpath(path57.dirname(target));
|
|
68494
68956
|
if (!isInside(root, realParent)) {
|
|
68495
68957
|
throw new Error("Export path resolves outside the active project.");
|
|
68496
68958
|
}
|
|
@@ -68686,7 +69148,7 @@ import { promises as fs34 } from "node:fs";
|
|
|
68686
69148
|
init_zod();
|
|
68687
69149
|
init_taskTool();
|
|
68688
69150
|
import { promises as fs33 } from "node:fs";
|
|
68689
|
-
import
|
|
69151
|
+
import path61 from "node:path";
|
|
68690
69152
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
68691
69153
|
var CsvFanoutArgsSchema = external_exports.object({
|
|
68692
69154
|
csv_path: external_exports.string().min(1),
|
|
@@ -68780,8 +69242,8 @@ function resolveMaxConcurrency(env = process.env) {
|
|
|
68780
69242
|
}
|
|
68781
69243
|
async function runCsvFanout(args, deps, opts) {
|
|
68782
69244
|
const start = Date.now();
|
|
68783
|
-
const absCsv =
|
|
68784
|
-
const absOut =
|
|
69245
|
+
const absCsv = path61.isAbsolute(args.csv_path) ? args.csv_path : path61.join(opts.parentCwd, args.csv_path);
|
|
69246
|
+
const absOut = path61.isAbsolute(args.output_csv_path) ? args.output_csv_path : path61.join(opts.parentCwd, args.output_csv_path);
|
|
68785
69247
|
const { headers: headers2, rows } = await readCsv(absCsv);
|
|
68786
69248
|
if (headers2.length === 0) {
|
|
68787
69249
|
throw new Error(`kraken_csv_fanout: ${absCsv} is empty`);
|
|
@@ -68837,7 +69299,7 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
68837
69299
|
errored += 1;
|
|
68838
69300
|
errors.push(`${row[args.id_column] ?? i}: ${res.error}`);
|
|
68839
69301
|
}
|
|
68840
|
-
await fs33.mkdir(
|
|
69302
|
+
await fs33.mkdir(path61.dirname(absOut), { recursive: true });
|
|
68841
69303
|
await queueWrite(serializeCsv(outHeaders, outputRecords));
|
|
68842
69304
|
}
|
|
68843
69305
|
}
|
|
@@ -69032,7 +69494,7 @@ function splitArgs(s) {
|
|
|
69032
69494
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
69033
69495
|
init_messageHelpers();
|
|
69034
69496
|
import { promises as fs35 } from "node:fs";
|
|
69035
|
-
import
|
|
69497
|
+
import path62 from "node:path";
|
|
69036
69498
|
|
|
69037
69499
|
// src/cli/kraken/workbenchView.ts
|
|
69038
69500
|
var EMPTY = {
|
|
@@ -69149,14 +69611,14 @@ function formatWorkbenchForTerminal(p3) {
|
|
|
69149
69611
|
|
|
69150
69612
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
69151
69613
|
async function handleKrakenWorkbench(ctx) {
|
|
69152
|
-
const dir =
|
|
69614
|
+
const dir = path62.join(ctx.cwd, ".zelari", "radio");
|
|
69153
69615
|
let latest = null;
|
|
69154
69616
|
let latestMtime = 0;
|
|
69155
69617
|
try {
|
|
69156
69618
|
const files = await fs35.readdir(dir);
|
|
69157
69619
|
for (const f of files) {
|
|
69158
69620
|
if (!f.startsWith("workbench-") || !f.endsWith(".md")) continue;
|
|
69159
|
-
const full =
|
|
69621
|
+
const full = path62.join(dir, f);
|
|
69160
69622
|
const stat2 = await fs35.stat(full);
|
|
69161
69623
|
if (stat2.mtimeMs > latestMtime) {
|
|
69162
69624
|
latestMtime = stat2.mtimeMs;
|
|
@@ -69173,10 +69635,10 @@ async function handleKrakenWorkbench(ctx) {
|
|
|
69173
69635
|
const parsed = parseWorkbench(content);
|
|
69174
69636
|
const rendered = formatWorkbenchForTerminal(parsed);
|
|
69175
69637
|
if (!rendered.trim()) {
|
|
69176
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
69638
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path62.basename(latest)}: (no nodes / no events yet)`);
|
|
69177
69639
|
return;
|
|
69178
69640
|
}
|
|
69179
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
69641
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path62.basename(latest)}:
|
|
69180
69642
|
${rendered}`);
|
|
69181
69643
|
}
|
|
69182
69644
|
|
|
@@ -69483,15 +69945,15 @@ ${result.output.split("\n").slice(-8).join("\n")}` : "";
|
|
|
69483
69945
|
// src/cli/slashHandlers/promoteMember.ts
|
|
69484
69946
|
init_messageHelpers();
|
|
69485
69947
|
import { promises as fs36 } from "node:fs";
|
|
69486
|
-
import
|
|
69948
|
+
import path65 from "node:path";
|
|
69487
69949
|
import os12 from "node:os";
|
|
69488
69950
|
async function handlePromoteMember(ctx, memberId) {
|
|
69489
69951
|
try {
|
|
69490
69952
|
const { promoteMember: promoteMember2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
69491
69953
|
const { skill, markdown } = promoteMember2(memberId);
|
|
69492
|
-
const skillDir = process.env.ANATHEMA_SKILL_DIR ??
|
|
69954
|
+
const skillDir = process.env.ANATHEMA_SKILL_DIR ?? path65.join(os12.homedir(), ".tmp", "zelari-code", "skills");
|
|
69493
69955
|
await fs36.mkdir(skillDir, { recursive: true });
|
|
69494
|
-
const filePath =
|
|
69956
|
+
const filePath = path65.join(skillDir, `${skill.id}.md`);
|
|
69495
69957
|
await fs36.writeFile(filePath, markdown, "utf8");
|
|
69496
69958
|
appendSystem(
|
|
69497
69959
|
ctx.setMessages,
|
|
@@ -69508,25 +69970,25 @@ async function handlePromoteMember(ctx, memberId) {
|
|
|
69508
69970
|
}
|
|
69509
69971
|
|
|
69510
69972
|
// src/cli/branchManager.ts
|
|
69511
|
-
import { promises as fs37, existsSync as existsSync45, readFileSync as
|
|
69512
|
-
import
|
|
69973
|
+
import { promises as fs37, existsSync as existsSync45, readFileSync as readFileSync37, writeFileSync as writeFileSync23, mkdirSync as mkdirSync19, statSync as statSync7, rmSync as rmSync3 } from "node:fs";
|
|
69974
|
+
import path66 from "node:path";
|
|
69513
69975
|
import os13 from "node:os";
|
|
69514
69976
|
var META_FILENAME = "meta.json";
|
|
69515
69977
|
var SESSIONS_SUBDIR = "sessions";
|
|
69516
69978
|
function getBranchesBaseDir() {
|
|
69517
|
-
return process.env.ANATHEMA_BRANCHES_DIR ??
|
|
69979
|
+
return process.env.ANATHEMA_BRANCHES_DIR ?? path66.join(os13.homedir(), ".tmp", "zelari-code", "branches");
|
|
69518
69980
|
}
|
|
69519
69981
|
function getSessionsBaseDir() {
|
|
69520
|
-
return process.env.ANATHEMA_SESSIONS_DIR ??
|
|
69982
|
+
return process.env.ANATHEMA_SESSIONS_DIR ?? path66.join(os13.homedir(), ".tmp", "zelari-code", "sessions");
|
|
69521
69983
|
}
|
|
69522
69984
|
function branchPathFor(name, baseDir) {
|
|
69523
|
-
return
|
|
69985
|
+
return path66.join(baseDir, name);
|
|
69524
69986
|
}
|
|
69525
69987
|
function metaPathFor(name, baseDir) {
|
|
69526
|
-
return
|
|
69988
|
+
return path66.join(baseDir, name, META_FILENAME);
|
|
69527
69989
|
}
|
|
69528
69990
|
function sessionsPathFor(name, baseDir) {
|
|
69529
|
-
return
|
|
69991
|
+
return path66.join(baseDir, name, SESSIONS_SUBDIR);
|
|
69530
69992
|
}
|
|
69531
69993
|
function readBranchMeta(name, baseDir) {
|
|
69532
69994
|
const metaPath = metaPathFor(name, baseDir);
|
|
@@ -69534,7 +69996,7 @@ function readBranchMeta(name, baseDir) {
|
|
|
69534
69996
|
throw new BranchNotFoundError(`Branch "${name}" not found`);
|
|
69535
69997
|
}
|
|
69536
69998
|
try {
|
|
69537
|
-
const raw =
|
|
69999
|
+
const raw = readFileSync37(metaPath, "utf-8");
|
|
69538
70000
|
const parsed = JSON.parse(raw);
|
|
69539
70001
|
if (!parsed || typeof parsed !== "object" || typeof parsed.name !== "string" || typeof parsed.createdAt !== "number" || typeof parsed.fromSessionId !== "string") {
|
|
69540
70002
|
throw new BranchCorruptError(`Branch "${name}" meta.json is malformed`);
|
|
@@ -69551,7 +70013,7 @@ function readBranchMeta(name, baseDir) {
|
|
|
69551
70013
|
}
|
|
69552
70014
|
function writeBranchMeta(name, baseDir, meta3) {
|
|
69553
70015
|
const metaPath = metaPathFor(name, baseDir);
|
|
69554
|
-
mkdirSync19(
|
|
70016
|
+
mkdirSync19(path66.dirname(metaPath), { recursive: true });
|
|
69555
70017
|
writeFileSync23(metaPath, JSON.stringify(meta3, null, 2), "utf-8");
|
|
69556
70018
|
}
|
|
69557
70019
|
async function countSessions(name, baseDir) {
|
|
@@ -69602,14 +70064,14 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
69602
70064
|
if (branchExists(name, baseDir)) {
|
|
69603
70065
|
throw new BranchAlreadyExistsError(name);
|
|
69604
70066
|
}
|
|
69605
|
-
const sourcePath =
|
|
70067
|
+
const sourcePath = path66.join(sessionsBaseDir, `${fromSessionId}.jsonl`);
|
|
69606
70068
|
if (!existsSync45(sourcePath)) {
|
|
69607
70069
|
throw new SessionNotFoundError(`Source session "${fromSessionId}" not found at ${sourcePath}`);
|
|
69608
70070
|
}
|
|
69609
70071
|
const branchPath = branchPathFor(name, baseDir);
|
|
69610
70072
|
const branchSessionsPath = sessionsPathFor(name, baseDir);
|
|
69611
70073
|
mkdirSync19(branchSessionsPath, { recursive: true });
|
|
69612
|
-
const destPath =
|
|
70074
|
+
const destPath = path66.join(branchSessionsPath, `${fromSessionId}.jsonl`);
|
|
69613
70075
|
await fs37.copyFile(sourcePath, destPath);
|
|
69614
70076
|
const meta3 = {
|
|
69615
70077
|
name,
|
|
@@ -69713,14 +70175,14 @@ async function handleBranchCheckout(ctx, branchName) {
|
|
|
69713
70175
|
// src/cli/slashHandlers/workspace.ts
|
|
69714
70176
|
init_messageHelpers();
|
|
69715
70177
|
import { promises as fs38 } from "node:fs";
|
|
69716
|
-
import
|
|
70178
|
+
import path67 from "node:path";
|
|
69717
70179
|
async function handleWorkspaceShow(ctx, what) {
|
|
69718
70180
|
try {
|
|
69719
|
-
const zelari =
|
|
70181
|
+
const zelari = path67.join(process.cwd(), ".zelari");
|
|
69720
70182
|
let content;
|
|
69721
70183
|
switch (what) {
|
|
69722
70184
|
case "plan": {
|
|
69723
|
-
const planPath =
|
|
70185
|
+
const planPath = path67.join(zelari, "plan.md");
|
|
69724
70186
|
try {
|
|
69725
70187
|
content = await fs38.readFile(planPath, "utf-8");
|
|
69726
70188
|
} catch {
|
|
@@ -69729,7 +70191,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
69729
70191
|
break;
|
|
69730
70192
|
}
|
|
69731
70193
|
case "decisions": {
|
|
69732
|
-
const decisionsDir =
|
|
70194
|
+
const decisionsDir = path67.join(zelari, "decisions");
|
|
69733
70195
|
try {
|
|
69734
70196
|
const files = (await fs38.readdir(decisionsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
69735
70197
|
if (files.length === 0) {
|
|
@@ -69739,7 +70201,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
69739
70201
|
`];
|
|
69740
70202
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
69741
70203
|
for (const f of files) {
|
|
69742
|
-
const raw = await fs38.readFile(
|
|
70204
|
+
const raw = await fs38.readFile(path67.join(decisionsDir, f), "utf-8");
|
|
69743
70205
|
const { meta: meta3, body } = parseFrontmatter2(raw);
|
|
69744
70206
|
const title = meta3.title ?? body.split("\n")[0]?.replace(/^#\s*/, "").trim() ?? f;
|
|
69745
70207
|
lines.push(`- **${f.replace(/\.md$/, "")}** [${meta3.status ?? "unknown"}] ${title}`);
|
|
@@ -69752,7 +70214,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
69752
70214
|
break;
|
|
69753
70215
|
}
|
|
69754
70216
|
case "risks": {
|
|
69755
|
-
const risksPath =
|
|
70217
|
+
const risksPath = path67.join(zelari, "risks.md");
|
|
69756
70218
|
try {
|
|
69757
70219
|
content = await fs38.readFile(risksPath, "utf-8");
|
|
69758
70220
|
} catch {
|
|
@@ -69761,7 +70223,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
69761
70223
|
break;
|
|
69762
70224
|
}
|
|
69763
70225
|
case "agents": {
|
|
69764
|
-
const agentsPath =
|
|
70226
|
+
const agentsPath = path67.join(process.cwd(), "AGENTS.MD");
|
|
69765
70227
|
try {
|
|
69766
70228
|
content = await fs38.readFile(agentsPath, "utf-8");
|
|
69767
70229
|
} catch {
|
|
@@ -69770,7 +70232,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
69770
70232
|
break;
|
|
69771
70233
|
}
|
|
69772
70234
|
case "docs": {
|
|
69773
|
-
const docsDir =
|
|
70235
|
+
const docsDir = path67.join(zelari, "docs");
|
|
69774
70236
|
try {
|
|
69775
70237
|
const files = (await fs38.readdir(docsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
69776
70238
|
content = files.length ? `# Docs (${files.length})
|
|
@@ -69812,7 +70274,7 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
69812
70274
|
return;
|
|
69813
70275
|
}
|
|
69814
70276
|
try {
|
|
69815
|
-
const target =
|
|
70277
|
+
const target = path67.join(process.cwd(), ".zelari");
|
|
69816
70278
|
await fs38.rm(target, { recursive: true, force: true });
|
|
69817
70279
|
appendSystem(ctx.setMessages, "[workspace] .zelari/ removed");
|
|
69818
70280
|
} catch (err) {
|
|
@@ -69824,7 +70286,7 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
69824
70286
|
init_provider2();
|
|
69825
70287
|
|
|
69826
70288
|
// src/cli/slashHandlers/skills.ts
|
|
69827
|
-
import
|
|
70289
|
+
import path68 from "node:path";
|
|
69828
70290
|
import os14 from "node:os";
|
|
69829
70291
|
|
|
69830
70292
|
// src/cli/skillHistory.ts
|
|
@@ -69953,7 +70415,7 @@ function handleSkillPicker(ctx, skills, openPicker, fallbackMessage) {
|
|
|
69953
70415
|
});
|
|
69954
70416
|
}
|
|
69955
70417
|
async function handleSkillStats(ctx, skillId) {
|
|
69956
|
-
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ??
|
|
70418
|
+
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ?? path68.join(os14.homedir(), ".tmp", "zelari-code", "skill-history.jsonl");
|
|
69957
70419
|
try {
|
|
69958
70420
|
const records = await readSkillHistory(historyFile);
|
|
69959
70421
|
const stats = getSkillStats(records, skillId);
|
|
@@ -69969,7 +70431,7 @@ async function handleSkillCompare(ctx, ids, fallbackMessage) {
|
|
|
69969
70431
|
appendSystem(ctx.setMessages, fallbackMessage ?? "[skill-compare] missing args");
|
|
69970
70432
|
return;
|
|
69971
70433
|
}
|
|
69972
|
-
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ??
|
|
70434
|
+
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ?? path68.join(os14.homedir(), ".tmp", "zelari-code", "skill-history.jsonl");
|
|
69973
70435
|
try {
|
|
69974
70436
|
const formatted = await compareSkillsFromFile(ids[0], ids[1], historyFile);
|
|
69975
70437
|
appendSystem(ctx.setMessages, formatted);
|
|
@@ -71484,6 +71946,54 @@ init_candidateRegistry();
|
|
|
71484
71946
|
init_metrics2();
|
|
71485
71947
|
init_completionGate();
|
|
71486
71948
|
init_delegationPolicy();
|
|
71949
|
+
|
|
71950
|
+
// src/cli/orchestration/policy.ts
|
|
71951
|
+
var DEFAULT_MAX_SOLO_CHARS = 300;
|
|
71952
|
+
var KRAKEN_SIGNALS = [
|
|
71953
|
+
{ re: /\bimplement(?:s|ed|ing)?\b/i, reason: "implementation signal" },
|
|
71954
|
+
{ re: /\brefactor(?:ing|ed)?\b/i, reason: "refactor signal" },
|
|
71955
|
+
{ re: /\bmigrat(?:e|es|ed|ion|ing)\b/i, reason: "migration signal" },
|
|
71956
|
+
{
|
|
71957
|
+
re: /\b(?:add|build|create|introduce)\b[^.?!]{0,48}\b(?:feature|endpoint|module|service|command|api|registry|runtime)\b/i,
|
|
71958
|
+
reason: "new-capability signal"
|
|
71959
|
+
},
|
|
71960
|
+
{
|
|
71961
|
+
re: /\b(?:unit|integration|e2e|end-to-end)\s+(?:tests?|testing|specs?)\b|\bwrite\s+(?:the\s+|some\s+)?tests?\b/i,
|
|
71962
|
+
reason: "test-writing signal"
|
|
71963
|
+
},
|
|
71964
|
+
{
|
|
71965
|
+
re: /\b\d+\s*-?\s*(?:files?|modules?|packages?|components?|services?|endpoints?|worktrees?)\b/i,
|
|
71966
|
+
reason: "multi-artifact count"
|
|
71967
|
+
},
|
|
71968
|
+
{
|
|
71969
|
+
re: /\b(?:across|spanning|between|touching)\s+(?:all\s+|the\s+)?(?:\w+\s+){0,2}(?:files|modules|packages|layers|surfaces)\b/i,
|
|
71970
|
+
reason: "cross-cutting scope"
|
|
71971
|
+
}
|
|
71972
|
+
];
|
|
71973
|
+
var QUESTION_RE = /\?\s*$|^(?:who|what|why|when|where|which|how|is|are|was|were|does|do|did|can|could|should|would|will)\b/i;
|
|
71974
|
+
var EXPLAIN_RE = /\b(?:explain|describe|summarize|summarise|clarify|walk\W*me\W*through)\b/i;
|
|
71975
|
+
var READONLY_RE = /\b(?:find|show|list|grep|search|locate|inspect|read|check|review|where\W+is)\b/i;
|
|
71976
|
+
function chooseOrchestration(task, opts = {}) {
|
|
71977
|
+
const text = String(task ?? "").trim();
|
|
71978
|
+
const failClosed = () => ({
|
|
71979
|
+
surface: "solo",
|
|
71980
|
+
reason: "fail-closed default"
|
|
71981
|
+
});
|
|
71982
|
+
if (!text) return failClosed();
|
|
71983
|
+
for (const { re, reason } of KRAKEN_SIGNALS) {
|
|
71984
|
+
if (re.test(text)) return { surface: "kraken", reason };
|
|
71985
|
+
}
|
|
71986
|
+
if (QUESTION_RE.test(text)) return { surface: "solo", reason: "question-shaped task" };
|
|
71987
|
+
if (EXPLAIN_RE.test(text)) return { surface: "solo", reason: "explanation request" };
|
|
71988
|
+
if (READONLY_RE.test(text)) return { surface: "solo", reason: "read-only request" };
|
|
71989
|
+
const budget = opts.maxSoloChars ?? DEFAULT_MAX_SOLO_CHARS;
|
|
71990
|
+
if (text.length <= budget) {
|
|
71991
|
+
return { surface: "solo", reason: "small task, no heavy signals" };
|
|
71992
|
+
}
|
|
71993
|
+
return failClosed();
|
|
71994
|
+
}
|
|
71995
|
+
|
|
71996
|
+
// src/cli/runHeadless.ts
|
|
71487
71997
|
init_headless();
|
|
71488
71998
|
init_claudeProvider();
|
|
71489
71999
|
init_skills2();
|
|
@@ -71522,12 +72032,13 @@ function createStreamScrubber2() {
|
|
|
71522
72032
|
init_taskTool();
|
|
71523
72033
|
init_sessionTodos();
|
|
71524
72034
|
import { promises as fs41 } from "node:fs";
|
|
71525
|
-
import
|
|
72035
|
+
import path70 from "node:path";
|
|
71526
72036
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
71527
72037
|
|
|
71528
72038
|
// src/cli/kraken/verifierLifecycle.ts
|
|
71529
72039
|
init_verification2();
|
|
71530
72040
|
init_krakenSelectTool();
|
|
72041
|
+
init_krakenModel();
|
|
71531
72042
|
|
|
71532
72043
|
// src/cli/kraken/verifierResolution.ts
|
|
71533
72044
|
init_providerConfig();
|
|
@@ -71571,18 +72082,61 @@ function makeVerifierCallModel(loadStream, identity, timeoutMs2 = 12e4) {
|
|
|
71571
72082
|
return { text, provider: identity.provider, model: identity.model };
|
|
71572
72083
|
};
|
|
71573
72084
|
}
|
|
71574
|
-
function resolveIdentity(selection, session) {
|
|
72085
|
+
function resolveIdentity(selection, session, familyCandidates, env = process.env) {
|
|
71575
72086
|
if (selection.mode === "fixed") {
|
|
71576
72087
|
return { provider: selection.provider, model: selection.model };
|
|
71577
72088
|
}
|
|
71578
|
-
|
|
72089
|
+
if (!session || !session.provider || !session.model) return null;
|
|
72090
|
+
if (familyCandidates && familyCandidates.length > 0) {
|
|
72091
|
+
const cross = resolveCrossModelVerifier(session, familyCandidates, env);
|
|
72092
|
+
if (cross) return { provider: cross.provider, model: cross.model };
|
|
72093
|
+
}
|
|
72094
|
+
return session;
|
|
72095
|
+
}
|
|
72096
|
+
function isTestEvidenceCriterion(criterionId2) {
|
|
72097
|
+
const id3 = criterionId2.toLowerCase();
|
|
72098
|
+
return ["test", "typecheck", "build", "lint"].some((k) => id3.includes(k));
|
|
72099
|
+
}
|
|
72100
|
+
function extractTestOutputExcerpt(results, maxChars = 4e3) {
|
|
72101
|
+
const lines = [];
|
|
72102
|
+
for (const r of results) {
|
|
72103
|
+
if (!isTestEvidenceCriterion(r.criterionId)) continue;
|
|
72104
|
+
lines.push([r.criterionId, r.status, r.detail].filter(Boolean).join(" \u2014 "));
|
|
72105
|
+
}
|
|
72106
|
+
if (lines.length === 0) return "";
|
|
72107
|
+
return lines.join("\n").slice(0, maxChars);
|
|
72108
|
+
}
|
|
72109
|
+
async function buildBlindReviewInput(evaluation, deps) {
|
|
72110
|
+
const results = evaluation.results ?? [];
|
|
72111
|
+
const passed = results.filter((r) => r.status === "pass").length;
|
|
72112
|
+
const verdict = evaluation.evaluation?.verdict ?? "UNKNOWN";
|
|
72113
|
+
const summary = `Kraken BUILD turn \u2014 deterministic evidence: ${passed}/${results.length} criteria pass, completion verdict ${verdict}.`;
|
|
72114
|
+
const task = deps.task?.trim();
|
|
72115
|
+
const testOutputExcerpt = extractTestOutputExcerpt(results);
|
|
72116
|
+
let diffSummary;
|
|
72117
|
+
try {
|
|
72118
|
+
const res = await (deps.getDiff ?? getWorkingDiff)({
|
|
72119
|
+
cwd: deps.cwd ?? process.cwd(),
|
|
72120
|
+
maxChars: 8e3,
|
|
72121
|
+
staged: true
|
|
72122
|
+
});
|
|
72123
|
+
if (res && !res.empty && res.diff) diffSummary = res.diff;
|
|
72124
|
+
} catch {
|
|
72125
|
+
}
|
|
72126
|
+
return {
|
|
72127
|
+
...task ? { task } : {},
|
|
72128
|
+
summary,
|
|
72129
|
+
...diffSummary !== void 0 ? { diffSummary } : {},
|
|
72130
|
+
...testOutputExcerpt ? { testOutputExcerpt } : {},
|
|
72131
|
+
results
|
|
72132
|
+
};
|
|
71579
72133
|
}
|
|
71580
72134
|
async function runAdvisoryVerifierReview(evaluation, deps = {}) {
|
|
71581
72135
|
if (!evaluation.evaluation || !evaluation.results) return null;
|
|
71582
72136
|
const env = deps.env ?? process.env;
|
|
71583
72137
|
const selection = deps.selection ?? loadVerifierModelSelection();
|
|
71584
72138
|
if (!verifierReviewEnabled(selection, env)) return null;
|
|
71585
|
-
const identity = resolveIdentity(selection, deps.session);
|
|
72139
|
+
const identity = resolveIdentity(selection, deps.session, deps.familyCandidates, env);
|
|
71586
72140
|
let callModel = deps.callModel;
|
|
71587
72141
|
if (!callModel) {
|
|
71588
72142
|
if (!identity || !deps.loadStream) return null;
|
|
@@ -71599,11 +72153,9 @@ async function runAdvisoryVerifierReview(evaluation, deps = {}) {
|
|
|
71599
72153
|
emit: deps.emit,
|
|
71600
72154
|
env
|
|
71601
72155
|
});
|
|
71602
|
-
const
|
|
71603
|
-
const summary = `Kraken BUILD turn \u2014 deterministic evidence: ${passed}/${evaluation.results.length} criteria pass, completion verdict ${evaluation.evaluation.verdict}.`;
|
|
72156
|
+
const blind = await buildBlindReviewInput(evaluation, deps);
|
|
71604
72157
|
const review = await service.reviewCompletion({
|
|
71605
|
-
|
|
71606
|
-
results: evaluation.results,
|
|
72158
|
+
...blind,
|
|
71607
72159
|
session: deps.session
|
|
71608
72160
|
});
|
|
71609
72161
|
evaluation.review = review;
|
|
@@ -71917,6 +72469,13 @@ ${err.stack}` : "";
|
|
|
71917
72469
|
model
|
|
71918
72470
|
});
|
|
71919
72471
|
}
|
|
72472
|
+
if (opts.orchestrationAuto) {
|
|
72473
|
+
const verdict = chooseOrchestration(opts.task ?? "");
|
|
72474
|
+
const line = `[orchestration] --mode auto -> surface=${verdict.surface} (${verdict.reason})`;
|
|
72475
|
+
if (opts.output === "json") emitEvent({ type: "log", message: line });
|
|
72476
|
+
else process.stderr.write(`[zelari-code --headless] ${line}
|
|
72477
|
+
`);
|
|
72478
|
+
}
|
|
71920
72479
|
const mode = opts.mode ?? (opts.useCouncil ? "council" : "kraken");
|
|
71921
72480
|
const profileId = resolveHeadlessProfileId(mode, opts.profile);
|
|
71922
72481
|
if (opts.output === "json") {
|
|
@@ -71990,7 +72549,7 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
71990
72549
|
try {
|
|
71991
72550
|
let preflightGraph;
|
|
71992
72551
|
if (opts.runPlan && opts.runPlan.trim() !== "") {
|
|
71993
|
-
const planPath =
|
|
72552
|
+
const planPath = path70.join(cwd, ".zelari", "radio", `plan-${opts.runPlan}.json`);
|
|
71994
72553
|
log(`loading pre-flight plan: ${planPath}`);
|
|
71995
72554
|
let raw;
|
|
71996
72555
|
try {
|
|
@@ -72030,8 +72589,8 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
72030
72589
|
log(formatKrakenGraphAscii2(graph));
|
|
72031
72590
|
if (opts.planOnly) {
|
|
72032
72591
|
const planId = randomUUID8();
|
|
72033
|
-
const planDir =
|
|
72034
|
-
const planPath =
|
|
72592
|
+
const planDir = path70.join(cwd, ".zelari", "radio");
|
|
72593
|
+
const planPath = path70.join(planDir, `plan-${planId}.json`);
|
|
72035
72594
|
await fs41.mkdir(planDir, { recursive: true });
|
|
72036
72595
|
await fs41.writeFile(
|
|
72037
72596
|
planPath,
|
|
@@ -72059,6 +72618,18 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
72059
72618
|
root: cwd,
|
|
72060
72619
|
audit,
|
|
72061
72620
|
sessionId: sessionId2,
|
|
72621
|
+
// P0.4 capability inheritance: tentacles intersect the headless
|
|
72622
|
+
// parent policy. Headless runs are auto-allow (the same literal
|
|
72623
|
+
// the main headless registry below uses), so this is a no-op
|
|
72624
|
+
// today — wired for correctness if that default ever tightens.
|
|
72625
|
+
parentPolicy: {
|
|
72626
|
+
read: "allow",
|
|
72627
|
+
write: "allow",
|
|
72628
|
+
execute: "allow",
|
|
72629
|
+
network: "allow",
|
|
72630
|
+
ui: "allow",
|
|
72631
|
+
auto: true
|
|
72632
|
+
},
|
|
72062
72633
|
// Anchor every tentacle to the SAME provider/model this run
|
|
72063
72634
|
// resolved (Desktop's selector, or --provider/--model), instead
|
|
72064
72635
|
// of the persisted provider.json default the factory falls back
|
|
@@ -72151,6 +72722,12 @@ async function registerHeadlessMcp(toolRegistry, opts) {
|
|
|
72151
72722
|
}
|
|
72152
72723
|
}
|
|
72153
72724
|
}
|
|
72725
|
+
function writeProofSafe(gate, meta3, baseDir = process.cwd()) {
|
|
72726
|
+
return writeCompletionProof(gate, { baseDir, meta: meta3 }).then(
|
|
72727
|
+
() => void 0,
|
|
72728
|
+
() => void 0
|
|
72729
|
+
);
|
|
72730
|
+
}
|
|
72154
72731
|
async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
72155
72732
|
const sessionId2 = crypto.randomUUID();
|
|
72156
72733
|
const memoryFactory = await Promise.resolve().then(() => (init_serviceFactory(), serviceFactory_exports));
|
|
@@ -72489,6 +73066,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
72489
73066
|
let strictExit = 0;
|
|
72490
73067
|
const verifierReviewDeps = {
|
|
72491
73068
|
session: { provider, model },
|
|
73069
|
+
task: effectiveTask,
|
|
72492
73070
|
loadStream: async (providerId, modelId) => {
|
|
72493
73071
|
if (providerId === provider) return providerStream;
|
|
72494
73072
|
try {
|
|
@@ -72516,6 +73094,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
72516
73094
|
if (opts.output === "json") {
|
|
72517
73095
|
emitEvent({ type: "verification_run", ...verificationPayload });
|
|
72518
73096
|
}
|
|
73097
|
+
await writeProofSafe(strictGate, { surface: "kraken", sessionId: spine.sessionId });
|
|
72519
73098
|
if (strictGate.blocked) {
|
|
72520
73099
|
const repairPrompt = buildKrakenRepairPrompt(gate);
|
|
72521
73100
|
if (opts.output === "json") {
|
|
@@ -72549,6 +73128,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
72549
73128
|
if (opts.output === "json") {
|
|
72550
73129
|
emitEvent({ type: "verification_run", ...afterPayload });
|
|
72551
73130
|
}
|
|
73131
|
+
await writeProofSafe(after, { surface: "kraken", sessionId: spine.sessionId });
|
|
72552
73132
|
if (!after.blocked) markRepairSucceeded();
|
|
72553
73133
|
else {
|
|
72554
73134
|
strictExit = strictGateExitCode(after);
|
|
@@ -72582,7 +73162,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
72582
73162
|
if (json3) {
|
|
72583
73163
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
72584
73164
|
else {
|
|
72585
|
-
await fs41.mkdir(
|
|
73165
|
+
await fs41.mkdir(path70.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
72586
73166
|
await fs41.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
72587
73167
|
}
|
|
72588
73168
|
}
|
|
@@ -72811,7 +73391,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
|
|
|
72811
73391
|
if (json3) {
|
|
72812
73392
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
72813
73393
|
else {
|
|
72814
|
-
await fs41.mkdir(
|
|
73394
|
+
await fs41.mkdir(path70.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
72815
73395
|
await fs41.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
72816
73396
|
}
|
|
72817
73397
|
}
|
|
@@ -73191,6 +73771,7 @@ ${ragContext}` : slicePrompt;
|
|
|
73191
73771
|
if (opts.output === "json") {
|
|
73192
73772
|
emitEvent({ type: "verification_run", ...missionVerificationPayload });
|
|
73193
73773
|
}
|
|
73774
|
+
await writeProofSafe(missionGate, { surface: "mission", sessionId: spine.sessionId }, projectRoot);
|
|
73194
73775
|
if (missionGate.blocked) {
|
|
73195
73776
|
exitCode = strictGateExitCode(missionGate);
|
|
73196
73777
|
spine.missionPhase("verification", "mission-strict-blocked");
|
|
@@ -73225,7 +73806,7 @@ ${ragContext}` : slicePrompt;
|
|
|
73225
73806
|
if (json3) {
|
|
73226
73807
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
73227
73808
|
else {
|
|
73228
|
-
await fs41.mkdir(
|
|
73809
|
+
await fs41.mkdir(path70.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
73229
73810
|
await fs41.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
73230
73811
|
}
|
|
73231
73812
|
}
|
|
@@ -73427,8 +74008,8 @@ function normalizeDraft(raw, sourceUrl, provider, model) {
|
|
|
73427
74008
|
let name = String(o.name ?? "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
73428
74009
|
if (!name || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) {
|
|
73429
74010
|
try {
|
|
73430
|
-
const
|
|
73431
|
-
name =
|
|
74011
|
+
const path74 = new URL(sourceUrl).pathname.split("/").filter(Boolean).pop()?.replace(/\.[a-z0-9]+$/i, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
74012
|
+
name = path74 && /^[a-z0-9]/.test(path74) ? path74 : "imported-skill";
|
|
73432
74013
|
} catch {
|
|
73433
74014
|
name = "imported-skill";
|
|
73434
74015
|
}
|