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