use std::io::{self, Write};
use tuika::term::program_status::{BlockKind, Report, State, write};
use crate::agent::Agent;
const APP: &str = "codex";
#[derive(Debug, Clone, PartialEq, Eq)]
enum Phase {
Idle,
Working,
Blocked(String),
Done,
}
pub struct ProgramStatus {
last: Option<Phase>,
}
impl ProgramStatus {
pub fn new() -> Self {
ProgramStatus { last: None }
}
pub fn sync(&mut self, agent: &Agent) -> io::Result<()> {
let phase = if let Some(command) = agent.pending_approval() {
Phase::Blocked(command.to_string())
} else if agent.is_running() {
Phase::Working
} else if matches!(
self.last,
Some(Phase::Working | Phase::Blocked(_) | Phase::Done)
) {
Phase::Done
} else {
Phase::Idle
};
if self.last.as_ref() == Some(&phase) {
return Ok(());
}
let report = match &phase {
Phase::Idle => Report::new(State::Idle).app(APP),
Phase::Working => Report::new(State::Working).app(APP).msg("Working"),
Phase::Blocked(command) => Report::new(State::Blocked)
.kind(BlockKind::Permission)
.app(APP)
.msg(&format!("Allow command? {command}")),
Phase::Done => Report::new(State::Done).app(APP).msg("Turn complete"),
};
self.last = Some(phase);
let mut out = io::stdout();
write(&mut out, &report)?;
out.flush()
}
pub fn clear(&mut self) {
let mut out = io::stdout();
let _ = write(&mut out, &Report::clear(None));
let _ = out.flush();
}
}