Skip to main content

bamboo_domain/session/
persistence.rs

1use std::io;
2use std::sync::Arc;
3
4use crate::session::types::Session;
5
6/// Port for runtime (non-authoritative) session persistence.
7///
8/// Implementors must:
9/// - Serialize concurrent saves per session ID.
10/// - Merge on-disk authoritative metadata (`title`, `pinned`, `title_version`,
11///   `metadata_version`) before writing, so UI edits are never clobbered.
12#[async_trait::async_trait]
13pub trait RuntimeSessionPersistence: Send + Sync {
14    /// Persist the session, merging any newer authoritative metadata from disk.
15    async fn save_runtime_session(&self, session: &mut Session) -> io::Result<()>;
16
17    /// Load the latest runtime-visible session snapshot when the persistence
18    /// implementation can coordinate reads. Tools may update a repository-owned
19    /// clone while an agent loop holds its own live Session; the loop uses this
20    /// hook to merge narrowly-scoped tool side effects before its next save.
21    async fn load_runtime_session(&self, _session_id: &str) -> io::Result<Option<Session>> {
22        Ok(None)
23    }
24
25    /// Append one JSON-line analysis record to the session's append-only
26    /// token-usage log (see [`Storage::append_token_usage_record`]). Defaults to
27    /// a no-op so non-file-backed persisters are unaffected.
28    ///
29    /// [`Storage::append_token_usage_record`]: crate::storage::Storage::append_token_usage_record
30    async fn append_token_usage_record(&self, session_id: &str, json_line: &str) -> io::Result<()> {
31        let _ = (session_id, json_line);
32        Ok(())
33    }
34}
35
36#[async_trait::async_trait]
37impl<T: RuntimeSessionPersistence + ?Sized> RuntimeSessionPersistence for Arc<T> {
38    async fn save_runtime_session(&self, session: &mut Session) -> io::Result<()> {
39        (**self).save_runtime_session(session).await
40    }
41
42    async fn load_runtime_session(&self, session_id: &str) -> io::Result<Option<Session>> {
43        (**self).load_runtime_session(session_id).await
44    }
45
46    async fn append_token_usage_record(&self, session_id: &str, json_line: &str) -> io::Result<()> {
47        (**self)
48            .append_token_usage_record(session_id, json_line)
49            .await
50    }
51}