@@ -16,8 +16,7 @@ use crate::types::{
1616 ToolChoice , ToolDefinition , ToolResultContentBlock , Usage ,
1717} ;
1818
19- use super :: { preflight_message_request, Provider , ProviderFuture , resolve_model_alias, strip_provider_prefix} ;
20-
19+ use super :: { preflight_message_request, resolve_model_alias, Provider , ProviderFuture } ;
2120
2221pub const DEFAULT_XAI_BASE_URL : & str = "https://api.x.ai/v1" ;
2322pub const DEFAULT_OPENAI_BASE_URL : & str = "https://api.openai.com/v1" ;
@@ -213,80 +212,22 @@ impl OpenAiCompatClient {
213212 }
214213
215214 pub async fn send_message (
216- & self ,
217- request : & MessageRequest ,
218- ) -> Result < MessageResponse , ApiError > {
219- // 1. Keep track of what Claw originally asked for
220- let original_model = request. model . clone ( ) ;
221- let canonical = resolve_model_alias ( & request. model ) ;
222-
223- // 2. Clean the model string (e.g., "openai/deepseek-v4-flash" -> "deepseek-v4-flash")
224- let downstream_model = strip_provider_prefix ( & canonical) ;
225-
226- let mut request = MessageRequest {
227- stream : false ,
228- ..request. clone ( )
229- } ;
230- request. model = downstream_model; // Use the clean name for the API payload
231-
232- preflight_message_request ( & request) ?;
233- let response = self . send_with_retry ( & request) . await ?;
234- let request_id = request_id_from_headers ( response. headers ( ) ) ;
235- let body = response. text ( ) . await . map_err ( ApiError :: from) ?;
236-
237- // Some backends return {"error":{"message":"...","type":"...","code":...}}
238- // instead of a valid completion object. Check for this before attempting
239- // full deserialization so the user sees the actual error, not a cryptic.
240- if let Ok ( raw) = serde_json:: from_str :: < serde_json:: Value > ( & body) {
241- if let Some ( err_obj) = raw. get ( "error" ) {
242- let msg = err_obj
243- . get ( "message" )
244- . and_then ( |m| m. as_str ( ) )
245- . unwrap_or ( "provider returned an error" )
246- . to_string ( ) ;
247- let code = err_obj
248- . get ( "code" )
249- . and_then ( serde_json:: Value :: as_u64)
250- . map ( |c| c as u16 ) ;
251- return Err ( ApiError :: Api {
252- status : reqwest:: StatusCode :: from_u16 ( code. unwrap_or ( 400 ) )
253- . unwrap_or ( reqwest:: StatusCode :: BAD_REQUEST ) ,
254- error_type : err_obj
255- . get ( "type" )
256- . and_then ( |t| t. as_str ( ) )
257- . map ( str:: to_owned) ,
258- message : Some ( msg) ,
259- request_id,
260- body,
261- retryable : false ,
262- suggested_action : suggested_action_for_status (
263- reqwest:: StatusCode :: from_u16 ( code. unwrap_or ( 400 ) )
264- . unwrap_or ( reqwest:: StatusCode :: BAD_REQUEST ) ,
265- ) ,
266- retry_after : None ,
267- } ) ;
268- }
269- }
270-
271- // Pass original_model to the deserializer error context so debugging logs are accurate
272- let payload = serde_json:: from_str :: < ChatCompletionResponse > ( & body) . map_err ( |error| {
273- ApiError :: json_deserialize ( self . config . provider_name , & original_model, & body, error)
274- } ) ?;
275-
276- let mut normalized = normalize_response ( & request. model , payload) ?;
277- if normalized. request_id . is_none ( ) {
278- normalized. request_id = request_id;
279- }
215+ & self ,
216+ request : & MessageRequest ,
217+ ) -> Result < MessageResponse , ApiError > {
218+ let original_model = request. model . clone ( ) ;
219+ let canonical = resolve_model_alias ( & request. model ) ;
280220
281- // 3. CRITICAL: Put the original model string back so Claw's internal routing stays happy
282- normalized. model = original_model;
221+ let mut request = MessageRequest {
222+ stream : false ,
223+ ..request. clone ( )
224+ } ;
225+ request. model = canonical;
283226
284- Ok ( normalized)
285- }
286- // Some backends return {"error":{"message":"...","type":"...","code":...}}
287- // instead of a valid completion object. Check for this before attempting
288- // full deserialization so the user sees the actual error, not a cryptic
289- // "missing field 'id'" parse failure.
227+ preflight_message_request ( & request) ?;
228+ let response = self . send_with_retry ( & request) . await ?;
229+ let request_id = request_id_from_headers ( response. headers ( ) ) ;
230+ let body = response. text ( ) . await . map_err ( ApiError :: from) ?;
290231 if let Ok ( raw) = serde_json:: from_str :: < serde_json:: Value > ( & body) {
291232 if let Some ( err_obj) = raw. get ( "error" ) {
292233 let msg = err_obj
@@ -318,41 +259,41 @@ impl OpenAiCompatClient {
318259 }
319260 }
320261 let payload = serde_json:: from_str :: < ChatCompletionResponse > ( & body) . map_err ( |error| {
321- ApiError :: json_deserialize ( self . config . provider_name , & request . model , & body, error)
262+ ApiError :: json_deserialize ( self . config . provider_name , & original_model , & body, error)
322263 } ) ?;
323264 let mut normalized = normalize_response ( & request. model , payload) ?;
324265 if normalized. request_id . is_none ( ) {
325266 normalized. request_id = request_id;
326267 }
268+ normalized. model = original_model;
327269 Ok ( normalized)
328270 }
329271
330- pub async fn stream_message (
331- & self ,
332- request : & MessageRequest ,
333- ) -> Result < MessageStream , ApiError > {
334- // 1. Keep track of the original model name
335- let original_model = request. model . clone ( ) ;
336- let canonical = resolve_model_alias ( & request. model ) ;
337-
338- // 2. Clean it up for DeepSeek
339- let downstream_model = strip_provider_prefix ( & canonical) ;
340-
341- let mut streaming_request = request. clone ( ) . with_streaming ( ) ;
342- streaming_request. model = downstream_model;
343-
344- preflight_message_request ( & streaming_request) ?;
345- let response = self . send_with_retry ( & streaming_request) . await ?;
346-
347- Ok ( MessageStream {
348- request_id : request_id_from_headers ( response. headers ( ) ) ,
349- response,
350- parser : OpenAiSseParser :: with_context ( self . config . provider_name , original_model. clone ( ) ) ,
351- pending : VecDeque :: new ( ) ,
352- done : false ,
353- state : StreamState :: new ( original_model) , // 3. Use the original name here
354- } )
355- }
272+ pub async fn stream_message (
273+ & self ,
274+ request : & MessageRequest ,
275+ ) -> Result < MessageStream , ApiError > {
276+ let original_model = request. model . clone ( ) ;
277+ let canonical = resolve_model_alias ( & request. model ) ;
278+
279+ let mut streaming_request = request. clone ( ) . with_streaming ( ) ;
280+ streaming_request. model = canonical;
281+
282+ preflight_message_request ( & streaming_request) ?;
283+ let response = self . send_with_retry ( & streaming_request) . await ?;
284+
285+ Ok ( MessageStream {
286+ request_id : request_id_from_headers ( response. headers ( ) ) ,
287+ response,
288+ parser : OpenAiSseParser :: with_context (
289+ self . config . provider_name ,
290+ original_model. clone ( ) ,
291+ ) ,
292+ pending : VecDeque :: new ( ) ,
293+ done : false ,
294+ state : StreamState :: new ( original_model) ,
295+ } )
296+ }
356297
357298 async fn send_with_retry (
358299 & self ,
0 commit comments