Skip to main content

gproxy_protocol/wire/openai/chat/
content.rs

1use crate::Rest;
2use serde::{Deserialize, Serialize};
3
4pub(crate) fn present_nullable<'de, D, T>(deserializer: D) -> Result<Option<Option<T>>, D::Error>
5where
6    D: serde::Deserializer<'de>,
7    T: Deserialize<'de>,
8{
9    Option::<T>::deserialize(deserializer).map(Some)
10}
11
12pub(crate) fn required_nullable<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
13where
14    D: serde::Deserializer<'de>,
15    T: Deserialize<'de>,
16{
17    Option::<T>::deserialize(deserializer)
18}
19
20#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
21#[serde(untagged)]
22#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
23#[derive(gproxy_protocol_macros::DeclaredFields)]
24// Keep the public wire variants inline, as with the Claude content unions.
25#[allow(clippy::large_enum_variant)]
26#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
27pub enum ChatMessage {
28    Developer(DeveloperMessage),
29    System(SystemMessage),
30    User(UserMessage),
31    Assistant(AssistantMessage),
32    Tool(ToolMessage),
33    Function(FunctionMessage),
34}
35
36#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
37#[serde(rename_all = "snake_case")]
38#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
39#[derive(gproxy_protocol_macros::DeclaredFields)]
40#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
41pub struct DeveloperMessage {
42    pub role: DeveloperRole,
43    pub content: TextContent,
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub name: Option<String>,
46    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
47    pub rest: Rest,
48}
49#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
50#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
51#[derive(gproxy_protocol_macros::DeclaredFields)]
52#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
53pub enum DeveloperRole {
54    #[serde(rename = "developer")]
55    Developer,
56}
57
58#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
59#[serde(rename_all = "snake_case")]
60#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
61#[derive(gproxy_protocol_macros::DeclaredFields)]
62#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
63pub struct SystemMessage {
64    pub role: SystemRole,
65    pub content: TextContent,
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub name: Option<String>,
68    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
69    pub rest: Rest,
70}
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
72#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
73#[derive(gproxy_protocol_macros::DeclaredFields)]
74#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
75pub enum SystemRole {
76    #[serde(rename = "system")]
77    System,
78}
79
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
81#[serde(rename_all = "snake_case")]
82#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
83#[derive(gproxy_protocol_macros::DeclaredFields)]
84#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
85pub struct UserMessage {
86    pub role: UserRole,
87    pub content: UserContent,
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub name: Option<String>,
90    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
91    pub rest: Rest,
92}
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
94#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
95#[derive(gproxy_protocol_macros::DeclaredFields)]
96#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
97pub enum UserRole {
98    #[serde(rename = "user")]
99    User,
100}
101
102#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
103#[serde(rename_all = "snake_case")]
104#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
105#[derive(gproxy_protocol_macros::DeclaredFields)]
106#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
107pub struct AssistantMessage {
108    #[serde(
109        default,
110        deserialize_with = "present_nullable",
111        skip_serializing_if = "Option::is_none"
112    )]
113    pub reasoning_details: Option<Option<Vec<super::reasoning::ReasoningDetail>>>,
114    /// Plain-text reasoning returned by compatible providers (for example DeepSeek).
115    #[serde(
116        default,
117        deserialize_with = "present_nullable",
118        skip_serializing_if = "Option::is_none"
119    )]
120    pub reasoning_content: Option<Option<String>>,
121    /// Alternative compatible-provider spelling. Kept separately on the wire.
122    #[serde(
123        default,
124        deserialize_with = "present_nullable",
125        skip_serializing_if = "Option::is_none"
126    )]
127    pub reasoning: Option<Option<String>>,
128    pub role: AssistantRole,
129    #[serde(
130        default,
131        deserialize_with = "present_nullable",
132        skip_serializing_if = "Option::is_none"
133    )]
134    pub content: Option<Option<AssistantContent>>,
135    #[serde(
136        default,
137        deserialize_with = "present_nullable",
138        skip_serializing_if = "Option::is_none"
139    )]
140    pub audio: Option<Option<AssistantAudio>>,
141    #[serde(
142        default,
143        deserialize_with = "present_nullable",
144        skip_serializing_if = "Option::is_none"
145    )]
146    pub refusal: Option<Option<String>>,
147    #[serde(skip_serializing_if = "Option::is_none")]
148    pub name: Option<String>,
149    #[serde(skip_serializing_if = "Option::is_none")]
150    pub tool_calls: Option<Vec<MessageToolCall>>,
151    #[serde(
152        default,
153        deserialize_with = "present_nullable",
154        skip_serializing_if = "Option::is_none"
155    )]
156    pub function_call: Option<Option<FunctionCall>>,
157    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
158    pub rest: Rest,
159}
160#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
161#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
162#[derive(gproxy_protocol_macros::DeclaredFields)]
163#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
164pub enum AssistantRole {
165    #[serde(rename = "assistant")]
166    Assistant,
167}
168
169#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
170#[serde(rename_all = "snake_case")]
171#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
172#[derive(gproxy_protocol_macros::DeclaredFields)]
173#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
174pub struct ToolMessage {
175    pub role: ToolRole,
176    pub content: TextContent,
177    pub tool_call_id: String,
178    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
179    pub rest: Rest,
180}
181#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
182#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
183#[derive(gproxy_protocol_macros::DeclaredFields)]
184#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
185pub enum ToolRole {
186    #[serde(rename = "tool")]
187    Tool,
188}
189
190#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
191#[serde(rename_all = "snake_case")]
192#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
193#[derive(gproxy_protocol_macros::DeclaredFields)]
194#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
195pub struct FunctionMessage {
196    pub role: FunctionRole,
197    #[wire(required)]
198    #[cfg_attr(feature = "schema", schemars(extend("x-gproxy-required" = true)))]
199    #[serde(deserialize_with = "required_nullable")]
200    pub content: Option<String>,
201    pub name: String,
202    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
203    pub rest: Rest,
204}
205#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
206#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
207#[derive(gproxy_protocol_macros::DeclaredFields)]
208#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
209pub enum FunctionRole {
210    #[serde(rename = "function")]
211    Function,
212}
213
214pub type TextContent = StringOrTextParts;
215#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
216#[serde(untagged)]
217#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
218#[derive(gproxy_protocol_macros::DeclaredFields)]
219#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
220pub enum StringOrTextParts {
221    Text(String),
222    Parts(Vec<TextPart>),
223}
224pub type UserContent = UserContentParts;
225#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
226#[serde(untagged)]
227#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
228#[derive(gproxy_protocol_macros::DeclaredFields)]
229#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
230pub enum UserContentParts {
231    Text(String),
232    Parts(Vec<UserContentPart>),
233}
234pub type AssistantContent = AssistantContentParts;
235#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
236#[serde(untagged)]
237#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
238#[derive(gproxy_protocol_macros::DeclaredFields)]
239#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
240pub enum AssistantContentParts {
241    Text(String),
242    Parts(Vec<AssistantContentPart>),
243}
244
245#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
246#[serde(untagged)]
247#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
248#[derive(gproxy_protocol_macros::DeclaredFields)]
249#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
250pub enum UserContentPart {
251    #[serde(rename = "text")]
252    Text(TextPart),
253    #[serde(rename = "image_url")]
254    Image(ImagePart),
255    #[serde(rename = "input_audio")]
256    InputAudio(InputAudioPart),
257    #[serde(rename = "file")]
258    File(FilePart),
259}
260#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
261#[serde(untagged)]
262#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
263#[derive(gproxy_protocol_macros::DeclaredFields)]
264#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
265pub enum AssistantContentPart {
266    #[serde(rename = "text")]
267    Text(TextPart),
268    #[serde(rename = "refusal")]
269    Refusal(RefusalPart),
270}
271#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
272#[serde(rename_all = "snake_case")]
273#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
274#[derive(gproxy_protocol_macros::DeclaredFields)]
275#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
276pub struct TextPart {
277    #[serde(rename = "type")]
278    pub type_: TextPartType,
279    pub text: String,
280    #[serde(skip_serializing_if = "Option::is_none")]
281    pub prompt_cache_breakpoint: Option<PromptCacheBreakpoint>,
282    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
283    pub rest: Rest,
284}
285#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
286#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
287#[derive(gproxy_protocol_macros::DeclaredFields)]
288#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
289pub enum TextPartType {
290    #[serde(rename = "text")]
291    Text,
292}
293#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
294#[serde(rename_all = "snake_case")]
295#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
296#[derive(gproxy_protocol_macros::DeclaredFields)]
297#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
298pub struct RefusalPart {
299    #[serde(rename = "type")]
300    pub type_: RefusalType,
301    pub refusal: String,
302    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
303    pub rest: Rest,
304}
305#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
306#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
307#[derive(gproxy_protocol_macros::DeclaredFields)]
308#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
309pub enum RefusalType {
310    #[serde(rename = "refusal")]
311    Refusal,
312}
313#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
314#[serde(rename_all = "snake_case")]
315#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
316#[derive(gproxy_protocol_macros::DeclaredFields)]
317#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
318pub struct ImagePart {
319    #[serde(rename = "type")]
320    pub type_: ImagePartType,
321    pub image_url: ImageUrl,
322    #[serde(skip_serializing_if = "Option::is_none")]
323    pub prompt_cache_breakpoint: Option<PromptCacheBreakpoint>,
324    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
325    pub rest: Rest,
326}
327#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
328#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
329#[derive(gproxy_protocol_macros::DeclaredFields)]
330#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
331pub enum ImagePartType {
332    #[serde(rename = "image_url")]
333    ImageUrl,
334}
335#[derive(
336    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
337)]
338#[serde(rename_all = "snake_case")]
339#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
340#[derive(gproxy_protocol_macros::DeclaredFields)]
341#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
342pub struct ImageUrl {
343    pub url: String,
344    #[serde(skip_serializing_if = "Option::is_none")]
345    pub detail: Option<ImageDetail>,
346    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
347    pub rest: Rest,
348}
349#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
350#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
351#[derive(gproxy_protocol_macros::DeclaredFields)]
352#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
353pub enum ImageDetail {
354    #[serde(rename = "auto")]
355    Auto,
356    #[serde(rename = "low")]
357    Low,
358    #[serde(rename = "high")]
359    High,
360}
361#[derive(
362    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
363)]
364#[serde(rename_all = "snake_case")]
365#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
366#[derive(gproxy_protocol_macros::DeclaredFields)]
367#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
368pub struct InputAudioPart {
369    #[serde(rename = "type")]
370    pub type_: InputAudioPartType,
371    pub input_audio: InputAudio,
372    #[serde(skip_serializing_if = "Option::is_none")]
373    pub prompt_cache_breakpoint: Option<PromptCacheBreakpoint>,
374    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
375    pub rest: Rest,
376}
377#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
378#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
379#[derive(gproxy_protocol_macros::DeclaredFields)]
380#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
381pub enum InputAudioPartType {
382    #[serde(rename = "input_audio")]
383    InputAudio,
384}
385#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
386#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
387#[derive(gproxy_protocol_macros::DeclaredFields)]
388#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
389pub enum AudioFormat {
390    #[serde(rename = "wav")]
391    Wav,
392    #[serde(rename = "mp3")]
393    Mp3,
394}
395#[derive(
396    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
397)]
398#[serde(rename_all = "snake_case")]
399#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
400#[derive(gproxy_protocol_macros::DeclaredFields)]
401#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
402pub struct InputAudio {
403    pub data: String,
404    pub format: AudioFormat,
405    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
406    pub rest: Rest,
407}
408#[derive(
409    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
410)]
411#[serde(rename_all = "snake_case")]
412#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
413#[derive(gproxy_protocol_macros::DeclaredFields)]
414#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
415pub struct FilePart {
416    #[serde(rename = "type")]
417    pub type_: FilePartType,
418    pub file: FileRef,
419    #[serde(skip_serializing_if = "Option::is_none")]
420    pub prompt_cache_breakpoint: Option<PromptCacheBreakpoint>,
421    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
422    pub rest: Rest,
423}
424#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
425#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
426#[derive(gproxy_protocol_macros::DeclaredFields)]
427#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
428pub enum FilePartType {
429    #[serde(rename = "file")]
430    File,
431}
432#[derive(
433    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
434)]
435#[serde(rename_all = "snake_case")]
436#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
437#[derive(gproxy_protocol_macros::DeclaredFields)]
438#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
439pub struct FileRef {
440    #[serde(skip_serializing_if = "Option::is_none")]
441    pub file_data: Option<String>,
442    #[serde(skip_serializing_if = "Option::is_none")]
443    pub file_id: Option<String>,
444    #[serde(skip_serializing_if = "Option::is_none")]
445    pub filename: Option<String>,
446    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
447    pub rest: Rest,
448}
449#[derive(
450    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
451)]
452#[serde(rename_all = "snake_case")]
453#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
454#[derive(gproxy_protocol_macros::DeclaredFields)]
455#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
456pub struct PromptCacheBreakpoint {
457    pub mode: PromptCacheMode,
458    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
459    pub rest: Rest,
460}
461#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
462#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
463#[derive(gproxy_protocol_macros::DeclaredFields)]
464#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
465pub enum PromptCacheMode {
466    #[serde(rename = "explicit")]
467    Explicit,
468}
469
470#[derive(
471    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
472)]
473#[serde(rename_all = "snake_case")]
474#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
475#[derive(gproxy_protocol_macros::DeclaredFields)]
476#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
477pub struct AssistantAudio {
478    pub id: String,
479    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
480    pub rest: Rest,
481}
482#[derive(
483    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
484)]
485#[serde(rename_all = "snake_case")]
486#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
487#[derive(gproxy_protocol_macros::DeclaredFields)]
488#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
489pub struct FunctionCall {
490    pub arguments: String,
491    pub name: String,
492    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
493    pub rest: Rest,
494}
495#[derive(
496    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
497)]
498#[serde(rename_all = "snake_case")]
499#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
500#[derive(gproxy_protocol_macros::DeclaredFields)]
501#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
502pub struct ChatToolCall {
503    pub id: String,
504    pub function: FunctionCall,
505    #[serde(rename = "type")]
506    pub type_: ChatToolCallType,
507    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
508    pub rest: Rest,
509}
510#[derive(
511    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
512)]
513#[serde(rename_all = "snake_case")]
514#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
515#[derive(gproxy_protocol_macros::DeclaredFields)]
516#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
517pub struct CustomToolCall {
518    pub id: String,
519    pub custom: CustomCall,
520    #[serde(rename = "type")]
521    pub type_: CustomToolCallType,
522    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
523    pub rest: Rest,
524}
525#[derive(
526    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
527)]
528#[serde(rename_all = "snake_case")]
529#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
530#[derive(gproxy_protocol_macros::DeclaredFields)]
531#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
532pub struct CustomCall {
533    pub input: String,
534    pub name: String,
535    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
536    pub rest: Rest,
537}
538#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
539#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
540#[derive(gproxy_protocol_macros::DeclaredFields)]
541#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
542pub enum ChatToolCallType {
543    #[serde(rename = "function")]
544    Function,
545}
546#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
547#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
548#[derive(gproxy_protocol_macros::DeclaredFields)]
549#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
550pub enum CustomToolCallType {
551    #[serde(rename = "custom")]
552    Custom,
553}
554
555#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
556#[serde(untagged)]
557#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
558#[derive(gproxy_protocol_macros::DeclaredFields)]
559#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
560pub enum MessageToolCall {
561    Function(ChatToolCall),
562    Custom(CustomToolCall),
563}