codex_wrapper/command/
resume.rs1use crate::Codex;
5use crate::command::CodexCommand;
6use crate::error::Result;
7use crate::exec::{self, CommandOutput};
8use crate::types::{ApprovalPolicy, SandboxMode};
9
10#[derive(Debug, Clone)]
12pub struct ResumeCommand {
13 session_id: Option<String>,
14 prompt: Option<String>,
15 last: bool,
16 all: bool,
17 config_overrides: Vec<String>,
18 enabled_features: Vec<String>,
19 disabled_features: Vec<String>,
20 images: Vec<String>,
21 model: Option<String>,
22 oss: bool,
23 local_provider: Option<String>,
24 profile: Option<String>,
25 sandbox: Option<SandboxMode>,
26 approval_policy: Option<ApprovalPolicy>,
27 full_auto: bool,
28 dangerously_bypass_approvals_and_sandbox: bool,
29 cd: Option<String>,
30 search: bool,
31 add_dirs: Vec<String>,
32}
33
34impl ResumeCommand {
35 #[must_use]
36 pub fn new() -> Self {
37 Self {
38 session_id: None,
39 prompt: None,
40 last: false,
41 all: false,
42 config_overrides: Vec::new(),
43 enabled_features: Vec::new(),
44 disabled_features: Vec::new(),
45 images: Vec::new(),
46 model: None,
47 oss: false,
48 local_provider: None,
49 profile: None,
50 sandbox: None,
51 approval_policy: None,
52 full_auto: false,
53 dangerously_bypass_approvals_and_sandbox: false,
54 cd: None,
55 search: false,
56 add_dirs: Vec::new(),
57 }
58 }
59
60 #[must_use]
62 pub fn session_id(mut self, id: impl Into<String>) -> Self {
63 self.session_id = Some(id.into());
64 self
65 }
66
67 #[must_use]
69 pub fn prompt(mut self, prompt: impl Into<String>) -> Self {
70 self.prompt = Some(prompt.into());
71 self
72 }
73
74 #[must_use]
76 pub fn last(mut self) -> Self {
77 self.last = true;
78 self
79 }
80
81 #[must_use]
83 pub fn all(mut self) -> Self {
84 self.all = true;
85 self
86 }
87
88 #[must_use]
89 pub fn config(mut self, key_value: impl Into<String>) -> Self {
90 self.config_overrides.push(key_value.into());
91 self
92 }
93
94 #[must_use]
95 pub fn enable(mut self, feature: impl Into<String>) -> Self {
96 self.enabled_features.push(feature.into());
97 self
98 }
99
100 #[must_use]
101 pub fn disable(mut self, feature: impl Into<String>) -> Self {
102 self.disabled_features.push(feature.into());
103 self
104 }
105
106 #[must_use]
107 pub fn image(mut self, path: impl Into<String>) -> Self {
108 self.images.push(path.into());
109 self
110 }
111
112 #[must_use]
113 pub fn model(mut self, model: impl Into<String>) -> Self {
114 self.model = Some(model.into());
115 self
116 }
117
118 #[must_use]
119 pub fn oss(mut self) -> Self {
120 self.oss = true;
121 self
122 }
123
124 #[must_use]
125 pub fn local_provider(mut self, provider: impl Into<String>) -> Self {
126 self.local_provider = Some(provider.into());
127 self
128 }
129
130 #[must_use]
131 pub fn profile(mut self, profile: impl Into<String>) -> Self {
132 self.profile = Some(profile.into());
133 self
134 }
135
136 #[must_use]
137 pub fn sandbox(mut self, sandbox: SandboxMode) -> Self {
138 self.sandbox = Some(sandbox);
139 self
140 }
141
142 #[must_use]
143 pub fn approval_policy(mut self, policy: ApprovalPolicy) -> Self {
144 self.approval_policy = Some(policy);
145 self
146 }
147
148 #[must_use]
149 pub fn full_auto(mut self) -> Self {
150 self.full_auto = true;
151 self
152 }
153
154 #[must_use]
155 pub fn dangerously_bypass_approvals_and_sandbox(mut self) -> Self {
156 self.dangerously_bypass_approvals_and_sandbox = true;
157 self
158 }
159
160 #[must_use]
161 pub fn cd(mut self, dir: impl Into<String>) -> Self {
162 self.cd = Some(dir.into());
163 self
164 }
165
166 #[must_use]
168 pub fn search(mut self) -> Self {
169 self.search = true;
170 self
171 }
172
173 #[must_use]
174 pub fn add_dir(mut self, dir: impl Into<String>) -> Self {
175 self.add_dirs.push(dir.into());
176 self
177 }
178}
179
180impl Default for ResumeCommand {
181 fn default() -> Self {
182 Self::new()
183 }
184}
185
186impl CodexCommand for ResumeCommand {
187 type Output = CommandOutput;
188
189 fn args(&self) -> Vec<String> {
190 let mut args = vec!["resume".into()];
191
192 for v in &self.config_overrides {
193 args.push("-c".into());
194 args.push(v.clone());
195 }
196 for v in &self.enabled_features {
197 args.push("--enable".into());
198 args.push(v.clone());
199 }
200 for v in &self.disabled_features {
201 args.push("--disable".into());
202 args.push(v.clone());
203 }
204 if self.last {
205 args.push("--last".into());
206 }
207 if self.all {
208 args.push("--all".into());
209 }
210 for v in &self.images {
211 args.push("--image".into());
212 args.push(v.clone());
213 }
214 if let Some(model) = &self.model {
215 args.push("--model".into());
216 args.push(model.clone());
217 }
218 if self.oss {
219 args.push("--oss".into());
220 }
221 if let Some(provider) = &self.local_provider {
222 args.push("--local-provider".into());
223 args.push(provider.clone());
224 }
225 if let Some(profile) = &self.profile {
226 args.push("--profile".into());
227 args.push(profile.clone());
228 }
229 if let Some(sandbox) = self.sandbox {
230 args.push("--sandbox".into());
231 args.push(sandbox.as_arg().into());
232 }
233 if let Some(policy) = self.approval_policy {
234 args.push("--ask-for-approval".into());
235 args.push(policy.as_arg().into());
236 }
237 if self.full_auto {
238 args.push("--full-auto".into());
239 }
240 if self.dangerously_bypass_approvals_and_sandbox {
241 args.push("--dangerously-bypass-approvals-and-sandbox".into());
242 }
243 if let Some(cd) = &self.cd {
244 args.push("--cd".into());
245 args.push(cd.clone());
246 }
247 if self.search {
248 args.push("--search".into());
249 }
250 for v in &self.add_dirs {
251 args.push("--add-dir".into());
252 args.push(v.clone());
253 }
254 if let Some(id) = &self.session_id {
255 args.push(id.clone());
256 }
257 if let Some(prompt) = &self.prompt {
258 args.push(prompt.clone());
259 }
260 args
261 }
262
263 async fn execute(&self, codex: &Codex) -> Result<CommandOutput> {
264 exec::run_codex(codex, self.args()).await
265 }
266}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271
272 #[test]
273 fn resume_last_args() {
274 let args = ResumeCommand::new()
275 .last()
276 .model("gpt-5")
277 .prompt("continue")
278 .args();
279 assert_eq!(
280 args,
281 vec!["resume", "--last", "--model", "gpt-5", "continue"]
282 );
283 }
284
285 #[test]
286 fn resume_session_id_args() {
287 let args = ResumeCommand::new()
288 .session_id("abc-123")
289 .sandbox(SandboxMode::WorkspaceWrite)
290 .search()
291 .args();
292 assert_eq!(
293 args,
294 vec![
295 "resume",
296 "--sandbox",
297 "workspace-write",
298 "--search",
299 "abc-123"
300 ]
301 );
302 }
303}