1use crate::cli::Cli;
2use crate::error::AppError;
3use crate::settings::{StatusLineSettings, WispSettings};
4use crate::workspace_status::WorkspaceStatus;
5use acp_utils::client::{AcpEvent, AcpPromptHandle, spawn_acp_session};
6use agent_client_protocol::schema::{
7 AuthMethod, Implementation, InitializeRequest, NewSessionRequest, PromptCapabilities, ProtocolVersion,
8 SessionCapabilities, SessionConfigOption, SessionId,
9};
10use std::env::current_dir;
11use tokio::sync::mpsc;
12use tui::Theme;
13
14#[doc = include_str!("docs/runtime_state.md")]
15pub struct RuntimeState {
16 pub session_id: SessionId,
17 pub agent_name: String,
18 pub prompt_capabilities: PromptCapabilities,
19 pub session_capabilities: SessionCapabilities,
20 pub config_options: Vec<SessionConfigOption>,
21 pub auth_methods: Vec<AuthMethod>,
22 pub theme: Theme,
23 pub settings: WispSettings,
24 pub event_rx: mpsc::UnboundedReceiver<AcpEvent>,
25 pub prompt_handle: AcpPromptHandle,
26 pub working_dir: std::path::PathBuf,
27 pub workspace_status: WorkspaceStatus,
28}
29
30impl RuntimeState {
31 pub async fn new(agent_command: &str, settings: WispSettings) -> Result<Self, AppError> {
32 let cwd = current_dir().unwrap_or_else(|_| std::path::PathBuf::from("."));
33 let workspace_status = WorkspaceStatus::resolve(&cwd);
34 let new_session_request = NewSessionRequest::new(cwd.clone());
35 let init_request = InitializeRequest::new(ProtocolVersion::LATEST)
36 .client_info(Implementation::new("wisp", env!("CARGO_PKG_VERSION")));
37
38 let session =
39 spawn_acp_session(agent_command, init_request, new_session_request).await.map_err(AppError::Acp)?;
40
41 let theme = crate::settings::load_theme(&settings);
42
43 Ok(Self {
44 session_id: session.session_id,
45 agent_name: session.agent_name,
46 prompt_capabilities: session.prompt_capabilities,
47 session_capabilities: session.session_capabilities,
48 config_options: session.config_options,
49 auth_methods: session.auth_methods,
50 theme,
51 settings,
52 event_rx: session.event_rx,
53 prompt_handle: session.prompt_handle,
54 working_dir: cwd,
55 workspace_status,
56 })
57 }
58
59 pub async fn from_cli(cli: &Cli) -> Result<Self, AppError> {
60 Self::new(&cli.agent, crate::settings::load_or_create_settings(StatusLineSettings::defaults())).await
61 }
62}