Skip to main content

aios_protocol/
session.rs

1//! Session and checkpoint types.
2
3use crate::ids::*;
4use chrono::{DateTime, Utc};
5use serde::{Deserialize, Serialize};
6
7/// Session manifest — describes a session's identity and configuration.
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct SessionManifest {
10    pub session_id: SessionId,
11    pub owner: String,
12    pub created_at: DateTime<Utc>,
13    pub workspace_root: String,
14    pub model_routing: ModelRouting,
15    pub policy: serde_json::Value,
16}
17
18/// LLM model routing configuration.
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct ModelRouting {
21    pub primary_model: String,
22    pub fallback_models: Vec<String>,
23    pub temperature: f32,
24}
25
26impl Default for ModelRouting {
27    fn default() -> Self {
28        Self {
29            primary_model: "claude-sonnet-4-5-20250929".to_owned(),
30            fallback_models: vec!["gpt-4.1".to_owned()],
31            temperature: 0.2,
32        }
33    }
34}
35
36/// Branch metadata within a session.
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct BranchInfo {
39    pub branch_id: BranchId,
40    pub parent_branch: Option<BranchId>,
41    pub fork_sequence: u64,
42    pub head_sequence: u64,
43    pub merged_into: Option<BranchId>,
44}
45
46/// Result of merging two branches.
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct BranchMergeResult {
49    pub source_branch: BranchId,
50    pub target_branch: BranchId,
51    pub source_head_sequence: u64,
52    pub target_head_sequence: u64,
53}
54
55/// Checkpoint manifest — a snapshot of state at a specific point.
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct CheckpointManifest {
58    pub checkpoint_id: CheckpointId,
59    pub session_id: SessionId,
60    pub branch_id: BranchId,
61    pub created_at: DateTime<Utc>,
62    pub event_sequence: u64,
63    pub state_hash: String,
64    pub note: String,
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn model_routing_default() {
73        let mr = ModelRouting::default();
74        assert!(mr.primary_model.contains("claude"));
75        assert_eq!(mr.temperature, 0.2);
76    }
77
78    #[test]
79    fn session_manifest_serde_roundtrip() {
80        let manifest = SessionManifest {
81            session_id: SessionId::from_string("S1"),
82            owner: "test".into(),
83            created_at: Utc::now(),
84            workspace_root: "/tmp/test".into(),
85            model_routing: ModelRouting::default(),
86            policy: serde_json::json!({}),
87        };
88        let json = serde_json::to_string(&manifest).unwrap();
89        let back: SessionManifest = serde_json::from_str(&json).unwrap();
90        assert_eq!(back.session_id.as_str(), "S1");
91    }
92}