codex_protocol/
items.rs

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}