@duckmind/dm-linux-x64 0.65.8 → 0.66.2

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 (549) hide show
  1. package/dm +2 -2
  2. package/extensions/.dm-extensions.json +14 -548
  3. package/extensions/dm-lens/clients/dispatch/runners/utils/runner-helpers.js +1 -1
  4. package/extensions/dm-mcp-adapter/mcp-keyring-helper.cjs +1 -1
  5. package/extensions/dm-ponytail/hooks/ponytail-activate.js +1 -1
  6. package/extensions/dm-ponytail/hooks/ponytail-instructions.js +1 -1
  7. package/extensions/dm-subagents/src/extension/tool-activation.js +7 -2
  8. package/extensions/dm-subagents/src/runs/background/runner-aliases.js +2 -2
  9. package/extensions/dm-subagents/src/runs/foreground/prompt-audit.js +4 -1
  10. package/extensions/dm-subagents/src/runs/shared/child-session.js +8 -6
  11. package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +5 -1
  12. package/extensions/dm-subagents/src/watchdog/permission-arbiter.js +9 -1
  13. package/extensions/dm-subagents/src/watchdog/review.js +4 -1
  14. package/extensions/dm-web-access/tool-activation.js +0 -1
  15. package/package.json +1 -1
  16. package/extensions/dm-lens/dist/clients/actionable-warnings-logger.js +0 -24
  17. package/extensions/dm-lens/dist/clients/actionable-warnings.js +0 -1014
  18. package/extensions/dm-lens/dist/clients/advisory-provenance.js +0 -385
  19. package/extensions/dm-lens/dist/clients/agent-behavior-client.js +0 -94
  20. package/extensions/dm-lens/dist/clients/agent-nudge.js +0 -151
  21. package/extensions/dm-lens/dist/clients/analysed-root.js +0 -1
  22. package/extensions/dm-lens/dist/clients/ast-grep-client.js +0 -576
  23. package/extensions/dm-lens/dist/clients/ast-grep-rule-manager.js +0 -114
  24. package/extensions/dm-lens/dist/clients/ast-grep-tool-logger.js +0 -85
  25. package/extensions/dm-lens/dist/clients/ast-grep-types.js +0 -1
  26. package/extensions/dm-lens/dist/clients/ast-grep-yaml-synth.js +0 -109
  27. package/extensions/dm-lens/dist/clients/atomic-write-staging.js +0 -66
  28. package/extensions/dm-lens/dist/clients/atomic-write.js +0 -37
  29. package/extensions/dm-lens/dist/clients/availability-probe-flight.js +0 -11
  30. package/extensions/dm-lens/dist/clients/bash-file-access.js +0 -830
  31. package/extensions/dm-lens/dist/clients/biome-client.js +0 -221
  32. package/extensions/dm-lens/dist/clients/blocker-freshness.js +0 -385
  33. package/extensions/dm-lens/dist/clients/blocker-past-eof.js +0 -49
  34. package/extensions/dm-lens/dist/clients/bootstrap.js +0 -246
  35. package/extensions/dm-lens/dist/clients/bounded-cache.js +0 -105
  36. package/extensions/dm-lens/dist/clients/bounded-pid-file-lock.js +0 -173
  37. package/extensions/dm-lens/dist/clients/bounded-telemetry.js +0 -104
  38. package/extensions/dm-lens/dist/clients/build-identity.js +0 -45
  39. package/extensions/dm-lens/dist/clients/bundled-resource-health.js +0 -41
  40. package/extensions/dm-lens/dist/clients/bus-events-logger.js +0 -48
  41. package/extensions/dm-lens/dist/clients/bus-publish.js +0 -117
  42. package/extensions/dm-lens/dist/clients/cache/rule-cache.js +0 -103
  43. package/extensions/dm-lens/dist/clients/cache-manager.js +0 -340
  44. package/extensions/dm-lens/dist/clients/cache-observability.js +0 -847
  45. package/extensions/dm-lens/dist/clients/call-graph.js +0 -628
  46. package/extensions/dm-lens/dist/clients/cargo-manifest.js +0 -151
  47. package/extensions/dm-lens/dist/clients/cascade-budget.js +0 -52
  48. package/extensions/dm-lens/dist/clients/cascade-format.js +0 -160
  49. package/extensions/dm-lens/dist/clients/cascade-logger.js +0 -22
  50. package/extensions/dm-lens/dist/clients/cascade-types.js +0 -1
  51. package/extensions/dm-lens/dist/clients/child-unref.js +0 -59
  52. package/extensions/dm-lens/dist/clients/code-quality-warnings.js +0 -192
  53. package/extensions/dm-lens/dist/clients/codebase-model.js +0 -110
  54. package/extensions/dm-lens/dist/clients/collateral-test-role.js +0 -8
  55. package/extensions/dm-lens/dist/clients/complexity-client.js +0 -398
  56. package/extensions/dm-lens/dist/clients/config-core/deny.js +0 -117
  57. package/extensions/dm-lens/dist/clients/config-core/index.js +0 -2
  58. package/extensions/dm-lens/dist/clients/config-core/merge.js +0 -228
  59. package/extensions/dm-lens/dist/clients/config-core/normalize.js +0 -217
  60. package/extensions/dm-lens/dist/clients/config-core/process-spec.js +0 -147
  61. package/extensions/dm-lens/dist/clients/config-core/provenance.js +0 -54
  62. package/extensions/dm-lens/dist/clients/config-core/records.js +0 -79
  63. package/extensions/dm-lens/dist/clients/config-core/resolve.js +0 -48
  64. package/extensions/dm-lens/dist/clients/config-core/safe-object.js +0 -22
  65. package/extensions/dm-lens/dist/clients/config-core/schema.js +0 -90
  66. package/extensions/dm-lens/dist/clients/config-diagnostic-codes.js +0 -90
  67. package/extensions/dm-lens/dist/clients/config-locations.js +0 -175
  68. package/extensions/dm-lens/dist/clients/config-resolve.js +0 -359
  69. package/extensions/dm-lens/dist/clients/config-schema.js +0 -128
  70. package/extensions/dm-lens/dist/clients/config-warn.js +0 -146
  71. package/extensions/dm-lens/dist/clients/console-guard-install.js +0 -4
  72. package/extensions/dm-lens/dist/clients/cooperative-budget.js +0 -36
  73. package/extensions/dm-lens/dist/clients/dead-code-client.js +0 -342
  74. package/extensions/dm-lens/dist/clients/dead-code-logger.js +0 -18
  75. package/extensions/dm-lens/dist/clients/deadline-utils.js +0 -117
  76. package/extensions/dm-lens/dist/clients/debug-handles.js +0 -121
  77. package/extensions/dm-lens/dist/clients/debug-heap.js +0 -80
  78. package/extensions/dm-lens/dist/clients/deferred-lsp-work.js +0 -33
  79. package/extensions/dm-lens/dist/clients/degradation-ledger.js +0 -272
  80. package/extensions/dm-lens/dist/clients/demoted-finding-render.js +0 -61
  81. package/extensions/dm-lens/dist/clients/dependency-checker.js +0 -525
  82. package/extensions/dm-lens/dist/clients/deps/ast-grep-napi.js +0 -17
  83. package/extensions/dm-lens/dist/clients/deps/dm-host-deps.js +0 -10
  84. package/extensions/dm-lens/dist/clients/deps/dm-tui-compat.js +0 -58
  85. package/extensions/dm-lens/dist/clients/deps/js-yaml.js +0 -7
  86. package/extensions/dm-lens/dist/clients/deps/minimatch.js +0 -6
  87. package/extensions/dm-lens/dist/clients/deps/pidusage.js +0 -5
  88. package/extensions/dm-lens/dist/clients/deps/typebox.js +0 -5
  89. package/extensions/dm-lens/dist/clients/deps/vscode-jsonrpc.js +0 -8
  90. package/extensions/dm-lens/dist/clients/deps/web-tree-sitter.js +0 -11
  91. package/extensions/dm-lens/dist/clients/diagnostic-dispositions.js +0 -318
  92. package/extensions/dm-lens/dist/clients/diagnostic-line-freshness.js +0 -144
  93. package/extensions/dm-lens/dist/clients/diagnostic-logger.js +0 -60
  94. package/extensions/dm-lens/dist/clients/diagnostic-tracker.js +0 -89
  95. package/extensions/dm-lens/dist/clients/diagnostics-publish.js +0 -134
  96. package/extensions/dm-lens/dist/clients/dispatch/ast-grep-catalog.js +0 -16
  97. package/extensions/dm-lens/dist/clients/dispatch/auxiliary-lsp.js +0 -158
  98. package/extensions/dm-lens/dist/clients/dispatch/collect-later-tier.js +0 -25
  99. package/extensions/dm-lens/dist/clients/dispatch/diagnostic-taxonomy.js +0 -58
  100. package/extensions/dm-lens/dist/clients/dispatch/dispatcher.js +0 -953
  101. package/extensions/dm-lens/dist/clients/dispatch/fact-provider-types.js +0 -1
  102. package/extensions/dm-lens/dist/clients/dispatch/fact-rule-runner.js +0 -17
  103. package/extensions/dm-lens/dist/clients/dispatch/fact-runner.js +0 -18
  104. package/extensions/dm-lens/dist/clients/dispatch/fact-scheduler.js +0 -52
  105. package/extensions/dm-lens/dist/clients/dispatch/fact-store.js +0 -199
  106. package/extensions/dm-lens/dist/clients/dispatch/facts/comment-facts.js +0 -20
  107. package/extensions/dm-lens/dist/clients/dispatch/facts/file-content.js +0 -18
  108. package/extensions/dm-lens/dist/clients/dispatch/facts/function-facts.js +0 -281
  109. package/extensions/dm-lens/dist/clients/dispatch/facts/import-facts.js +0 -169
  110. package/extensions/dm-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +0 -19
  111. package/extensions/dm-lens/dist/clients/dispatch/facts/try-catch-facts.js +0 -95
  112. package/extensions/dm-lens/dist/clients/dispatch/finding-policy.js +0 -159
  113. package/extensions/dm-lens/dist/clients/dispatch/indent-detect.js +0 -227
  114. package/extensions/dm-lens/dist/clients/dispatch/inline-suppressions.js +0 -52
  115. package/extensions/dm-lens/dist/clients/dispatch/integration.js +0 -1463
  116. package/extensions/dm-lens/dist/clients/dispatch/lazy.js +0 -8
  117. package/extensions/dm-lens/dist/clients/dispatch/pending-runner-findings.js +0 -75
  118. package/extensions/dm-lens/dist/clients/dispatch/plan.js +0 -278
  119. package/extensions/dm-lens/dist/clients/dispatch/priorities.js +0 -14
  120. package/extensions/dm-lens/dist/clients/dispatch/rule-id-normalize.js +0 -42
  121. package/extensions/dm-lens/dist/clients/dispatch/rule-ignores.js +0 -21
  122. package/extensions/dm-lens/dist/clients/dispatch/rule-policy.js +0 -73
  123. package/extensions/dm-lens/dist/clients/dispatch/rules/async-noise.js +0 -31
  124. package/extensions/dm-lens/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +0 -27
  125. package/extensions/dm-lens/dist/clients/dispatch/rules/cors-wildcard.js +0 -35
  126. package/extensions/dm-lens/dist/clients/dispatch/rules/error-obscuring.js +0 -29
  127. package/extensions/dm-lens/dist/clients/dispatch/rules/error-swallowing.js +0 -29
  128. package/extensions/dm-lens/dist/clients/dispatch/rules/framework-call-noise.js +0 -31
  129. package/extensions/dm-lens/dist/clients/dispatch/rules/high-complexity.js +0 -56
  130. package/extensions/dm-lens/dist/clients/dispatch/rules/high-fan-out.js +0 -45
  131. package/extensions/dm-lens/dist/clients/dispatch/rules/high-import-coupling.js +0 -31
  132. package/extensions/dm-lens/dist/clients/dispatch/rules/missing-error-propagation.js +0 -45
  133. package/extensions/dm-lens/dist/clients/dispatch/rules/no-commented-credentials.js +0 -46
  134. package/extensions/dm-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +0 -38
  135. package/extensions/dm-lens/dist/clients/dispatch/rules/placeholder-comments.js +0 -40
  136. package/extensions/dm-lens/dist/clients/dispatch/rules/unsafe-boundary.js +0 -101
  137. package/extensions/dm-lens/dist/clients/dispatch/runner-context.js +0 -46
  138. package/extensions/dm-lens/dist/clients/dispatch/runners/actionlint.js +0 -98
  139. package/extensions/dm-lens/dist/clients/dispatch/runners/ast-grep-napi.js +0 -690
  140. package/extensions/dm-lens/dist/clients/dispatch/runners/biome-check.js +0 -202
  141. package/extensions/dm-lens/dist/clients/dispatch/runners/cpp-check.js +0 -190
  142. package/extensions/dm-lens/dist/clients/dispatch/runners/credo.js +0 -66
  143. package/extensions/dm-lens/dist/clients/dispatch/runners/cue-vet.js +0 -167
  144. package/extensions/dm-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -151
  145. package/extensions/dm-lens/dist/clients/dispatch/runners/detekt.js +0 -157
  146. package/extensions/dm-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -157
  147. package/extensions/dm-lens/dist/clients/dispatch/runners/elixir-check.js +0 -153
  148. package/extensions/dm-lens/dist/clients/dispatch/runners/eslint.js +0 -99
  149. package/extensions/dm-lens/dist/clients/dispatch/runners/fact-rules.js +0 -20
  150. package/extensions/dm-lens/dist/clients/dispatch/runners/fish-indent.js +0 -65
  151. package/extensions/dm-lens/dist/clients/dispatch/runners/gleam-check.js +0 -107
  152. package/extensions/dm-lens/dist/clients/dispatch/runners/go-vet.js +0 -51
  153. package/extensions/dm-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -89
  154. package/extensions/dm-lens/dist/clients/dispatch/runners/hadolint.js +0 -83
  155. package/extensions/dm-lens/dist/clients/dispatch/runners/helm-lint.js +0 -144
  156. package/extensions/dm-lens/dist/clients/dispatch/runners/helm-render.js +0 -593
  157. package/extensions/dm-lens/dist/clients/dispatch/runners/htmlhint.js +0 -103
  158. package/extensions/dm-lens/dist/clients/dispatch/runners/index.js +0 -100
  159. package/extensions/dm-lens/dist/clients/dispatch/runners/javac.js +0 -82
  160. package/extensions/dm-lens/dist/clients/dispatch/runners/ktlint.js +0 -93
  161. package/extensions/dm-lens/dist/clients/dispatch/runners/lsp.js +0 -206
  162. package/extensions/dm-lens/dist/clients/dispatch/runners/markdownlint.js +0 -129
  163. package/extensions/dm-lens/dist/clients/dispatch/runners/mypy.js +0 -70
  164. package/extensions/dm-lens/dist/clients/dispatch/runners/oxlint.js +0 -305
  165. package/extensions/dm-lens/dist/clients/dispatch/runners/php-lint.js +0 -70
  166. package/extensions/dm-lens/dist/clients/dispatch/runners/phpstan.js +0 -90
  167. package/extensions/dm-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -56
  168. package/extensions/dm-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -307
  169. package/extensions/dm-lens/dist/clients/dispatch/runners/pyright.js +0 -118
  170. package/extensions/dm-lens/dist/clients/dispatch/runners/rubocop.js +0 -79
  171. package/extensions/dm-lens/dist/clients/dispatch/runners/ruff.js +0 -69
  172. package/extensions/dm-lens/dist/clients/dispatch/runners/rust-clippy.js +0 -147
  173. package/extensions/dm-lens/dist/clients/dispatch/runners/shellcheck.js +0 -111
  174. package/extensions/dm-lens/dist/clients/dispatch/runners/shfmt.js +0 -81
  175. package/extensions/dm-lens/dist/clients/dispatch/runners/spellcheck.js +0 -74
  176. package/extensions/dm-lens/dist/clients/dispatch/runners/spotbugs.js +0 -208
  177. package/extensions/dm-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -136
  178. package/extensions/dm-lens/dist/clients/dispatch/runners/stylelint.js +0 -118
  179. package/extensions/dm-lens/dist/clients/dispatch/runners/swiftlint.js +0 -143
  180. package/extensions/dm-lens/dist/clients/dispatch/runners/taplo.js +0 -97
  181. package/extensions/dm-lens/dist/clients/dispatch/runners/terragrunt.js +0 -110
  182. package/extensions/dm-lens/dist/clients/dispatch/runners/tflint.js +0 -104
  183. package/extensions/dm-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -516
  184. package/extensions/dm-lens/dist/clients/dispatch/runners/trivy-config.js +0 -155
  185. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/availability-policy.js +0 -285
  186. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +0 -61
  187. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -61
  188. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +0 -130
  189. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +0 -1067
  190. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +0 -40
  191. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/tool-failure.js +0 -117
  192. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +0 -88
  193. package/extensions/dm-lens/dist/clients/dispatch/runners/utils.js +0 -8
  194. package/extensions/dm-lens/dist/clients/dispatch/runners/vale.js +0 -106
  195. package/extensions/dm-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +0 -163
  196. package/extensions/dm-lens/dist/clients/dispatch/runners/yamllint.js +0 -83
  197. package/extensions/dm-lens/dist/clients/dispatch/runners/zig-check.js +0 -72
  198. package/extensions/dm-lens/dist/clients/dispatch/suppress-writer.js +0 -57
  199. package/extensions/dm-lens/dist/clients/dispatch/tool-profile.js +0 -30
  200. package/extensions/dm-lens/dist/clients/dispatch/types.js +0 -7
  201. package/extensions/dm-lens/dist/clients/dispatch/utils/format-utils.js +0 -45
  202. package/extensions/dm-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +0 -31
  203. package/extensions/dm-lens/dist/clients/disposition-logger.js +0 -19
  204. package/extensions/dm-lens/dist/clients/disposition-publish.js +0 -88
  205. package/extensions/dm-lens/dist/clients/durable-store.js +0 -77
  206. package/extensions/dm-lens/dist/clients/effective-config.js +0 -160
  207. package/extensions/dm-lens/dist/clients/env-utils.js +0 -26
  208. package/extensions/dm-lens/dist/clients/error-class.js +0 -3
  209. package/extensions/dm-lens/dist/clients/eval-timestamp.js +0 -2
  210. package/extensions/dm-lens/dist/clients/event-loop-hold.js +0 -119
  211. package/extensions/dm-lens/dist/clients/event-loop-monitor.js +0 -84
  212. package/extensions/dm-lens/dist/clients/extension-log.js +0 -230
  213. package/extensions/dm-lens/dist/clients/extension-mode.js +0 -20
  214. package/extensions/dm-lens/dist/clients/feature-hints.js +0 -88
  215. package/extensions/dm-lens/dist/clients/file-kinds.js +0 -304
  216. package/extensions/dm-lens/dist/clients/file-role.js +0 -50
  217. package/extensions/dm-lens/dist/clients/file-time.js +0 -112
  218. package/extensions/dm-lens/dist/clients/file-utils.js +0 -630
  219. package/extensions/dm-lens/dist/clients/finding-delivery-gate.js +0 -129
  220. package/extensions/dm-lens/dist/clients/finding-identity.js +0 -23
  221. package/extensions/dm-lens/dist/clients/fix-worklog.js +0 -75
  222. package/extensions/dm-lens/dist/clients/format-events-publish.js +0 -230
  223. package/extensions/dm-lens/dist/clients/format-service.js +0 -154
  224. package/extensions/dm-lens/dist/clients/formatters-lazy.js +0 -8
  225. package/extensions/dm-lens/dist/clients/formatters.js +0 -1351
  226. package/extensions/dm-lens/dist/clients/freshness-cadence.js +0 -1
  227. package/extensions/dm-lens/dist/clients/freshness.js +0 -8
  228. package/extensions/dm-lens/dist/clients/generated-artifacts.js +0 -209
  229. package/extensions/dm-lens/dist/clients/generation-guard.js +0 -105
  230. package/extensions/dm-lens/dist/clients/git-guard.js +0 -770
  231. package/extensions/dm-lens/dist/clients/git-tracked-ignore.js +0 -120
  232. package/extensions/dm-lens/dist/clients/gitleaks-client.js +0 -282
  233. package/extensions/dm-lens/dist/clients/go-client.js +0 -47
  234. package/extensions/dm-lens/dist/clients/govulncheck-client.js +0 -411
  235. package/extensions/dm-lens/dist/clients/gradle-ktfmt-style.js +0 -177
  236. package/extensions/dm-lens/dist/clients/grammar-source.js +0 -224
  237. package/extensions/dm-lens/dist/clients/gzip-stage-write.js +0 -85
  238. package/extensions/dm-lens/dist/clients/hashline-anchor.js +0 -222
  239. package/extensions/dm-lens/dist/clients/hook-budgets.js +0 -16
  240. package/extensions/dm-lens/dist/clients/host-edit-normalize.js +0 -87
  241. package/extensions/dm-lens/dist/clients/host-ports.js +0 -35
  242. package/extensions/dm-lens/dist/clients/indent-retarget.js +0 -102
  243. package/extensions/dm-lens/dist/clients/inline-blocker-dispositions.js +0 -103
  244. package/extensions/dm-lens/dist/clients/install-diagnostics.js +0 -123
  245. package/extensions/dm-lens/dist/clients/installer/index.js +0 -3770
  246. package/extensions/dm-lens/dist/clients/installer/managed-tool-refresh-session.js +0 -17
  247. package/extensions/dm-lens/dist/clients/installer/managed-tool-refresh.js +0 -522
  248. package/extensions/dm-lens/dist/clients/instance-reaper-state.js +0 -3
  249. package/extensions/dm-lens/dist/clients/instance-reaper.js +0 -577
  250. package/extensions/dm-lens/dist/clients/instance-registry-lock.js +0 -131
  251. package/extensions/dm-lens/dist/clients/instance-registry.js +0 -452
  252. package/extensions/dm-lens/dist/clients/jscpd-client.js +0 -252
  253. package/extensions/dm-lens/dist/clients/json-cache-read.js +0 -25
  254. package/extensions/dm-lens/dist/clients/knip-client.js +0 -472
  255. package/extensions/dm-lens/dist/clients/language-policy.js +0 -242
  256. package/extensions/dm-lens/dist/clients/language-profile.js +0 -261
  257. package/extensions/dm-lens/dist/clients/language-registry.js +0 -424
  258. package/extensions/dm-lens/dist/clients/latency-logger.js +0 -192
  259. package/extensions/dm-lens/dist/clients/lazy-import.js +0 -14
  260. package/extensions/dm-lens/dist/clients/ledger-bounds.js +0 -21
  261. package/extensions/dm-lens/dist/clients/lens-config.js +0 -237
  262. package/extensions/dm-lens/dist/clients/lens-engine.js +0 -181
  263. package/extensions/dm-lens/dist/clients/lens-events.js +0 -105
  264. package/extensions/dm-lens/dist/clients/lens-flag-registry.js +0 -302
  265. package/extensions/dm-lens/dist/clients/lens-map.js +0 -980
  266. package/extensions/dm-lens/dist/clients/live-bus-emitter.js +0 -53
  267. package/extensions/dm-lens/dist/clients/log-cleanup.js +0 -138
  268. package/extensions/dm-lens/dist/clients/lsp/aggregation.js +0 -88
  269. package/extensions/dm-lens/dist/clients/lsp/cascade-tier.js +0 -203
  270. package/extensions/dm-lens/dist/clients/lsp/client.js +0 -2709
  271. package/extensions/dm-lens/dist/clients/lsp/config.js +0 -252
  272. package/extensions/dm-lens/dist/clients/lsp/content-limits.js +0 -21
  273. package/extensions/dm-lens/dist/clients/lsp/diagnostic-binding.js +0 -79
  274. package/extensions/dm-lens/dist/clients/lsp/document-drift.js +0 -312
  275. package/extensions/dm-lens/dist/clients/lsp/edits.js +0 -930
  276. package/extensions/dm-lens/dist/clients/lsp/index.js +0 -4448
  277. package/extensions/dm-lens/dist/clients/lsp/inferred-project.js +0 -121
  278. package/extensions/dm-lens/dist/clients/lsp/jvm-runtime.js +0 -194
  279. package/extensions/dm-lens/dist/clients/lsp/language.js +0 -23
  280. package/extensions/dm-lens/dist/clients/lsp/launch.js +0 -468
  281. package/extensions/dm-lens/dist/clients/lsp/lombok.js +0 -146
  282. package/extensions/dm-lens/dist/clients/lsp/path-utils.js +0 -1
  283. package/extensions/dm-lens/dist/clients/lsp/pending-aux-coverage.js +0 -90
  284. package/extensions/dm-lens/dist/clients/lsp/position-encoding.js +0 -28
  285. package/extensions/dm-lens/dist/clients/lsp/ruby-drive-dirs.js +0 -42
  286. package/extensions/dm-lens/dist/clients/lsp/server.js +0 -2422
  287. package/extensions/dm-lens/dist/clients/lsp/session-roots.js +0 -52
  288. package/extensions/dm-lens/dist/clients/lsp/spawn-history.js +0 -15
  289. package/extensions/dm-lens/dist/clients/lsp/sync-kind.js +0 -30
  290. package/extensions/dm-lens/dist/clients/lsp/tsserver-sync.js +0 -156
  291. package/extensions/dm-lens/dist/clients/lsp/wait-policy/capability-snapshot.js +0 -1
  292. package/extensions/dm-lens/dist/clients/lsp/wait-policy/classification.js +0 -36
  293. package/extensions/dm-lens/dist/clients/lsp/wait-policy/index.js +0 -3
  294. package/extensions/dm-lens/dist/clients/lsp/wait-policy/strategies.js +0 -175
  295. package/extensions/dm-lens/dist/clients/lsp/watch-queue.js +0 -40
  296. package/extensions/dm-lens/dist/clients/lsp/workspace-diagnostics-cache.js +0 -267
  297. package/extensions/dm-lens/dist/clients/lsp/workspace-diagnostics-session.js +0 -7
  298. package/extensions/dm-lens/dist/clients/lsp/workspace-sweep-hold.js +0 -93
  299. package/extensions/dm-lens/dist/clients/lsp-budget.js +0 -83
  300. package/extensions/dm-lens/dist/clients/lsp-document-symbols.js +0 -93
  301. package/extensions/dm-lens/dist/clients/lsp-lazy.js +0 -8
  302. package/extensions/dm-lens/dist/clients/lsp-mutation.js +0 -273
  303. package/extensions/dm-lens/dist/clients/lsp-status.js +0 -37
  304. package/extensions/dm-lens/dist/clients/map-with-concurrency.js +0 -20
  305. package/extensions/dm-lens/dist/clients/mcp/analyze.js +0 -251
  306. package/extensions/dm-lens/dist/clients/mcp/host-shim.js +0 -14
  307. package/extensions/dm-lens/dist/clients/mcp/ipc.js +0 -302
  308. package/extensions/dm-lens/dist/clients/mcp/review.js +0 -137
  309. package/extensions/dm-lens/dist/clients/mcp/session.js +0 -305
  310. package/extensions/dm-lens/dist/clients/memory-sampler.js +0 -107
  311. package/extensions/dm-lens/dist/clients/message-end-attribution.js +0 -18
  312. package/extensions/dm-lens/dist/clients/metrics-client.js +0 -80
  313. package/extensions/dm-lens/dist/clients/metrics-history.js +0 -255
  314. package/extensions/dm-lens/dist/clients/middle-man-analysis.js +0 -161
  315. package/extensions/dm-lens/dist/clients/model-provider.js +0 -31
  316. package/extensions/dm-lens/dist/clients/module-report-lsp.js +0 -140
  317. package/extensions/dm-lens/dist/clients/module-report.js +0 -1642
  318. package/extensions/dm-lens/dist/clients/mutating-tool.js +0 -377
  319. package/extensions/dm-lens/dist/clients/mutation-attribution.js +0 -168
  320. package/extensions/dm-lens/dist/clients/mutation-bridge.js +0 -102
  321. package/extensions/dm-lens/dist/clients/ndjson-logger.js +0 -471
  322. package/extensions/dm-lens/dist/clients/observed-mutation-sources.js +0 -43
  323. package/extensions/dm-lens/dist/clients/observed-mutation.js +0 -709
  324. package/extensions/dm-lens/dist/clients/oldtext-autopatch.js +0 -100
  325. package/extensions/dm-lens/dist/clients/opaque-mutation-scan.js +0 -313
  326. package/extensions/dm-lens/dist/clients/opengrep-client.js +0 -216
  327. package/extensions/dm-lens/dist/clients/opengrep-config.js +0 -52
  328. package/extensions/dm-lens/dist/clients/package-manager.js +0 -303
  329. package/extensions/dm-lens/dist/clients/package-root.js +0 -25
  330. package/extensions/dm-lens/dist/clients/partial-edit-apply.js +0 -337
  331. package/extensions/dm-lens/dist/clients/path-attribution-telemetry.js +0 -31
  332. package/extensions/dm-lens/dist/clients/path-keyed-map.js +0 -57
  333. package/extensions/dm-lens/dist/clients/path-utils.js +0 -476
  334. package/extensions/dm-lens/dist/clients/performance-report.js +0 -291
  335. package/extensions/dm-lens/dist/clients/persist-debounce.js +0 -37
  336. package/extensions/dm-lens/dist/clients/persistent-reverify.js +0 -165
  337. package/extensions/dm-lens/dist/clients/php-cs-fixer-config.js +0 -15
  338. package/extensions/dm-lens/dist/clients/pipeline.js +0 -1091
  339. package/extensions/dm-lens/dist/clients/post-autofix-notice.js +0 -19
  340. package/extensions/dm-lens/dist/clients/print-mode.js +0 -3
  341. package/extensions/dm-lens/dist/clients/probe-home-state.js +0 -62
  342. package/extensions/dm-lens/dist/clients/process-bridge.js +0 -20
  343. package/extensions/dm-lens/dist/clients/process-singletons.js +0 -69
  344. package/extensions/dm-lens/dist/clients/process-snapshot.js +0 -22
  345. package/extensions/dm-lens/dist/clients/project-changes.js +0 -112
  346. package/extensions/dm-lens/dist/clients/project-conventions.js +0 -152
  347. package/extensions/dm-lens/dist/clients/project-diagnostics/cache.js +0 -91
  348. package/extensions/dm-lens/dist/clients/project-diagnostics/extractors.js +0 -53
  349. package/extensions/dm-lens/dist/clients/project-diagnostics/fresh-fetch.js +0 -408
  350. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +0 -64
  351. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +0 -38
  352. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +0 -21
  353. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +0 -23
  354. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +0 -28
  355. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +0 -45
  356. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +0 -34
  357. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +0 -32
  358. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +0 -79
  359. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +0 -41
  360. package/extensions/dm-lens/dist/clients/project-diagnostics/scanner.js +0 -349
  361. package/extensions/dm-lens/dist/clients/project-diagnostics/types.js +0 -1
  362. package/extensions/dm-lens/dist/clients/project-lens-config.js +0 -437
  363. package/extensions/dm-lens/dist/clients/project-report.js +0 -527
  364. package/extensions/dm-lens/dist/clients/project-scale.js +0 -60
  365. package/extensions/dm-lens/dist/clients/project-scan-policy.js +0 -4
  366. package/extensions/dm-lens/dist/clients/project-snapshot-fingerprint.js +0 -39
  367. package/extensions/dm-lens/dist/clients/project-snapshot-persist-worker.js +0 -14
  368. package/extensions/dm-lens/dist/clients/project-snapshot.js +0 -1178
  369. package/extensions/dm-lens/dist/clients/project-trust.js +0 -104
  370. package/extensions/dm-lens/dist/clients/python-environment.js +0 -120
  371. package/extensions/dm-lens/dist/clients/python-provenance.js +0 -551
  372. package/extensions/dm-lens/dist/clients/quiet-window-config.js +0 -16
  373. package/extensions/dm-lens/dist/clients/quiet-window.js +0 -126
  374. package/extensions/dm-lens/dist/clients/read-bridge.js +0 -46
  375. package/extensions/dm-lens/dist/clients/read-expansion.js +0 -218
  376. package/extensions/dm-lens/dist/clients/read-guard-logger.js +0 -178
  377. package/extensions/dm-lens/dist/clients/read-guard-tool-lines.js +0 -1042
  378. package/extensions/dm-lens/dist/clients/read-guard.js +0 -1096
  379. package/extensions/dm-lens/dist/clients/recent-touches.js +0 -126
  380. package/extensions/dm-lens/dist/clients/redact/secrets.js +0 -386
  381. package/extensions/dm-lens/dist/clients/resource-sampler.js +0 -344
  382. package/extensions/dm-lens/dist/clients/reverse-deps.js +0 -227
  383. package/extensions/dm-lens/dist/clients/review-graph/builder.js +0 -3635
  384. package/extensions/dm-lens/dist/clients/review-graph/format.js +0 -30
  385. package/extensions/dm-lens/dist/clients/review-graph/git-identity.js +0 -115
  386. package/extensions/dm-lens/dist/clients/review-graph/import-resolvers.js +0 -325
  387. package/extensions/dm-lens/dist/clients/review-graph/persist-worker.js +0 -8
  388. package/extensions/dm-lens/dist/clients/review-graph/query.js +0 -195
  389. package/extensions/dm-lens/dist/clients/review-graph/revision-drift.js +0 -3
  390. package/extensions/dm-lens/dist/clients/review-graph/service.js +0 -60
  391. package/extensions/dm-lens/dist/clients/review-graph/shared-extraction-ir.js +0 -54
  392. package/extensions/dm-lens/dist/clients/review-graph/symbol-id.js +0 -29
  393. package/extensions/dm-lens/dist/clients/review-graph/tsconfig-paths.js +0 -253
  394. package/extensions/dm-lens/dist/clients/review-graph/types.js +0 -1
  395. package/extensions/dm-lens/dist/clients/review-graph/workspace-modules.js +0 -374
  396. package/extensions/dm-lens/dist/clients/review-graph-logger.js +0 -51
  397. package/extensions/dm-lens/dist/clients/ruff-client.js +0 -109
  398. package/extensions/dm-lens/dist/clients/rules-scanner.js +0 -113
  399. package/extensions/dm-lens/dist/clients/run-duration.js +0 -9
  400. package/extensions/dm-lens/dist/clients/runtime-agent-end.js +0 -608
  401. package/extensions/dm-lens/dist/clients/runtime-config.js +0 -39
  402. package/extensions/dm-lens/dist/clients/runtime-context.js +0 -155
  403. package/extensions/dm-lens/dist/clients/runtime-coordinator.js +0 -817
  404. package/extensions/dm-lens/dist/clients/runtime-session.js +0 -1625
  405. package/extensions/dm-lens/dist/clients/runtime-tool-call.js +0 -868
  406. package/extensions/dm-lens/dist/clients/runtime-tool-result.js +0 -1317
  407. package/extensions/dm-lens/dist/clients/runtime-turn.js +0 -2333
  408. package/extensions/dm-lens/dist/clients/rust-client.js +0 -48
  409. package/extensions/dm-lens/dist/clients/safe-spawn.js +0 -1267
  410. package/extensions/dm-lens/dist/clients/sanitize.js +0 -174
  411. package/extensions/dm-lens/dist/clients/scan-utils.js +0 -7
  412. package/extensions/dm-lens/dist/clients/scratch-tree-policy.js +0 -57
  413. package/extensions/dm-lens/dist/clients/search-read-registration.js +0 -59
  414. package/extensions/dm-lens/dist/clients/secret-findings.js +0 -69
  415. package/extensions/dm-lens/dist/clients/security-scan-client.js +0 -208
  416. package/extensions/dm-lens/dist/clients/session-event-guard.js +0 -111
  417. package/extensions/dm-lens/dist/clients/session-lifecycle.js +0 -173
  418. package/extensions/dm-lens/dist/clients/session-start-observability.js +0 -47
  419. package/extensions/dm-lens/dist/clients/session-state-store.js +0 -63
  420. package/extensions/dm-lens/dist/clients/session-summary.js +0 -8
  421. package/extensions/dm-lens/dist/clients/sessionstart-logger.js +0 -22
  422. package/extensions/dm-lens/dist/clients/sg-runner.js +0 -627
  423. package/extensions/dm-lens/dist/clients/sgconfig.js +0 -280
  424. package/extensions/dm-lens/dist/clients/shared-checkout-guard.js +0 -177
  425. package/extensions/dm-lens/dist/clients/single-flight.js +0 -52
  426. package/extensions/dm-lens/dist/clients/situational-tool-telemetry.js +0 -85
  427. package/extensions/dm-lens/dist/clients/skills-resolver.js +0 -38
  428. package/extensions/dm-lens/dist/clients/slow-fs.js +0 -77
  429. package/extensions/dm-lens/dist/clients/smells-rollup.js +0 -118
  430. package/extensions/dm-lens/dist/clients/source-filter.js +0 -320
  431. package/extensions/dm-lens/dist/clients/source-walker.js +0 -96
  432. package/extensions/dm-lens/dist/clients/spawn-output-cap.js +0 -35
  433. package/extensions/dm-lens/dist/clients/spawn-timeout-cooldown.js +0 -51
  434. package/extensions/dm-lens/dist/clients/stale-marker.js +0 -1
  435. package/extensions/dm-lens/dist/clients/startup-scan.js +0 -222
  436. package/extensions/dm-lens/dist/clients/startup-timing.js +0 -67
  437. package/extensions/dm-lens/dist/clients/string-utils.js +0 -6
  438. package/extensions/dm-lens/dist/clients/subagent-mode.js +0 -40
  439. package/extensions/dm-lens/dist/clients/symbol-containment.js +0 -16
  440. package/extensions/dm-lens/dist/clients/symbol-types.js +0 -1
  441. package/extensions/dm-lens/dist/clients/test-runner-client.js +0 -1504
  442. package/extensions/dm-lens/dist/clients/test-runner-delivery.js +0 -260
  443. package/extensions/dm-lens/dist/clients/todo-scanner.js +0 -164
  444. package/extensions/dm-lens/dist/clients/tool-agreement.js +0 -377
  445. package/extensions/dm-lens/dist/clients/tool-config.js +0 -218
  446. package/extensions/dm-lens/dist/clients/tool-cwd.js +0 -235
  447. package/extensions/dm-lens/dist/clients/tool-definition.js +0 -22
  448. package/extensions/dm-lens/dist/clients/tool-event.js +0 -18
  449. package/extensions/dm-lens/dist/clients/tool-policy.js +0 -2393
  450. package/extensions/dm-lens/dist/clients/tool-probe.js +0 -5
  451. package/extensions/dm-lens/dist/clients/tool-render.js +0 -79
  452. package/extensions/dm-lens/dist/clients/tool-set-policy.js +0 -70
  453. package/extensions/dm-lens/dist/clients/tree-sitter-cache.js +0 -206
  454. package/extensions/dm-lens/dist/clients/tree-sitter-client.js +0 -2787
  455. package/extensions/dm-lens/dist/clients/tree-sitter-logger.js +0 -77
  456. package/extensions/dm-lens/dist/clients/tree-sitter-navigator.js +0 -198
  457. package/extensions/dm-lens/dist/clients/tree-sitter-query-loader.js +0 -318
  458. package/extensions/dm-lens/dist/clients/tree-sitter-shared.js +0 -87
  459. package/extensions/dm-lens/dist/clients/tree-sitter-symbol-extractor.js +0 -957
  460. package/extensions/dm-lens/dist/clients/trivy-client.js +0 -305
  461. package/extensions/dm-lens/dist/clients/tui-fit.js +0 -26
  462. package/extensions/dm-lens/dist/clients/turn-context.js +0 -48
  463. package/extensions/dm-lens/dist/clients/turn-end/lane.js +0 -1
  464. package/extensions/dm-lens/dist/clients/turn-end/lanes/govulncheck.js +0 -54
  465. package/extensions/dm-lens/dist/clients/turn-end/lanes/secrets.js +0 -131
  466. package/extensions/dm-lens/dist/clients/turn-summary-render.js +0 -56
  467. package/extensions/dm-lens/dist/clients/turn-summary.js +0 -84
  468. package/extensions/dm-lens/dist/clients/typos-config.js +0 -9
  469. package/extensions/dm-lens/dist/clients/user-notify.js +0 -15
  470. package/extensions/dm-lens/dist/clients/vanished-instance-marker.js +0 -18
  471. package/extensions/dm-lens/dist/clients/warm-attach.js +0 -210
  472. package/extensions/dm-lens/dist/clients/widget-state.js +0 -963
  473. package/extensions/dm-lens/dist/clients/word-index-logger.js +0 -21
  474. package/extensions/dm-lens/dist/clients/word-index-store.js +0 -222
  475. package/extensions/dm-lens/dist/clients/word-index.js +0 -1426
  476. package/extensions/dm-lens/dist/clients/workspace-topology.js +0 -261
  477. package/extensions/dm-lens/dist/clients/write-ordering-guard.js +0 -24
  478. package/extensions/dm-lens/dist/clients/zizmor-config.js +0 -160
  479. package/extensions/dm-lens/dist/i18n.js +0 -67
  480. package/extensions/dm-lens/dist/index.js +0 -1782
  481. package/extensions/dm-lens/dist/mcp/analyze-cli.js +0 -178
  482. package/extensions/dm-lens/dist/mcp/build-staleness.js +0 -55
  483. package/extensions/dm-lens/dist/mcp/cli.js +0 -78
  484. package/extensions/dm-lens/dist/mcp/server.js +0 -1208
  485. package/extensions/dm-lens/dist/mcp/worker.js +0 -33
  486. package/extensions/dm-lens/dist/scripts/lib/process-scan.mjs +0 -256
  487. package/extensions/dm-lens/dist/scripts/lib/skills-predicate.mjs +0 -53
  488. package/extensions/dm-lens/dist/scripts/lib/web-tree-sitter-dir.mjs +0 -45
  489. package/extensions/dm-lens/dist/tools/activate-tools.js +0 -61
  490. package/extensions/dm-lens/dist/tools/ast-grep-outline.js +0 -127
  491. package/extensions/dm-lens/dist/tools/ast-grep-replace.js +0 -226
  492. package/extensions/dm-lens/dist/tools/ast-grep-search.js +0 -687
  493. package/extensions/dm-lens/dist/tools/effective-config.js +0 -59
  494. package/extensions/dm-lens/dist/tools/lens-diagnostic-mark.js +0 -240
  495. package/extensions/dm-lens/dist/tools/lens-diagnostics.js +0 -1484
  496. package/extensions/dm-lens/dist/tools/lsp-diagnostics.js +0 -1088
  497. package/extensions/dm-lens/dist/tools/lsp-navigation.js +0 -1194
  498. package/extensions/dm-lens/dist/tools/lsp-structured-output.js +0 -277
  499. package/extensions/dm-lens/dist/tools/module-report.js +0 -332
  500. package/extensions/dm-lens/dist/tools/project-report.js +0 -72
  501. package/extensions/dm-lens/dist/tools/render-compact.js +0 -272
  502. package/extensions/dm-lens/dist/tools/scan-progress.js +0 -31
  503. package/extensions/dm-lens/dist/tools/shared.js +0 -26
  504. package/extensions/dm-lens/dist/tools/symbol-search.js +0 -133
  505. package/extensions/dm-mcp-adapter/dist/abort.js +0 -35
  506. package/extensions/dm-mcp-adapter/dist/agent-dir.js +0 -45
  507. package/extensions/dm-mcp-adapter/dist/agent-plugin-loader.js +0 -392
  508. package/extensions/dm-mcp-adapter/dist/agent-plugin-provenance.js +0 -26
  509. package/extensions/dm-mcp-adapter/dist/bearer-command-resolver.js +0 -182
  510. package/extensions/dm-mcp-adapter/dist/claude-plugin-loader.js +0 -350
  511. package/extensions/dm-mcp-adapter/dist/config.js +0 -1310
  512. package/extensions/dm-mcp-adapter/dist/consent-manager.js +0 -84
  513. package/extensions/dm-mcp-adapter/dist/elicitation-handler.js +0 -308
  514. package/extensions/dm-mcp-adapter/dist/errors.js +0 -225
  515. package/extensions/dm-mcp-adapter/dist/http-ca.js +0 -71
  516. package/extensions/dm-mcp-adapter/dist/jev-client.js +0 -359
  517. package/extensions/dm-mcp-adapter/dist/jev-contracts.js +0 -1
  518. package/extensions/dm-mcp-adapter/dist/jev-key-store.js +0 -176
  519. package/extensions/dm-mcp-adapter/dist/json-schema-validator.js +0 -70
  520. package/extensions/dm-mcp-adapter/dist/lifecycle.js +0 -387
  521. package/extensions/dm-mcp-adapter/dist/logger.js +0 -115
  522. package/extensions/dm-mcp-adapter/dist/mcp-auth-fetch.js +0 -86
  523. package/extensions/dm-mcp-adapter/dist/mcp-auth-flow.js +0 -949
  524. package/extensions/dm-mcp-adapter/dist/mcp-auth.js +0 -997
  525. package/extensions/dm-mcp-adapter/dist/mcp-bearer-store.js +0 -182
  526. package/extensions/dm-mcp-adapter/dist/mcp-callback-server.js +0 -381
  527. package/extensions/dm-mcp-adapter/dist/mcp-oauth-provider.js +0 -524
  528. package/extensions/dm-mcp-adapter/dist/mcp-probe.js +0 -151
  529. package/extensions/dm-mcp-adapter/dist/mcp-tasks.js +0 -300
  530. package/extensions/dm-mcp-adapter/dist/mcp-trace.js +0 -215
  531. package/extensions/dm-mcp-adapter/dist/metadata-cache.js +0 -267
  532. package/extensions/dm-mcp-adapter/dist/npx-resolver.js +0 -465
  533. package/extensions/dm-mcp-adapter/dist/package-mcp-loader.js +0 -135
  534. package/extensions/dm-mcp-adapter/dist/request-headers-command.js +0 -294
  535. package/extensions/dm-mcp-adapter/dist/resource-tools.js +0 -7
  536. package/extensions/dm-mcp-adapter/dist/runtime-owner.js +0 -94
  537. package/extensions/dm-mcp-adapter/dist/sampling-handler.js +0 -213
  538. package/extensions/dm-mcp-adapter/dist/secure-keyring.js +0 -191
  539. package/extensions/dm-mcp-adapter/dist/server-manager.js +0 -1514
  540. package/extensions/dm-mcp-adapter/dist/session-approvals.js +0 -127
  541. package/extensions/dm-mcp-adapter/dist/session-recovery.js +0 -82
  542. package/extensions/dm-mcp-adapter/dist/state.js +0 -1
  543. package/extensions/dm-mcp-adapter/dist/types.js +0 -286
  544. package/extensions/dm-mcp-adapter/dist/ui-app-bridge-helpers.js +0 -36
  545. package/extensions/dm-mcp-adapter/dist/ui-resource-handler.js +0 -204
  546. package/extensions/dm-mcp-adapter/dist/ui-stream-types.js +0 -58
  547. package/extensions/dm-mcp-adapter/dist/ui-tool-visibility.js +0 -26
  548. package/extensions/dm-mcp-adapter/dist/unix-socket-transport.js +0 -83
  549. package/extensions/dm-mcp-adapter/dist/utils.js +0 -382
@@ -1,2709 +0,0 @@
1
- import { spawn as nodeSpawn } from "node:child_process";
2
- import { EventEmitter } from "node:events";
3
- import { access, lstat, readFile } from "node:fs/promises";
4
- import * as os from "node:os";
5
- import { pathToFileURL } from "node:url";
6
- import { emitBounded } from "../bounded-telemetry.js";
7
- import { withTimeout } from "../deadline-utils.js";
8
- import { minimatch } from "../deps/minimatch.js";
9
- import { mapWithConcurrency } from "../map-with-concurrency.js";
10
- import { incrementDegradationCount, recordDegradationOnce } from "../degradation-ledger.js";
11
- import { CancellationTokenSource, createMessageConnection, StreamMessageReader, StreamMessageWriter } from "../deps/vscode-jsonrpc.js";
12
- import { logExtension } from "../extension-log.js";
13
- import { recordLspChild, removeLspChild } from "../instance-registry.js";
14
- import { workspaceDiagnosticsCacheSessionStart } from "./workspace-diagnostics-session.js";
15
- import { logLatency } from "../latency-logger.js";
16
- import { newLspMutationCorrelationId } from "../lsp-mutation.js";
17
- import { getProcessSingleton } from "../process-singletons.js";
18
- import { getAmbientAbortSignal, isOwnLiveChild, releaseOwnChildPid } from "../safe-spawn.js";
19
- import { raceToCompletion } from "./aggregation.js";
20
- import { hashDiagnosticContent } from "./diagnostic-binding.js";
21
- import { applyWorkspaceEdit, normalizeWorkspaceEditToUtf16 } from "./edits.js";
22
- import { normalizeMapKey, uriToPath } from "./path-utils.js";
23
- import { ADVERTISED_POSITION_ENCODINGS, convertCharacterOffset, lineTextAt, negotiatePositionEncoding } from "./position-encoding.js";
24
- import { negotiateSaveOptions, negotiateSyncKind, TEXT_DOCUMENT_SYNC_KIND_FULL, TEXT_DOCUMENT_SYNC_KIND_INCREMENTAL } from "./sync-kind.js";
25
- import { exceedsLspSyncLimits } from "./content-limits.js";
26
- import { probeTsserverProjectIdentity } from "./tsserver-sync.js";
27
- import { getStrategy } from "./wait-policy/index.js";
28
- import { WatchedFilesQueue } from "./watch-queue.js";
29
- import { clearAllWorkspaceDiagnosticsCaches, clearWorkspaceDiagnosticsCacheAtAndAbove } from "./workspace-diagnostics-cache.js";
30
- const PUB_DEBUG = Boolean(process.env.PILENS_PUB_DEBUG);
31
- function extractSpawnMarker(args) {
32
- if (!args)
33
- return;
34
- const tmpDir = os.tmpdir();
35
- for (let i = 0;i < args.length - 1; i++) {
36
- const flag = args[i];
37
- if (flag === "--config" || flag === "-c") {
38
- const value = args[i + 1];
39
- if (value?.startsWith(tmpDir))
40
- return value;
41
- }
42
- }
43
- return;
44
- }
45
- export const INITIALIZE_TIMEOUT_MS = positiveIntFromEnv("DM_LENS_LSP_INIT_TIMEOUT_MS", 15000);
46
- export const CLIENT_CAPABILITIES = {
47
- general: { positionEncodings: ADVERTISED_POSITION_ENCODINGS },
48
- window: {},
49
- workspace: {
50
- workspaceFolders: true,
51
- configuration: true,
52
- didChangeWatchedFiles: { dynamicRegistration: true },
53
- fileOperations: {
54
- dynamicRegistration: false,
55
- willRename: true,
56
- didRename: true
57
- }
58
- },
59
- textDocument: {
60
- synchronization: {
61
- dynamicRegistration: false,
62
- willSave: false,
63
- willSaveWaitUntil: false,
64
- didSave: true
65
- },
66
- completion: {
67
- dynamicRegistration: false,
68
- completionItem: { snippetSupport: false }
69
- },
70
- hover: { dynamicRegistration: false },
71
- signatureHelp: { dynamicRegistration: false },
72
- definition: { dynamicRegistration: false },
73
- typeDefinition: { dynamicRegistration: false },
74
- implementation: { dynamicRegistration: false },
75
- references: { dynamicRegistration: false },
76
- documentSymbol: { dynamicRegistration: false },
77
- codeAction: {
78
- dynamicRegistration: false,
79
- dataSupport: true,
80
- resolveSupport: { properties: ["edit", "command"] },
81
- codeActionLiteralSupport: {
82
- codeActionKind: {
83
- valueSet: [
84
- "quickfix",
85
- "refactor",
86
- "refactor.extract",
87
- "refactor.inline",
88
- "refactor.rewrite",
89
- "source",
90
- "source.organizeImports"
91
- ]
92
- }
93
- }
94
- },
95
- rename: { dynamicRegistration: false },
96
- publishDiagnostics: {
97
- relatedInformation: true,
98
- versionSupport: true
99
- }
100
- }
101
- };
102
- const NAV_REQUEST_TIMEOUT_MS = positiveIntFromEnv("DM_LENS_LSP_NAV_REQUEST_TIMEOUT_MS", 1e4);
103
- const DIAGNOSTICS_WAIT_TIMEOUT_MS = positiveIntFromEnv("DM_LENS_LSP_DIAGNOSTICS_WAIT_MS", 1e4);
104
- const PULL_DIAGNOSTICS_RETRY_INTERVAL_MS = positiveIntFromEnv("DM_LENS_LSP_PULL_RETRY_INTERVAL_MS", 250);
105
- const PULL_REQUEST_TIMEOUT_MS = positiveIntFromEnv("DM_LENS_LSP_PULL_REQUEST_TIMEOUT_MS", 1e4);
106
- const PULL_MIN_USABLE_BUDGET_MS = 5;
107
- const SHUTDOWN_REQUEST_TIMEOUT_MS = positiveIntFromEnv("DM_LENS_LSP_SHUTDOWN_TIMEOUT_MS", 1000);
108
- const EXIT_NOTIFY_TIMEOUT_MS = positiveIntFromEnv("DM_LENS_LSP_EXIT_NOTIFY_TIMEOUT_MS", 1000);
109
- const LIVENESS_PING_TIMEOUT_MS = positiveIntFromEnv("DM_LENS_LSP_LIVENESS_PING_TIMEOUT_MS", 300);
110
- const LIVENESS_PING_QUERY = "__dm_lens_liveness_ping__";
111
- const WORKSPACE_PULL_RESULT_CACHE_MAX = 4096;
112
- const WORKSPACE_PULL_SCOPE = "*workspace*";
113
- const REFRESH_REPULL_CONCURRENCY = 4;
114
- const EXECUTE_COMMAND_TIMEOUT_MS = positiveIntFromEnv("DM_LENS_LSP_EXECUTE_COMMAND_TIMEOUT_MS", 30000);
115
- const PROBE_COMMAND_TIMEOUT_MS = positiveIntFromEnv("DM_LENS_LSP_PROJECT_IDENTITY_PROBE_TIMEOUT_MS", 2500);
116
- const LSP_CRASH_CODES = new Set([
117
- "ERR_STREAM_DESTROYED",
118
- "ERR_STREAM_WRITE_AFTER_END",
119
- "EPIPE",
120
- "ECONNRESET"
121
- ]);
122
- let crashGuardInstalled = false;
123
- function isIgnorableLspRuntimeCrash(err) {
124
- if (!(err instanceof Error))
125
- return false;
126
- const code = err.code;
127
- if (code && LSP_CRASH_CODES.has(code))
128
- return true;
129
- const msg = err.message.toLowerCase();
130
- const stack = (err.stack ?? "").toLowerCase();
131
- return msg.includes("stream") || msg.includes("write after end") || stack.includes("vscode-jsonrpc/lib/node/ril.js");
132
- }
133
- function installCrashGuard() {
134
- if (crashGuardInstalled)
135
- return;
136
- crashGuardInstalled = true;
137
- process.on("uncaughtException", (err) => {
138
- if (isIgnorableLspRuntimeCrash(err)) {
139
- return;
140
- }
141
- throw err;
142
- });
143
- process.on("unhandledRejection", (reason) => {
144
- if (isIgnorableLspRuntimeCrash(reason)) {
145
- return;
146
- }
147
- throw reason instanceof Error ? reason : new Error(String(reason));
148
- });
149
- }
150
- export const MAX_INCREMENTAL_TEXT_RETAINED_ENTRIES = 128;
151
- export const MAX_INCREMENTAL_TEXT_RETAINED_BYTES = 64 * 1024 * 1024;
152
- const ACTIVE_CLIENTS_FAMILY = "lsp-client.active-clients";
153
- const ACTIVE_CLIENTS_VERSION = 1;
154
- function activeLspClientSet() {
155
- return getProcessSingleton(ACTIVE_CLIENTS_FAMILY, ACTIVE_CLIENTS_VERSION, () => new Set);
156
- }
157
- export function getLspDocumentTextRetentionSnapshot() {
158
- let entries = 0;
159
- let bytes = 0;
160
- const roots = new Set;
161
- const active = activeLspClientSet();
162
- for (const state of active) {
163
- entries += state.incrementalTextRetainedEntries ?? 0;
164
- bytes += state.incrementalTextRetainedBytes ?? 0;
165
- if (typeof state.root === "string" && state.root.length > 0) {
166
- roots.add(state.root);
167
- }
168
- }
169
- return { clients: active.size, entries, bytes, roots: roots.size };
170
- }
171
- function isClientAlive(state) {
172
- return state.isConnected && !state.isDestroyed && !state.lspProcess.process.killed;
173
- }
174
- function disposeClientConnection(state) {
175
- if (state.connectionDisposed)
176
- return;
177
- state.connectionDisposed = true;
178
- activeLspClientSet().delete(state);
179
- try {
180
- state.connection.dispose();
181
- } catch {}
182
- }
183
- export async function killProcessTree(proc, pid, options = {}) {
184
- if ((proc.exitCode != null || proc.signalCode != null) && !options.processExiting) {
185
- releaseOwnChildPid(pid);
186
- proc.unref?.();
187
- return;
188
- }
189
- if (process.platform === "win32" && pid > 0) {
190
- if (options.processExiting) {
191
- try {
192
- proc.kill();
193
- } catch {}
194
- proc.unref?.();
195
- return;
196
- }
197
- try {
198
- const taskkill = `${process.env.SystemRoot ?? "C:\\Windows"}\\System32\\taskkill.exe`;
199
- const killer = nodeSpawn(taskkill, ["/F", "/T", "/PID", String(pid)], {
200
- shell: false,
201
- windowsHide: true,
202
- stdio: "ignore",
203
- detached: !!options.fast
204
- });
205
- if (options.fast) {
206
- killer.unref();
207
- proc.unref?.();
208
- return;
209
- }
210
- await new Promise((resolve) => {
211
- killer.once("close", () => resolve());
212
- killer.once("error", (err) => {
213
- logLatency({
214
- type: "phase",
215
- phase: "lsp_kill_escalation",
216
- filePath: "",
217
- durationMs: 0,
218
- metadata: { pid, platform: "win32", taskkillError: String(err) }
219
- });
220
- resolve();
221
- });
222
- });
223
- } catch (err) {
224
- logLatency({
225
- type: "phase",
226
- phase: "lsp_kill_escalation",
227
- filePath: "",
228
- durationMs: 0,
229
- metadata: { pid, platform: "win32", taskkillSpawnError: String(err) }
230
- });
231
- }
232
- return;
233
- }
234
- const killPosixProcessGroup = (signal) => {
235
- if (!isOwnLiveChild(pid, "lsp-stop-posix-group"))
236
- return false;
237
- try {
238
- process.kill(-pid, signal);
239
- return true;
240
- } catch {
241
- return false;
242
- }
243
- };
244
- const killDirectChild = (signal) => {
245
- try {
246
- proc.kill(signal);
247
- } catch {}
248
- };
249
- try {
250
- let exited = proc.exitCode != null || proc.signalCode != null;
251
- proc.once?.("exit", () => {
252
- exited = true;
253
- });
254
- if (!killPosixProcessGroup("SIGTERM")) {
255
- killDirectChild("SIGTERM");
256
- }
257
- if (options.fast) {
258
- const timer = setTimeout(() => {
259
- if (!exited) {
260
- logLatency({
261
- type: "phase",
262
- phase: "lsp_kill_escalation",
263
- filePath: "",
264
- durationMs: 1500,
265
- metadata: { pid, platform: "posix", method: "SIGKILL", fast: true }
266
- });
267
- if (!killPosixProcessGroup("SIGKILL")) {
268
- killDirectChild("SIGKILL");
269
- }
270
- }
271
- releaseOwnChildPid(pid);
272
- }, 1500);
273
- timer.unref?.();
274
- proc.unref?.();
275
- return;
276
- }
277
- const exitedInTime = await new Promise((resolve) => {
278
- if (proc.exitCode != null || proc.signalCode != null) {
279
- resolve(true);
280
- return;
281
- }
282
- const onExit = () => {
283
- clearTimeout(timer);
284
- resolve(true);
285
- };
286
- const timer = setTimeout(() => {
287
- proc.off?.("exit", onExit);
288
- resolve(false);
289
- }, 1500);
290
- proc.once?.("exit", onExit);
291
- });
292
- if (!exitedInTime && !exited) {
293
- logLatency({
294
- type: "phase",
295
- phase: "lsp_kill_escalation",
296
- filePath: "",
297
- durationMs: 1500,
298
- metadata: { pid, platform: "posix", method: "SIGKILL", fast: false }
299
- });
300
- if (!killPosixProcessGroup("SIGKILL")) {
301
- killDirectChild("SIGKILL");
302
- }
303
- }
304
- releaseOwnChildPid(pid);
305
- } catch {}
306
- }
307
- export function stripDiagnosticNoiseLines(message) {
308
- const cleaned = message.split(/\r?\n/).filter((line) => {
309
- const trimmed = line.trim();
310
- if (/^for further information visit\b/i.test(trimmed))
311
- return false;
312
- if (/^https?:\/\/\S+$/i.test(trimmed))
313
- return false;
314
- return true;
315
- }).join(`
316
- `).trim();
317
- return cleaned || message.trim() || message;
318
- }
319
- function normalizeLspDiagnostic(diagnostic) {
320
- const message = stripDiagnosticNoiseLines(diagnostic.message);
321
- return message === diagnostic.message ? diagnostic : { ...diagnostic, message };
322
- }
323
- function normalizeLspDiagnostics(diagnostics) {
324
- return diagnostics.map(normalizeLspDiagnostic);
325
- }
326
- function mergeDiagnosticLists(...lists) {
327
- const merged = [];
328
- const seen = new Set;
329
- for (const diagnostic of lists.flatMap((list) => list ?? [])) {
330
- const key = [
331
- diagnostic.range.start.line,
332
- diagnostic.range.start.character,
333
- diagnostic.range.end.line,
334
- diagnostic.range.end.character,
335
- diagnostic.code ?? "",
336
- diagnostic.source ?? "",
337
- diagnostic.message
338
- ].join(":");
339
- if (seen.has(key))
340
- continue;
341
- seen.add(key);
342
- merged.push(diagnostic);
343
- }
344
- return merged;
345
- }
346
- function getMergedDiagnosticsForPath(state, normalizedPath) {
347
- const legacy = state;
348
- return mergeDiagnosticLists(state.pushDiagnostics?.get(normalizedPath) ?? legacy.diagnostics?.get(normalizedPath), state.documentPullDiagnostics?.get(normalizedPath));
349
- }
350
- const PULL_SOURCE_KEY_SEPARATOR = "\x00";
351
- const BARE_PULL_SOURCE = "";
352
- function pullSourceKey(normalizedPath, identifier) {
353
- return identifier === undefined ? normalizedPath : `${normalizedPath}${PULL_SOURCE_KEY_SEPARATOR}${identifier}`;
354
- }
355
- function pullSourceKeysForPath(state, normalizedPath) {
356
- const prefix = `${normalizedPath}${PULL_SOURCE_KEY_SEPARATOR}`;
357
- return [
358
- normalizedPath,
359
- ...[...state.pullResultIds?.keys() ?? []].filter((key) => key.startsWith(prefix))
360
- ];
361
- }
362
- function pullSourcesFor(state, normalizedPath) {
363
- if (!state.documentPullDiagnosticsBySource) {
364
- state.documentPullDiagnosticsBySource = new Map;
365
- }
366
- let sources = state.documentPullDiagnosticsBySource.get(normalizedPath);
367
- if (!sources) {
368
- sources = new Map;
369
- state.documentPullDiagnosticsBySource.set(normalizedPath, sources);
370
- }
371
- return sources;
372
- }
373
- function pullSourceDiagnostics(state, normalizedPath, identifier) {
374
- const sources = state.documentPullDiagnosticsBySource?.get(normalizedPath);
375
- const stored = sources?.get(identifier ?? BARE_PULL_SOURCE);
376
- if (stored)
377
- return stored;
378
- return sources && sources.size > 0 ? [] : state.documentPullDiagnostics.get(normalizedPath) ?? [];
379
- }
380
- function storePullSourceDiagnostics(state, normalizedPath, identifier, diagnostics) {
381
- const sources = pullSourcesFor(state, normalizedPath);
382
- sources.set(identifier ?? BARE_PULL_SOURCE, diagnostics);
383
- state.documentPullDiagnostics.set(normalizedPath, mergeDiagnosticLists(...sources.values()));
384
- }
385
- function pullGenerationFor(state, normalizedPath) {
386
- return state.pullGenerations?.get(normalizedPath) ?? 0;
387
- }
388
- function bumpPullGeneration(state, normalizedPath) {
389
- if (!state.pullGenerations)
390
- state.pullGenerations = new Map;
391
- state.pullGenerations.set(normalizedPath, (state.pullGenerations.get(normalizedPath) ?? 0) + 1);
392
- }
393
- function claimPullRequestSequence(state, sourceKey) {
394
- if (!state.pullRequestSequences)
395
- state.pullRequestSequences = new Map;
396
- const next = (state.pullRequestSequences.get(sourceKey) ?? 0) + 1;
397
- state.pullRequestSequences.set(sourceKey, next);
398
- return next;
399
- }
400
- function isNewestPullRequest(state, sourceKey, sequence) {
401
- return (state.pullRequestSequences?.get(sourceKey) ?? 0) === sequence;
402
- }
403
- function retirePullSource(state, identifier) {
404
- const suffix = `${PULL_SOURCE_KEY_SEPARATOR}${identifier}`;
405
- for (const source of [state.pullResultIds, state.pullRequestSequences]) {
406
- if (!source)
407
- continue;
408
- for (const key of source.keys()) {
409
- if (key.endsWith(suffix))
410
- source.delete(key);
411
- }
412
- }
413
- for (const [normalizedPath, sources] of state.documentPullDiagnosticsBySource ?? []) {
414
- if (!sources.delete(identifier))
415
- continue;
416
- state.documentPullDiagnostics.set(normalizedPath, mergeDiagnosticLists(...sources.values()));
417
- bumpDiagnosticsVersion(state, normalizedPath);
418
- state.diagnosticEmitter.emit("diagnostics", normalizedPath);
419
- }
420
- }
421
- export function pullDiagnosticSources(state) {
422
- const identifiers = new Set;
423
- for (const registration of state.dynamicRegistrations?.values() ?? []) {
424
- if (registration.method !== "textDocument/diagnostic")
425
- continue;
426
- if (registration.identifier)
427
- identifiers.add(registration.identifier);
428
- }
429
- return [undefined, ...[...identifiers].sort((a, b) => a.localeCompare(b))];
430
- }
431
- export function bumpDiagnosticsVersion(state, normalizedPath) {
432
- state.diagnosticsVersion += 1;
433
- state.diagnosticsVersionsByPath?.set(normalizedPath, state.diagnosticsVersion);
434
- }
435
- export function diagnosticsVersionForPath(state, normalizedPath) {
436
- return state.diagnosticsVersionsByPath?.get(normalizedPath) ?? 0;
437
- }
438
- export function clearDiagnosticsForPath(state, normalizedPath) {
439
- const legacy = state;
440
- state.pushDiagnostics?.delete(normalizedPath);
441
- const pending = state.pendingDiagnostics?.get(normalizedPath);
442
- if (pending)
443
- clearTimeout(pending);
444
- state.pendingDiagnostics?.delete(normalizedPath);
445
- state.pushDiagnosticTimestamps?.delete(normalizedPath);
446
- state.documentPullDiagnostics?.delete(normalizedPath);
447
- state.documentPullDiagnosticTimestamps?.delete(normalizedPath);
448
- state.diagnosticDocVersions?.delete(normalizedPath);
449
- state.diagnosticBindings?.delete(normalizedPath);
450
- state.diagnosticsVersionsByPath?.delete(normalizedPath);
451
- for (const key of pullSourceKeysForPath(state, normalizedPath)) {
452
- state.pullResultIds?.delete(key);
453
- }
454
- state.documentPullDiagnosticsBySource?.delete(normalizedPath);
455
- bumpPullGeneration(state, normalizedPath);
456
- state.workspacePullResultCache?.delete(normalizedPath);
457
- legacy.diagnostics?.delete(normalizedPath);
458
- legacy.diagnosticTimestamps?.delete(normalizedPath);
459
- }
460
- function logTypeScriptPullSettle(state, normalizedPath, durationMs, pullSettleSource) {
461
- if (state.serverId !== "typescript")
462
- return;
463
- const diagnostics = state.documentPullDiagnostics.get(normalizedPath) ?? [];
464
- const elapsedSinceDidOpenMs = Math.max(0, Date.now() - (state.documentOpenedAt.get(normalizedPath) ?? Date.now()));
465
- const diagnosticCodes = [
466
- ...new Set(diagnostics.map((diagnostic) => diagnostic.code).filter((code) => code !== undefined).map(String))
467
- ].slice(0, 8);
468
- const trackedVersion = state.diagnosticsVersionsByPath?.get(normalizedPath);
469
- logLatency({
470
- type: "phase",
471
- phase: "lsp_typescript_diagnostic_sequence",
472
- filePath: normalizedPath,
473
- durationMs,
474
- metadata: {
475
- serverId: state.serverId,
476
- outcome: "settled",
477
- launchVariant: state.launchVariant ?? "unknown",
478
- publicationIndex: state.diagnosticPublicationCounts.get(normalizedPath) ?? 0,
479
- version: trackedVersion ?? "pull-unversioned",
480
- diagnosticCount: diagnostics.length,
481
- diagnosticCodes,
482
- elapsedSinceDidOpenMs,
483
- settledReturn: true,
484
- settleSource: pullSettleSource
485
- }
486
- });
487
- }
488
- function scanSentContent(content) {
489
- let lfNewlineCount = 0;
490
- let index = 0;
491
- let start = 0;
492
- for (let i = 0;i < content.length; i++) {
493
- const code = content.charCodeAt(i);
494
- if (code !== 10 && code !== 13)
495
- continue;
496
- if (code === 10) {
497
- lfNewlineCount++;
498
- } else if (content.charCodeAt(i + 1) === 10) {
499
- lfNewlineCount++;
500
- i++;
501
- }
502
- index++;
503
- start = i + 1;
504
- }
505
- return { lfNewlineCount, lastLine: { index, start } };
506
- }
507
- function recordSentContent(state, normalizedPath, version, content, coalescedCount = 0) {
508
- const scan = scanSentContent(content);
509
- const previous = state.documentContentHashes.get(normalizedPath);
510
- if (previous && previous.version > version) {
511
- incrementDegradationCount({
512
- kind: "lsp-document-send-order",
513
- subject: `${state.serverId}:${normalizedPath}`,
514
- reason: `recorded version ${version} after newer version ${previous.version}`
515
- });
516
- return;
517
- }
518
- if (previous?.text !== undefined) {
519
- state.incrementalTextRetainedEntries = Math.max(0, (state.incrementalTextRetainedEntries ?? 1) - 1);
520
- state.incrementalTextRetainedBytes = Math.max(0, (state.incrementalTextRetainedBytes ?? previous.text.length * 2) - previous.text.length * 2);
521
- state.incrementalTextBearingPaths?.delete(normalizedPath);
522
- }
523
- state.documentContentHashes.delete(normalizedPath);
524
- state.documentContentHashes.set(normalizedPath, {
525
- version,
526
- hash: hashDiagnosticContent(content),
527
- ...state.syncKind === TEXT_DOCUMENT_SYNC_KIND_INCREMENTAL && {
528
- text: content,
529
- lastLine: scan.lastLine
530
- }
531
- });
532
- if (state.syncKind === TEXT_DOCUMENT_SYNC_KIND_INCREMENTAL) {
533
- state.incrementalTextRetainedEntries = (state.incrementalTextRetainedEntries ?? 0) + 1;
534
- state.incrementalTextRetainedBytes = (state.incrementalTextRetainedBytes ?? 0) + content.length * 2;
535
- if (!state.incrementalTextBearingPaths) {
536
- state.incrementalTextBearingPaths = new Set;
537
- }
538
- state.incrementalTextBearingPaths.add(normalizedPath);
539
- while ((state.incrementalTextRetainedEntries ?? 0) > MAX_INCREMENTAL_TEXT_RETAINED_ENTRIES || (state.incrementalTextRetainedBytes ?? 0) > MAX_INCREMENTAL_TEXT_RETAINED_BYTES) {
540
- const oldestPath = state.incrementalTextBearingPaths?.values().next().value;
541
- if (oldestPath === undefined)
542
- break;
543
- const binding = state.documentContentHashes.get(oldestPath);
544
- state.incrementalTextBearingPaths.delete(oldestPath);
545
- if (!binding || binding.text === undefined)
546
- continue;
547
- state.documentContentHashes.set(oldestPath, {
548
- version: binding.version,
549
- hash: binding.hash
550
- });
551
- state.incrementalTextRetainedEntries = Math.max(0, (state.incrementalTextRetainedEntries ?? 1) - 1);
552
- state.incrementalTextRetainedBytes = Math.max(0, (state.incrementalTextRetainedBytes ?? 0) - binding.text.length * 2);
553
- }
554
- }
555
- logLatency({
556
- type: "phase",
557
- phase: "lsp_document_send",
558
- filePath: normalizedPath,
559
- durationMs: 0,
560
- metadata: {
561
- version,
562
- contentLength: content.length,
563
- contentLineCount: scan.lfNewlineCount + 1,
564
- ...coalescedCount > 0 && { coalescedCount }
565
- }
566
- });
567
- }
568
- function buildContentChanges(state, normalizedPath, content) {
569
- if (state.syncKind !== TEXT_DOCUMENT_SYNC_KIND_INCREMENTAL) {
570
- return [{ text: content }];
571
- }
572
- const previous = state.documentContentHashes.get(normalizedPath);
573
- if (previous?.text === undefined) {
574
- return [{ text: content }];
575
- }
576
- const previousText = previous.text;
577
- const lastLine = previous.lastLine ?? scanSentContent(previousText).lastLine;
578
- const lastLineText = previousText.slice(lastLine.start);
579
- return [
580
- {
581
- range: {
582
- start: { line: 0, character: 0 },
583
- end: {
584
- line: lastLine.index,
585
- character: convertCharacterOffset(state.positionEncoding, lastLineText, lastLineText.length)
586
- }
587
- },
588
- text: content
589
- }
590
- ];
591
- }
592
- const DYNAMIC_OPERATION_METHOD_MAP = {
593
- "textDocument/definition": "definition",
594
- "textDocument/typeDefinition": "typeDefinition",
595
- "textDocument/declaration": "declaration",
596
- "textDocument/references": "references",
597
- "textDocument/hover": "hover",
598
- "textDocument/signatureHelp": "signatureHelp",
599
- "textDocument/documentSymbol": "documentSymbol",
600
- "workspace/symbol": "workspaceSymbol",
601
- "textDocument/codeAction": "codeAction",
602
- "textDocument/rename": "rename",
603
- "textDocument/implementation": "implementation",
604
- "textDocument/prepareCallHierarchy": "callHierarchy"
605
- };
606
- export function applyDynamicCapabilities(state) {
607
- const registrations = [...state.dynamicRegistrations.values()];
608
- const registeredMethods = new Set(registrations.map((r) => r.method));
609
- const hasDynamicPull = registeredMethods.has("textDocument/diagnostic") || registeredMethods.has("workspace/diagnostic");
610
- if (hasDynamicPull) {
611
- state.workspaceDiagnosticsSupport = {
612
- advertised: true,
613
- mode: "pull",
614
- workspaceDiagnostics: registrations.some((r) => r.workspaceDiagnostics === true) || registeredMethods.has("workspace/diagnostic"),
615
- diagnosticProviderKind: "dynamic"
616
- };
617
- } else if (state.staticDiagnosticsMode === "push-only" && state.workspaceDiagnosticsSupport.diagnosticProviderKind === "dynamic") {
618
- state.workspaceDiagnosticsSupport = {
619
- advertised: false,
620
- mode: "push-only",
621
- workspaceDiagnostics: false,
622
- diagnosticProviderKind: "none"
623
- };
624
- }
625
- for (const [method, key] of Object.entries(DYNAMIC_OPERATION_METHOD_MAP)) {
626
- if (registeredMethods.has(method)) {
627
- state.operationSupport[key] = true;
628
- }
629
- }
630
- }
631
- export function resolveConfigurationSection(initialization, section) {
632
- if (!initialization)
633
- return {};
634
- if (!section)
635
- return initialization;
636
- let cur = initialization;
637
- for (const part of section.split(".")) {
638
- if (typeof cur !== "object" || cur === null || !Object.hasOwn(cur, part)) {
639
- return {};
640
- }
641
- cur = cur[part];
642
- }
643
- return cur;
644
- }
645
- export function setupIncomingHandlers(state, initialization, onDiagnosticsPublished) {
646
- state.connection.onNotification("textDocument/publishDiagnostics", (params) => {
647
- const publishReceivedAt = Date.now();
648
- const filePath = uriToPath(params.uri);
649
- const normalizedPath = normalizeMapKey(filePath);
650
- if (state.closedDocuments?.has(normalizedPath))
651
- return;
652
- onDiagnosticsPublished?.(state.serverId);
653
- const newDiags = normalizeLspDiagnostics(params.diagnostics || []);
654
- const docVersion = params.version;
655
- if (PUB_DEBUG) {
656
- logExtension({
657
- subsystem: "lsp-pub",
658
- level: "debug",
659
- message: `server=${state.serverId} pubVersion=${docVersion} docVersion=${state.documentVersions?.get(normalizedPath)} diags=${newDiags.length}`
660
- });
661
- }
662
- const strategy = getStrategy(state.serverId, state.launchVariant);
663
- const isTypeScriptTelemetry = state.serverId === "typescript";
664
- const publicationIndex = isTypeScriptTelemetry ? (state.diagnosticPublicationCounts.get(normalizedPath) ?? 0) + 1 : 0;
665
- if (isTypeScriptTelemetry) {
666
- state.diagnosticPublicationCounts.set(normalizedPath, publicationIndex);
667
- }
668
- const diagnosticCodes = isTypeScriptTelemetry ? [
669
- ...new Set(newDiags.map((diagnostic) => diagnostic.code).filter((code) => code !== undefined).map(String))
670
- ].slice(0, 8) : [];
671
- const logSequence = (settledReturn, settleSource, durationMs) => {
672
- if (state.serverId !== "typescript")
673
- return;
674
- const elapsedSinceDidOpenMs = Math.max(0, Date.now() - (state.documentOpenedAt.get(normalizedPath) ?? Date.now()));
675
- logLatency({
676
- type: "phase",
677
- phase: "lsp_typescript_diagnostic_sequence",
678
- filePath: normalizedPath,
679
- durationMs,
680
- metadata: {
681
- serverId: state.serverId,
682
- outcome: settledReturn ? "settled" : "published",
683
- launchVariant: state.launchVariant ?? "unknown",
684
- publicationIndex,
685
- version: docVersion ?? "push-unversioned",
686
- diagnosticCount: newDiags.length,
687
- diagnosticCodes,
688
- elapsedSinceDidOpenMs,
689
- settledReturn,
690
- settleSource
691
- }
692
- });
693
- };
694
- const recordDocVersion = () => {
695
- if (docVersion !== undefined) {
696
- state.diagnosticDocVersions.set(normalizedPath, docVersion);
697
- }
698
- recordBinding();
699
- };
700
- const recordBinding = () => {
701
- if (docVersion === undefined) {
702
- state.diagnosticBindings.delete(normalizedPath);
703
- return;
704
- }
705
- const sent = state.documentContentHashes.get(normalizedPath);
706
- state.diagnosticBindings.set(normalizedPath, {
707
- version: docVersion,
708
- contentHash: sent && sent.version === docVersion ? sent.hash : undefined
709
- });
710
- };
711
- const isSupersededPush = () => {
712
- if (docVersion === undefined)
713
- return false;
714
- const currentVersion = state.documentVersions.get(normalizedPath);
715
- return currentVersion !== undefined && docVersion < currentVersion;
716
- };
717
- if (strategy.emptyFirstPublish === "indexing" && !state.emptyFirstPublishHoldSpent && newDiags.length === 0 && !state.pushDiagnostics.has(normalizedPath) && !state.pendingDiagnostics.has(normalizedPath)) {
718
- state.emptyFirstPublishHoldSpent = true;
719
- logLatency({
720
- type: "phase",
721
- phase: "lsp_empty_first_publish_held",
722
- filePath: normalizedPath,
723
- durationMs: Math.max(0, publishReceivedAt - (state.documentOpenedAt.get(normalizedPath) ?? publishReceivedAt)),
724
- metadata: {
725
- serverId: state.serverId,
726
- emptyFirstPublish: strategy.emptyFirstPublish,
727
- pubVersion: docVersion ?? "push-unversioned"
728
- }
729
- });
730
- return;
731
- }
732
- if (strategy.seedFirstPush && !state.pushDiagnostics.has(normalizedPath)) {
733
- if (isSupersededPush())
734
- return;
735
- state.pushDiagnostics.set(normalizedPath, newDiags);
736
- state.pushDiagnosticTimestamps.set(normalizedPath, Date.now());
737
- recordDocVersion();
738
- bumpDiagnosticsVersion(state, normalizedPath);
739
- state.diagnosticEmitter.emit("diagnostics", normalizedPath);
740
- logSequence(true, "first-push", 0);
741
- return;
742
- }
743
- logSequence(false, "publication", 0);
744
- const existingTimer = state.pendingDiagnostics.get(normalizedPath);
745
- if (existingTimer)
746
- clearTimeout(existingTimer);
747
- const timer = setTimeout(() => {
748
- state.pendingDiagnostics.delete(normalizedPath);
749
- if (isSupersededPush())
750
- return;
751
- state.pushDiagnostics.set(normalizedPath, newDiags);
752
- state.pushDiagnosticTimestamps.set(normalizedPath, Date.now());
753
- recordDocVersion();
754
- bumpDiagnosticsVersion(state, normalizedPath);
755
- state.diagnosticEmitter.emit("diagnostics", normalizedPath);
756
- logSequence(true, "quiet-window", Date.now() - publishReceivedAt);
757
- }, strategy.debounceMs);
758
- state.pendingDiagnostics.set(normalizedPath, timer);
759
- });
760
- state.connection.onRequest("workspace/workspaceFolders", () => [
761
- { name: "workspace", uri: pathToFileURL(state.root).href }
762
- ]);
763
- state.connection.onRequest("client/registerCapability", async (params) => {
764
- for (const reg of params?.registrations ?? []) {
765
- const options = reg.registerOptions;
766
- const commands = Array.isArray(options?.commands) ? options.commands.filter((cmd) => typeof cmd === "string") : undefined;
767
- if (reg.id && reg.method) {
768
- state.dynamicRegistrations.set(reg.id, {
769
- method: reg.method,
770
- ...typeof options?.identifier === "string" && options.identifier ? { identifier: options.identifier } : {},
771
- ...typeof options?.workspaceDiagnostics === "boolean" ? { workspaceDiagnostics: options.workspaceDiagnostics } : {},
772
- ...commands ? { commands } : {}
773
- });
774
- }
775
- if (reg.method === "workspace/executeCommand" && commands) {
776
- for (const cmd of commands)
777
- state.advertisedCommands.add(cmd);
778
- }
779
- }
780
- applyDynamicCapabilities(state);
781
- });
782
- state.connection.onRequest("client/unregisterCapability", async (params) => {
783
- const retiredIdentifiers = new Set;
784
- for (const unreg of params?.unregisterations ?? []) {
785
- if (!unreg.id)
786
- continue;
787
- const registration = state.dynamicRegistrations.get(unreg.id);
788
- state.dynamicRegistrations.delete(unreg.id);
789
- if (registration?.method === "textDocument/diagnostic" && registration.identifier) {
790
- retiredIdentifiers.add(registration.identifier);
791
- }
792
- }
793
- const stillRegistered = new Set([...state.dynamicRegistrations.values()].filter((r) => r.method === "textDocument/diagnostic").map((r) => r.identifier));
794
- for (const identifier of retiredIdentifiers) {
795
- if (!stillRegistered.has(identifier)) {
796
- retirePullSource(state, identifier);
797
- }
798
- }
799
- applyDynamicCapabilities(state);
800
- });
801
- state.connection.onRequest("workspace/applyEdit", async (params) => {
802
- if (state.serverEditsAllowed <= 0 || !params?.edit) {
803
- return { applied: false, failureReason: "edit not solicited" };
804
- }
805
- const context = state.activeMutationContext;
806
- const telemetryContext = context ?? {
807
- cwd: state.root,
808
- correlationId: newLspMutationCorrelationId(),
809
- tool: "lsp-workspace-applyEdit",
810
- source: "lsp-execute-command"
811
- };
812
- try {
813
- await applyWorkspaceEdit(params.edit, state.root, {
814
- positionEncoding: state.positionEncoding,
815
- documentVersions: state.documentVersions,
816
- mutationContext: telemetryContext
817
- });
818
- return { applied: true };
819
- } catch (err) {
820
- return {
821
- applied: false,
822
- failureReason: err instanceof Error ? err.message : String(err)
823
- };
824
- }
825
- });
826
- state.connection.onRequest("workspace/configuration", async (params) => {
827
- const items = params?.items ?? [];
828
- return items.map((item) => resolveConfigurationSection(initialization, item?.section));
829
- });
830
- state.connection.onRequest("window/workDoneProgress/create", async () => {});
831
- let refreshRepullRunning = false;
832
- let refreshRepullRerunRequested = false;
833
- const runRefreshRepullPool = async () => {
834
- do {
835
- refreshRepullRerunRequested = false;
836
- const toRepull = state.workspaceDiagnosticsSupport.mode === "pull" ? [...state.openDocuments] : [];
837
- if (toRepull.length > 0) {
838
- try {
839
- await mapWithConcurrency(toRepull, REFRESH_REPULL_CONCURRENCY, async (normalizedPath) => {
840
- const uri = state.openDocumentUris?.get(normalizedPath);
841
- const filePath = uri ? uriToPath(uri) : normalizedPath;
842
- await clientRequestPullDiagnostics(state, filePath);
843
- });
844
- } catch (err) {
845
- incrementDegradationCount({
846
- kind: "lsp-pull-unconfirmed",
847
- subject: state.serverId,
848
- reason: `refresh re-pull threw: ${err instanceof Error ? err.message : String(err)}`
849
- });
850
- }
851
- }
852
- } while (refreshRepullRerunRequested);
853
- refreshRepullRunning = false;
854
- };
855
- state.connection.onRequest("workspace/diagnostic/refresh", async () => {
856
- state.workspacePullResultCache.clear();
857
- clearAllWorkspaceDiagnosticsCaches();
858
- clearWorkspaceDiagnosticsCacheAtAndAbove(state.root);
859
- for (const normalizedPath of state.openDocuments) {
860
- clearDiagnosticsForPath(state, normalizedPath);
861
- }
862
- if (state.workspaceDiagnosticsSupport.mode === "pull" && state.openDocuments.size > 0) {
863
- if (refreshRepullRunning) {
864
- refreshRepullRerunRequested = true;
865
- } else {
866
- refreshRepullRunning = true;
867
- setImmediate(() => {
868
- runRefreshRepullPool();
869
- });
870
- }
871
- }
872
- return null;
873
- });
874
- }
875
- function markExitedIfUnset(state) {
876
- if (state.exitedAt === undefined) {
877
- state.exitedAt = Date.now();
878
- }
879
- }
880
- function setupConnectionLifecycle(state, recentStderr) {
881
- state.connection.onError(([error]) => {
882
- state.lastError = error instanceof Error ? error : new Error(String(error));
883
- state.isConnected = false;
884
- state.isDestroyed = true;
885
- markExitedIfUnset(state);
886
- disposeClientConnection(state);
887
- });
888
- state.connection.onClose(() => {
889
- state.isConnected = false;
890
- state.isDestroyed = true;
891
- markExitedIfUnset(state);
892
- disposeClientConnection(state);
893
- });
894
- state.lspProcess.process.on("exit", (code, signal) => {
895
- const wasIntentional = state.shutdownRequested;
896
- state.isConnected = false;
897
- state.isDestroyed = true;
898
- markExitedIfUnset(state);
899
- disposeClientConnection(state);
900
- if (!wasIntentional) {
901
- logLatency({
902
- type: "phase",
903
- phase: "lsp_server_unexpected_exit",
904
- filePath: state.root,
905
- durationMs: 0,
906
- metadata: {
907
- serverId: state.serverId,
908
- pid: state.lspProcess.pid,
909
- exitCode: code ?? null,
910
- exitSignal: signal ?? null,
911
- stderrTail: recentStderr(20)
912
- }
913
- });
914
- }
915
- });
916
- state.lspProcess.process.on("close", (code, signal) => {
917
- if (state.shutdownRequested)
918
- return;
919
- try {
920
- const stderrTail = recentStderr(20);
921
- incrementDegradationCount({
922
- kind: "lsp-server-unexpected-close",
923
- subject: state.serverId,
924
- reason: `closed unprompted: code=${code ?? "none"} signal=${signal ?? "none"} ` + `stderr=${stderrTail.length > 0 ? `present(${stderrTail.length}b)` : "empty"} root=${state.root}`
925
- });
926
- } catch {}
927
- });
928
- }
929
- const PULL_RACE_BACKSTOP_MARGIN_MS = 25;
930
- async function clientRequestPullDiagnostics(state, filePath, budgetMs = PULL_REQUEST_TIMEOUT_MS) {
931
- if (!isClientAlive(state))
932
- return { status: "unavailable" };
933
- const sources = pullDiagnosticSources(state);
934
- if (sources.length === 1) {
935
- return aggregatePullOutcomes(state, filePath, [
936
- await pullDiagnosticSource(state, filePath, budgetMs, undefined)
937
- ]);
938
- }
939
- const attempts = sources.map((identifier) => pullDiagnosticSource(state, filePath, budgetMs, identifier));
940
- const settled = await raceToCompletion(attempts, (results) => results.some((r) => r.status === "found" && r.primaryCount > 0), {
941
- timeoutMs: Math.max(1, Math.min(PULL_REQUEST_TIMEOUT_MS, budgetMs)) + PULL_RACE_BACKSTOP_MARGIN_MS
942
- });
943
- return aggregatePullOutcomes(state, filePath, settled);
944
- }
945
- function aggregatePullOutcomes(state, filePath, outcomes) {
946
- const found = outcomes.filter((o) => o.status === "found");
947
- if (found.length > 0) {
948
- const normalizedPath = normalizeMapKey(filePath);
949
- const unionCount = state.documentPullDiagnostics.get(normalizedPath)?.length ?? 0;
950
- return {
951
- status: "found",
952
- count: Math.max(unionCount, ...found.map((o) => o.count))
953
- };
954
- }
955
- if (outcomes.some((o) => o.status === "unavailable")) {
956
- return { status: "unavailable" };
957
- }
958
- return outcomes.some((o) => o.status === "clean") ? { status: "clean" } : { status: "unavailable" };
959
- }
960
- async function pullDiagnosticSource(state, filePath, budgetMs, identifier) {
961
- if (!isClientAlive(state))
962
- return { status: "unavailable" };
963
- const normalizedPath = normalizeMapKey(filePath);
964
- if (budgetMs < PULL_MIN_USABLE_BUDGET_MS) {
965
- emitBounded("lsp_pull_skipped_budget_exhausted", `${state.serverId}::${pullSourceKey(normalizedPath, identifier)}`, {
966
- type: "phase",
967
- filePath: normalizedPath,
968
- durationMs: 0,
969
- metadata: {
970
- identifier: identifier ?? "bare",
971
- remainingBudgetMs: budgetMs,
972
- server: state.serverId
973
- }
974
- }, {
975
- ledgerKind: "lsp-pull-skipped-budget-exhausted",
976
- reason: `pull skipped on ${state.serverId}: budget already exhausted (${budgetMs}ms remaining)`
977
- });
978
- return { status: "unavailable" };
979
- }
980
- const uri = pathToFileURL(filePath).href;
981
- const sourceKey = pullSourceKey(normalizedPath, identifier);
982
- if (state.abandonedPullRequests?.has(sourceKey)) {
983
- return { status: "unavailable" };
984
- }
985
- const previousResultId = state.pullResultIds.get(sourceKey);
986
- const generation = pullGenerationFor(state, normalizedPath);
987
- const requestSequence = claimPullRequestSequence(state, sourceKey);
988
- const requestStartedAt = Date.now();
989
- const effectiveTimeoutMs = Math.max(1, Math.min(PULL_REQUEST_TIMEOUT_MS, budgetMs));
990
- const pullAbort = new AbortController;
991
- const pullSettlement = { cancelled: false };
992
- const requestPromise = safeSendRequest(state.connection, "textDocument/diagnostic", {
993
- textDocument: { uri },
994
- ...identifier !== undefined && { identifier },
995
- ...previousResultId !== undefined && { previousResultId }
996
- }, pullAbort.signal, pullSettlement);
997
- try {
998
- const report = await withTimeout(requestPromise, effectiveTimeoutMs);
999
- if (!report) {
1000
- recordPullFailure(state, "textDocument/diagnostic", new Error("empty response"));
1001
- return { status: "unavailable" };
1002
- }
1003
- const now = Date.now();
1004
- const sentHash = state.documentContentHashes.get(normalizedPath)?.hash;
1005
- if (pullGenerationFor(state, normalizedPath) !== generation || !isNewestPullRequest(state, sourceKey, requestSequence)) {
1006
- return { status: "unavailable" };
1007
- }
1008
- let primaryCount;
1009
- if (report.kind === "unchanged") {
1010
- primaryCount = pullSourceDiagnostics(state, normalizedPath, identifier).length;
1011
- state.documentPullDiagnosticTimestamps.set(normalizedPath, now);
1012
- } else {
1013
- const primaryItems = normalizeLspDiagnostics(report.items ?? []);
1014
- storePullSourceDiagnostics(state, normalizedPath, identifier, primaryItems);
1015
- state.documentPullDiagnosticTimestamps.set(normalizedPath, now);
1016
- bumpDiagnosticsVersion(state, normalizedPath);
1017
- state.diagnosticBindings.set(normalizedPath, { contentHash: sentHash });
1018
- primaryCount = primaryItems.length;
1019
- }
1020
- let totalCount = primaryCount;
1021
- if (report.resultId !== undefined) {
1022
- state.pullResultIds.set(sourceKey, report.resultId);
1023
- } else {
1024
- state.pullResultIds.delete(sourceKey);
1025
- }
1026
- if (report.relatedDocuments) {
1027
- for (const [relatedUri, related] of Object.entries(report.relatedDocuments)) {
1028
- const relatedPath = uriToPath(relatedUri);
1029
- const relatedNormalized = normalizeMapKey(relatedPath);
1030
- if (related?.kind === "unchanged") {
1031
- totalCount += pullSourceDiagnostics(state, relatedNormalized, identifier).length;
1032
- state.documentPullDiagnosticTimestamps.set(relatedNormalized, now);
1033
- } else {
1034
- const relatedItems = normalizeLspDiagnostics(related?.items ?? []);
1035
- storePullSourceDiagnostics(state, relatedNormalized, identifier, relatedItems);
1036
- state.documentPullDiagnosticTimestamps.set(relatedNormalized, now);
1037
- state.diagnosticBindings.delete(relatedNormalized);
1038
- totalCount += relatedItems.length;
1039
- }
1040
- if (related?.resultId !== undefined) {
1041
- state.pullResultIds.set(pullSourceKey(relatedNormalized, identifier), related.resultId);
1042
- }
1043
- }
1044
- }
1045
- state.diagnosticEmitter.emit("diagnostics", normalizedPath);
1046
- return totalCount > 0 ? { status: "found", count: totalCount, primaryCount } : { status: "clean" };
1047
- } catch (err) {
1048
- if (isPullTimeoutError(err, effectiveTimeoutMs)) {
1049
- trackAbandonedPullRequest(state, sourceKey, requestPromise);
1050
- pullAbort.abort();
1051
- recordPullTimeoutTelemetry({
1052
- scope: normalizedPath,
1053
- identifier,
1054
- effectiveBudgetMs: effectiveTimeoutMs,
1055
- hadPreviousResultId: previousResultId !== undefined,
1056
- elapsedMs: Date.now() - requestStartedAt,
1057
- server: state.serverId
1058
- });
1059
- armLateAnswerTelemetry({
1060
- requestPromise,
1061
- scope: normalizedPath,
1062
- identifier,
1063
- subject: sourceKey,
1064
- requestStartedAt,
1065
- server: state.serverId,
1066
- settlement: pullSettlement
1067
- });
1068
- }
1069
- recordPullFailure(state, "textDocument/diagnostic", err);
1070
- return { status: "unavailable" };
1071
- }
1072
- }
1073
- function trackAbandonedPullRequest(state, sourceKey, requestPromise) {
1074
- if (!state.abandonedPullRequests)
1075
- state.abandonedPullRequests = new Map;
1076
- state.abandonedPullRequests.set(sourceKey, requestPromise);
1077
- const release = () => {
1078
- if (state.abandonedPullRequests?.get(sourceKey) === requestPromise) {
1079
- state.abandonedPullRequests.delete(sourceKey);
1080
- }
1081
- };
1082
- requestPromise.then(release, release);
1083
- }
1084
- function isPullTimeoutError(err, timeoutMs) {
1085
- return err instanceof Error && err.message === `Timeout after ${timeoutMs}ms`;
1086
- }
1087
- function recordPullTimeoutTelemetry(args) {
1088
- emitBounded("lsp_pull_diagnostic_timeout", `${args.server}::${args.scope}::${args.identifier ?? "bare"}`, {
1089
- type: "phase",
1090
- filePath: args.scope,
1091
- durationMs: args.elapsedMs,
1092
- metadata: {
1093
- identifier: args.identifier ?? "bare",
1094
- effectiveBudgetMs: args.effectiveBudgetMs,
1095
- hadPreviousResultId: args.hadPreviousResultId,
1096
- server: args.server
1097
- }
1098
- }, {
1099
- ledgerKind: "lsp-pull-diagnostic-timeout",
1100
- reason: `pull timeout on ${args.server} after ${args.elapsedMs}ms (budget ${args.effectiveBudgetMs}ms)`
1101
- });
1102
- }
1103
- function armLateAnswerTelemetry(args) {
1104
- args.requestPromise.then(() => {
1105
- if (args.settlement.cancelled)
1106
- return;
1107
- try {
1108
- const elapsedMs = Date.now() - args.requestStartedAt;
1109
- emitBounded("lsp_pull_late_answer_discarded", args.subject, {
1110
- type: "phase",
1111
- filePath: args.scope,
1112
- durationMs: elapsedMs,
1113
- metadata: { identifier: args.identifier ?? "bare" }
1114
- }, {
1115
- ledgerKind: "lsp-pull-late-answer",
1116
- reason: `late pull answer discarded after ${elapsedMs}ms`
1117
- });
1118
- } catch {}
1119
- }, (err) => {
1120
- try {
1121
- const elapsedMs = Date.now() - args.requestStartedAt;
1122
- const candidate = err;
1123
- const code = typeof candidate?.code === "number" || typeof candidate?.code === "string" ? candidate.code : undefined;
1124
- emitBounded("lsp_pull_late_rejection", `${args.server}::${args.subject}`, {
1125
- type: "phase",
1126
- filePath: args.scope,
1127
- durationMs: elapsedMs,
1128
- metadata: {
1129
- identifier: args.identifier ?? "bare",
1130
- server: args.server,
1131
- ...code !== undefined && { code }
1132
- }
1133
- }, {
1134
- ledgerKind: "lsp-pull-late-rejection",
1135
- reason: `late pull rejection ${elapsedMs}ms after timeout${code !== undefined ? ` (code ${code})` : ""}`
1136
- });
1137
- } catch {}
1138
- });
1139
- }
1140
- const PULL_FAILURE_HISTORY_LIMIT = 10;
1141
- function recordPullFailure(state, method, error) {
1142
- const candidate = error;
1143
- const message = typeof candidate.message === "string" ? candidate.message : "";
1144
- const unsupportedMessage = /^(?:method not found|unknown method|unsupported method)(?::|$)/i;
1145
- if (candidate.code === -32601 || candidate.code === "-32601" || unsupportedMessage.test(message.trim()))
1146
- return;
1147
- state.pullFailureHistory.push({
1148
- timestamp: Date.now(),
1149
- method,
1150
- ...typeof candidate.code === "number" || typeof candidate.code === "string" ? { code: candidate.code } : {},
1151
- message: typeof candidate.message === "string" ? candidate.message : String(error)
1152
- });
1153
- if (state.pullFailureHistory.length > PULL_FAILURE_HISTORY_LIMIT) {
1154
- state.pullFailureHistory.splice(0, state.pullFailureHistory.length - PULL_FAILURE_HISTORY_LIMIT);
1155
- }
1156
- }
1157
- export async function clientRequestWorkspaceDiagnostics(state, budgetMs) {
1158
- if (!isClientAlive(state))
1159
- return;
1160
- if (!state.workspaceDiagnosticsSupport.workspaceDiagnostics)
1161
- return;
1162
- if (state.abandonedPullRequests?.has(WORKSPACE_PULL_SCOPE))
1163
- return;
1164
- const previousResultIds = Array.from(state.workspacePullResultCache.values()).map((entry) => ({ uri: entry.uri, value: entry.resultId }));
1165
- if (budgetMs < PULL_MIN_USABLE_BUDGET_MS) {
1166
- emitBounded("lsp_pull_skipped_budget_exhausted", `${state.serverId}::${WORKSPACE_PULL_SCOPE}`, {
1167
- type: "phase",
1168
- filePath: WORKSPACE_PULL_SCOPE,
1169
- durationMs: 0,
1170
- metadata: {
1171
- identifier: "bare",
1172
- remainingBudgetMs: budgetMs,
1173
- server: state.serverId
1174
- }
1175
- }, {
1176
- ledgerKind: "lsp-pull-skipped-budget-exhausted",
1177
- reason: `workspace pull skipped on ${state.serverId}: budget already exhausted (${budgetMs}ms remaining)`
1178
- });
1179
- return;
1180
- }
1181
- const workspacePullStartedAt = Date.now();
1182
- const workspacePullTimeoutMs = Math.max(1, budgetMs);
1183
- const workspacePullAbort = new AbortController;
1184
- const workspacePullSettlement = { cancelled: false };
1185
- const workspaceRequestPromise = safeSendRequest(state.connection, "workspace/diagnostic", { previousResultIds }, workspacePullAbort.signal, workspacePullSettlement);
1186
- try {
1187
- const report = await withTimeout(workspaceRequestPromise, workspacePullTimeoutMs);
1188
- if (!report || !Array.isArray(report.items))
1189
- return;
1190
- const out = [];
1191
- const fallbackPullDeadline = Date.now() + Math.max(1, budgetMs);
1192
- for (const item of report.items) {
1193
- if (!item?.uri)
1194
- continue;
1195
- const filePath = uriToPath(item.uri);
1196
- const normalizedPath = normalizeMapKey(filePath);
1197
- if (item.kind === "unchanged") {
1198
- const prior = state.workspacePullResultCache.get(normalizedPath);
1199
- if (!prior) {
1200
- const remainingMs = fallbackPullDeadline - Date.now();
1201
- if (remainingMs <= 0) {
1202
- incrementDegradationCount({
1203
- kind: "lsp-pull-unconfirmed",
1204
- subject: state.serverId,
1205
- reason: "unchanged report with no workspacePullResultCache basis; the shared fallback-pull deadline was already exhausted by earlier files this sweep"
1206
- });
1207
- continue;
1208
- }
1209
- const outcome = await clientRequestPullDiagnostics(state, filePath, remainingMs);
1210
- if (outcome.status === "found") {
1211
- out.push({
1212
- filePath,
1213
- diagnostics: state.documentPullDiagnostics.get(normalizedPath) ?? [],
1214
- contentHash: state.diagnosticBindings.get(normalizedPath)?.contentHash
1215
- });
1216
- } else if (outcome.status === "unavailable") {
1217
- incrementDegradationCount({
1218
- kind: "lsp-pull-unconfirmed",
1219
- subject: state.serverId,
1220
- reason: "unchanged report with no workspacePullResultCache basis, and the per-file fallback pull was unavailable"
1221
- });
1222
- }
1223
- continue;
1224
- }
1225
- if (item.resultId !== undefined) {
1226
- state.workspacePullResultCache.set(normalizedPath, {
1227
- ...prior,
1228
- resultId: item.resultId
1229
- });
1230
- }
1231
- out.push({
1232
- filePath,
1233
- diagnostics: prior.diagnostics,
1234
- contentHash: prior.contentHash
1235
- });
1236
- continue;
1237
- }
1238
- const diagnostics = normalizeLspDiagnostics(item.items ?? []);
1239
- let contentHash;
1240
- try {
1241
- contentHash = hashDiagnosticContent(await readFile(filePath, "utf-8"));
1242
- } catch {
1243
- contentHash = undefined;
1244
- }
1245
- if (item.resultId !== undefined) {
1246
- if (state.workspacePullResultCache.size >= WORKSPACE_PULL_RESULT_CACHE_MAX) {
1247
- state.workspacePullResultCache.clear();
1248
- }
1249
- state.workspacePullResultCache.set(normalizedPath, {
1250
- uri: item.uri,
1251
- resultId: item.resultId,
1252
- diagnostics,
1253
- contentHash
1254
- });
1255
- } else {
1256
- state.workspacePullResultCache.delete(normalizedPath);
1257
- }
1258
- out.push({ filePath, diagnostics, contentHash });
1259
- }
1260
- return out;
1261
- } catch (err) {
1262
- if (isPullTimeoutError(err, workspacePullTimeoutMs)) {
1263
- trackAbandonedPullRequest(state, WORKSPACE_PULL_SCOPE, workspaceRequestPromise);
1264
- workspacePullAbort.abort();
1265
- recordPullTimeoutTelemetry({
1266
- scope: WORKSPACE_PULL_SCOPE,
1267
- identifier: undefined,
1268
- effectiveBudgetMs: workspacePullTimeoutMs,
1269
- hadPreviousResultId: previousResultIds.length > 0,
1270
- elapsedMs: Date.now() - workspacePullStartedAt,
1271
- server: state.serverId
1272
- });
1273
- armLateAnswerTelemetry({
1274
- requestPromise: workspaceRequestPromise,
1275
- scope: WORKSPACE_PULL_SCOPE,
1276
- identifier: undefined,
1277
- subject: WORKSPACE_PULL_SCOPE,
1278
- requestStartedAt: workspacePullStartedAt,
1279
- server: state.serverId,
1280
- settlement: workspacePullSettlement
1281
- });
1282
- }
1283
- recordPullFailure(state, "workspace/diagnostic", err);
1284
- return;
1285
- }
1286
- }
1287
- export async function clientWaitForDiagnostics(state, filePath, timeoutMs, options = {}) {
1288
- const normalizedPath = normalizeMapKey(filePath);
1289
- const minVersion = options.minVersion;
1290
- const pullSettleSource = options.pullSettleSource ?? "pull";
1291
- const hasFreshDiagnostics = () => minVersion === undefined || diagnosticsVersionForPath(state, normalizedPath) > minVersion;
1292
- const isVersionStale = () => {
1293
- const cachedVersion = state.diagnosticDocVersions?.get(normalizedPath);
1294
- if (cachedVersion === undefined)
1295
- return false;
1296
- const currentVersion = state.documentVersions?.get(normalizedPath);
1297
- return currentVersion !== undefined && cachedVersion < currentVersion;
1298
- };
1299
- if (state.workspaceDiagnosticsSupport.mode === "pull") {
1300
- const pullSettleStartedAt = Date.now();
1301
- let outcome = await clientRequestPullDiagnostics(state, filePath, timeoutMs);
1302
- if (outcome.status === "found") {
1303
- logTypeScriptPullSettle(state, normalizedPath, Date.now() - pullSettleStartedAt, pullSettleSource);
1304
- return;
1305
- }
1306
- let sawClean = outcome.status === "clean";
1307
- const strategy = getStrategy(state.serverId, state.launchVariant);
1308
- const retryBudgetMs = strategy.pullRetryBudgetMs > 0 ? Math.min(timeoutMs, strategy.pullRetryBudgetMs) : 0;
1309
- const startedAt = Date.now();
1310
- while (outcome.status !== "found" && Date.now() - startedAt < retryBudgetMs) {
1311
- await new Promise((resolve) => setTimeout(resolve, PULL_DIAGNOSTICS_RETRY_INTERVAL_MS));
1312
- outcome = await clientRequestPullDiagnostics(state, filePath, Math.max(0, retryBudgetMs - (Date.now() - startedAt)));
1313
- if (outcome.status === "clean")
1314
- sawClean = true;
1315
- }
1316
- if (options.pullOnly) {
1317
- if (outcome.status === "found" || sawClean) {
1318
- logTypeScriptPullSettle(state, normalizedPath, Date.now() - pullSettleStartedAt, pullSettleSource);
1319
- }
1320
- return;
1321
- }
1322
- if (outcome.status === "found" || sawClean) {
1323
- logTypeScriptPullSettle(state, normalizedPath, Date.now() - pullSettleStartedAt, pullSettleSource);
1324
- return;
1325
- }
1326
- }
1327
- if (hasFreshDiagnostics() && !isVersionStale() && getMergedDiagnosticsForPath(state, normalizedPath).length > 0) {
1328
- return;
1329
- }
1330
- return new Promise((resolve) => {
1331
- let debounceTimer;
1332
- const onDiagnostics = (fp) => {
1333
- if (normalizeMapKey(fp) !== normalizedPath)
1334
- return;
1335
- if (!hasFreshDiagnostics() || isVersionStale())
1336
- return;
1337
- if (debounceTimer)
1338
- clearTimeout(debounceTimer);
1339
- const strategy = getStrategy(state.serverId, state.launchVariant);
1340
- const hit = state.pushDiagnosticTimestamps.get(normalizedPath);
1341
- const timeSincePush = hit ? Date.now() - hit : 1 / 0;
1342
- const remaining = Math.max(0, strategy.debounceMs - timeSincePush);
1343
- debounceTimer = setTimeout(() => {
1344
- state.diagnosticEmitter.off("diagnostics", onDiagnostics);
1345
- clearTimeout(timeout);
1346
- resolve();
1347
- }, remaining);
1348
- };
1349
- state.diagnosticEmitter.on("diagnostics", onDiagnostics);
1350
- const timeout = setTimeout(() => {
1351
- if (debounceTimer)
1352
- clearTimeout(debounceTimer);
1353
- state.diagnosticEmitter.off("diagnostics", onDiagnostics);
1354
- resolve();
1355
- }, timeoutMs);
1356
- });
1357
- }
1358
- export function handleNotifyExternalChange(state, filePath, type) {
1359
- if (!isClientAlive(state))
1360
- return;
1361
- const normalizedPath = normalizeMapKey(filePath);
1362
- const uri = state.openDocumentUris?.get(normalizedPath) ?? pathToFileURL(filePath).href;
1363
- state.watchQueue.enqueue(uri, type);
1364
- }
1365
- async function sendDidSave(state, uri, content) {
1366
- const save = state.saveOptions;
1367
- if (!save)
1368
- return;
1369
- if (!isClientAlive(state))
1370
- return;
1371
- const limit = save.includeText ? exceedsLspSyncLimits(content) : { tooLarge: false, reason: "" };
1372
- if (limit.tooLarge) {
1373
- recordDegradationOnce({
1374
- kind: "lsp-did-save-text-omitted",
1375
- subject: state.serverId,
1376
- reason: limit.reason
1377
- });
1378
- }
1379
- await safeSendNotification(state.connection, "textDocument/didSave", {
1380
- textDocument: { uri },
1381
- ...save.includeText && !limit.tooLarge ? { text: content } : {}
1382
- });
1383
- }
1384
- async function handleNotifyOpenOnce(state, filePath, content, languageId, preserveDiagnostics = false, silent = false, coalescedCount = 0, saved = false) {
1385
- if (!isClientAlive(state))
1386
- return;
1387
- const normalizedPath = normalizeMapKey(filePath);
1388
- const uri = state.openDocumentUris?.get(normalizedPath) ?? pathToFileURL(filePath).href;
1389
- if (state.openDocuments.has(normalizedPath) || state.pendingOpens.has(normalizedPath)) {
1390
- const version = (state.documentVersions.get(normalizedPath) ?? 0) + 1;
1391
- state.documentVersions.set(normalizedPath, version);
1392
- if (!preserveDiagnostics) {
1393
- clearDiagnosticsForPath(state, normalizedPath);
1394
- }
1395
- if (getStrategy(state.serverId, state.launchVariant).reopenOnResync) {
1396
- await safeSendNotification(state.connection, "textDocument/didClose", {
1397
- textDocument: { uri }
1398
- });
1399
- state.openDocuments.delete(normalizedPath);
1400
- state.openDocumentUris?.delete(normalizedPath);
1401
- state.documentVersions.set(normalizedPath, version);
1402
- state.documentOpenedAt.set(normalizedPath, Date.now());
1403
- state.diagnosticPublicationCounts.set(normalizedPath, 0);
1404
- if (!isClientAlive(state))
1405
- return;
1406
- const reopenSent = await safeSendNotification(state.connection, "textDocument/didOpen", { textDocument: { uri, languageId, version, text: content } });
1407
- if (reopenSent)
1408
- recordSentContent(state, normalizedPath, version, content, coalescedCount);
1409
- state.openDocuments.add(normalizedPath);
1410
- state.openDocumentUris?.set(normalizedPath, uri);
1411
- if (saved && reopenSent)
1412
- await sendDidSave(state, uri, content);
1413
- return;
1414
- }
1415
- const changeSent = await safeSendNotification(state.connection, "textDocument/didChange", {
1416
- textDocument: { uri, version },
1417
- contentChanges: buildContentChanges(state, normalizedPath, content)
1418
- });
1419
- if (changeSent)
1420
- recordSentContent(state, normalizedPath, version, content, coalescedCount);
1421
- if (saved && changeSent)
1422
- await sendDidSave(state, uri, content);
1423
- return;
1424
- }
1425
- state.pendingOpens.add(normalizedPath);
1426
- state.documentVersions.set(normalizedPath, 0);
1427
- state.documentOpenedAt.set(normalizedPath, Date.now());
1428
- state.diagnosticPublicationCounts.set(normalizedPath, 0);
1429
- clearDiagnosticsForPath(state, normalizedPath);
1430
- if (!silent) {
1431
- let fileExists = true;
1432
- try {
1433
- await access(filePath);
1434
- } catch {
1435
- fileExists = false;
1436
- }
1437
- state.watchQueue.enqueue(uri, fileExists ? 2 : 1);
1438
- }
1439
- if (!isClientAlive(state))
1440
- return;
1441
- const openSent = await safeSendNotification(state.connection, "textDocument/didOpen", { textDocument: { uri, languageId, version: 0, text: content } });
1442
- if (openSent)
1443
- recordSentContent(state, normalizedPath, 0, content, coalescedCount);
1444
- state.pendingOpens.delete(normalizedPath);
1445
- state.openDocuments.add(normalizedPath);
1446
- state.closedDocuments?.delete(normalizedPath);
1447
- state.openDocumentUris?.set(normalizedPath, uri);
1448
- if (saved && openSent)
1449
- await sendDidSave(state, uri, content);
1450
- probeTsserverProjectIdentity({
1451
- serverId: state.serverId,
1452
- launchVariant: state.launchVariant,
1453
- clientRoot: state.root,
1454
- file: filePath,
1455
- normalizedFile: normalizedPath,
1456
- probedFiles: state.projectIdentityProbedFiles ?? (state.projectIdentityProbedFiles = new Set),
1457
- commandChannel: {
1458
- executeCommand: (command, args) => runReadOnlyServerCommand(state, command, args)
1459
- }
1460
- });
1461
- }
1462
- function enqueueDocumentNotify(state, normalizedPath, run, saved = false) {
1463
- let queue = state.notifyChangeQueues.get(normalizedPath);
1464
- if (!queue) {
1465
- queue = { running: false };
1466
- state.notifyChangeQueues.set(normalizedPath, queue);
1467
- }
1468
- return new Promise((resolve, reject) => {
1469
- const previous = queue?.pending;
1470
- const waiters = previous?.waiters ?? [];
1471
- waiters.push({ resolve, reject });
1472
- queue.pending = {
1473
- run,
1474
- waiters,
1475
- coalescedCount: (previous?.coalescedCount ?? 0) + (previous ? 1 : 0),
1476
- saved: saved || previous?.saved === true
1477
- };
1478
- if (queue.running)
1479
- return;
1480
- queue.running = true;
1481
- Promise.resolve().then(async () => {
1482
- try {
1483
- for (;; ) {
1484
- const next = queue.pending;
1485
- if (!next)
1486
- break;
1487
- queue.pending = undefined;
1488
- try {
1489
- await next.run(next.coalescedCount, next.saved);
1490
- for (const waiter of next.waiters)
1491
- waiter.resolve();
1492
- } catch (error) {
1493
- for (const waiter of next.waiters)
1494
- waiter.reject(error);
1495
- }
1496
- }
1497
- } finally {
1498
- queue.running = false;
1499
- if (!queue.pending && state.notifyChangeQueues.get(normalizedPath) === queue) {
1500
- state.notifyChangeQueues.delete(normalizedPath);
1501
- }
1502
- }
1503
- });
1504
- });
1505
- }
1506
- function cancelDocumentNotifyQueues(state) {
1507
- for (const queue of state.notifyChangeQueues.values()) {
1508
- for (const waiter of queue.pending?.waiters ?? [])
1509
- waiter.resolve();
1510
- queue.pending = undefined;
1511
- }
1512
- state.notifyChangeQueues.clear();
1513
- }
1514
- export function handleNotifyOpen(state, filePath, content, languageId, preserveDiagnostics = false, silent = false, saved = false) {
1515
- if (!isClientAlive(state))
1516
- return Promise.resolve();
1517
- const normalizedPath = normalizeMapKey(filePath);
1518
- return enqueueDocumentNotify(state, normalizedPath, (coalescedCount, queuedSaved) => handleNotifyOpenOnce(state, filePath, content, languageId, preserveDiagnostics, silent, coalescedCount, queuedSaved), saved);
1519
- }
1520
- async function handleNotifyChangeOnce(state, filePath, content, normalizedPath, coalescedCount = 0) {
1521
- if (!isClientAlive(state))
1522
- return;
1523
- const uri = state.openDocumentUris?.get(normalizedPath) ?? pathToFileURL(filePath).href;
1524
- if (!state.openDocuments.has(normalizedPath)) {
1525
- const fallbackOpenSent = await safeSendNotification(state.connection, "textDocument/didOpen", {
1526
- textDocument: {
1527
- uri,
1528
- languageId: "plaintext",
1529
- version: 0,
1530
- text: content
1531
- }
1532
- });
1533
- state.documentVersions.set(normalizedPath, 0);
1534
- state.documentOpenedAt.set(normalizedPath, Date.now());
1535
- state.diagnosticPublicationCounts.set(normalizedPath, 0);
1536
- if (fallbackOpenSent)
1537
- recordSentContent(state, normalizedPath, 0, content, coalescedCount);
1538
- state.openDocuments.add(normalizedPath);
1539
- state.openDocumentUris?.set(normalizedPath, uri);
1540
- return;
1541
- }
1542
- const version = (state.documentVersions.get(normalizedPath) ?? 0) + 1;
1543
- state.documentVersions.set(normalizedPath, version);
1544
- clearDiagnosticsForPath(state, normalizedPath);
1545
- const changeSent = await safeSendNotification(state.connection, "textDocument/didChange", {
1546
- textDocument: { uri, version },
1547
- contentChanges: buildContentChanges(state, normalizedPath, content)
1548
- });
1549
- if (changeSent)
1550
- recordSentContent(state, normalizedPath, version, content, coalescedCount);
1551
- }
1552
- export function handleNotifyChange(state, filePath, content) {
1553
- if (!isClientAlive(state))
1554
- return Promise.resolve();
1555
- const normalizedPath = normalizeMapKey(filePath);
1556
- return enqueueDocumentNotify(state, normalizedPath, (coalescedCount) => handleNotifyChangeOnce(state, filePath, content, normalizedPath, coalescedCount));
1557
- }
1558
- export async function closeDocument(state, filePath) {
1559
- if (!isClientAlive(state))
1560
- return;
1561
- const normalizedPath = normalizeMapKey(filePath);
1562
- if (!state.openDocuments.has(normalizedPath))
1563
- return;
1564
- await safeSendNotification(state.connection, "textDocument/didClose", {
1565
- textDocument: {
1566
- uri: state.openDocumentUris?.get(normalizedPath) ?? pathToFileURL(filePath).href
1567
- }
1568
- });
1569
- state.openDocuments.delete(normalizedPath);
1570
- state.closedDocuments?.add(normalizedPath);
1571
- state.openDocumentUris?.delete(normalizedPath);
1572
- state.documentVersions.delete(normalizedPath);
1573
- state.documentOpenedAt.delete(normalizedPath);
1574
- state.diagnosticPublicationCounts.delete(normalizedPath);
1575
- state.projectIdentityProbedFiles?.delete(normalizedPath);
1576
- const retained = state.documentContentHashes.get(normalizedPath);
1577
- if (retained?.text !== undefined) {
1578
- state.incrementalTextRetainedEntries = Math.max(0, (state.incrementalTextRetainedEntries ?? 1) - 1);
1579
- state.incrementalTextRetainedBytes = Math.max(0, (state.incrementalTextRetainedBytes ?? retained.text.length * 2) - retained.text.length * 2);
1580
- state.incrementalTextBearingPaths?.delete(normalizedPath);
1581
- }
1582
- state.documentContentHashes.delete(normalizedPath);
1583
- clearDiagnosticsForPath(state, normalizedPath);
1584
- }
1585
- function isAtLeastAsAggressiveShutdown(existing, requested) {
1586
- return !!existing.fast >= !!requested.fast && !!existing.processExiting >= !!requested.processExiting;
1587
- }
1588
- export function clientShutdown(state, options = {}) {
1589
- if (state.shutdownPromise && state.shutdownOptions && isAtLeastAsAggressiveShutdown(state.shutdownOptions, options)) {
1590
- return state.shutdownPromise;
1591
- }
1592
- state.shutdownOptions = options;
1593
- const attempt = clientShutdownOnce(state, options);
1594
- state.shutdownPromise = attempt;
1595
- attempt.catch(() => {
1596
- if (state.shutdownPromise === attempt) {
1597
- state.shutdownPromise = undefined;
1598
- state.shutdownOptions = undefined;
1599
- }
1600
- });
1601
- return attempt;
1602
- }
1603
- async function clientShutdownOnce(state, options) {
1604
- const shutdownStart = Date.now();
1605
- state.shutdownRequested = true;
1606
- state.isConnected = false;
1607
- state.isDestroyed = true;
1608
- for (const timer of state.pendingDiagnostics.values()) {
1609
- clearTimeout(timer);
1610
- }
1611
- state.pendingDiagnostics.clear();
1612
- state.pendingOpens.clear();
1613
- state.openDocuments.clear();
1614
- state.openDocumentUris?.clear();
1615
- cancelDocumentNotifyQueues(state);
1616
- state.projectIdentityProbedFiles?.clear();
1617
- state.watchQueue?.cancel();
1618
- state.diagnosticEmitter.removeAllListeners();
1619
- let shutdownRequestTimedOut = false;
1620
- let exitNotifyTimedOut = false;
1621
- let shutdownRequestUndelivered = false;
1622
- let exitNotifyUndelivered = false;
1623
- try {
1624
- if (!options.fast) {
1625
- try {
1626
- const shutdownAck = await withTimeout(safeSendRequest(state.connection, "shutdown", {}), SHUTDOWN_REQUEST_TIMEOUT_MS);
1627
- if (shutdownAck === undefined)
1628
- shutdownRequestUndelivered = true;
1629
- } catch (err) {
1630
- if (isShutdownTimeoutError(err, SHUTDOWN_REQUEST_TIMEOUT_MS)) {
1631
- shutdownRequestTimedOut = true;
1632
- } else {
1633
- shutdownRequestUndelivered = true;
1634
- }
1635
- }
1636
- try {
1637
- const exitSent = await withTimeout(safeSendNotification(state.connection, "exit", {}), EXIT_NOTIFY_TIMEOUT_MS);
1638
- if (exitSent === false)
1639
- exitNotifyUndelivered = true;
1640
- } catch (err) {
1641
- if (isShutdownTimeoutError(err, EXIT_NOTIFY_TIMEOUT_MS)) {
1642
- exitNotifyTimedOut = true;
1643
- } else {
1644
- exitNotifyUndelivered = true;
1645
- }
1646
- }
1647
- }
1648
- } finally {
1649
- disposeClientConnection(state);
1650
- const pid = state.lspProcess.pid;
1651
- logLatency({
1652
- type: "phase",
1653
- phase: "lsp_client_shutdown",
1654
- filePath: state.root,
1655
- durationMs: Date.now() - shutdownStart,
1656
- metadata: {
1657
- serverId: state.serverId,
1658
- pid,
1659
- fast: !!options.fast,
1660
- processExiting: !!options.processExiting,
1661
- shutdownRequestTimedOut,
1662
- exitNotifyTimedOut,
1663
- shutdownRequestUndelivered,
1664
- exitNotifyUndelivered,
1665
- shutdownOutcome: options.fast ? "fast" : shutdownRequestTimedOut || exitNotifyTimedOut || shutdownRequestUndelivered || exitNotifyUndelivered ? "forced" : "graceful"
1666
- }
1667
- });
1668
- removeLspChild(pid, extractSpawnMarker(state.lspProcess.args)).catch((err) => {
1669
- logLatency({
1670
- type: "phase",
1671
- phase: "lsp_registry_write_failed",
1672
- filePath: "",
1673
- durationMs: 0,
1674
- metadata: { op: "remove", pid, error: String(err) }
1675
- });
1676
- });
1677
- await killProcessTree(state.lspProcess.process, pid, options);
1678
- }
1679
- }
1680
- async function toWirePosition(state, filePath, line, character) {
1681
- if (state.positionEncoding === "utf-16")
1682
- return { line, character };
1683
- try {
1684
- const content = await readFile(filePath, "utf8");
1685
- return {
1686
- line,
1687
- character: convertCharacterOffset(state.positionEncoding, lineTextAt(content, line), character)
1688
- };
1689
- } catch {
1690
- return { line, character };
1691
- }
1692
- }
1693
- function navStaleDropEnabled() {
1694
- return process.env.DM_LENS_LSP_NAV_STALE_DROP !== "0";
1695
- }
1696
- export async function navRequest(state, method, params, staleCheckPath, timeoutMs = NAV_REQUEST_TIMEOUT_MS, signal = getAmbientAbortSignal()) {
1697
- if (!isClientAlive(state))
1698
- return null;
1699
- const normalizedPath = staleCheckPath !== undefined ? normalizeMapKey(staleCheckPath) : undefined;
1700
- const requestVersion = normalizedPath !== undefined ? state.documentVersions.get(normalizedPath) : undefined;
1701
- const requestStartedAt = Date.now();
1702
- const requestPromise = safeSendRequest(state.connection, method, params, signal);
1703
- const result = await withTimeout(requestPromise, timeoutMs).catch((err) => {
1704
- if (isNavTimeoutError(err, timeoutMs)) {
1705
- recordNavTimeoutTelemetry({
1706
- method,
1707
- scope: normalizedPath,
1708
- budgetMs: timeoutMs,
1709
- elapsedMs: Date.now() - requestStartedAt
1710
- });
1711
- armNavLateAnswerTelemetry({
1712
- requestPromise,
1713
- method,
1714
- scope: normalizedPath,
1715
- requestStartedAt
1716
- });
1717
- return;
1718
- }
1719
- if (err instanceof Error && err.message.startsWith("Timeout after")) {
1720
- return;
1721
- }
1722
- throw err;
1723
- });
1724
- if (normalizedPath !== undefined && requestVersion !== undefined && navStaleDropEnabled()) {
1725
- const currentVersion = state.documentVersions.get(normalizedPath);
1726
- if (currentVersion !== undefined && currentVersion > requestVersion) {
1727
- return;
1728
- }
1729
- }
1730
- return result;
1731
- }
1732
- function isNavTimeoutError(err, timeoutMs) {
1733
- return err instanceof Error && err.message === `Timeout after ${timeoutMs}ms`;
1734
- }
1735
- function isShutdownTimeoutError(err, timeoutMs) {
1736
- return err instanceof Error && err.message === `Timeout after ${timeoutMs}ms`;
1737
- }
1738
- const NAV_REQUEST_NO_PATH_SCOPE = "*no-path*";
1739
- function recordNavTimeoutTelemetry(args) {
1740
- emitBounded("lsp_nav_request_timeout", `${args.method}:${args.scope ?? NAV_REQUEST_NO_PATH_SCOPE}`, {
1741
- type: "phase",
1742
- filePath: args.scope ?? NAV_REQUEST_NO_PATH_SCOPE,
1743
- durationMs: args.elapsedMs,
1744
- metadata: { method: args.method, effectiveBudgetMs: args.budgetMs }
1745
- }, {
1746
- ledgerKind: "lsp-nav-request-timeout",
1747
- risingEdgePer: "identity",
1748
- reason: `timeout budget=${args.budgetMs}ms elapsed=${args.elapsedMs}ms`
1749
- });
1750
- }
1751
- function armNavLateAnswerTelemetry(args) {
1752
- args.requestPromise.then(() => {
1753
- try {
1754
- const elapsedMs = Date.now() - args.requestStartedAt;
1755
- emitBounded("lsp_nav_late_answer_discarded", `${args.method}:${args.scope ?? NAV_REQUEST_NO_PATH_SCOPE}`, {
1756
- type: "phase",
1757
- filePath: args.scope ?? NAV_REQUEST_NO_PATH_SCOPE,
1758
- durationMs: elapsedMs,
1759
- metadata: { method: args.method }
1760
- }, {
1761
- ledgerKind: "lsp-nav-late-answer",
1762
- risingEdgePer: "identity",
1763
- reason: `late nav answer discarded after ${elapsedMs}ms`
1764
- });
1765
- } catch {}
1766
- }, () => {});
1767
- }
1768
- function chooseLivenessProbe(state) {
1769
- if (state.operationSupport?.workspaceSymbol === true) {
1770
- return {
1771
- method: "workspace/symbol",
1772
- params: { query: LIVENESS_PING_QUERY }
1773
- };
1774
- }
1775
- const openUri = firstOpenDocumentUri(state);
1776
- if (openUri === undefined)
1777
- return;
1778
- if (state.operationSupport?.documentSymbol === true) {
1779
- return {
1780
- method: "textDocument/documentSymbol",
1781
- params: { textDocument: { uri: openUri } }
1782
- };
1783
- }
1784
- if (state.operationSupport?.hover === true) {
1785
- return {
1786
- method: "textDocument/hover",
1787
- params: {
1788
- textDocument: { uri: openUri },
1789
- position: { line: 0, character: 0 }
1790
- }
1791
- };
1792
- }
1793
- return;
1794
- }
1795
- function firstOpenDocumentUri(state) {
1796
- for (const normalizedPath of state.openDocuments) {
1797
- const uri = state.openDocumentUris?.get(normalizedPath);
1798
- if (uri !== undefined)
1799
- return uri;
1800
- }
1801
- return;
1802
- }
1803
- async function clientPingLiveness(state, timeoutMs = LIVENESS_PING_TIMEOUT_MS) {
1804
- if (!isClientAlive(state))
1805
- return false;
1806
- const probe = chooseLivenessProbe(state);
1807
- if (probe === undefined) {
1808
- try {
1809
- incrementDegradationCount({
1810
- kind: "lsp-liveness-probe-unsupported",
1811
- subject: state.serverId,
1812
- reason: "no advertised request method to probe with (no " + "workspaceSymbolProvider, and no open document with " + "documentSymbolProvider or hoverProvider); liveness from " + "process and connection state only"
1813
- });
1814
- } catch {}
1815
- return isClientAlive(state);
1816
- }
1817
- try {
1818
- await withTimeout(safeSendRequest(state.connection, probe.method, probe.params), timeoutMs);
1819
- } catch (err) {
1820
- if (err instanceof Error && err.message.startsWith("Timeout after")) {
1821
- return false;
1822
- }
1823
- }
1824
- return isClientAlive(state);
1825
- }
1826
- function syncMutationContextSlot(state) {
1827
- state.activeMutationContext = state.activeMutationDepth === 1 ? state.mutationContextOwner : undefined;
1828
- }
1829
- export async function runServerCommand(state, command, args, timeoutMs = EXECUTE_COMMAND_TIMEOUT_MS, mutationContext) {
1830
- if (!isClientAlive(state)) {
1831
- return { executed: false, reason: "lsp client not alive" };
1832
- }
1833
- if (!state.advertisedCommands.has(command)) {
1834
- return {
1835
- executed: false,
1836
- reason: `command "${command}" is not advertised by the ${state.serverId} server`
1837
- };
1838
- }
1839
- state.serverEditsAllowed += 1;
1840
- state.activeMutationDepth = (state.activeMutationDepth ?? 0) + 1;
1841
- const isMutationContextOwner = state.activeMutationDepth === 1;
1842
- if (isMutationContextOwner) {
1843
- state.mutationContextOwner = mutationContext;
1844
- }
1845
- syncMutationContextSlot(state);
1846
- try {
1847
- let result;
1848
- try {
1849
- result = await withTimeout(safeSendRequest(state.connection, "workspace/executeCommand", {
1850
- command,
1851
- arguments: args ?? []
1852
- }), timeoutMs);
1853
- } catch (err) {
1854
- if (err instanceof Error && err.message.startsWith("Timeout after")) {
1855
- return {
1856
- executed: false,
1857
- reason: `workspace/executeCommand timed out after ${timeoutMs}ms — the command may still be applying server-side`
1858
- };
1859
- }
1860
- throw err;
1861
- }
1862
- return { executed: true, result };
1863
- } finally {
1864
- state.serverEditsAllowed -= 1;
1865
- state.activeMutationDepth = Math.max(0, (state.activeMutationDepth ?? 0) - 1);
1866
- if (isMutationContextOwner) {
1867
- state.mutationContextOwner = undefined;
1868
- }
1869
- syncMutationContextSlot(state);
1870
- }
1871
- }
1872
- export async function runReadOnlyServerCommand(state, command, args, timeoutMs = PROBE_COMMAND_TIMEOUT_MS) {
1873
- if (!isClientAlive(state)) {
1874
- return { executed: false, reason: "lsp client not alive" };
1875
- }
1876
- if (!state.advertisedCommands.has(command)) {
1877
- return {
1878
- executed: false,
1879
- reason: `command "${command}" is not advertised by the ${state.serverId} server`
1880
- };
1881
- }
1882
- try {
1883
- const result = await withTimeout(safeSendRequest(state.connection, "workspace/executeCommand", {
1884
- command,
1885
- arguments: args ?? []
1886
- }), timeoutMs);
1887
- return { executed: true, result };
1888
- } catch (err) {
1889
- if (err instanceof Error && err.message.startsWith("Timeout after")) {
1890
- return {
1891
- executed: false,
1892
- reason: `workspace/executeCommand timed out after ${timeoutMs}ms`
1893
- };
1894
- }
1895
- throw err;
1896
- }
1897
- }
1898
- function validateWorkspaceEditVersions(state, edit) {
1899
- for (const change of edit.documentChanges ?? []) {
1900
- if (typeof change !== "object" || change === null || !("textDocument" in change))
1901
- continue;
1902
- const textDocument = change.textDocument;
1903
- if (!textDocument || typeof textDocument.uri !== "string" || textDocument.version == null)
1904
- continue;
1905
- const current = state.documentVersions.get(normalizeMapKey(uriToPath(textDocument.uri)));
1906
- if (current === undefined || current !== textDocument.version) {
1907
- throw new Error(`stale workspace edit document version for ${textDocument.uri}`);
1908
- }
1909
- }
1910
- }
1911
- function stripDocumentVersions(edit) {
1912
- if (!Array.isArray(edit.documentChanges))
1913
- return edit;
1914
- const documentChanges = edit.documentChanges.map((change) => {
1915
- if (typeof change === "object" && change !== null && "textDocument" in change && "edits" in change) {
1916
- const textDocument = change.textDocument;
1917
- if (textDocument && typeof textDocument.version === "number") {
1918
- return {
1919
- ...change,
1920
- textDocument: { ...textDocument, version: null }
1921
- };
1922
- }
1923
- }
1924
- return change;
1925
- });
1926
- return { ...edit, documentChanges };
1927
- }
1928
- export async function normalizeClientWorkspaceEdit(state, edit) {
1929
- validateWorkspaceEditVersions(state, edit);
1930
- const normalized = await normalizeWorkspaceEditToUtf16(edit, state.positionEncoding, state.root);
1931
- return stripDocumentVersions(normalized);
1932
- }
1933
- async function resolveCodeActionBestEffort(state, action) {
1934
- if (!isClientAlive(state))
1935
- return action;
1936
- if (action.edit) {
1937
- return {
1938
- ...action,
1939
- edit: await normalizeClientWorkspaceEdit(state, action.edit)
1940
- };
1941
- }
1942
- if (!state.operationSupport.codeActionResolve) {
1943
- recordDegradationOnce({
1944
- kind: "lsp-capability-skip",
1945
- subject: `${state.serverId}:codeAction/resolve`,
1946
- reason: "server did not advertise codeActionProvider.resolveProvider"
1947
- });
1948
- return action;
1949
- }
1950
- let resolved;
1951
- try {
1952
- resolved = await withTimeout(safeSendRequest(state.connection, "codeAction/resolve", action), NAV_REQUEST_TIMEOUT_MS);
1953
- } catch {
1954
- return action;
1955
- }
1956
- if (!resolved || typeof resolved !== "object")
1957
- return action;
1958
- const merged = { ...action, ...resolved };
1959
- return merged.edit ? {
1960
- ...merged,
1961
- edit: await normalizeClientWorkspaceEdit(state, merged.edit)
1962
- } : merged;
1963
- }
1964
- export async function createLSPClient(options) {
1965
- installCrashGuard();
1966
- const { serverId, process: lspProcess, root, sessionCwd, initialization, initializeTimeoutMs = INITIALIZE_TIMEOUT_MS, launchVariant, onDiagnosticsPublished } = options;
1967
- recordLspChild({
1968
- pid: lspProcess.pid,
1969
- serverId,
1970
- command: lspProcess.command,
1971
- marker: extractSpawnMarker(lspProcess.args),
1972
- sessionIdentity: {
1973
- projectRoot: sessionCwd ?? process.cwd(),
1974
- rootSource: sessionCwd ? "service-cwd" : "lsp-fallback",
1975
- startedAt: new Date(workspaceDiagnosticsCacheSessionStart()).toISOString()
1976
- }
1977
- }).catch((err) => {
1978
- logLatency({
1979
- type: "phase",
1980
- phase: "lsp_registry_write_failed",
1981
- filePath: "",
1982
- durationMs: 0,
1983
- metadata: { op: "record", pid: lspProcess.pid, error: String(err) }
1984
- });
1985
- });
1986
- const startupState = {
1987
- exitCode: null,
1988
- exitSignal: null,
1989
- closeCode: null,
1990
- closeSignal: null,
1991
- stderr: ""
1992
- };
1993
- const stderrRing = [];
1994
- const MAX_STDERR_LINES = 100;
1995
- const onStderr = (chunk) => {
1996
- stderrRing.push(chunk.toString());
1997
- if (stderrRing.length > MAX_STDERR_LINES)
1998
- stderrRing.shift();
1999
- if (startupState.stderr.length < 4096) {
2000
- startupState.stderr += chunk.toString();
2001
- }
2002
- };
2003
- const recentStderr = (lines = 10) => stderrRing.slice(-lines).join("").trim();
2004
- const checkProcessAlive = () => {
2005
- const exited = lspProcess.process.exitCode;
2006
- if (exited !== null) {
2007
- const tail = recentStderr(20);
2008
- return `LSP server ${serverId} exited with code ${exited}${tail ? `. stderr: ${tail}` : ""}`;
2009
- }
2010
- if (lspProcess.process.killed) {
2011
- return `LSP server ${serverId} was killed`;
2012
- }
2013
- return;
2014
- };
2015
- const onProcessExit = (code, signal) => {
2016
- startupState.exitCode = code;
2017
- startupState.exitSignal = signal;
2018
- };
2019
- const onProcessClose = (code, signal) => {
2020
- startupState.closeCode = code;
2021
- startupState.closeSignal = signal;
2022
- };
2023
- lspProcess.stderr.on("data", onStderr);
2024
- lspProcess.process.on("exit", onProcessExit);
2025
- lspProcess.process.on("close", onProcessClose);
2026
- const streamErrorHandler = (_label) => (err) => {
2027
- if (err.code === "ERR_STREAM_DESTROYED" || err.code === "ERR_STREAM_WRITE_AFTER_END" || err.code === "EPIPE" || err.code === "ECONNRESET")
2028
- return;
2029
- };
2030
- lspProcess.stdin.on("error", streamErrorHandler("stdin"));
2031
- lspProcess.stdout.on("error", streamErrorHandler("stdout"));
2032
- lspProcess.stderr.on("error", streamErrorHandler("stderr"));
2033
- const connection = createMessageConnection(new StreamMessageReader(lspProcess.stdout), new StreamMessageWriter(lspProcess.stdin));
2034
- const diagnosticEmitter = new EventEmitter;
2035
- diagnosticEmitter.setMaxListeners(50);
2036
- const state = {
2037
- isConnected: true,
2038
- isDestroyed: false,
2039
- shutdownRequested: false,
2040
- shutdownPromise: undefined,
2041
- shutdownOptions: undefined,
2042
- exitedAt: undefined,
2043
- connectionDisposed: false,
2044
- lastError: undefined,
2045
- connection,
2046
- pushDiagnostics: new Map,
2047
- pushDiagnosticTimestamps: new Map,
2048
- documentPullDiagnostics: new Map,
2049
- documentPullDiagnosticTimestamps: new Map,
2050
- pullFailureHistory: [],
2051
- pendingDiagnostics: new Map,
2052
- diagnosticPublicationCounts: new Map,
2053
- documentOpenedAt: new Map,
2054
- diagnosticEmitter,
2055
- diagnosticsVersion: 0,
2056
- diagnosticsVersionsByPath: new Map,
2057
- documentVersions: new Map,
2058
- notifyChangeQueues: new Map,
2059
- diagnosticDocVersions: new Map,
2060
- documentContentHashes: new Map,
2061
- incrementalTextRetainedEntries: 0,
2062
- incrementalTextBearingPaths: new Set,
2063
- incrementalTextRetainedBytes: 0,
2064
- diagnosticBindings: new Map,
2065
- pullResultIds: new Map,
2066
- documentPullDiagnosticsBySource: new Map,
2067
- pullGenerations: new Map,
2068
- pullRequestSequences: new Map,
2069
- workspacePullResultCache: new Map,
2070
- openDocuments: new Set,
2071
- emptyFirstPublishHoldSpent: false,
2072
- closedDocuments: new Set,
2073
- openDocumentUris: new Map,
2074
- pendingOpens: new Set,
2075
- projectIdentityProbedFiles: new Set,
2076
- workspaceDiagnosticsSupport: undefined,
2077
- operationSupport: undefined,
2078
- staticDiagnosticsMode: "push-only",
2079
- positionEncoding: "utf-16",
2080
- syncKind: TEXT_DOCUMENT_SYNC_KIND_FULL,
2081
- dynamicRegistrations: new Map,
2082
- advertisedCommands: new Set,
2083
- serverEditsAllowed: 0,
2084
- activeMutationDepth: 0,
2085
- serverId,
2086
- launchVariant,
2087
- root,
2088
- lspProcess,
2089
- watchQueue: undefined
2090
- };
2091
- activeLspClientSet().add(state);
2092
- state.watchQueue = new WatchedFilesQueue((changes) => {
2093
- if (!isClientAlive(state))
2094
- return;
2095
- safeSendNotification(state.connection, "workspace/didChangeWatchedFiles", { changes });
2096
- });
2097
- setupIncomingHandlers(state, initialization, onDiagnosticsPublished);
2098
- connection.listen();
2099
- setupConnectionLifecycle(state, recentStderr);
2100
- let initResult;
2101
- try {
2102
- initResult = await withTimeout(safeSendRequest(connection, "initialize", {
2103
- processId: process.pid,
2104
- rootUri: pathToFileURL(root).href,
2105
- workspaceFolders: [
2106
- { name: "workspace", uri: pathToFileURL(root).href }
2107
- ],
2108
- capabilities: CLIENT_CAPABILITIES,
2109
- initializationOptions: initialization
2110
- }), initializeTimeoutMs);
2111
- } catch (err) {
2112
- state.shutdownRequested = true;
2113
- const pid = lspProcess.pid;
2114
- killProcessTree(lspProcess.process, pid);
2115
- removeLspChild(pid, extractSpawnMarker(lspProcess.args)).catch((err) => {
2116
- logLatency({
2117
- type: "phase",
2118
- phase: "lsp_registry_write_failed",
2119
- filePath: "",
2120
- durationMs: 0,
2121
- metadata: { op: "remove", pid, error: String(err) }
2122
- });
2123
- });
2124
- setTimeout(() => {
2125
- if (lspProcess.process.exitCode === null && lspProcess.process.signalCode === null && process.platform !== "win32") {
2126
- lspProcess.process.kill("SIGKILL");
2127
- }
2128
- }, 2000);
2129
- throw err;
2130
- } finally {
2131
- lspProcess.stderr.off("data", onStderr);
2132
- }
2133
- if (initResult === undefined) {
2134
- const compactStderr = startupState.stderr.replace(/\s+/g, " ").trim().slice(0, 320);
2135
- const reinstallHint = serverId === "cpp" ? "Install clangd (LLVM/clang-tools) and ensure clangd.exe is on PATH." : `Try reinstalling: npm install -g ${serverId}-language-server.`;
2136
- const telemetry = [
2137
- `pid=${lspProcess.pid}`,
2138
- `exitCode=${startupState.exitCode ?? "none"}`,
2139
- `exitSignal=${startupState.exitSignal ?? "none"}`,
2140
- `closeCode=${startupState.closeCode ?? "none"}`,
2141
- `closeSignal=${startupState.closeSignal ?? "none"}`,
2142
- `root=${root}`,
2143
- compactStderr ? `stderr=${compactStderr}` : "stderr=<empty>"
2144
- ].join(" ");
2145
- throw new Error(`[lsp] ${serverId} failed to initialize - stream may have been destroyed. ` + `The server binary may be missing or crashed immediately. ${reinstallHint} ` + `telemetry: ${telemetry}`);
2146
- }
2147
- state.workspaceDiagnosticsSupport = detectWorkspaceDiagnosticsSupport(initResult);
2148
- state.operationSupport = detectOperationSupport(initResult);
2149
- const capabilities = initResult?.capabilities ?? {};
2150
- const workspace = isCapabilityRecord(capabilities.workspace) ? capabilities.workspace : undefined;
2151
- const fileOperations = isCapabilityRecord(workspace) ? workspace.fileOperations : undefined;
2152
- const malformedFileOperationRegistrations = new Set;
2153
- if (isCapabilityRecord(fileOperations)) {
2154
- for (const operation of ["willRename", "didRename"]) {
2155
- if (fileOperations[operation] !== undefined && parseFileOperationFilters(fileOperations[operation]) === undefined) {
2156
- malformedFileOperationRegistrations.add(operation);
2157
- }
2158
- }
2159
- }
2160
- state.fileOperationMalformedRegistrations = malformedFileOperationRegistrations;
2161
- if (isCapabilityRecord(fileOperations)) {
2162
- state.fileOperationFilters = {
2163
- willRename: parseFileOperationFilters(fileOperations.willRename),
2164
- didRename: parseFileOperationFilters(fileOperations.didRename)
2165
- };
2166
- }
2167
- state.positionEncoding = negotiatePositionEncoding(initResult?.capabilities);
2168
- state.syncKind = negotiateSyncKind(initResult?.capabilities);
2169
- state.saveOptions = negotiateSaveOptions(initResult?.capabilities);
2170
- state.rawCapabilityKeys = Object.keys(initResult?.capabilities ?? {}).sort((a, b) => a.localeCompare(b));
2171
- for (const cmd of detectExecuteCommands(initResult)) {
2172
- state.advertisedCommands.add(cmd);
2173
- }
2174
- state.staticDiagnosticsMode = state.workspaceDiagnosticsSupport.mode;
2175
- await safeSendNotification(connection, "initialized", {});
2176
- if (initialization) {
2177
- await safeSendNotification(connection, "workspace/didChangeConfiguration", {
2178
- settings: initialization
2179
- });
2180
- }
2181
- return {
2182
- serverId,
2183
- root,
2184
- connection,
2185
- isAlive: () => isClientAlive(state),
2186
- processExited: () => lspProcess.process.exitCode !== null || lspProcess.process.killed === true,
2187
- wasShutdownIntentional: () => state.shutdownRequested,
2188
- getExitedAt: () => state.exitedAt,
2189
- recentStderr: (lines) => recentStderr(lines),
2190
- getPullFailureHistory: () => state.pullFailureHistory.map((entry) => ({
2191
- ...entry,
2192
- message: entry.message.slice(0, 200)
2193
- })),
2194
- checkAlive: () => checkProcessAlive(),
2195
- pingLiveness: (timeoutMs) => clientPingLiveness(state, timeoutMs),
2196
- getProcessPid: () => lspProcess.pid,
2197
- notify: {
2198
- async open(filePath, content, languageId, preserveDiagnostics, silent, saved) {
2199
- return handleNotifyOpen(state, filePath, content, languageId, preserveDiagnostics, silent, saved);
2200
- },
2201
- async change(filePath, content) {
2202
- return handleNotifyChange(state, filePath, content);
2203
- },
2204
- watchedFileChange(filePath, type) {
2205
- handleNotifyExternalChange(state, filePath, type);
2206
- }
2207
- },
2208
- getDiagnostics(filePath) {
2209
- return getMergedDiagnosticsForPath(state, normalizeMapKey(filePath));
2210
- },
2211
- getDiagnosticBinding(filePath) {
2212
- return state.diagnosticBindings.get(normalizeMapKey(filePath));
2213
- },
2214
- getDiagnosticsVersionForPath(filePath) {
2215
- return diagnosticsVersionForPath(state, normalizeMapKey(filePath));
2216
- },
2217
- getAllDiagnostics() {
2218
- const result = new Map;
2219
- const keys = new Set([
2220
- ...state.pushDiagnostics.keys(),
2221
- ...state.documentPullDiagnostics.keys()
2222
- ]);
2223
- for (const key of keys) {
2224
- result.set(key, {
2225
- diags: getMergedDiagnosticsForPath(state, key),
2226
- ts: Math.max(state.pushDiagnosticTimestamps.get(key) ?? 0, state.documentPullDiagnosticTimestamps.get(key) ?? 0),
2227
- binding: state.diagnosticBindings.get(key)
2228
- });
2229
- }
2230
- return result;
2231
- },
2232
- getTrackedDiagnosticPaths() {
2233
- return [
2234
- ...new Set([
2235
- ...state.pushDiagnostics.keys(),
2236
- ...state.documentPullDiagnostics.keys()
2237
- ])
2238
- ].map((filePath) => process.platform === "win32" ? filePath.replace(/\//g, "\\") : filePath);
2239
- },
2240
- pruneDiagnostics(predicate) {
2241
- let removed = 0;
2242
- const keys = new Set([
2243
- ...state.pushDiagnostics.keys(),
2244
- ...state.documentPullDiagnostics.keys()
2245
- ]);
2246
- for (const key of keys) {
2247
- const diags = getMergedDiagnosticsForPath(state, key);
2248
- const ts = Math.max(state.pushDiagnosticTimestamps.get(key) ?? 0, state.documentPullDiagnosticTimestamps.get(key) ?? 0);
2249
- if (!predicate(key, ts, diags))
2250
- continue;
2251
- clearDiagnosticsForPath(state, key);
2252
- removed++;
2253
- }
2254
- return removed;
2255
- },
2256
- getWorkspaceDiagnosticsSupport() {
2257
- return state.workspaceDiagnosticsSupport;
2258
- },
2259
- requestWorkspaceDiagnostics(budgetMs) {
2260
- return clientRequestWorkspaceDiagnostics(state, budgetMs);
2261
- },
2262
- getOperationSupport() {
2263
- return state.operationSupport;
2264
- },
2265
- getMalformedFileOperationRegistrations() {
2266
- return state.fileOperationMalformedRegistrations ?? new Set;
2267
- },
2268
- getAdvertisedCommands() {
2269
- return [...state.advertisedCommands];
2270
- },
2271
- getRawCapabilityKeys() {
2272
- return state.rawCapabilityKeys ?? [];
2273
- },
2274
- getLaunchVariant() {
2275
- return state.launchVariant;
2276
- },
2277
- async executeCommand(command, args, mutationContext) {
2278
- return runServerCommand(state, command, args, EXECUTE_COMMAND_TIMEOUT_MS, mutationContext);
2279
- },
2280
- async executeReadOnlyCommand(command, args) {
2281
- return runReadOnlyServerCommand(state, command, args);
2282
- },
2283
- get diagnosticsVersion() {
2284
- return state.diagnosticsVersion;
2285
- },
2286
- async waitForDiagnostics(filePath, timeoutMs = DIAGNOSTICS_WAIT_TIMEOUT_MS, options) {
2287
- return clientWaitForDiagnostics(state, filePath, timeoutMs, options);
2288
- },
2289
- async definition(filePath, line, character) {
2290
- const result = await navRequest(state, "textDocument/definition", {
2291
- textDocument: { uri: pathToFileURL(filePath).href },
2292
- position: await toWirePosition(state, filePath, line, character)
2293
- }, filePath);
2294
- if (!result)
2295
- return [];
2296
- return Array.isArray(result) ? result : [result];
2297
- },
2298
- async typeDefinition(filePath, line, character) {
2299
- const result = await navRequest(state, "textDocument/typeDefinition", {
2300
- textDocument: { uri: pathToFileURL(filePath).href },
2301
- position: await toWirePosition(state, filePath, line, character)
2302
- }, filePath);
2303
- if (!result)
2304
- return [];
2305
- return Array.isArray(result) ? result : [result];
2306
- },
2307
- async declaration(filePath, line, character) {
2308
- const result = await navRequest(state, "textDocument/declaration", {
2309
- textDocument: { uri: pathToFileURL(filePath).href },
2310
- position: await toWirePosition(state, filePath, line, character)
2311
- }, filePath);
2312
- if (!result)
2313
- return [];
2314
- return Array.isArray(result) ? result : [result];
2315
- },
2316
- async references(filePath, line, character, includeDeclaration = true) {
2317
- const result = await navRequest(state, "textDocument/references", {
2318
- textDocument: { uri: pathToFileURL(filePath).href },
2319
- position: await toWirePosition(state, filePath, line, character),
2320
- context: { includeDeclaration }
2321
- }, filePath);
2322
- return result ?? [];
2323
- },
2324
- async hover(filePath, line, character) {
2325
- const result = await navRequest(state, "textDocument/hover", {
2326
- textDocument: { uri: pathToFileURL(filePath).href },
2327
- position: await toWirePosition(state, filePath, line, character)
2328
- }, filePath);
2329
- return result ?? null;
2330
- },
2331
- async signatureHelp(filePath, line, character) {
2332
- const result = await navRequest(state, "textDocument/signatureHelp", {
2333
- textDocument: { uri: pathToFileURL(filePath).href },
2334
- position: await toWirePosition(state, filePath, line, character)
2335
- }, filePath);
2336
- return result ?? null;
2337
- },
2338
- async documentSymbol(filePath) {
2339
- const result = await navRequest(state, "textDocument/documentSymbol", { textDocument: { uri: pathToFileURL(filePath).href } }, filePath);
2340
- return result ?? [];
2341
- },
2342
- isDocumentOpen(filePath) {
2343
- return state.openDocuments.has(normalizeMapKey(filePath));
2344
- },
2345
- openDocumentPaths() {
2346
- return [...state.openDocuments];
2347
- },
2348
- isBusy() {
2349
- return (activeRequestsByConnection.get(connection) ?? 0) > 0;
2350
- },
2351
- getDocumentUri(filePath) {
2352
- return state.openDocumentUris?.get(normalizeMapKey(filePath));
2353
- },
2354
- async workspaceSymbol(query) {
2355
- if (!isClientAlive(state))
2356
- return [];
2357
- const result = await navRequest(state, "workspace/symbol", {
2358
- query
2359
- });
2360
- return result ?? [];
2361
- },
2362
- async codeAction(filePath, line, character, endLine, endCharacter) {
2363
- if (!isClientAlive(state))
2364
- return [];
2365
- const uri = pathToFileURL(filePath).href;
2366
- const result = await navRequest(state, "textDocument/codeAction", {
2367
- textDocument: { uri },
2368
- range: {
2369
- start: await toWirePosition(state, filePath, line, character),
2370
- end: await toWirePosition(state, filePath, endLine, endCharacter)
2371
- },
2372
- context: {
2373
- diagnostics: getMergedDiagnosticsForPath(state, normalizeMapKey(filePath))
2374
- }
2375
- }, filePath);
2376
- if (!result || !Array.isArray(result))
2377
- return [];
2378
- const actions = result.filter((item) => typeof item === "object" && item !== null && ("title" in item));
2379
- return Promise.all(actions.map((action) => resolveCodeActionBestEffort(state, action)));
2380
- },
2381
- async rename(filePath, line, character, newName) {
2382
- const result = await navRequest(state, "textDocument/rename", {
2383
- textDocument: { uri: pathToFileURL(filePath).href },
2384
- position: await toWirePosition(state, filePath, line, character),
2385
- newName
2386
- }, filePath);
2387
- return result ? await normalizeClientWorkspaceEdit(state, result) : null;
2388
- },
2389
- closeDocument: (filePath) => closeDocument(state, filePath),
2390
- async willRenameFiles(oldFilePath, newFilePath) {
2391
- if (!isClientAlive(state))
2392
- return null;
2393
- const oldUri = pathToFileURL(oldFilePath).href;
2394
- const newUri = pathToFileURL(newFilePath).href;
2395
- if (!await fileOperationFiltersMatch(state.fileOperationFilters?.willRename, oldUri, newUri, oldFilePath, newFilePath)) {
2396
- recordDegradationOnce({
2397
- kind: "lsp-capability-skip",
2398
- subject: `${state.serverId}:workspace/willRenameFiles:filter`,
2399
- reason: "filter-mismatch"
2400
- });
2401
- return null;
2402
- }
2403
- const result = await navRequest(state, "workspace/willRenameFiles", {
2404
- files: [
2405
- {
2406
- oldUri,
2407
- newUri
2408
- }
2409
- ]
2410
- });
2411
- return result ? await normalizeClientWorkspaceEdit(state, result) : null;
2412
- },
2413
- async didRenameFiles(oldFilePath, newFilePath, oldUri, newUri) {
2414
- if (!isClientAlive(state))
2415
- return;
2416
- const wireOldUri = oldUri ?? pathToFileURL(oldFilePath).href;
2417
- const wireNewUri = newUri ?? pathToFileURL(newFilePath).href;
2418
- if (!await fileOperationFiltersMatch(state.fileOperationFilters?.didRename, wireOldUri, wireNewUri, oldFilePath, newFilePath)) {
2419
- recordDegradationOnce({
2420
- kind: "lsp-capability-skip",
2421
- subject: `${state.serverId}:workspace/didRenameFiles:filter`,
2422
- reason: "filter-mismatch"
2423
- });
2424
- return;
2425
- }
2426
- await safeSendNotification(state.connection, "workspace/didRenameFiles", {
2427
- files: [
2428
- {
2429
- oldUri: wireOldUri,
2430
- newUri: wireNewUri
2431
- }
2432
- ]
2433
- });
2434
- },
2435
- async implementation(filePath, line, character) {
2436
- const result = await navRequest(state, "textDocument/implementation", {
2437
- textDocument: { uri: pathToFileURL(filePath).href },
2438
- position: await toWirePosition(state, filePath, line, character)
2439
- }, filePath);
2440
- if (!result)
2441
- return [];
2442
- return Array.isArray(result) ? result : [result];
2443
- },
2444
- async prepareCallHierarchy(filePath, line, character) {
2445
- const result = await navRequest(state, "textDocument/prepareCallHierarchy", {
2446
- textDocument: { uri: pathToFileURL(filePath).href },
2447
- position: await toWirePosition(state, filePath, line, character)
2448
- }, filePath);
2449
- if (!result)
2450
- return [];
2451
- return Array.isArray(result) ? result : [result];
2452
- },
2453
- async incomingCalls(item) {
2454
- const result = await navRequest(state, "callHierarchy/incomingCalls", { item });
2455
- return result ?? [];
2456
- },
2457
- async outgoingCalls(item) {
2458
- const result = await navRequest(state, "callHierarchy/outgoingCalls", { item });
2459
- return result ?? [];
2460
- },
2461
- async shutdown(options) {
2462
- return clientShutdown(state, options);
2463
- }
2464
- };
2465
- }
2466
- async function safeSendNotification(connection, method, params) {
2467
- try {
2468
- await connection.sendNotification(method, params);
2469
- return true;
2470
- } catch (err) {
2471
- if (isStreamError(err)) {
2472
- return false;
2473
- }
2474
- throw err;
2475
- }
2476
- }
2477
- const activeRequestsByConnection = new WeakMap;
2478
- async function safeSendRequest(connection, method, params, signal, settlement) {
2479
- if (signal?.aborted)
2480
- return;
2481
- let tokenSource;
2482
- let onAbort;
2483
- if (signal) {
2484
- tokenSource = new CancellationTokenSource;
2485
- onAbort = () => tokenSource?.cancel();
2486
- signal.addEventListener("abort", onAbort, { once: true });
2487
- }
2488
- const send = () => tokenSource ? connection.sendRequest(method, params, tokenSource.token) : connection.sendRequest(method, params);
2489
- activeRequestsByConnection.set(connection, (activeRequestsByConnection.get(connection) ?? 0) + 1);
2490
- try {
2491
- const MAX_ATTEMPTS = 2;
2492
- for (let attempt = 1;; attempt++) {
2493
- try {
2494
- return await send();
2495
- } catch (err) {
2496
- if (isCancellationError(err)) {
2497
- if (settlement)
2498
- settlement.cancelled = true;
2499
- return;
2500
- }
2501
- if (isStreamError(err)) {
2502
- return;
2503
- }
2504
- if (isContentModifiedError(err)) {
2505
- if (attempt < MAX_ATTEMPTS && !signal?.aborted)
2506
- continue;
2507
- return;
2508
- }
2509
- throw err;
2510
- }
2511
- }
2512
- } finally {
2513
- const remaining = (activeRequestsByConnection.get(connection) ?? 1) - 1;
2514
- if (remaining > 0)
2515
- activeRequestsByConnection.set(connection, remaining);
2516
- else
2517
- activeRequestsByConnection.delete(connection);
2518
- if (signal && onAbort)
2519
- signal.removeEventListener("abort", onAbort);
2520
- tokenSource?.dispose();
2521
- }
2522
- }
2523
- function isCancellationError(err) {
2524
- const code = err?.code;
2525
- return code === -32800 || code === -32802;
2526
- }
2527
- function isContentModifiedError(err) {
2528
- return err?.code === -32801;
2529
- }
2530
- function isStreamError(err) {
2531
- if (!(err instanceof Error))
2532
- return false;
2533
- const msg = err.message.toLowerCase();
2534
- return msg.includes("stream") || msg.includes("destroyed") || msg.includes("closed") || msg.includes("disposed") || msg.includes("cancelled") || err.code === "ERR_STREAM_DESTROYED" || err.code === "ERR_STREAM_WRITE_AFTER_END" || err.code === "EPIPE";
2535
- }
2536
- function positiveIntFromEnv(name, fallback) {
2537
- const raw = process.env[name];
2538
- if (!raw)
2539
- return fallback;
2540
- const parsed = Number.parseInt(raw, 10);
2541
- if (!Number.isFinite(parsed) || parsed <= 0)
2542
- return fallback;
2543
- return parsed;
2544
- }
2545
- function detectWorkspaceDiagnosticsSupport(initResult) {
2546
- const capabilities = typeof initResult === "object" && initResult !== null ? initResult.capabilities : undefined;
2547
- const diagnosticProvider = capabilities?.diagnosticProvider;
2548
- if (!diagnosticProvider) {
2549
- return {
2550
- advertised: false,
2551
- mode: "push-only",
2552
- workspaceDiagnostics: false,
2553
- diagnosticProviderKind: "none"
2554
- };
2555
- }
2556
- if (typeof diagnosticProvider === "boolean") {
2557
- return {
2558
- advertised: diagnosticProvider,
2559
- mode: diagnosticProvider ? "pull" : "push-only",
2560
- workspaceDiagnostics: false,
2561
- diagnosticProviderKind: "boolean"
2562
- };
2563
- }
2564
- if (typeof diagnosticProvider === "object") {
2565
- return {
2566
- advertised: true,
2567
- mode: "pull",
2568
- workspaceDiagnostics: diagnosticProvider.workspaceDiagnostics === true,
2569
- diagnosticProviderKind: "object"
2570
- };
2571
- }
2572
- return {
2573
- advertised: false,
2574
- mode: "push-only",
2575
- workspaceDiagnostics: false,
2576
- diagnosticProviderKind: typeof diagnosticProvider
2577
- };
2578
- }
2579
- function detectExecuteCommands(initResult) {
2580
- const capabilities = typeof initResult === "object" && initResult !== null ? initResult.capabilities : undefined;
2581
- const provider = capabilities?.executeCommandProvider;
2582
- if (typeof provider !== "object" || provider === null)
2583
- return [];
2584
- const commands = provider.commands;
2585
- if (!Array.isArray(commands))
2586
- return [];
2587
- return commands.filter((cmd) => typeof cmd === "string");
2588
- }
2589
- function detectOperationSupport(initResult) {
2590
- const capabilities = typeof initResult === "object" && initResult !== null ? initResult.capabilities : undefined;
2591
- const hasProvider = (key) => {
2592
- const value = capabilities?.[key];
2593
- if (value === undefined || value === null)
2594
- return false;
2595
- if (typeof value === "boolean")
2596
- return value;
2597
- return isCapabilityRecord(value);
2598
- };
2599
- const codeActionProvider = capabilities?.codeActionProvider;
2600
- const workspace = capabilities?.workspace;
2601
- const fileOperations = isCapabilityRecord(workspace) ? workspace.fileOperations : undefined;
2602
- return {
2603
- definition: hasProvider("definitionProvider"),
2604
- typeDefinition: hasProvider("typeDefinitionProvider"),
2605
- declaration: hasProvider("declarationProvider"),
2606
- references: hasProvider("referencesProvider"),
2607
- hover: hasProvider("hoverProvider"),
2608
- signatureHelp: hasProvider("signatureHelpProvider"),
2609
- documentSymbol: hasProvider("documentSymbolProvider"),
2610
- workspaceSymbol: hasProvider("workspaceSymbolProvider"),
2611
- codeAction: hasProvider("codeActionProvider"),
2612
- codeActionResolve: isCapabilityRecord(codeActionProvider) && codeActionProvider.resolveProvider === true,
2613
- rename: hasProvider("renameProvider"),
2614
- willRenameFiles: isCapabilityRecord(fileOperations) && isFileOperationRegistrationOptions(fileOperations.willRename),
2615
- didRenameFiles: isCapabilityRecord(fileOperations) && isFileOperationRegistrationOptions(fileOperations.didRename),
2616
- implementation: hasProvider("implementationProvider"),
2617
- callHierarchy: hasProvider("callHierarchyProvider")
2618
- };
2619
- }
2620
- function isCapabilityRecord(value) {
2621
- return typeof value === "object" && value !== null && !Array.isArray(value);
2622
- }
2623
- function isFileOperationRegistrationOptions(value) {
2624
- return parseFileOperationFilters(value) !== undefined;
2625
- }
2626
- function parseFileOperationFilters(value) {
2627
- if (!isCapabilityRecord(value) || !Array.isArray(value.filters)) {
2628
- return;
2629
- }
2630
- const filters = [];
2631
- for (const entry of value.filters) {
2632
- if (!isCapabilityRecord(entry))
2633
- return;
2634
- const pattern = entry.pattern;
2635
- if (!isCapabilityRecord(pattern) || typeof pattern.glob !== "string" || pattern.glob.trim() === "") {
2636
- return;
2637
- }
2638
- if (entry.scheme !== undefined && (typeof entry.scheme !== "string" || entry.scheme.trim() === "" || !/^[A-Za-z][A-Za-z0-9+.-]*$/.test(entry.scheme))) {
2639
- return;
2640
- }
2641
- const matches = pattern.matches;
2642
- if (matches !== undefined && matches !== "file" && matches !== "folder") {
2643
- return;
2644
- }
2645
- if (pattern.options !== undefined && !isCapabilityRecord(pattern.options)) {
2646
- return;
2647
- }
2648
- const options = isCapabilityRecord(pattern.options) ? pattern.options : undefined;
2649
- if (options?.ignoreCase !== undefined && typeof options.ignoreCase !== "boolean") {
2650
- return;
2651
- }
2652
- filters.push({
2653
- scheme: entry.scheme?.toLowerCase(),
2654
- glob: pattern.glob,
2655
- matches: matches === "file" || matches === "folder" ? matches : undefined,
2656
- ignoreCase: options?.ignoreCase === true
2657
- });
2658
- }
2659
- return filters;
2660
- }
2661
- async function fileOperationFiltersMatch(filters, oldUri, newUri, oldFilePath, newFilePath) {
2662
- if (!filters || filters.length === 0)
2663
- return false;
2664
- const candidates = [oldUri, newUri].flatMap(fileOperationUriCandidates);
2665
- const entityKind = filters.some((filter) => filter.matches !== undefined) ? await probeRenameEntityKind(oldFilePath, newFilePath) : undefined;
2666
- for (const filter of filters) {
2667
- if (filter.scheme !== undefined && filter.scheme !== "file")
2668
- continue;
2669
- if (filter.matches !== undefined && filter.matches !== entityKind)
2670
- continue;
2671
- for (const candidate of candidates) {
2672
- try {
2673
- if (minimatch(candidate, filter.glob, {
2674
- nocase: filter.ignoreCase,
2675
- dot: true
2676
- })) {
2677
- return true;
2678
- }
2679
- } catch {}
2680
- }
2681
- }
2682
- return false;
2683
- }
2684
- function fileOperationUriCandidates(uri) {
2685
- let parsed;
2686
- try {
2687
- parsed = new URL(uri);
2688
- } catch {
2689
- return [];
2690
- }
2691
- if (parsed.protocol.toLowerCase() !== "file:")
2692
- return [];
2693
- let uriPath;
2694
- try {
2695
- uriPath = decodeURIComponent(parsed.pathname).replace(/\\/g, "/");
2696
- } catch {
2697
- return [];
2698
- }
2699
- return [uriPath];
2700
- }
2701
- async function probeRenameEntityKind(oldFilePath, newFilePath) {
2702
- for (const filePath of [oldFilePath, newFilePath]) {
2703
- try {
2704
- const info = await lstat(filePath);
2705
- return info.isDirectory() ? "folder" : "file";
2706
- } catch {}
2707
- }
2708
- return;
2709
- }