@@ -9,6 +9,7 @@ use anda_core::{
99 AgentOutput , BoxError , BoxPinFut , CompletionFeatures , CompletionRequest , ContentPart ,
1010 FunctionDefinition , Json , Message , Resource , Usage as ModelUsage ,
1111} ;
12+
1213use log:: { Level :: Debug , log_enabled} ;
1314use serde:: { Deserialize , Serialize } ;
1415use serde_json:: json;
@@ -116,6 +117,14 @@ pub struct CompletionResponse {
116117}
117118
118119impl CompletionResponse {
120+ pub fn parse_output ( & mut self ) {
121+ for choice in self . choices . iter_mut ( ) {
122+ if let Ok ( msg) = serde_json:: from_value :: < MessageOutput > ( choice. message . clone ( ) ) {
123+ choice. parsed_message = Some ( msg) ;
124+ }
125+ }
126+ }
127+
119128 fn try_into (
120129 mut self ,
121130 raw_history : Vec < Json > ,
@@ -140,9 +149,12 @@ impl CompletionResponse {
140149 if !matches ! ( choice. finish_reason. as_str( ) , "stop" | "tool_calls" ) {
141150 output. failed_reason = Some ( choice. finish_reason ) ;
142151 } else {
143- output. raw_history . push ( json ! ( & choice. message) ) ;
152+ output. raw_history . push ( choice. message ) ;
144153 let timestamp = unix_ms ( ) ;
145- let mut msg: Message = choice. message . into ( ) ;
154+ let mut msg: Message = choice
155+ . parsed_message
156+ . ok_or ( "Failed to parse message output" ) ?
157+ . into ( ) ;
146158 msg. name = Some ( self . model ) ;
147159 msg. timestamp = Some ( timestamp) ;
148160 output. content = msg. text ( ) . unwrap_or_default ( ) ;
@@ -156,7 +168,11 @@ impl CompletionResponse {
156168 fn maybe_failed ( & self ) -> bool {
157169 !self . choices . iter ( ) . any ( |choice| {
158170 matches ! ( choice. finish_reason. as_str( ) , "stop" | "tool_calls" )
159- && ( !choice. message . content . is_empty ( ) || choice. message . tool_calls . is_some ( ) )
171+ && choice
172+ . parsed_message
173+ . as_ref ( )
174+ . map ( |m| !m. content . is_empty ( ) || m. tool_calls . is_some ( ) )
175+ . unwrap_or ( false )
160176 } )
161177 }
162178}
@@ -187,6 +203,11 @@ fn to_message_input(msg: &Message) -> MessageInput {
187203 ContentPart :: ToolOutput {
188204 output, call_id, ..
189205 } => {
206+ if msg. content . len ( ) == 1 {
207+ res. content = serde_json:: to_value ( output) . unwrap_or_default ( ) ;
208+ res. tool_call_id = call_id. clone ( ) ;
209+ return res;
210+ }
190211 arr. push ( json ! ( {
191212 "type" : "text" ,
192213 "text" : serde_json:: to_string( output) . unwrap_or_default( ) ,
@@ -225,8 +246,11 @@ fn to_message_input(msg: &Message) -> MessageInput {
225246#[ derive( Debug , Deserialize , Serialize ) ]
226247pub struct Choice {
227248 pub index : usize ,
228- pub message : MessageOutput ,
249+ pub message : Json ,
229250 pub finish_reason : String ,
251+
252+ #[ serde( skip) ]
253+ pub parsed_message : Option < MessageOutput > ,
230254}
231255
232256/// Output message structure from Kimi API
@@ -236,6 +260,9 @@ pub struct MessageOutput {
236260 #[ serde( default ) ]
237261 pub content : String ,
238262
263+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
264+ pub reasoning_content : Option < String > ,
265+
239266 #[ serde( skip_serializing_if = "Option::is_none" ) ]
240267 pub tool_calls : Option < Vec < ToolCallOutput > > ,
241268}
@@ -440,7 +467,9 @@ impl CompletionFeaturesDyn for CompletionModel {
440467 if response. status ( ) . is_success ( ) {
441468 let text = response. text ( ) . await ?;
442469 match serde_json:: from_str :: < CompletionResponse > ( & text) {
443- Ok ( res) => {
470+ Ok ( mut res) => {
471+ res. parse_output ( ) ;
472+
444473 if log_enabled ! ( Debug ) {
445474 log:: debug!(
446475 request: serde = body,
0 commit comments