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}
31
32#[derive(Clone, Debug, Serialize, Deserialize)]
39#[serde(tag = "runtimeEventType", rename_all = "camelCase")]
40pub enum RuntimeEvent {
41 TextDelta {
43 session_id: SessionId,
44 text: String,
45 #[serde(default, skip_serializing_if = "Option::is_none")]
47 agent_id: Option<String>,
48 #[serde(default, skip_serializing_if = "Option::is_none")]
50 trace_id: Option<String>,
51 },
52 ThoughtDelta {
53 session_id: SessionId,
54 text: String,
55 #[serde(default, skip_serializing_if = "Option::is_none")]
56 agent_id: Option<String>,
57 #[serde(default, skip_serializing_if = "Option::is_none")]
58 trace_id: Option<String>,
59 },
60 ToolCallStarted {
61 session_id: SessionId,
62 tool_name: String,
63 args_json: String,
64 #[serde(default, skip_serializing_if = "Option::is_none")]
65 agent_id: Option<String>,
66 #[serde(default, skip_serializing_if = "Option::is_none")]
67 trace_id: Option<String>,
68 },
69 ToolCallFinished {
70 session_id: SessionId,
71 tool_name: String,
72 summary: String,
73 #[serde(default, skip_serializing_if = "Option::is_none")]
74 agent_id: Option<String>,
75 #[serde(default, skip_serializing_if = "Option::is_none")]
76 trace_id: Option<String>,
77 },
78 AwaitingApproval {
79 session_id: SessionId,
80 request: ApprovalRequest,
81 #[serde(default, skip_serializing_if = "Option::is_none")]
82 agent_id: Option<String>,
83 #[serde(default, skip_serializing_if = "Option::is_none")]
84 trace_id: Option<String>,
85 },
86 Checkpoint {
87 session_id: SessionId,
88 checkpoint: CheckpointData,
89 #[serde(default, skip_serializing_if = "Option::is_none")]
90 agent_id: Option<String>,
91 #[serde(default, skip_serializing_if = "Option::is_none")]
92 trace_id: Option<String>,
93 },
94 RunFinished {
95 session_id: SessionId,
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 RunCancelled {
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 PlanUpdated {
110 session_id: SessionId,
111 objective: String,
112 explanation: Option<String>,
113 plan: Vec<PlanItem>,
114 #[serde(default, skip_serializing_if = "Option::is_none")]
115 agent_id: Option<String>,
116 #[serde(default, skip_serializing_if = "Option::is_none")]
117 trace_id: Option<String>,
118 },
119 UserEvent {
122 session_id: SessionId,
123 event: UserEvent,
124 #[serde(default, skip_serializing_if = "Option::is_none")]
125 agent_id: Option<String>,
126 #[serde(default, skip_serializing_if = "Option::is_none")]
127 trace_id: Option<String>,
128 },
129}
130
131impl RuntimeEvent {
132 pub fn session_id(&self) -> &SessionId {
134 match self {
135 RuntimeEvent::TextDelta { session_id, .. } => session_id,
136 RuntimeEvent::ThoughtDelta { session_id, .. } => session_id,
137 RuntimeEvent::ToolCallStarted { session_id, .. } => session_id,
138 RuntimeEvent::ToolCallFinished { session_id, .. } => session_id,
139 RuntimeEvent::AwaitingApproval { session_id, .. } => session_id,
140 RuntimeEvent::Checkpoint { session_id, .. } => session_id,
141 RuntimeEvent::RunFinished { session_id, .. } => session_id,
142 RuntimeEvent::RunCancelled { session_id, .. } => session_id,
143 RuntimeEvent::PlanUpdated { session_id, .. } => session_id,
144 RuntimeEvent::UserEvent { session_id, .. } => session_id,
145 }
146 }
147
148 pub fn agent_id(&self) -> Option<&str> {
150 match self {
151 RuntimeEvent::TextDelta { agent_id, .. } => agent_id.as_deref(),
152 RuntimeEvent::ThoughtDelta { agent_id, .. } => agent_id.as_deref(),
153 RuntimeEvent::ToolCallStarted { agent_id, .. } => agent_id.as_deref(),
154 RuntimeEvent::ToolCallFinished { agent_id, .. } => agent_id.as_deref(),
155 RuntimeEvent::AwaitingApproval { agent_id, .. } => agent_id.as_deref(),
156 RuntimeEvent::Checkpoint { agent_id, .. } => agent_id.as_deref(),
157 RuntimeEvent::RunFinished { agent_id, .. } => agent_id.as_deref(),
158 RuntimeEvent::RunCancelled { agent_id, .. } => agent_id.as_deref(),
159 RuntimeEvent::PlanUpdated { agent_id, .. } => agent_id.as_deref(),
160 RuntimeEvent::UserEvent { agent_id, .. } => agent_id.as_deref(),
161 }
162 }
163
164 pub fn trace_id(&self) -> Option<&str> {
166 match self {
167 RuntimeEvent::TextDelta { trace_id, .. } => trace_id.as_deref(),
168 RuntimeEvent::ThoughtDelta { trace_id, .. } => trace_id.as_deref(),
169 RuntimeEvent::ToolCallStarted { trace_id, .. } => trace_id.as_deref(),
170 RuntimeEvent::ToolCallFinished { trace_id, .. } => trace_id.as_deref(),
171 RuntimeEvent::AwaitingApproval { trace_id, .. } => trace_id.as_deref(),
172 RuntimeEvent::Checkpoint { trace_id, .. } => trace_id.as_deref(),
173 RuntimeEvent::RunFinished { trace_id, .. } => trace_id.as_deref(),
174 RuntimeEvent::RunCancelled { trace_id, .. } => trace_id.as_deref(),
175 RuntimeEvent::PlanUpdated { trace_id, .. } => trace_id.as_deref(),
176 RuntimeEvent::UserEvent { trace_id, .. } => trace_id.as_deref(),
177 }
178 }
179}