Skip to content
Closed
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
2 changes: 1 addition & 1 deletion src/services/code-index/__tests__/manager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ describe("CodeIndexManager - handleSettingsChange regression", () => {
beforeEach(() => {
// Mock service factory objects
mockEmbedder = { embedderInfo: { name: "openai" } }
mockVectorStore = {}
mockVectorStore = { hasData: vi.fn().mockResolvedValue(false) }
mockScanner = {}
mockFileWatcher = {
onDidStartBatchProcessing: vi.fn(),
Expand Down
6 changes: 6 additions & 0 deletions src/services/code-index/interfaces/vector-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ export interface IVectorStore {
* @returns Promise resolving to boolean indicating if the collection exists
*/
collectionExists(): Promise<boolean>

/**
* Checks if the collection has any data (points)
* @returns Promise resolving to boolean indicating if the collection has data
*/
hasData(): Promise<boolean>
}

export interface VectorStoreSearchResult {
Expand Down
17 changes: 9 additions & 8 deletions src/services/code-index/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,15 @@ export class CodeIndexManager {
}

// 5. Handle Indexing Start/Restart
// The enhanced vectorStore.initialize() in startIndexing() now handles dimension changes automatically
// by detecting incompatible collections and recreating them, so we rely on that for dimension changes
const shouldStartOrRestartIndexing =
requiresRestart ||
(needsServiceRecreation && (!this._orchestrator || this._orchestrator.state !== "Indexing"))

if (shouldStartOrRestartIndexing) {
this._orchestrator?.startIndexing() // This method is async, but we don't await it here
// Only start indexing if:
// - Configuration requires restart (settings changed)
// - Or this is the first initialization (no orchestrator exists yet)
// The orchestrator's startIndexing method will check if an existing index exists
// and skip the full scan if data is already present
const shouldStartIndexing = requiresRestart || !this._orchestrator

if (shouldStartIndexing && this._orchestrator) {
this._orchestrator.startIndexing() // This method is async, but we don't await it here
}

return { requiresRestart }
Expand Down
11 changes: 11 additions & 0 deletions src/services/code-index/orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,17 @@ export class CodeIndexOrchestrator {
await this.cacheManager.clearCacheFile()
}

// Check if we have an existing index with data
const hasExistingData = !collectionCreated && (await this.vectorStore.hasData())

if (hasExistingData) {
console.log("[CodeIndexOrchestrator] Existing index found with data. Skipping initial scan.")
// Start the file watcher without doing a full scan
await this._startWatcher()
this.stateManager.setSystemState("Indexed", "Using existing index. File watcher started.")
return
}

this.stateManager.setSystemState("Indexing", "Services ready. Starting workspace scan...")

let cumulativeBlocksIndexed = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ describe("FileWatcher", () => {
upsertPoints: vi.fn().mockResolvedValue(undefined),
deletePointsByFilePath: vi.fn().mockResolvedValue(undefined),
deletePointsByMultipleFilePaths: vi.fn().mockResolvedValue(undefined),
hasData: vi.fn().mockResolvedValue(false),
}

mockIgnoreInstance = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ describe("DirectoryScanner", () => {
clearCollection: vi.fn().mockResolvedValue(undefined),
deleteCollection: vi.fn().mockResolvedValue(undefined),
collectionExists: vi.fn().mockResolvedValue(true),
hasData: vi.fn().mockResolvedValue(false),
}
mockCodeParser = {
parseFile: vi.fn().mockResolvedValue([]),
Expand Down
22 changes: 22 additions & 0 deletions src/services/code-index/vector-store/qdrant-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,4 +488,26 @@ export class QdrantVectorStore implements IVectorStore {
const collectionInfo = await this.getCollectionInfo()
return collectionInfo !== null
}

/**
* Checks if the collection has any data (points)
* @returns Promise resolving to boolean indicating if the collection has data
*/
async hasData(): Promise<boolean> {
try {
const collectionInfo = await this.getCollectionInfo()
if (!collectionInfo) {
return false
}

// Check if the collection has any points
// The collection info includes points_count or vectors_count depending on the version
const pointsCount = (collectionInfo as any).points_count || (collectionInfo as any).vectors_count || 0

return pointsCount > 0
} catch (error) {
console.warn(`[QdrantVectorStore] Error checking if collection has data:`, error)
return false
}
}
}