use adk_memory::MemoryEntry;
use chrono::{DateTime, Utc};
use serde::Serialize;
use serde_json::{Value, json};
#[derive(Debug, Serialize)]
pub struct MemoryResult {
pub content: String,
pub author: String,
pub timestamp: String,
}
pub fn format_memory_results(entries: &[MemoryEntry]) -> Value {
let results: Vec<MemoryResult> = entries
.iter()
.map(|entry| {
let content = extract_text_from_content(&entry.content);
MemoryResult {
content,
author: entry.author.clone(),
timestamp: entry.timestamp.to_rfc3339(),
}
})
.collect();
let count = results.len();
json!({
"memories": results,
"count": count
})
}
pub fn format_memory_results_as_text(entries: &[MemoryEntry]) -> String {
if entries.is_empty() {
return String::new();
}
let mut text = String::from("\n\n--- Relevant Memories ---\n");
for entry in entries {
let content = extract_text_from_content(&entry.content);
let timestamp = entry.timestamp.to_rfc3339();
text.push_str(&format!("[{timestamp}] {}: {content}\n", entry.author));
}
text.push_str("--- End Memories ---\n");
text
}
fn extract_text_from_content(content: &adk_core::Content) -> String {
content.parts.iter().filter_map(|part| part.text()).collect::<Vec<_>>().join(" ")
}
pub fn is_valid_iso8601(timestamp: &str) -> bool {
DateTime::parse_from_rfc3339(timestamp).is_ok() || timestamp.parse::<DateTime<Utc>>().is_ok()
}
#[cfg(test)]
mod tests {
use super::*;
use adk_core::Content;
use chrono::Utc;
fn make_entry(content: &str, author: &str) -> MemoryEntry {
MemoryEntry {
content: Content::new("user").with_text(content),
author: author.to_string(),
timestamp: Utc::now(),
}
}
#[test]
fn test_format_empty_results() {
let result = format_memory_results(&[]);
assert_eq!(result["count"], 0);
assert_eq!(result["memories"].as_array().unwrap().len(), 0);
}
#[test]
fn test_format_single_result() {
let entries = vec![make_entry("Hello world", "user")];
let result = format_memory_results(&entries);
assert_eq!(result["count"], 1);
let memories = result["memories"].as_array().unwrap();
assert_eq!(memories.len(), 1);
assert_eq!(memories[0]["content"], "Hello world");
assert_eq!(memories[0]["author"], "user");
assert!(memories[0]["timestamp"].as_str().is_some());
}
#[test]
fn test_format_multiple_results() {
let entries =
vec![make_entry("First memory", "user"), make_entry("Second memory", "assistant")];
let result = format_memory_results(&entries);
assert_eq!(result["count"], 2);
let memories = result["memories"].as_array().unwrap();
assert_eq!(memories[0]["content"], "First memory");
assert_eq!(memories[1]["content"], "Second memory");
}
#[test]
fn test_timestamp_is_iso8601() {
let entries = vec![make_entry("test", "user")];
let result = format_memory_results(&entries);
let timestamp = result["memories"][0]["timestamp"].as_str().unwrap();
assert!(is_valid_iso8601(timestamp));
}
#[test]
fn test_format_as_text_empty() {
let text = format_memory_results_as_text(&[]);
assert!(text.is_empty());
}
#[test]
fn test_format_as_text_with_entries() {
let entries = vec![make_entry("Hello", "user")];
let text = format_memory_results_as_text(&entries);
assert!(text.contains("Relevant Memories"));
assert!(text.contains("Hello"));
assert!(text.contains("user"));
}
}