markon_core/chat/
message.rs1use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(rename_all = "lowercase")]
12pub enum Role {
13 User,
14 Assistant,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
18#[serde(tag = "type", rename_all = "snake_case")]
19pub enum ContentBlock {
20 Text {
21 text: String,
22 },
23 ToolUse {
24 id: String,
25 name: String,
26 input: serde_json::Value,
27 },
28 ToolResult {
29 tool_use_id: String,
30 content: String,
31 #[serde(default, skip_serializing_if = "is_false")]
32 is_error: bool,
33 },
34}
35
36fn is_false(b: &bool) -> bool {
37 !*b
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct Message {
42 pub role: Role,
43 pub content: Vec<ContentBlock>,
44}
45
46impl Message {
47 #[allow(dead_code)]
48 pub(crate) fn user_text(text: impl Into<String>) -> Self {
49 Self {
50 role: Role::User,
51 content: vec![ContentBlock::Text { text: text.into() }],
52 }
53 }
54
55 #[allow(dead_code)]
56 pub(crate) fn assistant(content: Vec<ContentBlock>) -> Self {
57 Self {
58 role: Role::Assistant,
59 content,
60 }
61 }
62
63 #[allow(dead_code)]
64 pub(crate) fn tool_results(results: Vec<ContentBlock>) -> Self {
65 Self {
66 role: Role::User,
67 content: results,
68 }
69 }
70}
71
72#[derive(Debug, Clone, Default, Serialize, Deserialize)]
74pub struct Usage {
75 #[serde(default)]
76 pub input_tokens: u32,
77 #[serde(default)]
78 pub cache_creation_input_tokens: u32,
79 #[serde(default)]
80 pub cache_read_input_tokens: u32,
81 #[serde(default)]
82 pub output_tokens: u32,
83}
84
85impl Usage {
86 pub(crate) fn add(&mut self, other: &Usage) {
87 self.input_tokens += other.input_tokens;
88 self.cache_creation_input_tokens += other.cache_creation_input_tokens;
89 self.cache_read_input_tokens += other.cache_read_input_tokens;
90 self.output_tokens += other.output_tokens;
91 }
92}