@dreamtree-org/graphify 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,301 @@
1
+ import Graph from 'graphology';
2
+ import { z } from 'zod';
3
+
4
+ type Confidence = 'EXTRACTED' | 'INFERRED' | 'AMBIGUOUS';
5
+ type Relation = 'calls' | 'imports' | 'imports_from' | 'inherits' | 'implements' | 'mixes_in' | 'embeds' | 'references' | 'contains' | 'method' | 're_exports';
6
+ interface GraphNode {
7
+ id: string;
8
+ label: string;
9
+ sourceFile: string;
10
+ sourceLocation: string;
11
+ }
12
+ interface GraphEdge {
13
+ source: string;
14
+ target: string;
15
+ relation: Relation;
16
+ confidence: Confidence;
17
+ }
18
+ /** Per-file extractor output. Validate against this shape before buildGraph() consumes it. */
19
+ interface ExtractionResult {
20
+ nodes: GraphNode[];
21
+ edges: GraphEdge[];
22
+ }
23
+ type FileCategory = 'code' | 'document' | 'paper' | 'image' | 'video';
24
+ interface FileManifest {
25
+ scanRoot: string;
26
+ files: Record<FileCategory, string[]>;
27
+ totalFiles: number;
28
+ totalWords: number;
29
+ skippedSensitive: string[];
30
+ }
31
+ interface Analysis {
32
+ godNodes: string[];
33
+ surprises: string[];
34
+ openQuestions: string[];
35
+ }
36
+ interface ExportOptions {
37
+ outDir: string;
38
+ html?: boolean;
39
+ svg?: boolean;
40
+ graphml?: boolean;
41
+ neo4j?: boolean;
42
+ obsidian?: boolean;
43
+ obsidianDir?: string;
44
+ }
45
+
46
+ /**
47
+ * Walk `root` and categorize files into code/document/paper/image/video
48
+ * buckets. Does not follow symlinks (security.ts §5 — symlink traversal).
49
+ * Sensitive-looking files (.env, credentials, key material) are recorded in
50
+ * `skippedSensitive` and excluded from every other bucket/count.
51
+ */
52
+ declare function collectFiles(root: string): FileManifest;
53
+
54
+ type Extractor = (path: string) => Promise<ExtractionResult>;
55
+ /** File extension -> extractor module. Register new languages here. */
56
+ declare const EXTRACTOR_REGISTRY: Record<string, Extractor>;
57
+ /**
58
+ * Dispatch a single file to its language extractor. Returns an empty
59
+ * extraction (not a thrown error) for unregistered extensions so detect's
60
+ * file list and extract's coverage can diverge without crashing a run.
61
+ */
62
+ declare function extract(filePath: string): Promise<ExtractionResult>;
63
+
64
+ /**
65
+ * Merge per-file extraction results into one graphology graph.
66
+ *
67
+ * Every extraction is validated against the ExtractionResult schema before
68
+ * anything is added to the graph — a single malformed extraction throws
69
+ * (via validateExtraction()/ExtractionValidationError) before any node from
70
+ * *any* extraction is merged, so a bad extractor can never silently
71
+ * corrupt a graph that also contains good data.
72
+ *
73
+ * Nodes and edges are sorted before being added so the resulting graph (and
74
+ * the graph.json ultimately exported from it) is deterministic regardless
75
+ * of the order files were extracted in. Duplicate edges — same
76
+ * source/target/relation, e.g. two different call sites resolving to the
77
+ * same callee — are merged into a single edge, keeping the strongest
78
+ * confidence seen (EXTRACTED > INFERRED > AMBIGUOUS) rather than being
79
+ * counted as parallel edges (the schema has no call-count/weight field, so
80
+ * "A calls B" is either true or it isn't). Multiple distinct relations
81
+ * between the same pair (e.g. a file both `imports` and `imports_from` the
82
+ * same module) are kept as separate edges.
83
+ */
84
+ declare function buildGraph(extractions: ExtractionResult[]): Graph;
85
+
86
+ type ClusterAlgorithm = 'louvain' | 'leiden';
87
+ interface ClusterOptions {
88
+ /**
89
+ * `louvain` (default, v1 behavior, unchanged) or `leiden` (v2: better
90
+ * community quality / guaranteed well-connectedness, via
91
+ * `@aflsolutions/graphology-communities-leiden` — see master prompt's
92
+ * v2 upgrade ideas, "Real Leiden clustering"). Both run deterministically
93
+ * against a sorted working copy with the same fixed-seed PRNG.
94
+ */
95
+ algorithm?: ClusterAlgorithm;
96
+ /**
97
+ * Leiden-only: hard cap on outer iterations, for very large graphs where
98
+ * full convergence is expensive and the last iterations buy little
99
+ * additional modularity. Ignored for `algorithm: 'louvain'`.
100
+ */
101
+ maxIterations?: number;
102
+ }
103
+ /**
104
+ * Community detection — Louvain by default (v1, unchanged), or Leiden
105
+ * (v2, `{ algorithm: 'leiden' }`) for better-quality, guaranteed
106
+ * well-connected communities on the same graph. Deterministic: runs
107
+ * against a sorted working copy with a fixed RNG seed, then copies the
108
+ * resulting `community` assignment back onto the original graph by node id
109
+ * (so `cluster()` still mutates and returns the graph instance it was
110
+ * given). Labels each community after its highest-degree ("hub") member;
111
+ * no LLM required for a usable baseline. Also stamps a `communityHash`
112
+ * (sha256 of the community's sorted member ids) so `--cluster-only` can
113
+ * tell which communities actually changed vs. merely being relabeled with
114
+ * a different arbitrary index next run.
115
+ */
116
+ declare function cluster(graph: Graph, options?: ClusterOptions): Graph;
117
+
118
+ /**
119
+ * Surface god-nodes (excessive fan-in/out), structural surprises (self
120
+ * references, AMBIGUOUS edges), and open questions (isolated nodes,
121
+ * disconnected components) for a human to review in GRAPH_REPORT.md.
122
+ */
123
+ declare function analyze(graph: Graph): Analysis;
124
+
125
+ /**
126
+ * Render the plain-language GRAPH_REPORT.md content: a short summary,
127
+ * community breakdown, god nodes, structural surprises, and open
128
+ * questions — everything a human (or an agent) needs to sanity-check a
129
+ * freshly built graph before trusting it.
130
+ */
131
+ declare function renderReport(graph: Graph, analysis: Analysis, now?: Date): string;
132
+
133
+ /**
134
+ * Write graph.json (graphology's node-link serialization, GraphRAG-ready)
135
+ * and, per options, graph.html (vis-network, bundled inline — no CDN, works
136
+ * fully offline) and GRAPH_REPORT.md. Every label/title embedded in
137
+ * graph.html is passed through security.sanitizeLabel() + escapeHtml()
138
+ * first (XSS control, see SECURITY.md).
139
+ *
140
+ * Obsidian vault / .graphml / Neo4j cypher export are NOT implemented in
141
+ * v1 — if requested, exportGraph logs a clear warning and skips them
142
+ * rather than silently doing nothing or faking output.
143
+ */
144
+ declare function exportGraph(graph: Graph, options: ExportOptions, report?: string): Promise<void>;
145
+
146
+ interface PipelineOptions {
147
+ /** Where to write graph.json/graph.html/GRAPH_REPORT.md. Defaults to `<root>/graphify-out`. */
148
+ outDir?: string;
149
+ html?: boolean;
150
+ svg?: boolean;
151
+ graphml?: boolean;
152
+ neo4j?: boolean;
153
+ obsidian?: boolean;
154
+ /** `louvain` (default, v1) or `leiden` (v2 — better community quality, see cluster.ts). */
155
+ algorithm?: ClusterAlgorithm;
156
+ /** Leiden-only: cap on outer iterations for very large graphs. */
157
+ maxIterations?: number;
158
+ /** Called with a short progress message after each stage (e.g. for CLI stderr output). */
159
+ onProgress?: (message: string) => void;
160
+ }
161
+ interface PipelineResult {
162
+ manifest: FileManifest;
163
+ graph: Graph;
164
+ analysis: Analysis;
165
+ report: string;
166
+ }
167
+ /**
168
+ * The full `detect -> extract -> build -> cluster -> analyze -> report ->
169
+ * export` pipeline as a single library call — the CLI's default command is
170
+ * a thin wrapper over this. Every extension registered in
171
+ * EXTRACTOR_REGISTRY (see extract.ts) is run; files with no registered
172
+ * extractor are skipped (not an error — see extract()'s doc comment).
173
+ */
174
+ declare function runPipeline(root: string, options?: PipelineOptions): Promise<PipelineResult>;
175
+
176
+ /**
177
+ * Load a previously-exported graph.json back into a graphology Graph.
178
+ * Always goes through security.validateGraphPath() (path-traversal guard —
179
+ * see SECURITY.md) so a caller-supplied `outDir`/CLI arg can never make
180
+ * this read outside the graphify-out/ directory it resolves to.
181
+ */
182
+ declare function loadGraph(outDir?: string): Promise<Graph>;
183
+
184
+ interface NodeMatch {
185
+ id: string;
186
+ label: string;
187
+ score: number;
188
+ }
189
+ /** Score every node by how many query tokens appear in its label or id. */
190
+ declare function scoreNodes(graph: Graph, query: string): NodeMatch[];
191
+ /**
192
+ * Best-effort single-node resolution: the highest-scoring lexical match,
193
+ * or null if nothing in the graph matches at all. Deliberately does *not*
194
+ * fall back to "the most connected node" — path/explain name a specific
195
+ * node by intent, and silently substituting an unrelated one would be
196
+ * more misleading than clearly saying "no match".
197
+ */
198
+ declare function resolveNode(graph: Graph, query: string): NodeMatch | null;
199
+ interface VisitedNode {
200
+ id: string;
201
+ label: string;
202
+ sourceFile: string;
203
+ sourceLocation: string;
204
+ depth: number;
205
+ }
206
+ interface TraversalEdge {
207
+ source: string;
208
+ target: string;
209
+ relation: string;
210
+ confidence: string;
211
+ }
212
+ interface QueryResult {
213
+ seeds: NodeMatch[];
214
+ visited: VisitedNode[];
215
+ edges: TraversalEdge[];
216
+ }
217
+ interface QueryOptions {
218
+ dfs?: boolean;
219
+ /** Approximate cap on how many nodes to include (a stand-in for a true token budget — see docs). */
220
+ budget?: number;
221
+ maxDepth?: number;
222
+ maxSeeds?: number;
223
+ }
224
+ /**
225
+ * BFS (default, broad context) or DFS (--dfs, trace a specific path)
226
+ * traversal from the nodes whose label best matches `question`'s
227
+ * keywords. This is lexical retrieval, not natural-language
228
+ * understanding — it surfaces the neighborhood of the graph an agent (or
229
+ * a human) should look at to answer the question, it does not itself
230
+ * compose an answer.
231
+ */
232
+ declare function queryGraph(graph: Graph, question: string, options?: QueryOptions): QueryResult;
233
+ interface PathResult {
234
+ from: NodeMatch;
235
+ to: NodeMatch;
236
+ found: boolean;
237
+ path: string[];
238
+ edges: TraversalEdge[];
239
+ }
240
+ /** Shortest path between the nodes that best match `fromQuery` and `toQuery` (undirected BFS — connectivity, not call direction). */
241
+ declare function shortestPath(graph: Graph, fromQuery: string, toQuery: string): PathResult | null;
242
+ interface ExplainResult {
243
+ id: string;
244
+ label: string;
245
+ sourceFile: string;
246
+ sourceLocation: string;
247
+ communityLabel?: string;
248
+ outgoing: TraversalEdge[];
249
+ incoming: TraversalEdge[];
250
+ }
251
+ /** Plain-language-ready explanation of the node that best matches `query`. */
252
+ declare function explainNode(graph: Graph, query: string): ExplainResult | null;
253
+
254
+ declare const ExtractionResultSchema: z.ZodObject<{
255
+ nodes: z.ZodArray<z.ZodObject<{
256
+ id: z.ZodString;
257
+ label: z.ZodString;
258
+ sourceFile: z.ZodString;
259
+ sourceLocation: z.ZodString;
260
+ }, z.core.$strip>>;
261
+ edges: z.ZodArray<z.ZodObject<{
262
+ source: z.ZodString;
263
+ target: z.ZodString;
264
+ relation: z.ZodEnum<{
265
+ calls: "calls";
266
+ imports: "imports";
267
+ imports_from: "imports_from";
268
+ inherits: "inherits";
269
+ implements: "implements";
270
+ mixes_in: "mixes_in";
271
+ embeds: "embeds";
272
+ references: "references";
273
+ contains: "contains";
274
+ method: "method";
275
+ re_exports: "re_exports";
276
+ }>;
277
+ confidence: z.ZodEnum<{
278
+ EXTRACTED: "EXTRACTED";
279
+ INFERRED: "INFERRED";
280
+ AMBIGUOUS: "AMBIGUOUS";
281
+ }>;
282
+ }, z.core.$strip>>;
283
+ }, z.core.$strip>;
284
+ interface ExtractionValidationIssue {
285
+ path: Array<string | number>;
286
+ message: string;
287
+ }
288
+ /** Thrown by validateExtraction() on schema mismatch. Carries the raw zod issues. */
289
+ declare class ExtractionValidationError extends Error {
290
+ readonly issues: ExtractionValidationIssue[];
291
+ constructor(message: string, issues: ExtractionValidationIssue[]);
292
+ }
293
+ /**
294
+ * Validate an unknown value (typically an extractor's return value) against
295
+ * the ExtractionResult schema. Throws ExtractionValidationError with a clear,
296
+ * human-readable message on mismatch instead of letting malformed data reach
297
+ * buildGraph().
298
+ */
299
+ declare function validateExtraction(value: unknown, context?: string): ExtractionResult;
300
+
301
+ export { type Analysis, type ClusterAlgorithm, type ClusterOptions, type Confidence, EXTRACTOR_REGISTRY, type ExplainResult, type ExportOptions, type ExtractionResult, ExtractionResultSchema, ExtractionValidationError, type ExtractionValidationIssue, type FileCategory, type FileManifest, type GraphEdge, type GraphNode, type NodeMatch, type PathResult, type PipelineOptions, type PipelineResult, type QueryOptions, type QueryResult, type Relation, type TraversalEdge, type VisitedNode, analyze, buildGraph, cluster, collectFiles, explainNode, exportGraph, extract, loadGraph, queryGraph, renderReport, resolveNode, runPipeline, scoreNodes, shortestPath, validateExtraction };
@@ -0,0 +1,301 @@
1
+ import Graph from 'graphology';
2
+ import { z } from 'zod';
3
+
4
+ type Confidence = 'EXTRACTED' | 'INFERRED' | 'AMBIGUOUS';
5
+ type Relation = 'calls' | 'imports' | 'imports_from' | 'inherits' | 'implements' | 'mixes_in' | 'embeds' | 'references' | 'contains' | 'method' | 're_exports';
6
+ interface GraphNode {
7
+ id: string;
8
+ label: string;
9
+ sourceFile: string;
10
+ sourceLocation: string;
11
+ }
12
+ interface GraphEdge {
13
+ source: string;
14
+ target: string;
15
+ relation: Relation;
16
+ confidence: Confidence;
17
+ }
18
+ /** Per-file extractor output. Validate against this shape before buildGraph() consumes it. */
19
+ interface ExtractionResult {
20
+ nodes: GraphNode[];
21
+ edges: GraphEdge[];
22
+ }
23
+ type FileCategory = 'code' | 'document' | 'paper' | 'image' | 'video';
24
+ interface FileManifest {
25
+ scanRoot: string;
26
+ files: Record<FileCategory, string[]>;
27
+ totalFiles: number;
28
+ totalWords: number;
29
+ skippedSensitive: string[];
30
+ }
31
+ interface Analysis {
32
+ godNodes: string[];
33
+ surprises: string[];
34
+ openQuestions: string[];
35
+ }
36
+ interface ExportOptions {
37
+ outDir: string;
38
+ html?: boolean;
39
+ svg?: boolean;
40
+ graphml?: boolean;
41
+ neo4j?: boolean;
42
+ obsidian?: boolean;
43
+ obsidianDir?: string;
44
+ }
45
+
46
+ /**
47
+ * Walk `root` and categorize files into code/document/paper/image/video
48
+ * buckets. Does not follow symlinks (security.ts §5 — symlink traversal).
49
+ * Sensitive-looking files (.env, credentials, key material) are recorded in
50
+ * `skippedSensitive` and excluded from every other bucket/count.
51
+ */
52
+ declare function collectFiles(root: string): FileManifest;
53
+
54
+ type Extractor = (path: string) => Promise<ExtractionResult>;
55
+ /** File extension -> extractor module. Register new languages here. */
56
+ declare const EXTRACTOR_REGISTRY: Record<string, Extractor>;
57
+ /**
58
+ * Dispatch a single file to its language extractor. Returns an empty
59
+ * extraction (not a thrown error) for unregistered extensions so detect's
60
+ * file list and extract's coverage can diverge without crashing a run.
61
+ */
62
+ declare function extract(filePath: string): Promise<ExtractionResult>;
63
+
64
+ /**
65
+ * Merge per-file extraction results into one graphology graph.
66
+ *
67
+ * Every extraction is validated against the ExtractionResult schema before
68
+ * anything is added to the graph — a single malformed extraction throws
69
+ * (via validateExtraction()/ExtractionValidationError) before any node from
70
+ * *any* extraction is merged, so a bad extractor can never silently
71
+ * corrupt a graph that also contains good data.
72
+ *
73
+ * Nodes and edges are sorted before being added so the resulting graph (and
74
+ * the graph.json ultimately exported from it) is deterministic regardless
75
+ * of the order files were extracted in. Duplicate edges — same
76
+ * source/target/relation, e.g. two different call sites resolving to the
77
+ * same callee — are merged into a single edge, keeping the strongest
78
+ * confidence seen (EXTRACTED > INFERRED > AMBIGUOUS) rather than being
79
+ * counted as parallel edges (the schema has no call-count/weight field, so
80
+ * "A calls B" is either true or it isn't). Multiple distinct relations
81
+ * between the same pair (e.g. a file both `imports` and `imports_from` the
82
+ * same module) are kept as separate edges.
83
+ */
84
+ declare function buildGraph(extractions: ExtractionResult[]): Graph;
85
+
86
+ type ClusterAlgorithm = 'louvain' | 'leiden';
87
+ interface ClusterOptions {
88
+ /**
89
+ * `louvain` (default, v1 behavior, unchanged) or `leiden` (v2: better
90
+ * community quality / guaranteed well-connectedness, via
91
+ * `@aflsolutions/graphology-communities-leiden` — see master prompt's
92
+ * v2 upgrade ideas, "Real Leiden clustering"). Both run deterministically
93
+ * against a sorted working copy with the same fixed-seed PRNG.
94
+ */
95
+ algorithm?: ClusterAlgorithm;
96
+ /**
97
+ * Leiden-only: hard cap on outer iterations, for very large graphs where
98
+ * full convergence is expensive and the last iterations buy little
99
+ * additional modularity. Ignored for `algorithm: 'louvain'`.
100
+ */
101
+ maxIterations?: number;
102
+ }
103
+ /**
104
+ * Community detection — Louvain by default (v1, unchanged), or Leiden
105
+ * (v2, `{ algorithm: 'leiden' }`) for better-quality, guaranteed
106
+ * well-connected communities on the same graph. Deterministic: runs
107
+ * against a sorted working copy with a fixed RNG seed, then copies the
108
+ * resulting `community` assignment back onto the original graph by node id
109
+ * (so `cluster()` still mutates and returns the graph instance it was
110
+ * given). Labels each community after its highest-degree ("hub") member;
111
+ * no LLM required for a usable baseline. Also stamps a `communityHash`
112
+ * (sha256 of the community's sorted member ids) so `--cluster-only` can
113
+ * tell which communities actually changed vs. merely being relabeled with
114
+ * a different arbitrary index next run.
115
+ */
116
+ declare function cluster(graph: Graph, options?: ClusterOptions): Graph;
117
+
118
+ /**
119
+ * Surface god-nodes (excessive fan-in/out), structural surprises (self
120
+ * references, AMBIGUOUS edges), and open questions (isolated nodes,
121
+ * disconnected components) for a human to review in GRAPH_REPORT.md.
122
+ */
123
+ declare function analyze(graph: Graph): Analysis;
124
+
125
+ /**
126
+ * Render the plain-language GRAPH_REPORT.md content: a short summary,
127
+ * community breakdown, god nodes, structural surprises, and open
128
+ * questions — everything a human (or an agent) needs to sanity-check a
129
+ * freshly built graph before trusting it.
130
+ */
131
+ declare function renderReport(graph: Graph, analysis: Analysis, now?: Date): string;
132
+
133
+ /**
134
+ * Write graph.json (graphology's node-link serialization, GraphRAG-ready)
135
+ * and, per options, graph.html (vis-network, bundled inline — no CDN, works
136
+ * fully offline) and GRAPH_REPORT.md. Every label/title embedded in
137
+ * graph.html is passed through security.sanitizeLabel() + escapeHtml()
138
+ * first (XSS control, see SECURITY.md).
139
+ *
140
+ * Obsidian vault / .graphml / Neo4j cypher export are NOT implemented in
141
+ * v1 — if requested, exportGraph logs a clear warning and skips them
142
+ * rather than silently doing nothing or faking output.
143
+ */
144
+ declare function exportGraph(graph: Graph, options: ExportOptions, report?: string): Promise<void>;
145
+
146
+ interface PipelineOptions {
147
+ /** Where to write graph.json/graph.html/GRAPH_REPORT.md. Defaults to `<root>/graphify-out`. */
148
+ outDir?: string;
149
+ html?: boolean;
150
+ svg?: boolean;
151
+ graphml?: boolean;
152
+ neo4j?: boolean;
153
+ obsidian?: boolean;
154
+ /** `louvain` (default, v1) or `leiden` (v2 — better community quality, see cluster.ts). */
155
+ algorithm?: ClusterAlgorithm;
156
+ /** Leiden-only: cap on outer iterations for very large graphs. */
157
+ maxIterations?: number;
158
+ /** Called with a short progress message after each stage (e.g. for CLI stderr output). */
159
+ onProgress?: (message: string) => void;
160
+ }
161
+ interface PipelineResult {
162
+ manifest: FileManifest;
163
+ graph: Graph;
164
+ analysis: Analysis;
165
+ report: string;
166
+ }
167
+ /**
168
+ * The full `detect -> extract -> build -> cluster -> analyze -> report ->
169
+ * export` pipeline as a single library call — the CLI's default command is
170
+ * a thin wrapper over this. Every extension registered in
171
+ * EXTRACTOR_REGISTRY (see extract.ts) is run; files with no registered
172
+ * extractor are skipped (not an error — see extract()'s doc comment).
173
+ */
174
+ declare function runPipeline(root: string, options?: PipelineOptions): Promise<PipelineResult>;
175
+
176
+ /**
177
+ * Load a previously-exported graph.json back into a graphology Graph.
178
+ * Always goes through security.validateGraphPath() (path-traversal guard —
179
+ * see SECURITY.md) so a caller-supplied `outDir`/CLI arg can never make
180
+ * this read outside the graphify-out/ directory it resolves to.
181
+ */
182
+ declare function loadGraph(outDir?: string): Promise<Graph>;
183
+
184
+ interface NodeMatch {
185
+ id: string;
186
+ label: string;
187
+ score: number;
188
+ }
189
+ /** Score every node by how many query tokens appear in its label or id. */
190
+ declare function scoreNodes(graph: Graph, query: string): NodeMatch[];
191
+ /**
192
+ * Best-effort single-node resolution: the highest-scoring lexical match,
193
+ * or null if nothing in the graph matches at all. Deliberately does *not*
194
+ * fall back to "the most connected node" — path/explain name a specific
195
+ * node by intent, and silently substituting an unrelated one would be
196
+ * more misleading than clearly saying "no match".
197
+ */
198
+ declare function resolveNode(graph: Graph, query: string): NodeMatch | null;
199
+ interface VisitedNode {
200
+ id: string;
201
+ label: string;
202
+ sourceFile: string;
203
+ sourceLocation: string;
204
+ depth: number;
205
+ }
206
+ interface TraversalEdge {
207
+ source: string;
208
+ target: string;
209
+ relation: string;
210
+ confidence: string;
211
+ }
212
+ interface QueryResult {
213
+ seeds: NodeMatch[];
214
+ visited: VisitedNode[];
215
+ edges: TraversalEdge[];
216
+ }
217
+ interface QueryOptions {
218
+ dfs?: boolean;
219
+ /** Approximate cap on how many nodes to include (a stand-in for a true token budget — see docs). */
220
+ budget?: number;
221
+ maxDepth?: number;
222
+ maxSeeds?: number;
223
+ }
224
+ /**
225
+ * BFS (default, broad context) or DFS (--dfs, trace a specific path)
226
+ * traversal from the nodes whose label best matches `question`'s
227
+ * keywords. This is lexical retrieval, not natural-language
228
+ * understanding — it surfaces the neighborhood of the graph an agent (or
229
+ * a human) should look at to answer the question, it does not itself
230
+ * compose an answer.
231
+ */
232
+ declare function queryGraph(graph: Graph, question: string, options?: QueryOptions): QueryResult;
233
+ interface PathResult {
234
+ from: NodeMatch;
235
+ to: NodeMatch;
236
+ found: boolean;
237
+ path: string[];
238
+ edges: TraversalEdge[];
239
+ }
240
+ /** Shortest path between the nodes that best match `fromQuery` and `toQuery` (undirected BFS — connectivity, not call direction). */
241
+ declare function shortestPath(graph: Graph, fromQuery: string, toQuery: string): PathResult | null;
242
+ interface ExplainResult {
243
+ id: string;
244
+ label: string;
245
+ sourceFile: string;
246
+ sourceLocation: string;
247
+ communityLabel?: string;
248
+ outgoing: TraversalEdge[];
249
+ incoming: TraversalEdge[];
250
+ }
251
+ /** Plain-language-ready explanation of the node that best matches `query`. */
252
+ declare function explainNode(graph: Graph, query: string): ExplainResult | null;
253
+
254
+ declare const ExtractionResultSchema: z.ZodObject<{
255
+ nodes: z.ZodArray<z.ZodObject<{
256
+ id: z.ZodString;
257
+ label: z.ZodString;
258
+ sourceFile: z.ZodString;
259
+ sourceLocation: z.ZodString;
260
+ }, z.core.$strip>>;
261
+ edges: z.ZodArray<z.ZodObject<{
262
+ source: z.ZodString;
263
+ target: z.ZodString;
264
+ relation: z.ZodEnum<{
265
+ calls: "calls";
266
+ imports: "imports";
267
+ imports_from: "imports_from";
268
+ inherits: "inherits";
269
+ implements: "implements";
270
+ mixes_in: "mixes_in";
271
+ embeds: "embeds";
272
+ references: "references";
273
+ contains: "contains";
274
+ method: "method";
275
+ re_exports: "re_exports";
276
+ }>;
277
+ confidence: z.ZodEnum<{
278
+ EXTRACTED: "EXTRACTED";
279
+ INFERRED: "INFERRED";
280
+ AMBIGUOUS: "AMBIGUOUS";
281
+ }>;
282
+ }, z.core.$strip>>;
283
+ }, z.core.$strip>;
284
+ interface ExtractionValidationIssue {
285
+ path: Array<string | number>;
286
+ message: string;
287
+ }
288
+ /** Thrown by validateExtraction() on schema mismatch. Carries the raw zod issues. */
289
+ declare class ExtractionValidationError extends Error {
290
+ readonly issues: ExtractionValidationIssue[];
291
+ constructor(message: string, issues: ExtractionValidationIssue[]);
292
+ }
293
+ /**
294
+ * Validate an unknown value (typically an extractor's return value) against
295
+ * the ExtractionResult schema. Throws ExtractionValidationError with a clear,
296
+ * human-readable message on mismatch instead of letting malformed data reach
297
+ * buildGraph().
298
+ */
299
+ declare function validateExtraction(value: unknown, context?: string): ExtractionResult;
300
+
301
+ export { type Analysis, type ClusterAlgorithm, type ClusterOptions, type Confidence, EXTRACTOR_REGISTRY, type ExplainResult, type ExportOptions, type ExtractionResult, ExtractionResultSchema, ExtractionValidationError, type ExtractionValidationIssue, type FileCategory, type FileManifest, type GraphEdge, type GraphNode, type NodeMatch, type PathResult, type PipelineOptions, type PipelineResult, type QueryOptions, type QueryResult, type Relation, type TraversalEdge, type VisitedNode, analyze, buildGraph, cluster, collectFiles, explainNode, exportGraph, extract, loadGraph, queryGraph, renderReport, resolveNode, runPipeline, scoreNodes, shortestPath, validateExtraction };
package/dist/index.js ADDED
@@ -0,0 +1,43 @@
1
+ import {
2
+ EXTRACTOR_REGISTRY,
3
+ ExtractionResultSchema,
4
+ ExtractionValidationError,
5
+ analyze,
6
+ buildGraph,
7
+ cluster,
8
+ collectFiles,
9
+ exportGraph,
10
+ extract,
11
+ renderReport,
12
+ runPipeline,
13
+ validateExtraction
14
+ } from "./chunk-DG5FECXV.js";
15
+ import {
16
+ explainNode,
17
+ loadGraph,
18
+ queryGraph,
19
+ resolveNode,
20
+ scoreNodes,
21
+ shortestPath
22
+ } from "./chunk-5ANIDX3G.js";
23
+ export {
24
+ EXTRACTOR_REGISTRY,
25
+ ExtractionResultSchema,
26
+ ExtractionValidationError,
27
+ analyze,
28
+ buildGraph,
29
+ cluster,
30
+ collectFiles,
31
+ explainNode,
32
+ exportGraph,
33
+ extract,
34
+ loadGraph,
35
+ queryGraph,
36
+ renderReport,
37
+ resolveNode,
38
+ runPipeline,
39
+ scoreNodes,
40
+ shortestPath,
41
+ validateExtraction
42
+ };
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}