1use crate::harness::Harness;
9
10#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13#[cfg_attr(feature = "serde", serde(transparent))]
14pub struct SessionId(pub String);
15
16impl SessionId {
17 pub fn new(id: impl Into<String>) -> Self {
19 Self(id.into())
20 }
21
22 pub fn as_str(&self) -> &str {
24 &self.0
25 }
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31pub enum TurnRole {
32 User,
34 Assistant,
36 System,
38 Tool,
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48pub struct SessionTurn {
49 pub session_id: SessionId,
51 pub turn_index: u64,
53 pub role: TurnRole,
55 pub content: String,
57 pub timestamp: String,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq)]
63#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
64pub struct Session {
65 pub id: SessionId,
67 pub harness: Harness,
69 pub channel: Option<String>,
71 pub started_at: String,
73 pub ended_at: Option<String>,
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn session_turn_round_trips() {
83 let t = SessionTurn {
84 session_id: SessionId::new("sess_1"),
85 turn_index: 0,
86 role: TurnRole::User,
87 content: "hello".into(),
88 timestamp: "2026-07-05T12:00:00Z".into(),
89 };
90 assert_eq!(t.session_id.as_str(), "sess_1");
91 assert_eq!(t.role, TurnRole::User);
92 assert_eq!(t.turn_index, 0);
93 }
94}