apiari_claude_sdk/
session.rs1use std::path::PathBuf;
9
10#[derive(Debug, Clone, Default)]
15pub struct SessionOptions {
16 pub resume: Option<String>,
19
20 pub continue_conversation: bool,
22
23 pub fork_session: bool,
25
26 pub session_id: Option<String>,
28
29 pub model: Option<String>,
32
33 pub fallback_model: Option<String>,
35
36 pub max_budget_usd: Option<f64>,
38
39 pub max_turns: Option<u64>,
41
42 pub system_prompt: Option<String>,
45
46 pub append_system_prompt: Option<String>,
48
49 pub tools: Vec<String>,
52
53 pub allowed_tools: Vec<String>,
55
56 pub disallowed_tools: Vec<String>,
58
59 pub permission_mode: Option<PermissionMode>,
61
62 pub dangerously_skip_permissions: bool,
64
65 pub mcp_config: Vec<String>,
68
69 pub strict_mcp_config: bool,
71
72 pub working_dir: Option<PathBuf>,
75
76 pub add_dirs: Vec<PathBuf>,
78
79 pub include_partial_messages: bool,
82
83 pub effort: Option<String>,
86
87 pub no_session_persistence: bool,
89
90 pub json_schema: Option<String>,
92
93 pub agents: Option<String>,
95
96 pub settings: Option<String>,
98
99 pub setting_sources: Vec<String>,
101
102 pub env_vars: Vec<(String, String)>,
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
108pub enum PermissionMode {
109 Default,
111 AcceptEdits,
113 Plan,
115 BypassPermissions,
117 DontAsk,
119}
120
121impl PermissionMode {
122 pub fn as_str(&self) -> &'static str {
124 match self {
125 Self::Default => "default",
126 Self::AcceptEdits => "acceptEdits",
127 Self::Plan => "plan",
128 Self::BypassPermissions => "bypassPermissions",
129 Self::DontAsk => "dontAsk",
130 }
131 }
132}
133
134impl SessionOptions {
135 pub fn to_cli_args(&self) -> Vec<String> {
141 let mut args = Vec::new();
142
143 if let Some(ref id) = self.resume {
145 args.extend(["--resume".to_owned(), id.clone()]);
146 }
147 if self.continue_conversation {
148 args.push("--continue".to_owned());
149 }
150 if self.fork_session {
151 args.push("--fork-session".to_owned());
152 }
153 if let Some(ref id) = self.session_id {
154 args.extend(["--session-id".to_owned(), id.clone()]);
155 }
156
157 if let Some(ref model) = self.model {
159 args.extend(["--model".to_owned(), model.clone()]);
160 }
161 if let Some(ref model) = self.fallback_model {
162 args.extend(["--fallback-model".to_owned(), model.clone()]);
163 }
164 if let Some(budget) = self.max_budget_usd {
165 args.extend(["--max-budget-usd".to_owned(), budget.to_string()]);
166 }
167 if let Some(turns) = self.max_turns {
168 args.extend(["--max-turns".to_owned(), turns.to_string()]);
169 }
170
171 if let Some(ref prompt) = self.system_prompt {
173 args.extend(["--system-prompt".to_owned(), prompt.clone()]);
174 }
175 if let Some(ref prompt) = self.append_system_prompt {
176 args.extend(["--append-system-prompt".to_owned(), prompt.clone()]);
177 }
178
179 if !self.tools.is_empty() {
181 args.extend(["--tools".to_owned(), self.tools.join(",")]);
182 }
183 if !self.allowed_tools.is_empty() {
184 args.push("--allowedTools".to_owned());
185 for tool in &self.allowed_tools {
186 args.push(tool.clone());
187 }
188 }
189 if !self.disallowed_tools.is_empty() {
190 args.push("--disallowedTools".to_owned());
191 for tool in &self.disallowed_tools {
192 args.push(tool.clone());
193 }
194 }
195 if let Some(mode) = self.permission_mode {
196 args.extend(["--permission-mode".to_owned(), mode.as_str().to_owned()]);
197 }
198 if self.dangerously_skip_permissions {
199 args.push("--dangerously-skip-permissions".to_owned());
200 }
201
202 if !self.mcp_config.is_empty() {
204 args.push("--mcp-config".to_owned());
205 for cfg in &self.mcp_config {
206 args.push(cfg.clone());
207 }
208 }
209 if self.strict_mcp_config {
210 args.push("--strict-mcp-config".to_owned());
211 }
212
213 if !self.add_dirs.is_empty() {
215 args.push("--add-dir".to_owned());
216 for dir in &self.add_dirs {
217 args.push(dir.display().to_string());
218 }
219 }
220
221 if self.include_partial_messages {
223 args.push("--include-partial-messages".to_owned());
224 }
225
226 if let Some(ref effort) = self.effort {
228 args.extend(["--effort".to_owned(), effort.clone()]);
229 }
230 if self.no_session_persistence {
231 args.push("--no-session-persistence".to_owned());
232 }
233 if let Some(ref schema) = self.json_schema {
234 args.extend(["--json-schema".to_owned(), schema.clone()]);
235 }
236 if let Some(ref agents) = self.agents {
237 args.extend(["--agents".to_owned(), agents.clone()]);
238 }
239 if let Some(ref settings) = self.settings {
240 args.extend(["--settings".to_owned(), settings.clone()]);
241 }
242 if !self.setting_sources.is_empty() {
243 args.extend([
244 "--setting-sources".to_owned(),
245 self.setting_sources.join(","),
246 ]);
247 }
248
249 args
250 }
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256
257 #[test]
258 fn empty_options_produce_no_args() {
259 let opts = SessionOptions::default();
260 assert!(opts.to_cli_args().is_empty());
261 }
262
263 #[test]
264 fn model_and_tools_args() {
265 let opts = SessionOptions {
266 model: Some("sonnet".to_owned()),
267 allowed_tools: vec!["Bash".to_owned(), "Read".to_owned()],
268 max_turns: Some(5),
269 ..Default::default()
270 };
271 let args = opts.to_cli_args();
272 assert!(args.contains(&"--model".to_owned()));
273 assert!(args.contains(&"sonnet".to_owned()));
274 assert!(args.contains(&"--allowedTools".to_owned()));
275 assert!(args.contains(&"Bash".to_owned()));
276 assert!(args.contains(&"Read".to_owned()));
277 assert!(args.contains(&"--max-turns".to_owned()));
278 assert!(args.contains(&"5".to_owned()));
279 }
280
281 #[test]
282 fn resume_and_continue_flags() {
283 let opts = SessionOptions {
284 resume: Some("abc-123".to_owned()),
285 fork_session: true,
286 ..Default::default()
287 };
288 let args = opts.to_cli_args();
289 assert!(args.contains(&"--resume".to_owned()));
290 assert!(args.contains(&"abc-123".to_owned()));
291 assert!(args.contains(&"--fork-session".to_owned()));
292 }
293
294 #[test]
295 fn permission_mode_flag() {
296 let opts = SessionOptions {
297 permission_mode: Some(PermissionMode::AcceptEdits),
298 ..Default::default()
299 };
300 let args = opts.to_cli_args();
301 assert!(args.contains(&"--permission-mode".to_owned()));
302 assert!(args.contains(&"acceptEdits".to_owned()));
303 }
304}