Skip to main content

codetether_agent/tui/app/state/
mod.rs

1//! TUI application state — the central `AppState` struct and its methods.
2//!
3//! Methods are split into focused submodules by concern:
4//!
5//! - `agent_profile` — spawned agent types and profile lookup
6//! - `profile_defs` — named profile constants
7//! - `slash_commands` — `/command` constant table
8//! - `input_cursor` — cursor movement and text editing
9//! - `slash_suggest` — slash autocomplete suggestion methods
10//! - `scroll` — chat scroll sentinel scheme and tool-preview scroll
11//! - `session_nav` — session list filtering and selection
12//! - `worker_bridge` — A2A worker connection state
13//! - `history` — command history ↑/↓ navigation
14//! - `model_picker` — async model refresh from providers
15//! - `model_picker_nav` — synchronous model picker navigation
16//! - `timing` — request latency tracking
17//! - `steering` — queued steering messages
18//! - `settings_nav` — settings selection and view-mode switching
19//! - `message_cache` — render-line cache for performance
20
21#![allow(dead_code)]
22
23pub mod agent_profile;
24pub mod default_impl;
25pub mod history;
26pub mod input_cursor;
27pub mod input_edit;
28pub mod message_cache;
29pub mod model_picker;
30pub mod model_picker_nav;
31pub mod profile_defs;
32pub mod scroll;
33pub mod session_nav;
34pub mod settings_nav;
35pub mod slash_commands;
36pub mod slash_suggest;
37pub mod timing;
38pub mod worker_bridge;
39
40#[cfg(test)]
41mod tests;
42
43// Re-exports so external `use crate::tui::app::state::X` still works.
44pub use agent_profile::{SpawnedAgent, agent_profile};
45pub use profile_defs::AgentProfile;
46pub use slash_commands::SLASH_COMMANDS;
47
48use std::collections::{HashMap, HashSet, VecDeque};
49use std::sync::Arc;
50use std::time::Instant;
51
52use crate::session::{ImageAttachment, SessionSummary};
53use crate::tui::audit_view::AuditViewState;
54use crate::tui::bus_log::BusLogState;
55use crate::tui::chat::message::ChatMessage;
56use crate::tui::help::HelpScrollState;
57use crate::tui::models::{InputMode, ViewMode};
58use crate::tui::ralph_view::RalphViewState;
59use crate::tui::swarm_view::SwarmViewState;
60use crate::tui::symbol_search::SymbolSearchState;
61use crate::tui::worker_bridge::IncomingTask;
62
63pub use crate::session::SessionEvent;
64
65#[derive(Default)]
66pub struct App {
67    pub state: AppState,
68}
69
70pub struct AppState {
71    pub view_mode: ViewMode,
72    pub input_mode: InputMode,
73    pub messages: Vec<ChatMessage>,
74    pub input: String,
75    pub input_cursor: usize,
76    pub input_scroll: usize,
77    pub chat_scroll: usize,
78    pub chat_last_max_scroll: usize,
79    pub tool_preview_scroll: usize,
80    pub tool_preview_last_max_scroll: usize,
81    /// Selected index in the protocol/agent registry view (left pane list).
82    pub protocol_selected: usize,
83    /// Vertical scroll offset for the protocol/agent registry detail pane.
84    pub protocol_scroll: usize,
85    pub status: String,
86    pub processing: bool,
87    pub session_id: Option<String>,
88    pub sessions: Vec<SessionSummary>,
89    pub selected_session: usize,
90    pub session_filter: String,
91    pub cwd_display: String,
92    pub bus_log: BusLogState,
93    pub swarm: SwarmViewState,
94    pub audit: AuditViewState,
95    pub ralph: RalphViewState,
96    pub symbol_search: SymbolSearchState,
97    pub slash_suggestions: Vec<String>,
98    pub selected_slash_suggestion: usize,
99    pub command_history: Vec<String>,
100    pub history_index: Option<usize>,
101    pub worker_id: Option<String>,
102    pub worker_name: Option<String>,
103    pub a2a_connected: bool,
104    pub recent_tasks: Vec<String>,
105    pub worker_bridge_registered_agents: HashSet<String>,
106    pub worker_bridge_processing_state: Option<bool>,
107    pub worker_task_queue: VecDeque<IncomingTask>,
108    pub help_scroll: HelpScrollState,
109    pub show_help: bool,
110    pub available_models: Vec<String>,
111    pub selected_model_index: usize,
112    pub model_picker_active: bool,
113    pub model_filter: String,
114    pub streaming_text: String,
115    pub processing_started_at: Option<Instant>,
116    pub current_request_first_token_ms: Option<u64>,
117    pub current_request_last_token_ms: Option<u64>,
118    pub last_request_first_token_ms: Option<u64>,
119    pub last_request_last_token_ms: Option<u64>,
120    pub last_completion_model: Option<String>,
121    pub last_completion_latency_ms: Option<u64>,
122    pub last_completion_prompt_tokens: Option<usize>,
123    pub last_completion_output_tokens: Option<usize>,
124    pub last_tool_name: Option<String>,
125    pub last_tool_latency_ms: Option<u64>,
126    pub last_tool_success: Option<bool>,
127    pub pending_images: Vec<ImageAttachment>,
128    pub auto_apply_edits: bool,
129    pub allow_network: bool,
130    pub slash_autocomplete: bool,
131    pub use_worktree: bool,
132    pub selected_settings_index: usize,
133    pub mcp_registry: Arc<crate::tui::app::mcp::TuiMcpRegistry>,
134    pub spawned_agents: HashMap<String, SpawnedAgent>,
135    pub active_spawned_agent: Option<String>,
136    pub streaming_agent_texts: HashMap<String, String>,
137    pub cached_message_lines: Vec<ratatui::text::Line<'static>>,
138    pub cached_messages_len: usize,
139    pub cached_max_width: usize,
140    pub cached_streaming_snapshot: Option<String>,
141    pub cached_processing: bool,
142    pub cached_frozen_len: usize,
143    pub watchdog_notification: Option<super::watchdog::WatchdogNotification>,
144    pub main_watchdog_root_prompt: Option<String>,
145    pub main_last_event_at: Option<Instant>,
146    pub main_watchdog_restart_count: u32,
147    pub main_inflight_prompt: Option<String>,
148    pub okr_repository: Option<Arc<crate::okr::OkrRepository>>,
149    pub pending_okr_approval: Option<super::okr_gate::PendingOkrApproval>,
150    pub pending_smart_switch_retry: Option<crate::tui::app::smart_switch::PendingSmartSwitchRetry>,
151    pub smart_switch_retry_count: u32,
152    pub smart_switch_attempted_models: Vec<String>,
153    pub chat_sync_rx:
154        Option<tokio::sync::mpsc::UnboundedReceiver<crate::tui::chat::sync::ChatSyncUiEvent>>,
155    pub chat_sync_status: Option<String>,
156    pub chat_sync_last_success: Option<String>,
157    pub chat_sync_last_error: Option<String>,
158    pub chat_sync_uploaded_bytes: u64,
159    pub chat_sync_uploaded_batches: u64,
160    pub autochat: super::autochat::state::AutochatState,
161    pub file_picker_dir: std::path::PathBuf,
162    pub file_picker_entries: Vec<crate::tui::app::file_picker::FilePickerEntry>,
163    pub file_picker_selected: usize,
164    pub file_picker_filter: String,
165    pub file_picker_active: bool,
166    pub workspace: crate::tui::models::WorkspaceSnapshot,
167    pub chat_layout_mode: crate::tui::ui::webview::layout_mode::ChatLayoutMode,
168    /// Cancel handle for the in-flight provider turn. Notifying this
169    /// interrupts the current LLM stream so a user steering message can
170    /// be applied immediately instead of waiting for the turn to finish.
171    pub current_turn_cancel: Option<Arc<tokio::sync::Notify>>,
172    /// Timestamp of the previous key event. Used to detect paste bursts
173    /// on terminals that don't forward bracketed-paste markers — if a
174    /// bare `Enter` arrives within `PASTE_BURST_WINDOW_MS` of the last
175    /// key, we treat it as an embedded newline in pasted text instead
176    /// of a submit, so pasting multi-line content doesn't emit one
177    /// chat message per line.
178    pub last_key_at: Option<Instant>,
179}