lazycodex-ai 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 (145) hide show
  1. package/dist/cli/index.js +136 -44
  2. package/dist/cli-node/index.js +136 -44
  3. package/package.json +2 -2
  4. package/packages/lsp-daemon/dist/cli.js +41 -16
  5. package/packages/lsp-daemon/dist/client.js +41 -16
  6. package/packages/lsp-daemon/dist/index.js +41 -16
  7. package/packages/lsp-tools-mcp/dist/cli.js +41 -16
  8. package/packages/lsp-tools-mcp/dist/lsp/manager.js +41 -16
  9. package/packages/lsp-tools-mcp/dist/mcp.js +41 -16
  10. package/packages/lsp-tools-mcp/dist/tools.js +41 -16
  11. package/packages/lsp-tools-mcp/package.json +1 -1
  12. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  13. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  14. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  15. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +3 -17
  16. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +3 -17
  17. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  18. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  19. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  20. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  21. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  22. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  23. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  24. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  25. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +39 -16
  26. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  27. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  28. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  29. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  30. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  31. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  32. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  33. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  34. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +5 -4
  35. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +489 -4
  36. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  37. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -2
  38. package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +30 -14
  39. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +4 -0
  40. package/packages/omo-codex/plugin/components/ultrawork/src/directive.ts +5 -2
  41. package/packages/omo-codex/plugin/components/ultrawork/test/directive-source.test.ts +14 -8
  42. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +12 -1
  43. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
  44. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  45. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +4 -2
  46. package/packages/omo-codex/plugin/components/ulw-loop/README.md +1 -0
  47. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +9 -0
  48. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +14 -0
  49. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +10 -1
  50. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.d.ts +8 -0
  51. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +113 -0
  52. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +7 -5
  53. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
  54. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
  55. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +1 -0
  56. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +2 -0
  57. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +775 -312
  58. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +18 -0
  59. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +13 -0
  60. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +14 -0
  61. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +17 -9
  62. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +17 -2
  63. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +13 -0
  64. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +19 -0
  65. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +2 -0
  66. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +53 -0
  67. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.d.ts +9 -0
  68. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +85 -0
  69. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +1 -1
  70. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +41 -99
  71. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +4 -2
  72. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +184 -14
  73. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +6 -0
  74. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +33 -0
  75. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +3 -0
  76. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +15 -0
  77. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  78. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  79. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +17 -0
  80. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +7 -0
  81. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +25 -1
  82. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +127 -0
  83. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +8 -12
  84. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +2 -1
  85. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +1 -0
  86. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +2 -0
  87. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +18 -0
  88. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +23 -0
  89. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +19 -9
  90. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +18 -3
  91. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +27 -0
  92. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +57 -0
  93. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +103 -0
  94. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +1 -1
  95. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +50 -116
  96. package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +4 -2
  97. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +186 -12
  98. package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +36 -0
  99. package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +22 -0
  100. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +66 -3
  101. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +92 -0
  102. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-status-next-actions.test.ts +183 -0
  103. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +13 -3
  104. package/packages/omo-codex/plugin/components/ulw-loop/test/guided-recovery.test.ts +105 -0
  105. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate.test.ts +101 -0
  106. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +16 -15
  107. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-senpi-surface.test.ts +131 -0
  108. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +5 -0
  109. package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +300 -3
  110. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +9 -3
  111. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  112. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  113. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  114. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  115. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  116. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  117. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  118. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  119. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  120. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  121. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  122. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  123. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  124. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  125. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  126. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  127. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  128. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  129. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +1 -1
  130. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  131. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  132. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  133. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  134. package/packages/omo-codex/plugin/package-lock.json +13 -13
  135. package/packages/omo-codex/plugin/package.json +1 -1
  136. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +31 -2
  137. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  138. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +17 -0
  139. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +11 -1
  140. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +13 -0
  141. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +5 -2
  142. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
  143. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  144. package/packages/omo-codex/plugin/components/ultrawork/directive.md +0 -483
  145. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +0 -490
@@ -595,6 +595,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
595
595
  // ../lsp-core/src/lsp/connection.ts
596
596
  import { pathToFileURL } from "node:url";
597
597
 
598
+ // ../lsp-core/src/lsp/timer-provider.ts
599
+ var realTimerProvider = {
600
+ now: () => Date.now(),
601
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
602
+ clearTimeout: (handle) => clearTimeout(handle)
603
+ };
604
+
598
605
  // ../lsp-core/src/lsp/constants.ts
599
606
  var DEFAULT_MAX_REFERENCES = 200;
600
607
  var DEFAULT_MAX_SYMBOLS = 200;
@@ -1134,6 +1141,7 @@ class LspClientTransport {
1134
1141
  this.documentFormattingSupported = false;
1135
1142
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
1136
1143
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
1144
+ this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
1137
1145
  }
1138
1146
  pid() {
1139
1147
  return this.proc?.pid;
@@ -1234,7 +1242,7 @@ class LspClientTransport {
1234
1242
  const options = args[1];
1235
1243
  const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
1236
1244
  const timeoutController = new AbortController;
1237
- const timeoutHandle = setTimeout(() => {
1245
+ const timeoutHandle = this.timerProvider.setTimeout(() => {
1238
1246
  const stderrTail = this.stderrBuffer.slice(-5).join(`
1239
1247
  `);
1240
1248
  timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
@@ -1253,7 +1261,7 @@ class LspClientTransport {
1253
1261
  }
1254
1262
  throw error;
1255
1263
  } finally {
1256
- clearTimeout(timeoutHandle);
1264
+ this.timerProvider.clearTimeout(timeoutHandle);
1257
1265
  combinedSignal.dispose();
1258
1266
  }
1259
1267
  }
@@ -1634,6 +1642,17 @@ function canonicalPath(filePath) {
1634
1642
  return absolute;
1635
1643
  }
1636
1644
  }
1645
+ function normalizeDocumentUri(uri) {
1646
+ let decoded = uri;
1647
+ try {
1648
+ decoded = decodeURIComponent(uri);
1649
+ } catch {
1650
+ decoded = uri;
1651
+ }
1652
+ if (process.platform !== "win32")
1653
+ return decoded;
1654
+ return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
1655
+ }
1637
1656
  function isSameOrDescendant(candidate, parent) {
1638
1657
  const suffix = relative2(parent, candidate);
1639
1658
  return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
@@ -1650,7 +1669,12 @@ class WorkspaceDocumentState {
1650
1669
  this.openDocuments = new Map;
1651
1670
  this.openByUri = new Map;
1652
1671
  this.openPromises = new Map;
1653
- this.now = options.now ?? (() => Date.now());
1672
+ this.timerProvider = options.timerProvider ?? {
1673
+ now: options.now ?? (() => Date.now()),
1674
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
1675
+ clearTimeout: (handle) => clearTimeout(handle)
1676
+ };
1677
+ this.now = () => this.timerProvider.now();
1654
1678
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1655
1679
  }
1656
1680
  async openFile(filePath) {
@@ -1672,7 +1696,7 @@ class WorkspaceDocumentState {
1672
1696
  return this.openDocuments.get(canonicalPath(filePath))?.version;
1673
1697
  }
1674
1698
  getStoredDiagnostics(uri) {
1675
- const state = this.openByUri.get(uri);
1699
+ const state = this.openByUri.get(normalizeDocumentUri(uri));
1676
1700
  if (!state)
1677
1701
  return [];
1678
1702
  return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
@@ -1694,13 +1718,13 @@ class WorkspaceDocumentState {
1694
1718
  return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
1695
1719
  }
1696
1720
  getPullCache(snapshot) {
1697
- const state = this.openByUri.get(snapshot.uri);
1721
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1698
1722
  if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
1699
1723
  return null;
1700
1724
  return state.pullCache;
1701
1725
  }
1702
1726
  recordPullDiagnostics(snapshot, report) {
1703
- const state = this.openByUri.get(snapshot.uri);
1727
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1704
1728
  if (!state)
1705
1729
  return;
1706
1730
  state.pullCache = {
@@ -1710,7 +1734,7 @@ class WorkspaceDocumentState {
1710
1734
  };
1711
1735
  }
1712
1736
  recordPublishedDiagnostics(params) {
1713
- const state = this.openByUri.get(params.uri);
1737
+ const state = this.openByUri.get(normalizeDocumentUri(params.uri));
1714
1738
  if (!state)
1715
1739
  return;
1716
1740
  state.publishGeneration += 1;
@@ -1724,7 +1748,7 @@ class WorkspaceDocumentState {
1724
1748
  this.notifyWaiters(state);
1725
1749
  }
1726
1750
  resolvePushDiagnostics(snapshot) {
1727
- const state = this.openByUri.get(snapshot.uri);
1751
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1728
1752
  if (!state?.lastPublish)
1729
1753
  return { status: "missing" };
1730
1754
  const publish = state.lastPublish;
@@ -1738,7 +1762,7 @@ class WorkspaceDocumentState {
1738
1762
  return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
1739
1763
  }
1740
1764
  waitForDiagnosticsActivity(snapshot, timeoutMs) {
1741
- const state = this.openByUri.get(snapshot.uri);
1765
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1742
1766
  if (!state || timeoutMs <= 0)
1743
1767
  return Promise.resolve();
1744
1768
  return new Promise((resolveActivity) => {
@@ -1747,11 +1771,11 @@ class WorkspaceDocumentState {
1747
1771
  if (settled)
1748
1772
  return;
1749
1773
  settled = true;
1750
- clearTimeout(timer);
1774
+ this.timerProvider.clearTimeout(timer);
1751
1775
  state.waiters.delete(finish);
1752
1776
  resolveActivity();
1753
1777
  };
1754
- const timer = setTimeout(finish, timeoutMs);
1778
+ const timer = this.timerProvider.setTimeout(finish, timeoutMs);
1755
1779
  if (typeof timer.unref === "function")
1756
1780
  timer.unref();
1757
1781
  state.waiters.add(finish);
@@ -1859,7 +1883,7 @@ class WorkspaceDocumentState {
1859
1883
  waiters: new Set
1860
1884
  };
1861
1885
  this.openDocuments.set(path, state);
1862
- this.openByUri.set(state.uri, state);
1886
+ this.openByUri.set(normalizeDocumentUri(state.uri), state);
1863
1887
  this.notifyWaiters(state);
1864
1888
  await this.sendNotification("textDocument/didOpen", {
1865
1889
  textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
@@ -1884,7 +1908,7 @@ class WorkspaceDocumentState {
1884
1908
  }
1885
1909
  async closeDocument(state) {
1886
1910
  this.openDocuments.delete(state.path);
1887
- this.openByUri.delete(state.uri);
1911
+ this.openByUri.delete(normalizeDocumentUri(state.uri));
1888
1912
  this.clearDiagnostics(state.uri);
1889
1913
  this.notifyWaiters(state);
1890
1914
  await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
@@ -2971,6 +2995,7 @@ class LspClient extends LspClientConnection {
2971
2995
  this.diagnosticPullErrors = [];
2972
2996
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2973
2997
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2998
+ timerProvider: this.timerProvider,
2974
2999
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
2975
3000
  });
2976
3001
  this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
@@ -3074,7 +3099,7 @@ class LspClient extends LspClientConnection {
3074
3099
  const absPath = this.resolveWorkspacePath(filePath);
3075
3100
  const uri = pathToFileURL3(absPath).href;
3076
3101
  await this.openFile(absPath);
3077
- const deadlineAt = Date.now() + this.diagnosticsFreshnessTimeoutMs;
3102
+ const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
3078
3103
  for (;; ) {
3079
3104
  signal?.throwIfAborted();
3080
3105
  const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
@@ -3087,7 +3112,7 @@ class LspClient extends LspClientConnection {
3087
3112
  if (!pushFallbackOnly) {
3088
3113
  const cached = this.documents.getPullCache(snapshot);
3089
3114
  try {
3090
- const remainingMs2 = deadlineAt - Date.now();
3115
+ const remainingMs2 = deadlineAt - this.timerProvider.now();
3091
3116
  if (remainingMs2 <= 0)
3092
3117
  return this.freshnessTimeout(absPath);
3093
3118
  const result = await this.sendRequest("textDocument/diagnostic", {
@@ -3122,7 +3147,7 @@ class LspClient extends LspClientConnection {
3122
3147
  }
3123
3148
  if (!pushFallbackOnly)
3124
3149
  continue;
3125
- const remainingMs = deadlineAt - Date.now();
3150
+ const remainingMs = deadlineAt - this.timerProvider.now();
3126
3151
  if (remainingMs <= 0) {
3127
3152
  if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
3128
3153
  const cached = this.documents.getPullCache(snapshot);
@@ -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);