ainl_graph_extractor/
extractor.rs1use crate::persona_signals::{extract_pass, PersonaSignalExtractorState};
8use crate::recurrence::update_semantic_recurrence;
9use ainl_memory::SqliteGraphStore;
10use ainl_persona::{EvolutionEngine, PersonaSnapshot, RawSignal};
11use chrono::{DateTime, Utc};
12
13pub struct GraphExtractorTask {
14 pub agent_id: String,
15 pub evolution_engine: EvolutionEngine,
16 pub signal_state: PersonaSignalExtractorState,
17}
18
19#[derive(Debug, Clone)]
20pub struct ExtractionReport {
21 pub agent_id: String,
22 pub semantic_nodes_updated: usize,
23 pub signals_extracted: usize,
25 pub signals_applied: usize,
27 pub merged_signals: Vec<RawSignal>,
29 pub persona_snapshot: PersonaSnapshot,
30 pub timestamp: DateTime<Utc>,
31}
32
33impl GraphExtractorTask {
34 pub fn new(agent_id: &str) -> Self {
35 Self {
36 agent_id: agent_id.to_string(),
37 evolution_engine: EvolutionEngine::new(agent_id),
38 signal_state: PersonaSignalExtractorState::new(),
39 }
40 }
41
42 pub fn run_pass(&mut self, store: &SqliteGraphStore) -> Result<ExtractionReport, String> {
44 let semantic_nodes_updated = update_semantic_recurrence(store, &self.agent_id)?;
45 let mut signals = self.evolution_engine.extract_signals(store)?;
46 signals.extend(extract_pass(store, &self.agent_id, &mut self.signal_state)?);
47 let signals_extracted = signals.len();
48 let merged_signals = signals.clone();
49 let signals_applied = self.evolution_engine.ingest_signals(signals);
50 let persona_snapshot = self.evolution_engine.snapshot();
51 self.evolution_engine
52 .write_persona_node(store, &persona_snapshot)?;
53 Ok(ExtractionReport {
54 agent_id: self.agent_id.clone(),
55 semantic_nodes_updated,
56 signals_extracted,
57 signals_applied,
58 merged_signals,
59 persona_snapshot,
60 timestamp: Utc::now(),
61 })
62 }
63}