Skip to content

Commit 34f45f1

Browse files
dmarkeydaniel-lxs
andauthored
feat: add OpenRouter embedding provider support (#8973)
* feat: add OpenRouter embedding provider support Implement comprehensive OpenRouter embedding provider support for codebase indexing with the following features: - New OpenRouterEmbedder class with full API compatibility - Support for OpenRouter's OpenAI-compatible embedding endpoint - Rate limiting and retry logic with exponential backoff - Base64 embedding handling to bypass OpenAI package limitations - Global rate limit state management across embedder instances - Configuration updates for API key storage and provider selection - UI integration for OpenRouter provider settings - Comprehensive test suite with mocking - Model dimension support for OpenRouter's embedding models This adds OpenRouter as the 7th supported embedding provider alongside OpenAI, Ollama, OpenAI-compatible, Gemini, Mistral, and Vercel AI Gateway. * Add translation key * Fix mutex double release bug * Add translations * Add more translations * Fix failing tests * code-index(openrouter): fix HTTP-Referer header to RooCodeInc/Roo-Code; i18n: add and wire OpenRouter Code Index strings; test: assert default headers in embedder --------- Co-authored-by: daniel-lxs <[email protected]>
1 parent d0e519d commit 34f45f1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+965
-22
lines changed

packages/types/src/codebase-index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const codebaseIndexConfigSchema = z.object({
2222
codebaseIndexEnabled: z.boolean().optional(),
2323
codebaseIndexQdrantUrl: z.string().optional(),
2424
codebaseIndexEmbedderProvider: z
25-
.enum(["openai", "ollama", "openai-compatible", "gemini", "mistral", "vercel-ai-gateway"])
25+
.enum(["openai", "ollama", "openai-compatible", "gemini", "mistral", "vercel-ai-gateway", "openrouter"])
2626
.optional(),
2727
codebaseIndexEmbedderBaseUrl: z.string().optional(),
2828
codebaseIndexEmbedderModelId: z.string().optional(),
@@ -51,6 +51,7 @@ export const codebaseIndexModelsSchema = z.object({
5151
gemini: z.record(z.string(), z.object({ dimension: z.number() })).optional(),
5252
mistral: z.record(z.string(), z.object({ dimension: z.number() })).optional(),
5353
"vercel-ai-gateway": z.record(z.string(), z.object({ dimension: z.number() })).optional(),
54+
openrouter: z.record(z.string(), z.object({ dimension: z.number() })).optional(),
5455
})
5556

5657
export type CodebaseIndexModels = z.infer<typeof codebaseIndexModelsSchema>
@@ -68,6 +69,7 @@ export const codebaseIndexProviderSchema = z.object({
6869
codebaseIndexGeminiApiKey: z.string().optional(),
6970
codebaseIndexMistralApiKey: z.string().optional(),
7071
codebaseIndexVercelAiGatewayApiKey: z.string().optional(),
72+
codebaseIndexOpenRouterApiKey: z.string().optional(),
7173
})
7274

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

packages/types/src/global-settings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ export const SECRET_STATE_KEYS = [
232232
"codebaseIndexGeminiApiKey",
233233
"codebaseIndexMistralApiKey",
234234
"codebaseIndexVercelAiGatewayApiKey",
235+
"codebaseIndexOpenRouterApiKey",
235236
"huggingFaceApiKey",
236237
"sambaNovaApiKey",
237238
"zaiApiKey",

src/core/webview/webviewMessageHandler.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2556,6 +2556,12 @@ export const webviewMessageHandler = async (
25562556
settings.codebaseIndexVercelAiGatewayApiKey,
25572557
)
25582558
}
2559+
if (settings.codebaseIndexOpenRouterApiKey !== undefined) {
2560+
await provider.contextProxy.storeSecret(
2561+
"codebaseIndexOpenRouterApiKey",
2562+
settings.codebaseIndexOpenRouterApiKey,
2563+
)
2564+
}
25592565

25602566
// Send success response first - settings are saved regardless of validation
25612567
await provider.postMessageToWebview({
@@ -2693,6 +2699,7 @@ export const webviewMessageHandler = async (
26932699
const hasVercelAiGatewayApiKey = !!(await provider.context.secrets.get(
26942700
"codebaseIndexVercelAiGatewayApiKey",
26952701
))
2702+
const hasOpenRouterApiKey = !!(await provider.context.secrets.get("codebaseIndexOpenRouterApiKey"))
26962703

26972704
provider.postMessageToWebview({
26982705
type: "codeIndexSecretStatus",
@@ -2703,6 +2710,7 @@ export const webviewMessageHandler = async (
27032710
hasGeminiApiKey,
27042711
hasMistralApiKey,
27052712
hasVercelAiGatewayApiKey,
2713+
hasOpenRouterApiKey,
27062714
},
27072715
})
27082716
break

src/i18n/locales/ca/embeddings.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/de/embeddings.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/en/embeddings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"openAiCompatibleConfigMissing": "OpenAI Compatible configuration missing for embedder creation",
4848
"geminiConfigMissing": "Gemini configuration missing for embedder creation",
4949
"mistralConfigMissing": "Mistral configuration missing for embedder creation",
50+
"openRouterConfigMissing": "OpenRouter configuration missing for embedder creation",
5051
"vercelAiGatewayConfigMissing": "Vercel AI Gateway configuration missing for embedder creation",
5152
"invalidEmbedderType": "Invalid embedder type configured: {{embedderProvider}}",
5253
"vectorDimensionNotDeterminedOpenAiCompatible": "Could not determine vector dimension for model '{{modelId}}' with provider '{{provider}}'. Please ensure the 'Embedding Dimension' is correctly set in the OpenAI-Compatible provider settings.",

src/i18n/locales/es/embeddings.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/fr/embeddings.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/hi/embeddings.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/id/embeddings.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)