nlm-memory 0.10.0 → 0.10.1

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.
@@ -1,300 +0,0 @@
1
- /**
2
- * Batch scanner for the useful_hit_rate metric.
3
- *
4
- * Joins hook-log.jsonl (recall events) against Claude Code conversation
5
- * transcripts, writes one useful-hit-log.jsonl entry per recall event,
6
- * and returns aggregate counts.
7
- *
8
- * A recall is "useful" when ≥1 of the surfaced session IDs appears in the
9
- * text or tool_use inputs of the next NEXT_TURNS_LIMIT assistant turns after
10
- * the hook fired. Entries with no matching transcript get useful=null
11
- * (unmeasurable).
12
- *
13
- * Probe entries (promptPreview matching PROBE_PATTERNS) are excluded from
14
- * the scan to keep the metric clean.
15
- */
16
- import { readFile, appendFile, stat, mkdir, readdir } from "node:fs/promises";
17
- import { existsSync, readFileSync } from "node:fs";
18
- import { dirname, join } from "node:path";
19
- import { homedir } from "node:os";
20
- const NEXT_TURNS_LIMIT = 3;
21
- const PROBE_PATTERNS = [
22
- /concurrency probe/i,
23
- /test probe/i,
24
- /path test/i,
25
- /recall test/i,
26
- /smoke/i,
27
- /cutover/i,
28
- ];
29
- export function defaultUsefulHitLogPath() {
30
- return process.env["NLM_USEFUL_HIT_LOG"] ?? join(homedir(), ".nlm", "useful-hit-log.jsonl");
31
- }
32
- function defaultHookLogPath() {
33
- return process.env["NLM_HOOK_LOG"] ?? join(homedir(), ".nlm", "hook-log.jsonl");
34
- }
35
- function defaultTranscriptsDir() {
36
- return join(homedir(), ".claude", "projects");
37
- }
38
- export function isProbe(promptPreview) {
39
- return PROBE_PATTERNS.some((re) => re.test(promptPreview));
40
- }
41
- async function findTranscriptPath(conversationId, transcriptsDir) {
42
- let names;
43
- try {
44
- names = await readdir(transcriptsDir);
45
- }
46
- catch {
47
- return null;
48
- }
49
- for (const name of names) {
50
- const candidate = join(transcriptsDir, name, `${conversationId}.jsonl`);
51
- if (existsSync(candidate))
52
- return candidate;
53
- }
54
- return null;
55
- }
56
- /**
57
- * Read assistant turns from a Claude Code transcript JSONL that have a
58
- * timestamp >= afterTs. Returns up to `limit` turns, each as a single
59
- * concatenated string of text + serialized tool_use inputs.
60
- */
61
- export function extractAssistantTurnsAfter(transcriptPath, afterTs, limit) {
62
- let raw;
63
- try {
64
- raw = readFileSync(transcriptPath, "utf8");
65
- }
66
- catch {
67
- return [];
68
- }
69
- const turns = [];
70
- let pastCutoff = false;
71
- for (const line of raw.split("\n")) {
72
- const trimmed = line.trim();
73
- if (!trimmed)
74
- continue;
75
- let entry;
76
- try {
77
- entry = JSON.parse(trimmed);
78
- }
79
- catch {
80
- continue;
81
- }
82
- if (!pastCutoff) {
83
- const tsRaw = entry["timestamp"];
84
- if (typeof tsRaw === "string") {
85
- const ts = Date.parse(tsRaw);
86
- if (Number.isFinite(ts) && ts >= afterTs)
87
- pastCutoff = true;
88
- }
89
- if (!pastCutoff)
90
- continue;
91
- }
92
- if (entry["type"] !== "assistant")
93
- continue;
94
- const message = entry["message"];
95
- if (!message)
96
- continue;
97
- const content = message["content"];
98
- const parts = [];
99
- if (typeof content === "string") {
100
- if (content)
101
- parts.push(content);
102
- }
103
- else if (Array.isArray(content)) {
104
- for (const block of content) {
105
- if (block["type"] === "text" && typeof block["text"] === "string") {
106
- parts.push(block["text"]);
107
- }
108
- else if (block["type"] === "tool_use") {
109
- parts.push(JSON.stringify(block["input"]));
110
- }
111
- }
112
- }
113
- if (parts.length > 0) {
114
- turns.push(parts.join(" "));
115
- if (turns.length >= limit)
116
- break;
117
- }
118
- }
119
- return turns;
120
- }
121
- export function findMatchedId(ids, turns) {
122
- const haystack = turns.join(" ");
123
- for (const id of ids) {
124
- if (haystack.includes(id))
125
- return id;
126
- }
127
- return null;
128
- }
129
- async function readHookRecalls(hookLogPath, cutoff) {
130
- let raw;
131
- try {
132
- raw = await readFile(hookLogPath, "utf8");
133
- }
134
- catch {
135
- return [];
136
- }
137
- const results = [];
138
- for (const line of raw.split("\n")) {
139
- const trimmed = line.trim();
140
- if (!trimmed)
141
- continue;
142
- let entry;
143
- try {
144
- entry = JSON.parse(trimmed);
145
- }
146
- catch {
147
- continue;
148
- }
149
- // Skip stop-hook entries (they have a "kind" field)
150
- if (typeof entry["kind"] === "string")
151
- continue;
152
- const ts = typeof entry["ts"] === "string" ? entry["ts"] : null;
153
- if (!ts)
154
- continue;
155
- const tsMs = Date.parse(ts);
156
- if (!Number.isFinite(tsMs) || tsMs < cutoff)
157
- continue;
158
- const wouldInject = Array.isArray(entry["wouldInject"])
159
- ? entry["wouldInject"].filter((x) => typeof x === "string")
160
- : [];
161
- if (wouldInject.length === 0)
162
- continue;
163
- const conversationId = typeof entry["conversationId"] === "string" ? entry["conversationId"] : null;
164
- if (!conversationId)
165
- continue;
166
- const promptPreview = typeof entry["promptPreview"] === "string" ? entry["promptPreview"] : "";
167
- if (isProbe(promptPreview))
168
- continue;
169
- results.push({ ts, conversationId, promptPreview, wouldInject });
170
- }
171
- return results;
172
- }
173
- async function readScannedKeys(usefulHitLogPath) {
174
- const seen = new Set();
175
- try {
176
- await stat(usefulHitLogPath);
177
- }
178
- catch {
179
- return seen;
180
- }
181
- let raw;
182
- try {
183
- raw = await readFile(usefulHitLogPath, "utf8");
184
- }
185
- catch {
186
- return seen;
187
- }
188
- for (const line of raw.split("\n")) {
189
- const trimmed = line.trim();
190
- if (!trimmed)
191
- continue;
192
- let entry;
193
- try {
194
- entry = JSON.parse(trimmed);
195
- }
196
- catch {
197
- continue;
198
- }
199
- const ts = typeof entry["ts"] === "string" ? entry["ts"] : null;
200
- const convId = typeof entry["conversationId"] === "string" ? entry["conversationId"] : null;
201
- if (ts && convId)
202
- seen.add(`${ts}:${convId}`);
203
- }
204
- return seen;
205
- }
206
- export async function scanUsefulHits(opts) {
207
- const days = opts.days ?? 1;
208
- const hookLogPath = opts.hookLogPath ?? defaultHookLogPath();
209
- const usefulHitLogPath = opts.usefulHitLogPath ?? defaultUsefulHitLogPath();
210
- const transcriptsDir = opts.transcriptsDir ?? defaultTranscriptsDir();
211
- const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;
212
- const recalls = await readHookRecalls(hookLogPath, cutoff);
213
- const scannedKeys = await readScannedKeys(usefulHitLogPath);
214
- let total = 0;
215
- let measurable = 0;
216
- let useful = 0;
217
- const newEntries = [];
218
- for (const recall of recalls) {
219
- total += 1;
220
- const key = `${recall.ts}:${recall.conversationId}`;
221
- if (scannedKeys.has(key))
222
- continue;
223
- const transcriptPath = await findTranscriptPath(recall.conversationId, transcriptsDir);
224
- const hookTs = Date.parse(recall.ts);
225
- let usefulVal = null;
226
- let matchedId = null;
227
- if (transcriptPath !== null && Number.isFinite(hookTs)) {
228
- const turns = extractAssistantTurnsAfter(transcriptPath, hookTs, NEXT_TURNS_LIMIT);
229
- if (turns.length > 0) {
230
- measurable += 1;
231
- matchedId = findMatchedId(recall.wouldInject, turns);
232
- usefulVal = matchedId !== null;
233
- if (usefulVal)
234
- useful += 1;
235
- }
236
- }
237
- newEntries.push({
238
- ts: recall.ts,
239
- source: "hook",
240
- conversationId: recall.conversationId,
241
- returnedIds: recall.wouldInject,
242
- useful: usefulVal,
243
- matchedId,
244
- scannedAt: new Date().toISOString(),
245
- });
246
- }
247
- if (!opts.dryRun && newEntries.length > 0) {
248
- await mkdir(dirname(usefulHitLogPath), { recursive: true });
249
- await appendFile(usefulHitLogPath, newEntries.map((e) => JSON.stringify(e)).join("\n") + "\n", "utf8");
250
- }
251
- return { total, measurable, useful, appended: opts.dryRun ? 0 : newEntries.length };
252
- }
253
- /**
254
- * Compute useful_hit_rate from an existing useful-hit-log.jsonl over a
255
- * rolling window. Returns null if the log is absent or has no measurable
256
- * entries in the window.
257
- */
258
- export async function readUsefulHitRate(usefulHitLogPath = defaultUsefulHitLogPath(), days = 1) {
259
- try {
260
- await stat(usefulHitLogPath);
261
- }
262
- catch {
263
- return null;
264
- }
265
- let raw;
266
- try {
267
- raw = await readFile(usefulHitLogPath, "utf8");
268
- }
269
- catch {
270
- return null;
271
- }
272
- const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;
273
- let measurable = 0;
274
- let useful = 0;
275
- for (const line of raw.split("\n")) {
276
- const trimmed = line.trim();
277
- if (!trimmed)
278
- continue;
279
- let entry;
280
- try {
281
- entry = JSON.parse(trimmed);
282
- }
283
- catch {
284
- continue;
285
- }
286
- const tsRaw = typeof entry["ts"] === "string" ? entry["ts"] : null;
287
- if (!tsRaw)
288
- continue;
289
- const ts = Date.parse(tsRaw);
290
- if (!Number.isFinite(ts) || ts < cutoff)
291
- continue;
292
- if (entry["useful"] === null || entry["useful"] === undefined)
293
- continue;
294
- measurable += 1;
295
- if (entry["useful"] === true)
296
- useful += 1;
297
- }
298
- return measurable === 0 ? null : Math.round((useful / measurable) * 1000) / 1000;
299
- }
300
- //# sourceMappingURL=useful-scan.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useful-scan.js","sourceRoot":"","sources":["../../../src/core/recall/useful-scan.ts"],"names":[],"mappings":"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"}
@@ -1,26 +0,0 @@
1
- /**
2
- * Claude Code PreCompact hook entrypoint for NLM.
3
- *
4
- * Fires before Claude Code compacts a long transcript. At compaction time the
5
- * in-flight surfaced-IDs memo and any pending citation state would be lost.
6
- * This hook POSTs a compaction event to the daemon so it can do a final
7
- * synchronous citation scan of the transcript before the shape is lost.
8
- *
9
- * Daemon endpoint: POST localhost:3940/api/hook/pre-compact
10
- * This endpoint does NOT exist yet in the daemon — the hook ships fail-soft
11
- * (swallows errors) so it won't block compaction when the endpoint is absent.
12
- * The daemon-side handler is a follow-up task.
13
- *
14
- * Payload: { conversation_id, transcript_path, surfaced_set, ts }
15
- *
16
- * Fail-open by design: any error yields a clean exit with no output.
17
- */
18
- export interface PreCompactInput {
19
- readonly conversationId: string;
20
- readonly transcriptPath: string;
21
- }
22
- export interface PreCompactResult {
23
- readonly conversationId: string;
24
- readonly posted: boolean;
25
- }
26
- export declare function runPreCompact(input: PreCompactInput, portValue?: string): Promise<PreCompactResult>;
@@ -1,94 +0,0 @@
1
- /**
2
- * Claude Code PreCompact hook entrypoint for NLM.
3
- *
4
- * Fires before Claude Code compacts a long transcript. At compaction time the
5
- * in-flight surfaced-IDs memo and any pending citation state would be lost.
6
- * This hook POSTs a compaction event to the daemon so it can do a final
7
- * synchronous citation scan of the transcript before the shape is lost.
8
- *
9
- * Daemon endpoint: POST localhost:3940/api/hook/pre-compact
10
- * This endpoint does NOT exist yet in the daemon — the hook ships fail-soft
11
- * (swallows errors) so it won't block compaction when the endpoint is absent.
12
- * The daemon-side handler is a follow-up task.
13
- *
14
- * Payload: { conversation_id, transcript_path, surfaced_set, ts }
15
- *
16
- * Fail-open by design: any error yields a clean exit with no output.
17
- */
18
- import { pathToFileURL } from "node:url";
19
- import { appendFileSync, mkdirSync } from "node:fs";
20
- import { homedir } from "node:os";
21
- import { dirname, join } from "node:path";
22
- import { loadSurfaced } from "../core/hook/memo.js";
23
- const POST_TIMEOUT_MS = 1500;
24
- export async function runPreCompact(input, portValue = process.env["NLM_PORT"] ?? "3940") {
25
- const surfacedSet = [...loadSurfaced(input.conversationId)];
26
- const payload = {
27
- conversation_id: input.conversationId,
28
- transcript_path: input.transcriptPath,
29
- surfaced_set: surfacedSet,
30
- ts: new Date().toISOString(),
31
- };
32
- const controller = new AbortController();
33
- const timer = setTimeout(() => controller.abort(), POST_TIMEOUT_MS);
34
- try {
35
- const res = await fetch(`http://localhost:${portValue}/api/hook/pre-compact`, {
36
- method: "POST",
37
- headers: { "content-type": "application/json" },
38
- body: JSON.stringify(payload),
39
- signal: controller.signal,
40
- });
41
- return { conversationId: input.conversationId, posted: res.ok };
42
- }
43
- catch {
44
- // Endpoint absent or daemon down — fail soft, never block compaction.
45
- return { conversationId: input.conversationId, posted: false };
46
- }
47
- finally {
48
- clearTimeout(timer);
49
- }
50
- }
51
- function logPath() {
52
- return process.env["NLM_HOOK_LOG"] ?? join(homedir(), ".nlm", "hook-log.jsonl");
53
- }
54
- function logResult(result) {
55
- try {
56
- const path = logPath();
57
- mkdirSync(dirname(path), { recursive: true });
58
- appendFileSync(path, `${JSON.stringify({
59
- ts: new Date().toISOString(),
60
- kind: "pre-compact",
61
- conversationId: result.conversationId,
62
- posted: result.posted,
63
- })}\n`, "utf8");
64
- }
65
- catch {
66
- // Telemetry failure must never break the hook.
67
- }
68
- }
69
- function readStdin() {
70
- return new Promise((resolve) => {
71
- let data = "";
72
- process.stdin.setEncoding("utf8");
73
- process.stdin.on("data", (chunk) => (data += chunk));
74
- process.stdin.on("end", () => resolve(data));
75
- process.stdin.on("error", () => resolve(data));
76
- });
77
- }
78
- async function main() {
79
- try {
80
- const raw = await readStdin();
81
- const payload = JSON.parse(raw);
82
- const conversationId = typeof payload.session_id === "string" ? payload.session_id : "unknown";
83
- const transcriptPath = typeof payload.transcript_path === "string" ? payload.transcript_path : "";
84
- const result = await runPreCompact({ conversationId, transcriptPath });
85
- logResult(result);
86
- }
87
- catch {
88
- // Fail open — never block Claude Code compaction.
89
- }
90
- }
91
- if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
92
- void main();
93
- }
94
- //# sourceMappingURL=pre-compact-hook.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pre-compact-hook.js","sourceRoot":"","sources":["../../src/hook/pre-compact-hook.ts"],"names":[],"mappings":"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"}
@@ -1,30 +0,0 @@
1
- /**
2
- * Claude Code SubagentStart hook entrypoint for NLM.
3
- *
4
- * Fires when Claude Code dispatches a subagent (Agent tool). Subagents have
5
- * their own session IDs but are invisible to NLM's session corpus today.
6
- * This hook captures the parent→subagent link so NLM can correlate subagent
7
- * transcripts back to the dispatching conversation when SessionEnd fires.
8
- *
9
- * Capture-only. No recall injection — subagents inherit context from their
10
- * dispatch prompt; additional recall would pollute their narrow task scope.
11
- *
12
- * Daemon endpoint: POST localhost:3940/api/hook/subagent-start
13
- * This endpoint does NOT exist yet in the daemon — the hook ships fail-soft
14
- * (swallows errors). The daemon-side handler is a follow-up task.
15
- *
16
- * Payload: { parent_conversation_id, subagent_session_id, subagent_description, ts }
17
- *
18
- * Fail-open by design: any error yields a clean exit with no output.
19
- */
20
- export interface SubagentStartInput {
21
- readonly parentConversationId: string;
22
- readonly subagentSessionId: string;
23
- readonly subagentDescription: string;
24
- }
25
- export interface SubagentStartResult {
26
- readonly parentConversationId: string;
27
- readonly subagentSessionId: string;
28
- readonly posted: boolean;
29
- }
30
- export declare function runSubagentStart(input: SubagentStartInput, portValue?: string): Promise<SubagentStartResult>;
@@ -1,108 +0,0 @@
1
- /**
2
- * Claude Code SubagentStart hook entrypoint for NLM.
3
- *
4
- * Fires when Claude Code dispatches a subagent (Agent tool). Subagents have
5
- * their own session IDs but are invisible to NLM's session corpus today.
6
- * This hook captures the parent→subagent link so NLM can correlate subagent
7
- * transcripts back to the dispatching conversation when SessionEnd fires.
8
- *
9
- * Capture-only. No recall injection — subagents inherit context from their
10
- * dispatch prompt; additional recall would pollute their narrow task scope.
11
- *
12
- * Daemon endpoint: POST localhost:3940/api/hook/subagent-start
13
- * This endpoint does NOT exist yet in the daemon — the hook ships fail-soft
14
- * (swallows errors). The daemon-side handler is a follow-up task.
15
- *
16
- * Payload: { parent_conversation_id, subagent_session_id, subagent_description, ts }
17
- *
18
- * Fail-open by design: any error yields a clean exit with no output.
19
- */
20
- import { pathToFileURL } from "node:url";
21
- import { appendFileSync, mkdirSync } from "node:fs";
22
- import { homedir } from "node:os";
23
- import { dirname, join } from "node:path";
24
- const POST_TIMEOUT_MS = 1500;
25
- export async function runSubagentStart(input, portValue = process.env["NLM_PORT"] ?? "3940") {
26
- const payload = {
27
- parent_conversation_id: input.parentConversationId,
28
- subagent_session_id: input.subagentSessionId,
29
- subagent_description: input.subagentDescription,
30
- ts: new Date().toISOString(),
31
- };
32
- const controller = new AbortController();
33
- const timer = setTimeout(() => controller.abort(), POST_TIMEOUT_MS);
34
- try {
35
- const res = await fetch(`http://localhost:${portValue}/api/hook/subagent-start`, {
36
- method: "POST",
37
- headers: { "content-type": "application/json" },
38
- body: JSON.stringify(payload),
39
- signal: controller.signal,
40
- });
41
- return {
42
- parentConversationId: input.parentConversationId,
43
- subagentSessionId: input.subagentSessionId,
44
- posted: res.ok,
45
- };
46
- }
47
- catch {
48
- // Endpoint absent or daemon down — fail soft, never block subagent dispatch.
49
- return {
50
- parentConversationId: input.parentConversationId,
51
- subagentSessionId: input.subagentSessionId,
52
- posted: false,
53
- };
54
- }
55
- finally {
56
- clearTimeout(timer);
57
- }
58
- }
59
- function logPath() {
60
- return process.env["NLM_HOOK_LOG"] ?? join(homedir(), ".nlm", "hook-log.jsonl");
61
- }
62
- function logResult(result) {
63
- try {
64
- const path = logPath();
65
- mkdirSync(dirname(path), { recursive: true });
66
- appendFileSync(path, `${JSON.stringify({
67
- ts: new Date().toISOString(),
68
- kind: "subagent-start",
69
- parentConversationId: result.parentConversationId,
70
- subagentSessionId: result.subagentSessionId,
71
- posted: result.posted,
72
- })}\n`, "utf8");
73
- }
74
- catch {
75
- // Telemetry failure must never break the hook.
76
- }
77
- }
78
- function readStdin() {
79
- return new Promise((resolve) => {
80
- let data = "";
81
- process.stdin.setEncoding("utf8");
82
- process.stdin.on("data", (chunk) => (data += chunk));
83
- process.stdin.on("end", () => resolve(data));
84
- process.stdin.on("error", () => resolve(data));
85
- });
86
- }
87
- async function main() {
88
- try {
89
- const raw = await readStdin();
90
- const payload = JSON.parse(raw);
91
- const subagentSessionId = typeof payload.session_id === "string" ? payload.session_id : "unknown";
92
- const parentConversationId = typeof payload.parent_session_id === "string" ? payload.parent_session_id : "unknown";
93
- const subagentDescription = typeof payload.description === "string" ? payload.description : "";
94
- const result = await runSubagentStart({
95
- parentConversationId,
96
- subagentSessionId,
97
- subagentDescription,
98
- });
99
- logResult(result);
100
- }
101
- catch {
102
- // Fail open — never block subagent dispatch.
103
- }
104
- }
105
- if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
106
- void main();
107
- }
108
- //# sourceMappingURL=subagent-start-hook.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent-start-hook.js","sourceRoot":"","sources":["../../src/hook/subagent-start-hook.ts"],"names":[],"mappings":"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"}