-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Description
Problem (one or two sentences)
Users configuring OpenRouter embeddings for code indexing cannot select specific routing providers, forcing them to accept OpenRouter's automatic routing which may select providers with significantly higher costs (up to 4-5x price difference).
Context (who is affected and when)
Anyone using OpenRouter's embedding models for code indexing. The pricing disparity becomes critical when processing large codebases - some OpenRouter embedding providers cost 400-500% more than others for the same embedding model. This affects:
- Users on budget constraints who need cost-effective embedding providers
- Teams processing large repositories where embedding costs accumulate
- Users wanting consistency with their chat completion provider choice (which already has routing selection)
Desired behavior (conceptual, not technical)
When configuring OpenRouter embeddings in code indexing settings, users should be able to select a specific routing provider (similar to how they can select providers for chat completions). The system should respect this choice when creating embeddings, ensuring predictable costs and consistent provider selection.
Constraints / preferences (optional)
- Must maintain backwards compatibility with existing configurations (default to automatic routing if not specified)
- Should follow the same pattern as chat completion provider routing for consistency
- UI/UX should match the existing OpenRouter provider selector in chat settings
- No breaking changes to existing embedder API contracts
Request checklist
- I've searched existing Issues and Discussions for duplicates
- This describes a specific problem with clear context and impact
Roo Code Task Links (optional)
N/A
Acceptance criteria (optional)
Given a user has OpenRouter configured as their embedding provider
When they open code indexing settings
Then they should see a "Routing Provider" dropdown/selector (similar to chat completion settings)
And selecting a specific provider should pass that provider preference to the OpenRouter embedding API
And leaving it as "[default]" should maintain current behavior (automatic routing)
But existing configurations without this setting should continue working unchanged
Proposed approach (optional)
Following the existing pattern from chat completions:
-
Reuse existing configuration flow:
- Similar to how
openRouterSpecificProviderworks for chat (src/api/providers/openrouter.ts:154-161), add optional provider parameter toOpenRouterEmbedderconstructor (src/services/code-index/embedders/openrouter.ts:58-82) - Currently only takes
(apiKey, modelId?, maxItemTokens?)- extend to include optional provider
- Similar to how
-
Configuration chain updates:
CodeIndexConfigManager(src/services/code-index/config-manager.ts:136) loadsopenRouterOptions = { apiKey }- extend to include providerCodeIndexServiceFactory(src/services/code-index/service-factory.ts:87) passes provider to embedder constructor
-
Embedder implementation:
- Mirror the provider routing logic from chat completion (lines 154-161 in openrouter.ts)
- Add provider object with
order,only, andallow_fallbacksto embedding API calls
-
UI/Settings:
- Add new setting field for OpenRouter embedding provider selection
- Reuse existing provider endpoint fetching if applicable
-
Testing:
- Extend existing tests in src/services/code-index/embedders/tests/openrouter.spec.ts
- Test with provider specified
- Test backwards compatibility (undefined provider)
Trade-offs / risks (optional)
Backwards Compatibility: Fully maintained - optional parameter defaults to undefined, preserving current auto-routing behavior
Risks: Minimal. Potential for users to select providers that don't support their chosen embedding model, but this is the same risk that exists for chat completions.
Alternative Considered: Could implement provider filtering/validation, but that adds complexity. Better to match chat completion's approach and let OpenRouter's API handle invalid combinations.
🔍 Comprehensive Issue Scoping
Implementation Target
Enable provider routing for OpenRouter embeddings by extending the existing configuration chain to pass an optional provider preference through to the OpenRouter API, mirroring the proven pattern from chat completions.
Affected Components
Primary Files:
src/services/code-index/embedders/openrouter.ts(lines 58-82) - Constructor and embedding creation methodsrc/services/code-index/config-manager.ts(lines 23-136) - Configuration loadingsrc/services/code-index/service-factory.ts(lines 83-88) - Embedder instantiation- Settings UI component (location TBD) - Provider selection dropdown
Secondary Impact:
src/services/code-index/embedders/__tests__/openrouter.spec.ts- Test coveragesrc/services/code-index/interfaces/config.ts(lines 7-23) - Type definitions- Package.json settings schema - New setting definition
Current Implementation Analysis
Chat Completion (HAS provider routing):
// src/api/providers/openrouter.ts:154-161
...(this.options.openRouterSpecificProvider &&
this.options.openRouterSpecificProvider !== OPENROUTER_DEFAULT_PROVIDER_NAME && {
provider: {
order: [this.options.openRouterSpecificProvider],
only: [this.options.openRouterSpecificProvider],
allow_fallbacks: false,
}
})Embeddings (LACKS provider routing):
// src/services/code-index/embedders/openrouter.ts:58-82
constructor(apiKey: string, modelId?: string, maxItemTokens?: number) {
// Only accepts apiKey, modelId, maxItemTokens
// No provider parameter
}
// src/services/code-index/config-manager.ts:136
this.openRouterOptions = openRouterApiKey ? { apiKey: openRouterApiKey } : undefined
// Only stores apiKey
// src/services/code-index/service-factory.ts:87
return new OpenRouterEmbedder(config.openRouterOptions.apiKey, config.modelId)
// Only passes apiKey and modelIdThe pattern from chat completions shows exactly how to implement this. The chat handler passes the provider parameter through to the API request, setting provider.order and provider.only arrays with the specific provider when configured.
Proposed Implementation
Step 1: Extend OpenRouterEmbedder constructor
- File:
src/services/code-index/embedders/openrouter.ts - Changes: Add optional
specificProvider?: stringparameter to constructor (line 58) - Rationale: Mirror chat completion pattern, maintain backwards compatibility
Step 2: Store provider in instance variable
- File:
src/services/code-index/embedders/openrouter.ts - Changes: Add
private readonly specificProvider?: stringproperty, set in constructor - Rationale: Need to access provider value in embedding creation methods
Step 3: Apply provider routing in API calls
- File:
src/services/code-index/embedders/openrouter.ts - Changes: In
_embedBatchWithRetriesmethod (lines 183-190), add provider object conditionally (mirror lines 154-161 from chat) - Rationale: This is where the actual API call happens
Step 4: Update configuration interface
- File:
src/services/code-index/interfaces/config.ts - Changes: Extend
CodeIndexConfig.openRouterOptionsfrom{ apiKey: string }to{ apiKey: string; specificProvider?: string } - Rationale: Type safety for configuration chain
Step 5: Update config manager to load provider
- File:
src/services/code-index/config-manager.ts - Changes: Line 136 - load provider from settings and include in
openRouterOptions - Rationale: Configuration chain needs to pass provider through
Step 6: Update service factory
- File:
src/services/code-index/service-factory.ts - Changes: Line 87 - pass provider to OpenRouterEmbedder constructor
- Rationale: Connect configuration to embedder instantiation
Step 7: Add UI setting
- File: Package.json and settings UI (exact location TBD)
- Changes: Add
codebaseIndexOpenRouterSpecificProvidersetting (similar to chat'sopenRouterSpecificProvider) - Rationale: User needs way to configure provider
Step 8: Add tests
- File:
src/services/code-index/embedders/__tests__/openrouter.spec.ts - Changes: Test cases for provider specified and undefined (backwards compat)
- Rationale: Ensure feature works and doesn't break existing functionality
Code Architecture Considerations
- Follow existing OpenRouter chat completion pattern exactly
- Maintain full backwards compatibility (optional parameter)
- No changes to public embedder interface (IEmbedder)
- Reuse existing configuration architecture
Testing Requirements
-
Unit Tests:
- Test OpenRouterEmbedder with provider specified
- Test OpenRouterEmbedder without provider (backwards compat)
- Test provider=[default] behavior
- Test provider value flows through config chain
-
Integration Tests:
- Verify embedding API calls include provider object when configured
- Verify embedding API calls exclude provider object when not configured
-
Edge Cases:
- Provider string validation (empty string handling)
- Invalid provider names (let OpenRouter API handle)
- Config migration from old to new format
Performance Impact
- Expected change: Neutral
- Benchmarking: No - only adds optional parameter
- Optimization: None needed
Security Considerations
- No authentication/authorization changes
- No new data exposure risks
- Provider value is user-controlled string - validated by OpenRouter API
Migration Strategy
Fully backwards compatible - no migration needed:
- Existing configs continue working (provider parameter optional/undefined)
- New configs can opt into provider routing
- Default behavior unchanged
Rollback Plan
If issues arise:
- Remove provider parameter from embedder calls
- Revert configuration chain changes
- No database/storage changes to roll back
Dependencies and Breaking Changes
External Dependencies: None - uses existing OpenAI SDK patterns
API Contract Changes: None - purely additive (optional parameter)
Breaking Changes: None - fully backwards compatible
Metadata
Metadata
Assignees
Labels
Type
Projects
Status