#[cfg(feature = "tui")]
use crate::ui::tui::TuiEvent;
#[derive(Debug, Clone)]
pub enum AgentEvent {
Started,
Completed {
message: String,
},
Error {
message: String,
},
Status {
message: String,
},
TokenUsage {
prompt_tokens: u64,
completion_tokens: u64,
},
ToolStarted {
name: String,
},
ToolCompleted {
name: String,
success: bool,
duration_ms: u64,
},
AssistantDelta {
text: String,
},
ThinkingDelta {
text: String,
},
ThinkingEnd,
ToolProgress {
name: String,
status: String,
},
SpinnerStart {
message: String,
},
SpinnerUpdate {
message: String,
},
SpinnerStop,
InputQueued {
message: String,
position: usize,
},
}
pub trait EventEmitter: Send + Sync {
fn emit(&self, event: AgentEvent);
}
pub struct NoopEmitter;
impl EventEmitter for NoopEmitter {
fn emit(&self, _event: AgentEvent) {}
}
#[cfg(feature = "tui")]
pub struct TuiEmitter {
tx: std::sync::mpsc::Sender<TuiEvent>,
}
#[cfg(feature = "tui")]
impl TuiEmitter {
pub fn new(tx: std::sync::mpsc::Sender<TuiEvent>) -> Self {
Self { tx }
}
}
#[cfg(feature = "tui")]
impl EventEmitter for TuiEmitter {
fn emit(&self, event: AgentEvent) {
let tui_event = match event {
AgentEvent::Started => TuiEvent::AgentStarted,
AgentEvent::Completed { message } => TuiEvent::AgentCompleted { message },
AgentEvent::Error { message } => TuiEvent::AgentError { message },
AgentEvent::Status { message } => TuiEvent::StatusUpdate { message },
AgentEvent::TokenUsage {
prompt_tokens,
completion_tokens,
} => TuiEvent::TokenUsage {
prompt_tokens,
completion_tokens,
},
AgentEvent::ToolStarted { name } => TuiEvent::ToolStarted { name },
AgentEvent::ToolCompleted {
name,
success,
duration_ms,
} => TuiEvent::ToolCompleted {
name,
success,
duration_ms,
},
AgentEvent::AssistantDelta { text } => TuiEvent::AssistantDelta { text },
AgentEvent::ThinkingDelta { text } => TuiEvent::ThinkingDelta { text },
AgentEvent::ThinkingEnd => TuiEvent::ThinkingEnd,
AgentEvent::ToolProgress { name, status } => TuiEvent::ToolProgress { name, status },
AgentEvent::SpinnerStart { message } => TuiEvent::SpinnerStart { message },
AgentEvent::SpinnerUpdate { message } => TuiEvent::SpinnerUpdate { message },
AgentEvent::SpinnerStop => TuiEvent::SpinnerStop,
AgentEvent::InputQueued { message, position } => {
TuiEvent::InputQueued { message, position }
}
};
let _ = self.tx.send(tui_event);
}
}