alchemy_llm/types/
content.rs1use base64::Engine;
2use serde::{Deserialize, Serialize};
3
4use super::tool_call_id::ToolCallId;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7#[serde(tag = "type", rename_all = "camelCase")]
8pub enum Content {
9 #[serde(rename = "text")]
10 Text {
11 #[serde(flatten)]
12 inner: TextContent,
13 },
14 #[serde(rename = "thinking")]
15 Thinking {
16 #[serde(flatten)]
17 inner: ThinkingContent,
18 },
19 #[serde(rename = "image")]
20 Image {
21 #[serde(flatten)]
22 inner: ImageContent,
23 },
24 #[serde(rename = "toolCall")]
25 ToolCall {
26 #[serde(flatten)]
27 inner: ToolCall,
28 },
29}
30
31impl Content {
32 pub fn text(text: impl Into<String>) -> Self {
33 Self::Text {
34 inner: TextContent {
35 text: text.into(),
36 text_signature: None,
37 },
38 }
39 }
40
41 pub fn thinking(thinking: impl Into<String>) -> Self {
42 Self::Thinking {
43 inner: ThinkingContent {
44 thinking: thinking.into(),
45 thinking_signature: None,
46 },
47 }
48 }
49
50 pub fn tool_call(
51 id: impl Into<ToolCallId>,
52 name: impl Into<String>,
53 arguments: serde_json::Value,
54 ) -> Self {
55 Self::ToolCall {
56 inner: ToolCall {
57 id: id.into(),
58 name: name.into(),
59 arguments,
60 thought_signature: None,
61 },
62 }
63 }
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct TextContent {
68 pub text: String,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 pub text_signature: Option<String>,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct ThinkingContent {
75 pub thinking: String,
76 #[serde(skip_serializing_if = "Option::is_none")]
77 pub thinking_signature: Option<String>,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct ImageContent {
82 pub data: Vec<u8>,
83 pub mime_type: String,
84}
85
86impl ImageContent {
87 pub fn from_base64(data: &str, mime_type: String) -> Result<Self, base64::DecodeError> {
88 Ok(Self {
89 data: base64::engine::general_purpose::STANDARD.decode(data)?,
90 mime_type,
91 })
92 }
93
94 pub fn to_base64(&self) -> String {
95 base64::engine::general_purpose::STANDARD.encode(&self.data)
96 }
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct ToolCall {
101 pub id: ToolCallId,
102 pub name: String,
103 pub arguments: serde_json::Value,
104 #[serde(skip_serializing_if = "Option::is_none")]
105 pub thought_signature: Option<String>,
106}