pub struct FileStore { /* private fields */ }Expand description
A file-based implementation of the Memory trait.
This provides persistent storage of conversation history using files. Supports both JSON (human-readable) and MessagePack (compact binary) formats.
§Examples
use ceylon_next::memory::{FileStore, StorageFormat};
use std::sync::Arc;
#[tokio::main]
async fn main() {
// JSON format
let memory = Arc::new(
FileStore::new("memory.json", StorageFormat::Json).await.unwrap()
);
// MessagePack format
let memory_mp = Arc::new(
FileStore::new("memory.msgpack", StorageFormat::MessagePack).await.unwrap()
);
}Implementations§
Source§impl FileStore
impl FileStore
Sourcepub async fn new<P: Into<PathBuf>>(
file_path: P,
format: StorageFormat,
) -> Result<Self, String>
pub async fn new<P: Into<PathBuf>>( file_path: P, format: StorageFormat, ) -> Result<Self, String>
Creates a new file-based store with the given file path and format.
§Arguments
file_path- Path to the storage fileformat- Serialization format (JSON or MessagePack)
§Examples
use ceylon_next::memory::{FileStore, StorageFormat};
#[tokio::main]
async fn main() {
let store = FileStore::new("memory.json", StorageFormat::Json).await.unwrap();
}Examples found in repository?
examples/11_persistent_memory.rs (line 64)
16async fn main() {
17 println!("🤖 Ceylon Agent - Persistent Memory Example\n");
18
19 // ============================================
20 // Part 1: SQLite Backend
21 // ============================================
22 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
23 println!("📦 Part 1: SQLite Backend");
24 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
25
26 let sqlite_path = "agent_memory.db";
27 let sqlite_store = SqliteStore::new(sqlite_path).await
28 .expect("Failed to create SQLite store");
29
30 let mut agent = Agent::new("PersistentAssistant", "ollama::gemma3:latest");
31 agent.with_memory(Arc::new(sqlite_store))
32 .with_system_prompt("You are a helpful assistant with persistent memory across sessions.");
33
34 println!("✅ Created agent with SQLite backend at {}\n", sqlite_path);
35
36 // Run some tasks to populate memory
37 let tasks = vec![
38 "My name is Alice and I love programming in Rust",
39 "What programming language do I like?",
40 ];
41
42 for prompt in tasks {
43 println!("📋 Task: {}", prompt);
44 let mut task = TaskRequest::new(prompt);
45 task.with_priority(5);
46
47 let response = agent.run(task).await;
48 if let OutputData::Text(_) = response.result() {
49 println!("✓ Task completed\n");
50 }
51 }
52
53 println!("📊 SQLite database now contains conversation history");
54 println!(" This data persists even after the program exits!\n");
55
56 // ============================================
57 // Part 2: File-based Backend (JSON)
58 // ============================================
59 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
60 println!("📄 Part 2: File-based Backend (JSON)");
61 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
62
63 let json_path = "agent_memory.json";
64 let file_store = FileStore::new(json_path, StorageFormat::Json).await
65 .expect("Failed to create File store");
66
67 let mut agent2 = Agent::new("FileAssistant", "ollama::gemma3:latest");
68 agent2.with_memory(Arc::new(file_store))
69 .with_system_prompt("You are a helpful assistant storing memories in JSON files.");
70
71 println!("✅ Created agent with JSON file backend at {}\n", json_path);
72
73 let task = TaskRequest::new("Remember: My favorite color is blue");
74 let response = agent2.run(task).await;
75
76 if let OutputData::Text(_) = response.result() {
77 println!("✓ Memory saved to JSON file");
78 println!(" You can open {} to view the human-readable data!\n", json_path);
79 }
80
81 // ============================================
82 // Part 3: MessagePack Backend
83 // ============================================
84 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
85 println!("📦 Part 3: MessagePack Backend (Compact Binary)");
86 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
87
88 let msgpack_path = "agent_memory.msgpack";
89 let msgpack_store = FileStore::new(msgpack_path, StorageFormat::MessagePack).await
90 .expect("Failed to create MessagePack store");
91
92 let mut agent3 = Agent::new("BinaryAssistant", "ollama::gemma3:latest");
93 agent3.with_memory(Arc::new(msgpack_store))
94 .with_system_prompt("You are a helpful assistant using compact binary storage.");
95
96 println!("✅ Created agent with MessagePack backend at {}\n", msgpack_path);
97
98 let task = TaskRequest::new("Store this efficiently: The quick brown fox jumps over the lazy dog");
99 let response = agent3.run(task).await;
100
101 if let OutputData::Text(_) = response.result() {
102 println!("✓ Memory saved to MessagePack file");
103 println!(" Binary format is more compact than JSON!\n");
104 }
105
106 // ============================================
107 // Part 4: Memory Migration
108 // ============================================
109 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
110 println!("🔄 Part 4: Memory Migration Between Backends");
111 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
112
113 // Create source and destination stores
114 let source_db = SqliteStore::new("source.db").await.unwrap();
115
116 // Create an agent with source backend and add some data
117 let mut temp_agent = Agent::new("MigrationAgent", "ollama::gemma3:latest");
118 temp_agent.with_memory(Arc::new(source_db));
119
120 let task = TaskRequest::new("Migration test: This data will be migrated!");
121 temp_agent.run(task).await;
122
123 // Note: You would normally track your agent IDs. For this demo, we'll use
124 // a known pattern - the agent creates entries with its own ID
125 println!("💡 Tip: To migrate data, you need to know the agent's ID");
126 println!(" In production, track agent IDs when creating agents\n");
127
128 println!("✓ Migration between backends is available via migrate_memory()\n");
129 println!(" Example: migrate_memory(&source, &target, \"agent-id\").await\n");
130
131 // ============================================
132 // Part 5: Export/Import Utilities
133 // ============================================
134 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
135 println!("💾 Part 5: Export/Import Utilities");
136 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
137
138 // Demonstrate export/import with the existing SQLite database
139 println!("💡 Export and import utilities are available:\n");
140 println!(" • export_to_json(store, agent_id, path)");
141 println!(" • export_to_msgpack(store, agent_id, path)");
142 println!(" • import_from_json(store, path)");
143 println!(" • import_from_msgpack(store, path)\n");
144
145 println!("✓ These functions allow you to backup and restore agent memories\n");
146
147 // ============================================
148 // Summary
149 // ============================================
150 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
151 println!("📊 Summary: Available Backends");
152 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
153
154 println!("1. InMemoryStore (default)");
155 println!(" • Fast, but data lost on restart");
156 println!(" • Best for: Development, testing\n");
157
158 println!("2. SqliteStore");
159 println!(" • Persistent, efficient queries");
160 println!(" • Best for: Production apps, large datasets\n");
161
162 println!("3. FileStore (JSON)");
163 println!(" • Human-readable, easy to inspect");
164 println!(" • Best for: Debugging, data sharing\n");
165
166 println!("4. FileStore (MessagePack)");
167 println!(" • Compact binary format");
168 println!(" • Best for: Large datasets, bandwidth constraints\n");
169
170 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
171 println!("📝 Files Created:");
172 println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
173
174 println!("• agent_memory.db - SQLite database");
175 println!("• agent_memory.json - JSON storage");
176 println!("• agent_memory.msgpack - MessagePack storage");
177 println!("• backup.json - Migrated data");
178 println!("• exported_memory.json - Exported snapshot");
179 println!("• exported_memory.msgpack - Exported snapshot (binary)\n");
180
181 println!("✅ Example completed successfully!");
182 println!("\n💡 Tip: Check the created files to see your persisted data!");
183 println!(" Try running this example again - your SQLite data will persist!");
184}Sourcepub fn format(&self) -> StorageFormat
pub fn format(&self) -> StorageFormat
Returns the storage format being used.
Trait Implementations§
Source§impl Memory for FileStore
impl Memory for FileStore
Source§fn store<'life0, 'async_trait>(
&'life0 self,
entry: MemoryEntry,
) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn store<'life0, 'async_trait>(
&'life0 self,
entry: MemoryEntry,
) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Stores a conversation in memory.
Source§fn get<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<MemoryEntry>, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<MemoryEntry>, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Retrieves a specific conversation by ID.
Source§fn get_agent_history<'life0, 'life1, 'async_trait>(
&'life0 self,
agent_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<MemoryEntry>, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_agent_history<'life0, 'life1, 'async_trait>(
&'life0 self,
agent_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<MemoryEntry>, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Retrieves all conversations for an agent.
Source§fn get_recent<'life0, 'life1, 'async_trait>(
&'life0 self,
agent_id: &'life1 str,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<MemoryEntry>, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_recent<'life0, 'life1, 'async_trait>(
&'life0 self,
agent_id: &'life1 str,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<MemoryEntry>, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Retrieves the most recent N conversations for an agent.
Source§fn search<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
agent_id: &'life1 str,
query: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<MemoryEntry>, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn search<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
agent_id: &'life1 str,
query: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<MemoryEntry>, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Searches conversations for a query string.
Auto Trait Implementations§
impl Freeze for FileStore
impl RefUnwindSafe for FileStore
impl Send for FileStore
impl Sync for FileStore
impl Unpin for FileStore
impl UnwindSafe for FileStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more