vibe-code-explainer 0.3.4 → 0.3.6
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/chunk-GEAH6PTG.js +37 -0
- package/dist/chunk-GEAH6PTG.js.map +1 -0
- package/dist/{chunk-2PUO5G3C.js → chunk-KK76JK7S.js} +32 -92
- package/dist/chunk-KK76JK7S.js.map +1 -0
- package/dist/chunk-LWASVVBV.js +140 -0
- package/dist/chunk-LWASVVBV.js.map +1 -0
- package/dist/{chunk-ABPTVWQ3.js → chunk-R5H62KGX.js} +86 -85
- package/dist/chunk-R5H62KGX.js.map +1 -0
- package/dist/{chunk-XW3S5GNV.js → chunk-VJN7Y4SI.js} +114 -33
- package/dist/chunk-VJN7Y4SI.js.map +1 -0
- package/dist/cli/index.js +37 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/{config-AHHWBME7.js → config-4DNTCZ6X.js} +127 -8
- package/dist/config-4DNTCZ6X.js.map +1 -0
- package/dist/hooks/post-tool.js +143 -162
- package/dist/hooks/post-tool.js.map +1 -1
- package/dist/{init-XXK6SGF2.js → init-YHRKOKSY.js} +12 -16
- package/dist/init-YHRKOKSY.js.map +1 -0
- package/dist/ollama-43BPUEEC.js +12 -0
- package/dist/{schema-YEJIXFMK.js → schema-MYOWRNBW.js} +8 -4
- package/dist/{tracker-Z5EEYUUZ.js → tracker-Y2G5DW6Y.js} +2 -2
- package/dist/{uninstall-AIH4HVPZ.js → uninstall-YADL7OUB.js} +3 -3
- package/package.json +3 -2
- package/dist/chunk-2PUO5G3C.js.map +0 -1
- package/dist/chunk-ABPTVWQ3.js.map +0 -1
- package/dist/chunk-RK7ZFN4W.js +0 -97
- package/dist/chunk-RK7ZFN4W.js.map +0 -1
- package/dist/chunk-XW3S5GNV.js.map +0 -1
- package/dist/config-AHHWBME7.js.map +0 -1
- package/dist/init-XXK6SGF2.js.map +0 -1
- package/dist/ollama-2WHLTTDD.js +0 -14
- /package/dist/{ollama-2WHLTTDD.js.map → ollama-43BPUEEC.js.map} +0 -0
- /package/dist/{schema-YEJIXFMK.js.map → schema-MYOWRNBW.js.map} +0 -0
- /package/dist/{tracker-Z5EEYUUZ.js.map → tracker-Y2G5DW6Y.js.map} +0 -0
- /package/dist/{uninstall-AIH4HVPZ.js.map → uninstall-YADL7OUB.js.map} +0 -0
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
flagBool,
|
|
4
|
+
parseFlags
|
|
5
|
+
} from "./chunk-GEAH6PTG.js";
|
|
2
6
|
import {
|
|
3
7
|
MODEL_OPTIONS
|
|
4
8
|
} from "./chunk-SWGQLRTO.js";
|
|
@@ -8,8 +12,9 @@ import {
|
|
|
8
12
|
LANGUAGE_NAMES,
|
|
9
13
|
LEARNER_LEVEL_NAMES,
|
|
10
14
|
getGlobalConfigPath,
|
|
11
|
-
loadConfig
|
|
12
|
-
|
|
15
|
+
loadConfig,
|
|
16
|
+
validateConfig
|
|
17
|
+
} from "./chunk-LWASVVBV.js";
|
|
13
18
|
import "./chunk-7OCVIDC7.js";
|
|
14
19
|
|
|
15
20
|
// src/cli/config.ts
|
|
@@ -37,10 +42,10 @@ function normalizeModelName(name) {
|
|
|
37
42
|
}
|
|
38
43
|
function hasModel(installed, wanted) {
|
|
39
44
|
const wantedNorm = normalizeModelName(wanted);
|
|
45
|
+
const wantedLower = wanted.toLowerCase();
|
|
40
46
|
return installed.some((n) => {
|
|
41
47
|
const base = n.toLowerCase();
|
|
42
|
-
if (base ===
|
|
43
|
-
if (base === wanted.toLowerCase()) return true;
|
|
48
|
+
if (base === wantedLower) return true;
|
|
44
49
|
return normalizeModelName(base).startsWith(wantedNorm);
|
|
45
50
|
});
|
|
46
51
|
}
|
|
@@ -93,7 +98,7 @@ function renderCurrent(config) {
|
|
|
93
98
|
`${pc.bold("Detail level: ")} ${config.detailLevel}`,
|
|
94
99
|
`${pc.bold("Language: ")} ${LANGUAGE_NAMES[config.language]}`,
|
|
95
100
|
`${pc.bold("Learner level:")} ${LEARNER_LEVEL_NAMES[config.learnerLevel]}`,
|
|
96
|
-
`${pc.bold("Hooks: ")} ${hooks.
|
|
101
|
+
`${pc.bold("Hooks: ")} ${hooks.map((h) => `${h} \u2713`).join(" ") || "(all disabled)"}`,
|
|
97
102
|
`${pc.bold("Excluded: ")} ${excluded}`,
|
|
98
103
|
`${pc.bold("Skip if slow: ")} ${timeoutLabel}`
|
|
99
104
|
].join("\n");
|
|
@@ -276,7 +281,118 @@ async function changeTimeout(config) {
|
|
|
276
281
|
handleCancel(value);
|
|
277
282
|
return { ...config, skipIfSlowMs: value };
|
|
278
283
|
}
|
|
279
|
-
|
|
284
|
+
function resolveConfigPath() {
|
|
285
|
+
const projectPath = join(process.cwd(), CONFIG_FILENAME);
|
|
286
|
+
const globalPath = getGlobalConfigPath();
|
|
287
|
+
if (existsSync(projectPath)) return { configPath: projectPath, scope: "project" };
|
|
288
|
+
if (existsSync(globalPath)) return { configPath: globalPath, scope: "global" };
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
function runConfigShow(args) {
|
|
292
|
+
const { flags } = parseFlags(args);
|
|
293
|
+
const json = flagBool(flags, "json", "j");
|
|
294
|
+
const resolved = resolveConfigPath();
|
|
295
|
+
if (!resolved) {
|
|
296
|
+
process.stderr.write("[code-explainer] No config file found. Run 'vibe-code-explainer init' first.\n");
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
const config = loadConfig(resolved.configPath);
|
|
300
|
+
if (json) {
|
|
301
|
+
process.stdout.write(JSON.stringify(config, null, 2) + "\n");
|
|
302
|
+
} else {
|
|
303
|
+
process.stderr.write(renderCurrent(config) + "\n");
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function runConfigGet(args) {
|
|
307
|
+
const { positional } = parseFlags(args);
|
|
308
|
+
const key = positional[0];
|
|
309
|
+
if (!key) {
|
|
310
|
+
process.stderr.write("[code-explainer] Usage: vibe-code-explainer config get <key>\n");
|
|
311
|
+
process.exit(1);
|
|
312
|
+
}
|
|
313
|
+
const resolved = resolveConfigPath();
|
|
314
|
+
if (!resolved) {
|
|
315
|
+
process.stderr.write("[code-explainer] No config file found. Run 'vibe-code-explainer init' first.\n");
|
|
316
|
+
process.exit(1);
|
|
317
|
+
}
|
|
318
|
+
const config = loadConfig(resolved.configPath);
|
|
319
|
+
const parts = key.split(".");
|
|
320
|
+
let cur = config;
|
|
321
|
+
for (const part of parts) {
|
|
322
|
+
if (typeof cur !== "object" || cur === null) {
|
|
323
|
+
process.stderr.write(`[code-explainer] Key '${key}' not found in config.
|
|
324
|
+
`);
|
|
325
|
+
process.exit(1);
|
|
326
|
+
}
|
|
327
|
+
cur = cur[part];
|
|
328
|
+
}
|
|
329
|
+
if (cur === void 0) {
|
|
330
|
+
process.stderr.write(`[code-explainer] Key '${key}' not found in config.
|
|
331
|
+
`);
|
|
332
|
+
process.exit(1);
|
|
333
|
+
}
|
|
334
|
+
if (typeof cur === "object") {
|
|
335
|
+
process.stdout.write(JSON.stringify(cur) + "\n");
|
|
336
|
+
} else {
|
|
337
|
+
process.stdout.write(String(cur) + "\n");
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
function runConfigSet(args) {
|
|
341
|
+
const { positional } = parseFlags(args);
|
|
342
|
+
const [key, rawValue] = positional;
|
|
343
|
+
if (!key || rawValue === void 0) {
|
|
344
|
+
process.stderr.write("[code-explainer] Usage: vibe-code-explainer config set <key> <value>\n");
|
|
345
|
+
process.exit(1);
|
|
346
|
+
}
|
|
347
|
+
const resolved = resolveConfigPath();
|
|
348
|
+
if (!resolved) {
|
|
349
|
+
process.stderr.write("[code-explainer] No config file found. Run 'vibe-code-explainer init' first.\n");
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
let value = rawValue;
|
|
353
|
+
try {
|
|
354
|
+
value = JSON.parse(rawValue);
|
|
355
|
+
} catch {
|
|
356
|
+
}
|
|
357
|
+
const config = loadConfig(resolved.configPath);
|
|
358
|
+
const parts = key.split(".");
|
|
359
|
+
let cur = config;
|
|
360
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
361
|
+
const part = parts[i];
|
|
362
|
+
if (typeof cur[part] !== "object" || cur[part] === null) {
|
|
363
|
+
cur[part] = {};
|
|
364
|
+
}
|
|
365
|
+
cur = cur[part];
|
|
366
|
+
}
|
|
367
|
+
cur[parts[parts.length - 1]] = value;
|
|
368
|
+
try {
|
|
369
|
+
validateConfig(config);
|
|
370
|
+
} catch (err) {
|
|
371
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
372
|
+
process.stderr.write(`${msg}
|
|
373
|
+
`);
|
|
374
|
+
process.exit(1);
|
|
375
|
+
}
|
|
376
|
+
writeFileSync(resolved.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
377
|
+
process.stderr.write(`[code-explainer] Set ${key} = ${JSON.stringify(value)} in ${resolved.configPath}
|
|
378
|
+
`);
|
|
379
|
+
}
|
|
380
|
+
async function runConfig(rawArgs = []) {
|
|
381
|
+
const { flags, positional } = parseFlags(rawArgs);
|
|
382
|
+
const subcommand = positional[0];
|
|
383
|
+
const subArgs = positional.slice(1);
|
|
384
|
+
if (subcommand === "show") {
|
|
385
|
+
runConfigShow([...subArgs, ...Object.entries(flags).flatMap(([k, v]) => v === true ? [`--${k}`] : [`--${k}=${v}`])]);
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
if (subcommand === "get") {
|
|
389
|
+
runConfigGet(subArgs);
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
if (subcommand === "set") {
|
|
393
|
+
runConfigSet(subArgs);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
280
396
|
const projectPath = join(process.cwd(), CONFIG_FILENAME);
|
|
281
397
|
const globalPath = getGlobalConfigPath();
|
|
282
398
|
let configPath;
|
|
@@ -298,6 +414,7 @@ Run ${pc.cyan("npx vibe-code-explainer init")} first.`
|
|
|
298
414
|
process.exit(1);
|
|
299
415
|
}
|
|
300
416
|
intro(pc.bold(`code-explainer config (${scope})`));
|
|
417
|
+
const skipConfirm = flagBool(flags, "yes", "y");
|
|
301
418
|
let config = loadConfig(configPath);
|
|
302
419
|
while (true) {
|
|
303
420
|
note(renderCurrent(config), "Current settings");
|
|
@@ -329,9 +446,11 @@ Run ${pc.cyan("npx vibe-code-explainer init")} first.`
|
|
|
329
446
|
if (choice === "timeout") config = await changeTimeout(config);
|
|
330
447
|
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
331
448
|
}
|
|
332
|
-
|
|
449
|
+
if (!skipConfirm) {
|
|
450
|
+
outro(pc.green("Settings saved."));
|
|
451
|
+
}
|
|
333
452
|
}
|
|
334
453
|
export {
|
|
335
454
|
runConfig
|
|
336
455
|
};
|
|
337
|
-
//# sourceMappingURL=config-
|
|
456
|
+
//# sourceMappingURL=config-4DNTCZ6X.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/config.ts"],"sourcesContent":["import { intro, outro, select, confirm, text, cancel, isCancel, note } from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { spawn } from \"node:child_process\";\nimport { existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n DEFAULT_CONFIG,\n loadConfig,\n validateConfig,\n LANGUAGE_NAMES,\n LEARNER_LEVEL_NAMES,\n CONFIG_FILENAME,\n getGlobalConfigPath,\n type Config,\n type Engine,\n type DetailLevel,\n type Language,\n type LearnerLevel,\n} from \"../config/schema.js\";\nimport { MODEL_OPTIONS } from \"../detect/vram.js\";\nimport { parseFlags, flagBool } from \"./flags.js\";\n\ninterface OllamaTagResponse {\n models?: Array<{ name?: string; model?: string }>;\n}\n\nasync function listInstalledOllamaModels(url: string): Promise<string[] | null> {\n try {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), 3000);\n const res = await fetch(`${url}/api/tags`, { signal: ctrl.signal });\n clearTimeout(timer);\n if (!res.ok) return null;\n const data = (await res.json()) as OllamaTagResponse;\n if (!data.models) return [];\n return data.models\n .map((m) => m.name ?? m.model ?? \"\")\n .filter((n) => n.length > 0);\n } catch {\n return null;\n }\n}\n\nfunction normalizeModelName(name: string): string {\n // Ollama sometimes returns tags as \"qwen3.5:9b\" and sometimes as\n // \"qwen3.5:9b-q4_K_M\". Compare on the base \"<model>:<tag>\" prefix.\n return name.toLowerCase().split(/[-_]/)[0];\n}\n\nfunction hasModel(installed: string[], wanted: string): boolean {\n const wantedNorm = normalizeModelName(wanted);\n const wantedLower = wanted.toLowerCase();\n return installed.some((n) => {\n const base = n.toLowerCase();\n if (base === wantedLower) return true;\n // Looser match for variant tags (e.g. \"qwen3.5:9b-q4_K_M\" matches \"qwen3.5\")\n return normalizeModelName(base).startsWith(wantedNorm);\n });\n}\n\nasync function pullOllamaModel(model: string): Promise<boolean> {\n note(\n `Pulling ${pc.cyan(model)}\\n${pc.dim(\"This can take a while on the first run (several GB download).\")}`,\n \"Downloading model\"\n );\n return new Promise((resolvePromise) => {\n const child = spawn(\"ollama\", [\"pull\", model], { stdio: \"inherit\" });\n child.on(\"error\", () => {\n process.stderr.write(\n pc.red(\"\\nFailed to run `ollama pull`. Make sure Ollama is installed and running.\\n\")\n );\n resolvePromise(false);\n });\n child.on(\"close\", (code) => {\n if (code === 0) {\n process.stdout.write(pc.green(`\\n\\u2713 Pulled ${model}\\n`));\n resolvePromise(true);\n } else {\n process.stderr.write(pc.red(`\\n\\u2717 ollama pull exited with code ${code}\\n`));\n resolvePromise(false);\n }\n });\n });\n}\n\n\nfunction handleCancel<T>(value: T | symbol): asserts value is T {\n if (isCancel(value)) {\n cancel(\"Exited without saving.\");\n process.exit(0);\n }\n}\n\nfunction renderCurrent(config: Config): string {\n const hooks: string[] = [];\n if (config.hooks.edit) hooks.push(\"Edit\");\n if (config.hooks.write) hooks.push(\"Write\");\n if (config.hooks.bash) hooks.push(\"Bash\");\n\n const excluded = config.exclude.length > 0 ? config.exclude.join(\", \") : \"(none)\";\n const timeoutLabel =\n config.skipIfSlowMs === 0 ? \"Never skip\" : `${Math.round(config.skipIfSlowMs / 1000)}s`;\n\n return [\n `${pc.bold(\"Engine: \")} ${config.engine === \"ollama\" ? \"Local LLM (Ollama)\" : \"Claude Code (native)\"}`,\n `${pc.bold(\"Model: \")} ${config.ollamaModel}`,\n `${pc.bold(\"Ollama URL: \")} ${config.ollamaUrl}`,\n `${pc.bold(\"Detail level: \")} ${config.detailLevel}`,\n `${pc.bold(\"Language: \")} ${LANGUAGE_NAMES[config.language]}`,\n `${pc.bold(\"Learner level:\")} ${LEARNER_LEVEL_NAMES[config.learnerLevel]}`,\n `${pc.bold(\"Hooks: \")} ${hooks.map((h) => `${h} \\u2713`).join(\" \") || \"(all disabled)\"}`,\n `${pc.bold(\"Excluded: \")} ${excluded}`,\n `${pc.bold(\"Skip if slow: \")} ${timeoutLabel}`,\n ].join(\"\\n\");\n}\n\ntype MenuChoice =\n | \"engine\"\n | \"model\"\n | \"url\"\n | \"detail\"\n | \"language\"\n | \"level\"\n | \"hooks\"\n | \"exclude\"\n | \"timeout\"\n | \"back\";\n\nasync function changeEngine(config: Config): Promise<Config> {\n const value = await select<Engine>({\n message: \"Explanation engine\",\n options: [\n { label: \"Local LLM (Ollama)\", value: \"ollama\", hint: \"free, private, works offline\" },\n { label: \"Claude Code (native)\", value: \"claude\", hint: \"best quality, uses API tokens\" },\n ],\n initialValue: config.engine,\n });\n handleCancel(value);\n return { ...config, engine: value };\n}\n\nasync function changeModel(config: Config): Promise<Config> {\n const value = await select({\n message: \"Ollama model\",\n options: MODEL_OPTIONS.map((m) => ({\n label: m.label,\n value: m.model,\n hint: m.hint,\n })),\n initialValue: config.ollamaModel,\n });\n handleCancel(value);\n\n if (value === config.ollamaModel) {\n // Nothing actually changed; skip the download check.\n return config;\n }\n\n // Check whether Ollama already has the model pulled. If not, offer to pull it.\n const installed = await listInstalledOllamaModels(config.ollamaUrl);\n if (installed === null) {\n note(\n `Could not reach Ollama at ${pc.cyan(config.ollamaUrl)}. The model will be selected, but you'll need to pull it manually with ${pc.cyan(`ollama pull ${value}`)} before the first explanation.`,\n \"Ollama unreachable\"\n );\n return { ...config, ollamaModel: value };\n }\n\n if (hasModel(installed, value)) {\n note(`${pc.green(\"\\u2713\")} Model ${pc.cyan(value)} is already installed.`, \"Model ready\");\n return { ...config, ollamaModel: value };\n }\n\n const shouldPull = await confirm({\n message: `Model ${value} is not installed locally. Pull it now?`,\n initialValue: true,\n });\n handleCancel(shouldPull);\n\n if (!shouldPull) {\n note(\n `Saved the selection, but you must run ${pc.cyan(`ollama pull ${value}`)} before it works.`,\n \"Model not pulled\"\n );\n return { ...config, ollamaModel: value };\n }\n\n const pullOk = await pullOllamaModel(value);\n if (!pullOk) {\n note(\n `Pull failed. Saving the model selection anyway — run ${pc.cyan(`ollama pull ${value}`)} manually when Ollama is reachable.`,\n \"Pull failed\"\n );\n }\n return { ...config, ollamaModel: value };\n}\n\nasync function changeUrl(config: Config): Promise<Config> {\n const value = await text({\n message: \"Ollama endpoint URL\",\n initialValue: config.ollamaUrl,\n validate(v) {\n try {\n new URL(v);\n return;\n } catch {\n return \"Must be a valid URL (e.g., http://localhost:11434)\";\n }\n },\n });\n handleCancel(value);\n return { ...config, ollamaUrl: value };\n}\n\nasync function changeDetail(config: Config): Promise<Config> {\n const value = await select<DetailLevel>({\n message: \"Detail level\",\n options: [\n { label: \"Standard\", value: \"standard\", hint: \"1-2 sentence explanation per change (recommended)\" },\n { label: \"Minimal\", value: \"minimal\", hint: \"one short sentence per change\" },\n { label: \"Verbose\", value: \"verbose\", hint: \"detailed bullet-point breakdown\" },\n ],\n initialValue: config.detailLevel,\n });\n handleCancel(value);\n return { ...config, detailLevel: value };\n}\n\nasync function changeLanguage(config: Config): Promise<Config> {\n const value = await select<Language>({\n message: \"Language for explanations\",\n options: (Object.keys(LANGUAGE_NAMES) as Language[]).map((code) => ({\n label: LANGUAGE_NAMES[code],\n value: code,\n hint: code === \"en\" ? \"default\" : undefined,\n })),\n initialValue: config.language,\n });\n handleCancel(value);\n return { ...config, language: value };\n}\n\nasync function changeLevel(config: Config): Promise<Config> {\n const value = await select<LearnerLevel>({\n message: \"Programming knowledge level\",\n options: (Object.keys(LEARNER_LEVEL_NAMES) as LearnerLevel[]).map((code) => ({\n label: LEARNER_LEVEL_NAMES[code],\n value: code,\n hint: code === \"intermediate\" ? \"default\" : undefined,\n })),\n initialValue: config.learnerLevel,\n });\n handleCancel(value);\n return { ...config, learnerLevel: value };\n}\n\nasync function changeHooks(config: Config): Promise<Config> {\n const editOn = await confirm({ message: \"Explain file edits?\", initialValue: config.hooks.edit });\n handleCancel(editOn);\n const writeOn = await confirm({ message: \"Explain new files?\", initialValue: config.hooks.write });\n handleCancel(writeOn);\n const bashOn = await confirm({\n message: \"Explain destructive Bash commands (rm, git reset, etc.)?\",\n initialValue: config.hooks.bash,\n });\n handleCancel(bashOn);\n\n return {\n ...config,\n hooks: { edit: editOn, write: writeOn, bash: bashOn },\n };\n}\n\nasync function changeExclude(config: Config): Promise<Config> {\n const action = await select({\n message: `Current exclusions: ${config.exclude.join(\", \") || \"(none)\"}`,\n options: [\n { label: \"Add a pattern\", value: \"add\", hint: \"e.g., *.generated.*\" },\n { label: \"Remove a pattern\", value: \"remove\" },\n { label: \"Reset to defaults\", value: \"reset\", hint: DEFAULT_CONFIG.exclude.join(\", \") },\n { label: \"Back\", value: \"back\" },\n ],\n });\n handleCancel(action);\n\n if (action === \"back\") return config;\n if (action === \"reset\") return { ...config, exclude: [...DEFAULT_CONFIG.exclude] };\n\n if (action === \"add\") {\n const pattern = await text({ message: \"Glob pattern to exclude (e.g., *.generated.*)\" });\n handleCancel(pattern);\n if (!pattern.trim()) return config;\n const exclude = Array.from(new Set([...config.exclude, pattern.trim()]));\n return { ...config, exclude };\n }\n\n if (action === \"remove\") {\n if (config.exclude.length === 0) {\n note(\"No exclusions to remove.\", \"Exclusions\");\n return config;\n }\n const target = await select({\n message: \"Which pattern to remove?\",\n options: config.exclude.map((p) => ({ label: p, value: p })),\n });\n handleCancel(target);\n const exclude = config.exclude.filter((p) => p !== target);\n return { ...config, exclude };\n }\n\n return config;\n}\n\nasync function changeTimeout(config: Config): Promise<Config> {\n const value = await select<number>({\n message: \"Skip explanation if it takes longer than...\",\n options: [\n { label: \"5 seconds\", value: 5000, hint: \"fast, may skip complex changes\" },\n { label: \"8 seconds\", value: 8000, hint: \"balanced (recommended)\" },\n { label: \"15 seconds\", value: 15000, hint: \"patient, rarely skips\" },\n { label: \"Never skip\", value: 0, hint: \"always wait for the explanation\" },\n ],\n initialValue: config.skipIfSlowMs,\n });\n handleCancel(value);\n return { ...config, skipIfSlowMs: value };\n}\n\nfunction resolveConfigPath(): { configPath: string; scope: \"project\" | \"global\" } | null {\n const projectPath = join(process.cwd(), CONFIG_FILENAME);\n const globalPath = getGlobalConfigPath();\n if (existsSync(projectPath)) return { configPath: projectPath, scope: \"project\" };\n if (existsSync(globalPath)) return { configPath: globalPath, scope: \"global\" };\n return null;\n}\n\n/**\n * config show [--json]\n * Print the effective config. With --json, outputs machine-readable JSON so\n * agents can pipe to jq or parse directly.\n */\nfunction runConfigShow(args: string[]): void {\n const { flags } = parseFlags(args);\n const json = flagBool(flags, \"json\", \"j\");\n\n const resolved = resolveConfigPath();\n if (!resolved) {\n process.stderr.write(\"[code-explainer] No config file found. Run 'vibe-code-explainer init' first.\\n\");\n process.exit(1);\n }\n const config = loadConfig(resolved.configPath);\n if (json) {\n process.stdout.write(JSON.stringify(config, null, 2) + \"\\n\");\n } else {\n process.stderr.write(renderCurrent(config) + \"\\n\");\n }\n}\n\n/**\n * config get <key>\n * Print a single config field as a plain string (for scripting).\n * Key may be dot-separated for nested fields (e.g. hooks.bash).\n */\nfunction runConfigGet(args: string[]): void {\n const { positional } = parseFlags(args);\n const key = positional[0];\n if (!key) {\n process.stderr.write(\"[code-explainer] Usage: vibe-code-explainer config get <key>\\n\");\n process.exit(1);\n }\n const resolved = resolveConfigPath();\n if (!resolved) {\n process.stderr.write(\"[code-explainer] No config file found. Run 'vibe-code-explainer init' first.\\n\");\n process.exit(1);\n }\n const config = loadConfig(resolved.configPath) as unknown as Record<string, unknown>;\n const parts = key.split(\".\");\n let cur: unknown = config;\n for (const part of parts) {\n if (typeof cur !== \"object\" || cur === null) {\n process.stderr.write(`[code-explainer] Key '${key}' not found in config.\\n`);\n process.exit(1);\n }\n cur = (cur as Record<string, unknown>)[part];\n }\n if (cur === undefined) {\n process.stderr.write(`[code-explainer] Key '${key}' not found in config.\\n`);\n process.exit(1);\n }\n // Output plain scalar or JSON for objects/arrays.\n if (typeof cur === \"object\") {\n process.stdout.write(JSON.stringify(cur) + \"\\n\");\n } else {\n process.stdout.write(String(cur) + \"\\n\");\n }\n}\n\n/**\n * config set <key> <value>\n * Set a single config field. The value is parsed as JSON when it looks like\n * a JSON literal (number, boolean, array, object), otherwise treated as a\n * plain string.\n */\nfunction runConfigSet(args: string[]): void {\n const { positional } = parseFlags(args);\n const [key, rawValue] = positional;\n if (!key || rawValue === undefined) {\n process.stderr.write(\"[code-explainer] Usage: vibe-code-explainer config set <key> <value>\\n\");\n process.exit(1);\n }\n const resolved = resolveConfigPath();\n if (!resolved) {\n process.stderr.write(\"[code-explainer] No config file found. Run 'vibe-code-explainer init' first.\\n\");\n process.exit(1);\n }\n\n let value: unknown = rawValue;\n try {\n value = JSON.parse(rawValue);\n } catch {\n // Use as plain string\n }\n\n // Deep-set the key into the config object.\n const config = loadConfig(resolved.configPath) as unknown as Record<string, unknown>;\n const parts = key.split(\".\");\n let cur: Record<string, unknown> = config;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (typeof cur[part] !== \"object\" || cur[part] === null) {\n cur[part] = {};\n }\n cur = cur[part] as Record<string, unknown>;\n }\n cur[parts[parts.length - 1]] = value;\n\n // Validate the mutated config before writing so invalid values are rejected.\n try {\n validateConfig(config);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`${msg}\\n`);\n process.exit(1);\n }\n\n writeFileSync(resolved.configPath, JSON.stringify(config, null, 2) + \"\\n\");\n process.stderr.write(`[code-explainer] Set ${key} = ${JSON.stringify(value)} in ${resolved.configPath}\\n`);\n}\n\nexport async function runConfig(rawArgs: string[] = []): Promise<void> {\n const { flags, positional } = parseFlags(rawArgs);\n const subcommand = positional[0];\n const subArgs = positional.slice(1);\n\n // Non-interactive subcommands for agent-native access.\n if (subcommand === \"show\") { runConfigShow([...subArgs, ...Object.entries(flags).flatMap(([k, v]) => v === true ? [`--${k}`] : [`--${k}=${v}`])]); return; }\n if (subcommand === \"get\") { runConfigGet(subArgs); return; }\n if (subcommand === \"set\") { runConfigSet(subArgs); return; }\n\n // Interactive TUI mode.\n const projectPath = join(process.cwd(), CONFIG_FILENAME);\n const globalPath = getGlobalConfigPath();\n\n let configPath: string;\n let scope: \"project\" | \"global\";\n if (existsSync(projectPath)) {\n configPath = projectPath;\n scope = \"project\";\n } else if (existsSync(globalPath)) {\n configPath = globalPath;\n scope = \"global\";\n } else {\n intro(pc.bold(\"code-explainer config\"));\n cancel(\n `No config file found.\\nSearched: ${pc.cyan(projectPath)}\\n ${pc.cyan(globalPath)}\\nRun ${pc.cyan(\"npx vibe-code-explainer init\")} first.`\n );\n process.exit(1);\n }\n\n intro(pc.bold(`code-explainer config (${scope})`));\n\n // --yes: skip confirmation for non-interactive environments.\n const skipConfirm = flagBool(flags, \"yes\", \"y\");\n\n let config = loadConfig(configPath);\n\n while (true) {\n note(renderCurrent(config), \"Current settings\");\n\n const choice = await select<MenuChoice>({\n message: \"What would you like to change?\",\n options: [\n { label: \"Engine\", value: \"engine\" },\n { label: \"Model\", value: \"model\" },\n { label: \"Ollama URL\", value: \"url\" },\n { label: \"Detail level\", value: \"detail\" },\n { label: \"Language\", value: \"language\" },\n { label: \"Learner level\", value: \"level\" },\n { label: \"Enable/disable hooks\", value: \"hooks\" },\n { label: \"File exclusions\", value: \"exclude\" },\n { label: \"Latency timeout\", value: \"timeout\" },\n { label: \"Back (save and exit)\", value: \"back\" },\n ],\n });\n handleCancel(choice);\n\n if (choice === \"back\") break;\n if (choice === \"engine\") config = await changeEngine(config);\n if (choice === \"model\") config = await changeModel(config);\n if (choice === \"url\") config = await changeUrl(config);\n if (choice === \"detail\") config = await changeDetail(config);\n if (choice === \"language\") config = await changeLanguage(config);\n if (choice === \"level\") config = await changeLevel(config);\n if (choice === \"hooks\") config = await changeHooks(config);\n if (choice === \"exclude\") config = await changeExclude(config);\n if (choice === \"timeout\") config = await changeTimeout(config);\n\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n }\n\n if (!skipConfirm) {\n outro(pc.green(\"Settings saved.\"));\n }\n}\n"],"mappings":"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","names":[]}
|