tiny_agent/messages/
mod.rs1use crate::shared::ContentBlock;
11use serde::{Deserialize, Serialize};
12use serde_json::Value;
13use std::time::{SystemTime, UNIX_EPOCH};
14use tokio::sync::mpsc;
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct AgentMessage {
19 pub session_id: String,
20 pub at: u64,
21 #[serde(flatten)]
22 pub kind: MessageKind,
23}
24
25impl AgentMessage {
26 pub fn new(session_id: &str, kind: MessageKind) -> Self {
27 let at = SystemTime::now()
28 .duration_since(UNIX_EPOCH)
29 .map(|d| d.as_millis() as u64)
30 .unwrap_or(0);
31 Self {
32 session_id: session_id.to_string(),
33 at,
34 kind,
35 }
36 }
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
43#[serde(tag = "type", rename_all = "snake_case")]
44pub enum MessageKind {
45 UserMessage { text: String },
47 ReasoningStarted,
49 PartialAssistantMessage { delta: String },
51 AssistantMessage { blocks: Vec<ContentBlock> },
53 PartialToolCall {
55 call_id: String,
56 name: String,
57 delta: String,
58 },
59 ToolCall {
61 call_id: String,
62 name: String,
63 arguments: Value,
64 },
65 ToolOutput { chunk: String },
70 ToolResponse {
73 call_id: String,
74 output: Vec<ContentBlock>,
75 is_error: bool,
76 },
77}
78
79#[derive(Clone)]
81pub struct MessageChannel {
82 tx: mpsc::UnboundedSender<AgentMessage>,
83}
84
85impl MessageChannel {
86 pub fn new() -> (Self, mpsc::UnboundedReceiver<AgentMessage>) {
88 let (tx, rx) = mpsc::unbounded_channel();
89 (Self { tx }, rx)
90 }
91
92 pub fn disconnected() -> Self {
94 let (tx, _rx) = mpsc::unbounded_channel();
95 Self { tx }
96 }
97
98 pub fn send(&self, session_id: &str, kind: MessageKind) {
100 let _ = self.tx.send(AgentMessage::new(session_id, kind));
101 }
102}
103
104impl Default for MessageChannel {
105 fn default() -> Self {
106 Self::disconnected()
107 }
108}