1use async_trait::async_trait;
4use starweaver_context::{AgentCheckpoint, ResumableState};
5use starweaver_core::{RunId, SessionId};
6use starweaver_stream::{AgentStreamRecord, ReplayEvent};
7
8use crate::{
9 AcquireBackgroundSubagentContinuation, AcquireRunAdmission, AdmitRunControl,
10 BackgroundSubagentContinuationReceipt, BackgroundSubagentRecord,
11 DurableBackgroundSubagentDeliveryClaim, DurableBackgroundSubagentDeliveryRelease,
12 DurableControlReceipt, DurableRunControlIntent, DurableRunControlStatus, RunAdmissionLease,
13 RunAdmissionReceipt, SessionContinuationFence, UpdateManagedSession,
14 approval::{ApprovalRecord, DeferredToolRecord},
15 claim::HitlResumeClaim,
16 error::{SessionStoreError, SessionStoreResult},
17 evidence::RunEvidenceCommit,
18 host_events::{
19 DurableHostEventClass, DurableHostEventPage, DurableHostEventQuery, DurableHostEventRecord,
20 DurableHostEventScope, PendingHostEventPublication,
21 },
22 publication::{PendingStreamPublication, StreamPublicationTarget},
23 records::{
24 EnvironmentStateRef, RunRecord, RunStatus, RunTerminalProjection, SessionRecord,
25 SessionStatus, StreamCursorRef,
26 },
27 resume::SessionResumeSnapshot,
28 trace::{CompactRunTrace, CompactSessionTrace},
29};
30
31fn management_unsupported<T>() -> SessionStoreResult<T> {
32 Err(SessionStoreError::Failed(
33 "session store does not support agent session management".to_string(),
34 ))
35}
36
37#[derive(Clone, Debug, Default, Eq, PartialEq)]
39pub struct SessionFilter {
40 pub status: Option<SessionStatus>,
42 pub profile: Option<String>,
44 pub workspace: Option<String>,
46 pub limit: Option<usize>,
48}
49
50pub const MAX_STABLE_PAGE_SIZE: usize = 200;
52
53#[derive(Clone, Debug, Eq, PartialEq)]
55pub struct SessionPageKey {
56 pub updated_at: chrono::DateTime<chrono::Utc>,
58 pub session_id: SessionId,
60}
61
62impl SessionPageKey {
63 #[must_use]
65 pub fn from_session(session: &SessionRecord) -> Self {
66 Self {
67 updated_at: session.updated_at,
68 session_id: session.session_id.clone(),
69 }
70 }
71}
72
73#[derive(Clone, Debug, Eq, PartialEq)]
75pub struct SessionPageQuery {
76 after: Option<SessionPageKey>,
77 limit: usize,
78}
79
80impl SessionPageQuery {
81 pub fn new(after: Option<SessionPageKey>, limit: usize) -> SessionStoreResult<Self> {
87 validate_page_limit(limit)?;
88 Ok(Self { after, limit })
89 }
90
91 #[must_use]
93 pub const fn after(&self) -> Option<&SessionPageKey> {
94 self.after.as_ref()
95 }
96
97 #[must_use]
99 pub const fn limit(&self) -> usize {
100 self.limit
101 }
102}
103
104#[derive(Clone, Debug, Eq, PartialEq)]
106pub struct SessionPage {
107 pub sessions: Vec<SessionRecord>,
109 pub next_key: Option<SessionPageKey>,
111 pub has_more: bool,
113}
114
115#[derive(Clone, Debug, Eq, PartialEq)]
117pub struct InteractionPageKey {
118 pub updated_at: chrono::DateTime<chrono::Utc>,
120 pub interaction_id: String,
122}
123
124#[derive(Clone, Debug, Eq, PartialEq)]
126pub struct InteractionPageQuery {
127 session_id: Option<SessionId>,
128 run_id: Option<RunId>,
129 after: Option<InteractionPageKey>,
130 limit: usize,
131}
132
133impl InteractionPageQuery {
134 pub fn new(
140 session_id: Option<SessionId>,
141 run_id: Option<RunId>,
142 after: Option<InteractionPageKey>,
143 limit: usize,
144 ) -> SessionStoreResult<Self> {
145 validate_page_limit(limit)?;
146 Ok(Self {
147 session_id,
148 run_id,
149 after,
150 limit,
151 })
152 }
153
154 #[must_use]
156 pub const fn session_id(&self) -> Option<&SessionId> {
157 self.session_id.as_ref()
158 }
159
160 #[must_use]
162 pub const fn run_id(&self) -> Option<&RunId> {
163 self.run_id.as_ref()
164 }
165
166 #[must_use]
168 pub const fn after(&self) -> Option<&InteractionPageKey> {
169 self.after.as_ref()
170 }
171
172 #[must_use]
174 pub const fn limit(&self) -> usize {
175 self.limit
176 }
177}
178
179#[derive(Clone, Debug, Eq, PartialEq)]
181pub struct InteractionPage<T> {
182 pub records: Vec<T>,
184 pub next_key: Option<InteractionPageKey>,
186 pub has_more: bool,
188}
189
190fn validate_page_limit(limit: usize) -> SessionStoreResult<()> {
191 if !(1..=MAX_STABLE_PAGE_SIZE).contains(&limit) {
192 return Err(SessionStoreError::Failed(format!(
193 "stable page limit must be between 1 and {MAX_STABLE_PAGE_SIZE}"
194 )));
195 }
196 Ok(())
197}
198
199#[async_trait]
201pub trait SessionStore: Send + Sync {
202 async fn commit_run_evidence(&self, commit: RunEvidenceCommit)
209 -> SessionStoreResult<RunRecord>;
210
211 async fn commit_run_evidence_fenced(
217 &self,
218 _lease: &RunAdmissionLease,
219 _commit: RunEvidenceCommit,
220 ) -> SessionStoreResult<RunRecord> {
221 management_unsupported()
222 }
223
224 async fn append_replay_events_fenced(
231 &self,
232 _lease: &RunAdmissionLease,
233 _events: Vec<ReplayEvent>,
234 ) -> SessionStoreResult<()> {
235 management_unsupported()
236 }
237
238 async fn commit_checkpoint(
244 &self,
245 session_id: &SessionId,
246 checkpoint: AgentCheckpoint,
247 ) -> SessionStoreResult<()>;
248
249 async fn commit_checkpoint_fenced(
253 &self,
254 _lease: &RunAdmissionLease,
255 _checkpoint: AgentCheckpoint,
256 ) -> SessionStoreResult<()> {
257 management_unsupported()
258 }
259
260 async fn claim_hitl_resume(&self, _claim: HitlResumeClaim) -> SessionStoreResult<()> {
265 Err(SessionStoreError::Failed(
266 "session store does not support exclusive HITL resume claims".to_string(),
267 ))
268 }
269
270 async fn start_hitl_resume_effect(
275 &self,
276 _lease: &RunAdmissionLease,
277 _source_run_id: &RunId,
278 _claim_id: &str,
279 ) -> SessionStoreResult<()> {
280 management_unsupported()
281 }
282
283 async fn abort_admitted_hitl_resume(
289 &self,
290 _lease: &RunAdmissionLease,
291 _source_run_id: &RunId,
292 _claim_id: &str,
293 _output_preview: &str,
294 ) -> SessionStoreResult<crate::HitlResumeAbortOutcome> {
295 management_unsupported()
296 }
297
298 async fn mark_hitl_resume_started(
300 &self,
301 _session_id: &SessionId,
302 _run_id: &RunId,
303 _claim_id: &str,
304 ) -> SessionStoreResult<()> {
305 Err(SessionStoreError::Failed(
306 "session store does not support exclusive HITL resume claims".to_string(),
307 ))
308 }
309
310 async fn release_hitl_resume_claim(
312 &self,
313 _session_id: &SessionId,
314 _run_id: &RunId,
315 _claim_id: &str,
316 ) -> SessionStoreResult<()> {
317 Err(SessionStoreError::Failed(
318 "session store does not support exclusive HITL resume claims".to_string(),
319 ))
320 }
321
322 async fn pending_stream_publications(
324 &self,
325 _session_id: &SessionId,
326 ) -> SessionStoreResult<Vec<PendingStreamPublication>> {
327 Err(SessionStoreError::Failed(
328 "session store does not support transactional stream publication".to_string(),
329 ))
330 }
331
332 async fn acknowledge_stream_publication(
334 &self,
335 _publication_id: &str,
336 _target: StreamPublicationTarget,
337 ) -> SessionStoreResult<()> {
338 Err(SessionStoreError::Failed(
339 "session store does not support transactional stream publication".to_string(),
340 ))
341 }
342
343 async fn enqueue_host_event_publications(
348 &self,
349 _publications: Vec<PendingHostEventPublication>,
350 ) -> SessionStoreResult<()> {
351 management_unsupported()
352 }
353
354 async fn pending_host_event_publications(
356 &self,
357 _limit: usize,
358 ) -> SessionStoreResult<Vec<PendingHostEventPublication>> {
359 management_unsupported()
360 }
361
362 async fn materialize_host_event_publications(
367 &self,
368 _limit: usize,
369 ) -> SessionStoreResult<Vec<DurableHostEventRecord>> {
370 management_unsupported()
371 }
372
373 async fn replay_host_events(
375 &self,
376 _query: DurableHostEventQuery,
377 ) -> SessionStoreResult<DurableHostEventPage> {
378 management_unsupported()
379 }
380
381 async fn host_event_fence(
383 &self,
384 _scope: &DurableHostEventScope,
385 _event_classes: &[DurableHostEventClass],
386 ) -> SessionStoreResult<Option<u64>> {
387 management_unsupported()
388 }
389
390 async fn create_session_idempotent(
392 &self,
393 _session: SessionRecord,
394 _idempotency_key: &str,
395 _command_fingerprint: &str,
396 ) -> SessionStoreResult<SessionRecord> {
397 management_unsupported()
398 }
399
400 async fn create_session_idempotent_with_host_events(
405 &self,
406 _session: SessionRecord,
407 _idempotency_key: &str,
408 _command_fingerprint: &str,
409 _publications: Vec<PendingHostEventPublication>,
410 ) -> SessionStoreResult<SessionRecord> {
411 management_unsupported()
412 }
413
414 async fn load_session_mutation_receipt(
416 &self,
417 _namespace_id: &str,
418 _idempotency_key: &str,
419 _command_fingerprint: &str,
420 ) -> SessionStoreResult<Option<SessionRecord>> {
421 management_unsupported()
422 }
423
424 async fn update_managed_session(
426 &self,
427 _command: UpdateManagedSession,
428 _command_fingerprint: &str,
429 ) -> SessionStoreResult<SessionRecord> {
430 management_unsupported()
431 }
432
433 async fn update_managed_session_with_host_events(
435 &self,
436 _command: UpdateManagedSession,
437 _command_fingerprint: &str,
438 _publications: Vec<PendingHostEventPublication>,
439 ) -> SessionStoreResult<SessionRecord> {
440 management_unsupported()
441 }
442
443 async fn acquire_session_deletion_fence(
445 &self,
446 _session_id: &SessionId,
447 _expected_revision: u64,
448 _fence_id: &str,
449 _requested_by: &str,
450 _idempotency_key: &str,
451 _command_fingerprint: &str,
452 ) -> SessionStoreResult<SessionRecord> {
453 management_unsupported()
454 }
455
456 async fn tombstone_session(
458 &self,
459 _session_id: &SessionId,
460 _fence_id: &str,
461 ) -> SessionStoreResult<SessionRecord> {
462 management_unsupported()
463 }
464
465 #[allow(clippy::too_many_arguments)]
470 async fn tombstone_session_idempotent_with_host_events(
471 &self,
472 _session_id: &SessionId,
473 _fence_id: &str,
474 _idempotency_key: &str,
475 _command_fingerprint: &str,
476 _publications: Vec<PendingHostEventPublication>,
477 ) -> SessionStoreResult<SessionRecord> {
478 management_unsupported()
479 }
480
481 async fn session_continuation_fence(
483 &self,
484 _namespace_id: &str,
485 _session_id: &SessionId,
486 ) -> SessionStoreResult<SessionContinuationFence> {
487 management_unsupported()
488 }
489
490 async fn acquire_run_admission(
492 &self,
493 _request: AcquireRunAdmission,
494 ) -> SessionStoreResult<RunAdmissionReceipt> {
495 management_unsupported()
496 }
497
498 async fn load_run_admission_receipt(
500 &self,
501 _namespace_id: &str,
502 _idempotency_key: &str,
503 _command_fingerprint: &str,
504 ) -> SessionStoreResult<Option<RunAdmissionReceipt>> {
505 management_unsupported()
506 }
507
508 async fn heartbeat_run_admission(
510 &self,
511 _lease: &RunAdmissionLease,
512 _lease_expires_at: chrono::DateTime<chrono::Utc>,
513 ) -> SessionStoreResult<RunAdmissionLease> {
514 management_unsupported()
515 }
516
517 async fn release_run_admission(&self, _lease: &RunAdmissionLease) -> SessionStoreResult<()> {
519 management_unsupported()
520 }
521
522 async fn update_run_status_fenced(
527 &self,
528 _lease: &RunAdmissionLease,
529 _status: RunStatus,
530 _output_preview: Option<String>,
531 ) -> SessionStoreResult<RunRecord> {
532 management_unsupported()
533 }
534
535 async fn finalize_run_admission(
542 &self,
543 _lease: &RunAdmissionLease,
544 _terminal: RunTerminalProjection,
545 ) -> SessionStoreResult<RunRecord> {
546 management_unsupported()
547 }
548
549 async fn load_run_admission(
551 &self,
552 _target: &crate::ManagedRunTarget,
553 ) -> SessionStoreResult<Option<RunAdmissionLease>> {
554 management_unsupported()
555 }
556
557 async fn reconcile_expired_run_admissions(
565 &self,
566 _namespace_id: &str,
567 _now: chrono::DateTime<chrono::Utc>,
568 ) -> SessionStoreResult<Vec<crate::ManagedRunTarget>> {
569 management_unsupported()
570 }
571
572 async fn admit_run_control(
578 &self,
579 _request: AdmitRunControl,
580 ) -> SessionStoreResult<DurableRunControlIntent> {
581 management_unsupported()
582 }
583
584 async fn load_run_control_intent(
586 &self,
587 _target: &crate::ManagedRunTarget,
588 _operation_id: &str,
589 ) -> SessionStoreResult<Option<DurableRunControlIntent>> {
590 management_unsupported()
591 }
592
593 async fn list_run_control_intents(
595 &self,
596 _target: &crate::ManagedRunTarget,
597 _statuses: &[DurableRunControlStatus],
598 _limit: usize,
599 ) -> SessionStoreResult<Vec<DurableRunControlIntent>> {
600 management_unsupported()
601 }
602
603 async fn advance_run_control_intent(
608 &self,
609 _lease: &RunAdmissionLease,
610 _operation_id: &str,
611 _expected: DurableRunControlStatus,
612 _next: DurableRunControlStatus,
613 _occurred_at: chrono::DateTime<chrono::Utc>,
614 ) -> SessionStoreResult<DurableRunControlIntent> {
615 management_unsupported()
616 }
617
618 async fn reconcile_run_control_intent(
620 &self,
621 _target: &crate::ManagedRunTarget,
622 _operation_id: &str,
623 _occurred_at: chrono::DateTime<chrono::Utc>,
624 ) -> SessionStoreResult<DurableRunControlIntent> {
625 management_unsupported()
626 }
627
628 async fn load_control_receipt(
630 &self,
631 _target: &crate::ManagedRunTarget,
632 _idempotency_key: &str,
633 ) -> SessionStoreResult<Option<DurableControlReceipt>> {
634 management_unsupported()
635 }
636
637 async fn reserve_control_receipt(
639 &self,
640 _receipt: DurableControlReceipt,
641 ) -> SessionStoreResult<DurableControlReceipt> {
642 management_unsupported()
643 }
644
645 async fn update_control_receipt_state(
647 &self,
648 _receipt_id: &str,
649 _state: &str,
650 ) -> SessionStoreResult<DurableControlReceipt> {
651 management_unsupported()
652 }
653
654 async fn drain_background_subagent_operations(&self) -> SessionStoreResult<()> {
660 management_unsupported()
661 }
662
663 async fn record_background_subagent_acceptance(
665 &self,
666 _record: BackgroundSubagentRecord,
667 ) -> SessionStoreResult<BackgroundSubagentRecord> {
668 management_unsupported()
669 }
670
671 async fn update_background_subagent_execution(
673 &self,
674 _record: BackgroundSubagentRecord,
675 ) -> SessionStoreResult<BackgroundSubagentRecord> {
676 management_unsupported()
677 }
678
679 async fn heartbeat_background_subagent(
681 &self,
682 _attempt_id: &starweaver_core::SubagentAttemptId,
683 _host_instance_id: &str,
684 _fencing_generation: u64,
685 _lease_expires_at: chrono::DateTime<chrono::Utc>,
686 ) -> SessionStoreResult<BackgroundSubagentRecord> {
687 management_unsupported()
688 }
689
690 async fn commit_background_subagent_terminal(
692 &self,
693 commit: crate::BackgroundSubagentTerminalCommit,
694 ) -> SessionStoreResult<BackgroundSubagentRecord> {
695 if commit.artifact.is_some() {
696 return management_unsupported();
697 }
698 self.record_background_subagent_terminal(commit.record)
699 .await
700 }
701
702 async fn load_background_subagent_artifact(
704 &self,
705 _artifact_ref: &str,
706 ) -> SessionStoreResult<crate::BackgroundSubagentArtifact> {
707 management_unsupported()
708 }
709
710 async fn expire_background_subagent_retention(
712 &self,
713 _namespace_id: &str,
714 _now: chrono::DateTime<chrono::Utc>,
715 _limit: usize,
716 ) -> SessionStoreResult<Vec<BackgroundSubagentRecord>> {
717 management_unsupported()
718 }
719
720 async fn record_background_subagent_terminal(
722 &self,
723 _record: BackgroundSubagentRecord,
724 ) -> SessionStoreResult<BackgroundSubagentRecord> {
725 management_unsupported()
726 }
727
728 async fn load_background_subagent(
730 &self,
731 _attempt_id: &starweaver_core::SubagentAttemptId,
732 ) -> SessionStoreResult<BackgroundSubagentRecord> {
733 management_unsupported()
734 }
735
736 async fn list_background_subagents(
738 &self,
739 _namespace_id: &str,
740 _session_id: Option<&SessionId>,
741 _limit: usize,
742 ) -> SessionStoreResult<Vec<BackgroundSubagentRecord>> {
743 management_unsupported()
744 }
745
746 async fn list_pending_background_subagents(
748 &self,
749 _namespace_id: &str,
750 _session_id: Option<&SessionId>,
751 _limit: usize,
752 ) -> SessionStoreResult<Vec<BackgroundSubagentRecord>> {
753 management_unsupported()
754 }
755
756 async fn claim_background_subagent_delivery(
758 &self,
759 _attempt_id: &starweaver_core::SubagentAttemptId,
760 _claim: DurableBackgroundSubagentDeliveryClaim,
761 ) -> SessionStoreResult<BackgroundSubagentRecord> {
762 management_unsupported()
763 }
764
765 async fn acknowledge_background_subagent_delivery(
767 &self,
768 _attempt_id: &starweaver_core::SubagentAttemptId,
769 _claim_id: &str,
770 ) -> SessionStoreResult<BackgroundSubagentRecord> {
771 management_unsupported()
772 }
773
774 async fn release_background_subagent_delivery(
776 &self,
777 _attempt_id: &starweaver_core::SubagentAttemptId,
778 _claim_id: &str,
779 _release: DurableBackgroundSubagentDeliveryRelease,
780 ) -> SessionStoreResult<BackgroundSubagentRecord> {
781 management_unsupported()
782 }
783
784 async fn acquire_background_subagent_continuation(
786 &self,
787 _request: AcquireBackgroundSubagentContinuation,
788 ) -> SessionStoreResult<BackgroundSubagentContinuationReceipt> {
789 management_unsupported()
790 }
791
792 async fn reconcile_background_subagents(
794 &self,
795 _namespace_id: &str,
796 _now: chrono::DateTime<chrono::Utc>,
797 ) -> SessionStoreResult<Vec<BackgroundSubagentRecord>> {
798 management_unsupported()
799 }
800
801 async fn save_session(&self, session: SessionRecord) -> SessionStoreResult<()>;
806
807 async fn load_session(&self, session_id: &SessionId) -> SessionStoreResult<SessionRecord>;
809
810 async fn list_sessions(&self, filter: SessionFilter) -> SessionStoreResult<Vec<SessionRecord>>;
812
813 async fn list_session_page(&self, query: SessionPageQuery) -> SessionStoreResult<SessionPage>;
815
816 async fn update_session_status(
818 &self,
819 session_id: &SessionId,
820 status: SessionStatus,
821 ) -> SessionStoreResult<()>;
822
823 async fn save_context_state(
825 &self,
826 session_id: &SessionId,
827 state: ResumableState,
828 ) -> SessionStoreResult<()>;
829
830 async fn save_environment_state(
832 &self,
833 session_id: &SessionId,
834 environment_state: EnvironmentStateRef,
835 ) -> SessionStoreResult<()>;
836
837 async fn append_run(&self, run: RunRecord) -> SessionStoreResult<()>;
842
843 async fn load_run(
845 &self,
846 session_id: &SessionId,
847 run_id: &RunId,
848 ) -> SessionStoreResult<RunRecord>;
849
850 async fn list_runs(&self, session_id: &SessionId) -> SessionStoreResult<Vec<RunRecord>>;
852
853 async fn update_run_status(
858 &self,
859 session_id: &SessionId,
860 run_id: &RunId,
861 status: RunStatus,
862 output_preview: Option<String>,
863 ) -> SessionStoreResult<()>;
864
865 async fn append_checkpoint(
867 &self,
868 session_id: &SessionId,
869 checkpoint: AgentCheckpoint,
870 ) -> SessionStoreResult<()>;
871
872 async fn load_checkpoints(
874 &self,
875 session_id: &SessionId,
876 run_id: &RunId,
877 ) -> SessionStoreResult<Vec<AgentCheckpoint>>;
878
879 async fn latest_checkpoint(
881 &self,
882 session_id: &SessionId,
883 run_id: &RunId,
884 ) -> SessionStoreResult<Option<AgentCheckpoint>> {
885 let checkpoints = self.load_checkpoints(session_id, run_id).await?;
886 Ok(checkpoints.into_iter().last())
887 }
888
889 async fn append_stream_records(
891 &self,
892 session_id: &SessionId,
893 run_id: &RunId,
894 records: Vec<AgentStreamRecord>,
895 ) -> SessionStoreResult<()>;
896
897 async fn replay_stream_records(
899 &self,
900 session_id: &SessionId,
901 run_id: &RunId,
902 ) -> SessionStoreResult<Vec<AgentStreamRecord>>;
903
904 async fn replay_stream_records_after(
906 &self,
907 session_id: &SessionId,
908 run_id: &RunId,
909 after_sequence: Option<usize>,
910 ) -> SessionStoreResult<Vec<AgentStreamRecord>> {
911 let records = self.replay_stream_records(session_id, run_id).await?;
912 Ok(records
913 .into_iter()
914 .filter(|record| after_sequence.is_none_or(|cursor| record.sequence > cursor))
915 .collect())
916 }
917
918 async fn save_stream_cursor(
920 &self,
921 session_id: &SessionId,
922 run_id: &RunId,
923 cursor: StreamCursorRef,
924 ) -> SessionStoreResult<()>;
925
926 async fn append_approval(&self, approval: ApprovalRecord) -> SessionStoreResult<()>;
928
929 async fn load_approvals(
931 &self,
932 session_id: &SessionId,
933 run_id: &RunId,
934 ) -> SessionStoreResult<Vec<ApprovalRecord>>;
935
936 async fn append_deferred_tool(&self, record: DeferredToolRecord) -> SessionStoreResult<()>;
938
939 async fn load_deferred_tools(
941 &self,
942 session_id: &SessionId,
943 run_id: &RunId,
944 ) -> SessionStoreResult<Vec<DeferredToolRecord>>;
945
946 async fn resume_snapshot(
948 &self,
949 _session_id: &SessionId,
950 _run_id: &RunId,
951 ) -> SessionStoreResult<SessionResumeSnapshot> {
952 Err(SessionStoreError::Failed(
953 "session store does not support per-run resume snapshots".to_string(),
954 ))
955 }
956
957 async fn prepare_continuation(
962 &self,
963 session_id: &SessionId,
964 run_id: &RunId,
965 mode: crate::ContinuationPreparationMode,
966 ) -> SessionStoreResult<crate::PreparedContinuation> {
967 let snapshot = self.resume_snapshot(session_id, run_id).await?;
968 match mode {
969 crate::ContinuationPreparationMode::Ordinary => {
970 crate::PreparedContinuation::ordinary(snapshot)
971 }
972 crate::ContinuationPreparationMode::WaitingHitl => {
973 crate::PreparedContinuation::waiting_hitl(snapshot)
974 }
975 }
976 .map_err(|error| SessionStoreError::Conflict(error.to_string()))
977 }
978
979 async fn compact_run_trace(
981 &self,
982 session_id: &SessionId,
983 run_id: &RunId,
984 ) -> SessionStoreResult<CompactRunTrace>;
985
986 async fn compact_session_trace(
988 &self,
989 session_id: &SessionId,
990 ) -> SessionStoreResult<CompactSessionTrace>;
991}