1use std::path::PathBuf;
4use std::sync::Arc;
5
6use codei_agent::{AgentEvent, TurnOutcome};
7use codei_config::{load, LoadOptions, ResolvedConfig};
8use codei_session::{Session, SessionStore};
9
10use crate::error::SdkError;
11use crate::runtime::build_interactive_launch;
12use crate::turn::{approval_policy, run_turn_with_events};
13
14#[derive(Debug, Clone)]
16pub struct RunResult {
17 pub session_id: String,
18 pub outcome: TurnOutcome,
19}
20
21pub struct CodeiClientBuilder {
23 cwd: Option<PathBuf>,
24 model: Option<String>,
25 provider: Option<String>,
26 auto_approve: bool,
27}
28
29impl Default for CodeiClientBuilder {
30 fn default() -> Self {
31 Self {
32 cwd: None,
33 model: None,
34 provider: None,
35 auto_approve: true,
36 }
37 }
38}
39
40impl CodeiClientBuilder {
41 pub fn new() -> Self {
42 Self::default()
43 }
44
45 pub fn cwd(mut self, cwd: impl Into<PathBuf>) -> Self {
46 self.cwd = Some(cwd.into());
47 self
48 }
49
50 pub fn model(mut self, model: impl Into<String>) -> Self {
51 self.model = Some(model.into());
52 self
53 }
54
55 pub fn provider(mut self, provider: impl Into<String>) -> Self {
56 self.provider = Some(provider.into());
57 self
58 }
59
60 pub fn auto_approve(mut self, yes: bool) -> Self {
61 self.auto_approve = yes;
62 self
63 }
64
65 pub async fn build(self) -> Result<CodeiClient, SdkError> {
66 let resolved = load(&LoadOptions {
67 cwd: self.cwd,
68 model: self.model.clone(),
69 provider: self.provider.clone(),
70 language: None,
71 })?;
72
73 let config = Arc::new(resolved);
74 let store = Arc::new(SessionStore::open_for_config(&config.config.session)?);
75 let session = Session::new(config.cwd.clone());
76 let launch = build_interactive_launch(config, session, store).await?;
77
78 Ok(CodeiClient {
79 launch,
80 auto_approve: self.auto_approve,
81 })
82 }
83}
84
85pub struct CodeiClient {
87 launch: crate::runtime::InteractiveLaunch,
88 auto_approve: bool,
89}
90
91impl CodeiClient {
92 pub fn builder() -> CodeiClientBuilder {
93 CodeiClientBuilder::new()
94 }
95
96 pub fn config(&self) -> &Arc<ResolvedConfig> {
97 &self.launch.config
98 }
99
100 pub async fn run_with_handler<F>(
102 &mut self,
103 prompt: &str,
104 on_event: F,
105 ) -> Result<RunResult, SdkError>
106 where
107 F: FnMut(AgentEvent),
108 {
109 let policy = approval_policy(self.auto_approve);
110 let session_id = self.launch.session.id.clone();
111 let runtime = self.launch.runtime();
112
113 let outcome =
114 run_turn_with_events(&runtime, &mut self.launch.session, prompt, policy, on_event)
115 .await?;
116
117 Ok(RunResult {
118 session_id,
119 outcome,
120 })
121 }
122
123 pub async fn run(&mut self, prompt: &str) -> Result<RunResult, SdkError> {
125 self.run_with_handler(prompt, |_| {}).await
126 }
127}