| 126 | }; |
| 127 | |
| 128 | const performIndexing = async (incrementalOnly?: boolean, reason?: string): Promise<void> => { |
| 129 | indexState.status = 'indexing'; |
| 130 | const mode = incrementalOnly ? 'incremental' : 'full'; |
| 131 | console.error(`Indexing (${mode})${reason ? ` — ${reason}` : ''}: ${rootPath}`); |
| 132 | |
| 133 | try { |
| 134 | let lastLoggedProgress = { phase: '', percentage: -1 }; |
| 135 | const indexer = new CodebaseIndexer({ |
| 136 | rootPath, |
| 137 | incrementalOnly, |
| 138 | onProgress: (progress) => { |
| 139 | const shouldLog = |
| 140 | progress.phase !== lastLoggedProgress.phase || |
| 141 | (progress.percentage % 10 === 0 && |
| 142 | progress.percentage !== lastLoggedProgress.percentage); |
| 143 | if (shouldLog) { |
| 144 | console.error(`[${progress.phase}] ${progress.percentage}%`); |
| 145 | lastLoggedProgress = { phase: progress.phase, percentage: progress.percentage }; |
| 146 | } |
| 147 | } |
| 148 | }); |
| 149 | |
| 150 | indexState.indexer = indexer; |
| 151 | const stats = await indexer.index(); |
| 152 | indexState.status = 'ready'; |
| 153 | indexState.lastIndexed = new Date(); |
| 154 | indexState.stats = stats; |
| 155 | |
| 156 | console.error( |
| 157 | `Complete: ${stats.indexedFiles} files, ${stats.totalChunks} chunks in ${( |
| 158 | stats.duration / 1000 |
| 159 | ).toFixed(2)}s` |
| 160 | ); |
| 161 | } catch (error) { |
| 162 | indexState.status = 'error'; |
| 163 | indexState.error = error instanceof Error ? error.message : String(error); |
| 164 | console.error('Indexing failed:', indexState.error); |
| 165 | } |
| 166 | }; |
| 167 | |
| 168 | return { |
| 169 | indexState, |