use std::{
sync::{Arc, Mutex},
time::SystemTime,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum EventOutcome {
#[serde(rename = "success")]
Success { output: serde_json::Value },
#[serde(rename = "error")]
Error { message: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct McpToolCallEvent {
pub server: String,
pub tool: String,
pub cached_client: bool,
pub args: Option<serde_json::Value>,
pub outcome: EventOutcome,
pub started_at: SystemTime,
pub ended_at: SystemTime,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CallbackInvocationEvent {
pub id: String,
pub args: Option<serde_json::Value>,
pub outcome: EventOutcome,
pub started_at: SystemTime,
pub ended_at: SystemTime,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum RegistryEvent {
#[serde(rename = "mcp_tool_call")]
McpToolCall(McpToolCallEvent),
#[serde(rename = "callback_invocation")]
CallbackInvocation(CallbackInvocationEvent),
}
impl RegistryEvent {
pub fn started_at(&self) -> SystemTime {
match self {
RegistryEvent::McpToolCall(e) => e.started_at,
RegistryEvent::CallbackInvocation(e) => e.started_at,
}
}
}
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct RegistryTrace {
events: Arc<Mutex<Vec<RegistryEvent>>>,
}
impl RegistryTrace {
pub fn new() -> Self {
Self::default()
}
pub fn push(&self, event: RegistryEvent) {
if let Ok(mut events) = self.events.lock() {
events.push(event);
}
}
pub fn events(&self) -> Vec<RegistryEvent> {
self.events.lock().map(|e| e.clone()).unwrap_or_default()
}
pub fn len(&self) -> usize {
self.events.lock().map(|e| e.len()).unwrap_or(0)
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}