agent_core/tui/widgets/
conversation.rs

1//! ConversationView trait for conversation/chat display widgets.
2//!
3//! This trait defines the interface for widgets that display conversation history,
4//! supporting streaming, tool messages, and session state management.
5
6use ratatui::{layout::Rect, Frame};
7use std::any::Any;
8
9use super::ToolStatus;
10use crate::tui::themes::Theme;
11
12/// Trait for conversation/chat display widgets.
13///
14/// This trait is separate from the Widget trait - a ConversationView may also
15/// implement Widget, but this trait focuses specifically on conversation display
16/// functionality.
17///
18/// # Session State
19///
20/// ConversationView supports saving and restoring state for session switching:
21/// - `save_state()` returns an opaque state object
22/// - `restore_state()` restores from a previously saved state
23/// - `clear()` resets the view while preserving configuration
24///
25/// # Example Implementation
26///
27/// ```ignore
28/// impl ConversationView for MyChatView {
29///     fn add_user_message(&mut self, content: String) {
30///         self.messages.push(Message::user(content));
31///     }
32///     // ... implement other methods
33/// }
34/// ```
35pub trait ConversationView: Send + 'static {
36    // --- Message Operations ---
37
38    /// Add a user message to the conversation
39    fn add_user_message(&mut self, content: String);
40
41    /// Add an assistant message to the conversation
42    fn add_assistant_message(&mut self, content: String);
43
44    /// Add a system message to the conversation
45    fn add_system_message(&mut self, content: String);
46
47    // --- Streaming ---
48
49    /// Append text to the current streaming response
50    fn append_streaming(&mut self, text: &str);
51
52    /// Complete the streaming response and finalize it as a message
53    fn complete_streaming(&mut self);
54
55    /// Discard the streaming buffer without saving (used on cancel)
56    fn discard_streaming(&mut self);
57
58    /// Check if currently streaming a response
59    fn is_streaming(&self) -> bool;
60
61    // --- Tool Messages ---
62
63    /// Add a tool execution message
64    fn add_tool_message(&mut self, tool_use_id: &str, display_name: &str, display_title: &str);
65
66    /// Update the status of a tool message
67    fn update_tool_status(&mut self, tool_use_id: &str, status: ToolStatus);
68
69    // --- Scrolling ---
70
71    /// Scroll up by the implementation's scroll step
72    fn scroll_up(&mut self);
73
74    /// Scroll down by the implementation's scroll step
75    fn scroll_down(&mut self);
76
77    /// Enable auto-scroll and scroll to bottom (called when user submits a message)
78    fn enable_auto_scroll(&mut self);
79
80    // --- Rendering ---
81
82    /// Render the conversation view
83    ///
84    /// # Arguments
85    /// * `frame` - The ratatui frame to render to
86    /// * `area` - The area to render within
87    /// * `theme` - The current theme
88    /// * `pending_status` - Optional pending status message (e.g., "running tools...")
89    fn render(&mut self, frame: &mut Frame, area: Rect, theme: &Theme, pending_status: Option<&str>);
90
91    // --- Animation ---
92
93    /// Advance the spinner animation (called periodically during activity)
94    fn step_spinner(&mut self);
95
96    // --- Session State ---
97
98    /// Save the current state for session switching
99    ///
100    /// Returns an opaque state object that can be restored later.
101    fn save_state(&self) -> Box<dyn Any + Send>;
102
103    /// Restore state from a previously saved state
104    ///
105    /// If the state cannot be downcast to the expected type, this is a no-op.
106    fn restore_state(&mut self, state: Box<dyn Any + Send>);
107
108    /// Clear conversation content while preserving configuration
109    ///
110    /// This resets messages, streaming state, and scroll position,
111    /// but keeps settings like title, theme configuration, and renderers.
112    fn clear(&mut self);
113}
114
115/// Type alias for conversation view factory functions.
116///
117/// A factory is called to create a new ConversationView instance,
118/// typically when creating a new session or clearing the current one.
119///
120/// # Example
121///
122/// ```ignore
123/// let factory: ConversationViewFactory = Box::new(|| {
124///     Box::new(ChatView::new()
125///         .with_title("My Agent")
126///         .with_initial_content(welcome_renderer))
127/// });
128/// ```
129pub type ConversationViewFactory = Box<dyn Fn() -> Box<dyn ConversationView> + Send + Sync>;