recall-player 1.0.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/README.md +238 -0
- package/backend/dist/db/connection.d.ts +47 -0
- package/backend/dist/db/connection.d.ts.map +1 -0
- package/backend/dist/db/connection.js +88 -0
- package/backend/dist/db/connection.js.map +1 -0
- package/backend/dist/db/queries.d.ts +172 -0
- package/backend/dist/db/queries.d.ts.map +1 -0
- package/backend/dist/db/queries.js +436 -0
- package/backend/dist/db/queries.js.map +1 -0
- package/backend/dist/db/schema.d.ts +100 -0
- package/backend/dist/db/schema.d.ts.map +1 -0
- package/backend/dist/db/schema.js +6 -0
- package/backend/dist/db/schema.js.map +1 -0
- package/backend/dist/db/transcript-connection.d.ts +57 -0
- package/backend/dist/db/transcript-connection.d.ts.map +1 -0
- package/backend/dist/db/transcript-connection.js +112 -0
- package/backend/dist/db/transcript-connection.js.map +1 -0
- package/backend/dist/db/transcript-queries.d.ts +152 -0
- package/backend/dist/db/transcript-queries.d.ts.map +1 -0
- package/backend/dist/db/transcript-queries.js +706 -0
- package/backend/dist/db/transcript-queries.js.map +1 -0
- package/backend/dist/db/transcript-schema.d.ts +143 -0
- package/backend/dist/db/transcript-schema.d.ts.map +1 -0
- package/backend/dist/db/transcript-schema.js +10 -0
- package/backend/dist/db/transcript-schema.js.map +1 -0
- package/backend/dist/index.d.ts +2 -0
- package/backend/dist/index.d.ts.map +1 -0
- package/backend/dist/index.js +96 -0
- package/backend/dist/index.js.map +1 -0
- package/backend/dist/parser/agent-detector.d.ts +76 -0
- package/backend/dist/parser/agent-detector.d.ts.map +1 -0
- package/backend/dist/parser/agent-detector.js +281 -0
- package/backend/dist/parser/agent-detector.js.map +1 -0
- package/backend/dist/parser/base-parser.d.ts +123 -0
- package/backend/dist/parser/base-parser.d.ts.map +1 -0
- package/backend/dist/parser/base-parser.js +364 -0
- package/backend/dist/parser/base-parser.js.map +1 -0
- package/backend/dist/parser/claude-parser.d.ts +78 -0
- package/backend/dist/parser/claude-parser.d.ts.map +1 -0
- package/backend/dist/parser/claude-parser.js +247 -0
- package/backend/dist/parser/claude-parser.js.map +1 -0
- package/backend/dist/parser/codex-parser.d.ts +128 -0
- package/backend/dist/parser/codex-parser.d.ts.map +1 -0
- package/backend/dist/parser/codex-parser.js +371 -0
- package/backend/dist/parser/codex-parser.js.map +1 -0
- package/backend/dist/parser/gemini-parser.d.ts +107 -0
- package/backend/dist/parser/gemini-parser.d.ts.map +1 -0
- package/backend/dist/parser/gemini-parser.js +360 -0
- package/backend/dist/parser/gemini-parser.js.map +1 -0
- package/backend/dist/parser/parser-factory.d.ts +83 -0
- package/backend/dist/parser/parser-factory.d.ts.map +1 -0
- package/backend/dist/parser/parser-factory.js +163 -0
- package/backend/dist/parser/parser-factory.js.map +1 -0
- package/backend/dist/parser/session-indexer.d.ts +79 -0
- package/backend/dist/parser/session-indexer.d.ts.map +1 -0
- package/backend/dist/parser/session-indexer.js +558 -0
- package/backend/dist/parser/session-indexer.js.map +1 -0
- package/backend/dist/parser/timeline-builder.d.ts +7 -0
- package/backend/dist/parser/timeline-builder.d.ts.map +1 -0
- package/backend/dist/parser/timeline-builder.js +334 -0
- package/backend/dist/parser/timeline-builder.js.map +1 -0
- package/backend/dist/parser/transcript-parser.d.ts +25 -0
- package/backend/dist/parser/transcript-parser.d.ts.map +1 -0
- package/backend/dist/parser/transcript-parser.js +137 -0
- package/backend/dist/parser/transcript-parser.js.map +1 -0
- package/backend/dist/routes/commentary.d.ts +33 -0
- package/backend/dist/routes/commentary.d.ts.map +1 -0
- package/backend/dist/routes/commentary.js +153 -0
- package/backend/dist/routes/commentary.js.map +1 -0
- package/backend/dist/routes/import.d.ts +3 -0
- package/backend/dist/routes/import.d.ts.map +1 -0
- package/backend/dist/routes/import.js +220 -0
- package/backend/dist/routes/import.js.map +1 -0
- package/backend/dist/routes/sessions.d.ts +3 -0
- package/backend/dist/routes/sessions.d.ts.map +1 -0
- package/backend/dist/routes/sessions.js +393 -0
- package/backend/dist/routes/sessions.js.map +1 -0
- package/backend/dist/server.d.ts +25 -0
- package/backend/dist/server.d.ts.map +1 -0
- package/backend/dist/server.js +110 -0
- package/backend/dist/server.js.map +1 -0
- package/backend/dist/services/example-import.d.ts +20 -0
- package/backend/dist/services/example-import.d.ts.map +1 -0
- package/backend/dist/services/example-import.js +93 -0
- package/backend/dist/services/example-import.js.map +1 -0
- package/backend/dist/services/file-watcher.d.ts +22 -0
- package/backend/dist/services/file-watcher.d.ts.map +1 -0
- package/backend/dist/services/file-watcher.js +141 -0
- package/backend/dist/services/file-watcher.js.map +1 -0
- package/backend/dist/services/import-cli.d.ts +11 -0
- package/backend/dist/services/import-cli.d.ts.map +1 -0
- package/backend/dist/services/import-cli.js +171 -0
- package/backend/dist/services/import-cli.js.map +1 -0
- package/backend/dist/services/transcript-importer.d.ts +98 -0
- package/backend/dist/services/transcript-importer.d.ts.map +1 -0
- package/backend/dist/services/transcript-importer.js +342 -0
- package/backend/dist/services/transcript-importer.js.map +1 -0
- package/backend/dist/types/transcript.d.ts +174 -0
- package/backend/dist/types/transcript.d.ts.map +1 -0
- package/backend/dist/types/transcript.js +8 -0
- package/backend/dist/types/transcript.js.map +1 -0
- package/backend/package.json +40 -0
- package/backend/public/.gitkeep +0 -0
- package/backend/public/assets/index-D8IP1zNL.css +1 -0
- package/backend/public/assets/index-GtkMiMqE.js +69 -0
- package/backend/public/index.html +14 -0
- package/bin/recall.js +43 -0
- package/package.json +54 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ParsedTranscript, SessionTimeline } from '../types/transcript';
|
|
2
|
+
/**
|
|
3
|
+
* Build a playable timeline from parsed transcript
|
|
4
|
+
* Converts raw entries into structured PlaybackFrame objects
|
|
5
|
+
*/
|
|
6
|
+
export declare function buildTimeline(transcript: ParsedTranscript): Promise<SessionTimeline>;
|
|
7
|
+
//# sourceMappingURL=timeline-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline-builder.d.ts","sourceRoot":"","sources":["../../src/parser/timeline-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gBAAgB,EAEhB,eAAe,EAKhB,MAAM,qBAAqB,CAAC;AAE7B;;;GAGG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,gBAAgB,GAC3B,OAAO,CAAC,eAAe,CAAC,CAoD1B"}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildTimeline = buildTimeline;
|
|
4
|
+
/**
|
|
5
|
+
* Build a playable timeline from parsed transcript
|
|
6
|
+
* Converts raw entries into structured PlaybackFrame objects
|
|
7
|
+
*/
|
|
8
|
+
async function buildTimeline(transcript) {
|
|
9
|
+
const frames = [];
|
|
10
|
+
// Track tool results to match with tool calls
|
|
11
|
+
const toolResultMap = new Map();
|
|
12
|
+
// First pass: collect all tool results
|
|
13
|
+
for (const entry of transcript.entries) {
|
|
14
|
+
if (entry.message?.content) {
|
|
15
|
+
for (const block of entry.message.content) {
|
|
16
|
+
if (block.type === 'tool_result') {
|
|
17
|
+
toolResultMap.set(block.tool_use_id, block);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// Second pass: build frames
|
|
23
|
+
for (const entry of transcript.entries) {
|
|
24
|
+
const entryFrames = extractFramesFromEntry(entry, toolResultMap);
|
|
25
|
+
frames.push(...entryFrames);
|
|
26
|
+
}
|
|
27
|
+
// Calculate frame durations
|
|
28
|
+
calculateFrameDurations(frames);
|
|
29
|
+
// Build timeline metadata
|
|
30
|
+
const startedAt = new Date(transcript.metadata.startTime).getTime();
|
|
31
|
+
const completedAt = transcript.metadata.endTime
|
|
32
|
+
? new Date(transcript.metadata.endTime).getTime()
|
|
33
|
+
: undefined;
|
|
34
|
+
return {
|
|
35
|
+
sessionId: transcript.sessionId,
|
|
36
|
+
slug: transcript.metadata.slug || 'unknown-session',
|
|
37
|
+
project: transcript.metadata.projectName || 'Unknown Project',
|
|
38
|
+
agent: 'claude', // Legacy builder defaults to Claude
|
|
39
|
+
startedAt,
|
|
40
|
+
completedAt,
|
|
41
|
+
frames,
|
|
42
|
+
totalFrames: frames.length,
|
|
43
|
+
metadata: {
|
|
44
|
+
cwd: transcript.metadata.cwd || '',
|
|
45
|
+
claudeVersion: transcript.metadata.claudeVersion,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Extract playback frames from a single transcript entry
|
|
51
|
+
*/
|
|
52
|
+
function extractFramesFromEntry(entry, toolResultMap) {
|
|
53
|
+
const frames = [];
|
|
54
|
+
if (!entry.message?.content) {
|
|
55
|
+
return frames;
|
|
56
|
+
}
|
|
57
|
+
const timestamp = new Date(entry.timestamp).getTime();
|
|
58
|
+
const cwd = entry.cwd || '';
|
|
59
|
+
// Handle content as string or array
|
|
60
|
+
const content = entry.message.content;
|
|
61
|
+
const contentBlocks = Array.isArray(content) ? content : [{ type: 'text', text: content }];
|
|
62
|
+
// Process each content block
|
|
63
|
+
for (const block of contentBlocks) {
|
|
64
|
+
switch (block.type) {
|
|
65
|
+
case 'text':
|
|
66
|
+
// Text block - could be user message or Claude response
|
|
67
|
+
if (entry.message.role === 'user') {
|
|
68
|
+
frames.push({
|
|
69
|
+
id: `${entry.uuid}-user-text`,
|
|
70
|
+
type: 'user_message',
|
|
71
|
+
timestamp,
|
|
72
|
+
userMessage: {
|
|
73
|
+
text: block.text,
|
|
74
|
+
},
|
|
75
|
+
context: { cwd },
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
else if (entry.message.role === 'assistant') {
|
|
79
|
+
frames.push({
|
|
80
|
+
id: `${entry.uuid}-assistant-text`,
|
|
81
|
+
type: 'claude_response',
|
|
82
|
+
timestamp,
|
|
83
|
+
claudeResponse: {
|
|
84
|
+
text: block.text,
|
|
85
|
+
},
|
|
86
|
+
context: { cwd },
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
case 'thinking':
|
|
91
|
+
// Thinking block
|
|
92
|
+
if ('thinking' in block) {
|
|
93
|
+
frames.push({
|
|
94
|
+
id: `${entry.uuid}-thinking`,
|
|
95
|
+
type: 'claude_thinking',
|
|
96
|
+
timestamp,
|
|
97
|
+
thinking: {
|
|
98
|
+
text: block.thinking,
|
|
99
|
+
signature: block.signature,
|
|
100
|
+
},
|
|
101
|
+
context: { cwd },
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
case 'tool_use':
|
|
106
|
+
// Tool call - match with result
|
|
107
|
+
const toolUse = block;
|
|
108
|
+
const toolResult = toolResultMap.get(toolUse.id);
|
|
109
|
+
if (toolResult) {
|
|
110
|
+
const toolExecution = buildToolExecution(toolUse, toolResult);
|
|
111
|
+
frames.push({
|
|
112
|
+
id: `${entry.uuid}-tool-${toolUse.id}`,
|
|
113
|
+
type: 'tool_execution',
|
|
114
|
+
timestamp,
|
|
115
|
+
toolExecution,
|
|
116
|
+
context: {
|
|
117
|
+
cwd,
|
|
118
|
+
...extractFileContext(toolUse),
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
// Tool call without result yet (might be in-progress)
|
|
124
|
+
// Create a placeholder frame
|
|
125
|
+
frames.push({
|
|
126
|
+
id: `${entry.uuid}-tool-${toolUse.id}`,
|
|
127
|
+
type: 'tool_execution',
|
|
128
|
+
timestamp,
|
|
129
|
+
toolExecution: {
|
|
130
|
+
tool: toolUse.name,
|
|
131
|
+
input: toolUse.input,
|
|
132
|
+
output: {
|
|
133
|
+
content: '(No result available)',
|
|
134
|
+
isError: false,
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
context: {
|
|
138
|
+
cwd,
|
|
139
|
+
...extractFileContext(toolUse),
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
break;
|
|
144
|
+
// tool_result blocks are handled when processing tool_use
|
|
145
|
+
case 'tool_result':
|
|
146
|
+
break;
|
|
147
|
+
default:
|
|
148
|
+
// Unknown block type - skip
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return frames;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Build ToolExecution object from tool call and result
|
|
156
|
+
*/
|
|
157
|
+
function buildToolExecution(toolUse, toolResult) {
|
|
158
|
+
const output = extractToolOutput(toolResult);
|
|
159
|
+
const fileDiff = extractFileDiff(toolUse, toolResult);
|
|
160
|
+
return {
|
|
161
|
+
tool: toolUse.name,
|
|
162
|
+
input: toolUse.input,
|
|
163
|
+
output,
|
|
164
|
+
fileDiff,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Extract tool output from tool result block
|
|
169
|
+
*/
|
|
170
|
+
function extractToolOutput(toolResult) {
|
|
171
|
+
let content = '';
|
|
172
|
+
let isError = toolResult.is_error || false;
|
|
173
|
+
let exitCode;
|
|
174
|
+
// Handle different content formats
|
|
175
|
+
if (typeof toolResult.content === 'string') {
|
|
176
|
+
content = toolResult.content;
|
|
177
|
+
}
|
|
178
|
+
else if (Array.isArray(toolResult.content)) {
|
|
179
|
+
// Content is array of blocks
|
|
180
|
+
const textBlocks = toolResult.content
|
|
181
|
+
.filter((block) => block.type === 'text')
|
|
182
|
+
.map((block) => block.text);
|
|
183
|
+
content = textBlocks.join('\n');
|
|
184
|
+
}
|
|
185
|
+
// Extract exit code for Bash commands
|
|
186
|
+
if (content.includes('Exit code:')) {
|
|
187
|
+
const match = content.match(/Exit code: (\d+)/);
|
|
188
|
+
if (match && match[1]) {
|
|
189
|
+
exitCode = parseInt(match[1], 10);
|
|
190
|
+
isError = exitCode !== 0;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return { content, isError, exitCode };
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Extract file diff for file operations (Write, Edit)
|
|
197
|
+
*/
|
|
198
|
+
function extractFileDiff(toolUse, _toolResult) {
|
|
199
|
+
const input = toolUse.input;
|
|
200
|
+
if (toolUse.name === 'Write' && input.file_path && input.content) {
|
|
201
|
+
return {
|
|
202
|
+
filePath: input.file_path,
|
|
203
|
+
newContent: input.content,
|
|
204
|
+
language: inferLanguage(input.file_path),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (toolUse.name === 'Edit' &&
|
|
208
|
+
input.file_path &&
|
|
209
|
+
input.old_string &&
|
|
210
|
+
input.new_string) {
|
|
211
|
+
return {
|
|
212
|
+
filePath: input.file_path,
|
|
213
|
+
oldContent: input.old_string,
|
|
214
|
+
newContent: input.new_string,
|
|
215
|
+
language: inferLanguage(input.file_path),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Infer programming language from file extension
|
|
222
|
+
*/
|
|
223
|
+
function inferLanguage(filePath) {
|
|
224
|
+
const ext = filePath.split('.').pop()?.toLowerCase() || '';
|
|
225
|
+
const languageMap = {
|
|
226
|
+
ts: 'typescript',
|
|
227
|
+
tsx: 'tsx',
|
|
228
|
+
js: 'javascript',
|
|
229
|
+
jsx: 'jsx',
|
|
230
|
+
py: 'python',
|
|
231
|
+
rb: 'ruby',
|
|
232
|
+
go: 'go',
|
|
233
|
+
rs: 'rust',
|
|
234
|
+
java: 'java',
|
|
235
|
+
cpp: 'cpp',
|
|
236
|
+
c: 'c',
|
|
237
|
+
cs: 'csharp',
|
|
238
|
+
php: 'php',
|
|
239
|
+
swift: 'swift',
|
|
240
|
+
kt: 'kotlin',
|
|
241
|
+
sh: 'bash',
|
|
242
|
+
bash: 'bash',
|
|
243
|
+
zsh: 'bash',
|
|
244
|
+
json: 'json',
|
|
245
|
+
yaml: 'yaml',
|
|
246
|
+
yml: 'yaml',
|
|
247
|
+
xml: 'xml',
|
|
248
|
+
html: 'html',
|
|
249
|
+
css: 'css',
|
|
250
|
+
scss: 'scss',
|
|
251
|
+
sass: 'sass',
|
|
252
|
+
md: 'markdown',
|
|
253
|
+
sql: 'sql',
|
|
254
|
+
};
|
|
255
|
+
return languageMap[ext || ''] || 'text';
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Extract file context (files read/modified) from tool use
|
|
259
|
+
*/
|
|
260
|
+
function extractFileContext(toolUse) {
|
|
261
|
+
const context = {};
|
|
262
|
+
if (toolUse.name === 'Read' && toolUse.input.file_path) {
|
|
263
|
+
context.filesRead = [toolUse.input.file_path];
|
|
264
|
+
}
|
|
265
|
+
if ((toolUse.name === 'Write' || toolUse.name === 'Edit') &&
|
|
266
|
+
toolUse.input.file_path) {
|
|
267
|
+
context.filesModified = [toolUse.input.file_path];
|
|
268
|
+
}
|
|
269
|
+
return context;
|
|
270
|
+
}
|
|
271
|
+
// Dead air compression constants
|
|
272
|
+
const DEAD_AIR_THRESHOLD = 5000; // 5 seconds - compress gaps longer than this
|
|
273
|
+
const COMPRESSED_DURATION = 1500; // Compress long gaps to 1.5 seconds
|
|
274
|
+
/**
|
|
275
|
+
* Calculate duration for each frame based on content and timing
|
|
276
|
+
* Applies dead air compression for gaps > DEAD_AIR_THRESHOLD
|
|
277
|
+
*/
|
|
278
|
+
function calculateFrameDurations(frames) {
|
|
279
|
+
for (let i = 0; i < frames.length; i++) {
|
|
280
|
+
const frame = frames[i];
|
|
281
|
+
if (!frame)
|
|
282
|
+
continue;
|
|
283
|
+
const nextFrame = frames[i + 1];
|
|
284
|
+
if (nextFrame) {
|
|
285
|
+
// Actual time to next frame
|
|
286
|
+
const actualDuration = nextFrame.timestamp - frame.timestamp;
|
|
287
|
+
if (actualDuration > DEAD_AIR_THRESHOLD) {
|
|
288
|
+
// Dead air detected - compress it
|
|
289
|
+
frame.originalDuration = actualDuration;
|
|
290
|
+
frame.duration = COMPRESSED_DURATION;
|
|
291
|
+
frame.isCompressed = true;
|
|
292
|
+
}
|
|
293
|
+
else if (actualDuration < 30000) {
|
|
294
|
+
// Normal duration - use as-is
|
|
295
|
+
frame.duration = actualDuration;
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
// Very long gap (> 30s) - use default duration but mark as compressed
|
|
299
|
+
frame.originalDuration = actualDuration;
|
|
300
|
+
frame.duration = getDefaultDuration(frame);
|
|
301
|
+
frame.isCompressed = true;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
// Last frame - use default duration
|
|
306
|
+
frame.duration = getDefaultDuration(frame);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Get default duration for a frame based on its type and content
|
|
312
|
+
*/
|
|
313
|
+
function getDefaultDuration(frame) {
|
|
314
|
+
switch (frame.type) {
|
|
315
|
+
case 'user_message':
|
|
316
|
+
// 2-3 seconds based on length
|
|
317
|
+
const userText = frame.userMessage?.text || '';
|
|
318
|
+
return userText.length > 200 ? 3000 : 2000;
|
|
319
|
+
case 'claude_thinking':
|
|
320
|
+
// 1 second (collapsed by default)
|
|
321
|
+
return 1000;
|
|
322
|
+
case 'claude_response':
|
|
323
|
+
// 3-5 seconds based on length
|
|
324
|
+
const responseText = frame.claudeResponse?.text || '';
|
|
325
|
+
return Math.min(5000, 3000 + responseText.length / 100);
|
|
326
|
+
case 'tool_execution':
|
|
327
|
+
// 2 seconds for most tools, 1 second for file ops
|
|
328
|
+
const toolName = frame.toolExecution?.tool || '';
|
|
329
|
+
return toolName === 'Bash' ? 2000 : 1000;
|
|
330
|
+
default:
|
|
331
|
+
return 2000;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
//# sourceMappingURL=timeline-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline-builder.js","sourceRoot":"","sources":["../../src/parser/timeline-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { TranscriptEntry, ParsedTranscript } from '../types/transcript';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a .jsonl transcript file from Claude Code session
|
|
4
|
+
* @param filePath Absolute path to .jsonl file
|
|
5
|
+
* @returns Parsed transcript with all entries and metadata
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseTranscriptFile(filePath: string): Promise<ParsedTranscript>;
|
|
8
|
+
/**
|
|
9
|
+
* Build dependency graph from parentUuid relationships
|
|
10
|
+
* @returns Map of uuid -> list of child uuids
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildDependencyGraph(entries: TranscriptEntry[]): Map<string, string[]>;
|
|
13
|
+
/**
|
|
14
|
+
* Get all entries of a specific type
|
|
15
|
+
*/
|
|
16
|
+
export declare function getEntriesByType(entries: TranscriptEntry[], type: string): TranscriptEntry[];
|
|
17
|
+
/**
|
|
18
|
+
* Find entry by UUID
|
|
19
|
+
*/
|
|
20
|
+
export declare function findEntryByUuid(entries: TranscriptEntry[], uuid: string): TranscriptEntry | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Get child entries for a given UUID
|
|
23
|
+
*/
|
|
24
|
+
export declare function getChildEntries(entries: TranscriptEntry[], parentUuid: string): TranscriptEntry[];
|
|
25
|
+
//# sourceMappingURL=transcript-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript-parser.d.ts","sourceRoot":"","sources":["../../src/parser/transcript-parser.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,eAAe,EACf,gBAAgB,EAEjB,MAAM,qBAAqB,CAAC;AAE7B;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,CAAC,CAyC3B;AA8DD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,eAAe,EAAE,GACzB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAYvB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EAAE,EAC1B,IAAI,EAAE,MAAM,GACX,eAAe,EAAE,CAEnB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,eAAe,EAAE,EAC1B,IAAI,EAAE,MAAM,GACX,eAAe,GAAG,SAAS,CAE7B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,eAAe,EAAE,EAC1B,UAAU,EAAE,MAAM,GACjB,eAAe,EAAE,CAEnB"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseTranscriptFile = parseTranscriptFile;
|
|
7
|
+
exports.buildDependencyGraph = buildDependencyGraph;
|
|
8
|
+
exports.getEntriesByType = getEntriesByType;
|
|
9
|
+
exports.findEntryByUuid = findEntryByUuid;
|
|
10
|
+
exports.getChildEntries = getChildEntries;
|
|
11
|
+
const fs_1 = __importDefault(require("fs"));
|
|
12
|
+
const readline_1 = __importDefault(require("readline"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
/**
|
|
15
|
+
* Parse a .jsonl transcript file from Claude Code session
|
|
16
|
+
* @param filePath Absolute path to .jsonl file
|
|
17
|
+
* @returns Parsed transcript with all entries and metadata
|
|
18
|
+
*/
|
|
19
|
+
async function parseTranscriptFile(filePath) {
|
|
20
|
+
const entries = [];
|
|
21
|
+
// Create read stream for line-by-line processing
|
|
22
|
+
const fileStream = fs_1.default.createReadStream(filePath);
|
|
23
|
+
const rl = readline_1.default.createInterface({
|
|
24
|
+
input: fileStream,
|
|
25
|
+
crlfDelay: Infinity,
|
|
26
|
+
});
|
|
27
|
+
// Parse each line as JSON
|
|
28
|
+
for await (const line of rl) {
|
|
29
|
+
if (line.trim()) {
|
|
30
|
+
try {
|
|
31
|
+
const entry = JSON.parse(line);
|
|
32
|
+
entries.push(entry);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.warn(`Failed to parse line in ${filePath}:`, error);
|
|
36
|
+
// Continue parsing other lines
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Sort by timestamp for chronological order
|
|
41
|
+
entries.sort((a, b) => {
|
|
42
|
+
const timeA = new Date(a.timestamp).getTime();
|
|
43
|
+
const timeB = new Date(b.timestamp).getTime();
|
|
44
|
+
return timeA - timeB;
|
|
45
|
+
});
|
|
46
|
+
// Extract metadata from entries
|
|
47
|
+
const metadata = extractMetadata(entries, filePath);
|
|
48
|
+
// Session ID from first entry or filename
|
|
49
|
+
const sessionId = entries[0]?.sessionId || path_1.default.basename(filePath, '.jsonl');
|
|
50
|
+
return {
|
|
51
|
+
sessionId,
|
|
52
|
+
entries,
|
|
53
|
+
metadata,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Extract metadata from parsed transcript entries
|
|
58
|
+
*/
|
|
59
|
+
function extractMetadata(entries, filePath) {
|
|
60
|
+
const firstEntry = entries[0];
|
|
61
|
+
const lastEntry = entries[entries.length - 1];
|
|
62
|
+
// Extract project name from file path
|
|
63
|
+
// Path format: ~/.claude/projects/{encoded-project-path}/{session-uuid}.jsonl
|
|
64
|
+
const pathParts = filePath.split(path_1.default.sep);
|
|
65
|
+
const projectsIndex = pathParts.indexOf('projects');
|
|
66
|
+
const encodedProjectPath = projectsIndex >= 0 ? pathParts[projectsIndex + 1] : undefined;
|
|
67
|
+
// Decode project path (e.g., "-Users-fpirzada-Documents-cc-mem-video-player")
|
|
68
|
+
const projectName = encodedProjectPath
|
|
69
|
+
? decodeProjectPath(encodedProjectPath)
|
|
70
|
+
: undefined;
|
|
71
|
+
// Extract slug from first entry if available
|
|
72
|
+
const slug = extractSlug(entries);
|
|
73
|
+
return {
|
|
74
|
+
startTime: firstEntry?.timestamp || new Date().toISOString(),
|
|
75
|
+
endTime: lastEntry?.timestamp,
|
|
76
|
+
totalEntries: entries.length,
|
|
77
|
+
cwd: firstEntry?.cwd,
|
|
78
|
+
slug,
|
|
79
|
+
projectName,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Decode encoded project path from .claude/projects/ directory
|
|
84
|
+
* Example: "-Users-fpirzada-Documents-cc-mem-video-player" → "/Users/fpirzada/Documents/cc_mem_video_player"
|
|
85
|
+
*/
|
|
86
|
+
function decodeProjectPath(encoded) {
|
|
87
|
+
// Replace leading dash with slash, then replace dashes with slashes
|
|
88
|
+
return encoded.replace(/^-/, '/').replace(/-/g, '/');
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Extract human-readable slug from transcript entries
|
|
92
|
+
* Looks for session metadata entries that contain slug
|
|
93
|
+
*/
|
|
94
|
+
function extractSlug(entries) {
|
|
95
|
+
// Look for entries that might contain slug information
|
|
96
|
+
for (const entry of entries) {
|
|
97
|
+
if (entry.type === 'session_metadata' && entry.slug) {
|
|
98
|
+
return entry.slug;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// If no slug found, return undefined
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Build dependency graph from parentUuid relationships
|
|
106
|
+
* @returns Map of uuid -> list of child uuids
|
|
107
|
+
*/
|
|
108
|
+
function buildDependencyGraph(entries) {
|
|
109
|
+
const graph = new Map();
|
|
110
|
+
for (const entry of entries) {
|
|
111
|
+
if (entry.parentUuid) {
|
|
112
|
+
const children = graph.get(entry.parentUuid) || [];
|
|
113
|
+
children.push(entry.uuid);
|
|
114
|
+
graph.set(entry.parentUuid, children);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return graph;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get all entries of a specific type
|
|
121
|
+
*/
|
|
122
|
+
function getEntriesByType(entries, type) {
|
|
123
|
+
return entries.filter((entry) => entry.type === type);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Find entry by UUID
|
|
127
|
+
*/
|
|
128
|
+
function findEntryByUuid(entries, uuid) {
|
|
129
|
+
return entries.find((entry) => entry.uuid === uuid);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get child entries for a given UUID
|
|
133
|
+
*/
|
|
134
|
+
function getChildEntries(entries, parentUuid) {
|
|
135
|
+
return entries.filter((entry) => entry.parentUuid === parentUuid);
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=transcript-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript-parser.js","sourceRoot":"","sources":["../../src/parser/transcript-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
declare const router: import("express-serve-static-core").Router;
|
|
2
|
+
/**
|
|
3
|
+
* Observation from claude-mem
|
|
4
|
+
*/
|
|
5
|
+
export interface MemObservation {
|
|
6
|
+
id: number;
|
|
7
|
+
timestamp: number;
|
|
8
|
+
session_id: string;
|
|
9
|
+
type: string;
|
|
10
|
+
title: string;
|
|
11
|
+
content: string;
|
|
12
|
+
metadata?: Record<string, any>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Commentary bubble mapped to frame timeline
|
|
16
|
+
*/
|
|
17
|
+
export interface CommentaryBubble {
|
|
18
|
+
id: number;
|
|
19
|
+
timestamp: number;
|
|
20
|
+
frameIndex?: number;
|
|
21
|
+
type: string;
|
|
22
|
+
title: string;
|
|
23
|
+
content: string;
|
|
24
|
+
metadata?: Record<string, any>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Alternative implementation using direct sqlite access
|
|
28
|
+
* This is a fallback if MCP server is not available
|
|
29
|
+
* Exported for potential future use or testing
|
|
30
|
+
*/
|
|
31
|
+
export declare function queryClaudeMemDirect(sessionId: string): Promise<MemObservation[]>;
|
|
32
|
+
export default router;
|
|
33
|
+
//# sourceMappingURL=commentary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commentary.d.ts","sourceRoot":"","sources":["../../src/routes/commentary.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAGxB;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AA6GD;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CA6CvF;AAED,eAAe,MAAM,CAAC"}
|