systemprompt_wire/canonical/request/
content.rs1use serde_json::Value;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum Role {
15 System,
16 User,
17 Assistant,
18 Tool,
19}
20
21impl Role {
22 pub const fn as_str(self) -> &'static str {
23 match self {
24 Self::System => "system",
25 Self::User => "user",
26 Self::Assistant => "assistant",
27 Self::Tool => "tool",
28 }
29 }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub enum ImageDetail {
34 Auto,
35 Low,
36 High,
37}
38
39impl ImageDetail {
40 pub const fn as_str(self) -> &'static str {
41 match self {
42 Self::Auto => "auto",
43 Self::Low => "low",
44 Self::High => "high",
45 }
46 }
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum CacheTtl {
51 FiveMinutes,
52 OneHour,
53}
54
55impl CacheTtl {
56 pub const fn as_str(self) -> &'static str {
57 match self {
58 Self::FiveMinutes => "5m",
59 Self::OneHour => "1h",
60 }
61 }
62
63 #[must_use]
64 pub fn parse(value: &str) -> Option<Self> {
65 match value {
66 "5m" => Some(Self::FiveMinutes),
67 "1h" => Some(Self::OneHour),
68 _ => None,
69 }
70 }
71}
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
76pub struct CacheControl {
77 pub ttl: Option<CacheTtl>,
78}
79
80impl CacheControl {
81 pub const EPHEMERAL: Self = Self { ttl: None };
82
83 #[must_use]
84 pub const fn with_ttl(ttl: CacheTtl) -> Self {
85 Self { ttl: Some(ttl) }
86 }
87}
88
89#[derive(Debug, Clone, PartialEq, Eq)]
90pub struct SystemBlock {
91 pub text: String,
92 pub cache_control: Option<CacheControl>,
93}
94
95impl SystemBlock {
96 #[must_use]
97 pub fn text(text: impl Into<String>) -> Self {
98 Self {
99 text: text.into(),
100 cache_control: None,
101 }
102 }
103}
104
105#[derive(Debug, Clone)]
106pub enum ImageSource {
107 Base64 {
108 media_type: String,
109 data: String,
110 detail: Option<ImageDetail>,
111 },
112 Url {
113 url: String,
114 detail: Option<ImageDetail>,
115 },
116}
117
118#[derive(Debug, Clone)]
119pub enum CanonicalContent {
120 AnthropicToolBlock {
121 tool_name: String,
122 block: Value,
124 },
125 Text {
126 text: String,
127 cache_control: Option<CacheControl>,
128 },
129 Image {
130 source: ImageSource,
131 cache_control: Option<CacheControl>,
132 },
133 ToolUse {
134 id: String,
135 name: String,
136 input: Value,
138 signature: Option<String>,
140 cache_control: Option<CacheControl>,
141 },
142 ToolResult {
143 tool_use_id: String,
144 content: Vec<Self>,
145 is_error: bool,
146 structured_content: Option<Value>,
147 meta: Option<Value>,
149 cache_control: Option<CacheControl>,
150 },
151 Thinking {
152 text: String,
153 signature: Option<String>,
154 id: Option<String>,
157 encrypted_content: Option<String>,
158 },
159}
160
161impl CanonicalContent {
162 #[must_use]
163 pub fn text(text: impl Into<String>) -> Self {
164 Self::Text {
165 text: text.into(),
166 cache_control: None,
167 }
168 }
169
170 #[must_use]
171 pub const fn image(source: ImageSource) -> Self {
172 Self::Image {
173 source,
174 cache_control: None,
175 }
176 }
177
178 #[must_use]
180 pub const fn cache_control(&self) -> Option<CacheControl> {
181 match self {
182 Self::Text { cache_control, .. }
183 | Self::Image { cache_control, .. }
184 | Self::ToolUse { cache_control, .. }
185 | Self::ToolResult { cache_control, .. } => *cache_control,
186 Self::Thinking { .. } | Self::AnthropicToolBlock { .. } => None,
187 }
188 }
189}
190
191#[derive(Debug, Clone)]
192pub struct CanonicalMessage {
193 pub role: Role,
194 pub content: Vec<CanonicalContent>,
195}