claude_codes/io/
content_blocks.rs1use serde::{Deserialize, Deserializer, Serialize};
2use serde_json::Value;
3
4pub(crate) fn deserialize_content_blocks<'de, D>(
6 deserializer: D,
7) -> Result<Vec<ContentBlock>, D::Error>
8where
9 D: Deserializer<'de>,
10{
11 let value: Value = Value::deserialize(deserializer)?;
12 match value {
13 Value::String(s) => Ok(vec![ContentBlock::Text(TextBlock { text: s })]),
14 Value::Array(_) => serde_json::from_value(value).map_err(serde::de::Error::custom),
15 _ => Err(serde::de::Error::custom(
16 "content must be a string or array",
17 )),
18 }
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23#[serde(tag = "type", rename_all = "snake_case")]
24pub enum ContentBlock {
25 Text(TextBlock),
26 Image(ImageBlock),
27 Thinking(ThinkingBlock),
28 ToolUse(ToolUseBlock),
29 ToolResult(ToolResultBlock),
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct TextBlock {
35 pub text: String,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct ImageBlock {
41 pub source: ImageSource,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct ImageSource {
47 #[serde(rename = "type")]
48 pub source_type: String, pub media_type: String, pub data: String, }
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct ThinkingBlock {
56 pub thinking: String,
57 pub signature: String,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct ToolUseBlock {
63 pub id: String,
64 pub name: String,
65 pub input: Value,
66}
67
68impl ToolUseBlock {
69 pub fn typed_input(&self) -> Option<crate::tool_inputs::ToolInput> {
91 serde_json::from_value(self.input.clone()).ok()
92 }
93
94 pub fn try_typed_input(&self) -> Result<crate::tool_inputs::ToolInput, serde_json::Error> {
98 serde_json::from_value(self.input.clone())
99 }
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct ToolResultBlock {
105 pub tool_use_id: String,
106 #[serde(skip_serializing_if = "Option::is_none")]
107 pub content: Option<ToolResultContent>,
108 #[serde(skip_serializing_if = "Option::is_none")]
109 pub is_error: Option<bool>,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
114#[serde(untagged)]
115pub enum ToolResultContent {
116 Text(String),
117 Structured(Vec<Value>),
118}