pub mod bug_report;
pub mod capabilities;
pub mod connectivity;
pub mod debugging;
pub mod describe;
pub(crate) mod embeddings_view;
pub mod reporting;
pub mod schema_overview;
pub(crate) mod skills_section;
pub mod topics;
use crate::datatypes::values::Value;
use crate::graph::schema::DirGraph;
use crate::graph::storage::GraphRead;
use std::collections::HashMap;
pub use connectivity::{
compute_type_connectivity, derive_edge_counts_from_triples, sort_connectivity_triples,
};
pub struct ConnectionTypeStats {
pub connection_type: String,
pub count: usize,
pub source_types: Vec<String>,
pub target_types: Vec<String>,
pub property_names: Vec<String>,
}
pub struct NodeTypeOverview {
pub count: usize,
pub properties: HashMap<String, String>,
}
pub struct SchemaOverview {
pub node_types: Vec<(String, NodeTypeOverview)>,
pub connection_types: Vec<ConnectionTypeStats>,
pub indexes: Vec<String>,
pub node_count: usize,
pub edge_count: usize,
}
pub fn schema_overview_to_json(schema: &SchemaOverview) -> serde_json::Value {
let node_types: Vec<serde_json::Value> = schema
.node_types
.iter()
.map(|(name, ov)| {
serde_json::json!({
"type": name,
"count": ov.count,
"properties": ov.properties,
})
})
.collect();
let connection_types: Vec<serde_json::Value> = schema
.connection_types
.iter()
.map(|c| {
serde_json::json!({
"type": c.connection_type,
"count": c.count,
"source_types": c.source_types,
"target_types": c.target_types,
"property_names": c.property_names,
})
})
.collect();
serde_json::json!({
"node_types": node_types,
"connection_types": connection_types,
"indexes": schema.indexes,
"node_count": schema.node_count,
"edge_count": schema.edge_count,
})
}
pub struct PropertyStatInfo {
pub property_name: String,
pub type_string: String,
pub non_null: usize,
pub unique: usize,
pub values: Option<Vec<Value>>,
pub sample: Option<Value>,
pub approx: bool,
}
pub const EXACT_PROPERTY_STATS_MAX_NODES: usize = 200_000;
#[derive(Clone)]
pub struct NeighborConnection {
pub connection_type: String,
pub other_type: String,
pub count: usize,
}
#[derive(Clone)]
pub struct NeighborsSchema {
pub outgoing: Vec<NeighborConnection>,
pub incoming: Vec<NeighborConnection>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GraphScale {
Small,
Medium,
Large,
Extreme,
}
pub(crate) fn visible_types(graph: &DirGraph) -> impl Iterator<Item = (&str, usize)> + '_ {
graph
.type_indices
.iter()
.filter(|(nt, _)| !crate::graph::schema::is_system_label(nt))
.map(|(nt, indices)| (nt, indices.len()))
}
pub(crate) fn visible_node_count(graph: &DirGraph) -> usize {
let hidden: usize = graph
.type_indices
.iter()
.filter(|(nt, _)| crate::graph::schema::is_system_label(nt))
.map(|(_, indices)| indices.len())
.sum();
graph.graph.node_count().saturating_sub(hidden)
}
pub fn graph_scale(graph: &DirGraph) -> GraphScale {
let core_count = visible_types(graph)
.filter(|(nt, _)| !graph.parent_types.contains_key(*nt))
.count();
match core_count {
0..=15 => GraphScale::Small,
16..=200 => GraphScale::Medium,
201..=5000 => GraphScale::Large,
_ => GraphScale::Extreme,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DescribeSurface {
Python,
Cli,
Mcp,
}
impl DescribeSurface {
pub fn call(self, kwargs: &str, flags: &str) -> String {
match self {
DescribeSurface::Python => format!("describe({kwargs})"),
DescribeSurface::Mcp => format!("graph_overview({kwargs})"),
DescribeSurface::Cli => format!("kglite describe GRAPH {flags}"),
}
}
}
pub enum CypherDetail {
Off,
Overview,
Topics(Vec<String>),
}
pub enum FluentDetail {
Off,
Overview,
Topics(Vec<String>),
}
pub enum ConnectionDetail {
Off,
Overview,
Topics(Vec<String>),
}