use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Event {
Ping(PingEvent),
Usage(UsageEvent),
Status(StatusEvent),
Error(ErrorEvent),
BlockStart(BlockStart),
BlockDelta(BlockDelta),
BlockStop(BlockStop),
BlockAbort(BlockAbort),
}
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct PingEvent {
pub timestamp: Option<u64>,
}
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct UsageEvent {
pub input_tokens: Option<u64>,
pub output_tokens: Option<u64>,
pub total_tokens: Option<u64>,
pub cache_read_input_tokens: Option<u64>,
pub cache_creation_input_tokens: Option<u64>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StatusEvent {
pub status: ResponseStatus,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ResponseStatus {
Started,
Completed,
Cancelled,
Failed,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ErrorEvent {
pub code: Option<String>,
pub message: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum BlockType {
Text,
Thinking,
ToolUse,
ToolResult,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BlockStart {
pub index: usize,
pub block_type: BlockType,
pub metadata: BlockMetadata,
}
impl BlockStart {
pub fn block_type(&self) -> BlockType {
self.block_type
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum BlockMetadata {
Text,
Thinking,
ToolUse { id: String, name: String },
ToolResult { tool_use_id: String },
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BlockDelta {
pub index: usize,
pub delta: DeltaContent,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum DeltaContent {
Text(String),
Thinking(String),
InputJson(String),
}
impl DeltaContent {
pub fn block_type(&self) -> BlockType {
match self {
DeltaContent::Text(_) => BlockType::Text,
DeltaContent::Thinking(_) => BlockType::Thinking,
DeltaContent::InputJson(_) => BlockType::ToolUse,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BlockStop {
pub index: usize,
pub block_type: BlockType,
pub stop_reason: Option<StopReason>,
}
impl BlockStop {
pub fn block_type(&self) -> BlockType {
self.block_type
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BlockAbort {
pub index: usize,
pub block_type: BlockType,
pub reason: String,
}
impl BlockAbort {
pub fn block_type(&self) -> BlockType {
self.block_type
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum StopReason {
EndTurn,
MaxTokens,
StopSequence,
ToolUse,
}
impl Event {
pub fn text_block_start(index: usize) -> Self {
Event::BlockStart(BlockStart {
index,
block_type: BlockType::Text,
metadata: BlockMetadata::Text,
})
}
pub fn text_delta(index: usize, text: impl Into<String>) -> Self {
Event::BlockDelta(BlockDelta {
index,
delta: DeltaContent::Text(text.into()),
})
}
pub fn text_block_stop(index: usize, stop_reason: Option<StopReason>) -> Self {
Event::BlockStop(BlockStop {
index,
block_type: BlockType::Text,
stop_reason,
})
}
pub fn tool_use_start(index: usize, id: impl Into<String>, name: impl Into<String>) -> Self {
Event::BlockStart(BlockStart {
index,
block_type: BlockType::ToolUse,
metadata: BlockMetadata::ToolUse {
id: id.into(),
name: name.into(),
},
})
}
pub fn tool_input_delta(index: usize, json: impl Into<String>) -> Self {
Event::BlockDelta(BlockDelta {
index,
delta: DeltaContent::InputJson(json.into()),
})
}
pub fn tool_use_stop(index: usize) -> Self {
Event::BlockStop(BlockStop {
index,
block_type: BlockType::ToolUse,
stop_reason: Some(StopReason::ToolUse),
})
}
pub fn usage(input_tokens: u64, output_tokens: u64) -> Self {
Event::Usage(UsageEvent {
input_tokens: Some(input_tokens),
output_tokens: Some(output_tokens),
total_tokens: Some(input_tokens + output_tokens),
cache_read_input_tokens: None,
cache_creation_input_tokens: None,
})
}
pub fn ping() -> Self {
Event::Ping(PingEvent { timestamp: None })
}
}
impl From<crate::timeline::event::ResponseStatus> for ResponseStatus {
fn from(value: crate::timeline::event::ResponseStatus) -> Self {
match value {
crate::timeline::event::ResponseStatus::Started => ResponseStatus::Started,
crate::timeline::event::ResponseStatus::Completed => ResponseStatus::Completed,
crate::timeline::event::ResponseStatus::Cancelled => ResponseStatus::Cancelled,
crate::timeline::event::ResponseStatus::Failed => ResponseStatus::Failed,
}
}
}
impl From<crate::timeline::event::BlockType> for BlockType {
fn from(value: crate::timeline::event::BlockType) -> Self {
match value {
crate::timeline::event::BlockType::Text => BlockType::Text,
crate::timeline::event::BlockType::Thinking => BlockType::Thinking,
crate::timeline::event::BlockType::ToolUse => BlockType::ToolUse,
crate::timeline::event::BlockType::ToolResult => BlockType::ToolResult,
}
}
}
impl From<crate::timeline::event::BlockMetadata> for BlockMetadata {
fn from(value: crate::timeline::event::BlockMetadata) -> Self {
match value {
crate::timeline::event::BlockMetadata::Text => BlockMetadata::Text,
crate::timeline::event::BlockMetadata::Thinking => BlockMetadata::Thinking,
crate::timeline::event::BlockMetadata::ToolUse { id, name } => {
BlockMetadata::ToolUse { id, name }
}
crate::timeline::event::BlockMetadata::ToolResult { tool_use_id } => {
BlockMetadata::ToolResult { tool_use_id }
}
}
}
}
impl From<crate::timeline::event::DeltaContent> for DeltaContent {
fn from(value: crate::timeline::event::DeltaContent) -> Self {
match value {
crate::timeline::event::DeltaContent::Text(text) => DeltaContent::Text(text),
crate::timeline::event::DeltaContent::Thinking(text) => DeltaContent::Thinking(text),
crate::timeline::event::DeltaContent::InputJson(json) => DeltaContent::InputJson(json),
}
}
}
impl From<crate::timeline::event::StopReason> for StopReason {
fn from(value: crate::timeline::event::StopReason) -> Self {
match value {
crate::timeline::event::StopReason::EndTurn => StopReason::EndTurn,
crate::timeline::event::StopReason::MaxTokens => StopReason::MaxTokens,
crate::timeline::event::StopReason::StopSequence => StopReason::StopSequence,
crate::timeline::event::StopReason::ToolUse => StopReason::ToolUse,
}
}
}
impl From<crate::timeline::event::PingEvent> for PingEvent {
fn from(value: crate::timeline::event::PingEvent) -> Self {
PingEvent {
timestamp: value.timestamp,
}
}
}
impl From<crate::timeline::event::UsageEvent> for UsageEvent {
fn from(value: crate::timeline::event::UsageEvent) -> Self {
UsageEvent {
input_tokens: value.input_tokens,
output_tokens: value.output_tokens,
total_tokens: value.total_tokens,
cache_read_input_tokens: value.cache_read_input_tokens,
cache_creation_input_tokens: value.cache_creation_input_tokens,
}
}
}
impl From<crate::timeline::event::StatusEvent> for StatusEvent {
fn from(value: crate::timeline::event::StatusEvent) -> Self {
StatusEvent {
status: value.status.into(),
}
}
}
impl From<crate::timeline::event::ErrorEvent> for ErrorEvent {
fn from(value: crate::timeline::event::ErrorEvent) -> Self {
ErrorEvent {
code: value.code,
message: value.message,
}
}
}
impl From<crate::timeline::event::BlockStart> for BlockStart {
fn from(value: crate::timeline::event::BlockStart) -> Self {
BlockStart {
index: value.index,
block_type: value.block_type.into(),
metadata: value.metadata.into(),
}
}
}
impl From<crate::timeline::event::BlockDelta> for BlockDelta {
fn from(value: crate::timeline::event::BlockDelta) -> Self {
BlockDelta {
index: value.index,
delta: value.delta.into(),
}
}
}
impl From<crate::timeline::event::BlockStop> for BlockStop {
fn from(value: crate::timeline::event::BlockStop) -> Self {
BlockStop {
index: value.index,
block_type: value.block_type.into(),
stop_reason: value.stop_reason.map(Into::into),
}
}
}
impl From<crate::timeline::event::BlockAbort> for BlockAbort {
fn from(value: crate::timeline::event::BlockAbort) -> Self {
BlockAbort {
index: value.index,
block_type: value.block_type.into(),
reason: value.reason,
}
}
}
impl From<crate::timeline::event::Event> for Event {
fn from(value: crate::timeline::event::Event) -> Self {
match value {
crate::timeline::event::Event::Ping(p) => Event::Ping(p.into()),
crate::timeline::event::Event::Usage(u) => Event::Usage(u.into()),
crate::timeline::event::Event::Status(s) => Event::Status(s.into()),
crate::timeline::event::Event::Error(e) => Event::Error(e.into()),
crate::timeline::event::Event::BlockStart(s) => Event::BlockStart(s.into()),
crate::timeline::event::Event::BlockDelta(d) => Event::BlockDelta(d.into()),
crate::timeline::event::Event::BlockStop(s) => Event::BlockStop(s.into()),
crate::timeline::event::Event::BlockAbort(a) => Event::BlockAbort(a.into()),
}
}
}