@codragraph/cli 2.0.0 → 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.
- package/README.md +2 -2
- package/dist/_shared/cgdb/schema-constants.d.ts +16 -0
- package/dist/_shared/cgdb/schema-constants.d.ts.map +1 -0
- package/dist/_shared/cgdb/schema-constants.js +67 -0
- package/dist/_shared/cgdb/schema-constants.js.map +1 -0
- package/dist/_shared/index.d.ts +2 -2
- package/dist/_shared/index.js +1 -1
- package/dist/cli/analyze.js +3 -3
- package/dist/cli/graphstore.js +21 -21
- package/dist/cli/index-repo.js +3 -3
- package/dist/cli/wiki.js +3 -3
- package/dist/core/augmentation/engine.js +7 -7
- package/dist/core/cgdb/cgdb-adapter.d.ts +176 -0
- package/dist/core/cgdb/cgdb-adapter.js +1320 -0
- package/dist/core/cgdb/content-read.d.ts +46 -0
- package/dist/core/cgdb/content-read.js +64 -0
- package/dist/core/cgdb/csv-generator.d.ts +29 -0
- package/dist/core/cgdb/csv-generator.js +492 -0
- package/dist/core/cgdb/pool-adapter.d.ts +93 -0
- package/dist/core/cgdb/pool-adapter.js +550 -0
- package/dist/core/cgdb/schema.d.ts +62 -0
- package/dist/core/cgdb/schema.js +502 -0
- package/dist/core/embeddings/embedding-pipeline.js +4 -4
- package/dist/core/graphstore/cgdb-row-source.d.ts +19 -0
- package/dist/core/graphstore/cgdb-row-source.js +141 -0
- package/dist/core/graphstore/index.d.ts +1 -1
- package/dist/core/graphstore/index.js +3 -3
- package/dist/core/group/bridge-db.d.ts +2 -2
- package/dist/core/group/bridge-db.js +18 -18
- package/dist/core/group/bridge-schema.d.ts +4 -4
- package/dist/core/group/bridge-schema.js +4 -4
- package/dist/core/group/cross-impact.js +3 -3
- package/dist/core/group/sync.js +4 -4
- package/dist/core/run-analyze.js +24 -24
- package/dist/core/search/bm25-index.d.ts +3 -3
- package/dist/core/search/bm25-index.js +9 -9
- package/dist/core/search/hybrid-search.js +2 -2
- package/dist/core/wiki/generator.d.ts +2 -2
- package/dist/core/wiki/generator.js +4 -4
- package/dist/core/wiki/graph-queries.d.ts +2 -2
- package/dist/core/wiki/graph-queries.js +5 -5
- package/dist/mcp/core/cgdb-adapter.d.ts +5 -0
- package/dist/mcp/core/cgdb-adapter.js +5 -0
- package/dist/mcp/core/embedder.js +1 -1
- package/dist/mcp/local/local-backend.d.ts +2 -2
- package/dist/mcp/local/local-backend.js +15 -15
- package/dist/mcp/server.js +3 -3
- package/dist/mcp/tools.js +1 -1
- package/dist/server/analyze-worker.js +2 -2
- package/dist/server/api.js +31 -31
- package/dist/storage/repo-manager.d.ts +4 -4
- package/dist/storage/repo-manager.js +5 -5
- package/hooks/claude/codragraph-hook.cjs +4 -4
- package/package.json +3 -3
- package/scripts/build.js +8 -9
- package/vendor/tree-sitter-proto/bindings/node/index.js +3 -3
- package/vendor/tree-sitter-proto/src/node-types.json +1 -1
package/README.md
CHANGED
|
@@ -325,7 +325,7 @@ are too big.
|
|
|
325
325
|
|
|
326
326
|
### Index size — opt-in per-row compression
|
|
327
327
|
|
|
328
|
-
For repos where `.codragraph/
|
|
328
|
+
For repos where `.codragraph/cgdb` itself has grown large:
|
|
329
329
|
|
|
330
330
|
```bash
|
|
331
331
|
codragraph analyze --compress brotli # Node ≥ 18, brotli quality 6
|
|
@@ -334,7 +334,7 @@ codragraph analyze --compress none # explicit default
|
|
|
334
334
|
```
|
|
335
335
|
|
|
336
336
|
`--compress` routes every node-row content field through the matching
|
|
337
|
-
encoder before it's written to the CSV /
|
|
337
|
+
encoder before it's written to the CSV / cgdb; readers decode
|
|
338
338
|
transparently via the per-row `contentEncoding` tag. With the flag
|
|
339
339
|
unset, the on-disk layout is byte-identical to pre-1.8 indexes. Pre-1.8
|
|
340
340
|
indexes auto-trigger a full re-analyze the first time a 1.8+ CLI runs
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LadybugDB schema constants — single source of truth.
|
|
3
|
+
*
|
|
4
|
+
* NODE_TABLES and REL_TYPES define what the knowledge graph can contain.
|
|
5
|
+
* Both CLI and web must agree on these for data compatibility.
|
|
6
|
+
*
|
|
7
|
+
* Full DDL schemas remain in each package's own schema.ts because
|
|
8
|
+
* the CLI uses native LadybugDB and the web uses WASM.
|
|
9
|
+
*/
|
|
10
|
+
export declare const NODE_TABLES: readonly ["File", "Folder", "Function", "Class", "Interface", "Method", "CodeElement", "Community", "Process", "Section", "Struct", "Enum", "Macro", "Typedef", "Union", "Namespace", "Trait", "Impl", "TypeAlias", "Const", "Static", "Variable", "Property", "Record", "Delegate", "Annotation", "Constructor", "Template", "Module", "Route", "Tool"];
|
|
11
|
+
export type NodeTableName = (typeof NODE_TABLES)[number];
|
|
12
|
+
export declare const REL_TABLE_NAME = "CodeRelation";
|
|
13
|
+
export declare const REL_TYPES: readonly ["CONTAINS", "DEFINES", "IMPORTS", "CALLS", "EXTENDS", "IMPLEMENTS", "HAS_METHOD", "HAS_PROPERTY", "ACCESSES", "METHOD_OVERRIDES", "OVERRIDES", "METHOD_IMPLEMENTS", "MEMBER_OF", "STEP_IN_PROCESS", "HANDLES_ROUTE", "FETCHES", "HANDLES_TOOL", "ENTRY_POINT_OF", "WRAPS", "QUERIES"];
|
|
14
|
+
export type RelType = (typeof REL_TYPES)[number];
|
|
15
|
+
export declare const EMBEDDING_TABLE_NAME = "CodeEmbedding";
|
|
16
|
+
//# sourceMappingURL=schema-constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-constants.d.ts","sourceRoot":"","sources":["../../src/cgdb/schema-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,WAAW,0VAgCd,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAE7C,eAAO,MAAM,SAAS,iSAqBZ,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjD,eAAO,MAAM,oBAAoB,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LadybugDB schema constants — single source of truth.
|
|
3
|
+
*
|
|
4
|
+
* NODE_TABLES and REL_TYPES define what the knowledge graph can contain.
|
|
5
|
+
* Both CLI and web must agree on these for data compatibility.
|
|
6
|
+
*
|
|
7
|
+
* Full DDL schemas remain in each package's own schema.ts because
|
|
8
|
+
* the CLI uses native LadybugDB and the web uses WASM.
|
|
9
|
+
*/
|
|
10
|
+
export const NODE_TABLES = [
|
|
11
|
+
'File',
|
|
12
|
+
'Folder',
|
|
13
|
+
'Function',
|
|
14
|
+
'Class',
|
|
15
|
+
'Interface',
|
|
16
|
+
'Method',
|
|
17
|
+
'CodeElement',
|
|
18
|
+
'Community',
|
|
19
|
+
'Process',
|
|
20
|
+
'Section',
|
|
21
|
+
'Struct',
|
|
22
|
+
'Enum',
|
|
23
|
+
'Macro',
|
|
24
|
+
'Typedef',
|
|
25
|
+
'Union',
|
|
26
|
+
'Namespace',
|
|
27
|
+
'Trait',
|
|
28
|
+
'Impl',
|
|
29
|
+
'TypeAlias',
|
|
30
|
+
'Const',
|
|
31
|
+
'Static',
|
|
32
|
+
'Variable',
|
|
33
|
+
'Property',
|
|
34
|
+
'Record',
|
|
35
|
+
'Delegate',
|
|
36
|
+
'Annotation',
|
|
37
|
+
'Constructor',
|
|
38
|
+
'Template',
|
|
39
|
+
'Module',
|
|
40
|
+
'Route',
|
|
41
|
+
'Tool',
|
|
42
|
+
];
|
|
43
|
+
export const REL_TABLE_NAME = 'CodeRelation';
|
|
44
|
+
export const REL_TYPES = [
|
|
45
|
+
'CONTAINS',
|
|
46
|
+
'DEFINES',
|
|
47
|
+
'IMPORTS',
|
|
48
|
+
'CALLS',
|
|
49
|
+
'EXTENDS',
|
|
50
|
+
'IMPLEMENTS',
|
|
51
|
+
'HAS_METHOD',
|
|
52
|
+
'HAS_PROPERTY',
|
|
53
|
+
'ACCESSES',
|
|
54
|
+
'METHOD_OVERRIDES',
|
|
55
|
+
'OVERRIDES', // Legacy compat alias — kept until all stored indexes are migrated
|
|
56
|
+
'METHOD_IMPLEMENTS',
|
|
57
|
+
'MEMBER_OF',
|
|
58
|
+
'STEP_IN_PROCESS',
|
|
59
|
+
'HANDLES_ROUTE',
|
|
60
|
+
'FETCHES',
|
|
61
|
+
'HANDLES_TOOL',
|
|
62
|
+
'ENTRY_POINT_OF',
|
|
63
|
+
'WRAPS',
|
|
64
|
+
'QUERIES',
|
|
65
|
+
];
|
|
66
|
+
export const EMBEDDING_TABLE_NAME = 'CodeEmbedding';
|
|
67
|
+
//# sourceMappingURL=schema-constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-constants.js","sourceRoot":"","sources":["../../src/cgdb/schema-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM;IACN,QAAQ;IACR,UAAU;IACV,OAAO;IACP,WAAW;IACX,QAAQ;IACR,aAAa;IACb,WAAW;IACX,SAAS;IACT,SAAS;IACT,QAAQ;IACR,MAAM;IACN,OAAO;IACP,SAAS;IACT,OAAO;IACP,WAAW;IACX,OAAO;IACP,MAAM;IACN,WAAW;IACX,OAAO;IACP,QAAQ;IACR,UAAU;IACV,UAAU;IACV,QAAQ;IACR,UAAU;IACV,YAAY;IACZ,aAAa;IACb,UAAU;IACV,QAAQ;IACR,OAAO;IACP,MAAM;CACE,CAAC;AAIX,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,CAAC;AAE7C,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,UAAU;IACV,SAAS;IACT,SAAS;IACT,OAAO;IACP,SAAS;IACT,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,UAAU;IACV,kBAAkB;IAClB,WAAW,EAAE,mEAAmE;IAChF,mBAAmB;IACnB,WAAW;IACX,iBAAiB;IACjB,eAAe;IACf,SAAS;IACT,cAAc;IACd,gBAAgB;IAChB,OAAO;IACP,SAAS;CACD,CAAC;AAIX,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC"}
|
package/dist/_shared/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { NodeLabel, NodeProperties, RelationshipType, GraphNode, GraphRelationship, } from './graph/types.js';
|
|
2
|
-
export { NODE_TABLES, REL_TABLE_NAME, REL_TYPES, EMBEDDING_TABLE_NAME, } from './
|
|
3
|
-
export type { NodeTableName, RelType } from './
|
|
2
|
+
export { NODE_TABLES, REL_TABLE_NAME, REL_TYPES, EMBEDDING_TABLE_NAME, } from './cgdb/schema-constants.js';
|
|
3
|
+
export type { NodeTableName, RelType } from './cgdb/schema-constants.js';
|
|
4
4
|
export { SupportedLanguages } from './languages.js';
|
|
5
5
|
export { getLanguageFromFilename, getSyntaxLanguageFromFilename } from './language-detection.js';
|
|
6
6
|
export type { MroStrategy } from './mro-strategy.js';
|
package/dist/_shared/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Schema constants
|
|
2
|
-
export { NODE_TABLES, REL_TABLE_NAME, REL_TYPES, EMBEDDING_TABLE_NAME, } from './
|
|
2
|
+
export { NODE_TABLES, REL_TABLE_NAME, REL_TYPES, EMBEDDING_TABLE_NAME, } from './cgdb/schema-constants.js';
|
|
3
3
|
// Language support
|
|
4
4
|
export { SupportedLanguages } from './languages.js';
|
|
5
5
|
export { getLanguageFromFilename, getSyntaxLanguageFromFilename } from './language-detection.js';
|
package/dist/cli/analyze.js
CHANGED
|
@@ -12,7 +12,7 @@ import { execFileSync } from 'child_process';
|
|
|
12
12
|
import v8 from 'v8';
|
|
13
13
|
import cliProgress from 'cli-progress';
|
|
14
14
|
import * as fsSync from 'node:fs';
|
|
15
|
-
import {
|
|
15
|
+
import { closeCgdb } from '../core/cgdb/cgdb-adapter.js';
|
|
16
16
|
import { getStoragePaths, getGlobalRegistryPath, RegistryNameCollisionError, } from '../storage/repo-manager.js';
|
|
17
17
|
import { getGitRoot, hasGitDir } from '../storage/git.js';
|
|
18
18
|
import { runFullAnalysis } from '../core/run-analyze.js';
|
|
@@ -79,7 +79,7 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
79
79
|
// gracefully falls back to name-only matches instead of tokenising
|
|
80
80
|
// base64 garbage. Surface the trade-off so users know what they're
|
|
81
81
|
// opting into.
|
|
82
|
-
console.warn(` Note: --compress ${options.compress} reduces .codragraph/
|
|
82
|
+
console.warn(` Note: --compress ${options.compress} reduces .codragraph/cgdb size.\n` +
|
|
83
83
|
` BM25 search will index symbol names only (function bodies are not tokenised\n` +
|
|
84
84
|
` when compressed); embeddings, graph queries, and \`context\` / \`impact\` are\n` +
|
|
85
85
|
` unaffected. Run with --compress none if you rely on full-text search inside\n` +
|
|
@@ -182,7 +182,7 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
182
182
|
aborted = true;
|
|
183
183
|
bar.stop();
|
|
184
184
|
console.log('\n Interrupted — cleaning up...');
|
|
185
|
-
|
|
185
|
+
closeCgdb()
|
|
186
186
|
.catch(() => { })
|
|
187
187
|
.finally(() => process.exit(130));
|
|
188
188
|
};
|
package/dist/cli/graphstore.js
CHANGED
|
@@ -12,7 +12,7 @@ import fs from 'node:fs/promises';
|
|
|
12
12
|
import { FsCAS, createBranch, createCommit, DEFAULT_BRANCH, deleteBranch, diffSemantic, diffSnapshots, gc as runGc, getJson, listBranches, materializeSnapshot, parseObjectId, readCommit, readHead, resolveHeadCommit, setHead, threeWayMerge, walkCommits, writeHeadBranch, writeHeadDetached, } from '@codragraph/graphstore';
|
|
13
13
|
import { findRepo, loadMeta, saveMeta } from '../storage/repo-manager.js';
|
|
14
14
|
import { GRAPHSTORE_SUBDIR } from '../core/graphstore/index.js';
|
|
15
|
-
import {
|
|
15
|
+
import { initCgdb, closeCgdb } from '../core/cgdb/cgdb-adapter.js';
|
|
16
16
|
import { recordAnalysisSnapshot } from '../core/graphstore/index.js';
|
|
17
17
|
import { getCurrentCommit, hasGitDir } from '../storage/git.js';
|
|
18
18
|
const resolveGraphstore = async (cwd) => {
|
|
@@ -164,7 +164,7 @@ export const commitCommand = async (opts = {}) => {
|
|
|
164
164
|
const repo = await findRepo(process.cwd());
|
|
165
165
|
if (!repo)
|
|
166
166
|
throw new Error('No CodraGraph index found');
|
|
167
|
-
await
|
|
167
|
+
await initCgdb(repo.cgdbPath);
|
|
168
168
|
try {
|
|
169
169
|
const result = await recordAnalysisSnapshot({
|
|
170
170
|
storagePath: repo.storagePath,
|
|
@@ -191,7 +191,7 @@ export const commitCommand = async (opts = {}) => {
|
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
finally {
|
|
194
|
-
await
|
|
194
|
+
await closeCgdb();
|
|
195
195
|
}
|
|
196
196
|
// Avoid unused warnings while keeping the import live for future callers.
|
|
197
197
|
void ctx;
|
|
@@ -221,10 +221,10 @@ export const branchCreateCommand = async (name, opts = {}) => {
|
|
|
221
221
|
// ──────────────────────────────────────────────────────────────────────
|
|
222
222
|
//
|
|
223
223
|
// Two modes:
|
|
224
|
-
// - default : just move HEAD (no
|
|
224
|
+
// - default : just move HEAD (no cgdb rewrite). Cheap; good for
|
|
225
225
|
// log/diff inspection from a different vantage point.
|
|
226
226
|
// - --materialize : also rebuild the live LadybugDB from the target
|
|
227
|
-
// snapshot. Destructive of the current
|
|
227
|
+
// snapshot. Destructive of the current cgdb state —
|
|
228
228
|
// run `commit` first if you have unsaved changes.
|
|
229
229
|
export const checkoutCommand = async (target, opts = {}) => {
|
|
230
230
|
const ctx = await resolveGraphstore(process.cwd());
|
|
@@ -247,9 +247,9 @@ export const checkoutCommand = async (target, opts = {}) => {
|
|
|
247
247
|
throw new Error('No CodraGraph index found');
|
|
248
248
|
const commit = await readCommit(ctx.cas, commitId);
|
|
249
249
|
process.stdout.write(`materializing snapshot ${commit.snapshot.slice(7, 7 + 12)}...\n`);
|
|
250
|
-
// Wipe and reinit
|
|
251
|
-
await
|
|
252
|
-
for (const f of [repo.
|
|
250
|
+
// Wipe and reinit cgdb.
|
|
251
|
+
await closeCgdb();
|
|
252
|
+
for (const f of [repo.cgdbPath, `${repo.cgdbPath}.wal`, `${repo.cgdbPath}.lock`]) {
|
|
253
253
|
try {
|
|
254
254
|
await fs.rm(f, { recursive: true, force: true });
|
|
255
255
|
}
|
|
@@ -257,9 +257,9 @@ export const checkoutCommand = async (target, opts = {}) => {
|
|
|
257
257
|
/* swallow */
|
|
258
258
|
}
|
|
259
259
|
}
|
|
260
|
-
await
|
|
260
|
+
await initCgdb(repo.cgdbPath);
|
|
261
261
|
try {
|
|
262
|
-
const sink = await
|
|
262
|
+
const sink = await createCgdbRowSinkForCheckout(repo.cgdbPath);
|
|
263
263
|
const result = await materializeSnapshot({
|
|
264
264
|
cas: ctx.cas,
|
|
265
265
|
snapshotId: commit.snapshot,
|
|
@@ -269,14 +269,14 @@ export const checkoutCommand = async (target, opts = {}) => {
|
|
|
269
269
|
`${result.stats.edgeRowCount} edges\n`);
|
|
270
270
|
}
|
|
271
271
|
finally {
|
|
272
|
-
await
|
|
272
|
+
await closeCgdb();
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
275
|
};
|
|
276
276
|
// ──────────────────────────────────────────────────────────────────────
|
|
277
277
|
// codragraph materialize <target> --into <path>
|
|
278
278
|
// ──────────────────────────────────────────────────────────────────────
|
|
279
|
-
// Read-only inspection: rebuild a snapshot into a fresh sibling
|
|
279
|
+
// Read-only inspection: rebuild a snapshot into a fresh sibling cgdb
|
|
280
280
|
// without touching the live one. Useful for "let me query the graph as
|
|
281
281
|
// it was at commit X" without disturbing current work.
|
|
282
282
|
export const materializeCommand = async (target, opts) => {
|
|
@@ -295,9 +295,9 @@ export const materializeCommand = async (target, opts) => {
|
|
|
295
295
|
catch {
|
|
296
296
|
/* doesn't exist, good */
|
|
297
297
|
}
|
|
298
|
-
await
|
|
298
|
+
await initCgdb(into);
|
|
299
299
|
try {
|
|
300
|
-
const sink = await
|
|
300
|
+
const sink = await createCgdbRowSinkForCheckout(into);
|
|
301
301
|
const result = await materializeSnapshot({
|
|
302
302
|
cas: ctx.cas,
|
|
303
303
|
snapshotId: commit.snapshot,
|
|
@@ -310,7 +310,7 @@ export const materializeCommand = async (target, opts) => {
|
|
|
310
310
|
`edges: ${result.stats.edgeRowCount}\n`);
|
|
311
311
|
}
|
|
312
312
|
finally {
|
|
313
|
-
await
|
|
313
|
+
await closeCgdb();
|
|
314
314
|
}
|
|
315
315
|
};
|
|
316
316
|
// ──────────────────────────────────────────────────────────────────────
|
|
@@ -386,7 +386,7 @@ const locateSymbolHash = (manifest, symbolId, tableHint) => {
|
|
|
386
386
|
return null;
|
|
387
387
|
};
|
|
388
388
|
// ──────────────────────────────────────────────────────────────────────
|
|
389
|
-
//
|
|
389
|
+
// CgdbRowSink — used by checkout --materialize and `materialize` command.
|
|
390
390
|
// ──────────────────────────────────────────────────────────────────────
|
|
391
391
|
//
|
|
392
392
|
// Bulk-loads rows back into a fresh LadybugDB instance. Phase 4 keeps it
|
|
@@ -394,9 +394,9 @@ const locateSymbolHash = (manifest, symbolId, tableHint) => {
|
|
|
394
394
|
// `executeWithReusedStatement` helper. For typical repos (≤100k rows)
|
|
395
395
|
// this finishes in seconds; CSV-based bulk loading is a Phase 4.5
|
|
396
396
|
// optimization once we measure where the bottleneck actually is.
|
|
397
|
-
const
|
|
398
|
-
const { executeQuery } = await import('../core/
|
|
399
|
-
const { SCHEMA_QUERIES } = await import('../core/
|
|
397
|
+
const createCgdbRowSinkForCheckout = async (cgdbPath) => {
|
|
398
|
+
const { executeQuery } = await import('../core/cgdb/cgdb-adapter.js');
|
|
399
|
+
const { SCHEMA_QUERIES } = await import('../core/cgdb/schema.js');
|
|
400
400
|
// Recreate the schema; the path was just wiped, so this is a clean install.
|
|
401
401
|
for (const ddl of SCHEMA_QUERIES) {
|
|
402
402
|
try {
|
|
@@ -424,7 +424,7 @@ const createLbugRowSinkForCheckout = async (lbugPath) => {
|
|
|
424
424
|
endEdges: async () => { },
|
|
425
425
|
finalize: async () => { },
|
|
426
426
|
};
|
|
427
|
-
void
|
|
427
|
+
void cgdbPath;
|
|
428
428
|
return sink;
|
|
429
429
|
};
|
|
430
430
|
const insertNode = async (executeQuery, table, row) => {
|
|
@@ -468,7 +468,7 @@ const cypherLiteral = (v) => {
|
|
|
468
468
|
return JSON.stringify(v);
|
|
469
469
|
if (typeof v === 'number' || typeof v === 'boolean')
|
|
470
470
|
return String(v);
|
|
471
|
-
// Fall back to JSON for arrays / nested objects; the underlying
|
|
471
|
+
// Fall back to JSON for arrays / nested objects; the underlying cgdb
|
|
472
472
|
// schema is mostly scalar so this is rare.
|
|
473
473
|
return JSON.stringify(v);
|
|
474
474
|
};
|
package/dist/cli/index-repo.js
CHANGED
|
@@ -49,7 +49,7 @@ export const indexCommand = async (inputPathParts, options) => {
|
|
|
49
49
|
process.exitCode = 1;
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
|
-
const { storagePath,
|
|
52
|
+
const { storagePath, cgdbPath } = getStoragePaths(repoPath);
|
|
53
53
|
// ── Verify .codragraph/ exists ──────────────────────────────────────
|
|
54
54
|
try {
|
|
55
55
|
await fs.access(storagePath);
|
|
@@ -60,9 +60,9 @@ export const indexCommand = async (inputPathParts, options) => {
|
|
|
60
60
|
process.exitCode = 1;
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
|
-
// ── Verify
|
|
63
|
+
// ── Verify cgdb database exists ───────────────────────────────────
|
|
64
64
|
try {
|
|
65
|
-
await fs.access(
|
|
65
|
+
await fs.access(cgdbPath);
|
|
66
66
|
}
|
|
67
67
|
catch {
|
|
68
68
|
console.log(` .codragraph/ folder exists but contains no LadybugDB index.`);
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
|
85
|
-
const {
|
|
86
|
-
const {
|
|
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 (!
|
|
90
|
-
await
|
|
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
|
|
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>;
|