()
| 137 | } |
| 138 | |
| 139 | async initialize(): Promise<void> { |
| 140 | if (this.initialized) return; |
| 141 | |
| 142 | try { |
| 143 | // Fail closed on version mismatch/corruption before serving any results. |
| 144 | this.indexMeta = await readIndexMeta(this.rootPath); |
| 145 | await validateIndexArtifacts(this.rootPath, this.indexMeta); |
| 146 | |
| 147 | await this.loadKeywordIndex(); |
| 148 | await this.loadPatternIntelligence(); |
| 149 | |
| 150 | // Use the embedding config the index was built with, not the current env-var defaults. |
| 151 | // This ensures query vectors are in the same space as stored vectors. |
| 152 | // Legacy indexes (no embeddingProvider stored) fall back to env-var defaults. |
| 153 | const storedProvider = this.indexMeta.artifacts.vectorDb.embeddingProvider; |
| 154 | const storedModel = this.indexMeta.artifacts.vectorDb.embeddingModel; |
| 155 | const embeddingConfig: Partial<EmbeddingConfig> = storedProvider |
| 156 | ? { provider: storedProvider as EmbeddingConfig['provider'], model: storedModel } |
| 157 | : {}; |
| 158 | this.embeddingProvider = await getEmbeddingProvider(embeddingConfig); |
| 159 | this.storageProvider = await getStorageProvider({ |
| 160 | path: this.storagePath |
| 161 | }); |
| 162 | |
| 163 | this.initialized = true; |
| 164 | } catch (error) { |
| 165 | if (error instanceof IndexCorruptedError) { |
| 166 | throw error; // Propagate to handler for auto-heal |
| 167 | } |
| 168 | console.warn('Partial initialization (keyword search only):', error); |
| 169 | this.initialized = true; |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | private async loadKeywordIndex(): Promise<void> { |
| 174 | try { |
no test coverage detected