mneme-ai 2.47.0 → 2.49.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/alias_resolver.d.ts +50 -0
- package/dist/alias_resolver.d.ts.map +1 -0
- package/dist/alias_resolver.js +129 -0
- package/dist/alias_resolver.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +149 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.49.0 — AUTO-ALIAS RESOLVER.
|
|
3
|
+
*
|
|
4
|
+
* Wild idea: the WIRING LAG class isn't just "feature shipped but CLI verb
|
|
5
|
+
* missing" — it's ALSO "feature shipped but user typed a NATURAL ALIAS
|
|
6
|
+
* that doesn't exist". v2.48 shipped `mneme dev_tooling detect`; user
|
|
7
|
+
* tried `mneme dev` / `mneme detect` / `mneme tool_detect` and got
|
|
8
|
+
* cryptic `unknown command`. That's wiring lag at the keyboard surface.
|
|
9
|
+
*
|
|
10
|
+
* This module kills the class STRUCTURALLY:
|
|
11
|
+
* 1. Levenshtein-based fuzzy match against all known top-level verbs
|
|
12
|
+
* 2. Top-3 suggestions printed when user types unknown verb
|
|
13
|
+
* 3. Heat-map ledger of misses → next release adds them as real aliases
|
|
14
|
+
* 4. Intent-router fallback for natural-language phrases
|
|
15
|
+
*
|
|
16
|
+
* Pure deterministic except for the file-write to the heat-map ledger.
|
|
17
|
+
* Defensive — never throws.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Classic Levenshtein with single-char + transposition + similar-key
|
|
21
|
+
* discounts. O(m·n) DP — fine for command names (typically ≤ 20 chars).
|
|
22
|
+
*/
|
|
23
|
+
export declare function levenshteinDistance(a: string, b: string): number;
|
|
24
|
+
export interface Suggestion {
|
|
25
|
+
command: string;
|
|
26
|
+
distance: number;
|
|
27
|
+
/** Heuristic: does user's verb START WITH the command (or vice versa)? */
|
|
28
|
+
prefixMatch: boolean;
|
|
29
|
+
/** Distance normalized to candidate length (0=identical, 1=totally different). */
|
|
30
|
+
normalizedDistance: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Return top-N suggestions for `typed` from `known` commands, sorted by
|
|
34
|
+
* (prefixMatch desc, distance asc, normalizedDistance asc).
|
|
35
|
+
*/
|
|
36
|
+
export declare function suggestCommands(typed: string, known: ReadonlyArray<string>, opts?: {
|
|
37
|
+
topN?: number;
|
|
38
|
+
maxDistance?: number;
|
|
39
|
+
}): Suggestion[];
|
|
40
|
+
/**
|
|
41
|
+
* Append a missed-verb to the heat-map ledger so future releases can
|
|
42
|
+
* pre-add as a real alias. Never throws; best-effort write only.
|
|
43
|
+
*/
|
|
44
|
+
export declare function logMissedAlias(repoRoot: string, verb: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Print a friendly suggestion block to stderr. Returns the suggested
|
|
47
|
+
* command if there's a clear winner (distance ≤ 2), else null.
|
|
48
|
+
*/
|
|
49
|
+
export declare function printSuggestions(typed: string, suggestions: Suggestion[]): string | null;
|
|
50
|
+
//# sourceMappingURL=alias_resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alias_resolver.d.ts","sourceRoot":"","sources":["../src/alias_resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAyBhE;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,WAAW,EAAE,OAAO,CAAC;IACrB,kFAAkF;IAClF,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,EAC5B,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,UAAU,EAAE,CAoBd;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAQnE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,GAAG,IAAI,CA0BxF"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.49.0 — AUTO-ALIAS RESOLVER.
|
|
3
|
+
*
|
|
4
|
+
* Wild idea: the WIRING LAG class isn't just "feature shipped but CLI verb
|
|
5
|
+
* missing" — it's ALSO "feature shipped but user typed a NATURAL ALIAS
|
|
6
|
+
* that doesn't exist". v2.48 shipped `mneme dev_tooling detect`; user
|
|
7
|
+
* tried `mneme dev` / `mneme detect` / `mneme tool_detect` and got
|
|
8
|
+
* cryptic `unknown command`. That's wiring lag at the keyboard surface.
|
|
9
|
+
*
|
|
10
|
+
* This module kills the class STRUCTURALLY:
|
|
11
|
+
* 1. Levenshtein-based fuzzy match against all known top-level verbs
|
|
12
|
+
* 2. Top-3 suggestions printed when user types unknown verb
|
|
13
|
+
* 3. Heat-map ledger of misses → next release adds them as real aliases
|
|
14
|
+
* 4. Intent-router fallback for natural-language phrases
|
|
15
|
+
*
|
|
16
|
+
* Pure deterministic except for the file-write to the heat-map ledger.
|
|
17
|
+
* Defensive — never throws.
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, mkdirSync, appendFileSync } from "node:fs";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
/**
|
|
22
|
+
* Classic Levenshtein with single-char + transposition + similar-key
|
|
23
|
+
* discounts. O(m·n) DP — fine for command names (typically ≤ 20 chars).
|
|
24
|
+
*/
|
|
25
|
+
export function levenshteinDistance(a, b) {
|
|
26
|
+
if (!a || !b)
|
|
27
|
+
return Math.max(a?.length ?? 0, b?.length ?? 0);
|
|
28
|
+
a = a.toLowerCase();
|
|
29
|
+
b = b.toLowerCase();
|
|
30
|
+
if (a === b)
|
|
31
|
+
return 0;
|
|
32
|
+
const m = a.length;
|
|
33
|
+
const n = b.length;
|
|
34
|
+
const d = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
|
|
35
|
+
for (let i = 0; i <= m; i++)
|
|
36
|
+
d[i][0] = i;
|
|
37
|
+
for (let j = 0; j <= n; j++)
|
|
38
|
+
d[0][j] = j;
|
|
39
|
+
for (let i = 1; i <= m; i++) {
|
|
40
|
+
for (let j = 1; j <= n; j++) {
|
|
41
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
42
|
+
d[i][j] = Math.min(d[i - 1][j] + 1, // deletion
|
|
43
|
+
d[i][j - 1] + 1, // insertion
|
|
44
|
+
d[i - 1][j - 1] + cost);
|
|
45
|
+
// Damerau transposition discount
|
|
46
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
47
|
+
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return d[m][n];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Return top-N suggestions for `typed` from `known` commands, sorted by
|
|
55
|
+
* (prefixMatch desc, distance asc, normalizedDistance asc).
|
|
56
|
+
*/
|
|
57
|
+
export function suggestCommands(typed, known, opts = {}) {
|
|
58
|
+
const topN = opts.topN ?? 5;
|
|
59
|
+
const maxDistance = opts.maxDistance ?? 10;
|
|
60
|
+
const t = (typed ?? "").toLowerCase();
|
|
61
|
+
if (!t)
|
|
62
|
+
return [];
|
|
63
|
+
const scored = [];
|
|
64
|
+
for (const cmd of known) {
|
|
65
|
+
const c = cmd.toLowerCase();
|
|
66
|
+
const dist = levenshteinDistance(t, c);
|
|
67
|
+
if (dist > maxDistance)
|
|
68
|
+
continue;
|
|
69
|
+
const prefixMatch = c.startsWith(t) || t.startsWith(c);
|
|
70
|
+
const normalizedDistance = c.length === 0 ? 1 : dist / Math.max(c.length, t.length);
|
|
71
|
+
scored.push({ command: cmd, distance: dist, prefixMatch, normalizedDistance });
|
|
72
|
+
}
|
|
73
|
+
scored.sort((a, b) => {
|
|
74
|
+
if (a.prefixMatch !== b.prefixMatch)
|
|
75
|
+
return a.prefixMatch ? -1 : 1;
|
|
76
|
+
if (a.distance !== b.distance)
|
|
77
|
+
return a.distance - b.distance;
|
|
78
|
+
return a.normalizedDistance - b.normalizedDistance;
|
|
79
|
+
});
|
|
80
|
+
return scored.slice(0, topN);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Append a missed-verb to the heat-map ledger so future releases can
|
|
84
|
+
* pre-add as a real alias. Never throws; best-effort write only.
|
|
85
|
+
*/
|
|
86
|
+
export function logMissedAlias(repoRoot, verb) {
|
|
87
|
+
if (!repoRoot || !verb)
|
|
88
|
+
return;
|
|
89
|
+
try {
|
|
90
|
+
const dir = join(repoRoot, ".mneme");
|
|
91
|
+
if (!existsSync(dir))
|
|
92
|
+
mkdirSync(dir, { recursive: true });
|
|
93
|
+
const path = join(dir, "alias_misses.jsonl");
|
|
94
|
+
appendFileSync(path, JSON.stringify({ at: new Date().toISOString(), verb }) + "\n");
|
|
95
|
+
}
|
|
96
|
+
catch { /* defensive */ }
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Print a friendly suggestion block to stderr. Returns the suggested
|
|
100
|
+
* command if there's a clear winner (distance ≤ 2), else null.
|
|
101
|
+
*/
|
|
102
|
+
export function printSuggestions(typed, suggestions) {
|
|
103
|
+
if (suggestions.length === 0) {
|
|
104
|
+
process.stderr.write(`\n❓ Unknown command: ${JSON.stringify(typed)}\n`);
|
|
105
|
+
process.stderr.write(` Run \`mneme --help\` to see all available commands.\n\n`);
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
const winner = suggestions[0];
|
|
109
|
+
if (winner.distance <= 2 || winner.prefixMatch) {
|
|
110
|
+
process.stderr.write(`\n❓ Unknown command: ${JSON.stringify(typed)}\n\n`);
|
|
111
|
+
process.stderr.write(` Did you mean \`mneme ${winner.command}\`?\n`);
|
|
112
|
+
if (suggestions.length > 1) {
|
|
113
|
+
process.stderr.write(`\n Other closest matches:\n`);
|
|
114
|
+
for (const s of suggestions.slice(1, 4)) {
|
|
115
|
+
process.stderr.write(` • mneme ${s.command} (distance ${s.distance})\n`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
process.stderr.write(`\n Tip: set MNEME_AUTO_ALIAS=1 to auto-run the best match next time.\n\n`);
|
|
119
|
+
return winner.command;
|
|
120
|
+
}
|
|
121
|
+
process.stderr.write(`\n❓ Unknown command: ${JSON.stringify(typed)}\n`);
|
|
122
|
+
process.stderr.write(` Closest matches:\n`);
|
|
123
|
+
for (const s of suggestions.slice(0, 4)) {
|
|
124
|
+
process.stderr.write(` • mneme ${s.command} (distance ${s.distance})\n`);
|
|
125
|
+
}
|
|
126
|
+
process.stderr.write(`\n Run \`mneme --help\` for the full command list.\n\n`);
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=alias_resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alias_resolver.js","sourceRoot":"","sources":["../src/alias_resolver.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAuIA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAuIA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6yJvD"}
|
package/dist/index.js
CHANGED
|
@@ -4526,6 +4526,117 @@ export async function run(argv) {
|
|
|
4526
4526
|
registerArgusCommand(program);
|
|
4527
4527
|
// v2.46.0 — NEMESIS (Anti-Identity-Lie Engine + EU AI Act Article 50)
|
|
4528
4528
|
registerNemesisCommand(program);
|
|
4529
|
+
// v2.49.0 — B5 MULTI-ALIAS + F7 probe-coverage CLI + AUTO-ALIAS RESOLVER.
|
|
4530
|
+
// Closes wiring-lag-of-wiring-lag-fix: v2.48 shipped one verb; users
|
|
4531
|
+
// typed natural aliases (dev/detect/tool_detect) — all unknown. v2.49
|
|
4532
|
+
// wires every alias to the same handler.
|
|
4533
|
+
const devToolingDetect = async (path) => {
|
|
4534
|
+
try {
|
|
4535
|
+
const core = await import("@mneme-ai/core");
|
|
4536
|
+
const r = core.autoInit.detectDevTooling(path);
|
|
4537
|
+
process.stdout.write(JSON.stringify({ ok: true, path, result: r }, null, 2) + "\n");
|
|
4538
|
+
}
|
|
4539
|
+
catch (e) {
|
|
4540
|
+
process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
|
|
4541
|
+
process.exitCode = 1;
|
|
4542
|
+
}
|
|
4543
|
+
};
|
|
4544
|
+
// Aliases: `mneme detect`, `mneme tool_detect`, `mneme dev` (with no
|
|
4545
|
+
// sub) — all route to dev-tooling detect on current CWD.
|
|
4546
|
+
for (const alias of ["detect", "tool_detect"]) {
|
|
4547
|
+
program
|
|
4548
|
+
.command(alias)
|
|
4549
|
+
.description(`v2.49 alias for \`mneme dev_tooling detect\` — detect AI-dev scratch folder vs customer git repo.`)
|
|
4550
|
+
.option("--path <dir>", "Folder to check (default cwd).")
|
|
4551
|
+
.action(async (opts) => devToolingDetect(opts.path ?? process.cwd()));
|
|
4552
|
+
}
|
|
4553
|
+
// `mneme dev` parent — has `detect` subcommand AND default action.
|
|
4554
|
+
const devParent = program
|
|
4555
|
+
.command("dev")
|
|
4556
|
+
.description("v2.49 short alias for `mneme dev_tooling` — short-form access to DEV-TOOLING DETECTOR + RETROACTIVE CLEANSE.")
|
|
4557
|
+
.option("--path <dir>", "Folder to check (default cwd).")
|
|
4558
|
+
.action(async (opts) => devToolingDetect(opts.path ?? process.cwd()));
|
|
4559
|
+
devParent.command("detect")
|
|
4560
|
+
.description("Detect AI-dev folder.")
|
|
4561
|
+
.option("--path <dir>", "Folder.")
|
|
4562
|
+
.action(async (opts) => devToolingDetect(opts.path ?? process.cwd()));
|
|
4563
|
+
// v2.49.0 — F7 surface: `mneme release check` + `mneme probe coverage`.
|
|
4564
|
+
const releaseParent = program.command("release").description("v2.49 — release-time gates including MANDATORY probe-coverage check.");
|
|
4565
|
+
releaseParent.command("check")
|
|
4566
|
+
.description("Run the probe-coverage gate (refuses tag when new tool lacks TRUTH GATE probe binding).")
|
|
4567
|
+
.action(async () => {
|
|
4568
|
+
try {
|
|
4569
|
+
const core = await import("@mneme-ai/core");
|
|
4570
|
+
const r = core.releaseGate.crossCheckFromDisk(process.cwd());
|
|
4571
|
+
process.stdout.write(JSON.stringify(r, null, 2) + "\n");
|
|
4572
|
+
if (!r.ok)
|
|
4573
|
+
process.exitCode = 1;
|
|
4574
|
+
}
|
|
4575
|
+
catch (e) {
|
|
4576
|
+
process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
|
|
4577
|
+
process.exitCode = 1;
|
|
4578
|
+
}
|
|
4579
|
+
});
|
|
4580
|
+
const probeParent = program.command("probe").description("v2.49 — TRUTH GATE probe utilities.");
|
|
4581
|
+
probeParent.command("coverage")
|
|
4582
|
+
.description("Cross-check tool catalog vs claim catalog; report uncovered tools.")
|
|
4583
|
+
.action(async () => {
|
|
4584
|
+
try {
|
|
4585
|
+
const core = await import("@mneme-ai/core");
|
|
4586
|
+
const r = core.releaseGate.crossCheckFromDisk(process.cwd());
|
|
4587
|
+
process.stdout.write(JSON.stringify(r, null, 2) + "\n");
|
|
4588
|
+
if (!r.ok)
|
|
4589
|
+
process.exitCode = 1;
|
|
4590
|
+
}
|
|
4591
|
+
catch (e) {
|
|
4592
|
+
process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
|
|
4593
|
+
process.exitCode = 1;
|
|
4594
|
+
}
|
|
4595
|
+
});
|
|
4596
|
+
// v2.48.0 — Top-level `mneme dev_tooling` CLI (B5 fix: WIRING LAG class).
|
|
4597
|
+
// v2.45 shipped detectDevTooling() in core; v2.47 exposed it as MCP +
|
|
4598
|
+
// `mneme nemesis detect_tooling` subcommand — but users expect the
|
|
4599
|
+
// top-level verb. This adds `mneme dev_tooling [detect|cleanse]`.
|
|
4600
|
+
const dt = program.command("dev_tooling").description("v2.48 — Top-level surface for DEV-TOOLING DETECTOR (v2.45) + RETROACTIVE CLEANSE (v2.45). Closes WIRING LAG class: feature shipped in core but no top-level CLI verb.");
|
|
4601
|
+
dt.command("detect")
|
|
4602
|
+
.description("Detect whether CWD (or --path) is an AI-dev scratch folder vs customer git repo.")
|
|
4603
|
+
.option("--path <dir>", "Folder to check (default cwd).")
|
|
4604
|
+
.option("--json", "Force JSON output (default).")
|
|
4605
|
+
.action(async (opts) => {
|
|
4606
|
+
try {
|
|
4607
|
+
const core = await import("@mneme-ai/core");
|
|
4608
|
+
const path = opts.path ?? process.cwd();
|
|
4609
|
+
const r = core.autoInit.detectDevTooling(path);
|
|
4610
|
+
process.stdout.write(JSON.stringify({ ok: true, path, result: r }, null, 2) + "\n");
|
|
4611
|
+
}
|
|
4612
|
+
catch (e) {
|
|
4613
|
+
process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
|
|
4614
|
+
process.exitCode = 1;
|
|
4615
|
+
}
|
|
4616
|
+
});
|
|
4617
|
+
dt.command("cleanse")
|
|
4618
|
+
.description("Retroactive cleanse of AI-fingerprint files from git history. DRY-RUN default.")
|
|
4619
|
+
.option("--mode <m>", "scan | uncommit | filter-repo", "scan")
|
|
4620
|
+
.option("--execute", "Actually mutate (default dry-run).", false)
|
|
4621
|
+
.option("--confirm", "Required for filter-repo (destructive).", false)
|
|
4622
|
+
.action(async (opts) => {
|
|
4623
|
+
try {
|
|
4624
|
+
const core = await import("@mneme-ai/core");
|
|
4625
|
+
const r = core.cleanse({
|
|
4626
|
+
repoRoot: process.cwd(),
|
|
4627
|
+
mode: (opts.mode ?? "scan"),
|
|
4628
|
+
dryRun: !opts.execute,
|
|
4629
|
+
confirm: Boolean(opts.confirm),
|
|
4630
|
+
});
|
|
4631
|
+
process.stdout.write(JSON.stringify(r, null, 2) + "\n");
|
|
4632
|
+
if (!r.ok)
|
|
4633
|
+
process.exitCode = 1;
|
|
4634
|
+
}
|
|
4635
|
+
catch (e) {
|
|
4636
|
+
process.stdout.write(JSON.stringify({ ok: false, error: e.message }) + "\n");
|
|
4637
|
+
process.exitCode = 1;
|
|
4638
|
+
}
|
|
4639
|
+
});
|
|
4529
4640
|
// v2.19.8 — UNIVERSAL MCP SUBCOMMAND AUTO-ROUTER
|
|
4530
4641
|
// Reads the MCP tool catalog and auto-registers `mneme <family> <action>`
|
|
4531
4642
|
// for every MCP tool. Closes the "no CLI route for shipped MCP tool" bug
|
|
@@ -4709,8 +4820,45 @@ export async function run(argv) {
|
|
|
4709
4820
|
}
|
|
4710
4821
|
}
|
|
4711
4822
|
}
|
|
4712
|
-
//
|
|
4823
|
+
// v2.49.0 — AUTO-ALIAS RESOLVER. Before bailing with a cryptic
|
|
4824
|
+
// "unknown command" error, intercept the message + run Levenshtein
|
|
4825
|
+
// fuzzy match against all registered top-level verbs + print
|
|
4826
|
+
// suggestions. Closes the wiring-lag-at-keyboard-surface class.
|
|
4713
4827
|
restoreWriteErr();
|
|
4828
|
+
const unknownMatch = /unknown command (?:'|")([^'"]+)(?:'|")/i.exec(message);
|
|
4829
|
+
if (unknownMatch && unknownMatch[1]) {
|
|
4830
|
+
const typed = unknownMatch[1];
|
|
4831
|
+
try {
|
|
4832
|
+
const { suggestCommands, printSuggestions, logMissedAlias } = await import("./alias_resolver.js");
|
|
4833
|
+
// Gather all registered top-level command names.
|
|
4834
|
+
const known = [];
|
|
4835
|
+
for (const c of program.commands) {
|
|
4836
|
+
const name = (c.name?.() ?? c._name);
|
|
4837
|
+
if (name)
|
|
4838
|
+
known.push(name);
|
|
4839
|
+
}
|
|
4840
|
+
const suggestions = suggestCommands(typed, known, { topN: 5 });
|
|
4841
|
+
const winner = printSuggestions(typed, suggestions);
|
|
4842
|
+
try {
|
|
4843
|
+
logMissedAlias(process.cwd(), typed);
|
|
4844
|
+
}
|
|
4845
|
+
catch { /* */ }
|
|
4846
|
+
// Optional auto-run via env var
|
|
4847
|
+
if (winner && process.env["MNEME_AUTO_ALIAS"] === "1") {
|
|
4848
|
+
process.stderr.write(`\n→ MNEME_AUTO_ALIAS=1 set — auto-running \`mneme ${winner}\`...\n\n`);
|
|
4849
|
+
const restArgs = argv.slice(argv.findIndex((a) => a === typed) + 1);
|
|
4850
|
+
try {
|
|
4851
|
+
await program.parseAsync(["node", "mneme", winner, ...restArgs]);
|
|
4852
|
+
process.exit(0);
|
|
4853
|
+
}
|
|
4854
|
+
catch {
|
|
4855
|
+
process.exit(1);
|
|
4856
|
+
}
|
|
4857
|
+
}
|
|
4858
|
+
process.exit(1);
|
|
4859
|
+
}
|
|
4860
|
+
catch { /* fall through to generic error */ }
|
|
4861
|
+
}
|
|
4714
4862
|
ui.error(message);
|
|
4715
4863
|
process.exit(1);
|
|
4716
4864
|
}
|