Skip to main content

wisp/
runtime_state.rs

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