Skip to main content

gproxy_protocol/openai/
models.rs

1use serde::{Deserialize, Serialize};
2
3use super::common::{ListObjectType, ModelObjectType, OpenAiModelId, Rest};
4
5pub type ModelsWireModel = super::common::OpenAiWireModel<ListModelsRequest, ModelListResponse>;
6pub type ModelRetrieveWireModel = super::common::OpenAiWireModel<RetrieveModelRequest, Model>;
7
8#[derive(
9    Debug, Clone, PartialEq, Serialize, Deserialize, Default, gproxy_protocol_macros::WireBuilder,
10)]
11#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
12pub struct ListModelsRequest {
13    #[serde(default, flatten)]
14    pub rest: Rest,
15}
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
18#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
19pub struct RetrieveModelRequest {
20    pub model: OpenAiModelId,
21    #[serde(default, flatten)]
22    pub rest: Rest,
23}
24
25#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
26#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
27pub struct ModelListResponse {
28    pub data: Vec<Model>,
29    pub object: ListObjectType,
30    #[serde(default, flatten)]
31    pub rest: Rest,
32}
33
34#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
35#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
36pub struct Model {
37    pub id: OpenAiModelId,
38    #[serde(default, skip_serializing_if = "Option::is_none")]
39    pub created: Option<u64>,
40    // gproxy extensions: limits and capabilities surfaced from providers that
41    // report them (Claude, Gemini, Codex). The official OpenAI model object
42    // has none of these fields, so a consumer of this schema must treat them
43    // as gproxy-specific rather than OpenAI-compatible.
44    #[serde(default, skip_serializing_if = "Option::is_none")]
45    pub display_name: Option<String>,
46    #[serde(default, skip_serializing_if = "Option::is_none")]
47    pub description: Option<String>,
48    #[serde(default, skip_serializing_if = "Option::is_none")]
49    pub instructions: Option<String>,
50    /// Input allowance. OpenAI has no separate input limit — the context
51    /// window *is* the accepted input size — so peers that split the two
52    /// (Claude's `max_input_tokens`, Gemini's `inputTokenLimit`) map here.
53    #[serde(default, skip_serializing_if = "Option::is_none")]
54    pub context_window: Option<u64>,
55    /// Codex reports an override ceiling separately from the default budget;
56    /// kept verbatim so a client can see the headroom, while `context_window`
57    /// carries the value the catalogue consumes.
58    #[serde(default, skip_serializing_if = "Option::is_none")]
59    pub max_context_window: Option<u64>,
60    #[serde(default, skip_serializing_if = "Option::is_none")]
61    pub max_output_tokens: Option<u64>,
62    #[serde(default, skip_serializing_if = "Option::is_none")]
63    pub thinking_supported: Option<bool>,
64    #[serde(default, skip_serializing_if = "Option::is_none")]
65    pub input_modalities: Option<Vec<String>>,
66    #[serde(default, skip_serializing_if = "Option::is_none")]
67    pub output_modalities: Option<Vec<String>>,
68    #[serde(default, skip_serializing_if = "Option::is_none")]
69    pub supported_parameters: Option<Vec<String>>,
70    #[serde(default, skip_serializing_if = "Option::is_none")]
71    pub supported_reasoning_levels: Option<Vec<ModelReasoningLevel>>,
72    #[serde(default, skip_serializing_if = "Option::is_none")]
73    pub default_reasoning_level: Option<String>,
74    #[serde(default, skip_serializing_if = "Option::is_none")]
75    pub service_tiers: Option<Vec<ModelServiceTier>>,
76    #[serde(default, skip_serializing_if = "Option::is_none")]
77    pub default_service_tier: Option<String>,
78    #[serde(default, skip_serializing_if = "Option::is_none")]
79    pub generation_methods: Option<Vec<String>>,
80    #[serde(default, skip_serializing_if = "Option::is_none")]
81    pub supported_actions: Option<Vec<String>>,
82    pub object: ModelObjectType,
83    // Optional because OpenAI-compatible providers (DeepSeek among them)
84    // omit it; decoding a model list must not fail on their behalf.
85    #[serde(default, skip_serializing_if = "Option::is_none")]
86    pub owned_by: Option<String>,
87    #[serde(default, flatten)]
88    pub rest: Rest,
89}
90
91#[derive(
92    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
93)]
94#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
95pub struct ModelReasoningLevel {
96    pub effort: String,
97    pub description: String,
98}
99
100#[derive(
101    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
102)]
103#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
104pub struct ModelServiceTier {
105    pub id: String,
106    pub name: String,
107    pub description: String,
108}