Skip to main content

synaptic_memory/
history.rs

1use std::sync::Arc;
2
3use async_trait::async_trait;
4use synaptic_core::{MemoryStore, Message, RunnableConfig, SynapseError};
5use synaptic_runnables::{BoxRunnable, Runnable};
6
7/// Wraps a `Runnable<Vec<Message>, String>` with automatic message history
8/// load/save from a `MemoryStore`.
9///
10/// On each invocation:
11/// 1. Extracts `session_id` from `config.metadata["session_id"]` (defaults to `"default"`)
12/// 2. Loads conversation history from memory
13/// 3. Appends `Message::human(input)` to the history
14/// 4. Calls the inner runnable with the full message list
15/// 5. Appends `Message::ai(output)` to memory
16/// 6. Returns the output string
17pub struct RunnableWithMessageHistory {
18    inner: BoxRunnable<Vec<Message>, String>,
19    memory: Arc<dyn MemoryStore>,
20}
21
22impl RunnableWithMessageHistory {
23    /// Create a new history-aware runnable wrapper.
24    pub fn new(inner: BoxRunnable<Vec<Message>, String>, memory: Arc<dyn MemoryStore>) -> Self {
25        Self { inner, memory }
26    }
27}
28
29#[async_trait]
30impl Runnable<String, String> for RunnableWithMessageHistory {
31    async fn invoke(&self, input: String, config: &RunnableConfig) -> Result<String, SynapseError> {
32        // Extract session_id from config metadata
33        let session_id = config
34            .metadata
35            .get("session_id")
36            .and_then(|v| v.as_str())
37            .unwrap_or("default")
38            .to_string();
39
40        // Load existing history
41        let mut messages = self.memory.load(&session_id).await?;
42
43        // Append the new human message
44        let human_msg = Message::human(&input);
45        messages.push(human_msg.clone());
46        self.memory.append(&session_id, human_msg).await?;
47
48        // Call the inner runnable with the full message list
49        let output = self.inner.invoke(messages, config).await?;
50
51        // Save the AI response to memory
52        let ai_msg = Message::ai(&output);
53        self.memory.append(&session_id, ai_msg).await?;
54
55        Ok(output)
56    }
57}