zelari-code 1.31.1 → 1.32.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/commands/inspect.js +166 -0
- package/dist/cli/commands/inspect.js.map +1 -0
- package/dist/cli/hooks/useSlashDispatch.js +17 -0
- package/dist/cli/hooks/useSlashDispatch.js.map +1 -1
- package/dist/cli/main.bundled.js +1554 -837
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +30 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/mcp/mcpManager.js +15 -4
- package/dist/cli/mcp/mcpManager.js.map +1 -1
- package/dist/cli/safety/folderTrust.js +124 -0
- package/dist/cli/safety/folderTrust.js.map +1 -0
- package/dist/cli/safety/lifecycleHooks.js +52 -0
- package/dist/cli/safety/lifecycleHooks.js.map +1 -0
- package/dist/cli/slashCommands.js +18 -1
- package/dist/cli/slashCommands.js.map +1 -1
- package/dist/cli/slashHandlers/trust.js +52 -0
- package/dist/cli/slashHandlers/trust.js.map +1 -0
- package/dist/cli/toolRegistry.js +7 -0
- package/dist/cli/toolRegistry.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -395,7 +395,7 @@ async function refreshGrokToken(options) {
|
|
|
395
395
|
return parseTokenResponseBody(obj, accessToken);
|
|
396
396
|
}
|
|
397
397
|
async function openBrowser(url2) {
|
|
398
|
-
const { spawn:
|
|
398
|
+
const { spawn: spawn14 } = await import("node:child_process");
|
|
399
399
|
const cmd = (() => {
|
|
400
400
|
switch (process.platform) {
|
|
401
401
|
case "darwin":
|
|
@@ -408,7 +408,7 @@ async function openBrowser(url2) {
|
|
|
408
408
|
})();
|
|
409
409
|
return new Promise((resolve3, reject) => {
|
|
410
410
|
try {
|
|
411
|
-
const child =
|
|
411
|
+
const child = spawn14(cmd.bin, cmd.args, {
|
|
412
412
|
stdio: "ignore",
|
|
413
413
|
detached: true
|
|
414
414
|
});
|
|
@@ -1829,10 +1829,10 @@ function mergeDefs(...defs) {
|
|
|
1829
1829
|
function cloneDef(schema) {
|
|
1830
1830
|
return mergeDefs(schema._zod.def);
|
|
1831
1831
|
}
|
|
1832
|
-
function getElementAtPath(obj,
|
|
1833
|
-
if (!
|
|
1832
|
+
function getElementAtPath(obj, path51) {
|
|
1833
|
+
if (!path51)
|
|
1834
1834
|
return obj;
|
|
1835
|
-
return
|
|
1835
|
+
return path51.reduce((acc, key) => acc?.[key], obj);
|
|
1836
1836
|
}
|
|
1837
1837
|
function promiseAllObject(promisesObj) {
|
|
1838
1838
|
const keys = Object.keys(promisesObj);
|
|
@@ -2160,11 +2160,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
2160
2160
|
}
|
|
2161
2161
|
return false;
|
|
2162
2162
|
}
|
|
2163
|
-
function prefixIssues(
|
|
2163
|
+
function prefixIssues(path51, issues) {
|
|
2164
2164
|
return issues.map((iss) => {
|
|
2165
2165
|
var _a3;
|
|
2166
2166
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
2167
|
-
iss.path.unshift(
|
|
2167
|
+
iss.path.unshift(path51);
|
|
2168
2168
|
return iss;
|
|
2169
2169
|
});
|
|
2170
2170
|
}
|
|
@@ -2382,16 +2382,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2382
2382
|
}
|
|
2383
2383
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
2384
2384
|
const fieldErrors = { _errors: [] };
|
|
2385
|
-
const processError = (error52,
|
|
2385
|
+
const processError = (error52, path51 = []) => {
|
|
2386
2386
|
for (const issue2 of error52.issues) {
|
|
2387
2387
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
2388
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
2388
|
+
issue2.errors.map((issues) => processError({ issues }, [...path51, ...issue2.path]));
|
|
2389
2389
|
} else if (issue2.code === "invalid_key") {
|
|
2390
|
-
processError({ issues: issue2.issues }, [...
|
|
2390
|
+
processError({ issues: issue2.issues }, [...path51, ...issue2.path]);
|
|
2391
2391
|
} else if (issue2.code === "invalid_element") {
|
|
2392
|
-
processError({ issues: issue2.issues }, [...
|
|
2392
|
+
processError({ issues: issue2.issues }, [...path51, ...issue2.path]);
|
|
2393
2393
|
} else {
|
|
2394
|
-
const fullpath = [...
|
|
2394
|
+
const fullpath = [...path51, ...issue2.path];
|
|
2395
2395
|
if (fullpath.length === 0) {
|
|
2396
2396
|
fieldErrors._errors.push(mapper(issue2));
|
|
2397
2397
|
} else {
|
|
@@ -2418,17 +2418,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2418
2418
|
}
|
|
2419
2419
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
2420
2420
|
const result = { errors: [] };
|
|
2421
|
-
const processError = (error52,
|
|
2421
|
+
const processError = (error52, path51 = []) => {
|
|
2422
2422
|
var _a3, _b;
|
|
2423
2423
|
for (const issue2 of error52.issues) {
|
|
2424
2424
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
2425
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
2425
|
+
issue2.errors.map((issues) => processError({ issues }, [...path51, ...issue2.path]));
|
|
2426
2426
|
} else if (issue2.code === "invalid_key") {
|
|
2427
|
-
processError({ issues: issue2.issues }, [...
|
|
2427
|
+
processError({ issues: issue2.issues }, [...path51, ...issue2.path]);
|
|
2428
2428
|
} else if (issue2.code === "invalid_element") {
|
|
2429
|
-
processError({ issues: issue2.issues }, [...
|
|
2429
|
+
processError({ issues: issue2.issues }, [...path51, ...issue2.path]);
|
|
2430
2430
|
} else {
|
|
2431
|
-
const fullpath = [...
|
|
2431
|
+
const fullpath = [...path51, ...issue2.path];
|
|
2432
2432
|
if (fullpath.length === 0) {
|
|
2433
2433
|
result.errors.push(mapper(issue2));
|
|
2434
2434
|
continue;
|
|
@@ -2460,8 +2460,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2460
2460
|
}
|
|
2461
2461
|
function toDotPath(_path) {
|
|
2462
2462
|
const segs = [];
|
|
2463
|
-
const
|
|
2464
|
-
for (const seg of
|
|
2463
|
+
const path51 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
2464
|
+
for (const seg of path51) {
|
|
2465
2465
|
if (typeof seg === "number")
|
|
2466
2466
|
segs.push(`[${seg}]`);
|
|
2467
2467
|
else if (typeof seg === "symbol")
|
|
@@ -15964,13 +15964,13 @@ function resolveRef(ref, ctx) {
|
|
|
15964
15964
|
if (!ref.startsWith("#")) {
|
|
15965
15965
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
15966
15966
|
}
|
|
15967
|
-
const
|
|
15968
|
-
if (
|
|
15967
|
+
const path51 = ref.slice(1).split("/").filter(Boolean);
|
|
15968
|
+
if (path51.length === 0) {
|
|
15969
15969
|
return ctx.rootSchema;
|
|
15970
15970
|
}
|
|
15971
15971
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
15972
|
-
if (
|
|
15973
|
-
const key =
|
|
15972
|
+
if (path51[0] === defsKey) {
|
|
15973
|
+
const key = path51[1];
|
|
15974
15974
|
if (!key || !ctx.defs[key]) {
|
|
15975
15975
|
throw new Error(`Reference not found: ${ref}`);
|
|
15976
15976
|
}
|
|
@@ -18134,11 +18134,11 @@ var init_tools = __esm({
|
|
|
18134
18134
|
if (!ctx.addDocument)
|
|
18135
18135
|
return "Knowledge vault tool not available.";
|
|
18136
18136
|
const title = args["title"] || "New Document";
|
|
18137
|
-
const
|
|
18137
|
+
const path51 = args["path"] || `notes/${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
|
|
18138
18138
|
const content = args["content"] || "";
|
|
18139
18139
|
const tags = args["tags"] || [];
|
|
18140
18140
|
ctx.addDocument({
|
|
18141
|
-
path:
|
|
18141
|
+
path: path51,
|
|
18142
18142
|
title,
|
|
18143
18143
|
content,
|
|
18144
18144
|
format: "markdown",
|
|
@@ -18147,7 +18147,7 @@ var init_tools = __esm({
|
|
|
18147
18147
|
workspaceId: ctx.workspaceId
|
|
18148
18148
|
});
|
|
18149
18149
|
ctx.addActivity("vault", "created document", title);
|
|
18150
|
-
return `Document "${title}" created at "${
|
|
18150
|
+
return `Document "${title}" created at "${path51}".`;
|
|
18151
18151
|
}
|
|
18152
18152
|
}
|
|
18153
18153
|
];
|
|
@@ -21166,23 +21166,303 @@ var init_sessionJsonl = __esm({
|
|
|
21166
21166
|
}
|
|
21167
21167
|
});
|
|
21168
21168
|
|
|
21169
|
+
// packages/core/dist/core/hooks/types.js
|
|
21170
|
+
function normalizeToolName(raw) {
|
|
21171
|
+
const n = raw.toLowerCase().replace(/[_-]/g, "");
|
|
21172
|
+
return TOOL_ALIASES[n] ?? n;
|
|
21173
|
+
}
|
|
21174
|
+
function toolMatches(pattern, toolName) {
|
|
21175
|
+
if (pattern === "*")
|
|
21176
|
+
return true;
|
|
21177
|
+
return normalizeToolName(pattern) === normalizeToolName(toolName);
|
|
21178
|
+
}
|
|
21179
|
+
function hookMatches(hook, event, toolName) {
|
|
21180
|
+
if (!hook.match.events.includes(event))
|
|
21181
|
+
return false;
|
|
21182
|
+
if (event === "PreToolUse" || event === "PostToolUse") {
|
|
21183
|
+
if (!toolName)
|
|
21184
|
+
return false;
|
|
21185
|
+
return hook.match.tools.some((t) => toolMatches(t, toolName));
|
|
21186
|
+
}
|
|
21187
|
+
return true;
|
|
21188
|
+
}
|
|
21189
|
+
var TOOL_ALIASES;
|
|
21190
|
+
var init_types2 = __esm({
|
|
21191
|
+
"packages/core/dist/core/hooks/types.js"() {
|
|
21192
|
+
"use strict";
|
|
21193
|
+
TOOL_ALIASES = {
|
|
21194
|
+
read: "read_file",
|
|
21195
|
+
readfile: "read_file",
|
|
21196
|
+
cat: "read_file",
|
|
21197
|
+
write: "write_file",
|
|
21198
|
+
writefile: "write_file",
|
|
21199
|
+
edit: "edit_file",
|
|
21200
|
+
editfile: "edit_file",
|
|
21201
|
+
glob: "list_files",
|
|
21202
|
+
listdir: "list_files",
|
|
21203
|
+
listdirectory: "list_files",
|
|
21204
|
+
ls: "list_files",
|
|
21205
|
+
dir: "list_files",
|
|
21206
|
+
find: "list_files",
|
|
21207
|
+
grep: "grep_content",
|
|
21208
|
+
search: "grep_content",
|
|
21209
|
+
searchrag: "searchDocuments",
|
|
21210
|
+
rag: "searchDocuments",
|
|
21211
|
+
shell: "bash",
|
|
21212
|
+
terminal: "bash",
|
|
21213
|
+
cmd: "bash",
|
|
21214
|
+
run: "bash",
|
|
21215
|
+
exec: "bash"
|
|
21216
|
+
};
|
|
21217
|
+
}
|
|
21218
|
+
});
|
|
21219
|
+
|
|
21220
|
+
// packages/core/dist/core/hooks/lifecycleHookRunner.js
|
|
21221
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
21222
|
+
import { readdirSync, readFileSync as readFileSync4 } from "node:fs";
|
|
21223
|
+
import path12 from "node:path";
|
|
21224
|
+
function parseJson(text) {
|
|
21225
|
+
try {
|
|
21226
|
+
return JSON.parse(text);
|
|
21227
|
+
} catch {
|
|
21228
|
+
return null;
|
|
21229
|
+
}
|
|
21230
|
+
}
|
|
21231
|
+
var DEFAULT_TIMEOUT_MS, LifecycleHookRunner;
|
|
21232
|
+
var init_lifecycleHookRunner = __esm({
|
|
21233
|
+
"packages/core/dist/core/hooks/lifecycleHookRunner.js"() {
|
|
21234
|
+
"use strict";
|
|
21235
|
+
init_types2();
|
|
21236
|
+
DEFAULT_TIMEOUT_MS = 5e3;
|
|
21237
|
+
LifecycleHookRunner = class {
|
|
21238
|
+
hooks = [];
|
|
21239
|
+
logger;
|
|
21240
|
+
defaultTimeoutMs;
|
|
21241
|
+
constructor(options = {}) {
|
|
21242
|
+
this.logger = options.logger ?? ((msg) => console.error(`[hooks] ${msg}`));
|
|
21243
|
+
this.defaultTimeoutMs = options.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
21244
|
+
for (const dir of options.dirs ?? []) {
|
|
21245
|
+
this.loadDir(dir);
|
|
21246
|
+
}
|
|
21247
|
+
}
|
|
21248
|
+
/** Add a single hook definition (used by tests / programmatic config). */
|
|
21249
|
+
addHook(hook) {
|
|
21250
|
+
this.hooks.push(hook);
|
|
21251
|
+
}
|
|
21252
|
+
/** Scan a directory for `*.json` hook files and load them. Returns count. */
|
|
21253
|
+
loadDir(dir) {
|
|
21254
|
+
let files;
|
|
21255
|
+
try {
|
|
21256
|
+
files = readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
21257
|
+
} catch {
|
|
21258
|
+
return 0;
|
|
21259
|
+
}
|
|
21260
|
+
let loaded = 0;
|
|
21261
|
+
for (const f of files) {
|
|
21262
|
+
const full = path12.join(dir, f);
|
|
21263
|
+
try {
|
|
21264
|
+
const parsed = parseJson(readFileSync4(full, "utf8"));
|
|
21265
|
+
if (!parsed || !parsed.name || !parsed.match) {
|
|
21266
|
+
this.logger(`skipping invalid hook file ${full}`);
|
|
21267
|
+
continue;
|
|
21268
|
+
}
|
|
21269
|
+
parsed.name = parsed.name || path12.basename(f, ".json");
|
|
21270
|
+
this.hooks.push(parsed);
|
|
21271
|
+
loaded += 1;
|
|
21272
|
+
} catch (err) {
|
|
21273
|
+
this.logger(`failed to load hook ${full}: ${err instanceof Error ? err.message : String(err)}`);
|
|
21274
|
+
}
|
|
21275
|
+
}
|
|
21276
|
+
return loaded;
|
|
21277
|
+
}
|
|
21278
|
+
listHooks() {
|
|
21279
|
+
return [...this.hooks];
|
|
21280
|
+
}
|
|
21281
|
+
/**
|
|
21282
|
+
* Run matching PreToolUse hooks. Returns `{ ok: false }` ONLY when a hook
|
|
21283
|
+
* explicitly denies. All other outcomes (no match, crash, timeout, invalid
|
|
21284
|
+
* JSON, allow decision) return `{ ok: true }`.
|
|
21285
|
+
*/
|
|
21286
|
+
async runPreToolUse(toolName, toolInput, ctx) {
|
|
21287
|
+
for (const hook of this.hooks) {
|
|
21288
|
+
if (!hookMatches(hook, "PreToolUse", toolName))
|
|
21289
|
+
continue;
|
|
21290
|
+
const payload = {
|
|
21291
|
+
event: "PreToolUse",
|
|
21292
|
+
toolName,
|
|
21293
|
+
toolInput,
|
|
21294
|
+
sessionId: ctx.sessionId,
|
|
21295
|
+
cwd: ctx.cwd
|
|
21296
|
+
};
|
|
21297
|
+
const decision = await this.runHookSafely(hook, payload);
|
|
21298
|
+
if (decision.decision === "deny") {
|
|
21299
|
+
return {
|
|
21300
|
+
ok: false,
|
|
21301
|
+
hookName: hook.name,
|
|
21302
|
+
reason: decision.reason || `blocked by hook "${hook.name}"`
|
|
21303
|
+
};
|
|
21304
|
+
}
|
|
21305
|
+
}
|
|
21306
|
+
return { ok: true };
|
|
21307
|
+
}
|
|
21308
|
+
/** Run matching PostToolUse hooks. Fail-open, results are logged only. */
|
|
21309
|
+
async runPostToolUse(toolName, toolInput, toolOutput, ctx) {
|
|
21310
|
+
for (const hook of this.hooks) {
|
|
21311
|
+
if (!hookMatches(hook, "PostToolUse", toolName))
|
|
21312
|
+
continue;
|
|
21313
|
+
const payload = {
|
|
21314
|
+
event: "PostToolUse",
|
|
21315
|
+
toolName,
|
|
21316
|
+
toolInput,
|
|
21317
|
+
toolOutput,
|
|
21318
|
+
ok: ctx.ok ?? true,
|
|
21319
|
+
error: ctx.error,
|
|
21320
|
+
sessionId: ctx.sessionId,
|
|
21321
|
+
cwd: ctx.cwd
|
|
21322
|
+
};
|
|
21323
|
+
await this.runHookSafely(hook, payload);
|
|
21324
|
+
}
|
|
21325
|
+
}
|
|
21326
|
+
/** Run matching SessionStart hooks. Fail-open; deny never throws. */
|
|
21327
|
+
async runSessionStart(ctx) {
|
|
21328
|
+
return this.runSessionHooks("SessionStart", ctx);
|
|
21329
|
+
}
|
|
21330
|
+
/** Run matching SessionEnd hooks. Fail-open. */
|
|
21331
|
+
async runSessionEnd(ctx) {
|
|
21332
|
+
return this.runSessionHooks("SessionEnd", ctx);
|
|
21333
|
+
}
|
|
21334
|
+
async runSessionHooks(event, ctx) {
|
|
21335
|
+
for (const hook of this.hooks) {
|
|
21336
|
+
if (!hookMatches(hook, event, void 0))
|
|
21337
|
+
continue;
|
|
21338
|
+
const payload = {
|
|
21339
|
+
event,
|
|
21340
|
+
sessionId: ctx.sessionId,
|
|
21341
|
+
cwd: ctx.cwd
|
|
21342
|
+
};
|
|
21343
|
+
const decision = await this.runHookSafely(hook, payload);
|
|
21344
|
+
if (decision.decision === "deny") {
|
|
21345
|
+
return {
|
|
21346
|
+
ok: false,
|
|
21347
|
+
hookName: hook.name,
|
|
21348
|
+
reason: decision.reason || `blocked by hook "${hook.name}"`
|
|
21349
|
+
};
|
|
21350
|
+
}
|
|
21351
|
+
}
|
|
21352
|
+
return { ok: true };
|
|
21353
|
+
}
|
|
21354
|
+
/** Execute a single hook, swallowing every failure into an allow. */
|
|
21355
|
+
async runHookSafely(hook, payload) {
|
|
21356
|
+
try {
|
|
21357
|
+
const timeoutMs = hook.timeoutMs ?? this.defaultTimeoutMs;
|
|
21358
|
+
const raw = hook.url ? await this.postHttp(hook.url, payload, timeoutMs) : await this.execCommand(hook.command ?? "", payload, timeoutMs, hook.cwd);
|
|
21359
|
+
const decision = parseJson(raw);
|
|
21360
|
+
if (!decision) {
|
|
21361
|
+
this.logger(`hook "${hook.name}" returned invalid JSON (fail-open): ${raw.slice(0, 200)}`);
|
|
21362
|
+
return { decision: "allow" };
|
|
21363
|
+
}
|
|
21364
|
+
if (decision.decision === "deny" && typeof decision.reason !== "string") {
|
|
21365
|
+
this.logger(`hook "${hook.name}" denied without reason (fail-open)`);
|
|
21366
|
+
return { decision: "allow" };
|
|
21367
|
+
}
|
|
21368
|
+
return decision;
|
|
21369
|
+
} catch (err) {
|
|
21370
|
+
this.logger(`hook "${hook.name}" failed (fail-open): ${err instanceof Error ? err.message : String(err)}`);
|
|
21371
|
+
return { decision: "allow" };
|
|
21372
|
+
}
|
|
21373
|
+
}
|
|
21374
|
+
/** Spawn `command`, write JSON payload to stdin, read stdout until close. */
|
|
21375
|
+
execCommand(command, payload, timeoutMs, cwd) {
|
|
21376
|
+
return new Promise((resolve3, reject) => {
|
|
21377
|
+
const child = spawn2(command, {
|
|
21378
|
+
shell: true,
|
|
21379
|
+
cwd,
|
|
21380
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
21381
|
+
windowsHide: true
|
|
21382
|
+
});
|
|
21383
|
+
let stdout = "";
|
|
21384
|
+
let stderr = "";
|
|
21385
|
+
const timer = setTimeout(() => {
|
|
21386
|
+
child.kill("SIGKILL");
|
|
21387
|
+
reject(new Error(`timed out after ${timeoutMs}ms`));
|
|
21388
|
+
}, timeoutMs);
|
|
21389
|
+
child.stdout?.on("data", (d) => {
|
|
21390
|
+
stdout += d.toString();
|
|
21391
|
+
});
|
|
21392
|
+
child.stderr?.on("data", (d) => {
|
|
21393
|
+
stderr += d.toString();
|
|
21394
|
+
});
|
|
21395
|
+
child.on("error", (err) => {
|
|
21396
|
+
clearTimeout(timer);
|
|
21397
|
+
reject(err);
|
|
21398
|
+
});
|
|
21399
|
+
child.on("close", (code) => {
|
|
21400
|
+
clearTimeout(timer);
|
|
21401
|
+
if (code !== 0) {
|
|
21402
|
+
reject(new Error(`exited ${code}: ${stderr.trim().slice(0, 200)}`));
|
|
21403
|
+
return;
|
|
21404
|
+
}
|
|
21405
|
+
resolve3(stdout);
|
|
21406
|
+
});
|
|
21407
|
+
child.stdin?.on("error", () => {
|
|
21408
|
+
});
|
|
21409
|
+
child.stdin?.write(JSON.stringify(payload));
|
|
21410
|
+
child.stdin?.end();
|
|
21411
|
+
});
|
|
21412
|
+
}
|
|
21413
|
+
/** POST JSON payload; resolve with the response body text. */
|
|
21414
|
+
async postHttp(url2, payload, timeoutMs) {
|
|
21415
|
+
const ctrl = new AbortController();
|
|
21416
|
+
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
21417
|
+
try {
|
|
21418
|
+
const res = await fetch(url2, {
|
|
21419
|
+
method: "POST",
|
|
21420
|
+
headers: { "content-type": "application/json" },
|
|
21421
|
+
body: JSON.stringify(payload),
|
|
21422
|
+
signal: ctrl.signal
|
|
21423
|
+
});
|
|
21424
|
+
if (!res.ok) {
|
|
21425
|
+
throw new Error(`HTTP ${res.status}`);
|
|
21426
|
+
}
|
|
21427
|
+
return await res.text();
|
|
21428
|
+
} finally {
|
|
21429
|
+
clearTimeout(timer);
|
|
21430
|
+
}
|
|
21431
|
+
}
|
|
21432
|
+
};
|
|
21433
|
+
}
|
|
21434
|
+
});
|
|
21435
|
+
|
|
21436
|
+
// packages/core/dist/core/hooks/index.js
|
|
21437
|
+
var init_hooks = __esm({
|
|
21438
|
+
"packages/core/dist/core/hooks/index.js"() {
|
|
21439
|
+
"use strict";
|
|
21440
|
+
init_types2();
|
|
21441
|
+
init_lifecycleHookRunner();
|
|
21442
|
+
}
|
|
21443
|
+
});
|
|
21444
|
+
|
|
21169
21445
|
// packages/core/dist/harness/index.js
|
|
21170
21446
|
var harness_exports = {};
|
|
21171
21447
|
__export(harness_exports, {
|
|
21172
21448
|
AgentHarness: () => AgentHarness,
|
|
21173
21449
|
DOOM_LOOP_THRESHOLD: () => DOOM_LOOP_THRESHOLD,
|
|
21450
|
+
LifecycleHookRunner: () => LifecycleHookRunner,
|
|
21174
21451
|
SessionJsonlWriter: () => SessionJsonlWriter,
|
|
21175
21452
|
TEXT_LOOP_RECOVERY_SYSTEM: () => TEXT_LOOP_RECOVERY_SYSTEM,
|
|
21176
21453
|
TEXT_LOOP_RECOVERY_USER_PROMPT: () => TEXT_LOOP_RECOVERY_USER_PROMPT,
|
|
21177
21454
|
collapseLoopedAssistantText: () => collapseLoopedAssistantText,
|
|
21178
21455
|
detectAssistantTextLoop: () => detectAssistantTextLoop,
|
|
21179
21456
|
hashToolCall: () => hashToolCall,
|
|
21457
|
+
hookMatches: () => hookMatches,
|
|
21180
21458
|
isStatusTheaterUnit: () => isStatusTheaterUnit,
|
|
21181
21459
|
normalizeLoopUnit: () => normalizeLoopUnit,
|
|
21182
21460
|
normalizeTextToolArgs: () => normalizeTextToolArgs,
|
|
21461
|
+
normalizeToolName: () => normalizeToolName,
|
|
21183
21462
|
parseMinimaxStyleToolCalls: () => parseMinimaxStyleToolCalls,
|
|
21184
21463
|
parseTextToolCalls: () => parseTextToolCalls,
|
|
21185
21464
|
readSession: () => readSession,
|
|
21465
|
+
toolMatches: () => toolMatches,
|
|
21186
21466
|
wrapLegacyStream: () => wrapLegacyStream
|
|
21187
21467
|
});
|
|
21188
21468
|
var init_harness = __esm({
|
|
@@ -21191,6 +21471,7 @@ var init_harness = __esm({
|
|
|
21191
21471
|
init_AgentHarness();
|
|
21192
21472
|
init_providerStream();
|
|
21193
21473
|
init_sessionJsonl();
|
|
21474
|
+
init_hooks();
|
|
21194
21475
|
}
|
|
21195
21476
|
});
|
|
21196
21477
|
|
|
@@ -21667,7 +21948,7 @@ var init_parseCssMotion = __esm({
|
|
|
21667
21948
|
});
|
|
21668
21949
|
|
|
21669
21950
|
// packages/core/dist/council/verification/citeVerify.js
|
|
21670
|
-
import { existsSync as existsSync5, readFileSync as
|
|
21951
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
|
|
21671
21952
|
import { join } from "node:path";
|
|
21672
21953
|
function extractCitations(text) {
|
|
21673
21954
|
const out = [];
|
|
@@ -21704,7 +21985,7 @@ function verifyCitations(projectRoot, synthesisText) {
|
|
|
21704
21985
|
});
|
|
21705
21986
|
continue;
|
|
21706
21987
|
}
|
|
21707
|
-
const lines =
|
|
21988
|
+
const lines = readFileSync5(abs, "utf8").split(/\r?\n/);
|
|
21708
21989
|
if (cite.line > lines.length) {
|
|
21709
21990
|
results.push({
|
|
21710
21991
|
id: "synthesis.cite-invalid",
|
|
@@ -21967,14 +22248,14 @@ var init_synthesisAudit = __esm({
|
|
|
21967
22248
|
});
|
|
21968
22249
|
|
|
21969
22250
|
// packages/core/dist/council/verification/runChecks.js
|
|
21970
|
-
import { existsSync as existsSync6, readFileSync as
|
|
22251
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
|
|
21971
22252
|
import { join as join2 } from "node:path";
|
|
21972
22253
|
function loadNfrSpec(zelariRoot) {
|
|
21973
|
-
const
|
|
21974
|
-
if (!existsSync6(
|
|
22254
|
+
const path51 = join2(zelariRoot, "nfr-spec.json");
|
|
22255
|
+
if (!existsSync6(path51))
|
|
21975
22256
|
return null;
|
|
21976
22257
|
try {
|
|
21977
|
-
const raw = JSON.parse(
|
|
22258
|
+
const raw = JSON.parse(readFileSync6(path51, "utf8"));
|
|
21978
22259
|
if (raw.version !== 1 || !Array.isArray(raw.targets))
|
|
21979
22260
|
return null;
|
|
21980
22261
|
return raw;
|
|
@@ -22049,13 +22330,13 @@ function checkPlanReality(projectRoot, zelariRoot, targets, keywords) {
|
|
|
22049
22330
|
return [];
|
|
22050
22331
|
let plan;
|
|
22051
22332
|
try {
|
|
22052
|
-
plan = JSON.parse(
|
|
22333
|
+
plan = JSON.parse(readFileSync6(planPath, "utf8"));
|
|
22053
22334
|
} catch {
|
|
22054
22335
|
return [];
|
|
22055
22336
|
}
|
|
22056
22337
|
const milestoneText = (plan.milestones ?? []).map((m) => `${m.name ?? ""} ${m.description ?? ""}`).join(" ").toLowerCase();
|
|
22057
22338
|
const results = [];
|
|
22058
|
-
const targetContent = targets.map((t) =>
|
|
22339
|
+
const targetContent = targets.map((t) => readFileSync6(join2(projectRoot, t), "utf8").toLowerCase()).join("\n");
|
|
22059
22340
|
for (const kw of keywords) {
|
|
22060
22341
|
const low = kw.toLowerCase();
|
|
22061
22342
|
if (!milestoneText.includes(low))
|
|
@@ -22087,11 +22368,11 @@ function checkReadmeStale(projectRoot, targets) {
|
|
|
22087
22368
|
const readmePath = join2(projectRoot, "README.md");
|
|
22088
22369
|
if (!existsSync6(readmePath) || targets.length === 0)
|
|
22089
22370
|
return [];
|
|
22090
|
-
const readme =
|
|
22371
|
+
const readme = readFileSync6(readmePath, "utf8");
|
|
22091
22372
|
const htmlPath = join2(projectRoot, targets[0]);
|
|
22092
22373
|
if (!existsSync6(htmlPath))
|
|
22093
22374
|
return [];
|
|
22094
|
-
const html =
|
|
22375
|
+
const html = readFileSync6(htmlPath, "utf8");
|
|
22095
22376
|
const sectionCount = (html.match(/<section\s+id=/gi) ?? []).length;
|
|
22096
22377
|
const readmeSections = readme.match(/(\d+)\s+sezioni/i);
|
|
22097
22378
|
if (readmeSections) {
|
|
@@ -22129,7 +22410,7 @@ function runImplementationVerification(input) {
|
|
|
22129
22410
|
forbidLayoutProps: anim.forbidLayoutProps ?? true
|
|
22130
22411
|
};
|
|
22131
22412
|
for (const rel2 of targets) {
|
|
22132
|
-
const html =
|
|
22413
|
+
const html = readFileSync6(join2(input.projectRoot, rel2), "utf8");
|
|
22133
22414
|
for (const v of scanKeyframesViolations(html, scanOpts)) {
|
|
22134
22415
|
results.push({
|
|
22135
22416
|
id: "motion.keyframes",
|
|
@@ -22215,7 +22496,7 @@ var init_runChecks = __esm({
|
|
|
22215
22496
|
});
|
|
22216
22497
|
|
|
22217
22498
|
// packages/core/dist/council/verification/microGate.js
|
|
22218
|
-
import { existsSync as existsSync7, readFileSync as
|
|
22499
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7 } from "node:fs";
|
|
22219
22500
|
import { join as join3 } from "node:path";
|
|
22220
22501
|
function checkDeadHooksInHtml(html) {
|
|
22221
22502
|
const warnings = [];
|
|
@@ -22253,7 +22534,7 @@ function runMicroVerificationOnFile(projectRoot, relPath, zelariRoot) {
|
|
|
22253
22534
|
compositorOnly: anim.compositorOnly ?? true,
|
|
22254
22535
|
forbidLayoutProps: anim.forbidLayoutProps ?? true
|
|
22255
22536
|
};
|
|
22256
|
-
const html =
|
|
22537
|
+
const html = readFileSync7(abs, "utf8");
|
|
22257
22538
|
const warnings = [];
|
|
22258
22539
|
for (const v of scanKeyframesViolations(html, scanOpts)) {
|
|
22259
22540
|
warnings.push({
|
|
@@ -22609,7 +22890,7 @@ var init_implementationDelivery = __esm({
|
|
|
22609
22890
|
});
|
|
22610
22891
|
|
|
22611
22892
|
// packages/core/dist/council/verification/inlineJsAutofix.js
|
|
22612
|
-
import { readFileSync as
|
|
22893
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
|
|
22613
22894
|
import { join as join4 } from "node:path";
|
|
22614
22895
|
function minifyInlineJs(js) {
|
|
22615
22896
|
let out = js.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
@@ -22656,7 +22937,7 @@ function applyInlineJsAutofix(projectRoot, report) {
|
|
|
22656
22937
|
const abs = join4(projectRoot, rel2);
|
|
22657
22938
|
let html;
|
|
22658
22939
|
try {
|
|
22659
|
-
html =
|
|
22940
|
+
html = readFileSync8(abs, "utf8");
|
|
22660
22941
|
} catch {
|
|
22661
22942
|
continue;
|
|
22662
22943
|
}
|
|
@@ -24048,14 +24329,14 @@ var init_missionBrief = __esm({
|
|
|
24048
24329
|
});
|
|
24049
24330
|
|
|
24050
24331
|
// packages/core/dist/council/verification/types.js
|
|
24051
|
-
var
|
|
24332
|
+
var init_types3 = __esm({
|
|
24052
24333
|
"packages/core/dist/council/verification/types.js"() {
|
|
24053
24334
|
"use strict";
|
|
24054
24335
|
}
|
|
24055
24336
|
});
|
|
24056
24337
|
|
|
24057
24338
|
// packages/core/dist/council/verification/motionAutofix.js
|
|
24058
|
-
import { readFileSync as
|
|
24339
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
24059
24340
|
import { join as join6 } from "node:path";
|
|
24060
24341
|
function sanitizeTransitionPart(part) {
|
|
24061
24342
|
const tokens = part.trim().split(/\s+/);
|
|
@@ -24134,7 +24415,7 @@ function applyMotionAutofix(projectRoot, report) {
|
|
|
24134
24415
|
const abs = join6(projectRoot, rel2);
|
|
24135
24416
|
let html;
|
|
24136
24417
|
try {
|
|
24137
|
-
html =
|
|
24418
|
+
html = readFileSync9(abs, "utf8");
|
|
24138
24419
|
} catch {
|
|
24139
24420
|
continue;
|
|
24140
24421
|
}
|
|
@@ -24206,7 +24487,7 @@ var init_motionAutofix = __esm({
|
|
|
24206
24487
|
});
|
|
24207
24488
|
|
|
24208
24489
|
// packages/core/dist/council/verification/autofix.js
|
|
24209
|
-
import { readFileSync as
|
|
24490
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "node:fs";
|
|
24210
24491
|
import { join as join7 } from "node:path";
|
|
24211
24492
|
function applyDeterministicAutofix(projectRoot, report) {
|
|
24212
24493
|
const motion = applyMotionAutofix(projectRoot, report);
|
|
@@ -24222,7 +24503,7 @@ function applyDeterministicAutofix(projectRoot, report) {
|
|
|
24222
24503
|
if (!m || m[1] === "rm")
|
|
24223
24504
|
continue;
|
|
24224
24505
|
const abs = join7(projectRoot, rel2);
|
|
24225
|
-
let html =
|
|
24506
|
+
let html = readFileSync10(abs, "utf8");
|
|
24226
24507
|
const snippet = m[0];
|
|
24227
24508
|
if (!html.includes(snippet))
|
|
24228
24509
|
continue;
|
|
@@ -24252,7 +24533,7 @@ var init_autofix = __esm({
|
|
|
24252
24533
|
var init_verification = __esm({
|
|
24253
24534
|
"packages/core/dist/council/verification/index.js"() {
|
|
24254
24535
|
"use strict";
|
|
24255
|
-
|
|
24536
|
+
init_types3();
|
|
24256
24537
|
init_runChecks();
|
|
24257
24538
|
init_honesty();
|
|
24258
24539
|
init_parseCssMotion();
|
|
@@ -24270,19 +24551,19 @@ var init_verification = __esm({
|
|
|
24270
24551
|
});
|
|
24271
24552
|
|
|
24272
24553
|
// packages/core/dist/council/lessons/types.js
|
|
24273
|
-
var
|
|
24554
|
+
var init_types4 = __esm({
|
|
24274
24555
|
"packages/core/dist/council/lessons/types.js"() {
|
|
24275
24556
|
"use strict";
|
|
24276
24557
|
}
|
|
24277
24558
|
});
|
|
24278
24559
|
|
|
24279
24560
|
// packages/core/dist/council/lessons/io.js
|
|
24280
|
-
import { readFileSync as
|
|
24561
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
24281
24562
|
import { join as join8 } from "node:path";
|
|
24282
24563
|
function readLessonsDeduped(zelariRoot) {
|
|
24283
|
-
const
|
|
24564
|
+
const path51 = join8(zelariRoot, LESSONS_FILE);
|
|
24284
24565
|
try {
|
|
24285
|
-
const raw =
|
|
24566
|
+
const raw = readFileSync11(path51, "utf8");
|
|
24286
24567
|
const byId = /* @__PURE__ */ new Map();
|
|
24287
24568
|
for (const line of raw.split(/\r?\n/)) {
|
|
24288
24569
|
if (!line.trim())
|
|
@@ -24383,8 +24664,8 @@ function keywordsFrom(check2, signature) {
|
|
|
24383
24664
|
return [.../* @__PURE__ */ new Set([...fromId, ...words])].slice(0, 12);
|
|
24384
24665
|
}
|
|
24385
24666
|
function writeLesson(zelariRoot, lesson) {
|
|
24386
|
-
const
|
|
24387
|
-
appendFileSync(
|
|
24667
|
+
const path51 = join9(zelariRoot, LESSONS_FILE);
|
|
24668
|
+
appendFileSync(path51, `${JSON.stringify(lesson)}
|
|
24388
24669
|
`, "utf8");
|
|
24389
24670
|
}
|
|
24390
24671
|
function findSimilar(lessons, signature) {
|
|
@@ -24523,7 +24804,7 @@ var init_recallLessons = __esm({
|
|
|
24523
24804
|
var init_lessons = __esm({
|
|
24524
24805
|
"packages/core/dist/council/lessons/index.js"() {
|
|
24525
24806
|
"use strict";
|
|
24526
|
-
|
|
24807
|
+
init_types4();
|
|
24527
24808
|
init_io();
|
|
24528
24809
|
init_isAnswerLeak();
|
|
24529
24810
|
init_signatures();
|
|
@@ -24533,7 +24814,7 @@ var init_lessons = __esm({
|
|
|
24533
24814
|
});
|
|
24534
24815
|
|
|
24535
24816
|
// packages/core/dist/council/completion/types.js
|
|
24536
|
-
var
|
|
24817
|
+
var init_types5 = __esm({
|
|
24537
24818
|
"packages/core/dist/council/completion/types.js"() {
|
|
24538
24819
|
"use strict";
|
|
24539
24820
|
}
|
|
@@ -24614,7 +24895,7 @@ var init_buildCompletion = __esm({
|
|
|
24614
24895
|
var init_completion2 = __esm({
|
|
24615
24896
|
"packages/core/dist/council/completion/index.js"() {
|
|
24616
24897
|
"use strict";
|
|
24617
|
-
|
|
24898
|
+
init_types5();
|
|
24618
24899
|
init_buildCompletion();
|
|
24619
24900
|
}
|
|
24620
24901
|
});
|
|
@@ -24933,7 +25214,7 @@ var init_council = __esm({
|
|
|
24933
25214
|
});
|
|
24934
25215
|
|
|
24935
25216
|
// packages/core/dist/memory/types.js
|
|
24936
|
-
var
|
|
25217
|
+
var init_types6 = __esm({
|
|
24937
25218
|
"packages/core/dist/memory/types.js"() {
|
|
24938
25219
|
"use strict";
|
|
24939
25220
|
}
|
|
@@ -24997,9 +25278,9 @@ function findCycle(nodes) {
|
|
|
24997
25278
|
if (color.get(start) !== WHITE)
|
|
24998
25279
|
continue;
|
|
24999
25280
|
const stack = [[start, 0]];
|
|
25000
|
-
const
|
|
25281
|
+
const path51 = [];
|
|
25001
25282
|
color.set(start, GRAY);
|
|
25002
|
-
|
|
25283
|
+
path51.push(start);
|
|
25003
25284
|
while (stack.length > 0) {
|
|
25004
25285
|
const top = stack[stack.length - 1];
|
|
25005
25286
|
const [id, idx] = top;
|
|
@@ -25012,17 +25293,17 @@ function findCycle(nodes) {
|
|
|
25012
25293
|
continue;
|
|
25013
25294
|
const c = color.get(dep);
|
|
25014
25295
|
if (c === GRAY) {
|
|
25015
|
-
const at =
|
|
25016
|
-
return [...
|
|
25296
|
+
const at = path51.indexOf(dep);
|
|
25297
|
+
return [...path51.slice(at), dep];
|
|
25017
25298
|
}
|
|
25018
25299
|
if (c === WHITE) {
|
|
25019
25300
|
color.set(dep, GRAY);
|
|
25020
|
-
|
|
25301
|
+
path51.push(dep);
|
|
25021
25302
|
stack.push([dep, 0]);
|
|
25022
25303
|
}
|
|
25023
25304
|
} else {
|
|
25024
25305
|
color.set(id, BLACK);
|
|
25025
|
-
|
|
25306
|
+
path51.pop();
|
|
25026
25307
|
stack.pop();
|
|
25027
25308
|
}
|
|
25028
25309
|
}
|
|
@@ -25649,7 +25930,7 @@ var init_personas = __esm({
|
|
|
25649
25930
|
|
|
25650
25931
|
// packages/core/dist/kraken/runtime/types.js
|
|
25651
25932
|
var PlanError;
|
|
25652
|
-
var
|
|
25933
|
+
var init_types7 = __esm({
|
|
25653
25934
|
"packages/core/dist/kraken/runtime/types.js"() {
|
|
25654
25935
|
"use strict";
|
|
25655
25936
|
PlanError = class extends Error {
|
|
@@ -25747,7 +26028,7 @@ var MAX_BUNDLE_BYTES, FORBIDDEN_TOKENS;
|
|
|
25747
26028
|
var init_sandbox = __esm({
|
|
25748
26029
|
"packages/core/dist/kraken/runtime/sandbox.js"() {
|
|
25749
26030
|
"use strict";
|
|
25750
|
-
|
|
26031
|
+
init_types7();
|
|
25751
26032
|
MAX_BUNDLE_BYTES = 256 * 1024;
|
|
25752
26033
|
FORBIDDEN_TOKENS = [
|
|
25753
26034
|
/\bprocess\b/,
|
|
@@ -25810,7 +26091,7 @@ var init_runner = __esm({
|
|
|
25810
26091
|
"use strict";
|
|
25811
26092
|
init_verdict();
|
|
25812
26093
|
init_personas();
|
|
25813
|
-
|
|
26094
|
+
init_types7();
|
|
25814
26095
|
DEFAULT_MAX_TENTACLES = 200;
|
|
25815
26096
|
DEFAULT_PLAN_TIMEOUT_MS = 30 * 6e4;
|
|
25816
26097
|
ScriptRunner = class {
|
|
@@ -25942,8 +26223,8 @@ var init_runner = __esm({
|
|
|
25942
26223
|
failed: [...this.tentaclesById.values()].filter((r) => r.status === "error"),
|
|
25943
26224
|
pending: []
|
|
25944
26225
|
};
|
|
25945
|
-
const
|
|
25946
|
-
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${
|
|
26226
|
+
const path51 = await this.host.saveSnapshot(snapshot, ".zelari/kraken/snapshots");
|
|
26227
|
+
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${path51}`);
|
|
25947
26228
|
return snapshot;
|
|
25948
26229
|
}
|
|
25949
26230
|
callLog(msg, data) {
|
|
@@ -25994,7 +26275,7 @@ var init_runner = __esm({
|
|
|
25994
26275
|
var init_runtime = __esm({
|
|
25995
26276
|
"packages/core/dist/kraken/runtime/index.js"() {
|
|
25996
26277
|
"use strict";
|
|
25997
|
-
|
|
26278
|
+
init_types7();
|
|
25998
26279
|
init_sandbox();
|
|
25999
26280
|
init_runner();
|
|
26000
26281
|
}
|
|
@@ -26047,6 +26328,7 @@ __export(dist_exports, {
|
|
|
26047
26328
|
LANGUAGE_POLICY_MODULE_TYPE: () => LANGUAGE_POLICY_MODULE_TYPE,
|
|
26048
26329
|
LAYOUT_MOTION_PROPS: () => LAYOUT_MOTION_PROPS,
|
|
26049
26330
|
LESSONS_FILE: () => LESSONS_FILE,
|
|
26331
|
+
LifecycleHookRunner: () => LifecycleHookRunner,
|
|
26050
26332
|
MAX_DELIVERY_ATTEMPTS: () => MAX_DELIVERY_ATTEMPTS,
|
|
26051
26333
|
MAX_FINDINGS_CHARS: () => MAX_FINDINGS_CHARS,
|
|
26052
26334
|
MAX_RETRY_PER_MEMBER: () => MAX_RETRY_PER_MEMBER,
|
|
@@ -26155,6 +26437,7 @@ __export(dist_exports, {
|
|
|
26155
26437
|
getToolDescriptions: () => getToolDescriptions,
|
|
26156
26438
|
hasInteractiveClarification: () => hasInteractiveClarification,
|
|
26157
26439
|
hashToolCall: () => hashToolCall,
|
|
26440
|
+
hookMatches: () => hookMatches,
|
|
26158
26441
|
isAnswerLeak: () => isAnswerLeak,
|
|
26159
26442
|
isBrainAgentEndEvent: () => isBrainAgentEndEvent,
|
|
26160
26443
|
isBrainAgentStartEvent: () => isBrainAgentStartEvent,
|
|
@@ -26187,6 +26470,7 @@ __export(dist_exports, {
|
|
|
26187
26470
|
normalizeLoopUnit: () => normalizeLoopUnit,
|
|
26188
26471
|
normalizeScopePath: () => normalizeScopePath,
|
|
26189
26472
|
normalizeTextToolArgs: () => normalizeTextToolArgs,
|
|
26473
|
+
normalizeToolName: () => normalizeToolName,
|
|
26190
26474
|
parseClarificationRequest: () => parseClarificationRequest,
|
|
26191
26475
|
parseEvidenceTier: () => parseEvidenceTier,
|
|
26192
26476
|
parseMinimaxStyleToolCalls: () => parseMinimaxStyleToolCalls,
|
|
@@ -26241,6 +26525,7 @@ __export(dist_exports, {
|
|
|
26241
26525
|
taskMatchesNfrKeywords: () => taskMatchesNfrKeywords,
|
|
26242
26526
|
tierAtLeast: () => tierAtLeast,
|
|
26243
26527
|
tokenizeForSignature: () => tokenizeForSignature,
|
|
26528
|
+
toolMatches: () => toolMatches,
|
|
26244
26529
|
topoLevels: () => topoLevels,
|
|
26245
26530
|
unregisterCustomTool: () => unregisterCustomTool,
|
|
26246
26531
|
unregisterSkill: () => unregisterSkill,
|
|
@@ -26263,7 +26548,7 @@ var init_dist = __esm({
|
|
|
26263
26548
|
init_harness();
|
|
26264
26549
|
init_council();
|
|
26265
26550
|
init_skills2();
|
|
26266
|
-
|
|
26551
|
+
init_types6();
|
|
26267
26552
|
init_state();
|
|
26268
26553
|
init_kraken();
|
|
26269
26554
|
}
|
|
@@ -26961,9 +27246,9 @@ function spillToolOutput(fullText, meta3) {
|
|
|
26961
27246
|
const rnd = randomBytes(3).toString("hex");
|
|
26962
27247
|
const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
|
|
26963
27248
|
const file2 = `${stamp}-${safeTool}-${hash3}-${rnd}.txt`;
|
|
26964
|
-
const
|
|
26965
|
-
writeFileSync10(
|
|
26966
|
-
return
|
|
27249
|
+
const path51 = join11(dir, file2);
|
|
27250
|
+
writeFileSync10(path51, fullText, "utf8");
|
|
27251
|
+
return path51;
|
|
26967
27252
|
} catch {
|
|
26968
27253
|
return null;
|
|
26969
27254
|
}
|
|
@@ -27009,10 +27294,10 @@ function truncateToolResult(text, capOrOpts = TOOL_RESULT_LINE_CAP) {
|
|
|
27009
27294
|
${tail}`;
|
|
27010
27295
|
}
|
|
27011
27296
|
if (doSpill) {
|
|
27012
|
-
const
|
|
27013
|
-
if (
|
|
27297
|
+
const path51 = spillToolOutput(text, { toolName: opts.toolName });
|
|
27298
|
+
if (path51) {
|
|
27014
27299
|
const spillNote = `
|
|
27015
|
-
\u2026 [full output spilled to: ${
|
|
27300
|
+
\u2026 [full output spilled to: ${path51} \u2014 re-read with read_file if you need the complete text] \u2026`;
|
|
27016
27301
|
if (preview.includes("] \u2026\n")) {
|
|
27017
27302
|
preview = preview.replace("] \u2026\n", `] \u2026${spillNote}
|
|
27018
27303
|
`);
|
|
@@ -27062,12 +27347,21 @@ var init_registry2 = __esm({
|
|
|
27062
27347
|
})();
|
|
27063
27348
|
ToolRegistry = class {
|
|
27064
27349
|
tools = /* @__PURE__ */ new Map();
|
|
27350
|
+
/** v0.10.0: lifecycle hooks (PreToolUse/PostToolUse). Null = no hooks. */
|
|
27351
|
+
lifecycleHooks = null;
|
|
27065
27352
|
register(def) {
|
|
27066
27353
|
this.tools.set(def.name, def);
|
|
27067
27354
|
}
|
|
27068
27355
|
get(name) {
|
|
27069
27356
|
return this.tools.get(name);
|
|
27070
27357
|
}
|
|
27358
|
+
/** v0.10.0: attach the fail-open lifecycle hook runner (null to disable). */
|
|
27359
|
+
setLifecycleHooks(runner) {
|
|
27360
|
+
this.lifecycleHooks = runner;
|
|
27361
|
+
}
|
|
27362
|
+
getLifecycleHooks() {
|
|
27363
|
+
return this.lifecycleHooks;
|
|
27364
|
+
}
|
|
27071
27365
|
list() {
|
|
27072
27366
|
return Array.from(this.tools.keys());
|
|
27073
27367
|
}
|
|
@@ -27100,6 +27394,18 @@ var init_registry2 = __esm({
|
|
|
27100
27394
|
},
|
|
27101
27395
|
sessionId: options.sessionId ?? "default"
|
|
27102
27396
|
};
|
|
27397
|
+
if (this.lifecycleHooks) {
|
|
27398
|
+
try {
|
|
27399
|
+
const pre = await this.lifecycleHooks.runPreToolUse(name, parsed.data, {
|
|
27400
|
+
sessionId: ctx.sessionId,
|
|
27401
|
+
cwd: ctx.cwd
|
|
27402
|
+
});
|
|
27403
|
+
if (!pre.ok) {
|
|
27404
|
+
return typedErr(`[hook:${pre.hookName ?? "unknown"}] ${pre.reason ?? "denied"}`);
|
|
27405
|
+
}
|
|
27406
|
+
} catch (hookErr) {
|
|
27407
|
+
}
|
|
27408
|
+
}
|
|
27103
27409
|
try {
|
|
27104
27410
|
const result = await Promise.race([
|
|
27105
27411
|
tool.execute(parsed.data, ctx),
|
|
@@ -27128,6 +27434,17 @@ var init_registry2 = __esm({
|
|
|
27128
27434
|
}
|
|
27129
27435
|
}
|
|
27130
27436
|
}
|
|
27437
|
+
if (this.lifecycleHooks) {
|
|
27438
|
+
try {
|
|
27439
|
+
await this.lifecycleHooks.runPostToolUse(name, parsed.data, result, {
|
|
27440
|
+
sessionId: ctx.sessionId,
|
|
27441
|
+
cwd: ctx.cwd,
|
|
27442
|
+
ok: result.ok,
|
|
27443
|
+
error: result.ok ? void 0 : "error" in result ? result.error : void 0
|
|
27444
|
+
});
|
|
27445
|
+
} catch {
|
|
27446
|
+
}
|
|
27447
|
+
}
|
|
27131
27448
|
return result;
|
|
27132
27449
|
} catch (err) {
|
|
27133
27450
|
const error51 = err instanceof Error ? err.message : String(err);
|
|
@@ -27150,14 +27467,14 @@ var init_registry2 = __esm({
|
|
|
27150
27467
|
});
|
|
27151
27468
|
|
|
27152
27469
|
// src/cli/safety/sandboxPath.ts
|
|
27153
|
-
import
|
|
27470
|
+
import path15 from "node:path";
|
|
27154
27471
|
function resolveSandboxedPath(userPath, options = {}) {
|
|
27155
27472
|
if (typeof userPath !== "string" || userPath.length === 0) {
|
|
27156
27473
|
throw new SandboxViolationError("Empty path", userPath, "");
|
|
27157
27474
|
}
|
|
27158
|
-
const root =
|
|
27159
|
-
const resolved =
|
|
27160
|
-
const rootWithSep = root.endsWith(
|
|
27475
|
+
const root = path15.resolve(options.root ?? process.cwd());
|
|
27476
|
+
const resolved = path15.isAbsolute(userPath) ? path15.resolve(userPath) : path15.resolve(root, userPath);
|
|
27477
|
+
const rootWithSep = root.endsWith(path15.sep) ? root : root + path15.sep;
|
|
27161
27478
|
if (resolved !== root && !resolved.startsWith(rootWithSep)) {
|
|
27162
27479
|
throw new SandboxViolationError(
|
|
27163
27480
|
`Path escapes sandbox root: ${userPath} \u2192 ${resolved} (root: ${root})`,
|
|
@@ -27245,12 +27562,12 @@ __export(auditLogger_exports, {
|
|
|
27245
27562
|
AuditLogger: () => AuditLogger
|
|
27246
27563
|
});
|
|
27247
27564
|
import { promises as fs11 } from "node:fs";
|
|
27248
|
-
import
|
|
27565
|
+
import path16 from "node:path";
|
|
27249
27566
|
import os6 from "node:os";
|
|
27250
27567
|
function defaultAuditPath() {
|
|
27251
27568
|
const override = process.env.ANATHEMA_AUDIT_LOG;
|
|
27252
27569
|
if (override && override.trim().length > 0) return override;
|
|
27253
|
-
return
|
|
27570
|
+
return path16.join(os6.tmpdir(), "zelari-code", "audit.jsonl");
|
|
27254
27571
|
}
|
|
27255
27572
|
function redactArgs(args) {
|
|
27256
27573
|
const redacted = {};
|
|
@@ -27293,7 +27610,7 @@ var init_auditLogger = __esm({
|
|
|
27293
27610
|
async append(entry) {
|
|
27294
27611
|
const line = JSON.stringify(entry) + "\n";
|
|
27295
27612
|
this.writeQueue = this.writeQueue.then(async () => {
|
|
27296
|
-
await fs11.mkdir(
|
|
27613
|
+
await fs11.mkdir(path16.dirname(this.logPath), { recursive: true });
|
|
27297
27614
|
await fs11.appendFile(this.logPath, line, "utf-8");
|
|
27298
27615
|
});
|
|
27299
27616
|
return this.writeQueue;
|
|
@@ -27353,9 +27670,9 @@ var init_cmdline = __esm({
|
|
|
27353
27670
|
});
|
|
27354
27671
|
|
|
27355
27672
|
// src/cli/diagnostics/engine.ts
|
|
27356
|
-
import { spawn as
|
|
27673
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
27357
27674
|
import { existsSync as existsSync12 } from "node:fs";
|
|
27358
|
-
import
|
|
27675
|
+
import path17 from "node:path";
|
|
27359
27676
|
function parseEslintJson(stdout, _file2) {
|
|
27360
27677
|
const json2 = safeJson(stdout);
|
|
27361
27678
|
if (!Array.isArray(json2)) return [];
|
|
@@ -27414,7 +27731,7 @@ function safeJson(s) {
|
|
|
27414
27731
|
}
|
|
27415
27732
|
}
|
|
27416
27733
|
function providerForFile(file2, providers = DEFAULT_PROVIDERS) {
|
|
27417
|
-
const ext =
|
|
27734
|
+
const ext = path17.extname(file2).toLowerCase();
|
|
27418
27735
|
return providers.find((p3) => p3.extensions.includes(ext)) ?? null;
|
|
27419
27736
|
}
|
|
27420
27737
|
function resolveBin(bin, cwd) {
|
|
@@ -27422,10 +27739,10 @@ function resolveBin(bin, cwd) {
|
|
|
27422
27739
|
let dir = cwd;
|
|
27423
27740
|
for (let i = 0; i < 6; i += 1) {
|
|
27424
27741
|
for (const suffix of suffixes) {
|
|
27425
|
-
const candidate =
|
|
27742
|
+
const candidate = path17.join(dir, "node_modules", ".bin", `${bin}${suffix}`);
|
|
27426
27743
|
if (existsSync12(candidate)) return candidate;
|
|
27427
27744
|
}
|
|
27428
|
-
const parent =
|
|
27745
|
+
const parent = path17.dirname(dir);
|
|
27429
27746
|
if (parent === dir) break;
|
|
27430
27747
|
dir = parent;
|
|
27431
27748
|
}
|
|
@@ -27498,7 +27815,7 @@ var init_engine = __esm({
|
|
|
27498
27815
|
};
|
|
27499
27816
|
let child;
|
|
27500
27817
|
try {
|
|
27501
|
-
child = process.platform === "win32" ?
|
|
27818
|
+
child = process.platform === "win32" ? spawn3(buildCmdLine(cmd, args), { cwd: opts.cwd, shell: true }) : spawn3(cmd, args, { cwd: opts.cwd });
|
|
27502
27819
|
} catch {
|
|
27503
27820
|
done({ code: null, stdout: "", stderr: "" });
|
|
27504
27821
|
return;
|
|
@@ -27529,14 +27846,14 @@ var init_engine = __esm({
|
|
|
27529
27846
|
});
|
|
27530
27847
|
|
|
27531
27848
|
// src/cli/tools/krakenRadio.ts
|
|
27532
|
-
import { appendFileSync as appendFileSync3, existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as
|
|
27533
|
-
import
|
|
27849
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync13, readdirSync as readdirSync2 } from "node:fs";
|
|
27850
|
+
import path18 from "node:path";
|
|
27534
27851
|
function radioDir(cwd) {
|
|
27535
|
-
return
|
|
27852
|
+
return path18.join(cwd, ".zelari", "radio");
|
|
27536
27853
|
}
|
|
27537
27854
|
function radioPath(cwd, sessionId) {
|
|
27538
27855
|
const safe = (sessionId || "default").replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
27539
|
-
return
|
|
27856
|
+
return path18.join(radioDir(cwd), `${safe}.jsonl`);
|
|
27540
27857
|
}
|
|
27541
27858
|
function appendKrakenRadio(cwd, sessionId, event) {
|
|
27542
27859
|
try {
|
|
@@ -27563,7 +27880,7 @@ function readKrakenRadio(cwd, sessionId, limit = 50) {
|
|
|
27563
27880
|
try {
|
|
27564
27881
|
const file2 = radioPath(cwd, sessionId);
|
|
27565
27882
|
if (!existsSync13(file2)) return [];
|
|
27566
|
-
const lines =
|
|
27883
|
+
const lines = readFileSync13(file2, "utf8").split(/\r?\n/).filter(Boolean);
|
|
27567
27884
|
const slice = lines.slice(-Math.max(1, limit));
|
|
27568
27885
|
const out = [];
|
|
27569
27886
|
for (const line of slice) {
|
|
@@ -27586,7 +27903,7 @@ function formatKrakenRadioStatus(cwd, sessionId, limit = 12) {
|
|
|
27586
27903
|
const flag = e.ok === false ? "\u2717" : e.ok === true ? "\u2713" : "\xB7";
|
|
27587
27904
|
const ms = e.durationMs != null ? ` ${e.durationMs}ms` : "";
|
|
27588
27905
|
const model = e.model ? ` [${e.model}]` : "";
|
|
27589
|
-
const wt = e.worktree ? ` wt=${
|
|
27906
|
+
const wt = e.worktree ? ` wt=${path18.basename(e.worktree)}` : "";
|
|
27590
27907
|
const detail = e.detail ? ` \u2014 ${e.detail.slice(0, 120)}` : "";
|
|
27591
27908
|
return `${flag} ${e.ts.slice(11, 19)} ${e.kind} ${e.agent} "${e.description}"${model}${wt}${ms}${detail}`;
|
|
27592
27909
|
});
|
|
@@ -27601,7 +27918,7 @@ var init_krakenRadio = __esm({
|
|
|
27601
27918
|
// src/cli/tools/krakenWorktree.ts
|
|
27602
27919
|
import { execFile as execFile2 } from "node:child_process";
|
|
27603
27920
|
import { existsSync as existsSync14, mkdirSync as mkdirSync8, rmSync } from "node:fs";
|
|
27604
|
-
import
|
|
27921
|
+
import path19 from "node:path";
|
|
27605
27922
|
import { promisify } from "node:util";
|
|
27606
27923
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
27607
27924
|
function isKrakenWorktreeEnabled(env = process.env) {
|
|
@@ -27649,8 +27966,8 @@ async function createKrakenWorktree(cwd, label) {
|
|
|
27649
27966
|
const id = `${Date.now().toString(36)}-${randomBytes2(3).toString("hex")}`;
|
|
27650
27967
|
const slug = (label ?? "task").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 24) || "task";
|
|
27651
27968
|
const branch = `kraken/${slug}-${id}`;
|
|
27652
|
-
const wtRoot =
|
|
27653
|
-
const wtPath =
|
|
27969
|
+
const wtRoot = path19.join(repoRoot, ".zelari", "worktrees");
|
|
27970
|
+
const wtPath = path19.join(wtRoot, `kraken-${id}`);
|
|
27654
27971
|
try {
|
|
27655
27972
|
if (!existsSync14(wtRoot)) mkdirSync8(wtRoot, { recursive: true });
|
|
27656
27973
|
} catch {
|
|
@@ -28243,7 +28560,7 @@ var init_askUser = __esm({
|
|
|
28243
28560
|
});
|
|
28244
28561
|
|
|
28245
28562
|
// src/cli/skillsMd.ts
|
|
28246
|
-
import { existsSync as existsSync15, readdirSync as
|
|
28563
|
+
import { existsSync as existsSync15, readdirSync as readdirSync3, readFileSync as readFileSync14 } from "node:fs";
|
|
28247
28564
|
import { join as join12 } from "node:path";
|
|
28248
28565
|
import { homedir as homedir4 } from "node:os";
|
|
28249
28566
|
function skillMdSearchDirs(projectRoot = process.cwd()) {
|
|
@@ -28312,7 +28629,7 @@ function loadSkillMdSkills(projectRoot = process.cwd(), options = {}) {
|
|
|
28312
28629
|
if (!existsSync15(dir)) continue;
|
|
28313
28630
|
let entries;
|
|
28314
28631
|
try {
|
|
28315
|
-
entries =
|
|
28632
|
+
entries = readdirSync3(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
28316
28633
|
} catch {
|
|
28317
28634
|
continue;
|
|
28318
28635
|
}
|
|
@@ -28320,7 +28637,7 @@ function loadSkillMdSkills(projectRoot = process.cwd(), options = {}) {
|
|
|
28320
28637
|
const skillPath = join12(dir, entry, "SKILL.md");
|
|
28321
28638
|
if (!existsSync15(skillPath)) continue;
|
|
28322
28639
|
try {
|
|
28323
|
-
const parsed = parseSkillMd(
|
|
28640
|
+
const parsed = parseSkillMd(readFileSync14(skillPath, "utf8"), skillPath);
|
|
28324
28641
|
if (!parsed) {
|
|
28325
28642
|
summary.skipped.push({ path: skillPath, reason: "missing/invalid frontmatter (name, description) or empty body" });
|
|
28326
28643
|
continue;
|
|
@@ -28725,9 +29042,9 @@ var init_client = __esm({
|
|
|
28725
29042
|
});
|
|
28726
29043
|
|
|
28727
29044
|
// src/cli/lsp/servers.ts
|
|
28728
|
-
import
|
|
29045
|
+
import path20 from "node:path";
|
|
28729
29046
|
function languageIdForFile(file2) {
|
|
28730
|
-
const ext =
|
|
29047
|
+
const ext = path20.extname(file2).toLowerCase();
|
|
28731
29048
|
const map2 = {
|
|
28732
29049
|
".ts": "typescript",
|
|
28733
29050
|
".tsx": "typescriptreact",
|
|
@@ -28742,7 +29059,7 @@ function languageIdForFile(file2) {
|
|
|
28742
29059
|
return map2[ext] ?? "plaintext";
|
|
28743
29060
|
}
|
|
28744
29061
|
function serverForFile(file2, servers = LSP_SERVERS) {
|
|
28745
|
-
const ext =
|
|
29062
|
+
const ext = path20.extname(file2).toLowerCase();
|
|
28746
29063
|
return servers.find((s) => s.extensions.includes(ext)) ?? null;
|
|
28747
29064
|
}
|
|
28748
29065
|
function resolveServerCommand(file2, cwd, servers = LSP_SERVERS) {
|
|
@@ -28791,8 +29108,8 @@ var init_servers = __esm({
|
|
|
28791
29108
|
});
|
|
28792
29109
|
|
|
28793
29110
|
// src/cli/lsp/manager.ts
|
|
28794
|
-
import { spawn as
|
|
28795
|
-
import { readFileSync as
|
|
29111
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
29112
|
+
import { readFileSync as readFileSync15 } from "node:fs";
|
|
28796
29113
|
function processTransport(child) {
|
|
28797
29114
|
return {
|
|
28798
29115
|
send: (data) => {
|
|
@@ -28927,7 +29244,7 @@ var init_manager = __esm({
|
|
|
28927
29244
|
// languages already flagged as unavailable
|
|
28928
29245
|
constructor(options = {}) {
|
|
28929
29246
|
this.cwd = options.cwd ?? process.cwd();
|
|
28930
|
-
this.spawnImpl = options.spawnImpl ??
|
|
29247
|
+
this.spawnImpl = options.spawnImpl ?? spawn4;
|
|
28931
29248
|
this.timeoutMs = options.timeoutMs ?? 15e3;
|
|
28932
29249
|
this.onWarn = options.onWarn ?? ((m) => console.error(m));
|
|
28933
29250
|
}
|
|
@@ -28995,7 +29312,7 @@ var init_manager = __esm({
|
|
|
28995
29312
|
const uri = pathToUri(file2);
|
|
28996
29313
|
let text;
|
|
28997
29314
|
try {
|
|
28998
|
-
text =
|
|
29315
|
+
text = readFileSync15(file2, "utf8");
|
|
28999
29316
|
} catch {
|
|
29000
29317
|
text = "";
|
|
29001
29318
|
}
|
|
@@ -29110,9 +29427,9 @@ var init_manager = __esm({
|
|
|
29110
29427
|
|
|
29111
29428
|
// src/cli/ast/engine.ts
|
|
29112
29429
|
import { readFile } from "node:fs/promises";
|
|
29113
|
-
import
|
|
29430
|
+
import path21 from "node:path";
|
|
29114
29431
|
function isAstSupported(file2) {
|
|
29115
|
-
return TS_EXTENSIONS.has(
|
|
29432
|
+
return TS_EXTENSIONS.has(path21.extname(file2).toLowerCase());
|
|
29116
29433
|
}
|
|
29117
29434
|
function loadTs() {
|
|
29118
29435
|
if (!tsPromise) {
|
|
@@ -29132,7 +29449,7 @@ async function parseFileSymbols(file2) {
|
|
|
29132
29449
|
}
|
|
29133
29450
|
let source;
|
|
29134
29451
|
try {
|
|
29135
|
-
source = ts.createSourceFile(
|
|
29452
|
+
source = ts.createSourceFile(path21.basename(file2), text, ts.ScriptTarget.Latest, true);
|
|
29136
29453
|
} catch {
|
|
29137
29454
|
return [];
|
|
29138
29455
|
}
|
|
@@ -29317,13 +29634,13 @@ var init_store = __esm({
|
|
|
29317
29634
|
});
|
|
29318
29635
|
|
|
29319
29636
|
// src/cli/semantic/index.ts
|
|
29320
|
-
import { promises as fs12, existsSync as existsSync16, readFileSync as
|
|
29637
|
+
import { promises as fs12, existsSync as existsSync16, readFileSync as readFileSync16 } from "node:fs";
|
|
29321
29638
|
import { homedir as homedir5 } from "node:os";
|
|
29322
|
-
import
|
|
29639
|
+
import path22 from "node:path";
|
|
29323
29640
|
import { createHash as createHash2 } from "node:crypto";
|
|
29324
29641
|
function getIndexPath(root) {
|
|
29325
|
-
const hash3 = createHash2("sha1").update(
|
|
29326
|
-
return process.env.ZELARI_SEMANTIC_FILE ??
|
|
29642
|
+
const hash3 = createHash2("sha1").update(path22.resolve(root)).digest("hex").slice(0, 16);
|
|
29643
|
+
return process.env.ZELARI_SEMANTIC_FILE ?? path22.join(homedir5(), ".tmp", "zelari-code", "semantic", `${hash3}.json`);
|
|
29327
29644
|
}
|
|
29328
29645
|
async function collectSourceFiles(root, maxFiles = 1500) {
|
|
29329
29646
|
const out = [];
|
|
@@ -29341,11 +29658,11 @@ async function collectSourceFiles(root, maxFiles = 1500) {
|
|
|
29341
29658
|
if (entry.isDirectory() && IGNORE_DIRS.has(entry.name)) continue;
|
|
29342
29659
|
if (entry.isDirectory()) continue;
|
|
29343
29660
|
}
|
|
29344
|
-
const full =
|
|
29661
|
+
const full = path22.join(dir, entry.name);
|
|
29345
29662
|
if (entry.isDirectory()) {
|
|
29346
29663
|
if (IGNORE_DIRS.has(entry.name)) continue;
|
|
29347
29664
|
await walk2(full);
|
|
29348
|
-
} else if (SOURCE_EXTENSIONS.has(
|
|
29665
|
+
} else if (SOURCE_EXTENSIONS.has(path22.extname(entry.name).toLowerCase())) {
|
|
29349
29666
|
out.push(full);
|
|
29350
29667
|
}
|
|
29351
29668
|
}
|
|
@@ -29394,7 +29711,7 @@ async function buildIndex(files, embed, options) {
|
|
|
29394
29711
|
}
|
|
29395
29712
|
async function saveIndex(root, data) {
|
|
29396
29713
|
const file2 = getIndexPath(root);
|
|
29397
|
-
await fs12.mkdir(
|
|
29714
|
+
await fs12.mkdir(path22.dirname(file2), { recursive: true });
|
|
29398
29715
|
const tmp = `${file2}.tmp-${process.pid}`;
|
|
29399
29716
|
await fs12.writeFile(tmp, JSON.stringify(data), "utf8");
|
|
29400
29717
|
await fs12.rename(tmp, file2);
|
|
@@ -29403,7 +29720,7 @@ function loadIndex(root) {
|
|
|
29403
29720
|
const file2 = getIndexPath(root);
|
|
29404
29721
|
if (!existsSync16(file2)) return null;
|
|
29405
29722
|
try {
|
|
29406
|
-
const parsed = JSON.parse(
|
|
29723
|
+
const parsed = JSON.parse(readFileSync16(file2, "utf8"));
|
|
29407
29724
|
if (parsed && Array.isArray(parsed.chunks)) return parsed;
|
|
29408
29725
|
} catch {
|
|
29409
29726
|
}
|
|
@@ -29546,7 +29863,7 @@ var init_provider = __esm({
|
|
|
29546
29863
|
});
|
|
29547
29864
|
|
|
29548
29865
|
// src/cli/semantic/tools.ts
|
|
29549
|
-
import
|
|
29866
|
+
import path23 from "node:path";
|
|
29550
29867
|
function createSemanticTool(deps) {
|
|
29551
29868
|
const buildEmbedFn = deps.buildEmbedFn ?? buildProviderEmbedFn;
|
|
29552
29869
|
return {
|
|
@@ -29573,7 +29890,7 @@ function createSemanticTool(deps) {
|
|
|
29573
29890
|
return typedOk({
|
|
29574
29891
|
count: res.hits.length,
|
|
29575
29892
|
results: res.hits.map((h) => ({
|
|
29576
|
-
location: `${
|
|
29893
|
+
location: `${path23.relative(deps.root, h.file) || h.file}:${h.startLine}-${h.endLine}`,
|
|
29577
29894
|
score: Number(h.score.toFixed(3)),
|
|
29578
29895
|
preview: h.text.length > 400 ? `${h.text.slice(0, 400)}\u2026` : h.text
|
|
29579
29896
|
}))
|
|
@@ -29593,7 +29910,7 @@ var init_tools4 = __esm({
|
|
|
29593
29910
|
|
|
29594
29911
|
// src/cli/browser/driver.ts
|
|
29595
29912
|
import { createRequire } from "node:module";
|
|
29596
|
-
import
|
|
29913
|
+
import path24 from "node:path";
|
|
29597
29914
|
import { pathToFileURL } from "node:url";
|
|
29598
29915
|
function asPlaywright(mod) {
|
|
29599
29916
|
if (!mod || typeof mod !== "object") return null;
|
|
@@ -29604,10 +29921,10 @@ function asPlaywright(mod) {
|
|
|
29604
29921
|
return null;
|
|
29605
29922
|
}
|
|
29606
29923
|
async function loadPlaywright(cwd) {
|
|
29607
|
-
const base = cwd && cwd.length > 0 ?
|
|
29924
|
+
const base = cwd && cwd.length > 0 ? path24.resolve(cwd) : void 0;
|
|
29608
29925
|
if (base) {
|
|
29609
29926
|
try {
|
|
29610
|
-
const req = createRequire(
|
|
29927
|
+
const req = createRequire(path24.join(base, "package.json"));
|
|
29611
29928
|
const resolved = req.resolve("playwright");
|
|
29612
29929
|
const mod = await import(pathToFileURL(resolved).href);
|
|
29613
29930
|
const pw = asPlaywright(mod);
|
|
@@ -29822,7 +30139,7 @@ var init_driver = __esm({
|
|
|
29822
30139
|
});
|
|
29823
30140
|
|
|
29824
30141
|
// src/cli/browser/tools.ts
|
|
29825
|
-
import
|
|
30142
|
+
import path25 from "node:path";
|
|
29826
30143
|
import os7 from "node:os";
|
|
29827
30144
|
function createBrowserTool(deps = {}) {
|
|
29828
30145
|
return {
|
|
@@ -29841,7 +30158,7 @@ function createBrowserTool(deps = {}) {
|
|
|
29841
30158
|
execute: async (args, ctx) => {
|
|
29842
30159
|
const a = args;
|
|
29843
30160
|
const dir = deps.screenshotDir ?? os7.tmpdir();
|
|
29844
|
-
const screenshotPath = a.screenshot === false ? void 0 :
|
|
30161
|
+
const screenshotPath = a.screenshot === false ? void 0 : path25.join(dir, `zelari-browser-${Date.now()}.png`);
|
|
29845
30162
|
const result = await runBrowserCheck(
|
|
29846
30163
|
{
|
|
29847
30164
|
url: a.url,
|
|
@@ -29935,12 +30252,12 @@ import {
|
|
|
29935
30252
|
chmodSync,
|
|
29936
30253
|
existsSync as existsSync17,
|
|
29937
30254
|
mkdirSync as mkdirSync9,
|
|
29938
|
-
readFileSync as
|
|
30255
|
+
readFileSync as readFileSync17,
|
|
29939
30256
|
writeFileSync as writeFileSync11
|
|
29940
30257
|
} from "node:fs";
|
|
29941
30258
|
import { dirname as dirname2, join as join13 } from "node:path";
|
|
29942
30259
|
import { homedir as homedir6 } from "node:os";
|
|
29943
|
-
import { spawn as
|
|
30260
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
29944
30261
|
function getSshTargetsPath() {
|
|
29945
30262
|
return join13(homedir6(), ".zelari-code", "ssh-targets.json");
|
|
29946
30263
|
}
|
|
@@ -29953,21 +30270,21 @@ function normalizeAuth(auth) {
|
|
|
29953
30270
|
return "agent";
|
|
29954
30271
|
}
|
|
29955
30272
|
function readSecrets() {
|
|
29956
|
-
const
|
|
29957
|
-
if (!existsSync17(
|
|
30273
|
+
const path51 = getSshSecretsPath();
|
|
30274
|
+
if (!existsSync17(path51)) return {};
|
|
29958
30275
|
try {
|
|
29959
|
-
return JSON.parse(
|
|
30276
|
+
return JSON.parse(readFileSync17(path51, "utf8"));
|
|
29960
30277
|
} catch {
|
|
29961
30278
|
return {};
|
|
29962
30279
|
}
|
|
29963
30280
|
}
|
|
29964
30281
|
function writeSecrets(data) {
|
|
29965
|
-
const
|
|
29966
|
-
mkdirSync9(dirname2(
|
|
29967
|
-
writeFileSync11(
|
|
30282
|
+
const path51 = getSshSecretsPath();
|
|
30283
|
+
mkdirSync9(dirname2(path51), { recursive: true });
|
|
30284
|
+
writeFileSync11(path51, `${JSON.stringify(data, null, 2)}
|
|
29968
30285
|
`, "utf8");
|
|
29969
30286
|
try {
|
|
29970
|
-
chmodSync(
|
|
30287
|
+
chmodSync(path51, 384);
|
|
29971
30288
|
} catch {
|
|
29972
30289
|
}
|
|
29973
30290
|
}
|
|
@@ -29996,10 +30313,10 @@ function deleteSshPassword(id) {
|
|
|
29996
30313
|
writeSecrets({ passwords });
|
|
29997
30314
|
}
|
|
29998
30315
|
function readStore2() {
|
|
29999
|
-
const
|
|
30000
|
-
if (!existsSync17(
|
|
30316
|
+
const path51 = getSshTargetsPath();
|
|
30317
|
+
if (!existsSync17(path51)) return [];
|
|
30001
30318
|
try {
|
|
30002
|
-
const parsed = JSON.parse(
|
|
30319
|
+
const parsed = JSON.parse(readFileSync17(path51, "utf8"));
|
|
30003
30320
|
const list = Array.isArray(parsed.targets) ? parsed.targets : [];
|
|
30004
30321
|
return list.filter(
|
|
30005
30322
|
(t) => t && typeof t.id === "string" && typeof t.host === "string" && typeof t.user === "string"
|
|
@@ -30014,11 +30331,11 @@ function readStore2() {
|
|
|
30014
30331
|
}
|
|
30015
30332
|
}
|
|
30016
30333
|
function writeStore2(targets) {
|
|
30017
|
-
const
|
|
30018
|
-
mkdirSync9(dirname2(
|
|
30334
|
+
const path51 = getSshTargetsPath();
|
|
30335
|
+
mkdirSync9(dirname2(path51), { recursive: true });
|
|
30019
30336
|
const clean = targets.map(({ hasPassword: _hp, ...t }) => t);
|
|
30020
30337
|
writeFileSync11(
|
|
30021
|
-
|
|
30338
|
+
path51,
|
|
30022
30339
|
`${JSON.stringify({ targets: clean }, null, 2)}
|
|
30023
30340
|
`,
|
|
30024
30341
|
"utf8"
|
|
@@ -30170,7 +30487,7 @@ function runSsh(target, remoteCommand, timeoutMs = 6e4) {
|
|
|
30170
30487
|
if (!env.DISPLAY) env.DISPLAY = "1";
|
|
30171
30488
|
env.ZELARI_SSH_ASKPASS_PASS = pass;
|
|
30172
30489
|
}
|
|
30173
|
-
const child =
|
|
30490
|
+
const child = spawn5("ssh", args, {
|
|
30174
30491
|
windowsHide: true,
|
|
30175
30492
|
env,
|
|
30176
30493
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -30213,7 +30530,7 @@ function readSshPublicKey(keyOrPubPath) {
|
|
|
30213
30530
|
for (const p3 of candidates) {
|
|
30214
30531
|
if (!existsSync17(p3)) continue;
|
|
30215
30532
|
try {
|
|
30216
|
-
const content =
|
|
30533
|
+
const content = readFileSync17(p3, "utf8").trim();
|
|
30217
30534
|
if (!content) continue;
|
|
30218
30535
|
if (/BEGIN .*PRIVATE KEY/i.test(content)) {
|
|
30219
30536
|
return {
|
|
@@ -30264,11 +30581,11 @@ function formatSshTargetsForPrompt() {
|
|
|
30264
30581
|
];
|
|
30265
30582
|
for (const t of targets) {
|
|
30266
30583
|
const tags = t.tags?.length ? ` tags=[${t.tags.join(",")}]` : "";
|
|
30267
|
-
const
|
|
30584
|
+
const path51 = t.defaultRemotePath ? ` remotePath=${t.defaultRemotePath}` : "";
|
|
30268
30585
|
const allow = t.allowedCommands?.length ? ` allowed=${t.allowedCommands.join("|")}` : " allowed=status-only";
|
|
30269
30586
|
const auth = t.auth === "password" ? " auth=password" : t.auth === "keyPath" ? " auth=key" : " auth=agent";
|
|
30270
30587
|
lines.push(
|
|
30271
|
-
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${
|
|
30588
|
+
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${path51}${tags}${allow}`
|
|
30272
30589
|
);
|
|
30273
30590
|
}
|
|
30274
30591
|
return lines.join("\n");
|
|
@@ -30395,10 +30712,10 @@ var init_tools6 = __esm({
|
|
|
30395
30712
|
|
|
30396
30713
|
// src/cli/workspace/worldModel.ts
|
|
30397
30714
|
import { promises as fs13 } from "node:fs";
|
|
30398
|
-
import
|
|
30399
|
-
import { spawn as
|
|
30715
|
+
import path26 from "node:path";
|
|
30716
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
30400
30717
|
function worldDir(cwd) {
|
|
30401
|
-
return
|
|
30718
|
+
return path26.join(cwd, WORLD_DIR_NAME);
|
|
30402
30719
|
}
|
|
30403
30720
|
async function ensureWorldDir(cwd) {
|
|
30404
30721
|
const dir = worldDir(cwd);
|
|
@@ -30408,10 +30725,10 @@ async function ensureWorldDir(cwd) {
|
|
|
30408
30725
|
async function appendTimeline(cwd, entry) {
|
|
30409
30726
|
const dir = await ensureWorldDir(cwd);
|
|
30410
30727
|
const line = JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), ...entry }) + "\n";
|
|
30411
|
-
await fs13.appendFile(
|
|
30728
|
+
await fs13.appendFile(path26.join(dir, TIMELINE_FILE), line, "utf8");
|
|
30412
30729
|
}
|
|
30413
30730
|
async function readChecks(cwd) {
|
|
30414
|
-
const p3 =
|
|
30731
|
+
const p3 = path26.join(worldDir(cwd), CHECKS_FILE);
|
|
30415
30732
|
try {
|
|
30416
30733
|
const raw = await fs13.readFile(p3, "utf8");
|
|
30417
30734
|
const parsed = JSON.parse(raw);
|
|
@@ -30423,7 +30740,7 @@ async function readChecks(cwd) {
|
|
|
30423
30740
|
function runShell(command, cwd, timeoutMs, signal) {
|
|
30424
30741
|
return new Promise((resolve3) => {
|
|
30425
30742
|
const isWin = process.platform === "win32";
|
|
30426
|
-
const child =
|
|
30743
|
+
const child = spawn6(isWin ? "cmd.exe" : "/bin/sh", isWin ? ["/c", command] : ["-c", command], {
|
|
30427
30744
|
cwd,
|
|
30428
30745
|
env: process.env,
|
|
30429
30746
|
windowsHide: true,
|
|
@@ -30486,8 +30803,8 @@ function runShell(command, cwd, timeoutMs, signal) {
|
|
|
30486
30803
|
});
|
|
30487
30804
|
}
|
|
30488
30805
|
async function runBacktest(cwd, signal) {
|
|
30489
|
-
const checksPath =
|
|
30490
|
-
const hypothesisPath =
|
|
30806
|
+
const checksPath = path26.join(worldDir(cwd), CHECKS_FILE);
|
|
30807
|
+
const hypothesisPath = path26.join(worldDir(cwd), HYPOTHESIS_FILE);
|
|
30491
30808
|
const checks = await readChecks(cwd);
|
|
30492
30809
|
if (checks.length === 0) {
|
|
30493
30810
|
return {
|
|
@@ -30556,7 +30873,7 @@ var init_worldModel = __esm({
|
|
|
30556
30873
|
"use strict";
|
|
30557
30874
|
init_zod();
|
|
30558
30875
|
init_toolTypes();
|
|
30559
|
-
WORLD_DIR_NAME =
|
|
30876
|
+
WORLD_DIR_NAME = path26.join(".zelari", "world");
|
|
30560
30877
|
HYPOTHESIS_FILE = "hypothesis.md";
|
|
30561
30878
|
CHECKS_FILE = "checks.json";
|
|
30562
30879
|
TIMELINE_FILE = "timeline.jsonl";
|
|
@@ -30573,7 +30890,7 @@ var init_worldModel = __esm({
|
|
|
30573
30890
|
execute: async (args, ctx) => {
|
|
30574
30891
|
try {
|
|
30575
30892
|
const dir = await ensureWorldDir(ctx.cwd);
|
|
30576
|
-
const file2 =
|
|
30893
|
+
const file2 = path26.join(dir, HYPOTHESIS_FILE);
|
|
30577
30894
|
if (args.append) {
|
|
30578
30895
|
const block = `
|
|
30579
30896
|
|
|
@@ -30612,7 +30929,7 @@ ${args.content}
|
|
|
30612
30929
|
execute: async (args, ctx) => {
|
|
30613
30930
|
try {
|
|
30614
30931
|
const dir = await ensureWorldDir(ctx.cwd);
|
|
30615
|
-
const file2 =
|
|
30932
|
+
const file2 = path26.join(dir, CHECKS_FILE);
|
|
30616
30933
|
const body = { checks: args.checks };
|
|
30617
30934
|
await fs13.writeFile(file2, JSON.stringify(body, null, 2) + "\n", "utf8");
|
|
30618
30935
|
await appendTimeline(ctx.cwd, { kind: "checks_set", count: args.checks.length });
|
|
@@ -30651,8 +30968,8 @@ ${args.content}
|
|
|
30651
30968
|
stdoutPreview: "(dryRun)",
|
|
30652
30969
|
mismatch: "dryRun"
|
|
30653
30970
|
})),
|
|
30654
|
-
hypothesisPath:
|
|
30655
|
-
checksPath:
|
|
30971
|
+
hypothesisPath: path26.join(worldDir(ctx.cwd), HYPOTHESIS_FILE),
|
|
30972
|
+
checksPath: path26.join(worldDir(ctx.cwd), CHECKS_FILE)
|
|
30656
30973
|
});
|
|
30657
30974
|
}
|
|
30658
30975
|
const result = await runBacktest(ctx.cwd, ctx.signal);
|
|
@@ -30676,7 +30993,7 @@ ${args.content}
|
|
|
30676
30993
|
execute: async (args, ctx) => {
|
|
30677
30994
|
try {
|
|
30678
30995
|
const dir = await ensureWorldDir(ctx.cwd);
|
|
30679
|
-
const file2 =
|
|
30996
|
+
const file2 = path26.join(dir, TIMELINE_FILE);
|
|
30680
30997
|
await appendTimeline(ctx.cwd, {
|
|
30681
30998
|
kind: args.kind,
|
|
30682
30999
|
summary: args.summary,
|
|
@@ -30772,6 +31089,138 @@ var init_toolPermissions = __esm({
|
|
|
30772
31089
|
}
|
|
30773
31090
|
});
|
|
30774
31091
|
|
|
31092
|
+
// src/cli/safety/folderTrust.ts
|
|
31093
|
+
var folderTrust_exports = {};
|
|
31094
|
+
__export(folderTrust_exports, {
|
|
31095
|
+
_setTrustStorePathForTests: () => _setTrustStorePathForTests,
|
|
31096
|
+
getTrustStorePath: () => getTrustStorePath,
|
|
31097
|
+
hasTrustStore: () => hasTrustStore,
|
|
31098
|
+
isFolderTrusted: () => isFolderTrusted,
|
|
31099
|
+
listTrustedFolders: () => listTrustedFolders,
|
|
31100
|
+
trustFolder: () => trustFolder,
|
|
31101
|
+
untrustFolder: () => untrustFolder
|
|
31102
|
+
});
|
|
31103
|
+
import { homedir as homedir7 } from "node:os";
|
|
31104
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync10, readFileSync as readFileSync18, writeFileSync as writeFileSync12 } from "node:fs";
|
|
31105
|
+
import path27 from "node:path";
|
|
31106
|
+
function trustStorePath() {
|
|
31107
|
+
return _overrideStorePath ?? path27.join(homedir7(), ".zelari-code", "trust.json");
|
|
31108
|
+
}
|
|
31109
|
+
function normalize(p3) {
|
|
31110
|
+
const resolved = path27.resolve(p3);
|
|
31111
|
+
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
31112
|
+
}
|
|
31113
|
+
function readStore3() {
|
|
31114
|
+
try {
|
|
31115
|
+
const raw = readFileSync18(trustStorePath(), "utf8");
|
|
31116
|
+
const parsed = JSON.parse(raw);
|
|
31117
|
+
if (parsed && Array.isArray(parsed.folders)) return parsed;
|
|
31118
|
+
return DEFAULT_STORE;
|
|
31119
|
+
} catch {
|
|
31120
|
+
return DEFAULT_STORE;
|
|
31121
|
+
}
|
|
31122
|
+
}
|
|
31123
|
+
function writeStore3(store2) {
|
|
31124
|
+
const p3 = trustStorePath();
|
|
31125
|
+
try {
|
|
31126
|
+
mkdirSync10(path27.dirname(p3), { recursive: true });
|
|
31127
|
+
writeFileSync12(p3, JSON.stringify(store2, null, 2), "utf8");
|
|
31128
|
+
} catch (err) {
|
|
31129
|
+
throw new Error(
|
|
31130
|
+
`failed to persist trust store ${p3}: ${err instanceof Error ? err.message : String(err)}`
|
|
31131
|
+
);
|
|
31132
|
+
}
|
|
31133
|
+
}
|
|
31134
|
+
function envTrustedFolder() {
|
|
31135
|
+
const raw = process.env.ZELARI_FOLDER_TRUST?.trim();
|
|
31136
|
+
if (!raw) return null;
|
|
31137
|
+
const v = raw.toLowerCase();
|
|
31138
|
+
if (v === "1" || v === "true" || v === "yes" || v === "all") return "all";
|
|
31139
|
+
if (v === "0" || v === "false" || v === "no" || v === "none") return "none";
|
|
31140
|
+
return raw;
|
|
31141
|
+
}
|
|
31142
|
+
function isFolderTrusted(folderPath) {
|
|
31143
|
+
const env = envTrustedFolder();
|
|
31144
|
+
if (env === "all") return true;
|
|
31145
|
+
if (env === "none") return false;
|
|
31146
|
+
if (env) return normalize(env) === normalize(folderPath);
|
|
31147
|
+
const target = normalize(folderPath);
|
|
31148
|
+
return readStore3().folders.some((f) => normalize(f.path) === target);
|
|
31149
|
+
}
|
|
31150
|
+
function trustFolder(folderPath) {
|
|
31151
|
+
const store2 = readStore3();
|
|
31152
|
+
const normalized = path27.resolve(folderPath);
|
|
31153
|
+
if (!store2.folders.some((f) => normalize(f.path) === normalize(normalized))) {
|
|
31154
|
+
store2.folders.push({ path: normalized, trustedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
31155
|
+
writeStore3(store2);
|
|
31156
|
+
}
|
|
31157
|
+
return { ok: true, path: normalized };
|
|
31158
|
+
}
|
|
31159
|
+
function untrustFolder(folderPath) {
|
|
31160
|
+
const store2 = readStore3();
|
|
31161
|
+
const target = normalize(folderPath);
|
|
31162
|
+
const before = store2.folders.length;
|
|
31163
|
+
store2.folders = store2.folders.filter((f) => normalize(f.path) !== target);
|
|
31164
|
+
if (store2.folders.length === before) return { ok: true, removed: false };
|
|
31165
|
+
writeStore3(store2);
|
|
31166
|
+
return { ok: true, removed: true };
|
|
31167
|
+
}
|
|
31168
|
+
function listTrustedFolders() {
|
|
31169
|
+
const env = envTrustedFolder();
|
|
31170
|
+
if (env === "all") {
|
|
31171
|
+
return [{ path: "<all>", trustedAt: "env" }];
|
|
31172
|
+
}
|
|
31173
|
+
if (env) {
|
|
31174
|
+
return [{ path: env, trustedAt: "env" }];
|
|
31175
|
+
}
|
|
31176
|
+
return readStore3().folders;
|
|
31177
|
+
}
|
|
31178
|
+
function getTrustStorePath() {
|
|
31179
|
+
return trustStorePath();
|
|
31180
|
+
}
|
|
31181
|
+
function hasTrustStore() {
|
|
31182
|
+
return existsSync18(trustStorePath());
|
|
31183
|
+
}
|
|
31184
|
+
function _setTrustStorePathForTests(p3) {
|
|
31185
|
+
_overrideStorePath = p3;
|
|
31186
|
+
}
|
|
31187
|
+
var DEFAULT_STORE, _overrideStorePath;
|
|
31188
|
+
var init_folderTrust = __esm({
|
|
31189
|
+
"src/cli/safety/folderTrust.ts"() {
|
|
31190
|
+
"use strict";
|
|
31191
|
+
DEFAULT_STORE = { folders: [] };
|
|
31192
|
+
_overrideStorePath = null;
|
|
31193
|
+
}
|
|
31194
|
+
});
|
|
31195
|
+
|
|
31196
|
+
// src/cli/safety/lifecycleHooks.ts
|
|
31197
|
+
import { homedir as homedir8 } from "node:os";
|
|
31198
|
+
import { join as join14 } from "node:path";
|
|
31199
|
+
function globalHooksDir() {
|
|
31200
|
+
return join14(homedir8(), ".zelari-code", "hooks");
|
|
31201
|
+
}
|
|
31202
|
+
function projectHooksDir(projectRoot) {
|
|
31203
|
+
return join14(projectRoot, ".zelari", "hooks");
|
|
31204
|
+
}
|
|
31205
|
+
function createDefaultLifecycleHooks(projectRoot = process.cwd()) {
|
|
31206
|
+
const runner = new LifecycleHookRunner();
|
|
31207
|
+
const dirs = [globalHooksDir()];
|
|
31208
|
+
if (isFolderTrusted(projectRoot)) {
|
|
31209
|
+
dirs.push(projectHooksDir(projectRoot));
|
|
31210
|
+
}
|
|
31211
|
+
for (const dir of dirs) {
|
|
31212
|
+
runner.loadDir(dir);
|
|
31213
|
+
}
|
|
31214
|
+
return runner;
|
|
31215
|
+
}
|
|
31216
|
+
var init_lifecycleHooks = __esm({
|
|
31217
|
+
"src/cli/safety/lifecycleHooks.ts"() {
|
|
31218
|
+
"use strict";
|
|
31219
|
+
init_harness();
|
|
31220
|
+
init_folderTrust();
|
|
31221
|
+
}
|
|
31222
|
+
});
|
|
31223
|
+
|
|
30775
31224
|
// src/cli/tools/krakenModel.ts
|
|
30776
31225
|
var krakenModel_exports = {};
|
|
30777
31226
|
__export(krakenModel_exports, {
|
|
@@ -30887,6 +31336,9 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
30887
31336
|
const safeWebSearch = wrapWithAudit(webSearchTool, audit, sessionId);
|
|
30888
31337
|
const registry4 = new ToolRegistry();
|
|
30889
31338
|
const profile = options.profile ?? "full";
|
|
31339
|
+
const isParent = !options.profile || options.profile === "full";
|
|
31340
|
+
const hooks = isParent ? options.lifecycleHooks ?? createDefaultLifecycleHooks(root) : null;
|
|
31341
|
+
if (hooks) registry4.setLifecycleHooks(hooks);
|
|
30890
31342
|
const readOnly = options.readOnly === true || options.planMode === true || profile === "explore";
|
|
30891
31343
|
const verifyMode = profile === "verify";
|
|
30892
31344
|
const allowMutators = !readOnly && !verifyMode;
|
|
@@ -31291,6 +31743,7 @@ var init_toolRegistry = __esm({
|
|
|
31291
31743
|
init_worldModel();
|
|
31292
31744
|
init_openai_compatible();
|
|
31293
31745
|
init_toolPermissions();
|
|
31746
|
+
init_lifecycleHooks();
|
|
31294
31747
|
init_toolTypes();
|
|
31295
31748
|
init_skills2();
|
|
31296
31749
|
HARNESS_BUILTIN_NAMES = /* @__PURE__ */ new Set([
|
|
@@ -31311,12 +31764,12 @@ var init_toolRegistry = __esm({
|
|
|
31311
31764
|
// src/cli/state/fileStateStore.ts
|
|
31312
31765
|
import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
|
|
31313
31766
|
import { promises as fs14 } from "node:fs";
|
|
31314
|
-
import * as
|
|
31767
|
+
import * as path28 from "node:path";
|
|
31315
31768
|
function shortId() {
|
|
31316
31769
|
return randomUUID2().replace(/-/g, "").slice(0, 12);
|
|
31317
31770
|
}
|
|
31318
31771
|
async function writeJsonAtomic(filePath, data) {
|
|
31319
|
-
await fs14.mkdir(
|
|
31772
|
+
await fs14.mkdir(path28.dirname(filePath), { recursive: true });
|
|
31320
31773
|
const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
31321
31774
|
await fs14.writeFile(tmp, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
31322
31775
|
await fs14.rename(tmp, filePath);
|
|
@@ -31377,11 +31830,11 @@ var init_fileStateStore = __esm({
|
|
|
31377
31830
|
indexPath = "";
|
|
31378
31831
|
async init(projectRoot) {
|
|
31379
31832
|
this.root = projectRoot;
|
|
31380
|
-
this.stateDir =
|
|
31381
|
-
this.commitsDir =
|
|
31382
|
-
this.artifactsDir =
|
|
31383
|
-
this.headPath =
|
|
31384
|
-
this.indexPath =
|
|
31833
|
+
this.stateDir = path28.join(projectRoot, ".zelari", "state");
|
|
31834
|
+
this.commitsDir = path28.join(this.stateDir, "commits");
|
|
31835
|
+
this.artifactsDir = path28.join(this.stateDir, "artifacts");
|
|
31836
|
+
this.headPath = path28.join(this.stateDir, "HEAD.json");
|
|
31837
|
+
this.indexPath = path28.join(this.stateDir, "index.jsonl");
|
|
31385
31838
|
await fs14.mkdir(this.commitsDir, { recursive: true });
|
|
31386
31839
|
await fs14.mkdir(this.artifactsDir, { recursive: true });
|
|
31387
31840
|
}
|
|
@@ -31394,13 +31847,13 @@ var init_fileStateStore = __esm({
|
|
|
31394
31847
|
const discoveries = input.discoveries ?? [];
|
|
31395
31848
|
const parent = await this.head();
|
|
31396
31849
|
const id = shortId();
|
|
31397
|
-
const artifactRel =
|
|
31398
|
-
const artifactAbs =
|
|
31850
|
+
const artifactRel = path28.join("artifacts", id);
|
|
31851
|
+
const artifactAbs = path28.join(this.artifactsDir, id);
|
|
31399
31852
|
await fs14.mkdir(artifactAbs, { recursive: true });
|
|
31400
31853
|
const summary = defaultSummary(input, discoveries);
|
|
31401
|
-
await fs14.writeFile(
|
|
31402
|
-
await writeJsonAtomic(
|
|
31403
|
-
await writeJsonAtomic(
|
|
31854
|
+
await fs14.writeFile(path28.join(artifactAbs, "summary.md"), summary + "\n", "utf8");
|
|
31855
|
+
await writeJsonAtomic(path28.join(artifactAbs, "discoveries.json"), discoveries);
|
|
31856
|
+
await writeJsonAtomic(path28.join(artifactAbs, "verification.json"), input.verification);
|
|
31404
31857
|
const meta3 = {
|
|
31405
31858
|
id,
|
|
31406
31859
|
parentId: parent?.id ?? null,
|
|
@@ -31412,14 +31865,14 @@ var init_fileStateStore = __esm({
|
|
|
31412
31865
|
workspaceCheckpointId: input.workspaceCheckpointId,
|
|
31413
31866
|
verification: {
|
|
31414
31867
|
...input.verification,
|
|
31415
|
-
reportPath: input.verification.reportPath ??
|
|
31868
|
+
reportPath: input.verification.reportPath ?? path28.join(".zelari", "state", artifactRel, "verification.json").replace(/\\/g, "/")
|
|
31416
31869
|
},
|
|
31417
31870
|
changedPaths: input.changedPaths ?? [],
|
|
31418
31871
|
stablePromptHash: input.stablePromptHash,
|
|
31419
31872
|
discoveryCount: discoveries.length,
|
|
31420
31873
|
artifactDir: artifactRel.replace(/\\/g, "/")
|
|
31421
31874
|
};
|
|
31422
|
-
await writeJsonAtomic(
|
|
31875
|
+
await writeJsonAtomic(path28.join(this.commitsDir, `${id}.json`), meta3);
|
|
31423
31876
|
await writeJsonAtomic(this.headPath, { id, updatedAt: meta3.createdAt });
|
|
31424
31877
|
await fs14.appendFile(this.indexPath, JSON.stringify({ id, createdAt: meta3.createdAt, label: meta3.label }) + "\n", "utf8");
|
|
31425
31878
|
return stripStored(meta3);
|
|
@@ -31430,7 +31883,7 @@ var init_fileStateStore = __esm({
|
|
|
31430
31883
|
return this.get(head.id);
|
|
31431
31884
|
}
|
|
31432
31885
|
async get(id) {
|
|
31433
|
-
const stored = await readJsonFile(
|
|
31886
|
+
const stored = await readJsonFile(path28.join(this.commitsDir, `${id}.json`));
|
|
31434
31887
|
return stored ? stripStored(stored) : null;
|
|
31435
31888
|
}
|
|
31436
31889
|
async list(limit = 20) {
|
|
@@ -31469,9 +31922,9 @@ var init_fileStateStore = __esm({
|
|
|
31469
31922
|
async loadDiscoveries(id) {
|
|
31470
31923
|
const meta3 = id ? await this.get(id) : await this.head();
|
|
31471
31924
|
if (!meta3) return [];
|
|
31472
|
-
const stored = await readJsonFile(
|
|
31925
|
+
const stored = await readJsonFile(path28.join(this.commitsDir, `${meta3.id}.json`));
|
|
31473
31926
|
if (!stored?.artifactDir) return [];
|
|
31474
|
-
const discPath =
|
|
31927
|
+
const discPath = path28.join(this.stateDir, stored.artifactDir, "discoveries.json");
|
|
31475
31928
|
return await readJsonFile(discPath) ?? [];
|
|
31476
31929
|
}
|
|
31477
31930
|
async materializeContext(id, maxChars = DEFAULT_MATERIALIZE_CHARS) {
|
|
@@ -31917,8 +32370,8 @@ __export(conversationContext_exports, {
|
|
|
31917
32370
|
setHistory: () => setHistory,
|
|
31918
32371
|
setLastClarification: () => setLastClarification
|
|
31919
32372
|
});
|
|
31920
|
-
import { existsSync as
|
|
31921
|
-
import { join as
|
|
32373
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
32374
|
+
import { join as join16 } from "node:path";
|
|
31922
32375
|
function getHistory() {
|
|
31923
32376
|
return history;
|
|
31924
32377
|
}
|
|
@@ -31926,7 +32379,7 @@ function setHistory(messages) {
|
|
|
31926
32379
|
history = [...messages];
|
|
31927
32380
|
}
|
|
31928
32381
|
function compactInPlace(cwd = process.cwd()) {
|
|
31929
|
-
const durableStatePresent =
|
|
32382
|
+
const durableStatePresent = existsSync19(join16(cwd, ".zelari", "state", "HEAD.json"));
|
|
31930
32383
|
history = compactHistory(history, { durableStatePresent });
|
|
31931
32384
|
}
|
|
31932
32385
|
function appendMessages(msgs) {
|
|
@@ -32315,7 +32768,7 @@ var claudeProvider_exports = {};
|
|
|
32315
32768
|
__export(claudeProvider_exports, {
|
|
32316
32769
|
createLocalCliProvider: () => createLocalCliProvider
|
|
32317
32770
|
});
|
|
32318
|
-
import { spawn as
|
|
32771
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
32319
32772
|
function waitForExit(child, timeoutMs = 2e3) {
|
|
32320
32773
|
return new Promise((resolve3) => {
|
|
32321
32774
|
if (child.exitCode != null) return resolve3(child.exitCode);
|
|
@@ -32344,7 +32797,7 @@ function createLocalCliProvider(opts = {}) {
|
|
|
32344
32797
|
);
|
|
32345
32798
|
}
|
|
32346
32799
|
}
|
|
32347
|
-
const spawnFn = opts.spawnFn ??
|
|
32800
|
+
const spawnFn = opts.spawnFn ?? spawn7;
|
|
32348
32801
|
let child;
|
|
32349
32802
|
try {
|
|
32350
32803
|
child = spawnFn(cli, args, {
|
|
@@ -32439,14 +32892,14 @@ var init_claudeProvider = __esm({
|
|
|
32439
32892
|
});
|
|
32440
32893
|
|
|
32441
32894
|
// src/cli/workspace/projectInstructions.ts
|
|
32442
|
-
import { existsSync as
|
|
32443
|
-
import { join as
|
|
32895
|
+
import { existsSync as existsSync20, readFileSync as readFileSync19 } from "node:fs";
|
|
32896
|
+
import { join as join17 } from "node:path";
|
|
32444
32897
|
function loadProjectInstructions(projectRoot = process.cwd(), maxChars = MAX_CHARS) {
|
|
32445
32898
|
for (const name of CANDIDATES) {
|
|
32446
|
-
const full =
|
|
32447
|
-
if (!
|
|
32899
|
+
const full = join17(projectRoot, name);
|
|
32900
|
+
if (!existsSync20(full)) continue;
|
|
32448
32901
|
try {
|
|
32449
|
-
let raw =
|
|
32902
|
+
let raw = readFileSync19(full, "utf8");
|
|
32450
32903
|
raw = raw.replace(/\r\n/g, "\n").trim();
|
|
32451
32904
|
if (!raw) continue;
|
|
32452
32905
|
if (raw.length <= maxChars) {
|
|
@@ -32483,20 +32936,20 @@ var init_projectInstructions = __esm({
|
|
|
32483
32936
|
|
|
32484
32937
|
// src/cli/workspace/paths.ts
|
|
32485
32938
|
import {
|
|
32486
|
-
mkdirSync as
|
|
32487
|
-
writeFileSync as
|
|
32488
|
-
existsSync as
|
|
32939
|
+
mkdirSync as mkdirSync11,
|
|
32940
|
+
writeFileSync as writeFileSync13,
|
|
32941
|
+
existsSync as existsSync21,
|
|
32489
32942
|
accessSync,
|
|
32490
32943
|
constants,
|
|
32491
32944
|
realpathSync
|
|
32492
32945
|
} from "node:fs";
|
|
32493
|
-
import { join as
|
|
32494
|
-
import { homedir as
|
|
32946
|
+
import { join as join18, basename } from "node:path";
|
|
32947
|
+
import { homedir as homedir9 } from "node:os";
|
|
32495
32948
|
import { createHash as createHash4 } from "node:crypto";
|
|
32496
32949
|
function resolveWorkspaceRoot(projectRoot = process.cwd()) {
|
|
32497
32950
|
const candidates = [
|
|
32498
|
-
|
|
32499
|
-
|
|
32951
|
+
join18(projectRoot, ".zelari"),
|
|
32952
|
+
join18(homedir9(), ".zelari-code", "workspace", hashProject(projectRoot))
|
|
32500
32953
|
];
|
|
32501
32954
|
for (const candidate of candidates) {
|
|
32502
32955
|
if (isWritableDir(projectRoot) || candidate !== candidates[0]) {
|
|
@@ -32512,7 +32965,7 @@ function hashProject(projectPath) {
|
|
|
32512
32965
|
}
|
|
32513
32966
|
function isWritableDir(dir) {
|
|
32514
32967
|
try {
|
|
32515
|
-
if (!
|
|
32968
|
+
if (!existsSync21(dir)) return false;
|
|
32516
32969
|
accessSync(dir, constants.W_OK);
|
|
32517
32970
|
return true;
|
|
32518
32971
|
} catch {
|
|
@@ -32520,26 +32973,26 @@ function isWritableDir(dir) {
|
|
|
32520
32973
|
}
|
|
32521
32974
|
}
|
|
32522
32975
|
function ensureWorkspaceDir(workspaceDir) {
|
|
32523
|
-
|
|
32524
|
-
if (workspaceDir.endsWith("/.zelari") &&
|
|
32525
|
-
const gitignorePath =
|
|
32526
|
-
if (!
|
|
32527
|
-
|
|
32976
|
+
mkdirSync11(workspaceDir, { recursive: true });
|
|
32977
|
+
if (workspaceDir.endsWith("/.zelari") && existsSync21(join18(workspaceDir, "..", ".git"))) {
|
|
32978
|
+
const gitignorePath = join18(workspaceDir, ".gitignore");
|
|
32979
|
+
if (!existsSync21(gitignorePath)) {
|
|
32980
|
+
writeFileSync13(gitignorePath, "*\n!.gitignore\n");
|
|
32528
32981
|
}
|
|
32529
32982
|
}
|
|
32530
32983
|
}
|
|
32531
32984
|
function workspaceFile(rootDir, kind) {
|
|
32532
32985
|
switch (kind) {
|
|
32533
32986
|
case "plan":
|
|
32534
|
-
return
|
|
32987
|
+
return join18(rootDir, "plan.md");
|
|
32535
32988
|
case "risks":
|
|
32536
|
-
return
|
|
32989
|
+
return join18(rootDir, "risks.md");
|
|
32537
32990
|
case "index":
|
|
32538
|
-
return
|
|
32991
|
+
return join18(rootDir, "workspace.json");
|
|
32539
32992
|
}
|
|
32540
32993
|
}
|
|
32541
32994
|
function workspaceArtifact(rootDir, subdir, slug) {
|
|
32542
|
-
return
|
|
32995
|
+
return join18(rootDir, subdir, `${slug}.md`);
|
|
32543
32996
|
}
|
|
32544
32997
|
function projectName(projectRoot = process.cwd()) {
|
|
32545
32998
|
return basename(realpathSync(projectRoot));
|
|
@@ -32559,8 +33012,8 @@ __export(workspaceSummary_exports, {
|
|
|
32559
33012
|
buildWorkspaceSummary: () => buildWorkspaceSummary,
|
|
32560
33013
|
buildZelariReadHint: () => buildZelariReadHint
|
|
32561
33014
|
});
|
|
32562
|
-
import { existsSync as
|
|
32563
|
-
import { join as
|
|
33015
|
+
import { existsSync as existsSync22, readFileSync as readFileSync20, readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
|
|
33016
|
+
import { join as join19, relative } from "node:path";
|
|
32564
33017
|
function buildWorkspaceSummary(projectRoot = process.cwd(), options = {}) {
|
|
32565
33018
|
const { maxEntries = 30, maxChars = 3500, maxDeps = 24, maxScripts = 16 } = options;
|
|
32566
33019
|
const name = safeProjectName(projectRoot);
|
|
@@ -32593,11 +33046,11 @@ function formatTaskLine(t) {
|
|
|
32593
33046
|
}
|
|
32594
33047
|
function buildPlanSummary(projectRoot = process.cwd(), options) {
|
|
32595
33048
|
const zelariRoot = resolveWorkspaceRoot(projectRoot);
|
|
32596
|
-
const planPath =
|
|
32597
|
-
if (!
|
|
33049
|
+
const planPath = join19(zelariRoot, "plan.json");
|
|
33050
|
+
if (!existsSync22(planPath)) return null;
|
|
32598
33051
|
let plan;
|
|
32599
33052
|
try {
|
|
32600
|
-
plan = JSON.parse(
|
|
33053
|
+
plan = JSON.parse(readFileSync20(planPath, "utf8"));
|
|
32601
33054
|
} catch {
|
|
32602
33055
|
return null;
|
|
32603
33056
|
}
|
|
@@ -32733,8 +33186,8 @@ function pickNextTask(open) {
|
|
|
32733
33186
|
)[0];
|
|
32734
33187
|
}
|
|
32735
33188
|
function buildZelariReadHint(projectRoot = process.cwd()) {
|
|
32736
|
-
const planPath =
|
|
32737
|
-
if (!
|
|
33189
|
+
const planPath = join19(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
33190
|
+
if (!existsSync22(planPath)) return "";
|
|
32738
33191
|
return [
|
|
32739
33192
|
"# Council workspace detected (.zelari/) \u2014 DRAFT vault",
|
|
32740
33193
|
"`.zelari/plan.json` and `.zelari/docs/` hold **design hypotheses**, not verified product state.",
|
|
@@ -32749,10 +33202,10 @@ function safeProjectName(root) {
|
|
|
32749
33202
|
}
|
|
32750
33203
|
}
|
|
32751
33204
|
function readPackageJson(projectRoot) {
|
|
32752
|
-
const p3 =
|
|
32753
|
-
if (!
|
|
33205
|
+
const p3 = join19(projectRoot, "package.json");
|
|
33206
|
+
if (!existsSync22(p3)) return null;
|
|
32754
33207
|
try {
|
|
32755
|
-
return JSON.parse(
|
|
33208
|
+
return JSON.parse(readFileSync20(p3, "utf8"));
|
|
32756
33209
|
} catch {
|
|
32757
33210
|
return null;
|
|
32758
33211
|
}
|
|
@@ -32793,7 +33246,7 @@ function readBuildScripts(projectRoot, maxScripts = 16) {
|
|
|
32793
33246
|
function listShallow(projectRoot, maxEntries) {
|
|
32794
33247
|
const out = [];
|
|
32795
33248
|
try {
|
|
32796
|
-
const top =
|
|
33249
|
+
const top = readdirSync4(projectRoot, { withFileTypes: true }).filter(
|
|
32797
33250
|
(e) => !e.name.startsWith(".") && e.name !== "node_modules" && e.name !== "dist"
|
|
32798
33251
|
).sort((a, b) => a.name.localeCompare(b.name));
|
|
32799
33252
|
let count = 0;
|
|
@@ -32802,11 +33255,11 @@ function listShallow(projectRoot, maxEntries) {
|
|
|
32802
33255
|
out.push(`\u2026 (+${top.length - count} more)`);
|
|
32803
33256
|
break;
|
|
32804
33257
|
}
|
|
32805
|
-
const rel2 = relative(projectRoot,
|
|
33258
|
+
const rel2 = relative(projectRoot, join19(projectRoot, entry.name));
|
|
32806
33259
|
if (entry.isDirectory()) {
|
|
32807
33260
|
let inner = "";
|
|
32808
33261
|
try {
|
|
32809
|
-
const sub =
|
|
33262
|
+
const sub = readdirSync4(join19(projectRoot, entry.name), {
|
|
32810
33263
|
withFileTypes: true
|
|
32811
33264
|
}).filter((e) => !e.name.startsWith(".")).slice(0, 4).map((e) => e.name);
|
|
32812
33265
|
if (sub.length > 0)
|
|
@@ -32854,12 +33307,12 @@ var init_workspaceSummary = __esm({
|
|
|
32854
33307
|
});
|
|
32855
33308
|
|
|
32856
33309
|
// src/cli/workspace/buildLessonsSummary.ts
|
|
32857
|
-
import { existsSync as
|
|
32858
|
-
import { join as
|
|
33310
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
33311
|
+
import { join as join20 } from "node:path";
|
|
32859
33312
|
function buildLessonsSummary(projectRoot = process.cwd(), taskText) {
|
|
32860
33313
|
if (process.env["ZELARI_LESSONS"] === "0") return null;
|
|
32861
33314
|
const zelariRoot = resolveWorkspaceRoot(projectRoot);
|
|
32862
|
-
if (!
|
|
33315
|
+
if (!existsSync23(join20(zelariRoot, "lessons.jsonl"))) return null;
|
|
32863
33316
|
const lessons = recallLessons(zelariRoot, {
|
|
32864
33317
|
maxLessons: 5,
|
|
32865
33318
|
maxBytes: 2048,
|
|
@@ -32880,8 +33333,8 @@ var composeContext_exports = {};
|
|
|
32880
33333
|
__export(composeContext_exports, {
|
|
32881
33334
|
composeProjectContext: () => composeProjectContext
|
|
32882
33335
|
});
|
|
32883
|
-
import { existsSync as
|
|
32884
|
-
import { join as
|
|
33336
|
+
import { existsSync as existsSync24, readdirSync as readdirSync5, readFileSync as readFileSync21 } from "node:fs";
|
|
33337
|
+
import { join as join21 } from "node:path";
|
|
32885
33338
|
function cap2(text, max, label) {
|
|
32886
33339
|
if (!text || text.length <= max) return { text: text || "", truncated: false };
|
|
32887
33340
|
return {
|
|
@@ -32893,19 +33346,19 @@ function cap2(text, max, label) {
|
|
|
32893
33346
|
}
|
|
32894
33347
|
function buildDesignIndex(projectRoot, maxChars) {
|
|
32895
33348
|
const root = resolveWorkspaceRoot(projectRoot);
|
|
32896
|
-
if (!
|
|
33349
|
+
if (!existsSync24(root)) return "";
|
|
32897
33350
|
const lines = [
|
|
32898
33351
|
"# Design vault index (.zelari/) \u2014 HYPOTHESES only",
|
|
32899
33352
|
"Full design docs are NOT product source of truth. Open with list_files / read_file / searchDocuments if needed."
|
|
32900
33353
|
];
|
|
32901
|
-
const docsDir =
|
|
32902
|
-
if (
|
|
33354
|
+
const docsDir = join21(root, "docs");
|
|
33355
|
+
if (existsSync24(docsDir)) {
|
|
32903
33356
|
try {
|
|
32904
|
-
const docs =
|
|
33357
|
+
const docs = readdirSync5(docsDir).filter((n) => n.endsWith(".md")).slice(0, 12);
|
|
32905
33358
|
if (docs.length > 0) {
|
|
32906
33359
|
lines.push("", "## docs/ (titles only)");
|
|
32907
33360
|
for (const d of docs) lines.push(`- .zelari/docs/${d}`);
|
|
32908
|
-
if (
|
|
33361
|
+
if (readdirSync5(docsDir).filter((n) => n.endsWith(".md")).length > 12) {
|
|
32909
33362
|
lines.push("- \u2026 (more under .zelari/docs/)");
|
|
32910
33363
|
}
|
|
32911
33364
|
}
|
|
@@ -32913,14 +33366,14 @@ function buildDesignIndex(projectRoot, maxChars) {
|
|
|
32913
33366
|
}
|
|
32914
33367
|
}
|
|
32915
33368
|
for (const name of ["risks.md", "plan.json", "nfr-spec.json"]) {
|
|
32916
|
-
if (
|
|
33369
|
+
if (existsSync24(join21(root, name))) {
|
|
32917
33370
|
lines.push(`- .zelari/${name} present`);
|
|
32918
33371
|
}
|
|
32919
33372
|
}
|
|
32920
|
-
const decisionsDir =
|
|
32921
|
-
if (
|
|
33373
|
+
const decisionsDir = join21(root, "decisions");
|
|
33374
|
+
if (existsSync24(decisionsDir)) {
|
|
32922
33375
|
try {
|
|
32923
|
-
const n =
|
|
33376
|
+
const n = readdirSync5(decisionsDir).filter((f) => f.endsWith(".md")).length;
|
|
32924
33377
|
if (n > 0) lines.push(`- .zelari/decisions/ (${n} ADR file(s) \u2014 treat proposed as non-binding)`);
|
|
32925
33378
|
} catch {
|
|
32926
33379
|
}
|
|
@@ -33019,17 +33472,17 @@ function composeProjectContext(input) {
|
|
|
33019
33472
|
}
|
|
33020
33473
|
function readDurableHeadSync(projectRoot) {
|
|
33021
33474
|
try {
|
|
33022
|
-
const headPath =
|
|
33023
|
-
if (!
|
|
33024
|
-
const head = JSON.parse(
|
|
33475
|
+
const headPath = join21(projectRoot, ".zelari", "state", "HEAD.json");
|
|
33476
|
+
if (!existsSync24(headPath)) return "";
|
|
33477
|
+
const head = JSON.parse(readFileSync21(headPath, "utf8"));
|
|
33025
33478
|
if (!head?.id) return "";
|
|
33026
|
-
const metaPath =
|
|
33027
|
-
if (!
|
|
33028
|
-
const meta3 = JSON.parse(
|
|
33029
|
-
const discPath = meta3.artifactDir ?
|
|
33479
|
+
const metaPath = join21(projectRoot, ".zelari", "state", "commits", `${head.id}.json`);
|
|
33480
|
+
if (!existsSync24(metaPath)) return "";
|
|
33481
|
+
const meta3 = JSON.parse(readFileSync21(metaPath, "utf8"));
|
|
33482
|
+
const discPath = meta3.artifactDir ? join21(projectRoot, ".zelari", "state", meta3.artifactDir, "discoveries.json") : join21(projectRoot, ".zelari", "state", "artifacts", head.id, "discoveries.json");
|
|
33030
33483
|
let discoveries = [];
|
|
33031
|
-
if (
|
|
33032
|
-
discoveries = JSON.parse(
|
|
33484
|
+
if (existsSync24(discPath)) {
|
|
33485
|
+
discoveries = JSON.parse(readFileSync21(discPath, "utf8"));
|
|
33033
33486
|
}
|
|
33034
33487
|
const reusable = discoveries.filter((d) => d.reusable !== false);
|
|
33035
33488
|
const lines = [
|
|
@@ -33062,13 +33515,13 @@ var planDetect_exports = {};
|
|
|
33062
33515
|
__export(planDetect_exports, {
|
|
33063
33516
|
hasWorkspacePlan: () => hasWorkspacePlan
|
|
33064
33517
|
});
|
|
33065
|
-
import { existsSync as
|
|
33066
|
-
import { join as
|
|
33518
|
+
import { existsSync as existsSync25, readFileSync as readFileSync22 } from "node:fs";
|
|
33519
|
+
import { join as join22 } from "node:path";
|
|
33067
33520
|
function hasWorkspacePlan(projectRoot = process.cwd()) {
|
|
33068
|
-
const planPath =
|
|
33069
|
-
if (!
|
|
33521
|
+
const planPath = join22(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
33522
|
+
if (!existsSync25(planPath)) return false;
|
|
33070
33523
|
try {
|
|
33071
|
-
const parsed = JSON.parse(
|
|
33524
|
+
const parsed = JSON.parse(readFileSync22(planPath, "utf8"));
|
|
33072
33525
|
return Array.isArray(parsed.phases) && parsed.phases.length > 0;
|
|
33073
33526
|
} catch {
|
|
33074
33527
|
return false;
|
|
@@ -33128,14 +33581,14 @@ __export(storage_exports, {
|
|
|
33128
33581
|
workspaceMutex: () => workspaceMutex
|
|
33129
33582
|
});
|
|
33130
33583
|
import {
|
|
33131
|
-
readFileSync as
|
|
33132
|
-
writeFileSync as
|
|
33133
|
-
existsSync as
|
|
33134
|
-
mkdirSync as
|
|
33135
|
-
readdirSync as
|
|
33584
|
+
readFileSync as readFileSync23,
|
|
33585
|
+
writeFileSync as writeFileSync14,
|
|
33586
|
+
existsSync as existsSync26,
|
|
33587
|
+
mkdirSync as mkdirSync12,
|
|
33588
|
+
readdirSync as readdirSync6,
|
|
33136
33589
|
renameSync as renameSync2
|
|
33137
33590
|
} from "node:fs";
|
|
33138
|
-
import { dirname as dirname4, join as
|
|
33591
|
+
import { dirname as dirname4, join as join23 } from "node:path";
|
|
33139
33592
|
function parseFrontmatter(md) {
|
|
33140
33593
|
const m = FRONTMATTER_RE.exec(md);
|
|
33141
33594
|
if (!m) return { meta: {}, body: md };
|
|
@@ -33389,33 +33842,33 @@ var init_storage = __esm({
|
|
|
33389
33842
|
VALID_SCALARS = /^(true|false|null|~)$/i;
|
|
33390
33843
|
Storage = class {
|
|
33391
33844
|
/** Read a Markdown file with frontmatter. Throws if not found. */
|
|
33392
|
-
read(
|
|
33393
|
-
if (!
|
|
33394
|
-
throw new Error(`File not found: ${
|
|
33845
|
+
read(path51) {
|
|
33846
|
+
if (!existsSync26(path51)) {
|
|
33847
|
+
throw new Error(`File not found: ${path51}`);
|
|
33395
33848
|
}
|
|
33396
|
-
const md =
|
|
33849
|
+
const md = readFileSync23(path51, "utf8");
|
|
33397
33850
|
return parseFrontmatter(md);
|
|
33398
33851
|
}
|
|
33399
33852
|
/** Read a Markdown file; returns null if not found. */
|
|
33400
|
-
readIfExists(
|
|
33401
|
-
if (!
|
|
33402
|
-
return this.read(
|
|
33853
|
+
readIfExists(path51) {
|
|
33854
|
+
if (!existsSync26(path51)) return null;
|
|
33855
|
+
return this.read(path51);
|
|
33403
33856
|
}
|
|
33404
33857
|
/**
|
|
33405
33858
|
* Write a Markdown file atomically (tmp + rename). Creates parent dirs.
|
|
33406
33859
|
* The meta object is serialized as YAML frontmatter; body as Markdown.
|
|
33407
33860
|
*/
|
|
33408
|
-
write(
|
|
33409
|
-
|
|
33410
|
-
const tmp =
|
|
33861
|
+
write(path51, meta3, body) {
|
|
33862
|
+
mkdirSync12(dirname4(path51), { recursive: true });
|
|
33863
|
+
const tmp = path51 + ".tmp-" + process.pid;
|
|
33411
33864
|
const md = serializeFrontmatter(meta3, body);
|
|
33412
|
-
|
|
33413
|
-
renameSync2(tmp,
|
|
33865
|
+
writeFileSync14(tmp, md, "utf8");
|
|
33866
|
+
renameSync2(tmp, path51);
|
|
33414
33867
|
}
|
|
33415
33868
|
/** List all .md files in a directory (non-recursive). */
|
|
33416
33869
|
listMarkdown(dir) {
|
|
33417
|
-
if (!
|
|
33418
|
-
return
|
|
33870
|
+
if (!existsSync26(dir)) return [];
|
|
33871
|
+
return readdirSync6(dir).filter((f) => f.endsWith(".md") && !f.startsWith(".")).map((f) => join23(dir, f));
|
|
33419
33872
|
}
|
|
33420
33873
|
};
|
|
33421
33874
|
KeyedMutex = class {
|
|
@@ -33454,14 +33907,14 @@ __export(stubs_exports, {
|
|
|
33454
33907
|
resolveWorkspaceRoot: () => resolveWorkspaceRoot
|
|
33455
33908
|
});
|
|
33456
33909
|
import {
|
|
33457
|
-
existsSync as
|
|
33458
|
-
readdirSync as
|
|
33459
|
-
writeFileSync as
|
|
33460
|
-
readFileSync as
|
|
33461
|
-
mkdirSync as
|
|
33910
|
+
existsSync as existsSync27,
|
|
33911
|
+
readdirSync as readdirSync7,
|
|
33912
|
+
writeFileSync as writeFileSync15,
|
|
33913
|
+
readFileSync as readFileSync24,
|
|
33914
|
+
mkdirSync as mkdirSync13,
|
|
33462
33915
|
renameSync as renameSync3
|
|
33463
33916
|
} from "node:fs";
|
|
33464
|
-
import { join as
|
|
33917
|
+
import { join as join24, basename as basename2, dirname as dirname5, relative as relative2 } from "node:path";
|
|
33465
33918
|
function createWorkspaceContext(projectRoot = process.cwd()) {
|
|
33466
33919
|
const rootDir = resolveWorkspaceRoot(projectRoot);
|
|
33467
33920
|
return {
|
|
@@ -33471,14 +33924,14 @@ function createWorkspaceContext(projectRoot = process.cwd()) {
|
|
|
33471
33924
|
};
|
|
33472
33925
|
}
|
|
33473
33926
|
function planJsonPath(ctx) {
|
|
33474
|
-
return
|
|
33927
|
+
return join24(ctx.rootDir, "plan.json");
|
|
33475
33928
|
}
|
|
33476
33929
|
function readPlan(ctx) {
|
|
33477
33930
|
const jsonPath = planJsonPath(ctx);
|
|
33478
|
-
if (
|
|
33931
|
+
if (existsSync27(jsonPath)) {
|
|
33479
33932
|
try {
|
|
33480
33933
|
const parsed = JSON.parse(
|
|
33481
|
-
|
|
33934
|
+
readFileSync24(jsonPath, "utf8")
|
|
33482
33935
|
);
|
|
33483
33936
|
return {
|
|
33484
33937
|
phases: Array.isArray(parsed.phases) ? parsed.phases : [],
|
|
@@ -33488,8 +33941,8 @@ function readPlan(ctx) {
|
|
|
33488
33941
|
} catch {
|
|
33489
33942
|
}
|
|
33490
33943
|
}
|
|
33491
|
-
const
|
|
33492
|
-
const doc = ctx.storage.readIfExists(
|
|
33944
|
+
const path51 = workspaceFile(ctx.rootDir, "plan");
|
|
33945
|
+
const doc = ctx.storage.readIfExists(path51);
|
|
33493
33946
|
if (!doc) return { phases: [], tasks: [], milestones: [] };
|
|
33494
33947
|
const meta3 = doc.meta;
|
|
33495
33948
|
return {
|
|
@@ -33500,9 +33953,9 @@ function readPlan(ctx) {
|
|
|
33500
33953
|
}
|
|
33501
33954
|
function writePlan(ctx, summary) {
|
|
33502
33955
|
const jsonPath = planJsonPath(ctx);
|
|
33503
|
-
|
|
33956
|
+
mkdirSync13(dirname5(jsonPath), { recursive: true });
|
|
33504
33957
|
const tmp = jsonPath + ".tmp-" + process.pid;
|
|
33505
|
-
|
|
33958
|
+
writeFileSync15(tmp, JSON.stringify(summary, null, 2), "utf8");
|
|
33506
33959
|
renameSync3(tmp, jsonPath);
|
|
33507
33960
|
const mdPath = workspaceFile(ctx.rootDir, "plan");
|
|
33508
33961
|
const summaryMeta = {
|
|
@@ -33569,9 +34022,9 @@ function renderPlanBody(summary) {
|
|
|
33569
34022
|
return lines.join("\n");
|
|
33570
34023
|
}
|
|
33571
34024
|
function nextAdrId(ctx) {
|
|
33572
|
-
const decisionsDir =
|
|
33573
|
-
if (!
|
|
33574
|
-
const existing =
|
|
34025
|
+
const decisionsDir = join24(ctx.rootDir, "decisions");
|
|
34026
|
+
if (!existsSync27(decisionsDir)) return "001";
|
|
34027
|
+
const existing = readdirSync7(decisionsDir).filter((f) => f.endsWith(".md")).map((f) => f.match(/^(\d+)-/)).filter((m) => !!m).map((m) => parseInt(m[1], 10));
|
|
33575
34028
|
const max = existing.length === 0 ? 0 : Math.max(...existing);
|
|
33576
34029
|
return String(max + 1).padStart(3, "0");
|
|
33577
34030
|
}
|
|
@@ -33612,7 +34065,7 @@ function addTaskRecord(ctx, summary, phaseId, t, options) {
|
|
|
33612
34065
|
status: "pending",
|
|
33613
34066
|
priority: t.priority
|
|
33614
34067
|
});
|
|
33615
|
-
const taskPath =
|
|
34068
|
+
const taskPath = join24(ctx.rootDir, "plan-tasks", `${id}.md`);
|
|
33616
34069
|
const meta3 = {
|
|
33617
34070
|
kind: "task",
|
|
33618
34071
|
id,
|
|
@@ -33654,7 +34107,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
33654
34107
|
dueDate: input.dueDate,
|
|
33655
34108
|
targetVersion: version2
|
|
33656
34109
|
});
|
|
33657
|
-
const
|
|
34110
|
+
const path51 = join24(ctx.rootDir, "milestones", `${id}.md`);
|
|
33658
34111
|
const meta3 = {
|
|
33659
34112
|
kind: "milestone",
|
|
33660
34113
|
id,
|
|
@@ -33671,7 +34124,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
33671
34124
|
`Target version: ${version2}`,
|
|
33672
34125
|
""
|
|
33673
34126
|
].join("\n");
|
|
33674
|
-
ctx.storage.write(
|
|
34127
|
+
ctx.storage.write(path51, meta3, body);
|
|
33675
34128
|
return { id, created: true };
|
|
33676
34129
|
}
|
|
33677
34130
|
function readPlanSummary(ctx) {
|
|
@@ -33875,7 +34328,7 @@ function addIdeaStub(ctx) {
|
|
|
33875
34328
|
const tags = args["tags"] ?? [];
|
|
33876
34329
|
const category = args["category"] ?? "General";
|
|
33877
34330
|
const id = `${nextAdrId(ctx)}-${slugify3(title)}`;
|
|
33878
|
-
const
|
|
34331
|
+
const path51 = workspaceArtifact(ctx.rootDir, "decisions", id);
|
|
33879
34332
|
const meta3 = {
|
|
33880
34333
|
kind: "adr",
|
|
33881
34334
|
status: "proposed",
|
|
@@ -33901,7 +34354,7 @@ function addIdeaStub(ctx) {
|
|
|
33901
34354
|
...consequences.map((c) => `- ${c}`),
|
|
33902
34355
|
""
|
|
33903
34356
|
].join("\n");
|
|
33904
|
-
ctx.storage.write(
|
|
34357
|
+
ctx.storage.write(path51, meta3, body);
|
|
33905
34358
|
return `ADR ${id} created: "${title}". Status: proposed. Promote to accepted via /update ADR or manual edit.`;
|
|
33906
34359
|
});
|
|
33907
34360
|
}
|
|
@@ -33952,8 +34405,8 @@ function createNfrSpecStub(ctx) {
|
|
|
33952
34405
|
},
|
|
33953
34406
|
planFeatureKeywords: Array.isArray(args["planFeatureKeywords"]) ? args["planFeatureKeywords"] : void 0
|
|
33954
34407
|
};
|
|
33955
|
-
const outPath =
|
|
33956
|
-
|
|
34408
|
+
const outPath = join24(ctx.rootDir, "nfr-spec.json");
|
|
34409
|
+
writeFileSync15(outPath, JSON.stringify(spec, null, 2), "utf8");
|
|
33957
34410
|
return `NFR spec written to nfr-spec.json (${targets.length} target(s)).`;
|
|
33958
34411
|
});
|
|
33959
34412
|
}
|
|
@@ -33983,14 +34436,14 @@ function createDocumentStub(ctx) {
|
|
|
33983
34436
|
ctx.storage.write(risksPath, riskMeta, content);
|
|
33984
34437
|
return `Document "${title}" created at risks.md (workspace root).`;
|
|
33985
34438
|
}
|
|
33986
|
-
const
|
|
34439
|
+
const path51 = workspaceArtifact(ctx.rootDir, "docs", slug);
|
|
33987
34440
|
const meta3 = {
|
|
33988
34441
|
kind: "doc",
|
|
33989
34442
|
id: slug,
|
|
33990
34443
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
33991
34444
|
tags
|
|
33992
34445
|
};
|
|
33993
|
-
ctx.storage.write(
|
|
34446
|
+
ctx.storage.write(path51, meta3, content);
|
|
33994
34447
|
return `Document "${title}" created at docs/${slug}.md.`;
|
|
33995
34448
|
});
|
|
33996
34449
|
}
|
|
@@ -34016,18 +34469,18 @@ function searchDocumentsStub(ctx) {
|
|
|
34016
34469
|
(w) => w.length >= 3 && w !== "or" && w !== "and" && w !== "the"
|
|
34017
34470
|
);
|
|
34018
34471
|
const files = [
|
|
34019
|
-
...ctx.storage.listMarkdown(
|
|
34020
|
-
...ctx.storage.listMarkdown(
|
|
34021
|
-
...ctx.storage.listMarkdown(
|
|
34022
|
-
...ctx.storage.listMarkdown(
|
|
34023
|
-
...ctx.storage.listMarkdown(
|
|
34472
|
+
...ctx.storage.listMarkdown(join24(ctx.rootDir, "decisions")),
|
|
34473
|
+
...ctx.storage.listMarkdown(join24(ctx.rootDir, "docs")),
|
|
34474
|
+
...ctx.storage.listMarkdown(join24(ctx.rootDir, "reviews")),
|
|
34475
|
+
...ctx.storage.listMarkdown(join24(ctx.rootDir, "plan-tasks")),
|
|
34476
|
+
...ctx.storage.listMarkdown(join24(ctx.rootDir, "milestones")),
|
|
34024
34477
|
workspaceFile(ctx.rootDir, "plan"),
|
|
34025
34478
|
workspaceFile(ctx.rootDir, "risks")
|
|
34026
34479
|
];
|
|
34027
34480
|
const results = [];
|
|
34028
34481
|
for (const file2 of files) {
|
|
34029
|
-
if (!
|
|
34030
|
-
const raw =
|
|
34482
|
+
if (!existsSync27(file2)) continue;
|
|
34483
|
+
const raw = readFileSync24(file2, "utf8");
|
|
34031
34484
|
const content = raw.toLowerCase();
|
|
34032
34485
|
let idx = -1;
|
|
34033
34486
|
let matchLen = 0;
|
|
@@ -34078,9 +34531,9 @@ function linkDocumentsStub(ctx) {
|
|
|
34078
34531
|
const toId = args["toId"] ?? args["targetId"] ?? args["targetPathOrTitle"];
|
|
34079
34532
|
if (!fromId || !toId) return "linkDocuments requires fromId and toId.";
|
|
34080
34533
|
const allFiles = [
|
|
34081
|
-
...ctx.storage.listMarkdown(
|
|
34082
|
-
...ctx.storage.listMarkdown(
|
|
34083
|
-
...ctx.storage.listMarkdown(
|
|
34534
|
+
...ctx.storage.listMarkdown(join24(ctx.rootDir, "decisions")),
|
|
34535
|
+
...ctx.storage.listMarkdown(join24(ctx.rootDir, "docs")),
|
|
34536
|
+
...ctx.storage.listMarkdown(join24(ctx.rootDir, "reviews"))
|
|
34084
34537
|
];
|
|
34085
34538
|
const source = allFiles.find((f) => {
|
|
34086
34539
|
try {
|
|
@@ -34111,9 +34564,9 @@ function getDocumentBacklinksStub(ctx) {
|
|
|
34111
34564
|
const targetId = args["targetId"] ?? args["id"];
|
|
34112
34565
|
if (!targetId) return "getDocumentBacklinks requires targetId.";
|
|
34113
34566
|
const allFiles = [
|
|
34114
|
-
...ctx.storage.listMarkdown(
|
|
34115
|
-
...ctx.storage.listMarkdown(
|
|
34116
|
-
...ctx.storage.listMarkdown(
|
|
34567
|
+
...ctx.storage.listMarkdown(join24(ctx.rootDir, "decisions")),
|
|
34568
|
+
...ctx.storage.listMarkdown(join24(ctx.rootDir, "docs")),
|
|
34569
|
+
...ctx.storage.listMarkdown(join24(ctx.rootDir, "reviews"))
|
|
34117
34570
|
];
|
|
34118
34571
|
const backlinks = [];
|
|
34119
34572
|
for (const file2 of allFiles) {
|
|
@@ -34207,21 +34660,21 @@ __export(updater_exports, {
|
|
|
34207
34660
|
resolveBundledNpmCli: () => resolveBundledNpmCli
|
|
34208
34661
|
});
|
|
34209
34662
|
import { createRequire as createRequire2 } from "node:module";
|
|
34210
|
-
import { spawn as
|
|
34211
|
-
import { existsSync as
|
|
34212
|
-
import
|
|
34663
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
34664
|
+
import { existsSync as existsSync28 } from "node:fs";
|
|
34665
|
+
import path29 from "node:path";
|
|
34213
34666
|
import { fileURLToPath } from "node:url";
|
|
34214
34667
|
function resolveBundledNpmCli(execPath = process.execPath) {
|
|
34215
|
-
const dir =
|
|
34668
|
+
const dir = path29.dirname(execPath);
|
|
34216
34669
|
const candidates = [
|
|
34217
34670
|
// Windows: C:\...\node.exe → C:\...\node_modules\npm\bin\npm-cli.js
|
|
34218
|
-
|
|
34671
|
+
path29.join(dir, "node_modules", "npm", "bin", "npm-cli.js"),
|
|
34219
34672
|
// POSIX: <prefix>/bin/node → <prefix>/lib/node_modules/npm/bin/npm-cli.js
|
|
34220
|
-
|
|
34673
|
+
path29.join(dir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
|
|
34221
34674
|
];
|
|
34222
34675
|
for (const candidate of candidates) {
|
|
34223
34676
|
try {
|
|
34224
|
-
if (
|
|
34677
|
+
if (existsSync28(candidate)) return candidate;
|
|
34225
34678
|
} catch {
|
|
34226
34679
|
}
|
|
34227
34680
|
}
|
|
@@ -34234,7 +34687,7 @@ function looksLikeBrokenShim(exitCode, output) {
|
|
|
34234
34687
|
}
|
|
34235
34688
|
function getCurrentVersion() {
|
|
34236
34689
|
try {
|
|
34237
|
-
const pkgPath =
|
|
34690
|
+
const pkgPath = path29.resolve(__dirname2, "..", "..", "package.json");
|
|
34238
34691
|
const pkg = require2(pkgPath);
|
|
34239
34692
|
return pkg.version;
|
|
34240
34693
|
} catch {
|
|
@@ -34294,7 +34747,7 @@ async function checkForUpdate(fetcher = fetch, registryUrl) {
|
|
|
34294
34747
|
updateAvailable: cmp < 0
|
|
34295
34748
|
};
|
|
34296
34749
|
}
|
|
34297
|
-
async function performUpdate(packageName = "zelari-code", executor =
|
|
34750
|
+
async function performUpdate(packageName = "zelari-code", executor = spawn8, resolveNpmCli = resolveBundledNpmCli) {
|
|
34298
34751
|
const args = ["install", "-g", `${packageName}@latest`];
|
|
34299
34752
|
const primary = await runNpm(executor, args, "shim");
|
|
34300
34753
|
if (primary.ok) return primary;
|
|
@@ -34346,13 +34799,13 @@ var init_updater = __esm({
|
|
|
34346
34799
|
"use strict";
|
|
34347
34800
|
init_cmdline();
|
|
34348
34801
|
require2 = createRequire2(import.meta.url);
|
|
34349
|
-
__dirname2 =
|
|
34802
|
+
__dirname2 = path29.dirname(fileURLToPath(import.meta.url));
|
|
34350
34803
|
REGISTRY_URL = "https://registry.npmjs.org/zelari-code/latest";
|
|
34351
34804
|
}
|
|
34352
34805
|
});
|
|
34353
34806
|
|
|
34354
34807
|
// src/cli/mcp/mcpClient.ts
|
|
34355
|
-
import { spawn as
|
|
34808
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
34356
34809
|
var DEFAULT_REQUEST_TIMEOUT_MS, INIT_TIMEOUT_MS, MCP_PROTOCOL_VERSION, McpClient;
|
|
34357
34810
|
var init_mcpClient = __esm({
|
|
34358
34811
|
"src/cli/mcp/mcpClient.ts"() {
|
|
@@ -34380,10 +34833,10 @@ var init_mcpClient = __esm({
|
|
|
34380
34833
|
env: { ...process.env, ...this.config.env ?? {} },
|
|
34381
34834
|
windowsHide: true
|
|
34382
34835
|
};
|
|
34383
|
-
const child = process.platform === "win32" ?
|
|
34836
|
+
const child = process.platform === "win32" ? spawn9(buildCmdLine(this.config.command, this.config.args ?? []), {
|
|
34384
34837
|
...spawnOpts,
|
|
34385
34838
|
shell: true
|
|
34386
|
-
}) :
|
|
34839
|
+
}) : spawn9(this.config.command, this.config.args ?? [], spawnOpts);
|
|
34387
34840
|
this.child = child;
|
|
34388
34841
|
child.stdout.setEncoding("utf8");
|
|
34389
34842
|
child.stdout.on("data", (chunk) => this.onStdout(chunk));
|
|
@@ -34521,23 +34974,23 @@ var init_mcpClient = __esm({
|
|
|
34521
34974
|
|
|
34522
34975
|
// src/cli/mcp/mcpConfigIo.ts
|
|
34523
34976
|
import {
|
|
34524
|
-
existsSync as
|
|
34525
|
-
mkdirSync as
|
|
34526
|
-
readFileSync as
|
|
34527
|
-
writeFileSync as
|
|
34977
|
+
existsSync as existsSync29,
|
|
34978
|
+
mkdirSync as mkdirSync14,
|
|
34979
|
+
readFileSync as readFileSync25,
|
|
34980
|
+
writeFileSync as writeFileSync16
|
|
34528
34981
|
} from "node:fs";
|
|
34529
|
-
import { dirname as dirname6, join as
|
|
34530
|
-
import { homedir as
|
|
34982
|
+
import { dirname as dirname6, join as join25 } from "node:path";
|
|
34983
|
+
import { homedir as homedir10 } from "node:os";
|
|
34531
34984
|
function getUserMcpPath() {
|
|
34532
|
-
return
|
|
34985
|
+
return join25(homedir10(), ".zelari-code", "mcp.json");
|
|
34533
34986
|
}
|
|
34534
34987
|
function getProjectMcpPath(projectRoot) {
|
|
34535
|
-
return
|
|
34988
|
+
return join25(projectRoot, ".zelari", "mcp.json");
|
|
34536
34989
|
}
|
|
34537
|
-
function readFile2(
|
|
34538
|
-
if (!
|
|
34990
|
+
function readFile2(path51) {
|
|
34991
|
+
if (!existsSync29(path51)) return {};
|
|
34539
34992
|
try {
|
|
34540
|
-
const parsed = JSON.parse(
|
|
34993
|
+
const parsed = JSON.parse(readFileSync25(path51, "utf8"));
|
|
34541
34994
|
const out = {};
|
|
34542
34995
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
34543
34996
|
if (!cfg || typeof cfg.command !== "string" || !cfg.command.trim()) continue;
|
|
@@ -34553,10 +35006,10 @@ function readFile2(path48) {
|
|
|
34553
35006
|
return {};
|
|
34554
35007
|
}
|
|
34555
35008
|
}
|
|
34556
|
-
function writeFile(
|
|
34557
|
-
|
|
35009
|
+
function writeFile(path51, servers) {
|
|
35010
|
+
mkdirSync14(dirname6(path51), { recursive: true });
|
|
34558
35011
|
const body = { mcpServers: servers };
|
|
34559
|
-
|
|
35012
|
+
writeFileSync16(path51, `${JSON.stringify(body, null, 2)}
|
|
34560
35013
|
`, "utf8");
|
|
34561
35014
|
}
|
|
34562
35015
|
function listMcpServers(projectRoot) {
|
|
@@ -34589,9 +35042,9 @@ function upsertMcpServer(opts) {
|
|
|
34589
35042
|
if (!opts.config.command?.trim()) {
|
|
34590
35043
|
return { ok: false, error: "command is required" };
|
|
34591
35044
|
}
|
|
34592
|
-
let
|
|
35045
|
+
let path51;
|
|
34593
35046
|
if (opts.scope === "user") {
|
|
34594
|
-
|
|
35047
|
+
path51 = getUserMcpPath();
|
|
34595
35048
|
} else {
|
|
34596
35049
|
const root = opts.projectRoot?.trim();
|
|
34597
35050
|
if (!root) {
|
|
@@ -34600,30 +35053,30 @@ function upsertMcpServer(opts) {
|
|
|
34600
35053
|
error: "projectRoot required for project scope (Open Folder first)"
|
|
34601
35054
|
};
|
|
34602
35055
|
}
|
|
34603
|
-
|
|
35056
|
+
path51 = getProjectMcpPath(root);
|
|
34604
35057
|
}
|
|
34605
|
-
const current = readFile2(
|
|
35058
|
+
const current = readFile2(path51);
|
|
34606
35059
|
current[name] = {
|
|
34607
35060
|
command: opts.config.command.trim(),
|
|
34608
35061
|
args: opts.config.args,
|
|
34609
35062
|
env: opts.config.env,
|
|
34610
35063
|
enabled: opts.config.enabled !== false
|
|
34611
35064
|
};
|
|
34612
|
-
writeFile(
|
|
34613
|
-
return { ok: true, path:
|
|
35065
|
+
writeFile(path51, current);
|
|
35066
|
+
return { ok: true, path: path51 };
|
|
34614
35067
|
}
|
|
34615
35068
|
function removeMcpServer(opts) {
|
|
34616
|
-
const
|
|
34617
|
-
if (!
|
|
35069
|
+
const path51 = opts.scope === "user" ? getUserMcpPath() : opts.projectRoot ? getProjectMcpPath(opts.projectRoot) : null;
|
|
35070
|
+
if (!path51) {
|
|
34618
35071
|
return { ok: false, error: "projectRoot required for project scope" };
|
|
34619
35072
|
}
|
|
34620
|
-
const current = readFile2(
|
|
35073
|
+
const current = readFile2(path51);
|
|
34621
35074
|
if (!(opts.name in current)) {
|
|
34622
|
-
return { ok: false, error: `Server "${opts.name}" not found in ${
|
|
35075
|
+
return { ok: false, error: `Server "${opts.name}" not found in ${path51}` };
|
|
34623
35076
|
}
|
|
34624
35077
|
delete current[opts.name];
|
|
34625
|
-
writeFile(
|
|
34626
|
-
return { ok: true, path:
|
|
35078
|
+
writeFile(path51, current);
|
|
35079
|
+
return { ok: true, path: path51 };
|
|
34627
35080
|
}
|
|
34628
35081
|
var init_mcpConfigIo = __esm({
|
|
34629
35082
|
"src/cli/mcp/mcpConfigIo.ts"() {
|
|
@@ -34765,20 +35218,22 @@ __export(mcpManager_exports, {
|
|
|
34765
35218
|
readMcpConfig: () => readMcpConfig,
|
|
34766
35219
|
registerMcpTools: () => registerMcpTools
|
|
34767
35220
|
});
|
|
34768
|
-
import { existsSync as
|
|
34769
|
-
import { join as
|
|
34770
|
-
import { homedir as
|
|
34771
|
-
function readMcpConfig(projectRoot = process.cwd()) {
|
|
35221
|
+
import { existsSync as existsSync30, readFileSync as readFileSync26 } from "node:fs";
|
|
35222
|
+
import { join as join26 } from "node:path";
|
|
35223
|
+
import { homedir as homedir11 } from "node:os";
|
|
35224
|
+
function readMcpConfig(projectRoot = process.cwd(), opts) {
|
|
34772
35225
|
const merged = {};
|
|
34773
35226
|
const paths = [];
|
|
34774
35227
|
if (process.env["ZELARI_MCP_USER"] !== "0") {
|
|
34775
|
-
paths.push(
|
|
35228
|
+
paths.push(join26(homedir11(), ".zelari-code", "mcp.json"));
|
|
35229
|
+
}
|
|
35230
|
+
if (!opts?.skipProjectMcp) {
|
|
35231
|
+
paths.push(join26(projectRoot, ".zelari", "mcp.json"));
|
|
34776
35232
|
}
|
|
34777
|
-
paths.push(join25(projectRoot, ".zelari", "mcp.json"));
|
|
34778
35233
|
for (const p3 of paths) {
|
|
34779
|
-
if (!
|
|
35234
|
+
if (!existsSync30(p3)) continue;
|
|
34780
35235
|
try {
|
|
34781
|
-
const parsed = JSON.parse(
|
|
35236
|
+
const parsed = JSON.parse(readFileSync26(p3, "utf8"));
|
|
34782
35237
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
34783
35238
|
if (!cfg || typeof cfg.command !== "string" || cfg.command.length === 0) continue;
|
|
34784
35239
|
merged[name] = cfg;
|
|
@@ -34791,7 +35246,13 @@ function readMcpConfig(projectRoot = process.cwd()) {
|
|
|
34791
35246
|
async function ensureLoaded(projectRoot) {
|
|
34792
35247
|
if (state2.loaded) return;
|
|
34793
35248
|
state2.loaded = true;
|
|
34794
|
-
const
|
|
35249
|
+
const trusted = isFolderTrusted(projectRoot);
|
|
35250
|
+
if (!trusted && existsSync30(join26(projectRoot, ".zelari", "mcp.json"))) {
|
|
35251
|
+
state2.warnings.push(
|
|
35252
|
+
"[mcp] project .zelari/mcp.json ignored \u2014 folder not trusted (run /trust or `zelari-code --trust` to enable project MCP)"
|
|
35253
|
+
);
|
|
35254
|
+
}
|
|
35255
|
+
const servers = readMcpConfig(projectRoot, { skipProjectMcp: !trusted });
|
|
34795
35256
|
for (const [name, cfg] of Object.entries(servers)) {
|
|
34796
35257
|
if (cfg.enabled === false) continue;
|
|
34797
35258
|
if (isCuaDisabled() && isCuaMcpServerName(name)) {
|
|
@@ -34874,6 +35335,7 @@ var init_mcpManager = __esm({
|
|
|
34874
35335
|
init_toolTypes();
|
|
34875
35336
|
init_mcpClient();
|
|
34876
35337
|
init_mcpPresets();
|
|
35338
|
+
init_folderTrust();
|
|
34877
35339
|
state2 = { loaded: false, tools: [], warnings: [], clients: [] };
|
|
34878
35340
|
}
|
|
34879
35341
|
});
|
|
@@ -35010,15 +35472,15 @@ __export(agentsMd_exports, {
|
|
|
35010
35472
|
serializeAgentsMd: () => serializeAgentsMd,
|
|
35011
35473
|
updateAgentsMd: () => updateAgentsMd
|
|
35012
35474
|
});
|
|
35013
|
-
import { existsSync as
|
|
35475
|
+
import { existsSync as existsSync31, readFileSync as readFileSync27, writeFileSync as writeFileSync17 } from "node:fs";
|
|
35014
35476
|
import { createHash as createHash5 } from "node:crypto";
|
|
35015
|
-
import { join as
|
|
35477
|
+
import { join as join27 } from "node:path";
|
|
35016
35478
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
35017
35479
|
async function readPackageJson2(projectRoot) {
|
|
35018
|
-
const
|
|
35019
|
-
if (!
|
|
35480
|
+
const path51 = join27(projectRoot, "package.json");
|
|
35481
|
+
if (!existsSync31(path51)) return null;
|
|
35020
35482
|
try {
|
|
35021
|
-
return JSON.parse(await readFile3(
|
|
35483
|
+
return JSON.parse(await readFile3(path51, "utf8"));
|
|
35022
35484
|
} catch {
|
|
35023
35485
|
return null;
|
|
35024
35486
|
}
|
|
@@ -35040,8 +35502,8 @@ async function genTechStack(ctx) {
|
|
|
35040
35502
|
].join("\n");
|
|
35041
35503
|
}
|
|
35042
35504
|
async function genDecisions(ctx) {
|
|
35043
|
-
const decisionsDir =
|
|
35044
|
-
if (!
|
|
35505
|
+
const decisionsDir = join27(ctx.rootDir, "decisions");
|
|
35506
|
+
if (!existsSync31(decisionsDir)) return "_No ADRs yet._";
|
|
35045
35507
|
const files = ctx.storage.listMarkdown(decisionsDir).sort();
|
|
35046
35508
|
const accepted = [];
|
|
35047
35509
|
const proposed = [];
|
|
@@ -35066,9 +35528,9 @@ async function genDecisions(ctx) {
|
|
|
35066
35528
|
}
|
|
35067
35529
|
async function genConventions(ctx) {
|
|
35068
35530
|
const lines = [];
|
|
35069
|
-
const claudeMd =
|
|
35070
|
-
if (
|
|
35071
|
-
const content =
|
|
35531
|
+
const claudeMd = join27(ctx.projectRoot, "CLAUDE.MD");
|
|
35532
|
+
if (existsSync31(claudeMd)) {
|
|
35533
|
+
const content = readFileSync27(claudeMd, "utf8");
|
|
35072
35534
|
const match = content.match(/## Architecture rules[\s\S]+?(?=\n## |\n*$)/);
|
|
35073
35535
|
if (match) {
|
|
35074
35536
|
lines.push('<!-- Extracted from CLAUDE.MD "Architecture rules" -->');
|
|
@@ -35100,9 +35562,9 @@ async function genBuild(ctx) {
|
|
|
35100
35562
|
].join("\n");
|
|
35101
35563
|
}
|
|
35102
35564
|
async function genOpenQuestions(ctx) {
|
|
35103
|
-
const
|
|
35104
|
-
if (!
|
|
35105
|
-
const content =
|
|
35565
|
+
const path51 = join27(ctx.rootDir, "risks.md");
|
|
35566
|
+
if (!existsSync31(path51)) return "_No open questions._";
|
|
35567
|
+
const content = readFileSync27(path51, "utf8");
|
|
35106
35568
|
const lines = content.split("\n");
|
|
35107
35569
|
const questions = [];
|
|
35108
35570
|
let currentTitle = "";
|
|
@@ -35176,9 +35638,9 @@ function titleCase(id) {
|
|
|
35176
35638
|
return id.split("-").map((w) => w[0].toUpperCase() + w.slice(1)).join(" ");
|
|
35177
35639
|
}
|
|
35178
35640
|
async function updateAgentsMd(ctx, projectRoot) {
|
|
35179
|
-
const agentsPath =
|
|
35180
|
-
if (
|
|
35181
|
-
const content =
|
|
35641
|
+
const agentsPath = join27(projectRoot, "AGENTS.MD");
|
|
35642
|
+
if (existsSync31(agentsPath)) {
|
|
35643
|
+
const content = readFileSync27(agentsPath, "utf8");
|
|
35182
35644
|
const hasAnyMarker = AUTO_SECTIONS.some((id) => content.includes(MARKER_OPEN(id)));
|
|
35183
35645
|
if (!hasAnyMarker) {
|
|
35184
35646
|
return {
|
|
@@ -35193,8 +35655,8 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
35193
35655
|
newSections.set(id, await GENERATORS[id](ctx));
|
|
35194
35656
|
}
|
|
35195
35657
|
let manualContent = "";
|
|
35196
|
-
if (
|
|
35197
|
-
const { manualBlocks } = parseAgentsMd(
|
|
35658
|
+
if (existsSync31(agentsPath)) {
|
|
35659
|
+
const { manualBlocks } = parseAgentsMd(readFileSync27(agentsPath, "utf8"));
|
|
35198
35660
|
manualContent = manualBlocks.after;
|
|
35199
35661
|
} else {
|
|
35200
35662
|
const projectName2 = projectName(projectRoot);
|
|
@@ -35210,7 +35672,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
35210
35672
|
""
|
|
35211
35673
|
].join("\n");
|
|
35212
35674
|
}
|
|
35213
|
-
const oldContent =
|
|
35675
|
+
const oldContent = existsSync31(agentsPath) ? readFileSync27(agentsPath, "utf8") : "";
|
|
35214
35676
|
const { sections: oldSections } = parseAgentsMd(oldContent);
|
|
35215
35677
|
const changedSections = [];
|
|
35216
35678
|
for (const id of AUTO_SECTIONS) {
|
|
@@ -35222,7 +35684,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
35222
35684
|
return { changed: false, sections: [] };
|
|
35223
35685
|
}
|
|
35224
35686
|
const newContent = serializeAgentsMd(manualContent, newSections);
|
|
35225
|
-
|
|
35687
|
+
writeFileSync17(agentsPath, newContent, "utf8");
|
|
35226
35688
|
return { changed: true, sections: changedSections };
|
|
35227
35689
|
}
|
|
35228
35690
|
function hash2(s) {
|
|
@@ -35347,9 +35809,9 @@ var init_completeDesign = __esm({
|
|
|
35347
35809
|
});
|
|
35348
35810
|
|
|
35349
35811
|
// src/cli/workspace/projectSmoke.ts
|
|
35350
|
-
import { spawn as
|
|
35351
|
-
import { existsSync as
|
|
35352
|
-
import { join as
|
|
35812
|
+
import { spawn as spawn10 } from "node:child_process";
|
|
35813
|
+
import { existsSync as existsSync32, readFileSync as readFileSync28 } from "node:fs";
|
|
35814
|
+
import { join as join28 } from "node:path";
|
|
35353
35815
|
function pickSmokeScript(scripts) {
|
|
35354
35816
|
if (!scripts) return null;
|
|
35355
35817
|
for (const name of SMOKE_SCRIPT_PRIORITY) {
|
|
@@ -35357,17 +35819,17 @@ function pickSmokeScript(scripts) {
|
|
|
35357
35819
|
}
|
|
35358
35820
|
return null;
|
|
35359
35821
|
}
|
|
35360
|
-
async function runProjectSmoke(projectRoot, timeoutMs =
|
|
35822
|
+
async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS2) {
|
|
35361
35823
|
if (process.env["ZELARI_SMOKE"] === "0") {
|
|
35362
35824
|
return { ran: false, reason: "ZELARI_SMOKE=0 (disabled)" };
|
|
35363
35825
|
}
|
|
35364
|
-
const pkgPath =
|
|
35365
|
-
if (!
|
|
35826
|
+
const pkgPath = join28(projectRoot, "package.json");
|
|
35827
|
+
if (!existsSync32(pkgPath)) {
|
|
35366
35828
|
return { ran: false, reason: "no package.json (skipped)" };
|
|
35367
35829
|
}
|
|
35368
35830
|
let scripts = {};
|
|
35369
35831
|
try {
|
|
35370
|
-
const pkg = JSON.parse(
|
|
35832
|
+
const pkg = JSON.parse(readFileSync28(pkgPath, "utf8"));
|
|
35371
35833
|
scripts = pkg.scripts ?? {};
|
|
35372
35834
|
} catch {
|
|
35373
35835
|
return { ran: false, reason: "package.json unreadable (skipped)" };
|
|
@@ -35377,12 +35839,12 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
|
35377
35839
|
return { ran: false, reason: "no typecheck/test/build script (skipped)" };
|
|
35378
35840
|
}
|
|
35379
35841
|
return await new Promise((resolveRun) => {
|
|
35380
|
-
const child = process.platform === "win32" ?
|
|
35842
|
+
const child = process.platform === "win32" ? spawn10(buildCmdLine("npm.cmd", ["run", script]), {
|
|
35381
35843
|
cwd: projectRoot,
|
|
35382
35844
|
stdio: ["ignore", "pipe", "pipe"],
|
|
35383
35845
|
env: process.env,
|
|
35384
35846
|
shell: true
|
|
35385
|
-
}) :
|
|
35847
|
+
}) : spawn10("npm", ["run", script], {
|
|
35386
35848
|
cwd: projectRoot,
|
|
35387
35849
|
stdio: ["ignore", "pipe", "pipe"],
|
|
35388
35850
|
env: process.env
|
|
@@ -35437,13 +35899,13 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
|
35437
35899
|
});
|
|
35438
35900
|
});
|
|
35439
35901
|
}
|
|
35440
|
-
var SMOKE_SCRIPT_PRIORITY,
|
|
35902
|
+
var SMOKE_SCRIPT_PRIORITY, DEFAULT_TIMEOUT_MS2;
|
|
35441
35903
|
var init_projectSmoke = __esm({
|
|
35442
35904
|
"src/cli/workspace/projectSmoke.ts"() {
|
|
35443
35905
|
"use strict";
|
|
35444
35906
|
init_cmdline();
|
|
35445
35907
|
SMOKE_SCRIPT_PRIORITY = ["typecheck", "test", "build"];
|
|
35446
|
-
|
|
35908
|
+
DEFAULT_TIMEOUT_MS2 = 12e4;
|
|
35447
35909
|
}
|
|
35448
35910
|
});
|
|
35449
35911
|
|
|
@@ -35454,9 +35916,9 @@ __export(postCouncilHook_exports, {
|
|
|
35454
35916
|
runImplementationVerificationHook: () => runImplementationVerificationHook,
|
|
35455
35917
|
runPostCouncilHook: () => runPostCouncilHook
|
|
35456
35918
|
});
|
|
35457
|
-
import { spawn as
|
|
35458
|
-
import { existsSync as
|
|
35459
|
-
import { join as
|
|
35919
|
+
import { spawn as spawn11 } from "node:child_process";
|
|
35920
|
+
import { existsSync as existsSync33, readFileSync as readFileSync29 } from "node:fs";
|
|
35921
|
+
import { join as join29 } from "node:path";
|
|
35460
35922
|
async function runCompleteDesignPostProcessor(ctx, options) {
|
|
35461
35923
|
if (options?.runMode === "implementation") {
|
|
35462
35924
|
return {
|
|
@@ -35467,9 +35929,9 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
35467
35929
|
if (process.env["ZELARI_COMPLETE_DESIGN"] === "0") {
|
|
35468
35930
|
return { ran: false, reason: "ZELARI_COMPLETE_DESIGN=0 (disabled)" };
|
|
35469
35931
|
}
|
|
35470
|
-
const planJsonPath2 =
|
|
35471
|
-
const scriptPath =
|
|
35472
|
-
if (!
|
|
35932
|
+
const planJsonPath2 = join29(ctx.rootDir, "plan.json");
|
|
35933
|
+
const scriptPath = join29(ctx.projectRoot, "complete-design.mjs");
|
|
35934
|
+
if (!existsSync33(planJsonPath2)) {
|
|
35473
35935
|
return {
|
|
35474
35936
|
ran: false,
|
|
35475
35937
|
reason: ".zelari/plan.json missing (not design-phase)"
|
|
@@ -35477,7 +35939,7 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
35477
35939
|
}
|
|
35478
35940
|
let phaseCount = 0;
|
|
35479
35941
|
try {
|
|
35480
|
-
const parsed = JSON.parse(
|
|
35942
|
+
const parsed = JSON.parse(readFileSync29(planJsonPath2, "utf8"));
|
|
35481
35943
|
phaseCount = Array.isArray(parsed.phases) ? parsed.phases.length : 0;
|
|
35482
35944
|
} catch {
|
|
35483
35945
|
return { ran: false, reason: ".zelari/plan.json corrupt" };
|
|
@@ -35485,7 +35947,7 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
35485
35947
|
if (phaseCount === 0) {
|
|
35486
35948
|
return { ran: false, reason: ".zelari/plan.json has no phases" };
|
|
35487
35949
|
}
|
|
35488
|
-
if (!
|
|
35950
|
+
if (!existsSync33(scriptPath)) {
|
|
35489
35951
|
try {
|
|
35490
35952
|
const builtin = await runBuiltinCompleteDesign(ctx);
|
|
35491
35953
|
return {
|
|
@@ -35503,7 +35965,7 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
35503
35965
|
}
|
|
35504
35966
|
}
|
|
35505
35967
|
return await new Promise((resolveRun) => {
|
|
35506
|
-
const child =
|
|
35968
|
+
const child = spawn11(process.execPath, [scriptPath], {
|
|
35507
35969
|
cwd: ctx.projectRoot,
|
|
35508
35970
|
stdio: ["ignore", "pipe", "pipe"],
|
|
35509
35971
|
env: process.env
|
|
@@ -35669,8 +36131,8 @@ async function runPostCouncilHook(ctx, options) {
|
|
|
35669
36131
|
sources: scope.sources
|
|
35670
36132
|
} : void 0
|
|
35671
36133
|
});
|
|
35672
|
-
const
|
|
35673
|
-
completionHook = { ran: true, path:
|
|
36134
|
+
const path51 = writeCouncilCompletion(ctx.rootDir, completion);
|
|
36135
|
+
completionHook = { ran: true, path: path51, completion };
|
|
35674
36136
|
} catch (err) {
|
|
35675
36137
|
completionHook = {
|
|
35676
36138
|
ran: true,
|
|
@@ -35708,12 +36170,12 @@ __export(councilFeedback_exports, {
|
|
|
35708
36170
|
});
|
|
35709
36171
|
import {
|
|
35710
36172
|
promises as fs15,
|
|
35711
|
-
existsSync as
|
|
35712
|
-
readFileSync as
|
|
35713
|
-
writeFileSync as
|
|
35714
|
-
mkdirSync as
|
|
36173
|
+
existsSync as existsSync34,
|
|
36174
|
+
readFileSync as readFileSync30,
|
|
36175
|
+
writeFileSync as writeFileSync18,
|
|
36176
|
+
mkdirSync as mkdirSync15
|
|
35715
36177
|
} from "node:fs";
|
|
35716
|
-
import
|
|
36178
|
+
import path30 from "node:path";
|
|
35717
36179
|
import os8 from "node:os";
|
|
35718
36180
|
var FeedbackStore;
|
|
35719
36181
|
var init_councilFeedback = __esm({
|
|
@@ -35724,7 +36186,7 @@ var init_councilFeedback = __esm({
|
|
|
35724
36186
|
now;
|
|
35725
36187
|
entries = [];
|
|
35726
36188
|
constructor(options = {}) {
|
|
35727
|
-
this.file = options.file ?? (process.env.ANATHEMA_COUNCIL_FEEDBACK_FILE ??
|
|
36189
|
+
this.file = options.file ?? (process.env.ANATHEMA_COUNCIL_FEEDBACK_FILE ?? path30.join(os8.homedir(), ".tmp", "zelari-code", "council-feedback.json"));
|
|
35728
36190
|
this.now = options.now ?? Date.now;
|
|
35729
36191
|
this.load();
|
|
35730
36192
|
}
|
|
@@ -35817,9 +36279,9 @@ var init_councilFeedback = __esm({
|
|
|
35817
36279
|
}
|
|
35818
36280
|
// --- persistence ---------------------------------------------------------
|
|
35819
36281
|
load() {
|
|
35820
|
-
if (!
|
|
36282
|
+
if (!existsSync34(this.file)) return;
|
|
35821
36283
|
try {
|
|
35822
|
-
const raw =
|
|
36284
|
+
const raw = readFileSync30(this.file, "utf-8");
|
|
35823
36285
|
const parsed = JSON.parse(raw);
|
|
35824
36286
|
if (parsed && Array.isArray(parsed.entries)) {
|
|
35825
36287
|
this.entries = parsed.entries.filter(
|
|
@@ -35830,8 +36292,8 @@ var init_councilFeedback = __esm({
|
|
|
35830
36292
|
}
|
|
35831
36293
|
}
|
|
35832
36294
|
save() {
|
|
35833
|
-
|
|
35834
|
-
|
|
36295
|
+
mkdirSync15(path30.dirname(this.file), { recursive: true });
|
|
36296
|
+
writeFileSync18(
|
|
35835
36297
|
this.file,
|
|
35836
36298
|
JSON.stringify({ entries: this.entries }, null, 2),
|
|
35837
36299
|
{ encoding: "utf-8", mode: 384 }
|
|
@@ -35898,7 +36360,7 @@ import { execFile as execFile3 } from "node:child_process";
|
|
|
35898
36360
|
import { promisify as promisify2 } from "node:util";
|
|
35899
36361
|
import { mkdtempSync, rmSync as rmSync2 } from "node:fs";
|
|
35900
36362
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
35901
|
-
import
|
|
36363
|
+
import path31 from "node:path";
|
|
35902
36364
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
35903
36365
|
async function git2(cwd, args, env) {
|
|
35904
36366
|
const { stdout } = await execFileAsync2("git", ["-C", cwd, ...args], {
|
|
@@ -35918,8 +36380,8 @@ async function isGitRepo(cwd) {
|
|
|
35918
36380
|
return await gitSafe(cwd, ["rev-parse", "--is-inside-work-tree"]) === "true";
|
|
35919
36381
|
}
|
|
35920
36382
|
async function withTempIndex(fn) {
|
|
35921
|
-
const dir = mkdtempSync(
|
|
35922
|
-
const indexFile =
|
|
36383
|
+
const dir = mkdtempSync(path31.join(tmpdir2(), "zelari-ckpt-"));
|
|
36384
|
+
const indexFile = path31.join(dir, "index");
|
|
35923
36385
|
try {
|
|
35924
36386
|
return await fn(indexFile);
|
|
35925
36387
|
} finally {
|
|
@@ -36010,7 +36472,7 @@ async function restoreCheckpoint(cwd, id) {
|
|
|
36010
36472
|
const deleted = [];
|
|
36011
36473
|
for (const rel2 of added) {
|
|
36012
36474
|
try {
|
|
36013
|
-
rmSync2(
|
|
36475
|
+
rmSync2(path31.join(cwd, rel2), { force: true });
|
|
36014
36476
|
deleted.push(rel2);
|
|
36015
36477
|
} catch {
|
|
36016
36478
|
}
|
|
@@ -36111,7 +36573,7 @@ __export(fileBackend_exports, {
|
|
|
36111
36573
|
});
|
|
36112
36574
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
36113
36575
|
import { promises as fs16 } from "node:fs";
|
|
36114
|
-
import * as
|
|
36576
|
+
import * as path32 from "node:path";
|
|
36115
36577
|
function tokenize(text) {
|
|
36116
36578
|
return text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 3);
|
|
36117
36579
|
}
|
|
@@ -36155,8 +36617,8 @@ var init_fileBackend = __esm({
|
|
|
36155
36617
|
logPath = "";
|
|
36156
36618
|
memoryDir = "";
|
|
36157
36619
|
async init(projectRoot) {
|
|
36158
|
-
this.memoryDir =
|
|
36159
|
-
this.logPath =
|
|
36620
|
+
this.memoryDir = path32.join(projectRoot, ".zelari", "memory");
|
|
36621
|
+
this.logPath = path32.join(this.memoryDir, "log.jsonl");
|
|
36160
36622
|
await fs16.mkdir(this.memoryDir, { recursive: true });
|
|
36161
36623
|
}
|
|
36162
36624
|
async add(content, metadata = {}, graph) {
|
|
@@ -36229,12 +36691,12 @@ var init_fileBackend = __esm({
|
|
|
36229
36691
|
|
|
36230
36692
|
// src/cli/traceStore.ts
|
|
36231
36693
|
import { promises as fs17 } from "node:fs";
|
|
36232
|
-
import * as
|
|
36694
|
+
import * as path33 from "node:path";
|
|
36233
36695
|
function traceDir(projectRoot) {
|
|
36234
|
-
return
|
|
36696
|
+
return path33.join(projectRoot, ".zelari", "trace");
|
|
36235
36697
|
}
|
|
36236
36698
|
function tracePath(projectRoot, missionId) {
|
|
36237
|
-
return
|
|
36699
|
+
return path33.join(traceDir(projectRoot), `${missionId}.json`);
|
|
36238
36700
|
}
|
|
36239
36701
|
async function saveTrace(projectRoot, missionId, entries) {
|
|
36240
36702
|
const dir = traceDir(projectRoot);
|
|
@@ -36269,7 +36731,7 @@ __export(zelariMission_exports, {
|
|
|
36269
36731
|
});
|
|
36270
36732
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
36271
36733
|
import { promises as fs18 } from "node:fs";
|
|
36272
|
-
import * as
|
|
36734
|
+
import * as path34 from "node:path";
|
|
36273
36735
|
function resolveMaxIterations(env = process.env) {
|
|
36274
36736
|
const raw = env.ZELARI_MISSION_MAX_ITER;
|
|
36275
36737
|
const n = raw ? Number.parseInt(raw, 10) : DEFAULT_MAX_ITER;
|
|
@@ -36297,10 +36759,10 @@ function isMissionAutoStart(env = process.env) {
|
|
|
36297
36759
|
return env.ZELARI_MISSION_AUTO === "1";
|
|
36298
36760
|
}
|
|
36299
36761
|
async function writeMissionState(projectRoot, state3) {
|
|
36300
|
-
const dir =
|
|
36762
|
+
const dir = path34.join(projectRoot, ".zelari");
|
|
36301
36763
|
await fs18.mkdir(dir, { recursive: true });
|
|
36302
36764
|
await fs18.writeFile(
|
|
36303
|
-
|
|
36765
|
+
path34.join(dir, "mission-state.json"),
|
|
36304
36766
|
JSON.stringify(state3, null, 2) + "\n",
|
|
36305
36767
|
"utf8"
|
|
36306
36768
|
);
|
|
@@ -36900,7 +37362,7 @@ function safeSocketPath(socketPath) {
|
|
|
36900
37362
|
return socketPath.trim();
|
|
36901
37363
|
}
|
|
36902
37364
|
function startPermissionBroker(socketPath, handlers, opts) {
|
|
36903
|
-
const
|
|
37365
|
+
const path51 = safeSocketPath(socketPath);
|
|
36904
37366
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
36905
37367
|
const sockets = /* @__PURE__ */ new Set();
|
|
36906
37368
|
const server = createServer((socket) => {
|
|
@@ -37000,10 +37462,10 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
37000
37462
|
return new Promise((resolve3, reject) => {
|
|
37001
37463
|
const onError = (err) => reject(err);
|
|
37002
37464
|
server.once("error", onError);
|
|
37003
|
-
server.listen(
|
|
37465
|
+
server.listen(path51, () => {
|
|
37004
37466
|
server.removeListener("error", onError);
|
|
37005
37467
|
resolve3({
|
|
37006
|
-
socketPath:
|
|
37468
|
+
socketPath: path51,
|
|
37007
37469
|
stop: () => new Promise((res) => {
|
|
37008
37470
|
for (const s of sockets) s.destroy();
|
|
37009
37471
|
sockets.clear();
|
|
@@ -37014,7 +37476,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
37014
37476
|
if (done) return;
|
|
37015
37477
|
done = true;
|
|
37016
37478
|
if (process.platform !== "win32") {
|
|
37017
|
-
unlink(
|
|
37479
|
+
unlink(path51, () => res());
|
|
37018
37480
|
} else {
|
|
37019
37481
|
res();
|
|
37020
37482
|
}
|
|
@@ -37027,11 +37489,11 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
37027
37489
|
});
|
|
37028
37490
|
}
|
|
37029
37491
|
function requestBrokerAsk(socketPath, ask, opts) {
|
|
37030
|
-
const
|
|
37492
|
+
const path51 = safeSocketPath(socketPath);
|
|
37031
37493
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
37032
37494
|
const connectTimeoutMs = opts?.connectTimeoutMs ?? PERMISSION_BROKER_DEFAULT_CONNECT_TIMEOUT_MS;
|
|
37033
37495
|
return new Promise((resolve3, reject) => {
|
|
37034
|
-
const socket = connect(
|
|
37496
|
+
const socket = connect(path51);
|
|
37035
37497
|
let buffer = "";
|
|
37036
37498
|
let settled = false;
|
|
37037
37499
|
const settle = (fn) => {
|
|
@@ -37046,7 +37508,7 @@ function requestBrokerAsk(socketPath, ask, opts) {
|
|
|
37046
37508
|
settle(
|
|
37047
37509
|
() => reject(
|
|
37048
37510
|
new Error(
|
|
37049
|
-
`permission broker unavailable at "${
|
|
37511
|
+
`permission broker unavailable at "${path51}" (connect timed out after ${connectTimeoutMs}ms)`
|
|
37050
37512
|
)
|
|
37051
37513
|
)
|
|
37052
37514
|
);
|
|
@@ -37779,9 +38241,9 @@ __export(graphMemory_exports, {
|
|
|
37779
38241
|
toGraphSnapshot: () => toGraphSnapshot
|
|
37780
38242
|
});
|
|
37781
38243
|
import { promises as fs19 } from "node:fs";
|
|
37782
|
-
import
|
|
38244
|
+
import path36 from "node:path";
|
|
37783
38245
|
function snapshotPath(cwd) {
|
|
37784
|
-
return
|
|
38246
|
+
return path36.join(cwd, SNAPSHOT_DIR, SNAPSHOT_FILE);
|
|
37785
38247
|
}
|
|
37786
38248
|
function toGraphSnapshot(graph, opts) {
|
|
37787
38249
|
const unresolved = (opts.unresolvedFindings ?? []).map((u) => ({
|
|
@@ -37808,7 +38270,7 @@ async function saveGraphSnapshot(cwd, snapshot) {
|
|
|
37808
38270
|
try {
|
|
37809
38271
|
await fs19.access(cwd);
|
|
37810
38272
|
const file2 = snapshotPath(cwd);
|
|
37811
|
-
await fs19.mkdir(
|
|
38273
|
+
await fs19.mkdir(path36.dirname(file2), { recursive: true });
|
|
37812
38274
|
await fs19.writeFile(file2, JSON.stringify(snapshot, null, 2) + "\n", "utf8");
|
|
37813
38275
|
} catch {
|
|
37814
38276
|
}
|
|
@@ -37875,7 +38337,7 @@ var SNAPSHOT_DIR, SNAPSHOT_FILE, MAX_SNAPSHOT_FINDINGS_CHARS;
|
|
|
37875
38337
|
var init_graphMemory = __esm({
|
|
37876
38338
|
"src/cli/kraken/graphMemory.ts"() {
|
|
37877
38339
|
"use strict";
|
|
37878
|
-
SNAPSHOT_DIR =
|
|
38340
|
+
SNAPSHOT_DIR = path36.join(".zelari", "kraken");
|
|
37879
38341
|
SNAPSHOT_FILE = "last-graph.json";
|
|
37880
38342
|
MAX_SNAPSHOT_FINDINGS_CHARS = 400;
|
|
37881
38343
|
}
|
|
@@ -37891,14 +38353,14 @@ var init_tentacle = __esm({
|
|
|
37891
38353
|
|
|
37892
38354
|
// src/cli/kraken/workbench.ts
|
|
37893
38355
|
import { promises as fs20 } from "node:fs";
|
|
37894
|
-
import
|
|
38356
|
+
import path37 from "node:path";
|
|
37895
38357
|
function isWorkbenchEnabled(env = process.env) {
|
|
37896
38358
|
const v = (env.ZELARI_KRAKEN_WORKBENCH ?? "1").trim().toLowerCase();
|
|
37897
38359
|
if (v === "0" || v === "false" || v === "no" || v === "off") return false;
|
|
37898
38360
|
return true;
|
|
37899
38361
|
}
|
|
37900
38362
|
function workbenchPath(cwd, graphId) {
|
|
37901
|
-
return
|
|
38363
|
+
return path37.join(cwd, ".zelari", "radio", `workbench-${graphId}.md`);
|
|
37902
38364
|
}
|
|
37903
38365
|
function countByStatus2(nodes) {
|
|
37904
38366
|
const out = { pending: 0, running: 0, done: 0, error: 0, skipped: 0 };
|
|
@@ -38061,7 +38523,7 @@ var init_workbench = __esm({
|
|
|
38061
38523
|
if (!this.enabled) return null;
|
|
38062
38524
|
if (!this.dirty && this.lastWrite) return this.lastWrite;
|
|
38063
38525
|
const out = workbenchPath(this.cwd, this.graphId);
|
|
38064
|
-
await fs20.mkdir(
|
|
38526
|
+
await fs20.mkdir(path37.dirname(out), { recursive: true });
|
|
38065
38527
|
const body = this.render();
|
|
38066
38528
|
const tmp = `${out}.${process.pid}.${Date.now()}.tmp`;
|
|
38067
38529
|
await fs20.writeFile(tmp, body, "utf8");
|
|
@@ -38257,8 +38719,8 @@ __export(executor_exports, {
|
|
|
38257
38719
|
resolveNodeTimeoutMs: () => resolveNodeTimeoutMs,
|
|
38258
38720
|
thoroughnessForKind: () => thoroughnessForKind
|
|
38259
38721
|
});
|
|
38260
|
-
import { existsSync as
|
|
38261
|
-
import
|
|
38722
|
+
import { existsSync as existsSync35 } from "node:fs";
|
|
38723
|
+
import path38 from "node:path";
|
|
38262
38724
|
function resolveMaxParallel(env = process.env) {
|
|
38263
38725
|
const raw = env.ZELARI_KRAKEN_MAX_PARALLEL;
|
|
38264
38726
|
if (raw === void 0 || raw === "") return DEFAULT_MAX_PARALLEL;
|
|
@@ -38316,7 +38778,7 @@ function isWorldModelGateEnabled(cwd, env = process.env, checksExists = defaultC
|
|
|
38316
38778
|
}
|
|
38317
38779
|
function defaultChecksExists(cwd) {
|
|
38318
38780
|
try {
|
|
38319
|
-
return
|
|
38781
|
+
return existsSync35(path38.join(cwd, ".zelari", "world", "checks.json"));
|
|
38320
38782
|
} catch {
|
|
38321
38783
|
return false;
|
|
38322
38784
|
}
|
|
@@ -39283,7 +39745,7 @@ __export(prereqChecks_exports, {
|
|
|
39283
39745
|
runPrereqChecks: () => runPrereqChecks
|
|
39284
39746
|
});
|
|
39285
39747
|
import { execSync, spawnSync as spawnSync2 } from "node:child_process";
|
|
39286
|
-
import { existsSync as
|
|
39748
|
+
import { existsSync as existsSync36 } from "node:fs";
|
|
39287
39749
|
import { dirname as dirname7 } from "node:path";
|
|
39288
39750
|
function isWslBashPath2(p3) {
|
|
39289
39751
|
if (!p3 || typeof p3 !== "string") return false;
|
|
@@ -39407,7 +39869,7 @@ function agentProbeEnv() {
|
|
|
39407
39869
|
}
|
|
39408
39870
|
function existsSyncSafe2(p3) {
|
|
39409
39871
|
try {
|
|
39410
|
-
return
|
|
39872
|
+
return existsSync36(p3);
|
|
39411
39873
|
} catch {
|
|
39412
39874
|
return false;
|
|
39413
39875
|
}
|
|
@@ -39654,17 +40116,17 @@ var init_prereqChecks = __esm({
|
|
|
39654
40116
|
});
|
|
39655
40117
|
|
|
39656
40118
|
// src/cli/plugins/prefs.ts
|
|
39657
|
-
import { existsSync as
|
|
39658
|
-
import
|
|
40119
|
+
import { existsSync as existsSync37, readFileSync as readFileSync31, writeFileSync as writeFileSync19, mkdirSync as mkdirSync16 } from "node:fs";
|
|
40120
|
+
import path41 from "node:path";
|
|
39659
40121
|
import os9 from "node:os";
|
|
39660
40122
|
function getPluginPrefsPath() {
|
|
39661
|
-
return process.env.ZELARI_PLUGINS_PREFS_FILE ??
|
|
40123
|
+
return process.env.ZELARI_PLUGINS_PREFS_FILE ?? path41.join(os9.homedir(), ".tmp", "zelari-code", "plugins.json");
|
|
39662
40124
|
}
|
|
39663
40125
|
function getPluginPrefs() {
|
|
39664
40126
|
const file2 = getPluginPrefsPath();
|
|
39665
40127
|
try {
|
|
39666
|
-
if (!
|
|
39667
|
-
const raw =
|
|
40128
|
+
if (!existsSync37(file2)) return { ...DEFAULTS2, dontAskAgain: {} };
|
|
40129
|
+
const raw = readFileSync31(file2, "utf-8");
|
|
39668
40130
|
const parsed = JSON.parse(raw);
|
|
39669
40131
|
if (parsed && typeof parsed === "object" && parsed.dontAskAgain && typeof parsed.dontAskAgain === "object") {
|
|
39670
40132
|
const clean = {};
|
|
@@ -39679,8 +40141,8 @@ function getPluginPrefs() {
|
|
|
39679
40141
|
}
|
|
39680
40142
|
function writePluginPrefs(prefs) {
|
|
39681
40143
|
const file2 = getPluginPrefsPath();
|
|
39682
|
-
|
|
39683
|
-
|
|
40144
|
+
mkdirSync16(path41.dirname(file2), { recursive: true });
|
|
40145
|
+
writeFileSync19(file2, JSON.stringify(prefs, null, 2), {
|
|
39684
40146
|
encoding: "utf-8",
|
|
39685
40147
|
mode: 384
|
|
39686
40148
|
});
|
|
@@ -39715,8 +40177,8 @@ __export(registry_exports, {
|
|
|
39715
40177
|
findPlugin: () => findPlugin,
|
|
39716
40178
|
isBinaryOnPath: () => isBinaryOnPath
|
|
39717
40179
|
});
|
|
39718
|
-
import { existsSync as
|
|
39719
|
-
import
|
|
40180
|
+
import { existsSync as existsSync38 } from "node:fs";
|
|
40181
|
+
import path42 from "node:path";
|
|
39720
40182
|
function detectLocalBin(bin) {
|
|
39721
40183
|
return (cwd) => {
|
|
39722
40184
|
try {
|
|
@@ -39732,9 +40194,9 @@ function isBinaryOnPath(bin, opts = {}) {
|
|
|
39732
40194
|
return false;
|
|
39733
40195
|
}
|
|
39734
40196
|
const platform = opts.platform ?? process.platform;
|
|
39735
|
-
const exists = opts.exists ??
|
|
40197
|
+
const exists = opts.exists ?? existsSync38;
|
|
39736
40198
|
const pathEnv = opts.pathEnv ?? process.env.PATH ?? "";
|
|
39737
|
-
const pathMod = platform === "win32" ?
|
|
40199
|
+
const pathMod = platform === "win32" ? path42.win32 : path42.posix;
|
|
39738
40200
|
const sep2 = platform === "win32" ? ";" : ":";
|
|
39739
40201
|
const dirs = pathEnv.split(sep2).filter((d) => d.length > 0);
|
|
39740
40202
|
const candidates = [bin];
|
|
@@ -39871,7 +40333,7 @@ __export(atMentions_exports, {
|
|
|
39871
40333
|
extractAtMentions: () => extractAtMentions,
|
|
39872
40334
|
hasAtMentions: () => hasAtMentions
|
|
39873
40335
|
});
|
|
39874
|
-
import { existsSync as
|
|
40336
|
+
import { existsSync as existsSync41, readFileSync as readFileSync33, statSync as statSync6 } from "node:fs";
|
|
39875
40337
|
import { basename as basename3, isAbsolute as isAbsolute2, relative as relative3, resolve, sep } from "node:path";
|
|
39876
40338
|
function isImagePath(abs) {
|
|
39877
40339
|
const ext = abs.split(".").pop()?.toLowerCase() ?? "";
|
|
@@ -39925,7 +40387,7 @@ function resolveMention(token, cwd) {
|
|
|
39925
40387
|
note: "outside project root \u2014 skipped"
|
|
39926
40388
|
};
|
|
39927
40389
|
}
|
|
39928
|
-
if (!
|
|
40390
|
+
if (!existsSync41(abs)) {
|
|
39929
40391
|
return {
|
|
39930
40392
|
raw: token,
|
|
39931
40393
|
path: token,
|
|
@@ -39977,7 +40439,7 @@ function resolveMention(token, cwd) {
|
|
|
39977
40439
|
note: `image too large (${Math.round(st.size / 1024)} KB) \u2014 path only`
|
|
39978
40440
|
};
|
|
39979
40441
|
}
|
|
39980
|
-
const dataBase64 =
|
|
40442
|
+
const dataBase64 = readFileSync33(abs).toString("base64");
|
|
39981
40443
|
return {
|
|
39982
40444
|
raw: token,
|
|
39983
40445
|
path: rel2,
|
|
@@ -39988,7 +40450,7 @@ function resolveMention(token, cwd) {
|
|
|
39988
40450
|
};
|
|
39989
40451
|
}
|
|
39990
40452
|
try {
|
|
39991
|
-
const buf =
|
|
40453
|
+
const buf = readFileSync33(abs);
|
|
39992
40454
|
const head = buf.subarray(0, 800).toString("utf8");
|
|
39993
40455
|
if (!isProbablyText(abs, head)) {
|
|
39994
40456
|
return {
|
|
@@ -40086,9 +40548,9 @@ __export(triggerLock_exports, {
|
|
|
40086
40548
|
releaseLock: () => releaseLock
|
|
40087
40549
|
});
|
|
40088
40550
|
import { promises as fs28 } from "node:fs";
|
|
40089
|
-
import * as
|
|
40551
|
+
import * as path47 from "node:path";
|
|
40090
40552
|
function lockPath(projectRoot) {
|
|
40091
|
-
return
|
|
40553
|
+
return path47.join(projectRoot, ".zelari", "trigger.lock");
|
|
40092
40554
|
}
|
|
40093
40555
|
function isPidAlive(pid) {
|
|
40094
40556
|
try {
|
|
@@ -40101,7 +40563,7 @@ function isPidAlive(pid) {
|
|
|
40101
40563
|
}
|
|
40102
40564
|
async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date()) {
|
|
40103
40565
|
const lp = lockPath(projectRoot);
|
|
40104
|
-
const dir =
|
|
40566
|
+
const dir = path47.dirname(lp);
|
|
40105
40567
|
await fs28.mkdir(dir, { recursive: true });
|
|
40106
40568
|
try {
|
|
40107
40569
|
const raw = await fs28.readFile(lp, "utf8");
|
|
@@ -40383,6 +40845,269 @@ var init_desktopConfig = __esm({
|
|
|
40383
40845
|
}
|
|
40384
40846
|
});
|
|
40385
40847
|
|
|
40848
|
+
// src/cli/skillCategories.ts
|
|
40849
|
+
var CODING_CATEGORIES_LIST, CODING_CATEGORIES2;
|
|
40850
|
+
var init_skillCategories = __esm({
|
|
40851
|
+
"src/cli/skillCategories.ts"() {
|
|
40852
|
+
"use strict";
|
|
40853
|
+
CODING_CATEGORIES_LIST = [
|
|
40854
|
+
"plan",
|
|
40855
|
+
"refactor",
|
|
40856
|
+
"debug",
|
|
40857
|
+
"review",
|
|
40858
|
+
"test",
|
|
40859
|
+
"docs",
|
|
40860
|
+
"ops",
|
|
40861
|
+
"git",
|
|
40862
|
+
"db",
|
|
40863
|
+
"maint"
|
|
40864
|
+
];
|
|
40865
|
+
CODING_CATEGORIES2 = new Set(CODING_CATEGORIES_LIST);
|
|
40866
|
+
}
|
|
40867
|
+
});
|
|
40868
|
+
|
|
40869
|
+
// src/cli/skillConfigIo.ts
|
|
40870
|
+
import {
|
|
40871
|
+
existsSync as existsSync43,
|
|
40872
|
+
mkdirSync as mkdirSync19,
|
|
40873
|
+
readdirSync as readdirSync8,
|
|
40874
|
+
readFileSync as readFileSync35,
|
|
40875
|
+
rmSync as rmSync4,
|
|
40876
|
+
writeFileSync as writeFileSync21
|
|
40877
|
+
} from "node:fs";
|
|
40878
|
+
import { dirname as dirname9, join as join35 } from "node:path";
|
|
40879
|
+
import { homedir as homedir12 } from "node:os";
|
|
40880
|
+
function ensureBuiltinSkillsLoadedSync() {
|
|
40881
|
+
if (builtinsLoaded) return;
|
|
40882
|
+
for (const spec of BUILTIN_SKILL_MODULES) {
|
|
40883
|
+
try {
|
|
40884
|
+
require?.(spec);
|
|
40885
|
+
} catch {
|
|
40886
|
+
}
|
|
40887
|
+
}
|
|
40888
|
+
}
|
|
40889
|
+
function getUserSkillsDir() {
|
|
40890
|
+
return join35(homedir12(), ".zelari-code", "skills");
|
|
40891
|
+
}
|
|
40892
|
+
function getProjectSkillsDir(projectRoot) {
|
|
40893
|
+
return join35(projectRoot, ".zelari", "skills");
|
|
40894
|
+
}
|
|
40895
|
+
function skillFilePath(dir, name) {
|
|
40896
|
+
return join35(dir, name, "SKILL.md");
|
|
40897
|
+
}
|
|
40898
|
+
function classifyScope(skillPath, projectRoot) {
|
|
40899
|
+
const userDir = getUserSkillsDir().replace(/\\/g, "/");
|
|
40900
|
+
const norm = skillPath.replace(/\\/g, "/");
|
|
40901
|
+
if (norm.startsWith(userDir + "/") || norm === userDir) {
|
|
40902
|
+
return { scope: "user", writable: true };
|
|
40903
|
+
}
|
|
40904
|
+
if (projectRoot) {
|
|
40905
|
+
const projDir = getProjectSkillsDir(projectRoot).replace(/\\/g, "/");
|
|
40906
|
+
if (norm.startsWith(projDir + "/") || norm === projDir) {
|
|
40907
|
+
return { scope: "project", writable: true };
|
|
40908
|
+
}
|
|
40909
|
+
}
|
|
40910
|
+
return { scope: "compat", writable: false };
|
|
40911
|
+
}
|
|
40912
|
+
function entryFromParsed(parsed, projectRoot) {
|
|
40913
|
+
const { scope, writable } = classifyScope(parsed.sourcePath, projectRoot);
|
|
40914
|
+
return {
|
|
40915
|
+
id: parsed.name,
|
|
40916
|
+
name: parsed.name,
|
|
40917
|
+
description: parsed.description,
|
|
40918
|
+
category: parsed.category,
|
|
40919
|
+
estimatedCost: parsed.estimatedCost,
|
|
40920
|
+
requiredTools: parsed.requiredTools,
|
|
40921
|
+
scope,
|
|
40922
|
+
path: parsed.sourcePath,
|
|
40923
|
+
body: parsed.body,
|
|
40924
|
+
builtin: false,
|
|
40925
|
+
writable
|
|
40926
|
+
};
|
|
40927
|
+
}
|
|
40928
|
+
function entryFromBuiltin(skill) {
|
|
40929
|
+
return {
|
|
40930
|
+
id: skill.id,
|
|
40931
|
+
name: skill.name || skill.id,
|
|
40932
|
+
description: skill.description || "",
|
|
40933
|
+
category: skill.category,
|
|
40934
|
+
estimatedCost: skill.estimatedCost,
|
|
40935
|
+
requiredTools: skill.requiredTools,
|
|
40936
|
+
scope: "builtin",
|
|
40937
|
+
path: null,
|
|
40938
|
+
// Expose body so Desktop skill picker can expand like `/skill <id>`.
|
|
40939
|
+
body: skill.systemPromptFragment || void 0,
|
|
40940
|
+
builtin: true,
|
|
40941
|
+
writable: false
|
|
40942
|
+
};
|
|
40943
|
+
}
|
|
40944
|
+
function scanSkillsDir(dir, projectRoot, seen, out) {
|
|
40945
|
+
if (!existsSync43(dir)) return;
|
|
40946
|
+
let entries;
|
|
40947
|
+
try {
|
|
40948
|
+
entries = readdirSync8(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
40949
|
+
} catch {
|
|
40950
|
+
return;
|
|
40951
|
+
}
|
|
40952
|
+
for (const entry of entries) {
|
|
40953
|
+
const skillPath = skillFilePath(dir, entry);
|
|
40954
|
+
if (!existsSync43(skillPath)) continue;
|
|
40955
|
+
try {
|
|
40956
|
+
const parsed = parseSkillMd(readFileSync35(skillPath, "utf8"), skillPath);
|
|
40957
|
+
if (!parsed) continue;
|
|
40958
|
+
if (seen.has(parsed.name)) continue;
|
|
40959
|
+
seen.add(parsed.name);
|
|
40960
|
+
out.push(entryFromParsed(parsed, projectRoot));
|
|
40961
|
+
} catch {
|
|
40962
|
+
}
|
|
40963
|
+
}
|
|
40964
|
+
}
|
|
40965
|
+
function listSkillsSnapshot(projectRoot) {
|
|
40966
|
+
const root = projectRoot && projectRoot.trim() ? projectRoot.trim() : null;
|
|
40967
|
+
const userSkillsDir = getUserSkillsDir();
|
|
40968
|
+
const projectSkillsDir = root ? getProjectSkillsDir(root) : null;
|
|
40969
|
+
const skills = [];
|
|
40970
|
+
const seen = /* @__PURE__ */ new Set();
|
|
40971
|
+
if (root) {
|
|
40972
|
+
scanSkillsDir(join35(root, ".zelari", "skills"), root, seen, skills);
|
|
40973
|
+
scanSkillsDir(join35(root, ".claude", "skills"), root, seen, skills);
|
|
40974
|
+
scanSkillsDir(join35(root, ".opencode", "skills"), root, seen, skills);
|
|
40975
|
+
}
|
|
40976
|
+
scanSkillsDir(userSkillsDir, root, seen, skills);
|
|
40977
|
+
for (const s of listCodingSkills()) {
|
|
40978
|
+
if (seen.has(s.id)) continue;
|
|
40979
|
+
seen.add(s.id);
|
|
40980
|
+
if (s.builtin) {
|
|
40981
|
+
skills.push(entryFromBuiltin(s));
|
|
40982
|
+
}
|
|
40983
|
+
}
|
|
40984
|
+
skills.sort((a, b) => {
|
|
40985
|
+
const order = (s) => s === "project" ? 0 : s === "user" ? 1 : s === "compat" ? 2 : 3;
|
|
40986
|
+
const d = order(a.scope) - order(b.scope);
|
|
40987
|
+
if (d !== 0) return d;
|
|
40988
|
+
return a.id.localeCompare(b.id);
|
|
40989
|
+
});
|
|
40990
|
+
return { userSkillsDir, projectSkillsDir, skills };
|
|
40991
|
+
}
|
|
40992
|
+
function serializeSkillMd(opts) {
|
|
40993
|
+
const name = opts.name.trim().toLowerCase();
|
|
40994
|
+
const description = opts.description.trim();
|
|
40995
|
+
const body = opts.body.trim();
|
|
40996
|
+
const lines = ["---", `name: ${name}`, `description: ${description}`];
|
|
40997
|
+
const cat = (opts.category ?? "").trim().toLowerCase();
|
|
40998
|
+
if (cat && CODING_CATEGORIES2.has(cat)) {
|
|
40999
|
+
lines.push(`category: ${cat}`);
|
|
41000
|
+
}
|
|
41001
|
+
if (opts.tools && opts.tools.length > 0) {
|
|
41002
|
+
lines.push(`tools: [${opts.tools.map((t) => t.trim()).filter(Boolean).join(", ")}]`);
|
|
41003
|
+
}
|
|
41004
|
+
const cost = (opts.cost ?? "").trim().toLowerCase();
|
|
41005
|
+
if (cost === "low" || cost === "medium" || cost === "high") {
|
|
41006
|
+
lines.push(`cost: ${cost}`);
|
|
41007
|
+
}
|
|
41008
|
+
lines.push("---", "", body, "");
|
|
41009
|
+
return lines.join("\n");
|
|
41010
|
+
}
|
|
41011
|
+
function upsertSkill(opts) {
|
|
41012
|
+
const name = opts.name.trim().toLowerCase();
|
|
41013
|
+
if (!name || !NAME_RE.test(name)) {
|
|
41014
|
+
return {
|
|
41015
|
+
ok: false,
|
|
41016
|
+
error: "Invalid skill name (use lowercase letters, digits, hyphens; max 64 chars)"
|
|
41017
|
+
};
|
|
41018
|
+
}
|
|
41019
|
+
const description = opts.description.trim();
|
|
41020
|
+
if (!description) {
|
|
41021
|
+
return { ok: false, error: "description is required" };
|
|
41022
|
+
}
|
|
41023
|
+
const body = opts.body.trim();
|
|
41024
|
+
if (!body) {
|
|
41025
|
+
return { ok: false, error: "body is required" };
|
|
41026
|
+
}
|
|
41027
|
+
let dir;
|
|
41028
|
+
if (opts.scope === "user") {
|
|
41029
|
+
dir = getUserSkillsDir();
|
|
41030
|
+
} else {
|
|
41031
|
+
const root = opts.projectRoot?.trim();
|
|
41032
|
+
if (!root) {
|
|
41033
|
+
return {
|
|
41034
|
+
ok: false,
|
|
41035
|
+
error: "projectRoot required for project scope (Open Folder first)"
|
|
41036
|
+
};
|
|
41037
|
+
}
|
|
41038
|
+
dir = getProjectSkillsDir(root);
|
|
41039
|
+
}
|
|
41040
|
+
const path51 = skillFilePath(dir, name);
|
|
41041
|
+
const content = serializeSkillMd({
|
|
41042
|
+
name,
|
|
41043
|
+
description,
|
|
41044
|
+
body,
|
|
41045
|
+
category: opts.category,
|
|
41046
|
+
tools: opts.tools,
|
|
41047
|
+
cost: opts.cost
|
|
41048
|
+
});
|
|
41049
|
+
const parsed = parseSkillMd(content, path51);
|
|
41050
|
+
if (!parsed) {
|
|
41051
|
+
return { ok: false, error: "Generated SKILL.md failed validation" };
|
|
41052
|
+
}
|
|
41053
|
+
mkdirSync19(dirname9(path51), { recursive: true });
|
|
41054
|
+
writeFileSync21(path51, content, "utf8");
|
|
41055
|
+
return { ok: true, path: path51 };
|
|
41056
|
+
}
|
|
41057
|
+
function removeSkill(opts) {
|
|
41058
|
+
const name = opts.name.trim().toLowerCase();
|
|
41059
|
+
if (!name) {
|
|
41060
|
+
return { ok: false, error: "name is required" };
|
|
41061
|
+
}
|
|
41062
|
+
let dir;
|
|
41063
|
+
if (opts.scope === "user") {
|
|
41064
|
+
dir = getUserSkillsDir();
|
|
41065
|
+
} else {
|
|
41066
|
+
const root = opts.projectRoot?.trim();
|
|
41067
|
+
if (!root) {
|
|
41068
|
+
return { ok: false, error: "projectRoot required for project scope" };
|
|
41069
|
+
}
|
|
41070
|
+
dir = getProjectSkillsDir(root);
|
|
41071
|
+
}
|
|
41072
|
+
const skillDir = join35(dir, name);
|
|
41073
|
+
const path51 = skillFilePath(dir, name);
|
|
41074
|
+
if (!existsSync43(path51) && !existsSync43(skillDir)) {
|
|
41075
|
+
return { ok: false, error: `Skill "${name}" not found in ${dir}` };
|
|
41076
|
+
}
|
|
41077
|
+
try {
|
|
41078
|
+
rmSync4(skillDir, { recursive: true, force: true });
|
|
41079
|
+
} catch (err) {
|
|
41080
|
+
return {
|
|
41081
|
+
ok: false,
|
|
41082
|
+
error: err instanceof Error ? err.message : String(err)
|
|
41083
|
+
};
|
|
41084
|
+
}
|
|
41085
|
+
return { ok: true, path: path51 };
|
|
41086
|
+
}
|
|
41087
|
+
var NAME_RE, BUILTIN_SKILL_MODULES, builtinsLoaded;
|
|
41088
|
+
var init_skillConfigIo = __esm({
|
|
41089
|
+
"src/cli/skillConfigIo.ts"() {
|
|
41090
|
+
"use strict";
|
|
41091
|
+
init_skills2();
|
|
41092
|
+
init_skillsMd();
|
|
41093
|
+
init_skillCategories();
|
|
41094
|
+
NAME_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
41095
|
+
BUILTIN_SKILL_MODULES = [
|
|
41096
|
+
"@zelari/core/skills/builtin/debugging",
|
|
41097
|
+
"@zelari/core/skills/builtin/docs",
|
|
41098
|
+
"@zelari/core/skills/builtin/git-ops",
|
|
41099
|
+
"@zelari/core/skills/builtin/planning",
|
|
41100
|
+
"@zelari/core/skills/builtin/refactoring",
|
|
41101
|
+
"@zelari/core/skills/builtin/review",
|
|
41102
|
+
"@zelari/core/skills/builtin/testing",
|
|
41103
|
+
"@zelari/core/skills/builtin/schema-loop",
|
|
41104
|
+
"@zelari/core/skills/builtin/computer-use-cua",
|
|
41105
|
+
"@zelari/core/skills/builtin/qwen-mm-plugins"
|
|
41106
|
+
];
|
|
41107
|
+
builtinsLoaded = false;
|
|
41108
|
+
}
|
|
41109
|
+
});
|
|
41110
|
+
|
|
40386
41111
|
// src/cli/mcp/mcpPermissionServer.ts
|
|
40387
41112
|
import { createInterface } from "node:readline";
|
|
40388
41113
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
@@ -40651,36 +41376,36 @@ var init_permissionCli = __esm({
|
|
|
40651
41376
|
|
|
40652
41377
|
// src/cli/companion/config.ts
|
|
40653
41378
|
import {
|
|
40654
|
-
existsSync as
|
|
40655
|
-
mkdirSync as
|
|
40656
|
-
readFileSync as
|
|
40657
|
-
writeFileSync as
|
|
41379
|
+
existsSync as existsSync44,
|
|
41380
|
+
mkdirSync as mkdirSync20,
|
|
41381
|
+
readFileSync as readFileSync36,
|
|
41382
|
+
writeFileSync as writeFileSync22
|
|
40658
41383
|
} from "node:fs";
|
|
40659
|
-
import { join as
|
|
40660
|
-
import { homedir as
|
|
41384
|
+
import { join as join36 } from "node:path";
|
|
41385
|
+
import { homedir as homedir13 } from "node:os";
|
|
40661
41386
|
import { createHash as createHash6, randomBytes as randomBytes4, timingSafeEqual } from "node:crypto";
|
|
40662
41387
|
function getZelariHome() {
|
|
40663
|
-
return
|
|
41388
|
+
return join36(homedir13(), ".zelari-code");
|
|
40664
41389
|
}
|
|
40665
41390
|
function getCompanionConfigPath() {
|
|
40666
|
-
return
|
|
41391
|
+
return join36(getZelariHome(), "companion.json");
|
|
40667
41392
|
}
|
|
40668
41393
|
function getCompanionTokenPath() {
|
|
40669
|
-
return
|
|
41394
|
+
return join36(getZelariHome(), "companion.token");
|
|
40670
41395
|
}
|
|
40671
41396
|
function ensureHome() {
|
|
40672
41397
|
const home = getZelariHome();
|
|
40673
|
-
if (!
|
|
40674
|
-
|
|
41398
|
+
if (!existsSync44(home)) {
|
|
41399
|
+
mkdirSync20(home, { recursive: true });
|
|
40675
41400
|
}
|
|
40676
41401
|
}
|
|
40677
41402
|
function loadCompanionConfig() {
|
|
40678
|
-
const
|
|
40679
|
-
if (!
|
|
41403
|
+
const path51 = getCompanionConfigPath();
|
|
41404
|
+
if (!existsSync44(path51)) {
|
|
40680
41405
|
return { projects: [] };
|
|
40681
41406
|
}
|
|
40682
41407
|
try {
|
|
40683
|
-
const raw = JSON.parse(
|
|
41408
|
+
const raw = JSON.parse(readFileSync36(path51, "utf8"));
|
|
40684
41409
|
const projects = Array.isArray(raw.projects) ? raw.projects.filter(
|
|
40685
41410
|
(p3) => p3 && typeof p3.path === "string" && p3.path.trim() && typeof (p3.id ?? p3.name) === "string"
|
|
40686
41411
|
).map((p3) => ({
|
|
@@ -40699,7 +41424,7 @@ function loadCompanionConfig() {
|
|
|
40699
41424
|
}
|
|
40700
41425
|
function saveCompanionConfig(cfg) {
|
|
40701
41426
|
ensureHome();
|
|
40702
|
-
|
|
41427
|
+
writeFileSync22(
|
|
40703
41428
|
getCompanionConfigPath(),
|
|
40704
41429
|
JSON.stringify(
|
|
40705
41430
|
{
|
|
@@ -40718,16 +41443,16 @@ function loadOrCreateToken(explicit) {
|
|
|
40718
41443
|
return { token: explicit.trim(), created: false };
|
|
40719
41444
|
}
|
|
40720
41445
|
ensureHome();
|
|
40721
|
-
const
|
|
40722
|
-
if (
|
|
40723
|
-
const t =
|
|
41446
|
+
const path51 = getCompanionTokenPath();
|
|
41447
|
+
if (existsSync44(path51)) {
|
|
41448
|
+
const t = readFileSync36(path51, "utf8").trim();
|
|
40724
41449
|
if (t) return { token: t, created: false };
|
|
40725
41450
|
}
|
|
40726
41451
|
const token = randomBytes4(24).toString("base64url");
|
|
40727
|
-
|
|
41452
|
+
writeFileSync22(path51, token + "\n", "utf8");
|
|
40728
41453
|
try {
|
|
40729
41454
|
const fs30 = __require("node:fs");
|
|
40730
|
-
fs30.chmodSync?.(
|
|
41455
|
+
fs30.chmodSync?.(path51, 384);
|
|
40731
41456
|
} catch {
|
|
40732
41457
|
}
|
|
40733
41458
|
return { token, created: true };
|
|
@@ -40752,17 +41477,17 @@ function mergeProjects(cfg, extraPaths) {
|
|
|
40752
41477
|
byId.set(p3.id, p3);
|
|
40753
41478
|
}
|
|
40754
41479
|
for (const raw of extraPaths) {
|
|
40755
|
-
const
|
|
40756
|
-
if (!
|
|
40757
|
-
let id = slugFromPath(
|
|
41480
|
+
const path51 = raw.trim();
|
|
41481
|
+
if (!path51) continue;
|
|
41482
|
+
let id = slugFromPath(path51);
|
|
40758
41483
|
let n = 2;
|
|
40759
|
-
while (byId.has(id) && byId.get(id).path !==
|
|
40760
|
-
id = `${slugFromPath(
|
|
41484
|
+
while (byId.has(id) && byId.get(id).path !== path51) {
|
|
41485
|
+
id = `${slugFromPath(path51)}-${n++}`;
|
|
40761
41486
|
}
|
|
40762
41487
|
byId.set(id, {
|
|
40763
41488
|
id,
|
|
40764
|
-
name: slugFromPath(
|
|
40765
|
-
path:
|
|
41489
|
+
name: slugFromPath(path51),
|
|
41490
|
+
path: path51
|
|
40766
41491
|
});
|
|
40767
41492
|
}
|
|
40768
41493
|
return [...byId.values()];
|
|
@@ -40810,11 +41535,11 @@ var init_config = __esm({
|
|
|
40810
41535
|
});
|
|
40811
41536
|
|
|
40812
41537
|
// src/cli/companion/runManager.ts
|
|
40813
|
-
import { spawn as
|
|
41538
|
+
import { spawn as spawn13 } from "node:child_process";
|
|
40814
41539
|
import { createInterface as createInterface2 } from "node:readline";
|
|
40815
41540
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
40816
|
-
import { writeFileSync as
|
|
40817
|
-
import { join as
|
|
41541
|
+
import { writeFileSync as writeFileSync23, unlinkSync as unlinkSync2 } from "node:fs";
|
|
41542
|
+
import { join as join37 } from "node:path";
|
|
40818
41543
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
40819
41544
|
var RunManager;
|
|
40820
41545
|
var init_runManager = __esm({
|
|
@@ -40918,15 +41643,15 @@ var init_runManager = __esm({
|
|
|
40918
41643
|
}
|
|
40919
41644
|
let historyFile;
|
|
40920
41645
|
if (args.history && Array.isArray(args.history) && args.history.length > 0) {
|
|
40921
|
-
historyFile =
|
|
41646
|
+
historyFile = join37(tmpdir3(), `zelari-companion-hist-${id}.json`);
|
|
40922
41647
|
try {
|
|
40923
|
-
|
|
41648
|
+
writeFileSync23(historyFile, JSON.stringify(args.history), "utf8");
|
|
40924
41649
|
argv.push("--history-file", historyFile);
|
|
40925
41650
|
} catch {
|
|
40926
41651
|
historyFile = void 0;
|
|
40927
41652
|
}
|
|
40928
41653
|
}
|
|
40929
|
-
const child =
|
|
41654
|
+
const child = spawn13(process.execPath, argv, {
|
|
40930
41655
|
cwd: args.cwd,
|
|
40931
41656
|
env: {
|
|
40932
41657
|
...process.env,
|
|
@@ -41045,7 +41770,7 @@ __export(serve_exports, {
|
|
|
41045
41770
|
runCompanionServe: () => runCompanionServe
|
|
41046
41771
|
});
|
|
41047
41772
|
import { createServer as createServer2 } from "node:http";
|
|
41048
|
-
import { existsSync as
|
|
41773
|
+
import { existsSync as existsSync45 } from "node:fs";
|
|
41049
41774
|
import { resolve as resolve2 } from "node:path";
|
|
41050
41775
|
function readBody(req, max = 2e6) {
|
|
41051
41776
|
return new Promise((resolveBody, reject) => {
|
|
@@ -41093,7 +41818,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
41093
41818
|
let projects = mergeProjects(fileCfg, opts.projects ?? []);
|
|
41094
41819
|
projects = projects.filter((p3) => {
|
|
41095
41820
|
const abs = resolve2(p3.path);
|
|
41096
|
-
if (!
|
|
41821
|
+
if (!existsSync45(abs)) {
|
|
41097
41822
|
process.stderr.write(
|
|
41098
41823
|
`[zelari-code serve] skip missing project path: ${p3.path}
|
|
41099
41824
|
`
|
|
@@ -41139,9 +41864,9 @@ async function runCompanionServe(opts = {}) {
|
|
|
41139
41864
|
return;
|
|
41140
41865
|
}
|
|
41141
41866
|
const url2 = parseUrl(req);
|
|
41142
|
-
const
|
|
41867
|
+
const path51 = url2.pathname.replace(/\/+$/, "") || "/";
|
|
41143
41868
|
try {
|
|
41144
|
-
if (req.method === "GET" && (
|
|
41869
|
+
if (req.method === "GET" && (path51 === "/health" || path51 === "/v1/health")) {
|
|
41145
41870
|
sendJson2(res, 200, {
|
|
41146
41871
|
ok: true,
|
|
41147
41872
|
service: "zelari-companion",
|
|
@@ -41153,18 +41878,18 @@ async function runCompanionServe(opts = {}) {
|
|
|
41153
41878
|
});
|
|
41154
41879
|
return;
|
|
41155
41880
|
}
|
|
41156
|
-
if (
|
|
41881
|
+
if (path51.startsWith("/v1")) {
|
|
41157
41882
|
if (!tokenMatches(token, getBearer(req))) {
|
|
41158
41883
|
sendJson2(res, 401, { ok: false, error: "unauthorized" });
|
|
41159
41884
|
return;
|
|
41160
41885
|
}
|
|
41161
41886
|
}
|
|
41162
|
-
if (req.method === "GET" &&
|
|
41887
|
+
if (req.method === "GET" && path51 === "/v1/config") {
|
|
41163
41888
|
const snap = buildDesktopConfigSnapshot();
|
|
41164
41889
|
sendJson2(res, 200, { ok: true, ...snap });
|
|
41165
41890
|
return;
|
|
41166
41891
|
}
|
|
41167
|
-
if (req.method === "GET" &&
|
|
41892
|
+
if (req.method === "GET" && path51 === "/v1/projects") {
|
|
41168
41893
|
sendJson2(res, 200, {
|
|
41169
41894
|
ok: true,
|
|
41170
41895
|
projects: projects.map((p3) => ({
|
|
@@ -41175,7 +41900,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
41175
41900
|
});
|
|
41176
41901
|
return;
|
|
41177
41902
|
}
|
|
41178
|
-
if (req.method === "GET" &&
|
|
41903
|
+
if (req.method === "GET" && path51 === "/v1/runs") {
|
|
41179
41904
|
sendJson2(res, 200, {
|
|
41180
41905
|
ok: true,
|
|
41181
41906
|
active: runs.getActive(),
|
|
@@ -41193,7 +41918,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
41193
41918
|
});
|
|
41194
41919
|
return;
|
|
41195
41920
|
}
|
|
41196
|
-
if (req.method === "POST" &&
|
|
41921
|
+
if (req.method === "POST" && path51 === "/v1/runs") {
|
|
41197
41922
|
const raw = await readBody(req);
|
|
41198
41923
|
let body = {};
|
|
41199
41924
|
try {
|
|
@@ -41240,7 +41965,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
41240
41965
|
});
|
|
41241
41966
|
return;
|
|
41242
41967
|
}
|
|
41243
|
-
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(
|
|
41968
|
+
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path51);
|
|
41244
41969
|
if (req.method === "GET" && eventsMatch) {
|
|
41245
41970
|
const runId = eventsMatch[1];
|
|
41246
41971
|
const run = runs.getRun(runId);
|
|
@@ -41305,7 +42030,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
41305
42030
|
}, 500);
|
|
41306
42031
|
return;
|
|
41307
42032
|
}
|
|
41308
|
-
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(
|
|
42033
|
+
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path51);
|
|
41309
42034
|
if (req.method === "POST" && cancelMatch) {
|
|
41310
42035
|
const runId = cancelMatch[1];
|
|
41311
42036
|
const result = runs.cancel(runId);
|
|
@@ -41414,26 +42139,26 @@ __export(doctor_exports, {
|
|
|
41414
42139
|
runDoctor: () => runDoctor
|
|
41415
42140
|
});
|
|
41416
42141
|
import { execSync as execSync2 } from "node:child_process";
|
|
41417
|
-
import { existsSync as
|
|
42142
|
+
import { existsSync as existsSync46, readFileSync as readFileSync37, readlinkSync, statSync as statSync7 } from "node:fs";
|
|
41418
42143
|
import { createRequire as createRequire3 } from "node:module";
|
|
41419
42144
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
41420
|
-
import
|
|
42145
|
+
import path49 from "node:path";
|
|
41421
42146
|
function findPackageRoot(start) {
|
|
41422
42147
|
let dir = start;
|
|
41423
42148
|
for (let i = 0; i < 6; i += 1) {
|
|
41424
|
-
const candidate =
|
|
41425
|
-
if (
|
|
42149
|
+
const candidate = path49.join(dir, "package.json");
|
|
42150
|
+
if (existsSync46(candidate)) {
|
|
41426
42151
|
try {
|
|
41427
|
-
const pkg = JSON.parse(
|
|
42152
|
+
const pkg = JSON.parse(readFileSync37(candidate, "utf8"));
|
|
41428
42153
|
if (pkg.name === "zelari-code") return dir;
|
|
41429
42154
|
} catch {
|
|
41430
42155
|
}
|
|
41431
42156
|
}
|
|
41432
|
-
const parent =
|
|
42157
|
+
const parent = path49.dirname(dir);
|
|
41433
42158
|
if (parent === dir) break;
|
|
41434
42159
|
dir = parent;
|
|
41435
42160
|
}
|
|
41436
|
-
return
|
|
42161
|
+
return path49.resolve(__dirname3, "..", "..", "..");
|
|
41437
42162
|
}
|
|
41438
42163
|
function tryExec(cmd) {
|
|
41439
42164
|
try {
|
|
@@ -41447,8 +42172,8 @@ function tryExec(cmd) {
|
|
|
41447
42172
|
}
|
|
41448
42173
|
function readPackageJson3() {
|
|
41449
42174
|
try {
|
|
41450
|
-
const pkgPath =
|
|
41451
|
-
return JSON.parse(
|
|
42175
|
+
const pkgPath = path49.join(packageRoot, "package.json");
|
|
42176
|
+
return JSON.parse(readFileSync37(pkgPath, "utf8"));
|
|
41452
42177
|
} catch {
|
|
41453
42178
|
return null;
|
|
41454
42179
|
}
|
|
@@ -41463,8 +42188,8 @@ function checkShim(pkgName) {
|
|
|
41463
42188
|
}
|
|
41464
42189
|
const isWin = process.platform === "win32";
|
|
41465
42190
|
const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
|
|
41466
|
-
const shimPath =
|
|
41467
|
-
if (!
|
|
42191
|
+
const shimPath = path49.join(prefix, shimName);
|
|
42192
|
+
if (!existsSync46(shimPath)) {
|
|
41468
42193
|
return FAIL(
|
|
41469
42194
|
`shim not found at ${shimPath}
|
|
41470
42195
|
fix: npm install -g ${pkgName}@latest --force`
|
|
@@ -41473,7 +42198,7 @@ function checkShim(pkgName) {
|
|
|
41473
42198
|
try {
|
|
41474
42199
|
const st = statSync7(shimPath);
|
|
41475
42200
|
if (isWin) {
|
|
41476
|
-
const content =
|
|
42201
|
+
const content = readFileSync37(shimPath, "utf8");
|
|
41477
42202
|
if (content.includes(`${pkgName}\\bin\\`) || content.includes(`${pkgName}/bin/`)) {
|
|
41478
42203
|
return OK(`shim OK at ${shimPath} (${st.size} bytes)`);
|
|
41479
42204
|
}
|
|
@@ -41491,8 +42216,8 @@ function checkShim(pkgName) {
|
|
|
41491
42216
|
fix: npm install -g ${pkgName}@latest --force`
|
|
41492
42217
|
);
|
|
41493
42218
|
}
|
|
41494
|
-
const resolved =
|
|
41495
|
-
const expected =
|
|
42219
|
+
const resolved = path49.resolve(path49.dirname(shimPath), target);
|
|
42220
|
+
const expected = path49.join(
|
|
41496
42221
|
prefix,
|
|
41497
42222
|
"node_modules",
|
|
41498
42223
|
pkgName,
|
|
@@ -41531,8 +42256,8 @@ function checkNode(pkg) {
|
|
|
41531
42256
|
return OK(`node ${raw}`);
|
|
41532
42257
|
}
|
|
41533
42258
|
function checkBundle() {
|
|
41534
|
-
const bundle =
|
|
41535
|
-
if (!
|
|
42259
|
+
const bundle = path49.join(packageRoot, "dist", "cli", "main.bundled.js");
|
|
42260
|
+
if (!existsSync46(bundle)) {
|
|
41536
42261
|
return FAIL(
|
|
41537
42262
|
`dist/cli/main.bundled.js missing at ${bundle}
|
|
41538
42263
|
fix: npm run build:cli (then reinstall or run via tsx)`
|
|
@@ -41552,7 +42277,7 @@ function checkRuntimeDeps() {
|
|
|
41552
42277
|
const missing = [];
|
|
41553
42278
|
for (const dep of required2) {
|
|
41554
42279
|
try {
|
|
41555
|
-
const localReq = createRequire3(
|
|
42280
|
+
const localReq = createRequire3(path49.join(packageRoot, "package.json"));
|
|
41556
42281
|
localReq.resolve(dep);
|
|
41557
42282
|
} catch {
|
|
41558
42283
|
missing.push(dep);
|
|
@@ -41728,7 +42453,7 @@ var init_doctor = __esm({
|
|
|
41728
42453
|
"use strict";
|
|
41729
42454
|
init_prereqChecks();
|
|
41730
42455
|
require3 = createRequire3(import.meta.url);
|
|
41731
|
-
__dirname3 =
|
|
42456
|
+
__dirname3 = path49.dirname(fileURLToPath2(import.meta.url));
|
|
41732
42457
|
packageRoot = findPackageRoot(__dirname3);
|
|
41733
42458
|
OK = (message) => ({
|
|
41734
42459
|
ok: true,
|
|
@@ -41906,6 +42631,154 @@ var init_fixBudget = __esm({
|
|
|
41906
42631
|
}
|
|
41907
42632
|
});
|
|
41908
42633
|
|
|
42634
|
+
// src/cli/commands/inspect.ts
|
|
42635
|
+
var inspect_exports = {};
|
|
42636
|
+
__export(inspect_exports, {
|
|
42637
|
+
collectInspectReport: () => collectInspectReport,
|
|
42638
|
+
runInspect: () => runInspect
|
|
42639
|
+
});
|
|
42640
|
+
import path50 from "node:path";
|
|
42641
|
+
import { existsSync as existsSync47, readFileSync as readFileSync38, readdirSync as readdirSync9 } from "node:fs";
|
|
42642
|
+
import { homedir as homedir14 } from "node:os";
|
|
42643
|
+
async function collectInspectReport(cwd = process.cwd()) {
|
|
42644
|
+
ensureBuiltinSkillsLoadedSync();
|
|
42645
|
+
const snap = listSkillsSnapshot(cwd);
|
|
42646
|
+
const mcp = listMcpServers(cwd);
|
|
42647
|
+
const userMcpPath = path50.join(homedir14(), ".zelari-code", "mcp.json");
|
|
42648
|
+
const projectMcpPath = path50.join(cwd, ".zelari", "mcp.json");
|
|
42649
|
+
const globalHooks = globalHooksDir();
|
|
42650
|
+
const projectHooks = projectHooksDir(cwd);
|
|
42651
|
+
const projectTrusted = isFolderTrusted(cwd);
|
|
42652
|
+
const skillsByScope = (scope) => snap.skills.filter((s) => s.scope === scope).length;
|
|
42653
|
+
const pluginStates = await Promise.all(
|
|
42654
|
+
PLUGINS.map(async (p3) => ({
|
|
42655
|
+
id: p3.id,
|
|
42656
|
+
label: p3.label ?? p3.id,
|
|
42657
|
+
installed: await p3.detect(cwd)
|
|
42658
|
+
}))
|
|
42659
|
+
);
|
|
42660
|
+
return {
|
|
42661
|
+
schemaVersion: 1,
|
|
42662
|
+
zelariVersion: getCurrentVersion(),
|
|
42663
|
+
cwd,
|
|
42664
|
+
platform: `${process.platform}-${process.arch}`,
|
|
42665
|
+
node: process.version,
|
|
42666
|
+
phase: process.env.ZELARI_PHASE ?? "build",
|
|
42667
|
+
mode: process.env.ZELARI_MODE ?? "kraken",
|
|
42668
|
+
trust: {
|
|
42669
|
+
store: getTrustStorePath(),
|
|
42670
|
+
trusted: projectTrusted,
|
|
42671
|
+
folders: listTrustedFolders()
|
|
42672
|
+
},
|
|
42673
|
+
configSources: [
|
|
42674
|
+
{ path: userMcpPath, exists: existsSync47(userMcpPath) },
|
|
42675
|
+
{ path: projectMcpPath, exists: existsSync47(projectMcpPath) },
|
|
42676
|
+
{ path: path50.join(homedir14(), ".zelari-code", "provider.json"), exists: existsSync47(path50.join(homedir14(), ".zelari-code", "provider.json")) },
|
|
42677
|
+
{ path: path50.join(cwd, ".zelari", "AGENTS.md"), exists: existsSync47(path50.join(cwd, ".zelari", "AGENTS.md")) },
|
|
42678
|
+
{ path: path50.join(cwd, "AGENTS.md"), exists: existsSync47(path50.join(cwd, "AGENTS.md")) }
|
|
42679
|
+
],
|
|
42680
|
+
skills: {
|
|
42681
|
+
total: snap.skills.length,
|
|
42682
|
+
builtin: skillsByScope("builtin"),
|
|
42683
|
+
user: skillsByScope("user"),
|
|
42684
|
+
project: skillsByScope("project"),
|
|
42685
|
+
compat: skillsByScope("compat")
|
|
42686
|
+
},
|
|
42687
|
+
mcp: {
|
|
42688
|
+
user: mcp.servers.filter((s) => s.scope === "user").map((s) => ({ name: s.name, enabled: s.enabled !== false })),
|
|
42689
|
+
project: mcp.servers.filter((s) => s.scope === "project").map((s) => ({ name: s.name, enabled: s.enabled !== false })),
|
|
42690
|
+
projectTrusted,
|
|
42691
|
+
projectConfigExists: existsSync47(projectMcpPath)
|
|
42692
|
+
},
|
|
42693
|
+
hooks: {
|
|
42694
|
+
global: {
|
|
42695
|
+
path: globalHooks,
|
|
42696
|
+
active: true,
|
|
42697
|
+
files: listJsonFiles(globalHooks)
|
|
42698
|
+
},
|
|
42699
|
+
project: {
|
|
42700
|
+
path: projectHooks,
|
|
42701
|
+
active: projectTrusted,
|
|
42702
|
+
files: listJsonFiles(projectHooks)
|
|
42703
|
+
}
|
|
42704
|
+
},
|
|
42705
|
+
plugins: pluginStates,
|
|
42706
|
+
agentsMd: findAgentsMd(cwd)
|
|
42707
|
+
};
|
|
42708
|
+
}
|
|
42709
|
+
function listJsonFiles(dir) {
|
|
42710
|
+
try {
|
|
42711
|
+
return readdirSync9(dir).filter((f) => f.endsWith(".json")).sort();
|
|
42712
|
+
} catch {
|
|
42713
|
+
return [];
|
|
42714
|
+
}
|
|
42715
|
+
}
|
|
42716
|
+
function findAgentsMd(cwd) {
|
|
42717
|
+
const candidates = [
|
|
42718
|
+
path50.join(cwd, "AGENTS.md"),
|
|
42719
|
+
path50.join(cwd, ".zelari", "AGENTS.md")
|
|
42720
|
+
];
|
|
42721
|
+
const found = [];
|
|
42722
|
+
for (const c of candidates) {
|
|
42723
|
+
if (existsSync47(c)) {
|
|
42724
|
+
try {
|
|
42725
|
+
const text = readFileSync38(c, "utf8");
|
|
42726
|
+
found.push(`${c} (${text.length} bytes)`);
|
|
42727
|
+
} catch {
|
|
42728
|
+
found.push(`${c} (unreadable)`);
|
|
42729
|
+
}
|
|
42730
|
+
}
|
|
42731
|
+
}
|
|
42732
|
+
return found;
|
|
42733
|
+
}
|
|
42734
|
+
function formatHuman(r) {
|
|
42735
|
+
const lines = [
|
|
42736
|
+
`zelari-code inspect v${r.zelariVersion}`,
|
|
42737
|
+
` cwd: ${r.cwd}`,
|
|
42738
|
+
` platform: ${r.platform} node ${r.node}`,
|
|
42739
|
+
` phase: ${r.phase} mode: ${r.mode}`,
|
|
42740
|
+
``,
|
|
42741
|
+
`trust: ${r.trust.trusted ? "TRUSTED \u2714" : "NOT TRUSTED \u2716"} (store: ${r.trust.store})`,
|
|
42742
|
+
...r.trust.folders.map((f) => ` - ${f.path} (${f.trustedAt})`),
|
|
42743
|
+
``,
|
|
42744
|
+
`skills: ${r.skills.total} total (builtin ${r.skills.builtin}, user ${r.skills.user}, project ${r.skills.project}, compat ${r.skills.compat})`,
|
|
42745
|
+
``,
|
|
42746
|
+
`MCP:`,
|
|
42747
|
+
` user: ${r.mcp.user.length ? r.mcp.user.map((m) => m.name).join(", ") : "(none)"}`,
|
|
42748
|
+
` project: ${r.mcp.projectConfigExists ? r.mcp.projectTrusted ? r.mcp.project.map((m) => m.name).join(", ") || "(configured, no servers)" : "IGNORED (folder not trusted)" : "(no .zelari/mcp.json)"}`,
|
|
42749
|
+
``,
|
|
42750
|
+
`hooks:`,
|
|
42751
|
+
` global: ${r.hooks.global.active ? "active" : "inactive"} @ ${r.hooks.global.path} (${r.hooks.global.files.length} file(s))`,
|
|
42752
|
+
` project: ${r.hooks.project.active ? "active" : "IGNORED (folder not trusted)"} @ ${r.hooks.project.path} (${r.hooks.project.files.length} file(s))`,
|
|
42753
|
+
``,
|
|
42754
|
+
`plugins: ${r.plugins.length ? r.plugins.map((p3) => `${p3.id}${p3.installed ? "" : " (missing)"}`).join(", ") : "(none)"}`,
|
|
42755
|
+
``,
|
|
42756
|
+
`AGENTS.md rules:`,
|
|
42757
|
+
...r.agentsMd.length ? r.agentsMd.map((a) => ` - ${a}`) : [" (none)"]
|
|
42758
|
+
];
|
|
42759
|
+
return lines.join("\n");
|
|
42760
|
+
}
|
|
42761
|
+
async function runInspect(opts = {}) {
|
|
42762
|
+
const report = await collectInspectReport(opts.cwd ?? process.cwd());
|
|
42763
|
+
if (opts.json) {
|
|
42764
|
+
console.log(JSON.stringify(report, null, 2));
|
|
42765
|
+
} else {
|
|
42766
|
+
console.log(formatHuman(report));
|
|
42767
|
+
}
|
|
42768
|
+
return 0;
|
|
42769
|
+
}
|
|
42770
|
+
var init_inspect = __esm({
|
|
42771
|
+
"src/cli/commands/inspect.ts"() {
|
|
42772
|
+
"use strict";
|
|
42773
|
+
init_folderTrust();
|
|
42774
|
+
init_lifecycleHooks();
|
|
42775
|
+
init_mcpConfigIo();
|
|
42776
|
+
init_skillConfigIo();
|
|
42777
|
+
init_registry3();
|
|
42778
|
+
init_updater();
|
|
42779
|
+
}
|
|
42780
|
+
});
|
|
42781
|
+
|
|
41909
42782
|
// src/cli/main.ts
|
|
41910
42783
|
import React15 from "react";
|
|
41911
42784
|
import { render } from "ink";
|
|
@@ -44770,15 +45643,15 @@ import { useState as useState5, useRef as useRef3, useCallback, useEffect as use
|
|
|
44770
45643
|
|
|
44771
45644
|
// src/cli/sessionManager.ts
|
|
44772
45645
|
init_harness();
|
|
44773
|
-
import { promises as fs9, existsSync as existsSync9, readFileSync as
|
|
44774
|
-
import
|
|
45646
|
+
import { promises as fs9, existsSync as existsSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync4, unlinkSync, statSync } from "node:fs";
|
|
45647
|
+
import path13 from "node:path";
|
|
44775
45648
|
import os4 from "node:os";
|
|
44776
45649
|
import { randomUUID } from "node:crypto";
|
|
44777
45650
|
function getSessionBaseDir() {
|
|
44778
|
-
return process.env.ANATHEMA_SESSIONS_DIR ??
|
|
45651
|
+
return process.env.ANATHEMA_SESSIONS_DIR ?? path13.join(os4.homedir(), ".tmp", "zelari-code", "sessions");
|
|
44779
45652
|
}
|
|
44780
45653
|
function getCurrentSessionFile() {
|
|
44781
|
-
return process.env.ANATHEMA_CURRENT_SESSION_FILE ??
|
|
45654
|
+
return process.env.ANATHEMA_CURRENT_SESSION_FILE ?? path13.join(os4.homedir(), ".tmp", "zelari-code", "current.txt");
|
|
44782
45655
|
}
|
|
44783
45656
|
async function ensureSessionDir() {
|
|
44784
45657
|
await fs9.mkdir(getSessionBaseDir(), { recursive: true });
|
|
@@ -44787,7 +45660,7 @@ function getCurrentSessionId() {
|
|
|
44787
45660
|
const file2 = getCurrentSessionFile();
|
|
44788
45661
|
if (!existsSync9(file2)) return null;
|
|
44789
45662
|
try {
|
|
44790
|
-
const content =
|
|
45663
|
+
const content = readFileSync12(file2, "utf-8").trim();
|
|
44791
45664
|
return content.length > 0 ? content : null;
|
|
44792
45665
|
} catch {
|
|
44793
45666
|
return null;
|
|
@@ -44795,7 +45668,7 @@ function getCurrentSessionId() {
|
|
|
44795
45668
|
}
|
|
44796
45669
|
function setCurrentSessionId(id) {
|
|
44797
45670
|
const file2 = getCurrentSessionFile();
|
|
44798
|
-
mkdirSync4(
|
|
45671
|
+
mkdirSync4(path13.dirname(file2), { recursive: true });
|
|
44799
45672
|
writeFileSync9(file2, id, "utf-8");
|
|
44800
45673
|
}
|
|
44801
45674
|
function clearCurrentSessionId() {
|
|
@@ -44807,13 +45680,13 @@ function clearCurrentSessionId() {
|
|
|
44807
45680
|
}
|
|
44808
45681
|
}
|
|
44809
45682
|
function getCurrentBranchFile() {
|
|
44810
|
-
return process.env.ANATHEMA_CURRENT_BRANCH_FILE ??
|
|
45683
|
+
return process.env.ANATHEMA_CURRENT_BRANCH_FILE ?? path13.join(path13.dirname(getCurrentSessionFile()), "currentBranch.txt");
|
|
44811
45684
|
}
|
|
44812
45685
|
function getCurrentBranch() {
|
|
44813
45686
|
const file2 = getCurrentBranchFile();
|
|
44814
45687
|
if (!existsSync9(file2)) return null;
|
|
44815
45688
|
try {
|
|
44816
|
-
const content =
|
|
45689
|
+
const content = readFileSync12(file2, "utf-8").trim();
|
|
44817
45690
|
return content.length > 0 ? content : null;
|
|
44818
45691
|
} catch {
|
|
44819
45692
|
return null;
|
|
@@ -44821,7 +45694,7 @@ function getCurrentBranch() {
|
|
|
44821
45694
|
}
|
|
44822
45695
|
function setCurrentBranch(name) {
|
|
44823
45696
|
const file2 = getCurrentBranchFile();
|
|
44824
|
-
mkdirSync4(
|
|
45697
|
+
mkdirSync4(path13.dirname(file2), { recursive: true });
|
|
44825
45698
|
writeFileSync9(file2, name, "utf-8");
|
|
44826
45699
|
}
|
|
44827
45700
|
function newSessionId() {
|
|
@@ -44840,7 +45713,7 @@ async function listSessions() {
|
|
|
44840
45713
|
for (const entry of entries) {
|
|
44841
45714
|
if (!entry.endsWith(".jsonl")) continue;
|
|
44842
45715
|
const id = entry.replace(/\.jsonl$/, "");
|
|
44843
|
-
const filePath =
|
|
45716
|
+
const filePath = path13.join(baseDir, entry);
|
|
44844
45717
|
try {
|
|
44845
45718
|
const events = await readSession(filePath);
|
|
44846
45719
|
let firstTs = 0;
|
|
@@ -44887,7 +45760,7 @@ ${lines.join("\n")}`
|
|
|
44887
45760
|
return { message: `[${kind}] handled` };
|
|
44888
45761
|
}
|
|
44889
45762
|
async function loadSessionEvents(id) {
|
|
44890
|
-
const filePath =
|
|
45763
|
+
const filePath = path13.join(getSessionBaseDir(), `${id}.jsonl`);
|
|
44891
45764
|
return readSession(filePath);
|
|
44892
45765
|
}
|
|
44893
45766
|
|
|
@@ -45179,15 +46052,15 @@ import { useState as useState6, useRef as useRef4, useCallback as useCallback2 }
|
|
|
45179
46052
|
|
|
45180
46053
|
// src/cli/metrics.ts
|
|
45181
46054
|
import { promises as fs10, existsSync as existsSync10, statSync as statSync2, renameSync, appendFileSync as appendFileSync2, mkdirSync as mkdirSync5 } from "node:fs";
|
|
45182
|
-
import
|
|
46055
|
+
import path14 from "node:path";
|
|
45183
46056
|
import os5 from "node:os";
|
|
45184
46057
|
var METRICS_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
45185
46058
|
var MetricsLogger = class {
|
|
45186
46059
|
file;
|
|
45187
46060
|
writeQueue = Promise.resolve();
|
|
45188
46061
|
constructor(file2) {
|
|
45189
|
-
this.file = file2 ?? process.env.ANATHEMA_METRICS_FILE ??
|
|
45190
|
-
mkdirSync5(
|
|
46062
|
+
this.file = file2 ?? process.env.ANATHEMA_METRICS_FILE ?? path14.join(os5.homedir(), ".tmp", "zelari-code", "metrics.jsonl");
|
|
46063
|
+
mkdirSync5(path14.dirname(this.file), { recursive: true });
|
|
45191
46064
|
}
|
|
45192
46065
|
/** Fire-and-forget record append. */
|
|
45193
46066
|
record(rec) {
|
|
@@ -47318,6 +48191,8 @@ function handleSlashCommand(text, availableSkills) {
|
|
|
47318
48191
|
/index [status] \u2014 build the semantic code index for semantic_search
|
|
47319
48192
|
/mode [kraken|council|zelari] \u2014 switch dispatch mode (same as shift+tab; agent=alias kraken)
|
|
47320
48193
|
/kraken [sessionId] \u2014 show Kraken tentacle radio (last spawns)
|
|
48194
|
+
/trust [path] \u2014 trust a folder so project MCP + project hooks load
|
|
48195
|
+
/trust remove [path] \u2014 revoke folder trust
|
|
47321
48196
|
/help \u2014 show this help
|
|
47322
48197
|
/exit \u2014 exit the CLI
|
|
47323
48198
|
|
|
@@ -47806,6 +48681,23 @@ ${formatSkillList(availableSkills)}`
|
|
|
47806
48681
|
message: "Usage: /state status | /state commit [label] | /state show [id] | /state restore [id] [--no-tree]\nDurable verified accumulation under .zelari/state/ (not memory RAG)."
|
|
47807
48682
|
};
|
|
47808
48683
|
}
|
|
48684
|
+
case "trust": {
|
|
48685
|
+
const first = args[0];
|
|
48686
|
+
if (first === "remove" || first === "untrust") {
|
|
48687
|
+
return {
|
|
48688
|
+
handled: true,
|
|
48689
|
+
kind: "trust_remove",
|
|
48690
|
+
trustPath: args[1],
|
|
48691
|
+
message: "Usage: /trust remove [path]"
|
|
48692
|
+
};
|
|
48693
|
+
}
|
|
48694
|
+
return {
|
|
48695
|
+
handled: true,
|
|
48696
|
+
kind: first ? "trust_add" : "trust_status",
|
|
48697
|
+
trustPath: first && first !== "." ? first : process.cwd(),
|
|
48698
|
+
message: first ? "Usage: /trust [path]" : "Usage: /trust [path] | /trust remove [path]"
|
|
48699
|
+
};
|
|
48700
|
+
}
|
|
47809
48701
|
case "cache": {
|
|
47810
48702
|
const sub = (args[0] ?? "stats").toLowerCase();
|
|
47811
48703
|
if (sub === "stats" || sub === "") {
|
|
@@ -47893,7 +48785,7 @@ ${formatSkillList(availableSkills)}`
|
|
|
47893
48785
|
// src/cli/gitOps.ts
|
|
47894
48786
|
import { execFile as execFile4 } from "node:child_process";
|
|
47895
48787
|
import { promisify as promisify3 } from "node:util";
|
|
47896
|
-
import
|
|
48788
|
+
import path35 from "node:path";
|
|
47897
48789
|
var execFileAsync3 = promisify3(execFile4);
|
|
47898
48790
|
async function git3(cwd, args) {
|
|
47899
48791
|
try {
|
|
@@ -47939,7 +48831,7 @@ async function undoWorkingChanges(opts = {}) {
|
|
|
47939
48831
|
};
|
|
47940
48832
|
}
|
|
47941
48833
|
function defaultProjectRoot() {
|
|
47942
|
-
return
|
|
48834
|
+
return path35.resolve(__dirname, "..", "..", "..");
|
|
47943
48835
|
}
|
|
47944
48836
|
|
|
47945
48837
|
// src/cli/slashHandlers/git.ts
|
|
@@ -48216,6 +49108,45 @@ function handleCacheStats(ctx) {
|
|
|
48216
49108
|
);
|
|
48217
49109
|
}
|
|
48218
49110
|
|
|
49111
|
+
// src/cli/slashHandlers/trust.ts
|
|
49112
|
+
init_folderTrust();
|
|
49113
|
+
function resolvePath(raw) {
|
|
49114
|
+
if (!raw || raw === "." || raw === "./") return process.cwd();
|
|
49115
|
+
return raw;
|
|
49116
|
+
}
|
|
49117
|
+
function handleTrustStatus(ctx, target) {
|
|
49118
|
+
const trusted = isFolderTrusted(target);
|
|
49119
|
+
const all = listTrustedFolders();
|
|
49120
|
+
const lines = [
|
|
49121
|
+
`[trust] ${target}`,
|
|
49122
|
+
` status: ${trusted ? "trusted \u2714" : "NOT trusted \u2716"}`,
|
|
49123
|
+
` store: ${getTrustStorePath()}`,
|
|
49124
|
+
` folders: ${all.length === 0 ? "(none)" : ""}`,
|
|
49125
|
+
...all.map((f) => ` - ${f.path} (${f.trustedAt})`),
|
|
49126
|
+
"",
|
|
49127
|
+
trusted ? " Project MCP + project hooks are enabled for this folder." : " Project MCP (.zelari/mcp.json) and project hooks (.zelari/hooks/) are IGNORED until you run /trust ."
|
|
49128
|
+
];
|
|
49129
|
+
appendSystem(ctx.setMessages, lines.join("\n"));
|
|
49130
|
+
}
|
|
49131
|
+
function handleTrust(ctx, rawPath) {
|
|
49132
|
+
const target = resolvePath(rawPath);
|
|
49133
|
+
const res = trustFolder(target);
|
|
49134
|
+
appendSystem(
|
|
49135
|
+
ctx.setMessages,
|
|
49136
|
+
`[trust] trusted ${res.path}
|
|
49137
|
+
Project MCP + project hooks will load on the next session/turn (run /trust to confirm).`
|
|
49138
|
+
);
|
|
49139
|
+
}
|
|
49140
|
+
function handleUntrust(ctx, rawPath) {
|
|
49141
|
+
const target = resolvePath(rawPath);
|
|
49142
|
+
const res = untrustFolder(target);
|
|
49143
|
+
appendSystem(
|
|
49144
|
+
ctx.setMessages,
|
|
49145
|
+
res.removed ? `[trust] removed trust for ${target}
|
|
49146
|
+
Project MCP + project hooks are now ignored for this folder.` : `[trust] ${target} was not trusted (nothing to remove).`
|
|
49147
|
+
);
|
|
49148
|
+
}
|
|
49149
|
+
|
|
48219
49150
|
// src/cli/slashHandlers/semantic.ts
|
|
48220
49151
|
init_semantic();
|
|
48221
49152
|
init_provider();
|
|
@@ -48341,7 +49272,7 @@ import { promises as fs22 } from "node:fs";
|
|
|
48341
49272
|
init_zod();
|
|
48342
49273
|
init_taskTool();
|
|
48343
49274
|
import { promises as fs21 } from "node:fs";
|
|
48344
|
-
import
|
|
49275
|
+
import path39 from "node:path";
|
|
48345
49276
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
48346
49277
|
var CsvFanoutArgsSchema = external_exports.object({
|
|
48347
49278
|
csv_path: external_exports.string().min(1),
|
|
@@ -48435,8 +49366,8 @@ function resolveMaxConcurrency(env = process.env) {
|
|
|
48435
49366
|
}
|
|
48436
49367
|
async function runCsvFanout(args, deps, opts) {
|
|
48437
49368
|
const start = Date.now();
|
|
48438
|
-
const absCsv =
|
|
48439
|
-
const absOut =
|
|
49369
|
+
const absCsv = path39.isAbsolute(args.csv_path) ? args.csv_path : path39.join(opts.parentCwd, args.csv_path);
|
|
49370
|
+
const absOut = path39.isAbsolute(args.output_csv_path) ? args.output_csv_path : path39.join(opts.parentCwd, args.output_csv_path);
|
|
48440
49371
|
const { headers, rows } = await readCsv(absCsv);
|
|
48441
49372
|
if (headers.length === 0) {
|
|
48442
49373
|
throw new Error(`kraken_csv_fanout: ${absCsv} is empty`);
|
|
@@ -48492,7 +49423,7 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
48492
49423
|
errored += 1;
|
|
48493
49424
|
errors.push(`${row[args.id_column] ?? i}: ${res.error}`);
|
|
48494
49425
|
}
|
|
48495
|
-
await fs21.mkdir(
|
|
49426
|
+
await fs21.mkdir(path39.dirname(absOut), { recursive: true });
|
|
48496
49427
|
await queueWrite(serializeCsv(outHeaders, outputRecords));
|
|
48497
49428
|
}
|
|
48498
49429
|
}
|
|
@@ -48686,7 +49617,7 @@ function splitArgs(s) {
|
|
|
48686
49617
|
|
|
48687
49618
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
48688
49619
|
import { promises as fs23 } from "node:fs";
|
|
48689
|
-
import
|
|
49620
|
+
import path40 from "node:path";
|
|
48690
49621
|
|
|
48691
49622
|
// src/cli/kraken/workbenchView.ts
|
|
48692
49623
|
var EMPTY = {
|
|
@@ -48803,14 +49734,14 @@ function formatWorkbenchForTerminal(p3) {
|
|
|
48803
49734
|
|
|
48804
49735
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
48805
49736
|
async function handleKrakenWorkbench(ctx) {
|
|
48806
|
-
const dir =
|
|
49737
|
+
const dir = path40.join(ctx.cwd, ".zelari", "radio");
|
|
48807
49738
|
let latest = null;
|
|
48808
49739
|
let latestMtime = 0;
|
|
48809
49740
|
try {
|
|
48810
49741
|
const files = await fs23.readdir(dir);
|
|
48811
49742
|
for (const f of files) {
|
|
48812
49743
|
if (!f.startsWith("workbench-") || !f.endsWith(".md")) continue;
|
|
48813
|
-
const full =
|
|
49744
|
+
const full = path40.join(dir, f);
|
|
48814
49745
|
const stat = await fs23.stat(full);
|
|
48815
49746
|
if (stat.mtimeMs > latestMtime) {
|
|
48816
49747
|
latestMtime = stat.mtimeMs;
|
|
@@ -48827,10 +49758,10 @@ async function handleKrakenWorkbench(ctx) {
|
|
|
48827
49758
|
const parsed = parseWorkbench(content);
|
|
48828
49759
|
const rendered = formatWorkbenchForTerminal(parsed);
|
|
48829
49760
|
if (!rendered.trim()) {
|
|
48830
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
49761
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path40.basename(latest)}: (no nodes / no events yet)`);
|
|
48831
49762
|
return;
|
|
48832
49763
|
}
|
|
48833
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
49764
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path40.basename(latest)}:
|
|
48834
49765
|
${rendered}`);
|
|
48835
49766
|
}
|
|
48836
49767
|
|
|
@@ -48982,8 +49913,8 @@ init_registry3();
|
|
|
48982
49913
|
// src/cli/plugins/installer.ts
|
|
48983
49914
|
init_cmdline();
|
|
48984
49915
|
init_updater();
|
|
48985
|
-
import { spawn as
|
|
48986
|
-
async function installPlugin(spec, cwd, executor =
|
|
49916
|
+
import { spawn as spawn12 } from "node:child_process";
|
|
49917
|
+
async function installPlugin(spec, cwd, executor = spawn12) {
|
|
48987
49918
|
const scopeFlag = spec.installScope === "global" ? "-g" : "-D";
|
|
48988
49919
|
const args = ["install", scopeFlag, spec.npmPackage];
|
|
48989
49920
|
let result = await runNpm2(executor, args, cwd, "shim");
|
|
@@ -49132,15 +50063,15 @@ ${result.output.split("\n").slice(-8).join("\n")}` : "";
|
|
|
49132
50063
|
|
|
49133
50064
|
// src/cli/slashHandlers/promoteMember.ts
|
|
49134
50065
|
import { promises as fs24 } from "node:fs";
|
|
49135
|
-
import
|
|
50066
|
+
import path43 from "node:path";
|
|
49136
50067
|
import os10 from "node:os";
|
|
49137
50068
|
async function handlePromoteMember(ctx, memberId) {
|
|
49138
50069
|
try {
|
|
49139
50070
|
const { promoteMember: promoteMember2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
49140
50071
|
const { skill, markdown } = promoteMember2(memberId);
|
|
49141
|
-
const skillDir = process.env.ANATHEMA_SKILL_DIR ??
|
|
50072
|
+
const skillDir = process.env.ANATHEMA_SKILL_DIR ?? path43.join(os10.homedir(), ".tmp", "zelari-code", "skills");
|
|
49142
50073
|
await fs24.mkdir(skillDir, { recursive: true });
|
|
49143
|
-
const filePath =
|
|
50074
|
+
const filePath = path43.join(skillDir, `${skill.id}.md`);
|
|
49144
50075
|
await fs24.writeFile(filePath, markdown, "utf8");
|
|
49145
50076
|
appendSystem(
|
|
49146
50077
|
ctx.setMessages,
|
|
@@ -49157,33 +50088,33 @@ async function handlePromoteMember(ctx, memberId) {
|
|
|
49157
50088
|
}
|
|
49158
50089
|
|
|
49159
50090
|
// src/cli/branchManager.ts
|
|
49160
|
-
import { promises as fs25, existsSync as
|
|
49161
|
-
import
|
|
50091
|
+
import { promises as fs25, existsSync as existsSync39, readFileSync as readFileSync32, writeFileSync as writeFileSync20, mkdirSync as mkdirSync17, statSync as statSync4, rmSync as rmSync3 } from "node:fs";
|
|
50092
|
+
import path44 from "node:path";
|
|
49162
50093
|
import os11 from "node:os";
|
|
49163
50094
|
var META_FILENAME = "meta.json";
|
|
49164
50095
|
var SESSIONS_SUBDIR = "sessions";
|
|
49165
50096
|
function getBranchesBaseDir() {
|
|
49166
|
-
return process.env.ANATHEMA_BRANCHES_DIR ??
|
|
50097
|
+
return process.env.ANATHEMA_BRANCHES_DIR ?? path44.join(os11.homedir(), ".tmp", "zelari-code", "branches");
|
|
49167
50098
|
}
|
|
49168
50099
|
function getSessionsBaseDir() {
|
|
49169
|
-
return process.env.ANATHEMA_SESSIONS_DIR ??
|
|
50100
|
+
return process.env.ANATHEMA_SESSIONS_DIR ?? path44.join(os11.homedir(), ".tmp", "zelari-code", "sessions");
|
|
49170
50101
|
}
|
|
49171
50102
|
function branchPathFor(name, baseDir) {
|
|
49172
|
-
return
|
|
50103
|
+
return path44.join(baseDir, name);
|
|
49173
50104
|
}
|
|
49174
50105
|
function metaPathFor(name, baseDir) {
|
|
49175
|
-
return
|
|
50106
|
+
return path44.join(baseDir, name, META_FILENAME);
|
|
49176
50107
|
}
|
|
49177
50108
|
function sessionsPathFor(name, baseDir) {
|
|
49178
|
-
return
|
|
50109
|
+
return path44.join(baseDir, name, SESSIONS_SUBDIR);
|
|
49179
50110
|
}
|
|
49180
50111
|
function readBranchMeta(name, baseDir) {
|
|
49181
50112
|
const metaPath = metaPathFor(name, baseDir);
|
|
49182
|
-
if (!
|
|
50113
|
+
if (!existsSync39(metaPath)) {
|
|
49183
50114
|
throw new BranchNotFoundError(`Branch "${name}" not found`);
|
|
49184
50115
|
}
|
|
49185
50116
|
try {
|
|
49186
|
-
const raw =
|
|
50117
|
+
const raw = readFileSync32(metaPath, "utf-8");
|
|
49187
50118
|
const parsed = JSON.parse(raw);
|
|
49188
50119
|
if (!parsed || typeof parsed !== "object" || typeof parsed.name !== "string" || typeof parsed.createdAt !== "number" || typeof parsed.fromSessionId !== "string") {
|
|
49189
50120
|
throw new BranchCorruptError(`Branch "${name}" meta.json is malformed`);
|
|
@@ -49200,8 +50131,8 @@ function readBranchMeta(name, baseDir) {
|
|
|
49200
50131
|
}
|
|
49201
50132
|
function writeBranchMeta(name, baseDir, meta3) {
|
|
49202
50133
|
const metaPath = metaPathFor(name, baseDir);
|
|
49203
|
-
|
|
49204
|
-
|
|
50134
|
+
mkdirSync17(path44.dirname(metaPath), { recursive: true });
|
|
50135
|
+
writeFileSync20(metaPath, JSON.stringify(meta3, null, 2), "utf-8");
|
|
49205
50136
|
}
|
|
49206
50137
|
async function countSessions(name, baseDir) {
|
|
49207
50138
|
const sessionsPath = sessionsPathFor(name, baseDir);
|
|
@@ -49239,7 +50170,7 @@ var SessionNotFoundError = class extends Error {
|
|
|
49239
50170
|
};
|
|
49240
50171
|
function branchExists(name, baseDir = getBranchesBaseDir()) {
|
|
49241
50172
|
const bp = branchPathFor(name, baseDir);
|
|
49242
|
-
return
|
|
50173
|
+
return existsSync39(bp) && existsSync39(metaPathFor(name, baseDir));
|
|
49243
50174
|
}
|
|
49244
50175
|
async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(), sessionsBaseDir = getSessionsBaseDir()) {
|
|
49245
50176
|
if (!name || name.trim().length === 0) {
|
|
@@ -49251,14 +50182,14 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
49251
50182
|
if (branchExists(name, baseDir)) {
|
|
49252
50183
|
throw new BranchAlreadyExistsError(name);
|
|
49253
50184
|
}
|
|
49254
|
-
const sourcePath =
|
|
49255
|
-
if (!
|
|
50185
|
+
const sourcePath = path44.join(sessionsBaseDir, `${fromSessionId}.jsonl`);
|
|
50186
|
+
if (!existsSync39(sourcePath)) {
|
|
49256
50187
|
throw new SessionNotFoundError(`Source session "${fromSessionId}" not found at ${sourcePath}`);
|
|
49257
50188
|
}
|
|
49258
50189
|
const branchPath = branchPathFor(name, baseDir);
|
|
49259
50190
|
const branchSessionsPath = sessionsPathFor(name, baseDir);
|
|
49260
|
-
|
|
49261
|
-
const destPath =
|
|
50191
|
+
mkdirSync17(branchSessionsPath, { recursive: true });
|
|
50192
|
+
const destPath = path44.join(branchSessionsPath, `${fromSessionId}.jsonl`);
|
|
49262
50193
|
await fs25.copyFile(sourcePath, destPath);
|
|
49263
50194
|
const meta3 = {
|
|
49264
50195
|
name,
|
|
@@ -49285,7 +50216,7 @@ async function listBranches(baseDir = getBranchesBaseDir()) {
|
|
|
49285
50216
|
const results = [];
|
|
49286
50217
|
for (const entry of entries) {
|
|
49287
50218
|
const metaPath = metaPathFor(entry, baseDir);
|
|
49288
|
-
if (!
|
|
50219
|
+
if (!existsSync39(metaPath)) continue;
|
|
49289
50220
|
try {
|
|
49290
50221
|
const meta3 = readBranchMeta(entry, baseDir);
|
|
49291
50222
|
const sessionCount = await countSessions(entry, baseDir);
|
|
@@ -49359,14 +50290,14 @@ async function handleBranchCheckout(ctx, branchName) {
|
|
|
49359
50290
|
|
|
49360
50291
|
// src/cli/slashHandlers/workspace.ts
|
|
49361
50292
|
import { promises as fs26 } from "node:fs";
|
|
49362
|
-
import
|
|
50293
|
+
import path45 from "node:path";
|
|
49363
50294
|
async function handleWorkspaceShow(ctx, what) {
|
|
49364
50295
|
try {
|
|
49365
|
-
const zelari =
|
|
50296
|
+
const zelari = path45.join(process.cwd(), ".zelari");
|
|
49366
50297
|
let content;
|
|
49367
50298
|
switch (what) {
|
|
49368
50299
|
case "plan": {
|
|
49369
|
-
const planPath =
|
|
50300
|
+
const planPath = path45.join(zelari, "plan.md");
|
|
49370
50301
|
try {
|
|
49371
50302
|
content = await fs26.readFile(planPath, "utf-8");
|
|
49372
50303
|
} catch {
|
|
@@ -49375,7 +50306,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
49375
50306
|
break;
|
|
49376
50307
|
}
|
|
49377
50308
|
case "decisions": {
|
|
49378
|
-
const decisionsDir =
|
|
50309
|
+
const decisionsDir = path45.join(zelari, "decisions");
|
|
49379
50310
|
try {
|
|
49380
50311
|
const files = (await fs26.readdir(decisionsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
49381
50312
|
if (files.length === 0) {
|
|
@@ -49385,7 +50316,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
49385
50316
|
`];
|
|
49386
50317
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
49387
50318
|
for (const f of files) {
|
|
49388
|
-
const raw = await fs26.readFile(
|
|
50319
|
+
const raw = await fs26.readFile(path45.join(decisionsDir, f), "utf-8");
|
|
49389
50320
|
const { meta: meta3, body } = parseFrontmatter2(raw);
|
|
49390
50321
|
const title = meta3.title ?? body.split("\n")[0]?.replace(/^#\s*/, "").trim() ?? f;
|
|
49391
50322
|
lines.push(`- **${f.replace(/\.md$/, "")}** [${meta3.status ?? "unknown"}] ${title}`);
|
|
@@ -49398,7 +50329,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
49398
50329
|
break;
|
|
49399
50330
|
}
|
|
49400
50331
|
case "risks": {
|
|
49401
|
-
const risksPath =
|
|
50332
|
+
const risksPath = path45.join(zelari, "risks.md");
|
|
49402
50333
|
try {
|
|
49403
50334
|
content = await fs26.readFile(risksPath, "utf-8");
|
|
49404
50335
|
} catch {
|
|
@@ -49407,7 +50338,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
49407
50338
|
break;
|
|
49408
50339
|
}
|
|
49409
50340
|
case "agents": {
|
|
49410
|
-
const agentsPath =
|
|
50341
|
+
const agentsPath = path45.join(process.cwd(), "AGENTS.MD");
|
|
49411
50342
|
try {
|
|
49412
50343
|
content = await fs26.readFile(agentsPath, "utf-8");
|
|
49413
50344
|
} catch {
|
|
@@ -49416,7 +50347,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
49416
50347
|
break;
|
|
49417
50348
|
}
|
|
49418
50349
|
case "docs": {
|
|
49419
|
-
const docsDir =
|
|
50350
|
+
const docsDir = path45.join(zelari, "docs");
|
|
49420
50351
|
try {
|
|
49421
50352
|
const files = (await fs26.readdir(docsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
49422
50353
|
content = files.length ? `# Docs (${files.length})
|
|
@@ -49458,7 +50389,7 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
49458
50389
|
return;
|
|
49459
50390
|
}
|
|
49460
50391
|
try {
|
|
49461
|
-
const target =
|
|
50392
|
+
const target = path45.join(process.cwd(), ".zelari");
|
|
49462
50393
|
await fs26.rm(target, { recursive: true, force: true });
|
|
49463
50394
|
appendSystem(ctx.setMessages, "[workspace] .zelari/ removed");
|
|
49464
50395
|
} catch (err) {
|
|
@@ -49818,11 +50749,11 @@ function handleModelsRefresh(ctx) {
|
|
|
49818
50749
|
}
|
|
49819
50750
|
|
|
49820
50751
|
// src/cli/slashHandlers/skills.ts
|
|
49821
|
-
import
|
|
50752
|
+
import path46 from "node:path";
|
|
49822
50753
|
import os12 from "node:os";
|
|
49823
50754
|
|
|
49824
50755
|
// src/cli/skillHistory.ts
|
|
49825
|
-
import { promises as fs27, existsSync as
|
|
50756
|
+
import { promises as fs27, existsSync as existsSync40, statSync as statSync5, renameSync as renameSync4, appendFileSync as appendFileSync4, mkdirSync as mkdirSync18 } from "node:fs";
|
|
49826
50757
|
var SKILL_HISTORY_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
49827
50758
|
async function readSkillHistory(file2) {
|
|
49828
50759
|
let raw = "";
|
|
@@ -49944,7 +50875,7 @@ function handleSkillPicker(ctx, skills, openPicker, fallbackMessage) {
|
|
|
49944
50875
|
});
|
|
49945
50876
|
}
|
|
49946
50877
|
async function handleSkillStats(ctx, skillId) {
|
|
49947
|
-
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ??
|
|
50878
|
+
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ?? path46.join(os12.homedir(), ".tmp", "zelari-code", "skill-history.jsonl");
|
|
49948
50879
|
try {
|
|
49949
50880
|
const records = await readSkillHistory(historyFile);
|
|
49950
50881
|
const stats = getSkillStats(records, skillId);
|
|
@@ -49960,7 +50891,7 @@ async function handleSkillCompare(ctx, ids, fallbackMessage) {
|
|
|
49960
50891
|
appendSystem(ctx.setMessages, fallbackMessage ?? "[skill-compare] missing args");
|
|
49961
50892
|
return;
|
|
49962
50893
|
}
|
|
49963
|
-
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ??
|
|
50894
|
+
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ?? path46.join(os12.homedir(), ".tmp", "zelari-code", "skill-history.jsonl");
|
|
49964
50895
|
try {
|
|
49965
50896
|
const formatted = await compareSkillsFromFile(ids[0], ids[1], historyFile);
|
|
49966
50897
|
appendSystem(ctx.setMessages, formatted);
|
|
@@ -50350,6 +51281,21 @@ function useSlashDispatch(params) {
|
|
|
50350
51281
|
setInput("");
|
|
50351
51282
|
return;
|
|
50352
51283
|
}
|
|
51284
|
+
if (result.kind === "trust_status") {
|
|
51285
|
+
handleTrustStatus({ setMessages }, result.trustPath ?? process.cwd());
|
|
51286
|
+
setInput("");
|
|
51287
|
+
return;
|
|
51288
|
+
}
|
|
51289
|
+
if (result.kind === "trust_add") {
|
|
51290
|
+
handleTrust({ setMessages }, result.trustPath ?? process.cwd());
|
|
51291
|
+
setInput("");
|
|
51292
|
+
return;
|
|
51293
|
+
}
|
|
51294
|
+
if (result.kind === "trust_remove") {
|
|
51295
|
+
handleUntrust({ setMessages }, result.trustPath ?? process.cwd());
|
|
51296
|
+
setInput("");
|
|
51297
|
+
return;
|
|
51298
|
+
}
|
|
50353
51299
|
if (result.kind === "index_build") {
|
|
50354
51300
|
await handleIndexBuild({ ...baseCtx, cwd: process.cwd() });
|
|
50355
51301
|
setInput("");
|
|
@@ -51117,9 +52063,9 @@ function ContinueKey({ onContinue }) {
|
|
|
51117
52063
|
init_providerConfig();
|
|
51118
52064
|
|
|
51119
52065
|
// src/cli/wizard/firstRun.ts
|
|
51120
|
-
import { existsSync as
|
|
52066
|
+
import { existsSync as existsSync42 } from "node:fs";
|
|
51121
52067
|
function shouldRunWizard(input) {
|
|
51122
|
-
const exists = input.exists ??
|
|
52068
|
+
const exists = input.exists ?? existsSync42;
|
|
51123
52069
|
if (input.hasResetConfigFlag) {
|
|
51124
52070
|
return { shouldRun: true, reason: "--reset-config flag forced wizard" };
|
|
51125
52071
|
}
|
|
@@ -51404,7 +52350,7 @@ init_keyStore();
|
|
|
51404
52350
|
init_providerConfig();
|
|
51405
52351
|
init_openai_compatible();
|
|
51406
52352
|
init_phase();
|
|
51407
|
-
import { readFileSync as
|
|
52353
|
+
import { readFileSync as readFileSync34 } from "node:fs";
|
|
51408
52354
|
function parseHeadlessFlags(argv) {
|
|
51409
52355
|
if (!argv.includes("--headless")) {
|
|
51410
52356
|
return { options: null };
|
|
@@ -51476,7 +52422,7 @@ function parseHeadlessFlags(argv) {
|
|
|
51476
52422
|
let raw = null;
|
|
51477
52423
|
if (arg === "--history-file") {
|
|
51478
52424
|
try {
|
|
51479
|
-
raw =
|
|
52425
|
+
raw = readFileSync34(next, "utf-8");
|
|
51480
52426
|
} catch {
|
|
51481
52427
|
raw = null;
|
|
51482
52428
|
}
|
|
@@ -51622,7 +52568,7 @@ function createStreamScrubber() {
|
|
|
51622
52568
|
// src/cli/runHeadless.ts
|
|
51623
52569
|
init_taskTool();
|
|
51624
52570
|
import { promises as fs29 } from "node:fs";
|
|
51625
|
-
import
|
|
52571
|
+
import path48 from "node:path";
|
|
51626
52572
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
51627
52573
|
async function runHeadless(opts) {
|
|
51628
52574
|
resetTaskSpawnCount();
|
|
@@ -51770,7 +52716,7 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
51770
52716
|
try {
|
|
51771
52717
|
let preflightGraph;
|
|
51772
52718
|
if (opts.runPlan && opts.runPlan.trim() !== "") {
|
|
51773
|
-
const planPath =
|
|
52719
|
+
const planPath = path48.join(cwd, ".zelari", "radio", `plan-${opts.runPlan}.json`);
|
|
51774
52720
|
log(`loading pre-flight plan: ${planPath}`);
|
|
51775
52721
|
let raw;
|
|
51776
52722
|
try {
|
|
@@ -51810,8 +52756,8 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
51810
52756
|
log(formatKrakenGraphAscii2(graph));
|
|
51811
52757
|
if (opts.planOnly) {
|
|
51812
52758
|
const planId = randomUUID6();
|
|
51813
|
-
const planDir =
|
|
51814
|
-
const planPath =
|
|
52759
|
+
const planDir = path48.join(cwd, ".zelari", "radio");
|
|
52760
|
+
const planPath = path48.join(planDir, `plan-${planId}.json`);
|
|
51815
52761
|
await fs29.mkdir(planDir, { recursive: true });
|
|
51816
52762
|
await fs29.writeFile(planPath, JSON.stringify(graph, null, 2), "utf8");
|
|
51817
52763
|
log(`plan-only: wrote ${planPath} (${graph.nodes.size} nodes)`);
|
|
@@ -52799,263 +53745,13 @@ init_skillsMd();
|
|
|
52799
53745
|
init_skills2();
|
|
52800
53746
|
init_updater();
|
|
52801
53747
|
init_mcpConfigIo();
|
|
52802
|
-
|
|
52803
|
-
// src/cli/skillConfigIo.ts
|
|
52804
|
-
init_skills2();
|
|
52805
|
-
init_skillsMd();
|
|
52806
|
-
import {
|
|
52807
|
-
existsSync as existsSync42,
|
|
52808
|
-
mkdirSync as mkdirSync18,
|
|
52809
|
-
readdirSync as readdirSync7,
|
|
52810
|
-
readFileSync as readFileSync33,
|
|
52811
|
-
rmSync as rmSync4,
|
|
52812
|
-
writeFileSync as writeFileSync20
|
|
52813
|
-
} from "node:fs";
|
|
52814
|
-
import { dirname as dirname9, join as join34 } from "node:path";
|
|
52815
|
-
import { homedir as homedir10 } from "node:os";
|
|
52816
|
-
|
|
52817
|
-
// src/cli/skillCategories.ts
|
|
52818
|
-
var CODING_CATEGORIES_LIST = [
|
|
52819
|
-
"plan",
|
|
52820
|
-
"refactor",
|
|
52821
|
-
"debug",
|
|
52822
|
-
"review",
|
|
52823
|
-
"test",
|
|
52824
|
-
"docs",
|
|
52825
|
-
"ops",
|
|
52826
|
-
"git",
|
|
52827
|
-
"db",
|
|
52828
|
-
"maint"
|
|
52829
|
-
];
|
|
52830
|
-
var CODING_CATEGORIES2 = new Set(CODING_CATEGORIES_LIST);
|
|
52831
|
-
|
|
52832
|
-
// src/cli/skillConfigIo.ts
|
|
52833
|
-
var NAME_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
52834
|
-
var BUILTIN_SKILL_MODULES = [
|
|
52835
|
-
"@zelari/core/skills/builtin/debugging",
|
|
52836
|
-
"@zelari/core/skills/builtin/docs",
|
|
52837
|
-
"@zelari/core/skills/builtin/git-ops",
|
|
52838
|
-
"@zelari/core/skills/builtin/planning",
|
|
52839
|
-
"@zelari/core/skills/builtin/refactoring",
|
|
52840
|
-
"@zelari/core/skills/builtin/review",
|
|
52841
|
-
"@zelari/core/skills/builtin/testing",
|
|
52842
|
-
"@zelari/core/skills/builtin/schema-loop",
|
|
52843
|
-
"@zelari/core/skills/builtin/computer-use-cua",
|
|
52844
|
-
"@zelari/core/skills/builtin/qwen-mm-plugins"
|
|
52845
|
-
];
|
|
52846
|
-
var builtinsLoaded = false;
|
|
52847
|
-
function ensureBuiltinSkillsLoadedSync() {
|
|
52848
|
-
if (builtinsLoaded) return;
|
|
52849
|
-
for (const spec of BUILTIN_SKILL_MODULES) {
|
|
52850
|
-
try {
|
|
52851
|
-
require?.(spec);
|
|
52852
|
-
} catch {
|
|
52853
|
-
}
|
|
52854
|
-
}
|
|
52855
|
-
}
|
|
52856
|
-
function getUserSkillsDir() {
|
|
52857
|
-
return join34(homedir10(), ".zelari-code", "skills");
|
|
52858
|
-
}
|
|
52859
|
-
function getProjectSkillsDir(projectRoot) {
|
|
52860
|
-
return join34(projectRoot, ".zelari", "skills");
|
|
52861
|
-
}
|
|
52862
|
-
function skillFilePath(dir, name) {
|
|
52863
|
-
return join34(dir, name, "SKILL.md");
|
|
52864
|
-
}
|
|
52865
|
-
function classifyScope(skillPath, projectRoot) {
|
|
52866
|
-
const userDir = getUserSkillsDir().replace(/\\/g, "/");
|
|
52867
|
-
const norm = skillPath.replace(/\\/g, "/");
|
|
52868
|
-
if (norm.startsWith(userDir + "/") || norm === userDir) {
|
|
52869
|
-
return { scope: "user", writable: true };
|
|
52870
|
-
}
|
|
52871
|
-
if (projectRoot) {
|
|
52872
|
-
const projDir = getProjectSkillsDir(projectRoot).replace(/\\/g, "/");
|
|
52873
|
-
if (norm.startsWith(projDir + "/") || norm === projDir) {
|
|
52874
|
-
return { scope: "project", writable: true };
|
|
52875
|
-
}
|
|
52876
|
-
}
|
|
52877
|
-
return { scope: "compat", writable: false };
|
|
52878
|
-
}
|
|
52879
|
-
function entryFromParsed(parsed, projectRoot) {
|
|
52880
|
-
const { scope, writable } = classifyScope(parsed.sourcePath, projectRoot);
|
|
52881
|
-
return {
|
|
52882
|
-
id: parsed.name,
|
|
52883
|
-
name: parsed.name,
|
|
52884
|
-
description: parsed.description,
|
|
52885
|
-
category: parsed.category,
|
|
52886
|
-
estimatedCost: parsed.estimatedCost,
|
|
52887
|
-
requiredTools: parsed.requiredTools,
|
|
52888
|
-
scope,
|
|
52889
|
-
path: parsed.sourcePath,
|
|
52890
|
-
body: parsed.body,
|
|
52891
|
-
builtin: false,
|
|
52892
|
-
writable
|
|
52893
|
-
};
|
|
52894
|
-
}
|
|
52895
|
-
function entryFromBuiltin(skill) {
|
|
52896
|
-
return {
|
|
52897
|
-
id: skill.id,
|
|
52898
|
-
name: skill.name || skill.id,
|
|
52899
|
-
description: skill.description || "",
|
|
52900
|
-
category: skill.category,
|
|
52901
|
-
estimatedCost: skill.estimatedCost,
|
|
52902
|
-
requiredTools: skill.requiredTools,
|
|
52903
|
-
scope: "builtin",
|
|
52904
|
-
path: null,
|
|
52905
|
-
// Expose body so Desktop skill picker can expand like `/skill <id>`.
|
|
52906
|
-
body: skill.systemPromptFragment || void 0,
|
|
52907
|
-
builtin: true,
|
|
52908
|
-
writable: false
|
|
52909
|
-
};
|
|
52910
|
-
}
|
|
52911
|
-
function scanSkillsDir(dir, projectRoot, seen, out) {
|
|
52912
|
-
if (!existsSync42(dir)) return;
|
|
52913
|
-
let entries;
|
|
52914
|
-
try {
|
|
52915
|
-
entries = readdirSync7(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
52916
|
-
} catch {
|
|
52917
|
-
return;
|
|
52918
|
-
}
|
|
52919
|
-
for (const entry of entries) {
|
|
52920
|
-
const skillPath = skillFilePath(dir, entry);
|
|
52921
|
-
if (!existsSync42(skillPath)) continue;
|
|
52922
|
-
try {
|
|
52923
|
-
const parsed = parseSkillMd(readFileSync33(skillPath, "utf8"), skillPath);
|
|
52924
|
-
if (!parsed) continue;
|
|
52925
|
-
if (seen.has(parsed.name)) continue;
|
|
52926
|
-
seen.add(parsed.name);
|
|
52927
|
-
out.push(entryFromParsed(parsed, projectRoot));
|
|
52928
|
-
} catch {
|
|
52929
|
-
}
|
|
52930
|
-
}
|
|
52931
|
-
}
|
|
52932
|
-
function listSkillsSnapshot(projectRoot) {
|
|
52933
|
-
const root = projectRoot && projectRoot.trim() ? projectRoot.trim() : null;
|
|
52934
|
-
const userSkillsDir = getUserSkillsDir();
|
|
52935
|
-
const projectSkillsDir = root ? getProjectSkillsDir(root) : null;
|
|
52936
|
-
const skills = [];
|
|
52937
|
-
const seen = /* @__PURE__ */ new Set();
|
|
52938
|
-
if (root) {
|
|
52939
|
-
scanSkillsDir(join34(root, ".zelari", "skills"), root, seen, skills);
|
|
52940
|
-
scanSkillsDir(join34(root, ".claude", "skills"), root, seen, skills);
|
|
52941
|
-
scanSkillsDir(join34(root, ".opencode", "skills"), root, seen, skills);
|
|
52942
|
-
}
|
|
52943
|
-
scanSkillsDir(userSkillsDir, root, seen, skills);
|
|
52944
|
-
for (const s of listCodingSkills()) {
|
|
52945
|
-
if (seen.has(s.id)) continue;
|
|
52946
|
-
seen.add(s.id);
|
|
52947
|
-
if (s.builtin) {
|
|
52948
|
-
skills.push(entryFromBuiltin(s));
|
|
52949
|
-
}
|
|
52950
|
-
}
|
|
52951
|
-
skills.sort((a, b) => {
|
|
52952
|
-
const order = (s) => s === "project" ? 0 : s === "user" ? 1 : s === "compat" ? 2 : 3;
|
|
52953
|
-
const d = order(a.scope) - order(b.scope);
|
|
52954
|
-
if (d !== 0) return d;
|
|
52955
|
-
return a.id.localeCompare(b.id);
|
|
52956
|
-
});
|
|
52957
|
-
return { userSkillsDir, projectSkillsDir, skills };
|
|
52958
|
-
}
|
|
52959
|
-
function serializeSkillMd(opts) {
|
|
52960
|
-
const name = opts.name.trim().toLowerCase();
|
|
52961
|
-
const description = opts.description.trim();
|
|
52962
|
-
const body = opts.body.trim();
|
|
52963
|
-
const lines = ["---", `name: ${name}`, `description: ${description}`];
|
|
52964
|
-
const cat = (opts.category ?? "").trim().toLowerCase();
|
|
52965
|
-
if (cat && CODING_CATEGORIES2.has(cat)) {
|
|
52966
|
-
lines.push(`category: ${cat}`);
|
|
52967
|
-
}
|
|
52968
|
-
if (opts.tools && opts.tools.length > 0) {
|
|
52969
|
-
lines.push(`tools: [${opts.tools.map((t) => t.trim()).filter(Boolean).join(", ")}]`);
|
|
52970
|
-
}
|
|
52971
|
-
const cost = (opts.cost ?? "").trim().toLowerCase();
|
|
52972
|
-
if (cost === "low" || cost === "medium" || cost === "high") {
|
|
52973
|
-
lines.push(`cost: ${cost}`);
|
|
52974
|
-
}
|
|
52975
|
-
lines.push("---", "", body, "");
|
|
52976
|
-
return lines.join("\n");
|
|
52977
|
-
}
|
|
52978
|
-
function upsertSkill(opts) {
|
|
52979
|
-
const name = opts.name.trim().toLowerCase();
|
|
52980
|
-
if (!name || !NAME_RE.test(name)) {
|
|
52981
|
-
return {
|
|
52982
|
-
ok: false,
|
|
52983
|
-
error: "Invalid skill name (use lowercase letters, digits, hyphens; max 64 chars)"
|
|
52984
|
-
};
|
|
52985
|
-
}
|
|
52986
|
-
const description = opts.description.trim();
|
|
52987
|
-
if (!description) {
|
|
52988
|
-
return { ok: false, error: "description is required" };
|
|
52989
|
-
}
|
|
52990
|
-
const body = opts.body.trim();
|
|
52991
|
-
if (!body) {
|
|
52992
|
-
return { ok: false, error: "body is required" };
|
|
52993
|
-
}
|
|
52994
|
-
let dir;
|
|
52995
|
-
if (opts.scope === "user") {
|
|
52996
|
-
dir = getUserSkillsDir();
|
|
52997
|
-
} else {
|
|
52998
|
-
const root = opts.projectRoot?.trim();
|
|
52999
|
-
if (!root) {
|
|
53000
|
-
return {
|
|
53001
|
-
ok: false,
|
|
53002
|
-
error: "projectRoot required for project scope (Open Folder first)"
|
|
53003
|
-
};
|
|
53004
|
-
}
|
|
53005
|
-
dir = getProjectSkillsDir(root);
|
|
53006
|
-
}
|
|
53007
|
-
const path48 = skillFilePath(dir, name);
|
|
53008
|
-
const content = serializeSkillMd({
|
|
53009
|
-
name,
|
|
53010
|
-
description,
|
|
53011
|
-
body,
|
|
53012
|
-
category: opts.category,
|
|
53013
|
-
tools: opts.tools,
|
|
53014
|
-
cost: opts.cost
|
|
53015
|
-
});
|
|
53016
|
-
const parsed = parseSkillMd(content, path48);
|
|
53017
|
-
if (!parsed) {
|
|
53018
|
-
return { ok: false, error: "Generated SKILL.md failed validation" };
|
|
53019
|
-
}
|
|
53020
|
-
mkdirSync18(dirname9(path48), { recursive: true });
|
|
53021
|
-
writeFileSync20(path48, content, "utf8");
|
|
53022
|
-
return { ok: true, path: path48 };
|
|
53023
|
-
}
|
|
53024
|
-
function removeSkill(opts) {
|
|
53025
|
-
const name = opts.name.trim().toLowerCase();
|
|
53026
|
-
if (!name) {
|
|
53027
|
-
return { ok: false, error: "name is required" };
|
|
53028
|
-
}
|
|
53029
|
-
let dir;
|
|
53030
|
-
if (opts.scope === "user") {
|
|
53031
|
-
dir = getUserSkillsDir();
|
|
53032
|
-
} else {
|
|
53033
|
-
const root = opts.projectRoot?.trim();
|
|
53034
|
-
if (!root) {
|
|
53035
|
-
return { ok: false, error: "projectRoot required for project scope" };
|
|
53036
|
-
}
|
|
53037
|
-
dir = getProjectSkillsDir(root);
|
|
53038
|
-
}
|
|
53039
|
-
const skillDir = join34(dir, name);
|
|
53040
|
-
const path48 = skillFilePath(dir, name);
|
|
53041
|
-
if (!existsSync42(path48) && !existsSync42(skillDir)) {
|
|
53042
|
-
return { ok: false, error: `Skill "${name}" not found in ${dir}` };
|
|
53043
|
-
}
|
|
53044
|
-
try {
|
|
53045
|
-
rmSync4(skillDir, { recursive: true, force: true });
|
|
53046
|
-
} catch (err) {
|
|
53047
|
-
return {
|
|
53048
|
-
ok: false,
|
|
53049
|
-
error: err instanceof Error ? err.message : String(err)
|
|
53050
|
-
};
|
|
53051
|
-
}
|
|
53052
|
-
return { ok: true, path: path48 };
|
|
53053
|
-
}
|
|
53748
|
+
init_skillConfigIo();
|
|
53054
53749
|
|
|
53055
53750
|
// src/cli/generateSkillFromUrl.ts
|
|
53056
53751
|
init_providerConfig();
|
|
53057
53752
|
init_keyStore();
|
|
53058
53753
|
init_openai_compatible();
|
|
53754
|
+
init_skillCategories();
|
|
53059
53755
|
var MAX_PAGE_CHARS = 24e3;
|
|
53060
53756
|
var FETCH_TIMEOUT_MS2 = 25e3;
|
|
53061
53757
|
var LLM_TIMEOUT_MS = 9e4;
|
|
@@ -53139,8 +53835,8 @@ function normalizeDraft(raw, sourceUrl, provider, model) {
|
|
|
53139
53835
|
let name = String(o.name ?? "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
53140
53836
|
if (!name || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) {
|
|
53141
53837
|
try {
|
|
53142
|
-
const
|
|
53143
|
-
name =
|
|
53838
|
+
const path51 = new URL(sourceUrl).pathname.split("/").filter(Boolean).pop()?.replace(/\.[a-z0-9]+$/i, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
53839
|
+
name = path51 && /^[a-z0-9]/.test(path51) ? path51 : "imported-skill";
|
|
53144
53840
|
} catch {
|
|
53145
53841
|
name = "imported-skill";
|
|
53146
53842
|
}
|
|
@@ -53415,9 +54111,30 @@ function pickRootComponent() {
|
|
|
53415
54111
|
console.error(`${red}\u2717${reset} ${result.error}`);
|
|
53416
54112
|
process.exit(1);
|
|
53417
54113
|
}
|
|
54114
|
+
if (argv.includes("--inspect") || argv.includes("inspect")) {
|
|
54115
|
+
const { runInspect: runInspect2 } = (init_inspect(), __toCommonJS(inspect_exports));
|
|
54116
|
+
const json2 = argv.includes("--json");
|
|
54117
|
+
void runInspect2({ json: json2 }).then((code) => process.exit(code));
|
|
54118
|
+
return { kind: "done" };
|
|
54119
|
+
}
|
|
54120
|
+
if (argv.includes("--trust")) {
|
|
54121
|
+
const { trustFolder: trustFolder2 } = (init_folderTrust(), __toCommonJS(folderTrust_exports));
|
|
54122
|
+
const i = argv.indexOf("--trust");
|
|
54123
|
+
const target = argv[i + 1] && !argv[i + 1].startsWith("--") ? argv[i + 1] : process.cwd();
|
|
54124
|
+
try {
|
|
54125
|
+
const res = trustFolder2(target);
|
|
54126
|
+
console.log(JSON.stringify({ ok: true, path: res.path }));
|
|
54127
|
+
process.exit(0);
|
|
54128
|
+
} catch (err) {
|
|
54129
|
+
console.error(
|
|
54130
|
+
`[zelari-code --trust] ${err instanceof Error ? err.message : String(err)}`
|
|
54131
|
+
);
|
|
54132
|
+
process.exit(1);
|
|
54133
|
+
}
|
|
54134
|
+
}
|
|
53418
54135
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
53419
54136
|
console.log(
|
|
53420
|
-
"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 Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\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 --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 --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 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 --print-config Print provider/model config as JSON (no secrets)\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 --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\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 (required)\n --args <json> JSON array of args (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 --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 ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
54137
|
+
"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 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 --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 --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 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 --print-config Print provider/model config as JSON (no secrets)\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 --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\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 (required)\n --args <json> JSON array of args (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 --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 ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
53421
54138
|
);
|
|
53422
54139
|
process.exit(0);
|
|
53423
54140
|
}
|