starweaver_session/store/
contract.rs1use async_trait::async_trait;
4use starweaver_context::{AgentCheckpoint, ResumableState};
5use starweaver_core::{RunId, SessionId};
6use starweaver_stream::AgentStreamRecord;
7
8use crate::{
9 approval::{ApprovalRecord, DeferredToolRecord},
10 claim::HitlResumeClaim,
11 error::{SessionStoreError, SessionStoreResult},
12 evidence::RunEvidenceCommit,
13 publication::{PendingStreamPublication, StreamPublicationTarget},
14 records::{
15 EnvironmentStateRef, RunRecord, RunStatus, SessionRecord, SessionStatus, StreamCursorRef,
16 },
17 resume::SessionResumeSnapshot,
18 trace::{CompactRunTrace, CompactSessionTrace},
19};
20
21#[derive(Clone, Debug, Default, Eq, PartialEq)]
23pub struct SessionFilter {
24 pub status: Option<SessionStatus>,
26 pub profile: Option<String>,
28 pub workspace: Option<String>,
30 pub limit: Option<usize>,
32}
33
34#[async_trait]
36pub trait SessionStore: Send + Sync {
37 async fn commit_run_evidence(&self, commit: RunEvidenceCommit)
42 -> SessionStoreResult<RunRecord>;
43
44 async fn commit_checkpoint(
50 &self,
51 session_id: &SessionId,
52 checkpoint: AgentCheckpoint,
53 ) -> SessionStoreResult<()>;
54
55 async fn claim_hitl_resume(&self, _claim: HitlResumeClaim) -> SessionStoreResult<()> {
60 Err(SessionStoreError::Failed(
61 "session store does not support exclusive HITL resume claims".to_string(),
62 ))
63 }
64
65 async fn mark_hitl_resume_started(
67 &self,
68 _session_id: &SessionId,
69 _run_id: &RunId,
70 _claim_id: &str,
71 ) -> SessionStoreResult<()> {
72 Err(SessionStoreError::Failed(
73 "session store does not support exclusive HITL resume claims".to_string(),
74 ))
75 }
76
77 async fn release_hitl_resume_claim(
79 &self,
80 _session_id: &SessionId,
81 _run_id: &RunId,
82 _claim_id: &str,
83 ) -> SessionStoreResult<()> {
84 Err(SessionStoreError::Failed(
85 "session store does not support exclusive HITL resume claims".to_string(),
86 ))
87 }
88
89 async fn pending_stream_publications(
91 &self,
92 _session_id: &SessionId,
93 ) -> SessionStoreResult<Vec<PendingStreamPublication>> {
94 Err(SessionStoreError::Failed(
95 "session store does not support transactional stream publication".to_string(),
96 ))
97 }
98
99 async fn acknowledge_stream_publication(
101 &self,
102 _publication_id: &str,
103 _target: StreamPublicationTarget,
104 ) -> SessionStoreResult<()> {
105 Err(SessionStoreError::Failed(
106 "session store does not support transactional stream publication".to_string(),
107 ))
108 }
109
110 async fn save_session(&self, session: SessionRecord) -> SessionStoreResult<()>;
112
113 async fn load_session(&self, session_id: &SessionId) -> SessionStoreResult<SessionRecord>;
115
116 async fn list_sessions(&self, filter: SessionFilter) -> SessionStoreResult<Vec<SessionRecord>>;
118
119 async fn update_session_status(
121 &self,
122 session_id: &SessionId,
123 status: SessionStatus,
124 ) -> SessionStoreResult<()>;
125
126 async fn save_context_state(
128 &self,
129 session_id: &SessionId,
130 state: ResumableState,
131 ) -> SessionStoreResult<()>;
132
133 async fn save_environment_state(
135 &self,
136 session_id: &SessionId,
137 environment_state: EnvironmentStateRef,
138 ) -> SessionStoreResult<()>;
139
140 async fn append_run(&self, run: RunRecord) -> SessionStoreResult<()>;
145
146 async fn load_run(
148 &self,
149 session_id: &SessionId,
150 run_id: &RunId,
151 ) -> SessionStoreResult<RunRecord>;
152
153 async fn list_runs(&self, session_id: &SessionId) -> SessionStoreResult<Vec<RunRecord>>;
155
156 async fn update_run_status(
158 &self,
159 session_id: &SessionId,
160 run_id: &RunId,
161 status: RunStatus,
162 output_preview: Option<String>,
163 ) -> SessionStoreResult<()>;
164
165 async fn append_checkpoint(
167 &self,
168 session_id: &SessionId,
169 checkpoint: AgentCheckpoint,
170 ) -> SessionStoreResult<()>;
171
172 async fn load_checkpoints(
174 &self,
175 session_id: &SessionId,
176 run_id: &RunId,
177 ) -> SessionStoreResult<Vec<AgentCheckpoint>>;
178
179 async fn latest_checkpoint(
181 &self,
182 session_id: &SessionId,
183 run_id: &RunId,
184 ) -> SessionStoreResult<Option<AgentCheckpoint>> {
185 let checkpoints = self.load_checkpoints(session_id, run_id).await?;
186 Ok(checkpoints.into_iter().last())
187 }
188
189 async fn append_stream_records(
191 &self,
192 session_id: &SessionId,
193 run_id: &RunId,
194 records: Vec<AgentStreamRecord>,
195 ) -> SessionStoreResult<()>;
196
197 async fn replay_stream_records(
199 &self,
200 session_id: &SessionId,
201 run_id: &RunId,
202 ) -> SessionStoreResult<Vec<AgentStreamRecord>>;
203
204 async fn replay_stream_records_after(
206 &self,
207 session_id: &SessionId,
208 run_id: &RunId,
209 after_sequence: Option<usize>,
210 ) -> SessionStoreResult<Vec<AgentStreamRecord>> {
211 let records = self.replay_stream_records(session_id, run_id).await?;
212 Ok(records
213 .into_iter()
214 .filter(|record| after_sequence.is_none_or(|cursor| record.sequence > cursor))
215 .collect())
216 }
217
218 async fn save_stream_cursor(
220 &self,
221 session_id: &SessionId,
222 run_id: &RunId,
223 cursor: StreamCursorRef,
224 ) -> SessionStoreResult<()>;
225
226 async fn append_approval(&self, approval: ApprovalRecord) -> SessionStoreResult<()>;
228
229 async fn load_approvals(
231 &self,
232 session_id: &SessionId,
233 run_id: &RunId,
234 ) -> SessionStoreResult<Vec<ApprovalRecord>>;
235
236 async fn append_deferred_tool(&self, record: DeferredToolRecord) -> SessionStoreResult<()>;
238
239 async fn load_deferred_tools(
241 &self,
242 session_id: &SessionId,
243 run_id: &RunId,
244 ) -> SessionStoreResult<Vec<DeferredToolRecord>>;
245
246 async fn resume_snapshot(
248 &self,
249 _session_id: &SessionId,
250 _run_id: &RunId,
251 ) -> SessionStoreResult<SessionResumeSnapshot> {
252 Err(SessionStoreError::Failed(
253 "session store does not support per-run resume snapshots".to_string(),
254 ))
255 }
256
257 async fn compact_run_trace(
259 &self,
260 session_id: &SessionId,
261 run_id: &RunId,
262 ) -> SessionStoreResult<CompactRunTrace>;
263
264 async fn compact_session_trace(
266 &self,
267 session_id: &SessionId,
268 ) -> SessionStoreResult<CompactSessionTrace>;
269}