zelari-code 2.37.0 → 2.37.2
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/runOneTurn.js +15 -5
- package/dist/cli/headless/runOneTurn.js.map +1 -1
- package/dist/cli/headless.js +11 -0
- package/dist/cli/headless.js.map +1 -1
- package/dist/cli/headlessSpine.js +26 -0
- package/dist/cli/headlessSpine.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +12 -3
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/kraken/completionGate.js +78 -1
- package/dist/cli/kraken/completionGate.js.map +1 -1
- package/dist/cli/kraken/verificationBridge.js +153 -32
- package/dist/cli/kraken/verificationBridge.js.map +1 -1
- package/dist/cli/kraken/verifyReport.js.map +1 -1
- package/dist/cli/main.bundled.js +661 -387
- package/dist/cli/main.bundled.js.map +3 -3
- package/dist/cli/main.js +1 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/provider/capabilities.js +14 -0
- package/dist/cli/provider/capabilities.js.map +1 -1
- package/dist/cli/provider/openai-compatible.js +244 -58
- package/dist/cli/provider/openai-compatible.js.map +1 -1
- package/dist/cli/runHeadless.js +16 -1
- package/dist/cli/runHeadless.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -3482,10 +3482,10 @@ function mergeDefs(...defs) {
|
|
|
3482
3482
|
function cloneDef(schema) {
|
|
3483
3483
|
return mergeDefs(schema._zod.def);
|
|
3484
3484
|
}
|
|
3485
|
-
function getElementAtPath(obj,
|
|
3486
|
-
if (!
|
|
3485
|
+
function getElementAtPath(obj, path101) {
|
|
3486
|
+
if (!path101)
|
|
3487
3487
|
return obj;
|
|
3488
|
-
return
|
|
3488
|
+
return path101.reduce((acc, key) => acc?.[key], obj);
|
|
3489
3489
|
}
|
|
3490
3490
|
function promiseAllObject(promisesObj) {
|
|
3491
3491
|
const keys = Object.keys(promisesObj);
|
|
@@ -3813,11 +3813,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
3813
3813
|
}
|
|
3814
3814
|
return false;
|
|
3815
3815
|
}
|
|
3816
|
-
function prefixIssues(
|
|
3816
|
+
function prefixIssues(path101, issues) {
|
|
3817
3817
|
return issues.map((iss) => {
|
|
3818
3818
|
var _a3;
|
|
3819
3819
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
3820
|
-
iss.path.unshift(
|
|
3820
|
+
iss.path.unshift(path101);
|
|
3821
3821
|
return iss;
|
|
3822
3822
|
});
|
|
3823
3823
|
}
|
|
@@ -4035,16 +4035,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4035
4035
|
}
|
|
4036
4036
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
4037
4037
|
const fieldErrors = { _errors: [] };
|
|
4038
|
-
const processError = (error52,
|
|
4038
|
+
const processError = (error52, path101 = []) => {
|
|
4039
4039
|
for (const issue2 of error52.issues) {
|
|
4040
4040
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
4041
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
4041
|
+
issue2.errors.map((issues) => processError({ issues }, [...path101, ...issue2.path]));
|
|
4042
4042
|
} else if (issue2.code === "invalid_key") {
|
|
4043
|
-
processError({ issues: issue2.issues }, [...
|
|
4043
|
+
processError({ issues: issue2.issues }, [...path101, ...issue2.path]);
|
|
4044
4044
|
} else if (issue2.code === "invalid_element") {
|
|
4045
|
-
processError({ issues: issue2.issues }, [...
|
|
4045
|
+
processError({ issues: issue2.issues }, [...path101, ...issue2.path]);
|
|
4046
4046
|
} else {
|
|
4047
|
-
const fullpath = [...
|
|
4047
|
+
const fullpath = [...path101, ...issue2.path];
|
|
4048
4048
|
if (fullpath.length === 0) {
|
|
4049
4049
|
fieldErrors._errors.push(mapper(issue2));
|
|
4050
4050
|
} else {
|
|
@@ -4071,17 +4071,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4071
4071
|
}
|
|
4072
4072
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
4073
4073
|
const result = { errors: [] };
|
|
4074
|
-
const processError = (error52,
|
|
4074
|
+
const processError = (error52, path101 = []) => {
|
|
4075
4075
|
var _a3, _b;
|
|
4076
4076
|
for (const issue2 of error52.issues) {
|
|
4077
4077
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
4078
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
4078
|
+
issue2.errors.map((issues) => processError({ issues }, [...path101, ...issue2.path]));
|
|
4079
4079
|
} else if (issue2.code === "invalid_key") {
|
|
4080
|
-
processError({ issues: issue2.issues }, [...
|
|
4080
|
+
processError({ issues: issue2.issues }, [...path101, ...issue2.path]);
|
|
4081
4081
|
} else if (issue2.code === "invalid_element") {
|
|
4082
|
-
processError({ issues: issue2.issues }, [...
|
|
4082
|
+
processError({ issues: issue2.issues }, [...path101, ...issue2.path]);
|
|
4083
4083
|
} else {
|
|
4084
|
-
const fullpath = [...
|
|
4084
|
+
const fullpath = [...path101, ...issue2.path];
|
|
4085
4085
|
if (fullpath.length === 0) {
|
|
4086
4086
|
result.errors.push(mapper(issue2));
|
|
4087
4087
|
continue;
|
|
@@ -4113,8 +4113,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4113
4113
|
}
|
|
4114
4114
|
function toDotPath(_path) {
|
|
4115
4115
|
const segs = [];
|
|
4116
|
-
const
|
|
4117
|
-
for (const seg of
|
|
4116
|
+
const path101 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
4117
|
+
for (const seg of path101) {
|
|
4118
4118
|
if (typeof seg === "number")
|
|
4119
4119
|
segs.push(`[${seg}]`);
|
|
4120
4120
|
else if (typeof seg === "symbol")
|
|
@@ -17617,13 +17617,13 @@ function resolveRef(ref, ctx) {
|
|
|
17617
17617
|
if (!ref.startsWith("#")) {
|
|
17618
17618
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
17619
17619
|
}
|
|
17620
|
-
const
|
|
17621
|
-
if (
|
|
17620
|
+
const path101 = ref.slice(1).split("/").filter(Boolean);
|
|
17621
|
+
if (path101.length === 0) {
|
|
17622
17622
|
return ctx.rootSchema;
|
|
17623
17623
|
}
|
|
17624
17624
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
17625
|
-
if (
|
|
17626
|
-
const key =
|
|
17625
|
+
if (path101[0] === defsKey) {
|
|
17626
|
+
const key = path101[1];
|
|
17627
17627
|
if (!key || !ctx.defs[key]) {
|
|
17628
17628
|
throw new Error(`Reference not found: ${ref}`);
|
|
17629
17629
|
}
|
|
@@ -18457,17 +18457,17 @@ var init_newlines = __esm({
|
|
|
18457
18457
|
});
|
|
18458
18458
|
|
|
18459
18459
|
// packages/core/dist/core/tools/builtin/fileEvents.js
|
|
18460
|
-
function fileReadEvent(
|
|
18461
|
-
return { kind: "file.read", actor: { type: "tool" }, data: { path:
|
|
18460
|
+
function fileReadEvent(path101, snapshotId) {
|
|
18461
|
+
return { kind: "file.read", actor: { type: "tool" }, data: { path: path101, snapshotId } };
|
|
18462
18462
|
}
|
|
18463
|
-
function fileAppliedEvent(
|
|
18464
|
-
return { kind: "file.applied", actor: { type: "tool" }, data: { path:
|
|
18463
|
+
function fileAppliedEvent(path101, snapshotId, bytes) {
|
|
18464
|
+
return { kind: "file.applied", actor: { type: "tool" }, data: { path: path101, snapshotId, bytes } };
|
|
18465
18465
|
}
|
|
18466
|
-
function fileRejectedEvent(
|
|
18466
|
+
function fileRejectedEvent(path101, reason, hint) {
|
|
18467
18467
|
return {
|
|
18468
18468
|
kind: "file.rejected",
|
|
18469
18469
|
actor: { type: "tool" },
|
|
18470
|
-
data: hint === void 0 ? { path:
|
|
18470
|
+
data: hint === void 0 ? { path: path101, reason } : { path: path101, reason, hint }
|
|
18471
18471
|
};
|
|
18472
18472
|
}
|
|
18473
18473
|
function reReadHint(reject) {
|
|
@@ -20336,11 +20336,11 @@ var init_tools = __esm({
|
|
|
20336
20336
|
if (!ctx.addDocument)
|
|
20337
20337
|
return "Knowledge vault tool not available.";
|
|
20338
20338
|
const title = args["title"] || "New Document";
|
|
20339
|
-
const
|
|
20339
|
+
const path101 = args["path"] || `notes/${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
|
|
20340
20340
|
const content = args["content"] || "";
|
|
20341
20341
|
const tags = args["tags"] || [];
|
|
20342
20342
|
ctx.addDocument({
|
|
20343
|
-
path:
|
|
20343
|
+
path: path101,
|
|
20344
20344
|
title,
|
|
20345
20345
|
content,
|
|
20346
20346
|
format: "markdown",
|
|
@@ -20349,7 +20349,7 @@ var init_tools = __esm({
|
|
|
20349
20349
|
workspaceId: ctx.workspaceId
|
|
20350
20350
|
});
|
|
20351
20351
|
ctx.addActivity("vault", "created document", title);
|
|
20352
|
-
return `Document "${title}" created at "${
|
|
20352
|
+
return `Document "${title}" created at "${path101}".`;
|
|
20353
20353
|
}
|
|
20354
20354
|
}
|
|
20355
20355
|
];
|
|
@@ -22036,7 +22036,20 @@ function evaluateKrakenCompletionGate(mode) {
|
|
|
22036
22036
|
};
|
|
22037
22037
|
}
|
|
22038
22038
|
}
|
|
22039
|
-
function
|
|
22039
|
+
function excerptEntries(excerpts) {
|
|
22040
|
+
if (!excerpts) return [];
|
|
22041
|
+
return excerpts instanceof Map ? [...excerpts.entries()] : Object.entries(excerpts);
|
|
22042
|
+
}
|
|
22043
|
+
function excerptBlock(name, raw) {
|
|
22044
|
+
const trimmed = raw.trim();
|
|
22045
|
+
const truncated = trimmed.length > REPAIR_FAIL_EXCERPT_CAP;
|
|
22046
|
+
const tail2 = truncated ? trimmed.slice(trimmed.length - REPAIR_FAIL_EXCERPT_CAP) : trimmed;
|
|
22047
|
+
const lines = [`Failure excerpt (tail, capped ${REPAIR_FAIL_EXCERPT_CAP} chars) \u2014 ${name}:`];
|
|
22048
|
+
if (truncated) lines.push(`\u2026[truncated ${trimmed.length - REPAIR_FAIL_EXCERPT_CAP} chars]`);
|
|
22049
|
+
lines.push(tail2, "");
|
|
22050
|
+
return lines;
|
|
22051
|
+
}
|
|
22052
|
+
function buildKrakenRepairPrompt(gate, excerpts) {
|
|
22040
22053
|
const lines = [
|
|
22041
22054
|
`The BUILD turn is ending, but the required checks from kraken_select are not all satisfied (passed ${gate.passed}/${gate.total}).`,
|
|
22042
22055
|
""
|
|
@@ -22053,6 +22066,36 @@ function buildKrakenRepairPrompt(gate) {
|
|
|
22053
22066
|
for (const check2 of gate.unknownChecks) lines.push(`- ${check2}`);
|
|
22054
22067
|
lines.push("");
|
|
22055
22068
|
}
|
|
22069
|
+
const entries = excerptEntries(excerpts);
|
|
22070
|
+
if (entries.length > 0) {
|
|
22071
|
+
const byName = new Map(entries);
|
|
22072
|
+
const used = /* @__PURE__ */ new Set();
|
|
22073
|
+
const blocks = [];
|
|
22074
|
+
let emitted = 0;
|
|
22075
|
+
for (const check2 of [...gate.failedChecks, ...gate.unknownChecks]) {
|
|
22076
|
+
if (emitted >= MAX_REPAIR_EXCERPTS) break;
|
|
22077
|
+
const raw = byName.get(check2);
|
|
22078
|
+
if (raw === void 0 || used.has(check2)) continue;
|
|
22079
|
+
used.add(check2);
|
|
22080
|
+
blocks.push(excerptBlock(check2, raw));
|
|
22081
|
+
emitted += 1;
|
|
22082
|
+
}
|
|
22083
|
+
let leadInPushed = false;
|
|
22084
|
+
for (const [name, raw] of entries) {
|
|
22085
|
+
if (emitted >= MAX_REPAIR_EXCERPTS) break;
|
|
22086
|
+
if (used.has(name)) continue;
|
|
22087
|
+
if (!leadInPushed) {
|
|
22088
|
+
blocks.push([
|
|
22089
|
+
"DETERMINISTIC check failures with captured output (criteria pack / task contract):",
|
|
22090
|
+
""
|
|
22091
|
+
]);
|
|
22092
|
+
leadInPushed = true;
|
|
22093
|
+
}
|
|
22094
|
+
blocks.push(excerptBlock(name, raw));
|
|
22095
|
+
emitted += 1;
|
|
22096
|
+
}
|
|
22097
|
+
for (const block of blocks) lines.push(...block);
|
|
22098
|
+
}
|
|
22056
22099
|
lines.push(
|
|
22057
22100
|
"Recover this turn:",
|
|
22058
22101
|
"1. The approach selection is settled \u2014 do NOT call kraken_select again.",
|
|
@@ -22063,7 +22106,7 @@ function buildKrakenRepairPrompt(gate) {
|
|
|
22063
22106
|
);
|
|
22064
22107
|
return lines.join("\n");
|
|
22065
22108
|
}
|
|
22066
|
-
var OPEN_GATE;
|
|
22109
|
+
var OPEN_GATE, REPAIR_FAIL_EXCERPT_CAP, MAX_REPAIR_EXCERPTS;
|
|
22067
22110
|
var init_completionGate = __esm({
|
|
22068
22111
|
"src/cli/kraken/completionGate.ts"() {
|
|
22069
22112
|
"use strict";
|
|
@@ -22076,6 +22119,8 @@ var init_completionGate = __esm({
|
|
|
22076
22119
|
failedChecks: [],
|
|
22077
22120
|
unknownChecks: []
|
|
22078
22121
|
};
|
|
22122
|
+
REPAIR_FAIL_EXCERPT_CAP = 2e3;
|
|
22123
|
+
MAX_REPAIR_EXCERPTS = 5;
|
|
22079
22124
|
}
|
|
22080
22125
|
});
|
|
22081
22126
|
|
|
@@ -25174,16 +25219,16 @@ function runRetentionFromEnv() {
|
|
|
25174
25219
|
maxTotalBytes: Number.isFinite(parseMb) && parseMb > 0 ? Math.round(parseMb * 1024 * 1024) : DEFAULT_RUN_RETENTION_MAX_MB * 1024 * 1024
|
|
25175
25220
|
};
|
|
25176
25221
|
}
|
|
25177
|
-
async function dirSize(
|
|
25222
|
+
async function dirSize(path101) {
|
|
25178
25223
|
let total = 0;
|
|
25179
25224
|
let entries;
|
|
25180
25225
|
try {
|
|
25181
|
-
entries = await readdir(
|
|
25226
|
+
entries = await readdir(path101, { withFileTypes: true });
|
|
25182
25227
|
} catch {
|
|
25183
25228
|
return 0;
|
|
25184
25229
|
}
|
|
25185
25230
|
for (const entry of entries) {
|
|
25186
|
-
const child = join3(
|
|
25231
|
+
const child = join3(path101, entry.name);
|
|
25187
25232
|
if (entry.isDirectory())
|
|
25188
25233
|
total += await dirSize(child);
|
|
25189
25234
|
else {
|
|
@@ -25210,19 +25255,19 @@ async function enforceRunRetention(runsDir, options = {}) {
|
|
|
25210
25255
|
for (const entry of entries) {
|
|
25211
25256
|
if (!entry.isDirectory())
|
|
25212
25257
|
continue;
|
|
25213
|
-
const
|
|
25258
|
+
const path101 = join3(runsDir, entry.name);
|
|
25214
25259
|
let startedAt = 0;
|
|
25215
25260
|
let endedAt;
|
|
25216
25261
|
let completed = false;
|
|
25217
25262
|
try {
|
|
25218
|
-
const manifest = JSON.parse(await readFile(join3(
|
|
25263
|
+
const manifest = JSON.parse(await readFile(join3(path101, "manifest.json"), "utf8"));
|
|
25219
25264
|
startedAt = manifest.startedAt ?? 0;
|
|
25220
25265
|
endedAt = manifest.endedAt;
|
|
25221
25266
|
completed = Boolean(endedAt) && manifest.status !== "running";
|
|
25222
25267
|
} catch {
|
|
25223
25268
|
completed = false;
|
|
25224
25269
|
}
|
|
25225
|
-
infos.push({ name: entry.name, path:
|
|
25270
|
+
infos.push({ name: entry.name, path: path101, startedAt, endedAt, completed, bytes: await dirSize(path101) });
|
|
25226
25271
|
}
|
|
25227
25272
|
const remove = async (info) => {
|
|
25228
25273
|
await rm(info.path, { recursive: true, force: true });
|
|
@@ -25709,12 +25754,12 @@ var init_engine = __esm({
|
|
|
25709
25754
|
* content digest) and the returned ref carries the event seq when the
|
|
25710
25755
|
* emitter resolved one.
|
|
25711
25756
|
*/
|
|
25712
|
-
async fsEvidence(observation,
|
|
25757
|
+
async fsEvidence(observation, path101, sha256, content, extra = {}) {
|
|
25713
25758
|
const digest = sha256 && content !== void 0 ? sha256(content) : void 0;
|
|
25714
|
-
const seq = await this.emitEvidence({ observation, path:
|
|
25759
|
+
const seq = await this.emitEvidence({ observation, path: path101, ...extra, ...digest ? { digest } : {} });
|
|
25715
25760
|
return {
|
|
25716
25761
|
tier: "fs-observation",
|
|
25717
|
-
ref:
|
|
25762
|
+
ref: path101,
|
|
25718
25763
|
capturedAt: Date.now(),
|
|
25719
25764
|
...digest ? { digest } : {},
|
|
25720
25765
|
...seq !== void 0 ? { seq } : {}
|
|
@@ -27184,11 +27229,14 @@ var init_contractCompiler = __esm({
|
|
|
27184
27229
|
var verificationBridge_exports = {};
|
|
27185
27230
|
__export(verificationBridge_exports, {
|
|
27186
27231
|
STRICT_DONE_EXIT_CODE: () => STRICT_DONE_EXIT_CODE,
|
|
27232
|
+
allowUnverified: () => allowUnverified,
|
|
27187
27233
|
anchorSelectionEvidence: () => anchorSelectionEvidence,
|
|
27188
27234
|
evaluateStrictBuildGate: () => evaluateStrictBuildGate,
|
|
27189
27235
|
evaluateStrictBuildGateFromSession: () => evaluateStrictBuildGateFromSession,
|
|
27190
27236
|
krakenResultsToContract: () => krakenResultsToContract,
|
|
27191
27237
|
matchNoteToToolTrace: () => matchNoteToToolTrace,
|
|
27238
|
+
missionClaimExitCode: () => missionClaimExitCode,
|
|
27239
|
+
repairExcerptsFromEvaluation: () => repairExcerptsFromEvaluation,
|
|
27192
27240
|
strictDoneEnabled: () => strictDoneEnabled,
|
|
27193
27241
|
strictEnvOverlay: () => strictEnvOverlay,
|
|
27194
27242
|
strictGateEventPayload: () => strictGateEventPayload,
|
|
@@ -27224,20 +27272,20 @@ function criterionId(check2, index) {
|
|
|
27224
27272
|
function normalize3(text) {
|
|
27225
27273
|
return text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
27226
27274
|
}
|
|
27227
|
-
function matchResult(check2, byNormalized) {
|
|
27228
|
-
|
|
27229
|
-
|
|
27230
|
-
|
|
27231
|
-
for (const key of byNormalized.keys()) {
|
|
27232
|
-
if (key.length >= 8 && (key.includes(norm) || norm.includes(key))) {
|
|
27233
|
-
return byNormalized.get(key);
|
|
27234
|
-
}
|
|
27275
|
+
function matchResult(check2, byNormalized, byId, id3) {
|
|
27276
|
+
if (byId && id3) {
|
|
27277
|
+
const byCriterion = byId.get(id3);
|
|
27278
|
+
if (byCriterion) return byCriterion;
|
|
27235
27279
|
}
|
|
27236
|
-
return
|
|
27280
|
+
return byNormalized.get(normalize3(check2));
|
|
27237
27281
|
}
|
|
27238
27282
|
function krakenResultsToContract(requiredChecks, results, now = Date.now()) {
|
|
27239
27283
|
const byNormalized = /* @__PURE__ */ new Map();
|
|
27240
|
-
|
|
27284
|
+
const byId = /* @__PURE__ */ new Map();
|
|
27285
|
+
for (const r of results ?? []) {
|
|
27286
|
+
byNormalized.set(normalize3(r.check), r);
|
|
27287
|
+
if (r.criterionId) byId.set(r.criterionId, r);
|
|
27288
|
+
}
|
|
27241
27289
|
const criteria = [];
|
|
27242
27290
|
const verifications = [];
|
|
27243
27291
|
requiredChecks.forEach((check2, i) => {
|
|
@@ -27247,12 +27295,12 @@ function krakenResultsToContract(requiredChecks, results, now = Date.now()) {
|
|
|
27247
27295
|
text: check2,
|
|
27248
27296
|
source: "kraken-selection",
|
|
27249
27297
|
required: true,
|
|
27250
|
-
check: { kind: "none", reason: "
|
|
27298
|
+
check: { kind: "none", reason: "verify tentacle proposal \u2014 runtime evidence required" }
|
|
27251
27299
|
});
|
|
27252
|
-
const reported = matchResult(check2, byNormalized);
|
|
27300
|
+
const reported = matchResult(check2, byNormalized, byId, id3);
|
|
27253
27301
|
const evidence = reported?.note && reported.note.trim().length > 0 ? [
|
|
27254
27302
|
{
|
|
27255
|
-
tier: "
|
|
27303
|
+
tier: "verifier-llm",
|
|
27256
27304
|
ref: reported.note.trim().slice(0, 500),
|
|
27257
27305
|
capturedAt: now
|
|
27258
27306
|
}
|
|
@@ -27299,12 +27347,12 @@ async function anchorSelectionEvidence(results, emit, toolTrace) {
|
|
|
27299
27347
|
for (const r of results) {
|
|
27300
27348
|
for (const ev of r.evidence) {
|
|
27301
27349
|
if (ev.seq !== void 0) continue;
|
|
27302
|
-
if (ev.tier === "
|
|
27350
|
+
if (ev.tier === "human") continue;
|
|
27303
27351
|
try {
|
|
27304
27352
|
const match = toolTrace && toolTrace.length > 0 ? matchNoteToToolTrace(ev.ref, toolTrace) : null;
|
|
27305
27353
|
if (match) {
|
|
27306
27354
|
const digest = sha256Hex2(match.output);
|
|
27307
|
-
const
|
|
27355
|
+
const appended = await emit({
|
|
27308
27356
|
kind: "verification.evidence",
|
|
27309
27357
|
actor: { type: "system", role: "verification" },
|
|
27310
27358
|
data: {
|
|
@@ -27320,16 +27368,17 @@ async function anchorSelectionEvidence(results, emit, toolTrace) {
|
|
|
27320
27368
|
...match.command ? { command: match.command } : {}
|
|
27321
27369
|
}
|
|
27322
27370
|
});
|
|
27323
|
-
const toolSeq =
|
|
27371
|
+
const toolSeq = appended && typeof appended === "object" && "seq" in appended ? Number(appended.seq) : NaN;
|
|
27324
27372
|
if (Number.isFinite(toolSeq) && toolSeq > 0) {
|
|
27325
27373
|
ev.seq = toolSeq;
|
|
27326
27374
|
ev.digest = digest;
|
|
27375
|
+
ev.tier = "tool-output";
|
|
27327
27376
|
ev.ref = `${match.tool}${match.command ? ` ${match.command}` : ""} \u2192 ${match.ok ? "ok" : "error"} @seq`;
|
|
27328
27377
|
counts.toolResultAnchored += 1;
|
|
27329
27378
|
}
|
|
27330
27379
|
continue;
|
|
27331
27380
|
}
|
|
27332
|
-
|
|
27381
|
+
await emit({
|
|
27333
27382
|
kind: "verification.evidence",
|
|
27334
27383
|
actor: { type: "system", role: "verification" },
|
|
27335
27384
|
data: {
|
|
@@ -27337,14 +27386,11 @@ async function anchorSelectionEvidence(results, emit, toolTrace) {
|
|
|
27337
27386
|
provenance: "note-fallback",
|
|
27338
27387
|
criterionId: r.criterionId,
|
|
27339
27388
|
ref: ev.ref,
|
|
27340
|
-
tier: ev.tier
|
|
27389
|
+
tier: ev.tier,
|
|
27390
|
+
anchored: false
|
|
27341
27391
|
}
|
|
27342
27392
|
});
|
|
27343
|
-
|
|
27344
|
-
if (Number.isFinite(seq) && seq > 0) {
|
|
27345
|
-
ev.seq = seq;
|
|
27346
|
-
counts.noteFallback += 1;
|
|
27347
|
-
}
|
|
27393
|
+
counts.noteFallback += 1;
|
|
27348
27394
|
} catch {
|
|
27349
27395
|
}
|
|
27350
27396
|
}
|
|
@@ -27358,7 +27404,8 @@ async function evaluateStrictBuildGate(mode, options = {}) {
|
|
|
27358
27404
|
const selectionAvailable = gate.selectionUsed && gate.total > 0;
|
|
27359
27405
|
const scopeContract = options.taskContract ?? activeContractScope()?.contract;
|
|
27360
27406
|
const contractPlan = scopeContract ? compileVerificationCriteria(scopeContract) : [];
|
|
27361
|
-
|
|
27407
|
+
const nothingBindable = !selectionAvailable && !nativeOn && contractPlan.length === 0;
|
|
27408
|
+
if (!strictOn && !nativeOn) {
|
|
27362
27409
|
return {
|
|
27363
27410
|
gate,
|
|
27364
27411
|
strict: false,
|
|
@@ -27368,6 +27415,17 @@ async function evaluateStrictBuildGate(mode, options = {}) {
|
|
|
27368
27415
|
summary: gate.blocked ? `blocked: ${gate.failedChecks.length} failed, ${gate.unknownChecks.length} unknown` : "open"
|
|
27369
27416
|
};
|
|
27370
27417
|
}
|
|
27418
|
+
if (nothingBindable) {
|
|
27419
|
+
return {
|
|
27420
|
+
gate,
|
|
27421
|
+
strict: true,
|
|
27422
|
+
unverified: true,
|
|
27423
|
+
evaluation: null,
|
|
27424
|
+
native: null,
|
|
27425
|
+
blocked: true,
|
|
27426
|
+
summary: "unverified (strict on: no criteria \u2014 pack off/unbound, no selection contract, no task contract)"
|
|
27427
|
+
};
|
|
27428
|
+
}
|
|
27371
27429
|
const checks = selectionAvailable ? krakenRequiredChecks() : [];
|
|
27372
27430
|
const contract = selectionAvailable ? krakenResultsToContract(checks, getKrakenCheckResults()) : { criteria: [], results: [] };
|
|
27373
27431
|
const anchoring = await anchorSelectionEvidence(
|
|
@@ -27389,6 +27447,19 @@ async function evaluateStrictBuildGate(mode, options = {}) {
|
|
|
27389
27447
|
const allCriteria = [...contract.criteria, ...native?.criteria ?? [], ...compiled?.criteria ?? []];
|
|
27390
27448
|
const allResults = [...contract.results, ...native?.results ?? [], ...compiled?.results ?? []];
|
|
27391
27449
|
if (allCriteria.length === 0) {
|
|
27450
|
+
if (strictOn) {
|
|
27451
|
+
return {
|
|
27452
|
+
gate,
|
|
27453
|
+
strict: true,
|
|
27454
|
+
unverified: true,
|
|
27455
|
+
evaluation: null,
|
|
27456
|
+
native,
|
|
27457
|
+
compiled,
|
|
27458
|
+
results: allResults,
|
|
27459
|
+
blocked: true,
|
|
27460
|
+
summary: "unverified (strict on: native pack bound no command, no selection contract)"
|
|
27461
|
+
};
|
|
27462
|
+
}
|
|
27392
27463
|
return {
|
|
27393
27464
|
gate,
|
|
27394
27465
|
strict: false,
|
|
@@ -27414,14 +27485,51 @@ async function evaluateStrictBuildGate(mode, options = {}) {
|
|
|
27414
27485
|
summary: blocked ? `blocked (strict ${evaluation?.verdict ?? "n/a"}): ${legacyPart}evidence ${evaluation?.evidenceComplete ? "complete" : "incomplete"}` : `open (strict PASS): ${evaluation?.satisfied.length ?? 0}/${allCriteria.length} criteria pass with evidence`
|
|
27415
27486
|
};
|
|
27416
27487
|
}
|
|
27417
|
-
function
|
|
27418
|
-
|
|
27488
|
+
function repairExcerptsFromEvaluation(evaluation) {
|
|
27489
|
+
const excerpts = /* @__PURE__ */ new Map();
|
|
27490
|
+
const nameById = /* @__PURE__ */ new Map();
|
|
27491
|
+
for (const c of [...evaluation.native?.criteria ?? [], ...evaluation.compiled?.criteria ?? []]) {
|
|
27492
|
+
nameById.set(c.id, c.text);
|
|
27493
|
+
}
|
|
27494
|
+
try {
|
|
27495
|
+
krakenRequiredChecks().forEach((text, i) => {
|
|
27496
|
+
if (!nameById.has(criterionId(text, i))) nameById.set(criterionId(text, i), text);
|
|
27497
|
+
});
|
|
27498
|
+
} catch {
|
|
27499
|
+
}
|
|
27500
|
+
for (const r of evaluation.results ?? []) {
|
|
27501
|
+
if (r.status === "pass") continue;
|
|
27502
|
+
const detail = r.detail?.trim();
|
|
27503
|
+
if (!detail) continue;
|
|
27504
|
+
excerpts.set(nameById.get(r.criterionId) ?? r.criterionId, detail);
|
|
27505
|
+
}
|
|
27506
|
+
return excerpts;
|
|
27507
|
+
}
|
|
27508
|
+
function allowUnverified(env = process.env) {
|
|
27509
|
+
const v = env.ZELARI_ALLOW_UNVERIFIED?.toLowerCase();
|
|
27510
|
+
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
27511
|
+
}
|
|
27512
|
+
function strictGateExitCode(evaluation, env = process.env) {
|
|
27513
|
+
if (evaluation.strict && evaluation.blocked) {
|
|
27514
|
+
if (evaluation.unverified && allowUnverified(env)) return 0;
|
|
27515
|
+
return STRICT_DONE_EXIT_CODE;
|
|
27516
|
+
}
|
|
27517
|
+
return 0;
|
|
27518
|
+
}
|
|
27519
|
+
function missionClaimExitCode(evidenceCount, env = process.env) {
|
|
27520
|
+
if (evidenceCount < 0) return 0;
|
|
27521
|
+
if (evidenceCount > 0) return 0;
|
|
27522
|
+
if (allowUnverified(env)) return 0;
|
|
27523
|
+
return STRICT_DONE_EXIT_CODE;
|
|
27419
27524
|
}
|
|
27420
27525
|
function strictGateEventPayload(evaluation) {
|
|
27421
27526
|
return {
|
|
27422
27527
|
engine: evaluation.native ? "kraken-legacy+completion-policy+criteria-pack" : "kraken-legacy+completion-policy",
|
|
27423
27528
|
strict: evaluation.strict,
|
|
27424
27529
|
verdict: evaluation.evaluation?.verdict ?? (evaluation.blocked ? "BLOCKED" : "PASS"),
|
|
27530
|
+
// M1.2: UNVERIFIED marker — strict on, nothing evaluable. Present only
|
|
27531
|
+
// when true so historical payloads stay byte-identical.
|
|
27532
|
+
...evaluation.unverified ? { unverified: true } : {},
|
|
27425
27533
|
legacy: {
|
|
27426
27534
|
total: evaluation.gate.total,
|
|
27427
27535
|
passed: evaluation.gate.passed,
|
|
@@ -31734,11 +31842,11 @@ var init_synthesisAudit = __esm({
|
|
|
31734
31842
|
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
31735
31843
|
import { join as join5 } from "node:path";
|
|
31736
31844
|
function loadNfrSpec(zelariRoot) {
|
|
31737
|
-
const
|
|
31738
|
-
if (!existsSync10(
|
|
31845
|
+
const path101 = join5(zelariRoot, "nfr-spec.json");
|
|
31846
|
+
if (!existsSync10(path101))
|
|
31739
31847
|
return null;
|
|
31740
31848
|
try {
|
|
31741
|
-
const raw = JSON.parse(readFileSync9(
|
|
31849
|
+
const raw = JSON.parse(readFileSync9(path101, "utf8"));
|
|
31742
31850
|
if (raw.version !== 1 || !Array.isArray(raw.targets))
|
|
31743
31851
|
return null;
|
|
31744
31852
|
return raw;
|
|
@@ -34139,9 +34247,9 @@ var init_types9 = __esm({
|
|
|
34139
34247
|
import { readFileSync as readFileSync14 } from "node:fs";
|
|
34140
34248
|
import { join as join11 } from "node:path";
|
|
34141
34249
|
function readLessonsDeduped(zelariRoot) {
|
|
34142
|
-
const
|
|
34250
|
+
const path101 = join11(zelariRoot, LESSONS_FILE);
|
|
34143
34251
|
try {
|
|
34144
|
-
const raw = readFileSync14(
|
|
34252
|
+
const raw = readFileSync14(path101, "utf8");
|
|
34145
34253
|
const byId = /* @__PURE__ */ new Map();
|
|
34146
34254
|
for (const line of raw.split(/\r?\n/)) {
|
|
34147
34255
|
if (!line.trim())
|
|
@@ -34242,8 +34350,8 @@ function keywordsFrom(check2, signature) {
|
|
|
34242
34350
|
return [.../* @__PURE__ */ new Set([...fromId, ...words])].slice(0, 12);
|
|
34243
34351
|
}
|
|
34244
34352
|
function writeLesson(zelariRoot, lesson) {
|
|
34245
|
-
const
|
|
34246
|
-
appendFileSync(
|
|
34353
|
+
const path101 = join12(zelariRoot, LESSONS_FILE);
|
|
34354
|
+
appendFileSync(path101, `${JSON.stringify(lesson)}
|
|
34247
34355
|
`, "utf8");
|
|
34248
34356
|
}
|
|
34249
34357
|
function findSimilar(lessons, signature) {
|
|
@@ -36211,9 +36319,9 @@ function findCycle(nodes) {
|
|
|
36211
36319
|
if (color.get(start) !== WHITE)
|
|
36212
36320
|
continue;
|
|
36213
36321
|
const stack = [[start, 0]];
|
|
36214
|
-
const
|
|
36322
|
+
const path101 = [];
|
|
36215
36323
|
color.set(start, GRAY);
|
|
36216
|
-
|
|
36324
|
+
path101.push(start);
|
|
36217
36325
|
while (stack.length > 0) {
|
|
36218
36326
|
const top = stack[stack.length - 1];
|
|
36219
36327
|
const [id3, idx] = top;
|
|
@@ -36226,17 +36334,17 @@ function findCycle(nodes) {
|
|
|
36226
36334
|
continue;
|
|
36227
36335
|
const c = color.get(dep);
|
|
36228
36336
|
if (c === GRAY) {
|
|
36229
|
-
const at =
|
|
36230
|
-
return [...
|
|
36337
|
+
const at = path101.indexOf(dep);
|
|
36338
|
+
return [...path101.slice(at), dep];
|
|
36231
36339
|
}
|
|
36232
36340
|
if (c === WHITE) {
|
|
36233
36341
|
color.set(dep, GRAY);
|
|
36234
|
-
|
|
36342
|
+
path101.push(dep);
|
|
36235
36343
|
stack.push([dep, 0]);
|
|
36236
36344
|
}
|
|
36237
36345
|
} else {
|
|
36238
36346
|
color.set(id3, BLACK);
|
|
36239
|
-
|
|
36347
|
+
path101.pop();
|
|
36240
36348
|
stack.pop();
|
|
36241
36349
|
}
|
|
36242
36350
|
}
|
|
@@ -37156,8 +37264,8 @@ var init_runner = __esm({
|
|
|
37156
37264
|
failed: [...this.tentaclesById.values()].filter((r) => r.status === "error"),
|
|
37157
37265
|
pending: []
|
|
37158
37266
|
};
|
|
37159
|
-
const
|
|
37160
|
-
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${
|
|
37267
|
+
const path101 = await this.host.saveSnapshot(snapshot, ".zelari/kraken/snapshots");
|
|
37268
|
+
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${path101}`);
|
|
37161
37269
|
return snapshot;
|
|
37162
37270
|
}
|
|
37163
37271
|
callLog(msg, data) {
|
|
@@ -38308,7 +38416,7 @@ var CORE_VERSION;
|
|
|
38308
38416
|
var init_version = __esm({
|
|
38309
38417
|
"packages/core/dist/version.js"() {
|
|
38310
38418
|
"use strict";
|
|
38311
|
-
CORE_VERSION = "2.37.
|
|
38419
|
+
CORE_VERSION = "2.37.2";
|
|
38312
38420
|
}
|
|
38313
38421
|
});
|
|
38314
38422
|
|
|
@@ -40767,9 +40875,9 @@ function spillToolOutput(fullText, meta3) {
|
|
|
40767
40875
|
const rnd = randomBytes3(3).toString("hex");
|
|
40768
40876
|
const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
|
|
40769
40877
|
const file2 = `${stamp}-${safeTool}-${hash3}-${rnd}.txt`;
|
|
40770
|
-
const
|
|
40771
|
-
writeFileSync12(
|
|
40772
|
-
return
|
|
40878
|
+
const path101 = join14(dir, file2);
|
|
40879
|
+
writeFileSync12(path101, fullText, "utf8");
|
|
40880
|
+
return path101;
|
|
40773
40881
|
} catch {
|
|
40774
40882
|
return null;
|
|
40775
40883
|
}
|
|
@@ -40815,10 +40923,10 @@ function truncateToolResult(text, capOrOpts = TOOL_RESULT_LINE_CAP) {
|
|
|
40815
40923
|
${tail2}`;
|
|
40816
40924
|
}
|
|
40817
40925
|
if (doSpill) {
|
|
40818
|
-
const
|
|
40819
|
-
if (
|
|
40926
|
+
const path101 = spillToolOutput(text, { toolName: opts.toolName });
|
|
40927
|
+
if (path101) {
|
|
40820
40928
|
const spillNote = `
|
|
40821
|
-
\u2026 [full output spilled to: ${
|
|
40929
|
+
\u2026 [full output spilled to: ${path101} \u2014 re-read with read_file if you need the complete text] \u2026`;
|
|
40822
40930
|
if (preview.includes("] \u2026\n")) {
|
|
40823
40931
|
preview = preview.replace("] \u2026\n", `] \u2026${spillNote}
|
|
40824
40932
|
`);
|
|
@@ -41589,28 +41697,28 @@ var init_storage = __esm({
|
|
|
41589
41697
|
VALID_SCALARS = /^(true|false|null|~)$/i;
|
|
41590
41698
|
Storage = class {
|
|
41591
41699
|
/** Read a Markdown file with frontmatter. Throws if not found. */
|
|
41592
|
-
read(
|
|
41593
|
-
if (!existsSync19(
|
|
41594
|
-
throw new Error(`File not found: ${
|
|
41700
|
+
read(path101) {
|
|
41701
|
+
if (!existsSync19(path101)) {
|
|
41702
|
+
throw new Error(`File not found: ${path101}`);
|
|
41595
41703
|
}
|
|
41596
|
-
const md = readFileSync17(
|
|
41704
|
+
const md = readFileSync17(path101, "utf8");
|
|
41597
41705
|
return parseFrontmatter(md);
|
|
41598
41706
|
}
|
|
41599
41707
|
/** Read a Markdown file; returns null if not found. */
|
|
41600
|
-
readIfExists(
|
|
41601
|
-
if (!existsSync19(
|
|
41602
|
-
return this.read(
|
|
41708
|
+
readIfExists(path101) {
|
|
41709
|
+
if (!existsSync19(path101)) return null;
|
|
41710
|
+
return this.read(path101);
|
|
41603
41711
|
}
|
|
41604
41712
|
/**
|
|
41605
41713
|
* Write a Markdown file atomically (tmp + rename). Creates parent dirs.
|
|
41606
41714
|
* The meta object is serialized as YAML frontmatter; body as Markdown.
|
|
41607
41715
|
*/
|
|
41608
|
-
write(
|
|
41609
|
-
mkdirSync10(dirname2(
|
|
41610
|
-
const tmp =
|
|
41716
|
+
write(path101, meta3, body) {
|
|
41717
|
+
mkdirSync10(dirname2(path101), { recursive: true });
|
|
41718
|
+
const tmp = path101 + ".tmp-" + process.pid;
|
|
41611
41719
|
const md = serializeFrontmatter(meta3, body);
|
|
41612
41720
|
writeFileSync14(tmp, md, "utf8");
|
|
41613
|
-
renameSync2(tmp,
|
|
41721
|
+
renameSync2(tmp, path101);
|
|
41614
41722
|
}
|
|
41615
41723
|
/** List all .md files in a directory (non-recursive). */
|
|
41616
41724
|
listMarkdown(dir) {
|
|
@@ -41721,8 +41829,8 @@ function nextPlanTaskId(store6) {
|
|
|
41721
41829
|
return `t${store6.counter}`;
|
|
41722
41830
|
}
|
|
41723
41831
|
function writePlanTaskArtifact(rootDir, task) {
|
|
41724
|
-
const
|
|
41725
|
-
mkdirSync11(dirname3(
|
|
41832
|
+
const path101 = join17(rootDir, "plan-tasks", `${task.id}.md`);
|
|
41833
|
+
mkdirSync11(dirname3(path101), { recursive: true });
|
|
41726
41834
|
const meta3 = {
|
|
41727
41835
|
kind: "task",
|
|
41728
41836
|
id: task.id,
|
|
@@ -41743,7 +41851,7 @@ function writePlanTaskArtifact(rootDir, task) {
|
|
|
41743
41851
|
task.notes?.trim() ? task.notes.trim() : "_(no notes)_",
|
|
41744
41852
|
""
|
|
41745
41853
|
].filter((l) => l !== null).join("\n");
|
|
41746
|
-
new Storage().write(
|
|
41854
|
+
new Storage().write(path101, meta3, body);
|
|
41747
41855
|
}
|
|
41748
41856
|
function loadHandle(rootDir) {
|
|
41749
41857
|
const jsonPath = join17(rootDir, "plan.json");
|
|
@@ -48175,6 +48283,7 @@ function frozenProfile(input) {
|
|
|
48175
48283
|
Object.freeze(input.buildRecovery);
|
|
48176
48284
|
Object.freeze(input.sampling);
|
|
48177
48285
|
Object.freeze(input.compaction);
|
|
48286
|
+
if (input.stream) Object.freeze(input.stream);
|
|
48178
48287
|
return Object.freeze(input);
|
|
48179
48288
|
}
|
|
48180
48289
|
function resolveHarnessProfile(model, providerId) {
|
|
@@ -48247,6 +48356,18 @@ var init_capabilities = __esm({
|
|
|
48247
48356
|
buildRecovery: { forceToolChoice: true, maxForcedTurns: 1 },
|
|
48248
48357
|
sampling: { temperature: 0.7 },
|
|
48249
48358
|
compaction: { ...SHARED_COMPACTION },
|
|
48359
|
+
// Copied from Grok Build (`~/.grok/config.toml` + user-guide):
|
|
48360
|
+
// inference_idle_timeout_secs = 600
|
|
48361
|
+
// max_retries = 8
|
|
48362
|
+
// xAI SDK timeout = 3600s on reasoning models
|
|
48363
|
+
// grok-4.6 xhigh reasons with hidden tokens + SSE keep-alives and no
|
|
48364
|
+
// content for minutes; a 5-min useful-token idle kills BUILD.
|
|
48365
|
+
stream: {
|
|
48366
|
+
idleMs: 6e5,
|
|
48367
|
+
firstTokenIdleMs: 6e5,
|
|
48368
|
+
maxMs: 36e5,
|
|
48369
|
+
maxRetries: 8
|
|
48370
|
+
},
|
|
48250
48371
|
profile: "grok"
|
|
48251
48372
|
});
|
|
48252
48373
|
MINIMAX_M3_CAPS = frozenProfile({
|
|
@@ -50871,18 +50992,40 @@ var openai_compatible_exports = {};
|
|
|
50871
50992
|
__export(openai_compatible_exports, {
|
|
50872
50993
|
PROVIDER_CONNECT_TIMEOUT_MS: () => PROVIDER_CONNECT_TIMEOUT_MS,
|
|
50873
50994
|
PROVIDER_ENDPOINTS: () => PROVIDER_ENDPOINTS,
|
|
50995
|
+
PROVIDER_FIRST_TOKEN_IDLE_MS: () => PROVIDER_FIRST_TOKEN_IDLE_MS,
|
|
50874
50996
|
PROVIDER_STREAM_IDLE_MS: () => PROVIDER_STREAM_IDLE_MS,
|
|
50875
50997
|
PROVIDER_STREAM_MAX_MS: () => PROVIDER_STREAM_MAX_MS,
|
|
50876
50998
|
dataUriFromImage: () => dataUriFromImage,
|
|
50999
|
+
glmModelLooksVision: () => glmModelLooksVision,
|
|
51000
|
+
isGlmCodingEndpoint: () => isGlmCodingEndpoint,
|
|
51001
|
+
isTextOnlyContentRejection: () => isTextOnlyContentRejection,
|
|
50877
51002
|
modelSupportsVision: () => modelSupportsVision,
|
|
50878
51003
|
openaiCompatibleProvider: () => openaiCompatibleProvider,
|
|
50879
51004
|
parseCachedPromptTokens: () => parseCachedPromptTokens,
|
|
50880
51005
|
providerConfigFor: () => providerConfigFor,
|
|
50881
51006
|
providerFromEnv: () => providerFromEnv,
|
|
50882
51007
|
readChunkWithTimeout: () => readChunkWithTimeout,
|
|
51008
|
+
resetTextOnlyVisionMemory: () => resetTextOnlyVisionMemory,
|
|
50883
51009
|
resolveActiveProvider: () => resolveActiveProvider2,
|
|
50884
|
-
resolveBaseUrl: () => resolveBaseUrl
|
|
50885
|
-
|
|
51010
|
+
resolveBaseUrl: () => resolveBaseUrl,
|
|
51011
|
+
resolveStreamTimeouts: () => resolveStreamTimeouts
|
|
51012
|
+
});
|
|
51013
|
+
function resolveStreamTimeouts(capabilities) {
|
|
51014
|
+
const envIdle = process.env.ZELARI_PROVIDER_STREAM_IDLE_MS ?? process.env.ZELARI_PROVIDER_TIMEOUT_MS;
|
|
51015
|
+
const envFirst = process.env.ZELARI_PROVIDER_FIRST_TOKEN_IDLE_MS;
|
|
51016
|
+
const envMax = process.env.ZELARI_PROVIDER_STREAM_MAX_MS;
|
|
51017
|
+
const envRetries = process.env.ZELARI_PROVIDER_MAX_RETRIES;
|
|
51018
|
+
const idleMs = envIdle ? PROVIDER_STREAM_IDLE_MS : capabilities.stream?.idleMs ?? PROVIDER_STREAM_IDLE_MS;
|
|
51019
|
+
const firstRaw = envFirst ? PROVIDER_FIRST_TOKEN_IDLE_MS : capabilities.stream?.firstTokenIdleMs ?? PROVIDER_FIRST_TOKEN_IDLE_MS;
|
|
51020
|
+
const maxMs = envMax ? PROVIDER_STREAM_MAX_MS : capabilities.stream?.maxMs ?? PROVIDER_STREAM_MAX_MS;
|
|
51021
|
+
const maxRetries = envRetries ? MAX_RETRIES : capabilities.stream?.maxRetries ?? MAX_RETRIES;
|
|
51022
|
+
return {
|
|
51023
|
+
idleMs,
|
|
51024
|
+
firstTokenIdleMs: Math.max(firstRaw, idleMs),
|
|
51025
|
+
maxMs,
|
|
51026
|
+
maxRetries
|
|
51027
|
+
};
|
|
51028
|
+
}
|
|
50886
51029
|
function abortableSleep(ms, signal) {
|
|
50887
51030
|
return new Promise((resolve9) => {
|
|
50888
51031
|
if (signal?.aborted) return resolve9();
|
|
@@ -50901,6 +51044,12 @@ function isTimeoutAbortMessage(msg) {
|
|
|
50901
51044
|
const m = msg.toLowerCase();
|
|
50902
51045
|
return m.includes("aborted due to timeout") || m.includes("timeout") || m.includes("the operation was aborted");
|
|
50903
51046
|
}
|
|
51047
|
+
function formatStreamIdleError(elapsedMs, budgetMs, kind2) {
|
|
51048
|
+
const elapsedS = Math.max(1, Math.round(elapsedMs / 1e3));
|
|
51049
|
+
const budgetS = Math.max(1, Math.round(budgetMs / 1e3));
|
|
51050
|
+
const why = kind2 === "keep-alive" ? "no content tokens \u2014 keep-alive frames don't count" : "no tokens";
|
|
51051
|
+
return `Provider stream idle for ${elapsedS}s of ${budgetS}s (${why}). The model/gateway stalled \u2014 try again or switch model. Override with ZELARI_PROVIDER_STREAM_IDLE_MS or ZELARI_PROVIDER_FIRST_TOKEN_IDLE_MS.`;
|
|
51052
|
+
}
|
|
50904
51053
|
async function readChunkWithTimeout(reader, opts) {
|
|
50905
51054
|
if (opts.signal?.aborted) {
|
|
50906
51055
|
throw new Error("aborted");
|
|
@@ -50914,9 +51063,7 @@ async function readChunkWithTimeout(reader, opts) {
|
|
|
50914
51063
|
}
|
|
50915
51064
|
const idleElapsed = now - opts.lastUsefulAt();
|
|
50916
51065
|
if (idleElapsed >= opts.idleMs) {
|
|
50917
|
-
throw new Error(
|
|
50918
|
-
`Provider stream idle for ${Math.round(idleElapsed / 1e3)}s (no content tokens \u2014 keep-alive frames don't count). The model/gateway stalled \u2014 try again or switch model. Override with ZELARI_PROVIDER_STREAM_IDLE_MS.`
|
|
50919
|
-
);
|
|
51066
|
+
throw new Error(formatStreamIdleError(idleElapsed, opts.idleMs, "keep-alive"));
|
|
50920
51067
|
}
|
|
50921
51068
|
const waitMs = Math.min(opts.idleMs - idleElapsed, remaining);
|
|
50922
51069
|
let idleTimer;
|
|
@@ -50926,11 +51073,8 @@ async function readChunkWithTimeout(reader, opts) {
|
|
|
50926
51073
|
reader.read(),
|
|
50927
51074
|
new Promise((_, reject) => {
|
|
50928
51075
|
idleTimer = setTimeout(() => {
|
|
50929
|
-
|
|
50930
|
-
|
|
50931
|
-
`Provider stream idle for ${Math.round(waitMs / 1e3)}s (no tokens). The model/gateway stalled \u2014 try again or switch model. Override with ZELARI_PROVIDER_STREAM_IDLE_MS.`
|
|
50932
|
-
)
|
|
50933
|
-
);
|
|
51076
|
+
const elapsed = Date.now() - opts.lastUsefulAt();
|
|
51077
|
+
reject(new Error(formatStreamIdleError(elapsed, opts.idleMs, "silence")));
|
|
50934
51078
|
}, waitMs);
|
|
50935
51079
|
if (opts.signal) {
|
|
50936
51080
|
onAbort = () => reject(new Error("aborted"));
|
|
@@ -50952,9 +51096,52 @@ function backoffDelay(attempt, retryAfterHeader) {
|
|
|
50952
51096
|
}
|
|
50953
51097
|
return Math.min(BACKOFF_BASE_MS * 2 ** attempt, BACKOFF_CAP_MS);
|
|
50954
51098
|
}
|
|
50955
|
-
function
|
|
50956
|
-
|
|
50957
|
-
|
|
51099
|
+
function visionMemoryKey(model, probe) {
|
|
51100
|
+
return `${probe?.providerId ?? ""}::${model}::${probe?.baseUrl ?? ""}`;
|
|
51101
|
+
}
|
|
51102
|
+
function resetTextOnlyVisionMemory() {
|
|
51103
|
+
textOnlyVisionMemory.clear();
|
|
51104
|
+
}
|
|
51105
|
+
function isGlmCodingEndpoint(baseUrl) {
|
|
51106
|
+
if (!baseUrl) return false;
|
|
51107
|
+
return /\/coding(\/|$)/i.test(baseUrl);
|
|
51108
|
+
}
|
|
51109
|
+
function glmModelLooksVision(model) {
|
|
51110
|
+
const n = model.trim().toLowerCase();
|
|
51111
|
+
if (!n) return false;
|
|
51112
|
+
if (/(?:^|[-_/.])(?:vl|vision)(?:[-_/.]|$)/.test(n)) return true;
|
|
51113
|
+
return /^glm[-_.]?[\w.]*v(?:-|$)/.test(n);
|
|
51114
|
+
}
|
|
51115
|
+
function glmModelIsTextOnly(model) {
|
|
51116
|
+
const n = model.trim().toLowerCase();
|
|
51117
|
+
if (!n.startsWith("glm")) return false;
|
|
51118
|
+
return !glmModelLooksVision(n);
|
|
51119
|
+
}
|
|
51120
|
+
function isTextOnlyContentRejection(status, body) {
|
|
51121
|
+
if (status !== 400) return false;
|
|
51122
|
+
if (!/messages\.content\.type/i.test(body)) return false;
|
|
51123
|
+
return /allowed values/i.test(body) || /\[\s*['"]text['"]\s*\]/.test(body) || /取值范围/.test(body) || /is invalid/i.test(body);
|
|
51124
|
+
}
|
|
51125
|
+
function messagesHaveImageUrl(messages) {
|
|
51126
|
+
for (const m of messages) {
|
|
51127
|
+
const content = m.content;
|
|
51128
|
+
if (!Array.isArray(content)) continue;
|
|
51129
|
+
for (const part of content) {
|
|
51130
|
+
if (part && typeof part === "object" && part.type === "image_url") {
|
|
51131
|
+
return true;
|
|
51132
|
+
}
|
|
51133
|
+
}
|
|
51134
|
+
}
|
|
51135
|
+
return false;
|
|
51136
|
+
}
|
|
51137
|
+
function modelSupportsVision(model, probe) {
|
|
51138
|
+
const force = (process.env.ZELARI_VISION ?? "").trim().toLowerCase();
|
|
51139
|
+
if (force === "0" || force === "false" || force === "off") return false;
|
|
51140
|
+
if (force === "1" || force === "true" || force === "on") return true;
|
|
51141
|
+
if (textOnlyVisionMemory.has(visionMemoryKey(model, probe))) return false;
|
|
51142
|
+
if (isGlmCodingEndpoint(probe?.baseUrl)) return false;
|
|
51143
|
+
if (glmModelIsTextOnly(model)) return false;
|
|
51144
|
+
return true;
|
|
50958
51145
|
}
|
|
50959
51146
|
function dataUriFromImage(img) {
|
|
50960
51147
|
return `data:${img.mime};base64,${img.dataBase64}`;
|
|
@@ -51074,29 +51261,38 @@ function positiveEnvInt(name) {
|
|
|
51074
51261
|
function openaiCompatibleProvider(config2) {
|
|
51075
51262
|
return async function* (params) {
|
|
51076
51263
|
const capabilities = capabilitiesFor(params.model, config2.providerId);
|
|
51077
|
-
const
|
|
51264
|
+
const streamTimeouts = resolveStreamTimeouts(capabilities);
|
|
51265
|
+
const visionProbe = {
|
|
51266
|
+
providerId: config2.providerId,
|
|
51267
|
+
baseUrl: config2.baseUrl
|
|
51268
|
+
};
|
|
51269
|
+
let vision = modelSupportsVision(params.model, visionProbe);
|
|
51078
51270
|
const msgsIn = params.messages;
|
|
51079
|
-
|
|
51080
|
-
|
|
51081
|
-
|
|
51082
|
-
|
|
51083
|
-
|
|
51084
|
-
|
|
51085
|
-
|
|
51086
|
-
|
|
51087
|
-
|
|
51088
|
-
|
|
51089
|
-
if (m.
|
|
51090
|
-
|
|
51091
|
-
|
|
51092
|
-
|
|
51093
|
-
|
|
51094
|
-
|
|
51095
|
-
|
|
51096
|
-
|
|
51097
|
-
|
|
51098
|
-
|
|
51099
|
-
|
|
51271
|
+
const wireMessages = (visionFlag) => {
|
|
51272
|
+
let toolRunImages = [];
|
|
51273
|
+
return msgsIn.flatMap((m, i) => {
|
|
51274
|
+
const cacheable = visionFlag && !(m.role === "user" && m.images && m.images.length > 0);
|
|
51275
|
+
if (cacheable) {
|
|
51276
|
+
const cached2 = messageMappingCache.get(m);
|
|
51277
|
+
if (cached2) return [cached2];
|
|
51278
|
+
}
|
|
51279
|
+
const mapped = mapAgentMessage(m, visionFlag);
|
|
51280
|
+
if (cacheable) messageMappingCache.set(m, mapped);
|
|
51281
|
+
if (m.role === "tool") {
|
|
51282
|
+
if (m.images && m.images.length > 0) toolRunImages.push(...m.images);
|
|
51283
|
+
const next = msgsIn[i + 1];
|
|
51284
|
+
const runEnds = !next || next.role !== "tool";
|
|
51285
|
+
if (runEnds && visionFlag && toolRunImages.length > 0) {
|
|
51286
|
+
const followUp = imagesFollowUpMessage(toolRunImages);
|
|
51287
|
+
toolRunImages = [];
|
|
51288
|
+
return [mapped, followUp];
|
|
51289
|
+
}
|
|
51290
|
+
if (runEnds) toolRunImages = [];
|
|
51291
|
+
}
|
|
51292
|
+
return [mapped];
|
|
51293
|
+
});
|
|
51294
|
+
};
|
|
51295
|
+
let messages = wireMessages(vision);
|
|
51100
51296
|
const generation = params.generation;
|
|
51101
51297
|
const body = {
|
|
51102
51298
|
// Use `params.model` (per-call override from AgentHarness, e.g. for
|
|
@@ -51146,6 +51342,7 @@ function openaiCompatibleProvider(config2) {
|
|
|
51146
51342
|
const recoveryAttempt = generation?.recoveryAttempt ?? 1;
|
|
51147
51343
|
const forceRecoveryTool = generation?.toolChoice === "required" && capabilities.buildRecovery.forceToolChoice && recoveryAttempt <= capabilities.buildRecovery.maxForcedTurns;
|
|
51148
51344
|
body.tool_choice = forceRecoveryTool ? "required" : "auto";
|
|
51345
|
+
if (config2.providerId === "glm") body.tool_stream = true;
|
|
51149
51346
|
}
|
|
51150
51347
|
const headers3 = {
|
|
51151
51348
|
"Content-Type": "application/json",
|
|
@@ -51160,7 +51357,7 @@ function openaiCompatibleProvider(config2) {
|
|
|
51160
51357
|
let response;
|
|
51161
51358
|
let lastErrText = "";
|
|
51162
51359
|
let lastStatus = 0;
|
|
51163
|
-
for (let attempt = 0; attempt <=
|
|
51360
|
+
for (let attempt = 0; attempt <= streamTimeouts.maxRetries; attempt += 1) {
|
|
51164
51361
|
if (params.signal?.aborted) {
|
|
51165
51362
|
yield { kind: "error", message: "aborted" };
|
|
51166
51363
|
return;
|
|
@@ -51201,7 +51398,7 @@ function openaiCompatibleProvider(config2) {
|
|
|
51201
51398
|
yield { kind: "error", message: "aborted" };
|
|
51202
51399
|
return;
|
|
51203
51400
|
}
|
|
51204
|
-
const maxAttempts = isTimeoutAbortMessage(lastErrText) ? Math.min(1,
|
|
51401
|
+
const maxAttempts = isTimeoutAbortMessage(lastErrText) ? Math.min(1, streamTimeouts.maxRetries) : streamTimeouts.maxRetries;
|
|
51205
51402
|
if (attempt < maxAttempts) {
|
|
51206
51403
|
await abortableSleep(backoffDelay(attempt, null), params.signal);
|
|
51207
51404
|
continue;
|
|
@@ -51212,7 +51409,14 @@ function openaiCompatibleProvider(config2) {
|
|
|
51212
51409
|
if (response.ok && response.body) break;
|
|
51213
51410
|
lastStatus = response.status;
|
|
51214
51411
|
lastErrText = await response.text().catch(() => "");
|
|
51215
|
-
if (
|
|
51412
|
+
if (vision && isTextOnlyContentRejection(lastStatus, lastErrText) && messagesHaveImageUrl(messages)) {
|
|
51413
|
+
textOnlyVisionMemory.add(visionMemoryKey(params.model, visionProbe));
|
|
51414
|
+
vision = false;
|
|
51415
|
+
messages = wireMessages(false);
|
|
51416
|
+
body.messages = messages;
|
|
51417
|
+
continue;
|
|
51418
|
+
}
|
|
51419
|
+
if (!RETRYABLE_STATUSES.has(response.status) || attempt >= streamTimeouts.maxRetries) break;
|
|
51216
51420
|
const retryAfter = response.headers.get("retry-after");
|
|
51217
51421
|
await abortableSleep(backoffDelay(attempt, retryAfter), params.signal);
|
|
51218
51422
|
}
|
|
@@ -51258,17 +51462,19 @@ function openaiCompatibleProvider(config2) {
|
|
|
51258
51462
|
}
|
|
51259
51463
|
toolCallAccumulator.clear();
|
|
51260
51464
|
};
|
|
51261
|
-
const streamDeadline = Date.now() +
|
|
51465
|
+
const streamDeadline = Date.now() + streamTimeouts.maxMs;
|
|
51262
51466
|
let lastUsefulAt = Date.now();
|
|
51467
|
+
let emittedUseful = false;
|
|
51263
51468
|
const markUseful = () => {
|
|
51264
51469
|
lastUsefulAt = Date.now();
|
|
51470
|
+
emittedUseful = true;
|
|
51265
51471
|
};
|
|
51266
51472
|
try {
|
|
51267
51473
|
while (true) {
|
|
51268
51474
|
let chunk;
|
|
51269
51475
|
try {
|
|
51270
51476
|
chunk = await readChunkWithTimeout(reader, {
|
|
51271
|
-
idleMs:
|
|
51477
|
+
idleMs: emittedUseful ? streamTimeouts.idleMs : streamTimeouts.firstTokenIdleMs,
|
|
51272
51478
|
deadlineMs: streamDeadline,
|
|
51273
51479
|
signal: params.signal,
|
|
51274
51480
|
lastUsefulAt: () => lastUsefulAt
|
|
@@ -51323,17 +51529,33 @@ function openaiCompatibleProvider(config2) {
|
|
|
51323
51529
|
}
|
|
51324
51530
|
};
|
|
51325
51531
|
}
|
|
51326
|
-
|
|
51532
|
+
const content = delta?.content;
|
|
51533
|
+
if (typeof content === "string" && content.length > 0) {
|
|
51327
51534
|
markUseful();
|
|
51328
|
-
yield { kind: "text", delta:
|
|
51535
|
+
yield { kind: "text", delta: content };
|
|
51536
|
+
} else if (Array.isArray(content)) {
|
|
51537
|
+
for (const part of content) {
|
|
51538
|
+
if (!part || typeof part !== "object") continue;
|
|
51539
|
+
const p3 = part;
|
|
51540
|
+
const text = typeof p3.text === "string" ? p3.text : "";
|
|
51541
|
+
if (!text) continue;
|
|
51542
|
+
markUseful();
|
|
51543
|
+
const partType = typeof p3.type === "string" ? p3.type : "text";
|
|
51544
|
+
yield {
|
|
51545
|
+
kind: partType === "reasoning" || partType === "thinking" ? "thinking" : "text",
|
|
51546
|
+
delta: text
|
|
51547
|
+
};
|
|
51548
|
+
}
|
|
51329
51549
|
}
|
|
51330
|
-
const
|
|
51331
|
-
|
|
51550
|
+
const reasoningRaw = delta?.reasoning_content ?? delta?.reasoning ?? delta?.thinking;
|
|
51551
|
+
const reasoning = typeof reasoningRaw === "string" ? reasoningRaw : reasoningRaw && typeof reasoningRaw === "object" && typeof reasoningRaw.text === "string" ? reasoningRaw.text : reasoningRaw && typeof reasoningRaw === "object" && typeof reasoningRaw.content === "string" ? reasoningRaw.content : "";
|
|
51552
|
+
if (reasoning.length > 0) {
|
|
51332
51553
|
markUseful();
|
|
51333
51554
|
yield { kind: "thinking", delta: reasoning };
|
|
51334
51555
|
}
|
|
51335
51556
|
const details = delta?.reasoning_details;
|
|
51336
|
-
if (Array.isArray(details)) {
|
|
51557
|
+
if (Array.isArray(details) && details.length > 0) {
|
|
51558
|
+
markUseful();
|
|
51337
51559
|
for (const d of details) {
|
|
51338
51560
|
if (!d || typeof d !== "object") continue;
|
|
51339
51561
|
const t = d.text;
|
|
@@ -51353,6 +51575,7 @@ function openaiCompatibleProvider(config2) {
|
|
|
51353
51575
|
}
|
|
51354
51576
|
}
|
|
51355
51577
|
if (Array.isArray(delta?.tool_calls)) {
|
|
51578
|
+
markUseful();
|
|
51356
51579
|
for (const tc of delta.tool_calls) {
|
|
51357
51580
|
const idx = tc.index ?? 0;
|
|
51358
51581
|
const existing = toolCallAccumulator.get(idx) ?? {
|
|
@@ -51419,7 +51642,7 @@ async function providerConfigFor(providerId) {
|
|
|
51419
51642
|
...extraFromStored(providerId)
|
|
51420
51643
|
};
|
|
51421
51644
|
}
|
|
51422
|
-
var RETRYABLE_STATUSES, MAX_RETRIES, BACKOFF_BASE_MS, BACKOFF_CAP_MS, PROVIDER_CONNECT_TIMEOUT_MS, PROVIDER_STREAM_IDLE_MS, PROVIDER_STREAM_MAX_MS, PROVIDER_ENDPOINTS, messageMappingCache;
|
|
51645
|
+
var RETRYABLE_STATUSES, MAX_RETRIES, BACKOFF_BASE_MS, BACKOFF_CAP_MS, PROVIDER_CONNECT_TIMEOUT_MS, PROVIDER_STREAM_IDLE_MS, PROVIDER_FIRST_TOKEN_IDLE_MS, PROVIDER_STREAM_MAX_MS, textOnlyVisionMemory, PROVIDER_ENDPOINTS, messageMappingCache;
|
|
51423
51646
|
var init_openai_compatible = __esm({
|
|
51424
51647
|
"src/cli/provider/openai-compatible.ts"() {
|
|
51425
51648
|
"use strict";
|
|
@@ -51445,11 +51668,17 @@ var init_openai_compatible = __esm({
|
|
|
51445
51668
|
const n = raw ? Number.parseInt(raw, 10) : 3e5;
|
|
51446
51669
|
return Number.isFinite(n) && n >= 15e3 ? n : 3e5;
|
|
51447
51670
|
})();
|
|
51671
|
+
PROVIDER_FIRST_TOKEN_IDLE_MS = (() => {
|
|
51672
|
+
const raw = process.env.ZELARI_PROVIDER_FIRST_TOKEN_IDLE_MS;
|
|
51673
|
+
const n = raw ? Number.parseInt(raw, 10) : 6e5;
|
|
51674
|
+
return Number.isFinite(n) && n >= 15e3 ? n : 6e5;
|
|
51675
|
+
})();
|
|
51448
51676
|
PROVIDER_STREAM_MAX_MS = (() => {
|
|
51449
51677
|
const raw = process.env.ZELARI_PROVIDER_STREAM_MAX_MS;
|
|
51450
51678
|
const n = raw ? Number.parseInt(raw, 10) : 18e5;
|
|
51451
51679
|
return Number.isFinite(n) && n >= 6e4 ? n : 18e5;
|
|
51452
51680
|
})();
|
|
51681
|
+
textOnlyVisionMemory = /* @__PURE__ */ new Set();
|
|
51453
51682
|
PROVIDER_ENDPOINTS = {
|
|
51454
51683
|
"openai-compatible": "https://api.x.ai/v1",
|
|
51455
51684
|
"minimax": "https://api.minimax.io/v1",
|
|
@@ -52074,21 +52303,21 @@ function normalizeAuth(auth) {
|
|
|
52074
52303
|
return "agent";
|
|
52075
52304
|
}
|
|
52076
52305
|
function readSecrets() {
|
|
52077
|
-
const
|
|
52078
|
-
if (!existsSync30(
|
|
52306
|
+
const path101 = getSshSecretsPath();
|
|
52307
|
+
if (!existsSync30(path101)) return {};
|
|
52079
52308
|
try {
|
|
52080
|
-
return JSON.parse(readFileSync22(
|
|
52309
|
+
return JSON.parse(readFileSync22(path101, "utf8"));
|
|
52081
52310
|
} catch {
|
|
52082
52311
|
return {};
|
|
52083
52312
|
}
|
|
52084
52313
|
}
|
|
52085
52314
|
function writeSecrets(data) {
|
|
52086
|
-
const
|
|
52087
|
-
mkdirSync13(dirname4(
|
|
52088
|
-
writeFileSync16(
|
|
52315
|
+
const path101 = getSshSecretsPath();
|
|
52316
|
+
mkdirSync13(dirname4(path101), { recursive: true });
|
|
52317
|
+
writeFileSync16(path101, `${JSON.stringify(data, null, 2)}
|
|
52089
52318
|
`, "utf8");
|
|
52090
52319
|
try {
|
|
52091
|
-
chmodSync(
|
|
52320
|
+
chmodSync(path101, 384);
|
|
52092
52321
|
} catch {
|
|
52093
52322
|
}
|
|
52094
52323
|
}
|
|
@@ -52117,10 +52346,10 @@ function deleteSshPassword(id3) {
|
|
|
52117
52346
|
writeSecrets({ passwords });
|
|
52118
52347
|
}
|
|
52119
52348
|
function readStore2() {
|
|
52120
|
-
const
|
|
52121
|
-
if (!existsSync30(
|
|
52349
|
+
const path101 = getSshTargetsPath();
|
|
52350
|
+
if (!existsSync30(path101)) return [];
|
|
52122
52351
|
try {
|
|
52123
|
-
const parsed = JSON.parse(readFileSync22(
|
|
52352
|
+
const parsed = JSON.parse(readFileSync22(path101, "utf8"));
|
|
52124
52353
|
const list = Array.isArray(parsed.targets) ? parsed.targets : [];
|
|
52125
52354
|
return list.filter(
|
|
52126
52355
|
(t) => t && typeof t.id === "string" && typeof t.host === "string" && typeof t.user === "string"
|
|
@@ -52135,11 +52364,11 @@ function readStore2() {
|
|
|
52135
52364
|
}
|
|
52136
52365
|
}
|
|
52137
52366
|
function writeStore2(targets) {
|
|
52138
|
-
const
|
|
52139
|
-
mkdirSync13(dirname4(
|
|
52367
|
+
const path101 = getSshTargetsPath();
|
|
52368
|
+
mkdirSync13(dirname4(path101), { recursive: true });
|
|
52140
52369
|
const clean = targets.map(({ hasPassword: _hp, ...t }) => t);
|
|
52141
52370
|
writeFileSync16(
|
|
52142
|
-
|
|
52371
|
+
path101,
|
|
52143
52372
|
`${JSON.stringify({ targets: clean }, null, 2)}
|
|
52144
52373
|
`,
|
|
52145
52374
|
"utf8"
|
|
@@ -52385,11 +52614,11 @@ function formatSshTargetsForPrompt() {
|
|
|
52385
52614
|
];
|
|
52386
52615
|
for (const t of targets) {
|
|
52387
52616
|
const tags = t.tags?.length ? ` tags=[${t.tags.join(",")}]` : "";
|
|
52388
|
-
const
|
|
52617
|
+
const path101 = t.defaultRemotePath ? ` remotePath=${t.defaultRemotePath}` : "";
|
|
52389
52618
|
const allow = t.allowedCommands?.length ? ` allowed=${t.allowedCommands.join("|")}` : " allowed=status-only";
|
|
52390
52619
|
const auth = t.auth === "password" ? " auth=password" : t.auth === "keyPath" ? " auth=key" : " auth=agent";
|
|
52391
52620
|
lines.push(
|
|
52392
|
-
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${
|
|
52621
|
+
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${path101}${tags}${allow}`
|
|
52393
52622
|
);
|
|
52394
52623
|
}
|
|
52395
52624
|
return lines.join("\n");
|
|
@@ -57289,6 +57518,8 @@ function parseHeadlessFlags(argv) {
|
|
|
57289
57518
|
missionStrict = true;
|
|
57290
57519
|
} else if (arg === "--no-mission-strict") {
|
|
57291
57520
|
missionStrict = false;
|
|
57521
|
+
} else if (arg === "--allow-unverified") {
|
|
57522
|
+
process.env.ZELARI_ALLOW_UNVERIFIED = "1";
|
|
57292
57523
|
} else if (arg === "--kraken-graph") {
|
|
57293
57524
|
krakenGraph = argv[i + 1];
|
|
57294
57525
|
i++;
|
|
@@ -57402,6 +57633,7 @@ __export(headlessSpine_exports, {
|
|
|
57402
57633
|
seedHeadlessModelHistory: () => seedHeadlessModelHistory,
|
|
57403
57634
|
sessionStartedEvent: () => sessionStartedEvent
|
|
57404
57635
|
});
|
|
57636
|
+
import path67 from "node:path";
|
|
57405
57637
|
function sessionStartedEvent(handle) {
|
|
57406
57638
|
return {
|
|
57407
57639
|
type: "session_started",
|
|
@@ -57413,6 +57645,20 @@ function resolveHeadlessProfileId(mode, explicit) {
|
|
|
57413
57645
|
if (explicit) return resolveProfile(explicit).id;
|
|
57414
57646
|
return defaultProfileForMode(mode ?? "kraken");
|
|
57415
57647
|
}
|
|
57648
|
+
async function countVerificationEvidenceInLog(mirror, sessionId2) {
|
|
57649
|
+
if (mirror.status !== "active" && mirror.status !== "closed") return -1;
|
|
57650
|
+
try {
|
|
57651
|
+
await mirror.flush().catch(() => void 0);
|
|
57652
|
+
const report = await readSessionLog(path67.join(mirror.sessionsDir, sessionId2, "events.jsonl"));
|
|
57653
|
+
return report.events.filter((e) => e.kind === "verification.evidence").length;
|
|
57654
|
+
} catch (err) {
|
|
57655
|
+
process.stderr.write(
|
|
57656
|
+
`[zelari-code] verification-evidence count unavailable (${err instanceof Error ? err.message : String(err)}) \u2014 event-back gate skipped
|
|
57657
|
+
`
|
|
57658
|
+
);
|
|
57659
|
+
return -1;
|
|
57660
|
+
}
|
|
57661
|
+
}
|
|
57416
57662
|
async function openHeadlessSpine(opts) {
|
|
57417
57663
|
const profileId = resolveHeadlessProfileId(opts.mode, opts.profile);
|
|
57418
57664
|
let profileTools = [];
|
|
@@ -57484,6 +57730,9 @@ async function openHeadlessSpine(opts) {
|
|
|
57484
57730
|
lastVerificationRun() {
|
|
57485
57731
|
return spine.lastVerificationRun();
|
|
57486
57732
|
},
|
|
57733
|
+
countVerificationEvidence() {
|
|
57734
|
+
return countVerificationEvidenceInLog(spine, opts.sessionId);
|
|
57735
|
+
},
|
|
57487
57736
|
missionPhase(phase2, note) {
|
|
57488
57737
|
spine.missionPhase(phase2, note);
|
|
57489
57738
|
},
|
|
@@ -57591,6 +57840,7 @@ var init_headlessSpine = __esm({
|
|
|
57591
57840
|
init_dist();
|
|
57592
57841
|
init_session();
|
|
57593
57842
|
init_mission2();
|
|
57843
|
+
init_session();
|
|
57594
57844
|
init_runtime();
|
|
57595
57845
|
init_sessionSpine();
|
|
57596
57846
|
init_budgetRuntime();
|
|
@@ -58194,7 +58444,7 @@ var init_planDetect = __esm({
|
|
|
58194
58444
|
// src/cli/memory/legacyImport.ts
|
|
58195
58445
|
import { createHash as createHash18 } from "node:crypto";
|
|
58196
58446
|
import { promises as fs27 } from "node:fs";
|
|
58197
|
-
import * as
|
|
58447
|
+
import * as path68 from "node:path";
|
|
58198
58448
|
function sourceId(fact, line) {
|
|
58199
58449
|
return `jsonl:${fact.id ?? createHash18("sha256").update(line).digest("hex")}`;
|
|
58200
58450
|
}
|
|
@@ -58212,7 +58462,7 @@ function timestamp(value) {
|
|
|
58212
58462
|
}
|
|
58213
58463
|
async function importLegacyMemoryLog(backend, service) {
|
|
58214
58464
|
const result = { found: 0, imported: 0, skipped: 0, corrupt: 0 };
|
|
58215
|
-
const logPath =
|
|
58465
|
+
const logPath = path68.join(path68.dirname(backend.databasePath), "log.jsonl");
|
|
58216
58466
|
let raw;
|
|
58217
58467
|
try {
|
|
58218
58468
|
raw = await fs27.readFile(logPath, "utf8");
|
|
@@ -58395,7 +58645,7 @@ var init_sqliteCodec = __esm({
|
|
|
58395
58645
|
// src/cli/memory/sqliteRpc.ts
|
|
58396
58646
|
import { existsSync as existsSync36 } from "node:fs";
|
|
58397
58647
|
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
58398
|
-
import * as
|
|
58648
|
+
import * as path69 from "node:path";
|
|
58399
58649
|
import { Worker } from "node:worker_threads";
|
|
58400
58650
|
function isBusy(error51) {
|
|
58401
58651
|
const candidate = error51;
|
|
@@ -58404,10 +58654,10 @@ function isBusy(error51) {
|
|
|
58404
58654
|
);
|
|
58405
58655
|
}
|
|
58406
58656
|
function resolveWorkerUrl() {
|
|
58407
|
-
const here =
|
|
58408
|
-
const direct =
|
|
58657
|
+
const here = path69.dirname(fileURLToPath2(import.meta.url));
|
|
58658
|
+
const direct = path69.join(here, "sqliteWorker.mjs");
|
|
58409
58659
|
if (existsSync36(direct)) return pathToFileURL2(direct);
|
|
58410
|
-
return pathToFileURL2(
|
|
58660
|
+
return pathToFileURL2(path69.join(here, "memory", "sqliteWorker.mjs"));
|
|
58411
58661
|
}
|
|
58412
58662
|
var SqliteWorkerRpc;
|
|
58413
58663
|
var init_sqliteRpc = __esm({
|
|
@@ -58696,7 +58946,7 @@ WHERE NOT EXISTS (SELECT 1 FROM memory_fts f WHERE f.node_id = n.id);
|
|
|
58696
58946
|
// src/cli/memory/sqliteBackend.ts
|
|
58697
58947
|
import { createHash as createHash19, randomUUID as randomUUID6 } from "node:crypto";
|
|
58698
58948
|
import { promises as fs28 } from "node:fs";
|
|
58699
|
-
import * as
|
|
58949
|
+
import * as path70 from "node:path";
|
|
58700
58950
|
function boundedLimit(value, fallback = 50) {
|
|
58701
58951
|
return Math.max(1, Math.min(Math.floor(value ?? fallback), 1e5));
|
|
58702
58952
|
}
|
|
@@ -58758,16 +59008,16 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
58758
59008
|
try {
|
|
58759
59009
|
resolved = await fs28.realpath(projectRoot);
|
|
58760
59010
|
} catch {
|
|
58761
|
-
resolved =
|
|
59011
|
+
resolved = path70.resolve(projectRoot);
|
|
58762
59012
|
}
|
|
58763
59013
|
if (this.initialized && resolved === this.projectRoot) return;
|
|
58764
59014
|
if (this.initialized) await this.close();
|
|
58765
59015
|
const filename = this.options.filename ?? "memory.db";
|
|
58766
|
-
if (
|
|
59016
|
+
if (path70.basename(filename) !== filename || filename === "." || filename === "..") {
|
|
58767
59017
|
throw new Error("SQLite memory filename must not contain a path.");
|
|
58768
59018
|
}
|
|
58769
|
-
const zelariDirectory =
|
|
58770
|
-
const directory =
|
|
59019
|
+
const zelariDirectory = path70.join(resolved, ".zelari");
|
|
59020
|
+
const directory = path70.join(zelariDirectory, "memory");
|
|
58771
59021
|
for (const candidate of [zelariDirectory, directory]) {
|
|
58772
59022
|
let stat8;
|
|
58773
59023
|
try {
|
|
@@ -58786,12 +59036,12 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
58786
59036
|
}
|
|
58787
59037
|
}
|
|
58788
59038
|
const canonicalDirectory = await fs28.realpath(directory);
|
|
58789
|
-
const relativeDirectory =
|
|
58790
|
-
if (relativeDirectory.startsWith("..") ||
|
|
59039
|
+
const relativeDirectory = path70.relative(resolved, canonicalDirectory);
|
|
59040
|
+
if (relativeDirectory.startsWith("..") || path70.isAbsolute(relativeDirectory)) {
|
|
58791
59041
|
throw new Error("SQLite memory directory resolves outside the active project.");
|
|
58792
59042
|
}
|
|
58793
59043
|
this.projectRoot = resolved;
|
|
58794
|
-
this.databasePath =
|
|
59044
|
+
this.databasePath = path70.join(canonicalDirectory, filename);
|
|
58795
59045
|
const opened = await this.rpc.open({
|
|
58796
59046
|
dbPath: this.databasePath,
|
|
58797
59047
|
schemaSql: SQLITE_MEMORY_BASE_SCHEMA,
|
|
@@ -59324,7 +59574,7 @@ __export(serviceFactory_exports, {
|
|
|
59324
59574
|
});
|
|
59325
59575
|
import { createHash as createHash20 } from "node:crypto";
|
|
59326
59576
|
import { promises as fs29 } from "node:fs";
|
|
59327
|
-
import * as
|
|
59577
|
+
import * as path71 from "node:path";
|
|
59328
59578
|
function isMemoryV2Enabled(env = process.env) {
|
|
59329
59579
|
if (env.ZELARI_MEMORY === "0") return false;
|
|
59330
59580
|
if (env.ZELARI_MEMORY_BACKEND === "file" || env.ZELARI_MEMORY_BACKEND === "jsonl") return false;
|
|
@@ -59345,7 +59595,7 @@ async function canonicalProjectId(projectRoot) {
|
|
|
59345
59595
|
try {
|
|
59346
59596
|
canonical = await fs29.realpath(projectRoot);
|
|
59347
59597
|
} catch {
|
|
59348
|
-
canonical =
|
|
59598
|
+
canonical = path71.resolve(projectRoot);
|
|
59349
59599
|
}
|
|
59350
59600
|
canonical = canonical.replace(/\\/g, "/").replace(/\/$/, "");
|
|
59351
59601
|
if (process.platform === "win32") canonical = canonical.toLocaleLowerCase("en-US");
|
|
@@ -60047,8 +60297,8 @@ function readPlan(ctx) {
|
|
|
60047
60297
|
} catch {
|
|
60048
60298
|
}
|
|
60049
60299
|
}
|
|
60050
|
-
const
|
|
60051
|
-
const doc = ctx.storage.readIfExists(
|
|
60300
|
+
const path101 = workspaceFile(ctx.rootDir, "plan");
|
|
60301
|
+
const doc = ctx.storage.readIfExists(path101);
|
|
60052
60302
|
if (!doc) return { phases: [], tasks: [], milestones: [] };
|
|
60053
60303
|
const meta3 = doc.meta;
|
|
60054
60304
|
return {
|
|
@@ -60229,7 +60479,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
60229
60479
|
dueDate: input.dueDate,
|
|
60230
60480
|
targetVersion: version2
|
|
60231
60481
|
});
|
|
60232
|
-
const
|
|
60482
|
+
const path101 = join31(ctx.rootDir, "milestones", `${id3}.md`);
|
|
60233
60483
|
const meta3 = {
|
|
60234
60484
|
kind: "milestone",
|
|
60235
60485
|
id: id3,
|
|
@@ -60246,7 +60496,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
60246
60496
|
`Target version: ${version2}`,
|
|
60247
60497
|
""
|
|
60248
60498
|
].join("\n");
|
|
60249
|
-
ctx.storage.write(
|
|
60499
|
+
ctx.storage.write(path101, meta3, body);
|
|
60250
60500
|
return { id: id3, created: true };
|
|
60251
60501
|
}
|
|
60252
60502
|
function readPlanSummary(ctx) {
|
|
@@ -60450,7 +60700,7 @@ function addIdeaStub(ctx) {
|
|
|
60450
60700
|
const tags = args["tags"] ?? [];
|
|
60451
60701
|
const category = args["category"] ?? "General";
|
|
60452
60702
|
const id3 = `${nextAdrId(ctx)}-${slugify3(title)}`;
|
|
60453
|
-
const
|
|
60703
|
+
const path101 = workspaceArtifact(ctx.rootDir, "decisions", id3);
|
|
60454
60704
|
const meta3 = {
|
|
60455
60705
|
kind: "adr",
|
|
60456
60706
|
status: "proposed",
|
|
@@ -60476,7 +60726,7 @@ function addIdeaStub(ctx) {
|
|
|
60476
60726
|
...consequences.map((c) => `- ${c}`),
|
|
60477
60727
|
""
|
|
60478
60728
|
].join("\n");
|
|
60479
|
-
ctx.storage.write(
|
|
60729
|
+
ctx.storage.write(path101, meta3, body);
|
|
60480
60730
|
return `ADR ${id3} created: "${title}". Status: proposed. Promote to accepted via /update ADR or manual edit.`;
|
|
60481
60731
|
});
|
|
60482
60732
|
}
|
|
@@ -60558,14 +60808,14 @@ function createDocumentStub(ctx) {
|
|
|
60558
60808
|
ctx.storage.write(risksPath, riskMeta, content);
|
|
60559
60809
|
return `Document "${title}" created at risks.md (workspace root).`;
|
|
60560
60810
|
}
|
|
60561
|
-
const
|
|
60811
|
+
const path101 = workspaceArtifact(ctx.rootDir, "docs", slug);
|
|
60562
60812
|
const meta3 = {
|
|
60563
60813
|
kind: "doc",
|
|
60564
60814
|
id: slug,
|
|
60565
60815
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
60566
60816
|
tags
|
|
60567
60817
|
};
|
|
60568
|
-
ctx.storage.write(
|
|
60818
|
+
ctx.storage.write(path101, meta3, content);
|
|
60569
60819
|
return `Document "${title}" created at docs/${slug}.md.`;
|
|
60570
60820
|
});
|
|
60571
60821
|
}
|
|
@@ -61190,10 +61440,10 @@ function getUserMcpPath() {
|
|
|
61190
61440
|
function getProjectMcpPath(projectRoot) {
|
|
61191
61441
|
return join32(projectRoot, ".zelari", "mcp.json");
|
|
61192
61442
|
}
|
|
61193
|
-
function readFile9(
|
|
61194
|
-
if (!existsSync42(
|
|
61443
|
+
function readFile9(path101) {
|
|
61444
|
+
if (!existsSync42(path101)) return {};
|
|
61195
61445
|
try {
|
|
61196
|
-
const parsed = JSON.parse(readFileSync30(
|
|
61446
|
+
const parsed = JSON.parse(readFileSync30(path101, "utf8"));
|
|
61197
61447
|
const out = {};
|
|
61198
61448
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
61199
61449
|
const hasCommand = !!cfg && typeof cfg.command === "string" && !!cfg.command.trim();
|
|
@@ -61215,10 +61465,10 @@ function readFile9(path100) {
|
|
|
61215
61465
|
return {};
|
|
61216
61466
|
}
|
|
61217
61467
|
}
|
|
61218
|
-
function writeFile3(
|
|
61219
|
-
mkdirSync17(dirname9(
|
|
61468
|
+
function writeFile3(path101, servers) {
|
|
61469
|
+
mkdirSync17(dirname9(path101), { recursive: true });
|
|
61220
61470
|
const body = { mcpServers: servers };
|
|
61221
|
-
writeFileSync19(
|
|
61471
|
+
writeFileSync19(path101, `${JSON.stringify(body, null, 2)}
|
|
61222
61472
|
`, "utf8");
|
|
61223
61473
|
}
|
|
61224
61474
|
function listMcpServers(projectRoot) {
|
|
@@ -61256,9 +61506,9 @@ function upsertMcpServer(opts) {
|
|
|
61256
61506
|
error: "either command (stdio) or url (http) is required"
|
|
61257
61507
|
};
|
|
61258
61508
|
}
|
|
61259
|
-
let
|
|
61509
|
+
let path101;
|
|
61260
61510
|
if (opts.scope === "user") {
|
|
61261
|
-
|
|
61511
|
+
path101 = getUserMcpPath();
|
|
61262
61512
|
} else {
|
|
61263
61513
|
const root = opts.projectRoot?.trim();
|
|
61264
61514
|
if (!root) {
|
|
@@ -61267,9 +61517,9 @@ function upsertMcpServer(opts) {
|
|
|
61267
61517
|
error: "projectRoot required for project scope (Open Folder first)"
|
|
61268
61518
|
};
|
|
61269
61519
|
}
|
|
61270
|
-
|
|
61520
|
+
path101 = getProjectMcpPath(root);
|
|
61271
61521
|
}
|
|
61272
|
-
const current = readFile9(
|
|
61522
|
+
const current = readFile9(path101);
|
|
61273
61523
|
current[name] = {
|
|
61274
61524
|
command: hasCommand ? opts.config.command.trim() : void 0,
|
|
61275
61525
|
args: opts.config.args,
|
|
@@ -61280,21 +61530,21 @@ function upsertMcpServer(opts) {
|
|
|
61280
61530
|
serial: opts.config.serial,
|
|
61281
61531
|
enabled: opts.config.enabled !== false
|
|
61282
61532
|
};
|
|
61283
|
-
writeFile3(
|
|
61284
|
-
return { ok: true, path:
|
|
61533
|
+
writeFile3(path101, current);
|
|
61534
|
+
return { ok: true, path: path101 };
|
|
61285
61535
|
}
|
|
61286
61536
|
function removeMcpServer(opts) {
|
|
61287
|
-
const
|
|
61288
|
-
if (!
|
|
61537
|
+
const path101 = opts.scope === "user" ? getUserMcpPath() : opts.projectRoot ? getProjectMcpPath(opts.projectRoot) : null;
|
|
61538
|
+
if (!path101) {
|
|
61289
61539
|
return { ok: false, error: "projectRoot required for project scope" };
|
|
61290
61540
|
}
|
|
61291
|
-
const current = readFile9(
|
|
61541
|
+
const current = readFile9(path101);
|
|
61292
61542
|
if (!(opts.name in current)) {
|
|
61293
|
-
return { ok: false, error: `Server "${opts.name}" not found in ${
|
|
61543
|
+
return { ok: false, error: `Server "${opts.name}" not found in ${path101}` };
|
|
61294
61544
|
}
|
|
61295
61545
|
delete current[opts.name];
|
|
61296
|
-
writeFile3(
|
|
61297
|
-
return { ok: true, path:
|
|
61546
|
+
writeFile3(path101, current);
|
|
61547
|
+
return { ok: true, path: path101 };
|
|
61298
61548
|
}
|
|
61299
61549
|
var init_mcpConfigIo = __esm({
|
|
61300
61550
|
"src/cli/mcp/mcpConfigIo.ts"() {
|
|
@@ -61765,10 +62015,10 @@ import { createHash as createHash21 } from "node:crypto";
|
|
|
61765
62015
|
import { join as join34 } from "node:path";
|
|
61766
62016
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
61767
62017
|
async function readPackageJson3(projectRoot) {
|
|
61768
|
-
const
|
|
61769
|
-
if (!existsSync44(
|
|
62018
|
+
const path101 = join34(projectRoot, "package.json");
|
|
62019
|
+
if (!existsSync44(path101)) return null;
|
|
61770
62020
|
try {
|
|
61771
|
-
return JSON.parse(await readFile10(
|
|
62021
|
+
return JSON.parse(await readFile10(path101, "utf8"));
|
|
61772
62022
|
} catch {
|
|
61773
62023
|
return null;
|
|
61774
62024
|
}
|
|
@@ -61850,9 +62100,9 @@ async function genBuild(ctx) {
|
|
|
61850
62100
|
].join("\n");
|
|
61851
62101
|
}
|
|
61852
62102
|
async function genOpenQuestions(ctx) {
|
|
61853
|
-
const
|
|
61854
|
-
if (!existsSync44(
|
|
61855
|
-
const content = readFileSync32(
|
|
62103
|
+
const path101 = join34(ctx.rootDir, "risks.md");
|
|
62104
|
+
if (!existsSync44(path101)) return "_No open questions._";
|
|
62105
|
+
const content = readFileSync32(path101, "utf8");
|
|
61856
62106
|
const lines = content.split("\n");
|
|
61857
62107
|
const questions = [];
|
|
61858
62108
|
let currentTitle = "";
|
|
@@ -62126,9 +62376,9 @@ function versionKey(value) {
|
|
|
62126
62376
|
function firstString2(v) {
|
|
62127
62377
|
return typeof v === "string" && v.trim().length > 0 ? v : null;
|
|
62128
62378
|
}
|
|
62129
|
-
function readFileSyncSafe(
|
|
62379
|
+
function readFileSyncSafe(path101) {
|
|
62130
62380
|
try {
|
|
62131
|
-
return readFileSync33(
|
|
62381
|
+
return readFileSync33(path101, "utf8");
|
|
62132
62382
|
} catch {
|
|
62133
62383
|
return null;
|
|
62134
62384
|
}
|
|
@@ -62376,7 +62626,7 @@ __export(evidenceFromSpine_exports, {
|
|
|
62376
62626
|
evidenceRefsFromEventLines: () => evidenceRefsFromEventLines
|
|
62377
62627
|
});
|
|
62378
62628
|
import { existsSync as existsSync47, readFileSync as readFileSync35 } from "node:fs";
|
|
62379
|
-
import
|
|
62629
|
+
import path72 from "node:path";
|
|
62380
62630
|
function asRecord2(v) {
|
|
62381
62631
|
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
62382
62632
|
}
|
|
@@ -62414,7 +62664,7 @@ function evidenceRefsFromEventLines(lines) {
|
|
|
62414
62664
|
}
|
|
62415
62665
|
function collectSessionEvidenceRefs(sessionId2) {
|
|
62416
62666
|
try {
|
|
62417
|
-
const file2 =
|
|
62667
|
+
const file2 = path72.join(sessionsDir(), sessionId2, "events.jsonl");
|
|
62418
62668
|
if (!existsSync47(file2)) return [];
|
|
62419
62669
|
return evidenceRefsFromEventLines(readFileSync35(file2, "utf8").split("\n"));
|
|
62420
62670
|
} catch {
|
|
@@ -62664,8 +62914,8 @@ async function runPostCouncilHook(ctx, options) {
|
|
|
62664
62914
|
sources: scope.sources
|
|
62665
62915
|
} : void 0
|
|
62666
62916
|
});
|
|
62667
|
-
const
|
|
62668
|
-
completionHook = { ran: true, path:
|
|
62917
|
+
const path101 = writeCouncilCompletion(ctx.rootDir, completion);
|
|
62918
|
+
completionHook = { ran: true, path: path101, completion };
|
|
62669
62919
|
} catch (err) {
|
|
62670
62920
|
completionHook = {
|
|
62671
62921
|
ran: true,
|
|
@@ -62710,7 +62960,7 @@ import {
|
|
|
62710
62960
|
writeFileSync as writeFileSync22,
|
|
62711
62961
|
mkdirSync as mkdirSync18
|
|
62712
62962
|
} from "node:fs";
|
|
62713
|
-
import
|
|
62963
|
+
import path73 from "node:path";
|
|
62714
62964
|
var FeedbackStore;
|
|
62715
62965
|
var init_councilFeedback = __esm({
|
|
62716
62966
|
"src/cli/councilFeedback.ts"() {
|
|
@@ -62827,7 +63077,7 @@ var init_councilFeedback = __esm({
|
|
|
62827
63077
|
}
|
|
62828
63078
|
}
|
|
62829
63079
|
save() {
|
|
62830
|
-
mkdirSync18(
|
|
63080
|
+
mkdirSync18(path73.dirname(this.file), { recursive: true });
|
|
62831
63081
|
writeFileSync22(
|
|
62832
63082
|
this.file,
|
|
62833
63083
|
JSON.stringify({ entries: this.entries }, null, 2),
|
|
@@ -62902,12 +63152,12 @@ __export(ledger_exports, {
|
|
|
62902
63152
|
readLedger: () => readLedger
|
|
62903
63153
|
});
|
|
62904
63154
|
import { appendFileSync as appendFileSync4, existsSync as existsSync50, mkdirSync as mkdirSync19, readFileSync as readFileSync38 } from "node:fs";
|
|
62905
|
-
import
|
|
63155
|
+
import path74 from "node:path";
|
|
62906
63156
|
function evolutionMode(env = process.env) {
|
|
62907
63157
|
return env[EVOLUTION_ENV] === "shadow" ? "shadow" : "0";
|
|
62908
63158
|
}
|
|
62909
63159
|
function ledgerPath(cwd) {
|
|
62910
|
-
return
|
|
63160
|
+
return path74.join(cwd, LEDGER_REL);
|
|
62911
63161
|
}
|
|
62912
63162
|
function appendLedgerEntry(cwd, entry) {
|
|
62913
63163
|
if (evolutionMode() === "0") {
|
|
@@ -62915,7 +63165,7 @@ function appendLedgerEntry(cwd, entry) {
|
|
|
62915
63165
|
}
|
|
62916
63166
|
try {
|
|
62917
63167
|
const file2 = ledgerPath(cwd);
|
|
62918
|
-
mkdirSync19(
|
|
63168
|
+
mkdirSync19(path74.dirname(file2), { recursive: true });
|
|
62919
63169
|
appendFileSync4(file2, `${JSON.stringify(entry)}
|
|
62920
63170
|
`, "utf8");
|
|
62921
63171
|
return { written: true, path: file2 };
|
|
@@ -63016,7 +63266,7 @@ var init_ledger = __esm({
|
|
|
63016
63266
|
"src/cli/evolution/ledger.ts"() {
|
|
63017
63267
|
"use strict";
|
|
63018
63268
|
EVOLUTION_ENV = "ZELARI_EVOLUTION";
|
|
63019
|
-
LEDGER_REL =
|
|
63269
|
+
LEDGER_REL = path74.join(".zelari", "evolution", "ledger.jsonl");
|
|
63020
63270
|
TIER_WEIGHTS = {
|
|
63021
63271
|
build: 1,
|
|
63022
63272
|
"tool-output": 1,
|
|
@@ -63158,7 +63408,7 @@ __export(fileBackend_exports, {
|
|
|
63158
63408
|
});
|
|
63159
63409
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
63160
63410
|
import { promises as fs31 } from "node:fs";
|
|
63161
|
-
import * as
|
|
63411
|
+
import * as path75 from "node:path";
|
|
63162
63412
|
function tokenize2(text) {
|
|
63163
63413
|
return text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 3);
|
|
63164
63414
|
}
|
|
@@ -63211,8 +63461,8 @@ var init_fileBackend = __esm({
|
|
|
63211
63461
|
logPath = "";
|
|
63212
63462
|
memoryDir = "";
|
|
63213
63463
|
async init(projectRoot) {
|
|
63214
|
-
this.memoryDir =
|
|
63215
|
-
this.logPath =
|
|
63464
|
+
this.memoryDir = path75.join(projectRoot, ".zelari", "memory");
|
|
63465
|
+
this.logPath = path75.join(this.memoryDir, "log.jsonl");
|
|
63216
63466
|
await fs31.mkdir(this.memoryDir, { recursive: true });
|
|
63217
63467
|
}
|
|
63218
63468
|
async add(content, metadata2 = {}, graph) {
|
|
@@ -63285,12 +63535,12 @@ var init_fileBackend = __esm({
|
|
|
63285
63535
|
|
|
63286
63536
|
// src/cli/traceStore.ts
|
|
63287
63537
|
import { promises as fs32 } from "node:fs";
|
|
63288
|
-
import * as
|
|
63538
|
+
import * as path76 from "node:path";
|
|
63289
63539
|
function traceDir(projectRoot) {
|
|
63290
|
-
return
|
|
63540
|
+
return path76.join(projectRoot, ".zelari", "trace");
|
|
63291
63541
|
}
|
|
63292
63542
|
function tracePath(projectRoot, missionId) {
|
|
63293
|
-
return
|
|
63543
|
+
return path76.join(traceDir(projectRoot), `${missionId}.json`);
|
|
63294
63544
|
}
|
|
63295
63545
|
async function saveTrace(projectRoot, missionId, entries) {
|
|
63296
63546
|
const dir = traceDir(projectRoot);
|
|
@@ -63332,7 +63582,7 @@ __export(zelariMission_exports, {
|
|
|
63332
63582
|
});
|
|
63333
63583
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
63334
63584
|
import { promises as fs33 } from "node:fs";
|
|
63335
|
-
import * as
|
|
63585
|
+
import * as path77 from "node:path";
|
|
63336
63586
|
function resolveMaxIterations(env = process.env) {
|
|
63337
63587
|
const raw = env.ZELARI_MISSION_MAX_ITER;
|
|
63338
63588
|
const n = raw ? Number.parseInt(raw, 10) : DEFAULT_MAX_ITER;
|
|
@@ -63375,10 +63625,10 @@ function isMissionAutoStart(env = process.env) {
|
|
|
63375
63625
|
return env.ZELARI_MISSION_AUTO === "1";
|
|
63376
63626
|
}
|
|
63377
63627
|
async function writeMissionState(projectRoot, state3) {
|
|
63378
|
-
const dir =
|
|
63628
|
+
const dir = path77.join(projectRoot, ".zelari");
|
|
63379
63629
|
await fs33.mkdir(dir, { recursive: true });
|
|
63380
63630
|
await fs33.writeFile(
|
|
63381
|
-
|
|
63631
|
+
path77.join(dir, "mission-state.json"),
|
|
63382
63632
|
JSON.stringify(state3, null, 2) + "\n",
|
|
63383
63633
|
"utf8"
|
|
63384
63634
|
);
|
|
@@ -63392,7 +63642,7 @@ async function writeMissionState(projectRoot, state3) {
|
|
|
63392
63642
|
async function loadMissionState(projectRoot) {
|
|
63393
63643
|
try {
|
|
63394
63644
|
const raw = await fs33.readFile(
|
|
63395
|
-
|
|
63645
|
+
path77.join(projectRoot, ".zelari", "mission-state.json"),
|
|
63396
63646
|
"utf8"
|
|
63397
63647
|
);
|
|
63398
63648
|
const parsed = JSON.parse(raw);
|
|
@@ -64151,7 +64401,7 @@ function safeSocketPath(socketPath) {
|
|
|
64151
64401
|
return socketPath.trim();
|
|
64152
64402
|
}
|
|
64153
64403
|
function startPermissionBroker(socketPath, handlers, opts) {
|
|
64154
|
-
const
|
|
64404
|
+
const path101 = safeSocketPath(socketPath);
|
|
64155
64405
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
64156
64406
|
const sockets = /* @__PURE__ */ new Set();
|
|
64157
64407
|
const server = createServer2((socket) => {
|
|
@@ -64251,10 +64501,10 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
64251
64501
|
return new Promise((resolve9, reject) => {
|
|
64252
64502
|
const onError = (err) => reject(err);
|
|
64253
64503
|
server.once("error", onError);
|
|
64254
|
-
server.listen(
|
|
64504
|
+
server.listen(path101, () => {
|
|
64255
64505
|
server.removeListener("error", onError);
|
|
64256
64506
|
resolve9({
|
|
64257
|
-
socketPath:
|
|
64507
|
+
socketPath: path101,
|
|
64258
64508
|
stop: () => new Promise((res) => {
|
|
64259
64509
|
for (const s of sockets) s.destroy();
|
|
64260
64510
|
sockets.clear();
|
|
@@ -64265,7 +64515,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
64265
64515
|
if (done) return;
|
|
64266
64516
|
done = true;
|
|
64267
64517
|
if (process.platform !== "win32") {
|
|
64268
|
-
unlink(
|
|
64518
|
+
unlink(path101, () => res());
|
|
64269
64519
|
} else {
|
|
64270
64520
|
res();
|
|
64271
64521
|
}
|
|
@@ -64278,11 +64528,11 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
64278
64528
|
});
|
|
64279
64529
|
}
|
|
64280
64530
|
function requestBrokerAsk(socketPath, ask, opts) {
|
|
64281
|
-
const
|
|
64531
|
+
const path101 = safeSocketPath(socketPath);
|
|
64282
64532
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
64283
64533
|
const connectTimeoutMs = opts?.connectTimeoutMs ?? PERMISSION_BROKER_DEFAULT_CONNECT_TIMEOUT_MS;
|
|
64284
64534
|
return new Promise((resolve9, reject) => {
|
|
64285
|
-
const socket = connect(
|
|
64535
|
+
const socket = connect(path101);
|
|
64286
64536
|
let buffer = "";
|
|
64287
64537
|
let settled = false;
|
|
64288
64538
|
const settle = (fn) => {
|
|
@@ -64297,7 +64547,7 @@ function requestBrokerAsk(socketPath, ask, opts) {
|
|
|
64297
64547
|
settle(
|
|
64298
64548
|
() => reject(
|
|
64299
64549
|
new Error(
|
|
64300
|
-
`permission broker unavailable at "${
|
|
64550
|
+
`permission broker unavailable at "${path101}" (connect timed out after ${connectTimeoutMs}ms)`
|
|
64301
64551
|
)
|
|
64302
64552
|
)
|
|
64303
64553
|
);
|
|
@@ -65486,7 +65736,7 @@ var init_prereqChecks = __esm({
|
|
|
65486
65736
|
|
|
65487
65737
|
// src/cli/plugins/prefs.ts
|
|
65488
65738
|
import { existsSync as existsSync53, readFileSync as readFileSync40, writeFileSync as writeFileSync23, mkdirSync as mkdirSync20 } from "node:fs";
|
|
65489
|
-
import
|
|
65739
|
+
import path83 from "node:path";
|
|
65490
65740
|
function getPluginPrefsPath() {
|
|
65491
65741
|
return pluginsPrefsPath();
|
|
65492
65742
|
}
|
|
@@ -65509,7 +65759,7 @@ function getPluginPrefs() {
|
|
|
65509
65759
|
}
|
|
65510
65760
|
function writePluginPrefs(prefs) {
|
|
65511
65761
|
const file2 = getPluginPrefsPath();
|
|
65512
|
-
mkdirSync20(
|
|
65762
|
+
mkdirSync20(path83.dirname(file2), { recursive: true });
|
|
65513
65763
|
writeFileSync23(file2, JSON.stringify(prefs, null, 2), {
|
|
65514
65764
|
encoding: "utf-8",
|
|
65515
65765
|
mode: 384
|
|
@@ -65547,7 +65797,7 @@ __export(registry_exports, {
|
|
|
65547
65797
|
isBinaryOnPath: () => isBinaryOnPath
|
|
65548
65798
|
});
|
|
65549
65799
|
import { existsSync as existsSync54 } from "node:fs";
|
|
65550
|
-
import
|
|
65800
|
+
import path84 from "node:path";
|
|
65551
65801
|
function detectLocalBin(bin) {
|
|
65552
65802
|
return (cwd) => {
|
|
65553
65803
|
try {
|
|
@@ -65565,7 +65815,7 @@ function isBinaryOnPath(bin, opts = {}) {
|
|
|
65565
65815
|
const platform = opts.platform ?? process.platform;
|
|
65566
65816
|
const exists = opts.exists ?? existsSync54;
|
|
65567
65817
|
const pathEnv = opts.pathEnv ?? process.env.PATH ?? "";
|
|
65568
|
-
const pathMod = platform === "win32" ?
|
|
65818
|
+
const pathMod = platform === "win32" ? path84.win32 : path84.posix;
|
|
65569
65819
|
const sep4 = platform === "win32" ? ";" : ":";
|
|
65570
65820
|
const dirs = pathEnv.split(sep4).filter((d) => d.length > 0);
|
|
65571
65821
|
const candidates = [bin];
|
|
@@ -66670,7 +66920,7 @@ var init_policy = __esm({
|
|
|
66670
66920
|
|
|
66671
66921
|
// src/cli/orchestration/facts.ts
|
|
66672
66922
|
import { promises as fs43 } from "node:fs";
|
|
66673
|
-
import
|
|
66923
|
+
import path88 from "node:path";
|
|
66674
66924
|
async function collectRepoFileCount(root = process.cwd()) {
|
|
66675
66925
|
try {
|
|
66676
66926
|
await fs43.readdir(root);
|
|
@@ -66690,7 +66940,7 @@ async function collectRepoFileCount(root = process.cwd()) {
|
|
|
66690
66940
|
}
|
|
66691
66941
|
for (const e of entries) {
|
|
66692
66942
|
if (e.isDirectory()) {
|
|
66693
|
-
if (!SKIP_DIRS.has(e.name)) queue.push(
|
|
66943
|
+
if (!SKIP_DIRS.has(e.name)) queue.push(path88.join(dir, e.name));
|
|
66694
66944
|
} else if (e.isFile()) {
|
|
66695
66945
|
count++;
|
|
66696
66946
|
if (count > MAX_WALK_FILES) return count;
|
|
@@ -66788,7 +67038,7 @@ var init_streamScrub = __esm({
|
|
|
66788
67038
|
});
|
|
66789
67039
|
|
|
66790
67040
|
// src/cli/harnessState.ts
|
|
66791
|
-
import
|
|
67041
|
+
import path89 from "node:path";
|
|
66792
67042
|
function asString4(v) {
|
|
66793
67043
|
return typeof v === "string" ? v : "";
|
|
66794
67044
|
}
|
|
@@ -66963,7 +67213,7 @@ function contractFor(t) {
|
|
|
66963
67213
|
};
|
|
66964
67214
|
}
|
|
66965
67215
|
async function readHarnessState(sessionDir) {
|
|
66966
|
-
const report = await readSessionLog(
|
|
67216
|
+
const report = await readSessionLog(path89.join(sessionDir, "events.jsonl"));
|
|
66967
67217
|
return deriveHarnessState(report.events);
|
|
66968
67218
|
}
|
|
66969
67219
|
var init_harnessState = __esm({
|
|
@@ -66974,12 +67224,12 @@ var init_harnessState = __esm({
|
|
|
66974
67224
|
});
|
|
66975
67225
|
|
|
66976
67226
|
// src/cli/headless/harnessStateEmit.ts
|
|
66977
|
-
import
|
|
67227
|
+
import path90 from "node:path";
|
|
66978
67228
|
async function emitHarnessStateEvent(opts) {
|
|
66979
67229
|
if (opts.output !== "json") return;
|
|
66980
67230
|
try {
|
|
66981
67231
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.workspaceRoot });
|
|
66982
|
-
const state3 = await readHarnessState(
|
|
67232
|
+
const state3 = await readHarnessState(path90.join(sessionsDir2, opts.spine.sessionId));
|
|
66983
67233
|
opts.emitEvent({ type: "harness_state", ...state3 });
|
|
66984
67234
|
} catch (err) {
|
|
66985
67235
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -67536,13 +67786,13 @@ var init_verifierLifecycle = __esm({
|
|
|
67536
67786
|
|
|
67537
67787
|
// src/cli/extensions/sandboxedFs.ts
|
|
67538
67788
|
import { promises as fsp } from "node:fs";
|
|
67539
|
-
import
|
|
67789
|
+
import path91 from "node:path";
|
|
67540
67790
|
function errText(prefix, p3, err) {
|
|
67541
67791
|
const msg = err instanceof Error ? err.message : String(err);
|
|
67542
67792
|
return `[extension-fs] ${prefix} "${p3}": ${msg}`;
|
|
67543
67793
|
}
|
|
67544
67794
|
function bindSandboxedFs(root) {
|
|
67545
|
-
const resolvedRoot =
|
|
67795
|
+
const resolvedRoot = path91.resolve(root);
|
|
67546
67796
|
return {
|
|
67547
67797
|
root: resolvedRoot,
|
|
67548
67798
|
async readFile(relativePath) {
|
|
@@ -67558,7 +67808,7 @@ function bindSandboxedFs(root) {
|
|
|
67558
67808
|
try {
|
|
67559
67809
|
const target = resolveSandboxedPath(relativePath, { root: resolvedRoot });
|
|
67560
67810
|
verifyContainment(target, { root: resolvedRoot });
|
|
67561
|
-
await fsp.mkdir(
|
|
67811
|
+
await fsp.mkdir(path91.dirname(target), { recursive: true });
|
|
67562
67812
|
await fsp.writeFile(target, data, "utf8");
|
|
67563
67813
|
return typedOk({ path: target });
|
|
67564
67814
|
} catch (err) {
|
|
@@ -67743,7 +67993,7 @@ var init_loader = __esm({
|
|
|
67743
67993
|
|
|
67744
67994
|
// src/cli/headless/runOneTurn.ts
|
|
67745
67995
|
import { promises as fs44 } from "node:fs";
|
|
67746
|
-
import
|
|
67996
|
+
import path92 from "node:path";
|
|
67747
67997
|
function planModeFromOpts(opts) {
|
|
67748
67998
|
return (opts.phase ?? "build") === "plan";
|
|
67749
67999
|
}
|
|
@@ -68221,11 +68471,14 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
68221
68471
|
return null;
|
|
68222
68472
|
}
|
|
68223
68473
|
},
|
|
68224
|
-
|
|
68474
|
+
// F3 seam adapter (same as the gate sites below): the core engine reads
|
|
68475
|
+
// the anchor as `out.seq`, while the spine resolves the seq NUMBER. A bare
|
|
68476
|
+
// number here leaves the review evidence unanchored on the spine.
|
|
68477
|
+
emit: async (input) => ({ seq: await spine.appendEvent(input) })
|
|
68225
68478
|
};
|
|
68226
68479
|
const strictEnv = strictEnvOverlay(opts);
|
|
68227
68480
|
if (pass.finalReason === "completed" && pass.exitCode === 0 && isKrakenMode(opts.mode) && (isKrakenSelectionEnabled() || nativePackEnabled()) && !planModeFromOpts(opts)) {
|
|
68228
|
-
const strictGate = await evaluateStrictBuildGate("build", { emit: (input) => spine.appendEvent(input), cwd, env: strictEnv });
|
|
68481
|
+
const strictGate = await evaluateStrictBuildGate("build", { emit: async (input) => ({ seq: await spine.appendEvent(input) }), cwd, env: strictEnv });
|
|
68229
68482
|
await runAdvisoryVerifierReview(strictGate, verifierReviewDeps).catch(() => void 0);
|
|
68230
68483
|
const gate = strictGate.gate;
|
|
68231
68484
|
const verificationPayload = strictGateEventPayload(strictGate);
|
|
@@ -68235,7 +68488,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
68235
68488
|
}
|
|
68236
68489
|
await writeProofSafe(strictGate, { surface: "kraken", sessionId: spine.sessionId }, cwd);
|
|
68237
68490
|
if (strictGate.blocked) {
|
|
68238
|
-
const repairPrompt = buildKrakenRepairPrompt(gate);
|
|
68491
|
+
const repairPrompt = buildKrakenRepairPrompt(gate, repairExcerptsFromEvaluation(strictGate));
|
|
68239
68492
|
if (opts.output === "json") {
|
|
68240
68493
|
emitEvent({
|
|
68241
68494
|
type: "log",
|
|
@@ -68260,7 +68513,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
68260
68513
|
successfulWrites: pass.successfulWrites + repair.successfulWrites,
|
|
68261
68514
|
emittedWrites: pass.emittedWrites + repair.emittedWrites
|
|
68262
68515
|
};
|
|
68263
|
-
const after = await evaluateStrictBuildGate("build", { emit: (input) => spine.appendEvent(input), cwd, env: strictEnv });
|
|
68516
|
+
const after = await evaluateStrictBuildGate("build", { emit: async (input) => ({ seq: await spine.appendEvent(input) }), cwd, env: strictEnv });
|
|
68264
68517
|
await runAdvisoryVerifierReview(after, verifierReviewDeps).catch(() => void 0);
|
|
68265
68518
|
const afterPayload = strictGateEventPayload(after);
|
|
68266
68519
|
spine.verificationRun(afterPayload);
|
|
@@ -68310,7 +68563,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
68310
68563
|
if (json3) {
|
|
68311
68564
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
68312
68565
|
else {
|
|
68313
|
-
await fs44.mkdir(
|
|
68566
|
+
await fs44.mkdir(path92.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
68314
68567
|
await fs44.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
68315
68568
|
}
|
|
68316
68569
|
}
|
|
@@ -69359,9 +69612,9 @@ __export(triggerLock_exports, {
|
|
|
69359
69612
|
releaseLock: () => releaseLock
|
|
69360
69613
|
});
|
|
69361
69614
|
import { promises as fs45 } from "node:fs";
|
|
69362
|
-
import * as
|
|
69615
|
+
import * as path93 from "node:path";
|
|
69363
69616
|
function lockPath(projectRoot) {
|
|
69364
|
-
return
|
|
69617
|
+
return path93.join(projectRoot, ".zelari", "trigger.lock");
|
|
69365
69618
|
}
|
|
69366
69619
|
function isPidAlive(pid) {
|
|
69367
69620
|
try {
|
|
@@ -69374,7 +69627,7 @@ function isPidAlive(pid) {
|
|
|
69374
69627
|
}
|
|
69375
69628
|
async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date()) {
|
|
69376
69629
|
const lp = lockPath(projectRoot);
|
|
69377
|
-
const dir =
|
|
69630
|
+
const dir = path93.dirname(lp);
|
|
69378
69631
|
await fs45.mkdir(dir, { recursive: true });
|
|
69379
69632
|
try {
|
|
69380
69633
|
const raw = await fs45.readFile(lp, "utf8");
|
|
@@ -69406,7 +69659,7 @@ var init_triggerLock = __esm({
|
|
|
69406
69659
|
|
|
69407
69660
|
// src/cli/runHeadless.ts
|
|
69408
69661
|
import { promises as fs46 } from "node:fs";
|
|
69409
|
-
import
|
|
69662
|
+
import path94 from "node:path";
|
|
69410
69663
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
69411
69664
|
async function runHeadless(opts) {
|
|
69412
69665
|
resetTaskSpawnCount();
|
|
@@ -69650,7 +69903,7 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
69650
69903
|
try {
|
|
69651
69904
|
let preflightGraph;
|
|
69652
69905
|
if (opts.runPlan && opts.runPlan.trim() !== "") {
|
|
69653
|
-
const planPath =
|
|
69906
|
+
const planPath = path94.join(cwd, ".zelari", "radio", `plan-${opts.runPlan}.json`);
|
|
69654
69907
|
log(`loading pre-flight plan: ${planPath}`);
|
|
69655
69908
|
let raw;
|
|
69656
69909
|
try {
|
|
@@ -69693,8 +69946,8 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
69693
69946
|
log(formatKrakenGraphAscii2(graph));
|
|
69694
69947
|
if (opts.planOnly) {
|
|
69695
69948
|
const planId = randomUUID10();
|
|
69696
|
-
const planDir =
|
|
69697
|
-
const planPath =
|
|
69949
|
+
const planDir = path94.join(cwd, ".zelari", "radio");
|
|
69950
|
+
const planPath = path94.join(planDir, `plan-${planId}.json`);
|
|
69698
69951
|
await fs46.mkdir(planDir, { recursive: true });
|
|
69699
69952
|
await fs46.writeFile(
|
|
69700
69953
|
planPath,
|
|
@@ -70085,7 +70338,7 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
70085
70338
|
if (json3) {
|
|
70086
70339
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
70087
70340
|
else {
|
|
70088
|
-
await fs46.mkdir(
|
|
70341
|
+
await fs46.mkdir(path94.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
70089
70342
|
await fs46.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
70090
70343
|
}
|
|
70091
70344
|
}
|
|
@@ -70508,6 +70761,22 @@ ${ragContext}` : slicePrompt;
|
|
|
70508
70761
|
if (missionGate.blocked) {
|
|
70509
70762
|
exitCode = strictGateExitCode(missionGate);
|
|
70510
70763
|
spine.missionPhase("verification", "mission-strict-blocked");
|
|
70764
|
+
} else if (
|
|
70765
|
+
// M2.1/R4b: an open strict gate is not enough — the success claim must
|
|
70766
|
+
// be event-backed: zero `verification.evidence` events in the spine
|
|
70767
|
+
// means narration-only done → strict exit code. Same overlay seam as
|
|
70768
|
+
// the gate above (H10-fix1) so --allow-unverified /
|
|
70769
|
+
// ZELARI_ALLOW_UNVERIFIED=1 waives mission-side too. `opts.phase` is
|
|
70770
|
+
// the only phase/mode discriminant on this site: `--phase plan`
|
|
70771
|
+
// missions are design-only (no verification expected), so the gate
|
|
70772
|
+
// applies unconditionally to build-phase claims.
|
|
70773
|
+
opts.phase !== "plan" && missionClaimExitCode(await spine.countVerificationEvidence(), strictEnvOverlay(opts)) !== 0
|
|
70774
|
+
) {
|
|
70775
|
+
exitCode = STRICT_DONE_EXIT_CODE;
|
|
70776
|
+
spine.missionPhase("verification", "mission-event-back-missing");
|
|
70777
|
+
process.stderr.write(
|
|
70778
|
+
"[zelari-code --headless] mission success claim has zero verification.evidence events (narration-only done) \u2014 exit 4 (waive with --allow-unverified / ZELARI_ALLOW_UNVERIFIED=1)\n"
|
|
70779
|
+
);
|
|
70511
70780
|
} else {
|
|
70512
70781
|
exitCode = 0;
|
|
70513
70782
|
spine.missionPhase("done", "mission-success");
|
|
@@ -70541,7 +70810,7 @@ ${ragContext}` : slicePrompt;
|
|
|
70541
70810
|
if (json3) {
|
|
70542
70811
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
70543
70812
|
else {
|
|
70544
|
-
await fs46.mkdir(
|
|
70813
|
+
await fs46.mkdir(path94.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
70545
70814
|
await fs46.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
70546
70815
|
}
|
|
70547
70816
|
}
|
|
@@ -71166,7 +71435,7 @@ function upsertSkill(opts) {
|
|
|
71166
71435
|
}
|
|
71167
71436
|
dir = getProjectSkillsDir(root);
|
|
71168
71437
|
}
|
|
71169
|
-
const
|
|
71438
|
+
const path101 = skillFilePath(dir, name);
|
|
71170
71439
|
const content = serializeSkillMd({
|
|
71171
71440
|
name,
|
|
71172
71441
|
description,
|
|
@@ -71175,13 +71444,13 @@ function upsertSkill(opts) {
|
|
|
71175
71444
|
tools: opts.tools,
|
|
71176
71445
|
cost: opts.cost
|
|
71177
71446
|
});
|
|
71178
|
-
const parsed = parseSkillMd(content,
|
|
71447
|
+
const parsed = parseSkillMd(content, path101);
|
|
71179
71448
|
if (!parsed) {
|
|
71180
71449
|
return { ok: false, error: "Generated SKILL.md failed validation" };
|
|
71181
71450
|
}
|
|
71182
|
-
mkdirSync23(dirname13(
|
|
71183
|
-
writeFileSync25(
|
|
71184
|
-
return { ok: true, path:
|
|
71451
|
+
mkdirSync23(dirname13(path101), { recursive: true });
|
|
71452
|
+
writeFileSync25(path101, content, "utf8");
|
|
71453
|
+
return { ok: true, path: path101 };
|
|
71185
71454
|
}
|
|
71186
71455
|
function removeSkill(opts) {
|
|
71187
71456
|
const name = opts.name.trim().toLowerCase();
|
|
@@ -71199,8 +71468,8 @@ function removeSkill(opts) {
|
|
|
71199
71468
|
dir = getProjectSkillsDir(root);
|
|
71200
71469
|
}
|
|
71201
71470
|
const skillDir = join46(dir, name);
|
|
71202
|
-
const
|
|
71203
|
-
if (!existsSync59(
|
|
71471
|
+
const path101 = skillFilePath(dir, name);
|
|
71472
|
+
if (!existsSync59(path101) && !existsSync59(skillDir)) {
|
|
71204
71473
|
return { ok: false, error: `Skill "${name}" not found in ${dir}` };
|
|
71205
71474
|
}
|
|
71206
71475
|
try {
|
|
@@ -71211,7 +71480,7 @@ function removeSkill(opts) {
|
|
|
71211
71480
|
error: err instanceof Error ? err.message : String(err)
|
|
71212
71481
|
};
|
|
71213
71482
|
}
|
|
71214
|
-
return { ok: true, path:
|
|
71483
|
+
return { ok: true, path: path101 };
|
|
71215
71484
|
}
|
|
71216
71485
|
var NAME_RE, BUILTIN_SKILL_MODULES, builtinsLoaded;
|
|
71217
71486
|
var init_skillConfigIo = __esm({
|
|
@@ -71332,7 +71601,7 @@ var init_jsonApi = __esm({
|
|
|
71332
71601
|
});
|
|
71333
71602
|
|
|
71334
71603
|
// src/cli/memory/mcpAdapter.ts
|
|
71335
|
-
import * as
|
|
71604
|
+
import * as path95 from "node:path";
|
|
71336
71605
|
var id2, projectId, source, SearchSchema, AddSchema, LinkSchema, RetractSchema, MEMORY_MCP_TOOLS, MemoryMcpAdapter;
|
|
71337
71606
|
var init_mcpAdapter = __esm({
|
|
71338
71607
|
"src/cli/memory/mcpAdapter.ts"() {
|
|
@@ -71502,8 +71771,8 @@ var init_mcpAdapter = __esm({
|
|
|
71502
71771
|
this.takeWrite();
|
|
71503
71772
|
const externalFile = args.source?.file;
|
|
71504
71773
|
if (externalFile) {
|
|
71505
|
-
const normalized =
|
|
71506
|
-
if (
|
|
71774
|
+
const normalized = path95.normalize(externalFile);
|
|
71775
|
+
if (path95.isAbsolute(normalized) || normalized === ".." || normalized.startsWith(`..${path95.sep}`)) {
|
|
71507
71776
|
throw new Error("source.file must be project-relative and cannot escape the project");
|
|
71508
71777
|
}
|
|
71509
71778
|
}
|
|
@@ -72030,12 +72299,12 @@ function ensureHome() {
|
|
|
72030
72299
|
}
|
|
72031
72300
|
}
|
|
72032
72301
|
function loadCompanionConfig() {
|
|
72033
|
-
const
|
|
72034
|
-
if (!existsSync60(
|
|
72302
|
+
const path101 = getCompanionConfigPath();
|
|
72303
|
+
if (!existsSync60(path101)) {
|
|
72035
72304
|
return { projects: [] };
|
|
72036
72305
|
}
|
|
72037
72306
|
try {
|
|
72038
|
-
const raw = JSON.parse(readFileSync45(
|
|
72307
|
+
const raw = JSON.parse(readFileSync45(path101, "utf8"));
|
|
72039
72308
|
const projects = Array.isArray(raw.projects) ? raw.projects.filter(
|
|
72040
72309
|
(p3) => p3 && typeof p3.path === "string" && p3.path.trim() && typeof (p3.id ?? p3.name) === "string"
|
|
72041
72310
|
).map((p3) => ({
|
|
@@ -72073,16 +72342,16 @@ function loadOrCreateToken(explicit) {
|
|
|
72073
72342
|
return { token: explicit.trim(), created: false };
|
|
72074
72343
|
}
|
|
72075
72344
|
ensureHome();
|
|
72076
|
-
const
|
|
72077
|
-
if (existsSync60(
|
|
72078
|
-
const t = readFileSync45(
|
|
72345
|
+
const path101 = getCompanionTokenPath();
|
|
72346
|
+
if (existsSync60(path101)) {
|
|
72347
|
+
const t = readFileSync45(path101, "utf8").trim();
|
|
72079
72348
|
if (t) return { token: t, created: false };
|
|
72080
72349
|
}
|
|
72081
72350
|
const token = randomBytes7(24).toString("base64url");
|
|
72082
|
-
writeFileSync26(
|
|
72351
|
+
writeFileSync26(path101, token + "\n", "utf8");
|
|
72083
72352
|
try {
|
|
72084
72353
|
const fs48 = __require("node:fs");
|
|
72085
|
-
fs48.chmodSync?.(
|
|
72354
|
+
fs48.chmodSync?.(path101, 384);
|
|
72086
72355
|
} catch {
|
|
72087
72356
|
}
|
|
72088
72357
|
return { token, created: true };
|
|
@@ -72107,17 +72376,17 @@ function mergeProjects(cfg, extraPaths) {
|
|
|
72107
72376
|
byId.set(p3.id, p3);
|
|
72108
72377
|
}
|
|
72109
72378
|
for (const raw of extraPaths) {
|
|
72110
|
-
const
|
|
72111
|
-
if (!
|
|
72112
|
-
let id3 = slugFromPath(
|
|
72379
|
+
const path101 = raw.trim();
|
|
72380
|
+
if (!path101) continue;
|
|
72381
|
+
let id3 = slugFromPath(path101);
|
|
72113
72382
|
let n = 2;
|
|
72114
|
-
while (byId.has(id3) && byId.get(id3).path !==
|
|
72115
|
-
id3 = `${slugFromPath(
|
|
72383
|
+
while (byId.has(id3) && byId.get(id3).path !== path101) {
|
|
72384
|
+
id3 = `${slugFromPath(path101)}-${n++}`;
|
|
72116
72385
|
}
|
|
72117
72386
|
byId.set(id3, {
|
|
72118
72387
|
id: id3,
|
|
72119
|
-
name: slugFromPath(
|
|
72120
|
-
path:
|
|
72388
|
+
name: slugFromPath(path101),
|
|
72389
|
+
path: path101
|
|
72121
72390
|
});
|
|
72122
72391
|
}
|
|
72123
72392
|
return [...byId.values()];
|
|
@@ -72360,7 +72629,7 @@ var init_askUserBridge = __esm({
|
|
|
72360
72629
|
|
|
72361
72630
|
// src/cli/serve/spineLockSweep.ts
|
|
72362
72631
|
import { promises as fs47 } from "node:fs";
|
|
72363
|
-
import
|
|
72632
|
+
import path96 from "node:path";
|
|
72364
72633
|
async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
72365
72634
|
const dir = sessionsDir2 ?? resolveSessionsDir();
|
|
72366
72635
|
const onSwept = options.onSwept ?? ((sessionId2, reason) => {
|
|
@@ -72378,7 +72647,7 @@ async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
|
72378
72647
|
return result;
|
|
72379
72648
|
}
|
|
72380
72649
|
for (const sessionId2 of entries) {
|
|
72381
|
-
const lockPath2 =
|
|
72650
|
+
const lockPath2 = path96.join(dir, sessionId2, "writer.lock");
|
|
72382
72651
|
try {
|
|
72383
72652
|
const raw = await fs47.readFile(lockPath2, "utf-8");
|
|
72384
72653
|
let lockInfo = {};
|
|
@@ -73375,9 +73644,9 @@ async function runCompanionServe(opts = {}) {
|
|
|
73375
73644
|
return;
|
|
73376
73645
|
}
|
|
73377
73646
|
const url2 = parseUrl(req);
|
|
73378
|
-
const
|
|
73647
|
+
const path101 = url2.pathname.replace(/\/+$/, "") || "/";
|
|
73379
73648
|
try {
|
|
73380
|
-
if (req.method === "GET" && (
|
|
73649
|
+
if (req.method === "GET" && (path101 === "/health" || path101 === "/v1/health")) {
|
|
73381
73650
|
sendJson2(res, 200, {
|
|
73382
73651
|
ok: true,
|
|
73383
73652
|
service: "zelari-companion",
|
|
@@ -73389,18 +73658,18 @@ async function runCompanionServe(opts = {}) {
|
|
|
73389
73658
|
});
|
|
73390
73659
|
return;
|
|
73391
73660
|
}
|
|
73392
|
-
if (
|
|
73661
|
+
if (path101.startsWith("/v1")) {
|
|
73393
73662
|
if (!tokenMatches(token, getBearer(req))) {
|
|
73394
73663
|
sendJson2(res, 401, { ok: false, error: "unauthorized" });
|
|
73395
73664
|
return;
|
|
73396
73665
|
}
|
|
73397
73666
|
}
|
|
73398
|
-
if (req.method === "GET" &&
|
|
73667
|
+
if (req.method === "GET" && path101 === "/v1/config") {
|
|
73399
73668
|
const snap = buildDesktopConfigSnapshot();
|
|
73400
73669
|
sendJson2(res, 200, { ok: true, ...snap });
|
|
73401
73670
|
return;
|
|
73402
73671
|
}
|
|
73403
|
-
if (req.method === "GET" &&
|
|
73672
|
+
if (req.method === "GET" && path101 === "/v1/projects") {
|
|
73404
73673
|
sendJson2(res, 200, {
|
|
73405
73674
|
ok: true,
|
|
73406
73675
|
projects: projects.map((p3) => ({
|
|
@@ -73411,7 +73680,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
73411
73680
|
});
|
|
73412
73681
|
return;
|
|
73413
73682
|
}
|
|
73414
|
-
if (req.method === "GET" &&
|
|
73683
|
+
if (req.method === "GET" && path101 === "/v1/runs") {
|
|
73415
73684
|
sendJson2(res, 200, {
|
|
73416
73685
|
ok: true,
|
|
73417
73686
|
active: runs.getActive(),
|
|
@@ -73429,7 +73698,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
73429
73698
|
});
|
|
73430
73699
|
return;
|
|
73431
73700
|
}
|
|
73432
|
-
if (req.method === "POST" &&
|
|
73701
|
+
if (req.method === "POST" && path101 === "/v1/runs") {
|
|
73433
73702
|
const raw = await readBody(req);
|
|
73434
73703
|
let body = {};
|
|
73435
73704
|
try {
|
|
@@ -73477,7 +73746,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
73477
73746
|
});
|
|
73478
73747
|
return;
|
|
73479
73748
|
}
|
|
73480
|
-
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(
|
|
73749
|
+
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path101);
|
|
73481
73750
|
if (req.method === "GET" && eventsMatch) {
|
|
73482
73751
|
const runId = eventsMatch[1];
|
|
73483
73752
|
const run = runs.getRun(runId);
|
|
@@ -73542,7 +73811,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
73542
73811
|
}, 500);
|
|
73543
73812
|
return;
|
|
73544
73813
|
}
|
|
73545
|
-
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(
|
|
73814
|
+
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path101);
|
|
73546
73815
|
if (req.method === "POST" && cancelMatch) {
|
|
73547
73816
|
const runId = cancelMatch[1];
|
|
73548
73817
|
const result = runs.cancel(runId);
|
|
@@ -73553,7 +73822,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
73553
73822
|
sendJson2(res, 200, { ok: true, cancelled: runId });
|
|
73554
73823
|
return;
|
|
73555
73824
|
}
|
|
73556
|
-
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(
|
|
73825
|
+
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(path101);
|
|
73557
73826
|
if (req.method === "POST" && steerMatch) {
|
|
73558
73827
|
const runId = steerMatch[1];
|
|
73559
73828
|
const raw = await readBody(req);
|
|
@@ -73722,11 +73991,11 @@ import { execSync as execSync2 } from "node:child_process";
|
|
|
73722
73991
|
import { existsSync as existsSync62, readFileSync as readFileSync46, readlinkSync, statSync as statSync10 } from "node:fs";
|
|
73723
73992
|
import { createRequire as createRequire3 } from "node:module";
|
|
73724
73993
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
73725
|
-
import
|
|
73994
|
+
import path97 from "node:path";
|
|
73726
73995
|
function findPackageRoot(start) {
|
|
73727
73996
|
let dir = start;
|
|
73728
73997
|
for (let i = 0; i < 6; i += 1) {
|
|
73729
|
-
const candidate =
|
|
73998
|
+
const candidate = path97.join(dir, "package.json");
|
|
73730
73999
|
if (existsSync62(candidate)) {
|
|
73731
74000
|
try {
|
|
73732
74001
|
const pkg = JSON.parse(readFileSync46(candidate, "utf8"));
|
|
@@ -73734,11 +74003,11 @@ function findPackageRoot(start) {
|
|
|
73734
74003
|
} catch {
|
|
73735
74004
|
}
|
|
73736
74005
|
}
|
|
73737
|
-
const parent =
|
|
74006
|
+
const parent = path97.dirname(dir);
|
|
73738
74007
|
if (parent === dir) break;
|
|
73739
74008
|
dir = parent;
|
|
73740
74009
|
}
|
|
73741
|
-
return
|
|
74010
|
+
return path97.resolve(__dirname3, "..", "..", "..");
|
|
73742
74011
|
}
|
|
73743
74012
|
function tryExec(cmd) {
|
|
73744
74013
|
try {
|
|
@@ -73752,7 +74021,7 @@ function tryExec(cmd) {
|
|
|
73752
74021
|
}
|
|
73753
74022
|
function readPackageJson4() {
|
|
73754
74023
|
try {
|
|
73755
|
-
const pkgPath =
|
|
74024
|
+
const pkgPath = path97.join(packageRoot, "package.json");
|
|
73756
74025
|
return JSON.parse(readFileSync46(pkgPath, "utf8"));
|
|
73757
74026
|
} catch {
|
|
73758
74027
|
return null;
|
|
@@ -73764,7 +74033,7 @@ function getGlobalPrefix() {
|
|
|
73764
74033
|
return (process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX || "").trim();
|
|
73765
74034
|
}
|
|
73766
74035
|
function isSourceCheckout() {
|
|
73767
|
-
return existsSync62(
|
|
74036
|
+
return existsSync62(path97.join(packageRoot, "src", "cli", "main.ts")) && existsSync62(path97.join(packageRoot, "apps", "desktop", "package.json"));
|
|
73768
74037
|
}
|
|
73769
74038
|
function checkShim(pkgName) {
|
|
73770
74039
|
const prefix = getGlobalPrefix();
|
|
@@ -73773,9 +74042,9 @@ function checkShim(pkgName) {
|
|
|
73773
74042
|
}
|
|
73774
74043
|
const isWin = process.platform === "win32";
|
|
73775
74044
|
const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
|
|
73776
|
-
const shimPath =
|
|
74045
|
+
const shimPath = path97.join(prefix, shimName);
|
|
73777
74046
|
if (!existsSync62(shimPath)) {
|
|
73778
|
-
const localBin =
|
|
74047
|
+
const localBin = path97.join(packageRoot, "bin", "zelari-code.js");
|
|
73779
74048
|
if (isSourceCheckout() && existsSync62(localBin)) {
|
|
73780
74049
|
return WARN(
|
|
73781
74050
|
`global shim not found at ${shimPath}
|
|
@@ -73809,8 +74078,8 @@ function checkShim(pkgName) {
|
|
|
73809
74078
|
fix: npm install -g ${pkgName}@latest --force`
|
|
73810
74079
|
);
|
|
73811
74080
|
}
|
|
73812
|
-
const resolved =
|
|
73813
|
-
const expected =
|
|
74081
|
+
const resolved = path97.resolve(path97.dirname(shimPath), target);
|
|
74082
|
+
const expected = path97.join(
|
|
73814
74083
|
prefix,
|
|
73815
74084
|
"node_modules",
|
|
73816
74085
|
pkgName,
|
|
@@ -73852,7 +74121,7 @@ function checkNode(pkg) {
|
|
|
73852
74121
|
return OK(`node ${raw} (engines.node ${enginesNode ?? ">= 20.0.0"})`);
|
|
73853
74122
|
}
|
|
73854
74123
|
function checkBundle() {
|
|
73855
|
-
const bundle =
|
|
74124
|
+
const bundle = path97.join(packageRoot, "dist", "cli", "main.bundled.js");
|
|
73856
74125
|
if (!existsSync62(bundle)) {
|
|
73857
74126
|
return FAIL(
|
|
73858
74127
|
`dist/cli/main.bundled.js missing at ${bundle}
|
|
@@ -73873,7 +74142,7 @@ function checkRuntimeDeps() {
|
|
|
73873
74142
|
const missing = [];
|
|
73874
74143
|
for (const dep of required2) {
|
|
73875
74144
|
try {
|
|
73876
|
-
const localReq = createRequire3(
|
|
74145
|
+
const localReq = createRequire3(path97.join(packageRoot, "package.json"));
|
|
73877
74146
|
localReq.resolve(dep);
|
|
73878
74147
|
} catch {
|
|
73879
74148
|
missing.push(dep);
|
|
@@ -74150,7 +74419,7 @@ var init_doctor = __esm({
|
|
|
74150
74419
|
init_metrics3();
|
|
74151
74420
|
init_contextGrowthSummary();
|
|
74152
74421
|
require3 = createRequire3(import.meta.url);
|
|
74153
|
-
__dirname3 =
|
|
74422
|
+
__dirname3 = path97.dirname(fileURLToPath3(import.meta.url));
|
|
74154
74423
|
packageRoot = findPackageRoot(__dirname3);
|
|
74155
74424
|
OK = (message) => ({
|
|
74156
74425
|
ok: true,
|
|
@@ -74259,7 +74528,7 @@ __export(userSettings_exports, {
|
|
|
74259
74528
|
settingsOverrides: () => settingsOverrides
|
|
74260
74529
|
});
|
|
74261
74530
|
import { existsSync as existsSync63, readFileSync as readFileSync47 } from "node:fs";
|
|
74262
|
-
import
|
|
74531
|
+
import path98 from "node:path";
|
|
74263
74532
|
function parseBool(raw) {
|
|
74264
74533
|
const v = raw.trim().toLowerCase();
|
|
74265
74534
|
if (["1", "true", "yes", "on"].includes(v)) return true;
|
|
@@ -74326,8 +74595,8 @@ function envValueFor(key, env) {
|
|
|
74326
74595
|
function resolveUserSettings(opts = {}) {
|
|
74327
74596
|
const cwd = opts.cwd ?? process.cwd();
|
|
74328
74597
|
const env = opts.env ?? process.env;
|
|
74329
|
-
const userPath =
|
|
74330
|
-
const projectPath =
|
|
74598
|
+
const userPath = path98.join(zelariHome(), SETTINGS_FILE_NAME);
|
|
74599
|
+
const projectPath = path98.join(cwd, ".zelari", SETTINGS_FILE_NAME);
|
|
74331
74600
|
const warnings = [];
|
|
74332
74601
|
const userLayer = loadFileLayer(userPath, "user", warnings);
|
|
74333
74602
|
const projectLayer = loadFileLayer(projectPath, "project", warnings);
|
|
@@ -74541,7 +74810,7 @@ __export(inspectSession_exports, {
|
|
|
74541
74810
|
renderInspectReport: () => renderInspectReport,
|
|
74542
74811
|
runInspectSession: () => runInspectSession
|
|
74543
74812
|
});
|
|
74544
|
-
import
|
|
74813
|
+
import path99 from "node:path";
|
|
74545
74814
|
import { existsSync as existsSync64 } from "node:fs";
|
|
74546
74815
|
function formatLimit(limit) {
|
|
74547
74816
|
return `${Math.round(limit / 1e3)}k`;
|
|
@@ -74575,8 +74844,8 @@ function renderInspectReport(state3) {
|
|
|
74575
74844
|
}
|
|
74576
74845
|
async function runInspectSession(opts) {
|
|
74577
74846
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.cwd ?? process.cwd() });
|
|
74578
|
-
const sessionDir =
|
|
74579
|
-
const eventsPath =
|
|
74847
|
+
const sessionDir = path99.join(sessionsDir2, opts.sessionId);
|
|
74848
|
+
const eventsPath = path99.join(sessionDir, "events.jsonl");
|
|
74580
74849
|
if (!existsSync64(sessionDir)) {
|
|
74581
74850
|
console.error(`zelari-code inspect: no session directory at ${sessionDir}`);
|
|
74582
74851
|
return 1;
|
|
@@ -74610,14 +74879,14 @@ __export(inspect_exports, {
|
|
|
74610
74879
|
collectInspectReport: () => collectInspectReport,
|
|
74611
74880
|
runInspect: () => runInspect
|
|
74612
74881
|
});
|
|
74613
|
-
import
|
|
74882
|
+
import path100 from "node:path";
|
|
74614
74883
|
import { existsSync as existsSync65, readFileSync as readFileSync48, readdirSync as readdirSync13 } from "node:fs";
|
|
74615
74884
|
async function collectInspectReport(cwd = process.cwd()) {
|
|
74616
74885
|
ensureBuiltinSkillsLoadedSync();
|
|
74617
74886
|
const snap = listSkillsSnapshot(cwd);
|
|
74618
74887
|
const mcp = listMcpServers(cwd);
|
|
74619
|
-
const userMcpPath =
|
|
74620
|
-
const projectMcpPath =
|
|
74888
|
+
const userMcpPath = path100.join(zelariHome(), "mcp.json");
|
|
74889
|
+
const projectMcpPath = path100.join(cwd, ".zelari", "mcp.json");
|
|
74621
74890
|
const globalHooks = globalHooksDir();
|
|
74622
74891
|
const projectHooks = projectHooksDir(cwd);
|
|
74623
74892
|
const projectTrusted = isFolderTrusted(cwd);
|
|
@@ -74645,9 +74914,9 @@ async function collectInspectReport(cwd = process.cwd()) {
|
|
|
74645
74914
|
configSources: [
|
|
74646
74915
|
{ path: userMcpPath, exists: existsSync65(userMcpPath) },
|
|
74647
74916
|
{ path: projectMcpPath, exists: existsSync65(projectMcpPath) },
|
|
74648
|
-
{ path:
|
|
74649
|
-
{ path:
|
|
74650
|
-
{ path:
|
|
74917
|
+
{ path: path100.join(zelariHome(), "provider.json"), exists: existsSync65(path100.join(zelariHome(), "provider.json")) },
|
|
74918
|
+
{ path: path100.join(cwd, ".zelari", "AGENTS.md"), exists: existsSync65(path100.join(cwd, ".zelari", "AGENTS.md")) },
|
|
74919
|
+
{ path: path100.join(cwd, "AGENTS.md"), exists: existsSync65(path100.join(cwd, "AGENTS.md")) }
|
|
74651
74920
|
],
|
|
74652
74921
|
skills: {
|
|
74653
74922
|
total: snap.skills.length,
|
|
@@ -74687,8 +74956,8 @@ function listJsonFiles(dir) {
|
|
|
74687
74956
|
}
|
|
74688
74957
|
function findAgentsMd(cwd) {
|
|
74689
74958
|
const candidates = [
|
|
74690
|
-
|
|
74691
|
-
|
|
74959
|
+
path100.join(cwd, "AGENTS.md"),
|
|
74960
|
+
path100.join(cwd, ".zelari", "AGENTS.md")
|
|
74692
74961
|
];
|
|
74693
74962
|
const found = [];
|
|
74694
74963
|
for (const c of candidates) {
|
|
@@ -78441,7 +78710,10 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
78441
78710
|
progressRuntime.observe(event);
|
|
78442
78711
|
if (event.type === "agent_end") {
|
|
78443
78712
|
let krakenSuppressFinish = false;
|
|
78444
|
-
const krakenSpineEmit = (input) =>
|
|
78713
|
+
const krakenSpineEmit = async (input) => {
|
|
78714
|
+
const seq = await (writerRef.current?.spine?.appendEvent(input) ?? Promise.resolve(null));
|
|
78715
|
+
return { seq };
|
|
78716
|
+
};
|
|
78445
78717
|
const writeProofSafe2 = (gate) => writeCompletionProof(gate, { meta: { surface: "kraken", sessionId: sessionId2 } }).then(
|
|
78446
78718
|
() => void 0,
|
|
78447
78719
|
() => void 0
|
|
@@ -78455,7 +78727,9 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
78455
78727
|
if (krakenGate.blocked) {
|
|
78456
78728
|
krakenRepairEnqueued = true;
|
|
78457
78729
|
markRepairTriggered();
|
|
78458
|
-
harness2.enqueue(
|
|
78730
|
+
harness2.enqueue(
|
|
78731
|
+
buildKrakenRepairPrompt(krakenGate, repairExcerptsFromEvaluation(strictGate))
|
|
78732
|
+
);
|
|
78459
78733
|
appendSystem(
|
|
78460
78734
|
setMessages,
|
|
78461
78735
|
formatStrictBlockExplanation(strictGate),
|
|
@@ -79949,10 +80223,10 @@ init_ledger();
|
|
|
79949
80223
|
|
|
79950
80224
|
// src/cli/evolution/proposals.ts
|
|
79951
80225
|
import { existsSync as existsSync51, readFileSync as readFileSync39 } from "node:fs";
|
|
79952
|
-
import
|
|
79953
|
-
var PROPOSALS_REL =
|
|
80226
|
+
import path78 from "node:path";
|
|
80227
|
+
var PROPOSALS_REL = path78.join(".zelari", "evolution", "proposals.jsonl");
|
|
79954
80228
|
function proposalsPath(cwd) {
|
|
79955
|
-
return
|
|
80229
|
+
return path78.join(cwd, PROPOSALS_REL);
|
|
79956
80230
|
}
|
|
79957
80231
|
function readProposalStore(cwd) {
|
|
79958
80232
|
const file2 = proposalsPath(cwd);
|
|
@@ -81062,11 +81336,11 @@ function handleCacheStats(ctx) {
|
|
|
81062
81336
|
init_messageHelpers();
|
|
81063
81337
|
init_serviceFactory();
|
|
81064
81338
|
import { promises as fs35 } from "node:fs";
|
|
81065
|
-
import * as
|
|
81339
|
+
import * as path80 from "node:path";
|
|
81066
81340
|
|
|
81067
81341
|
// src/cli/memory/promotion.ts
|
|
81068
81342
|
import { promises as fs34 } from "node:fs";
|
|
81069
|
-
import * as
|
|
81343
|
+
import * as path79 from "node:path";
|
|
81070
81344
|
var START = "<!-- zelari:memory-promotions:start -->";
|
|
81071
81345
|
var END = "<!-- zelari:memory-promotions:end -->";
|
|
81072
81346
|
var DURABLE_KINDS = /* @__PURE__ */ new Set(["fact", "decision", "constraint", "preference", "procedure"]);
|
|
@@ -81077,13 +81351,13 @@ function lineFor(node) {
|
|
|
81077
81351
|
}
|
|
81078
81352
|
async function promoteMemoryToAgentsMd(projectRoot, node) {
|
|
81079
81353
|
if (node.status !== "active") {
|
|
81080
|
-
return { added: false, path:
|
|
81354
|
+
return { added: false, path: path79.join(projectRoot, "AGENTS.md"), reason: `memory is ${node.status}` };
|
|
81081
81355
|
}
|
|
81082
81356
|
if (!DURABLE_KINDS.has(node.kind)) {
|
|
81083
|
-
return { added: false, path:
|
|
81357
|
+
return { added: false, path: path79.join(projectRoot, "AGENTS.md"), reason: `${node.kind} is not a durable instruction kind` };
|
|
81084
81358
|
}
|
|
81085
|
-
const root = await fs34.realpath(projectRoot).catch(() =>
|
|
81086
|
-
const target =
|
|
81359
|
+
const root = await fs34.realpath(projectRoot).catch(() => path79.resolve(projectRoot));
|
|
81360
|
+
const target = path79.join(root, "AGENTS.md");
|
|
81087
81361
|
try {
|
|
81088
81362
|
const stat8 = await fs34.lstat(target);
|
|
81089
81363
|
if (stat8.isSymbolicLink() || !stat8.isFile()) throw new Error("AGENTS.md must be a regular project file.");
|
|
@@ -81148,22 +81422,22 @@ function sourceLine(source2) {
|
|
|
81148
81422
|
return entries.length ? entries.map(([key, value]) => `${key}=${value}`).join(" \xB7 ") : "unknown";
|
|
81149
81423
|
}
|
|
81150
81424
|
function isInside(root, target) {
|
|
81151
|
-
const relative6 =
|
|
81152
|
-
return relative6 === "" || !relative6.startsWith("..") && !
|
|
81425
|
+
const relative6 = path80.relative(root, target);
|
|
81426
|
+
return relative6 === "" || !relative6.startsWith("..") && !path80.isAbsolute(relative6);
|
|
81153
81427
|
}
|
|
81154
81428
|
async function safeExportPath(cwd, requested) {
|
|
81155
|
-
const lexicalRoot =
|
|
81429
|
+
const lexicalRoot = path80.resolve(cwd);
|
|
81156
81430
|
const root = await fs35.realpath(lexicalRoot).catch(() => lexicalRoot);
|
|
81157
|
-
const fallback =
|
|
81158
|
-
const target = requested?.trim() ?
|
|
81431
|
+
const fallback = path80.join(root, ".zelari", "memory", `export-${Date.now()}.json`);
|
|
81432
|
+
const target = requested?.trim() ? path80.resolve(root, requested.trim()) : fallback;
|
|
81159
81433
|
if (!isInside(root, target)) {
|
|
81160
81434
|
throw new Error("Export path must stay inside the active project.");
|
|
81161
81435
|
}
|
|
81162
|
-
const parent =
|
|
81163
|
-
const relativeParent =
|
|
81436
|
+
const parent = path80.dirname(target);
|
|
81437
|
+
const relativeParent = path80.relative(root, parent);
|
|
81164
81438
|
let cursor = root;
|
|
81165
|
-
for (const segment of relativeParent.split(
|
|
81166
|
-
cursor =
|
|
81439
|
+
for (const segment of relativeParent.split(path80.sep).filter(Boolean)) {
|
|
81440
|
+
cursor = path80.join(cursor, segment);
|
|
81167
81441
|
try {
|
|
81168
81442
|
const stat8 = await fs35.lstat(cursor);
|
|
81169
81443
|
if (stat8.isSymbolicLink()) {
|
|
@@ -81335,9 +81609,9 @@ ${message}` : message
|
|
|
81335
81609
|
}
|
|
81336
81610
|
case "export": {
|
|
81337
81611
|
const target = await safeExportPath(ctx.cwd, args.join(" ").trim() || void 0);
|
|
81338
|
-
await fs35.mkdir(
|
|
81339
|
-
const root = await fs35.realpath(ctx.cwd).catch(() =>
|
|
81340
|
-
const realParent = await fs35.realpath(
|
|
81612
|
+
await fs35.mkdir(path80.dirname(target), { recursive: true });
|
|
81613
|
+
const root = await fs35.realpath(ctx.cwd).catch(() => path80.resolve(ctx.cwd));
|
|
81614
|
+
const realParent = await fs35.realpath(path80.dirname(target));
|
|
81341
81615
|
if (!isInside(root, realParent)) {
|
|
81342
81616
|
throw new Error("Export path resolves outside the active project.");
|
|
81343
81617
|
}
|
|
@@ -81552,7 +81826,7 @@ import { promises as fs37 } from "node:fs";
|
|
|
81552
81826
|
init_zod();
|
|
81553
81827
|
init_taskTool();
|
|
81554
81828
|
import { promises as fs36 } from "node:fs";
|
|
81555
|
-
import
|
|
81829
|
+
import path81 from "node:path";
|
|
81556
81830
|
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
81557
81831
|
var CsvFanoutArgsSchema = external_exports.object({
|
|
81558
81832
|
csv_path: external_exports.string().min(1),
|
|
@@ -81646,8 +81920,8 @@ function resolveMaxConcurrency(env = process.env) {
|
|
|
81646
81920
|
}
|
|
81647
81921
|
async function runCsvFanout(args, deps, opts) {
|
|
81648
81922
|
const start = Date.now();
|
|
81649
|
-
const absCsv =
|
|
81650
|
-
const absOut =
|
|
81923
|
+
const absCsv = path81.isAbsolute(args.csv_path) ? args.csv_path : path81.join(opts.parentCwd, args.csv_path);
|
|
81924
|
+
const absOut = path81.isAbsolute(args.output_csv_path) ? args.output_csv_path : path81.join(opts.parentCwd, args.output_csv_path);
|
|
81651
81925
|
const { headers: headers3, rows } = await readCsv(absCsv);
|
|
81652
81926
|
if (headers3.length === 0) {
|
|
81653
81927
|
throw new Error(`kraken_csv_fanout: ${absCsv} is empty`);
|
|
@@ -81703,7 +81977,7 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
81703
81977
|
errored += 1;
|
|
81704
81978
|
errors.push(`${row[args.id_column] ?? i}: ${res.error}`);
|
|
81705
81979
|
}
|
|
81706
|
-
await fs36.mkdir(
|
|
81980
|
+
await fs36.mkdir(path81.dirname(absOut), { recursive: true });
|
|
81707
81981
|
await queueWrite(serializeCsv(outHeaders, outputRecords));
|
|
81708
81982
|
}
|
|
81709
81983
|
}
|
|
@@ -81898,7 +82172,7 @@ function splitArgs(s) {
|
|
|
81898
82172
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
81899
82173
|
init_messageHelpers();
|
|
81900
82174
|
import { promises as fs38 } from "node:fs";
|
|
81901
|
-
import
|
|
82175
|
+
import path82 from "node:path";
|
|
81902
82176
|
|
|
81903
82177
|
// src/cli/kraken/workbenchView.ts
|
|
81904
82178
|
var EMPTY = {
|
|
@@ -82015,14 +82289,14 @@ function formatWorkbenchForTerminal(p3) {
|
|
|
82015
82289
|
|
|
82016
82290
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
82017
82291
|
async function handleKrakenWorkbench(ctx) {
|
|
82018
|
-
const dir =
|
|
82292
|
+
const dir = path82.join(ctx.cwd, ".zelari", "radio");
|
|
82019
82293
|
let latest = null;
|
|
82020
82294
|
let latestMtime = 0;
|
|
82021
82295
|
try {
|
|
82022
82296
|
const files = await fs38.readdir(dir);
|
|
82023
82297
|
for (const f of files) {
|
|
82024
82298
|
if (!f.startsWith("workbench-") || !f.endsWith(".md")) continue;
|
|
82025
|
-
const full =
|
|
82299
|
+
const full = path82.join(dir, f);
|
|
82026
82300
|
const stat8 = await fs38.stat(full);
|
|
82027
82301
|
if (stat8.mtimeMs > latestMtime) {
|
|
82028
82302
|
latestMtime = stat8.mtimeMs;
|
|
@@ -82039,10 +82313,10 @@ async function handleKrakenWorkbench(ctx) {
|
|
|
82039
82313
|
const parsed = parseWorkbench(content);
|
|
82040
82314
|
const rendered = formatWorkbenchForTerminal(parsed);
|
|
82041
82315
|
if (!rendered.trim()) {
|
|
82042
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
82316
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path82.basename(latest)}: (no nodes / no events yet)`);
|
|
82043
82317
|
return;
|
|
82044
82318
|
}
|
|
82045
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
82319
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path82.basename(latest)}:
|
|
82046
82320
|
${rendered}`);
|
|
82047
82321
|
}
|
|
82048
82322
|
|
|
@@ -82350,14 +82624,14 @@ ${result.output.split("\n").slice(-8).join("\n")}` : "";
|
|
|
82350
82624
|
init_messageHelpers();
|
|
82351
82625
|
init_paths();
|
|
82352
82626
|
import { promises as fs39 } from "node:fs";
|
|
82353
|
-
import
|
|
82627
|
+
import path85 from "node:path";
|
|
82354
82628
|
async function handlePromoteMember(ctx, memberId) {
|
|
82355
82629
|
try {
|
|
82356
82630
|
const { promoteMember: promoteMember2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
82357
82631
|
const { skill, markdown } = promoteMember2(memberId);
|
|
82358
82632
|
const skillDir = skillsDir();
|
|
82359
82633
|
await fs39.mkdir(skillDir, { recursive: true });
|
|
82360
|
-
const filePath =
|
|
82634
|
+
const filePath = path85.join(skillDir, `${skill.id}.md`);
|
|
82361
82635
|
const previous = await fs39.readFile(filePath, "utf8").catch(() => null);
|
|
82362
82636
|
const { createHash: createHash24 } = await import("node:crypto");
|
|
82363
82637
|
const sha = (s) => createHash24("sha256").update(s, "utf8").digest("hex");
|
|
@@ -82383,7 +82657,7 @@ ${lineage}
|
|
|
82383
82657
|
// src/cli/branchManager.ts
|
|
82384
82658
|
init_paths();
|
|
82385
82659
|
import { promises as fs40, existsSync as existsSync55, readFileSync as readFileSync41, writeFileSync as writeFileSync24, mkdirSync as mkdirSync21, statSync as statSync7, rmSync as rmSync3 } from "node:fs";
|
|
82386
|
-
import
|
|
82660
|
+
import path86 from "node:path";
|
|
82387
82661
|
var META_FILENAME = "meta.json";
|
|
82388
82662
|
var SESSIONS_SUBDIR = "sessions";
|
|
82389
82663
|
function getBranchesBaseDir() {
|
|
@@ -82393,13 +82667,13 @@ function getSessionsBaseDir() {
|
|
|
82393
82667
|
return sessionsDir();
|
|
82394
82668
|
}
|
|
82395
82669
|
function branchPathFor(name, baseDir) {
|
|
82396
|
-
return
|
|
82670
|
+
return path86.join(baseDir, name);
|
|
82397
82671
|
}
|
|
82398
82672
|
function metaPathFor(name, baseDir) {
|
|
82399
|
-
return
|
|
82673
|
+
return path86.join(baseDir, name, META_FILENAME);
|
|
82400
82674
|
}
|
|
82401
82675
|
function sessionsPathFor(name, baseDir) {
|
|
82402
|
-
return
|
|
82676
|
+
return path86.join(baseDir, name, SESSIONS_SUBDIR);
|
|
82403
82677
|
}
|
|
82404
82678
|
function readBranchMeta(name, baseDir) {
|
|
82405
82679
|
const metaPath = metaPathFor(name, baseDir);
|
|
@@ -82424,7 +82698,7 @@ function readBranchMeta(name, baseDir) {
|
|
|
82424
82698
|
}
|
|
82425
82699
|
function writeBranchMeta(name, baseDir, meta3) {
|
|
82426
82700
|
const metaPath = metaPathFor(name, baseDir);
|
|
82427
|
-
mkdirSync21(
|
|
82701
|
+
mkdirSync21(path86.dirname(metaPath), { recursive: true });
|
|
82428
82702
|
writeFileSync24(metaPath, JSON.stringify(meta3, null, 2), "utf-8");
|
|
82429
82703
|
}
|
|
82430
82704
|
async function countSessions(name, baseDir) {
|
|
@@ -82475,14 +82749,14 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
82475
82749
|
if (branchExists(name, baseDir)) {
|
|
82476
82750
|
throw new BranchAlreadyExistsError(name);
|
|
82477
82751
|
}
|
|
82478
|
-
const sourcePath =
|
|
82752
|
+
const sourcePath = path86.join(sessionsBaseDir, `${fromSessionId}.jsonl`);
|
|
82479
82753
|
if (!existsSync55(sourcePath)) {
|
|
82480
82754
|
throw new SessionNotFoundError(`Source session "${fromSessionId}" not found at ${sourcePath}`);
|
|
82481
82755
|
}
|
|
82482
82756
|
const branchPath = branchPathFor(name, baseDir);
|
|
82483
82757
|
const branchSessionsPath = sessionsPathFor(name, baseDir);
|
|
82484
82758
|
mkdirSync21(branchSessionsPath, { recursive: true });
|
|
82485
|
-
const destPath =
|
|
82759
|
+
const destPath = path86.join(branchSessionsPath, `${fromSessionId}.jsonl`);
|
|
82486
82760
|
await fs40.copyFile(sourcePath, destPath);
|
|
82487
82761
|
const meta3 = {
|
|
82488
82762
|
name,
|
|
@@ -82586,14 +82860,14 @@ async function handleBranchCheckout(ctx, branchName) {
|
|
|
82586
82860
|
// src/cli/slashHandlers/workspace.ts
|
|
82587
82861
|
init_messageHelpers();
|
|
82588
82862
|
import { promises as fs41 } from "node:fs";
|
|
82589
|
-
import
|
|
82863
|
+
import path87 from "node:path";
|
|
82590
82864
|
async function handleWorkspaceShow(ctx, what) {
|
|
82591
82865
|
try {
|
|
82592
|
-
const zelari =
|
|
82866
|
+
const zelari = path87.join(process.cwd(), ".zelari");
|
|
82593
82867
|
let content;
|
|
82594
82868
|
switch (what) {
|
|
82595
82869
|
case "plan": {
|
|
82596
|
-
const planPath =
|
|
82870
|
+
const planPath = path87.join(zelari, "plan.md");
|
|
82597
82871
|
try {
|
|
82598
82872
|
content = await fs41.readFile(planPath, "utf-8");
|
|
82599
82873
|
} catch {
|
|
@@ -82602,7 +82876,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82602
82876
|
break;
|
|
82603
82877
|
}
|
|
82604
82878
|
case "decisions": {
|
|
82605
|
-
const decisionsDir =
|
|
82879
|
+
const decisionsDir = path87.join(zelari, "decisions");
|
|
82606
82880
|
try {
|
|
82607
82881
|
const files = (await fs41.readdir(decisionsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
82608
82882
|
if (files.length === 0) {
|
|
@@ -82612,7 +82886,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82612
82886
|
`];
|
|
82613
82887
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
82614
82888
|
for (const f of files) {
|
|
82615
|
-
const raw = await fs41.readFile(
|
|
82889
|
+
const raw = await fs41.readFile(path87.join(decisionsDir, f), "utf-8");
|
|
82616
82890
|
const { meta: meta3, body } = parseFrontmatter2(raw);
|
|
82617
82891
|
const title = meta3.title ?? body.split("\n")[0]?.replace(/^#\s*/, "").trim() ?? f;
|
|
82618
82892
|
lines.push(`- **${f.replace(/\.md$/, "")}** [${meta3.status ?? "unknown"}] ${title}`);
|
|
@@ -82625,7 +82899,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82625
82899
|
break;
|
|
82626
82900
|
}
|
|
82627
82901
|
case "risks": {
|
|
82628
|
-
const risksPath =
|
|
82902
|
+
const risksPath = path87.join(zelari, "risks.md");
|
|
82629
82903
|
try {
|
|
82630
82904
|
content = await fs41.readFile(risksPath, "utf-8");
|
|
82631
82905
|
} catch {
|
|
@@ -82634,7 +82908,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82634
82908
|
break;
|
|
82635
82909
|
}
|
|
82636
82910
|
case "agents": {
|
|
82637
|
-
const agentsPath =
|
|
82911
|
+
const agentsPath = path87.join(process.cwd(), "AGENTS.MD");
|
|
82638
82912
|
try {
|
|
82639
82913
|
content = await fs41.readFile(agentsPath, "utf-8");
|
|
82640
82914
|
} catch {
|
|
@@ -82643,7 +82917,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82643
82917
|
break;
|
|
82644
82918
|
}
|
|
82645
82919
|
case "docs": {
|
|
82646
|
-
const docsDir =
|
|
82920
|
+
const docsDir = path87.join(zelari, "docs");
|
|
82647
82921
|
try {
|
|
82648
82922
|
const files = (await fs41.readdir(docsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
82649
82923
|
content = files.length ? `# Docs (${files.length})
|
|
@@ -82685,7 +82959,7 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
82685
82959
|
return;
|
|
82686
82960
|
}
|
|
82687
82961
|
try {
|
|
82688
|
-
const target =
|
|
82962
|
+
const target = path87.join(process.cwd(), ".zelari");
|
|
82689
82963
|
await fs41.rm(target, { recursive: true, force: true });
|
|
82690
82964
|
appendSystem(ctx.setMessages, "[workspace] .zelari/ removed");
|
|
82691
82965
|
} catch (err) {
|
|
@@ -84569,8 +84843,8 @@ function normalizeDraft(raw, sourceUrl, provider, model) {
|
|
|
84569
84843
|
let name = String(o.name ?? "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
84570
84844
|
if (!name || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) {
|
|
84571
84845
|
try {
|
|
84572
|
-
const
|
|
84573
|
-
name =
|
|
84846
|
+
const path101 = new URL(sourceUrl).pathname.split("/").filter(Boolean).pop()?.replace(/\.[a-z0-9]+$/i, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
84847
|
+
name = path101 && /^[a-z0-9]/.test(path101) ? path101 : "imported-skill";
|
|
84574
84848
|
} catch {
|
|
84575
84849
|
name = "imported-skill";
|
|
84576
84850
|
}
|
|
@@ -84983,7 +85257,7 @@ proposals: npm run evolve:propose \u2014 decisions in npm run evolve:decide (P1:
|
|
|
84983
85257
|
}
|
|
84984
85258
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
84985
85259
|
console.log(
|
|
84986
|
-
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor [--json] Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --inspect [--json] Unified project inspection (config, skills, MCP,\n hooks, plugins, AGENTS.md, trust status)\n --trust [path] Trust the cwd (or path) so project MCP + hooks load\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --fix-budget Set recommended ZELARI_MAX_TOOL_LOOP_HARD=180,\n ZELARI_MAX_TOOL_LOOP_ITERATIONS=60, ZELARI_CONTEXT_LIMIT=400000\n at User scope (prevents the agent stopping mid-task)\n --permission-mcp <socket> MCP stdio server for external agent permission prompts\n (spawned by claude --permission-prompt-tool)\n --memory-mcp Optional MCP stdio server for project memory\n --cwd <path> Trusted project root (requires ZELARI_MEMORY_MCP=1)\n --client-id <id> Stable local owner identity for private memories\n --memory-json <json> Read-only project-memory bridge for Zelari Desktop\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --mode kraken|council|zelari Dispatch mode (default: kraken; agent=alias)\n zelari/mission mode auto-scopes slices from open tasks in .zelari/plan.json\n --council Alias for --mode council\n --phase plan|build Work phase (default: build)\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n --profile <id> Capability profile (minimal/v1|kraken/v1|council/v1|mission/v1)\n --resume <id> Continue a 2.0 spine session\n --resume-mission Resume .zelari/mission-state.json (not the spine)\n --export-session <path> Write zelari-session-export/1 after the run\n --strict-done Evidence-based BUILD completion gate\n --task-file <path> Read the task prompt from a file (Windows argv cap)\n --once Single-cycle run (cron/git-hook triggers, ADR-0014)\n --kraken-graph <goal> Plan + execute a Kraken task graph\n (variant: --kraken-graph-file <path>; kill-switch\n ZELARI_KRAKEN_GRAPH=0)\n --plan-only Serialize the graph plan to .zelari/radio/ and exit 0\n --run-plan <id> Execute a pre-built .zelari/radio/plan-<id>.json\n --gauntlet Host-driven gauntlet loop (builder/critic tentacles)\n --session-export <id> Print a portable 2.0 session export (no LLM)\n serve Companion host for Android/remote clients (Tailscale)\n --bind <ip> Listen address (default: 127.0.0.1; use Tailscale IP)\n --port <n> Port (default: 7421)\n --token <secret> Bearer token (default: ~/.zelari-code/companion.token)\n --project <path> Allowlisted project root (repeatable)\n --save-projects Persist --project list to companion.json\n --serve-harness Long-lived harness kernel for hosts (NDJSON JSON-RPC\n on stdin/stdout; Desktop/companion transport)\n --print-config Print provider/model config as JSON (no secrets)\n --print-settings Print zelari.config.json values + the origin of\n each (default < user < project < env)\n --permissions <p> Permission preset: strict | standard | yolo \u2014 changes\n category DEFAULTS only (env vars and policy files win)\n --evolve-status Evolution ledger stats (read-only; ADR-0036; the\n ledger is written only when ZELARI_EVOLUTION=shadow)\n --plugins-status JSON status of optional plugins (Playwright, eslint, \u2026)\n --plugins-install <id> Install plugin (playwright also fetches Chromium)\n --cwd <path> Workspace for -D installs (default: process.cwd())\n --set-config Persist provider/model/endpoint\n --provider <id> Set active provider\n --model <id> Set model for that provider\n --endpoint <url> Custom OpenAI-compatible base URL\n --endpoint-clear Remove custom endpoint override\n --thinking <spec> Thinking effort (auto|off|low|medium|high|budget:N)\n --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\n --login-oauth Start subscription OAuth (grok, chatgpt, anthropic)\n --provider <id> grok | chatgpt | anthropic\n --code <paste> Anthropic magic-link code (CODE#STATE)\n --no-browser Do not open the system browser\n --refresh-oauth Force-refresh an OAuth access token\n --provider <id> grok | chatgpt | anthropic\n --logout-oauth Clear stored OAuth credentials\n --provider <id> grok | chatgpt | anthropic\n --discover-models Refresh model list for a provider\n --provider <id> Provider (default: active)\n --print-mcp Print MCP server config (user + project)\n --cwd <path> Project root for .zelari/mcp.json\n --set-mcp Add/update an MCP server entry\n --name <id> Server name (required)\n --command <bin> Executable for stdio servers\n --url <endpoint> Streamable HTTP endpoint (e.g. UE 5.8 editor)\n --args <json> JSON array of args (stdio, optional)\n --timeout <ms> Per-server request timeout (http, optional)\n --scope user|project Default: user\n --enabled true|false Default: true\n --cwd <path> Required when scope=project\n --set-mcp-preset Install a named MCP preset (e.g. cua)\n --preset cua Cua Driver desktop computer-use (MCP)\n --preset unreal-mcp Unreal Engine 5.8+ editor (MCP over HTTP)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-mcp Remove an MCP server entry\n --name <id> --scope user|project [--cwd <path>]\n --print-skills Print skills (builtin + user + project)\n --cwd <path> Project root for .zelari/skills\n --set-skill Add/update a SKILL.md skill\n --name <id> Skill id (required)\n --description <t> One-line description (required)\n --body <text> Markdown instructions (required)\n --category <c> plan|refactor|debug|review|test|docs|ops|git|db|maint\n --tools <csv> Comma-separated required tools (optional)\n --cost <l> low|medium|high (default: medium)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-skill Remove a user/project SKILL.md\n --name <id> --scope user|project [--cwd <path>]\n --generate-skill-from-url Fetch URL + draft skill via model (JSON)\n --url <https://...> Required\n --provider <id> Override active provider\n --model <name> Override model for the selected provider\n --print-ssh-targets Print SSH deploy/monitor targets\n --set-ssh-target Upsert target (--json '{...}' or flags)\n --remove-ssh-target --id <id>\n --test-ssh-target --id <id> (BatchMode ssh true)\n --print-ssh-pubkey --path <private-or-.pub> (display public key)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n ZELARI_MEMORY_MCP=1 Enable the optional external memory MCP server\n ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
85260
|
+
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor [--json] Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --inspect [--json] Unified project inspection (config, skills, MCP,\n hooks, plugins, AGENTS.md, trust status)\n --trust [path] Trust the cwd (or path) so project MCP + hooks load\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --fix-budget Set recommended ZELARI_MAX_TOOL_LOOP_HARD=180,\n ZELARI_MAX_TOOL_LOOP_ITERATIONS=60, ZELARI_CONTEXT_LIMIT=400000\n at User scope (prevents the agent stopping mid-task)\n --permission-mcp <socket> MCP stdio server for external agent permission prompts\n (spawned by claude --permission-prompt-tool)\n --memory-mcp Optional MCP stdio server for project memory\n --cwd <path> Trusted project root (requires ZELARI_MEMORY_MCP=1)\n --client-id <id> Stable local owner identity for private memories\n --memory-json <json> Read-only project-memory bridge for Zelari Desktop\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --mode kraken|council|zelari Dispatch mode (default: kraken; agent=alias)\n zelari/mission mode auto-scopes slices from open tasks in .zelari/plan.json\n --council Alias for --mode council\n --phase plan|build Work phase (default: build)\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n --profile <id> Capability profile (minimal/v1|kraken/v1|council/v1|mission/v1)\n --resume <id> Continue a 2.0 spine session\n --resume-mission Resume .zelari/mission-state.json (not the spine)\n --export-session <path> Write zelari-session-export/1 after the run\n --strict-done Evidence-based BUILD completion gate\n --allow-unverified Exit 0 when strict is ON but nothing could be verified (M1.2)\n --task-file <path> Read the task prompt from a file (Windows argv cap)\n --once Single-cycle run (cron/git-hook triggers, ADR-0014)\n --kraken-graph <goal> Plan + execute a Kraken task graph\n (variant: --kraken-graph-file <path>; kill-switch\n ZELARI_KRAKEN_GRAPH=0)\n --plan-only Serialize the graph plan to .zelari/radio/ and exit 0\n --run-plan <id> Execute a pre-built .zelari/radio/plan-<id>.json\n --gauntlet Host-driven gauntlet loop (builder/critic tentacles)\n --session-export <id> Print a portable 2.0 session export (no LLM)\n serve Companion host for Android/remote clients (Tailscale)\n --bind <ip> Listen address (default: 127.0.0.1; use Tailscale IP)\n --port <n> Port (default: 7421)\n --token <secret> Bearer token (default: ~/.zelari-code/companion.token)\n --project <path> Allowlisted project root (repeatable)\n --save-projects Persist --project list to companion.json\n --serve-harness Long-lived harness kernel for hosts (NDJSON JSON-RPC\n on stdin/stdout; Desktop/companion transport)\n --print-config Print provider/model config as JSON (no secrets)\n --print-settings Print zelari.config.json values + the origin of\n each (default < user < project < env)\n --permissions <p> Permission preset: strict | standard | yolo \u2014 changes\n category DEFAULTS only (env vars and policy files win)\n --evolve-status Evolution ledger stats (read-only; ADR-0036; the\n ledger is written only when ZELARI_EVOLUTION=shadow)\n --plugins-status JSON status of optional plugins (Playwright, eslint, \u2026)\n --plugins-install <id> Install plugin (playwright also fetches Chromium)\n --cwd <path> Workspace for -D installs (default: process.cwd())\n --set-config Persist provider/model/endpoint\n --provider <id> Set active provider\n --model <id> Set model for that provider\n --endpoint <url> Custom OpenAI-compatible base URL\n --endpoint-clear Remove custom endpoint override\n --thinking <spec> Thinking effort (auto|off|low|medium|high|budget:N)\n --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\n --login-oauth Start subscription OAuth (grok, chatgpt, anthropic)\n --provider <id> grok | chatgpt | anthropic\n --code <paste> Anthropic magic-link code (CODE#STATE)\n --no-browser Do not open the system browser\n --refresh-oauth Force-refresh an OAuth access token\n --provider <id> grok | chatgpt | anthropic\n --logout-oauth Clear stored OAuth credentials\n --provider <id> grok | chatgpt | anthropic\n --discover-models Refresh model list for a provider\n --provider <id> Provider (default: active)\n --print-mcp Print MCP server config (user + project)\n --cwd <path> Project root for .zelari/mcp.json\n --set-mcp Add/update an MCP server entry\n --name <id> Server name (required)\n --command <bin> Executable for stdio servers\n --url <endpoint> Streamable HTTP endpoint (e.g. UE 5.8 editor)\n --args <json> JSON array of args (stdio, optional)\n --timeout <ms> Per-server request timeout (http, optional)\n --scope user|project Default: user\n --enabled true|false Default: true\n --cwd <path> Required when scope=project\n --set-mcp-preset Install a named MCP preset (e.g. cua)\n --preset cua Cua Driver desktop computer-use (MCP)\n --preset unreal-mcp Unreal Engine 5.8+ editor (MCP over HTTP)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-mcp Remove an MCP server entry\n --name <id> --scope user|project [--cwd <path>]\n --print-skills Print skills (builtin + user + project)\n --cwd <path> Project root for .zelari/skills\n --set-skill Add/update a SKILL.md skill\n --name <id> Skill id (required)\n --description <t> One-line description (required)\n --body <text> Markdown instructions (required)\n --category <c> plan|refactor|debug|review|test|docs|ops|git|db|maint\n --tools <csv> Comma-separated required tools (optional)\n --cost <l> low|medium|high (default: medium)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-skill Remove a user/project SKILL.md\n --name <id> --scope user|project [--cwd <path>]\n --generate-skill-from-url Fetch URL + draft skill via model (JSON)\n --url <https://...> Required\n --provider <id> Override active provider\n --model <name> Override model for the selected provider\n --print-ssh-targets Print SSH deploy/monitor targets\n --set-ssh-target Upsert target (--json '{...}' or flags)\n --remove-ssh-target --id <id>\n --test-ssh-target --id <id> (BatchMode ssh true)\n --print-ssh-pubkey --path <private-or-.pub> (display public key)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n ZELARI_MEMORY_MCP=1 Enable the optional external memory MCP server\n ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
84987
85261
|
);
|
|
84988
85262
|
process.exit(0);
|
|
84989
85263
|
}
|