lynkr 9.9.0 → 9.10.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 +92 -23
- package/bin/cli.js +13 -7
- package/bin/lynkr-init.js +34 -12
- package/bin/lynkr-reset.js +71 -0
- package/config/model-tiers.json +199 -52
- package/package.json +3 -3
- package/scripts/build-eval-set.js +256 -0
- package/scripts/mine-difficulty-anchors.js +288 -0
- package/scripts/validate-difficulty-classifier.js +144 -0
- package/scripts/validate-intent-anchors.js +186 -0
- package/src/api/providers-handler.js +0 -1
- package/src/api/router.js +292 -160
- package/src/clients/databricks.js +95 -6
- package/src/config/index.js +3 -43
- package/src/context/tool-result-compressor.js +883 -40
- package/src/orchestrator/index.js +117 -1235
- package/src/orchestrator/passthrough-stream.js +382 -0
- package/src/orchestrator/sse-transformer.js +408 -0
- package/src/routing/affinity-store.js +17 -3
- package/src/routing/classifier-setup.js +207 -0
- package/src/routing/complexity-analyzer.js +40 -4
- package/src/routing/difficulty-classifier.js +261 -0
- package/src/routing/index.js +70 -7
- package/src/routing/intent-score.js +132 -12
- package/src/routing/session-affinity.js +8 -1
- package/src/routing/side-channel-detector.js +103 -0
- package/src/server.js +20 -46
- package/src/agents/context-manager.js +0 -236
- package/src/agents/decomposition/dispatcher.js +0 -185
- package/src/agents/decomposition/gate.js +0 -136
- package/src/agents/decomposition/index.js +0 -183
- package/src/agents/decomposition/model-call.js +0 -75
- package/src/agents/decomposition/planner.js +0 -223
- package/src/agents/decomposition/synthesizer.js +0 -89
- package/src/agents/decomposition/telemetry.js +0 -55
- package/src/agents/definitions/loader.js +0 -653
- package/src/agents/executor.js +0 -457
- package/src/agents/index.js +0 -165
- package/src/agents/parallel-coordinator.js +0 -68
- package/src/agents/reflector.js +0 -331
- package/src/agents/skillbook.js +0 -331
- package/src/agents/store.js +0 -259
- package/src/edits/index.js +0 -171
- package/src/indexer/babel-parser.js +0 -213
- package/src/indexer/index.js +0 -1629
- package/src/indexer/navigation/index.js +0 -32
- package/src/indexer/navigation/providers/treeSitter.js +0 -36
- package/src/indexer/parser.js +0 -443
- package/src/tasks/store.js +0 -349
- package/src/tests/coverage.js +0 -173
- package/src/tests/index.js +0 -171
- package/src/tests/store.js +0 -213
- package/src/tools/agent-task.js +0 -145
- package/src/tools/code-mode.js +0 -304
- package/src/tools/decompose.js +0 -91
- package/src/tools/edits.js +0 -94
- package/src/tools/execution.js +0 -171
- package/src/tools/git.js +0 -1346
- package/src/tools/index.js +0 -306
- package/src/tools/indexer.js +0 -360
- package/src/tools/lazy-loader.js +0 -366
- package/src/tools/mcp-remote.js +0 -88
- package/src/tools/mcp.js +0 -116
- package/src/tools/process.js +0 -167
- package/src/tools/smart-selection.js +0 -180
- package/src/tools/stubs.js +0 -55
- package/src/tools/tasks.js +0 -260
- package/src/tools/tests.js +0 -132
- package/src/tools/tinyfish.js +0 -358
- package/src/tools/truncate.js +0 -106
- package/src/tools/web-client.js +0 -71
- package/src/tools/web.js +0 -415
- package/src/tools/workspace.js +0 -204
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
const logger = require("../../logger");
|
|
2
|
-
const { analyzeWithTreeSitter } = require("./providers/treeSitter");
|
|
3
|
-
|
|
4
|
-
const PROVIDERS = [analyzeWithTreeSitter];
|
|
5
|
-
|
|
6
|
-
function analyzeFile({ relativePath, content, language }) {
|
|
7
|
-
for (const provider of PROVIDERS) {
|
|
8
|
-
try {
|
|
9
|
-
const result = provider({ relativePath, content, language });
|
|
10
|
-
if (result && result.definitions && result.definitions.length) {
|
|
11
|
-
return result;
|
|
12
|
-
}
|
|
13
|
-
if (result) {
|
|
14
|
-
return result;
|
|
15
|
-
}
|
|
16
|
-
} catch (err) {
|
|
17
|
-
logger.debug(
|
|
18
|
-
{
|
|
19
|
-
err,
|
|
20
|
-
provider: provider.name,
|
|
21
|
-
file: relativePath,
|
|
22
|
-
},
|
|
23
|
-
"Navigation provider failed",
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
module.exports = {
|
|
31
|
-
analyzeFile,
|
|
32
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
const { parseFile } = require("../../parser");
|
|
2
|
-
|
|
3
|
-
function analyzeWithTreeSitter({ relativePath, content, language }) {
|
|
4
|
-
if (typeof content !== "string") {
|
|
5
|
-
return null;
|
|
6
|
-
}
|
|
7
|
-
const analysis = parseFile(relativePath, content, language);
|
|
8
|
-
if (!analysis) {
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
const engine = "tree_sitter";
|
|
12
|
-
const withEngine = (items) =>
|
|
13
|
-
Array.isArray(items)
|
|
14
|
-
? items.map((item) => ({
|
|
15
|
-
...item,
|
|
16
|
-
engine,
|
|
17
|
-
}))
|
|
18
|
-
: [];
|
|
19
|
-
return {
|
|
20
|
-
engine,
|
|
21
|
-
language: analysis.language ?? language,
|
|
22
|
-
symbols: analysis.symbols ?? [],
|
|
23
|
-
definitions: analysis.definitions ?? analysis.symbols ?? [],
|
|
24
|
-
references: withEngine(analysis.references),
|
|
25
|
-
dependencies: analysis.dependencies ?? [],
|
|
26
|
-
exports: withEngine(analysis.exports),
|
|
27
|
-
imports: withEngine(analysis.imports),
|
|
28
|
-
metadata: {
|
|
29
|
-
relativePath,
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
module.exports = {
|
|
35
|
-
analyzeWithTreeSitter,
|
|
36
|
-
};
|
package/src/indexer/parser.js
DELETED
|
@@ -1,443 +0,0 @@
|
|
|
1
|
-
const logger = require("../logger");
|
|
2
|
-
|
|
3
|
-
// Lazy load heavy dependencies
|
|
4
|
-
let Parser = null;
|
|
5
|
-
let JavaScript = null;
|
|
6
|
-
let TypeScript = null;
|
|
7
|
-
let TSX = null;
|
|
8
|
-
let Python = null;
|
|
9
|
-
let treeSitterAvailable = null; // null = not checked, true/false = result
|
|
10
|
-
|
|
11
|
-
function isTreeSitterAvailable() {
|
|
12
|
-
if (treeSitterAvailable !== null) {
|
|
13
|
-
return treeSitterAvailable;
|
|
14
|
-
}
|
|
15
|
-
try {
|
|
16
|
-
require.resolve("tree-sitter");
|
|
17
|
-
treeSitterAvailable = true;
|
|
18
|
-
logger.info("[Parser] tree-sitter available");
|
|
19
|
-
} catch {
|
|
20
|
-
treeSitterAvailable = false;
|
|
21
|
-
logger.info("[Parser] tree-sitter not available - using babel fallback for JS/TS (Python parsing disabled)");
|
|
22
|
-
}
|
|
23
|
-
return treeSitterAvailable;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function getTreeSitterParser() {
|
|
27
|
-
if (!isTreeSitterAvailable()) {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
if (!Parser) {
|
|
31
|
-
try {
|
|
32
|
-
Parser = require("tree-sitter");
|
|
33
|
-
} catch (err) {
|
|
34
|
-
logger.warn({ err: err.message }, "[Parser] Failed to load tree-sitter");
|
|
35
|
-
treeSitterAvailable = false;
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return Parser;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function getLanguageModule(language) {
|
|
43
|
-
if (!isTreeSitterAvailable()) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
try {
|
|
47
|
-
switch (language) {
|
|
48
|
-
case "javascript":
|
|
49
|
-
case "javascript-react":
|
|
50
|
-
if (!JavaScript) {
|
|
51
|
-
JavaScript = require("tree-sitter-javascript");
|
|
52
|
-
}
|
|
53
|
-
return JavaScript;
|
|
54
|
-
case "typescript":
|
|
55
|
-
if (!TypeScript) {
|
|
56
|
-
const ts = require("tree-sitter-typescript");
|
|
57
|
-
TypeScript = ts.typescript;
|
|
58
|
-
}
|
|
59
|
-
return TypeScript;
|
|
60
|
-
case "typescript-react":
|
|
61
|
-
if (!TSX) {
|
|
62
|
-
const ts = require("tree-sitter-typescript");
|
|
63
|
-
TSX = ts.tsx;
|
|
64
|
-
}
|
|
65
|
-
return TSX;
|
|
66
|
-
case "python":
|
|
67
|
-
if (!Python) {
|
|
68
|
-
Python = require("tree-sitter-python");
|
|
69
|
-
}
|
|
70
|
-
return Python;
|
|
71
|
-
default:
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
} catch (err) {
|
|
75
|
-
logger.warn({ err: err.message, language }, "[Parser] Failed to load language module");
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const parserCache = {};
|
|
81
|
-
|
|
82
|
-
const LANGUAGE_MAP = {
|
|
83
|
-
javascript: { getLanguage: () => getLanguageModule("javascript"), type: "javascript" },
|
|
84
|
-
"javascript-react": { getLanguage: () => getLanguageModule("javascript-react"), type: "javascript" },
|
|
85
|
-
typescript: { getLanguage: () => getLanguageModule("typescript"), type: "typescript" },
|
|
86
|
-
"typescript-react": { getLanguage: () => getLanguageModule("typescript-react"), type: "typescript" },
|
|
87
|
-
python: { getLanguage: () => getLanguageModule("python"), type: "python" },
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
function getParser(languageKey) {
|
|
91
|
-
if (!isTreeSitterAvailable()) {
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
const entry = LANGUAGE_MAP[languageKey];
|
|
95
|
-
if (!entry) return null;
|
|
96
|
-
if (!parserCache[languageKey]) {
|
|
97
|
-
const ParserClass = getTreeSitterParser();
|
|
98
|
-
if (!ParserClass) return null;
|
|
99
|
-
const parser = new ParserClass();
|
|
100
|
-
const language = entry.getLanguage();
|
|
101
|
-
if (!language) return null;
|
|
102
|
-
parser.setLanguage(language);
|
|
103
|
-
parserCache[languageKey] = parser;
|
|
104
|
-
}
|
|
105
|
-
return parserCache[languageKey];
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function nodeText(node, source) {
|
|
109
|
-
return source.slice(node.startIndex, node.endIndex);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function positionOf(node) {
|
|
113
|
-
return {
|
|
114
|
-
line: node.startPosition.row + 1,
|
|
115
|
-
column: node.startPosition.column + 1,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function identifierName(node, source) {
|
|
120
|
-
if (!node) return null;
|
|
121
|
-
if (node.type === "identifier" || node.type === "property_identifier") {
|
|
122
|
-
return nodeText(node, source);
|
|
123
|
-
}
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function extractJavaScript(tree, source) {
|
|
128
|
-
const symbols = [];
|
|
129
|
-
const dependencies = [];
|
|
130
|
-
const references = [];
|
|
131
|
-
const imports = [];
|
|
132
|
-
const exports = [];
|
|
133
|
-
|
|
134
|
-
const registerReference = (nameNode, refNode) => {
|
|
135
|
-
if (!nameNode || !refNode) return;
|
|
136
|
-
const name = identifierName(nameNode, source);
|
|
137
|
-
if (!name) return;
|
|
138
|
-
references.push({
|
|
139
|
-
name,
|
|
140
|
-
line: refNode.startPosition.row + 1,
|
|
141
|
-
column: refNode.startPosition.column + 1,
|
|
142
|
-
snippet: nodeText(refNode, source),
|
|
143
|
-
});
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
const visit = (node) => {
|
|
147
|
-
switch (node.type) {
|
|
148
|
-
case "function_declaration": {
|
|
149
|
-
const nameNode = node.childForFieldName("name");
|
|
150
|
-
if (nameNode) {
|
|
151
|
-
symbols.push({
|
|
152
|
-
name: nodeText(nameNode, source),
|
|
153
|
-
kind: "function",
|
|
154
|
-
...positionOf(nameNode),
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
case "class_declaration": {
|
|
160
|
-
const nameNode = node.childForFieldName("name");
|
|
161
|
-
if (nameNode) {
|
|
162
|
-
symbols.push({
|
|
163
|
-
name: nodeText(nameNode, source),
|
|
164
|
-
kind: "class",
|
|
165
|
-
...positionOf(nameNode),
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
case "method_definition": {
|
|
171
|
-
const nameNode = node.childForFieldName("name");
|
|
172
|
-
if (nameNode) {
|
|
173
|
-
symbols.push({
|
|
174
|
-
name: nodeText(nameNode, source),
|
|
175
|
-
kind: "method",
|
|
176
|
-
...positionOf(nameNode),
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
break;
|
|
180
|
-
}
|
|
181
|
-
case "arrow_function": {
|
|
182
|
-
const parent = node.parent;
|
|
183
|
-
if (parent && parent.type === "variable_declarator") {
|
|
184
|
-
const nameNode = parent.childForFieldName("name");
|
|
185
|
-
if (nameNode) {
|
|
186
|
-
symbols.push({
|
|
187
|
-
name: nodeText(nameNode, source),
|
|
188
|
-
kind: "function",
|
|
189
|
-
...positionOf(nameNode),
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
break;
|
|
194
|
-
}
|
|
195
|
-
case "identifier": {
|
|
196
|
-
registerReference(node, node);
|
|
197
|
-
break;
|
|
198
|
-
}
|
|
199
|
-
case "import_statement": {
|
|
200
|
-
const sourceNode = node.childForFieldName("source");
|
|
201
|
-
if (sourceNode) {
|
|
202
|
-
const importPath = nodeText(sourceNode, source).replace(/['"]/g, "");
|
|
203
|
-
dependencies.push({
|
|
204
|
-
kind: "import",
|
|
205
|
-
path: importPath,
|
|
206
|
-
metadata: {
|
|
207
|
-
clause: nodeText(node, source),
|
|
208
|
-
},
|
|
209
|
-
});
|
|
210
|
-
imports.push({
|
|
211
|
-
path: importPath,
|
|
212
|
-
clause: nodeText(node, source),
|
|
213
|
-
line: sourceNode.startPosition.row + 1,
|
|
214
|
-
column: sourceNode.startPosition.column + 1,
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
break;
|
|
218
|
-
}
|
|
219
|
-
case "call_expression": {
|
|
220
|
-
const funcNode = node.child(0);
|
|
221
|
-
if (funcNode && funcNode.type === "identifier" && nodeText(funcNode, source) === "require") {
|
|
222
|
-
const argsNode = node.child(1);
|
|
223
|
-
if (argsNode && argsNode.firstChild) {
|
|
224
|
-
const required = nodeText(argsNode.firstChild, source).replace(/['"]/g, "");
|
|
225
|
-
dependencies.push({
|
|
226
|
-
kind: "require",
|
|
227
|
-
path: required,
|
|
228
|
-
metadata: {
|
|
229
|
-
clause: nodeText(node, source),
|
|
230
|
-
},
|
|
231
|
-
});
|
|
232
|
-
imports.push({
|
|
233
|
-
path: required,
|
|
234
|
-
clause: nodeText(node, source),
|
|
235
|
-
line: node.startPosition.row + 1,
|
|
236
|
-
column: node.startPosition.column + 1,
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
case "export_statement":
|
|
243
|
-
case "export_clause":
|
|
244
|
-
case "export_default_declaration": {
|
|
245
|
-
exports.push({
|
|
246
|
-
clause: nodeText(node, source),
|
|
247
|
-
line: node.startPosition.row + 1,
|
|
248
|
-
column: node.startPosition.column + 1,
|
|
249
|
-
});
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
252
|
-
default:
|
|
253
|
-
break;
|
|
254
|
-
}
|
|
255
|
-
for (const child of node.children) {
|
|
256
|
-
visit(child);
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
visit(tree.rootNode);
|
|
261
|
-
return {
|
|
262
|
-
symbols,
|
|
263
|
-
dependencies,
|
|
264
|
-
references,
|
|
265
|
-
imports,
|
|
266
|
-
exports,
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function extractPython(tree, source) {
|
|
271
|
-
const symbols = [];
|
|
272
|
-
const dependencies = [];
|
|
273
|
-
const references = [];
|
|
274
|
-
const imports = [];
|
|
275
|
-
|
|
276
|
-
const registerReference = (nameNode) => {
|
|
277
|
-
if (!nameNode) return;
|
|
278
|
-
const name = nodeText(nameNode, source);
|
|
279
|
-
if (!name) return;
|
|
280
|
-
references.push({
|
|
281
|
-
name,
|
|
282
|
-
line: nameNode.startPosition.row + 1,
|
|
283
|
-
column: nameNode.startPosition.column + 1,
|
|
284
|
-
snippet: nodeText(nameNode, source),
|
|
285
|
-
});
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
const visit = (node) => {
|
|
289
|
-
switch (node.type) {
|
|
290
|
-
case "function_definition": {
|
|
291
|
-
const nameNode = node.childForFieldName("name");
|
|
292
|
-
if (nameNode) {
|
|
293
|
-
symbols.push({
|
|
294
|
-
name: nodeText(nameNode, source),
|
|
295
|
-
kind: "function",
|
|
296
|
-
...positionOf(nameNode),
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
break;
|
|
300
|
-
}
|
|
301
|
-
case "class_definition": {
|
|
302
|
-
const nameNode = node.childForFieldName("name");
|
|
303
|
-
if (nameNode) {
|
|
304
|
-
symbols.push({
|
|
305
|
-
name: nodeText(nameNode, source),
|
|
306
|
-
kind: "class",
|
|
307
|
-
...positionOf(nameNode),
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
break;
|
|
311
|
-
}
|
|
312
|
-
case "import_statement": {
|
|
313
|
-
const moduleNode = node.childForFieldName("module");
|
|
314
|
-
if (moduleNode) {
|
|
315
|
-
dependencies.push({
|
|
316
|
-
kind: "import",
|
|
317
|
-
path: nodeText(moduleNode, source),
|
|
318
|
-
metadata: {
|
|
319
|
-
clause: nodeText(node, source),
|
|
320
|
-
},
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
break;
|
|
324
|
-
}
|
|
325
|
-
case "import_from_statement": {
|
|
326
|
-
const moduleNode = node.childForFieldName("module");
|
|
327
|
-
if (moduleNode) {
|
|
328
|
-
dependencies.push({
|
|
329
|
-
kind: "import_from",
|
|
330
|
-
path: nodeText(moduleNode, source),
|
|
331
|
-
metadata: {
|
|
332
|
-
clause: nodeText(node, source),
|
|
333
|
-
},
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
break;
|
|
337
|
-
}
|
|
338
|
-
case "call": // older parser versions
|
|
339
|
-
case "function_call": {
|
|
340
|
-
const nameNode =
|
|
341
|
-
node.childForFieldName("name") ??
|
|
342
|
-
node.namedChildren?.find((child) => child.type === "identifier") ??
|
|
343
|
-
node.child(0);
|
|
344
|
-
registerReference(nameNode);
|
|
345
|
-
break;
|
|
346
|
-
}
|
|
347
|
-
case "identifier": {
|
|
348
|
-
registerReference(node);
|
|
349
|
-
break;
|
|
350
|
-
}
|
|
351
|
-
default:
|
|
352
|
-
break;
|
|
353
|
-
}
|
|
354
|
-
for (const child of node.children) {
|
|
355
|
-
visit(child);
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
|
|
359
|
-
visit(tree.rootNode);
|
|
360
|
-
return {
|
|
361
|
-
symbols,
|
|
362
|
-
dependencies,
|
|
363
|
-
references,
|
|
364
|
-
imports,
|
|
365
|
-
exports: [],
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function parseFile(relativePath, content, language) {
|
|
370
|
-
// Try tree-sitter first (faster, more accurate)
|
|
371
|
-
const parser = getParser(language);
|
|
372
|
-
if (parser) {
|
|
373
|
-
try {
|
|
374
|
-
const tree = parser.parse(content);
|
|
375
|
-
const langType = LANGUAGE_MAP[language]?.type;
|
|
376
|
-
if (langType === "javascript" || langType === "typescript") {
|
|
377
|
-
const analysis = extractJavaScript(tree, content);
|
|
378
|
-
return {
|
|
379
|
-
...analysis,
|
|
380
|
-
language: langType,
|
|
381
|
-
definitions: analysis.symbols,
|
|
382
|
-
parser: "tree-sitter",
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
if (langType === "python") {
|
|
386
|
-
const analysis = extractPython(tree, content);
|
|
387
|
-
return {
|
|
388
|
-
...analysis,
|
|
389
|
-
language: langType,
|
|
390
|
-
definitions: analysis.symbols,
|
|
391
|
-
parser: "tree-sitter",
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
} catch (err) {
|
|
395
|
-
logger.warn({ err, file: relativePath, language }, "Tree-sitter parse failed, trying babel fallback");
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// Fallback to Babel parser for JS/TS (pure JS, no native modules)
|
|
400
|
-
const langType = LANGUAGE_MAP[language]?.type;
|
|
401
|
-
if (langType === "javascript" || langType === "typescript") {
|
|
402
|
-
try {
|
|
403
|
-
const babelParser = require("./babel-parser");
|
|
404
|
-
const result = babelParser.parseFile(relativePath, content, language);
|
|
405
|
-
if (result) {
|
|
406
|
-
logger.debug({ file: relativePath, parser: "babel" }, "Parsed with babel fallback");
|
|
407
|
-
return result;
|
|
408
|
-
}
|
|
409
|
-
} catch (err) {
|
|
410
|
-
logger.debug({ err: err.message }, "Babel parser fallback not available");
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
return null;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* Get info about available parsers
|
|
419
|
-
*/
|
|
420
|
-
function getParserInfo() {
|
|
421
|
-
const treeSitter = isTreeSitterAvailable();
|
|
422
|
-
let babel = false;
|
|
423
|
-
try {
|
|
424
|
-
const babelParser = require("./babel-parser");
|
|
425
|
-
babel = babelParser.isBabelAvailable();
|
|
426
|
-
} catch {
|
|
427
|
-
babel = false;
|
|
428
|
-
}
|
|
429
|
-
return {
|
|
430
|
-
treeSitter,
|
|
431
|
-
babel,
|
|
432
|
-
jsTs: treeSitter || babel, // JS/TS parsing available
|
|
433
|
-
python: treeSitter, // Python only via tree-sitter
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
module.exports = {
|
|
438
|
-
parseFile,
|
|
439
|
-
LANGUAGE_MAP,
|
|
440
|
-
getParser,
|
|
441
|
-
isTreeSitterAvailable,
|
|
442
|
-
getParserInfo,
|
|
443
|
-
};
|