From 094eb4b8baa5abd878dcf5b611cf615955bc79eb Mon Sep 17 00:00:00 2001 From: asepharyana Date: Mon, 20 Jul 2026 17:25:19 +0700 Subject: [PATCH] feat: refactor auto-review engine to use spawn_subagent for improved thread handling --- .../src/subagent/auto/engine.rs | 112 +++++++++--------- 1 file changed, 58 insertions(+), 54 deletions(-) diff --git a/apps/infrastructure/src/subagent/auto/engine.rs b/apps/infrastructure/src/subagent/auto/engine.rs index a619dcd..32b82ef 100644 --- a/apps/infrastructure/src/subagent/auto/engine.rs +++ b/apps/infrastructure/src/subagent/auto/engine.rs @@ -19,7 +19,7 @@ use tracing::{debug, info, instrument, warn}; use crate::subagent::context::SubagentContext; use crate::subagent::division::AccessTier; -use crate::subagent::engine::run_agent; +use crate::subagent::spawn::spawn_subagent; use crate::tools::ToolCtx; use crate::{AgentStatus, TurnEvent}; @@ -174,64 +174,19 @@ pub fn spawn_background_review( model, ); - // 7. Run the subagent engine directly on this thread - // (creates its own tokio runtime, calls run_agent with Write tools) - let rt = match tokio::runtime::Runtime::new() { - Ok(r) => r, - Err(e) => { - warn!(error = %e, "auto-review: failed to create tokio runtime"); - push_event( - &turn_events, - TurnEvent::WorkflowAgentUpdate { - agent_id, - agent_name, - status: AgentStatus::Failed(format!("runtime error: {e}")), - }, - ); - return; - } - }; - - let result = rt.block_on(run_agent( + // 7. Spawn the subagent via spawn_subagent (creates its own OS thread + // + tokio runtime internally, avoiding nested runtime panics). + let handle = spawn_subagent( subagent_ctx, - "Auto-review and fix issues in the changed files", + "Auto-review and fix issues in the changed files".to_string(), AccessTier::Write, tool_ctx, - )); + ); // 8. Report results - match result { - Ok(report) => { - let trimmed = report.trim(); - if trimmed.is_empty() || trimmed.contains("no issues") { - push_event( - &turn_events, - TurnEvent::SystemNote { - kind: "review".into(), - message: "✅ Auto-review: no issues found.".into(), - }, - ); - info!("auto-review: no issues found"); - } else { - push_event( - &turn_events, - TurnEvent::SystemNote { - kind: "review_finding".into(), - message: format!("📋 Auto-review complete:\n{}", trimmed), - }, - ); - info!("auto-review: completed with findings"); - } - push_event( - &turn_events, - TurnEvent::WorkflowAgentUpdate { - agent_id, - agent_name, - status: AgentStatus::Completed, - }, - ); - } - Err(e) => { + let report = match handle.join() { + Ok(Ok(r)) => r, + Ok(Err(e)) => { warn!(error = %e, "auto-review subagent failed"); push_event( &turn_events, @@ -248,8 +203,57 @@ pub fn spawn_background_review( status: AgentStatus::Failed(e.to_string()), }, ); + return; } + Err(e) => { + warn!(error = ?e, "auto-review subagent panicked"); + push_event( + &turn_events, + TurnEvent::SystemNote { + kind: "review".into(), + message: "⚠️ Auto-review agent panicked.".into(), + }, + ); + push_event( + &turn_events, + TurnEvent::WorkflowAgentUpdate { + agent_id, + agent_name, + status: AgentStatus::Failed("panicked".to_string()), + }, + ); + return; + } + }; + + let trimmed = report.trim(); + if trimmed.is_empty() || trimmed.to_lowercase().contains("no issues") { + push_event( + &turn_events, + TurnEvent::SystemNote { + kind: "review".into(), + message: "✅ Auto-review: no issues found.".into(), + }, + ); + info!("auto-review: no issues found"); + } else { + push_event( + &turn_events, + TurnEvent::SystemNote { + kind: "review_finding".into(), + message: format!("📋 Auto-review complete:\n{}", trimmed), + }, + ); + info!("auto-review: completed with findings"); } + push_event( + &turn_events, + TurnEvent::WorkflowAgentUpdate { + agent_id, + agent_name, + status: AgentStatus::Completed, + }, + ); }); }