sqlite_graphrag/commands/graph_export/
args.rs1use crate::cli::GraphExportFormat;
4use crate::entity_type::EntityType;
5use serde::Serialize;
6use std::path::PathBuf;
7
8#[derive(clap::Subcommand)]
11pub enum GraphSubcommand {
12 Traverse(GraphTraverseArgs),
14 Stats(GraphStatsArgs),
16 Entities(GraphEntitiesArgs),
18 RecomputeDegree(GraphRecomputeDegreeArgs),
20}
21
22#[derive(clap::ValueEnum, Clone, Copy, Debug, PartialEq, Eq)]
24pub enum GraphTraverseFormat {
25 Json,
27}
28
29#[derive(clap::ValueEnum, Clone, Copy, Debug, PartialEq, Eq)]
31pub enum GraphStatsFormat {
32 Json,
34 Text,
36}
37
38#[derive(clap::Args)]
39#[command(after_long_help = "EXAMPLES:\n \
40 # Export full entity snapshot as JSON (default)\n \
41 sqlite-graphrag graph\n\n \
42 # Traverse relationships from a starting entity\n \
43 sqlite-graphrag graph traverse --from acme-corp --depth 2\n\n \
44 # Show graph statistics as structured JSON\n \
45 sqlite-graphrag graph stats --format json\n\n \
46 # List entities filtered by type\n \
47 sqlite-graphrag graph entities --entity-type person\n\n \
48 # Export full snapshot in DOT format for Graphviz\n \
49 sqlite-graphrag graph --format dot --output graph.dot\n\n \
50NOTES:\n \
51 Without a subcommand, exports the full entity+edge snapshot.\n \
52 Use `traverse`, `stats`, or `entities` for targeted queries.")]
53pub struct GraphArgs {
55 #[command(subcommand)]
57 pub subcommand: Option<GraphSubcommand>,
58 #[arg(long)]
60 pub namespace: Option<String>,
61 #[arg(long, value_enum, default_value = "json")]
63 pub format: GraphExportFormat,
64 #[arg(long)]
66 pub output: Option<PathBuf>,
67 #[arg(long, hide = true, help = "No-op; JSON is always emitted on stdout")]
69 pub json: bool,
70 #[arg(long)]
72 pub db: Option<String>,
73}
74
75#[derive(clap::Args)]
76#[command(after_long_help = "EXAMPLES:\n \
77 # Traverse relationships from an entity with default depth (2)\n \
78 sqlite-graphrag graph traverse --from acme-corp\n\n \
79 # Increase traversal depth to 3 hops\n \
80 sqlite-graphrag graph traverse --from acme-corp --depth 3\n\n \
81 # Traverse within a specific namespace\n \
82 sqlite-graphrag graph traverse --from acme-corp --namespace project-x\n\n \
83NOTES:\n \
84 Output is always JSON. The `hops` array contains each reachable entity\n \
85 with its relation, direction (inbound/outbound), weight, and depth level.\n \
86 Short nicknames (e.g. `danilo` vs `danilo-aguiar-teixeira`) do not exact-match;\n \
87 without `--fuzzy` the error includes ranked suggestions (v1.1.05). With\n \
88 `--fuzzy`, a clear single winner is auto-resolved and warned on stderr.")]
89pub struct GraphTraverseArgs {
91 #[arg(long)]
93 pub from: String,
94 #[arg(long, default_value_t = 2u32)]
96 pub depth: u32,
97 #[arg(long, default_value_t = false)]
101 pub fuzzy: bool,
102 #[arg(long)]
104 pub namespace: Option<String>,
105 #[arg(long, value_enum, default_value = "json")]
107 pub format: GraphTraverseFormat,
108 #[arg(long, hide = true, help = "No-op; JSON is always emitted on stdout")]
110 pub json: bool,
111 #[arg(long)]
113 pub db: Option<String>,
114}
115
116#[derive(clap::Args)]
117#[command(after_long_help = "EXAMPLES:\n \
118 # Show stats for all namespaces (human-readable text)\n \
119 sqlite-graphrag graph stats --format text\n\n \
120 # Show stats as structured JSON\n \
121 sqlite-graphrag graph stats --format json\n\n \
122 # Show stats for a specific namespace\n \
123 sqlite-graphrag graph stats --namespace project-x --format text\n\n \
124NOTES:\n \
125 Reports node_count, edge_count, avg_degree, and max_degree.\n \
126 Default format is JSON. Use `--format text` for a compact single-line summary.")]
127pub struct GraphStatsArgs {
129 #[arg(long)]
131 pub namespace: Option<String>,
132 #[arg(long, value_enum, default_value = "json")]
134 pub format: GraphStatsFormat,
135 #[arg(long, hide = true, help = "No-op; JSON is always emitted on stdout")]
137 pub json: bool,
138 #[arg(long)]
140 pub db: Option<String>,
141}
142
143#[derive(Debug, Clone, Copy, clap::ValueEnum)]
145pub enum EntitySortField {
146 Name,
148 Degree,
150 CreatedAt,
152}
153
154#[derive(Debug, Clone, Copy, Default, clap::ValueEnum)]
156pub enum SortOrder {
157 #[default]
159 Asc,
160 Desc,
162}
163
164#[derive(clap::Args)]
165#[command(after_long_help = "EXAMPLES:\n \
166 # List all entities (default limit applies)\n \
167 sqlite-graphrag graph entities\n\n \
168 # Filter by entity type\n \
169 sqlite-graphrag graph entities --entity-type person\n\n \
170 # Filter by namespace and type\n \
171 sqlite-graphrag graph entities --namespace project-x --entity-type concept\n\n \
172 # Paginate results (skip first 20, return next 10)\n \
173 sqlite-graphrag graph entities --offset 20 --limit 10\n\n \
174 # Sort by degree descending (most connected first)\n \
175 sqlite-graphrag graph entities --sort-by degree --order desc\n\n \
176 # Sort by creation date ascending\n \
177 sqlite-graphrag graph entities --sort-by created-at --order asc\n\n \
178NOTES:\n \
179 Output is always JSON with `entities`, `total_count`, `limit`, and `offset` fields.\n \
180 Entity types are canonical strings (e.g. `person`, `organization`, `location`).")]
181pub struct GraphEntitiesArgs {
183 #[arg(long)]
185 pub namespace: Option<String>,
186 #[arg(long, value_enum)]
188 pub entity_type: Option<EntityType>,
189 #[arg(long, default_value_t = crate::constants::K_GRAPH_ENTITIES_DEFAULT_LIMIT)]
191 pub limit: usize,
192 #[arg(long, default_value_t = 0usize)]
194 pub offset: usize,
195 #[arg(long, value_enum, help = "Sort entities by field")]
197 pub sort_by: Option<EntitySortField>,
198 #[arg(long, value_enum, default_value_t = SortOrder::Asc, help = "Sort order")]
200 pub order: SortOrder,
201 #[arg(long, hide = true, help = "No-op; JSON is always emitted on stdout")]
203 pub json: bool,
204 #[arg(long)]
206 pub db: Option<String>,
207}
208
209#[derive(clap::Args)]
210#[command(after_long_help = "EXAMPLES:\n \
211 # Preview divergences without writing (recommended first run)\n \
212 sqlite-graphrag graph recompute-degree --dry-run\n\n \
213 # Reconcile every namespace\n \
214 sqlite-graphrag graph recompute-degree\n\n \
215 # Reconcile a single namespace\n \
216 sqlite-graphrag graph recompute-degree --namespace project-x\n\n\
217NOTES:\n \
218 `entities.degree` is a derived cache (incremented on link, recalculated\n \
219 on merge/delete) that drifts when edges are written by paths that skip\n \
220 the recalculation. This command recomputes every entity's degree from\n \
221 the real `relationships` rows (same semantics as the canonical\n \
222 `recalculate_degree` helper: COUNT(*) WHERE source_id = id OR\n \
223 target_id = id) inside one transaction. Entities left with zero edges\n \
224 are zeroed. Envelope: {total, updated, zeroed, unchanged}.")]
225pub struct GraphRecomputeDegreeArgs {
227 #[arg(long)]
229 pub namespace: Option<String>,
230 #[arg(long)]
232 pub dry_run: bool,
233 #[arg(long, hide = true, help = "No-op; JSON is always emitted on stdout")]
235 pub json: bool,
236 #[arg(long)]
238 pub db: Option<String>,
239}
240
241#[derive(Serialize)]
242pub(crate) struct TraverseHop {
243 pub(crate) entity: String,
244 pub(crate) relation: String,
245 pub(crate) direction: String,
246 pub(crate) weight: f64,
247 pub(crate) depth: u32,
248}
249
250#[derive(Serialize)]
251pub(crate) struct GraphTraverseResponse {
252 pub(crate) from: String,
253 pub(crate) namespace: String,
254 pub(crate) depth: u32,
255 pub(crate) hops: Vec<TraverseHop>,
256 pub(crate) elapsed_ms: u64,
257}
258
259#[derive(Serialize)]
260pub(crate) struct GraphStatsResponse {
261 pub(crate) namespace: Option<String>,
262 pub(crate) node_count: i64,
263 pub(crate) edge_count: i64,
264 pub(crate) avg_degree: f64,
265 pub(crate) max_degree: i64,
266 pub(crate) elapsed_ms: u64,
267}
268
269#[derive(Serialize)]
270pub(crate) struct EntityItem {
271 pub(crate) id: i64,
272 pub(crate) name: String,
273 pub(crate) entity_type: String,
274 pub(crate) namespace: String,
275 pub(crate) created_at: String,
276 pub(crate) degree: u32,
278 #[serde(skip_serializing_if = "Option::is_none")]
279 pub(crate) description: Option<String>,
280}
281
282#[derive(Serialize)]
283pub(crate) struct GraphEntitiesResponse {
284 pub(crate) entities: Vec<EntityItem>,
285 pub(crate) total_count: i64,
286 pub(crate) limit: usize,
287 pub(crate) offset: usize,
288 pub(crate) namespace: Option<String>,
289 pub(crate) elapsed_ms: u64,
290}