Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

Commit 45cfeb4

Browse files
committed
fix: trim URL inputs and expand openai-compatible embedding model profiles
- Add input trimming for URL and identifier fields in CodeIndexPopover handleSaveSettings to prevent leading/trailing whitespace from causing silent authentication failures (Bug 3 from #12366) - Expand openai-compatible model profiles with popular third-party embedding models (Qwen, BAAI BGE, Nomic, Mixedbread) for better auto-dimension detection (Bug 2 from #12366) - Add tests for new model dimension lookups
1 parent e921f9d commit 45cfeb4

3 files changed

Lines changed: 48 additions & 2 deletions

File tree

src/shared/__tests__/embeddingModels.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,25 @@ describe("embeddingModels", () => {
5757
expect(getModelDimension("openai", "text-embedding-3-large")).toBe(3072)
5858
expect(getModelDimension("openai", "text-embedding-ada-002")).toBe(1536)
5959
})
60+
61+
it("should return correct dimensions for openai-compatible third-party models", () => {
62+
// Qwen models (commonly available on Featherless AI, Together AI, etc.)
63+
expect(getModelDimension("openai-compatible", "Qwen/Qwen3-Embedding-0.6B")).toBe(1024)
64+
expect(getModelDimension("openai-compatible", "Qwen/Qwen3-Embedding-4B")).toBe(2560)
65+
expect(getModelDimension("openai-compatible", "Qwen/Qwen3-Embedding-8B")).toBe(4096)
66+
// BAAI BGE models
67+
expect(getModelDimension("openai-compatible", "BAAI/bge-large-en-v1.5")).toBe(1024)
68+
expect(getModelDimension("openai-compatible", "BAAI/bge-base-en-v1.5")).toBe(768)
69+
expect(getModelDimension("openai-compatible", "BAAI/bge-small-en-v1.5")).toBe(384)
70+
// Nomic models
71+
expect(getModelDimension("openai-compatible", "nomic-embed-text")).toBe(768)
72+
// Mixedbread models
73+
expect(getModelDimension("openai-compatible", "mixedbread-ai/mxbai-embed-large-v1")).toBe(1024)
74+
})
75+
76+
it("should still return undefined for unknown models on openai-compatible", () => {
77+
expect(getModelDimension("openai-compatible", "some-unknown-model")).toBeUndefined()
78+
})
6079
})
6180

6281
describe("getModelScoreThreshold", () => {

src/shared/embeddingModels.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ export const EMBEDDING_MODEL_PROFILES: EmbeddingModelProfiles = {
3232
scoreThreshold: 0.15,
3333
queryPrefix: "Represent this query for searching relevant code: ",
3434
},
35+
// Nomic models (commonly available on third-party providers)
36+
"nomic-embed-text": { dimension: 768, scoreThreshold: 0.4 },
37+
"nomic-ai/nomic-embed-text-v1.5": { dimension: 768, scoreThreshold: 0.4 },
38+
// Qwen embedding models (Featherless AI, Together AI, etc.)
39+
"Qwen/Qwen3-Embedding-0.6B": { dimension: 1024, scoreThreshold: 0.4 },
40+
"Qwen/Qwen3-Embedding-4B": { dimension: 2560, scoreThreshold: 0.4 },
41+
"Qwen/Qwen3-Embedding-8B": { dimension: 4096, scoreThreshold: 0.4 },
42+
// BAAI BGE models (commonly self-hosted)
43+
"BAAI/bge-large-en-v1.5": { dimension: 1024, scoreThreshold: 0.4 },
44+
"BAAI/bge-base-en-v1.5": { dimension: 768, scoreThreshold: 0.4 },
45+
"BAAI/bge-small-en-v1.5": { dimension: 384, scoreThreshold: 0.4 },
46+
// Mixedbread models
47+
"mixedbread-ai/mxbai-embed-large-v1": { dimension: 1024, scoreThreshold: 0.4 },
3548
},
3649
gemini: {
3750
"gemini-embedding-001": { dimension: 3072, scoreThreshold: 0.4 },

webview-ui/src/components/chat/CodeIndexPopover.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,15 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
539539
// Prepare settings to save
540540
const settingsToSave: any = {}
541541

542+
// Keys whose string values should be trimmed before saving
543+
const trimKeys = new Set([
544+
"codebaseIndexQdrantUrl",
545+
"codebaseIndexEmbedderBaseUrl",
546+
"codebaseIndexOpenAiCompatibleBaseUrl",
547+
"codebaseIndexEmbedderModelId",
548+
"codebaseIndexQdrantApiKey",
549+
])
550+
542551
// Iterate through all current settings
543552
for (const [key, value] of Object.entries(currentSettings)) {
544553
// For secret fields with placeholder, don't send the placeholder
@@ -549,8 +558,13 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
549558
continue
550559
}
551560

552-
// Include all other fields, including empty strings (which clear secrets)
553-
settingsToSave[key] = value
561+
// Trim whitespace from URL and identifier fields to prevent silent failures
562+
if (trimKeys.has(key) && typeof value === "string") {
563+
settingsToSave[key] = value.trim()
564+
} else {
565+
// Include all other fields, including empty strings (which clear secrets)
566+
settingsToSave[key] = value
567+
}
554568
}
555569

556570
// Always include codebaseIndexEnabled to ensure it's persisted

0 commit comments

Comments
 (0)