gproxy_protocol/protocol/claude/common/blocks/
content.rs1use serde::{Deserialize, Serialize};
2
3use super::super::server_tools::*;
4use super::super::{JsonObject, MessageRole, StringOrArray, TypedObject};
5use super::*;
6use crate::protocol::extensible::type_tag_union_deserialize;
7
8pub type MessageContent = StringOrArray<ContentBlockParam>;
9pub type SystemPrompt = StringOrArray<TextBlock>;
10pub type ContentBlock = ResponseContentBlock;
11
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
13#[non_exhaustive]
14pub struct MessageParam {
15 pub role: MessageRole,
16 pub content: MessageContent,
17 #[serde(default, flatten, skip_serializing_if = "JsonObject::is_empty")]
18 pub extra: JsonObject,
19}
20
21#[derive(Debug, Clone, PartialEq, Serialize)]
25#[serde(untagged)]
26#[non_exhaustive]
27pub enum ContentBlockParam {
28 Text(TextBlock),
29 Image(ImageBlock),
30 Document(DocumentBlock),
31 SearchResult(SearchResultBlock),
32 Thinking(ThinkingBlock),
33 RedactedThinking(RedactedThinkingBlock),
34 ToolUse(ToolUseBlock),
35 ToolResult(ToolResultBlock),
36 ServerToolUse(ServerToolUseBlock),
37 WebSearchToolResult(WebSearchToolResultBlock),
38 WebFetchToolResult(WebFetchToolResultBlock),
39 AdvisorToolResult(AdvisorToolResultBlock),
40 CodeExecutionToolResult(CodeExecutionToolResultBlock),
41 BashCodeExecutionToolResult(BashCodeExecutionToolResultBlock),
42 TextEditorCodeExecutionToolResult(TextEditorCodeExecutionToolResultBlock),
43 ToolSearchToolResult(ToolSearchToolResultBlock),
44 McpToolUse(McpToolUseBlock),
45 McpToolResult(McpToolResultBlock),
46 ContainerUpload(ContainerUploadBlock),
47 Compaction(CompactionBlock),
48 MidConversationSystem(MidConversationSystemBlock),
49 ToolAddition(ToolAdditionBlock),
50 ToolRemoval(ToolRemovalBlock),
51 Fallback(FallbackBlock),
52 Raw(TypedObject),
53}
54
55type_tag_union_deserialize!(ContentBlockParam {
56 "text" => Text,
57 "image" => Image,
58 "document" => Document,
59 "search_result" => SearchResult,
60 "thinking" => Thinking,
61 "redacted_thinking" => RedactedThinking,
62 "tool_use" => ToolUse,
63 "tool_result" => ToolResult,
64 "server_tool_use" => ServerToolUse,
65 "web_search_tool_result" => WebSearchToolResult,
66 "web_fetch_tool_result" => WebFetchToolResult,
67 "advisor_tool_result" => AdvisorToolResult,
68 "code_execution_tool_result" => CodeExecutionToolResult,
69 "bash_code_execution_tool_result" => BashCodeExecutionToolResult,
70 "text_editor_code_execution_tool_result" => TextEditorCodeExecutionToolResult,
71 "tool_search_tool_result" => ToolSearchToolResult,
72 "mcp_tool_use" => McpToolUse,
73 "mcp_tool_result" => McpToolResult,
74 "container_upload" => ContainerUpload,
75 "compaction" => Compaction,
76 "mid_conv_system" => MidConversationSystem,
77 "tool_addition" => ToolAddition,
78 "tool_removal" => ToolRemoval,
79 "fallback" => Fallback,
80});
81
82#[derive(Debug, Clone, PartialEq, Serialize)]
83#[serde(untagged)]
84#[non_exhaustive]
85pub enum ResponseContentBlock {
86 Text(ResponseTextBlock),
87 Thinking(ThinkingBlock),
88 RedactedThinking(RedactedThinkingBlock),
89 ToolUse(ResponseToolUseBlock),
90 ServerToolUse(ResponseServerToolUseBlock),
91 WebSearchToolResult(ResponseWebSearchToolResultBlock),
92 WebFetchToolResult(ResponseWebFetchToolResultBlock),
93 AdvisorToolResult(ResponseAdvisorToolResultBlock),
94 CodeExecutionToolResult(ResponseCodeExecutionToolResultBlock),
95 BashCodeExecutionToolResult(ResponseBashCodeExecutionToolResultBlock),
96 TextEditorCodeExecutionToolResult(ResponseTextEditorCodeExecutionToolResultBlock),
97 ToolSearchToolResult(ResponseToolSearchToolResultBlock),
98 McpToolUse(ResponseMcpToolUseBlock),
99 McpToolResult(ResponseMcpToolResultBlock),
100 ContainerUpload(ResponseContainerUploadBlock),
101 Compaction(ResponseCompactionBlock),
102 Fallback(FallbackBlock),
103 Raw(TypedObject),
104}
105
106type_tag_union_deserialize!(ResponseContentBlock {
107 "text" => Text,
108 "thinking" => Thinking,
109 "redacted_thinking" => RedactedThinking,
110 "tool_use" => ToolUse,
111 "server_tool_use" => ServerToolUse,
112 "web_search_tool_result" => WebSearchToolResult,
113 "web_fetch_tool_result" => WebFetchToolResult,
114 "advisor_tool_result" => AdvisorToolResult,
115 "code_execution_tool_result" => CodeExecutionToolResult,
116 "bash_code_execution_tool_result" => BashCodeExecutionToolResult,
117 "text_editor_code_execution_tool_result" => TextEditorCodeExecutionToolResult,
118 "tool_search_tool_result" => ToolSearchToolResult,
119 "mcp_tool_use" => McpToolUse,
120 "mcp_tool_result" => McpToolResult,
121 "container_upload" => ContainerUpload,
122 "compaction" => Compaction,
123 "fallback" => Fallback,
124});
125
126#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
127#[serde(untagged)]
128#[non_exhaustive]
129pub enum ToolResultContent {
130 Text(String),
131 Blocks(Vec<ToolResultContentBlock>),
132 Raw(serde_json::Value),
133}
134
135#[derive(Debug, Clone, PartialEq, Serialize)]
136#[serde(untagged)]
137#[non_exhaustive]
138pub enum ToolResultContentBlock {
139 Text(TextBlock),
140 Image(ImageBlock),
141 SearchResult(SearchResultBlock),
142 Document(DocumentBlock),
143 ToolReference(ToolReferenceBlock),
144 Raw(TypedObject),
145}
146
147type_tag_union_deserialize!(ToolResultContentBlock {
148 "text" => Text,
149 "image" => Image,
150 "search_result" => SearchResult,
151 "document" => Document,
152 "tool_reference" => ToolReference,
153});
154
155pub type McpToolResultContent = StringOrArray<TextBlock>;
156
157#[cfg(test)]
158mod tests {
159 use serde_json::json;
160
161 use super::*;
162
163 #[test]
164 fn tag_dispatch_falls_back_to_raw() {
165 let wire = json!({"type": "hologram", "payload": {"x": 1}});
167 let block: ContentBlockParam = serde_json::from_value(wire.clone()).unwrap();
168 assert!(matches!(block, ContentBlockParam::Raw(_)));
169 assert_eq!(serde_json::to_value(&block).unwrap(), wire);
170
171 let wire = json!({"type": "tool_use", "id": 42});
174 let block: ContentBlockParam = serde_json::from_value(wire.clone()).unwrap();
175 assert!(matches!(block, ContentBlockParam::Raw(_)));
176 assert_eq!(serde_json::to_value(&block).unwrap(), wire);
177 }
178}