Skip to main content

cli_agents/
types.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4/// Supported CLI agents.
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
6#[serde(rename_all = "lowercase")]
7#[non_exhaustive]
8pub enum CliName {
9    Claude,
10    Codex,
11    Gemini,
12}
13
14impl std::fmt::Display for CliName {
15    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16        match self {
17            Self::Claude => write!(f, "claude"),
18            Self::Codex => write!(f, "codex"),
19            Self::Gemini => write!(f, "gemini"),
20        }
21    }
22}
23
24/// MCP server configuration.
25#[derive(Debug, Clone, Default, Serialize, Deserialize)]
26#[serde(rename_all = "camelCase")]
27pub struct McpServer {
28    // ── stdio transport ──
29    pub command: Option<String>,
30    pub args: Option<Vec<String>>,
31    pub env: Option<HashMap<String, String>>,
32    pub cwd: Option<String>,
33
34    // ── HTTP/SSE transport ──
35    pub url: Option<String>,
36    #[serde(rename = "type")]
37    pub transport_type: Option<McpTransport>,
38    pub headers: Option<HashMap<String, String>>,
39
40    // ── Tool filtering ──
41    pub include_tools: Option<Vec<String>>,
42    pub exclude_tools: Option<Vec<String>>,
43
44    // ── Timeouts ──
45    pub timeout: Option<u64>,
46}
47
48#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
49#[serde(rename_all = "lowercase")]
50pub enum McpTransport {
51    Stdio,
52    Sse,
53    Http,
54}
55
56/// Filesystem setting sources Claude Code loads at startup.
57///
58/// Maps to the `--setting-sources` CLI flag. When omitted, the Claude CLI
59/// loads all three (user, project, local) and fires their hooks.
60/// Pass `Some(vec![])` to skip all of them — useful when embedding the CLI
61/// in another app that doesn't want global SessionStart hooks running.
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
63#[serde(rename_all = "lowercase")]
64pub enum SettingSource {
65    User,
66    Project,
67    Local,
68}
69
70impl SettingSource {
71    pub fn as_str(&self) -> &'static str {
72        match self {
73            Self::User => "user",
74            Self::Project => "project",
75            Self::Local => "local",
76        }
77    }
78}
79
80// ── Provider-specific options ──
81
82#[derive(Debug, Clone, Default, Serialize, Deserialize)]
83#[serde(rename_all = "camelCase")]
84pub struct ClaudeOptions {
85    pub allowed_tools: Option<String>,
86    pub disallowed_tools: Option<String>,
87    pub tools: Option<String>,
88    pub append_system_prompt: Option<String>,
89    pub max_turns: Option<u32>,
90    pub max_budget_usd: Option<f64>,
91    pub max_thinking_tokens: Option<u32>,
92    pub continue_session: Option<bool>,
93    pub include_partial_messages: Option<bool>,
94    pub effort: Option<String>,
95    pub agents: Option<serde_json::Value>,
96    /// Filesystem settings the CLI loads (and fires hooks for).
97    /// `None` = let the CLI default (loads user/project/local).
98    /// `Some(vec![])` = load nothing — silences global SessionStart hooks.
99    pub setting_sources: Option<Vec<SettingSource>>,
100}
101
102#[derive(Debug, Clone, Default, Serialize, Deserialize)]
103#[serde(rename_all = "camelCase")]
104pub struct CodexOptions {
105    pub approval_policy: Option<String>,
106    pub sandbox_mode: Option<String>,
107    pub additional_directories: Option<Vec<String>>,
108    pub images: Option<Vec<String>>,
109    pub output_schema: Option<String>,
110}
111
112#[derive(Debug, Clone, Default, Serialize, Deserialize)]
113#[serde(rename_all = "camelCase")]
114pub struct GeminiOptions {
115    pub approval_mode: Option<String>,
116    pub sandbox: Option<bool>,
117    pub extra_args: Option<Vec<String>>,
118}
119
120#[derive(Debug, Clone, Default, Serialize, Deserialize)]
121pub struct ProviderOptions {
122    pub claude: Option<ClaudeOptions>,
123    pub codex: Option<CodexOptions>,
124    pub gemini: Option<GeminiOptions>,
125}
126
127/// Options passed to [`run()`](crate::run).
128#[derive(Debug, Clone, Default, Serialize, Deserialize)]
129#[serde(rename_all = "camelCase")]
130pub struct RunOptions {
131    /// Which CLI to use. If `None`, auto-discovers the first available.
132    pub cli: Option<CliName>,
133
134    /// The task/prompt to send to the agent.
135    pub task: String,
136
137    /// System prompt (where supported).
138    pub system_prompt: Option<String>,
139
140    /// Path to a system prompt file (alternative to inline `system_prompt`).
141    pub system_prompt_file: Option<String>,
142
143    /// MCP servers to connect.
144    pub mcp_servers: Option<HashMap<String, McpServer>>,
145
146    /// Working directory for the CLI process.
147    pub cwd: Option<String>,
148
149    /// Model name (e.g. "sonnet", "opus", "o3").
150    pub model: Option<String>,
151
152    /// Idle timeout in milliseconds. Default: 300_000 (5 minutes).
153    pub idle_timeout_ms: Option<u64>,
154
155    /// Total timeout in milliseconds. No default.
156    pub total_timeout_ms: Option<u64>,
157
158    /// Max consecutive tool failures before aborting. Default: 3.
159    pub max_consecutive_tool_failures: Option<u32>,
160
161    /// Extra environment variables for the CLI process.
162    pub env: Option<HashMap<String, String>>,
163
164    /// Explicit path to the CLI executable (skips discovery).
165    pub executable_path: Option<String>,
166
167    /// Session ID to resume a previous conversation.
168    pub resume_session_id: Option<String>,
169
170    /// Maximum bytes to buffer from CLI stdout before aborting.
171    ///
172    /// Prevents OOM if the CLI produces unexpectedly large output.
173    /// Defaults to 10 MB when `None`.
174    pub max_output_bytes: Option<usize>,
175
176    /// Skip permission prompts and run in fully autonomous mode.
177    ///
178    /// When `true`, passes provider-specific flags to bypass interactive approval
179    /// (e.g. `--dangerously-skip-permissions` for Claude). **Use with caution** —
180    /// the agent will be able to execute tools without human confirmation.
181    ///
182    /// Defaults to `false`.
183    #[serde(default)]
184    pub skip_permissions: bool,
185
186    /// Provider-specific options.
187    pub providers: Option<ProviderOptions>,
188}
189
190/// Result from a completed run.
191#[derive(Debug, Clone, Default, Serialize, Deserialize)]
192#[serde(rename_all = "camelCase")]
193#[non_exhaustive]
194pub struct RunResult {
195    pub success: bool,
196    pub text: Option<String>,
197    pub exit_code: Option<i32>,
198    pub stats: Option<RunStats>,
199    pub session_id: Option<String>,
200    pub stderr: Option<String>,
201    pub cost_usd: Option<f64>,
202}
203
204#[derive(Debug, Clone, Default, Serialize, Deserialize)]
205#[serde(rename_all = "camelCase")]
206#[non_exhaustive]
207pub struct RunStats {
208    pub input_tokens: Option<u64>,
209    pub output_tokens: Option<u64>,
210    pub total_tokens: Option<u64>,
211    pub cached_tokens: Option<u64>,
212    pub duration_ms: Option<u64>,
213    pub tool_calls: Option<u32>,
214}