zelari-code 1.0.1 → 1.0.3
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/main.bundled.js +533 -195
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +67 -46
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/mcp/mcpClient.js +29 -26
- package/dist/cli/mcp/mcpClient.js.map +1 -1
- package/dist/cli/slashHandlers/updater.js +77 -6
- package/dist/cli/slashHandlers/updater.js.map +1 -1
- package/dist/cli/utils/doctor.js +287 -0
- package/dist/cli/utils/doctor.js.map +1 -0
- package/package.json +4 -2
- package/scripts/postinstall.mjs +186 -0
package/dist/cli/main.bundled.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __crq } from 'node:module'; const require = __crq(import.meta.url);
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
7
|
var __esm = (fn, res) => function __init() {
|
|
6
8
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
7
9
|
};
|
|
@@ -9,6 +11,15 @@ var __export = (target, all) => {
|
|
|
9
11
|
for (var name in all)
|
|
10
12
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
13
|
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
12
23
|
|
|
13
24
|
// src/cli/grokOAuth.ts
|
|
14
25
|
var grokOAuth_exports = {};
|
|
@@ -1522,10 +1533,10 @@ function mergeDefs(...defs) {
|
|
|
1522
1533
|
function cloneDef(schema) {
|
|
1523
1534
|
return mergeDefs(schema._zod.def);
|
|
1524
1535
|
}
|
|
1525
|
-
function getElementAtPath(obj,
|
|
1526
|
-
if (!
|
|
1536
|
+
function getElementAtPath(obj, path25) {
|
|
1537
|
+
if (!path25)
|
|
1527
1538
|
return obj;
|
|
1528
|
-
return
|
|
1539
|
+
return path25.reduce((acc, key) => acc?.[key], obj);
|
|
1529
1540
|
}
|
|
1530
1541
|
function promiseAllObject(promisesObj) {
|
|
1531
1542
|
const keys = Object.keys(promisesObj);
|
|
@@ -1853,11 +1864,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
1853
1864
|
}
|
|
1854
1865
|
return false;
|
|
1855
1866
|
}
|
|
1856
|
-
function prefixIssues(
|
|
1867
|
+
function prefixIssues(path25, issues) {
|
|
1857
1868
|
return issues.map((iss) => {
|
|
1858
1869
|
var _a3;
|
|
1859
1870
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
1860
|
-
iss.path.unshift(
|
|
1871
|
+
iss.path.unshift(path25);
|
|
1861
1872
|
return iss;
|
|
1862
1873
|
});
|
|
1863
1874
|
}
|
|
@@ -2075,16 +2086,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2075
2086
|
}
|
|
2076
2087
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
2077
2088
|
const fieldErrors = { _errors: [] };
|
|
2078
|
-
const processError = (error52,
|
|
2089
|
+
const processError = (error52, path25 = []) => {
|
|
2079
2090
|
for (const issue2 of error52.issues) {
|
|
2080
2091
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
2081
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
2092
|
+
issue2.errors.map((issues) => processError({ issues }, [...path25, ...issue2.path]));
|
|
2082
2093
|
} else if (issue2.code === "invalid_key") {
|
|
2083
|
-
processError({ issues: issue2.issues }, [...
|
|
2094
|
+
processError({ issues: issue2.issues }, [...path25, ...issue2.path]);
|
|
2084
2095
|
} else if (issue2.code === "invalid_element") {
|
|
2085
|
-
processError({ issues: issue2.issues }, [...
|
|
2096
|
+
processError({ issues: issue2.issues }, [...path25, ...issue2.path]);
|
|
2086
2097
|
} else {
|
|
2087
|
-
const fullpath = [...
|
|
2098
|
+
const fullpath = [...path25, ...issue2.path];
|
|
2088
2099
|
if (fullpath.length === 0) {
|
|
2089
2100
|
fieldErrors._errors.push(mapper(issue2));
|
|
2090
2101
|
} else {
|
|
@@ -2111,17 +2122,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2111
2122
|
}
|
|
2112
2123
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
2113
2124
|
const result = { errors: [] };
|
|
2114
|
-
const processError = (error52,
|
|
2125
|
+
const processError = (error52, path25 = []) => {
|
|
2115
2126
|
var _a3, _b;
|
|
2116
2127
|
for (const issue2 of error52.issues) {
|
|
2117
2128
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
2118
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
2129
|
+
issue2.errors.map((issues) => processError({ issues }, [...path25, ...issue2.path]));
|
|
2119
2130
|
} else if (issue2.code === "invalid_key") {
|
|
2120
|
-
processError({ issues: issue2.issues }, [...
|
|
2131
|
+
processError({ issues: issue2.issues }, [...path25, ...issue2.path]);
|
|
2121
2132
|
} else if (issue2.code === "invalid_element") {
|
|
2122
|
-
processError({ issues: issue2.issues }, [...
|
|
2133
|
+
processError({ issues: issue2.issues }, [...path25, ...issue2.path]);
|
|
2123
2134
|
} else {
|
|
2124
|
-
const fullpath = [...
|
|
2135
|
+
const fullpath = [...path25, ...issue2.path];
|
|
2125
2136
|
if (fullpath.length === 0) {
|
|
2126
2137
|
result.errors.push(mapper(issue2));
|
|
2127
2138
|
continue;
|
|
@@ -2153,8 +2164,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2153
2164
|
}
|
|
2154
2165
|
function toDotPath(_path) {
|
|
2155
2166
|
const segs = [];
|
|
2156
|
-
const
|
|
2157
|
-
for (const seg of
|
|
2167
|
+
const path25 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
2168
|
+
for (const seg of path25) {
|
|
2158
2169
|
if (typeof seg === "number")
|
|
2159
2170
|
segs.push(`[${seg}]`);
|
|
2160
2171
|
else if (typeof seg === "symbol")
|
|
@@ -15657,13 +15668,13 @@ function resolveRef(ref, ctx) {
|
|
|
15657
15668
|
if (!ref.startsWith("#")) {
|
|
15658
15669
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
15659
15670
|
}
|
|
15660
|
-
const
|
|
15661
|
-
if (
|
|
15671
|
+
const path25 = ref.slice(1).split("/").filter(Boolean);
|
|
15672
|
+
if (path25.length === 0) {
|
|
15662
15673
|
return ctx.rootSchema;
|
|
15663
15674
|
}
|
|
15664
15675
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
15665
|
-
if (
|
|
15666
|
-
const key =
|
|
15676
|
+
if (path25[0] === defsKey) {
|
|
15677
|
+
const key = path25[1];
|
|
15667
15678
|
if (!key || !ctx.defs[key]) {
|
|
15668
15679
|
throw new Error(`Reference not found: ${ref}`);
|
|
15669
15680
|
}
|
|
@@ -17693,11 +17704,11 @@ var init_tools = __esm({
|
|
|
17693
17704
|
if (!ctx.addDocument)
|
|
17694
17705
|
return "Knowledge vault tool not available.";
|
|
17695
17706
|
const title = args["title"] || "New Document";
|
|
17696
|
-
const
|
|
17707
|
+
const path25 = args["path"] || `notes/${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
|
|
17697
17708
|
const content = args["content"] || "";
|
|
17698
17709
|
const tags = args["tags"] || [];
|
|
17699
17710
|
ctx.addDocument({
|
|
17700
|
-
path:
|
|
17711
|
+
path: path25,
|
|
17701
17712
|
title,
|
|
17702
17713
|
content,
|
|
17703
17714
|
format: "markdown",
|
|
@@ -17706,7 +17717,7 @@ var init_tools = __esm({
|
|
|
17706
17717
|
workspaceId: ctx.workspaceId
|
|
17707
17718
|
});
|
|
17708
17719
|
ctx.addActivity("vault", "created document", title);
|
|
17709
|
-
return `Document "${title}" created at "${
|
|
17720
|
+
return `Document "${title}" created at "${path25}".`;
|
|
17710
17721
|
}
|
|
17711
17722
|
}
|
|
17712
17723
|
];
|
|
@@ -20212,11 +20223,11 @@ var init_synthesisAudit = __esm({
|
|
|
20212
20223
|
import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
20213
20224
|
import { join as join2 } from "node:path";
|
|
20214
20225
|
function loadNfrSpec(zelariRoot) {
|
|
20215
|
-
const
|
|
20216
|
-
if (!existsSync8(
|
|
20226
|
+
const path25 = join2(zelariRoot, "nfr-spec.json");
|
|
20227
|
+
if (!existsSync8(path25))
|
|
20217
20228
|
return null;
|
|
20218
20229
|
try {
|
|
20219
|
-
const raw = JSON.parse(readFileSync6(
|
|
20230
|
+
const raw = JSON.parse(readFileSync6(path25, "utf8"));
|
|
20220
20231
|
if (raw.version !== 1 || !Array.isArray(raw.targets))
|
|
20221
20232
|
return null;
|
|
20222
20233
|
return raw;
|
|
@@ -22405,9 +22416,9 @@ var init_types2 = __esm({
|
|
|
22405
22416
|
import { readFileSync as readFileSync11 } from "node:fs";
|
|
22406
22417
|
import { join as join8 } from "node:path";
|
|
22407
22418
|
function readLessonsDeduped(zelariRoot) {
|
|
22408
|
-
const
|
|
22419
|
+
const path25 = join8(zelariRoot, LESSONS_FILE);
|
|
22409
22420
|
try {
|
|
22410
|
-
const raw = readFileSync11(
|
|
22421
|
+
const raw = readFileSync11(path25, "utf8");
|
|
22411
22422
|
const byId = /* @__PURE__ */ new Map();
|
|
22412
22423
|
for (const line of raw.split(/\r?\n/)) {
|
|
22413
22424
|
if (!line.trim())
|
|
@@ -22508,8 +22519,8 @@ function keywordsFrom(check2, signature) {
|
|
|
22508
22519
|
return [.../* @__PURE__ */ new Set([...fromId, ...words])].slice(0, 12);
|
|
22509
22520
|
}
|
|
22510
22521
|
function writeLesson(zelariRoot, lesson) {
|
|
22511
|
-
const
|
|
22512
|
-
appendFileSync2(
|
|
22522
|
+
const path25 = join9(zelariRoot, LESSONS_FILE);
|
|
22523
|
+
appendFileSync2(path25, `${JSON.stringify(lesson)}
|
|
22513
22524
|
`, "utf8");
|
|
22514
22525
|
}
|
|
22515
22526
|
function findSimilar(lessons, signature) {
|
|
@@ -23649,28 +23660,28 @@ var init_storage = __esm({
|
|
|
23649
23660
|
VALID_SCALARS = /^(true|false|null|~)$/i;
|
|
23650
23661
|
Storage = class {
|
|
23651
23662
|
/** Read a Markdown file with frontmatter. Throws if not found. */
|
|
23652
|
-
read(
|
|
23653
|
-
if (!existsSync13(
|
|
23654
|
-
throw new Error(`File not found: ${
|
|
23663
|
+
read(path25) {
|
|
23664
|
+
if (!existsSync13(path25)) {
|
|
23665
|
+
throw new Error(`File not found: ${path25}`);
|
|
23655
23666
|
}
|
|
23656
|
-
const md = readFileSync13(
|
|
23667
|
+
const md = readFileSync13(path25, "utf8");
|
|
23657
23668
|
return parseFrontmatter(md);
|
|
23658
23669
|
}
|
|
23659
23670
|
/** Read a Markdown file; returns null if not found. */
|
|
23660
|
-
readIfExists(
|
|
23661
|
-
if (!existsSync13(
|
|
23662
|
-
return this.read(
|
|
23671
|
+
readIfExists(path25) {
|
|
23672
|
+
if (!existsSync13(path25)) return null;
|
|
23673
|
+
return this.read(path25);
|
|
23663
23674
|
}
|
|
23664
23675
|
/**
|
|
23665
23676
|
* Write a Markdown file atomically (tmp + rename). Creates parent dirs.
|
|
23666
23677
|
* The meta object is serialized as YAML frontmatter; body as Markdown.
|
|
23667
23678
|
*/
|
|
23668
|
-
write(
|
|
23669
|
-
mkdirSync7(dirname(
|
|
23670
|
-
const tmp =
|
|
23679
|
+
write(path25, meta3, body) {
|
|
23680
|
+
mkdirSync7(dirname(path25), { recursive: true });
|
|
23681
|
+
const tmp = path25 + ".tmp-" + process.pid;
|
|
23671
23682
|
const md = serializeFrontmatter(meta3, body);
|
|
23672
23683
|
writeFileSync11(tmp, md, "utf8");
|
|
23673
|
-
renameSync2(tmp,
|
|
23684
|
+
renameSync2(tmp, path25);
|
|
23674
23685
|
}
|
|
23675
23686
|
/** List all .md files in a directory (non-recursive). */
|
|
23676
23687
|
listMarkdown(dir) {
|
|
@@ -23748,8 +23759,8 @@ function readPlan(ctx) {
|
|
|
23748
23759
|
} catch {
|
|
23749
23760
|
}
|
|
23750
23761
|
}
|
|
23751
|
-
const
|
|
23752
|
-
const doc = ctx.storage.readIfExists(
|
|
23762
|
+
const path25 = workspaceFile(ctx.rootDir, "plan");
|
|
23763
|
+
const doc = ctx.storage.readIfExists(path25);
|
|
23753
23764
|
if (!doc) return { phases: [], tasks: [], milestones: [] };
|
|
23754
23765
|
const meta3 = doc.meta;
|
|
23755
23766
|
return {
|
|
@@ -23914,7 +23925,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
23914
23925
|
dueDate: input.dueDate,
|
|
23915
23926
|
targetVersion: version2
|
|
23916
23927
|
});
|
|
23917
|
-
const
|
|
23928
|
+
const path25 = join14(ctx.rootDir, "milestones", `${id}.md`);
|
|
23918
23929
|
const meta3 = {
|
|
23919
23930
|
kind: "milestone",
|
|
23920
23931
|
id,
|
|
@@ -23931,7 +23942,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
23931
23942
|
`Target version: ${version2}`,
|
|
23932
23943
|
""
|
|
23933
23944
|
].join("\n");
|
|
23934
|
-
ctx.storage.write(
|
|
23945
|
+
ctx.storage.write(path25, meta3, body);
|
|
23935
23946
|
return { id, created: true };
|
|
23936
23947
|
}
|
|
23937
23948
|
function readPlanSummary(ctx) {
|
|
@@ -24135,7 +24146,7 @@ function addIdeaStub(ctx) {
|
|
|
24135
24146
|
const tags = args["tags"] ?? [];
|
|
24136
24147
|
const category = args["category"] ?? "General";
|
|
24137
24148
|
const id = `${nextAdrId(ctx)}-${slugify3(title)}`;
|
|
24138
|
-
const
|
|
24149
|
+
const path25 = workspaceArtifact(ctx.rootDir, "decisions", id);
|
|
24139
24150
|
const meta3 = {
|
|
24140
24151
|
kind: "adr",
|
|
24141
24152
|
status: "proposed",
|
|
@@ -24161,7 +24172,7 @@ function addIdeaStub(ctx) {
|
|
|
24161
24172
|
...consequences.map((c) => `- ${c}`),
|
|
24162
24173
|
""
|
|
24163
24174
|
].join("\n");
|
|
24164
|
-
ctx.storage.write(
|
|
24175
|
+
ctx.storage.write(path25, meta3, body);
|
|
24165
24176
|
return `ADR ${id} created: "${title}". Status: proposed. Promote to accepted via /update ADR or manual edit.`;
|
|
24166
24177
|
});
|
|
24167
24178
|
}
|
|
@@ -24243,14 +24254,14 @@ function createDocumentStub(ctx) {
|
|
|
24243
24254
|
ctx.storage.write(risksPath, riskMeta, content);
|
|
24244
24255
|
return `Document "${title}" created at risks.md (workspace root).`;
|
|
24245
24256
|
}
|
|
24246
|
-
const
|
|
24257
|
+
const path25 = workspaceArtifact(ctx.rootDir, "docs", slug);
|
|
24247
24258
|
const meta3 = {
|
|
24248
24259
|
kind: "doc",
|
|
24249
24260
|
id: slug,
|
|
24250
24261
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
24251
24262
|
tags
|
|
24252
24263
|
};
|
|
24253
|
-
ctx.storage.write(
|
|
24264
|
+
ctx.storage.write(path25, meta3, content);
|
|
24254
24265
|
return `Document "${title}" created at docs/${slug}.md.`;
|
|
24255
24266
|
});
|
|
24256
24267
|
}
|
|
@@ -24469,13 +24480,133 @@ var init_cmdline = __esm({
|
|
|
24469
24480
|
}
|
|
24470
24481
|
});
|
|
24471
24482
|
|
|
24472
|
-
// src/cli/
|
|
24483
|
+
// src/cli/updater.ts
|
|
24484
|
+
var updater_exports = {};
|
|
24485
|
+
__export(updater_exports, {
|
|
24486
|
+
REGISTRY_URL: () => REGISTRY_URL,
|
|
24487
|
+
checkForUpdate: () => checkForUpdate,
|
|
24488
|
+
compareSemver: () => compareSemver,
|
|
24489
|
+
fetchLatestVersion: () => fetchLatestVersion,
|
|
24490
|
+
getCurrentVersion: () => getCurrentVersion,
|
|
24491
|
+
performUpdate: () => performUpdate
|
|
24492
|
+
});
|
|
24493
|
+
import { createRequire } from "node:module";
|
|
24473
24494
|
import { spawn as spawn2 } from "node:child_process";
|
|
24495
|
+
import path15 from "node:path";
|
|
24496
|
+
import { fileURLToPath } from "node:url";
|
|
24497
|
+
function getCurrentVersion() {
|
|
24498
|
+
try {
|
|
24499
|
+
const pkgPath = path15.resolve(__dirname2, "..", "..", "package.json");
|
|
24500
|
+
const pkg = require2(pkgPath);
|
|
24501
|
+
return pkg.version;
|
|
24502
|
+
} catch {
|
|
24503
|
+
return "0.0.0";
|
|
24504
|
+
}
|
|
24505
|
+
}
|
|
24506
|
+
function compareSemver(a, b) {
|
|
24507
|
+
const parse3 = (v) => {
|
|
24508
|
+
const m = v.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
|
|
24509
|
+
if (!m) return [0, 0, 0, null];
|
|
24510
|
+
return [Number(m[1]), Number(m[2]), Number(m[3]), m[4] ?? null];
|
|
24511
|
+
};
|
|
24512
|
+
const [a1, a2, a3, aPre] = parse3(a);
|
|
24513
|
+
const [b1, b2, b3, bPre] = parse3(b);
|
|
24514
|
+
if (a1 !== b1) return a1 < b1 ? -1 : 1;
|
|
24515
|
+
if (a2 !== b2) return a2 < b2 ? -1 : 1;
|
|
24516
|
+
if (a3 !== b3) return a3 < b3 ? -1 : 1;
|
|
24517
|
+
if (aPre === bPre) return 0;
|
|
24518
|
+
if (aPre === null) return 1;
|
|
24519
|
+
if (bPre === null) return -1;
|
|
24520
|
+
return aPre < bPre ? -1 : 1;
|
|
24521
|
+
}
|
|
24522
|
+
async function fetchLatestVersion(fetcher = fetch, registryUrl = REGISTRY_URL, timeoutMs = 5e3) {
|
|
24523
|
+
try {
|
|
24524
|
+
const controller = new AbortController();
|
|
24525
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
24526
|
+
const response = await fetcher(registryUrl, { signal: controller.signal });
|
|
24527
|
+
clearTimeout(timer);
|
|
24528
|
+
if (!response.ok) {
|
|
24529
|
+
return { error: `Registry responded ${response.status}` };
|
|
24530
|
+
}
|
|
24531
|
+
const data = await response.json();
|
|
24532
|
+
if (!data.version || typeof data.version !== "string") {
|
|
24533
|
+
return { error: "Registry response missing version field" };
|
|
24534
|
+
}
|
|
24535
|
+
return { version: data.version };
|
|
24536
|
+
} catch (err) {
|
|
24537
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
24538
|
+
return { error: message };
|
|
24539
|
+
}
|
|
24540
|
+
}
|
|
24541
|
+
async function checkForUpdate(fetcher = fetch, registryUrl) {
|
|
24542
|
+
const currentVersion = getCurrentVersion();
|
|
24543
|
+
const latest = await fetchLatestVersion(fetcher, registryUrl);
|
|
24544
|
+
if ("error" in latest) {
|
|
24545
|
+
return {
|
|
24546
|
+
currentVersion,
|
|
24547
|
+
latestVersion: currentVersion,
|
|
24548
|
+
updateAvailable: false,
|
|
24549
|
+
error: latest.error
|
|
24550
|
+
};
|
|
24551
|
+
}
|
|
24552
|
+
const cmp = compareSemver(currentVersion, latest.version);
|
|
24553
|
+
return {
|
|
24554
|
+
currentVersion,
|
|
24555
|
+
latestVersion: latest.version,
|
|
24556
|
+
updateAvailable: cmp < 0
|
|
24557
|
+
};
|
|
24558
|
+
}
|
|
24559
|
+
async function performUpdate(packageName = "zelari-code", executor = spawn2) {
|
|
24560
|
+
return new Promise((resolve) => {
|
|
24561
|
+
const args = ["install", "-g", `${packageName}@latest`];
|
|
24562
|
+
let stdout = "";
|
|
24563
|
+
let stderr = "";
|
|
24564
|
+
const stdio = ["ignore", "pipe", "pipe"];
|
|
24565
|
+
const child = process.platform === "win32" ? executor(buildCmdLine("npm", args), { stdio, shell: true }) : executor("npm", args, { stdio });
|
|
24566
|
+
child.stdout?.on("data", (chunk) => {
|
|
24567
|
+
stdout += chunk.toString();
|
|
24568
|
+
});
|
|
24569
|
+
child.stderr?.on("data", (chunk) => {
|
|
24570
|
+
stderr += chunk.toString();
|
|
24571
|
+
});
|
|
24572
|
+
child.on("error", (err) => {
|
|
24573
|
+
resolve({
|
|
24574
|
+
ok: false,
|
|
24575
|
+
output: stdout + stderr,
|
|
24576
|
+
error: err.message,
|
|
24577
|
+
exitCode: null
|
|
24578
|
+
});
|
|
24579
|
+
});
|
|
24580
|
+
child.on("close", (code) => {
|
|
24581
|
+
const ok = code === 0;
|
|
24582
|
+
resolve({
|
|
24583
|
+
ok,
|
|
24584
|
+
output: stdout + stderr,
|
|
24585
|
+
error: ok ? void 0 : `npm exited with code ${code}`,
|
|
24586
|
+
exitCode: code
|
|
24587
|
+
});
|
|
24588
|
+
});
|
|
24589
|
+
});
|
|
24590
|
+
}
|
|
24591
|
+
var require2, __dirname2, REGISTRY_URL;
|
|
24592
|
+
var init_updater = __esm({
|
|
24593
|
+
"src/cli/updater.ts"() {
|
|
24594
|
+
"use strict";
|
|
24595
|
+
init_cmdline();
|
|
24596
|
+
require2 = createRequire(import.meta.url);
|
|
24597
|
+
__dirname2 = path15.dirname(fileURLToPath(import.meta.url));
|
|
24598
|
+
REGISTRY_URL = "https://registry.npmjs.org/zelari-code/latest";
|
|
24599
|
+
}
|
|
24600
|
+
});
|
|
24601
|
+
|
|
24602
|
+
// src/cli/mcp/mcpClient.ts
|
|
24603
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
24474
24604
|
var DEFAULT_REQUEST_TIMEOUT_MS, INIT_TIMEOUT_MS, MCP_PROTOCOL_VERSION, McpClient;
|
|
24475
24605
|
var init_mcpClient = __esm({
|
|
24476
24606
|
"src/cli/mcp/mcpClient.ts"() {
|
|
24477
24607
|
"use strict";
|
|
24478
24608
|
init_cmdline();
|
|
24609
|
+
init_updater();
|
|
24479
24610
|
DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
24480
24611
|
INIT_TIMEOUT_MS = 15e3;
|
|
24481
24612
|
MCP_PROTOCOL_VERSION = "2025-03-26";
|
|
@@ -24497,17 +24628,26 @@ var init_mcpClient = __esm({
|
|
|
24497
24628
|
env: { ...process.env, ...this.config.env ?? {} },
|
|
24498
24629
|
windowsHide: true
|
|
24499
24630
|
};
|
|
24500
|
-
const child = process.platform === "win32" ?
|
|
24631
|
+
const child = process.platform === "win32" ? spawn3(buildCmdLine(this.config.command, this.config.args ?? []), {
|
|
24501
24632
|
...spawnOpts,
|
|
24502
24633
|
shell: true
|
|
24503
|
-
}) :
|
|
24634
|
+
}) : spawn3(this.config.command, this.config.args ?? [], spawnOpts);
|
|
24504
24635
|
this.child = child;
|
|
24505
24636
|
child.stdout.setEncoding("utf8");
|
|
24506
24637
|
child.stdout.on("data", (chunk) => this.onStdout(chunk));
|
|
24507
|
-
child.on(
|
|
24638
|
+
child.on(
|
|
24639
|
+
"error",
|
|
24640
|
+
(err) => this.failAll(
|
|
24641
|
+
new Error(`[mcp:${this.serverName}] spawn failed: ${err.message}`)
|
|
24642
|
+
)
|
|
24643
|
+
);
|
|
24508
24644
|
child.on("exit", (code) => {
|
|
24509
24645
|
if (!this.closed) {
|
|
24510
|
-
this.failAll(
|
|
24646
|
+
this.failAll(
|
|
24647
|
+
new Error(
|
|
24648
|
+
`[mcp:${this.serverName}] server exited (code ${code ?? "null"})`
|
|
24649
|
+
)
|
|
24650
|
+
);
|
|
24511
24651
|
}
|
|
24512
24652
|
});
|
|
24513
24653
|
await this.request(
|
|
@@ -24515,7 +24655,7 @@ var init_mcpClient = __esm({
|
|
|
24515
24655
|
{
|
|
24516
24656
|
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
24517
24657
|
capabilities: {},
|
|
24518
|
-
clientInfo: { name: "zelari-code", version:
|
|
24658
|
+
clientInfo: { name: "zelari-code", version: getCurrentVersion() }
|
|
24519
24659
|
},
|
|
24520
24660
|
INIT_TIMEOUT_MS
|
|
24521
24661
|
);
|
|
@@ -24524,7 +24664,9 @@ var init_mcpClient = __esm({
|
|
|
24524
24664
|
/** Discover the server's tools. */
|
|
24525
24665
|
async listTools() {
|
|
24526
24666
|
const res = await this.request("tools/list", {});
|
|
24527
|
-
return (res.tools ?? []).filter(
|
|
24667
|
+
return (res.tools ?? []).filter(
|
|
24668
|
+
(t) => !!t.name
|
|
24669
|
+
).map((t) => ({
|
|
24528
24670
|
name: t.name,
|
|
24529
24671
|
description: t.description ?? "",
|
|
24530
24672
|
inputSchema: t.inputSchema ?? { type: "object", properties: {} }
|
|
@@ -24535,9 +24677,16 @@ var init_mcpClient = __esm({
|
|
|
24535
24677
|
* items are summarized by type. Throws when the server flags isError.
|
|
24536
24678
|
*/
|
|
24537
24679
|
async callTool(name, args, timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS) {
|
|
24538
|
-
const res = await this.request(
|
|
24539
|
-
|
|
24540
|
-
|
|
24680
|
+
const res = await this.request(
|
|
24681
|
+
"tools/call",
|
|
24682
|
+
{ name, arguments: args },
|
|
24683
|
+
timeoutMs
|
|
24684
|
+
);
|
|
24685
|
+
const text = (res.content ?? []).map(
|
|
24686
|
+
(c) => c.type === "text" && typeof c.text === "string" ? c.text : `[${c.type ?? "unknown"} content]`
|
|
24687
|
+
).join("\n");
|
|
24688
|
+
if (res.isError)
|
|
24689
|
+
throw new Error(text || `tool "${name}" reported an error`);
|
|
24541
24690
|
return text;
|
|
24542
24691
|
}
|
|
24543
24692
|
/** Terminate the server process and reject all in-flight requests. */
|
|
@@ -24550,13 +24699,18 @@ var init_mcpClient = __esm({
|
|
|
24550
24699
|
// ── JSON-RPC plumbing ────────────────────────────────────────────────
|
|
24551
24700
|
request(method, params, timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS) {
|
|
24552
24701
|
const child = this.child;
|
|
24553
|
-
if (!child)
|
|
24702
|
+
if (!child)
|
|
24703
|
+
return Promise.reject(new Error(`[mcp:${this.serverName}] not started`));
|
|
24554
24704
|
const id = this.nextId++;
|
|
24555
24705
|
const payload = JSON.stringify({ jsonrpc: "2.0", id, method, params });
|
|
24556
24706
|
return new Promise((resolve, reject) => {
|
|
24557
24707
|
const timer = setTimeout(() => {
|
|
24558
24708
|
this.pending.delete(id);
|
|
24559
|
-
reject(
|
|
24709
|
+
reject(
|
|
24710
|
+
new Error(
|
|
24711
|
+
`[mcp:${this.serverName}] ${method} timed out after ${timeoutMs}ms`
|
|
24712
|
+
)
|
|
24713
|
+
);
|
|
24560
24714
|
}, timeoutMs);
|
|
24561
24715
|
this.pending.set(id, { resolve, reject, timer });
|
|
24562
24716
|
child.stdin.write(payload + "\n", (err) => {
|
|
@@ -24569,7 +24723,9 @@ var init_mcpClient = __esm({
|
|
|
24569
24723
|
});
|
|
24570
24724
|
}
|
|
24571
24725
|
notify(method, params) {
|
|
24572
|
-
this.child?.stdin.write(
|
|
24726
|
+
this.child?.stdin.write(
|
|
24727
|
+
JSON.stringify({ jsonrpc: "2.0", method, params }) + "\n"
|
|
24728
|
+
);
|
|
24573
24729
|
}
|
|
24574
24730
|
onStdout(chunk) {
|
|
24575
24731
|
this.stdoutBuffer += chunk;
|
|
@@ -24590,7 +24746,11 @@ var init_mcpClient = __esm({
|
|
|
24590
24746
|
this.pending.delete(msg.id);
|
|
24591
24747
|
clearTimeout(pending.timer);
|
|
24592
24748
|
if (msg.error) {
|
|
24593
|
-
pending.reject(
|
|
24749
|
+
pending.reject(
|
|
24750
|
+
new Error(
|
|
24751
|
+
`[mcp:${this.serverName}] ${msg.error.message ?? "JSON-RPC error"} (code ${msg.error.code ?? "?"})`
|
|
24752
|
+
)
|
|
24753
|
+
);
|
|
24594
24754
|
} else {
|
|
24595
24755
|
pending.resolve(msg.result);
|
|
24596
24756
|
}
|
|
@@ -24868,10 +25028,10 @@ import { createHash as createHash2 } from "node:crypto";
|
|
|
24868
25028
|
import { join as join17 } from "node:path";
|
|
24869
25029
|
import { readFile } from "node:fs/promises";
|
|
24870
25030
|
async function readPackageJson2(projectRoot) {
|
|
24871
|
-
const
|
|
24872
|
-
if (!existsSync17(
|
|
25031
|
+
const path25 = join17(projectRoot, "package.json");
|
|
25032
|
+
if (!existsSync17(path25)) return null;
|
|
24873
25033
|
try {
|
|
24874
|
-
return JSON.parse(await readFile(
|
|
25034
|
+
return JSON.parse(await readFile(path25, "utf8"));
|
|
24875
25035
|
} catch {
|
|
24876
25036
|
return null;
|
|
24877
25037
|
}
|
|
@@ -24953,9 +25113,9 @@ async function genBuild(ctx) {
|
|
|
24953
25113
|
].join("\n");
|
|
24954
25114
|
}
|
|
24955
25115
|
async function genOpenQuestions(ctx) {
|
|
24956
|
-
const
|
|
24957
|
-
if (!existsSync17(
|
|
24958
|
-
const content = readFileSync17(
|
|
25116
|
+
const path25 = join17(ctx.rootDir, "risks.md");
|
|
25117
|
+
if (!existsSync17(path25)) return "_No open questions._";
|
|
25118
|
+
const content = readFileSync17(path25, "utf8");
|
|
24959
25119
|
const lines = content.split("\n");
|
|
24960
25120
|
const questions = [];
|
|
24961
25121
|
let currentTitle = "";
|
|
@@ -25200,7 +25360,7 @@ var init_completeDesign = __esm({
|
|
|
25200
25360
|
});
|
|
25201
25361
|
|
|
25202
25362
|
// src/cli/workspace/projectSmoke.ts
|
|
25203
|
-
import { spawn as
|
|
25363
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
25204
25364
|
import { existsSync as existsSync18, readFileSync as readFileSync18 } from "node:fs";
|
|
25205
25365
|
import { join as join18 } from "node:path";
|
|
25206
25366
|
function pickSmokeScript(scripts) {
|
|
@@ -25231,7 +25391,7 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
|
25231
25391
|
}
|
|
25232
25392
|
return await new Promise((resolveRun) => {
|
|
25233
25393
|
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
25234
|
-
const child =
|
|
25394
|
+
const child = spawn4(npmCmd, ["run", script], {
|
|
25235
25395
|
cwd: projectRoot,
|
|
25236
25396
|
stdio: ["ignore", "pipe", "pipe"],
|
|
25237
25397
|
env: process.env,
|
|
@@ -25303,7 +25463,7 @@ __export(postCouncilHook_exports, {
|
|
|
25303
25463
|
runImplementationVerificationHook: () => runImplementationVerificationHook,
|
|
25304
25464
|
runPostCouncilHook: () => runPostCouncilHook
|
|
25305
25465
|
});
|
|
25306
|
-
import { spawn as
|
|
25466
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
25307
25467
|
import { existsSync as existsSync19, readFileSync as readFileSync19 } from "node:fs";
|
|
25308
25468
|
import { join as join19 } from "node:path";
|
|
25309
25469
|
async function runCompleteDesignPostProcessor(ctx, options) {
|
|
@@ -25352,7 +25512,7 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
25352
25512
|
}
|
|
25353
25513
|
}
|
|
25354
25514
|
return await new Promise((resolveRun) => {
|
|
25355
|
-
const child =
|
|
25515
|
+
const child = spawn5(process.execPath, [scriptPath], {
|
|
25356
25516
|
cwd: ctx.projectRoot,
|
|
25357
25517
|
stdio: ["ignore", "pipe", "pipe"],
|
|
25358
25518
|
env: process.env
|
|
@@ -25518,8 +25678,8 @@ async function runPostCouncilHook(ctx, options) {
|
|
|
25518
25678
|
sources: scope.sources
|
|
25519
25679
|
} : void 0
|
|
25520
25680
|
});
|
|
25521
|
-
const
|
|
25522
|
-
completionHook = { ran: true, path:
|
|
25681
|
+
const path25 = writeCouncilCompletion(ctx.rootDir, completion);
|
|
25682
|
+
completionHook = { ran: true, path: path25, completion };
|
|
25523
25683
|
} catch (err) {
|
|
25524
25684
|
completionHook = {
|
|
25525
25685
|
ran: true,
|
|
@@ -25588,7 +25748,7 @@ import {
|
|
|
25588
25748
|
writeFileSync as writeFileSync14,
|
|
25589
25749
|
mkdirSync as mkdirSync9
|
|
25590
25750
|
} from "node:fs";
|
|
25591
|
-
import
|
|
25751
|
+
import path16 from "node:path";
|
|
25592
25752
|
import os7 from "node:os";
|
|
25593
25753
|
var FeedbackStore;
|
|
25594
25754
|
var init_councilFeedback = __esm({
|
|
@@ -25599,7 +25759,7 @@ var init_councilFeedback = __esm({
|
|
|
25599
25759
|
now;
|
|
25600
25760
|
entries = [];
|
|
25601
25761
|
constructor(options = {}) {
|
|
25602
|
-
this.file = options.file ?? (process.env.ANATHEMA_COUNCIL_FEEDBACK_FILE ??
|
|
25762
|
+
this.file = options.file ?? (process.env.ANATHEMA_COUNCIL_FEEDBACK_FILE ?? path16.join(os7.homedir(), ".tmp", "zelari-code", "council-feedback.json"));
|
|
25603
25763
|
this.now = options.now ?? Date.now;
|
|
25604
25764
|
this.load();
|
|
25605
25765
|
}
|
|
@@ -25705,7 +25865,7 @@ var init_councilFeedback = __esm({
|
|
|
25705
25865
|
}
|
|
25706
25866
|
}
|
|
25707
25867
|
save() {
|
|
25708
|
-
mkdirSync9(
|
|
25868
|
+
mkdirSync9(path16.dirname(this.file), { recursive: true });
|
|
25709
25869
|
writeFileSync14(
|
|
25710
25870
|
this.file,
|
|
25711
25871
|
JSON.stringify({ entries: this.entries }, null, 2),
|
|
@@ -25740,7 +25900,7 @@ __export(fileBackend_exports, {
|
|
|
25740
25900
|
});
|
|
25741
25901
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
25742
25902
|
import { promises as fs13 } from "node:fs";
|
|
25743
|
-
import * as
|
|
25903
|
+
import * as path17 from "node:path";
|
|
25744
25904
|
function tokenize(text) {
|
|
25745
25905
|
return text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 3);
|
|
25746
25906
|
}
|
|
@@ -25778,8 +25938,8 @@ var init_fileBackend = __esm({
|
|
|
25778
25938
|
logPath = "";
|
|
25779
25939
|
memoryDir = "";
|
|
25780
25940
|
async init(projectRoot) {
|
|
25781
|
-
this.memoryDir =
|
|
25782
|
-
this.logPath =
|
|
25941
|
+
this.memoryDir = path17.join(projectRoot, ".zelari", "memory");
|
|
25942
|
+
this.logPath = path17.join(this.memoryDir, "log.jsonl");
|
|
25783
25943
|
await fs13.mkdir(this.memoryDir, { recursive: true });
|
|
25784
25944
|
}
|
|
25785
25945
|
async add(content, metadata = {}, graph) {
|
|
@@ -25860,7 +26020,7 @@ __export(zelariMission_exports, {
|
|
|
25860
26020
|
});
|
|
25861
26021
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
25862
26022
|
import { promises as fs14 } from "node:fs";
|
|
25863
|
-
import * as
|
|
26023
|
+
import * as path18 from "node:path";
|
|
25864
26024
|
function resolveMaxIterations(env = process.env) {
|
|
25865
26025
|
const raw = env.ZELARI_MISSION_MAX_ITER;
|
|
25866
26026
|
const n = raw ? Number.parseInt(raw, 10) : DEFAULT_MAX_ITER;
|
|
@@ -25876,10 +26036,10 @@ function isMissionAutoStart(env = process.env) {
|
|
|
25876
26036
|
return env.ZELARI_MISSION_AUTO === "1";
|
|
25877
26037
|
}
|
|
25878
26038
|
async function writeMissionState(projectRoot, state2) {
|
|
25879
|
-
const dir =
|
|
26039
|
+
const dir = path18.join(projectRoot, ".zelari");
|
|
25880
26040
|
await fs14.mkdir(dir, { recursive: true });
|
|
25881
26041
|
await fs14.writeFile(
|
|
25882
|
-
|
|
26042
|
+
path18.join(dir, "mission-state.json"),
|
|
25883
26043
|
JSON.stringify(state2, null, 2) + "\n",
|
|
25884
26044
|
"utf8"
|
|
25885
26045
|
);
|
|
@@ -26007,122 +26167,249 @@ var init_zelariMission = __esm({
|
|
|
26007
26167
|
}
|
|
26008
26168
|
});
|
|
26009
26169
|
|
|
26010
|
-
// src/cli/
|
|
26011
|
-
var
|
|
26012
|
-
__export(
|
|
26013
|
-
|
|
26014
|
-
checkForUpdate: () => checkForUpdate,
|
|
26015
|
-
compareSemver: () => compareSemver,
|
|
26016
|
-
fetchLatestVersion: () => fetchLatestVersion,
|
|
26017
|
-
getCurrentVersion: () => getCurrentVersion,
|
|
26018
|
-
performUpdate: () => performUpdate
|
|
26170
|
+
// src/cli/utils/doctor.ts
|
|
26171
|
+
var doctor_exports = {};
|
|
26172
|
+
__export(doctor_exports, {
|
|
26173
|
+
runDoctor: () => runDoctor
|
|
26019
26174
|
});
|
|
26020
|
-
import {
|
|
26021
|
-
import {
|
|
26022
|
-
import
|
|
26023
|
-
import { fileURLToPath } from "node:url";
|
|
26024
|
-
|
|
26175
|
+
import { execSync } from "node:child_process";
|
|
26176
|
+
import { existsSync as existsSync26, readFileSync as readFileSync23, readlinkSync, statSync as statSync6 } from "node:fs";
|
|
26177
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
26178
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
26179
|
+
import path24 from "node:path";
|
|
26180
|
+
function findPackageRoot(start) {
|
|
26181
|
+
let dir = start;
|
|
26182
|
+
for (let i = 0; i < 6; i += 1) {
|
|
26183
|
+
const candidate = path24.join(dir, "package.json");
|
|
26184
|
+
if (existsSync26(candidate)) {
|
|
26185
|
+
try {
|
|
26186
|
+
const pkg = JSON.parse(readFileSync23(candidate, "utf8"));
|
|
26187
|
+
if (pkg.name === "zelari-code") return dir;
|
|
26188
|
+
} catch {
|
|
26189
|
+
}
|
|
26190
|
+
}
|
|
26191
|
+
const parent = path24.dirname(dir);
|
|
26192
|
+
if (parent === dir) break;
|
|
26193
|
+
dir = parent;
|
|
26194
|
+
}
|
|
26195
|
+
return path24.resolve(__dirname3, "..", "..", "..");
|
|
26196
|
+
}
|
|
26197
|
+
function tryExec(cmd) {
|
|
26025
26198
|
try {
|
|
26026
|
-
|
|
26027
|
-
|
|
26028
|
-
|
|
26199
|
+
return execSync(cmd, {
|
|
26200
|
+
encoding: "utf8",
|
|
26201
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
26202
|
+
}).trim();
|
|
26029
26203
|
} catch {
|
|
26030
|
-
return "
|
|
26204
|
+
return "";
|
|
26031
26205
|
}
|
|
26032
26206
|
}
|
|
26033
|
-
function
|
|
26034
|
-
|
|
26035
|
-
const
|
|
26036
|
-
|
|
26037
|
-
|
|
26038
|
-
|
|
26039
|
-
|
|
26040
|
-
const [b1, b2, b3, bPre] = parse3(b);
|
|
26041
|
-
if (a1 !== b1) return a1 < b1 ? -1 : 1;
|
|
26042
|
-
if (a2 !== b2) return a2 < b2 ? -1 : 1;
|
|
26043
|
-
if (a3 !== b3) return a3 < b3 ? -1 : 1;
|
|
26044
|
-
if (aPre === bPre) return 0;
|
|
26045
|
-
if (aPre === null) return 1;
|
|
26046
|
-
if (bPre === null) return -1;
|
|
26047
|
-
return aPre < bPre ? -1 : 1;
|
|
26207
|
+
function readPackageJson3() {
|
|
26208
|
+
try {
|
|
26209
|
+
const pkgPath = path24.join(packageRoot, "package.json");
|
|
26210
|
+
return JSON.parse(readFileSync23(pkgPath, "utf8"));
|
|
26211
|
+
} catch {
|
|
26212
|
+
return null;
|
|
26213
|
+
}
|
|
26048
26214
|
}
|
|
26049
|
-
|
|
26215
|
+
function getGlobalPrefix() {
|
|
26216
|
+
return (process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX || "").trim() || tryExec("npm prefix -g");
|
|
26217
|
+
}
|
|
26218
|
+
function checkShim(pkgName) {
|
|
26219
|
+
const prefix = getGlobalPrefix();
|
|
26220
|
+
if (!prefix) {
|
|
26221
|
+
return WARN("npm global prefix not detectable (run inside an npm context)");
|
|
26222
|
+
}
|
|
26223
|
+
const isWin = process.platform === "win32";
|
|
26224
|
+
const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
|
|
26225
|
+
const shimPath = path24.join(prefix, shimName);
|
|
26226
|
+
if (!existsSync26(shimPath)) {
|
|
26227
|
+
return FAIL(
|
|
26228
|
+
`shim not found at ${shimPath}
|
|
26229
|
+
fix: npm install -g ${pkgName}@latest --force`
|
|
26230
|
+
);
|
|
26231
|
+
}
|
|
26050
26232
|
try {
|
|
26051
|
-
const
|
|
26052
|
-
|
|
26053
|
-
|
|
26054
|
-
|
|
26055
|
-
|
|
26056
|
-
|
|
26233
|
+
const st = statSync6(shimPath);
|
|
26234
|
+
if (isWin) {
|
|
26235
|
+
const content = readFileSync23(shimPath, "utf8");
|
|
26236
|
+
if (content.includes(`${pkgName}\\bin\\`) || content.includes(`${pkgName}/bin/`)) {
|
|
26237
|
+
return OK(`shim OK at ${shimPath} (${st.size} bytes)`);
|
|
26238
|
+
}
|
|
26239
|
+
return FAIL(
|
|
26240
|
+
`shim at ${shimPath} does not reference ${pkgName}/bin/
|
|
26241
|
+
fix: npm install -g ${pkgName}@latest --force`
|
|
26242
|
+
);
|
|
26057
26243
|
}
|
|
26058
|
-
|
|
26059
|
-
|
|
26060
|
-
|
|
26244
|
+
let target;
|
|
26245
|
+
try {
|
|
26246
|
+
target = readlinkSync(shimPath);
|
|
26247
|
+
} catch {
|
|
26248
|
+
return FAIL(
|
|
26249
|
+
`shim at ${shimPath} is not a symlink (POSIX global installs should be symlinks)
|
|
26250
|
+
fix: npm install -g ${pkgName}@latest --force`
|
|
26251
|
+
);
|
|
26061
26252
|
}
|
|
26062
|
-
|
|
26253
|
+
const resolved = path24.resolve(path24.dirname(shimPath), target);
|
|
26254
|
+
const expected = path24.join(
|
|
26255
|
+
prefix,
|
|
26256
|
+
"node_modules",
|
|
26257
|
+
pkgName,
|
|
26258
|
+
"bin",
|
|
26259
|
+
"zelari-code.js"
|
|
26260
|
+
);
|
|
26261
|
+
if (resolved === expected) {
|
|
26262
|
+
return OK(`shim OK at ${shimPath} \u2192 ${resolved}`);
|
|
26263
|
+
}
|
|
26264
|
+
return FAIL(
|
|
26265
|
+
`shim at ${shimPath} points to ${resolved}
|
|
26266
|
+
expected ${expected}
|
|
26267
|
+
fix: npm install -g ${pkgName}@latest --force`
|
|
26268
|
+
);
|
|
26063
26269
|
} catch (err) {
|
|
26064
|
-
|
|
26065
|
-
|
|
26270
|
+
return FAIL(
|
|
26271
|
+
`could not inspect shim: ${err instanceof Error ? err.message : String(err)}`
|
|
26272
|
+
);
|
|
26066
26273
|
}
|
|
26067
26274
|
}
|
|
26068
|
-
|
|
26069
|
-
const
|
|
26070
|
-
|
|
26071
|
-
|
|
26072
|
-
return {
|
|
26073
|
-
currentVersion,
|
|
26074
|
-
latestVersion: currentVersion,
|
|
26075
|
-
updateAvailable: false,
|
|
26076
|
-
error: latest.error
|
|
26077
|
-
};
|
|
26275
|
+
function checkNode(pkg) {
|
|
26276
|
+
const raw = tryExec("node --version");
|
|
26277
|
+
if (!raw) {
|
|
26278
|
+
return FAIL("`node` not found on PATH");
|
|
26078
26279
|
}
|
|
26079
|
-
const
|
|
26080
|
-
|
|
26081
|
-
|
|
26082
|
-
|
|
26083
|
-
|
|
26084
|
-
|
|
26280
|
+
const m = raw.match(/^v?(\d+)\.(\d+)\.(\d+)/);
|
|
26281
|
+
if (!m) {
|
|
26282
|
+
return WARN(`could not parse node version: ${raw}`);
|
|
26283
|
+
}
|
|
26284
|
+
const major = Number(m[1]);
|
|
26285
|
+
if (major < 20) {
|
|
26286
|
+
return FAIL(
|
|
26287
|
+
`node ${raw} is older than the required engines.node (>= 20.0.0)`
|
|
26288
|
+
);
|
|
26289
|
+
}
|
|
26290
|
+
return OK(`node ${raw}`);
|
|
26085
26291
|
}
|
|
26086
|
-
|
|
26087
|
-
|
|
26088
|
-
|
|
26089
|
-
|
|
26090
|
-
|
|
26091
|
-
|
|
26092
|
-
|
|
26093
|
-
|
|
26094
|
-
|
|
26095
|
-
|
|
26096
|
-
|
|
26097
|
-
|
|
26292
|
+
function checkBundle() {
|
|
26293
|
+
const bundle = path24.join(packageRoot, "dist", "cli", "main.bundled.js");
|
|
26294
|
+
if (!existsSync26(bundle)) {
|
|
26295
|
+
return FAIL(
|
|
26296
|
+
`dist/cli/main.bundled.js missing at ${bundle}
|
|
26297
|
+
fix: npm run build:cli (then reinstall or run via tsx)`
|
|
26298
|
+
);
|
|
26299
|
+
}
|
|
26300
|
+
try {
|
|
26301
|
+
const st = statSync6(bundle);
|
|
26302
|
+
return OK(`bundle OK (${(st.size / 1024 / 1024).toFixed(2)} MB)`);
|
|
26303
|
+
} catch (err) {
|
|
26304
|
+
return FAIL(
|
|
26305
|
+
`could not stat bundle: ${err instanceof Error ? err.message : String(err)}`
|
|
26306
|
+
);
|
|
26307
|
+
}
|
|
26308
|
+
}
|
|
26309
|
+
function checkRuntimeDeps() {
|
|
26310
|
+
const required2 = ["react", "react-dom", "ink", "ink-text-input", "zod"];
|
|
26311
|
+
const missing = [];
|
|
26312
|
+
for (const dep of required2) {
|
|
26313
|
+
try {
|
|
26314
|
+
const localReq = createRequire2(path24.join(packageRoot, "package.json"));
|
|
26315
|
+
localReq.resolve(dep);
|
|
26316
|
+
} catch {
|
|
26317
|
+
missing.push(dep);
|
|
26318
|
+
}
|
|
26319
|
+
}
|
|
26320
|
+
if (missing.length === 0) {
|
|
26321
|
+
return OK(
|
|
26322
|
+
"runtime deps resolvable (react, react-dom, ink, ink-text-input, zod)"
|
|
26323
|
+
);
|
|
26324
|
+
}
|
|
26325
|
+
return FAIL(
|
|
26326
|
+
`missing runtime deps: ${missing.join(", ")}
|
|
26327
|
+
fix: npm install -g ${"<pkg>"} --force (then reopen the terminal)`
|
|
26328
|
+
);
|
|
26329
|
+
}
|
|
26330
|
+
function checkPath() {
|
|
26331
|
+
const prefix = getGlobalPrefix();
|
|
26332
|
+
if (!prefix) return WARN("npm global prefix not detectable");
|
|
26333
|
+
const pathSep = process.platform === "win32" ? ";" : ":";
|
|
26334
|
+
const pathDirs = (process.env.PATH || "").split(pathSep);
|
|
26335
|
+
if (pathDirs.includes(prefix)) {
|
|
26336
|
+
return OK(`PATH includes npm prefix (${prefix})`);
|
|
26337
|
+
}
|
|
26338
|
+
return WARN(
|
|
26339
|
+
`PATH does not include npm prefix (${prefix})
|
|
26340
|
+
symptom: "zelari-code: command not found" after install
|
|
26341
|
+
fix (POSIX): export PATH="$(npm prefix -g)/bin:$PATH"
|
|
26342
|
+
fix (Windows): $env:Path = "$(npm prefix -g);$env:Path"`
|
|
26343
|
+
);
|
|
26344
|
+
}
|
|
26345
|
+
function runDoctor() {
|
|
26346
|
+
const pkg = readPackageJson3();
|
|
26347
|
+
const pkgName = pkg?.name ?? "zelari-code";
|
|
26348
|
+
const checks = [
|
|
26349
|
+
{ name: "node", run: () => checkNode(pkg) },
|
|
26350
|
+
{ name: "bin shim", run: () => checkShim(pkgName) },
|
|
26351
|
+
{ name: "cli bundle", run: () => checkBundle() },
|
|
26352
|
+
{ name: "runtime deps", run: () => checkRuntimeDeps() },
|
|
26353
|
+
{ name: "PATH", run: () => checkPath() }
|
|
26354
|
+
];
|
|
26355
|
+
console.log(`zelari-code doctor (v${pkg?.version ?? "unknown"})`);
|
|
26356
|
+
console.log("platform:", process.platform, process.arch);
|
|
26357
|
+
console.log("node: ", process.version);
|
|
26358
|
+
console.log("prefix: ", getGlobalPrefix() || "(unknown)");
|
|
26359
|
+
console.log("root: ", packageRoot);
|
|
26360
|
+
console.log("");
|
|
26361
|
+
let criticalFails = 0;
|
|
26362
|
+
let warns = 0;
|
|
26363
|
+
for (const c of checks) {
|
|
26364
|
+
let result;
|
|
26365
|
+
try {
|
|
26366
|
+
result = c.run();
|
|
26367
|
+
} catch (err) {
|
|
26368
|
+
result = FAIL(
|
|
26369
|
+
`unexpected error: ${err instanceof Error ? err.message : String(err)}`
|
|
26370
|
+
);
|
|
26371
|
+
}
|
|
26372
|
+
const tag = result.ok ? "OK " : result.severity === "critical" ? "FAIL" : "WARN";
|
|
26373
|
+
const color = result.ok ? "\x1B[32m" : result.severity === "critical" ? "\x1B[31m" : "\x1B[33m";
|
|
26374
|
+
const reset = "\x1B[0m";
|
|
26375
|
+
console.log(
|
|
26376
|
+
` ${color}${tag}${reset} ${c.name.padEnd(14)}${result.message.replace(/\n/g, "\n ")}`
|
|
26377
|
+
);
|
|
26378
|
+
if (!result.ok) {
|
|
26379
|
+
if (result.severity === "critical") criticalFails += 1;
|
|
26380
|
+
else warns += 1;
|
|
26381
|
+
}
|
|
26382
|
+
}
|
|
26383
|
+
console.log("");
|
|
26384
|
+
if (criticalFails === 0 && warns === 0) {
|
|
26385
|
+
console.log("\x1B[32m\u2714 all checks passed\x1B[0m");
|
|
26386
|
+
return true;
|
|
26387
|
+
}
|
|
26388
|
+
console.log(`\u2717 ${criticalFails} critical failure(s), ${warns} warning(s)`);
|
|
26389
|
+
return criticalFails === 0;
|
|
26390
|
+
}
|
|
26391
|
+
var require3, __dirname3, packageRoot, OK, FAIL, WARN;
|
|
26392
|
+
var init_doctor = __esm({
|
|
26393
|
+
"src/cli/utils/doctor.ts"() {
|
|
26394
|
+
"use strict";
|
|
26395
|
+
require3 = createRequire2(import.meta.url);
|
|
26396
|
+
__dirname3 = path24.dirname(fileURLToPath2(import.meta.url));
|
|
26397
|
+
packageRoot = findPackageRoot(__dirname3);
|
|
26398
|
+
OK = (message) => ({
|
|
26399
|
+
ok: true,
|
|
26400
|
+
message,
|
|
26401
|
+
severity: "critical"
|
|
26098
26402
|
});
|
|
26099
|
-
|
|
26100
|
-
|
|
26101
|
-
|
|
26102
|
-
|
|
26103
|
-
error: err.message,
|
|
26104
|
-
exitCode: null
|
|
26105
|
-
});
|
|
26403
|
+
FAIL = (message, severity = "critical") => ({
|
|
26404
|
+
ok: false,
|
|
26405
|
+
message,
|
|
26406
|
+
severity
|
|
26106
26407
|
});
|
|
26107
|
-
|
|
26108
|
-
|
|
26109
|
-
|
|
26110
|
-
|
|
26111
|
-
output: stdout + stderr,
|
|
26112
|
-
error: ok ? void 0 : `npm exited with code ${code}`,
|
|
26113
|
-
exitCode: code
|
|
26114
|
-
});
|
|
26408
|
+
WARN = (message) => ({
|
|
26409
|
+
ok: false,
|
|
26410
|
+
message,
|
|
26411
|
+
severity: "warn"
|
|
26115
26412
|
});
|
|
26116
|
-
});
|
|
26117
|
-
}
|
|
26118
|
-
var require2, __dirname2, REGISTRY_URL;
|
|
26119
|
-
var init_updater = __esm({
|
|
26120
|
-
"src/cli/updater.ts"() {
|
|
26121
|
-
"use strict";
|
|
26122
|
-
init_cmdline();
|
|
26123
|
-
require2 = createRequire(import.meta.url);
|
|
26124
|
-
__dirname2 = path19.dirname(fileURLToPath(import.meta.url));
|
|
26125
|
-
REGISTRY_URL = "https://registry.npmjs.org/zelari-code/latest";
|
|
26126
26413
|
}
|
|
26127
26414
|
});
|
|
26128
26415
|
|
|
@@ -31448,7 +31735,7 @@ ${formatSkillList(availableSkills)}`
|
|
|
31448
31735
|
// src/cli/gitOps.ts
|
|
31449
31736
|
import { execFile as execFile2 } from "node:child_process";
|
|
31450
31737
|
import { promisify } from "node:util";
|
|
31451
|
-
import
|
|
31738
|
+
import path19 from "node:path";
|
|
31452
31739
|
var execFileAsync = promisify(execFile2);
|
|
31453
31740
|
async function git(cwd, args) {
|
|
31454
31741
|
try {
|
|
@@ -31494,7 +31781,7 @@ async function undoWorkingChanges(opts = {}) {
|
|
|
31494
31781
|
};
|
|
31495
31782
|
}
|
|
31496
31783
|
function defaultProjectRoot() {
|
|
31497
|
-
return
|
|
31784
|
+
return path19.resolve(__dirname, "..", "..", "..");
|
|
31498
31785
|
}
|
|
31499
31786
|
|
|
31500
31787
|
// src/cli/slashHandlers/git.ts
|
|
@@ -31599,14 +31886,23 @@ async function handleUpdateCheck(ctx) {
|
|
|
31599
31886
|
Run \`/update --yes\` to install. You'll need to restart manually after.`
|
|
31600
31887
|
);
|
|
31601
31888
|
} else {
|
|
31602
|
-
appendSystem(
|
|
31889
|
+
appendSystem(
|
|
31890
|
+
ctx.setMessages,
|
|
31891
|
+
`[update] up to date (${info.currentVersion})`
|
|
31892
|
+
);
|
|
31603
31893
|
}
|
|
31604
31894
|
} catch (err) {
|
|
31605
|
-
appendSystem(
|
|
31895
|
+
appendSystem(
|
|
31896
|
+
ctx.setMessages,
|
|
31897
|
+
`[update error] ${err instanceof Error ? err.message : String(err)}`
|
|
31898
|
+
);
|
|
31606
31899
|
}
|
|
31607
31900
|
}
|
|
31608
31901
|
async function handleUpdatePerform(ctx) {
|
|
31609
|
-
appendSystem(
|
|
31902
|
+
appendSystem(
|
|
31903
|
+
ctx.setMessages,
|
|
31904
|
+
"[update] running `npm install -g zelari-code@latest`..."
|
|
31905
|
+
);
|
|
31610
31906
|
try {
|
|
31611
31907
|
const { performUpdate: performUpdate2 } = await Promise.resolve().then(() => (init_updater(), updater_exports));
|
|
31612
31908
|
const res = await performUpdate2();
|
|
@@ -31619,18 +31915,48 @@ Please restart zelari-code manually to use the new version.
|
|
|
31619
31915
|
(exit with /exit or Ctrl+C, then run \`zelari-code\` again)`
|
|
31620
31916
|
);
|
|
31621
31917
|
} else {
|
|
31918
|
+
const output = res.output?.trim() || "(empty)";
|
|
31919
|
+
const hint = buildUpdateFailureHint(
|
|
31920
|
+
res.error ?? "",
|
|
31921
|
+
output,
|
|
31922
|
+
res.exitCode
|
|
31923
|
+
);
|
|
31622
31924
|
appendSystem(
|
|
31623
31925
|
ctx.setMessages,
|
|
31624
31926
|
`[update] \u274C failed: ${res.error ?? "unknown error"}
|
|
31927
|
+
exit code: ${res.exitCode ?? "n/a"}
|
|
31625
31928
|
|
|
31626
31929
|
npm output:
|
|
31627
|
-
${
|
|
31930
|
+
${output}
|
|
31931
|
+
|
|
31932
|
+
` + hint
|
|
31628
31933
|
);
|
|
31629
31934
|
}
|
|
31630
31935
|
} catch (err) {
|
|
31631
|
-
appendSystem(
|
|
31936
|
+
appendSystem(
|
|
31937
|
+
ctx.setMessages,
|
|
31938
|
+
`[update error] ${err instanceof Error ? err.message : String(err)}`
|
|
31939
|
+
);
|
|
31632
31940
|
}
|
|
31633
31941
|
}
|
|
31942
|
+
function buildUpdateFailureHint(error51, output, exitCode) {
|
|
31943
|
+
const haystack = `${error51}
|
|
31944
|
+
${output}`.toLowerCase();
|
|
31945
|
+
const isWin = process.platform === "win32";
|
|
31946
|
+
if (haystack.includes("eresolve") || haystack.includes("epeerinvalid") || haystack.includes("peer dep")) {
|
|
31947
|
+
return "\u{1F4A1} hint: peer-dependency conflict. Try:\n npm install -g zelari-code@latest --legacy-peer-deps\n or: npm install -g zelari-code@latest --force";
|
|
31948
|
+
}
|
|
31949
|
+
if (haystack.includes("eacces") || haystack.includes("eperm")) {
|
|
31950
|
+
return "\u{1F4A1} hint: permission denied. On macOS/Linux, avoid sudo with npm:\n https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally\n On Windows, re-run the terminal as Administrator.";
|
|
31951
|
+
}
|
|
31952
|
+
if (haystack.includes("enoent") && haystack.includes("npm")) {
|
|
31953
|
+
return '\u{1F4A1} hint: `npm` was not found on PATH for the spawned shell.\n Re-open the terminal so it picks up your current PATH, or set:\n export PATH="$(npm prefix -g)/bin:$PATH" (POSIX)\n $env:Path = "$(npm prefix -g);$env:Path" (PowerShell)';
|
|
31954
|
+
}
|
|
31955
|
+
if (haystack.includes("zelari-code") && (haystack.includes("not found") || haystack.includes("eexist") || haystack.includes("ebusy") || haystack.includes("shim") || exitCode === 0)) {
|
|
31956
|
+
return "\u{1F4A1} hint: the install may have completed but the global bin shim\n is missing or stale (common on Windows + npm 10/11 after major\n upgrades). To repair:\n npm install -g zelari-code@latest --force\n Then re-open the terminal. If `zelari-code` is still not found,\n run the doctor: `zelari-code doctor`";
|
|
31957
|
+
}
|
|
31958
|
+
return "\u{1F4A1} hint: the install did not succeed. To retry with more detail:\n npm install -g zelari-code@latest --verbose 2>&1 | tail -40\n On Windows, also try: `npm install -g zelari-code@latest --force`\n" + (isWin ? " Run `zelari-code doctor` from a new terminal to diagnose shim / PATH issues.\n" : "");
|
|
31959
|
+
}
|
|
31634
31960
|
|
|
31635
31961
|
// src/cli/slashHandlers/promoteMember.ts
|
|
31636
31962
|
import { promises as fs15 } from "node:fs";
|
|
@@ -33827,7 +34153,8 @@ function loadSkillMdSkills(projectRoot = process.cwd(), options = {}) {
|
|
|
33827
34153
|
|
|
33828
34154
|
// src/cli/main.ts
|
|
33829
34155
|
init_skills2();
|
|
33830
|
-
|
|
34156
|
+
init_updater();
|
|
34157
|
+
var VERSION = getCurrentVersion();
|
|
33831
34158
|
async function backgroundUpdateCheck() {
|
|
33832
34159
|
if (process.env.ANATHEMA_DEV === "1") return;
|
|
33833
34160
|
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
@@ -33860,9 +34187,14 @@ function pickRootComponent() {
|
|
|
33860
34187
|
console.log(`zelari-code v${VERSION}`);
|
|
33861
34188
|
process.exit(0);
|
|
33862
34189
|
}
|
|
34190
|
+
if (argv.includes("--doctor") || argv.includes("doctor")) {
|
|
34191
|
+
const { runDoctor: runDoctor2 } = (init_doctor(), __toCommonJS(doctor_exports));
|
|
34192
|
+
const healthy = runDoctor2();
|
|
34193
|
+
process.exit(healthy ? 0 : 1);
|
|
34194
|
+
}
|
|
33863
34195
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
33864
34196
|
console.log(
|
|
33865
|
-
"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 --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 --council Use the 6-member council pipeline\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ANATHEMA_DEV=1 Disable background update check\n"
|
|
34197
|
+
"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 --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 --council Use the 6-member council pipeline\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ANATHEMA_DEV=1 Disable background update check\n"
|
|
33866
34198
|
);
|
|
33867
34199
|
process.exit(0);
|
|
33868
34200
|
}
|
|
@@ -33887,7 +34219,11 @@ function pickRootComponent() {
|
|
|
33887
34219
|
}
|
|
33888
34220
|
return {
|
|
33889
34221
|
kind: "app",
|
|
33890
|
-
element: React13.createElement(
|
|
34222
|
+
element: React13.createElement(
|
|
34223
|
+
SplashGate,
|
|
34224
|
+
{ version: VERSION },
|
|
34225
|
+
React13.createElement(App)
|
|
34226
|
+
)
|
|
33891
34227
|
};
|
|
33892
34228
|
}
|
|
33893
34229
|
function loadUserSkills() {
|
|
@@ -33895,7 +34231,9 @@ function loadUserSkills() {
|
|
|
33895
34231
|
const existing = new Set(listCodingSkills().map((s) => s.id));
|
|
33896
34232
|
const summary = loadSkillMdSkills(process.cwd(), { existingIds: existing });
|
|
33897
34233
|
if (summary.loaded.length > 0) {
|
|
33898
|
-
console.error(
|
|
34234
|
+
console.error(
|
|
34235
|
+
`[zelari-code] loaded ${summary.loaded.length} SKILL.md skill(s): ${summary.loaded.join(", ")}`
|
|
34236
|
+
);
|
|
33899
34237
|
}
|
|
33900
34238
|
for (const s of summary.skipped) {
|
|
33901
34239
|
console.error(`[zelari-code] skipped SKILL.md at ${s.path}: ${s.reason}`);
|