1use serde::{Deserialize, Serialize};
2
3use crate::Rest;
4
5#[derive(
11 Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
12)]
13#[serde(rename_all = "snake_case")]
14#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
15#[derive(gproxy_protocol_macros::DeclaredFields)]
16#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
17pub struct ListModelsQuery {
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub after_id: Option<String>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub before_id: Option<String>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub limit: Option<i64>,
24 #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
25 pub rest: Rest,
26}
27
28pub type ListModelsRequest = crate::WireRequest<()>;
29pub type GetModelRequest = crate::WireRequest<()>;
30
31#[derive(
32 Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
33)]
34#[serde(rename_all = "snake_case")]
35#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
36#[derive(gproxy_protocol_macros::DeclaredFields)]
37#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
38pub struct ListModelsResponseBody {
39 pub data: Vec<ModelInfo>,
40 pub first_id: String,
41 pub has_more: bool,
42 pub last_id: String,
43 #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
44 pub rest: Rest,
45}
46
47pub type ListModelsResponse = crate::WireResponse<ListModelsResponseBody>;
48pub type GetModelResponse = crate::WireResponse<ModelInfo>;
49
50#[derive(
51 Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
52)]
53#[serde(rename_all = "snake_case")]
54#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
55#[derive(gproxy_protocol_macros::DeclaredFields)]
56#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
57pub struct ModelInfo {
58 pub id: String,
59 #[serde(default)]
60 pub allowed_fallback_models: Vec<String>,
61 pub capabilities: ModelCapabilities,
62 pub created_at: String,
63 pub display_name: String,
64 #[serde(
66 default,
67 deserialize_with = "present_nullable",
68 skip_serializing_if = "Option::is_none"
69 )]
70 pub line: Option<Option<String>>,
71 pub max_input_tokens: i64,
72 pub max_tokens: i64,
73 #[serde(rename = "type")]
74 pub type_: ModelType,
75 #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
76 pub rest: Rest,
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
80#[serde(rename_all = "snake_case")]
81#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
82#[derive(gproxy_protocol_macros::DeclaredFields)]
83#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
84pub enum ModelType {
85 Model,
86}
87
88#[derive(
89 Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
90)]
91#[serde(rename_all = "snake_case")]
92#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
93#[derive(gproxy_protocol_macros::DeclaredFields)]
94#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
95pub struct ModelCapabilities {
96 pub batch: CapabilitySupport,
97 pub citations: CapabilitySupport,
98 pub code_execution: CapabilitySupport,
99 pub context_management: ContextManagementCapability,
100 pub effort: EffortCapability,
101 pub image_input: CapabilitySupport,
102 pub pdf_input: CapabilitySupport,
103 pub structured_outputs: CapabilitySupport,
104 #[serde(default, skip_serializing_if = "Option::is_none")]
105 pub server_tools: Option<ServerToolsCapability>,
106 pub thinking: ThinkingCapability,
107 #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
108 pub rest: Rest,
109}
110
111#[derive(
112 Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
113)]
114#[serde(rename_all = "snake_case")]
115#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
116#[derive(gproxy_protocol_macros::DeclaredFields)]
117#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
118pub struct CapabilitySupport {
119 pub supported: bool,
120 #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
121 pub rest: Rest,
122}
123
124#[derive(
125 Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
126)]
127#[serde(rename_all = "snake_case")]
128#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
129#[derive(gproxy_protocol_macros::DeclaredFields)]
130#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
131pub struct ContextManagementCapability {
132 pub clear_thinking_20251015: CapabilitySupport,
133 pub clear_tool_uses_20250919: CapabilitySupport,
134 pub compact_20260112: CapabilitySupport,
135 pub supported: bool,
136 #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
137 pub rest: Rest,
138}
139
140#[derive(
141 Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
142)]
143#[serde(rename_all = "snake_case")]
144#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
145#[derive(gproxy_protocol_macros::DeclaredFields)]
146#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
147pub struct EffortCapability {
148 pub high: CapabilitySupport,
149 pub low: CapabilitySupport,
150 pub max: CapabilitySupport,
151 pub medium: CapabilitySupport,
152 pub supported: bool,
153 pub xhigh: CapabilitySupport,
154 #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
155 pub rest: Rest,
156}
157
158#[derive(
159 Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
160)]
161#[serde(rename_all = "snake_case")]
162#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
163#[derive(gproxy_protocol_macros::DeclaredFields)]
164#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
165pub struct ThinkingCapability {
166 pub supported: bool,
167 pub types: ThinkingTypes,
168 #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
169 pub rest: Rest,
170}
171
172#[derive(
173 Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
174)]
175#[serde(rename_all = "snake_case")]
176#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
177#[derive(gproxy_protocol_macros::DeclaredFields)]
178#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
179pub struct ThinkingTypes {
180 pub adaptive: CapabilitySupport,
181 pub enabled: CapabilitySupport,
182 #[serde(default, skip_serializing_if = "Option::is_none")]
183 pub disabled: Option<CapabilitySupport>,
184 #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
185 pub rest: Rest,
186}
187
188#[derive(
191 Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
192)]
193#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
194#[derive(gproxy_protocol_macros::DeclaredFields)]
195#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
196pub struct ServerToolsCapability {
197 pub supported: bool,
198 pub web_search: CapabilitySupport,
199 pub code_execution: CapabilitySupport,
200 #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
201 pub rest: Rest,
202}
203
204fn present_nullable<'de, D, T>(d: D) -> Result<Option<Option<T>>, D::Error>
205where
206 D: serde::Deserializer<'de>,
207 T: Deserialize<'de>,
208{
209 Option::<T>::deserialize(d).map(Some)
210}