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::llm_client::event::ResponseStatus> for ResponseStatus {
300 fn from(value: crate::llm_client::event::ResponseStatus) -> Self {
301 match value {
302 crate::llm_client::event::ResponseStatus::Started => ResponseStatus::Started,
303 crate::llm_client::event::ResponseStatus::Completed => ResponseStatus::Completed,
304 crate::llm_client::event::ResponseStatus::Cancelled => ResponseStatus::Cancelled,
305 crate::llm_client::event::ResponseStatus::Failed => ResponseStatus::Failed,
306 }
307 }
308}
309
310impl From<crate::llm_client::event::BlockType> for BlockType {
311 fn from(value: crate::llm_client::event::BlockType) -> Self {
312 match value {
313 crate::llm_client::event::BlockType::Text => BlockType::Text,
314 crate::llm_client::event::BlockType::Thinking => BlockType::Thinking,
315 crate::llm_client::event::BlockType::ToolUse => BlockType::ToolUse,
316 crate::llm_client::event::BlockType::ToolResult => BlockType::ToolResult,
317 }
318 }
319}
320
321impl From<crate::llm_client::event::BlockMetadata> for BlockMetadata {
322 fn from(value: crate::llm_client::event::BlockMetadata) -> Self {
323 match value {
324 crate::llm_client::event::BlockMetadata::Text => BlockMetadata::Text,
325 crate::llm_client::event::BlockMetadata::Thinking => BlockMetadata::Thinking,
326 crate::llm_client::event::BlockMetadata::ToolUse { id, name } => {
327 BlockMetadata::ToolUse { id, name }
328 }
329 crate::llm_client::event::BlockMetadata::ToolResult { tool_use_id } => {
330 BlockMetadata::ToolResult { tool_use_id }
331 }
332 }
333 }
334}
335
336impl From<crate::llm_client::event::DeltaContent> for DeltaContent {
337 fn from(value: crate::llm_client::event::DeltaContent) -> Self {
338 match value {
339 crate::llm_client::event::DeltaContent::Text(text) => DeltaContent::Text(text),
340 crate::llm_client::event::DeltaContent::Thinking(text) => DeltaContent::Thinking(text),
341 crate::llm_client::event::DeltaContent::InputJson(json) => {
342 DeltaContent::InputJson(json)
343 }
344 }
345 }
346}
347
348impl From<crate::llm_client::event::StopReason> for StopReason {
349 fn from(value: crate::llm_client::event::StopReason) -> Self {
350 match value {
351 crate::llm_client::event::StopReason::EndTurn => StopReason::EndTurn,
352 crate::llm_client::event::StopReason::MaxTokens => StopReason::MaxTokens,
353 crate::llm_client::event::StopReason::StopSequence => StopReason::StopSequence,
354 crate::llm_client::event::StopReason::ToolUse => StopReason::ToolUse,
355 }
356 }
357}
358
359impl From<crate::llm_client::event::PingEvent> for PingEvent {
360 fn from(value: crate::llm_client::event::PingEvent) -> Self {
361 PingEvent {
362 timestamp: value.timestamp,
363 }
364 }
365}
366
367impl From<crate::llm_client::event::UsageEvent> for UsageEvent {
368 fn from(value: crate::llm_client::event::UsageEvent) -> Self {
369 UsageEvent {
370 input_tokens: value.input_tokens,
371 output_tokens: value.output_tokens,
372 total_tokens: value.total_tokens,
373 cache_read_input_tokens: value.cache_read_input_tokens,
374 cache_creation_input_tokens: value.cache_creation_input_tokens,
375 }
376 }
377}
378
379impl From<crate::llm_client::event::StatusEvent> for StatusEvent {
380 fn from(value: crate::llm_client::event::StatusEvent) -> Self {
381 StatusEvent {
382 status: value.status.into(),
383 }
384 }
385}
386
387impl From<crate::llm_client::event::ErrorEvent> for ErrorEvent {
388 fn from(value: crate::llm_client::event::ErrorEvent) -> Self {
389 ErrorEvent {
390 code: value.code,
391 message: value.message,
392 }
393 }
394}
395
396impl From<crate::llm_client::event::BlockStart> for BlockStart {
397 fn from(value: crate::llm_client::event::BlockStart) -> Self {
398 BlockStart {
399 index: value.index,
400 block_type: value.block_type.into(),
401 metadata: value.metadata.into(),
402 }
403 }
404}
405
406impl From<crate::llm_client::event::BlockDelta> for BlockDelta {
407 fn from(value: crate::llm_client::event::BlockDelta) -> Self {
408 BlockDelta {
409 index: value.index,
410 delta: value.delta.into(),
411 }
412 }
413}
414
415impl From<crate::llm_client::event::BlockStop> for BlockStop {
416 fn from(value: crate::llm_client::event::BlockStop) -> Self {
417 BlockStop {
418 index: value.index,
419 block_type: value.block_type.into(),
420 stop_reason: value.stop_reason.map(Into::into),
421 }
422 }
423}
424
425impl From<crate::llm_client::event::BlockAbort> for BlockAbort {
426 fn from(value: crate::llm_client::event::BlockAbort) -> Self {
427 BlockAbort {
428 index: value.index,
429 block_type: value.block_type.into(),
430 reason: value.reason,
431 }
432 }
433}
434
435impl From<crate::llm_client::event::Event> for Event {
436 fn from(value: crate::llm_client::event::Event) -> Self {
437 match value {
438 crate::llm_client::event::Event::Ping(p) => Event::Ping(p.into()),
439 crate::llm_client::event::Event::Usage(u) => Event::Usage(u.into()),
440 crate::llm_client::event::Event::Status(s) => Event::Status(s.into()),
441 crate::llm_client::event::Event::Error(e) => Event::Error(e.into()),
442 crate::llm_client::event::Event::BlockStart(s) => Event::BlockStart(s.into()),
443 crate::llm_client::event::Event::BlockDelta(d) => Event::BlockDelta(d.into()),
444 crate::llm_client::event::Event::BlockStop(s) => Event::BlockStop(s.into()),
445 crate::llm_client::event::Event::BlockAbort(a) => Event::BlockAbort(a.into()),
446 }
447 }
448}