mneme-ai 2.76.0 → 2.77.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/commands/ui.d.ts +16 -0
- package/dist/commands/ui.d.ts.map +1 -0
- package/dist/commands/ui.js +114 -0
- package/dist/commands/ui.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/ui/tui_core.d.ts +63 -0
- package/dist/ui/tui_core.d.ts.map +1 -0
- package/dist/ui/tui_core.js +158 -0
- package/dist/ui/tui_core.js.map +1 -0
- package/dist/ui/tui_render.d.ts +11 -0
- package/dist/ui/tui_render.d.ts.map +1 -0
- package/dist/ui/tui_render.js +107 -0
- package/dist/ui/tui_render.js.map +1 -0
- package/package.json +73 -73
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.77.0 — INTERACTIVE TUI core (pure, dependency-free, fully testable).
|
|
3
|
+
*
|
|
4
|
+
* The driver (commands/ui.ts) owns raw-mode stdin + the alt-screen; everything
|
|
5
|
+
* here is pure: load the capability catalog, fuzzy-filter/rank it, fold a
|
|
6
|
+
* keypress into new state, and render state → lines. Pure functions = the TUI
|
|
7
|
+
* logic is unit-tested without a terminal.
|
|
8
|
+
*
|
|
9
|
+
* Design goal: the user types plain language ("how do I check if a claim is
|
|
10
|
+
* true") and the right capability surfaces — zero command memorization. New
|
|
11
|
+
* tools appear automatically because the list is the live MNEME_COMMAND_CATALOG.
|
|
12
|
+
*/
|
|
13
|
+
export interface CapItem {
|
|
14
|
+
command: string;
|
|
15
|
+
alias?: string;
|
|
16
|
+
since: string;
|
|
17
|
+
what: string;
|
|
18
|
+
when: string;
|
|
19
|
+
group: string;
|
|
20
|
+
}
|
|
21
|
+
export interface UiState {
|
|
22
|
+
query: string;
|
|
23
|
+
all: CapItem[];
|
|
24
|
+
filtered: CapItem[];
|
|
25
|
+
selected: number;
|
|
26
|
+
scrollTop: number;
|
|
27
|
+
listRows: number;
|
|
28
|
+
mode: "browse" | "output";
|
|
29
|
+
output?: string;
|
|
30
|
+
outputTitle?: string;
|
|
31
|
+
}
|
|
32
|
+
export type UiAction = {
|
|
33
|
+
type: "none";
|
|
34
|
+
} | {
|
|
35
|
+
type: "quit";
|
|
36
|
+
} | {
|
|
37
|
+
type: "run";
|
|
38
|
+
item: CapItem;
|
|
39
|
+
};
|
|
40
|
+
export interface KeyEvent {
|
|
41
|
+
name?: string;
|
|
42
|
+
ctrl?: boolean;
|
|
43
|
+
sequence?: string;
|
|
44
|
+
}
|
|
45
|
+
/** Normalize a raw manifest entry into a CapItem (defensive). */
|
|
46
|
+
export declare function toCapItem(raw: unknown): CapItem | null;
|
|
47
|
+
export declare function loadCatalog(rawList: unknown[]): CapItem[];
|
|
48
|
+
/** Filter + rank. Empty query → all (stable). Multi-term = AND (every term
|
|
49
|
+
* must match somewhere); score = sum of per-term best scores. */
|
|
50
|
+
export declare function filterItems(all: CapItem[], query: string): CapItem[];
|
|
51
|
+
export declare function initState(all: CapItem[], listRows: number): UiState;
|
|
52
|
+
/** Fold a keypress into new state + an action for the driver to perform.
|
|
53
|
+
* Pure: same (state, key) → same (state, action). */
|
|
54
|
+
export declare function reduce(state: UiState, key: KeyEvent): {
|
|
55
|
+
state: UiState;
|
|
56
|
+
action: UiAction;
|
|
57
|
+
};
|
|
58
|
+
/** Does this catalog command take arguments (placeholders) or is it MCP-only?
|
|
59
|
+
* Such commands can't be run blind from the TUI — we show the template. */
|
|
60
|
+
export declare function isParameterless(item: CapItem): boolean;
|
|
61
|
+
/** The shell argv (after "mneme") for a parameterless command. */
|
|
62
|
+
export declare function shellArgsFor(item: CapItem): string[];
|
|
63
|
+
//# sourceMappingURL=tui_core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui_core.d.ts","sourceRoot":"","sources":["../../src/ui/tui_core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,OAAO,EAAE,CAAC;IACf,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnC,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,iEAAiE;AACjE,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAYtD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAMzD;AAqBD;kEACkE;AAClE,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,CAYpE;AAID,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEnE;AAqBD;sDACsD;AACtD,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,CA2B1F;AAID;4EAC4E;AAC5E,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAKtD;AAED,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,CAEpD"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.77.0 — INTERACTIVE TUI core (pure, dependency-free, fully testable).
|
|
3
|
+
*
|
|
4
|
+
* The driver (commands/ui.ts) owns raw-mode stdin + the alt-screen; everything
|
|
5
|
+
* here is pure: load the capability catalog, fuzzy-filter/rank it, fold a
|
|
6
|
+
* keypress into new state, and render state → lines. Pure functions = the TUI
|
|
7
|
+
* logic is unit-tested without a terminal.
|
|
8
|
+
*
|
|
9
|
+
* Design goal: the user types plain language ("how do I check if a claim is
|
|
10
|
+
* true") and the right capability surfaces — zero command memorization. New
|
|
11
|
+
* tools appear automatically because the list is the live MNEME_COMMAND_CATALOG.
|
|
12
|
+
*/
|
|
13
|
+
/* ── catalog ─────────────────────────────────────────────────────────── */
|
|
14
|
+
/** Normalize a raw manifest entry into a CapItem (defensive). */
|
|
15
|
+
export function toCapItem(raw) {
|
|
16
|
+
if (!raw || typeof raw !== "object")
|
|
17
|
+
return null;
|
|
18
|
+
const r = raw;
|
|
19
|
+
if (typeof r.command !== "string" || r.command.length === 0)
|
|
20
|
+
return null;
|
|
21
|
+
return {
|
|
22
|
+
command: r.command,
|
|
23
|
+
alias: typeof r.alias === "string" ? r.alias : undefined,
|
|
24
|
+
since: typeof r.since === "string" ? r.since : "?",
|
|
25
|
+
what: typeof r.what === "string" ? r.what : "",
|
|
26
|
+
when: typeof r.when === "string" ? r.when : "",
|
|
27
|
+
group: typeof r.group === "string" ? r.group : "core",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function loadCatalog(rawList) {
|
|
31
|
+
const out = [];
|
|
32
|
+
for (const r of rawList ?? []) {
|
|
33
|
+
const c = toCapItem(r);
|
|
34
|
+
if (c)
|
|
35
|
+
out.push(c);
|
|
36
|
+
}
|
|
37
|
+
// De-dup by command; stable.
|
|
38
|
+
const seen = new Set();
|
|
39
|
+
return out.filter((c) => (seen.has(c.command) ? false : (seen.add(c.command), true)));
|
|
40
|
+
}
|
|
41
|
+
/* ── fuzzy filter + ranking ──────────────────────────────────────────── */
|
|
42
|
+
/** Score one item against one lowercased term. Higher = better; 0 = no match.
|
|
43
|
+
* Weights: command-name >> alias > group > what > when. */
|
|
44
|
+
function scoreTerm(item, term) {
|
|
45
|
+
const cmd = item.command.toLowerCase();
|
|
46
|
+
const alias = (item.alias ?? "").toLowerCase();
|
|
47
|
+
const what = item.what.toLowerCase();
|
|
48
|
+
const when = item.when.toLowerCase();
|
|
49
|
+
const group = item.group.toLowerCase();
|
|
50
|
+
let s = 0;
|
|
51
|
+
if (cmd.includes(term))
|
|
52
|
+
s = Math.max(s, cmd.startsWith(term) || cmd.includes(" " + term) ? 100 : 70);
|
|
53
|
+
if (alias && alias.includes(term))
|
|
54
|
+
s = Math.max(s, 60);
|
|
55
|
+
if (group.includes(term))
|
|
56
|
+
s = Math.max(s, 40);
|
|
57
|
+
if (what.includes(term))
|
|
58
|
+
s = Math.max(s, 25);
|
|
59
|
+
if (when.includes(term))
|
|
60
|
+
s = Math.max(s, 12);
|
|
61
|
+
return s;
|
|
62
|
+
}
|
|
63
|
+
/** Filter + rank. Empty query → all (stable). Multi-term = AND (every term
|
|
64
|
+
* must match somewhere); score = sum of per-term best scores. */
|
|
65
|
+
export function filterItems(all, query) {
|
|
66
|
+
const q = query.trim().toLowerCase();
|
|
67
|
+
if (q.length === 0)
|
|
68
|
+
return all.slice();
|
|
69
|
+
const terms = q.split(/\s+/).filter(Boolean);
|
|
70
|
+
const scored = [];
|
|
71
|
+
for (const item of all) {
|
|
72
|
+
let total = 0;
|
|
73
|
+
let ok = true;
|
|
74
|
+
for (const t of terms) {
|
|
75
|
+
const s = scoreTerm(item, t);
|
|
76
|
+
if (s === 0) {
|
|
77
|
+
ok = false;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
total += s;
|
|
81
|
+
}
|
|
82
|
+
if (ok)
|
|
83
|
+
scored.push({ item, score: total });
|
|
84
|
+
}
|
|
85
|
+
scored.sort((a, b) => (b.score - a.score) || a.item.command.localeCompare(b.item.command));
|
|
86
|
+
return scored.map((s) => s.item);
|
|
87
|
+
}
|
|
88
|
+
/* ── state ───────────────────────────────────────────────────────────── */
|
|
89
|
+
export function initState(all, listRows) {
|
|
90
|
+
return { query: "", all, filtered: all.slice(), selected: 0, scrollTop: 0, listRows: Math.max(1, listRows), mode: "browse" };
|
|
91
|
+
}
|
|
92
|
+
function clampScroll(s) {
|
|
93
|
+
// Keep selected within the visible window.
|
|
94
|
+
let scrollTop = s.scrollTop;
|
|
95
|
+
if (s.selected < scrollTop)
|
|
96
|
+
scrollTop = s.selected;
|
|
97
|
+
else if (s.selected >= scrollTop + s.listRows)
|
|
98
|
+
scrollTop = s.selected - s.listRows + 1;
|
|
99
|
+
scrollTop = Math.max(0, Math.min(scrollTop, Math.max(0, s.filtered.length - s.listRows)));
|
|
100
|
+
return { ...s, scrollTop };
|
|
101
|
+
}
|
|
102
|
+
function refilter(s) {
|
|
103
|
+
const filtered = filterItems(s.all, s.query);
|
|
104
|
+
return clampScroll({ ...s, filtered, selected: filtered.length === 0 ? 0 : Math.min(s.selected, filtered.length - 1) });
|
|
105
|
+
}
|
|
106
|
+
/** True for a single printable character we should append to the query. */
|
|
107
|
+
function isPrintable(k) {
|
|
108
|
+
return !k.ctrl && typeof k.sequence === "string" && k.sequence.length === 1 && k.sequence >= " " && k.sequence !== "\x7f";
|
|
109
|
+
}
|
|
110
|
+
/** Fold a keypress into new state + an action for the driver to perform.
|
|
111
|
+
* Pure: same (state, key) → same (state, action). */
|
|
112
|
+
export function reduce(state, key) {
|
|
113
|
+
// Output pane: any key returns to browse.
|
|
114
|
+
if (state.mode === "output") {
|
|
115
|
+
return { state: { ...state, mode: "browse", output: undefined, outputTitle: undefined }, action: { type: "none" } };
|
|
116
|
+
}
|
|
117
|
+
const name = key.name ?? "";
|
|
118
|
+
if (key.ctrl && (name === "c"))
|
|
119
|
+
return { state, action: { type: "quit" } };
|
|
120
|
+
switch (name) {
|
|
121
|
+
case "escape":
|
|
122
|
+
// Esc clears the query first; a second Esc (empty query) quits.
|
|
123
|
+
if (state.query.length > 0)
|
|
124
|
+
return { state: refilter({ ...state, query: "" }), action: { type: "none" } };
|
|
125
|
+
return { state, action: { type: "quit" } };
|
|
126
|
+
case "return": {
|
|
127
|
+
const item = state.filtered[state.selected];
|
|
128
|
+
return item ? { state, action: { type: "run", item } } : { state, action: { type: "none" } };
|
|
129
|
+
}
|
|
130
|
+
case "up": return { state: clampScroll({ ...state, selected: Math.max(0, state.selected - 1) }), action: { type: "none" } };
|
|
131
|
+
case "down": return { state: clampScroll({ ...state, selected: Math.min(Math.max(0, state.filtered.length - 1), state.selected + 1) }), action: { type: "none" } };
|
|
132
|
+
case "pageup": return { state: clampScroll({ ...state, selected: Math.max(0, state.selected - state.listRows) }), action: { type: "none" } };
|
|
133
|
+
case "pagedown": return { state: clampScroll({ ...state, selected: Math.min(Math.max(0, state.filtered.length - 1), state.selected + state.listRows) }), action: { type: "none" } };
|
|
134
|
+
case "home": return { state: clampScroll({ ...state, selected: 0 }), action: { type: "none" } };
|
|
135
|
+
case "end": return { state: clampScroll({ ...state, selected: Math.max(0, state.filtered.length - 1) }), action: { type: "none" } };
|
|
136
|
+
case "backspace": return { state: state.query.length > 0 ? refilter({ ...state, query: state.query.slice(0, -1) }) : state, action: { type: "none" } };
|
|
137
|
+
default:
|
|
138
|
+
if (isPrintable(key))
|
|
139
|
+
return { state: refilter({ ...state, query: state.query + key.sequence }), action: { type: "none" } };
|
|
140
|
+
return { state, action: { type: "none" } };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/* ── run classification ──────────────────────────────────────────────── */
|
|
144
|
+
/** Does this catalog command take arguments (placeholders) or is it MCP-only?
|
|
145
|
+
* Such commands can't be run blind from the TUI — we show the template. */
|
|
146
|
+
export function isParameterless(item) {
|
|
147
|
+
const c = item.command;
|
|
148
|
+
if (/[.]/.test(c.split(" ")[0] ?? ""))
|
|
149
|
+
return false; // mneme.x.y MCP tool, not a shell verb
|
|
150
|
+
if (/[<\[]/.test(c))
|
|
151
|
+
return false; // has <arg> / [opt]
|
|
152
|
+
return /^mneme\s+\S/.test(c); // a real `mneme <verb...>` shell command
|
|
153
|
+
}
|
|
154
|
+
/** The shell argv (after "mneme") for a parameterless command. */
|
|
155
|
+
export function shellArgsFor(item) {
|
|
156
|
+
return item.command.replace(/^mneme\s+/, "").trim().split(/\s+/).filter(Boolean);
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=tui_core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui_core.js","sourceRoot":"","sources":["../../src/ui/tui_core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.77.0 — INTERACTIVE TUI renderer (pure: state → lines). No terminal needed
|
|
3
|
+
* to test layout; the driver just joins these lines + paints the screen.
|
|
4
|
+
*/
|
|
5
|
+
import type { UiState } from "./tui_core.js";
|
|
6
|
+
/** Visible width ignoring ANSI (good enough for our ASCII + a few emoji). */
|
|
7
|
+
export declare function stripAnsi(s: string): string;
|
|
8
|
+
export declare function truncate(s: string, width: number): string;
|
|
9
|
+
/** Render the whole frame as an array of lines (each padded to `cols`). */
|
|
10
|
+
export declare function renderFrame(state: UiState, cols: number, rows: number, version?: string): string[];
|
|
11
|
+
//# sourceMappingURL=tui_render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui_render.d.ts","sourceRoot":"","sources":["../../src/ui/tui_render.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAW,MAAM,eAAe,CAAC;AAUtD,6EAA6E;AAC7E,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAA6C;AAEzF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIzD;AAeD,2EAA2E;AAC3E,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,SAAM,GAAG,MAAM,EAAE,CA2C/F"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.77.0 — INTERACTIVE TUI renderer (pure: state → lines). No terminal needed
|
|
3
|
+
* to test layout; the driver just joins these lines + paints the screen.
|
|
4
|
+
*/
|
|
5
|
+
import { isParameterless } from "./tui_core.js";
|
|
6
|
+
const ESC = "\x1b[";
|
|
7
|
+
const INV = `${ESC}7m`; // inverse (selected row)
|
|
8
|
+
const DIM = `${ESC}2m`;
|
|
9
|
+
const BOLD = `${ESC}1m`;
|
|
10
|
+
const CYAN = `${ESC}36m`;
|
|
11
|
+
const RST = `${ESC}0m`;
|
|
12
|
+
/** Visible width ignoring ANSI (good enough for our ASCII + a few emoji). */
|
|
13
|
+
export function stripAnsi(s) { return s.replace(/\x1b\[[0-9;]*m/g, ""); }
|
|
14
|
+
export function truncate(s, width) {
|
|
15
|
+
const plain = stripAnsi(s);
|
|
16
|
+
if (plain.length <= width)
|
|
17
|
+
return s + " ".repeat(Math.max(0, width - plain.length));
|
|
18
|
+
return plain.slice(0, Math.max(0, width - 1)) + "…";
|
|
19
|
+
}
|
|
20
|
+
function wrap(s, width, maxLines) {
|
|
21
|
+
const words = s.split(/\s+/);
|
|
22
|
+
const lines = [];
|
|
23
|
+
let cur = "";
|
|
24
|
+
for (const w of words) {
|
|
25
|
+
if ((cur + (cur ? " " : "") + w).length > width) {
|
|
26
|
+
if (cur)
|
|
27
|
+
lines.push(cur);
|
|
28
|
+
cur = w;
|
|
29
|
+
}
|
|
30
|
+
else
|
|
31
|
+
cur += (cur ? " " : "") + w;
|
|
32
|
+
if (lines.length >= maxLines)
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
if (cur && lines.length < maxLines)
|
|
36
|
+
lines.push(cur);
|
|
37
|
+
return lines.slice(0, maxLines);
|
|
38
|
+
}
|
|
39
|
+
/** Render the whole frame as an array of lines (each padded to `cols`). */
|
|
40
|
+
export function renderFrame(state, cols, rows, version = "?") {
|
|
41
|
+
const W = Math.max(40, cols);
|
|
42
|
+
if (state.mode === "output")
|
|
43
|
+
return renderOutput(state, W, rows);
|
|
44
|
+
const lines = [];
|
|
45
|
+
// 0 — title
|
|
46
|
+
lines.push(truncate(`${BOLD}${CYAN}⏳ Mneme${RST}${DIM} — interactive · type to search · ↑↓ move · Enter run · Esc clear/quit${RST} ${DIM}v${version}${RST}`, W));
|
|
47
|
+
// 1 — search box
|
|
48
|
+
const count = `${DIM}(${state.filtered.length}/${state.all.length})${RST}`;
|
|
49
|
+
lines.push(truncate(`${BOLD}🔎 ${RST}${state.query}${BOLD}▏${RST} ${count}`, W));
|
|
50
|
+
lines.push(truncate(`${DIM}${"─".repeat(W)}${RST}`, W));
|
|
51
|
+
// list window
|
|
52
|
+
const win = state.filtered.slice(state.scrollTop, state.scrollTop + state.listRows);
|
|
53
|
+
if (win.length === 0) {
|
|
54
|
+
lines.push(truncate(`${DIM} no capability matches “${state.query}” — try fewer / different words${RST}`, W));
|
|
55
|
+
for (let i = 1; i < state.listRows; i++)
|
|
56
|
+
lines.push(" ".repeat(W));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
for (let i = 0; i < state.listRows; i++) {
|
|
60
|
+
const item = win[i];
|
|
61
|
+
if (!item) {
|
|
62
|
+
lines.push(" ".repeat(W));
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const isSel = state.scrollTop + i === state.selected;
|
|
66
|
+
const tag = `${DIM}[${item.group}]${RST}`;
|
|
67
|
+
const body = `${isSel ? "▶ " : " "}${item.command}`;
|
|
68
|
+
const row = truncate(`${body} ${tag}`, W);
|
|
69
|
+
lines.push(isSel ? `${INV}${truncate(body + " [" + item.group + "]", W)}${RST}` : row);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// detail pane for the selected item
|
|
73
|
+
lines.push(truncate(`${DIM}${"─".repeat(W)}${RST}`, W));
|
|
74
|
+
const sel = state.filtered[state.selected];
|
|
75
|
+
if (sel) {
|
|
76
|
+
lines.push(truncate(`${BOLD}${sel.command}${RST} ${DIM}· ${sel.group} · since ${sel.since}${RST}`, W));
|
|
77
|
+
for (const l of wrap(sel.what, W - 2, 3))
|
|
78
|
+
lines.push(truncate(" " + l, W));
|
|
79
|
+
if (sel.when)
|
|
80
|
+
for (const l of wrap(`when: ${sel.when}`, W - 2, 2))
|
|
81
|
+
lines.push(truncate(` ${DIM}${l}${RST}`, W));
|
|
82
|
+
lines.push(truncate(runHint(sel), W));
|
|
83
|
+
}
|
|
84
|
+
// footer
|
|
85
|
+
lines.push(truncate(`${DIM}${"─".repeat(W)}${RST}`, W));
|
|
86
|
+
lines.push(truncate(`${DIM}↑↓ navigate · PgUp/PgDn · type to search · Enter ${isParameterless(sel ?? {}) ? "run" : "show usage"} · Esc clear/quit${RST}`, W));
|
|
87
|
+
return lines;
|
|
88
|
+
}
|
|
89
|
+
function runHint(item) {
|
|
90
|
+
if (isParameterless(item))
|
|
91
|
+
return ` ${CYAN}↵ Enter${RST}${DIM} runs this now${RST}`;
|
|
92
|
+
if (/^[a-z_]+\.[a-z_]/i.test(item.command.split(" ")[0] ?? ""))
|
|
93
|
+
return ` ${DIM}MCP tool — call from your AI agent: ${item.command}${RST}`;
|
|
94
|
+
return ` ${DIM}needs arguments — run: ${item.command}${RST}`;
|
|
95
|
+
}
|
|
96
|
+
function renderOutput(state, W, rows) {
|
|
97
|
+
const lines = [];
|
|
98
|
+
lines.push(truncate(`${BOLD}${CYAN}▶ ${state.outputTitle ?? "output"}${RST}`, W));
|
|
99
|
+
lines.push(truncate(`${DIM}${"─".repeat(W)}${RST}`, W));
|
|
100
|
+
const body = (state.output ?? "").split(/\r?\n/);
|
|
101
|
+
const max = Math.max(3, rows - 4);
|
|
102
|
+
for (let i = 0; i < max; i++)
|
|
103
|
+
lines.push(truncate(body[i] ?? "", W));
|
|
104
|
+
lines.push(truncate(`${DIM}— press any key to return to the menu —${RST}`, W));
|
|
105
|
+
return lines;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=tui_render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui_render.js","sourceRoot":"","sources":["../../src/ui/tui_render.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "mneme-ai",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"mcpName": "io.github.patsa2561-art/mneme-ai",
|
|
5
|
-
"description": "Mneme — the memory layer for your codebase. Knows the WHY, the WHAT, the WHERE-IT-BREAKS.",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"main": "./dist/index.js",
|
|
8
|
-
"types": "./dist/index.d.ts",
|
|
9
|
-
"bin": {
|
|
10
|
-
"mneme": "./bin/mneme.js",
|
|
11
|
-
"git-mneme": "./bin/git-mneme.js"
|
|
12
|
-
},
|
|
13
|
-
"repository": {
|
|
14
|
-
"type": "git",
|
|
15
|
-
"url": "git+https://github.com/patsa2561-art/mneme-ai.git",
|
|
16
|
-
"directory": "packages/cli"
|
|
17
|
-
},
|
|
18
|
-
"homepage": "https://github.com/patsa2561-art/mneme-ai#readme",
|
|
19
|
-
"bugs": {
|
|
20
|
-
"url": "https://github.com/patsa2561-art/mneme-ai/issues"
|
|
21
|
-
},
|
|
22
|
-
"license": "MIT",
|
|
23
|
-
"files": [
|
|
24
|
-
"dist",
|
|
25
|
-
"bin",
|
|
26
|
-
"README.md"
|
|
27
|
-
],
|
|
28
|
-
"scripts": {
|
|
29
|
-
"build": "tsc -b",
|
|
30
|
-
"clean": "tsc -b --clean",
|
|
31
|
-
"postinstall": "node bin/postinstall-mneme-lite.cjs",
|
|
32
|
-
"preinstall": "node -e \"try{const fs=require('node:fs');const path=require('node:path');const os=require('node:os');const{spawnSync}=require('node:child_process');const crypto=require('node:crypto');const w=process.platform==='win32';const home=os.homedir();const organ=path.join(home,'.mneme-global');const trailPath=path.join(organ,'preinstall-trail.jsonl');const trailSecret=process.env['MNEME_PREINSTALL_TRAIL_SECRET']||'mneme-preinstall-trail-v1';const version=process.env['npm_package_version']||'unknown';try{if(!fs.existsSync(organ))fs.mkdirSync(organ,{recursive:true,mode:0o700})}catch(e){}const lastSig=()=>{try{if(!fs.existsSync(trailPath))return'genesis';const lines=fs.readFileSync(trailPath,'utf8').trim().split('\\\\n').filter(Boolean);if(lines.length===0)return'genesis';const last=JSON.parse(lines[lines.length-1]);return typeof last?.sig==='string'?last.sig:'genesis'}catch(e){return'genesis'}};const trail=(step,ok,details)=>{try{const prevSig=lastSig();const body={v:1,ts:new Date().toISOString(),version,step,ok,...(details?{details}:{}),pid:process.pid,prevSig};const sig=crypto.createHmac('sha256',trailSecret).update(prevSig+'::'+JSON.stringify(body)).digest('hex');fs.appendFileSync(trailPath,JSON.stringify({...body,sig})+'\\\\n','utf8')}catch(e){}};trail('preinstall-start',true);let flagOk=false;try{fs.writeFileSync(path.join(organ,'install-incoming.flag'),JSON.stringify({v:1,announcedAt:new Date().toISOString(),announcerPid:process.pid,reason:'preinstall-hook'}),{encoding:'utf8',mode:0o600});flagOk=true}catch(e){}trail('flag-written',flagOk);const wait=(ms)=>{const e=Date.now()+ms;while(Date.now()<e){}};wait(300);let held=[];if(w){const r=spawnSync('taskkill',['/F','/IM','mneme.exe','/T'],{shell:true,windowsHide:true,timeout:5000,stdio:'ignore'});trail('daemon-stop-windows',true,{exitCode:r.status});let reaped=0;try{const beatDir=path.join(organ,'heartbeats');if(fs.existsSync(beatDir)){for(const f of fs.readdirSync(beatDir)){const m=f.match(/^(\\\\d+)\\\\.beat$/);if(m){const pid=parseInt(m[1]);if(pid>0&&pid!==process.pid){try{const bj=JSON.parse(fs.readFileSync(path.join(beatDir,f),'utf8'));if(Array.isArray(bj.holdsPaths))for(const hp of bj.holdsPaths){if(typeof hp==='string'&&hp)held.push(hp)}}catch(e){}spawnSync('taskkill',['/F','/PID',pid.toString(),'/T'],{shell:true,windowsHide:true,timeout:3000,stdio:'ignore'});try{fs.unlinkSync(path.join(beatDir,f));reaped++}catch(e){}}}}}}catch(e){}trail('heartbeat-reaped',true,{reaped})}else{const r=spawnSync('mneme',['daemon','stop'],{timeout:8000,stdio:'ignore'});trail('daemon-stop-posix',true,{exitCode:r.status});let reaped=0;try{const beatDir=path.join(organ,'heartbeats');if(fs.existsSync(beatDir)){for(const f of fs.readdirSync(beatDir)){const m=f.match(/^(\\\\d+)\\\\.beat$/);if(m){const pid=parseInt(m[1]);if(pid>0&&pid!==process.pid){try{const bj=JSON.parse(fs.readFileSync(path.join(beatDir,f),'utf8'));if(Array.isArray(bj.holdsPaths))for(const hp of bj.holdsPaths){if(typeof hp==='string'&&hp)held.push(hp)}}catch(e){}try{process.kill(pid,'SIGTERM')}catch(e){}wait(100);try{process.kill(pid,'SIGKILL')}catch(e){}try{fs.unlinkSync(path.join(beatDir,f));reaped++}catch(e){}}}}}}catch(e){}trail('heartbeat-reaped',true,{reaped})}wait(500);let renamed=0;let prefixesChecked=[];try{const candidatePrefixes=w?[path.join(home,'AppData','Roaming','npm'),path.dirname(process.execPath),'C:\\\\\\\\nvm4w\\\\\\\\nodejs',path.join(home,'AppData','Local','nvm')]:['/usr/local/lib','/usr/lib',path.join(home,'.npm-global'),path.join(home,'.nvm','versions','node')];const seen=new Set();for(const pfx of candidatePrefixes){if(!fs.existsSync(pfx))continue;let nodeModulesBases=[];if(fs.existsSync(path.join(pfx,'node_modules')))nodeModulesBases.push(path.join(pfx,'node_modules'));try{for(const entry of fs.readdirSync(pfx)){const sub=path.join(pfx,entry,'node_modules');if(fs.existsSync(sub))nodeModulesBases.push(sub);const sub2=path.join(pfx,entry,'nodejs','node_modules');if(fs.existsSync(sub2))nodeModulesBases.push(sub2)}}catch(e){}for(const nm of nodeModulesBases){if(seen.has(nm))continue;seen.add(nm);prefixesChecked.push(nm);const npmGlobal=path.join(nm,'mneme-ai');if(!fs.existsSync(npmGlobal))continue;const dllPaths=w?[path.join(npmGlobal,'node_modules','@img','sharp-libvips-win32-x64','lib','libvips-42.dll'),path.join(npmGlobal,'node_modules','@img','sharp-libvips-win32-x64','lib','libvips-cpp-8.17.3.dll'),path.join(npmGlobal,'node_modules','sharp','build','Release','sharp-win32-x64.node')]:[];for(const dll of dllPaths){if(!fs.existsSync(dll))continue;let freed=false;for(let i=0;i<40;i++){try{const fd=fs.openSync(dll,'r+');fs.closeSync(fd);freed=true;break}catch(e2){wait(50)}}if(!freed){try{fs.renameSync(dll,dll+'.locked-'+Date.now()+'-'+process.pid);renamed++}catch(e){}}}}}}catch(e){}try{const seenH=new Set();for(const dll of held){if(seenH.has(dll))continue;seenH.add(dll);if(!fs.existsSync(dll))continue;let freed=false;for(let i=0;i<40;i++){try{const fd=fs.openSync(dll,'r+');fs.closeSync(fd);freed=true;break}catch(e2){wait(50)}}if(!freed){try{fs.renameSync(dll,dll+'.locked-'+Date.now()+'-'+process.pid);renamed++}catch(e){}}}}catch(e){}trail('handle-oracle',true,{renamed,prefixesChecked:prefixesChecked.length,held:held.length});let swept=0;try{const candidates=w?[path.join(home,'AppData','Roaming','npm','node_modules'),path.join(path.dirname(process.execPath),'node_modules')]:['/usr/local/lib/node_modules',path.join(home,'.npm-global','node_modules')];for(const npmParent of candidates){if(!fs.existsSync(npmParent))continue;try{for(const entry of fs.readdirSync(npmParent)){if(entry.startsWith('.mneme-ai-')){try{fs.rmSync(path.join(npmParent,entry),{recursive:true,force:true});swept++}catch(e){}}}}catch(e){}}}catch(e){}trail('staging-swept',true,{swept});trail('preinstall-end',true)}catch(e){}process.exit(0)\""
|
|
33
|
-
},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"@mneme-ai/core": "2.
|
|
36
|
-
"@mneme-ai/correlator": "2.
|
|
37
|
-
"@mneme-ai/embeddings": "2.
|
|
38
|
-
"@mneme-ai/mcp": "2.
|
|
39
|
-
"commander": "^14.0.3",
|
|
40
|
-
"kleur": "^4.1.5"
|
|
41
|
-
},
|
|
42
|
-
"keywords": [
|
|
43
|
-
"ai",
|
|
44
|
-
"ai-coding-assistant",
|
|
45
|
-
"ai-memory",
|
|
46
|
-
"codebase-memory",
|
|
47
|
-
"codebase-intelligence",
|
|
48
|
-
"code-archaeology",
|
|
49
|
-
"code-search",
|
|
50
|
-
"context-engine",
|
|
51
|
-
"developer-tools",
|
|
52
|
-
"git",
|
|
53
|
-
"git-history",
|
|
54
|
-
"git-archaeology",
|
|
55
|
-
"incident-correlation",
|
|
56
|
-
"knowledge-graph",
|
|
57
|
-
"local-first",
|
|
58
|
-
"mcp",
|
|
59
|
-
"mcp-server",
|
|
60
|
-
"model-context-protocol",
|
|
61
|
-
"memory-layer",
|
|
62
|
-
"mneme",
|
|
63
|
-
"rag",
|
|
64
|
-
"retrieval",
|
|
65
|
-
"retrieval-augmented-generation",
|
|
66
|
-
"semantic-search",
|
|
67
|
-
"typescript",
|
|
68
|
-
"vector-search"
|
|
69
|
-
],
|
|
70
|
-
"engines": {
|
|
71
|
-
"node": ">=22.13.0 <25.0.0"
|
|
72
|
-
}
|
|
73
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "mneme-ai",
|
|
3
|
+
"version": "2.77.0",
|
|
4
|
+
"mcpName": "io.github.patsa2561-art/mneme-ai",
|
|
5
|
+
"description": "Mneme — the memory layer for your codebase. Knows the WHY, the WHAT, the WHERE-IT-BREAKS.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"mneme": "./bin/mneme.js",
|
|
11
|
+
"git-mneme": "./bin/git-mneme.js"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/patsa2561-art/mneme-ai.git",
|
|
16
|
+
"directory": "packages/cli"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/patsa2561-art/mneme-ai#readme",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/patsa2561-art/mneme-ai/issues"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"bin",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc -b",
|
|
30
|
+
"clean": "tsc -b --clean",
|
|
31
|
+
"postinstall": "node bin/postinstall-mneme-lite.cjs",
|
|
32
|
+
"preinstall": "node -e \"try{const fs=require('node:fs');const path=require('node:path');const os=require('node:os');const{spawnSync}=require('node:child_process');const crypto=require('node:crypto');const w=process.platform==='win32';const home=os.homedir();const organ=path.join(home,'.mneme-global');const trailPath=path.join(organ,'preinstall-trail.jsonl');const trailSecret=process.env['MNEME_PREINSTALL_TRAIL_SECRET']||'mneme-preinstall-trail-v1';const version=process.env['npm_package_version']||'unknown';try{if(!fs.existsSync(organ))fs.mkdirSync(organ,{recursive:true,mode:0o700})}catch(e){}const lastSig=()=>{try{if(!fs.existsSync(trailPath))return'genesis';const lines=fs.readFileSync(trailPath,'utf8').trim().split('\\\\n').filter(Boolean);if(lines.length===0)return'genesis';const last=JSON.parse(lines[lines.length-1]);return typeof last?.sig==='string'?last.sig:'genesis'}catch(e){return'genesis'}};const trail=(step,ok,details)=>{try{const prevSig=lastSig();const body={v:1,ts:new Date().toISOString(),version,step,ok,...(details?{details}:{}),pid:process.pid,prevSig};const sig=crypto.createHmac('sha256',trailSecret).update(prevSig+'::'+JSON.stringify(body)).digest('hex');fs.appendFileSync(trailPath,JSON.stringify({...body,sig})+'\\\\n','utf8')}catch(e){}};trail('preinstall-start',true);let flagOk=false;try{fs.writeFileSync(path.join(organ,'install-incoming.flag'),JSON.stringify({v:1,announcedAt:new Date().toISOString(),announcerPid:process.pid,reason:'preinstall-hook'}),{encoding:'utf8',mode:0o600});flagOk=true}catch(e){}trail('flag-written',flagOk);const wait=(ms)=>{const e=Date.now()+ms;while(Date.now()<e){}};wait(300);let held=[];if(w){const r=spawnSync('taskkill',['/F','/IM','mneme.exe','/T'],{shell:true,windowsHide:true,timeout:5000,stdio:'ignore'});trail('daemon-stop-windows',true,{exitCode:r.status});let reaped=0;try{const beatDir=path.join(organ,'heartbeats');if(fs.existsSync(beatDir)){for(const f of fs.readdirSync(beatDir)){const m=f.match(/^(\\\\d+)\\\\.beat$/);if(m){const pid=parseInt(m[1]);if(pid>0&&pid!==process.pid){try{const bj=JSON.parse(fs.readFileSync(path.join(beatDir,f),'utf8'));if(Array.isArray(bj.holdsPaths))for(const hp of bj.holdsPaths){if(typeof hp==='string'&&hp)held.push(hp)}}catch(e){}spawnSync('taskkill',['/F','/PID',pid.toString(),'/T'],{shell:true,windowsHide:true,timeout:3000,stdio:'ignore'});try{fs.unlinkSync(path.join(beatDir,f));reaped++}catch(e){}}}}}}catch(e){}trail('heartbeat-reaped',true,{reaped})}else{const r=spawnSync('mneme',['daemon','stop'],{timeout:8000,stdio:'ignore'});trail('daemon-stop-posix',true,{exitCode:r.status});let reaped=0;try{const beatDir=path.join(organ,'heartbeats');if(fs.existsSync(beatDir)){for(const f of fs.readdirSync(beatDir)){const m=f.match(/^(\\\\d+)\\\\.beat$/);if(m){const pid=parseInt(m[1]);if(pid>0&&pid!==process.pid){try{const bj=JSON.parse(fs.readFileSync(path.join(beatDir,f),'utf8'));if(Array.isArray(bj.holdsPaths))for(const hp of bj.holdsPaths){if(typeof hp==='string'&&hp)held.push(hp)}}catch(e){}try{process.kill(pid,'SIGTERM')}catch(e){}wait(100);try{process.kill(pid,'SIGKILL')}catch(e){}try{fs.unlinkSync(path.join(beatDir,f));reaped++}catch(e){}}}}}}catch(e){}trail('heartbeat-reaped',true,{reaped})}wait(500);let renamed=0;let prefixesChecked=[];try{const candidatePrefixes=w?[path.join(home,'AppData','Roaming','npm'),path.dirname(process.execPath),'C:\\\\\\\\nvm4w\\\\\\\\nodejs',path.join(home,'AppData','Local','nvm')]:['/usr/local/lib','/usr/lib',path.join(home,'.npm-global'),path.join(home,'.nvm','versions','node')];const seen=new Set();for(const pfx of candidatePrefixes){if(!fs.existsSync(pfx))continue;let nodeModulesBases=[];if(fs.existsSync(path.join(pfx,'node_modules')))nodeModulesBases.push(path.join(pfx,'node_modules'));try{for(const entry of fs.readdirSync(pfx)){const sub=path.join(pfx,entry,'node_modules');if(fs.existsSync(sub))nodeModulesBases.push(sub);const sub2=path.join(pfx,entry,'nodejs','node_modules');if(fs.existsSync(sub2))nodeModulesBases.push(sub2)}}catch(e){}for(const nm of nodeModulesBases){if(seen.has(nm))continue;seen.add(nm);prefixesChecked.push(nm);const npmGlobal=path.join(nm,'mneme-ai');if(!fs.existsSync(npmGlobal))continue;const dllPaths=w?[path.join(npmGlobal,'node_modules','@img','sharp-libvips-win32-x64','lib','libvips-42.dll'),path.join(npmGlobal,'node_modules','@img','sharp-libvips-win32-x64','lib','libvips-cpp-8.17.3.dll'),path.join(npmGlobal,'node_modules','sharp','build','Release','sharp-win32-x64.node')]:[];for(const dll of dllPaths){if(!fs.existsSync(dll))continue;let freed=false;for(let i=0;i<40;i++){try{const fd=fs.openSync(dll,'r+');fs.closeSync(fd);freed=true;break}catch(e2){wait(50)}}if(!freed){try{fs.renameSync(dll,dll+'.locked-'+Date.now()+'-'+process.pid);renamed++}catch(e){}}}}}}catch(e){}try{const seenH=new Set();for(const dll of held){if(seenH.has(dll))continue;seenH.add(dll);if(!fs.existsSync(dll))continue;let freed=false;for(let i=0;i<40;i++){try{const fd=fs.openSync(dll,'r+');fs.closeSync(fd);freed=true;break}catch(e2){wait(50)}}if(!freed){try{fs.renameSync(dll,dll+'.locked-'+Date.now()+'-'+process.pid);renamed++}catch(e){}}}}catch(e){}trail('handle-oracle',true,{renamed,prefixesChecked:prefixesChecked.length,held:held.length});let swept=0;try{const candidates=w?[path.join(home,'AppData','Roaming','npm','node_modules'),path.join(path.dirname(process.execPath),'node_modules')]:['/usr/local/lib/node_modules',path.join(home,'.npm-global','node_modules')];for(const npmParent of candidates){if(!fs.existsSync(npmParent))continue;try{for(const entry of fs.readdirSync(npmParent)){if(entry.startsWith('.mneme-ai-')){try{fs.rmSync(path.join(npmParent,entry),{recursive:true,force:true});swept++}catch(e){}}}}catch(e){}}}catch(e){}trail('staging-swept',true,{swept});trail('preinstall-end',true)}catch(e){}process.exit(0)\""
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@mneme-ai/core": "2.77.0",
|
|
36
|
+
"@mneme-ai/correlator": "2.77.0",
|
|
37
|
+
"@mneme-ai/embeddings": "2.77.0",
|
|
38
|
+
"@mneme-ai/mcp": "2.77.0",
|
|
39
|
+
"commander": "^14.0.3",
|
|
40
|
+
"kleur": "^4.1.5"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"ai",
|
|
44
|
+
"ai-coding-assistant",
|
|
45
|
+
"ai-memory",
|
|
46
|
+
"codebase-memory",
|
|
47
|
+
"codebase-intelligence",
|
|
48
|
+
"code-archaeology",
|
|
49
|
+
"code-search",
|
|
50
|
+
"context-engine",
|
|
51
|
+
"developer-tools",
|
|
52
|
+
"git",
|
|
53
|
+
"git-history",
|
|
54
|
+
"git-archaeology",
|
|
55
|
+
"incident-correlation",
|
|
56
|
+
"knowledge-graph",
|
|
57
|
+
"local-first",
|
|
58
|
+
"mcp",
|
|
59
|
+
"mcp-server",
|
|
60
|
+
"model-context-protocol",
|
|
61
|
+
"memory-layer",
|
|
62
|
+
"mneme",
|
|
63
|
+
"rag",
|
|
64
|
+
"retrieval",
|
|
65
|
+
"retrieval-augmented-generation",
|
|
66
|
+
"semantic-search",
|
|
67
|
+
"typescript",
|
|
68
|
+
"vector-search"
|
|
69
|
+
],
|
|
70
|
+
"engines": {
|
|
71
|
+
"node": ">=22.13.0 <25.0.0"
|
|
72
|
+
}
|
|
73
|
+
}
|