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/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1510,7 +1510,7 @@ export class ClineProvider
customCondensingPrompt,
codebaseIndexModels: codebaseIndexModels ?? EMBEDDING_MODEL_PROFILES,
codebaseIndexConfig: codebaseIndexConfig ?? {
codebaseIndexEnabled: false,
codebaseIndexEnabled: true,
codebaseIndexQdrantUrl: "http://localhost:6333",
codebaseIndexEmbedderProvider: "openai",
codebaseIndexEmbedderBaseUrl: "",
Expand Down Expand Up @@ -1668,7 +1668,7 @@ export class ClineProvider
customCondensingPrompt: stateValues.customCondensingPrompt,
codebaseIndexModels: stateValues.codebaseIndexModels ?? EMBEDDING_MODEL_PROFILES,
codebaseIndexConfig: stateValues.codebaseIndexConfig ?? {
codebaseIndexEnabled: false,
codebaseIndexEnabled: true,
codebaseIndexQdrantUrl: "http://localhost:6333",
codebaseIndexEmbedderProvider: "openai",
codebaseIndexEmbedderBaseUrl: "",
Expand Down
2 changes: 1 addition & 1 deletion src/core/webview/__tests__/ClineProvider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ describe("ClineProvider", () => {
alwaysAllowReadOnlyOutsideWorkspace: false,
alwaysAllowWrite: false,
codebaseIndexConfig: {
codebaseIndexEnabled: false,
codebaseIndexEnabled: true,
codebaseIndexQdrantUrl: "",
codebaseIndexEmbedderProvider: "openai",
codebaseIndexEmbedderBaseUrl: "",
Expand Down
15 changes: 0 additions & 15 deletions src/core/webview/webviewMessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1221,21 +1221,6 @@ export const webviewMessageHandler = async (
break
case "browserToolEnabled":
await updateGlobalState("browserToolEnabled", message.bool ?? true)
await provider.postStateToWebview()
break
case "codebaseIndexEnabled":
// Update the codebaseIndexConfig with the new enabled state
const currentCodebaseConfig = getGlobalState("codebaseIndexConfig") || {}
await updateGlobalState("codebaseIndexConfig", {
...currentCodebaseConfig,
codebaseIndexEnabled: message.bool ?? false,
})

// Notify the code index manager about the change
if (provider.codeIndexManager) {
await provider.codeIndexManager.handleSettingsChange()
}

await provider.postStateToWebview()
break
case "language":
Expand Down
38 changes: 15 additions & 23 deletions src/services/code-index/__tests__/config-manager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe("CodeIndexConfigManager", () => {
describe("constructor", () => {
it("should initialize with ContextProxy", () => {
expect(configManager).toBeDefined()
expect(configManager.isFeatureEnabled).toBe(false)
expect(configManager.isFeatureEnabled).toBe(true)
expect(configManager.currentEmbedderProvider).toBe("openai")
})
})
Expand All @@ -45,7 +45,6 @@ describe("CodeIndexConfigManager", () => {
const result = await configManager.loadConfiguration()

expect(result.currentConfig).toEqual({
isEnabled: false,
isConfigured: false,
embedderProvider: "openai",
modelId: undefined,
Expand Down Expand Up @@ -77,7 +76,6 @@ describe("CodeIndexConfigManager", () => {
const result = await configManager.loadConfiguration()

expect(result.currentConfig).toEqual({
isEnabled: true,
isConfigured: true,
embedderProvider: "openai",
modelId: "text-embedding-3-large",
Expand Down Expand Up @@ -111,7 +109,6 @@ describe("CodeIndexConfigManager", () => {
const result = await configManager.loadConfiguration()

expect(result.currentConfig).toEqual({
isEnabled: true,
isConfigured: true,
embedderProvider: "openai-compatible",
modelId: "text-embedding-3-large",
Expand Down Expand Up @@ -149,7 +146,6 @@ describe("CodeIndexConfigManager", () => {
const result = await configManager.loadConfiguration()

expect(result.currentConfig).toEqual({
isEnabled: true,
isConfigured: true,
embedderProvider: "openai-compatible",
modelId: "custom-model",
Expand Down Expand Up @@ -188,7 +184,6 @@ describe("CodeIndexConfigManager", () => {
const result = await configManager.loadConfiguration()

expect(result.currentConfig).toEqual({
isEnabled: true,
isConfigured: true,
embedderProvider: "openai-compatible",
modelId: "custom-model",
Expand Down Expand Up @@ -227,7 +222,6 @@ describe("CodeIndexConfigManager", () => {
const result = await configManager.loadConfiguration()

expect(result.currentConfig).toEqual({
isEnabled: true,
isConfigured: true,
embedderProvider: "openai-compatible",
modelId: "custom-model",
Expand Down Expand Up @@ -326,14 +320,14 @@ describe("CodeIndexConfigManager", () => {
})

it("should detect restart requirement when transitioning to enabled+configured", async () => {
// Initial state - disabled
// Initial state - enabled but not configured
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: false,
codebaseIndexEnabled: true,
})

await configManager.loadConfiguration()

// Enable and configure
// Configure the feature
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: true,
codebaseIndexQdrantUrl: "http://qdrant.local",
Expand Down Expand Up @@ -689,29 +683,28 @@ describe("CodeIndexConfigManager", () => {
expect(result.requiresRestart).toBe(true)
})

it("should not require restart when disabled remains disabled", async () => {
// Initial state - disabled but configured
it("should require restart when enabled and provider changes even if unconfigured", async () => {
// Initial state - enabled but not configured (missing API key)
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: false,
codebaseIndexEnabled: true,
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai",
})
setupSecretMocks({
codeIndexOpenAiKey: "test-key",
})
setupSecretMocks({})

await configManager.loadConfiguration()

// Still disabled but change other settings
// Still enabled but change provider while remaining unconfigured
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: false,
codebaseIndexQdrantUrl: "http://different-qdrant.local",
codebaseIndexEnabled: true,
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "ollama",
codebaseIndexEmbedderBaseUrl: "http://ollama.local",
})

const result = await configManager.loadConfiguration()
expect(result.requiresRestart).toBe(false)
// Should require restart because provider changed while enabled
expect(result.requiresRestart).toBe(true)
})

it("should not require restart when unconfigured remains unconfigured", async () => {
Expand Down Expand Up @@ -970,7 +963,7 @@ describe("CodeIndexConfigManager", () => {
it("should not require restart when API keys transition from undefined to empty string", async () => {
// Initial state with undefined API keys
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: false, // Start disabled to avoid restart due to enable+configure
codebaseIndexEnabled: true, // Always enabled now
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai",
})
Expand Down Expand Up @@ -1208,7 +1201,6 @@ describe("CodeIndexConfigManager", () => {
it("should return correct configuration via getConfig", () => {
const config = configManager.getConfig()
expect(config).toEqual({
isEnabled: true,
isConfigured: true,
embedderProvider: "openai",
modelId: "text-embedding-3-large",
Expand Down Expand Up @@ -1267,7 +1259,7 @@ describe("CodeIndexConfigManager", () => {
it("should properly initialize with current config to prevent false restarts", async () => {
// Setup configuration
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: false, // Start disabled to avoid transition restart
codebaseIndexEnabled: true, // Always enabled now
codebaseIndexQdrantUrl: "http://qdrant.local",
codebaseIndexEmbedderProvider: "openai",
codebaseIndexEmbedderModelId: "text-embedding-3-small",
Expand Down
3 changes: 0 additions & 3 deletions src/services/code-index/__tests__/manager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ describe("CodeIndexManager - handleSettingsChange regression", () => {
isFeatureConfigured: true,
isFeatureEnabled: true,
getConfig: vi.fn().mockReturnValue({
isEnabled: true,
isConfigured: true,
embedderProvider: "openai",
modelId: "text-embedding-3-small",
Expand Down Expand Up @@ -149,7 +148,6 @@ describe("CodeIndexManager - handleSettingsChange regression", () => {
isFeatureConfigured: true,
isFeatureEnabled: true,
getConfig: vi.fn().mockReturnValue({
isEnabled: true,
isConfigured: true,
embedderProvider: "openai",
modelId: "text-embedding-3-small",
Expand Down Expand Up @@ -276,7 +274,6 @@ describe("CodeIndexManager - handleSettingsChange regression", () => {
isFeatureConfigured: true,
isFeatureEnabled: true,
getConfig: vitest.fn().mockReturnValue({
isEnabled: true,
isConfigured: true,
embedderProvider: "openai",
modelId: "text-embedding-3-small",
Expand Down
98 changes: 45 additions & 53 deletions src/services/code-index/config-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { getDefaultModelId, getModelDimension, getModelScoreThreshold } from "..
* Handles loading, validating, and providing access to configuration values.
*/
export class CodeIndexConfigManager {
private isEnabled: boolean = false
private embedderProvider: EmbedderProvider = "openai"
private modelId?: string
private modelDimension?: number
Expand Down Expand Up @@ -42,7 +41,7 @@ export class CodeIndexConfigManager {
private _loadAndSetConfiguration(): void {
// Load configuration from storage
const codebaseIndexConfig = this.contextProxy?.getGlobalState("codebaseIndexConfig") ?? {
codebaseIndexEnabled: false,
codebaseIndexEnabled: true,
codebaseIndexQdrantUrl: "http://localhost:6333",
codebaseIndexEmbedderProvider: "openai",
codebaseIndexEmbedderBaseUrl: "",
Expand All @@ -69,7 +68,7 @@ export class CodeIndexConfigManager {
const geminiApiKey = this.contextProxy?.getSecret("codebaseIndexGeminiApiKey") ?? ""

// Update instance variables with configuration
this.isEnabled = codebaseIndexEnabled || false
// Note: codebaseIndexEnabled is no longer used as the feature is always enabled
this.qdrantUrl = codebaseIndexQdrantUrl
this.qdrantApiKey = qdrantApiKey ?? ""
this.searchMinScore = codebaseIndexSearchMinScore
Expand Down Expand Up @@ -127,7 +126,6 @@ export class CodeIndexConfigManager {
public async loadConfiguration(): Promise<{
configSnapshot: PreviousConfigSnapshot
currentConfig: {
isEnabled: boolean
isConfigured: boolean
embedderProvider: EmbedderProvider
modelId?: string
Expand All @@ -144,7 +142,7 @@ export class CodeIndexConfigManager {
}> {
// Capture the ACTUAL previous state before loading new configuration
const previousConfigSnapshot: PreviousConfigSnapshot = {
enabled: this.isEnabled,
enabled: true, // Feature is always enabled
configured: this.isConfigured(),
embedderProvider: this.embedderProvider,
modelId: this.modelId,
Expand All @@ -169,7 +167,6 @@ export class CodeIndexConfigManager {
return {
configSnapshot: previousConfigSnapshot,
currentConfig: {
isEnabled: this.isEnabled,
isConfigured: this.isConfigured(),
embedderProvider: this.embedderProvider,
modelId: this.modelId,
Expand Down Expand Up @@ -246,66 +243,62 @@ export class CodeIndexConfigManager {
const prevQdrantUrl = prev?.qdrantUrl ?? ""
const prevQdrantApiKey = prev?.qdrantApiKey ?? ""

// 1. Transition from disabled/unconfigured to enabled+configured
if ((!prevEnabled || !prevConfigured) && this.isEnabled && nowConfigured) {
// 1. Transition from unconfigured to configured
// Since the feature is always enabled, we only check configuration status
if (!prevConfigured && nowConfigured) {
return true
}

// 2. If was disabled and still is, no restart needed
if (!prevEnabled && !this.isEnabled) {
return false
}

// 3. If wasn't ready before and isn't ready now, no restart needed
if (!prevConfigured && !nowConfigured) {
return false
}

// 4. CRITICAL CHANGES - Always restart for these
if (this.isEnabled || prevEnabled) {
// Provider change
if (prevProvider !== this.embedderProvider) {
return true
}
// Since feature is always enabled, we always check for critical changes

// Authentication changes (API keys)
const currentOpenAiKey = this.openAiOptions?.openAiNativeApiKey ?? ""
const currentOllamaBaseUrl = this.ollamaOptions?.ollamaBaseUrl ?? ""
const currentOpenAiCompatibleBaseUrl = this.openAiCompatibleOptions?.baseUrl ?? ""
const currentOpenAiCompatibleApiKey = this.openAiCompatibleOptions?.apiKey ?? ""
const currentModelDimension = this.modelDimension
const currentGeminiApiKey = this.geminiOptions?.apiKey ?? ""
const currentQdrantUrl = this.qdrantUrl ?? ""
const currentQdrantApiKey = this.qdrantApiKey ?? ""

if (prevOpenAiKey !== currentOpenAiKey) {
return true
}
// Provider change
if (prevProvider !== this.embedderProvider) {
return true
}

if (prevOllamaBaseUrl !== currentOllamaBaseUrl) {
return true
}
// Authentication changes (API keys)
const currentOpenAiKey = this.openAiOptions?.openAiNativeApiKey ?? ""
const currentOllamaBaseUrl = this.ollamaOptions?.ollamaBaseUrl ?? ""
const currentOpenAiCompatibleBaseUrl = this.openAiCompatibleOptions?.baseUrl ?? ""
const currentOpenAiCompatibleApiKey = this.openAiCompatibleOptions?.apiKey ?? ""
const currentModelDimension = this.modelDimension
const currentGeminiApiKey = this.geminiOptions?.apiKey ?? ""
const currentQdrantUrl = this.qdrantUrl ?? ""
const currentQdrantApiKey = this.qdrantApiKey ?? ""

if (prevOpenAiKey !== currentOpenAiKey) {
return true
}

if (
prevOpenAiCompatibleBaseUrl !== currentOpenAiCompatibleBaseUrl ||
prevOpenAiCompatibleApiKey !== currentOpenAiCompatibleApiKey
) {
return true
}
if (prevOllamaBaseUrl !== currentOllamaBaseUrl) {
return true
}

// Check for model dimension changes (generic for all providers)
if (prevModelDimension !== currentModelDimension) {
return true
}
if (
prevOpenAiCompatibleBaseUrl !== currentOpenAiCompatibleBaseUrl ||
prevOpenAiCompatibleApiKey !== currentOpenAiCompatibleApiKey
) {
return true
}

if (prevQdrantUrl !== currentQdrantUrl || prevQdrantApiKey !== currentQdrantApiKey) {
return true
}
// Check for model dimension changes (generic for all providers)
if (prevModelDimension !== currentModelDimension) {
return true
}

// Vector dimension changes (still important for compatibility)
if (this._hasVectorDimensionChanged(prevProvider, prev?.modelId)) {
return true
}
if (prevQdrantUrl !== currentQdrantUrl || prevQdrantApiKey !== currentQdrantApiKey) {
return true
}

// Vector dimension changes (still important for compatibility)
if (this._hasVectorDimensionChanged(prevProvider, prev?.modelId)) {
return true
}

return false
Expand Down Expand Up @@ -342,7 +335,6 @@ export class CodeIndexConfigManager {
*/
public getConfig(): CodeIndexConfig {
return {
isEnabled: this.isEnabled,
isConfigured: this.isConfigured(),
embedderProvider: this.embedderProvider,
modelId: this.modelId,
Expand All @@ -362,7 +354,7 @@ export class CodeIndexConfigManager {
* Gets whether the code indexing feature is enabled
*/
public get isFeatureEnabled(): boolean {
return this.isEnabled
return true
}

/**
Expand Down
1 change: 0 additions & 1 deletion src/services/code-index/interfaces/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { EmbedderProvider } from "./manager"
* Configuration state for the code indexing feature
*/
export interface CodeIndexConfig {
isEnabled: boolean
isConfigured: boolean
embedderProvider: EmbedderProvider
modelId?: string
Expand Down
Loading
Loading