claude_codes/io/
claude_input.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use uuid::Uuid;
4
5use super::content_blocks::{ContentBlock, ImageBlock, ImageSource, TextBlock};
6use super::control::{ControlRequest, ControlResponse};
7use super::message_types::{MessageContent, UserMessage};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11#[serde(tag = "type", rename_all = "snake_case")]
12pub enum ClaudeInput {
13 User(UserMessage),
15
16 ControlRequest(ControlRequest),
18
19 ControlResponse(ControlResponse),
21
22 #[serde(untagged)]
24 Raw(Value),
25}
26
27impl ClaudeInput {
28 pub fn user_message(text: impl Into<String>, session_id: Uuid) -> Self {
30 ClaudeInput::User(UserMessage {
31 message: MessageContent {
32 role: "user".to_string(),
33 content: vec![ContentBlock::Text(TextBlock { text: text.into() })],
34 },
35 session_id: Some(session_id),
36 })
37 }
38
39 pub fn user_message_blocks(blocks: Vec<ContentBlock>, session_id: Uuid) -> Self {
41 ClaudeInput::User(UserMessage {
42 message: MessageContent {
43 role: "user".to_string(),
44 content: blocks,
45 },
46 session_id: Some(session_id),
47 })
48 }
49
50 pub fn user_message_with_image(
53 image_data: String,
54 media_type: String,
55 text: Option<String>,
56 session_id: Uuid,
57 ) -> Result<Self, String> {
58 let valid_types = ["image/jpeg", "image/png", "image/gif", "image/webp"];
60
61 if !valid_types.contains(&media_type.as_str()) {
62 return Err(format!(
63 "Invalid media type '{}'. Only JPEG, PNG, GIF, and WebP are supported.",
64 media_type
65 ));
66 }
67
68 let mut blocks = vec![ContentBlock::Image(ImageBlock {
69 source: ImageSource {
70 source_type: "base64".to_string(),
71 media_type,
72 data: image_data,
73 },
74 })];
75
76 if let Some(text_content) = text {
77 blocks.push(ContentBlock::Text(TextBlock { text: text_content }));
78 }
79
80 Ok(Self::user_message_blocks(blocks, session_id))
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn test_serialize_user_message() {
90 let session_uuid = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
91 let input = ClaudeInput::user_message("Hello, Claude!", session_uuid);
92 let json = serde_json::to_string(&input).unwrap();
93 assert!(json.contains("\"type\":\"user\""));
94 assert!(json.contains("\"role\":\"user\""));
95 assert!(json.contains("\"text\":\"Hello, Claude!\""));
96 assert!(json.contains("550e8400-e29b-41d4-a716-446655440000"));
97 }
98}