oh-my-opencode 5.0.0-beta.31 → 5.0.0-beta.32

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 (227) hide show
  1. package/dist/cli/index.js +136 -44
  2. package/dist/cli-node/index.js +136 -44
  3. package/dist/features/background-agent/parent-wake-notifier-types.d.ts +1 -1
  4. package/dist/features/background-agent/parent-wake-prompt-dispatch.d.ts +1 -1
  5. package/dist/features/background-agent/parent-wake-session-inspector.d.ts +1 -1
  6. package/dist/features/monitor/manager-internals.d.ts +1 -1
  7. package/dist/features/monitor/output-injector-types.d.ts +1 -1
  8. package/dist/features/team-mode/tools/messaging-live-delivery-recipient.d.ts +1 -0
  9. package/dist/features/team-mode/tools/messaging-runtime.d.ts +1 -0
  10. package/dist/hooks/anthropic-context-window-limit-recovery/tool-result-storage.d.ts +11 -0
  11. package/dist/index.js +286 -99
  12. package/dist/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  13. package/dist/tools/session-manager/directory-filter.d.ts +2 -0
  14. package/dist/tui.js +109 -23
  15. package/package.json +16 -15
  16. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +47 -19
  17. package/packages/lsp-core/src/lsp/client-diagnostics-pull-timeout.test.ts +64 -0
  18. package/packages/lsp-core/src/lsp/client.ts +6 -3
  19. package/packages/lsp-core/src/lsp/controlled-clock-test-support.ts +61 -0
  20. package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +10 -3
  21. package/packages/lsp-core/src/lsp/timer-provider.ts +13 -0
  22. package/packages/lsp-core/src/lsp/transport-request-timeout.test.ts +73 -0
  23. package/packages/lsp-core/src/lsp/transport.ts +7 -2
  24. package/packages/lsp-core/src/lsp/workspace-document-state.test.ts +84 -1
  25. package/packages/lsp-core/src/lsp/workspace-document-state.ts +30 -11
  26. package/packages/lsp-core/src/tools/parameters.test.ts +51 -0
  27. package/packages/lsp-daemon/dist/cli.js +41 -16
  28. package/packages/lsp-daemon/dist/client.js +41 -16
  29. package/packages/lsp-daemon/dist/index.js +41 -16
  30. package/packages/lsp-tools-mcp/dist/cli.js +41 -16
  31. package/packages/lsp-tools-mcp/dist/lsp/manager.js +41 -16
  32. package/packages/lsp-tools-mcp/dist/mcp.js +41 -16
  33. package/packages/lsp-tools-mcp/dist/tools.js +41 -16
  34. package/packages/lsp-tools-mcp/package.json +1 -1
  35. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  36. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  37. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  38. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +3 -17
  39. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +3 -17
  40. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  41. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  42. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  43. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  44. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  45. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  46. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  47. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  48. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +39 -16
  49. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  50. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  51. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  52. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  53. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  54. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  55. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  56. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  57. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +5 -4
  58. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +489 -4
  59. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  60. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -2
  61. package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +30 -14
  62. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +4 -0
  63. package/packages/omo-codex/plugin/components/ultrawork/src/directive.ts +5 -2
  64. package/packages/omo-codex/plugin/components/ultrawork/test/directive-source.test.ts +14 -8
  65. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +12 -1
  66. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
  67. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  68. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +4 -2
  69. package/packages/omo-codex/plugin/components/ulw-loop/README.md +1 -0
  70. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +9 -0
  71. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +14 -0
  72. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +10 -1
  73. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.d.ts +8 -0
  74. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +113 -0
  75. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +7 -5
  76. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
  77. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
  78. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +1 -0
  79. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +2 -0
  80. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +775 -312
  81. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +18 -0
  82. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +13 -0
  83. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +14 -0
  84. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +17 -9
  85. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +17 -2
  86. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +13 -0
  87. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +19 -0
  88. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +2 -0
  89. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +53 -0
  90. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.d.ts +9 -0
  91. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +85 -0
  92. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +1 -1
  93. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +41 -99
  94. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +4 -2
  95. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +184 -14
  96. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +6 -0
  97. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +33 -0
  98. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +3 -0
  99. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +15 -0
  100. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  101. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  102. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +17 -0
  103. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +7 -0
  104. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +25 -1
  105. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +127 -0
  106. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +8 -12
  107. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +2 -1
  108. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +1 -0
  109. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +2 -0
  110. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +18 -0
  111. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +23 -0
  112. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +19 -9
  113. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +18 -3
  114. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +27 -0
  115. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +57 -0
  116. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +103 -0
  117. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +1 -1
  118. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +50 -116
  119. package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +4 -2
  120. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +186 -12
  121. package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +36 -0
  122. package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +22 -0
  123. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +66 -3
  124. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +92 -0
  125. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-status-next-actions.test.ts +183 -0
  126. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +13 -3
  127. package/packages/omo-codex/plugin/components/ulw-loop/test/guided-recovery.test.ts +105 -0
  128. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate.test.ts +101 -0
  129. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +16 -15
  130. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-senpi-surface.test.ts +131 -0
  131. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +5 -0
  132. package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +300 -3
  133. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +9 -3
  134. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  135. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  136. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  137. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  138. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  139. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  140. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  141. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  142. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  143. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  144. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  145. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  146. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  147. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  148. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  149. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  150. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  151. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  152. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +1 -1
  153. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  154. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  155. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  156. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  157. package/packages/omo-codex/plugin/package-lock.json +13 -13
  158. package/packages/omo-codex/plugin/package.json +1 -1
  159. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +31 -2
  160. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  161. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +17 -0
  162. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +11 -1
  163. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +13 -0
  164. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +5 -2
  165. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
  166. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  167. package/dist/features/builtin-skills/index.d.ts +0 -1
  168. package/dist/features/builtin-skills/skill-file-loader.d.ts +0 -1
  169. package/dist/features/builtin-skills/skills/agent-browser-skill.d.ts +0 -1
  170. package/dist/features/builtin-skills/skills/agent-browser-template.d.ts +0 -1
  171. package/dist/features/builtin-skills/skills/debugging.d.ts +0 -1
  172. package/dist/features/builtin-skills/skills/dev-browser.d.ts +0 -1
  173. package/dist/features/builtin-skills/skills/frontend.d.ts +0 -1
  174. package/dist/features/builtin-skills/skills/git-master-sections/commit-atomic-planning.d.ts +0 -1
  175. package/dist/features/builtin-skills/skills/git-master-sections/commit-context-analysis.d.ts +0 -1
  176. package/dist/features/builtin-skills/skills/git-master-sections/commit-execution-verification.d.ts +0 -1
  177. package/dist/features/builtin-skills/skills/git-master-sections/commit-workflow.d.ts +0 -1
  178. package/dist/features/builtin-skills/skills/git-master-sections/history-search-workflow.d.ts +0 -1
  179. package/dist/features/builtin-skills/skills/git-master-sections/overview.d.ts +0 -1
  180. package/dist/features/builtin-skills/skills/git-master-sections/quick-reference.d.ts +0 -1
  181. package/dist/features/builtin-skills/skills/git-master-sections/rebase-workflow.d.ts +0 -1
  182. package/dist/features/builtin-skills/skills/git-master-skill-metadata.d.ts +0 -1
  183. package/dist/features/builtin-skills/skills/git-master.d.ts +0 -1
  184. package/dist/features/builtin-skills/skills/index.d.ts +0 -1
  185. package/dist/features/builtin-skills/skills/init-deep.d.ts +0 -1
  186. package/dist/features/builtin-skills/skills/playwright-cli.d.ts +0 -1
  187. package/dist/features/builtin-skills/skills/playwright-mcp-skill.d.ts +0 -1
  188. package/dist/features/builtin-skills/skills/playwright.d.ts +0 -1
  189. package/dist/features/builtin-skills/skills/remove-ai-slops.d.ts +0 -1
  190. package/dist/features/builtin-skills/skills/review-work.d.ts +0 -1
  191. package/dist/features/builtin-skills/skills/security-research.d.ts +0 -1
  192. package/dist/features/builtin-skills/skills/security-review.d.ts +0 -1
  193. package/dist/features/builtin-skills/skills/team-mode.d.ts +0 -1
  194. package/dist/features/builtin-skills/skills/visual-qa.d.ts +0 -1
  195. package/dist/features/builtin-skills/skills.d.ts +0 -1
  196. package/dist/features/builtin-skills/types.d.ts +0 -1
  197. package/dist/features/claude-code-plugin-loader/agent-loader.d.ts +0 -1
  198. package/dist/features/claude-code-plugin-loader/command-loader.d.ts +0 -1
  199. package/dist/features/claude-code-plugin-loader/discovery-core.d.ts +0 -1
  200. package/dist/features/claude-code-plugin-loader/discovery-paths.d.ts +0 -1
  201. package/dist/features/claude-code-plugin-loader/discovery.d.ts +0 -1
  202. package/dist/features/claude-code-plugin-loader/hook-loader.d.ts +0 -1
  203. package/dist/features/claude-code-plugin-loader/index.d.ts +0 -1
  204. package/dist/features/claude-code-plugin-loader/install-path-resolver.d.ts +0 -1
  205. package/dist/features/claude-code-plugin-loader/installed-plugin-database.d.ts +0 -1
  206. package/dist/features/claude-code-plugin-loader/loaded-plugin.d.ts +0 -1
  207. package/dist/features/claude-code-plugin-loader/loader.d.ts +0 -1
  208. package/dist/features/claude-code-plugin-loader/mcp-server-loader.d.ts +0 -1
  209. package/dist/features/claude-code-plugin-loader/plugin-key.d.ts +0 -1
  210. package/dist/features/claude-code-plugin-loader/plugin-manifest.d.ts +0 -1
  211. package/dist/features/claude-code-plugin-loader/plugin-path-resolver.d.ts +0 -1
  212. package/dist/features/claude-code-plugin-loader/plugin-settings.d.ts +0 -1
  213. package/dist/features/claude-code-plugin-loader/scope-filter.d.ts +0 -1
  214. package/dist/features/claude-code-plugin-loader/skill-loader.d.ts +0 -1
  215. package/dist/features/claude-code-plugin-loader/types.d.ts +0 -1
  216. package/dist/shared/prompt-async-gate/message-inspection-error.d.ts +0 -1
  217. package/dist/shared/prompt-async-gate/pending-tool-turn.d.ts +0 -1
  218. package/dist/shared/prompt-async-gate/prompt-message-state.d.ts +0 -1
  219. package/dist/shared/prompt-async-gate/queue.d.ts +0 -1
  220. package/dist/shared/prompt-async-gate/recent-dispatches.d.ts +0 -1
  221. package/dist/shared/prompt-async-gate/reservations.d.ts +0 -1
  222. package/dist/shared/prompt-async-gate/semantic-dedupe.d.ts +0 -1
  223. package/dist/shared/prompt-async-gate/session-idle-dispatch.d.ts +0 -1
  224. package/dist/shared/prompt-async-gate/timing.d.ts +0 -1
  225. package/dist/shared/prompt-async-gate/types.d.ts +0 -1
  226. package/packages/omo-codex/plugin/components/ultrawork/directive.md +0 -483
  227. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +0 -490
@@ -1250,6 +1250,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
1250
1250
  // ../lsp-core/src/lsp/connection.ts
1251
1251
  import { pathToFileURL } from "node:url";
1252
1252
 
1253
+ // ../lsp-core/src/lsp/timer-provider.ts
1254
+ var realTimerProvider = {
1255
+ now: () => Date.now(),
1256
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
1257
+ clearTimeout: (handle) => clearTimeout(handle)
1258
+ };
1259
+
1253
1260
  // ../lsp-core/src/lsp/constants.ts
1254
1261
  var DEFAULT_MAX_REFERENCES = 200;
1255
1262
  var DEFAULT_MAX_SYMBOLS = 200;
@@ -1789,6 +1796,7 @@ class LspClientTransport {
1789
1796
  this.documentFormattingSupported = false;
1790
1797
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
1791
1798
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
1799
+ this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
1792
1800
  }
1793
1801
  pid() {
1794
1802
  return this.proc?.pid;
@@ -1889,7 +1897,7 @@ class LspClientTransport {
1889
1897
  const options = args[1];
1890
1898
  const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
1891
1899
  const timeoutController = new AbortController;
1892
- const timeoutHandle = setTimeout(() => {
1900
+ const timeoutHandle = this.timerProvider.setTimeout(() => {
1893
1901
  const stderrTail = this.stderrBuffer.slice(-5).join(`
1894
1902
  `);
1895
1903
  timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
@@ -1908,7 +1916,7 @@ class LspClientTransport {
1908
1916
  }
1909
1917
  throw error;
1910
1918
  } finally {
1911
- clearTimeout(timeoutHandle);
1919
+ this.timerProvider.clearTimeout(timeoutHandle);
1912
1920
  combinedSignal.dispose();
1913
1921
  }
1914
1922
  }
@@ -2289,6 +2297,17 @@ function canonicalPath(filePath) {
2289
2297
  return absolute;
2290
2298
  }
2291
2299
  }
2300
+ function normalizeDocumentUri(uri) {
2301
+ let decoded = uri;
2302
+ try {
2303
+ decoded = decodeURIComponent(uri);
2304
+ } catch {
2305
+ decoded = uri;
2306
+ }
2307
+ if (process.platform !== "win32")
2308
+ return decoded;
2309
+ return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
2310
+ }
2292
2311
  function isSameOrDescendant(candidate, parent) {
2293
2312
  const suffix = relative2(parent, candidate);
2294
2313
  return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
@@ -2305,7 +2324,12 @@ class WorkspaceDocumentState {
2305
2324
  this.openDocuments = new Map;
2306
2325
  this.openByUri = new Map;
2307
2326
  this.openPromises = new Map;
2308
- this.now = options.now ?? (() => Date.now());
2327
+ this.timerProvider = options.timerProvider ?? {
2328
+ now: options.now ?? (() => Date.now()),
2329
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
2330
+ clearTimeout: (handle) => clearTimeout(handle)
2331
+ };
2332
+ this.now = () => this.timerProvider.now();
2309
2333
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
2310
2334
  }
2311
2335
  async openFile(filePath) {
@@ -2327,7 +2351,7 @@ class WorkspaceDocumentState {
2327
2351
  return this.openDocuments.get(canonicalPath(filePath))?.version;
2328
2352
  }
2329
2353
  getStoredDiagnostics(uri) {
2330
- const state = this.openByUri.get(uri);
2354
+ const state = this.openByUri.get(normalizeDocumentUri(uri));
2331
2355
  if (!state)
2332
2356
  return [];
2333
2357
  return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
@@ -2349,13 +2373,13 @@ class WorkspaceDocumentState {
2349
2373
  return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
2350
2374
  }
2351
2375
  getPullCache(snapshot) {
2352
- const state = this.openByUri.get(snapshot.uri);
2376
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2353
2377
  if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
2354
2378
  return null;
2355
2379
  return state.pullCache;
2356
2380
  }
2357
2381
  recordPullDiagnostics(snapshot, report) {
2358
- const state = this.openByUri.get(snapshot.uri);
2382
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2359
2383
  if (!state)
2360
2384
  return;
2361
2385
  state.pullCache = {
@@ -2365,7 +2389,7 @@ class WorkspaceDocumentState {
2365
2389
  };
2366
2390
  }
2367
2391
  recordPublishedDiagnostics(params) {
2368
- const state = this.openByUri.get(params.uri);
2392
+ const state = this.openByUri.get(normalizeDocumentUri(params.uri));
2369
2393
  if (!state)
2370
2394
  return;
2371
2395
  state.publishGeneration += 1;
@@ -2379,7 +2403,7 @@ class WorkspaceDocumentState {
2379
2403
  this.notifyWaiters(state);
2380
2404
  }
2381
2405
  resolvePushDiagnostics(snapshot) {
2382
- const state = this.openByUri.get(snapshot.uri);
2406
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2383
2407
  if (!state?.lastPublish)
2384
2408
  return { status: "missing" };
2385
2409
  const publish = state.lastPublish;
@@ -2393,7 +2417,7 @@ class WorkspaceDocumentState {
2393
2417
  return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
2394
2418
  }
2395
2419
  waitForDiagnosticsActivity(snapshot, timeoutMs) {
2396
- const state = this.openByUri.get(snapshot.uri);
2420
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2397
2421
  if (!state || timeoutMs <= 0)
2398
2422
  return Promise.resolve();
2399
2423
  return new Promise((resolveActivity) => {
@@ -2402,11 +2426,11 @@ class WorkspaceDocumentState {
2402
2426
  if (settled)
2403
2427
  return;
2404
2428
  settled = true;
2405
- clearTimeout(timer);
2429
+ this.timerProvider.clearTimeout(timer);
2406
2430
  state.waiters.delete(finish);
2407
2431
  resolveActivity();
2408
2432
  };
2409
- const timer = setTimeout(finish, timeoutMs);
2433
+ const timer = this.timerProvider.setTimeout(finish, timeoutMs);
2410
2434
  if (typeof timer.unref === "function")
2411
2435
  timer.unref();
2412
2436
  state.waiters.add(finish);
@@ -2514,7 +2538,7 @@ class WorkspaceDocumentState {
2514
2538
  waiters: new Set
2515
2539
  };
2516
2540
  this.openDocuments.set(path2, state);
2517
- this.openByUri.set(state.uri, state);
2541
+ this.openByUri.set(normalizeDocumentUri(state.uri), state);
2518
2542
  this.notifyWaiters(state);
2519
2543
  await this.sendNotification("textDocument/didOpen", {
2520
2544
  textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
@@ -2539,7 +2563,7 @@ class WorkspaceDocumentState {
2539
2563
  }
2540
2564
  async closeDocument(state) {
2541
2565
  this.openDocuments.delete(state.path);
2542
- this.openByUri.delete(state.uri);
2566
+ this.openByUri.delete(normalizeDocumentUri(state.uri));
2543
2567
  this.clearDiagnostics(state.uri);
2544
2568
  this.notifyWaiters(state);
2545
2569
  await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
@@ -3626,6 +3650,7 @@ class LspClient extends LspClientConnection {
3626
3650
  this.diagnosticPullErrors = [];
3627
3651
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
3628
3652
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
3653
+ timerProvider: this.timerProvider,
3629
3654
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
3630
3655
  });
3631
3656
  this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
@@ -3729,7 +3754,7 @@ class LspClient extends LspClientConnection {
3729
3754
  const absPath = this.resolveWorkspacePath(filePath);
3730
3755
  const uri = pathToFileURL3(absPath).href;
3731
3756
  await this.openFile(absPath);
3732
- const deadlineAt = Date.now() + this.diagnosticsFreshnessTimeoutMs;
3757
+ const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
3733
3758
  for (;; ) {
3734
3759
  signal?.throwIfAborted();
3735
3760
  const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
@@ -3742,7 +3767,7 @@ class LspClient extends LspClientConnection {
3742
3767
  if (!pushFallbackOnly) {
3743
3768
  const cached = this.documents.getPullCache(snapshot);
3744
3769
  try {
3745
- const remainingMs2 = deadlineAt - Date.now();
3770
+ const remainingMs2 = deadlineAt - this.timerProvider.now();
3746
3771
  if (remainingMs2 <= 0)
3747
3772
  return this.freshnessTimeout(absPath);
3748
3773
  const result = await this.sendRequest("textDocument/diagnostic", {
@@ -3777,7 +3802,7 @@ class LspClient extends LspClientConnection {
3777
3802
  }
3778
3803
  if (!pushFallbackOnly)
3779
3804
  continue;
3780
- const remainingMs = deadlineAt - Date.now();
3805
+ const remainingMs = deadlineAt - this.timerProvider.now();
3781
3806
  if (remainingMs <= 0) {
3782
3807
  if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
3783
3808
  const cached = this.documents.getPullCache(snapshot);
@@ -15,6 +15,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
15
15
  // ../lsp-core/src/lsp/connection.ts
16
16
  import { pathToFileURL } from "node:url";
17
17
 
18
+ // ../lsp-core/src/lsp/timer-provider.ts
19
+ var realTimerProvider = {
20
+ now: () => Date.now(),
21
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
22
+ clearTimeout: (handle) => clearTimeout(handle)
23
+ };
24
+
18
25
  // ../lsp-core/src/lsp/constants.ts
19
26
  var DEFAULT_MAX_REFERENCES = 200;
20
27
  var DEFAULT_MAX_SYMBOLS = 200;
@@ -631,6 +638,7 @@ class LspClientTransport {
631
638
  this.documentFormattingSupported = false;
632
639
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
633
640
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
641
+ this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
634
642
  }
635
643
  pid() {
636
644
  return this.proc?.pid;
@@ -731,7 +739,7 @@ class LspClientTransport {
731
739
  const options = args[1];
732
740
  const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
733
741
  const timeoutController = new AbortController;
734
- const timeoutHandle = setTimeout(() => {
742
+ const timeoutHandle = this.timerProvider.setTimeout(() => {
735
743
  const stderrTail = this.stderrBuffer.slice(-5).join(`
736
744
  `);
737
745
  timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
@@ -750,7 +758,7 @@ class LspClientTransport {
750
758
  }
751
759
  throw error;
752
760
  } finally {
753
- clearTimeout(timeoutHandle);
761
+ this.timerProvider.clearTimeout(timeoutHandle);
754
762
  combinedSignal.dispose();
755
763
  }
756
764
  }
@@ -1141,6 +1149,17 @@ function canonicalPath(filePath) {
1141
1149
  return absolute;
1142
1150
  }
1143
1151
  }
1152
+ function normalizeDocumentUri(uri) {
1153
+ let decoded = uri;
1154
+ try {
1155
+ decoded = decodeURIComponent(uri);
1156
+ } catch {
1157
+ decoded = uri;
1158
+ }
1159
+ if (process.platform !== "win32")
1160
+ return decoded;
1161
+ return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
1162
+ }
1144
1163
  function isSameOrDescendant(candidate, parent) {
1145
1164
  const suffix = relative(parent, candidate);
1146
1165
  return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
@@ -1157,7 +1176,12 @@ class WorkspaceDocumentState {
1157
1176
  this.openDocuments = new Map;
1158
1177
  this.openByUri = new Map;
1159
1178
  this.openPromises = new Map;
1160
- this.now = options.now ?? (() => Date.now());
1179
+ this.timerProvider = options.timerProvider ?? {
1180
+ now: options.now ?? (() => Date.now()),
1181
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
1182
+ clearTimeout: (handle) => clearTimeout(handle)
1183
+ };
1184
+ this.now = () => this.timerProvider.now();
1161
1185
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1162
1186
  }
1163
1187
  async openFile(filePath) {
@@ -1179,7 +1203,7 @@ class WorkspaceDocumentState {
1179
1203
  return this.openDocuments.get(canonicalPath(filePath))?.version;
1180
1204
  }
1181
1205
  getStoredDiagnostics(uri) {
1182
- const state = this.openByUri.get(uri);
1206
+ const state = this.openByUri.get(normalizeDocumentUri(uri));
1183
1207
  if (!state)
1184
1208
  return [];
1185
1209
  return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
@@ -1201,13 +1225,13 @@ class WorkspaceDocumentState {
1201
1225
  return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
1202
1226
  }
1203
1227
  getPullCache(snapshot) {
1204
- const state = this.openByUri.get(snapshot.uri);
1228
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1205
1229
  if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
1206
1230
  return null;
1207
1231
  return state.pullCache;
1208
1232
  }
1209
1233
  recordPullDiagnostics(snapshot, report) {
1210
- const state = this.openByUri.get(snapshot.uri);
1234
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1211
1235
  if (!state)
1212
1236
  return;
1213
1237
  state.pullCache = {
@@ -1217,7 +1241,7 @@ class WorkspaceDocumentState {
1217
1241
  };
1218
1242
  }
1219
1243
  recordPublishedDiagnostics(params) {
1220
- const state = this.openByUri.get(params.uri);
1244
+ const state = this.openByUri.get(normalizeDocumentUri(params.uri));
1221
1245
  if (!state)
1222
1246
  return;
1223
1247
  state.publishGeneration += 1;
@@ -1231,7 +1255,7 @@ class WorkspaceDocumentState {
1231
1255
  this.notifyWaiters(state);
1232
1256
  }
1233
1257
  resolvePushDiagnostics(snapshot) {
1234
- const state = this.openByUri.get(snapshot.uri);
1258
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1235
1259
  if (!state?.lastPublish)
1236
1260
  return { status: "missing" };
1237
1261
  const publish = state.lastPublish;
@@ -1245,7 +1269,7 @@ class WorkspaceDocumentState {
1245
1269
  return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
1246
1270
  }
1247
1271
  waitForDiagnosticsActivity(snapshot, timeoutMs) {
1248
- const state = this.openByUri.get(snapshot.uri);
1272
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1249
1273
  if (!state || timeoutMs <= 0)
1250
1274
  return Promise.resolve();
1251
1275
  return new Promise((resolveActivity) => {
@@ -1254,11 +1278,11 @@ class WorkspaceDocumentState {
1254
1278
  if (settled)
1255
1279
  return;
1256
1280
  settled = true;
1257
- clearTimeout(timer);
1281
+ this.timerProvider.clearTimeout(timer);
1258
1282
  state.waiters.delete(finish);
1259
1283
  resolveActivity();
1260
1284
  };
1261
- const timer = setTimeout(finish, timeoutMs);
1285
+ const timer = this.timerProvider.setTimeout(finish, timeoutMs);
1262
1286
  if (typeof timer.unref === "function")
1263
1287
  timer.unref();
1264
1288
  state.waiters.add(finish);
@@ -1366,7 +1390,7 @@ class WorkspaceDocumentState {
1366
1390
  waiters: new Set
1367
1391
  };
1368
1392
  this.openDocuments.set(path, state);
1369
- this.openByUri.set(state.uri, state);
1393
+ this.openByUri.set(normalizeDocumentUri(state.uri), state);
1370
1394
  this.notifyWaiters(state);
1371
1395
  await this.sendNotification("textDocument/didOpen", {
1372
1396
  textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
@@ -1391,7 +1415,7 @@ class WorkspaceDocumentState {
1391
1415
  }
1392
1416
  async closeDocument(state) {
1393
1417
  this.openDocuments.delete(state.path);
1394
- this.openByUri.delete(state.uri);
1418
+ this.openByUri.delete(normalizeDocumentUri(state.uri));
1395
1419
  this.clearDiagnostics(state.uri);
1396
1420
  this.notifyWaiters(state);
1397
1421
  await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
@@ -2478,6 +2502,7 @@ class LspClient extends LspClientConnection {
2478
2502
  this.diagnosticPullErrors = [];
2479
2503
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2480
2504
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2505
+ timerProvider: this.timerProvider,
2481
2506
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
2482
2507
  });
2483
2508
  this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
@@ -2581,7 +2606,7 @@ class LspClient extends LspClientConnection {
2581
2606
  const absPath = this.resolveWorkspacePath(filePath);
2582
2607
  const uri = pathToFileURL3(absPath).href;
2583
2608
  await this.openFile(absPath);
2584
- const deadlineAt = Date.now() + this.diagnosticsFreshnessTimeoutMs;
2609
+ const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
2585
2610
  for (;; ) {
2586
2611
  signal?.throwIfAborted();
2587
2612
  const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
@@ -2594,7 +2619,7 @@ class LspClient extends LspClientConnection {
2594
2619
  if (!pushFallbackOnly) {
2595
2620
  const cached = this.documents.getPullCache(snapshot);
2596
2621
  try {
2597
- const remainingMs2 = deadlineAt - Date.now();
2622
+ const remainingMs2 = deadlineAt - this.timerProvider.now();
2598
2623
  if (remainingMs2 <= 0)
2599
2624
  return this.freshnessTimeout(absPath);
2600
2625
  const result = await this.sendRequest("textDocument/diagnostic", {
@@ -2629,7 +2654,7 @@ class LspClient extends LspClientConnection {
2629
2654
  }
2630
2655
  if (!pushFallbackOnly)
2631
2656
  continue;
2632
- const remainingMs = deadlineAt - Date.now();
2657
+ const remainingMs = deadlineAt - this.timerProvider.now();
2633
2658
  if (remainingMs <= 0) {
2634
2659
  if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
2635
2660
  const cached = this.documents.getPullCache(snapshot);
@@ -17,6 +17,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
17
17
  // ../lsp-core/src/lsp/connection.ts
18
18
  import { pathToFileURL } from "node:url";
19
19
 
20
+ // ../lsp-core/src/lsp/timer-provider.ts
21
+ var realTimerProvider = {
22
+ now: () => Date.now(),
23
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
24
+ clearTimeout: (handle) => clearTimeout(handle)
25
+ };
26
+
20
27
  // ../lsp-core/src/lsp/constants.ts
21
28
  var DEFAULT_MAX_REFERENCES = 200;
22
29
  var DEFAULT_MAX_SYMBOLS = 200;
@@ -633,6 +640,7 @@ class LspClientTransport {
633
640
  this.documentFormattingSupported = false;
634
641
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
635
642
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
643
+ this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
636
644
  }
637
645
  pid() {
638
646
  return this.proc?.pid;
@@ -733,7 +741,7 @@ class LspClientTransport {
733
741
  const options = args[1];
734
742
  const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
735
743
  const timeoutController = new AbortController;
736
- const timeoutHandle = setTimeout(() => {
744
+ const timeoutHandle = this.timerProvider.setTimeout(() => {
737
745
  const stderrTail = this.stderrBuffer.slice(-5).join(`
738
746
  `);
739
747
  timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
@@ -752,7 +760,7 @@ class LspClientTransport {
752
760
  }
753
761
  throw error;
754
762
  } finally {
755
- clearTimeout(timeoutHandle);
763
+ this.timerProvider.clearTimeout(timeoutHandle);
756
764
  combinedSignal.dispose();
757
765
  }
758
766
  }
@@ -1143,6 +1151,17 @@ function canonicalPath(filePath) {
1143
1151
  return absolute;
1144
1152
  }
1145
1153
  }
1154
+ function normalizeDocumentUri(uri) {
1155
+ let decoded = uri;
1156
+ try {
1157
+ decoded = decodeURIComponent(uri);
1158
+ } catch {
1159
+ decoded = uri;
1160
+ }
1161
+ if (process.platform !== "win32")
1162
+ return decoded;
1163
+ return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
1164
+ }
1146
1165
  function isSameOrDescendant(candidate, parent) {
1147
1166
  const suffix = relative(parent, candidate);
1148
1167
  return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
@@ -1159,7 +1178,12 @@ class WorkspaceDocumentState {
1159
1178
  this.openDocuments = new Map;
1160
1179
  this.openByUri = new Map;
1161
1180
  this.openPromises = new Map;
1162
- this.now = options.now ?? (() => Date.now());
1181
+ this.timerProvider = options.timerProvider ?? {
1182
+ now: options.now ?? (() => Date.now()),
1183
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
1184
+ clearTimeout: (handle) => clearTimeout(handle)
1185
+ };
1186
+ this.now = () => this.timerProvider.now();
1163
1187
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1164
1188
  }
1165
1189
  async openFile(filePath) {
@@ -1181,7 +1205,7 @@ class WorkspaceDocumentState {
1181
1205
  return this.openDocuments.get(canonicalPath(filePath))?.version;
1182
1206
  }
1183
1207
  getStoredDiagnostics(uri) {
1184
- const state = this.openByUri.get(uri);
1208
+ const state = this.openByUri.get(normalizeDocumentUri(uri));
1185
1209
  if (!state)
1186
1210
  return [];
1187
1211
  return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
@@ -1203,13 +1227,13 @@ class WorkspaceDocumentState {
1203
1227
  return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
1204
1228
  }
1205
1229
  getPullCache(snapshot) {
1206
- const state = this.openByUri.get(snapshot.uri);
1230
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1207
1231
  if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
1208
1232
  return null;
1209
1233
  return state.pullCache;
1210
1234
  }
1211
1235
  recordPullDiagnostics(snapshot, report) {
1212
- const state = this.openByUri.get(snapshot.uri);
1236
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1213
1237
  if (!state)
1214
1238
  return;
1215
1239
  state.pullCache = {
@@ -1219,7 +1243,7 @@ class WorkspaceDocumentState {
1219
1243
  };
1220
1244
  }
1221
1245
  recordPublishedDiagnostics(params) {
1222
- const state = this.openByUri.get(params.uri);
1246
+ const state = this.openByUri.get(normalizeDocumentUri(params.uri));
1223
1247
  if (!state)
1224
1248
  return;
1225
1249
  state.publishGeneration += 1;
@@ -1233,7 +1257,7 @@ class WorkspaceDocumentState {
1233
1257
  this.notifyWaiters(state);
1234
1258
  }
1235
1259
  resolvePushDiagnostics(snapshot) {
1236
- const state = this.openByUri.get(snapshot.uri);
1260
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1237
1261
  if (!state?.lastPublish)
1238
1262
  return { status: "missing" };
1239
1263
  const publish = state.lastPublish;
@@ -1247,7 +1271,7 @@ class WorkspaceDocumentState {
1247
1271
  return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
1248
1272
  }
1249
1273
  waitForDiagnosticsActivity(snapshot, timeoutMs) {
1250
- const state = this.openByUri.get(snapshot.uri);
1274
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1251
1275
  if (!state || timeoutMs <= 0)
1252
1276
  return Promise.resolve();
1253
1277
  return new Promise((resolveActivity) => {
@@ -1256,11 +1280,11 @@ class WorkspaceDocumentState {
1256
1280
  if (settled)
1257
1281
  return;
1258
1282
  settled = true;
1259
- clearTimeout(timer);
1283
+ this.timerProvider.clearTimeout(timer);
1260
1284
  state.waiters.delete(finish);
1261
1285
  resolveActivity();
1262
1286
  };
1263
- const timer = setTimeout(finish, timeoutMs);
1287
+ const timer = this.timerProvider.setTimeout(finish, timeoutMs);
1264
1288
  if (typeof timer.unref === "function")
1265
1289
  timer.unref();
1266
1290
  state.waiters.add(finish);
@@ -1368,7 +1392,7 @@ class WorkspaceDocumentState {
1368
1392
  waiters: new Set
1369
1393
  };
1370
1394
  this.openDocuments.set(path, state);
1371
- this.openByUri.set(state.uri, state);
1395
+ this.openByUri.set(normalizeDocumentUri(state.uri), state);
1372
1396
  this.notifyWaiters(state);
1373
1397
  await this.sendNotification("textDocument/didOpen", {
1374
1398
  textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
@@ -1393,7 +1417,7 @@ class WorkspaceDocumentState {
1393
1417
  }
1394
1418
  async closeDocument(state) {
1395
1419
  this.openDocuments.delete(state.path);
1396
- this.openByUri.delete(state.uri);
1420
+ this.openByUri.delete(normalizeDocumentUri(state.uri));
1397
1421
  this.clearDiagnostics(state.uri);
1398
1422
  this.notifyWaiters(state);
1399
1423
  await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
@@ -2480,6 +2504,7 @@ class LspClient extends LspClientConnection {
2480
2504
  this.diagnosticPullErrors = [];
2481
2505
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2482
2506
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2507
+ timerProvider: this.timerProvider,
2483
2508
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
2484
2509
  });
2485
2510
  this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
@@ -2583,7 +2608,7 @@ class LspClient extends LspClientConnection {
2583
2608
  const absPath = this.resolveWorkspacePath(filePath);
2584
2609
  const uri = pathToFileURL3(absPath).href;
2585
2610
  await this.openFile(absPath);
2586
- const deadlineAt = Date.now() + this.diagnosticsFreshnessTimeoutMs;
2611
+ const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
2587
2612
  for (;; ) {
2588
2613
  signal?.throwIfAborted();
2589
2614
  const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
@@ -2596,7 +2621,7 @@ class LspClient extends LspClientConnection {
2596
2621
  if (!pushFallbackOnly) {
2597
2622
  const cached = this.documents.getPullCache(snapshot);
2598
2623
  try {
2599
- const remainingMs2 = deadlineAt - Date.now();
2624
+ const remainingMs2 = deadlineAt - this.timerProvider.now();
2600
2625
  if (remainingMs2 <= 0)
2601
2626
  return this.freshnessTimeout(absPath);
2602
2627
  const result = await this.sendRequest("textDocument/diagnostic", {
@@ -2631,7 +2656,7 @@ class LspClient extends LspClientConnection {
2631
2656
  }
2632
2657
  if (!pushFallbackOnly)
2633
2658
  continue;
2634
- const remainingMs = deadlineAt - Date.now();
2659
+ const remainingMs = deadlineAt - this.timerProvider.now();
2635
2660
  if (remainingMs <= 0) {
2636
2661
  if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
2637
2662
  const cached = this.documents.getPullCache(snapshot);