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