zelari-code 2.41.0 → 2.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/headless.js.map +1 -1
- package/dist/cli/main.bundled.js +1113 -856
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +14 -3
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/mcp/mcpClient.js +9 -1
- package/dist/cli/mcp/mcpClient.js.map +1 -1
- package/dist/cli/mcp/mcpConfigIo.js +65 -1
- package/dist/cli/mcp/mcpConfigIo.js.map +1 -1
- package/dist/cli/mcp/mcpManager.js +1 -1
- package/dist/cli/mcp/mcpManager.js.map +1 -1
- package/dist/cli/runHeadless.js +20 -3
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/serve/harnessServer.js +42 -2
- package/dist/cli/serve/harnessServer.js.map +1 -1
- package/dist/cli/toolRegistry.js +70 -1
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/tools/createSkillTool.js +156 -0
- package/dist/cli/tools/createSkillTool.js.map +1 -0
- package/dist/cli/tools/taskTool.js +21 -0
- package/dist/cli/tools/taskTool.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -807,7 +807,7 @@ async function openBrowser(url2) {
|
|
|
807
807
|
return { bin: "xdg-open", args: [url2] };
|
|
808
808
|
}
|
|
809
809
|
})();
|
|
810
|
-
return new Promise((
|
|
810
|
+
return new Promise((resolve10, reject) => {
|
|
811
811
|
try {
|
|
812
812
|
const child = spawn19(cmd.bin, cmd.args, {
|
|
813
813
|
stdio: "ignore",
|
|
@@ -816,9 +816,9 @@ async function openBrowser(url2) {
|
|
|
816
816
|
child.on("error", (err) => reject(err));
|
|
817
817
|
child.on("spawn", () => {
|
|
818
818
|
child.unref();
|
|
819
|
-
|
|
819
|
+
resolve10();
|
|
820
820
|
});
|
|
821
|
-
setTimeout(() =>
|
|
821
|
+
setTimeout(() => resolve10(), 100);
|
|
822
822
|
} catch (err) {
|
|
823
823
|
reject(err);
|
|
824
824
|
}
|
|
@@ -867,7 +867,7 @@ async function waitForLoopbackCallback(options) {
|
|
|
867
867
|
const host = options.host ?? "127.0.0.1";
|
|
868
868
|
const timeoutMs2 = options.timeoutMs ?? 3e5;
|
|
869
869
|
const expectedPath = options.path.startsWith("/") ? options.path : `/${options.path}`;
|
|
870
|
-
return new Promise((
|
|
870
|
+
return new Promise((resolve10, reject) => {
|
|
871
871
|
let settled = false;
|
|
872
872
|
const server = createServer((req, res) => {
|
|
873
873
|
const url2 = new URL(req.url ?? "/", `http://${host}`);
|
|
@@ -896,7 +896,7 @@ async function waitForLoopbackCallback(options) {
|
|
|
896
896
|
clearTimeout(timer);
|
|
897
897
|
server.close(() => {
|
|
898
898
|
if (err) reject(err);
|
|
899
|
-
else
|
|
899
|
+
else resolve10(value ?? {});
|
|
900
900
|
});
|
|
901
901
|
};
|
|
902
902
|
server.on("error", (err) => finish2(void 0, err));
|
|
@@ -3482,10 +3482,10 @@ function mergeDefs(...defs) {
|
|
|
3482
3482
|
function cloneDef(schema) {
|
|
3483
3483
|
return mergeDefs(schema._zod.def);
|
|
3484
3484
|
}
|
|
3485
|
-
function getElementAtPath(obj,
|
|
3486
|
-
if (!
|
|
3485
|
+
function getElementAtPath(obj, path104) {
|
|
3486
|
+
if (!path104)
|
|
3487
3487
|
return obj;
|
|
3488
|
-
return
|
|
3488
|
+
return path104.reduce((acc, key) => acc?.[key], obj);
|
|
3489
3489
|
}
|
|
3490
3490
|
function promiseAllObject(promisesObj) {
|
|
3491
3491
|
const keys = Object.keys(promisesObj);
|
|
@@ -3813,11 +3813,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
3813
3813
|
}
|
|
3814
3814
|
return false;
|
|
3815
3815
|
}
|
|
3816
|
-
function prefixIssues(
|
|
3816
|
+
function prefixIssues(path104, issues) {
|
|
3817
3817
|
return issues.map((iss) => {
|
|
3818
3818
|
var _a3;
|
|
3819
3819
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
3820
|
-
iss.path.unshift(
|
|
3820
|
+
iss.path.unshift(path104);
|
|
3821
3821
|
return iss;
|
|
3822
3822
|
});
|
|
3823
3823
|
}
|
|
@@ -4035,16 +4035,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4035
4035
|
}
|
|
4036
4036
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
4037
4037
|
const fieldErrors = { _errors: [] };
|
|
4038
|
-
const processError = (error52,
|
|
4038
|
+
const processError = (error52, path104 = []) => {
|
|
4039
4039
|
for (const issue2 of error52.issues) {
|
|
4040
4040
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
4041
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
4041
|
+
issue2.errors.map((issues) => processError({ issues }, [...path104, ...issue2.path]));
|
|
4042
4042
|
} else if (issue2.code === "invalid_key") {
|
|
4043
|
-
processError({ issues: issue2.issues }, [...
|
|
4043
|
+
processError({ issues: issue2.issues }, [...path104, ...issue2.path]);
|
|
4044
4044
|
} else if (issue2.code === "invalid_element") {
|
|
4045
|
-
processError({ issues: issue2.issues }, [...
|
|
4045
|
+
processError({ issues: issue2.issues }, [...path104, ...issue2.path]);
|
|
4046
4046
|
} else {
|
|
4047
|
-
const fullpath = [...
|
|
4047
|
+
const fullpath = [...path104, ...issue2.path];
|
|
4048
4048
|
if (fullpath.length === 0) {
|
|
4049
4049
|
fieldErrors._errors.push(mapper(issue2));
|
|
4050
4050
|
} else {
|
|
@@ -4071,17 +4071,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4071
4071
|
}
|
|
4072
4072
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
4073
4073
|
const result = { errors: [] };
|
|
4074
|
-
const processError = (error52,
|
|
4074
|
+
const processError = (error52, path104 = []) => {
|
|
4075
4075
|
var _a3, _b;
|
|
4076
4076
|
for (const issue2 of error52.issues) {
|
|
4077
4077
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
4078
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
4078
|
+
issue2.errors.map((issues) => processError({ issues }, [...path104, ...issue2.path]));
|
|
4079
4079
|
} else if (issue2.code === "invalid_key") {
|
|
4080
|
-
processError({ issues: issue2.issues }, [...
|
|
4080
|
+
processError({ issues: issue2.issues }, [...path104, ...issue2.path]);
|
|
4081
4081
|
} else if (issue2.code === "invalid_element") {
|
|
4082
|
-
processError({ issues: issue2.issues }, [...
|
|
4082
|
+
processError({ issues: issue2.issues }, [...path104, ...issue2.path]);
|
|
4083
4083
|
} else {
|
|
4084
|
-
const fullpath = [...
|
|
4084
|
+
const fullpath = [...path104, ...issue2.path];
|
|
4085
4085
|
if (fullpath.length === 0) {
|
|
4086
4086
|
result.errors.push(mapper(issue2));
|
|
4087
4087
|
continue;
|
|
@@ -4113,8 +4113,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4113
4113
|
}
|
|
4114
4114
|
function toDotPath(_path) {
|
|
4115
4115
|
const segs = [];
|
|
4116
|
-
const
|
|
4117
|
-
for (const seg of
|
|
4116
|
+
const path104 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
4117
|
+
for (const seg of path104) {
|
|
4118
4118
|
if (typeof seg === "number")
|
|
4119
4119
|
segs.push(`[${seg}]`);
|
|
4120
4120
|
else if (typeof seg === "symbol")
|
|
@@ -17617,13 +17617,13 @@ function resolveRef(ref, ctx) {
|
|
|
17617
17617
|
if (!ref.startsWith("#")) {
|
|
17618
17618
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
17619
17619
|
}
|
|
17620
|
-
const
|
|
17621
|
-
if (
|
|
17620
|
+
const path104 = ref.slice(1).split("/").filter(Boolean);
|
|
17621
|
+
if (path104.length === 0) {
|
|
17622
17622
|
return ctx.rootSchema;
|
|
17623
17623
|
}
|
|
17624
17624
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
17625
|
-
if (
|
|
17626
|
-
const key =
|
|
17625
|
+
if (path104[0] === defsKey) {
|
|
17626
|
+
const key = path104[1];
|
|
17627
17627
|
if (!key || !ctx.defs[key]) {
|
|
17628
17628
|
throw new Error(`Reference not found: ${ref}`);
|
|
17629
17629
|
}
|
|
@@ -18457,17 +18457,17 @@ var init_newlines = __esm({
|
|
|
18457
18457
|
});
|
|
18458
18458
|
|
|
18459
18459
|
// packages/core/dist/core/tools/builtin/fileEvents.js
|
|
18460
|
-
function fileReadEvent(
|
|
18461
|
-
return { kind: "file.read", actor: { type: "tool" }, data: { path:
|
|
18460
|
+
function fileReadEvent(path104, snapshotId) {
|
|
18461
|
+
return { kind: "file.read", actor: { type: "tool" }, data: { path: path104, snapshotId } };
|
|
18462
18462
|
}
|
|
18463
|
-
function fileAppliedEvent(
|
|
18464
|
-
return { kind: "file.applied", actor: { type: "tool" }, data: { path:
|
|
18463
|
+
function fileAppliedEvent(path104, snapshotId, bytes) {
|
|
18464
|
+
return { kind: "file.applied", actor: { type: "tool" }, data: { path: path104, snapshotId, bytes } };
|
|
18465
18465
|
}
|
|
18466
|
-
function fileRejectedEvent(
|
|
18466
|
+
function fileRejectedEvent(path104, reason, hint) {
|
|
18467
18467
|
return {
|
|
18468
18468
|
kind: "file.rejected",
|
|
18469
18469
|
actor: { type: "tool" },
|
|
18470
|
-
data: hint === void 0 ? { path:
|
|
18470
|
+
data: hint === void 0 ? { path: path104, reason } : { path: path104, reason, hint }
|
|
18471
18471
|
};
|
|
18472
18472
|
}
|
|
18473
18473
|
function reReadHint(reject) {
|
|
@@ -19066,12 +19066,12 @@ function withNodeDirOnPath(base2) {
|
|
|
19066
19066
|
const nodeDir = dirname(process.execPath);
|
|
19067
19067
|
if (!nodeDir)
|
|
19068
19068
|
return env;
|
|
19069
|
-
const
|
|
19069
|
+
const sep5 = process.platform === "win32" ? ";" : ":";
|
|
19070
19070
|
const current = env.PATH ?? env.Path ?? "";
|
|
19071
|
-
const parts = current.split(
|
|
19071
|
+
const parts = current.split(sep5).filter((p3) => p3.length > 0);
|
|
19072
19072
|
const has = parts.some((p3) => p3.toLowerCase() === nodeDir.toLowerCase());
|
|
19073
19073
|
if (!has) {
|
|
19074
|
-
env.PATH = `${nodeDir}${
|
|
19074
|
+
env.PATH = `${nodeDir}${sep5}${current}`;
|
|
19075
19075
|
}
|
|
19076
19076
|
} catch {
|
|
19077
19077
|
}
|
|
@@ -19086,7 +19086,7 @@ function createBashTool(spawnSeam) {
|
|
|
19086
19086
|
timeoutMs: 6e4,
|
|
19087
19087
|
inputSchema: BashArgsSchema,
|
|
19088
19088
|
execute: async (args, ctx) => {
|
|
19089
|
-
return new Promise((
|
|
19089
|
+
return new Promise((resolve10) => {
|
|
19090
19090
|
const start = Date.now();
|
|
19091
19091
|
const cwd = args.cwd ?? ctx.cwd;
|
|
19092
19092
|
const resolved = resolveShell();
|
|
@@ -19113,7 +19113,7 @@ function createBashTool(spawnSeam) {
|
|
|
19113
19113
|
if (spawnSeam) {
|
|
19114
19114
|
const seamResult = spawnSeam({ program, argv, cwd, env, signal: ctx.signal });
|
|
19115
19115
|
if (seamResult.outcome !== "spawned") {
|
|
19116
|
-
|
|
19116
|
+
resolve10(typedErr(seamResult.reason));
|
|
19117
19117
|
return;
|
|
19118
19118
|
}
|
|
19119
19119
|
child = seamResult.child;
|
|
@@ -19140,14 +19140,14 @@ function createBashTool(spawnSeam) {
|
|
|
19140
19140
|
});
|
|
19141
19141
|
const timer = setTimeout(() => {
|
|
19142
19142
|
child.kill("SIGTERM");
|
|
19143
|
-
|
|
19143
|
+
resolve10(typedErr(`Bash command timed out after ${args.timeoutMs}ms. If it was waiting for interactive input: stdin is closed \u2014 pass non-interactive flags or create the files directly instead of retrying.`));
|
|
19144
19144
|
}, args.timeoutMs);
|
|
19145
19145
|
child.on("close", (code) => {
|
|
19146
19146
|
clearTimeout(timer);
|
|
19147
19147
|
const cappedStdout = stdout.slice(0, maxBuffer);
|
|
19148
19148
|
const cappedStderr = stderr.slice(0, maxBuffer);
|
|
19149
19149
|
const interactive = INTERACTIVE_CANCEL_RE.test(cappedStdout) || INTERACTIVE_CANCEL_RE.test(cappedStderr);
|
|
19150
|
-
|
|
19150
|
+
resolve10(typedOk({
|
|
19151
19151
|
stdout: cappedStdout,
|
|
19152
19152
|
stderr: cappedStderr,
|
|
19153
19153
|
exitCode: code ?? -1,
|
|
@@ -19159,7 +19159,7 @@ function createBashTool(spawnSeam) {
|
|
|
19159
19159
|
});
|
|
19160
19160
|
child.on("error", (err) => {
|
|
19161
19161
|
clearTimeout(timer);
|
|
19162
|
-
|
|
19162
|
+
resolve10(typedErr(err.message));
|
|
19163
19163
|
});
|
|
19164
19164
|
});
|
|
19165
19165
|
}
|
|
@@ -20336,11 +20336,11 @@ var init_tools = __esm({
|
|
|
20336
20336
|
if (!ctx.addDocument)
|
|
20337
20337
|
return "Knowledge vault tool not available.";
|
|
20338
20338
|
const title = args["title"] || "New Document";
|
|
20339
|
-
const
|
|
20339
|
+
const path104 = args["path"] || `notes/${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
|
|
20340
20340
|
const content = args["content"] || "";
|
|
20341
20341
|
const tags = args["tags"] || [];
|
|
20342
20342
|
ctx.addDocument({
|
|
20343
|
-
path:
|
|
20343
|
+
path: path104,
|
|
20344
20344
|
title,
|
|
20345
20345
|
content,
|
|
20346
20346
|
format: "markdown",
|
|
@@ -20349,7 +20349,7 @@ var init_tools = __esm({
|
|
|
20349
20349
|
workspaceId: ctx.workspaceId
|
|
20350
20350
|
});
|
|
20351
20351
|
ctx.addActivity("vault", "created document", title);
|
|
20352
|
-
return `Document "${title}" created at "${
|
|
20352
|
+
return `Document "${title}" created at "${path104}".`;
|
|
20353
20353
|
}
|
|
20354
20354
|
}
|
|
20355
20355
|
];
|
|
@@ -22259,7 +22259,7 @@ var init_nodeProviders = __esm({
|
|
|
22259
22259
|
const isWindows = process.platform === "win32";
|
|
22260
22260
|
const file2 = isWindows ? "cmd.exe" : "/bin/sh";
|
|
22261
22261
|
const args = isWindows ? ["/d", "/s", "/c", command] : ["-c", command];
|
|
22262
|
-
return await new Promise((
|
|
22262
|
+
return await new Promise((resolve10) => {
|
|
22263
22263
|
const child = spawn2(file2, args, {
|
|
22264
22264
|
cwd,
|
|
22265
22265
|
shell: false,
|
|
@@ -22292,7 +22292,7 @@ var init_nodeProviders = __esm({
|
|
|
22292
22292
|
});
|
|
22293
22293
|
child.on("error", (err) => {
|
|
22294
22294
|
clearTimeout(timer);
|
|
22295
|
-
|
|
22295
|
+
resolve10({
|
|
22296
22296
|
exitCode: null,
|
|
22297
22297
|
stdout,
|
|
22298
22298
|
stderr: `${stderr}${err.message}`,
|
|
@@ -22302,7 +22302,7 @@ var init_nodeProviders = __esm({
|
|
|
22302
22302
|
});
|
|
22303
22303
|
child.on("close", (code) => {
|
|
22304
22304
|
clearTimeout(timer);
|
|
22305
|
-
|
|
22305
|
+
resolve10({ exitCode: code, stdout, stderr, durationMs: Date.now() - started, timedOut });
|
|
22306
22306
|
});
|
|
22307
22307
|
});
|
|
22308
22308
|
}
|
|
@@ -22380,7 +22380,7 @@ import path16 from "node:path";
|
|
|
22380
22380
|
import crypto2 from "node:crypto";
|
|
22381
22381
|
import { spawn as spawn3 } from "node:child_process";
|
|
22382
22382
|
async function git(cwd, args) {
|
|
22383
|
-
return await new Promise((
|
|
22383
|
+
return await new Promise((resolve10, reject) => {
|
|
22384
22384
|
const child = spawn3("git", args, { cwd, shell: false });
|
|
22385
22385
|
let stdout = "";
|
|
22386
22386
|
let stderr = "";
|
|
@@ -22389,7 +22389,7 @@ async function git(cwd, args) {
|
|
|
22389
22389
|
child.on("error", (err) => reject(err));
|
|
22390
22390
|
child.on("close", (code) => {
|
|
22391
22391
|
if (code === 0)
|
|
22392
|
-
|
|
22392
|
+
resolve10(stdout);
|
|
22393
22393
|
else
|
|
22394
22394
|
reject(new Error(`git ${args.join(" ")} failed (${code}): ${stderr.trim()}`));
|
|
22395
22395
|
});
|
|
@@ -25287,16 +25287,16 @@ function runRetentionFromEnv() {
|
|
|
25287
25287
|
maxTotalBytes: Number.isFinite(parseMb) && parseMb > 0 ? Math.round(parseMb * 1024 * 1024) : DEFAULT_RUN_RETENTION_MAX_MB * 1024 * 1024
|
|
25288
25288
|
};
|
|
25289
25289
|
}
|
|
25290
|
-
async function dirSize(
|
|
25290
|
+
async function dirSize(path104) {
|
|
25291
25291
|
let total = 0;
|
|
25292
25292
|
let entries;
|
|
25293
25293
|
try {
|
|
25294
|
-
entries = await readdir(
|
|
25294
|
+
entries = await readdir(path104, { withFileTypes: true });
|
|
25295
25295
|
} catch {
|
|
25296
25296
|
return 0;
|
|
25297
25297
|
}
|
|
25298
25298
|
for (const entry of entries) {
|
|
25299
|
-
const child = join3(
|
|
25299
|
+
const child = join3(path104, entry.name);
|
|
25300
25300
|
if (entry.isDirectory())
|
|
25301
25301
|
total += await dirSize(child);
|
|
25302
25302
|
else {
|
|
@@ -25323,19 +25323,19 @@ async function enforceRunRetention(runsDir, options = {}) {
|
|
|
25323
25323
|
for (const entry of entries) {
|
|
25324
25324
|
if (!entry.isDirectory())
|
|
25325
25325
|
continue;
|
|
25326
|
-
const
|
|
25326
|
+
const path104 = join3(runsDir, entry.name);
|
|
25327
25327
|
let startedAt = 0;
|
|
25328
25328
|
let endedAt;
|
|
25329
25329
|
let completed = false;
|
|
25330
25330
|
try {
|
|
25331
|
-
const manifest = JSON.parse(await readFile(join3(
|
|
25331
|
+
const manifest = JSON.parse(await readFile(join3(path104, "manifest.json"), "utf8"));
|
|
25332
25332
|
startedAt = manifest.startedAt ?? 0;
|
|
25333
25333
|
endedAt = manifest.endedAt;
|
|
25334
25334
|
completed = Boolean(endedAt) && manifest.status !== "running";
|
|
25335
25335
|
} catch {
|
|
25336
25336
|
completed = false;
|
|
25337
25337
|
}
|
|
25338
|
-
infos.push({ name: entry.name, path:
|
|
25338
|
+
infos.push({ name: entry.name, path: path104, startedAt, endedAt, completed, bytes: await dirSize(path104) });
|
|
25339
25339
|
}
|
|
25340
25340
|
const remove = async (info) => {
|
|
25341
25341
|
await rm(info.path, { recursive: true, force: true });
|
|
@@ -25893,12 +25893,12 @@ var init_engine = __esm({
|
|
|
25893
25893
|
* content digest) and the returned ref carries the event seq when the
|
|
25894
25894
|
* emitter resolved one.
|
|
25895
25895
|
*/
|
|
25896
|
-
async fsEvidence(observation,
|
|
25896
|
+
async fsEvidence(observation, path104, sha2562, content, extra = {}) {
|
|
25897
25897
|
const digest = sha2562 && content !== void 0 ? sha2562(content) : void 0;
|
|
25898
|
-
const seq = await this.emitEvidence({ observation, path:
|
|
25898
|
+
const seq = await this.emitEvidence({ observation, path: path104, ...extra, ...digest ? { digest } : {} });
|
|
25899
25899
|
return {
|
|
25900
25900
|
tier: "fs-observation",
|
|
25901
|
-
ref:
|
|
25901
|
+
ref: path104,
|
|
25902
25902
|
capturedAt: Date.now(),
|
|
25903
25903
|
...digest ? { digest } : {},
|
|
25904
25904
|
...seq !== void 0 ? { seq } : {}
|
|
@@ -30504,8 +30504,8 @@ function wrapLegacyStream(legacyStream, params, _messages, _tools) {
|
|
|
30504
30504
|
}
|
|
30505
30505
|
if (done)
|
|
30506
30506
|
break;
|
|
30507
|
-
await new Promise((
|
|
30508
|
-
resolveNext =
|
|
30507
|
+
await new Promise((resolve10) => {
|
|
30508
|
+
resolveNext = resolve10;
|
|
30509
30509
|
});
|
|
30510
30510
|
}
|
|
30511
30511
|
await promise2;
|
|
@@ -30638,11 +30638,11 @@ var init_sessionJsonl = __esm({
|
|
|
30638
30638
|
*/
|
|
30639
30639
|
scheduleFlush() {
|
|
30640
30640
|
if (this.pending.length > 0 && !this.flushDeferred) {
|
|
30641
|
-
let
|
|
30641
|
+
let resolve10;
|
|
30642
30642
|
const promise2 = new Promise((r) => {
|
|
30643
|
-
|
|
30643
|
+
resolve10 = r;
|
|
30644
30644
|
});
|
|
30645
|
-
this.flushDeferred = { promise: promise2, resolve:
|
|
30645
|
+
this.flushDeferred = { promise: promise2, resolve: resolve10 };
|
|
30646
30646
|
}
|
|
30647
30647
|
if (this.flushTimer === null && this.pending.length > 0) {
|
|
30648
30648
|
this.flushTimer = setTimeout(() => {
|
|
@@ -30949,7 +30949,7 @@ var init_lifecycleHookRunner = __esm({
|
|
|
30949
30949
|
}
|
|
30950
30950
|
/** Spawn `command`, write JSON payload to stdin, read stdout until close. */
|
|
30951
30951
|
execCommand(command, payload, timeoutMs2, cwd) {
|
|
30952
|
-
return new Promise((
|
|
30952
|
+
return new Promise((resolve10, reject) => {
|
|
30953
30953
|
const argv = splitHookCommandLine(command);
|
|
30954
30954
|
if (argv.length === 0) {
|
|
30955
30955
|
reject(new Error("empty hook command"));
|
|
@@ -30983,7 +30983,7 @@ var init_lifecycleHookRunner = __esm({
|
|
|
30983
30983
|
reject(new Error(`exited ${code}: ${stderr.trim().slice(0, 200)}`));
|
|
30984
30984
|
return;
|
|
30985
30985
|
}
|
|
30986
|
-
|
|
30986
|
+
resolve10(stdout);
|
|
30987
30987
|
});
|
|
30988
30988
|
child.stdin?.on("error", () => {
|
|
30989
30989
|
});
|
|
@@ -31032,7 +31032,17 @@ var init_appServerTypes = __esm({
|
|
|
31032
31032
|
|
|
31033
31033
|
// packages/core/dist/harness/appServer.js
|
|
31034
31034
|
import { randomUUID } from "node:crypto";
|
|
31035
|
-
import { resolve } from "node:path";
|
|
31035
|
+
import { isAbsolute, resolve } from "node:path";
|
|
31036
|
+
function resolveSessionWorkspaceRoot(workspaceRoot) {
|
|
31037
|
+
if (typeof workspaceRoot !== "string" || workspaceRoot.trim() === "") {
|
|
31038
|
+
throw new Error("HarnessAppServer: createSession requires a non-empty `workspaceRoot` (it never falls back to process.cwd(): sessions on different workspaces must stay isolated)");
|
|
31039
|
+
}
|
|
31040
|
+
const raw = workspaceRoot.trim();
|
|
31041
|
+
if (!isAbsolute(raw)) {
|
|
31042
|
+
throw new Error(`HarnessAppServer: createSession workspaceRoot must be an absolute path (got '${raw}') \u2014 a relative root would resolve against the server process.cwd() and mix sessions (ADR-0016)`);
|
|
31043
|
+
}
|
|
31044
|
+
return resolve(raw);
|
|
31045
|
+
}
|
|
31036
31046
|
var HarnessAppServer;
|
|
31037
31047
|
var init_appServer = __esm({
|
|
31038
31048
|
"packages/core/dist/harness/appServer.js"() {
|
|
@@ -31053,7 +31063,7 @@ var init_appServer = __esm({
|
|
|
31053
31063
|
this.defaultServicesFactory = options.createWorkspaceServices;
|
|
31054
31064
|
}
|
|
31055
31065
|
createSession(options) {
|
|
31056
|
-
const root =
|
|
31066
|
+
const root = resolveSessionWorkspaceRoot(options.workspaceRoot);
|
|
31057
31067
|
const factory = options.createWorkspaceServices ?? this.defaultServicesFactory;
|
|
31058
31068
|
if (!factory) {
|
|
31059
31069
|
throw new Error("HarnessAppServer: createWorkspaceServices factory is required");
|
|
@@ -31289,6 +31299,7 @@ __export(harness_exports, {
|
|
|
31289
31299
|
recordToolResult: () => recordToolResult,
|
|
31290
31300
|
recordUsage: () => recordUsage,
|
|
31291
31301
|
resolveRequestSnapshotMode: () => resolveRequestSnapshotMode,
|
|
31302
|
+
resolveSessionWorkspaceRoot: () => resolveSessionWorkspaceRoot,
|
|
31292
31303
|
runExtensionPreToolUse: () => runExtensionPreToolUse,
|
|
31293
31304
|
sha256Hex: () => sha256Hex,
|
|
31294
31305
|
splitHookCommandLine: () => splitHookCommandLine,
|
|
@@ -32107,11 +32118,11 @@ var init_synthesisAudit = __esm({
|
|
|
32107
32118
|
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
32108
32119
|
import { join as join5 } from "node:path";
|
|
32109
32120
|
function loadNfrSpec(zelariRoot) {
|
|
32110
|
-
const
|
|
32111
|
-
if (!existsSync10(
|
|
32121
|
+
const path104 = join5(zelariRoot, "nfr-spec.json");
|
|
32122
|
+
if (!existsSync10(path104))
|
|
32112
32123
|
return null;
|
|
32113
32124
|
try {
|
|
32114
|
-
const raw = JSON.parse(readFileSync9(
|
|
32125
|
+
const raw = JSON.parse(readFileSync9(path104, "utf8"));
|
|
32115
32126
|
if (raw.version !== 1 || !Array.isArray(raw.targets))
|
|
32116
32127
|
return null;
|
|
32117
32128
|
return raw;
|
|
@@ -34512,9 +34523,9 @@ var init_types9 = __esm({
|
|
|
34512
34523
|
import { readFileSync as readFileSync14 } from "node:fs";
|
|
34513
34524
|
import { join as join11 } from "node:path";
|
|
34514
34525
|
function readLessonsDeduped(zelariRoot) {
|
|
34515
|
-
const
|
|
34526
|
+
const path104 = join11(zelariRoot, LESSONS_FILE);
|
|
34516
34527
|
try {
|
|
34517
|
-
const raw = readFileSync14(
|
|
34528
|
+
const raw = readFileSync14(path104, "utf8");
|
|
34518
34529
|
const byId = /* @__PURE__ */ new Map();
|
|
34519
34530
|
for (const line of raw.split(/\r?\n/)) {
|
|
34520
34531
|
if (!line.trim())
|
|
@@ -34615,8 +34626,8 @@ function keywordsFrom(check2, signature) {
|
|
|
34615
34626
|
return [.../* @__PURE__ */ new Set([...fromId, ...words])].slice(0, 12);
|
|
34616
34627
|
}
|
|
34617
34628
|
function writeLesson(zelariRoot, lesson) {
|
|
34618
|
-
const
|
|
34619
|
-
appendFileSync(
|
|
34629
|
+
const path104 = join12(zelariRoot, LESSONS_FILE);
|
|
34630
|
+
appendFileSync(path104, `${JSON.stringify(lesson)}
|
|
34620
34631
|
`, "utf8");
|
|
34621
34632
|
}
|
|
34622
34633
|
function findSimilar(lessons, signature) {
|
|
@@ -36584,9 +36595,9 @@ function findCycle(nodes) {
|
|
|
36584
36595
|
if (color.get(start) !== WHITE)
|
|
36585
36596
|
continue;
|
|
36586
36597
|
const stack = [[start, 0]];
|
|
36587
|
-
const
|
|
36598
|
+
const path104 = [];
|
|
36588
36599
|
color.set(start, GRAY);
|
|
36589
|
-
|
|
36600
|
+
path104.push(start);
|
|
36590
36601
|
while (stack.length > 0) {
|
|
36591
36602
|
const top = stack[stack.length - 1];
|
|
36592
36603
|
const [id3, idx] = top;
|
|
@@ -36599,17 +36610,17 @@ function findCycle(nodes) {
|
|
|
36599
36610
|
continue;
|
|
36600
36611
|
const c = color.get(dep);
|
|
36601
36612
|
if (c === GRAY) {
|
|
36602
|
-
const at =
|
|
36603
|
-
return [...
|
|
36613
|
+
const at = path104.indexOf(dep);
|
|
36614
|
+
return [...path104.slice(at), dep];
|
|
36604
36615
|
}
|
|
36605
36616
|
if (c === WHITE) {
|
|
36606
36617
|
color.set(dep, GRAY);
|
|
36607
|
-
|
|
36618
|
+
path104.push(dep);
|
|
36608
36619
|
stack.push([dep, 0]);
|
|
36609
36620
|
}
|
|
36610
36621
|
} else {
|
|
36611
36622
|
color.set(id3, BLACK);
|
|
36612
|
-
|
|
36623
|
+
path104.pop();
|
|
36613
36624
|
stack.pop();
|
|
36614
36625
|
}
|
|
36615
36626
|
}
|
|
@@ -37529,8 +37540,8 @@ var init_runner = __esm({
|
|
|
37529
37540
|
failed: [...this.tentaclesById.values()].filter((r) => r.status === "error"),
|
|
37530
37541
|
pending: []
|
|
37531
37542
|
};
|
|
37532
|
-
const
|
|
37533
|
-
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${
|
|
37543
|
+
const path104 = await this.host.saveSnapshot(snapshot, ".zelari/kraken/snapshots");
|
|
37544
|
+
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${path104}`);
|
|
37534
37545
|
return snapshot;
|
|
37535
37546
|
}
|
|
37536
37547
|
callLog(msg, data) {
|
|
@@ -38826,7 +38837,7 @@ var CORE_VERSION;
|
|
|
38826
38837
|
var init_version = __esm({
|
|
38827
38838
|
"packages/core/dist/version.js"() {
|
|
38828
38839
|
"use strict";
|
|
38829
|
-
CORE_VERSION = "2.
|
|
38840
|
+
CORE_VERSION = "2.42.0";
|
|
38830
38841
|
}
|
|
38831
38842
|
});
|
|
38832
38843
|
|
|
@@ -39309,6 +39320,7 @@ __export(dist_exports, {
|
|
|
39309
39320
|
resolveRequestSnapshotMode: () => resolveRequestSnapshotMode,
|
|
39310
39321
|
resolveResponseLanguage: () => resolveResponseLanguage,
|
|
39311
39322
|
resolveRoleSystemPrompt: () => resolveRoleSystemPrompt,
|
|
39323
|
+
resolveSessionWorkspaceRoot: () => resolveSessionWorkspaceRoot,
|
|
39312
39324
|
resolveSessionsDir: () => resolveSessionsDir,
|
|
39313
39325
|
resolveSkillDependencies: () => resolveSkillDependencies,
|
|
39314
39326
|
resolveVerifyRetryTool: () => resolveVerifyRetryTool,
|
|
@@ -40162,7 +40174,7 @@ ${fallback.output}`
|
|
|
40162
40174
|
return primary;
|
|
40163
40175
|
}
|
|
40164
40176
|
function runNpm(executor, args, mode, npmCliPath) {
|
|
40165
|
-
return new Promise((
|
|
40177
|
+
return new Promise((resolve10) => {
|
|
40166
40178
|
let stdout = "";
|
|
40167
40179
|
let stderr = "";
|
|
40168
40180
|
const stdio = ["ignore", "pipe", "pipe"];
|
|
@@ -40174,7 +40186,7 @@ function runNpm(executor, args, mode, npmCliPath) {
|
|
|
40174
40186
|
stderr += chunk.toString();
|
|
40175
40187
|
});
|
|
40176
40188
|
child.on("error", (err) => {
|
|
40177
|
-
|
|
40189
|
+
resolve10({
|
|
40178
40190
|
ok: false,
|
|
40179
40191
|
output: stdout + stderr,
|
|
40180
40192
|
error: err.message,
|
|
@@ -40183,7 +40195,7 @@ function runNpm(executor, args, mode, npmCliPath) {
|
|
|
40183
40195
|
});
|
|
40184
40196
|
child.on("close", (code) => {
|
|
40185
40197
|
const ok = code === 0;
|
|
40186
|
-
|
|
40198
|
+
resolve10({
|
|
40187
40199
|
ok,
|
|
40188
40200
|
output: stdout + stderr,
|
|
40189
40201
|
error: ok ? void 0 : `npm exited with code ${code}`,
|
|
@@ -41308,9 +41320,9 @@ function spillToolOutput(fullText, meta3) {
|
|
|
41308
41320
|
const rnd = randomBytes3(3).toString("hex");
|
|
41309
41321
|
const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
|
|
41310
41322
|
const file2 = `${stamp}-${safeTool}-${hash3}-${rnd}.txt`;
|
|
41311
|
-
const
|
|
41312
|
-
writeFileSync12(
|
|
41313
|
-
return
|
|
41323
|
+
const path104 = join14(dir, file2);
|
|
41324
|
+
writeFileSync12(path104, fullText, "utf8");
|
|
41325
|
+
return path104;
|
|
41314
41326
|
} catch {
|
|
41315
41327
|
return null;
|
|
41316
41328
|
}
|
|
@@ -41356,10 +41368,10 @@ function truncateToolResult(text, capOrOpts = TOOL_RESULT_LINE_CAP) {
|
|
|
41356
41368
|
${tail2}`;
|
|
41357
41369
|
}
|
|
41358
41370
|
if (doSpill) {
|
|
41359
|
-
const
|
|
41360
|
-
if (
|
|
41371
|
+
const path104 = spillToolOutput(text, { toolName: opts.toolName });
|
|
41372
|
+
if (path104) {
|
|
41361
41373
|
const spillNote = `
|
|
41362
|
-
\u2026 [full output spilled to: ${
|
|
41374
|
+
\u2026 [full output spilled to: ${path104} \u2014 re-read with read_file if you need the complete text] \u2026`;
|
|
41363
41375
|
if (preview.includes("] \u2026\n")) {
|
|
41364
41376
|
preview = preview.replace("] \u2026\n", `] \u2026${spillNote}
|
|
41365
41377
|
`);
|
|
@@ -42162,28 +42174,28 @@ var init_storage = __esm({
|
|
|
42162
42174
|
VALID_SCALARS = /^(true|false|null|~)$/i;
|
|
42163
42175
|
Storage = class {
|
|
42164
42176
|
/** Read a Markdown file with frontmatter. Throws if not found. */
|
|
42165
|
-
read(
|
|
42166
|
-
if (!existsSync19(
|
|
42167
|
-
throw new Error(`File not found: ${
|
|
42177
|
+
read(path104) {
|
|
42178
|
+
if (!existsSync19(path104)) {
|
|
42179
|
+
throw new Error(`File not found: ${path104}`);
|
|
42168
42180
|
}
|
|
42169
|
-
const md = readFileSync17(
|
|
42181
|
+
const md = readFileSync17(path104, "utf8");
|
|
42170
42182
|
return parseFrontmatter(md);
|
|
42171
42183
|
}
|
|
42172
42184
|
/** Read a Markdown file; returns null if not found. */
|
|
42173
|
-
readIfExists(
|
|
42174
|
-
if (!existsSync19(
|
|
42175
|
-
return this.read(
|
|
42185
|
+
readIfExists(path104) {
|
|
42186
|
+
if (!existsSync19(path104)) return null;
|
|
42187
|
+
return this.read(path104);
|
|
42176
42188
|
}
|
|
42177
42189
|
/**
|
|
42178
42190
|
* Write a Markdown file atomically (tmp + rename). Creates parent dirs.
|
|
42179
42191
|
* The meta object is serialized as YAML frontmatter; body as Markdown.
|
|
42180
42192
|
*/
|
|
42181
|
-
write(
|
|
42182
|
-
mkdirSync10(dirname2(
|
|
42183
|
-
const tmp =
|
|
42193
|
+
write(path104, meta3, body) {
|
|
42194
|
+
mkdirSync10(dirname2(path104), { recursive: true });
|
|
42195
|
+
const tmp = path104 + ".tmp-" + process.pid;
|
|
42184
42196
|
const md = serializeFrontmatter(meta3, body);
|
|
42185
42197
|
writeFileSync14(tmp, md, "utf8");
|
|
42186
|
-
renameSync2(tmp,
|
|
42198
|
+
renameSync2(tmp, path104);
|
|
42187
42199
|
}
|
|
42188
42200
|
/** List all .md files in a directory (non-recursive). */
|
|
42189
42201
|
listMarkdown(dir) {
|
|
@@ -42197,8 +42209,8 @@ var init_storage = __esm({
|
|
|
42197
42209
|
const prev2 = this.chains.get(key) ?? Promise.resolve();
|
|
42198
42210
|
let release = () => {
|
|
42199
42211
|
};
|
|
42200
|
-
const next = new Promise((
|
|
42201
|
-
release =
|
|
42212
|
+
const next = new Promise((resolve10) => {
|
|
42213
|
+
release = resolve10;
|
|
42202
42214
|
});
|
|
42203
42215
|
const chained = prev2.then(() => next);
|
|
42204
42216
|
this.chains.set(key, chained);
|
|
@@ -42294,8 +42306,8 @@ function nextPlanTaskId(store6) {
|
|
|
42294
42306
|
return `t${store6.counter}`;
|
|
42295
42307
|
}
|
|
42296
42308
|
function writePlanTaskArtifact(rootDir, task) {
|
|
42297
|
-
const
|
|
42298
|
-
mkdirSync11(dirname3(
|
|
42309
|
+
const path104 = join17(rootDir, "plan-tasks", `${task.id}.md`);
|
|
42310
|
+
mkdirSync11(dirname3(path104), { recursive: true });
|
|
42299
42311
|
const meta3 = {
|
|
42300
42312
|
kind: "task",
|
|
42301
42313
|
id: task.id,
|
|
@@ -42316,7 +42328,7 @@ function writePlanTaskArtifact(rootDir, task) {
|
|
|
42316
42328
|
task.notes?.trim() ? task.notes.trim() : "_(no notes)_",
|
|
42317
42329
|
""
|
|
42318
42330
|
].filter((l) => l !== null).join("\n");
|
|
42319
|
-
new Storage().write(
|
|
42331
|
+
new Storage().write(path104, meta3, body);
|
|
42320
42332
|
}
|
|
42321
42333
|
function loadHandle(rootDir) {
|
|
42322
42334
|
const jsonPath = join17(rootDir, "plan.json");
|
|
@@ -42994,14 +43006,14 @@ var init_engine2 = __esm({
|
|
|
42994
43006
|
parse: parseRuffJson
|
|
42995
43007
|
}
|
|
42996
43008
|
];
|
|
42997
|
-
defaultRunner = (cmd, args, opts) => new Promise((
|
|
43009
|
+
defaultRunner = (cmd, args, opts) => new Promise((resolve10) => {
|
|
42998
43010
|
let stdout = "";
|
|
42999
43011
|
let stderr = "";
|
|
43000
43012
|
let settled = false;
|
|
43001
43013
|
const done = (r) => {
|
|
43002
43014
|
if (settled) return;
|
|
43003
43015
|
settled = true;
|
|
43004
|
-
|
|
43016
|
+
resolve10(r);
|
|
43005
43017
|
};
|
|
43006
43018
|
let child;
|
|
43007
43019
|
try {
|
|
@@ -44056,7 +44068,7 @@ async function readChecks(cwd) {
|
|
|
44056
44068
|
}
|
|
44057
44069
|
}
|
|
44058
44070
|
function runShell(command, cwd, timeoutMs2, signal) {
|
|
44059
|
-
return new Promise((
|
|
44071
|
+
return new Promise((resolve10) => {
|
|
44060
44072
|
const isWin = process.platform === "win32";
|
|
44061
44073
|
const child = spawn8(isWin ? "cmd.exe" : "/bin/sh", isWin ? ["/c", command] : ["-c", command], {
|
|
44062
44074
|
cwd,
|
|
@@ -44070,7 +44082,7 @@ function runShell(command, cwd, timeoutMs2, signal) {
|
|
|
44070
44082
|
const finish2 = (exitCode) => {
|
|
44071
44083
|
if (settled) return;
|
|
44072
44084
|
settled = true;
|
|
44073
|
-
|
|
44085
|
+
resolve10({ exitCode, stdout, stderr });
|
|
44074
44086
|
};
|
|
44075
44087
|
const timer = setTimeout(() => {
|
|
44076
44088
|
try {
|
|
@@ -46781,8 +46793,8 @@ ${upstream}` : node.prompt,
|
|
|
46781
46793
|
if (ms <= 0) return promise2;
|
|
46782
46794
|
let timer;
|
|
46783
46795
|
const TIMED_OUT = Symbol("timeout");
|
|
46784
|
-
const timeout = new Promise((
|
|
46785
|
-
timer = setTimeout(() =>
|
|
46796
|
+
const timeout = new Promise((resolve10) => {
|
|
46797
|
+
timer = setTimeout(() => resolve10(TIMED_OUT), ms);
|
|
46786
46798
|
});
|
|
46787
46799
|
const raced = await Promise.race([promise2, timeout]).finally(() => {
|
|
46788
46800
|
if (timer) clearTimeout(timer);
|
|
@@ -46791,8 +46803,8 @@ ${upstream}` : node.prompt,
|
|
|
46791
46803
|
controller?.abort();
|
|
46792
46804
|
const graceMs = this.cancelGraceMs ?? resolveCancelGraceMs();
|
|
46793
46805
|
let graceTimer;
|
|
46794
|
-
const grace = new Promise((
|
|
46795
|
-
graceTimer = setTimeout(() =>
|
|
46806
|
+
const grace = new Promise((resolve10) => {
|
|
46807
|
+
graceTimer = setTimeout(() => resolve10(TIMED_OUT), graceMs);
|
|
46796
46808
|
});
|
|
46797
46809
|
const settled = await Promise.race([promise2, grace]).finally(() => {
|
|
46798
46810
|
if (graceTimer) clearTimeout(graceTimer);
|
|
@@ -47861,7 +47873,10 @@ async function runTentacle(opts) {
|
|
|
47861
47873
|
sub = await deps.createSubAgentContext({
|
|
47862
47874
|
agent,
|
|
47863
47875
|
thoroughness,
|
|
47864
|
-
cwd: effectiveCwd
|
|
47876
|
+
cwd: effectiveCwd,
|
|
47877
|
+
// Per-spawn thinking effort (ADR-0017): the factory applies arg > per-kind
|
|
47878
|
+
// env > inherited provider default and reports the winner back on `sub`.
|
|
47879
|
+
...args.thinkingEffort ? { thinkingEffort: args.thinkingEffort } : {}
|
|
47865
47880
|
});
|
|
47866
47881
|
} catch (err) {
|
|
47867
47882
|
if (worktree) await cleanupKrakenWorktree(worktree);
|
|
@@ -47897,6 +47912,8 @@ async function runTentacle(opts) {
|
|
|
47897
47912
|
error: "task: no provider configured for the sub-agent (set an API key / run /login)."
|
|
47898
47913
|
};
|
|
47899
47914
|
}
|
|
47915
|
+
const requestedThinking = args.thinkingEffort && args.thinkingEffort.toLowerCase() !== "inherit" ? args.thinkingEffort : void 0;
|
|
47916
|
+
const spawnThinking = sub.thinking ?? requestedThinking;
|
|
47900
47917
|
emitActivity({
|
|
47901
47918
|
type: "agent_spawned",
|
|
47902
47919
|
agentId: liveId,
|
|
@@ -47904,6 +47921,7 @@ async function runTentacle(opts) {
|
|
|
47904
47921
|
title: args.description,
|
|
47905
47922
|
...sub.model ? { model: sub.model } : {},
|
|
47906
47923
|
...sub.provider ? { provider: sub.provider } : {},
|
|
47924
|
+
...spawnThinking ? { thinking: spawnThinking } : {},
|
|
47907
47925
|
...args.scope && args.scope.length > 0 ? { scope: args.scope } : {},
|
|
47908
47926
|
...worktree ? { worktree: worktree.path } : {},
|
|
47909
47927
|
ts: Date.now()
|
|
@@ -48238,7 +48256,8 @@ RESTRICTED in this mode: only agent=${allowedAgents.join("|")} is allowed.` : ""
|
|
|
48238
48256
|
description: args.description,
|
|
48239
48257
|
prompt: args.prompt,
|
|
48240
48258
|
scope: args.scope,
|
|
48241
|
-
acceptance: args.acceptance
|
|
48259
|
+
acceptance: args.acceptance,
|
|
48260
|
+
...args.thinkingEffort ? { thinkingEffort: args.thinkingEffort } : {}
|
|
48242
48261
|
},
|
|
48243
48262
|
agent,
|
|
48244
48263
|
thoroughness,
|
|
@@ -48394,6 +48413,9 @@ var init_taskTool = __esm({
|
|
|
48394
48413
|
),
|
|
48395
48414
|
acceptance: external_exports.array(external_exports.string().min(1)).max(16).optional().describe(
|
|
48396
48415
|
"Optional acceptance checklist (contract). Appended to the prompt as Acceptance criteria."
|
|
48416
|
+
),
|
|
48417
|
+
thinkingEffort: external_exports.enum(["inherit", "auto", "off", "low", "medium", "high", "xhigh", "max"]).optional().describe(
|
|
48418
|
+
"Thinking effort for THIS tentacle only (ADR-0017), overriding the provider default used by the lead. 'inherit' (and omitting the field) defers to the per-kind default: ZELARI_KRAKEN_<EXPLORE|GENERAL|VERIFY>_THINKING, else the provider thinkingByProvider value. Token budgets are not accepted here \u2014 set ZELARI_KRAKEN_<KIND>_THINKING='budget:<n>' instead. Invalid values are ignored."
|
|
48397
48419
|
)
|
|
48398
48420
|
});
|
|
48399
48421
|
TaskPurposeSchema = external_exports.enum(["candidate"]).optional().describe(
|
|
@@ -49910,6 +49932,383 @@ var init_skillTool = __esm({
|
|
|
49910
49932
|
}
|
|
49911
49933
|
});
|
|
49912
49934
|
|
|
49935
|
+
// src/cli/skillCategories.ts
|
|
49936
|
+
var CODING_CATEGORIES_LIST, CODING_CATEGORIES2;
|
|
49937
|
+
var init_skillCategories = __esm({
|
|
49938
|
+
"src/cli/skillCategories.ts"() {
|
|
49939
|
+
"use strict";
|
|
49940
|
+
CODING_CATEGORIES_LIST = [
|
|
49941
|
+
"plan",
|
|
49942
|
+
"refactor",
|
|
49943
|
+
"debug",
|
|
49944
|
+
"review",
|
|
49945
|
+
"test",
|
|
49946
|
+
"docs",
|
|
49947
|
+
"ops",
|
|
49948
|
+
"git",
|
|
49949
|
+
"db",
|
|
49950
|
+
"maint"
|
|
49951
|
+
];
|
|
49952
|
+
CODING_CATEGORIES2 = new Set(CODING_CATEGORIES_LIST);
|
|
49953
|
+
}
|
|
49954
|
+
});
|
|
49955
|
+
|
|
49956
|
+
// src/cli/skillConfigIo.ts
|
|
49957
|
+
import {
|
|
49958
|
+
existsSync as existsSync28,
|
|
49959
|
+
mkdirSync as mkdirSync13,
|
|
49960
|
+
readdirSync as readdirSync6,
|
|
49961
|
+
readFileSync as readFileSync20,
|
|
49962
|
+
rmSync as rmSync3,
|
|
49963
|
+
writeFileSync as writeFileSync16
|
|
49964
|
+
} from "node:fs";
|
|
49965
|
+
import { dirname as dirname4, join as join20 } from "node:path";
|
|
49966
|
+
function ensureBuiltinSkillsLoadedSync() {
|
|
49967
|
+
if (builtinsLoaded) return;
|
|
49968
|
+
for (const spec of BUILTIN_SKILL_MODULES) {
|
|
49969
|
+
try {
|
|
49970
|
+
require?.(spec);
|
|
49971
|
+
} catch {
|
|
49972
|
+
}
|
|
49973
|
+
}
|
|
49974
|
+
}
|
|
49975
|
+
function getUserSkillsDir() {
|
|
49976
|
+
return join20(zelariHome(), "skills");
|
|
49977
|
+
}
|
|
49978
|
+
function getProjectSkillsDir(projectRoot) {
|
|
49979
|
+
return join20(projectRoot, ".zelari", "skills");
|
|
49980
|
+
}
|
|
49981
|
+
function skillFilePath(dir, name) {
|
|
49982
|
+
return join20(dir, name, "SKILL.md");
|
|
49983
|
+
}
|
|
49984
|
+
function classifyScope(skillPath, projectRoot) {
|
|
49985
|
+
const userDir = getUserSkillsDir().replace(/\\/g, "/");
|
|
49986
|
+
const norm = skillPath.replace(/\\/g, "/");
|
|
49987
|
+
if (norm.startsWith(userDir + "/") || norm === userDir) {
|
|
49988
|
+
return { scope: "user", writable: true };
|
|
49989
|
+
}
|
|
49990
|
+
if (projectRoot) {
|
|
49991
|
+
const projDir = getProjectSkillsDir(projectRoot).replace(/\\/g, "/");
|
|
49992
|
+
if (norm.startsWith(projDir + "/") || norm === projDir) {
|
|
49993
|
+
return { scope: "project", writable: true };
|
|
49994
|
+
}
|
|
49995
|
+
}
|
|
49996
|
+
return { scope: "compat", writable: false };
|
|
49997
|
+
}
|
|
49998
|
+
function entryFromParsed(parsed, projectRoot) {
|
|
49999
|
+
const { scope, writable } = classifyScope(parsed.sourcePath, projectRoot);
|
|
50000
|
+
return {
|
|
50001
|
+
id: parsed.name,
|
|
50002
|
+
name: parsed.name,
|
|
50003
|
+
description: parsed.description,
|
|
50004
|
+
category: parsed.category,
|
|
50005
|
+
estimatedCost: parsed.estimatedCost,
|
|
50006
|
+
requiredTools: parsed.requiredTools,
|
|
50007
|
+
scope,
|
|
50008
|
+
path: parsed.sourcePath,
|
|
50009
|
+
body: parsed.body,
|
|
50010
|
+
builtin: false,
|
|
50011
|
+
writable
|
|
50012
|
+
};
|
|
50013
|
+
}
|
|
50014
|
+
function entryFromBuiltin(skill) {
|
|
50015
|
+
return {
|
|
50016
|
+
id: skill.id,
|
|
50017
|
+
name: skill.name || skill.id,
|
|
50018
|
+
description: skill.description || "",
|
|
50019
|
+
category: skill.category,
|
|
50020
|
+
estimatedCost: skill.estimatedCost,
|
|
50021
|
+
requiredTools: skill.requiredTools,
|
|
50022
|
+
scope: "builtin",
|
|
50023
|
+
path: null,
|
|
50024
|
+
// Expose body so Desktop skill picker can expand like `/skill <id>`.
|
|
50025
|
+
body: skill.systemPromptFragment || void 0,
|
|
50026
|
+
builtin: true,
|
|
50027
|
+
writable: false
|
|
50028
|
+
};
|
|
50029
|
+
}
|
|
50030
|
+
function scanSkillsDir(dir, projectRoot, seen, out) {
|
|
50031
|
+
if (!existsSync28(dir)) return;
|
|
50032
|
+
let entries;
|
|
50033
|
+
try {
|
|
50034
|
+
entries = readdirSync6(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
50035
|
+
} catch {
|
|
50036
|
+
return;
|
|
50037
|
+
}
|
|
50038
|
+
for (const entry of entries) {
|
|
50039
|
+
const skillPath = skillFilePath(dir, entry);
|
|
50040
|
+
if (!existsSync28(skillPath)) continue;
|
|
50041
|
+
try {
|
|
50042
|
+
const parsed = parseSkillMd(readFileSync20(skillPath, "utf8"), skillPath);
|
|
50043
|
+
if (!parsed) continue;
|
|
50044
|
+
if (seen.has(parsed.name)) continue;
|
|
50045
|
+
seen.add(parsed.name);
|
|
50046
|
+
out.push(entryFromParsed(parsed, projectRoot));
|
|
50047
|
+
} catch {
|
|
50048
|
+
}
|
|
50049
|
+
}
|
|
50050
|
+
}
|
|
50051
|
+
function listSkillsSnapshot(projectRoot) {
|
|
50052
|
+
const root = projectRoot && projectRoot.trim() ? projectRoot.trim() : null;
|
|
50053
|
+
const userSkillsDir = getUserSkillsDir();
|
|
50054
|
+
const projectSkillsDir = root ? getProjectSkillsDir(root) : null;
|
|
50055
|
+
const skills = [];
|
|
50056
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50057
|
+
if (root) {
|
|
50058
|
+
scanSkillsDir(join20(root, ".zelari", "skills"), root, seen, skills);
|
|
50059
|
+
scanSkillsDir(join20(root, ".claude", "skills"), root, seen, skills);
|
|
50060
|
+
scanSkillsDir(join20(root, ".opencode", "skills"), root, seen, skills);
|
|
50061
|
+
}
|
|
50062
|
+
scanSkillsDir(userSkillsDir, root, seen, skills);
|
|
50063
|
+
for (const s of listCodingSkills()) {
|
|
50064
|
+
if (seen.has(s.id)) continue;
|
|
50065
|
+
seen.add(s.id);
|
|
50066
|
+
if (s.builtin) {
|
|
50067
|
+
skills.push(entryFromBuiltin(s));
|
|
50068
|
+
}
|
|
50069
|
+
}
|
|
50070
|
+
skills.sort((a, b) => {
|
|
50071
|
+
const order = (s) => s === "project" ? 0 : s === "user" ? 1 : s === "compat" ? 2 : 3;
|
|
50072
|
+
const d = order(a.scope) - order(b.scope);
|
|
50073
|
+
if (d !== 0) return d;
|
|
50074
|
+
return a.id.localeCompare(b.id);
|
|
50075
|
+
});
|
|
50076
|
+
return { userSkillsDir, projectSkillsDir, skills };
|
|
50077
|
+
}
|
|
50078
|
+
function serializeSkillMd(opts) {
|
|
50079
|
+
const name = opts.name.trim().toLowerCase();
|
|
50080
|
+
const description = opts.description.trim();
|
|
50081
|
+
const body = opts.body.trim();
|
|
50082
|
+
const lines = ["---", `name: ${name}`, `description: ${description}`];
|
|
50083
|
+
const cat = (opts.category ?? "").trim().toLowerCase();
|
|
50084
|
+
if (cat && CODING_CATEGORIES2.has(cat)) {
|
|
50085
|
+
lines.push(`category: ${cat}`);
|
|
50086
|
+
}
|
|
50087
|
+
if (opts.tools && opts.tools.length > 0) {
|
|
50088
|
+
lines.push(`tools: [${opts.tools.map((t) => t.trim()).filter(Boolean).join(", ")}]`);
|
|
50089
|
+
}
|
|
50090
|
+
const cost = (opts.cost ?? "").trim().toLowerCase();
|
|
50091
|
+
if (cost === "low" || cost === "medium" || cost === "high") {
|
|
50092
|
+
lines.push(`cost: ${cost}`);
|
|
50093
|
+
}
|
|
50094
|
+
lines.push("---", "", body, "");
|
|
50095
|
+
return lines.join("\n");
|
|
50096
|
+
}
|
|
50097
|
+
function upsertSkill(opts) {
|
|
50098
|
+
const name = opts.name.trim().toLowerCase();
|
|
50099
|
+
if (!name || !NAME_RE.test(name)) {
|
|
50100
|
+
return {
|
|
50101
|
+
ok: false,
|
|
50102
|
+
error: "Invalid skill name (use lowercase letters, digits, hyphens; max 64 chars)"
|
|
50103
|
+
};
|
|
50104
|
+
}
|
|
50105
|
+
const description = opts.description.trim();
|
|
50106
|
+
if (!description) {
|
|
50107
|
+
return { ok: false, error: "description is required" };
|
|
50108
|
+
}
|
|
50109
|
+
const body = opts.body.trim();
|
|
50110
|
+
if (!body) {
|
|
50111
|
+
return { ok: false, error: "body is required" };
|
|
50112
|
+
}
|
|
50113
|
+
let dir;
|
|
50114
|
+
if (opts.scope === "user") {
|
|
50115
|
+
dir = getUserSkillsDir();
|
|
50116
|
+
} else {
|
|
50117
|
+
const root = opts.projectRoot?.trim();
|
|
50118
|
+
if (!root) {
|
|
50119
|
+
return {
|
|
50120
|
+
ok: false,
|
|
50121
|
+
error: "projectRoot required for project scope (Open Folder first)"
|
|
50122
|
+
};
|
|
50123
|
+
}
|
|
50124
|
+
dir = getProjectSkillsDir(root);
|
|
50125
|
+
}
|
|
50126
|
+
const path104 = skillFilePath(dir, name);
|
|
50127
|
+
const content = serializeSkillMd({
|
|
50128
|
+
name,
|
|
50129
|
+
description,
|
|
50130
|
+
body,
|
|
50131
|
+
category: opts.category,
|
|
50132
|
+
tools: opts.tools,
|
|
50133
|
+
cost: opts.cost
|
|
50134
|
+
});
|
|
50135
|
+
const parsed = parseSkillMd(content, path104);
|
|
50136
|
+
if (!parsed) {
|
|
50137
|
+
return { ok: false, error: "Generated SKILL.md failed validation" };
|
|
50138
|
+
}
|
|
50139
|
+
mkdirSync13(dirname4(path104), { recursive: true });
|
|
50140
|
+
writeFileSync16(path104, content, "utf8");
|
|
50141
|
+
return { ok: true, path: path104 };
|
|
50142
|
+
}
|
|
50143
|
+
function removeSkill(opts) {
|
|
50144
|
+
const name = opts.name.trim().toLowerCase();
|
|
50145
|
+
if (!name) {
|
|
50146
|
+
return { ok: false, error: "name is required" };
|
|
50147
|
+
}
|
|
50148
|
+
let dir;
|
|
50149
|
+
if (opts.scope === "user") {
|
|
50150
|
+
dir = getUserSkillsDir();
|
|
50151
|
+
} else {
|
|
50152
|
+
const root = opts.projectRoot?.trim();
|
|
50153
|
+
if (!root) {
|
|
50154
|
+
return { ok: false, error: "projectRoot required for project scope" };
|
|
50155
|
+
}
|
|
50156
|
+
dir = getProjectSkillsDir(root);
|
|
50157
|
+
}
|
|
50158
|
+
const skillDir = join20(dir, name);
|
|
50159
|
+
const path104 = skillFilePath(dir, name);
|
|
50160
|
+
if (!existsSync28(path104) && !existsSync28(skillDir)) {
|
|
50161
|
+
return { ok: false, error: `Skill "${name}" not found in ${dir}` };
|
|
50162
|
+
}
|
|
50163
|
+
try {
|
|
50164
|
+
rmSync3(skillDir, { recursive: true, force: true });
|
|
50165
|
+
} catch (err) {
|
|
50166
|
+
return {
|
|
50167
|
+
ok: false,
|
|
50168
|
+
error: err instanceof Error ? err.message : String(err)
|
|
50169
|
+
};
|
|
50170
|
+
}
|
|
50171
|
+
return { ok: true, path: path104 };
|
|
50172
|
+
}
|
|
50173
|
+
var NAME_RE, BUILTIN_SKILL_MODULES, builtinsLoaded;
|
|
50174
|
+
var init_skillConfigIo = __esm({
|
|
50175
|
+
"src/cli/skillConfigIo.ts"() {
|
|
50176
|
+
"use strict";
|
|
50177
|
+
init_skills2();
|
|
50178
|
+
init_skillsMd();
|
|
50179
|
+
init_skillCategories();
|
|
50180
|
+
init_paths();
|
|
50181
|
+
NAME_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
50182
|
+
BUILTIN_SKILL_MODULES = [
|
|
50183
|
+
"@zelari/core/skills/builtin/debugging",
|
|
50184
|
+
"@zelari/core/skills/builtin/docs",
|
|
50185
|
+
"@zelari/core/skills/builtin/git-ops",
|
|
50186
|
+
"@zelari/core/skills/builtin/planning",
|
|
50187
|
+
"@zelari/core/skills/builtin/refactoring",
|
|
50188
|
+
"@zelari/core/skills/builtin/review",
|
|
50189
|
+
"@zelari/core/skills/builtin/unrealEditor",
|
|
50190
|
+
"@zelari/core/skills/builtin/testing",
|
|
50191
|
+
"@zelari/core/skills/builtin/schema-loop",
|
|
50192
|
+
"@zelari/core/skills/builtin/computer-use-cua",
|
|
50193
|
+
"@zelari/core/skills/builtin/qwen-mm-plugins"
|
|
50194
|
+
];
|
|
50195
|
+
builtinsLoaded = false;
|
|
50196
|
+
}
|
|
50197
|
+
});
|
|
50198
|
+
|
|
50199
|
+
// src/cli/tools/createSkillTool.ts
|
|
50200
|
+
import { existsSync as existsSync29 } from "node:fs";
|
|
50201
|
+
import { resolve as resolve3, sep } from "node:path";
|
|
50202
|
+
function createCreateSkillTool(opts) {
|
|
50203
|
+
const root = opts?.cwd ?? process.cwd();
|
|
50204
|
+
return {
|
|
50205
|
+
name: "create_skill",
|
|
50206
|
+
description: 'Create a NEW reusable skill (a SKILL.md procedure) that you can invoke in later turns with the `skill` tool or `/skill <name>`. Use it when the user asks to save a procedure as a skill ("salva questa procedura come skill", "crea una skill per X", "make this reusable"), or when you just worked out a repeatable workflow worth persisting. Write `instructions` as a COMPLETE, self-contained markdown procedure (goal, ordered steps, exact commands, verification, pitfalls): it becomes the skill body verbatim. scope=project (default) saves to <cwd>/.zelari/skills and is shared with the repo; scope=user saves to ~/.zelari-code/skills for every project. Creating an existing name fails unless overwrite=true. Does not edit built-in skills.',
|
|
50207
|
+
permissions: ["write"],
|
|
50208
|
+
timeoutMs: 1e4,
|
|
50209
|
+
inputSchema: CreateSkillArgsSchema,
|
|
50210
|
+
execute: async (args) => {
|
|
50211
|
+
const name = typeof args?.name === "string" ? args.name.trim() : "";
|
|
50212
|
+
if (!NAME_RE2.test(name)) {
|
|
50213
|
+
return typedErr(
|
|
50214
|
+
`Invalid skill name ${JSON.stringify(name)}. Use a slug of 2-40 chars: lowercase letters, digits and hyphens, starting with a letter or digit (e.g. "release-checklist").`
|
|
50215
|
+
);
|
|
50216
|
+
}
|
|
50217
|
+
const description = (args?.description ?? "").replace(/\s+/g, " ").trim();
|
|
50218
|
+
if (!description) {
|
|
50219
|
+
return typedErr("description is required: one line explaining when to use this skill.");
|
|
50220
|
+
}
|
|
50221
|
+
const instructions = (args?.instructions ?? "").trim();
|
|
50222
|
+
if (!instructions) {
|
|
50223
|
+
return typedErr(
|
|
50224
|
+
"instructions is required: the markdown body of the skill (goal, steps, commands, pitfalls)."
|
|
50225
|
+
);
|
|
50226
|
+
}
|
|
50227
|
+
const scope = args?.scope === "user" ? "user" : "project";
|
|
50228
|
+
const overwrite = args?.overwrite === true;
|
|
50229
|
+
const dir = scope === "user" ? getUserSkillsDir() : getProjectSkillsDir(root);
|
|
50230
|
+
const skillDir = resolve3(dir, name);
|
|
50231
|
+
const path104 = resolve3(skillDir, "SKILL.md");
|
|
50232
|
+
if (!path104.startsWith(resolve3(dir) + sep)) {
|
|
50233
|
+
return typedErr(
|
|
50234
|
+
`Refused: "${name}" would resolve outside the ${scope} skills directory (${resolve3(dir)}).`
|
|
50235
|
+
);
|
|
50236
|
+
}
|
|
50237
|
+
const existed = existsSync29(path104);
|
|
50238
|
+
if (existed && !overwrite) {
|
|
50239
|
+
return typedErr(
|
|
50240
|
+
`Skill "${name}" already exists at ${path104} \u2014 nothing was written. Call create_skill again with overwrite: true to replace it, or pick another name.`
|
|
50241
|
+
);
|
|
50242
|
+
}
|
|
50243
|
+
const written = upsertSkill({
|
|
50244
|
+
scope,
|
|
50245
|
+
name,
|
|
50246
|
+
description,
|
|
50247
|
+
body: instructions,
|
|
50248
|
+
projectRoot: root
|
|
50249
|
+
});
|
|
50250
|
+
if (!written.ok) {
|
|
50251
|
+
return typedErr(`Could not write SKILL.md for "${name}": ${written.error}`);
|
|
50252
|
+
}
|
|
50253
|
+
let loadable = false;
|
|
50254
|
+
try {
|
|
50255
|
+
loadSkillMdSkills(root);
|
|
50256
|
+
const registered = getCodingSkillById(name);
|
|
50257
|
+
loadable = (registered?.systemPromptFragment ?? "").trim() === instructions;
|
|
50258
|
+
} catch {
|
|
50259
|
+
}
|
|
50260
|
+
const verb = existed ? "Replaced existing skill" : "Created skill";
|
|
50261
|
+
const lines = [
|
|
50262
|
+
`${verb} "${name}" (${scope} scope).`,
|
|
50263
|
+
`Saved to: ${written.path}`
|
|
50264
|
+
];
|
|
50265
|
+
if (!loadable) {
|
|
50266
|
+
lines.push(
|
|
50267
|
+
`Note: \`${name}\` currently resolves to a DIFFERENT skill already registered from another root (a built-in or an earlier search dir wins), so \`/skill ${name}\` may load that one instead. The file on disk is unchanged.`
|
|
50268
|
+
);
|
|
50269
|
+
}
|
|
50270
|
+
lines.push(
|
|
50271
|
+
`Use it now: \`/skill ${name}\` \u2014 or call the \`skill\` tool with name "${name}". Skills are discovered on demand, so no restart is needed.`
|
|
50272
|
+
);
|
|
50273
|
+
return typedOk({
|
|
50274
|
+
name,
|
|
50275
|
+
scope,
|
|
50276
|
+
path: written.path,
|
|
50277
|
+
overwritten: existed,
|
|
50278
|
+
loadable,
|
|
50279
|
+
message: lines.join("\n")
|
|
50280
|
+
});
|
|
50281
|
+
}
|
|
50282
|
+
};
|
|
50283
|
+
}
|
|
50284
|
+
var NAME_RE2, CreateSkillArgsSchema;
|
|
50285
|
+
var init_createSkillTool = __esm({
|
|
50286
|
+
"src/cli/tools/createSkillTool.ts"() {
|
|
50287
|
+
"use strict";
|
|
50288
|
+
init_zod();
|
|
50289
|
+
init_skills2();
|
|
50290
|
+
init_toolTypes();
|
|
50291
|
+
init_skillConfigIo();
|
|
50292
|
+
init_skillsMd();
|
|
50293
|
+
NAME_RE2 = /^[a-z0-9][a-z0-9-]{1,39}$/;
|
|
50294
|
+
CreateSkillArgsSchema = external_exports.object({
|
|
50295
|
+
name: external_exports.string().regex(NAME_RE2).describe(
|
|
50296
|
+
"Skill id/slug: 2-40 chars, lowercase letters/digits/hyphens, must start with a letter or digit."
|
|
50297
|
+
),
|
|
50298
|
+
description: external_exports.string().min(1).describe(
|
|
50299
|
+
"One-line description shown in the skill catalog (when to use it). Collapsed to a single line."
|
|
50300
|
+
),
|
|
50301
|
+
instructions: external_exports.string().min(1).describe(
|
|
50302
|
+
"The skill body, in markdown: goal, step-by-step procedure, exact commands, pitfalls. Becomes the loaded instructions verbatim."
|
|
50303
|
+
),
|
|
50304
|
+
scope: external_exports.enum(["project", "user"]).optional().describe(
|
|
50305
|
+
"Where to save: 'project' (default) = <cwd>/.zelari/skills (repo-shared); 'user' = ~/.zelari-code/skills (every project)."
|
|
50306
|
+
),
|
|
50307
|
+
overwrite: external_exports.boolean().optional().describe("Default false: fail if a SKILL.md for that name already exists. Pass true to replace it.")
|
|
50308
|
+
});
|
|
50309
|
+
}
|
|
50310
|
+
});
|
|
50311
|
+
|
|
49913
50312
|
// src/cli/tools/todoTools.ts
|
|
49914
50313
|
function createTodoWriteTool() {
|
|
49915
50314
|
return {
|
|
@@ -50301,13 +50700,13 @@ async function scanTsbuildinfo(root) {
|
|
|
50301
50700
|
return found;
|
|
50302
50701
|
}
|
|
50303
50702
|
async function gitStatusPorcelain(root) {
|
|
50304
|
-
return new Promise((
|
|
50703
|
+
return new Promise((resolve10) => {
|
|
50305
50704
|
const child = spawn9("git", ["status", "--porcelain"], { cwd: root, shell: false });
|
|
50306
50705
|
let out = "";
|
|
50307
50706
|
child.stdout.on("data", (d) => out += d.toString());
|
|
50308
50707
|
child.stderr.on("data", (d) => out += d.toString());
|
|
50309
|
-
child.on("error", () =>
|
|
50310
|
-
child.on("close", (code) =>
|
|
50708
|
+
child.on("error", () => resolve10("<git-unavailable>"));
|
|
50709
|
+
child.on("close", (code) => resolve10(code === 0 ? out : `<git-exit-${code ?? "none"}>`));
|
|
50311
50710
|
});
|
|
50312
50711
|
}
|
|
50313
50712
|
async function fingerprintWorkspace(root) {
|
|
@@ -50354,14 +50753,14 @@ var init_inspectTypecheckSafety = __esm({
|
|
|
50354
50753
|
// src/cli/tools/inspectCommand.ts
|
|
50355
50754
|
import { spawn as spawn10 } from "node:child_process";
|
|
50356
50755
|
import { createHash as createHash14 } from "node:crypto";
|
|
50357
|
-
import { existsSync as
|
|
50756
|
+
import { existsSync as existsSync30, promises as fs23 } from "node:fs";
|
|
50358
50757
|
import os2 from "node:os";
|
|
50359
50758
|
import path52 from "node:path";
|
|
50360
50759
|
function resolveNodeModuleBin(start, rel2) {
|
|
50361
50760
|
let dir = path52.resolve(start);
|
|
50362
50761
|
for (; ; ) {
|
|
50363
50762
|
const candidate = path52.join(dir, "node_modules", rel2);
|
|
50364
|
-
if (
|
|
50763
|
+
if (existsSync30(candidate)) return candidate;
|
|
50365
50764
|
const parent = path52.dirname(dir);
|
|
50366
50765
|
if (parent === dir) return void 0;
|
|
50367
50766
|
dir = parent;
|
|
@@ -50465,12 +50864,12 @@ function buildInspectCommand(op, ctx) {
|
|
|
50465
50864
|
}
|
|
50466
50865
|
}
|
|
50467
50866
|
function runSpawn(command, argv, opts) {
|
|
50468
|
-
return new Promise((
|
|
50867
|
+
return new Promise((resolve10) => {
|
|
50469
50868
|
let child;
|
|
50470
50869
|
try {
|
|
50471
50870
|
child = spawn10(command, argv, { cwd: opts.cwd, shell: false });
|
|
50472
50871
|
} catch (err) {
|
|
50473
|
-
|
|
50872
|
+
resolve10({ code: null, stdout: "", stderr: String(err), timedOut: false, spawnError: String(err) });
|
|
50474
50873
|
return;
|
|
50475
50874
|
}
|
|
50476
50875
|
let stdout = "";
|
|
@@ -50492,14 +50891,14 @@ function runSpawn(command, argv, opts) {
|
|
|
50492
50891
|
if (settled) return;
|
|
50493
50892
|
settled = true;
|
|
50494
50893
|
clearTimeout(timer);
|
|
50495
|
-
|
|
50894
|
+
resolve10({ code: null, stdout, stderr, timedOut, spawnError: err.message });
|
|
50496
50895
|
});
|
|
50497
50896
|
child.on("close", (code) => {
|
|
50498
50897
|
if (settled) return;
|
|
50499
50898
|
settled = true;
|
|
50500
50899
|
clearTimeout(timer);
|
|
50501
50900
|
opts.signal?.removeEventListener("abort", onAbort);
|
|
50502
|
-
|
|
50901
|
+
resolve10({ code, stdout, stderr, timedOut });
|
|
50503
50902
|
});
|
|
50504
50903
|
});
|
|
50505
50904
|
}
|
|
@@ -50784,7 +51183,7 @@ function createExecProcessTool(root, opts = {}) {
|
|
|
50784
51183
|
const msg = err instanceof SandboxViolationError ? err.message : String(err);
|
|
50785
51184
|
return typedErr(`[sandbox] ${msg}`);
|
|
50786
51185
|
}
|
|
50787
|
-
return new Promise((
|
|
51186
|
+
return new Promise((resolve10) => {
|
|
50788
51187
|
const start = Date.now();
|
|
50789
51188
|
const spec = { ...baseSpec, network: opts.resolveNetwork?.(input) ?? baseSpec.network };
|
|
50790
51189
|
const res = spawnJailed(spec, {
|
|
@@ -50796,11 +51195,11 @@ function createExecProcessTool(root, opts = {}) {
|
|
|
50796
51195
|
envExtras: { CI: process.env.CI ?? "1" }
|
|
50797
51196
|
});
|
|
50798
51197
|
if (res.outcome === "denied") {
|
|
50799
|
-
|
|
51198
|
+
resolve10(typedErr(res.reason));
|
|
50800
51199
|
return;
|
|
50801
51200
|
}
|
|
50802
51201
|
if (res.outcome === "failed") {
|
|
50803
|
-
|
|
51202
|
+
resolve10(typedErr(`exec_process could not launch ${input.program}: ${res.reason}`));
|
|
50804
51203
|
return;
|
|
50805
51204
|
}
|
|
50806
51205
|
const meta3 = res.notice ? { status: "complete", warnings: [`os-jail: ${res.notice}`] } : void 0;
|
|
@@ -50816,7 +51215,7 @@ function createExecProcessTool(root, opts = {}) {
|
|
|
50816
51215
|
const timeoutMs2 = typeof input.timeoutMs === "number" && input.timeoutMs > 0 ? input.timeoutMs : 3e4;
|
|
50817
51216
|
const timer = setTimeout(() => {
|
|
50818
51217
|
child.kill("SIGTERM");
|
|
50819
|
-
|
|
51218
|
+
resolve10(
|
|
50820
51219
|
typedErr(
|
|
50821
51220
|
`exec_process timed out after ${timeoutMs2}ms running: ${[input.program, ...argv].join(" ")}`
|
|
50822
51221
|
)
|
|
@@ -50824,11 +51223,11 @@ function createExecProcessTool(root, opts = {}) {
|
|
|
50824
51223
|
}, timeoutMs2);
|
|
50825
51224
|
child.on("error", (err) => {
|
|
50826
51225
|
clearTimeout(timer);
|
|
50827
|
-
|
|
51226
|
+
resolve10(typedErr(`exec_process could not launch ${input.program}: ${err.message}`));
|
|
50828
51227
|
});
|
|
50829
51228
|
child.on("close", (code) => {
|
|
50830
51229
|
clearTimeout(timer);
|
|
50831
|
-
|
|
51230
|
+
resolve10(
|
|
50832
51231
|
typedOk(
|
|
50833
51232
|
{
|
|
50834
51233
|
exitCode: code ?? -1,
|
|
@@ -51357,12 +51756,12 @@ var init_client = __esm({
|
|
|
51357
51756
|
if (this.closed) return Promise.reject(new Error("LSP transport is closed"));
|
|
51358
51757
|
const id3 = this.nextId++;
|
|
51359
51758
|
const msg = { jsonrpc: "2.0", id: id3, method, ...params !== void 0 ? { params } : {} };
|
|
51360
|
-
return new Promise((
|
|
51759
|
+
return new Promise((resolve10, reject) => {
|
|
51361
51760
|
const timer = setTimeout(() => {
|
|
51362
51761
|
this.pending.delete(id3);
|
|
51363
51762
|
reject(new Error(`LSP request "${method}" timed out after ${this.timeoutMs}ms`));
|
|
51364
51763
|
}, this.timeoutMs);
|
|
51365
|
-
this.pending.set(id3, { resolve:
|
|
51764
|
+
this.pending.set(id3, { resolve: resolve10, reject, timer });
|
|
51366
51765
|
this.transport.send(encodeMessage(msg));
|
|
51367
51766
|
});
|
|
51368
51767
|
}
|
|
@@ -51481,7 +51880,7 @@ var init_servers = __esm({
|
|
|
51481
51880
|
|
|
51482
51881
|
// src/cli/lsp/manager.ts
|
|
51483
51882
|
import { spawn as spawn11 } from "node:child_process";
|
|
51484
|
-
import { readFileSync as
|
|
51883
|
+
import { readFileSync as readFileSync21 } from "node:fs";
|
|
51485
51884
|
import path54 from "node:path";
|
|
51486
51885
|
function processTransport(child) {
|
|
51487
51886
|
return {
|
|
@@ -51639,8 +52038,8 @@ var init_manager = __esm({
|
|
|
51639
52038
|
if (cached2 !== void 0) return cached2;
|
|
51640
52039
|
let resolveInit;
|
|
51641
52040
|
let rejectInit;
|
|
51642
|
-
const initialized = new Promise((
|
|
51643
|
-
resolveInit =
|
|
52041
|
+
const initialized = new Promise((resolve10, reject) => {
|
|
52042
|
+
resolveInit = resolve10;
|
|
51644
52043
|
rejectInit = reject;
|
|
51645
52044
|
});
|
|
51646
52045
|
let entry = null;
|
|
@@ -51695,7 +52094,7 @@ var init_manager = __esm({
|
|
|
51695
52094
|
const uri = pathToUri(file2);
|
|
51696
52095
|
let text;
|
|
51697
52096
|
try {
|
|
51698
|
-
text =
|
|
52097
|
+
text = readFileSync21(file2, "utf8");
|
|
51699
52098
|
} catch {
|
|
51700
52099
|
text = "";
|
|
51701
52100
|
}
|
|
@@ -51975,7 +52374,7 @@ var init_store2 = __esm({
|
|
|
51975
52374
|
});
|
|
51976
52375
|
|
|
51977
52376
|
// src/cli/semantic/index.ts
|
|
51978
|
-
import { promises as fs24, existsSync as
|
|
52377
|
+
import { promises as fs24, existsSync as existsSync31, readFileSync as readFileSync22 } from "node:fs";
|
|
51979
52378
|
import path55 from "node:path";
|
|
51980
52379
|
import { createHash as createHash15 } from "node:crypto";
|
|
51981
52380
|
function getIndexPath(root) {
|
|
@@ -52058,9 +52457,9 @@ async function saveIndex(root, data) {
|
|
|
52058
52457
|
}
|
|
52059
52458
|
function loadIndex(root) {
|
|
52060
52459
|
const file2 = getIndexPath(root);
|
|
52061
|
-
if (!
|
|
52460
|
+
if (!existsSync31(file2)) return null;
|
|
52062
52461
|
try {
|
|
52063
|
-
const parsed = JSON.parse(
|
|
52462
|
+
const parsed = JSON.parse(readFileSync22(file2, "utf8"));
|
|
52064
52463
|
if (parsed && Array.isArray(parsed.chunks)) return parsed;
|
|
52065
52464
|
} catch {
|
|
52066
52465
|
}
|
|
@@ -52165,14 +52564,14 @@ function resolveStreamTimeouts(capabilities) {
|
|
|
52165
52564
|
};
|
|
52166
52565
|
}
|
|
52167
52566
|
function abortableSleep(ms, signal) {
|
|
52168
|
-
return new Promise((
|
|
52169
|
-
if (signal?.aborted) return
|
|
52170
|
-
const t = setTimeout(
|
|
52567
|
+
return new Promise((resolve10) => {
|
|
52568
|
+
if (signal?.aborted) return resolve10();
|
|
52569
|
+
const t = setTimeout(resolve10, ms);
|
|
52171
52570
|
signal?.addEventListener(
|
|
52172
52571
|
"abort",
|
|
52173
52572
|
() => {
|
|
52174
52573
|
clearTimeout(t);
|
|
52175
|
-
|
|
52574
|
+
resolve10();
|
|
52176
52575
|
},
|
|
52177
52576
|
{ once: true }
|
|
52178
52577
|
);
|
|
@@ -53046,8 +53445,8 @@ async function runBrowserCheck(options, loader) {
|
|
|
53046
53445
|
const failedRequests = [];
|
|
53047
53446
|
const evaluateResults = [];
|
|
53048
53447
|
const base2 = { ok: false, consoleErrors, pageErrors, failedRequests };
|
|
53049
|
-
const
|
|
53050
|
-
const pw = await
|
|
53448
|
+
const resolve10 = loader ?? (() => loadPlaywright(options.cwd ?? process.cwd()));
|
|
53449
|
+
const pw = await resolve10();
|
|
53051
53450
|
if (!pw) {
|
|
53052
53451
|
return {
|
|
53053
53452
|
...base2,
|
|
@@ -53422,18 +53821,18 @@ __export(targets_exports, {
|
|
|
53422
53821
|
});
|
|
53423
53822
|
import {
|
|
53424
53823
|
chmodSync,
|
|
53425
|
-
existsSync as
|
|
53426
|
-
mkdirSync as
|
|
53427
|
-
readFileSync as
|
|
53428
|
-
writeFileSync as
|
|
53824
|
+
existsSync as existsSync32,
|
|
53825
|
+
mkdirSync as mkdirSync14,
|
|
53826
|
+
readFileSync as readFileSync23,
|
|
53827
|
+
writeFileSync as writeFileSync17
|
|
53429
53828
|
} from "node:fs";
|
|
53430
|
-
import { dirname as
|
|
53829
|
+
import { dirname as dirname5, join as join21 } from "node:path";
|
|
53431
53830
|
import { spawn as spawn12 } from "node:child_process";
|
|
53432
53831
|
function getSshTargetsPath() {
|
|
53433
|
-
return
|
|
53832
|
+
return join21(zelariHome(), "ssh-targets.json");
|
|
53434
53833
|
}
|
|
53435
53834
|
function getSshSecretsPath() {
|
|
53436
|
-
return
|
|
53835
|
+
return join21(zelariHome(), "ssh-secrets.json");
|
|
53437
53836
|
}
|
|
53438
53837
|
function normalizeAuth(auth) {
|
|
53439
53838
|
if (auth === "keyPath") return "keyPath";
|
|
@@ -53441,21 +53840,21 @@ function normalizeAuth(auth) {
|
|
|
53441
53840
|
return "agent";
|
|
53442
53841
|
}
|
|
53443
53842
|
function readSecrets() {
|
|
53444
|
-
const
|
|
53445
|
-
if (!
|
|
53843
|
+
const path104 = getSshSecretsPath();
|
|
53844
|
+
if (!existsSync32(path104)) return {};
|
|
53446
53845
|
try {
|
|
53447
|
-
return JSON.parse(
|
|
53846
|
+
return JSON.parse(readFileSync23(path104, "utf8"));
|
|
53448
53847
|
} catch {
|
|
53449
53848
|
return {};
|
|
53450
53849
|
}
|
|
53451
53850
|
}
|
|
53452
53851
|
function writeSecrets(data) {
|
|
53453
|
-
const
|
|
53454
|
-
|
|
53455
|
-
|
|
53852
|
+
const path104 = getSshSecretsPath();
|
|
53853
|
+
mkdirSync14(dirname5(path104), { recursive: true });
|
|
53854
|
+
writeFileSync17(path104, `${JSON.stringify(data, null, 2)}
|
|
53456
53855
|
`, "utf8");
|
|
53457
53856
|
try {
|
|
53458
|
-
chmodSync(
|
|
53857
|
+
chmodSync(path104, 384);
|
|
53459
53858
|
} catch {
|
|
53460
53859
|
}
|
|
53461
53860
|
}
|
|
@@ -53484,10 +53883,10 @@ function deleteSshPassword(id3) {
|
|
|
53484
53883
|
writeSecrets({ passwords });
|
|
53485
53884
|
}
|
|
53486
53885
|
function readStore2() {
|
|
53487
|
-
const
|
|
53488
|
-
if (!
|
|
53886
|
+
const path104 = getSshTargetsPath();
|
|
53887
|
+
if (!existsSync32(path104)) return [];
|
|
53489
53888
|
try {
|
|
53490
|
-
const parsed = JSON.parse(
|
|
53889
|
+
const parsed = JSON.parse(readFileSync23(path104, "utf8"));
|
|
53491
53890
|
const list = Array.isArray(parsed.targets) ? parsed.targets : [];
|
|
53492
53891
|
return list.filter(
|
|
53493
53892
|
(t) => t && typeof t.id === "string" && typeof t.host === "string" && typeof t.user === "string"
|
|
@@ -53502,11 +53901,11 @@ function readStore2() {
|
|
|
53502
53901
|
}
|
|
53503
53902
|
}
|
|
53504
53903
|
function writeStore2(targets) {
|
|
53505
|
-
const
|
|
53506
|
-
|
|
53904
|
+
const path104 = getSshTargetsPath();
|
|
53905
|
+
mkdirSync14(dirname5(path104), { recursive: true });
|
|
53507
53906
|
const clean = targets.map(({ hasPassword: _hp, ...t }) => t);
|
|
53508
|
-
|
|
53509
|
-
|
|
53907
|
+
writeFileSync17(
|
|
53908
|
+
path104,
|
|
53510
53909
|
`${JSON.stringify({ targets: clean }, null, 2)}
|
|
53511
53910
|
`,
|
|
53512
53911
|
"utf8"
|
|
@@ -53606,17 +54005,17 @@ function buildSshBaseArgs(target) {
|
|
|
53606
54005
|
return args;
|
|
53607
54006
|
}
|
|
53608
54007
|
function ensureAskpassHelper() {
|
|
53609
|
-
const dir =
|
|
53610
|
-
|
|
53611
|
-
const cjs =
|
|
53612
|
-
|
|
54008
|
+
const dir = join21(zelariHome(), "ssh-helpers");
|
|
54009
|
+
mkdirSync14(dir, { recursive: true });
|
|
54010
|
+
const cjs = join21(dir, "askpass.cjs");
|
|
54011
|
+
writeFileSync17(
|
|
53613
54012
|
cjs,
|
|
53614
54013
|
"process.stdout.write(process.env.ZELARI_SSH_ASKPASS_PASS || '');\n",
|
|
53615
54014
|
"utf8"
|
|
53616
54015
|
);
|
|
53617
54016
|
if (process.platform === "win32") {
|
|
53618
|
-
const cmd =
|
|
53619
|
-
|
|
54017
|
+
const cmd = join21(dir, "askpass.cmd");
|
|
54018
|
+
writeFileSync17(
|
|
53620
54019
|
cmd,
|
|
53621
54020
|
`@echo off\r
|
|
53622
54021
|
node "%~dp0askpass.cjs"\r
|
|
@@ -53625,8 +54024,8 @@ node "%~dp0askpass.cjs"\r
|
|
|
53625
54024
|
);
|
|
53626
54025
|
return cmd;
|
|
53627
54026
|
}
|
|
53628
|
-
const sh =
|
|
53629
|
-
|
|
54027
|
+
const sh = join21(dir, "askpass.sh");
|
|
54028
|
+
writeFileSync17(
|
|
53630
54029
|
sh,
|
|
53631
54030
|
`#!/bin/sh
|
|
53632
54031
|
exec node "$(dirname "$0")/askpass.cjs"
|
|
@@ -53640,9 +54039,9 @@ exec node "$(dirname "$0")/askpass.cjs"
|
|
|
53640
54039
|
return sh;
|
|
53641
54040
|
}
|
|
53642
54041
|
function runSsh(target, remoteCommand, timeoutMs2 = 6e4) {
|
|
53643
|
-
return new Promise((
|
|
54042
|
+
return new Promise((resolve10) => {
|
|
53644
54043
|
if (target.auth === "password" && !getSshPassword(target.id)) {
|
|
53645
|
-
|
|
54044
|
+
resolve10({
|
|
53646
54045
|
code: 1,
|
|
53647
54046
|
stdout: "",
|
|
53648
54047
|
stderr: "No password stored for this target \u2014 edit target and set password"
|
|
@@ -53674,7 +54073,7 @@ function runSsh(target, remoteCommand, timeoutMs2 = 6e4) {
|
|
|
53674
54073
|
});
|
|
53675
54074
|
const timer = setTimeout(() => {
|
|
53676
54075
|
child.kill("SIGTERM");
|
|
53677
|
-
|
|
54076
|
+
resolve10({
|
|
53678
54077
|
code: 124,
|
|
53679
54078
|
stdout,
|
|
53680
54079
|
stderr: stderr + "\n[ssh] timeout"
|
|
@@ -53682,7 +54081,7 @@ function runSsh(target, remoteCommand, timeoutMs2 = 6e4) {
|
|
|
53682
54081
|
}, timeoutMs2);
|
|
53683
54082
|
child.on("error", (err) => {
|
|
53684
54083
|
clearTimeout(timer);
|
|
53685
|
-
|
|
54084
|
+
resolve10({
|
|
53686
54085
|
code: 127,
|
|
53687
54086
|
stdout,
|
|
53688
54087
|
stderr: err.message.includes("ENOENT") ? "ssh not found on PATH \u2014 install OpenSSH client" : err.message
|
|
@@ -53690,7 +54089,7 @@ function runSsh(target, remoteCommand, timeoutMs2 = 6e4) {
|
|
|
53690
54089
|
});
|
|
53691
54090
|
child.on("close", (code) => {
|
|
53692
54091
|
clearTimeout(timer);
|
|
53693
|
-
|
|
54092
|
+
resolve10({ code: code ?? 1, stdout, stderr });
|
|
53694
54093
|
});
|
|
53695
54094
|
});
|
|
53696
54095
|
}
|
|
@@ -53699,9 +54098,9 @@ function readSshPublicKey(keyOrPubPath) {
|
|
|
53699
54098
|
if (!raw) return { ok: false, error: "Empty path" };
|
|
53700
54099
|
const candidates = raw.endsWith(".pub") ? [raw] : [`${raw}.pub`, raw];
|
|
53701
54100
|
for (const p3 of candidates) {
|
|
53702
|
-
if (!
|
|
54101
|
+
if (!existsSync32(p3)) continue;
|
|
53703
54102
|
try {
|
|
53704
|
-
const content =
|
|
54103
|
+
const content = readFileSync23(p3, "utf8").trim();
|
|
53705
54104
|
if (!content) continue;
|
|
53706
54105
|
if (/BEGIN .*PRIVATE KEY/i.test(content)) {
|
|
53707
54106
|
return {
|
|
@@ -53752,11 +54151,11 @@ function formatSshTargetsForPrompt() {
|
|
|
53752
54151
|
];
|
|
53753
54152
|
for (const t of targets) {
|
|
53754
54153
|
const tags = t.tags?.length ? ` tags=[${t.tags.join(",")}]` : "";
|
|
53755
|
-
const
|
|
54154
|
+
const path104 = t.defaultRemotePath ? ` remotePath=${t.defaultRemotePath}` : "";
|
|
53756
54155
|
const allow = t.allowedCommands?.length ? ` allowed=${t.allowedCommands.join("|")}` : " allowed=status-only";
|
|
53757
54156
|
const auth = t.auth === "password" ? " auth=password" : t.auth === "keyPath" ? " auth=key" : " auth=agent";
|
|
53758
54157
|
lines.push(
|
|
53759
|
-
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${
|
|
54158
|
+
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${path104}${tags}${allow}`
|
|
53760
54159
|
);
|
|
53761
54160
|
}
|
|
53762
54161
|
return lines.join("\n");
|
|
@@ -54467,14 +54866,14 @@ function backoffDelay2(attempt, retryAfterHeader) {
|
|
|
54467
54866
|
return Math.min(BACKOFF_BASE_MS2 * 2 ** attempt, BACKOFF_CAP_MS2);
|
|
54468
54867
|
}
|
|
54469
54868
|
function abortableSleep2(ms, signal) {
|
|
54470
|
-
return new Promise((
|
|
54471
|
-
if (signal?.aborted) return
|
|
54472
|
-
const t = setTimeout(
|
|
54869
|
+
return new Promise((resolve10) => {
|
|
54870
|
+
if (signal?.aborted) return resolve10();
|
|
54871
|
+
const t = setTimeout(resolve10, ms);
|
|
54473
54872
|
signal?.addEventListener(
|
|
54474
54873
|
"abort",
|
|
54475
54874
|
() => {
|
|
54476
54875
|
clearTimeout(t);
|
|
54477
|
-
|
|
54876
|
+
resolve10();
|
|
54478
54877
|
},
|
|
54479
54878
|
{ once: true }
|
|
54480
54879
|
);
|
|
@@ -55141,7 +55540,7 @@ __export(folderTrust_exports, {
|
|
|
55141
55540
|
trustFolder: () => trustFolder,
|
|
55142
55541
|
untrustFolder: () => untrustFolder
|
|
55143
55542
|
});
|
|
55144
|
-
import { existsSync as
|
|
55543
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync15, readFileSync as readFileSync24, writeFileSync as writeFileSync18 } from "node:fs";
|
|
55145
55544
|
import path60 from "node:path";
|
|
55146
55545
|
function trustStorePath() {
|
|
55147
55546
|
return _overrideStorePath ?? trustConfigPath();
|
|
@@ -55152,7 +55551,7 @@ function normalize6(p3) {
|
|
|
55152
55551
|
}
|
|
55153
55552
|
function readStore3() {
|
|
55154
55553
|
try {
|
|
55155
|
-
const raw =
|
|
55554
|
+
const raw = readFileSync24(trustStorePath(), "utf8");
|
|
55156
55555
|
const parsed = JSON.parse(raw);
|
|
55157
55556
|
if (parsed && Array.isArray(parsed.folders)) return parsed;
|
|
55158
55557
|
return DEFAULT_STORE;
|
|
@@ -55163,8 +55562,8 @@ function readStore3() {
|
|
|
55163
55562
|
function writeStore3(store6) {
|
|
55164
55563
|
const p3 = trustStorePath();
|
|
55165
55564
|
try {
|
|
55166
|
-
|
|
55167
|
-
|
|
55565
|
+
mkdirSync15(path60.dirname(p3), { recursive: true });
|
|
55566
|
+
writeFileSync18(p3, JSON.stringify(store6, null, 2), "utf8");
|
|
55168
55567
|
} catch (err) {
|
|
55169
55568
|
throw new Error(
|
|
55170
55569
|
`failed to persist trust store ${p3}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -55219,7 +55618,7 @@ function getTrustStorePath() {
|
|
|
55219
55618
|
return trustStorePath();
|
|
55220
55619
|
}
|
|
55221
55620
|
function hasTrustStore() {
|
|
55222
|
-
return
|
|
55621
|
+
return existsSync33(trustStorePath());
|
|
55223
55622
|
}
|
|
55224
55623
|
function _setTrustStorePathForTests(p3) {
|
|
55225
55624
|
_overrideStorePath = p3;
|
|
@@ -55235,13 +55634,13 @@ var init_folderTrust = __esm({
|
|
|
55235
55634
|
});
|
|
55236
55635
|
|
|
55237
55636
|
// src/cli/safety/lifecycleHooks.ts
|
|
55238
|
-
import { join as
|
|
55239
|
-
import { readdirSync as
|
|
55637
|
+
import { join as join22 } from "node:path";
|
|
55638
|
+
import { readdirSync as readdirSync7, statSync as statSync3 } from "node:fs";
|
|
55240
55639
|
function globalHooksDir() {
|
|
55241
|
-
return
|
|
55640
|
+
return join22(zelariHome(), "hooks");
|
|
55242
55641
|
}
|
|
55243
55642
|
function projectHooksDir(projectRoot) {
|
|
55244
|
-
return
|
|
55643
|
+
return join22(projectRoot, ".zelari", "hooks");
|
|
55245
55644
|
}
|
|
55246
55645
|
function resolveHookFailureMode(override, env = process.env) {
|
|
55247
55646
|
const v = override?.trim().toLowerCase();
|
|
@@ -55254,7 +55653,7 @@ function fingerprintHookDirs(dirs) {
|
|
|
55254
55653
|
for (const dir of dirs) {
|
|
55255
55654
|
let names;
|
|
55256
55655
|
try {
|
|
55257
|
-
names =
|
|
55656
|
+
names = readdirSync7(dir).filter((f) => f.endsWith(".json")).sort();
|
|
55258
55657
|
} catch {
|
|
55259
55658
|
parts.push(`${dir}:missing`);
|
|
55260
55659
|
continue;
|
|
@@ -55268,7 +55667,7 @@ function fingerprintHookDirs(dirs) {
|
|
|
55268
55667
|
continue;
|
|
55269
55668
|
}
|
|
55270
55669
|
for (const name of names) {
|
|
55271
|
-
const full =
|
|
55670
|
+
const full = join22(dir, name);
|
|
55272
55671
|
try {
|
|
55273
55672
|
const st = statSync3(full);
|
|
55274
55673
|
parts.push(`${full}:${st.mtimeMs}:${st.size}`);
|
|
@@ -55553,8 +55952,8 @@ function networkClaimsForUrls(urls) {
|
|
|
55553
55952
|
}
|
|
55554
55953
|
function mcpClaimFromName(registryName) {
|
|
55555
55954
|
const rest = registryName.startsWith("mcp_") ? registryName.slice("mcp_".length) : "";
|
|
55556
|
-
const
|
|
55557
|
-
return
|
|
55955
|
+
const sep5 = rest.indexOf("_");
|
|
55956
|
+
return sep5 <= 0 || sep5 === rest.length - 1 ? null : { kind: "mcp", server: rest.slice(0, sep5), tool: rest.slice(sep5 + 1) };
|
|
55558
55957
|
}
|
|
55559
55958
|
function browserActionUrls(a) {
|
|
55560
55959
|
const actions = Array.isArray(a["actions"]) ? a["actions"] : [];
|
|
@@ -55968,9 +56367,11 @@ __export(toolRegistry_exports, {
|
|
|
55968
56367
|
createKrakenSubAgentContextFactory: () => createKrakenSubAgentContextFactory,
|
|
55969
56368
|
getCliToolCatalogEntries: () => getCliToolCatalogEntries,
|
|
55970
56369
|
registerCliToolsIntoCouncilCatalog: () => registerCliToolsIntoCouncilCatalog,
|
|
56370
|
+
resolveTentacleThinkingInput: () => resolveTentacleThinkingInput,
|
|
56371
|
+
tentacleThinkingEnvKey: () => tentacleThinkingEnvKey,
|
|
55971
56372
|
wrapWithSandbox: () => wrapWithSandbox
|
|
55972
56373
|
});
|
|
55973
|
-
import { existsSync as
|
|
56374
|
+
import { existsSync as existsSync34 } from "node:fs";
|
|
55974
56375
|
import path63 from "node:path";
|
|
55975
56376
|
function createBuiltinToolRegistry(options = {}) {
|
|
55976
56377
|
const root = options.root ?? process.cwd();
|
|
@@ -56127,6 +56528,10 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
56127
56528
|
if (skillTool) {
|
|
56128
56529
|
registry4.register(skillTool);
|
|
56129
56530
|
}
|
|
56531
|
+
const skillCreateTool = enableSkill ? withPerm(createCreateSkillTool({ cwd: root })) : null;
|
|
56532
|
+
if (skillCreateTool) {
|
|
56533
|
+
registry4.register(skillCreateTool);
|
|
56534
|
+
}
|
|
56130
56535
|
const enableTodos = options.enableTodos !== false && options.readOnly !== true && !gauntletParent && profile === "full";
|
|
56131
56536
|
const todoWrite = enableTodos ? withPerm(createTodoWriteTool()) : null;
|
|
56132
56537
|
const todoRead = enableTodos ? withPerm(createTodoReadTool()) : null;
|
|
@@ -56154,6 +56559,7 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
56154
56559
|
...allowBash ? [safeBash, safeExecProcess] : [],
|
|
56155
56560
|
...askUserTool ? [askUserTool] : [],
|
|
56156
56561
|
...skillTool ? [skillTool] : [],
|
|
56562
|
+
...skillCreateTool ? [skillCreateTool] : [],
|
|
56157
56563
|
...todoWrite ? [todoWrite] : [],
|
|
56158
56564
|
...todoRead ? [todoRead] : [],
|
|
56159
56565
|
...planTaskToolsWrapped.length > 0 ? planTaskToolsWrapped : []
|
|
@@ -56337,9 +56743,29 @@ function taskAgentToProfile(agent) {
|
|
|
56337
56743
|
if (agent === "verify") return "verify";
|
|
56338
56744
|
return "explore";
|
|
56339
56745
|
}
|
|
56746
|
+
function tentacleThinkingEnvKey(agent) {
|
|
56747
|
+
if (agent === "explore") return "ZELARI_KRAKEN_EXPLORE_THINKING";
|
|
56748
|
+
if (agent === "verify") return "ZELARI_KRAKEN_VERIFY_THINKING";
|
|
56749
|
+
return "ZELARI_KRAKEN_GENERAL_THINKING";
|
|
56750
|
+
}
|
|
56751
|
+
function resolveTentacleThinkingInput(agent, taskArg, env = process.env) {
|
|
56752
|
+
const fromArg = typeof taskArg === "string" ? taskArg.trim() : "";
|
|
56753
|
+
const argWins = fromArg.length > 0 && fromArg.toLowerCase() !== "inherit";
|
|
56754
|
+
const key = tentacleThinkingEnvKey(agent);
|
|
56755
|
+
const raw = (argWins ? fromArg : (env[key] ?? "").trim()).trim();
|
|
56756
|
+
if (!raw) return void 0;
|
|
56757
|
+
if (isValidThinkingInput(raw)) return raw.toLowerCase();
|
|
56758
|
+
if (!warnedThinkingInputs.has(raw)) {
|
|
56759
|
+
warnedThinkingInputs.add(raw);
|
|
56760
|
+
console.warn(
|
|
56761
|
+
`[kraken] ignoring invalid thinking effort "${raw}" for the ${agent} tentacle (${key}); using the provider default.`
|
|
56762
|
+
);
|
|
56763
|
+
}
|
|
56764
|
+
return void 0;
|
|
56765
|
+
}
|
|
56340
56766
|
function createKrakenSubAgentContextFactory(opts) {
|
|
56341
56767
|
const { root, audit, sessionId: sessionId2, provider: providerOverride, model: modelOverride, parentPolicy, onPermissionAsk } = opts;
|
|
56342
|
-
return async ({ agent, cwd: subCwd }) => {
|
|
56768
|
+
return async ({ agent, cwd: subCwd, thinkingEffort }) => {
|
|
56343
56769
|
const cfg = providerOverride ? await providerConfigFor(providerOverride) : await providerFromEnv();
|
|
56344
56770
|
if (!cfg) return null;
|
|
56345
56771
|
const { resolveKrakenSubModelAsync: resolveKrakenSubModelAsync2, parseQualifiedModelRef: parseQualifiedModelRef2 } = await Promise.resolve().then(() => (init_krakenModel(), krakenModel_exports));
|
|
@@ -56358,6 +56784,8 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
56358
56784
|
}
|
|
56359
56785
|
}
|
|
56360
56786
|
const subCfg = { ...effCfg, model };
|
|
56787
|
+
const thinkingInput = resolveTentacleThinkingInput(agent, thinkingEffort, process.env);
|
|
56788
|
+
if (thinkingInput) subCfg.thinking = parseThinkingSpec(thinkingInput);
|
|
56361
56789
|
const subProfile = taskAgentToProfile(agent);
|
|
56362
56790
|
const subRoot = subCwd || root;
|
|
56363
56791
|
const agentPolicyForSubProfile = defaultPermissionPolicy({ auto: true });
|
|
@@ -56394,6 +56822,9 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
56394
56822
|
providerStream,
|
|
56395
56823
|
model,
|
|
56396
56824
|
provider: subCfg.providerId,
|
|
56825
|
+
// E (thinking): report the spec actually applied so the parent's
|
|
56826
|
+
// `agent_spawned` event can surface it (arg > kind env > inherited).
|
|
56827
|
+
...subCfg.thinking !== void 0 ? { thinking: stringifyThinkingSpec(subCfg.thinking) } : {},
|
|
56397
56828
|
...model !== parentModel ? {
|
|
56398
56829
|
fallback: {
|
|
56399
56830
|
model: parentModel,
|
|
@@ -56617,7 +57048,7 @@ function claimedSourcePath(token, args, root) {
|
|
|
56617
57048
|
const candidate = path63.isAbsolute(cleaned) ? path63.normalize(cleaned) : path63.resolve(base2, cleaned);
|
|
56618
57049
|
try {
|
|
56619
57050
|
const contained = resolveSandboxedPath(candidate, { root });
|
|
56620
|
-
if (
|
|
57051
|
+
if (existsSync34(contained)) return contained;
|
|
56621
57052
|
} catch {
|
|
56622
57053
|
}
|
|
56623
57054
|
}
|
|
@@ -56851,7 +57282,7 @@ function redactForAudit(args) {
|
|
|
56851
57282
|
}
|
|
56852
57283
|
return out;
|
|
56853
57284
|
}
|
|
56854
|
-
var HARNESS_BUILTIN_NAMES, DIAG_SOURCE_EXTENSIONS, EXEC_DIAGNOSTICS_MAX_FILES;
|
|
57285
|
+
var HARNESS_BUILTIN_NAMES, warnedThinkingInputs, DIAG_SOURCE_EXTENSIONS, EXEC_DIAGNOSTICS_MAX_FILES;
|
|
56855
57286
|
var init_toolRegistry = __esm({
|
|
56856
57287
|
"src/cli/toolRegistry.ts"() {
|
|
56857
57288
|
"use strict";
|
|
@@ -56873,6 +57304,7 @@ var init_toolRegistry = __esm({
|
|
|
56873
57304
|
init_krakenSelectTool();
|
|
56874
57305
|
init_askUser();
|
|
56875
57306
|
init_skillTool();
|
|
57307
|
+
init_createSkillTool();
|
|
56876
57308
|
init_todoTools();
|
|
56877
57309
|
init_planTaskTools();
|
|
56878
57310
|
init_inspectCommand();
|
|
@@ -56890,6 +57322,7 @@ var init_toolRegistry = __esm({
|
|
|
56890
57322
|
init_openai_compatible();
|
|
56891
57323
|
init_resolveStream();
|
|
56892
57324
|
init_providerConfig();
|
|
57325
|
+
init_thinking();
|
|
56893
57326
|
init_crossProviderFailover();
|
|
56894
57327
|
init_keyStore();
|
|
56895
57328
|
init_toolPermissions();
|
|
@@ -56924,6 +57357,7 @@ var init_toolRegistry = __esm({
|
|
|
56924
57357
|
"fetch_url",
|
|
56925
57358
|
"web_search"
|
|
56926
57359
|
]);
|
|
57360
|
+
warnedThinkingInputs = /* @__PURE__ */ new Set();
|
|
56927
57361
|
DIAG_SOURCE_EXTENSIONS = new Set(
|
|
56928
57362
|
DEFAULT_PROVIDERS.flatMap((p3) => p3.extensions)
|
|
56929
57363
|
);
|
|
@@ -56932,7 +57366,7 @@ var init_toolRegistry = __esm({
|
|
|
56932
57366
|
});
|
|
56933
57367
|
|
|
56934
57368
|
// src/cli/metrics.ts
|
|
56935
|
-
import { promises as fs27, existsSync as
|
|
57369
|
+
import { promises as fs27, existsSync as existsSync35, statSync as statSync4, renameSync as renameSync4, appendFileSync as appendFileSync3, mkdirSync as mkdirSync16 } from "node:fs";
|
|
56936
57370
|
import path64 from "node:path";
|
|
56937
57371
|
async function readMetrics(file2) {
|
|
56938
57372
|
let raw = "";
|
|
@@ -56983,7 +57417,7 @@ var init_metrics3 = __esm({
|
|
|
56983
57417
|
writeQueue = Promise.resolve();
|
|
56984
57418
|
constructor(file2) {
|
|
56985
57419
|
this.file = file2 ?? metricsPath();
|
|
56986
|
-
|
|
57420
|
+
mkdirSync16(path64.dirname(this.file), { recursive: true });
|
|
56987
57421
|
}
|
|
56988
57422
|
/** Metrics file path — doctor/summary readers use this. */
|
|
56989
57423
|
get filePath() {
|
|
@@ -56998,12 +57432,12 @@ var init_metrics3 = __esm({
|
|
|
56998
57432
|
}
|
|
56999
57433
|
/** Append a single record synchronously (file I/O). */
|
|
57000
57434
|
append(rec) {
|
|
57001
|
-
return new Promise((
|
|
57435
|
+
return new Promise((resolve10, reject) => {
|
|
57002
57436
|
try {
|
|
57003
57437
|
this.maybeRotate();
|
|
57004
57438
|
const line = JSON.stringify(rec) + "\n";
|
|
57005
57439
|
appendFileSync3(this.file, line, { encoding: "utf-8" });
|
|
57006
|
-
|
|
57440
|
+
resolve10();
|
|
57007
57441
|
} catch (err) {
|
|
57008
57442
|
reject(err);
|
|
57009
57443
|
}
|
|
@@ -57018,7 +57452,7 @@ var init_metrics3 = __esm({
|
|
|
57018
57452
|
}
|
|
57019
57453
|
/** If the file is over the rotation threshold, rotate it. */
|
|
57020
57454
|
maybeRotate() {
|
|
57021
|
-
if (!
|
|
57455
|
+
if (!existsSync35(this.file)) return;
|
|
57022
57456
|
try {
|
|
57023
57457
|
const stat8 = statSync4(this.file);
|
|
57024
57458
|
if (stat8.size >= METRICS_ROTATE_BYTES) {
|
|
@@ -58300,7 +58734,7 @@ var init_sqliteCodec = __esm({
|
|
|
58300
58734
|
});
|
|
58301
58735
|
|
|
58302
58736
|
// src/cli/memory/sqliteRpc.ts
|
|
58303
|
-
import { existsSync as
|
|
58737
|
+
import { existsSync as existsSync36 } from "node:fs";
|
|
58304
58738
|
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
58305
58739
|
import * as path69 from "node:path";
|
|
58306
58740
|
import { Worker } from "node:worker_threads";
|
|
@@ -58313,7 +58747,7 @@ function isBusy(error51) {
|
|
|
58313
58747
|
function resolveWorkerUrl() {
|
|
58314
58748
|
const here = path69.dirname(fileURLToPath2(import.meta.url));
|
|
58315
58749
|
const direct = path69.join(here, "sqliteWorker.mjs");
|
|
58316
|
-
if (
|
|
58750
|
+
if (existsSync36(direct)) return pathToFileURL2(direct);
|
|
58317
58751
|
return pathToFileURL2(path69.join(here, "memory", "sqliteWorker.mjs"));
|
|
58318
58752
|
}
|
|
58319
58753
|
var SqliteWorkerRpc;
|
|
@@ -58388,8 +58822,8 @@ var init_sqliteRpc = __esm({
|
|
|
58388
58822
|
const worker = this.worker;
|
|
58389
58823
|
if (!worker) return Promise.reject(new Error("SQLite worker is not open."));
|
|
58390
58824
|
const id3 = this.nextId++;
|
|
58391
|
-
return new Promise((
|
|
58392
|
-
this.pending.set(id3, { resolve:
|
|
58825
|
+
return new Promise((resolve10, reject) => {
|
|
58826
|
+
this.pending.set(id3, { resolve: resolve10, reject });
|
|
58393
58827
|
worker.postMessage({ id: id3, operation, args });
|
|
58394
58828
|
});
|
|
58395
58829
|
}
|
|
@@ -58400,7 +58834,7 @@ var init_sqliteRpc = __esm({
|
|
|
58400
58834
|
return await this.request(operation, args);
|
|
58401
58835
|
} catch (error51) {
|
|
58402
58836
|
if (!isBusy(error51) || attempt >= 3) throw error51;
|
|
58403
|
-
await new Promise((
|
|
58837
|
+
await new Promise((resolve10) => setTimeout(resolve10, 25 * 2 ** attempt));
|
|
58404
58838
|
attempt += 1;
|
|
58405
58839
|
}
|
|
58406
58840
|
}
|
|
@@ -60024,8 +60458,8 @@ __export(conversationContext_exports, {
|
|
|
60024
60458
|
setHistory: () => setHistory,
|
|
60025
60459
|
setLastClarification: () => setLastClarification
|
|
60026
60460
|
});
|
|
60027
|
-
import { existsSync as
|
|
60028
|
-
import { join as
|
|
60461
|
+
import { existsSync as existsSync37 } from "node:fs";
|
|
60462
|
+
import { join as join28 } from "node:path";
|
|
60029
60463
|
function getHistory() {
|
|
60030
60464
|
return history;
|
|
60031
60465
|
}
|
|
@@ -60034,7 +60468,7 @@ function setHistory(messages) {
|
|
|
60034
60468
|
history = projected === messages ? [...messages] : projected;
|
|
60035
60469
|
}
|
|
60036
60470
|
function compactInPlace(cwd = process.cwd()) {
|
|
60037
|
-
const durableStatePresent =
|
|
60471
|
+
const durableStatePresent = existsSync37(join28(cwd, ".zelari", "state", "HEAD.json"));
|
|
60038
60472
|
history = applySessionSurface(compactHistory(history, { durableStatePresent }));
|
|
60039
60473
|
}
|
|
60040
60474
|
function appendMessages(msgs) {
|
|
@@ -60416,7 +60850,7 @@ var init_mode = __esm({
|
|
|
60416
60850
|
});
|
|
60417
60851
|
|
|
60418
60852
|
// src/cli/headless.ts
|
|
60419
|
-
import { readFileSync as
|
|
60853
|
+
import { readFileSync as readFileSync25 } from "node:fs";
|
|
60420
60854
|
import path73 from "node:path";
|
|
60421
60855
|
function resolveHeadlessCwd(opts) {
|
|
60422
60856
|
const raw = typeof opts.cwd === "string" ? opts.cwd.trim() : "";
|
|
@@ -60479,7 +60913,7 @@ function parseHeadlessFlags(argv) {
|
|
|
60479
60913
|
const next = argv[i + 1];
|
|
60480
60914
|
if (next) {
|
|
60481
60915
|
try {
|
|
60482
|
-
const fromFile =
|
|
60916
|
+
const fromFile = readFileSync25(next, "utf-8");
|
|
60483
60917
|
if (fromFile.trim()) task = fromFile;
|
|
60484
60918
|
} catch {
|
|
60485
60919
|
}
|
|
@@ -60528,7 +60962,7 @@ function parseHeadlessFlags(argv) {
|
|
|
60528
60962
|
let raw = null;
|
|
60529
60963
|
if (arg === "--history-file") {
|
|
60530
60964
|
try {
|
|
60531
|
-
raw =
|
|
60965
|
+
raw = readFileSync25(next, "utf-8");
|
|
60532
60966
|
} catch {
|
|
60533
60967
|
raw = null;
|
|
60534
60968
|
}
|
|
@@ -60630,7 +61064,7 @@ function parseHeadlessFlags(argv) {
|
|
|
60630
61064
|
const next = argv[i + 1];
|
|
60631
61065
|
if (next) {
|
|
60632
61066
|
try {
|
|
60633
|
-
const fromFile =
|
|
61067
|
+
const fromFile = readFileSync25(next, "utf-8");
|
|
60634
61068
|
if (fromFile.trim()) krakenGraph = fromFile;
|
|
60635
61069
|
} catch {
|
|
60636
61070
|
}
|
|
@@ -61319,13 +61753,13 @@ __export(claudeProvider_exports, {
|
|
|
61319
61753
|
});
|
|
61320
61754
|
import { spawn as spawn13 } from "node:child_process";
|
|
61321
61755
|
function waitForExit(child, timeoutMs2 = 2e3) {
|
|
61322
|
-
return new Promise((
|
|
61323
|
-
if (child.exitCode != null) return
|
|
61324
|
-
const timer = setTimeout(() =>
|
|
61756
|
+
return new Promise((resolve10) => {
|
|
61757
|
+
if (child.exitCode != null) return resolve10(child.exitCode);
|
|
61758
|
+
const timer = setTimeout(() => resolve10(child.exitCode ?? null), timeoutMs2);
|
|
61325
61759
|
timer.unref?.();
|
|
61326
61760
|
child.once("exit", (code) => {
|
|
61327
61761
|
clearTimeout(timer);
|
|
61328
|
-
|
|
61762
|
+
resolve10(code ?? null);
|
|
61329
61763
|
});
|
|
61330
61764
|
});
|
|
61331
61765
|
}
|
|
@@ -61528,13 +61962,13 @@ var planDetect_exports = {};
|
|
|
61528
61962
|
__export(planDetect_exports, {
|
|
61529
61963
|
hasWorkspacePlan: () => hasWorkspacePlan
|
|
61530
61964
|
});
|
|
61531
|
-
import { existsSync as
|
|
61532
|
-
import { join as
|
|
61965
|
+
import { existsSync as existsSync38, readFileSync as readFileSync26 } from "node:fs";
|
|
61966
|
+
import { join as join29 } from "node:path";
|
|
61533
61967
|
function hasWorkspacePlan(projectRoot = process.cwd()) {
|
|
61534
|
-
const planPath =
|
|
61535
|
-
if (!
|
|
61968
|
+
const planPath = join29(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
61969
|
+
if (!existsSync38(planPath)) return false;
|
|
61536
61970
|
try {
|
|
61537
|
-
const parsed = JSON.parse(
|
|
61971
|
+
const parsed = JSON.parse(readFileSync26(planPath, "utf8"));
|
|
61538
61972
|
return Array.isArray(parsed.phases) && parsed.phases.length > 0;
|
|
61539
61973
|
} catch {
|
|
61540
61974
|
return false;
|
|
@@ -61548,14 +61982,14 @@ var init_planDetect = __esm({
|
|
|
61548
61982
|
});
|
|
61549
61983
|
|
|
61550
61984
|
// src/cli/workspace/projectInstructions.ts
|
|
61551
|
-
import { existsSync as
|
|
61552
|
-
import { join as
|
|
61985
|
+
import { existsSync as existsSync39, readFileSync as readFileSync27 } from "node:fs";
|
|
61986
|
+
import { join as join30 } from "node:path";
|
|
61553
61987
|
function loadProjectInstructions(projectRoot = process.cwd(), maxChars = MAX_CHARS) {
|
|
61554
61988
|
for (const name of CANDIDATES) {
|
|
61555
|
-
const full =
|
|
61556
|
-
if (!
|
|
61989
|
+
const full = join30(projectRoot, name);
|
|
61990
|
+
if (!existsSync39(full)) continue;
|
|
61557
61991
|
try {
|
|
61558
|
-
let raw =
|
|
61992
|
+
let raw = readFileSync27(full, "utf8");
|
|
61559
61993
|
raw = raw.replace(/\r\n/g, "\n").trim();
|
|
61560
61994
|
if (!raw) continue;
|
|
61561
61995
|
if (raw.length <= maxChars) {
|
|
@@ -61599,8 +62033,8 @@ __export(workspaceSummary_exports, {
|
|
|
61599
62033
|
buildWorkspaceSummary: () => buildWorkspaceSummary,
|
|
61600
62034
|
buildZelariReadHint: () => buildZelariReadHint
|
|
61601
62035
|
});
|
|
61602
|
-
import { existsSync as
|
|
61603
|
-
import { join as
|
|
62036
|
+
import { existsSync as existsSync40, readFileSync as readFileSync28, readdirSync as readdirSync8, statSync as statSync5 } from "node:fs";
|
|
62037
|
+
import { join as join31, relative as relative2 } from "node:path";
|
|
61604
62038
|
function buildWorkspaceSummary(projectRoot = process.cwd(), options = {}) {
|
|
61605
62039
|
const { maxEntries = 30, maxChars = 3500, maxDeps = 24, maxScripts = 16 } = options;
|
|
61606
62040
|
const name = safeProjectName(projectRoot);
|
|
@@ -61633,11 +62067,11 @@ function formatTaskLine(t) {
|
|
|
61633
62067
|
}
|
|
61634
62068
|
function buildPlanSummary(projectRoot = process.cwd(), options) {
|
|
61635
62069
|
const zelariRoot = resolveWorkspaceRoot(projectRoot);
|
|
61636
|
-
const planPath =
|
|
61637
|
-
if (!
|
|
62070
|
+
const planPath = join31(zelariRoot, "plan.json");
|
|
62071
|
+
if (!existsSync40(planPath)) return null;
|
|
61638
62072
|
let plan;
|
|
61639
62073
|
try {
|
|
61640
|
-
plan = JSON.parse(
|
|
62074
|
+
plan = JSON.parse(readFileSync28(planPath, "utf8"));
|
|
61641
62075
|
} catch {
|
|
61642
62076
|
return null;
|
|
61643
62077
|
}
|
|
@@ -61776,8 +62210,8 @@ function pickNextTask(open2) {
|
|
|
61776
62210
|
)[0];
|
|
61777
62211
|
}
|
|
61778
62212
|
function buildZelariReadHint(projectRoot = process.cwd()) {
|
|
61779
|
-
const planPath =
|
|
61780
|
-
if (!
|
|
62213
|
+
const planPath = join31(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
62214
|
+
if (!existsSync40(planPath)) return "";
|
|
61781
62215
|
return [
|
|
61782
62216
|
"# Council workspace detected (.zelari/) \u2014 DRAFT vault",
|
|
61783
62217
|
"`.zelari/plan.json` and `.zelari/docs/` hold **design hypotheses**, not verified product state.",
|
|
@@ -61792,10 +62226,10 @@ function safeProjectName(root) {
|
|
|
61792
62226
|
}
|
|
61793
62227
|
}
|
|
61794
62228
|
function readPackageJson2(projectRoot) {
|
|
61795
|
-
const p3 =
|
|
61796
|
-
if (!
|
|
62229
|
+
const p3 = join31(projectRoot, "package.json");
|
|
62230
|
+
if (!existsSync40(p3)) return null;
|
|
61797
62231
|
try {
|
|
61798
|
-
return JSON.parse(
|
|
62232
|
+
return JSON.parse(readFileSync28(p3, "utf8"));
|
|
61799
62233
|
} catch {
|
|
61800
62234
|
return null;
|
|
61801
62235
|
}
|
|
@@ -61836,7 +62270,7 @@ function readBuildScripts(projectRoot, maxScripts = 16) {
|
|
|
61836
62270
|
function listShallow(projectRoot, maxEntries) {
|
|
61837
62271
|
const out = [];
|
|
61838
62272
|
try {
|
|
61839
|
-
const top =
|
|
62273
|
+
const top = readdirSync8(projectRoot, { withFileTypes: true }).filter(
|
|
61840
62274
|
(e) => !e.name.startsWith(".") && e.name !== "node_modules" && e.name !== "dist"
|
|
61841
62275
|
).sort((a, b) => a.name.localeCompare(b.name));
|
|
61842
62276
|
let count = 0;
|
|
@@ -61845,11 +62279,11 @@ function listShallow(projectRoot, maxEntries) {
|
|
|
61845
62279
|
out.push(`\u2026 (+${top.length - count} more)`);
|
|
61846
62280
|
break;
|
|
61847
62281
|
}
|
|
61848
|
-
const rel2 = relative2(projectRoot,
|
|
62282
|
+
const rel2 = relative2(projectRoot, join31(projectRoot, entry.name));
|
|
61849
62283
|
if (entry.isDirectory()) {
|
|
61850
62284
|
let inner = "";
|
|
61851
62285
|
try {
|
|
61852
|
-
const sub =
|
|
62286
|
+
const sub = readdirSync8(join31(projectRoot, entry.name), {
|
|
61853
62287
|
withFileTypes: true
|
|
61854
62288
|
}).filter((e) => !e.name.startsWith(".")).slice(0, 4).map((e) => e.name);
|
|
61855
62289
|
if (sub.length > 0)
|
|
@@ -61897,12 +62331,12 @@ var init_workspaceSummary = __esm({
|
|
|
61897
62331
|
});
|
|
61898
62332
|
|
|
61899
62333
|
// src/cli/workspace/buildLessonsSummary.ts
|
|
61900
|
-
import { existsSync as
|
|
61901
|
-
import { join as
|
|
62334
|
+
import { existsSync as existsSync41 } from "node:fs";
|
|
62335
|
+
import { join as join32 } from "node:path";
|
|
61902
62336
|
function buildLessonsSummary(projectRoot = process.cwd(), taskText) {
|
|
61903
62337
|
if (process.env["ZELARI_LESSONS"] === "0") return null;
|
|
61904
62338
|
const zelariRoot = resolveWorkspaceRoot(projectRoot);
|
|
61905
|
-
if (!
|
|
62339
|
+
if (!existsSync41(join32(zelariRoot, "lessons.jsonl"))) return null;
|
|
61906
62340
|
const lessons = recallLessons(zelariRoot, {
|
|
61907
62341
|
maxLessons: 5,
|
|
61908
62342
|
maxBytes: 2048,
|
|
@@ -61923,8 +62357,8 @@ var composeContext_exports = {};
|
|
|
61923
62357
|
__export(composeContext_exports, {
|
|
61924
62358
|
composeProjectContext: () => composeProjectContext
|
|
61925
62359
|
});
|
|
61926
|
-
import { existsSync as
|
|
61927
|
-
import { join as
|
|
62360
|
+
import { existsSync as existsSync42, readdirSync as readdirSync9, readFileSync as readFileSync29 } from "node:fs";
|
|
62361
|
+
import { join as join33 } from "node:path";
|
|
61928
62362
|
function cap2(text, max, label) {
|
|
61929
62363
|
if (!text || text.length <= max) return { text: text || "", truncated: false };
|
|
61930
62364
|
return {
|
|
@@ -61936,19 +62370,19 @@ function cap2(text, max, label) {
|
|
|
61936
62370
|
}
|
|
61937
62371
|
function buildDesignIndex(projectRoot, maxChars) {
|
|
61938
62372
|
const root = resolveWorkspaceRoot(projectRoot);
|
|
61939
|
-
if (!
|
|
62373
|
+
if (!existsSync42(root)) return "";
|
|
61940
62374
|
const lines = [
|
|
61941
62375
|
"# Design vault index (.zelari/) \u2014 HYPOTHESES only",
|
|
61942
62376
|
"Full design docs are NOT product source of truth. Open with list_files / read_file / searchDocuments if needed."
|
|
61943
62377
|
];
|
|
61944
|
-
const docsDir =
|
|
61945
|
-
if (
|
|
62378
|
+
const docsDir = join33(root, "docs");
|
|
62379
|
+
if (existsSync42(docsDir)) {
|
|
61946
62380
|
try {
|
|
61947
|
-
const docs =
|
|
62381
|
+
const docs = readdirSync9(docsDir).filter((n) => n.endsWith(".md")).slice(0, 12);
|
|
61948
62382
|
if (docs.length > 0) {
|
|
61949
62383
|
lines.push("", "## docs/ (titles only)");
|
|
61950
62384
|
for (const d of docs) lines.push(`- .zelari/docs/${d}`);
|
|
61951
|
-
if (
|
|
62385
|
+
if (readdirSync9(docsDir).filter((n) => n.endsWith(".md")).length > 12) {
|
|
61952
62386
|
lines.push("- \u2026 (more under .zelari/docs/)");
|
|
61953
62387
|
}
|
|
61954
62388
|
}
|
|
@@ -61956,14 +62390,14 @@ function buildDesignIndex(projectRoot, maxChars) {
|
|
|
61956
62390
|
}
|
|
61957
62391
|
}
|
|
61958
62392
|
for (const name of ["risks.md", "plan.json", "nfr-spec.json"]) {
|
|
61959
|
-
if (
|
|
62393
|
+
if (existsSync42(join33(root, name))) {
|
|
61960
62394
|
lines.push(`- .zelari/${name} present`);
|
|
61961
62395
|
}
|
|
61962
62396
|
}
|
|
61963
|
-
const decisionsDir =
|
|
61964
|
-
if (
|
|
62397
|
+
const decisionsDir = join33(root, "decisions");
|
|
62398
|
+
if (existsSync42(decisionsDir)) {
|
|
61965
62399
|
try {
|
|
61966
|
-
const n =
|
|
62400
|
+
const n = readdirSync9(decisionsDir).filter((f) => f.endsWith(".md")).length;
|
|
61967
62401
|
if (n > 0) lines.push(`- .zelari/decisions/ (${n} ADR file(s) \u2014 treat proposed as non-binding)`);
|
|
61968
62402
|
} catch {
|
|
61969
62403
|
}
|
|
@@ -62062,17 +62496,17 @@ function composeProjectContext(input) {
|
|
|
62062
62496
|
}
|
|
62063
62497
|
function readDurableHeadSync(projectRoot) {
|
|
62064
62498
|
try {
|
|
62065
|
-
const headPath =
|
|
62066
|
-
if (!
|
|
62067
|
-
const head = JSON.parse(
|
|
62499
|
+
const headPath = join33(projectRoot, ".zelari", "state", "HEAD.json");
|
|
62500
|
+
if (!existsSync42(headPath)) return "";
|
|
62501
|
+
const head = JSON.parse(readFileSync29(headPath, "utf8"));
|
|
62068
62502
|
if (!head?.id) return "";
|
|
62069
|
-
const metaPath =
|
|
62070
|
-
if (!
|
|
62071
|
-
const meta3 = JSON.parse(
|
|
62072
|
-
const discPath = meta3.artifactDir ?
|
|
62503
|
+
const metaPath = join33(projectRoot, ".zelari", "state", "commits", `${head.id}.json`);
|
|
62504
|
+
if (!existsSync42(metaPath)) return "";
|
|
62505
|
+
const meta3 = JSON.parse(readFileSync29(metaPath, "utf8"));
|
|
62506
|
+
const discPath = meta3.artifactDir ? join33(projectRoot, ".zelari", "state", meta3.artifactDir, "discoveries.json") : join33(projectRoot, ".zelari", "state", "artifacts", head.id, "discoveries.json");
|
|
62073
62507
|
let discoveries = [];
|
|
62074
|
-
if (
|
|
62075
|
-
discoveries = JSON.parse(
|
|
62508
|
+
if (existsSync42(discPath)) {
|
|
62509
|
+
discoveries = JSON.parse(readFileSync29(discPath, "utf8"));
|
|
62076
62510
|
}
|
|
62077
62511
|
const reusable = discoveries.filter((d) => d.reusable !== false);
|
|
62078
62512
|
const lines = [
|
|
@@ -62146,14 +62580,14 @@ __export(stubs_exports, {
|
|
|
62146
62580
|
resolveWorkspaceRoot: () => resolveWorkspaceRoot
|
|
62147
62581
|
});
|
|
62148
62582
|
import {
|
|
62149
|
-
existsSync as
|
|
62150
|
-
readdirSync as
|
|
62151
|
-
writeFileSync as
|
|
62152
|
-
readFileSync as
|
|
62153
|
-
mkdirSync as
|
|
62583
|
+
existsSync as existsSync43,
|
|
62584
|
+
readdirSync as readdirSync10,
|
|
62585
|
+
writeFileSync as writeFileSync19,
|
|
62586
|
+
readFileSync as readFileSync30,
|
|
62587
|
+
mkdirSync as mkdirSync17,
|
|
62154
62588
|
renameSync as renameSync5
|
|
62155
62589
|
} from "node:fs";
|
|
62156
|
-
import { join as
|
|
62590
|
+
import { join as join34, basename as basename4, dirname as dirname10, relative as relative3 } from "node:path";
|
|
62157
62591
|
function createWorkspaceContext(projectRoot = process.cwd()) {
|
|
62158
62592
|
const rootDir = resolveWorkspaceRoot(projectRoot);
|
|
62159
62593
|
return {
|
|
@@ -62163,14 +62597,14 @@ function createWorkspaceContext(projectRoot = process.cwd()) {
|
|
|
62163
62597
|
};
|
|
62164
62598
|
}
|
|
62165
62599
|
function planJsonPath(ctx) {
|
|
62166
|
-
return
|
|
62600
|
+
return join34(ctx.rootDir, "plan.json");
|
|
62167
62601
|
}
|
|
62168
62602
|
function readPlan(ctx) {
|
|
62169
62603
|
const jsonPath = planJsonPath(ctx);
|
|
62170
|
-
if (
|
|
62604
|
+
if (existsSync43(jsonPath)) {
|
|
62171
62605
|
try {
|
|
62172
62606
|
const parsed = JSON.parse(
|
|
62173
|
-
|
|
62607
|
+
readFileSync30(jsonPath, "utf8")
|
|
62174
62608
|
);
|
|
62175
62609
|
const { phases, tasks, milestones, ...root } = parsed;
|
|
62176
62610
|
return {
|
|
@@ -62182,8 +62616,8 @@ function readPlan(ctx) {
|
|
|
62182
62616
|
} catch {
|
|
62183
62617
|
}
|
|
62184
62618
|
}
|
|
62185
|
-
const
|
|
62186
|
-
const doc = ctx.storage.readIfExists(
|
|
62619
|
+
const path104 = workspaceFile(ctx.rootDir, "plan");
|
|
62620
|
+
const doc = ctx.storage.readIfExists(path104);
|
|
62187
62621
|
if (!doc) return { phases: [], tasks: [], milestones: [] };
|
|
62188
62622
|
const meta3 = doc.meta;
|
|
62189
62623
|
return {
|
|
@@ -62194,9 +62628,9 @@ function readPlan(ctx) {
|
|
|
62194
62628
|
}
|
|
62195
62629
|
function writePlan(ctx, summary) {
|
|
62196
62630
|
const jsonPath = planJsonPath(ctx);
|
|
62197
|
-
|
|
62631
|
+
mkdirSync17(dirname10(jsonPath), { recursive: true });
|
|
62198
62632
|
const tmp = jsonPath + ".tmp-" + process.pid;
|
|
62199
|
-
|
|
62633
|
+
writeFileSync19(
|
|
62200
62634
|
tmp,
|
|
62201
62635
|
JSON.stringify(
|
|
62202
62636
|
{
|
|
@@ -62276,9 +62710,9 @@ function renderPlanBody(summary) {
|
|
|
62276
62710
|
return lines.join("\n");
|
|
62277
62711
|
}
|
|
62278
62712
|
function nextAdrId(ctx) {
|
|
62279
|
-
const decisionsDir =
|
|
62280
|
-
if (!
|
|
62281
|
-
const existing =
|
|
62713
|
+
const decisionsDir = join34(ctx.rootDir, "decisions");
|
|
62714
|
+
if (!existsSync43(decisionsDir)) return "001";
|
|
62715
|
+
const existing = readdirSync10(decisionsDir).filter((f) => f.endsWith(".md")).map((f) => f.match(/^(\d+)-/)).filter((m) => !!m).map((m) => parseInt(m[1], 10));
|
|
62282
62716
|
const max = existing.length === 0 ? 0 : Math.max(...existing);
|
|
62283
62717
|
return String(max + 1).padStart(3, "0");
|
|
62284
62718
|
}
|
|
@@ -62322,7 +62756,7 @@ function addTaskRecord(ctx, summary, phaseId, t, options) {
|
|
|
62322
62756
|
// plan.json record (they already live in tags + the artifact body md).
|
|
62323
62757
|
files: t.fileRefs
|
|
62324
62758
|
});
|
|
62325
|
-
const taskPath =
|
|
62759
|
+
const taskPath = join34(ctx.rootDir, "plan-tasks", `${id3}.md`);
|
|
62326
62760
|
const meta3 = {
|
|
62327
62761
|
kind: "task",
|
|
62328
62762
|
id: id3,
|
|
@@ -62364,7 +62798,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
62364
62798
|
dueDate: input.dueDate,
|
|
62365
62799
|
targetVersion: version2
|
|
62366
62800
|
});
|
|
62367
|
-
const
|
|
62801
|
+
const path104 = join34(ctx.rootDir, "milestones", `${id3}.md`);
|
|
62368
62802
|
const meta3 = {
|
|
62369
62803
|
kind: "milestone",
|
|
62370
62804
|
id: id3,
|
|
@@ -62381,7 +62815,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
62381
62815
|
`Target version: ${version2}`,
|
|
62382
62816
|
""
|
|
62383
62817
|
].join("\n");
|
|
62384
|
-
ctx.storage.write(
|
|
62818
|
+
ctx.storage.write(path104, meta3, body);
|
|
62385
62819
|
return { id: id3, created: true };
|
|
62386
62820
|
}
|
|
62387
62821
|
function readPlanSummary(ctx) {
|
|
@@ -62585,7 +63019,7 @@ function addIdeaStub(ctx) {
|
|
|
62585
63019
|
const tags = args["tags"] ?? [];
|
|
62586
63020
|
const category = args["category"] ?? "General";
|
|
62587
63021
|
const id3 = `${nextAdrId(ctx)}-${slugify3(title)}`;
|
|
62588
|
-
const
|
|
63022
|
+
const path104 = workspaceArtifact(ctx.rootDir, "decisions", id3);
|
|
62589
63023
|
const meta3 = {
|
|
62590
63024
|
kind: "adr",
|
|
62591
63025
|
status: "proposed",
|
|
@@ -62611,7 +63045,7 @@ function addIdeaStub(ctx) {
|
|
|
62611
63045
|
...consequences.map((c) => `- ${c}`),
|
|
62612
63046
|
""
|
|
62613
63047
|
].join("\n");
|
|
62614
|
-
ctx.storage.write(
|
|
63048
|
+
ctx.storage.write(path104, meta3, body);
|
|
62615
63049
|
return `ADR ${id3} created: "${title}". Status: proposed. Promote to accepted via /update ADR or manual edit.`;
|
|
62616
63050
|
});
|
|
62617
63051
|
}
|
|
@@ -62662,8 +63096,8 @@ function createNfrSpecStub(ctx) {
|
|
|
62662
63096
|
},
|
|
62663
63097
|
planFeatureKeywords: Array.isArray(args["planFeatureKeywords"]) ? args["planFeatureKeywords"] : void 0
|
|
62664
63098
|
};
|
|
62665
|
-
const outPath =
|
|
62666
|
-
|
|
63099
|
+
const outPath = join34(ctx.rootDir, "nfr-spec.json");
|
|
63100
|
+
writeFileSync19(outPath, JSON.stringify(spec, null, 2), "utf8");
|
|
62667
63101
|
return `NFR spec written to nfr-spec.json (${targets.length} target(s)).`;
|
|
62668
63102
|
});
|
|
62669
63103
|
}
|
|
@@ -62693,14 +63127,14 @@ function createDocumentStub(ctx) {
|
|
|
62693
63127
|
ctx.storage.write(risksPath, riskMeta, content);
|
|
62694
63128
|
return `Document "${title}" created at risks.md (workspace root).`;
|
|
62695
63129
|
}
|
|
62696
|
-
const
|
|
63130
|
+
const path104 = workspaceArtifact(ctx.rootDir, "docs", slug);
|
|
62697
63131
|
const meta3 = {
|
|
62698
63132
|
kind: "doc",
|
|
62699
63133
|
id: slug,
|
|
62700
63134
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
62701
63135
|
tags
|
|
62702
63136
|
};
|
|
62703
|
-
ctx.storage.write(
|
|
63137
|
+
ctx.storage.write(path104, meta3, content);
|
|
62704
63138
|
return `Document "${title}" created at docs/${slug}.md.`;
|
|
62705
63139
|
});
|
|
62706
63140
|
}
|
|
@@ -62726,18 +63160,18 @@ function searchDocumentsStub(ctx) {
|
|
|
62726
63160
|
(w) => w.length >= 3 && w !== "or" && w !== "and" && w !== "the"
|
|
62727
63161
|
);
|
|
62728
63162
|
const files = [
|
|
62729
|
-
...ctx.storage.listMarkdown(
|
|
62730
|
-
...ctx.storage.listMarkdown(
|
|
62731
|
-
...ctx.storage.listMarkdown(
|
|
62732
|
-
...ctx.storage.listMarkdown(
|
|
62733
|
-
...ctx.storage.listMarkdown(
|
|
63163
|
+
...ctx.storage.listMarkdown(join34(ctx.rootDir, "decisions")),
|
|
63164
|
+
...ctx.storage.listMarkdown(join34(ctx.rootDir, "docs")),
|
|
63165
|
+
...ctx.storage.listMarkdown(join34(ctx.rootDir, "reviews")),
|
|
63166
|
+
...ctx.storage.listMarkdown(join34(ctx.rootDir, "plan-tasks")),
|
|
63167
|
+
...ctx.storage.listMarkdown(join34(ctx.rootDir, "milestones")),
|
|
62734
63168
|
workspaceFile(ctx.rootDir, "plan"),
|
|
62735
63169
|
workspaceFile(ctx.rootDir, "risks")
|
|
62736
63170
|
];
|
|
62737
63171
|
const results = [];
|
|
62738
63172
|
for (const file2 of files) {
|
|
62739
|
-
if (!
|
|
62740
|
-
const raw =
|
|
63173
|
+
if (!existsSync43(file2)) continue;
|
|
63174
|
+
const raw = readFileSync30(file2, "utf8");
|
|
62741
63175
|
const content = raw.toLowerCase();
|
|
62742
63176
|
let idx = -1;
|
|
62743
63177
|
let matchLen = 0;
|
|
@@ -62788,9 +63222,9 @@ function linkDocumentsStub(ctx) {
|
|
|
62788
63222
|
const toId = args["toId"] ?? args["targetId"] ?? args["targetPathOrTitle"];
|
|
62789
63223
|
if (!fromId || !toId) return "linkDocuments requires fromId and toId.";
|
|
62790
63224
|
const allFiles = [
|
|
62791
|
-
...ctx.storage.listMarkdown(
|
|
62792
|
-
...ctx.storage.listMarkdown(
|
|
62793
|
-
...ctx.storage.listMarkdown(
|
|
63225
|
+
...ctx.storage.listMarkdown(join34(ctx.rootDir, "decisions")),
|
|
63226
|
+
...ctx.storage.listMarkdown(join34(ctx.rootDir, "docs")),
|
|
63227
|
+
...ctx.storage.listMarkdown(join34(ctx.rootDir, "reviews"))
|
|
62794
63228
|
];
|
|
62795
63229
|
const source2 = allFiles.find((f) => {
|
|
62796
63230
|
try {
|
|
@@ -62821,9 +63255,9 @@ function getDocumentBacklinksStub(ctx) {
|
|
|
62821
63255
|
const targetId = args["targetId"] ?? args["id"];
|
|
62822
63256
|
if (!targetId) return "getDocumentBacklinks requires targetId.";
|
|
62823
63257
|
const allFiles = [
|
|
62824
|
-
...ctx.storage.listMarkdown(
|
|
62825
|
-
...ctx.storage.listMarkdown(
|
|
62826
|
-
...ctx.storage.listMarkdown(
|
|
63258
|
+
...ctx.storage.listMarkdown(join34(ctx.rootDir, "decisions")),
|
|
63259
|
+
...ctx.storage.listMarkdown(join34(ctx.rootDir, "docs")),
|
|
63260
|
+
...ctx.storage.listMarkdown(join34(ctx.rootDir, "reviews"))
|
|
62827
63261
|
];
|
|
62828
63262
|
const backlinks = [];
|
|
62829
63263
|
for (const file2 of allFiles) {
|
|
@@ -63067,9 +63501,10 @@ var init_mcpClient = __esm({
|
|
|
63067
63501
|
MAX_LIST_PAGES = 50;
|
|
63068
63502
|
MCP_PROTOCOL_VERSION = "2025-03-26";
|
|
63069
63503
|
McpClient = class {
|
|
63070
|
-
constructor(serverName, config2) {
|
|
63504
|
+
constructor(serverName, config2, spawnCwd) {
|
|
63071
63505
|
this.serverName = serverName;
|
|
63072
63506
|
this.config = config2;
|
|
63507
|
+
this.spawnCwd = spawnCwd;
|
|
63073
63508
|
this.defaultTimeoutMs = config2.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
63074
63509
|
this.serial = config2.serial ?? this.transportKind() === "http";
|
|
63075
63510
|
}
|
|
@@ -63116,7 +63551,11 @@ var init_mcpClient = __esm({
|
|
|
63116
63551
|
const spawnOpts = {
|
|
63117
63552
|
stdio: ["pipe", "pipe", "pipe"],
|
|
63118
63553
|
env: { ...process.env, ...this.config.env ?? {} },
|
|
63119
|
-
windowsHide: true
|
|
63554
|
+
windowsHide: true,
|
|
63555
|
+
// MCP servers are project-scoped: their cwd is the session project
|
|
63556
|
+
// root, not the CLI process cwd (the Desktop launches the CLI from its
|
|
63557
|
+
// install dir, so "." entries would jail themselves to the app folder).
|
|
63558
|
+
cwd: this.spawnCwd
|
|
63120
63559
|
};
|
|
63121
63560
|
const child = process.platform === "win32" ? spawn14(buildCmdLine(command, this.config.args ?? []), {
|
|
63122
63561
|
...spawnOpts,
|
|
@@ -63235,7 +63674,7 @@ var init_mcpClient = __esm({
|
|
|
63235
63674
|
if (!transport && !child)
|
|
63236
63675
|
return Promise.reject(new Error(`[mcp:${this.serverName}] not started`));
|
|
63237
63676
|
const id3 = this.nextId++;
|
|
63238
|
-
return new Promise((
|
|
63677
|
+
return new Promise((resolve10, reject) => {
|
|
63239
63678
|
const timer = setTimeout(() => {
|
|
63240
63679
|
this.pending.delete(id3);
|
|
63241
63680
|
reject(
|
|
@@ -63244,7 +63683,7 @@ var init_mcpClient = __esm({
|
|
|
63244
63683
|
)
|
|
63245
63684
|
);
|
|
63246
63685
|
}, timeoutMs2);
|
|
63247
|
-
this.pending.set(id3, { resolve:
|
|
63686
|
+
this.pending.set(id3, { resolve: resolve10, reject, timer });
|
|
63248
63687
|
if (transport) {
|
|
63249
63688
|
void transport.send({ id: id3, method, params }, timeoutMs2);
|
|
63250
63689
|
} else {
|
|
@@ -63313,22 +63752,22 @@ var init_mcpClient = __esm({
|
|
|
63313
63752
|
|
|
63314
63753
|
// src/cli/mcp/mcpConfigIo.ts
|
|
63315
63754
|
import {
|
|
63316
|
-
existsSync as
|
|
63317
|
-
mkdirSync as
|
|
63318
|
-
readFileSync as
|
|
63319
|
-
writeFileSync as
|
|
63755
|
+
existsSync as existsSync44,
|
|
63756
|
+
mkdirSync as mkdirSync18,
|
|
63757
|
+
readFileSync as readFileSync31,
|
|
63758
|
+
writeFileSync as writeFileSync20
|
|
63320
63759
|
} from "node:fs";
|
|
63321
|
-
import { dirname as
|
|
63760
|
+
import { dirname as dirname11, join as join35 } from "node:path";
|
|
63322
63761
|
function getUserMcpPath() {
|
|
63323
|
-
return
|
|
63762
|
+
return join35(zelariHome(), "mcp.json");
|
|
63324
63763
|
}
|
|
63325
63764
|
function getProjectMcpPath(projectRoot) {
|
|
63326
|
-
return
|
|
63765
|
+
return join35(projectRoot, ".zelari", "mcp.json");
|
|
63327
63766
|
}
|
|
63328
|
-
function readFile10(
|
|
63329
|
-
if (!
|
|
63767
|
+
function readFile10(path104) {
|
|
63768
|
+
if (!existsSync44(path104)) return {};
|
|
63330
63769
|
try {
|
|
63331
|
-
const parsed = JSON.parse(
|
|
63770
|
+
const parsed = JSON.parse(readFileSync31(path104, "utf8"));
|
|
63332
63771
|
const out = {};
|
|
63333
63772
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
63334
63773
|
const hasCommand = !!cfg && typeof cfg.command === "string" && !!cfg.command.trim();
|
|
@@ -63350,10 +63789,10 @@ function readFile10(path103) {
|
|
|
63350
63789
|
return {};
|
|
63351
63790
|
}
|
|
63352
63791
|
}
|
|
63353
|
-
function writeFile4(
|
|
63354
|
-
|
|
63792
|
+
function writeFile4(path104, servers) {
|
|
63793
|
+
mkdirSync18(dirname11(path104), { recursive: true });
|
|
63355
63794
|
const body = { mcpServers: servers };
|
|
63356
|
-
|
|
63795
|
+
writeFileSync20(path104, `${JSON.stringify(body, null, 2)}
|
|
63357
63796
|
`, "utf8");
|
|
63358
63797
|
}
|
|
63359
63798
|
function listMcpServers(projectRoot) {
|
|
@@ -63375,6 +63814,46 @@ function listMcpServers(projectRoot) {
|
|
|
63375
63814
|
};
|
|
63376
63815
|
return { userPath, projectPath, servers, merged };
|
|
63377
63816
|
}
|
|
63817
|
+
function requireEnvKey(key) {
|
|
63818
|
+
if (!ENV_KEY_RE.test(key)) {
|
|
63819
|
+
throw new Error(
|
|
63820
|
+
`Invalid env key "${key}" \u2014 use letters, digits, _ (no leading digit)`
|
|
63821
|
+
);
|
|
63822
|
+
}
|
|
63823
|
+
return key;
|
|
63824
|
+
}
|
|
63825
|
+
function parseMcpEnvFlag(raw) {
|
|
63826
|
+
if (raw.length === 0) return void 0;
|
|
63827
|
+
const env = {};
|
|
63828
|
+
for (const value of raw) {
|
|
63829
|
+
const text = value.trim();
|
|
63830
|
+
if (text.startsWith("{") || text.startsWith("[")) {
|
|
63831
|
+
let parsed;
|
|
63832
|
+
try {
|
|
63833
|
+
parsed = JSON.parse(text);
|
|
63834
|
+
} catch {
|
|
63835
|
+
throw new Error(`--env is not valid JSON: ${text}`);
|
|
63836
|
+
}
|
|
63837
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
63838
|
+
throw new Error('--env JSON must be an object of "KEY": "VALUE" pairs');
|
|
63839
|
+
}
|
|
63840
|
+
for (const [key2, val] of Object.entries(parsed)) {
|
|
63841
|
+
if (typeof val !== "string") {
|
|
63842
|
+
throw new Error(`--env "${key2}" must map to a string value`);
|
|
63843
|
+
}
|
|
63844
|
+
env[requireEnvKey(key2)] = val;
|
|
63845
|
+
}
|
|
63846
|
+
continue;
|
|
63847
|
+
}
|
|
63848
|
+
const eq = text.indexOf("=");
|
|
63849
|
+
const key = eq > 0 ? text.slice(0, eq).trim() : "";
|
|
63850
|
+
if (!key) {
|
|
63851
|
+
throw new Error(`Invalid --env "${text}" \u2014 use KEY=VALUE or a JSON object`);
|
|
63852
|
+
}
|
|
63853
|
+
env[requireEnvKey(key)] = text.slice(eq + 1);
|
|
63854
|
+
}
|
|
63855
|
+
return env;
|
|
63856
|
+
}
|
|
63378
63857
|
function upsertMcpServer(opts) {
|
|
63379
63858
|
const name = opts.name.trim();
|
|
63380
63859
|
if (!name || !/^[a-zA-Z0-9_-]+$/.test(name)) {
|
|
@@ -63391,9 +63870,9 @@ function upsertMcpServer(opts) {
|
|
|
63391
63870
|
error: "either command (stdio) or url (http) is required"
|
|
63392
63871
|
};
|
|
63393
63872
|
}
|
|
63394
|
-
let
|
|
63873
|
+
let path104;
|
|
63395
63874
|
if (opts.scope === "user") {
|
|
63396
|
-
|
|
63875
|
+
path104 = getUserMcpPath();
|
|
63397
63876
|
} else {
|
|
63398
63877
|
const root = opts.projectRoot?.trim();
|
|
63399
63878
|
if (!root) {
|
|
@@ -63402,39 +63881,46 @@ function upsertMcpServer(opts) {
|
|
|
63402
63881
|
error: "projectRoot required for project scope (Open Folder first)"
|
|
63403
63882
|
};
|
|
63404
63883
|
}
|
|
63405
|
-
|
|
63884
|
+
path104 = getProjectMcpPath(root);
|
|
63406
63885
|
}
|
|
63407
|
-
const current = readFile10(
|
|
63886
|
+
const current = readFile10(path104);
|
|
63887
|
+
const previous = current[name];
|
|
63408
63888
|
current[name] = {
|
|
63409
63889
|
command: hasCommand ? opts.config.command.trim() : void 0,
|
|
63410
63890
|
args: opts.config.args,
|
|
63411
|
-
|
|
63891
|
+
// Back-compat: callers that only flip `enabled` (Desktop toggle) or that
|
|
63892
|
+
// have no env channel at all (`--set-mcp` without `--env`) must not wipe
|
|
63893
|
+
// env written by hand or by another tool. An explicit env always wins —
|
|
63894
|
+
// including `{}`, which clears it.
|
|
63895
|
+
env: opts.config.env ?? previous?.env,
|
|
63412
63896
|
type: hasUrl ? "http" : opts.config.type === "http" ? "http" : "stdio",
|
|
63413
63897
|
url: hasUrl ? opts.config.url.trim() : void 0,
|
|
63414
63898
|
timeoutMs: opts.config.timeoutMs,
|
|
63415
63899
|
serial: opts.config.serial,
|
|
63416
63900
|
enabled: opts.config.enabled !== false
|
|
63417
63901
|
};
|
|
63418
|
-
writeFile4(
|
|
63419
|
-
return { ok: true, path:
|
|
63902
|
+
writeFile4(path104, current);
|
|
63903
|
+
return { ok: true, path: path104 };
|
|
63420
63904
|
}
|
|
63421
63905
|
function removeMcpServer(opts) {
|
|
63422
|
-
const
|
|
63423
|
-
if (!
|
|
63906
|
+
const path104 = opts.scope === "user" ? getUserMcpPath() : opts.projectRoot ? getProjectMcpPath(opts.projectRoot) : null;
|
|
63907
|
+
if (!path104) {
|
|
63424
63908
|
return { ok: false, error: "projectRoot required for project scope" };
|
|
63425
63909
|
}
|
|
63426
|
-
const current = readFile10(
|
|
63910
|
+
const current = readFile10(path104);
|
|
63427
63911
|
if (!(opts.name in current)) {
|
|
63428
|
-
return { ok: false, error: `Server "${opts.name}" not found in ${
|
|
63912
|
+
return { ok: false, error: `Server "${opts.name}" not found in ${path104}` };
|
|
63429
63913
|
}
|
|
63430
63914
|
delete current[opts.name];
|
|
63431
|
-
writeFile4(
|
|
63432
|
-
return { ok: true, path:
|
|
63915
|
+
writeFile4(path104, current);
|
|
63916
|
+
return { ok: true, path: path104 };
|
|
63433
63917
|
}
|
|
63918
|
+
var ENV_KEY_RE;
|
|
63434
63919
|
var init_mcpConfigIo = __esm({
|
|
63435
63920
|
"src/cli/mcp/mcpConfigIo.ts"() {
|
|
63436
63921
|
"use strict";
|
|
63437
63922
|
init_paths();
|
|
63923
|
+
ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
63438
63924
|
}
|
|
63439
63925
|
});
|
|
63440
63926
|
|
|
@@ -63601,21 +64087,21 @@ __export(mcpManager_exports, {
|
|
|
63601
64087
|
readMcpConfig: () => readMcpConfig,
|
|
63602
64088
|
registerMcpTools: () => registerMcpTools
|
|
63603
64089
|
});
|
|
63604
|
-
import { existsSync as
|
|
63605
|
-
import { join as
|
|
64090
|
+
import { existsSync as existsSync45, readFileSync as readFileSync32 } from "node:fs";
|
|
64091
|
+
import { join as join36 } from "node:path";
|
|
63606
64092
|
function readMcpConfig(projectRoot = process.cwd(), opts) {
|
|
63607
64093
|
const merged = {};
|
|
63608
64094
|
const paths = [];
|
|
63609
64095
|
if (process.env["ZELARI_MCP_USER"] !== "0") {
|
|
63610
|
-
paths.push(
|
|
64096
|
+
paths.push(join36(zelariHome(), "mcp.json"));
|
|
63611
64097
|
}
|
|
63612
64098
|
if (!opts?.skipProjectMcp) {
|
|
63613
|
-
paths.push(
|
|
64099
|
+
paths.push(join36(projectRoot, ".zelari", "mcp.json"));
|
|
63614
64100
|
}
|
|
63615
64101
|
for (const p3 of paths) {
|
|
63616
|
-
if (!
|
|
64102
|
+
if (!existsSync45(p3)) continue;
|
|
63617
64103
|
try {
|
|
63618
|
-
const parsed = JSON.parse(
|
|
64104
|
+
const parsed = JSON.parse(readFileSync32(p3, "utf8"));
|
|
63619
64105
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
63620
64106
|
const hasCommand = !!cfg && typeof cfg.command === "string" && cfg.command.length > 0;
|
|
63621
64107
|
const hasUrl = !!cfg && typeof cfg.url === "string" && /^https?:\/\//i.test(cfg.url);
|
|
@@ -63631,7 +64117,7 @@ async function ensureLoaded(projectRoot) {
|
|
|
63631
64117
|
if (state2.loaded) return;
|
|
63632
64118
|
state2.loaded = true;
|
|
63633
64119
|
const trusted = isFolderTrusted(projectRoot);
|
|
63634
|
-
if (!trusted &&
|
|
64120
|
+
if (!trusted && existsSync45(join36(projectRoot, ".zelari", "mcp.json"))) {
|
|
63635
64121
|
state2.warnings.push(
|
|
63636
64122
|
"[mcp] project .zelari/mcp.json ignored \u2014 folder not trusted (run /trust or `zelari-code --trust` to enable project MCP)"
|
|
63637
64123
|
);
|
|
@@ -63645,7 +64131,7 @@ async function ensureLoaded(projectRoot) {
|
|
|
63645
64131
|
);
|
|
63646
64132
|
continue;
|
|
63647
64133
|
}
|
|
63648
|
-
const client = new McpClient(name, cfg);
|
|
64134
|
+
const client = new McpClient(name, cfg, projectRoot);
|
|
63649
64135
|
try {
|
|
63650
64136
|
await client.start();
|
|
63651
64137
|
const tools = await client.listTools();
|
|
@@ -63895,15 +64381,15 @@ __export(agentsMd_exports, {
|
|
|
63895
64381
|
serializeAgentsMd: () => serializeAgentsMd,
|
|
63896
64382
|
updateAgentsMd: () => updateAgentsMd
|
|
63897
64383
|
});
|
|
63898
|
-
import { existsSync as
|
|
64384
|
+
import { existsSync as existsSync46, readFileSync as readFileSync33, writeFileSync as writeFileSync21 } from "node:fs";
|
|
63899
64385
|
import { createHash as createHash24 } from "node:crypto";
|
|
63900
|
-
import { join as
|
|
64386
|
+
import { join as join37 } from "node:path";
|
|
63901
64387
|
import { readFile as readFile11 } from "node:fs/promises";
|
|
63902
64388
|
async function readPackageJson3(projectRoot) {
|
|
63903
|
-
const
|
|
63904
|
-
if (!
|
|
64389
|
+
const path104 = join37(projectRoot, "package.json");
|
|
64390
|
+
if (!existsSync46(path104)) return null;
|
|
63905
64391
|
try {
|
|
63906
|
-
return JSON.parse(await readFile11(
|
|
64392
|
+
return JSON.parse(await readFile11(path104, "utf8"));
|
|
63907
64393
|
} catch {
|
|
63908
64394
|
return null;
|
|
63909
64395
|
}
|
|
@@ -63925,8 +64411,8 @@ async function genTechStack(ctx) {
|
|
|
63925
64411
|
].join("\n");
|
|
63926
64412
|
}
|
|
63927
64413
|
async function genDecisions(ctx) {
|
|
63928
|
-
const decisionsDir =
|
|
63929
|
-
if (!
|
|
64414
|
+
const decisionsDir = join37(ctx.rootDir, "decisions");
|
|
64415
|
+
if (!existsSync46(decisionsDir)) return "_No ADRs yet._";
|
|
63930
64416
|
const files = ctx.storage.listMarkdown(decisionsDir).sort();
|
|
63931
64417
|
const accepted = [];
|
|
63932
64418
|
const proposed = [];
|
|
@@ -63951,9 +64437,9 @@ async function genDecisions(ctx) {
|
|
|
63951
64437
|
}
|
|
63952
64438
|
async function genConventions(ctx) {
|
|
63953
64439
|
const lines = [];
|
|
63954
|
-
const claudeMd =
|
|
63955
|
-
if (
|
|
63956
|
-
const content =
|
|
64440
|
+
const claudeMd = join37(ctx.projectRoot, "CLAUDE.MD");
|
|
64441
|
+
if (existsSync46(claudeMd)) {
|
|
64442
|
+
const content = readFileSync33(claudeMd, "utf8");
|
|
63957
64443
|
const match = content.match(/## Architecture rules[\s\S]+?(?=\n## |\n*$)/);
|
|
63958
64444
|
if (match) {
|
|
63959
64445
|
lines.push('<!-- Extracted from CLAUDE.MD "Architecture rules" -->');
|
|
@@ -63985,9 +64471,9 @@ async function genBuild(ctx) {
|
|
|
63985
64471
|
].join("\n");
|
|
63986
64472
|
}
|
|
63987
64473
|
async function genOpenQuestions(ctx) {
|
|
63988
|
-
const
|
|
63989
|
-
if (!
|
|
63990
|
-
const content =
|
|
64474
|
+
const path104 = join37(ctx.rootDir, "risks.md");
|
|
64475
|
+
if (!existsSync46(path104)) return "_No open questions._";
|
|
64476
|
+
const content = readFileSync33(path104, "utf8");
|
|
63991
64477
|
const lines = content.split("\n");
|
|
63992
64478
|
const questions = [];
|
|
63993
64479
|
let currentTitle = "";
|
|
@@ -64061,9 +64547,9 @@ function titleCase(id3) {
|
|
|
64061
64547
|
return id3.split("-").map((w) => w[0].toUpperCase() + w.slice(1)).join(" ");
|
|
64062
64548
|
}
|
|
64063
64549
|
async function updateAgentsMd(ctx, projectRoot) {
|
|
64064
|
-
const agentsPath =
|
|
64065
|
-
if (
|
|
64066
|
-
const content =
|
|
64550
|
+
const agentsPath = join37(projectRoot, "AGENTS.MD");
|
|
64551
|
+
if (existsSync46(agentsPath)) {
|
|
64552
|
+
const content = readFileSync33(agentsPath, "utf8");
|
|
64067
64553
|
const hasAnyMarker = AUTO_SECTIONS.some((id3) => content.includes(MARKER_OPEN(id3)));
|
|
64068
64554
|
if (!hasAnyMarker) {
|
|
64069
64555
|
return {
|
|
@@ -64078,8 +64564,8 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
64078
64564
|
newSections.set(id3, await GENERATORS[id3](ctx));
|
|
64079
64565
|
}
|
|
64080
64566
|
let manualContent = "";
|
|
64081
|
-
if (
|
|
64082
|
-
const { manualBlocks } = parseAgentsMd(
|
|
64567
|
+
if (existsSync46(agentsPath)) {
|
|
64568
|
+
const { manualBlocks } = parseAgentsMd(readFileSync33(agentsPath, "utf8"));
|
|
64083
64569
|
manualContent = manualBlocks.after;
|
|
64084
64570
|
} else {
|
|
64085
64571
|
const projectName2 = projectName(projectRoot);
|
|
@@ -64095,7 +64581,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
64095
64581
|
""
|
|
64096
64582
|
].join("\n");
|
|
64097
64583
|
}
|
|
64098
|
-
const oldContent =
|
|
64584
|
+
const oldContent = existsSync46(agentsPath) ? readFileSync33(agentsPath, "utf8") : "";
|
|
64099
64585
|
const { sections: oldSections } = parseAgentsMd(oldContent);
|
|
64100
64586
|
const changedSections = [];
|
|
64101
64587
|
for (const id3 of AUTO_SECTIONS) {
|
|
@@ -64107,7 +64593,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
64107
64593
|
return { changed: false, sections: [] };
|
|
64108
64594
|
}
|
|
64109
64595
|
const newContent = serializeAgentsMd(manualContent, newSections);
|
|
64110
|
-
|
|
64596
|
+
writeFileSync21(agentsPath, newContent, "utf8");
|
|
64111
64597
|
return { changed: true, sections: changedSections };
|
|
64112
64598
|
}
|
|
64113
64599
|
function hash2(s) {
|
|
@@ -64232,12 +64718,12 @@ var init_completeDesign = __esm({
|
|
|
64232
64718
|
});
|
|
64233
64719
|
|
|
64234
64720
|
// src/cli/workspace/planDriftCheck.ts
|
|
64235
|
-
import { existsSync as
|
|
64236
|
-
import { join as
|
|
64721
|
+
import { existsSync as existsSync47, readFileSync as readFileSync34, readdirSync as readdirSync11, statSync as statSync6, writeFileSync as writeFileSync22 } from "node:fs";
|
|
64722
|
+
import { join as join38 } from "node:path";
|
|
64237
64723
|
function findCanonicalDoc(rootDir) {
|
|
64238
|
-
const docsDir =
|
|
64239
|
-
if (!
|
|
64240
|
-
const candidates =
|
|
64724
|
+
const docsDir = join38(rootDir, "docs");
|
|
64725
|
+
if (!existsSync47(docsDir)) return null;
|
|
64726
|
+
const candidates = readdirSync11(docsDir).filter((f) => /^plan-canonical.*\.md$/i.test(f)).map((f) => ({ f, mtime: statSync6(join38(docsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
64241
64727
|
return candidates.length > 0 ? candidates[0].f : null;
|
|
64242
64728
|
}
|
|
64243
64729
|
function parseCanonicalDoc(text) {
|
|
@@ -64261,9 +64747,9 @@ function versionKey(value) {
|
|
|
64261
64747
|
function firstString2(v) {
|
|
64262
64748
|
return typeof v === "string" && v.trim().length > 0 ? v : null;
|
|
64263
64749
|
}
|
|
64264
|
-
function readFileSyncSafe(
|
|
64750
|
+
function readFileSyncSafe(path104) {
|
|
64265
64751
|
try {
|
|
64266
|
-
return
|
|
64752
|
+
return readFileSync34(path104, "utf8");
|
|
64267
64753
|
} catch {
|
|
64268
64754
|
return null;
|
|
64269
64755
|
}
|
|
@@ -64272,13 +64758,13 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
64272
64758
|
if (process.env["ZELARI_DRIFT_CHECK"] === "0") {
|
|
64273
64759
|
return { ran: false, reason: "ZELARI_DRIFT_CHECK=0 (disabled)" };
|
|
64274
64760
|
}
|
|
64275
|
-
const planPath =
|
|
64276
|
-
if (!
|
|
64761
|
+
const planPath = join38(rootDir, "plan.json");
|
|
64762
|
+
if (!existsSync47(planPath)) {
|
|
64277
64763
|
return { ran: false, reason: ".zelari/plan.json missing (not design-phase)" };
|
|
64278
64764
|
}
|
|
64279
64765
|
let plan;
|
|
64280
64766
|
try {
|
|
64281
|
-
plan = JSON.parse(
|
|
64767
|
+
plan = JSON.parse(readFileSync34(planPath, "utf8"));
|
|
64282
64768
|
} catch {
|
|
64283
64769
|
return { ran: false, reason: ".zelari/plan.json corrupt" };
|
|
64284
64770
|
}
|
|
@@ -64288,7 +64774,7 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
64288
64774
|
const milestones = Array.isArray(plan.milestones) ? plan.milestones : [];
|
|
64289
64775
|
const phaseIds = new Set(phases.map((p3) => typeof p3.id === "string" ? p3.id : "").filter(Boolean));
|
|
64290
64776
|
const canonicalName = findCanonicalDoc(rootDir);
|
|
64291
|
-
const canonicalText = canonicalName ? readFileSyncSafe(
|
|
64777
|
+
const canonicalText = canonicalName ? readFileSyncSafe(join38(rootDir, "docs", canonicalName)) : null;
|
|
64292
64778
|
if (canonicalText !== null) {
|
|
64293
64779
|
const { activePhases, blockedPrefixes } = parseCanonicalDoc(canonicalText);
|
|
64294
64780
|
for (const id3 of activePhases) {
|
|
@@ -64367,8 +64853,8 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
64367
64853
|
const canonicalParsed = canonicalName !== null && canonicalText !== null;
|
|
64368
64854
|
let reportPath;
|
|
64369
64855
|
try {
|
|
64370
|
-
reportPath =
|
|
64371
|
-
|
|
64856
|
+
reportPath = join38(rootDir, "drift-report.json");
|
|
64857
|
+
writeFileSync22(
|
|
64372
64858
|
reportPath,
|
|
64373
64859
|
JSON.stringify(
|
|
64374
64860
|
{
|
|
@@ -64404,8 +64890,8 @@ var init_planDriftCheck = __esm({
|
|
|
64404
64890
|
|
|
64405
64891
|
// src/cli/workspace/projectSmoke.ts
|
|
64406
64892
|
import { spawn as spawn15 } from "node:child_process";
|
|
64407
|
-
import { existsSync as
|
|
64408
|
-
import { join as
|
|
64893
|
+
import { existsSync as existsSync48, readFileSync as readFileSync35 } from "node:fs";
|
|
64894
|
+
import { join as join39 } from "node:path";
|
|
64409
64895
|
function pickSmokeScript(scripts) {
|
|
64410
64896
|
if (!scripts) return null;
|
|
64411
64897
|
for (const name of SMOKE_SCRIPT_PRIORITY) {
|
|
@@ -64417,13 +64903,13 @@ async function runProjectSmoke(projectRoot, timeoutMs2 = DEFAULT_TIMEOUT_MS3) {
|
|
|
64417
64903
|
if (process.env["ZELARI_SMOKE"] === "0") {
|
|
64418
64904
|
return { ran: false, reason: "ZELARI_SMOKE=0 (disabled)" };
|
|
64419
64905
|
}
|
|
64420
|
-
const pkgPath =
|
|
64421
|
-
if (!
|
|
64906
|
+
const pkgPath = join39(projectRoot, "package.json");
|
|
64907
|
+
if (!existsSync48(pkgPath)) {
|
|
64422
64908
|
return { ran: false, reason: "no package.json (skipped)" };
|
|
64423
64909
|
}
|
|
64424
64910
|
let scripts = {};
|
|
64425
64911
|
try {
|
|
64426
|
-
const pkg = JSON.parse(
|
|
64912
|
+
const pkg = JSON.parse(readFileSync35(pkgPath, "utf8"));
|
|
64427
64913
|
scripts = pkg.scripts ?? {};
|
|
64428
64914
|
} catch {
|
|
64429
64915
|
return { ran: false, reason: "package.json unreadable (skipped)" };
|
|
@@ -64510,7 +64996,7 @@ __export(evidenceFromSpine_exports, {
|
|
|
64510
64996
|
collectSessionEvidenceRefs: () => collectSessionEvidenceRefs,
|
|
64511
64997
|
evidenceRefsFromEventLines: () => evidenceRefsFromEventLines
|
|
64512
64998
|
});
|
|
64513
|
-
import { existsSync as
|
|
64999
|
+
import { existsSync as existsSync49, readFileSync as readFileSync36 } from "node:fs";
|
|
64514
65000
|
import path75 from "node:path";
|
|
64515
65001
|
function asRecord2(v) {
|
|
64516
65002
|
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
@@ -64550,8 +65036,8 @@ function evidenceRefsFromEventLines(lines) {
|
|
|
64550
65036
|
function collectSessionEvidenceRefs(sessionId2) {
|
|
64551
65037
|
try {
|
|
64552
65038
|
const file2 = path75.join(sessionsDir(), sessionId2, "events.jsonl");
|
|
64553
|
-
if (!
|
|
64554
|
-
return evidenceRefsFromEventLines(
|
|
65039
|
+
if (!existsSync49(file2)) return [];
|
|
65040
|
+
return evidenceRefsFromEventLines(readFileSync36(file2, "utf8").split("\n"));
|
|
64555
65041
|
} catch {
|
|
64556
65042
|
return [];
|
|
64557
65043
|
}
|
|
@@ -64574,8 +65060,8 @@ __export(postCouncilHook_exports, {
|
|
|
64574
65060
|
runPostCouncilHook: () => runPostCouncilHook
|
|
64575
65061
|
});
|
|
64576
65062
|
import { spawn as spawn16 } from "node:child_process";
|
|
64577
|
-
import { existsSync as
|
|
64578
|
-
import { join as
|
|
65063
|
+
import { existsSync as existsSync50, readFileSync as readFileSync37 } from "node:fs";
|
|
65064
|
+
import { join as join40 } from "node:path";
|
|
64579
65065
|
async function runCompleteDesignPostProcessor(ctx, options) {
|
|
64580
65066
|
if (options?.runMode === "implementation") {
|
|
64581
65067
|
return {
|
|
@@ -64586,9 +65072,9 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
64586
65072
|
if (process.env["ZELARI_COMPLETE_DESIGN"] === "0") {
|
|
64587
65073
|
return { ran: false, reason: "ZELARI_COMPLETE_DESIGN=0 (disabled)" };
|
|
64588
65074
|
}
|
|
64589
|
-
const planJsonPath2 =
|
|
64590
|
-
const scriptPath =
|
|
64591
|
-
if (!
|
|
65075
|
+
const planJsonPath2 = join40(ctx.rootDir, "plan.json");
|
|
65076
|
+
const scriptPath = join40(ctx.projectRoot, "complete-design.mjs");
|
|
65077
|
+
if (!existsSync50(planJsonPath2)) {
|
|
64592
65078
|
return {
|
|
64593
65079
|
ran: false,
|
|
64594
65080
|
reason: ".zelari/plan.json missing (not design-phase)"
|
|
@@ -64596,7 +65082,7 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
64596
65082
|
}
|
|
64597
65083
|
let phaseCount = 0;
|
|
64598
65084
|
try {
|
|
64599
|
-
const parsed = JSON.parse(
|
|
65085
|
+
const parsed = JSON.parse(readFileSync37(planJsonPath2, "utf8"));
|
|
64600
65086
|
phaseCount = Array.isArray(parsed.phases) ? parsed.phases.length : 0;
|
|
64601
65087
|
} catch {
|
|
64602
65088
|
return { ran: false, reason: ".zelari/plan.json corrupt" };
|
|
@@ -64604,7 +65090,7 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
64604
65090
|
if (phaseCount === 0) {
|
|
64605
65091
|
return { ran: false, reason: ".zelari/plan.json has no phases" };
|
|
64606
65092
|
}
|
|
64607
|
-
if (!
|
|
65093
|
+
if (!existsSync50(scriptPath)) {
|
|
64608
65094
|
try {
|
|
64609
65095
|
const builtin = await runBuiltinCompleteDesign(ctx);
|
|
64610
65096
|
return {
|
|
@@ -64799,8 +65285,8 @@ async function runPostCouncilHook(ctx, options) {
|
|
|
64799
65285
|
sources: scope.sources
|
|
64800
65286
|
} : void 0
|
|
64801
65287
|
});
|
|
64802
|
-
const
|
|
64803
|
-
completionHook = { ran: true, path:
|
|
65288
|
+
const path104 = writeCouncilCompletion(ctx.rootDir, completion);
|
|
65289
|
+
completionHook = { ran: true, path: path104, completion };
|
|
64804
65290
|
} catch (err) {
|
|
64805
65291
|
completionHook = {
|
|
64806
65292
|
ran: true,
|
|
@@ -64840,10 +65326,10 @@ __export(councilFeedback_exports, {
|
|
|
64840
65326
|
});
|
|
64841
65327
|
import {
|
|
64842
65328
|
promises as fs33,
|
|
64843
|
-
existsSync as
|
|
64844
|
-
readFileSync as
|
|
64845
|
-
writeFileSync as
|
|
64846
|
-
mkdirSync as
|
|
65329
|
+
existsSync as existsSync51,
|
|
65330
|
+
readFileSync as readFileSync38,
|
|
65331
|
+
writeFileSync as writeFileSync23,
|
|
65332
|
+
mkdirSync as mkdirSync19
|
|
64847
65333
|
} from "node:fs";
|
|
64848
65334
|
import path76 from "node:path";
|
|
64849
65335
|
var FeedbackStore;
|
|
@@ -64949,9 +65435,9 @@ var init_councilFeedback = __esm({
|
|
|
64949
65435
|
}
|
|
64950
65436
|
// --- persistence ---------------------------------------------------------
|
|
64951
65437
|
load() {
|
|
64952
|
-
if (!
|
|
65438
|
+
if (!existsSync51(this.file)) return;
|
|
64953
65439
|
try {
|
|
64954
|
-
const raw =
|
|
65440
|
+
const raw = readFileSync38(this.file, "utf-8");
|
|
64955
65441
|
const parsed = JSON.parse(raw);
|
|
64956
65442
|
if (parsed && Array.isArray(parsed.entries)) {
|
|
64957
65443
|
this.entries = parsed.entries.filter(
|
|
@@ -64962,8 +65448,8 @@ var init_councilFeedback = __esm({
|
|
|
64962
65448
|
}
|
|
64963
65449
|
}
|
|
64964
65450
|
save() {
|
|
64965
|
-
|
|
64966
|
-
|
|
65451
|
+
mkdirSync19(path76.dirname(this.file), { recursive: true });
|
|
65452
|
+
writeFileSync23(
|
|
64967
65453
|
this.file,
|
|
64968
65454
|
JSON.stringify({ entries: this.entries }, null, 2),
|
|
64969
65455
|
{ encoding: "utf-8", mode: 384 }
|
|
@@ -65036,7 +65522,7 @@ __export(ledger_exports, {
|
|
|
65036
65522
|
ledgerStats: () => ledgerStats,
|
|
65037
65523
|
readLedger: () => readLedger
|
|
65038
65524
|
});
|
|
65039
|
-
import { appendFileSync as appendFileSync4, existsSync as
|
|
65525
|
+
import { appendFileSync as appendFileSync4, existsSync as existsSync52, mkdirSync as mkdirSync20, readFileSync as readFileSync39 } from "node:fs";
|
|
65040
65526
|
import path77 from "node:path";
|
|
65041
65527
|
function evolutionMode(env = process.env) {
|
|
65042
65528
|
return env[EVOLUTION_ENV] === "shadow" ? "shadow" : "0";
|
|
@@ -65050,7 +65536,7 @@ function appendLedgerEntry(cwd, entry) {
|
|
|
65050
65536
|
}
|
|
65051
65537
|
try {
|
|
65052
65538
|
const file2 = ledgerPath(cwd);
|
|
65053
|
-
|
|
65539
|
+
mkdirSync20(path77.dirname(file2), { recursive: true });
|
|
65054
65540
|
appendFileSync4(file2, `${JSON.stringify(entry)}
|
|
65055
65541
|
`, "utf8");
|
|
65056
65542
|
return { written: true, path: file2 };
|
|
@@ -65063,10 +65549,10 @@ function appendLedgerEntry(cwd, entry) {
|
|
|
65063
65549
|
}
|
|
65064
65550
|
function readLedger(cwd) {
|
|
65065
65551
|
const file2 = ledgerPath(cwd);
|
|
65066
|
-
if (!
|
|
65552
|
+
if (!existsSync52(file2)) return [];
|
|
65067
65553
|
let raw;
|
|
65068
65554
|
try {
|
|
65069
|
-
raw =
|
|
65555
|
+
raw = readFileSync39(file2, "utf8");
|
|
65070
65556
|
} catch {
|
|
65071
65557
|
return [];
|
|
65072
65558
|
}
|
|
@@ -66286,7 +66772,7 @@ function safeSocketPath(socketPath) {
|
|
|
66286
66772
|
return socketPath.trim();
|
|
66287
66773
|
}
|
|
66288
66774
|
function startPermissionBroker(socketPath, handlers, opts) {
|
|
66289
|
-
const
|
|
66775
|
+
const path104 = safeSocketPath(socketPath);
|
|
66290
66776
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
66291
66777
|
const sockets = /* @__PURE__ */ new Set();
|
|
66292
66778
|
const server = createServer2((socket) => {
|
|
@@ -66383,13 +66869,13 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
66383
66869
|
});
|
|
66384
66870
|
}
|
|
66385
66871
|
}
|
|
66386
|
-
return new Promise((
|
|
66872
|
+
return new Promise((resolve10, reject) => {
|
|
66387
66873
|
const onError = (err) => reject(err);
|
|
66388
66874
|
server.once("error", onError);
|
|
66389
|
-
server.listen(
|
|
66875
|
+
server.listen(path104, () => {
|
|
66390
66876
|
server.removeListener("error", onError);
|
|
66391
|
-
|
|
66392
|
-
socketPath:
|
|
66877
|
+
resolve10({
|
|
66878
|
+
socketPath: path104,
|
|
66393
66879
|
stop: () => new Promise((res) => {
|
|
66394
66880
|
for (const s of sockets) s.destroy();
|
|
66395
66881
|
sockets.clear();
|
|
@@ -66400,7 +66886,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
66400
66886
|
if (done) return;
|
|
66401
66887
|
done = true;
|
|
66402
66888
|
if (process.platform !== "win32") {
|
|
66403
|
-
unlink(
|
|
66889
|
+
unlink(path104, () => res());
|
|
66404
66890
|
} else {
|
|
66405
66891
|
res();
|
|
66406
66892
|
}
|
|
@@ -66413,11 +66899,11 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
66413
66899
|
});
|
|
66414
66900
|
}
|
|
66415
66901
|
function requestBrokerAsk(socketPath, ask, opts) {
|
|
66416
|
-
const
|
|
66902
|
+
const path104 = safeSocketPath(socketPath);
|
|
66417
66903
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
66418
66904
|
const connectTimeoutMs = opts?.connectTimeoutMs ?? PERMISSION_BROKER_DEFAULT_CONNECT_TIMEOUT_MS;
|
|
66419
|
-
return new Promise((
|
|
66420
|
-
const socket = connect(
|
|
66905
|
+
return new Promise((resolve10, reject) => {
|
|
66906
|
+
const socket = connect(path104);
|
|
66421
66907
|
let buffer = "";
|
|
66422
66908
|
let settled = false;
|
|
66423
66909
|
const settle = (fn) => {
|
|
@@ -66432,7 +66918,7 @@ function requestBrokerAsk(socketPath, ask, opts) {
|
|
|
66432
66918
|
settle(
|
|
66433
66919
|
() => reject(
|
|
66434
66920
|
new Error(
|
|
66435
|
-
`permission broker unavailable at "${
|
|
66921
|
+
`permission broker unavailable at "${path104}" (connect timed out after ${connectTimeoutMs}ms)`
|
|
66436
66922
|
)
|
|
66437
66923
|
)
|
|
66438
66924
|
);
|
|
@@ -66469,7 +66955,7 @@ function requestBrokerAsk(socketPath, ask, opts) {
|
|
|
66469
66955
|
}
|
|
66470
66956
|
if (msg?.t === "answer" && msg.id === ask.id) {
|
|
66471
66957
|
const { t: _t, id: _id, ...answer } = msg;
|
|
66472
|
-
settle(() =>
|
|
66958
|
+
settle(() => resolve10(answer));
|
|
66473
66959
|
return;
|
|
66474
66960
|
}
|
|
66475
66961
|
}
|
|
@@ -67249,8 +67735,8 @@ __export(prereqChecks_exports, {
|
|
|
67249
67735
|
runPrereqChecks: () => runPrereqChecks
|
|
67250
67736
|
});
|
|
67251
67737
|
import { execSync, spawnSync as spawnSync2 } from "node:child_process";
|
|
67252
|
-
import { existsSync as
|
|
67253
|
-
import { dirname as
|
|
67738
|
+
import { existsSync as existsSync54 } from "node:fs";
|
|
67739
|
+
import { dirname as dirname13 } from "node:path";
|
|
67254
67740
|
function isWslBashPath2(p3) {
|
|
67255
67741
|
if (!p3 || typeof p3 !== "string") return false;
|
|
67256
67742
|
const n = p3.replace(/\//g, "\\").toLowerCase();
|
|
@@ -67356,16 +67842,16 @@ function resolveAgentShellSync() {
|
|
|
67356
67842
|
function agentProbeEnv() {
|
|
67357
67843
|
const env = { ...process.env };
|
|
67358
67844
|
try {
|
|
67359
|
-
const nodeDir =
|
|
67845
|
+
const nodeDir = dirname13(process.execPath);
|
|
67360
67846
|
if (!nodeDir) return env;
|
|
67361
|
-
const
|
|
67847
|
+
const sep5 = process.platform === "win32" ? ";" : ":";
|
|
67362
67848
|
const current = env.PATH ?? env.Path ?? "";
|
|
67363
|
-
const parts = current.split(
|
|
67849
|
+
const parts = current.split(sep5).filter((p3) => p3.length > 0);
|
|
67364
67850
|
const has = parts.some(
|
|
67365
67851
|
(p3) => p3.toLowerCase() === nodeDir.toLowerCase()
|
|
67366
67852
|
);
|
|
67367
67853
|
if (!has) {
|
|
67368
|
-
env.PATH = `${nodeDir}${
|
|
67854
|
+
env.PATH = `${nodeDir}${sep5}${current}`;
|
|
67369
67855
|
}
|
|
67370
67856
|
} catch {
|
|
67371
67857
|
}
|
|
@@ -67373,7 +67859,7 @@ function agentProbeEnv() {
|
|
|
67373
67859
|
}
|
|
67374
67860
|
function existsSyncSafe2(p3) {
|
|
67375
67861
|
try {
|
|
67376
|
-
return
|
|
67862
|
+
return existsSync54(p3);
|
|
67377
67863
|
} catch {
|
|
67378
67864
|
return false;
|
|
67379
67865
|
}
|
|
@@ -67620,7 +68106,7 @@ var init_prereqChecks = __esm({
|
|
|
67620
68106
|
});
|
|
67621
68107
|
|
|
67622
68108
|
// src/cli/plugins/prefs.ts
|
|
67623
|
-
import { existsSync as
|
|
68109
|
+
import { existsSync as existsSync55, readFileSync as readFileSync41, writeFileSync as writeFileSync24, mkdirSync as mkdirSync21 } from "node:fs";
|
|
67624
68110
|
import path85 from "node:path";
|
|
67625
68111
|
function getPluginPrefsPath() {
|
|
67626
68112
|
return pluginsPrefsPath();
|
|
@@ -67628,8 +68114,8 @@ function getPluginPrefsPath() {
|
|
|
67628
68114
|
function getPluginPrefs() {
|
|
67629
68115
|
const file2 = getPluginPrefsPath();
|
|
67630
68116
|
try {
|
|
67631
|
-
if (!
|
|
67632
|
-
const raw =
|
|
68117
|
+
if (!existsSync55(file2)) return { ...DEFAULTS2, dontAskAgain: {} };
|
|
68118
|
+
const raw = readFileSync41(file2, "utf-8");
|
|
67633
68119
|
const parsed = JSON.parse(raw);
|
|
67634
68120
|
if (parsed && typeof parsed === "object" && parsed.dontAskAgain && typeof parsed.dontAskAgain === "object") {
|
|
67635
68121
|
const clean = {};
|
|
@@ -67644,8 +68130,8 @@ function getPluginPrefs() {
|
|
|
67644
68130
|
}
|
|
67645
68131
|
function writePluginPrefs(prefs) {
|
|
67646
68132
|
const file2 = getPluginPrefsPath();
|
|
67647
|
-
|
|
67648
|
-
|
|
68133
|
+
mkdirSync21(path85.dirname(file2), { recursive: true });
|
|
68134
|
+
writeFileSync24(file2, JSON.stringify(prefs, null, 2), {
|
|
67649
68135
|
encoding: "utf-8",
|
|
67650
68136
|
mode: 384
|
|
67651
68137
|
});
|
|
@@ -67681,7 +68167,7 @@ __export(registry_exports, {
|
|
|
67681
68167
|
findPlugin: () => findPlugin,
|
|
67682
68168
|
isBinaryOnPath: () => isBinaryOnPath
|
|
67683
68169
|
});
|
|
67684
|
-
import { existsSync as
|
|
68170
|
+
import { existsSync as existsSync56 } from "node:fs";
|
|
67685
68171
|
import path86 from "node:path";
|
|
67686
68172
|
function detectLocalBin(bin) {
|
|
67687
68173
|
return (cwd) => {
|
|
@@ -67698,11 +68184,11 @@ function isBinaryOnPath(bin, opts = {}) {
|
|
|
67698
68184
|
return false;
|
|
67699
68185
|
}
|
|
67700
68186
|
const platform = opts.platform ?? process.platform;
|
|
67701
|
-
const exists = opts.exists ??
|
|
68187
|
+
const exists = opts.exists ?? existsSync56;
|
|
67702
68188
|
const pathEnv = opts.pathEnv ?? process.env.PATH ?? "";
|
|
67703
68189
|
const pathMod = platform === "win32" ? path86.win32 : path86.posix;
|
|
67704
|
-
const
|
|
67705
|
-
const dirs = pathEnv.split(
|
|
68190
|
+
const sep5 = platform === "win32" ? ";" : ":";
|
|
68191
|
+
const dirs = pathEnv.split(sep5).filter((d) => d.length > 0);
|
|
67706
68192
|
const candidates = [bin];
|
|
67707
68193
|
if (platform === "win32") {
|
|
67708
68194
|
const pathExt = opts.pathExt ?? process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM";
|
|
@@ -68442,8 +68928,8 @@ __export(atMentions_exports, {
|
|
|
68442
68928
|
extractAtMentions: () => extractAtMentions,
|
|
68443
68929
|
hasAtMentions: () => hasAtMentions
|
|
68444
68930
|
});
|
|
68445
|
-
import { existsSync as
|
|
68446
|
-
import { basename as basename5, isAbsolute as
|
|
68931
|
+
import { existsSync as existsSync59, readFileSync as readFileSync43, statSync as statSync9 } from "node:fs";
|
|
68932
|
+
import { basename as basename5, isAbsolute as isAbsolute5, relative as relative5, resolve as resolve7, sep as sep3 } from "node:path";
|
|
68447
68933
|
function isImagePath(abs) {
|
|
68448
68934
|
const ext = abs.split(".").pop()?.toLowerCase() ?? "";
|
|
68449
68935
|
return ext in IMAGE_MIME_BY_EXT;
|
|
@@ -68457,9 +68943,9 @@ function isProbablyText(name, head) {
|
|
|
68457
68943
|
return !head.includes("\0") && /[\x09\x0a\x0d\x20-\x7e]/.test(head.slice(0, 200));
|
|
68458
68944
|
}
|
|
68459
68945
|
function underRoot(abs, root) {
|
|
68460
|
-
const a =
|
|
68461
|
-
const r =
|
|
68462
|
-
const prefix = r.endsWith(
|
|
68946
|
+
const a = resolve7(abs);
|
|
68947
|
+
const r = resolve7(root);
|
|
68948
|
+
const prefix = r.endsWith(sep3) ? r : r + sep3;
|
|
68463
68949
|
return a === r || a.startsWith(prefix);
|
|
68464
68950
|
}
|
|
68465
68951
|
function extractAtMentions(text) {
|
|
@@ -68486,7 +68972,7 @@ function extractAtMentions(text) {
|
|
|
68486
68972
|
return out;
|
|
68487
68973
|
}
|
|
68488
68974
|
function resolveMention(token, cwd) {
|
|
68489
|
-
const abs =
|
|
68975
|
+
const abs = isAbsolute5(token) ? resolve7(token) : resolve7(cwd, token);
|
|
68490
68976
|
if (!underRoot(abs, cwd) && !isImagePath(abs)) {
|
|
68491
68977
|
return {
|
|
68492
68978
|
raw: token,
|
|
@@ -68496,7 +68982,7 @@ function resolveMention(token, cwd) {
|
|
|
68496
68982
|
note: "outside project root \u2014 skipped"
|
|
68497
68983
|
};
|
|
68498
68984
|
}
|
|
68499
|
-
if (!
|
|
68985
|
+
if (!existsSync59(abs)) {
|
|
68500
68986
|
return {
|
|
68501
68987
|
raw: token,
|
|
68502
68988
|
path: token,
|
|
@@ -68548,7 +69034,7 @@ function resolveMention(token, cwd) {
|
|
|
68548
69034
|
note: `image too large (${Math.round(st.size / 1024)} KB) \u2014 path only`
|
|
68549
69035
|
};
|
|
68550
69036
|
}
|
|
68551
|
-
const dataBase64 =
|
|
69037
|
+
const dataBase64 = readFileSync43(abs).toString("base64");
|
|
68552
69038
|
return {
|
|
68553
69039
|
raw: token,
|
|
68554
69040
|
path: rel2,
|
|
@@ -68559,7 +69045,7 @@ function resolveMention(token, cwd) {
|
|
|
68559
69045
|
};
|
|
68560
69046
|
}
|
|
68561
69047
|
try {
|
|
68562
|
-
const buf =
|
|
69048
|
+
const buf = readFileSync43(abs);
|
|
68563
69049
|
const head = buf.subarray(0, 800).toString("utf8");
|
|
68564
69050
|
if (!isProbablyText(abs, head)) {
|
|
68565
69051
|
return {
|
|
@@ -69458,7 +69944,7 @@ var init_liveTurnAbort = __esm({
|
|
|
69458
69944
|
});
|
|
69459
69945
|
|
|
69460
69946
|
// src/cli/headless/policyGate.ts
|
|
69461
|
-
import { isAbsolute as
|
|
69947
|
+
import { isAbsolute as isAbsolute6, resolve as resolve8 } from "node:path";
|
|
69462
69948
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
69463
69949
|
function checkStrictPolicyLoad(root, opts) {
|
|
69464
69950
|
if (isPolicyEngineDisabled()) return { blocked: false, warnings: [] };
|
|
@@ -69467,7 +69953,7 @@ function checkStrictPolicyLoad(root, opts) {
|
|
|
69467
69953
|
return { blocked: false, warnings: set2.warnings };
|
|
69468
69954
|
} catch (err) {
|
|
69469
69955
|
if (!(err instanceof PolicyLoadError)) throw err;
|
|
69470
|
-
const file2 =
|
|
69956
|
+
const file2 = isAbsolute6(err.file) ? err.file : resolve8(root, err.file);
|
|
69471
69957
|
return {
|
|
69472
69958
|
blocked: true,
|
|
69473
69959
|
warnings: [],
|
|
@@ -69720,27 +70206,27 @@ var init_sandboxedFs = __esm({
|
|
|
69720
70206
|
});
|
|
69721
70207
|
|
|
69722
70208
|
// src/cli/extensions/loader.ts
|
|
69723
|
-
import { join as
|
|
69724
|
-
import { readdirSync as
|
|
70209
|
+
import { join as join46 } from "node:path";
|
|
70210
|
+
import { readdirSync as readdirSync12, readFileSync as readFileSync44 } from "node:fs";
|
|
69725
70211
|
import { createHash as createHash25 } from "node:crypto";
|
|
69726
70212
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
69727
70213
|
function globalExtensionsDir() {
|
|
69728
|
-
return
|
|
70214
|
+
return join46(zelariHome(), "extensions");
|
|
69729
70215
|
}
|
|
69730
70216
|
function projectExtensionsDir(projectRoot) {
|
|
69731
|
-
return
|
|
70217
|
+
return join46(projectRoot, ".zelari", "extensions");
|
|
69732
70218
|
}
|
|
69733
70219
|
function sha256File(file2) {
|
|
69734
|
-
return createHash25("sha256").update(
|
|
70220
|
+
return createHash25("sha256").update(readFileSync44(file2)).digest("hex");
|
|
69735
70221
|
}
|
|
69736
70222
|
function candidateFiles(dir) {
|
|
69737
70223
|
let names;
|
|
69738
70224
|
try {
|
|
69739
|
-
names =
|
|
70225
|
+
names = readdirSync12(dir);
|
|
69740
70226
|
} catch {
|
|
69741
70227
|
return [];
|
|
69742
70228
|
}
|
|
69743
|
-
return names.filter((n) => EXTENSION_FILE_EXTS.has(n.slice(n.lastIndexOf(".")).toLowerCase())).sort().map((n) =>
|
|
70229
|
+
return names.filter((n) => EXTENSION_FILE_EXTS.has(n.slice(n.lastIndexOf(".")).toLowerCase())).sort().map((n) => join46(dir, n));
|
|
69744
70230
|
}
|
|
69745
70231
|
function extractExtension(mod) {
|
|
69746
70232
|
const m = mod;
|
|
@@ -69769,7 +70255,7 @@ async function loadExtensionsFromDirs(dirs, options = {}) {
|
|
|
69769
70255
|
if (files.length === 0) continue;
|
|
69770
70256
|
let lock = null;
|
|
69771
70257
|
try {
|
|
69772
|
-
lock = JSON.parse(
|
|
70258
|
+
lock = JSON.parse(readFileSync44(join46(dir.path, EXTENSIONS_LOCK_FILE), "utf8"));
|
|
69773
70259
|
} catch {
|
|
69774
70260
|
lock = null;
|
|
69775
70261
|
if (dirHasLockFile(dir.path)) {
|
|
@@ -69836,7 +70322,7 @@ function basenameOf(file2) {
|
|
|
69836
70322
|
}
|
|
69837
70323
|
function dirHasLockFile(dir) {
|
|
69838
70324
|
try {
|
|
69839
|
-
|
|
70325
|
+
readFileSync44(join46(dir, EXTENSIONS_LOCK_FILE));
|
|
69840
70326
|
return true;
|
|
69841
70327
|
} catch {
|
|
69842
70328
|
return false;
|
|
@@ -72692,7 +73178,10 @@ ${ragContext}` : slicePrompt;
|
|
|
72692
73178
|
if (opts.output === "json") {
|
|
72693
73179
|
emitEvent({ type: "verification_run", ...missionVerificationPayload });
|
|
72694
73180
|
}
|
|
72695
|
-
|
|
73181
|
+
surfaceOpsKnowledgeNotices(
|
|
73182
|
+
await writeProofSafe(missionGate, { surface: "mission", sessionId: spine.sessionId }, projectRoot),
|
|
73183
|
+
opts
|
|
73184
|
+
);
|
|
72696
73185
|
if (missionGate.blocked) {
|
|
72697
73186
|
exitCode = strictGateExitCode(missionGate);
|
|
72698
73187
|
spine.missionPhase("verification", "mission-strict-blocked");
|
|
@@ -72789,6 +73278,11 @@ var init_runHeadless = __esm({
|
|
|
72789
73278
|
["krakenExploreModel", "ZELARI_KRAKEN_EXPLORE_MODEL"],
|
|
72790
73279
|
["krakenGeneralModel", "ZELARI_KRAKEN_GENERAL_MODEL"],
|
|
72791
73280
|
["krakenVerifyModel", "ZELARI_KRAKEN_VERIFY_MODEL"],
|
|
73281
|
+
// Per-tentacle thinking effort (ADR-0017) — same per-kind mapping as the
|
|
73282
|
+
// models above; the spawn factory reads them to override thinkingByProvider.
|
|
73283
|
+
["krakenExploreThinking", "ZELARI_KRAKEN_EXPLORE_THINKING"],
|
|
73284
|
+
["krakenGeneralThinking", "ZELARI_KRAKEN_GENERAL_THINKING"],
|
|
73285
|
+
["krakenVerifyThinking", "ZELARI_KRAKEN_VERIFY_THINKING"],
|
|
72792
73286
|
["krakenPlannerModel", "ZELARI_KRAKEN_PLANNER_MODEL"],
|
|
72793
73287
|
["krakenDelegation", "ZELARI_KRAKEN_DELEGATION"]
|
|
72794
73288
|
];
|
|
@@ -73179,270 +73673,6 @@ var init_desktopConfig = __esm({
|
|
|
73179
73673
|
}
|
|
73180
73674
|
});
|
|
73181
73675
|
|
|
73182
|
-
// src/cli/skillCategories.ts
|
|
73183
|
-
var CODING_CATEGORIES_LIST, CODING_CATEGORIES2;
|
|
73184
|
-
var init_skillCategories = __esm({
|
|
73185
|
-
"src/cli/skillCategories.ts"() {
|
|
73186
|
-
"use strict";
|
|
73187
|
-
CODING_CATEGORIES_LIST = [
|
|
73188
|
-
"plan",
|
|
73189
|
-
"refactor",
|
|
73190
|
-
"debug",
|
|
73191
|
-
"review",
|
|
73192
|
-
"test",
|
|
73193
|
-
"docs",
|
|
73194
|
-
"ops",
|
|
73195
|
-
"git",
|
|
73196
|
-
"db",
|
|
73197
|
-
"maint"
|
|
73198
|
-
];
|
|
73199
|
-
CODING_CATEGORIES2 = new Set(CODING_CATEGORIES_LIST);
|
|
73200
|
-
}
|
|
73201
|
-
});
|
|
73202
|
-
|
|
73203
|
-
// src/cli/skillConfigIo.ts
|
|
73204
|
-
import {
|
|
73205
|
-
existsSync as existsSync59,
|
|
73206
|
-
mkdirSync as mkdirSync23,
|
|
73207
|
-
readdirSync as readdirSync12,
|
|
73208
|
-
readFileSync as readFileSync44,
|
|
73209
|
-
rmSync as rmSync4,
|
|
73210
|
-
writeFileSync as writeFileSync25
|
|
73211
|
-
} from "node:fs";
|
|
73212
|
-
import { dirname as dirname14, join as join47 } from "node:path";
|
|
73213
|
-
function ensureBuiltinSkillsLoadedSync() {
|
|
73214
|
-
if (builtinsLoaded) return;
|
|
73215
|
-
for (const spec of BUILTIN_SKILL_MODULES) {
|
|
73216
|
-
try {
|
|
73217
|
-
require?.(spec);
|
|
73218
|
-
} catch {
|
|
73219
|
-
}
|
|
73220
|
-
}
|
|
73221
|
-
}
|
|
73222
|
-
function getUserSkillsDir() {
|
|
73223
|
-
return join47(zelariHome(), "skills");
|
|
73224
|
-
}
|
|
73225
|
-
function getProjectSkillsDir(projectRoot) {
|
|
73226
|
-
return join47(projectRoot, ".zelari", "skills");
|
|
73227
|
-
}
|
|
73228
|
-
function skillFilePath(dir, name) {
|
|
73229
|
-
return join47(dir, name, "SKILL.md");
|
|
73230
|
-
}
|
|
73231
|
-
function classifyScope(skillPath, projectRoot) {
|
|
73232
|
-
const userDir = getUserSkillsDir().replace(/\\/g, "/");
|
|
73233
|
-
const norm = skillPath.replace(/\\/g, "/");
|
|
73234
|
-
if (norm.startsWith(userDir + "/") || norm === userDir) {
|
|
73235
|
-
return { scope: "user", writable: true };
|
|
73236
|
-
}
|
|
73237
|
-
if (projectRoot) {
|
|
73238
|
-
const projDir = getProjectSkillsDir(projectRoot).replace(/\\/g, "/");
|
|
73239
|
-
if (norm.startsWith(projDir + "/") || norm === projDir) {
|
|
73240
|
-
return { scope: "project", writable: true };
|
|
73241
|
-
}
|
|
73242
|
-
}
|
|
73243
|
-
return { scope: "compat", writable: false };
|
|
73244
|
-
}
|
|
73245
|
-
function entryFromParsed(parsed, projectRoot) {
|
|
73246
|
-
const { scope, writable } = classifyScope(parsed.sourcePath, projectRoot);
|
|
73247
|
-
return {
|
|
73248
|
-
id: parsed.name,
|
|
73249
|
-
name: parsed.name,
|
|
73250
|
-
description: parsed.description,
|
|
73251
|
-
category: parsed.category,
|
|
73252
|
-
estimatedCost: parsed.estimatedCost,
|
|
73253
|
-
requiredTools: parsed.requiredTools,
|
|
73254
|
-
scope,
|
|
73255
|
-
path: parsed.sourcePath,
|
|
73256
|
-
body: parsed.body,
|
|
73257
|
-
builtin: false,
|
|
73258
|
-
writable
|
|
73259
|
-
};
|
|
73260
|
-
}
|
|
73261
|
-
function entryFromBuiltin(skill) {
|
|
73262
|
-
return {
|
|
73263
|
-
id: skill.id,
|
|
73264
|
-
name: skill.name || skill.id,
|
|
73265
|
-
description: skill.description || "",
|
|
73266
|
-
category: skill.category,
|
|
73267
|
-
estimatedCost: skill.estimatedCost,
|
|
73268
|
-
requiredTools: skill.requiredTools,
|
|
73269
|
-
scope: "builtin",
|
|
73270
|
-
path: null,
|
|
73271
|
-
// Expose body so Desktop skill picker can expand like `/skill <id>`.
|
|
73272
|
-
body: skill.systemPromptFragment || void 0,
|
|
73273
|
-
builtin: true,
|
|
73274
|
-
writable: false
|
|
73275
|
-
};
|
|
73276
|
-
}
|
|
73277
|
-
function scanSkillsDir(dir, projectRoot, seen, out) {
|
|
73278
|
-
if (!existsSync59(dir)) return;
|
|
73279
|
-
let entries;
|
|
73280
|
-
try {
|
|
73281
|
-
entries = readdirSync12(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
73282
|
-
} catch {
|
|
73283
|
-
return;
|
|
73284
|
-
}
|
|
73285
|
-
for (const entry of entries) {
|
|
73286
|
-
const skillPath = skillFilePath(dir, entry);
|
|
73287
|
-
if (!existsSync59(skillPath)) continue;
|
|
73288
|
-
try {
|
|
73289
|
-
const parsed = parseSkillMd(readFileSync44(skillPath, "utf8"), skillPath);
|
|
73290
|
-
if (!parsed) continue;
|
|
73291
|
-
if (seen.has(parsed.name)) continue;
|
|
73292
|
-
seen.add(parsed.name);
|
|
73293
|
-
out.push(entryFromParsed(parsed, projectRoot));
|
|
73294
|
-
} catch {
|
|
73295
|
-
}
|
|
73296
|
-
}
|
|
73297
|
-
}
|
|
73298
|
-
function listSkillsSnapshot(projectRoot) {
|
|
73299
|
-
const root = projectRoot && projectRoot.trim() ? projectRoot.trim() : null;
|
|
73300
|
-
const userSkillsDir = getUserSkillsDir();
|
|
73301
|
-
const projectSkillsDir = root ? getProjectSkillsDir(root) : null;
|
|
73302
|
-
const skills = [];
|
|
73303
|
-
const seen = /* @__PURE__ */ new Set();
|
|
73304
|
-
if (root) {
|
|
73305
|
-
scanSkillsDir(join47(root, ".zelari", "skills"), root, seen, skills);
|
|
73306
|
-
scanSkillsDir(join47(root, ".claude", "skills"), root, seen, skills);
|
|
73307
|
-
scanSkillsDir(join47(root, ".opencode", "skills"), root, seen, skills);
|
|
73308
|
-
}
|
|
73309
|
-
scanSkillsDir(userSkillsDir, root, seen, skills);
|
|
73310
|
-
for (const s of listCodingSkills()) {
|
|
73311
|
-
if (seen.has(s.id)) continue;
|
|
73312
|
-
seen.add(s.id);
|
|
73313
|
-
if (s.builtin) {
|
|
73314
|
-
skills.push(entryFromBuiltin(s));
|
|
73315
|
-
}
|
|
73316
|
-
}
|
|
73317
|
-
skills.sort((a, b) => {
|
|
73318
|
-
const order = (s) => s === "project" ? 0 : s === "user" ? 1 : s === "compat" ? 2 : 3;
|
|
73319
|
-
const d = order(a.scope) - order(b.scope);
|
|
73320
|
-
if (d !== 0) return d;
|
|
73321
|
-
return a.id.localeCompare(b.id);
|
|
73322
|
-
});
|
|
73323
|
-
return { userSkillsDir, projectSkillsDir, skills };
|
|
73324
|
-
}
|
|
73325
|
-
function serializeSkillMd(opts) {
|
|
73326
|
-
const name = opts.name.trim().toLowerCase();
|
|
73327
|
-
const description = opts.description.trim();
|
|
73328
|
-
const body = opts.body.trim();
|
|
73329
|
-
const lines = ["---", `name: ${name}`, `description: ${description}`];
|
|
73330
|
-
const cat = (opts.category ?? "").trim().toLowerCase();
|
|
73331
|
-
if (cat && CODING_CATEGORIES2.has(cat)) {
|
|
73332
|
-
lines.push(`category: ${cat}`);
|
|
73333
|
-
}
|
|
73334
|
-
if (opts.tools && opts.tools.length > 0) {
|
|
73335
|
-
lines.push(`tools: [${opts.tools.map((t) => t.trim()).filter(Boolean).join(", ")}]`);
|
|
73336
|
-
}
|
|
73337
|
-
const cost = (opts.cost ?? "").trim().toLowerCase();
|
|
73338
|
-
if (cost === "low" || cost === "medium" || cost === "high") {
|
|
73339
|
-
lines.push(`cost: ${cost}`);
|
|
73340
|
-
}
|
|
73341
|
-
lines.push("---", "", body, "");
|
|
73342
|
-
return lines.join("\n");
|
|
73343
|
-
}
|
|
73344
|
-
function upsertSkill(opts) {
|
|
73345
|
-
const name = opts.name.trim().toLowerCase();
|
|
73346
|
-
if (!name || !NAME_RE.test(name)) {
|
|
73347
|
-
return {
|
|
73348
|
-
ok: false,
|
|
73349
|
-
error: "Invalid skill name (use lowercase letters, digits, hyphens; max 64 chars)"
|
|
73350
|
-
};
|
|
73351
|
-
}
|
|
73352
|
-
const description = opts.description.trim();
|
|
73353
|
-
if (!description) {
|
|
73354
|
-
return { ok: false, error: "description is required" };
|
|
73355
|
-
}
|
|
73356
|
-
const body = opts.body.trim();
|
|
73357
|
-
if (!body) {
|
|
73358
|
-
return { ok: false, error: "body is required" };
|
|
73359
|
-
}
|
|
73360
|
-
let dir;
|
|
73361
|
-
if (opts.scope === "user") {
|
|
73362
|
-
dir = getUserSkillsDir();
|
|
73363
|
-
} else {
|
|
73364
|
-
const root = opts.projectRoot?.trim();
|
|
73365
|
-
if (!root) {
|
|
73366
|
-
return {
|
|
73367
|
-
ok: false,
|
|
73368
|
-
error: "projectRoot required for project scope (Open Folder first)"
|
|
73369
|
-
};
|
|
73370
|
-
}
|
|
73371
|
-
dir = getProjectSkillsDir(root);
|
|
73372
|
-
}
|
|
73373
|
-
const path103 = skillFilePath(dir, name);
|
|
73374
|
-
const content = serializeSkillMd({
|
|
73375
|
-
name,
|
|
73376
|
-
description,
|
|
73377
|
-
body,
|
|
73378
|
-
category: opts.category,
|
|
73379
|
-
tools: opts.tools,
|
|
73380
|
-
cost: opts.cost
|
|
73381
|
-
});
|
|
73382
|
-
const parsed = parseSkillMd(content, path103);
|
|
73383
|
-
if (!parsed) {
|
|
73384
|
-
return { ok: false, error: "Generated SKILL.md failed validation" };
|
|
73385
|
-
}
|
|
73386
|
-
mkdirSync23(dirname14(path103), { recursive: true });
|
|
73387
|
-
writeFileSync25(path103, content, "utf8");
|
|
73388
|
-
return { ok: true, path: path103 };
|
|
73389
|
-
}
|
|
73390
|
-
function removeSkill(opts) {
|
|
73391
|
-
const name = opts.name.trim().toLowerCase();
|
|
73392
|
-
if (!name) {
|
|
73393
|
-
return { ok: false, error: "name is required" };
|
|
73394
|
-
}
|
|
73395
|
-
let dir;
|
|
73396
|
-
if (opts.scope === "user") {
|
|
73397
|
-
dir = getUserSkillsDir();
|
|
73398
|
-
} else {
|
|
73399
|
-
const root = opts.projectRoot?.trim();
|
|
73400
|
-
if (!root) {
|
|
73401
|
-
return { ok: false, error: "projectRoot required for project scope" };
|
|
73402
|
-
}
|
|
73403
|
-
dir = getProjectSkillsDir(root);
|
|
73404
|
-
}
|
|
73405
|
-
const skillDir = join47(dir, name);
|
|
73406
|
-
const path103 = skillFilePath(dir, name);
|
|
73407
|
-
if (!existsSync59(path103) && !existsSync59(skillDir)) {
|
|
73408
|
-
return { ok: false, error: `Skill "${name}" not found in ${dir}` };
|
|
73409
|
-
}
|
|
73410
|
-
try {
|
|
73411
|
-
rmSync4(skillDir, { recursive: true, force: true });
|
|
73412
|
-
} catch (err) {
|
|
73413
|
-
return {
|
|
73414
|
-
ok: false,
|
|
73415
|
-
error: err instanceof Error ? err.message : String(err)
|
|
73416
|
-
};
|
|
73417
|
-
}
|
|
73418
|
-
return { ok: true, path: path103 };
|
|
73419
|
-
}
|
|
73420
|
-
var NAME_RE, BUILTIN_SKILL_MODULES, builtinsLoaded;
|
|
73421
|
-
var init_skillConfigIo = __esm({
|
|
73422
|
-
"src/cli/skillConfigIo.ts"() {
|
|
73423
|
-
"use strict";
|
|
73424
|
-
init_skills2();
|
|
73425
|
-
init_skillsMd();
|
|
73426
|
-
init_skillCategories();
|
|
73427
|
-
init_paths();
|
|
73428
|
-
NAME_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
73429
|
-
BUILTIN_SKILL_MODULES = [
|
|
73430
|
-
"@zelari/core/skills/builtin/debugging",
|
|
73431
|
-
"@zelari/core/skills/builtin/docs",
|
|
73432
|
-
"@zelari/core/skills/builtin/git-ops",
|
|
73433
|
-
"@zelari/core/skills/builtin/planning",
|
|
73434
|
-
"@zelari/core/skills/builtin/refactoring",
|
|
73435
|
-
"@zelari/core/skills/builtin/review",
|
|
73436
|
-
"@zelari/core/skills/builtin/unrealEditor",
|
|
73437
|
-
"@zelari/core/skills/builtin/testing",
|
|
73438
|
-
"@zelari/core/skills/builtin/schema-loop",
|
|
73439
|
-
"@zelari/core/skills/builtin/computer-use-cua",
|
|
73440
|
-
"@zelari/core/skills/builtin/qwen-mm-plugins"
|
|
73441
|
-
];
|
|
73442
|
-
builtinsLoaded = false;
|
|
73443
|
-
}
|
|
73444
|
-
});
|
|
73445
|
-
|
|
73446
73676
|
// src/cli/memory/jsonApi.ts
|
|
73447
73677
|
var jsonApi_exports = {};
|
|
73448
73678
|
__export(jsonApi_exports, {
|
|
@@ -73809,8 +74039,8 @@ async function startMemoryMcpServer(options) {
|
|
|
73809
74039
|
let stopped = false;
|
|
73810
74040
|
let finalizePromise;
|
|
73811
74041
|
let resolveClosed = () => void 0;
|
|
73812
|
-
const closed = new Promise((
|
|
73813
|
-
resolveClosed =
|
|
74042
|
+
const closed = new Promise((resolve10) => {
|
|
74043
|
+
resolveClosed = resolve10;
|
|
73814
74044
|
});
|
|
73815
74045
|
const adapter = new MemoryMcpAdapter({
|
|
73816
74046
|
service,
|
|
@@ -73957,8 +74187,8 @@ function startPermissionMcpServer(opts) {
|
|
|
73957
74187
|
});
|
|
73958
74188
|
let closedResolve = () => {
|
|
73959
74189
|
};
|
|
73960
|
-
const closed = new Promise((
|
|
73961
|
-
closedResolve =
|
|
74190
|
+
const closed = new Promise((resolve10) => {
|
|
74191
|
+
closedResolve = resolve10;
|
|
73962
74192
|
});
|
|
73963
74193
|
let stopped = false;
|
|
73964
74194
|
const send = (obj) => {
|
|
@@ -74211,7 +74441,7 @@ var init_permissionCli = __esm({
|
|
|
74211
74441
|
|
|
74212
74442
|
// src/cli/companion/config.ts
|
|
74213
74443
|
import {
|
|
74214
|
-
existsSync as
|
|
74444
|
+
existsSync as existsSync61,
|
|
74215
74445
|
mkdirSync as mkdirSync24,
|
|
74216
74446
|
readFileSync as readFileSync45,
|
|
74217
74447
|
writeFileSync as writeFileSync26
|
|
@@ -74229,17 +74459,17 @@ function getCompanionTokenPath() {
|
|
|
74229
74459
|
}
|
|
74230
74460
|
function ensureHome() {
|
|
74231
74461
|
const home = getZelariHome();
|
|
74232
|
-
if (!
|
|
74462
|
+
if (!existsSync61(home)) {
|
|
74233
74463
|
mkdirSync24(home, { recursive: true });
|
|
74234
74464
|
}
|
|
74235
74465
|
}
|
|
74236
74466
|
function loadCompanionConfig() {
|
|
74237
|
-
const
|
|
74238
|
-
if (!
|
|
74467
|
+
const path104 = getCompanionConfigPath();
|
|
74468
|
+
if (!existsSync61(path104)) {
|
|
74239
74469
|
return { projects: [] };
|
|
74240
74470
|
}
|
|
74241
74471
|
try {
|
|
74242
|
-
const raw = JSON.parse(readFileSync45(
|
|
74472
|
+
const raw = JSON.parse(readFileSync45(path104, "utf8"));
|
|
74243
74473
|
const projects = Array.isArray(raw.projects) ? raw.projects.filter(
|
|
74244
74474
|
(p3) => p3 && typeof p3.path === "string" && p3.path.trim() && typeof (p3.id ?? p3.name) === "string"
|
|
74245
74475
|
).map((p3) => ({
|
|
@@ -74277,16 +74507,16 @@ function loadOrCreateToken(explicit) {
|
|
|
74277
74507
|
return { token: explicit.trim(), created: false };
|
|
74278
74508
|
}
|
|
74279
74509
|
ensureHome();
|
|
74280
|
-
const
|
|
74281
|
-
if (
|
|
74282
|
-
const t = readFileSync45(
|
|
74510
|
+
const path104 = getCompanionTokenPath();
|
|
74511
|
+
if (existsSync61(path104)) {
|
|
74512
|
+
const t = readFileSync45(path104, "utf8").trim();
|
|
74283
74513
|
if (t) return { token: t, created: false };
|
|
74284
74514
|
}
|
|
74285
74515
|
const token = randomBytes7(24).toString("base64url");
|
|
74286
|
-
writeFileSync26(
|
|
74516
|
+
writeFileSync26(path104, token + "\n", "utf8");
|
|
74287
74517
|
try {
|
|
74288
74518
|
const fs50 = __require("node:fs");
|
|
74289
|
-
fs50.chmodSync?.(
|
|
74519
|
+
fs50.chmodSync?.(path104, 384);
|
|
74290
74520
|
} catch {
|
|
74291
74521
|
}
|
|
74292
74522
|
return { token, created: true };
|
|
@@ -74311,17 +74541,17 @@ function mergeProjects(cfg, extraPaths) {
|
|
|
74311
74541
|
byId.set(p3.id, p3);
|
|
74312
74542
|
}
|
|
74313
74543
|
for (const raw of extraPaths) {
|
|
74314
|
-
const
|
|
74315
|
-
if (!
|
|
74316
|
-
let id3 = slugFromPath(
|
|
74544
|
+
const path104 = raw.trim();
|
|
74545
|
+
if (!path104) continue;
|
|
74546
|
+
let id3 = slugFromPath(path104);
|
|
74317
74547
|
let n = 2;
|
|
74318
|
-
while (byId.has(id3) && byId.get(id3).path !==
|
|
74319
|
-
id3 = `${slugFromPath(
|
|
74548
|
+
while (byId.has(id3) && byId.get(id3).path !== path104) {
|
|
74549
|
+
id3 = `${slugFromPath(path104)}-${n++}`;
|
|
74320
74550
|
}
|
|
74321
74551
|
byId.set(id3, {
|
|
74322
74552
|
id: id3,
|
|
74323
|
-
name: slugFromPath(
|
|
74324
|
-
path:
|
|
74553
|
+
name: slugFromPath(path104),
|
|
74554
|
+
path: path104
|
|
74325
74555
|
});
|
|
74326
74556
|
}
|
|
74327
74557
|
return [...byId.values()];
|
|
@@ -74407,11 +74637,11 @@ function createServePermissionBridge(write, timeoutMs2 = 12e4) {
|
|
|
74407
74637
|
onPermissionAsk(payload) {
|
|
74408
74638
|
const requestId = `perm-${Date.now()}-${++seq}`;
|
|
74409
74639
|
const categories = payload.categories && payload.categories.length > 0 ? payload.categories : payload.category ? payload.category.split(",").map((c) => c.trim()).filter(Boolean) : [];
|
|
74410
|
-
return new Promise((
|
|
74640
|
+
return new Promise((resolve10) => {
|
|
74411
74641
|
const timer = setTimeout(() => {
|
|
74412
74642
|
settle(requestId, "deny", true);
|
|
74413
74643
|
}, timeoutMs2);
|
|
74414
|
-
pending.set(requestId, { resolve:
|
|
74644
|
+
pending.set(requestId, { resolve: resolve10, timer, payload });
|
|
74415
74645
|
write(
|
|
74416
74646
|
JSON.stringify({
|
|
74417
74647
|
type: "permission.request",
|
|
@@ -74521,11 +74751,11 @@ function createServeAskUserBridge(write, timeoutMs2 = askUserTimeoutMs()) {
|
|
|
74521
74751
|
const choices = req.choices.map((c) => c.trim()).filter(Boolean);
|
|
74522
74752
|
if (choices.length < 2) return Promise.resolve(null);
|
|
74523
74753
|
const requestId = `ask-${Date.now()}-${++seq}`;
|
|
74524
|
-
return new Promise((
|
|
74754
|
+
return new Promise((resolve10) => {
|
|
74525
74755
|
const timer = setTimeout(() => {
|
|
74526
74756
|
settle(requestId, null, true);
|
|
74527
74757
|
}, timeoutMs2);
|
|
74528
|
-
pending.set(requestId, { resolve:
|
|
74758
|
+
pending.set(requestId, { resolve: resolve10, timer });
|
|
74529
74759
|
write(
|
|
74530
74760
|
JSON.stringify({
|
|
74531
74761
|
type: "ask_user.request",
|
|
@@ -74625,11 +74855,13 @@ __export(harnessServer_exports, {
|
|
|
74625
74855
|
bindHarnessTurnOptions: () => bindHarnessTurnOptions,
|
|
74626
74856
|
createCliRunTurn: () => createCliRunTurn,
|
|
74627
74857
|
createCliWorkspaceServices: () => createCliWorkspaceServices,
|
|
74858
|
+
resolveSessionCreateRoot: () => resolveSessionCreateRoot,
|
|
74628
74859
|
resolveTurnLspProvider: () => resolveTurnLspProvider,
|
|
74629
74860
|
runHarnessServer: () => runHarnessServer,
|
|
74630
74861
|
startHarnessServer: () => startHarnessServer
|
|
74631
74862
|
});
|
|
74632
74863
|
import { createInterface as createInterface3 } from "node:readline";
|
|
74864
|
+
import path99 from "node:path";
|
|
74633
74865
|
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
74634
74866
|
function createCliWorkspaceServices(workspaceRoot) {
|
|
74635
74867
|
const mode = activePolicyLoadMode();
|
|
@@ -74655,6 +74887,23 @@ function createCliWorkspaceServices(workspaceRoot) {
|
|
|
74655
74887
|
}
|
|
74656
74888
|
};
|
|
74657
74889
|
}
|
|
74890
|
+
function resolveSessionCreateRoot(params, cwd = process.cwd()) {
|
|
74891
|
+
const raw = params.workspaceRoot;
|
|
74892
|
+
if (typeof raw !== "string" || raw.trim() === "") {
|
|
74893
|
+
return {
|
|
74894
|
+
ok: false,
|
|
74895
|
+
message: "session.create requires a non-empty string `workspaceRoot` (the sidecar never substitutes its own cwd: sessions on different workspaces must stay isolated)"
|
|
74896
|
+
};
|
|
74897
|
+
}
|
|
74898
|
+
const root = raw.trim();
|
|
74899
|
+
if (!path99.isAbsolute(root)) {
|
|
74900
|
+
return {
|
|
74901
|
+
ok: false,
|
|
74902
|
+
message: `session.create workspaceRoot must be an absolute path (got '${root}') \u2014 a relative root would resolve against the sidecar cwd (${cwd}) and mix conversations (ADR-0016)`
|
|
74903
|
+
};
|
|
74904
|
+
}
|
|
74905
|
+
return { ok: true, root };
|
|
74906
|
+
}
|
|
74658
74907
|
function bindHarnessTurnOptions(input, workspaceRoot) {
|
|
74659
74908
|
const turnInput = input;
|
|
74660
74909
|
if (typeof turnInput.task !== "string" || turnInput.task.length === 0) {
|
|
@@ -74760,9 +75009,12 @@ function startHarnessServer(options = {}) {
|
|
|
74760
75009
|
};
|
|
74761
75010
|
}
|
|
74762
75011
|
case "session.create": {
|
|
74763
|
-
const
|
|
75012
|
+
const resolved = resolveSessionCreateRoot(params);
|
|
75013
|
+
if (!resolved.ok) {
|
|
75014
|
+
return { id: req.id ?? null, ok: false, error: { code: "bad_request", message: resolved.message } };
|
|
75015
|
+
}
|
|
74764
75016
|
const session = server.createSession({
|
|
74765
|
-
workspaceRoot: root,
|
|
75017
|
+
workspaceRoot: resolved.root,
|
|
74766
75018
|
runTurn: options.runTurn ?? createCliRunTurn(
|
|
74767
75019
|
asRegistryAskHandler(permissionBridge),
|
|
74768
75020
|
askUserBridge.onAskUser
|
|
@@ -74984,8 +75236,8 @@ var init_harnessClient = __esm({
|
|
|
74984
75236
|
);
|
|
74985
75237
|
}
|
|
74986
75238
|
const id3 = this.nextId++;
|
|
74987
|
-
return new Promise((
|
|
74988
|
-
this.pending.set(id3, { resolve:
|
|
75239
|
+
return new Promise((resolve10, reject) => {
|
|
75240
|
+
this.pending.set(id3, { resolve: resolve10, reject });
|
|
74989
75241
|
this.transport.write(JSON.stringify({ id: id3, method, params }));
|
|
74990
75242
|
});
|
|
74991
75243
|
}
|
|
@@ -75480,8 +75732,8 @@ __export(serve_exports, {
|
|
|
75480
75732
|
runCompanionServe: () => runCompanionServe
|
|
75481
75733
|
});
|
|
75482
75734
|
import { createServer as createServer3 } from "node:http";
|
|
75483
|
-
import { existsSync as
|
|
75484
|
-
import { resolve as
|
|
75735
|
+
import { existsSync as existsSync62 } from "node:fs";
|
|
75736
|
+
import { resolve as resolve9 } from "node:path";
|
|
75485
75737
|
function readBody(req, max = 2e6) {
|
|
75486
75738
|
return new Promise((resolveBody, reject) => {
|
|
75487
75739
|
const chunks = [];
|
|
@@ -75528,8 +75780,8 @@ async function runCompanionServe(opts = {}) {
|
|
|
75528
75780
|
const { token, created } = loadOrCreateToken(opts.token);
|
|
75529
75781
|
let projects = mergeProjects(fileCfg, opts.projects ?? []);
|
|
75530
75782
|
projects = projects.filter((p3) => {
|
|
75531
|
-
const abs =
|
|
75532
|
-
if (!
|
|
75783
|
+
const abs = resolve9(p3.path);
|
|
75784
|
+
if (!existsSync62(abs)) {
|
|
75533
75785
|
process.stderr.write(
|
|
75534
75786
|
`[zelari-code serve] skip missing project path: ${p3.path}
|
|
75535
75787
|
`
|
|
@@ -75548,7 +75800,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
75548
75800
|
});
|
|
75549
75801
|
}
|
|
75550
75802
|
if (projects.length === 0) {
|
|
75551
|
-
const cwd =
|
|
75803
|
+
const cwd = resolve9(process.cwd());
|
|
75552
75804
|
projects = [
|
|
75553
75805
|
{
|
|
75554
75806
|
id: "default",
|
|
@@ -75580,9 +75832,9 @@ async function runCompanionServe(opts = {}) {
|
|
|
75580
75832
|
return;
|
|
75581
75833
|
}
|
|
75582
75834
|
const url2 = parseUrl(req);
|
|
75583
|
-
const
|
|
75835
|
+
const path104 = url2.pathname.replace(/\/+$/, "") || "/";
|
|
75584
75836
|
try {
|
|
75585
|
-
if (req.method === "GET" && (
|
|
75837
|
+
if (req.method === "GET" && (path104 === "/health" || path104 === "/v1/health")) {
|
|
75586
75838
|
sendJson2(res, 200, {
|
|
75587
75839
|
ok: true,
|
|
75588
75840
|
service: "zelari-companion",
|
|
@@ -75594,18 +75846,18 @@ async function runCompanionServe(opts = {}) {
|
|
|
75594
75846
|
});
|
|
75595
75847
|
return;
|
|
75596
75848
|
}
|
|
75597
|
-
if (
|
|
75849
|
+
if (path104.startsWith("/v1")) {
|
|
75598
75850
|
if (!tokenMatches(token, getBearer(req))) {
|
|
75599
75851
|
sendJson2(res, 401, { ok: false, error: "unauthorized" });
|
|
75600
75852
|
return;
|
|
75601
75853
|
}
|
|
75602
75854
|
}
|
|
75603
|
-
if (req.method === "GET" &&
|
|
75855
|
+
if (req.method === "GET" && path104 === "/v1/config") {
|
|
75604
75856
|
const snap = buildDesktopConfigSnapshot();
|
|
75605
75857
|
sendJson2(res, 200, { ok: true, ...snap });
|
|
75606
75858
|
return;
|
|
75607
75859
|
}
|
|
75608
|
-
if (req.method === "GET" &&
|
|
75860
|
+
if (req.method === "GET" && path104 === "/v1/projects") {
|
|
75609
75861
|
sendJson2(res, 200, {
|
|
75610
75862
|
ok: true,
|
|
75611
75863
|
projects: projects.map((p3) => ({
|
|
@@ -75616,7 +75868,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
75616
75868
|
});
|
|
75617
75869
|
return;
|
|
75618
75870
|
}
|
|
75619
|
-
if (req.method === "GET" &&
|
|
75871
|
+
if (req.method === "GET" && path104 === "/v1/runs") {
|
|
75620
75872
|
sendJson2(res, 200, {
|
|
75621
75873
|
ok: true,
|
|
75622
75874
|
active: runs.getActive(),
|
|
@@ -75634,7 +75886,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
75634
75886
|
});
|
|
75635
75887
|
return;
|
|
75636
75888
|
}
|
|
75637
|
-
if (req.method === "POST" &&
|
|
75889
|
+
if (req.method === "POST" && path104 === "/v1/runs") {
|
|
75638
75890
|
const raw = await readBody(req);
|
|
75639
75891
|
let body = {};
|
|
75640
75892
|
try {
|
|
@@ -75682,7 +75934,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
75682
75934
|
});
|
|
75683
75935
|
return;
|
|
75684
75936
|
}
|
|
75685
|
-
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(
|
|
75937
|
+
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path104);
|
|
75686
75938
|
if (req.method === "GET" && eventsMatch) {
|
|
75687
75939
|
const runId = eventsMatch[1];
|
|
75688
75940
|
const run = runs.getRun(runId);
|
|
@@ -75747,7 +75999,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
75747
75999
|
}, 500);
|
|
75748
76000
|
return;
|
|
75749
76001
|
}
|
|
75750
|
-
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(
|
|
76002
|
+
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path104);
|
|
75751
76003
|
if (req.method === "POST" && cancelMatch) {
|
|
75752
76004
|
const runId = cancelMatch[1];
|
|
75753
76005
|
const result = runs.cancel(runId);
|
|
@@ -75758,7 +76010,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
75758
76010
|
sendJson2(res, 200, { ok: true, cancelled: runId });
|
|
75759
76011
|
return;
|
|
75760
76012
|
}
|
|
75761
|
-
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(
|
|
76013
|
+
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(path104);
|
|
75762
76014
|
if (req.method === "POST" && steerMatch) {
|
|
75763
76015
|
const runId = steerMatch[1];
|
|
75764
76016
|
const raw = await readBody(req);
|
|
@@ -75924,26 +76176,26 @@ __export(doctor_exports, {
|
|
|
75924
76176
|
runDoctor: () => runDoctor
|
|
75925
76177
|
});
|
|
75926
76178
|
import { execSync as execSync2 } from "node:child_process";
|
|
75927
|
-
import { existsSync as
|
|
76179
|
+
import { existsSync as existsSync63, readFileSync as readFileSync46, readlinkSync, statSync as statSync10 } from "node:fs";
|
|
75928
76180
|
import { createRequire as createRequire3 } from "node:module";
|
|
75929
76181
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
75930
|
-
import
|
|
76182
|
+
import path100 from "node:path";
|
|
75931
76183
|
function findPackageRoot(start) {
|
|
75932
76184
|
let dir = start;
|
|
75933
76185
|
for (let i = 0; i < 6; i += 1) {
|
|
75934
|
-
const candidate =
|
|
75935
|
-
if (
|
|
76186
|
+
const candidate = path100.join(dir, "package.json");
|
|
76187
|
+
if (existsSync63(candidate)) {
|
|
75936
76188
|
try {
|
|
75937
76189
|
const pkg = JSON.parse(readFileSync46(candidate, "utf8"));
|
|
75938
76190
|
if (pkg.name === "zelari-code") return dir;
|
|
75939
76191
|
} catch {
|
|
75940
76192
|
}
|
|
75941
76193
|
}
|
|
75942
|
-
const parent =
|
|
76194
|
+
const parent = path100.dirname(dir);
|
|
75943
76195
|
if (parent === dir) break;
|
|
75944
76196
|
dir = parent;
|
|
75945
76197
|
}
|
|
75946
|
-
return
|
|
76198
|
+
return path100.resolve(__dirname3, "..", "..", "..");
|
|
75947
76199
|
}
|
|
75948
76200
|
function tryExec(cmd) {
|
|
75949
76201
|
try {
|
|
@@ -75957,7 +76209,7 @@ function tryExec(cmd) {
|
|
|
75957
76209
|
}
|
|
75958
76210
|
function readPackageJson4() {
|
|
75959
76211
|
try {
|
|
75960
|
-
const pkgPath =
|
|
76212
|
+
const pkgPath = path100.join(packageRoot, "package.json");
|
|
75961
76213
|
return JSON.parse(readFileSync46(pkgPath, "utf8"));
|
|
75962
76214
|
} catch {
|
|
75963
76215
|
return null;
|
|
@@ -75969,7 +76221,7 @@ function getGlobalPrefix() {
|
|
|
75969
76221
|
return (process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX || "").trim();
|
|
75970
76222
|
}
|
|
75971
76223
|
function isSourceCheckout() {
|
|
75972
|
-
return
|
|
76224
|
+
return existsSync63(path100.join(packageRoot, "src", "cli", "main.ts")) && existsSync63(path100.join(packageRoot, "apps", "desktop", "package.json"));
|
|
75973
76225
|
}
|
|
75974
76226
|
function checkShim(pkgName) {
|
|
75975
76227
|
const prefix = getGlobalPrefix();
|
|
@@ -75978,10 +76230,10 @@ function checkShim(pkgName) {
|
|
|
75978
76230
|
}
|
|
75979
76231
|
const isWin = process.platform === "win32";
|
|
75980
76232
|
const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
|
|
75981
|
-
const shimPath =
|
|
75982
|
-
if (!
|
|
75983
|
-
const localBin =
|
|
75984
|
-
if (isSourceCheckout() &&
|
|
76233
|
+
const shimPath = path100.join(prefix, shimName);
|
|
76234
|
+
if (!existsSync63(shimPath)) {
|
|
76235
|
+
const localBin = path100.join(packageRoot, "bin", "zelari-code.js");
|
|
76236
|
+
if (isSourceCheckout() && existsSync63(localBin)) {
|
|
75985
76237
|
return WARN(
|
|
75986
76238
|
`global shim not found at ${shimPath}
|
|
75987
76239
|
source checkout \u2014 using ${localBin}
|
|
@@ -76014,8 +76266,8 @@ function checkShim(pkgName) {
|
|
|
76014
76266
|
fix: npm install -g ${pkgName}@latest --force`
|
|
76015
76267
|
);
|
|
76016
76268
|
}
|
|
76017
|
-
const resolved =
|
|
76018
|
-
const expected =
|
|
76269
|
+
const resolved = path100.resolve(path100.dirname(shimPath), target);
|
|
76270
|
+
const expected = path100.join(
|
|
76019
76271
|
prefix,
|
|
76020
76272
|
"node_modules",
|
|
76021
76273
|
pkgName,
|
|
@@ -76057,8 +76309,8 @@ function checkNode(pkg) {
|
|
|
76057
76309
|
return OK(`node ${raw} (engines.node ${enginesNode ?? ">= 20.0.0"})`);
|
|
76058
76310
|
}
|
|
76059
76311
|
function checkBundle() {
|
|
76060
|
-
const bundle =
|
|
76061
|
-
if (!
|
|
76312
|
+
const bundle = path100.join(packageRoot, "dist", "cli", "main.bundled.js");
|
|
76313
|
+
if (!existsSync63(bundle)) {
|
|
76062
76314
|
return FAIL(
|
|
76063
76315
|
`dist/cli/main.bundled.js missing at ${bundle}
|
|
76064
76316
|
fix: npm run build:cli (then reinstall or run via tsx)`
|
|
@@ -76078,7 +76330,7 @@ function checkRuntimeDeps() {
|
|
|
76078
76330
|
const missing = [];
|
|
76079
76331
|
for (const dep of required2) {
|
|
76080
76332
|
try {
|
|
76081
|
-
const localReq = createRequire3(
|
|
76333
|
+
const localReq = createRequire3(path100.join(packageRoot, "package.json"));
|
|
76082
76334
|
localReq.resolve(dep);
|
|
76083
76335
|
} catch {
|
|
76084
76336
|
missing.push(dep);
|
|
@@ -76355,7 +76607,7 @@ var init_doctor = __esm({
|
|
|
76355
76607
|
init_metrics3();
|
|
76356
76608
|
init_contextGrowthSummary();
|
|
76357
76609
|
require3 = createRequire3(import.meta.url);
|
|
76358
|
-
__dirname3 =
|
|
76610
|
+
__dirname3 = path100.dirname(fileURLToPath3(import.meta.url));
|
|
76359
76611
|
packageRoot = findPackageRoot(__dirname3);
|
|
76360
76612
|
OK = (message) => ({
|
|
76361
76613
|
ok: true,
|
|
@@ -76463,8 +76715,8 @@ __export(userSettings_exports, {
|
|
|
76463
76715
|
resolveUserSettings: () => resolveUserSettings,
|
|
76464
76716
|
settingsOverrides: () => settingsOverrides
|
|
76465
76717
|
});
|
|
76466
|
-
import { existsSync as
|
|
76467
|
-
import
|
|
76718
|
+
import { existsSync as existsSync64, readFileSync as readFileSync47 } from "node:fs";
|
|
76719
|
+
import path101 from "node:path";
|
|
76468
76720
|
function parseBool(raw) {
|
|
76469
76721
|
const v = raw.trim().toLowerCase();
|
|
76470
76722
|
if (["1", "true", "yes", "on"].includes(v)) return true;
|
|
@@ -76479,7 +76731,7 @@ function parseEnum(values, raw) {
|
|
|
76479
76731
|
return values.includes(v) ? v : void 0;
|
|
76480
76732
|
}
|
|
76481
76733
|
function loadFileLayer(file2, origin, warnings) {
|
|
76482
|
-
if (!
|
|
76734
|
+
if (!existsSync64(file2)) return {};
|
|
76483
76735
|
let raw;
|
|
76484
76736
|
try {
|
|
76485
76737
|
raw = readFileSync47(file2, "utf8");
|
|
@@ -76531,8 +76783,8 @@ function envValueFor(key, env) {
|
|
|
76531
76783
|
function resolveUserSettings(opts = {}) {
|
|
76532
76784
|
const cwd = opts.cwd ?? process.cwd();
|
|
76533
76785
|
const env = opts.env ?? process.env;
|
|
76534
|
-
const userPath =
|
|
76535
|
-
const projectPath =
|
|
76786
|
+
const userPath = path101.join(zelariHome(), SETTINGS_FILE_NAME);
|
|
76787
|
+
const projectPath = path101.join(cwd, ".zelari", SETTINGS_FILE_NAME);
|
|
76536
76788
|
const warnings = [];
|
|
76537
76789
|
const userLayer = loadFileLayer(userPath, "user", warnings);
|
|
76538
76790
|
const projectLayer = loadFileLayer(projectPath, "project", warnings);
|
|
@@ -76590,8 +76842,8 @@ function printSettingsReport(opts = {}) {
|
|
|
76590
76842
|
}
|
|
76591
76843
|
lines.push("");
|
|
76592
76844
|
lines.push("layers:");
|
|
76593
|
-
lines.push(` user: ${r.userPath} (${
|
|
76594
|
-
lines.push(` project: ${r.projectPath} (${
|
|
76845
|
+
lines.push(` user: ${r.userPath} (${existsSync64(r.userPath) ? "loaded" : "not found"})`);
|
|
76846
|
+
lines.push(` project: ${r.projectPath} (${existsSync64(r.projectPath) ? "loaded" : "not found"})`);
|
|
76595
76847
|
if (r.warnings.length > 0) {
|
|
76596
76848
|
lines.push("");
|
|
76597
76849
|
lines.push("warnings:");
|
|
@@ -76746,8 +76998,8 @@ __export(inspectSession_exports, {
|
|
|
76746
76998
|
renderInspectReport: () => renderInspectReport,
|
|
76747
76999
|
runInspectSession: () => runInspectSession
|
|
76748
77000
|
});
|
|
76749
|
-
import
|
|
76750
|
-
import { existsSync as
|
|
77001
|
+
import path102 from "node:path";
|
|
77002
|
+
import { existsSync as existsSync65 } from "node:fs";
|
|
76751
77003
|
function formatLimit(limit) {
|
|
76752
77004
|
return `${Math.round(limit / 1e3)}k`;
|
|
76753
77005
|
}
|
|
@@ -76780,13 +77032,13 @@ function renderInspectReport(state3) {
|
|
|
76780
77032
|
}
|
|
76781
77033
|
async function runInspectSession(opts) {
|
|
76782
77034
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.cwd ?? process.cwd() });
|
|
76783
|
-
const sessionDir =
|
|
76784
|
-
const eventsPath =
|
|
76785
|
-
if (!
|
|
77035
|
+
const sessionDir = path102.join(sessionsDir2, opts.sessionId);
|
|
77036
|
+
const eventsPath = path102.join(sessionDir, "events.jsonl");
|
|
77037
|
+
if (!existsSync65(sessionDir)) {
|
|
76786
77038
|
console.error(`zelari-code inspect: no session directory at ${sessionDir}`);
|
|
76787
77039
|
return 1;
|
|
76788
77040
|
}
|
|
76789
|
-
if (!
|
|
77041
|
+
if (!existsSync65(eventsPath)) {
|
|
76790
77042
|
console.error(`zelari-code inspect: session directory has no events.jsonl at ${eventsPath}`);
|
|
76791
77043
|
return 1;
|
|
76792
77044
|
}
|
|
@@ -76815,14 +77067,14 @@ __export(inspect_exports, {
|
|
|
76815
77067
|
collectInspectReport: () => collectInspectReport,
|
|
76816
77068
|
runInspect: () => runInspect
|
|
76817
77069
|
});
|
|
76818
|
-
import
|
|
76819
|
-
import { existsSync as
|
|
77070
|
+
import path103 from "node:path";
|
|
77071
|
+
import { existsSync as existsSync66, readFileSync as readFileSync48, readdirSync as readdirSync13 } from "node:fs";
|
|
76820
77072
|
async function collectInspectReport(cwd = process.cwd()) {
|
|
76821
77073
|
ensureBuiltinSkillsLoadedSync();
|
|
76822
77074
|
const snap = listSkillsSnapshot(cwd);
|
|
76823
77075
|
const mcp = listMcpServers(cwd);
|
|
76824
|
-
const userMcpPath =
|
|
76825
|
-
const projectMcpPath =
|
|
77076
|
+
const userMcpPath = path103.join(zelariHome(), "mcp.json");
|
|
77077
|
+
const projectMcpPath = path103.join(cwd, ".zelari", "mcp.json");
|
|
76826
77078
|
const globalHooks = globalHooksDir();
|
|
76827
77079
|
const projectHooks = projectHooksDir(cwd);
|
|
76828
77080
|
const projectTrusted = isFolderTrusted(cwd);
|
|
@@ -76848,11 +77100,11 @@ async function collectInspectReport(cwd = process.cwd()) {
|
|
|
76848
77100
|
folders: listTrustedFolders()
|
|
76849
77101
|
},
|
|
76850
77102
|
configSources: [
|
|
76851
|
-
{ path: userMcpPath, exists:
|
|
76852
|
-
{ path: projectMcpPath, exists:
|
|
76853
|
-
{ path:
|
|
76854
|
-
{ path:
|
|
76855
|
-
{ path:
|
|
77103
|
+
{ path: userMcpPath, exists: existsSync66(userMcpPath) },
|
|
77104
|
+
{ path: projectMcpPath, exists: existsSync66(projectMcpPath) },
|
|
77105
|
+
{ path: path103.join(zelariHome(), "provider.json"), exists: existsSync66(path103.join(zelariHome(), "provider.json")) },
|
|
77106
|
+
{ path: path103.join(cwd, ".zelari", "AGENTS.md"), exists: existsSync66(path103.join(cwd, ".zelari", "AGENTS.md")) },
|
|
77107
|
+
{ path: path103.join(cwd, "AGENTS.md"), exists: existsSync66(path103.join(cwd, "AGENTS.md")) }
|
|
76856
77108
|
],
|
|
76857
77109
|
skills: {
|
|
76858
77110
|
total: snap.skills.length,
|
|
@@ -76865,7 +77117,7 @@ async function collectInspectReport(cwd = process.cwd()) {
|
|
|
76865
77117
|
user: mcp.servers.filter((s) => s.scope === "user").map((s) => ({ name: s.name, enabled: s.enabled !== false })),
|
|
76866
77118
|
project: mcp.servers.filter((s) => s.scope === "project").map((s) => ({ name: s.name, enabled: s.enabled !== false })),
|
|
76867
77119
|
projectTrusted,
|
|
76868
|
-
projectConfigExists:
|
|
77120
|
+
projectConfigExists: existsSync66(projectMcpPath)
|
|
76869
77121
|
},
|
|
76870
77122
|
hooks: {
|
|
76871
77123
|
global: {
|
|
@@ -76892,12 +77144,12 @@ function listJsonFiles(dir) {
|
|
|
76892
77144
|
}
|
|
76893
77145
|
function findAgentsMd(cwd) {
|
|
76894
77146
|
const candidates = [
|
|
76895
|
-
|
|
76896
|
-
|
|
77147
|
+
path103.join(cwd, "AGENTS.md"),
|
|
77148
|
+
path103.join(cwd, ".zelari", "AGENTS.md")
|
|
76897
77149
|
];
|
|
76898
77150
|
const found = [];
|
|
76899
77151
|
for (const c of candidates) {
|
|
76900
|
-
if (
|
|
77152
|
+
if (existsSync66(c)) {
|
|
76901
77153
|
try {
|
|
76902
77154
|
const text = readFileSync48(c, "utf8");
|
|
76903
77155
|
found.push(`${c} (${text.length} bytes)`);
|
|
@@ -77352,12 +77604,12 @@ function mergeChanges(unstaged, staged, untrackedPaths) {
|
|
|
77352
77604
|
return [...byPath.values()].sort((a, b) => churn(b) - churn(a));
|
|
77353
77605
|
}
|
|
77354
77606
|
function runGit(args, cwd) {
|
|
77355
|
-
return new Promise((
|
|
77607
|
+
return new Promise((resolve10, reject) => {
|
|
77356
77608
|
execFile(
|
|
77357
77609
|
"git",
|
|
77358
77610
|
args,
|
|
77359
77611
|
{ cwd, timeout: 5e3, windowsHide: true, maxBuffer: 4 * 1024 * 1024 },
|
|
77360
|
-
(err, stdout) => err ? reject(err) :
|
|
77612
|
+
(err, stdout) => err ? reject(err) : resolve10(stdout)
|
|
77361
77613
|
);
|
|
77362
77614
|
});
|
|
77363
77615
|
}
|
|
@@ -79936,7 +80188,7 @@ init_toolPermissions();
|
|
|
79936
80188
|
init_askUserTimeout();
|
|
79937
80189
|
function createPermissionAskHandler(opts) {
|
|
79938
80190
|
const { setPicker: setPicker2, appendSystem: appendSystem2 } = opts;
|
|
79939
|
-
return (req) => new Promise((
|
|
80191
|
+
return (req) => new Promise((resolve10) => {
|
|
79940
80192
|
const cats = req.categories;
|
|
79941
80193
|
const catLabel = cats.length === 1 ? cats[0] : cats.join("+") || "action";
|
|
79942
80194
|
const title = `Allow tool "${req.toolName}"?`;
|
|
@@ -79962,7 +80214,7 @@ ${detail}${note}${claimsBlock}
|
|
|
79962
80214
|
cancelAskTimeout();
|
|
79963
80215
|
setPicker2(null);
|
|
79964
80216
|
if (note2) appendSystem2?.(note2, Date.now());
|
|
79965
|
-
|
|
80217
|
+
resolve10(ok);
|
|
79966
80218
|
};
|
|
79967
80219
|
cancelAskTimeout = armPickerTimeout(
|
|
79968
80220
|
() => finish2(
|
|
@@ -80161,10 +80413,10 @@ function useChatTurn(params) {
|
|
|
80161
80413
|
}
|
|
80162
80414
|
} catch {
|
|
80163
80415
|
}
|
|
80164
|
-
const onAskUser = setPicker2 ? (req) => new Promise((
|
|
80416
|
+
const onAskUser = setPicker2 ? (req) => new Promise((resolve10) => {
|
|
80165
80417
|
const choices = req.choices ?? [];
|
|
80166
80418
|
if (choices.length < 2) {
|
|
80167
|
-
|
|
80419
|
+
resolve10(null);
|
|
80168
80420
|
return;
|
|
80169
80421
|
}
|
|
80170
80422
|
setLastClarification({
|
|
@@ -80188,7 +80440,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
80188
80440
|
settled = true;
|
|
80189
80441
|
cancelAskTimeout();
|
|
80190
80442
|
setPicker2(null);
|
|
80191
|
-
|
|
80443
|
+
resolve10(value);
|
|
80192
80444
|
};
|
|
80193
80445
|
cancelAskTimeout = armPickerTimeout(
|
|
80194
80446
|
() => {
|
|
@@ -81134,10 +81386,10 @@ async function dispatchCouncilPromptImpl(text, deps, overrides = {}) {
|
|
|
81134
81386
|
const { composeProjectContext: composeProjectContext2 } = await Promise.resolve().then(() => (init_composeContext(), composeContext_exports));
|
|
81135
81387
|
const { FeedbackStore: FeedbackStore2 } = await Promise.resolve().then(() => (init_councilFeedback(), councilFeedback_exports));
|
|
81136
81388
|
const workPhase = getPhase();
|
|
81137
|
-
const onAskUserCouncil = setPicker2 ? (req) => new Promise((
|
|
81389
|
+
const onAskUserCouncil = setPicker2 ? (req) => new Promise((resolve10) => {
|
|
81138
81390
|
const choices = req.choices ?? [];
|
|
81139
81391
|
if (choices.length < 2) {
|
|
81140
|
-
|
|
81392
|
+
resolve10(null);
|
|
81141
81393
|
return;
|
|
81142
81394
|
}
|
|
81143
81395
|
setLastClarification({
|
|
@@ -81161,7 +81413,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
81161
81413
|
settled = true;
|
|
81162
81414
|
cancelAskTimeout();
|
|
81163
81415
|
setPicker2(null);
|
|
81164
|
-
|
|
81416
|
+
resolve10(value);
|
|
81165
81417
|
};
|
|
81166
81418
|
cancelAskTimeout = armPickerTimeout(
|
|
81167
81419
|
() => {
|
|
@@ -81343,10 +81595,10 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
81343
81595
|
appendSystem(setMessages, message, Date.now());
|
|
81344
81596
|
},
|
|
81345
81597
|
// v1.8.0: pause council when a member asks a structured question.
|
|
81346
|
-
onClarification: setPicker2 ? (req) => new Promise((
|
|
81598
|
+
onClarification: setPicker2 ? (req) => new Promise((resolve10) => {
|
|
81347
81599
|
const choices = req.choices ?? [];
|
|
81348
81600
|
if (choices.length < 2) {
|
|
81349
|
-
|
|
81601
|
+
resolve10(null);
|
|
81350
81602
|
return;
|
|
81351
81603
|
}
|
|
81352
81604
|
setLastClarification({
|
|
@@ -81367,7 +81619,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
81367
81619
|
if (settled) return;
|
|
81368
81620
|
settled = true;
|
|
81369
81621
|
setPicker2(null);
|
|
81370
|
-
|
|
81622
|
+
resolve10(value);
|
|
81371
81623
|
};
|
|
81372
81624
|
setPicker2({
|
|
81373
81625
|
kind: "clarification",
|
|
@@ -82025,10 +82277,10 @@ function usePermissionBroker(opts) {
|
|
|
82025
82277
|
setPicker: setPicker2,
|
|
82026
82278
|
appendSystem: (msg, at) => appendSystem(setMessages, msg, at ?? Date.now())
|
|
82027
82279
|
});
|
|
82028
|
-
const onQuestion = (req) => new Promise((
|
|
82280
|
+
const onQuestion = (req) => new Promise((resolve10) => {
|
|
82029
82281
|
const choices = (req.choices ?? []).map((c) => String(c).trim()).filter((c) => c.length > 0);
|
|
82030
82282
|
if (choices.length < 2) {
|
|
82031
|
-
|
|
82283
|
+
resolve10(null);
|
|
82032
82284
|
return;
|
|
82033
82285
|
}
|
|
82034
82286
|
let settled = false;
|
|
@@ -82038,7 +82290,7 @@ function usePermissionBroker(opts) {
|
|
|
82038
82290
|
settled = true;
|
|
82039
82291
|
cancelWaitTimeout?.();
|
|
82040
82292
|
setPicker2(null);
|
|
82041
|
-
|
|
82293
|
+
resolve10(value);
|
|
82042
82294
|
};
|
|
82043
82295
|
const waitTimeoutMs = askUserTimeoutMs();
|
|
82044
82296
|
cancelWaitTimeout = armPickerTimeout(() => {
|
|
@@ -82107,7 +82359,7 @@ init_mode();
|
|
|
82107
82359
|
init_ledger();
|
|
82108
82360
|
|
|
82109
82361
|
// src/cli/evolution/proposals.ts
|
|
82110
|
-
import { existsSync as
|
|
82362
|
+
import { existsSync as existsSync53, readFileSync as readFileSync40 } from "node:fs";
|
|
82111
82363
|
import path81 from "node:path";
|
|
82112
82364
|
var PROPOSALS_REL = path81.join(".zelari", "evolution", "proposals.jsonl");
|
|
82113
82365
|
function proposalsPath(cwd) {
|
|
@@ -82115,10 +82367,10 @@ function proposalsPath(cwd) {
|
|
|
82115
82367
|
}
|
|
82116
82368
|
function readProposalStore(cwd) {
|
|
82117
82369
|
const file2 = proposalsPath(cwd);
|
|
82118
|
-
if (!
|
|
82370
|
+
if (!existsSync53(file2)) return [];
|
|
82119
82371
|
let raw;
|
|
82120
82372
|
try {
|
|
82121
|
-
raw =
|
|
82373
|
+
raw = readFileSync40(file2, "utf8");
|
|
82122
82374
|
} catch {
|
|
82123
82375
|
return [];
|
|
82124
82376
|
}
|
|
@@ -84008,7 +84260,7 @@ async function handleKrakenFanout(ctx, raw) {
|
|
|
84008
84260
|
}
|
|
84009
84261
|
return;
|
|
84010
84262
|
}
|
|
84011
|
-
const absCsv =
|
|
84263
|
+
const absCsv = isAbsolute4(parsed.args.csv_path) ? parsed.args.csv_path : joinPath(ctx.cwd, parsed.args.csv_path);
|
|
84012
84264
|
try {
|
|
84013
84265
|
await fs39.access(absCsv);
|
|
84014
84266
|
} catch {
|
|
@@ -84044,7 +84296,7 @@ async function handleKrakenFanout(ctx, raw) {
|
|
|
84044
84296
|
);
|
|
84045
84297
|
}
|
|
84046
84298
|
}
|
|
84047
|
-
function
|
|
84299
|
+
function isAbsolute4(p3) {
|
|
84048
84300
|
return /^([A-Za-z]:[\\/]|[\\/])/.test(p3);
|
|
84049
84301
|
}
|
|
84050
84302
|
function joinPath(a, b) {
|
|
@@ -84416,7 +84668,7 @@ ${browsers.output}` : "") + (browsers.ok ? "" : `
|
|
|
84416
84668
|
return result;
|
|
84417
84669
|
}
|
|
84418
84670
|
function runPlaywrightInstallChromium(cwd, executor) {
|
|
84419
|
-
return new Promise((
|
|
84671
|
+
return new Promise((resolve10) => {
|
|
84420
84672
|
let stdout = "";
|
|
84421
84673
|
let stderr = "";
|
|
84422
84674
|
const stdio = ["ignore", "pipe", "pipe"];
|
|
@@ -84429,7 +84681,7 @@ function runPlaywrightInstallChromium(cwd, executor) {
|
|
|
84429
84681
|
stderr += chunk.toString();
|
|
84430
84682
|
});
|
|
84431
84683
|
child.on("error", (err) => {
|
|
84432
|
-
|
|
84684
|
+
resolve10({
|
|
84433
84685
|
ok: false,
|
|
84434
84686
|
output: stdout + stderr,
|
|
84435
84687
|
error: err.message,
|
|
@@ -84438,7 +84690,7 @@ function runPlaywrightInstallChromium(cwd, executor) {
|
|
|
84438
84690
|
});
|
|
84439
84691
|
child.on("close", (code) => {
|
|
84440
84692
|
const ok = code === 0;
|
|
84441
|
-
|
|
84693
|
+
resolve10({
|
|
84442
84694
|
ok,
|
|
84443
84695
|
output: stdout + stderr,
|
|
84444
84696
|
exitCode: code,
|
|
@@ -84448,7 +84700,7 @@ function runPlaywrightInstallChromium(cwd, executor) {
|
|
|
84448
84700
|
});
|
|
84449
84701
|
}
|
|
84450
84702
|
function runNpm2(executor, args, cwd, mode, npmCliPath) {
|
|
84451
|
-
return new Promise((
|
|
84703
|
+
return new Promise((resolve10) => {
|
|
84452
84704
|
let stdout = "";
|
|
84453
84705
|
let stderr = "";
|
|
84454
84706
|
const stdio = ["ignore", "pipe", "pipe"];
|
|
@@ -84460,7 +84712,7 @@ function runNpm2(executor, args, cwd, mode, npmCliPath) {
|
|
|
84460
84712
|
stderr += chunk.toString();
|
|
84461
84713
|
});
|
|
84462
84714
|
child.on("error", (err) => {
|
|
84463
|
-
|
|
84715
|
+
resolve10({
|
|
84464
84716
|
ok: false,
|
|
84465
84717
|
output: stdout + stderr,
|
|
84466
84718
|
error: err.message,
|
|
@@ -84469,7 +84721,7 @@ function runNpm2(executor, args, cwd, mode, npmCliPath) {
|
|
|
84469
84721
|
});
|
|
84470
84722
|
child.on("close", (code) => {
|
|
84471
84723
|
const ok = code === 0;
|
|
84472
|
-
|
|
84724
|
+
resolve10({
|
|
84473
84725
|
ok,
|
|
84474
84726
|
output: stdout + stderr,
|
|
84475
84727
|
exitCode: code,
|
|
@@ -84568,7 +84820,7 @@ ${lineage}
|
|
|
84568
84820
|
|
|
84569
84821
|
// src/cli/branchManager.ts
|
|
84570
84822
|
init_paths();
|
|
84571
|
-
import { promises as fs42, existsSync as
|
|
84823
|
+
import { promises as fs42, existsSync as existsSync57, readFileSync as readFileSync42, writeFileSync as writeFileSync25, mkdirSync as mkdirSync22, statSync as statSync7, rmSync as rmSync4 } from "node:fs";
|
|
84572
84824
|
import path88 from "node:path";
|
|
84573
84825
|
var META_FILENAME = "meta.json";
|
|
84574
84826
|
var SESSIONS_SUBDIR = "sessions";
|
|
@@ -84589,11 +84841,11 @@ function sessionsPathFor(name, baseDir) {
|
|
|
84589
84841
|
}
|
|
84590
84842
|
function readBranchMeta(name, baseDir) {
|
|
84591
84843
|
const metaPath = metaPathFor(name, baseDir);
|
|
84592
|
-
if (!
|
|
84844
|
+
if (!existsSync57(metaPath)) {
|
|
84593
84845
|
throw new BranchNotFoundError(`Branch "${name}" not found`);
|
|
84594
84846
|
}
|
|
84595
84847
|
try {
|
|
84596
|
-
const raw =
|
|
84848
|
+
const raw = readFileSync42(metaPath, "utf-8");
|
|
84597
84849
|
const parsed = JSON.parse(raw);
|
|
84598
84850
|
if (!parsed || typeof parsed !== "object" || typeof parsed.name !== "string" || typeof parsed.createdAt !== "number" || typeof parsed.fromSessionId !== "string") {
|
|
84599
84851
|
throw new BranchCorruptError(`Branch "${name}" meta.json is malformed`);
|
|
@@ -84610,8 +84862,8 @@ function readBranchMeta(name, baseDir) {
|
|
|
84610
84862
|
}
|
|
84611
84863
|
function writeBranchMeta(name, baseDir, meta3) {
|
|
84612
84864
|
const metaPath = metaPathFor(name, baseDir);
|
|
84613
|
-
|
|
84614
|
-
|
|
84865
|
+
mkdirSync22(path88.dirname(metaPath), { recursive: true });
|
|
84866
|
+
writeFileSync25(metaPath, JSON.stringify(meta3, null, 2), "utf-8");
|
|
84615
84867
|
}
|
|
84616
84868
|
async function countSessions(name, baseDir) {
|
|
84617
84869
|
const sessionsPath = sessionsPathFor(name, baseDir);
|
|
@@ -84649,7 +84901,7 @@ var SessionNotFoundError = class extends Error {
|
|
|
84649
84901
|
};
|
|
84650
84902
|
function branchExists(name, baseDir = getBranchesBaseDir()) {
|
|
84651
84903
|
const bp = branchPathFor(name, baseDir);
|
|
84652
|
-
return
|
|
84904
|
+
return existsSync57(bp) && existsSync57(metaPathFor(name, baseDir));
|
|
84653
84905
|
}
|
|
84654
84906
|
async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(), sessionsBaseDir = getSessionsBaseDir()) {
|
|
84655
84907
|
if (!name || name.trim().length === 0) {
|
|
@@ -84662,12 +84914,12 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
84662
84914
|
throw new BranchAlreadyExistsError(name);
|
|
84663
84915
|
}
|
|
84664
84916
|
const sourcePath = path88.join(sessionsBaseDir, `${fromSessionId}.jsonl`);
|
|
84665
|
-
if (!
|
|
84917
|
+
if (!existsSync57(sourcePath)) {
|
|
84666
84918
|
throw new SessionNotFoundError(`Source session "${fromSessionId}" not found at ${sourcePath}`);
|
|
84667
84919
|
}
|
|
84668
84920
|
const branchPath = branchPathFor(name, baseDir);
|
|
84669
84921
|
const branchSessionsPath = sessionsPathFor(name, baseDir);
|
|
84670
|
-
|
|
84922
|
+
mkdirSync22(branchSessionsPath, { recursive: true });
|
|
84671
84923
|
const destPath = path88.join(branchSessionsPath, `${fromSessionId}.jsonl`);
|
|
84672
84924
|
await fs42.copyFile(sourcePath, destPath);
|
|
84673
84925
|
const meta3 = {
|
|
@@ -84695,7 +84947,7 @@ async function listBranches(baseDir = getBranchesBaseDir()) {
|
|
|
84695
84947
|
const results = [];
|
|
84696
84948
|
for (const entry of entries) {
|
|
84697
84949
|
const metaPath = metaPathFor(entry, baseDir);
|
|
84698
|
-
if (!
|
|
84950
|
+
if (!existsSync57(metaPath)) continue;
|
|
84699
84951
|
try {
|
|
84700
84952
|
const meta3 = readBranchMeta(entry, baseDir);
|
|
84701
84953
|
const sessionCount = await countSessions(entry, baseDir);
|
|
@@ -84883,7 +85135,7 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
84883
85135
|
init_provider2();
|
|
84884
85136
|
|
|
84885
85137
|
// src/cli/skillHistory.ts
|
|
84886
|
-
import { promises as fs44, existsSync as
|
|
85138
|
+
import { promises as fs44, existsSync as existsSync58, statSync as statSync8, renameSync as renameSync6, appendFileSync as appendFileSync5, mkdirSync as mkdirSync23 } from "node:fs";
|
|
84887
85139
|
init_paths();
|
|
84888
85140
|
var SKILL_HISTORY_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
84889
85141
|
async function readSkillHistory(file2) {
|
|
@@ -86294,9 +86546,9 @@ init_metrics3();
|
|
|
86294
86546
|
init_providerConfig();
|
|
86295
86547
|
|
|
86296
86548
|
// src/cli/wizard/firstRun.ts
|
|
86297
|
-
import { existsSync as
|
|
86549
|
+
import { existsSync as existsSync60 } from "node:fs";
|
|
86298
86550
|
function shouldRunWizard(input) {
|
|
86299
|
-
const exists = input.exists ??
|
|
86551
|
+
const exists = input.exists ?? existsSync60;
|
|
86300
86552
|
if (input.hasResetConfigFlag) {
|
|
86301
86553
|
return { shouldRun: true, reason: "--reset-config flag forced wizard" };
|
|
86302
86554
|
}
|
|
@@ -86769,8 +87021,8 @@ function normalizeDraft(raw, sourceUrl, provider, model) {
|
|
|
86769
87021
|
let name = String(o.name ?? "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
86770
87022
|
if (!name || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) {
|
|
86771
87023
|
try {
|
|
86772
|
-
const
|
|
86773
|
-
name =
|
|
87024
|
+
const path104 = new URL(sourceUrl).pathname.split("/").filter(Boolean).pop()?.replace(/\.[a-z0-9]+$/i, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
87025
|
+
name = path104 && /^[a-z0-9]/.test(path104) ? path104 : "imported-skill";
|
|
86774
87026
|
} catch {
|
|
86775
87027
|
name = "imported-skill";
|
|
86776
87028
|
}
|
|
@@ -86933,7 +87185,7 @@ function runPreflight() {
|
|
|
86933
87185
|
}
|
|
86934
87186
|
async function backgroundUpdateCheck() {
|
|
86935
87187
|
if (process.env.ANATHEMA_DEV === "1") return;
|
|
86936
|
-
await new Promise((
|
|
87188
|
+
await new Promise((resolve10) => setTimeout(resolve10, 3e3));
|
|
86937
87189
|
try {
|
|
86938
87190
|
const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_updater(), updater_exports));
|
|
86939
87191
|
const info = await checkForUpdate2();
|
|
@@ -87183,7 +87435,7 @@ proposals: npm run evolve:propose \u2014 decisions in npm run evolve:decide (P1:
|
|
|
87183
87435
|
}
|
|
87184
87436
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
87185
87437
|
console.log(
|
|
87186
|
-
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor [--json] Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --inspect [--json] Unified project inspection (config, skills, MCP,\n hooks, plugins, AGENTS.md, trust status)\n --trust [path] Trust the cwd (or path) so project MCP + hooks load\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --fix-budget Set recommended ZELARI_MAX_TOOL_LOOP_HARD=180,\n ZELARI_MAX_TOOL_LOOP_ITERATIONS=60, ZELARI_CONTEXT_LIMIT=400000\n at User scope (prevents the agent stopping mid-task)\n --permission-mcp <socket> MCP stdio server for external agent permission prompts\n (spawned by claude --permission-prompt-tool)\n --memory-mcp Optional MCP stdio server for project memory\n --cwd <path> Trusted project root (requires ZELARI_MEMORY_MCP=1)\n --client-id <id> Stable local owner identity for private memories\n --memory-json <json> Read-only project-memory bridge for Zelari Desktop\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --mode kraken|council|zelari Dispatch mode (default: kraken; agent=alias)\n zelari/mission mode auto-scopes slices from open tasks in .zelari/plan.json\n --council Alias for --mode council\n --phase plan|build Work phase (default: build)\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n --profile <id> Capability profile (minimal/v1|kraken/v1|council/v1|mission/v1)\n --resume <id> Continue a 2.0 spine session\n --resume-mission Resume .zelari/mission-state.json (not the spine)\n --export-session <path> Write zelari-session-export/1 after the run\n --strict-done Evidence-based BUILD completion gate\n --allow-unverified Exit 0 when strict is ON but nothing could be verified (M1.2)\n --task-file <path> Read the task prompt from a file (Windows argv cap)\n --once Single-cycle run (cron/git-hook triggers, ADR-0014)\n --kraken-graph <goal> Plan + execute a Kraken task graph\n (variant: --kraken-graph-file <path>; kill-switch\n ZELARI_KRAKEN_GRAPH=0)\n --plan-only Serialize the graph plan to .zelari/radio/ and exit 0\n --run-plan <id> Execute a pre-built .zelari/radio/plan-<id>.json\n --gauntlet Host-driven gauntlet loop (builder/critic tentacles)\n --session-export <id> Print a portable 2.0 session export (no LLM)\n serve Companion host for Android/remote clients (Tailscale)\n --bind <ip> Listen address (default: 127.0.0.1; use Tailscale IP)\n --port <n> Port (default: 7421)\n --token <secret> Bearer token (default: ~/.zelari-code/companion.token)\n --project <path> Allowlisted project root (repeatable)\n --save-projects Persist --project list to companion.json\n --serve-harness Long-lived harness kernel for hosts (NDJSON JSON-RPC\n on stdin/stdout; Desktop/companion transport)\n --print-config Print provider/model config as JSON (no secrets)\n --print-settings Print zelari.config.json values + the origin of\n each (default < user < project < env)\n --permissions <p> Permission preset: strict | standard | yolo \u2014 changes\n category DEFAULTS only (env vars and policy files win)\n --evolve-status Evolution ledger stats (read-only; ADR-0036; the\n ledger is written only when ZELARI_EVOLUTION=shadow)\n --plugins-status JSON status of optional plugins (Playwright, eslint, \u2026)\n --plugins-install <id> Install plugin (playwright also fetches Chromium)\n --cwd <path> Workspace for -D installs (default: process.cwd())\n --set-config Persist provider/model/endpoint\n --provider <id> Set active provider\n --model <id> Set model for that provider\n --endpoint <url> Custom OpenAI-compatible base URL\n --endpoint-clear Remove custom endpoint override\n --thinking <spec> Thinking effort (auto|off|low|medium|high|budget:N)\n --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\n --login-oauth Start subscription OAuth (grok, chatgpt, anthropic)\n --provider <id> grok | chatgpt | anthropic\n --code <paste> Anthropic magic-link code (CODE#STATE)\n --no-browser Do not open the system browser\n --refresh-oauth Force-refresh an OAuth access token\n --provider <id> grok | chatgpt | anthropic\n --logout-oauth Clear stored OAuth credentials\n --provider <id> grok | chatgpt | anthropic\n --discover-models Refresh model list for a provider\n --provider <id> Provider (default: active)\n --print-mcp Print MCP server config (user + project)\n --cwd <path> Project root for .zelari/mcp.json\n --set-mcp Add/update an MCP server entry\n --name <id> Server name (required)\n --command <bin> Executable for stdio servers\n --url <endpoint> Streamable HTTP endpoint (e.g. UE 5.8 editor)\n --args <json> JSON array of args (stdio, optional)\n --timeout <ms> Per-server request timeout (http, optional)\n --scope user|project Default: user\n --enabled true|false Default: true\n --cwd <path> Required when scope=project\n --set-mcp-preset Install a named MCP preset (e.g. cua)\n --preset cua Cua Driver desktop computer-use (MCP)\n --preset unreal-mcp Unreal Engine 5.8+ editor (MCP over HTTP)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-mcp Remove an MCP server entry\n --name <id> --scope user|project [--cwd <path>]\n --print-skills Print skills (builtin + user + project)\n --cwd <path> Project root for .zelari/skills\n --set-skill Add/update a SKILL.md skill\n --name <id> Skill id (required)\n --description <t> One-line description (required)\n --body <text> Markdown instructions (required)\n --category <c> plan|refactor|debug|review|test|docs|ops|git|db|maint\n --tools <csv> Comma-separated required tools (optional)\n --cost <l> low|medium|high (default: medium)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-skill Remove a user/project SKILL.md\n --name <id> --scope user|project [--cwd <path>]\n --generate-skill-from-url Fetch URL + draft skill via model (JSON)\n --url <https://...> Required\n --provider <id> Override active provider\n --model <name> Override model for the selected provider\n --print-ssh-targets Print SSH deploy/monitor targets\n --set-ssh-target Upsert target (--json '{...}' or flags)\n --remove-ssh-target --id <id>\n --test-ssh-target --id <id> (BatchMode ssh true)\n --print-ssh-pubkey --path <private-or-.pub> (display public key)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n ZELARI_MEMORY_MCP=1 Enable the optional external memory MCP server\n ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
87438
|
+
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor [--json] Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --inspect [--json] Unified project inspection (config, skills, MCP,\n hooks, plugins, AGENTS.md, trust status)\n --trust [path] Trust the cwd (or path) so project MCP + hooks load\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --fix-budget Set recommended ZELARI_MAX_TOOL_LOOP_HARD=180,\n ZELARI_MAX_TOOL_LOOP_ITERATIONS=60, ZELARI_CONTEXT_LIMIT=400000\n at User scope (prevents the agent stopping mid-task)\n --permission-mcp <socket> MCP stdio server for external agent permission prompts\n (spawned by claude --permission-prompt-tool)\n --memory-mcp Optional MCP stdio server for project memory\n --cwd <path> Trusted project root (requires ZELARI_MEMORY_MCP=1)\n --client-id <id> Stable local owner identity for private memories\n --memory-json <json> Read-only project-memory bridge for Zelari Desktop\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --mode kraken|council|zelari Dispatch mode (default: kraken; agent=alias)\n zelari/mission mode auto-scopes slices from open tasks in .zelari/plan.json\n --council Alias for --mode council\n --phase plan|build Work phase (default: build)\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n --profile <id> Capability profile (minimal/v1|kraken/v1|council/v1|mission/v1)\n --resume <id> Continue a 2.0 spine session\n --resume-mission Resume .zelari/mission-state.json (not the spine)\n --export-session <path> Write zelari-session-export/1 after the run\n --strict-done Evidence-based BUILD completion gate\n --allow-unverified Exit 0 when strict is ON but nothing could be verified (M1.2)\n --task-file <path> Read the task prompt from a file (Windows argv cap)\n --once Single-cycle run (cron/git-hook triggers, ADR-0014)\n --kraken-graph <goal> Plan + execute a Kraken task graph\n (variant: --kraken-graph-file <path>; kill-switch\n ZELARI_KRAKEN_GRAPH=0)\n --plan-only Serialize the graph plan to .zelari/radio/ and exit 0\n --run-plan <id> Execute a pre-built .zelari/radio/plan-<id>.json\n --gauntlet Host-driven gauntlet loop (builder/critic tentacles)\n --session-export <id> Print a portable 2.0 session export (no LLM)\n serve Companion host for Android/remote clients (Tailscale)\n --bind <ip> Listen address (default: 127.0.0.1; use Tailscale IP)\n --port <n> Port (default: 7421)\n --token <secret> Bearer token (default: ~/.zelari-code/companion.token)\n --project <path> Allowlisted project root (repeatable)\n --save-projects Persist --project list to companion.json\n --serve-harness Long-lived harness kernel for hosts (NDJSON JSON-RPC\n on stdin/stdout; Desktop/companion transport)\n --print-config Print provider/model config as JSON (no secrets)\n --print-settings Print zelari.config.json values + the origin of\n each (default < user < project < env)\n --permissions <p> Permission preset: strict | standard | yolo \u2014 changes\n category DEFAULTS only (env vars and policy files win)\n --evolve-status Evolution ledger stats (read-only; ADR-0036; the\n ledger is written only when ZELARI_EVOLUTION=shadow)\n --plugins-status JSON status of optional plugins (Playwright, eslint, \u2026)\n --plugins-install <id> Install plugin (playwright also fetches Chromium)\n --cwd <path> Workspace for -D installs (default: process.cwd())\n --set-config Persist provider/model/endpoint\n --provider <id> Set active provider\n --model <id> Set model for that provider\n --endpoint <url> Custom OpenAI-compatible base URL\n --endpoint-clear Remove custom endpoint override\n --thinking <spec> Thinking effort (auto|off|low|medium|high|budget:N)\n --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\n --login-oauth Start subscription OAuth (grok, chatgpt, anthropic)\n --provider <id> grok | chatgpt | anthropic\n --code <paste> Anthropic magic-link code (CODE#STATE)\n --no-browser Do not open the system browser\n --refresh-oauth Force-refresh an OAuth access token\n --provider <id> grok | chatgpt | anthropic\n --logout-oauth Clear stored OAuth credentials\n --provider <id> grok | chatgpt | anthropic\n --discover-models Refresh model list for a provider\n --provider <id> Provider (default: active)\n --print-mcp Print MCP server config (user + project)\n --cwd <path> Project root for .zelari/mcp.json\n --set-mcp Add/update an MCP server entry\n --name <id> Server name (required)\n --command <bin> Executable for stdio servers\n --url <endpoint> Streamable HTTP endpoint (e.g. UE 5.8 editor)\n --args <json> JSON array of args (stdio, optional)\n --env <json|K=V> Env for the server: JSON object or KEY=VALUE,\n repeatable (omit to keep the stored env)\n --timeout <ms> Per-server request timeout (http, optional)\n --scope user|project Default: user\n --enabled true|false Default: true\n --cwd <path> Required when scope=project\n --set-mcp-preset Install a named MCP preset (e.g. cua)\n --preset cua Cua Driver desktop computer-use (MCP)\n --preset unreal-mcp Unreal Engine 5.8+ editor (MCP over HTTP)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-mcp Remove an MCP server entry\n --name <id> --scope user|project [--cwd <path>]\n --print-skills Print skills (builtin + user + project)\n --cwd <path> Project root for .zelari/skills\n --set-skill Add/update a SKILL.md skill\n --name <id> Skill id (required)\n --description <t> One-line description (required)\n --body <text> Markdown instructions (required)\n --category <c> plan|refactor|debug|review|test|docs|ops|git|db|maint\n --tools <csv> Comma-separated required tools (optional)\n --cost <l> low|medium|high (default: medium)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-skill Remove a user/project SKILL.md\n --name <id> --scope user|project [--cwd <path>]\n --generate-skill-from-url Fetch URL + draft skill via model (JSON)\n --url <https://...> Required\n --provider <id> Override active provider\n --model <name> Override model for the selected provider\n --print-ssh-targets Print SSH deploy/monitor targets\n --set-ssh-target Upsert target (--json '{...}' or flags)\n --remove-ssh-target --id <id>\n --test-ssh-target --id <id> (BatchMode ssh true)\n --print-ssh-pubkey --path <private-or-.pub> (display public key)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n ZELARI_MEMORY_MCP=1 Enable the optional external memory MCP server\n ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
87187
87439
|
);
|
|
87188
87440
|
process.exit(0);
|
|
87189
87441
|
}
|
|
@@ -87223,6 +87475,11 @@ proposals: npm run evolve:propose \u2014 decisions in npm run evolve:decide (P1:
|
|
|
87223
87475
|
if (!Array.isArray(parsed)) throw new Error("--args must be a JSON array");
|
|
87224
87476
|
args = parsed.map(String);
|
|
87225
87477
|
}
|
|
87478
|
+
const envValues = [];
|
|
87479
|
+
for (let i = 0; i < argv.length - 1; i++) {
|
|
87480
|
+
if (argv[i] === "--env") envValues.push(argv[i + 1]);
|
|
87481
|
+
}
|
|
87482
|
+
const env = parseMcpEnvFlag(envValues);
|
|
87226
87483
|
const timeoutMs2 = timeoutRaw !== void 0 ? Number(timeoutRaw) : void 0;
|
|
87227
87484
|
if (timeoutMs2 !== void 0 && (!Number.isFinite(timeoutMs2) || timeoutMs2 <= 0)) {
|
|
87228
87485
|
throw new Error("--timeout must be a positive number of milliseconds");
|
|
@@ -87238,7 +87495,7 @@ proposals: npm run evolve:propose \u2014 decisions in npm run evolve:decide (P1:
|
|
|
87238
87495
|
scope,
|
|
87239
87496
|
name,
|
|
87240
87497
|
projectRoot: cwd,
|
|
87241
|
-
config: url2 ? { type: "http", url: url2, timeoutMs: timeoutMs2, serial: true, enabled } : { command, args, enabled }
|
|
87498
|
+
config: url2 ? { type: "http", url: url2, timeoutMs: timeoutMs2, serial: true, enabled, env } : { command, args, env, enabled }
|
|
87242
87499
|
});
|
|
87243
87500
|
if (!result.ok) throw new Error(result.error);
|
|
87244
87501
|
console.log(JSON.stringify({ ok: true, path: result.path, name, scope }));
|
|
@@ -87729,7 +87986,7 @@ function main() {
|
|
|
87729
87986
|
closeMcpClients2();
|
|
87730
87987
|
} catch {
|
|
87731
87988
|
}
|
|
87732
|
-
await new Promise((
|
|
87989
|
+
await new Promise((resolve10) => setImmediate(resolve10));
|
|
87733
87990
|
process.exit(code);
|
|
87734
87991
|
}).catch(async (err) => {
|
|
87735
87992
|
console.error(
|