use serde::{Deserialize, Serialize};
use crate::message::Message;
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct Session {
pub history: Vec<Message>,
pub driver_state: serde_json::Value,
#[serde(default)]
pub cost_usd: f64,
#[serde(default)]
pub usage_stats: serde_json::Value,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::message::{Content, Role};
#[test]
fn session_round_trips_with_driver_state() {
let session = Session {
history: vec![Message {
role: Role::User,
content: vec![Content::Text("fix the test".into())],
}],
driver_state: serde_json::json!({ "key": "interactive:main" }),
cost_usd: 0.0,
usage_stats: serde_json::Value::Null,
};
let json = serde_json::to_string(&session).unwrap();
let back: Session = serde_json::from_str(&json).unwrap();
assert_eq!(back, session);
}
#[test]
fn a_session_written_before_cost_existed_loads_as_free() {
let session = Session {
history: vec![Message::text(Role::User, "hi")],
..Session::default()
};
let mut value = serde_json::to_value(&session).unwrap();
value
.as_object_mut()
.unwrap()
.remove("cost_usd")
.expect("the field was written");
let session: Session = serde_json::from_value(value).unwrap();
assert_eq!(session.cost_usd, 0.0);
}
#[test]
fn a_session_written_before_usage_stats_existed_loads_without() {
let session = Session {
history: vec![Message::text(Role::User, "hi")],
..Session::default()
};
let mut value = serde_json::to_value(&session).unwrap();
value
.as_object_mut()
.unwrap()
.remove("usage_stats")
.expect("the field was written");
let session: Session = serde_json::from_value(value).unwrap();
assert_eq!(session.usage_stats, serde_json::Value::Null);
}
#[test]
fn the_usage_stats_blob_round_trips_through_the_saved_format() {
let session = Session {
usage_stats: serde_json::json!({ "transcript": { "requests": 3 } }),
..Session::default()
};
let json = serde_json::to_string(&session).unwrap();
let back: Session = serde_json::from_str(&json).unwrap();
assert_eq!(back.usage_stats["transcript"]["requests"], 3);
}
#[test]
fn the_cost_round_trips_through_the_saved_format() {
let session = Session {
cost_usd: 4.275,
..Session::default()
};
let json = serde_json::to_string(&session).unwrap();
let back: Session = serde_json::from_str(&json).unwrap();
assert_eq!(back.cost_usd, 4.275);
}
}