@duckmind/dm-darwin-x64 0.66.5 → 0.66.7

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