Skip to main content

gproxy_protocol/wire/openai/
models.rs

1use serde::{Deserialize, Serialize};
2
3use crate::Rest;
4
5/// Query/path request shapes for `GET /models` and `GET /models/{model}`.
6/// Source: `upstream_docs/openai/docs/List models.md` and `Retrieve model.md`.
7/// Extended catalog fields follow `samples/codex/codex-rs/protocol/src/openai_models.rs`.
8pub type ListModelsRequest = crate::WireRequest<()>;
9
10#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(rename_all = "snake_case")]
12#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
13#[derive(gproxy_protocol_macros::DeclaredFields)]
14pub enum ListObject {
15    #[default]
16    List,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(rename_all = "snake_case")]
21#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
22#[derive(gproxy_protocol_macros::DeclaredFields)]
23pub enum ModelObject {
24    Model,
25}
26
27pub type GetModelRequest = crate::WireRequest<()>;
28
29#[derive(
30    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
31)]
32#[serde(rename_all = "snake_case")]
33#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
34#[derive(gproxy_protocol_macros::DeclaredFields)]
35pub struct ListModelsResponseBody {
36    #[serde(default)]
37    pub data: Vec<Model>,
38    #[serde(default)]
39    pub object: ListObject,
40    #[serde(default, skip_serializing_if = "Option::is_none")]
41    pub models: Option<Vec<Model>>,
42    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
43    pub rest: Rest,
44}
45
46pub type ListModelsResponse = crate::WireResponse<ListModelsResponseBody>;
47pub type GetModelResponse = crate::WireResponse<Model>;
48
49#[derive(
50    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
51)]
52#[serde(rename_all = "snake_case")]
53#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
54#[derive(gproxy_protocol_macros::DeclaredFields)]
55pub struct Model {
56    #[serde(default, skip_serializing_if = "String::is_empty")]
57    pub id: String,
58    #[serde(default, skip_serializing_if = "Option::is_none")]
59    pub slug: Option<String>,
60    /// Some compatible catalogs do not report a creation timestamp.
61    #[wire(required)]
62    #[serde(default, skip_serializing_if = "Option::is_none")]
63    pub created: Option<i64>,
64    #[wire(required)]
65    #[serde(default, skip_serializing_if = "Option::is_none")]
66    pub object: Option<ModelObject>,
67    #[wire(required)]
68    #[serde(default, skip_serializing_if = "Option::is_none")]
69    pub owned_by: Option<String>,
70
71    // GPROXY model extensions, matching the v3 OpenAI model contract.
72    #[serde(default, skip_serializing_if = "Option::is_none")]
73    pub display_name: Option<String>,
74    #[serde(default, skip_serializing_if = "Option::is_none")]
75    pub description: Option<String>,
76    #[serde(default, skip_serializing_if = "Option::is_none")]
77    pub instructions: Option<String>,
78    #[serde(default, skip_serializing_if = "Option::is_none")]
79    pub context_window: Option<u64>,
80    #[serde(default, skip_serializing_if = "Option::is_none")]
81    pub max_context_window: Option<u64>,
82    #[serde(default, skip_serializing_if = "Option::is_none")]
83    pub max_output_tokens: Option<u64>,
84    #[serde(default, skip_serializing_if = "Option::is_none")]
85    pub thinking_supported: Option<bool>,
86    #[serde(default, skip_serializing_if = "Option::is_none")]
87    pub input_modalities: Option<Vec<String>>,
88    #[serde(default, skip_serializing_if = "Option::is_none")]
89    pub output_modalities: Option<Vec<String>>,
90    #[serde(default, skip_serializing_if = "Option::is_none")]
91    pub supported_parameters: Option<Vec<String>>,
92    #[serde(
93        default,
94        deserialize_with = "reasoning_levels",
95        skip_serializing_if = "Option::is_none"
96    )]
97    pub supported_reasoning_levels: Option<Vec<ModelReasoningLevel>>,
98    #[serde(default, skip_serializing_if = "Option::is_none")]
99    pub default_reasoning_level: Option<ModelReasoningEffort>,
100    #[serde(default, skip_serializing_if = "Option::is_none")]
101    pub service_tiers: Option<Vec<ModelServiceTier>>,
102    #[serde(default, skip_serializing_if = "Option::is_none")]
103    pub default_service_tier: Option<String>,
104    #[serde(default, skip_serializing_if = "Option::is_none")]
105    pub generation_methods: Option<Vec<String>>,
106    #[serde(default, skip_serializing_if = "Option::is_none")]
107    pub supported_actions: Option<Vec<String>>,
108
109    // Codex model catalog extensions.
110    #[serde(default, skip_serializing_if = "Option::is_none")]
111    pub guardian: Option<GuardianModelPolicy>,
112    #[serde(default, skip_serializing_if = "Option::is_none")]
113    pub shell_type: Option<ConfigShellToolType>,
114    #[serde(default, skip_serializing_if = "Option::is_none")]
115    pub visibility: Option<ModelVisibility>,
116    #[serde(default, skip_serializing_if = "Option::is_none")]
117    pub supported_in_api: Option<bool>,
118    #[serde(default, skip_serializing_if = "Option::is_none")]
119    pub priority: Option<i32>,
120    #[serde(default, skip_serializing_if = "Option::is_none")]
121    pub additional_speed_tiers: Option<Vec<String>>,
122    #[serde(default, skip_serializing_if = "Option::is_none")]
123    pub available_access_programs: Option<ModelAccessPrograms>,
124    #[serde(default, skip_serializing_if = "Option::is_none")]
125    pub availability_nux: Option<ModelAvailabilityNux>,
126    #[serde(default, skip_serializing_if = "Option::is_none")]
127    pub upgrade: Option<ModelInfoUpgrade>,
128    #[serde(default, skip_serializing_if = "Option::is_none")]
129    pub model_messages: Option<ModelMessages>,
130    #[serde(default, skip_serializing_if = "Option::is_none")]
131    pub include_skills_usage_instructions: Option<bool>,
132    #[serde(default, skip_serializing_if = "Option::is_none")]
133    pub include_plugin_usage_instructions: Option<bool>,
134    #[serde(default, skip_serializing_if = "Option::is_none")]
135    pub include_apps_usage_instructions: Option<bool>,
136    #[serde(default, skip_serializing_if = "Option::is_none")]
137    pub supports_reasoning_summary_parameter: Option<bool>,
138    #[serde(default, skip_serializing_if = "Option::is_none")]
139    pub default_reasoning_summary: Option<ModelReasoningSummary>,
140    #[serde(default, skip_serializing_if = "Option::is_none")]
141    pub support_verbosity: Option<bool>,
142    #[serde(default, skip_serializing_if = "Option::is_none")]
143    pub default_verbosity: Option<super::responses::TextVerbosity>,
144    #[serde(default, skip_serializing_if = "Option::is_none")]
145    pub apply_patch_tool_type: Option<ApplyPatchToolType>,
146    #[serde(default, skip_serializing_if = "Option::is_none")]
147    pub web_search_tool_type: Option<WebSearchToolType>,
148    #[serde(default, skip_serializing_if = "Option::is_none")]
149    pub truncation_policy: Option<TruncationPolicyConfig>,
150    #[serde(default, skip_serializing_if = "Option::is_none")]
151    pub supports_image_detail_original: Option<bool>,
152    #[serde(default, skip_serializing_if = "Option::is_none")]
153    pub auto_compact_token_limit: Option<i64>,
154    #[serde(default, skip_serializing_if = "Option::is_none")]
155    pub comp_hash: Option<String>,
156    #[serde(default, skip_serializing_if = "Option::is_none")]
157    pub effective_context_window_percent: Option<i64>,
158    #[serde(default, skip_serializing_if = "Option::is_none")]
159    pub experimental_supported_tools: Option<Vec<String>>,
160    #[serde(default, skip_serializing_if = "Option::is_none")]
161    pub supports_search_tool: Option<bool>,
162    #[serde(default, skip_serializing_if = "Option::is_none")]
163    pub supports_experimental_context: Option<bool>,
164    #[serde(default, skip_serializing_if = "Option::is_none")]
165    pub use_responses_lite: Option<bool>,
166    #[serde(default, skip_serializing_if = "Option::is_none")]
167    pub supports_reasoning_effort_updates: Option<bool>,
168    #[serde(default, skip_serializing_if = "Option::is_none")]
169    pub node_repl_auto_review_required: Option<bool>,
170    #[serde(default, skip_serializing_if = "Option::is_none")]
171    pub node_repl_disabled: Option<bool>,
172    #[serde(default, skip_serializing_if = "Option::is_none")]
173    pub auto_review_model_override: Option<String>,
174    #[serde(default, skip_serializing_if = "Option::is_none")]
175    pub model_specialty: Option<String>,
176    #[serde(
177        default,
178        deserialize_with = "optional_selector",
179        skip_serializing_if = "Option::is_none"
180    )]
181    pub tool_mode: Option<ToolMode>,
182    #[serde(
183        default,
184        deserialize_with = "optional_selector",
185        skip_serializing_if = "Option::is_none"
186    )]
187    pub multi_agent_version: Option<MultiAgentVersion>,
188    #[serde(default, skip_serializing_if = "Option::is_none")]
189    pub multi_agent_reasoning_effort: Option<ModelReasoningEffort>,
190    #[serde(default, skip_serializing_if = "Option::is_none")]
191    pub base_instructions: Option<String>,
192    // Fields also advertised by the bundled Codex catalog.
193    #[serde(default, skip_serializing_if = "Option::is_none")]
194    pub prefer_websockets: Option<bool>,
195    #[serde(default, skip_serializing_if = "Option::is_none")]
196    pub supports_parallel_tool_calls: Option<bool>,
197    #[serde(default, skip_serializing_if = "Option::is_none")]
198    pub supports_reasoning_summaries: Option<bool>,
199    #[serde(default, skip_serializing_if = "Option::is_none")]
200    pub requires_sandboxed_review: Option<bool>,
201    #[serde(default, skip_serializing_if = "Option::is_none")]
202    pub available_in_plans: Option<Vec<String>>,
203    #[serde(default, skip_serializing_if = "Option::is_none")]
204    pub minimal_client_version: Option<ClientVersion>,
205    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
206    pub rest: Rest,
207}
208
209#[derive(
210    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
211)]
212pub struct ModelReasoningLevel {
213    pub effort: ModelReasoningEffort,
214    pub description: String,
215}
216#[derive(
217    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
218)]
219pub struct ModelServiceTier {
220    pub id: String,
221    pub name: String,
222    pub description: String,
223}
224
225fn reasoning_levels<'de, D>(deserializer: D) -> Result<Option<Vec<ModelReasoningLevel>>, D::Error>
226where
227    D: serde::Deserializer<'de>,
228{
229    #[derive(Deserialize)]
230    #[serde(untagged)]
231    enum Level {
232        Preset(ModelReasoningLevel),
233        Effort(ModelReasoningEffort),
234    }
235    Ok(
236        Option::<Vec<Level>>::deserialize(deserializer)?.map(|levels| {
237            levels
238                .into_iter()
239                .map(|level| match level {
240                    Level::Preset(preset) => preset,
241                    Level::Effort(effort) => ModelReasoningLevel {
242                        effort,
243                        description: String::new(),
244                    },
245                })
246                .collect()
247        }),
248    )
249}
250
251#[derive(
252    Debug,
253    Clone,
254    Default,
255    PartialEq,
256    Eq,
257    Serialize,
258    Deserialize,
259    gproxy_protocol_macros::DeclaredFields,
260)]
261pub struct ModelMessages {
262    #[serde(default, skip_serializing_if = "Option::is_none")]
263    pub content_filter_guidance: Option<String>,
264    #[serde(default, skip_serializing_if = "Option::is_none")]
265    pub persistent_instructions: Option<String>,
266    #[serde(default, skip_serializing_if = "Option::is_none")]
267    pub tools: Option<ToolMessages>,
268    #[serde(default, skip_serializing_if = "Option::is_none")]
269    pub instructions_template: Option<String>,
270    #[serde(default, skip_serializing_if = "Option::is_none")]
271    pub instructions_variables: Option<ModelInstructionsVariables>,
272    #[serde(default, skip_serializing_if = "Option::is_none")]
273    pub approvals: Option<ApprovalMessages>,
274    #[serde(default, skip_serializing_if = "Option::is_none")]
275    pub collaboration_modes: Option<CollaborationModeMessages>,
276    #[serde(default, skip_serializing_if = "Option::is_none")]
277    pub auto_review: Option<AutoReviewMessages>,
278    #[serde(default, skip_serializing_if = "Option::is_none")]
279    pub permissions: Option<PermissionMessages>,
280    #[serde(default, skip_serializing_if = "Option::is_none")]
281    pub multi_agent: Option<MultiAgentMessages>,
282    #[serde(default, skip_serializing_if = "Option::is_none")]
283    pub token_budget: Option<ModelTokenBudgetConfig>,
284    #[serde(default, skip_serializing_if = "Option::is_none")]
285    pub guardian_v2: Option<GuardianV2ModelConfig>,
286    #[serde(default, skip_serializing_if = "Option::is_none")]
287    pub confirmation_policies: Option<ConfirmationPolicies>,
288    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
289    pub rest: Rest,
290}
291
292#[derive(
293    Debug,
294    Clone,
295    Default,
296    PartialEq,
297    Eq,
298    Serialize,
299    Deserialize,
300    gproxy_protocol_macros::DeclaredFields,
301)]
302pub struct ConfirmationPolicies {
303    #[serde(default, skip_serializing_if = "Option::is_none")]
304    pub browser_use: Option<String>,
305    #[serde(default, skip_serializing_if = "Option::is_none")]
306    pub computer_use: Option<String>,
307    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
308    pub rest: Rest,
309}
310
311#[derive(
312    Debug,
313    Clone,
314    Default,
315    PartialEq,
316    Eq,
317    Serialize,
318    Deserialize,
319    gproxy_protocol_macros::DeclaredFields,
320)]
321pub struct ToolMessages {
322    #[serde(default, skip_serializing_if = "Option::is_none")]
323    pub functions_namespace_functions_description_prefixes:
324        Option<std::collections::BTreeMap<String, String>>,
325    #[serde(default, skip_serializing_if = "Option::is_none")]
326    pub indirect_description_prefixes: Option<IndirectDescriptionPrefixes>,
327    #[serde(default, skip_serializing_if = "Option::is_none")]
328    pub send_user_message_async: Option<ToolMessage>,
329    #[serde(default, skip_serializing_if = "Option::is_none")]
330    pub multi_agent: Option<MultiAgentToolMessages>,
331    #[serde(default, skip_serializing_if = "Option::is_none")]
332    pub code_mode: Option<CodeModeToolMessages>,
333    #[serde(default, skip_serializing_if = "Option::is_none")]
334    pub mcp_resources: Option<McpResourceToolMessages>,
335    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
336    pub rest: Rest,
337}
338
339#[derive(
340    Debug,
341    Clone,
342    Default,
343    PartialEq,
344    Eq,
345    Serialize,
346    Deserialize,
347    gproxy_protocol_macros::DeclaredFields,
348)]
349pub struct IndirectDescriptionPrefixes {
350    #[serde(default, skip_serializing_if = "Option::is_none")]
351    pub namespaces: Option<std::collections::BTreeMap<String, String>>,
352    #[serde(default, skip_serializing_if = "Option::is_none")]
353    pub mcp_servers: Option<std::collections::BTreeMap<String, String>>,
354    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
355    pub rest: Rest,
356}
357
358#[derive(
359    Debug,
360    Clone,
361    Default,
362    PartialEq,
363    Eq,
364    Serialize,
365    Deserialize,
366    gproxy_protocol_macros::DeclaredFields,
367)]
368pub struct ToolMessage {
369    #[serde(default, skip_serializing_if = "Option::is_none")]
370    pub description: Option<String>,
371    #[serde(default, skip_serializing_if = "Option::is_none")]
372    pub parameters: Option<String>,
373    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
374    pub rest: Rest,
375}
376
377#[derive(
378    Debug,
379    Clone,
380    Default,
381    PartialEq,
382    Eq,
383    Serialize,
384    Deserialize,
385    gproxy_protocol_macros::DeclaredFields,
386)]
387pub struct MultiAgentToolMessages {
388    #[serde(default, skip_serializing_if = "Option::is_none")]
389    pub spawn_agent: Option<ToolMessage>,
390    #[serde(default, skip_serializing_if = "Option::is_none")]
391    pub send_message: Option<ToolMessage>,
392    #[serde(default, skip_serializing_if = "Option::is_none")]
393    pub followup_task: Option<ToolMessage>,
394    #[serde(default, skip_serializing_if = "Option::is_none")]
395    pub wait_agent: Option<ToolMessage>,
396    #[serde(default, skip_serializing_if = "Option::is_none")]
397    pub interrupt_agent: Option<ToolMessage>,
398    #[serde(default, skip_serializing_if = "Option::is_none")]
399    pub list_agents: Option<ToolMessage>,
400    #[serde(default, skip_serializing_if = "Option::is_none")]
401    pub create_channel: Option<ToolMessage>,
402    #[serde(default, skip_serializing_if = "Option::is_none")]
403    pub get_channels: Option<ToolMessage>,
404    #[serde(default, skip_serializing_if = "Option::is_none")]
405    pub list_threads: Option<ToolMessage>,
406    #[serde(default, skip_serializing_if = "Option::is_none")]
407    pub search_posts: Option<ToolMessage>,
408    #[serde(default, skip_serializing_if = "Option::is_none")]
409    pub read_thread: Option<ToolMessage>,
410    #[serde(default, skip_serializing_if = "Option::is_none")]
411    pub read_post: Option<ToolMessage>,
412    #[serde(default, skip_serializing_if = "Option::is_none")]
413    pub subscribe: Option<ToolMessage>,
414    #[serde(default, skip_serializing_if = "Option::is_none")]
415    pub unsubscribe: Option<ToolMessage>,
416    #[serde(default, skip_serializing_if = "Option::is_none")]
417    pub post: Option<ToolMessage>,
418    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
419    pub rest: Rest,
420}
421
422#[derive(
423    Debug,
424    Clone,
425    Default,
426    PartialEq,
427    Eq,
428    Serialize,
429    Deserialize,
430    gproxy_protocol_macros::DeclaredFields,
431)]
432pub struct McpResourceToolMessages {
433    #[serde(default, skip_serializing_if = "Option::is_none")]
434    pub list_mcp_resources: Option<ToolMessage>,
435    #[serde(default, skip_serializing_if = "Option::is_none")]
436    pub list_mcp_resource_templates: Option<ToolMessage>,
437    #[serde(default, skip_serializing_if = "Option::is_none")]
438    pub read_mcp_resource: Option<ToolMessage>,
439    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
440    pub rest: Rest,
441}
442
443#[derive(
444    Debug,
445    Clone,
446    Default,
447    PartialEq,
448    Eq,
449    Serialize,
450    Deserialize,
451    gproxy_protocol_macros::DeclaredFields,
452)]
453pub struct CodeModeToolMessages {
454    #[serde(default, skip_serializing_if = "Option::is_none")]
455    pub exec: Option<ToolMessage>,
456    #[serde(default, skip_serializing_if = "Option::is_none")]
457    pub wait: Option<ToolMessage>,
458    #[serde(default, skip_serializing_if = "Option::is_none")]
459    pub deferred_nested_tools_guidance: Option<String>,
460    #[serde(default, skip_serializing_if = "Option::is_none")]
461    pub mcp_typescript_preamble: Option<String>,
462    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
463    pub rest: Rest,
464}
465
466#[derive(
467    Debug,
468    Clone,
469    Default,
470    PartialEq,
471    Eq,
472    Serialize,
473    Deserialize,
474    gproxy_protocol_macros::DeclaredFields,
475)]
476pub struct ModelTokenBudgetConfig {
477    #[serde(default)]
478    pub enabled: bool,
479    #[serde(default)]
480    pub use_history_notes_extension: bool,
481    pub reminder_threshold_tokens: i64,
482    pub reminder_message_template: String,
483    pub guidance_message: String,
484    pub auto_compact_fallback_prompt: String,
485    pub auto_compact_fallback_buffer_tokens: i64,
486    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
487    pub rest: Rest,
488}
489
490#[derive(
491    Debug,
492    Clone,
493    Default,
494    PartialEq,
495    Eq,
496    Serialize,
497    Deserialize,
498    gproxy_protocol_macros::DeclaredFields,
499)]
500pub struct ApprovalMessages {
501    #[serde(default, skip_serializing_if = "Option::is_none")]
502    pub on_request: Option<String>,
503    #[serde(default, skip_serializing_if = "Option::is_none")]
504    pub on_request_auto_review: Option<String>,
505    #[serde(default, skip_serializing_if = "Option::is_none")]
506    pub never: Option<String>,
507    #[serde(default, skip_serializing_if = "Option::is_none")]
508    pub unless_trusted: Option<String>,
509    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
510    pub rest: Rest,
511}
512
513#[derive(
514    Debug,
515    Clone,
516    Default,
517    PartialEq,
518    Eq,
519    Serialize,
520    Deserialize,
521    gproxy_protocol_macros::DeclaredFields,
522)]
523pub struct CollaborationModeMessages {
524    #[serde(default, skip_serializing_if = "Option::is_none")]
525    pub default: Option<String>,
526    #[serde(default, skip_serializing_if = "Option::is_none")]
527    pub plan: Option<String>,
528    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
529    pub rest: Rest,
530}
531
532#[derive(
533    Debug,
534    Clone,
535    Default,
536    PartialEq,
537    Eq,
538    Serialize,
539    Deserialize,
540    gproxy_protocol_macros::DeclaredFields,
541)]
542pub struct AutoReviewMessages {
543    #[serde(default, skip_serializing_if = "Option::is_none")]
544    pub policy: Option<String>,
545    #[serde(default, skip_serializing_if = "Option::is_none")]
546    pub policy_template: Option<String>,
547    #[serde(default, skip_serializing_if = "Option::is_none")]
548    pub node_repl_policy: Option<String>,
549    #[serde(default, skip_serializing_if = "Option::is_none")]
550    pub rejection_instructions: Option<String>,
551    #[serde(default, skip_serializing_if = "Option::is_none")]
552    pub timeout_instructions: Option<String>,
553    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
554    pub rest: Rest,
555}
556
557#[derive(
558    Debug,
559    Clone,
560    Default,
561    PartialEq,
562    Eq,
563    Serialize,
564    Deserialize,
565    gproxy_protocol_macros::DeclaredFields,
566)]
567pub struct PermissionMessages {
568    #[serde(default, skip_serializing_if = "Option::is_none")]
569    pub danger_full_access: Option<String>,
570    #[serde(default, skip_serializing_if = "Option::is_none")]
571    pub workspace_write: Option<String>,
572    #[serde(default, skip_serializing_if = "Option::is_none")]
573    pub read_only: Option<String>,
574    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
575    pub rest: Rest,
576}
577
578#[derive(
579    Debug,
580    Clone,
581    Default,
582    PartialEq,
583    Eq,
584    Serialize,
585    Deserialize,
586    gproxy_protocol_macros::DeclaredFields,
587)]
588pub struct MultiAgentMessages {
589    #[serde(default, skip_serializing_if = "Option::is_none")]
590    pub role: Option<MultiAgentRoleMessages>,
591    #[serde(default, skip_serializing_if = "Option::is_none")]
592    pub mode: Option<MultiAgentModeMessages>,
593    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
594    pub rest: Rest,
595}
596
597#[derive(
598    Debug,
599    Clone,
600    Default,
601    PartialEq,
602    Eq,
603    Serialize,
604    Deserialize,
605    gproxy_protocol_macros::DeclaredFields,
606)]
607pub struct MultiAgentRoleMessages {
608    #[serde(default, skip_serializing_if = "Option::is_none")]
609    pub root: Option<String>,
610    #[serde(default, skip_serializing_if = "Option::is_none")]
611    pub subagent: Option<String>,
612    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
613    pub rest: Rest,
614}
615
616#[derive(
617    Debug,
618    Clone,
619    Default,
620    PartialEq,
621    Eq,
622    Serialize,
623    Deserialize,
624    gproxy_protocol_macros::DeclaredFields,
625)]
626pub struct MultiAgentModeMessages {
627    #[serde(default, skip_serializing_if = "Option::is_none")]
628    pub explicit: Option<String>,
629    #[serde(default, skip_serializing_if = "Option::is_none")]
630    pub proactive: Option<String>,
631    #[serde(default, skip_serializing_if = "Option::is_none")]
632    pub hint_text: Option<String>,
633    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
634    pub rest: Rest,
635}
636
637#[derive(
638    Debug,
639    Clone,
640    Default,
641    PartialEq,
642    Eq,
643    Serialize,
644    Deserialize,
645    gproxy_protocol_macros::DeclaredFields,
646)]
647pub struct ModelInstructionsVariables {
648    #[serde(default, skip_serializing_if = "Option::is_none")]
649    pub personality_default: Option<String>,
650    #[serde(default, skip_serializing_if = "Option::is_none")]
651    pub personality_friendly: Option<String>,
652    #[serde(default, skip_serializing_if = "Option::is_none")]
653    pub personality_pragmatic: Option<String>,
654    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
655    pub rest: Rest,
656}
657
658#[derive(
659    Debug,
660    Clone,
661    Default,
662    PartialEq,
663    Eq,
664    Serialize,
665    Deserialize,
666    gproxy_protocol_macros::DeclaredFields,
667)]
668pub struct ModelInfoUpgrade {
669    pub model: String,
670    pub migration_markdown: String,
671    #[serde(default, skip_serializing_if = "Option::is_none")]
672    pub retirement_at: Option<String>,
673    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
674    pub rest: Rest,
675}
676
677#[derive(
678    Debug,
679    Clone,
680    Default,
681    PartialEq,
682    Eq,
683    Serialize,
684    Deserialize,
685    gproxy_protocol_macros::DeclaredFields,
686)]
687pub struct ModelAvailabilityNux {
688    pub message: String,
689    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
690    pub rest: Rest,
691}
692
693#[derive(
694    Debug,
695    Clone,
696    Default,
697    PartialEq,
698    Eq,
699    Serialize,
700    Deserialize,
701    gproxy_protocol_macros::DeclaredFields,
702)]
703pub struct GuardianModelPolicy {
704    #[serde(default, skip_serializing_if = "Option::is_none")]
705    pub computer_use: Option<GuardianReviewMode>,
706    #[serde(default, skip_serializing_if = "Option::is_none")]
707    pub shell: Option<GuardianReviewMode>,
708    #[serde(default, skip_serializing_if = "Option::is_none")]
709    pub file_changes: Option<GuardianReviewMode>,
710    #[serde(default, skip_serializing_if = "Option::is_none")]
711    pub mcp: Option<GuardianReviewMode>,
712    #[serde(default, skip_serializing_if = "Option::is_none")]
713    pub network: Option<GuardianReviewMode>,
714    #[serde(default, skip_serializing_if = "Option::is_none")]
715    pub permissions: Option<GuardianReviewMode>,
716    #[serde(default, skip_serializing_if = "Option::is_none")]
717    pub other_tools: Option<GuardianReviewMode>,
718    #[serde(default, skip_serializing_if = "Option::is_none")]
719    pub unscored_action: Option<GuardianUnscoredAction>,
720    #[serde(default, skip_serializing_if = "Option::is_none")]
721    pub initial_cua_call: Option<bool>,
722    #[serde(default, skip_serializing_if = "Option::is_none")]
723    pub sandboxed_exec_commands: Option<bool>,
724    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
725    pub rest: Rest,
726}
727
728#[derive(
729    Debug,
730    Clone,
731    Default,
732    PartialEq,
733    Eq,
734    Serialize,
735    Deserialize,
736    gproxy_protocol_macros::DeclaredFields,
737)]
738pub struct GuardianV2ModelConfig {
739    #[serde(default, skip_serializing_if = "Option::is_none")]
740    pub async_classifier_mode: Option<AsyncClassifierMode>,
741    #[serde(default, skip_serializing_if = "Option::is_none")]
742    pub async_classifier_conversation_token_limit: Option<usize>,
743    #[serde(default, skip_serializing_if = "Option::is_none")]
744    pub classifier_instructions: Option<String>,
745    #[serde(default, skip_serializing_if = "Option::is_none")]
746    pub review_threshold_basis_points: Option<u16>,
747    #[serde(default, skip_serializing_if = "Option::is_none")]
748    pub max_tool_call_lag: Option<usize>,
749    #[serde(default, skip_serializing_if = "Option::is_none")]
750    pub reasoning_effort: Option<ModelReasoningEffort>,
751    #[serde(default, skip_serializing_if = "Option::is_none")]
752    pub transcript: Option<GuardianV2TranscriptModelConfig>,
753    #[serde(default, skip_serializing_if = "Option::is_none")]
754    pub max_action_tokens: Option<usize>,
755    #[serde(default, skip_serializing_if = "Option::is_none")]
756    pub max_classifier_instruction_tokens: Option<usize>,
757    #[serde(default, skip_serializing_if = "Option::is_none")]
758    pub reuse_parent_compaction: Option<bool>,
759    #[serde(default, skip_serializing_if = "Option::is_none")]
760    pub max_parent_compaction_tokens: Option<usize>,
761    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
762    pub rest: Rest,
763}
764
765#[derive(
766    Debug,
767    Clone,
768    Default,
769    PartialEq,
770    Eq,
771    Serialize,
772    Deserialize,
773    gproxy_protocol_macros::DeclaredFields,
774)]
775pub struct GuardianV2TranscriptModelConfig {
776    #[serde(default, skip_serializing_if = "Option::is_none")]
777    pub sources: Option<Vec<String>>,
778    #[serde(default, skip_serializing_if = "Option::is_none")]
779    pub include_images: Option<bool>,
780    #[serde(default, skip_serializing_if = "Option::is_none")]
781    pub max_message_entry_tokens: Option<usize>,
782    #[serde(default, skip_serializing_if = "Option::is_none")]
783    pub max_tool_entry_tokens: Option<usize>,
784    #[serde(default, skip_serializing_if = "Option::is_none")]
785    pub max_message_transcript_tokens: Option<usize>,
786    #[serde(default, skip_serializing_if = "Option::is_none")]
787    pub max_tool_transcript_tokens: Option<usize>,
788    #[serde(default, skip_serializing_if = "Option::is_none")]
789    pub max_recent_non_user_entries: Option<usize>,
790    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
791    pub rest: Rest,
792}
793
794#[derive(
795    Debug,
796    Clone,
797    Default,
798    PartialEq,
799    Eq,
800    Serialize,
801    Deserialize,
802    gproxy_protocol_macros::DeclaredFields,
803)]
804pub struct ModelAccessPrograms {
805    #[serde(deserialize_with = "known_cyber_programs")]
806    pub cyber: Vec<CyberAccessProgram>,
807    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
808    pub rest: Rest,
809}
810
811#[derive(
812    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
813)]
814#[serde(rename_all = "snake_case")]
815pub enum ModelVisibility {
816    List,
817    Hide,
818    None,
819}
820
821#[derive(
822    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
823)]
824#[serde(rename_all = "snake_case")]
825pub enum ConfigShellToolType {
826    #[serde(alias = "default", alias = "local", alias = "shell_command")]
827    UnifiedExec,
828    Disabled,
829}
830
831#[derive(
832    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
833)]
834#[serde(rename_all = "snake_case")]
835pub enum ApplyPatchToolType {
836    Freeform,
837}
838
839#[derive(
840    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
841)]
842#[serde(rename_all = "snake_case")]
843pub enum WebSearchToolType {
844    Text,
845    TextAndImage,
846}
847
848#[derive(
849    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
850)]
851#[serde(rename_all = "snake_case")]
852pub enum TruncationMode {
853    Bytes,
854    Tokens,
855}
856
857#[derive(
858    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
859)]
860pub struct TruncationPolicyConfig {
861    pub mode: TruncationMode,
862    pub limit: i64,
863    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
864    pub rest: Rest,
865}
866
867#[derive(
868    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
869)]
870#[serde(rename_all = "snake_case")]
871pub enum ToolMode {
872    Direct,
873    CodeMode,
874    CodeModeOnly,
875}
876
877#[derive(
878    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
879)]
880#[serde(rename_all = "snake_case")]
881pub enum MultiAgentVersion {
882    Disabled,
883    V1,
884    V2,
885}
886
887#[derive(
888    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
889)]
890#[serde(rename_all = "snake_case")]
891pub enum CyberAccessProgram {
892    Standard,
893    DaybreakBlue,
894    DaybreakRed,
895}
896
897#[derive(
898    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
899)]
900#[serde(rename_all = "snake_case")]
901pub enum GuardianReviewMode {
902    Disabled,
903    Synchronous,
904    Adaptive,
905    #[serde(untagged)]
906    Unknown(String),
907}
908
909#[derive(
910    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
911)]
912#[serde(rename_all = "snake_case")]
913pub enum GuardianUnscoredAction {
914    Ignore,
915    AgeScore,
916    InvalidateScore,
917    #[serde(untagged)]
918    Unknown(String),
919}
920
921#[derive(
922    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
923)]
924#[serde(rename_all = "snake_case")]
925pub enum AsyncClassifierMode {
926    Snapshot,
927    Conversation,
928}
929
930#[derive(
931    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
932)]
933#[serde(rename_all = "snake_case")]
934pub enum ModelReasoningSummary {
935    Auto,
936    Concise,
937    Detailed,
938    None,
939}
940
941fn optional_selector<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
942where
943    D: serde::Deserializer<'de>,
944    T: serde::de::DeserializeOwned,
945{
946    Ok(Option::<String>::deserialize(deserializer)?
947        .and_then(|value| serde_json::from_value(serde_json::Value::String(value)).ok()))
948}
949
950fn known_cyber_programs<'de, D>(deserializer: D) -> Result<Vec<CyberAccessProgram>, D::Error>
951where
952    D: serde::Deserializer<'de>,
953{
954    Ok(Vec::<String>::deserialize(deserializer)?
955        .into_iter()
956        .filter_map(|value| serde_json::from_value(serde_json::Value::String(value)).ok())
957        .collect())
958}
959
960#[derive(
961    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
962)]
963#[serde(untagged)]
964pub enum ClientVersion {
965    Text(String),
966    Components([u32; 3]),
967}
968
969/// Catalog effort choices include CLI modes such as Ultra and Persistent;
970/// they are distinct from the Responses request's reasoning-effort parameter.
971#[derive(
972    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::DeclaredFields,
973)]
974#[serde(rename_all = "snake_case")]
975pub enum ModelReasoningEffort {
976    None,
977    Minimal,
978    Low,
979    Medium,
980    High,
981    Xhigh,
982    Max,
983    Ultra,
984    Persistent,
985    #[serde(untagged)]
986    Custom(String),
987}