codex_runtime/ergonomic/
config.rs1use std::path::PathBuf;
2use std::sync::Arc;
3use std::time::Duration;
4
5use serde_json::Value;
6
7use crate::plugin::{PostHook, PreHook};
8use crate::runtime::{
9 ApprovalPolicy, ClientConfig, CompatibilityGuard, InitializeCapabilities, PromptAttachment,
10 ReasoningEffort, RunProfile, RuntimeHookConfig, SandboxPolicy, SessionConfig, ShellCommandHook,
11};
12
13use crate::ergonomic::paths::absolutize_cwd_without_fs_checks;
14
15#[derive(Clone, Debug, PartialEq)]
18pub struct WorkflowConfig {
19 pub cwd: String,
20 pub client_config: ClientConfig,
21 pub run_profile: RunProfile,
22}
23
24impl WorkflowConfig {
25 pub fn new(cwd: impl Into<String>) -> Self {
31 let normalized_cwd = absolutize_cwd_without_fs_checks(&cwd.into());
32 Self {
33 cwd: normalized_cwd,
34 client_config: ClientConfig::new(),
35 run_profile: RunProfile::new(),
36 }
37 }
38
39 pub fn with_client_config(mut self, client_config: ClientConfig) -> Self {
41 self.client_config = client_config;
42 self
43 }
44
45 pub fn with_run_profile(mut self, run_profile: RunProfile) -> Self {
47 self.run_profile = run_profile;
48 self
49 }
50
51 pub fn with_cli_bin(mut self, cli_bin: impl Into<PathBuf>) -> Self {
53 self.client_config = self.client_config.with_cli_bin(cli_bin);
54 self
55 }
56
57 pub fn with_compatibility_guard(mut self, guard: CompatibilityGuard) -> Self {
59 self.client_config = self.client_config.with_compatibility_guard(guard);
60 self
61 }
62
63 pub fn without_compatibility_guard(mut self) -> Self {
65 self.client_config = self.client_config.without_compatibility_guard();
66 self
67 }
68
69 pub fn with_initialize_capabilities(
71 mut self,
72 initialize_capabilities: InitializeCapabilities,
73 ) -> Self {
74 self.client_config = self
75 .client_config
76 .with_initialize_capabilities(initialize_capabilities);
77 self
78 }
79
80 pub fn enable_experimental_api(mut self) -> Self {
82 self.client_config = self.client_config.enable_experimental_api();
83 self
84 }
85
86 pub fn with_global_hooks(mut self, hooks: RuntimeHookConfig) -> Self {
88 self.client_config = self.client_config.with_hooks(hooks);
89 self
90 }
91
92 pub fn with_global_pre_hook(mut self, hook: Arc<dyn PreHook>) -> Self {
94 self.client_config = self.client_config.with_pre_hook(hook);
95 self
96 }
97
98 pub fn with_global_post_hook(mut self, hook: Arc<dyn PostHook>) -> Self {
100 self.client_config = self.client_config.with_post_hook(hook);
101 self
102 }
103
104 pub fn with_global_pre_tool_use_hook(mut self, hook: Arc<dyn PreHook>) -> Self {
108 self.client_config = self.client_config.with_pre_tool_use_hook(hook);
109 self
110 }
111
112 pub fn with_model(mut self, model: impl Into<String>) -> Self {
114 self.run_profile = self.run_profile.with_model(model);
115 self
116 }
117
118 pub fn with_effort(mut self, effort: ReasoningEffort) -> Self {
120 self.run_profile = self.run_profile.with_effort(effort);
121 self
122 }
123
124 pub fn with_approval_policy(mut self, approval_policy: ApprovalPolicy) -> Self {
126 self.run_profile = self.run_profile.with_approval_policy(approval_policy);
127 self
128 }
129
130 pub fn with_sandbox_policy(mut self, sandbox_policy: SandboxPolicy) -> Self {
132 self.run_profile = self.run_profile.with_sandbox_policy(sandbox_policy);
133 self
134 }
135
136 pub fn with_timeout(mut self, timeout: Duration) -> Self {
138 self.run_profile = self.run_profile.with_timeout(timeout);
139 self
140 }
141
142 pub fn with_output_schema(mut self, output_schema: Value) -> Self {
144 self.run_profile = self.run_profile.with_output_schema(output_schema);
145 self
146 }
147
148 pub fn with_attachment(mut self, attachment: PromptAttachment) -> Self {
150 self.run_profile = self.run_profile.with_attachment(attachment);
151 self
152 }
153
154 pub fn attach_path(mut self, path: impl Into<String>) -> Self {
156 self.run_profile = self.run_profile.attach_path(path);
157 self
158 }
159
160 pub fn attach_path_with_placeholder(
162 mut self,
163 path: impl Into<String>,
164 placeholder: impl Into<String>,
165 ) -> Self {
166 self.run_profile = self
167 .run_profile
168 .attach_path_with_placeholder(path, placeholder);
169 self
170 }
171
172 pub fn attach_image_url(mut self, url: impl Into<String>) -> Self {
174 self.run_profile = self.run_profile.attach_image_url(url);
175 self
176 }
177
178 pub fn attach_local_image(mut self, path: impl Into<String>) -> Self {
180 self.run_profile = self.run_profile.attach_local_image(path);
181 self
182 }
183
184 pub fn attach_skill(mut self, name: impl Into<String>, path: impl Into<String>) -> Self {
186 self.run_profile = self.run_profile.attach_skill(name, path);
187 self
188 }
189
190 pub fn with_run_hooks(mut self, hooks: RuntimeHookConfig) -> Self {
192 self.run_profile = self.run_profile.with_hooks(hooks);
193 self
194 }
195
196 pub fn with_run_pre_hook(mut self, hook: Arc<dyn PreHook>) -> Self {
198 self.run_profile = self.run_profile.with_pre_hook(hook);
199 self
200 }
201
202 pub fn with_run_post_hook(mut self, hook: Arc<dyn PostHook>) -> Self {
204 self.run_profile = self.run_profile.with_post_hook(hook);
205 self
206 }
207
208 pub fn with_shell_pre_hook(self, name: &'static str, command: impl Into<String>) -> Self {
213 self.with_global_pre_hook(Arc::new(ShellCommandHook::new(name, command)))
214 }
215
216 pub fn with_shell_post_hook(self, name: &'static str, command: impl Into<String>) -> Self {
221 self.with_global_post_hook(Arc::new(ShellCommandHook::new(name, command)))
222 }
223
224 pub fn with_shell_pre_hook_timeout(
227 self,
228 name: &'static str,
229 command: impl Into<String>,
230 timeout: Duration,
231 ) -> Self {
232 self.with_global_pre_hook(Arc::new(
233 ShellCommandHook::new(name, command).with_timeout(timeout),
234 ))
235 }
236
237 pub fn to_session_config(&self) -> SessionConfig {
239 SessionConfig::from_profile(self.cwd.clone(), self.run_profile.clone())
240 }
241}