use std::any::Any;
use tokio::sync::mpsc;
use crate::controller::{ControlCmd, ControllerInputPayload};
use crate::widgets::ConversationView;
use super::SlashCommand;
#[derive(Debug, Clone)]
pub enum PendingAction {
OpenThemePicker,
OpenSessionPicker,
ClearConversation,
CompactConversation,
CreateNewSession,
Quit,
}
pub struct CommandContext<'a> {
session_id: i64,
agent_name: &'a str,
version: &'a str,
commands: &'a [Box<dyn SlashCommand>],
conversation: &'a mut dyn ConversationView,
controller_tx: Option<&'a mpsc::Sender<ControllerInputPayload>>,
pending_actions: Vec<PendingAction>,
extension: Option<&'a dyn Any>,
}
impl<'a> CommandContext<'a> {
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
session_id: i64,
agent_name: &'a str,
version: &'a str,
commands: &'a [Box<dyn SlashCommand>],
conversation: &'a mut dyn ConversationView,
controller_tx: Option<&'a mpsc::Sender<ControllerInputPayload>>,
extension: Option<&'a dyn Any>,
) -> Self {
Self {
session_id,
agent_name,
version,
commands,
conversation,
controller_tx,
pending_actions: Vec::new(),
extension,
}
}
pub fn session_id(&self) -> i64 {
self.session_id
}
pub fn agent_name(&self) -> &str {
self.agent_name
}
pub fn version(&self) -> &str {
self.version
}
pub fn commands(&self) -> &[Box<dyn SlashCommand>] {
self.commands
}
pub fn show_message(&mut self, msg: impl Into<String>) {
self.conversation.add_system_message(msg.into());
}
pub fn clear_conversation(&mut self) {
self.pending_actions.push(PendingAction::ClearConversation);
}
pub fn compact_conversation(&mut self) {
self.pending_actions.push(PendingAction::CompactConversation);
}
pub fn open_theme_picker(&mut self) {
self.pending_actions.push(PendingAction::OpenThemePicker);
}
pub fn open_session_picker(&mut self) {
self.pending_actions.push(PendingAction::OpenSessionPicker);
}
pub fn request_quit(&mut self) {
self.pending_actions.push(PendingAction::Quit);
}
pub fn create_new_session(&mut self) {
self.pending_actions.push(PendingAction::CreateNewSession);
}
pub fn send_to_controller(&self, cmd: ControlCmd) {
if let Some(tx) = self.controller_tx {
let payload = ControllerInputPayload::control(self.session_id, cmd);
let _ = tx.try_send(payload);
}
}
pub fn extension<T: 'static>(&self) -> Option<&T> {
self.extension?.downcast_ref::<T>()
}
pub(crate) fn take_pending_actions(&mut self) -> Vec<PendingAction> {
std::mem::take(&mut self.pending_actions)
}
}