use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "kind")]
#[non_exhaustive]
pub enum StreamEvent {
#[serde(rename = "standard")]
Standard {
event: String,
name: String,
run_id: String,
#[serde(default)]
parent_ids: Vec<String>,
#[serde(default)]
tags: Vec<String>,
#[serde(default)]
metadata: HashMap<String, Value>,
data: EventData,
},
#[serde(rename = "custom")]
Custom {
name: String,
run_id: String,
#[serde(default)]
parent_ids: Vec<String>,
#[serde(default)]
tags: Vec<String>,
#[serde(default)]
metadata: HashMap<String, Value>,
data: Value,
},
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct EventData {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub input: Option<Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub output: Option<Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub chunk: Option<Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub category: Option<ContentCategory>,
}
pub fn dispatch_custom_event(name: impl Into<String>, data: serde_json::Value) -> StreamEvent {
StreamEvent::Custom {
name: name.into(),
run_id: String::new(),
parent_ids: Vec::new(),
tags: Vec::new(),
metadata: HashMap::new(),
data,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum ContentCategory {
Primary,
Secondary,
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::panic)]
mod tests {
use super::*;
#[test]
fn test_dispatch_custom_event() {
let data = serde_json::json!({"key": "value"});
let event = dispatch_custom_event("my_event", data.clone());
match event {
StreamEvent::Custom { name, data: d, .. } => {
assert_eq!(name, "my_event");
assert_eq!(d, data);
}
_ => panic!("expected Custom variant"),
}
}
#[test]
fn test_dispatch_custom_event_empty_defaults() {
let event = dispatch_custom_event("test", serde_json::Value::Null);
match event {
StreamEvent::Custom {
run_id,
parent_ids,
tags,
metadata,
..
} => {
assert!(run_id.is_empty());
assert!(parent_ids.is_empty());
assert!(tags.is_empty());
assert!(metadata.is_empty());
}
_ => panic!("expected Custom variant"),
}
}
}