anthropic_async/resources/
messages.rs1use crate::{
2 client::Client,
3 config::Config,
4 error::AnthropicError,
5 types::common::validate_mixed_ttl_order,
6 types::content::{ContentBlockParam, MessageContentParam, SystemParam},
7 types::messages::{
8 MessageTokensCountRequest, MessageTokensCountResponse, MessagesCreateRequest,
9 MessagesCreateResponse,
10 },
11};
12
13pub struct Messages<'c, C: Config> {
17 client: &'c Client<C>,
18}
19
20impl<'c, C: Config> Messages<'c, C> {
21 #[must_use]
23 pub const fn new(client: &'c Client<C>) -> Self {
24 Self { client }
25 }
26
27 pub async fn create(
36 &self,
37 req: MessagesCreateRequest,
38 ) -> Result<MessagesCreateResponse, AnthropicError> {
39 let mut ttls = Vec::new();
41
42 if let Some(system) = &req.system
44 && let SystemParam::Blocks(blocks) = system
45 {
46 for tb in blocks {
47 if let Some(cc) = &tb.cache_control
48 && let Some(ttl) = &cc.ttl
49 {
50 ttls.push(ttl.clone());
51 }
52 }
53 }
54
55 for message in &req.messages {
57 if let MessageContentParam::Blocks(blocks) = &message.content {
58 for block in blocks {
59 match block {
60 ContentBlockParam::Text {
61 cache_control: Some(cc),
62 ..
63 }
64 | ContentBlockParam::Image {
65 cache_control: Some(cc),
66 ..
67 }
68 | ContentBlockParam::Document {
69 cache_control: Some(cc),
70 ..
71 }
72 | ContentBlockParam::ToolResult {
73 cache_control: Some(cc),
74 ..
75 } => {
76 if let Some(ttl) = &cc.ttl {
77 ttls.push(ttl.clone());
78 }
79 }
80 _ => {}
81 }
82 }
83 }
84 }
85
86 if !validate_mixed_ttl_order(ttls) {
87 return Err(AnthropicError::Config(
88 "Invalid cache_control TTL ordering: 1h must precede 5m".into(),
89 ));
90 }
91
92 if let Some(t) = req.temperature
94 && !(0.0..=1.0).contains(&t)
95 {
96 return Err(AnthropicError::Config(format!(
97 "Invalid temperature {t}: must be in [0.0, 1.0]"
98 )));
99 }
100
101 if let Some(p) = req.top_p
102 && (!(0.0..=1.0).contains(&p) || p == 0.0)
103 {
104 return Err(AnthropicError::Config(format!(
105 "Invalid top_p {p}: must be in (0.0, 1.0]"
106 )));
107 }
108
109 if let Some(k) = req.top_k
110 && k < 1
111 {
112 return Err(AnthropicError::Config(format!(
113 "Invalid top_k {k}: must be >= 1"
114 )));
115 }
116
117 if req.max_tokens == 0 {
118 return Err(AnthropicError::Config(
119 "max_tokens must be greater than 0".into(),
120 ));
121 }
122
123 self.client.post("/v1/messages", req).await
124 }
125
126 pub async fn count_tokens(
134 &self,
135 req: MessageTokensCountRequest,
136 ) -> Result<MessageTokensCountResponse, AnthropicError> {
137 self.client.post("/v1/messages/count_tokens", req).await
139 }
140}
141
142impl<C: Config> crate::Client<C> {
144 #[must_use]
146 pub const fn messages(&self) -> Messages<'_, C> {
147 Messages::new(self)
148 }
149}