llm_kernel/graph/mod.rs
1//! AI agent memory graph — SQLite-backed long-term memory with FTS5 search,
2//! smart recall, and graph-structured relevance boosting.
3//!
4//! This is **not** a general-purpose graph library. It is an agent *memory*
5//! layer: nodes carry importance and decaying recency/access signals, and are
6//! recalled by composite scoring (recency + importance + access + FTS + graph
7//! boost), with CSR algorithms ([`algo`]) surfacing structurally central
8//! memories. The niche is comparable to **Zep / Mem0 / Letta**, but local-first
9//! and vault-based rather than a hosted service.
10//!
11//! For pure topology with no memory semantics, `petgraph` or a graph database
12//! is a better fit; this module optimizes for *recall* of accumulated context.
13//!
14//! Provides a complete knowledge graph layer on top of SQLite:
15//!
16//! - **Types**: [`GraphNode`], [`GraphEdge`], [`ScoredNode`], [`GraphStats`]
17//! - **Schema**: [`init_graph_schema`] — creates tables, FTS5, indexes
18//! - **CRUD**: node/edge insert, read, update, delete
19//! - **Search**: FTS5 full-text search and dynamic filtering
20//! - **Recall**: [`smart_recall`] — composite scoring with recency, importance, access, FTS, graph boost
21//! - **Traversal**: [`graph_neighbors`] (1-hop), [`related_nodes`] (BFS via recursive CTE)
22//! - **Algorithms**: pure-Rust CSR algorithms in [`algo`] — [`pagerank()`], [`connected_components()`], [`label_propagation()`], [`dijkstra()`], [`jaccard_similarity()`]
23//! - **Lifecycle**: [`decay_importance`], [`tag_stale_nodes`], [`compute_stats`]
24//!
25//! All functions take `&rusqlite::Connection` — no hardcoded paths.
26//!
27//! ```no_run
28//! use rusqlite::Connection;
29//! use llm_kernel::graph::{init_graph_schema, upsert_node, smart_recall, GraphNode};
30//!
31//! let conn = Connection::open_in_memory().unwrap();
32//! init_graph_schema(&conn).unwrap();
33//!
34//! upsert_node(&conn, &GraphNode {
35//! id: "rust-ownership".into(),
36//! node_type: "concept".into(),
37//! title: "Rust Ownership Model".into(),
38//! body: "Ownership, borrowing, and lifetimes...".into(),
39//! tags: vec!["rust".into(), "memory-safety".into()],
40//! projects: vec!["my-project".into()],
41//! agents: vec![],
42//! created: "2026-01-01T00:00:00Z".into(),
43//! updated: "2026-01-01T00:00:00Z".into(),
44//! importance: 0.8,
45//! access_count: 0,
46//! accessed_at: String::new(),
47//! }).unwrap();
48//!
49//! let results = smart_recall(&conn, Some("my-project"), Some("ownership"), 5).unwrap();
50//! for scored in &results {
51//! println!("{:.2} — {}", scored.score, scored.node.title);
52//! }
53//! ```
54
55pub mod algo;
56pub mod backend;
57pub mod dedup;
58pub mod lifecycle;
59pub mod recall;
60pub mod schema;
61pub mod search;
62pub mod store;
63pub mod traversal;
64pub mod types;
65
66/// CJK-aware graph search (Rust-side segmentation; no schema change).
67#[cfg(feature = "graph-cjk")]
68pub mod cjk;
69
70/// PostgreSQL `GraphBackend` (feature `graph-pg`).
71#[cfg(feature = "graph-pg")]
72pub mod pg;
73
74#[cfg(feature = "graph-async")]
75pub mod async_graph;
76
77#[cfg(feature = "graph-pool")]
78pub mod async_pool;
79#[cfg(feature = "graph-pool")]
80pub use async_pool::AsyncPoolGraph;
81
82// Re-export primary types and functions
83pub use algo::{
84 CsrGraph, LABEL_PROPAGATION_ITERS, PAGERANK_DAMPING, PAGERANK_EPS, PAGERANK_ITERS,
85 SHORTEST_PATH_W_MIN, adamic_adar, common_neighbors, connected_components, dijkstra,
86 jaccard_similarity, label_propagation, label_propagation_default, link_prediction, pagerank,
87 pagerank_default, pagerank_scores, shortest_path, shortest_path_ids,
88};
89pub use backend::{GraphBackend, SqliteGraph};
90pub use dedup::{find_duplicate, upsert_node_dedup};
91pub use lifecycle::{compute_stats, decay_importance, tag_stale_nodes, touch_node, touch_nodes};
92pub use recall::smart_recall;
93pub use schema::{GRAPH_SCHEMA_VERSION, init_graph_schema, migrate_graph, schema_version};
94pub use search::{query_nodes, search_nodes};
95pub use store::{
96 append_edge, delete_edge, delete_node, read_edges, read_node, read_nodes, upsert_node,
97};
98pub use traversal::{build_graph, graph_neighbors, related_nodes};
99pub use types::{
100 Graph, GraphEdge, GraphNode, GraphNodeSummary, GraphStats, ScoredNode, validate_uuid,
101};
102
103#[cfg(feature = "graph-cjk")]
104pub use cjk::{search_nodes_cjk, segment_cjk};
105
106#[cfg(feature = "graph-pg")]
107pub use pg::PgGraph;