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

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 (538) 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 +66932 -64746
  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 +66795 -64586
  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 +793 -323
  26. package/packages/lsp-daemon/dist/client.d.ts +10 -0
  27. package/packages/lsp-daemon/dist/client.js +753 -280
  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 +757 -289
  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 +712 -244
  36. package/packages/lsp-tools-mcp/dist/lsp/manager.js +248 -119
  37. package/packages/lsp-tools-mcp/dist/mcp.js +714 -246
  38. package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
  39. package/packages/lsp-tools-mcp/dist/tools.js +718 -254
  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 +741 -294
  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 +3 -2
  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 +36 -13
  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/coding-agent-sessions/AGENTS.md +62 -0
  296. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
  297. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  298. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
  299. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  300. package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
  301. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
  302. package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
  303. package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
  304. package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
  305. package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
  306. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  307. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  308. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -0
  309. package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
  310. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
  311. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
  312. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
  313. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
  314. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
  315. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
  316. package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
  317. package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  318. package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
  319. package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
  320. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +11 -7
  321. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
  322. package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
  323. package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
  324. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
  325. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  326. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  327. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  328. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
  329. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
  330. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +13 -13
  331. package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +1 -1
  332. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +4 -4
  333. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  334. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -0
  335. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  336. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
  337. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  338. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  339. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +15 -3
  340. package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +19 -26
  341. package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
  342. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -2
  343. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
  344. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +22 -1
  345. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -7
  346. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +31 -7
  347. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
  348. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +5 -5
  349. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +4 -2
  350. package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
  351. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +3 -2
  352. package/packages/omo-codex/plugin/test/AGENTS.md +47 -0
  353. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
  354. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +9 -48
  355. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +2 -3
  356. package/packages/omo-codex/plugin/test/aggregate-mcp.test.mjs +2 -7
  357. package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
  358. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
  359. package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
  360. package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
  361. package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -27
  362. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +0 -31
  363. package/packages/omo-codex/plugin/test/canonical-ultrawork-directive.test.mjs +53 -0
  364. package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +2 -2
  365. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +1 -51
  366. package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +2 -2
  367. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +4 -5
  368. package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
  369. package/packages/omo-codex/plugin/test/mcp-research-servers.test.mjs +1 -3
  370. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
  371. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
  372. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
  373. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +23 -13
  374. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +14 -119
  375. package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
  376. package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
  377. package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
  378. package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
  379. package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
  380. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +5 -5
  381. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
  382. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2817 -913
  383. package/packages/{omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md → prompts-core/prompts/ultrawork/codex.md} +15 -10
  384. package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
  385. package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
  386. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
  387. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  388. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
  389. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  390. package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
  391. package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
  392. package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
  393. package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
  394. package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
  395. package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
  396. package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  397. package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  398. package/packages/shared-skills/skills/debugging/SKILL.md +2 -0
  399. package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
  400. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
  401. package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
  402. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
  403. package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
  404. package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
  405. package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
  406. package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
  407. package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
  408. package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  409. package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
  410. package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
  411. package/packages/shared-skills/skills/frontend/SKILL.md +11 -7
  412. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
  413. package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
  414. package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
  415. package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
  416. package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  417. package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  418. package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  419. package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
  420. package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
  421. package/packages/shared-skills/skills/init-deep/SKILL.md +13 -13
  422. package/packages/shared-skills/skills/review-work/SKILL.md +3 -3
  423. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  424. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -0
  425. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  426. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
  427. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  428. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  429. package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +17 -16
  430. package/packages/shared-skills/skills/ulw-plan/SKILL.md +6 -7
  431. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
  432. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
  433. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
  434. package/packages/shared-skills/skills/ulw-research/SKILL.md +4 -2
  435. package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
  436. package/packages/shared-skills/skills/visual-qa/SKILL.md +3 -2
  437. package/script/qa/web-terminal-visual-qa.mjs +2 -0
  438. package/script/qa/xterm-live-terminal.mjs +18 -2
  439. package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts +0 -1
  440. package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts +0 -1
  441. package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts +0 -1
  442. package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.d.ts +0 -1
  443. package/packages/lsp-tools-mcp/dist/missing-dependency-result.d.ts +0 -1
  444. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +0 -58
  445. package/packages/omo-codex/plugin/components/codegraph/NODE-RUNTIME-LICENSES.md +0 -2951
  446. package/packages/omo-codex/plugin/components/codegraph/NOTICE +0 -16
  447. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +0 -12136
  448. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +0 -9734
  449. package/packages/omo-codex/plugin/components/codegraph/package.json +0 -33
  450. package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +0 -29
  451. package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +0 -79
  452. package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +0 -33
  453. package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +0 -25
  454. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +0 -131
  455. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +0 -258
  456. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +0 -309
  457. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +0 -80
  458. package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +0 -34
  459. package/packages/omo-codex/plugin/components/codegraph/src/serve-invocation.ts +0 -29
  460. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +0 -263
  461. package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +0 -106
  462. package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +0 -145
  463. package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +0 -21
  464. package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +0 -139
  465. package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +0 -15
  466. package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +0 -32
  467. package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +0 -109
  468. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +0 -148
  469. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +0 -175
  470. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +0 -81
  471. package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +0 -34
  472. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +0 -112
  473. package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +0 -26
  474. package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +0 -160
  475. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +0 -50
  476. package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +0 -29
  477. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +0 -320
  478. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +0 -172
  479. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +0 -91
  480. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +0 -100
  481. package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +0 -76
  482. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +0 -133
  483. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +0 -245
  484. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +0 -69
  485. package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +0 -43
  486. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +0 -147
  487. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +0 -175
  488. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +0 -385
  489. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +0 -206
  490. package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +0 -58
  491. package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +0 -104
  492. package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +0 -65
  493. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-availability.test.ts +0 -106
  494. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +0 -116
  495. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +0 -258
  496. package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +0 -56
  497. package/packages/omo-codex/plugin/components/codegraph/tsconfig.build.json +0 -13
  498. package/packages/omo-codex/plugin/components/codegraph/tsconfig.json +0 -25
  499. package/packages/omo-codex/plugin/components/start-work-continuation/LICENSE +0 -21
  500. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
  501. package/packages/omo-codex/plugin/components/ultrawork/directive.md +0 -471
  502. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +0 -18
  503. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +0 -17
  504. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
  505. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
  506. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/editor.mjs +0 -125
  507. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/jsonc.mjs +0 -43
  508. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/scaffold.mjs +0 -29
  509. package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +0 -121
  510. package/packages/omo-codex/plugin/skills/data-scientist/references/common-scenarios.md +0 -176
  511. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-templates.md +0 -197
  512. package/packages/omo-codex/plugin/skills/data-scientist/references/integration-patterns.md +0 -153
  513. package/packages/omo-codex/plugin/skills/data-scientist/references/performance-benchmarks.md +0 -37
  514. package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
  515. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
  516. package/packages/omo-codex/plugin/test/component-codegraph-mcp-smoke.test.mjs +0 -76
  517. package/packages/omo-codex/plugin/test/migrate-omo-sot.test.mjs +0 -179
  518. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
  519. package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
  520. package/packages/shared-skills/skills/data-scientist/references/common-scenarios.md +0 -176
  521. package/packages/shared-skills/skills/data-scientist/references/execution-templates.md +0 -197
  522. package/packages/shared-skills/skills/data-scientist/references/integration-patterns.md +0 -153
  523. package/packages/shared-skills/skills/data-scientist/references/performance-benchmarks.md +0 -37
  524. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/.gitattributes +0 -0
  525. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/CHANGELOG.md +0 -0
  526. /package/packages/omo-codex/plugin/components/{codegraph → ulw-execute-continuation}/LICENSE +0 -0
  527. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/plan-checklist.ts +0 -0
  528. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/types.ts +0 -0
  529. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
  530. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
  531. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
  532. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
  533. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
  534. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
  535. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
  536. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
  537. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
  538. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
@@ -1,6 +1,6 @@
1
1
  // ../lsp-core/src/lsp/client-wrapper.ts
2
- import { existsSync as existsSync9, statSync as statSync3 } from "node:fs";
3
- import { dirname as dirname6, join as join4, resolve as resolve7 } from "node:path";
2
+ import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
3
+ import { basename as basename3, dirname as dirname8, join as join5, resolve as resolve8 } from "node:path";
4
4
 
5
5
  // ../lsp-core/src/request-context.ts
6
6
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -9,18 +9,17 @@ import { homedir } from "node:os";
9
9
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
10
10
 
11
11
  class LspRequestContextParseError extends Error {
12
- code;
13
- name = "LspRequestContextParseError";
14
12
  constructor(code, message) {
15
13
  super(message);
16
14
  this.code = code;
15
+ this.name = "LspRequestContextParseError";
17
16
  }
18
17
  }
19
18
 
20
19
  class LspRequestContextUnavailableError extends Error {
21
- name = "LspRequestContextUnavailableError";
22
20
  constructor() {
23
21
  super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
22
+ this.name = "LspRequestContextUnavailableError";
24
23
  }
25
24
  }
26
25
  var storage = new AsyncLocalStorage;
@@ -50,7 +49,7 @@ function contextEnv(key) {
50
49
  }
51
50
  function createStandaloneMcpRequestContext(input = {}) {
52
51
  const env = input.env ?? process.env;
53
- const cwd = canonicalCwd(input.cwd ?? process.cwd());
52
+ const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
54
53
  const home = input.homeDir ?? homedir();
55
54
  const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
56
55
  const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
@@ -193,22 +192,15 @@ function effectiveExtension(filePath) {
193
192
 
194
193
  // ../lsp-core/src/lsp/errors.ts
195
194
  class LspConnectionClosedError extends Error {
196
- serverId;
197
- root;
198
- name = "LspConnectionClosedError";
199
195
  constructor(serverId, root, message) {
200
196
  super(message ?? `LSP connection closed for ${serverId} at ${root}`);
201
197
  this.serverId = serverId;
202
198
  this.root = root;
199
+ this.name = "LspConnectionClosedError";
203
200
  }
204
201
  }
205
202
 
206
203
  class LspProcessExitedError extends Error {
207
- serverId;
208
- root;
209
- exitCode;
210
- stderrTail;
211
- name = "LspProcessExitedError";
212
204
  constructor(serverId, root, exitCode, stderrTail) {
213
205
  const stderrSuffix = stderrTail ? `
214
206
  stderr tail: ${stderrTail}` : "";
@@ -217,46 +209,59 @@ stderr tail: ${stderrTail}` : "";
217
209
  this.root = root;
218
210
  this.exitCode = exitCode;
219
211
  this.stderrTail = stderrTail;
212
+ this.name = "LspProcessExitedError";
220
213
  }
221
214
  }
222
215
 
223
216
  class LspRequestTimeoutError extends Error {
224
- method;
225
- stderrTail;
226
- name = "LspRequestTimeoutError";
227
217
  constructor(method, stderrTail) {
228
218
  const stderrSuffix = stderrTail ? `
229
219
  recent stderr: ${stderrTail}` : "";
230
220
  super(`LSP request timeout (method: ${method})${stderrSuffix}`);
231
221
  this.method = method;
232
222
  this.stderrTail = stderrTail;
223
+ this.name = "LspRequestTimeoutError";
233
224
  }
234
225
  }
235
226
 
236
227
  class LspInvalidPathError extends Error {
237
- name = "LspInvalidPathError";
228
+ constructor() {
229
+ super(...arguments);
230
+ this.name = "LspInvalidPathError";
231
+ }
238
232
  }
239
233
 
240
234
  class LspServerLookupError extends Error {
241
- lookup;
242
- name = "LspServerLookupError";
243
235
  constructor(message, lookup) {
244
236
  super(message);
245
237
  this.lookup = lookup;
238
+ this.name = "LspServerLookupError";
246
239
  }
247
240
  }
248
241
 
249
242
  class LspServerInitializingError extends Error {
250
- originalError;
251
- name = "LspServerInitializingError";
252
243
  constructor(originalError) {
253
244
  super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
254
245
  this.originalError = originalError;
246
+ this.name = "LspServerInitializingError";
255
247
  }
256
248
  }
257
249
 
258
250
  class LspProcessSpawnError extends Error {
259
- name = "LspProcessSpawnError";
251
+ constructor() {
252
+ super(...arguments);
253
+ this.name = "LspProcessSpawnError";
254
+ }
255
+ }
256
+
257
+ class LspClientRespawnBudgetExceededError extends Error {
258
+ constructor(serverId, root, retryLimit) {
259
+ super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
260
+ this.serverId = serverId;
261
+ this.root = root;
262
+ this.retryLimit = retryLimit;
263
+ this.name = "LspClientRespawnBudgetExceededError";
264
+ }
260
265
  }
261
266
  function isLspDeadConnectionError(err) {
262
267
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
@@ -279,6 +284,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
279
284
  // ../lsp-core/src/lsp/connection.ts
280
285
  import { pathToFileURL } from "node:url";
281
286
 
287
+ // ../lsp-core/src/lsp/timer-provider.ts
288
+ var realTimerProvider = {
289
+ now: () => Date.now(),
290
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
291
+ clearTimeout: (handle) => clearTimeout(handle)
292
+ };
293
+
282
294
  // ../lsp-core/src/lsp/constants.ts
283
295
  var DEFAULT_MAX_REFERENCES = 200;
284
296
  var DEFAULT_MAX_SYMBOLS = 200;
@@ -287,9 +299,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
287
299
  var REQUEST_TIMEOUT_MS = 15000;
288
300
  var INIT_TIMEOUT_MS = 60000;
289
301
  var IDLE_TIMEOUT_MS = 5 * 60000;
302
+ var MAX_RESIDENT_CLIENTS = 6;
290
303
  var REAPER_INTERVAL_MS = 60000;
291
304
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
292
305
  var STOP_SIGKILL_GRACE_MS = 1000;
306
+ var CLIENT_RESPAWN_RETRY_LIMIT = 2;
307
+ var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
293
308
 
294
309
  // ../lsp-core/src/lsp/json-rpc-connection.ts
295
310
  var HEADER_SEPARATOR = `\r
@@ -301,20 +316,31 @@ var METHOD_NOT_FOUND = -32601;
301
316
  var INTERNAL_ERROR = -32603;
302
317
 
303
318
  class JsonRpcConnection {
304
- reader;
305
- writer;
306
- pendingRequests = new Map;
307
- notificationHandlers = new Map;
308
- requestHandlers = new Map;
309
- closeHandlers = [];
310
- errorHandlers = [];
311
- inputBuffer = Buffer.alloc(0);
312
- nextRequestId = 1;
313
- listening = false;
314
- disposed = false;
315
319
  constructor(reader, writer) {
316
320
  this.reader = reader;
317
321
  this.writer = writer;
322
+ this.pendingRequests = new Map;
323
+ this.notificationHandlers = new Map;
324
+ this.requestHandlers = new Map;
325
+ this.closeHandlers = [];
326
+ this.errorHandlers = [];
327
+ this.inputBuffer = Buffer.alloc(0);
328
+ this.nextRequestId = 1;
329
+ this.listening = false;
330
+ this.disposed = false;
331
+ this.handleData = (chunk) => {
332
+ const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
333
+ this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
334
+ this.drainInputBuffer();
335
+ };
336
+ this.handleClose = () => {
337
+ for (const handler of this.closeHandlers) {
338
+ handler();
339
+ }
340
+ };
341
+ this.handleStreamError = (error) => {
342
+ this.emitError(error);
343
+ };
318
344
  }
319
345
  listen() {
320
346
  if (this.listening)
@@ -435,19 +461,6 @@ class JsonRpcConnection {
435
461
  this.notificationHandlers.clear();
436
462
  this.requestHandlers.clear();
437
463
  }
438
- handleData = (chunk) => {
439
- const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
440
- this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
441
- this.drainInputBuffer();
442
- };
443
- handleClose = () => {
444
- for (const handler of this.closeHandlers) {
445
- handler();
446
- }
447
- };
448
- handleStreamError = (error) => {
449
- this.emitError(error);
450
- };
451
464
  drainInputBuffer() {
452
465
  while (true) {
453
466
  const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR);
@@ -795,33 +808,29 @@ function isPosition(value) {
795
808
 
796
809
  // ../lsp-core/src/lsp/transport.ts
797
810
  class LspClientNotStartedError extends Error {
798
- serverId;
799
- root;
800
- name = "LspClientNotStartedError";
801
811
  constructor(serverId, root) {
802
812
  super("LSP client not started");
803
813
  this.serverId = serverId;
804
814
  this.root = root;
815
+ this.name = "LspClientNotStartedError";
805
816
  }
806
817
  }
807
818
 
808
819
  class LspClientTransport {
809
- root;
810
- server;
811
- proc = null;
812
- connection = null;
813
- stderrBuffer = [];
814
- processExited = false;
815
- diagnosticsStore = new Map;
816
- requestTimeoutMs;
817
- initializeTimeoutMs;
818
- workspaceApplyEditHandler = null;
819
- diagnosticPullSupported = false;
820
820
  constructor(root, server, timeouts = {}) {
821
821
  this.root = root;
822
822
  this.server = server;
823
+ this.proc = null;
824
+ this.connection = null;
825
+ this.stderrBuffer = [];
826
+ this.processExited = false;
827
+ this.diagnosticsStore = new Map;
828
+ this.workspaceApplyEditHandler = null;
829
+ this.diagnosticPullSupported = false;
830
+ this.documentFormattingSupported = false;
823
831
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
824
832
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
833
+ this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
825
834
  }
826
835
  pid() {
827
836
  return this.proc?.pid;
@@ -841,6 +850,12 @@ class LspClientTransport {
841
850
  isDiagnosticPullSupported() {
842
851
  return this.diagnosticPullSupported;
843
852
  }
853
+ setDocumentFormattingSupported(supported) {
854
+ this.documentFormattingSupported = supported;
855
+ }
856
+ isDocumentFormattingSupported() {
857
+ return this.documentFormattingSupported;
858
+ }
844
859
  handlePublishDiagnostics(params) {
845
860
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
846
861
  }
@@ -916,7 +931,7 @@ class LspClientTransport {
916
931
  const options = args[1];
917
932
  const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
918
933
  const timeoutController = new AbortController;
919
- const timeoutHandle = setTimeout(() => {
934
+ const timeoutHandle = this.timerProvider.setTimeout(() => {
920
935
  const stderrTail = this.stderrBuffer.slice(-5).join(`
921
936
  `);
922
937
  timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
@@ -935,7 +950,7 @@ class LspClientTransport {
935
950
  }
936
951
  throw error;
937
952
  } finally {
938
- clearTimeout(timeoutHandle);
953
+ this.timerProvider.clearTimeout(timeoutHandle);
939
954
  combinedSignal.dispose();
940
955
  }
941
956
  }
@@ -1054,6 +1069,14 @@ function supportsDiagnosticPull(capabilities) {
1054
1069
  return false;
1055
1070
  return Object.hasOwn(capabilities, "diagnosticProvider");
1056
1071
  }
1072
+ function supportsDocumentFormatting(capabilities) {
1073
+ if (capabilities === undefined)
1074
+ return false;
1075
+ const provider = capabilities.documentFormattingProvider;
1076
+ if (provider === undefined || provider === null || provider === false)
1077
+ return false;
1078
+ return provider === true || typeof provider === "object";
1079
+ }
1057
1080
 
1058
1081
  class LspClientConnection extends LspClientTransport {
1059
1082
  async initialize() {
@@ -1070,6 +1093,7 @@ class LspClientConnection extends LspClientTransport {
1070
1093
  references: {},
1071
1094
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
1072
1095
  publishDiagnostics: {},
1096
+ formatting: { dynamicRegistration: false },
1073
1097
  rename: {
1074
1098
  prepareSupport: true,
1075
1099
  prepareSupportDefaultBehavior: 1
@@ -1111,6 +1135,7 @@ class LspClientConnection extends LspClientTransport {
1111
1135
  initializationOptions: this.server.initialization
1112
1136
  }, { timeoutMs: this.initializeTimeoutMs });
1113
1137
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
1138
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
1114
1139
  await this.sendNotification("initialized", {});
1115
1140
  await this.sendNotification("workspace/didChangeConfiguration", {
1116
1141
  settings: { json: { validate: { enable: true } } }
@@ -1306,6 +1331,17 @@ function canonicalPath(filePath) {
1306
1331
  return absolute;
1307
1332
  }
1308
1333
  }
1334
+ function normalizeDocumentUri(uri) {
1335
+ let decoded = uri;
1336
+ try {
1337
+ decoded = decodeURIComponent(uri);
1338
+ } catch {
1339
+ decoded = uri;
1340
+ }
1341
+ if (process.platform !== "win32")
1342
+ return decoded;
1343
+ return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
1344
+ }
1309
1345
  function isSameOrDescendant(candidate, parent) {
1310
1346
  const suffix = relative2(parent, candidate);
1311
1347
  return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
@@ -1316,17 +1352,18 @@ function movedPath(candidate, oldPath, newPath) {
1316
1352
  }
1317
1353
 
1318
1354
  class WorkspaceDocumentState {
1319
- sendNotification;
1320
- clearDiagnostics;
1321
- openDocuments = new Map;
1322
- openByUri = new Map;
1323
- openPromises = new Map;
1324
- now;
1325
- versionlessPublishQuiescenceMs;
1326
1355
  constructor(sendNotification, clearDiagnostics, options = {}) {
1327
1356
  this.sendNotification = sendNotification;
1328
1357
  this.clearDiagnostics = clearDiagnostics;
1329
- this.now = options.now ?? (() => Date.now());
1358
+ this.openDocuments = new Map;
1359
+ this.openByUri = new Map;
1360
+ this.openPromises = new Map;
1361
+ this.timerProvider = options.timerProvider ?? {
1362
+ now: options.now ?? (() => Date.now()),
1363
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
1364
+ clearTimeout: (handle) => clearTimeout(handle)
1365
+ };
1366
+ this.now = () => this.timerProvider.now();
1330
1367
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1331
1368
  }
1332
1369
  async openFile(filePath) {
@@ -1348,7 +1385,7 @@ class WorkspaceDocumentState {
1348
1385
  return this.openDocuments.get(canonicalPath(filePath))?.version;
1349
1386
  }
1350
1387
  getStoredDiagnostics(uri) {
1351
- const state = this.openByUri.get(uri);
1388
+ const state = this.openByUri.get(normalizeDocumentUri(uri));
1352
1389
  if (!state)
1353
1390
  return [];
1354
1391
  return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
@@ -1370,13 +1407,13 @@ class WorkspaceDocumentState {
1370
1407
  return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
1371
1408
  }
1372
1409
  getPullCache(snapshot) {
1373
- const state = this.openByUri.get(snapshot.uri);
1410
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1374
1411
  if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
1375
1412
  return null;
1376
1413
  return state.pullCache;
1377
1414
  }
1378
1415
  recordPullDiagnostics(snapshot, report) {
1379
- const state = this.openByUri.get(snapshot.uri);
1416
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1380
1417
  if (!state)
1381
1418
  return;
1382
1419
  state.pullCache = {
@@ -1386,7 +1423,7 @@ class WorkspaceDocumentState {
1386
1423
  };
1387
1424
  }
1388
1425
  recordPublishedDiagnostics(params) {
1389
- const state = this.openByUri.get(params.uri);
1426
+ const state = this.openByUri.get(normalizeDocumentUri(params.uri));
1390
1427
  if (!state)
1391
1428
  return;
1392
1429
  state.publishGeneration += 1;
@@ -1400,7 +1437,7 @@ class WorkspaceDocumentState {
1400
1437
  this.notifyWaiters(state);
1401
1438
  }
1402
1439
  resolvePushDiagnostics(snapshot) {
1403
- const state = this.openByUri.get(snapshot.uri);
1440
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1404
1441
  if (!state?.lastPublish)
1405
1442
  return { status: "missing" };
1406
1443
  const publish = state.lastPublish;
@@ -1414,7 +1451,7 @@ class WorkspaceDocumentState {
1414
1451
  return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
1415
1452
  }
1416
1453
  waitForDiagnosticsActivity(snapshot, timeoutMs) {
1417
- const state = this.openByUri.get(snapshot.uri);
1454
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1418
1455
  if (!state || timeoutMs <= 0)
1419
1456
  return Promise.resolve();
1420
1457
  return new Promise((resolveActivity) => {
@@ -1423,11 +1460,11 @@ class WorkspaceDocumentState {
1423
1460
  if (settled)
1424
1461
  return;
1425
1462
  settled = true;
1426
- clearTimeout(timer);
1463
+ this.timerProvider.clearTimeout(timer);
1427
1464
  state.waiters.delete(finish);
1428
1465
  resolveActivity();
1429
1466
  };
1430
- const timer = setTimeout(finish, timeoutMs);
1467
+ const timer = this.timerProvider.setTimeout(finish, timeoutMs);
1431
1468
  if (typeof timer.unref === "function")
1432
1469
  timer.unref();
1433
1470
  state.waiters.add(finish);
@@ -1535,7 +1572,7 @@ class WorkspaceDocumentState {
1535
1572
  waiters: new Set
1536
1573
  };
1537
1574
  this.openDocuments.set(path, state);
1538
- this.openByUri.set(state.uri, state);
1575
+ this.openByUri.set(normalizeDocumentUri(state.uri), state);
1539
1576
  this.notifyWaiters(state);
1540
1577
  await this.sendNotification("textDocument/didOpen", {
1541
1578
  textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
@@ -1560,7 +1597,7 @@ class WorkspaceDocumentState {
1560
1597
  }
1561
1598
  async closeDocument(state) {
1562
1599
  this.openDocuments.delete(state.path);
1563
- this.openByUri.delete(state.uri);
1600
+ this.openByUri.delete(normalizeDocumentUri(state.uri));
1564
1601
  this.clearDiagnostics(state.uri);
1565
1602
  this.notifyWaiters(state);
1566
1603
  await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
@@ -1589,13 +1626,11 @@ import { dirname as dirname2, isAbsolute as isAbsolute2, relative as relative3,
1589
1626
  import { fileURLToPath } from "node:url";
1590
1627
 
1591
1628
  class WorkspaceEditPathError extends Error {
1592
- path;
1593
- detail;
1594
- name = "WorkspaceEditPathError";
1595
1629
  constructor(path, detail) {
1596
1630
  super(`${detail}: ${path}`);
1597
1631
  this.path = path;
1598
1632
  this.detail = detail;
1633
+ this.name = "WorkspaceEditPathError";
1599
1634
  }
1600
1635
  }
1601
1636
  function isPathInsideWorkspace(filePath, workspaceRoot) {
@@ -1887,13 +1922,11 @@ function canonicalFingerprint(operations) {
1887
1922
 
1888
1923
  // ../lsp-core/src/lsp/workspace-edit-types.ts
1889
1924
  class WorkspaceEditValidationError extends Error {
1890
- changeIndex;
1891
- detail;
1892
- name = "WorkspaceEditValidationError";
1893
1925
  constructor(changeIndex, detail) {
1894
1926
  super(`change ${changeIndex}: ${detail}`);
1895
1927
  this.changeIndex = changeIndex;
1896
1928
  this.detail = detail;
1929
+ this.name = "WorkspaceEditValidationError";
1897
1930
  }
1898
1931
  }
1899
1932
 
@@ -2391,10 +2424,9 @@ function simulateDelete(operation, virtual) {
2391
2424
  import { existsSync as existsSync5, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
2392
2425
  import { dirname as dirname4, resolve as resolve5 } from "node:path";
2393
2426
  class WorkspaceSnapshotBuilder {
2394
- workspaceRoot;
2395
- snapshots = new Map;
2396
2427
  constructor(workspaceRoot) {
2397
2428
  this.workspaceRoot = workspaceRoot;
2429
+ this.snapshots = new Map;
2398
2430
  }
2399
2431
  build(operations) {
2400
2432
  this.add(this.workspaceRoot, false);
@@ -2438,8 +2470,10 @@ function snapshotOperations(operations, workspaceRoot) {
2438
2470
 
2439
2471
  // ../lsp-core/src/lsp/workspace-edit-plan.ts
2440
2472
  class PlanPathIndex {
2441
- firstChangeByPath = new Map;
2442
- reportedPathByCanonical = new Map;
2473
+ constructor() {
2474
+ this.firstChangeByPath = new Map;
2475
+ this.reportedPathByCanonical = new Map;
2476
+ }
2443
2477
  build(operations) {
2444
2478
  for (const operation of operations) {
2445
2479
  switch (operation.kind) {
@@ -2528,14 +2562,11 @@ function isRecord4(value) {
2528
2562
  }
2529
2563
 
2530
2564
  class WorkspaceMutationController {
2531
- workspaceRoot;
2532
- documents;
2533
- activeLease = null;
2534
- nextLeaseId = 1;
2535
- io;
2536
2565
  constructor(workspaceRoot, documents) {
2537
2566
  this.workspaceRoot = workspaceRoot;
2538
2567
  this.documents = documents;
2568
+ this.activeLease = null;
2569
+ this.nextLeaseId = 1;
2539
2570
  }
2540
2571
  setIo(io) {
2541
2572
  this.io = io;
@@ -2648,14 +2679,12 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
2648
2679
  var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
2649
2680
 
2650
2681
  class LspClient extends LspClientConnection {
2651
- diagnosticPullErrors = [];
2652
- documents;
2653
- workspaceMutations;
2654
- diagnosticsFreshnessTimeoutMs;
2655
2682
  constructor(root, server, options = {}) {
2656
2683
  super(root, server, options);
2684
+ this.diagnosticPullErrors = [];
2657
2685
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2658
2686
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2687
+ timerProvider: this.timerProvider,
2659
2688
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
2660
2689
  });
2661
2690
  this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
@@ -2708,6 +2737,18 @@ class LspClient extends LspClientConnection {
2708
2737
  textDocument: { uri: pathToFileURL3(absPath).href }
2709
2738
  }, options);
2710
2739
  }
2740
+ async formatDocument(filePath, options, signal) {
2741
+ if (!this.isDocumentFormattingSupported())
2742
+ return null;
2743
+ const absPath = this.resolveWorkspacePath(filePath);
2744
+ await this.openFile(absPath);
2745
+ const requestOptions = signal === undefined ? {} : { signal };
2746
+ const edits = await this.sendRequest("textDocument/formatting", {
2747
+ textDocument: { uri: pathToFileURL3(absPath).href },
2748
+ options
2749
+ }, requestOptions);
2750
+ return edits ?? [];
2751
+ }
2711
2752
  async workspaceSymbols(query, signal) {
2712
2753
  const options = signal === undefined ? {} : { signal };
2713
2754
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -2747,7 +2788,7 @@ class LspClient extends LspClientConnection {
2747
2788
  const absPath = this.resolveWorkspacePath(filePath);
2748
2789
  const uri = pathToFileURL3(absPath).href;
2749
2790
  await this.openFile(absPath);
2750
- const deadlineAt = Date.now() + this.diagnosticsFreshnessTimeoutMs;
2791
+ const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
2751
2792
  for (;; ) {
2752
2793
  signal?.throwIfAborted();
2753
2794
  const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
@@ -2760,7 +2801,7 @@ class LspClient extends LspClientConnection {
2760
2801
  if (!pushFallbackOnly) {
2761
2802
  const cached = this.documents.getPullCache(snapshot);
2762
2803
  try {
2763
- const remainingMs2 = deadlineAt - Date.now();
2804
+ const remainingMs2 = deadlineAt - this.timerProvider.now();
2764
2805
  if (remainingMs2 <= 0)
2765
2806
  return this.freshnessTimeout(absPath);
2766
2807
  const result = await this.sendRequest("textDocument/diagnostic", {
@@ -2795,7 +2836,7 @@ class LspClient extends LspClientConnection {
2795
2836
  }
2796
2837
  if (!pushFallbackOnly)
2797
2838
  continue;
2798
- const remainingMs = deadlineAt - Date.now();
2839
+ const remainingMs = deadlineAt - this.timerProvider.now();
2799
2840
  if (remainingMs <= 0) {
2800
2841
  if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
2801
2842
  const cached = this.documents.getPullCache(snapshot);
@@ -2953,18 +2994,16 @@ function awaitWithSignal(promise, signal) {
2953
2994
  }
2954
2995
 
2955
2996
  class LspManager {
2956
- clients = new Map;
2957
- reaperHandle = null;
2958
- signalDisposer = null;
2959
- disposed = false;
2960
- idleTimeoutMs;
2961
- initTimeoutMs;
2962
- reaperIntervalMs;
2963
- clientFactory;
2964
- now;
2965
2997
  constructor(options = {}) {
2998
+ this.clients = new Map;
2999
+ this.pendingStops = new Map;
3000
+ this.respawnBudgets = new Map;
3001
+ this.reaperHandle = null;
3002
+ this.signalDisposer = null;
3003
+ this.disposed = false;
2966
3004
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
2967
3005
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
3006
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
2968
3007
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
2969
3008
  this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
2970
3009
  this.now = options.now ?? (() => Date.now());
@@ -2984,24 +3023,79 @@ class LspManager {
2984
3023
  getKey(root, serverId) {
2985
3024
  return `${root}::${serverId}`;
2986
3025
  }
3026
+ tombstoneStop(key, client) {
3027
+ const stop = stopClientBestEffort(client);
3028
+ this.pendingStops.set(key, stop);
3029
+ stop.finally(() => {
3030
+ if (this.pendingStops.get(key) === stop) {
3031
+ this.pendingStops.delete(key);
3032
+ }
3033
+ });
3034
+ return stop;
3035
+ }
3036
+ recordDeadGeneration(key) {
3037
+ let budget = this.respawnBudgets.get(key);
3038
+ if (budget === undefined) {
3039
+ budget = { deadGenerations: 0, exhaustedAt: null };
3040
+ this.respawnBudgets.set(key, budget);
3041
+ }
3042
+ budget.deadGenerations += 1;
3043
+ }
3044
+ markHealthyGeneration(key) {
3045
+ this.respawnBudgets.delete(key);
3046
+ }
3047
+ ensureRespawnAllowed(key, root, serverId) {
3048
+ const budget = this.respawnBudgets.get(key);
3049
+ if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
3050
+ return;
3051
+ if (budget.exhaustedAt === null) {
3052
+ budget.exhaustedAt = this.now();
3053
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3054
+ }
3055
+ if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
3056
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3057
+ }
3058
+ budget.deadGenerations = 0;
3059
+ budget.exhaustedAt = null;
3060
+ }
2987
3061
  reapStale() {
2988
3062
  const t = this.now();
2989
3063
  for (const [key, managed] of this.clients) {
2990
3064
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
2991
- stopClientBestEffort(managed.client);
2992
3065
  this.clients.delete(key);
3066
+ this.tombstoneStop(key, managed.client);
2993
3067
  continue;
2994
3068
  }
2995
3069
  if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
2996
- stopClientBestEffort(managed.client);
2997
3070
  this.clients.delete(key);
3071
+ this.tombstoneStop(key, managed.client);
3072
+ }
3073
+ }
3074
+ }
3075
+ evictForAdmission() {
3076
+ while (this.clients.size >= this.maxResidentClients) {
3077
+ const victim = this.leastRecentlyUsedIdleClient();
3078
+ if (!victim)
3079
+ return;
3080
+ this.clients.delete(victim.key);
3081
+ this.tombstoneStop(victim.key, victim.managed.client);
3082
+ }
3083
+ }
3084
+ leastRecentlyUsedIdleClient() {
3085
+ let candidate = null;
3086
+ for (const [key, managed] of this.clients) {
3087
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
3088
+ continue;
3089
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
3090
+ candidate = { key, managed };
2998
3091
  }
2999
3092
  }
3093
+ return candidate;
3000
3094
  }
3001
3095
  async tryDeleteIfOrphaned(key, managed) {
3002
3096
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
3003
3097
  this.clients.delete(key);
3004
- await stopClientBestEffort(managed.client);
3098
+ await this.tombstoneStop(key, managed.client);
3005
3099
  }
3006
3100
  }
3007
3101
  async getClient(root, server, signal) {
@@ -3010,12 +3104,22 @@ class LspManager {
3010
3104
  }
3011
3105
  signal?.throwIfAborted();
3012
3106
  const key = this.getKey(root, server.id);
3107
+ for (;; ) {
3108
+ const pendingStop = this.pendingStops.get(key);
3109
+ if (pendingStop === undefined)
3110
+ break;
3111
+ await awaitWithSignal(pendingStop, signal);
3112
+ signal?.throwIfAborted();
3113
+ }
3114
+ if (this.disposed) {
3115
+ throw new Error("LspManager has been disposed");
3116
+ }
3013
3117
  let managed = this.clients.get(key);
3014
3118
  if (managed) {
3015
3119
  const t = this.now();
3016
3120
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3017
- await stopClientBestEffort(managed.client);
3018
3121
  this.clients.delete(key);
3122
+ await this.tombstoneStop(key, managed.client);
3019
3123
  managed = undefined;
3020
3124
  }
3021
3125
  }
@@ -3036,14 +3140,20 @@ class LspManager {
3036
3140
  signal.throwIfAborted();
3037
3141
  }
3038
3142
  if (!managed.client.isAlive()) {
3039
- await stopClientBestEffort(managed.client);
3040
- this.clients.delete(key);
3143
+ this.recordDeadGeneration(key);
3144
+ if (this.clients.get(key) === managed) {
3145
+ this.clients.delete(key);
3146
+ }
3147
+ await this.tombstoneStop(key, managed.client);
3041
3148
  return this.getClient(root, server, signal);
3042
3149
  }
3150
+ this.markHealthyGeneration(key);
3043
3151
  managed.refCount++;
3044
3152
  managed.lastUsedAt = this.now();
3045
3153
  return managed.client;
3046
3154
  }
3155
+ this.evictForAdmission();
3156
+ this.ensureRespawnAllowed(key, root, server.id);
3047
3157
  const client = this.clientFactory(root, server);
3048
3158
  const initStartedAt = this.now();
3049
3159
  const initPromise = (async () => {
@@ -3067,7 +3177,7 @@ class LspManager {
3067
3177
  if (this.clients.get(key) === newManaged) {
3068
3178
  this.clients.delete(key);
3069
3179
  }
3070
- await stopClientBestEffort(client);
3180
+ await this.tombstoneStop(key, client);
3071
3181
  throw err;
3072
3182
  }
3073
3183
  newManaged.pendingWaiters--;
@@ -3078,6 +3188,15 @@ class LspManager {
3078
3188
  await this.tryDeleteIfOrphaned(key, newManaged);
3079
3189
  signal.throwIfAborted();
3080
3190
  }
3191
+ if (!client.isAlive()) {
3192
+ this.recordDeadGeneration(key);
3193
+ if (this.clients.get(key) === newManaged) {
3194
+ this.clients.delete(key);
3195
+ }
3196
+ await this.tombstoneStop(key, client);
3197
+ return this.getClient(root, server, signal);
3198
+ }
3199
+ this.markHealthyGeneration(key);
3081
3200
  newManaged.refCount++;
3082
3201
  newManaged.lastUsedAt = this.now();
3083
3202
  return client;
@@ -3098,14 +3217,20 @@ class LspManager {
3098
3217
  if (client && managed.client !== client)
3099
3218
  return;
3100
3219
  this.clients.delete(key);
3101
- stopClientBestEffort(managed.client);
3220
+ this.tombstoneStop(key, managed.client);
3102
3221
  }
3103
3222
  warmupClient(root, server) {
3104
3223
  if (this.disposed)
3105
3224
  return;
3106
3225
  const key = this.getKey(root, server.id);
3107
- if (this.clients.has(key))
3226
+ if (this.clients.has(key) || this.pendingStops.has(key))
3227
+ return;
3228
+ this.evictForAdmission();
3229
+ try {
3230
+ this.ensureRespawnAllowed(key, root, server.id);
3231
+ } catch {
3108
3232
  return;
3233
+ }
3109
3234
  const client = this.clientFactory(root, server);
3110
3235
  const initStartedAt = this.now();
3111
3236
  const initPromise = (async () => {
@@ -3131,7 +3256,7 @@ class LspManager {
3131
3256
  if (this.clients.get(key) === managed) {
3132
3257
  this.clients.delete(key);
3133
3258
  }
3134
- stopClientBestEffort(client);
3259
+ this.tombstoneStop(key, client);
3135
3260
  });
3136
3261
  }
3137
3262
  isServerInitializing(root, serverId) {
@@ -3175,8 +3300,11 @@ class LspManager {
3175
3300
  for (const managed of this.clients.values()) {
3176
3301
  stopPromises.push(stopClientBestEffort(managed.client));
3177
3302
  }
3303
+ const tombstonedStops = [...this.pendingStops.values()];
3178
3304
  this.clients.clear();
3179
- await Promise.allSettled(stopPromises);
3305
+ this.respawnBudgets.clear();
3306
+ await Promise.allSettled([...stopPromises, ...tombstonedStops]);
3307
+ this.pendingStops.clear();
3180
3308
  }
3181
3309
  }
3182
3310
  var _defaultInstance = null;
@@ -3194,57 +3322,52 @@ async function disposeDefaultLspManager() {
3194
3322
  }
3195
3323
  }
3196
3324
 
3197
- // ../lsp-core/src/lsp/server-install-state.ts
3198
- import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3199
- import { dirname as dirname5 } from "node:path";
3200
- function getInstallDecisionsPath() {
3201
- return lspRequestContext().installDecisionsPath;
3202
- }
3203
- function loadInstallDecisions() {
3204
- const path = getInstallDecisionsPath();
3205
- if (!existsSync6(path))
3206
- return {};
3207
- try {
3208
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
3209
- return isInstallDecisions(parsed) ? parsed : {};
3210
- } catch {
3211
- return {};
3325
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3326
+ import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
3327
+ import { dirname as dirname5, join as join3 } from "node:path";
3328
+
3329
+ // ../lsp-core/src/lsp/workspace-markers.ts
3330
+ var GIT_WORKSPACE_MARKER = ".git";
3331
+ var PROJECT_WORKSPACE_MARKERS = [
3332
+ "package.json",
3333
+ "pyproject.toml",
3334
+ "Cargo.toml",
3335
+ "go.mod",
3336
+ "pom.xml",
3337
+ "build.gradle"
3338
+ ];
3339
+ var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
3340
+
3341
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3342
+ function findWorkspaceRootOutsideContext(directory) {
3343
+ const marked = nearestMarkedAncestor(directory);
3344
+ if (marked !== undefined)
3345
+ return marked;
3346
+ return realpathSync4(nearestExistingAncestor(directory));
3347
+ }
3348
+ function nearestMarkedAncestor(directory) {
3349
+ let current = directory;
3350
+ for (;; ) {
3351
+ if (existsSync6(current) && WORKSPACE_MARKERS.some((marker) => existsSync6(join3(current, marker)))) {
3352
+ return realpathSync4(current);
3353
+ }
3354
+ const parent = dirname5(current);
3355
+ if (parent === current)
3356
+ return;
3357
+ current = parent;
3212
3358
  }
3213
3359
  }
3214
- function loadInstallDecision(serverId) {
3215
- return loadInstallDecisions()[serverId];
3216
- }
3217
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3218
- const decisions = loadInstallDecisions();
3219
- decisions[serverId] = { decision, decidedAt };
3220
- writeInstallDecisions(decisions);
3221
- }
3222
- function isInstallDecision(value) {
3223
- return value === "declined" || value === "allowed";
3224
- }
3225
- function writeInstallDecisions(decisions) {
3226
- const path = getInstallDecisionsPath();
3227
- mkdirSync(dirname5(path), { recursive: true });
3228
- const tmpPath = `${path}.tmp`;
3229
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3230
- `, "utf8");
3231
- renameSync2(tmpPath, path);
3232
- }
3233
- function isInstallDecisions(value) {
3234
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3235
- }
3236
- function isInstallDecisionRecord(value) {
3237
- if (!isRecord5(value))
3238
- return false;
3239
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3240
- }
3241
- function isRecord5(value) {
3242
- return typeof value === "object" && value !== null && !Array.isArray(value);
3360
+ function nearestExistingAncestor(directory) {
3361
+ let current = directory;
3362
+ while (!existsSync6(current)) {
3363
+ const parent = dirname5(current);
3364
+ if (parent === current)
3365
+ return current;
3366
+ current = parent;
3367
+ }
3368
+ return current;
3243
3369
  }
3244
3370
 
3245
- // ../lsp-core/src/lsp/config-loader.ts
3246
- import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
3247
-
3248
3371
  // ../lsp-core/src/lsp/server-definitions.ts
3249
3372
  var LSP_INSTALL_HINTS = {
3250
3373
  typescript: "npm install -g typescript-language-server typescript",
@@ -3290,6 +3413,26 @@ var LSP_INSTALL_HINTS = {
3290
3413
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
3291
3414
  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"
3292
3415
  };
3416
+ var LSP_LOCAL_INSTALL_HINTS = {
3417
+ typescript: "bun add -d typescript-language-server typescript",
3418
+ vue: "bun add -d @vue/language-server",
3419
+ eslint: "bun add -d vscode-langservers-extracted",
3420
+ oxlint: "bun add -d oxlint",
3421
+ biome: "bun add -d @biomejs/biome",
3422
+ svelte: "bun add -d svelte-language-server",
3423
+ astro: "bun add -d @astrojs/language-server",
3424
+ bash: "bun add -d bash-language-server",
3425
+ "bash-ls": "bun add -d bash-language-server",
3426
+ "yaml-ls": "bun add -d yaml-language-server",
3427
+ php: "bun add -d intelephense",
3428
+ prisma: "bun add -d prisma",
3429
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
3430
+ pyright: "uv add --dev pyright",
3431
+ basedpyright: "uv add --dev basedpyright",
3432
+ ruff: "uv add --dev ruff",
3433
+ ty: "uv add --dev ty",
3434
+ "ruby-lsp": "bundle add ruby-lsp --group development"
3435
+ };
3293
3436
  var BUILTIN_SERVERS = {
3294
3437
  typescript: {
3295
3438
  command: ["typescript-language-server", "--stdio"],
@@ -3392,7 +3535,56 @@ var BUILTIN_SERVERS = {
3392
3535
  }
3393
3536
  };
3394
3537
 
3538
+ // ../lsp-core/src/lsp/server-install-state.ts
3539
+ import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3540
+ import { dirname as dirname6 } from "node:path";
3541
+ function getInstallDecisionsPath() {
3542
+ return lspRequestContext().installDecisionsPath;
3543
+ }
3544
+ function loadInstallDecisions() {
3545
+ const path = getInstallDecisionsPath();
3546
+ if (!existsSync7(path))
3547
+ return {};
3548
+ try {
3549
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
3550
+ return isInstallDecisions(parsed) ? parsed : {};
3551
+ } catch {
3552
+ return {};
3553
+ }
3554
+ }
3555
+ function loadInstallDecision(serverId) {
3556
+ return loadInstallDecisions()[serverId];
3557
+ }
3558
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3559
+ const decisions = loadInstallDecisions();
3560
+ decisions[serverId] = { decision, decidedAt };
3561
+ writeInstallDecisions(decisions);
3562
+ }
3563
+ function isInstallDecision(value) {
3564
+ return value === "declined" || value === "allowed";
3565
+ }
3566
+ function writeInstallDecisions(decisions) {
3567
+ const path = getInstallDecisionsPath();
3568
+ mkdirSync(dirname6(path), { recursive: true });
3569
+ const tmpPath = `${path}.tmp`;
3570
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3571
+ `, "utf8");
3572
+ renameSync2(tmpPath, path);
3573
+ }
3574
+ function isInstallDecisions(value) {
3575
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3576
+ }
3577
+ function isInstallDecisionRecord(value) {
3578
+ if (!isRecord5(value))
3579
+ return false;
3580
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3581
+ }
3582
+ function isRecord5(value) {
3583
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3584
+ }
3585
+
3395
3586
  // ../lsp-core/src/lsp/config-loader.ts
3587
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
3396
3588
  function getProjectConfigPaths() {
3397
3589
  return lspRequestContext().projectConfigPaths;
3398
3590
  }
@@ -3400,7 +3592,7 @@ function getUserConfigPath() {
3400
3592
  return lspRequestContext().userConfigPath;
3401
3593
  }
3402
3594
  function loadJsonFile(path) {
3403
- if (!existsSync7(path))
3595
+ if (!existsSync8(path))
3404
3596
  return null;
3405
3597
  try {
3406
3598
  const parsed = JSON.parse(readFileSync4(path, "utf-8"));
@@ -3588,54 +3780,155 @@ function getDisabledServerIds() {
3588
3780
  }
3589
3781
 
3590
3782
  // ../lsp-core/src/lsp/server-installation.ts
3591
- import { existsSync as existsSync8 } from "node:fs";
3592
- import { delimiter as delimiter3, join as join3 } from "node:path";
3593
- function isServerInstalled(command, _workingDirectory) {
3594
- if (command.length === 0)
3595
- return false;
3596
- const [cmd] = command;
3597
- if (!cmd)
3598
- return false;
3599
- if (cmd.includes("/") || cmd.includes("\\")) {
3600
- if (existsSync8(cmd))
3601
- return true;
3783
+ import { existsSync as existsSync9 } from "node:fs";
3784
+ import { delimiter as delimiter3, dirname as dirname7, isAbsolute as isAbsolute3, join as join4, resolve as resolve7 } from "node:path";
3785
+ var LOCAL_BIN_RULES = [
3786
+ {
3787
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
3788
+ binDirs: [join4("node_modules", ".bin")]
3789
+ },
3790
+ {
3791
+ markers: [
3792
+ "pyproject.toml",
3793
+ "ty.toml",
3794
+ "requirements.txt",
3795
+ "setup.py",
3796
+ "setup.cfg",
3797
+ "Pipfile",
3798
+ "pyrightconfig.json",
3799
+ "ruff.toml",
3800
+ ".ruff.toml"
3801
+ ],
3802
+ binDirs: [
3803
+ join4(".venv", "bin"),
3804
+ join4(".venv", "Scripts"),
3805
+ join4("venv", "bin"),
3806
+ join4("venv", "Scripts"),
3807
+ join4(".env", "bin"),
3808
+ join4(".env", "Scripts")
3809
+ ]
3810
+ },
3811
+ {
3812
+ markers: ["Gemfile", "Gemfile.lock"],
3813
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
3814
+ },
3815
+ {
3816
+ markers: ["go.mod", "go.sum", "go.work"],
3817
+ binDirs: ["bin"]
3818
+ }
3819
+ ];
3820
+ var resolutionCache = new Map;
3821
+ var probeCount = 0;
3822
+ function probe(path) {
3823
+ probeCount += 1;
3824
+ return existsSync9(path);
3825
+ }
3826
+ function executableSuffixes(platform, pathExt) {
3827
+ if (platform !== "win32")
3828
+ return [""];
3829
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
3830
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
3831
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
3832
+ }
3833
+ function probeWithSuffixes(directory, command, suffixes) {
3834
+ for (const suffix of suffixes) {
3835
+ const candidate = join4(directory, command + suffix);
3836
+ if (probe(candidate))
3837
+ return candidate;
3602
3838
  }
3603
- const isWindows = process.platform === "win32";
3604
- let exts = [""];
3605
- if (isWindows) {
3606
- const pathExt = process.env["PATHEXT"] ?? "";
3607
- if (pathExt) {
3608
- const systemExts = pathExt.split(";").filter(Boolean);
3609
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
3610
- } else {
3611
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
3839
+ return null;
3840
+ }
3841
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
3842
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
3843
+ let current = resolve7(workingDirectory);
3844
+ while (true) {
3845
+ for (const rule of LOCAL_BIN_RULES) {
3846
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
3847
+ continue;
3848
+ for (const binDir of rule.binDirs) {
3849
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
3850
+ if (found !== null)
3851
+ return found;
3852
+ }
3612
3853
  }
3854
+ if (probe(join4(current, ".git")))
3855
+ return null;
3856
+ if (boundary !== undefined && current === boundary)
3857
+ return null;
3858
+ const parent = dirname7(current);
3859
+ if (parent === current)
3860
+ return null;
3861
+ current = parent;
3613
3862
  }
3614
- let pathEnv = process.env["PATH"] ?? "";
3615
- if (isWindows && !pathEnv) {
3863
+ }
3864
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
3865
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
3866
+ if (platform === "win32" && !pathEnv) {
3616
3867
  pathEnv = process.env["Path"] ?? "";
3617
3868
  }
3618
- const paths = pathEnv.split(delimiter3);
3619
- for (const p of paths) {
3620
- for (const suffix of exts) {
3621
- if (existsSync8(join3(p, cmd + suffix))) {
3622
- return true;
3623
- }
3624
- }
3869
+ for (const entry of pathEnv.split(delimiter3)) {
3870
+ if (entry.length === 0)
3871
+ continue;
3872
+ const found = probeWithSuffixes(entry, command, suffixes);
3873
+ if (found !== null)
3874
+ return found;
3625
3875
  }
3626
- if (cmd === "node")
3627
- return true;
3628
- return false;
3876
+ return null;
3877
+ }
3878
+ function resolveServerBinary(command, workingDirectory, options = {}) {
3879
+ if (command.length === 0)
3880
+ return null;
3881
+ const [cmd] = command;
3882
+ if (cmd === undefined || cmd.length === 0)
3883
+ return null;
3884
+ const platform = options.platform ?? process.platform;
3885
+ const suffixes = executableSuffixes(platform, options.pathExt);
3886
+ if (cmd.includes("/") || cmd.includes("\\")) {
3887
+ const explicit = isAbsolute3(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
3888
+ return probe(explicit) ? explicit : null;
3889
+ }
3890
+ const cacheKey = JSON.stringify([
3891
+ workingDirectory ?? "",
3892
+ cmd,
3893
+ platform,
3894
+ options.stopAt ?? "",
3895
+ options.pathExt ?? "",
3896
+ options.pathEnv ?? process.env["PATH"] ?? ""
3897
+ ]);
3898
+ const cached = resolutionCache.get(cacheKey);
3899
+ if (cached !== undefined)
3900
+ return cached;
3901
+ let resolved = null;
3902
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
3903
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
3904
+ }
3905
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
3906
+ if (resolved === null && cmd === "node")
3907
+ resolved = cmd;
3908
+ resolutionCache.set(cacheKey, resolved);
3909
+ return resolved;
3910
+ }
3911
+ function isServerInstalled(command, workingDirectory, options = {}) {
3912
+ if (command.length === 0)
3913
+ return false;
3914
+ return resolveServerBinary(command, workingDirectory, options) !== null;
3629
3915
  }
3630
3916
 
3631
3917
  // ../lsp-core/src/lsp/server-resolution.ts
3918
+ function withResolvedCommand(command, binaryPath) {
3919
+ return [binaryPath, ...command.slice(1)];
3920
+ }
3632
3921
  function findServerForExtension(ext) {
3633
3922
  const servers = getMergedServers();
3923
+ const workingDirectory = contextCwd();
3634
3924
  for (const server of servers) {
3635
- if (server.extensions.includes(ext) && isServerInstalled(server.command)) {
3925
+ if (!server.extensions.includes(ext))
3926
+ continue;
3927
+ const binaryPath = resolveServerBinary(server.command, workingDirectory);
3928
+ if (binaryPath !== null) {
3636
3929
  const resolvedServer = {
3637
3930
  id: server.id,
3638
- command: server.command,
3931
+ command: withResolvedCommand(server.command, binaryPath),
3639
3932
  extensions: server.extensions,
3640
3933
  priority: server.priority
3641
3934
  };
@@ -3682,6 +3975,7 @@ function findServerForExtension(ext) {
3682
3975
  function getAllServers() {
3683
3976
  const servers = getMergedServers();
3684
3977
  const disabled = getDisabledServerIds();
3978
+ const workingDirectory = contextCwd();
3685
3979
  const result = [];
3686
3980
  const seen = new Set;
3687
3981
  for (const server of servers) {
@@ -3689,7 +3983,7 @@ function getAllServers() {
3689
3983
  continue;
3690
3984
  result.push({
3691
3985
  id: server.id,
3692
- installed: isServerInstalled(server.command),
3986
+ installed: isServerInstalled(server.command, workingDirectory),
3693
3987
  extensions: server.extensions,
3694
3988
  disabled: false,
3695
3989
  source: server.source,
@@ -3703,7 +3997,7 @@ function getAllServers() {
3703
3997
  const builtin = BUILTIN_SERVERS[id];
3704
3998
  result.push({
3705
3999
  id,
3706
- installed: builtin ? isServerInstalled(builtin.command) : false,
4000
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
3707
4001
  extensions: builtin?.extensions ?? [],
3708
4002
  disabled: true,
3709
4003
  source: "disabled",
@@ -3714,7 +4008,6 @@ function getAllServers() {
3714
4008
  }
3715
4009
 
3716
4010
  // ../lsp-core/src/lsp/client-wrapper.ts
3717
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
3718
4011
  function isDirectoryPath(filePath) {
3719
4012
  try {
3720
4013
  return statSync3(filePath).isDirectory();
@@ -3723,32 +4016,90 @@ function isDirectoryPath(filePath) {
3723
4016
  }
3724
4017
  }
3725
4018
  function findWorkspaceRoot(filePath) {
3726
- const abs = resolvePathInsideContext(filePath);
4019
+ const cwd = contextCwd();
4020
+ const abs = resolveReadablePathInsideContext(filePath);
3727
4021
  let dir = abs;
3728
4022
  if (!isDirectoryPath(dir)) {
3729
- dir = dirname6(dir);
3730
- }
3731
- let prevDir = "";
3732
- while (dir !== prevDir) {
3733
- for (const marker of WORKSPACE_MARKERS) {
3734
- if (existsSync9(join4(dir, marker))) {
3735
- return dir;
4023
+ dir = dirname8(dir);
4024
+ }
4025
+ if (!isPathInside(cwd, abs))
4026
+ return findWorkspaceRootOutsideContext(dir);
4027
+ const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4028
+ let nearestPackageRoot;
4029
+ while (isPathInside(cwd, dir)) {
4030
+ const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4031
+ if (canonicalDir !== undefined) {
4032
+ if (existsSync10(join5(dir, GIT_WORKSPACE_MARKER))) {
4033
+ return canonicalDir;
4034
+ }
4035
+ if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
4036
+ nearestPackageRoot = canonicalDir;
3736
4037
  }
3737
4038
  }
3738
- prevDir = dir;
3739
- dir = dirname6(dir);
4039
+ if (dir === cwd)
4040
+ break;
4041
+ dir = dirname8(dir);
3740
4042
  }
3741
- return dirname6(abs);
4043
+ return nearestPackageRoot ?? fallbackRoot;
4044
+ }
4045
+ function hasProjectWorkspaceMarker(directory) {
4046
+ return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync10(join5(directory, marker)));
4047
+ }
4048
+ function resolveReadablePathInsideContext(filePath) {
4049
+ const cwd = contextCwd();
4050
+ const abs = resolve8(cwd, filePath);
4051
+ if (isPathInside(cwd, abs))
4052
+ return abs;
4053
+ const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4054
+ if (rebased !== undefined)
4055
+ return rebased;
4056
+ return canonicalizeExistingOrNearestAncestor(abs);
3742
4057
  }
3743
4058
  function resolvePathInsideContext(filePath) {
3744
4059
  const cwd = contextCwd();
3745
- const abs = resolve7(cwd, filePath);
4060
+ const abs = resolveReadablePathInsideContext(filePath);
3746
4061
  const canonical = canonicalizeExistingOrNearestAncestor(abs);
3747
4062
  if (!isPathInside(cwd, canonical)) {
3748
4063
  throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
3749
4064
  }
3750
4065
  return canonical;
3751
4066
  }
4067
+ function rebaseThroughCanonicalAncestor(path, cwd) {
4068
+ let current = path;
4069
+ const suffix = [];
4070
+ while (true) {
4071
+ if (existsSync10(current)) {
4072
+ const canonical = realpathSync5(current);
4073
+ if (isPathInside(cwd, canonical))
4074
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
4075
+ }
4076
+ const parent = dirname8(current);
4077
+ if (parent === current)
4078
+ return;
4079
+ suffix.unshift(basename3(current));
4080
+ current = parent;
4081
+ }
4082
+ }
4083
+ function existingDirectoryInsideContext(directory, cwd) {
4084
+ if (!existsSync10(directory))
4085
+ return;
4086
+ const canonical = realpathSync5(directory);
4087
+ if (!statSync3(canonical).isDirectory())
4088
+ return;
4089
+ return isPathInside(cwd, canonical) ? canonical : undefined;
4090
+ }
4091
+ function nearestExistingDirectoryInsideContext(directory, cwd) {
4092
+ let current = directory;
4093
+ while (isPathInside(cwd, current)) {
4094
+ const canonical = existingDirectoryInsideContext(current, cwd);
4095
+ if (canonical !== undefined)
4096
+ return canonical;
4097
+ if (current === cwd)
4098
+ return;
4099
+ current = dirname8(current);
4100
+ }
4101
+ return;
4102
+ }
3752
4103
  function formatServerLookupError(result) {
3753
4104
  if (result.status === "not_installed") {
3754
4105
  return formatNotInstalled(result);
@@ -3772,6 +4123,19 @@ function formatServerLookupError(result) {
3772
4123
  ].join(`
3773
4124
  `);
3774
4125
  }
4126
+ function formatInstallOptions(serverId, installHint) {
4127
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
4128
+ if (localHint === undefined) {
4129
+ return ["To install, run:", ` ${installHint}`];
4130
+ }
4131
+ return [
4132
+ "To install in THIS repository (preferred — no global install needed):",
4133
+ ` ${localHint}`,
4134
+ "",
4135
+ "Or install it globally:",
4136
+ ` ${installHint}`
4137
+ ];
4138
+ }
3775
4139
  function formatNotInstalled(result) {
3776
4140
  const { server, installHint } = result;
3777
4141
  const extensions = server.extensions.join(", ");
@@ -3786,19 +4150,19 @@ function formatNotInstalled(result) {
3786
4150
  `Command not found: ${server.command[0]}`,
3787
4151
  ""
3788
4152
  ];
4153
+ const installOptions = formatInstallOptions(server.id, installHint);
3789
4154
  if (decision === "allowed") {
3790
4155
  return [
3791
4156
  ...header,
3792
4157
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
3793
- ` ${installHint}`
4158
+ ...installOptions.slice(1)
3794
4159
  ].join(`
3795
4160
  `);
3796
4161
  }
3797
4162
  if (!context.capabilities.installDecisionTool) {
3798
4163
  return [
3799
4164
  ...header,
3800
- "To install, run:",
3801
- ` ${installHint}`,
4165
+ ...installOptions,
3802
4166
  "",
3803
4167
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
3804
4168
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -3807,8 +4171,7 @@ function formatNotInstalled(result) {
3807
4171
  }
3808
4172
  return [
3809
4173
  ...header,
3810
- "To install, run:",
3811
- ` ${installHint}`,
4174
+ ...installOptions,
3812
4175
  "",
3813
4176
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
3814
4177
  "- If the user agrees: run the install command above, then retry this tool.",
@@ -3819,7 +4182,7 @@ function formatNotInstalled(result) {
3819
4182
  ].join(`
3820
4183
  `);
3821
4184
  }
3822
- var READ_ONLY_RETRY_TOOLS = new Set([
4185
+ var READ_ONLY_TOOLS = new Set([
3823
4186
  "diagnostics",
3824
4187
  "definition",
3825
4188
  "references",
@@ -3828,7 +4191,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
3828
4191
  "prepareRename"
3829
4192
  ]);
3830
4193
  async function withLspClient(filePath, fn, toolName, options = {}) {
3831
- const absPath = resolvePathInsideContext(filePath);
4194
+ const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
3832
4195
  if (isDirectoryPath(absPath)) {
3833
4196
  throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
3834
4197
  }
@@ -3843,9 +4206,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
3843
4206
  const acquireAndCall = async (allowRetry) => {
3844
4207
  const client = await manager.getClient(root, server, options.signal);
3845
4208
  try {
3846
- return await fn(client, root);
4209
+ return await fn(client, root, absPath);
3847
4210
  } catch (err) {
3848
- if (allowRetry && READ_ONLY_RETRY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4211
+ if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
3849
4212
  manager.invalidateClient(root, server.id, client);
3850
4213
  return acquireAndCall(false);
3851
4214
  }
@@ -3863,8 +4226,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
3863
4226
  }
3864
4227
 
3865
4228
  // ../lsp-core/src/lsp/directory-diagnostics.ts
3866
- import { existsSync as existsSync10, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
3867
- import { join as join5, resolve as resolve8 } from "node:path";
4229
+ import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4230
+ import { join as join6, resolve as resolve9 } from "node:path";
3868
4231
 
3869
4232
  // ../lsp-core/src/lsp/formatters.ts
3870
4233
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -3994,7 +4357,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
3994
4357
  for (const entry of entries) {
3995
4358
  if (files.length >= maxFiles)
3996
4359
  return;
3997
- const fullPath = join5(currentDir, entry);
4360
+ const fullPath = join6(currentDir, entry);
3998
4361
  let stat;
3999
4362
  try {
4000
4363
  stat = lstatSync4(fullPath);
@@ -4019,8 +4382,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4019
4382
  if (!extension.startsWith(".")) {
4020
4383
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4021
4384
  }
4022
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4023
- if (!existsSync10(absDir)) {
4385
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
4386
+ if (!existsSync11(absDir)) {
4024
4387
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4025
4388
  }
4026
4389
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
@@ -4107,7 +4470,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4107
4470
 
4108
4471
  // ../lsp-core/src/lsp/infer-extension.ts
4109
4472
  import { lstatSync as lstatSync5, readdirSync as readdirSync4 } from "node:fs";
4110
- import { join as join6 } from "node:path";
4473
+ import { join as join7 } from "node:path";
4111
4474
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
4112
4475
  var MAX_SCAN_ENTRIES = 500;
4113
4476
  function inferExtensionFromDirectory(directory) {
@@ -4125,7 +4488,7 @@ function inferExtensionFromDirectory(directory) {
4125
4488
  for (const entry of entries) {
4126
4489
  if (scanned >= MAX_SCAN_ENTRIES)
4127
4490
  return;
4128
- const fullPath = join6(dir, entry);
4491
+ const fullPath = join7(dir, entry);
4129
4492
  let stat;
4130
4493
  try {
4131
4494
  stat = lstatSync5(fullPath);
@@ -4300,7 +4663,7 @@ async function executeLspDiagnostics(params, signal) {
4300
4663
  const filePath = requireString(params, "filePath");
4301
4664
  const severity = severityFilter(params);
4302
4665
  try {
4303
- const absPath = resolvePathInsideContext(filePath);
4666
+ const absPath = resolveReadablePathInsideContext(filePath);
4304
4667
  if (isDirectoryPath(absPath)) {
4305
4668
  const extension = inferExtensionFromDirectory(absPath);
4306
4669
  if (!extension) {
@@ -4329,7 +4692,7 @@ async function executeLspDiagnostics(params, signal) {
4329
4692
  };
4330
4693
  return text(output2.output, details2);
4331
4694
  }
4332
- const result = await withLspClient(filePath, async (client) => client.diagnostics(filePath, signal), "diagnostics", clientOptions(signal));
4695
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
4333
4696
  if (result.transientError) {
4334
4697
  const message = result.transientError.message;
4335
4698
  const details2 = {
@@ -4376,6 +4739,96 @@ async function executeLspDiagnostics(params, signal) {
4376
4739
  throw error;
4377
4740
  }
4378
4741
  }
4742
+ // ../lsp-core/src/lsp/format-document.ts
4743
+ import { readFileSync as readFileSync5, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
4744
+ var DEFAULT_FORMATTING_OPTIONS = {
4745
+ tabSize: 4,
4746
+ insertSpaces: false,
4747
+ trimTrailingWhitespace: true,
4748
+ insertFinalNewline: true,
4749
+ trimFinalNewlines: true
4750
+ };
4751
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
4752
+ async function formatDocumentWithClient(client, filePath, options = {}) {
4753
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
4754
+ if (edits === null)
4755
+ return { status: "unavailable", reason: "capability_not_advertised" };
4756
+ if (edits.length === 0)
4757
+ return UNCHANGED;
4758
+ const before = readFileSync5(filePath, "utf-8");
4759
+ const normalized = normalizeTextEdits(before, edits, 0);
4760
+ if (normalized.text === before)
4761
+ return UNCHANGED;
4762
+ writeAtomically(filePath, normalized.text);
4763
+ await client.openFile(filePath);
4764
+ return {
4765
+ status: "formatted",
4766
+ ...lineDelta(normalized.edits)
4767
+ };
4768
+ }
4769
+ function lineDelta(edits) {
4770
+ let linesAdded = 0;
4771
+ let linesRemoved = 0;
4772
+ for (const edit of edits) {
4773
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
4774
+ linesAdded += edit.newText.split(`
4775
+ `).length;
4776
+ }
4777
+ return { linesAdded, linesRemoved };
4778
+ }
4779
+ function writeAtomically(filePath, content) {
4780
+ const tempPath = `${filePath}.omo-format.tmp`;
4781
+ writeFileSync3(tempPath, content, "utf-8");
4782
+ try {
4783
+ renameSync3(tempPath, filePath);
4784
+ } catch (error) {
4785
+ try {
4786
+ unlinkSync(tempPath);
4787
+ } catch {}
4788
+ throw error;
4789
+ }
4790
+ }
4791
+
4792
+ // ../lsp-core/src/tools/format.ts
4793
+ async function executeLspFormat(params, signal) {
4794
+ const filePath = requireString(params, "filePath");
4795
+ try {
4796
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
4797
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
4798
+ } catch (error) {
4799
+ const missingDependency = missingDependencyResult(error, {
4800
+ filePath,
4801
+ status: "unavailable",
4802
+ reason: "server_unavailable",
4803
+ linesAdded: 0,
4804
+ linesRemoved: 0
4805
+ });
4806
+ if (missingDependency)
4807
+ return missingDependency;
4808
+ throw error;
4809
+ }
4810
+ }
4811
+ function formatDetails(filePath, result) {
4812
+ if (result.status === "unavailable") {
4813
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
4814
+ }
4815
+ return {
4816
+ filePath,
4817
+ status: result.status,
4818
+ linesAdded: result.linesAdded,
4819
+ linesRemoved: result.linesRemoved
4820
+ };
4821
+ }
4822
+ function describeResult(filePath, result) {
4823
+ if (result.status === "unavailable") {
4824
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
4825
+ }
4826
+ if (result.status === "unchanged") {
4827
+ return `Already formatted: ${filePath}`;
4828
+ }
4829
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
4830
+ }
4831
+
4379
4832
  // ../lsp-core/src/tools/install-decision.ts
4380
4833
  async function executeLspInstallDecision(params) {
4381
4834
  const serverId = requireString(params, "server_id");
@@ -4404,7 +4857,7 @@ async function executeLspGotoDefinition(params, signal) {
4404
4857
  const line = requireNumber(params, "line");
4405
4858
  const character = requireNumber(params, "character");
4406
4859
  try {
4407
- const result = await withLspClient(filePath, async (client) => client.definition(filePath, line, character, signal), "definition", clientOptions(signal));
4860
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
4408
4861
  const locations = !result ? [] : Array.isArray(result) ? result : [result];
4409
4862
  const details = { filePath, line, character, locations };
4410
4863
  if (locations.length === 0)
@@ -4429,7 +4882,7 @@ async function executeLspFindReferences(params, signal) {
4429
4882
  const character = requireNumber(params, "character");
4430
4883
  const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
4431
4884
  try {
4432
- const result = await withLspClient(filePath, async (client) => client.references(filePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
4885
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
4433
4886
  const references = Array.isArray(result) ? result : [];
4434
4887
  const total = references.length;
4435
4888
  const truncated = total > DEFAULT_MAX_REFERENCES;
@@ -4471,7 +4924,7 @@ async function executeLspPrepareRename(params, signal) {
4471
4924
  const line = requireNumber(params, "line");
4472
4925
  const character = requireNumber(params, "character");
4473
4926
  try {
4474
- const result = await withLspClient(filePath, async (client) => client.prepareRename(filePath, line, character, signal), "prepareRename", clientOptions(signal));
4927
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
4475
4928
  const details = { filePath, line, character, result };
4476
4929
  return text(formatPrepareRenameResult(result), details);
4477
4930
  } catch (error) {
@@ -4492,7 +4945,7 @@ async function executeLspRename(params, signal) {
4492
4945
  const character = requireNumber(params, "character");
4493
4946
  const newName = requireString(params, "newName");
4494
4947
  try {
4495
- const result = await withLspClient(filePath, async (client) => client.rename(filePath, line, character, newName, signal), "rename", clientOptions(signal));
4948
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
4496
4949
  const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
4497
4950
  return text(formatApplyResult(result.apply), details, !result.apply.success);
4498
4951
  } catch (error) {
@@ -4572,7 +5025,7 @@ async function executeLspSymbols(params, signal) {
4572
5025
  const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
4573
5026
  return formatSymbolsResult(filePath, scope, symbols2, limit, query);
4574
5027
  }
4575
- const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(filePath, signal), "documentSymbols", clientOptions(signal));
5028
+ const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
4576
5029
  return formatSymbolsResult(filePath, scope, symbols, limit);
4577
5030
  } catch (error) {
4578
5031
  const query = optionalString(params, "query");
@@ -4708,6 +5161,16 @@ var LSP_MCP_TOOLS = [
4708
5161
  }, ["filePath", "line", "character", "newName"]),
4709
5162
  execute: executeLspRename
4710
5163
  },
5164
+ {
5165
+ name: "format",
5166
+ aliases: ["lsp_format"],
5167
+ title: "LSP Format",
5168
+ description: "Format a source file with its language server and write the returned edits to disk.",
5169
+ inputSchema: objectSchema({
5170
+ filePath: { type: "string", description: "Source file path to format." }
5171
+ }, ["filePath"]),
5172
+ execute: executeLspFormat
5173
+ },
4711
5174
  {
4712
5175
  name: "install_decision",
4713
5176
  aliases: ["lsp_install_decision"],
@@ -4741,16 +5204,17 @@ function coerceToolArguments(value) {
4741
5204
  return isRecord7(value) ? value : {};
4742
5205
  }
4743
5206
  export {
4744
- isRecord7 as isRecord,
4745
- executeLspTool,
4746
- executeLspSymbols,
4747
- executeLspStatus,
4748
- executeLspRename,
4749
- executeLspPrepareRename,
4750
- executeLspInstallDecision,
4751
- executeLspGotoDefinition,
4752
- executeLspFindReferences,
4753
- executeLspDiagnostics,
5207
+ LSP_MCP_TOOLS,
4754
5208
  coerceToolArguments,
4755
- LSP_MCP_TOOLS
5209
+ executeLspDiagnostics,
5210
+ executeLspFindReferences,
5211
+ executeLspFormat,
5212
+ executeLspGotoDefinition,
5213
+ executeLspInstallDecision,
5214
+ executeLspPrepareRename,
5215
+ executeLspRename,
5216
+ executeLspStatus,
5217
+ executeLspSymbols,
5218
+ executeLspTool,
5219
+ isRecord7 as isRecord
4756
5220
  };