use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use tokio::sync::mpsc;
use tokio::task::JoinHandle;
use crate::agent::plan::runtime::{ActivePlan, review_once};
use crate::agent::plan::workflow::{ReviewStep, implement_retry_prompt};
use crate::agent::tools::background::{BackgroundStore, prepend_pending_notifications};
use crate::event::AgentEvent;
use crate::provider::AnyAgent;
use crate::session::MessageRole;
use crate::ui::colors::{c_agent, c_error};
use crate::ui::run_handlers::RunCtx;
#[allow(clippy::too_many_arguments)]
pub(super) async fn drive_plan_review(
ctx: &mut RunCtx<'_>,
agent: &mut AnyAgent,
bg_store: &Option<BackgroundStore>,
interjection_queue: &Arc<Mutex<VecDeque<String>>>,
agent_rx: &mut Option<mpsc::Receiver<AgentEvent>>,
agent_abort: &mut Option<JoinHandle<()>>,
agent_interject: &mut Option<mpsc::Sender<()>>,
agent_cancel: &mut Option<mpsc::Sender<()>>,
is_running: &mut bool,
) -> anyhow::Result<()> {
if *is_running {
return Ok(());
}
let Some(active) = ctx.active_plan.take() else {
return Ok(());
};
let transcript = crate::agent::review::build_transcript(ctx.session);
ctx.renderer
.write_line("Phase: Review — reviewer runs the code…", c_agent())?;
match review_once(agent, &active.plan, transcript, active.cycles_left).await {
Ok(ReviewStep::Approved) => {
ctx.renderer
.write_line("Phase: Review — ✓ reviewer approved", c_agent())?;
}
Ok(ReviewStep::Exhausted) => {
ctx.renderer.write_line(
"Phase: Review — fix-cycle budget spent; stopping. Continue manually if needed.",
c_agent(),
)?;
}
Ok(ReviewStep::Retry { feedback }) => {
ctx.renderer.write_line(
"Phase: Review — changes needed; re-implementing…",
c_agent(),
)?;
let retry_prompt = implement_retry_prompt(&feedback);
ctx.last_user_prompt.clone_from(&retry_prompt);
ctx.session.add_message(MessageRole::User, &retry_prompt);
let runner = agent.clone().spawn_runner(
prepend_pending_notifications(&retry_prompt, bg_store.as_ref()),
crate::agent::runner::convert_history(ctx.session),
Some(interjection_queue.clone()),
);
runner.install_into(
agent_rx,
agent_abort,
agent_interject,
agent_cancel,
is_running,
);
*ctx.active_plan = Some(ActivePlan {
plan: active.plan,
cycles_left: active.cycles_left - 1,
});
}
Err(e) => {
ctx.renderer.write_line(
&format!("Phase: Review — reviewer error: {e}; stopping"),
c_error(),
)?;
}
}
Ok(())
}