codetether_agent/tui/chat/message.rs
1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
4pub enum MessageType {
5 User,
6 Assistant,
7 System,
8 Error,
9 ToolCall {
10 name: String,
11 arguments: String,
12 },
13 ToolResult {
14 name: String,
15 output: String,
16 success: bool,
17 #[serde(default)]
18 duration_ms: Option<u64>,
19 },
20 Thinking(String),
21 Image {
22 url: String,
23 },
24 File {
25 path: String,
26 #[serde(default)]
27 size: Option<u64>,
28 },
29}
30
31/// Token usage attributed to a single chat message.
32///
33/// Populated from [`crate::session::SessionEvent::UsageReport`] after a
34/// provider completion returns. Attached to the most recent assistant /
35/// tool-call message produced by that completion.
36///
37/// # Examples
38///
39/// ```rust
40/// use codetether_agent::tui::chat::message::MessageUsage;
41///
42/// let usage = MessageUsage {
43/// model: "anthropic/claude-opus-4".into(),
44/// prompt_tokens: 1523,
45/// completion_tokens: 284,
46/// duration_ms: 4210,
47/// };
48/// assert_eq!(usage.prompt_tokens, 1523);
49/// ```
50#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
51pub struct MessageUsage {
52 /// Model that produced this completion.
53 pub model: String,
54 /// Input / prompt tokens charged for this completion.
55 pub prompt_tokens: usize,
56 /// Output / completion tokens produced by this completion.
57 pub completion_tokens: usize,
58 /// Wall-clock latency of the provider request in milliseconds.
59 pub duration_ms: u64,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct ChatMessage {
64 pub message_type: MessageType,
65 pub content: String,
66 pub timestamp: std::time::SystemTime,
67 /// Per-message token usage, populated after the provider returns.
68 /// `None` for messages that do not correspond to a provider call
69 /// (user input, system notices, tool results).
70 #[serde(default)]
71 pub usage: Option<MessageUsage>,
72}
73
74impl ChatMessage {
75 pub fn new(message_type: MessageType, content: impl Into<String>) -> Self {
76 Self {
77 message_type,
78 content: content.into(),
79 timestamp: std::time::SystemTime::now(),
80 usage: None,
81 }
82 }
83}