@@ -270,19 +270,25 @@ impl DatabricksProvider {
270270
271271 fn is_responses_model ( model_name : & str ) -> bool {
272272 let normalized = model_name. to_ascii_lowercase ( ) ;
273- normalized. contains ( "codex" )
274- || normalized. starts_with ( "gpt-5-pro" )
275- || normalized. starts_with ( "gpt-5.2-pro" )
276- || normalized. starts_with ( "gpt-5.4" )
273+ let base = normalized
274+ . strip_prefix ( "databricks-" )
275+ . unwrap_or ( & normalized) ;
276+ base. contains ( "codex" )
277+ || base. starts_with ( "gpt-5-pro" )
278+ || base. starts_with ( "gpt-5.2-pro" )
279+ || base. starts_with ( "gpt-5.4" )
277280 }
278281
279282 fn get_endpoint_path ( & self , model_name : & str , is_embedding : bool ) -> String {
280283 if is_embedding {
281284 "serving-endpoints/text-embedding-3-small/invocations" . to_string ( )
282- } else if Self :: is_responses_model ( model_name) {
283- "serving-endpoints/responses" . to_string ( )
284285 } else {
285- format ! ( "serving-endpoints/{}/invocations" , model_name)
286+ let ( clean_name, _) = super :: utils:: extract_reasoning_effort ( model_name) ;
287+ if Self :: is_responses_model ( & clean_name) {
288+ "serving-endpoints/responses" . to_string ( )
289+ } else {
290+ format ! ( "serving-endpoints/{}/invocations" , clean_name)
291+ }
286292 }
287293 }
288294
@@ -654,4 +660,122 @@ mod tests {
654660 assert ! ( !DatabricksProvider :: is_responses_model( "o3-mini" ) ) ;
655661 assert ! ( !DatabricksProvider :: is_responses_model( "claude-sonnet-4" ) ) ;
656662 }
663+
664+ // --- Bug-fix tests: databricks-prefixed model names ---
665+
666+ #[ test]
667+ fn databricks_prefixed_gpt_5_4_is_responses_model ( ) {
668+ assert ! (
669+ DatabricksProvider :: is_responses_model( "databricks-gpt-5.4" ) ,
670+ "databricks-gpt-5.4 should route to the Responses API"
671+ ) ;
672+ }
673+
674+ #[ test]
675+ fn databricks_prefixed_gpt_5_4_mini_is_responses_model ( ) {
676+ assert ! ( DatabricksProvider :: is_responses_model(
677+ "databricks-gpt-5.4-mini"
678+ ) ) ;
679+ }
680+
681+ #[ test]
682+ fn databricks_prefixed_gpt_5_pro_is_responses_model ( ) {
683+ assert ! ( DatabricksProvider :: is_responses_model(
684+ "databricks-gpt-5-pro"
685+ ) ) ;
686+ }
687+
688+ #[ test]
689+ fn databricks_prefixed_codex_is_responses_model ( ) {
690+ assert ! ( DatabricksProvider :: is_responses_model(
691+ "databricks-gpt-5-codex"
692+ ) ) ;
693+ }
694+
695+ #[ test]
696+ fn databricks_prefixed_non_responses_model_is_not_matched ( ) {
697+ assert ! ( !DatabricksProvider :: is_responses_model( "databricks-gpt-4o" ) ) ;
698+ assert ! ( !DatabricksProvider :: is_responses_model(
699+ "databricks-claude-sonnet-4"
700+ ) ) ;
701+ }
702+
703+ // --- Bug-fix tests: reasoning suffix must be stripped from endpoint path ---
704+
705+ #[ test]
706+ fn endpoint_path_strips_reasoning_suffix_for_chat_model ( ) {
707+ let provider = DatabricksProvider {
708+ api_client : super :: super :: api_client:: ApiClient :: new (
709+ "https://example.com" . to_string ( ) ,
710+ super :: super :: api_client:: AuthMethod :: NoAuth ,
711+ )
712+ . unwrap ( ) ,
713+ auth : DatabricksAuth :: Token ( "fake" . into ( ) ) ,
714+ model : ModelConfig :: new_or_fail ( "databricks-gpt-5-4" ) ,
715+ image_format : ImageFormat :: OpenAi ,
716+ retry_config : RetryConfig :: default ( ) ,
717+ fast_retry_config : RetryConfig :: new ( 0 , 0 , 1.0 , 0 ) ,
718+ name : "databricks" . into ( ) ,
719+ token_cache : std:: sync:: Arc :: new ( std:: sync:: Mutex :: new ( None ) ) ,
720+ instance_id : None ,
721+ } ;
722+
723+ // "databricks-gpt-5-4-high" — the "-high" is a reasoning effort suffix,
724+ // not part of the Databricks endpoint name.
725+ let path = provider. get_endpoint_path ( "databricks-gpt-5-4-high" , false ) ;
726+ assert_eq ! (
727+ path, "serving-endpoints/databricks-gpt-5-4/invocations" ,
728+ "reasoning suffix '-high' must be stripped from the endpoint name"
729+ ) ;
730+ }
731+
732+ #[ test]
733+ fn endpoint_path_routes_prefixed_responses_model_correctly ( ) {
734+ let provider = DatabricksProvider {
735+ api_client : super :: super :: api_client:: ApiClient :: new (
736+ "https://example.com" . to_string ( ) ,
737+ super :: super :: api_client:: AuthMethod :: NoAuth ,
738+ )
739+ . unwrap ( ) ,
740+ auth : DatabricksAuth :: Token ( "fake" . into ( ) ) ,
741+ model : ModelConfig :: new_or_fail ( "databricks-gpt-5.4" ) ,
742+ image_format : ImageFormat :: OpenAi ,
743+ retry_config : RetryConfig :: default ( ) ,
744+ fast_retry_config : RetryConfig :: new ( 0 , 0 , 1.0 , 0 ) ,
745+ name : "databricks" . into ( ) ,
746+ token_cache : std:: sync:: Arc :: new ( std:: sync:: Mutex :: new ( None ) ) ,
747+ instance_id : None ,
748+ } ;
749+
750+ let path = provider. get_endpoint_path ( "databricks-gpt-5.4-high" , false ) ;
751+ assert_eq ! (
752+ path, "serving-endpoints/responses" ,
753+ "databricks-gpt-5.4 variants must route to the Responses API"
754+ ) ;
755+ }
756+
757+ #[ test]
758+ fn endpoint_path_unchanged_for_non_reasoning_model ( ) {
759+ let provider = DatabricksProvider {
760+ api_client : super :: super :: api_client:: ApiClient :: new (
761+ "https://example.com" . to_string ( ) ,
762+ super :: super :: api_client:: AuthMethod :: NoAuth ,
763+ )
764+ . unwrap ( ) ,
765+ auth : DatabricksAuth :: Token ( "fake" . into ( ) ) ,
766+ model : ModelConfig :: new_or_fail ( "databricks-claude-sonnet-4" ) ,
767+ image_format : ImageFormat :: OpenAi ,
768+ retry_config : RetryConfig :: default ( ) ,
769+ fast_retry_config : RetryConfig :: new ( 0 , 0 , 1.0 , 0 ) ,
770+ name : "databricks" . into ( ) ,
771+ token_cache : std:: sync:: Arc :: new ( std:: sync:: Mutex :: new ( None ) ) ,
772+ instance_id : None ,
773+ } ;
774+
775+ let path = provider. get_endpoint_path ( "databricks-claude-sonnet-4" , false ) ;
776+ assert_eq ! (
777+ path,
778+ "serving-endpoints/databricks-claude-sonnet-4/invocations"
779+ ) ;
780+ }
657781}
0 commit comments