memhook 0.2.2 → 0.4.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/CHANGELOG.md +30 -72
- package/README.md +158 -69
- package/dist/bin/memhook.d.ts +11 -6
- package/dist/bin/memhook.d.ts.map +1 -1
- package/dist/bin/memhook.js +208 -21
- package/dist/bin/memhook.js.map +1 -1
- package/dist/src/ansi.d.ts +71 -0
- package/dist/src/ansi.d.ts.map +1 -0
- package/dist/src/ansi.js +100 -0
- package/dist/src/ansi.js.map +1 -0
- package/dist/src/backup.d.ts +10 -0
- package/dist/src/backup.d.ts.map +1 -0
- package/dist/src/backup.js +17 -0
- package/dist/src/backup.js.map +1 -0
- package/dist/src/cache.d.ts.map +1 -1
- package/dist/src/cache.js +14 -7
- package/dist/src/cache.js.map +1 -1
- package/dist/src/config.d.ts +11 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +6 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/configFile.d.ts +6 -0
- package/dist/src/configFile.d.ts.map +1 -1
- package/dist/src/configFile.js.map +1 -1
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/init.d.ts +48 -0
- package/dist/src/init.d.ts.map +1 -0
- package/dist/src/init.js +327 -0
- package/dist/src/init.js.map +1 -0
- package/dist/src/install.d.ts +87 -0
- package/dist/src/install.d.ts.map +1 -0
- package/dist/src/install.js +124 -0
- package/dist/src/install.js.map +1 -0
- package/dist/src/router.d.ts +22 -0
- package/dist/src/router.d.ts.map +1 -1
- package/dist/src/router.js +113 -8
- package/dist/src/router.js.map +1 -1
- package/dist/src/skills.d.ts +68 -0
- package/dist/src/skills.d.ts.map +1 -0
- package/dist/src/skills.js +73 -0
- package/dist/src/skills.js.map +1 -0
- package/dist/src/skillsCmd.d.ts +51 -0
- package/dist/src/skillsCmd.d.ts.map +1 -0
- package/dist/src/skillsCmd.js +273 -0
- package/dist/src/skillsCmd.js.map +1 -0
- package/dist/src/tail.d.ts +76 -0
- package/dist/src/tail.d.ts.map +1 -0
- package/dist/src/tail.js +280 -0
- package/dist/src/tail.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/package.json +9 -2
- package/skills/curate/SKILL.md +181 -0
- package/skills/curate/reference.md +105 -0
- package/skills/relay/SKILL.md +162 -0
- package/skills/wrap/SKILL.md +173 -0
package/dist/bin/memhook.js
CHANGED
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* memhook CLI
|
|
3
|
+
* memhook CLI.
|
|
4
4
|
*
|
|
5
5
|
* memhook run Read stdin (Claude Code hook JSON), write hook output
|
|
6
6
|
* memhook build-catalog Rebuild ~/.claude/cache/memory-catalog.txt
|
|
7
|
+
* memhook init Wire memhook into ~/.claude/settings.json (interactive)
|
|
8
|
+
* memhook uninstall Remove memhook's hooks from ~/.claude/settings.json
|
|
9
|
+
* memhook tail Pretty live view of the JSONL routing log
|
|
7
10
|
* memhook version Print package version
|
|
8
11
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* Only `run` obeys the fail-soft hook contract (never throws, never exits
|
|
13
|
+
* non-zero). The interactive commands (`init`/`uninstall`/`tail`) may exit
|
|
14
|
+
* non-zero on user error and are free to use the TTY — docs/SPECIFICATION.md §9.
|
|
15
|
+
*
|
|
16
|
+
* Wired into ~/.claude/settings.json hooks (see `memhook init`):
|
|
17
|
+
* "UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "memhook run" }] }]
|
|
18
|
+
* "SessionStart": [{ "hooks": [{ "type": "command", "command": "memhook build-catalog" }] }]
|
|
14
19
|
*/
|
|
15
20
|
import { route } from "../src/router.js";
|
|
16
21
|
import { buildCatalog } from "../src/catalog.js";
|
|
17
22
|
import { loadConfig } from "../src/config.js";
|
|
23
|
+
import { runInit, runUninstall } from "../src/init.js";
|
|
24
|
+
import { runTail } from "../src/tail.js";
|
|
25
|
+
import { runSkills } from "../src/skillsCmd.js";
|
|
26
|
+
import { isCompanionSkill } from "../src/skills.js";
|
|
18
27
|
import { MEMHOOK_VERSION as VERSION } from "../src/version.js";
|
|
28
|
+
const PROVIDERS = ["anthropic", "openai", "ollama"];
|
|
29
|
+
const SKILLS_SUBCOMMANDS = ["install", "uninstall", "list"];
|
|
19
30
|
async function main() {
|
|
20
31
|
const cmd = process.argv[2] ?? "help";
|
|
32
|
+
const args = process.argv.slice(3);
|
|
21
33
|
switch (cmd) {
|
|
22
34
|
case "run":
|
|
23
35
|
await cmdRun();
|
|
@@ -25,6 +37,18 @@ async function main() {
|
|
|
25
37
|
case "build-catalog":
|
|
26
38
|
cmdBuildCatalog();
|
|
27
39
|
break;
|
|
40
|
+
case "init":
|
|
41
|
+
process.exitCode = await cmdInit(args);
|
|
42
|
+
break;
|
|
43
|
+
case "uninstall":
|
|
44
|
+
process.exitCode = await cmdUninstall(args);
|
|
45
|
+
break;
|
|
46
|
+
case "tail":
|
|
47
|
+
process.exitCode = await cmdTail(args);
|
|
48
|
+
break;
|
|
49
|
+
case "skills":
|
|
50
|
+
process.exitCode = await cmdSkills(args);
|
|
51
|
+
break;
|
|
28
52
|
case "version":
|
|
29
53
|
case "--version":
|
|
30
54
|
case "-v":
|
|
@@ -42,19 +66,20 @@ async function main() {
|
|
|
42
66
|
}
|
|
43
67
|
}
|
|
44
68
|
async function cmdRun() {
|
|
45
|
-
|
|
46
|
-
|
|
69
|
+
// Fail-soft: read stdin AND route inside one try, so ANY error — a stdin
|
|
70
|
+
// read error (stdin 'error' event) just as much as a routing error — falls
|
|
71
|
+
// back to empty additionalContext and exit 0, never a non-zero exit that
|
|
72
|
+
// would block the user prompt.
|
|
73
|
+
let output = {
|
|
74
|
+
hookSpecificOutput: {
|
|
75
|
+
hookEventName: "UserPromptSubmit",
|
|
76
|
+
additionalContext: "",
|
|
77
|
+
},
|
|
78
|
+
};
|
|
47
79
|
try {
|
|
48
|
-
output = await route(
|
|
80
|
+
output = await route(await readStdin());
|
|
49
81
|
}
|
|
50
82
|
catch (err) {
|
|
51
|
-
// Fail-soft: emit empty additionalContext, never block the user prompt
|
|
52
|
-
output = {
|
|
53
|
-
hookSpecificOutput: {
|
|
54
|
-
hookEventName: "UserPromptSubmit",
|
|
55
|
-
additionalContext: "",
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
83
|
if (process.env["MEMHOOK_DEBUG"] === "true") {
|
|
59
84
|
process.stderr.write(`memhook run error: ${String(err)}\n`);
|
|
60
85
|
}
|
|
@@ -69,6 +94,130 @@ function cmdBuildCatalog() {
|
|
|
69
94
|
});
|
|
70
95
|
process.stderr.write(`[memhook build-catalog] ${config.catalog.path} — ${result.lines}L, ${result.bytes}B\n`);
|
|
71
96
|
}
|
|
97
|
+
async function cmdInit(args) {
|
|
98
|
+
const { flags } = parseArgs(args, BOOL_INIT);
|
|
99
|
+
let provider;
|
|
100
|
+
if (typeof flags["provider"] === "string") {
|
|
101
|
+
if (!PROVIDERS.includes(flags["provider"])) {
|
|
102
|
+
process.stderr.write(`memhook init: unknown provider "${flags["provider"]}"\n`);
|
|
103
|
+
return 1;
|
|
104
|
+
}
|
|
105
|
+
provider = flags["provider"];
|
|
106
|
+
}
|
|
107
|
+
let skills;
|
|
108
|
+
if (flags["no-skills"] === true)
|
|
109
|
+
skills = false;
|
|
110
|
+
else if (flags["skills"] === true)
|
|
111
|
+
skills = true;
|
|
112
|
+
return runInit({
|
|
113
|
+
yes: flags["yes"] === true,
|
|
114
|
+
dryRun: flags["dry-run"] === true,
|
|
115
|
+
provider,
|
|
116
|
+
apiKeyEnv: strFlag(flags["api-key-env"]),
|
|
117
|
+
model: strFlag(flags["model"]),
|
|
118
|
+
bin: strFlag(flags["bin"]) ?? "memhook",
|
|
119
|
+
settingsPath: strFlag(flags["settings"]),
|
|
120
|
+
noCatalog: flags["no-catalog"] === true,
|
|
121
|
+
skills,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
async function cmdSkills(args) {
|
|
125
|
+
const { flags, positionals } = parseArgs(args, BOOL_SKILLS);
|
|
126
|
+
const sub = positionals[0] ?? "list";
|
|
127
|
+
if (!SKILLS_SUBCOMMANDS.includes(sub)) {
|
|
128
|
+
process.stderr.write(`memhook skills: unknown subcommand "${sub}" (install | uninstall | list)\n`);
|
|
129
|
+
return 1;
|
|
130
|
+
}
|
|
131
|
+
const names = [];
|
|
132
|
+
for (const n of positionals.slice(1)) {
|
|
133
|
+
if (!isCompanionSkill(n)) {
|
|
134
|
+
process.stderr.write(`memhook skills: unknown skill "${n}" (wrap | curate | relay)\n`);
|
|
135
|
+
return 1;
|
|
136
|
+
}
|
|
137
|
+
names.push(n);
|
|
138
|
+
}
|
|
139
|
+
return runSkills({
|
|
140
|
+
subcommand: sub,
|
|
141
|
+
names: names.length > 0 ? names : undefined,
|
|
142
|
+
yes: flags["yes"] === true,
|
|
143
|
+
dryRun: flags["dry-run"] === true,
|
|
144
|
+
force: flags["force"] === true,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
async function cmdUninstall(args) {
|
|
148
|
+
const { flags } = parseArgs(args, BOOL_UNINSTALL);
|
|
149
|
+
return runUninstall({
|
|
150
|
+
yes: flags["yes"] === true,
|
|
151
|
+
dryRun: flags["dry-run"] === true,
|
|
152
|
+
settingsPath: strFlag(flags["settings"]),
|
|
153
|
+
purge: flags["purge"] === true,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
async function cmdTail(args) {
|
|
157
|
+
const { flags } = parseArgs(args, BOOL_TAIL);
|
|
158
|
+
const linesRaw = strFlag(flags["lines"]);
|
|
159
|
+
const lines = linesRaw !== undefined && /^\d+$/.test(linesRaw) ? Number(linesRaw) : 10;
|
|
160
|
+
const statusRaw = strFlag(flags["status"]);
|
|
161
|
+
const status = statusRaw
|
|
162
|
+
? statusRaw
|
|
163
|
+
.split(",")
|
|
164
|
+
.map((s) => s.trim())
|
|
165
|
+
.filter(Boolean)
|
|
166
|
+
: undefined;
|
|
167
|
+
return runTail({
|
|
168
|
+
file: strFlag(flags["file"]),
|
|
169
|
+
lines,
|
|
170
|
+
noFollow: flags["no-follow"] === true,
|
|
171
|
+
status,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
// ── tiny flag parser ─────────────────────────────────────────────────────────
|
|
175
|
+
const BOOL_INIT = new Set(["yes", "dry-run", "no-catalog", "skills", "no-skills"]);
|
|
176
|
+
const BOOL_UNINSTALL = new Set(["yes", "dry-run", "purge"]);
|
|
177
|
+
const BOOL_TAIL = new Set(["no-follow"]);
|
|
178
|
+
const BOOL_SKILLS = new Set(["yes", "dry-run", "force"]);
|
|
179
|
+
const SHORT = { "-y": "--yes", "-n": "--lines" };
|
|
180
|
+
function strFlag(v) {
|
|
181
|
+
return typeof v === "string" ? v : undefined;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Parse `--key value`, `--key=value`, and boolean flags (those listed in
|
|
185
|
+
* `bools`, plus any `--key` not followed by a value). Unknown long flags that
|
|
186
|
+
* take a value consume the next non-dash token.
|
|
187
|
+
*/
|
|
188
|
+
function parseArgs(args, bools) {
|
|
189
|
+
const flags = {};
|
|
190
|
+
const positionals = [];
|
|
191
|
+
for (let i = 0; i < args.length; i++) {
|
|
192
|
+
const raw = args[i];
|
|
193
|
+
if (raw === undefined)
|
|
194
|
+
continue;
|
|
195
|
+
const a = SHORT[raw] ?? raw;
|
|
196
|
+
if (!a.startsWith("--")) {
|
|
197
|
+
positionals.push(a);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const key = a.slice(2);
|
|
201
|
+
const eq = key.indexOf("=");
|
|
202
|
+
if (eq >= 0) {
|
|
203
|
+
flags[key.slice(0, eq)] = key.slice(eq + 1);
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (bools.has(key)) {
|
|
207
|
+
flags[key] = true;
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const next = args[i + 1];
|
|
211
|
+
if (next !== undefined && !next.startsWith("-")) {
|
|
212
|
+
flags[key] = next;
|
|
213
|
+
i++;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
flags[key] = true;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return { flags, positionals };
|
|
220
|
+
}
|
|
72
221
|
function readStdin() {
|
|
73
222
|
return new Promise((resolve, reject) => {
|
|
74
223
|
let data = "";
|
|
@@ -82,30 +231,68 @@ function printHelp() {
|
|
|
82
231
|
console.log(`memhook ${VERSION}
|
|
83
232
|
|
|
84
233
|
USAGE
|
|
85
|
-
memhook <command>
|
|
234
|
+
memhook <command> [options]
|
|
86
235
|
|
|
87
236
|
COMMANDS
|
|
88
237
|
run Read Claude Code hook JSON from stdin, emit additionalContext
|
|
89
238
|
build-catalog Rebuild the memory catalog at $MEMHOOK_CATALOG_PATH
|
|
239
|
+
init Wire memhook into ~/.claude/settings.json (with backup)
|
|
240
|
+
uninstall Remove memhook's hooks from ~/.claude/settings.json
|
|
241
|
+
tail Pretty live view of the routing log (status, latency, memories)
|
|
242
|
+
skills Install/uninstall/list companion skills (/wrap /curate /relay)
|
|
90
243
|
version Print version
|
|
91
244
|
help Show this message
|
|
92
245
|
|
|
246
|
+
init OPTIONS
|
|
247
|
+
--provider <p> anthropic | openai | ollama (else prompted; default anthropic)
|
|
248
|
+
--api-key-env <n> env var holding the API key (default per provider)
|
|
249
|
+
--model <m> override the model id
|
|
250
|
+
--bin <name> command written into settings.json (default: memhook)
|
|
251
|
+
--settings <path> settings file to patch (default: ~/.claude/settings.json)
|
|
252
|
+
--no-catalog skip the initial catalog build
|
|
253
|
+
--skills install companion skills (default: ask / yes in --yes mode)
|
|
254
|
+
--no-skills skip installing companion skills
|
|
255
|
+
--dry-run print the plan, write nothing
|
|
256
|
+
-y, --yes non-interactive (accept defaults / flags)
|
|
257
|
+
|
|
258
|
+
uninstall OPTIONS
|
|
259
|
+
--settings <path> settings file to patch (default: ~/.claude/settings.json)
|
|
260
|
+
--dry-run print the plan, write nothing
|
|
261
|
+
-y, --yes non-interactive
|
|
262
|
+
--purge also report cache + log locations to clean up
|
|
263
|
+
|
|
264
|
+
tail OPTIONS
|
|
265
|
+
-n, --lines <N> history lines to show before following (default: 10)
|
|
266
|
+
--no-follow print the recent log + summary, then exit (no live follow)
|
|
267
|
+
--status <a,b> only show these statuses (e.g. ok,cache_hit)
|
|
268
|
+
--file <path> log file to read (default: $MEMHOOK_LOG_PATH)
|
|
269
|
+
|
|
270
|
+
skills SUBCOMMANDS
|
|
271
|
+
install [names…] copy /wrap /curate /relay into ~/.claude/skills (default: all)
|
|
272
|
+
uninstall [names…] remove the bundled companion skills (backs up first)
|
|
273
|
+
list show each skill's install status
|
|
274
|
+
--force overwrite a skill that differs from shipped (backs up first)
|
|
275
|
+
--dry-run print the plan, write nothing
|
|
276
|
+
-y, --yes non-interactive (accept defaults)
|
|
277
|
+
|
|
93
278
|
ENV VARS
|
|
94
279
|
MEMHOOK_ENABLED toggle (default: true)
|
|
95
280
|
MEMHOOK_PROVIDER anthropic | openai | ollama (default: anthropic)
|
|
96
281
|
MEMHOOK_MODEL model id (per-provider default if unset)
|
|
97
282
|
MEMHOOK_API_KEY_ENV env var name holding the API key
|
|
98
|
-
(anthropic: ANTHROPIC_API_KEY, openai: OPENAI_API_KEY,
|
|
99
|
-
ollama: none required)
|
|
100
283
|
MEMHOOK_BASE_URL override the provider API endpoint
|
|
101
284
|
MEMHOOK_CONFIG path to a YAML config file
|
|
102
|
-
|
|
285
|
+
MEMHOOK_LOG_PATH JSONL log path (read by 'memhook tail')
|
|
103
286
|
MEMHOOK_MAX_FILES file-count cap (default: 5)
|
|
104
287
|
MEMHOOK_MAX_ADDITIONAL_CHARS injection size cap (default: 9500)
|
|
105
|
-
MEMHOOK_MAX_OUTPUT_TOKENS model output cap (default: 200)
|
|
106
288
|
MEMHOOK_TIMEOUT_MS request timeout (default: 8000; ollama: 30000)
|
|
107
289
|
MEMHOOK_DISABLE_CACHE=true skip local LRU cache
|
|
108
290
|
MEMHOOK_DISABLE_PREFILTER=true skip trivial-prompt skip
|
|
291
|
+
MEMHOOK_CURATE_NUDGE /curate-nudge toggle (default: true)
|
|
292
|
+
MEMHOOK_CURATE_NUDGE_TOKENS catalog-token threshold to nudge (default: 15000)
|
|
293
|
+
MEMHOOK_CURATE_NUDGE_FILES memory-file-count threshold to nudge (default: 250)
|
|
294
|
+
MEMHOOK_CURATE_NUDGE_COOLDOWN_DAYS min days between nudges (default: 7)
|
|
295
|
+
NO_COLOR / MEMHOOK_NO_COLOR disable colour in init/tail output
|
|
109
296
|
MEMHOOK_DEBUG=true print errors to stderr (default: silent fail-soft)
|
|
110
297
|
|
|
111
298
|
PROVIDERS
|
package/dist/bin/memhook.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memhook.js","sourceRoot":"","sources":["../../bin/memhook.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"memhook.js","sourceRoot":"","sources":["../../bin/memhook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-dependency ANSI styling for the interactive CLI commands
|
|
3
|
+
* (`memhook init`, `memhook tail`).
|
|
4
|
+
*
|
|
5
|
+
* This module is NOT used by the hook entrypoint (`memhook run`) — the hook's
|
|
6
|
+
* stdout is reserved for the JSON envelope and must stay byte-clean. Colour is
|
|
7
|
+
* only ever emitted to a human-facing TTY.
|
|
8
|
+
*
|
|
9
|
+
* Colour is disabled (every styler becomes the identity function) when:
|
|
10
|
+
* - `NO_COLOR` is set (any value) — https://no-color.org/
|
|
11
|
+
* - `MEMHOOK_NO_COLOR` is set (memhook-specific opt-out)
|
|
12
|
+
* - `TERM=dumb`
|
|
13
|
+
* - the target stream is not a TTY (piped to a file / another process)
|
|
14
|
+
* `FORCE_COLOR` (any value) overrides all of the above and forces colour on,
|
|
15
|
+
* which is what the test-suite and `| less -R` rely on.
|
|
16
|
+
*/
|
|
17
|
+
export interface AnsiOptions {
|
|
18
|
+
/** Whether the destination is an interactive terminal. */
|
|
19
|
+
isTTY: boolean;
|
|
20
|
+
env: NodeJS.ProcessEnv;
|
|
21
|
+
}
|
|
22
|
+
/** Decide once whether colour should be emitted for a given stream + env. */
|
|
23
|
+
export declare function colorEnabled({ isTTY, env }: AnsiOptions): boolean;
|
|
24
|
+
/** SGR codes used by the CLI. Kept tiny on purpose. */
|
|
25
|
+
declare const CODES: {
|
|
26
|
+
readonly bold: 1;
|
|
27
|
+
readonly dim: 2;
|
|
28
|
+
readonly italic: 3;
|
|
29
|
+
readonly underline: 4;
|
|
30
|
+
readonly red: 31;
|
|
31
|
+
readonly green: 32;
|
|
32
|
+
readonly yellow: 33;
|
|
33
|
+
readonly blue: 34;
|
|
34
|
+
readonly magenta: 35;
|
|
35
|
+
readonly cyan: 36;
|
|
36
|
+
readonly white: 37;
|
|
37
|
+
readonly gray: 90;
|
|
38
|
+
readonly brightGreen: 92;
|
|
39
|
+
readonly brightCyan: 96;
|
|
40
|
+
};
|
|
41
|
+
export type AnsiColor = keyof typeof CODES;
|
|
42
|
+
export interface Ansi {
|
|
43
|
+
readonly enabled: boolean;
|
|
44
|
+
/** Wrap `s` in the SGR code for `name`, or return it untouched if disabled. */
|
|
45
|
+
style(name: AnsiColor, s: string): string;
|
|
46
|
+
bold(s: string): string;
|
|
47
|
+
dim(s: string): string;
|
|
48
|
+
red(s: string): string;
|
|
49
|
+
green(s: string): string;
|
|
50
|
+
yellow(s: string): string;
|
|
51
|
+
cyan(s: string): string;
|
|
52
|
+
gray(s: string): string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build an `Ansi` styler. When colour is disabled every method is the identity
|
|
56
|
+
* function, so call-sites never branch on `enabled` themselves.
|
|
57
|
+
*/
|
|
58
|
+
export declare function makeAnsi(opts: AnsiOptions): Ansi;
|
|
59
|
+
/**
|
|
60
|
+
* Visible width of a string with ANSI escapes stripped — used to pad/align
|
|
61
|
+
* columns correctly even when the cell contains colour codes.
|
|
62
|
+
*/
|
|
63
|
+
export declare function visibleWidth(s: string): number;
|
|
64
|
+
/** Left-pad `s` to `width` visible columns (right-align). */
|
|
65
|
+
export declare function padStart(s: string, width: number): string;
|
|
66
|
+
/** Right-pad `s` to `width` visible columns (left-align). */
|
|
67
|
+
export declare function padEnd(s: string, width: number): string;
|
|
68
|
+
/** Truncate to `max` chars, appending `…` when cut. Callers pass plain text. */
|
|
69
|
+
export declare function truncate(s: string, max: number): string;
|
|
70
|
+
export {};
|
|
71
|
+
//# sourceMappingURL=ansi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansi.d.ts","sourceRoot":"","sources":["../../src/ansi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,MAAM,WAAW,WAAW;IAC1B,0DAA0D;IAC1D,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,WAAW,GAAG,OAAO,CAMjE;AAED,uDAAuD;AACvD,QAAA,MAAM,KAAK;;;;;;;;;;;;;;;CAeD,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,KAAK,CAAC;AAE3C,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,+EAA+E;IAC/E,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE1C,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAehD;AAKD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,6DAA6D;AAC7D,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED,6DAA6D;AAC7D,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIvD"}
|
package/dist/src/ansi.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-dependency ANSI styling for the interactive CLI commands
|
|
3
|
+
* (`memhook init`, `memhook tail`).
|
|
4
|
+
*
|
|
5
|
+
* This module is NOT used by the hook entrypoint (`memhook run`) — the hook's
|
|
6
|
+
* stdout is reserved for the JSON envelope and must stay byte-clean. Colour is
|
|
7
|
+
* only ever emitted to a human-facing TTY.
|
|
8
|
+
*
|
|
9
|
+
* Colour is disabled (every styler becomes the identity function) when:
|
|
10
|
+
* - `NO_COLOR` is set (any value) — https://no-color.org/
|
|
11
|
+
* - `MEMHOOK_NO_COLOR` is set (memhook-specific opt-out)
|
|
12
|
+
* - `TERM=dumb`
|
|
13
|
+
* - the target stream is not a TTY (piped to a file / another process)
|
|
14
|
+
* `FORCE_COLOR` (any value) overrides all of the above and forces colour on,
|
|
15
|
+
* which is what the test-suite and `| less -R` rely on.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The ANSI escape introducer (0x1b). Built from a char code so the source file
|
|
19
|
+
* stays printable ASCII — no raw control byte to be mangled by an editor,
|
|
20
|
+
* `git`, or a copy/paste.
|
|
21
|
+
*/
|
|
22
|
+
const ESC = String.fromCharCode(27);
|
|
23
|
+
const CSI = `${ESC}[`;
|
|
24
|
+
const RESET = `${CSI}0m`;
|
|
25
|
+
/** Decide once whether colour should be emitted for a given stream + env. */
|
|
26
|
+
export function colorEnabled({ isTTY, env }) {
|
|
27
|
+
if (env["FORCE_COLOR"] !== undefined && env["FORCE_COLOR"] !== "")
|
|
28
|
+
return true;
|
|
29
|
+
if (env["NO_COLOR"] !== undefined)
|
|
30
|
+
return false;
|
|
31
|
+
if (env["MEMHOOK_NO_COLOR"] !== undefined)
|
|
32
|
+
return false;
|
|
33
|
+
if (env["TERM"] === "dumb")
|
|
34
|
+
return false;
|
|
35
|
+
return isTTY;
|
|
36
|
+
}
|
|
37
|
+
/** SGR codes used by the CLI. Kept tiny on purpose. */
|
|
38
|
+
const CODES = {
|
|
39
|
+
bold: 1,
|
|
40
|
+
dim: 2,
|
|
41
|
+
italic: 3,
|
|
42
|
+
underline: 4,
|
|
43
|
+
red: 31,
|
|
44
|
+
green: 32,
|
|
45
|
+
yellow: 33,
|
|
46
|
+
blue: 34,
|
|
47
|
+
magenta: 35,
|
|
48
|
+
cyan: 36,
|
|
49
|
+
white: 37,
|
|
50
|
+
gray: 90,
|
|
51
|
+
brightGreen: 92,
|
|
52
|
+
brightCyan: 96,
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Build an `Ansi` styler. When colour is disabled every method is the identity
|
|
56
|
+
* function, so call-sites never branch on `enabled` themselves.
|
|
57
|
+
*/
|
|
58
|
+
export function makeAnsi(opts) {
|
|
59
|
+
const enabled = colorEnabled(opts);
|
|
60
|
+
const wrap = (name, s) => enabled ? `${CSI}${CODES[name]}m${s}${RESET}` : s;
|
|
61
|
+
return {
|
|
62
|
+
enabled,
|
|
63
|
+
style: wrap,
|
|
64
|
+
bold: (s) => wrap("bold", s),
|
|
65
|
+
dim: (s) => wrap("dim", s),
|
|
66
|
+
red: (s) => wrap("red", s),
|
|
67
|
+
green: (s) => wrap("green", s),
|
|
68
|
+
yellow: (s) => wrap("yellow", s),
|
|
69
|
+
cyan: (s) => wrap("cyan", s),
|
|
70
|
+
gray: (s) => wrap("gray", s),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** Matches any SGR escape sequence, e.g. "ESC[32m" or "ESC[0m". */
|
|
74
|
+
const SGR_RE = new RegExp(`${ESC}\\[[0-9;]*m`, "g");
|
|
75
|
+
/**
|
|
76
|
+
* Visible width of a string with ANSI escapes stripped — used to pad/align
|
|
77
|
+
* columns correctly even when the cell contains colour codes.
|
|
78
|
+
*/
|
|
79
|
+
export function visibleWidth(s) {
|
|
80
|
+
return s.replace(SGR_RE, "").length;
|
|
81
|
+
}
|
|
82
|
+
/** Left-pad `s` to `width` visible columns (right-align). */
|
|
83
|
+
export function padStart(s, width) {
|
|
84
|
+
const gap = width - visibleWidth(s);
|
|
85
|
+
return gap > 0 ? " ".repeat(gap) + s : s;
|
|
86
|
+
}
|
|
87
|
+
/** Right-pad `s` to `width` visible columns (left-align). */
|
|
88
|
+
export function padEnd(s, width) {
|
|
89
|
+
const gap = width - visibleWidth(s);
|
|
90
|
+
return gap > 0 ? s + " ".repeat(gap) : s;
|
|
91
|
+
}
|
|
92
|
+
/** Truncate to `max` chars, appending `…` when cut. Callers pass plain text. */
|
|
93
|
+
export function truncate(s, max) {
|
|
94
|
+
if (s.length <= max)
|
|
95
|
+
return s;
|
|
96
|
+
if (max <= 1)
|
|
97
|
+
return s.slice(0, max);
|
|
98
|
+
return s.slice(0, max - 1) + "…";
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=ansi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansi.js","sourceRoot":"","sources":["../../src/ansi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny shared backup helpers for the interactive commands (init / uninstall /
|
|
3
|
+
* skills). Extracted so both `init.ts` and `skillsCmd.ts` can use them without
|
|
4
|
+
* importing each other (which would create a module cycle).
|
|
5
|
+
*/
|
|
6
|
+
/** A backup path next to `path`, stamped so successive runs never collide. */
|
|
7
|
+
export declare function backupPath(path: string, stamp: string): string;
|
|
8
|
+
/** A filesystem-safe ISO-ish timestamp for backup filenames. */
|
|
9
|
+
export declare function stampNow(): string;
|
|
10
|
+
//# sourceMappingURL=backup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../src/backup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,IAAI,MAAM,CAKjC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny shared backup helpers for the interactive commands (init / uninstall /
|
|
3
|
+
* skills). Extracted so both `init.ts` and `skillsCmd.ts` can use them without
|
|
4
|
+
* importing each other (which would create a module cycle).
|
|
5
|
+
*/
|
|
6
|
+
/** A backup path next to `path`, stamped so successive runs never collide. */
|
|
7
|
+
export function backupPath(path, stamp) {
|
|
8
|
+
return `${path}.bak-${stamp}`;
|
|
9
|
+
}
|
|
10
|
+
/** A filesystem-safe ISO-ish timestamp for backup filenames. */
|
|
11
|
+
export function stampNow() {
|
|
12
|
+
return new Date()
|
|
13
|
+
.toISOString()
|
|
14
|
+
.replace(/[:.]/g, "-")
|
|
15
|
+
.replace(/-(\d{3})Z$/, "Z");
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=backup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/backup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,8EAA8E;AAC9E,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,KAAa;IACpD,OAAO,GAAG,IAAI,QAAQ,KAAK,EAAE,CAAC;AAChC,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,IAAI,EAAE;SACd,WAAW,EAAE;SACb,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;AAChC,CAAC"}
|
package/dist/src/cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgBH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,UAAU;IAEnB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAFZ,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM;IAKvC,GAAG,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM;IAKjC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAuB/B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKrC,UAAU,IAAI,MAAM;CAwBrB"}
|
package/dist/src/cache.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* filesystem mtime check.
|
|
11
11
|
*/
|
|
12
12
|
import { createHash } from "node:crypto";
|
|
13
|
-
import { mkdirSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { closeSync, fstatSync, mkdirSync, openSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
export class LocalCache {
|
|
16
16
|
dir;
|
|
@@ -28,22 +28,29 @@ export class LocalCache {
|
|
|
28
28
|
}
|
|
29
29
|
get(key) {
|
|
30
30
|
const file = join(this.dir, `${key}.json`);
|
|
31
|
-
|
|
31
|
+
// Open once, then `fstat` (for the TTL check) and read from the SAME fd.
|
|
32
|
+
// A single handle — rather than statSync-then-readFileSync on the path —
|
|
33
|
+
// closes a check-then-use window (CodeQL js/file-system-race). Any failure
|
|
34
|
+
// (missing, unreadable, vanished mid-read) is treated as a cache miss.
|
|
35
|
+
let fd;
|
|
32
36
|
try {
|
|
33
|
-
|
|
37
|
+
fd = openSync(file, "r");
|
|
34
38
|
}
|
|
35
39
|
catch {
|
|
36
40
|
return null;
|
|
37
41
|
}
|
|
38
|
-
const ageMs = Date.now() - stat.mtimeMs;
|
|
39
|
-
if (ageMs > this.ttlMin * 60_000)
|
|
40
|
-
return null;
|
|
41
42
|
try {
|
|
42
|
-
|
|
43
|
+
const ageMs = Date.now() - fstatSync(fd).mtimeMs;
|
|
44
|
+
if (ageMs > this.ttlMin * 60_000)
|
|
45
|
+
return null;
|
|
46
|
+
return readFileSync(fd, "utf8");
|
|
43
47
|
}
|
|
44
48
|
catch {
|
|
45
49
|
return null;
|
|
46
50
|
}
|
|
51
|
+
finally {
|
|
52
|
+
closeSync(fd);
|
|
53
|
+
}
|
|
47
54
|
}
|
|
48
55
|
put(key, value) {
|
|
49
56
|
const file = join(this.dir, `${key}.json`);
|
package/dist/src/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"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"}
|
package/dist/src/config.d.ts
CHANGED
|
@@ -54,6 +54,17 @@ export interface MemhookConfig {
|
|
|
54
54
|
logging: {
|
|
55
55
|
jsonlPath: string;
|
|
56
56
|
};
|
|
57
|
+
/**
|
|
58
|
+
* Optional proactive nudge: when the memory catalog grows past a threshold,
|
|
59
|
+
* the router attaches a one-line `systemMessage` suggesting `/curate`. This
|
|
60
|
+
* is local-only (no outbound call) and best-effort (never affects fail-soft).
|
|
61
|
+
*/
|
|
62
|
+
curateNudge: {
|
|
63
|
+
enabled: boolean;
|
|
64
|
+
thresholdTokens: number;
|
|
65
|
+
thresholdFiles: number;
|
|
66
|
+
cooldownDays: number;
|
|
67
|
+
};
|
|
57
68
|
scriptVersion: string;
|
|
58
69
|
}
|
|
59
70
|
export declare function loadConfig(env?: NodeJS.ProcessEnv): MemhookConfig;
|
package/dist/src/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,YAAY,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,2EAA2E;QAC3E,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC7B,yEAAyE;QACzE,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IACF,SAAS,EAAE;QACT,QAAQ,EAAE,MAAM,CAAC;QACjB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;QACtB,oEAAoE;QACpE,eAAe,EAAE,IAAI,GAAG,IAAI,CAAC;KAC9B,CAAC;IACF,KAAK,EAAE;QACL,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,SAAS,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;QACrC,YAAY,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC;IACF,KAAK,EAAE;QACL,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,aAAa,EAAE,MAAM,CAAC;CACvB;AAuDD,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,YAAY,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,2EAA2E;QAC3E,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC7B,yEAAyE;QACzE,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IACF,SAAS,EAAE;QACT,QAAQ,EAAE,MAAM,CAAC;QACjB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;QACtB,oEAAoE;QACpE,eAAe,EAAE,IAAI,GAAG,IAAI,CAAC;KAC9B,CAAC;IACF,KAAK,EAAE;QACL,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,SAAS,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;QACrC,YAAY,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC;IACF,KAAK,EAAE;QACL,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF;;;;OAIG;IACH,WAAW,EAAE;QACX,OAAO,EAAE,OAAO,CAAC;QACjB,eAAe,EAAE,MAAM,CAAC;QACxB,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,aAAa,EAAE,MAAM,CAAC;CACvB;AAuDD,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,aAAa,CAmJ9E"}
|
package/dist/src/config.js
CHANGED
|
@@ -166,6 +166,12 @@ export function loadConfig(env = process.env) {
|
|
|
166
166
|
logging: {
|
|
167
167
|
jsonlPath: str("MEMHOOK_LOG_PATH", yaml?.logging?.jsonlPath, join(home, ".claude", "logs", "memhook.log")),
|
|
168
168
|
},
|
|
169
|
+
curateNudge: {
|
|
170
|
+
enabled: bool("MEMHOOK_CURATE_NUDGE", yaml?.curateNudge?.enabled, true),
|
|
171
|
+
thresholdTokens: num("MEMHOOK_CURATE_NUDGE_TOKENS", yaml?.curateNudge?.thresholdTokens, 15000),
|
|
172
|
+
thresholdFiles: num("MEMHOOK_CURATE_NUDGE_FILES", yaml?.curateNudge?.thresholdFiles, 250),
|
|
173
|
+
cooldownDays: num("MEMHOOK_CURATE_NUDGE_COOLDOWN_DAYS", yaml?.curateNudge?.cooldownDays, 7),
|
|
174
|
+
},
|
|
169
175
|
scriptVersion: MEMHOOK_VERSION,
|
|
170
176
|
};
|
|
171
177
|
}
|