1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4use super::approval::ApprovalRequest;
5use super::checkpoint::CheckpointData;
6use super::plan_update::PlanItem;
7use super::session::SessionId;
8
9#[derive(Clone, Debug, Serialize, Deserialize)]
19#[serde(tag = "userEventType", rename_all = "camelCase")]
20pub enum UserEvent {
21 Progress { text: String },
23 SubAgentEvent {
25 subagent: String,
26 event: Box<RuntimeEvent>,
27 },
28 Structured { event_type: String, data: Value },
30 ToolPartialResult {
33 tool_call_id: String,
34 content: String,
35 is_partial: bool,
36 },
37}
38
39#[derive(Clone, Debug, Serialize, Deserialize)]
46#[serde(tag = "runtimeEventType", rename_all = "camelCase")]
47pub enum RuntimeEvent {
48 TextDelta {
50 session_id: SessionId,
51 text: String,
52 #[serde(default, skip_serializing_if = "Option::is_none")]
54 agent_id: Option<String>,
55 #[serde(default, skip_serializing_if = "Option::is_none")]
57 trace_id: Option<String>,
58 },
59 ThoughtDelta {
60 session_id: SessionId,
61 text: String,
62 #[serde(default, skip_serializing_if = "Option::is_none")]
63 agent_id: Option<String>,
64 #[serde(default, skip_serializing_if = "Option::is_none")]
65 trace_id: Option<String>,
66 },
67 ToolCallStarted {
68 session_id: SessionId,
69 tool_name: String,
70 args_json: String,
71 #[serde(default, skip_serializing_if = "Option::is_none")]
72 agent_id: Option<String>,
73 #[serde(default, skip_serializing_if = "Option::is_none")]
74 trace_id: Option<String>,
75 },
76 ToolCallFinished {
77 session_id: SessionId,
78 tool_name: String,
79 summary: String,
80 #[serde(default, skip_serializing_if = "Option::is_none")]
81 agent_id: Option<String>,
82 #[serde(default, skip_serializing_if = "Option::is_none")]
83 trace_id: Option<String>,
84 },
85 AwaitingApproval {
86 session_id: SessionId,
87 request: ApprovalRequest,
88 #[serde(default, skip_serializing_if = "Option::is_none")]
89 agent_id: Option<String>,
90 #[serde(default, skip_serializing_if = "Option::is_none")]
91 trace_id: Option<String>,
92 },
93 Checkpoint {
94 session_id: SessionId,
95 checkpoint: CheckpointData,
96 #[serde(default, skip_serializing_if = "Option::is_none")]
97 agent_id: Option<String>,
98 #[serde(default, skip_serializing_if = "Option::is_none")]
99 trace_id: Option<String>,
100 },
101 RunFinished {
102 session_id: SessionId,
103 #[serde(default, skip_serializing_if = "Option::is_none")]
104 agent_id: Option<String>,
105 #[serde(default, skip_serializing_if = "Option::is_none")]
106 trace_id: Option<String>,
107 },
108 RunCancelled {
109 session_id: SessionId,
110 #[serde(default, skip_serializing_if = "Option::is_none")]
111 agent_id: Option<String>,
112 #[serde(default, skip_serializing_if = "Option::is_none")]
113 trace_id: Option<String>,
114 },
115 PlanUpdated {
117 session_id: SessionId,
118 objective: String,
119 explanation: Option<String>,
120 plan: Vec<PlanItem>,
121 #[serde(default, skip_serializing_if = "Option::is_none")]
122 agent_id: Option<String>,
123 #[serde(default, skip_serializing_if = "Option::is_none")]
124 trace_id: Option<String>,
125 },
126 UserEvent {
129 session_id: SessionId,
130 event: UserEvent,
131 #[serde(default, skip_serializing_if = "Option::is_none")]
132 agent_id: Option<String>,
133 #[serde(default, skip_serializing_if = "Option::is_none")]
134 trace_id: Option<String>,
135 },
136}
137
138impl RuntimeEvent {
139 pub fn session_id(&self) -> &SessionId {
141 match self {
142 RuntimeEvent::TextDelta { session_id, .. } => session_id,
143 RuntimeEvent::ThoughtDelta { session_id, .. } => session_id,
144 RuntimeEvent::ToolCallStarted { session_id, .. } => session_id,
145 RuntimeEvent::ToolCallFinished { session_id, .. } => session_id,
146 RuntimeEvent::AwaitingApproval { session_id, .. } => session_id,
147 RuntimeEvent::Checkpoint { session_id, .. } => session_id,
148 RuntimeEvent::RunFinished { session_id, .. } => session_id,
149 RuntimeEvent::RunCancelled { session_id, .. } => session_id,
150 RuntimeEvent::PlanUpdated { session_id, .. } => session_id,
151 RuntimeEvent::UserEvent { session_id, .. } => session_id,
152 }
153 }
154
155 pub fn agent_id(&self) -> Option<&str> {
157 match self {
158 RuntimeEvent::TextDelta { agent_id, .. } => agent_id.as_deref(),
159 RuntimeEvent::ThoughtDelta { agent_id, .. } => agent_id.as_deref(),
160 RuntimeEvent::ToolCallStarted { agent_id, .. } => agent_id.as_deref(),
161 RuntimeEvent::ToolCallFinished { agent_id, .. } => agent_id.as_deref(),
162 RuntimeEvent::AwaitingApproval { agent_id, .. } => agent_id.as_deref(),
163 RuntimeEvent::Checkpoint { agent_id, .. } => agent_id.as_deref(),
164 RuntimeEvent::RunFinished { agent_id, .. } => agent_id.as_deref(),
165 RuntimeEvent::RunCancelled { agent_id, .. } => agent_id.as_deref(),
166 RuntimeEvent::PlanUpdated { agent_id, .. } => agent_id.as_deref(),
167 RuntimeEvent::UserEvent { agent_id, .. } => agent_id.as_deref(),
168 }
169 }
170
171 pub fn trace_id(&self) -> Option<&str> {
173 match self {
174 RuntimeEvent::TextDelta { trace_id, .. } => trace_id.as_deref(),
175 RuntimeEvent::ThoughtDelta { trace_id, .. } => trace_id.as_deref(),
176 RuntimeEvent::ToolCallStarted { trace_id, .. } => trace_id.as_deref(),
177 RuntimeEvent::ToolCallFinished { trace_id, .. } => trace_id.as_deref(),
178 RuntimeEvent::AwaitingApproval { trace_id, .. } => trace_id.as_deref(),
179 RuntimeEvent::Checkpoint { trace_id, .. } => trace_id.as_deref(),
180 RuntimeEvent::RunFinished { trace_id, .. } => trace_id.as_deref(),
181 RuntimeEvent::RunCancelled { trace_id, .. } => trace_id.as_deref(),
182 RuntimeEvent::PlanUpdated { trace_id, .. } => trace_id.as_deref(),
183 RuntimeEvent::UserEvent { trace_id, .. } => trace_id.as_deref(),
184 }
185 }
186}