switchyard_libsy/core/
state.rs1use std::collections::{BTreeMap, HashMap};
7
8use serde::{Deserialize, Serialize};
9
10use crate::algorithms::util::tool_signals::ToolSignals;
11
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14#[serde(rename_all = "snake_case")]
15pub enum StateValue {
16 String(String),
18 Count(u32),
20 Bool(bool),
22}
23
24#[derive(Debug, Clone, Default, Serialize, Deserialize)]
26pub struct State {
27 #[serde(skip)]
31 pub tool_signals: Option<ToolSignals>,
32 #[serde(skip)]
34 pub target_prompts: HashMap<switchyard_protocol::ModelId, String>,
35 #[serde(flatten)]
37 pub extra: BTreeMap<String, StateValue>,
38}
39
40impl PartialEq for State {
41 fn eq(&self, other: &Self) -> bool {
42 self.extra == other.extra
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn state_round_trips_through_json_and_compares_extra_only() -> serde_json::Result<()> {
52 let mut state = State::default();
53 state
54 .extra
55 .insert("capable_hold_turns".to_string(), StateValue::Count(2));
56 state.extra.insert(
57 "fall_open".to_string(),
58 StateValue::String("capable".to_string()),
59 );
60 state
61 .extra
62 .insert("vgr_handoff_sent".to_string(), StateValue::Bool(true));
63 let json = serde_json::json!({
64 "capable_hold_turns": {"count": 2},
65 "fall_open": {"string": "capable"},
66 "vgr_handoff_sent": {"bool": true},
67 });
68
69 let with_signals = State {
70 tool_signals: Some(ToolSignals::default()),
71 ..state.clone()
72 };
73 assert_eq!(serde_json::to_value(&with_signals)?, json);
74 assert_eq!(serde_json::from_value::<State>(json)?, state);
75 assert_eq!(with_signals, state);
76 Ok(())
77 }
78}