1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5#[serde(rename_all = "snake_case")]
6pub enum Role {
7 User,
8 Assistant,
9}
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17#[serde(tag = "type", rename_all = "snake_case")]
18pub enum Content {
19 Text {
20 text: String,
21 },
22 ToolUse {
23 id: String,
24 name: String,
25 input: Value,
26 },
27 ToolResult {
28 tool_use_id: String,
29 content: Value,
30 #[serde(default)]
31 is_error: bool,
32 },
33 Thinking {
34 text: String,
35 #[serde(default, skip_serializing_if = "Option::is_none")]
36 provider_data: Option<Value>,
37 },
38}
39
40#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
41pub struct Message {
42 pub role: Role,
43 pub content: Vec<Content>,
44}
45
46impl Message {
47 pub fn user(text: impl Into<String>) -> Self {
48 Self { role: Role::User, content: vec![Content::Text { text: text.into() }] }
49 }
50
51 pub fn assistant(content: Vec<Content>) -> Self {
52 Self { role: Role::Assistant, content }
53 }
54
55 pub fn text(&self) -> String {
57 content_text(&self.content)
58 }
59}
60
61pub fn content_text(content: &[Content]) -> String {
62 content
63 .iter()
64 .filter_map(|c| match c {
65 Content::Text { text } => Some(text.as_str()),
66 _ => None,
67 })
68 .collect::<Vec<_>>()
69 .join("")
70}