use cognis_core::Event;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StreamMode {
Values,
Updates,
Messages,
Tasks,
Checkpoints,
Debug,
Custom,
}
impl StreamMode {
pub fn matches(self, event: &Event) -> bool {
match self {
StreamMode::Debug => true,
StreamMode::Values => matches!(event, Event::OnEnd { .. }),
StreamMode::Updates => matches!(event, Event::OnNodeEnd { .. }),
StreamMode::Tasks => matches!(event, Event::OnNodeStart { .. }),
StreamMode::Messages => matches!(
event,
Event::OnLlmToken { .. } | Event::OnToolStart { .. } | Event::OnToolEnd { .. }
),
StreamMode::Checkpoints => matches!(event, Event::OnCheckpoint { .. }),
StreamMode::Custom => matches!(event, Event::Custom { .. }),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct StreamModes(Vec<StreamMode>);
impl StreamModes {
pub fn none() -> Self {
Self(Vec::new())
}
pub fn debug() -> Self {
Self(vec![StreamMode::Debug])
}
pub fn only(mode: StreamMode) -> Self {
Self(vec![mode])
}
pub fn from_modes<I: IntoIterator<Item = StreamMode>>(modes: I) -> Self {
Self(modes.into_iter().collect())
}
pub fn with(mut self, mode: StreamMode) -> Self {
if !self.0.contains(&mode) {
self.0.push(mode);
}
self
}
pub fn matches(&self, event: &Event) -> bool {
self.0.iter().any(|m| m.matches(event))
}
pub fn modes(&self) -> &[StreamMode] {
&self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
use uuid::Uuid;
fn ev_node_start() -> Event {
Event::OnNodeStart {
node: "x".into(),
step: 0,
run_id: Uuid::nil(),
}
}
fn ev_node_end() -> Event {
Event::OnNodeEnd {
node: "x".into(),
step: 0,
output: serde_json::Value::Null,
run_id: Uuid::nil(),
}
}
fn ev_on_end() -> Event {
Event::OnEnd {
runnable: "graph".into(),
run_id: Uuid::nil(),
output: serde_json::Value::Null,
}
}
fn ev_token() -> Event {
Event::OnLlmToken {
token: "t".into(),
run_id: Uuid::nil(),
}
}
#[test]
fn debug_matches_everything() {
assert!(StreamMode::Debug.matches(&ev_node_start()));
assert!(StreamMode::Debug.matches(&ev_node_end()));
assert!(StreamMode::Debug.matches(&ev_token()));
}
#[test]
fn tasks_matches_only_starts() {
assert!(StreamMode::Tasks.matches(&ev_node_start()));
assert!(!StreamMode::Tasks.matches(&ev_node_end()));
}
#[test]
fn updates_matches_only_node_end() {
assert!(StreamMode::Updates.matches(&ev_node_end()));
assert!(!StreamMode::Updates.matches(&ev_node_start()));
}
#[test]
fn messages_matches_only_llm_or_tool() {
assert!(StreamMode::Messages.matches(&ev_token()));
assert!(!StreamMode::Messages.matches(&ev_node_end()));
}
#[test]
fn values_matches_only_graph_on_end() {
assert!(StreamMode::Values.matches(&ev_on_end()));
assert!(!StreamMode::Values.matches(&ev_node_end()));
}
#[test]
fn modes_set_unions_filters() {
let modes = StreamModes::only(StreamMode::Tasks).with(StreamMode::Updates);
assert!(modes.matches(&ev_node_start()));
assert!(modes.matches(&ev_node_end()));
assert!(!modes.matches(&ev_token()));
}
}