1use crate::Codex;
14use crate::command::CodexCommand;
15use crate::error::Result;
16use crate::exec::{self, CommandOutput};
17
18fn push_config(
20 args: &mut Vec<String>,
21 config_overrides: &[String],
22 enabled: &[String],
23 disabled: &[String],
24) {
25 for value in config_overrides {
26 args.push("-c".into());
27 args.push(value.clone());
28 }
29 for value in enabled {
30 args.push("--enable".into());
31 args.push(value.clone());
32 }
33 for value in disabled {
34 args.push("--disable".into());
35 args.push(value.clone());
36 }
37}
38
39#[derive(Debug, Clone)]
41pub struct ArchiveCommand {
42 session: String,
43 config_overrides: Vec<String>,
44 enabled_features: Vec<String>,
45 disabled_features: Vec<String>,
46 retry_policy: Option<crate::retry::RetryPolicy>,
47}
48
49impl ArchiveCommand {
50 #[must_use]
52 pub fn new(session: impl Into<String>) -> Self {
53 Self {
54 session: session.into(),
55 config_overrides: Vec::new(),
56 enabled_features: Vec::new(),
57 disabled_features: Vec::new(),
58 retry_policy: None,
59 }
60 }
61
62 #[must_use]
64 pub fn config(mut self, key_value: impl Into<String>) -> Self {
65 self.config_overrides.push(key_value.into());
66 self
67 }
68
69 #[must_use]
71 pub fn enable(mut self, feature: impl Into<String>) -> Self {
72 self.enabled_features.push(feature.into());
73 self
74 }
75
76 #[must_use]
78 pub fn disable(mut self, feature: impl Into<String>) -> Self {
79 self.disabled_features.push(feature.into());
80 self
81 }
82
83 #[must_use]
85 pub fn retry(mut self, policy: crate::retry::RetryPolicy) -> Self {
86 self.retry_policy = Some(policy);
87 self
88 }
89}
90
91impl CodexCommand for ArchiveCommand {
92 type Output = CommandOutput;
93
94 fn args(&self) -> Vec<String> {
95 let mut args = vec!["archive".to_string()];
96 push_config(
97 &mut args,
98 &self.config_overrides,
99 &self.enabled_features,
100 &self.disabled_features,
101 );
102 args.push(self.session.clone());
103 args
104 }
105
106 async fn execute(&self, codex: &Codex) -> Result<CommandOutput> {
107 exec::run_codex_with_retry(codex, self.args(), self.retry_policy.as_ref()).await
108 }
109}
110
111#[derive(Debug, Clone)]
113pub struct DeleteCommand {
114 session: String,
115 force: bool,
116 config_overrides: Vec<String>,
117 enabled_features: Vec<String>,
118 disabled_features: Vec<String>,
119 retry_policy: Option<crate::retry::RetryPolicy>,
120}
121
122impl DeleteCommand {
123 #[must_use]
125 pub fn new(session: impl Into<String>) -> Self {
126 Self {
127 session: session.into(),
128 force: false,
129 config_overrides: Vec::new(),
130 enabled_features: Vec::new(),
131 disabled_features: Vec::new(),
132 retry_policy: None,
133 }
134 }
135
136 #[must_use]
138 pub fn force(mut self) -> Self {
139 self.force = true;
140 self
141 }
142
143 #[must_use]
145 pub fn config(mut self, key_value: impl Into<String>) -> Self {
146 self.config_overrides.push(key_value.into());
147 self
148 }
149
150 #[must_use]
152 pub fn enable(mut self, feature: impl Into<String>) -> Self {
153 self.enabled_features.push(feature.into());
154 self
155 }
156
157 #[must_use]
159 pub fn disable(mut self, feature: impl Into<String>) -> Self {
160 self.disabled_features.push(feature.into());
161 self
162 }
163
164 #[must_use]
166 pub fn retry(mut self, policy: crate::retry::RetryPolicy) -> Self {
167 self.retry_policy = Some(policy);
168 self
169 }
170}
171
172impl CodexCommand for DeleteCommand {
173 type Output = CommandOutput;
174
175 fn args(&self) -> Vec<String> {
176 let mut args = vec!["delete".to_string()];
177 push_config(
178 &mut args,
179 &self.config_overrides,
180 &self.enabled_features,
181 &self.disabled_features,
182 );
183 if self.force {
184 args.push("--force".into());
185 }
186 args.push(self.session.clone());
187 args
188 }
189
190 async fn execute(&self, codex: &Codex) -> Result<CommandOutput> {
191 exec::run_codex_with_retry(codex, self.args(), self.retry_policy.as_ref()).await
192 }
193}
194
195#[derive(Debug, Clone)]
197pub struct UnarchiveCommand {
198 session: String,
199 config_overrides: Vec<String>,
200 enabled_features: Vec<String>,
201 disabled_features: Vec<String>,
202 retry_policy: Option<crate::retry::RetryPolicy>,
203}
204
205impl UnarchiveCommand {
206 #[must_use]
208 pub fn new(session: impl Into<String>) -> Self {
209 Self {
210 session: session.into(),
211 config_overrides: Vec::new(),
212 enabled_features: Vec::new(),
213 disabled_features: Vec::new(),
214 retry_policy: None,
215 }
216 }
217
218 #[must_use]
220 pub fn config(mut self, key_value: impl Into<String>) -> Self {
221 self.config_overrides.push(key_value.into());
222 self
223 }
224
225 #[must_use]
227 pub fn enable(mut self, feature: impl Into<String>) -> Self {
228 self.enabled_features.push(feature.into());
229 self
230 }
231
232 #[must_use]
234 pub fn disable(mut self, feature: impl Into<String>) -> Self {
235 self.disabled_features.push(feature.into());
236 self
237 }
238
239 #[must_use]
241 pub fn retry(mut self, policy: crate::retry::RetryPolicy) -> Self {
242 self.retry_policy = Some(policy);
243 self
244 }
245}
246
247impl CodexCommand for UnarchiveCommand {
248 type Output = CommandOutput;
249
250 fn args(&self) -> Vec<String> {
251 let mut args = vec!["unarchive".to_string()];
252 push_config(
253 &mut args,
254 &self.config_overrides,
255 &self.enabled_features,
256 &self.disabled_features,
257 );
258 args.push(self.session.clone());
259 args
260 }
261
262 async fn execute(&self, codex: &Codex) -> Result<CommandOutput> {
263 exec::run_codex_with_retry(codex, self.args(), self.retry_policy.as_ref()).await
264 }
265}
266
267#[cfg(test)]
268mod tests {
269 use super::*;
270
271 #[test]
272 fn archive_args() {
273 let args = ArchiveCommand::new("sess-1").args();
274 assert_eq!(args, vec!["archive", "sess-1"]);
275 }
276
277 #[test]
278 fn archive_args_with_config() {
279 let args = ArchiveCommand::new("sess-1")
280 .config("foo=bar")
281 .enable("beta")
282 .args();
283 assert_eq!(
284 args,
285 vec!["archive", "-c", "foo=bar", "--enable", "beta", "sess-1"]
286 );
287 }
288
289 #[test]
290 fn delete_args() {
291 let args = DeleteCommand::new("sess-2").args();
292 assert_eq!(args, vec!["delete", "sess-2"]);
293 }
294
295 #[test]
296 fn delete_args_force() {
297 let args = DeleteCommand::new("sess-2").force().args();
298 assert_eq!(args, vec!["delete", "--force", "sess-2"]);
299 }
300
301 #[test]
302 fn unarchive_args() {
303 let args = UnarchiveCommand::new("sess-3").args();
304 assert_eq!(args, vec!["unarchive", "sess-3"]);
305 }
306}