zelari-code 1.4.1 → 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/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 +1141 -545
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +49 -3
- 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/updater.js +1 -1
- package/dist/cli/updater.js.map +1 -1
- package/dist/cli/utils/doctor.js +43 -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/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 +32 -0
- package/scripts/repair-path.mjs +104 -0
package/dist/cli/main.js
CHANGED
|
@@ -8,6 +8,7 @@ import { render } from "ink";
|
|
|
8
8
|
// @ts-ignore
|
|
9
9
|
import { App } from "./app.js";
|
|
10
10
|
import { SplashGate } from "./components/SplashScreen.js";
|
|
11
|
+
import { PluginGate } from "./components/PluginGate.js";
|
|
11
12
|
import { getMetricsLogger } from "./metrics.js";
|
|
12
13
|
import { getProviderConfigPath } from "./providerConfig.js";
|
|
13
14
|
import { parseWizardFlags, shouldRunWizard } from "./wizard/firstRun.js";
|
|
@@ -164,10 +165,45 @@ function pickRootComponent() {
|
|
|
164
165
|
// v1.0.3: install-health diagnostic. Runs BEFORE the bundle is loaded
|
|
165
166
|
// and before any provider / config work, so it works on a broken
|
|
166
167
|
// install (missing bundle, missing shim, wrong PATH, etc.).
|
|
168
|
+
// v1.5.0: async — the optional-plugins check delegates to
|
|
169
|
+
// detectMissingPlugins (dynamic import + async detection).
|
|
167
170
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
168
171
|
const { runDoctor } = require("./utils/doctor.js");
|
|
169
|
-
|
|
170
|
-
|
|
172
|
+
void runDoctor().then((healthy) => process.exit(healthy ? 0 : 1));
|
|
173
|
+
return { kind: "done" };
|
|
174
|
+
}
|
|
175
|
+
if (argv.includes("--fix-path") || argv.includes("fix-path")) {
|
|
176
|
+
// v1.4.2: runtime PATH repair. Companion to the install-time auto-fix
|
|
177
|
+
// in scripts/postinstall.mjs. Handles the "PATH lost AFTER install"
|
|
178
|
+
// case that postinstall can't reach retroactively. Windows-only at the
|
|
179
|
+
// effect level; POSIX prints an advisory and exits 1.
|
|
180
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
181
|
+
const { repairWindowsUserPath } = require("./utils/fixPath.js");
|
|
182
|
+
const result = repairWindowsUserPath();
|
|
183
|
+
const green = "\x1b[32m";
|
|
184
|
+
const red = "\x1b[31m";
|
|
185
|
+
const dim = "\x1b[2m";
|
|
186
|
+
const reset = "\x1b[0m";
|
|
187
|
+
if (result.ok) {
|
|
188
|
+
if (result.alreadyOk) {
|
|
189
|
+
// eslint-disable-next-line no-console
|
|
190
|
+
console.log(`${green}✔${reset} npm prefix already on user PATH: ${result.prefix}`);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
// eslint-disable-next-line no-console
|
|
194
|
+
console.log(`${green}✔${reset} added npm prefix to user PATH: ${result.prefix}`);
|
|
195
|
+
// eslint-disable-next-line no-console
|
|
196
|
+
console.log(`${dim}open a NEW terminal for the change to take effect, then run: zelari-code --version${reset}`);
|
|
197
|
+
}
|
|
198
|
+
process.exit(0);
|
|
199
|
+
}
|
|
200
|
+
// eslint-disable-next-line no-console
|
|
201
|
+
console.error(`${red}✗${reset} ${result.error}`);
|
|
202
|
+
if (result.prefix) {
|
|
203
|
+
// eslint-disable-next-line no-console
|
|
204
|
+
console.error(`${dim}prefix: ${result.prefix}${reset}`);
|
|
205
|
+
}
|
|
206
|
+
process.exit(1);
|
|
171
207
|
}
|
|
172
208
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
173
209
|
// eslint-disable-next-line no-console
|
|
@@ -180,6 +216,8 @@ function pickRootComponent() {
|
|
|
180
216
|
" --help, -h Print this help and exit\n" +
|
|
181
217
|
" --doctor Diagnose install health (shim, bundle, PATH, deps,\n" +
|
|
182
218
|
" node/git/bash in the agent shell)\n" +
|
|
219
|
+
" --fix-path Add the npm global prefix to the user PATH\n" +
|
|
220
|
+
" (Windows only; fixes 'command not found' after install)\n" +
|
|
183
221
|
" --skip-checks Skip the boot-time prerequisite check\n" +
|
|
184
222
|
" (alias for ZELARI_SKIP_PREFLIGHT=1)\n" +
|
|
185
223
|
" --no-wizard Skip the first-run wizard\n" +
|
|
@@ -194,6 +232,7 @@ function pickRootComponent() {
|
|
|
194
232
|
"Environment:\n" +
|
|
195
233
|
" ZELARI_NO_WIZARD=1 Skip the first-run wizard\n" +
|
|
196
234
|
" ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n" +
|
|
235
|
+
" ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n" +
|
|
197
236
|
" ANATHEMA_DEV=1 Disable background update check + preflight\n");
|
|
198
237
|
process.exit(0);
|
|
199
238
|
}
|
|
@@ -224,9 +263,16 @@ function pickRootComponent() {
|
|
|
224
263
|
// v0.7.8: one-shot startup splash (ASCII emblem, ~2s or any-key skip),
|
|
225
264
|
// then the App mounts. Skipped automatically for non-TTY stdout, small
|
|
226
265
|
// terminals, or ZELARI_NO_SPLASH=1 — see components/SplashScreen.tsx.
|
|
266
|
+
// v1.5.0: PluginGate wraps App inside SplashGate — after the splash, it
|
|
267
|
+
// detects missing optional plugins (Playwright, eslint, ruff, LSP servers)
|
|
268
|
+
// and offers to install them before the App mounts. Skips on non-TTY,
|
|
269
|
+
// ZELARI_NO_PLUGIN_PROMPT=1, or when nothing is missing.
|
|
227
270
|
return {
|
|
228
271
|
kind: "app",
|
|
229
|
-
element: React.createElement(SplashGate, { version: VERSION }, React.createElement(
|
|
272
|
+
element: React.createElement(SplashGate, { version: VERSION }, React.createElement(PluginGate, {
|
|
273
|
+
cwd: process.cwd(),
|
|
274
|
+
children: React.createElement(App),
|
|
275
|
+
})),
|
|
230
276
|
};
|
|
231
277
|
}
|
|
232
278
|
/**
|
package/dist/cli/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* plugins/installer — spawn `npm install` for a plugin, buffered.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors updater.ts:performUpdate (the self-update install path) with two
|
|
5
|
+
* differences:
|
|
6
|
+
* 1. The install scope is per-plugin: `-D` (project-local) for linters +
|
|
7
|
+
* Playwright (that's how diagnostics/engine.ts + browser/driver.ts
|
|
8
|
+
* resolve them via node_modules/.bin / dynamic import), `-g` (global)
|
|
9
|
+
* for LSP servers (cross-project dev tools).
|
|
10
|
+
* 2. No `@latest` pinning — plugins don't self-update, so we install
|
|
11
|
+
* whatever npm resolves as current.
|
|
12
|
+
*
|
|
13
|
+
* Everything else is identical and reuses the updater's hard-won platform
|
|
14
|
+
* handling: buildCmdLine + shell:true on win32 for the `.cmd` shim, and the
|
|
15
|
+
* broken-shim fallback to the npm bundled next to Node (rescues
|
|
16
|
+
* Volta/nvm-windows/fnm where the global npm shim is broken).
|
|
17
|
+
*
|
|
18
|
+
* Output is BUFFERED (stdout+stderr concatenated), surfaced as a single
|
|
19
|
+
* string after exit — same UX as /update. This keeps the install gate simple
|
|
20
|
+
* (no streaming-log component needed) and matches the house style.
|
|
21
|
+
*
|
|
22
|
+
* Contract: never throws. Errors → { ok: false, error }.
|
|
23
|
+
*
|
|
24
|
+
* @see src/cli/updater.ts — performUpdate / runNpm, the template this mirrors
|
|
25
|
+
* @see src/cli/utils/cmdline.ts — buildCmdLine (win32 DEP0190-safe quoting)
|
|
26
|
+
*/
|
|
27
|
+
import { spawn } from 'node:child_process';
|
|
28
|
+
import { buildCmdLine } from '../utils/cmdline.js';
|
|
29
|
+
import { resolveBundledNpmCli, looksLikeBrokenShim, } from '../updater.js';
|
|
30
|
+
/**
|
|
31
|
+
* Install a plugin via npm. Respects PluginSpec.installScope (-D vs -g).
|
|
32
|
+
*
|
|
33
|
+
* @param spec The plugin to install.
|
|
34
|
+
* @param cwd Working directory (matters for -D installs; ignored by -g
|
|
35
|
+
* except as the spawn cwd).
|
|
36
|
+
* @param executor Injected spawn (tests). Defaults to node:child_process.spawn.
|
|
37
|
+
*/
|
|
38
|
+
export async function installPlugin(spec, cwd, executor = spawn) {
|
|
39
|
+
const scopeFlag = spec.installScope === 'global' ? '-g' : '-D';
|
|
40
|
+
const args = ['install', scopeFlag, spec.npmPackage];
|
|
41
|
+
// Attempt 1: PATH-resolved npm (shell on win32 for the .cmd shim).
|
|
42
|
+
const primary = await runNpm(executor, args, cwd, 'shim');
|
|
43
|
+
if (primary.ok)
|
|
44
|
+
return primary;
|
|
45
|
+
// Attempt 2: if attempt 1 died like a broken bin shim (Volta/nvm/fnm),
|
|
46
|
+
// retry via the npm bundled with Node. No shell, no .cmd in the way.
|
|
47
|
+
const npmCli = resolveBundledNpmCli();
|
|
48
|
+
if (npmCli && looksLikeBrokenShim(primary.exitCode, primary.output)) {
|
|
49
|
+
const fallback = await runNpm(executor, args, cwd, 'bundled', npmCli);
|
|
50
|
+
return {
|
|
51
|
+
...fallback,
|
|
52
|
+
output: `[plugins] npm shim failed (${primary.error ?? 'exit ' + primary.exitCode}); ` +
|
|
53
|
+
`retried via bundled npm (${npmCli}).\n${fallback.output}`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return primary;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Spawn one npm invocation and collect its buffered result.
|
|
60
|
+
*
|
|
61
|
+
* `mode: 'shim'` runs the PATH-resolved `npm` (shell on Windows for `.cmd`).
|
|
62
|
+
* `mode: 'bundled'` runs `node <npmCliPath> ...` directly, bypassing shims.
|
|
63
|
+
*
|
|
64
|
+
* Direct copy of updater.ts:runNpm with cwd threaded through. Keeping the two
|
|
65
|
+
* in lockstep means platform fixes (DEP0190, broken-shim detection) apply to
|
|
66
|
+
* both — diverging would let one rot while the other gets fixed.
|
|
67
|
+
*/
|
|
68
|
+
function runNpm(executor, args, cwd, mode, npmCliPath) {
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
let stdout = '';
|
|
71
|
+
let stderr = '';
|
|
72
|
+
const stdio = ['ignore', 'pipe', 'pipe'];
|
|
73
|
+
const child = mode === 'bundled' && npmCliPath
|
|
74
|
+
? executor(process.execPath, [npmCliPath, ...args], { stdio, cwd })
|
|
75
|
+
: process.platform === 'win32'
|
|
76
|
+
? executor(buildCmdLine('npm', args), { stdio, shell: true, cwd })
|
|
77
|
+
: executor('npm', args, { stdio, cwd });
|
|
78
|
+
child.stdout?.on('data', (chunk) => {
|
|
79
|
+
stdout += chunk.toString();
|
|
80
|
+
});
|
|
81
|
+
child.stderr?.on('data', (chunk) => {
|
|
82
|
+
stderr += chunk.toString();
|
|
83
|
+
});
|
|
84
|
+
child.on('error', (err) => {
|
|
85
|
+
resolve({
|
|
86
|
+
ok: false,
|
|
87
|
+
output: stdout + stderr,
|
|
88
|
+
error: err.message,
|
|
89
|
+
exitCode: null,
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
child.on('close', (code) => {
|
|
93
|
+
const ok = code === 0;
|
|
94
|
+
resolve({
|
|
95
|
+
ok,
|
|
96
|
+
output: stdout + stderr,
|
|
97
|
+
exitCode: code,
|
|
98
|
+
error: ok ? undefined : `npm exited with code ${code}`,
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../../../src/cli/plugins/installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* plugins/prefs — persistence of plugin-installation preferences.
|
|
3
|
+
*
|
|
4
|
+
* Stores the "don't ask me again about plugin X" dismissal so the boot gate
|
|
5
|
+
* doesn't nag users who've already decided. Modeled on providerConfig.ts:
|
|
6
|
+
* - JSON file in ~/.tmp/zelari-code/ alongside provider.json / keys.json
|
|
7
|
+
* - existsSync + JSON.parse + validate, graceful fallback to defaults on
|
|
8
|
+
* corrupt/missing file (a broken prefs file must never block boot)
|
|
9
|
+
* - read-modify-write mutators, mode 0o600 (owner-only) on write
|
|
10
|
+
*
|
|
11
|
+
* Shape:
|
|
12
|
+
* { version: 1, dontAskAgain: { "<pluginId>": true } }
|
|
13
|
+
*
|
|
14
|
+
* `version` is reserved for forward migration — bumping it lets a future
|
|
15
|
+
* release rewrite the schema without a silent data loss.
|
|
16
|
+
*
|
|
17
|
+
* Env override: ZELARI_PLUGINS_PREFS_FILE (tests + CI isolate the file).
|
|
18
|
+
*
|
|
19
|
+
* @see src/cli/providerConfig.ts — the canonical read-modify-write template
|
|
20
|
+
*/
|
|
21
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
22
|
+
import path from 'node:path';
|
|
23
|
+
import os from 'node:os';
|
|
24
|
+
const DEFAULTS = {
|
|
25
|
+
version: 1,
|
|
26
|
+
dontAskAgain: {},
|
|
27
|
+
};
|
|
28
|
+
/** Path to the prefs file. Env-overridable for tests. */
|
|
29
|
+
export function getPluginPrefsPath() {
|
|
30
|
+
return process.env.ZELARI_PLUGINS_PREFS_FILE
|
|
31
|
+
?? path.join(os.homedir(), '.tmp', 'zelari-code', 'plugins.json');
|
|
32
|
+
}
|
|
33
|
+
/** Read prefs, falling back to defaults on missing/corrupt file. Never throws. */
|
|
34
|
+
export function getPluginPrefs() {
|
|
35
|
+
const file = getPluginPrefsPath();
|
|
36
|
+
try {
|
|
37
|
+
if (!existsSync(file))
|
|
38
|
+
return { ...DEFAULTS, dontAskAgain: {} };
|
|
39
|
+
const raw = readFileSync(file, 'utf-8');
|
|
40
|
+
const parsed = JSON.parse(raw);
|
|
41
|
+
if (parsed &&
|
|
42
|
+
typeof parsed === 'object' &&
|
|
43
|
+
parsed.dontAskAgain &&
|
|
44
|
+
typeof parsed.dontAskAgain === 'object') {
|
|
45
|
+
// Sanitize: keep only boolean-true entries with a non-empty id; drop junk.
|
|
46
|
+
const clean = {};
|
|
47
|
+
for (const [k, v] of Object.entries(parsed.dontAskAgain)) {
|
|
48
|
+
if (typeof k === 'string' && k.length > 0 && v === true)
|
|
49
|
+
clean[k] = true;
|
|
50
|
+
}
|
|
51
|
+
return { version: 1, dontAskAgain: clean };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Corrupt JSON or unreadable — fall through to defaults.
|
|
56
|
+
}
|
|
57
|
+
return { ...DEFAULTS, dontAskAgain: {} };
|
|
58
|
+
}
|
|
59
|
+
function writePluginPrefs(prefs) {
|
|
60
|
+
const file = getPluginPrefsPath();
|
|
61
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
62
|
+
writeFileSync(file, JSON.stringify(prefs, null, 2), {
|
|
63
|
+
encoding: 'utf-8',
|
|
64
|
+
mode: 0o600,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Mark a plugin as "don't ask again" (user picked 'Don't ask again' in the
|
|
69
|
+
* boot prompt, or `ZELARI_NO_PLUGIN_PROMPT` style dismissal). Idempotent.
|
|
70
|
+
*/
|
|
71
|
+
export function markDontAskAgain(pluginId) {
|
|
72
|
+
try {
|
|
73
|
+
const prefs = getPluginPrefs();
|
|
74
|
+
prefs.dontAskAgain[pluginId] = true;
|
|
75
|
+
writePluginPrefs(prefs);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// A failed write (read-only home, full disk) must never block boot.
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Clear the "don't ask again" flag for a plugin (so /plugins can re-offer). */
|
|
82
|
+
export function clearDontAskAgain(pluginId) {
|
|
83
|
+
try {
|
|
84
|
+
const prefs = getPluginPrefs();
|
|
85
|
+
delete prefs.dontAskAgain[pluginId];
|
|
86
|
+
writePluginPrefs(prefs);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Same fail-safe contract.
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** Has the user muted this plugin at the boot prompt? */
|
|
93
|
+
export function isMuted(pluginId) {
|
|
94
|
+
return getPluginPrefs().dontAskAgain[pluginId] === true;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=prefs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefs.js","sourceRoot":"","sources":["../../../src/cli/plugins/prefs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* plugins/registry — catalog of optional tool plugins zelari-code can offer
|
|
3
|
+
* to install when missing.
|
|
4
|
+
*
|
|
5
|
+
* A "plugin" here is an OPTIONAL dependency of an edge feature: Playwright
|
|
6
|
+
* powers `browser_check`, typescript-language-server / pyright power the LSP
|
|
7
|
+
* navigation tools, eslint / ruff power the post-edit diagnostics loop. None
|
|
8
|
+
* are required to boot — every one of these features degrades silently when
|
|
9
|
+
* its binary is absent (see browser/driver.ts, lsp/manager.ts,
|
|
10
|
+
* diagnostics/engine.ts). The plugin manager is a DISCOVERY layer on top: it
|
|
11
|
+
* detects absence and offers to install, without changing how the tools
|
|
12
|
+
* register or degrade.
|
|
13
|
+
*
|
|
14
|
+
* The binary names are NOT redeclared here — they're sourced from the
|
|
15
|
+
* existing registries the features already use, so a single source of truth
|
|
16
|
+
* is preserved:
|
|
17
|
+
* - DEFAULT_PROVIDERS (diagnostics/engine.ts) → eslint, ruff
|
|
18
|
+
* - LSP_SERVERS (lsp/servers.ts) → typescript-language-server,
|
|
19
|
+
* pyright-langserver
|
|
20
|
+
* - defaultPlaywrightLoader (browser/driver) → playwright
|
|
21
|
+
*
|
|
22
|
+
* Detection mirrors how each feature actually resolves its binary:
|
|
23
|
+
* - project-local linters (eslint/ruff) → resolveBin() walk of node_modules/.bin
|
|
24
|
+
* - LSP servers → PATH probe via `<bin> --version`
|
|
25
|
+
* (they're global dev tools, conventionally installed once)
|
|
26
|
+
* - Playwright → the same dynamic-import loader the
|
|
27
|
+
* browser_check tool uses, so "installed" means "importable + has chromium"
|
|
28
|
+
*
|
|
29
|
+
* Contract: detect() is async, never throws, returns Promise<boolean>. The
|
|
30
|
+
* caller (PluginGate / doctor / /plugins) treats false as "missing, offer to
|
|
31
|
+
* install" and true as "present, leave alone."
|
|
32
|
+
*
|
|
33
|
+
* @see scripts/postinstall.mjs — required install-time deps (this file is
|
|
34
|
+
* the OPTIONAL complement: tools we recommend but don't mandate)
|
|
35
|
+
*/
|
|
36
|
+
import { spawnSync } from 'node:child_process';
|
|
37
|
+
import { resolveBin } from '../diagnostics/engine.js';
|
|
38
|
+
import { defaultPlaywrightLoader } from '../browser/driver.js';
|
|
39
|
+
import { DEFAULT_PROVIDERS } from '../diagnostics/engine.js';
|
|
40
|
+
import { LSP_SERVERS } from '../lsp/servers.js';
|
|
41
|
+
import { isMuted } from './prefs.js';
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Detection primitives — wrap the existing resolution mechanisms.
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
/**
|
|
46
|
+
* Detect a project-local binary (eslint, ruff). resolveBin walks up to 6
|
|
47
|
+
* parent dirs looking for `node_modules/.bin/<bin>`; on miss it returns the
|
|
48
|
+
* bare name, which we treat as "not found locally". This matches how
|
|
49
|
+
* diagnostics/engine.ts actually resolves the linter at call time.
|
|
50
|
+
*/
|
|
51
|
+
function detectLocalBin(bin) {
|
|
52
|
+
return (cwd) => {
|
|
53
|
+
try {
|
|
54
|
+
const resolved = resolveBin(bin, cwd);
|
|
55
|
+
// resolveBin returns the bare name when nothing is found.
|
|
56
|
+
return Promise.resolve(resolved !== bin);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return Promise.resolve(false);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Detect a globally-installed binary (LSP servers). Spawn `<bin> --version`
|
|
65
|
+
* synchronously through the default shell; a non-zero / errored spawn means
|
|
66
|
+
* "not on PATH". This is the pattern prereqChecks.ts uses for node/git/bash,
|
|
67
|
+
* adapted for a generic binary. Synchronous because detection runs at boot
|
|
68
|
+
* gate / doctor time where blocking briefly is acceptable.
|
|
69
|
+
*/
|
|
70
|
+
function detectGlobalBin(bin) {
|
|
71
|
+
return () => {
|
|
72
|
+
try {
|
|
73
|
+
// On win32 a bare binary name needs shell:true so .cmd shims resolve;
|
|
74
|
+
// on POSIX a direct spawn is fine.
|
|
75
|
+
const res = spawnSync(bin, ['--version'], {
|
|
76
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
77
|
+
shell: process.platform === 'win32',
|
|
78
|
+
timeout: 4000,
|
|
79
|
+
});
|
|
80
|
+
return Promise.resolve(res.status === 0 || (res.stdout != null && res.stdout.toString().trim().length > 0 && res.error === undefined));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return Promise.resolve(false);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Detect Playwright via the exact loader browser_check uses. */
|
|
88
|
+
async function detectPlaywright() {
|
|
89
|
+
try {
|
|
90
|
+
const mod = await defaultPlaywrightLoader();
|
|
91
|
+
return mod !== null;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
// Plugin catalog.
|
|
99
|
+
//
|
|
100
|
+
// IDs are stable forever (persisted to plugins.json). Derived from the feature
|
|
101
|
+
// registries so the binary names stay in lockstep — if diagnostics/engine.ts
|
|
102
|
+
// renames `eslint` to something else, this catalog follows automatically.
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
/** The canonical plugin list. Order = display order in prompts + doctor. */
|
|
105
|
+
export const PLUGINS = [
|
|
106
|
+
{
|
|
107
|
+
id: 'eslint',
|
|
108
|
+
label: 'ESLint (diagnostics for JS/TS)',
|
|
109
|
+
npmPackage: 'eslint',
|
|
110
|
+
installScope: 'dev',
|
|
111
|
+
detect: detectLocalBin(binForProvider('eslint')),
|
|
112
|
+
featureGate: 'ZELARI_DIAGNOSTICS',
|
|
113
|
+
description: 'Enables the post-edit diagnostics loop for .js/.jsx/.ts/.tsx/.mjs/.cjs files.',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: 'ruff',
|
|
117
|
+
label: 'Ruff (diagnostics for Python)',
|
|
118
|
+
npmPackage: 'ruff',
|
|
119
|
+
installScope: 'dev',
|
|
120
|
+
detect: detectLocalBin(binForProvider('ruff')),
|
|
121
|
+
featureGate: 'ZELARI_DIAGNOSTICS',
|
|
122
|
+
description: 'Enables the post-edit diagnostics loop for .py files.',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: 'playwright',
|
|
126
|
+
label: 'Playwright (browser_check tool)',
|
|
127
|
+
npmPackage: 'playwright',
|
|
128
|
+
installScope: 'dev',
|
|
129
|
+
detect: () => detectPlaywright(),
|
|
130
|
+
postInstallHint: 'Then fetch the browser binary: `npx playwright install chromium`',
|
|
131
|
+
featureGate: 'ZELARI_BROWSER',
|
|
132
|
+
description: 'Powers the browser_check tool (URL probing, click/fill/wait, screenshots).',
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: 'typescript-language-server',
|
|
136
|
+
label: 'typescript-language-server (LSP for TS/JS)',
|
|
137
|
+
npmPackage: 'typescript-language-server',
|
|
138
|
+
installScope: 'global',
|
|
139
|
+
detect: detectGlobalBin(binForLspLanguage('typescript')),
|
|
140
|
+
featureGate: 'ZELARI_LSP',
|
|
141
|
+
description: 'Powers go_to_definition / find_references / hover_type / rename_symbol for TS/JS.',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
id: 'pyright',
|
|
145
|
+
label: 'pyright (LSP for Python)',
|
|
146
|
+
npmPackage: 'pyright',
|
|
147
|
+
installScope: 'global',
|
|
148
|
+
detect: detectGlobalBin(binForLspLanguage('python')),
|
|
149
|
+
featureGate: 'ZELARI_LSP',
|
|
150
|
+
description: 'Powers go_to_definition / find_references / hover_type / rename_symbol for Python.',
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// Small adapters so the catalog above derives binary names from the existing
|
|
155
|
+
// registries rather than hardcoding them (single source of truth).
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
/** Look up a diagnostic provider's binary name by provider name. */
|
|
158
|
+
function binForProvider(name) {
|
|
159
|
+
const p = DEFAULT_PROVIDERS.find((x) => x.name === name);
|
|
160
|
+
if (!p)
|
|
161
|
+
throw new Error(`plugin registry: unknown diagnostic provider '${name}'`);
|
|
162
|
+
return p.bin;
|
|
163
|
+
}
|
|
164
|
+
/** Look up an LSP server's binary name by language. */
|
|
165
|
+
function binForLspLanguage(language) {
|
|
166
|
+
const s = LSP_SERVERS.find((x) => x.language === language);
|
|
167
|
+
if (!s)
|
|
168
|
+
throw new Error(`plugin registry: unknown LSP language '${language}'`);
|
|
169
|
+
return s.bin;
|
|
170
|
+
}
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
// Aggregating detector — what the gate / doctor / /plugins call.
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
/**
|
|
175
|
+
* Detect all plugins that are MISSING, in display order, after applying the
|
|
176
|
+
* two filters that suppress noise:
|
|
177
|
+
* 1. featureGate — if ZELARI_BROWSER=0 etc., the feature is off, so don't
|
|
178
|
+
* prompt to install the tool it needs.
|
|
179
|
+
* 2. dontAskAgain — if the user dismissed this plugin before, respect it.
|
|
180
|
+
* (The `/plugins` command passes `includeMuted: true` to re-surface them.)
|
|
181
|
+
*
|
|
182
|
+
* Never throws. A detect() that rejects is treated as "missing".
|
|
183
|
+
*/
|
|
184
|
+
export async function detectMissingPlugins(cwd, opts = {}) {
|
|
185
|
+
const missing = [];
|
|
186
|
+
for (const spec of PLUGINS) {
|
|
187
|
+
// Filter 1: kill-switch. If the feature is disabled, don't offer its tool.
|
|
188
|
+
if (process.env[spec.featureGate] === '0')
|
|
189
|
+
continue;
|
|
190
|
+
// Filter 2: user-muted (unless explicitly re-surfaced via /plugins).
|
|
191
|
+
if (!opts.includeMuted && isMuted(spec.id))
|
|
192
|
+
continue;
|
|
193
|
+
let present = false;
|
|
194
|
+
try {
|
|
195
|
+
present = await spec.detect(cwd);
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
present = false;
|
|
199
|
+
}
|
|
200
|
+
if (!present)
|
|
201
|
+
missing.push(spec);
|
|
202
|
+
}
|
|
203
|
+
return missing;
|
|
204
|
+
}
|
|
205
|
+
/** Look up a plugin by id (for `/plugins install <id>`). */
|
|
206
|
+
export function findPlugin(id) {
|
|
207
|
+
return PLUGINS.find((p) => p.id === id);
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/cli/plugins/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -73,7 +73,7 @@ export function handleSlashCommand(text, availableSkills) {
|
|
|
73
73
|
kind: 'help',
|
|
74
74
|
message: `Available commands:\n /login <provider> — authenticate with provider (grok, minimax, glm, custom)\n /model — pick the active model from a list (auto-discovers, v0.7.10)\n /model <name> — switch the active model directly\n /model show — print the current model\n /models — list discovered models for the active provider (v3-U)\n /models refresh (or /discover) — re-discover models for the active provider\n /provider — pick the active provider from a list (v0.7.10)\n /provider <name> — switch the active provider directly\n /provider custom <baseUrl> — point the active provider at a self-hosted endpoint (Ollama, LM Studio, vLLM, ...)\n /provider custom clear — clear the custom endpoint override\n /skill <name> [input] — invoke a skill (autocomplete with /skill <TAB>)\n /skill-stats [name] — show invocation stats (success rate, avg duration, total tokens)\n /council <input> — invoke the multi-agent council on input\n /zelari <input> — run an autonomous mission (multi-run council until the MVP slice is complete)\n /council-feedback <memberId> <1-5> [note] — rate a council member for future ranking (Task I.2)
|
|
75
75
|
/promote-member <memberId> — promote a council member to a standalone skill (v3-K)
|
|
76
|
-
/update [--yes|-y] — check for zelari-code updates; --yes performs the update (v3-N)\n /steer <text> — enqueue a follow-up prompt on the active run (Task 18.2)\n /steer --interrupt <text> — cancel current run + enqueue <text> for next dispatch (Task C.3.2)\n /compact — compact the session transcript\n /clear — clear the visible transcript (session is preserved)\n /sessions — list past sessions\n /resume <id> — load a past session\n /branch <name> — snapshot the current session into a new branch\n /branches — list branches\n /checkout <name> — switch the active branch\n /new — start a fresh session\n /diff [--staged] — show uncommitted changes (or staged with --staged)\n /undo [--yes] — revert working-tree changes (destructive! requires --yes)\n /checkpoint [label] — snapshot the working tree as a restore point\n /rollback [id|latest] — restore the working tree to a checkpoint (no arg: list)\n /index [status] — build the semantic code index for semantic_search\n /mode [agent|council|zelari] — switch dispatch mode (same as shift+tab; no arg cycles)\n /help — show this help\n /exit — exit the CLI\n\n${formatSkillList(availableSkills)}`,
|
|
76
|
+
/update [--yes|-y] — check for zelari-code updates; --yes performs the update (v3-N)\n /plugins — list optional tool plugins (Playwright, eslint, ruff, LSP servers)\n /plugins install <id> — install a plugin now (e.g. /plugins install eslint)\n /steer <text> — enqueue a follow-up prompt on the active run (Task 18.2)\n /steer --interrupt <text> — cancel current run + enqueue <text> for next dispatch (Task C.3.2)\n /compact — compact the session transcript\n /clear — clear the visible transcript (session is preserved)\n /sessions — list past sessions\n /resume <id> — load a past session\n /branch <name> — snapshot the current session into a new branch\n /branches — list branches\n /checkout <name> — switch the active branch\n /new — start a fresh session\n /diff [--staged] — show uncommitted changes (or staged with --staged)\n /undo [--yes] — revert working-tree changes (destructive! requires --yes)\n /checkpoint [label] — snapshot the working tree as a restore point\n /rollback [id|latest] — restore the working tree to a checkpoint (no arg: list)\n /index [status] — build the semantic code index for semantic_search\n /mode [agent|council|zelari] — switch dispatch mode (same as shift+tab; no arg cycles)\n /help — show this help\n /exit — exit the CLI\n\n${formatSkillList(availableSkills)}`,
|
|
77
77
|
};
|
|
78
78
|
case 'exit':
|
|
79
79
|
return { handled: true, kind: 'exit', message: 'Goodbye.' };
|
|
@@ -432,6 +432,23 @@ export function handleSlashCommand(text, availableSkills) {
|
|
|
432
432
|
updateForce: force,
|
|
433
433
|
};
|
|
434
434
|
}
|
|
435
|
+
case 'plugins': {
|
|
436
|
+
// Usage:
|
|
437
|
+
// /plugins → list all optional plugins (status + install hints)
|
|
438
|
+
// /plugins install <id> → install a specific plugin now
|
|
439
|
+
if (args.length === 0) {
|
|
440
|
+
return { handled: true, kind: 'plugins_list' };
|
|
441
|
+
}
|
|
442
|
+
if (args[0] === 'install' && args[1]) {
|
|
443
|
+
return { handled: true, kind: 'plugins_install', pluginId: args[1] };
|
|
444
|
+
}
|
|
445
|
+
return {
|
|
446
|
+
handled: true,
|
|
447
|
+
kind: 'plugins_usage',
|
|
448
|
+
message: 'Usage: /plugins — list optional tool plugins (Playwright, eslint, ruff, LSP servers)\n' +
|
|
449
|
+
' /plugins install <id> — install a plugin now (e.g. /plugins install eslint)',
|
|
450
|
+
};
|
|
451
|
+
}
|
|
435
452
|
case 'undo': {
|
|
436
453
|
const confirmed = args.includes('--yes') || args.includes('-y');
|
|
437
454
|
if (confirmed) {
|