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}