Skip to main content

mnemo_core/query/
event_builder.rs

1use uuid::Uuid;
2
3use crate::model::event::{AgentEvent, EventType};
4use crate::query::MnemoEngine;
5
6/// Build an AgentEvent with proper hash chain linking.
7///
8/// Looks up the latest event hash for the agent and computes prev_hash
9/// to maintain chain integrity. This centralizes event construction
10/// that was previously duplicated across 8 query files.
11pub async fn build_event(
12    engine: &MnemoEngine,
13    agent_id: &str,
14    event_type: EventType,
15    payload: serde_json::Value,
16    content_for_hash: &str,
17    thread_id: Option<String>,
18) -> AgentEvent {
19    let now = chrono::Utc::now().to_rfc3339();
20    let event_content_hash = crate::hash::compute_content_hash(content_for_hash, agent_id, &now);
21    let prev_event_hash = match engine.storage.get_latest_event_hash(agent_id, None).await {
22        Ok(hash) => hash,
23        Err(e) => {
24            tracing::warn!(error = %e, "failed to get latest event hash, starting new chain segment");
25            None
26        }
27    };
28    let event_prev_hash = Some(crate::hash::compute_chain_hash(
29        &event_content_hash,
30        prev_event_hash.as_deref(),
31    ));
32
33    AgentEvent {
34        id: Uuid::now_v7(),
35        agent_id: agent_id.to_string(),
36        thread_id,
37        run_id: None,
38        parent_event_id: None,
39        event_type,
40        payload,
41        trace_id: None,
42        span_id: None,
43        model: None,
44        tokens_input: None,
45        tokens_output: None,
46        latency_ms: None,
47        cost_usd: None,
48        timestamp: now.clone(),
49        logical_clock: 0,
50        content_hash: event_content_hash,
51        prev_hash: event_prev_hash,
52        embedding: None,
53    }
54}