use crate::{Event, Session};
use adk_core::Result;
use adk_core::identity::{AdkIdentity, AppName, SessionId, UserId};
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use serde_json::Value;
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct CreateRequest {
pub app_name: String,
pub user_id: String,
pub session_id: Option<String>,
pub state: HashMap<String, Value>,
}
impl CreateRequest {
pub fn try_app_name(&self) -> Result<AppName> {
Ok(AppName::try_from(self.app_name.as_str())?)
}
pub fn try_user_id(&self) -> Result<UserId> {
Ok(UserId::try_from(self.user_id.as_str())?)
}
pub fn try_session_id(&self) -> Result<Option<SessionId>> {
self.session_id.as_deref().map(SessionId::try_from).transpose().map_err(Into::into)
}
pub fn try_identity(&self) -> Result<Option<AdkIdentity>> {
let Some(sid) = self.try_session_id()? else {
return Ok(None);
};
Ok(Some(AdkIdentity {
app_name: self.try_app_name()?,
user_id: self.try_user_id()?,
session_id: sid,
}))
}
}
#[derive(Debug, Clone)]
pub struct GetRequest {
pub app_name: String,
pub user_id: String,
pub session_id: String,
pub num_recent_events: Option<usize>,
pub after: Option<DateTime<Utc>>,
}
impl GetRequest {
pub fn try_identity(&self) -> Result<AdkIdentity> {
Ok(AdkIdentity {
app_name: AppName::try_from(self.app_name.as_str())?,
user_id: UserId::try_from(self.user_id.as_str())?,
session_id: SessionId::try_from(self.session_id.as_str())?,
})
}
}
#[derive(Debug, Clone)]
pub struct ListRequest {
pub app_name: String,
pub user_id: String,
pub limit: Option<usize>,
pub offset: Option<usize>,
}
impl ListRequest {
pub fn try_app_name(&self) -> Result<AppName> {
Ok(AppName::try_from(self.app_name.as_str())?)
}
pub fn try_user_id(&self) -> Result<UserId> {
Ok(UserId::try_from(self.user_id.as_str())?)
}
}
#[derive(Debug, Clone)]
pub struct AppendEventRequest {
pub identity: AdkIdentity,
pub event: Event,
}
#[derive(Debug, Clone)]
pub struct DeleteRequest {
pub app_name: String,
pub user_id: String,
pub session_id: String,
}
impl DeleteRequest {
pub fn try_identity(&self) -> Result<AdkIdentity> {
Ok(AdkIdentity {
app_name: AppName::try_from(self.app_name.as_str())?,
user_id: UserId::try_from(self.user_id.as_str())?,
session_id: SessionId::try_from(self.session_id.as_str())?,
})
}
}
#[async_trait]
pub trait SessionService: Send + Sync {
async fn create(&self, req: CreateRequest) -> Result<Box<dyn Session>>;
async fn get(&self, req: GetRequest) -> Result<Box<dyn Session>>;
async fn list(&self, req: ListRequest) -> Result<Vec<Box<dyn Session>>>;
async fn delete(&self, req: DeleteRequest) -> Result<()>;
async fn append_event(&self, session_id: &str, event: Event) -> Result<()>;
async fn get_for_identity(&self, identity: &AdkIdentity) -> Result<Box<dyn Session>> {
self.get(GetRequest {
app_name: identity.app_name.as_ref().to_string(),
user_id: identity.user_id.as_ref().to_string(),
session_id: identity.session_id.as_ref().to_string(),
num_recent_events: None,
after: None,
})
.await
}
async fn delete_for_identity(&self, identity: &AdkIdentity) -> Result<()> {
self.delete(DeleteRequest {
app_name: identity.app_name.as_ref().to_string(),
user_id: identity.user_id.as_ref().to_string(),
session_id: identity.session_id.as_ref().to_string(),
})
.await
}
async fn append_event_for_identity(&self, req: AppendEventRequest) -> Result<()> {
self.append_event(req.identity.session_id.as_ref(), req.event).await
}
async fn delete_all_sessions(&self, app_name: &str, user_id: &str) -> Result<()> {
let _ = (app_name, user_id);
Err(adk_core::AdkError::session("delete_all_sessions not implemented"))
}
async fn health_check(&self) -> Result<()> {
Ok(())
}
}