@@ -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