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