@@ -725,4 +725,100 @@ describe("useSelectedModel", () => {
725725 expect ( result . current . info ) . toEqual ( customModelInfo )
726726 } )
727727 } )
728+
729+ describe ( "openai provider" , ( ) => {
730+ beforeEach ( ( ) => {
731+ mockUseRouterModels . mockReturnValue ( {
732+ data : {
733+ openrouter : { } ,
734+ requesty : { } ,
735+ unbound : { } ,
736+ litellm : { } ,
737+ "io-intelligence" : { } ,
738+ } ,
739+ isLoading : false ,
740+ isError : false ,
741+ } as any )
742+
743+ mockUseOpenRouterModelProviders . mockReturnValue ( {
744+ data : { } ,
745+ isLoading : false ,
746+ isError : false ,
747+ } as any )
748+ } )
749+
750+ it ( "should use openAiModelInfoSaneDefaults when no custom model info is provided" , ( ) => {
751+ const apiConfiguration : ProviderSettings = {
752+ apiProvider : "openai" ,
753+ openAiModelId : "gpt-4o" ,
754+ }
755+
756+ const wrapper = createWrapper ( )
757+ const { result } = renderHook ( ( ) => useSelectedModel ( apiConfiguration ) , { wrapper } )
758+
759+ expect ( result . current . provider ) . toBe ( "openai" )
760+ expect ( result . current . id ) . toBe ( "gpt-4o" )
761+ expect ( result . current . info ) . toEqual ( openAiModelInfoSaneDefaults )
762+ expect ( result . current . info ?. supportsNativeTools ) . toBe ( true )
763+ expect ( result . current . info ?. defaultToolProtocol ) . toBe ( "native" )
764+ } )
765+
766+ it ( "should merge native tool defaults with custom model info" , ( ) => {
767+ const customModelInfo : ModelInfo = {
768+ maxTokens : 16384 ,
769+ contextWindow : 128000 ,
770+ supportsImages : true ,
771+ supportsPromptCache : false ,
772+ inputPrice : 0.01 ,
773+ outputPrice : 0.03 ,
774+ description : "Custom OpenAI-compatible model" ,
775+ }
776+
777+ const apiConfiguration : ProviderSettings = {
778+ apiProvider : "openai" ,
779+ openAiModelId : "custom-model" ,
780+ openAiCustomModelInfo : customModelInfo ,
781+ }
782+
783+ const wrapper = createWrapper ( )
784+ const { result } = renderHook ( ( ) => useSelectedModel ( apiConfiguration ) , { wrapper } )
785+
786+ expect ( result . current . provider ) . toBe ( "openai" )
787+ expect ( result . current . id ) . toBe ( "custom-model" )
788+ // Should merge native tool defaults with custom model info
789+ const nativeToolDefaults = {
790+ supportsNativeTools : openAiModelInfoSaneDefaults . supportsNativeTools ,
791+ defaultToolProtocol : openAiModelInfoSaneDefaults . defaultToolProtocol ,
792+ }
793+ expect ( result . current . info ) . toEqual ( { ...nativeToolDefaults , ...customModelInfo } )
794+ expect ( result . current . info ?. supportsNativeTools ) . toBe ( true )
795+ expect ( result . current . info ?. defaultToolProtocol ) . toBe ( "native" )
796+ } )
797+
798+ it ( "should allow custom model info to override native tool defaults" , ( ) => {
799+ const customModelInfo : ModelInfo = {
800+ maxTokens : 8192 ,
801+ contextWindow : 32000 ,
802+ supportsImages : false ,
803+ supportsPromptCache : false ,
804+ supportsNativeTools : false , // Explicitly disable
805+ defaultToolProtocol : "xml" , // Override default to use XML instead of native
806+ }
807+
808+ const apiConfiguration : ProviderSettings = {
809+ apiProvider : "openai" ,
810+ openAiModelId : "custom-model-no-tools" ,
811+ openAiCustomModelInfo : customModelInfo ,
812+ }
813+
814+ const wrapper = createWrapper ( )
815+ const { result } = renderHook ( ( ) => useSelectedModel ( apiConfiguration ) , { wrapper } )
816+
817+ expect ( result . current . provider ) . toBe ( "openai" )
818+ expect ( result . current . id ) . toBe ( "custom-model-no-tools" )
819+ // Custom model info should override the native tool defaults
820+ expect ( result . current . info ?. supportsNativeTools ) . toBe ( false )
821+ expect ( result . current . info ?. defaultToolProtocol ) . toBe ( "xml" )
822+ } )
823+ } )
728824} )
0 commit comments