@codragraph/cli 1.6.3 → 2.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.
- package/README.md +50 -16
- package/dist/cli/ai-context.js +2 -2
- package/dist/cli/analyze.d.ts +22 -0
- package/dist/cli/analyze.js +111 -8
- package/dist/cli/compress-stats.d.ts +29 -0
- package/dist/cli/compress-stats.js +97 -0
- package/dist/cli/graphstore.d.ts +6 -2
- package/dist/cli/graphstore.js +24 -2
- package/dist/cli/index.js +17 -6
- package/dist/cli/profile-heap.d.ts +35 -0
- package/dist/cli/profile-heap.js +126 -0
- package/dist/cli/setup.d.ts +13 -0
- package/dist/cli/setup.js +75 -29
- package/dist/cli/skill-gen.d.ts +14 -2
- package/dist/cli/skill-gen.js +53 -20
- package/dist/cli/tool.js +4 -0
- package/dist/config/ignore-service.js +1 -1
- package/dist/core/embeddings/embedding-pipeline.js +24 -7
- package/dist/core/group/bridge-db.js +111 -24
- package/dist/core/group/extractors/grpc-patterns/proto.js +1 -12
- package/dist/core/ingestion/call-processor.js +2 -2
- package/dist/core/ingestion/cobol/cobol-preprocessor.js +1 -1
- package/dist/core/ingestion/cobol/jcl-parser.d.ts +1 -1
- package/dist/core/ingestion/cobol/jcl-parser.js +1 -1
- package/dist/core/ingestion/cobol-processor.d.ts +1 -1
- package/dist/core/ingestion/cobol-processor.js +1 -1
- package/dist/core/ingestion/heritage-extractors/generic.js +1 -1
- package/dist/core/ingestion/heritage-processor.js +1 -1
- package/dist/core/ingestion/import-processor.js +1 -1
- package/dist/core/ingestion/mro-processor.js +1 -1
- package/dist/core/ingestion/parsing-processor.js +1 -1
- package/dist/core/ingestion/type-extractors/c-cpp.js +1 -1
- package/dist/core/ingestion/type-extractors/python.js +1 -1
- package/dist/core/ingestion/type-extractors/shared.js +0 -3
- package/dist/core/lbug/content-read.d.ts +46 -0
- package/dist/core/lbug/content-read.js +64 -0
- package/dist/core/lbug/csv-generator.d.ts +2 -6
- package/dist/core/lbug/csv-generator.js +45 -12
- package/dist/core/lbug/lbug-adapter.d.ts +4 -1
- package/dist/core/lbug/lbug-adapter.js +157 -25
- package/dist/core/lbug/pool-adapter.js +51 -44
- package/dist/core/lbug/schema.d.ts +7 -7
- package/dist/core/lbug/schema.js +18 -0
- package/dist/core/run-analyze.d.ts +13 -0
- package/dist/core/run-analyze.js +91 -4
- package/dist/core/search/bm25-index.js +153 -12
- package/dist/core/wiki/generator.js +4 -4
- package/dist/mcp/local/local-backend.js +22 -5
- package/dist/mcp/resources.js +2 -3
- package/dist/server/api.js +4 -3
- package/dist/storage/repo-manager.d.ts +39 -0
- package/dist/storage/repo-manager.js +19 -0
- package/hooks/claude/codragraph-hook.cjs +108 -5
- package/hooks/claude/pre-tool-use.sh +6 -1
- package/package.json +4 -4
- package/scripts/build-tree-sitter-proto.cjs +15 -3
- package/scripts/patch-tree-sitter-swift.cjs +17 -4
- package/skills/codragraph-api-surface.md +110 -0
- package/skills/codragraph-cli.md +5 -5
- package/skills/codragraph-config-audit.md +146 -0
- package/skills/codragraph-cross-repo-impact.md +135 -0
- package/skills/codragraph-data-lineage.md +137 -0
- package/skills/codragraph-dead-code.md +119 -0
- package/skills/codragraph-debugging.md +1 -1
- package/skills/codragraph-exploring.md +1 -1
- package/skills/codragraph-gh-actions-debug.md +162 -0
- package/skills/codragraph-gh-issue-workflow.md +178 -0
- package/skills/codragraph-gh-pr-workflow.md +176 -0
- package/skills/codragraph-gh-release-workflow.md +187 -0
- package/skills/codragraph-git-bisect.md +176 -0
- package/skills/codragraph-git-force-push.md +147 -0
- package/skills/codragraph-git-history-rewrite.md +174 -0
- package/skills/codragraph-git-rebase-vs-merge.md +138 -0
- package/skills/codragraph-git-recovery.md +181 -0
- package/skills/codragraph-git-worktree.md +145 -0
- package/skills/codragraph-guide.md +1 -1
- package/skills/codragraph-impact-analysis.md +1 -1
- package/skills/codragraph-migration-tracking.md +130 -0
- package/skills/codragraph-notebook-context.md +136 -0
- package/skills/codragraph-observability-coverage.md +125 -0
- package/skills/codragraph-onboarding.md +129 -0
- package/skills/codragraph-perf-hotspots.md +132 -0
- package/skills/codragraph-pr-review.md +1 -1
- package/skills/codragraph-project-switcher.md +116 -0
- package/skills/codragraph-refactoring.md +1 -1
- package/skills/codragraph-security-audit.md +144 -0
- package/skills/codragraph-sql-tracing.md +122 -0
- package/skills/codragraph-supply-chain-audit.md +153 -0
- package/skills/codragraph-test-coverage.md +97 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import lbug from '@ladybugdb/core';
|
|
2
2
|
import { KnowledgeGraph } from '../graph/types.js';
|
|
3
3
|
import type { CachedEmbedding } from '../embeddings/types.js';
|
|
4
|
+
import type { ContentEncoding } from '@codragraph/graphstore';
|
|
4
5
|
/** Factory for creating WriteStreams — injectable for testing. */
|
|
5
6
|
export type WriteStreamFactory = (filePath: string) => import('fs').WriteStream;
|
|
6
7
|
/** Result of splitting the relationship CSV into per-label-pair files. */
|
|
@@ -51,7 +52,9 @@ export declare const initLbug: (dbPath: string) => Promise<{
|
|
|
51
52
|
*/
|
|
52
53
|
export declare const withLbugDb: <T>(dbPath: string, operation: () => Promise<T>) => Promise<T>;
|
|
53
54
|
export type LbugProgressCallback = (message: string) => void;
|
|
54
|
-
export declare const loadGraphToLbug: (graph: KnowledgeGraph, repoPath: string, storagePath: string, onProgress?: LbugProgressCallback
|
|
55
|
+
export declare const loadGraphToLbug: (graph: KnowledgeGraph, repoPath: string, storagePath: string, onProgress?: LbugProgressCallback, options?: {
|
|
56
|
+
compress?: ContentEncoding;
|
|
57
|
+
}) => Promise<{
|
|
55
58
|
success: boolean;
|
|
56
59
|
insertedRels: number;
|
|
57
60
|
skippedRels: number;
|
|
@@ -276,7 +276,7 @@ const doInitLbug = async (dbPath) => {
|
|
|
276
276
|
const parentDir = path.dirname(dbPath);
|
|
277
277
|
await fs.mkdir(parentDir, { recursive: true });
|
|
278
278
|
db = new lbug.Database(dbPath);
|
|
279
|
-
conn = new lbug.Connection(db);
|
|
279
|
+
conn = trackConnection(new lbug.Connection(db));
|
|
280
280
|
for (const schemaQuery of SCHEMA_QUERIES) {
|
|
281
281
|
try {
|
|
282
282
|
await conn.query(schemaQuery);
|
|
@@ -294,14 +294,14 @@ const doInitLbug = async (dbPath) => {
|
|
|
294
294
|
currentDbPath = dbPath;
|
|
295
295
|
return { db, conn };
|
|
296
296
|
};
|
|
297
|
-
export const loadGraphToLbug = async (graph, repoPath, storagePath, onProgress) => {
|
|
297
|
+
export const loadGraphToLbug = async (graph, repoPath, storagePath, onProgress, options) => {
|
|
298
298
|
if (!conn) {
|
|
299
299
|
throw new Error('LadybugDB not initialized. Call initLbug first.');
|
|
300
300
|
}
|
|
301
301
|
const log = onProgress || (() => { });
|
|
302
302
|
const csvDir = path.join(storagePath, 'csv');
|
|
303
303
|
log('Streaming CSVs to disk...');
|
|
304
|
-
const csvResult = await streamAllCSVsToDisk(graph, repoPath, csvDir);
|
|
304
|
+
const csvResult = await streamAllCSVsToDisk(graph, repoPath, csvDir, options?.compress);
|
|
305
305
|
const validTables = new Set(NODE_TABLES);
|
|
306
306
|
const getNodeLabel = (nodeId) => {
|
|
307
307
|
if (nodeId.startsWith('comm_'))
|
|
@@ -322,7 +322,7 @@ export const loadGraphToLbug = async (graph, repoPath, storagePath, onProgress)
|
|
|
322
322
|
try {
|
|
323
323
|
await conn.query(copyQuery);
|
|
324
324
|
}
|
|
325
|
-
catch (
|
|
325
|
+
catch (_err) {
|
|
326
326
|
try {
|
|
327
327
|
const retryQuery = copyQuery.replace('auto_detect=false)', 'auto_detect=false, IGNORE_ERRORS=true)');
|
|
328
328
|
await conn.query(retryQuery);
|
|
@@ -360,7 +360,7 @@ export const loadGraphToLbug = async (graph, repoPath, storagePath, onProgress)
|
|
|
360
360
|
try {
|
|
361
361
|
await conn.query(copyQuery);
|
|
362
362
|
}
|
|
363
|
-
catch (
|
|
363
|
+
catch (_err) {
|
|
364
364
|
try {
|
|
365
365
|
const retryQuery = copyQuery.replace('auto_detect=false)', 'auto_detect=false, IGNORE_ERRORS=true)');
|
|
366
366
|
await conn.query(retryQuery);
|
|
@@ -504,8 +504,12 @@ const TABLES_WITH_EXPORTED = new Set([
|
|
|
504
504
|
]);
|
|
505
505
|
const getCopyQuery = (table, filePath) => {
|
|
506
506
|
const t = escapeTableName(table);
|
|
507
|
+
// RFC 0001 Phase 2: every content-bearing table also lists
|
|
508
|
+
// `contentEncoding` immediately after `content` to match the schema +
|
|
509
|
+
// CSV layout. Tables without a content column (Folder, Community,
|
|
510
|
+
// Process, Route, Tool) are unchanged.
|
|
507
511
|
if (table === 'File') {
|
|
508
|
-
return `COPY ${t}(id, name, filePath, content) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
512
|
+
return `COPY ${t}(id, name, filePath, content, contentEncoding) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
509
513
|
}
|
|
510
514
|
if (table === 'Folder') {
|
|
511
515
|
return `COPY ${t}(id, name, filePath) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
@@ -517,7 +521,7 @@ const getCopyQuery = (table, filePath) => {
|
|
|
517
521
|
return `COPY ${t}(id, label, heuristicLabel, processType, stepCount, communities, entryPointId, terminalId) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
518
522
|
}
|
|
519
523
|
if (table === 'Section') {
|
|
520
|
-
return `COPY ${t}(id, name, filePath, startLine, endLine, level, content, description) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
524
|
+
return `COPY ${t}(id, name, filePath, startLine, endLine, level, content, contentEncoding, description) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
521
525
|
}
|
|
522
526
|
if (table === 'Route') {
|
|
523
527
|
return `COPY ${t}(id, name, filePath, responseKeys, errorKeys, middleware) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
@@ -526,14 +530,14 @@ const getCopyQuery = (table, filePath) => {
|
|
|
526
530
|
return `COPY ${t}(id, name, filePath, description) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
527
531
|
}
|
|
528
532
|
if (table === 'Method') {
|
|
529
|
-
return `COPY ${t}(id, name, filePath, startLine, endLine, isExported, content, description, parameterCount, returnType) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
533
|
+
return `COPY ${t}(id, name, filePath, startLine, endLine, isExported, content, contentEncoding, description, parameterCount, returnType) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
530
534
|
}
|
|
531
535
|
// TypeScript/JS code element tables have isExported; multi-language tables do not
|
|
532
536
|
if (TABLES_WITH_EXPORTED.has(table)) {
|
|
533
|
-
return `COPY ${t}(id, name, filePath, startLine, endLine, isExported, content, description) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
537
|
+
return `COPY ${t}(id, name, filePath, startLine, endLine, isExported, content, contentEncoding, description) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
534
538
|
}
|
|
535
539
|
// Multi-language tables (Struct, Impl, Trait, Macro, etc.)
|
|
536
|
-
return `COPY ${t}(id, name, filePath, startLine, endLine, content, description) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
540
|
+
return `COPY ${t}(id, name, filePath, startLine, endLine, content, contentEncoding, description) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
537
541
|
};
|
|
538
542
|
/**
|
|
539
543
|
* Insert a single node to LadybugDB
|
|
@@ -587,9 +591,10 @@ export const insertNodeToLbug = async (label, properties, dbPath) => {
|
|
|
587
591
|
// Use per-query connection if dbPath provided (avoids lock conflicts)
|
|
588
592
|
if (targetDbPath) {
|
|
589
593
|
const tempDb = new lbug.Database(targetDbPath);
|
|
590
|
-
const tempConn = new lbug.Connection(tempDb);
|
|
594
|
+
const tempConn = trackConnection(new lbug.Connection(tempDb));
|
|
591
595
|
try {
|
|
592
|
-
await tempConn.query(query);
|
|
596
|
+
const qr = await tempConn.query(query);
|
|
597
|
+
await closeQueryResult(qr);
|
|
593
598
|
return true;
|
|
594
599
|
}
|
|
595
600
|
finally {
|
|
@@ -635,7 +640,7 @@ export const batchInsertNodesToLbug = async (nodes, dbPath) => {
|
|
|
635
640
|
};
|
|
636
641
|
// Open a single connection for all inserts
|
|
637
642
|
const tempDb = new lbug.Database(dbPath);
|
|
638
|
-
const tempConn = new lbug.Connection(tempDb);
|
|
643
|
+
const tempConn = trackConnection(new lbug.Connection(tempDb));
|
|
639
644
|
let inserted = 0;
|
|
640
645
|
let failed = 0;
|
|
641
646
|
try {
|
|
@@ -671,7 +676,7 @@ export const batchInsertNodesToLbug = async (nodes, dbPath) => {
|
|
|
671
676
|
await tempConn.query(query);
|
|
672
677
|
inserted++;
|
|
673
678
|
}
|
|
674
|
-
catch (
|
|
679
|
+
catch (_e) {
|
|
675
680
|
// Don't console.error here - it corrupts MCP JSON-RPC on stderr
|
|
676
681
|
failed++;
|
|
677
682
|
}
|
|
@@ -689,6 +694,83 @@ export const batchInsertNodesToLbug = async (nodes, dbPath) => {
|
|
|
689
694
|
}
|
|
690
695
|
return { inserted, failed };
|
|
691
696
|
};
|
|
697
|
+
/**
|
|
698
|
+
* Track every live QueryResult / PreparedStatement returned by the
|
|
699
|
+
* connection, and force-close them in `closeLbug()` BEFORE `conn.close()`
|
|
700
|
+
* runs.
|
|
701
|
+
*
|
|
702
|
+
* Why this exists: per upstream Kuzu issue #5316 the close-order is
|
|
703
|
+
* QueryResult & PreparedStatement → Connection → Database
|
|
704
|
+
* Leaking any of these to GC means V8 finalizes the native handles AFTER
|
|
705
|
+
* `db.close()` has run, which corrupts memory and segfaults the process
|
|
706
|
+
* at exit (Windows: 0xC0000005, Linux: SIGSEGV). Kuzu was archived
|
|
707
|
+
* 2025-10-10 and LadybugDB inherits the same C++ core, so the
|
|
708
|
+
* close-discipline is on us — neither upstream is going to ship a fix.
|
|
709
|
+
*
|
|
710
|
+
* Per-call-site close (the `try/finally { closeQueryResult }` blocks
|
|
711
|
+
* below) handles the happy path. The tracking Set is a backstop for any
|
|
712
|
+
* call site that forgets, AND for the fire-and-forget DDL / COPY /
|
|
713
|
+
* extension-load queries that drop the QueryResult on the floor.
|
|
714
|
+
*/
|
|
715
|
+
const liveLbugHandles = new Set();
|
|
716
|
+
const closeQueryResult = async (qr) => {
|
|
717
|
+
if (!qr)
|
|
718
|
+
return;
|
|
719
|
+
const candidates = Array.isArray(qr) ? qr : [qr];
|
|
720
|
+
for (const r of candidates) {
|
|
721
|
+
liveLbugHandles.delete(r);
|
|
722
|
+
try {
|
|
723
|
+
const close = r?.close;
|
|
724
|
+
if (typeof close === 'function')
|
|
725
|
+
await Promise.resolve(close.call(r));
|
|
726
|
+
}
|
|
727
|
+
catch {
|
|
728
|
+
/* best-effort */
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
const closeStmt = async (stmt) => {
|
|
733
|
+
if (!stmt)
|
|
734
|
+
return;
|
|
735
|
+
liveLbugHandles.delete(stmt);
|
|
736
|
+
try {
|
|
737
|
+
const close = stmt?.close;
|
|
738
|
+
if (typeof close === 'function')
|
|
739
|
+
await Promise.resolve(close.call(stmt));
|
|
740
|
+
}
|
|
741
|
+
catch {
|
|
742
|
+
/* best-effort */
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
/**
|
|
746
|
+
* Wrap `conn.query` and `conn.execute` to register every returned
|
|
747
|
+
* QueryResult in the live-handle tracker. PreparedStatements from
|
|
748
|
+
* `conn.prepare` are tracked the same way. Idempotent — safe to call
|
|
749
|
+
* twice on the same Connection.
|
|
750
|
+
*/
|
|
751
|
+
const trackConnection = (rawConn) => {
|
|
752
|
+
const c = rawConn;
|
|
753
|
+
if (c.__lbugTracked)
|
|
754
|
+
return rawConn;
|
|
755
|
+
c.__lbugTracked = true;
|
|
756
|
+
const wrap = (orig) => async function (...args) {
|
|
757
|
+
const qr = await orig.apply(this, args);
|
|
758
|
+
if (qr && typeof qr === 'object') {
|
|
759
|
+
if (Array.isArray(qr))
|
|
760
|
+
qr.forEach((r) => r && liveLbugHandles.add(r));
|
|
761
|
+
else
|
|
762
|
+
liveLbugHandles.add(qr);
|
|
763
|
+
}
|
|
764
|
+
return qr;
|
|
765
|
+
};
|
|
766
|
+
if (typeof c.query === 'function')
|
|
767
|
+
c.query = wrap(c.query);
|
|
768
|
+
if (typeof c.execute === 'function')
|
|
769
|
+
c.execute = wrap(c.execute);
|
|
770
|
+
if (typeof c.prepare === 'function')
|
|
771
|
+
c.prepare = wrap(c.prepare);
|
|
772
|
+
return rawConn;
|
|
773
|
+
};
|
|
692
774
|
export const executeQuery = async (cypher) => {
|
|
693
775
|
if (!conn) {
|
|
694
776
|
throw new Error('LadybugDB not initialized. Call initLbug first.');
|
|
@@ -697,8 +779,12 @@ export const executeQuery = async (cypher) => {
|
|
|
697
779
|
// LadybugDB uses getAll() instead of hasNext()/getNext()
|
|
698
780
|
// Query returns QueryResult for single queries, QueryResult[] for multi-statement
|
|
699
781
|
const result = Array.isArray(queryResult) ? queryResult[0] : queryResult;
|
|
700
|
-
|
|
701
|
-
|
|
782
|
+
try {
|
|
783
|
+
return await result.getAll();
|
|
784
|
+
}
|
|
785
|
+
finally {
|
|
786
|
+
await closeQueryResult(queryResult);
|
|
787
|
+
}
|
|
702
788
|
};
|
|
703
789
|
export const streamQuery = async (cypher, onRow) => {
|
|
704
790
|
if (!conn) {
|
|
@@ -735,11 +821,18 @@ export const executePrepared = async (cypher, params) => {
|
|
|
735
821
|
const stmt = await conn.prepare(cypher);
|
|
736
822
|
if (!stmt.isSuccess()) {
|
|
737
823
|
const errMsg = await stmt.getErrorMessage();
|
|
824
|
+
await closeStmt(stmt);
|
|
738
825
|
throw new Error(`Prepare failed: ${errMsg}`);
|
|
739
826
|
}
|
|
740
827
|
const queryResult = await conn.execute(stmt, params);
|
|
741
828
|
const result = Array.isArray(queryResult) ? queryResult[0] : queryResult;
|
|
742
|
-
|
|
829
|
+
try {
|
|
830
|
+
return await result.getAll();
|
|
831
|
+
}
|
|
832
|
+
finally {
|
|
833
|
+
await closeQueryResult(queryResult);
|
|
834
|
+
await closeStmt(stmt);
|
|
835
|
+
}
|
|
743
836
|
};
|
|
744
837
|
export const executeWithReusedStatement = async (cypher, paramsList) => {
|
|
745
838
|
if (!conn) {
|
|
@@ -753,18 +846,27 @@ export const executeWithReusedStatement = async (cypher, paramsList) => {
|
|
|
753
846
|
const stmt = await conn.prepare(cypher);
|
|
754
847
|
if (!stmt.isSuccess()) {
|
|
755
848
|
const errMsg = await stmt.getErrorMessage();
|
|
849
|
+
await closeStmt(stmt);
|
|
756
850
|
throw new Error(`Prepare failed: ${errMsg}`);
|
|
757
851
|
}
|
|
758
852
|
try {
|
|
759
853
|
for (const params of subBatch) {
|
|
760
|
-
|
|
854
|
+
// `conn.execute` returns a QueryResult — close it as soon as
|
|
855
|
+
// we don't need its rows. Old code dropped the reference to GC,
|
|
856
|
+
// which is what segfaulted the process at exit on Windows
|
|
857
|
+
// (Kuzu issue #5316: QueryResult & PreparedStatement → Connection
|
|
858
|
+
// → Database close-order is required for native-binding safety).
|
|
859
|
+
const qr = await conn.execute(stmt, params);
|
|
860
|
+
await closeQueryResult(qr);
|
|
761
861
|
}
|
|
762
862
|
}
|
|
763
863
|
catch (e) {
|
|
764
864
|
// Log the error and continue with next batch
|
|
765
865
|
console.warn('Batch execution error:', e);
|
|
766
866
|
}
|
|
767
|
-
|
|
867
|
+
finally {
|
|
868
|
+
await closeStmt(stmt);
|
|
869
|
+
}
|
|
768
870
|
}
|
|
769
871
|
};
|
|
770
872
|
export const getLbugStats = async () => {
|
|
@@ -772,8 +874,9 @@ export const getLbugStats = async () => {
|
|
|
772
874
|
return { nodes: 0, edges: 0 };
|
|
773
875
|
let totalNodes = 0;
|
|
774
876
|
for (const tableName of NODE_TABLES) {
|
|
877
|
+
let queryResult;
|
|
775
878
|
try {
|
|
776
|
-
|
|
879
|
+
queryResult = await conn.query(`MATCH (n:${escapeTableName(tableName)}) RETURN count(n) AS cnt`);
|
|
777
880
|
const nodeResult = Array.isArray(queryResult) ? queryResult[0] : queryResult;
|
|
778
881
|
const nodeRows = await nodeResult.getAll();
|
|
779
882
|
if (nodeRows.length > 0) {
|
|
@@ -783,11 +886,15 @@ export const getLbugStats = async () => {
|
|
|
783
886
|
catch {
|
|
784
887
|
// ignore
|
|
785
888
|
}
|
|
889
|
+
finally {
|
|
890
|
+
await closeQueryResult(queryResult);
|
|
891
|
+
}
|
|
786
892
|
}
|
|
787
893
|
let totalEdges = 0;
|
|
894
|
+
let edgeQueryResult;
|
|
788
895
|
try {
|
|
789
|
-
|
|
790
|
-
const edgeResult = Array.isArray(
|
|
896
|
+
edgeQueryResult = await conn.query(`MATCH ()-[r:${REL_TABLE_NAME}]->() RETURN count(r) AS cnt`);
|
|
897
|
+
const edgeResult = Array.isArray(edgeQueryResult) ? edgeQueryResult[0] : edgeQueryResult;
|
|
791
898
|
const edgeRows = await edgeResult.getAll();
|
|
792
899
|
if (edgeRows.length > 0) {
|
|
793
900
|
totalEdges = Number(edgeRows[0]?.cnt ?? edgeRows[0]?.[0] ?? 0);
|
|
@@ -796,6 +903,9 @@ export const getLbugStats = async () => {
|
|
|
796
903
|
catch {
|
|
797
904
|
// ignore
|
|
798
905
|
}
|
|
906
|
+
finally {
|
|
907
|
+
await closeQueryResult(edgeQueryResult);
|
|
908
|
+
}
|
|
799
909
|
return { nodes: totalNodes, edges: totalEdges };
|
|
800
910
|
};
|
|
801
911
|
/**
|
|
@@ -929,6 +1039,24 @@ export const fetchExistingEmbeddingHashes = async (execQuery) => {
|
|
|
929
1039
|
}
|
|
930
1040
|
};
|
|
931
1041
|
export const closeLbug = async () => {
|
|
1042
|
+
// Drain every live QueryResult / PreparedStatement BEFORE closing the
|
|
1043
|
+
// Connection or the Database. Required by upstream Kuzu (#5316) — the
|
|
1044
|
+
// close-order is `QueryResult/PreparedStatement → Connection → Database`,
|
|
1045
|
+
// and any outstanding handle held when `db.close()` runs corrupts memory
|
|
1046
|
+
// and crashes the process at exit (Windows: 0xC0000005, POSIX: SIGSEGV).
|
|
1047
|
+
// Snapshot the Set so concurrent close() calls don't deadlock the iteration.
|
|
1048
|
+
const handles = Array.from(liveLbugHandles);
|
|
1049
|
+
liveLbugHandles.clear();
|
|
1050
|
+
for (const h of handles) {
|
|
1051
|
+
try {
|
|
1052
|
+
const close = h?.close;
|
|
1053
|
+
if (typeof close === 'function')
|
|
1054
|
+
await Promise.resolve(close.call(h));
|
|
1055
|
+
}
|
|
1056
|
+
catch {
|
|
1057
|
+
/* best-effort */
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
932
1060
|
if (conn) {
|
|
933
1061
|
try {
|
|
934
1062
|
await conn.close();
|
|
@@ -963,7 +1091,7 @@ export const deleteNodesForFile = async (filePath, dbPath) => {
|
|
|
963
1091
|
let targetConn = conn;
|
|
964
1092
|
if (usePerQuery) {
|
|
965
1093
|
tempDb = new lbug.Database(dbPath);
|
|
966
|
-
tempConn = new lbug.Connection(tempDb);
|
|
1094
|
+
tempConn = trackConnection(new lbug.Connection(tempDb));
|
|
967
1095
|
targetConn = tempConn;
|
|
968
1096
|
}
|
|
969
1097
|
else if (!conn) {
|
|
@@ -991,7 +1119,7 @@ export const deleteNodesForFile = async (filePath, dbPath) => {
|
|
|
991
1119
|
deletedNodes += count;
|
|
992
1120
|
}
|
|
993
1121
|
}
|
|
994
|
-
catch (
|
|
1122
|
+
catch (_e) {
|
|
995
1123
|
// Some tables may not support this query, skip
|
|
996
1124
|
}
|
|
997
1125
|
}
|
|
@@ -1148,8 +1276,9 @@ export const queryFTS = async (tableName, indexName, query, limit = 20, conjunct
|
|
|
1148
1276
|
ORDER BY score DESC
|
|
1149
1277
|
LIMIT ${limit}
|
|
1150
1278
|
`;
|
|
1279
|
+
let queryResult;
|
|
1151
1280
|
try {
|
|
1152
|
-
|
|
1281
|
+
queryResult = await conn.query(cypher);
|
|
1153
1282
|
const result = Array.isArray(queryResult) ? queryResult[0] : queryResult;
|
|
1154
1283
|
const rows = await result.getAll();
|
|
1155
1284
|
return rows.map((row) => {
|
|
@@ -1171,6 +1300,9 @@ export const queryFTS = async (tableName, indexName, query, limit = 20, conjunct
|
|
|
1171
1300
|
}
|
|
1172
1301
|
throw e;
|
|
1173
1302
|
}
|
|
1303
|
+
finally {
|
|
1304
|
+
await closeQueryResult(queryResult);
|
|
1305
|
+
}
|
|
1174
1306
|
};
|
|
1175
1307
|
/**
|
|
1176
1308
|
* Drop an FTS index
|
|
@@ -280,29 +280,18 @@ async function doInitLbug(repoId, dbPath) {
|
|
|
280
280
|
finally {
|
|
281
281
|
preWarmActive = false;
|
|
282
282
|
}
|
|
283
|
-
// Load FTS
|
|
284
|
-
//
|
|
285
|
-
//
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
// Load VECTOR extension once per shared Database for semantic search support.
|
|
296
|
-
if (!shared.vectorLoaded) {
|
|
297
|
-
try {
|
|
298
|
-
await available[0].query('INSTALL VECTOR');
|
|
299
|
-
await available[0].query('LOAD EXTENSION VECTOR');
|
|
300
|
-
shared.vectorLoaded = true;
|
|
301
|
-
}
|
|
302
|
-
catch {
|
|
303
|
-
// VECTOR extension may not be available
|
|
304
|
-
}
|
|
305
|
-
}
|
|
283
|
+
// Load FTS + VECTOR extensions on EVERY connection in the pool.
|
|
284
|
+
//
|
|
285
|
+
// CRITICAL: LadybugDB's extension state is per-connection on macOS (and
|
|
286
|
+
// possibly other platforms) — loading on `available[0]` does NOT propagate
|
|
287
|
+
// to the other connections. Since checkout pops from the end of the array,
|
|
288
|
+
// queries would otherwise hit unloaded connections and `QUERY_FTS_INDEX`
|
|
289
|
+
// would silently return 0 rows (catch in queryFTSViaExecutor swallows the
|
|
290
|
+
// "extension not loaded" error). That broke every search on macOS.
|
|
291
|
+
//
|
|
292
|
+
// Load on all connections concurrently, but BEFORE the pool is registered
|
|
293
|
+
// so no checkout can race the load.
|
|
294
|
+
await loadExtensionsOnConnections(available, shared);
|
|
306
295
|
// Register pool entry only after all connections are pre-warmed and FTS is
|
|
307
296
|
// loaded. Concurrent executeQuery calls see either "not initialized"
|
|
308
297
|
// (and throw cleanly) or a fully ready pool — never a half-built one.
|
|
@@ -317,6 +306,42 @@ async function doInitLbug(repoId, dbPath) {
|
|
|
317
306
|
});
|
|
318
307
|
ensureIdleTimer();
|
|
319
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* Load FTS + VECTOR extensions on every connection in the pool.
|
|
311
|
+
* Per-connection load is required because LadybugDB's extension state is
|
|
312
|
+
* not always shared across connections of the same Database (observed on
|
|
313
|
+
* macOS native bindings — silent FTS failures otherwise).
|
|
314
|
+
*/
|
|
315
|
+
async function loadExtensionsOnConnections(conns, shared) {
|
|
316
|
+
// FTS: every connection needs `LOAD EXTENSION fts` independently.
|
|
317
|
+
await Promise.all(conns.map(async (c) => {
|
|
318
|
+
try {
|
|
319
|
+
await c.query('LOAD EXTENSION fts');
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
// already-loaded / not-installed — FTS queries fail gracefully if missing
|
|
323
|
+
}
|
|
324
|
+
}));
|
|
325
|
+
shared.ftsLoaded = true;
|
|
326
|
+
// VECTOR: install once on the Database (idempotent), then LOAD on every
|
|
327
|
+
// connection. INSTALL is a no-op after the first call but we run it on
|
|
328
|
+
// conn[0] to guarantee the package is present before fanning out LOADs.
|
|
329
|
+
try {
|
|
330
|
+
await conns[0].query('INSTALL VECTOR');
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
/* not available — semantic search will be a no-op */
|
|
334
|
+
}
|
|
335
|
+
await Promise.all(conns.map(async (c) => {
|
|
336
|
+
try {
|
|
337
|
+
await c.query('LOAD EXTENSION VECTOR');
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
/* not available — semantic search will be a no-op */
|
|
341
|
+
}
|
|
342
|
+
}));
|
|
343
|
+
shared.vectorLoaded = true;
|
|
344
|
+
}
|
|
320
345
|
/**
|
|
321
346
|
* Initialize a pool entry from a pre-existing Database object.
|
|
322
347
|
*
|
|
@@ -354,27 +379,9 @@ export async function initLbugWithDb(repoId, existingDb, dbPath) {
|
|
|
354
379
|
finally {
|
|
355
380
|
preWarmActive = false;
|
|
356
381
|
}
|
|
357
|
-
// Load FTS
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
await available[0].query('LOAD EXTENSION fts');
|
|
361
|
-
shared.ftsLoaded = true;
|
|
362
|
-
}
|
|
363
|
-
catch {
|
|
364
|
-
// Extension may already be loaded or not installed
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
// Load VECTOR extension for semantic search support
|
|
368
|
-
if (!shared.vectorLoaded) {
|
|
369
|
-
try {
|
|
370
|
-
await available[0].query('INSTALL VECTOR');
|
|
371
|
-
await available[0].query('LOAD EXTENSION VECTOR');
|
|
372
|
-
shared.vectorLoaded = true;
|
|
373
|
-
}
|
|
374
|
-
catch {
|
|
375
|
-
// VECTOR extension may not be available
|
|
376
|
-
}
|
|
377
|
-
}
|
|
382
|
+
// Load FTS + VECTOR on every connection (see loadExtensionsOnConnections
|
|
383
|
+
// for why per-connection load is required on macOS native bindings).
|
|
384
|
+
await loadExtensionsOnConnections(available, shared);
|
|
378
385
|
pool.set(repoId, {
|
|
379
386
|
db: existingDb,
|
|
380
387
|
available,
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
import { NODE_TABLES, REL_TABLE_NAME, REL_TYPES, EMBEDDING_TABLE_NAME } from '../../_shared/index.js';
|
|
12
12
|
export { NODE_TABLES, REL_TABLE_NAME, REL_TYPES, EMBEDDING_TABLE_NAME };
|
|
13
13
|
export type { NodeTableName, RelType } from '../../_shared/index.js';
|
|
14
|
-
export declare const FILE_SCHEMA = "\nCREATE NODE TABLE File (\n id STRING,\n name STRING,\n filePath STRING,\n content STRING,\n PRIMARY KEY (id)\n)";
|
|
14
|
+
export declare const FILE_SCHEMA = "\nCREATE NODE TABLE File (\n id STRING,\n name STRING,\n filePath STRING,\n content STRING,\n contentEncoding STRING DEFAULT 'none',\n PRIMARY KEY (id)\n)";
|
|
15
15
|
export declare const FOLDER_SCHEMA = "\nCREATE NODE TABLE Folder (\n id STRING,\n name STRING,\n filePath STRING,\n PRIMARY KEY (id)\n)";
|
|
16
|
-
export declare const FUNCTION_SCHEMA = "\nCREATE NODE TABLE Function (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n isExported BOOLEAN,\n content STRING,\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
17
|
-
export declare const CLASS_SCHEMA = "\nCREATE NODE TABLE Class (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n isExported BOOLEAN,\n content STRING,\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
18
|
-
export declare const INTERFACE_SCHEMA = "\nCREATE NODE TABLE Interface (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n isExported BOOLEAN,\n content STRING,\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
19
|
-
export declare const METHOD_SCHEMA = "\nCREATE NODE TABLE Method (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n isExported BOOLEAN,\n content STRING,\n description STRING,\n parameterCount INT32,\n returnType STRING,\n PRIMARY KEY (id)\n)";
|
|
20
|
-
export declare const CODE_ELEMENT_SCHEMA = "\nCREATE NODE TABLE CodeElement (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n isExported BOOLEAN,\n content STRING,\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
16
|
+
export declare const FUNCTION_SCHEMA = "\nCREATE NODE TABLE Function (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n isExported BOOLEAN,\n content STRING,\n contentEncoding STRING DEFAULT 'none',\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
17
|
+
export declare const CLASS_SCHEMA = "\nCREATE NODE TABLE Class (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n isExported BOOLEAN,\n content STRING,\n contentEncoding STRING DEFAULT 'none',\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
18
|
+
export declare const INTERFACE_SCHEMA = "\nCREATE NODE TABLE Interface (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n isExported BOOLEAN,\n content STRING,\n contentEncoding STRING DEFAULT 'none',\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
19
|
+
export declare const METHOD_SCHEMA = "\nCREATE NODE TABLE Method (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n isExported BOOLEAN,\n content STRING,\n contentEncoding STRING DEFAULT 'none',\n description STRING,\n parameterCount INT32,\n returnType STRING,\n PRIMARY KEY (id)\n)";
|
|
20
|
+
export declare const CODE_ELEMENT_SCHEMA = "\nCREATE NODE TABLE CodeElement (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n isExported BOOLEAN,\n content STRING,\n contentEncoding STRING DEFAULT 'none',\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
21
21
|
export declare const COMMUNITY_SCHEMA = "\nCREATE NODE TABLE Community (\n id STRING,\n label STRING,\n heuristicLabel STRING,\n keywords STRING[],\n description STRING,\n enrichedBy STRING,\n cohesion DOUBLE,\n symbolCount INT32,\n PRIMARY KEY (id)\n)";
|
|
22
22
|
export declare const PROCESS_SCHEMA = "\nCREATE NODE TABLE Process (\n id STRING,\n label STRING,\n heuristicLabel STRING,\n processType STRING,\n stepCount INT32,\n communities STRING[],\n entryPointId STRING,\n terminalId STRING,\n PRIMARY KEY (id)\n)";
|
|
23
23
|
export declare const STRUCT_SCHEMA: string;
|
|
@@ -41,7 +41,7 @@ export declare const TEMPLATE_SCHEMA: string;
|
|
|
41
41
|
export declare const MODULE_SCHEMA: string;
|
|
42
42
|
export declare const ROUTE_SCHEMA = "\nCREATE NODE TABLE Route (\n id STRING,\n name STRING,\n filePath STRING,\n responseKeys STRING[],\n errorKeys STRING[],\n middleware STRING[],\n PRIMARY KEY (id)\n)";
|
|
43
43
|
export declare const TOOL_SCHEMA = "\nCREATE NODE TABLE Tool (\n id STRING,\n name STRING,\n filePath STRING,\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
44
|
-
export declare const SECTION_SCHEMA = "\nCREATE NODE TABLE Section (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n level INT64,\n content STRING,\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
44
|
+
export declare const SECTION_SCHEMA = "\nCREATE NODE TABLE Section (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n level INT64,\n content STRING,\n contentEncoding STRING DEFAULT 'none',\n description STRING,\n PRIMARY KEY (id)\n)";
|
|
45
45
|
export declare const RELATION_SCHEMA = "\nCREATE REL TABLE CodeRelation (\n FROM File TO File,\n FROM File TO Folder,\n FROM File TO Function,\n FROM File TO Class,\n FROM File TO Interface,\n FROM File TO Method,\n FROM File TO CodeElement,\n FROM File TO `Struct`,\n FROM File TO `Enum`,\n FROM File TO `Macro`,\n FROM File TO `Typedef`,\n FROM File TO `Union`,\n FROM File TO `Namespace`,\n FROM File TO `Trait`,\n FROM File TO `Impl`,\n FROM File TO `TypeAlias`,\n FROM File TO `Const`,\n FROM File TO `Static`,\n FROM File TO `Variable`,\n FROM File TO `Property`,\n FROM File TO `Record`,\n FROM File TO `Delegate`,\n FROM File TO `Annotation`,\n FROM File TO `Constructor`,\n FROM File TO `Template`,\n FROM File TO `Module`,\n FROM File TO Section,\n FROM Folder TO Folder,\n FROM Folder TO File,\n FROM Function TO Function,\n FROM Function TO Method,\n FROM Function TO Class,\n FROM Function TO Community,\n FROM Function TO `Macro`,\n FROM Function TO `Struct`,\n FROM Function TO `Template`,\n FROM Function TO `Enum`,\n FROM Function TO `Namespace`,\n FROM Function TO `TypeAlias`,\n FROM Function TO `Module`,\n FROM Function TO `Impl`,\n FROM Function TO Interface,\n FROM Function TO `Constructor`,\n FROM Function TO `Const`,\n FROM Function TO `Typedef`,\n FROM Function TO `Union`,\n FROM Function TO `Property`,\n FROM Function TO CodeElement,\n FROM Class TO Method,\n FROM Class TO Function,\n FROM Class TO Class,\n FROM Class TO Interface,\n FROM Class TO Community,\n FROM Class TO `Template`,\n FROM Class TO `TypeAlias`,\n FROM Class TO `Struct`,\n FROM Class TO `Enum`,\n FROM Class TO `Annotation`,\n FROM Class TO `Constructor`,\n FROM Class TO `Trait`,\n FROM Class TO `Macro`,\n FROM Class TO `Impl`,\n FROM Class TO `Union`,\n FROM Class TO `Namespace`,\n FROM Class TO `Typedef`,\n FROM Class TO `Property`,\n FROM Method TO Function,\n FROM Method TO Method,\n FROM Method TO Class,\n FROM Method TO Community,\n FROM Method TO `Template`,\n FROM Method TO `Struct`,\n FROM Method TO `TypeAlias`,\n FROM Method TO `Enum`,\n FROM Method TO `Macro`,\n FROM Method TO `Namespace`,\n FROM Method TO `Module`,\n FROM Method TO `Impl`,\n FROM Method TO Interface,\n FROM Method TO `Constructor`,\n FROM Method TO `Property`,\n FROM Method TO CodeElement,\n FROM `Template` TO `Template`,\n FROM `Template` TO Function,\n FROM `Template` TO Method,\n FROM `Template` TO Class,\n FROM `Template` TO `Struct`,\n FROM `Template` TO `TypeAlias`,\n FROM `Template` TO `Enum`,\n FROM `Template` TO `Macro`,\n FROM `Template` TO Interface,\n FROM `Template` TO `Constructor`,\n FROM `Module` TO `Module`,\n FROM Section TO Section,\n FROM Section TO File,\n FROM File TO Route,\n FROM Function TO Route,\n FROM Method TO Route,\n FROM File TO Tool,\n FROM Function TO Tool,\n FROM Method TO Tool,\n FROM CodeElement TO Community,\n FROM Interface TO Community,\n FROM Interface TO Function,\n FROM Interface TO Method,\n FROM Interface TO Class,\n FROM Interface TO Interface,\n FROM Interface TO `TypeAlias`,\n FROM Interface TO `Struct`,\n FROM Interface TO `Constructor`,\n FROM Interface TO `Property`,\n FROM `Struct` TO Community,\n FROM `Struct` TO `Trait`,\n FROM `Struct` TO `Struct`,\n FROM `Struct` TO Class,\n FROM `Struct` TO `Enum`,\n FROM `Struct` TO Function,\n FROM `Struct` TO Method,\n FROM `Struct` TO Interface,\n FROM `Struct` TO `Constructor`,\n FROM `Struct` TO `Property`,\n FROM `Enum` TO `Enum`,\n FROM `Enum` TO Community,\n FROM `Enum` TO Class,\n FROM `Enum` TO Interface,\n FROM `Macro` TO Community,\n FROM `Macro` TO Function,\n FROM `Macro` TO Method,\n FROM `Module` TO Function,\n FROM `Module` TO Method,\n FROM `Typedef` TO Community,\n FROM `Union` TO Community,\n FROM `Namespace` TO Community,\n FROM `Namespace` TO `Struct`,\n FROM `Trait` TO Method,\n FROM `Trait` TO `Constructor`,\n FROM `Trait` TO `Property`,\n FROM `Trait` TO Community,\n FROM `Impl` TO Method,\n FROM `Impl` TO `Constructor`,\n FROM `Impl` TO `Property`,\n FROM `Impl` TO Community,\n FROM `Impl` TO `Trait`,\n FROM `Impl` TO `Struct`,\n FROM `Impl` TO `Impl`,\n FROM `TypeAlias` TO Community,\n FROM `TypeAlias` TO `Trait`,\n FROM `TypeAlias` TO Class,\n FROM `Const` TO Community,\n FROM `Static` TO Community,\n FROM `Variable` TO Community,\n FROM `Property` TO Community,\n FROM `Record` TO Method,\n FROM `Record` TO `Constructor`,\n FROM `Record` TO `Property`,\n FROM `Record` TO Community,\n FROM `Delegate` TO Community,\n FROM `Annotation` TO Community,\n FROM `Constructor` TO Community,\n FROM `Constructor` TO Interface,\n FROM `Constructor` TO Class,\n FROM `Constructor` TO Method,\n FROM `Constructor` TO Function,\n FROM `Constructor` TO `Constructor`,\n FROM `Constructor` TO `Struct`,\n FROM `Constructor` TO `Macro`,\n FROM `Constructor` TO `Template`,\n FROM `Constructor` TO `TypeAlias`,\n FROM `Constructor` TO `Enum`,\n FROM `Constructor` TO `Annotation`,\n FROM `Constructor` TO `Impl`,\n FROM `Constructor` TO `Namespace`,\n FROM `Constructor` TO `Module`,\n FROM `Constructor` TO `Property`,\n FROM `Constructor` TO `Typedef`,\n FROM `Template` TO Community,\n FROM `Module` TO Community,\n FROM Function TO Process,\n FROM Method TO Process,\n FROM Class TO Process,\n FROM Interface TO Process,\n FROM `Struct` TO Process,\n FROM `Constructor` TO Process,\n FROM `Module` TO Process,\n FROM `Macro` TO Process,\n FROM `Impl` TO Process,\n FROM `Typedef` TO Process,\n FROM `TypeAlias` TO Process,\n FROM `Enum` TO Process,\n FROM `Union` TO Process,\n FROM `Namespace` TO Process,\n FROM `Trait` TO Process,\n FROM `Const` TO Process,\n FROM `Static` TO Process,\n FROM `Variable` TO Process,\n FROM `Property` TO Process,\n FROM `Record` TO Process,\n FROM `Delegate` TO Process,\n FROM `Annotation` TO Process,\n FROM `Template` TO Process,\n FROM CodeElement TO Process,\n FROM Route TO Process,\n FROM Tool TO Process,\n type STRING,\n confidence DOUBLE,\n reason STRING,\n step INT32\n)";
|
|
46
46
|
export declare const EMBEDDING_DIMS: number;
|
|
47
47
|
/** HNSW vector index name for the CodeEmbedding table. */
|
package/dist/core/lbug/schema.js
CHANGED
|
@@ -15,12 +15,23 @@ export { NODE_TABLES, REL_TABLE_NAME, REL_TYPES, EMBEDDING_TABLE_NAME };
|
|
|
15
15
|
// ============================================================================
|
|
16
16
|
// NODE TABLE SCHEMAS
|
|
17
17
|
// ============================================================================
|
|
18
|
+
// RFC 0001 Phase 2 — every node table that has `content STRING` also carries
|
|
19
|
+
// `contentEncoding STRING DEFAULT 'none'`. Default keeps existing
|
|
20
|
+
// uncompressed reads working (an empty/missing tag means "no decode
|
|
21
|
+
// needed"); writers opt into compression by setting it to 'brotli' or
|
|
22
|
+
// 'zstd' alongside the encoded bytes.
|
|
23
|
+
//
|
|
24
|
+
// Adding the column to every relevant table at once keeps the read path
|
|
25
|
+
// simple — every `RETURN n.content` site can also `RETURN n.contentEncoding`
|
|
26
|
+
// without per-table feature detection. Tables WITHOUT a content column
|
|
27
|
+
// (Folder, Community, Process, Route, Tool) are intentionally not touched.
|
|
18
28
|
export const FILE_SCHEMA = `
|
|
19
29
|
CREATE NODE TABLE File (
|
|
20
30
|
id STRING,
|
|
21
31
|
name STRING,
|
|
22
32
|
filePath STRING,
|
|
23
33
|
content STRING,
|
|
34
|
+
contentEncoding STRING DEFAULT 'none',
|
|
24
35
|
PRIMARY KEY (id)
|
|
25
36
|
)`;
|
|
26
37
|
export const FOLDER_SCHEMA = `
|
|
@@ -39,6 +50,7 @@ CREATE NODE TABLE Function (
|
|
|
39
50
|
endLine INT64,
|
|
40
51
|
isExported BOOLEAN,
|
|
41
52
|
content STRING,
|
|
53
|
+
contentEncoding STRING DEFAULT 'none',
|
|
42
54
|
description STRING,
|
|
43
55
|
PRIMARY KEY (id)
|
|
44
56
|
)`;
|
|
@@ -51,6 +63,7 @@ CREATE NODE TABLE Class (
|
|
|
51
63
|
endLine INT64,
|
|
52
64
|
isExported BOOLEAN,
|
|
53
65
|
content STRING,
|
|
66
|
+
contentEncoding STRING DEFAULT 'none',
|
|
54
67
|
description STRING,
|
|
55
68
|
PRIMARY KEY (id)
|
|
56
69
|
)`;
|
|
@@ -63,6 +76,7 @@ CREATE NODE TABLE Interface (
|
|
|
63
76
|
endLine INT64,
|
|
64
77
|
isExported BOOLEAN,
|
|
65
78
|
content STRING,
|
|
79
|
+
contentEncoding STRING DEFAULT 'none',
|
|
66
80
|
description STRING,
|
|
67
81
|
PRIMARY KEY (id)
|
|
68
82
|
)`;
|
|
@@ -75,6 +89,7 @@ CREATE NODE TABLE Method (
|
|
|
75
89
|
endLine INT64,
|
|
76
90
|
isExported BOOLEAN,
|
|
77
91
|
content STRING,
|
|
92
|
+
contentEncoding STRING DEFAULT 'none',
|
|
78
93
|
description STRING,
|
|
79
94
|
parameterCount INT32,
|
|
80
95
|
returnType STRING,
|
|
@@ -89,6 +104,7 @@ CREATE NODE TABLE CodeElement (
|
|
|
89
104
|
endLine INT64,
|
|
90
105
|
isExported BOOLEAN,
|
|
91
106
|
content STRING,
|
|
107
|
+
contentEncoding STRING DEFAULT 'none',
|
|
92
108
|
description STRING,
|
|
93
109
|
PRIMARY KEY (id)
|
|
94
110
|
)`;
|
|
@@ -135,6 +151,7 @@ CREATE NODE TABLE \`${name}\` (
|
|
|
135
151
|
startLine INT64,
|
|
136
152
|
endLine INT64,
|
|
137
153
|
content STRING,
|
|
154
|
+
contentEncoding STRING DEFAULT 'none',
|
|
138
155
|
description STRING,
|
|
139
156
|
PRIMARY KEY (id)
|
|
140
157
|
)`;
|
|
@@ -187,6 +204,7 @@ CREATE NODE TABLE Section (
|
|
|
187
204
|
endLine INT64,
|
|
188
205
|
level INT64,
|
|
189
206
|
content STRING,
|
|
207
|
+
contentEncoding STRING DEFAULT 'none',
|
|
190
208
|
description STRING,
|
|
191
209
|
PRIMARY KEY (id)
|
|
192
210
|
)`;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* IMPORTANT: This module must NEVER call process.exit(). The caller (CLI
|
|
9
9
|
* wrapper or server worker) is responsible for process lifecycle.
|
|
10
10
|
*/
|
|
11
|
+
import type { ContentEncoding } from '@codragraph/graphstore';
|
|
11
12
|
export interface AnalyzeCallbacks {
|
|
12
13
|
onProgress: (phase: string, percent: number, message: string) => void;
|
|
13
14
|
onLog?: (message: string) => void;
|
|
@@ -41,6 +42,18 @@ export interface AnalyzeOptions {
|
|
|
41
42
|
* of a pipeline re-index.
|
|
42
43
|
*/
|
|
43
44
|
allowDuplicateName?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* RFC 0001 Phase 2 — opt into per-row content compression. `'none'`
|
|
47
|
+
* (or undefined) writes plain text and the schema-default tag, exactly
|
|
48
|
+
* as pre-Phase-2 indexes do. `'brotli'` and `'zstd'` route every
|
|
49
|
+
* content field through `encodeContent` before it hits the CSV; the
|
|
50
|
+
* read path decodes via the per-row `contentEncoding` tag.
|
|
51
|
+
*
|
|
52
|
+
* Choosing `'zstd'` requires Node ≥ 22.15 on the indexer (the runtime
|
|
53
|
+
* that wrote the rows). Readers on older Node will get a clear
|
|
54
|
+
* forward-compat error rather than silently bad content.
|
|
55
|
+
*/
|
|
56
|
+
compress?: ContentEncoding;
|
|
44
57
|
}
|
|
45
58
|
export interface AnalyzeResult {
|
|
46
59
|
repoName: string;
|