Skip to content

Commit a80795b

Browse files
SannidhyaSahdaniel-lxsellipsis-dev[bot]
authored
feat: Add OpenAI Compatible embedder for codebase indexing (#4066)
* feat: Add OpenAI Compatible embedder for codebase indexing - Implement OpenAiCompatibleEmbedder with batching and retry logic - Add configuration support for base URL and API key - Update UI with provider selection and input fields - Add comprehensive test coverage - Support for all OpenAI-compatible endpoints (LiteLLM, LMStudio, Ollama, etc.) - Add internationalization for 17 languages * fix: Update CodeIndexSettings tests for OpenAI Compatible provider - Fix field count expectations (4 fields including Qdrant) - Use specific test IDs for button selection - Fix input handling with clear() before type() - Use toHaveBeenLastCalledWith for better assertions - Fix status text matching with regex pattern * fix: resolve UI test failures and ESLint errors - Remove unused waitFor import to fix ESLint error - Fix test expectations to match actual component behavior for input fields - Simplify provider selection test by removing complex mock interactions - All CodeIndexSettings tests now pass (20/20) * feat: add custom model infrastructure for OpenAI-compatible embedder - Add manual model ID and embedding dimension configuration - Enable custom model input via text field in settings UI - Add modelDimension parameter to OpenAiCompatibleEmbedder - Update configuration management to persist dimension setting - Prioritize manual dimension over hardcoded model profiles - Add comprehensive test coverage for new functionality This allows users to specify any custom embedding model and its dimension for OpenAI-compatible providers, removing dependency on hardcoded model profiles. * Add missing translations for OpenAI-compatible model dimension settings in all locales * refactor: remove unused modelDimension parameter from OpenAiCompatibleEmbedder - Remove modelDimension property and constructor parameter from OpenAiCompatibleEmbedder class - Update ServiceFactory to not pass dimension to embedder constructor - Update tests to match new constructor signature - The dimension is still used for QdrantVectorStore configuration * chore: bot suggestion Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * chore: bot suggestion Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * refactor: rename OpenAiCompatibleEmbedder to OpenAICompatibleEmbedder for consistency * feat: add model dimension validation for OpenAI-compatible settings * refactor: improve default model ID retrieval logic for embedding providers * feat: add default model ID retrieval for openai-compatible provider * refactor: update default model ID retrieval to use shared utility function * fix: Remove unnecessary type assertion in OpenAICompatibleEmbedder * feat: add model dimension input for openai-compatible provider --------- Co-authored-by: Daniel Riccio <[email protected]> Co-authored-by: Daniel <[email protected]> Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
1 parent f561208 commit a80795b

33 files changed

+2403
-50
lines changed

packages/types/src/__tests__/index.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,12 @@ describe("GLOBAL_STATE_KEYS", () => {
1414
it("should not contain secret state keys", () => {
1515
expect(GLOBAL_STATE_KEYS).not.toContain("openRouterApiKey")
1616
})
17+
18+
it("should contain OpenAI Compatible base URL setting", () => {
19+
expect(GLOBAL_STATE_KEYS).toContain("codebaseIndexOpenAiCompatibleBaseUrl")
20+
})
21+
22+
it("should not contain OpenAI Compatible API key (secret)", () => {
23+
expect(GLOBAL_STATE_KEYS).not.toContain("codebaseIndexOpenAiCompatibleApiKey")
24+
})
1725
})

packages/types/src/codebase-index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { z } from "zod"
77
export const codebaseIndexConfigSchema = z.object({
88
codebaseIndexEnabled: z.boolean().optional(),
99
codebaseIndexQdrantUrl: z.string().optional(),
10-
codebaseIndexEmbedderProvider: z.enum(["openai", "ollama"]).optional(),
10+
codebaseIndexEmbedderProvider: z.enum(["openai", "ollama", "openai-compatible"]).optional(),
1111
codebaseIndexEmbedderBaseUrl: z.string().optional(),
1212
codebaseIndexEmbedderModelId: z.string().optional(),
1313
})
@@ -21,6 +21,7 @@ export type CodebaseIndexConfig = z.infer<typeof codebaseIndexConfigSchema>
2121
export const codebaseIndexModelsSchema = z.object({
2222
openai: z.record(z.string(), z.object({ dimension: z.number() })).optional(),
2323
ollama: z.record(z.string(), z.object({ dimension: z.number() })).optional(),
24+
"openai-compatible": z.record(z.string(), z.object({ dimension: z.number() })).optional(),
2425
})
2526

2627
export type CodebaseIndexModels = z.infer<typeof codebaseIndexModelsSchema>
@@ -32,6 +33,9 @@ export type CodebaseIndexModels = z.infer<typeof codebaseIndexModelsSchema>
3233
export const codebaseIndexProviderSchema = z.object({
3334
codeIndexOpenAiKey: z.string().optional(),
3435
codeIndexQdrantApiKey: z.string().optional(),
36+
codebaseIndexOpenAiCompatibleBaseUrl: z.string().optional(),
37+
codebaseIndexOpenAiCompatibleApiKey: z.string().optional(),
38+
codebaseIndexOpenAiCompatibleModelDimension: z.number().optional(),
3539
})
3640

3741
export type CodebaseIndexProvider = z.infer<typeof codebaseIndexProviderSchema>

packages/types/src/global-settings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ export type SecretState = Pick<
223223
| "litellmApiKey"
224224
| "codeIndexOpenAiKey"
225225
| "codeIndexQdrantApiKey"
226+
| "codebaseIndexOpenAiCompatibleApiKey"
226227
>
227228

228229
export const SECRET_STATE_KEYS = keysOf<SecretState>()([
@@ -245,6 +246,7 @@ export const SECRET_STATE_KEYS = keysOf<SecretState>()([
245246
"litellmApiKey",
246247
"codeIndexOpenAiKey",
247248
"codeIndexQdrantApiKey",
249+
"codebaseIndexOpenAiCompatibleApiKey",
248250
])
249251

250252
export const isSecretStateKey = (key: string): key is Keys<SecretState> =>

packages/types/src/provider-settings.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,9 @@ export const PROVIDER_SETTINGS_KEYS = keysOf<ProviderSettings>()([
336336
// Code Index
337337
"codeIndexOpenAiKey",
338338
"codeIndexQdrantApiKey",
339+
"codebaseIndexOpenAiCompatibleBaseUrl",
340+
"codebaseIndexOpenAiCompatibleApiKey",
341+
"codebaseIndexOpenAiCompatibleModelDimension",
339342
// Reasoning
340343
"enableReasoningEffort",
341344
"reasoningEffort",

0 commit comments

Comments
 (0)