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,393 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const express_1 = require("express");
|
|
4
|
+
const session_indexer_1 = require("../parser/session-indexer");
|
|
5
|
+
const parser_factory_1 = require("../parser/parser-factory");
|
|
6
|
+
const agent_detector_1 = require("../parser/agent-detector");
|
|
7
|
+
const transcript_queries_1 = require("../db/transcript-queries");
|
|
8
|
+
const router = (0, express_1.Router)();
|
|
9
|
+
// Global cache for parsed timelines (optional optimization)
|
|
10
|
+
const timelineCache = new Map();
|
|
11
|
+
/**
|
|
12
|
+
* Helper to get data source from query parameter
|
|
13
|
+
* Defaults to 'filesystem' for backwards compatibility
|
|
14
|
+
*/
|
|
15
|
+
function getDataSource(req) {
|
|
16
|
+
const source = getStringParam(req.query.source);
|
|
17
|
+
if (source === 'db') {
|
|
18
|
+
return 'db';
|
|
19
|
+
}
|
|
20
|
+
return 'filesystem';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Helper to safely extract string query parameters
|
|
24
|
+
*/
|
|
25
|
+
function getStringParam(value) {
|
|
26
|
+
if (typeof value === 'string') {
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* GET /api/agents
|
|
33
|
+
* List available agents and their session counts
|
|
34
|
+
*
|
|
35
|
+
* Response:
|
|
36
|
+
* - agents: Array of available agent types
|
|
37
|
+
* - counts: Object mapping agent type to session count
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* GET /api/agents
|
|
41
|
+
* {
|
|
42
|
+
* "agents": ["claude", "codex"],
|
|
43
|
+
* "counts": { "claude": 150, "codex": 25 }
|
|
44
|
+
* }
|
|
45
|
+
*/
|
|
46
|
+
router.get('/agents', async (_req, res) => {
|
|
47
|
+
try {
|
|
48
|
+
const indexer = (0, session_indexer_1.getSessionIndexer)();
|
|
49
|
+
const available = await indexer.getAvailableAgents();
|
|
50
|
+
res.json(available);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.error('Error fetching agents:', error);
|
|
54
|
+
res.status(500).json({
|
|
55
|
+
error: 'Failed to fetch agents',
|
|
56
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
/**
|
|
61
|
+
* GET /api/sessions
|
|
62
|
+
* List all available sessions
|
|
63
|
+
*
|
|
64
|
+
* Query Parameters:
|
|
65
|
+
* - source (string): Data source - 'filesystem' or 'db' (default: 'filesystem')
|
|
66
|
+
* - offset (number): Skip N sessions (default: 0)
|
|
67
|
+
* - limit (number): Return N sessions (default: 20)
|
|
68
|
+
* - project (string): Filter by project name
|
|
69
|
+
* - agent (string): Filter by agent type ('claude', 'codex', 'gemini', 'unknown')
|
|
70
|
+
*
|
|
71
|
+
* Response:
|
|
72
|
+
* - sessions: Array of session metadata
|
|
73
|
+
* - total: Total number of sessions
|
|
74
|
+
* - offset: Current offset
|
|
75
|
+
* - limit: Current limit
|
|
76
|
+
* - source: Data source used
|
|
77
|
+
* - agent: Agent filter if applied
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* GET /api/sessions?limit=10&offset=0
|
|
81
|
+
* GET /api/sessions?source=db&limit=10
|
|
82
|
+
* GET /api/sessions?project=/Users/fpirzada/Documents/cc_mem_video_player
|
|
83
|
+
* GET /api/sessions?agent=claude
|
|
84
|
+
*/
|
|
85
|
+
router.get('/', async (req, res) => {
|
|
86
|
+
try {
|
|
87
|
+
const source = getDataSource(req);
|
|
88
|
+
const offsetStr = getStringParam(req.query.offset);
|
|
89
|
+
const limitStr = getStringParam(req.query.limit);
|
|
90
|
+
const offset = offsetStr ? parseInt(offsetStr, 10) : 0;
|
|
91
|
+
const limit = limitStr ? parseInt(limitStr, 10) : 20;
|
|
92
|
+
const projectFilter = getStringParam(req.query.project);
|
|
93
|
+
const agent = getStringParam(req.query.agent);
|
|
94
|
+
if (source === 'db') {
|
|
95
|
+
// Use database
|
|
96
|
+
const result = (0, transcript_queries_1.getTranscriptSessions)({
|
|
97
|
+
offset,
|
|
98
|
+
limit,
|
|
99
|
+
project: projectFilter,
|
|
100
|
+
agent,
|
|
101
|
+
});
|
|
102
|
+
res.json({
|
|
103
|
+
sessions: result.sessions,
|
|
104
|
+
total: result.total,
|
|
105
|
+
offset,
|
|
106
|
+
limit,
|
|
107
|
+
source: 'db',
|
|
108
|
+
agent,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Use filesystem (existing implementation)
|
|
113
|
+
const indexer = (0, session_indexer_1.getSessionIndexer)();
|
|
114
|
+
let sessions = await indexer.getAllSessions();
|
|
115
|
+
// Filter by project if specified
|
|
116
|
+
if (projectFilter) {
|
|
117
|
+
sessions = sessions.filter((s) => s.project.includes(projectFilter));
|
|
118
|
+
}
|
|
119
|
+
// Filter by agent if specified
|
|
120
|
+
if (agent) {
|
|
121
|
+
sessions = sessions.filter((s) => s.agent === agent);
|
|
122
|
+
}
|
|
123
|
+
// Sort by start time (most recent first)
|
|
124
|
+
sessions.sort((a, b) => {
|
|
125
|
+
return new Date(b.startTime).getTime() - new Date(a.startTime).getTime();
|
|
126
|
+
});
|
|
127
|
+
// Apply pagination
|
|
128
|
+
const paginatedSessions = sessions.slice(offset, offset + limit);
|
|
129
|
+
res.json({
|
|
130
|
+
sessions: paginatedSessions,
|
|
131
|
+
total: sessions.length,
|
|
132
|
+
offset,
|
|
133
|
+
limit,
|
|
134
|
+
source: 'filesystem',
|
|
135
|
+
agent,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.error('Error fetching sessions:', error);
|
|
141
|
+
res.status(500).json({
|
|
142
|
+
error: 'Failed to fetch sessions',
|
|
143
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
144
|
+
stack: error instanceof Error ? error.stack : undefined
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
/**
|
|
149
|
+
* GET /api/sessions/:id
|
|
150
|
+
* Get session timeline metadata (without frames)
|
|
151
|
+
*
|
|
152
|
+
* URL Parameters:
|
|
153
|
+
* - id: Session UUID
|
|
154
|
+
*
|
|
155
|
+
* Response:
|
|
156
|
+
* - SessionTimeline object (without frames array)
|
|
157
|
+
*
|
|
158
|
+
* Status Codes:
|
|
159
|
+
* - 200: Success
|
|
160
|
+
* - 404: Session not found
|
|
161
|
+
* - 500: Internal error
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* GET /api/sessions/4b198fdf-b80d-4bbc-806f-2900282cdc56
|
|
165
|
+
*/
|
|
166
|
+
router.get('/:id', async (req, res) => {
|
|
167
|
+
try {
|
|
168
|
+
const sessionId = req.params.id;
|
|
169
|
+
if (!sessionId) {
|
|
170
|
+
res.status(400).json({ error: 'Session ID is required' });
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const indexer = (0, session_indexer_1.getSessionIndexer)();
|
|
174
|
+
// Get session metadata from index
|
|
175
|
+
const metadata = await indexer.getSessionMetadata(sessionId);
|
|
176
|
+
if (!metadata) {
|
|
177
|
+
res.status(404).json({ error: 'Session not found' });
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
// Build timeline to get full metadata
|
|
181
|
+
const timeline = await getOrBuildTimeline(sessionId);
|
|
182
|
+
if (!timeline) {
|
|
183
|
+
res.status(404).json({ error: 'Failed to load session timeline' });
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
// Return timeline without frames
|
|
187
|
+
const { frames, ...timelineMetadata } = timeline;
|
|
188
|
+
res.json(timelineMetadata);
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
console.error('Error fetching session:', error);
|
|
192
|
+
res.status(500).json({
|
|
193
|
+
error: 'Failed to fetch session',
|
|
194
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
/**
|
|
199
|
+
* GET /api/sessions/:id/frames
|
|
200
|
+
* Get playback frames for a session with pagination
|
|
201
|
+
*
|
|
202
|
+
* URL Parameters:
|
|
203
|
+
* - id: Session UUID
|
|
204
|
+
*
|
|
205
|
+
* Query Parameters:
|
|
206
|
+
* - source (string): Data source - 'filesystem' or 'db' (default: 'filesystem')
|
|
207
|
+
* - offset (number): Skip N frames (default: 0)
|
|
208
|
+
* - limit (number): Return N frames (default: 100)
|
|
209
|
+
*
|
|
210
|
+
* Response:
|
|
211
|
+
* - frames: Array of PlaybackFrame objects
|
|
212
|
+
* - total: Total number of frames
|
|
213
|
+
* - offset: Current offset
|
|
214
|
+
* - limit: Current limit
|
|
215
|
+
* - source: Data source used
|
|
216
|
+
*
|
|
217
|
+
* Status Codes:
|
|
218
|
+
* - 200: Success
|
|
219
|
+
* - 404: Session not found
|
|
220
|
+
* - 500: Internal error
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* GET /api/sessions/4b198fdf-b80d-4bbc-806f-2900282cdc56/frames?offset=0&limit=100
|
|
224
|
+
* GET /api/sessions/4b198fdf-b80d-4bbc-806f-2900282cdc56/frames?source=db&offset=0&limit=100
|
|
225
|
+
*/
|
|
226
|
+
router.get('/:id/frames', async (req, res) => {
|
|
227
|
+
try {
|
|
228
|
+
const sessionId = req.params.id;
|
|
229
|
+
if (!sessionId) {
|
|
230
|
+
res.status(400).json({ error: 'Session ID is required' });
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const source = getDataSource(req);
|
|
234
|
+
const offsetStr = getStringParam(req.query.offset);
|
|
235
|
+
const limitStr = getStringParam(req.query.limit);
|
|
236
|
+
const offset = offsetStr ? parseInt(offsetStr, 10) : 0;
|
|
237
|
+
const limit = limitStr ? parseInt(limitStr, 10) : 100;
|
|
238
|
+
if (source === 'db') {
|
|
239
|
+
// Use database
|
|
240
|
+
const result = (0, transcript_queries_1.getTranscriptFrames)(sessionId, { offset, limit });
|
|
241
|
+
res.json({
|
|
242
|
+
frames: result.frames,
|
|
243
|
+
total: result.total,
|
|
244
|
+
offset,
|
|
245
|
+
limit,
|
|
246
|
+
source: 'db',
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
// Use filesystem (existing implementation)
|
|
251
|
+
const timeline = await getOrBuildTimeline(sessionId);
|
|
252
|
+
if (!timeline) {
|
|
253
|
+
res.status(404).json({ error: 'Session not found' });
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const paginatedFrames = timeline.frames.slice(offset, offset + limit);
|
|
257
|
+
res.json({
|
|
258
|
+
frames: paginatedFrames,
|
|
259
|
+
total: timeline.totalFrames,
|
|
260
|
+
offset,
|
|
261
|
+
limit,
|
|
262
|
+
source: 'filesystem',
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
console.error('Error fetching session frames:', error);
|
|
268
|
+
res.status(500).json({
|
|
269
|
+
error: 'Failed to fetch session frames',
|
|
270
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
/**
|
|
275
|
+
* GET /api/sessions/:id/frames/:frameId
|
|
276
|
+
* Get a single playback frame by ID
|
|
277
|
+
*
|
|
278
|
+
* URL Parameters:
|
|
279
|
+
* - id: Session UUID
|
|
280
|
+
* - frameId: Frame ID
|
|
281
|
+
*
|
|
282
|
+
* Response:
|
|
283
|
+
* - PlaybackFrame object
|
|
284
|
+
*
|
|
285
|
+
* Status Codes:
|
|
286
|
+
* - 200: Success
|
|
287
|
+
* - 404: Session or frame not found
|
|
288
|
+
* - 500: Internal error
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* GET /api/sessions/4b198fdf-b80d-4bbc-806f-2900282cdc56/frames/abc123-user-text
|
|
292
|
+
*/
|
|
293
|
+
router.get('/:id/frames/:frameId', async (req, res) => {
|
|
294
|
+
try {
|
|
295
|
+
const sessionId = req.params.id;
|
|
296
|
+
const frameId = req.params.frameId;
|
|
297
|
+
if (!sessionId || !frameId) {
|
|
298
|
+
res.status(400).json({ error: 'Session ID and Frame ID are required' });
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
// Build or get cached timeline
|
|
302
|
+
const timeline = await getOrBuildTimeline(sessionId);
|
|
303
|
+
if (!timeline) {
|
|
304
|
+
res.status(404).json({ error: 'Session not found' });
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
// Find frame by ID
|
|
308
|
+
const frame = timeline.frames.find((f) => f.id === frameId);
|
|
309
|
+
if (!frame) {
|
|
310
|
+
res.status(404).json({ error: 'Frame not found' });
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
res.json(frame);
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
console.error('Error fetching frame:', error);
|
|
317
|
+
res.status(500).json({
|
|
318
|
+
error: 'Failed to fetch frame',
|
|
319
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
/**
|
|
324
|
+
* POST /api/sessions/:id/refresh
|
|
325
|
+
* Refresh cached timeline for a session
|
|
326
|
+
* Forces re-parsing of transcript file
|
|
327
|
+
*
|
|
328
|
+
* URL Parameters:
|
|
329
|
+
* - id: Session UUID
|
|
330
|
+
*
|
|
331
|
+
* Response:
|
|
332
|
+
* - success: boolean
|
|
333
|
+
* - message: string
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* POST /api/sessions/4b198fdf-b80d-4bbc-806f-2900282cdc56/refresh
|
|
337
|
+
*/
|
|
338
|
+
router.post('/:id/refresh', async (req, res) => {
|
|
339
|
+
try {
|
|
340
|
+
const sessionId = req.params.id;
|
|
341
|
+
if (!sessionId) {
|
|
342
|
+
res.status(400).json({ error: 'Session ID is required' });
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
// Clear cache
|
|
346
|
+
timelineCache.delete(sessionId);
|
|
347
|
+
// Rebuild timeline
|
|
348
|
+
const timeline = await getOrBuildTimeline(sessionId);
|
|
349
|
+
if (!timeline) {
|
|
350
|
+
res.status(404).json({ error: 'Session not found' });
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
res.json({
|
|
354
|
+
success: true,
|
|
355
|
+
message: 'Timeline refreshed successfully',
|
|
356
|
+
totalFrames: timeline.totalFrames,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
console.error('Error refreshing session:', error);
|
|
361
|
+
res.status(500).json({
|
|
362
|
+
error: 'Failed to refresh session',
|
|
363
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
/**
|
|
368
|
+
* Helper: Get or build timeline for a session
|
|
369
|
+
* Uses cache if available, otherwise parses transcript file
|
|
370
|
+
* Automatically detects agent type from file path
|
|
371
|
+
*/
|
|
372
|
+
async function getOrBuildTimeline(sessionId) {
|
|
373
|
+
// Check cache first
|
|
374
|
+
if (timelineCache.has(sessionId)) {
|
|
375
|
+
return timelineCache.get(sessionId);
|
|
376
|
+
}
|
|
377
|
+
// Find session file
|
|
378
|
+
const indexer = (0, session_indexer_1.getSessionIndexer)();
|
|
379
|
+
const filePath = await indexer.findSessionFile(sessionId);
|
|
380
|
+
if (!filePath) {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
// Detect agent type from file path
|
|
384
|
+
const agentType = (0, agent_detector_1.detectAgentFromPath)(filePath);
|
|
385
|
+
// Parse transcript and build timeline using ParserFactory
|
|
386
|
+
const transcript = await parser_factory_1.ParserFactory.parseFile(filePath);
|
|
387
|
+
const timeline = await parser_factory_1.ParserFactory.buildTimeline(transcript, agentType);
|
|
388
|
+
// Cache for future requests
|
|
389
|
+
timelineCache.set(sessionId, timeline);
|
|
390
|
+
return timeline;
|
|
391
|
+
}
|
|
392
|
+
exports.default = router;
|
|
393
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Application } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Create and configure Express application
|
|
4
|
+
*
|
|
5
|
+
* Sets up the Express server with:
|
|
6
|
+
* - CORS middleware (allows cross-origin requests from frontend)
|
|
7
|
+
* - JSON body parsing
|
|
8
|
+
* - Request logging
|
|
9
|
+
* - API routes
|
|
10
|
+
* - Static file serving (for production frontend)
|
|
11
|
+
* - SPA fallback (serves index.html for non-API routes)
|
|
12
|
+
* - Global error handler
|
|
13
|
+
*
|
|
14
|
+
* @returns {Application} Configured Express application
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* import { createServer } from './server';
|
|
18
|
+
*
|
|
19
|
+
* const app = createServer();
|
|
20
|
+
* app.listen(3001, () => {
|
|
21
|
+
* console.log('Server running on http://localhost:3001');
|
|
22
|
+
* });
|
|
23
|
+
*/
|
|
24
|
+
export declare function createServer(): Application;
|
|
25
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,WAAW,EAAmC,MAAM,SAAS,CAAC;AAOhF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,IAAI,WAAW,CAkF1C"}
|
|
@@ -0,0 +1,110 @@
|
|
|
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.createServer = createServer;
|
|
7
|
+
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const cors_1 = __importDefault(require("cors"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const sessions_1 = __importDefault(require("./routes/sessions"));
|
|
11
|
+
const commentary_1 = __importDefault(require("./routes/commentary"));
|
|
12
|
+
const import_1 = __importDefault(require("./routes/import"));
|
|
13
|
+
/**
|
|
14
|
+
* Create and configure Express application
|
|
15
|
+
*
|
|
16
|
+
* Sets up the Express server with:
|
|
17
|
+
* - CORS middleware (allows cross-origin requests from frontend)
|
|
18
|
+
* - JSON body parsing
|
|
19
|
+
* - Request logging
|
|
20
|
+
* - API routes
|
|
21
|
+
* - Static file serving (for production frontend)
|
|
22
|
+
* - SPA fallback (serves index.html for non-API routes)
|
|
23
|
+
* - Global error handler
|
|
24
|
+
*
|
|
25
|
+
* @returns {Application} Configured Express application
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* import { createServer } from './server';
|
|
29
|
+
*
|
|
30
|
+
* const app = createServer();
|
|
31
|
+
* app.listen(3001, () => {
|
|
32
|
+
* console.log('Server running on http://localhost:3001');
|
|
33
|
+
* });
|
|
34
|
+
*/
|
|
35
|
+
function createServer() {
|
|
36
|
+
const app = (0, express_1.default)();
|
|
37
|
+
// Middleware
|
|
38
|
+
app.use((0, cors_1.default)());
|
|
39
|
+
app.use(express_1.default.json());
|
|
40
|
+
// Request logging
|
|
41
|
+
app.use((req, _res, next) => {
|
|
42
|
+
console.log(`${new Date().toISOString()} ${req.method} ${req.url}`);
|
|
43
|
+
next();
|
|
44
|
+
});
|
|
45
|
+
// API Routes
|
|
46
|
+
app.use('/api/sessions', sessions_1.default);
|
|
47
|
+
app.use('/api/sessions', commentary_1.default);
|
|
48
|
+
app.use('/api/import', import_1.default);
|
|
49
|
+
// Mount sessions router at /api for /api/agents endpoint
|
|
50
|
+
app.use('/api', sessions_1.default);
|
|
51
|
+
// Health check with DB status
|
|
52
|
+
app.get('/api/health', (_req, res) => {
|
|
53
|
+
try {
|
|
54
|
+
const { getDbInstance } = require('./db/connection');
|
|
55
|
+
const { getTranscriptDbInstance } = require('./db/transcript-connection');
|
|
56
|
+
const db = getDbInstance();
|
|
57
|
+
const transcriptDb = getTranscriptDbInstance();
|
|
58
|
+
// Test queries to ensure actual connectivity
|
|
59
|
+
db.prepare('SELECT 1').get();
|
|
60
|
+
transcriptDb.prepare('SELECT 1').get();
|
|
61
|
+
res.json({
|
|
62
|
+
status: 'ok',
|
|
63
|
+
timestamp: new Date().toISOString(),
|
|
64
|
+
databases: {
|
|
65
|
+
claude_mem: 'connected',
|
|
66
|
+
transcripts: 'connected'
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
console.error('Health check failed:', err);
|
|
72
|
+
res.status(500).json({
|
|
73
|
+
status: 'error',
|
|
74
|
+
message: err instanceof Error ? err.message : 'Database connection failed',
|
|
75
|
+
stack: err instanceof Error ? err.stack : undefined
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
// Serve built frontend (for production)
|
|
80
|
+
const publicDir = path_1.default.join(__dirname, '..', 'public');
|
|
81
|
+
app.use(express_1.default.static(publicDir));
|
|
82
|
+
// SPA fallback - serve index.html for all non-API routes
|
|
83
|
+
// Note: This will only work when frontend is built and deployed
|
|
84
|
+
app.use((req, res, next) => {
|
|
85
|
+
if (!req.url.startsWith('/api')) {
|
|
86
|
+
const indexPath = path_1.default.join(publicDir, 'index.html');
|
|
87
|
+
// Only serve index.html if it exists (frontend is built)
|
|
88
|
+
if (require('fs').existsSync(indexPath)) {
|
|
89
|
+
res.sendFile(indexPath);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
next();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
next();
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
// Error handler
|
|
100
|
+
app.use((err, _req, res, _next) => {
|
|
101
|
+
console.error('Unhandled error:', err);
|
|
102
|
+
res.status(500).json({
|
|
103
|
+
error: 'Internal server error',
|
|
104
|
+
message: err.message,
|
|
105
|
+
stack: err.stack
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
return app;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example usage of the transcript-importer service
|
|
3
|
+
*
|
|
4
|
+
* This demonstrates how to use both single-file imports
|
|
5
|
+
* and bulk imports with progress tracking.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Example 1: Import a single transcript file
|
|
9
|
+
*/
|
|
10
|
+
declare function _exampleSingleImport(): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Example 2: Bulk import all transcripts with progress tracking
|
|
13
|
+
*/
|
|
14
|
+
declare function _exampleBulkImport(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Example 3: Check import progress
|
|
17
|
+
*/
|
|
18
|
+
declare function _exampleCheckProgress(): void;
|
|
19
|
+
export { _exampleSingleImport as exampleSingleImport, _exampleBulkImport as exampleBulkImport, _exampleCheckProgress as exampleCheckProgress, };
|
|
20
|
+
//# sourceMappingURL=example-import.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example-import.d.ts","sourceRoot":"","sources":["../../src/services/example-import.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;GAEG;AACH,iBAAe,oBAAoB,kBAalC;AAED;;GAEG;AACH,iBAAe,kBAAkB,kBA8BhC;AAED;;GAEG;AACH,iBAAS,qBAAqB,SAS7B;AA0BD,OAAO,EACL,oBAAoB,IAAI,mBAAmB,EAC3C,kBAAkB,IAAI,iBAAiB,EACvC,qBAAqB,IAAI,oBAAoB,GAC9C,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Example usage of the transcript-importer service
|
|
4
|
+
*
|
|
5
|
+
* This demonstrates how to use both single-file imports
|
|
6
|
+
* and bulk imports with progress tracking.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.exampleSingleImport = _exampleSingleImport;
|
|
10
|
+
exports.exampleBulkImport = _exampleBulkImport;
|
|
11
|
+
exports.exampleCheckProgress = _exampleCheckProgress;
|
|
12
|
+
const transcript_importer_1 = require("./transcript-importer");
|
|
13
|
+
const transcript_queries_1 = require("../db/transcript-queries");
|
|
14
|
+
/**
|
|
15
|
+
* Example 1: Import a single transcript file
|
|
16
|
+
*/
|
|
17
|
+
async function _exampleSingleImport() {
|
|
18
|
+
console.log('=== Example 1: Single Import ===\n');
|
|
19
|
+
// Initialize database schema first
|
|
20
|
+
(0, transcript_queries_1.initializeTranscriptSchema)();
|
|
21
|
+
try {
|
|
22
|
+
const filePath = '/Users/fpirzada/.claude/projects/my-project/session-123.jsonl';
|
|
23
|
+
await (0, transcript_importer_1.importTranscript)(filePath);
|
|
24
|
+
console.log('✓ Successfully imported session');
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error('✗ Import failed:', error);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Example 2: Bulk import all transcripts with progress tracking
|
|
32
|
+
*/
|
|
33
|
+
async function _exampleBulkImport() {
|
|
34
|
+
console.log('\n=== Example 2: Bulk Import ===\n');
|
|
35
|
+
const summary = await (0, transcript_importer_1.bulkImportTranscripts)({
|
|
36
|
+
sourcePath: '/Users/fpirzada/.claude/projects',
|
|
37
|
+
parallel: 10,
|
|
38
|
+
skipExisting: true,
|
|
39
|
+
onProgress: (completed, total) => {
|
|
40
|
+
const percent = Math.round((completed / total) * 100);
|
|
41
|
+
process.stdout.write(`\rProgress: ${completed}/${total} (${percent}%)`);
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
console.log('\n\nImport Summary:');
|
|
45
|
+
console.log(` Total files: ${summary.totalFiles}`);
|
|
46
|
+
console.log(` Successful: ${summary.successful}`);
|
|
47
|
+
console.log(` Failed: ${summary.failed}`);
|
|
48
|
+
console.log(` Skipped: ${summary.skipped}`);
|
|
49
|
+
console.log(` Duration: ${(summary.duration / 1000).toFixed(2)}s`);
|
|
50
|
+
// Show failed imports
|
|
51
|
+
if (summary.failed > 0) {
|
|
52
|
+
console.log('\nFailed imports:');
|
|
53
|
+
summary.results
|
|
54
|
+
.filter((r) => !r.success)
|
|
55
|
+
.forEach((r) => {
|
|
56
|
+
console.log(` - ${r.filePath}`);
|
|
57
|
+
console.log(` Error: ${r.error}`);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Example 3: Check import progress
|
|
63
|
+
*/
|
|
64
|
+
function _exampleCheckProgress() {
|
|
65
|
+
console.log('\n=== Example 3: Check Progress ===\n');
|
|
66
|
+
const stats = (0, transcript_importer_1.getImportProgress)();
|
|
67
|
+
console.log('Import Statistics:');
|
|
68
|
+
console.log(` Total: ${stats.total}`);
|
|
69
|
+
console.log(` Pending: ${stats.pending}`);
|
|
70
|
+
console.log(` Completed: ${stats.completed}`);
|
|
71
|
+
console.log(` Failed: ${stats.failed}`);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Run all examples
|
|
75
|
+
*/
|
|
76
|
+
async function main() {
|
|
77
|
+
try {
|
|
78
|
+
// Uncomment the example you want to run:
|
|
79
|
+
// await exampleSingleImport();
|
|
80
|
+
// await exampleBulkImport();
|
|
81
|
+
// exampleCheckProgress();
|
|
82
|
+
console.log('\nNote: Uncomment the examples in main() to run them.');
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.error('Error:', error);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Run if executed directly
|
|
90
|
+
if (require.main === module) {
|
|
91
|
+
main();
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=example-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example-import.js","sourceRoot":"","sources":["../../src/services/example-import.ts"],"names":[],"mappings":"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"}
|