1#![allow(deprecated)]
28
29pub mod activity;
30pub mod factories;
31pub mod lifecycle;
32pub mod reasoning;
33pub mod special;
34pub mod state;
35pub mod subagent;
36pub mod text;
37pub mod tool;
38
39use std::fmt;
40use std::str::FromStr;
41
42use serde::{Deserialize, Serialize};
43use serde_json::Value;
44
45use crate::JsonObject;
46use crate::error::{Error, Result};
47use crate::ids::SubagentRunId;
48
49pub use activity::{ActivityDeltaEvent, ActivitySnapshotEvent};
50pub use lifecycle::{
51 RunErrorEvent, RunFinishedEvent, RunStartedEvent, StepFinishedEvent, StepStartedEvent,
52};
53pub use reasoning::{
54 ReasoningEncryptedValueEvent, ReasoningEncryptedValueSubtype, ReasoningEndEvent,
55 ReasoningMessageChunkEvent, ReasoningMessageContentEvent, ReasoningMessageEndEvent,
56 ReasoningMessageStartEvent, ReasoningRole, ReasoningStartEvent, ThinkingEndEvent,
57 ThinkingStartEvent, ThinkingTextMessageContentEvent, ThinkingTextMessageEndEvent,
58 ThinkingTextMessageStartEvent,
59};
60pub use special::{CustomEvent, RawEvent};
61pub use state::{MessagesSnapshotEvent, StateDeltaEvent, StateSnapshotEvent};
62pub use subagent::{
63 SubagentErrorEvent, SubagentFinishedEvent, SubagentOutcome, SubagentStartedEvent,
64};
65pub use text::{
66 TextMessageChunkEvent, TextMessageContentEvent, TextMessageEndEvent, TextMessageRole,
67 TextMessageStartEvent,
68};
69pub use tool::{
70 ToolCallArgsEvent, ToolCallChunkEvent, ToolCallEndEvent, ToolCallResultEvent,
71 ToolCallStartEvent, ToolResultRole,
72};
73
74#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
77#[serde(rename_all = "camelCase")]
78#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
79#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
80pub struct BaseEvent {
81 #[serde(default, skip_serializing_if = "Option::is_none")]
83 pub timestamp: Option<i64>,
84 #[serde(default, skip_serializing_if = "Option::is_none")]
86 pub raw_event: Option<Value>,
87 #[serde(
91 default,
92 deserialize_with = "crate::serde_util::reject_null",
93 skip_serializing_if = "Option::is_none"
94 )]
95 #[cfg_attr(
96 feature = "schemars",
97 schemars(with = "Option<std::collections::BTreeMap<String, serde_json::Value>>")
98 )]
99 #[cfg_attr(feature = "utoipa", schema(value_type = Option<Object>))]
100 pub metadata: Option<JsonObject>,
101}
102
103impl BaseEvent {
104 pub fn new() -> Self {
106 Self::default()
107 }
108
109 pub const fn is_empty(&self) -> bool {
112 self.timestamp.is_none() && self.raw_event.is_none() && self.metadata.is_none()
113 }
114}
115
116macro_rules! define_events {
117 ($(
118 $(#[$meta:meta])*
119 $variant:ident($payload:ty) => $tag:literal,
120 )*) => {
121 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
138 #[serde(tag = "type")]
139 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
140 #[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
141 pub enum Event {
142 $(
143 $(#[$meta])*
144 #[serde(rename = $tag)]
145 $variant($payload),
146 )*
147 }
148
149 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
155 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
156 #[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
157 pub enum EventType {
158 $(
159 $(#[$meta])*
160 #[serde(rename = $tag)]
161 $variant,
162 )*
163 }
164
165 impl EventType {
166 pub const ALL: &'static [EventType] = &[$(EventType::$variant),*];
168
169 pub const fn as_str(&self) -> &'static str {
171 match self {
172 $(Self::$variant => $tag,)*
173 }
174 }
175 }
176
177 impl FromStr for EventType {
178 type Err = Error;
179
180 fn from_str(s: &str) -> Result<Self> {
181 match s {
182 $($tag => Ok(Self::$variant),)*
183 other => Err(Error::UnknownEventType(other.to_owned())),
184 }
185 }
186 }
187
188 impl Event {
189 pub const fn event_type(&self) -> EventType {
191 match self {
192 $(Self::$variant(_) => EventType::$variant,)*
193 }
194 }
195
196 pub const fn base(&self) -> &BaseEvent {
198 match self {
199 $(Self::$variant(payload) => &payload.base,)*
200 }
201 }
202
203 pub const fn base_mut(&mut self) -> &mut BaseEvent {
205 match self {
206 $(Self::$variant(payload) => &mut payload.base,)*
207 }
208 }
209 }
210
211 $(
212 impl From<$payload> for Event {
213 fn from(payload: $payload) -> Self {
214 Self::$variant(payload)
215 }
216 }
217 )*
218 };
219}
220
221define_events! {
222 TextMessageStart(TextMessageStartEvent) => "TEXT_MESSAGE_START",
224 TextMessageContent(TextMessageContentEvent) => "TEXT_MESSAGE_CONTENT",
226 TextMessageEnd(TextMessageEndEvent) => "TEXT_MESSAGE_END",
228 TextMessageChunk(TextMessageChunkEvent) => "TEXT_MESSAGE_CHUNK",
230 ToolCallStart(ToolCallStartEvent) => "TOOL_CALL_START",
232 ToolCallArgs(ToolCallArgsEvent) => "TOOL_CALL_ARGS",
234 ToolCallEnd(ToolCallEndEvent) => "TOOL_CALL_END",
236 ToolCallChunk(ToolCallChunkEvent) => "TOOL_CALL_CHUNK",
238 ToolCallResult(ToolCallResultEvent) => "TOOL_CALL_RESULT",
240 #[cfg_attr(not(feature = "utoipa"), deprecated(note = "use Event::ReasoningStart"))]
242 ThinkingStart(ThinkingStartEvent) => "THINKING_START",
243 #[cfg_attr(not(feature = "utoipa"), deprecated(note = "use Event::ReasoningEnd"))]
245 ThinkingEnd(ThinkingEndEvent) => "THINKING_END",
246 #[cfg_attr(not(feature = "utoipa"), deprecated(note = "use Event::ReasoningMessageStart"))]
248 ThinkingTextMessageStart(ThinkingTextMessageStartEvent) => "THINKING_TEXT_MESSAGE_START",
249 #[cfg_attr(not(feature = "utoipa"), deprecated(note = "use Event::ReasoningMessageContent"))]
251 ThinkingTextMessageContent(ThinkingTextMessageContentEvent) => "THINKING_TEXT_MESSAGE_CONTENT",
252 #[cfg_attr(not(feature = "utoipa"), deprecated(note = "use Event::ReasoningMessageEnd"))]
254 ThinkingTextMessageEnd(ThinkingTextMessageEndEvent) => "THINKING_TEXT_MESSAGE_END",
255 StateSnapshot(StateSnapshotEvent) => "STATE_SNAPSHOT",
257 StateDelta(StateDeltaEvent) => "STATE_DELTA",
259 MessagesSnapshot(MessagesSnapshotEvent) => "MESSAGES_SNAPSHOT",
261 ActivitySnapshot(ActivitySnapshotEvent) => "ACTIVITY_SNAPSHOT",
263 ActivityDelta(ActivityDeltaEvent) => "ACTIVITY_DELTA",
265 Raw(RawEvent) => "RAW",
267 Custom(CustomEvent) => "CUSTOM",
269 RunStarted(RunStartedEvent) => "RUN_STARTED",
271 RunFinished(RunFinishedEvent) => "RUN_FINISHED",
273 RunError(RunErrorEvent) => "RUN_ERROR",
275 StepStarted(StepStartedEvent) => "STEP_STARTED",
277 StepFinished(StepFinishedEvent) => "STEP_FINISHED",
279 ReasoningStart(ReasoningStartEvent) => "REASONING_START",
281 ReasoningMessageStart(ReasoningMessageStartEvent) => "REASONING_MESSAGE_START",
283 ReasoningMessageContent(ReasoningMessageContentEvent) => "REASONING_MESSAGE_CONTENT",
285 ReasoningMessageEnd(ReasoningMessageEndEvent) => "REASONING_MESSAGE_END",
287 ReasoningMessageChunk(ReasoningMessageChunkEvent) => "REASONING_MESSAGE_CHUNK",
289 ReasoningEnd(ReasoningEndEvent) => "REASONING_END",
291 ReasoningEncryptedValue(ReasoningEncryptedValueEvent) => "REASONING_ENCRYPTED_VALUE",
293 SubagentStarted(SubagentStartedEvent) => "SUBAGENT_STARTED",
295 SubagentFinished(SubagentFinishedEvent) => "SUBAGENT_FINISHED",
297 SubagentError(SubagentErrorEvent) => "SUBAGENT_ERROR",
299}
300
301impl fmt::Display for EventType {
302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303 f.write_str(self.as_str())
304 }
305}
306
307impl Event {
308 #[must_use]
310 pub fn with_timestamp(mut self, timestamp: i64) -> Self {
311 self.base_mut().timestamp = Some(timestamp);
312 self
313 }
314
315 #[must_use]
317 pub fn with_raw_event(mut self, raw_event: impl Into<Value>) -> Self {
318 self.base_mut().raw_event = Some(raw_event.into());
319 self
320 }
321
322 #[must_use]
325 pub fn with_metadata(mut self, metadata: JsonObject) -> Self {
326 self.base_mut().metadata = Some(metadata);
327 self
328 }
329
330 pub const fn metadata(&self) -> Option<&JsonObject> {
332 self.base().metadata.as_ref()
333 }
334
335 pub const fn is_deprecated(&self) -> bool {
338 matches!(
339 self.event_type(),
340 EventType::ThinkingStart
341 | EventType::ThinkingEnd
342 | EventType::ThinkingTextMessageStart
343 | EventType::ThinkingTextMessageContent
344 | EventType::ThinkingTextMessageEnd
345 )
346 }
347
348 fn attribution(&self) -> Option<&Option<SubagentRunId>> {
355 match self {
356 Self::TextMessageStart(e) => Some(&e.subagent_run_id),
357 Self::TextMessageContent(e) => Some(&e.subagent_run_id),
358 Self::TextMessageEnd(e) => Some(&e.subagent_run_id),
359 Self::TextMessageChunk(e) => Some(&e.subagent_run_id),
360 Self::ToolCallStart(e) => Some(&e.subagent_run_id),
361 Self::ToolCallArgs(e) => Some(&e.subagent_run_id),
362 Self::ToolCallEnd(e) => Some(&e.subagent_run_id),
363 Self::ToolCallChunk(e) => Some(&e.subagent_run_id),
364 Self::ToolCallResult(e) => Some(&e.subagent_run_id),
365 Self::StateSnapshot(e) => Some(&e.subagent_run_id),
366 Self::StateDelta(e) => Some(&e.subagent_run_id),
367 Self::ActivitySnapshot(e) => Some(&e.subagent_run_id),
368 Self::ActivityDelta(e) => Some(&e.subagent_run_id),
369 Self::Raw(e) => Some(&e.subagent_run_id),
370 Self::Custom(e) => Some(&e.subagent_run_id),
371 Self::StepStarted(e) => Some(&e.subagent_run_id),
372 Self::StepFinished(e) => Some(&e.subagent_run_id),
373 Self::ReasoningStart(e) => Some(&e.subagent_run_id),
374 Self::ReasoningMessageStart(e) => Some(&e.subagent_run_id),
375 Self::ReasoningMessageContent(e) => Some(&e.subagent_run_id),
376 Self::ReasoningMessageEnd(e) => Some(&e.subagent_run_id),
377 Self::ReasoningMessageChunk(e) => Some(&e.subagent_run_id),
378 Self::ReasoningEnd(e) => Some(&e.subagent_run_id),
379 Self::ReasoningEncryptedValue(e) => Some(&e.subagent_run_id),
380 Self::RunStarted(_)
381 | Self::RunFinished(_)
382 | Self::RunError(_)
383 | Self::MessagesSnapshot(_)
384 | Self::ThinkingStart(_)
385 | Self::ThinkingEnd(_)
386 | Self::ThinkingTextMessageStart(_)
387 | Self::ThinkingTextMessageContent(_)
388 | Self::ThinkingTextMessageEnd(_)
389 | Self::SubagentStarted(_)
390 | Self::SubagentFinished(_)
391 | Self::SubagentError(_) => None,
392 }
393 }
394
395 fn attribution_mut(&mut self) -> Option<&mut Option<SubagentRunId>> {
396 match self {
397 Self::TextMessageStart(e) => Some(&mut e.subagent_run_id),
398 Self::TextMessageContent(e) => Some(&mut e.subagent_run_id),
399 Self::TextMessageEnd(e) => Some(&mut e.subagent_run_id),
400 Self::TextMessageChunk(e) => Some(&mut e.subagent_run_id),
401 Self::ToolCallStart(e) => Some(&mut e.subagent_run_id),
402 Self::ToolCallArgs(e) => Some(&mut e.subagent_run_id),
403 Self::ToolCallEnd(e) => Some(&mut e.subagent_run_id),
404 Self::ToolCallChunk(e) => Some(&mut e.subagent_run_id),
405 Self::ToolCallResult(e) => Some(&mut e.subagent_run_id),
406 Self::StateSnapshot(e) => Some(&mut e.subagent_run_id),
407 Self::StateDelta(e) => Some(&mut e.subagent_run_id),
408 Self::ActivitySnapshot(e) => Some(&mut e.subagent_run_id),
409 Self::ActivityDelta(e) => Some(&mut e.subagent_run_id),
410 Self::Raw(e) => Some(&mut e.subagent_run_id),
411 Self::Custom(e) => Some(&mut e.subagent_run_id),
412 Self::StepStarted(e) => Some(&mut e.subagent_run_id),
413 Self::StepFinished(e) => Some(&mut e.subagent_run_id),
414 Self::ReasoningStart(e) => Some(&mut e.subagent_run_id),
415 Self::ReasoningMessageStart(e) => Some(&mut e.subagent_run_id),
416 Self::ReasoningMessageContent(e) => Some(&mut e.subagent_run_id),
417 Self::ReasoningMessageEnd(e) => Some(&mut e.subagent_run_id),
418 Self::ReasoningMessageChunk(e) => Some(&mut e.subagent_run_id),
419 Self::ReasoningEnd(e) => Some(&mut e.subagent_run_id),
420 Self::ReasoningEncryptedValue(e) => Some(&mut e.subagent_run_id),
421 Self::RunStarted(_)
422 | Self::RunFinished(_)
423 | Self::RunError(_)
424 | Self::MessagesSnapshot(_)
425 | Self::ThinkingStart(_)
426 | Self::ThinkingEnd(_)
427 | Self::ThinkingTextMessageStart(_)
428 | Self::ThinkingTextMessageContent(_)
429 | Self::ThinkingTextMessageEnd(_)
430 | Self::SubagentStarted(_)
431 | Self::SubagentFinished(_)
432 | Self::SubagentError(_) => None,
433 }
434 }
435
436 pub fn subagent_run_id(&self) -> Option<&SubagentRunId> {
443 match self {
444 Self::SubagentStarted(e) => Some(&e.subagent_run_id),
445 Self::SubagentFinished(e) => Some(&e.subagent_run_id),
446 Self::SubagentError(e) => Some(&e.subagent_run_id),
447 _ => self.attribution().and_then(Option::as_ref),
448 }
449 }
450
451 pub fn set_subagent_run_id(&mut self, id: impl Into<SubagentRunId>) -> bool {
458 let id = id.into();
459 match self {
460 Self::SubagentStarted(e) => e.subagent_run_id = id,
461 Self::SubagentFinished(e) => e.subagent_run_id = id,
462 Self::SubagentError(e) => e.subagent_run_id = id,
463 _ => match self.attribution_mut() {
464 Some(slot) => *slot = Some(id),
465 None => return false,
466 },
467 }
468 true
469 }
470
471 pub fn clear_subagent_run_id(&mut self) -> Option<SubagentRunId> {
477 self.attribution_mut().and_then(Option::take)
478 }
479
480 #[must_use]
483 pub fn with_subagent_run_id(mut self, id: impl Into<SubagentRunId>) -> Self {
484 self.set_subagent_run_id(id);
485 self
486 }
487}
488
489impl EventType {
490 pub const fn is_attributable(self) -> bool {
498 !matches!(
499 self,
500 Self::RunStarted
501 | Self::RunFinished
502 | Self::RunError
503 | Self::MessagesSnapshot
504 | Self::ThinkingStart
505 | Self::ThinkingEnd
506 | Self::ThinkingTextMessageStart
507 | Self::ThinkingTextMessageContent
508 | Self::ThinkingTextMessageEnd
509 | Self::SubagentStarted
510 | Self::SubagentFinished
511 | Self::SubagentError
512 )
513 }
514}