@@ -1136,12 +1136,10 @@ impl Agent {
11361136 break ;
11371137 }
11381138
1139- if let Some ( final_output_tool) = self . final_output_tool. lock( ) . await . as_ref( ) {
1140- if final_output_tool. final_output. is_some( ) {
1141- let final_event = AgentEvent :: Message (
1142- Message :: assistant( ) . with_text( final_output_tool. final_output. clone( ) . unwrap( ) )
1143- ) ;
1144- yield final_event;
1139+ {
1140+ let guard = self . final_output_tool. lock( ) . await ;
1141+ if let Some ( ref output) = guard. as_ref( ) . and_then( |fot| fot. final_output. clone( ) ) {
1142+ yield AgentEvent :: Message ( Message :: assistant( ) . with_text( output) ) ;
11451143 break ;
11461144 }
11471145 }
@@ -1600,42 +1598,52 @@ impl Agent {
16001598 }
16011599
16021600 if no_tools_called {
1603- if let Some ( final_output_tool) = self . final_output_tool. lock( ) . await . as_ref( ) {
1604- if final_output_tool. final_output. is_none( ) {
1601+ // Lock, extract state, drop guard before branching — handle_retry_logic
1602+ // also locks final_output_tool and tokio::sync::Mutex is not reentrant.
1603+ let final_output = {
1604+ let guard = self . final_output_tool. lock( ) . await ;
1605+ guard. as_ref( ) . map( |fot| fot. final_output. clone( ) )
1606+ } ;
1607+
1608+ match final_output {
1609+ Some ( None ) => {
16051610 warn!( "Final output tool has not been called yet. Continuing agent loop." ) ;
16061611 let message = Message :: user( ) . with_text( FINAL_OUTPUT_CONTINUATION_MESSAGE ) ;
16071612 session_manager. add_message( & session_config. id, & message) . await ?;
16081613 conversation. push( message. clone( ) ) ;
16091614 yield AgentEvent :: Message ( message) ;
1610- } else {
1611- let message = Message :: assistant( ) . with_text( final_output_tool. final_output. clone( ) . unwrap( ) ) ;
1615+ }
1616+ Some ( Some ( output) ) => {
1617+ let message = Message :: assistant( ) . with_text( output) ;
16121618 session_manager. add_message( & session_config. id, & message) . await ?;
16131619 conversation. push( message. clone( ) ) ;
16141620 yield AgentEvent :: Message ( message) ;
16151621 exit_chat = true ;
16161622 }
1617- } else if did_recovery_compact_this_iteration {
1618- // Avoid setting exit_chat; continue from last user message in the conversation
1619- } else {
1620- match self . handle_retry_logic( & mut conversation, & session_config, & initial_messages) . await {
1621- Ok ( should_retry) => {
1622- if should_retry {
1623- info!( "Retry logic triggered, restarting agent loop" ) ;
1624- session_manager. replace_conversation( & session_config. id, & conversation) . await ?;
1625- yield AgentEvent :: HistoryReplaced ( conversation. clone( ) ) ;
1626- } else {
1623+ None if did_recovery_compact_this_iteration => {
1624+ // continue from last user message after recovery compact
1625+ }
1626+ None => {
1627+ match self . handle_retry_logic( & mut conversation, & session_config, & initial_messages) . await {
1628+ Ok ( should_retry) => {
1629+ if should_retry {
1630+ info!( "Retry logic triggered, restarting agent loop" ) ;
1631+ session_manager. replace_conversation( & session_config. id, & conversation) . await ?;
1632+ yield AgentEvent :: HistoryReplaced ( conversation. clone( ) ) ;
1633+ } else {
1634+ exit_chat = true ;
1635+ }
1636+ }
1637+ Err ( e) => {
1638+ error!( "Retry logic failed: {}" , e) ;
1639+ yield AgentEvent :: Message (
1640+ Message :: assistant( ) . with_text(
1641+ format!( "Retry logic encountered an error: {}" , e)
1642+ )
1643+ ) ;
16271644 exit_chat = true ;
16281645 }
16291646 }
1630- Err ( e) => {
1631- error!( "Retry logic failed: {}" , e) ;
1632- yield AgentEvent :: Message (
1633- Message :: assistant( ) . with_text(
1634- format!( "Retry logic encountered an error: {}" , e)
1635- )
1636- ) ;
1637- exit_chat = true ;
1638- }
16391647 }
16401648 }
16411649 }
0 commit comments