lazycodex-ai 5.0.0-beta.4 → 5.0.0-beta.42

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 (551) hide show
  1. package/README.ja.md +25 -21
  2. package/README.ko.md +25 -21
  3. package/README.md +38 -23
  4. package/README.ru.md +24 -20
  5. package/README.zh-cn.md +25 -21
  6. package/dist/cli/config-manager/parse-opencode-config-file.d.ts +2 -1
  7. package/dist/cli/doctor/checks/system-plugin.d.ts +4 -3
  8. package/dist/cli/fallback-lane-policy.d.ts +1 -0
  9. package/dist/cli/index.js +67006 -64814
  10. package/dist/cli/install-codex/install-codex-test-fixtures.d.ts +1 -1
  11. package/dist/cli/run/on-complete-hook.d.ts +2 -0
  12. package/dist/cli/runtime-commands.d.ts +1 -1
  13. package/dist/cli/worktree-sweep/classify.d.ts +16 -0
  14. package/dist/cli/worktree-sweep/format.d.ts +8 -0
  15. package/dist/cli/worktree-sweep/git.d.ts +19 -0
  16. package/dist/cli/worktree-sweep/index.d.ts +7 -0
  17. package/dist/cli/worktree-sweep/options.d.ts +2 -0
  18. package/dist/cli/worktree-sweep/parse-worktree-list.d.ts +8 -0
  19. package/dist/cli/worktree-sweep/sweep.d.ts +2 -0
  20. package/dist/cli/worktree-sweep/types.d.ts +65 -0
  21. package/dist/cli/worktree-sweep/worktree-sweep.d.ts +2 -0
  22. package/dist/cli-node/index.js +67283 -65068
  23. package/package.json +9 -9
  24. package/packages/git-bash-mcp/dist/cli.js +6 -1
  25. package/packages/lsp-daemon/dist/cli.js +804 -329
  26. package/packages/lsp-daemon/dist/client.d.ts +10 -0
  27. package/packages/lsp-daemon/dist/client.js +764 -286
  28. package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
  29. package/packages/lsp-daemon/dist/daemon-client.js +3 -0
  30. package/packages/lsp-daemon/dist/ensure-daemon.js +1 -0
  31. package/packages/lsp-daemon/dist/index.js +768 -295
  32. package/packages/lsp-daemon/dist/proxy.js +3 -0
  33. package/packages/lsp-daemon/dist/version-reap.js +1 -1
  34. package/packages/lsp-daemon/package.json +1 -1
  35. package/packages/lsp-tools-mcp/dist/cli.js +723 -250
  36. package/packages/lsp-tools-mcp/dist/lsp/manager.js +259 -125
  37. package/packages/lsp-tools-mcp/dist/mcp.js +725 -252
  38. package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
  39. package/packages/lsp-tools-mcp/dist/tools.js +729 -260
  40. package/packages/lsp-tools-mcp/package.json +1 -1
  41. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +4 -6
  42. package/packages/omo-codex/plugin/.mcp.json +0 -6
  43. package/packages/omo-codex/plugin/AGENTS.md +47 -0
  44. package/packages/omo-codex/plugin/README.md +2 -2
  45. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +45 -49
  46. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  47. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  48. package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +1 -0
  49. package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +9 -0
  50. package/packages/omo-codex/plugin/components/comment-checker/biome.json +2 -2
  51. package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +2 -1
  52. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  53. package/packages/omo-codex/plugin/components/comment-checker/package.json +5 -5
  54. package/packages/omo-codex/plugin/components/comment-checker/src/apply-patch.ts +2 -8
  55. package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +1 -2
  56. package/packages/omo-codex/plugin/components/comment-checker/src/request-extractor.ts +1 -1
  57. package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +1 -0
  58. package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +1 -1
  59. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  60. package/packages/omo-codex/plugin/components/git-bash/package.json +3 -4
  61. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
  62. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +1 -5
  63. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +1 -5
  64. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  65. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +5 -5
  66. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +1 -5
  67. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +4 -21
  68. package/packages/omo-codex/plugin/components/lcx/skills/lcx-doctor/SKILL.md +1 -1
  69. package/packages/omo-codex/plugin/components/lsp/AGENTS.md +30 -15
  70. package/packages/omo-codex/plugin/components/lsp/biome.json +2 -2
  71. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +4 -4
  72. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +752 -300
  73. package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.js +1 -1
  74. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  75. package/packages/omo-codex/plugin/components/lsp/package.json +5 -5
  76. package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
  77. package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +1 -1
  78. package/packages/omo-codex/plugin/components/lsp/src/daemon-cli-path.ts +1 -5
  79. package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +6 -7
  80. package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +1 -2
  81. package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +11 -1
  82. package/packages/omo-codex/plugin/components/rules/AGENTS.md +12 -0
  83. package/packages/omo-codex/plugin/components/rules/biome.json +2 -2
  84. package/packages/omo-codex/plugin/components/rules/dist/cli.js +60 -45
  85. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  86. package/packages/omo-codex/plugin/components/rules/package.json +7 -7
  87. package/packages/omo-codex/plugin/components/rules/src/config.ts +1 -2
  88. package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +1 -2
  89. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +9 -5
  90. package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +1 -4
  91. package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +4 -9
  92. package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
  93. package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +17 -25
  94. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
  95. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
  96. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
  97. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
  98. package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
  99. package/packages/omo-codex/plugin/components/rules/test/dynamic-target-fingerprints.test.ts +1 -2
  100. package/packages/omo-codex/plugin/components/rules/test/engine.test.ts +7 -4
  101. package/packages/omo-codex/plugin/components/rules/test/finder.test.ts +2 -3
  102. package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +39 -72
  103. package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +1 -2
  104. package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
  105. package/packages/omo-codex/plugin/components/rules/test/matcher.test.ts +2 -3
  106. package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +1 -1
  107. package/packages/omo-codex/plugin/components/rules/test/parser.test.ts +1 -2
  108. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +5 -6
  109. package/packages/omo-codex/plugin/components/rules/test/rules-engine-consumption.test.ts +3 -6
  110. package/packages/omo-codex/plugin/components/rules/test/scanner.test.ts +1 -2
  111. package/packages/omo-codex/plugin/components/rules/test/sources.test.ts +2 -5
  112. package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +2 -17
  113. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  114. package/packages/omo-codex/plugin/components/teammode/package.json +5 -5
  115. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +4 -10
  116. package/packages/omo-codex/plugin/components/telemetry/AGENTS.md +8 -0
  117. package/packages/omo-codex/plugin/components/telemetry/biome.json +2 -2
  118. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2463 -437
  119. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2467 -441
  120. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  121. package/packages/omo-codex/plugin/components/telemetry/package.json +5 -5
  122. package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +1 -4
  123. package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -14
  124. package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +1 -1
  125. package/packages/omo-codex/plugin/components/telemetry/test/diagnostics.test.ts +2 -5
  126. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +10 -4
  127. package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
  128. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +489 -4
  129. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  130. package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -6
  131. package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +30 -14
  132. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -7
  133. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +31 -7
  134. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
  135. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +5 -5
  136. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +4 -0
  137. package/packages/omo-codex/plugin/components/ultrawork/src/directive.ts +5 -2
  138. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +9 -1
  139. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
  140. package/packages/omo-codex/plugin/components/ultrawork/test/directive-source.test.ts +14 -8
  141. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +12 -1
  142. package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
  143. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +2 -2
  144. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/NOTICE +1 -1
  145. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/README.md +5 -5
  146. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/biome.json +2 -2
  147. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/directive.md +6 -6
  148. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +12 -12
  149. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +28 -0
  150. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/package.json +12 -12
  151. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/boulder-reader.ts +1 -1
  152. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/cli.ts +1 -1
  153. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/codex-hook.ts +3 -3
  154. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/directive.ts +1 -1
  155. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/index.ts +1 -1
  156. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/boulder-reader.test.ts +3 -3
  157. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +1 -4
  158. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +8 -22
  159. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +19 -0
  160. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
  161. package/packages/omo-codex/plugin/components/ulw-loop/README.md +12 -1
  162. package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
  163. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +15 -3
  164. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.d.ts +12 -0
  165. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +45 -0
  166. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +9 -0
  167. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +15 -0
  168. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +15 -1
  169. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.d.ts +8 -0
  170. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +120 -0
  171. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +40 -39
  172. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +7 -2
  173. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
  174. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +12 -1
  175. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +2 -0
  176. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +958 -342
  177. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.d.ts +2 -0
  178. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +27 -6
  179. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +13 -0
  180. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +15 -1
  181. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +17 -9
  182. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +1 -1
  183. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +17 -2
  184. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +13 -0
  185. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +19 -0
  186. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +7 -0
  187. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +9 -0
  188. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.d.ts +12 -0
  189. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +104 -0
  190. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.d.ts +13 -1
  191. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +65 -9
  192. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +5 -1
  193. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +4 -2
  194. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +69 -111
  195. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +4 -2
  196. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +185 -14
  197. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +6 -0
  198. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +33 -0
  199. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +3 -3
  200. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +18 -0
  201. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +65 -0
  202. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  203. package/packages/omo-codex/plugin/components/ulw-loop/package.json +5 -5
  204. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +4 -3
  205. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
  206. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +22 -1
  207. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +81 -0
  208. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +7 -0
  209. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +31 -1
  210. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +134 -0
  211. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +38 -71
  212. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +7 -2
  213. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +14 -1
  214. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +2 -0
  215. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +3 -5
  216. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +34 -5
  217. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +26 -1
  218. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
  219. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +19 -9
  220. package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +1 -1
  221. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +18 -3
  222. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +27 -0
  223. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +11 -0
  224. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +123 -0
  225. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +68 -15
  226. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +6 -1
  227. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +82 -131
  228. package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +4 -2
  229. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +187 -12
  230. package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +36 -0
  231. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +3 -3
  232. package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +95 -0
  233. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
  234. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +133 -1
  235. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +137 -0
  236. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +25 -0
  237. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +26 -2
  238. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-status-next-actions.test.ts +183 -0
  239. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +37 -2
  240. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +18 -0
  241. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
  242. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +7 -3
  243. package/packages/omo-codex/plugin/components/ulw-loop/test/guided-recovery.test.ts +105 -0
  244. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -37
  245. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +9 -0
  246. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate-basics.test.ts +258 -0
  247. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-cap-and-dedupe.test.ts +22 -0
  248. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-poisoning-cascades.test.ts +97 -0
  249. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +46 -2
  250. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-senpi-surface.test.ts +131 -0
  251. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-single-report.test.ts +241 -0
  252. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +48 -3
  253. package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +318 -1
  254. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +8 -5
  255. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
  256. package/packages/omo-codex/plugin/components/ulw-loop/test/surface.test.ts +74 -0
  257. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +13 -8
  258. package/packages/omo-codex/plugin/components/ulw-loop/vitest.config.ts +1 -0
  259. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  260. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  261. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  262. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  263. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  264. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  265. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  266. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  267. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  268. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  269. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  270. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  271. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  272. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  273. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +17 -0
  274. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  275. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +17 -0
  276. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  277. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  278. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  279. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  280. package/packages/omo-codex/plugin/model-catalog.json +3 -3
  281. package/packages/omo-codex/plugin/package-lock.json +676 -524
  282. package/packages/omo-codex/plugin/package.json +2 -3
  283. package/packages/omo-codex/plugin/scripts/AGENTS.md +39 -0
  284. package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -2
  285. package/packages/omo-codex/plugin/scripts/auto-update.mjs +0 -9
  286. package/packages/omo-codex/plugin/scripts/canonical-ultrawork-directive.mjs +17 -0
  287. package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +0 -1
  288. package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +3 -3
  289. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +42 -31
  290. package/packages/omo-codex/plugin/shared/package.json +3 -4
  291. package/packages/omo-codex/plugin/shared/src/config-loader.ts +2 -102
  292. package/packages/omo-codex/plugin/shared/src/config-migration.ts +0 -1
  293. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +41 -130
  294. package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +51 -0
  295. package/packages/omo-codex/plugin/skills/ast-grep/SKILL.md +1 -1
  296. package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +62 -0
  297. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
  298. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  299. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
  300. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  301. package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
  302. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
  303. package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
  304. package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
  305. package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
  306. package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
  307. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  308. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  309. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +3 -1
  310. package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
  311. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
  312. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
  313. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
  314. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
  315. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
  316. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
  317. package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
  318. package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  319. package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
  320. package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
  321. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +12 -8
  322. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
  323. package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
  324. package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
  325. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
  326. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  327. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  328. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  329. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
  330. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
  331. package/packages/omo-codex/plugin/skills/git-master/SKILL.md +1 -1
  332. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +14 -14
  333. package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +1 -1
  334. package/packages/omo-codex/plugin/skills/lsp-setup/SKILL.md +1 -1
  335. package/packages/omo-codex/plugin/skills/programming/SKILL.md +1 -1
  336. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +1 -1
  337. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +1 -1
  338. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +101 -419
  339. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
  340. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +26 -9
  341. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  342. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
  343. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +23 -18
  344. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  345. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +15 -3
  346. package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +19 -26
  347. package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
  348. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +4 -3
  349. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
  350. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +22 -1
  351. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -7
  352. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +31 -7
  353. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
  354. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +5 -5
  355. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +8 -3
  356. package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
  357. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +4 -3
  358. package/packages/omo-codex/plugin/test/AGENTS.md +47 -0
  359. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
  360. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +9 -48
  361. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +2 -3
  362. package/packages/omo-codex/plugin/test/aggregate-mcp.test.mjs +2 -7
  363. package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
  364. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
  365. package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
  366. package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
  367. package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -27
  368. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +0 -31
  369. package/packages/omo-codex/plugin/test/canonical-ultrawork-directive.test.mjs +53 -0
  370. package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +2 -2
  371. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +1 -51
  372. package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +2 -2
  373. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +4 -5
  374. package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
  375. package/packages/omo-codex/plugin/test/mcp-research-servers.test.mjs +1 -3
  376. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
  377. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
  378. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
  379. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +24 -14
  380. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +14 -119
  381. package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
  382. package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
  383. package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
  384. package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
  385. package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
  386. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +5 -5
  387. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
  388. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2818 -913
  389. package/packages/{omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md → prompts-core/prompts/ultrawork/codex.md} +15 -10
  390. package/packages/shared-skills/package.json +7 -1
  391. package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
  392. package/packages/shared-skills/skills/ast-grep/SKILL.md +1 -1
  393. package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
  394. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
  395. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  396. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
  397. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  398. package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
  399. package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
  400. package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
  401. package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
  402. package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
  403. package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
  404. package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  405. package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  406. package/packages/shared-skills/skills/debugging/SKILL.md +3 -1
  407. package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
  408. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
  409. package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
  410. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
  411. package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
  412. package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
  413. package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
  414. package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
  415. package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
  416. package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  417. package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
  418. package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
  419. package/packages/shared-skills/skills/frontend/SKILL.md +12 -8
  420. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
  421. package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
  422. package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
  423. package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
  424. package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  425. package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  426. package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  427. package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
  428. package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
  429. package/packages/shared-skills/skills/git-master/SKILL.md +1 -1
  430. package/packages/shared-skills/skills/init-deep/SKILL.md +14 -14
  431. package/packages/shared-skills/skills/lsp-setup/SKILL.md +1 -1
  432. package/packages/shared-skills/skills/programming/SKILL.md +1 -1
  433. package/packages/shared-skills/skills/refactor/SKILL.md +1 -1
  434. package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +1 -1
  435. package/packages/shared-skills/skills/review-work/SKILL.md +100 -418
  436. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
  437. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +26 -9
  438. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  439. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
  440. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +23 -18
  441. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  442. package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +17 -16
  443. package/packages/shared-skills/skills/ulw-plan/SKILL.md +7 -8
  444. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
  445. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
  446. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
  447. package/packages/shared-skills/skills/ulw-research/SKILL.md +8 -3
  448. package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
  449. package/packages/shared-skills/skills/visual-qa/SKILL.md +4 -3
  450. package/script/qa/web-terminal-visual-qa.mjs +2 -0
  451. package/script/qa/xterm-live-terminal.mjs +18 -2
  452. package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts +0 -1
  453. package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts +0 -1
  454. package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts +0 -1
  455. package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.d.ts +0 -1
  456. package/packages/lsp-tools-mcp/dist/missing-dependency-result.d.ts +0 -1
  457. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +0 -58
  458. package/packages/omo-codex/plugin/components/codegraph/NODE-RUNTIME-LICENSES.md +0 -2951
  459. package/packages/omo-codex/plugin/components/codegraph/NOTICE +0 -16
  460. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +0 -12136
  461. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +0 -9734
  462. package/packages/omo-codex/plugin/components/codegraph/package.json +0 -33
  463. package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +0 -29
  464. package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +0 -79
  465. package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +0 -33
  466. package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +0 -25
  467. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +0 -131
  468. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +0 -258
  469. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +0 -309
  470. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +0 -80
  471. package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +0 -34
  472. package/packages/omo-codex/plugin/components/codegraph/src/serve-invocation.ts +0 -29
  473. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +0 -263
  474. package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +0 -106
  475. package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +0 -145
  476. package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +0 -21
  477. package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +0 -139
  478. package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +0 -15
  479. package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +0 -32
  480. package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +0 -109
  481. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +0 -148
  482. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +0 -175
  483. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +0 -81
  484. package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +0 -34
  485. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +0 -112
  486. package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +0 -26
  487. package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +0 -160
  488. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +0 -50
  489. package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +0 -29
  490. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +0 -320
  491. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +0 -172
  492. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +0 -91
  493. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +0 -100
  494. package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +0 -76
  495. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +0 -133
  496. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +0 -245
  497. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +0 -69
  498. package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +0 -43
  499. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +0 -147
  500. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +0 -175
  501. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +0 -385
  502. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +0 -206
  503. package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +0 -58
  504. package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +0 -104
  505. package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +0 -65
  506. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-availability.test.ts +0 -106
  507. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +0 -116
  508. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +0 -258
  509. package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +0 -56
  510. package/packages/omo-codex/plugin/components/codegraph/tsconfig.build.json +0 -13
  511. package/packages/omo-codex/plugin/components/codegraph/tsconfig.json +0 -25
  512. package/packages/omo-codex/plugin/components/start-work-continuation/LICENSE +0 -21
  513. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
  514. package/packages/omo-codex/plugin/components/ultrawork/directive.md +0 -471
  515. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +0 -18
  516. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +0 -17
  517. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
  518. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
  519. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/editor.mjs +0 -125
  520. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/jsonc.mjs +0 -43
  521. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/scaffold.mjs +0 -29
  522. package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +0 -121
  523. package/packages/omo-codex/plugin/skills/data-scientist/references/common-scenarios.md +0 -176
  524. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-templates.md +0 -197
  525. package/packages/omo-codex/plugin/skills/data-scientist/references/integration-patterns.md +0 -153
  526. package/packages/omo-codex/plugin/skills/data-scientist/references/performance-benchmarks.md +0 -37
  527. package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
  528. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
  529. package/packages/omo-codex/plugin/test/component-codegraph-mcp-smoke.test.mjs +0 -76
  530. package/packages/omo-codex/plugin/test/migrate-omo-sot.test.mjs +0 -179
  531. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
  532. package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
  533. package/packages/shared-skills/skills/data-scientist/references/common-scenarios.md +0 -176
  534. package/packages/shared-skills/skills/data-scientist/references/execution-templates.md +0 -197
  535. package/packages/shared-skills/skills/data-scientist/references/integration-patterns.md +0 -153
  536. package/packages/shared-skills/skills/data-scientist/references/performance-benchmarks.md +0 -37
  537. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/.gitattributes +0 -0
  538. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/CHANGELOG.md +0 -0
  539. /package/packages/omo-codex/plugin/components/{codegraph → ulw-execute-continuation}/LICENSE +0 -0
  540. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/plan-checklist.ts +0 -0
  541. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/types.ts +0 -0
  542. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
  543. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
  544. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
  545. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
  546. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
  547. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
  548. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
  549. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
  550. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
  551. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
@@ -1,7 +1,11 @@
1
+ // src/client.ts
2
+ import { statSync as statSync5 } from "node:fs";
3
+ import { isAbsolute as isAbsolute6 } from "node:path";
4
+
1
5
  // src/daemon-client.ts
2
6
  import { connect } from "node:net";
3
7
  import { homedir as homedir3 } from "node:os";
4
- import { join as join7 } from "node:path";
8
+ import { join as join8 } from "node:path";
5
9
 
6
10
  // ../lsp-core/src/request-context.ts
7
11
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -10,18 +14,17 @@ import { homedir } from "node:os";
10
14
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
11
15
 
12
16
  class LspRequestContextParseError extends Error {
13
- code;
14
- name = "LspRequestContextParseError";
15
17
  constructor(code, message) {
16
18
  super(message);
17
19
  this.code = code;
20
+ this.name = "LspRequestContextParseError";
18
21
  }
19
22
  }
20
23
 
21
24
  class LspRequestContextUnavailableError extends Error {
22
- name = "LspRequestContextUnavailableError";
23
25
  constructor() {
24
26
  super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
27
+ this.name = "LspRequestContextUnavailableError";
25
28
  }
26
29
  }
27
30
  var storage = new AsyncLocalStorage;
@@ -41,7 +44,7 @@ function contextCwd() {
41
44
  }
42
45
  function createStandaloneMcpRequestContext(input = {}) {
43
46
  const env = input.env ?? process.env;
44
- const cwd = canonicalCwd(input.cwd ?? process.cwd());
47
+ const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
45
48
  const home = input.homeDir ?? homedir();
46
49
  const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
47
50
  const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
@@ -179,7 +182,6 @@ function isPlainRecord(value) {
179
182
 
180
183
  // src/daemon-request-error.ts
181
184
  class DaemonRequestError extends Error {
182
- requestWritten;
183
185
  constructor(message, requestWritten) {
184
186
  super(message);
185
187
  this.name = "DaemonRequestError";
@@ -202,7 +204,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
202
204
  }
203
205
 
204
206
  class DaemonRequestTimedOutError extends DaemonRequestError {
205
- timeoutMs;
206
207
  constructor(requestWritten, timeoutMs) {
207
208
  super("daemon request timed out", requestWritten);
208
209
  this.name = "DaemonRequestTimedOutError";
@@ -281,14 +282,12 @@ var PROTOCOL_ERROR_CODE = -32002;
281
282
  var AUTH_TOKEN_BYTES = 32;
282
283
 
283
284
  class UnsafePrivateDirectoryError extends Error {
284
- path;
285
- reason;
286
- name = "UnsafePrivateDirectoryError";
287
- code = "unsafe_private_directory";
288
285
  constructor(path, reason) {
289
286
  super(`unsafe private directory ${path}: ${reason}`);
290
287
  this.path = path;
291
288
  this.reason = reason;
289
+ this.name = "UnsafePrivateDirectoryError";
290
+ this.code = "unsafe_private_directory";
292
291
  }
293
292
  }
294
293
  function authEnvelope(token) {
@@ -472,20 +471,18 @@ var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
472
471
  var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
473
472
 
474
473
  class InvalidRuntimeOverrideError extends Error {
475
- code = "invalid_runtime_override";
476
- reason;
477
474
  constructor(reason, message) {
478
475
  super(message);
476
+ this.code = "invalid_runtime_override";
479
477
  this.name = "InvalidRuntimeOverrideError";
480
478
  this.reason = reason;
481
479
  }
482
480
  }
483
481
 
484
482
  class InvalidDaemonVersionError extends Error {
485
- code = "invalid_daemon_version";
486
- version;
487
483
  constructor(version) {
488
484
  super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
485
+ this.code = "invalid_daemon_version";
489
486
  this.name = "InvalidDaemonVersionError";
490
487
  this.version = version;
491
488
  }
@@ -531,10 +528,9 @@ var requireFromHere = createRequire(import.meta.url);
531
528
  var MAX_SOCKET_PATH_LENGTH = 100;
532
529
 
533
530
  class InvalidDaemonDirectoryError extends Error {
534
- code = "invalid_daemon_directory";
535
- directory;
536
531
  constructor(directory) {
537
532
  super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
533
+ this.code = "invalid_daemon_directory";
538
534
  this.name = "InvalidDaemonDirectoryError";
539
535
  this.directory = directory;
540
536
  }
@@ -729,7 +725,8 @@ function spawnDaemonProcess(paths) {
729
725
  try {
730
726
  const child = spawn(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
731
727
  detached: true,
732
- stdio: ["ignore", logFd, logFd]
728
+ stdio: ["ignore", logFd, logFd],
729
+ windowsHide: true
733
730
  });
734
731
  child.once("spawn", () => closeSync2(logFd));
735
732
  child.once("error", (error) => {
@@ -1010,6 +1007,7 @@ async function runJsonRpcStdioServer(config) {
1010
1007
  const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
1011
1008
  isClosed = true;
1012
1009
  config.onIdleTimeout?.();
1010
+ config.input.destroy();
1013
1011
  });
1014
1012
  const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
1015
1013
  isClosed = true;
@@ -1106,7 +1104,11 @@ function createParentWatchdog(config, onDeadParent) {
1106
1104
  const probeAlive = config.probeAlive ?? isProcessAlive;
1107
1105
  let fired = false;
1108
1106
  const timer = setInterval(() => {
1109
- if (fired || probeAlive(parentPid))
1107
+ if (fired)
1108
+ return;
1109
+ const alive = probeAlive(parentPid);
1110
+ config.onPoll?.(alive);
1111
+ if (alive)
1110
1112
  return;
1111
1113
  fired = true;
1112
1114
  onDeadParent(parentPid, pollIntervalMs);
@@ -1141,8 +1143,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
1141
1143
  };
1142
1144
  }
1143
1145
  // ../lsp-core/src/lsp/client-wrapper.ts
1144
- import { existsSync as existsSync10, statSync as statSync4 } from "node:fs";
1145
- import { dirname as dirname8, join as join4, resolve as resolve7 } from "node:path";
1146
+ import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
1147
+ import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
1146
1148
 
1147
1149
  // ../lsp-core/src/lsp/effective-extension.ts
1148
1150
  import { basename as basename2, extname } from "node:path";
@@ -1156,22 +1158,15 @@ function effectiveExtension(filePath) {
1156
1158
 
1157
1159
  // ../lsp-core/src/lsp/errors.ts
1158
1160
  class LspConnectionClosedError extends Error {
1159
- serverId;
1160
- root;
1161
- name = "LspConnectionClosedError";
1162
1161
  constructor(serverId, root, message) {
1163
1162
  super(message ?? `LSP connection closed for ${serverId} at ${root}`);
1164
1163
  this.serverId = serverId;
1165
1164
  this.root = root;
1165
+ this.name = "LspConnectionClosedError";
1166
1166
  }
1167
1167
  }
1168
1168
 
1169
1169
  class LspProcessExitedError extends Error {
1170
- serverId;
1171
- root;
1172
- exitCode;
1173
- stderrTail;
1174
- name = "LspProcessExitedError";
1175
1170
  constructor(serverId, root, exitCode, stderrTail) {
1176
1171
  const stderrSuffix = stderrTail ? `
1177
1172
  stderr tail: ${stderrTail}` : "";
@@ -1180,46 +1175,59 @@ stderr tail: ${stderrTail}` : "";
1180
1175
  this.root = root;
1181
1176
  this.exitCode = exitCode;
1182
1177
  this.stderrTail = stderrTail;
1178
+ this.name = "LspProcessExitedError";
1183
1179
  }
1184
1180
  }
1185
1181
 
1186
1182
  class LspRequestTimeoutError extends Error {
1187
- method;
1188
- stderrTail;
1189
- name = "LspRequestTimeoutError";
1190
1183
  constructor(method, stderrTail) {
1191
1184
  const stderrSuffix = stderrTail ? `
1192
1185
  recent stderr: ${stderrTail}` : "";
1193
1186
  super(`LSP request timeout (method: ${method})${stderrSuffix}`);
1194
1187
  this.method = method;
1195
1188
  this.stderrTail = stderrTail;
1189
+ this.name = "LspRequestTimeoutError";
1196
1190
  }
1197
1191
  }
1198
1192
 
1199
1193
  class LspInvalidPathError extends Error {
1200
- name = "LspInvalidPathError";
1194
+ constructor() {
1195
+ super(...arguments);
1196
+ this.name = "LspInvalidPathError";
1197
+ }
1201
1198
  }
1202
1199
 
1203
1200
  class LspServerLookupError extends Error {
1204
- lookup;
1205
- name = "LspServerLookupError";
1206
1201
  constructor(message, lookup) {
1207
1202
  super(message);
1208
1203
  this.lookup = lookup;
1204
+ this.name = "LspServerLookupError";
1209
1205
  }
1210
1206
  }
1211
1207
 
1212
1208
  class LspServerInitializingError extends Error {
1213
- originalError;
1214
- name = "LspServerInitializingError";
1215
1209
  constructor(originalError) {
1216
1210
  super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
1217
1211
  this.originalError = originalError;
1212
+ this.name = "LspServerInitializingError";
1218
1213
  }
1219
1214
  }
1220
1215
 
1221
1216
  class LspProcessSpawnError extends Error {
1222
- name = "LspProcessSpawnError";
1217
+ constructor() {
1218
+ super(...arguments);
1219
+ this.name = "LspProcessSpawnError";
1220
+ }
1221
+ }
1222
+
1223
+ class LspClientRespawnBudgetExceededError extends Error {
1224
+ constructor(serverId, root, retryLimit) {
1225
+ super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
1226
+ this.serverId = serverId;
1227
+ this.root = root;
1228
+ this.retryLimit = retryLimit;
1229
+ this.name = "LspClientRespawnBudgetExceededError";
1230
+ }
1223
1231
  }
1224
1232
  function isLspDeadConnectionError(err) {
1225
1233
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
@@ -1242,6 +1250,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
1242
1250
  // ../lsp-core/src/lsp/connection.ts
1243
1251
  import { pathToFileURL } from "node:url";
1244
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
+
1245
1260
  // ../lsp-core/src/lsp/constants.ts
1246
1261
  var DEFAULT_MAX_REFERENCES = 200;
1247
1262
  var DEFAULT_MAX_SYMBOLS = 200;
@@ -1250,9 +1265,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
1250
1265
  var REQUEST_TIMEOUT_MS = 15000;
1251
1266
  var INIT_TIMEOUT_MS = 60000;
1252
1267
  var IDLE_TIMEOUT_MS = 5 * 60000;
1268
+ var MAX_RESIDENT_CLIENTS = 6;
1253
1269
  var REAPER_INTERVAL_MS = 60000;
1254
1270
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
1255
1271
  var STOP_SIGKILL_GRACE_MS = 1000;
1272
+ var CLIENT_RESPAWN_RETRY_LIMIT = 2;
1273
+ var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
1256
1274
 
1257
1275
  // ../lsp-core/src/lsp/json-rpc-connection.ts
1258
1276
  var HEADER_SEPARATOR2 = `\r
@@ -1264,20 +1282,31 @@ var METHOD_NOT_FOUND = -32601;
1264
1282
  var INTERNAL_ERROR = -32603;
1265
1283
 
1266
1284
  class JsonRpcConnection {
1267
- reader;
1268
- writer;
1269
- pendingRequests = new Map;
1270
- notificationHandlers = new Map;
1271
- requestHandlers = new Map;
1272
- closeHandlers = [];
1273
- errorHandlers = [];
1274
- inputBuffer = Buffer.alloc(0);
1275
- nextRequestId = 1;
1276
- listening = false;
1277
- disposed = false;
1278
1285
  constructor(reader, writer) {
1279
1286
  this.reader = reader;
1280
1287
  this.writer = writer;
1288
+ this.pendingRequests = new Map;
1289
+ this.notificationHandlers = new Map;
1290
+ this.requestHandlers = new Map;
1291
+ this.closeHandlers = [];
1292
+ this.errorHandlers = [];
1293
+ this.inputBuffer = Buffer.alloc(0);
1294
+ this.nextRequestId = 1;
1295
+ this.listening = false;
1296
+ this.disposed = false;
1297
+ this.handleData = (chunk) => {
1298
+ const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
1299
+ this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
1300
+ this.drainInputBuffer();
1301
+ };
1302
+ this.handleClose = () => {
1303
+ for (const handler of this.closeHandlers) {
1304
+ handler();
1305
+ }
1306
+ };
1307
+ this.handleStreamError = (error) => {
1308
+ this.emitError(error);
1309
+ };
1281
1310
  }
1282
1311
  listen() {
1283
1312
  if (this.listening)
@@ -1312,6 +1341,7 @@ class JsonRpcConnection {
1312
1341
  let cancelAfterWrite = false;
1313
1342
  let settled = false;
1314
1343
  const writeCancel = () => this.writeMessage({ jsonrpc: "2.0", method: "$/cancelRequest", params: { id } });
1344
+ let rejectAfterCancelWrite;
1315
1345
  const responsePromise = new Promise((resolve2, reject) => {
1316
1346
  const cleanup = () => {
1317
1347
  options.signal?.removeEventListener("abort", onAbort);
@@ -1323,15 +1353,19 @@ class JsonRpcConnection {
1323
1353
  this.pendingRequests.delete(key);
1324
1354
  cleanup();
1325
1355
  const rejectCancelled = () => reject(abortError2(options.signal));
1356
+ rejectAfterCancelWrite = async () => {
1357
+ try {
1358
+ await writeCancel();
1359
+ } catch (error) {
1360
+ this.emitError(toError(error));
1361
+ }
1362
+ rejectCancelled();
1363
+ };
1326
1364
  if (!requestWritten) {
1327
1365
  cancelAfterWrite = true;
1328
- rejectCancelled();
1329
1366
  return;
1330
1367
  }
1331
- writeCancel().then(rejectCancelled, (error) => {
1332
- this.emitError(toError(error));
1333
- rejectCancelled();
1334
- });
1368
+ rejectAfterCancelWrite();
1335
1369
  };
1336
1370
  const onAbort = () => settleCancel();
1337
1371
  this.pendingRequests.set(key, {
@@ -1359,7 +1393,7 @@ class JsonRpcConnection {
1359
1393
  await this.writeMessage(message);
1360
1394
  requestWritten = true;
1361
1395
  if (cancelAfterWrite)
1362
- await writeCancel();
1396
+ await rejectAfterCancelWrite?.();
1363
1397
  } catch (error) {
1364
1398
  if (settled)
1365
1399
  return responsePromise;
@@ -1398,19 +1432,6 @@ class JsonRpcConnection {
1398
1432
  this.notificationHandlers.clear();
1399
1433
  this.requestHandlers.clear();
1400
1434
  }
1401
- handleData = (chunk) => {
1402
- const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
1403
- this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
1404
- this.drainInputBuffer();
1405
- };
1406
- handleClose = () => {
1407
- for (const handler of this.closeHandlers) {
1408
- handler();
1409
- }
1410
- };
1411
- handleStreamError = (error) => {
1412
- this.emitError(error);
1413
- };
1414
1435
  drainInputBuffer() {
1415
1436
  while (true) {
1416
1437
  const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
@@ -1758,33 +1779,29 @@ function isPosition(value) {
1758
1779
 
1759
1780
  // ../lsp-core/src/lsp/transport.ts
1760
1781
  class LspClientNotStartedError extends Error {
1761
- serverId;
1762
- root;
1763
- name = "LspClientNotStartedError";
1764
1782
  constructor(serverId, root) {
1765
1783
  super("LSP client not started");
1766
1784
  this.serverId = serverId;
1767
1785
  this.root = root;
1786
+ this.name = "LspClientNotStartedError";
1768
1787
  }
1769
1788
  }
1770
1789
 
1771
1790
  class LspClientTransport {
1772
- root;
1773
- server;
1774
- proc = null;
1775
- connection = null;
1776
- stderrBuffer = [];
1777
- processExited = false;
1778
- diagnosticsStore = new Map;
1779
- requestTimeoutMs;
1780
- initializeTimeoutMs;
1781
- workspaceApplyEditHandler = null;
1782
- diagnosticPullSupported = false;
1783
1791
  constructor(root, server2, timeouts = {}) {
1784
1792
  this.root = root;
1785
1793
  this.server = server2;
1794
+ this.proc = null;
1795
+ this.connection = null;
1796
+ this.stderrBuffer = [];
1797
+ this.processExited = false;
1798
+ this.diagnosticsStore = new Map;
1799
+ this.workspaceApplyEditHandler = null;
1800
+ this.diagnosticPullSupported = false;
1801
+ this.documentFormattingSupported = false;
1786
1802
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
1787
1803
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
1804
+ this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
1788
1805
  }
1789
1806
  pid() {
1790
1807
  return this.proc?.pid;
@@ -1804,6 +1821,12 @@ class LspClientTransport {
1804
1821
  isDiagnosticPullSupported() {
1805
1822
  return this.diagnosticPullSupported;
1806
1823
  }
1824
+ setDocumentFormattingSupported(supported) {
1825
+ this.documentFormattingSupported = supported;
1826
+ }
1827
+ isDocumentFormattingSupported() {
1828
+ return this.documentFormattingSupported;
1829
+ }
1807
1830
  handlePublishDiagnostics(params) {
1808
1831
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
1809
1832
  }
@@ -1879,7 +1902,7 @@ class LspClientTransport {
1879
1902
  const options = args[1];
1880
1903
  const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
1881
1904
  const timeoutController = new AbortController;
1882
- const timeoutHandle = setTimeout(() => {
1905
+ const timeoutHandle = this.timerProvider.setTimeout(() => {
1883
1906
  const stderrTail = this.stderrBuffer.slice(-5).join(`
1884
1907
  `);
1885
1908
  timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
@@ -1898,7 +1921,7 @@ class LspClientTransport {
1898
1921
  }
1899
1922
  throw error;
1900
1923
  } finally {
1901
- clearTimeout(timeoutHandle);
1924
+ this.timerProvider.clearTimeout(timeoutHandle);
1902
1925
  combinedSignal.dispose();
1903
1926
  }
1904
1927
  }
@@ -2017,6 +2040,14 @@ function supportsDiagnosticPull(capabilities) {
2017
2040
  return false;
2018
2041
  return Object.hasOwn(capabilities, "diagnosticProvider");
2019
2042
  }
2043
+ function supportsDocumentFormatting(capabilities) {
2044
+ if (capabilities === undefined)
2045
+ return false;
2046
+ const provider = capabilities.documentFormattingProvider;
2047
+ if (provider === undefined || provider === null || provider === false)
2048
+ return false;
2049
+ return provider === true || typeof provider === "object";
2050
+ }
2020
2051
 
2021
2052
  class LspClientConnection extends LspClientTransport {
2022
2053
  async initialize() {
@@ -2033,6 +2064,7 @@ class LspClientConnection extends LspClientTransport {
2033
2064
  references: {},
2034
2065
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
2035
2066
  publishDiagnostics: {},
2067
+ formatting: { dynamicRegistration: false },
2036
2068
  rename: {
2037
2069
  prepareSupport: true,
2038
2070
  prepareSupportDefaultBehavior: 1
@@ -2074,6 +2106,7 @@ class LspClientConnection extends LspClientTransport {
2074
2106
  initializationOptions: this.server.initialization
2075
2107
  }, { timeoutMs: this.initializeTimeoutMs });
2076
2108
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
2109
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
2077
2110
  await this.sendNotification("initialized", {});
2078
2111
  await this.sendNotification("workspace/didChangeConfiguration", {
2079
2112
  settings: { json: { validate: { enable: true } } }
@@ -2269,6 +2302,17 @@ function canonicalPath(filePath) {
2269
2302
  return absolute;
2270
2303
  }
2271
2304
  }
2305
+ function normalizeDocumentUri(uri) {
2306
+ let decoded = uri;
2307
+ try {
2308
+ decoded = decodeURIComponent(uri);
2309
+ } catch {
2310
+ decoded = uri;
2311
+ }
2312
+ if (process.platform !== "win32")
2313
+ return decoded;
2314
+ return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
2315
+ }
2272
2316
  function isSameOrDescendant(candidate, parent) {
2273
2317
  const suffix = relative2(parent, candidate);
2274
2318
  return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
@@ -2279,17 +2323,18 @@ function movedPath(candidate, oldPath, newPath) {
2279
2323
  }
2280
2324
 
2281
2325
  class WorkspaceDocumentState {
2282
- sendNotification;
2283
- clearDiagnostics;
2284
- openDocuments = new Map;
2285
- openByUri = new Map;
2286
- openPromises = new Map;
2287
- now;
2288
- versionlessPublishQuiescenceMs;
2289
2326
  constructor(sendNotification, clearDiagnostics, options = {}) {
2290
2327
  this.sendNotification = sendNotification;
2291
2328
  this.clearDiagnostics = clearDiagnostics;
2292
- this.now = options.now ?? (() => Date.now());
2329
+ this.openDocuments = new Map;
2330
+ this.openByUri = new Map;
2331
+ this.openPromises = new Map;
2332
+ this.timerProvider = options.timerProvider ?? {
2333
+ now: options.now ?? (() => Date.now()),
2334
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
2335
+ clearTimeout: (handle) => clearTimeout(handle)
2336
+ };
2337
+ this.now = () => this.timerProvider.now();
2293
2338
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
2294
2339
  }
2295
2340
  async openFile(filePath) {
@@ -2311,7 +2356,7 @@ class WorkspaceDocumentState {
2311
2356
  return this.openDocuments.get(canonicalPath(filePath))?.version;
2312
2357
  }
2313
2358
  getStoredDiagnostics(uri) {
2314
- const state = this.openByUri.get(uri);
2359
+ const state = this.openByUri.get(normalizeDocumentUri(uri));
2315
2360
  if (!state)
2316
2361
  return [];
2317
2362
  return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
@@ -2333,13 +2378,13 @@ class WorkspaceDocumentState {
2333
2378
  return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
2334
2379
  }
2335
2380
  getPullCache(snapshot) {
2336
- const state = this.openByUri.get(snapshot.uri);
2381
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2337
2382
  if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
2338
2383
  return null;
2339
2384
  return state.pullCache;
2340
2385
  }
2341
2386
  recordPullDiagnostics(snapshot, report) {
2342
- const state = this.openByUri.get(snapshot.uri);
2387
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2343
2388
  if (!state)
2344
2389
  return;
2345
2390
  state.pullCache = {
@@ -2349,7 +2394,7 @@ class WorkspaceDocumentState {
2349
2394
  };
2350
2395
  }
2351
2396
  recordPublishedDiagnostics(params) {
2352
- const state = this.openByUri.get(params.uri);
2397
+ const state = this.openByUri.get(normalizeDocumentUri(params.uri));
2353
2398
  if (!state)
2354
2399
  return;
2355
2400
  state.publishGeneration += 1;
@@ -2363,7 +2408,7 @@ class WorkspaceDocumentState {
2363
2408
  this.notifyWaiters(state);
2364
2409
  }
2365
2410
  resolvePushDiagnostics(snapshot) {
2366
- const state = this.openByUri.get(snapshot.uri);
2411
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2367
2412
  if (!state?.lastPublish)
2368
2413
  return { status: "missing" };
2369
2414
  const publish = state.lastPublish;
@@ -2377,7 +2422,7 @@ class WorkspaceDocumentState {
2377
2422
  return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
2378
2423
  }
2379
2424
  waitForDiagnosticsActivity(snapshot, timeoutMs) {
2380
- const state = this.openByUri.get(snapshot.uri);
2425
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2381
2426
  if (!state || timeoutMs <= 0)
2382
2427
  return Promise.resolve();
2383
2428
  return new Promise((resolveActivity) => {
@@ -2386,11 +2431,11 @@ class WorkspaceDocumentState {
2386
2431
  if (settled)
2387
2432
  return;
2388
2433
  settled = true;
2389
- clearTimeout(timer);
2434
+ this.timerProvider.clearTimeout(timer);
2390
2435
  state.waiters.delete(finish);
2391
2436
  resolveActivity();
2392
2437
  };
2393
- const timer = setTimeout(finish, timeoutMs);
2438
+ const timer = this.timerProvider.setTimeout(finish, timeoutMs);
2394
2439
  if (typeof timer.unref === "function")
2395
2440
  timer.unref();
2396
2441
  state.waiters.add(finish);
@@ -2498,7 +2543,7 @@ class WorkspaceDocumentState {
2498
2543
  waiters: new Set
2499
2544
  };
2500
2545
  this.openDocuments.set(path2, state);
2501
- this.openByUri.set(state.uri, state);
2546
+ this.openByUri.set(normalizeDocumentUri(state.uri), state);
2502
2547
  this.notifyWaiters(state);
2503
2548
  await this.sendNotification("textDocument/didOpen", {
2504
2549
  textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
@@ -2523,7 +2568,7 @@ class WorkspaceDocumentState {
2523
2568
  }
2524
2569
  async closeDocument(state) {
2525
2570
  this.openDocuments.delete(state.path);
2526
- this.openByUri.delete(state.uri);
2571
+ this.openByUri.delete(normalizeDocumentUri(state.uri));
2527
2572
  this.clearDiagnostics(state.uri);
2528
2573
  this.notifyWaiters(state);
2529
2574
  await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
@@ -2552,13 +2597,11 @@ import { dirname as dirname4, isAbsolute as isAbsolute4, relative as relative3,
2552
2597
  import { fileURLToPath as fileURLToPath2 } from "node:url";
2553
2598
 
2554
2599
  class WorkspaceEditPathError extends Error {
2555
- path;
2556
- detail;
2557
- name = "WorkspaceEditPathError";
2558
2600
  constructor(path2, detail) {
2559
2601
  super(`${detail}: ${path2}`);
2560
2602
  this.path = path2;
2561
2603
  this.detail = detail;
2604
+ this.name = "WorkspaceEditPathError";
2562
2605
  }
2563
2606
  }
2564
2607
  function isPathInsideWorkspace(filePath, workspaceRoot) {
@@ -2850,13 +2893,11 @@ function canonicalFingerprint(operations) {
2850
2893
 
2851
2894
  // ../lsp-core/src/lsp/workspace-edit-types.ts
2852
2895
  class WorkspaceEditValidationError extends Error {
2853
- changeIndex;
2854
- detail;
2855
- name = "WorkspaceEditValidationError";
2856
2896
  constructor(changeIndex, detail) {
2857
2897
  super(`change ${changeIndex}: ${detail}`);
2858
2898
  this.changeIndex = changeIndex;
2859
2899
  this.detail = detail;
2900
+ this.name = "WorkspaceEditValidationError";
2860
2901
  }
2861
2902
  }
2862
2903
 
@@ -3354,10 +3395,9 @@ function simulateDelete(operation, virtual) {
3354
3395
  import { existsSync as existsSync6, lstatSync as lstatSync4, readdirSync as readdirSync2 } from "node:fs";
3355
3396
  import { dirname as dirname6, resolve as resolve5 } from "node:path";
3356
3397
  class WorkspaceSnapshotBuilder {
3357
- workspaceRoot;
3358
- snapshots = new Map;
3359
3398
  constructor(workspaceRoot) {
3360
3399
  this.workspaceRoot = workspaceRoot;
3400
+ this.snapshots = new Map;
3361
3401
  }
3362
3402
  build(operations) {
3363
3403
  this.add(this.workspaceRoot, false);
@@ -3401,8 +3441,10 @@ function snapshotOperations(operations, workspaceRoot) {
3401
3441
 
3402
3442
  // ../lsp-core/src/lsp/workspace-edit-plan.ts
3403
3443
  class PlanPathIndex {
3404
- firstChangeByPath = new Map;
3405
- reportedPathByCanonical = new Map;
3444
+ constructor() {
3445
+ this.firstChangeByPath = new Map;
3446
+ this.reportedPathByCanonical = new Map;
3447
+ }
3406
3448
  build(operations) {
3407
3449
  for (const operation of operations) {
3408
3450
  switch (operation.kind) {
@@ -3491,14 +3533,11 @@ function isRecord4(value) {
3491
3533
  }
3492
3534
 
3493
3535
  class WorkspaceMutationController {
3494
- workspaceRoot;
3495
- documents;
3496
- activeLease = null;
3497
- nextLeaseId = 1;
3498
- io;
3499
3536
  constructor(workspaceRoot, documents) {
3500
3537
  this.workspaceRoot = workspaceRoot;
3501
3538
  this.documents = documents;
3539
+ this.activeLease = null;
3540
+ this.nextLeaseId = 1;
3502
3541
  }
3503
3542
  setIo(io) {
3504
3543
  this.io = io;
@@ -3611,14 +3650,12 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
3611
3650
  var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
3612
3651
 
3613
3652
  class LspClient extends LspClientConnection {
3614
- diagnosticPullErrors = [];
3615
- documents;
3616
- workspaceMutations;
3617
- diagnosticsFreshnessTimeoutMs;
3618
3653
  constructor(root, server2, options = {}) {
3619
3654
  super(root, server2, options);
3655
+ this.diagnosticPullErrors = [];
3620
3656
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
3621
3657
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
3658
+ timerProvider: this.timerProvider,
3622
3659
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
3623
3660
  });
3624
3661
  this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
@@ -3671,6 +3708,18 @@ class LspClient extends LspClientConnection {
3671
3708
  textDocument: { uri: pathToFileURL3(absPath).href }
3672
3709
  }, options);
3673
3710
  }
3711
+ async formatDocument(filePath, options, signal) {
3712
+ if (!this.isDocumentFormattingSupported())
3713
+ return null;
3714
+ const absPath = this.resolveWorkspacePath(filePath);
3715
+ await this.openFile(absPath);
3716
+ const requestOptions = signal === undefined ? {} : { signal };
3717
+ const edits = await this.sendRequest("textDocument/formatting", {
3718
+ textDocument: { uri: pathToFileURL3(absPath).href },
3719
+ options
3720
+ }, requestOptions);
3721
+ return edits ?? [];
3722
+ }
3674
3723
  async workspaceSymbols(query, signal) {
3675
3724
  const options = signal === undefined ? {} : { signal };
3676
3725
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -3710,7 +3759,7 @@ class LspClient extends LspClientConnection {
3710
3759
  const absPath = this.resolveWorkspacePath(filePath);
3711
3760
  const uri = pathToFileURL3(absPath).href;
3712
3761
  await this.openFile(absPath);
3713
- const deadlineAt = Date.now() + this.diagnosticsFreshnessTimeoutMs;
3762
+ const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
3714
3763
  for (;; ) {
3715
3764
  signal?.throwIfAborted();
3716
3765
  const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
@@ -3723,7 +3772,7 @@ class LspClient extends LspClientConnection {
3723
3772
  if (!pushFallbackOnly) {
3724
3773
  const cached = this.documents.getPullCache(snapshot);
3725
3774
  try {
3726
- const remainingMs2 = deadlineAt - Date.now();
3775
+ const remainingMs2 = deadlineAt - this.timerProvider.now();
3727
3776
  if (remainingMs2 <= 0)
3728
3777
  return this.freshnessTimeout(absPath);
3729
3778
  const result = await this.sendRequest("textDocument/diagnostic", {
@@ -3758,7 +3807,7 @@ class LspClient extends LspClientConnection {
3758
3807
  }
3759
3808
  if (!pushFallbackOnly)
3760
3809
  continue;
3761
- const remainingMs = deadlineAt - Date.now();
3810
+ const remainingMs = deadlineAt - this.timerProvider.now();
3762
3811
  if (remainingMs <= 0) {
3763
3812
  if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
3764
3813
  const cached = this.documents.getPullCache(snapshot);
@@ -3916,18 +3965,16 @@ function awaitWithSignal2(promise, signal) {
3916
3965
  }
3917
3966
 
3918
3967
  class LspManager {
3919
- clients = new Map;
3920
- reaperHandle = null;
3921
- signalDisposer = null;
3922
- disposed = false;
3923
- idleTimeoutMs;
3924
- initTimeoutMs;
3925
- reaperIntervalMs;
3926
- clientFactory;
3927
- now;
3928
3968
  constructor(options = {}) {
3969
+ this.clients = new Map;
3970
+ this.pendingStops = new Map;
3971
+ this.respawnBudgets = new Map;
3972
+ this.reaperHandle = null;
3973
+ this.signalDisposer = null;
3974
+ this.disposed = false;
3929
3975
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
3930
3976
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
3977
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
3931
3978
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
3932
3979
  this.clientFactory = options.clientFactory ?? ((root, server2) => new LspClient(root, server2));
3933
3980
  this.now = options.now ?? (() => Date.now());
@@ -3947,24 +3994,79 @@ class LspManager {
3947
3994
  getKey(root, serverId) {
3948
3995
  return `${root}::${serverId}`;
3949
3996
  }
3997
+ tombstoneStop(key, client) {
3998
+ const stop = stopClientBestEffort(client);
3999
+ this.pendingStops.set(key, stop);
4000
+ stop.finally(() => {
4001
+ if (this.pendingStops.get(key) === stop) {
4002
+ this.pendingStops.delete(key);
4003
+ }
4004
+ });
4005
+ return stop;
4006
+ }
4007
+ recordDeadGeneration(key) {
4008
+ let budget = this.respawnBudgets.get(key);
4009
+ if (budget === undefined) {
4010
+ budget = { deadGenerations: 0, exhaustedAt: null };
4011
+ this.respawnBudgets.set(key, budget);
4012
+ }
4013
+ budget.deadGenerations += 1;
4014
+ }
4015
+ markHealthyGeneration(key) {
4016
+ this.respawnBudgets.delete(key);
4017
+ }
4018
+ ensureRespawnAllowed(key, root, serverId) {
4019
+ const budget = this.respawnBudgets.get(key);
4020
+ if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
4021
+ return;
4022
+ if (budget.exhaustedAt === null) {
4023
+ budget.exhaustedAt = this.now();
4024
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
4025
+ }
4026
+ if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
4027
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
4028
+ }
4029
+ budget.deadGenerations = 0;
4030
+ budget.exhaustedAt = null;
4031
+ }
3950
4032
  reapStale() {
3951
4033
  const t = this.now();
3952
4034
  for (const [key, managed] of this.clients) {
3953
4035
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3954
- stopClientBestEffort(managed.client);
3955
4036
  this.clients.delete(key);
4037
+ this.tombstoneStop(key, managed.client);
3956
4038
  continue;
3957
4039
  }
3958
4040
  if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
3959
- stopClientBestEffort(managed.client);
3960
4041
  this.clients.delete(key);
4042
+ this.tombstoneStop(key, managed.client);
3961
4043
  }
3962
4044
  }
3963
4045
  }
4046
+ evictForAdmission() {
4047
+ while (this.clients.size >= this.maxResidentClients) {
4048
+ const victim = this.leastRecentlyUsedIdleClient();
4049
+ if (!victim)
4050
+ return;
4051
+ this.clients.delete(victim.key);
4052
+ this.tombstoneStop(victim.key, victim.managed.client);
4053
+ }
4054
+ }
4055
+ leastRecentlyUsedIdleClient() {
4056
+ let candidate = null;
4057
+ for (const [key, managed] of this.clients) {
4058
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
4059
+ continue;
4060
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
4061
+ candidate = { key, managed };
4062
+ }
4063
+ }
4064
+ return candidate;
4065
+ }
3964
4066
  async tryDeleteIfOrphaned(key, managed) {
3965
4067
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
3966
4068
  this.clients.delete(key);
3967
- await stopClientBestEffort(managed.client);
4069
+ await this.tombstoneStop(key, managed.client);
3968
4070
  }
3969
4071
  }
3970
4072
  async getClient(root, server2, signal) {
@@ -3973,12 +4075,22 @@ class LspManager {
3973
4075
  }
3974
4076
  signal?.throwIfAborted();
3975
4077
  const key = this.getKey(root, server2.id);
4078
+ for (;; ) {
4079
+ const pendingStop = this.pendingStops.get(key);
4080
+ if (pendingStop === undefined)
4081
+ break;
4082
+ await awaitWithSignal2(pendingStop, signal);
4083
+ signal?.throwIfAborted();
4084
+ }
4085
+ if (this.disposed) {
4086
+ throw new Error("LspManager has been disposed");
4087
+ }
3976
4088
  let managed = this.clients.get(key);
3977
4089
  if (managed) {
3978
4090
  const t = this.now();
3979
4091
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3980
- await stopClientBestEffort(managed.client);
3981
4092
  this.clients.delete(key);
4093
+ await this.tombstoneStop(key, managed.client);
3982
4094
  managed = undefined;
3983
4095
  }
3984
4096
  }
@@ -3999,14 +4111,20 @@ class LspManager {
3999
4111
  signal.throwIfAborted();
4000
4112
  }
4001
4113
  if (!managed.client.isAlive()) {
4002
- await stopClientBestEffort(managed.client);
4003
- this.clients.delete(key);
4114
+ this.recordDeadGeneration(key);
4115
+ if (this.clients.get(key) === managed) {
4116
+ this.clients.delete(key);
4117
+ }
4118
+ await this.tombstoneStop(key, managed.client);
4004
4119
  return this.getClient(root, server2, signal);
4005
4120
  }
4121
+ this.markHealthyGeneration(key);
4006
4122
  managed.refCount++;
4007
4123
  managed.lastUsedAt = this.now();
4008
4124
  return managed.client;
4009
4125
  }
4126
+ this.evictForAdmission();
4127
+ this.ensureRespawnAllowed(key, root, server2.id);
4010
4128
  const client = this.clientFactory(root, server2);
4011
4129
  const initStartedAt = this.now();
4012
4130
  const initPromise = (async () => {
@@ -4030,7 +4148,7 @@ class LspManager {
4030
4148
  if (this.clients.get(key) === newManaged) {
4031
4149
  this.clients.delete(key);
4032
4150
  }
4033
- await stopClientBestEffort(client);
4151
+ await this.tombstoneStop(key, client);
4034
4152
  throw err;
4035
4153
  }
4036
4154
  newManaged.pendingWaiters--;
@@ -4041,6 +4159,15 @@ class LspManager {
4041
4159
  await this.tryDeleteIfOrphaned(key, newManaged);
4042
4160
  signal.throwIfAborted();
4043
4161
  }
4162
+ if (!client.isAlive()) {
4163
+ this.recordDeadGeneration(key);
4164
+ if (this.clients.get(key) === newManaged) {
4165
+ this.clients.delete(key);
4166
+ }
4167
+ await this.tombstoneStop(key, client);
4168
+ return this.getClient(root, server2, signal);
4169
+ }
4170
+ this.markHealthyGeneration(key);
4044
4171
  newManaged.refCount++;
4045
4172
  newManaged.lastUsedAt = this.now();
4046
4173
  return client;
@@ -4061,14 +4188,20 @@ class LspManager {
4061
4188
  if (client && managed.client !== client)
4062
4189
  return;
4063
4190
  this.clients.delete(key);
4064
- stopClientBestEffort(managed.client);
4191
+ this.tombstoneStop(key, managed.client);
4065
4192
  }
4066
4193
  warmupClient(root, server2) {
4067
4194
  if (this.disposed)
4068
4195
  return;
4069
4196
  const key = this.getKey(root, server2.id);
4070
- if (this.clients.has(key))
4197
+ if (this.clients.has(key) || this.pendingStops.has(key))
4071
4198
  return;
4199
+ this.evictForAdmission();
4200
+ try {
4201
+ this.ensureRespawnAllowed(key, root, server2.id);
4202
+ } catch {
4203
+ return;
4204
+ }
4072
4205
  const client = this.clientFactory(root, server2);
4073
4206
  const initStartedAt = this.now();
4074
4207
  const initPromise = (async () => {
@@ -4094,7 +4227,7 @@ class LspManager {
4094
4227
  if (this.clients.get(key) === managed) {
4095
4228
  this.clients.delete(key);
4096
4229
  }
4097
- stopClientBestEffort(client);
4230
+ this.tombstoneStop(key, client);
4098
4231
  });
4099
4232
  }
4100
4233
  isServerInitializing(root, serverId) {
@@ -4138,8 +4271,11 @@ class LspManager {
4138
4271
  for (const managed of this.clients.values()) {
4139
4272
  stopPromises.push(stopClientBestEffort(managed.client));
4140
4273
  }
4274
+ const tombstonedStops = [...this.pendingStops.values()];
4141
4275
  this.clients.clear();
4142
- await Promise.allSettled(stopPromises);
4276
+ this.respawnBudgets.clear();
4277
+ await Promise.allSettled([...stopPromises, ...tombstonedStops]);
4278
+ this.pendingStops.clear();
4143
4279
  }
4144
4280
  }
4145
4281
  var _defaultInstance = null;
@@ -4157,57 +4293,52 @@ async function disposeDefaultLspManager() {
4157
4293
  }
4158
4294
  }
4159
4295
 
4160
- // ../lsp-core/src/lsp/server-install-state.ts
4161
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4162
- import { dirname as dirname7 } from "node:path";
4163
- function getInstallDecisionsPath() {
4164
- return lspRequestContext().installDecisionsPath;
4165
- }
4166
- function loadInstallDecisions() {
4167
- const path2 = getInstallDecisionsPath();
4168
- if (!existsSync7(path2))
4169
- return {};
4170
- try {
4171
- const parsed = JSON.parse(readFileSync4(path2, "utf8"));
4172
- return isInstallDecisions(parsed) ? parsed : {};
4173
- } catch {
4174
- return {};
4296
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
4297
+ import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
4298
+ import { dirname as dirname7, join as join3 } from "node:path";
4299
+
4300
+ // ../lsp-core/src/lsp/workspace-markers.ts
4301
+ var GIT_WORKSPACE_MARKER = ".git";
4302
+ var PROJECT_WORKSPACE_MARKERS = [
4303
+ "package.json",
4304
+ "pyproject.toml",
4305
+ "Cargo.toml",
4306
+ "go.mod",
4307
+ "pom.xml",
4308
+ "build.gradle"
4309
+ ];
4310
+ var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
4311
+
4312
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
4313
+ function findWorkspaceRootOutsideContext(directory) {
4314
+ const marked = nearestMarkedAncestor(directory);
4315
+ if (marked !== undefined)
4316
+ return marked;
4317
+ return realpathSync4(nearestExistingAncestor(directory));
4318
+ }
4319
+ function nearestMarkedAncestor(directory) {
4320
+ let current = directory;
4321
+ for (;; ) {
4322
+ if (existsSync7(current) && WORKSPACE_MARKERS.some((marker) => existsSync7(join3(current, marker)))) {
4323
+ return realpathSync4(current);
4324
+ }
4325
+ const parent = dirname7(current);
4326
+ if (parent === current)
4327
+ return;
4328
+ current = parent;
4175
4329
  }
4176
4330
  }
4177
- function loadInstallDecision(serverId) {
4178
- return loadInstallDecisions()[serverId];
4179
- }
4180
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4181
- const decisions = loadInstallDecisions();
4182
- decisions[serverId] = { decision, decidedAt };
4183
- writeInstallDecisions(decisions);
4184
- }
4185
- function isInstallDecision(value) {
4186
- return value === "declined" || value === "allowed";
4187
- }
4188
- function writeInstallDecisions(decisions) {
4189
- const path2 = getInstallDecisionsPath();
4190
- mkdirSync3(dirname7(path2), { recursive: true });
4191
- const tmpPath = `${path2}.tmp`;
4192
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4193
- `, "utf8");
4194
- renameSync2(tmpPath, path2);
4195
- }
4196
- function isInstallDecisions(value) {
4197
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4198
- }
4199
- function isInstallDecisionRecord(value) {
4200
- if (!isRecord5(value))
4201
- return false;
4202
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4203
- }
4204
- function isRecord5(value) {
4205
- return typeof value === "object" && value !== null && !Array.isArray(value);
4331
+ function nearestExistingAncestor(directory) {
4332
+ let current = directory;
4333
+ while (!existsSync7(current)) {
4334
+ const parent = dirname7(current);
4335
+ if (parent === current)
4336
+ return current;
4337
+ current = parent;
4338
+ }
4339
+ return current;
4206
4340
  }
4207
4341
 
4208
- // ../lsp-core/src/lsp/config-loader.ts
4209
- import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
4210
-
4211
4342
  // ../lsp-core/src/lsp/server-definitions.ts
4212
4343
  var LSP_INSTALL_HINTS = {
4213
4344
  typescript: "npm install -g typescript-language-server typescript",
@@ -4253,6 +4384,26 @@ var LSP_INSTALL_HINTS = {
4253
4384
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
4254
4385
  razor: "Razor runs through the Roslyn language server (cohosting). " + "Install: dotnet tool install -g roslyn-language-server --prerelease (requires v5.8.0+). See https://github.com/dotnet/razor"
4255
4386
  };
4387
+ var LSP_LOCAL_INSTALL_HINTS = {
4388
+ typescript: "bun add -d typescript-language-server typescript",
4389
+ vue: "bun add -d @vue/language-server",
4390
+ eslint: "bun add -d vscode-langservers-extracted",
4391
+ oxlint: "bun add -d oxlint",
4392
+ biome: "bun add -d @biomejs/biome",
4393
+ svelte: "bun add -d svelte-language-server",
4394
+ astro: "bun add -d @astrojs/language-server",
4395
+ bash: "bun add -d bash-language-server",
4396
+ "bash-ls": "bun add -d bash-language-server",
4397
+ "yaml-ls": "bun add -d yaml-language-server",
4398
+ php: "bun add -d intelephense",
4399
+ prisma: "bun add -d prisma",
4400
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
4401
+ pyright: "uv add --dev pyright",
4402
+ basedpyright: "uv add --dev basedpyright",
4403
+ ruff: "uv add --dev ruff",
4404
+ ty: "uv add --dev ty",
4405
+ "ruby-lsp": "bundle add ruby-lsp --group development"
4406
+ };
4256
4407
  var BUILTIN_SERVERS = {
4257
4408
  typescript: {
4258
4409
  command: ["typescript-language-server", "--stdio"],
@@ -4355,7 +4506,56 @@ var BUILTIN_SERVERS = {
4355
4506
  }
4356
4507
  };
4357
4508
 
4509
+ // ../lsp-core/src/lsp/server-install-state.ts
4510
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4511
+ import { dirname as dirname8 } from "node:path";
4512
+ function getInstallDecisionsPath() {
4513
+ return lspRequestContext().installDecisionsPath;
4514
+ }
4515
+ function loadInstallDecisions() {
4516
+ const path2 = getInstallDecisionsPath();
4517
+ if (!existsSync8(path2))
4518
+ return {};
4519
+ try {
4520
+ const parsed = JSON.parse(readFileSync4(path2, "utf8"));
4521
+ return isInstallDecisions(parsed) ? parsed : {};
4522
+ } catch {
4523
+ return {};
4524
+ }
4525
+ }
4526
+ function loadInstallDecision(serverId) {
4527
+ return loadInstallDecisions()[serverId];
4528
+ }
4529
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4530
+ const decisions = loadInstallDecisions();
4531
+ decisions[serverId] = { decision, decidedAt };
4532
+ writeInstallDecisions(decisions);
4533
+ }
4534
+ function isInstallDecision(value) {
4535
+ return value === "declined" || value === "allowed";
4536
+ }
4537
+ function writeInstallDecisions(decisions) {
4538
+ const path2 = getInstallDecisionsPath();
4539
+ mkdirSync3(dirname8(path2), { recursive: true });
4540
+ const tmpPath = `${path2}.tmp`;
4541
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4542
+ `, "utf8");
4543
+ renameSync2(tmpPath, path2);
4544
+ }
4545
+ function isInstallDecisions(value) {
4546
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4547
+ }
4548
+ function isInstallDecisionRecord(value) {
4549
+ if (!isRecord5(value))
4550
+ return false;
4551
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4552
+ }
4553
+ function isRecord5(value) {
4554
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4555
+ }
4556
+
4358
4557
  // ../lsp-core/src/lsp/config-loader.ts
4558
+ import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
4359
4559
  function getProjectConfigPaths() {
4360
4560
  return lspRequestContext().projectConfigPaths;
4361
4561
  }
@@ -4363,7 +4563,7 @@ function getUserConfigPath() {
4363
4563
  return lspRequestContext().userConfigPath;
4364
4564
  }
4365
4565
  function loadJsonFile(path2) {
4366
- if (!existsSync8(path2))
4566
+ if (!existsSync9(path2))
4367
4567
  return null;
4368
4568
  try {
4369
4569
  const parsed = JSON.parse(readFileSync5(path2, "utf-8"));
@@ -4551,54 +4751,155 @@ function getDisabledServerIds() {
4551
4751
  }
4552
4752
 
4553
4753
  // ../lsp-core/src/lsp/server-installation.ts
4554
- import { existsSync as existsSync9 } from "node:fs";
4555
- import { delimiter as delimiter3, join as join3 } from "node:path";
4556
- function isServerInstalled(command, _workingDirectory) {
4557
- if (command.length === 0)
4558
- return false;
4559
- const [cmd] = command;
4560
- if (!cmd)
4561
- return false;
4562
- if (cmd.includes("/") || cmd.includes("\\")) {
4563
- if (existsSync9(cmd))
4564
- return true;
4754
+ import { existsSync as existsSync10 } from "node:fs";
4755
+ import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
4756
+ var LOCAL_BIN_RULES = [
4757
+ {
4758
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
4759
+ binDirs: [join4("node_modules", ".bin")]
4760
+ },
4761
+ {
4762
+ markers: [
4763
+ "pyproject.toml",
4764
+ "ty.toml",
4765
+ "requirements.txt",
4766
+ "setup.py",
4767
+ "setup.cfg",
4768
+ "Pipfile",
4769
+ "pyrightconfig.json",
4770
+ "ruff.toml",
4771
+ ".ruff.toml"
4772
+ ],
4773
+ binDirs: [
4774
+ join4(".venv", "bin"),
4775
+ join4(".venv", "Scripts"),
4776
+ join4("venv", "bin"),
4777
+ join4("venv", "Scripts"),
4778
+ join4(".env", "bin"),
4779
+ join4(".env", "Scripts")
4780
+ ]
4781
+ },
4782
+ {
4783
+ markers: ["Gemfile", "Gemfile.lock"],
4784
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
4785
+ },
4786
+ {
4787
+ markers: ["go.mod", "go.sum", "go.work"],
4788
+ binDirs: ["bin"]
4789
+ }
4790
+ ];
4791
+ var resolutionCache = new Map;
4792
+ var probeCount = 0;
4793
+ function probe(path2) {
4794
+ probeCount += 1;
4795
+ return existsSync10(path2);
4796
+ }
4797
+ function executableSuffixes(platform, pathExt) {
4798
+ if (platform !== "win32")
4799
+ return [""];
4800
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
4801
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
4802
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4803
+ }
4804
+ function probeWithSuffixes(directory, command, suffixes) {
4805
+ for (const suffix of suffixes) {
4806
+ const candidate = join4(directory, command + suffix);
4807
+ if (probe(candidate))
4808
+ return candidate;
4565
4809
  }
4566
- const isWindows = process.platform === "win32";
4567
- let exts = [""];
4568
- if (isWindows) {
4569
- const pathExt = process.env["PATHEXT"] ?? "";
4570
- if (pathExt) {
4571
- const systemExts = pathExt.split(";").filter(Boolean);
4572
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4573
- } else {
4574
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
4810
+ return null;
4811
+ }
4812
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
4813
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
4814
+ let current = resolve7(workingDirectory);
4815
+ while (true) {
4816
+ for (const rule of LOCAL_BIN_RULES) {
4817
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
4818
+ continue;
4819
+ for (const binDir of rule.binDirs) {
4820
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
4821
+ if (found !== null)
4822
+ return found;
4823
+ }
4575
4824
  }
4825
+ if (probe(join4(current, ".git")))
4826
+ return null;
4827
+ if (boundary !== undefined && current === boundary)
4828
+ return null;
4829
+ const parent = dirname9(current);
4830
+ if (parent === current)
4831
+ return null;
4832
+ current = parent;
4576
4833
  }
4577
- let pathEnv = process.env["PATH"] ?? "";
4578
- if (isWindows && !pathEnv) {
4834
+ }
4835
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
4836
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
4837
+ if (platform === "win32" && !pathEnv) {
4579
4838
  pathEnv = process.env["Path"] ?? "";
4580
4839
  }
4581
- const paths = pathEnv.split(delimiter3);
4582
- for (const p of paths) {
4583
- for (const suffix of exts) {
4584
- if (existsSync9(join3(p, cmd + suffix))) {
4585
- return true;
4586
- }
4587
- }
4840
+ for (const entry of pathEnv.split(delimiter3)) {
4841
+ if (entry.length === 0)
4842
+ continue;
4843
+ const found = probeWithSuffixes(entry, command, suffixes);
4844
+ if (found !== null)
4845
+ return found;
4588
4846
  }
4589
- if (cmd === "node")
4590
- return true;
4591
- return false;
4847
+ return null;
4848
+ }
4849
+ function resolveServerBinary(command, workingDirectory, options = {}) {
4850
+ if (command.length === 0)
4851
+ return null;
4852
+ const [cmd] = command;
4853
+ if (cmd === undefined || cmd.length === 0)
4854
+ return null;
4855
+ const platform = options.platform ?? process.platform;
4856
+ const suffixes = executableSuffixes(platform, options.pathExt);
4857
+ if (cmd.includes("/") || cmd.includes("\\")) {
4858
+ const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
4859
+ return probe(explicit) ? explicit : null;
4860
+ }
4861
+ const cacheKey = JSON.stringify([
4862
+ workingDirectory ?? "",
4863
+ cmd,
4864
+ platform,
4865
+ options.stopAt ?? "",
4866
+ options.pathExt ?? "",
4867
+ options.pathEnv ?? process.env["PATH"] ?? ""
4868
+ ]);
4869
+ const cached = resolutionCache.get(cacheKey);
4870
+ if (cached !== undefined)
4871
+ return cached;
4872
+ let resolved = null;
4873
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
4874
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
4875
+ }
4876
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
4877
+ if (resolved === null && cmd === "node")
4878
+ resolved = cmd;
4879
+ resolutionCache.set(cacheKey, resolved);
4880
+ return resolved;
4881
+ }
4882
+ function isServerInstalled(command, workingDirectory, options = {}) {
4883
+ if (command.length === 0)
4884
+ return false;
4885
+ return resolveServerBinary(command, workingDirectory, options) !== null;
4592
4886
  }
4593
4887
 
4594
4888
  // ../lsp-core/src/lsp/server-resolution.ts
4889
+ function withResolvedCommand(command, binaryPath) {
4890
+ return [binaryPath, ...command.slice(1)];
4891
+ }
4595
4892
  function findServerForExtension(ext) {
4596
4893
  const servers = getMergedServers();
4894
+ const workingDirectory = contextCwd();
4597
4895
  for (const server2 of servers) {
4598
- if (server2.extensions.includes(ext) && isServerInstalled(server2.command)) {
4896
+ if (!server2.extensions.includes(ext))
4897
+ continue;
4898
+ const binaryPath = resolveServerBinary(server2.command, workingDirectory);
4899
+ if (binaryPath !== null) {
4599
4900
  const resolvedServer = {
4600
4901
  id: server2.id,
4601
- command: server2.command,
4902
+ command: withResolvedCommand(server2.command, binaryPath),
4602
4903
  extensions: server2.extensions,
4603
4904
  priority: server2.priority
4604
4905
  };
@@ -4645,6 +4946,7 @@ function findServerForExtension(ext) {
4645
4946
  function getAllServers() {
4646
4947
  const servers = getMergedServers();
4647
4948
  const disabled = getDisabledServerIds();
4949
+ const workingDirectory = contextCwd();
4648
4950
  const result = [];
4649
4951
  const seen = new Set;
4650
4952
  for (const server2 of servers) {
@@ -4652,7 +4954,7 @@ function getAllServers() {
4652
4954
  continue;
4653
4955
  result.push({
4654
4956
  id: server2.id,
4655
- installed: isServerInstalled(server2.command),
4957
+ installed: isServerInstalled(server2.command, workingDirectory),
4656
4958
  extensions: server2.extensions,
4657
4959
  disabled: false,
4658
4960
  source: server2.source,
@@ -4666,7 +4968,7 @@ function getAllServers() {
4666
4968
  const builtin = BUILTIN_SERVERS[id];
4667
4969
  result.push({
4668
4970
  id,
4669
- installed: builtin ? isServerInstalled(builtin.command) : false,
4971
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
4670
4972
  extensions: builtin?.extensions ?? [],
4671
4973
  disabled: true,
4672
4974
  source: "disabled",
@@ -4677,7 +4979,6 @@ function getAllServers() {
4677
4979
  }
4678
4980
 
4679
4981
  // ../lsp-core/src/lsp/client-wrapper.ts
4680
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
4681
4982
  function isDirectoryPath(filePath) {
4682
4983
  try {
4683
4984
  return statSync4(filePath).isDirectory();
@@ -4686,32 +4987,90 @@ function isDirectoryPath(filePath) {
4686
4987
  }
4687
4988
  }
4688
4989
  function findWorkspaceRoot(filePath) {
4689
- const abs = resolvePathInsideContext(filePath);
4990
+ const cwd = contextCwd();
4991
+ const abs = resolveReadablePathInsideContext(filePath);
4690
4992
  let dir = abs;
4691
4993
  if (!isDirectoryPath(dir)) {
4692
- dir = dirname8(dir);
4693
- }
4694
- let prevDir = "";
4695
- while (dir !== prevDir) {
4696
- for (const marker of WORKSPACE_MARKERS) {
4697
- if (existsSync10(join4(dir, marker))) {
4698
- return dir;
4994
+ dir = dirname10(dir);
4995
+ }
4996
+ if (!isPathInside(cwd, abs))
4997
+ return findWorkspaceRootOutsideContext(dir);
4998
+ const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4999
+ let nearestPackageRoot;
5000
+ while (isPathInside(cwd, dir)) {
5001
+ const canonicalDir = existingDirectoryInsideContext(dir, cwd);
5002
+ if (canonicalDir !== undefined) {
5003
+ if (existsSync11(join5(dir, GIT_WORKSPACE_MARKER))) {
5004
+ return canonicalDir;
5005
+ }
5006
+ if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
5007
+ nearestPackageRoot = canonicalDir;
4699
5008
  }
4700
5009
  }
4701
- prevDir = dir;
4702
- dir = dirname8(dir);
5010
+ if (dir === cwd)
5011
+ break;
5012
+ dir = dirname10(dir);
4703
5013
  }
4704
- return dirname8(abs);
5014
+ return nearestPackageRoot ?? fallbackRoot;
5015
+ }
5016
+ function hasProjectWorkspaceMarker(directory) {
5017
+ return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync11(join5(directory, marker)));
5018
+ }
5019
+ function resolveReadablePathInsideContext(filePath) {
5020
+ const cwd = contextCwd();
5021
+ const abs = resolve8(cwd, filePath);
5022
+ if (isPathInside(cwd, abs))
5023
+ return abs;
5024
+ const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
5025
+ if (rebased !== undefined)
5026
+ return rebased;
5027
+ return canonicalizeExistingOrNearestAncestor(abs);
4705
5028
  }
4706
5029
  function resolvePathInsideContext(filePath) {
4707
5030
  const cwd = contextCwd();
4708
- const abs = resolve7(cwd, filePath);
5031
+ const abs = resolveReadablePathInsideContext(filePath);
4709
5032
  const canonical = canonicalizeExistingOrNearestAncestor(abs);
4710
5033
  if (!isPathInside(cwd, canonical)) {
4711
5034
  throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
4712
5035
  }
4713
5036
  return canonical;
4714
5037
  }
5038
+ function rebaseThroughCanonicalAncestor(path2, cwd) {
5039
+ let current = path2;
5040
+ const suffix = [];
5041
+ while (true) {
5042
+ if (existsSync11(current)) {
5043
+ const canonical = realpathSync5(current);
5044
+ if (isPathInside(cwd, canonical))
5045
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
5046
+ }
5047
+ const parent = dirname10(current);
5048
+ if (parent === current)
5049
+ return;
5050
+ suffix.unshift(basename3(current));
5051
+ current = parent;
5052
+ }
5053
+ }
5054
+ function existingDirectoryInsideContext(directory, cwd) {
5055
+ if (!existsSync11(directory))
5056
+ return;
5057
+ const canonical = realpathSync5(directory);
5058
+ if (!statSync4(canonical).isDirectory())
5059
+ return;
5060
+ return isPathInside(cwd, canonical) ? canonical : undefined;
5061
+ }
5062
+ function nearestExistingDirectoryInsideContext(directory, cwd) {
5063
+ let current = directory;
5064
+ while (isPathInside(cwd, current)) {
5065
+ const canonical = existingDirectoryInsideContext(current, cwd);
5066
+ if (canonical !== undefined)
5067
+ return canonical;
5068
+ if (current === cwd)
5069
+ return;
5070
+ current = dirname10(current);
5071
+ }
5072
+ return;
5073
+ }
4715
5074
  function formatServerLookupError(result) {
4716
5075
  if (result.status === "not_installed") {
4717
5076
  return formatNotInstalled(result);
@@ -4735,6 +5094,19 @@ function formatServerLookupError(result) {
4735
5094
  ].join(`
4736
5095
  `);
4737
5096
  }
5097
+ function formatInstallOptions(serverId, installHint) {
5098
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
5099
+ if (localHint === undefined) {
5100
+ return ["To install, run:", ` ${installHint}`];
5101
+ }
5102
+ return [
5103
+ "To install in THIS repository (preferred — no global install needed):",
5104
+ ` ${localHint}`,
5105
+ "",
5106
+ "Or install it globally:",
5107
+ ` ${installHint}`
5108
+ ];
5109
+ }
4738
5110
  function formatNotInstalled(result) {
4739
5111
  const { server: server2, installHint } = result;
4740
5112
  const extensions = server2.extensions.join(", ");
@@ -4749,19 +5121,19 @@ function formatNotInstalled(result) {
4749
5121
  `Command not found: ${server2.command[0]}`,
4750
5122
  ""
4751
5123
  ];
5124
+ const installOptions = formatInstallOptions(server2.id, installHint);
4752
5125
  if (decision === "allowed") {
4753
5126
  return [
4754
5127
  ...header,
4755
5128
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
4756
- ` ${installHint}`
5129
+ ...installOptions.slice(1)
4757
5130
  ].join(`
4758
5131
  `);
4759
5132
  }
4760
5133
  if (!context.capabilities.installDecisionTool) {
4761
5134
  return [
4762
5135
  ...header,
4763
- "To install, run:",
4764
- ` ${installHint}`,
5136
+ ...installOptions,
4765
5137
  "",
4766
5138
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4767
5139
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -4770,8 +5142,7 @@ function formatNotInstalled(result) {
4770
5142
  }
4771
5143
  return [
4772
5144
  ...header,
4773
- "To install, run:",
4774
- ` ${installHint}`,
5145
+ ...installOptions,
4775
5146
  "",
4776
5147
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4777
5148
  "- If the user agrees: run the install command above, then retry this tool.",
@@ -4782,7 +5153,7 @@ function formatNotInstalled(result) {
4782
5153
  ].join(`
4783
5154
  `);
4784
5155
  }
4785
- var READ_ONLY_RETRY_TOOLS = new Set([
5156
+ var READ_ONLY_TOOLS = new Set([
4786
5157
  "diagnostics",
4787
5158
  "definition",
4788
5159
  "references",
@@ -4791,7 +5162,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
4791
5162
  "prepareRename"
4792
5163
  ]);
4793
5164
  async function withLspClient(filePath, fn, toolName, options = {}) {
4794
- const absPath = resolvePathInsideContext(filePath);
5165
+ const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
4795
5166
  if (isDirectoryPath(absPath)) {
4796
5167
  throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
4797
5168
  }
@@ -4806,9 +5177,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4806
5177
  const acquireAndCall = async (allowRetry) => {
4807
5178
  const client = await manager.getClient(root, server2, options.signal);
4808
5179
  try {
4809
- return await fn(client, root);
5180
+ return await fn(client, root, absPath);
4810
5181
  } catch (err) {
4811
- if (allowRetry && READ_ONLY_RETRY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
5182
+ if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4812
5183
  manager.invalidateClient(root, server2.id, client);
4813
5184
  return acquireAndCall(false);
4814
5185
  }
@@ -4826,8 +5197,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4826
5197
  }
4827
5198
 
4828
5199
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4829
- import { existsSync as existsSync11, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
4830
- import { join as join5, resolve as resolve8 } from "node:path";
5200
+ import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
5201
+ import { join as join6, resolve as resolve9 } from "node:path";
4831
5202
 
4832
5203
  // ../lsp-core/src/lsp/formatters.ts
4833
5204
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -4957,7 +5328,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
4957
5328
  for (const entry of entries) {
4958
5329
  if (files.length >= maxFiles)
4959
5330
  return;
4960
- const fullPath = join5(currentDir, entry);
5331
+ const fullPath = join6(currentDir, entry);
4961
5332
  let stat;
4962
5333
  try {
4963
5334
  stat = lstatSync5(fullPath);
@@ -4982,8 +5353,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4982
5353
  if (!extension.startsWith(".")) {
4983
5354
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4984
5355
  }
4985
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4986
- if (!existsSync11(absDir)) {
5356
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
5357
+ if (!existsSync12(absDir)) {
4987
5358
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4988
5359
  }
4989
5360
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
@@ -5070,7 +5441,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5070
5441
 
5071
5442
  // ../lsp-core/src/lsp/infer-extension.ts
5072
5443
  import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
5073
- import { join as join6 } from "node:path";
5444
+ import { join as join7 } from "node:path";
5074
5445
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
5075
5446
  var MAX_SCAN_ENTRIES = 500;
5076
5447
  function inferExtensionFromDirectory(directory) {
@@ -5088,7 +5459,7 @@ function inferExtensionFromDirectory(directory) {
5088
5459
  for (const entry of entries) {
5089
5460
  if (scanned >= MAX_SCAN_ENTRIES)
5090
5461
  return;
5091
- const fullPath = join6(dir, entry);
5462
+ const fullPath = join7(dir, entry);
5092
5463
  let stat;
5093
5464
  try {
5094
5465
  stat = lstatSync6(fullPath);
@@ -5263,7 +5634,7 @@ async function executeLspDiagnostics(params, signal) {
5263
5634
  const filePath = requireString(params, "filePath");
5264
5635
  const severity = severityFilter(params);
5265
5636
  try {
5266
- const absPath = resolvePathInsideContext(filePath);
5637
+ const absPath = resolveReadablePathInsideContext(filePath);
5267
5638
  if (isDirectoryPath(absPath)) {
5268
5639
  const extension = inferExtensionFromDirectory(absPath);
5269
5640
  if (!extension) {
@@ -5292,7 +5663,7 @@ async function executeLspDiagnostics(params, signal) {
5292
5663
  };
5293
5664
  return text(output2.output, details2);
5294
5665
  }
5295
- const result = await withLspClient(filePath, async (client) => client.diagnostics(filePath, signal), "diagnostics", clientOptions(signal));
5666
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
5296
5667
  if (result.transientError) {
5297
5668
  const message = result.transientError.message;
5298
5669
  const details2 = {
@@ -5339,6 +5710,96 @@ async function executeLspDiagnostics(params, signal) {
5339
5710
  throw error;
5340
5711
  }
5341
5712
  }
5713
+ // ../lsp-core/src/lsp/format-document.ts
5714
+ import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
5715
+ var DEFAULT_FORMATTING_OPTIONS = {
5716
+ tabSize: 4,
5717
+ insertSpaces: false,
5718
+ trimTrailingWhitespace: true,
5719
+ insertFinalNewline: true,
5720
+ trimFinalNewlines: true
5721
+ };
5722
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
5723
+ async function formatDocumentWithClient(client, filePath, options = {}) {
5724
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
5725
+ if (edits === null)
5726
+ return { status: "unavailable", reason: "capability_not_advertised" };
5727
+ if (edits.length === 0)
5728
+ return UNCHANGED;
5729
+ const before = readFileSync6(filePath, "utf-8");
5730
+ const normalized = normalizeTextEdits(before, edits, 0);
5731
+ if (normalized.text === before)
5732
+ return UNCHANGED;
5733
+ writeAtomically(filePath, normalized.text);
5734
+ await client.openFile(filePath);
5735
+ return {
5736
+ status: "formatted",
5737
+ ...lineDelta(normalized.edits)
5738
+ };
5739
+ }
5740
+ function lineDelta(edits) {
5741
+ let linesAdded = 0;
5742
+ let linesRemoved = 0;
5743
+ for (const edit of edits) {
5744
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
5745
+ linesAdded += edit.newText.split(`
5746
+ `).length;
5747
+ }
5748
+ return { linesAdded, linesRemoved };
5749
+ }
5750
+ function writeAtomically(filePath, content) {
5751
+ const tempPath = `${filePath}.omo-format.tmp`;
5752
+ writeFileSync3(tempPath, content, "utf-8");
5753
+ try {
5754
+ renameSync3(tempPath, filePath);
5755
+ } catch (error) {
5756
+ try {
5757
+ unlinkSync2(tempPath);
5758
+ } catch {}
5759
+ throw error;
5760
+ }
5761
+ }
5762
+
5763
+ // ../lsp-core/src/tools/format.ts
5764
+ async function executeLspFormat(params, signal) {
5765
+ const filePath = requireString(params, "filePath");
5766
+ try {
5767
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
5768
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
5769
+ } catch (error) {
5770
+ const missingDependency = missingDependencyResult(error, {
5771
+ filePath,
5772
+ status: "unavailable",
5773
+ reason: "server_unavailable",
5774
+ linesAdded: 0,
5775
+ linesRemoved: 0
5776
+ });
5777
+ if (missingDependency)
5778
+ return missingDependency;
5779
+ throw error;
5780
+ }
5781
+ }
5782
+ function formatDetails(filePath, result) {
5783
+ if (result.status === "unavailable") {
5784
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
5785
+ }
5786
+ return {
5787
+ filePath,
5788
+ status: result.status,
5789
+ linesAdded: result.linesAdded,
5790
+ linesRemoved: result.linesRemoved
5791
+ };
5792
+ }
5793
+ function describeResult(filePath, result) {
5794
+ if (result.status === "unavailable") {
5795
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
5796
+ }
5797
+ if (result.status === "unchanged") {
5798
+ return `Already formatted: ${filePath}`;
5799
+ }
5800
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
5801
+ }
5802
+
5342
5803
  // ../lsp-core/src/tools/install-decision.ts
5343
5804
  async function executeLspInstallDecision(params) {
5344
5805
  const serverId = requireString(params, "server_id");
@@ -5367,7 +5828,7 @@ async function executeLspGotoDefinition(params, signal) {
5367
5828
  const line = requireNumber(params, "line");
5368
5829
  const character = requireNumber(params, "character");
5369
5830
  try {
5370
- const result = await withLspClient(filePath, async (client) => client.definition(filePath, line, character, signal), "definition", clientOptions(signal));
5831
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
5371
5832
  const locations = !result ? [] : Array.isArray(result) ? result : [result];
5372
5833
  const details = { filePath, line, character, locations };
5373
5834
  if (locations.length === 0)
@@ -5392,7 +5853,7 @@ async function executeLspFindReferences(params, signal) {
5392
5853
  const character = requireNumber(params, "character");
5393
5854
  const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
5394
5855
  try {
5395
- const result = await withLspClient(filePath, async (client) => client.references(filePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5856
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5396
5857
  const references = Array.isArray(result) ? result : [];
5397
5858
  const total = references.length;
5398
5859
  const truncated = total > DEFAULT_MAX_REFERENCES;
@@ -5434,7 +5895,7 @@ async function executeLspPrepareRename(params, signal) {
5434
5895
  const line = requireNumber(params, "line");
5435
5896
  const character = requireNumber(params, "character");
5436
5897
  try {
5437
- const result = await withLspClient(filePath, async (client) => client.prepareRename(filePath, line, character, signal), "prepareRename", clientOptions(signal));
5898
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
5438
5899
  const details = { filePath, line, character, result };
5439
5900
  return text(formatPrepareRenameResult(result), details);
5440
5901
  } catch (error) {
@@ -5455,7 +5916,7 @@ async function executeLspRename(params, signal) {
5455
5916
  const character = requireNumber(params, "character");
5456
5917
  const newName = requireString(params, "newName");
5457
5918
  try {
5458
- const result = await withLspClient(filePath, async (client) => client.rename(filePath, line, character, newName, signal), "rename", clientOptions(signal));
5919
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
5459
5920
  const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
5460
5921
  return text(formatApplyResult(result.apply), details, !result.apply.success);
5461
5922
  } catch (error) {
@@ -5535,7 +5996,7 @@ async function executeLspSymbols(params, signal) {
5535
5996
  const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
5536
5997
  return formatSymbolsResult(filePath, scope, symbols2, limit, query);
5537
5998
  }
5538
- const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(filePath, signal), "documentSymbols", clientOptions(signal));
5999
+ const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
5539
6000
  return formatSymbolsResult(filePath, scope, symbols, limit);
5540
6001
  } catch (error) {
5541
6002
  const query = optionalString(params, "query");
@@ -5671,6 +6132,16 @@ var LSP_MCP_TOOLS = [
5671
6132
  }, ["filePath", "line", "character", "newName"]),
5672
6133
  execute: executeLspRename
5673
6134
  },
6135
+ {
6136
+ name: "format",
6137
+ aliases: ["lsp_format"],
6138
+ title: "LSP Format",
6139
+ description: "Format a source file with its language server and write the returned edits to disk.",
6140
+ inputSchema: objectSchema({
6141
+ filePath: { type: "string", description: "Source file path to format." }
6142
+ }, ["filePath"]),
6143
+ execute: executeLspFormat
6144
+ },
5674
6145
  {
5675
6146
  name: "install_decision",
5676
6147
  aliases: ["lsp_install_decision"],
@@ -5771,7 +6242,10 @@ function requestedProtocolVersion(params) {
5771
6242
  var CONTEXT_KEY = "_context";
5772
6243
 
5773
6244
  class InvalidDaemonRequestError extends Error {
5774
- name = "InvalidDaemonRequestError";
6245
+ constructor() {
6246
+ super(...arguments);
6247
+ this.name = "InvalidDaemonRequestError";
6248
+ }
5775
6249
  }
5776
6250
  function extractRequestContext(raw) {
5777
6251
  if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
@@ -5887,14 +6361,17 @@ async function callToolViaDaemon(name, args, options) {
5887
6361
  function callDiagnosticsViaDaemon(filePath, options) {
5888
6362
  return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
5889
6363
  }
6364
+ function callFormatViaDaemon(filePath, options) {
6365
+ return callToolViaDaemon("format", { filePath }, options);
6366
+ }
5890
6367
  function currentRequestContext(env = process.env) {
5891
6368
  const cwd = process.cwd();
5892
6369
  const home = env["HOME"] ?? homedir3();
5893
6370
  return parseLspRequestContext({
5894
6371
  cwd,
5895
- projectConfigPaths: [join7(cwd, ".codex", "lsp-client.json")],
5896
- userConfigPath: join7(home, ".codex", "lsp-client.json"),
5897
- installDecisionsPath: join7(home, ".codex", "lsp-install-decisions.json"),
6372
+ projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
6373
+ userConfigPath: join8(home, ".codex", "lsp-client.json"),
6374
+ installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
5898
6375
  capabilities: { installDecisionTool: true }
5899
6376
  });
5900
6377
  }
@@ -5909,7 +6386,7 @@ function withContext(args, context) {
5909
6386
  function ensureDaemonAvailable(paths, ensure, signal) {
5910
6387
  if (!signal)
5911
6388
  return ensure(paths);
5912
- return new Promise((resolve9, reject) => {
6389
+ return new Promise((resolve10, reject) => {
5913
6390
  let settled = false;
5914
6391
  const finish = (run) => {
5915
6392
  if (settled)
@@ -5924,11 +6401,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
5924
6401
  return;
5925
6402
  }
5926
6403
  signal.addEventListener("abort", onAbort, { once: true });
5927
- Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve9()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
6404
+ Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
5928
6405
  });
5929
6406
  }
5930
6407
  function sendToolCall(paths, token, name, args, options) {
5931
- return new Promise((resolve9, reject) => {
6408
+ return new Promise((resolve10, reject) => {
5932
6409
  const socket = connect(paths.socket);
5933
6410
  const requestId = allocateProxyRequestId();
5934
6411
  let settled = false;
@@ -5981,7 +6458,7 @@ function sendToolCall(paths, token, name, args, options) {
5981
6458
  }
5982
6459
  const result = toToolResult(message, requestId);
5983
6460
  if (result)
5984
- finish(() => resolve9(result));
6461
+ finish(() => resolve10(result));
5985
6462
  else
5986
6463
  finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
5987
6464
  });
@@ -6027,18 +6504,15 @@ function isRetryableTool(name) {
6027
6504
  }
6028
6505
 
6029
6506
  // src/client.ts
6030
- import { statSync as statSync5 } from "node:fs";
6031
- import { isAbsolute as isAbsolute5 } from "node:path";
6032
6507
  var OMO_LSP_DAEMON_DIR2 = "OMO_LSP_DAEMON_DIR";
6033
6508
  var OMO_LSP_DAEMON_CLI2 = "OMO_LSP_DAEMON_CLI";
6034
6509
  var OMO_LSP_DAEMON_VERSION2 = "OMO_LSP_DAEMON_VERSION";
6035
6510
  var DAEMON_VERSION_PATTERN2 = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
6036
6511
 
6037
6512
  class InvalidRuntimeOverrideError2 extends Error {
6038
- code = "invalid_runtime_override";
6039
- reason;
6040
6513
  constructor(reason, message) {
6041
6514
  super(message);
6515
+ this.code = "invalid_runtime_override";
6042
6516
  this.name = "InvalidRuntimeOverrideError";
6043
6517
  this.reason = reason;
6044
6518
  }
@@ -6058,12 +6532,12 @@ function resolveDaemonRuntime2(env, defaults) {
6058
6532
  throw new InvalidRuntimeOverrideError2("paired_values_required", `${OMO_LSP_DAEMON_CLI2} and ${OMO_LSP_DAEMON_VERSION2} must be set together`);
6059
6533
  }
6060
6534
  if (!hasCliOverride || !hasVersionOverride) {
6061
- if (!isAbsolute5(defaults.cliPath)) {
6535
+ if (!isAbsolute6(defaults.cliPath)) {
6062
6536
  throw new InvalidRuntimeOverrideError2("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
6063
6537
  }
6064
6538
  return { cliPath: defaults.cliPath, version: validateDaemonVersion2(defaults.version) };
6065
6539
  }
6066
- if (!isAbsolute5(cliOverride)) {
6540
+ if (!isAbsolute6(cliOverride)) {
6067
6541
  throw new InvalidRuntimeOverrideError2("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI2} must be an absolute path to an existing regular file`);
6068
6542
  }
6069
6543
  const stat = statSync5(cliOverride, { throwIfNoEntry: false });
@@ -6081,17 +6555,21 @@ function callToolViaDaemon2(name, args, options) {
6081
6555
  function callDiagnosticsViaDaemon2(filePath, options) {
6082
6556
  return callDiagnosticsViaDaemon(filePath, options);
6083
6557
  }
6558
+ function callFormatViaDaemon2(filePath, options) {
6559
+ return callFormatViaDaemon(filePath, options);
6560
+ }
6084
6561
  function currentRequestContext2(env = process.env) {
6085
6562
  return currentRequestContext(env);
6086
6563
  }
6087
6564
  export {
6088
- validateDaemonVersion2 as validateDaemonVersion,
6089
- resolveDaemonRuntime2 as resolveDaemonRuntime,
6090
- currentRequestContext2 as currentRequestContext,
6091
- callToolViaDaemon2 as callToolViaDaemon,
6092
- callDiagnosticsViaDaemon2 as callDiagnosticsViaDaemon,
6093
- OMO_LSP_DAEMON_VERSION2 as OMO_LSP_DAEMON_VERSION,
6094
- OMO_LSP_DAEMON_DIR2 as OMO_LSP_DAEMON_DIR,
6565
+ InvalidRuntimeOverrideError2 as InvalidRuntimeOverrideError,
6095
6566
  OMO_LSP_DAEMON_CLI2 as OMO_LSP_DAEMON_CLI,
6096
- InvalidRuntimeOverrideError2 as InvalidRuntimeOverrideError
6567
+ OMO_LSP_DAEMON_DIR2 as OMO_LSP_DAEMON_DIR,
6568
+ OMO_LSP_DAEMON_VERSION2 as OMO_LSP_DAEMON_VERSION,
6569
+ callDiagnosticsViaDaemon2 as callDiagnosticsViaDaemon,
6570
+ callFormatViaDaemon2 as callFormatViaDaemon,
6571
+ callToolViaDaemon2 as callToolViaDaemon,
6572
+ currentRequestContext2 as currentRequestContext,
6573
+ resolveDaemonRuntime2 as resolveDaemonRuntime,
6574
+ validateDaemonVersion2 as validateDaemonVersion
6097
6575
  };