@@ -546,6 +546,76 @@ describe("ModelResolver", () => {
546546 } ) ,
547547 )
548548
549+ it . effect ( "routes supported AISDK catalog packages through native provider packages" , ( ) =>
550+ Effect . gen ( function * ( ) {
551+ const native = yield * ModelResolver . fromCatalogModel ( model ( Provider . aisdk ( "@ai-sdk/openai" ) ) )
552+ const packages = [
553+ [ "@ai-sdk/google" , "@opencode-ai/ai/providers/google" , "gemini" ] ,
554+ [ "@openrouter/ai-sdk-provider" , "@opencode-ai/ai/providers/openrouter" , "openrouter" ] ,
555+ [ "@ai-sdk/xai" , "@opencode-ai/ai/providers/xai" , "xai" ] ,
556+ ] as const
557+
558+ yield * Effect . forEach ( packages , ( [ catalogPackage , nativePackage , optionKey ] ) =>
559+ ModelResolver . fromCatalogModel (
560+ model ( Provider . aisdk ( catalogPackage ) , {
561+ modelID : "api-model" ,
562+ settings : { baseURL : "https://provider.example/v1" , reasoningEffort : "high" } ,
563+ headers : { "x-provider" : "header" } ,
564+ body : { custom : true } ,
565+ } ) ,
566+ Credential . Key . make ( { type : "key" , key : "secret" } ) ,
567+ {
568+ loadPackage : ( specifier ) => {
569+ expect ( specifier ) . toBe ( nativePackage )
570+ return Effect . succeed ( {
571+ model : ( modelID , settings ) => {
572+ expect ( modelID ) . toBe ( "api-model" )
573+ expect ( settings ) . toMatchObject ( {
574+ apiKey : "secret" ,
575+ baseURL : "https://provider.example/v1" ,
576+ headers : { "x-provider" : "header" } ,
577+ body : { custom : true } ,
578+ limits : { context : 100 , output : 20 } ,
579+ providerOptions : { [ optionKey ] : { reasoningEffort : "high" } } ,
580+ } )
581+ return Model . make ( { id : modelID , provider : "native-provider" , route : native . route } )
582+ } ,
583+ } )
584+ } ,
585+ loadAISDK : ( ) => Effect . die ( "AI SDK loader should not be called" ) ,
586+ } ,
587+ ) ,
588+ )
589+ } ) ,
590+ )
591+
592+ it . effect ( "loads supported AISDK catalog packages as native routes" , ( ) =>
593+ Effect . gen ( function * ( ) {
594+ const google = yield * ModelResolver . fromCatalogModel (
595+ model ( Provider . aisdk ( "@ai-sdk/google" ) , { settings : { thinkingConfig : { thinkingBudget : 1_024 } } } ) ,
596+ )
597+ const openrouter = yield * ModelResolver . fromCatalogModel (
598+ model ( Provider . aisdk ( "@openrouter/ai-sdk-provider" ) , {
599+ settings : { reasoning : { effort : "high" } } ,
600+ } ) ,
601+ )
602+ const xai = yield * ModelResolver . fromCatalogModel (
603+ model ( Provider . aisdk ( "@ai-sdk/xai" ) , { settings : { reasoningEffort : "high" } } ) ,
604+ )
605+
606+ expect ( google . route . id ) . toBe ( "gemini" )
607+ expect ( google . route . defaults . providerOptions ) . toEqual ( {
608+ gemini : { thinkingConfig : { thinkingBudget : 1_024 } } ,
609+ } )
610+ expect ( openrouter . route . id ) . toBe ( "openrouter" )
611+ expect ( openrouter . route . defaults . providerOptions ) . toEqual ( { openrouter : { reasoning : { effort : "high" } } } )
612+ expect ( xai . route . id ) . toBe ( "openai-responses" )
613+ expect ( xai . route . defaults . providerOptions ) . toEqual ( {
614+ xai : { reasoningEffort : "high" , store : false } ,
615+ } )
616+ } ) ,
617+ )
618+
549619 it . effect ( "loads arbitrary AISDK packages through the injected AISDK loader" , ( ) =>
550620 Effect . gen ( function * ( ) {
551621 const native = yield * ModelResolver . fromCatalogModel (
@@ -554,8 +624,8 @@ describe("ModelResolver", () => {
554624 } ) ,
555625 )
556626 const resolved = yield * ModelResolver . fromCatalogModel (
557- model ( Provider . aisdk ( "@ai-sdk/google " ) , {
558- modelID : "gemini -api-model" ,
627+ model ( Provider . aisdk ( "@ai-sdk/mistral " ) , {
628+ modelID : "mistral -api-model" ,
559629 settings : { project : "test" } ,
560630 headers : { "x-aisdk" : "header" } ,
561631 body : { custom : true } ,
@@ -566,9 +636,9 @@ describe("ModelResolver", () => {
566636 Effect . sync ( ( ) => {
567637 expect ( runtime ) . toMatchObject ( {
568638 id : "test-model" ,
569- modelID : "gemini -api-model" ,
639+ modelID : "mistral -api-model" ,
570640 providerID : "test-provider" ,
571- package : Provider . aisdk ( "@ai-sdk/google " ) ,
641+ package : Provider . aisdk ( "@ai-sdk/mistral " ) ,
572642 settings : { project : "test" , apiKey : "fallback-secret" } ,
573643 headers : { "x-aisdk" : "header" } ,
574644 body : { custom : true } ,
@@ -582,25 +652,25 @@ describe("ModelResolver", () => {
582652 } ,
583653 )
584654
585- expect ( resolved ) . toMatchObject ( { id : "gemini -api-model" , provider : "test-provider" } )
655+ expect ( resolved ) . toMatchObject ( { id : "mistral -api-model" , provider : "test-provider" } )
586656 } ) ,
587657 )
588658
589659 it . effect ( "rejects AISDK packages without an available loader" , ( ) =>
590660 Effect . gen ( function * ( ) {
591661 const failure = yield * ModelResolver . fromCatalogModel (
592- model ( Provider . aisdk ( "@ai-sdk/google " ) , {
593- settings : { baseURL : "https://google .example/v1" } ,
662+ model ( Provider . aisdk ( "@ai-sdk/mistral " ) , {
663+ settings : { baseURL : "https://mistral .example/v1" } ,
594664 } ) ,
595665 ) . pipe ( Effect . flip )
596666
597667 expect ( failure ) . toMatchObject ( {
598668 _tag : "SessionRunnerModel.UnsupportedPackageError" ,
599669 providerID : "test-provider" ,
600670 modelID : "test-model" ,
601- package : "aisdk:@ai-sdk/google " ,
671+ package : "aisdk:@ai-sdk/mistral " ,
602672 } )
603- expect ( failure . message ) . toBe ( "Unsupported package for test-provider/test-model: aisdk:@ai-sdk/google " )
673+ expect ( failure . message ) . toBe ( "Unsupported package for test-provider/test-model: aisdk:@ai-sdk/mistral " )
604674 } ) ,
605675 )
606676
@@ -612,8 +682,8 @@ describe("ModelResolver", () => {
612682 } ) ,
613683 )
614684 yield * ModelResolver . fromCatalogModel (
615- model ( Provider . aisdk ( "@ai-sdk/google " ) , {
616- settings : { apiKey : "" , baseURL : "https://google .example/v1" } ,
685+ model ( Provider . aisdk ( "@ai-sdk/mistral " ) , {
686+ settings : { apiKey : "" , baseURL : "https://mistral .example/v1" } ,
617687 } ) ,
618688 undefined ,
619689 {
0 commit comments