use std::sync::Arc;
use async_trait::async_trait;
use synaptic_core::{MemoryStore, Message, RunnableConfig, SynapticError};
use synaptic_runnables::{BoxRunnable, Runnable};
pub struct RunnableWithMessageHistory {
inner: BoxRunnable<Vec<Message>, String>,
memory: Arc<dyn MemoryStore>,
}
impl RunnableWithMessageHistory {
pub fn new(inner: BoxRunnable<Vec<Message>, String>, memory: Arc<dyn MemoryStore>) -> Self {
Self { inner, memory }
}
}
#[async_trait]
impl Runnable<String, String> for RunnableWithMessageHistory {
async fn invoke(
&self,
input: String,
config: &RunnableConfig,
) -> Result<String, SynapticError> {
let session_id = config
.metadata
.get("session_id")
.and_then(|v| v.as_str())
.unwrap_or("default")
.to_string();
let mut messages = self.memory.load(&session_id).await?;
let human_msg = Message::human(&input);
messages.push(human_msg.clone());
self.memory.append(&session_id, human_msg).await?;
let output = self.inner.invoke(messages, config).await?;
let ai_msg = Message::ai(&output);
self.memory.append(&session_id, ai_msg).await?;
Ok(output)
}
}