recall-mcp-v3 3.2.0 → 3.2.2

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.
@@ -0,0 +1,414 @@
1
+ /**
2
+ * Preprocessor Unit Tests
3
+ *
4
+ * Tests for the JSONL transcript preprocessor that extracts
5
+ * high-signal content from Claude Code transcripts.
6
+ */
7
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
8
+ import * as fs from 'fs';
9
+ import * as path from 'path';
10
+ import * as os from 'os';
11
+ import { preprocessTranscript } from '../preprocessor.js';
12
+ // Test fixtures directory
13
+ const FIXTURES_DIR = path.join(os.tmpdir(), 'recall-preprocessor-tests');
14
+ // Sample JSONL entries for testing
15
+ const SAMPLE_USER_MESSAGE = {
16
+ type: 'user',
17
+ timestamp: '2026-01-28T10:00:00.000Z',
18
+ uuid: 'user-1',
19
+ message: { role: 'user', content: 'Fix the authentication bug in the login flow' },
20
+ };
21
+ const SAMPLE_ASSISTANT_WITH_THINKING = {
22
+ type: 'assistant',
23
+ timestamp: '2026-01-28T10:00:05.000Z',
24
+ uuid: 'assistant-1',
25
+ parentUuid: 'user-1',
26
+ message: {
27
+ role: 'assistant',
28
+ content: [
29
+ {
30
+ type: 'thinking',
31
+ thinking: 'I need to analyze the authentication flow. The bug is likely in the token validation step where we check expiry times.',
32
+ },
33
+ {
34
+ type: 'text',
35
+ text: 'I found the issue. The token expiry check was using local time instead of UTC.',
36
+ },
37
+ ],
38
+ },
39
+ };
40
+ const SAMPLE_TOOL_USE = {
41
+ type: 'assistant',
42
+ timestamp: '2026-01-28T10:00:10.000Z',
43
+ uuid: 'assistant-2',
44
+ message: {
45
+ role: 'assistant',
46
+ content: [
47
+ {
48
+ type: 'tool_use',
49
+ id: 'tool-1',
50
+ name: 'Edit',
51
+ input: {
52
+ file_path: '/src/auth/token.ts',
53
+ old_string: 'new Date()',
54
+ new_string: 'new Date().toISOString()',
55
+ },
56
+ },
57
+ ],
58
+ },
59
+ };
60
+ const SAMPLE_TOOL_RESULT_SUCCESS = {
61
+ type: 'user',
62
+ timestamp: '2026-01-28T10:00:15.000Z',
63
+ uuid: 'user-2',
64
+ message: {
65
+ role: 'user',
66
+ content: [
67
+ {
68
+ type: 'tool_result',
69
+ tool_use_id: 'tool-1',
70
+ content: 'File edited successfully',
71
+ },
72
+ ],
73
+ },
74
+ };
75
+ const SAMPLE_TOOL_RESULT_ERROR = {
76
+ type: 'user',
77
+ timestamp: '2026-01-28T10:00:20.000Z',
78
+ uuid: 'user-3',
79
+ message: {
80
+ role: 'user',
81
+ content: [
82
+ {
83
+ type: 'tool_result',
84
+ tool_use_id: 'tool-2',
85
+ content: 'Error: ENOENT: no such file or directory',
86
+ is_error: true,
87
+ },
88
+ ],
89
+ },
90
+ };
91
+ const SAMPLE_SYSTEM_MESSAGE = {
92
+ type: 'system',
93
+ timestamp: '2026-01-28T10:00:00.000Z',
94
+ message: { content: 'System initialization complete' },
95
+ };
96
+ const SAMPLE_PROGRESS_MESSAGE = {
97
+ type: 'progress',
98
+ timestamp: '2026-01-28T10:00:01.000Z',
99
+ content: { tool: 'Read', status: 'started' },
100
+ };
101
+ const SAMPLE_FILE_HISTORY = {
102
+ type: 'file-history-snapshot',
103
+ timestamp: '2026-01-28T10:00:02.000Z',
104
+ files: ['/src/auth/token.ts'],
105
+ };
106
+ const SAMPLE_USER_FILLER = {
107
+ type: 'user',
108
+ timestamp: '2026-01-28T10:00:25.000Z',
109
+ uuid: 'user-4',
110
+ message: { role: 'user', content: 'ok' },
111
+ };
112
+ const SAMPLE_CONCLUSION = {
113
+ type: 'assistant',
114
+ timestamp: '2026-01-28T10:01:00.000Z',
115
+ uuid: 'assistant-5',
116
+ message: {
117
+ role: 'assistant',
118
+ content: [
119
+ {
120
+ type: 'text',
121
+ text: 'In summary, the authentication bug was caused by timezone handling. The fix involved converting all timestamps to UTC before comparison. This resolved the issue where tokens were being incorrectly marked as expired for users in different timezones. The tests now pass and the login flow works correctly.',
122
+ },
123
+ ],
124
+ },
125
+ };
126
+ // Helper to create test JSONL file
127
+ function createTestJsonl(filename, entries) {
128
+ const filepath = path.join(FIXTURES_DIR, filename);
129
+ const content = entries.map((e) => JSON.stringify(e)).join('\n');
130
+ fs.writeFileSync(filepath, content);
131
+ return filepath;
132
+ }
133
+ describe('preprocessTranscript', () => {
134
+ beforeAll(() => {
135
+ // Create fixtures directory
136
+ if (!fs.existsSync(FIXTURES_DIR)) {
137
+ fs.mkdirSync(FIXTURES_DIR, { recursive: true });
138
+ }
139
+ });
140
+ afterAll(() => {
141
+ // Cleanup fixtures
142
+ if (fs.existsSync(FIXTURES_DIR)) {
143
+ fs.rmSync(FIXTURES_DIR, { recursive: true });
144
+ }
145
+ });
146
+ it('extracts thinking blocks', async () => {
147
+ const filepath = createTestJsonl('thinking.jsonl', [
148
+ SAMPLE_USER_MESSAGE,
149
+ SAMPLE_ASSISTANT_WITH_THINKING,
150
+ ]);
151
+ const result = await preprocessTranscript(filepath);
152
+ expect(result.content).toContain('token validation');
153
+ expect(result.stats.thinkingBlocksIncluded).toBeGreaterThan(0);
154
+ });
155
+ it('captures errors from tool_results', async () => {
156
+ const filepath = createTestJsonl('errors.jsonl', [
157
+ SAMPLE_USER_MESSAGE,
158
+ SAMPLE_TOOL_RESULT_ERROR,
159
+ ]);
160
+ const result = await preprocessTranscript(filepath);
161
+ expect(result.content).toContain('ENOENT');
162
+ expect(result.stats.errorsFound).toBeGreaterThan(0);
163
+ });
164
+ it('logs tool calls with inputs', async () => {
165
+ // Add a non-code-change tool (Read) to test tool call logging
166
+ const readToolUse = {
167
+ type: 'assistant',
168
+ timestamp: '2026-01-28T10:00:08.000Z',
169
+ uuid: 'assistant-read',
170
+ message: {
171
+ role: 'assistant',
172
+ content: [
173
+ {
174
+ type: 'tool_use',
175
+ id: 'tool-read',
176
+ name: 'Read',
177
+ input: { file_path: '/src/config.ts' },
178
+ },
179
+ ],
180
+ },
181
+ };
182
+ const filepath = createTestJsonl('tools.jsonl', [
183
+ SAMPLE_USER_MESSAGE,
184
+ readToolUse,
185
+ SAMPLE_TOOL_USE, // Edit tool - counted as code change
186
+ SAMPLE_TOOL_RESULT_SUCCESS,
187
+ ]);
188
+ const result = await preprocessTranscript(filepath);
189
+ // Edit should be in code changes section
190
+ expect(result.content).toContain('Edit');
191
+ expect(result.content).toContain('token.ts');
192
+ // Read tool should be logged as a regular tool call
193
+ expect(result.stats.toolCallsLogged).toBeGreaterThan(0);
194
+ });
195
+ it('discards system messages', async () => {
196
+ const filepath = createTestJsonl('system.jsonl', [
197
+ SAMPLE_SYSTEM_MESSAGE,
198
+ SAMPLE_USER_MESSAGE,
199
+ SAMPLE_ASSISTANT_WITH_THINKING,
200
+ ]);
201
+ const result = await preprocessTranscript(filepath);
202
+ expect(result.content).not.toContain('System initialization');
203
+ // Should still have the user and assistant messages
204
+ expect(result.stats.messagesExtracted).toBeGreaterThan(0);
205
+ });
206
+ it('discards progress events', async () => {
207
+ const filepath = createTestJsonl('progress.jsonl', [
208
+ SAMPLE_PROGRESS_MESSAGE,
209
+ SAMPLE_USER_MESSAGE,
210
+ ]);
211
+ const result = await preprocessTranscript(filepath);
212
+ expect(result.content).not.toContain('"status": "started"');
213
+ });
214
+ it('discards file-history-snapshot events', async () => {
215
+ const filepath = createTestJsonl('filehistory.jsonl', [
216
+ SAMPLE_FILE_HISTORY,
217
+ SAMPLE_USER_MESSAGE,
218
+ ]);
219
+ const result = await preprocessTranscript(filepath);
220
+ expect(result.content).not.toContain('file-history-snapshot');
221
+ });
222
+ it('skips user filler messages', async () => {
223
+ const filepath = createTestJsonl('filler.jsonl', [
224
+ SAMPLE_USER_MESSAGE,
225
+ SAMPLE_USER_FILLER,
226
+ SAMPLE_ASSISTANT_WITH_THINKING,
227
+ ]);
228
+ const result = await preprocessTranscript(filepath);
229
+ // The actual user intent should be there
230
+ expect(result.content).toContain('authentication bug');
231
+ // But short filler shouldn't be prominently featured
232
+ // (it may appear but not as a separate "user intent" section)
233
+ });
234
+ it('respects maxTokens limit', async () => {
235
+ // Create a file with lots of content
236
+ const manyMessages = [];
237
+ for (let i = 0; i < 100; i++) {
238
+ manyMessages.push({
239
+ type: 'user',
240
+ timestamp: `2026-01-28T10:${String(i).padStart(2, '0')}:00.000Z`,
241
+ uuid: `user-${i}`,
242
+ message: { role: 'user', content: `This is a moderately long message number ${i} that adds to the total token count of the processed output.` },
243
+ });
244
+ manyMessages.push({
245
+ type: 'assistant',
246
+ timestamp: `2026-01-28T10:${String(i).padStart(2, '0')}:05.000Z`,
247
+ uuid: `assistant-${i}`,
248
+ message: {
249
+ role: 'assistant',
250
+ content: [
251
+ { type: 'text', text: `Response to message ${i} with some additional content to increase the size.` },
252
+ ],
253
+ },
254
+ });
255
+ }
256
+ const filepath = createTestJsonl('large.jsonl', manyMessages);
257
+ // Set a low token limit
258
+ const result = await preprocessTranscript(filepath, { maxTokens: 1000 });
259
+ // Should be under the limit (1000 tokens * ~4 chars = 4000 chars)
260
+ expect(result.stats.processedSize).toBeLessThan(5000);
261
+ });
262
+ it('handles malformed JSONL gracefully', async () => {
263
+ const filepath = path.join(FIXTURES_DIR, 'malformed.jsonl');
264
+ fs.writeFileSync(filepath, `
265
+ ${JSON.stringify(SAMPLE_USER_MESSAGE)}
266
+ {invalid json here
267
+ ${JSON.stringify(SAMPLE_ASSISTANT_WITH_THINKING)}
268
+ also not json
269
+ ${JSON.stringify(SAMPLE_CONCLUSION)}
270
+ `);
271
+ // Should not throw, should skip invalid lines
272
+ const result = await preprocessTranscript(filepath);
273
+ // Should still extract valid messages
274
+ expect(result.stats.messagesExtracted).toBeGreaterThan(0);
275
+ expect(result.content).toContain('authentication');
276
+ });
277
+ it('captures key conclusions', async () => {
278
+ const filepath = createTestJsonl('conclusion.jsonl', [
279
+ SAMPLE_USER_MESSAGE,
280
+ SAMPLE_ASSISTANT_WITH_THINKING,
281
+ SAMPLE_CONCLUSION,
282
+ ]);
283
+ const result = await preprocessTranscript(filepath);
284
+ expect(result.content).toContain('summary');
285
+ expect(result.content).toContain('timezone');
286
+ });
287
+ it('includes YAML header with metadata', async () => {
288
+ const filepath = createTestJsonl('metadata.jsonl', [
289
+ SAMPLE_USER_MESSAGE,
290
+ SAMPLE_ASSISTANT_WITH_THINKING,
291
+ SAMPLE_CONCLUSION,
292
+ ]);
293
+ const result = await preprocessTranscript(filepath);
294
+ // Check for YAML header
295
+ expect(result.content).toMatch(/^---/);
296
+ expect(result.content).toContain('start_time:');
297
+ expect(result.content).toContain('end_time:');
298
+ expect(result.content).toContain('primary_goal:');
299
+ });
300
+ it('returns accurate stats', async () => {
301
+ const filepath = createTestJsonl('stats.jsonl', [
302
+ SAMPLE_USER_MESSAGE,
303
+ SAMPLE_ASSISTANT_WITH_THINKING,
304
+ SAMPLE_TOOL_USE,
305
+ SAMPLE_TOOL_RESULT_SUCCESS,
306
+ SAMPLE_TOOL_RESULT_ERROR,
307
+ SAMPLE_CONCLUSION,
308
+ ]);
309
+ const result = await preprocessTranscript(filepath);
310
+ expect(result.stats.originalSize).toBeGreaterThan(0);
311
+ expect(result.stats.processedSize).toBeGreaterThan(0);
312
+ expect(result.stats.processedSize).toBeLessThan(result.stats.originalSize);
313
+ expect(result.stats.errorsFound).toBe(1); // One error result
314
+ expect(result.stats.thinkingBlocksIncluded).toBeGreaterThanOrEqual(1);
315
+ });
316
+ });
317
+ describe('preprocessTranscript - error detection', () => {
318
+ beforeAll(() => {
319
+ if (!fs.existsSync(FIXTURES_DIR)) {
320
+ fs.mkdirSync(FIXTURES_DIR, { recursive: true });
321
+ }
322
+ });
323
+ afterAll(() => {
324
+ if (fs.existsSync(FIXTURES_DIR)) {
325
+ fs.rmSync(FIXTURES_DIR, { recursive: true });
326
+ }
327
+ });
328
+ it('detects errors from is_error flag', async () => {
329
+ const filepath = createTestJsonl('error-flag.jsonl', [
330
+ SAMPLE_USER_MESSAGE,
331
+ SAMPLE_TOOL_RESULT_ERROR,
332
+ ]);
333
+ const result = await preprocessTranscript(filepath);
334
+ expect(result.stats.errorsFound).toBe(1);
335
+ });
336
+ it('detects errors from content patterns', async () => {
337
+ const errorResult = {
338
+ type: 'user',
339
+ timestamp: '2026-01-28T10:00:00.000Z',
340
+ message: {
341
+ content: [
342
+ {
343
+ type: 'tool_result',
344
+ tool_use_id: 'tool-1',
345
+ content: 'Error: failed to compile\nTypeScript error at line 42',
346
+ },
347
+ ],
348
+ },
349
+ };
350
+ const filepath = createTestJsonl('error-pattern.jsonl', [
351
+ SAMPLE_USER_MESSAGE,
352
+ errorResult,
353
+ ]);
354
+ const result = await preprocessTranscript(filepath);
355
+ expect(result.stats.errorsFound).toBeGreaterThan(0);
356
+ });
357
+ it('does not flag code snippets mentioning error as errors', async () => {
358
+ // This tests the false positive prevention
359
+ const codeResult = {
360
+ type: 'user',
361
+ timestamp: '2026-01-28T10:00:00.000Z',
362
+ message: {
363
+ content: [
364
+ {
365
+ type: 'tool_result',
366
+ tool_use_id: 'tool-1',
367
+ content: ` 1→function handleError(error) {
368
+ 2→ console.log(error.message);
369
+ 3→ return { error: null };
370
+ 4→}`,
371
+ },
372
+ ],
373
+ },
374
+ };
375
+ const filepath = createTestJsonl('code-error.jsonl', [
376
+ SAMPLE_USER_MESSAGE,
377
+ codeResult,
378
+ ]);
379
+ const result = await preprocessTranscript(filepath);
380
+ // Should NOT count code mentioning "error" as an actual error
381
+ expect(result.stats.errorsFound).toBe(0);
382
+ });
383
+ });
384
+ describe('preprocessTranscript - priority extraction', () => {
385
+ beforeAll(() => {
386
+ if (!fs.existsSync(FIXTURES_DIR)) {
387
+ fs.mkdirSync(FIXTURES_DIR, { recursive: true });
388
+ }
389
+ });
390
+ afterAll(() => {
391
+ if (fs.existsSync(FIXTURES_DIR)) {
392
+ fs.rmSync(FIXTURES_DIR, { recursive: true });
393
+ }
394
+ });
395
+ it('includes Priority 1 section header', async () => {
396
+ const filepath = createTestJsonl('p1.jsonl', [
397
+ SAMPLE_USER_MESSAGE,
398
+ SAMPLE_TOOL_RESULT_ERROR,
399
+ ]);
400
+ const result = await preprocessTranscript(filepath);
401
+ expect(result.content).toContain('Priority 1');
402
+ expect(result.content).toContain('Outcomes');
403
+ });
404
+ it('includes Priority 2 section when thinking blocks present', async () => {
405
+ const filepath = createTestJsonl('p2.jsonl', [
406
+ SAMPLE_USER_MESSAGE,
407
+ SAMPLE_ASSISTANT_WITH_THINKING,
408
+ ]);
409
+ const result = await preprocessTranscript(filepath);
410
+ expect(result.content).toContain('Priority 2');
411
+ expect(result.content).toContain('Reasoning');
412
+ });
413
+ });
414
+ //# sourceMappingURL=preprocessor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preprocessor.test.js","sourceRoot":"","sources":["../../src/__tests__/preprocessor.test.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -4,15 +4,54 @@
4
4
  * CLI commands for use from shell hooks (e.g., SessionEnd).
5
5
  * This allows Claude Code hooks to trigger Recall saves automatically.
6
6
  */
7
+ /**
8
+ * Find the current session's transcript file.
9
+ *
10
+ * Claude Code stores transcripts at:
11
+ * ~/.claude/projects/<project-hash>/<session-uuid>.jsonl
12
+ *
13
+ * The project hash is derived from the absolute path of the project.
14
+ * Algorithm: Replace all / with - (keeps leading dash)
15
+ *
16
+ * Example:
17
+ * Path: /Users/ray/projects/recall-v3
18
+ * Hash: -Users-ray-projects-recall-v3
19
+ *
20
+ * This function walks UP the directory tree to find transcripts, so it works
21
+ * even when called from a subdirectory (e.g., packages/mcp-v3).
22
+ *
23
+ * @param cwd The current working directory (project path)
24
+ * @returns Path to most recent JSONL file, or null if not found
25
+ */
26
+ export declare function findCurrentTranscript(cwd: string): string | null;
27
+ /**
28
+ * Find the most recent transcript GLOBALLY across all projects.
29
+ * This is a fallback when path-based resolution fails (e.g., when MCP runs as subprocess).
30
+ *
31
+ * @returns Object with transcriptPath and projectPath, or null if not found
32
+ */
33
+ export declare function findMostRecentTranscriptGlobally(): {
34
+ transcriptPath: string;
35
+ projectPath: string;
36
+ } | null;
7
37
  /**
8
38
  * Save a transcript with AI summarization.
9
39
  * This is the main entry point for SessionEnd hooks.
40
+ *
41
+ * Uses the new preprocessor to extract high-signal content from JSONL,
42
+ * with fallback to the old parseTranscript() if preprocessing fails.
10
43
  */
11
44
  export declare function saveTranscript(options: {
12
45
  transcriptPath: string;
13
46
  cwd: string;
14
47
  quiet?: boolean;
15
- }): Promise<void>;
48
+ }): Promise<{
49
+ sessionId: string;
50
+ stats?: {
51
+ originalSize: number;
52
+ processedSize: number;
53
+ };
54
+ }>;
16
55
  /**
17
56
  * CLI entry point - parses arguments and dispatches to commands.
18
57
  */
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA0PH;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoHhB;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmF1D"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiMH;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA2BhE;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,IAAI;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAmEzG;AAqID;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CA8L1F;AAWD;;GAEG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqG1D"}