use rho_sdk::ToolCallId;
use crate::tui::{
activity::{ActivityPhase, LoadingSpinner},
provider_attempt::ProviderAttempt,
reasoning_phase::ReasoningPhase,
tool_call_batch::ToolCallBatch,
ToolEntry,
};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(in crate::tui) enum SessionUiPhase {
#[default]
Idle,
ProviderTurn,
Compacting,
}
impl SessionUiPhase {
pub(in crate::tui) const fn is_busy(self) -> bool {
!matches!(self, Self::Idle)
}
pub(in crate::tui) const fn is_provider_turn(self) -> bool {
matches!(self, Self::ProviderTurn)
}
pub(in crate::tui) const fn allows_idle_subagent_delivery(self) -> bool {
matches!(self, Self::Idle)
}
pub(in crate::tui) const fn busy_status_label(self) -> &'static str {
if self.is_busy() {
"running"
} else {
"ready"
}
}
}
#[derive(Default)]
pub(in crate::tui) struct TurnUi {
current_turn_start: Option<usize>,
provider_attempt: ProviderAttempt,
reasoning_phase: ReasoningPhase,
session_ui: SessionUiPhase,
activity_phase: ActivityPhase,
loading_spinner: LoadingSpinner,
tool_calls: ToolCallBatch,
}
impl TurnUi {
pub(in crate::tui) fn current_turn_start(&self) -> Option<usize> {
self.current_turn_start
}
pub(in crate::tui) fn set_current_turn_start(&mut self, start: Option<usize>) {
self.current_turn_start = start;
}
pub(in crate::tui) fn provider_attempt_mut(&mut self) -> &mut ProviderAttempt {
&mut self.provider_attempt
}
pub(in crate::tui) fn reasoning_phase(&self) -> &ReasoningPhase {
&self.reasoning_phase
}
pub(in crate::tui) fn reasoning_phase_mut(&mut self) -> &mut ReasoningPhase {
&mut self.reasoning_phase
}
pub(in crate::tui) fn session_ui(&self) -> SessionUiPhase {
self.session_ui
}
pub(in crate::tui) fn is_busy(&self) -> bool {
self.session_ui.is_busy()
}
pub(in crate::tui) fn is_provider_turn(&self) -> bool {
self.session_ui.is_provider_turn()
}
pub(in crate::tui) fn enter_provider_turn(&mut self) {
self.session_ui = SessionUiPhase::ProviderTurn;
}
pub(in crate::tui) fn enter_compact(&mut self) {
self.session_ui = SessionUiPhase::Compacting;
}
pub(in crate::tui) fn end_busy(&mut self) {
self.session_ui = SessionUiPhase::Idle;
}
pub(in crate::tui) fn activity_phase(&self) -> ActivityPhase {
self.activity_phase
}
pub(in crate::tui) fn set_activity_phase(&mut self, phase: ActivityPhase) {
self.activity_phase = phase;
}
pub(in crate::tui) fn loading_spinner(&self) -> &LoadingSpinner {
&self.loading_spinner
}
pub(in crate::tui) fn start_loading(&mut self) {
self.loading_spinner.start();
}
pub(in crate::tui) fn start_loading_if_needed(&mut self) {
self.loading_spinner.start_if_needed();
}
pub(in crate::tui) fn stop_loading(&mut self) {
self.loading_spinner.stop();
}
pub(in crate::tui) fn tool_calls(&self) -> &ToolCallBatch {
&self.tool_calls
}
pub(in crate::tui) fn tool_calls_mut(&mut self) -> &mut ToolCallBatch {
&mut self.tool_calls
}
pub(in crate::tui) fn clear_tool_calls(&mut self) {
self.tool_calls.clear();
}
pub(in crate::tui) fn tool_started(&mut self, call_id: ToolCallId, display_lines: Vec<String>) {
self.tool_calls.started(call_id, display_lines);
}
pub(in crate::tui) fn tool_updated(&mut self, call_id: ToolCallId, display_lines: Vec<String>) {
self.tool_calls.updated(call_id, display_lines);
}
pub(in crate::tui) fn tool_call_preview(
&mut self,
index: usize,
call_id: Option<ToolCallId>,
display_lines: Vec<String>,
) {
self.tool_calls.preview(index, call_id, display_lines);
}
pub(in crate::tui) fn tool_call_proposed(
&mut self,
call_id: ToolCallId,
display_lines: Vec<String>,
) {
self.tool_calls.preview_call(call_id, display_lines);
}
pub(in crate::tui) fn tool_finished(&mut self, call_id: &ToolCallId) -> bool {
self.tool_calls.finished(call_id)
}
pub(in crate::tui) fn latest_tool_mut(&mut self) -> Option<&mut ToolEntry> {
self.tool_calls.latest_mut()
}
}