1use std::collections::BTreeMap;
2
3use bytes::Bytes;
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use serde_json::Value;
6
7pub type JsonObject = BTreeMap<String, Value>;
8pub type QueryParams = crate::transport::QueryParams;
9
10macro_rules! string_enum {
11 ($name:ident { $($variant:ident => $wire:literal,)* }) => {
12 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
13 pub enum $name {
14 $($variant,)*
15 Unknown(String),
16 }
17
18 impl $name {
19 pub fn as_str(&self) -> &str {
20 match self {
21 $(Self::$variant => $wire,)*
22 Self::Unknown(value) => value,
23 }
24 }
25 }
26
27 impl From<&str> for $name {
28 fn from(value: &str) -> Self {
29 match value {
30 $($wire => Self::$variant,)*
31 other => Self::Unknown(other.to_owned()),
32 }
33 }
34 }
35
36 impl From<String> for $name {
37 fn from(value: String) -> Self {
38 Self::from(value.as_str())
39 }
40 }
41
42 impl Serialize for $name {
43 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
44 where
45 S: Serializer,
46 {
47 serializer.serialize_str(self.as_str())
48 }
49 }
50
51 impl<'de> Deserialize<'de> for $name {
52 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
53 where
54 D: Deserializer<'de>,
55 {
56 let value = String::deserialize(deserializer)?;
57 Ok(Self::from(value))
58 }
59 }
60 };
61}
62
63macro_rules! json_object_type {
64 ($name:ident) => {
65 #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
66 pub struct $name {
67 #[serde(flatten)]
68 pub extra: JsonObject,
69 }
70
71 impl $name {
72 pub fn new() -> Self {
73 Self::default()
74 }
75
76 pub fn with_field(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
77 self.extra.insert(key.into(), value.into());
78 self
79 }
80 }
81 };
82}
83
84macro_rules! query_struct {
85 ($name:ident { $($field:ident : $typ:ty => $wire:literal,)* }) => {
86 #[derive(Debug, Clone, Default, PartialEq)]
87 pub struct $name {
88 $(pub $field: Option<$typ>,)*
89 pub extra: QueryParams,
90 }
91
92 impl $name {
93 pub fn new() -> Self {
94 Self::default()
95 }
96
97 pub fn with_extra_query(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
98 self.extra.push((key.into(), value.into()));
99 self
100 }
101 }
102
103 impl crate::transport::IntoQueryParams for $name {
104 fn into_query_params(self) -> QueryParams {
105 let mut query = Vec::new();
106 $(
107 if let Some(value) = self.$field {
108 query.push(($wire.to_owned(), value.to_string()));
109 }
110 )*
111 query.extend(self.extra);
112 query
113 }
114 }
115 };
116}
117
118query_struct!(PaginationQuery {
119 offset: u32 => "offset",
120 limit: u32 => "limit",
121});
122
123query_struct!(ActivityQuery {
124 date: String => "date",
125 api_key_hash: String => "api_key_hash",
126 user_id: String => "user_id",
127});
128
129query_struct!(BenchmarksQuery {
130 source: String => "source",
131 task_type: String => "task_type",
132 arena: String => "arena",
133 category: String => "category",
134 max_results: u32 => "max_results",
135});
136
137query_struct!(TaskClassificationsQuery {
138 window: String => "window",
139});
140
141query_struct!(AppRankingsQuery {
142 category: String => "category",
143 subcategory: String => "subcategory",
144 sort: String => "sort",
145 start_date: String => "start_date",
146 end_date: String => "end_date",
147 limit: u32 => "limit",
148 offset: u32 => "offset",
149});
150
151query_struct!(RankingsDailyQuery {
152 start_date: String => "start_date",
153 end_date: String => "end_date",
154});
155
156query_struct!(FilesQuery {
157 limit: u32 => "limit",
158 cursor: String => "cursor",
159 workspace_id: String => "workspace_id",
160});
161
162query_struct!(WorkspaceScopedPaginationQuery {
163 offset: u32 => "offset",
164 limit: u32 => "limit",
165 workspace_id: String => "workspace_id",
166});
167
168query_struct!(KeysQuery {
169 include_disabled: bool => "include_disabled",
170 offset: u32 => "offset",
171 workspace_id: String => "workspace_id",
172});
173
174query_struct!(ModelsQuery {
175 category: String => "category",
176 supported_parameters: String => "supported_parameters",
177 output_modalities: String => "output_modalities",
178 sort: String => "sort",
179 q: String => "q",
180 input_modalities: String => "input_modalities",
181 context: u32 => "context",
182 min_price: f64 => "min_price",
183 max_price: f64 => "max_price",
184 arch: String => "arch",
185 model_authors: String => "model_authors",
186 providers: String => "providers",
187 distillable: String => "distillable",
188 zdr: String => "zdr",
189 region: String => "region",
190 min_output_price: f64 => "min_output_price",
191 max_output_price: f64 => "max_output_price",
192 min_age_days: u32 => "min_age_days",
193 max_age_days: u32 => "max_age_days",
194 min_intelligence_index: f64 => "min_intelligence_index",
195 max_intelligence_index: f64 => "max_intelligence_index",
196 min_coding_index: f64 => "min_coding_index",
197 max_coding_index: f64 => "max_coding_index",
198 min_agentic_index: f64 => "min_agentic_index",
199 max_agentic_index: f64 => "max_agentic_index",
200 min_tool_success_rate: f64 => "min_tool_success_rate",
201 max_tool_success_rate: f64 => "max_tool_success_rate",
202});
203
204query_struct!(ModelCountQuery {
205 output_modalities: String => "output_modalities",
206});
207
208query_struct!(VideoContentQuery {
209 index: u32 => "index",
210});
211
212pub type ByokKeysQuery = WorkspaceScopedPaginationQuery;
213pub type GuardrailsQuery = WorkspaceScopedPaginationQuery;
214pub type ObservabilityDestinationsQuery = WorkspaceScopedPaginationQuery;
215pub type KeyAssignmentsQuery = PaginationQuery;
216pub type MemberAssignmentsQuery = PaginationQuery;
217pub type OrganizationMembersQuery = PaginationQuery;
218pub type PresetsQuery = PaginationQuery;
219pub type PresetVersionsQuery = PaginationQuery;
220pub type WorkspacesQuery = PaginationQuery;
221pub type WorkspaceMembersQuery = PaginationQuery;
222
223string_enum!(ChatRole {
224 System => "system",
225 User => "user",
226 Assistant => "assistant",
227 Developer => "developer",
228 Tool => "tool",
229});
230
231string_enum!(FinishReason {
232 Stop => "stop",
233 Length => "length",
234 ToolCalls => "tool_calls",
235 ContentFilter => "content_filter",
236 Error => "error",
237});
238
239string_enum!(ServiceTier {
240 Auto => "auto",
241 Default => "default",
242 Flex => "flex",
243 Priority => "priority",
244 Scale => "scale",
245});
246
247string_enum!(DataCollection {
248 Allow => "allow",
249 Deny => "deny",
250});
251
252string_enum!(ProviderSort {
253 Price => "price",
254 Throughput => "throughput",
255 Latency => "latency",
256});
257
258#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
259#[serde(untagged)]
260pub enum StringOrList {
261 String(String),
262 List(Vec<String>),
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
266#[serde(untagged)]
267pub enum ChatContent {
268 Text(String),
269 Parts(Vec<ContentPart>),
270 Null,
271}
272
273impl Default for ChatContent {
274 fn default() -> Self {
275 Self::Text(String::new())
276 }
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
280pub struct ContentPart {
281 #[serde(rename = "type")]
282 pub type_: String,
283 #[serde(default, flatten)]
284 pub extra: JsonObject,
285}
286
287impl ContentPart {
288 pub fn text(text: impl Into<String>) -> Self {
289 let mut extra = JsonObject::new();
290 extra.insert("text".to_owned(), Value::String(text.into()));
291 Self {
292 type_: "text".to_owned(),
293 extra,
294 }
295 }
296
297 pub fn image_url(url: impl Into<String>) -> Self {
298 let mut image_url = JsonObject::new();
299 image_url.insert("url".to_owned(), Value::String(url.into()));
300 let mut extra = JsonObject::new();
301 extra.insert(
302 "image_url".to_owned(),
303 Value::Object(image_url.into_iter().collect()),
304 );
305 Self {
306 type_: "image_url".to_owned(),
307 extra,
308 }
309 }
310
311 pub fn with_field(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
312 self.extra.insert(key.into(), value.into());
313 self
314 }
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
318pub struct ChatMessage {
319 pub role: ChatRole,
320 #[serde(default, skip_serializing_if = "Option::is_none")]
321 pub content: Option<ChatContent>,
322 #[serde(skip_serializing_if = "Option::is_none")]
323 pub name: Option<String>,
324 #[serde(skip_serializing_if = "Option::is_none")]
325 pub tool_call_id: Option<String>,
326 #[serde(default, flatten)]
327 pub extra: JsonObject,
328}
329
330impl ChatMessage {
331 pub fn new(role: ChatRole, content: ChatContent) -> Self {
332 Self {
333 role,
334 content: Some(content),
335 name: None,
336 tool_call_id: None,
337 extra: JsonObject::new(),
338 }
339 }
340
341 pub fn system(content: impl Into<String>) -> Self {
342 Self::new(ChatRole::System, ChatContent::Text(content.into()))
343 }
344
345 pub fn user(content: impl Into<String>) -> Self {
346 Self::new(ChatRole::User, ChatContent::Text(content.into()))
347 }
348
349 pub fn assistant(content: impl Into<String>) -> Self {
350 Self::new(ChatRole::Assistant, ChatContent::Text(content.into()))
351 }
352
353 pub fn tool(tool_call_id: impl Into<String>, content: impl Into<String>) -> Self {
354 let mut msg = Self::new(ChatRole::Tool, ChatContent::Text(content.into()));
355 msg.tool_call_id = Some(tool_call_id.into());
356 msg
357 }
358
359 pub fn with_field(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
360 self.extra.insert(key.into(), value.into());
361 self
362 }
363}
364
365#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
366pub struct ProviderPriceLimit {
367 #[serde(skip_serializing_if = "Option::is_none")]
368 pub prompt: Option<String>,
369 #[serde(skip_serializing_if = "Option::is_none")]
370 pub completion: Option<String>,
371 #[serde(skip_serializing_if = "Option::is_none")]
372 pub request: Option<String>,
373 #[serde(skip_serializing_if = "Option::is_none")]
374 pub image: Option<String>,
375 #[serde(skip_serializing_if = "Option::is_none")]
376 pub audio: Option<String>,
377 #[serde(default, flatten)]
378 pub extra: JsonObject,
379}
380
381#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
382pub struct ProviderPreferences {
383 #[serde(skip_serializing_if = "Option::is_none")]
384 pub allow_fallbacks: Option<bool>,
385 #[serde(skip_serializing_if = "Option::is_none")]
386 pub data_collection: Option<DataCollection>,
387 #[serde(skip_serializing_if = "Option::is_none")]
388 pub enforce_distillable_text: Option<bool>,
389 #[serde(skip_serializing_if = "Option::is_none")]
390 pub ignore: Option<Vec<String>>,
391 #[serde(skip_serializing_if = "Option::is_none")]
392 pub max_price: Option<ProviderPriceLimit>,
393 #[serde(skip_serializing_if = "Option::is_none")]
394 pub only: Option<Vec<String>>,
395 #[serde(skip_serializing_if = "Option::is_none")]
396 pub order: Option<Vec<String>>,
397 #[serde(skip_serializing_if = "Option::is_none")]
398 pub preferred_max_latency: Option<f64>,
399 #[serde(skip_serializing_if = "Option::is_none")]
400 pub preferred_min_throughput: Option<f64>,
401 #[serde(skip_serializing_if = "Option::is_none")]
402 pub quantizations: Option<Vec<String>>,
403 #[serde(skip_serializing_if = "Option::is_none")]
404 pub require_parameters: Option<bool>,
405 #[serde(skip_serializing_if = "Option::is_none")]
406 pub sort: Option<Value>,
407 #[serde(skip_serializing_if = "Option::is_none")]
408 pub zdr: Option<bool>,
409 #[serde(default, flatten)]
410 pub extra: JsonObject,
411}
412
413impl ProviderPreferences {
414 pub fn new() -> Self {
415 Self::default()
416 }
417
418 pub fn require_parameters(mut self, value: bool) -> Self {
419 self.require_parameters = Some(value);
420 self
421 }
422
423 pub fn only(mut self, providers: impl IntoIterator<Item = impl Into<String>>) -> Self {
424 self.only = Some(providers.into_iter().map(Into::into).collect());
425 self
426 }
427
428 pub fn order(mut self, providers: impl IntoIterator<Item = impl Into<String>>) -> Self {
429 self.order = Some(providers.into_iter().map(Into::into).collect());
430 self
431 }
432
433 pub fn with_field(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
434 self.extra.insert(key.into(), value.into());
435 self
436 }
437}
438
439#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
440pub struct ChatCompletionRequest {
441 #[serde(skip_serializing_if = "Option::is_none")]
442 pub cache_control: Option<Value>,
443 #[serde(skip_serializing_if = "Option::is_none")]
444 pub debug: Option<bool>,
445 #[serde(skip_serializing_if = "Option::is_none")]
446 pub image_config: Option<Value>,
447 #[serde(skip_serializing_if = "Option::is_none")]
448 pub logit_bias: Option<Value>,
449 #[serde(skip_serializing_if = "Option::is_none")]
450 pub model: Option<String>,
451 #[serde(skip_serializing_if = "Option::is_none")]
452 pub models: Option<Vec<String>>,
453 pub messages: Vec<ChatMessage>,
454 #[serde(skip_serializing_if = "Option::is_none")]
455 pub temperature: Option<f64>,
456 #[serde(skip_serializing_if = "Option::is_none")]
457 pub max_tokens: Option<u32>,
458 #[serde(skip_serializing_if = "Option::is_none")]
459 pub max_completion_tokens: Option<u32>,
460 #[serde(skip_serializing_if = "Option::is_none")]
461 pub min_p: Option<f64>,
462 #[serde(skip_serializing_if = "Option::is_none")]
463 pub modalities: Option<Vec<String>>,
464 #[serde(skip_serializing_if = "Option::is_none")]
465 pub response_format: Option<Value>,
466 #[serde(skip_serializing_if = "Option::is_none")]
467 pub provider: Option<ProviderPreferences>,
468 #[serde(skip_serializing_if = "Option::is_none")]
469 pub plugins: Option<Value>,
470 #[serde(skip_serializing_if = "Option::is_none")]
471 pub route: Option<Value>,
472 #[serde(skip_serializing_if = "Option::is_none")]
473 pub service_tier: Option<ServiceTier>,
474 #[serde(skip_serializing_if = "Option::is_none")]
475 pub stream: Option<bool>,
476 #[serde(skip_serializing_if = "Option::is_none")]
477 pub stream_options: Option<Value>,
478 #[serde(skip_serializing_if = "Option::is_none")]
479 pub tools: Option<Value>,
480 #[serde(skip_serializing_if = "Option::is_none")]
481 pub tool_choice: Option<Value>,
482 #[serde(skip_serializing_if = "Option::is_none")]
483 pub parallel_tool_calls: Option<bool>,
484 #[serde(skip_serializing_if = "Option::is_none")]
485 pub reasoning: Option<Value>,
486 #[serde(skip_serializing_if = "Option::is_none")]
487 pub reasoning_effort: Option<String>,
488 #[serde(skip_serializing_if = "Option::is_none")]
489 pub stop: Option<Value>,
490 #[serde(skip_serializing_if = "Option::is_none")]
491 pub stop_server_tools_when: Option<Value>,
492 #[serde(skip_serializing_if = "Option::is_none")]
493 pub top_a: Option<f64>,
494 #[serde(skip_serializing_if = "Option::is_none")]
495 pub top_p: Option<f64>,
496 #[serde(skip_serializing_if = "Option::is_none")]
497 pub top_k: Option<u32>,
498 #[serde(skip_serializing_if = "Option::is_none")]
499 pub top_logprobs: Option<u32>,
500 #[serde(skip_serializing_if = "Option::is_none")]
501 pub logprobs: Option<bool>,
502 #[serde(skip_serializing_if = "Option::is_none")]
503 pub frequency_penalty: Option<f64>,
504 #[serde(skip_serializing_if = "Option::is_none")]
505 pub presence_penalty: Option<f64>,
506 #[serde(skip_serializing_if = "Option::is_none")]
507 pub repetition_penalty: Option<f64>,
508 #[serde(skip_serializing_if = "Option::is_none")]
509 pub seed: Option<i64>,
510 #[serde(skip_serializing_if = "Option::is_none")]
511 pub user: Option<String>,
512 #[serde(skip_serializing_if = "Option::is_none")]
513 pub session_id: Option<String>,
514 #[serde(skip_serializing_if = "Option::is_none")]
515 pub metadata: Option<JsonObject>,
516 #[serde(skip_serializing_if = "Option::is_none")]
517 pub trace: Option<Value>,
518 #[serde(default, flatten)]
519 pub extra: JsonObject,
520}
521
522impl ChatCompletionRequest {
523 pub fn new(model: impl Into<String>, messages: Vec<ChatMessage>) -> Self {
524 Self::from_model_fields(Some(model.into()), None, messages)
525 }
526
527 pub fn new_with_models(
528 models: impl IntoIterator<Item = impl Into<String>>,
529 messages: Vec<ChatMessage>,
530 ) -> Self {
531 Self::from_model_fields(
532 None,
533 Some(models.into_iter().map(Into::into).collect()),
534 messages,
535 )
536 }
537
538 fn from_model_fields(
539 model: Option<String>,
540 models: Option<Vec<String>>,
541 messages: Vec<ChatMessage>,
542 ) -> Self {
543 Self {
544 cache_control: None,
545 debug: None,
546 image_config: None,
547 logit_bias: None,
548 model,
549 models,
550 messages,
551 temperature: None,
552 max_tokens: None,
553 max_completion_tokens: None,
554 min_p: None,
555 modalities: None,
556 response_format: None,
557 provider: None,
558 plugins: None,
559 route: None,
560 service_tier: None,
561 stream: None,
562 stream_options: None,
563 tools: None,
564 tool_choice: None,
565 parallel_tool_calls: None,
566 reasoning: None,
567 reasoning_effort: None,
568 stop: None,
569 stop_server_tools_when: None,
570 top_a: None,
571 top_p: None,
572 top_k: None,
573 top_logprobs: None,
574 logprobs: None,
575 frequency_penalty: None,
576 presence_penalty: None,
577 repetition_penalty: None,
578 seed: None,
579 user: None,
580 session_id: None,
581 metadata: None,
582 trace: None,
583 extra: JsonObject::new(),
584 }
585 }
586
587 pub fn message(mut self, message: ChatMessage) -> Self {
588 self.messages.push(message);
589 self
590 }
591
592 pub fn temperature(mut self, value: f64) -> Self {
593 self.temperature = Some(value);
594 self
595 }
596
597 pub fn max_tokens(mut self, value: u32) -> Self {
598 self.max_tokens = Some(value);
599 self
600 }
601
602 pub fn stream(mut self, value: bool) -> Self {
603 self.stream = Some(value);
604 self
605 }
606
607 pub fn provider(mut self, value: ProviderPreferences) -> Self {
608 self.provider = Some(value);
609 self
610 }
611
612 pub fn with_field(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
613 self.extra.insert(key.into(), value.into());
614 self
615 }
616}
617
618#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
619pub struct Usage {
620 #[serde(default)]
621 pub prompt_tokens: Option<i64>,
622 #[serde(default)]
623 pub completion_tokens: Option<i64>,
624 #[serde(default)]
625 pub total_tokens: Option<i64>,
626 #[serde(default, flatten)]
627 pub extra: JsonObject,
628}
629
630#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
631pub struct ChatChoice {
632 #[serde(default)]
633 pub index: Option<i64>,
634 #[serde(default)]
635 pub finish_reason: Option<FinishReason>,
636 #[serde(default)]
637 pub message: Option<ChatMessage>,
638 #[serde(default)]
639 pub delta: Option<Value>,
640 #[serde(default)]
641 pub logprobs: Option<Value>,
642 #[serde(default, flatten)]
643 pub extra: JsonObject,
644}
645
646#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
647pub struct ChatCompletionResponse {
648 #[serde(default)]
649 pub id: Option<String>,
650 #[serde(default)]
651 pub choices: Vec<ChatChoice>,
652 #[serde(default)]
653 pub created: Option<i64>,
654 #[serde(default)]
655 pub model: Option<String>,
656 #[serde(default)]
657 pub object: Option<String>,
658 #[serde(default)]
659 pub usage: Option<Usage>,
660 #[serde(default)]
661 pub system_fingerprint: Option<String>,
662 #[serde(default)]
663 pub service_tier: Option<ServiceTier>,
664 #[serde(default)]
665 pub openrouter_metadata: Option<Value>,
666 #[serde(default, flatten)]
667 pub extra: JsonObject,
668}
669
670pub type ChatStreamChunk = ChatCompletionResponse;
671
672#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
673pub struct ResponsesRequest {
674 #[serde(skip_serializing_if = "Option::is_none")]
675 pub background: Option<bool>,
676 #[serde(skip_serializing_if = "Option::is_none")]
677 pub cache_control: Option<Value>,
678 #[serde(skip_serializing_if = "Option::is_none")]
679 pub debug: Option<bool>,
680 #[serde(skip_serializing_if = "Option::is_none")]
681 pub model: Option<String>,
682 #[serde(skip_serializing_if = "Option::is_none")]
683 pub models: Option<Vec<String>>,
684 #[serde(skip_serializing_if = "Option::is_none")]
685 pub input: Option<Value>,
686 #[serde(skip_serializing_if = "Option::is_none")]
687 pub instructions: Option<String>,
688 #[serde(skip_serializing_if = "Option::is_none")]
689 pub previous_response_id: Option<String>,
690 #[serde(skip_serializing_if = "Option::is_none")]
691 pub temperature: Option<f64>,
692 #[serde(skip_serializing_if = "Option::is_none")]
693 pub frequency_penalty: Option<f64>,
694 #[serde(skip_serializing_if = "Option::is_none")]
695 pub image_config: Option<Value>,
696 #[serde(skip_serializing_if = "Option::is_none")]
697 pub include: Option<Value>,
698 #[serde(skip_serializing_if = "Option::is_none")]
699 pub max_output_tokens: Option<u32>,
700 #[serde(skip_serializing_if = "Option::is_none")]
701 pub max_tool_calls: Option<u32>,
702 #[serde(skip_serializing_if = "Option::is_none")]
703 pub metadata: Option<JsonObject>,
704 #[serde(skip_serializing_if = "Option::is_none")]
705 pub modalities: Option<Vec<String>>,
706 #[serde(skip_serializing_if = "Option::is_none")]
707 pub parallel_tool_calls: Option<bool>,
708 #[serde(skip_serializing_if = "Option::is_none")]
709 pub plugins: Option<Value>,
710 #[serde(skip_serializing_if = "Option::is_none")]
711 pub presence_penalty: Option<f64>,
712 #[serde(skip_serializing_if = "Option::is_none")]
713 pub prompt: Option<Value>,
714 #[serde(skip_serializing_if = "Option::is_none")]
715 pub prompt_cache_key: Option<String>,
716 #[serde(skip_serializing_if = "Option::is_none")]
717 pub reasoning: Option<Value>,
718 #[serde(skip_serializing_if = "Option::is_none")]
719 pub route: Option<Value>,
720 #[serde(skip_serializing_if = "Option::is_none")]
721 pub safety_identifier: Option<String>,
722 #[serde(skip_serializing_if = "Option::is_none")]
723 pub service_tier: Option<ServiceTier>,
724 #[serde(skip_serializing_if = "Option::is_none")]
725 pub session_id: Option<String>,
726 #[serde(skip_serializing_if = "Option::is_none")]
727 pub stop_server_tools_when: Option<Value>,
728 #[serde(skip_serializing_if = "Option::is_none")]
729 pub text: Option<Value>,
730 #[serde(skip_serializing_if = "Option::is_none")]
731 pub tools: Option<Value>,
732 #[serde(skip_serializing_if = "Option::is_none")]
733 pub tool_choice: Option<Value>,
734 #[serde(skip_serializing_if = "Option::is_none")]
735 pub provider: Option<ProviderPreferences>,
736 #[serde(skip_serializing_if = "Option::is_none")]
737 pub stream: Option<bool>,
738 #[serde(skip_serializing_if = "Option::is_none")]
739 pub store: Option<bool>,
740 #[serde(skip_serializing_if = "Option::is_none")]
741 pub top_k: Option<u32>,
742 #[serde(skip_serializing_if = "Option::is_none")]
743 pub top_logprobs: Option<u32>,
744 #[serde(skip_serializing_if = "Option::is_none")]
745 pub top_p: Option<f64>,
746 #[serde(skip_serializing_if = "Option::is_none")]
747 pub trace: Option<Value>,
748 #[serde(skip_serializing_if = "Option::is_none")]
749 pub truncation: Option<String>,
750 #[serde(skip_serializing_if = "Option::is_none")]
751 pub user: Option<String>,
752 #[serde(default, flatten)]
753 pub extra: JsonObject,
754}
755
756impl ResponsesRequest {
757 pub fn new(model: impl Into<String>, input: impl Into<Value>) -> Self {
758 Self::from_model_fields(Some(model.into()), None, input.into())
759 }
760
761 pub fn new_with_models(
762 models: impl IntoIterator<Item = impl Into<String>>,
763 input: impl Into<Value>,
764 ) -> Self {
765 Self::from_model_fields(
766 None,
767 Some(models.into_iter().map(Into::into).collect()),
768 input.into(),
769 )
770 }
771
772 fn from_model_fields(model: Option<String>, models: Option<Vec<String>>, input: Value) -> Self {
773 Self {
774 background: None,
775 cache_control: None,
776 debug: None,
777 model,
778 models,
779 input: Some(input),
780 instructions: None,
781 previous_response_id: None,
782 temperature: None,
783 frequency_penalty: None,
784 image_config: None,
785 include: None,
786 max_output_tokens: None,
787 max_tool_calls: None,
788 metadata: None,
789 modalities: None,
790 parallel_tool_calls: None,
791 plugins: None,
792 presence_penalty: None,
793 prompt: None,
794 prompt_cache_key: None,
795 reasoning: None,
796 route: None,
797 safety_identifier: None,
798 service_tier: None,
799 session_id: None,
800 stop_server_tools_when: None,
801 text: None,
802 tools: None,
803 tool_choice: None,
804 provider: None,
805 stream: None,
806 store: None,
807 top_k: None,
808 top_logprobs: None,
809 top_p: None,
810 trace: None,
811 truncation: None,
812 user: None,
813 extra: JsonObject::new(),
814 }
815 }
816
817 pub fn stream(mut self, value: bool) -> Self {
818 self.stream = Some(value);
819 self
820 }
821
822 pub fn with_field(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
823 self.extra.insert(key.into(), value.into());
824 self
825 }
826}
827
828#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
829pub struct ResponsesResponse {
830 #[serde(default)]
831 pub id: Option<String>,
832 #[serde(default)]
833 pub object: Option<String>,
834 #[serde(default)]
835 pub status: Option<String>,
836 #[serde(default)]
837 pub model: Option<String>,
838 #[serde(default)]
839 pub output: Option<Value>,
840 #[serde(default)]
841 pub output_text: Option<String>,
842 #[serde(default)]
843 pub usage: Option<Usage>,
844 #[serde(default, flatten)]
845 pub extra: JsonObject,
846}
847
848#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
849pub struct StreamedResponsesEvent {
850 #[serde(default, rename = "type")]
851 pub type_: Option<String>,
852 #[serde(default)]
853 pub response: Option<ResponsesResponse>,
854 #[serde(default)]
855 pub item: Option<Value>,
856 #[serde(default)]
857 pub delta: Option<Value>,
858 #[serde(default, flatten)]
859 pub extra: JsonObject,
860}
861
862#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
863pub struct MessagesRequest {
864 #[serde(skip_serializing_if = "Option::is_none")]
865 pub cache_control: Option<Value>,
866 #[serde(skip_serializing_if = "Option::is_none")]
867 pub context_management: Option<Value>,
868 #[serde(skip_serializing_if = "Option::is_none")]
869 pub fallbacks: Option<Value>,
870 #[serde(skip_serializing_if = "Option::is_none")]
871 pub model: Option<String>,
872 #[serde(skip_serializing_if = "Option::is_none")]
873 pub models: Option<Vec<String>>,
874 pub messages: Vec<ChatMessage>,
875 #[serde(skip_serializing_if = "Option::is_none")]
876 pub metadata: Option<JsonObject>,
877 #[serde(skip_serializing_if = "Option::is_none")]
878 pub max_tokens: Option<u32>,
879 #[serde(skip_serializing_if = "Option::is_none")]
880 pub output_config: Option<Value>,
881 #[serde(skip_serializing_if = "Option::is_none")]
882 pub plugins: Option<Value>,
883 #[serde(skip_serializing_if = "Option::is_none")]
884 pub system: Option<Value>,
885 #[serde(skip_serializing_if = "Option::is_none")]
886 pub temperature: Option<f64>,
887 #[serde(skip_serializing_if = "Option::is_none")]
888 pub tools: Option<Value>,
889 #[serde(skip_serializing_if = "Option::is_none")]
890 pub tool_choice: Option<Value>,
891 #[serde(skip_serializing_if = "Option::is_none")]
892 pub thinking: Option<Value>,
893 #[serde(skip_serializing_if = "Option::is_none")]
894 pub provider: Option<ProviderPreferences>,
895 #[serde(skip_serializing_if = "Option::is_none")]
896 pub route: Option<Value>,
897 #[serde(skip_serializing_if = "Option::is_none")]
898 pub service_tier: Option<ServiceTier>,
899 #[serde(skip_serializing_if = "Option::is_none")]
900 pub session_id: Option<String>,
901 #[serde(skip_serializing_if = "Option::is_none")]
902 pub speed: Option<f64>,
903 #[serde(skip_serializing_if = "Option::is_none")]
904 pub stop_sequences: Option<Vec<String>>,
905 #[serde(skip_serializing_if = "Option::is_none")]
906 pub stop_server_tools_when: Option<Value>,
907 #[serde(skip_serializing_if = "Option::is_none")]
908 pub stream: Option<bool>,
909 #[serde(skip_serializing_if = "Option::is_none")]
910 pub top_k: Option<u32>,
911 #[serde(skip_serializing_if = "Option::is_none")]
912 pub top_p: Option<f64>,
913 #[serde(skip_serializing_if = "Option::is_none")]
914 pub trace: Option<Value>,
915 #[serde(skip_serializing_if = "Option::is_none")]
916 pub user: Option<String>,
917 #[serde(default, flatten)]
918 pub extra: JsonObject,
919}
920
921impl MessagesRequest {
922 pub fn new(model: impl Into<String>, messages: Vec<ChatMessage>) -> Self {
923 Self::from_model_fields(Some(model.into()), None, messages)
924 }
925
926 pub fn new_with_models(
927 models: impl IntoIterator<Item = impl Into<String>>,
928 messages: Vec<ChatMessage>,
929 ) -> Self {
930 Self::from_model_fields(
931 None,
932 Some(models.into_iter().map(Into::into).collect()),
933 messages,
934 )
935 }
936
937 fn from_model_fields(
938 model: Option<String>,
939 models: Option<Vec<String>>,
940 messages: Vec<ChatMessage>,
941 ) -> Self {
942 Self {
943 cache_control: None,
944 context_management: None,
945 fallbacks: None,
946 model,
947 models,
948 messages,
949 metadata: None,
950 max_tokens: None,
951 output_config: None,
952 plugins: None,
953 system: None,
954 temperature: None,
955 tools: None,
956 tool_choice: None,
957 thinking: None,
958 provider: None,
959 route: None,
960 service_tier: None,
961 session_id: None,
962 speed: None,
963 stop_sequences: None,
964 stop_server_tools_when: None,
965 stream: None,
966 top_k: None,
967 top_p: None,
968 trace: None,
969 user: None,
970 extra: JsonObject::new(),
971 }
972 }
973
974 pub fn max_tokens(mut self, value: u32) -> Self {
975 self.max_tokens = Some(value);
976 self
977 }
978
979 pub fn stream(mut self, value: bool) -> Self {
980 self.stream = Some(value);
981 self
982 }
983
984 pub fn with_field(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
985 self.extra.insert(key.into(), value.into());
986 self
987 }
988}
989
990#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
991pub struct MessagesResponse {
992 #[serde(default)]
993 pub id: Option<String>,
994 #[serde(default, rename = "type")]
995 pub type_: Option<String>,
996 #[serde(default)]
997 pub role: Option<String>,
998 #[serde(default)]
999 pub content: Option<Value>,
1000 #[serde(default)]
1001 pub model: Option<String>,
1002 #[serde(default)]
1003 pub stop_reason: Option<String>,
1004 #[serde(default)]
1005 pub usage: Option<Usage>,
1006 #[serde(default, flatten)]
1007 pub extra: JsonObject,
1008}
1009
1010pub type MessagesStreamEvent = MessagesResponse;
1011
1012#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1013pub struct EmbeddingsRequest {
1014 pub model: String,
1015 pub input: Value,
1016 #[serde(skip_serializing_if = "Option::is_none")]
1017 pub dimensions: Option<u32>,
1018 #[serde(skip_serializing_if = "Option::is_none")]
1019 pub encoding_format: Option<String>,
1020 #[serde(skip_serializing_if = "Option::is_none")]
1021 pub input_type: Option<String>,
1022 #[serde(skip_serializing_if = "Option::is_none")]
1023 pub provider: Option<ProviderPreferences>,
1024 #[serde(skip_serializing_if = "Option::is_none")]
1025 pub user: Option<String>,
1026 #[serde(default, flatten)]
1027 pub extra: JsonObject,
1028}
1029
1030impl EmbeddingsRequest {
1031 pub fn new(model: impl Into<String>, input: impl Into<Value>) -> Self {
1032 Self {
1033 model: model.into(),
1034 input: input.into(),
1035 dimensions: None,
1036 encoding_format: None,
1037 input_type: None,
1038 provider: None,
1039 user: None,
1040 extra: JsonObject::new(),
1041 }
1042 }
1043}
1044
1045json_object_type!(EmbeddingsResponse);
1046json_object_type!(EmbeddingModelsResponse);
1047
1048#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1049#[serde(untagged)]
1050pub enum RerankDocument {
1051 Text(String),
1052 Object(Value),
1053}
1054
1055impl From<String> for RerankDocument {
1056 fn from(value: String) -> Self {
1057 Self::Text(value)
1058 }
1059}
1060
1061impl From<&str> for RerankDocument {
1062 fn from(value: &str) -> Self {
1063 Self::Text(value.to_owned())
1064 }
1065}
1066
1067#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1068pub struct RerankRequest {
1069 pub model: String,
1070 pub query: String,
1071 pub documents: Vec<RerankDocument>,
1072 #[serde(skip_serializing_if = "Option::is_none")]
1073 pub provider: Option<ProviderPreferences>,
1074 #[serde(skip_serializing_if = "Option::is_none")]
1075 pub top_n: Option<u32>,
1076 #[serde(default, flatten)]
1077 pub extra: JsonObject,
1078}
1079
1080impl RerankRequest {
1081 pub fn new(
1082 model: impl Into<String>,
1083 query: impl Into<String>,
1084 documents: impl IntoIterator<Item = impl Into<RerankDocument>>,
1085 ) -> Self {
1086 Self {
1087 model: model.into(),
1088 query: query.into(),
1089 documents: documents.into_iter().map(Into::into).collect(),
1090 provider: None,
1091 top_n: None,
1092 extra: JsonObject::new(),
1093 }
1094 }
1095}
1096
1097json_object_type!(RerankResponse);
1098
1099#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1100pub struct SpeechRequest {
1101 pub model: String,
1102 pub input: String,
1103 pub voice: String,
1104 #[serde(skip_serializing_if = "Option::is_none")]
1105 pub response_format: Option<String>,
1106 #[serde(skip_serializing_if = "Option::is_none")]
1107 pub speed: Option<f64>,
1108 #[serde(default, flatten)]
1109 pub extra: JsonObject,
1110}
1111
1112impl SpeechRequest {
1113 pub fn new(
1114 model: impl Into<String>,
1115 input: impl Into<String>,
1116 voice: impl Into<String>,
1117 ) -> Self {
1118 Self {
1119 model: model.into(),
1120 input: input.into(),
1121 voice: voice.into(),
1122 response_format: None,
1123 speed: None,
1124 extra: JsonObject::new(),
1125 }
1126 }
1127}
1128
1129#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1130pub struct TranscriptionRequest {
1131 pub model: String,
1132 pub input_audio: Value,
1133 #[serde(skip_serializing_if = "Option::is_none")]
1134 pub language: Option<String>,
1135 #[serde(skip_serializing_if = "Option::is_none")]
1136 pub provider: Option<ProviderPreferences>,
1137 #[serde(skip_serializing_if = "Option::is_none")]
1138 pub temperature: Option<f64>,
1139 #[serde(default, flatten)]
1140 pub extra: JsonObject,
1141}
1142
1143impl TranscriptionRequest {
1144 pub fn new(model: impl Into<String>, input_audio: impl Into<Value>) -> Self {
1145 Self {
1146 model: model.into(),
1147 input_audio: input_audio.into(),
1148 language: None,
1149 provider: None,
1150 temperature: None,
1151 extra: JsonObject::new(),
1152 }
1153 }
1154}
1155
1156#[derive(Debug, Clone, PartialEq)]
1157pub struct TranscriptionFileRequest {
1158 pub model: String,
1159 pub bytes: Bytes,
1160 pub file_name: Option<String>,
1161 pub content_type: Option<String>,
1162 pub language: Option<String>,
1163 pub response_format: Option<String>,
1164 pub temperature: Option<f64>,
1165}
1166
1167impl TranscriptionFileRequest {
1168 pub fn new(model: impl Into<String>, bytes: impl Into<Bytes>) -> Self {
1169 Self {
1170 model: model.into(),
1171 bytes: bytes.into(),
1172 file_name: None,
1173 content_type: None,
1174 language: None,
1175 response_format: None,
1176 temperature: None,
1177 }
1178 }
1179
1180 pub fn with_file_name(mut self, value: impl Into<String>) -> Self {
1181 self.file_name = Some(value.into());
1182 self
1183 }
1184
1185 pub fn with_content_type(mut self, value: impl Into<String>) -> Self {
1186 self.content_type = Some(value.into());
1187 self
1188 }
1189}
1190
1191json_object_type!(TranscriptionResponse);
1192
1193#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1194pub struct ImageGenerationRequest {
1195 pub model: String,
1196 #[serde(skip_serializing_if = "Option::is_none")]
1197 pub prompt: Option<String>,
1198 #[serde(skip_serializing_if = "Option::is_none")]
1199 pub aspect_ratio: Option<String>,
1200 #[serde(skip_serializing_if = "Option::is_none")]
1201 pub background: Option<String>,
1202 #[serde(skip_serializing_if = "Option::is_none")]
1203 pub input_references: Option<Value>,
1204 #[serde(skip_serializing_if = "Option::is_none")]
1205 pub n: Option<u32>,
1206 #[serde(skip_serializing_if = "Option::is_none")]
1207 pub output_compression: Option<u32>,
1208 #[serde(skip_serializing_if = "Option::is_none")]
1209 pub output_format: Option<String>,
1210 #[serde(skip_serializing_if = "Option::is_none")]
1211 pub provider: Option<ProviderPreferences>,
1212 #[serde(skip_serializing_if = "Option::is_none")]
1213 pub quality: Option<String>,
1214 #[serde(skip_serializing_if = "Option::is_none")]
1215 pub resolution: Option<String>,
1216 #[serde(skip_serializing_if = "Option::is_none")]
1217 pub seed: Option<i64>,
1218 #[serde(skip_serializing_if = "Option::is_none")]
1219 pub size: Option<String>,
1220 #[serde(skip_serializing_if = "Option::is_none")]
1221 pub stream: Option<bool>,
1222 #[serde(default, flatten)]
1223 pub extra: JsonObject,
1224}
1225
1226impl ImageGenerationRequest {
1227 pub fn new(model: impl Into<String>) -> Self {
1228 Self {
1229 model: model.into(),
1230 prompt: None,
1231 aspect_ratio: None,
1232 background: None,
1233 input_references: None,
1234 n: None,
1235 output_compression: None,
1236 output_format: None,
1237 provider: None,
1238 quality: None,
1239 resolution: None,
1240 seed: None,
1241 size: None,
1242 stream: None,
1243 extra: JsonObject::new(),
1244 }
1245 }
1246
1247 pub fn prompt(mut self, prompt: impl Into<String>) -> Self {
1248 self.prompt = Some(prompt.into());
1249 self
1250 }
1251}
1252
1253json_object_type!(ImageGenerationResponse);
1254json_object_type!(ImageModelsResponse);
1255json_object_type!(ImageModelEndpointsResponse);
1256
1257#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1258pub struct VideoGenerationRequest {
1259 pub model: String,
1260 #[serde(skip_serializing_if = "Option::is_none")]
1261 pub prompt: Option<String>,
1262 #[serde(skip_serializing_if = "Option::is_none")]
1263 pub aspect_ratio: Option<String>,
1264 #[serde(skip_serializing_if = "Option::is_none")]
1265 pub callback_url: Option<String>,
1266 #[serde(skip_serializing_if = "Option::is_none")]
1267 pub duration: Option<f64>,
1268 #[serde(skip_serializing_if = "Option::is_none")]
1269 pub frame_images: Option<Value>,
1270 #[serde(skip_serializing_if = "Option::is_none")]
1271 pub generate_audio: Option<bool>,
1272 #[serde(skip_serializing_if = "Option::is_none")]
1273 pub input_references: Option<Value>,
1274 #[serde(skip_serializing_if = "Option::is_none")]
1275 pub provider: Option<ProviderPreferences>,
1276 #[serde(skip_serializing_if = "Option::is_none")]
1277 pub resolution: Option<String>,
1278 #[serde(skip_serializing_if = "Option::is_none")]
1279 pub seed: Option<i64>,
1280 #[serde(skip_serializing_if = "Option::is_none")]
1281 pub size: Option<String>,
1282 #[serde(default, flatten)]
1283 pub extra: JsonObject,
1284}
1285
1286impl VideoGenerationRequest {
1287 pub fn new(model: impl Into<String>) -> Self {
1288 Self {
1289 model: model.into(),
1290 prompt: None,
1291 aspect_ratio: None,
1292 callback_url: None,
1293 duration: None,
1294 frame_images: None,
1295 generate_audio: None,
1296 input_references: None,
1297 provider: None,
1298 resolution: None,
1299 seed: None,
1300 size: None,
1301 extra: JsonObject::new(),
1302 }
1303 }
1304
1305 pub fn prompt(mut self, prompt: impl Into<String>) -> Self {
1306 self.prompt = Some(prompt.into());
1307 self
1308 }
1309}
1310
1311json_object_type!(VideoGenerationResponse);
1312json_object_type!(VideoStatusResponse);
1313json_object_type!(VideoModelsResponse);
1314
1315#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1316pub struct BinaryResponse {
1317 #[serde(skip)]
1318 pub bytes: Bytes,
1319 pub content_type: Option<String>,
1320 pub content_disposition: Option<String>,
1321}
1322
1323#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1324pub struct FileUploadRequest {
1325 #[serde(skip)]
1326 pub bytes: Bytes,
1327 pub file_name: Option<String>,
1328 pub content_type: Option<String>,
1329}
1330
1331impl FileUploadRequest {
1332 pub fn new(bytes: impl Into<Bytes>) -> Self {
1333 Self {
1334 bytes: bytes.into(),
1335 file_name: None,
1336 content_type: None,
1337 }
1338 }
1339
1340 pub fn with_file_name(mut self, value: impl Into<String>) -> Self {
1341 self.file_name = Some(value.into());
1342 self
1343 }
1344
1345 pub fn with_content_type(mut self, value: impl Into<String>) -> Self {
1346 self.content_type = Some(value.into());
1347 self
1348 }
1349}
1350
1351json_object_type!(FileListResponse);
1352json_object_type!(FileMetadataResponse);
1353json_object_type!(FileDeleteResponse);
1354json_object_type!(FileUploadResponse);
1355
1356#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1357pub struct GenerationResponse {
1358 #[serde(default)]
1359 pub data: Option<GenerationData>,
1360 #[serde(default, flatten)]
1361 pub extra: JsonObject,
1362}
1363
1364#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1365pub struct GenerationData {
1366 #[serde(default)]
1367 pub id: Option<String>,
1368 #[serde(default)]
1369 pub model: Option<String>,
1370 #[serde(default)]
1371 pub total_cost: Option<f64>,
1372 #[serde(default)]
1373 pub usage: Option<f64>,
1374 #[serde(default)]
1375 pub provider_name: Option<String>,
1376 #[serde(default)]
1377 pub latency: Option<f64>,
1378 #[serde(default)]
1379 pub tokens_prompt: Option<i64>,
1380 #[serde(default)]
1381 pub tokens_completion: Option<i64>,
1382 #[serde(default)]
1383 pub finish_reason: Option<String>,
1384 #[serde(default, flatten)]
1385 pub extra: JsonObject,
1386}
1387
1388impl GenerationResponse {
1389 pub fn total_cost(&self) -> Option<f64> {
1390 self.data.as_ref().and_then(|data| data.total_cost)
1391 }
1392}
1393
1394json_object_type!(GenerationContentResponse);
1395
1396#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1397pub struct DataResponse<T> {
1398 #[serde(default)]
1399 pub data: Option<T>,
1400 #[serde(default, flatten)]
1401 pub extra: JsonObject,
1402}
1403
1404#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1405pub struct ListResponse<T> {
1406 #[serde(default)]
1407 pub data: Vec<T>,
1408 #[serde(default)]
1409 pub total_count: Option<i64>,
1410 #[serde(default, flatten)]
1411 pub extra: JsonObject,
1412}
1413
1414#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1415pub struct DeleteResponse {
1416 #[serde(default)]
1417 pub deleted: Option<bool>,
1418 #[serde(default, flatten)]
1419 pub extra: JsonObject,
1420}
1421
1422#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1423pub struct ActivityResponse {
1424 #[serde(default)]
1425 pub data: Vec<ActivityItem>,
1426 #[serde(default, flatten)]
1427 pub extra: JsonObject,
1428}
1429
1430#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1431pub struct ActivityItem {
1432 #[serde(default)]
1433 pub date: Option<String>,
1434 #[serde(default)]
1435 pub model: Option<String>,
1436 #[serde(default)]
1437 pub provider_name: Option<String>,
1438 #[serde(default)]
1439 pub usage: Option<f64>,
1440 #[serde(default)]
1441 pub tokens_prompt: Option<i64>,
1442 #[serde(default)]
1443 pub tokens_completion: Option<i64>,
1444 #[serde(default)]
1445 pub requests: Option<i64>,
1446 #[serde(default, flatten)]
1447 pub extra: JsonObject,
1448}
1449
1450#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1451pub struct AnalyticsMetaResponse {
1452 #[serde(default)]
1453 pub data: Option<AnalyticsMetaData>,
1454 #[serde(default, flatten)]
1455 pub extra: JsonObject,
1456}
1457
1458#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1459pub struct AnalyticsMetaData {
1460 #[serde(default)]
1461 pub metrics: Option<Value>,
1462 #[serde(default)]
1463 pub dimensions: Option<Value>,
1464 #[serde(default)]
1465 pub operators: Option<Value>,
1466 #[serde(default)]
1467 pub granularities: Option<Value>,
1468 #[serde(default, flatten)]
1469 pub extra: JsonObject,
1470}
1471
1472#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1473pub struct AnalyticsQueryRequest {
1474 #[serde(skip_serializing_if = "Option::is_none")]
1475 pub metrics: Option<Vec<String>>,
1476 #[serde(skip_serializing_if = "Option::is_none")]
1477 pub dimensions: Option<Vec<String>>,
1478 #[serde(skip_serializing_if = "Option::is_none")]
1479 pub filters: Option<Value>,
1480 #[serde(skip_serializing_if = "Option::is_none")]
1481 pub granularity: Option<String>,
1482 #[serde(skip_serializing_if = "Option::is_none")]
1483 pub time_range: Option<Value>,
1484 #[serde(skip_serializing_if = "Option::is_none")]
1485 pub order_by: Option<Value>,
1486 #[serde(skip_serializing_if = "Option::is_none")]
1487 pub limit: Option<u32>,
1488 #[serde(skip_serializing_if = "Option::is_none")]
1489 pub group_limit: Option<u32>,
1490 #[serde(default, flatten)]
1491 pub extra: JsonObject,
1492}
1493
1494impl AnalyticsQueryRequest {
1495 pub fn new() -> Self {
1496 Self::default()
1497 }
1498
1499 pub fn with_field(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
1500 self.extra.insert(key.into(), value.into());
1501 self
1502 }
1503}
1504
1505#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1506pub struct AnalyticsQueryResponse {
1507 #[serde(default)]
1508 pub data: Option<AnalyticsQueryData>,
1509 #[serde(default, flatten)]
1510 pub extra: JsonObject,
1511}
1512
1513#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1514pub struct AnalyticsQueryData {
1515 #[serde(default)]
1516 pub data: Option<Value>,
1517 #[serde(default)]
1518 pub metadata: Option<Value>,
1519 #[serde(default)]
1520 pub warnings: Option<Value>,
1521 #[serde(default, rename = "cachedAt")]
1522 pub cached_at: Option<String>,
1523 #[serde(default, flatten)]
1524 pub extra: JsonObject,
1525}
1526json_object_type!(AuthKeyExchangeRequest);
1527json_object_type!(AuthKeyExchangeResponse);
1528json_object_type!(AuthKeyCodeRequest);
1529json_object_type!(AuthKeyCodeResponse);
1530json_object_type!(BenchmarksResponse);
1531json_object_type!(TaskClassificationResponse);
1532#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1533pub struct CreditsResponse {
1534 #[serde(default)]
1535 pub data: Option<CreditsData>,
1536 #[serde(default, flatten)]
1537 pub extra: JsonObject,
1538}
1539
1540#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1541pub struct CreditsData {
1542 #[serde(default)]
1543 pub total_credits: Option<f64>,
1544 #[serde(default)]
1545 pub total_usage: Option<f64>,
1546 #[serde(default, flatten)]
1547 pub extra: JsonObject,
1548}
1549json_object_type!(AppRankingsResponse);
1550json_object_type!(RankingsDailyResponse);
1551json_object_type!(EndpointsZdrResponse);
1552pub type CurrentKeyResponse = DataResponse<KeyData>;
1553pub type KeyListResponse = ListResponse<KeyData>;
1554pub type KeyResponse = DataResponse<KeyData>;
1555pub type KeyDeleteResponse = DeleteResponse;
1556
1557#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1558pub struct KeyCreateRequest {
1559 #[serde(skip_serializing_if = "Option::is_none")]
1560 pub name: Option<String>,
1561 #[serde(skip_serializing_if = "Option::is_none")]
1562 pub limit: Option<f64>,
1563 #[serde(skip_serializing_if = "Option::is_none")]
1564 pub limit_reset: Option<String>,
1565 #[serde(skip_serializing_if = "Option::is_none")]
1566 pub include_byok_in_limit: Option<bool>,
1567 #[serde(skip_serializing_if = "Option::is_none")]
1568 pub expires_at: Option<String>,
1569 #[serde(skip_serializing_if = "Option::is_none")]
1570 pub creator_user_id: Option<String>,
1571 #[serde(skip_serializing_if = "Option::is_none")]
1572 pub workspace_id: Option<String>,
1573 #[serde(default, flatten)]
1574 pub extra: JsonObject,
1575}
1576
1577#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1578pub struct KeyUpdateRequest {
1579 #[serde(skip_serializing_if = "Option::is_none")]
1580 pub name: Option<String>,
1581 #[serde(skip_serializing_if = "Option::is_none")]
1582 pub limit: Option<f64>,
1583 #[serde(skip_serializing_if = "Option::is_none")]
1584 pub limit_reset: Option<String>,
1585 #[serde(skip_serializing_if = "Option::is_none")]
1586 pub include_byok_in_limit: Option<bool>,
1587 #[serde(skip_serializing_if = "Option::is_none")]
1588 pub expires_at: Option<String>,
1589 #[serde(skip_serializing_if = "Option::is_none")]
1590 pub disabled: Option<bool>,
1591 #[serde(default, flatten)]
1592 pub extra: JsonObject,
1593}
1594
1595#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1596pub struct KeyCreateResponse {
1597 #[serde(default)]
1598 pub data: Option<KeyData>,
1599 #[serde(default)]
1600 pub key: Option<String>,
1601 #[serde(default, flatten)]
1602 pub extra: JsonObject,
1603}
1604
1605pub type KeyUpdateResponse = DataResponse<KeyData>;
1606
1607#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1608pub struct KeyData {
1609 #[serde(default)]
1610 pub hash: Option<String>,
1611 #[serde(default)]
1612 pub name: Option<String>,
1613 #[serde(default)]
1614 pub label: Option<String>,
1615 #[serde(default)]
1616 pub disabled: Option<bool>,
1617 #[serde(default)]
1618 pub limit: Option<f64>,
1619 #[serde(default)]
1620 pub limit_reset: Option<String>,
1621 #[serde(default)]
1622 pub include_byok_in_limit: Option<bool>,
1623 #[serde(default)]
1624 pub usage: Option<f64>,
1625 #[serde(default)]
1626 pub usage_limit: Option<f64>,
1627 #[serde(default)]
1628 pub byok_usage: Option<f64>,
1629 #[serde(default)]
1630 pub byok_usage_limit: Option<f64>,
1631 #[serde(default)]
1632 pub created_at: Option<String>,
1633 #[serde(default)]
1634 pub updated_at: Option<String>,
1635 #[serde(default)]
1636 pub creator_user_id: Option<String>,
1637 #[serde(default)]
1638 pub workspace_id: Option<String>,
1639 #[serde(default)]
1640 pub expires_at: Option<String>,
1641 #[serde(default, flatten)]
1642 pub extra: JsonObject,
1643}
1644json_object_type!(ModelListResponse);
1645json_object_type!(ModelResponse);
1646json_object_type!(ModelEndpointsResponse);
1647json_object_type!(ModelCountResponse);
1648json_object_type!(UserModelsResponse);
1649json_object_type!(ProviderListResponse);
1650pub type ByokListResponse = ListResponse<ByokKey>;
1651pub type ByokCreateResponse = DataResponse<ByokKey>;
1652pub type ByokResponse = DataResponse<ByokKey>;
1653pub type ByokUpdateResponse = DataResponse<ByokKey>;
1654pub type ByokDeleteResponse = DeleteResponse;
1655
1656#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1657pub struct ByokCreateRequest {
1658 #[serde(skip_serializing_if = "Option::is_none")]
1659 pub provider: Option<String>,
1660 #[serde(skip_serializing_if = "Option::is_none")]
1661 pub key: Option<String>,
1662 #[serde(skip_serializing_if = "Option::is_none")]
1663 pub name: Option<String>,
1664 #[serde(skip_serializing_if = "Option::is_none")]
1665 pub workspace_id: Option<String>,
1666 #[serde(skip_serializing_if = "Option::is_none")]
1667 pub disabled: Option<bool>,
1668 #[serde(skip_serializing_if = "Option::is_none")]
1669 pub is_fallback: Option<bool>,
1670 #[serde(skip_serializing_if = "Option::is_none")]
1671 pub allowed_models: Option<Vec<String>>,
1672 #[serde(skip_serializing_if = "Option::is_none")]
1673 pub allowed_user_ids: Option<Vec<String>>,
1674 #[serde(default, flatten)]
1675 pub extra: JsonObject,
1676}
1677
1678pub type ByokUpdateRequest = ByokCreateRequest;
1679
1680#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1681pub struct ByokKey {
1682 #[serde(default)]
1683 pub id: Option<String>,
1684 #[serde(default)]
1685 pub provider: Option<String>,
1686 #[serde(default)]
1687 pub workspace_id: Option<String>,
1688 #[serde(default)]
1689 pub label: Option<String>,
1690 #[serde(default)]
1691 pub name: Option<String>,
1692 #[serde(default)]
1693 pub disabled: Option<bool>,
1694 #[serde(default)]
1695 pub is_fallback: Option<bool>,
1696 #[serde(default)]
1697 pub allowed_models: Option<Vec<String>>,
1698 #[serde(default)]
1699 pub allowed_api_key_hashes: Option<Vec<String>>,
1700 #[serde(default)]
1701 pub allowed_user_ids: Option<Vec<String>>,
1702 #[serde(default)]
1703 pub sort_order: Option<i64>,
1704 #[serde(default)]
1705 pub created_at: Option<String>,
1706 #[serde(default, flatten)]
1707 pub extra: JsonObject,
1708}
1709
1710pub type GuardrailListResponse = ListResponse<Guardrail>;
1711pub type GuardrailCreateResponse = DataResponse<Guardrail>;
1712pub type GuardrailResponse = DataResponse<Guardrail>;
1713pub type GuardrailUpdateResponse = DataResponse<Guardrail>;
1714pub type GuardrailDeleteResponse = DeleteResponse;
1715
1716#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1717pub struct GuardrailCreateRequest {
1718 #[serde(flatten)]
1719 pub fields: GuardrailFields,
1720}
1721
1722pub type GuardrailUpdateRequest = GuardrailCreateRequest;
1723
1724#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1725pub struct GuardrailFields {
1726 #[serde(skip_serializing_if = "Option::is_none")]
1727 pub name: Option<String>,
1728 #[serde(skip_serializing_if = "Option::is_none")]
1729 pub description: Option<String>,
1730 #[serde(skip_serializing_if = "Option::is_none")]
1731 pub workspace_id: Option<String>,
1732 #[serde(skip_serializing_if = "Option::is_none")]
1733 pub limit_usd: Option<f64>,
1734 #[serde(skip_serializing_if = "Option::is_none")]
1735 pub reset_interval: Option<String>,
1736 #[serde(skip_serializing_if = "Option::is_none")]
1737 pub allowed_models: Option<Vec<String>>,
1738 #[serde(skip_serializing_if = "Option::is_none")]
1739 pub ignored_models: Option<Vec<String>>,
1740 #[serde(skip_serializing_if = "Option::is_none")]
1741 pub allowed_providers: Option<Vec<String>>,
1742 #[serde(skip_serializing_if = "Option::is_none")]
1743 pub ignored_providers: Option<Vec<String>>,
1744 #[serde(skip_serializing_if = "Option::is_none")]
1745 pub content_filters: Option<Value>,
1746 #[serde(skip_serializing_if = "Option::is_none")]
1747 pub content_filter_builtins: Option<Value>,
1748 #[serde(skip_serializing_if = "Option::is_none")]
1749 pub enforce_zdr: Option<bool>,
1750 #[serde(skip_serializing_if = "Option::is_none")]
1751 pub enforce_zdr_models: Option<Vec<String>>,
1752 #[serde(default, flatten)]
1753 pub extra: JsonObject,
1754}
1755
1756#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1757pub struct Guardrail {
1758 #[serde(default)]
1759 pub id: Option<String>,
1760 #[serde(flatten)]
1761 pub fields: GuardrailFields,
1762 #[serde(default)]
1763 pub created_at: Option<String>,
1764 #[serde(default)]
1765 pub updated_at: Option<String>,
1766}
1767
1768pub type KeyAssignmentsResponse = ListResponse<KeyAssignment>;
1769pub type MemberAssignmentsResponse = ListResponse<MemberAssignment>;
1770
1771#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1772pub struct KeyAssignment {
1773 #[serde(default)]
1774 pub key_hash: Option<String>,
1775 #[serde(default)]
1776 pub guardrail_id: Option<String>,
1777 #[serde(default, flatten)]
1778 pub extra: JsonObject,
1779}
1780
1781#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1782pub struct MemberAssignment {
1783 #[serde(default)]
1784 pub member_user_id: Option<String>,
1785 #[serde(default)]
1786 pub guardrail_id: Option<String>,
1787 #[serde(default, flatten)]
1788 pub extra: JsonObject,
1789}
1790
1791#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1792pub struct BulkAssignKeysRequest {
1793 #[serde(default)]
1794 pub key_hashes: Vec<String>,
1795 #[serde(default, flatten)]
1796 pub extra: JsonObject,
1797}
1798
1799pub type BulkUnassignKeysRequest = BulkAssignKeysRequest;
1800
1801#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1802pub struct BulkAssignMembersRequest {
1803 #[serde(default)]
1804 pub member_user_ids: Vec<String>,
1805 #[serde(default, flatten)]
1806 pub extra: JsonObject,
1807}
1808
1809pub type BulkUnassignMembersRequest = BulkAssignMembersRequest;
1810
1811#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1812pub struct AssignmentCountResponse {
1813 #[serde(default)]
1814 pub assigned_count: Option<i64>,
1815 #[serde(default)]
1816 pub unassigned_count: Option<i64>,
1817 #[serde(default, flatten)]
1818 pub extra: JsonObject,
1819}
1820
1821pub type BulkAssignKeysResponse = AssignmentCountResponse;
1822pub type BulkUnassignKeysResponse = AssignmentCountResponse;
1823pub type BulkAssignMembersResponse = AssignmentCountResponse;
1824pub type BulkUnassignMembersResponse = AssignmentCountResponse;
1825
1826pub type ObservabilityDestinationListResponse = ListResponse<ObservabilityDestination>;
1827pub type ObservabilityDestinationCreateResponse = DataResponse<ObservabilityDestination>;
1828pub type ObservabilityDestinationResponse = DataResponse<ObservabilityDestination>;
1829pub type ObservabilityDestinationUpdateResponse = DataResponse<ObservabilityDestination>;
1830pub type ObservabilityDestinationDeleteResponse = DeleteResponse;
1831
1832#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1833pub struct ObservabilityDestinationCreateRequest {
1834 #[serde(flatten)]
1835 pub fields: ObservabilityDestinationFields,
1836}
1837
1838pub type ObservabilityDestinationUpdateRequest = ObservabilityDestinationCreateRequest;
1839
1840#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1841pub struct ObservabilityDestinationFields {
1842 #[serde(skip_serializing_if = "Option::is_none", rename = "type")]
1843 pub type_: Option<String>,
1844 #[serde(skip_serializing_if = "Option::is_none")]
1845 pub name: Option<String>,
1846 #[serde(skip_serializing_if = "Option::is_none")]
1847 pub config: Option<Value>,
1848 #[serde(skip_serializing_if = "Option::is_none")]
1849 pub workspace_id: Option<String>,
1850 #[serde(skip_serializing_if = "Option::is_none")]
1851 pub enabled: Option<bool>,
1852 #[serde(skip_serializing_if = "Option::is_none")]
1853 pub privacy_mode: Option<String>,
1854 #[serde(skip_serializing_if = "Option::is_none")]
1855 pub sampling_rate: Option<f64>,
1856 #[serde(skip_serializing_if = "Option::is_none")]
1857 pub api_key_hashes: Option<Vec<String>>,
1858 #[serde(skip_serializing_if = "Option::is_none")]
1859 pub filter_rules: Option<Value>,
1860 #[serde(default, flatten)]
1861 pub extra: JsonObject,
1862}
1863
1864#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1865pub struct ObservabilityDestination {
1866 #[serde(default)]
1867 pub id: Option<String>,
1868 #[serde(flatten)]
1869 pub fields: ObservabilityDestinationFields,
1870 #[serde(default)]
1871 pub created_at: Option<String>,
1872 #[serde(default)]
1873 pub updated_at: Option<String>,
1874}
1875
1876pub type OrganizationMembersResponse = ListResponse<OrganizationMember>;
1877
1878#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1879pub struct OrganizationMember {
1880 #[serde(default)]
1881 pub id: Option<String>,
1882 #[serde(default)]
1883 pub first_name: Option<String>,
1884 #[serde(default)]
1885 pub last_name: Option<String>,
1886 #[serde(default)]
1887 pub email: Option<String>,
1888 #[serde(default)]
1889 pub role: Option<String>,
1890 #[serde(default, flatten)]
1891 pub extra: JsonObject,
1892}
1893json_object_type!(PresetListResponse);
1894json_object_type!(PresetResponse);
1895json_object_type!(PresetCreateFromInferenceResponse);
1896json_object_type!(PresetVersionListResponse);
1897json_object_type!(PresetVersionResponse);
1898pub type WorkspaceListResponse = ListResponse<Workspace>;
1899pub type WorkspaceCreateResponse = DataResponse<Workspace>;
1900pub type WorkspaceResponse = DataResponse<Workspace>;
1901pub type WorkspaceUpdateResponse = DataResponse<Workspace>;
1902pub type WorkspaceDeleteResponse = DeleteResponse;
1903
1904#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1905pub struct WorkspaceCreateRequest {
1906 #[serde(flatten)]
1907 pub fields: WorkspaceFields,
1908}
1909
1910pub type WorkspaceUpdateRequest = WorkspaceCreateRequest;
1911
1912#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1913pub struct WorkspaceFields {
1914 #[serde(skip_serializing_if = "Option::is_none")]
1915 pub name: Option<String>,
1916 #[serde(skip_serializing_if = "Option::is_none")]
1917 pub slug: Option<String>,
1918 #[serde(skip_serializing_if = "Option::is_none")]
1919 pub description: Option<String>,
1920 #[serde(skip_serializing_if = "Option::is_none")]
1921 pub default_text_model: Option<String>,
1922 #[serde(skip_serializing_if = "Option::is_none")]
1923 pub default_image_model: Option<String>,
1924 #[serde(skip_serializing_if = "Option::is_none")]
1925 pub default_provider_sort: Option<Value>,
1926 #[serde(skip_serializing_if = "Option::is_none")]
1927 pub is_logging_enabled: Option<bool>,
1928 #[serde(skip_serializing_if = "Option::is_none")]
1929 pub is_observability_enabled: Option<bool>,
1930 #[serde(skip_serializing_if = "Option::is_none")]
1931 pub io_logging_enabled: Option<bool>,
1932 #[serde(skip_serializing_if = "Option::is_none")]
1933 pub io_logging_sampling_rate: Option<f64>,
1934 #[serde(skip_serializing_if = "Option::is_none")]
1935 pub io_logging_api_key_ids: Option<Vec<String>>,
1936 #[serde(default, flatten)]
1937 pub extra: JsonObject,
1938}
1939
1940#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1941pub struct Workspace {
1942 #[serde(default)]
1943 pub id: Option<String>,
1944 #[serde(flatten)]
1945 pub fields: WorkspaceFields,
1946 #[serde(default)]
1947 pub created_at: Option<String>,
1948 #[serde(default)]
1949 pub updated_at: Option<String>,
1950 #[serde(default)]
1951 pub created_by: Option<String>,
1952}
1953
1954pub type WorkspaceBudgetListResponse = ListResponse<WorkspaceBudget>;
1955pub type WorkspaceBudgetUpsertResponse = DataResponse<WorkspaceBudget>;
1956pub type WorkspaceBudgetDeleteResponse = DeleteResponse;
1957
1958#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1959pub struct WorkspaceBudgetUpsertRequest {
1960 #[serde(skip_serializing_if = "Option::is_none")]
1961 pub limit_usd: Option<f64>,
1962 #[serde(default, flatten)]
1963 pub extra: JsonObject,
1964}
1965
1966#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1967pub struct WorkspaceBudget {
1968 #[serde(default)]
1969 pub id: Option<String>,
1970 #[serde(default)]
1971 pub workspace_id: Option<String>,
1972 #[serde(default)]
1973 pub limit_usd: Option<f64>,
1974 #[serde(default)]
1975 pub reset_interval: Option<String>,
1976 #[serde(default)]
1977 pub created_at: Option<String>,
1978 #[serde(default)]
1979 pub updated_at: Option<String>,
1980 #[serde(default, flatten)]
1981 pub extra: JsonObject,
1982}
1983
1984pub type WorkspaceMemberListResponse = ListResponse<WorkspaceMember>;
1985
1986#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
1987pub struct WorkspaceMember {
1988 #[serde(default)]
1989 pub id: Option<String>,
1990 #[serde(default)]
1991 pub workspace_id: Option<String>,
1992 #[serde(default)]
1993 pub user_id: Option<String>,
1994 #[serde(default)]
1995 pub role: Option<String>,
1996 #[serde(default)]
1997 pub created_at: Option<String>,
1998 #[serde(default, flatten)]
1999 pub extra: JsonObject,
2000}
2001
2002#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
2003pub struct BulkAddWorkspaceMembersRequest {
2004 #[serde(default)]
2005 pub user_ids: Vec<String>,
2006 #[serde(default, flatten)]
2007 pub extra: JsonObject,
2008}
2009
2010pub type BulkRemoveWorkspaceMembersRequest = BulkAddWorkspaceMembersRequest;
2011
2012#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
2013pub struct BulkAddWorkspaceMembersResponse {
2014 #[serde(default)]
2015 pub data: Vec<WorkspaceMember>,
2016 #[serde(default)]
2017 pub added_count: Option<i64>,
2018 #[serde(default, flatten)]
2019 pub extra: JsonObject,
2020}
2021
2022#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
2023pub struct BulkRemoveWorkspaceMembersResponse {
2024 #[serde(default)]
2025 pub removed_count: Option<i64>,
2026 #[serde(default, flatten)]
2027 pub extra: JsonObject,
2028}
2029
2030#[cfg(test)]
2031mod tests {
2032 use super::{
2033 ChatCompletionRequest, ChatMessage, ChatRole, EmbeddingsRequest, ImageGenerationRequest,
2034 MessagesRequest, ProviderPreferences, RerankDocument, RerankRequest, ResponsesRequest,
2035 TranscriptionRequest, VideoGenerationRequest,
2036 };
2037 use serde_json::json;
2038
2039 #[test]
2040 fn unknown_enums_round_trip() {
2041 let role: ChatRole = serde_json::from_str("\"new_role\"").unwrap();
2042 assert_eq!(role.as_str(), "new_role");
2043 assert_eq!(serde_json::to_string(&role).unwrap(), "\"new_role\"");
2044 }
2045
2046 #[test]
2047 fn provider_preferences_serialize_stable_and_extra_fields() {
2048 let prefs = ProviderPreferences::new()
2049 .require_parameters(true)
2050 .only(["openai"])
2051 .with_field("custom", true);
2052 let value = serde_json::to_value(prefs).unwrap();
2053 assert_eq!(value["require_parameters"], true);
2054 assert_eq!(value["only"][0], "openai");
2055 assert_eq!(value["custom"], true);
2056 }
2057
2058 #[test]
2059 fn multi_model_request_constructors_serialize_models_without_model() {
2060 let chat = ChatCompletionRequest::new_with_models(
2061 ["openai/gpt-4o-mini", "anthropic/claude-haiku"],
2062 vec![ChatMessage::user("hi")],
2063 );
2064 let chat = serde_json::to_value(chat).unwrap();
2065 assert!(chat.get("model").is_none());
2066 assert_eq!(chat["models"][0], "openai/gpt-4o-mini");
2067
2068 let responses = ResponsesRequest::new_with_models(
2069 ["openai/gpt-4o-mini", "anthropic/claude-haiku"],
2070 "hi",
2071 );
2072 let responses = serde_json::to_value(responses).unwrap();
2073 assert!(responses.get("model").is_none());
2074 assert_eq!(responses["models"][1], "anthropic/claude-haiku");
2075
2076 let messages = MessagesRequest::new_with_models(
2077 ["anthropic/claude-sonnet", "anthropic/claude-haiku"],
2078 vec![ChatMessage::user("hi")],
2079 );
2080 let messages = serde_json::to_value(messages).unwrap();
2081 assert!(messages.get("model").is_none());
2082 assert_eq!(messages["models"][0], "anthropic/claude-sonnet");
2083 }
2084
2085 #[test]
2086 fn expanded_request_fields_serialize_with_openrouter_wire_names() {
2087 let mut chat =
2088 ChatCompletionRequest::new("openai/gpt-4o-mini", vec![ChatMessage::user("hello")]);
2089 chat.cache_control = Some(json!({"type": "ephemeral"}));
2090 chat.modalities = Some(vec!["text".to_owned(), "image".to_owned()]);
2091 chat.stop_server_tools_when = Some(json!("first_tool_call"));
2092 chat.top_a = Some(0.4);
2093 chat.trace = Some(json!({"enabled": true}));
2094 let chat = serde_json::to_value(chat).unwrap();
2095 assert_eq!(chat["cache_control"]["type"], "ephemeral");
2096 assert_eq!(chat["modalities"][1], "image");
2097 assert_eq!(chat["stop_server_tools_when"], "first_tool_call");
2098 assert_eq!(chat["top_a"], 0.4);
2099 assert_eq!(chat["trace"]["enabled"], true);
2100
2101 let mut responses = ResponsesRequest::new("openai/gpt-4o-mini", "hello");
2102 responses.background = Some(true);
2103 responses.max_tool_calls = Some(3);
2104 responses.prompt_cache_key = Some("cache-key".to_owned());
2105 responses.safety_identifier = Some("user-1".to_owned());
2106 responses.truncation = Some("auto".to_owned());
2107 let responses = serde_json::to_value(responses).unwrap();
2108 assert_eq!(responses["background"], true);
2109 assert_eq!(responses["max_tool_calls"], 3);
2110 assert_eq!(responses["prompt_cache_key"], "cache-key");
2111 assert_eq!(responses["safety_identifier"], "user-1");
2112 assert_eq!(responses["truncation"], "auto");
2113
2114 let mut messages =
2115 MessagesRequest::new("anthropic/claude-haiku", vec![ChatMessage::user("hello")]);
2116 messages.context_management = Some(json!({"clear_function_results": true}));
2117 messages.stop_sequences = Some(vec!["END".to_owned()]);
2118 messages.speed = Some(1.1);
2119 messages.top_p = Some(0.9);
2120 let messages = serde_json::to_value(messages).unwrap();
2121 assert_eq!(
2122 messages["context_management"]["clear_function_results"],
2123 true
2124 );
2125 assert_eq!(messages["stop_sequences"][0], "END");
2126 assert_eq!(messages["speed"], 1.1);
2127 assert_eq!(messages["top_p"], 0.9);
2128
2129 let mut image = ImageGenerationRequest::new("openai/gpt-image-1").prompt("a chair");
2130 image.aspect_ratio = Some("1:1".to_owned());
2131 image.n = Some(2);
2132 image.output_format = Some("png".to_owned());
2133 image.stream = Some(true);
2134 let image = serde_json::to_value(image).unwrap();
2135 assert_eq!(image["aspect_ratio"], "1:1");
2136 assert_eq!(image["n"], 2);
2137 assert_eq!(image["output_format"], "png");
2138 assert_eq!(image["stream"], true);
2139
2140 let mut video = VideoGenerationRequest::new("provider/video").prompt("waves");
2141 video.callback_url = Some("https://example.test/callback".to_owned());
2142 video.generate_audio = Some(false);
2143 video.frame_images = Some(json!(["image-1"]));
2144 let video = serde_json::to_value(video).unwrap();
2145 assert_eq!(video["callback_url"], "https://example.test/callback");
2146 assert_eq!(video["generate_audio"], false);
2147 assert_eq!(video["frame_images"][0], "image-1");
2148
2149 let mut embeddings = EmbeddingsRequest::new("openai/text-embedding-3-small", "hello");
2150 embeddings.dimensions = Some(128);
2151 embeddings.encoding_format = Some("float".to_owned());
2152 embeddings.input_type = Some("query".to_owned());
2153 let embeddings = serde_json::to_value(embeddings).unwrap();
2154 assert_eq!(embeddings["dimensions"], 128);
2155 assert_eq!(embeddings["encoding_format"], "float");
2156 assert_eq!(embeddings["input_type"], "query");
2157
2158 let mut rerank = RerankRequest::new(
2159 "cohere/rerank",
2160 "query",
2161 [
2162 RerankDocument::Text("plain".to_owned()),
2163 RerankDocument::Object(json!({"text": "rich"})),
2164 ],
2165 );
2166 rerank.top_n = Some(1);
2167 let rerank = serde_json::to_value(rerank).unwrap();
2168 assert_eq!(rerank["documents"][0], "plain");
2169 assert_eq!(rerank["documents"][1]["text"], "rich");
2170 assert_eq!(rerank["top_n"], 1);
2171
2172 let mut transcription =
2173 TranscriptionRequest::new("openai/whisper-1", json!({"data": "base64"}));
2174 transcription.temperature = Some(0.2);
2175 let transcription = serde_json::to_value(transcription).unwrap();
2176 assert_eq!(transcription["temperature"], 0.2);
2177 assert_eq!(transcription["input_audio"]["data"], "base64");
2178 }
2179}