use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::message::Message;
use crate::model::{ModelResponse, Usage};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Event {
pub run_id: String,
pub seq: u64,
pub at: DateTime<Utc>,
pub kind: EventKind,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum EventKind {
RunStarted {
agent: String,
input: Message,
},
ModelCalled {
step: u32,
response: ModelResponse,
cost_usd: Option<f64>,
duration_ms: u64,
},
ModelFailed {
step: u32,
error: String,
#[serde(default)]
usage: Usage,
#[serde(default)]
cost_usd: Option<f64>,
},
ToolDenied {
call_id: String,
tool: String,
reason: String,
},
ApprovalRequested {
call_id: String,
tool: String,
input: Value,
reason: String,
},
ApprovalDecided {
call_id: String,
approved: bool,
by: Option<String>,
note: Option<String>,
},
ToolCompleted {
call_id: String,
tool: String,
output: Value,
is_error: bool,
duration_ms: u64,
},
BudgetExceeded {
reason: String,
},
RunCompleted {
output: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
structured: Option<Value>,
},
FinishRejected {
step: u32,
reason: String,
},
RunFailed {
error: String,
},
}
impl EventKind {
pub fn name(&self) -> &'static str {
match self {
EventKind::RunStarted { .. } => "run_started",
EventKind::ModelCalled { .. } => "model_called",
EventKind::ModelFailed { .. } => "model_failed",
EventKind::ToolDenied { .. } => "tool_denied",
EventKind::ApprovalRequested { .. } => "approval_requested",
EventKind::ApprovalDecided { .. } => "approval_decided",
EventKind::ToolCompleted { .. } => "tool_completed",
EventKind::BudgetExceeded { .. } => "budget_exceeded",
EventKind::RunCompleted { .. } => "run_completed",
EventKind::FinishRejected { .. } => "finish_rejected",
EventKind::RunFailed { .. } => "run_failed",
}
}
}