Skip to content

Commit e09d1ef

Browse files
committed
🤖 refactor: flatten OpenRouter provider config (remove nested 'provider' key)
- Support both flat and nested config formats for backwards compatibility - New flat format: { order: [...], allow_fallbacks: false } - Old nested format: { provider: { order: [...], ... } } still works - Update docs to show simpler flat format - Routing options automatically wrapped under 'provider' for API Resolves unnecessary nesting in user configuration.
1 parent 7e210e0 commit e09d1ef

File tree

2 files changed

+49
-11
lines changed

2 files changed

+49
-11
lines changed

‎docs/models.md‎

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,8 @@ OpenRouter can route requests to specific infrastructure providers (Cerebras, Fi
6060
"openrouter": {
6161
"apiKey": "sk-or-v1-...",
6262
// Use Cerebras for ultra-fast inference
63-
"provider": {
64-
"order": ["Cerebras", "Fireworks"], // Try in order
65-
"allow_fallbacks": true // Allow other providers if unavailable
66-
}
63+
"order": ["Cerebras", "Fireworks"], // Try in order
64+
"allow_fallbacks": true // Allow other providers if unavailable
6765
}
6866
}
6967
```
@@ -74,10 +72,8 @@ Or require a specific provider (no fallbacks):
7472
{
7573
"openrouter": {
7674
"apiKey": "sk-or-v1-...",
77-
"provider": {
78-
"order": ["Cerebras"], // Only try Cerebras
79-
"allow_fallbacks": false // Fail if Cerebras unavailable
80-
}
75+
"order": ["Cerebras"], // Only try Cerebras
76+
"allow_fallbacks": false // Fail if Cerebras unavailable
8177
}
8278
}
8379
```
@@ -93,6 +89,8 @@ Or require a specific provider (no fallbacks):
9389

9490
See [OpenRouter Provider Routing docs](https://openrouter.ai/docs/features/provider-routing) for details.
9591

92+
**Note:** The old nested format with `"provider": { ... }` is still supported for backwards compatibility.
93+
9694
**Reasoning Models:**
9795

9896
OpenRouter supports reasoning models like Claude Sonnet Thinking. Use the thinking slider to control reasoning effort:

‎src/services/aiService.ts‎

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,50 @@ export class AIService extends EventEmitter {
432432
: defaultFetchWithUnlimitedTimeout;
433433

434434
// Extract standard provider settings (apiKey, baseUrl, headers, fetch)
435-
// and move everything else to extraBody for transparent pass-through
436435
const { apiKey, baseUrl, headers, fetch: _fetch, ...extraOptions } = providerConfig;
437436

437+
// OpenRouter routing options that need to be nested under "provider" in API request
438+
// See: https://openrouter.ai/docs/features/provider-routing
439+
const OPENROUTER_ROUTING_OPTIONS = [
440+
"order",
441+
"allow_fallbacks",
442+
"only",
443+
"ignore",
444+
"require_parameters",
445+
"data_collection",
446+
"sort",
447+
"quantizations",
448+
];
449+
450+
// Build extraBody, supporting both flat and nested config formats
451+
let extraBody: Record<string, unknown> | undefined;
452+
453+
if ("provider" in extraOptions && typeof extraOptions.provider === "object") {
454+
// Old nested format: { provider: { order: [...], ... } }
455+
// Pass through as-is for backwards compatibility
456+
extraBody = extraOptions;
457+
} else {
458+
// New flat format: { order: [...], allow_fallbacks: false, ... }
459+
// Restructure: routing options go under "provider", others stay at root
460+
const routingOptions: Record<string, unknown> = {};
461+
const otherOptions: Record<string, unknown> = {};
462+
463+
for (const [key, value] of Object.entries(extraOptions)) {
464+
if (OPENROUTER_ROUTING_OPTIONS.includes(key)) {
465+
routingOptions[key] = value;
466+
} else {
467+
otherOptions[key] = value;
468+
}
469+
}
470+
471+
// Build extraBody with provider nesting if routing options exist
472+
if (Object.keys(routingOptions).length > 0) {
473+
extraBody = { provider: routingOptions, ...otherOptions };
474+
} else if (Object.keys(otherOptions).length > 0) {
475+
extraBody = otherOptions;
476+
}
477+
}
478+
438479
// Lazy-load OpenRouter provider to reduce startup time
439480
const { createOpenRouter } = await import("@openrouter/ai-sdk-provider");
440481
const provider = createOpenRouter({
@@ -443,8 +484,7 @@ export class AIService extends EventEmitter {
443484
headers: headers as Record<string, string> | undefined,
444485
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
445486
fetch: baseFetch as any,
446-
// Pass all additional config options (like provider routing) via extraBody
447-
extraBody: Object.keys(extraOptions).length > 0 ? extraOptions : undefined,
487+
extraBody,
448488
});
449489
return Ok(provider(modelId));
450490
}

0 commit comments

Comments
 (0)