1use crate::protocol::AgentMessageEvent;
2use crate::protocol::AgentReasoningEvent;
3use crate::protocol::AgentReasoningRawContentEvent;
4use crate::protocol::EventMsg;
5use crate::protocol::UserMessageEvent;
6use crate::protocol::WebSearchEndEvent;
7use crate::user_input::UserInput;
8use schemars::JsonSchema;
9use serde::Deserialize;
10use serde::Serialize;
11use ts_rs::TS;
12
13#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
14#[serde(tag = "type")]
15#[ts(tag = "type")]
16pub enum TurnItem {
17 UserMessage(UserMessageItem),
18 AgentMessage(AgentMessageItem),
19 Reasoning(ReasoningItem),
20 WebSearch(WebSearchItem),
21}
22
23#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
24pub struct UserMessageItem {
25 pub id: String,
26 pub content: Vec<UserInput>,
27}
28
29#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
30#[serde(tag = "type")]
31#[ts(tag = "type")]
32pub enum AgentMessageContent {
33 Text { text: String },
34}
35
36#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
37pub struct AgentMessageItem {
38 pub id: String,
39 pub content: Vec<AgentMessageContent>,
40}
41
42#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
43pub struct ReasoningItem {
44 pub id: String,
45 pub summary_text: Vec<String>,
46 #[serde(default)]
47 pub raw_content: Vec<String>,
48}
49
50#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
51pub struct WebSearchItem {
52 pub id: String,
53 pub query: String,
54}
55
56impl UserMessageItem {
57 pub fn new(content: &[UserInput]) -> Self {
58 Self {
59 id: uuid::Uuid::new_v4().to_string(),
60 content: content.to_vec(),
61 }
62 }
63
64 pub fn as_legacy_event(&self) -> EventMsg {
65 EventMsg::UserMessage(UserMessageEvent {
66 message: self.message(),
67 images: Some(self.image_urls()),
68 })
69 }
70
71 pub fn message(&self) -> String {
72 self.content
73 .iter()
74 .map(|c| match c {
75 UserInput::Text { text } => text.clone(),
76 _ => String::new(),
77 })
78 .collect::<Vec<String>>()
79 .join("")
80 }
81
82 pub fn image_urls(&self) -> Vec<String> {
83 self.content
84 .iter()
85 .filter_map(|c| match c {
86 UserInput::Image { image_url } => Some(image_url.clone()),
87 _ => None,
88 })
89 .collect()
90 }
91}
92
93impl AgentMessageItem {
94 pub fn new(content: &[AgentMessageContent]) -> Self {
95 Self {
96 id: uuid::Uuid::new_v4().to_string(),
97 content: content.to_vec(),
98 }
99 }
100
101 pub fn as_legacy_events(&self) -> Vec<EventMsg> {
102 self.content
103 .iter()
104 .map(|c| match c {
105 AgentMessageContent::Text { text } => EventMsg::AgentMessage(AgentMessageEvent {
106 message: text.clone(),
107 }),
108 })
109 .collect()
110 }
111}
112
113impl ReasoningItem {
114 pub fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg> {
115 let mut events = Vec::new();
116 for summary in &self.summary_text {
117 events.push(EventMsg::AgentReasoning(AgentReasoningEvent {
118 text: summary.clone(),
119 }));
120 }
121
122 if show_raw_agent_reasoning {
123 for entry in &self.raw_content {
124 events.push(EventMsg::AgentReasoningRawContent(
125 AgentReasoningRawContentEvent {
126 text: entry.clone(),
127 },
128 ));
129 }
130 }
131
132 events
133 }
134}
135
136impl WebSearchItem {
137 pub fn as_legacy_event(&self) -> EventMsg {
138 EventMsg::WebSearchEnd(WebSearchEndEvent {
139 call_id: self.id.clone(),
140 query: self.query.clone(),
141 })
142 }
143}
144
145impl TurnItem {
146 pub fn id(&self) -> String {
147 match self {
148 TurnItem::UserMessage(item) => item.id.clone(),
149 TurnItem::AgentMessage(item) => item.id.clone(),
150 TurnItem::Reasoning(item) => item.id.clone(),
151 TurnItem::WebSearch(item) => item.id.clone(),
152 }
153 }
154
155 pub fn as_legacy_events(&self, show_raw_agent_reasoning: bool) -> Vec<EventMsg> {
156 match self {
157 TurnItem::UserMessage(item) => vec![item.as_legacy_event()],
158 TurnItem::AgentMessage(item) => item.as_legacy_events(),
159 TurnItem::WebSearch(item) => vec![item.as_legacy_event()],
160 TurnItem::Reasoning(item) => item.as_legacy_events(show_raw_agent_reasoning),
161 }
162 }
163}