@codragraph/cli 1.6.4 → 2.1.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.
Files changed (105) hide show
  1. package/README.md +34 -0
  2. package/dist/_shared/cgdb/schema-constants.d.ts +16 -0
  3. package/dist/_shared/cgdb/schema-constants.d.ts.map +1 -0
  4. package/dist/_shared/cgdb/schema-constants.js +67 -0
  5. package/dist/_shared/cgdb/schema-constants.js.map +1 -0
  6. package/dist/_shared/index.d.ts +2 -2
  7. package/dist/_shared/index.js +1 -1
  8. package/dist/cli/analyze.d.ts +22 -0
  9. package/dist/cli/analyze.js +109 -6
  10. package/dist/cli/compress-stats.d.ts +29 -0
  11. package/dist/cli/compress-stats.js +97 -0
  12. package/dist/cli/graphstore.d.ts +6 -2
  13. package/dist/cli/graphstore.js +45 -23
  14. package/dist/cli/index-repo.js +3 -3
  15. package/dist/cli/index.js +16 -2
  16. package/dist/cli/profile-heap.d.ts +35 -0
  17. package/dist/cli/profile-heap.js +126 -0
  18. package/dist/cli/setup.d.ts +13 -0
  19. package/dist/cli/setup.js +22 -11
  20. package/dist/cli/skill-gen.d.ts +14 -2
  21. package/dist/cli/skill-gen.js +52 -19
  22. package/dist/cli/tool.js +4 -0
  23. package/dist/cli/wiki.js +3 -3
  24. package/dist/core/augmentation/engine.js +7 -7
  25. package/dist/core/cgdb/cgdb-adapter.d.ts +176 -0
  26. package/dist/core/cgdb/cgdb-adapter.js +1320 -0
  27. package/dist/core/cgdb/content-read.d.ts +46 -0
  28. package/dist/core/cgdb/content-read.js +64 -0
  29. package/dist/core/cgdb/csv-generator.d.ts +29 -0
  30. package/dist/core/cgdb/csv-generator.js +492 -0
  31. package/dist/core/cgdb/pool-adapter.d.ts +93 -0
  32. package/dist/core/cgdb/pool-adapter.js +550 -0
  33. package/dist/core/cgdb/schema.d.ts +62 -0
  34. package/dist/core/cgdb/schema.js +502 -0
  35. package/dist/core/embeddings/embedding-pipeline.js +27 -10
  36. package/dist/core/graphstore/cgdb-row-source.d.ts +19 -0
  37. package/dist/core/graphstore/cgdb-row-source.js +141 -0
  38. package/dist/core/graphstore/index.d.ts +1 -1
  39. package/dist/core/graphstore/index.js +3 -3
  40. package/dist/core/group/bridge-db.d.ts +2 -2
  41. package/dist/core/group/bridge-db.js +123 -36
  42. package/dist/core/group/bridge-schema.d.ts +4 -4
  43. package/dist/core/group/bridge-schema.js +4 -4
  44. package/dist/core/group/cross-impact.js +3 -3
  45. package/dist/core/group/sync.js +4 -4
  46. package/dist/core/lbug/content-read.d.ts +46 -0
  47. package/dist/core/lbug/content-read.js +64 -0
  48. package/dist/core/lbug/csv-generator.d.ts +2 -6
  49. package/dist/core/lbug/csv-generator.js +45 -12
  50. package/dist/core/lbug/lbug-adapter.d.ts +4 -1
  51. package/dist/core/lbug/lbug-adapter.js +153 -21
  52. package/dist/core/lbug/schema.d.ts +7 -7
  53. package/dist/core/lbug/schema.js +18 -0
  54. package/dist/core/run-analyze.d.ts +13 -0
  55. package/dist/core/run-analyze.js +114 -27
  56. package/dist/core/search/bm25-index.d.ts +3 -3
  57. package/dist/core/search/bm25-index.js +75 -23
  58. package/dist/core/search/hybrid-search.js +2 -2
  59. package/dist/core/wiki/generator.d.ts +2 -2
  60. package/dist/core/wiki/generator.js +4 -4
  61. package/dist/core/wiki/graph-queries.d.ts +2 -2
  62. package/dist/core/wiki/graph-queries.js +5 -5
  63. package/dist/mcp/core/cgdb-adapter.d.ts +5 -0
  64. package/dist/mcp/core/cgdb-adapter.js +5 -0
  65. package/dist/mcp/core/embedder.js +1 -1
  66. package/dist/mcp/local/local-backend.d.ts +2 -2
  67. package/dist/mcp/local/local-backend.js +36 -19
  68. package/dist/mcp/server.js +3 -3
  69. package/dist/mcp/tools.js +1 -1
  70. package/dist/server/analyze-worker.js +2 -2
  71. package/dist/server/api.js +34 -33
  72. package/dist/storage/repo-manager.d.ts +42 -3
  73. package/dist/storage/repo-manager.js +23 -4
  74. package/hooks/claude/codragraph-hook.cjs +98 -5
  75. package/package.json +4 -4
  76. package/scripts/build-tree-sitter-proto.cjs +15 -3
  77. package/scripts/build.js +8 -9
  78. package/scripts/patch-tree-sitter-swift.cjs +17 -4
  79. package/skills/codragraph-api-surface.md +110 -0
  80. package/skills/codragraph-config-audit.md +146 -0
  81. package/skills/codragraph-cross-repo-impact.md +135 -0
  82. package/skills/codragraph-data-lineage.md +137 -0
  83. package/skills/codragraph-dead-code.md +119 -0
  84. package/skills/codragraph-gh-actions-debug.md +162 -0
  85. package/skills/codragraph-gh-issue-workflow.md +178 -0
  86. package/skills/codragraph-gh-pr-workflow.md +176 -0
  87. package/skills/codragraph-gh-release-workflow.md +187 -0
  88. package/skills/codragraph-git-bisect.md +176 -0
  89. package/skills/codragraph-git-force-push.md +147 -0
  90. package/skills/codragraph-git-history-rewrite.md +174 -0
  91. package/skills/codragraph-git-rebase-vs-merge.md +138 -0
  92. package/skills/codragraph-git-recovery.md +181 -0
  93. package/skills/codragraph-git-worktree.md +145 -0
  94. package/skills/codragraph-migration-tracking.md +130 -0
  95. package/skills/codragraph-notebook-context.md +136 -0
  96. package/skills/codragraph-observability-coverage.md +125 -0
  97. package/skills/codragraph-onboarding.md +129 -0
  98. package/skills/codragraph-perf-hotspots.md +132 -0
  99. package/skills/codragraph-project-switcher.md +116 -0
  100. package/skills/codragraph-security-audit.md +144 -0
  101. package/skills/codragraph-sql-tracing.md +122 -0
  102. package/skills/codragraph-supply-chain-audit.md +153 -0
  103. package/skills/codragraph-test-coverage.md +97 -0
  104. package/vendor/tree-sitter-proto/bindings/node/index.js +3 -3
  105. package/vendor/tree-sitter-proto/src/node-types.json +1 -1
package/dist/cli/tool.js CHANGED
@@ -16,6 +16,7 @@
16
16
  */
17
17
  import { writeSync } from 'node:fs';
18
18
  import { LocalBackend } from '../mcp/local/local-backend.js';
19
+ import { emitTokenStats } from './compress-stats.js';
19
20
  let _backend = null;
20
21
  async function getBackend() {
21
22
  if (_backend)
@@ -68,6 +69,7 @@ export async function queryCommand(queryText, options) {
68
69
  repo: options?.repo,
69
70
  });
70
71
  output(result);
72
+ emitTokenStats(result);
71
73
  }
72
74
  export async function contextCommand(name, options) {
73
75
  if (!name?.trim() && !options?.uid) {
@@ -83,6 +85,7 @@ export async function contextCommand(name, options) {
83
85
  repo: options?.repo,
84
86
  });
85
87
  output(result);
88
+ emitTokenStats(result);
86
89
  }
87
90
  export async function impactCommand(target, options) {
88
91
  if (!target?.trim()) {
@@ -99,6 +102,7 @@ export async function impactCommand(target, options) {
99
102
  repo: options?.repo,
100
103
  });
101
104
  output(result);
105
+ emitTokenStats(result);
102
106
  }
103
107
  catch (err) {
104
108
  // Belt-and-suspenders: catch infrastructure failures (getBackend, callTool transport)
package/dist/cli/wiki.js CHANGED
@@ -91,7 +91,7 @@ export const wikiCommand = async (inputPath, options) => {
91
91
  return;
92
92
  }
93
93
  // ── Check for existing index ────────────────────────────────────────
94
- const { storagePath, lbugPath } = getStoragePaths(repoPath);
94
+ const { storagePath, cgdbPath } = getStoragePaths(repoPath);
95
95
  const meta = await loadMeta(storagePath);
96
96
  if (!meta) {
97
97
  console.log(' Error: No CodraGraph index found.');
@@ -333,7 +333,7 @@ export const wikiCommand = async (inputPath, options) => {
333
333
  concurrency: options?.concurrency ? parseInt(options.concurrency, 10) : undefined,
334
334
  reviewOnly: options?.review,
335
335
  };
336
- const generator = new WikiGenerator(repoPath, storagePath, lbugPath, llmConfig, wikiOptions, (phase, percent, detail) => {
336
+ const generator = new WikiGenerator(repoPath, storagePath, cgdbPath, llmConfig, wikiOptions, (phase, percent, detail) => {
337
337
  const label = detail || phase;
338
338
  if (label !== lastPhase) {
339
339
  lastPhase = label;
@@ -406,7 +406,7 @@ export const wikiCommand = async (inputPath, options) => {
406
406
  ...wikiOptions,
407
407
  reviewOnly: false,
408
408
  };
409
- const continueGenerator = new WikiGenerator(repoPath, storagePath, lbugPath, llmConfig, continueOptions, (phase, percent, detail) => {
409
+ const continueGenerator = new WikiGenerator(repoPath, storagePath, cgdbPath, llmConfig, continueOptions, (phase, percent, detail) => {
410
410
  const label = detail || phase;
411
411
  if (label !== lastPhase) {
412
412
  lastPhase = label;
@@ -56,7 +56,7 @@ async function findRepoForCwd(cwd) {
56
56
  return {
57
57
  name: bestMatch.name,
58
58
  storagePath: bestMatch.storagePath,
59
- lbugPath: path.join(bestMatch.storagePath, 'lbug'),
59
+ cgdbPath: path.join(bestMatch.storagePath, 'cgdb'),
60
60
  };
61
61
  }
62
62
  catch {
@@ -81,16 +81,16 @@ export async function augment(pattern, cwd) {
81
81
  const repo = await findRepoForCwd(workDir);
82
82
  if (!repo)
83
83
  return '';
84
- // Lazy-load lbug adapter (skip unnecessary init)
85
- const { initLbug, executeQuery, isLbugReady } = await import('../lbug/pool-adapter.js');
86
- const { searchFTSFromLbug } = await import('../search/bm25-index.js');
84
+ // Lazy-load cgdb adapter (skip unnecessary init)
85
+ const { initCgdb, executeQuery, isCgdbReady } = await import('../cgdb/pool-adapter.js');
86
+ const { searchFTSFromCgdb } = await import('../search/bm25-index.js');
87
87
  const repoId = repo.name.toLowerCase();
88
88
  // Init LadybugDB if not already
89
- if (!isLbugReady(repoId)) {
90
- await initLbug(repoId, repo.lbugPath);
89
+ if (!isCgdbReady(repoId)) {
90
+ await initCgdb(repoId, repo.cgdbPath);
91
91
  }
92
92
  // Step 1: BM25 search (fast, no embeddings)
93
- const bm25Results = await searchFTSFromLbug(pattern, 10, repoId);
93
+ const bm25Results = await searchFTSFromCgdb(pattern, 10, repoId);
94
94
  if (bm25Results.length === 0)
95
95
  return '';
96
96
  // Step 2: Map BM25 file results to symbols
@@ -0,0 +1,176 @@
1
+ import cgdb from '@ladybugdb/core';
2
+ import { KnowledgeGraph } from '../graph/types.js';
3
+ import type { CachedEmbedding } from '../embeddings/types.js';
4
+ import type { ContentEncoding } from '@codragraph/graphstore';
5
+ /** Factory for creating WriteStreams — injectable for testing. */
6
+ export type WriteStreamFactory = (filePath: string) => import('fs').WriteStream;
7
+ /** Result of splitting the relationship CSV into per-label-pair files. */
8
+ export interface RelCsvSplitResult {
9
+ relHeader: string;
10
+ relsByPairMeta: Map<string, {
11
+ csvPath: string;
12
+ rows: number;
13
+ }>;
14
+ pairWriteStreams: Map<string, import('fs').WriteStream>;
15
+ skippedRels: number;
16
+ totalValidRels: number;
17
+ }
18
+ /**
19
+ * Split a relationship CSV into per-label-pair files on disk.
20
+ *
21
+ * Streams the CSV line-by-line, routing each relationship to a file named
22
+ * `rel_{fromLabel}_{toLabel}.csv`. Handles backpressure correctly: only one
23
+ * drain listener per stream at a time, and readline resumes only when ALL
24
+ * backpressured streams have drained.
25
+ *
26
+ * @param csvPath Path to the combined relationship CSV
27
+ * @param csvDir Directory to write per-pair CSV files
28
+ * @param validTables Set of valid node table names
29
+ * @param getNodeLabel Function to extract the label from a node ID
30
+ * @param wsFactory Optional WriteStream factory (defaults to fs.createWriteStream)
31
+ */
32
+ export declare const splitRelCsvByLabelPair: (csvPath: string, csvDir: string, validTables: Set<string>, getNodeLabel: (id: string) => string, wsFactory?: WriteStreamFactory) => Promise<RelCsvSplitResult>;
33
+ /** Expose the current Database for pool adapter reuse in tests. */
34
+ export declare const getDatabase: () => cgdb.Database | null;
35
+ /**
36
+ * Return true when the error message indicates that another process holds
37
+ * an exclusive lock on the LadybugDB file (e.g. `codragraph analyze` or
38
+ * `codragraph serve` running at the same time).
39
+ */
40
+ export declare const isDbBusyError: (err: unknown) => boolean;
41
+ export declare const initCgdb: (dbPath: string) => Promise<{
42
+ db: cgdb.Database;
43
+ conn: cgdb.Connection;
44
+ }>;
45
+ /**
46
+ * Execute multiple queries against one repo DB atomically.
47
+ * While the callback runs, no other request can switch the active DB.
48
+ *
49
+ * Automatically retries up to DB_LOCK_RETRY_ATTEMPTS times when the
50
+ * database is busy (e.g. `codragraph analyze` holds the write lock).
51
+ * Each retry waits DB_LOCK_RETRY_DELAY_MS * attempt milliseconds.
52
+ */
53
+ export declare const withCgdbDb: <T>(dbPath: string, operation: () => Promise<T>) => Promise<T>;
54
+ export type CgdbProgressCallback = (message: string) => void;
55
+ export declare const loadGraphToCgdb: (graph: KnowledgeGraph, repoPath: string, storagePath: string, onProgress?: CgdbProgressCallback, options?: {
56
+ compress?: ContentEncoding;
57
+ }) => Promise<{
58
+ success: boolean;
59
+ insertedRels: number;
60
+ skippedRels: number;
61
+ warnings: string[];
62
+ }>;
63
+ /**
64
+ * Insert a single node to LadybugDB
65
+ * @param label - Node type (File, Function, Class, etc.)
66
+ * @param properties - Node properties
67
+ * @param dbPath - Path to LadybugDB database (optional if already initialized)
68
+ */
69
+ export declare const insertNodeToCgdb: (label: string, properties: Record<string, any>, dbPath?: string) => Promise<boolean>;
70
+ /**
71
+ * Batch insert multiple nodes to LadybugDB using a single connection
72
+ * @param nodes - Array of {label, properties} to insert
73
+ * @param dbPath - Path to LadybugDB database
74
+ * @returns Object with success count and error count
75
+ */
76
+ export declare const batchInsertNodesToCgdb: (nodes: Array<{
77
+ label: string;
78
+ properties: Record<string, any>;
79
+ }>, dbPath: string) => Promise<{
80
+ inserted: number;
81
+ failed: number;
82
+ }>;
83
+ export declare const executeQuery: (cypher: string) => Promise<any[]>;
84
+ export declare const streamQuery: (cypher: string, onRow: (row: any) => void | Promise<void>) => Promise<number>;
85
+ /**
86
+ * Execute a single parameterized query (prepare/execute pattern).
87
+ * Prevents Cypher injection by binding values as parameters.
88
+ */
89
+ export declare const executePrepared: (cypher: string, params: Record<string, any>) => Promise<any[]>;
90
+ export declare const executeWithReusedStatement: (cypher: string, paramsList: Array<Record<string, any>>) => Promise<void>;
91
+ export declare const getCgdbStats: () => Promise<{
92
+ nodes: number;
93
+ edges: number;
94
+ }>;
95
+ /**
96
+ * Load cached embeddings from LadybugDB before a rebuild.
97
+ * Returns all embedding vectors so they can be re-inserted after the graph is reloaded,
98
+ * avoiding expensive re-embedding of unchanged nodes.
99
+ *
100
+ * Detects old schema (no chunkIndex column) and returns empty cache to trigger rebuild.
101
+ */
102
+ export declare const loadCachedEmbeddings: () => Promise<{
103
+ embeddingNodeIds: Set<string>;
104
+ embeddings: CachedEmbedding[];
105
+ }>;
106
+ /**
107
+ * Fetch existing embedding hashes from CodeEmbedding table for incremental embedding.
108
+ * Returns a Map<nodeId, contentHash> suitable for passing to `runEmbeddingPipeline`.
109
+ * Handles legacy DBs without the `contentHash` column (all rows treated as stale with empty hash).
110
+ * Returns undefined if the CodeEmbedding table does not exist.
111
+ *
112
+ * @param execQuery - Cypher query executor (typically pool-adapter's `executeQuery`)
113
+ */
114
+ export declare const fetchExistingEmbeddingHashes: (execQuery: (cypher: string) => Promise<any[]>) => Promise<Map<string, string> | undefined>;
115
+ export declare const closeCgdb: () => Promise<void>;
116
+ export declare const isCgdbReady: () => boolean;
117
+ /**
118
+ * Delete all nodes (and their relationships) for a specific file from LadybugDB
119
+ * @param filePath - The file path to delete nodes for
120
+ * @param dbPath - Optional path to LadybugDB for per-query connection
121
+ * @returns Object with counts of deleted nodes
122
+ */
123
+ export declare const deleteNodesForFile: (filePath: string, dbPath?: string) => Promise<{
124
+ deletedNodes: number;
125
+ }>;
126
+ export declare const getEmbeddingTableName: () => string;
127
+ /**
128
+ * Load the FTS extension (required before using FTS functions).
129
+ * Safe to call multiple times — tracks loaded state via module-level ftsLoaded.
130
+ */
131
+ export declare const loadFTSExtension: () => Promise<void>;
132
+ /**
133
+ * Load the VECTOR extension (required before using QUERY_VECTOR_INDEX).
134
+ * Safe to call multiple times -- tracks loaded state via module-level vectorExtensionLoaded.
135
+ */
136
+ export declare const loadVectorExtension: () => Promise<void>;
137
+ /**
138
+ * Create a full-text search index on a table
139
+ * @param tableName - The node table name (e.g., 'File', 'CodeSymbol')
140
+ * @param indexName - Name for the FTS index
141
+ * @param properties - List of properties to index (e.g., ['name', 'code'])
142
+ * @param stemmer - Stemming algorithm (default: 'porter')
143
+ */
144
+ export declare const createFTSIndex: (tableName: string, indexName: string, properties: string[], stemmer?: string) => Promise<void>;
145
+ /**
146
+ * Lazy-create an FTS index, caching the fact in-process.
147
+ *
148
+ * Used by `queryFTS` so that `analyze` doesn't pay the ~440 ms × 5 fixed
149
+ * LadybugDB cost up-front (it dominates analyze on small repos). Instead,
150
+ * the cost is moved to the first `query`/`context` call in a session,
151
+ * where it's amortised across many lookups.
152
+ *
153
+ * Safe to call repeatedly — the in-process Set guarantees only the first
154
+ * call hits LadybugDB. `closeCgdb` clears the cache so re-init starts fresh.
155
+ */
156
+ export declare const ensureFTSIndex: (tableName: string, indexName: string, properties: string[], stemmer?: string) => Promise<void>;
157
+ /**
158
+ * Query a full-text search index
159
+ * @param tableName - The node table name
160
+ * @param indexName - FTS index name
161
+ * @param query - Search query string
162
+ * @param limit - Maximum results
163
+ * @param conjunctive - If true, all terms must match (AND); if false, any term matches (OR)
164
+ * @returns Array of { node properties, score }
165
+ */
166
+ export declare const queryFTS: (tableName: string, indexName: string, query: string, limit?: number, conjunctive?: boolean) => Promise<Array<{
167
+ nodeId: string;
168
+ name: string;
169
+ filePath: string;
170
+ score: number;
171
+ [key: string]: any;
172
+ }>>;
173
+ /**
174
+ * Drop an FTS index
175
+ */
176
+ export declare const dropFTSIndex: (tableName: string, indexName: string) => Promise<void>;