zelari-code 1.3.0 → 1.5.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/README.md +67 -3
- package/dist/cli/components/PluginGate.js +195 -0
- package/dist/cli/components/PluginGate.js.map +1 -0
- package/dist/cli/diagnostics/engine.js +2 -10
- package/dist/cli/diagnostics/engine.js.map +1 -1
- package/dist/cli/hooks/useSlashDispatch.js +17 -0
- package/dist/cli/hooks/useSlashDispatch.js.map +1 -1
- package/dist/cli/lsp/tools.js +3 -12
- package/dist/cli/lsp/tools.js.map +1 -1
- package/dist/cli/main.bundled.js +1460 -551
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +124 -6
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/plugins/installer.js +103 -0
- package/dist/cli/plugins/installer.js.map +1 -0
- package/dist/cli/plugins/prefs.js +96 -0
- package/dist/cli/plugins/prefs.js.map +1 -0
- package/dist/cli/plugins/registry.js +209 -0
- package/dist/cli/plugins/registry.js.map +1 -0
- package/dist/cli/slashCommands.js +18 -1
- package/dist/cli/slashCommands.js.map +1 -1
- package/dist/cli/slashHandlers/plugins.js +75 -0
- package/dist/cli/slashHandlers/plugins.js.map +1 -0
- package/dist/cli/slashHandlers/updater.js +27 -3
- package/dist/cli/slashHandlers/updater.js.map +1 -1
- package/dist/cli/updater.js +1 -1
- package/dist/cli/updater.js.map +1 -1
- package/dist/cli/utils/doctor.js +66 -4
- package/dist/cli/utils/doctor.js.map +1 -1
- package/dist/cli/utils/fixPath.js +119 -0
- package/dist/cli/utils/fixPath.js.map +1 -0
- package/dist/cli/utils/paths.js +47 -0
- package/dist/cli/utils/paths.js.map +1 -1
- package/dist/cli/utils/prereqChecks.js +362 -0
- package/dist/cli/utils/prereqChecks.js.map +1 -0
- package/package.json +4 -2
- package/scripts/diagnose-path.ps1 +22 -0
- package/scripts/dump-path.ps1 +13 -0
- package/scripts/fix-path.ps1 +26 -0
- package/scripts/path-length.ps1 +15 -0
- package/scripts/postinstall.mjs +78 -1
- package/scripts/repair-path.mjs +104 -0
package/dist/cli/utils/paths.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { homedir } from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
2
3
|
/**
|
|
3
4
|
* shortenCwd — compact a directory path for one-line UI surfaces
|
|
4
5
|
* (StatusBar, banner).
|
|
@@ -17,4 +18,50 @@ export function shortenCwd(p, maxLen = 40, home = homedir()) {
|
|
|
17
18
|
return out;
|
|
18
19
|
return `…${out.slice(-(maxLen - 1))}`;
|
|
19
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* relativePosix — relativize a path against a root and normalize to `/`.
|
|
23
|
+
*
|
|
24
|
+
* Why: `path.relative()` on win32 joins segments with backslashes. Every
|
|
25
|
+
* agent-facing surface (LSP tool results, diagnostic output) wants forward
|
|
26
|
+
* slashes — they match `file://` URIs, JSON, markdown, and every other path
|
|
27
|
+
* already shown to the model. Before this helper, two near-identical private
|
|
28
|
+
* functions (`relPath` in lsp/tools.ts, `relative` in diagnostics/engine.ts)
|
|
29
|
+
* called `path.relative` with zero normalization, producing `src\a.ts` on
|
|
30
|
+
* Windows where the rest of the output stream uses `src/a.ts`.
|
|
31
|
+
*
|
|
32
|
+
* Semantics:
|
|
33
|
+
* - Returns the relative path when `to` is inside `from`.
|
|
34
|
+
* - Returns `to` unchanged when it escapes the root (`..` traversal) or the
|
|
35
|
+
* relativization fails, so absolute paths outside the project are shown
|
|
36
|
+
* as-is rather than as a misleading `..\..\elsewhere`.
|
|
37
|
+
* - Output always uses `/` regardless of platform separator.
|
|
38
|
+
*
|
|
39
|
+
* Not for: filesystem I/O (platform-native separators matter there) or URI
|
|
40
|
+
* construction (see lsp/protocol.ts `pathToUri`, which also percent-encodes).
|
|
41
|
+
*
|
|
42
|
+
* @param from Anchor directory (typically the project root).
|
|
43
|
+
* @param to Target file or directory (absolute, or already relative).
|
|
44
|
+
* @returns POSIX-style relative path, or `to` if it can't be relativized.
|
|
45
|
+
*/
|
|
46
|
+
export function relativePosix(from, to) {
|
|
47
|
+
try {
|
|
48
|
+
// Use the platform-specific path module explicitly rather than the
|
|
49
|
+
// default export. The default is bound to process.platform AT MODULE
|
|
50
|
+
// LOAD TIME — mutating process.platform later (e.g. in a test that
|
|
51
|
+
// simulates win32 on a Linux runner) does NOT rebind it, so
|
|
52
|
+
// path.relative would use posix semantics and fail on Windows paths.
|
|
53
|
+
// path.win32 / path.posix are stable platform-specific namespaces that
|
|
54
|
+
// work regardless of the host platform.
|
|
55
|
+
const p = process.platform === 'win32' ? path.win32 : path.posix;
|
|
56
|
+
const rel = p.relative(from, to);
|
|
57
|
+
if (!rel || rel.startsWith('..'))
|
|
58
|
+
return to;
|
|
59
|
+
// Normalize any platform separator to forward slashes. On win32 path.relative
|
|
60
|
+
// joins with '\\'; on POSIX it's already '/'. Either way, split on both.
|
|
61
|
+
return rel.split(/[\\/]/).join('/');
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return to;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
20
67
|
//# sourceMappingURL=paths.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/cli/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/cli/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,CAAS,EAAE,MAAM,GAAG,EAAE,EAAE,OAAe,OAAO,EAAE;IACzE,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IACE,IAAI;QACJ,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,EAC3E,CAAC;QACD,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IACrC,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,GAAG,CAAC;IACrC,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;AACxC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,EAAU;IACpD,IAAI,CAAC;QACH,mEAAmE;QACnE,qEAAqE;QACrE,mEAAmE;QACnE,4DAA4D;QAC5D,qEAAqE;QACrE,uEAAuE;QACvE,wCAAwC;QACxC,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;QACjE,MAAM,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,CAAC;QAC5C,8EAA8E;QAC9E,yEAAyE;QACzE,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prereqChecks.ts — prerequisite detection that mirrors the agent's shell.
|
|
3
|
+
*
|
|
4
|
+
* Why this exists separately from `doctor.ts`:
|
|
5
|
+
* The legacy `checkNode()` in doctor.ts probes `node --version` from the
|
|
6
|
+
* zelari-code main process. On Windows that main process is a native Node
|
|
7
|
+
* binary whose PATH always contains node (otherwise zelari-code wouldn't
|
|
8
|
+
* be running). But the AGENT — the thing that actually runs `npm`,
|
|
9
|
+
* `tsc`, build scripts — launches commands through the resolved shell
|
|
10
|
+
* (Git Bash on Windows, see `resolveShell()` in shellResolver.ts), which
|
|
11
|
+
* inherits a DIFFERENT PATH. A user can have node visible to the main
|
|
12
|
+
* process yet invisible to the agent's bash (e.g. Node installed for
|
|
13
|
+
* "current user" only, while Git Bash inherits the system PATH). The
|
|
14
|
+
* legacy doctor check passes in that case and never warns — until the
|
|
15
|
+
* agent tries `npm run build` and gets `node: not found`, mid-task.
|
|
16
|
+
*
|
|
17
|
+
* These checks probe THROUGH the same shell the agent will use, so they
|
|
18
|
+
* detect the real mismatch before it bites. They power:
|
|
19
|
+
* - the boot-time preflight (src/cli/main.ts `runPreflight`),
|
|
20
|
+
* - the `--doctor` "agent shell" rows (src/cli/utils/doctor.ts),
|
|
21
|
+
* - the post-update prerequisite warnings (slashHandlers/updater.ts).
|
|
22
|
+
*
|
|
23
|
+
* Design contract (inherited from doctor.ts):
|
|
24
|
+
* - NEVER throws. Every check catches its own errors and returns a
|
|
25
|
+
* FAIL/WARN result. A broken prereq check must never crash the CLI.
|
|
26
|
+
* - Sync API: doctor's `run()` loop is sync and we keep that shape.
|
|
27
|
+
* - No dependency on @zelari/core: the bash-resolution chain is
|
|
28
|
+
* replicated here (see `resolveAgentShellSync` below) so this module
|
|
29
|
+
* works even when the core bundle is broken — which is exactly when a
|
|
30
|
+
* user needs `--doctor` to diagnose the breakage.
|
|
31
|
+
*
|
|
32
|
+
* @see packages/core/src/core/tools/builtin/shellResolver.ts — the canonical
|
|
33
|
+
* resolver; keep `resolveAgentShellSync` in sync with its detection chain.
|
|
34
|
+
* @see src/cli/utils/doctor.ts — the opt-in `zelari-code doctor` command.
|
|
35
|
+
*/
|
|
36
|
+
import { execSync, spawnSync } from "node:child_process";
|
|
37
|
+
import { existsSync } from "node:fs";
|
|
38
|
+
/** Minimum Node major version (mirrors `engines.node` ">=20.0.0" in package.json). */
|
|
39
|
+
const MIN_NODE_MAJOR = 20;
|
|
40
|
+
/** Standard Git for Windows bash locations (mirrors shellResolver.STANDARD_BASH_PATHS). */
|
|
41
|
+
const STANDARD_BASH_PATHS = [
|
|
42
|
+
"C:\\Program Files\\Git\\bin\\bash.exe",
|
|
43
|
+
"C:\\Program Files\\Git\\usr\\bin\\bash.exe",
|
|
44
|
+
"C:\\Program Files (x86)\\Git\\bin\\bash.exe",
|
|
45
|
+
"C:\\Program Files (x86)\\Git\\usr\\bin\\bash.exe",
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Resolve the shell the agent will use — SYNC version of `resolveShell()`.
|
|
49
|
+
*
|
|
50
|
+
* Replicated (not imported) so this module has no runtime dependency on
|
|
51
|
+
* @zelari/core. The detection order MUST stay in lockstep with
|
|
52
|
+
* `packages/core/src/core/tools/builtin/shellResolver.ts:resolveBashWindows`:
|
|
53
|
+
* 1. ZELARI_SHELL env var (explicit override)
|
|
54
|
+
* 2. SHELL env var (set by Git Bash / MSYS2 sessions)
|
|
55
|
+
* 3. Standard Git for Windows install paths (existsSync probe)
|
|
56
|
+
* 4. `where bash` (PATH lookup)
|
|
57
|
+
* 5. Fallback: cmd.exe on win32, /bin/sh on POSIX
|
|
58
|
+
*/
|
|
59
|
+
function resolveAgentShellSync() {
|
|
60
|
+
// POSIX: Node's `shell: true` already uses /bin/sh — bash-compatible enough.
|
|
61
|
+
if (process.platform !== "win32") {
|
|
62
|
+
return { bashPath: null, isBash: true, via: "/bin/sh" };
|
|
63
|
+
}
|
|
64
|
+
// 1. Explicit override.
|
|
65
|
+
const envShell = process.env.ZELARI_SHELL;
|
|
66
|
+
if (envShell && envShell.trim().length > 0 && existsSyncSafe(envShell)) {
|
|
67
|
+
return { bashPath: envShell, isBash: true, via: `bash (${envShell})` };
|
|
68
|
+
}
|
|
69
|
+
// 2. SHELL env var (Git Bash / MSYS2 sessions).
|
|
70
|
+
const sessionShell = process.env.SHELL;
|
|
71
|
+
if (sessionShell &&
|
|
72
|
+
sessionShell.trim().length > 0 &&
|
|
73
|
+
existsSyncSafe(sessionShell)) {
|
|
74
|
+
return {
|
|
75
|
+
bashPath: sessionShell,
|
|
76
|
+
isBash: true,
|
|
77
|
+
via: `bash (${sessionShell})`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// 3. Standard install paths.
|
|
81
|
+
for (const p of STANDARD_BASH_PATHS) {
|
|
82
|
+
if (existsSyncSafe(p)) {
|
|
83
|
+
return { bashPath: p, isBash: true, via: `bash (${p})` };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// 4. `where bash` — PATH lookup. `where` ships with Windows as a real .exe.
|
|
87
|
+
try {
|
|
88
|
+
const result = spawnSync("where", ["bash"], {
|
|
89
|
+
encoding: "utf8",
|
|
90
|
+
windowsHide: true,
|
|
91
|
+
});
|
|
92
|
+
if (result.status === 0 && result.stdout) {
|
|
93
|
+
const first = result.stdout
|
|
94
|
+
.split(/\r?\n/)
|
|
95
|
+
.find((l) => l.trim().length > 0);
|
|
96
|
+
if (first && existsSyncSafe(first)) {
|
|
97
|
+
const trimmed = first.trim();
|
|
98
|
+
return { bashPath: trimmed, isBash: true, via: `bash (${trimmed})` };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// `where` unavailable or failed — fall through to cmd.exe.
|
|
104
|
+
}
|
|
105
|
+
// 5. Fallback: cmd.exe. POSIX commands (ls, which, $VAR) may fail here.
|
|
106
|
+
return { bashPath: null, isBash: false, via: "cmd.exe" };
|
|
107
|
+
}
|
|
108
|
+
/** existsSync that swallows edge-case errors (invalid chars on win32, etc.). */
|
|
109
|
+
function existsSyncSafe(p) {
|
|
110
|
+
try {
|
|
111
|
+
return existsSync(p);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Probe `<tool> --version` through the agent's resolved shell.
|
|
119
|
+
*
|
|
120
|
+
* Returns the raw stdout (trimmed) and parsed semver, or empty strings when
|
|
121
|
+
* the tool isn't reachable. Never throws.
|
|
122
|
+
*/
|
|
123
|
+
function probeTool(tool) {
|
|
124
|
+
const shell = resolveAgentShellSync();
|
|
125
|
+
let stdout = "";
|
|
126
|
+
if (shell.bashPath) {
|
|
127
|
+
// Real bash (win32 Git Bash or explicit ZELARI_SHELL): spawn directly
|
|
128
|
+
// with `-c` so we get the EXACT environment the agent's `bash` tool
|
|
129
|
+
// gets — this is what catches the "node visible to main, invisible to
|
|
130
|
+
// bash" mismatch.
|
|
131
|
+
try {
|
|
132
|
+
const r = spawnSync(shell.bashPath, ["-c", `${tool} --version`], {
|
|
133
|
+
encoding: "utf8",
|
|
134
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
135
|
+
windowsHide: true,
|
|
136
|
+
});
|
|
137
|
+
if (r.status === 0)
|
|
138
|
+
stdout = (r.stdout || "").trim();
|
|
139
|
+
// status !== 0 means the tool isn't on bash's PATH (or errored) — leave stdout empty.
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// spawn failure (e.g. bashPath stale) — fall through to empty.
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (process.platform === "win32") {
|
|
146
|
+
// cmd.exe fallback (no Git Bash found). execSync with shell:true → cmd.exe.
|
|
147
|
+
try {
|
|
148
|
+
stdout = execSync(`${tool} --version`, {
|
|
149
|
+
encoding: "utf8",
|
|
150
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
151
|
+
}).trim();
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// not on cmd's PATH either
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
// POSIX non-bash (shouldn't happen — resolveAgentShellSync returns isBash:true on POSIX).
|
|
159
|
+
try {
|
|
160
|
+
stdout = execSync(`${tool} --version`, {
|
|
161
|
+
encoding: "utf8",
|
|
162
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
163
|
+
}).trim();
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// ignore
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const m = stdout.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
170
|
+
return {
|
|
171
|
+
found: stdout.length > 0,
|
|
172
|
+
version: m ? `${m[1]}.${m[2]}.${m[3]}` : "",
|
|
173
|
+
raw: stdout,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Actionable fix hint when node isn't visible to the agent shell.
|
|
178
|
+
* OS-specific because the root cause differs (system vs user PATH on Windows;
|
|
179
|
+
* nvm symlink on macOS/Linux; missing install entirely).
|
|
180
|
+
*/
|
|
181
|
+
function nodeMissingHint() {
|
|
182
|
+
const shell = resolveAgentShellSync();
|
|
183
|
+
if (process.platform === "win32") {
|
|
184
|
+
return (`node is not reachable from the agent's shell (${shell.via}).\n` +
|
|
185
|
+
` This usually means Node was installed for "current user" only,\n` +
|
|
186
|
+
` while Git Bash inherits the SYSTEM Path. Fix (pick one):\n` +
|
|
187
|
+
` - Reinstall Node (https://nodejs.org) and choose\n` +
|
|
188
|
+
` "Add to PATH for all users", OR\n` +
|
|
189
|
+
` - Add C:\\Program Files\\nodejs\\ to the SYSTEM Path\n` +
|
|
190
|
+
` (System Properties → Environment Variables → Path), OR\n` +
|
|
191
|
+
` - Set ZELARI_SHELL to a bash that already sees node.`);
|
|
192
|
+
}
|
|
193
|
+
return (`node is not on the agent's shell PATH.\n` +
|
|
194
|
+
` Install Node >= ${MIN_NODE_MAJOR} (https://nodejs.org) or, if you use\n` +
|
|
195
|
+
` nvm, run \`nvm use <version>\` and reopen this terminal.`);
|
|
196
|
+
}
|
|
197
|
+
/** Check `node` is reachable from the agent shell and meets the minimum version. */
|
|
198
|
+
export function checkAgentNode() {
|
|
199
|
+
const probe = probeTool("node");
|
|
200
|
+
if (!probe.found) {
|
|
201
|
+
return {
|
|
202
|
+
ok: false,
|
|
203
|
+
severity: "critical",
|
|
204
|
+
tool: "node",
|
|
205
|
+
message: nodeMissingHint(),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const major = Number(probe.version.split(".")[0]);
|
|
209
|
+
if (!probe.version || Number.isNaN(major)) {
|
|
210
|
+
// node IS on PATH but version string looks weird — degrade to warn, don't hard-fail.
|
|
211
|
+
return {
|
|
212
|
+
ok: false,
|
|
213
|
+
severity: "warn",
|
|
214
|
+
tool: "node",
|
|
215
|
+
message: `could not parse node version from "${probe.raw}" (node is reachable, but version check skipped)`,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
if (major < MIN_NODE_MAJOR) {
|
|
219
|
+
return {
|
|
220
|
+
ok: false,
|
|
221
|
+
severity: "critical",
|
|
222
|
+
tool: "node",
|
|
223
|
+
message: `node ${probe.version} is older than the required >= ${MIN_NODE_MAJOR}.0.0 (from engines.node). Upgrade: https://nodejs.org`,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
ok: true,
|
|
228
|
+
severity: "critical",
|
|
229
|
+
tool: "node",
|
|
230
|
+
message: `node ${probe.version} (agent shell)`,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/** Check `git` is reachable from the agent shell. Soft prereq (warn, not block). */
|
|
234
|
+
export function checkAgentGit() {
|
|
235
|
+
const probe = probeTool("git");
|
|
236
|
+
if (!probe.found) {
|
|
237
|
+
const hint = process.platform === "win32"
|
|
238
|
+
? `Install Git for Windows: https://git-scm.com/download/win`
|
|
239
|
+
: `Install git (e.g. \`brew install git\` on macOS, \`apt install git\` on Debian)`;
|
|
240
|
+
return {
|
|
241
|
+
ok: false,
|
|
242
|
+
severity: "warn",
|
|
243
|
+
tool: "git",
|
|
244
|
+
message: `git not found on the agent's shell PATH — /diff, /undo and the git sidebar will be disabled. ${hint}`,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
ok: true,
|
|
249
|
+
severity: "warn",
|
|
250
|
+
tool: "git",
|
|
251
|
+
message: `git ${probe.version} (agent shell)`,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Check that a real bash is available on Windows. When the resolver falls
|
|
256
|
+
* back to cmd.exe, POSIX commands (`ls`, `which`, `$VAR`, `&&`) will fail
|
|
257
|
+
* inside the agent's `bash` tool — confusing and hard to debug. Warn only.
|
|
258
|
+
*/
|
|
259
|
+
export function checkAgentBash() {
|
|
260
|
+
if (process.platform !== "win32") {
|
|
261
|
+
return {
|
|
262
|
+
ok: true,
|
|
263
|
+
severity: "warn",
|
|
264
|
+
tool: "bash",
|
|
265
|
+
message: "POSIX shell always available on this platform",
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
const shell = resolveAgentShellSync();
|
|
269
|
+
if (shell.isBash) {
|
|
270
|
+
return {
|
|
271
|
+
ok: true,
|
|
272
|
+
severity: "warn",
|
|
273
|
+
tool: "bash",
|
|
274
|
+
message: `real bash available (${shell.via})`,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
ok: false,
|
|
279
|
+
severity: "warn",
|
|
280
|
+
tool: "bash",
|
|
281
|
+
message: `no Git Bash found — the agent's \`bash\` tool falls back to cmd.exe,\n` +
|
|
282
|
+
` where POSIX commands (ls, which, $VAR, &&) may fail. Install Git\n` +
|
|
283
|
+
` for Windows (https://git-scm.com/download/win) or set ZELARI_SHELL\n` +
|
|
284
|
+
` to your bash binary.`,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Probe `node --version` from the zelari-code main process (NOT the agent
|
|
289
|
+
* shell). Kept for differential diagnostics: if this passes but
|
|
290
|
+
* `checkAgentNode` fails, the problem is a PATH mismatch between the main
|
|
291
|
+
* process and the agent's bash — not a missing Node install.
|
|
292
|
+
*/
|
|
293
|
+
export function checkMainNode() {
|
|
294
|
+
try {
|
|
295
|
+
const raw = execSync("node --version", {
|
|
296
|
+
encoding: "utf8",
|
|
297
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
298
|
+
}).trim();
|
|
299
|
+
const m = raw.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
300
|
+
const version = m ? `${m[1]}.${m[2]}.${m[3]}` : "";
|
|
301
|
+
const major = Number(version.split(".")[0]);
|
|
302
|
+
if (version && !Number.isNaN(major) && major >= MIN_NODE_MAJOR) {
|
|
303
|
+
return {
|
|
304
|
+
ok: true,
|
|
305
|
+
severity: "critical",
|
|
306
|
+
tool: "node",
|
|
307
|
+
message: `node ${version} (main process)`,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
ok: false,
|
|
312
|
+
severity: "warn",
|
|
313
|
+
tool: "node",
|
|
314
|
+
message: `node present in main process but version unparseable or < ${MIN_NODE_MAJOR}: "${raw}"`,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
return {
|
|
319
|
+
ok: false,
|
|
320
|
+
severity: "critical",
|
|
321
|
+
tool: "node",
|
|
322
|
+
message: "node not found on the main process PATH (zelari-code itself runs on node — this is unexpected)",
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Run all prerequisite checks and aggregate. Never throws.
|
|
328
|
+
*
|
|
329
|
+
* @param opts.mode 'preflight' = boot-time gate (node critical, git/bash warn);
|
|
330
|
+
* 'full' = same checks, used by `--doctor` for the full report.
|
|
331
|
+
* Currently identical; the flag is reserved for future
|
|
332
|
+
* heavier checks that shouldn't run on every boot.
|
|
333
|
+
*/
|
|
334
|
+
export function runPrereqChecks(opts = { mode: "preflight" }) {
|
|
335
|
+
const checks = [
|
|
336
|
+
() => checkAgentNode(),
|
|
337
|
+
() => checkAgentGit(),
|
|
338
|
+
() => checkAgentBash(),
|
|
339
|
+
];
|
|
340
|
+
const results = [];
|
|
341
|
+
for (const run of checks) {
|
|
342
|
+
try {
|
|
343
|
+
results.push(run());
|
|
344
|
+
}
|
|
345
|
+
catch (err) {
|
|
346
|
+
// Defensive: a check throwing is itself a failure, never a crash.
|
|
347
|
+
results.push({
|
|
348
|
+
ok: false,
|
|
349
|
+
severity: "warn",
|
|
350
|
+
tool: "node",
|
|
351
|
+
message: `prereq check crashed: ${err instanceof Error ? err.message : String(err)}`,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
const hasCriticalFail = results.some((r) => !r.ok && r.severity === "critical");
|
|
356
|
+
const warnings = results.filter((r) => !r.ok && r.severity === "warn");
|
|
357
|
+
// Reference opts.mode so it stays meaningful even while behaviour is identical
|
|
358
|
+
// across modes today (reserved for future full-only checks).
|
|
359
|
+
void opts.mode;
|
|
360
|
+
return { results, hasCriticalFail, warnings };
|
|
361
|
+
}
|
|
362
|
+
//# sourceMappingURL=prereqChecks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prereqChecks.js","sourceRoot":"","sources":["../../../src/cli/utils/prereqChecks.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zelari-code",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Zelari Code — AI Council coding agent CLI. Multi-agent orchestration (Caronte, Nettuno, Gerione, Plutone, Minosse, Lucifero) with slash commands, provider-agnostic LLM streaming, and self-update.",
|
|
5
5
|
"author": "N-THEM Studio",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
"bin",
|
|
17
17
|
"dist",
|
|
18
18
|
"scripts/postinstall.mjs",
|
|
19
|
+
"scripts/repair-path.mjs",
|
|
20
|
+
"scripts/*.ps1",
|
|
19
21
|
"LICENSE",
|
|
20
22
|
"README.md",
|
|
21
23
|
"package.json"
|
|
@@ -45,7 +47,7 @@
|
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
|
47
49
|
"@testing-library/react": "^16.3.2",
|
|
48
|
-
"@zelari/core": "1.
|
|
50
|
+
"@zelari/core": "1.5.0",
|
|
49
51
|
"@types/node": "^25.3.0",
|
|
50
52
|
"@types/react": "^19.0.10",
|
|
51
53
|
"esbuild": "^0.25.0",
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
$prefix = (npm config get prefix).Trim()
|
|
2
|
+
Write-Host "npm prefix: $prefix"
|
|
3
|
+
Write-Host ""
|
|
4
|
+
Write-Host "=== Session PATH (npm-related) ==="
|
|
5
|
+
$env:Path -split ';' | Where-Object { $_ -and ($_ -match 'npm' -or $_ -eq $prefix) }
|
|
6
|
+
Write-Host ""
|
|
7
|
+
Write-Host "=== User PATH (npm-related) ==="
|
|
8
|
+
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
9
|
+
$userPath -split ';' | Where-Object { $_ -and ($_ -match 'npm' -or $_ -eq $prefix) }
|
|
10
|
+
Write-Host ""
|
|
11
|
+
Write-Host "=== Machine PATH (npm-related) ==="
|
|
12
|
+
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'Machine')
|
|
13
|
+
$machinePath -split ';' | Where-Object { $_ -and ($_ -match 'npm' -or $_ -eq $prefix) }
|
|
14
|
+
Write-Host ""
|
|
15
|
+
Write-Host "=== Shims in prefix ==="
|
|
16
|
+
Get-ChildItem "$prefix\zelari-code*" -ErrorAction SilentlyContinue | Select-Object Name, FullName
|
|
17
|
+
Write-Host ""
|
|
18
|
+
Write-Host "=== where.exe zelari-code ==="
|
|
19
|
+
where.exe zelari-code 2>&1
|
|
20
|
+
Write-Host ""
|
|
21
|
+
Write-Host "=== Direct run ==="
|
|
22
|
+
& "$prefix\zelari-code.cmd" --version
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
2
|
+
Write-Host "User PATH length: $($userPath.Length)"
|
|
3
|
+
Write-Host "Contains Z:\npm-global: $($userPath -like '*Z:\npm-global*')"
|
|
4
|
+
Write-Host ""
|
|
5
|
+
Write-Host "=== All User PATH entries ==="
|
|
6
|
+
$i = 0
|
|
7
|
+
$userPath -split ';' | ForEach-Object {
|
|
8
|
+
if ($_) { Write-Host ("{0,3}: [{1}]" -f $i++, $_) }
|
|
9
|
+
}
|
|
10
|
+
Write-Host ""
|
|
11
|
+
Write-Host "=== Fresh merged PATH simulation ==="
|
|
12
|
+
$merged = [Environment]::GetEnvironmentVariable('Path', 'Machine') + ';' + $userPath
|
|
13
|
+
$merged -split ';' | Where-Object { $_ -match 'npm' -or $_ -eq 'Z:\npm-global' }
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Ensures npm global prefix is on the user PATH and reloads PATH in this session.
|
|
2
|
+
$prefix = (npm config get prefix).Trim()
|
|
3
|
+
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
4
|
+
|
|
5
|
+
if ($userPath -notlike "*$prefix*") {
|
|
6
|
+
$updated = if ($userPath) { "$userPath;$prefix" } else { $prefix }
|
|
7
|
+
[Environment]::SetEnvironmentVariable('Path', $updated, 'User')
|
|
8
|
+
Write-Host "PATH aggiornato (registry): aggiunto $prefix"
|
|
9
|
+
} else {
|
|
10
|
+
Write-Host "PATH registry gia contiene: $prefix"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
# Reload full PATH from registry into this session (fixes stale terminals).
|
|
14
|
+
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'Machine')
|
|
15
|
+
$freshUserPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
16
|
+
$env:Path = "$machinePath;$freshUserPath"
|
|
17
|
+
|
|
18
|
+
Write-Host ""
|
|
19
|
+
Write-Host "Verifica:"
|
|
20
|
+
where.exe zelari-code 2>$null
|
|
21
|
+
if ($LASTEXITCODE -ne 0) {
|
|
22
|
+
Write-Error "zelari-code non trovato. Esegui: npm link (dalla root del repo)"
|
|
23
|
+
exit 1
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
zelari-code --version
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
$machine = [Environment]::GetEnvironmentVariable('Path', 'Machine')
|
|
2
|
+
$user = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
3
|
+
$merged = "$machine;$user"
|
|
4
|
+
Write-Host "Machine PATH length: $($machine.Length)"
|
|
5
|
+
Write-Host "User PATH length: $($user.Length)"
|
|
6
|
+
Write-Host "Merged PATH length: $($merged.Length)"
|
|
7
|
+
Write-Host "Session PATH length: $($env:Path.Length)"
|
|
8
|
+
Write-Host ""
|
|
9
|
+
Write-Host "Session has Z:\npm-global: $($env:Path -like '*Z:\npm-global*')"
|
|
10
|
+
Write-Host ""
|
|
11
|
+
# Count entries in session vs expected
|
|
12
|
+
$sessionEntries = ($env:Path -split ';' | Where-Object { $_ }).Count
|
|
13
|
+
$mergedEntries = ($merged -split ';' | Where-Object { $_ }).Count
|
|
14
|
+
Write-Host "Session entries: $sessionEntries"
|
|
15
|
+
Write-Host "Merged entries: $mergedEntries"
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -41,6 +41,13 @@ import {
|
|
|
41
41
|
import { fileURLToPath } from 'node:url';
|
|
42
42
|
import path from 'node:path';
|
|
43
43
|
|
|
44
|
+
// Re-exported so existing imports (`import { repairWindowsPath } from
|
|
45
|
+
// './postinstall.mjs'`) keep working. The implementation lives in
|
|
46
|
+
// repair-path.mjs, which has no install-time side effects and is safe to
|
|
47
|
+
// import in unit tests.
|
|
48
|
+
import { repairWindowsPath } from './repair-path.mjs';
|
|
49
|
+
export { repairWindowsPath };
|
|
50
|
+
|
|
44
51
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
45
52
|
const pkgRoot = path.resolve(__dirname, '..');
|
|
46
53
|
|
|
@@ -163,6 +170,29 @@ function repairWindowsShim(prefix, pkgName) {
|
|
|
163
170
|
return cmdWritten;
|
|
164
171
|
}
|
|
165
172
|
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Thin wrapper around repairWindowsPath for the postinstall flow.
|
|
176
|
+
*
|
|
177
|
+
* Logs one of three outcomes (auto-fixed / already-ok / failed-but-continue)
|
|
178
|
+
* so the user understands what happened. Always non-fatal: a PATH write
|
|
179
|
+
* failure still leaves the install in a working state (the shim exists);
|
|
180
|
+
* the user can repair manually via `zelari-code --fix-path` later.
|
|
181
|
+
*
|
|
182
|
+
* @param {string} prefix npm global prefix
|
|
183
|
+
*/
|
|
184
|
+
function ensureWindowsPath(prefix) {
|
|
185
|
+
if (process.platform !== 'win32') return;
|
|
186
|
+
const repaired = repairWindowsPath(prefix);
|
|
187
|
+
if (repaired) {
|
|
188
|
+
note(`added ${prefix} to the user PATH`);
|
|
189
|
+
note('open a NEW terminal for the change to take effect, then run `zelari-code --version`.');
|
|
190
|
+
}
|
|
191
|
+
// already-present or failed: silent on already-present (expected, common),
|
|
192
|
+
// and silent on failure because the warning block below covers the
|
|
193
|
+
// "command not found" symptom if it later bites the user.
|
|
194
|
+
}
|
|
195
|
+
|
|
166
196
|
const warn = (msg) => {
|
|
167
197
|
// eslint-disable-next-line no-console
|
|
168
198
|
console.warn(`[zelari-code postinstall] ${msg}`);
|
|
@@ -173,6 +203,49 @@ const note = (msg) => {
|
|
|
173
203
|
console.warn(`[zelari-code postinstall] ${msg}`);
|
|
174
204
|
};
|
|
175
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Best-effort git availability check (v1.4.0).
|
|
208
|
+
*
|
|
209
|
+
* git is not a hard prerequisite (zelari-code boots without it), but /diff,
|
|
210
|
+
* /undo and the live git sidebar all silently degrade to no-op when git is
|
|
211
|
+
* missing — which is confusing. Surface it once at install/update time so
|
|
212
|
+
* the user knows what they're missing and how to fix it. Node is NOT checked
|
|
213
|
+
* here: by definition npm (which requires node) just ran this script.
|
|
214
|
+
*
|
|
215
|
+
* Non-blocking, fail-safe: any error is swallowed. Mirrors the contract of
|
|
216
|
+
* the rest of this file (never throw, never fail the install).
|
|
217
|
+
*/
|
|
218
|
+
function checkGitAvailable() {
|
|
219
|
+
try {
|
|
220
|
+
let out = '';
|
|
221
|
+
try {
|
|
222
|
+
out = execSync('git --version', {
|
|
223
|
+
encoding: 'utf8',
|
|
224
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
225
|
+
}).trim();
|
|
226
|
+
} catch {
|
|
227
|
+
// git not on PATH — fall through to the warning below.
|
|
228
|
+
}
|
|
229
|
+
if (!out) {
|
|
230
|
+
const hint =
|
|
231
|
+
process.platform === 'win32'
|
|
232
|
+
? 'Install Git for Windows: https://git-scm.com/download/win'
|
|
233
|
+
: process.platform === 'darwin'
|
|
234
|
+
? 'Install git: `brew install git` (or Xcode command-line tools)'
|
|
235
|
+
: 'Install git: `apt install git` (or your distro equivalent)';
|
|
236
|
+
warn('--------------------------------------------------------------');
|
|
237
|
+
warn(' git not found on PATH (optional but recommended).');
|
|
238
|
+
warn('--------------------------------------------------------------');
|
|
239
|
+
warn(' Without git, /diff, /undo and the git sidebar are disabled.');
|
|
240
|
+
warn(` ${hint}`);
|
|
241
|
+
warn(' Run `zelari-code --doctor` after install to re-check.');
|
|
242
|
+
warn('--------------------------------------------------------------');
|
|
243
|
+
}
|
|
244
|
+
} catch {
|
|
245
|
+
// Even the check itself must never break the install.
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
176
249
|
try {
|
|
177
250
|
// 0. Only run for global installs. Local installs (`npm install zelari-code`)
|
|
178
251
|
// create a `node_modules/.bin/zelari-code` symlink that npm handles
|
|
@@ -224,11 +297,13 @@ try {
|
|
|
224
297
|
// Auto-repair the most common Windows failure: the package unpacked but
|
|
225
298
|
// npm never created the bin shim. We only write shims that are MISSING,
|
|
226
299
|
// and only under our own bin name → no risk of shadowing another tool.
|
|
227
|
-
|
|
300
|
+
if (isWin) {
|
|
228
301
|
const repaired = repairWindowsShim(prefix, pkgName);
|
|
229
302
|
if (repaired && existsSync(shimPath)) {
|
|
230
303
|
note(`shim was missing — auto-created ${shimPath}`);
|
|
304
|
+
ensureWindowsPath(prefix);
|
|
231
305
|
note('open a NEW terminal and run `zelari-code --version` to confirm.');
|
|
306
|
+
checkGitAvailable();
|
|
232
307
|
process.exit(0);
|
|
233
308
|
}
|
|
234
309
|
}
|
|
@@ -279,6 +354,8 @@ try {
|
|
|
279
354
|
|
|
280
355
|
if (shimOk) {
|
|
281
356
|
note(`shim OK: ${shimPath}`);
|
|
357
|
+
ensureWindowsPath(prefix);
|
|
358
|
+
checkGitAvailable();
|
|
282
359
|
process.exit(0);
|
|
283
360
|
}
|
|
284
361
|
|