starweaver_cli/local_store/
session_store.rs1use async_trait::async_trait;
4use starweaver_context::ResumableState;
5use starweaver_core::{RunId, SessionId};
6use starweaver_runtime::{AgentCheckpoint, AgentStreamRecord};
7use starweaver_session::{
8 ApprovalRecord, CompactRunTrace, CompactSessionTrace, DeferredToolRecord, EnvironmentStateRef,
9 HitlResumeClaim, PendingStreamPublication, RunEvidenceCommit, RunRecord, RunStatus,
10 SessionFilter, SessionRecord, SessionStatus, SessionStore, SessionStoreResult, StreamCursorRef,
11 StreamPublicationTarget,
12};
13use starweaver_storage::SqliteSessionStore;
14
15use crate::config::CliConfig;
16
17#[derive(Clone, Debug)]
19pub struct LocalSessionStore {
20 store: SqliteSessionStore,
21}
22
23impl LocalSessionStore {
24 pub fn new(config: CliConfig) -> SessionStoreResult<Self> {
26 crate::config::ensure_config_dirs(&config)
27 .map_err(|error| starweaver_session::SessionStoreError::Failed(error.to_string()))?;
28 let database_path = config.database_path;
29 Ok(Self {
30 store: SqliteSessionStore::open(&database_path)?,
31 })
32 }
33}
34
35#[async_trait]
36impl SessionStore for LocalSessionStore {
37 async fn commit_run_evidence(
38 &self,
39 commit: RunEvidenceCommit,
40 ) -> SessionStoreResult<RunRecord> {
41 self.store.commit_run_evidence(commit).await
42 }
43
44 async fn commit_checkpoint(
45 &self,
46 session_id: &SessionId,
47 checkpoint: AgentCheckpoint,
48 ) -> SessionStoreResult<()> {
49 self.store.commit_checkpoint(session_id, checkpoint).await
50 }
51
52 async fn claim_hitl_resume(&self, claim: HitlResumeClaim) -> SessionStoreResult<()> {
53 self.store.claim_hitl_resume(claim).await
54 }
55
56 async fn mark_hitl_resume_started(
57 &self,
58 session_id: &SessionId,
59 run_id: &RunId,
60 claim_id: &str,
61 ) -> SessionStoreResult<()> {
62 self.store
63 .mark_hitl_resume_started(session_id, run_id, claim_id)
64 .await
65 }
66
67 async fn release_hitl_resume_claim(
68 &self,
69 session_id: &SessionId,
70 run_id: &RunId,
71 claim_id: &str,
72 ) -> SessionStoreResult<()> {
73 self.store
74 .release_hitl_resume_claim(session_id, run_id, claim_id)
75 .await
76 }
77
78 async fn pending_stream_publications(
79 &self,
80 session_id: &SessionId,
81 ) -> SessionStoreResult<Vec<PendingStreamPublication>> {
82 self.store.pending_stream_publications(session_id).await
83 }
84
85 async fn acknowledge_stream_publication(
86 &self,
87 publication_id: &str,
88 target: StreamPublicationTarget,
89 ) -> SessionStoreResult<()> {
90 self.store
91 .acknowledge_stream_publication(publication_id, target)
92 .await
93 }
94
95 async fn save_session(&self, session: SessionRecord) -> SessionStoreResult<()> {
96 self.store.save_session(session).await
97 }
98
99 async fn load_session(&self, session_id: &SessionId) -> SessionStoreResult<SessionRecord> {
100 self.store.load_session(session_id).await
101 }
102
103 async fn list_sessions(&self, filter: SessionFilter) -> SessionStoreResult<Vec<SessionRecord>> {
104 self.store.list_sessions(filter).await
105 }
106
107 async fn update_session_status(
108 &self,
109 session_id: &SessionId,
110 status: SessionStatus,
111 ) -> SessionStoreResult<()> {
112 self.store.update_session_status(session_id, status).await
113 }
114
115 async fn save_context_state(
116 &self,
117 session_id: &SessionId,
118 state: ResumableState,
119 ) -> SessionStoreResult<()> {
120 self.store.save_context_state(session_id, state).await
121 }
122
123 async fn save_environment_state(
124 &self,
125 session_id: &SessionId,
126 environment_state: EnvironmentStateRef,
127 ) -> SessionStoreResult<()> {
128 self.store
129 .save_environment_state(session_id, environment_state)
130 .await
131 }
132
133 async fn append_run(&self, run: RunRecord) -> SessionStoreResult<()> {
134 self.store.append_run(run).await
135 }
136
137 async fn load_run(
138 &self,
139 session_id: &SessionId,
140 run_id: &RunId,
141 ) -> SessionStoreResult<RunRecord> {
142 self.store.load_run(session_id, run_id).await
143 }
144
145 async fn list_runs(&self, session_id: &SessionId) -> SessionStoreResult<Vec<RunRecord>> {
146 self.store.list_runs(session_id).await
147 }
148
149 async fn update_run_status(
150 &self,
151 session_id: &SessionId,
152 run_id: &RunId,
153 status: RunStatus,
154 output_preview: Option<String>,
155 ) -> SessionStoreResult<()> {
156 self.store
157 .update_run_status(session_id, run_id, status, output_preview)
158 .await
159 }
160
161 async fn append_checkpoint(
162 &self,
163 session_id: &SessionId,
164 checkpoint: AgentCheckpoint,
165 ) -> SessionStoreResult<()> {
166 self.store.append_checkpoint(session_id, checkpoint).await
167 }
168
169 async fn load_checkpoints(
170 &self,
171 session_id: &SessionId,
172 run_id: &RunId,
173 ) -> SessionStoreResult<Vec<AgentCheckpoint>> {
174 self.store.load_checkpoints(session_id, run_id).await
175 }
176
177 async fn append_stream_records(
178 &self,
179 session_id: &SessionId,
180 run_id: &RunId,
181 records: Vec<AgentStreamRecord>,
182 ) -> SessionStoreResult<()> {
183 self.store
184 .append_stream_records(session_id, run_id, records)
185 .await
186 }
187
188 async fn replay_stream_records(
189 &self,
190 session_id: &SessionId,
191 run_id: &RunId,
192 ) -> SessionStoreResult<Vec<AgentStreamRecord>> {
193 self.store.replay_stream_records(session_id, run_id).await
194 }
195
196 async fn replay_stream_records_after(
197 &self,
198 session_id: &SessionId,
199 run_id: &RunId,
200 after_sequence: Option<usize>,
201 ) -> SessionStoreResult<Vec<AgentStreamRecord>> {
202 self.store
203 .replay_stream_records_after(session_id, run_id, after_sequence)
204 .await
205 }
206
207 async fn save_stream_cursor(
208 &self,
209 session_id: &SessionId,
210 run_id: &RunId,
211 cursor: StreamCursorRef,
212 ) -> SessionStoreResult<()> {
213 self.store
214 .save_stream_cursor(session_id, run_id, cursor)
215 .await
216 }
217
218 async fn append_approval(&self, approval: ApprovalRecord) -> SessionStoreResult<()> {
219 self.store.append_approval(approval).await
220 }
221
222 async fn load_approvals(
223 &self,
224 session_id: &SessionId,
225 run_id: &RunId,
226 ) -> SessionStoreResult<Vec<ApprovalRecord>> {
227 self.store.load_approvals(session_id, run_id).await
228 }
229
230 async fn append_deferred_tool(&self, record: DeferredToolRecord) -> SessionStoreResult<()> {
231 self.store.append_deferred_tool(record).await
232 }
233
234 async fn load_deferred_tools(
235 &self,
236 session_id: &SessionId,
237 run_id: &RunId,
238 ) -> SessionStoreResult<Vec<DeferredToolRecord>> {
239 self.store.load_deferred_tools(session_id, run_id).await
240 }
241
242 async fn compact_run_trace(
243 &self,
244 session_id: &SessionId,
245 run_id: &RunId,
246 ) -> SessionStoreResult<CompactRunTrace> {
247 self.store.compact_run_trace(session_id, run_id).await
248 }
249
250 async fn compact_session_trace(
251 &self,
252 session_id: &SessionId,
253 ) -> SessionStoreResult<CompactSessionTrace> {
254 self.store.compact_session_trace(session_id).await
255 }
256}