sh_layer2/checkpoint_system/
mod.rs1mod atomic;
13mod checksum;
14mod recovery;
15mod retry;
16mod writer;
17
18pub use atomic::AtomicFileWriter;
19pub use checksum::ChecksumUtils;
20pub use recovery::CrashRecovery;
21pub use retry::{
22 ErrorCategory, ErrorRecovery, FallbackStrategy, InterruptedSession, RecoveryAction,
23 RecoveryLayer, RecoveryResult, RetryPolicy, SessionRecovery,
24};
25pub use writer::CheckpointWriter;
26
27use async_trait::async_trait;
28use serde::{Deserialize, Serialize};
29use std::path::Path;
30
31use crate::types::{CheckpointId, CheckpointMeta, Layer2Result, SessionId};
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct CheckpointData {
36 pub checkpoint_id: CheckpointId,
37 pub session_id: SessionId,
38 pub created_at: chrono::DateTime<chrono::Utc>,
39 pub trigger: String,
40 pub iteration: i32,
41 pub messages: Vec<serde_json::Value>,
42 pub tool_calls_pending: Vec<serde_json::Value>,
43 pub tool_results: serde_json::Value,
44 pub tokens_used: i64,
45 pub cost_estimate: f64,
46 pub resume_hint: Option<String>,
47}
48
49#[async_trait]
51pub trait CheckpointSystemTrait: Send + Sync {
52 async fn save(&self, data: &CheckpointData) -> Layer2Result<CheckpointId>;
54
55 async fn load(
57 &self,
58 session_id: &SessionId,
59 checkpoint_id: Option<&CheckpointId>,
60 ) -> Layer2Result<Option<CheckpointData>>;
61
62 async fn list(&self, session_id: &SessionId) -> Layer2Result<Vec<CheckpointMeta>>;
64
65 async fn delete(
67 &self,
68 session_id: &SessionId,
69 checkpoint_id: &CheckpointId,
70 ) -> Layer2Result<bool>;
71
72 fn verify(&self, path: &Path) -> Layer2Result<bool>;
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn test_checkpoint_data_creation() {
82 let data = CheckpointData {
83 checkpoint_id: CheckpointId::new(),
84 session_id: SessionId::new(),
85 created_at: chrono::Utc::now(),
86 trigger: "manual".to_string(),
87 iteration: 0,
88 messages: Vec::new(),
89 tool_calls_pending: Vec::new(),
90 tool_results: serde_json::Value::Null,
91 tokens_used: 0,
92 cost_estimate: 0.0,
93 resume_hint: None,
94 };
95
96 assert_eq!(data.trigger, "manual");
97 }
98}