1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
26pub enum Event {
27 Ping(PingEvent),
29 Usage(UsageEvent),
31 Status(StatusEvent),
33 Error(ErrorEvent),
35
36 BlockStart(BlockStart),
38 BlockDelta(BlockDelta),
40 BlockStop(BlockStop),
42 BlockAbort(BlockAbort),
44}
45
46#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
52pub struct PingEvent {
53 pub timestamp: Option<u64>,
54}
55
56#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
58pub struct UsageEvent {
59 pub input_tokens: Option<u64>,
61 pub output_tokens: Option<u64>,
63 pub total_tokens: Option<u64>,
65 pub cache_read_input_tokens: Option<u64>,
67 pub cache_creation_input_tokens: Option<u64>,
69}
70
71#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
73pub struct StatusEvent {
74 pub status: ResponseStatus,
75}
76
77#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
79pub enum ResponseStatus {
80 Started,
82 Completed,
84 Cancelled,
86 Failed,
88}
89
90#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
92pub struct ErrorEvent {
93 pub code: Option<String>,
94 pub message: String,
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
103pub enum BlockType {
104 Text,
106 Thinking,
108 ToolUse,
110 ToolResult,
112}
113
114#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
116pub struct BlockStart {
117 pub index: usize,
119 pub block_type: BlockType,
121 pub metadata: BlockMetadata,
123}
124
125impl BlockStart {
126 pub fn block_type(&self) -> BlockType {
127 self.block_type
128 }
129}
130
131#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
133pub enum BlockMetadata {
134 Text,
135 Thinking,
136 ToolUse { id: String, name: String },
137 ToolResult { tool_use_id: String },
138}
139
140#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
142pub struct BlockDelta {
143 pub index: usize,
145 pub delta: DeltaContent,
147}
148
149#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
151pub enum DeltaContent {
152 Text(String),
154 Thinking(String),
156 InputJson(String),
158}
159
160impl DeltaContent {
161 pub fn block_type(&self) -> BlockType {
163 match self {
164 DeltaContent::Text(_) => BlockType::Text,
165 DeltaContent::Thinking(_) => BlockType::Thinking,
166 DeltaContent::InputJson(_) => BlockType::ToolUse,
167 }
168 }
169}
170
171#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
173pub struct BlockStop {
174 pub index: usize,
176 pub block_type: BlockType,
178 pub stop_reason: Option<StopReason>,
180}
181
182impl BlockStop {
183 pub fn block_type(&self) -> BlockType {
184 self.block_type
185 }
186}
187
188#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
190pub struct BlockAbort {
191 pub index: usize,
193 pub block_type: BlockType,
195 pub reason: String,
197}
198
199impl BlockAbort {
200 pub fn block_type(&self) -> BlockType {
201 self.block_type
202 }
203}
204
205#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
207pub enum StopReason {
208 EndTurn,
210 MaxTokens,
212 StopSequence,
214 ToolUse,
216}
217
218impl Event {
223 pub fn text_block_start(index: usize) -> Self {
225 Event::BlockStart(BlockStart {
226 index,
227 block_type: BlockType::Text,
228 metadata: BlockMetadata::Text,
229 })
230 }
231
232 pub fn text_delta(index: usize, text: impl Into<String>) -> Self {
234 Event::BlockDelta(BlockDelta {
235 index,
236 delta: DeltaContent::Text(text.into()),
237 })
238 }
239
240 pub fn text_block_stop(index: usize, stop_reason: Option<StopReason>) -> Self {
242 Event::BlockStop(BlockStop {
243 index,
244 block_type: BlockType::Text,
245 stop_reason,
246 })
247 }
248
249 pub fn tool_use_start(index: usize, id: impl Into<String>, name: impl Into<String>) -> Self {
251 Event::BlockStart(BlockStart {
252 index,
253 block_type: BlockType::ToolUse,
254 metadata: BlockMetadata::ToolUse {
255 id: id.into(),
256 name: name.into(),
257 },
258 })
259 }
260
261 pub fn tool_input_delta(index: usize, json: impl Into<String>) -> Self {
263 Event::BlockDelta(BlockDelta {
264 index,
265 delta: DeltaContent::InputJson(json.into()),
266 })
267 }
268
269 pub fn tool_use_stop(index: usize) -> Self {
271 Event::BlockStop(BlockStop {
272 index,
273 block_type: BlockType::ToolUse,
274 stop_reason: Some(StopReason::ToolUse),
275 })
276 }
277
278 pub fn usage(input_tokens: u64, output_tokens: u64) -> Self {
280 Event::Usage(UsageEvent {
281 input_tokens: Some(input_tokens),
282 output_tokens: Some(output_tokens),
283 total_tokens: Some(input_tokens + output_tokens),
284 cache_read_input_tokens: None,
285 cache_creation_input_tokens: None,
286 })
287 }
288
289 pub fn ping() -> Self {
291 Event::Ping(PingEvent { timestamp: None })
292 }
293}
294
295impl From<crate::timeline::event::ResponseStatus> for ResponseStatus {
300 fn from(value: crate::timeline::event::ResponseStatus) -> Self {
301 match value {
302 crate::timeline::event::ResponseStatus::Started => ResponseStatus::Started,
303 crate::timeline::event::ResponseStatus::Completed => ResponseStatus::Completed,
304 crate::timeline::event::ResponseStatus::Cancelled => ResponseStatus::Cancelled,
305 crate::timeline::event::ResponseStatus::Failed => ResponseStatus::Failed,
306 }
307 }
308}
309
310impl From<crate::timeline::event::BlockType> for BlockType {
311 fn from(value: crate::timeline::event::BlockType) -> Self {
312 match value {
313 crate::timeline::event::BlockType::Text => BlockType::Text,
314 crate::timeline::event::BlockType::Thinking => BlockType::Thinking,
315 crate::timeline::event::BlockType::ToolUse => BlockType::ToolUse,
316 crate::timeline::event::BlockType::ToolResult => BlockType::ToolResult,
317 }
318 }
319}
320
321impl From<crate::timeline::event::BlockMetadata> for BlockMetadata {
322 fn from(value: crate::timeline::event::BlockMetadata) -> Self {
323 match value {
324 crate::timeline::event::BlockMetadata::Text => BlockMetadata::Text,
325 crate::timeline::event::BlockMetadata::Thinking => BlockMetadata::Thinking,
326 crate::timeline::event::BlockMetadata::ToolUse { id, name } => {
327 BlockMetadata::ToolUse { id, name }
328 }
329 crate::timeline::event::BlockMetadata::ToolResult { tool_use_id } => {
330 BlockMetadata::ToolResult { tool_use_id }
331 }
332 }
333 }
334}
335
336impl From<crate::timeline::event::DeltaContent> for DeltaContent {
337 fn from(value: crate::timeline::event::DeltaContent) -> Self {
338 match value {
339 crate::timeline::event::DeltaContent::Text(text) => DeltaContent::Text(text),
340 crate::timeline::event::DeltaContent::Thinking(text) => DeltaContent::Thinking(text),
341 crate::timeline::event::DeltaContent::InputJson(json) => DeltaContent::InputJson(json),
342 }
343 }
344}
345
346impl From<crate::timeline::event::StopReason> for StopReason {
347 fn from(value: crate::timeline::event::StopReason) -> Self {
348 match value {
349 crate::timeline::event::StopReason::EndTurn => StopReason::EndTurn,
350 crate::timeline::event::StopReason::MaxTokens => StopReason::MaxTokens,
351 crate::timeline::event::StopReason::StopSequence => StopReason::StopSequence,
352 crate::timeline::event::StopReason::ToolUse => StopReason::ToolUse,
353 }
354 }
355}
356
357impl From<crate::timeline::event::PingEvent> for PingEvent {
358 fn from(value: crate::timeline::event::PingEvent) -> Self {
359 PingEvent {
360 timestamp: value.timestamp,
361 }
362 }
363}
364
365impl From<crate::timeline::event::UsageEvent> for UsageEvent {
366 fn from(value: crate::timeline::event::UsageEvent) -> Self {
367 UsageEvent {
368 input_tokens: value.input_tokens,
369 output_tokens: value.output_tokens,
370 total_tokens: value.total_tokens,
371 cache_read_input_tokens: value.cache_read_input_tokens,
372 cache_creation_input_tokens: value.cache_creation_input_tokens,
373 }
374 }
375}
376
377impl From<crate::timeline::event::StatusEvent> for StatusEvent {
378 fn from(value: crate::timeline::event::StatusEvent) -> Self {
379 StatusEvent {
380 status: value.status.into(),
381 }
382 }
383}
384
385impl From<crate::timeline::event::ErrorEvent> for ErrorEvent {
386 fn from(value: crate::timeline::event::ErrorEvent) -> Self {
387 ErrorEvent {
388 code: value.code,
389 message: value.message,
390 }
391 }
392}
393
394impl From<crate::timeline::event::BlockStart> for BlockStart {
395 fn from(value: crate::timeline::event::BlockStart) -> Self {
396 BlockStart {
397 index: value.index,
398 block_type: value.block_type.into(),
399 metadata: value.metadata.into(),
400 }
401 }
402}
403
404impl From<crate::timeline::event::BlockDelta> for BlockDelta {
405 fn from(value: crate::timeline::event::BlockDelta) -> Self {
406 BlockDelta {
407 index: value.index,
408 delta: value.delta.into(),
409 }
410 }
411}
412
413impl From<crate::timeline::event::BlockStop> for BlockStop {
414 fn from(value: crate::timeline::event::BlockStop) -> Self {
415 BlockStop {
416 index: value.index,
417 block_type: value.block_type.into(),
418 stop_reason: value.stop_reason.map(Into::into),
419 }
420 }
421}
422
423impl From<crate::timeline::event::BlockAbort> for BlockAbort {
424 fn from(value: crate::timeline::event::BlockAbort) -> Self {
425 BlockAbort {
426 index: value.index,
427 block_type: value.block_type.into(),
428 reason: value.reason,
429 }
430 }
431}
432
433impl From<crate::timeline::event::Event> for Event {
434 fn from(value: crate::timeline::event::Event) -> Self {
435 match value {
436 crate::timeline::event::Event::Ping(p) => Event::Ping(p.into()),
437 crate::timeline::event::Event::Usage(u) => Event::Usage(u.into()),
438 crate::timeline::event::Event::Status(s) => Event::Status(s.into()),
439 crate::timeline::event::Event::Error(e) => Event::Error(e.into()),
440 crate::timeline::event::Event::BlockStart(s) => Event::BlockStart(s.into()),
441 crate::timeline::event::Event::BlockDelta(d) => Event::BlockDelta(d.into()),
442 crate::timeline::event::Event::BlockStop(s) => Event::BlockStop(s.into()),
443 crate::timeline::event::Event::BlockAbort(a) => Event::BlockAbort(a.into()),
444 }
445 }
446}