lynkr 7.0.1 → 7.2.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.
@@ -6,41 +6,74 @@ let JavaScript = null;
6
6
  let TypeScript = null;
7
7
  let TSX = null;
8
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
+ }
9
25
 
10
26
  function getTreeSitterParser() {
27
+ if (!isTreeSitterAvailable()) {
28
+ return null;
29
+ }
11
30
  if (!Parser) {
12
- Parser = require("tree-sitter");
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
+ }
13
38
  }
14
39
  return Parser;
15
40
  }
16
41
 
17
42
  function getLanguageModule(language) {
18
- switch (language) {
19
- case "javascript":
20
- case "javascript-react":
21
- if (!JavaScript) {
22
- JavaScript = require("tree-sitter-javascript");
23
- }
24
- return JavaScript;
25
- case "typescript":
26
- if (!TypeScript) {
27
- const ts = require("tree-sitter-typescript");
28
- TypeScript = ts.typescript;
29
- }
30
- return TypeScript;
31
- case "typescript-react":
32
- if (!TSX) {
33
- const ts = require("tree-sitter-typescript");
34
- TSX = ts.tsx;
35
- }
36
- return TSX;
37
- case "python":
38
- if (!Python) {
39
- Python = require("tree-sitter-python");
40
- }
41
- return Python;
42
- default:
43
- return null;
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;
44
77
  }
45
78
  }
46
79
 
@@ -55,10 +88,14 @@ const LANGUAGE_MAP = {
55
88
  };
56
89
 
57
90
  function getParser(languageKey) {
91
+ if (!isTreeSitterAvailable()) {
92
+ return null;
93
+ }
58
94
  const entry = LANGUAGE_MAP[languageKey];
59
95
  if (!entry) return null;
60
96
  if (!parserCache[languageKey]) {
61
97
  const ParserClass = getTreeSitterParser();
98
+ if (!ParserClass) return null;
62
99
  const parser = new ParserClass();
63
100
  const language = entry.getLanguage();
64
101
  if (!language) return null;
@@ -330,37 +367,77 @@ function extractPython(tree, source) {
330
367
  }
331
368
 
332
369
  function parseFile(relativePath, content, language) {
370
+ // Try tree-sitter first (faster, more accurate)
333
371
  const parser = getParser(language);
334
- if (!parser) {
335
- return null;
336
- }
337
- try {
338
- const tree = parser.parse(content);
339
- const langType = LANGUAGE_MAP[language]?.type;
340
- if (langType === "javascript" || langType === "typescript") {
341
- const analysis = extractJavaScript(tree, content);
342
- return {
343
- ...analysis,
344
- language: langType,
345
- definitions: analysis.symbols,
346
- };
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");
347
396
  }
348
- if (langType === "python") {
349
- const analysis = extractPython(tree, content);
350
- return {
351
- ...analysis,
352
- language: langType,
353
- definitions: analysis.symbols,
354
- };
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");
355
411
  }
356
- } catch (err) {
357
- logger.warn({ err, file: relativePath, language }, "Tree-sitter parse failed");
358
412
  }
413
+
359
414
  return null;
360
415
  }
361
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
+
362
437
  module.exports = {
363
438
  parseFile,
364
439
  LANGUAGE_MAP,
365
440
  getParser,
441
+ isTreeSitterAvailable,
442
+ getParserInfo,
366
443
  };
package/src/server.js CHANGED
@@ -32,6 +32,7 @@ const { initializeHeadroom, shutdownHeadroom, getHeadroomManager } = require("./
32
32
  const { getWorkerPool, isWorkerPoolReady } = require("./workers/pool");
33
33
  const lazyLoader = require("./tools/lazy-loader");
34
34
  const { setLazyLoader } = require("./tools");
35
+ const { waitForOllama } = require("./clients/ollama-startup");
35
36
 
36
37
  // Initialize MCP
37
38
  initialiseMcp();
@@ -199,6 +200,13 @@ async function start() {
199
200
  }
200
201
 
201
202
  const app = createApp();
203
+
204
+ // Wait for Ollama if it's the configured provider or preferred for routing
205
+ const provider = config.modelProvider?.type?.toLowerCase();
206
+ if (provider === "ollama" || config.modelProvider?.preferOllama) {
207
+ await waitForOllama();
208
+ }
209
+
202
210
  const server = app.listen(config.port, () => {
203
211
  console.log(`Claude→Databricks proxy listening on http://localhost:${config.port}`);
204
212
  });