1use std::collections::HashMap;
7
8use serde::{Deserialize, Serialize};
9use serde_json::Value;
10use validator::Validate;
11
12use crate::validated::Normalizable;
13
14#[serde_with::skip_serializing_none]
22#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
23#[validate(schema(function = "validate_mcp_config"))]
24pub struct CreateMessageRequest {
25 #[validate(length(min = 1, message = "model field is required and cannot be empty"))]
27 pub model: String,
28
29 #[validate(length(min = 1, message = "messages array is required and cannot be empty"))]
31 pub messages: Vec<InputMessage>,
32
33 #[validate(range(min = 1, message = "max_tokens must be greater than 0"))]
35 pub max_tokens: u32,
36
37 pub metadata: Option<Metadata>,
39
40 pub service_tier: Option<ServiceTier>,
42
43 pub stop_sequences: Option<Vec<String>>,
45
46 pub stream: Option<bool>,
48
49 pub system: Option<SystemContent>,
51
52 pub temperature: Option<f64>,
54
55 pub thinking: Option<ThinkingConfig>,
57
58 pub tool_choice: Option<ToolChoice>,
60
61 pub tools: Option<Vec<Tool>>,
63
64 pub top_k: Option<u32>,
66
67 pub top_p: Option<f64>,
69
70 pub container: Option<ContainerConfig>,
73
74 pub mcp_servers: Option<Vec<McpServerConfig>>,
76}
77
78impl Normalizable for CreateMessageRequest {
79 }
81
82impl CreateMessageRequest {
83 pub fn is_stream(&self) -> bool {
85 self.stream.unwrap_or(false)
86 }
87
88 pub fn get_model(&self) -> &str {
90 &self.model
91 }
92
93 pub fn has_mcp_toolset(&self) -> bool {
95 self.tools
96 .as_ref()
97 .is_some_and(|tools| tools.iter().any(|t| matches!(t, Tool::McpToolset(_))))
98 }
99
100 pub fn mcp_server_configs(&self) -> Option<&[McpServerConfig]> {
102 self.mcp_servers
103 .as_deref()
104 .filter(|servers| !servers.is_empty())
105 }
106}
107
108fn validate_mcp_config(req: &CreateMessageRequest) -> Result<(), validator::ValidationError> {
110 if req.has_mcp_toolset() && req.mcp_server_configs().is_none() {
111 let mut e = validator::ValidationError::new("mcp_servers_required");
112 e.message = Some("mcp_servers is required when mcp_toolset tools are present".into());
113 return Err(e);
114 }
115 Ok(())
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct Metadata {
121 #[serde(skip_serializing_if = "Option::is_none")]
123 pub user_id: Option<String>,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128#[serde(rename_all = "snake_case")]
129pub enum ServiceTier {
130 Auto,
131 StandardOnly,
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
136#[serde(untagged)]
137pub enum SystemContent {
138 String(String),
139 Blocks(Vec<TextBlock>),
140}
141
142#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct InputMessage {
145 pub role: Role,
147
148 pub content: InputContent,
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
154#[serde(rename_all = "lowercase")]
155pub enum Role {
156 User,
157 Assistant,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
162#[serde(untagged)]
163pub enum InputContent {
164 String(String),
165 Blocks(Vec<InputContentBlock>),
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
174#[serde(tag = "type", rename_all = "snake_case")]
175pub enum InputContentBlock {
176 Text(TextBlock),
178 Image(ImageBlock),
180 Document(DocumentBlock),
182 ToolUse(ToolUseBlock),
184 ToolResult(ToolResultBlock),
186 Thinking(ThinkingBlock),
188 RedactedThinking(RedactedThinkingBlock),
190 ServerToolUse(ServerToolUseBlock),
192 SearchResult(SearchResultBlock),
194 WebSearchToolResult(WebSearchToolResultBlock),
196}
197
198#[serde_with::skip_serializing_none]
200#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct TextBlock {
202 pub text: String,
204
205 pub cache_control: Option<CacheControl>,
207
208 pub citations: Option<Vec<Citation>>,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct ImageBlock {
215 pub source: ImageSource,
217
218 #[serde(skip_serializing_if = "Option::is_none")]
220 pub cache_control: Option<CacheControl>,
221}
222
223#[derive(Debug, Clone, Serialize, Deserialize)]
225#[serde(tag = "type", rename_all = "snake_case")]
226pub enum ImageSource {
227 Base64 { media_type: String, data: String },
228 Url { url: String },
229}
230
231#[serde_with::skip_serializing_none]
233#[derive(Debug, Clone, Serialize, Deserialize)]
234pub struct DocumentBlock {
235 pub source: DocumentSource,
237
238 pub cache_control: Option<CacheControl>,
240
241 pub title: Option<String>,
243
244 pub context: Option<String>,
246
247 pub citations: Option<CitationsConfig>,
249}
250
251#[derive(Debug, Clone, Serialize, Deserialize)]
253#[serde(tag = "type", rename_all = "snake_case")]
254pub enum DocumentSource {
255 Base64 { media_type: String, data: String },
256 Text { data: String },
257 Url { url: String },
258 Content { content: Vec<InputContentBlock> },
259}
260
261#[derive(Debug, Clone, Serialize, Deserialize)]
263pub struct ToolUseBlock {
264 pub id: String,
266
267 pub name: String,
269
270 pub input: Value,
272
273 #[serde(skip_serializing_if = "Option::is_none")]
275 pub cache_control: Option<CacheControl>,
276}
277
278#[serde_with::skip_serializing_none]
280#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct ToolResultBlock {
282 pub tool_use_id: String,
284
285 pub content: Option<ToolResultContent>,
287
288 pub is_error: Option<bool>,
290
291 pub cache_control: Option<CacheControl>,
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize)]
297#[serde(untagged)]
298pub enum ToolResultContent {
299 String(String),
300 Blocks(Vec<ToolResultContentBlock>),
301}
302
303#[derive(Debug, Clone, Serialize, Deserialize)]
305#[serde(tag = "type", rename_all = "snake_case")]
306pub enum ToolResultContentBlock {
307 Text(TextBlock),
308 Image(ImageBlock),
309 Document(DocumentBlock),
310 SearchResult(SearchResultBlock),
311}
312
313#[derive(Debug, Clone, Serialize, Deserialize)]
315pub struct ThinkingBlock {
316 pub thinking: String,
318
319 pub signature: String,
321}
322
323#[derive(Debug, Clone, Serialize, Deserialize)]
325pub struct RedactedThinkingBlock {
326 pub data: String,
328}
329
330#[derive(Debug, Clone, Serialize, Deserialize)]
332pub struct ServerToolUseBlock {
333 pub id: String,
335
336 pub name: String,
338
339 pub input: Value,
341
342 #[serde(skip_serializing_if = "Option::is_none")]
344 pub cache_control: Option<CacheControl>,
345}
346
347#[serde_with::skip_serializing_none]
349#[derive(Debug, Clone, Serialize, Deserialize)]
350pub struct SearchResultBlock {
351 pub source: String,
353
354 pub title: String,
356
357 pub content: Vec<TextBlock>,
359
360 pub cache_control: Option<CacheControl>,
362
363 pub citations: Option<CitationsConfig>,
365}
366
367#[derive(Debug, Clone, Serialize, Deserialize)]
369pub struct WebSearchToolResultBlock {
370 pub tool_use_id: String,
372
373 pub content: WebSearchToolResultContent,
375
376 #[serde(skip_serializing_if = "Option::is_none")]
378 pub cache_control: Option<CacheControl>,
379}
380
381#[derive(Debug, Clone, Serialize, Deserialize)]
383#[serde(untagged)]
384pub enum WebSearchToolResultContent {
385 Results(Vec<WebSearchResultBlock>),
386 Error(WebSearchToolResultError),
387}
388
389#[derive(Debug, Clone, Serialize, Deserialize)]
391pub struct WebSearchResultBlock {
392 pub title: String,
394
395 pub url: String,
397
398 pub encrypted_content: String,
400
401 #[serde(skip_serializing_if = "Option::is_none")]
403 pub page_age: Option<String>,
404}
405
406#[derive(Debug, Clone, Serialize, Deserialize)]
408pub struct WebSearchToolResultError {
409 #[serde(rename = "type")]
410 pub error_type: String,
411 pub error_code: WebSearchToolResultErrorCode,
412}
413
414#[derive(Debug, Clone, Serialize, Deserialize)]
416#[serde(rename_all = "snake_case")]
417pub enum WebSearchToolResultErrorCode {
418 InvalidToolInput,
419 Unavailable,
420 MaxUsesExceeded,
421 TooManyRequests,
422 QueryTooLong,
423}
424
425#[derive(Debug, Clone, Serialize, Deserialize)]
427#[serde(tag = "type", rename_all = "snake_case")]
428pub enum CacheControl {
429 Ephemeral,
430}
431
432#[derive(Debug, Clone, Serialize, Deserialize)]
434pub struct CitationsConfig {
435 #[serde(skip_serializing_if = "Option::is_none")]
436 pub enabled: Option<bool>,
437}
438
439#[derive(Debug, Clone, Serialize, Deserialize)]
441#[serde(tag = "type", rename_all = "snake_case")]
442#[expect(
443 clippy::enum_variant_names,
444 reason = "variant names match the OpenAI API citation type discriminators (char_location, page_location, etc.)"
445)]
446pub enum Citation {
447 CharLocation(CharLocationCitation),
448 PageLocation(PageLocationCitation),
449 ContentBlockLocation(ContentBlockLocationCitation),
450 WebSearchResultLocation(WebSearchResultLocationCitation),
451 SearchResultLocation(SearchResultLocationCitation),
452}
453
454#[derive(Debug, Clone, Serialize, Deserialize)]
456pub struct CharLocationCitation {
457 pub cited_text: String,
458 pub document_index: u32,
459 pub document_title: Option<String>,
460 pub start_char_index: u32,
461 pub end_char_index: u32,
462 #[serde(skip_serializing_if = "Option::is_none")]
463 pub file_id: Option<String>,
464}
465
466#[derive(Debug, Clone, Serialize, Deserialize)]
468pub struct PageLocationCitation {
469 pub cited_text: String,
470 pub document_index: u32,
471 pub document_title: Option<String>,
472 pub start_page_number: u32,
473 pub end_page_number: u32,
474}
475
476#[derive(Debug, Clone, Serialize, Deserialize)]
478pub struct ContentBlockLocationCitation {
479 pub cited_text: String,
480 pub document_index: u32,
481 pub document_title: Option<String>,
482 pub start_block_index: u32,
483 pub end_block_index: u32,
484}
485
486#[derive(Debug, Clone, Serialize, Deserialize)]
488pub struct WebSearchResultLocationCitation {
489 pub cited_text: String,
490 pub url: String,
491 pub title: Option<String>,
492 pub encrypted_index: String,
493}
494
495#[derive(Debug, Clone, Serialize, Deserialize)]
497pub struct SearchResultLocationCitation {
498 pub cited_text: String,
499 pub search_result_index: u32,
500 pub source: String,
501 pub title: Option<String>,
502 pub start_block_index: u32,
503 pub end_block_index: u32,
504}
505
506#[derive(Debug, Clone, Serialize, Deserialize)]
512#[serde(untagged)]
513pub enum Tool {
514 McpToolset(McpToolset),
516 Custom(CustomTool),
518 Bash(BashTool),
520 TextEditor(TextEditorTool),
522 WebSearch(WebSearchTool),
524}
525
526#[serde_with::skip_serializing_none]
528#[derive(Debug, Clone, Serialize, Deserialize)]
529pub struct CustomTool {
530 pub name: String,
532
533 #[serde(rename = "type")]
535 pub tool_type: Option<String>,
536
537 pub description: Option<String>,
539
540 pub input_schema: InputSchema,
542
543 pub cache_control: Option<CacheControl>,
545}
546
547#[serde_with::skip_serializing_none]
549#[derive(Debug, Clone, Serialize, Deserialize)]
550pub struct InputSchema {
551 #[serde(rename = "type")]
552 pub schema_type: String,
553
554 pub properties: Option<HashMap<String, Value>>,
555
556 pub required: Option<Vec<String>>,
557
558 #[serde(flatten)]
560 pub additional: HashMap<String, Value>,
561}
562
563#[derive(Debug, Clone, Serialize, Deserialize)]
565pub struct BashTool {
566 #[serde(rename = "type")]
567 pub tool_type: String, pub name: String, #[serde(skip_serializing_if = "Option::is_none")]
572 pub cache_control: Option<CacheControl>,
573}
574
575#[derive(Debug, Clone, Serialize, Deserialize)]
577pub struct TextEditorTool {
578 #[serde(rename = "type")]
579 pub tool_type: String, pub name: String, #[serde(skip_serializing_if = "Option::is_none")]
584 pub cache_control: Option<CacheControl>,
585}
586
587#[serde_with::skip_serializing_none]
589#[derive(Debug, Clone, Serialize, Deserialize)]
590pub struct WebSearchTool {
591 #[serde(rename = "type")]
592 pub tool_type: String, pub name: String, pub allowed_domains: Option<Vec<String>>,
597
598 pub blocked_domains: Option<Vec<String>>,
599
600 pub max_uses: Option<u32>,
601
602 pub user_location: Option<UserLocation>,
603
604 pub cache_control: Option<CacheControl>,
605}
606
607#[serde_with::skip_serializing_none]
609#[derive(Debug, Clone, Serialize, Deserialize)]
610pub struct UserLocation {
611 #[serde(rename = "type")]
612 pub location_type: String, pub city: Option<String>,
615
616 pub region: Option<String>,
617
618 pub country: Option<String>,
619
620 pub timezone: Option<String>,
621}
622
623#[serde_with::skip_serializing_none]
629#[derive(Debug, Clone, Serialize, Deserialize)]
630#[serde(tag = "type", rename_all = "snake_case")]
631pub enum ToolChoice {
632 Auto {
634 disable_parallel_tool_use: Option<bool>,
635 },
636 Any {
638 disable_parallel_tool_use: Option<bool>,
639 },
640 Tool {
642 name: String,
643 disable_parallel_tool_use: Option<bool>,
644 },
645 None,
647}
648
649#[derive(Debug, Clone, Serialize, Deserialize)]
655#[serde(tag = "type", rename_all = "snake_case")]
656pub enum ThinkingConfig {
657 Enabled {
659 budget_tokens: u32,
661 },
662 Disabled,
664}
665
666#[derive(Debug, Clone, Serialize, Deserialize)]
672pub struct Message {
673 pub id: String,
675
676 #[serde(rename = "type")]
678 pub message_type: String,
679
680 pub role: String,
682
683 pub content: Vec<ContentBlock>,
685
686 pub model: String,
688
689 pub stop_reason: Option<StopReason>,
691
692 pub stop_sequence: Option<String>,
694
695 pub usage: Usage,
697}
698
699#[derive(Debug, Clone, Serialize, Deserialize)]
701#[serde(tag = "type", rename_all = "snake_case")]
702pub enum ContentBlock {
703 Text {
705 text: String,
706 #[serde(skip_serializing_if = "Option::is_none")]
707 citations: Option<Vec<Citation>>,
708 },
709 ToolUse {
711 id: String,
712 name: String,
713 input: Value,
714 },
715 Thinking { thinking: String, signature: String },
717 RedactedThinking { data: String },
719 ServerToolUse {
721 id: String,
722 name: String,
723 input: Value,
724 },
725 WebSearchToolResult {
727 tool_use_id: String,
728 content: WebSearchToolResultContent,
729 },
730 McpToolUse {
732 id: String,
733 name: String,
734 server_name: String,
735 input: Value,
736 },
737 McpToolResult {
739 tool_use_id: String,
740 content: Option<ToolResultContent>,
741 is_error: Option<bool>,
742 },
743}
744
745#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
747#[serde(rename_all = "snake_case")]
748pub enum StopReason {
749 EndTurn,
751 MaxTokens,
753 StopSequence,
755 ToolUse,
757 PauseTurn,
759 Refusal,
761}
762
763#[serde_with::skip_serializing_none]
765#[derive(Debug, Clone, Serialize, Deserialize)]
766pub struct Usage {
767 pub input_tokens: u32,
769
770 pub output_tokens: u32,
772
773 pub cache_creation_input_tokens: Option<u32>,
775
776 pub cache_read_input_tokens: Option<u32>,
778
779 pub cache_creation: Option<CacheCreation>,
781
782 pub server_tool_use: Option<ServerToolUsage>,
784
785 pub service_tier: Option<String>,
787}
788
789#[derive(Debug, Clone, Serialize, Deserialize)]
791pub struct CacheCreation {
792 #[serde(flatten)]
793 pub tokens_by_ttl: HashMap<String, u32>,
794}
795
796#[derive(Debug, Clone, Serialize, Deserialize)]
798pub struct ServerToolUsage {
799 pub web_search_requests: u32,
800}
801
802#[derive(Debug, Clone, Serialize, Deserialize)]
808#[serde(tag = "type", rename_all = "snake_case")]
809pub enum MessageStreamEvent {
810 MessageStart { message: Message },
812 MessageDelta {
814 delta: MessageDelta,
815 usage: MessageDeltaUsage,
816 },
817 MessageStop,
819 ContentBlockStart {
821 index: u32,
822 content_block: ContentBlock,
823 },
824 ContentBlockDelta {
826 index: u32,
827 delta: ContentBlockDelta,
828 },
829 ContentBlockStop { index: u32 },
831 Ping,
833 Error { error: ErrorResponse },
835}
836
837#[serde_with::skip_serializing_none]
839#[derive(Debug, Clone, Serialize, Deserialize)]
840pub struct MessageDelta {
841 pub stop_reason: Option<StopReason>,
842
843 pub stop_sequence: Option<String>,
844}
845
846#[serde_with::skip_serializing_none]
848#[derive(Debug, Clone, Serialize, Deserialize)]
849pub struct MessageDeltaUsage {
850 pub output_tokens: u32,
851
852 pub input_tokens: Option<u32>,
853
854 pub cache_creation_input_tokens: Option<u32>,
855
856 pub cache_read_input_tokens: Option<u32>,
857
858 pub server_tool_use: Option<ServerToolUsage>,
859}
860
861#[derive(Debug, Clone, Serialize, Deserialize)]
863#[serde(tag = "type", rename_all = "snake_case")]
864#[expect(
865 clippy::enum_variant_names,
866 reason = "variant names match the OpenAI/Anthropic streaming delta type discriminators (text_delta, input_json_delta, etc.)"
867)]
868pub enum ContentBlockDelta {
869 TextDelta { text: String },
871 InputJsonDelta { partial_json: String },
873 ThinkingDelta { thinking: String },
875 SignatureDelta { signature: String },
877 CitationsDelta { citation: Citation },
879}
880
881#[derive(Debug, Clone, Serialize, Deserialize)]
887pub struct ErrorResponse {
888 #[serde(rename = "type")]
889 pub error_type: String,
890
891 pub message: String,
892}
893
894#[derive(Debug, Clone, Serialize, Deserialize)]
896#[serde(tag = "type", rename_all = "snake_case")]
897#[expect(
898 clippy::enum_variant_names,
899 reason = "variant names match the OpenAI API error type discriminators (invalid_request_error, authentication_error, etc.)"
900)]
901pub enum ApiError {
902 InvalidRequestError { message: String },
903 AuthenticationError { message: String },
904 BillingError { message: String },
905 PermissionError { message: String },
906 NotFoundError { message: String },
907 RateLimitError { message: String },
908 TimeoutError { message: String },
909 ApiError { message: String },
910 OverloadedError { message: String },
911}
912
913#[serde_with::skip_serializing_none]
919#[derive(Debug, Clone, Serialize, Deserialize)]
920pub struct CountMessageTokensRequest {
921 pub model: String,
923
924 pub messages: Vec<InputMessage>,
926
927 pub system: Option<SystemContent>,
929
930 pub thinking: Option<ThinkingConfig>,
932
933 pub tool_choice: Option<ToolChoice>,
935
936 pub tools: Option<Vec<Tool>>,
938}
939
940#[derive(Debug, Clone, Serialize, Deserialize)]
942pub struct CountMessageTokensResponse {
943 pub input_tokens: u32,
944}
945
946#[derive(Debug, Clone, Serialize, Deserialize)]
952pub struct ModelInfo {
953 #[serde(rename = "type")]
955 pub model_type: String,
956
957 pub id: String,
959
960 pub display_name: String,
962
963 pub created_at: String,
965}
966
967#[derive(Debug, Clone, Serialize, Deserialize)]
969pub struct ListModelsResponse {
970 pub data: Vec<ModelInfo>,
971 pub has_more: bool,
972 pub first_id: Option<String>,
973 pub last_id: Option<String>,
974}
975
976#[serde_with::skip_serializing_none]
982#[derive(Debug, Clone, Serialize, Deserialize)]
983pub struct ContainerConfig {
984 pub id: Option<String>,
986
987 pub skills: Option<Vec<String>>,
989}
990
991#[serde_with::skip_serializing_none]
993#[derive(Debug, Clone, Serialize, Deserialize)]
994pub struct McpServerConfig {
995 pub name: String,
997
998 pub url: String,
1000
1001 pub authorization_token: Option<String>,
1003
1004 pub tool_configuration: Option<McpToolConfiguration>,
1006}
1007
1008#[serde_with::skip_serializing_none]
1010#[derive(Debug, Clone, Serialize, Deserialize)]
1011pub struct McpToolConfiguration {
1012 pub enabled: Option<bool>,
1014
1015 pub allowed_tools: Option<Vec<String>>,
1017}
1018
1019#[derive(Debug, Clone, Serialize, Deserialize)]
1025pub struct McpToolUseBlock {
1026 pub id: String,
1028
1029 pub name: String,
1031
1032 pub server_name: String,
1034
1035 pub input: Value,
1037
1038 #[serde(skip_serializing_if = "Option::is_none")]
1040 pub cache_control: Option<CacheControl>,
1041}
1042
1043#[serde_with::skip_serializing_none]
1045#[derive(Debug, Clone, Serialize, Deserialize)]
1046pub struct McpToolResultBlock {
1047 pub tool_use_id: String,
1049
1050 pub content: Option<ToolResultContent>,
1052
1053 pub is_error: Option<bool>,
1055
1056 pub cache_control: Option<CacheControl>,
1058}
1059
1060#[serde_with::skip_serializing_none]
1062#[derive(Debug, Clone, Serialize, Deserialize)]
1063pub struct McpToolset {
1064 #[serde(rename = "type")]
1065 pub toolset_type: String, pub mcp_server_name: String,
1069
1070 pub default_config: Option<McpToolDefaultConfig>,
1072
1073 pub configs: Option<HashMap<String, McpToolConfig>>,
1075
1076 pub cache_control: Option<CacheControl>,
1078}
1079
1080#[serde_with::skip_serializing_none]
1082#[derive(Debug, Clone, Serialize, Deserialize)]
1083pub struct McpToolDefaultConfig {
1084 pub enabled: Option<bool>,
1086
1087 pub defer_loading: Option<bool>,
1089}
1090
1091#[serde_with::skip_serializing_none]
1093#[derive(Debug, Clone, Serialize, Deserialize)]
1094pub struct McpToolConfig {
1095 pub enabled: Option<bool>,
1097
1098 pub defer_loading: Option<bool>,
1100}
1101
1102#[serde_with::skip_serializing_none]
1108#[derive(Debug, Clone, Serialize, Deserialize)]
1109pub struct CodeExecutionTool {
1110 #[serde(rename = "type")]
1111 pub tool_type: String, pub name: String, pub allowed_callers: Option<Vec<String>>,
1117
1118 pub defer_loading: Option<bool>,
1120
1121 pub strict: Option<bool>,
1123
1124 pub cache_control: Option<CacheControl>,
1126}
1127
1128#[derive(Debug, Clone, Serialize, Deserialize)]
1130pub struct CodeExecutionResultBlock {
1131 pub stdout: String,
1133
1134 pub stderr: String,
1136
1137 pub return_code: i32,
1139
1140 pub content: Vec<CodeExecutionOutputBlock>,
1142}
1143
1144#[derive(Debug, Clone, Serialize, Deserialize)]
1146pub struct CodeExecutionOutputBlock {
1147 #[serde(rename = "type")]
1148 pub block_type: String, pub file_id: String,
1152}
1153
1154#[derive(Debug, Clone, Serialize, Deserialize)]
1156pub struct CodeExecutionToolResultBlock {
1157 pub tool_use_id: String,
1159
1160 pub content: CodeExecutionToolResultContent,
1162
1163 #[serde(skip_serializing_if = "Option::is_none")]
1165 pub cache_control: Option<CacheControl>,
1166}
1167
1168#[derive(Debug, Clone, Serialize, Deserialize)]
1170#[serde(untagged)]
1171pub enum CodeExecutionToolResultContent {
1172 Success(CodeExecutionResultBlock),
1173 Error(CodeExecutionToolResultError),
1174}
1175
1176#[derive(Debug, Clone, Serialize, Deserialize)]
1178pub struct CodeExecutionToolResultError {
1179 #[serde(rename = "type")]
1180 pub error_type: String, pub error_code: CodeExecutionToolResultErrorCode,
1183}
1184
1185#[derive(Debug, Clone, Serialize, Deserialize)]
1187#[serde(rename_all = "snake_case")]
1188pub enum CodeExecutionToolResultErrorCode {
1189 Unavailable,
1190 CodeExecutionExceededTimeout,
1191 ContainerExpired,
1192 InvalidToolInput,
1193}
1194
1195#[derive(Debug, Clone, Serialize, Deserialize)]
1197pub struct BashCodeExecutionResultBlock {
1198 pub stdout: String,
1200
1201 pub stderr: String,
1203
1204 pub return_code: i32,
1206
1207 pub content: Vec<BashCodeExecutionOutputBlock>,
1209}
1210
1211#[derive(Debug, Clone, Serialize, Deserialize)]
1213pub struct BashCodeExecutionOutputBlock {
1214 #[serde(rename = "type")]
1215 pub block_type: String, pub file_id: String,
1219}
1220
1221#[derive(Debug, Clone, Serialize, Deserialize)]
1223pub struct BashCodeExecutionToolResultBlock {
1224 pub tool_use_id: String,
1226
1227 pub content: BashCodeExecutionToolResultContent,
1229
1230 #[serde(skip_serializing_if = "Option::is_none")]
1232 pub cache_control: Option<CacheControl>,
1233}
1234
1235#[derive(Debug, Clone, Serialize, Deserialize)]
1237#[serde(untagged)]
1238pub enum BashCodeExecutionToolResultContent {
1239 Success(BashCodeExecutionResultBlock),
1240 Error(BashCodeExecutionToolResultError),
1241}
1242
1243#[derive(Debug, Clone, Serialize, Deserialize)]
1245pub struct BashCodeExecutionToolResultError {
1246 #[serde(rename = "type")]
1247 pub error_type: String, pub error_code: BashCodeExecutionToolResultErrorCode,
1250}
1251
1252#[derive(Debug, Clone, Serialize, Deserialize)]
1254#[serde(rename_all = "snake_case")]
1255pub enum BashCodeExecutionToolResultErrorCode {
1256 Unavailable,
1257 CodeExecutionExceededTimeout,
1258 ContainerExpired,
1259 InvalidToolInput,
1260}
1261
1262#[derive(Debug, Clone, Serialize, Deserialize)]
1264pub struct TextEditorCodeExecutionToolResultBlock {
1265 pub tool_use_id: String,
1267
1268 pub content: TextEditorCodeExecutionToolResultContent,
1270
1271 #[serde(skip_serializing_if = "Option::is_none")]
1273 pub cache_control: Option<CacheControl>,
1274}
1275
1276#[derive(Debug, Clone, Serialize, Deserialize)]
1278#[serde(untagged)]
1279pub enum TextEditorCodeExecutionToolResultContent {
1280 CreateResult(TextEditorCodeExecutionCreateResultBlock),
1281 StrReplaceResult(TextEditorCodeExecutionStrReplaceResultBlock),
1282 ViewResult(TextEditorCodeExecutionViewResultBlock),
1283 Error(TextEditorCodeExecutionToolResultError),
1284}
1285
1286#[derive(Debug, Clone, Serialize, Deserialize)]
1288pub struct TextEditorCodeExecutionCreateResultBlock {
1289 #[serde(rename = "type")]
1290 pub block_type: String, }
1292
1293#[derive(Debug, Clone, Serialize, Deserialize)]
1295pub struct TextEditorCodeExecutionStrReplaceResultBlock {
1296 #[serde(rename = "type")]
1297 pub block_type: String, #[serde(skip_serializing_if = "Option::is_none")]
1301 pub snippet: Option<String>,
1302}
1303
1304#[derive(Debug, Clone, Serialize, Deserialize)]
1306pub struct TextEditorCodeExecutionViewResultBlock {
1307 #[serde(rename = "type")]
1308 pub block_type: String, pub content: String,
1312}
1313
1314#[derive(Debug, Clone, Serialize, Deserialize)]
1316pub struct TextEditorCodeExecutionToolResultError {
1317 #[serde(rename = "type")]
1318 pub error_type: String,
1319
1320 pub error_code: TextEditorCodeExecutionToolResultErrorCode,
1321}
1322
1323#[derive(Debug, Clone, Serialize, Deserialize)]
1325#[serde(rename_all = "snake_case")]
1326pub enum TextEditorCodeExecutionToolResultErrorCode {
1327 Unavailable,
1328 InvalidToolInput,
1329 FileNotFound,
1330 ContainerExpired,
1331}
1332
1333#[serde_with::skip_serializing_none]
1339#[derive(Debug, Clone, Serialize, Deserialize)]
1340pub struct WebFetchTool {
1341 #[serde(rename = "type")]
1342 pub tool_type: String, pub name: String, pub allowed_callers: Option<Vec<String>>,
1348
1349 pub max_uses: Option<u32>,
1351
1352 pub cache_control: Option<CacheControl>,
1354}
1355
1356#[derive(Debug, Clone, Serialize, Deserialize)]
1358pub struct WebFetchResultBlock {
1359 #[serde(rename = "type")]
1360 pub block_type: String, pub url: String,
1364
1365 pub content: DocumentBlock,
1367
1368 #[serde(skip_serializing_if = "Option::is_none")]
1370 pub retrieved_at: Option<String>,
1371}
1372
1373#[derive(Debug, Clone, Serialize, Deserialize)]
1375pub struct WebFetchToolResultBlock {
1376 pub tool_use_id: String,
1378
1379 pub content: WebFetchToolResultContent,
1381
1382 #[serde(skip_serializing_if = "Option::is_none")]
1384 pub cache_control: Option<CacheControl>,
1385}
1386
1387#[derive(Debug, Clone, Serialize, Deserialize)]
1389#[serde(untagged)]
1390pub enum WebFetchToolResultContent {
1391 Success(WebFetchResultBlock),
1392 Error(WebFetchToolResultError),
1393}
1394
1395#[derive(Debug, Clone, Serialize, Deserialize)]
1397pub struct WebFetchToolResultError {
1398 #[serde(rename = "type")]
1399 pub error_type: String, pub error_code: WebFetchToolResultErrorCode,
1402}
1403
1404#[derive(Debug, Clone, Serialize, Deserialize)]
1406#[serde(rename_all = "snake_case")]
1407pub enum WebFetchToolResultErrorCode {
1408 InvalidToolInput,
1409 Unavailable,
1410 MaxUsesExceeded,
1411 TooManyRequests,
1412 UrlNotAllowed,
1413 FetchFailed,
1414 ContentTooLarge,
1415}
1416
1417#[serde_with::skip_serializing_none]
1423#[derive(Debug, Clone, Serialize, Deserialize)]
1424pub struct ToolSearchTool {
1425 #[serde(rename = "type")]
1426 pub tool_type: String, pub name: String,
1429
1430 pub allowed_callers: Option<Vec<String>>,
1432
1433 pub cache_control: Option<CacheControl>,
1435}
1436
1437#[derive(Debug, Clone, Serialize, Deserialize)]
1439pub struct ToolReferenceBlock {
1440 #[serde(rename = "type")]
1441 pub block_type: String, pub tool_name: String,
1445
1446 #[serde(skip_serializing_if = "Option::is_none")]
1448 pub description: Option<String>,
1449}
1450
1451#[derive(Debug, Clone, Serialize, Deserialize)]
1453pub struct ToolSearchResultBlock {
1454 #[serde(rename = "type")]
1455 pub block_type: String, pub tool_name: String,
1459
1460 #[serde(skip_serializing_if = "Option::is_none")]
1462 pub score: Option<f64>,
1463}
1464
1465#[derive(Debug, Clone, Serialize, Deserialize)]
1467pub struct ToolSearchToolResultBlock {
1468 pub tool_use_id: String,
1470
1471 pub content: Vec<ToolSearchResultBlock>,
1473
1474 #[serde(skip_serializing_if = "Option::is_none")]
1476 pub cache_control: Option<CacheControl>,
1477}
1478
1479#[derive(Debug, Clone, Serialize, Deserialize)]
1485pub struct ContainerUploadBlock {
1486 #[serde(rename = "type")]
1487 pub block_type: String, pub file_id: String,
1491
1492 pub file_name: String,
1494
1495 #[serde(skip_serializing_if = "Option::is_none")]
1497 pub file_path: Option<String>,
1498}
1499
1500#[serde_with::skip_serializing_none]
1506#[derive(Debug, Clone, Serialize, Deserialize)]
1507pub struct MemoryTool {
1508 #[serde(rename = "type")]
1509 pub tool_type: String, pub name: String, pub allowed_callers: Option<Vec<String>>,
1515
1516 pub defer_loading: Option<bool>,
1518
1519 pub strict: Option<bool>,
1521
1522 pub input_examples: Option<Vec<Value>>,
1524
1525 pub cache_control: Option<CacheControl>,
1527}
1528
1529#[serde_with::skip_serializing_none]
1535#[derive(Debug, Clone, Serialize, Deserialize)]
1536pub struct ComputerUseTool {
1537 #[serde(rename = "type")]
1538 pub tool_type: String, pub name: String, pub display_width_px: u32,
1544
1545 pub display_height_px: u32,
1547
1548 pub display_number: Option<u32>,
1550
1551 pub allowed_callers: Option<Vec<String>>,
1553
1554 pub cache_control: Option<CacheControl>,
1556}
1557
1558#[derive(Debug, Clone, Serialize, Deserialize)]
1564#[serde(tag = "type", rename_all = "snake_case")]
1565pub enum BetaInputContentBlock {
1566 Text(TextBlock),
1568 Image(ImageBlock),
1569 Document(DocumentBlock),
1570 ToolUse(ToolUseBlock),
1571 ToolResult(ToolResultBlock),
1572 Thinking(ThinkingBlock),
1573 RedactedThinking(RedactedThinkingBlock),
1574 ServerToolUse(ServerToolUseBlock),
1575 SearchResult(SearchResultBlock),
1576 WebSearchToolResult(WebSearchToolResultBlock),
1577
1578 McpToolUse(McpToolUseBlock),
1580 McpToolResult(McpToolResultBlock),
1581
1582 CodeExecutionToolResult(CodeExecutionToolResultBlock),
1584 BashCodeExecutionToolResult(BashCodeExecutionToolResultBlock),
1585 TextEditorCodeExecutionToolResult(TextEditorCodeExecutionToolResultBlock),
1586
1587 WebFetchToolResult(WebFetchToolResultBlock),
1589
1590 ToolSearchToolResult(ToolSearchToolResultBlock),
1592 ToolReference(ToolReferenceBlock),
1593
1594 ContainerUpload(ContainerUploadBlock),
1596}
1597
1598#[serde_with::skip_serializing_none]
1600#[derive(Debug, Clone, Serialize, Deserialize)]
1601#[serde(tag = "type", rename_all = "snake_case")]
1602pub enum BetaContentBlock {
1603 Text {
1605 text: String,
1606 citations: Option<Vec<Citation>>,
1607 },
1608 ToolUse {
1609 id: String,
1610 name: String,
1611 input: Value,
1612 },
1613 Thinking {
1614 thinking: String,
1615 signature: String,
1616 },
1617 RedactedThinking {
1618 data: String,
1619 },
1620 ServerToolUse {
1621 id: String,
1622 name: String,
1623 input: Value,
1624 },
1625 WebSearchToolResult {
1626 tool_use_id: String,
1627 content: WebSearchToolResultContent,
1628 },
1629
1630 McpToolUse {
1632 id: String,
1633 name: String,
1634 server_name: String,
1635 input: Value,
1636 },
1637 McpToolResult {
1638 tool_use_id: String,
1639 content: Option<ToolResultContent>,
1640 is_error: Option<bool>,
1641 },
1642
1643 CodeExecutionToolResult {
1645 tool_use_id: String,
1646 content: CodeExecutionToolResultContent,
1647 },
1648 BashCodeExecutionToolResult {
1649 tool_use_id: String,
1650 content: BashCodeExecutionToolResultContent,
1651 },
1652 TextEditorCodeExecutionToolResult {
1653 tool_use_id: String,
1654 content: TextEditorCodeExecutionToolResultContent,
1655 },
1656
1657 WebFetchToolResult {
1659 tool_use_id: String,
1660 content: WebFetchToolResultContent,
1661 },
1662
1663 ToolSearchToolResult {
1665 tool_use_id: String,
1666 content: Vec<ToolSearchResultBlock>,
1667 },
1668 ToolReference {
1669 tool_name: String,
1670 description: Option<String>,
1671 },
1672
1673 ContainerUpload {
1675 file_id: String,
1676 file_name: String,
1677 file_path: Option<String>,
1678 },
1679}
1680
1681#[derive(Debug, Clone, Serialize, Deserialize)]
1683#[serde(untagged)]
1684pub enum BetaTool {
1685 Custom(CustomTool),
1687 Bash(BashTool),
1688 TextEditor(TextEditorTool),
1689 WebSearch(WebSearchTool),
1690
1691 CodeExecution(CodeExecutionTool),
1693 McpToolset(McpToolset),
1694 WebFetch(WebFetchTool),
1695 ToolSearch(ToolSearchTool),
1696 Memory(MemoryTool),
1697 ComputerUse(ComputerUseTool),
1698}
1699
1700#[derive(Debug, Clone, Serialize, Deserialize)]
1702#[serde(rename_all = "snake_case")]
1703pub enum BetaServerToolName {
1704 WebSearch,
1705 WebFetch,
1706 CodeExecution,
1707 BashCodeExecution,
1708 TextEditorCodeExecution,
1709 ToolSearchToolRegex,
1710 ToolSearchToolBm25,
1711}
1712
1713#[derive(Debug, Clone, Serialize, Deserialize)]
1715#[serde(tag = "type", rename_all = "snake_case")]
1716pub enum ServerToolCaller {
1717 Direct,
1719 #[serde(rename = "code_execution_20250825")]
1721 CodeExecution20250825,
1722}