Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/services/code-index/__tests__/manager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ describe("CodeIndexManager - handleExternalSettingsChange regression", () => {
expect(manager.isInitialized).toBe(true)

// Mock the methods that would be called during restart
const stopWatcherSpy = vitest.spyOn(manager, "stopWatcher").mockImplementation(() => {})
const recreateServicesSpy = vitest.spyOn(manager as any, "_recreateServices").mockImplementation(() => {})
const startIndexingSpy = vitest.spyOn(manager, "startIndexing").mockResolvedValue()

// Mock the feature state
Expand All @@ -100,7 +100,7 @@ describe("CodeIndexManager - handleExternalSettingsChange regression", () => {

// Verify that the restart sequence was called
expect(mockConfigManager.loadConfiguration).toHaveBeenCalled()
expect(stopWatcherSpy).toHaveBeenCalled()
expect(recreateServicesSpy).toHaveBeenCalled()
expect(startIndexingSpy).toHaveBeenCalled()
})

Expand Down
109 changes: 60 additions & 49 deletions src/services/code-index/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,54 +123,7 @@ export class CodeIndexManager {
const needsServiceRecreation = !this._serviceFactory || requiresRestart

if (needsServiceRecreation) {
// Stop watcher if it exists
if (this._orchestrator) {
this.stopWatcher()
}

// (Re)Initialize service factory
this._serviceFactory = new CodeIndexServiceFactory(
this._configManager,
this.workspacePath,
this._cacheManager,
)

const ignoreInstance = ignore()
const ignorePath = path.join(getWorkspacePath(), ".gitignore")
try {
const content = await fs.readFile(ignorePath, "utf8")
ignoreInstance.add(content)
ignoreInstance.add(".gitignore")
} catch (error) {
// Should never happen: reading file failed even though it exists
console.error("Unexpected error loading .gitignore:", error)
}

// (Re)Create shared service instances
const { embedder, vectorStore, scanner, fileWatcher } = this._serviceFactory.createServices(
this.context,
this._cacheManager,
ignoreInstance,
)

// (Re)Initialize orchestrator
this._orchestrator = new CodeIndexOrchestrator(
this._configManager,
this._stateManager,
this.workspacePath,
this._cacheManager,
vectorStore,
scanner,
fileWatcher,
)

// (Re)Initialize search service
this._searchService = new CodeIndexSearchService(
this._configManager,
this._stateManager,
embedder,
vectorStore,
)
await this._recreateServices()
}

// 5. Handle Indexing Start/Restart
Expand Down Expand Up @@ -248,6 +201,61 @@ export class CodeIndexManager {
return this._searchService!.searchIndex(query, directoryPrefix)
}

/**
* Private helper method to recreate services with current configuration.
* Used by both initialize() and handleExternalSettingsChange().
*/
private async _recreateServices(): Promise<void> {
// Stop watcher if it exists
if (this._orchestrator) {
this.stopWatcher()
}

// (Re)Initialize service factory
this._serviceFactory = new CodeIndexServiceFactory(
this._configManager!,
this.workspacePath,
this._cacheManager!,
)

const ignoreInstance = ignore()
const ignorePath = path.join(getWorkspacePath(), ".gitignore")
try {
const content = await fs.readFile(ignorePath, "utf8")
ignoreInstance.add(content)
ignoreInstance.add(".gitignore")
} catch (error) {
// Should never happen: reading file failed even though it exists
console.error("Unexpected error loading .gitignore:", error)
}

// (Re)Create shared service instances
const { embedder, vectorStore, scanner, fileWatcher } = this._serviceFactory.createServices(
this.context,
this._cacheManager!,
ignoreInstance,
)

// (Re)Initialize orchestrator
this._orchestrator = new CodeIndexOrchestrator(
this._configManager!,
this._stateManager,
this.workspacePath,
this._cacheManager!,
vectorStore,
scanner,
fileWatcher,
)

// (Re)Initialize search service
this._searchService = new CodeIndexSearchService(
this._configManager!,
this._stateManager,
embedder,
vectorStore,
)
}

/**
* Handles external settings changes by reloading configuration.
* This method should be called when API provider settings are updated
Expand All @@ -263,7 +271,10 @@ export class CodeIndexManager {

// If configuration changes require a restart and the manager is initialized, restart the service
if (requiresRestart && isFeatureEnabled && isFeatureConfigured && this.isInitialized) {
this.stopWatcher()
// Recreate services with new configuration
await this._recreateServices()

// Start indexing with new services
await this.startIndexing()
}
}
Expand Down
Loading