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,22 @@
1
+ /**
2
+ * Starts watching the Claude projects directory for new .jsonl files
3
+ *
4
+ * When a .jsonl file is added or modified, it will be automatically
5
+ * imported after a 2-second debounce period.
6
+ *
7
+ * @throws Error if watcher is already running
8
+ */
9
+ export declare function startWatcher(): void;
10
+ /**
11
+ * Stops the file watcher and cleans up resources
12
+ *
13
+ * Clears all pending debounce timers and closes the watcher instance.
14
+ */
15
+ export declare function stopWatcher(): Promise<void>;
16
+ /**
17
+ * Returns whether the watcher is currently running
18
+ *
19
+ * @returns True if watcher is active, false otherwise
20
+ */
21
+ export declare function isWatcherRunning(): boolean;
22
+ //# sourceMappingURL=file-watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-watcher.d.ts","sourceRoot":"","sources":["../../src/services/file-watcher.ts"],"names":[],"mappings":"AAsDA;;;;;;;GAOG;AACH,wBAAgB,YAAY,IAAI,IAAI,CA2CnC;AAED;;;;GAIG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAwBjD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C"}
@@ -0,0 +1,141 @@
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.startWatcher = startWatcher;
7
+ exports.stopWatcher = stopWatcher;
8
+ exports.isWatcherRunning = isWatcherRunning;
9
+ const chokidar_1 = __importDefault(require("chokidar"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const os_1 = __importDefault(require("os"));
12
+ const transcript_importer_1 = require("./transcript-importer");
13
+ /**
14
+ * File watcher instance
15
+ */
16
+ let watcher = null;
17
+ /**
18
+ * Debounce timers for file changes
19
+ * Maps file path to timeout ID
20
+ */
21
+ const debounceTimers = new Map();
22
+ /**
23
+ * Debounce delay in milliseconds
24
+ */
25
+ const DEBOUNCE_DELAY = 2000;
26
+ /**
27
+ * Directory to watch for Claude project files
28
+ */
29
+ const WATCH_DIR = path_1.default.join(os_1.default.homedir(), '.claude', 'projects');
30
+ /**
31
+ * Handles a file change event with debouncing
32
+ *
33
+ * @param filePath - Absolute path to the changed file
34
+ */
35
+ function handleFileChange(filePath) {
36
+ // Clear existing timer for this file
37
+ const existingTimer = debounceTimers.get(filePath);
38
+ if (existingTimer) {
39
+ clearTimeout(existingTimer);
40
+ }
41
+ // Set new timer
42
+ const timer = setTimeout(async () => {
43
+ try {
44
+ console.log(`[FileWatcher] Importing transcript from: ${filePath}`);
45
+ await (0, transcript_importer_1.importTranscript)(filePath);
46
+ console.log(`[FileWatcher] Successfully imported: ${filePath}`);
47
+ debounceTimers.delete(filePath);
48
+ }
49
+ catch (error) {
50
+ console.error(`[FileWatcher] Error importing ${filePath}:`, error);
51
+ debounceTimers.delete(filePath);
52
+ }
53
+ }, DEBOUNCE_DELAY);
54
+ debounceTimers.set(filePath, timer);
55
+ }
56
+ /**
57
+ * Starts watching the Claude projects directory for new .jsonl files
58
+ *
59
+ * When a .jsonl file is added or modified, it will be automatically
60
+ * imported after a 2-second debounce period.
61
+ *
62
+ * @throws Error if watcher is already running
63
+ */
64
+ function startWatcher() {
65
+ if (watcher) {
66
+ console.warn('[FileWatcher] Watcher is already running');
67
+ return;
68
+ }
69
+ console.log(`[FileWatcher] Starting file watcher on: ${WATCH_DIR}`);
70
+ try {
71
+ watcher = chokidar_1.default.watch('*.jsonl', {
72
+ cwd: WATCH_DIR,
73
+ persistent: true,
74
+ ignoreInitial: false,
75
+ awaitWriteFinish: {
76
+ stabilityThreshold: 500,
77
+ pollInterval: 100
78
+ },
79
+ depth: 0, // Only watch the projects directory, not subdirectories
80
+ });
81
+ watcher
82
+ .on('add', (relativePath) => {
83
+ const absolutePath = path_1.default.join(WATCH_DIR, relativePath);
84
+ console.log(`[FileWatcher] New file detected: ${relativePath}`);
85
+ handleFileChange(absolutePath);
86
+ })
87
+ .on('change', (relativePath) => {
88
+ const absolutePath = path_1.default.join(WATCH_DIR, relativePath);
89
+ console.log(`[FileWatcher] File changed: ${relativePath}`);
90
+ handleFileChange(absolutePath);
91
+ })
92
+ .on('error', (error) => {
93
+ console.error('[FileWatcher] Watcher error:', error);
94
+ })
95
+ .on('ready', () => {
96
+ console.log('[FileWatcher] Initial scan complete. Ready for changes.');
97
+ });
98
+ }
99
+ catch (error) {
100
+ console.error('[FileWatcher] Failed to start watcher:', error);
101
+ watcher = null;
102
+ throw error;
103
+ }
104
+ }
105
+ /**
106
+ * Stops the file watcher and cleans up resources
107
+ *
108
+ * Clears all pending debounce timers and closes the watcher instance.
109
+ */
110
+ async function stopWatcher() {
111
+ if (!watcher) {
112
+ console.warn('[FileWatcher] No watcher running');
113
+ return;
114
+ }
115
+ console.log('[FileWatcher] Stopping file watcher...');
116
+ // Clear all debounce timers
117
+ for (const timer of debounceTimers.values()) {
118
+ clearTimeout(timer);
119
+ }
120
+ debounceTimers.clear();
121
+ // Close the watcher
122
+ try {
123
+ await watcher.close();
124
+ watcher = null;
125
+ console.log('[FileWatcher] File watcher stopped');
126
+ }
127
+ catch (error) {
128
+ console.error('[FileWatcher] Error stopping watcher:', error);
129
+ watcher = null;
130
+ throw error;
131
+ }
132
+ }
133
+ /**
134
+ * Returns whether the watcher is currently running
135
+ *
136
+ * @returns True if watcher is active, false otherwise
137
+ */
138
+ function isWatcherRunning() {
139
+ return watcher !== null;
140
+ }
141
+ //# sourceMappingURL=file-watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-watcher.js","sourceRoot":"","sources":["../../src/services/file-watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI tool for importing Claude Code transcripts
4
+ *
5
+ * Usage:
6
+ * npm run import # Import all from ~/.claude/projects/
7
+ * npm run import -- --single <file> # Import a single file
8
+ * npm run import -- --help # Show help
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=import-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-cli.d.ts","sourceRoot":"","sources":["../../src/services/import-cli.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG"}
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * CLI tool for importing Claude Code transcripts
5
+ *
6
+ * Usage:
7
+ * npm run import # Import all from ~/.claude/projects/
8
+ * npm run import -- --single <file> # Import a single file
9
+ * npm run import -- --help # Show help
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const transcript_importer_1 = require("./transcript-importer");
13
+ const transcript_queries_1 = require("../db/transcript-queries");
14
+ const args = process.argv.slice(2);
15
+ function printHelp() {
16
+ console.log(`
17
+ Claude Code Transcript Importer
18
+ ================================
19
+
20
+ Usage:
21
+ npm run import # Bulk import all transcripts
22
+ npm run import -- --single <file> # Import a single file
23
+ npm run import -- --stats # Show import statistics
24
+ npm run import -- --help # Show this help
25
+
26
+ Options:
27
+ --source <path> Source directory (default: ~/.claude/projects/)
28
+ --parallel <n> Number of parallel imports (default: 10)
29
+ --skip-existing Skip already imported sessions (default: true)
30
+ --no-skip Force re-import existing sessions
31
+
32
+ Examples:
33
+ # Import all transcripts from default location
34
+ npm run import
35
+
36
+ # Import from a specific directory
37
+ npm run import -- --source /path/to/transcripts
38
+
39
+ # Import a single file
40
+ npm run import -- --single ~/.claude/projects/my-project/session-123.jsonl
41
+
42
+ # Import with 20 parallel workers
43
+ npm run import -- --parallel 20
44
+
45
+ # Force re-import of all sessions
46
+ npm run import -- --no-skip
47
+ `);
48
+ }
49
+ async function main() {
50
+ // Parse arguments
51
+ const options = {
52
+ sourcePath: undefined,
53
+ parallel: 10,
54
+ skipExisting: true,
55
+ };
56
+ let mode = 'bulk';
57
+ let singleFile;
58
+ for (let i = 0; i < args.length; i++) {
59
+ const arg = args[i];
60
+ switch (arg) {
61
+ case '--help':
62
+ case '-h':
63
+ mode = 'help';
64
+ break;
65
+ case '--stats':
66
+ mode = 'stats';
67
+ break;
68
+ case '--single':
69
+ mode = 'single';
70
+ singleFile = args[++i];
71
+ break;
72
+ case '--source':
73
+ options.sourcePath = args[++i];
74
+ break;
75
+ case '--parallel':
76
+ options.parallel = parseInt(args[++i] || '10', 10);
77
+ break;
78
+ case '--skip-existing':
79
+ options.skipExisting = true;
80
+ break;
81
+ case '--no-skip':
82
+ options.skipExisting = false;
83
+ break;
84
+ default:
85
+ console.error(`Unknown option: ${arg}`);
86
+ console.error('Run with --help for usage information');
87
+ process.exit(1);
88
+ }
89
+ }
90
+ // Initialize database
91
+ (0, transcript_queries_1.initializeTranscriptSchema)();
92
+ // Execute based on mode
93
+ switch (mode) {
94
+ case 'help':
95
+ printHelp();
96
+ break;
97
+ case 'stats':
98
+ console.log('Import Statistics:\n');
99
+ const stats = (0, transcript_importer_1.getImportProgress)();
100
+ console.log(` Total sessions: ${stats.total}`);
101
+ console.log(` Pending: ${stats.pending}`);
102
+ console.log(` Completed: ${stats.completed}`);
103
+ console.log(` Failed: ${stats.failed}`);
104
+ break;
105
+ case 'single':
106
+ if (!singleFile) {
107
+ console.error('Error: --single requires a file path');
108
+ process.exit(1);
109
+ }
110
+ console.log(`Importing single file: ${singleFile}\n`);
111
+ try {
112
+ await (0, transcript_importer_1.importTranscript)(singleFile);
113
+ console.log('\n✓ Import completed successfully');
114
+ }
115
+ catch (error) {
116
+ console.error('\n✗ Import failed:', error);
117
+ process.exit(1);
118
+ }
119
+ break;
120
+ case 'bulk':
121
+ console.log('Starting bulk import...\n');
122
+ // Add progress callback
123
+ options.onProgress = (completed, total) => {
124
+ const percent = Math.round((completed / total) * 100);
125
+ const bar = createProgressBar(percent, 40);
126
+ process.stdout.write(`\r${bar} ${completed}/${total} (${percent}%)`);
127
+ };
128
+ try {
129
+ const summary = await (0, transcript_importer_1.bulkImportTranscripts)(options);
130
+ console.log('\n\nImport Summary:');
131
+ console.log('===============');
132
+ console.log(` Total files: ${summary.totalFiles}`);
133
+ console.log(` Successful: ${summary.successful}`);
134
+ console.log(` Failed: ${summary.failed}`);
135
+ console.log(` Skipped: ${summary.skipped}`);
136
+ console.log(` Duration: ${(summary.duration / 1000).toFixed(2)}s`);
137
+ if (summary.failed > 0) {
138
+ console.log('\nFailed imports:');
139
+ summary.results
140
+ .filter((r) => !r.success)
141
+ .forEach((r) => {
142
+ console.log(` × ${r.sessionId}`);
143
+ console.log(` File: ${r.filePath}`);
144
+ console.log(` Error: ${r.error}`);
145
+ });
146
+ }
147
+ if (summary.failed > 0) {
148
+ process.exit(1);
149
+ }
150
+ }
151
+ catch (error) {
152
+ console.error('\n✗ Bulk import failed:', error);
153
+ process.exit(1);
154
+ }
155
+ break;
156
+ }
157
+ }
158
+ /**
159
+ * Create a simple progress bar
160
+ */
161
+ function createProgressBar(percent, width) {
162
+ const filled = Math.round((percent / 100) * width);
163
+ const empty = width - filled;
164
+ return `[${'█'.repeat(filled)}${' '.repeat(empty)}]`;
165
+ }
166
+ // Run CLI
167
+ main().catch((error) => {
168
+ console.error('Fatal error:', error);
169
+ process.exit(1);
170
+ });
171
+ //# sourceMappingURL=import-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-cli.js","sourceRoot":"","sources":["../../src/services/import-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Bulk Transcript Importer Service
3
+ *
4
+ * Scans ~/.claude/projects/ for .jsonl transcript files and imports them
5
+ * into the SQLite database for fast querying and playback.
6
+ *
7
+ * Features:
8
+ * - Parallel processing (configurable concurrency)
9
+ * - Progress tracking via parsing_status table
10
+ * - Skip already imported sessions
11
+ * - Graceful error handling
12
+ * - Progress callbacks for monitoring
13
+ *
14
+ * @module transcript-importer
15
+ */
16
+ import { AgentType } from '../parser/agent-detector';
17
+ import type { ImportJobConfig } from '../db/transcript-schema';
18
+ /**
19
+ * Import result for a single session
20
+ */
21
+ interface ImportResult {
22
+ sessionId: string;
23
+ filePath: string;
24
+ success: boolean;
25
+ framesImported?: number;
26
+ error?: string;
27
+ skipped?: boolean;
28
+ }
29
+ /**
30
+ * Import summary for bulk operations
31
+ */
32
+ interface ImportSummary {
33
+ totalFiles: number;
34
+ successful: number;
35
+ failed: number;
36
+ skipped: number;
37
+ results: ImportResult[];
38
+ duration: number;
39
+ }
40
+ /**
41
+ * Import a single transcript file into the database
42
+ *
43
+ * Parses the .jsonl file, builds a timeline, and inserts all data
44
+ * into the database. Updates parsing_status table for progress tracking.
45
+ *
46
+ * @param filePath - Absolute path to .jsonl transcript file
47
+ * @param agent - Optional agent type override. If not specified, auto-detected from path.
48
+ * @returns Promise that resolves when import is complete
49
+ * @throws Error if parsing or database insertion fails
50
+ *
51
+ * @example
52
+ * await importTranscript('/Users/me/.claude/projects/my-project/session-123.jsonl');
53
+ *
54
+ * @example
55
+ * await importTranscript('/custom/path/session.jsonl', 'codex');
56
+ */
57
+ export declare function importTranscript(filePath: string, agent?: AgentType): Promise<void>;
58
+ /**
59
+ * Bulk import all transcript files from a directory
60
+ *
61
+ * Scans the source directory recursively for .jsonl files and imports
62
+ * them in parallel (respecting concurrency limit). Skips already imported
63
+ * sessions by default.
64
+ *
65
+ * @param config - Import job configuration
66
+ * @returns Promise resolving to import summary
67
+ *
68
+ * @example
69
+ * const summary = await bulkImportTranscripts({
70
+ * sourcePath: '~/.claude/projects',
71
+ * parallel: 10,
72
+ * onProgress: (completed, total) => {
73
+ * console.log(`Progress: ${completed}/${total}`);
74
+ * }
75
+ * });
76
+ *
77
+ * console.log(`Imported ${summary.successful} sessions`);
78
+ */
79
+ export declare function bulkImportTranscripts(config?: ImportJobConfig): Promise<ImportSummary>;
80
+ /**
81
+ * Get import progress statistics
82
+ *
83
+ * Returns current state of all import jobs tracked in parsing_status table.
84
+ *
85
+ * @returns Import statistics
86
+ *
87
+ * @example
88
+ * const stats = getImportProgress();
89
+ * console.log(`Pending: ${stats.pending}, Completed: ${stats.completed}`);
90
+ */
91
+ export declare function getImportProgress(): {
92
+ total: number;
93
+ pending: number;
94
+ completed: number;
95
+ failed: number;
96
+ };
97
+ export {};
98
+ //# sourceMappingURL=transcript-importer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-importer.d.ts","sourceRoot":"","sources":["../../src/services/transcript-importer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,EAAuB,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAU1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAa/D;;GAEG;AACH,UAAU,YAAY;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAiGzF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,aAAa,CAAC,CA+ExB;AAuHD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,IAAI;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,CAGA"}