Skip to content
Draft
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
19 changes: 19 additions & 0 deletions src/shared/__tests__/embeddingModels.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,25 @@ describe("embeddingModels", () => {
expect(getModelDimension("openai", "text-embedding-3-large")).toBe(3072)
expect(getModelDimension("openai", "text-embedding-ada-002")).toBe(1536)
})

it("should return correct dimensions for openai-compatible third-party models", () => {
// Qwen models (commonly available on Featherless AI, Together AI, etc.)
expect(getModelDimension("openai-compatible", "Qwen/Qwen3-Embedding-0.6B")).toBe(1024)
expect(getModelDimension("openai-compatible", "Qwen/Qwen3-Embedding-4B")).toBe(2560)
expect(getModelDimension("openai-compatible", "Qwen/Qwen3-Embedding-8B")).toBe(4096)
// BAAI BGE models
expect(getModelDimension("openai-compatible", "BAAI/bge-large-en-v1.5")).toBe(1024)
expect(getModelDimension("openai-compatible", "BAAI/bge-base-en-v1.5")).toBe(768)
expect(getModelDimension("openai-compatible", "BAAI/bge-small-en-v1.5")).toBe(384)
// Nomic models
expect(getModelDimension("openai-compatible", "nomic-embed-text")).toBe(768)
// Mixedbread models
expect(getModelDimension("openai-compatible", "mixedbread-ai/mxbai-embed-large-v1")).toBe(1024)
})

it("should still return undefined for unknown models on openai-compatible", () => {
expect(getModelDimension("openai-compatible", "some-unknown-model")).toBeUndefined()
})
})

describe("getModelScoreThreshold", () => {
Expand Down
13 changes: 13 additions & 0 deletions src/shared/embeddingModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ export const EMBEDDING_MODEL_PROFILES: EmbeddingModelProfiles = {
scoreThreshold: 0.15,
queryPrefix: "Represent this query for searching relevant code: ",
},
// Nomic models (commonly available on third-party providers)
"nomic-embed-text": { dimension: 768, scoreThreshold: 0.4 },
"nomic-ai/nomic-embed-text-v1.5": { dimension: 768, scoreThreshold: 0.4 },
// Qwen embedding models (Featherless AI, Together AI, etc.)
"Qwen/Qwen3-Embedding-0.6B": { dimension: 1024, scoreThreshold: 0.4 },
"Qwen/Qwen3-Embedding-4B": { dimension: 2560, scoreThreshold: 0.4 },
"Qwen/Qwen3-Embedding-8B": { dimension: 4096, scoreThreshold: 0.4 },
// BAAI BGE models (commonly self-hosted)
"BAAI/bge-large-en-v1.5": { dimension: 1024, scoreThreshold: 0.4 },
"BAAI/bge-base-en-v1.5": { dimension: 768, scoreThreshold: 0.4 },
"BAAI/bge-small-en-v1.5": { dimension: 384, scoreThreshold: 0.4 },
// Mixedbread models
"mixedbread-ai/mxbai-embed-large-v1": { dimension: 1024, scoreThreshold: 0.4 },
},
gemini: {
"gemini-embedding-001": { dimension: 3072, scoreThreshold: 0.4 },
Expand Down
18 changes: 16 additions & 2 deletions webview-ui/src/components/chat/CodeIndexPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,15 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
// Prepare settings to save
const settingsToSave: any = {}

// Keys whose string values should be trimmed before saving
const trimKeys = new Set([
"codebaseIndexQdrantUrl",
"codebaseIndexEmbedderBaseUrl",
"codebaseIndexOpenAiCompatibleBaseUrl",
"codebaseIndexEmbedderModelId",
"codebaseIndexQdrantApiKey",
])

// Iterate through all current settings
for (const [key, value] of Object.entries(currentSettings)) {
// For secret fields with placeholder, don't send the placeholder
Expand All @@ -549,8 +558,13 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
continue
}

// Include all other fields, including empty strings (which clear secrets)
settingsToSave[key] = value
// Trim whitespace from URL and identifier fields to prevent silent failures
if (trimKeys.has(key) && typeof value === "string") {
settingsToSave[key] = value.trim()
} else {
// Include all other fields, including empty strings (which clear secrets)
settingsToSave[key] = value
}
}

// Always include codebaseIndexEnabled to ensure it's persisted
Expand Down
Loading