codex_runtime/runtime/client/
profile.rs1use std::sync::Arc;
2use std::time::Duration;
3
4use serde_json::Value;
5
6use crate::plugin::{PostHook, PreHook};
7use crate::runtime::api::{
8 ApprovalPolicy, PromptAttachment, PromptRunParams, ReasoningEffort, SandboxPolicy,
9 SandboxPreset, ThreadStartParams, DEFAULT_REASONING_EFFORT,
10};
11use crate::runtime::hooks::RuntimeHookConfig;
12
13#[derive(Clone, Debug, PartialEq)]
14struct ProfileCore {
15 model: Option<String>,
16 effort: ReasoningEffort,
17 approval_policy: ApprovalPolicy,
18 sandbox_policy: SandboxPolicy,
19 privileged_escalation_approved: bool,
20 attachments: Vec<PromptAttachment>,
21 timeout: Duration,
22 output_schema: Option<Value>,
23 hooks: RuntimeHookConfig,
24}
25
26impl Default for ProfileCore {
27 fn default() -> Self {
28 Self {
29 model: None,
30 effort: DEFAULT_REASONING_EFFORT,
31 approval_policy: ApprovalPolicy::Never,
32 sandbox_policy: SandboxPolicy::Preset(SandboxPreset::ReadOnly),
33 privileged_escalation_approved: false,
34 attachments: Vec::new(),
35 timeout: Duration::from_secs(120),
36 output_schema: None,
37 hooks: RuntimeHookConfig::default(),
38 }
39 }
40}
41
42impl ProfileCore {
43 fn into_run_profile(self) -> RunProfile {
44 RunProfile {
45 model: self.model,
46 effort: self.effort,
47 approval_policy: self.approval_policy,
48 sandbox_policy: self.sandbox_policy,
49 privileged_escalation_approved: self.privileged_escalation_approved,
50 attachments: self.attachments,
51 timeout: self.timeout,
52 output_schema: self.output_schema,
53 hooks: self.hooks,
54 }
55 }
56
57 fn into_session_config(self, cwd: String) -> SessionConfig {
58 SessionConfig {
59 cwd,
60 model: self.model,
61 effort: self.effort,
62 approval_policy: self.approval_policy,
63 sandbox_policy: self.sandbox_policy,
64 privileged_escalation_approved: self.privileged_escalation_approved,
65 attachments: self.attachments,
66 timeout: self.timeout,
67 output_schema: self.output_schema,
68 hooks: self.hooks,
69 }
70 }
71
72 fn into_prompt_params(self, cwd: String, prompt: String) -> PromptRunParams {
73 PromptRunParams {
74 cwd,
75 prompt,
76 model: self.model,
77 effort: Some(self.effort),
78 approval_policy: self.approval_policy,
79 sandbox_policy: self.sandbox_policy,
80 privileged_escalation_approved: self.privileged_escalation_approved,
81 attachments: self.attachments,
82 timeout: self.timeout,
83 output_schema: self.output_schema,
84 }
85 }
86
87 fn into_thread_start_params(self, cwd: String) -> ThreadStartParams {
88 ThreadStartParams {
89 model: self.model,
90 cwd: Some(cwd),
91 approval_policy: Some(self.approval_policy),
92 sandbox_policy: Some(self.sandbox_policy),
93 privileged_escalation_approved: self.privileged_escalation_approved,
94 ..ThreadStartParams::default()
95 }
96 }
97}
98
99impl From<RunProfile> for ProfileCore {
100 fn from(profile: RunProfile) -> Self {
101 Self {
102 model: profile.model,
103 effort: profile.effort,
104 approval_policy: profile.approval_policy,
105 sandbox_policy: profile.sandbox_policy,
106 privileged_escalation_approved: profile.privileged_escalation_approved,
107 attachments: profile.attachments,
108 timeout: profile.timeout,
109 output_schema: profile.output_schema,
110 hooks: profile.hooks,
111 }
112 }
113}
114
115impl From<&SessionConfig> for ProfileCore {
116 fn from(config: &SessionConfig) -> Self {
117 Self {
118 model: config.model.clone(),
119 effort: config.effort,
120 approval_policy: config.approval_policy,
121 sandbox_policy: config.sandbox_policy.clone(),
122 privileged_escalation_approved: config.privileged_escalation_approved,
123 attachments: config.attachments.clone(),
124 timeout: config.timeout,
125 output_schema: config.output_schema.clone(),
126 hooks: config.hooks.clone(),
127 }
128 }
129}
130
131macro_rules! impl_profile_builder_methods {
132 () => {
133 pub fn with_model(mut self, model: impl Into<String>) -> Self {
136 self.model = Some(model.into());
137 self
138 }
139
140 pub fn with_effort(mut self, effort: ReasoningEffort) -> Self {
143 self.effort = effort;
144 self
145 }
146
147 pub fn with_approval_policy(mut self, approval_policy: ApprovalPolicy) -> Self {
150 self.approval_policy = approval_policy;
151 self
152 }
153
154 pub fn with_sandbox_policy(mut self, sandbox_policy: SandboxPolicy) -> Self {
157 self.sandbox_policy = sandbox_policy;
158 self
159 }
160
161 pub fn allow_privileged_escalation(mut self) -> Self {
163 self.privileged_escalation_approved = true;
164 self
165 }
166
167 pub fn with_timeout(mut self, timeout: Duration) -> Self {
170 self.timeout = timeout;
171 self
172 }
173
174 pub fn with_output_schema(mut self, output_schema: Value) -> Self {
176 self.output_schema = Some(output_schema);
177 self
178 }
179
180 pub fn with_attachment(mut self, attachment: PromptAttachment) -> Self {
183 self.attachments.push(attachment);
184 self
185 }
186
187 pub fn attach_path(self, path: impl Into<String>) -> Self {
190 self.with_attachment(PromptAttachment::AtPath {
191 path: path.into(),
192 placeholder: None,
193 })
194 }
195
196 pub fn attach_path_with_placeholder(
199 self,
200 path: impl Into<String>,
201 placeholder: impl Into<String>,
202 ) -> Self {
203 self.with_attachment(PromptAttachment::AtPath {
204 path: path.into(),
205 placeholder: Some(placeholder.into()),
206 })
207 }
208
209 pub fn attach_image_url(self, url: impl Into<String>) -> Self {
212 self.with_attachment(PromptAttachment::ImageUrl { url: url.into() })
213 }
214
215 pub fn attach_local_image(self, path: impl Into<String>) -> Self {
218 self.with_attachment(PromptAttachment::LocalImage { path: path.into() })
219 }
220
221 pub fn attach_skill(self, name: impl Into<String>, path: impl Into<String>) -> Self {
224 self.with_attachment(PromptAttachment::Skill {
225 name: name.into(),
226 path: path.into(),
227 })
228 }
229
230 pub fn with_hooks(mut self, hooks: RuntimeHookConfig) -> Self {
233 self.hooks = hooks;
234 self
235 }
236
237 pub fn with_pre_hook(mut self, hook: Arc<dyn PreHook>) -> Self {
240 self.hooks.pre_hooks.push(hook);
241 self
242 }
243
244 pub fn with_post_hook(mut self, hook: Arc<dyn PostHook>) -> Self {
247 self.hooks.post_hooks.push(hook);
248 self
249 }
250
251 pub fn with_pre_tool_use_hook(mut self, hook: Arc<dyn PreHook>) -> Self {
254 self.hooks.pre_tool_use_hooks.push(hook);
255 self
256 }
257 };
258}
259
260#[derive(Clone, Debug, PartialEq)]
261pub struct RunProfile {
262 pub model: Option<String>,
263 pub effort: ReasoningEffort,
264 pub approval_policy: ApprovalPolicy,
265 pub sandbox_policy: SandboxPolicy,
266 pub privileged_escalation_approved: bool,
268 pub attachments: Vec<PromptAttachment>,
269 pub timeout: Duration,
270 pub output_schema: Option<Value>,
271 pub hooks: RuntimeHookConfig,
272}
273
274impl Default for RunProfile {
275 fn default() -> Self {
276 ProfileCore::default().into_run_profile()
277 }
278}
279
280impl RunProfile {
281 pub fn new() -> Self {
284 Self::default()
285 }
286
287 impl_profile_builder_methods!();
288}
289
290#[derive(Clone, Debug, PartialEq)]
291pub struct SessionConfig {
292 pub cwd: String,
293 pub model: Option<String>,
294 pub effort: ReasoningEffort,
295 pub approval_policy: ApprovalPolicy,
296 pub sandbox_policy: SandboxPolicy,
297 pub privileged_escalation_approved: bool,
299 pub attachments: Vec<PromptAttachment>,
300 pub timeout: Duration,
301 pub output_schema: Option<Value>,
302 pub hooks: RuntimeHookConfig,
303}
304
305impl SessionConfig {
306 pub fn new(cwd: impl Into<String>) -> Self {
309 Self::from_profile(cwd, RunProfile::default())
310 }
311
312 pub fn from_profile(cwd: impl Into<String>, profile: RunProfile) -> Self {
315 ProfileCore::from(profile).into_session_config(cwd.into())
316 }
317
318 pub fn profile(&self) -> RunProfile {
321 ProfileCore::from(self).into_run_profile()
322 }
323
324 impl_profile_builder_methods!();
325}
326
327pub(super) fn session_prompt_params(
330 config: &SessionConfig,
331 prompt: impl Into<String>,
332) -> PromptRunParams {
333 ProfileCore::from(config).into_prompt_params(config.cwd.clone(), prompt.into())
334}
335
336pub(super) fn profile_to_prompt_params(
339 cwd: String,
340 prompt: impl Into<String>,
341 profile: RunProfile,
342) -> PromptRunParams {
343 ProfileCore::from(profile).into_prompt_params(cwd, prompt.into())
344}
345
346pub(super) fn profile_to_prompt_params_with_hooks(
348 cwd: String,
349 prompt: impl Into<String>,
350 mut profile: RunProfile,
351) -> (PromptRunParams, RuntimeHookConfig) {
352 let hooks = std::mem::take(&mut profile.hooks);
353 let params = profile_to_prompt_params(cwd, prompt, profile);
354 (params, hooks)
355}
356
357pub(super) fn session_thread_start_params(config: &SessionConfig) -> ThreadStartParams {
360 ProfileCore::from(config).into_thread_start_params(config.cwd.clone())
361}