pybao-cli 1.5.45 → 1.5.47

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.
Files changed (154) hide show
  1. package/dist/REPL-45IVQWUI.js +53 -0
  2. package/dist/{acp-Y3YRP7PX.js → acp-KELESOXO.js} +30 -30
  3. package/dist/{agentsValidate-LYQDYON6.js → agentsValidate-J7PHU22S.js} +7 -7
  4. package/dist/{ask-BH7SPGEV.js → ask-ZICPHRGR.js} +30 -30
  5. package/dist/{autoUpdater-WQ7NSMS6.js → autoUpdater-6KGZQTW5.js} +3 -3
  6. package/dist/{chunk-F6A7OSLF.js → chunk-2AU4PKSQ.js} +3 -3
  7. package/dist/{chunk-2CFC3PYO.js → chunk-4VVWAA6O.js} +1 -1
  8. package/dist/{chunk-FGYA5FY5.js → chunk-57BVHCH3.js} +2 -2
  9. package/dist/{chunk-BGT7XDPE.js → chunk-5OBGGU2O.js} +3 -3
  10. package/dist/{chunk-T2V55G3O.js → chunk-5OJHTSFR.js} +3 -1
  11. package/dist/chunk-5OJHTSFR.js.map +7 -0
  12. package/dist/{chunk-6TJCSOV3.js → chunk-6JVCLWCU.js} +3 -3
  13. package/dist/{chunk-3V35SGQ7.js → chunk-7UF7PBUR.js} +1 -1
  14. package/dist/{chunk-BIRC5MFX.js → chunk-7WPBMV6W.js} +1 -1
  15. package/dist/{chunk-QYZADXNT.js → chunk-A5O2MBVW.js} +2 -2
  16. package/dist/{chunk-HFEWWAXY.js → chunk-CN443EB5.js} +1 -1
  17. package/dist/{chunk-ILSNA4QO.js → chunk-GHNPBDR6.js} +1 -1
  18. package/dist/{chunk-HPEY66LP.js → chunk-IAIXAB4N.js} +3 -3
  19. package/dist/{chunk-7XHORF4S.js → chunk-ITD4GQ6O.js} +1 -1
  20. package/dist/{chunk-SD2KLYSK.js → chunk-J3TM7T3W.js} +360 -44
  21. package/dist/chunk-J3TM7T3W.js.map +7 -0
  22. package/dist/{chunk-FZDJSTSK.js → chunk-K3AQYDRJ.js} +3 -3
  23. package/dist/{chunk-ZJJR2GKA.js → chunk-MWL7Q5HG.js} +1 -1
  24. package/dist/{chunk-7BDU4UKY.js → chunk-N2W52I56.js} +1 -1
  25. package/dist/{chunk-G57Q2LMI.js → chunk-OPEQBEHZ.js} +4 -4
  26. package/dist/{chunk-FDU3LJPV.js → chunk-OTMVCWZ2.js} +3 -3
  27. package/dist/{chunk-K4GZU7WR.js → chunk-Q2FTNJHH.js} +3 -3
  28. package/dist/{chunk-PZ3WTDXV.js → chunk-Q4WANADY.js} +2 -2
  29. package/dist/{chunk-SRWWGIOO.js → chunk-RRLBQ3XD.js} +2 -2
  30. package/dist/{chunk-FS2I7CEG.js → chunk-SD3VNTAR.js} +4 -4
  31. package/dist/{chunk-B4DLSHE7.js → chunk-T6S6TXIY.js} +3 -3
  32. package/dist/{chunk-FSHVF7L6.js → chunk-TLMCXAET.js} +1 -1
  33. package/dist/{chunk-LO7D5L6Q.js → chunk-US6EALFL.js} +2 -2
  34. package/dist/{chunk-RHUSN5MT.js → chunk-UUTMXSER.js} +1 -1
  35. package/dist/{chunk-VHDLVHEI.js → chunk-V6W537PO.js} +1 -1
  36. package/dist/{chunk-A3E3KOP5.js → chunk-VDLMXEHU.js} +638 -129
  37. package/dist/chunk-VDLMXEHU.js.map +7 -0
  38. package/dist/{chunk-LFTLSBFK.js → chunk-XIAHHC4E.js} +2 -2
  39. package/dist/{chunk-HPLKXHZG.js → chunk-ZLNJ6XFU.js} +4 -4
  40. package/dist/{cli-SPB5RXN4.js → cli-P7N4INGY.js} +90 -90
  41. package/dist/commands-BTSWDZVO.js +57 -0
  42. package/dist/{config-BMWR2IR4.js → config-XVX25KIN.js} +4 -4
  43. package/dist/{context-SNWJ6H3N.js → context-OBZ5CNGA.js} +6 -6
  44. package/dist/{conversationPersistence-L6KNQU6J.js → conversationPersistence-CB3RZIY7.js} +3 -3
  45. package/dist/{conversationTracker-LE56DVAC.js → conversationTracker-HDEFZTDC.js} +4 -4
  46. package/dist/{customCommands-4X76E7O3.js → customCommands-ELEQAM5Y.js} +4 -4
  47. package/dist/{env-FP3P46RT.js → env-FMH4AH2H.js} +2 -2
  48. package/dist/{file-KV52REUC.js → file-6TB2IASX.js} +4 -4
  49. package/dist/index.js +3 -3
  50. package/dist/{llm-OTA3UYTD.js → llm-QPAHJ643.js} +31 -31
  51. package/dist/{llmLazy-6C5RDNID.js → llmLazy-RYJWZZ7Y.js} +1 -1
  52. package/dist/{loader-OQK52QDI.js → loader-EPUS22XU.js} +4 -4
  53. package/dist/{lsp-EIMYRWRU.js → lsp-WIEWEHYU.js} +7 -6
  54. package/dist/{lspAnchor-5TJ5JKEJ.js → lspAnchor-YI3SOGER.js} +8 -8
  55. package/dist/{mcp-ESHTAOQ2.js → mcp-Q6UOFMLT.js} +7 -7
  56. package/dist/{mentionProcessor-SVY2HFAN.js → mentionProcessor-3IV63BZT.js} +5 -5
  57. package/dist/{messages-WTIERLAV.js → messages-XU4LSUWY.js} +1 -1
  58. package/dist/{model-XIQ6J7WO.js → model-JFUZ777G.js} +5 -5
  59. package/dist/{openai-MHDKXTKR.js → openai-PQN2VFKQ.js} +5 -5
  60. package/dist/{outputStyles-AOELRVFL.js → outputStyles-PJNN6AH4.js} +4 -4
  61. package/dist/{pluginRuntime-3CCOPRUZ.js → pluginRuntime-TLFHDTDH.js} +6 -6
  62. package/dist/{pluginValidation-L3NUKGCQ.js → pluginValidation-TZUKRIFW.js} +6 -6
  63. package/dist/prompts-Y4JPHIGG.js +59 -0
  64. package/dist/{pybAgentSessionLoad-DS67RJAJ.js → pybAgentSessionLoad-EFAWFGRE.js} +4 -4
  65. package/dist/{pybAgentSessionResume-UGQCQVNW.js → pybAgentSessionResume-YQSKGG3W.js} +4 -4
  66. package/dist/{pybAgentStreamJsonSession-YFYCFTMO.js → pybAgentStreamJsonSession-BYHCDZXV.js} +1 -1
  67. package/dist/{pybHooks-XUN2UYB2.js → pybHooks-ZH3DUHNO.js} +4 -4
  68. package/dist/query-SA5YQRDP.js +57 -0
  69. package/dist/{registry-XAPOPN44.js → registry-A2AB7N66.js} +5 -5
  70. package/dist/{ripgrep-DQDBRTBS.js → ripgrep-CYA5VVPU.js} +3 -3
  71. package/dist/{skillMarketplace-SUMGVSYS.js → skillMarketplace-6CDVELA7.js} +3 -3
  72. package/dist/{state-QUWQKTQZ.js → state-MDP57623.js} +2 -2
  73. package/dist/{theme-GZSN2BNR.js → theme-MYY4MVK7.js} +5 -5
  74. package/dist/{toolPermissionSettings-G5JQX7I2.js → toolPermissionSettings-ALND7SVQ.js} +6 -6
  75. package/dist/tools-6M5WFR3S.js +57 -0
  76. package/dist/{userInput-PKPNFQMN.js → userInput-FBVWRPOG.js} +32 -32
  77. package/package.json +3 -1
  78. package/dist/REPL-FPYYTXYI.js +0 -53
  79. package/dist/chunk-A3E3KOP5.js.map +0 -7
  80. package/dist/chunk-SD2KLYSK.js.map +0 -7
  81. package/dist/chunk-T2V55G3O.js.map +0 -7
  82. package/dist/commands-SWWMSOJY.js +0 -57
  83. package/dist/prompts-LCARBCSA.js +0 -59
  84. package/dist/query-63DINS6E.js +0 -57
  85. package/dist/tools-PPRXMRLD.js +0 -57
  86. /package/dist/{REPL-FPYYTXYI.js.map → REPL-45IVQWUI.js.map} +0 -0
  87. /package/dist/{acp-Y3YRP7PX.js.map → acp-KELESOXO.js.map} +0 -0
  88. /package/dist/{agentsValidate-LYQDYON6.js.map → agentsValidate-J7PHU22S.js.map} +0 -0
  89. /package/dist/{ask-BH7SPGEV.js.map → ask-ZICPHRGR.js.map} +0 -0
  90. /package/dist/{autoUpdater-WQ7NSMS6.js.map → autoUpdater-6KGZQTW5.js.map} +0 -0
  91. /package/dist/{chunk-F6A7OSLF.js.map → chunk-2AU4PKSQ.js.map} +0 -0
  92. /package/dist/{chunk-2CFC3PYO.js.map → chunk-4VVWAA6O.js.map} +0 -0
  93. /package/dist/{chunk-FGYA5FY5.js.map → chunk-57BVHCH3.js.map} +0 -0
  94. /package/dist/{chunk-BGT7XDPE.js.map → chunk-5OBGGU2O.js.map} +0 -0
  95. /package/dist/{chunk-6TJCSOV3.js.map → chunk-6JVCLWCU.js.map} +0 -0
  96. /package/dist/{chunk-3V35SGQ7.js.map → chunk-7UF7PBUR.js.map} +0 -0
  97. /package/dist/{chunk-BIRC5MFX.js.map → chunk-7WPBMV6W.js.map} +0 -0
  98. /package/dist/{chunk-QYZADXNT.js.map → chunk-A5O2MBVW.js.map} +0 -0
  99. /package/dist/{chunk-HFEWWAXY.js.map → chunk-CN443EB5.js.map} +0 -0
  100. /package/dist/{chunk-ILSNA4QO.js.map → chunk-GHNPBDR6.js.map} +0 -0
  101. /package/dist/{chunk-HPEY66LP.js.map → chunk-IAIXAB4N.js.map} +0 -0
  102. /package/dist/{chunk-7XHORF4S.js.map → chunk-ITD4GQ6O.js.map} +0 -0
  103. /package/dist/{chunk-FZDJSTSK.js.map → chunk-K3AQYDRJ.js.map} +0 -0
  104. /package/dist/{chunk-ZJJR2GKA.js.map → chunk-MWL7Q5HG.js.map} +0 -0
  105. /package/dist/{chunk-7BDU4UKY.js.map → chunk-N2W52I56.js.map} +0 -0
  106. /package/dist/{chunk-G57Q2LMI.js.map → chunk-OPEQBEHZ.js.map} +0 -0
  107. /package/dist/{chunk-FDU3LJPV.js.map → chunk-OTMVCWZ2.js.map} +0 -0
  108. /package/dist/{chunk-K4GZU7WR.js.map → chunk-Q2FTNJHH.js.map} +0 -0
  109. /package/dist/{chunk-PZ3WTDXV.js.map → chunk-Q4WANADY.js.map} +0 -0
  110. /package/dist/{chunk-SRWWGIOO.js.map → chunk-RRLBQ3XD.js.map} +0 -0
  111. /package/dist/{chunk-FS2I7CEG.js.map → chunk-SD3VNTAR.js.map} +0 -0
  112. /package/dist/{chunk-B4DLSHE7.js.map → chunk-T6S6TXIY.js.map} +0 -0
  113. /package/dist/{chunk-FSHVF7L6.js.map → chunk-TLMCXAET.js.map} +0 -0
  114. /package/dist/{chunk-LO7D5L6Q.js.map → chunk-US6EALFL.js.map} +0 -0
  115. /package/dist/{chunk-RHUSN5MT.js.map → chunk-UUTMXSER.js.map} +0 -0
  116. /package/dist/{chunk-VHDLVHEI.js.map → chunk-V6W537PO.js.map} +0 -0
  117. /package/dist/{chunk-LFTLSBFK.js.map → chunk-XIAHHC4E.js.map} +0 -0
  118. /package/dist/{chunk-HPLKXHZG.js.map → chunk-ZLNJ6XFU.js.map} +0 -0
  119. /package/dist/{cli-SPB5RXN4.js.map → cli-P7N4INGY.js.map} +0 -0
  120. /package/dist/{commands-SWWMSOJY.js.map → commands-BTSWDZVO.js.map} +0 -0
  121. /package/dist/{config-BMWR2IR4.js.map → config-XVX25KIN.js.map} +0 -0
  122. /package/dist/{context-SNWJ6H3N.js.map → context-OBZ5CNGA.js.map} +0 -0
  123. /package/dist/{conversationPersistence-L6KNQU6J.js.map → conversationPersistence-CB3RZIY7.js.map} +0 -0
  124. /package/dist/{conversationTracker-LE56DVAC.js.map → conversationTracker-HDEFZTDC.js.map} +0 -0
  125. /package/dist/{customCommands-4X76E7O3.js.map → customCommands-ELEQAM5Y.js.map} +0 -0
  126. /package/dist/{env-FP3P46RT.js.map → env-FMH4AH2H.js.map} +0 -0
  127. /package/dist/{file-KV52REUC.js.map → file-6TB2IASX.js.map} +0 -0
  128. /package/dist/{llm-OTA3UYTD.js.map → llm-QPAHJ643.js.map} +0 -0
  129. /package/dist/{llmLazy-6C5RDNID.js.map → llmLazy-RYJWZZ7Y.js.map} +0 -0
  130. /package/dist/{loader-OQK52QDI.js.map → loader-EPUS22XU.js.map} +0 -0
  131. /package/dist/{lsp-EIMYRWRU.js.map → lsp-WIEWEHYU.js.map} +0 -0
  132. /package/dist/{lspAnchor-5TJ5JKEJ.js.map → lspAnchor-YI3SOGER.js.map} +0 -0
  133. /package/dist/{mcp-ESHTAOQ2.js.map → mcp-Q6UOFMLT.js.map} +0 -0
  134. /package/dist/{mentionProcessor-SVY2HFAN.js.map → mentionProcessor-3IV63BZT.js.map} +0 -0
  135. /package/dist/{messages-WTIERLAV.js.map → messages-XU4LSUWY.js.map} +0 -0
  136. /package/dist/{model-XIQ6J7WO.js.map → model-JFUZ777G.js.map} +0 -0
  137. /package/dist/{openai-MHDKXTKR.js.map → openai-PQN2VFKQ.js.map} +0 -0
  138. /package/dist/{outputStyles-AOELRVFL.js.map → outputStyles-PJNN6AH4.js.map} +0 -0
  139. /package/dist/{pluginRuntime-3CCOPRUZ.js.map → pluginRuntime-TLFHDTDH.js.map} +0 -0
  140. /package/dist/{pluginValidation-L3NUKGCQ.js.map → pluginValidation-TZUKRIFW.js.map} +0 -0
  141. /package/dist/{prompts-LCARBCSA.js.map → prompts-Y4JPHIGG.js.map} +0 -0
  142. /package/dist/{pybAgentSessionLoad-DS67RJAJ.js.map → pybAgentSessionLoad-EFAWFGRE.js.map} +0 -0
  143. /package/dist/{pybAgentSessionResume-UGQCQVNW.js.map → pybAgentSessionResume-YQSKGG3W.js.map} +0 -0
  144. /package/dist/{pybAgentStreamJsonSession-YFYCFTMO.js.map → pybAgentStreamJsonSession-BYHCDZXV.js.map} +0 -0
  145. /package/dist/{pybHooks-XUN2UYB2.js.map → pybHooks-ZH3DUHNO.js.map} +0 -0
  146. /package/dist/{query-63DINS6E.js.map → query-SA5YQRDP.js.map} +0 -0
  147. /package/dist/{registry-XAPOPN44.js.map → registry-A2AB7N66.js.map} +0 -0
  148. /package/dist/{ripgrep-DQDBRTBS.js.map → ripgrep-CYA5VVPU.js.map} +0 -0
  149. /package/dist/{skillMarketplace-SUMGVSYS.js.map → skillMarketplace-6CDVELA7.js.map} +0 -0
  150. /package/dist/{state-QUWQKTQZ.js.map → state-MDP57623.js.map} +0 -0
  151. /package/dist/{theme-GZSN2BNR.js.map → theme-MYY4MVK7.js.map} +0 -0
  152. /package/dist/{toolPermissionSettings-G5JQX7I2.js.map → toolPermissionSettings-ALND7SVQ.js.map} +0 -0
  153. /package/dist/{tools-PPRXMRLD.js.map → tools-6M5WFR3S.js.map} +0 -0
  154. /package/dist/{userInput-PKPNFQMN.js.map → userInput-FBVWRPOG.js.map} +0 -0
@@ -1,25 +1,28 @@
1
1
  import { createRequire as __pybCreateRequire } from "node:module";
2
2
  const require = __pybCreateRequire(import.meta.url);
3
+ import {
4
+ emitTelemetryEvent
5
+ } from "./chunk-TFHFYID3.js";
3
6
  import {
4
7
  LspServerRegistry,
5
8
  findNearestRoot,
6
9
  getInstallNotices
7
- } from "./chunk-BGT7XDPE.js";
10
+ } from "./chunk-5OBGGU2O.js";
8
11
  import {
9
12
  levenshtein
10
13
  } from "./chunk-UZ34JEUK.js";
11
14
  import {
12
15
  debug
13
- } from "./chunk-ZJJR2GKA.js";
16
+ } from "./chunk-MWL7Q5HG.js";
14
17
  import {
15
18
  getCwd,
16
19
  getSessionRoot
17
- } from "./chunk-HFEWWAXY.js";
20
+ } from "./chunk-CN443EB5.js";
18
21
 
19
22
  // src/lsp/index.ts
20
- import { extname as extname2 } from "path";
21
- import { pathToFileURL as pathToFileURL2 } from "url";
22
- import { readFile as readFile4 } from "fs/promises";
23
+ import { extname as extname3 } from "path";
24
+ import { pathToFileURL as pathToFileURL3 } from "url";
25
+ import { readFile as readFile5 } from "fs/promises";
23
26
  import * as http from "http";
24
27
  import { createHash as createHash4 } from "crypto";
25
28
 
@@ -565,7 +568,7 @@ var LspClientManager = class _LspClientManager {
565
568
  const safeCwd = /[^\x00-\x7F]/.test(resolvedRoot) ? process.cwd() : resolvedRoot;
566
569
  let initOpts = serverInfo.initializationOptions;
567
570
  if (serverInfo.id === "pyright" || serverInfo.id === "ty") {
568
- const { detectPythonVenv } = await import("./registry-XAPOPN44.js");
571
+ const { detectPythonVenv } = await import("./registry-A2AB7N66.js");
569
572
  const pythonPath = detectPythonVenv(resolvedRoot);
570
573
  if (pythonPath) {
571
574
  initOpts = { ...initOpts ?? {}, pythonPath };
@@ -660,12 +663,12 @@ var LspClientManager = class _LspClientManager {
660
663
  }
661
664
  return uri;
662
665
  };
663
- const flattenSymbols = (items, output = []) => {
666
+ const flattenSymbols2 = (items, output = []) => {
664
667
  for (const item of items) {
665
668
  if (!item || typeof item !== "object") continue;
666
669
  output.push(item);
667
670
  if (Array.isArray(item.children) && item.children.length > 0) {
668
- flattenSymbols(item.children, output);
671
+ flattenSymbols2(item.children, output);
669
672
  }
670
673
  }
671
674
  return output;
@@ -687,7 +690,7 @@ var LspClientManager = class _LspClientManager {
687
690
  documentSymbols = await this.documentSymbol(filePath, rootPath) ?? [];
688
691
  documentCache.set(filePath, documentSymbols);
689
692
  }
690
- const flat = flattenSymbols(documentSymbols);
693
+ const flat = flattenSymbols2(documentSymbols);
691
694
  for (const sym of symbols) {
692
695
  let match = flat.find(
693
696
  (item) => item?.name === sym.name && (sym.kind === void 0 || item?.kind === sym.kind)
@@ -1416,7 +1419,8 @@ function formatGenericDiagnosticsResult(diagnostics) {
1416
1419
  return { formatted: "No diagnostics found.", resultCount: 0, fileCount: 0 };
1417
1420
  }
1418
1421
  const lines = diagnostics.map((d) => {
1419
- return `[${d.severity === 1 ? "Error" : d.severity === 2 ? "Warning" : "Info"}] Line ${d.range.start.line + 1}: ${d.message}`;
1422
+ const suggestion = d.hint ? ` Suggestion: ${d.hint}` : "";
1423
+ return `[${d.severity === 1 ? "Error" : d.severity === 2 ? "Warning" : "Info"}] Line ${d.range.start.line + 1}: ${d.message}${suggestion}`;
1420
1424
  });
1421
1425
  return {
1422
1426
  formatted: ["Diagnostics:", ...lines].join("\n"),
@@ -2416,9 +2420,234 @@ var ScopeAnalyzer = class {
2416
2420
  }
2417
2421
  };
2418
2422
 
2423
+ // src/lsp/fallbackResult.ts
2424
+ function inferQuality(source) {
2425
+ if (source === "lsp" || source === "hybrid") return "full";
2426
+ if (source === "tree-sitter") return "partial";
2427
+ return "minimal";
2428
+ }
2429
+ function inferConfidence(source) {
2430
+ if (source === "lsp" || source === "hybrid" || source === "tree-sitter") return "high";
2431
+ if (source === "token-scan") return "low";
2432
+ return "low";
2433
+ }
2434
+ function buildEnhancedFallbackResult(input) {
2435
+ return {
2436
+ ...input,
2437
+ quality: input.quality ?? inferQuality(input.source),
2438
+ confidence: input.confidence ?? inferConfidence(input.source)
2439
+ };
2440
+ }
2441
+ function toLspFallbackResultEvent(input) {
2442
+ return {
2443
+ channel: "lsp",
2444
+ phase: "LSP_FALLBACK_RESULT",
2445
+ timestamp: input.timestamp ?? Date.now(),
2446
+ data: {
2447
+ operation: input.operation,
2448
+ source: input.result.source ?? "none",
2449
+ quality: input.result.quality ?? "minimal",
2450
+ confidence: input.result.confidence ?? "low",
2451
+ reason: input.result.fallbackReason ?? "UNKNOWN",
2452
+ language: input.language,
2453
+ duration: input.duration
2454
+ }
2455
+ };
2456
+ }
2457
+
2458
+ // src/lsp/treeSitterFallback/index.ts
2459
+ function formatFallbackNotice(operation, reason, capability, detail) {
2460
+ const base = `Fallback ${operation} (reason: ${reason}, capability: ${capability})`;
2461
+ return detail ? `${base} ${detail}` : base;
2462
+ }
2463
+ function buildFallbackResult(input) {
2464
+ return buildEnhancedFallbackResult({
2465
+ formatted: formatFallbackNotice(
2466
+ input.operation,
2467
+ input.reason,
2468
+ input.capability,
2469
+ input.detail
2470
+ ),
2471
+ resultCount: input.resultCount ?? 0,
2472
+ fileCount: input.fileCount ?? 0,
2473
+ source: input.source,
2474
+ fallbackReason: input.reason,
2475
+ fallbackSuggestion: input.fallbackSuggestion
2476
+ });
2477
+ }
2478
+
2479
+ // src/lsp/treeSitterFallback/diagnosticsHints.ts
2480
+ var INCLUDE_PATTERNS = [
2481
+ /missing.*bracket/i,
2482
+ /missing.*brace/i,
2483
+ /missing.*semicolon/i,
2484
+ /unclosed.*string/i,
2485
+ /missing.*keyword/i
2486
+ ];
2487
+ var EXCLUDE_PATTERNS = [
2488
+ /type.*mismatch/i,
2489
+ /undefined/i,
2490
+ /unused/i,
2491
+ /import.*not.*found/i
2492
+ ];
2493
+ function inferDiagnosticsHint(message) {
2494
+ const text = String(message ?? "");
2495
+ if (!text) return void 0;
2496
+ if (EXCLUDE_PATTERNS.some((pattern) => pattern.test(text))) {
2497
+ return void 0;
2498
+ }
2499
+ if (/missing.*semicolon/i.test(text)) {
2500
+ return "Insert a semicolon at the end of the statement.";
2501
+ }
2502
+ if (/missing.*bracket/i.test(text)) {
2503
+ return "Add the missing bracket to complete the expression.";
2504
+ }
2505
+ if (/missing.*brace/i.test(text)) {
2506
+ return "Add the missing brace to close the current block.";
2507
+ }
2508
+ if (/unclosed.*string/i.test(text)) {
2509
+ return "Close the string literal with a matching quote.";
2510
+ }
2511
+ if (/missing.*keyword/i.test(text)) {
2512
+ return "Add the required language keyword to complete the statement.";
2513
+ }
2514
+ if (INCLUDE_PATTERNS.some((pattern) => pattern.test(text))) {
2515
+ return "Apply the syntax fix near this location and rerun diagnostics.";
2516
+ }
2517
+ return void 0;
2518
+ }
2519
+ function attachDiagnosticsHints(diagnostics) {
2520
+ return diagnostics.map((item) => {
2521
+ const hint = inferDiagnosticsHint(String(item.message ?? ""));
2522
+ if (!hint) return item;
2523
+ return {
2524
+ ...item,
2525
+ hint
2526
+ };
2527
+ });
2528
+ }
2529
+
2530
+ // src/lsp/treeSitterFallback/workspaceSymbolIndex.ts
2531
+ import { extname as extname2 } from "node:path";
2532
+ import { readdir as readdir3, readFile as readFile4, stat } from "node:fs/promises";
2533
+ import { pathToFileURL as pathToFileURL2 } from "node:url";
2534
+ var DEFAULT_MAX_FILES = 500;
2535
+ var DEFAULT_MAX_FILE_SIZE_BYTES = 100 * 1024;
2536
+ var DEFAULT_MAX_INDEX_TIME_MS = 3e4;
2537
+ var DEFAULT_EXCLUDE = ["node_modules", "dist", ".git", ".pyb"];
2538
+ var KIND_TO_LSP = {
2539
+ Class: 5,
2540
+ Function: 12,
2541
+ Interface: 11,
2542
+ Enum: 10,
2543
+ Variable: 13
2544
+ };
2545
+ function getAllowedExtensions() {
2546
+ return /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".json"]);
2547
+ }
2548
+ function shouldExcludePath(pathLike) {
2549
+ const lower = pathLike.toLowerCase();
2550
+ return DEFAULT_EXCLUDE.some((item) => lower.includes(`\\${item.toLowerCase()}\\`) || lower.endsWith(`\\${item.toLowerCase()}`));
2551
+ }
2552
+ function normalizeRegexResult(match) {
2553
+ if (!match) return null;
2554
+ const name = String(match[1] ?? "").trim();
2555
+ return name.length > 0 ? name : null;
2556
+ }
2557
+ function parseSymbolsFromContent(content, uri) {
2558
+ const lines = content.split("\n");
2559
+ const symbols = [];
2560
+ for (let i = 0; i < lines.length; i += 1) {
2561
+ const line = lines[i] ?? "";
2562
+ const className = normalizeRegexResult(/(?:export\s+)?class\s+([A-Za-z_]\w*)/.exec(line));
2563
+ if (className) {
2564
+ symbols.push({ name: className, kind: "Class", line: i, character: line.indexOf(className), uri });
2565
+ }
2566
+ const functionName = normalizeRegexResult(/(?:export\s+)?function\s+([A-Za-z_]\w*)/.exec(line));
2567
+ if (functionName) {
2568
+ symbols.push({ name: functionName, kind: "Function", line: i, character: line.indexOf(functionName), uri });
2569
+ }
2570
+ const interfaceName = normalizeRegexResult(/(?:export\s+)?interface\s+([A-Za-z_]\w*)/.exec(line));
2571
+ if (interfaceName) {
2572
+ symbols.push({ name: interfaceName, kind: "Interface", line: i, character: line.indexOf(interfaceName), uri });
2573
+ }
2574
+ const enumName = normalizeRegexResult(/(?:export\s+)?enum\s+([A-Za-z_]\w*)/.exec(line));
2575
+ if (enumName) {
2576
+ symbols.push({ name: enumName, kind: "Enum", line: i, character: line.indexOf(enumName), uri });
2577
+ }
2578
+ const variableName = normalizeRegexResult(/(?:export\s+)?(?:const|let|var)\s+([A-Za-z_]\w*)/.exec(line));
2579
+ if (variableName) {
2580
+ symbols.push({ name: variableName, kind: "Variable", line: i, character: line.indexOf(variableName), uri });
2581
+ }
2582
+ }
2583
+ return symbols;
2584
+ }
2585
+ async function collectFiles(rootPath, maxFiles, maxIndexTimeMs) {
2586
+ const files = [];
2587
+ const queue = [rootPath];
2588
+ const allowed = getAllowedExtensions();
2589
+ const startedAt = Date.now();
2590
+ while (queue.length > 0 && files.length < maxFiles) {
2591
+ if (Date.now() - startedAt > maxIndexTimeMs) break;
2592
+ const current = queue.shift();
2593
+ if (!current) continue;
2594
+ if (shouldExcludePath(current)) continue;
2595
+ const entries = await readdir3(current, { withFileTypes: true });
2596
+ for (const entry of entries) {
2597
+ const next = `${current}\\${entry.name}`;
2598
+ if (shouldExcludePath(next)) continue;
2599
+ if (entry.isDirectory()) {
2600
+ queue.push(next);
2601
+ } else if (entry.isFile() && allowed.has(extname2(entry.name).toLowerCase())) {
2602
+ files.push(next);
2603
+ if (files.length >= maxFiles) break;
2604
+ }
2605
+ }
2606
+ }
2607
+ return files;
2608
+ }
2609
+ async function searchWorkspaceSymbolsWithLightweightIndex(input) {
2610
+ const query = String(input.query ?? "").trim().toLowerCase();
2611
+ if (!query) return [];
2612
+ const maxFiles = input.maxFiles ?? Number(process.env.PYB_TS_WORKSPACE_SYMBOL_MAX_FILES ?? DEFAULT_MAX_FILES);
2613
+ const maxFileSizeBytes = input.maxFileSizeBytes ?? Number(process.env.PYB_TS_WORKSPACE_SYMBOL_MAX_FILE_SIZE ?? DEFAULT_MAX_FILE_SIZE_BYTES);
2614
+ const maxIndexTimeMs = input.maxIndexTimeMs ?? Number(process.env.PYB_TS_WORKSPACE_SYMBOL_MAX_INDEX_TIME_MS ?? DEFAULT_MAX_INDEX_TIME_MS);
2615
+ const files = await collectFiles(input.rootPath, maxFiles, maxIndexTimeMs);
2616
+ const matched = [];
2617
+ const startedAt = Date.now();
2618
+ for (const filePath of files) {
2619
+ if (Date.now() - startedAt > maxIndexTimeMs) break;
2620
+ const fileStat = await stat(filePath);
2621
+ if (fileStat.size > maxFileSizeBytes) continue;
2622
+ const content = await readFile4(filePath, "utf8");
2623
+ const uri = pathToFileURL2(filePath).toString();
2624
+ const symbols = parseSymbolsFromContent(content, uri);
2625
+ for (const symbol of symbols) {
2626
+ if (!symbol.name.toLowerCase().includes(query)) continue;
2627
+ matched.push({
2628
+ name: symbol.name,
2629
+ kind: KIND_TO_LSP[symbol.kind],
2630
+ uri: symbol.uri,
2631
+ location: {
2632
+ uri: symbol.uri,
2633
+ range: {
2634
+ start: { line: symbol.line, character: Math.max(0, symbol.character) },
2635
+ end: { line: symbol.line, character: Math.max(0, symbol.character + symbol.name.length) }
2636
+ }
2637
+ },
2638
+ range: {
2639
+ start: { line: symbol.line, character: Math.max(0, symbol.character) },
2640
+ end: { line: symbol.line, character: Math.max(0, symbol.character + symbol.name.length) }
2641
+ }
2642
+ });
2643
+ }
2644
+ }
2645
+ return matched;
2646
+ }
2647
+
2419
2648
  // src/lsp/index.ts
2420
2649
  function normalizeUri(filePath) {
2421
- let uri = pathToFileURL2(filePath).href;
2650
+ let uri = pathToFileURL3(filePath).href;
2422
2651
  if (process.platform === "win32") {
2423
2652
  uri = uri.replace(/^file:\/\/\/([a-zA-Z]):\//, (_match, drive) => {
2424
2653
  return `file:///${drive.toLowerCase()}%3A/`;
@@ -2566,9 +2795,39 @@ ${truncationLine}` : parts.join("\n");
2566
2795
  fileCount: 1
2567
2796
  };
2568
2797
  }
2569
- function formatFallbackNotice(operation, reason, capability, detail) {
2570
- const base = `Fallback ${operation} (reason: ${reason}, capability: ${capability})`;
2571
- return detail ? `${base} ${detail}` : base;
2798
+ function formatFallbackNotice2(operation, reason, capability, detail) {
2799
+ return formatFallbackNotice(operation, reason, capability, detail);
2800
+ }
2801
+ function emitFallbackTelemetry(operation, filePath, startedAt, result) {
2802
+ emitTelemetryEvent(
2803
+ toLspFallbackResultEvent({
2804
+ operation,
2805
+ language: ParserRegistry.getLanguage(filePath) ?? "unknown",
2806
+ duration: Date.now() - startedAt,
2807
+ result
2808
+ })
2809
+ );
2810
+ }
2811
+ function finalizeFallbackResult(operation, filePath, startedAt, result) {
2812
+ emitFallbackTelemetry(operation, filePath, startedAt, result);
2813
+ return result;
2814
+ }
2815
+ function isWorkspaceSymbolFallbackEnabled() {
2816
+ const raw = String(process.env.PYB_TS_WORKSPACE_SYMBOL_FALLBACK ?? "").trim().toLowerCase();
2817
+ return raw === "1" || raw === "true";
2818
+ }
2819
+ function toDocumentSymbolTreeSitterFallback(filePath, fallbackReason, formatted) {
2820
+ return buildEnhancedFallbackResult({
2821
+ ...formatted,
2822
+ formatted: formatFallbackNotice2(
2823
+ "documentSymbol",
2824
+ fallbackReason,
2825
+ "tree-sitter symbols",
2826
+ formatted.formatted
2827
+ ),
2828
+ source: "tree-sitter",
2829
+ fallbackReason
2830
+ });
2572
2831
  }
2573
2832
  var fastPathFailures = /* @__PURE__ */ new Map();
2574
2833
  var fastPathLastFallbackReason = /* @__PURE__ */ new Map();
@@ -2887,11 +3146,156 @@ function findSymbolAtPosition(symbols, line, character) {
2887
3146
  for (const sym of symbols) visit(sym);
2888
3147
  return matched;
2889
3148
  }
3149
+ function flattenSymbols(symbols) {
3150
+ const result = [];
3151
+ const visit = (node) => {
3152
+ if (!node || typeof node !== "object") return;
3153
+ result.push(node);
3154
+ if (Array.isArray(node.children)) {
3155
+ for (const child of node.children) {
3156
+ visit(child);
3157
+ }
3158
+ }
3159
+ };
3160
+ for (const symbol of symbols) {
3161
+ visit(symbol);
3162
+ }
3163
+ return result;
3164
+ }
3165
+ function getSymbolLocation(symbol, filePath) {
3166
+ const range = symbol?.selectionRange ?? symbol?.range ?? symbol?.location?.range;
3167
+ if (!range) return null;
3168
+ return {
3169
+ uri: normalizeUri(filePath),
3170
+ range
3171
+ };
3172
+ }
3173
+ function pickNearestSymbolByLine(symbols, line) {
3174
+ if (!symbols.length) return null;
3175
+ return [...symbols].sort((a, b) => {
3176
+ const aLine = a?.selectionRange?.start?.line ?? a?.range?.start?.line ?? 0;
3177
+ const bLine = b?.selectionRange?.start?.line ?? b?.range?.start?.line ?? 0;
3178
+ return Math.abs(aLine - line) - Math.abs(bLine - line);
3179
+ })[0];
3180
+ }
3181
+ async function buildGoToDefinitionUnavailableFallback(input) {
3182
+ const content = await readFile5(input.filePath, "utf-8");
3183
+ const lines = content.split("\n");
3184
+ const zeroLine = input.line - 1;
3185
+ const zeroChar = input.character - 1;
3186
+ const token = extractTokenAtPosition(lines, zeroLine, zeroChar);
3187
+ const symbols = await TreeSitterLspAdapter.getDocumentSymbols(input.filePath);
3188
+ const flat = flattenSymbols(symbols).filter((sym) => typeof sym?.name === "string");
3189
+ if (token) {
3190
+ const exactMatches = flat.filter((sym) => sym.name === token);
3191
+ if (exactMatches.length === 1) {
3192
+ const location = getSymbolLocation(exactMatches[0], input.filePath);
3193
+ if (location) {
3194
+ const formatted = formatGenericDefinitionResult(location);
3195
+ return buildEnhancedFallbackResult({
3196
+ ...formatted,
3197
+ source: "tree-sitter",
3198
+ fallbackReason: input.fallbackReason,
3199
+ fallbackSuggestion: "Enable LSP for cross-file definition resolution.",
3200
+ confidence: "high"
3201
+ });
3202
+ }
3203
+ }
3204
+ if (exactMatches.length > 1) {
3205
+ const selected = pickNearestSymbolByLine(exactMatches, zeroLine);
3206
+ const location = selected ? getSymbolLocation(selected, input.filePath) : null;
3207
+ if (location) {
3208
+ const formatted = formatGenericDefinitionResult(location);
3209
+ return buildEnhancedFallbackResult({
3210
+ ...formatted,
3211
+ source: "tree-sitter",
3212
+ fallbackReason: input.fallbackReason,
3213
+ fallbackSuggestion: "Multiple same-name symbols found; enable LSP for precise semantic disambiguation.",
3214
+ confidence: "medium"
3215
+ });
3216
+ }
3217
+ }
3218
+ const tokenMatches = findTokenOccurrencesInLines(token, lines);
3219
+ if (tokenMatches.length > 0) {
3220
+ const selected = [...tokenMatches].sort((a, b) => a.line - b.line || a.start - b.start)[0];
3221
+ const formatted = formatGenericDefinitionResult({
3222
+ uri: normalizeUri(input.filePath),
3223
+ range: {
3224
+ start: { line: selected.line, character: selected.start },
3225
+ end: { line: selected.line, character: selected.end }
3226
+ }
3227
+ });
3228
+ return buildEnhancedFallbackResult({
3229
+ ...formatted,
3230
+ source: "token-scan",
3231
+ fallbackReason: input.fallbackReason,
3232
+ fallbackSuggestion: "Token match fallback is low confidence; enable LSP for semantic accuracy.",
3233
+ confidence: "low"
3234
+ });
3235
+ }
3236
+ }
3237
+ return buildFallbackResult({
3238
+ operation: "goToDefinition",
3239
+ reason: input.fallbackReason,
3240
+ capability: "none",
3241
+ source: "none",
3242
+ detail: "No same-file definition candidate found.",
3243
+ fallbackSuggestion: "Retry with LSP enabled or provide a narrower symbol context."
3244
+ });
3245
+ }
3246
+ async function buildHoverUnavailableFallback(input) {
3247
+ const symbols = await TreeSitterLspAdapter.getDocumentSymbols(input.filePath);
3248
+ const symbol = findSymbolAtPosition(symbols, input.line - 1, input.character - 1);
3249
+ if (symbol) {
3250
+ const range = symbol?.range;
3251
+ const rangeText = range ? `${range.start.line + 1}:${range.start.character + 1}-${range.end.line + 1}:${range.end.character + 1}` : "unknown";
3252
+ const hoverFormatted = formatGenericHoverResult(
3253
+ {
3254
+ contents: `name: ${symbol.name}
3255
+ kind: ${symbol.kind}
3256
+ range: ${rangeText}`
3257
+ },
3258
+ input.line,
3259
+ input.character
3260
+ );
3261
+ return buildEnhancedFallbackResult({
3262
+ ...hoverFormatted,
3263
+ source: "tree-sitter",
3264
+ fallbackReason: input.fallbackReason,
3265
+ fallbackSuggestion: "Enable LSP to get full type and documentation hover content.",
3266
+ confidence: "high"
3267
+ });
3268
+ }
3269
+ const content = await readFile5(input.filePath, "utf-8");
3270
+ const token = extractTokenAtPosition(content.split("\n"), input.line - 1, input.character - 1);
3271
+ if (token) {
3272
+ const hoverFormatted = formatGenericHoverResult(
3273
+ { contents: `token: ${token}` },
3274
+ input.line,
3275
+ input.character
3276
+ );
3277
+ return buildEnhancedFallbackResult({
3278
+ ...hoverFormatted,
3279
+ source: "token-scan",
3280
+ fallbackReason: input.fallbackReason,
3281
+ fallbackSuggestion: "Token-only hover is minimal; enable LSP for semantic hover details.",
3282
+ confidence: "low"
3283
+ });
3284
+ }
3285
+ return buildFallbackResult({
3286
+ operation: "hover",
3287
+ reason: input.fallbackReason,
3288
+ capability: "none",
3289
+ source: "none",
3290
+ detail: "No hover candidate found.",
3291
+ fallbackSuggestion: "Retry with LSP enabled for full hover support."
3292
+ });
3293
+ }
2890
3294
  async function getTreeSitterDiagnostics(filePath) {
2891
3295
  const lang = ParserRegistry.getLanguage(filePath);
2892
3296
  if (!lang) return [];
2893
3297
  const parser = await loadLanguage(lang);
2894
- const content = await readFile4(filePath, "utf-8");
3298
+ const content = await readFile5(filePath, "utf-8");
2895
3299
  const tree = parser.parse(content);
2896
3300
  if (!tree) return [];
2897
3301
  const diagnostics = [];
@@ -2905,9 +3309,24 @@ async function getTreeSitterDiagnostics(filePath) {
2905
3309
  };
2906
3310
  const key = `${range.start.line}:${range.start.character}:${range.end.line}:${range.end.character}:${node.type}`;
2907
3311
  if (!seen.has(key)) {
3312
+ const lowerType = String(node.type ?? "").toLowerCase();
3313
+ let message = `Syntax error near ${node.type}`;
3314
+ if (node.isMissing) {
3315
+ if (lowerType.includes(";")) {
3316
+ message = "missing semicolon near statement";
3317
+ } else if (lowerType.includes(")") || lowerType.includes("(")) {
3318
+ message = "missing bracket near expression";
3319
+ } else if (lowerType.includes("}") || lowerType.includes("{")) {
3320
+ message = "missing brace near block";
3321
+ } else if (lowerType.includes("string") || lowerType.includes('"') || lowerType.includes("'")) {
3322
+ message = "unclosed string literal";
3323
+ } else {
3324
+ message = `missing keyword near ${node.type}`;
3325
+ }
3326
+ }
2908
3327
  diagnostics.push({
2909
3328
  range,
2910
- message: `Syntax error near ${node.type}`,
3329
+ message,
2911
3330
  severity: 1
2912
3331
  });
2913
3332
  seen.add(key);
@@ -2918,7 +3337,7 @@ async function getTreeSitterDiagnostics(filePath) {
2918
3337
  }
2919
3338
  };
2920
3339
  visit(tree.rootNode);
2921
- return diagnostics;
3340
+ return attachDiagnosticsHints(diagnostics);
2922
3341
  }
2923
3342
  function sortWorkspaceSymbols(symbols) {
2924
3343
  return [...symbols].sort((a, b) => {
@@ -3049,7 +3468,7 @@ var LspAPI = {
3049
3468
  input.filePath,
3050
3469
  rootPath
3051
3470
  );
3052
- const ext = extname2(input.filePath);
3471
+ const ext = extname3(input.filePath);
3053
3472
  const fallbackServer = LspServerRegistry.getInstance().getServerForExtension(ext);
3054
3473
  const serverId = client ? client.serverId ?? fallbackServer?.id ?? "unknown" : fallbackServer?.id ?? "unknown";
3055
3474
  const recordAttempt = (operation) => {
@@ -3275,8 +3694,56 @@ var LspAPI = {
3275
3694
  }
3276
3695
  }
3277
3696
  const fallbackOperation = input.operation;
3697
+ const fallbackStartedAt = Date.now();
3278
3698
  recordAttempt(input.operation);
3279
3699
  recordFailure(input.operation, "unavailable");
3700
+ if (fallbackOperation === "workspaceSymbol") {
3701
+ const query = String(input.query ?? "").trim();
3702
+ if (!isWorkspaceSymbolFallbackEnabled()) {
3703
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildFallbackResult({
3704
+ operation: "workspaceSymbol",
3705
+ reason: "lsp-unavailable",
3706
+ capability: "none",
3707
+ source: "none",
3708
+ detail: `No LSP server available for file type: ${ext}. Workspace fallback is disabled.`,
3709
+ fallbackSuggestion: "Set PYB_TS_WORKSPACE_SYMBOL_FALLBACK=1 to enable lightweight index fallback."
3710
+ }));
3711
+ }
3712
+ try {
3713
+ const symbols = await searchWorkspaceSymbolsWithLightweightIndex({
3714
+ rootPath,
3715
+ query
3716
+ });
3717
+ if (symbols.length > 0) {
3718
+ const formatted = formatGenericDocumentSymbolResult(symbols);
3719
+ const fileCount = new Set(symbols.map((item) => String(item.uri ?? item.location?.uri ?? ""))).size;
3720
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildEnhancedFallbackResult({
3721
+ ...formatted,
3722
+ fileCount,
3723
+ source: "tree-sitter",
3724
+ fallbackReason: "lsp-unavailable",
3725
+ fallbackSuggestion: "Lightweight index fallback is partial; enable LSP for full workspace semantics."
3726
+ }));
3727
+ }
3728
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildFallbackResult({
3729
+ operation: "workspaceSymbol",
3730
+ reason: "lsp-unavailable",
3731
+ capability: "tree-sitter index",
3732
+ source: "none",
3733
+ detail: `No workspace symbols matched query "${query}".`,
3734
+ fallbackSuggestion: "Broaden the query or enable LSP for richer workspace symbol resolution."
3735
+ }));
3736
+ } catch {
3737
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildFallbackResult({
3738
+ operation: "workspaceSymbol",
3739
+ reason: "lsp-unavailable",
3740
+ capability: "none",
3741
+ source: "none",
3742
+ detail: "Workspace symbol lightweight index failed.",
3743
+ fallbackSuggestion: "Retry with narrower scope or enable LSP."
3744
+ }));
3745
+ }
3746
+ }
3280
3747
  if (LSP_FALLBACK_BOUNDARY.has(fallbackOperation)) {
3281
3748
  const lang = ParserRegistry.getLanguage(input.filePath);
3282
3749
  const fallbackReason = lang ? "lsp-unavailable" : "unsupported";
@@ -3288,33 +3755,33 @@ var LspAPI = {
3288
3755
  try {
3289
3756
  const diagnostics = await getTreeSitterDiagnostics(input.filePath);
3290
3757
  const formatted = formatGenericDiagnosticsResult(diagnostics);
3291
- return {
3292
- formatted: formatFallbackNotice(
3758
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildEnhancedFallbackResult({
3759
+ formatted: formatFallbackNotice2(
3293
3760
  "diagnostics",
3294
3761
  fallbackReason,
3295
3762
  "tree-sitter diagnostics",
3296
3763
  formatted.formatted
3297
3764
  ),
3298
3765
  resultCount: formatted.resultCount,
3299
- fileCount: formatted.fileCount
3300
- };
3766
+ fileCount: formatted.fileCount,
3767
+ source: "tree-sitter",
3768
+ fallbackReason
3769
+ }));
3301
3770
  } catch {
3302
- return {
3303
- formatted: formatFallbackNotice(
3304
- "diagnostics",
3305
- fallbackReason,
3306
- "none",
3307
- `LSP unavailable for ${ext}. Static analysis not available.`
3308
- ),
3309
- resultCount: 0,
3310
- fileCount: 0
3311
- };
3771
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildFallbackResult({
3772
+ operation: "diagnostics",
3773
+ reason: fallbackReason,
3774
+ capability: "none",
3775
+ source: "none",
3776
+ detail: `LSP unavailable for ${ext}. Static analysis not available.`,
3777
+ fallbackSuggestion: "Retry after LSP is ready or run diagnostics with a supported language server."
3778
+ }));
3312
3779
  }
3313
3780
  }
3314
3781
  if (fallbackOperation === "findReferences") {
3315
3782
  if (input.line !== void 0 && input.character !== void 0) {
3316
3783
  try {
3317
- const content = await readFile4(input.filePath, "utf-8");
3784
+ const content = await readFile5(input.filePath, "utf-8");
3318
3785
  const lines = content.split("\n");
3319
3786
  const token = extractTokenAtPosition(
3320
3787
  lines,
@@ -3333,31 +3800,32 @@ var LspAPI = {
3333
3800
  }));
3334
3801
  if (refs.length > 0) {
3335
3802
  const formatted = formatGenericReferencesResult(refs);
3336
- return {
3337
- formatted: formatFallbackNotice(
3803
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildEnhancedFallbackResult({
3804
+ formatted: formatFallbackNotice2(
3338
3805
  "findReferences",
3339
3806
  fallbackReason,
3340
3807
  "token scan",
3341
3808
  formatted.formatted
3342
3809
  ),
3343
3810
  resultCount: formatted.resultCount,
3344
- fileCount: formatted.fileCount
3345
- };
3811
+ fileCount: formatted.fileCount,
3812
+ source: "token-scan",
3813
+ fallbackReason,
3814
+ fallbackSuggestion: "Use narrower symbol names or enable LSP for higher precision references."
3815
+ }));
3346
3816
  }
3347
3817
  }
3348
3818
  } catch {
3349
3819
  }
3350
3820
  }
3351
- return {
3352
- formatted: formatFallbackNotice(
3353
- "findReferences",
3354
- fallbackReason,
3355
- "token scan",
3356
- `LSP unavailable for ${ext}. Returning 0 references.`
3357
- ),
3358
- resultCount: 0,
3359
- fileCount: 0
3360
- };
3821
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildFallbackResult({
3822
+ operation: "findReferences",
3823
+ reason: fallbackReason,
3824
+ capability: "token scan",
3825
+ source: "token-scan",
3826
+ detail: `LSP unavailable for ${ext}. Returning 0 references.`,
3827
+ fallbackSuggestion: "Retry with LSP enabled for cross-file reference accuracy."
3828
+ }));
3361
3829
  }
3362
3830
  if (fallbackOperation === "prepareCallHierarchy") {
3363
3831
  if (input.line !== void 0 && input.character !== void 0) {
@@ -3377,50 +3845,51 @@ var LspAPI = {
3377
3845
  selectionRange: symbol.range
3378
3846
  };
3379
3847
  const formatted = formatGenericCallHierarchyItemsResult([item]);
3380
- return {
3381
- formatted: formatFallbackNotice(
3848
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildEnhancedFallbackResult({
3849
+ formatted: formatFallbackNotice2(
3382
3850
  "prepareCallHierarchy",
3383
3851
  fallbackReason,
3384
3852
  "tree-sitter symbols",
3385
3853
  formatted.formatted
3386
3854
  ),
3387
3855
  resultCount: formatted.resultCount,
3388
- fileCount: formatted.fileCount
3389
- };
3856
+ fileCount: formatted.fileCount,
3857
+ source: "tree-sitter",
3858
+ fallbackReason
3859
+ }));
3390
3860
  }
3391
3861
  } catch {
3392
3862
  }
3393
3863
  }
3394
- return {
3395
- formatted: formatFallbackNotice(
3396
- "prepareCallHierarchy",
3397
- fallbackReason,
3398
- "tree-sitter symbols",
3399
- `LSP unavailable for ${ext}. Returning 0 items.`
3400
- ),
3401
- resultCount: 0,
3402
- fileCount: 0
3403
- };
3864
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildFallbackResult({
3865
+ operation: "prepareCallHierarchy",
3866
+ reason: fallbackReason,
3867
+ capability: "tree-sitter symbols",
3868
+ source: "tree-sitter",
3869
+ detail: `LSP unavailable for ${ext}. Returning 0 items.`,
3870
+ fallbackSuggestion: "Enable LSP to retrieve full call hierarchy."
3871
+ }));
3404
3872
  }
3405
3873
  if (fallbackOperation === "incomingCalls" || fallbackOperation === "outgoingCalls") {
3406
- return {
3407
- formatted: formatFallbackNotice(
3408
- fallbackOperation,
3409
- fallbackReason,
3410
- "none",
3411
- `LSP unavailable for ${ext}. Returning 0 items.`
3412
- ),
3413
- resultCount: 0,
3414
- fileCount: 0
3415
- };
3874
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildFallbackResult({
3875
+ operation: fallbackOperation,
3876
+ reason: fallbackReason,
3877
+ capability: "none",
3878
+ source: "none",
3879
+ detail: `LSP unavailable for ${ext}. Returning 0 items.`,
3880
+ fallbackSuggestion: "Enable LSP for incoming/outgoing calls support."
3881
+ }));
3416
3882
  }
3417
3883
  }
3418
3884
  }
3419
- return {
3420
- formatted: `No LSP server available for file type: ${ext}`,
3421
- resultCount: 0,
3422
- fileCount: 0
3423
- };
3885
+ return finalizeFallbackResult(fallbackOperation, input.filePath, fallbackStartedAt, buildFallbackResult({
3886
+ operation: fallbackOperation,
3887
+ reason: "unsupported",
3888
+ capability: "none",
3889
+ source: "none",
3890
+ detail: `No LSP server available for file type: ${ext}`,
3891
+ fallbackSuggestion: "Use a supported language extension or configure an LSP server for this file type."
3892
+ }));
3424
3893
  },
3425
3894
  async runAll(inputs) {
3426
3895
  return Promise.all(inputs.map((input) => this.run(input)));
@@ -3535,7 +4004,7 @@ var LspFacade = {
3535
4004
  let contentLength = 0;
3536
4005
  try {
3537
4006
  const start = Date.now();
3538
- const content = await readFile4(input.filePath, "utf-8");
4007
+ const content = await readFile5(input.filePath, "utf-8");
3539
4008
  contentLength = content.length;
3540
4009
  contentHash = computeContentHash(content);
3541
4010
  const cached = getCachedFastPathSymbols(input.filePath, contentHash, now);
@@ -3544,15 +4013,13 @@ var LspFacade = {
3544
4013
  recordFastPathSuccess(input.filePath, Date.now() - start, Date.now());
3545
4014
  const formatted = formatTreeSitterDocumentSymbolResult(cached);
3546
4015
  if (fallbackReason) {
3547
- return {
3548
- ...formatted,
3549
- formatted: formatFallbackNotice(
3550
- "documentSymbol",
3551
- fallbackReason,
3552
- "tree-sitter symbols",
3553
- formatted.formatted
3554
- )
3555
- };
4016
+ const fallback = toDocumentSymbolTreeSitterFallback(
4017
+ input.filePath,
4018
+ fallbackReason,
4019
+ formatted
4020
+ );
4021
+ emitFallbackTelemetry("documentSymbol", input.filePath, now, fallback);
4022
+ return fallback;
3556
4023
  }
3557
4024
  return formatted;
3558
4025
  }
@@ -3572,15 +4039,13 @@ var LspFacade = {
3572
4039
  recordFastPathSuccess(input.filePath, Date.now() - start, Date.now());
3573
4040
  const formatted = formatTreeSitterDocumentSymbolResult(symbols);
3574
4041
  if (fallbackReason) {
3575
- return {
3576
- ...formatted,
3577
- formatted: formatFallbackNotice(
3578
- "documentSymbol",
3579
- fallbackReason,
3580
- "tree-sitter symbols",
3581
- formatted.formatted
3582
- )
3583
- };
4042
+ const fallback = toDocumentSymbolTreeSitterFallback(
4043
+ input.filePath,
4044
+ fallbackReason,
4045
+ formatted
4046
+ );
4047
+ emitFallbackTelemetry("documentSymbol", input.filePath, now, fallback);
4048
+ return fallback;
3584
4049
  }
3585
4050
  return formatted;
3586
4051
  }
@@ -3609,7 +4074,7 @@ var LspFacade = {
3609
4074
  let contentLength = 0;
3610
4075
  try {
3611
4076
  const start = Date.now();
3612
- const content = await readFile4(input.filePath, "utf-8");
4077
+ const content = await readFile5(input.filePath, "utf-8");
3613
4078
  contentLength = content.length;
3614
4079
  contentHash = computeContentHash(content);
3615
4080
  const cached = getCachedFastPathSymbols(input.filePath, contentHash, now);
@@ -3618,15 +4083,13 @@ var LspFacade = {
3618
4083
  recordFastPathSuccess(input.filePath, Date.now() - start, Date.now());
3619
4084
  const formatted = formatTreeSitterDocumentSymbolResult(cached);
3620
4085
  if (fallbackReason) {
3621
- return {
3622
- ...formatted,
3623
- formatted: formatFallbackNotice(
3624
- "documentSymbol",
3625
- fallbackReason,
3626
- "tree-sitter symbols",
3627
- formatted.formatted
3628
- )
3629
- };
4086
+ const fallback = toDocumentSymbolTreeSitterFallback(
4087
+ input.filePath,
4088
+ fallbackReason,
4089
+ formatted
4090
+ );
4091
+ emitFallbackTelemetry("documentSymbol", input.filePath, now, fallback);
4092
+ return fallback;
3630
4093
  }
3631
4094
  return formatted;
3632
4095
  }
@@ -3646,15 +4109,13 @@ var LspFacade = {
3646
4109
  recordFastPathSuccess(input.filePath, Date.now() - start, Date.now());
3647
4110
  const formatted = formatTreeSitterDocumentSymbolResult(symbols);
3648
4111
  if (fallbackReason) {
3649
- return {
3650
- ...formatted,
3651
- formatted: formatFallbackNotice(
3652
- "documentSymbol",
3653
- fallbackReason,
3654
- "tree-sitter symbols",
3655
- formatted.formatted
3656
- )
3657
- };
4112
+ const fallback = toDocumentSymbolTreeSitterFallback(
4113
+ input.filePath,
4114
+ fallbackReason,
4115
+ formatted
4116
+ );
4117
+ emitFallbackTelemetry("documentSymbol", input.filePath, now, fallback);
4118
+ return fallback;
3658
4119
  }
3659
4120
  return formatted;
3660
4121
  }
@@ -3690,7 +4151,7 @@ var LspFacade = {
3690
4151
  let contentLength = 0;
3691
4152
  try {
3692
4153
  const start = Date.now();
3693
- const content = await readFile4(input.filePath, "utf-8");
4154
+ const content = await readFile5(input.filePath, "utf-8");
3694
4155
  contentLength = content.length;
3695
4156
  contentHash = computeContentHash(content);
3696
4157
  const cached = getCachedFastPathSymbols(input.filePath, contentHash, now);
@@ -3750,7 +4211,7 @@ var LspFacade = {
3750
4211
  }
3751
4212
  const effectiveStrategy = strategy === "lsp" ? "tree-sitter" : strategy;
3752
4213
  scopeStrategyUsed.set(input.filePath, effectiveStrategy);
3753
- const code = await readFile4(input.filePath, "utf-8");
4214
+ const code = await readFile5(input.filePath, "utf-8");
3754
4215
  const scope = await ScopeAnalyzer.getScope(input.filePath, code, {
3755
4216
  row: input.line - 1,
3756
4217
  column: input.character - 1
@@ -3792,11 +4253,15 @@ var LspFacade = {
3792
4253
  rootPath
3793
4254
  });
3794
4255
  if (!touched) {
3795
- return {
3796
- formatted: `No LSP server available for file type: ${extname2(input.filePath)}`,
4256
+ const fallback = buildEnhancedFallbackResult({
4257
+ formatted: `No LSP server available for file type: ${extname3(input.filePath)}`,
3797
4258
  resultCount: 0,
3798
- fileCount: 0
3799
- };
4259
+ fileCount: 0,
4260
+ source: "none",
4261
+ fallbackReason: "lsp-unavailable"
4262
+ });
4263
+ emitFallbackTelemetry("diagnostics", input.filePath, Date.now(), fallback);
4264
+ return fallback;
3800
4265
  }
3801
4266
  if (shouldWait) {
3802
4267
  const ready = await LspClientManager.getInstance().waitForReadiness(
@@ -3805,11 +4270,15 @@ var LspFacade = {
3805
4270
  timeoutMs
3806
4271
  );
3807
4272
  if (!ready) {
3808
- return {
4273
+ const fallback = buildEnhancedFallbackResult({
3809
4274
  formatted: `Diagnostics timeout after ${timeoutMs}ms`,
3810
4275
  resultCount: 0,
3811
- fileCount: 0
3812
- };
4276
+ fileCount: 0,
4277
+ source: "none",
4278
+ fallbackReason: "lsp-timeout"
4279
+ });
4280
+ emitFallbackTelemetry("diagnostics", input.filePath, Date.now(), fallback);
4281
+ return fallback;
3813
4282
  }
3814
4283
  }
3815
4284
  } else {
@@ -3819,11 +4288,43 @@ var LspFacade = {
3819
4288
  rootPath
3820
4289
  });
3821
4290
  if (!touched) {
3822
- return {
3823
- formatted: `No LSP server available for file type: ${extname2(input.filePath)}`,
4291
+ if (input.operation === "goToDefinition" && input.line !== void 0 && input.character !== void 0) {
4292
+ const startedAt = Date.now();
4293
+ try {
4294
+ const fallback2 = await buildGoToDefinitionUnavailableFallback({
4295
+ filePath: input.filePath,
4296
+ line: input.line,
4297
+ character: input.character,
4298
+ fallbackReason: "lsp-unavailable"
4299
+ });
4300
+ emitFallbackTelemetry("goToDefinition", input.filePath, startedAt, fallback2);
4301
+ return fallback2;
4302
+ } catch {
4303
+ }
4304
+ }
4305
+ if (input.operation === "hover" && input.line !== void 0 && input.character !== void 0) {
4306
+ const startedAt = Date.now();
4307
+ try {
4308
+ const fallback2 = await buildHoverUnavailableFallback({
4309
+ filePath: input.filePath,
4310
+ line: input.line,
4311
+ character: input.character,
4312
+ fallbackReason: "lsp-unavailable"
4313
+ });
4314
+ emitFallbackTelemetry("hover", input.filePath, startedAt, fallback2);
4315
+ return fallback2;
4316
+ } catch {
4317
+ }
4318
+ }
4319
+ const fallback = buildEnhancedFallbackResult({
4320
+ formatted: `No LSP server available for file type: ${extname3(input.filePath)}`,
3824
4321
  resultCount: 0,
3825
- fileCount: 0
3826
- };
4322
+ fileCount: 0,
4323
+ source: "none",
4324
+ fallbackReason: "lsp-unavailable"
4325
+ });
4326
+ emitFallbackTelemetry(input.operation, input.filePath, Date.now(), fallback);
4327
+ return fallback;
3827
4328
  }
3828
4329
  }
3829
4330
  }
@@ -3832,7 +4333,15 @@ var LspFacade = {
3832
4333
  const symbols = await LspAPI.workspaceSymbol(query, { rootPath });
3833
4334
  const normalized = symbols.map(normalizeWorkspaceSymbol).filter(Boolean);
3834
4335
  const sorted = sortWorkspaceSymbols(normalized);
3835
- return formatGenericDocumentSymbolResult(sorted);
4336
+ if (sorted.length > 0) {
4337
+ return formatGenericDocumentSymbolResult(sorted);
4338
+ }
4339
+ return LspAPI.run({
4340
+ operation: "workspaceSymbol",
4341
+ filePath: input.filePath,
4342
+ query,
4343
+ rootPath
4344
+ });
3836
4345
  }
3837
4346
  if (input.operation === "diagnostics") {
3838
4347
  const diagnostics = await LspAPI.diagnostics(input.filePath, rootPath);