use serde::{Deserialize, Serialize};
use crate::message::AgentMessage;
use crate::session_event::{CompactionReason, CompactionResult};
pub type AgentEventSink = Box<dyn Fn(AgentEvent) + Send + Sync>;
#[non_exhaustive]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum AgentEvent {
AgentStart,
AgentEnd { messages: Vec<AgentMessage> },
TurnStart,
TurnEnd {
message: AgentMessage,
tool_results: Vec<opi_ai::message::ToolResultMessage>,
},
MessageStart { message: AgentMessage },
MessageUpdate {
message: AgentMessage,
#[serde(
serialize_with = "serde_json_bridge::serialize",
deserialize_with = "deserialize_boxed_stream_event"
)]
assistant_event: Box<opi_ai::stream::AssistantStreamEvent>,
},
MessageEnd { message: AgentMessage },
ToolExecutionStart {
tool_call_id: String,
tool_name: String,
args: serde_json::Value,
},
ToolExecutionUpdate {
tool_call_id: String,
tool_name: String,
args: serde_json::Value,
partial_result: serde_json::Value,
},
ToolExecutionEnd {
tool_call_id: String,
tool_name: String,
result: serde_json::Value,
details: Option<serde_json::Value>,
is_error: bool,
},
QueueUpdate {
steering: Vec<String>,
follow_up: Vec<String>,
},
AutoRetryStart {
attempt: u32,
max_attempts: u32,
delay_ms: u64,
error_message: String,
},
AutoRetryEnd {
success: bool,
attempt: u32,
final_error: Option<String>,
},
CompactionStart { reason: CompactionReason },
CompactionEnd {
reason: CompactionReason,
result: Option<CompactionResult>,
aborted: bool,
error_message: Option<String>,
},
SessionPersistError { message: String },
}
fn deserialize_boxed_stream_event<'de, D>(
deserializer: D,
) -> Result<Box<opi_ai::stream::AssistantStreamEvent>, D::Error>
where
D: serde::Deserializer<'de>,
{
let v = serde_json::Value::deserialize(deserializer)?;
let event: opi_ai::stream::AssistantStreamEvent =
serde_json::from_value(v).map_err(serde::de::Error::custom)?;
Ok(Box::new(event))
}
mod serde_json_bridge {
use serde::{Serialize as _, Serializer};
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: serde::Serialize,
S: Serializer,
{
serde_json::to_value(value)
.map_err(serde::ser::Error::custom)
.and_then(|v| v.serialize(serializer))
}
}