oli_tui/app/
state.rs

1use crate::agent::core::Agent;
2use crate::apis::api_client::SessionManager;
3use crate::app::commands::SpecialCommand;
4use crate::app::history::ConversationSummary;
5use crate::app::models::ToolPermissionStatus;
6use crate::app::permissions::PendingToolExecution;
7use crate::app::utils::ScrollState;
8use crate::models::ModelConfig;
9use std::sync::mpsc;
10use std::time::{Duration, Instant};
11use tokio::runtime::Runtime;
12use uuid::Uuid;
13
14#[derive(Debug, PartialEq)]
15pub enum AppState {
16    Setup,
17    ApiKeyInput,
18    Error(String),
19    Chat,
20}
21
22/// Status of a task
23#[derive(Debug, Clone, PartialEq)]
24pub enum TaskStatus {
25    /// Task is in progress/ongoing
26    InProgress,
27    /// Task completed successfully
28    Completed {
29        duration: Duration,
30        tool_uses: u32,
31        input_tokens: u32,
32        output_tokens: u32,
33    },
34    /// Task failed
35    Failed(String),
36}
37
38/// Represents a task the assistant is working on
39#[derive(Debug, Clone)]
40pub struct Task {
41    pub id: String,
42    pub description: String,
43    pub status: TaskStatus,
44    pub created_at: Instant,
45    pub updated_at: Instant,
46    pub tool_count: u32,
47    pub input_tokens: u32,
48    pub output_tokens: u32,
49}
50
51impl Task {
52    /// Create a new in-progress task
53    pub fn new(description: &str) -> Self {
54        let now = Instant::now();
55        Self {
56            id: format!("{}", Uuid::new_v4().simple()),
57            description: description.to_string(),
58            status: TaskStatus::InProgress,
59            created_at: now,
60            updated_at: now,
61            tool_count: 0,
62            input_tokens: 0,
63            output_tokens: 0,
64        }
65    }
66
67    /// Mark task as completed
68    pub fn complete(&mut self, _tool_uses: u32, output_tokens: u32) {
69        // Calculate duration from task creation to now, not just since last update
70        let now = Instant::now();
71        let duration = now.duration_since(self.created_at);
72
73        // Store the output tokens
74        self.output_tokens = output_tokens;
75
76        self.status = TaskStatus::Completed {
77            duration,
78            tool_uses: self.tool_count, // Use actual tool count from task
79            input_tokens: self.input_tokens,
80            output_tokens: self.output_tokens,
81        };
82        self.updated_at = now;
83    }
84
85    /// Mark task as failed
86    pub fn fail(&mut self, error: &str) {
87        self.status = TaskStatus::Failed(error.to_string());
88        self.updated_at = Instant::now();
89    }
90
91    /// Increment tool count
92    pub fn add_tool_use(&mut self) {
93        self.tool_count += 1;
94        self.updated_at = Instant::now();
95    }
96
97    /// Add input tokens
98    pub fn add_input_tokens(&mut self, tokens: u32) {
99        self.input_tokens += tokens;
100        self.updated_at = Instant::now();
101    }
102
103    /// Check if this task is still in progress
104    pub fn is_in_progress(&self) -> bool {
105        matches!(self.status, TaskStatus::InProgress)
106    }
107}
108
109use tui_textarea::TextArea;
110
111pub struct App {
112    pub state: AppState,
113    pub textarea: TextArea<'static>, // TextArea widget for improved multiline input
114    pub input: String,               // Keep for backward compatibility during transition
115    pub messages: Vec<String>,
116    pub logs: Vec<String>, // Store logs separately from messages
117    pub show_logs: bool,   // Toggle between logs and messages display
118    pub selected_model: usize,
119    pub available_models: Vec<ModelConfig>,
120    pub error_message: Option<String>,
121    pub debug_messages: bool,
122    pub message_scroll: ScrollState, // Improved scrolling for messages
123    pub log_scroll: ScrollState,     // Separate scrolling for logs
124    pub scroll_position: usize,      // Legacy scroll position (kept for compatibility)
125    pub last_query_time: Instant,
126    pub last_message_time: Instant, // Timestamp for message animations
127    pub use_agent: bool,
128    pub agent: Option<Agent>,
129    pub tokio_runtime: Option<Runtime>,
130    pub agent_progress_rx: Option<mpsc::Receiver<String>>,
131    pub api_key: Option<String>,
132    pub current_working_dir: Option<String>,
133    // Command-related fields
134    pub command_mode: bool,
135    pub available_commands: Vec<SpecialCommand>,
136    pub selected_command: usize,
137    pub show_command_menu: bool,
138    // Tool permission-related fields
139    pub permission_required: bool, // If true, we're waiting for user input on a tool permission
140    pub pending_tool: Option<PendingToolExecution>, // The tool waiting for permission
141    pub tool_permission_status: ToolPermissionStatus, // Current permission status
142    pub tool_execution_in_progress: bool, // Flag to indicate active tool execution
143    pub show_intermediate_steps: bool, // Show intermediate steps like tool use and file reads
144    pub show_shortcuts_hint: bool, // Show the shortcut hint below input box
145    pub show_detailed_shortcuts: bool, // Show all shortcuts when ? is pressed
146    // Cursor position in input - kept for backward compatibility
147    pub cursor_position: usize, // Current cursor position in the input string
148    // Task tracking
149    pub tasks: Vec<Task>,
150    pub current_task_id: Option<String>,
151    pub task_scroll: ScrollState,    // Improved scrolling for task list
152    pub task_scroll_position: usize, // Legacy scroll position (kept for compatibility)
153    // Conversation history management
154    pub conversation_summaries: Vec<ConversationSummary>, // History of conversation summaries
155    // Session management for API conversation
156    pub session_manager: Option<SessionManager>, // Manages the API conversation session
157    // Session information for logging
158    pub session_id: String, // Unique ID for the current session
159}