1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
12#[serde(tag = "type", rename_all = "snake_case")]
13pub enum InteractionContent {
14 Text {
15 text: String,
16 #[serde(default, skip_serializing_if = "Vec::is_empty")]
17 annotations: Vec<Annotation>,
18 },
19 Image {
20 #[serde(skip_serializing_if = "Option::is_none")]
21 data: Option<String>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 uri: Option<String>,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 mime_type: Option<ImageMimeType>,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 resolution: Option<MediaResolution>,
28 },
29 Audio {
30 #[serde(skip_serializing_if = "Option::is_none")]
31 data: Option<String>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 uri: Option<String>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 mime_type: Option<AudioMimeType>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 channels: Option<i32>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 sample_rate: Option<i32>,
40 },
41 Document {
42 #[serde(skip_serializing_if = "Option::is_none")]
43 data: Option<String>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 uri: Option<String>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 mime_type: Option<DocumentMimeType>,
48 },
49 Video {
50 #[serde(skip_serializing_if = "Option::is_none")]
51 data: Option<String>,
52 #[serde(skip_serializing_if = "Option::is_none")]
53 uri: Option<String>,
54 #[serde(skip_serializing_if = "Option::is_none")]
55 mime_type: Option<VideoMimeType>,
56 #[serde(skip_serializing_if = "Option::is_none")]
57 resolution: Option<MediaResolution>,
58 },
59}
60
61impl InteractionContent {
62 pub fn text(text: impl Into<String>) -> Self {
64 Self::Text {
65 text: text.into(),
66 annotations: vec![],
67 }
68 }
69
70 pub fn image(data: impl Into<String>, mime_type: ImageMimeType) -> Self {
72 Self::Image {
73 data: Some(data.into()),
74 uri: None,
75 mime_type: Some(mime_type),
76 resolution: None,
77 }
78 }
79
80 pub fn image_uri(uri: impl Into<String>, mime_type: ImageMimeType) -> Self {
82 Self::Image {
83 data: None,
84 uri: Some(uri.into()),
85 mime_type: Some(mime_type),
86 resolution: None,
87 }
88 }
89
90 pub fn audio(data: impl Into<String>, mime_type: AudioMimeType) -> Self {
92 Self::Audio {
93 data: Some(data.into()),
94 uri: None,
95 mime_type: Some(mime_type),
96 channels: None,
97 sample_rate: None,
98 }
99 }
100
101 pub fn video_uri(uri: impl Into<String>) -> Self {
103 Self::Video {
104 data: None,
105 uri: Some(uri.into()),
106 mime_type: None,
107 resolution: None,
108 }
109 }
110
111 pub fn document(data: impl Into<String>, mime_type: DocumentMimeType) -> Self {
113 Self::Document {
114 data: Some(data.into()),
115 uri: None,
116 mime_type: Some(mime_type),
117 }
118 }
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
127#[serde(tag = "type", rename_all = "snake_case")]
128pub enum Annotation {
129 UrlCitation {
130 #[serde(skip_serializing_if = "Option::is_none")]
131 url: Option<String>,
132 #[serde(skip_serializing_if = "Option::is_none")]
133 title: Option<String>,
134 #[serde(skip_serializing_if = "Option::is_none")]
135 start_index: Option<i64>,
136 #[serde(skip_serializing_if = "Option::is_none")]
137 end_index: Option<i64>,
138 },
139 FileCitation {
140 #[serde(skip_serializing_if = "Option::is_none")]
141 document_uri: Option<String>,
142 #[serde(skip_serializing_if = "Option::is_none")]
143 file_name: Option<String>,
144 #[serde(skip_serializing_if = "Option::is_none")]
145 source: Option<String>,
146 #[serde(skip_serializing_if = "Option::is_none")]
147 custom_metadata: Option<serde_json::Value>,
148 #[serde(skip_serializing_if = "Option::is_none")]
149 page_number: Option<i64>,
150 #[serde(skip_serializing_if = "Option::is_none")]
151 media_id: Option<String>,
152 #[serde(skip_serializing_if = "Option::is_none")]
153 start_index: Option<i64>,
154 #[serde(skip_serializing_if = "Option::is_none")]
155 end_index: Option<i64>,
156 },
157 PlaceCitation {
158 #[serde(skip_serializing_if = "Option::is_none")]
159 place_id: Option<String>,
160 #[serde(skip_serializing_if = "Option::is_none")]
161 name: Option<String>,
162 #[serde(skip_serializing_if = "Option::is_none")]
163 url: Option<String>,
164 #[serde(skip_serializing_if = "Option::is_none")]
165 review_snippets: Option<ReviewSnippet>,
166 #[serde(skip_serializing_if = "Option::is_none")]
167 start_index: Option<i64>,
168 #[serde(skip_serializing_if = "Option::is_none")]
169 end_index: Option<i64>,
170 },
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
174pub struct ReviewSnippet {
175 #[serde(skip_serializing_if = "Option::is_none")]
176 pub title: Option<String>,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub url: Option<String>,
179 #[serde(skip_serializing_if = "Option::is_none")]
180 pub review_id: Option<String>,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
192#[serde(tag = "type", rename_all = "snake_case")]
193pub enum Step {
194 UserInput {
195 #[serde(default, skip_serializing_if = "Vec::is_empty")]
196 content: Vec<InteractionContent>,
197 },
198
199 ModelOutput {
200 #[serde(default, skip_serializing_if = "Vec::is_empty")]
201 content: Vec<InteractionContent>,
202 #[serde(skip_serializing_if = "Option::is_none")]
203 error: Option<Status>,
204 },
205
206 Thought {
207 #[serde(skip_serializing_if = "Option::is_none")]
208 signature: Option<String>,
209 #[serde(default, skip_serializing_if = "Vec::is_empty")]
210 summary: Vec<ThoughtSummaryContent>,
211 },
212
213 FunctionCall {
214 name: String,
215 arguments: serde_json::Value,
216 id: String,
217 },
218
219 FunctionResult {
220 #[serde(skip_serializing_if = "Option::is_none")]
221 name: Option<String>,
222 call_id: String,
223 result: StepResult,
224 #[serde(skip_serializing_if = "Option::is_none")]
225 is_error: Option<bool>,
226 },
227
228 CodeExecutionCall {
229 arguments: CodeExecutionCallArguments,
230 id: String,
231 #[serde(skip_serializing_if = "Option::is_none")]
232 signature: Option<String>,
233 },
234
235 CodeExecutionResult {
236 result: String,
237 call_id: String,
238 #[serde(skip_serializing_if = "Option::is_none")]
239 is_error: Option<bool>,
240 #[serde(skip_serializing_if = "Option::is_none")]
241 signature: Option<String>,
242 },
243
244 UrlContextCall {
245 id: String,
246 #[serde(skip_serializing_if = "Option::is_none")]
247 signature: Option<String>,
248 arguments: UrlContextCallArguments,
249 },
250
251 UrlContextResult {
252 result: UrlContextResultData,
253 #[serde(skip_serializing_if = "Option::is_none")]
254 is_error: Option<bool>,
255 call_id: String,
256 #[serde(skip_serializing_if = "Option::is_none")]
257 signature: Option<String>,
258 },
259
260 GoogleSearchCall {
261 arguments: GoogleSearchCallArguments,
262 #[serde(skip_serializing_if = "Option::is_none")]
263 search_type: Option<GoogleSearchType>,
264 id: String,
265 #[serde(skip_serializing_if = "Option::is_none")]
266 signature: Option<String>,
267 },
268
269 GoogleSearchResult {
270 result: GoogleSearchResultItem,
271 #[serde(skip_serializing_if = "Option::is_none")]
272 is_error: Option<bool>,
273 call_id: String,
274 #[serde(skip_serializing_if = "Option::is_none")]
275 signature: Option<String>,
276 },
277
278 GoogleMapsCall {
279 #[serde(skip_serializing_if = "Option::is_none")]
280 arguments: Option<GoogleMapsCallArguments>,
281 id: String,
282 #[serde(skip_serializing_if = "Option::is_none")]
283 signature: Option<String>,
284 },
285
286 GoogleMapsResult {
287 result: GoogleMapsResultItem,
288 call_id: String,
289 #[serde(skip_serializing_if = "Option::is_none")]
290 signature: Option<String>,
291 },
292
293 FileSearchCall {
294 id: String,
295 #[serde(skip_serializing_if = "Option::is_none")]
296 signature: Option<String>,
297 },
298
299 FileSearchResult {
300 #[serde(default, skip_serializing_if = "Vec::is_empty")]
301 citations: Vec<Annotation>,
302 call_id: String,
303 #[serde(skip_serializing_if = "Option::is_none")]
304 signature: Option<String>,
305 },
306
307 McpServerToolCall {
308 name: String,
309 server_name: String,
310 arguments: serde_json::Value,
311 id: String,
312 },
313
314 McpServerToolResult {
315 #[serde(skip_serializing_if = "Option::is_none")]
316 name: Option<String>,
317 #[serde(skip_serializing_if = "Option::is_none")]
318 server_name: Option<String>,
319 call_id: String,
320 result: StepResult,
321 },
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
330#[serde(untagged)]
331pub enum StepResult {
332 ContentArray(Vec<StepResultContent>),
333 Object(serde_json::Value),
334 String(String),
335}
336
337impl StepResult {
338 pub fn from_string(s: impl Into<String>) -> Self {
339 Self::String(s.into())
340 }
341
342 pub fn from_json(value: serde_json::Value) -> Self {
343 Self::Object(value)
344 }
345}
346
347#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
349#[serde(tag = "type", rename_all = "snake_case")]
350pub enum StepResultContent {
351 Text {
352 text: String,
353 },
354 Image {
355 #[serde(skip_serializing_if = "Option::is_none")]
356 data: Option<String>,
357 #[serde(skip_serializing_if = "Option::is_none")]
358 uri: Option<String>,
359 #[serde(skip_serializing_if = "Option::is_none")]
360 mime_type: Option<ImageMimeType>,
361 },
362}
363
364#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
366#[serde(tag = "type", rename_all = "snake_case")]
367pub enum ThoughtSummaryContent {
368 Text { text: String },
369}
370
371#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
372pub struct CodeExecutionCallArguments {
373 #[serde(skip_serializing_if = "Option::is_none")]
374 pub language: Option<CodeLanguage>,
375 #[serde(skip_serializing_if = "Option::is_none")]
376 pub code: Option<String>,
377}
378
379#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
380pub struct UrlContextCallArguments {
381 #[serde(default, skip_serializing_if = "Vec::is_empty")]
382 pub urls: Vec<String>,
383}
384
385#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
386pub struct GoogleSearchCallArguments {
387 #[serde(default, skip_serializing_if = "Vec::is_empty")]
388 pub queries: Vec<String>,
389}
390
391#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
392pub struct GoogleMapsCallArguments {
393 #[serde(default, skip_serializing_if = "Vec::is_empty")]
394 pub queries: Vec<String>,
395}
396
397#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
398pub struct GoogleSearchResultItem {
399 #[serde(skip_serializing_if = "Option::is_none")]
400 pub search_suggestions: Option<String>,
401}
402
403#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
404pub struct GoogleMapsResultItem {
405 #[serde(skip_serializing_if = "Option::is_none")]
406 pub places: Option<GoogleMapsResultPlaces>,
407}
408
409#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
410pub struct GoogleMapsResultPlaces {
411 #[serde(skip_serializing_if = "Option::is_none")]
412 pub place_id: Option<String>,
413 #[serde(skip_serializing_if = "Option::is_none")]
414 pub name: Option<String>,
415 #[serde(skip_serializing_if = "Option::is_none")]
416 pub url: Option<String>,
417 #[serde(skip_serializing_if = "Option::is_none")]
418 pub review_snippets: Option<ReviewSnippet>,
419 #[serde(skip_serializing_if = "Option::is_none")]
420 pub widget_context_token: Option<String>,
421}
422
423#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
424pub struct UrlContextResultData {
425 #[serde(skip_serializing_if = "Option::is_none")]
426 pub url: Option<String>,
427 #[serde(skip_serializing_if = "Option::is_none")]
428 pub status: Option<UrlContextStatus>,
429}
430
431#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
432pub struct Status {
433 #[serde(skip_serializing_if = "Option::is_none")]
434 pub code: Option<i32>,
435 #[serde(skip_serializing_if = "Option::is_none")]
436 pub message: Option<String>,
437 #[serde(default, skip_serializing_if = "Vec::is_empty")]
438 pub details: Vec<serde_json::Value>,
439}
440
441#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
447#[serde(rename_all = "snake_case")]
448pub struct Interaction {
449 #[serde(skip_serializing_if = "Option::is_none")]
450 pub id: Option<String>,
451
452 #[serde(default)]
453 pub status: InteractionStatus,
454
455 #[serde(skip_serializing_if = "Option::is_none")]
456 pub model: Option<String>,
457
458 #[serde(skip_serializing_if = "Option::is_none")]
459 pub agent: Option<String>,
460
461 #[serde(skip_serializing_if = "Option::is_none")]
462 pub object: Option<String>,
463
464 #[serde(skip_serializing_if = "Option::is_none")]
465 pub created: Option<String>,
466
467 #[serde(skip_serializing_if = "Option::is_none")]
468 pub updated: Option<String>,
469
470 #[serde(default, skip_serializing_if = "Vec::is_empty")]
471 pub steps: Vec<Step>,
472
473 #[serde(skip_serializing_if = "Option::is_none")]
474 pub usage: Option<InteractionUsage>,
475
476 #[serde(skip_serializing_if = "Option::is_none")]
477 pub system_instruction: Option<String>,
478
479 #[serde(default, skip_serializing_if = "Vec::is_empty")]
480 pub tools: Vec<InteractionTool>,
481
482 #[serde(skip_serializing_if = "Option::is_none")]
483 pub previous_interaction_id: Option<String>,
484
485 #[serde(skip_serializing_if = "Option::is_none")]
486 pub environment_id: Option<String>,
487
488 #[serde(skip_serializing_if = "Option::is_none")]
489 pub response_modalities: Option<Vec<ResponseModality>>,
490
491 #[serde(skip_serializing_if = "Option::is_none")]
492 pub service_tier: Option<ServiceTier>,
493
494 #[serde(skip_serializing_if = "Option::is_none")]
495 pub cached_content: Option<String>,
496
497 #[serde(skip_serializing_if = "Option::is_none")]
498 pub agent_config: Option<AgentConfig>,
499
500 #[serde(skip_serializing_if = "Option::is_none")]
501 pub error: Option<InteractionError>,
502}
503
504#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
506#[serde(rename_all = "snake_case")]
507pub enum InteractionStatus {
508 #[default]
509 InProgress,
510 RequiresAction,
511 Completed,
512 Failed,
513 Cancelled,
514 Incomplete,
515 BudgetExceeded,
516}
517
518impl InteractionStatus {
519 pub fn is_terminal(&self) -> bool {
520 matches!(
521 self,
522 Self::Completed
523 | Self::Failed
524 | Self::Cancelled
525 | Self::Incomplete
526 | Self::BudgetExceeded
527 )
528 }
529
530 pub fn is_active(&self) -> bool {
531 matches!(self, Self::InProgress | Self::RequiresAction)
532 }
533}
534
535impl AsRef<str> for InteractionStatus {
536 fn as_ref(&self) -> &str {
537 match self {
538 Self::InProgress => "in_progress",
539 Self::RequiresAction => "requires_action",
540 Self::Completed => "completed",
541 Self::Failed => "failed",
542 Self::Cancelled => "cancelled",
543 Self::Incomplete => "incomplete",
544 Self::BudgetExceeded => "budget_exceeded",
545 }
546 }
547}
548
549#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
550pub struct InteractionError {
551 #[serde(skip_serializing_if = "Option::is_none")]
552 pub code: Option<String>,
553 #[serde(skip_serializing_if = "Option::is_none")]
554 pub message: Option<String>,
555}
556
557#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
563#[serde(tag = "type", rename_all = "snake_case")]
564pub enum InteractionTool {
565 Function {
566 #[serde(skip_serializing_if = "Option::is_none")]
567 name: Option<String>,
568 #[serde(skip_serializing_if = "Option::is_none")]
569 description: Option<String>,
570 #[serde(skip_serializing_if = "Option::is_none")]
571 parameters: Option<serde_json::Value>,
572 },
573
574 CodeExecution,
575
576 UrlContext,
577
578 ComputerUse {
579 #[serde(skip_serializing_if = "Option::is_none")]
580 environment: Option<ComputerUseEnvironment>,
581 #[serde(default, skip_serializing_if = "Vec::is_empty")]
582 excluded_predefined_functions: Vec<String>,
583 #[serde(skip_serializing_if = "Option::is_none")]
584 enable_prompt_injection_detection: Option<bool>,
585 #[serde(default, skip_serializing_if = "Vec::is_empty")]
586 disabled_safety_policies: Vec<ComputerUseSafetyPolicy>,
587 },
588
589 McpServer {
590 #[serde(skip_serializing_if = "Option::is_none")]
591 name: Option<String>,
592 #[serde(skip_serializing_if = "Option::is_none")]
593 url: Option<String>,
594 #[serde(skip_serializing_if = "Option::is_none")]
595 headers: Option<serde_json::Value>,
596 #[serde(skip_serializing_if = "Option::is_none")]
597 allowed_tools: Option<AllowedTools>,
598 },
599
600 GoogleSearch {
601 #[serde(default, skip_serializing_if = "Vec::is_empty")]
602 search_types: Vec<GoogleSearchType>,
603 },
604
605 FileSearch {
606 #[serde(default, skip_serializing_if = "Vec::is_empty")]
607 file_search_store_names: Vec<String>,
608 #[serde(skip_serializing_if = "Option::is_none")]
609 top_k: Option<i64>,
610 #[serde(skip_serializing_if = "Option::is_none")]
611 metadata_filter: Option<String>,
612 },
613
614 GoogleMaps {
615 #[serde(skip_serializing_if = "Option::is_none")]
616 enable_widget: Option<bool>,
617 #[serde(skip_serializing_if = "Option::is_none")]
618 latitude: Option<f64>,
619 #[serde(skip_serializing_if = "Option::is_none")]
620 longitude: Option<f64>,
621 },
622
623 Retrieval {
624 #[serde(default, skip_serializing_if = "Vec::is_empty")]
625 retrieval_types: Vec<RetrievalType>,
626 #[serde(skip_serializing_if = "Option::is_none")]
627 exa_ai_search_config: Option<ExaAISearchConfig>,
628 #[serde(skip_serializing_if = "Option::is_none")]
629 parallel_ai_search_config: Option<ParallelAISearchConfig>,
630 #[serde(skip_serializing_if = "Option::is_none")]
631 rag_store_config: Option<RagStoreConfig>,
632 },
633}
634
635impl InteractionTool {
636 pub fn function(
638 name: impl Into<String>,
639 description: impl Into<String>,
640 parameters: serde_json::Value,
641 ) -> Self {
642 Self::Function {
643 name: Some(name.into()),
644 description: Some(description.into()),
645 parameters: Some(parameters),
646 }
647 }
648
649 pub fn google_search() -> Self {
651 Self::GoogleSearch {
652 search_types: vec![GoogleSearchType::WebSearch],
653 }
654 }
655
656 pub fn code_execution() -> Self {
658 Self::CodeExecution
659 }
660
661 pub fn url_context() -> Self {
663 Self::UrlContext
664 }
665
666 pub fn google_maps() -> Self {
668 Self::GoogleMaps {
669 enable_widget: None,
670 latitude: None,
671 longitude: None,
672 }
673 }
674
675 pub fn file_search(store_names: Vec<String>) -> Self {
677 Self::FileSearch {
678 file_search_store_names: store_names,
679 top_k: None,
680 metadata_filter: None,
681 }
682 }
683
684 pub fn mcp_server(name: impl Into<String>, url: impl Into<String>) -> Self {
686 Self::McpServer {
687 name: Some(name.into()),
688 url: Some(url.into()),
689 headers: None,
690 allowed_tools: None,
691 }
692 }
693
694 pub fn computer_use(environment: ComputerUseEnvironment) -> Self {
696 Self::ComputerUse {
697 environment: Some(environment),
698 excluded_predefined_functions: vec![],
699 enable_prompt_injection_detection: None,
700 disabled_safety_policies: vec![],
701 }
702 }
703
704 pub fn retrieval(retrieval_types: Vec<RetrievalType>) -> Self {
706 Self::Retrieval {
707 retrieval_types,
708 exa_ai_search_config: None,
709 parallel_ai_search_config: None,
710 rag_store_config: None,
711 }
712 }
713}
714
715#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
716pub struct AllowedTools {
717 #[serde(skip_serializing_if = "Option::is_none")]
718 pub mode: Option<ToolChoiceMode>,
719 #[serde(default, skip_serializing_if = "Vec::is_empty")]
720 pub tools: Vec<String>,
721}
722
723#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
724pub struct ExaAISearchConfig {
725 #[serde(skip_serializing_if = "Option::is_none")]
726 pub api_key: Option<String>,
727 #[serde(skip_serializing_if = "Option::is_none")]
728 pub custom_config: Option<serde_json::Value>,
729}
730
731#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
732pub struct ParallelAISearchConfig {
733 #[serde(skip_serializing_if = "Option::is_none")]
734 pub api_key: Option<String>,
735 #[serde(skip_serializing_if = "Option::is_none")]
736 pub custom_config: Option<serde_json::Value>,
737}
738
739#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
740pub struct RagStoreConfig {
741 #[serde(skip_serializing_if = "Option::is_none")]
742 pub rag_resources: Option<RagResource>,
743}
744
745#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
746pub struct RagResource {
747 #[serde(skip_serializing_if = "Option::is_none")]
748 pub rag_corpus: Option<String>,
749 #[serde(default, skip_serializing_if = "Vec::is_empty")]
750 pub rag_file_ids: Vec<String>,
751 #[serde(skip_serializing_if = "Option::is_none")]
752 pub rag_retrieval_config: Option<RagRetrievalConfig>,
753}
754
755#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
757pub struct RagRetrievalConfig {
758 #[serde(skip_serializing_if = "Option::is_none")]
759 pub top_k: Option<i64>,
760 #[serde(skip_serializing_if = "Option::is_none")]
761 pub hybrid_search: Option<HybridSearch>,
762 #[serde(skip_serializing_if = "Option::is_none")]
763 pub filter: Option<RagFilter>,
764 #[serde(skip_serializing_if = "Option::is_none")]
765 pub ranking: Option<Ranking>,
766}
767
768#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
770pub struct HybridSearch {
771 #[serde(skip_serializing_if = "Option::is_none")]
772 pub alpha: Option<f64>,
773}
774
775#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
777pub struct RagFilter {
778 #[serde(skip_serializing_if = "Option::is_none")]
779 pub vector_distance_threshold: Option<f64>,
780 #[serde(skip_serializing_if = "Option::is_none")]
781 pub vector_similarity_threshold: Option<f64>,
782 #[serde(skip_serializing_if = "Option::is_none")]
783 pub metadata_filter: Option<String>,
784}
785
786#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
788pub struct Ranking {
789 #[serde(flatten)]
790 pub config: Option<serde_json::Value>,
791}
792
793#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
799#[serde(tag = "type", rename_all = "snake_case")]
800pub enum ResponseFormat {
801 Text {
802 #[serde(skip_serializing_if = "Option::is_none")]
803 mime_type: Option<TextMimeType>,
804 #[serde(skip_serializing_if = "Option::is_none")]
805 schema: Option<serde_json::Value>,
806 },
807 Audio {
808 #[serde(skip_serializing_if = "Option::is_none")]
809 mime_type: Option<AudioOutputMimeType>,
810 #[serde(skip_serializing_if = "Option::is_none")]
811 delivery: Option<DeliveryMode>,
812 #[serde(skip_serializing_if = "Option::is_none")]
813 sample_rate: Option<i32>,
814 #[serde(skip_serializing_if = "Option::is_none")]
815 bit_rate: Option<i32>,
816 },
817 Image {
818 #[serde(skip_serializing_if = "Option::is_none")]
819 mime_type: Option<ImageOutputMimeType>,
820 #[serde(skip_serializing_if = "Option::is_none")]
821 delivery: Option<DeliveryMode>,
822 #[serde(skip_serializing_if = "Option::is_none")]
823 aspect_ratio: Option<AspectRatio>,
824 #[serde(skip_serializing_if = "Option::is_none")]
825 image_size: Option<ImageSize>,
826 },
827 Video {
828 #[serde(skip_serializing_if = "Option::is_none")]
829 delivery: Option<DeliveryMode>,
830 #[serde(skip_serializing_if = "Option::is_none")]
831 gcs_uri: Option<String>,
832 #[serde(skip_serializing_if = "Option::is_none")]
833 aspect_ratio: Option<VideoAspectRatio>,
834 #[serde(skip_serializing_if = "Option::is_none")]
835 duration: Option<String>,
836 },
837}
838
839impl ResponseFormat {
840 pub fn json_schema(schema: serde_json::Value) -> Self {
842 Self::Text {
843 mime_type: Some(TextMimeType::ApplicationJson),
844 schema: Some(schema),
845 }
846 }
847
848 pub fn text() -> Self {
850 Self::Text {
851 mime_type: Some(TextMimeType::TextPlain),
852 schema: None,
853 }
854 }
855}
856
857#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
863#[serde(rename_all = "snake_case")]
864pub struct InteractionGenerationConfig {
865 #[serde(skip_serializing_if = "Option::is_none")]
866 pub temperature: Option<f64>,
867
868 #[serde(skip_serializing_if = "Option::is_none")]
869 pub top_p: Option<f64>,
870
871 #[serde(skip_serializing_if = "Option::is_none")]
872 pub seed: Option<i64>,
873
874 #[serde(default, skip_serializing_if = "Vec::is_empty")]
875 pub stop_sequences: Vec<String>,
876
877 #[serde(skip_serializing_if = "Option::is_none")]
878 pub thinking_level: Option<InteractionThinkingLevel>,
879
880 #[serde(skip_serializing_if = "Option::is_none")]
881 pub thinking_summaries: Option<ThinkingSummaries>,
882
883 #[serde(skip_serializing_if = "Option::is_none")]
884 pub max_output_tokens: Option<i64>,
885
886 #[serde(default, skip_serializing_if = "Vec::is_empty")]
887 pub speech_config: Vec<InteractionSpeechConfig>,
888
889 #[serde(skip_serializing_if = "Option::is_none")]
890 pub video_config: Option<VideoConfig>,
891
892 #[serde(skip_serializing_if = "Option::is_none")]
893 pub presence_penalty: Option<f64>,
894
895 #[serde(skip_serializing_if = "Option::is_none")]
896 pub frequency_penalty: Option<f64>,
897
898 #[serde(skip_serializing_if = "Option::is_none")]
899 pub tool_choice: Option<ToolChoiceConfig>,
900}
901
902#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
903#[serde(rename_all = "snake_case")]
904pub enum InteractionThinkingLevel {
905 Minimal,
906 Low,
907 Medium,
908 High,
909}
910
911#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
912#[serde(rename_all = "snake_case")]
913pub enum ThinkingSummaries {
914 Auto,
915 None,
916}
917
918#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
919#[serde(rename_all = "snake_case")]
920pub struct InteractionSpeechConfig {
921 #[serde(skip_serializing_if = "Option::is_none")]
922 pub voice: Option<String>,
923 #[serde(skip_serializing_if = "Option::is_none")]
924 pub language: Option<String>,
925 #[serde(skip_serializing_if = "Option::is_none")]
926 pub speaker: Option<String>,
927}
928
929#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
930#[serde(rename_all = "snake_case")]
931pub struct VideoConfig {
932 #[serde(skip_serializing_if = "Option::is_none")]
933 pub task: Option<VideoTask>,
934}
935
936#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
937pub struct ToolChoiceConfig {
938 #[serde(skip_serializing_if = "Option::is_none")]
939 pub allowed_tools: Option<AllowedTools>,
940}
941
942#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
948#[serde(rename_all = "snake_case")]
949pub struct InteractionUsage {
950 #[serde(skip_serializing_if = "Option::is_none")]
951 pub total_input_tokens: Option<i64>,
952
953 #[serde(default, skip_serializing_if = "Vec::is_empty")]
954 pub input_tokens_by_modality: Vec<ModalityTokens>,
955
956 #[serde(skip_serializing_if = "Option::is_none")]
957 pub total_cached_tokens: Option<i64>,
958
959 #[serde(default, skip_serializing_if = "Vec::is_empty")]
960 pub cached_tokens_by_modality: Vec<ModalityTokens>,
961
962 #[serde(skip_serializing_if = "Option::is_none")]
963 pub total_output_tokens: Option<i64>,
964
965 #[serde(default, skip_serializing_if = "Vec::is_empty")]
966 pub output_tokens_by_modality: Vec<ModalityTokens>,
967
968 #[serde(skip_serializing_if = "Option::is_none")]
969 pub total_tool_use_tokens: Option<i64>,
970
971 #[serde(default, skip_serializing_if = "Vec::is_empty")]
972 pub tool_use_tokens_by_modality: Vec<ModalityTokens>,
973
974 #[serde(skip_serializing_if = "Option::is_none")]
975 pub total_thought_tokens: Option<i64>,
976
977 #[serde(skip_serializing_if = "Option::is_none")]
978 pub total_tokens: Option<i64>,
979
980 #[serde(default, skip_serializing_if = "Vec::is_empty")]
981 pub grounding_tool_count: Vec<GroundingToolCount>,
982}
983
984#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
985pub struct ModalityTokens {
986 #[serde(skip_serializing_if = "Option::is_none")]
987 pub modality: Option<ResponseModality>,
988 #[serde(skip_serializing_if = "Option::is_none")]
989 pub tokens: Option<i64>,
990}
991
992#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
993pub struct GroundingToolCount {
994 #[serde(rename = "type")]
995 pub grounding_type: Option<GroundingType>,
996 #[serde(skip_serializing_if = "Option::is_none")]
997 pub count: Option<i64>,
998}
999
1000#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1006#[serde(tag = "type", rename_all = "kebab-case")]
1007pub enum AgentConfig {
1008 Dynamic,
1009
1010 DeepResearch {
1011 #[serde(skip_serializing_if = "Option::is_none")]
1012 thinking_summaries: Option<ThinkingSummaries>,
1013 #[serde(skip_serializing_if = "Option::is_none")]
1014 visualization: Option<Visualization>,
1015 #[serde(skip_serializing_if = "Option::is_none")]
1016 collaborative_planning: Option<bool>,
1017 #[serde(skip_serializing_if = "Option::is_none")]
1018 enable_bigquery_tool: Option<bool>,
1019 },
1020}
1021
1022#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1027#[serde(rename_all = "snake_case")]
1028pub enum ResponseModality {
1029 Text,
1030 Image,
1031 Audio,
1032 Video,
1033 Document,
1034}
1035
1036#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1037#[serde(rename_all = "snake_case")]
1038pub enum ServiceTier {
1039 Flex,
1040 Standard,
1041 Priority,
1042}
1043
1044#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1045#[serde(rename_all = "snake_case")]
1046pub enum DeliveryMode {
1047 Inline,
1048 Uri,
1049}
1050
1051#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1052#[serde(rename_all = "snake_case")]
1053pub enum MediaResolution {
1054 Low,
1055 Medium,
1056 High,
1057 UltraHigh,
1058}
1059
1060#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1061pub enum ImageMimeType {
1062 #[serde(rename = "image/png")]
1063 Png,
1064 #[serde(rename = "image/jpeg")]
1065 Jpeg,
1066 #[serde(rename = "image/webp")]
1067 Webp,
1068 #[serde(rename = "image/heic")]
1069 Heic,
1070 #[serde(rename = "image/heif")]
1071 Heif,
1072 #[serde(rename = "image/gif")]
1073 Gif,
1074 #[serde(rename = "image/bmp")]
1075 Bmp,
1076 #[serde(rename = "image/tiff")]
1077 Tiff,
1078}
1079
1080#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1081pub enum AudioMimeType {
1082 #[serde(rename = "audio/wav")]
1083 Wav,
1084 #[serde(rename = "audio/mp3")]
1085 Mp3,
1086 #[serde(rename = "audio/aac")]
1087 Aac,
1088 #[serde(rename = "audio/flac")]
1089 Flac,
1090 #[serde(rename = "audio/ogg")]
1091 Ogg,
1092 #[serde(rename = "audio/ogg_opus")]
1093 OggOpus,
1094 #[serde(rename = "audio/m4a")]
1095 M4a,
1096 #[serde(rename = "audio/opus")]
1097 Opus,
1098 #[serde(rename = "audio/pcm")]
1099 Pcm,
1100 #[serde(rename = "audio/l16")]
1101 L16,
1102 #[serde(rename = "audio/mulaw")]
1103 Mulaw,
1104 #[serde(rename = "audio/alaw")]
1105 Alaw,
1106 #[serde(rename = "audio/amr")]
1107 Amr,
1108 #[serde(rename = "audio/aiff")]
1109 Aiff,
1110 #[serde(rename = "audio/mpeg")]
1111 Mpeg,
1112}
1113
1114#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1115pub enum VideoMimeType {
1116 #[serde(rename = "video/mp4")]
1117 Mp4,
1118 #[serde(rename = "video/webm")]
1119 Webm,
1120 #[serde(rename = "video/quicktime")]
1121 Quicktime,
1122 #[serde(rename = "video/mpeg")]
1123 Mpeg,
1124 #[serde(rename = "video/x-ms-wmv")]
1125 Wmv,
1126 #[serde(rename = "video/x-flv")]
1127 Flv,
1128 #[serde(rename = "video/3gpp")]
1129 ThreeGpp,
1130 #[serde(rename = "video/avi")]
1131 Avi,
1132}
1133
1134#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1135pub enum DocumentMimeType {
1136 #[serde(rename = "application/pdf")]
1137 Pdf,
1138 #[serde(rename = "text/plain")]
1139 TextPlain,
1140 #[serde(rename = "text/html")]
1141 TextHtml,
1142 #[serde(rename = "text/css")]
1143 TextCss,
1144 #[serde(rename = "text/csv")]
1145 TextCsv,
1146 #[serde(rename = "text/javascript")]
1147 TextJavascript,
1148 #[serde(rename = "text/x-typescript")]
1149 TextXTypescript,
1150 #[serde(rename = "application/json")]
1151 ApplicationJson,
1152 #[serde(rename = "application/rtf")]
1153 Rtf,
1154 #[serde(rename = "application/vnd.openxmlformats-officedocument.wordprocessingml.document")]
1155 Docx,
1156 #[serde(rename = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")]
1157 Xlsx,
1158 #[serde(rename = "application/vnd.openxmlformats-officedocument.presentationml.presentation")]
1159 Pptx,
1160 #[serde(rename = "application/vnd.ms-excel")]
1161 Xls,
1162 #[serde(rename = "application/vnd.ms-powerpoint")]
1163 Ppt,
1164 #[serde(rename = "application/msword")]
1165 Doc,
1166 #[serde(rename = "text/markdown")]
1167 TextMarkdown,
1168 #[serde(rename = "text/x-python")]
1169 TextXPython,
1170 #[serde(rename = "application/x-java-source")]
1171 ApplicationXJavaSource,
1172 #[serde(rename = "application/x-sh")]
1173 ApplicationXSh,
1174 #[serde(rename = "application/typescript")]
1175 ApplicationTypescript,
1176 #[serde(rename = "application/x-typescript")]
1177 ApplicationXTypescript,
1178 #[serde(rename = "application/javascript")]
1179 ApplicationJavascript,
1180}
1181
1182#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1183pub enum TextMimeType {
1184 #[serde(rename = "text/plain")]
1185 TextPlain,
1186 #[serde(rename = "application/json")]
1187 ApplicationJson,
1188}
1189
1190#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1191pub enum AudioOutputMimeType {
1192 #[serde(rename = "audio/mp3")]
1193 Mp3,
1194 #[serde(rename = "audio/ogg_opus")]
1195 OggOpus,
1196 #[serde(rename = "audio/l16")]
1197 L16,
1198 #[serde(rename = "audio/wav")]
1199 Wav,
1200 #[serde(rename = "audio/alaw")]
1201 Alaw,
1202 #[serde(rename = "audio/mulaw")]
1203 Mulaw,
1204}
1205
1206#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1207pub enum ImageOutputMimeType {
1208 #[serde(rename = "image/jpeg")]
1209 Jpeg,
1210 #[serde(rename = "image/png")]
1211 Png,
1212}
1213
1214#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1215pub enum AspectRatio {
1216 #[serde(rename = "1:1")]
1217 R1x1,
1218 #[serde(rename = "2:3")]
1219 R2x3,
1220 #[serde(rename = "3:2")]
1221 R3x2,
1222 #[serde(rename = "3:4")]
1223 R3x4,
1224 #[serde(rename = "4:3")]
1225 R4x3,
1226 #[serde(rename = "4:5")]
1227 R4x5,
1228 #[serde(rename = "5:4")]
1229 R5x4,
1230 #[serde(rename = "9:16")]
1231 R9x16,
1232 #[serde(rename = "16:9")]
1233 R16x9,
1234 #[serde(rename = "21:9")]
1235 R21x9,
1236 #[serde(rename = "1:8")]
1237 R1x8,
1238 #[serde(rename = "8:1")]
1239 R8x1,
1240 #[serde(rename = "1:4")]
1241 R1x4,
1242 #[serde(rename = "4:1")]
1243 R4x1,
1244}
1245
1246#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1247#[serde(rename_all = "snake_case")]
1248pub enum ImageSize {
1249 #[serde(rename = "512")]
1250 S512,
1251 #[serde(rename = "1K")]
1252 S1k,
1253 #[serde(rename = "2K")]
1254 S2k,
1255 #[serde(rename = "4K")]
1256 S4k,
1257}
1258
1259#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1260pub enum VideoAspectRatio {
1261 #[serde(rename = "16:9")]
1262 R16x9,
1263 #[serde(rename = "9:16")]
1264 R9x16,
1265}
1266
1267#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1268#[serde(rename_all = "snake_case")]
1269pub enum VideoTask {
1270 TextToVideo,
1271 ImageToVideo,
1272 ReferenceToVideo,
1273 Edit,
1274}
1275
1276#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1277#[serde(rename_all = "snake_case")]
1278pub enum CodeLanguage {
1279 Python,
1280}
1281
1282#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1283#[serde(rename_all = "snake_case")]
1284pub enum GoogleSearchType {
1285 WebSearch,
1286 ImageSearch,
1287 EnterpriseWebSearch,
1288}
1289
1290#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1291#[serde(rename_all = "snake_case")]
1292pub enum RetrievalType {
1293 RagStore,
1294 ExaAiSearch,
1295 ParallelAiSearch,
1296}
1297
1298#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1299#[serde(rename_all = "snake_case")]
1300pub enum ComputerUseEnvironment {
1301 Browser,
1302 Mobile,
1303 Desktop,
1304}
1305
1306#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1307#[serde(rename_all = "snake_case")]
1308pub enum ComputerUseSafetyPolicy {
1309 DangerousContent,
1310 Harassment,
1311 HateSpeech,
1312 SexuallyExplicit,
1313 CivilIntegrity,
1314 Csam,
1315 TributeSpeech,
1316 Unspecified,
1317}
1318
1319#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1320#[serde(rename_all = "snake_case")]
1321pub enum UrlContextStatus {
1322 Success,
1323 Error,
1324 Paywall,
1325 Unsafe,
1326}
1327
1328#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1329#[serde(rename_all = "snake_case")]
1330pub enum ToolChoiceMode {
1331 Auto,
1332 Any,
1333 None,
1334 Validated,
1335}
1336
1337#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1338#[serde(rename_all = "snake_case")]
1339pub enum Visualization {
1340 Off,
1341 Auto,
1342}
1343
1344#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1345#[serde(rename_all = "snake_case")]
1346pub enum GroundingType {
1347 GoogleSearch,
1348 GoogleMaps,
1349 Retrieval,
1350}
1351
1352#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
1357#[serde(rename_all = "snake_case")]
1358pub struct WebhookConfig {
1359 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1360 pub uris: Vec<String>,
1361 #[serde(skip_serializing_if = "Option::is_none")]
1362 pub user_metadata: Option<serde_json::Value>,
1363}
1364
1365#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1371#[serde(untagged)]
1372pub enum EnvironmentConfigOrString {
1373 Config(EnvironmentConfig),
1374 Id(String),
1375}
1376
1377#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1379#[serde(tag = "type", rename_all = "snake_case")]
1380pub enum EnvironmentConfig {
1381 Remote {
1382 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1383 sources: Vec<EnvironmentSource>,
1384 #[serde(skip_serializing_if = "Option::is_none")]
1385 environment_id: Option<String>,
1386 #[serde(skip_serializing_if = "Option::is_none")]
1387 network: Option<EnvironmentNetwork>,
1388 },
1389}
1390
1391#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1393#[serde(tag = "type", rename_all = "snake_case")]
1394pub enum EnvironmentSource {
1395 Gcs {
1396 #[serde(skip_serializing_if = "Option::is_none")]
1397 source: Option<String>,
1398 #[serde(skip_serializing_if = "Option::is_none")]
1399 target: Option<String>,
1400 },
1401 Inline {
1402 #[serde(skip_serializing_if = "Option::is_none")]
1403 target: Option<String>,
1404 #[serde(skip_serializing_if = "Option::is_none")]
1405 content: Option<String>,
1406 #[serde(skip_serializing_if = "Option::is_none")]
1407 encoding: Option<String>,
1408 },
1409 Repository {
1410 #[serde(skip_serializing_if = "Option::is_none")]
1411 source: Option<String>,
1412 #[serde(skip_serializing_if = "Option::is_none")]
1413 target: Option<String>,
1414 },
1415 SkillRegistry {
1416 #[serde(skip_serializing_if = "Option::is_none")]
1417 source: Option<String>,
1418 #[serde(skip_serializing_if = "Option::is_none")]
1419 target: Option<String>,
1420 },
1421}
1422
1423#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1425#[serde(untagged)]
1426pub enum EnvironmentNetwork {
1427 Allowlist(EnvironmentNetworkEgressAllowlist),
1428 Disabled(String),
1429}
1430
1431#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
1432pub struct EnvironmentNetworkEgressAllowlist {
1433 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1434 pub allowlist: Vec<AllowlistEntry>,
1435}
1436
1437#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
1438pub struct AllowlistEntry {
1439 #[serde(skip_serializing_if = "Option::is_none")]
1440 pub domain: Option<String>,
1441 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1442 pub transform: Vec<serde_json::Value>,
1443}
1444
1445#[derive(Debug, Clone, Serialize, Deserialize)]
1451#[serde(rename_all = "snake_case")]
1452pub struct CreateInteractionRequest {
1453 #[serde(skip_serializing_if = "Option::is_none")]
1454 pub model: Option<String>,
1455
1456 #[serde(skip_serializing_if = "Option::is_none")]
1457 pub agent: Option<String>,
1458
1459 pub input: InteractionInput,
1460
1461 #[serde(skip_serializing_if = "Option::is_none")]
1462 pub system_instruction: Option<String>,
1463
1464 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1465 pub tools: Vec<InteractionTool>,
1466
1467 #[serde(skip_serializing_if = "Option::is_none")]
1468 pub response_format: Option<ResponseFormat>,
1469
1470 #[serde(skip_serializing_if = "Option::is_none")]
1471 pub stream: Option<bool>,
1472
1473 #[serde(skip_serializing_if = "Option::is_none")]
1474 pub store: Option<bool>,
1475
1476 #[serde(skip_serializing_if = "Option::is_none")]
1477 pub background: Option<bool>,
1478
1479 #[serde(skip_serializing_if = "Option::is_none")]
1480 pub generation_config: Option<InteractionGenerationConfig>,
1481
1482 #[serde(skip_serializing_if = "Option::is_none")]
1483 pub agent_config: Option<AgentConfig>,
1484
1485 #[serde(skip_serializing_if = "Option::is_none")]
1486 pub previous_interaction_id: Option<String>,
1487
1488 #[serde(skip_serializing_if = "Option::is_none")]
1489 pub environment: Option<EnvironmentConfigOrString>,
1490
1491 #[serde(skip_serializing_if = "Option::is_none")]
1492 pub cached_content: Option<String>,
1493
1494 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1495 pub response_modalities: Vec<ResponseModality>,
1496
1497 #[serde(skip_serializing_if = "Option::is_none")]
1498 pub service_tier: Option<ServiceTier>,
1499
1500 #[serde(skip_serializing_if = "Option::is_none")]
1501 pub webhook_config: Option<WebhookConfig>,
1502}
1503
1504#[derive(Debug, Clone, Serialize, Deserialize)]
1506#[serde(untagged)]
1507pub enum InteractionInput {
1508 Text(String),
1509 Content(InteractionContent),
1510 ContentArray(Vec<InteractionContent>),
1511 StepArray(Vec<Step>),
1512}
1513
1514impl InteractionInput {
1515 pub fn text(text: impl Into<String>) -> Self {
1517 Self::Text(text.into())
1518 }
1519
1520 pub fn content_array(content: Vec<InteractionContent>) -> Self {
1522 Self::ContentArray(content)
1523 }
1524
1525 pub fn step_array(steps: Vec<Step>) -> Self {
1527 Self::StepArray(steps)
1528 }
1529}
1530
1531impl From<String> for InteractionInput {
1532 fn from(s: String) -> Self {
1533 Self::Text(s)
1534 }
1535}
1536
1537impl From<&str> for InteractionInput {
1538 fn from(s: &str) -> Self {
1539 Self::Text(s.to_string())
1540 }
1541}
1542
1543impl From<Vec<InteractionContent>> for InteractionInput {
1544 fn from(c: Vec<InteractionContent>) -> Self {
1545 Self::ContentArray(c)
1546 }
1547}
1548
1549impl From<Vec<Step>> for InteractionInput {
1550 fn from(s: Vec<Step>) -> Self {
1551 Self::StepArray(s)
1552 }
1553}