Skip to main content

codex_app_server_sdk/protocol/
requests.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4macro_rules! opaque_struct {
5    ($name:ident) => {
6        #[derive(Debug, Clone, Serialize, Deserialize, Default)]
7        #[serde(rename_all = "camelCase")]
8        pub struct $name {
9            #[serde(flatten)]
10            pub extra: serde_json::Map<String, Value>,
11        }
12    };
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
16#[serde(rename_all = "camelCase")]
17pub struct ClientInfo {
18    pub name: String,
19    pub title: String,
20    pub version: String,
21}
22
23impl ClientInfo {
24    pub fn new(
25        name: impl Into<String>,
26        title: impl Into<String>,
27        version: impl Into<String>,
28    ) -> Self {
29        Self {
30            name: name.into(),
31            title: title.into(),
32            version: version.into(),
33        }
34    }
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize, Default)]
38#[serde(rename_all = "camelCase")]
39pub struct InitializeCapabilities {
40    #[serde(default, skip_serializing_if = "Option::is_none")]
41    pub experimental_api: Option<bool>,
42    #[serde(flatten)]
43    pub extra: serde_json::Map<String, Value>,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
47#[serde(rename_all = "camelCase")]
48pub struct InitializeParams {
49    pub client_info: ClientInfo,
50    #[serde(default, skip_serializing_if = "Option::is_none")]
51    pub capabilities: Option<InitializeCapabilities>,
52    #[serde(flatten)]
53    pub extra: serde_json::Map<String, Value>,
54}
55
56impl InitializeParams {
57    pub fn new(client_info: ClientInfo) -> Self {
58        Self {
59            client_info,
60            capabilities: None,
61            extra: serde_json::Map::new(),
62        }
63    }
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize, Default)]
67#[serde(rename_all = "camelCase")]
68pub struct PaginationParams {
69    #[serde(default, skip_serializing_if = "Option::is_none")]
70    pub limit: Option<u32>,
71    #[serde(default, skip_serializing_if = "Option::is_none")]
72    pub cursor: Option<String>,
73    #[serde(flatten)]
74    pub extra: serde_json::Map<String, Value>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize, Default)]
78#[serde(rename_all = "camelCase")]
79pub struct ThreadStartParams {
80    #[serde(default, skip_serializing_if = "Option::is_none")]
81    pub model: Option<String>,
82    #[serde(default, skip_serializing_if = "Option::is_none")]
83    pub model_provider: Option<String>,
84    #[serde(default, skip_serializing_if = "Option::is_none")]
85    pub cwd: Option<String>,
86    #[serde(default, skip_serializing_if = "Option::is_none")]
87    pub approval_policy: Option<String>,
88    #[serde(default, skip_serializing_if = "Option::is_none")]
89    pub sandbox: Option<String>,
90    #[serde(default, skip_serializing_if = "Option::is_none")]
91    pub sandbox_policy: Option<Value>,
92    #[serde(default, skip_serializing_if = "Option::is_none")]
93    pub effort: Option<String>,
94    #[serde(default, skip_serializing_if = "Option::is_none")]
95    pub summary: Option<String>,
96    #[serde(default, skip_serializing_if = "Option::is_none")]
97    pub personality: Option<String>,
98    #[serde(default, skip_serializing_if = "Option::is_none")]
99    pub ephemeral: Option<bool>,
100    #[serde(default, skip_serializing_if = "Option::is_none")]
101    pub base_instructions: Option<String>,
102    #[serde(default, skip_serializing_if = "Option::is_none")]
103    pub developer_instructions: Option<String>,
104    #[serde(flatten)]
105    pub extra: serde_json::Map<String, Value>,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize, Default)]
109#[serde(rename_all = "camelCase")]
110pub struct ThreadResumeParams {
111    pub thread_id: String,
112    #[serde(default, skip_serializing_if = "Option::is_none")]
113    pub history: Option<Vec<Value>>,
114    #[serde(default, skip_serializing_if = "Option::is_none")]
115    pub path: Option<String>,
116    #[serde(default, skip_serializing_if = "Option::is_none")]
117    pub model: Option<String>,
118    #[serde(default, skip_serializing_if = "Option::is_none")]
119    pub model_provider: Option<String>,
120    #[serde(default, skip_serializing_if = "Option::is_none")]
121    pub cwd: Option<String>,
122    #[serde(default, skip_serializing_if = "Option::is_none")]
123    pub approval_policy: Option<String>,
124    #[serde(default, skip_serializing_if = "Option::is_none")]
125    pub sandbox: Option<String>,
126    #[serde(default, skip_serializing_if = "Option::is_none")]
127    pub config: Option<serde_json::Map<String, Value>>,
128    #[serde(default, skip_serializing_if = "Option::is_none")]
129    pub base_instructions: Option<String>,
130    #[serde(default, skip_serializing_if = "Option::is_none")]
131    pub developer_instructions: Option<String>,
132    #[serde(default, skip_serializing_if = "Option::is_none")]
133    pub personality: Option<String>,
134    #[serde(default, skip_serializing_if = "Option::is_none")]
135    pub persist_extended_history: Option<bool>,
136    #[serde(flatten)]
137    pub extra: serde_json::Map<String, Value>,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
141#[serde(rename_all = "camelCase")]
142pub struct ThreadIdParams {
143    pub thread_id: String,
144    #[serde(flatten)]
145    pub extra: serde_json::Map<String, Value>,
146}
147
148impl ThreadResumeParams {
149    pub fn from_thread_id(thread_id: impl Into<String>) -> Self {
150        Self {
151            thread_id: thread_id.into(),
152            ..Self::default()
153        }
154    }
155}
156
157impl From<ThreadIdParams> for ThreadResumeParams {
158    fn from(value: ThreadIdParams) -> Self {
159        Self {
160            thread_id: value.thread_id,
161            extra: value.extra,
162            ..Self::default()
163        }
164    }
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize)]
168#[serde(rename_all = "camelCase")]
169pub struct ThreadForkParams {
170    pub thread_id: String,
171    #[serde(default, skip_serializing_if = "Option::is_none")]
172    pub from_turn_id: Option<String>,
173    #[serde(flatten)]
174    pub extra: serde_json::Map<String, Value>,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
178#[serde(rename_all = "camelCase")]
179pub struct ThreadSetNameParams {
180    pub thread_id: String,
181    pub name: String,
182    #[serde(flatten)]
183    pub extra: serde_json::Map<String, Value>,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
187#[serde(rename_all = "camelCase")]
188pub struct ThreadRollbackParams {
189    pub thread_id: String,
190    pub count: u32,
191    #[serde(flatten)]
192    pub extra: serde_json::Map<String, Value>,
193}
194
195#[derive(Debug, Clone, Serialize, Deserialize)]
196#[serde(rename_all = "camelCase")]
197pub struct ThreadBackgroundTerminalsCleanParams {
198    pub thread_id: String,
199    #[serde(flatten)]
200    pub extra: serde_json::Map<String, Value>,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize, Default)]
204#[serde(rename_all = "camelCase")]
205pub struct ThreadListParams {
206    #[serde(default, skip_serializing_if = "Option::is_none")]
207    pub limit: Option<u32>,
208    #[serde(default, skip_serializing_if = "Option::is_none")]
209    pub cursor: Option<String>,
210    #[serde(default, skip_serializing_if = "Option::is_none")]
211    pub archived: Option<bool>,
212    #[serde(default, skip_serializing_if = "Option::is_none")]
213    pub source_kinds: Option<Vec<String>>,
214    #[serde(default, skip_serializing_if = "Option::is_none")]
215    pub model_providers: Option<Vec<String>>,
216    #[serde(flatten)]
217    pub extra: serde_json::Map<String, Value>,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize)]
221#[serde(rename_all = "camelCase")]
222pub struct ThreadReadParams {
223    pub thread_id: String,
224    #[serde(default, skip_serializing_if = "Option::is_none")]
225    pub include_turns: Option<bool>,
226    #[serde(flatten)]
227    pub extra: serde_json::Map<String, Value>,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
231#[serde(tag = "type", rename_all = "camelCase")]
232pub enum TurnInputItem {
233    Text {
234        text: String,
235    },
236    Image {
237        url: String,
238    },
239    LocalImage {
240        path: String,
241    },
242    Skill {
243        name: String,
244        path: String,
245    },
246    #[serde(other)]
247    Unknown,
248}
249
250impl TurnInputItem {
251    pub fn text(text: impl Into<String>) -> Self {
252        Self::Text { text: text.into() }
253    }
254}
255
256#[derive(Debug, Clone, Serialize, Deserialize)]
257#[serde(rename_all = "camelCase")]
258pub struct TurnStartParams {
259    pub thread_id: String,
260    pub input: Vec<TurnInputItem>,
261    #[serde(default, skip_serializing_if = "Option::is_none")]
262    pub cwd: Option<String>,
263    #[serde(default, skip_serializing_if = "Option::is_none")]
264    pub model: Option<String>,
265    #[serde(default, skip_serializing_if = "Option::is_none")]
266    pub model_provider: Option<String>,
267    #[serde(default, skip_serializing_if = "Option::is_none")]
268    pub effort: Option<String>,
269    #[serde(default, skip_serializing_if = "Option::is_none")]
270    pub summary: Option<String>,
271    #[serde(default, skip_serializing_if = "Option::is_none")]
272    pub personality: Option<String>,
273    #[serde(default, skip_serializing_if = "Option::is_none")]
274    pub output_schema: Option<Value>,
275    #[serde(default, skip_serializing_if = "Option::is_none")]
276    pub approval_policy: Option<String>,
277    #[serde(default, skip_serializing_if = "Option::is_none")]
278    pub sandbox_policy: Option<Value>,
279    #[serde(default, skip_serializing_if = "Option::is_none")]
280    pub collaboration_mode: Option<String>,
281    #[serde(flatten)]
282    pub extra: serde_json::Map<String, Value>,
283}
284
285impl TurnStartParams {
286    pub fn text(thread_id: impl Into<String>, text: impl Into<String>) -> Self {
287        Self {
288            thread_id: thread_id.into(),
289            input: vec![TurnInputItem::text(text)],
290            cwd: None,
291            model: None,
292            model_provider: None,
293            effort: None,
294            summary: None,
295            personality: None,
296            output_schema: None,
297            approval_policy: None,
298            sandbox_policy: None,
299            collaboration_mode: None,
300            extra: serde_json::Map::new(),
301        }
302    }
303}
304
305#[derive(Debug, Clone, Serialize, Deserialize)]
306#[serde(rename_all = "camelCase")]
307pub struct TurnSteerParams {
308    pub thread_id: String,
309    pub input: Vec<TurnInputItem>,
310    #[serde(default, skip_serializing_if = "Option::is_none")]
311    pub expected_turn_id: Option<String>,
312    #[serde(flatten)]
313    pub extra: serde_json::Map<String, Value>,
314}
315
316#[derive(Debug, Clone, Serialize, Deserialize)]
317#[serde(rename_all = "camelCase")]
318pub struct TurnInterruptParams {
319    pub thread_id: String,
320    pub turn_id: String,
321    #[serde(flatten)]
322    pub extra: serde_json::Map<String, Value>,
323}
324
325#[derive(Debug, Clone, Serialize, Deserialize, Default)]
326#[serde(rename_all = "camelCase")]
327pub struct SkillsListParams {
328    #[serde(default, skip_serializing_if = "Option::is_none")]
329    pub cwd: Option<Vec<String>>,
330    #[serde(default, skip_serializing_if = "Option::is_none")]
331    pub force_reload: Option<bool>,
332    #[serde(flatten)]
333    pub extra: serde_json::Map<String, Value>,
334}
335
336opaque_struct!(SkillsRemoteReadParams);
337opaque_struct!(SkillsRemoteWriteParams);
338opaque_struct!(SkillsConfigWriteParams);
339opaque_struct!(AppsListParams);
340opaque_struct!(ReviewStartParams);
341opaque_struct!(ModelListParams);
342opaque_struct!(ExperimentalFeatureListParams);
343opaque_struct!(CollaborationModeListParams);
344opaque_struct!(MockExperimentalMethodParams);
345opaque_struct!(McpServerOauthLoginParams);
346opaque_struct!(ListMcpServerStatusParams);
347opaque_struct!(WindowsSandboxSetupStartParams);
348opaque_struct!(FeedbackUploadParams);
349opaque_struct!(CommandExecParams);
350opaque_struct!(ConfigReadParams);
351opaque_struct!(ConfigValueWriteParams);
352opaque_struct!(ConfigBatchWriteParams);
353opaque_struct!(FuzzyFileSearchSessionStartParams);
354opaque_struct!(FuzzyFileSearchSessionUpdateParams);
355opaque_struct!(FuzzyFileSearchSessionStopParams);
356
357#[derive(Debug, Clone, Serialize, Deserialize)]
358#[serde(rename_all = "camelCase")]
359pub struct LoginAccountParams {
360    #[serde(rename = "type")]
361    pub login_type: String,
362    #[serde(default, skip_serializing_if = "Option::is_none")]
363    pub api_key: Option<String>,
364    #[serde(default, skip_serializing_if = "Option::is_none")]
365    pub id_token: Option<String>,
366    #[serde(default, skip_serializing_if = "Option::is_none")]
367    pub access_token: Option<String>,
368    #[serde(flatten)]
369    pub extra: serde_json::Map<String, Value>,
370}
371
372impl LoginAccountParams {
373    pub fn api_key(key: impl Into<String>) -> Self {
374        Self {
375            login_type: "apiKey".to_string(),
376            api_key: Some(key.into()),
377            id_token: None,
378            access_token: None,
379            extra: serde_json::Map::new(),
380        }
381    }
382
383    pub fn chatgpt(id_token: impl Into<String>, access_token: impl Into<String>) -> Self {
384        Self {
385            login_type: "chatgpt".to_string(),
386            api_key: None,
387            id_token: Some(id_token.into()),
388            access_token: Some(access_token.into()),
389            extra: serde_json::Map::new(),
390        }
391    }
392}
393
394#[derive(Debug, Clone, Serialize, Deserialize)]
395#[serde(rename_all = "camelCase")]
396pub struct CancelLoginAccountParams {
397    pub login_id: String,
398    #[serde(flatten)]
399    pub extra: serde_json::Map<String, Value>,
400}
401
402#[derive(Debug, Clone, Serialize, Deserialize, Default)]
403#[serde(rename_all = "camelCase")]
404pub struct GetAccountParams {
405    #[serde(default, skip_serializing_if = "Option::is_none")]
406    pub refresh_token: Option<bool>,
407    #[serde(flatten)]
408    pub extra: serde_json::Map<String, Value>,
409}
410
411pub type ThreadArchiveParams = ThreadIdParams;
412pub type ThreadUnarchiveParams = ThreadIdParams;
413pub type ThreadCompactStartParams = ThreadIdParams;
414pub type ThreadLoadedListParams = PaginationParams;