1use chrono::Utc;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Copy, PartialEq, Default)]
6pub enum ToolExecutionMode {
7 #[default]
9 Parallel,
10 Sequential,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq)]
16pub enum QueueMode {
17 All,
19 OneAtATime,
21}
22
23#[derive(Debug)]
26pub struct PendingMessageQueue {
27 messages: Vec<AgentMessage>,
28 mode: QueueMode,
29}
30
31impl PendingMessageQueue {
32 pub fn new(mode: QueueMode) -> Self {
33 Self {
34 messages: Vec::new(),
35 mode,
36 }
37 }
38
39 pub fn enqueue(&mut self, msg: AgentMessage) {
41 self.messages.push(msg);
42 }
43
44 pub fn drain(&mut self) -> Vec<AgentMessage> {
46 match self.mode {
47 QueueMode::All => self.messages.drain(..).collect(),
48 QueueMode::OneAtATime => {
49 if self.messages.is_empty() {
50 vec![]
51 } else {
52 vec![self.messages.remove(0)]
53 }
54 }
55 }
56 }
57
58 pub fn drain_all(&mut self) -> Vec<AgentMessage> {
61 self.messages.drain(..).collect()
62 }
63
64 pub fn is_empty(&self) -> bool {
65 self.messages.is_empty()
66 }
67
68 pub fn len(&self) -> usize {
69 self.messages.len()
70 }
71
72 pub fn clear(&mut self) {
73 self.messages.clear();
74 }
75}
76
77#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
79#[serde(rename_all = "camelCase")]
80pub enum Role {
81 User,
82 Assistant,
83 ToolResult,
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct ToolCall {
89 pub id: String,
90 pub name: String,
91 pub arguments: serde_json::Value,
92}
93
94#[derive(Debug, Clone, Default, Serialize, Deserialize)]
96pub struct Usage {
97 pub input_tokens: Option<i32>,
98 pub output_tokens: Option<i32>,
99 pub cache_tokens: Option<i32>,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
104#[serde(rename_all = "camelCase")]
105pub struct AgentMessage {
106 pub id: String,
107 pub parent_id: Option<String>,
108 pub role: Role,
109 pub content: String,
110 #[serde(default, skip_serializing_if = "Vec::is_empty")]
111 pub tool_calls: Vec<ToolCall>,
112 #[serde(skip_serializing_if = "Option::is_none")]
113 pub tool_call_id: Option<String>,
114 #[serde(skip_serializing_if = "Option::is_none")]
115 pub usage: Option<Usage>,
116 pub is_error: bool,
117 pub timestamp: i64,
118}
119
120impl AgentMessage {
121 pub fn user(content: impl Into<String>) -> Self {
122 Self {
123 id: uuid::Uuid::new_v4().to_string(),
124 parent_id: None,
125 role: Role::User,
126 content: content.into(),
127 tool_calls: vec![],
128 tool_call_id: None,
129 usage: None,
130 is_error: false,
131 timestamp: Utc::now().timestamp_millis(),
132 }
133 }
134
135 pub fn tool_result(
136 tool_call_id: impl Into<String>,
137 content: impl Into<String>,
138 is_error: bool,
139 ) -> Self {
140 Self {
141 id: uuid::Uuid::new_v4().to_string(),
142 parent_id: None,
143 role: Role::ToolResult,
144 content: content.into(),
145 tool_calls: vec![],
146 tool_call_id: Some(tool_call_id.into()),
147 usage: None,
148 is_error,
149 timestamp: Utc::now().timestamp_millis(),
150 }
151 }
152}