1use std::path::{Path, PathBuf};
2use std::sync::{Arc, RwLock};
3
4use codei_config::{load, LoadOptions, ResolvedConfig};
5use codei_llm::{create_provider, LlmProvider};
6use codei_mcp::McpManager;
7use codei_session::{Session, SessionStore};
8
9use crate::error::SdkError;
10
11#[derive(Clone)]
13pub struct AgentRuntime {
14 pub config: Arc<ResolvedConfig>,
15 pub provider: Arc<dyn LlmProvider>,
16 pub provider_name: String,
17 pub model: Arc<RwLock<String>>,
18 pub store: Arc<SessionStore>,
19 pub mcp: Option<Arc<McpManager>>,
20}
21
22pub struct InteractiveLaunch {
24 pub config: Arc<ResolvedConfig>,
25 pub provider: Arc<dyn LlmProvider>,
26 pub provider_name: String,
27 pub model: Arc<RwLock<String>>,
28 pub session: Session,
29 pub store: Arc<SessionStore>,
30 pub mcp: Option<Arc<McpManager>>,
31}
32
33impl InteractiveLaunch {
34 pub fn runtime(&self) -> AgentRuntime {
35 AgentRuntime {
36 config: Arc::clone(&self.config),
37 provider: Arc::clone(&self.provider),
38 provider_name: self.provider_name.clone(),
39 model: Arc::clone(&self.model),
40 store: Arc::clone(&self.store),
41 mcp: self.mcp.clone(),
42 }
43 }
44}
45
46pub fn resolve_session(
47 store: &SessionStore,
48 cwd: &Path,
49 resume: Option<&str>,
50 continue_latest: bool,
51) -> Result<Session, codei_session::SessionError> {
52 if let Some(id) = resume {
53 return store.load(id);
54 }
55 if continue_latest {
56 if let Some(session) = store.latest()? {
57 return Ok(session);
58 }
59 }
60 Ok(Session::new(cwd.to_path_buf()))
61}
62
63pub async fn build_interactive_launch(
64 config: Arc<ResolvedConfig>,
65 session: Session,
66 store: Arc<SessionStore>,
67) -> Result<InteractiveLaunch, SdkError> {
68 let runtime = build_agent_runtime(config, store).await?;
69 Ok(InteractiveLaunch {
70 config: runtime.config,
71 provider: runtime.provider,
72 provider_name: runtime.provider_name,
73 model: runtime.model,
74 session,
75 store: runtime.store,
76 mcp: runtime.mcp,
77 })
78}
79
80pub async fn build_agent_runtime(
81 config: Arc<ResolvedConfig>,
82 store: Arc<SessionStore>,
83) -> Result<AgentRuntime, SdkError> {
84 let provider_name = config.config.defaults.provider.clone();
85 let provider = create_provider(&config)?;
86 let mcp = McpManager::connect_optional().await;
87 let model = Arc::new(RwLock::new(config.config.defaults.model.clone()));
88 Ok(AgentRuntime {
89 config,
90 provider,
91 provider_name,
92 model,
93 store,
94 mcp,
95 })
96}
97
98pub async fn open_session_store(default_cwd: PathBuf) -> Result<Arc<SessionStore>, SdkError> {
99 let resolved = load(&LoadOptions {
100 cwd: Some(default_cwd),
101 ..Default::default()
102 })?;
103 Ok(Arc::new(SessionStore::open_for_config(
104 &resolved.config.session,
105 )?))
106}