zelari-code 1.2.0 → 1.4.1

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.
Files changed (53) hide show
  1. package/README.md +67 -3
  2. package/dist/cli/app.js +3 -1
  3. package/dist/cli/app.js.map +1 -1
  4. package/dist/cli/ast/engine.js +126 -0
  5. package/dist/cli/ast/engine.js.map +1 -0
  6. package/dist/cli/ast/tools.js +71 -0
  7. package/dist/cli/ast/tools.js.map +1 -0
  8. package/dist/cli/browser/driver.js +125 -0
  9. package/dist/cli/browser/driver.js.map +1 -0
  10. package/dist/cli/browser/tools.js +71 -0
  11. package/dist/cli/browser/tools.js.map +1 -0
  12. package/dist/cli/hooks/useSlashDispatch.js +33 -2
  13. package/dist/cli/hooks/useSlashDispatch.js.map +1 -1
  14. package/dist/cli/lsp/client.js +89 -0
  15. package/dist/cli/lsp/client.js.map +1 -0
  16. package/dist/cli/lsp/manager.js +287 -0
  17. package/dist/cli/lsp/manager.js.map +1 -0
  18. package/dist/cli/lsp/protocol.js +83 -0
  19. package/dist/cli/lsp/protocol.js.map +1 -0
  20. package/dist/cli/lsp/servers.js +80 -0
  21. package/dist/cli/lsp/servers.js.map +1 -0
  22. package/dist/cli/lsp/tools.js +125 -0
  23. package/dist/cli/lsp/tools.js.map +1 -0
  24. package/dist/cli/main.bundled.js +1884 -281
  25. package/dist/cli/main.bundled.js.map +4 -4
  26. package/dist/cli/main.js +75 -3
  27. package/dist/cli/main.js.map +1 -1
  28. package/dist/cli/mode.js +32 -0
  29. package/dist/cli/mode.js.map +1 -0
  30. package/dist/cli/semantic/embeddings.js +71 -0
  31. package/dist/cli/semantic/embeddings.js.map +1 -0
  32. package/dist/cli/semantic/index.js +147 -0
  33. package/dist/cli/semantic/index.js.map +1 -0
  34. package/dist/cli/semantic/provider.js +29 -0
  35. package/dist/cli/semantic/provider.js.map +1 -0
  36. package/dist/cli/semantic/store.js +71 -0
  37. package/dist/cli/semantic/store.js.map +1 -0
  38. package/dist/cli/semantic/tools.js +54 -0
  39. package/dist/cli/semantic/tools.js.map +1 -0
  40. package/dist/cli/slashCommands.js +22 -1
  41. package/dist/cli/slashCommands.js.map +1 -1
  42. package/dist/cli/slashHandlers/semantic.js +37 -0
  43. package/dist/cli/slashHandlers/semantic.js.map +1 -0
  44. package/dist/cli/slashHandlers/updater.js +27 -3
  45. package/dist/cli/slashHandlers/updater.js.map +1 -1
  46. package/dist/cli/toolRegistry.js +50 -0
  47. package/dist/cli/toolRegistry.js.map +1 -1
  48. package/dist/cli/utils/doctor.js +23 -0
  49. package/dist/cli/utils/doctor.js.map +1 -1
  50. package/dist/cli/utils/prereqChecks.js +362 -0
  51. package/dist/cli/utils/prereqChecks.js.map +1 -0
  52. package/package.json +3 -3
  53. package/scripts/postinstall.mjs +46 -1
@@ -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.2.0",
3
+ "version": "1.4.1",
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",
@@ -40,17 +40,17 @@
40
40
  "ink": "^6.8.0",
41
41
  "ink-text-input": "^6.0.0",
42
42
  "react": "^19.2.7",
43
+ "typescript": "~5.7.2",
43
44
  "zod": "^4.4.3"
44
45
  },
45
46
  "devDependencies": {
46
47
  "@testing-library/react": "^16.3.2",
47
- "@zelari/core": "1.2.0",
48
+ "@zelari/core": "1.4.1",
48
49
  "@types/node": "^25.3.0",
49
50
  "@types/react": "^19.0.10",
50
51
  "esbuild": "^0.25.0",
51
52
  "jsdom": "^29.1.1",
52
53
  "react-dom": "^19.2.7",
53
- "typescript": "~5.7.2",
54
54
  "vitest": "^4.1.9"
55
55
  },
56
56
  "keywords": [
@@ -173,6 +173,49 @@ const note = (msg) => {
173
173
  console.warn(`[zelari-code postinstall] ${msg}`);
174
174
  };
175
175
 
176
+ /**
177
+ * Best-effort git availability check (v1.4.0).
178
+ *
179
+ * git is not a hard prerequisite (zelari-code boots without it), but /diff,
180
+ * /undo and the live git sidebar all silently degrade to no-op when git is
181
+ * missing — which is confusing. Surface it once at install/update time so
182
+ * the user knows what they're missing and how to fix it. Node is NOT checked
183
+ * here: by definition npm (which requires node) just ran this script.
184
+ *
185
+ * Non-blocking, fail-safe: any error is swallowed. Mirrors the contract of
186
+ * the rest of this file (never throw, never fail the install).
187
+ */
188
+ function checkGitAvailable() {
189
+ try {
190
+ let out = '';
191
+ try {
192
+ out = execSync('git --version', {
193
+ encoding: 'utf8',
194
+ stdio: ['ignore', 'pipe', 'ignore'],
195
+ }).trim();
196
+ } catch {
197
+ // git not on PATH — fall through to the warning below.
198
+ }
199
+ if (!out) {
200
+ const hint =
201
+ process.platform === 'win32'
202
+ ? 'Install Git for Windows: https://git-scm.com/download/win'
203
+ : process.platform === 'darwin'
204
+ ? 'Install git: `brew install git` (or Xcode command-line tools)'
205
+ : 'Install git: `apt install git` (or your distro equivalent)';
206
+ warn('--------------------------------------------------------------');
207
+ warn(' git not found on PATH (optional but recommended).');
208
+ warn('--------------------------------------------------------------');
209
+ warn(' Without git, /diff, /undo and the git sidebar are disabled.');
210
+ warn(` ${hint}`);
211
+ warn(' Run `zelari-code --doctor` after install to re-check.');
212
+ warn('--------------------------------------------------------------');
213
+ }
214
+ } catch {
215
+ // Even the check itself must never break the install.
216
+ }
217
+ }
218
+
176
219
  try {
177
220
  // 0. Only run for global installs. Local installs (`npm install zelari-code`)
178
221
  // create a `node_modules/.bin/zelari-code` symlink that npm handles
@@ -224,11 +267,12 @@ try {
224
267
  // Auto-repair the most common Windows failure: the package unpacked but
225
268
  // npm never created the bin shim. We only write shims that are MISSING,
226
269
  // and only under our own bin name → no risk of shadowing another tool.
227
- if (isWin) {
270
+ if (isWin) {
228
271
  const repaired = repairWindowsShim(prefix, pkgName);
229
272
  if (repaired && existsSync(shimPath)) {
230
273
  note(`shim was missing — auto-created ${shimPath}`);
231
274
  note('open a NEW terminal and run `zelari-code --version` to confirm.');
275
+ checkGitAvailable();
232
276
  process.exit(0);
233
277
  }
234
278
  }
@@ -279,6 +323,7 @@ try {
279
323
 
280
324
  if (shimOk) {
281
325
  note(`shim OK: ${shimPath}`);
326
+ checkGitAvailable();
282
327
  process.exit(0);
283
328
  }
284
329