wisp/session/
session_model.rs1use crate::session::session_config_view::{LocalConfigKind, LocalConfigOption};
2use crate::session::workspace_status::WorkspaceStatus;
3use acp_utils::notifications::{AetherCapabilities, McpServerStatus, McpServerStatusEntry};
4use agent_client_protocol::schema::v1::{self as acp, SessionId};
5use std::path::{Path, PathBuf};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum WorkspaceMoveState {
9 Idle,
10 Listing,
11 Picking,
12 Moving,
13 LoadingSession,
14}
15
16impl WorkspaceMoveState {
17 pub fn is_idle(self) -> bool {
18 matches!(self, Self::Idle)
19 }
20}
21
22pub struct SessionModel {
23 session_id: SessionId,
24 agent_name: String,
25 working_dir: PathBuf,
26 workspace_status: WorkspaceStatus,
27 prompt_capabilities: acp::PromptCapabilities,
28 capabilities: AetherCapabilities,
29 config_options: Vec<LocalConfigOption>,
30 auth_methods: Vec<acp::AuthMethod>,
31 workspace_move_state: WorkspaceMoveState,
32 server_statuses: Vec<McpServerStatusEntry>,
33}
34
35impl SessionModel {
36 pub fn from_config(config: crate::app::AppConfig, capabilities: AetherCapabilities) -> Self {
37 let crate::app::AppConfig {
38 session_id,
39 agent_name,
40 working_dir,
41 workspace_status,
42 prompt_capabilities,
43 config_options,
44 auth_methods,
45 ..
46 } = config;
47 Self {
48 session_id,
49 agent_name,
50 working_dir,
51 workspace_status,
52 prompt_capabilities,
53 capabilities,
54 config_options: config_options.into_iter().map(LocalConfigOption::from_acp).collect(),
55 auth_methods,
56 workspace_move_state: WorkspaceMoveState::Idle,
57 server_statuses: Vec::new(),
58 }
59 }
60
61 pub fn session_id(&self) -> &SessionId {
62 &self.session_id
63 }
64
65 pub fn agent_name(&self) -> &str {
66 &self.agent_name
67 }
68
69 pub fn working_dir(&self) -> &Path {
70 &self.working_dir
71 }
72
73 pub fn prompt_capabilities(&self) -> &acp::PromptCapabilities {
74 &self.prompt_capabilities
75 }
76
77 pub fn capabilities(&self) -> &AetherCapabilities {
78 &self.capabilities
79 }
80
81 pub fn config_options(&self) -> &[LocalConfigOption] {
82 &self.config_options
83 }
84
85 pub fn auth_methods(&self) -> &[acp::AuthMethod] {
86 &self.auth_methods
87 }
88
89 pub fn workspace_status(&self) -> &WorkspaceStatus {
90 &self.workspace_status
91 }
92
93 pub fn workspace_move_state(&self) -> WorkspaceMoveState {
94 self.workspace_move_state
95 }
96
97 pub fn begin_workspace_listing(&mut self) {
98 self.workspace_move_state = WorkspaceMoveState::Listing;
99 }
100
101 pub fn begin_workspace_picking(&mut self) {
102 self.workspace_move_state = WorkspaceMoveState::Picking;
103 }
104
105 pub fn begin_workspace_move(&mut self) {
106 self.workspace_move_state = WorkspaceMoveState::Moving;
107 }
108
109 pub fn begin_workspace_load(&mut self) {
111 self.workspace_move_state = WorkspaceMoveState::LoadingSession;
112 }
113
114 pub fn end_workspace_move(&mut self) {
117 self.workspace_move_state = WorkspaceMoveState::Idle;
118 }
119
120 pub fn cancel_workspace_picking(&mut self) {
123 if self.workspace_move_state == WorkspaceMoveState::Picking {
124 self.workspace_move_state = WorkspaceMoveState::Idle;
125 }
126 }
127
128 pub fn server_statuses(&self) -> &[McpServerStatusEntry] {
129 &self.server_statuses
130 }
131
132 pub fn unhealthy_server_count(&self) -> usize {
133 self.server_statuses.iter().filter(|server| !matches!(server.status, McpServerStatus::Connected { .. })).count()
134 }
135
136 pub fn update_server_statuses(&mut self, statuses: &[McpServerStatusEntry]) {
137 self.server_statuses = statuses.to_vec();
138 }
139
140 pub fn set_auth_methods(&mut self, auth_methods: &[acp::AuthMethod]) {
141 self.auth_methods = auth_methods.to_vec();
142 }
143
144 pub fn update_config_options(&mut self, config_options: Vec<acp::SessionConfigOption>) {
148 let next = config_options.into_iter().map(LocalConfigOption::from_acp).collect::<Vec<_>>();
149 self.config_options = next;
150 }
151
152 pub fn update_config_option_value(&mut self, config_id: &str, value: &str) {
153 if let Some(option) = self.config_options.iter_mut().find(|option| option.id == config_id)
154 && let LocalConfigKind::Select { current_value, .. } = &mut option.kind
155 {
156 current_value.clear();
157 current_value.push_str(value);
158 }
159 }
160
161
162 pub fn set_session(&mut self, session_id: SessionId, config_options: Vec<acp::SessionConfigOption>) {
163 self.session_id = session_id;
164 self.config_options = config_options.into_iter().map(LocalConfigOption::from_acp).collect();
165 }
166
167 pub fn set_working_dir(&mut self, working_dir: PathBuf) {
168 self.working_dir = working_dir;
169 }
170
171 pub fn set_workspace_status(&mut self, workspace_status: WorkspaceStatus) {
172 self.workspace_status = workspace_status;
173 }
174}