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
118 changes: 118 additions & 0 deletions src/services/code-index/__tests__/config-manager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1807,6 +1807,124 @@ describe("CodeIndexConfigManager", () => {
// Should return undefined since custom dimension is invalid
expect(configManager.currentModelDimension).toBe(undefined)
})

describe("OpenRouter provider dimension handling", () => {
it("should correctly handle OpenRouter mistral model dimensions across restarts", async () => {
// Mock getModelDimension to return correct dimensions for OpenRouter models
mockedGetModelDimension.mockImplementation((provider, modelId) => {
if (provider === "openrouter") {
if (modelId === "mistralai/codestral-embed-2505") return 1536
if (modelId === "mistralai/mistral-embed-2312") return 1024
if (modelId === "openai/text-embedding-3-large") return 3072
}
return undefined
})

// Initial configuration with OpenRouter and Mistral model
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: true,
codebaseIndexEmbedderProvider: "openrouter",
codebaseIndexEmbedderModelId: "mistralai/codestral-embed-2505",
codebaseIndexQdrantUrl: "http://localhost:6333",
})
mockContextProxy.getSecret.mockImplementation((key: string) => {
if (key === "codebaseIndexOpenRouterApiKey") return "test-openrouter-key"
if (key === "codeIndexQdrantApiKey") return "test-qdrant-key"
return undefined
})

configManager = new CodeIndexConfigManager(mockContextProxy)
await configManager.loadConfiguration()

// Should correctly return the built-in dimension for the Mistral model
expect(configManager.currentModelDimension).toBe(1536)
expect(mockedGetModelDimension).toHaveBeenCalledWith("openrouter", "mistralai/codestral-embed-2505")

// Simulate restart by creating a new config manager with same configuration
const restartConfigManager = new CodeIndexConfigManager(mockContextProxy)
await restartConfigManager.loadConfiguration()

// After "restart", dimension should still be correct
expect(restartConfigManager.currentModelDimension).toBe(1536)
expect(restartConfigManager.isFeatureConfigured).toBe(true)
})

it("should not require restart for OpenRouter when same model dimensions are used", async () => {
// Mock both models to have same dimension
mockedGetModelDimension.mockImplementation((provider, modelId) => {
if (provider === "openrouter") {
if (modelId === "mistralai/codestral-embed-2505") return 1536
if (modelId === "openai/text-embedding-3-small") return 1536
}
return undefined
})

// Initial state with OpenRouter and Mistral model
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: true,
codebaseIndexEmbedderProvider: "openrouter",
codebaseIndexEmbedderModelId: "mistralai/codestral-embed-2505",
codebaseIndexQdrantUrl: "http://localhost:6333",
})
mockContextProxy.getSecret.mockImplementation((key: string) => {
if (key === "codebaseIndexOpenRouterApiKey") return "test-key"
if (key === "codeIndexQdrantApiKey") return "test-key"
return undefined
})

await configManager.loadConfiguration()

// Change to another model with same dimension
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: true,
codebaseIndexEmbedderProvider: "openrouter",
codebaseIndexEmbedderModelId: "openai/text-embedding-3-small", // Same 1536 dimension
codebaseIndexQdrantUrl: "http://localhost:6333",
})

const result = await configManager.loadConfiguration()
// Should NOT require restart since dimensions are the same
expect(result.requiresRestart).toBe(false)
})

it("should require restart for OpenRouter when model dimensions change", async () => {
// Mock models with different dimensions
mockedGetModelDimension.mockImplementation((provider, modelId) => {
if (provider === "openrouter") {
if (modelId === "mistralai/codestral-embed-2505") return 1536
if (modelId === "mistralai/mistral-embed-2312") return 1024
}
return undefined
})

// Initial state with 1536-dimension model
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: true,
codebaseIndexEmbedderProvider: "openrouter",
codebaseIndexEmbedderModelId: "mistralai/codestral-embed-2505",
codebaseIndexQdrantUrl: "http://localhost:6333",
})
mockContextProxy.getSecret.mockImplementation((key: string) => {
if (key === "codebaseIndexOpenRouterApiKey") return "test-key"
if (key === "codeIndexQdrantApiKey") return "test-key"
return undefined
})

await configManager.loadConfiguration()

// Change to model with different dimension
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: true,
codebaseIndexEmbedderProvider: "openrouter",
codebaseIndexEmbedderModelId: "mistralai/mistral-embed-2312", // Different 1024 dimension
codebaseIndexQdrantUrl: "http://localhost:6333",
})

const result = await configManager.loadConfiguration()
// Should require restart since dimensions changed
expect(result.requiresRestart).toBe(true)
})
})
})
})
})
2 changes: 1 addition & 1 deletion src/shared/embeddingModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export const EMBEDDING_MODEL_PROFILES: EmbeddingModelProfiles = {
"google/gemini-embedding-001": { dimension: 3072, scoreThreshold: 0.4 },
// Mistral models via OpenRouter
"mistralai/mistral-embed-2312": { dimension: 1024, scoreThreshold: 0.4 },
"mistralai/codestral-embed-2505": { dimension: 3072, scoreThreshold: 0.4 },
"mistralai/codestral-embed-2505": { dimension: 1536, scoreThreshold: 0.4 },
// Qwen models via OpenRouter
"qwen/qwen3-embedding-8b": { dimension: 4096, scoreThreshold: 0.4 },
},
Expand Down