claude_api/messages/
input.rs1use serde::{Deserialize, Serialize};
13
14use crate::messages::content::ContentBlock;
15use crate::types::Role;
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
19#[non_exhaustive]
20pub struct MessageInput {
21 pub role: Role,
23 pub content: MessageContent,
25}
26
27impl MessageInput {
28 pub fn user(content: impl Into<MessageContent>) -> Self {
30 Self {
31 role: Role::User,
32 content: content.into(),
33 }
34 }
35
36 pub fn assistant(content: impl Into<MessageContent>) -> Self {
38 Self {
39 role: Role::Assistant,
40 content: content.into(),
41 }
42 }
43}
44
45#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
48#[serde(untagged)]
49pub enum MessageContent {
50 Text(String),
52 Blocks(Vec<ContentBlock>),
54}
55
56impl From<&str> for MessageContent {
57 fn from(s: &str) -> Self {
58 Self::Text(s.to_owned())
59 }
60}
61
62impl From<String> for MessageContent {
63 fn from(s: String) -> Self {
64 Self::Text(s)
65 }
66}
67
68impl From<Vec<ContentBlock>> for MessageContent {
69 fn from(v: Vec<ContentBlock>) -> Self {
70 Self::Blocks(v)
71 }
72}
73
74impl From<ContentBlock> for MessageContent {
75 fn from(b: ContentBlock) -> Self {
76 Self::Blocks(vec![b])
77 }
78}
79
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
85#[serde(untagged)]
86pub enum SystemPrompt {
87 Text(String),
89 Blocks(Vec<ContentBlock>),
91}
92
93impl From<&str> for SystemPrompt {
94 fn from(s: &str) -> Self {
95 Self::Text(s.to_owned())
96 }
97}
98
99impl From<String> for SystemPrompt {
100 fn from(s: String) -> Self {
101 Self::Text(s)
102 }
103}
104
105impl From<Vec<ContentBlock>> for SystemPrompt {
106 fn from(v: Vec<ContentBlock>) -> Self {
107 Self::Blocks(v)
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use pretty_assertions::assert_eq;
115 use serde_json::json;
116
117 #[test]
118 fn message_input_user_with_string_content() {
119 let m = MessageInput::user("hello");
120 assert_eq!(
121 serde_json::to_value(&m).unwrap(),
122 json!({"role": "user", "content": "hello"})
123 );
124 }
125
126 #[test]
127 fn message_input_assistant_with_blocks_content() {
128 let m = MessageInput::assistant(vec![ContentBlock::text("hi")]);
129 assert_eq!(
130 serde_json::to_value(&m).unwrap(),
131 json!({
132 "role": "assistant",
133 "content": [{"type": "text", "text": "hi"}]
134 })
135 );
136 }
137
138 #[test]
139 fn message_content_round_trips_text_and_blocks() {
140 let t: MessageContent = "x".into();
141 assert_eq!(serde_json::to_value(&t).unwrap(), json!("x"));
142
143 let b: MessageContent = ContentBlock::text("y").into();
144 assert_eq!(
145 serde_json::to_value(&b).unwrap(),
146 json!([{"type": "text", "text": "y"}])
147 );
148 }
149
150 #[test]
151 fn system_prompt_text_serializes_as_string() {
152 let s: SystemPrompt = "be concise".into();
153 assert_eq!(serde_json::to_value(&s).unwrap(), json!("be concise"));
154 }
155
156 #[test]
157 fn system_prompt_blocks_serializes_as_array() {
158 let s: SystemPrompt = vec![ContentBlock::text("be concise")].into();
159 assert_eq!(
160 serde_json::to_value(&s).unwrap(),
161 json!([{"type": "text", "text": "be concise"}])
162 );
163 }
164}