Skip to main content

gproxy_protocol/wire/claude/
models.rs

1use serde::{Deserialize, Serialize};
2
3use crate::Rest;
4
5/// Request/response shapes for `GET /v1/models` and `GET /v1/models/{model_id}`.
6/// `after_id`, `before_id`, and `limit` are query parameters; `anthropic_beta`
7/// is the repeated `anthropic-beta` request header; `model_id` is a path
8/// parameter. Source: `upstream_docs/claude/docs/List Models.md` and
9/// `Get a Model.md`.
10#[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    /// Provider-reported model line; new lines are allowed without inferring from IDs.
65    #[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/// Server tool availability is separate from programmatic tool calling
189/// (`ModelCapabilities::code_execution`).
190#[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}