1use async_trait::async_trait;
4use chrono::{DateTime, Utc};
5use starweaver_context::ResumableState;
6use starweaver_core::{RunId, SessionId, SubagentAttemptId};
7use starweaver_runtime::{AgentCheckpoint, AgentStreamRecord};
8use starweaver_session::{
9 AcquireBackgroundSubagentContinuation, AcquireRunAdmission, AdmitRunControl, ApprovalRecord,
10 BackgroundSubagentArtifact, BackgroundSubagentContinuationReceipt, BackgroundSubagentRecord,
11 BackgroundSubagentTerminalCommit, CompactRunTrace, CompactSessionTrace, DeferredToolRecord,
12 DurableBackgroundSubagentDeliveryClaim, DurableBackgroundSubagentDeliveryRelease,
13 DurableControlReceipt, DurableHostEventClass, DurableHostEventPage, DurableHostEventQuery,
14 DurableHostEventRecord, DurableHostEventScope, DurableRunControlIntent,
15 DurableRunControlStatus, EnvironmentStateRef, HitlResumeAbortOutcome, HitlResumeClaim,
16 ManagedRunTarget, PendingHostEventPublication, PendingStreamPublication, RunAdmissionLease,
17 RunAdmissionReceipt, RunEvidenceCommit, RunRecord, RunStatus, RunTerminalProjection,
18 SessionContinuationFence, SessionFilter, SessionPage, SessionPageQuery, SessionRecord,
19 SessionResumeSnapshot, SessionStatus, SessionStore, SessionStoreResult, StreamCursorRef,
20 StreamPublicationTarget, UpdateManagedSession,
21};
22use starweaver_storage::SqliteSessionStore;
23use starweaver_stream::ReplayEvent;
24
25use crate::config::CliConfig;
26
27#[derive(Clone, Debug)]
29pub struct LocalSessionStore {
30 store: SqliteSessionStore,
31}
32
33impl LocalSessionStore {
34 pub fn new(config: CliConfig) -> SessionStoreResult<Self> {
36 crate::config::ensure_config_dirs(&config)
37 .map_err(|error| starweaver_session::SessionStoreError::Failed(error.to_string()))?;
38 let database_path = config.database_path;
39 Ok(Self {
40 store: SqliteSessionStore::open(&database_path)?,
41 })
42 }
43}
44
45#[async_trait]
46impl SessionStore for LocalSessionStore {
47 async fn commit_run_evidence(
48 &self,
49 commit: RunEvidenceCommit,
50 ) -> SessionStoreResult<RunRecord> {
51 self.store.commit_run_evidence(commit).await
52 }
53
54 async fn commit_checkpoint(
55 &self,
56 session_id: &SessionId,
57 checkpoint: AgentCheckpoint,
58 ) -> SessionStoreResult<()> {
59 self.store.commit_checkpoint(session_id, checkpoint).await
60 }
61
62 async fn claim_hitl_resume(&self, claim: HitlResumeClaim) -> SessionStoreResult<()> {
63 self.store.claim_hitl_resume(claim).await
64 }
65
66 async fn start_hitl_resume_effect(
67 &self,
68 lease: &RunAdmissionLease,
69 source_run_id: &RunId,
70 claim_id: &str,
71 ) -> SessionStoreResult<()> {
72 self.store
73 .start_hitl_resume_effect(lease, source_run_id, claim_id)
74 .await
75 }
76
77 async fn abort_admitted_hitl_resume(
78 &self,
79 lease: &RunAdmissionLease,
80 source_run_id: &RunId,
81 claim_id: &str,
82 output_preview: &str,
83 ) -> SessionStoreResult<HitlResumeAbortOutcome> {
84 self.store
85 .abort_admitted_hitl_resume(lease, source_run_id, claim_id, output_preview)
86 .await
87 }
88
89 async fn mark_hitl_resume_started(
90 &self,
91 session_id: &SessionId,
92 run_id: &RunId,
93 claim_id: &str,
94 ) -> SessionStoreResult<()> {
95 self.store
96 .mark_hitl_resume_started(session_id, run_id, claim_id)
97 .await
98 }
99
100 async fn release_hitl_resume_claim(
101 &self,
102 session_id: &SessionId,
103 run_id: &RunId,
104 claim_id: &str,
105 ) -> SessionStoreResult<()> {
106 self.store
107 .release_hitl_resume_claim(session_id, run_id, claim_id)
108 .await
109 }
110
111 async fn pending_stream_publications(
112 &self,
113 session_id: &SessionId,
114 ) -> SessionStoreResult<Vec<PendingStreamPublication>> {
115 self.store.pending_stream_publications(session_id).await
116 }
117
118 async fn acknowledge_stream_publication(
119 &self,
120 publication_id: &str,
121 target: StreamPublicationTarget,
122 ) -> SessionStoreResult<()> {
123 self.store
124 .acknowledge_stream_publication(publication_id, target)
125 .await
126 }
127
128 async fn create_session_idempotent(
129 &self,
130 session: SessionRecord,
131 idempotency_key: &str,
132 command_fingerprint: &str,
133 ) -> SessionStoreResult<SessionRecord> {
134 self.store
135 .create_session_idempotent(session, idempotency_key, command_fingerprint)
136 .await
137 }
138
139 async fn update_managed_session(
140 &self,
141 command: UpdateManagedSession,
142 command_fingerprint: &str,
143 ) -> SessionStoreResult<SessionRecord> {
144 self.store
145 .update_managed_session(command, command_fingerprint)
146 .await
147 }
148
149 async fn acquire_session_deletion_fence(
150 &self,
151 session_id: &SessionId,
152 expected_revision: u64,
153 fence_id: &str,
154 requested_by: &str,
155 idempotency_key: &str,
156 command_fingerprint: &str,
157 ) -> SessionStoreResult<SessionRecord> {
158 self.store
159 .acquire_session_deletion_fence(
160 session_id,
161 expected_revision,
162 fence_id,
163 requested_by,
164 idempotency_key,
165 command_fingerprint,
166 )
167 .await
168 }
169
170 async fn tombstone_session(
171 &self,
172 session_id: &SessionId,
173 fence_id: &str,
174 ) -> SessionStoreResult<SessionRecord> {
175 self.store.tombstone_session(session_id, fence_id).await
176 }
177
178 async fn session_continuation_fence(
179 &self,
180 namespace_id: &str,
181 session_id: &SessionId,
182 ) -> SessionStoreResult<SessionContinuationFence> {
183 self.store
184 .session_continuation_fence(namespace_id, session_id)
185 .await
186 }
187
188 async fn acquire_run_admission(
189 &self,
190 request: AcquireRunAdmission,
191 ) -> SessionStoreResult<RunAdmissionReceipt> {
192 self.store.acquire_run_admission(request).await
193 }
194
195 async fn heartbeat_run_admission(
196 &self,
197 lease: &RunAdmissionLease,
198 lease_expires_at: chrono::DateTime<chrono::Utc>,
199 ) -> SessionStoreResult<RunAdmissionLease> {
200 self.store
201 .heartbeat_run_admission(lease, lease_expires_at)
202 .await
203 }
204
205 async fn release_run_admission(&self, lease: &RunAdmissionLease) -> SessionStoreResult<()> {
206 self.store.release_run_admission(lease).await
207 }
208
209 async fn load_run_admission(
210 &self,
211 target: &ManagedRunTarget,
212 ) -> SessionStoreResult<Option<RunAdmissionLease>> {
213 self.store.load_run_admission(target).await
214 }
215
216 async fn reconcile_expired_run_admissions(
217 &self,
218 namespace_id: &str,
219 now: chrono::DateTime<chrono::Utc>,
220 ) -> SessionStoreResult<Vec<ManagedRunTarget>> {
221 self.store
222 .reconcile_expired_run_admissions(namespace_id, now)
223 .await
224 }
225
226 async fn load_control_receipt(
227 &self,
228 target: &ManagedRunTarget,
229 idempotency_key: &str,
230 ) -> SessionStoreResult<Option<DurableControlReceipt>> {
231 self.store
232 .load_control_receipt(target, idempotency_key)
233 .await
234 }
235
236 async fn reserve_control_receipt(
237 &self,
238 receipt: DurableControlReceipt,
239 ) -> SessionStoreResult<DurableControlReceipt> {
240 self.store.reserve_control_receipt(receipt).await
241 }
242
243 async fn update_control_receipt_state(
244 &self,
245 receipt_id: &str,
246 state: &str,
247 ) -> SessionStoreResult<DurableControlReceipt> {
248 self.store
249 .update_control_receipt_state(receipt_id, state)
250 .await
251 }
252
253 async fn drain_background_subagent_operations(&self) -> SessionStoreResult<()> {
254 self.store.drain_background_subagent_operations().await
255 }
256
257 async fn save_session(&self, session: SessionRecord) -> SessionStoreResult<()> {
258 self.store.save_session(session).await
259 }
260
261 async fn load_session(&self, session_id: &SessionId) -> SessionStoreResult<SessionRecord> {
262 self.store.load_session(session_id).await
263 }
264
265 async fn list_sessions(&self, filter: SessionFilter) -> SessionStoreResult<Vec<SessionRecord>> {
266 self.store.list_sessions(filter).await
267 }
268
269 async fn list_session_page(&self, query: SessionPageQuery) -> SessionStoreResult<SessionPage> {
270 self.store.list_session_page(query).await
271 }
272
273 async fn update_session_status(
274 &self,
275 session_id: &SessionId,
276 status: SessionStatus,
277 ) -> SessionStoreResult<()> {
278 self.store.update_session_status(session_id, status).await
279 }
280
281 async fn save_context_state(
282 &self,
283 session_id: &SessionId,
284 state: ResumableState,
285 ) -> SessionStoreResult<()> {
286 self.store.save_context_state(session_id, state).await
287 }
288
289 async fn save_environment_state(
290 &self,
291 session_id: &SessionId,
292 environment_state: EnvironmentStateRef,
293 ) -> SessionStoreResult<()> {
294 self.store
295 .save_environment_state(session_id, environment_state)
296 .await
297 }
298
299 async fn append_run(&self, run: RunRecord) -> SessionStoreResult<()> {
300 self.store.append_run(run).await
301 }
302
303 async fn load_run(
304 &self,
305 session_id: &SessionId,
306 run_id: &RunId,
307 ) -> SessionStoreResult<RunRecord> {
308 self.store.load_run(session_id, run_id).await
309 }
310
311 async fn list_runs(&self, session_id: &SessionId) -> SessionStoreResult<Vec<RunRecord>> {
312 self.store.list_runs(session_id).await
313 }
314
315 async fn update_run_status(
316 &self,
317 session_id: &SessionId,
318 run_id: &RunId,
319 status: RunStatus,
320 output_preview: Option<String>,
321 ) -> SessionStoreResult<()> {
322 self.store
323 .update_run_status(session_id, run_id, status, output_preview)
324 .await
325 }
326
327 async fn append_checkpoint(
328 &self,
329 session_id: &SessionId,
330 checkpoint: AgentCheckpoint,
331 ) -> SessionStoreResult<()> {
332 self.store.append_checkpoint(session_id, checkpoint).await
333 }
334
335 async fn load_checkpoints(
336 &self,
337 session_id: &SessionId,
338 run_id: &RunId,
339 ) -> SessionStoreResult<Vec<AgentCheckpoint>> {
340 self.store.load_checkpoints(session_id, run_id).await
341 }
342
343 async fn append_stream_records(
344 &self,
345 session_id: &SessionId,
346 run_id: &RunId,
347 records: Vec<AgentStreamRecord>,
348 ) -> SessionStoreResult<()> {
349 self.store
350 .append_stream_records(session_id, run_id, records)
351 .await
352 }
353
354 async fn replay_stream_records(
355 &self,
356 session_id: &SessionId,
357 run_id: &RunId,
358 ) -> SessionStoreResult<Vec<AgentStreamRecord>> {
359 self.store.replay_stream_records(session_id, run_id).await
360 }
361
362 async fn replay_stream_records_after(
363 &self,
364 session_id: &SessionId,
365 run_id: &RunId,
366 after_sequence: Option<usize>,
367 ) -> SessionStoreResult<Vec<AgentStreamRecord>> {
368 self.store
369 .replay_stream_records_after(session_id, run_id, after_sequence)
370 .await
371 }
372
373 async fn save_stream_cursor(
374 &self,
375 session_id: &SessionId,
376 run_id: &RunId,
377 cursor: StreamCursorRef,
378 ) -> SessionStoreResult<()> {
379 self.store
380 .save_stream_cursor(session_id, run_id, cursor)
381 .await
382 }
383
384 async fn append_approval(&self, approval: ApprovalRecord) -> SessionStoreResult<()> {
385 self.store.append_approval(approval).await
386 }
387
388 async fn load_approvals(
389 &self,
390 session_id: &SessionId,
391 run_id: &RunId,
392 ) -> SessionStoreResult<Vec<ApprovalRecord>> {
393 self.store.load_approvals(session_id, run_id).await
394 }
395
396 async fn append_deferred_tool(&self, record: DeferredToolRecord) -> SessionStoreResult<()> {
397 self.store.append_deferred_tool(record).await
398 }
399
400 async fn load_deferred_tools(
401 &self,
402 session_id: &SessionId,
403 run_id: &RunId,
404 ) -> SessionStoreResult<Vec<DeferredToolRecord>> {
405 self.store.load_deferred_tools(session_id, run_id).await
406 }
407
408 async fn compact_run_trace(
409 &self,
410 session_id: &SessionId,
411 run_id: &RunId,
412 ) -> SessionStoreResult<CompactRunTrace> {
413 self.store.compact_run_trace(session_id, run_id).await
414 }
415
416 async fn compact_session_trace(
417 &self,
418 session_id: &SessionId,
419 ) -> SessionStoreResult<CompactSessionTrace> {
420 self.store.compact_session_trace(session_id).await
421 }
422
423 async fn commit_run_evidence_fenced(
424 &self,
425 lease: &RunAdmissionLease,
426 commit: RunEvidenceCommit,
427 ) -> SessionStoreResult<RunRecord> {
428 self.store.commit_run_evidence_fenced(lease, commit).await
429 }
430
431 async fn append_replay_events_fenced(
432 &self,
433 lease: &RunAdmissionLease,
434 events: Vec<ReplayEvent>,
435 ) -> SessionStoreResult<()> {
436 self.store.append_replay_events_fenced(lease, events).await
437 }
438
439 async fn commit_checkpoint_fenced(
440 &self,
441 lease: &RunAdmissionLease,
442 checkpoint: AgentCheckpoint,
443 ) -> SessionStoreResult<()> {
444 self.store.commit_checkpoint_fenced(lease, checkpoint).await
445 }
446
447 async fn enqueue_host_event_publications(
448 &self,
449 publications: Vec<PendingHostEventPublication>,
450 ) -> SessionStoreResult<()> {
451 self.store
452 .enqueue_host_event_publications(publications)
453 .await
454 }
455
456 async fn pending_host_event_publications(
457 &self,
458 limit: usize,
459 ) -> SessionStoreResult<Vec<PendingHostEventPublication>> {
460 self.store.pending_host_event_publications(limit).await
461 }
462
463 async fn materialize_host_event_publications(
464 &self,
465 limit: usize,
466 ) -> SessionStoreResult<Vec<DurableHostEventRecord>> {
467 self.store.materialize_host_event_publications(limit).await
468 }
469
470 async fn replay_host_events(
471 &self,
472 query: DurableHostEventQuery,
473 ) -> SessionStoreResult<DurableHostEventPage> {
474 self.store.replay_host_events(query).await
475 }
476
477 async fn host_event_fence(
478 &self,
479 scope: &DurableHostEventScope,
480 event_classes: &[DurableHostEventClass],
481 ) -> SessionStoreResult<Option<u64>> {
482 self.store.host_event_fence(scope, event_classes).await
483 }
484
485 async fn create_session_idempotent_with_host_events(
486 &self,
487 session: SessionRecord,
488 idempotency_key: &str,
489 command_fingerprint: &str,
490 publications: Vec<PendingHostEventPublication>,
491 ) -> SessionStoreResult<SessionRecord> {
492 self.store
493 .create_session_idempotent_with_host_events(
494 session,
495 idempotency_key,
496 command_fingerprint,
497 publications,
498 )
499 .await
500 }
501
502 async fn load_session_mutation_receipt(
503 &self,
504 namespace_id: &str,
505 idempotency_key: &str,
506 command_fingerprint: &str,
507 ) -> SessionStoreResult<Option<SessionRecord>> {
508 self.store
509 .load_session_mutation_receipt(namespace_id, idempotency_key, command_fingerprint)
510 .await
511 }
512
513 async fn update_managed_session_with_host_events(
514 &self,
515 command: UpdateManagedSession,
516 command_fingerprint: &str,
517 publications: Vec<PendingHostEventPublication>,
518 ) -> SessionStoreResult<SessionRecord> {
519 self.store
520 .update_managed_session_with_host_events(command, command_fingerprint, publications)
521 .await
522 }
523
524 async fn tombstone_session_idempotent_with_host_events(
525 &self,
526 session_id: &SessionId,
527 fence_id: &str,
528 idempotency_key: &str,
529 command_fingerprint: &str,
530 publications: Vec<PendingHostEventPublication>,
531 ) -> SessionStoreResult<SessionRecord> {
532 self.store
533 .tombstone_session_idempotent_with_host_events(
534 session_id,
535 fence_id,
536 idempotency_key,
537 command_fingerprint,
538 publications,
539 )
540 .await
541 }
542
543 async fn load_run_admission_receipt(
544 &self,
545 namespace_id: &str,
546 idempotency_key: &str,
547 command_fingerprint: &str,
548 ) -> SessionStoreResult<Option<RunAdmissionReceipt>> {
549 self.store
550 .load_run_admission_receipt(namespace_id, idempotency_key, command_fingerprint)
551 .await
552 }
553
554 async fn update_run_status_fenced(
555 &self,
556 lease: &RunAdmissionLease,
557 status: RunStatus,
558 output_preview: Option<String>,
559 ) -> SessionStoreResult<RunRecord> {
560 self.store
561 .update_run_status_fenced(lease, status, output_preview)
562 .await
563 }
564
565 async fn finalize_run_admission(
566 &self,
567 lease: &RunAdmissionLease,
568 terminal: RunTerminalProjection,
569 ) -> SessionStoreResult<RunRecord> {
570 self.store.finalize_run_admission(lease, terminal).await
571 }
572
573 async fn admit_run_control(
574 &self,
575 request: AdmitRunControl,
576 ) -> SessionStoreResult<DurableRunControlIntent> {
577 self.store.admit_run_control(request).await
578 }
579
580 async fn load_run_control_intent(
581 &self,
582 target: &ManagedRunTarget,
583 operation_id: &str,
584 ) -> SessionStoreResult<Option<DurableRunControlIntent>> {
585 self.store
586 .load_run_control_intent(target, operation_id)
587 .await
588 }
589
590 async fn list_run_control_intents(
591 &self,
592 target: &ManagedRunTarget,
593 statuses: &[DurableRunControlStatus],
594 limit: usize,
595 ) -> SessionStoreResult<Vec<DurableRunControlIntent>> {
596 self.store
597 .list_run_control_intents(target, statuses, limit)
598 .await
599 }
600
601 async fn advance_run_control_intent(
602 &self,
603 lease: &RunAdmissionLease,
604 operation_id: &str,
605 expected: DurableRunControlStatus,
606 next: DurableRunControlStatus,
607 occurred_at: DateTime<Utc>,
608 ) -> SessionStoreResult<DurableRunControlIntent> {
609 self.store
610 .advance_run_control_intent(lease, operation_id, expected, next, occurred_at)
611 .await
612 }
613
614 async fn reconcile_run_control_intent(
615 &self,
616 target: &ManagedRunTarget,
617 operation_id: &str,
618 occurred_at: DateTime<Utc>,
619 ) -> SessionStoreResult<DurableRunControlIntent> {
620 self.store
621 .reconcile_run_control_intent(target, operation_id, occurred_at)
622 .await
623 }
624
625 async fn record_background_subagent_acceptance(
626 &self,
627 record: BackgroundSubagentRecord,
628 ) -> SessionStoreResult<BackgroundSubagentRecord> {
629 self.store
630 .record_background_subagent_acceptance(record)
631 .await
632 }
633
634 async fn update_background_subagent_execution(
635 &self,
636 record: BackgroundSubagentRecord,
637 ) -> SessionStoreResult<BackgroundSubagentRecord> {
638 self.store
639 .update_background_subagent_execution(record)
640 .await
641 }
642
643 async fn heartbeat_background_subagent(
644 &self,
645 attempt_id: &SubagentAttemptId,
646 host_instance_id: &str,
647 fencing_generation: u64,
648 lease_expires_at: chrono::DateTime<chrono::Utc>,
649 ) -> SessionStoreResult<BackgroundSubagentRecord> {
650 self.store
651 .heartbeat_background_subagent(
652 attempt_id,
653 host_instance_id,
654 fencing_generation,
655 lease_expires_at,
656 )
657 .await
658 }
659
660 async fn commit_background_subagent_terminal(
661 &self,
662 commit: BackgroundSubagentTerminalCommit,
663 ) -> SessionStoreResult<BackgroundSubagentRecord> {
664 self.store.commit_background_subagent_terminal(commit).await
665 }
666
667 async fn load_background_subagent_artifact(
668 &self,
669 artifact_ref: &str,
670 ) -> SessionStoreResult<BackgroundSubagentArtifact> {
671 self.store
672 .load_background_subagent_artifact(artifact_ref)
673 .await
674 }
675
676 async fn expire_background_subagent_retention(
677 &self,
678 namespace_id: &str,
679 now: chrono::DateTime<chrono::Utc>,
680 limit: usize,
681 ) -> SessionStoreResult<Vec<BackgroundSubagentRecord>> {
682 self.store
683 .expire_background_subagent_retention(namespace_id, now, limit)
684 .await
685 }
686
687 async fn record_background_subagent_terminal(
688 &self,
689 record: BackgroundSubagentRecord,
690 ) -> SessionStoreResult<BackgroundSubagentRecord> {
691 self.store.record_background_subagent_terminal(record).await
692 }
693
694 async fn load_background_subagent(
695 &self,
696 attempt_id: &SubagentAttemptId,
697 ) -> SessionStoreResult<BackgroundSubagentRecord> {
698 self.store.load_background_subagent(attempt_id).await
699 }
700
701 async fn list_background_subagents(
702 &self,
703 namespace_id: &str,
704 session_id: Option<&SessionId>,
705 limit: usize,
706 ) -> SessionStoreResult<Vec<BackgroundSubagentRecord>> {
707 self.store
708 .list_background_subagents(namespace_id, session_id, limit)
709 .await
710 }
711
712 async fn list_pending_background_subagents(
713 &self,
714 namespace_id: &str,
715 session_id: Option<&SessionId>,
716 limit: usize,
717 ) -> SessionStoreResult<Vec<BackgroundSubagentRecord>> {
718 self.store
719 .list_pending_background_subagents(namespace_id, session_id, limit)
720 .await
721 }
722
723 async fn claim_background_subagent_delivery(
724 &self,
725 attempt_id: &SubagentAttemptId,
726 claim: DurableBackgroundSubagentDeliveryClaim,
727 ) -> SessionStoreResult<BackgroundSubagentRecord> {
728 self.store
729 .claim_background_subagent_delivery(attempt_id, claim)
730 .await
731 }
732
733 async fn acknowledge_background_subagent_delivery(
734 &self,
735 attempt_id: &SubagentAttemptId,
736 claim_id: &str,
737 ) -> SessionStoreResult<BackgroundSubagentRecord> {
738 self.store
739 .acknowledge_background_subagent_delivery(attempt_id, claim_id)
740 .await
741 }
742
743 async fn release_background_subagent_delivery(
744 &self,
745 attempt_id: &SubagentAttemptId,
746 claim_id: &str,
747 release: DurableBackgroundSubagentDeliveryRelease,
748 ) -> SessionStoreResult<BackgroundSubagentRecord> {
749 self.store
750 .release_background_subagent_delivery(attempt_id, claim_id, release)
751 .await
752 }
753
754 async fn acquire_background_subagent_continuation(
755 &self,
756 request: AcquireBackgroundSubagentContinuation,
757 ) -> SessionStoreResult<BackgroundSubagentContinuationReceipt> {
758 self.store
759 .acquire_background_subagent_continuation(request)
760 .await
761 }
762
763 async fn reconcile_background_subagents(
764 &self,
765 namespace_id: &str,
766 now: chrono::DateTime<chrono::Utc>,
767 ) -> SessionStoreResult<Vec<BackgroundSubagentRecord>> {
768 self.store
769 .reconcile_background_subagents(namespace_id, now)
770 .await
771 }
772
773 async fn latest_checkpoint(
774 &self,
775 session_id: &SessionId,
776 run_id: &RunId,
777 ) -> SessionStoreResult<Option<AgentCheckpoint>> {
778 self.store.latest_checkpoint(session_id, run_id).await
779 }
780
781 async fn resume_snapshot(
782 &self,
783 session_id: &SessionId,
784 run_id: &RunId,
785 ) -> SessionStoreResult<SessionResumeSnapshot> {
786 self.store.resume_snapshot(session_id, run_id).await
787 }
788}