1pub mod sub;
2use crate::config::Config;
3use crate::config::Profile;
4use crate::models::Backend;
5use crate::models::{
6 BenchTuneConfig, DiscoveredModel, ListSort, ModelSettings, ModelState, SearchResult,
7 SearchSort, ServerMetrics,
8};
9use ratatui::layout::Rect;
10use ratatui::text::Line;
11use serde::{Deserialize, Serialize};
12use std::collections::HashMap;
13use std::sync::atomic::AtomicBool;
14use std::sync::{Arc, Mutex};
15
16pub use sub::{
18 BenchTuneState, DownloadState, EditState, LoadingState, LogState, PendingOperations,
19 PickerState, SearchState, ServerState, SettingsState, UIState,
20};
21
22pub static API_PORT_CACHE: Mutex<(u16, String)> = Mutex::new((0, String::new()));
24
25pub struct ResizeState {
27 pub start_x: u16,
29 pub start_pct: u16,
31 pub container: Rect,
33}
34
35pub struct SettingsRenderCache {
37 pub hash: u64,
38 pub selected: usize,
39 pub lines: Vec<Line<'static>>,
40 pub selected_content_line: usize,
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
45pub enum ActivePanel {
46 #[default]
47 Models,
48 Log,
49 ServerSettings,
50 LlmSettings,
51 Profiles,
52 SystemPromptPresets,
53 SearchReadme,
54 ActiveModel,
55 ModelInfo,
56 Downloads,
57}
58
59#[derive(Debug, Clone)]
61pub enum ModelsMode {
62 List { sort_by: ListSort },
64 Search {
66 query: String,
67 results: Vec<SearchResult>,
68 sort_by: SearchSort,
69 show_readme: bool,
70 page: usize,
71 loading: bool,
73 has_more: bool,
75 },
76 Files {
78 model_id: String,
79 files: Vec<(String, u64, String)>, selected_idx: Option<usize>,
81 previous_query: String,
82 previous_results: Vec<SearchResult>,
83 selected_result: Option<SearchResult>,
84 },
85 BenchTune,
87}
88
89#[derive(Debug, Clone, PartialEq)]
91pub enum GlobalMode {
92 Normal,
93 CmdLine {
94 cmd_line: String,
95 },
96 HostPicker {
97 entries: Vec<(String, String)>, selected: usize,
99 },
100 BackendPicker {
101 entries: Vec<(Backend, Option<String>)>,
102 selected: usize,
103 },
104 Confirmation {
105 selected: bool,
106 kind: ConfirmationKind,
107 display_name: String,
108 detail: Option<String>,
109 },
110 RpcManager,
111 About,
112 MaxConcurrentPicker {
113 value: String,
114 },
115 SpecTypePicker {
116 entries: Vec<String>,
117 selected: usize,
118 },
119 YarnRoPESettings {
120 scale: String,
121 freq_base: String,
122 freq_scale: String,
123 selected_field: i32, editing: bool,
125 edit_buffer: String,
126 edit_cursor_pos: usize,
127 },
128 BenchTuneSetup {
129 config: BenchTuneConfig,
130 selected_idx: usize,
131 editing_param: bool,
132 editing_param_field: i32,
133 param_edit_buffer: String,
134 param_edit_cursor_pos: usize,
135 bench_mode_selection: usize,
136 editing_prompt: bool,
137 editing_kwargs: bool,
138 },
139 PromptPicker {
140 entries: Vec<(String, String)>, selected: usize,
142 editing: bool,
143 edit_buffer: String,
144 edit_cursor_pos: usize,
145 confirm_delete: bool,
146 },
147 ProfilePicker {
148 entries: Vec<(String, String)>, selected: usize,
150 profiles: Vec<Profile>,
151 },
152 DashboardPicker {
153 enabled: bool,
154 port: String,
155 auth_key: String,
156 tls_enabled: bool,
157 tls_cert: String,
158 tls_key: String,
159 selected_field: i32, editing: bool,
161 edit_buffer: String,
162 edit_cursor_pos: usize,
163 },
164 ApiEndpointPicker {
165 enabled: bool,
166 port: String,
167 api_key: String,
168 tls_enabled: bool,
169 tls_cert: String,
170 tls_key: String,
171 selected_field: i32, editing: bool,
173 edit_buffer: String,
174 edit_cursor_pos: usize,
175 },
176 DashboardUrl {
177 host: String,
178 ws_port: String,
179 api_port: u16,
180 llm_port: u16,
181 auth_key: String,
182 ws_enabled: bool,
183 tls_enabled: bool,
184 },
185 SearchInput {
186 buffer: String,
187 cursor_pos: usize,
188 },
189 GgufNaming {
190 explanation: crate::tui::gguf_naming::GgufExplanation,
191 filename: String,
192 },
193 Onboarding {
194 step: usize,
195 },
196 ChatTemplatePicker {
197 entries: Vec<String>,
198 selected: usize,
199 },
200 ChatTemplateFilePicker {
201 entries: Vec<(String, String)>, selected: usize,
203 },
204 WebSearchPicker {
205 enabled: bool,
206 engine: String,
207 engine_url: String,
208 api_key: Option<String>,
209 selected_field: i32, engine_picker_selected: usize,
211 editing: bool,
212 edit_buffer: String,
213 edit_cursor_pos: usize,
214 check_status: Option<WebSearchCheckStatus>,
215 },
216 LlamaServerOptionsPicker {
217 port: String,
218 threads: u32,
219 threads_batch: u32,
220 log_level: String,
221 webui: bool,
222 selected_field: i32, mode_picker_selected: usize,
224 editing: bool,
225 edit_buffer: String,
226 edit_cursor_pos: usize,
227 },
228}
229
230#[derive(Debug, Clone, PartialEq)]
231pub enum WebSearchCheckStatus {
232 Checking,
233 Ok,
234 Error(String),
235}
236
237#[derive(Debug, Clone, Copy, PartialEq, Eq)]
238pub enum ConfirmationKind {
239 Exit,
240 Reset,
241 Delete,
242 Unload,
243 DeleteBackend,
244}
245
246#[derive(Debug, Clone)]
248pub struct TextScrollState {
249 pub offset: usize,
250 pub last_tick: std::time::Instant,
251 pub direction: i8,
252 pub hold_count: u8,
253 pub max_offset: usize,
254 pub visible: bool,
255 pub cached_output: Option<String>,
257 pub cached_width: u16,
259 pub cached_offset: usize,
261}
262
263#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
265pub enum LoadingPhase {
266 ServerStarting,
267 LoadingModel,
268 LoadingMeta,
269 LoadingTensors,
270 ServerListening,
271 Complete,
272}
273
274impl LoadingPhase {
275 pub fn label(&self) -> &'static str {
276 match self {
277 LoadingPhase::ServerStarting => "Server starting...",
278 LoadingPhase::LoadingModel => "Loading model weights...",
279 LoadingPhase::LoadingMeta => "Loading metadata...",
280 LoadingPhase::LoadingTensors => "Loading tensors...",
281 LoadingPhase::ServerListening => "Server listening...",
282 LoadingPhase::Complete => "Ready",
283 }
284 }
285}
286
287pub struct App {
289 pub running: bool,
291 pub config: Config,
292 pub models: Vec<DiscoveredModel>,
293 pub selected_model_idx: Option<usize>,
294 pub models_mode: ModelsMode,
295 pub settings: ModelSettings,
296 pub model_settings_cache: ModelSettings,
297 pub model_states: HashMap<String, ModelState>,
298 pub metrics: ServerMetrics,
299 pub max_threads: u32,
300 pub cancelled: Option<Arc<AtomicBool>>,
301 pub server_mode: crate::models::ServerMode,
302 pub router_max_models: u32,
303 pub ws_server_handle: Option<tokio::task::JoinHandle<()>>,
304 pub ws_shutdown_tx: Option<tokio::sync::watch::Sender<bool>>,
305 pub background_tasks: HashMap<String, tokio::task::JoinHandle<()>>,
306
307 pub settings_state: SettingsState,
309 pub picker: PickerState,
310 pub download: DownloadState,
311 pub server: ServerState,
312 pub bench_tune: BenchTuneState,
313 pub log: LogState,
314 pub loading: LoadingState,
315 pub pending: PendingOperations,
316 pub search: SearchState,
317 pub ui: UIState,
318 pub edit: EditState,
319
320 pub active_model_hint: Option<(String, crate::models::ModelState)>,
323
324 pub pending_tx: tokio::sync::mpsc::Sender<super::pending_events::PendingEvent>,
326 pub pending_rx: tokio::sync::mpsc::Receiver<super::pending_events::PendingEvent>,
327 pub server_ready: bool,
328}