1use crate::services::message::Message;
7use ratatui::text::Line;
8use std::collections::HashMap;
9use std::path::PathBuf;
10use std::sync::Arc;
11use uuid::Uuid;
12
13pub type MessageLinesCache = (Vec<Message>, usize, Vec<Line<'static>>);
15
16#[derive(Clone, Debug)]
19pub struct RenderedMessageCache {
20 pub content_hash: u64,
22 pub rendered_lines: Arc<Vec<Line<'static>>>,
24 pub width: usize,
26}
27
28pub type PerMessageCache = HashMap<Uuid, RenderedMessageCache>;
31
32#[derive(Clone, Debug)]
35pub struct VisibleLinesCache {
36 pub scroll: usize,
38 pub width: usize,
40 pub height: usize,
42 pub lines: Arc<Vec<Line<'static>>>,
44 pub source_generation: u64,
46}
47
48#[derive(Debug, Default, Clone)]
50pub struct RenderMetrics {
51 pub last_render_time_us: u64,
53 pub cache_hits: usize,
55 pub cache_misses: usize,
57 pub total_lines: usize,
59 pub avg_render_time_us: u64,
61 render_count: u64,
63}
64
65impl RenderMetrics {
66 pub fn new() -> Self {
67 Self::default()
68 }
69
70 pub fn record_render(
72 &mut self,
73 render_time_us: u64,
74 cache_hits: usize,
75 cache_misses: usize,
76 total_lines: usize,
77 ) {
78 self.last_render_time_us = render_time_us;
79 self.cache_hits = cache_hits;
80 self.cache_misses = cache_misses;
81 self.total_lines = total_lines;
82
83 self.render_count += 1;
85 if self.render_count == 1 {
86 self.avg_render_time_us = render_time_us;
87 } else {
88 self.avg_render_time_us = (self.avg_render_time_us * 9 + render_time_us) / 10;
90 }
91 }
92
93 pub fn reset(&mut self) {
95 *self = Self::default();
96 }
97}
98
99pub struct FileSearchResult {
101 pub filtered_helpers: Vec<HelperCommand>,
102 pub filtered_files: Vec<String>,
103 pub cursor_position: usize,
104 pub input: String,
105}
106
107#[derive(Debug, Clone)]
108pub struct HelperCommand {
109 pub command: &'static str,
110 pub description: &'static str,
111}
112
113#[derive(Debug, Clone)]
114pub struct AttachedImage {
115 pub placeholder: String,
116 pub path: PathBuf,
117 pub filename: String,
118 pub dimensions: (u32, u32),
119 pub start_pos: usize,
120 pub end_pos: usize,
121}
122
123#[derive(Debug)]
124pub struct SessionInfo {
125 pub title: String,
126 pub id: String,
127 pub updated_at: String,
128 pub checkpoints: Vec<String>,
129}
130
131#[derive(Debug, PartialEq)]
132pub enum LoadingType {
133 Llm,
134 Sessions,
135}
136
137#[derive(Debug, Clone, PartialEq, Eq, Hash)]
138pub enum LoadingOperation {
139 LlmRequest,
140 ToolExecution,
141 SessionsList,
142 StreamProcessing,
143 LocalContext,
144 Rulebooks,
145 CheckpointResume,
146}
147
148#[derive(Debug, Clone, PartialEq)]
149pub enum ToolCallStatus {
150 Approved,
151 Rejected,
152 Executed,
153 Skipped,
154 Pending,
155}
156
157#[derive(Debug, Clone, Copy, PartialEq, Default)]
159pub enum ShortcutsPopupMode {
160 #[default]
161 Commands,
162 Shortcuts,
163 Sessions,
164}
165
166#[derive(Debug)]
167pub struct LoadingStateManager {
168 active_operations: std::collections::HashSet<LoadingOperation>,
169}
170
171impl Default for LoadingStateManager {
172 fn default() -> Self {
173 Self::new()
174 }
175}
176
177impl LoadingStateManager {
178 pub fn new() -> Self {
179 Self {
180 active_operations: std::collections::HashSet::new(),
181 }
182 }
183
184 pub fn start_operation(&mut self, operation: LoadingOperation) {
185 self.active_operations.insert(operation);
186 }
187
188 pub fn end_operation(&mut self, operation: LoadingOperation) {
189 self.active_operations.remove(&operation);
190 }
191
192 pub fn is_loading(&self) -> bool {
193 !self.active_operations.is_empty()
194 }
195
196 pub fn get_loading_type(&self) -> LoadingType {
197 if self
198 .active_operations
199 .contains(&LoadingOperation::SessionsList)
200 {
201 LoadingType::Sessions
202 } else {
203 LoadingType::Llm
204 }
205 }
206
207 pub fn clear_all(&mut self) {
208 self.active_operations.clear();
209 }
210}