engram_core/
export_handler.rs1use std::sync::Arc;
2
3use serde_json::{Value, json};
4
5use engram_storage::Memory;
6
7use crate::error::CoreError;
8use crate::lock_helpers;
9use crate::server::ServerState;
10use crate::timestamp::current_utc_timestamp;
11
12pub async fn handle(state: &Arc<ServerState>, _params: Value) -> Result<Value, CoreError> {
13 let state_clone = Arc::clone(state);
14 tokio::task::spawn_blocking(move || {
15 let database = lock_helpers::lock_db(&state_clone);
16 let memories = query_active_memories(&database)?;
17 let exported_at = current_utc_timestamp();
18 let count = memories.len();
19 let serialized: Vec<Value> = memories.iter().map(memory_to_portable_json).collect();
20 Ok::<Value, CoreError>(json!({
21 "version": 1,
22 "memories": serialized,
23 "exported_at": exported_at,
24 "count": count,
25 }))
26 })
27 .await
28 .map_err(|error| CoreError::SocketError(error.to_string()))?
29}
30
31fn query_active_memories(database: &engram_storage::Database) -> Result<Vec<Memory>, CoreError> {
32 let mut statement = database
33 .connection()
34 .prepare("SELECT * FROM memories WHERE superseded_by IS NULL")
35 .map_err(|error| CoreError::ExportFailed(error.to_string()))?;
36 let rows = statement
37 .query_map([], engram_storage::row_to_memory)
38 .map_err(|error| CoreError::ExportFailed(error.to_string()))?;
39 let mut memories = Vec::new();
40 for row in rows {
41 memories.push(row.map_err(|error| CoreError::ExportFailed(error.to_string()))?);
42 }
43 Ok(memories)
44}
45
46pub fn memory_to_portable_json(memory: &Memory) -> Value {
47 json!({
48 "id": memory.id,
49 "memory_type": memory.memory_type,
50 "context": memory.context,
51 "action": memory.action,
52 "result": memory.result,
53 "score": memory.score,
54 "tags": memory.tags,
55 "project": memory.project,
56 "parent_id": memory.parent_id,
57 "source_ids": memory.source_ids,
58 "insight_type": memory.insight_type,
59 "created_at": memory.created_at,
60 "updated_at": memory.updated_at,
61 "used_count": memory.used_count,
62 "last_used_at": memory.last_used_at,
63 })
64}