zelari-code 2.34.0 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/browser/tools.js +23 -1
- package/dist/cli/browser/tools.js.map +1 -1
- package/dist/cli/councilDispatcher.js +1 -0
- package/dist/cli/councilDispatcher.js.map +1 -1
- package/dist/cli/headless/liveTurnAbort.js +67 -0
- package/dist/cli/headless/liveTurnAbort.js.map +1 -0
- package/dist/cli/headless/runOneTurn.js +5 -1
- package/dist/cli/headless/runOneTurn.js.map +1 -1
- package/dist/cli/headless.js.map +1 -1
- package/dist/cli/main.bundled.js +1352 -818
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/provider/openai-compatible.js +53 -24
- package/dist/cli/provider/openai-compatible.js.map +1 -1
- package/dist/cli/runHeadless.js +55 -7
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/serve/askUserBridge.js +59 -0
- package/dist/cli/serve/askUserBridge.js.map +1 -0
- package/dist/cli/serve/harnessServer.js +14 -2
- package/dist/cli/serve/harnessServer.js.map +1 -1
- package/dist/cli/serve/permissionBridge.js +64 -8
- package/dist/cli/serve/permissionBridge.js.map +1 -1
- package/dist/cli/serve/sessionControl.js +5 -3
- package/dist/cli/serve/sessionControl.js.map +1 -1
- package/dist/cli/toolRegistry.js +44 -17
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/tools/krakenModel.js +18 -0
- package/dist/cli/tools/krakenModel.js.map +1 -1
- package/dist/cli/tools/screenshotTool.js +111 -0
- package/dist/cli/tools/screenshotTool.js.map +1 -0
- package/dist/cli/tools/taskTool.js +59 -9
- package/dist/cli/tools/taskTool.js.map +1 -1
- package/dist/cli/utils/doctor.js +24 -3
- package/dist/cli/utils/doctor.js.map +1 -1
- package/dist/cli/utils/fixPath.js +18 -14
- package/dist/cli/utils/fixPath.js.map +1 -1
- package/dist/cli/utils/streamScrub.js +5 -3
- package/dist/cli/utils/streamScrub.js.map +1 -1
- package/dist/cli/zelariMission.js +14 -0
- package/dist/cli/zelariMission.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -3414,10 +3414,10 @@ function mergeDefs(...defs) {
|
|
|
3414
3414
|
function cloneDef(schema) {
|
|
3415
3415
|
return mergeDefs(schema._zod.def);
|
|
3416
3416
|
}
|
|
3417
|
-
function getElementAtPath(obj,
|
|
3418
|
-
if (!
|
|
3417
|
+
function getElementAtPath(obj, path100) {
|
|
3418
|
+
if (!path100)
|
|
3419
3419
|
return obj;
|
|
3420
|
-
return
|
|
3420
|
+
return path100.reduce((acc, key) => acc?.[key], obj);
|
|
3421
3421
|
}
|
|
3422
3422
|
function promiseAllObject(promisesObj) {
|
|
3423
3423
|
const keys = Object.keys(promisesObj);
|
|
@@ -3745,11 +3745,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
3745
3745
|
}
|
|
3746
3746
|
return false;
|
|
3747
3747
|
}
|
|
3748
|
-
function prefixIssues(
|
|
3748
|
+
function prefixIssues(path100, issues) {
|
|
3749
3749
|
return issues.map((iss) => {
|
|
3750
3750
|
var _a3;
|
|
3751
3751
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
3752
|
-
iss.path.unshift(
|
|
3752
|
+
iss.path.unshift(path100);
|
|
3753
3753
|
return iss;
|
|
3754
3754
|
});
|
|
3755
3755
|
}
|
|
@@ -3967,16 +3967,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
3967
3967
|
}
|
|
3968
3968
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
3969
3969
|
const fieldErrors = { _errors: [] };
|
|
3970
|
-
const processError = (error52,
|
|
3970
|
+
const processError = (error52, path100 = []) => {
|
|
3971
3971
|
for (const issue2 of error52.issues) {
|
|
3972
3972
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
3973
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
3973
|
+
issue2.errors.map((issues) => processError({ issues }, [...path100, ...issue2.path]));
|
|
3974
3974
|
} else if (issue2.code === "invalid_key") {
|
|
3975
|
-
processError({ issues: issue2.issues }, [...
|
|
3975
|
+
processError({ issues: issue2.issues }, [...path100, ...issue2.path]);
|
|
3976
3976
|
} else if (issue2.code === "invalid_element") {
|
|
3977
|
-
processError({ issues: issue2.issues }, [...
|
|
3977
|
+
processError({ issues: issue2.issues }, [...path100, ...issue2.path]);
|
|
3978
3978
|
} else {
|
|
3979
|
-
const fullpath = [...
|
|
3979
|
+
const fullpath = [...path100, ...issue2.path];
|
|
3980
3980
|
if (fullpath.length === 0) {
|
|
3981
3981
|
fieldErrors._errors.push(mapper(issue2));
|
|
3982
3982
|
} else {
|
|
@@ -4003,17 +4003,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4003
4003
|
}
|
|
4004
4004
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
4005
4005
|
const result = { errors: [] };
|
|
4006
|
-
const processError = (error52,
|
|
4006
|
+
const processError = (error52, path100 = []) => {
|
|
4007
4007
|
var _a3, _b;
|
|
4008
4008
|
for (const issue2 of error52.issues) {
|
|
4009
4009
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
4010
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
4010
|
+
issue2.errors.map((issues) => processError({ issues }, [...path100, ...issue2.path]));
|
|
4011
4011
|
} else if (issue2.code === "invalid_key") {
|
|
4012
|
-
processError({ issues: issue2.issues }, [...
|
|
4012
|
+
processError({ issues: issue2.issues }, [...path100, ...issue2.path]);
|
|
4013
4013
|
} else if (issue2.code === "invalid_element") {
|
|
4014
|
-
processError({ issues: issue2.issues }, [...
|
|
4014
|
+
processError({ issues: issue2.issues }, [...path100, ...issue2.path]);
|
|
4015
4015
|
} else {
|
|
4016
|
-
const fullpath = [...
|
|
4016
|
+
const fullpath = [...path100, ...issue2.path];
|
|
4017
4017
|
if (fullpath.length === 0) {
|
|
4018
4018
|
result.errors.push(mapper(issue2));
|
|
4019
4019
|
continue;
|
|
@@ -4045,8 +4045,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4045
4045
|
}
|
|
4046
4046
|
function toDotPath(_path) {
|
|
4047
4047
|
const segs = [];
|
|
4048
|
-
const
|
|
4049
|
-
for (const seg of
|
|
4048
|
+
const path100 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
4049
|
+
for (const seg of path100) {
|
|
4050
4050
|
if (typeof seg === "number")
|
|
4051
4051
|
segs.push(`[${seg}]`);
|
|
4052
4052
|
else if (typeof seg === "symbol")
|
|
@@ -17549,13 +17549,13 @@ function resolveRef(ref, ctx) {
|
|
|
17549
17549
|
if (!ref.startsWith("#")) {
|
|
17550
17550
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
17551
17551
|
}
|
|
17552
|
-
const
|
|
17553
|
-
if (
|
|
17552
|
+
const path100 = ref.slice(1).split("/").filter(Boolean);
|
|
17553
|
+
if (path100.length === 0) {
|
|
17554
17554
|
return ctx.rootSchema;
|
|
17555
17555
|
}
|
|
17556
17556
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
17557
|
-
if (
|
|
17558
|
-
const key =
|
|
17557
|
+
if (path100[0] === defsKey) {
|
|
17558
|
+
const key = path100[1];
|
|
17559
17559
|
if (!key || !ctx.defs[key]) {
|
|
17560
17560
|
throw new Error(`Reference not found: ${ref}`);
|
|
17561
17561
|
}
|
|
@@ -18327,7 +18327,9 @@ var init_zod = __esm({
|
|
|
18327
18327
|
});
|
|
18328
18328
|
|
|
18329
18329
|
// packages/core/dist/core/tools/toolTypes.js
|
|
18330
|
-
function typedOk(value, meta3) {
|
|
18330
|
+
function typedOk(value, meta3, images) {
|
|
18331
|
+
if (images && images.length > 0)
|
|
18332
|
+
return { ok: true, value, meta: meta3, images };
|
|
18331
18333
|
return meta3 ? { ok: true, value, meta: meta3 } : { ok: true, value };
|
|
18332
18334
|
}
|
|
18333
18335
|
function typedErr(error51, meta3) {
|
|
@@ -18387,17 +18389,17 @@ var init_newlines = __esm({
|
|
|
18387
18389
|
});
|
|
18388
18390
|
|
|
18389
18391
|
// packages/core/dist/core/tools/builtin/fileEvents.js
|
|
18390
|
-
function fileReadEvent(
|
|
18391
|
-
return { kind: "file.read", actor: { type: "tool" }, data: { path:
|
|
18392
|
+
function fileReadEvent(path100, snapshotId) {
|
|
18393
|
+
return { kind: "file.read", actor: { type: "tool" }, data: { path: path100, snapshotId } };
|
|
18392
18394
|
}
|
|
18393
|
-
function fileAppliedEvent(
|
|
18394
|
-
return { kind: "file.applied", actor: { type: "tool" }, data: { path:
|
|
18395
|
+
function fileAppliedEvent(path100, snapshotId, bytes) {
|
|
18396
|
+
return { kind: "file.applied", actor: { type: "tool" }, data: { path: path100, snapshotId, bytes } };
|
|
18395
18397
|
}
|
|
18396
|
-
function fileRejectedEvent(
|
|
18398
|
+
function fileRejectedEvent(path100, reason, hint) {
|
|
18397
18399
|
return {
|
|
18398
18400
|
kind: "file.rejected",
|
|
18399
18401
|
actor: { type: "tool" },
|
|
18400
|
-
data: hint === void 0 ? { path:
|
|
18402
|
+
data: hint === void 0 ? { path: path100, reason } : { path: path100, reason, hint }
|
|
18401
18403
|
};
|
|
18402
18404
|
}
|
|
18403
18405
|
function reReadHint(reject) {
|
|
@@ -19313,8 +19315,8 @@ async function searchFile(absPath, relPath, regex, contextLines, remainingSlots)
|
|
|
19313
19315
|
}
|
|
19314
19316
|
async function isDirectory(p3) {
|
|
19315
19317
|
try {
|
|
19316
|
-
const
|
|
19317
|
-
return
|
|
19318
|
+
const stat8 = await fs7.stat(p3);
|
|
19319
|
+
return stat8.isDirectory();
|
|
19318
19320
|
} catch {
|
|
19319
19321
|
return false;
|
|
19320
19322
|
}
|
|
@@ -20266,11 +20268,11 @@ var init_tools = __esm({
|
|
|
20266
20268
|
if (!ctx.addDocument)
|
|
20267
20269
|
return "Knowledge vault tool not available.";
|
|
20268
20270
|
const title = args["title"] || "New Document";
|
|
20269
|
-
const
|
|
20271
|
+
const path100 = args["path"] || `notes/${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
|
|
20270
20272
|
const content = args["content"] || "";
|
|
20271
20273
|
const tags = args["tags"] || [];
|
|
20272
20274
|
ctx.addDocument({
|
|
20273
|
-
path:
|
|
20275
|
+
path: path100,
|
|
20274
20276
|
title,
|
|
20275
20277
|
content,
|
|
20276
20278
|
format: "markdown",
|
|
@@ -20279,7 +20281,7 @@ var init_tools = __esm({
|
|
|
20279
20281
|
workspaceId: ctx.workspaceId
|
|
20280
20282
|
});
|
|
20281
20283
|
ctx.addActivity("vault", "created document", title);
|
|
20282
|
-
return `Document "${title}" created at "${
|
|
20284
|
+
return `Document "${title}" created at "${path100}".`;
|
|
20283
20285
|
}
|
|
20284
20286
|
}
|
|
20285
20287
|
];
|
|
@@ -25104,16 +25106,16 @@ function runRetentionFromEnv() {
|
|
|
25104
25106
|
maxTotalBytes: Number.isFinite(parseMb) && parseMb > 0 ? Math.round(parseMb * 1024 * 1024) : DEFAULT_RUN_RETENTION_MAX_MB * 1024 * 1024
|
|
25105
25107
|
};
|
|
25106
25108
|
}
|
|
25107
|
-
async function dirSize(
|
|
25109
|
+
async function dirSize(path100) {
|
|
25108
25110
|
let total = 0;
|
|
25109
25111
|
let entries;
|
|
25110
25112
|
try {
|
|
25111
|
-
entries = await readdir(
|
|
25113
|
+
entries = await readdir(path100, { withFileTypes: true });
|
|
25112
25114
|
} catch {
|
|
25113
25115
|
return 0;
|
|
25114
25116
|
}
|
|
25115
25117
|
for (const entry of entries) {
|
|
25116
|
-
const child = join3(
|
|
25118
|
+
const child = join3(path100, entry.name);
|
|
25117
25119
|
if (entry.isDirectory())
|
|
25118
25120
|
total += await dirSize(child);
|
|
25119
25121
|
else {
|
|
@@ -25140,19 +25142,19 @@ async function enforceRunRetention(runsDir, options = {}) {
|
|
|
25140
25142
|
for (const entry of entries) {
|
|
25141
25143
|
if (!entry.isDirectory())
|
|
25142
25144
|
continue;
|
|
25143
|
-
const
|
|
25145
|
+
const path100 = join3(runsDir, entry.name);
|
|
25144
25146
|
let startedAt = 0;
|
|
25145
25147
|
let endedAt;
|
|
25146
25148
|
let completed = false;
|
|
25147
25149
|
try {
|
|
25148
|
-
const manifest = JSON.parse(await readFile(join3(
|
|
25150
|
+
const manifest = JSON.parse(await readFile(join3(path100, "manifest.json"), "utf8"));
|
|
25149
25151
|
startedAt = manifest.startedAt ?? 0;
|
|
25150
25152
|
endedAt = manifest.endedAt;
|
|
25151
25153
|
completed = Boolean(endedAt) && manifest.status !== "running";
|
|
25152
25154
|
} catch {
|
|
25153
25155
|
completed = false;
|
|
25154
25156
|
}
|
|
25155
|
-
infos.push({ name: entry.name, path:
|
|
25157
|
+
infos.push({ name: entry.name, path: path100, startedAt, endedAt, completed, bytes: await dirSize(path100) });
|
|
25156
25158
|
}
|
|
25157
25159
|
const remove = async (info) => {
|
|
25158
25160
|
await rm(info.path, { recursive: true, force: true });
|
|
@@ -25639,12 +25641,12 @@ var init_engine = __esm({
|
|
|
25639
25641
|
* content digest) and the returned ref carries the event seq when the
|
|
25640
25642
|
* emitter resolved one.
|
|
25641
25643
|
*/
|
|
25642
|
-
async fsEvidence(observation,
|
|
25644
|
+
async fsEvidence(observation, path100, sha256, content, extra = {}) {
|
|
25643
25645
|
const digest = sha256 && content !== void 0 ? sha256(content) : void 0;
|
|
25644
|
-
const seq = await this.emitEvidence({ observation, path:
|
|
25646
|
+
const seq = await this.emitEvidence({ observation, path: path100, ...extra, ...digest ? { digest } : {} });
|
|
25645
25647
|
return {
|
|
25646
25648
|
tier: "fs-observation",
|
|
25647
|
-
ref:
|
|
25649
|
+
ref: path100,
|
|
25648
25650
|
capturedAt: Date.now(),
|
|
25649
25651
|
...digest ? { digest } : {},
|
|
25650
25652
|
...seq !== void 0 ? { seq } : {}
|
|
@@ -28372,6 +28374,136 @@ var init_textLoopDetect = __esm({
|
|
|
28372
28374
|
}
|
|
28373
28375
|
});
|
|
28374
28376
|
|
|
28377
|
+
// packages/core/dist/agents/council/outputCleaning.js
|
|
28378
|
+
function extractBalancedJsonObject(s) {
|
|
28379
|
+
const start = s.indexOf("{");
|
|
28380
|
+
if (start < 0)
|
|
28381
|
+
return null;
|
|
28382
|
+
let depth = 0;
|
|
28383
|
+
let inString = false;
|
|
28384
|
+
let escape = false;
|
|
28385
|
+
for (let i = start; i < s.length; i++) {
|
|
28386
|
+
const ch = s[i];
|
|
28387
|
+
if (inString) {
|
|
28388
|
+
if (escape) {
|
|
28389
|
+
escape = false;
|
|
28390
|
+
continue;
|
|
28391
|
+
}
|
|
28392
|
+
if (ch === "\\") {
|
|
28393
|
+
escape = true;
|
|
28394
|
+
continue;
|
|
28395
|
+
}
|
|
28396
|
+
if (ch === '"')
|
|
28397
|
+
inString = false;
|
|
28398
|
+
continue;
|
|
28399
|
+
}
|
|
28400
|
+
if (ch === '"') {
|
|
28401
|
+
inString = true;
|
|
28402
|
+
continue;
|
|
28403
|
+
}
|
|
28404
|
+
if (ch === "{")
|
|
28405
|
+
depth++;
|
|
28406
|
+
else if (ch === "}") {
|
|
28407
|
+
depth--;
|
|
28408
|
+
if (depth === 0)
|
|
28409
|
+
return s.slice(start, i + 1);
|
|
28410
|
+
}
|
|
28411
|
+
}
|
|
28412
|
+
return null;
|
|
28413
|
+
}
|
|
28414
|
+
function parseClarificationRequest(text) {
|
|
28415
|
+
const start = text.indexOf(QUESTION_MARKER);
|
|
28416
|
+
if (start < 0)
|
|
28417
|
+
return null;
|
|
28418
|
+
const rest = text.slice(start + QUESTION_MARKER.length);
|
|
28419
|
+
const end = rest.indexOf(QUESTION_END_MARKER);
|
|
28420
|
+
const block = end >= 0 ? rest.slice(0, end) : rest;
|
|
28421
|
+
const cleaned = block.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim();
|
|
28422
|
+
const jsonText = extractBalancedJsonObject(cleaned) ?? (() => {
|
|
28423
|
+
const objStart = cleaned.indexOf("{");
|
|
28424
|
+
const objEnd = cleaned.lastIndexOf("}");
|
|
28425
|
+
return objStart >= 0 && objEnd > objStart ? cleaned.slice(objStart, objEnd + 1) : cleaned;
|
|
28426
|
+
})();
|
|
28427
|
+
try {
|
|
28428
|
+
const parsed = JSON.parse(jsonText);
|
|
28429
|
+
if (typeof parsed.question !== "string" || !parsed.question.trim())
|
|
28430
|
+
return null;
|
|
28431
|
+
return {
|
|
28432
|
+
question: parsed.question.trim(),
|
|
28433
|
+
choices: Array.isArray(parsed.choices) ? parsed.choices.filter((c) => typeof c === "string" && c.trim().length > 0).map((c) => c.trim()) : void 0,
|
|
28434
|
+
context: typeof parsed.context === "string" ? parsed.context.trim() : void 0
|
|
28435
|
+
};
|
|
28436
|
+
} catch {
|
|
28437
|
+
return null;
|
|
28438
|
+
}
|
|
28439
|
+
}
|
|
28440
|
+
function hasInteractiveClarification(text) {
|
|
28441
|
+
const c = parseClarificationRequest(text);
|
|
28442
|
+
return !!(c && c.choices && c.choices.length >= 2);
|
|
28443
|
+
}
|
|
28444
|
+
function stripQuestionBlocks(text) {
|
|
28445
|
+
let out = "";
|
|
28446
|
+
let rest = text;
|
|
28447
|
+
while (true) {
|
|
28448
|
+
const start = rest.indexOf(QUESTION_MARKER);
|
|
28449
|
+
if (start < 0) {
|
|
28450
|
+
out += rest;
|
|
28451
|
+
break;
|
|
28452
|
+
}
|
|
28453
|
+
out += rest.slice(0, start);
|
|
28454
|
+
const afterMarker = rest.slice(start + QUESTION_MARKER.length);
|
|
28455
|
+
const trimmed = afterMarker.replace(/^\s+/, "");
|
|
28456
|
+
if (!trimmed.startsWith("{")) {
|
|
28457
|
+
out += QUESTION_MARKER;
|
|
28458
|
+
rest = afterMarker;
|
|
28459
|
+
continue;
|
|
28460
|
+
}
|
|
28461
|
+
const endIdx = afterMarker.indexOf(QUESTION_END_MARKER);
|
|
28462
|
+
if (endIdx >= 0) {
|
|
28463
|
+
rest = afterMarker.slice(endIdx + QUESTION_END_MARKER.length);
|
|
28464
|
+
continue;
|
|
28465
|
+
}
|
|
28466
|
+
const json3 = extractBalancedJsonObject(trimmed);
|
|
28467
|
+
if (json3) {
|
|
28468
|
+
const jsonAt = afterMarker.indexOf(json3);
|
|
28469
|
+
rest = afterMarker.slice(jsonAt + json3.length);
|
|
28470
|
+
continue;
|
|
28471
|
+
}
|
|
28472
|
+
break;
|
|
28473
|
+
}
|
|
28474
|
+
return out.replace(/\n{3,}/g, "\n\n").trim();
|
|
28475
|
+
}
|
|
28476
|
+
function parseThinking(text) {
|
|
28477
|
+
const complete = text.match(/<think(?:ing)?>([\s\S]*?)<\/think(?:ing)?>/i);
|
|
28478
|
+
if (complete)
|
|
28479
|
+
return complete[1].trim();
|
|
28480
|
+
const open2 = text.match(/<think(?:ing)?>([\s\S]*)$/i);
|
|
28481
|
+
return open2 ? open2[1].trim() : "";
|
|
28482
|
+
}
|
|
28483
|
+
function cleanAgentContent(text, opts = {}) {
|
|
28484
|
+
const stripQuestion = opts.stripQuestion !== false;
|
|
28485
|
+
const stripThink = opts.stripThink !== false;
|
|
28486
|
+
let out = text;
|
|
28487
|
+
if (stripThink) {
|
|
28488
|
+
out = out.replace(/<think(?:ing)?>[\s\S]*?<\/think(?:ing)?>/gi, "").replace(/<think(?:ing)?>[\s\S]*$/gi, "").replace(/<\/think(?:ing)?>/gi, "");
|
|
28489
|
+
}
|
|
28490
|
+
out = out.replace(/<minimax:tool_call>[\s\S]*?<\/minimax:tool_call>/gi, "").replace(/<\/?minimax:tool_call>/gi, "").replace(/<tool_call>[\s\S]*?<\/tool_call>/gi, "").replace(/<\/?tool_call>/gi, "").replace(/<function_call>[\s\S]*?<\/function_call>/gi, "").replace(/<\/?function_call>/gi, "").replace(/<invoke\b[^>]*>[\s\S]*?<\/invoke>/gi, "").replace(/<\/invoke>/gi, "").replace(/<parameter\b[^>]*>[\s\S]*?<\/parameter>/gi, "").replace(/<\/parameter>/gi, "").replace(/\]\s*<\]\s*minimax\s*\[>\s*\[?<invoke\b[^>]*>[\s\S]*?<\/invoke>/gi, "").replace(/<minimax:tool_call>[\s\S]*$/gi, "").replace(/<tool_call>[\s\S]*$/gi, "").replace(/<function_call>[\s\S]*$/gi, "").replace(/<invoke\b[^>]*>[\s\S]*$/gi, "").replace(/\]\s*<\]\s*minimax\s*\[>[\s\S]*$/gi, "").replace(/^\s*\]\s*<\]\s*minimax\s*\[>.*$/gim, "").replace(/^\s*<\/?(?:tool_call|function_call|invoke|parameter|minimax:tool_call)\b[^>]*>\s*$/gim, "");
|
|
28491
|
+
if (stripQuestion) {
|
|
28492
|
+
out = stripQuestionBlocks(out);
|
|
28493
|
+
}
|
|
28494
|
+
out = out.replace(/\n{3,}/g, "\n\n").trim();
|
|
28495
|
+
return scrubProprietaryLeak(out);
|
|
28496
|
+
}
|
|
28497
|
+
var QUESTION_MARKER, QUESTION_END_MARKER;
|
|
28498
|
+
var init_outputCleaning = __esm({
|
|
28499
|
+
"packages/core/dist/agents/council/outputCleaning.js"() {
|
|
28500
|
+
"use strict";
|
|
28501
|
+
init_secrecyPolicy();
|
|
28502
|
+
QUESTION_MARKER = "---QUESTION---";
|
|
28503
|
+
QUESTION_END_MARKER = "---END---";
|
|
28504
|
+
}
|
|
28505
|
+
});
|
|
28506
|
+
|
|
28375
28507
|
// packages/core/dist/core/AgentHarness.js
|
|
28376
28508
|
function gateAdvice(hardLimit) {
|
|
28377
28509
|
return hardLimit ? "Finalize now with the evidence already collected; no further tool calls will run this turn." : "Prioritize verification/repair actions (test, typecheck, build, read failures) or finalize honestly.";
|
|
@@ -28668,6 +28800,7 @@ var init_AgentHarness = __esm({
|
|
|
28668
28800
|
init_requestSnapshot();
|
|
28669
28801
|
init_textLoopDetect();
|
|
28670
28802
|
init_ObserverBus();
|
|
28803
|
+
init_outputCleaning();
|
|
28671
28804
|
init_textLoopDetect();
|
|
28672
28805
|
TOOL_CALL_TRUNCATED_RECOVERY_MARKER = "[harness] Previous tool call was truncated";
|
|
28673
28806
|
TOOL_CALL_TRUNCATED_RECOVERY_USER = `${TOOL_CALL_TRUNCATED_RECOVERY_MARKER} by the provider before completion (finish_reason=tool_calls but no complete tool_call arrived). Retry with a shorter payload or split the work into smaller tool calls.`;
|
|
@@ -28975,7 +29108,8 @@ ${shared.content}`,
|
|
|
28975
29108
|
return {
|
|
28976
29109
|
content: resultStr,
|
|
28977
29110
|
isError: !result.ok,
|
|
28978
|
-
durationMs: Date.now() - startMs
|
|
29111
|
+
durationMs: Date.now() - startMs,
|
|
29112
|
+
...result.ok && result.images && result.images.length > 0 ? { images: result.images } : {}
|
|
28979
29113
|
};
|
|
28980
29114
|
})();
|
|
28981
29115
|
inflight.set(callKey, prom);
|
|
@@ -28996,7 +29130,8 @@ ${shared.content}`,
|
|
|
28996
29130
|
toolCallId: p3.toolCallId,
|
|
28997
29131
|
content: r.content,
|
|
28998
29132
|
isError: r.isError,
|
|
28999
|
-
endEvent
|
|
29133
|
+
endEvent,
|
|
29134
|
+
...r.images ? { images: r.images } : {}
|
|
29000
29135
|
// Cache already written in invokeOne; no need to re-set.
|
|
29001
29136
|
};
|
|
29002
29137
|
};
|
|
@@ -29548,7 +29683,8 @@ ${cached2}`
|
|
|
29548
29683
|
yield item.endEvent;
|
|
29549
29684
|
turnToolResults.push({
|
|
29550
29685
|
toolCallId: item.toolCallId,
|
|
29551
|
-
content: item.content
|
|
29686
|
+
content: item.content,
|
|
29687
|
+
...item.images ? { images: item.images } : {}
|
|
29552
29688
|
});
|
|
29553
29689
|
if (item.cacheKey && item.content && !item.isError) {
|
|
29554
29690
|
this.toolCallCache.set(item.cacheKey, item.content);
|
|
@@ -29562,7 +29698,7 @@ ${cached2}`
|
|
|
29562
29698
|
}
|
|
29563
29699
|
pendingNativeTools.length = 0;
|
|
29564
29700
|
}
|
|
29565
|
-
const clarificationPause =
|
|
29701
|
+
const clarificationPause = hasInteractiveClarification(turnText);
|
|
29566
29702
|
if (clarificationPause) {
|
|
29567
29703
|
finishRef.value = "stop";
|
|
29568
29704
|
finishRef.clarificationRequested = true;
|
|
@@ -29728,7 +29864,8 @@ ${cached2}`
|
|
|
29728
29864
|
this.config.messages.push({
|
|
29729
29865
|
role: "tool",
|
|
29730
29866
|
toolCallId: tr.toolCallId,
|
|
29731
|
-
content: tr.content
|
|
29867
|
+
content: tr.content,
|
|
29868
|
+
...tr.images ? { images: tr.images } : {}
|
|
29732
29869
|
});
|
|
29733
29870
|
}
|
|
29734
29871
|
if (truncatedToolCall) {
|
|
@@ -31529,11 +31666,11 @@ var init_synthesisAudit = __esm({
|
|
|
31529
31666
|
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
31530
31667
|
import { join as join5 } from "node:path";
|
|
31531
31668
|
function loadNfrSpec(zelariRoot) {
|
|
31532
|
-
const
|
|
31533
|
-
if (!existsSync10(
|
|
31669
|
+
const path100 = join5(zelariRoot, "nfr-spec.json");
|
|
31670
|
+
if (!existsSync10(path100))
|
|
31534
31671
|
return null;
|
|
31535
31672
|
try {
|
|
31536
|
-
const raw = JSON.parse(readFileSync9(
|
|
31673
|
+
const raw = JSON.parse(readFileSync9(path100, "utf8"));
|
|
31537
31674
|
if (raw.version !== 1 || !Array.isArray(raw.targets))
|
|
31538
31675
|
return null;
|
|
31539
31676
|
return raw;
|
|
@@ -32128,101 +32265,36 @@ var init_types7 = __esm({
|
|
|
32128
32265
|
}
|
|
32129
32266
|
});
|
|
32130
32267
|
|
|
32131
|
-
// packages/core/dist/agents/council/
|
|
32132
|
-
function
|
|
32133
|
-
|
|
32134
|
-
if (start < 0)
|
|
32135
|
-
return null;
|
|
32136
|
-
let depth = 0;
|
|
32137
|
-
let inString = false;
|
|
32138
|
-
let escape = false;
|
|
32139
|
-
for (let i = start; i < s.length; i++) {
|
|
32140
|
-
const ch = s[i];
|
|
32141
|
-
if (inString) {
|
|
32142
|
-
if (escape) {
|
|
32143
|
-
escape = false;
|
|
32144
|
-
continue;
|
|
32145
|
-
}
|
|
32146
|
-
if (ch === "\\") {
|
|
32147
|
-
escape = true;
|
|
32148
|
-
continue;
|
|
32149
|
-
}
|
|
32150
|
-
if (ch === '"')
|
|
32151
|
-
inString = false;
|
|
32152
|
-
continue;
|
|
32153
|
-
}
|
|
32154
|
-
if (ch === '"') {
|
|
32155
|
-
inString = true;
|
|
32156
|
-
continue;
|
|
32157
|
-
}
|
|
32158
|
-
if (ch === "{")
|
|
32159
|
-
depth++;
|
|
32160
|
-
else if (ch === "}") {
|
|
32161
|
-
depth--;
|
|
32162
|
-
if (depth === 0)
|
|
32163
|
-
return s.slice(start, i + 1);
|
|
32164
|
-
}
|
|
32165
|
-
}
|
|
32166
|
-
return null;
|
|
32268
|
+
// packages/core/dist/agents/council/cancel.js
|
|
32269
|
+
function isCouncilCancelled(signal) {
|
|
32270
|
+
return signal?.aborted === true;
|
|
32167
32271
|
}
|
|
32168
|
-
function
|
|
32169
|
-
|
|
32170
|
-
|
|
32171
|
-
|
|
32172
|
-
|
|
32173
|
-
|
|
32174
|
-
const block = end >= 0 ? rest.slice(0, end) : rest;
|
|
32175
|
-
const cleaned = block.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim();
|
|
32176
|
-
const jsonText = extractBalancedJsonObject(cleaned) ?? (() => {
|
|
32177
|
-
const objStart = cleaned.indexOf("{");
|
|
32178
|
-
const objEnd = cleaned.lastIndexOf("}");
|
|
32179
|
-
return objStart >= 0 && objEnd > objStart ? cleaned.slice(objStart, objEnd + 1) : cleaned;
|
|
32180
|
-
})();
|
|
32181
|
-
try {
|
|
32182
|
-
const parsed = JSON.parse(jsonText);
|
|
32183
|
-
if (typeof parsed.question !== "string" || !parsed.question.trim())
|
|
32184
|
-
return null;
|
|
32185
|
-
return {
|
|
32186
|
-
question: parsed.question.trim(),
|
|
32187
|
-
choices: Array.isArray(parsed.choices) ? parsed.choices.filter((c) => typeof c === "string" && c.trim().length > 0).map((c) => c.trim()) : void 0,
|
|
32188
|
-
context: typeof parsed.context === "string" ? parsed.context.trim() : void 0
|
|
32189
|
-
};
|
|
32190
|
-
} catch {
|
|
32191
|
-
return null;
|
|
32272
|
+
function bindHarnessAbort(harness, signal) {
|
|
32273
|
+
if (!signal)
|
|
32274
|
+
return () => void 0;
|
|
32275
|
+
if (signal.aborted) {
|
|
32276
|
+
harness.cancel();
|
|
32277
|
+
return () => void 0;
|
|
32192
32278
|
}
|
|
32279
|
+
const onAbort = () => {
|
|
32280
|
+
harness.cancel();
|
|
32281
|
+
};
|
|
32282
|
+
signal.addEventListener("abort", onAbort);
|
|
32283
|
+
return () => {
|
|
32284
|
+
signal.removeEventListener("abort", onAbort);
|
|
32285
|
+
};
|
|
32193
32286
|
}
|
|
32194
|
-
function
|
|
32195
|
-
const
|
|
32196
|
-
|
|
32197
|
-
|
|
32198
|
-
|
|
32199
|
-
|
|
32200
|
-
if (complete)
|
|
32201
|
-
return complete[1].trim();
|
|
32202
|
-
const open2 = text.match(/<think(?:ing)?>([\s\S]*)$/i);
|
|
32203
|
-
return open2 ? open2[1].trim() : "";
|
|
32204
|
-
}
|
|
32205
|
-
function cleanAgentContent(text, opts = {}) {
|
|
32206
|
-
const stripQuestion = opts.stripQuestion !== false;
|
|
32207
|
-
const stripThink = opts.stripThink !== false;
|
|
32208
|
-
let out = text;
|
|
32209
|
-
if (stripThink) {
|
|
32210
|
-
out = out.replace(/<think(?:ing)?>[\s\S]*?<\/think(?:ing)?>/gi, "").replace(/<think(?:ing)?>[\s\S]*$/gi, "").replace(/<\/think(?:ing)?>/gi, "");
|
|
32211
|
-
}
|
|
32212
|
-
out = out.replace(/<minimax:tool_call>[\s\S]*?<\/minimax:tool_call>/gi, "").replace(/<\/?minimax:tool_call>/gi, "").replace(/<tool_call>[\s\S]*?<\/tool_call>/gi, "").replace(/<\/?tool_call>/gi, "").replace(/<function_call>[\s\S]*?<\/function_call>/gi, "").replace(/<\/?function_call>/gi, "").replace(/<invoke\b[^>]*>[\s\S]*?<\/invoke>/gi, "").replace(/<\/invoke>/gi, "").replace(/<parameter\b[^>]*>[\s\S]*?<\/parameter>/gi, "").replace(/<\/parameter>/gi, "").replace(/\]\s*<\]\s*minimax\s*\[>\s*\[?<invoke\b[^>]*>[\s\S]*?<\/invoke>/gi, "").replace(/<minimax:tool_call>[\s\S]*$/gi, "").replace(/<tool_call>[\s\S]*$/gi, "").replace(/<function_call>[\s\S]*$/gi, "").replace(/<invoke\b[^>]*>[\s\S]*$/gi, "").replace(/\]\s*<\]\s*minimax\s*\[>[\s\S]*$/gi, "").replace(/^\s*\]\s*<\]\s*minimax\s*\[>.*$/gim, "").replace(/^\s*<\/?(?:tool_call|function_call|invoke|parameter|minimax:tool_call)\b[^>]*>\s*$/gim, "");
|
|
32213
|
-
if (stripQuestion) {
|
|
32214
|
-
out = out.replace(/---QUESTION---[\s\S]*?---END---/g, "").replace(/---QUESTION---[\s\S]*$/g, "");
|
|
32287
|
+
async function* runHarnessWithAbort(harness, signal) {
|
|
32288
|
+
const unbind = bindHarnessAbort(harness, signal);
|
|
32289
|
+
try {
|
|
32290
|
+
yield* harness.run();
|
|
32291
|
+
} finally {
|
|
32292
|
+
unbind();
|
|
32215
32293
|
}
|
|
32216
|
-
out = out.replace(/\n{3,}/g, "\n\n").trim();
|
|
32217
|
-
return scrubProprietaryLeak(out);
|
|
32218
32294
|
}
|
|
32219
|
-
var
|
|
32220
|
-
|
|
32221
|
-
"packages/core/dist/agents/council/outputCleaning.js"() {
|
|
32295
|
+
var init_cancel = __esm({
|
|
32296
|
+
"packages/core/dist/agents/council/cancel.js"() {
|
|
32222
32297
|
"use strict";
|
|
32223
|
-
init_secrecyPolicy();
|
|
32224
|
-
QUESTION_MARKER = "---QUESTION---";
|
|
32225
|
-
QUESTION_END_MARKER = "---END---";
|
|
32226
32298
|
}
|
|
32227
32299
|
});
|
|
32228
32300
|
|
|
@@ -32531,6 +32603,8 @@ function buildRetryPrompt(missingToolNames) {
|
|
|
32531
32603
|
return `You did not emit the required workspace tools: ${names}. Call ${names} NOW with concrete arguments. No prose. No search.`;
|
|
32532
32604
|
}
|
|
32533
32605
|
async function* runRetryTurnForMember(args) {
|
|
32606
|
+
if (isCouncilCancelled(args.signal))
|
|
32607
|
+
return [];
|
|
32534
32608
|
const executableMissing = args.executableTools ? args.missingToolNames.filter((n) => args.executableTools.has(n)) : args.missingToolNames;
|
|
32535
32609
|
if (executableMissing.length === 0) {
|
|
32536
32610
|
return [];
|
|
@@ -32566,7 +32640,7 @@ async function* runRetryTurnForMember(args) {
|
|
|
32566
32640
|
providerStream: (params) => args.providerStream(params)
|
|
32567
32641
|
});
|
|
32568
32642
|
const retryEmitted = [];
|
|
32569
|
-
for await (const event of retryHarness.
|
|
32643
|
+
for await (const event of runHarnessWithAbort(retryHarness, args.signal)) {
|
|
32570
32644
|
if (event.type === "tool_execution_start") {
|
|
32571
32645
|
retryEmitted.push(event.toolName);
|
|
32572
32646
|
}
|
|
@@ -32575,6 +32649,8 @@ async function* runRetryTurnForMember(args) {
|
|
|
32575
32649
|
return retryEmitted;
|
|
32576
32650
|
}
|
|
32577
32651
|
async function* applyRetryIfMissing(args) {
|
|
32652
|
+
if (isCouncilCancelled(args.config.signal))
|
|
32653
|
+
return;
|
|
32578
32654
|
if (args.check.ok)
|
|
32579
32655
|
return;
|
|
32580
32656
|
const missingToolNames = args.check.missing.map((m) => m.split(" ")[0]);
|
|
@@ -32607,7 +32683,8 @@ async function* applyRetryIfMissing(args) {
|
|
|
32607
32683
|
toolRegistry: args.config.tools,
|
|
32608
32684
|
providerStream: args.config.providerStream,
|
|
32609
32685
|
runMode: args.config.runMode,
|
|
32610
|
-
languageModule: args.languageModule
|
|
32686
|
+
languageModule: args.languageModule,
|
|
32687
|
+
signal: args.config.signal
|
|
32611
32688
|
});
|
|
32612
32689
|
for await (const event of retryGenerator) {
|
|
32613
32690
|
if (event.type === "tool_execution_start") {
|
|
@@ -32626,6 +32703,7 @@ var init_retryTurn = __esm({
|
|
|
32626
32703
|
"packages/core/dist/agents/council/retryTurn.js"() {
|
|
32627
32704
|
"use strict";
|
|
32628
32705
|
init_AgentHarness();
|
|
32706
|
+
init_cancel();
|
|
32629
32707
|
init_toolSchemas();
|
|
32630
32708
|
init_memberMessages();
|
|
32631
32709
|
init_toolEmission();
|
|
@@ -32635,6 +32713,8 @@ var init_retryTurn = __esm({
|
|
|
32635
32713
|
|
|
32636
32714
|
// packages/core/dist/agents/council/chairmanDelivery.js
|
|
32637
32715
|
async function* applyCompletionRetry(args) {
|
|
32716
|
+
if (isCouncilCancelled(args.config.signal))
|
|
32717
|
+
return;
|
|
32638
32718
|
const check2 = checkImplementationCompletion(args.emittedToolNames);
|
|
32639
32719
|
if (check2.ok)
|
|
32640
32720
|
return;
|
|
@@ -32664,7 +32744,8 @@ async function* applyCompletionRetry(args) {
|
|
|
32664
32744
|
providerStream: args.config.providerStream,
|
|
32665
32745
|
runMode: args.config.runMode,
|
|
32666
32746
|
retryPrompt: buildImplementationVerifyRetryPrompt(retryTool),
|
|
32667
|
-
languageModule: args.languageModule
|
|
32747
|
+
languageModule: args.languageModule,
|
|
32748
|
+
signal: args.config.signal
|
|
32668
32749
|
});
|
|
32669
32750
|
for await (const event of retryGenerator) {
|
|
32670
32751
|
if (event.type === "tool_execution_start") {
|
|
@@ -32697,6 +32778,8 @@ ${blocks}
|
|
|
32697
32778
|
Rules: animate ONLY transform and opacity. Replace any box-shadow / background / background-position / filter / color / border-color / width / height / grid-template-rows used in @keyframes or transitions with transform/opacity equivalents (e.g. render a glow via a pseudo-element that scales and fades). For every classList.add('x') in the script, add a matching '.x' CSS rule. Use read_file to see the exact lines, then edit_file. When the listed items are fixed, stop \u2014 no summary.`;
|
|
32698
32779
|
}
|
|
32699
32780
|
async function* applyImplementationWriteRetry(args) {
|
|
32781
|
+
if (isCouncilCancelled(args.config.signal))
|
|
32782
|
+
return;
|
|
32700
32783
|
if (args.check.ok)
|
|
32701
32784
|
return;
|
|
32702
32785
|
if (!shouldRetryMember(["write_file"], 0))
|
|
@@ -32723,7 +32806,8 @@ async function* applyImplementationWriteRetry(args) {
|
|
|
32723
32806
|
providerStream: args.config.providerStream,
|
|
32724
32807
|
runMode: "implementation",
|
|
32725
32808
|
retryPrompt: buildImplementationWriteRetryPrompt(args.userMessage),
|
|
32726
|
-
languageModule: args.languageModule
|
|
32809
|
+
languageModule: args.languageModule,
|
|
32810
|
+
signal: args.config.signal
|
|
32727
32811
|
});
|
|
32728
32812
|
for await (const event of retryGenerator) {
|
|
32729
32813
|
if (event.type === "tool_execution_start")
|
|
@@ -32751,6 +32835,8 @@ async function* runChairmanDeliveryLoop(args) {
|
|
|
32751
32835
|
const zelariRoot = `${args.projectRoot}/.zelari`;
|
|
32752
32836
|
let attempt = 0;
|
|
32753
32837
|
while (attempt < maxAttempts) {
|
|
32838
|
+
if (isCouncilCancelled(args.config.signal))
|
|
32839
|
+
return false;
|
|
32754
32840
|
const report = runImplementationVerification({
|
|
32755
32841
|
projectRoot: args.projectRoot,
|
|
32756
32842
|
zelariRoot
|
|
@@ -32793,7 +32879,8 @@ async function* runChairmanDeliveryLoop(args) {
|
|
|
32793
32879
|
providerStream: args.config.providerStream,
|
|
32794
32880
|
runMode: "implementation",
|
|
32795
32881
|
retryPrompt: buildDeliveryFixPrompt(blocking, args.userMessage),
|
|
32796
|
-
languageModule: args.languageModule
|
|
32882
|
+
languageModule: args.languageModule,
|
|
32883
|
+
signal: args.config.signal
|
|
32797
32884
|
});
|
|
32798
32885
|
for await (const event of fixGenerator) {
|
|
32799
32886
|
if (event.type === "tool_execution_start")
|
|
@@ -32826,6 +32913,7 @@ var init_chairmanDelivery = __esm({
|
|
|
32826
32913
|
init_runChecks();
|
|
32827
32914
|
init_inlineJsAutofix();
|
|
32828
32915
|
init_retryTurn();
|
|
32916
|
+
init_cancel();
|
|
32829
32917
|
MAX_DELIVERY_ATTEMPTS = 2;
|
|
32830
32918
|
}
|
|
32831
32919
|
});
|
|
@@ -32887,6 +32975,8 @@ async function* runChairmanFixLoop(args) {
|
|
|
32887
32975
|
let current = Array.from(args.violations.values());
|
|
32888
32976
|
let attempt = 0;
|
|
32889
32977
|
while (current.length > 0 && attempt < maxAttempts) {
|
|
32978
|
+
if (isCouncilCancelled(args.config.signal))
|
|
32979
|
+
return;
|
|
32890
32980
|
attempt++;
|
|
32891
32981
|
try {
|
|
32892
32982
|
const fixGenerator = runRetryTurnForMember({
|
|
@@ -32907,7 +32997,8 @@ async function* runChairmanFixLoop(args) {
|
|
|
32907
32997
|
providerStream: args.config.providerStream,
|
|
32908
32998
|
runMode: "implementation",
|
|
32909
32999
|
retryPrompt: buildMotionFixPrompt(current),
|
|
32910
|
-
languageModule: args.languageModule
|
|
33000
|
+
languageModule: args.languageModule,
|
|
33001
|
+
signal: args.config.signal
|
|
32911
33002
|
});
|
|
32912
33003
|
for await (const event of fixGenerator) {
|
|
32913
33004
|
if (event.type === "tool_execution_start")
|
|
@@ -32935,6 +33026,7 @@ var init_chairmanFixLoop = __esm({
|
|
|
32935
33026
|
init_microGate();
|
|
32936
33027
|
init_chairmanDelivery();
|
|
32937
33028
|
init_retryTurn();
|
|
33029
|
+
init_cancel();
|
|
32938
33030
|
}
|
|
32939
33031
|
});
|
|
32940
33032
|
|
|
@@ -32976,6 +33068,17 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
32976
33068
|
model: config2.model,
|
|
32977
33069
|
provider: config2.provider ?? "minimax"
|
|
32978
33070
|
};
|
|
33071
|
+
if (isCouncilCancelled(config2.signal)) {
|
|
33072
|
+
yield {
|
|
33073
|
+
type: "agent_end",
|
|
33074
|
+
id: crypto.randomUUID(),
|
|
33075
|
+
ts: Date.now(),
|
|
33076
|
+
sessionId: sessionId2,
|
|
33077
|
+
reason: "cancelled",
|
|
33078
|
+
durationMs: 0
|
|
33079
|
+
};
|
|
33080
|
+
return;
|
|
33081
|
+
}
|
|
32979
33082
|
const emitMemberCost = (input) => {
|
|
32980
33083
|
const usage = input.usage;
|
|
32981
33084
|
const prompt = usage?.promptTokens ?? 0;
|
|
@@ -33005,6 +33108,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
33005
33108
|
const oracle = agents.find((a) => a.id === "minos") ?? (config2.skipSpecialists ? getAgent("minos") : void 0);
|
|
33006
33109
|
const chairman = agents.find((a) => a.id === "lucifer") ?? (config2.skipSpecialists ? getAgent("lucifer") : void 0);
|
|
33007
33110
|
for (const agent of specialists) {
|
|
33111
|
+
if (isCouncilCancelled(config2.signal))
|
|
33112
|
+
break;
|
|
33008
33113
|
if (completedIds.has(agent.id))
|
|
33009
33114
|
continue;
|
|
33010
33115
|
callbacks.onAgentStart?.(agent);
|
|
@@ -33050,7 +33155,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
33050
33155
|
const emittedToolNames = [];
|
|
33051
33156
|
const memberStart = Date.now();
|
|
33052
33157
|
try {
|
|
33053
|
-
for await (const event of harness.
|
|
33158
|
+
for await (const event of runHarnessWithAbort(harness, config2.signal)) {
|
|
33054
33159
|
yield event;
|
|
33055
33160
|
if (event.type === "tool_execution_start") {
|
|
33056
33161
|
toolCalls += 1;
|
|
@@ -33072,7 +33177,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
33072
33177
|
fullText = `Error: ${err instanceof Error ? err.message : "Unknown"}`;
|
|
33073
33178
|
errored = true;
|
|
33074
33179
|
}
|
|
33075
|
-
if (isDesignPhase && !errored && !NON_RETRY_AGENTS.has(agent.id)) {
|
|
33180
|
+
if (isDesignPhase && !errored && !NON_RETRY_AGENTS.has(agent.id) && !isCouncilCancelled(config2.signal)) {
|
|
33076
33181
|
const specialistCheck = enforceDesignPhaseToolEmissions(agent.id, emittedToolNames);
|
|
33077
33182
|
yield* applyRetryIfMissing({
|
|
33078
33183
|
agent,
|
|
@@ -33155,7 +33260,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
33155
33260
|
}
|
|
33156
33261
|
}
|
|
33157
33262
|
}
|
|
33158
|
-
if (oracle && !completedIds.has(oracle.id)) {
|
|
33263
|
+
if (oracle && !completedIds.has(oracle.id) && !isCouncilCancelled(config2.signal)) {
|
|
33159
33264
|
callbacks.onAgentStart?.(oracle);
|
|
33160
33265
|
const override = config2.agentModels?.[oracle.id];
|
|
33161
33266
|
const effectiveProvider = override?.providerId ?? config2.provider ?? "minimax";
|
|
@@ -33204,7 +33309,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
33204
33309
|
const emittedToolNames = [];
|
|
33205
33310
|
const memberStart = Date.now();
|
|
33206
33311
|
try {
|
|
33207
|
-
for await (const event of harness.
|
|
33312
|
+
for await (const event of runHarnessWithAbort(harness, config2.signal)) {
|
|
33208
33313
|
yield event;
|
|
33209
33314
|
if (event.type === "tool_execution_start") {
|
|
33210
33315
|
toolCalls += 1;
|
|
@@ -33226,7 +33331,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
33226
33331
|
fullText = `Review error: ${err instanceof Error ? err.message : "Unknown"}`;
|
|
33227
33332
|
errored = true;
|
|
33228
33333
|
}
|
|
33229
|
-
if (isDesignPhase && !errored) {
|
|
33334
|
+
if (isDesignPhase && !errored && !isCouncilCancelled(config2.signal)) {
|
|
33230
33335
|
const oracleCheck = enforceDesignPhaseToolEmissions(oracle.id, emittedToolNames);
|
|
33231
33336
|
yield* applyRetryIfMissing({
|
|
33232
33337
|
agent: oracle,
|
|
@@ -33286,7 +33391,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
33286
33391
|
});
|
|
33287
33392
|
agentOutputs.push({ name: oracle.name, role: oracle.role, content: cleaned });
|
|
33288
33393
|
}
|
|
33289
|
-
if (chairman && !completedIds.has(chairman.id)) {
|
|
33394
|
+
if (chairman && !completedIds.has(chairman.id) && !isCouncilCancelled(config2.signal)) {
|
|
33290
33395
|
callbacks.onSynthesisStart?.();
|
|
33291
33396
|
callbacks.onAgentStart?.(chairman);
|
|
33292
33397
|
const override = config2.agentModels?.[chairman.id];
|
|
@@ -33333,7 +33438,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
33333
33438
|
let chairmanProjectRoot = parseProjectRootFromWorkspaceContext(config2.workspaceContext ?? "");
|
|
33334
33439
|
const memberStart = Date.now();
|
|
33335
33440
|
try {
|
|
33336
|
-
for await (const event of chairmanHarness.
|
|
33441
|
+
for await (const event of runHarnessWithAbort(chairmanHarness, config2.signal)) {
|
|
33337
33442
|
yield event;
|
|
33338
33443
|
if (event.type === "tool_execution_start") {
|
|
33339
33444
|
toolCalls += 1;
|
|
@@ -33397,7 +33502,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
33397
33502
|
errored = true;
|
|
33398
33503
|
lastErrorMessage = err instanceof Error ? err.message : String(err);
|
|
33399
33504
|
}
|
|
33400
|
-
if (isDesignPhase && !errored) {
|
|
33505
|
+
if (isDesignPhase && !errored && !isCouncilCancelled(config2.signal)) {
|
|
33401
33506
|
const chairmanCheck = enforceDesignPhaseToolEmissions(chairman.id, emittedToolNames);
|
|
33402
33507
|
yield* applyRetryIfMissing({
|
|
33403
33508
|
agent: chairman,
|
|
@@ -33418,7 +33523,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
33418
33523
|
});
|
|
33419
33524
|
} else if (isDesignPhase) {
|
|
33420
33525
|
enforceDesignPhaseToolEmissions(chairman.id, emittedToolNames);
|
|
33421
|
-
} else if (!errored) {
|
|
33526
|
+
} else if (!errored && !isCouncilCancelled(config2.signal)) {
|
|
33422
33527
|
if (chairmanProjectRoot) {
|
|
33423
33528
|
const zelariRoot = `${chairmanProjectRoot}/.zelari`;
|
|
33424
33529
|
const spec = loadNfrSpec(zelariRoot) ?? DEFAULT_NFR_SPEC;
|
|
@@ -33547,7 +33652,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
33547
33652
|
id: crypto.randomUUID(),
|
|
33548
33653
|
ts: Date.now(),
|
|
33549
33654
|
sessionId: sessionId2,
|
|
33550
|
-
reason: "completed",
|
|
33655
|
+
reason: isCouncilCancelled(config2.signal) ? "cancelled" : "completed",
|
|
33551
33656
|
durationMs: 0
|
|
33552
33657
|
};
|
|
33553
33658
|
}
|
|
@@ -33566,6 +33671,7 @@ var init_councilApi = __esm({
|
|
|
33566
33671
|
init_runChecks();
|
|
33567
33672
|
init_implementationDelivery();
|
|
33568
33673
|
init_types7();
|
|
33674
|
+
init_cancel();
|
|
33569
33675
|
init_types7();
|
|
33570
33676
|
init_outputCleaning();
|
|
33571
33677
|
init_outputCleaning();
|
|
@@ -33947,9 +34053,9 @@ var init_types9 = __esm({
|
|
|
33947
34053
|
import { readFileSync as readFileSync14 } from "node:fs";
|
|
33948
34054
|
import { join as join11 } from "node:path";
|
|
33949
34055
|
function readLessonsDeduped(zelariRoot) {
|
|
33950
|
-
const
|
|
34056
|
+
const path100 = join11(zelariRoot, LESSONS_FILE);
|
|
33951
34057
|
try {
|
|
33952
|
-
const raw = readFileSync14(
|
|
34058
|
+
const raw = readFileSync14(path100, "utf8");
|
|
33953
34059
|
const byId = /* @__PURE__ */ new Map();
|
|
33954
34060
|
for (const line of raw.split(/\r?\n/)) {
|
|
33955
34061
|
if (!line.trim())
|
|
@@ -34050,8 +34156,8 @@ function keywordsFrom(check2, signature) {
|
|
|
34050
34156
|
return [.../* @__PURE__ */ new Set([...fromId, ...words])].slice(0, 12);
|
|
34051
34157
|
}
|
|
34052
34158
|
function writeLesson(zelariRoot, lesson) {
|
|
34053
|
-
const
|
|
34054
|
-
appendFileSync(
|
|
34159
|
+
const path100 = join12(zelariRoot, LESSONS_FILE);
|
|
34160
|
+
appendFileSync(path100, `${JSON.stringify(lesson)}
|
|
34055
34161
|
`, "utf8");
|
|
34056
34162
|
}
|
|
34057
34163
|
function findSimilar(lessons, signature) {
|
|
@@ -34572,6 +34678,7 @@ __export(council_exports, {
|
|
|
34572
34678
|
shouldRetryMember: () => shouldRetryMember,
|
|
34573
34679
|
slugify: () => slugify2,
|
|
34574
34680
|
stripClarificationProtocol: () => stripClarificationProtocol,
|
|
34681
|
+
stripQuestionBlocks: () => stripQuestionBlocks,
|
|
34575
34682
|
swapMembers: () => swapMembers,
|
|
34576
34683
|
systemMessagesFromSplit: () => systemMessagesFromSplit,
|
|
34577
34684
|
taskMatchesNfrKeywords: () => taskMatchesNfrKeywords,
|
|
@@ -36017,9 +36124,9 @@ function findCycle(nodes) {
|
|
|
36017
36124
|
if (color.get(start) !== WHITE)
|
|
36018
36125
|
continue;
|
|
36019
36126
|
const stack = [[start, 0]];
|
|
36020
|
-
const
|
|
36127
|
+
const path100 = [];
|
|
36021
36128
|
color.set(start, GRAY);
|
|
36022
|
-
|
|
36129
|
+
path100.push(start);
|
|
36023
36130
|
while (stack.length > 0) {
|
|
36024
36131
|
const top = stack[stack.length - 1];
|
|
36025
36132
|
const [id3, idx] = top;
|
|
@@ -36032,17 +36139,17 @@ function findCycle(nodes) {
|
|
|
36032
36139
|
continue;
|
|
36033
36140
|
const c = color.get(dep);
|
|
36034
36141
|
if (c === GRAY) {
|
|
36035
|
-
const at =
|
|
36036
|
-
return [...
|
|
36142
|
+
const at = path100.indexOf(dep);
|
|
36143
|
+
return [...path100.slice(at), dep];
|
|
36037
36144
|
}
|
|
36038
36145
|
if (c === WHITE) {
|
|
36039
36146
|
color.set(dep, GRAY);
|
|
36040
|
-
|
|
36147
|
+
path100.push(dep);
|
|
36041
36148
|
stack.push([dep, 0]);
|
|
36042
36149
|
}
|
|
36043
36150
|
} else {
|
|
36044
36151
|
color.set(id3, BLACK);
|
|
36045
|
-
|
|
36152
|
+
path100.pop();
|
|
36046
36153
|
stack.pop();
|
|
36047
36154
|
}
|
|
36048
36155
|
}
|
|
@@ -36962,8 +37069,8 @@ var init_runner = __esm({
|
|
|
36962
37069
|
failed: [...this.tentaclesById.values()].filter((r) => r.status === "error"),
|
|
36963
37070
|
pending: []
|
|
36964
37071
|
};
|
|
36965
|
-
const
|
|
36966
|
-
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${
|
|
37072
|
+
const path100 = await this.host.saveSnapshot(snapshot, ".zelari/kraken/snapshots");
|
|
37073
|
+
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${path100}`);
|
|
36967
37074
|
return snapshot;
|
|
36968
37075
|
}
|
|
36969
37076
|
callLog(msg, data) {
|
|
@@ -38114,7 +38221,7 @@ var CORE_VERSION;
|
|
|
38114
38221
|
var init_version = __esm({
|
|
38115
38222
|
"packages/core/dist/version.js"() {
|
|
38116
38223
|
"use strict";
|
|
38117
|
-
CORE_VERSION = "2.
|
|
38224
|
+
CORE_VERSION = "2.35.0";
|
|
38118
38225
|
}
|
|
38119
38226
|
});
|
|
38120
38227
|
|
|
@@ -38626,6 +38733,7 @@ __export(dist_exports, {
|
|
|
38626
38733
|
strictBuildGate: () => strictBuildGate,
|
|
38627
38734
|
stripAnsi: () => stripAnsi,
|
|
38628
38735
|
stripClarificationProtocol: () => stripClarificationProtocol,
|
|
38736
|
+
stripQuestionBlocks: () => stripQuestionBlocks,
|
|
38629
38737
|
swapMembers: () => swapMembers,
|
|
38630
38738
|
systemMessagesFromSplit: () => systemMessagesFromSplit,
|
|
38631
38739
|
taskMatchesNfrKeywords: () => taskMatchesNfrKeywords,
|
|
@@ -40571,9 +40679,9 @@ function spillToolOutput(fullText, meta3) {
|
|
|
40571
40679
|
const rnd = randomBytes3(3).toString("hex");
|
|
40572
40680
|
const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
|
|
40573
40681
|
const file2 = `${stamp}-${safeTool}-${hash3}-${rnd}.txt`;
|
|
40574
|
-
const
|
|
40575
|
-
writeFileSync12(
|
|
40576
|
-
return
|
|
40682
|
+
const path100 = join14(dir, file2);
|
|
40683
|
+
writeFileSync12(path100, fullText, "utf8");
|
|
40684
|
+
return path100;
|
|
40577
40685
|
} catch {
|
|
40578
40686
|
return null;
|
|
40579
40687
|
}
|
|
@@ -40619,10 +40727,10 @@ function truncateToolResult(text, capOrOpts = TOOL_RESULT_LINE_CAP) {
|
|
|
40619
40727
|
${tail2}`;
|
|
40620
40728
|
}
|
|
40621
40729
|
if (doSpill) {
|
|
40622
|
-
const
|
|
40623
|
-
if (
|
|
40730
|
+
const path100 = spillToolOutput(text, { toolName: opts.toolName });
|
|
40731
|
+
if (path100) {
|
|
40624
40732
|
const spillNote = `
|
|
40625
|
-
\u2026 [full output spilled to: ${
|
|
40733
|
+
\u2026 [full output spilled to: ${path100} \u2014 re-read with read_file if you need the complete text] \u2026`;
|
|
40626
40734
|
if (preview.includes("] \u2026\n")) {
|
|
40627
40735
|
preview = preview.replace("] \u2026\n", `] \u2026${spillNote}
|
|
40628
40736
|
`);
|
|
@@ -41393,28 +41501,28 @@ var init_storage = __esm({
|
|
|
41393
41501
|
VALID_SCALARS = /^(true|false|null|~)$/i;
|
|
41394
41502
|
Storage = class {
|
|
41395
41503
|
/** Read a Markdown file with frontmatter. Throws if not found. */
|
|
41396
|
-
read(
|
|
41397
|
-
if (!existsSync19(
|
|
41398
|
-
throw new Error(`File not found: ${
|
|
41504
|
+
read(path100) {
|
|
41505
|
+
if (!existsSync19(path100)) {
|
|
41506
|
+
throw new Error(`File not found: ${path100}`);
|
|
41399
41507
|
}
|
|
41400
|
-
const md = readFileSync17(
|
|
41508
|
+
const md = readFileSync17(path100, "utf8");
|
|
41401
41509
|
return parseFrontmatter(md);
|
|
41402
41510
|
}
|
|
41403
41511
|
/** Read a Markdown file; returns null if not found. */
|
|
41404
|
-
readIfExists(
|
|
41405
|
-
if (!existsSync19(
|
|
41406
|
-
return this.read(
|
|
41512
|
+
readIfExists(path100) {
|
|
41513
|
+
if (!existsSync19(path100)) return null;
|
|
41514
|
+
return this.read(path100);
|
|
41407
41515
|
}
|
|
41408
41516
|
/**
|
|
41409
41517
|
* Write a Markdown file atomically (tmp + rename). Creates parent dirs.
|
|
41410
41518
|
* The meta object is serialized as YAML frontmatter; body as Markdown.
|
|
41411
41519
|
*/
|
|
41412
|
-
write(
|
|
41413
|
-
mkdirSync10(dirname2(
|
|
41414
|
-
const tmp =
|
|
41520
|
+
write(path100, meta3, body) {
|
|
41521
|
+
mkdirSync10(dirname2(path100), { recursive: true });
|
|
41522
|
+
const tmp = path100 + ".tmp-" + process.pid;
|
|
41415
41523
|
const md = serializeFrontmatter(meta3, body);
|
|
41416
41524
|
writeFileSync14(tmp, md, "utf8");
|
|
41417
|
-
renameSync2(tmp,
|
|
41525
|
+
renameSync2(tmp, path100);
|
|
41418
41526
|
}
|
|
41419
41527
|
/** List all .md files in a directory (non-recursive). */
|
|
41420
41528
|
listMarkdown(dir) {
|
|
@@ -41489,8 +41597,8 @@ function nextPlanTaskId(store6) {
|
|
|
41489
41597
|
return `t${store6.counter}`;
|
|
41490
41598
|
}
|
|
41491
41599
|
function writePlanTaskArtifact(rootDir, task) {
|
|
41492
|
-
const
|
|
41493
|
-
mkdirSync11(dirname3(
|
|
41600
|
+
const path100 = join17(rootDir, "plan-tasks", `${task.id}.md`);
|
|
41601
|
+
mkdirSync11(dirname3(path100), { recursive: true });
|
|
41494
41602
|
const meta3 = {
|
|
41495
41603
|
kind: "task",
|
|
41496
41604
|
id: task.id,
|
|
@@ -41511,7 +41619,7 @@ function writePlanTaskArtifact(rootDir, task) {
|
|
|
41511
41619
|
task.notes?.trim() ? task.notes.trim() : "_(no notes)_",
|
|
41512
41620
|
""
|
|
41513
41621
|
].filter((l) => l !== null).join("\n");
|
|
41514
|
-
new Storage().write(
|
|
41622
|
+
new Storage().write(path100, meta3, body);
|
|
41515
41623
|
}
|
|
41516
41624
|
function loadHandle(rootDir) {
|
|
41517
41625
|
const jsonPath = join17(rootDir, "plan.json");
|
|
@@ -44116,6 +44224,7 @@ __export(krakenModel_exports, {
|
|
|
44116
44224
|
inferModelFamily: () => inferModelFamily,
|
|
44117
44225
|
isCheapModelId: () => isCheapModelId,
|
|
44118
44226
|
isKrakenAutoModelEnabled: () => isKrakenAutoModelEnabled,
|
|
44227
|
+
isUnknownModelError: () => isUnknownModelError,
|
|
44119
44228
|
parseQualifiedModelRef: () => parseQualifiedModelRef,
|
|
44120
44229
|
pickCheapModel: () => pickCheapModel,
|
|
44121
44230
|
pickDifferentFamily: () => pickDifferentFamily,
|
|
@@ -44227,6 +44336,12 @@ function resolveKrakenSubModel(agent, parentModel, env = process.env, opts = {})
|
|
|
44227
44336
|
}
|
|
44228
44337
|
return parentModel;
|
|
44229
44338
|
}
|
|
44339
|
+
function isUnknownModelError(message) {
|
|
44340
|
+
if (!message) return false;
|
|
44341
|
+
const m = message.toLowerCase();
|
|
44342
|
+
if (!/model/.test(m)) return false;
|
|
44343
|
+
return /http\s*404/.test(m) || /not-found/.test(m) || /not_found/.test(m) || /does not exist/.test(m) || /unknown model/.test(m) || /model_not_found/.test(m);
|
|
44344
|
+
}
|
|
44230
44345
|
function resolveKrakenPlannerModel(parentModel, env = process.env) {
|
|
44231
44346
|
const specific = env.ZELARI_KRAKEN_PLANNER_MODEL?.trim();
|
|
44232
44347
|
if (specific) return specific;
|
|
@@ -46026,6 +46141,12 @@ ${failed.error ?? "unknown error"}`,
|
|
|
46026
46141
|
// src/cli/tools/taskTool.ts
|
|
46027
46142
|
import { existsSync as existsSync26 } from "node:fs";
|
|
46028
46143
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
46144
|
+
function permissionsForTaskAgent(agent) {
|
|
46145
|
+
const kind2 = agent ?? "explore";
|
|
46146
|
+
if (kind2 === "general") return ["read", "write", "execute", "network"];
|
|
46147
|
+
if (kind2 === "verify") return ["read", "execute", "network"];
|
|
46148
|
+
return ["read"];
|
|
46149
|
+
}
|
|
46029
46150
|
function resetTaskSpawnCount() {
|
|
46030
46151
|
const g = globalThis;
|
|
46031
46152
|
g.__zelariTaskSpawnCount = 0;
|
|
@@ -46507,17 +46628,45 @@ ${taskUserContent}`,
|
|
|
46507
46628
|
};
|
|
46508
46629
|
}
|
|
46509
46630
|
const startedTools = /* @__PURE__ */ new Map();
|
|
46510
|
-
const
|
|
46631
|
+
const onHarnessEvent = (ev) => {
|
|
46632
|
+
if (ev.type === "tool_execution_start") {
|
|
46633
|
+
startedTools.set(ev.toolCallId, ev.toolName);
|
|
46634
|
+
emitActivity({ type: "agent_tool", agentId: liveId, toolCallId: ev.toolCallId, tool: ev.toolName, status: "started", ...ev.args ? { summary: toolCommandHint(ev.args) } : {}, ts: Date.now() });
|
|
46635
|
+
} else if (ev.type === "tool_execution_end") {
|
|
46636
|
+
emitActivity({ type: "agent_tool", agentId: liveId, toolCallId: ev.toolCallId, tool: startedTools.get(ev.toolCallId) ?? "unknown", status: ev.isError ? "failed" : "completed", durationMs: ev.durationMs, ts: Date.now() });
|
|
46637
|
+
}
|
|
46638
|
+
};
|
|
46639
|
+
let { result, error: error51, aborted: aborted2, usage, toolTrace } = await runSubAgent(harness, {
|
|
46511
46640
|
...opts.signal ? { signal: opts.signal } : {},
|
|
46512
|
-
onEvent:
|
|
46513
|
-
|
|
46514
|
-
|
|
46515
|
-
|
|
46516
|
-
|
|
46517
|
-
|
|
46641
|
+
onEvent: onHarnessEvent
|
|
46642
|
+
});
|
|
46643
|
+
if (!aborted2 && !result && sub.fallback && sub.fallback.model !== sub.model) {
|
|
46644
|
+
const { isUnknownModelError: isUnknownModelError2 } = await Promise.resolve().then(() => (init_krakenModel(), krakenModel_exports));
|
|
46645
|
+
if (isUnknownModelError2(error51)) {
|
|
46646
|
+
emitPhase(`model ${sub.model} unavailable \u2014 retrying with ${sub.fallback.model}`);
|
|
46647
|
+
const retryConfig = {
|
|
46648
|
+
...config2,
|
|
46649
|
+
model: sub.fallback.model,
|
|
46650
|
+
provider: sub.fallback.provider,
|
|
46651
|
+
providerStream: sub.fallback.providerStream
|
|
46652
|
+
};
|
|
46653
|
+
try {
|
|
46654
|
+
harness = deps.harnessFactory ? deps.harnessFactory(retryConfig) : new (await Promise.resolve().then(() => (init_harness(), harness_exports))).AgentHarness(retryConfig);
|
|
46655
|
+
const retry = await runSubAgent(harness, {
|
|
46656
|
+
...opts.signal ? { signal: opts.signal } : {},
|
|
46657
|
+
onEvent: onHarnessEvent
|
|
46658
|
+
});
|
|
46659
|
+
result = retry.result;
|
|
46660
|
+
error51 = retry.error;
|
|
46661
|
+
aborted2 = retry.aborted;
|
|
46662
|
+
usage = retry.usage;
|
|
46663
|
+
toolTrace = retry.toolTrace;
|
|
46664
|
+
sub = { ...sub, model: sub.fallback.model, provider: sub.fallback.provider };
|
|
46665
|
+
} catch (err) {
|
|
46666
|
+
error51 = err instanceof Error ? err.message : String(err);
|
|
46518
46667
|
}
|
|
46519
46668
|
}
|
|
46520
|
-
}
|
|
46669
|
+
}
|
|
46521
46670
|
const durationMs = Date.now() - started;
|
|
46522
46671
|
if (aborted2) {
|
|
46523
46672
|
if (worktree && !shouldKeepWorktree()) await cleanupKrakenWorktree(worktree);
|
|
@@ -50672,12 +50821,9 @@ function backoffDelay(attempt, retryAfterHeader) {
|
|
|
50672
50821
|
}
|
|
50673
50822
|
return Math.min(BACKOFF_BASE_MS * 2 ** attempt, BACKOFF_CAP_MS);
|
|
50674
50823
|
}
|
|
50675
|
-
function modelSupportsVision(
|
|
50824
|
+
function modelSupportsVision(_model) {
|
|
50676
50825
|
const force = process.env.ZELARI_VISION;
|
|
50677
|
-
|
|
50678
|
-
if (force === "0" || force === "false" || force === "off") return false;
|
|
50679
|
-
const m = model.toLowerCase();
|
|
50680
|
-
return VISION_MODEL_HINTS.some((hint) => m.includes(hint));
|
|
50826
|
+
return !(force === "0" || force === "false" || force === "off");
|
|
50681
50827
|
}
|
|
50682
50828
|
function dataUriFromImage(img) {
|
|
50683
50829
|
return `data:${img.mime};base64,${img.dataBase64}`;
|
|
@@ -50772,6 +50918,22 @@ ${notes}
|
|
|
50772
50918
|
}
|
|
50773
50919
|
return { role: m.role, content: m.content };
|
|
50774
50920
|
}
|
|
50921
|
+
function imagesFollowUpMessage(images) {
|
|
50922
|
+
const labels = images.map((img) => img.alt ?? img.mime).join(", ");
|
|
50923
|
+
return {
|
|
50924
|
+
role: "user",
|
|
50925
|
+
content: [
|
|
50926
|
+
{
|
|
50927
|
+
type: "text",
|
|
50928
|
+
text: `[Immagine(i) dal tool: ${labels} \u2014 usa questi pixel per l'analisi visiva.]`
|
|
50929
|
+
},
|
|
50930
|
+
...images.map((img) => ({
|
|
50931
|
+
type: "image_url",
|
|
50932
|
+
image_url: { url: dataUriFromImage(img) }
|
|
50933
|
+
}))
|
|
50934
|
+
]
|
|
50935
|
+
};
|
|
50936
|
+
}
|
|
50775
50937
|
function positiveEnvInt(name) {
|
|
50776
50938
|
const raw = process.env[name];
|
|
50777
50939
|
if (!raw) return void 0;
|
|
@@ -50782,15 +50944,27 @@ function openaiCompatibleProvider(config2) {
|
|
|
50782
50944
|
return async function* (params) {
|
|
50783
50945
|
const capabilities = capabilitiesFor(params.model, config2.providerId);
|
|
50784
50946
|
const vision = modelSupportsVision(params.model);
|
|
50785
|
-
const
|
|
50947
|
+
const msgsIn = params.messages;
|
|
50948
|
+
let toolRunImages = [];
|
|
50949
|
+
const messages = msgsIn.flatMap((m, i) => {
|
|
50786
50950
|
const cacheable = !(m.role === "user" && m.images && m.images.length > 0);
|
|
50787
50951
|
if (cacheable) {
|
|
50788
50952
|
const cached2 = messageMappingCache.get(m);
|
|
50789
|
-
if (cached2) return cached2;
|
|
50953
|
+
if (cached2) return [cached2];
|
|
50790
50954
|
}
|
|
50791
50955
|
const mapped = mapAgentMessage(m, vision);
|
|
50792
50956
|
if (cacheable) messageMappingCache.set(m, mapped);
|
|
50793
|
-
|
|
50957
|
+
if (m.role === "tool") {
|
|
50958
|
+
if (m.images && m.images.length > 0) toolRunImages.push(...m.images);
|
|
50959
|
+
const next = msgsIn[i + 1];
|
|
50960
|
+
const runEnds = !next || next.role !== "tool";
|
|
50961
|
+
if (runEnds && vision && toolRunImages.length > 0) {
|
|
50962
|
+
const followUp = imagesFollowUpMessage(toolRunImages);
|
|
50963
|
+
toolRunImages = [];
|
|
50964
|
+
return [mapped, followUp];
|
|
50965
|
+
}
|
|
50966
|
+
}
|
|
50967
|
+
return [mapped];
|
|
50794
50968
|
});
|
|
50795
50969
|
const generation = params.generation;
|
|
50796
50970
|
const body = {
|
|
@@ -51114,7 +51288,7 @@ async function providerConfigFor(providerId) {
|
|
|
51114
51288
|
...extraFromStored(providerId)
|
|
51115
51289
|
};
|
|
51116
51290
|
}
|
|
51117
|
-
var RETRYABLE_STATUSES, MAX_RETRIES, BACKOFF_BASE_MS, BACKOFF_CAP_MS, PROVIDER_CONNECT_TIMEOUT_MS, PROVIDER_STREAM_IDLE_MS, PROVIDER_STREAM_MAX_MS,
|
|
51291
|
+
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;
|
|
51118
51292
|
var init_openai_compatible = __esm({
|
|
51119
51293
|
"src/cli/provider/openai-compatible.ts"() {
|
|
51120
51294
|
"use strict";
|
|
@@ -51145,33 +51319,6 @@ var init_openai_compatible = __esm({
|
|
|
51145
51319
|
const n = raw ? Number.parseInt(raw, 10) : 18e5;
|
|
51146
51320
|
return Number.isFinite(n) && n >= 6e4 ? n : 18e5;
|
|
51147
51321
|
})();
|
|
51148
|
-
VISION_MODEL_HINTS = [
|
|
51149
|
-
"grok-4",
|
|
51150
|
-
"grok-3",
|
|
51151
|
-
"grok-2-vision",
|
|
51152
|
-
"grok-vision",
|
|
51153
|
-
"glm-4v",
|
|
51154
|
-
"glm-4.5v",
|
|
51155
|
-
"glm-4.1v",
|
|
51156
|
-
"glm-5v",
|
|
51157
|
-
"qwen-vl",
|
|
51158
|
-
"qwen2-vl",
|
|
51159
|
-
"qwen2.5-vl",
|
|
51160
|
-
"qwen3-vl",
|
|
51161
|
-
"gpt-4o",
|
|
51162
|
-
"gpt-4.1",
|
|
51163
|
-
"gpt-4.5",
|
|
51164
|
-
"gpt-4-vision",
|
|
51165
|
-
"gpt-5",
|
|
51166
|
-
"claude-3",
|
|
51167
|
-
"claude-4",
|
|
51168
|
-
"gemini-",
|
|
51169
|
-
"gemini/",
|
|
51170
|
-
"minimax-m1",
|
|
51171
|
-
"minimax-m2",
|
|
51172
|
-
"minimax-m3",
|
|
51173
|
-
"deepseek-vl"
|
|
51174
|
-
];
|
|
51175
51322
|
PROVIDER_ENDPOINTS = {
|
|
51176
51323
|
"openai-compatible": "https://api.x.ai/v1",
|
|
51177
51324
|
"minimax": "https://api.minimax.io/v1",
|
|
@@ -51566,6 +51713,16 @@ var init_driver = __esm({
|
|
|
51566
51713
|
// src/cli/browser/tools.ts
|
|
51567
51714
|
import path56 from "node:path";
|
|
51568
51715
|
import os3 from "node:os";
|
|
51716
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
51717
|
+
async function loadImageBlock(filePath) {
|
|
51718
|
+
try {
|
|
51719
|
+
const buf = await readFile7(filePath);
|
|
51720
|
+
if (buf.byteLength > SCREENSHOT_MAX_BYTES) return void 0;
|
|
51721
|
+
return { mime: "image/png", dataBase64: buf.toString("base64"), alt: path56.basename(filePath) };
|
|
51722
|
+
} catch {
|
|
51723
|
+
return void 0;
|
|
51724
|
+
}
|
|
51725
|
+
}
|
|
51569
51726
|
function createBrowserTool(deps = {}) {
|
|
51570
51727
|
return {
|
|
51571
51728
|
name: "browser_check",
|
|
@@ -51618,17 +51775,23 @@ function createBrowserTool(deps = {}) {
|
|
|
51618
51775
|
note: "Weak smoke only: no selector/text/evaluate assertions. No console/page errors is necessary but not sufficient to claim a logic fix. Add waitForSelector, waitForText, or evaluate (DOM/read hooks) for stronger evidence.",
|
|
51619
51776
|
smokeStrength: "weak"
|
|
51620
51777
|
} : { smokeStrength: "asserted" }
|
|
51621
|
-
});
|
|
51778
|
+
}, void 0, await toolImages(result.screenshotPath));
|
|
51622
51779
|
}
|
|
51623
51780
|
};
|
|
51624
51781
|
}
|
|
51625
|
-
|
|
51782
|
+
async function toolImages(screenshotPath) {
|
|
51783
|
+
if (!screenshotPath) return void 0;
|
|
51784
|
+
const image = await loadImageBlock(screenshotPath);
|
|
51785
|
+
return image ? [image] : void 0;
|
|
51786
|
+
}
|
|
51787
|
+
var SCREENSHOT_MAX_BYTES, ActionSchema;
|
|
51626
51788
|
var init_tools5 = __esm({
|
|
51627
51789
|
"src/cli/browser/tools.ts"() {
|
|
51628
51790
|
"use strict";
|
|
51629
51791
|
init_zod();
|
|
51630
51792
|
init_toolTypes();
|
|
51631
51793
|
init_driver();
|
|
51794
|
+
SCREENSHOT_MAX_BYTES = 8 * 1024 * 1024;
|
|
51632
51795
|
ActionSchema = external_exports.discriminatedUnion("type", [
|
|
51633
51796
|
external_exports.object({ type: external_exports.literal("click"), selector: external_exports.string().min(1) }),
|
|
51634
51797
|
external_exports.object({ type: external_exports.literal("fill"), selector: external_exports.string().min(1), value: external_exports.string() }),
|
|
@@ -51653,6 +51816,92 @@ var init_tools5 = __esm({
|
|
|
51653
51816
|
}
|
|
51654
51817
|
});
|
|
51655
51818
|
|
|
51819
|
+
// src/cli/tools/screenshotTool.ts
|
|
51820
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
51821
|
+
import { mkdir as mkdir3, readFile as readFile8, stat as stat7 } from "node:fs/promises";
|
|
51822
|
+
import path57 from "node:path";
|
|
51823
|
+
import { promisify as promisify4 } from "node:util";
|
|
51824
|
+
async function captureWindows(target) {
|
|
51825
|
+
const script = `Add-Type -AssemblyName System.Windows.Forms,System.Drawing;$b=[System.Windows.Forms.SystemInformation]::VirtualScreen;$bmp=New-Object System.Drawing.Bitmap $b.Width,$b.Height;$g=[System.Drawing.Graphics]::FromImage($bmp);$g.CopyFromScreen($b.Left,$b.Top,0,0,$bmp.Size);$g.Dispose(); $bmp.Save('${target.replace(/'/g, "''")}'); $bmp.Dispose();`;
|
|
51826
|
+
await execFileAsync4("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], {
|
|
51827
|
+
timeout: 12e3,
|
|
51828
|
+
windowsHide: true
|
|
51829
|
+
});
|
|
51830
|
+
}
|
|
51831
|
+
async function captureUnixLike(target) {
|
|
51832
|
+
const attempts = process.platform === "darwin" ? [["screencapture", ["-x", target]]] : [
|
|
51833
|
+
["gnome-screenshot", ["-f", target]],
|
|
51834
|
+
["scrot", [target]],
|
|
51835
|
+
["import", ["-window", "root", target]]
|
|
51836
|
+
];
|
|
51837
|
+
let lastErr = null;
|
|
51838
|
+
for (const [bin, args] of attempts) {
|
|
51839
|
+
try {
|
|
51840
|
+
await execFileAsync4(bin, args, { timeout: 12e3 });
|
|
51841
|
+
return;
|
|
51842
|
+
} catch (e) {
|
|
51843
|
+
lastErr = e;
|
|
51844
|
+
}
|
|
51845
|
+
}
|
|
51846
|
+
throw lastErr ?? new Error("no screen-capture utility available");
|
|
51847
|
+
}
|
|
51848
|
+
function createScreenshotTool(deps = {}) {
|
|
51849
|
+
return {
|
|
51850
|
+
name: "screenshot",
|
|
51851
|
+
description: "Capture a screenshot of the user screen(s) as PNG. Use it when the user asks to see/check something on screen (running app, game, dialog, error window) or when you need to LOOK at the current UI state to debug it. The image is returned to you as pixels (vision) and saved to disk; give the path back to the user so they can open it.",
|
|
51852
|
+
permissions: ["ui"],
|
|
51853
|
+
timeoutMs: 2e4,
|
|
51854
|
+
inputSchema: external_exports.object({
|
|
51855
|
+
note: external_exports.string().max(200).optional().describe("Why you are capturing (shown to the user with the permission prompt).")
|
|
51856
|
+
}),
|
|
51857
|
+
execute: async (args, ctx) => {
|
|
51858
|
+
const a = args;
|
|
51859
|
+
const dir = deps.outDir ?? path57.join(ctx.cwd ?? process.cwd(), ".zelari", "screenshots");
|
|
51860
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
51861
|
+
const target = path57.join(dir, `screenshot-${stamp}.png`);
|
|
51862
|
+
const capture = deps.capture ?? (process.platform === "win32" ? captureWindows : captureUnixLike);
|
|
51863
|
+
try {
|
|
51864
|
+
await mkdir3(dir, { recursive: true });
|
|
51865
|
+
await capture(target);
|
|
51866
|
+
const meta3 = await stat7(target);
|
|
51867
|
+
if (meta3.size === 0) return typedErr(`capture produced an empty file: ${target}`);
|
|
51868
|
+
const buf = await readFile8(target);
|
|
51869
|
+
const image = {
|
|
51870
|
+
mime: "image/png",
|
|
51871
|
+
dataBase64: buf.toString("base64"),
|
|
51872
|
+
alt: path57.basename(target)
|
|
51873
|
+
};
|
|
51874
|
+
const attachable = meta3.size <= SCREENSHOT_MAX_BYTES2;
|
|
51875
|
+
return typedOk(
|
|
51876
|
+
{
|
|
51877
|
+
ok: true,
|
|
51878
|
+
path: target,
|
|
51879
|
+
bytes: meta3.size,
|
|
51880
|
+
...a.note ? { note: a.note } : {},
|
|
51881
|
+
...attachable ? {} : { warning: "PNG over 8MB: pixels not attached to the model context; open the path instead." }
|
|
51882
|
+
},
|
|
51883
|
+
void 0,
|
|
51884
|
+
attachable ? [image] : void 0
|
|
51885
|
+
);
|
|
51886
|
+
} catch (e) {
|
|
51887
|
+
return typedErr(
|
|
51888
|
+
`screen capture failed on ${process.platform}: ${e instanceof Error ? e.message : String(e)}`
|
|
51889
|
+
);
|
|
51890
|
+
}
|
|
51891
|
+
}
|
|
51892
|
+
};
|
|
51893
|
+
}
|
|
51894
|
+
var execFileAsync4, SCREENSHOT_MAX_BYTES2;
|
|
51895
|
+
var init_screenshotTool = __esm({
|
|
51896
|
+
"src/cli/tools/screenshotTool.ts"() {
|
|
51897
|
+
"use strict";
|
|
51898
|
+
init_zod();
|
|
51899
|
+
init_toolTypes();
|
|
51900
|
+
execFileAsync4 = promisify4(execFile5);
|
|
51901
|
+
SCREENSHOT_MAX_BYTES2 = 8 * 1024 * 1024;
|
|
51902
|
+
}
|
|
51903
|
+
});
|
|
51904
|
+
|
|
51656
51905
|
// src/cli/ssh/targets.ts
|
|
51657
51906
|
var targets_exports = {};
|
|
51658
51907
|
__export(targets_exports, {
|
|
@@ -51694,21 +51943,21 @@ function normalizeAuth(auth) {
|
|
|
51694
51943
|
return "agent";
|
|
51695
51944
|
}
|
|
51696
51945
|
function readSecrets() {
|
|
51697
|
-
const
|
|
51698
|
-
if (!existsSync30(
|
|
51946
|
+
const path100 = getSshSecretsPath();
|
|
51947
|
+
if (!existsSync30(path100)) return {};
|
|
51699
51948
|
try {
|
|
51700
|
-
return JSON.parse(readFileSync22(
|
|
51949
|
+
return JSON.parse(readFileSync22(path100, "utf8"));
|
|
51701
51950
|
} catch {
|
|
51702
51951
|
return {};
|
|
51703
51952
|
}
|
|
51704
51953
|
}
|
|
51705
51954
|
function writeSecrets(data) {
|
|
51706
|
-
const
|
|
51707
|
-
mkdirSync13(dirname4(
|
|
51708
|
-
writeFileSync16(
|
|
51955
|
+
const path100 = getSshSecretsPath();
|
|
51956
|
+
mkdirSync13(dirname4(path100), { recursive: true });
|
|
51957
|
+
writeFileSync16(path100, `${JSON.stringify(data, null, 2)}
|
|
51709
51958
|
`, "utf8");
|
|
51710
51959
|
try {
|
|
51711
|
-
chmodSync(
|
|
51960
|
+
chmodSync(path100, 384);
|
|
51712
51961
|
} catch {
|
|
51713
51962
|
}
|
|
51714
51963
|
}
|
|
@@ -51737,10 +51986,10 @@ function deleteSshPassword(id3) {
|
|
|
51737
51986
|
writeSecrets({ passwords });
|
|
51738
51987
|
}
|
|
51739
51988
|
function readStore2() {
|
|
51740
|
-
const
|
|
51741
|
-
if (!existsSync30(
|
|
51989
|
+
const path100 = getSshTargetsPath();
|
|
51990
|
+
if (!existsSync30(path100)) return [];
|
|
51742
51991
|
try {
|
|
51743
|
-
const parsed = JSON.parse(readFileSync22(
|
|
51992
|
+
const parsed = JSON.parse(readFileSync22(path100, "utf8"));
|
|
51744
51993
|
const list = Array.isArray(parsed.targets) ? parsed.targets : [];
|
|
51745
51994
|
return list.filter(
|
|
51746
51995
|
(t) => t && typeof t.id === "string" && typeof t.host === "string" && typeof t.user === "string"
|
|
@@ -51755,11 +52004,11 @@ function readStore2() {
|
|
|
51755
52004
|
}
|
|
51756
52005
|
}
|
|
51757
52006
|
function writeStore2(targets) {
|
|
51758
|
-
const
|
|
51759
|
-
mkdirSync13(dirname4(
|
|
52007
|
+
const path100 = getSshTargetsPath();
|
|
52008
|
+
mkdirSync13(dirname4(path100), { recursive: true });
|
|
51760
52009
|
const clean = targets.map(({ hasPassword: _hp, ...t }) => t);
|
|
51761
52010
|
writeFileSync16(
|
|
51762
|
-
|
|
52011
|
+
path100,
|
|
51763
52012
|
`${JSON.stringify({ targets: clean }, null, 2)}
|
|
51764
52013
|
`,
|
|
51765
52014
|
"utf8"
|
|
@@ -52005,11 +52254,11 @@ function formatSshTargetsForPrompt() {
|
|
|
52005
52254
|
];
|
|
52006
52255
|
for (const t of targets) {
|
|
52007
52256
|
const tags = t.tags?.length ? ` tags=[${t.tags.join(",")}]` : "";
|
|
52008
|
-
const
|
|
52257
|
+
const path100 = t.defaultRemotePath ? ` remotePath=${t.defaultRemotePath}` : "";
|
|
52009
52258
|
const allow = t.allowedCommands?.length ? ` allowed=${t.allowedCommands.join("|")}` : " allowed=status-only";
|
|
52010
52259
|
const auth = t.auth === "password" ? " auth=password" : t.auth === "keyPath" ? " auth=key" : " auth=agent";
|
|
52011
52260
|
lines.push(
|
|
52012
|
-
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${
|
|
52261
|
+
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${path100}${tags}${allow}`
|
|
52013
52262
|
);
|
|
52014
52263
|
}
|
|
52015
52264
|
return lines.join("\n");
|
|
@@ -52995,12 +53244,12 @@ __export(folderTrust_exports, {
|
|
|
52995
53244
|
untrustFolder: () => untrustFolder
|
|
52996
53245
|
});
|
|
52997
53246
|
import { existsSync as existsSync31, mkdirSync as mkdirSync14, readFileSync as readFileSync23, writeFileSync as writeFileSync17 } from "node:fs";
|
|
52998
|
-
import
|
|
53247
|
+
import path58 from "node:path";
|
|
52999
53248
|
function trustStorePath() {
|
|
53000
53249
|
return _overrideStorePath ?? trustConfigPath();
|
|
53001
53250
|
}
|
|
53002
53251
|
function normalize6(p3) {
|
|
53003
|
-
const resolved =
|
|
53252
|
+
const resolved = path58.resolve(p3);
|
|
53004
53253
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
53005
53254
|
}
|
|
53006
53255
|
function readStore3() {
|
|
@@ -53016,7 +53265,7 @@ function readStore3() {
|
|
|
53016
53265
|
function writeStore3(store6) {
|
|
53017
53266
|
const p3 = trustStorePath();
|
|
53018
53267
|
try {
|
|
53019
|
-
mkdirSync14(
|
|
53268
|
+
mkdirSync14(path58.dirname(p3), { recursive: true });
|
|
53020
53269
|
writeFileSync17(p3, JSON.stringify(store6, null, 2), "utf8");
|
|
53021
53270
|
} catch (err) {
|
|
53022
53271
|
throw new Error(
|
|
@@ -53042,7 +53291,7 @@ function isFolderTrusted(folderPath) {
|
|
|
53042
53291
|
}
|
|
53043
53292
|
function trustFolder(folderPath) {
|
|
53044
53293
|
const store6 = readStore3();
|
|
53045
|
-
const normalized =
|
|
53294
|
+
const normalized = path58.resolve(folderPath);
|
|
53046
53295
|
if (!store6.folders.some((f) => normalize6(f.path) === normalize6(normalized))) {
|
|
53047
53296
|
store6.folders.push({ path: normalized, trustedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
53048
53297
|
writeStore3(store6);
|
|
@@ -53168,7 +53417,7 @@ var init_lifecycleHooks = __esm({
|
|
|
53168
53417
|
|
|
53169
53418
|
// src/cli/safety/astGate.ts
|
|
53170
53419
|
import { promises as fs23 } from "node:fs";
|
|
53171
|
-
import
|
|
53420
|
+
import path59 from "node:path";
|
|
53172
53421
|
function astGateEnabled() {
|
|
53173
53422
|
return process.env.ZELARI_AST_GATE !== "0";
|
|
53174
53423
|
}
|
|
@@ -53203,9 +53452,9 @@ function wrapWithAstGate(original, opts) {
|
|
|
53203
53452
|
const containedPathOf = (args) => {
|
|
53204
53453
|
const raw = args["path"];
|
|
53205
53454
|
if (typeof raw !== "string" || raw.length === 0) return null;
|
|
53206
|
-
const absPath =
|
|
53207
|
-
const rel2 =
|
|
53208
|
-
if (rel2.startsWith("..") ||
|
|
53455
|
+
const absPath = path59.isAbsolute(raw) ? raw : path59.join(opts.root, raw);
|
|
53456
|
+
const rel2 = path59.relative(opts.root, absPath);
|
|
53457
|
+
if (rel2.startsWith("..") || path59.isAbsolute(rel2)) return null;
|
|
53209
53458
|
return absPath;
|
|
53210
53459
|
};
|
|
53211
53460
|
return {
|
|
@@ -53230,7 +53479,7 @@ function wrapWithAstGate(original, opts) {
|
|
|
53230
53479
|
if (!result.ok) return result;
|
|
53231
53480
|
if (gateTarget !== null && !isAstSupported(gateTarget)) {
|
|
53232
53481
|
process.stderr.write(
|
|
53233
|
-
`[ast_gate] LOUD SKIP (unsupported-extension): ${original.name} ${gateTarget} \u2014 ${
|
|
53482
|
+
`[ast_gate] LOUD SKIP (unsupported-extension): ${original.name} ${gateTarget} \u2014 ${path59.extname(gateTarget) || "(no extension)"} is outside the AST surface; write KEPT, NOT syntax-gated.
|
|
53234
53483
|
`
|
|
53235
53484
|
);
|
|
53236
53485
|
return result;
|
|
@@ -53247,7 +53496,7 @@ function wrapWithAstGate(original, opts) {
|
|
|
53247
53496
|
return result;
|
|
53248
53497
|
}
|
|
53249
53498
|
const post = await fs23.readFile(absPath, "utf8");
|
|
53250
|
-
const syntaxError = firstSyntaxError(ts,
|
|
53499
|
+
const syntaxError = firstSyntaxError(ts, path59.basename(absPath), post);
|
|
53251
53500
|
if (!syntaxError) return result;
|
|
53252
53501
|
const parseError = `${syntaxError.message} (line ${syntaxError.line}, col ${syntaxError.character})`;
|
|
53253
53502
|
let revertedTo;
|
|
@@ -53258,7 +53507,7 @@ function wrapWithAstGate(original, opts) {
|
|
|
53258
53507
|
await fs23.writeFile(absPath, preContent, "utf8");
|
|
53259
53508
|
revertedTo = snapshotIdOf(preContent);
|
|
53260
53509
|
}
|
|
53261
|
-
const relLabel =
|
|
53510
|
+
const relLabel = path59.relative(opts.root, absPath) || path59.basename(absPath);
|
|
53262
53511
|
return typedErr(
|
|
53263
53512
|
`[ast_gate_reverted] ${original.name}: ${absPath} written but the file no longer parses \u2014 write REVERTED (revertedTo=${revertedTo}). ${parseError}. Fix the syntax and re-apply (read_file first for a fresh snapshotId).`,
|
|
53264
53513
|
{
|
|
@@ -53683,7 +53932,7 @@ var init_resourceClaims = __esm({
|
|
|
53683
53932
|
// src/cli/toolResultCache.ts
|
|
53684
53933
|
import { createHash as createHash15 } from "node:crypto";
|
|
53685
53934
|
import { promises as fs24 } from "node:fs";
|
|
53686
|
-
import
|
|
53935
|
+
import path60 from "node:path";
|
|
53687
53936
|
function isToolCacheEnabled() {
|
|
53688
53937
|
const raw = process.env.ZELARI_TOOL_CACHE;
|
|
53689
53938
|
return raw !== "0" && raw !== "false" && raw !== "off";
|
|
@@ -53768,7 +54017,7 @@ async function statKey(toolName, input, ctx) {
|
|
|
53768
54017
|
if (!input || typeof input !== "object") return null;
|
|
53769
54018
|
const rawPath = input.path;
|
|
53770
54019
|
if (typeof rawPath !== "string" || rawPath.length === 0) return null;
|
|
53771
|
-
const abs =
|
|
54020
|
+
const abs = path60.isAbsolute(rawPath) ? rawPath : path60.join(ctx.cwd, rawPath);
|
|
53772
54021
|
try {
|
|
53773
54022
|
const st = await fs24.stat(abs);
|
|
53774
54023
|
return hashKey({
|
|
@@ -53824,7 +54073,7 @@ __export(toolRegistry_exports, {
|
|
|
53824
54073
|
wrapWithSandbox: () => wrapWithSandbox
|
|
53825
54074
|
});
|
|
53826
54075
|
import { existsSync as existsSync32 } from "node:fs";
|
|
53827
|
-
import
|
|
54076
|
+
import path61 from "node:path";
|
|
53828
54077
|
function createBuiltinToolRegistry(options = {}) {
|
|
53829
54078
|
const root = options.root ?? process.cwd();
|
|
53830
54079
|
const audit = options.audit ?? new AuditLogger();
|
|
@@ -54049,6 +54298,15 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
54049
54298
|
permissions: browserTool.permissions ?? []
|
|
54050
54299
|
});
|
|
54051
54300
|
}
|
|
54301
|
+
if (!readOnly && !gauntletParent && process.env.ZELARI_SCREENSHOT !== "0") {
|
|
54302
|
+
const screenshotTool = createScreenshotTool();
|
|
54303
|
+
registry4.register(screenshotTool);
|
|
54304
|
+
tools.push({
|
|
54305
|
+
name: screenshotTool.name,
|
|
54306
|
+
description: screenshotTool.description,
|
|
54307
|
+
permissions: screenshotTool.permissions ?? []
|
|
54308
|
+
});
|
|
54309
|
+
}
|
|
54052
54310
|
if (!readOnly && !gauntletParent && process.env.ZELARI_SSH !== "0") {
|
|
54053
54311
|
for (const t of createSshTools()) {
|
|
54054
54312
|
registry4.register(t);
|
|
@@ -54082,6 +54340,7 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
54082
54340
|
// registry's own policy (permPolicy above) — they can never
|
|
54083
54341
|
// exceed it.
|
|
54084
54342
|
parentPolicy: permPolicy,
|
|
54343
|
+
...options.onPermissionAsk ? { onPermissionAsk: options.onPermissionAsk } : {},
|
|
54085
54344
|
...options.subAgentProvider ? { provider: options.subAgentProvider } : {},
|
|
54086
54345
|
...options.subAgentModel ? { model: options.subAgentModel } : {}
|
|
54087
54346
|
}),
|
|
@@ -54181,12 +54440,13 @@ function taskAgentToProfile(agent) {
|
|
|
54181
54440
|
return "explore";
|
|
54182
54441
|
}
|
|
54183
54442
|
function createKrakenSubAgentContextFactory(opts) {
|
|
54184
|
-
const { root, audit, sessionId: sessionId2, provider: providerOverride, model: modelOverride, parentPolicy } = opts;
|
|
54443
|
+
const { root, audit, sessionId: sessionId2, provider: providerOverride, model: modelOverride, parentPolicy, onPermissionAsk } = opts;
|
|
54185
54444
|
return async ({ agent, cwd: subCwd }) => {
|
|
54186
54445
|
const cfg = providerOverride ? await providerConfigFor(providerOverride) : await providerFromEnv();
|
|
54187
54446
|
if (!cfg) return null;
|
|
54188
54447
|
const { resolveKrakenSubModel: resolveKrakenSubModel2, parseQualifiedModelRef: parseQualifiedModelRef2 } = await Promise.resolve().then(() => (init_krakenModel(), krakenModel_exports));
|
|
54189
|
-
const
|
|
54448
|
+
const parentModel = modelOverride || cfg.model;
|
|
54449
|
+
const resolvedModel = resolveKrakenSubModel2(agent, parentModel);
|
|
54190
54450
|
let effCfg = cfg;
|
|
54191
54451
|
let model = resolvedModel;
|
|
54192
54452
|
const ref = parseQualifiedModelRef2(resolvedModel);
|
|
@@ -54215,6 +54475,7 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
54215
54475
|
diagnostics: false,
|
|
54216
54476
|
lspProvider: null,
|
|
54217
54477
|
permissionPolicy: effectiveSubPolicy,
|
|
54478
|
+
...onPermissionAsk ? { onPermissionAsk } : {},
|
|
54218
54479
|
// P0.5: the tentacle's agent identity drives per-agent policy rules.
|
|
54219
54480
|
policyAgent: agent
|
|
54220
54481
|
});
|
|
@@ -54222,6 +54483,13 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
54222
54483
|
providerStream: buildProviderStream(subCfg),
|
|
54223
54484
|
model,
|
|
54224
54485
|
provider: subCfg.providerId,
|
|
54486
|
+
...model !== parentModel ? {
|
|
54487
|
+
fallback: {
|
|
54488
|
+
model: parentModel,
|
|
54489
|
+
provider: cfg.providerId,
|
|
54490
|
+
providerStream: buildProviderStream({ ...cfg, model: parentModel })
|
|
54491
|
+
}
|
|
54492
|
+
} : {},
|
|
54225
54493
|
registry: subRegistry,
|
|
54226
54494
|
tools: subRegistry.toOpenAITools().map((t) => ({
|
|
54227
54495
|
name: t.function.name,
|
|
@@ -54241,11 +54509,14 @@ function wrapWithPermissions(original, policy, onAsk, agentLayers, precedence =
|
|
|
54241
54509
|
return {
|
|
54242
54510
|
...original,
|
|
54243
54511
|
execute: async (input, ctx) => {
|
|
54244
|
-
const
|
|
54512
|
+
const requiredNow = original.name === "task" ? permissionsForTaskAgent(
|
|
54513
|
+
input?.agent
|
|
54514
|
+
) : required2;
|
|
54515
|
+
const decision = resolveToolPermission(original.name, requiredNow, policy);
|
|
54245
54516
|
const rule = agentLayers ? matchAgentPolicyRuleLayered(
|
|
54246
54517
|
agentLayers,
|
|
54247
54518
|
precedence,
|
|
54248
|
-
|
|
54519
|
+
requiredNow,
|
|
54249
54520
|
input ?? {},
|
|
54250
54521
|
root ?? process.cwd()
|
|
54251
54522
|
) : null;
|
|
@@ -54257,25 +54528,25 @@ function wrapWithPermissions(original, policy, onAsk, agentLayers, precedence =
|
|
|
54257
54528
|
root ?? process.cwd()
|
|
54258
54529
|
) : void 0;
|
|
54259
54530
|
const contractRule = matchContractCapabilityRule(
|
|
54260
|
-
|
|
54531
|
+
requiredNow,
|
|
54261
54532
|
input ?? {},
|
|
54262
54533
|
root ?? process.cwd()
|
|
54263
54534
|
);
|
|
54264
54535
|
let action = intersectEffects(mergeRuleEffect(decision.action, rule), claims?.effect, contractRule?.effect);
|
|
54265
54536
|
let actionReason = decision.reason;
|
|
54266
|
-
if (action !== "deny" && (
|
|
54537
|
+
if (action !== "deny" && (requiredNow.includes("write") || requiredNow.includes("execute"))) {
|
|
54267
54538
|
const provHit = provenanceMatchIn(JSON.stringify(input ?? {}));
|
|
54268
|
-
if (provHit && provenanceAppliesTo(provHit.source,
|
|
54539
|
+
if (provHit && provenanceAppliesTo(provHit.source, requiredNow)) {
|
|
54269
54540
|
const provNote = `[provenance] args embed non-user ${provHit.source} content (via ${provHit.tool})`;
|
|
54270
54541
|
if (action === "allow") {
|
|
54271
54542
|
action = "ask";
|
|
54272
|
-
actionReason = `${provNote} \u2014 confirm before ${
|
|
54543
|
+
actionReason = `${provNote} \u2014 confirm before ${requiredNow.join("+")}`;
|
|
54273
54544
|
} else {
|
|
54274
54545
|
actionReason = `${decision.reason} \xB7 ${provNote}`;
|
|
54275
54546
|
}
|
|
54276
54547
|
}
|
|
54277
54548
|
}
|
|
54278
|
-
if (action === "allow" &&
|
|
54549
|
+
if (action === "allow" && requiredNow.includes("execute") && activePermissionPreset() !== "yolo" && !isSessionGranted(original.name, requiredNow)) {
|
|
54279
54550
|
const destructiveHit = destructiveCommandHit(input ?? {});
|
|
54280
54551
|
if (destructiveHit) {
|
|
54281
54552
|
action = "ask";
|
|
@@ -54318,7 +54589,7 @@ function wrapWithPermissions(original, policy, onAsk, agentLayers, precedence =
|
|
|
54318
54589
|
}
|
|
54319
54590
|
}
|
|
54320
54591
|
const outcome = await original.execute(input, ctx);
|
|
54321
|
-
recordResultForProvenance(original.name,
|
|
54592
|
+
recordResultForProvenance(original.name, requiredNow, outcome);
|
|
54322
54593
|
return outcome;
|
|
54323
54594
|
}
|
|
54324
54595
|
};
|
|
@@ -54420,14 +54691,14 @@ function wrapWithDiagnostics(original, root, runner) {
|
|
|
54420
54691
|
function claimedSourcePath(token, args, root) {
|
|
54421
54692
|
const cleaned = token.replace(/^["']|["']$/g, "");
|
|
54422
54693
|
if (!cleaned || cleaned.startsWith("-")) return null;
|
|
54423
|
-
if (!DIAG_SOURCE_EXTENSIONS.has(
|
|
54694
|
+
if (!DIAG_SOURCE_EXTENSIONS.has(path61.extname(cleaned).toLowerCase())) return null;
|
|
54424
54695
|
const bases = [root];
|
|
54425
54696
|
const cwd = args["cwd"];
|
|
54426
54697
|
if (typeof cwd === "string" && cwd.length > 0) {
|
|
54427
|
-
bases.unshift(
|
|
54698
|
+
bases.unshift(path61.isAbsolute(cwd) ? cwd : path61.resolve(root, cwd));
|
|
54428
54699
|
}
|
|
54429
54700
|
for (const base2 of bases) {
|
|
54430
|
-
const candidate =
|
|
54701
|
+
const candidate = path61.isAbsolute(cleaned) ? path61.normalize(cleaned) : path61.resolve(base2, cleaned);
|
|
54431
54702
|
try {
|
|
54432
54703
|
const contained = resolveSandboxedPath(candidate, { root });
|
|
54433
54704
|
if (existsSync32(contained)) return contained;
|
|
@@ -54697,6 +54968,7 @@ var init_toolRegistry = __esm({
|
|
|
54697
54968
|
init_tools3();
|
|
54698
54969
|
init_tools4();
|
|
54699
54970
|
init_tools5();
|
|
54971
|
+
init_screenshotTool();
|
|
54700
54972
|
init_tools6();
|
|
54701
54973
|
init_worldModel();
|
|
54702
54974
|
init_openai_compatible();
|
|
@@ -54743,7 +55015,7 @@ var init_toolRegistry = __esm({
|
|
|
54743
55015
|
|
|
54744
55016
|
// src/cli/metrics.ts
|
|
54745
55017
|
import { promises as fs25, existsSync as existsSync33, statSync as statSync4, renameSync as renameSync4, appendFileSync as appendFileSync3, mkdirSync as mkdirSync15 } from "node:fs";
|
|
54746
|
-
import
|
|
55018
|
+
import path62 from "node:path";
|
|
54747
55019
|
async function readMetrics(file2) {
|
|
54748
55020
|
let raw = "";
|
|
54749
55021
|
try {
|
|
@@ -54793,7 +55065,7 @@ var init_metrics3 = __esm({
|
|
|
54793
55065
|
writeQueue = Promise.resolve();
|
|
54794
55066
|
constructor(file2) {
|
|
54795
55067
|
this.file = file2 ?? metricsPath();
|
|
54796
|
-
mkdirSync15(
|
|
55068
|
+
mkdirSync15(path62.dirname(this.file), { recursive: true });
|
|
54797
55069
|
}
|
|
54798
55070
|
/** Metrics file path — doctor/summary readers use this. */
|
|
54799
55071
|
get filePath() {
|
|
@@ -54830,8 +55102,8 @@ var init_metrics3 = __esm({
|
|
|
54830
55102
|
maybeRotate() {
|
|
54831
55103
|
if (!existsSync33(this.file)) return;
|
|
54832
55104
|
try {
|
|
54833
|
-
const
|
|
54834
|
-
if (
|
|
55105
|
+
const stat8 = statSync4(this.file);
|
|
55106
|
+
if (stat8.size >= METRICS_ROTATE_BYTES) {
|
|
54835
55107
|
const rotated = this.file.replace(/\.jsonl$/, ".1.jsonl");
|
|
54836
55108
|
renameSync4(this.file, rotated);
|
|
54837
55109
|
}
|
|
@@ -55125,15 +55397,15 @@ __export(completionProofProbe_exports, {
|
|
|
55125
55397
|
gatherGitAttestation: () => gatherGitAttestation,
|
|
55126
55398
|
harnessManifest: () => harnessManifest
|
|
55127
55399
|
});
|
|
55128
|
-
import { execFile as
|
|
55129
|
-
import { promisify as
|
|
55400
|
+
import { execFile as execFile6 } from "node:child_process";
|
|
55401
|
+
import { promisify as promisify5 } from "node:util";
|
|
55130
55402
|
async function readHarnessVersion() {
|
|
55131
55403
|
if (cachedHarnessVersion !== null) return cachedHarnessVersion;
|
|
55132
55404
|
try {
|
|
55133
|
-
const { readFile:
|
|
55405
|
+
const { readFile: readFile11 } = await import("node:fs/promises");
|
|
55134
55406
|
const { fileURLToPath: fileURLToPath4 } = await import("node:url");
|
|
55135
55407
|
const pkgPath = fileURLToPath4(new URL("../../../package.json", import.meta.url));
|
|
55136
|
-
const parsed = JSON.parse(await
|
|
55408
|
+
const parsed = JSON.parse(await readFile11(pkgPath, "utf8"));
|
|
55137
55409
|
if (typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
55138
55410
|
return cachedHarnessVersion = parsed.version;
|
|
55139
55411
|
}
|
|
@@ -55157,7 +55429,7 @@ async function harnessManifest(env = process.env) {
|
|
|
55157
55429
|
}
|
|
55158
55430
|
async function git5(cwd, args) {
|
|
55159
55431
|
try {
|
|
55160
|
-
const { stdout } = await
|
|
55432
|
+
const { stdout } = await execFileAsync5("git", ["-C", cwd, ...args], {
|
|
55161
55433
|
maxBuffer: 32 * 1024 * 1024,
|
|
55162
55434
|
windowsHide: true
|
|
55163
55435
|
});
|
|
@@ -55199,7 +55471,7 @@ function activeTaskContractSnapshot() {
|
|
|
55199
55471
|
return void 0;
|
|
55200
55472
|
}
|
|
55201
55473
|
}
|
|
55202
|
-
var HARNESS_VERSION_FALLBACK, ADAPTER_IDS, cachedHarnessVersion,
|
|
55474
|
+
var HARNESS_VERSION_FALLBACK, ADAPTER_IDS, cachedHarnessVersion, execFileAsync5;
|
|
55203
55475
|
var init_completionProofProbe = __esm({
|
|
55204
55476
|
"src/cli/kraken/completionProofProbe.ts"() {
|
|
55205
55477
|
"use strict";
|
|
@@ -55207,7 +55479,7 @@ var init_completionProofProbe = __esm({
|
|
|
55207
55479
|
HARNESS_VERSION_FALLBACK = "2.13.0";
|
|
55208
55480
|
ADAPTER_IDS = ["node", "python", "rust", "go", "java", "dotnet"];
|
|
55209
55481
|
cachedHarnessVersion = null;
|
|
55210
|
-
|
|
55482
|
+
execFileAsync5 = promisify5(execFile6);
|
|
55211
55483
|
}
|
|
55212
55484
|
});
|
|
55213
55485
|
|
|
@@ -55311,7 +55583,7 @@ var init_completionProofAttestation = __esm({
|
|
|
55311
55583
|
// src/cli/kraken/completionProofPersist.ts
|
|
55312
55584
|
import { open, rename as rename2, rm as rm2 } from "node:fs/promises";
|
|
55313
55585
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
55314
|
-
import
|
|
55586
|
+
import path63 from "node:path";
|
|
55315
55587
|
function isTruthyFlag2(v) {
|
|
55316
55588
|
const n = v?.trim().toLowerCase();
|
|
55317
55589
|
return n === "1" || n === "true" || n === "yes" || n === "on";
|
|
@@ -55353,8 +55625,8 @@ function isWindowsRenameBlock(err) {
|
|
|
55353
55625
|
return code === "EPERM" || code === "ENOTEMPTY" || code === "EEXIST";
|
|
55354
55626
|
}
|
|
55355
55627
|
async function writeFileAtomic(target, data) {
|
|
55356
|
-
const dir =
|
|
55357
|
-
const tmp =
|
|
55628
|
+
const dir = path63.dirname(target);
|
|
55629
|
+
const tmp = path63.join(dir, `.${path63.basename(target)}.${randomBytes5(6).toString("hex")}.tmp`);
|
|
55358
55630
|
let fh = null;
|
|
55359
55631
|
try {
|
|
55360
55632
|
fh = await open(tmp, "w");
|
|
@@ -55399,8 +55671,8 @@ var init_completionProofPersist = __esm({
|
|
|
55399
55671
|
});
|
|
55400
55672
|
|
|
55401
55673
|
// src/cli/kraken/completionProof.ts
|
|
55402
|
-
import { mkdir as
|
|
55403
|
-
import
|
|
55674
|
+
import { mkdir as mkdir4 } from "node:fs/promises";
|
|
55675
|
+
import path64 from "node:path";
|
|
55404
55676
|
function verdictOf(evaluation) {
|
|
55405
55677
|
return evaluation.evaluation?.verdict ?? (evaluation.blocked ? "BLOCKED" : "PASS");
|
|
55406
55678
|
}
|
|
@@ -55545,8 +55817,8 @@ async function writeCompletionProofDetailed(evaluation, options = {}) {
|
|
|
55545
55817
|
const mode = options.persistenceMode ?? activeProofPersistenceMode();
|
|
55546
55818
|
try {
|
|
55547
55819
|
const baseDir = options.baseDir ?? process.cwd();
|
|
55548
|
-
const dir =
|
|
55549
|
-
await
|
|
55820
|
+
const dir = path64.join(baseDir, ".zelari");
|
|
55821
|
+
await mkdir4(dir, { recursive: true });
|
|
55550
55822
|
const requested = options.attestation ?? {};
|
|
55551
55823
|
const plan = requested.skipProbes || requested.verificationPlan !== void 0 ? void 0 : await defaultVerificationPlanSnapshot(baseDir);
|
|
55552
55824
|
const wrapper = await buildAttestedWrapper(
|
|
@@ -55565,8 +55837,8 @@ async function writeCompletionProofDetailed(evaluation, options = {}) {
|
|
|
55565
55837
|
baseDir
|
|
55566
55838
|
);
|
|
55567
55839
|
const rendered = renderCompletionProof(evaluation, options.meta ?? {}, wrapper.attestation);
|
|
55568
|
-
const markdownPath =
|
|
55569
|
-
const jsonPath =
|
|
55840
|
+
const markdownPath = path64.join(dir, "completion-proof.md");
|
|
55841
|
+
const jsonPath = path64.join(dir, "completion-proof.json");
|
|
55570
55842
|
await writeFileAtomic(markdownPath, rendered.markdown);
|
|
55571
55843
|
await writeFileAtomic(jsonPath, rendered.json);
|
|
55572
55844
|
return { paths: { markdownPath, jsonPath }, mode, requiredBlockReason: null };
|
|
@@ -55654,15 +55926,34 @@ var init_spineTelemetry = __esm({
|
|
|
55654
55926
|
}
|
|
55655
55927
|
});
|
|
55656
55928
|
|
|
55929
|
+
// src/cli/hooks/askUserTimeout.ts
|
|
55930
|
+
function askUserTimeoutMs() {
|
|
55931
|
+
const raw = process.env.ZELARI_ASK_USER_TIMEOUT_MS?.trim();
|
|
55932
|
+
if (!raw) return 3e5;
|
|
55933
|
+
const n = Number.parseInt(raw, 10);
|
|
55934
|
+
if (!Number.isFinite(n) || n < 0) return 3e5;
|
|
55935
|
+
return n;
|
|
55936
|
+
}
|
|
55937
|
+
function armPickerTimeout(onFire, ms) {
|
|
55938
|
+
if (ms <= 0) return () => void 0;
|
|
55939
|
+
const id3 = setTimeout(onFire, ms);
|
|
55940
|
+
return () => clearTimeout(id3);
|
|
55941
|
+
}
|
|
55942
|
+
var init_askUserTimeout = __esm({
|
|
55943
|
+
"src/cli/hooks/askUserTimeout.ts"() {
|
|
55944
|
+
"use strict";
|
|
55945
|
+
}
|
|
55946
|
+
});
|
|
55947
|
+
|
|
55657
55948
|
// src/cli/state/fileStateStore.ts
|
|
55658
55949
|
import { createHash as createHash17, randomUUID as randomUUID5 } from "node:crypto";
|
|
55659
55950
|
import { promises as fs26 } from "node:fs";
|
|
55660
|
-
import * as
|
|
55951
|
+
import * as path65 from "node:path";
|
|
55661
55952
|
function shortId() {
|
|
55662
55953
|
return randomUUID5().replace(/-/g, "").slice(0, 12);
|
|
55663
55954
|
}
|
|
55664
55955
|
async function writeJsonAtomic(filePath, data) {
|
|
55665
|
-
await fs26.mkdir(
|
|
55956
|
+
await fs26.mkdir(path65.dirname(filePath), { recursive: true });
|
|
55666
55957
|
const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
55667
55958
|
await fs26.writeFile(tmp, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
55668
55959
|
await fs26.rename(tmp, filePath);
|
|
@@ -55723,11 +56014,11 @@ var init_fileStateStore = __esm({
|
|
|
55723
56014
|
indexPath = "";
|
|
55724
56015
|
async init(projectRoot) {
|
|
55725
56016
|
this.root = projectRoot;
|
|
55726
|
-
this.stateDir =
|
|
55727
|
-
this.commitsDir =
|
|
55728
|
-
this.artifactsDir =
|
|
55729
|
-
this.headPath =
|
|
55730
|
-
this.indexPath =
|
|
56017
|
+
this.stateDir = path65.join(projectRoot, ".zelari", "state");
|
|
56018
|
+
this.commitsDir = path65.join(this.stateDir, "commits");
|
|
56019
|
+
this.artifactsDir = path65.join(this.stateDir, "artifacts");
|
|
56020
|
+
this.headPath = path65.join(this.stateDir, "HEAD.json");
|
|
56021
|
+
this.indexPath = path65.join(this.stateDir, "index.jsonl");
|
|
55731
56022
|
await fs26.mkdir(this.commitsDir, { recursive: true });
|
|
55732
56023
|
await fs26.mkdir(this.artifactsDir, { recursive: true });
|
|
55733
56024
|
}
|
|
@@ -55740,13 +56031,13 @@ var init_fileStateStore = __esm({
|
|
|
55740
56031
|
const discoveries = input.discoveries ?? [];
|
|
55741
56032
|
const parent = await this.head();
|
|
55742
56033
|
const id3 = shortId();
|
|
55743
|
-
const artifactRel =
|
|
55744
|
-
const artifactAbs =
|
|
56034
|
+
const artifactRel = path65.join("artifacts", id3);
|
|
56035
|
+
const artifactAbs = path65.join(this.artifactsDir, id3);
|
|
55745
56036
|
await fs26.mkdir(artifactAbs, { recursive: true });
|
|
55746
56037
|
const summary = defaultSummary(input, discoveries);
|
|
55747
|
-
await fs26.writeFile(
|
|
55748
|
-
await writeJsonAtomic(
|
|
55749
|
-
await writeJsonAtomic(
|
|
56038
|
+
await fs26.writeFile(path65.join(artifactAbs, "summary.md"), summary + "\n", "utf8");
|
|
56039
|
+
await writeJsonAtomic(path65.join(artifactAbs, "discoveries.json"), discoveries);
|
|
56040
|
+
await writeJsonAtomic(path65.join(artifactAbs, "verification.json"), input.verification);
|
|
55750
56041
|
const meta3 = {
|
|
55751
56042
|
id: id3,
|
|
55752
56043
|
parentId: parent?.id ?? null,
|
|
@@ -55758,14 +56049,14 @@ var init_fileStateStore = __esm({
|
|
|
55758
56049
|
workspaceCheckpointId: input.workspaceCheckpointId,
|
|
55759
56050
|
verification: {
|
|
55760
56051
|
...input.verification,
|
|
55761
|
-
reportPath: input.verification.reportPath ??
|
|
56052
|
+
reportPath: input.verification.reportPath ?? path65.join(".zelari", "state", artifactRel, "verification.json").replace(/\\/g, "/")
|
|
55762
56053
|
},
|
|
55763
56054
|
changedPaths: input.changedPaths ?? [],
|
|
55764
56055
|
stablePromptHash: input.stablePromptHash,
|
|
55765
56056
|
discoveryCount: discoveries.length,
|
|
55766
56057
|
artifactDir: artifactRel.replace(/\\/g, "/")
|
|
55767
56058
|
};
|
|
55768
|
-
await writeJsonAtomic(
|
|
56059
|
+
await writeJsonAtomic(path65.join(this.commitsDir, `${id3}.json`), meta3);
|
|
55769
56060
|
await writeJsonAtomic(this.headPath, { id: id3, updatedAt: meta3.createdAt });
|
|
55770
56061
|
await fs26.appendFile(this.indexPath, JSON.stringify({ id: id3, createdAt: meta3.createdAt, label: meta3.label }) + "\n", "utf8");
|
|
55771
56062
|
return stripStored(meta3);
|
|
@@ -55776,7 +56067,7 @@ var init_fileStateStore = __esm({
|
|
|
55776
56067
|
return this.get(head.id);
|
|
55777
56068
|
}
|
|
55778
56069
|
async get(id3) {
|
|
55779
|
-
const stored = await readJsonFile(
|
|
56070
|
+
const stored = await readJsonFile(path65.join(this.commitsDir, `${id3}.json`));
|
|
55780
56071
|
return stored ? stripStored(stored) : null;
|
|
55781
56072
|
}
|
|
55782
56073
|
async list(limit = 20) {
|
|
@@ -55815,9 +56106,9 @@ var init_fileStateStore = __esm({
|
|
|
55815
56106
|
async loadDiscoveries(id3) {
|
|
55816
56107
|
const meta3 = id3 ? await this.get(id3) : await this.head();
|
|
55817
56108
|
if (!meta3) return [];
|
|
55818
|
-
const stored = await readJsonFile(
|
|
56109
|
+
const stored = await readJsonFile(path65.join(this.commitsDir, `${meta3.id}.json`));
|
|
55819
56110
|
if (!stored?.artifactDir) return [];
|
|
55820
|
-
const discPath =
|
|
56111
|
+
const discPath = path65.join(this.stateDir, stored.artifactDir, "discoveries.json");
|
|
55821
56112
|
return await readJsonFile(discPath) ?? [];
|
|
55822
56113
|
}
|
|
55823
56114
|
async materializeContext(id3, maxChars = DEFAULT_MATERIALIZE_CHARS) {
|
|
@@ -56420,10 +56711,10 @@ var init_mode = __esm({
|
|
|
56420
56711
|
|
|
56421
56712
|
// src/cli/headless.ts
|
|
56422
56713
|
import { readFileSync as readFileSync24 } from "node:fs";
|
|
56423
|
-
import
|
|
56714
|
+
import path66 from "node:path";
|
|
56424
56715
|
function resolveHeadlessCwd(opts) {
|
|
56425
56716
|
const raw = typeof opts.cwd === "string" ? opts.cwd.trim() : "";
|
|
56426
|
-
return
|
|
56717
|
+
return path66.resolve(raw.length > 0 ? raw : process.cwd());
|
|
56427
56718
|
}
|
|
56428
56719
|
function defaultProfileForMode(mode) {
|
|
56429
56720
|
switch (mode) {
|
|
@@ -57525,7 +57816,7 @@ var init_planDetect = __esm({
|
|
|
57525
57816
|
// src/cli/memory/legacyImport.ts
|
|
57526
57817
|
import { createHash as createHash18 } from "node:crypto";
|
|
57527
57818
|
import { promises as fs27 } from "node:fs";
|
|
57528
|
-
import * as
|
|
57819
|
+
import * as path67 from "node:path";
|
|
57529
57820
|
function sourceId(fact, line) {
|
|
57530
57821
|
return `jsonl:${fact.id ?? createHash18("sha256").update(line).digest("hex")}`;
|
|
57531
57822
|
}
|
|
@@ -57543,7 +57834,7 @@ function timestamp(value) {
|
|
|
57543
57834
|
}
|
|
57544
57835
|
async function importLegacyMemoryLog(backend, service) {
|
|
57545
57836
|
const result = { found: 0, imported: 0, skipped: 0, corrupt: 0 };
|
|
57546
|
-
const logPath =
|
|
57837
|
+
const logPath = path67.join(path67.dirname(backend.databasePath), "log.jsonl");
|
|
57547
57838
|
let raw;
|
|
57548
57839
|
try {
|
|
57549
57840
|
raw = await fs27.readFile(logPath, "utf8");
|
|
@@ -57726,7 +58017,7 @@ var init_sqliteCodec = __esm({
|
|
|
57726
58017
|
// src/cli/memory/sqliteRpc.ts
|
|
57727
58018
|
import { existsSync as existsSync36 } from "node:fs";
|
|
57728
58019
|
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
57729
|
-
import * as
|
|
58020
|
+
import * as path68 from "node:path";
|
|
57730
58021
|
import { Worker } from "node:worker_threads";
|
|
57731
58022
|
function isBusy(error51) {
|
|
57732
58023
|
const candidate = error51;
|
|
@@ -57735,10 +58026,10 @@ function isBusy(error51) {
|
|
|
57735
58026
|
);
|
|
57736
58027
|
}
|
|
57737
58028
|
function resolveWorkerUrl() {
|
|
57738
|
-
const here =
|
|
57739
|
-
const direct =
|
|
58029
|
+
const here = path68.dirname(fileURLToPath2(import.meta.url));
|
|
58030
|
+
const direct = path68.join(here, "sqliteWorker.mjs");
|
|
57740
58031
|
if (existsSync36(direct)) return pathToFileURL2(direct);
|
|
57741
|
-
return pathToFileURL2(
|
|
58032
|
+
return pathToFileURL2(path68.join(here, "memory", "sqliteWorker.mjs"));
|
|
57742
58033
|
}
|
|
57743
58034
|
var SqliteWorkerRpc;
|
|
57744
58035
|
var init_sqliteRpc = __esm({
|
|
@@ -58027,7 +58318,7 @@ WHERE NOT EXISTS (SELECT 1 FROM memory_fts f WHERE f.node_id = n.id);
|
|
|
58027
58318
|
// src/cli/memory/sqliteBackend.ts
|
|
58028
58319
|
import { createHash as createHash19, randomUUID as randomUUID6 } from "node:crypto";
|
|
58029
58320
|
import { promises as fs28 } from "node:fs";
|
|
58030
|
-
import * as
|
|
58321
|
+
import * as path69 from "node:path";
|
|
58031
58322
|
function boundedLimit(value, fallback = 50) {
|
|
58032
58323
|
return Math.max(1, Math.min(Math.floor(value ?? fallback), 1e5));
|
|
58033
58324
|
}
|
|
@@ -58089,20 +58380,20 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
58089
58380
|
try {
|
|
58090
58381
|
resolved = await fs28.realpath(projectRoot);
|
|
58091
58382
|
} catch {
|
|
58092
|
-
resolved =
|
|
58383
|
+
resolved = path69.resolve(projectRoot);
|
|
58093
58384
|
}
|
|
58094
58385
|
if (this.initialized && resolved === this.projectRoot) return;
|
|
58095
58386
|
if (this.initialized) await this.close();
|
|
58096
58387
|
const filename = this.options.filename ?? "memory.db";
|
|
58097
|
-
if (
|
|
58388
|
+
if (path69.basename(filename) !== filename || filename === "." || filename === "..") {
|
|
58098
58389
|
throw new Error("SQLite memory filename must not contain a path.");
|
|
58099
58390
|
}
|
|
58100
|
-
const zelariDirectory =
|
|
58101
|
-
const directory =
|
|
58391
|
+
const zelariDirectory = path69.join(resolved, ".zelari");
|
|
58392
|
+
const directory = path69.join(zelariDirectory, "memory");
|
|
58102
58393
|
for (const candidate of [zelariDirectory, directory]) {
|
|
58103
|
-
let
|
|
58394
|
+
let stat8;
|
|
58104
58395
|
try {
|
|
58105
|
-
|
|
58396
|
+
stat8 = await fs28.lstat(candidate);
|
|
58106
58397
|
} catch (error51) {
|
|
58107
58398
|
if (error51.code !== "ENOENT") throw error51;
|
|
58108
58399
|
try {
|
|
@@ -58110,19 +58401,19 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
58110
58401
|
} catch (mkdirError) {
|
|
58111
58402
|
if (mkdirError.code !== "EEXIST") throw mkdirError;
|
|
58112
58403
|
}
|
|
58113
|
-
|
|
58404
|
+
stat8 = await fs28.lstat(candidate);
|
|
58114
58405
|
}
|
|
58115
|
-
if (
|
|
58406
|
+
if (stat8.isSymbolicLink() || !stat8.isDirectory()) {
|
|
58116
58407
|
throw new Error(`Memory directory is not a real directory: ${candidate}`);
|
|
58117
58408
|
}
|
|
58118
58409
|
}
|
|
58119
58410
|
const canonicalDirectory = await fs28.realpath(directory);
|
|
58120
|
-
const relativeDirectory =
|
|
58121
|
-
if (relativeDirectory.startsWith("..") ||
|
|
58411
|
+
const relativeDirectory = path69.relative(resolved, canonicalDirectory);
|
|
58412
|
+
if (relativeDirectory.startsWith("..") || path69.isAbsolute(relativeDirectory)) {
|
|
58122
58413
|
throw new Error("SQLite memory directory resolves outside the active project.");
|
|
58123
58414
|
}
|
|
58124
58415
|
this.projectRoot = resolved;
|
|
58125
|
-
this.databasePath =
|
|
58416
|
+
this.databasePath = path69.join(canonicalDirectory, filename);
|
|
58126
58417
|
const opened = await this.rpc.open({
|
|
58127
58418
|
dbPath: this.databasePath,
|
|
58128
58419
|
schemaSql: SQLITE_MEMORY_BASE_SCHEMA,
|
|
@@ -58655,7 +58946,7 @@ __export(serviceFactory_exports, {
|
|
|
58655
58946
|
});
|
|
58656
58947
|
import { createHash as createHash20 } from "node:crypto";
|
|
58657
58948
|
import { promises as fs29 } from "node:fs";
|
|
58658
|
-
import * as
|
|
58949
|
+
import * as path70 from "node:path";
|
|
58659
58950
|
function isMemoryV2Enabled(env = process.env) {
|
|
58660
58951
|
if (env.ZELARI_MEMORY === "0") return false;
|
|
58661
58952
|
if (env.ZELARI_MEMORY_BACKEND === "file" || env.ZELARI_MEMORY_BACKEND === "jsonl") return false;
|
|
@@ -58676,7 +58967,7 @@ async function canonicalProjectId(projectRoot) {
|
|
|
58676
58967
|
try {
|
|
58677
58968
|
canonical = await fs29.realpath(projectRoot);
|
|
58678
58969
|
} catch {
|
|
58679
|
-
canonical =
|
|
58970
|
+
canonical = path70.resolve(projectRoot);
|
|
58680
58971
|
}
|
|
58681
58972
|
canonical = canonical.replace(/\\/g, "/").replace(/\/$/, "");
|
|
58682
58973
|
if (process.platform === "win32") canonical = canonical.toLocaleLowerCase("en-US");
|
|
@@ -59378,8 +59669,8 @@ function readPlan(ctx) {
|
|
|
59378
59669
|
} catch {
|
|
59379
59670
|
}
|
|
59380
59671
|
}
|
|
59381
|
-
const
|
|
59382
|
-
const doc = ctx.storage.readIfExists(
|
|
59672
|
+
const path100 = workspaceFile(ctx.rootDir, "plan");
|
|
59673
|
+
const doc = ctx.storage.readIfExists(path100);
|
|
59383
59674
|
if (!doc) return { phases: [], tasks: [], milestones: [] };
|
|
59384
59675
|
const meta3 = doc.meta;
|
|
59385
59676
|
return {
|
|
@@ -59560,7 +59851,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
59560
59851
|
dueDate: input.dueDate,
|
|
59561
59852
|
targetVersion: version2
|
|
59562
59853
|
});
|
|
59563
|
-
const
|
|
59854
|
+
const path100 = join31(ctx.rootDir, "milestones", `${id3}.md`);
|
|
59564
59855
|
const meta3 = {
|
|
59565
59856
|
kind: "milestone",
|
|
59566
59857
|
id: id3,
|
|
@@ -59577,7 +59868,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
59577
59868
|
`Target version: ${version2}`,
|
|
59578
59869
|
""
|
|
59579
59870
|
].join("\n");
|
|
59580
|
-
ctx.storage.write(
|
|
59871
|
+
ctx.storage.write(path100, meta3, body);
|
|
59581
59872
|
return { id: id3, created: true };
|
|
59582
59873
|
}
|
|
59583
59874
|
function readPlanSummary(ctx) {
|
|
@@ -59781,7 +60072,7 @@ function addIdeaStub(ctx) {
|
|
|
59781
60072
|
const tags = args["tags"] ?? [];
|
|
59782
60073
|
const category = args["category"] ?? "General";
|
|
59783
60074
|
const id3 = `${nextAdrId(ctx)}-${slugify3(title)}`;
|
|
59784
|
-
const
|
|
60075
|
+
const path100 = workspaceArtifact(ctx.rootDir, "decisions", id3);
|
|
59785
60076
|
const meta3 = {
|
|
59786
60077
|
kind: "adr",
|
|
59787
60078
|
status: "proposed",
|
|
@@ -59807,7 +60098,7 @@ function addIdeaStub(ctx) {
|
|
|
59807
60098
|
...consequences.map((c) => `- ${c}`),
|
|
59808
60099
|
""
|
|
59809
60100
|
].join("\n");
|
|
59810
|
-
ctx.storage.write(
|
|
60101
|
+
ctx.storage.write(path100, meta3, body);
|
|
59811
60102
|
return `ADR ${id3} created: "${title}". Status: proposed. Promote to accepted via /update ADR or manual edit.`;
|
|
59812
60103
|
});
|
|
59813
60104
|
}
|
|
@@ -59889,14 +60180,14 @@ function createDocumentStub(ctx) {
|
|
|
59889
60180
|
ctx.storage.write(risksPath, riskMeta, content);
|
|
59890
60181
|
return `Document "${title}" created at risks.md (workspace root).`;
|
|
59891
60182
|
}
|
|
59892
|
-
const
|
|
60183
|
+
const path100 = workspaceArtifact(ctx.rootDir, "docs", slug);
|
|
59893
60184
|
const meta3 = {
|
|
59894
60185
|
kind: "doc",
|
|
59895
60186
|
id: slug,
|
|
59896
60187
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
59897
60188
|
tags
|
|
59898
60189
|
};
|
|
59899
|
-
ctx.storage.write(
|
|
60190
|
+
ctx.storage.write(path100, meta3, content);
|
|
59900
60191
|
return `Document "${title}" created at docs/${slug}.md.`;
|
|
59901
60192
|
});
|
|
59902
60193
|
}
|
|
@@ -60521,10 +60812,10 @@ function getUserMcpPath() {
|
|
|
60521
60812
|
function getProjectMcpPath(projectRoot) {
|
|
60522
60813
|
return join32(projectRoot, ".zelari", "mcp.json");
|
|
60523
60814
|
}
|
|
60524
|
-
function
|
|
60525
|
-
if (!existsSync42(
|
|
60815
|
+
function readFile9(path100) {
|
|
60816
|
+
if (!existsSync42(path100)) return {};
|
|
60526
60817
|
try {
|
|
60527
|
-
const parsed = JSON.parse(readFileSync30(
|
|
60818
|
+
const parsed = JSON.parse(readFileSync30(path100, "utf8"));
|
|
60528
60819
|
const out = {};
|
|
60529
60820
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
60530
60821
|
const hasCommand = !!cfg && typeof cfg.command === "string" && !!cfg.command.trim();
|
|
@@ -60546,17 +60837,17 @@ function readFile7(path99) {
|
|
|
60546
60837
|
return {};
|
|
60547
60838
|
}
|
|
60548
60839
|
}
|
|
60549
|
-
function writeFile3(
|
|
60550
|
-
mkdirSync17(dirname9(
|
|
60840
|
+
function writeFile3(path100, servers) {
|
|
60841
|
+
mkdirSync17(dirname9(path100), { recursive: true });
|
|
60551
60842
|
const body = { mcpServers: servers };
|
|
60552
|
-
writeFileSync19(
|
|
60843
|
+
writeFileSync19(path100, `${JSON.stringify(body, null, 2)}
|
|
60553
60844
|
`, "utf8");
|
|
60554
60845
|
}
|
|
60555
60846
|
function listMcpServers(projectRoot) {
|
|
60556
60847
|
const userPath = getUserMcpPath();
|
|
60557
|
-
const userServers =
|
|
60848
|
+
const userServers = readFile9(userPath);
|
|
60558
60849
|
const projectPath = projectRoot && projectRoot.trim() ? getProjectMcpPath(projectRoot.trim()) : null;
|
|
60559
|
-
const projectServers = projectPath ?
|
|
60850
|
+
const projectServers = projectPath ? readFile9(projectPath) : {};
|
|
60560
60851
|
const servers = [];
|
|
60561
60852
|
for (const [name, cfg] of Object.entries(userServers)) {
|
|
60562
60853
|
servers.push({ name, ...cfg, scope: "user", path: userPath });
|
|
@@ -60587,9 +60878,9 @@ function upsertMcpServer(opts) {
|
|
|
60587
60878
|
error: "either command (stdio) or url (http) is required"
|
|
60588
60879
|
};
|
|
60589
60880
|
}
|
|
60590
|
-
let
|
|
60881
|
+
let path100;
|
|
60591
60882
|
if (opts.scope === "user") {
|
|
60592
|
-
|
|
60883
|
+
path100 = getUserMcpPath();
|
|
60593
60884
|
} else {
|
|
60594
60885
|
const root = opts.projectRoot?.trim();
|
|
60595
60886
|
if (!root) {
|
|
@@ -60598,9 +60889,9 @@ function upsertMcpServer(opts) {
|
|
|
60598
60889
|
error: "projectRoot required for project scope (Open Folder first)"
|
|
60599
60890
|
};
|
|
60600
60891
|
}
|
|
60601
|
-
|
|
60892
|
+
path100 = getProjectMcpPath(root);
|
|
60602
60893
|
}
|
|
60603
|
-
const current =
|
|
60894
|
+
const current = readFile9(path100);
|
|
60604
60895
|
current[name] = {
|
|
60605
60896
|
command: hasCommand ? opts.config.command.trim() : void 0,
|
|
60606
60897
|
args: opts.config.args,
|
|
@@ -60611,21 +60902,21 @@ function upsertMcpServer(opts) {
|
|
|
60611
60902
|
serial: opts.config.serial,
|
|
60612
60903
|
enabled: opts.config.enabled !== false
|
|
60613
60904
|
};
|
|
60614
|
-
writeFile3(
|
|
60615
|
-
return { ok: true, path:
|
|
60905
|
+
writeFile3(path100, current);
|
|
60906
|
+
return { ok: true, path: path100 };
|
|
60616
60907
|
}
|
|
60617
60908
|
function removeMcpServer(opts) {
|
|
60618
|
-
const
|
|
60619
|
-
if (!
|
|
60909
|
+
const path100 = opts.scope === "user" ? getUserMcpPath() : opts.projectRoot ? getProjectMcpPath(opts.projectRoot) : null;
|
|
60910
|
+
if (!path100) {
|
|
60620
60911
|
return { ok: false, error: "projectRoot required for project scope" };
|
|
60621
60912
|
}
|
|
60622
|
-
const current =
|
|
60913
|
+
const current = readFile9(path100);
|
|
60623
60914
|
if (!(opts.name in current)) {
|
|
60624
|
-
return { ok: false, error: `Server "${opts.name}" not found in ${
|
|
60915
|
+
return { ok: false, error: `Server "${opts.name}" not found in ${path100}` };
|
|
60625
60916
|
}
|
|
60626
60917
|
delete current[opts.name];
|
|
60627
|
-
writeFile3(
|
|
60628
|
-
return { ok: true, path:
|
|
60918
|
+
writeFile3(path100, current);
|
|
60919
|
+
return { ok: true, path: path100 };
|
|
60629
60920
|
}
|
|
60630
60921
|
var init_mcpConfigIo = __esm({
|
|
60631
60922
|
"src/cli/mcp/mcpConfigIo.ts"() {
|
|
@@ -61040,7 +61331,8 @@ async function* dispatchCouncil(userMessage, options) {
|
|
|
61040
61331
|
maxToolLoopIterations: options.maxToolLoopIterations,
|
|
61041
61332
|
maxToolLoopHardCap: options.maxToolLoopHardCap,
|
|
61042
61333
|
skipSpecialists: options.skipSpecialists,
|
|
61043
|
-
feedbackStore: options.feedbackStore
|
|
61334
|
+
feedbackStore: options.feedbackStore,
|
|
61335
|
+
signal: options.signal
|
|
61044
61336
|
};
|
|
61045
61337
|
if (!options.disableWorkspaceTools) {
|
|
61046
61338
|
const { setWorkspaceStubs: setWorkspaceStubs2 } = await Promise.resolve().then(() => (init_skills2(), skills_exports));
|
|
@@ -61093,12 +61385,12 @@ __export(agentsMd_exports, {
|
|
|
61093
61385
|
import { existsSync as existsSync44, readFileSync as readFileSync32, writeFileSync as writeFileSync20 } from "node:fs";
|
|
61094
61386
|
import { createHash as createHash21 } from "node:crypto";
|
|
61095
61387
|
import { join as join34 } from "node:path";
|
|
61096
|
-
import { readFile as
|
|
61388
|
+
import { readFile as readFile10 } from "node:fs/promises";
|
|
61097
61389
|
async function readPackageJson3(projectRoot) {
|
|
61098
|
-
const
|
|
61099
|
-
if (!existsSync44(
|
|
61390
|
+
const path100 = join34(projectRoot, "package.json");
|
|
61391
|
+
if (!existsSync44(path100)) return null;
|
|
61100
61392
|
try {
|
|
61101
|
-
return JSON.parse(await
|
|
61393
|
+
return JSON.parse(await readFile10(path100, "utf8"));
|
|
61102
61394
|
} catch {
|
|
61103
61395
|
return null;
|
|
61104
61396
|
}
|
|
@@ -61180,9 +61472,9 @@ async function genBuild(ctx) {
|
|
|
61180
61472
|
].join("\n");
|
|
61181
61473
|
}
|
|
61182
61474
|
async function genOpenQuestions(ctx) {
|
|
61183
|
-
const
|
|
61184
|
-
if (!existsSync44(
|
|
61185
|
-
const content = readFileSync32(
|
|
61475
|
+
const path100 = join34(ctx.rootDir, "risks.md");
|
|
61476
|
+
if (!existsSync44(path100)) return "_No open questions._";
|
|
61477
|
+
const content = readFileSync32(path100, "utf8");
|
|
61186
61478
|
const lines = content.split("\n");
|
|
61187
61479
|
const questions = [];
|
|
61188
61480
|
let currentTitle = "";
|
|
@@ -61456,9 +61748,9 @@ function versionKey(value) {
|
|
|
61456
61748
|
function firstString2(v) {
|
|
61457
61749
|
return typeof v === "string" && v.trim().length > 0 ? v : null;
|
|
61458
61750
|
}
|
|
61459
|
-
function readFileSyncSafe(
|
|
61751
|
+
function readFileSyncSafe(path100) {
|
|
61460
61752
|
try {
|
|
61461
|
-
return readFileSync33(
|
|
61753
|
+
return readFileSync33(path100, "utf8");
|
|
61462
61754
|
} catch {
|
|
61463
61755
|
return null;
|
|
61464
61756
|
}
|
|
@@ -61706,7 +61998,7 @@ __export(evidenceFromSpine_exports, {
|
|
|
61706
61998
|
evidenceRefsFromEventLines: () => evidenceRefsFromEventLines
|
|
61707
61999
|
});
|
|
61708
62000
|
import { existsSync as existsSync47, readFileSync as readFileSync35 } from "node:fs";
|
|
61709
|
-
import
|
|
62001
|
+
import path71 from "node:path";
|
|
61710
62002
|
function asRecord2(v) {
|
|
61711
62003
|
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
61712
62004
|
}
|
|
@@ -61744,7 +62036,7 @@ function evidenceRefsFromEventLines(lines) {
|
|
|
61744
62036
|
}
|
|
61745
62037
|
function collectSessionEvidenceRefs(sessionId2) {
|
|
61746
62038
|
try {
|
|
61747
|
-
const file2 =
|
|
62039
|
+
const file2 = path71.join(sessionsDir(), sessionId2, "events.jsonl");
|
|
61748
62040
|
if (!existsSync47(file2)) return [];
|
|
61749
62041
|
return evidenceRefsFromEventLines(readFileSync35(file2, "utf8").split("\n"));
|
|
61750
62042
|
} catch {
|
|
@@ -61994,8 +62286,8 @@ async function runPostCouncilHook(ctx, options) {
|
|
|
61994
62286
|
sources: scope.sources
|
|
61995
62287
|
} : void 0
|
|
61996
62288
|
});
|
|
61997
|
-
const
|
|
61998
|
-
completionHook = { ran: true, path:
|
|
62289
|
+
const path100 = writeCouncilCompletion(ctx.rootDir, completion);
|
|
62290
|
+
completionHook = { ran: true, path: path100, completion };
|
|
61999
62291
|
} catch (err) {
|
|
62000
62292
|
completionHook = {
|
|
62001
62293
|
ran: true,
|
|
@@ -62040,7 +62332,7 @@ import {
|
|
|
62040
62332
|
writeFileSync as writeFileSync22,
|
|
62041
62333
|
mkdirSync as mkdirSync18
|
|
62042
62334
|
} from "node:fs";
|
|
62043
|
-
import
|
|
62335
|
+
import path72 from "node:path";
|
|
62044
62336
|
var FeedbackStore;
|
|
62045
62337
|
var init_councilFeedback = __esm({
|
|
62046
62338
|
"src/cli/councilFeedback.ts"() {
|
|
@@ -62157,7 +62449,7 @@ var init_councilFeedback = __esm({
|
|
|
62157
62449
|
}
|
|
62158
62450
|
}
|
|
62159
62451
|
save() {
|
|
62160
|
-
mkdirSync18(
|
|
62452
|
+
mkdirSync18(path72.dirname(this.file), { recursive: true });
|
|
62161
62453
|
writeFileSync22(
|
|
62162
62454
|
this.file,
|
|
62163
62455
|
JSON.stringify({ entries: this.entries }, null, 2),
|
|
@@ -62232,12 +62524,12 @@ __export(ledger_exports, {
|
|
|
62232
62524
|
readLedger: () => readLedger
|
|
62233
62525
|
});
|
|
62234
62526
|
import { appendFileSync as appendFileSync4, existsSync as existsSync50, mkdirSync as mkdirSync19, readFileSync as readFileSync38 } from "node:fs";
|
|
62235
|
-
import
|
|
62527
|
+
import path73 from "node:path";
|
|
62236
62528
|
function evolutionMode(env = process.env) {
|
|
62237
62529
|
return env[EVOLUTION_ENV] === "shadow" ? "shadow" : "0";
|
|
62238
62530
|
}
|
|
62239
62531
|
function ledgerPath(cwd) {
|
|
62240
|
-
return
|
|
62532
|
+
return path73.join(cwd, LEDGER_REL);
|
|
62241
62533
|
}
|
|
62242
62534
|
function appendLedgerEntry(cwd, entry) {
|
|
62243
62535
|
if (evolutionMode() === "0") {
|
|
@@ -62245,7 +62537,7 @@ function appendLedgerEntry(cwd, entry) {
|
|
|
62245
62537
|
}
|
|
62246
62538
|
try {
|
|
62247
62539
|
const file2 = ledgerPath(cwd);
|
|
62248
|
-
mkdirSync19(
|
|
62540
|
+
mkdirSync19(path73.dirname(file2), { recursive: true });
|
|
62249
62541
|
appendFileSync4(file2, `${JSON.stringify(entry)}
|
|
62250
62542
|
`, "utf8");
|
|
62251
62543
|
return { written: true, path: file2 };
|
|
@@ -62346,7 +62638,7 @@ var init_ledger = __esm({
|
|
|
62346
62638
|
"src/cli/evolution/ledger.ts"() {
|
|
62347
62639
|
"use strict";
|
|
62348
62640
|
EVOLUTION_ENV = "ZELARI_EVOLUTION";
|
|
62349
|
-
LEDGER_REL =
|
|
62641
|
+
LEDGER_REL = path73.join(".zelari", "evolution", "ledger.jsonl");
|
|
62350
62642
|
TIER_WEIGHTS = {
|
|
62351
62643
|
build: 1,
|
|
62352
62644
|
"tool-output": 1,
|
|
@@ -62488,7 +62780,7 @@ __export(fileBackend_exports, {
|
|
|
62488
62780
|
});
|
|
62489
62781
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
62490
62782
|
import { promises as fs31 } from "node:fs";
|
|
62491
|
-
import * as
|
|
62783
|
+
import * as path74 from "node:path";
|
|
62492
62784
|
function tokenize2(text) {
|
|
62493
62785
|
return text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 3);
|
|
62494
62786
|
}
|
|
@@ -62541,8 +62833,8 @@ var init_fileBackend = __esm({
|
|
|
62541
62833
|
logPath = "";
|
|
62542
62834
|
memoryDir = "";
|
|
62543
62835
|
async init(projectRoot) {
|
|
62544
|
-
this.memoryDir =
|
|
62545
|
-
this.logPath =
|
|
62836
|
+
this.memoryDir = path74.join(projectRoot, ".zelari", "memory");
|
|
62837
|
+
this.logPath = path74.join(this.memoryDir, "log.jsonl");
|
|
62546
62838
|
await fs31.mkdir(this.memoryDir, { recursive: true });
|
|
62547
62839
|
}
|
|
62548
62840
|
async add(content, metadata2 = {}, graph) {
|
|
@@ -62615,12 +62907,12 @@ var init_fileBackend = __esm({
|
|
|
62615
62907
|
|
|
62616
62908
|
// src/cli/traceStore.ts
|
|
62617
62909
|
import { promises as fs32 } from "node:fs";
|
|
62618
|
-
import * as
|
|
62910
|
+
import * as path75 from "node:path";
|
|
62619
62911
|
function traceDir(projectRoot) {
|
|
62620
|
-
return
|
|
62912
|
+
return path75.join(projectRoot, ".zelari", "trace");
|
|
62621
62913
|
}
|
|
62622
62914
|
function tracePath(projectRoot, missionId) {
|
|
62623
|
-
return
|
|
62915
|
+
return path75.join(traceDir(projectRoot), `${missionId}.json`);
|
|
62624
62916
|
}
|
|
62625
62917
|
async function saveTrace(projectRoot, missionId, entries) {
|
|
62626
62918
|
const dir = traceDir(projectRoot);
|
|
@@ -62657,7 +62949,7 @@ __export(zelariMission_exports, {
|
|
|
62657
62949
|
});
|
|
62658
62950
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
62659
62951
|
import { promises as fs33 } from "node:fs";
|
|
62660
|
-
import * as
|
|
62952
|
+
import * as path76 from "node:path";
|
|
62661
62953
|
function resolveMaxIterations(env = process.env) {
|
|
62662
62954
|
const raw = env.ZELARI_MISSION_MAX_ITER;
|
|
62663
62955
|
const n = raw ? Number.parseInt(raw, 10) : DEFAULT_MAX_ITER;
|
|
@@ -62700,10 +62992,10 @@ function isMissionAutoStart(env = process.env) {
|
|
|
62700
62992
|
return env.ZELARI_MISSION_AUTO === "1";
|
|
62701
62993
|
}
|
|
62702
62994
|
async function writeMissionState(projectRoot, state3) {
|
|
62703
|
-
const dir =
|
|
62995
|
+
const dir = path76.join(projectRoot, ".zelari");
|
|
62704
62996
|
await fs33.mkdir(dir, { recursive: true });
|
|
62705
62997
|
await fs33.writeFile(
|
|
62706
|
-
|
|
62998
|
+
path76.join(dir, "mission-state.json"),
|
|
62707
62999
|
JSON.stringify(state3, null, 2) + "\n",
|
|
62708
63000
|
"utf8"
|
|
62709
63001
|
);
|
|
@@ -62798,6 +63090,13 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
62798
63090
|
let forcePivot = false;
|
|
62799
63091
|
const missionStartMs = now().getTime();
|
|
62800
63092
|
while (true) {
|
|
63093
|
+
if (deps.signal?.aborted) {
|
|
63094
|
+
state3.status = "cancelled";
|
|
63095
|
+
state3.updatedAt = now().toISOString();
|
|
63096
|
+
await persist();
|
|
63097
|
+
deps.emit("[zelari] missione cancellata.");
|
|
63098
|
+
return state3;
|
|
63099
|
+
}
|
|
62801
63100
|
const runMode = pendingDesign ? "design-phase" : "implementation";
|
|
62802
63101
|
if (runMode === "implementation") {
|
|
62803
63102
|
deps.onMissionPhase?.("build", `impl-${implStep + 1}`);
|
|
@@ -62854,6 +63153,13 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
62854
63153
|
);
|
|
62855
63154
|
return state3;
|
|
62856
63155
|
}
|
|
63156
|
+
if (deps.signal?.aborted) {
|
|
63157
|
+
state3.status = "cancelled";
|
|
63158
|
+
state3.updatedAt = now().toISOString();
|
|
63159
|
+
await persist();
|
|
63160
|
+
deps.emit("[zelari] missione cancellata.");
|
|
63161
|
+
return state3;
|
|
63162
|
+
}
|
|
62857
63163
|
if (typeof result.costUsd === "number") cumulativeCostUsd += result.costUsd;
|
|
62858
63164
|
if (typeof result.costTokens === "number") cumulativeTokens += result.costTokens;
|
|
62859
63165
|
await deps.memory.add(
|
|
@@ -63378,7 +63684,7 @@ function safeSocketPath(socketPath) {
|
|
|
63378
63684
|
return socketPath.trim();
|
|
63379
63685
|
}
|
|
63380
63686
|
function startPermissionBroker(socketPath, handlers, opts) {
|
|
63381
|
-
const
|
|
63687
|
+
const path100 = safeSocketPath(socketPath);
|
|
63382
63688
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
63383
63689
|
const sockets = /* @__PURE__ */ new Set();
|
|
63384
63690
|
const server = createServer2((socket) => {
|
|
@@ -63478,10 +63784,10 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
63478
63784
|
return new Promise((resolve9, reject) => {
|
|
63479
63785
|
const onError = (err) => reject(err);
|
|
63480
63786
|
server.once("error", onError);
|
|
63481
|
-
server.listen(
|
|
63787
|
+
server.listen(path100, () => {
|
|
63482
63788
|
server.removeListener("error", onError);
|
|
63483
63789
|
resolve9({
|
|
63484
|
-
socketPath:
|
|
63790
|
+
socketPath: path100,
|
|
63485
63791
|
stop: () => new Promise((res) => {
|
|
63486
63792
|
for (const s of sockets) s.destroy();
|
|
63487
63793
|
sockets.clear();
|
|
@@ -63492,7 +63798,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
63492
63798
|
if (done) return;
|
|
63493
63799
|
done = true;
|
|
63494
63800
|
if (process.platform !== "win32") {
|
|
63495
|
-
unlink(
|
|
63801
|
+
unlink(path100, () => res());
|
|
63496
63802
|
} else {
|
|
63497
63803
|
res();
|
|
63498
63804
|
}
|
|
@@ -63505,11 +63811,11 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
63505
63811
|
});
|
|
63506
63812
|
}
|
|
63507
63813
|
function requestBrokerAsk(socketPath, ask, opts) {
|
|
63508
|
-
const
|
|
63814
|
+
const path100 = safeSocketPath(socketPath);
|
|
63509
63815
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
63510
63816
|
const connectTimeoutMs = opts?.connectTimeoutMs ?? PERMISSION_BROKER_DEFAULT_CONNECT_TIMEOUT_MS;
|
|
63511
63817
|
return new Promise((resolve9, reject) => {
|
|
63512
|
-
const socket = connect(
|
|
63818
|
+
const socket = connect(path100);
|
|
63513
63819
|
let buffer = "";
|
|
63514
63820
|
let settled = false;
|
|
63515
63821
|
const settle = (fn) => {
|
|
@@ -63524,7 +63830,7 @@ function requestBrokerAsk(socketPath, ask, opts) {
|
|
|
63524
63830
|
settle(
|
|
63525
63831
|
() => reject(
|
|
63526
63832
|
new Error(
|
|
63527
|
-
`permission broker unavailable at "${
|
|
63833
|
+
`permission broker unavailable at "${path100}" (connect timed out after ${connectTimeoutMs}ms)`
|
|
63528
63834
|
)
|
|
63529
63835
|
)
|
|
63530
63836
|
);
|
|
@@ -64713,7 +65019,7 @@ var init_prereqChecks = __esm({
|
|
|
64713
65019
|
|
|
64714
65020
|
// src/cli/plugins/prefs.ts
|
|
64715
65021
|
import { existsSync as existsSync53, readFileSync as readFileSync40, writeFileSync as writeFileSync23, mkdirSync as mkdirSync20 } from "node:fs";
|
|
64716
|
-
import
|
|
65022
|
+
import path82 from "node:path";
|
|
64717
65023
|
function getPluginPrefsPath() {
|
|
64718
65024
|
return pluginsPrefsPath();
|
|
64719
65025
|
}
|
|
@@ -64736,7 +65042,7 @@ function getPluginPrefs() {
|
|
|
64736
65042
|
}
|
|
64737
65043
|
function writePluginPrefs(prefs) {
|
|
64738
65044
|
const file2 = getPluginPrefsPath();
|
|
64739
|
-
mkdirSync20(
|
|
65045
|
+
mkdirSync20(path82.dirname(file2), { recursive: true });
|
|
64740
65046
|
writeFileSync23(file2, JSON.stringify(prefs, null, 2), {
|
|
64741
65047
|
encoding: "utf-8",
|
|
64742
65048
|
mode: 384
|
|
@@ -64774,7 +65080,7 @@ __export(registry_exports, {
|
|
|
64774
65080
|
isBinaryOnPath: () => isBinaryOnPath
|
|
64775
65081
|
});
|
|
64776
65082
|
import { existsSync as existsSync54 } from "node:fs";
|
|
64777
|
-
import
|
|
65083
|
+
import path83 from "node:path";
|
|
64778
65084
|
function detectLocalBin(bin) {
|
|
64779
65085
|
return (cwd) => {
|
|
64780
65086
|
try {
|
|
@@ -64792,7 +65098,7 @@ function isBinaryOnPath(bin, opts = {}) {
|
|
|
64792
65098
|
const platform = opts.platform ?? process.platform;
|
|
64793
65099
|
const exists = opts.exists ?? existsSync54;
|
|
64794
65100
|
const pathEnv = opts.pathEnv ?? process.env.PATH ?? "";
|
|
64795
|
-
const pathMod = platform === "win32" ?
|
|
65101
|
+
const pathMod = platform === "win32" ? path83.win32 : path83.posix;
|
|
64796
65102
|
const sep4 = platform === "win32" ? ";" : ":";
|
|
64797
65103
|
const dirs = pathEnv.split(sep4).filter((d) => d.length > 0);
|
|
64798
65104
|
const candidates = [bin];
|
|
@@ -65887,7 +66193,7 @@ var init_policy = __esm({
|
|
|
65887
66193
|
|
|
65888
66194
|
// src/cli/orchestration/facts.ts
|
|
65889
66195
|
import { promises as fs43 } from "node:fs";
|
|
65890
|
-
import
|
|
66196
|
+
import path87 from "node:path";
|
|
65891
66197
|
async function collectRepoFileCount(root = process.cwd()) {
|
|
65892
66198
|
try {
|
|
65893
66199
|
await fs43.readdir(root);
|
|
@@ -65907,7 +66213,7 @@ async function collectRepoFileCount(root = process.cwd()) {
|
|
|
65907
66213
|
}
|
|
65908
66214
|
for (const e of entries) {
|
|
65909
66215
|
if (e.isDirectory()) {
|
|
65910
|
-
if (!SKIP_DIRS.has(e.name)) queue.push(
|
|
66216
|
+
if (!SKIP_DIRS.has(e.name)) queue.push(path87.join(dir, e.name));
|
|
65911
66217
|
} else if (e.isFile()) {
|
|
65912
66218
|
count++;
|
|
65913
66219
|
if (count > MAX_WALK_FILES) return count;
|
|
@@ -65972,11 +66278,12 @@ var init_facts = __esm({
|
|
|
65972
66278
|
});
|
|
65973
66279
|
|
|
65974
66280
|
// src/cli/utils/streamScrub.ts
|
|
65975
|
-
function createStreamScrubber2() {
|
|
66281
|
+
function createStreamScrubber2(opts = {}) {
|
|
66282
|
+
const stripQuestion = opts.stripQuestion !== false;
|
|
65976
66283
|
let rawBuf = "";
|
|
65977
66284
|
let emittedLen = 0;
|
|
65978
66285
|
const snapshot = () => {
|
|
65979
|
-
const cleaned = cleanAgentContent(rawBuf);
|
|
66286
|
+
const cleaned = cleanAgentContent(rawBuf, { stripQuestion });
|
|
65980
66287
|
if (cleaned.length <= emittedLen) return "";
|
|
65981
66288
|
const delta = cleaned.slice(emittedLen);
|
|
65982
66289
|
emittedLen = cleaned.length;
|
|
@@ -66004,7 +66311,7 @@ var init_streamScrub = __esm({
|
|
|
66004
66311
|
});
|
|
66005
66312
|
|
|
66006
66313
|
// src/cli/harnessState.ts
|
|
66007
|
-
import
|
|
66314
|
+
import path88 from "node:path";
|
|
66008
66315
|
function asString4(v) {
|
|
66009
66316
|
return typeof v === "string" ? v : "";
|
|
66010
66317
|
}
|
|
@@ -66179,7 +66486,7 @@ function contractFor(t) {
|
|
|
66179
66486
|
};
|
|
66180
66487
|
}
|
|
66181
66488
|
async function readHarnessState(sessionDir) {
|
|
66182
|
-
const report = await readSessionLog(
|
|
66489
|
+
const report = await readSessionLog(path88.join(sessionDir, "events.jsonl"));
|
|
66183
66490
|
return deriveHarnessState(report.events);
|
|
66184
66491
|
}
|
|
66185
66492
|
var init_harnessState = __esm({
|
|
@@ -66190,12 +66497,12 @@ var init_harnessState = __esm({
|
|
|
66190
66497
|
});
|
|
66191
66498
|
|
|
66192
66499
|
// src/cli/headless/harnessStateEmit.ts
|
|
66193
|
-
import
|
|
66500
|
+
import path89 from "node:path";
|
|
66194
66501
|
async function emitHarnessStateEvent(opts) {
|
|
66195
66502
|
if (opts.output !== "json") return;
|
|
66196
66503
|
try {
|
|
66197
66504
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.workspaceRoot });
|
|
66198
|
-
const state3 = await readHarnessState(
|
|
66505
|
+
const state3 = await readHarnessState(path89.join(sessionsDir2, opts.spine.sessionId));
|
|
66199
66506
|
opts.emitEvent({ type: "harness_state", ...state3 });
|
|
66200
66507
|
} catch (err) {
|
|
66201
66508
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -66214,215 +66521,39 @@ var init_harnessStateEmit = __esm({
|
|
|
66214
66521
|
}
|
|
66215
66522
|
});
|
|
66216
66523
|
|
|
66217
|
-
// src/cli/
|
|
66218
|
-
import {
|
|
66219
|
-
|
|
66220
|
-
|
|
66221
|
-
if (isPolicyEngineDisabled()) return { blocked: false, warnings: [] };
|
|
66222
|
-
try {
|
|
66223
|
-
const set2 = loadPolicySet(root, opts);
|
|
66224
|
-
return { blocked: false, warnings: set2.warnings };
|
|
66225
|
-
} catch (err) {
|
|
66226
|
-
if (!(err instanceof PolicyLoadError)) throw err;
|
|
66227
|
-
const file2 = isAbsolute5(err.file) ? err.file : resolve7(root, err.file);
|
|
66228
|
-
return {
|
|
66229
|
-
blocked: true,
|
|
66230
|
-
warnings: [],
|
|
66231
|
-
block: {
|
|
66232
|
-
reason: POLICY_LOAD_BLOCK_REASON,
|
|
66233
|
-
exitCode: POLICY_LOAD_EXIT_CODE,
|
|
66234
|
-
code: err.code,
|
|
66235
|
-
file: file2,
|
|
66236
|
-
...err.message ? { detail: err.message } : {}
|
|
66237
|
-
}
|
|
66238
|
-
};
|
|
66239
|
-
}
|
|
66240
|
-
}
|
|
66241
|
-
function reportPolicyLoadBlocked(block, output) {
|
|
66242
|
-
const where = `${block.file}${block.detail ? ` \u2014 ${block.detail}` : ""}`;
|
|
66243
|
-
process.stderr.write(`[zelari-code --headless] ${block.reason}: ${where}
|
|
66244
|
-
`);
|
|
66245
|
-
if (output === "json") {
|
|
66246
|
-
emitEvent({
|
|
66247
|
-
type: "error",
|
|
66248
|
-
severity: "fatal",
|
|
66249
|
-
message: `${block.reason}: ${where}`,
|
|
66250
|
-
code: block.reason
|
|
66251
|
-
});
|
|
66252
|
-
}
|
|
66253
|
-
}
|
|
66254
|
-
async function recordPolicyLoadBlockedOnSpine(block, opts = {}) {
|
|
66255
|
-
try {
|
|
66256
|
-
const { openHeadlessSpine: openHeadlessSpine2 } = await Promise.resolve().then(() => (init_headlessSpine(), headlessSpine_exports));
|
|
66257
|
-
const sessionId2 = opts.resumeSessionId ?? randomUUID9();
|
|
66258
|
-
const spine = await openHeadlessSpine2({
|
|
66259
|
-
sessionId: sessionId2,
|
|
66260
|
-
...opts.mode ? { mode: opts.mode } : {},
|
|
66261
|
-
...opts.profile ? { profile: opts.profile } : {},
|
|
66262
|
-
workspace: opts.workspace ?? process.cwd()
|
|
66263
|
-
});
|
|
66264
|
-
if (opts.mode === "zelari") {
|
|
66265
|
-
spine.missionPhase("dispatch", block.reason);
|
|
66266
|
-
}
|
|
66267
|
-
spine.note(block.reason, {
|
|
66268
|
-
code: block.code,
|
|
66269
|
-
file: block.file,
|
|
66270
|
-
exitCode: block.exitCode,
|
|
66271
|
-
...block.detail ? { detail: block.detail } : {}
|
|
66272
|
-
});
|
|
66273
|
-
await spine.close("error");
|
|
66274
|
-
} catch {
|
|
66275
|
-
}
|
|
66276
|
-
}
|
|
66277
|
-
var init_policyGate = __esm({
|
|
66278
|
-
"src/cli/headless/policyGate.ts"() {
|
|
66279
|
-
"use strict";
|
|
66280
|
-
init_policyEngine();
|
|
66281
|
-
init_policyLoadMode();
|
|
66282
|
-
init_headless();
|
|
66283
|
-
}
|
|
66284
|
-
});
|
|
66285
|
-
|
|
66286
|
-
// src/cli/kraken/verifierResolution.ts
|
|
66287
|
-
function verifierOverrideToModelSelection(override) {
|
|
66288
|
-
if (override && typeof override.provider === "string" && typeof override.model === "string" && override.provider.trim().length > 0 && override.model.trim().length > 0) {
|
|
66289
|
-
return {
|
|
66290
|
-
mode: "fixed",
|
|
66291
|
-
provider: override.provider.trim(),
|
|
66292
|
-
model: override.model.trim()
|
|
66293
|
-
};
|
|
66294
|
-
}
|
|
66295
|
-
return { mode: "inherit" };
|
|
66296
|
-
}
|
|
66297
|
-
function loadVerifierModelSelection() {
|
|
66298
|
-
return verifierOverrideToModelSelection(getKrakenVerifierOverride());
|
|
66299
|
-
}
|
|
66300
|
-
var init_verifierResolution = __esm({
|
|
66301
|
-
"src/cli/kraken/verifierResolution.ts"() {
|
|
66302
|
-
"use strict";
|
|
66303
|
-
init_providerConfig();
|
|
66304
|
-
}
|
|
66305
|
-
});
|
|
66306
|
-
|
|
66307
|
-
// src/cli/kraken/verifierLifecycle.ts
|
|
66308
|
-
function verifierReviewEnabled(selection = loadVerifierModelSelection(), env = process.env) {
|
|
66309
|
-
const v = env.ZELARI_VERIFIER_REVIEW?.toLowerCase();
|
|
66310
|
-
if (v === "0" || v === "false" || v === "off") return false;
|
|
66311
|
-
if (v === "1" || v === "true" || v === "on") return true;
|
|
66312
|
-
return selection.mode === "fixed";
|
|
66524
|
+
// src/cli/serve/sessionControl.ts
|
|
66525
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
66526
|
+
function runWithSession(sessionId2, fn) {
|
|
66527
|
+
return dispatchContext.run({ sessionId: sessionId2, token: {} }, fn);
|
|
66313
66528
|
}
|
|
66314
|
-
function
|
|
66315
|
-
|
|
66316
|
-
|
|
66317
|
-
|
|
66318
|
-
|
|
66529
|
+
function registerLiveTurnControl(control) {
|
|
66530
|
+
const store6 = dispatchContext.getStore();
|
|
66531
|
+
if (!store6) return void 0;
|
|
66532
|
+
const registered = { ...control, token: store6.token };
|
|
66533
|
+
liveTurns.set(store6.sessionId, registered);
|
|
66534
|
+
return () => {
|
|
66535
|
+
if (liveTurns.get(store6.sessionId) === registered) {
|
|
66536
|
+
liveTurns.delete(store6.sessionId);
|
|
66319
66537
|
}
|
|
66320
|
-
const { text } = await collectProviderText(stream, {
|
|
66321
|
-
messages: [
|
|
66322
|
-
{ role: "system", content: system },
|
|
66323
|
-
{ role: "user", content: user }
|
|
66324
|
-
],
|
|
66325
|
-
model: identity.model,
|
|
66326
|
-
provider: identity.provider,
|
|
66327
|
-
tools: [],
|
|
66328
|
-
signal: AbortSignal.timeout(timeoutMs2)
|
|
66329
|
-
});
|
|
66330
|
-
return { text, provider: identity.provider, model: identity.model };
|
|
66331
66538
|
};
|
|
66332
66539
|
}
|
|
66333
|
-
function
|
|
66334
|
-
|
|
66335
|
-
return ["test", "typecheck", "build", "lint"].some((k) => id3.includes(k));
|
|
66336
|
-
}
|
|
66337
|
-
function extractTestOutputExcerpt(results, maxChars = 4e3) {
|
|
66338
|
-
const lines = [];
|
|
66339
|
-
for (const r of results) {
|
|
66340
|
-
if (!isTestEvidenceCriterion(r.criterionId)) continue;
|
|
66341
|
-
lines.push([r.criterionId, r.status, r.detail].filter(Boolean).join(" \u2014 "));
|
|
66342
|
-
}
|
|
66343
|
-
if (lines.length === 0) return "";
|
|
66344
|
-
return lines.join("\n").slice(0, maxChars);
|
|
66345
|
-
}
|
|
66346
|
-
async function buildBlindReviewInput(evaluation, deps) {
|
|
66347
|
-
const results = evaluation.results ?? [];
|
|
66348
|
-
const passed = results.filter((r) => r.status === "pass").length;
|
|
66349
|
-
const verdict = evaluation.evaluation?.verdict ?? "UNKNOWN";
|
|
66350
|
-
const summary = `Kraken BUILD turn \u2014 deterministic evidence: ${passed}/${results.length} criteria pass, completion verdict ${verdict}.`;
|
|
66351
|
-
const task = deps.task?.trim();
|
|
66352
|
-
const testOutputExcerpt = extractTestOutputExcerpt(results);
|
|
66353
|
-
let diffSummary;
|
|
66354
|
-
try {
|
|
66355
|
-
const res = await (deps.getDiff ?? getWorkingDiff)({
|
|
66356
|
-
cwd: deps.cwd ?? process.cwd(),
|
|
66357
|
-
maxChars: 8e3,
|
|
66358
|
-
staged: true
|
|
66359
|
-
});
|
|
66360
|
-
if (res && !res.empty && res.diff) diffSummary = res.diff;
|
|
66361
|
-
} catch {
|
|
66362
|
-
}
|
|
66363
|
-
return {
|
|
66364
|
-
...task ? { task } : {},
|
|
66365
|
-
summary,
|
|
66366
|
-
...diffSummary !== void 0 ? { diffSummary } : {},
|
|
66367
|
-
...testOutputExcerpt ? { testOutputExcerpt } : {},
|
|
66368
|
-
results
|
|
66369
|
-
};
|
|
66540
|
+
function getLiveTurnControl(sessionId2) {
|
|
66541
|
+
return liveTurns.get(sessionId2);
|
|
66370
66542
|
}
|
|
66371
|
-
|
|
66372
|
-
|
|
66373
|
-
|
|
66374
|
-
const
|
|
66375
|
-
if (
|
|
66376
|
-
|
|
66377
|
-
if (risk === "low") return null;
|
|
66378
|
-
const route = resolveVerifierRouting(
|
|
66379
|
-
selection.mode === "fixed" ? { provider: selection.provider, model: selection.model } : null,
|
|
66380
|
-
risk,
|
|
66381
|
-
{
|
|
66382
|
-
selectionMode: selection.mode === "fixed" ? "fixed" : "inherit",
|
|
66383
|
-
session: deps.session ?? null,
|
|
66384
|
-
familyCandidates: deps.familyCandidates,
|
|
66385
|
-
env
|
|
66386
|
-
}
|
|
66387
|
-
);
|
|
66388
|
-
const reviewers = route.reviewers;
|
|
66389
|
-
let callModel = deps.callModel;
|
|
66390
|
-
if (reviewers.length === 0 || !callModel && !deps.loadStream) return null;
|
|
66391
|
-
const blind = await buildBlindReviewInput(evaluation, deps);
|
|
66392
|
-
const reviews = [];
|
|
66393
|
-
for (const reviewer of reviewers) {
|
|
66394
|
-
const call = callModel ?? makeVerifierCallModel(deps.loadStream, reviewer.identity, deps.timeoutMs);
|
|
66395
|
-
const service = new VerifierService({
|
|
66396
|
-
callModel: call,
|
|
66397
|
-
config: {
|
|
66398
|
-
enabled: true,
|
|
66399
|
-
model: selection,
|
|
66400
|
-
progressScoring: false,
|
|
66401
|
-
bon: { enabled: false, n: 3 }
|
|
66402
|
-
},
|
|
66403
|
-
emit: deps.emit,
|
|
66404
|
-
env
|
|
66405
|
-
});
|
|
66406
|
-
reviews.push(await service.reviewCompletion({ ...blind, session: deps.session }));
|
|
66407
|
-
}
|
|
66408
|
-
const review = reviews.length > 1 ? mergeVerifierVerdicts(reviews) : reviews[0];
|
|
66409
|
-
evaluation.review = review;
|
|
66410
|
-
if (reviews.length > 1 && risk === "critical") {
|
|
66411
|
-
evaluation.reviewDivergence = divergenceFromReviews(
|
|
66412
|
-
reviews,
|
|
66413
|
-
reviewers.map((r) => ({ family: r.family, role: r.role }))
|
|
66414
|
-
);
|
|
66543
|
+
function clearSessionTurnControl(sessionId2) {
|
|
66544
|
+
const store6 = dispatchContext.getStore();
|
|
66545
|
+
if (!store6 || store6.sessionId !== sessionId2) return;
|
|
66546
|
+
const registered = liveTurns.get(sessionId2);
|
|
66547
|
+
if (registered && registered.token === store6.token) {
|
|
66548
|
+
liveTurns.delete(sessionId2);
|
|
66415
66549
|
}
|
|
66416
|
-
return review;
|
|
66417
66550
|
}
|
|
66418
|
-
var
|
|
66419
|
-
|
|
66551
|
+
var dispatchContext, liveTurns;
|
|
66552
|
+
var init_sessionControl = __esm({
|
|
66553
|
+
"src/cli/serve/sessionControl.ts"() {
|
|
66420
66554
|
"use strict";
|
|
66421
|
-
|
|
66422
|
-
|
|
66423
|
-
init_gitOps();
|
|
66424
|
-
init_verifierResolution();
|
|
66425
|
-
init_verifierRouting();
|
|
66555
|
+
dispatchContext = new AsyncLocalStorage();
|
|
66556
|
+
liveTurns = /* @__PURE__ */ new Map();
|
|
66426
66557
|
}
|
|
66427
66558
|
});
|
|
66428
66559
|
|
|
@@ -66652,51 +66783,289 @@ var init_controlBridge = __esm({
|
|
|
66652
66783
|
}
|
|
66653
66784
|
});
|
|
66654
66785
|
|
|
66655
|
-
// src/cli/
|
|
66656
|
-
|
|
66657
|
-
|
|
66658
|
-
|
|
66786
|
+
// src/cli/headless/liveTurnAbort.ts
|
|
66787
|
+
function attachHeadlessLiveCancel(opts) {
|
|
66788
|
+
const abort = new AbortController();
|
|
66789
|
+
const controlQueue = new RuntimeControlQueue();
|
|
66790
|
+
const cancel = () => {
|
|
66791
|
+
if (!abort.signal.aborted) abort.abort();
|
|
66792
|
+
return true;
|
|
66793
|
+
};
|
|
66794
|
+
const controlPlane = opts?.output === "json" && process.stdin.isTTY !== true && process.env.ZELARI_SERVE_HARNESS !== "1" ? (() => {
|
|
66795
|
+
emitEvent(protocolInfoEvent());
|
|
66796
|
+
return attachControlPlane({
|
|
66797
|
+
input: process.stdin,
|
|
66798
|
+
queue: controlQueue,
|
|
66799
|
+
emit: emitEvent,
|
|
66800
|
+
onCancel: () => {
|
|
66801
|
+
cancel();
|
|
66802
|
+
}
|
|
66803
|
+
});
|
|
66804
|
+
})() : void 0;
|
|
66805
|
+
const unregister = process.env.ZELARI_SERVE_HARNESS === "1" ? registerLiveTurnControl({
|
|
66806
|
+
queue: controlQueue,
|
|
66807
|
+
cancel
|
|
66808
|
+
}) : void 0;
|
|
66809
|
+
if (unregister) {
|
|
66810
|
+
const appliedBoundary = {
|
|
66811
|
+
steer: "turn-end",
|
|
66812
|
+
follow_up: "run-end",
|
|
66813
|
+
cancel: "cancel"
|
|
66814
|
+
};
|
|
66815
|
+
controlQueue.onDrained = (events) => {
|
|
66816
|
+
for (const event of events) {
|
|
66817
|
+
emitEvent(
|
|
66818
|
+
controlAppliedEvent(
|
|
66819
|
+
event.id,
|
|
66820
|
+
event.type,
|
|
66821
|
+
appliedBoundary[event.type] ?? "unknown"
|
|
66822
|
+
)
|
|
66823
|
+
);
|
|
66824
|
+
}
|
|
66825
|
+
};
|
|
66826
|
+
}
|
|
66827
|
+
return {
|
|
66828
|
+
signal: abort.signal,
|
|
66829
|
+
cancel,
|
|
66830
|
+
dispose() {
|
|
66831
|
+
controlPlane?.finalize();
|
|
66832
|
+
controlPlane?.dispose();
|
|
66833
|
+
unregister?.();
|
|
66834
|
+
}
|
|
66835
|
+
};
|
|
66659
66836
|
}
|
|
66660
|
-
|
|
66661
|
-
|
|
66662
|
-
|
|
66663
|
-
|
|
66664
|
-
|
|
66665
|
-
|
|
66666
|
-
|
|
66667
|
-
|
|
66837
|
+
var init_liveTurnAbort = __esm({
|
|
66838
|
+
"src/cli/headless/liveTurnAbort.ts"() {
|
|
66839
|
+
"use strict";
|
|
66840
|
+
init_runtime();
|
|
66841
|
+
init_sessionControl();
|
|
66842
|
+
init_controlBridge();
|
|
66843
|
+
init_protocol2();
|
|
66844
|
+
init_headless();
|
|
66845
|
+
}
|
|
66846
|
+
});
|
|
66847
|
+
|
|
66848
|
+
// src/cli/headless/policyGate.ts
|
|
66849
|
+
import { isAbsolute as isAbsolute5, resolve as resolve7 } from "node:path";
|
|
66850
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
66851
|
+
function checkStrictPolicyLoad(root, opts) {
|
|
66852
|
+
if (isPolicyEngineDisabled()) return { blocked: false, warnings: [] };
|
|
66853
|
+
try {
|
|
66854
|
+
const set2 = loadPolicySet(root, opts);
|
|
66855
|
+
return { blocked: false, warnings: set2.warnings };
|
|
66856
|
+
} catch (err) {
|
|
66857
|
+
if (!(err instanceof PolicyLoadError)) throw err;
|
|
66858
|
+
const file2 = isAbsolute5(err.file) ? err.file : resolve7(root, err.file);
|
|
66859
|
+
return {
|
|
66860
|
+
blocked: true,
|
|
66861
|
+
warnings: [],
|
|
66862
|
+
block: {
|
|
66863
|
+
reason: POLICY_LOAD_BLOCK_REASON,
|
|
66864
|
+
exitCode: POLICY_LOAD_EXIT_CODE,
|
|
66865
|
+
code: err.code,
|
|
66866
|
+
file: file2,
|
|
66867
|
+
...err.message ? { detail: err.message } : {}
|
|
66868
|
+
}
|
|
66869
|
+
};
|
|
66870
|
+
}
|
|
66871
|
+
}
|
|
66872
|
+
function reportPolicyLoadBlocked(block, output) {
|
|
66873
|
+
const where = `${block.file}${block.detail ? ` \u2014 ${block.detail}` : ""}`;
|
|
66874
|
+
process.stderr.write(`[zelari-code --headless] ${block.reason}: ${where}
|
|
66875
|
+
`);
|
|
66876
|
+
if (output === "json") {
|
|
66877
|
+
emitEvent({
|
|
66878
|
+
type: "error",
|
|
66879
|
+
severity: "fatal",
|
|
66880
|
+
message: `${block.reason}: ${where}`,
|
|
66881
|
+
code: block.reason
|
|
66882
|
+
});
|
|
66883
|
+
}
|
|
66884
|
+
}
|
|
66885
|
+
async function recordPolicyLoadBlockedOnSpine(block, opts = {}) {
|
|
66886
|
+
try {
|
|
66887
|
+
const { openHeadlessSpine: openHeadlessSpine2 } = await Promise.resolve().then(() => (init_headlessSpine(), headlessSpine_exports));
|
|
66888
|
+
const sessionId2 = opts.resumeSessionId ?? randomUUID9();
|
|
66889
|
+
const spine = await openHeadlessSpine2({
|
|
66890
|
+
sessionId: sessionId2,
|
|
66891
|
+
...opts.mode ? { mode: opts.mode } : {},
|
|
66892
|
+
...opts.profile ? { profile: opts.profile } : {},
|
|
66893
|
+
workspace: opts.workspace ?? process.cwd()
|
|
66894
|
+
});
|
|
66895
|
+
if (opts.mode === "zelari") {
|
|
66896
|
+
spine.missionPhase("dispatch", block.reason);
|
|
66668
66897
|
}
|
|
66898
|
+
spine.note(block.reason, {
|
|
66899
|
+
code: block.code,
|
|
66900
|
+
file: block.file,
|
|
66901
|
+
exitCode: block.exitCode,
|
|
66902
|
+
...block.detail ? { detail: block.detail } : {}
|
|
66903
|
+
});
|
|
66904
|
+
await spine.close("error");
|
|
66905
|
+
} catch {
|
|
66906
|
+
}
|
|
66907
|
+
}
|
|
66908
|
+
var init_policyGate = __esm({
|
|
66909
|
+
"src/cli/headless/policyGate.ts"() {
|
|
66910
|
+
"use strict";
|
|
66911
|
+
init_policyEngine();
|
|
66912
|
+
init_policyLoadMode();
|
|
66913
|
+
init_headless();
|
|
66914
|
+
}
|
|
66915
|
+
});
|
|
66916
|
+
|
|
66917
|
+
// src/cli/kraken/verifierResolution.ts
|
|
66918
|
+
function verifierOverrideToModelSelection(override) {
|
|
66919
|
+
if (override && typeof override.provider === "string" && typeof override.model === "string" && override.provider.trim().length > 0 && override.model.trim().length > 0) {
|
|
66920
|
+
return {
|
|
66921
|
+
mode: "fixed",
|
|
66922
|
+
provider: override.provider.trim(),
|
|
66923
|
+
model: override.model.trim()
|
|
66924
|
+
};
|
|
66925
|
+
}
|
|
66926
|
+
return { mode: "inherit" };
|
|
66927
|
+
}
|
|
66928
|
+
function loadVerifierModelSelection() {
|
|
66929
|
+
return verifierOverrideToModelSelection(getKrakenVerifierOverride());
|
|
66930
|
+
}
|
|
66931
|
+
var init_verifierResolution = __esm({
|
|
66932
|
+
"src/cli/kraken/verifierResolution.ts"() {
|
|
66933
|
+
"use strict";
|
|
66934
|
+
init_providerConfig();
|
|
66935
|
+
}
|
|
66936
|
+
});
|
|
66937
|
+
|
|
66938
|
+
// src/cli/kraken/verifierLifecycle.ts
|
|
66939
|
+
function verifierReviewEnabled(selection = loadVerifierModelSelection(), env = process.env) {
|
|
66940
|
+
const v = env.ZELARI_VERIFIER_REVIEW?.toLowerCase();
|
|
66941
|
+
if (v === "0" || v === "false" || v === "off") return false;
|
|
66942
|
+
if (v === "1" || v === "true" || v === "on") return true;
|
|
66943
|
+
return selection.mode === "fixed";
|
|
66944
|
+
}
|
|
66945
|
+
function makeVerifierCallModel(loadStream, identity, timeoutMs2 = 12e4) {
|
|
66946
|
+
return async ({ system, user }) => {
|
|
66947
|
+
const stream = await loadStream(identity.provider, identity.model);
|
|
66948
|
+
if (!stream) {
|
|
66949
|
+
throw new Error(`no provider config for verifier "${identity.provider}"`);
|
|
66950
|
+
}
|
|
66951
|
+
const { text } = await collectProviderText(stream, {
|
|
66952
|
+
messages: [
|
|
66953
|
+
{ role: "system", content: system },
|
|
66954
|
+
{ role: "user", content: user }
|
|
66955
|
+
],
|
|
66956
|
+
model: identity.model,
|
|
66957
|
+
provider: identity.provider,
|
|
66958
|
+
tools: [],
|
|
66959
|
+
signal: AbortSignal.timeout(timeoutMs2)
|
|
66960
|
+
});
|
|
66961
|
+
return { text, provider: identity.provider, model: identity.model };
|
|
66669
66962
|
};
|
|
66670
66963
|
}
|
|
66671
|
-
function
|
|
66672
|
-
|
|
66964
|
+
function isTestEvidenceCriterion(criterionId2) {
|
|
66965
|
+
const id3 = criterionId2.toLowerCase();
|
|
66966
|
+
return ["test", "typecheck", "build", "lint"].some((k) => id3.includes(k));
|
|
66673
66967
|
}
|
|
66674
|
-
function
|
|
66675
|
-
const
|
|
66676
|
-
|
|
66677
|
-
|
|
66678
|
-
|
|
66679
|
-
liveTurns.delete(sessionId2);
|
|
66968
|
+
function extractTestOutputExcerpt(results, maxChars = 4e3) {
|
|
66969
|
+
const lines = [];
|
|
66970
|
+
for (const r of results) {
|
|
66971
|
+
if (!isTestEvidenceCriterion(r.criterionId)) continue;
|
|
66972
|
+
lines.push([r.criterionId, r.status, r.detail].filter(Boolean).join(" \u2014 "));
|
|
66680
66973
|
}
|
|
66974
|
+
if (lines.length === 0) return "";
|
|
66975
|
+
return lines.join("\n").slice(0, maxChars);
|
|
66681
66976
|
}
|
|
66682
|
-
|
|
66683
|
-
|
|
66684
|
-
|
|
66977
|
+
async function buildBlindReviewInput(evaluation, deps) {
|
|
66978
|
+
const results = evaluation.results ?? [];
|
|
66979
|
+
const passed = results.filter((r) => r.status === "pass").length;
|
|
66980
|
+
const verdict = evaluation.evaluation?.verdict ?? "UNKNOWN";
|
|
66981
|
+
const summary = `Kraken BUILD turn \u2014 deterministic evidence: ${passed}/${results.length} criteria pass, completion verdict ${verdict}.`;
|
|
66982
|
+
const task = deps.task?.trim();
|
|
66983
|
+
const testOutputExcerpt = extractTestOutputExcerpt(results);
|
|
66984
|
+
let diffSummary;
|
|
66985
|
+
try {
|
|
66986
|
+
const res = await (deps.getDiff ?? getWorkingDiff)({
|
|
66987
|
+
cwd: deps.cwd ?? process.cwd(),
|
|
66988
|
+
maxChars: 8e3,
|
|
66989
|
+
staged: true
|
|
66990
|
+
});
|
|
66991
|
+
if (res && !res.empty && res.diff) diffSummary = res.diff;
|
|
66992
|
+
} catch {
|
|
66993
|
+
}
|
|
66994
|
+
return {
|
|
66995
|
+
...task ? { task } : {},
|
|
66996
|
+
summary,
|
|
66997
|
+
...diffSummary !== void 0 ? { diffSummary } : {},
|
|
66998
|
+
...testOutputExcerpt ? { testOutputExcerpt } : {},
|
|
66999
|
+
results
|
|
67000
|
+
};
|
|
67001
|
+
}
|
|
67002
|
+
async function runAdvisoryVerifierReview(evaluation, deps = {}) {
|
|
67003
|
+
if (!evaluation.evaluation || !evaluation.results) return null;
|
|
67004
|
+
const env = deps.env ?? process.env;
|
|
67005
|
+
const selection = deps.selection ?? loadVerifierModelSelection();
|
|
67006
|
+
if (!verifierReviewEnabled(selection, env)) return null;
|
|
67007
|
+
const risk = deps.risk ?? activeRisk(env);
|
|
67008
|
+
if (risk === "low") return null;
|
|
67009
|
+
const route = resolveVerifierRouting(
|
|
67010
|
+
selection.mode === "fixed" ? { provider: selection.provider, model: selection.model } : null,
|
|
67011
|
+
risk,
|
|
67012
|
+
{
|
|
67013
|
+
selectionMode: selection.mode === "fixed" ? "fixed" : "inherit",
|
|
67014
|
+
session: deps.session ?? null,
|
|
67015
|
+
familyCandidates: deps.familyCandidates,
|
|
67016
|
+
env
|
|
67017
|
+
}
|
|
67018
|
+
);
|
|
67019
|
+
const reviewers = route.reviewers;
|
|
67020
|
+
let callModel = deps.callModel;
|
|
67021
|
+
if (reviewers.length === 0 || !callModel && !deps.loadStream) return null;
|
|
67022
|
+
const blind = await buildBlindReviewInput(evaluation, deps);
|
|
67023
|
+
const reviews = [];
|
|
67024
|
+
for (const reviewer of reviewers) {
|
|
67025
|
+
const call = callModel ?? makeVerifierCallModel(deps.loadStream, reviewer.identity, deps.timeoutMs);
|
|
67026
|
+
const service = new VerifierService({
|
|
67027
|
+
callModel: call,
|
|
67028
|
+
config: {
|
|
67029
|
+
enabled: true,
|
|
67030
|
+
model: selection,
|
|
67031
|
+
progressScoring: false,
|
|
67032
|
+
bon: { enabled: false, n: 3 }
|
|
67033
|
+
},
|
|
67034
|
+
emit: deps.emit,
|
|
67035
|
+
env
|
|
67036
|
+
});
|
|
67037
|
+
reviews.push(await service.reviewCompletion({ ...blind, session: deps.session }));
|
|
67038
|
+
}
|
|
67039
|
+
const review = reviews.length > 1 ? mergeVerifierVerdicts(reviews) : reviews[0];
|
|
67040
|
+
evaluation.review = review;
|
|
67041
|
+
if (reviews.length > 1 && risk === "critical") {
|
|
67042
|
+
evaluation.reviewDivergence = divergenceFromReviews(
|
|
67043
|
+
reviews,
|
|
67044
|
+
reviewers.map((r) => ({ family: r.family, role: r.role }))
|
|
67045
|
+
);
|
|
67046
|
+
}
|
|
67047
|
+
return review;
|
|
67048
|
+
}
|
|
67049
|
+
var init_verifierLifecycle = __esm({
|
|
67050
|
+
"src/cli/kraken/verifierLifecycle.ts"() {
|
|
66685
67051
|
"use strict";
|
|
66686
|
-
|
|
66687
|
-
|
|
67052
|
+
init_verification();
|
|
67053
|
+
init_krakenSelectTool();
|
|
67054
|
+
init_gitOps();
|
|
67055
|
+
init_verifierResolution();
|
|
67056
|
+
init_verifierRouting();
|
|
66688
67057
|
}
|
|
66689
67058
|
});
|
|
66690
67059
|
|
|
66691
67060
|
// src/cli/extensions/sandboxedFs.ts
|
|
66692
67061
|
import { promises as fsp } from "node:fs";
|
|
66693
|
-
import
|
|
67062
|
+
import path90 from "node:path";
|
|
66694
67063
|
function errText(prefix, p3, err) {
|
|
66695
67064
|
const msg = err instanceof Error ? err.message : String(err);
|
|
66696
67065
|
return `[extension-fs] ${prefix} "${p3}": ${msg}`;
|
|
66697
67066
|
}
|
|
66698
67067
|
function bindSandboxedFs(root) {
|
|
66699
|
-
const resolvedRoot =
|
|
67068
|
+
const resolvedRoot = path90.resolve(root);
|
|
66700
67069
|
return {
|
|
66701
67070
|
root: resolvedRoot,
|
|
66702
67071
|
async readFile(relativePath) {
|
|
@@ -66712,7 +67081,7 @@ function bindSandboxedFs(root) {
|
|
|
66712
67081
|
try {
|
|
66713
67082
|
const target = resolveSandboxedPath(relativePath, { root: resolvedRoot });
|
|
66714
67083
|
verifyContainment(target, { root: resolvedRoot });
|
|
66715
|
-
await fsp.mkdir(
|
|
67084
|
+
await fsp.mkdir(path90.dirname(target), { recursive: true });
|
|
66716
67085
|
await fsp.writeFile(target, data, "utf8");
|
|
66717
67086
|
return typedOk({ path: target });
|
|
66718
67087
|
} catch (err) {
|
|
@@ -66897,7 +67266,7 @@ var init_loader = __esm({
|
|
|
66897
67266
|
|
|
66898
67267
|
// src/cli/headless/runOneTurn.ts
|
|
66899
67268
|
import { promises as fs44 } from "node:fs";
|
|
66900
|
-
import
|
|
67269
|
+
import path91 from "node:path";
|
|
66901
67270
|
function planModeFromOpts(opts) {
|
|
66902
67271
|
return (opts.phase ?? "build") === "plan";
|
|
66903
67272
|
}
|
|
@@ -67046,6 +67415,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
67046
67415
|
// an interactive approval (permission.request over NDJSON) instead of
|
|
67047
67416
|
// the fail-closed typedErr. Absent handler ⇒ unchanged fail-closed.
|
|
67048
67417
|
...opts.onPermissionAsk ? { onPermissionAsk: opts.onPermissionAsk } : {},
|
|
67418
|
+
...opts.onAskUser ? { onAskUser: opts.onAskUser } : {},
|
|
67049
67419
|
permissionPolicy: defaultPermissionPolicy2(),
|
|
67050
67420
|
...nativeMemory ? { memoryService: nativeMemory } : {},
|
|
67051
67421
|
memoryAutoWrite,
|
|
@@ -67272,7 +67642,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
67272
67642
|
let finalReason = "completed";
|
|
67273
67643
|
let exitCode = 0;
|
|
67274
67644
|
const textBuffer = [];
|
|
67275
|
-
const scrub = createStreamScrubber2();
|
|
67645
|
+
const scrub = createStreamScrubber2({ stripQuestion: opts.output !== "json" });
|
|
67276
67646
|
try {
|
|
67277
67647
|
for await (const event of harness.run()) {
|
|
67278
67648
|
progressRuntime.observe(event);
|
|
@@ -67463,7 +67833,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
67463
67833
|
if (json3) {
|
|
67464
67834
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
67465
67835
|
else {
|
|
67466
|
-
await fs44.mkdir(
|
|
67836
|
+
await fs44.mkdir(path91.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
67467
67837
|
await fs44.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
67468
67838
|
}
|
|
67469
67839
|
}
|
|
@@ -68442,9 +68812,9 @@ __export(triggerLock_exports, {
|
|
|
68442
68812
|
releaseLock: () => releaseLock
|
|
68443
68813
|
});
|
|
68444
68814
|
import { promises as fs45 } from "node:fs";
|
|
68445
|
-
import * as
|
|
68815
|
+
import * as path92 from "node:path";
|
|
68446
68816
|
function lockPath(projectRoot) {
|
|
68447
|
-
return
|
|
68817
|
+
return path92.join(projectRoot, ".zelari", "trigger.lock");
|
|
68448
68818
|
}
|
|
68449
68819
|
function isPidAlive(pid) {
|
|
68450
68820
|
try {
|
|
@@ -68457,7 +68827,7 @@ function isPidAlive(pid) {
|
|
|
68457
68827
|
}
|
|
68458
68828
|
async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date()) {
|
|
68459
68829
|
const lp = lockPath(projectRoot);
|
|
68460
|
-
const dir =
|
|
68830
|
+
const dir = path92.dirname(lp);
|
|
68461
68831
|
await fs45.mkdir(dir, { recursive: true });
|
|
68462
68832
|
try {
|
|
68463
68833
|
const raw = await fs45.readFile(lp, "utf8");
|
|
@@ -68489,7 +68859,7 @@ var init_triggerLock = __esm({
|
|
|
68489
68859
|
|
|
68490
68860
|
// src/cli/runHeadless.ts
|
|
68491
68861
|
import { promises as fs46 } from "node:fs";
|
|
68492
|
-
import
|
|
68862
|
+
import path93 from "node:path";
|
|
68493
68863
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
68494
68864
|
async function runHeadless(opts) {
|
|
68495
68865
|
resetTaskSpawnCount();
|
|
@@ -68733,7 +69103,7 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
68733
69103
|
try {
|
|
68734
69104
|
let preflightGraph;
|
|
68735
69105
|
if (opts.runPlan && opts.runPlan.trim() !== "") {
|
|
68736
|
-
const planPath =
|
|
69106
|
+
const planPath = path93.join(cwd, ".zelari", "radio", `plan-${opts.runPlan}.json`);
|
|
68737
69107
|
log(`loading pre-flight plan: ${planPath}`);
|
|
68738
69108
|
let raw;
|
|
68739
69109
|
try {
|
|
@@ -68776,8 +69146,8 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
68776
69146
|
log(formatKrakenGraphAscii2(graph));
|
|
68777
69147
|
if (opts.planOnly) {
|
|
68778
69148
|
const planId = randomUUID10();
|
|
68779
|
-
const planDir =
|
|
68780
|
-
const planPath =
|
|
69149
|
+
const planDir = path93.join(cwd, ".zelari", "radio");
|
|
69150
|
+
const planPath = path93.join(planDir, `plan-${planId}.json`);
|
|
68781
69151
|
await fs46.mkdir(planDir, { recursive: true });
|
|
68782
69152
|
await fs46.writeFile(
|
|
68783
69153
|
planPath,
|
|
@@ -68814,6 +69184,7 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
68814
69184
|
// ask without a UI fails closed), so this intersection actually
|
|
68815
69185
|
// bites: tentacles can never exceed the preset.
|
|
68816
69186
|
parentPolicy: defaultPermissionPolicy2(),
|
|
69187
|
+
...opts.onPermissionAsk ? { onPermissionAsk: opts.onPermissionAsk } : {},
|
|
68817
69188
|
// Anchor every tentacle to the SAME provider/model this run
|
|
68818
69189
|
// resolved (Desktop's selector, or --provider/--model), instead
|
|
68819
69190
|
// of the persisted provider.json default the factory falls back
|
|
@@ -68930,6 +69301,8 @@ async function buildCouncilToolRegistry(planMode, opts, memoryService, memoryAut
|
|
|
68930
69301
|
planMode,
|
|
68931
69302
|
...extras?.lspProvider ? { lspProvider: extras.lspProvider } : {},
|
|
68932
69303
|
permissionPolicy: defaultPermissionPolicy2(),
|
|
69304
|
+
...opts?.onPermissionAsk ? { onPermissionAsk: opts.onPermissionAsk } : {},
|
|
69305
|
+
...opts?.onAskUser ? { onAskUser: opts.onAskUser } : {},
|
|
68933
69306
|
...memoryService ? { memoryService } : {},
|
|
68934
69307
|
memoryAutoWrite
|
|
68935
69308
|
});
|
|
@@ -68949,6 +69322,14 @@ async function buildCouncilToolRegistry(planMode, opts, memoryService, memoryAut
|
|
|
68949
69322
|
return { toolRegistry, workspaceCtx: realCtx };
|
|
68950
69323
|
}
|
|
68951
69324
|
async function runHeadlessCouncil(opts, provider, model, providerStream, extras) {
|
|
69325
|
+
const live = attachHeadlessLiveCancel({ output: opts.output });
|
|
69326
|
+
try {
|
|
69327
|
+
return await runHeadlessCouncilBody(opts, provider, model, providerStream, extras, live.signal);
|
|
69328
|
+
} finally {
|
|
69329
|
+
live.dispose();
|
|
69330
|
+
}
|
|
69331
|
+
}
|
|
69332
|
+
async function runHeadlessCouncilBody(opts, provider, model, providerStream, extras, signal) {
|
|
68952
69333
|
const { dispatchCouncil: dispatchCouncil2 } = await Promise.resolve().then(() => (init_councilDispatcher(), councilDispatcher_exports));
|
|
68953
69334
|
const sessionId2 = crypto.randomUUID();
|
|
68954
69335
|
const cwd = resolveHeadlessCwd(opts);
|
|
@@ -69024,7 +69405,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
69024
69405
|
const effectiveTask = buildCouncilTaskWithHistory(opts.task, historySeed);
|
|
69025
69406
|
if (opts.task) spine.userMessage(effectiveTask);
|
|
69026
69407
|
let exitCode = 0;
|
|
69027
|
-
const scrub = createStreamScrubber2();
|
|
69408
|
+
const scrub = createStreamScrubber2({ stripQuestion: opts.output !== "json" });
|
|
69028
69409
|
let lastAssistantText = "";
|
|
69029
69410
|
let currentAssistantText = "";
|
|
69030
69411
|
try {
|
|
@@ -69059,6 +69440,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
69059
69440
|
tools: toolRegistry,
|
|
69060
69441
|
feedbackStore,
|
|
69061
69442
|
runMode: councilRunMode,
|
|
69443
|
+
signal,
|
|
69062
69444
|
// t23: an auto-SELECTED council runs the LITE tier (3 members) unless
|
|
69063
69445
|
// ZELARI_COUNCIL_TIER / ZELARI_COUNCIL_SIZE explicitly opt into full.
|
|
69064
69446
|
...opts.orchestrationDecision?.strategy === "council" && process.env["ZELARI_COUNCIL_TIER"] === void 0 && process.env["ZELARI_COUNCIL_SIZE"] === void 0 ? { councilSize: COUNCIL_TIER_SIZES.lite } : {},
|
|
@@ -69117,7 +69499,9 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
69117
69499
|
return 2;
|
|
69118
69500
|
}
|
|
69119
69501
|
try {
|
|
69120
|
-
await spine.close(
|
|
69502
|
+
await spine.close(
|
|
69503
|
+
signal.aborted ? "stopped" : exitCode === 0 ? "completed" : "error"
|
|
69504
|
+
);
|
|
69121
69505
|
} catch {
|
|
69122
69506
|
}
|
|
69123
69507
|
try {
|
|
@@ -69129,7 +69513,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
69129
69513
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
69130
69514
|
mode: "shadow",
|
|
69131
69515
|
taskClass: classifyTask2({ prompt: effectiveTask }).taskClass,
|
|
69132
|
-
verdict: exitCode === 0 ? "PASS" : exitCode === 3 ? "FAIL" : "UNKNOWN"
|
|
69516
|
+
verdict: signal.aborted ? "UNKNOWN" : exitCode === 0 ? "PASS" : exitCode === 3 ? "FAIL" : "UNKNOWN"
|
|
69133
69517
|
});
|
|
69134
69518
|
}
|
|
69135
69519
|
} catch {
|
|
@@ -69141,14 +69525,14 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
69141
69525
|
if (json3) {
|
|
69142
69526
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
69143
69527
|
else {
|
|
69144
|
-
await fs46.mkdir(
|
|
69528
|
+
await fs46.mkdir(path93.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
69145
69529
|
await fs46.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
69146
69530
|
}
|
|
69147
69531
|
}
|
|
69148
69532
|
} catch {
|
|
69149
69533
|
}
|
|
69150
69534
|
}
|
|
69151
|
-
if (nativeMemory && memoryAutoWrite && lastAssistantText) {
|
|
69535
|
+
if (nativeMemory && memoryAutoWrite && lastAssistantText && !signal.aborted) {
|
|
69152
69536
|
try {
|
|
69153
69537
|
await nativeMemory.remember({
|
|
69154
69538
|
kind: councilRunMode === "design-phase" ? "decision" : "outcome",
|
|
@@ -69175,6 +69559,14 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
69175
69559
|
return exitCode;
|
|
69176
69560
|
}
|
|
69177
69561
|
async function runHeadlessZelari(opts, provider, model, providerStream, extras) {
|
|
69562
|
+
const live = attachHeadlessLiveCancel({ output: opts.output });
|
|
69563
|
+
try {
|
|
69564
|
+
return await runHeadlessZelariBody(opts, provider, model, providerStream, extras, live.signal);
|
|
69565
|
+
} finally {
|
|
69566
|
+
live.dispose();
|
|
69567
|
+
}
|
|
69568
|
+
}
|
|
69569
|
+
async function runHeadlessZelariBody(opts, provider, model, providerStream, extras, signal) {
|
|
69178
69570
|
const projectRoot = resolveHeadlessCwd(opts);
|
|
69179
69571
|
const sessionId2 = opts.resumeSessionId ?? crypto.randomUUID();
|
|
69180
69572
|
const spine = await openHeadlessSpine({
|
|
@@ -69285,6 +69677,7 @@ ${JSON.stringify({ deliverable: brief.deliverableThisMission, mvp: brief.sliceMv
|
|
|
69285
69677
|
memory,
|
|
69286
69678
|
emit,
|
|
69287
69679
|
buildViaAgent,
|
|
69680
|
+
signal,
|
|
69288
69681
|
onMissionPhase: (phase2, note) => spine.missionPhase(phase2, note),
|
|
69289
69682
|
onMissionProgress: (advice, iteration) => spine.missionProgress({
|
|
69290
69683
|
recommendation: advice.recommendation,
|
|
@@ -69310,7 +69703,7 @@ ${ragContext}` : slicePrompt;
|
|
|
69310
69703
|
let writeCount = 0;
|
|
69311
69704
|
let chairmanErrored = false;
|
|
69312
69705
|
let membersCompleted = 0;
|
|
69313
|
-
const scrub = createStreamScrubber2();
|
|
69706
|
+
const scrub = createStreamScrubber2({ stripQuestion: opts.output !== "json" });
|
|
69314
69707
|
const { composeProjectContext: composeProjectContext3 } = await Promise.resolve().then(() => (init_composeContext(), composeContext_exports));
|
|
69315
69708
|
const { loadDurableContext: loadDurableContext3 } = await Promise.resolve().then(() => (init_loadDurableContext(), loadDurableContext_exports));
|
|
69316
69709
|
const memOnly = ragContext?.trim() ? ragContext : void 0;
|
|
@@ -69333,6 +69726,7 @@ ${ragContext}` : slicePrompt;
|
|
|
69333
69726
|
tools: toolRegistry,
|
|
69334
69727
|
feedbackStore,
|
|
69335
69728
|
runMode: effectiveRunMode,
|
|
69729
|
+
signal,
|
|
69336
69730
|
maxToolCallsChairman: chairmanBudget,
|
|
69337
69731
|
...implementerRetry ? { skipSpecialists: true } : {},
|
|
69338
69732
|
workspaceContext: composed2.workspaceContext,
|
|
@@ -69380,11 +69774,20 @@ ${ragContext}` : slicePrompt;
|
|
|
69380
69774
|
}
|
|
69381
69775
|
let completionOk = false;
|
|
69382
69776
|
let degraded = false;
|
|
69777
|
+
if (signal.aborted) {
|
|
69778
|
+
return {
|
|
69779
|
+
completionOk: false,
|
|
69780
|
+
ran: membersCompleted > 0 || synthesisText.length > 0,
|
|
69781
|
+
synthesisText: synthesisText || void 0,
|
|
69782
|
+
writeCount,
|
|
69783
|
+
degraded: true
|
|
69784
|
+
};
|
|
69785
|
+
}
|
|
69383
69786
|
try {
|
|
69384
69787
|
const { detectDegradedRun: detectDegradedRun3 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
69385
69788
|
const d = detectDegradedRun3({
|
|
69386
69789
|
chairmanErrored,
|
|
69387
|
-
councilAborted:
|
|
69790
|
+
councilAborted: signal.aborted,
|
|
69388
69791
|
luciferWriteCount: writeCount,
|
|
69389
69792
|
synthesisText,
|
|
69390
69793
|
runMode: effectiveRunMode
|
|
@@ -69451,7 +69854,9 @@ ${ragContext}` : slicePrompt;
|
|
|
69451
69854
|
const { registry: agentRegistry } = createBuiltinToolRegistry2({
|
|
69452
69855
|
root: projectRoot,
|
|
69453
69856
|
planMode: false,
|
|
69454
|
-
permissionPolicy: defaultPermissionPolicy2()
|
|
69857
|
+
permissionPolicy: defaultPermissionPolicy2(),
|
|
69858
|
+
...opts.onPermissionAsk ? { onPermissionAsk: opts.onPermissionAsk } : {},
|
|
69859
|
+
...opts.onAskUser ? { onAskUser: opts.onAskUser } : {}
|
|
69455
69860
|
});
|
|
69456
69861
|
await registerHeadlessMcp(agentRegistry, opts);
|
|
69457
69862
|
const durableState = await loadDurableContext2(projectRoot);
|
|
@@ -69518,7 +69923,10 @@ ${ragContext}` : slicePrompt;
|
|
|
69518
69923
|
}
|
|
69519
69924
|
});
|
|
69520
69925
|
if (state3.status === "error") exitCode = exitCode || 3;
|
|
69521
|
-
else if (state3.status === "
|
|
69926
|
+
else if (state3.status === "cancelled") {
|
|
69927
|
+
exitCode = 0;
|
|
69928
|
+
spine.missionPhase("verification", "mission-cancelled");
|
|
69929
|
+
} else if (state3.status === "success") {
|
|
69522
69930
|
const missionGate = await evaluateStrictBuildGate("build", {
|
|
69523
69931
|
emit: (input) => spine.appendEvent(input),
|
|
69524
69932
|
surface: "mission",
|
|
@@ -69556,7 +69964,8 @@ ${ragContext}` : slicePrompt;
|
|
|
69556
69964
|
}
|
|
69557
69965
|
await memory.close().catch(() => void 0);
|
|
69558
69966
|
try {
|
|
69559
|
-
if (
|
|
69967
|
+
if (signal.aborted) await spine.close("stopped");
|
|
69968
|
+
else if (exitCode === 0) await spine.close("completed");
|
|
69560
69969
|
else await spine.close(exitCode === 2 ? "error" : "stopped");
|
|
69561
69970
|
} catch {
|
|
69562
69971
|
}
|
|
@@ -69567,7 +69976,7 @@ ${ragContext}` : slicePrompt;
|
|
|
69567
69976
|
if (json3) {
|
|
69568
69977
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
69569
69978
|
else {
|
|
69570
|
-
await fs46.mkdir(
|
|
69979
|
+
await fs46.mkdir(path93.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
69571
69980
|
await fs46.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
69572
69981
|
}
|
|
69573
69982
|
}
|
|
@@ -69603,6 +70012,7 @@ var init_runHeadless = __esm({
|
|
|
69603
70012
|
init_metrics3();
|
|
69604
70013
|
init_headlessSpine();
|
|
69605
70014
|
init_harnessStateEmit();
|
|
70015
|
+
init_liveTurnAbort();
|
|
69606
70016
|
init_policyGate();
|
|
69607
70017
|
init_policyLoadMode();
|
|
69608
70018
|
init_runOneTurn();
|
|
@@ -70179,7 +70589,7 @@ function upsertSkill(opts) {
|
|
|
70179
70589
|
}
|
|
70180
70590
|
dir = getProjectSkillsDir(root);
|
|
70181
70591
|
}
|
|
70182
|
-
const
|
|
70592
|
+
const path100 = skillFilePath(dir, name);
|
|
70183
70593
|
const content = serializeSkillMd({
|
|
70184
70594
|
name,
|
|
70185
70595
|
description,
|
|
@@ -70188,13 +70598,13 @@ function upsertSkill(opts) {
|
|
|
70188
70598
|
tools: opts.tools,
|
|
70189
70599
|
cost: opts.cost
|
|
70190
70600
|
});
|
|
70191
|
-
const parsed = parseSkillMd(content,
|
|
70601
|
+
const parsed = parseSkillMd(content, path100);
|
|
70192
70602
|
if (!parsed) {
|
|
70193
70603
|
return { ok: false, error: "Generated SKILL.md failed validation" };
|
|
70194
70604
|
}
|
|
70195
|
-
mkdirSync23(dirname13(
|
|
70196
|
-
writeFileSync25(
|
|
70197
|
-
return { ok: true, path:
|
|
70605
|
+
mkdirSync23(dirname13(path100), { recursive: true });
|
|
70606
|
+
writeFileSync25(path100, content, "utf8");
|
|
70607
|
+
return { ok: true, path: path100 };
|
|
70198
70608
|
}
|
|
70199
70609
|
function removeSkill(opts) {
|
|
70200
70610
|
const name = opts.name.trim().toLowerCase();
|
|
@@ -70212,8 +70622,8 @@ function removeSkill(opts) {
|
|
|
70212
70622
|
dir = getProjectSkillsDir(root);
|
|
70213
70623
|
}
|
|
70214
70624
|
const skillDir = join46(dir, name);
|
|
70215
|
-
const
|
|
70216
|
-
if (!existsSync59(
|
|
70625
|
+
const path100 = skillFilePath(dir, name);
|
|
70626
|
+
if (!existsSync59(path100) && !existsSync59(skillDir)) {
|
|
70217
70627
|
return { ok: false, error: `Skill "${name}" not found in ${dir}` };
|
|
70218
70628
|
}
|
|
70219
70629
|
try {
|
|
@@ -70224,7 +70634,7 @@ function removeSkill(opts) {
|
|
|
70224
70634
|
error: err instanceof Error ? err.message : String(err)
|
|
70225
70635
|
};
|
|
70226
70636
|
}
|
|
70227
|
-
return { ok: true, path:
|
|
70637
|
+
return { ok: true, path: path100 };
|
|
70228
70638
|
}
|
|
70229
70639
|
var NAME_RE, BUILTIN_SKILL_MODULES, builtinsLoaded;
|
|
70230
70640
|
var init_skillConfigIo = __esm({
|
|
@@ -70345,7 +70755,7 @@ var init_jsonApi = __esm({
|
|
|
70345
70755
|
});
|
|
70346
70756
|
|
|
70347
70757
|
// src/cli/memory/mcpAdapter.ts
|
|
70348
|
-
import * as
|
|
70758
|
+
import * as path94 from "node:path";
|
|
70349
70759
|
var id2, projectId, source, SearchSchema, AddSchema, LinkSchema, RetractSchema, MEMORY_MCP_TOOLS, MemoryMcpAdapter;
|
|
70350
70760
|
var init_mcpAdapter = __esm({
|
|
70351
70761
|
"src/cli/memory/mcpAdapter.ts"() {
|
|
@@ -70515,8 +70925,8 @@ var init_mcpAdapter = __esm({
|
|
|
70515
70925
|
this.takeWrite();
|
|
70516
70926
|
const externalFile = args.source?.file;
|
|
70517
70927
|
if (externalFile) {
|
|
70518
|
-
const normalized =
|
|
70519
|
-
if (
|
|
70928
|
+
const normalized = path94.normalize(externalFile);
|
|
70929
|
+
if (path94.isAbsolute(normalized) || normalized === ".." || normalized.startsWith(`..${path94.sep}`)) {
|
|
70520
70930
|
throw new Error("source.file must be project-relative and cannot escape the project");
|
|
70521
70931
|
}
|
|
70522
70932
|
}
|
|
@@ -71043,12 +71453,12 @@ function ensureHome() {
|
|
|
71043
71453
|
}
|
|
71044
71454
|
}
|
|
71045
71455
|
function loadCompanionConfig() {
|
|
71046
|
-
const
|
|
71047
|
-
if (!existsSync60(
|
|
71456
|
+
const path100 = getCompanionConfigPath();
|
|
71457
|
+
if (!existsSync60(path100)) {
|
|
71048
71458
|
return { projects: [] };
|
|
71049
71459
|
}
|
|
71050
71460
|
try {
|
|
71051
|
-
const raw = JSON.parse(readFileSync45(
|
|
71461
|
+
const raw = JSON.parse(readFileSync45(path100, "utf8"));
|
|
71052
71462
|
const projects = Array.isArray(raw.projects) ? raw.projects.filter(
|
|
71053
71463
|
(p3) => p3 && typeof p3.path === "string" && p3.path.trim() && typeof (p3.id ?? p3.name) === "string"
|
|
71054
71464
|
).map((p3) => ({
|
|
@@ -71086,16 +71496,16 @@ function loadOrCreateToken(explicit) {
|
|
|
71086
71496
|
return { token: explicit.trim(), created: false };
|
|
71087
71497
|
}
|
|
71088
71498
|
ensureHome();
|
|
71089
|
-
const
|
|
71090
|
-
if (existsSync60(
|
|
71091
|
-
const t = readFileSync45(
|
|
71499
|
+
const path100 = getCompanionTokenPath();
|
|
71500
|
+
if (existsSync60(path100)) {
|
|
71501
|
+
const t = readFileSync45(path100, "utf8").trim();
|
|
71092
71502
|
if (t) return { token: t, created: false };
|
|
71093
71503
|
}
|
|
71094
71504
|
const token = randomBytes7(24).toString("base64url");
|
|
71095
|
-
writeFileSync26(
|
|
71505
|
+
writeFileSync26(path100, token + "\n", "utf8");
|
|
71096
71506
|
try {
|
|
71097
71507
|
const fs48 = __require("node:fs");
|
|
71098
|
-
fs48.chmodSync?.(
|
|
71508
|
+
fs48.chmodSync?.(path100, 384);
|
|
71099
71509
|
} catch {
|
|
71100
71510
|
}
|
|
71101
71511
|
return { token, created: true };
|
|
@@ -71120,17 +71530,17 @@ function mergeProjects(cfg, extraPaths) {
|
|
|
71120
71530
|
byId.set(p3.id, p3);
|
|
71121
71531
|
}
|
|
71122
71532
|
for (const raw of extraPaths) {
|
|
71123
|
-
const
|
|
71124
|
-
if (!
|
|
71125
|
-
let id3 = slugFromPath(
|
|
71533
|
+
const path100 = raw.trim();
|
|
71534
|
+
if (!path100) continue;
|
|
71535
|
+
let id3 = slugFromPath(path100);
|
|
71126
71536
|
let n = 2;
|
|
71127
|
-
while (byId.has(id3) && byId.get(id3).path !==
|
|
71128
|
-
id3 = `${slugFromPath(
|
|
71537
|
+
while (byId.has(id3) && byId.get(id3).path !== path100) {
|
|
71538
|
+
id3 = `${slugFromPath(path100)}-${n++}`;
|
|
71129
71539
|
}
|
|
71130
71540
|
byId.set(id3, {
|
|
71131
71541
|
id: id3,
|
|
71132
|
-
name: slugFromPath(
|
|
71133
|
-
path:
|
|
71542
|
+
name: slugFromPath(path100),
|
|
71543
|
+
path: path100
|
|
71134
71544
|
});
|
|
71135
71545
|
}
|
|
71136
71546
|
return [...byId.values()];
|
|
@@ -71190,38 +71600,61 @@ function applyTurnPermissionPreset(input) {
|
|
|
71190
71600
|
process.env[PRESET_ENV] = value;
|
|
71191
71601
|
return true;
|
|
71192
71602
|
}
|
|
71603
|
+
function isPermissionDecision(value) {
|
|
71604
|
+
return typeof value === "string" && PERMISSION_DECISIONS.includes(value);
|
|
71605
|
+
}
|
|
71193
71606
|
function createServePermissionBridge(write, timeoutMs2 = 12e4) {
|
|
71194
71607
|
const pending = /* @__PURE__ */ new Map();
|
|
71195
71608
|
let seq = 0;
|
|
71196
|
-
const settle = (requestId, decision) => {
|
|
71609
|
+
const settle = (requestId, decision, timedOut = false) => {
|
|
71197
71610
|
const entry = pending.get(requestId);
|
|
71198
71611
|
if (!entry) return false;
|
|
71199
71612
|
pending.delete(requestId);
|
|
71200
71613
|
clearTimeout(entry.timer);
|
|
71614
|
+
write(
|
|
71615
|
+
JSON.stringify({
|
|
71616
|
+
type: "permission.settled",
|
|
71617
|
+
requestId,
|
|
71618
|
+
decision,
|
|
71619
|
+
...timedOut ? { timedOut: true } : {}
|
|
71620
|
+
})
|
|
71621
|
+
);
|
|
71201
71622
|
entry.resolve(decision);
|
|
71202
71623
|
return true;
|
|
71203
71624
|
};
|
|
71204
71625
|
return {
|
|
71205
71626
|
onPermissionAsk(payload) {
|
|
71206
71627
|
const requestId = `perm-${Date.now()}-${++seq}`;
|
|
71628
|
+
const categories = payload.categories && payload.categories.length > 0 ? payload.categories : payload.category ? payload.category.split(",").map((c) => c.trim()).filter(Boolean) : [];
|
|
71207
71629
|
return new Promise((resolve9) => {
|
|
71208
71630
|
const timer = setTimeout(() => {
|
|
71209
|
-
settle(requestId, "deny");
|
|
71631
|
+
settle(requestId, "deny", true);
|
|
71210
71632
|
}, timeoutMs2);
|
|
71211
|
-
pending.set(requestId, { resolve: resolve9, timer });
|
|
71633
|
+
pending.set(requestId, { resolve: resolve9, timer, payload });
|
|
71212
71634
|
write(
|
|
71213
71635
|
JSON.stringify({
|
|
71214
71636
|
type: "permission.request",
|
|
71215
71637
|
requestId,
|
|
71216
71638
|
tool: payload.tool,
|
|
71217
71639
|
category: payload.category,
|
|
71640
|
+
categories,
|
|
71218
71641
|
...payload.inputPreview !== void 0 ? { inputPreview: payload.inputPreview } : {},
|
|
71219
71642
|
...payload.reason !== void 0 ? { reason: payload.reason } : {}
|
|
71220
71643
|
})
|
|
71221
71644
|
);
|
|
71222
71645
|
});
|
|
71223
71646
|
},
|
|
71224
|
-
respond: settle,
|
|
71647
|
+
respond: (requestId, decision) => settle(requestId, decision, false),
|
|
71648
|
+
releaseGranted() {
|
|
71649
|
+
let n = 0;
|
|
71650
|
+
for (const [id3, entry] of [...pending]) {
|
|
71651
|
+
const cats = entry.payload.categories && entry.payload.categories.length > 0 ? entry.payload.categories : entry.payload.category ? entry.payload.category.split(",").map((c) => c.trim()).filter(Boolean) : [];
|
|
71652
|
+
if (isSessionGranted(entry.payload.tool, cats)) {
|
|
71653
|
+
if (settle(id3, "allow", false)) n += 1;
|
|
71654
|
+
}
|
|
71655
|
+
}
|
|
71656
|
+
return n;
|
|
71657
|
+
},
|
|
71225
71658
|
pendingCount: () => pending.size
|
|
71226
71659
|
};
|
|
71227
71660
|
}
|
|
@@ -71233,8 +71666,11 @@ function servePermissionRespond(bridge, params) {
|
|
|
71233
71666
|
if (typeof requestId !== "string" || requestId.length === 0) {
|
|
71234
71667
|
return { accepted: false, reason: "permission.respond requires a non-empty string requestId" };
|
|
71235
71668
|
}
|
|
71236
|
-
if (decision
|
|
71237
|
-
return {
|
|
71669
|
+
if (!isPermissionDecision(decision)) {
|
|
71670
|
+
return {
|
|
71671
|
+
accepted: false,
|
|
71672
|
+
reason: "permission.respond decision must be 'allow' | 'deny' | 'always-tool' | 'always-category'"
|
|
71673
|
+
};
|
|
71238
71674
|
}
|
|
71239
71675
|
return { accepted: bridge.respond(requestId, decision) };
|
|
71240
71676
|
}
|
|
@@ -71244,24 +71680,110 @@ function asRegistryAskHandler(bridge) {
|
|
|
71244
71680
|
const decision = await bridge.onPermissionAsk({
|
|
71245
71681
|
tool: req.toolName,
|
|
71246
71682
|
category: req.categories.join(",") || "other",
|
|
71683
|
+
categories: req.categories,
|
|
71247
71684
|
reason,
|
|
71248
71685
|
...req.claims && req.claims.length > 0 ? { inputPreview: req.claims.map((c) => c.summary).join(" \xB7 ") } : {}
|
|
71249
71686
|
});
|
|
71250
|
-
|
|
71687
|
+
if (decision === "deny") return false;
|
|
71688
|
+
if (decision === "always-tool") {
|
|
71689
|
+
grantSessionTool(req.toolName);
|
|
71690
|
+
bridge.releaseGranted();
|
|
71691
|
+
} else if (decision === "always-category") {
|
|
71692
|
+
for (const cat of req.categories) {
|
|
71693
|
+
grantSessionCategory(cat);
|
|
71694
|
+
}
|
|
71695
|
+
grantSessionTool(req.toolName);
|
|
71696
|
+
bridge.releaseGranted();
|
|
71697
|
+
}
|
|
71698
|
+
return true;
|
|
71251
71699
|
};
|
|
71252
71700
|
}
|
|
71253
|
-
var SERVE_PERMISSION_PRESETS, PRESET_ENV;
|
|
71701
|
+
var SERVE_PERMISSION_PRESETS, PRESET_ENV, PERMISSION_DECISIONS;
|
|
71254
71702
|
var init_permissionBridge = __esm({
|
|
71255
71703
|
"src/cli/serve/permissionBridge.ts"() {
|
|
71256
71704
|
"use strict";
|
|
71705
|
+
init_toolPermissions();
|
|
71257
71706
|
SERVE_PERMISSION_PRESETS = ["standard", "strict", "yolo"];
|
|
71258
71707
|
PRESET_ENV = "ZELARI_PERMISSION_PRESET";
|
|
71708
|
+
PERMISSION_DECISIONS = [
|
|
71709
|
+
"allow",
|
|
71710
|
+
"deny",
|
|
71711
|
+
"always-tool",
|
|
71712
|
+
"always-category"
|
|
71713
|
+
];
|
|
71714
|
+
}
|
|
71715
|
+
});
|
|
71716
|
+
|
|
71717
|
+
// src/cli/serve/askUserBridge.ts
|
|
71718
|
+
function createServeAskUserBridge(write, timeoutMs2 = askUserTimeoutMs()) {
|
|
71719
|
+
const pending = /* @__PURE__ */ new Map();
|
|
71720
|
+
let seq = 0;
|
|
71721
|
+
const settle = (requestId, answer, timedOut = false) => {
|
|
71722
|
+
const entry = pending.get(requestId);
|
|
71723
|
+
if (!entry) return false;
|
|
71724
|
+
pending.delete(requestId);
|
|
71725
|
+
clearTimeout(entry.timer);
|
|
71726
|
+
write(
|
|
71727
|
+
JSON.stringify({
|
|
71728
|
+
type: "ask_user.settled",
|
|
71729
|
+
requestId,
|
|
71730
|
+
answer,
|
|
71731
|
+
...timedOut ? { timedOut: true } : {}
|
|
71732
|
+
})
|
|
71733
|
+
);
|
|
71734
|
+
entry.resolve(answer);
|
|
71735
|
+
return true;
|
|
71736
|
+
};
|
|
71737
|
+
return {
|
|
71738
|
+
onAskUser(req) {
|
|
71739
|
+
const question = req.question.trim();
|
|
71740
|
+
const choices = req.choices.map((c) => c.trim()).filter(Boolean);
|
|
71741
|
+
if (choices.length < 2) return Promise.resolve(null);
|
|
71742
|
+
const requestId = `ask-${Date.now()}-${++seq}`;
|
|
71743
|
+
return new Promise((resolve9) => {
|
|
71744
|
+
const timer = setTimeout(() => {
|
|
71745
|
+
settle(requestId, null, true);
|
|
71746
|
+
}, timeoutMs2);
|
|
71747
|
+
pending.set(requestId, { resolve: resolve9, timer });
|
|
71748
|
+
write(
|
|
71749
|
+
JSON.stringify({
|
|
71750
|
+
type: "ask_user.request",
|
|
71751
|
+
requestId,
|
|
71752
|
+
question,
|
|
71753
|
+
choices,
|
|
71754
|
+
...req.context ? { context: req.context } : {}
|
|
71755
|
+
})
|
|
71756
|
+
);
|
|
71757
|
+
});
|
|
71758
|
+
},
|
|
71759
|
+
respond: (requestId, answer) => settle(requestId, answer, false),
|
|
71760
|
+
pendingCount: () => pending.size
|
|
71761
|
+
};
|
|
71762
|
+
}
|
|
71763
|
+
function serveAskUserRespond(bridge, params) {
|
|
71764
|
+
if (!params || typeof params !== "object") {
|
|
71765
|
+
return { accepted: false, reason: "ask_user.respond requires an object params" };
|
|
71766
|
+
}
|
|
71767
|
+
const { requestId, answer } = params;
|
|
71768
|
+
if (typeof requestId !== "string" || requestId.length === 0) {
|
|
71769
|
+
return { accepted: false, reason: "ask_user.respond requires a non-empty string requestId" };
|
|
71770
|
+
}
|
|
71771
|
+
if (answer !== null && typeof answer !== "string") {
|
|
71772
|
+
return { accepted: false, reason: "ask_user.respond answer must be a string or null" };
|
|
71773
|
+
}
|
|
71774
|
+
const text = typeof answer === "string" ? answer.trim() : null;
|
|
71775
|
+
return { accepted: bridge.respond(requestId, text && text.length > 0 ? text : null) };
|
|
71776
|
+
}
|
|
71777
|
+
var init_askUserBridge = __esm({
|
|
71778
|
+
"src/cli/serve/askUserBridge.ts"() {
|
|
71779
|
+
"use strict";
|
|
71780
|
+
init_askUserTimeout();
|
|
71259
71781
|
}
|
|
71260
71782
|
});
|
|
71261
71783
|
|
|
71262
71784
|
// src/cli/serve/spineLockSweep.ts
|
|
71263
71785
|
import { promises as fs47 } from "node:fs";
|
|
71264
|
-
import
|
|
71786
|
+
import path95 from "node:path";
|
|
71265
71787
|
async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
71266
71788
|
const dir = sessionsDir2 ?? resolveSessionsDir();
|
|
71267
71789
|
const onSwept = options.onSwept ?? ((sessionId2, reason) => {
|
|
@@ -71279,7 +71801,7 @@ async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
|
71279
71801
|
return result;
|
|
71280
71802
|
}
|
|
71281
71803
|
for (const sessionId2 of entries) {
|
|
71282
|
-
const lockPath2 =
|
|
71804
|
+
const lockPath2 = path95.join(dir, sessionId2, "writer.lock");
|
|
71283
71805
|
try {
|
|
71284
71806
|
const raw = await fs47.readFile(lockPath2, "utf-8");
|
|
71285
71807
|
let lockInfo = {};
|
|
@@ -71372,7 +71894,7 @@ function resolveTurnLspProvider(services) {
|
|
|
71372
71894
|
const candidate = services?.lspManager;
|
|
71373
71895
|
return candidate instanceof LspManager ? candidate : void 0;
|
|
71374
71896
|
}
|
|
71375
|
-
function createCliRunTurn(onPermissionAsk) {
|
|
71897
|
+
function createCliRunTurn(onPermissionAsk, onAskUser) {
|
|
71376
71898
|
let streamPromise = null;
|
|
71377
71899
|
const ensureStream = () => {
|
|
71378
71900
|
if (!streamPromise) {
|
|
@@ -71399,6 +71921,7 @@ function createCliRunTurn(onPermissionAsk) {
|
|
|
71399
71921
|
const { provider, model, stream } = await ensureStream();
|
|
71400
71922
|
const opts = bindHarnessTurnOptions(input, deps.session.workspaceRoot);
|
|
71401
71923
|
if (onPermissionAsk) opts.onPermissionAsk = onPermissionAsk;
|
|
71924
|
+
if (onAskUser) opts.onAskUser = onAskUser;
|
|
71402
71925
|
applyTurnPermissionPreset(input);
|
|
71403
71926
|
const lspProvider = resolveTurnLspProvider(deps.services);
|
|
71404
71927
|
const exitCode = await dispatchHeadlessTurn(
|
|
@@ -71434,6 +71957,7 @@ function startHarnessServer(options = {}) {
|
|
|
71434
71957
|
write(JSON.stringify(envelope));
|
|
71435
71958
|
};
|
|
71436
71959
|
const permissionBridge = createServePermissionBridge(write);
|
|
71960
|
+
const askUserBridge = createServeAskUserBridge(write);
|
|
71437
71961
|
const dispatch = async (req) => {
|
|
71438
71962
|
if (typeof req.method !== "string") {
|
|
71439
71963
|
return { id: req.id ?? null, ok: false, error: { code: "bad_request", message: "missing method" } };
|
|
@@ -71447,11 +71971,21 @@ function startHarnessServer(options = {}) {
|
|
|
71447
71971
|
result: servePermissionRespond(permissionBridge, params)
|
|
71448
71972
|
};
|
|
71449
71973
|
}
|
|
71974
|
+
case "ask_user.respond": {
|
|
71975
|
+
return {
|
|
71976
|
+
id: req.id ?? null,
|
|
71977
|
+
ok: true,
|
|
71978
|
+
result: serveAskUserRespond(askUserBridge, params)
|
|
71979
|
+
};
|
|
71980
|
+
}
|
|
71450
71981
|
case "session.create": {
|
|
71451
71982
|
const root = typeof params.workspaceRoot === "string" ? params.workspaceRoot : process.cwd();
|
|
71452
71983
|
const session = server.createSession({
|
|
71453
71984
|
workspaceRoot: root,
|
|
71454
|
-
runTurn: options.runTurn ?? createCliRunTurn(
|
|
71985
|
+
runTurn: options.runTurn ?? createCliRunTurn(
|
|
71986
|
+
asRegistryAskHandler(permissionBridge),
|
|
71987
|
+
askUserBridge.onAskUser
|
|
71988
|
+
)
|
|
71455
71989
|
});
|
|
71456
71990
|
return { id: req.id ?? null, ok: true, result: { sessionId: session.id, workspaceRoot: session.workspaceRoot } };
|
|
71457
71991
|
}
|
|
@@ -71605,6 +72139,7 @@ var init_harnessServer = __esm({
|
|
|
71605
72139
|
init_policyGate();
|
|
71606
72140
|
init_policyLoadMode();
|
|
71607
72141
|
init_permissionBridge();
|
|
72142
|
+
init_askUserBridge();
|
|
71608
72143
|
init_spineLockSweep();
|
|
71609
72144
|
}
|
|
71610
72145
|
});
|
|
@@ -72263,9 +72798,9 @@ async function runCompanionServe(opts = {}) {
|
|
|
72263
72798
|
return;
|
|
72264
72799
|
}
|
|
72265
72800
|
const url2 = parseUrl(req);
|
|
72266
|
-
const
|
|
72801
|
+
const path100 = url2.pathname.replace(/\/+$/, "") || "/";
|
|
72267
72802
|
try {
|
|
72268
|
-
if (req.method === "GET" && (
|
|
72803
|
+
if (req.method === "GET" && (path100 === "/health" || path100 === "/v1/health")) {
|
|
72269
72804
|
sendJson2(res, 200, {
|
|
72270
72805
|
ok: true,
|
|
72271
72806
|
service: "zelari-companion",
|
|
@@ -72277,18 +72812,18 @@ async function runCompanionServe(opts = {}) {
|
|
|
72277
72812
|
});
|
|
72278
72813
|
return;
|
|
72279
72814
|
}
|
|
72280
|
-
if (
|
|
72815
|
+
if (path100.startsWith("/v1")) {
|
|
72281
72816
|
if (!tokenMatches(token, getBearer(req))) {
|
|
72282
72817
|
sendJson2(res, 401, { ok: false, error: "unauthorized" });
|
|
72283
72818
|
return;
|
|
72284
72819
|
}
|
|
72285
72820
|
}
|
|
72286
|
-
if (req.method === "GET" &&
|
|
72821
|
+
if (req.method === "GET" && path100 === "/v1/config") {
|
|
72287
72822
|
const snap = buildDesktopConfigSnapshot();
|
|
72288
72823
|
sendJson2(res, 200, { ok: true, ...snap });
|
|
72289
72824
|
return;
|
|
72290
72825
|
}
|
|
72291
|
-
if (req.method === "GET" &&
|
|
72826
|
+
if (req.method === "GET" && path100 === "/v1/projects") {
|
|
72292
72827
|
sendJson2(res, 200, {
|
|
72293
72828
|
ok: true,
|
|
72294
72829
|
projects: projects.map((p3) => ({
|
|
@@ -72299,7 +72834,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
72299
72834
|
});
|
|
72300
72835
|
return;
|
|
72301
72836
|
}
|
|
72302
|
-
if (req.method === "GET" &&
|
|
72837
|
+
if (req.method === "GET" && path100 === "/v1/runs") {
|
|
72303
72838
|
sendJson2(res, 200, {
|
|
72304
72839
|
ok: true,
|
|
72305
72840
|
active: runs.getActive(),
|
|
@@ -72317,7 +72852,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
72317
72852
|
});
|
|
72318
72853
|
return;
|
|
72319
72854
|
}
|
|
72320
|
-
if (req.method === "POST" &&
|
|
72855
|
+
if (req.method === "POST" && path100 === "/v1/runs") {
|
|
72321
72856
|
const raw = await readBody(req);
|
|
72322
72857
|
let body = {};
|
|
72323
72858
|
try {
|
|
@@ -72365,7 +72900,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
72365
72900
|
});
|
|
72366
72901
|
return;
|
|
72367
72902
|
}
|
|
72368
|
-
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(
|
|
72903
|
+
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path100);
|
|
72369
72904
|
if (req.method === "GET" && eventsMatch) {
|
|
72370
72905
|
const runId = eventsMatch[1];
|
|
72371
72906
|
const run = runs.getRun(runId);
|
|
@@ -72430,7 +72965,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
72430
72965
|
}, 500);
|
|
72431
72966
|
return;
|
|
72432
72967
|
}
|
|
72433
|
-
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(
|
|
72968
|
+
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path100);
|
|
72434
72969
|
if (req.method === "POST" && cancelMatch) {
|
|
72435
72970
|
const runId = cancelMatch[1];
|
|
72436
72971
|
const result = runs.cancel(runId);
|
|
@@ -72441,7 +72976,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
72441
72976
|
sendJson2(res, 200, { ok: true, cancelled: runId });
|
|
72442
72977
|
return;
|
|
72443
72978
|
}
|
|
72444
|
-
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(
|
|
72979
|
+
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(path100);
|
|
72445
72980
|
if (req.method === "POST" && steerMatch) {
|
|
72446
72981
|
const runId = steerMatch[1];
|
|
72447
72982
|
const raw = await readBody(req);
|
|
@@ -72610,11 +73145,11 @@ import { execSync as execSync2 } from "node:child_process";
|
|
|
72610
73145
|
import { existsSync as existsSync62, readFileSync as readFileSync46, readlinkSync, statSync as statSync10 } from "node:fs";
|
|
72611
73146
|
import { createRequire as createRequire3 } from "node:module";
|
|
72612
73147
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
72613
|
-
import
|
|
73148
|
+
import path96 from "node:path";
|
|
72614
73149
|
function findPackageRoot(start) {
|
|
72615
73150
|
let dir = start;
|
|
72616
73151
|
for (let i = 0; i < 6; i += 1) {
|
|
72617
|
-
const candidate =
|
|
73152
|
+
const candidate = path96.join(dir, "package.json");
|
|
72618
73153
|
if (existsSync62(candidate)) {
|
|
72619
73154
|
try {
|
|
72620
73155
|
const pkg = JSON.parse(readFileSync46(candidate, "utf8"));
|
|
@@ -72622,11 +73157,11 @@ function findPackageRoot(start) {
|
|
|
72622
73157
|
} catch {
|
|
72623
73158
|
}
|
|
72624
73159
|
}
|
|
72625
|
-
const parent =
|
|
73160
|
+
const parent = path96.dirname(dir);
|
|
72626
73161
|
if (parent === dir) break;
|
|
72627
73162
|
dir = parent;
|
|
72628
73163
|
}
|
|
72629
|
-
return
|
|
73164
|
+
return path96.resolve(__dirname3, "..", "..", "..");
|
|
72630
73165
|
}
|
|
72631
73166
|
function tryExec(cmd) {
|
|
72632
73167
|
try {
|
|
@@ -72640,14 +73175,19 @@ function tryExec(cmd) {
|
|
|
72640
73175
|
}
|
|
72641
73176
|
function readPackageJson4() {
|
|
72642
73177
|
try {
|
|
72643
|
-
const pkgPath =
|
|
73178
|
+
const pkgPath = path96.join(packageRoot, "package.json");
|
|
72644
73179
|
return JSON.parse(readFileSync46(pkgPath, "utf8"));
|
|
72645
73180
|
} catch {
|
|
72646
73181
|
return null;
|
|
72647
73182
|
}
|
|
72648
73183
|
}
|
|
72649
73184
|
function getGlobalPrefix() {
|
|
72650
|
-
|
|
73185
|
+
const fromNpm = tryExec("npm prefix -g");
|
|
73186
|
+
if (fromNpm) return fromNpm;
|
|
73187
|
+
return (process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX || "").trim();
|
|
73188
|
+
}
|
|
73189
|
+
function isSourceCheckout() {
|
|
73190
|
+
return existsSync62(path96.join(packageRoot, "src", "cli", "main.ts")) && existsSync62(path96.join(packageRoot, "apps", "desktop", "package.json"));
|
|
72651
73191
|
}
|
|
72652
73192
|
function checkShim(pkgName) {
|
|
72653
73193
|
const prefix = getGlobalPrefix();
|
|
@@ -72656,8 +73196,16 @@ function checkShim(pkgName) {
|
|
|
72656
73196
|
}
|
|
72657
73197
|
const isWin = process.platform === "win32";
|
|
72658
73198
|
const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
|
|
72659
|
-
const shimPath =
|
|
73199
|
+
const shimPath = path96.join(prefix, shimName);
|
|
72660
73200
|
if (!existsSync62(shimPath)) {
|
|
73201
|
+
const localBin = path96.join(packageRoot, "bin", "zelari-code.js");
|
|
73202
|
+
if (isSourceCheckout() && existsSync62(localBin)) {
|
|
73203
|
+
return WARN(
|
|
73204
|
+
`global shim not found at ${shimPath}
|
|
73205
|
+
source checkout \u2014 using ${localBin}
|
|
73206
|
+
optional: npm install -g ${pkgName}@latest --force`
|
|
73207
|
+
);
|
|
73208
|
+
}
|
|
72661
73209
|
return FAIL(
|
|
72662
73210
|
`shim not found at ${shimPath}
|
|
72663
73211
|
fix: npm install -g ${pkgName}@latest --force`
|
|
@@ -72684,8 +73232,8 @@ function checkShim(pkgName) {
|
|
|
72684
73232
|
fix: npm install -g ${pkgName}@latest --force`
|
|
72685
73233
|
);
|
|
72686
73234
|
}
|
|
72687
|
-
const resolved =
|
|
72688
|
-
const expected =
|
|
73235
|
+
const resolved = path96.resolve(path96.dirname(shimPath), target);
|
|
73236
|
+
const expected = path96.join(
|
|
72689
73237
|
prefix,
|
|
72690
73238
|
"node_modules",
|
|
72691
73239
|
pkgName,
|
|
@@ -72727,7 +73275,7 @@ function checkNode(pkg) {
|
|
|
72727
73275
|
return OK(`node ${raw} (engines.node ${enginesNode ?? ">= 20.0.0"})`);
|
|
72728
73276
|
}
|
|
72729
73277
|
function checkBundle() {
|
|
72730
|
-
const bundle =
|
|
73278
|
+
const bundle = path96.join(packageRoot, "dist", "cli", "main.bundled.js");
|
|
72731
73279
|
if (!existsSync62(bundle)) {
|
|
72732
73280
|
return FAIL(
|
|
72733
73281
|
`dist/cli/main.bundled.js missing at ${bundle}
|
|
@@ -72748,7 +73296,7 @@ function checkRuntimeDeps() {
|
|
|
72748
73296
|
const missing = [];
|
|
72749
73297
|
for (const dep of required2) {
|
|
72750
73298
|
try {
|
|
72751
|
-
const localReq = createRequire3(
|
|
73299
|
+
const localReq = createRequire3(path96.join(packageRoot, "package.json"));
|
|
72752
73300
|
localReq.resolve(dep);
|
|
72753
73301
|
} catch {
|
|
72754
73302
|
missing.push(dep);
|
|
@@ -73025,7 +73573,7 @@ var init_doctor = __esm({
|
|
|
73025
73573
|
init_metrics3();
|
|
73026
73574
|
init_contextGrowthSummary();
|
|
73027
73575
|
require3 = createRequire3(import.meta.url);
|
|
73028
|
-
__dirname3 =
|
|
73576
|
+
__dirname3 = path96.dirname(fileURLToPath3(import.meta.url));
|
|
73029
73577
|
packageRoot = findPackageRoot(__dirname3);
|
|
73030
73578
|
OK = (message) => ({
|
|
73031
73579
|
ok: true,
|
|
@@ -73052,16 +73600,15 @@ __export(fixPath_exports, {
|
|
|
73052
73600
|
});
|
|
73053
73601
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
73054
73602
|
function getGlobalPrefix2() {
|
|
73055
|
-
|
|
73056
|
-
|
|
73057
|
-
|
|
73058
|
-
|
|
73059
|
-
|
|
73060
|
-
|
|
73061
|
-
|
|
73062
|
-
|
|
73063
|
-
|
|
73064
|
-
})();
|
|
73603
|
+
try {
|
|
73604
|
+
const fromNpm = spawnSync3("npm", ["prefix", "-g"], {
|
|
73605
|
+
encoding: "utf8",
|
|
73606
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
73607
|
+
}).stdout?.trim() ?? "";
|
|
73608
|
+
if (fromNpm) return fromNpm;
|
|
73609
|
+
} catch {
|
|
73610
|
+
}
|
|
73611
|
+
return (process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX || "").trim();
|
|
73065
73612
|
}
|
|
73066
73613
|
function powershell(script) {
|
|
73067
73614
|
try {
|
|
@@ -73135,7 +73682,7 @@ __export(userSettings_exports, {
|
|
|
73135
73682
|
settingsOverrides: () => settingsOverrides
|
|
73136
73683
|
});
|
|
73137
73684
|
import { existsSync as existsSync63, readFileSync as readFileSync47 } from "node:fs";
|
|
73138
|
-
import
|
|
73685
|
+
import path97 from "node:path";
|
|
73139
73686
|
function parseBool(raw) {
|
|
73140
73687
|
const v = raw.trim().toLowerCase();
|
|
73141
73688
|
if (["1", "true", "yes", "on"].includes(v)) return true;
|
|
@@ -73202,8 +73749,8 @@ function envValueFor(key, env) {
|
|
|
73202
73749
|
function resolveUserSettings(opts = {}) {
|
|
73203
73750
|
const cwd = opts.cwd ?? process.cwd();
|
|
73204
73751
|
const env = opts.env ?? process.env;
|
|
73205
|
-
const userPath =
|
|
73206
|
-
const projectPath =
|
|
73752
|
+
const userPath = path97.join(zelariHome(), SETTINGS_FILE_NAME);
|
|
73753
|
+
const projectPath = path97.join(cwd, ".zelari", SETTINGS_FILE_NAME);
|
|
73207
73754
|
const warnings = [];
|
|
73208
73755
|
const userLayer = loadFileLayer(userPath, "user", warnings);
|
|
73209
73756
|
const projectLayer = loadFileLayer(projectPath, "project", warnings);
|
|
@@ -73417,7 +73964,7 @@ __export(inspectSession_exports, {
|
|
|
73417
73964
|
renderInspectReport: () => renderInspectReport,
|
|
73418
73965
|
runInspectSession: () => runInspectSession
|
|
73419
73966
|
});
|
|
73420
|
-
import
|
|
73967
|
+
import path98 from "node:path";
|
|
73421
73968
|
import { existsSync as existsSync64 } from "node:fs";
|
|
73422
73969
|
function formatLimit(limit) {
|
|
73423
73970
|
return `${Math.round(limit / 1e3)}k`;
|
|
@@ -73451,8 +73998,8 @@ function renderInspectReport(state3) {
|
|
|
73451
73998
|
}
|
|
73452
73999
|
async function runInspectSession(opts) {
|
|
73453
74000
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.cwd ?? process.cwd() });
|
|
73454
|
-
const sessionDir =
|
|
73455
|
-
const eventsPath =
|
|
74001
|
+
const sessionDir = path98.join(sessionsDir2, opts.sessionId);
|
|
74002
|
+
const eventsPath = path98.join(sessionDir, "events.jsonl");
|
|
73456
74003
|
if (!existsSync64(sessionDir)) {
|
|
73457
74004
|
console.error(`zelari-code inspect: no session directory at ${sessionDir}`);
|
|
73458
74005
|
return 1;
|
|
@@ -73486,14 +74033,14 @@ __export(inspect_exports, {
|
|
|
73486
74033
|
collectInspectReport: () => collectInspectReport,
|
|
73487
74034
|
runInspect: () => runInspect
|
|
73488
74035
|
});
|
|
73489
|
-
import
|
|
74036
|
+
import path99 from "node:path";
|
|
73490
74037
|
import { existsSync as existsSync65, readFileSync as readFileSync48, readdirSync as readdirSync13 } from "node:fs";
|
|
73491
74038
|
async function collectInspectReport(cwd = process.cwd()) {
|
|
73492
74039
|
ensureBuiltinSkillsLoadedSync();
|
|
73493
74040
|
const snap = listSkillsSnapshot(cwd);
|
|
73494
74041
|
const mcp = listMcpServers(cwd);
|
|
73495
|
-
const userMcpPath =
|
|
73496
|
-
const projectMcpPath =
|
|
74042
|
+
const userMcpPath = path99.join(zelariHome(), "mcp.json");
|
|
74043
|
+
const projectMcpPath = path99.join(cwd, ".zelari", "mcp.json");
|
|
73497
74044
|
const globalHooks = globalHooksDir();
|
|
73498
74045
|
const projectHooks = projectHooksDir(cwd);
|
|
73499
74046
|
const projectTrusted = isFolderTrusted(cwd);
|
|
@@ -73521,9 +74068,9 @@ async function collectInspectReport(cwd = process.cwd()) {
|
|
|
73521
74068
|
configSources: [
|
|
73522
74069
|
{ path: userMcpPath, exists: existsSync65(userMcpPath) },
|
|
73523
74070
|
{ path: projectMcpPath, exists: existsSync65(projectMcpPath) },
|
|
73524
|
-
{ path:
|
|
73525
|
-
{ path:
|
|
73526
|
-
{ path:
|
|
74071
|
+
{ path: path99.join(zelariHome(), "provider.json"), exists: existsSync65(path99.join(zelariHome(), "provider.json")) },
|
|
74072
|
+
{ path: path99.join(cwd, ".zelari", "AGENTS.md"), exists: existsSync65(path99.join(cwd, ".zelari", "AGENTS.md")) },
|
|
74073
|
+
{ path: path99.join(cwd, "AGENTS.md"), exists: existsSync65(path99.join(cwd, "AGENTS.md")) }
|
|
73527
74074
|
],
|
|
73528
74075
|
skills: {
|
|
73529
74076
|
total: snap.skills.length,
|
|
@@ -73563,8 +74110,8 @@ function listJsonFiles(dir) {
|
|
|
73563
74110
|
}
|
|
73564
74111
|
function findAgentsMd(cwd) {
|
|
73565
74112
|
const candidates = [
|
|
73566
|
-
|
|
73567
|
-
|
|
74113
|
+
path99.join(cwd, "AGENTS.md"),
|
|
74114
|
+
path99.join(cwd, ".zelari", "AGENTS.md")
|
|
73568
74115
|
];
|
|
73569
74116
|
const found = [];
|
|
73570
74117
|
for (const c of candidates) {
|
|
@@ -76700,22 +77247,7 @@ init_spineTelemetry();
|
|
|
76700
77247
|
|
|
76701
77248
|
// src/cli/hooks/permissionPicker.ts
|
|
76702
77249
|
init_toolPermissions();
|
|
76703
|
-
|
|
76704
|
-
// src/cli/hooks/askUserTimeout.ts
|
|
76705
|
-
function askUserTimeoutMs() {
|
|
76706
|
-
const raw = process.env.ZELARI_ASK_USER_TIMEOUT_MS?.trim();
|
|
76707
|
-
if (!raw) return 3e5;
|
|
76708
|
-
const n = Number.parseInt(raw, 10);
|
|
76709
|
-
if (!Number.isFinite(n) || n < 0) return 3e5;
|
|
76710
|
-
return n;
|
|
76711
|
-
}
|
|
76712
|
-
function armPickerTimeout(onFire, ms) {
|
|
76713
|
-
if (ms <= 0) return () => void 0;
|
|
76714
|
-
const id3 = setTimeout(onFire, ms);
|
|
76715
|
-
return () => clearTimeout(id3);
|
|
76716
|
-
}
|
|
76717
|
-
|
|
76718
|
-
// src/cli/hooks/permissionPicker.ts
|
|
77250
|
+
init_askUserTimeout();
|
|
76719
77251
|
function createPermissionAskHandler(opts) {
|
|
76720
77252
|
const { setPicker: setPicker2, appendSystem: appendSystem2 } = opts;
|
|
76721
77253
|
return (req) => new Promise((resolve9) => {
|
|
@@ -76808,6 +77340,7 @@ ${detail}${note}${claimsBlock}
|
|
|
76808
77340
|
}
|
|
76809
77341
|
|
|
76810
77342
|
// src/cli/hooks/useChatTurn.ts
|
|
77343
|
+
init_askUserTimeout();
|
|
76811
77344
|
init_toolPermissions();
|
|
76812
77345
|
init_skills2();
|
|
76813
77346
|
init_fileStateStore();
|
|
@@ -78737,6 +79270,7 @@ init_permissionBroker();
|
|
|
78737
79270
|
init_brokerHandlers();
|
|
78738
79271
|
import { useEffect as useEffect5, useRef as useRef5 } from "react";
|
|
78739
79272
|
init_messageHelpers();
|
|
79273
|
+
init_askUserTimeout();
|
|
78740
79274
|
function usePermissionBroker(opts) {
|
|
78741
79275
|
const { setPicker: setPicker2, setMessages } = opts;
|
|
78742
79276
|
const handleRef = useRef5(null);
|
|
@@ -78832,10 +79366,10 @@ init_ledger();
|
|
|
78832
79366
|
|
|
78833
79367
|
// src/cli/evolution/proposals.ts
|
|
78834
79368
|
import { existsSync as existsSync51, readFileSync as readFileSync39 } from "node:fs";
|
|
78835
|
-
import
|
|
78836
|
-
var PROPOSALS_REL =
|
|
79369
|
+
import path77 from "node:path";
|
|
79370
|
+
var PROPOSALS_REL = path77.join(".zelari", "evolution", "proposals.jsonl");
|
|
78837
79371
|
function proposalsPath(cwd) {
|
|
78838
|
-
return
|
|
79372
|
+
return path77.join(cwd, PROPOSALS_REL);
|
|
78839
79373
|
}
|
|
78840
79374
|
function readProposalStore(cwd) {
|
|
78841
79375
|
const file2 = proposalsPath(cwd);
|
|
@@ -79927,11 +80461,11 @@ function handleCacheStats(ctx) {
|
|
|
79927
80461
|
init_messageHelpers();
|
|
79928
80462
|
init_serviceFactory();
|
|
79929
80463
|
import { promises as fs35 } from "node:fs";
|
|
79930
|
-
import * as
|
|
80464
|
+
import * as path79 from "node:path";
|
|
79931
80465
|
|
|
79932
80466
|
// src/cli/memory/promotion.ts
|
|
79933
80467
|
import { promises as fs34 } from "node:fs";
|
|
79934
|
-
import * as
|
|
80468
|
+
import * as path78 from "node:path";
|
|
79935
80469
|
var START = "<!-- zelari:memory-promotions:start -->";
|
|
79936
80470
|
var END = "<!-- zelari:memory-promotions:end -->";
|
|
79937
80471
|
var DURABLE_KINDS = /* @__PURE__ */ new Set(["fact", "decision", "constraint", "preference", "procedure"]);
|
|
@@ -79942,16 +80476,16 @@ function lineFor(node) {
|
|
|
79942
80476
|
}
|
|
79943
80477
|
async function promoteMemoryToAgentsMd(projectRoot, node) {
|
|
79944
80478
|
if (node.status !== "active") {
|
|
79945
|
-
return { added: false, path:
|
|
80479
|
+
return { added: false, path: path78.join(projectRoot, "AGENTS.md"), reason: `memory is ${node.status}` };
|
|
79946
80480
|
}
|
|
79947
80481
|
if (!DURABLE_KINDS.has(node.kind)) {
|
|
79948
|
-
return { added: false, path:
|
|
80482
|
+
return { added: false, path: path78.join(projectRoot, "AGENTS.md"), reason: `${node.kind} is not a durable instruction kind` };
|
|
79949
80483
|
}
|
|
79950
|
-
const root = await fs34.realpath(projectRoot).catch(() =>
|
|
79951
|
-
const target =
|
|
80484
|
+
const root = await fs34.realpath(projectRoot).catch(() => path78.resolve(projectRoot));
|
|
80485
|
+
const target = path78.join(root, "AGENTS.md");
|
|
79952
80486
|
try {
|
|
79953
|
-
const
|
|
79954
|
-
if (
|
|
80487
|
+
const stat8 = await fs34.lstat(target);
|
|
80488
|
+
if (stat8.isSymbolicLink() || !stat8.isFile()) throw new Error("AGENTS.md must be a regular project file.");
|
|
79955
80489
|
} catch (error51) {
|
|
79956
80490
|
if (error51.code !== "ENOENT") throw error51;
|
|
79957
80491
|
}
|
|
@@ -80013,25 +80547,25 @@ function sourceLine(source2) {
|
|
|
80013
80547
|
return entries.length ? entries.map(([key, value]) => `${key}=${value}`).join(" \xB7 ") : "unknown";
|
|
80014
80548
|
}
|
|
80015
80549
|
function isInside(root, target) {
|
|
80016
|
-
const relative6 =
|
|
80017
|
-
return relative6 === "" || !relative6.startsWith("..") && !
|
|
80550
|
+
const relative6 = path79.relative(root, target);
|
|
80551
|
+
return relative6 === "" || !relative6.startsWith("..") && !path79.isAbsolute(relative6);
|
|
80018
80552
|
}
|
|
80019
80553
|
async function safeExportPath(cwd, requested) {
|
|
80020
|
-
const lexicalRoot =
|
|
80554
|
+
const lexicalRoot = path79.resolve(cwd);
|
|
80021
80555
|
const root = await fs35.realpath(lexicalRoot).catch(() => lexicalRoot);
|
|
80022
|
-
const fallback =
|
|
80023
|
-
const target = requested?.trim() ?
|
|
80556
|
+
const fallback = path79.join(root, ".zelari", "memory", `export-${Date.now()}.json`);
|
|
80557
|
+
const target = requested?.trim() ? path79.resolve(root, requested.trim()) : fallback;
|
|
80024
80558
|
if (!isInside(root, target)) {
|
|
80025
80559
|
throw new Error("Export path must stay inside the active project.");
|
|
80026
80560
|
}
|
|
80027
|
-
const parent =
|
|
80028
|
-
const relativeParent =
|
|
80561
|
+
const parent = path79.dirname(target);
|
|
80562
|
+
const relativeParent = path79.relative(root, parent);
|
|
80029
80563
|
let cursor = root;
|
|
80030
|
-
for (const segment of relativeParent.split(
|
|
80031
|
-
cursor =
|
|
80564
|
+
for (const segment of relativeParent.split(path79.sep).filter(Boolean)) {
|
|
80565
|
+
cursor = path79.join(cursor, segment);
|
|
80032
80566
|
try {
|
|
80033
|
-
const
|
|
80034
|
-
if (
|
|
80567
|
+
const stat8 = await fs35.lstat(cursor);
|
|
80568
|
+
if (stat8.isSymbolicLink()) {
|
|
80035
80569
|
throw new Error("Export path must not traverse a symbolic link.");
|
|
80036
80570
|
}
|
|
80037
80571
|
} catch (error51) {
|
|
@@ -80200,9 +80734,9 @@ ${message}` : message
|
|
|
80200
80734
|
}
|
|
80201
80735
|
case "export": {
|
|
80202
80736
|
const target = await safeExportPath(ctx.cwd, args.join(" ").trim() || void 0);
|
|
80203
|
-
await fs35.mkdir(
|
|
80204
|
-
const root = await fs35.realpath(ctx.cwd).catch(() =>
|
|
80205
|
-
const realParent = await fs35.realpath(
|
|
80737
|
+
await fs35.mkdir(path79.dirname(target), { recursive: true });
|
|
80738
|
+
const root = await fs35.realpath(ctx.cwd).catch(() => path79.resolve(ctx.cwd));
|
|
80739
|
+
const realParent = await fs35.realpath(path79.dirname(target));
|
|
80206
80740
|
if (!isInside(root, realParent)) {
|
|
80207
80741
|
throw new Error("Export path resolves outside the active project.");
|
|
80208
80742
|
}
|
|
@@ -80417,7 +80951,7 @@ import { promises as fs37 } from "node:fs";
|
|
|
80417
80951
|
init_zod();
|
|
80418
80952
|
init_taskTool();
|
|
80419
80953
|
import { promises as fs36 } from "node:fs";
|
|
80420
|
-
import
|
|
80954
|
+
import path80 from "node:path";
|
|
80421
80955
|
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
80422
80956
|
var CsvFanoutArgsSchema = external_exports.object({
|
|
80423
80957
|
csv_path: external_exports.string().min(1),
|
|
@@ -80511,8 +81045,8 @@ function resolveMaxConcurrency(env = process.env) {
|
|
|
80511
81045
|
}
|
|
80512
81046
|
async function runCsvFanout(args, deps, opts) {
|
|
80513
81047
|
const start = Date.now();
|
|
80514
|
-
const absCsv =
|
|
80515
|
-
const absOut =
|
|
81048
|
+
const absCsv = path80.isAbsolute(args.csv_path) ? args.csv_path : path80.join(opts.parentCwd, args.csv_path);
|
|
81049
|
+
const absOut = path80.isAbsolute(args.output_csv_path) ? args.output_csv_path : path80.join(opts.parentCwd, args.output_csv_path);
|
|
80516
81050
|
const { headers: headers2, rows } = await readCsv(absCsv);
|
|
80517
81051
|
if (headers2.length === 0) {
|
|
80518
81052
|
throw new Error(`kraken_csv_fanout: ${absCsv} is empty`);
|
|
@@ -80568,7 +81102,7 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
80568
81102
|
errored += 1;
|
|
80569
81103
|
errors.push(`${row[args.id_column] ?? i}: ${res.error}`);
|
|
80570
81104
|
}
|
|
80571
|
-
await fs36.mkdir(
|
|
81105
|
+
await fs36.mkdir(path80.dirname(absOut), { recursive: true });
|
|
80572
81106
|
await queueWrite(serializeCsv(outHeaders, outputRecords));
|
|
80573
81107
|
}
|
|
80574
81108
|
}
|
|
@@ -80763,7 +81297,7 @@ function splitArgs(s) {
|
|
|
80763
81297
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
80764
81298
|
init_messageHelpers();
|
|
80765
81299
|
import { promises as fs38 } from "node:fs";
|
|
80766
|
-
import
|
|
81300
|
+
import path81 from "node:path";
|
|
80767
81301
|
|
|
80768
81302
|
// src/cli/kraken/workbenchView.ts
|
|
80769
81303
|
var EMPTY = {
|
|
@@ -80880,17 +81414,17 @@ function formatWorkbenchForTerminal(p3) {
|
|
|
80880
81414
|
|
|
80881
81415
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
80882
81416
|
async function handleKrakenWorkbench(ctx) {
|
|
80883
|
-
const dir =
|
|
81417
|
+
const dir = path81.join(ctx.cwd, ".zelari", "radio");
|
|
80884
81418
|
let latest = null;
|
|
80885
81419
|
let latestMtime = 0;
|
|
80886
81420
|
try {
|
|
80887
81421
|
const files = await fs38.readdir(dir);
|
|
80888
81422
|
for (const f of files) {
|
|
80889
81423
|
if (!f.startsWith("workbench-") || !f.endsWith(".md")) continue;
|
|
80890
|
-
const full =
|
|
80891
|
-
const
|
|
80892
|
-
if (
|
|
80893
|
-
latestMtime =
|
|
81424
|
+
const full = path81.join(dir, f);
|
|
81425
|
+
const stat8 = await fs38.stat(full);
|
|
81426
|
+
if (stat8.mtimeMs > latestMtime) {
|
|
81427
|
+
latestMtime = stat8.mtimeMs;
|
|
80894
81428
|
latest = full;
|
|
80895
81429
|
}
|
|
80896
81430
|
}
|
|
@@ -80904,10 +81438,10 @@ async function handleKrakenWorkbench(ctx) {
|
|
|
80904
81438
|
const parsed = parseWorkbench(content);
|
|
80905
81439
|
const rendered = formatWorkbenchForTerminal(parsed);
|
|
80906
81440
|
if (!rendered.trim()) {
|
|
80907
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
81441
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path81.basename(latest)}: (no nodes / no events yet)`);
|
|
80908
81442
|
return;
|
|
80909
81443
|
}
|
|
80910
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
81444
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path81.basename(latest)}:
|
|
80911
81445
|
${rendered}`);
|
|
80912
81446
|
}
|
|
80913
81447
|
|
|
@@ -81215,14 +81749,14 @@ ${result.output.split("\n").slice(-8).join("\n")}` : "";
|
|
|
81215
81749
|
init_messageHelpers();
|
|
81216
81750
|
init_paths();
|
|
81217
81751
|
import { promises as fs39 } from "node:fs";
|
|
81218
|
-
import
|
|
81752
|
+
import path84 from "node:path";
|
|
81219
81753
|
async function handlePromoteMember(ctx, memberId) {
|
|
81220
81754
|
try {
|
|
81221
81755
|
const { promoteMember: promoteMember2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
81222
81756
|
const { skill, markdown } = promoteMember2(memberId);
|
|
81223
81757
|
const skillDir = skillsDir();
|
|
81224
81758
|
await fs39.mkdir(skillDir, { recursive: true });
|
|
81225
|
-
const filePath =
|
|
81759
|
+
const filePath = path84.join(skillDir, `${skill.id}.md`);
|
|
81226
81760
|
const previous = await fs39.readFile(filePath, "utf8").catch(() => null);
|
|
81227
81761
|
const { createHash: createHash24 } = await import("node:crypto");
|
|
81228
81762
|
const sha = (s) => createHash24("sha256").update(s, "utf8").digest("hex");
|
|
@@ -81248,7 +81782,7 @@ ${lineage}
|
|
|
81248
81782
|
// src/cli/branchManager.ts
|
|
81249
81783
|
init_paths();
|
|
81250
81784
|
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";
|
|
81251
|
-
import
|
|
81785
|
+
import path85 from "node:path";
|
|
81252
81786
|
var META_FILENAME = "meta.json";
|
|
81253
81787
|
var SESSIONS_SUBDIR = "sessions";
|
|
81254
81788
|
function getBranchesBaseDir() {
|
|
@@ -81258,13 +81792,13 @@ function getSessionsBaseDir() {
|
|
|
81258
81792
|
return sessionsDir();
|
|
81259
81793
|
}
|
|
81260
81794
|
function branchPathFor(name, baseDir) {
|
|
81261
|
-
return
|
|
81795
|
+
return path85.join(baseDir, name);
|
|
81262
81796
|
}
|
|
81263
81797
|
function metaPathFor(name, baseDir) {
|
|
81264
|
-
return
|
|
81798
|
+
return path85.join(baseDir, name, META_FILENAME);
|
|
81265
81799
|
}
|
|
81266
81800
|
function sessionsPathFor(name, baseDir) {
|
|
81267
|
-
return
|
|
81801
|
+
return path85.join(baseDir, name, SESSIONS_SUBDIR);
|
|
81268
81802
|
}
|
|
81269
81803
|
function readBranchMeta(name, baseDir) {
|
|
81270
81804
|
const metaPath = metaPathFor(name, baseDir);
|
|
@@ -81289,7 +81823,7 @@ function readBranchMeta(name, baseDir) {
|
|
|
81289
81823
|
}
|
|
81290
81824
|
function writeBranchMeta(name, baseDir, meta3) {
|
|
81291
81825
|
const metaPath = metaPathFor(name, baseDir);
|
|
81292
|
-
mkdirSync21(
|
|
81826
|
+
mkdirSync21(path85.dirname(metaPath), { recursive: true });
|
|
81293
81827
|
writeFileSync24(metaPath, JSON.stringify(meta3, null, 2), "utf-8");
|
|
81294
81828
|
}
|
|
81295
81829
|
async function countSessions(name, baseDir) {
|
|
@@ -81340,14 +81874,14 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
81340
81874
|
if (branchExists(name, baseDir)) {
|
|
81341
81875
|
throw new BranchAlreadyExistsError(name);
|
|
81342
81876
|
}
|
|
81343
|
-
const sourcePath =
|
|
81877
|
+
const sourcePath = path85.join(sessionsBaseDir, `${fromSessionId}.jsonl`);
|
|
81344
81878
|
if (!existsSync55(sourcePath)) {
|
|
81345
81879
|
throw new SessionNotFoundError(`Source session "${fromSessionId}" not found at ${sourcePath}`);
|
|
81346
81880
|
}
|
|
81347
81881
|
const branchPath = branchPathFor(name, baseDir);
|
|
81348
81882
|
const branchSessionsPath = sessionsPathFor(name, baseDir);
|
|
81349
81883
|
mkdirSync21(branchSessionsPath, { recursive: true });
|
|
81350
|
-
const destPath =
|
|
81884
|
+
const destPath = path85.join(branchSessionsPath, `${fromSessionId}.jsonl`);
|
|
81351
81885
|
await fs40.copyFile(sourcePath, destPath);
|
|
81352
81886
|
const meta3 = {
|
|
81353
81887
|
name,
|
|
@@ -81451,14 +81985,14 @@ async function handleBranchCheckout(ctx, branchName) {
|
|
|
81451
81985
|
// src/cli/slashHandlers/workspace.ts
|
|
81452
81986
|
init_messageHelpers();
|
|
81453
81987
|
import { promises as fs41 } from "node:fs";
|
|
81454
|
-
import
|
|
81988
|
+
import path86 from "node:path";
|
|
81455
81989
|
async function handleWorkspaceShow(ctx, what) {
|
|
81456
81990
|
try {
|
|
81457
|
-
const zelari =
|
|
81991
|
+
const zelari = path86.join(process.cwd(), ".zelari");
|
|
81458
81992
|
let content;
|
|
81459
81993
|
switch (what) {
|
|
81460
81994
|
case "plan": {
|
|
81461
|
-
const planPath =
|
|
81995
|
+
const planPath = path86.join(zelari, "plan.md");
|
|
81462
81996
|
try {
|
|
81463
81997
|
content = await fs41.readFile(planPath, "utf-8");
|
|
81464
81998
|
} catch {
|
|
@@ -81467,7 +82001,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
81467
82001
|
break;
|
|
81468
82002
|
}
|
|
81469
82003
|
case "decisions": {
|
|
81470
|
-
const decisionsDir =
|
|
82004
|
+
const decisionsDir = path86.join(zelari, "decisions");
|
|
81471
82005
|
try {
|
|
81472
82006
|
const files = (await fs41.readdir(decisionsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
81473
82007
|
if (files.length === 0) {
|
|
@@ -81477,7 +82011,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
81477
82011
|
`];
|
|
81478
82012
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
81479
82013
|
for (const f of files) {
|
|
81480
|
-
const raw = await fs41.readFile(
|
|
82014
|
+
const raw = await fs41.readFile(path86.join(decisionsDir, f), "utf-8");
|
|
81481
82015
|
const { meta: meta3, body } = parseFrontmatter2(raw);
|
|
81482
82016
|
const title = meta3.title ?? body.split("\n")[0]?.replace(/^#\s*/, "").trim() ?? f;
|
|
81483
82017
|
lines.push(`- **${f.replace(/\.md$/, "")}** [${meta3.status ?? "unknown"}] ${title}`);
|
|
@@ -81490,7 +82024,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
81490
82024
|
break;
|
|
81491
82025
|
}
|
|
81492
82026
|
case "risks": {
|
|
81493
|
-
const risksPath =
|
|
82027
|
+
const risksPath = path86.join(zelari, "risks.md");
|
|
81494
82028
|
try {
|
|
81495
82029
|
content = await fs41.readFile(risksPath, "utf-8");
|
|
81496
82030
|
} catch {
|
|
@@ -81499,7 +82033,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
81499
82033
|
break;
|
|
81500
82034
|
}
|
|
81501
82035
|
case "agents": {
|
|
81502
|
-
const agentsPath =
|
|
82036
|
+
const agentsPath = path86.join(process.cwd(), "AGENTS.MD");
|
|
81503
82037
|
try {
|
|
81504
82038
|
content = await fs41.readFile(agentsPath, "utf-8");
|
|
81505
82039
|
} catch {
|
|
@@ -81508,7 +82042,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
81508
82042
|
break;
|
|
81509
82043
|
}
|
|
81510
82044
|
case "docs": {
|
|
81511
|
-
const docsDir =
|
|
82045
|
+
const docsDir = path86.join(zelari, "docs");
|
|
81512
82046
|
try {
|
|
81513
82047
|
const files = (await fs41.readdir(docsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
81514
82048
|
content = files.length ? `# Docs (${files.length})
|
|
@@ -81550,7 +82084,7 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
81550
82084
|
return;
|
|
81551
82085
|
}
|
|
81552
82086
|
try {
|
|
81553
|
-
const target =
|
|
82087
|
+
const target = path86.join(process.cwd(), ".zelari");
|
|
81554
82088
|
await fs41.rm(target, { recursive: true, force: true });
|
|
81555
82089
|
appendSystem(ctx.setMessages, "[workspace] .zelari/ removed");
|
|
81556
82090
|
} catch (err) {
|
|
@@ -83433,8 +83967,8 @@ function normalizeDraft(raw, sourceUrl, provider, model) {
|
|
|
83433
83967
|
let name = String(o.name ?? "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
83434
83968
|
if (!name || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) {
|
|
83435
83969
|
try {
|
|
83436
|
-
const
|
|
83437
|
-
name =
|
|
83970
|
+
const path100 = new URL(sourceUrl).pathname.split("/").filter(Boolean).pop()?.replace(/\.[a-z0-9]+$/i, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
83971
|
+
name = path100 && /^[a-z0-9]/.test(path100) ? path100 : "imported-skill";
|
|
83438
83972
|
} catch {
|
|
83439
83973
|
name = "imported-skill";
|
|
83440
83974
|
}
|