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