cogito_claude/lib.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2025 Michael Dippery <michael@monkey-robot.com>
3
4//! An implementation of a client for Anthropic's Claude API.
5//!
6//! This provider implements traits from [cogito] to provide a uniform way
7//! to access Anthropic's Claude API. This makes it easy to swap out other
8//! providers for Anthropic's Claude in your application, or vice versa.
9//!
10//! This library assumes you pass authentication tokens for the Anthropic API
11//! using [`cogito::service::Auth`]. **This means that you are solely
12//! responsible for paying the costs of API access; the Cogito developers
13//! are not responsible for costs you incur while using this library.**
14//!
15//! # Cost
16//!
17//! There's no such thing as a free lunch, and there's no such thing as free
18//! Claude access. When you create a Claude API client, you will need to
19//! select a [`ClaudeModel`]. Models are billed on a per-token basis, where
20//! a token is the smallest unit of text that the model reads and processes.
21//! There are two types of tokens: input tokens and output tokens.
22//!
23//! - **Input tokens** are the token used in any _requests_ made to the
24//! Claude AI. This is the "prompt" that users of this library send to
25//! Claude for summarization.
26//! - **Output tokens** are tokens generated in the output that is sent back
27//! to a client in response to a request.
28//!
29//! Prices are expressed in US dollars per $1 million tokens. As of
30//! 25 November 2025, the prices for each model are as follows.
31//!
32//! For the latest pricing, see the [pricing documentation] in the Claude
33//! platform documentation.
34//!
35//! | Model | Designation | Input | Output |
36//! |------------|-------------------|------:|-------:|
37//! | Sonnet 4.5 | claude-sonnet-4-5 | $3 | $15 |
38//! | Haiku 4.5 | claude-haiku-4-5 | $1 | $5 |
39//! | Opus 4.5 | claude-opus-4-5 | $5 | $25 |
40//! | Opus 4.1 | claude-opus-4-1 | $15 | $75 |
41//!
42//! [`cogito::service::Auth`]: https://docs.rs/cogito/latest/cogito/service/struct.Auth.html
43//! [pricing documentation]: https://platform.claude.com/docs/en/about-claude/pricing
44
45pub mod client;
46pub mod service;
47
48use cogito::AiModel;
49use serde::{Deserialize, Serialize};
50use std::fmt;
51
52/// Available Claude AI models.
53///
54/// For more information on the differences between each model, see the
55/// [model overview] in the Claude platform documentation.
56///
57/// The [default model] is [Sonnet 4.5], which Anthropic describes as "our
58/// smartest model for complex agents and coding". The cheapest and fastest
59/// model, [Haiku 4.5], is the "fastest model with near-frontier intelligence".
60/// [Opus 4.5] is a "premium model combining maximum intelligence with
61/// practical performance", and [Opus 4.1] is an "exceptional model for
62/// specialized reasoning tasks" (and also the most expensive!).
63///
64/// # Cost
65///
66/// Claude API usage has a cost, and the cost of each model differs; naturally,
67/// the more powerful models cost more to use. See the [cost breakdown] in the
68/// `cogito_claude` module documentation for more details, or visit Anthropic's
69/// [pricing] documentation for the latest prices.
70///
71/// [cost breakdown]: self#Cost
72/// [default model]: ClaudeModel::default()
73/// [model overview]: https://platform.claude.com/docs/en/about-claude/models/overview
74/// [pricing]: https://platform.claude.com/docs/en/about-claude/pricing
75/// [Haiku 4.5]: ClaudeModel::Haiku45
76/// [Opus 4.1]: ClaudeModel::Opus41
77/// [Opus 4.5]: ClaudeModel::Opus45
78/// [Sonnet 4.5]: ClaudeModel::Sonnet45
79#[derive(Clone, Copy, Debug, Default, PartialEq, Deserialize, Serialize)]
80pub enum ClaudeModel {
81 /// Anthropic's flagship model.
82 ///
83 /// According to Anthropic, this model is "our smartest model for
84 /// complex agents and coding".
85 #[default]
86 #[serde(rename = "claude-sonnet-4-5")]
87 Sonnet45,
88
89 /// Anthropic's fastest and cheapest model.
90 ///
91 /// According to Anthropic, this model is "our fastest model with
92 /// near-frontier intelligence".
93 #[serde(rename = "claude-haiku-4-5")]
94 Haiku45,
95
96 /// A premium model.
97 ///
98 /// This model "combines maximum intelligence with practical performance".
99 #[serde(rename = "claude-opus-4-5")]
100 Opus45,
101
102 /// An expensive, premium model.
103 ///
104 /// According to Anthropic, an "exceptional model for specialize
105 /// reasoning tasks".
106 #[serde(rename = "claude-opus-4-1")]
107 Opus41,
108}
109
110impl AiModel for ClaudeModel {
111 /// Anthropic's standard model.
112 fn flagship() -> Self {
113 ClaudeModel::default()
114 }
115
116 /// The "best" model as defined by Anthropic.
117 fn best() -> Self {
118 ClaudeModel::default()
119 }
120
121 /// Anthropic's cheapest model.
122 fn cheapest() -> Self {
123 ClaudeModel::Haiku45
124 }
125
126 /// Anthropic's fastest model.
127 fn fastest() -> Self {
128 ClaudeModel::Haiku45
129 }
130}
131
132impl fmt::Display for ClaudeModel {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 let s = serde_json::to_string(&self)
135 .unwrap_or_else(|_| panic!("could not serialize {:?}", self));
136 let s = s.trim_matches('"');
137 f.write_fmt(format_args!("{}", s))
138 }
139}
140
141/// Convenience module for splat imports.
142///
143/// To import the most common data structures and traits from this crate,
144/// add
145///
146/// ```
147/// use cogito_claude::prelude::*;
148/// ```
149///
150/// in your project.
151pub mod prelude {
152 pub use crate::ClaudeModel;
153 pub use crate::client::{ClaudeClient, ClaudeRequest, ClaudeResponse};
154 pub use crate::service::ClaudeService;
155 pub use cogito::AiModel;
156 pub use cogito::client::{AiClient, AiRequest, AiResponse};
157}
158
159#[cfg(test)]
160mod tests {
161 use super::*;
162
163 #[test]
164 fn it_returns_a_valid_display_string() {
165 let test_cases = vec![
166 (ClaudeModel::Sonnet45, "claude-sonnet-4-5"),
167 (ClaudeModel::Haiku45, "claude-haiku-4-5"),
168 (ClaudeModel::Opus45, "claude-opus-4-5"),
169 (ClaudeModel::Opus41, "claude-opus-4-1"),
170 ];
171
172 for (model, descriptor) in test_cases {
173 assert_eq!(model.to_string(), descriptor, "ClaudeModel::{:?}", model);
174 }
175 }
176}