gitnexus 1.6.5-rc.2 → 1.6.5-rc.4
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 +1 -1
- package/dist/cli/augment.d.ts +1 -1
- package/dist/cli/augment.js +1 -1
- package/dist/core/augmentation/engine.d.ts +2 -2
- package/dist/core/augmentation/engine.js +2 -2
- package/dist/core/embeddings/ast-utils.js +2 -1
- package/dist/core/group/extractors/grpc-extractor.js +2 -1
- package/dist/core/group/extractors/http-route-extractor.js +2 -1
- package/dist/core/group/extractors/include-extractor.js +2 -1
- package/dist/core/group/extractors/thrift-extractor.js +2 -1
- package/dist/core/group/extractors/tree-sitter-scanner.js +2 -1
- package/dist/core/ingestion/call-processor.js +3 -2
- package/dist/core/ingestion/heritage-processor.js +3 -2
- package/dist/core/ingestion/import-processor.js +2 -1
- package/dist/core/ingestion/languages/csharp/captures.js +2 -1
- package/dist/core/ingestion/languages/csharp/namespace-siblings.js +3 -2
- package/dist/core/ingestion/languages/go/captures.js +2 -1
- package/dist/core/ingestion/languages/go/range-binding.js +2 -1
- package/dist/core/ingestion/languages/python/captures.js +2 -1
- package/dist/core/ingestion/languages/typescript/captures.js +2 -1
- package/dist/core/ingestion/parsing-processor.js +2 -1
- package/dist/core/ingestion/workers/parse-worker.js +2 -1
- package/dist/core/lbug/lbug-adapter.js +8 -0
- package/dist/core/lbug/pool-adapter.js +19 -2
- package/dist/core/tree-sitter/safe-parse.d.ts +6 -0
- package/dist/core/tree-sitter/safe-parse.js +32 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ To configure MCP for your editor, run `npx gitnexus setup` once — or set it up
|
|
|
33
33
|
| Editor | MCP | Skills | Hooks (auto-augment) | Support |
|
|
34
34
|
|--------|-----|--------|---------------------|---------|
|
|
35
35
|
| **Claude Code** | Yes | Yes | Yes (PreToolUse) | **Full** |
|
|
36
|
-
| **Cursor** | Yes | Yes |
|
|
36
|
+
| **Cursor** | Yes | Yes | Yes (postToolUse, [manual install](../gitnexus-cursor-integration/README.md#hook-install)) | **Full** |
|
|
37
37
|
| **Codex** | Yes | Yes | — | MCP + Skills |
|
|
38
38
|
| **Windsurf** | Yes | — | — | MCP |
|
|
39
39
|
| **OpenCode** | Yes | Yes | — | MCP + Skills |
|
package/dist/cli/augment.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Augment CLI Command
|
|
3
3
|
*
|
|
4
4
|
* Fast-path command for platform hooks.
|
|
5
|
-
* Shells out from Claude Code PreToolUse / Cursor
|
|
5
|
+
* Shells out from Claude Code PreToolUse / Cursor postToolUse hooks.
|
|
6
6
|
*
|
|
7
7
|
* Usage: gitnexus augment <pattern>
|
|
8
8
|
* Returns enriched text to stdout.
|
package/dist/cli/augment.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Augment CLI Command
|
|
3
3
|
*
|
|
4
4
|
* Fast-path command for platform hooks.
|
|
5
|
-
* Shells out from Claude Code PreToolUse / Cursor
|
|
5
|
+
* Shells out from Claude Code PreToolUse / Cursor postToolUse hooks.
|
|
6
6
|
*
|
|
7
7
|
* Usage: gitnexus augment <pattern>
|
|
8
8
|
* Returns enriched text to stdout.
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Augmentation Engine
|
|
3
3
|
*
|
|
4
4
|
* Lightweight, fast-path enrichment of search patterns with knowledge graph context.
|
|
5
|
-
* Designed to be called from platform hooks (Claude Code PreToolUse, Cursor
|
|
6
|
-
* when an agent runs grep/glob/search.
|
|
5
|
+
* Designed to be called from platform hooks (Claude Code PreToolUse, Cursor postToolUse)
|
|
6
|
+
* when an agent runs grep/glob/read/search.
|
|
7
7
|
*
|
|
8
8
|
* Performance target: <500ms cold start, <200ms warm.
|
|
9
9
|
*
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Augmentation Engine
|
|
3
3
|
*
|
|
4
4
|
* Lightweight, fast-path enrichment of search patterns with knowledge graph context.
|
|
5
|
-
* Designed to be called from platform hooks (Claude Code PreToolUse, Cursor
|
|
6
|
-
* when an agent runs grep/glob/search.
|
|
5
|
+
* Designed to be called from platform hooks (Claude Code PreToolUse, Cursor postToolUse)
|
|
6
|
+
* when an agent runs grep/glob/read/search.
|
|
7
7
|
*
|
|
8
8
|
* Performance target: <500ms cold start, <200ms warm.
|
|
9
9
|
*
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { getLanguageFromFilename } from '../../_shared/index.js';
|
|
7
7
|
import { createParserForLanguage, isLanguageAvailable, resolveLanguageKey, } from '../tree-sitter/parser-loader.js';
|
|
8
|
+
import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
|
|
8
9
|
const parserCache = new Map();
|
|
9
10
|
/**
|
|
10
11
|
* Ensure parser is initialized and language is loaded, then parse content.
|
|
@@ -22,7 +23,7 @@ export const ensureAndParse = async (content, filePath) => {
|
|
|
22
23
|
parserInstance = await createParserForLanguage(language, filePath);
|
|
23
24
|
parserCache.set(parserKey, parserInstance);
|
|
24
25
|
}
|
|
25
|
-
return parserInstance
|
|
26
|
+
return parseSourceSafe(parserInstance, content);
|
|
26
27
|
};
|
|
27
28
|
const FUNCTION_LIKE_TYPES = new Set([
|
|
28
29
|
'function_declaration',
|
|
@@ -3,6 +3,7 @@ import { glob } from 'glob';
|
|
|
3
3
|
import Parser from 'tree-sitter';
|
|
4
4
|
import { createIgnoreFilter } from '../../../config/ignore-service.js';
|
|
5
5
|
import { readSafe } from './fs-utils.js';
|
|
6
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
6
7
|
import { logger } from '../../logger.js';
|
|
7
8
|
import { GRPC_SCAN_GLOB, getPluginForFile, hasProtoPlugin, } from './grpc-patterns/index.js';
|
|
8
9
|
/**
|
|
@@ -352,7 +353,7 @@ export class GrpcExtractor {
|
|
|
352
353
|
let detections = [];
|
|
353
354
|
try {
|
|
354
355
|
parser.setLanguage(plugin.language);
|
|
355
|
-
const tree = parser
|
|
356
|
+
const tree = parseSourceSafe(parser, content);
|
|
356
357
|
detections = plugin.scan(tree);
|
|
357
358
|
}
|
|
358
359
|
catch {
|
|
@@ -3,6 +3,7 @@ import { glob } from 'glob';
|
|
|
3
3
|
import Parser from 'tree-sitter';
|
|
4
4
|
import { createIgnoreFilter } from '../../../config/ignore-service.js';
|
|
5
5
|
import { readSafe } from './fs-utils.js';
|
|
6
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
6
7
|
import { getPluginForFile, HTTP_SCAN_GLOB } from './http-patterns/index.js';
|
|
7
8
|
/**
|
|
8
9
|
* Language-agnostic orchestrator for HTTP route (provider + consumer)
|
|
@@ -154,7 +155,7 @@ export class HttpRouteExtractor {
|
|
|
154
155
|
}
|
|
155
156
|
try {
|
|
156
157
|
parser.setLanguage(plugin.language);
|
|
157
|
-
const tree = parser
|
|
158
|
+
const tree = parseSourceSafe(parser, content);
|
|
158
159
|
const detections = plugin.scan(tree);
|
|
159
160
|
cachedDetections.set(rel, detections);
|
|
160
161
|
return detections;
|
|
@@ -8,6 +8,7 @@ import { readSafe } from './fs-utils.js';
|
|
|
8
8
|
import { buildSuffixIndex } from '../../ingestion/import-resolvers/utils.js';
|
|
9
9
|
import { createIgnoreFilter } from '../../../config/ignore-service.js';
|
|
10
10
|
import { getMaxFileSizeBytes } from '../../ingestion/utils/max-file-size.js';
|
|
11
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
11
12
|
import { logger } from '../../logger.js';
|
|
12
13
|
/**
|
|
13
14
|
* Cross-repo C/C++ `#include` dependency extractor.
|
|
@@ -457,7 +458,7 @@ export class IncludeExtractor {
|
|
|
457
458
|
let extractionSource;
|
|
458
459
|
try {
|
|
459
460
|
parser.setLanguage(lang);
|
|
460
|
-
const tree = parser
|
|
461
|
+
const tree = parseSourceSafe(parser, content);
|
|
461
462
|
let matches;
|
|
462
463
|
try {
|
|
463
464
|
matches = query.matches(tree.rootNode);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { glob } from 'glob';
|
|
2
2
|
import Parser from 'tree-sitter';
|
|
3
3
|
import { readSafe } from './fs-utils.js';
|
|
4
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
4
5
|
import { getPluginForFile, THRIFT_SCAN_GLOB, } from './thrift-patterns/index.js';
|
|
5
6
|
function normalizeThriftPath(rel) {
|
|
6
7
|
return rel.replace(/\\/g, '/');
|
|
@@ -228,7 +229,7 @@ export class ThriftExtractor {
|
|
|
228
229
|
let detections = [];
|
|
229
230
|
try {
|
|
230
231
|
parser.setLanguage(plugin.language);
|
|
231
|
-
const tree = parser
|
|
232
|
+
const tree = parseSourceSafe(parser, content);
|
|
232
233
|
detections = plugin.scan(tree);
|
|
233
234
|
}
|
|
234
235
|
catch {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Parser from 'tree-sitter';
|
|
2
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
2
3
|
/**
|
|
3
4
|
* Compile a LanguagePatterns bundle. Call this once per plugin, at
|
|
4
5
|
* module load time, and export the result. Throws if any pattern
|
|
@@ -60,7 +61,7 @@ export function scanFile(parser, plugin, content) {
|
|
|
60
61
|
let tree;
|
|
61
62
|
try {
|
|
62
63
|
parser.setLanguage(plugin.language);
|
|
63
|
-
tree = parser
|
|
64
|
+
tree = parseSourceSafe(parser, content);
|
|
64
65
|
}
|
|
65
66
|
catch {
|
|
66
67
|
return [];
|
|
@@ -29,6 +29,7 @@ import { getLanguageFromFilename, SupportedLanguages } from '../../_shared/index
|
|
|
29
29
|
import { isRegistryPrimary } from './registry-primary-flag.js';
|
|
30
30
|
import { isVerboseIngestionEnabled } from './utils/verbose.js';
|
|
31
31
|
import { yieldToEventLoop } from './utils/event-loop.js';
|
|
32
|
+
import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
|
|
32
33
|
import { FUNCTION_NODE_TYPES, findEnclosingClassId, findEnclosingClassInfo, genericFuncName, inferFunctionLabel, } from './utils/ast-helpers.js';
|
|
33
34
|
import { typeTagForId, constTagForId, buildCollisionGroups } from './utils/method-props.js';
|
|
34
35
|
import { countCallArguments, inferCallForm, extractReceiverName, extractReceiverNode, extractMixedChain, extractCallArgTypes, } from './utils/call-analysis.js';
|
|
@@ -614,7 +615,7 @@ importedRawReturnTypesMap, heritageMap, bindingAccumulator) => {
|
|
|
614
615
|
if (!tree) {
|
|
615
616
|
const parseContent = provider.preprocessSource?.(file.content, file.path) ?? file.content;
|
|
616
617
|
try {
|
|
617
|
-
tree = parser
|
|
618
|
+
tree = parseSourceSafe(parser, parseContent, undefined, {
|
|
618
619
|
bufferSize: getTreeSitterBufferSize(parseContent),
|
|
619
620
|
});
|
|
620
621
|
}
|
|
@@ -2586,7 +2587,7 @@ export const extractFetchCallsFromFiles = async (files, astCache) => {
|
|
|
2586
2587
|
if (!tree) {
|
|
2587
2588
|
const parseContent = provider.preprocessSource?.(file.content, file.path) ?? file.content;
|
|
2588
2589
|
try {
|
|
2589
|
-
tree = parser
|
|
2590
|
+
tree = parseSourceSafe(parser, parseContent, undefined, {
|
|
2590
2591
|
bufferSize: getTreeSitterBufferSize(parseContent),
|
|
2591
2592
|
});
|
|
2592
2593
|
}
|
|
@@ -19,6 +19,7 @@ import { generateId } from '../../lib/utils.js';
|
|
|
19
19
|
import { getLanguageFromFilename } from '../../_shared/index.js';
|
|
20
20
|
import { isVerboseIngestionEnabled } from './utils/verbose.js';
|
|
21
21
|
import { yieldToEventLoop } from './utils/event-loop.js';
|
|
22
|
+
import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
|
|
22
23
|
import { getProvider } from './languages/index.js';
|
|
23
24
|
import { getTreeSitterBufferSize } from './constants.js';
|
|
24
25
|
import { resolveExtendsType } from './model/heritage-map.js';
|
|
@@ -152,7 +153,7 @@ export const processHeritage = async (graph, files, astCache, ctx, onProgress) =
|
|
|
152
153
|
// re-parses see the same input as the cached AST.
|
|
153
154
|
const parseContent = provider.preprocessSource?.(file.content, file.path) ?? file.content;
|
|
154
155
|
try {
|
|
155
|
-
tree = parser
|
|
156
|
+
tree = parseSourceSafe(parser, parseContent, undefined, {
|
|
156
157
|
bufferSize: getTreeSitterBufferSize(parseContent),
|
|
157
158
|
});
|
|
158
159
|
}
|
|
@@ -300,7 +301,7 @@ export async function extractExtractedHeritageFromFiles(files, astCache) {
|
|
|
300
301
|
if (!tree) {
|
|
301
302
|
const parseContent = provider.preprocessSource?.(file.content, file.path) ?? file.content;
|
|
302
303
|
try {
|
|
303
|
-
tree = parser
|
|
304
|
+
tree = parseSourceSafe(parser, parseContent, undefined, {
|
|
304
305
|
bufferSize: getTreeSitterBufferSize(parseContent),
|
|
305
306
|
});
|
|
306
307
|
}
|
|
@@ -5,6 +5,7 @@ import { generateId } from '../../lib/utils.js';
|
|
|
5
5
|
import { getLanguageFromFilename } from '../../_shared/index.js';
|
|
6
6
|
import { isVerboseIngestionEnabled } from './utils/verbose.js';
|
|
7
7
|
import { yieldToEventLoop } from './utils/event-loop.js';
|
|
8
|
+
import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
|
|
8
9
|
import { getTreeSitterBufferSize } from './constants.js';
|
|
9
10
|
import { loadImportConfigs } from './language-config.js';
|
|
10
11
|
import { buildSuffixIndex } from './import-resolvers/utils.js';
|
|
@@ -243,7 +244,7 @@ export const processImports = async (graph, files, astCache, ctx, onProgress, re
|
|
|
243
244
|
if (!tree) {
|
|
244
245
|
const parseContent = provider.preprocessSource?.(file.content, file.path) ?? file.content;
|
|
245
246
|
try {
|
|
246
|
-
tree = parser
|
|
247
|
+
tree = parseSourceSafe(parser, parseContent, undefined, {
|
|
247
248
|
bufferSize: getTreeSitterBufferSize(parseContent),
|
|
248
249
|
});
|
|
249
250
|
}
|
|
@@ -22,6 +22,7 @@ import { synthesizeCsharpReceiverBinding } from './receiver-binding.js';
|
|
|
22
22
|
import { getCsharpParser, getCsharpScopeQuery } from './query.js';
|
|
23
23
|
import { recordCacheHit, recordCacheMiss } from './cache-stats.js';
|
|
24
24
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
25
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
25
26
|
/** Declaration anchors that carry function-like arity metadata. */
|
|
26
27
|
const FUNCTION_DECL_TAGS = [
|
|
27
28
|
'@declaration.method',
|
|
@@ -75,7 +76,7 @@ export function emitCsharpScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
|
75
76
|
// the LanguageProvider contract layer; cast here at the use site.
|
|
76
77
|
let tree = cachedTree;
|
|
77
78
|
if (tree === undefined) {
|
|
78
|
-
tree = getCsharpParser()
|
|
79
|
+
tree = parseSourceSafe(getCsharpParser(), sourceText, undefined, {
|
|
79
80
|
bufferSize: getTreeSitterBufferSize(sourceText),
|
|
80
81
|
});
|
|
81
82
|
recordCacheMiss();
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
import { getCsharpParser } from './query.js';
|
|
34
34
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
35
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
35
36
|
/** Build a structural view of a C# file by walking the tree-sitter
|
|
36
37
|
* AST. Prefers `cachedTree` (handed in via `treeCache`) so we don't
|
|
37
38
|
* re-parse files the orchestrator already parsed for `extractParsedFile`;
|
|
@@ -39,7 +40,7 @@ import { getTreeSitterBufferSize } from '../../constants.js';
|
|
|
39
40
|
* shared across calls. */
|
|
40
41
|
function extractFileStructure(content, cachedTree) {
|
|
41
42
|
const tree = cachedTree ??
|
|
42
|
-
getCsharpParser()
|
|
43
|
+
parseSourceSafe(getCsharpParser(), content, undefined, {
|
|
43
44
|
bufferSize: getTreeSitterBufferSize(content),
|
|
44
45
|
});
|
|
45
46
|
const namespaces = [];
|
|
@@ -332,7 +333,7 @@ export function populateCsharpNamespaceSiblings(parsedFiles, indexes, inputs) {
|
|
|
332
333
|
const key = q.includes('.') ? q.slice(q.lastIndexOf('.') + 1) : q;
|
|
333
334
|
if (key === '')
|
|
334
335
|
continue;
|
|
335
|
-
const arr = defsByName.get(key) ?? [];
|
|
336
|
+
const arr = [...(defsByName.get(key) ?? [])];
|
|
336
337
|
arr.push(def);
|
|
337
338
|
defsByName.set(key, arr);
|
|
338
339
|
}
|
|
@@ -6,10 +6,11 @@ import { splitGoImportStatement } from './import-decomposer.js';
|
|
|
6
6
|
import { synthesizeGoReceiverBinding } from './receiver-binding.js';
|
|
7
7
|
import { synthesizeGoTypeBindings } from './type-binding.js';
|
|
8
8
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
9
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
9
10
|
export function emitGoScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
10
11
|
let tree = cachedTree;
|
|
11
12
|
if (tree === undefined) {
|
|
12
|
-
tree = getGoParser()
|
|
13
|
+
tree = parseSourceSafe(getGoParser(), sourceText, undefined, {
|
|
13
14
|
bufferSize: getTreeSitterBufferSize(sourceText),
|
|
14
15
|
});
|
|
15
16
|
recordGoCacheMiss();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getGoParser } from './query.js';
|
|
2
2
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
3
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
3
4
|
export function populateGoRangeBindings(parsedFiles, _indexes, ctx) {
|
|
4
5
|
const parser = getGoParser();
|
|
5
6
|
for (const parsed of parsedFiles) {
|
|
@@ -8,7 +9,7 @@ export function populateGoRangeBindings(parsedFiles, _indexes, ctx) {
|
|
|
8
9
|
continue;
|
|
9
10
|
const cachedTree = ctx.treeCache?.get(parsed.filePath);
|
|
10
11
|
const tree = cachedTree ??
|
|
11
|
-
parser
|
|
12
|
+
parseSourceSafe(parser, sourceText, undefined, {
|
|
12
13
|
bufferSize: getTreeSitterBufferSize(sourceText),
|
|
13
14
|
});
|
|
14
15
|
const moduleScope = parsed.scopes.find((s) => s.kind === 'Module');
|
|
@@ -22,6 +22,7 @@ import { synthesizeReceiverTypeBinding } from './receiver-binding.js';
|
|
|
22
22
|
import { computePythonArityMetadata } from './arity-metadata.js';
|
|
23
23
|
import { recordCacheHit, recordCacheMiss } from './cache-stats.js';
|
|
24
24
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
25
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
25
26
|
import { pythonFunctionDefinitionLabel } from './simple-hooks.js';
|
|
26
27
|
export function emitPythonScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
27
28
|
// Skip the parse when the caller (parse phase's ASTCache) already
|
|
@@ -32,7 +33,7 @@ export function emitPythonScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
|
32
33
|
let tree = cachedTree;
|
|
33
34
|
if (tree === undefined) {
|
|
34
35
|
try {
|
|
35
|
-
tree = getPythonParser()
|
|
36
|
+
tree = parseSourceSafe(getPythonParser(), sourceText, undefined, {
|
|
36
37
|
bufferSize: getTreeSitterBufferSize(sourceText),
|
|
37
38
|
});
|
|
38
39
|
}
|
|
@@ -31,6 +31,7 @@ import { recordCacheHit, recordCacheMiss } from './cache-stats.js';
|
|
|
31
31
|
import { synthesizeTsReceiverBinding } from './receiver-binding.js';
|
|
32
32
|
import { computeTsArityMetadata } from './arity-metadata.js';
|
|
33
33
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
34
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
34
35
|
/** tree-sitter-typescript node types for function-like scopes that may
|
|
35
36
|
* carry a synthesized `this` binding. Kept in sync with the
|
|
36
37
|
* `@scope.function` patterns in `query.ts`. */
|
|
@@ -119,7 +120,7 @@ export function emitTsScopeCaptures(sourceText, filePath, cachedTree) {
|
|
|
119
120
|
tree = undefined;
|
|
120
121
|
}
|
|
121
122
|
if (tree === undefined) {
|
|
122
|
-
tree = getTsParser(filePath)
|
|
123
|
+
tree = parseSourceSafe(getTsParser(filePath), sourceText, undefined, {
|
|
123
124
|
bufferSize: getTreeSitterBufferSize(sourceText),
|
|
124
125
|
});
|
|
125
126
|
recordCacheMiss();
|
|
@@ -5,6 +5,7 @@ import { generateId } from '../../lib/utils.js';
|
|
|
5
5
|
import { getLanguageFromFilename, SupportedLanguages } from '../../_shared/index.js';
|
|
6
6
|
import { extractVueScript, isVueSetupTopLevel } from './vue-sfc-extractor.js';
|
|
7
7
|
import { yieldToEventLoop } from './utils/event-loop.js';
|
|
8
|
+
import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
|
|
8
9
|
import { isVerboseIngestionEnabled } from './utils/verbose.js';
|
|
9
10
|
import { getDefinitionNodeFromCaptures, findEnclosingClassInfo, getLabelFromCaptures, CLASS_CONTAINER_TYPES, } from './utils/ast-helpers.js';
|
|
10
11
|
import { detectFrameworkFromAST } from './framework-detection.js';
|
|
@@ -274,7 +275,7 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, sco
|
|
|
274
275
|
}
|
|
275
276
|
let tree;
|
|
276
277
|
try {
|
|
277
|
-
tree = parser
|
|
278
|
+
tree = parseSourceSafe(parser, parseContent, undefined, {
|
|
278
279
|
bufferSize: getTreeSitterBufferSize(parseContent),
|
|
279
280
|
});
|
|
280
281
|
}
|
|
@@ -16,6 +16,7 @@ import { createRequire } from 'node:module';
|
|
|
16
16
|
import { SupportedLanguages } from '../../../_shared/index.js';
|
|
17
17
|
import { getProvider } from '../languages/index.js';
|
|
18
18
|
import { getTreeSitterBufferSize, getTreeSitterContentByteLength, TREE_SITTER_MAX_BUFFER, } from '../constants.js';
|
|
19
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
19
20
|
// tree-sitter-swift is an optionalDependency — may not be installed
|
|
20
21
|
const _require = createRequire(import.meta.url);
|
|
21
22
|
let Swift = null;
|
|
@@ -1026,7 +1027,7 @@ const processFileGroup = (files, language, queryString, result, onFileProcessed)
|
|
|
1026
1027
|
clearCaches(); // Reset memoization before each new file
|
|
1027
1028
|
let tree;
|
|
1028
1029
|
try {
|
|
1029
|
-
tree = parser
|
|
1030
|
+
tree = parseSourceSafe(parser, parseContent, undefined, {
|
|
1030
1031
|
bufferSize: getTreeSitterBufferSize(parseContent),
|
|
1031
1032
|
});
|
|
1032
1033
|
}
|
|
@@ -1102,6 +1102,14 @@ export const loadVectorExtension = async (targetConn, opts = {}) => {
|
|
|
1102
1102
|
const useModuleState = targetConn === undefined;
|
|
1103
1103
|
if (useModuleState && vectorExtensionLoaded)
|
|
1104
1104
|
return true;
|
|
1105
|
+
// INSTALL VECTOR crashes with SIGSEGV on Windows: the KuzuDB native extension
|
|
1106
|
+
// installer has an unhandled error path on Windows that raises a fatal signal
|
|
1107
|
+
// that JS try/catch cannot intercept. Skip loading — vector/embedding search
|
|
1108
|
+
// is unavailable but all graph index queries still work. Do NOT set
|
|
1109
|
+
// vectorExtensionLoaded here: the flag means "successfully loaded", and a
|
|
1110
|
+
// subsequent call would otherwise short-circuit to `return true` at the top.
|
|
1111
|
+
if (process.platform === 'win32')
|
|
1112
|
+
return false;
|
|
1105
1113
|
if (!isVectorExtensionSupportedByPlatform())
|
|
1106
1114
|
return false;
|
|
1107
1115
|
const c = targetConn ?? conn;
|
|
@@ -348,7 +348,18 @@ async function doInitLbug(repoId, dbPath) {
|
|
|
348
348
|
// install; analyze owns extension installation. If LOAD fails, search
|
|
349
349
|
// features degrade gracefully and the user-facing query path proceeds.
|
|
350
350
|
if (!shared.ftsLoaded) {
|
|
351
|
-
|
|
351
|
+
// Windows guard: LOAD EXTENSION fts crashes with SIGSEGV on Windows when
|
|
352
|
+
// the FTS extension binary is not installed locally (@ladybugdb/core native
|
|
353
|
+
// bug — the extension loader hits an unhandled error path that signals SIGSEGV
|
|
354
|
+
// rather than throwing a JS exception, so try/catch cannot protect here).
|
|
355
|
+
// Skip the load on Windows; bm25-index.js catches the resulting Kuzu catalog
|
|
356
|
+
// errors and returns empty BM25 results gracefully. Graph queries are unaffected.
|
|
357
|
+
if (process.platform === 'win32') {
|
|
358
|
+
shared.ftsLoaded = true;
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
shared.ftsLoaded = await loadFTSExtension(available[0], { policy: 'load-only' });
|
|
362
|
+
}
|
|
352
363
|
}
|
|
353
364
|
// Register pool entry only after all connections are pre-warmed and FTS is
|
|
354
365
|
// loaded. Concurrent executeQuery calls see either "not initialized"
|
|
@@ -404,8 +415,14 @@ export async function initLbugWithDb(repoId, existingDb, dbPath) {
|
|
|
404
415
|
// Load FTS extension if not already loaded on this Database.
|
|
405
416
|
// policy: 'load-only' — same contract as initLbug above; the read pool
|
|
406
417
|
// must not block on a network install during query execution.
|
|
418
|
+
// Windows guard: same SIGSEGV risk as doInitLbug above — skip on Windows.
|
|
407
419
|
if (!shared.ftsLoaded) {
|
|
408
|
-
|
|
420
|
+
if (process.platform === 'win32') {
|
|
421
|
+
shared.ftsLoaded = true;
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
shared.ftsLoaded = await loadFTSExtension(available[0], { policy: 'load-only' });
|
|
425
|
+
}
|
|
409
426
|
}
|
|
410
427
|
pool.set(repoId, {
|
|
411
428
|
db: existingDb,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type Parser from 'tree-sitter';
|
|
2
|
+
/**
|
|
3
|
+
* Parse `sourceText` safely on every platform. See {@link SAFE_PARSE_CHUNK_CHARS}
|
|
4
|
+
* for the underlying tree-sitter binding bug this works around.
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseSourceSafe(parser: Parser, sourceText: string, oldTree?: Parser.Tree, options?: Parser.Options): Parser.Tree;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tree-sitter 0.21.x's Node native binding crashes (SIGSEGV) on Windows when
|
|
3
|
+
* `parser.parse(string, …)` is handed a JS string longer than 32 767 chars.
|
|
4
|
+
* The crash happens inside the binding's V8 string-to-buffer conversion and
|
|
5
|
+
* cannot be intercepted from JavaScript. The callback (`Parser.Input`) overload
|
|
6
|
+
* pulls source in fixed-size chunks via repeated callback invocations and
|
|
7
|
+
* bypasses that conversion path entirely.
|
|
8
|
+
*
|
|
9
|
+
* Chunk size is comfortably below the boundary; any value < 32 767 works.
|
|
10
|
+
*/
|
|
11
|
+
const SAFE_PARSE_CHUNK_CHARS = 16 * 1024;
|
|
12
|
+
/**
|
|
13
|
+
* Files at or below this length skip the callback machinery and use the
|
|
14
|
+
* direct string overload — the bug only manifests above the int16 boundary,
|
|
15
|
+
* so small inputs save the cost of N callback invocations per parse.
|
|
16
|
+
*/
|
|
17
|
+
const DIRECT_PARSE_LIMIT_CHARS = 16 * 1024;
|
|
18
|
+
/**
|
|
19
|
+
* Parse `sourceText` safely on every platform. See {@link SAFE_PARSE_CHUNK_CHARS}
|
|
20
|
+
* for the underlying tree-sitter binding bug this works around.
|
|
21
|
+
*/
|
|
22
|
+
export function parseSourceSafe(parser, sourceText, oldTree, options) {
|
|
23
|
+
if (sourceText.length <= DIRECT_PARSE_LIMIT_CHARS) {
|
|
24
|
+
return parser.parse(sourceText, oldTree, options);
|
|
25
|
+
}
|
|
26
|
+
const input = (index) => {
|
|
27
|
+
if (index >= sourceText.length)
|
|
28
|
+
return null;
|
|
29
|
+
return sourceText.slice(index, index + SAFE_PARSE_CHUNK_CHARS);
|
|
30
|
+
};
|
|
31
|
+
return parser.parse(input, oldTree, options);
|
|
32
|
+
}
|
package/package.json
CHANGED