synwire_core/runnables/
events.rs1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9#[serde(tag = "kind")]
10#[non_exhaustive]
11pub enum StreamEvent {
12 #[serde(rename = "standard")]
14 Standard {
15 event: String,
17 name: String,
19 run_id: String,
21 #[serde(default)]
23 parent_ids: Vec<String>,
24 #[serde(default)]
26 tags: Vec<String>,
27 #[serde(default)]
29 metadata: HashMap<String, Value>,
30 data: EventData,
32 },
33 #[serde(rename = "custom")]
35 Custom {
36 name: String,
38 run_id: String,
40 #[serde(default)]
42 parent_ids: Vec<String>,
43 #[serde(default)]
45 tags: Vec<String>,
46 #[serde(default)]
48 metadata: HashMap<String, Value>,
49 data: Value,
51 },
52}
53
54#[derive(Debug, Clone, Default, Serialize, Deserialize)]
56pub struct EventData {
57 #[serde(default, skip_serializing_if = "Option::is_none")]
59 pub input: Option<Value>,
60 #[serde(default, skip_serializing_if = "Option::is_none")]
62 pub output: Option<Value>,
63 #[serde(default, skip_serializing_if = "Option::is_none")]
65 pub chunk: Option<Value>,
66 #[serde(default, skip_serializing_if = "Option::is_none")]
68 pub error: Option<String>,
69 #[serde(default, skip_serializing_if = "Option::is_none")]
72 pub category: Option<ContentCategory>,
73}
74
75pub fn dispatch_custom_event(name: impl Into<String>, data: serde_json::Value) -> StreamEvent {
81 StreamEvent::Custom {
82 name: name.into(),
83 run_id: String::new(),
84 parent_ids: Vec::new(),
85 tags: Vec::new(),
86 metadata: HashMap::new(),
87 data,
88 }
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
93#[non_exhaustive]
94pub enum ContentCategory {
95 Primary,
97 Secondary,
99}
100
101#[cfg(test)]
102#[allow(clippy::unwrap_used, clippy::panic)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn test_dispatch_custom_event() {
108 let data = serde_json::json!({"key": "value"});
109 let event = dispatch_custom_event("my_event", data.clone());
110 match event {
111 StreamEvent::Custom { name, data: d, .. } => {
112 assert_eq!(name, "my_event");
113 assert_eq!(d, data);
114 }
115 _ => panic!("expected Custom variant"),
116 }
117 }
118
119 #[test]
120 fn test_dispatch_custom_event_empty_defaults() {
121 let event = dispatch_custom_event("test", serde_json::Value::Null);
122 match event {
123 StreamEvent::Custom {
124 run_id,
125 parent_ids,
126 tags,
127 metadata,
128 ..
129 } => {
130 assert!(run_id.is_empty());
131 assert!(parent_ids.is_empty());
132 assert!(tags.is_empty());
133 assert!(metadata.is_empty());
134 }
135 _ => panic!("expected Custom variant"),
136 }
137 }
138}