1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7pub enum OperationFamily {
8 #[serde(rename = "model_list")]
9 ModelList,
10 #[serde(rename = "model_get")]
11 ModelGet,
12 #[serde(rename = "count_tokens")]
13 CountToken,
14 #[serde(rename = "compact")]
15 Compact,
16 #[serde(rename = "generate_content")]
17 GenerateContent,
18 #[serde(rename = "stream_generate_content")]
19 StreamGenerateContent,
20 #[serde(rename = "create_image")]
21 CreateImage,
22 #[serde(rename = "stream_create_image")]
23 StreamCreateImage,
24 #[serde(rename = "create_image_edit")]
25 CreateImageEdit,
26 #[serde(rename = "stream_create_image_edit")]
27 StreamCreateImageEdit,
28 #[serde(rename = "openai_response_websocket")]
29 OpenAiResponseWebSocket,
30 #[serde(rename = "gemini_live")]
31 GeminiLive,
32 #[serde(rename = "embeddings")]
33 Embedding,
34 #[serde(rename = "file_upload")]
35 FileUpload,
36 #[serde(rename = "file_list")]
37 FileList,
38 #[serde(rename = "file_get")]
39 FileGet,
40 #[serde(rename = "file_content")]
41 FileContent,
42 #[serde(rename = "file_delete")]
43 FileDelete,
44}
45
46impl OperationFamily {
47 pub const fn is_stream(self) -> bool {
48 matches!(
49 self,
50 Self::StreamGenerateContent | Self::StreamCreateImage | Self::StreamCreateImageEdit
51 )
52 }
53
54 pub const fn can_be_stream_driven(self) -> bool {
55 matches!(
56 self,
57 Self::GenerateContent | Self::Compact | Self::CreateImage | Self::CreateImageEdit
58 )
59 }
60}
61
62impl fmt::Display for OperationFamily {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 let label = match self {
65 Self::ModelList => "model_list",
66 Self::ModelGet => "model_get",
67 Self::CountToken => "count_tokens",
68 Self::Compact => "compact",
69 Self::GenerateContent => "generate_content",
70 Self::StreamGenerateContent => "stream_generate_content",
71 Self::CreateImage => "create_image",
72 Self::StreamCreateImage => "stream_create_image",
73 Self::CreateImageEdit => "create_image_edit",
74 Self::StreamCreateImageEdit => "stream_create_image_edit",
75 Self::OpenAiResponseWebSocket => "openai_response_websocket",
76 Self::GeminiLive => "gemini_live",
77 Self::Embedding => "embeddings",
78 Self::FileUpload => "file_upload",
79 Self::FileList => "file_list",
80 Self::FileGet => "file_get",
81 Self::FileContent => "file_content",
82 Self::FileDelete => "file_delete",
83 };
84 f.write_str(label)
85 }
86}
87
88impl TryFrom<&str> for OperationFamily {
89 type Error = &'static str;
90
91 fn try_from(value: &str) -> Result<Self, Self::Error> {
92 match value {
93 "model_list" => Ok(Self::ModelList),
94 "model_get" => Ok(Self::ModelGet),
95 "count_tokens" => Ok(Self::CountToken),
96 "compact" => Ok(Self::Compact),
97 "generate_content" => Ok(Self::GenerateContent),
98 "stream_generate_content" => Ok(Self::StreamGenerateContent),
99 "create_image" => Ok(Self::CreateImage),
100 "stream_create_image" => Ok(Self::StreamCreateImage),
101 "create_image_edit" => Ok(Self::CreateImageEdit),
102 "stream_create_image_edit" => Ok(Self::StreamCreateImageEdit),
103 "openai_response_websocket" => Ok(Self::OpenAiResponseWebSocket),
104 "gemini_live" => Ok(Self::GeminiLive),
105 "embeddings" => Ok(Self::Embedding),
106 "file_upload" => Ok(Self::FileUpload),
107 "file_list" => Ok(Self::FileList),
108 "file_get" => Ok(Self::FileGet),
109 "file_content" => Ok(Self::FileContent),
110 "file_delete" => Ok(Self::FileDelete),
111 _ => Err("unknown operation family"),
112 }
113 }
114}
115
116impl TryFrom<String> for OperationFamily {
117 type Error = &'static str;
118
119 fn try_from(value: String) -> Result<Self, Self::Error> {
120 Self::try_from(value.as_str())
121 }
122}
123
124#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
126pub enum ProtocolKind {
127 #[serde(rename = "openai")]
128 OpenAi,
129 #[serde(rename = "claude")]
130 Claude,
131 #[serde(rename = "gemini")]
132 Gemini,
133 #[serde(rename = "openai_chat_completions")]
134 OpenAiChatCompletion,
135 #[serde(rename = "gemini_ndjson")]
136 GeminiNDJson,
137 #[serde(rename = "openai_response")]
138 OpenAiResponse,
139}
140
141impl ProtocolKind {
142 pub const fn normalize_gemini_stream(self) -> Self {
143 match self {
144 Self::GeminiNDJson => Self::Gemini,
145 _ => self,
146 }
147 }
148}
149
150impl fmt::Display for ProtocolKind {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 let label = match self {
153 Self::OpenAi => "openai",
154 Self::Claude => "claude",
155 Self::Gemini => "gemini",
156 Self::OpenAiChatCompletion => "openai_chat_completions",
157 Self::GeminiNDJson => "gemini_ndjson",
158 Self::OpenAiResponse => "openai_response",
159 };
160 f.write_str(label)
161 }
162}
163
164impl TryFrom<&str> for ProtocolKind {
165 type Error = &'static str;
166
167 fn try_from(value: &str) -> Result<Self, Self::Error> {
168 match value {
169 "openai" => Ok(Self::OpenAi),
170 "claude" => Ok(Self::Claude),
171 "gemini" => Ok(Self::Gemini),
172 "openai_chat_completions" => Ok(Self::OpenAiChatCompletion),
173 "gemini_ndjson" => Ok(Self::GeminiNDJson),
174 "openai_response" => Ok(Self::OpenAiResponse),
175 _ => Err("unknown protocol kind"),
176 }
177 }
178}
179
180impl TryFrom<String> for ProtocolKind {
181 type Error = &'static str;
182
183 fn try_from(value: String) -> Result<Self, Self::Error> {
184 Self::try_from(value.as_str())
185 }
186}