1pub mod fs;
2
3use crate::capture::CaptureRecord;
4use async_trait::async_trait;
5use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7use thiserror::Error;
8
9pub use fs::FsStore;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct SessionMeta {
13 pub session_id: String,
14 pub provider: String,
15 pub upstream: String,
16 pub proxy_port: u16,
17 pub api_port: u16,
18 pub started_at: DateTime<Utc>,
19 pub ended_at: Option<DateTime<Utc>>,
20 pub request_count: u64,
21 pub schema_version: u32,
22}
23
24#[derive(Debug, Clone, Serialize)]
25pub struct RequestSummary {
26 pub seq: u64,
27 pub session_id: String,
28 pub request_id: Option<String>,
29 pub started_at: DateTime<Utc>,
30 pub duration_ms: Option<u64>,
31 pub model: Option<String>,
32 pub status: Option<u16>,
33 pub input_tokens: Option<u64>,
34 pub output_tokens: Option<u64>,
35 pub has_error: bool,
36}
37
38#[derive(Debug, Error)]
39pub enum StoreError {
40 #[error("io error: {0}")]
41 Io(#[from] std::io::Error),
42 #[error("serde: {0}")]
43 Json(#[from] serde_json::Error),
44 #[error("session not found: {0}")]
45 SessionNotFound(String),
46}
47
48#[async_trait]
49pub trait Store: Send + Sync + 'static {
50 fn as_any(&self) -> &dyn std::any::Any;
51 async fn init_session(&self, meta: SessionMeta) -> Result<(), StoreError>;
52 async fn finalize_session(&self, session_id: &str) -> Result<(), StoreError>;
53 async fn append(&self, rec: CaptureRecord) -> Result<(), StoreError>;
54 async fn list_sessions(&self) -> Result<Vec<SessionMeta>, StoreError>;
55 async fn list_requests(&self, session_id: &str) -> Result<Vec<RequestSummary>, StoreError>;
56 async fn get_request(
57 &self,
58 session_id: &str,
59 seq: u64,
60 ) -> Result<Option<CaptureRecord>, StoreError>;
61}