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.
Files changed (108) hide show
  1. package/README.md +238 -0
  2. package/backend/dist/db/connection.d.ts +47 -0
  3. package/backend/dist/db/connection.d.ts.map +1 -0
  4. package/backend/dist/db/connection.js +88 -0
  5. package/backend/dist/db/connection.js.map +1 -0
  6. package/backend/dist/db/queries.d.ts +172 -0
  7. package/backend/dist/db/queries.d.ts.map +1 -0
  8. package/backend/dist/db/queries.js +436 -0
  9. package/backend/dist/db/queries.js.map +1 -0
  10. package/backend/dist/db/schema.d.ts +100 -0
  11. package/backend/dist/db/schema.d.ts.map +1 -0
  12. package/backend/dist/db/schema.js +6 -0
  13. package/backend/dist/db/schema.js.map +1 -0
  14. package/backend/dist/db/transcript-connection.d.ts +57 -0
  15. package/backend/dist/db/transcript-connection.d.ts.map +1 -0
  16. package/backend/dist/db/transcript-connection.js +112 -0
  17. package/backend/dist/db/transcript-connection.js.map +1 -0
  18. package/backend/dist/db/transcript-queries.d.ts +152 -0
  19. package/backend/dist/db/transcript-queries.d.ts.map +1 -0
  20. package/backend/dist/db/transcript-queries.js +706 -0
  21. package/backend/dist/db/transcript-queries.js.map +1 -0
  22. package/backend/dist/db/transcript-schema.d.ts +143 -0
  23. package/backend/dist/db/transcript-schema.d.ts.map +1 -0
  24. package/backend/dist/db/transcript-schema.js +10 -0
  25. package/backend/dist/db/transcript-schema.js.map +1 -0
  26. package/backend/dist/index.d.ts +2 -0
  27. package/backend/dist/index.d.ts.map +1 -0
  28. package/backend/dist/index.js +96 -0
  29. package/backend/dist/index.js.map +1 -0
  30. package/backend/dist/parser/agent-detector.d.ts +76 -0
  31. package/backend/dist/parser/agent-detector.d.ts.map +1 -0
  32. package/backend/dist/parser/agent-detector.js +281 -0
  33. package/backend/dist/parser/agent-detector.js.map +1 -0
  34. package/backend/dist/parser/base-parser.d.ts +123 -0
  35. package/backend/dist/parser/base-parser.d.ts.map +1 -0
  36. package/backend/dist/parser/base-parser.js +364 -0
  37. package/backend/dist/parser/base-parser.js.map +1 -0
  38. package/backend/dist/parser/claude-parser.d.ts +78 -0
  39. package/backend/dist/parser/claude-parser.d.ts.map +1 -0
  40. package/backend/dist/parser/claude-parser.js +247 -0
  41. package/backend/dist/parser/claude-parser.js.map +1 -0
  42. package/backend/dist/parser/codex-parser.d.ts +128 -0
  43. package/backend/dist/parser/codex-parser.d.ts.map +1 -0
  44. package/backend/dist/parser/codex-parser.js +371 -0
  45. package/backend/dist/parser/codex-parser.js.map +1 -0
  46. package/backend/dist/parser/gemini-parser.d.ts +107 -0
  47. package/backend/dist/parser/gemini-parser.d.ts.map +1 -0
  48. package/backend/dist/parser/gemini-parser.js +360 -0
  49. package/backend/dist/parser/gemini-parser.js.map +1 -0
  50. package/backend/dist/parser/parser-factory.d.ts +83 -0
  51. package/backend/dist/parser/parser-factory.d.ts.map +1 -0
  52. package/backend/dist/parser/parser-factory.js +163 -0
  53. package/backend/dist/parser/parser-factory.js.map +1 -0
  54. package/backend/dist/parser/session-indexer.d.ts +79 -0
  55. package/backend/dist/parser/session-indexer.d.ts.map +1 -0
  56. package/backend/dist/parser/session-indexer.js +558 -0
  57. package/backend/dist/parser/session-indexer.js.map +1 -0
  58. package/backend/dist/parser/timeline-builder.d.ts +7 -0
  59. package/backend/dist/parser/timeline-builder.d.ts.map +1 -0
  60. package/backend/dist/parser/timeline-builder.js +334 -0
  61. package/backend/dist/parser/timeline-builder.js.map +1 -0
  62. package/backend/dist/parser/transcript-parser.d.ts +25 -0
  63. package/backend/dist/parser/transcript-parser.d.ts.map +1 -0
  64. package/backend/dist/parser/transcript-parser.js +137 -0
  65. package/backend/dist/parser/transcript-parser.js.map +1 -0
  66. package/backend/dist/routes/commentary.d.ts +33 -0
  67. package/backend/dist/routes/commentary.d.ts.map +1 -0
  68. package/backend/dist/routes/commentary.js +153 -0
  69. package/backend/dist/routes/commentary.js.map +1 -0
  70. package/backend/dist/routes/import.d.ts +3 -0
  71. package/backend/dist/routes/import.d.ts.map +1 -0
  72. package/backend/dist/routes/import.js +220 -0
  73. package/backend/dist/routes/import.js.map +1 -0
  74. package/backend/dist/routes/sessions.d.ts +3 -0
  75. package/backend/dist/routes/sessions.d.ts.map +1 -0
  76. package/backend/dist/routes/sessions.js +393 -0
  77. package/backend/dist/routes/sessions.js.map +1 -0
  78. package/backend/dist/server.d.ts +25 -0
  79. package/backend/dist/server.d.ts.map +1 -0
  80. package/backend/dist/server.js +110 -0
  81. package/backend/dist/server.js.map +1 -0
  82. package/backend/dist/services/example-import.d.ts +20 -0
  83. package/backend/dist/services/example-import.d.ts.map +1 -0
  84. package/backend/dist/services/example-import.js +93 -0
  85. package/backend/dist/services/example-import.js.map +1 -0
  86. package/backend/dist/services/file-watcher.d.ts +22 -0
  87. package/backend/dist/services/file-watcher.d.ts.map +1 -0
  88. package/backend/dist/services/file-watcher.js +141 -0
  89. package/backend/dist/services/file-watcher.js.map +1 -0
  90. package/backend/dist/services/import-cli.d.ts +11 -0
  91. package/backend/dist/services/import-cli.d.ts.map +1 -0
  92. package/backend/dist/services/import-cli.js +171 -0
  93. package/backend/dist/services/import-cli.js.map +1 -0
  94. package/backend/dist/services/transcript-importer.d.ts +98 -0
  95. package/backend/dist/services/transcript-importer.d.ts.map +1 -0
  96. package/backend/dist/services/transcript-importer.js +342 -0
  97. package/backend/dist/services/transcript-importer.js.map +1 -0
  98. package/backend/dist/types/transcript.d.ts +174 -0
  99. package/backend/dist/types/transcript.d.ts.map +1 -0
  100. package/backend/dist/types/transcript.js +8 -0
  101. package/backend/dist/types/transcript.js.map +1 -0
  102. package/backend/package.json +40 -0
  103. package/backend/public/.gitkeep +0 -0
  104. package/backend/public/assets/index-D8IP1zNL.css +1 -0
  105. package/backend/public/assets/index-GtkMiMqE.js +69 -0
  106. package/backend/public/index.html +14 -0
  107. package/bin/recall.js +43 -0
  108. package/package.json +54 -0
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.queryClaudeMemDirect = queryClaudeMemDirect;
4
+ const express_1 = require("express");
5
+ const child_process_1 = require("child_process");
6
+ const util_1 = require("util");
7
+ const router = (0, express_1.Router)();
8
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
9
+ /**
10
+ * GET /api/sessions/:id/commentary
11
+ * Get claude-mem observations for a session mapped to timeline
12
+ *
13
+ * URL Parameters:
14
+ * - id: Session UUID
15
+ *
16
+ * Response:
17
+ * - commentary: Array of CommentaryBubble objects
18
+ * - total: Total number of observations
19
+ * - sessionId: The session ID
20
+ *
21
+ * Status Codes:
22
+ * - 200: Success
23
+ * - 500: Internal error
24
+ *
25
+ * @example
26
+ * GET /api/sessions/4b198fdf-b80d-4bbc-806f-2900282cdc56/commentary
27
+ */
28
+ router.get('/:id/commentary', async (req, res) => {
29
+ try {
30
+ const sessionId = req.params.id;
31
+ if (!sessionId) {
32
+ res.status(400).json({ error: 'Session ID is required' });
33
+ return;
34
+ }
35
+ // Query claude-mem for observations matching this session ID
36
+ const observations = await queryClaudeMemObservations(sessionId);
37
+ // Map observations to commentary bubbles
38
+ const commentary = observations.map((obs) => ({
39
+ id: obs.id,
40
+ timestamp: obs.timestamp,
41
+ type: obs.type,
42
+ title: obs.title,
43
+ content: obs.content,
44
+ metadata: obs.metadata,
45
+ }));
46
+ res.json({
47
+ commentary,
48
+ total: commentary.length,
49
+ sessionId,
50
+ });
51
+ }
52
+ catch (error) {
53
+ console.error('Error fetching commentary:', error);
54
+ res.status(500).json({
55
+ error: 'Failed to fetch commentary',
56
+ message: error instanceof Error ? error.message : 'Unknown error',
57
+ });
58
+ }
59
+ });
60
+ /**
61
+ * Query claude-mem MCP server for observations
62
+ * Uses the claude CLI with MCP integration
63
+ */
64
+ async function queryClaudeMemObservations(sessionId) {
65
+ try {
66
+ // Use the claude-mem MCP search to find observations for this session
67
+ // The search command queries the claude-mem sqlite database
68
+ const query = JSON.stringify({
69
+ session_id: sessionId,
70
+ limit: 100,
71
+ });
72
+ // Execute search via MCP server
73
+ // Note: This assumes claude-mem MCP server is running and configured
74
+ const command = `claude mcp call claude-mem search '${query}'`;
75
+ const { stdout, stderr } = await execAsync(command);
76
+ if (stderr) {
77
+ console.warn('claude-mem search warning:', stderr);
78
+ }
79
+ // Parse the MCP response
80
+ const response = JSON.parse(stdout);
81
+ // Extract observations from the response
82
+ // The exact format depends on claude-mem's response structure
83
+ const observations = [];
84
+ if (response && response.results) {
85
+ for (const result of response.results) {
86
+ observations.push({
87
+ id: result.id,
88
+ timestamp: result.timestamp || Date.now(),
89
+ session_id: sessionId,
90
+ type: result.type || 'observation',
91
+ title: result.title || result.summary || 'Observation',
92
+ content: result.content || result.text || '',
93
+ metadata: result.metadata,
94
+ });
95
+ }
96
+ }
97
+ return observations;
98
+ }
99
+ catch (error) {
100
+ console.error('Error querying claude-mem:', error);
101
+ // Return empty array if claude-mem is not available
102
+ // This allows the app to work without claude-mem installed
103
+ return [];
104
+ }
105
+ }
106
+ /**
107
+ * Alternative implementation using direct sqlite access
108
+ * This is a fallback if MCP server is not available
109
+ * Exported for potential future use or testing
110
+ */
111
+ async function queryClaudeMemDirect(sessionId) {
112
+ try {
113
+ // Import better-sqlite3
114
+ const Database = require('better-sqlite3');
115
+ const os = require('os');
116
+ const path = require('path');
117
+ // claude-mem stores data in ~/.claude-mem/memory.db
118
+ const dbPath = path.join(os.homedir(), '.claude-mem', 'memory.db');
119
+ const db = new Database(dbPath, { readonly: true });
120
+ // Query observations for this session
121
+ const stmt = db.prepare(`
122
+ SELECT
123
+ id,
124
+ timestamp,
125
+ session_id,
126
+ type,
127
+ title,
128
+ content,
129
+ metadata
130
+ FROM observations
131
+ WHERE session_id = ?
132
+ ORDER BY timestamp ASC
133
+ `);
134
+ const rows = stmt.all(sessionId);
135
+ db.close();
136
+ // Map to MemObservation format
137
+ return rows.map((row) => ({
138
+ id: row.id,
139
+ timestamp: row.timestamp,
140
+ session_id: row.session_id,
141
+ type: row.type || 'observation',
142
+ title: row.title || 'Observation',
143
+ content: row.content || '',
144
+ metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
145
+ }));
146
+ }
147
+ catch (error) {
148
+ console.error('Error querying claude-mem database directly:', error);
149
+ return [];
150
+ }
151
+ }
152
+ exports.default = router;
153
+ //# sourceMappingURL=commentary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commentary.js","sourceRoot":"","sources":["../../src/routes/commentary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
3
+ //# sourceMappingURL=import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/routes/import.ts"],"names":[],"mappings":"AASA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA6OxB,eAAe,MAAM,CAAC"}
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const express_1 = require("express");
4
+ const transcript_importer_1 = require("../services/transcript-importer");
5
+ const transcript_queries_1 = require("../db/transcript-queries");
6
+ const agent_detector_1 = require("../parser/agent-detector");
7
+ const router = (0, express_1.Router)();
8
+ /**
9
+ * Track current import job state
10
+ */
11
+ let currentImportJob = {
12
+ status: 'idle',
13
+ totalSessions: 0,
14
+ completedSessions: 0,
15
+ failedSessions: 0,
16
+ };
17
+ /**
18
+ * POST /api/import/start
19
+ * Start a bulk import of transcript files
20
+ *
21
+ * Request Body:
22
+ * - sourcePath (string, optional): Path to scan for .jsonl files (default: ~/.claude/projects/)
23
+ * - parallel (number, optional): Number of parallel workers (default: 10)
24
+ * - skipExisting (boolean, optional): Skip already imported sessions (default: true)
25
+ *
26
+ * Response:
27
+ * - success: boolean
28
+ * - message: string
29
+ * - jobId: string (for tracking)
30
+ *
31
+ * Status Codes:
32
+ * - 202: Import job started
33
+ * - 400: Invalid request
34
+ * - 409: Import already in progress
35
+ * - 500: Internal error
36
+ *
37
+ * @example
38
+ * POST /api/import/start
39
+ * {
40
+ * "parallel": 10,
41
+ * "skipExisting": true
42
+ * }
43
+ */
44
+ router.post('/start', async (req, res) => {
45
+ try {
46
+ // Check if import is already running
47
+ if (currentImportJob.status === 'importing') {
48
+ res.status(409).json({
49
+ success: false,
50
+ error: 'Import already in progress',
51
+ currentJob: currentImportJob,
52
+ });
53
+ return;
54
+ }
55
+ // Get config from request body
56
+ const { sourcePath, parallel = 10, skipExisting = true, } = req.body || {};
57
+ // Reset job state
58
+ currentImportJob = {
59
+ status: 'importing',
60
+ totalSessions: 0,
61
+ completedSessions: 0,
62
+ failedSessions: 0,
63
+ startedAt: new Date().toISOString(),
64
+ };
65
+ // Start import in background (don't await)
66
+ (0, transcript_importer_1.bulkImportTranscripts)({
67
+ sourcePath,
68
+ parallel,
69
+ skipExisting,
70
+ onProgress: (completed, total) => {
71
+ currentImportJob.totalSessions = total;
72
+ currentImportJob.completedSessions = completed;
73
+ },
74
+ })
75
+ .then((summary) => {
76
+ currentImportJob.status = 'completed';
77
+ currentImportJob.completedAt = new Date().toISOString();
78
+ currentImportJob.totalSessions = summary.totalFiles;
79
+ currentImportJob.completedSessions = summary.successful;
80
+ currentImportJob.failedSessions = summary.failed;
81
+ console.log(`[Import] Completed: ${summary.successful}/${summary.totalFiles} sessions`);
82
+ })
83
+ .catch((error) => {
84
+ currentImportJob.status = 'failed';
85
+ currentImportJob.completedAt = new Date().toISOString();
86
+ currentImportJob.errorMessage = error instanceof Error ? error.message : 'Unknown error';
87
+ console.error('[Import] Failed:', error);
88
+ });
89
+ // Return immediately
90
+ res.status(202).json({
91
+ success: true,
92
+ message: 'Import job started',
93
+ job: currentImportJob,
94
+ });
95
+ }
96
+ catch (error) {
97
+ console.error('Error starting import:', error);
98
+ res.status(500).json({
99
+ success: false,
100
+ error: 'Failed to start import',
101
+ message: error instanceof Error ? error.message : 'Unknown error',
102
+ });
103
+ }
104
+ });
105
+ /**
106
+ * GET /api/import/status
107
+ * Get current import job status
108
+ *
109
+ * Response:
110
+ * - status: 'idle' | 'importing' | 'completed' | 'failed'
111
+ * - totalSessions: number
112
+ * - completedSessions: number
113
+ * - failedSessions: number
114
+ * - currentSession?: string
115
+ * - startedAt?: string
116
+ * - completedAt?: string
117
+ * - errorMessage?: string
118
+ *
119
+ * Status Codes:
120
+ * - 200: Success
121
+ *
122
+ * @example
123
+ * GET /api/import/status
124
+ */
125
+ router.get('/status', (_req, res) => {
126
+ res.json(currentImportJob);
127
+ });
128
+ /**
129
+ * GET /api/import/stats
130
+ * Get database import statistics
131
+ *
132
+ * Response:
133
+ * - total: Total sessions in parsing_status table
134
+ * - pending: Number of pending imports
135
+ * - completed: Number of completed imports
136
+ * - failed: Number of failed imports
137
+ *
138
+ * Status Codes:
139
+ * - 200: Success
140
+ * - 500: Internal error
141
+ *
142
+ * @example
143
+ * GET /api/import/stats
144
+ */
145
+ router.get('/stats', (_req, res) => {
146
+ try {
147
+ const stats = (0, transcript_queries_1.getImportStats)();
148
+ res.json(stats);
149
+ }
150
+ catch (error) {
151
+ console.error('Error fetching import stats:', error);
152
+ res.status(500).json({
153
+ error: 'Failed to fetch import stats',
154
+ message: error instanceof Error ? error.message : 'Unknown error',
155
+ });
156
+ }
157
+ });
158
+ /**
159
+ * POST /api/import/single
160
+ * Import a single transcript file
161
+ *
162
+ * Request Body:
163
+ * - filePath (string, required): Path to .jsonl file
164
+ * - agent (string, optional): Agent type ('claude', 'codex', 'gemini', 'unknown')
165
+ * If not specified, auto-detected from file path
166
+ *
167
+ * Response:
168
+ * - success: boolean
169
+ * - message: string
170
+ * - agent: string (detected or specified agent type)
171
+ *
172
+ * Status Codes:
173
+ * - 200: Import successful
174
+ * - 400: Invalid request
175
+ * - 500: Import failed
176
+ *
177
+ * @example
178
+ * POST /api/import/single
179
+ * {
180
+ * "filePath": "/Users/fpirzada/.claude/projects/my-project/session.jsonl"
181
+ * }
182
+ *
183
+ * @example
184
+ * POST /api/import/single
185
+ * {
186
+ * "filePath": "/custom/path/session.jsonl",
187
+ * "agent": "codex"
188
+ * }
189
+ */
190
+ router.post('/single', async (req, res) => {
191
+ try {
192
+ const { filePath, agent: specifiedAgent } = req.body || {};
193
+ if (!filePath || typeof filePath !== 'string') {
194
+ res.status(400).json({
195
+ success: false,
196
+ error: 'Missing required field: filePath',
197
+ });
198
+ return;
199
+ }
200
+ // Determine agent type: use specified agent or auto-detect from path
201
+ const agent = specifiedAgent || (0, agent_detector_1.detectAgentFromPath)(filePath);
202
+ // Import the file
203
+ await (0, transcript_importer_1.importTranscript)(filePath, agent);
204
+ res.json({
205
+ success: true,
206
+ message: 'Transcript imported successfully',
207
+ agent,
208
+ });
209
+ }
210
+ catch (error) {
211
+ console.error('Error importing transcript:', error);
212
+ res.status(500).json({
213
+ success: false,
214
+ error: 'Failed to import transcript',
215
+ message: error instanceof Error ? error.message : 'Unknown error',
216
+ });
217
+ }
218
+ });
219
+ exports.default = router;
220
+ //# sourceMappingURL=import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/routes/import.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
3
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAUA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAwaxB,eAAe,MAAM,CAAC"}