starweaver_session/store/
contract.rs1use async_trait::async_trait;
4use starweaver_context::ResumableState;
5use starweaver_core::{RunId, SessionId};
6use starweaver_runtime::{AgentCheckpoint, AgentStreamRecord};
7
8use crate::{
9 approval::{ApprovalRecord, DeferredToolRecord},
10 error::SessionStoreResult,
11 records::{
12 EnvironmentStateRef, RunRecord, RunStatus, SessionRecord, SessionStatus, StreamCursorRef,
13 },
14 resume::SessionResumeSnapshot,
15 trace::{CompactRunTrace, CompactSessionTrace},
16};
17
18#[derive(Clone, Debug, Default, Eq, PartialEq)]
20pub struct SessionFilter {
21 pub status: Option<SessionStatus>,
23 pub profile: Option<String>,
25 pub workspace: Option<String>,
27 pub limit: Option<usize>,
29}
30
31#[async_trait]
33pub trait SessionStore: Send + Sync {
34 async fn save_session(&self, session: SessionRecord) -> SessionStoreResult<()>;
36
37 async fn load_session(&self, session_id: &SessionId) -> SessionStoreResult<SessionRecord>;
39
40 async fn list_sessions(&self, filter: SessionFilter) -> SessionStoreResult<Vec<SessionRecord>>;
42
43 async fn update_session_status(
45 &self,
46 session_id: &SessionId,
47 status: SessionStatus,
48 ) -> SessionStoreResult<()>;
49
50 async fn save_context_state(
52 &self,
53 session_id: &SessionId,
54 state: ResumableState,
55 ) -> SessionStoreResult<()>;
56
57 async fn save_environment_state(
59 &self,
60 session_id: &SessionId,
61 environment_state: EnvironmentStateRef,
62 ) -> SessionStoreResult<()>;
63
64 async fn append_run(&self, run: RunRecord) -> SessionStoreResult<()>;
66
67 async fn load_run(
69 &self,
70 session_id: &SessionId,
71 run_id: &RunId,
72 ) -> SessionStoreResult<RunRecord>;
73
74 async fn list_runs(&self, session_id: &SessionId) -> SessionStoreResult<Vec<RunRecord>>;
76
77 async fn update_run_status(
79 &self,
80 session_id: &SessionId,
81 run_id: &RunId,
82 status: RunStatus,
83 output_preview: Option<String>,
84 ) -> SessionStoreResult<()>;
85
86 async fn append_checkpoint(
88 &self,
89 session_id: &SessionId,
90 checkpoint: AgentCheckpoint,
91 ) -> SessionStoreResult<()>;
92
93 async fn load_checkpoints(
95 &self,
96 session_id: &SessionId,
97 run_id: &RunId,
98 ) -> SessionStoreResult<Vec<AgentCheckpoint>>;
99
100 async fn latest_checkpoint(
102 &self,
103 session_id: &SessionId,
104 run_id: &RunId,
105 ) -> SessionStoreResult<Option<AgentCheckpoint>> {
106 let checkpoints = self.load_checkpoints(session_id, run_id).await?;
107 Ok(checkpoints.into_iter().last())
108 }
109
110 async fn append_stream_records(
112 &self,
113 session_id: &SessionId,
114 run_id: &RunId,
115 records: Vec<AgentStreamRecord>,
116 ) -> SessionStoreResult<()>;
117
118 async fn replay_stream_records(
120 &self,
121 session_id: &SessionId,
122 run_id: &RunId,
123 ) -> SessionStoreResult<Vec<AgentStreamRecord>>;
124
125 async fn replay_stream_records_after(
127 &self,
128 session_id: &SessionId,
129 run_id: &RunId,
130 after_sequence: Option<usize>,
131 ) -> SessionStoreResult<Vec<AgentStreamRecord>> {
132 let records = self.replay_stream_records(session_id, run_id).await?;
133 Ok(records
134 .into_iter()
135 .filter(|record| after_sequence.map_or(true, |cursor| record.sequence > cursor))
136 .collect())
137 }
138
139 async fn save_stream_cursor(
141 &self,
142 session_id: &SessionId,
143 run_id: &RunId,
144 cursor: StreamCursorRef,
145 ) -> SessionStoreResult<()>;
146
147 async fn append_approval(&self, approval: ApprovalRecord) -> SessionStoreResult<()>;
149
150 async fn load_approvals(
152 &self,
153 session_id: &SessionId,
154 run_id: &RunId,
155 ) -> SessionStoreResult<Vec<ApprovalRecord>>;
156
157 async fn append_deferred_tool(&self, record: DeferredToolRecord) -> SessionStoreResult<()>;
159
160 async fn load_deferred_tools(
162 &self,
163 session_id: &SessionId,
164 run_id: &RunId,
165 ) -> SessionStoreResult<Vec<DeferredToolRecord>>;
166
167 async fn resume_snapshot(
169 &self,
170 session_id: &SessionId,
171 run_id: &RunId,
172 ) -> SessionStoreResult<SessionResumeSnapshot> {
173 let session = self.load_session(session_id).await?;
174 let run = self.load_run(session_id, run_id).await?;
175 let latest_checkpoint = self.latest_checkpoint(session_id, run_id).await?;
176 let after_sequence = latest_checkpoint
177 .as_ref()
178 .and_then(|checkpoint| checkpoint.resume.cursor.stream_cursor);
179 let stream_records = self
180 .replay_stream_records_after(session_id, run_id, after_sequence)
181 .await?;
182 let approvals = self.load_approvals(session_id, run_id).await?;
183 let deferred_tools = self.load_deferred_tools(session_id, run_id).await?;
184 let environment_state = run
185 .environment_state
186 .clone()
187 .or_else(|| session.environment_state.clone());
188 let mut stream_cursors = session.stream_cursors.clone();
189 stream_cursors.extend(run.stream_cursors.clone());
190 Ok(SessionResumeSnapshot {
191 state: session.state.clone(),
192 session,
193 run,
194 environment_state,
195 latest_checkpoint,
196 stream_records,
197 approvals,
198 deferred_tools,
199 stream_cursors,
200 })
201 }
202
203 async fn compact_run_trace(
205 &self,
206 session_id: &SessionId,
207 run_id: &RunId,
208 ) -> SessionStoreResult<CompactRunTrace>;
209
210 async fn compact_session_trace(
212 &self,
213 session_id: &SessionId,
214 ) -> SessionStoreResult<CompactSessionTrace>;
215}