use crate::error::Result;
use crate::llm::types::Message;
use futures::future::BoxFuture;
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Checkpoint {
pub session_id: String,
pub checkpoint_id: String,
pub messages: Vec<Message>,
#[serde(default)]
pub parent_checkpoint_id: Option<String>,
#[serde(default)]
pub summary: Option<String>,
#[serde(default)]
pub metadata: Option<Value>,
pub created_at: u64,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ThreadState {
pub messages: Vec<Message>,
#[serde(default)]
pub summary: Option<String>,
#[serde(default)]
pub metadata: Option<Value>,
}
impl ThreadState {
pub fn from_messages(messages: Vec<Message>) -> Self {
Self {
messages,
summary: None,
metadata: None,
}
}
}
impl Checkpoint {
pub fn thread_state(&self) -> ThreadState {
ThreadState {
messages: self.messages.clone(),
summary: self.summary.clone(),
metadata: self.metadata.clone(),
}
}
}
pub trait Checkpointer: Send + Sync {
fn put<'a>(
&'a self,
session_id: &'a str,
messages: Vec<Message>,
) -> BoxFuture<'a, Result<String>>;
fn get<'a>(&'a self, session_id: &'a str) -> BoxFuture<'a, Result<Option<Checkpoint>>>;
fn list<'a>(&'a self, session_id: &'a str) -> BoxFuture<'a, Result<Vec<Checkpoint>>>;
fn delete_session<'a>(&'a self, session_id: &'a str) -> BoxFuture<'a, Result<()>>;
fn list_sessions(&self) -> BoxFuture<'_, Result<Vec<String>>>;
fn put_state<'a>(
&'a self,
session_id: &'a str,
state: ThreadState,
) -> BoxFuture<'a, Result<String>> {
self.put(session_id, state.messages)
}
fn get_state<'a>(&'a self, session_id: &'a str) -> BoxFuture<'a, Result<Option<ThreadState>>> {
Box::pin(async move { Ok(self.get(session_id).await?.map(|cp| cp.thread_state())) })
}
}