oh-my-opencode 5.0.0-beta.6 → 5.0.0-beta.60

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 (990) hide show
  1. package/.agents/command/publish.md +59 -23
  2. package/.agents/skills/codex-qa/scripts/lsp-e2e.sh +1 -3
  3. package/.agents/skills/opencode-qa/scripts/lsp-e2e.sh +1 -1
  4. package/.agents/skills/pre-publish-review/SKILL.md +9 -12
  5. package/.agents/skills/publish/SKILL.md +59 -23
  6. package/.agents/skills/senpi-qa/SKILL.md +80 -0
  7. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.mjs +65 -0
  8. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.test.mjs +171 -0
  9. package/.agents/skills/tech-debt-audit/SKILL.md +6 -76
  10. package/.agents/skills/work-with-pr/SKILL.md +37 -23
  11. package/.opencode/command/publish.md +59 -23
  12. package/.opencode/skills/pre-publish-review/SKILL.md +9 -12
  13. package/.opencode/skills/work-with-pr/SKILL.md +37 -23
  14. package/README.ja.md +65 -60
  15. package/README.ko.md +66 -61
  16. package/README.md +65 -72
  17. package/README.ru.md +62 -60
  18. package/README.zh-cn.md +61 -60
  19. package/THIRD-PARTY-NOTICES.md +27 -99
  20. package/dist/agents/atlas/agent.d.ts +0 -1
  21. package/dist/agents/gpt-prompt-identity.d.ts +1 -1
  22. package/dist/agents/sisyphus/grok-4.d.ts +20 -0
  23. package/dist/agents/sisyphus/index.d.ts +2 -0
  24. package/dist/agents/sisyphus-agent-config.d.ts +6 -0
  25. package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
  26. package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +15 -4
  27. package/dist/agents/types.d.ts +4 -2
  28. package/dist/cli/config-manager/parse-opencode-config-file.d.ts +2 -1
  29. package/dist/cli/doctor/checks/index.d.ts +2 -0
  30. package/dist/cli/doctor/checks/latest-version.d.ts +11 -0
  31. package/dist/cli/doctor/checks/system-plugin.d.ts +4 -3
  32. package/dist/cli/doctor/framework/constants.d.ts +5 -0
  33. package/dist/cli/doctor/framework/types.d.ts +2 -0
  34. package/dist/cli/fallback-lane-policy.d.ts +1 -0
  35. package/dist/cli/index.js +51738 -59690
  36. package/dist/cli/install-codex/install-codex-test-fixtures.d.ts +1 -1
  37. package/dist/cli/run/on-complete-hook.d.ts +2 -0
  38. package/dist/cli/runtime-commands.d.ts +1 -1
  39. package/dist/cli/worktree-sweep/classify.d.ts +16 -0
  40. package/dist/cli/worktree-sweep/format.d.ts +8 -0
  41. package/dist/cli/worktree-sweep/git.d.ts +19 -0
  42. package/dist/cli/worktree-sweep/index.d.ts +7 -0
  43. package/dist/cli/worktree-sweep/options.d.ts +2 -0
  44. package/dist/cli/worktree-sweep/parse-worktree-list.d.ts +8 -0
  45. package/dist/cli/worktree-sweep/sweep.d.ts +2 -0
  46. package/dist/cli/worktree-sweep/types.d.ts +65 -0
  47. package/dist/cli/worktree-sweep/worktree-sweep.d.ts +2 -0
  48. package/dist/cli-node/index.js +50900 -58829
  49. package/dist/config/index.d.ts +1 -1
  50. package/dist/config/schema/background-task.d.ts +1 -0
  51. package/dist/config/schema/commands.d.ts +1 -1
  52. package/dist/config/schema/hooks.d.ts +1 -2
  53. package/dist/config/schema/oh-my-opencode-config.d.ts +5 -11
  54. package/dist/config/schema/ulw-execute.d.ts +5 -0
  55. package/dist/config/schema.d.ts +0 -1
  56. package/dist/config/validate.d.ts +2 -0
  57. package/dist/create-hooks.d.ts +3 -2
  58. package/dist/features/background-agent/compaction-aware-message-resolver.d.ts +1 -0
  59. package/dist/features/background-agent/constants.d.ts +0 -7
  60. package/dist/features/background-agent/error-classifier.d.ts +1 -0
  61. package/dist/features/background-agent/manager.d.ts +9 -1
  62. package/dist/features/background-agent/parent-wake-dispatched-tracker.d.ts +0 -1
  63. package/dist/features/background-agent/parent-wake-notifier-types.d.ts +1 -1
  64. package/dist/features/background-agent/parent-wake-prompt-dispatch.d.ts +1 -1
  65. package/dist/features/background-agent/parent-wake-session-inspector.d.ts +1 -1
  66. package/dist/features/background-agent/subagent-spawn-limits.d.ts +8 -0
  67. package/dist/features/background-agent/types.d.ts +4 -0
  68. package/dist/features/btw-side/btw-command-draft.d.ts +7 -0
  69. package/dist/features/btw-side/context-injector.d.ts +15 -0
  70. package/dist/features/btw-side/index.d.ts +8 -0
  71. package/dist/features/btw-side/metadata.d.ts +15 -0
  72. package/dist/features/btw-side/parent-context-budget.d.ts +9 -0
  73. package/dist/features/btw-side/server-session-registry.d.ts +8 -0
  74. package/dist/features/btw-side/tui-adoption-cache.d.ts +13 -0
  75. package/dist/features/btw-side/tui-adoption-guard.d.ts +5 -0
  76. package/dist/features/btw-side/tui-controller-types.d.ts +68 -0
  77. package/dist/features/btw-side/tui-controller.d.ts +19 -0
  78. package/dist/features/btw-side/tui-escape-return.d.ts +12 -0
  79. package/dist/features/btw-side/tui-keymap.d.ts +17 -0
  80. package/dist/features/btw-side/tui-parent-validator.d.ts +6 -0
  81. package/dist/features/btw-side/tui-picker-options.d.ts +20 -0
  82. package/dist/features/btw-side/tui-picker.d.ts +9 -0
  83. package/dist/features/btw-side/tui-prompt-queue.d.ts +8 -0
  84. package/dist/features/btw-side/tui-session-bridge.d.ts +11 -0
  85. package/dist/features/btw-side/tui-session-catalog.d.ts +35 -0
  86. package/dist/features/btw-side/tui-side-removal.d.ts +11 -0
  87. package/dist/features/btw-side/tui-side-start.d.ts +9 -0
  88. package/dist/features/btw-side/tui-wiring.d.ts +8 -0
  89. package/dist/features/builtin-commands/templates/ulw-execute.d.ts +1 -0
  90. package/dist/features/builtin-commands/types.d.ts +1 -1
  91. package/dist/features/claude-tasks/storage.d.ts +7 -2
  92. package/dist/features/hook-message-injector/index.d.ts +1 -0
  93. package/dist/features/hook-message-injector/sdk-message-lookup.d.ts +1 -0
  94. package/dist/features/monitor/manager-internals.d.ts +1 -1
  95. package/dist/features/monitor/output-injector-types.d.ts +1 -1
  96. package/dist/features/opengateway-provider/index.d.ts +13 -0
  97. package/dist/features/task-toast-manager/manager.d.ts +0 -24
  98. package/dist/features/team-mode/tools/messaging-fallback-wake.d.ts +17 -0
  99. package/dist/features/team-mode/tools/messaging-live-delivery-recipient.d.ts +3 -0
  100. package/dist/features/team-mode/tools/messaging-runtime.d.ts +7 -0
  101. package/dist/hooks/anthropic-context-window-limit-recovery/message-storage-directory.d.ts +0 -3
  102. package/dist/hooks/anthropic-context-window-limit-recovery/state.d.ts +1 -0
  103. package/dist/hooks/anthropic-context-window-limit-recovery/storage/empty-messages.d.ts +0 -1
  104. package/dist/hooks/anthropic-context-window-limit-recovery/tool-result-storage.d.ts +11 -0
  105. package/dist/hooks/atlas/atlas-hook.d.ts +1 -0
  106. package/dist/hooks/atlas/atlas-lifecycle-store.d.ts +50 -0
  107. package/dist/hooks/atlas/event-handler.d.ts +1 -0
  108. package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
  109. package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
  110. package/dist/hooks/atlas/tool-execute-before.d.ts +3 -0
  111. package/dist/hooks/atlas/types.d.ts +1 -0
  112. package/dist/hooks/claude-code-hooks/session-hook-state.d.ts +1 -0
  113. package/dist/hooks/claude-code-hooks/stop.d.ts +2 -0
  114. package/dist/hooks/claude-code-hooks/todo.d.ts +0 -1
  115. package/dist/hooks/claude-code-hooks/transcript.d.ts +2 -0
  116. package/dist/hooks/compaction-context-injector/validated-model.d.ts +2 -0
  117. package/dist/hooks/fsync-skip-warning/index.d.ts +4 -0
  118. package/dist/hooks/hashline-edit-diff-enhancer/hook.d.ts +1 -0
  119. package/dist/hooks/hashline-edit-diff-enhancer/pending-captures.d.ts +13 -0
  120. package/dist/hooks/index.d.ts +1 -2
  121. package/dist/hooks/keyword-detector/hook.d.ts +9 -0
  122. package/dist/hooks/keyword-detector/ultrawork/index.d.ts +2 -0
  123. package/dist/hooks/keyword-detector/ultrawork/source-detector.d.ts +0 -1
  124. package/dist/hooks/model-fallback/hook.d.ts +1 -1
  125. package/dist/hooks/prometheus-md-only/agent-resolution.d.ts +2 -2
  126. package/dist/hooks/runtime-fallback/chat-message-handler.d.ts +2 -0
  127. package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +1 -0
  128. package/dist/hooks/runtime-fallback/runtime-model-settings.d.ts +6 -0
  129. package/dist/hooks/runtime-fallback/session-status-handler.d.ts +1 -1
  130. package/dist/hooks/runtime-fallback/types.d.ts +3 -1
  131. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  132. package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
  133. package/dist/hooks/{start-work → ulw-execute}/context-info-builder.d.ts +1 -1
  134. package/dist/hooks/{start-work → ulw-execute}/index.d.ts +1 -1
  135. package/dist/hooks/ulw-execute/ulw-execute-hook.d.ts +23 -0
  136. package/dist/hooks/unstable-agent-babysitter/task-message-analyzer.d.ts +1 -0
  137. package/dist/index.js +29256 -25391
  138. package/dist/mcp/index.d.ts +0 -4
  139. package/dist/mcp/types.d.ts +0 -1
  140. package/dist/oh-my-opencode.schema.json +21 -47
  141. package/dist/plugin/chat-message/types.d.ts +6 -4
  142. package/dist/plugin/chat-message/ulw-execute-message.d.ts +5 -0
  143. package/dist/plugin/event-session-lifecycle.d.ts +1 -0
  144. package/dist/plugin/hooks/create-core-hooks.d.ts +2 -2
  145. package/dist/plugin/hooks/create-session-hooks.d.ts +2 -3
  146. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
  147. package/dist/plugin/messages-transform.d.ts +1 -0
  148. package/dist/plugin/stop-continuation.d.ts +3 -0
  149. package/dist/plugin/system-transform.d.ts +5 -1
  150. package/dist/plugin-dispose.d.ts +3 -0
  151. package/dist/shared/agent-tool-restrictions.d.ts +0 -1
  152. package/dist/shared/compaction-agent-config-checkpoint.d.ts +1 -0
  153. package/dist/shared/index.d.ts +2 -0
  154. package/dist/shared/legacy-plugin-warning.d.ts +2 -1
  155. package/dist/shared/normalize-sdk-response.d.ts +1 -0
  156. package/dist/shared/omo-process-sweep.d.ts +2 -4
  157. package/dist/shared/plugin-entry-migrator.d.ts +4 -3
  158. package/dist/shared/plugin-entry-shape.d.ts +6 -0
  159. package/dist/shared/runtime-fallback-retry-marker.d.ts +16 -0
  160. package/dist/shared/shell-env.d.ts +1 -1
  161. package/dist/skills/ast-grep/AGENTS.md +51 -0
  162. package/dist/skills/ast-grep/SKILL.md +1 -1
  163. package/dist/skills/coding-agent-sessions/AGENTS.md +62 -0
  164. package/dist/skills/coding-agent-sessions/SKILL.md +1 -1
  165. package/dist/skills/data-scientist/SKILL.md +99 -239
  166. package/dist/skills/data-scientist/references/execution-surfaces.md +91 -0
  167. package/dist/skills/data-scientist/references/placement.md +74 -0
  168. package/dist/skills/data-scientist/references/polars-lane.md +95 -0
  169. package/dist/skills/data-scientist/references/uv-setup.md +1 -1
  170. package/dist/skills/data-scientist/references/visualization.md +64 -0
  171. package/dist/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  172. package/dist/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  173. package/dist/skills/debugging/SKILL.md +3 -1
  174. package/dist/skills/debugging/references/methodology/00-setup.md +12 -0
  175. package/dist/skills/debugging/references/methodology/02-investigate.md +21 -0
  176. package/dist/skills/debugging/references/runtimes/go.md +15 -1
  177. package/dist/skills/debugging/references/runtimes/native-binary.md +38 -0
  178. package/dist/skills/debugging/references/runtimes/node.md +25 -0
  179. package/dist/skills/debugging/references/runtimes/python.md +13 -0
  180. package/dist/skills/debugging/references/runtimes/rust.md +41 -0
  181. package/dist/skills/debugging/references/scripts/dap.mjs +267 -0
  182. package/dist/skills/debugging/references/scripts/dap.test.ts +86 -0
  183. package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  184. package/dist/skills/debugging/references/tools/dap.md +103 -0
  185. package/dist/skills/debugging/references/tools/frida.md +193 -0
  186. package/dist/skills/frontend/ATTRIBUTION.md +10 -0
  187. package/dist/skills/frontend/SKILL.md +15 -8
  188. package/dist/skills/frontend/references/design/README.md +10 -2
  189. package/dist/skills/frontend/references/design/_INDEX.md +2 -0
  190. package/dist/skills/frontend/references/design/ambience-skill.md +145 -0
  191. package/dist/skills/frontend/references/design/interaction-skill.md +2 -0
  192. package/dist/skills/frontend/references/design/print-paged-media.md +76 -0
  193. package/dist/skills/frontend/references/design/stylegallery.md +80 -0
  194. package/dist/skills/frontend/references/designpowers/README.md +1 -1
  195. package/dist/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  196. package/dist/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  197. package/dist/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  198. package/dist/skills/frontend/references/designpowers/orchestration.md +1 -1
  199. package/dist/skills/frontend/references/designpowers/routing.md +5 -5
  200. package/dist/skills/git-master/SKILL.md +1 -1
  201. package/dist/skills/init-deep/SKILL.md +14 -14
  202. package/dist/skills/lsp-setup/SKILL.md +1 -1
  203. package/dist/skills/programming/SKILL.md +1 -1
  204. package/dist/skills/refactor/SKILL.md +4 -4
  205. package/dist/skills/remove-ai-slops/SKILL.md +1 -1
  206. package/dist/skills/review-work/SKILL.md +101 -419
  207. package/dist/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
  208. package/dist/skills/ultimate-browsing/SKILL.md +26 -9
  209. package/dist/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  210. package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
  211. package/dist/skills/ultimate-browsing/references/chrome-stealth.md +23 -18
  212. package/dist/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  213. package/dist/skills/{start-work → ulw-execute}/SKILL.md +20 -19
  214. package/dist/skills/ulw-plan/SKILL.md +7 -8
  215. package/dist/skills/ulw-plan/references/full-workflow.md +31 -7
  216. package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
  217. package/dist/skills/ulw-plan/references/intent-unclear.md +5 -5
  218. package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  219. package/dist/skills/ulw-research/SKILL.md +8 -3
  220. package/dist/skills/visual-qa/AGENTS.md +58 -0
  221. package/dist/skills/visual-qa/SKILL.md +4 -3
  222. package/dist/tools/delegate-task/builtin-categories.d.ts +3 -1
  223. package/dist/tools/delegate-task/builtin-category-definition.d.ts +2 -1
  224. package/dist/tools/delegate-task/constants.d.ts +2 -2
  225. package/dist/tools/delegate-task/openai-categories.d.ts +7 -2
  226. package/dist/tools/delegate-task/sync-session-cleanup.d.ts +3 -0
  227. package/dist/tools/delegate-task/sync-session-poller.d.ts +1 -0
  228. package/dist/tools/delegate-task/tool-description.d.ts +3 -1
  229. package/dist/tools/delegate-task/types.d.ts +4 -0
  230. package/dist/tools/session-manager/directory-filter.d.ts +2 -0
  231. package/dist/tui.d.ts +12 -0
  232. package/dist/tui.js +37048 -46599
  233. package/package.json +47 -41
  234. package/packages/git-bash-mcp/dist/cli.js +6 -1
  235. package/packages/git-bash-mcp/package.json +1 -1
  236. package/packages/lsp-core/src/index.ts +1 -0
  237. package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
  238. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +57 -48
  239. package/packages/lsp-core/src/lsp/client-diagnostics-pull-timeout.test.ts +64 -0
  240. package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
  241. package/packages/lsp-core/src/lsp/client-wrapper.test.ts +103 -6
  242. package/packages/lsp-core/src/lsp/client-wrapper.ts +50 -16
  243. package/packages/lsp-core/src/lsp/client.ts +32 -3
  244. package/packages/lsp-core/src/lsp/connection.ts +16 -0
  245. package/packages/lsp-core/src/lsp/constants.ts +6 -0
  246. package/packages/lsp-core/src/lsp/controlled-clock-test-support.ts +61 -0
  247. package/packages/lsp-core/src/lsp/errors.ts +15 -0
  248. package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +10 -3
  249. package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
  250. package/packages/lsp-core/src/lsp/format-document.ts +90 -0
  251. package/packages/lsp-core/src/lsp/json-rpc-connection.ts +11 -6
  252. package/packages/lsp-core/src/lsp/manager-lifecycle.test.ts +262 -0
  253. package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
  254. package/packages/lsp-core/src/lsp/manager.ts +138 -12
  255. package/packages/lsp-core/src/lsp/outside-context-workspace.ts +33 -0
  256. package/packages/lsp-core/src/lsp/server-definitions.ts +29 -0
  257. package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
  258. package/packages/lsp-core/src/lsp/server-installation.ts +200 -27
  259. package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
  260. package/packages/lsp-core/src/lsp/server-resolution.ts +18 -5
  261. package/packages/lsp-core/src/lsp/timer-provider.ts +13 -0
  262. package/packages/lsp-core/src/lsp/transport-request-timeout.test.ts +73 -0
  263. package/packages/lsp-core/src/lsp/transport.ts +16 -2
  264. package/packages/lsp-core/src/lsp/types.ts +8 -0
  265. package/packages/lsp-core/src/lsp/workspace-apply-edit-test-support.ts +29 -1
  266. package/packages/lsp-core/src/lsp/workspace-document-state.test.ts +84 -1
  267. package/packages/lsp-core/src/lsp/workspace-document-state.ts +30 -11
  268. package/packages/lsp-core/src/lsp/workspace-markers.ts +18 -0
  269. package/packages/lsp-core/src/mcp.ts +3 -0
  270. package/packages/lsp-core/src/request-context.test.ts +29 -0
  271. package/packages/lsp-core/src/request-context.ts +1 -1
  272. package/packages/lsp-core/src/tool-surface.test.ts +13 -1
  273. package/packages/lsp-core/src/tools/definitions.ts +14 -0
  274. package/packages/lsp-core/src/tools/format.test.ts +56 -0
  275. package/packages/lsp-core/src/tools/format.ts +56 -0
  276. package/packages/lsp-core/src/tools/index.ts +1 -0
  277. package/packages/lsp-core/src/tools/parameters.test.ts +51 -0
  278. package/packages/lsp-core/src/tools/types.ts +10 -0
  279. package/packages/lsp-daemon/dist/cli.js +902 -479
  280. package/packages/lsp-daemon/dist/client.d.ts +10 -0
  281. package/packages/lsp-daemon/dist/client.js +920 -493
  282. package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
  283. package/packages/lsp-daemon/dist/daemon-client.js +3 -0
  284. package/packages/lsp-daemon/dist/ensure-daemon.d.ts +6 -1
  285. package/packages/lsp-daemon/dist/ensure-daemon.js +10 -2
  286. package/packages/lsp-daemon/dist/index.js +824 -402
  287. package/packages/lsp-daemon/dist/ownership.js +2 -2
  288. package/packages/lsp-daemon/dist/proxy.js +3 -0
  289. package/packages/lsp-daemon/dist/version-reap.js +1 -1
  290. package/packages/lsp-daemon/package.json +1 -1
  291. package/packages/lsp-tools-mcp/dist/cli.js +762 -341
  292. package/packages/lsp-tools-mcp/dist/lsp/manager.js +272 -138
  293. package/packages/lsp-tools-mcp/dist/mcp.js +787 -368
  294. package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
  295. package/packages/lsp-tools-mcp/dist/tools.js +717 -302
  296. package/packages/lsp-tools-mcp/package.json +1 -1
  297. package/packages/omo-codex/THIRD-PARTY-NOTICES.md +4 -21
  298. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +4 -6
  299. package/packages/omo-codex/plugin/.mcp.json +0 -6
  300. package/packages/omo-codex/plugin/AGENTS.md +47 -0
  301. package/packages/omo-codex/plugin/README.md +6 -2
  302. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +197 -148
  303. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  304. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  305. package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +1 -0
  306. package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +9 -0
  307. package/packages/omo-codex/plugin/components/comment-checker/biome.json +2 -2
  308. package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +2 -1
  309. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  310. package/packages/omo-codex/plugin/components/comment-checker/package.json +5 -5
  311. package/packages/omo-codex/plugin/components/comment-checker/src/apply-patch.ts +2 -8
  312. package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +1 -2
  313. package/packages/omo-codex/plugin/components/comment-checker/src/request-extractor.ts +1 -1
  314. package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +1 -0
  315. package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +1 -1
  316. package/packages/omo-codex/plugin/components/git-bash/dist/cli.js +1 -1
  317. package/packages/omo-codex/plugin/components/git-bash/dist/codex-hook.js +2 -1
  318. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  319. package/packages/omo-codex/plugin/components/git-bash/package.json +3 -4
  320. package/packages/omo-codex/plugin/components/git-bash/src/codex-hook.ts +2 -1
  321. package/packages/omo-codex/plugin/components/git-bash/test/codex-hook.test.ts +6 -7
  322. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/AGENTS.md +2 -2
  323. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
  324. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/directive.md +2 -0
  325. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +36 -29
  326. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +32 -26
  327. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/types.d.ts +3 -0
  328. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  329. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +5 -5
  330. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +32 -28
  331. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/types.ts +3 -0
  332. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/cli.test.ts +1 -1
  333. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +137 -28
  334. package/packages/omo-codex/plugin/components/lcx/skills/lcx-doctor/SKILL.md +4 -2
  335. package/packages/omo-codex/plugin/components/lsp/AGENTS.md +30 -15
  336. package/packages/omo-codex/plugin/components/lsp/biome.json +2 -2
  337. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +4 -4
  338. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +941 -540
  339. package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.js +1 -1
  340. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  341. package/packages/omo-codex/plugin/components/lsp/package.json +5 -5
  342. package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
  343. package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +1 -1
  344. package/packages/omo-codex/plugin/components/lsp/src/daemon-cli-path.ts +1 -5
  345. package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +6 -7
  346. package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +1 -2
  347. package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +11 -1
  348. package/packages/omo-codex/plugin/components/rules/AGENTS.md +12 -0
  349. package/packages/omo-codex/plugin/components/rules/README.md +2 -0
  350. package/packages/omo-codex/plugin/components/rules/biome.json +2 -2
  351. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-6.md +123 -0
  352. package/packages/omo-codex/plugin/components/rules/dist/cli.js +91 -68
  353. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  354. package/packages/omo-codex/plugin/components/rules/package.json +7 -7
  355. package/packages/omo-codex/plugin/components/rules/src/config.ts +1 -2
  356. package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +1 -2
  357. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +15 -5
  358. package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +1 -4
  359. package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +4 -9
  360. package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
  361. package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +17 -25
  362. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
  363. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
  364. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
  365. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
  366. package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
  367. package/packages/omo-codex/plugin/components/rules/test/dynamic-target-fingerprints.test.ts +1 -2
  368. package/packages/omo-codex/plugin/components/rules/test/engine.test.ts +7 -4
  369. package/packages/omo-codex/plugin/components/rules/test/finder.test.ts +2 -3
  370. package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +39 -72
  371. package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +38 -3
  372. package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
  373. package/packages/omo-codex/plugin/components/rules/test/matcher.test.ts +2 -3
  374. package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +1 -1
  375. package/packages/omo-codex/plugin/components/rules/test/parser.test.ts +1 -2
  376. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +29 -6
  377. package/packages/omo-codex/plugin/components/rules/test/rules-engine-consumption.test.ts +3 -6
  378. package/packages/omo-codex/plugin/components/rules/test/scanner.test.ts +1 -2
  379. package/packages/omo-codex/plugin/components/rules/test/sources.test.ts +2 -5
  380. package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +2 -17
  381. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  382. package/packages/omo-codex/plugin/components/teammode/package.json +5 -5
  383. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +4 -10
  384. package/packages/omo-codex/plugin/components/telemetry/AGENTS.md +8 -0
  385. package/packages/omo-codex/plugin/components/telemetry/biome.json +2 -2
  386. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2407 -684
  387. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2411 -689
  388. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  389. package/packages/omo-codex/plugin/components/telemetry/package.json +5 -5
  390. package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +1 -4
  391. package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -14
  392. package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +1 -1
  393. package/packages/omo-codex/plugin/components/telemetry/test/diagnostics.test.ts +2 -5
  394. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +10 -4
  395. package/packages/omo-codex/plugin/components/ultrawork/README.md +2 -0
  396. package/packages/omo-codex/plugin/components/ultrawork/agents/explorer.toml +1 -1
  397. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +1 -1
  398. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +1 -1
  399. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
  400. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.toml +1 -1
  401. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
  402. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-low.toml +1 -1
  403. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +1 -1
  404. package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +1 -1
  405. package/packages/omo-codex/plugin/components/ultrawork/agents/metis.toml +1 -1
  406. package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +1 -1
  407. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
  408. package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
  409. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +490 -4
  410. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  411. package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -6
  412. package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +30 -14
  413. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -7
  414. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +31 -7
  415. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
  416. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +5 -5
  417. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +4 -0
  418. package/packages/omo-codex/plugin/components/ultrawork/src/directive.ts +5 -2
  419. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +9 -1
  420. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
  421. package/packages/omo-codex/plugin/components/ultrawork/test/directive-source.test.ts +14 -8
  422. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +12 -1
  423. package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
  424. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +4 -4
  425. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/NOTICE +1 -1
  426. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/README.md +6 -6
  427. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/biome.json +2 -2
  428. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/directive.md +10 -10
  429. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +16 -16
  430. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +16 -0
  431. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/package.json +12 -12
  432. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/boulder-reader.ts +1 -1
  433. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/cli.ts +1 -1
  434. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/codex-hook.ts +4 -4
  435. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/directive.ts +1 -1
  436. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/index.ts +1 -1
  437. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/types.ts +1 -1
  438. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/boulder-reader.test.ts +3 -3
  439. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +4 -11
  440. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +24 -22
  441. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +19 -0
  442. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
  443. package/packages/omo-codex/plugin/components/ulw-loop/README.md +12 -1
  444. package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
  445. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +26 -13
  446. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.d.ts +16 -0
  447. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +25 -0
  448. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +10 -4
  449. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +2 -5
  450. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +5 -78
  451. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.d.ts +12 -0
  452. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +114 -0
  453. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.d.ts +7 -1
  454. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +50 -42
  455. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +2 -2
  456. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +21 -8
  457. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
  458. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +12 -1
  459. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +1 -1
  460. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +40 -37
  461. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +1396 -516
  462. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.d.ts +2 -0
  463. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +28 -8
  464. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +2 -5
  465. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +24 -20
  466. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -0
  467. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +1 -0
  468. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +17 -9
  469. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.d.ts +1 -0
  470. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +13 -4
  471. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
  472. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +34 -4
  473. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +14 -0
  474. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +29 -0
  475. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +7 -0
  476. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +9 -0
  477. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.d.ts +12 -0
  478. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +104 -0
  479. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.d.ts +13 -1
  480. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +65 -9
  481. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +5 -1
  482. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +4 -2
  483. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +72 -117
  484. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.d.ts +2 -0
  485. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +16 -7
  486. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/factory.d.ts +2 -0
  487. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/factory.js +125 -0
  488. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/manifest.d.ts +46 -0
  489. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/manifest.js +28 -0
  490. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/types.d.ts +127 -0
  491. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/types.js +1 -0
  492. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk.d.ts +3 -0
  493. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk.js +3 -0
  494. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.d.ts +6 -1
  495. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +195 -29
  496. package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.d.ts +9 -0
  497. package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.js +227 -0
  498. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +6 -0
  499. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +33 -0
  500. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +20 -6
  501. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +19 -0
  502. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +75 -0
  503. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +17 -4
  504. package/packages/omo-codex/plugin/components/ulw-loop/package.json +6 -6
  505. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +10 -4
  506. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
  507. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +32 -8
  508. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +40 -0
  509. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +8 -6
  510. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +5 -98
  511. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +134 -0
  512. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +52 -73
  513. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +10 -4
  514. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +24 -8
  515. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +14 -1
  516. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +52 -46
  517. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +8 -6
  518. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +35 -7
  519. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +34 -28
  520. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
  521. package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +1 -0
  522. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +19 -9
  523. package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +25 -4
  524. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +39 -4
  525. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +38 -0
  526. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +11 -0
  527. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +123 -0
  528. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +71 -15
  529. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +6 -1
  530. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +92 -136
  531. package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +29 -8
  532. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/factory.ts +159 -0
  533. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/manifest.ts +42 -0
  534. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/types.ts +140 -0
  535. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk.ts +3 -0
  536. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +205 -28
  537. package/packages/omo-codex/plugin/components/ulw-loop/src/state-lock.ts +239 -0
  538. package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +36 -0
  539. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +19 -6
  540. package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +107 -0
  541. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
  542. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +131 -82
  543. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +147 -0
  544. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint.test.ts +16 -22
  545. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +4 -2
  546. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint.test.ts +31 -2
  547. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-commands.test.ts +2 -0
  548. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-complete-goals.test.ts +3 -1
  549. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +35 -8
  550. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +38 -4
  551. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-json-errors.test.ts +27 -0
  552. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-scope-required.test.ts +144 -0
  553. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-status-next-actions.test.ts +185 -0
  554. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +8 -3
  555. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +6 -0
  556. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +37 -2
  557. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +52 -11
  558. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
  559. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/cli-session.ts +4 -0
  560. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +9 -4
  561. package/packages/omo-codex/plugin/components/ulw-loop/test/guided-recovery.test.ts +67 -0
  562. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -37
  563. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +9 -0
  564. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io-cross-process.test.ts +106 -0
  565. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +36 -2
  566. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate-basics.test.ts +258 -0
  567. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-cap-and-dedupe.test.ts +22 -0
  568. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-fields-messages.test.ts +98 -0
  569. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-lazycodex-surface.test.ts +93 -0
  570. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-poisoning-cascades.test.ts +97 -0
  571. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +51 -2
  572. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-senpi-surface.test.ts +131 -0
  573. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-single-report.test.ts +241 -0
  574. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +58 -3
  575. package/packages/omo-codex/plugin/components/ulw-loop/test/review-blockers.test.ts +9 -7
  576. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-contract.test.ts +137 -0
  577. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-session-context.test.ts +148 -0
  578. package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +444 -7
  579. package/packages/omo-codex/plugin/components/ulw-loop/test/state-lock.test.ts +218 -0
  580. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +8 -5
  581. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
  582. package/packages/omo-codex/plugin/components/ulw-loop/test/surface.test.ts +74 -0
  583. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +13 -8
  584. package/packages/omo-codex/plugin/components/ulw-loop/vitest.config.ts +1 -0
  585. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  586. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  587. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  588. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  589. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  590. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  591. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  592. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +18 -0
  593. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  594. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  595. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  596. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  597. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  598. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  599. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  600. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +17 -0
  601. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  602. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  603. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  604. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  605. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  606. package/packages/omo-codex/plugin/model-catalog.json +16 -7
  607. package/packages/omo-codex/plugin/package-lock.json +676 -524
  608. package/packages/omo-codex/plugin/package.json +2 -3
  609. package/packages/omo-codex/plugin/scripts/AGENTS.md +39 -0
  610. package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -2
  611. package/packages/omo-codex/plugin/scripts/auto-update.mjs +0 -9
  612. package/packages/omo-codex/plugin/scripts/canonical-ultrawork-directive.mjs +17 -0
  613. package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +0 -1
  614. package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +16 -7
  615. package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +8 -4
  616. package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +19 -90
  617. package/packages/omo-codex/plugin/scripts/migrate-codex-config/toml-section-editor.mjs +1 -1
  618. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +94 -55
  619. package/packages/omo-codex/plugin/shared/package.json +3 -4
  620. package/packages/omo-codex/plugin/shared/src/config-loader.ts +2 -102
  621. package/packages/omo-codex/plugin/shared/src/config-migration.ts +0 -1
  622. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +41 -130
  623. package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +51 -0
  624. package/packages/omo-codex/plugin/skills/ast-grep/SKILL.md +1 -1
  625. package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +62 -0
  626. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +1 -1
  627. package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
  628. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
  629. package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
  630. package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
  631. package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
  632. package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
  633. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  634. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  635. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +3 -1
  636. package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
  637. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
  638. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
  639. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
  640. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
  641. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
  642. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
  643. package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
  644. package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  645. package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
  646. package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
  647. package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +10 -0
  648. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +15 -8
  649. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +10 -2
  650. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +2 -0
  651. package/packages/omo-codex/plugin/skills/frontend/references/design/ambience-skill.md +145 -0
  652. package/packages/omo-codex/plugin/skills/frontend/references/design/interaction-skill.md +2 -0
  653. package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
  654. package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
  655. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
  656. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  657. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  658. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  659. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
  660. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
  661. package/packages/omo-codex/plugin/skills/git-master/SKILL.md +1 -1
  662. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +18 -16
  663. package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +4 -2
  664. package/packages/omo-codex/plugin/skills/lsp-setup/SKILL.md +1 -1
  665. package/packages/omo-codex/plugin/skills/programming/SKILL.md +1 -1
  666. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +8 -6
  667. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +5 -3
  668. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +114 -422
  669. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
  670. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +26 -9
  671. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  672. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
  673. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +23 -18
  674. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  675. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +26 -13
  676. package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +29 -31
  677. package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
  678. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +34 -4
  679. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
  680. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +32 -8
  681. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -7
  682. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +31 -7
  683. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
  684. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +5 -5
  685. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +12 -5
  686. package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
  687. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +8 -5
  688. package/packages/omo-codex/plugin/test/AGENTS.md +47 -0
  689. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
  690. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +16 -51
  691. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +2 -3
  692. package/packages/omo-codex/plugin/test/aggregate-mcp.test.mjs +2 -7
  693. package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +14 -4
  694. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
  695. package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
  696. package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
  697. package/packages/omo-codex/plugin/test/auto-update.test.mjs +4 -29
  698. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +0 -31
  699. package/packages/omo-codex/plugin/test/canonical-ultrawork-directive.test.mjs +53 -0
  700. package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +2 -2
  701. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +1 -51
  702. package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +88 -2
  703. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +5 -6
  704. package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
  705. package/packages/omo-codex/plugin/test/mcp-research-servers.test.mjs +1 -3
  706. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +35 -35
  707. package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +1 -1
  708. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
  709. package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +107 -15
  710. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +168 -0
  711. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +54 -24
  712. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +18 -119
  713. package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
  714. package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
  715. package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
  716. package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
  717. package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
  718. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +5 -5
  719. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
  720. package/packages/omo-codex/scripts/AGENTS.md +36 -0
  721. package/packages/omo-codex/scripts/check-model-catalog-parity.mjs +42 -0
  722. package/packages/omo-codex/scripts/install-cache-copy.test.mjs +27 -1
  723. package/packages/omo-codex/scripts/install-config-autonomous-features.test.mjs +1 -1
  724. package/packages/omo-codex/scripts/install-config-autonomous.test.mjs +2 -1
  725. package/packages/omo-codex/scripts/install-config-git-bash.test.mjs +0 -23
  726. package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +5 -5
  727. package/packages/omo-codex/scripts/install-config.test.mjs +15 -17
  728. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2987 -1370
  729. package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +3 -4
  730. package/packages/omo-codex/scripts/install-git-bash-mcp-env.test.mjs +1 -25
  731. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
  732. package/packages/omo-codex/scripts/install-mcp-runtime.test.mjs +0 -36
  733. package/packages/omo-codex/scripts/install-packaged-local.test.mjs +1 -6
  734. package/packages/{omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md → prompts-core/prompts/ultrawork/codex.md} +26 -20
  735. package/packages/shared-skills/package.json +7 -1
  736. package/packages/shared-skills/skill-source-filter.d.ts +16 -0
  737. package/packages/shared-skills/skill-source-filter.mjs +44 -0
  738. package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
  739. package/packages/shared-skills/skills/ast-grep/SKILL.md +1 -1
  740. package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
  741. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +1 -1
  742. package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
  743. package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
  744. package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
  745. package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
  746. package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
  747. package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
  748. package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  749. package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  750. package/packages/shared-skills/skills/debugging/SKILL.md +3 -1
  751. package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
  752. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
  753. package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
  754. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
  755. package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
  756. package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
  757. package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
  758. package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
  759. package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
  760. package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  761. package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
  762. package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
  763. package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +10 -0
  764. package/packages/shared-skills/skills/frontend/SKILL.md +15 -8
  765. package/packages/shared-skills/skills/frontend/references/design/README.md +10 -2
  766. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +2 -0
  767. package/packages/shared-skills/skills/frontend/references/design/ambience-skill.md +145 -0
  768. package/packages/shared-skills/skills/frontend/references/design/interaction-skill.md +2 -0
  769. package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
  770. package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
  771. package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
  772. package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  773. package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  774. package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  775. package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
  776. package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
  777. package/packages/shared-skills/skills/git-master/SKILL.md +1 -1
  778. package/packages/shared-skills/skills/init-deep/SKILL.md +14 -14
  779. package/packages/shared-skills/skills/lsp-setup/SKILL.md +1 -1
  780. package/packages/shared-skills/skills/programming/SKILL.md +1 -1
  781. package/packages/shared-skills/skills/refactor/SKILL.md +4 -4
  782. package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +1 -1
  783. package/packages/shared-skills/skills/review-work/SKILL.md +101 -419
  784. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
  785. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +26 -9
  786. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  787. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
  788. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +23 -18
  789. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  790. package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +20 -19
  791. package/packages/shared-skills/skills/ulw-plan/SKILL.md +7 -8
  792. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
  793. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
  794. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
  795. package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  796. package/packages/shared-skills/skills/ulw-research/SKILL.md +8 -3
  797. package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
  798. package/packages/shared-skills/skills/visual-qa/SKILL.md +4 -3
  799. package/postinstall.mjs +2 -0
  800. package/script/qa/web-terminal-visual-qa.mjs +2 -0
  801. package/script/qa/xterm-live-terminal.mjs +18 -2
  802. package/dist/config/schema/codegraph.d.ts +0 -12
  803. package/dist/config/schema/start-work.d.ts +0 -5
  804. package/dist/features/builtin-commands/templates/start-work.d.ts +0 -1
  805. package/dist/features/builtin-skills/index.d.ts +0 -1
  806. package/dist/features/builtin-skills/skill-file-loader.d.ts +0 -1
  807. package/dist/features/builtin-skills/skills/agent-browser-skill.d.ts +0 -1
  808. package/dist/features/builtin-skills/skills/agent-browser-template.d.ts +0 -1
  809. package/dist/features/builtin-skills/skills/debugging.d.ts +0 -1
  810. package/dist/features/builtin-skills/skills/dev-browser.d.ts +0 -1
  811. package/dist/features/builtin-skills/skills/frontend.d.ts +0 -1
  812. package/dist/features/builtin-skills/skills/git-master-sections/commit-atomic-planning.d.ts +0 -1
  813. package/dist/features/builtin-skills/skills/git-master-sections/commit-context-analysis.d.ts +0 -1
  814. package/dist/features/builtin-skills/skills/git-master-sections/commit-execution-verification.d.ts +0 -1
  815. package/dist/features/builtin-skills/skills/git-master-sections/commit-workflow.d.ts +0 -1
  816. package/dist/features/builtin-skills/skills/git-master-sections/history-search-workflow.d.ts +0 -1
  817. package/dist/features/builtin-skills/skills/git-master-sections/overview.d.ts +0 -1
  818. package/dist/features/builtin-skills/skills/git-master-sections/quick-reference.d.ts +0 -1
  819. package/dist/features/builtin-skills/skills/git-master-sections/rebase-workflow.d.ts +0 -1
  820. package/dist/features/builtin-skills/skills/git-master-skill-metadata.d.ts +0 -1
  821. package/dist/features/builtin-skills/skills/git-master.d.ts +0 -1
  822. package/dist/features/builtin-skills/skills/index.d.ts +0 -1
  823. package/dist/features/builtin-skills/skills/init-deep.d.ts +0 -1
  824. package/dist/features/builtin-skills/skills/playwright-cli.d.ts +0 -1
  825. package/dist/features/builtin-skills/skills/playwright-mcp-skill.d.ts +0 -1
  826. package/dist/features/builtin-skills/skills/playwright.d.ts +0 -1
  827. package/dist/features/builtin-skills/skills/remove-ai-slops.d.ts +0 -1
  828. package/dist/features/builtin-skills/skills/review-work.d.ts +0 -1
  829. package/dist/features/builtin-skills/skills/security-research.d.ts +0 -1
  830. package/dist/features/builtin-skills/skills/security-review.d.ts +0 -1
  831. package/dist/features/builtin-skills/skills/team-mode.d.ts +0 -1
  832. package/dist/features/builtin-skills/skills/visual-qa.d.ts +0 -1
  833. package/dist/features/builtin-skills/skills.d.ts +0 -1
  834. package/dist/features/builtin-skills/types.d.ts +0 -1
  835. package/dist/features/claude-code-plugin-loader/agent-loader.d.ts +0 -1
  836. package/dist/features/claude-code-plugin-loader/command-loader.d.ts +0 -1
  837. package/dist/features/claude-code-plugin-loader/discovery-core.d.ts +0 -1
  838. package/dist/features/claude-code-plugin-loader/discovery-paths.d.ts +0 -1
  839. package/dist/features/claude-code-plugin-loader/discovery.d.ts +0 -1
  840. package/dist/features/claude-code-plugin-loader/hook-loader.d.ts +0 -1
  841. package/dist/features/claude-code-plugin-loader/index.d.ts +0 -1
  842. package/dist/features/claude-code-plugin-loader/install-path-resolver.d.ts +0 -1
  843. package/dist/features/claude-code-plugin-loader/installed-plugin-database.d.ts +0 -1
  844. package/dist/features/claude-code-plugin-loader/loaded-plugin.d.ts +0 -1
  845. package/dist/features/claude-code-plugin-loader/loader.d.ts +0 -1
  846. package/dist/features/claude-code-plugin-loader/mcp-server-loader.d.ts +0 -1
  847. package/dist/features/claude-code-plugin-loader/plugin-key.d.ts +0 -1
  848. package/dist/features/claude-code-plugin-loader/plugin-manifest.d.ts +0 -1
  849. package/dist/features/claude-code-plugin-loader/plugin-path-resolver.d.ts +0 -1
  850. package/dist/features/claude-code-plugin-loader/plugin-settings.d.ts +0 -1
  851. package/dist/features/claude-code-plugin-loader/scope-filter.d.ts +0 -1
  852. package/dist/features/claude-code-plugin-loader/skill-loader.d.ts +0 -1
  853. package/dist/features/claude-code-plugin-loader/types.d.ts +0 -1
  854. package/dist/hooks/codegraph-bootstrap/command-runner.d.ts +0 -17
  855. package/dist/hooks/codegraph-bootstrap/hook.d.ts +0 -35
  856. package/dist/hooks/codegraph-bootstrap/index.d.ts +0 -1
  857. package/dist/hooks/codegraph-bootstrap/project-root.d.ts +0 -1
  858. package/dist/hooks/codegraph-bootstrap/status.d.ts +0 -11
  859. package/dist/hooks/ralph-loop/completion-promise-detector-test-input.d.ts +0 -11
  860. package/dist/hooks/ralph-loop/loop-session-recovery.d.ts +0 -7
  861. package/dist/hooks/start-work/start-work-hook.d.ts +0 -23
  862. package/dist/mcp/codegraph.d.ts +0 -16
  863. package/dist/plugin/chat-message/start-work-message.d.ts +0 -5
  864. package/dist/shared/prompt-async-gate/message-inspection-error.d.ts +0 -1
  865. package/dist/shared/prompt-async-gate/pending-tool-turn.d.ts +0 -1
  866. package/dist/shared/prompt-async-gate/prompt-message-state.d.ts +0 -1
  867. package/dist/shared/prompt-async-gate/queue.d.ts +0 -1
  868. package/dist/shared/prompt-async-gate/recent-dispatches.d.ts +0 -1
  869. package/dist/shared/prompt-async-gate/reservations.d.ts +0 -1
  870. package/dist/shared/prompt-async-gate/semantic-dedupe.d.ts +0 -1
  871. package/dist/shared/prompt-async-gate/session-idle-dispatch.d.ts +0 -1
  872. package/dist/shared/prompt-async-gate/timing.d.ts +0 -1
  873. package/dist/shared/prompt-async-gate/types.d.ts +0 -1
  874. package/dist/skills/data-scientist/references/common-scenarios.md +0 -176
  875. package/dist/skills/data-scientist/references/execution-templates.md +0 -197
  876. package/dist/skills/data-scientist/references/integration-patterns.md +0 -153
  877. package/dist/skills/data-scientist/references/performance-benchmarks.md +0 -37
  878. package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
  879. package/dist/tools/call-omo-agent/message-storage-directory.d.ts +0 -1
  880. package/dist/tools/delegate-task/anthropic-categories.d.ts +0 -2
  881. package/dist/tools/delegate-task/model-string-parser.d.ts +0 -1
  882. package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts +0 -1
  883. package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts +0 -1
  884. package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts +0 -1
  885. package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.d.ts +0 -1
  886. package/packages/lsp-tools-mcp/dist/missing-dependency-result.d.ts +0 -1
  887. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +0 -58
  888. package/packages/omo-codex/plugin/components/codegraph/NODE-RUNTIME-LICENSES.md +0 -2951
  889. package/packages/omo-codex/plugin/components/codegraph/NOTICE +0 -16
  890. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +0 -12149
  891. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +0 -9747
  892. package/packages/omo-codex/plugin/components/codegraph/package.json +0 -33
  893. package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +0 -29
  894. package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +0 -79
  895. package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +0 -33
  896. package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +0 -25
  897. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +0 -131
  898. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +0 -258
  899. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +0 -309
  900. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +0 -80
  901. package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +0 -34
  902. package/packages/omo-codex/plugin/components/codegraph/src/serve-invocation.ts +0 -29
  903. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +0 -263
  904. package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +0 -106
  905. package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +0 -145
  906. package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +0 -21
  907. package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +0 -139
  908. package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +0 -15
  909. package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +0 -32
  910. package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +0 -109
  911. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +0 -148
  912. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +0 -175
  913. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +0 -81
  914. package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +0 -34
  915. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +0 -112
  916. package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +0 -26
  917. package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +0 -160
  918. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +0 -50
  919. package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +0 -29
  920. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +0 -320
  921. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +0 -172
  922. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +0 -91
  923. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +0 -100
  924. package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +0 -76
  925. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +0 -133
  926. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +0 -245
  927. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +0 -69
  928. package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +0 -43
  929. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +0 -147
  930. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +0 -175
  931. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +0 -385
  932. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +0 -206
  933. package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +0 -58
  934. package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +0 -104
  935. package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +0 -65
  936. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-availability.test.ts +0 -106
  937. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +0 -116
  938. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +0 -258
  939. package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +0 -56
  940. package/packages/omo-codex/plugin/components/codegraph/tsconfig.build.json +0 -13
  941. package/packages/omo-codex/plugin/components/codegraph/tsconfig.json +0 -25
  942. package/packages/omo-codex/plugin/components/start-work-continuation/LICENSE +0 -21
  943. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
  944. package/packages/omo-codex/plugin/components/ultrawork/directive.md +0 -471
  945. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +0 -18
  946. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +0 -17
  947. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
  948. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
  949. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/editor.mjs +0 -125
  950. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/jsonc.mjs +0 -43
  951. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/scaffold.mjs +0 -29
  952. package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +0 -121
  953. package/packages/omo-codex/plugin/skills/data-scientist/references/common-scenarios.md +0 -176
  954. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-templates.md +0 -197
  955. package/packages/omo-codex/plugin/skills/data-scientist/references/integration-patterns.md +0 -153
  956. package/packages/omo-codex/plugin/skills/data-scientist/references/performance-benchmarks.md +0 -37
  957. package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
  958. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
  959. package/packages/omo-codex/plugin/test/component-codegraph-mcp-smoke.test.mjs +0 -76
  960. package/packages/omo-codex/plugin/test/migrate-omo-sot.test.mjs +0 -179
  961. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
  962. package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
  963. package/packages/shared-skills/skills/data-scientist/references/common-scenarios.md +0 -176
  964. package/packages/shared-skills/skills/data-scientist/references/execution-templates.md +0 -197
  965. package/packages/shared-skills/skills/data-scientist/references/integration-patterns.md +0 -153
  966. package/packages/shared-skills/skills/data-scientist/references/performance-benchmarks.md +0 -37
  967. /package/dist/hooks/{start-work → ulw-execute}/context-info-formatters.d.ts +0 -0
  968. /package/dist/hooks/{start-work → ulw-execute}/explicit-plan-context.d.ts +0 -0
  969. /package/dist/hooks/{start-work → ulw-execute}/notepad-scaffold.d.ts +0 -0
  970. /package/dist/hooks/{start-work → ulw-execute}/parse-user-request.d.ts +0 -0
  971. /package/dist/hooks/{start-work → ulw-execute}/plan-discovery-context.d.ts +0 -0
  972. /package/dist/hooks/{start-work → ulw-execute}/plan-selection.d.ts +0 -0
  973. /package/dist/hooks/{start-work → ulw-execute}/session-plan-affinity.d.ts +0 -0
  974. /package/dist/hooks/{start-work → ulw-execute}/work-initializer.d.ts +0 -0
  975. /package/dist/hooks/{start-work → ulw-execute}/worktree-block.d.ts +0 -0
  976. /package/dist/hooks/{start-work → ulw-execute}/worktree-detector.d.ts +0 -0
  977. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/.gitattributes +0 -0
  978. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/CHANGELOG.md +0 -0
  979. /package/packages/omo-codex/plugin/components/{codegraph → ulw-execute-continuation}/LICENSE +0 -0
  980. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/plan-checklist.ts +0 -0
  981. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
  982. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
  983. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
  984. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
  985. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
  986. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
  987. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
  988. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
  989. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
  990. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
@@ -1,7 +1,11 @@
1
+ // src/client.ts
2
+ import { statSync as statSync5 } from "node:fs";
3
+ import { isAbsolute as isAbsolute6 } from "node:path";
4
+
1
5
  // src/daemon-client.ts
2
6
  import { connect } from "node:net";
3
7
  import { homedir as homedir3 } from "node:os";
4
- import { join as join7 } from "node:path";
8
+ import { join as join8 } from "node:path";
5
9
 
6
10
  // ../lsp-core/src/request-context.ts
7
11
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -10,18 +14,17 @@ import { homedir } from "node:os";
10
14
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
11
15
 
12
16
  class LspRequestContextParseError extends Error {
13
- code;
14
- name = "LspRequestContextParseError";
15
17
  constructor(code, message) {
16
18
  super(message);
17
19
  this.code = code;
20
+ this.name = "LspRequestContextParseError";
18
21
  }
19
22
  }
20
23
 
21
24
  class LspRequestContextUnavailableError extends Error {
22
- name = "LspRequestContextUnavailableError";
23
25
  constructor() {
24
26
  super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
27
+ this.name = "LspRequestContextUnavailableError";
25
28
  }
26
29
  }
27
30
  var storage = new AsyncLocalStorage;
@@ -41,7 +44,7 @@ function contextCwd() {
41
44
  }
42
45
  function createStandaloneMcpRequestContext(input = {}) {
43
46
  const env = input.env ?? process.env;
44
- const cwd = canonicalCwd(input.cwd ?? process.cwd());
47
+ const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
45
48
  const home = input.homeDir ?? homedir();
46
49
  const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
47
50
  const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
@@ -179,7 +182,6 @@ function isPlainRecord(value) {
179
182
 
180
183
  // src/daemon-request-error.ts
181
184
  class DaemonRequestError extends Error {
182
- requestWritten;
183
185
  constructor(message, requestWritten) {
184
186
  super(message);
185
187
  this.name = "DaemonRequestError";
@@ -202,7 +204,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
202
204
  }
203
205
 
204
206
  class DaemonRequestTimedOutError extends DaemonRequestError {
205
- timeoutMs;
206
207
  constructor(requestWritten, timeoutMs) {
207
208
  super("daemon request timed out", requestWritten);
208
209
  this.name = "DaemonRequestTimedOutError";
@@ -281,14 +282,12 @@ var PROTOCOL_ERROR_CODE = -32002;
281
282
  var AUTH_TOKEN_BYTES = 32;
282
283
 
283
284
  class UnsafePrivateDirectoryError extends Error {
284
- path;
285
- reason;
286
- name = "UnsafePrivateDirectoryError";
287
- code = "unsafe_private_directory";
288
285
  constructor(path, reason) {
289
286
  super(`unsafe private directory ${path}: ${reason}`);
290
287
  this.path = path;
291
288
  this.reason = reason;
289
+ this.name = "UnsafePrivateDirectoryError";
290
+ this.code = "unsafe_private_directory";
292
291
  }
293
292
  }
294
293
  function authEnvelope(token) {
@@ -472,20 +471,18 @@ var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
472
471
  var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
473
472
 
474
473
  class InvalidRuntimeOverrideError extends Error {
475
- code = "invalid_runtime_override";
476
- reason;
477
474
  constructor(reason, message) {
478
475
  super(message);
476
+ this.code = "invalid_runtime_override";
479
477
  this.name = "InvalidRuntimeOverrideError";
480
478
  this.reason = reason;
481
479
  }
482
480
  }
483
481
 
484
482
  class InvalidDaemonVersionError extends Error {
485
- code = "invalid_daemon_version";
486
- version;
487
483
  constructor(version) {
488
484
  super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
485
+ this.code = "invalid_daemon_version";
489
486
  this.name = "InvalidDaemonVersionError";
490
487
  this.version = version;
491
488
  }
@@ -531,10 +528,9 @@ var requireFromHere = createRequire(import.meta.url);
531
528
  var MAX_SOCKET_PATH_LENGTH = 100;
532
529
 
533
530
  class InvalidDaemonDirectoryError extends Error {
534
- code = "invalid_daemon_directory";
535
- directory;
536
531
  constructor(directory) {
537
532
  super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
533
+ this.code = "invalid_daemon_directory";
538
534
  this.name = "InvalidDaemonDirectoryError";
539
535
  this.directory = directory;
540
536
  }
@@ -688,7 +684,7 @@ async function probeDaemon(paths, timeoutMs = PROBE_TIMEOUT_MS, signal) {
688
684
  return await pingDaemon(paths, token, timeoutMs, signal) !== null;
689
685
  }
690
686
  function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
691
- return new Promise((resolve2) => {
687
+ return new Promise((resolve) => {
692
688
  const socket = new Socket;
693
689
  let settled = false;
694
690
  let timer;
@@ -700,7 +696,7 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
700
696
  clearTimeout(timer);
701
697
  signal?.removeEventListener("abort", onAbort);
702
698
  socket.destroy();
703
- resolve2(value);
699
+ resolve(value);
704
700
  };
705
701
  const onAbort = () => finish(null);
706
702
  const decoder = createLineDecoder((message) => {
@@ -723,13 +719,17 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
723
719
  socket.connect(paths.socket);
724
720
  });
725
721
  }
726
- function spawnDaemonProcess(paths) {
722
+ function spawnDaemonProcess(paths, deps = {}) {
727
723
  mkdirSync2(dirname3(paths.log), { recursive: true });
728
724
  const logFd = openSync2(paths.log, "a");
729
725
  try {
730
- const child = spawn(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
726
+ const spawnDaemonChild = deps.spawn ?? spawn;
727
+ const executable = deps.resolveExecutable?.() ?? resolveDaemonNodeExecutable();
728
+ const child = spawnDaemonChild(executable, [paths.cliPath, "daemon"], {
731
729
  detached: true,
732
- stdio: ["ignore", logFd, logFd]
730
+ stdio: ["ignore", logFd, logFd],
731
+ windowsHide: true,
732
+ env: { ...process.env, BUN_BE_BUN: "1" }
733
733
  });
734
734
  child.once("spawn", () => closeSync2(logFd));
735
735
  child.once("error", (error) => {
@@ -759,7 +759,7 @@ function defaultEnsureDaemonDeps() {
759
759
  };
760
760
  }
761
761
  function sleepWithSignal(ms, signal) {
762
- return new Promise((resolve2) => {
762
+ return new Promise((resolve) => {
763
763
  let settled = false;
764
764
  const finish = () => {
765
765
  if (settled)
@@ -767,7 +767,7 @@ function sleepWithSignal(ms, signal) {
767
767
  settled = true;
768
768
  clearTimeout(timer);
769
769
  signal?.removeEventListener("abort", finish);
770
- resolve2();
770
+ resolve();
771
771
  };
772
772
  const timer = setTimeout(finish, ms);
773
773
  if (signal?.aborted) {
@@ -782,7 +782,7 @@ function awaitWithSignal(promise, signal) {
782
782
  return promise;
783
783
  if (signal.aborted)
784
784
  return Promise.reject(abortError(signal));
785
- return new Promise((resolve2, reject) => {
785
+ return new Promise((resolve, reject) => {
786
786
  let settled = false;
787
787
  const finish = (run) => {
788
788
  if (settled)
@@ -793,7 +793,7 @@ function awaitWithSignal(promise, signal) {
793
793
  };
794
794
  const onAbort = () => finish(() => reject(abortError(signal)));
795
795
  signal.addEventListener("abort", onAbort, { once: true });
796
- promise.then((value) => finish(() => resolve2(value)), (error) => finish(() => reject(error)));
796
+ promise.then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error)));
797
797
  });
798
798
  }
799
799
  function throwIfAborted(signal) {
@@ -822,18 +822,18 @@ function parsePingResponse(message) {
822
822
  return null;
823
823
  if (!endpoint || typeof endpoint !== "object" || Array.isArray(endpoint))
824
824
  return null;
825
- const path2 = Reflect.get(endpoint, "path");
825
+ const path = Reflect.get(endpoint, "path");
826
826
  const kind = Reflect.get(endpoint, "kind");
827
- if (typeof path2 !== "string")
827
+ if (typeof path !== "string")
828
828
  return null;
829
829
  if (kind === "windows")
830
- return { pid, nonce, startedAt, endpoint: { kind, path: path2 } };
830
+ return { pid, nonce, startedAt, endpoint: { kind, path } };
831
831
  if (kind === "missing")
832
- return { pid, nonce, startedAt, endpoint: { kind, path: path2 } };
832
+ return { pid, nonce, startedAt, endpoint: { kind, path } };
833
833
  const dev = Reflect.get(endpoint, "dev");
834
834
  const ino = Reflect.get(endpoint, "ino");
835
835
  if (kind === "unix" && typeof dev === "number" && typeof ino === "number") {
836
- return { pid, nonce, startedAt, endpoint: { kind, path: path2, dev, ino } };
836
+ return { pid, nonce, startedAt, endpoint: { kind, path, dev, ino } };
837
837
  }
838
838
  return null;
839
839
  }
@@ -881,7 +881,7 @@ ${body}` : `${body}
881
881
  await writeChunk(output, payload);
882
882
  }
883
883
  function writeChunk(output, chunk) {
884
- return new Promise((resolve2, reject) => {
884
+ return new Promise((resolve, reject) => {
885
885
  let settled = false;
886
886
  const onError = (error) => {
887
887
  if (settled)
@@ -901,7 +901,7 @@ function writeChunk(output, chunk) {
901
901
  return;
902
902
  }
903
903
  output.removeListener("error", onError);
904
- resolve2();
904
+ resolve();
905
905
  });
906
906
  } catch (error) {
907
907
  output.removeListener("error", onError);
@@ -1010,6 +1010,7 @@ async function runJsonRpcStdioServer(config) {
1010
1010
  const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
1011
1011
  isClosed = true;
1012
1012
  config.onIdleTimeout?.();
1013
+ config.input.destroy();
1013
1014
  });
1014
1015
  const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
1015
1016
  isClosed = true;
@@ -1106,7 +1107,11 @@ function createParentWatchdog(config, onDeadParent) {
1106
1107
  const probeAlive = config.probeAlive ?? isProcessAlive;
1107
1108
  let fired = false;
1108
1109
  const timer = setInterval(() => {
1109
- if (fired || probeAlive(parentPid))
1110
+ if (fired)
1111
+ return;
1112
+ const alive = probeAlive(parentPid);
1113
+ config.onPoll?.(alive);
1114
+ if (alive)
1110
1115
  return;
1111
1116
  fired = true;
1112
1117
  onDeadParent(parentPid, pollIntervalMs);
@@ -1141,8 +1146,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
1141
1146
  };
1142
1147
  }
1143
1148
  // ../lsp-core/src/lsp/client-wrapper.ts
1144
- import { existsSync as existsSync10, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
1145
- import { basename as basename3, dirname as dirname8, join as join4, resolve as resolve7 } from "node:path";
1149
+ import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
1150
+ import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
1146
1151
 
1147
1152
  // ../lsp-core/src/lsp/effective-extension.ts
1148
1153
  import { basename as basename2, extname } from "node:path";
@@ -1156,22 +1161,15 @@ function effectiveExtension(filePath) {
1156
1161
 
1157
1162
  // ../lsp-core/src/lsp/errors.ts
1158
1163
  class LspConnectionClosedError extends Error {
1159
- serverId;
1160
- root;
1161
- name = "LspConnectionClosedError";
1162
1164
  constructor(serverId, root, message) {
1163
1165
  super(message ?? `LSP connection closed for ${serverId} at ${root}`);
1164
1166
  this.serverId = serverId;
1165
1167
  this.root = root;
1168
+ this.name = "LspConnectionClosedError";
1166
1169
  }
1167
1170
  }
1168
1171
 
1169
1172
  class LspProcessExitedError extends Error {
1170
- serverId;
1171
- root;
1172
- exitCode;
1173
- stderrTail;
1174
- name = "LspProcessExitedError";
1175
1173
  constructor(serverId, root, exitCode, stderrTail) {
1176
1174
  const stderrSuffix = stderrTail ? `
1177
1175
  stderr tail: ${stderrTail}` : "";
@@ -1180,46 +1178,59 @@ stderr tail: ${stderrTail}` : "";
1180
1178
  this.root = root;
1181
1179
  this.exitCode = exitCode;
1182
1180
  this.stderrTail = stderrTail;
1181
+ this.name = "LspProcessExitedError";
1183
1182
  }
1184
1183
  }
1185
1184
 
1186
1185
  class LspRequestTimeoutError extends Error {
1187
- method;
1188
- stderrTail;
1189
- name = "LspRequestTimeoutError";
1190
1186
  constructor(method, stderrTail) {
1191
1187
  const stderrSuffix = stderrTail ? `
1192
1188
  recent stderr: ${stderrTail}` : "";
1193
1189
  super(`LSP request timeout (method: ${method})${stderrSuffix}`);
1194
1190
  this.method = method;
1195
1191
  this.stderrTail = stderrTail;
1192
+ this.name = "LspRequestTimeoutError";
1196
1193
  }
1197
1194
  }
1198
1195
 
1199
1196
  class LspInvalidPathError extends Error {
1200
- name = "LspInvalidPathError";
1197
+ constructor() {
1198
+ super(...arguments);
1199
+ this.name = "LspInvalidPathError";
1200
+ }
1201
1201
  }
1202
1202
 
1203
1203
  class LspServerLookupError extends Error {
1204
- lookup;
1205
- name = "LspServerLookupError";
1206
1204
  constructor(message, lookup) {
1207
1205
  super(message);
1208
1206
  this.lookup = lookup;
1207
+ this.name = "LspServerLookupError";
1209
1208
  }
1210
1209
  }
1211
1210
 
1212
1211
  class LspServerInitializingError extends Error {
1213
- originalError;
1214
- name = "LspServerInitializingError";
1215
1212
  constructor(originalError) {
1216
1213
  super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
1217
1214
  this.originalError = originalError;
1215
+ this.name = "LspServerInitializingError";
1218
1216
  }
1219
1217
  }
1220
1218
 
1221
1219
  class LspProcessSpawnError extends Error {
1222
- name = "LspProcessSpawnError";
1220
+ constructor() {
1221
+ super(...arguments);
1222
+ this.name = "LspProcessSpawnError";
1223
+ }
1224
+ }
1225
+
1226
+ class LspClientRespawnBudgetExceededError extends Error {
1227
+ constructor(serverId, root, retryLimit) {
1228
+ super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
1229
+ this.serverId = serverId;
1230
+ this.root = root;
1231
+ this.retryLimit = retryLimit;
1232
+ this.name = "LspClientRespawnBudgetExceededError";
1233
+ }
1223
1234
  }
1224
1235
  function isLspDeadConnectionError(err) {
1225
1236
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
@@ -1242,6 +1253,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
1242
1253
  // ../lsp-core/src/lsp/connection.ts
1243
1254
  import { pathToFileURL } from "node:url";
1244
1255
 
1256
+ // ../lsp-core/src/lsp/timer-provider.ts
1257
+ var realTimerProvider = {
1258
+ now: () => Date.now(),
1259
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
1260
+ clearTimeout: (handle) => clearTimeout(handle)
1261
+ };
1262
+
1245
1263
  // ../lsp-core/src/lsp/constants.ts
1246
1264
  var DEFAULT_MAX_REFERENCES = 200;
1247
1265
  var DEFAULT_MAX_SYMBOLS = 200;
@@ -1250,9 +1268,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
1250
1268
  var REQUEST_TIMEOUT_MS = 15000;
1251
1269
  var INIT_TIMEOUT_MS = 60000;
1252
1270
  var IDLE_TIMEOUT_MS = 5 * 60000;
1271
+ var MAX_RESIDENT_CLIENTS = 6;
1253
1272
  var REAPER_INTERVAL_MS = 60000;
1254
1273
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
1255
1274
  var STOP_SIGKILL_GRACE_MS = 1000;
1275
+ var CLIENT_RESPAWN_RETRY_LIMIT = 2;
1276
+ var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
1256
1277
 
1257
1278
  // ../lsp-core/src/lsp/json-rpc-connection.ts
1258
1279
  var HEADER_SEPARATOR2 = `\r
@@ -1264,20 +1285,31 @@ var METHOD_NOT_FOUND = -32601;
1264
1285
  var INTERNAL_ERROR = -32603;
1265
1286
 
1266
1287
  class JsonRpcConnection {
1267
- reader;
1268
- writer;
1269
- pendingRequests = new Map;
1270
- notificationHandlers = new Map;
1271
- requestHandlers = new Map;
1272
- closeHandlers = [];
1273
- errorHandlers = [];
1274
- inputBuffer = Buffer.alloc(0);
1275
- nextRequestId = 1;
1276
- listening = false;
1277
- disposed = false;
1278
1288
  constructor(reader, writer) {
1279
1289
  this.reader = reader;
1280
1290
  this.writer = writer;
1291
+ this.pendingRequests = new Map;
1292
+ this.notificationHandlers = new Map;
1293
+ this.requestHandlers = new Map;
1294
+ this.closeHandlers = [];
1295
+ this.errorHandlers = [];
1296
+ this.inputBuffer = Buffer.alloc(0);
1297
+ this.nextRequestId = 1;
1298
+ this.listening = false;
1299
+ this.disposed = false;
1300
+ this.handleData = (chunk) => {
1301
+ const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
1302
+ this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
1303
+ this.drainInputBuffer();
1304
+ };
1305
+ this.handleClose = () => {
1306
+ for (const handler of this.closeHandlers) {
1307
+ handler();
1308
+ }
1309
+ };
1310
+ this.handleStreamError = (error) => {
1311
+ this.emitError(error);
1312
+ };
1281
1313
  }
1282
1314
  listen() {
1283
1315
  if (this.listening)
@@ -1312,7 +1344,8 @@ class JsonRpcConnection {
1312
1344
  let cancelAfterWrite = false;
1313
1345
  let settled = false;
1314
1346
  const writeCancel = () => this.writeMessage({ jsonrpc: "2.0", method: "$/cancelRequest", params: { id } });
1315
- const responsePromise = new Promise((resolve2, reject) => {
1347
+ let rejectAfterCancelWrite;
1348
+ const responsePromise = new Promise((resolve, reject) => {
1316
1349
  const cleanup = () => {
1317
1350
  options.signal?.removeEventListener("abort", onAbort);
1318
1351
  };
@@ -1323,22 +1356,26 @@ class JsonRpcConnection {
1323
1356
  this.pendingRequests.delete(key);
1324
1357
  cleanup();
1325
1358
  const rejectCancelled = () => reject(abortError2(options.signal));
1359
+ rejectAfterCancelWrite = async () => {
1360
+ try {
1361
+ await writeCancel();
1362
+ } catch (error) {
1363
+ this.emitError(toError(error));
1364
+ }
1365
+ rejectCancelled();
1366
+ };
1326
1367
  if (!requestWritten) {
1327
1368
  cancelAfterWrite = true;
1328
- rejectCancelled();
1329
1369
  return;
1330
1370
  }
1331
- writeCancel().then(rejectCancelled, (error) => {
1332
- this.emitError(toError(error));
1333
- rejectCancelled();
1334
- });
1371
+ rejectAfterCancelWrite();
1335
1372
  };
1336
1373
  const onAbort = () => settleCancel();
1337
1374
  this.pendingRequests.set(key, {
1338
1375
  resolve(result) {
1339
1376
  settled = true;
1340
1377
  cleanup();
1341
- resolve2(result);
1378
+ resolve(result);
1342
1379
  },
1343
1380
  reject(error) {
1344
1381
  settled = true;
@@ -1359,7 +1396,7 @@ class JsonRpcConnection {
1359
1396
  await this.writeMessage(message);
1360
1397
  requestWritten = true;
1361
1398
  if (cancelAfterWrite)
1362
- await writeCancel();
1399
+ await rejectAfterCancelWrite?.();
1363
1400
  } catch (error) {
1364
1401
  if (settled)
1365
1402
  return responsePromise;
@@ -1398,19 +1435,6 @@ class JsonRpcConnection {
1398
1435
  this.notificationHandlers.clear();
1399
1436
  this.requestHandlers.clear();
1400
1437
  }
1401
- handleData = (chunk) => {
1402
- const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
1403
- this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
1404
- this.drainInputBuffer();
1405
- };
1406
- handleClose = () => {
1407
- for (const handler of this.closeHandlers) {
1408
- handler();
1409
- }
1410
- };
1411
- handleStreamError = (error) => {
1412
- this.emitError(error);
1413
- };
1414
1438
  drainInputBuffer() {
1415
1439
  while (true) {
1416
1440
  const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
@@ -1510,13 +1534,13 @@ class JsonRpcConnection {
1510
1534
  const payload = `Content-Length: ${Buffer.byteLength(body, "utf8")}\r
1511
1535
  \r
1512
1536
  ${body}`;
1513
- return new Promise((resolve2, reject) => {
1537
+ return new Promise((resolve, reject) => {
1514
1538
  this.writer.write(payload, (error) => {
1515
1539
  if (error) {
1516
1540
  reject(error);
1517
1541
  return;
1518
1542
  }
1519
- resolve2();
1543
+ resolve();
1520
1544
  });
1521
1545
  });
1522
1546
  }
@@ -1603,9 +1627,9 @@ function validateCwd(cwd) {
1603
1627
  }
1604
1628
  }
1605
1629
  function wrap(proc) {
1606
- const exitedPromise = new Promise((resolve2) => {
1607
- proc.once("close", (code) => resolve2(code ?? 0));
1608
- proc.once("error", () => resolve2(1));
1630
+ const exitedPromise = new Promise((resolve) => {
1631
+ proc.once("close", (code) => resolve(code ?? 0));
1632
+ proc.once("error", () => resolve(1));
1609
1633
  });
1610
1634
  if (!proc.stdin || !proc.stdout || !proc.stderr) {
1611
1635
  throw new LspProcessSpawnError("Spawned process is missing one of stdin/stdout/stderr pipes");
@@ -1758,33 +1782,29 @@ function isPosition(value) {
1758
1782
 
1759
1783
  // ../lsp-core/src/lsp/transport.ts
1760
1784
  class LspClientNotStartedError extends Error {
1761
- serverId;
1762
- root;
1763
- name = "LspClientNotStartedError";
1764
1785
  constructor(serverId, root) {
1765
1786
  super("LSP client not started");
1766
1787
  this.serverId = serverId;
1767
1788
  this.root = root;
1789
+ this.name = "LspClientNotStartedError";
1768
1790
  }
1769
1791
  }
1770
1792
 
1771
1793
  class LspClientTransport {
1772
- root;
1773
- server;
1774
- proc = null;
1775
- connection = null;
1776
- stderrBuffer = [];
1777
- processExited = false;
1778
- diagnosticsStore = new Map;
1779
- requestTimeoutMs;
1780
- initializeTimeoutMs;
1781
- workspaceApplyEditHandler = null;
1782
- diagnosticPullSupported = false;
1783
- constructor(root, server2, timeouts = {}) {
1794
+ constructor(root, server, timeouts = {}) {
1784
1795
  this.root = root;
1785
- this.server = server2;
1796
+ this.server = server;
1797
+ this.proc = null;
1798
+ this.connection = null;
1799
+ this.stderrBuffer = [];
1800
+ this.processExited = false;
1801
+ this.diagnosticsStore = new Map;
1802
+ this.workspaceApplyEditHandler = null;
1803
+ this.diagnosticPullSupported = false;
1804
+ this.documentFormattingSupported = false;
1786
1805
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
1787
1806
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
1807
+ this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
1788
1808
  }
1789
1809
  pid() {
1790
1810
  return this.proc?.pid;
@@ -1804,6 +1824,12 @@ class LspClientTransport {
1804
1824
  isDiagnosticPullSupported() {
1805
1825
  return this.diagnosticPullSupported;
1806
1826
  }
1827
+ setDocumentFormattingSupported(supported) {
1828
+ this.documentFormattingSupported = supported;
1829
+ }
1830
+ isDocumentFormattingSupported() {
1831
+ return this.documentFormattingSupported;
1832
+ }
1807
1833
  handlePublishDiagnostics(params) {
1808
1834
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
1809
1835
  }
@@ -1879,7 +1905,7 @@ class LspClientTransport {
1879
1905
  const options = args[1];
1880
1906
  const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
1881
1907
  const timeoutController = new AbortController;
1882
- const timeoutHandle = setTimeout(() => {
1908
+ const timeoutHandle = this.timerProvider.setTimeout(() => {
1883
1909
  const stderrTail = this.stderrBuffer.slice(-5).join(`
1884
1910
  `);
1885
1911
  timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
@@ -1898,7 +1924,7 @@ class LspClientTransport {
1898
1924
  }
1899
1925
  throw error;
1900
1926
  } finally {
1901
- clearTimeout(timeoutHandle);
1927
+ this.timerProvider.clearTimeout(timeoutHandle);
1902
1928
  combinedSignal.dispose();
1903
1929
  }
1904
1930
  }
@@ -1949,8 +1975,8 @@ class LspClientTransport {
1949
1975
  try {
1950
1976
  proc.kill();
1951
1977
  let timeoutId;
1952
- const timeoutPromise = new Promise((resolve2) => {
1953
- timeoutId = setTimeout(resolve2, STOP_HARD_KILL_TIMEOUT_MS);
1978
+ const timeoutPromise = new Promise((resolve) => {
1979
+ timeoutId = setTimeout(resolve, STOP_HARD_KILL_TIMEOUT_MS);
1954
1980
  });
1955
1981
  await Promise.race([
1956
1982
  proc.exited.then(() => {
@@ -1966,7 +1992,7 @@ class LspClientTransport {
1966
1992
  proc.kill("SIGKILL");
1967
1993
  await Promise.race([
1968
1994
  proc.exited,
1969
- new Promise((resolve2) => setTimeout(resolve2, STOP_SIGKILL_GRACE_MS))
1995
+ new Promise((resolve) => setTimeout(resolve, STOP_SIGKILL_GRACE_MS))
1970
1996
  ]);
1971
1997
  } catch (error) {
1972
1998
  reportBestEffortCleanupError("hard process kill", error instanceof Error ? error : String(error));
@@ -2017,6 +2043,14 @@ function supportsDiagnosticPull(capabilities) {
2017
2043
  return false;
2018
2044
  return Object.hasOwn(capabilities, "diagnosticProvider");
2019
2045
  }
2046
+ function supportsDocumentFormatting(capabilities) {
2047
+ if (capabilities === undefined)
2048
+ return false;
2049
+ const provider = capabilities.documentFormattingProvider;
2050
+ if (provider === undefined || provider === null || provider === false)
2051
+ return false;
2052
+ return provider === true || typeof provider === "object";
2053
+ }
2020
2054
 
2021
2055
  class LspClientConnection extends LspClientTransport {
2022
2056
  async initialize() {
@@ -2033,6 +2067,7 @@ class LspClientConnection extends LspClientTransport {
2033
2067
  references: {},
2034
2068
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
2035
2069
  publishDiagnostics: {},
2070
+ formatting: { dynamicRegistration: false },
2036
2071
  rename: {
2037
2072
  prepareSupport: true,
2038
2073
  prepareSupportDefaultBehavior: 1
@@ -2074,6 +2109,7 @@ class LspClientConnection extends LspClientTransport {
2074
2109
  initializationOptions: this.server.initialization
2075
2110
  }, { timeoutMs: this.initializeTimeoutMs });
2076
2111
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
2112
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
2077
2113
  await this.sendNotification("initialized", {});
2078
2114
  await this.sendNotification("workspace/didChangeConfiguration", {
2079
2115
  settings: { json: { validate: { enable: true } } }
@@ -2269,6 +2305,17 @@ function canonicalPath(filePath) {
2269
2305
  return absolute;
2270
2306
  }
2271
2307
  }
2308
+ function normalizeDocumentUri(uri) {
2309
+ let decoded = uri;
2310
+ try {
2311
+ decoded = decodeURIComponent(uri);
2312
+ } catch {
2313
+ decoded = uri;
2314
+ }
2315
+ if (process.platform !== "win32")
2316
+ return decoded;
2317
+ return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
2318
+ }
2272
2319
  function isSameOrDescendant(candidate, parent) {
2273
2320
  const suffix = relative2(parent, candidate);
2274
2321
  return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
@@ -2279,30 +2326,31 @@ function movedPath(candidate, oldPath, newPath) {
2279
2326
  }
2280
2327
 
2281
2328
  class WorkspaceDocumentState {
2282
- sendNotification;
2283
- clearDiagnostics;
2284
- openDocuments = new Map;
2285
- openByUri = new Map;
2286
- openPromises = new Map;
2287
- now;
2288
- versionlessPublishQuiescenceMs;
2289
2329
  constructor(sendNotification, clearDiagnostics, options = {}) {
2290
2330
  this.sendNotification = sendNotification;
2291
2331
  this.clearDiagnostics = clearDiagnostics;
2292
- this.now = options.now ?? (() => Date.now());
2332
+ this.openDocuments = new Map;
2333
+ this.openByUri = new Map;
2334
+ this.openPromises = new Map;
2335
+ this.timerProvider = options.timerProvider ?? {
2336
+ now: options.now ?? (() => Date.now()),
2337
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
2338
+ clearTimeout: (handle) => clearTimeout(handle)
2339
+ };
2340
+ this.now = () => this.timerProvider.now();
2293
2341
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
2294
2342
  }
2295
2343
  async openFile(filePath) {
2296
- const path2 = canonicalPath(filePath);
2297
- const existingOpen = this.openPromises.get(path2);
2344
+ const path = canonicalPath(filePath);
2345
+ const existingOpen = this.openPromises.get(path);
2298
2346
  if (existingOpen) {
2299
2347
  await existingOpen;
2300
- return this.openFile(path2);
2348
+ return this.openFile(path);
2301
2349
  }
2302
- const text = readFileSync2(path2, "utf-8");
2303
- const existing = this.openDocuments.get(path2);
2350
+ const text = readFileSync2(path, "utf-8");
2351
+ const existing = this.openDocuments.get(path);
2304
2352
  if (!existing)
2305
- return this.openDocumentSingleFlight(path2, text);
2353
+ return this.openDocumentSingleFlight(path, text);
2306
2354
  if (existing.text === text)
2307
2355
  return;
2308
2356
  await this.changeDocument(existing, text);
@@ -2311,7 +2359,7 @@ class WorkspaceDocumentState {
2311
2359
  return this.openDocuments.get(canonicalPath(filePath))?.version;
2312
2360
  }
2313
2361
  getStoredDiagnostics(uri) {
2314
- const state = this.openByUri.get(uri);
2362
+ const state = this.openByUri.get(normalizeDocumentUri(uri));
2315
2363
  if (!state)
2316
2364
  return [];
2317
2365
  return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
@@ -2333,13 +2381,13 @@ class WorkspaceDocumentState {
2333
2381
  return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
2334
2382
  }
2335
2383
  getPullCache(snapshot) {
2336
- const state = this.openByUri.get(snapshot.uri);
2384
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2337
2385
  if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
2338
2386
  return null;
2339
2387
  return state.pullCache;
2340
2388
  }
2341
2389
  recordPullDiagnostics(snapshot, report) {
2342
- const state = this.openByUri.get(snapshot.uri);
2390
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2343
2391
  if (!state)
2344
2392
  return;
2345
2393
  state.pullCache = {
@@ -2349,7 +2397,7 @@ class WorkspaceDocumentState {
2349
2397
  };
2350
2398
  }
2351
2399
  recordPublishedDiagnostics(params) {
2352
- const state = this.openByUri.get(params.uri);
2400
+ const state = this.openByUri.get(normalizeDocumentUri(params.uri));
2353
2401
  if (!state)
2354
2402
  return;
2355
2403
  state.publishGeneration += 1;
@@ -2363,7 +2411,7 @@ class WorkspaceDocumentState {
2363
2411
  this.notifyWaiters(state);
2364
2412
  }
2365
2413
  resolvePushDiagnostics(snapshot) {
2366
- const state = this.openByUri.get(snapshot.uri);
2414
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2367
2415
  if (!state?.lastPublish)
2368
2416
  return { status: "missing" };
2369
2417
  const publish = state.lastPublish;
@@ -2377,7 +2425,7 @@ class WorkspaceDocumentState {
2377
2425
  return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
2378
2426
  }
2379
2427
  waitForDiagnosticsActivity(snapshot, timeoutMs) {
2380
- const state = this.openByUri.get(snapshot.uri);
2428
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
2381
2429
  if (!state || timeoutMs <= 0)
2382
2430
  return Promise.resolve();
2383
2431
  return new Promise((resolveActivity) => {
@@ -2386,18 +2434,18 @@ class WorkspaceDocumentState {
2386
2434
  if (settled)
2387
2435
  return;
2388
2436
  settled = true;
2389
- clearTimeout(timer);
2437
+ this.timerProvider.clearTimeout(timer);
2390
2438
  state.waiters.delete(finish);
2391
2439
  resolveActivity();
2392
2440
  };
2393
- const timer = setTimeout(finish, timeoutMs);
2441
+ const timer = this.timerProvider.setTimeout(finish, timeoutMs);
2394
2442
  if (typeof timer.unref === "function")
2395
2443
  timer.unref();
2396
2444
  state.waiters.add(finish);
2397
2445
  });
2398
2446
  }
2399
2447
  validateVersions(operations) {
2400
- const versions = new Map([...this.openDocuments].map(([path2, state]) => [path2, state.version]));
2448
+ const versions = new Map([...this.openDocuments].map(([path, state]) => [path, state.version]));
2401
2449
  for (const operation of operations) {
2402
2450
  if (operation.kind === "text") {
2403
2451
  const current = versions.get(operation.path);
@@ -2413,17 +2461,17 @@ class WorkspaceDocumentState {
2413
2461
  continue;
2414
2462
  }
2415
2463
  if (operation.kind === "rename") {
2416
- const moved = [...versions].filter(([path2]) => isSameOrDescendant(path2, operation.oldPath));
2417
- for (const [path2] of moved)
2418
- versions.delete(path2);
2419
- for (const [path2] of moved)
2420
- versions.set(movedPath(path2, operation.oldPath, operation.newPath), 1);
2464
+ const moved = [...versions].filter(([path]) => isSameOrDescendant(path, operation.oldPath));
2465
+ for (const [path] of moved)
2466
+ versions.delete(path);
2467
+ for (const [path] of moved)
2468
+ versions.set(movedPath(path, operation.oldPath, operation.newPath), 1);
2421
2469
  continue;
2422
2470
  }
2423
2471
  if (operation.kind === "delete") {
2424
- for (const path2 of [...versions.keys()]) {
2425
- if (isSameOrDescendant(path2, operation.path))
2426
- versions.delete(path2);
2472
+ for (const path of [...versions.keys()]) {
2473
+ if (isSameOrDescendant(path, operation.path))
2474
+ versions.delete(path);
2427
2475
  }
2428
2476
  continue;
2429
2477
  }
@@ -2467,8 +2515,8 @@ class WorkspaceDocumentState {
2467
2515
  for (const state of moved)
2468
2516
  await this.closeDocument(state);
2469
2517
  for (const state of moved) {
2470
- const path2 = movedPath(state.path, mutation.oldPath, mutation.newPath);
2471
- await this.openDocumentSingleFlight(path2, readFileSync2(path2, "utf-8"));
2518
+ const path = movedPath(state.path, mutation.oldPath, mutation.newPath);
2519
+ await this.openDocumentSingleFlight(path, readFileSync2(path, "utf-8"));
2472
2520
  }
2473
2521
  if (moved.length === 0) {
2474
2522
  watched.push({ uri: pathToFileURL2(mutation.oldPath).href, type: 3 });
@@ -2482,31 +2530,31 @@ class WorkspaceDocumentState {
2482
2530
  if (removed.length === 0)
2483
2531
  watched.push({ uri: pathToFileURL2(mutation.path).href, type: 3 });
2484
2532
  }
2485
- async openDocumentSingleFlight(path2, text) {
2486
- const existing = this.openPromises.get(path2);
2533
+ async openDocumentSingleFlight(path, text) {
2534
+ const existing = this.openPromises.get(path);
2487
2535
  if (existing)
2488
2536
  return existing;
2489
2537
  const open = (async () => {
2490
2538
  const state = {
2491
- path: path2,
2492
- uri: pathToFileURL2(path2).href,
2493
- languageId: getLanguageId(effectiveExtension(path2)),
2539
+ path,
2540
+ uri: pathToFileURL2(path).href,
2541
+ languageId: getLanguageId(effectiveExtension(path)),
2494
2542
  text,
2495
2543
  version: 1,
2496
2544
  generation: 1,
2497
2545
  publishGeneration: 0,
2498
2546
  waiters: new Set
2499
2547
  };
2500
- this.openDocuments.set(path2, state);
2501
- this.openByUri.set(state.uri, state);
2548
+ this.openDocuments.set(path, state);
2549
+ this.openByUri.set(normalizeDocumentUri(state.uri), state);
2502
2550
  this.notifyWaiters(state);
2503
2551
  await this.sendNotification("textDocument/didOpen", {
2504
2552
  textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
2505
2553
  });
2506
2554
  })().finally(() => {
2507
- this.openPromises.delete(path2);
2555
+ this.openPromises.delete(path);
2508
2556
  });
2509
- this.openPromises.set(path2, open);
2557
+ this.openPromises.set(path, open);
2510
2558
  return open;
2511
2559
  }
2512
2560
  async changeDocument(state, text) {
@@ -2523,7 +2571,7 @@ class WorkspaceDocumentState {
2523
2571
  }
2524
2572
  async closeDocument(state) {
2525
2573
  this.openDocuments.delete(state.path);
2526
- this.openByUri.delete(state.uri);
2574
+ this.openByUri.delete(normalizeDocumentUri(state.uri));
2527
2575
  this.clearDiagnostics(state.uri);
2528
2576
  this.notifyWaiters(state);
2529
2577
  await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
@@ -2552,13 +2600,11 @@ import { dirname as dirname4, isAbsolute as isAbsolute4, relative as relative3,
2552
2600
  import { fileURLToPath as fileURLToPath2 } from "node:url";
2553
2601
 
2554
2602
  class WorkspaceEditPathError extends Error {
2555
- path;
2556
- detail;
2557
- name = "WorkspaceEditPathError";
2558
- constructor(path2, detail) {
2559
- super(`${detail}: ${path2}`);
2560
- this.path = path2;
2603
+ constructor(path, detail) {
2604
+ super(`${detail}: ${path}`);
2605
+ this.path = path;
2561
2606
  this.detail = detail;
2607
+ this.name = "WorkspaceEditPathError";
2562
2608
  }
2563
2609
  }
2564
2610
  function isPathInsideWorkspace(filePath, workspaceRoot) {
@@ -2620,28 +2666,28 @@ function uriToCanonicalWorkspacePath(uri, workspaceRoot) {
2620
2666
  return { success: false, error: `${requestedPath}: ${detail}` };
2621
2667
  }
2622
2668
  }
2623
- function snapshotPath(path2, includeChildren) {
2624
- if (!existsSync4(path2))
2669
+ function snapshotPath(path, includeChildren) {
2670
+ if (!existsSync4(path))
2625
2671
  return { kind: "missing" };
2626
- const stats = lstatSync2(path2);
2672
+ const stats = lstatSync2(path);
2627
2673
  if (stats.isFile())
2628
- return { kind: "file", content: readFileSync3(path2, "utf-8") };
2674
+ return { kind: "file", content: readFileSync3(path, "utf-8") };
2629
2675
  if (stats.isDirectory()) {
2630
- return includeChildren ? { kind: "directory", children: readdirSync(path2).sort() } : { kind: "directory" };
2676
+ return includeChildren ? { kind: "directory", children: readdirSync(path).sort() } : { kind: "directory" };
2631
2677
  }
2632
- throw new WorkspaceEditPathError(path2, "unsupported filesystem entry");
2678
+ throw new WorkspaceEditPathError(path, "unsupported filesystem entry");
2633
2679
  }
2634
2680
 
2635
2681
  // ../lsp-core/src/lsp/workspace-edit-commit.ts
2636
2682
  var DEFAULT_IO = {
2637
- writeFile(path2, content) {
2638
- writeFileSync(path2, content, "utf-8");
2683
+ writeFile(path, content) {
2684
+ writeFileSync(path, content, "utf-8");
2639
2685
  },
2640
2686
  rename(oldPath, newPath) {
2641
2687
  renameSync(oldPath, newPath);
2642
2688
  },
2643
- remove(path2, recursive) {
2644
- rmSync(path2, { recursive, force: false });
2689
+ remove(path, recursive) {
2690
+ rmSync(path, { recursive, force: false });
2645
2691
  }
2646
2692
  };
2647
2693
  function snapshotsEqual(expected, actual) {
@@ -2654,8 +2700,8 @@ function snapshotsEqual(expected, actual) {
2654
2700
  }
2655
2701
  return true;
2656
2702
  }
2657
- function liveSnapshot(path2, expected) {
2658
- return snapshotPath(path2, expected.kind === "directory" && expected.children !== undefined);
2703
+ function liveSnapshot(path, expected) {
2704
+ return snapshotPath(path, expected.kind === "directory" && expected.children !== undefined);
2659
2705
  }
2660
2706
  function firstOperationIndex(plan) {
2661
2707
  return plan.operations[0]?.changeIndex ?? 0;
@@ -2676,28 +2722,28 @@ function failedCommit(plan, failure) {
2676
2722
  };
2677
2723
  }
2678
2724
  function verifySnapshots(plan) {
2679
- for (const [path2, expected] of plan.snapshots) {
2725
+ for (const [path, expected] of plan.snapshots) {
2680
2726
  let actual;
2681
2727
  try {
2682
- actual = liveSnapshot(path2, expected);
2728
+ actual = liveSnapshot(path, expected);
2683
2729
  } catch (error) {
2684
- const changeIndex = plan.firstChangeByPath.get(path2) ?? firstOperationIndex(plan);
2730
+ const changeIndex = plan.firstChangeByPath.get(path) ?? firstOperationIndex(plan);
2685
2731
  const detail = error instanceof Error ? error.message : String(error);
2686
- return failedCommit(plan, { message: `cannot verify snapshot for ${path2}: ${detail}`, changeIndex });
2732
+ return failedCommit(plan, { message: `cannot verify snapshot for ${path}: ${detail}`, changeIndex });
2687
2733
  }
2688
2734
  if (!snapshotsEqual(expected, actual)) {
2689
- const changeIndex = plan.firstChangeByPath.get(path2) ?? firstOperationIndex(plan);
2690
- return failedCommit(plan, { message: `workspace state changed before commit: ${path2}`, changeIndex });
2735
+ const changeIndex = plan.firstChangeByPath.get(path) ?? firstOperationIndex(plan);
2736
+ return failedCommit(plan, { message: `workspace state changed before commit: ${path}`, changeIndex });
2691
2737
  }
2692
2738
  }
2693
2739
  return null;
2694
2740
  }
2695
- function addModifiedPath(paths, path2) {
2696
- if (!paths.includes(path2))
2697
- paths.push(path2);
2741
+ function addModifiedPath(paths, path) {
2742
+ if (!paths.includes(path))
2743
+ paths.push(path);
2698
2744
  }
2699
- function reportedPath(plan, path2) {
2700
- return plan.reportedPathByCanonical.get(path2) ?? path2;
2745
+ function reportedPath(plan, path) {
2746
+ return plan.reportedPathByCanonical.get(path) ?? path;
2701
2747
  }
2702
2748
  function changedPathsForMutation(mutation) {
2703
2749
  return mutation.kind === "rename" ? [mutation.oldPath, mutation.newPath] : [mutation.path];
@@ -2705,8 +2751,8 @@ function changedPathsForMutation(mutation) {
2705
2751
  function mutationDelta(operations) {
2706
2752
  const changedPaths = new Set;
2707
2753
  for (const operation of operations) {
2708
- for (const path2 of changedPathsForMutation(operation))
2709
- changedPaths.add(path2);
2754
+ for (const path of changedPathsForMutation(operation))
2755
+ changedPaths.add(path);
2710
2756
  }
2711
2757
  return { operations, changedPaths: [...changedPaths].sort() };
2712
2758
  }
@@ -2850,13 +2896,11 @@ function canonicalFingerprint(operations) {
2850
2896
 
2851
2897
  // ../lsp-core/src/lsp/workspace-edit-types.ts
2852
2898
  class WorkspaceEditValidationError extends Error {
2853
- changeIndex;
2854
- detail;
2855
- name = "WorkspaceEditValidationError";
2856
2899
  constructor(changeIndex, detail) {
2857
2900
  super(`change ${changeIndex}: ${detail}`);
2858
2901
  this.changeIndex = changeIndex;
2859
2902
  this.detail = detail;
2903
+ this.name = "WorkspaceEditValidationError";
2860
2904
  }
2861
2905
  }
2862
2906
 
@@ -2942,14 +2986,14 @@ function parseSinglePathResource(input, kind) {
2942
2986
  return;
2943
2987
  }
2944
2988
  if (kind === "create") {
2945
- const options2 = parseOptions(change["options"], ["overwrite", "ignoreIfExists"], changeIndex);
2989
+ const options = parseOptions(change["options"], ["overwrite", "ignoreIfExists"], changeIndex);
2946
2990
  target.operations.push({
2947
2991
  kind,
2948
2992
  changeIndex,
2949
2993
  path: resolvedPath.path,
2950
2994
  reportedPath: resolvedPath.requestedPath,
2951
- overwrite: options2["overwrite"] ?? false,
2952
- ignoreIfExists: options2["ignoreIfExists"] ?? false,
2995
+ overwrite: options["overwrite"] ?? false,
2996
+ ignoreIfExists: options["ignoreIfExists"] ?? false,
2953
2997
  followedSymbolicLink: resolvedPath.followedSymbolicLink
2954
2998
  });
2955
2999
  return;
@@ -3207,12 +3251,12 @@ function isSameOrDescendant2(candidate, parent) {
3207
3251
  const relativePath = relative4(parent, candidate);
3208
3252
  return relativePath === "" || !relativePath.startsWith("..") && relativePath !== "..";
3209
3253
  }
3210
- function removeVirtualSubtree(virtual, path2) {
3254
+ function removeVirtualSubtree(virtual, path) {
3211
3255
  for (const candidate of [...virtual.keys()]) {
3212
- if (isSameOrDescendant2(candidate, path2))
3256
+ if (isSameOrDescendant2(candidate, path))
3213
3257
  virtual.delete(candidate);
3214
3258
  }
3215
- virtual.set(path2, { kind: "missing" });
3259
+ virtual.set(path, { kind: "missing" });
3216
3260
  }
3217
3261
  function moveVirtualSubtree(virtual, oldPath, newPath) {
3218
3262
  const moved = [...virtual.entries()].filter(([candidate]) => isSameOrDescendant2(candidate, oldPath));
@@ -3223,16 +3267,16 @@ function moveVirtualSubtree(virtual, oldPath, newPath) {
3223
3267
  virtual.set(suffix === "" ? newPath : resolve4(newPath, suffix), entry);
3224
3268
  }
3225
3269
  }
3226
- function virtualDirectoryHasChildren(virtual, path2) {
3270
+ function virtualDirectoryHasChildren(virtual, path) {
3227
3271
  for (const [candidate, entry] of virtual) {
3228
- if (candidate !== path2 && entry.kind !== "missing" && isSameOrDescendant2(candidate, path2))
3272
+ if (candidate !== path && entry.kind !== "missing" && isSameOrDescendant2(candidate, path))
3229
3273
  return true;
3230
3274
  }
3231
3275
  return false;
3232
3276
  }
3233
- function requireVirtualParent(virtual, path2, changeIndex) {
3234
- if (virtual.get(dirname5(path2))?.kind !== "directory") {
3235
- throw new WorkspaceEditValidationError(changeIndex, `parent directory does not exist for ${path2}`);
3277
+ function requireVirtualParent(virtual, path, changeIndex) {
3278
+ if (virtual.get(dirname5(path))?.kind !== "directory") {
3279
+ throw new WorkspaceEditValidationError(changeIndex, `parent directory does not exist for ${path}`);
3236
3280
  }
3237
3281
  }
3238
3282
  function simulateOperations(parsed, snapshots) {
@@ -3354,10 +3398,9 @@ function simulateDelete(operation, virtual) {
3354
3398
  import { existsSync as existsSync6, lstatSync as lstatSync4, readdirSync as readdirSync2 } from "node:fs";
3355
3399
  import { dirname as dirname6, resolve as resolve5 } from "node:path";
3356
3400
  class WorkspaceSnapshotBuilder {
3357
- workspaceRoot;
3358
- snapshots = new Map;
3359
3401
  constructor(workspaceRoot) {
3360
3402
  this.workspaceRoot = workspaceRoot;
3403
+ this.snapshots = new Map;
3361
3404
  }
3362
3405
  build(operations) {
3363
3406
  this.add(this.workspaceRoot, false);
@@ -3378,21 +3421,21 @@ class WorkspaceSnapshotBuilder {
3378
3421
  }
3379
3422
  return this.snapshots;
3380
3423
  }
3381
- add(path2, includeChildren) {
3382
- let candidate = path2;
3424
+ add(path, includeChildren) {
3425
+ let candidate = path;
3383
3426
  while (true) {
3384
3427
  const existing = this.snapshots.get(candidate);
3385
3428
  if (existing === undefined || includeChildren && existing.kind === "directory" && existing.children === undefined) {
3386
- this.snapshots.set(candidate, snapshotPath(candidate, includeChildren && candidate === path2));
3429
+ this.snapshots.set(candidate, snapshotPath(candidate, includeChildren && candidate === path));
3387
3430
  }
3388
3431
  if (candidate === this.workspaceRoot)
3389
3432
  break;
3390
3433
  candidate = dirname6(candidate);
3391
3434
  }
3392
- if (!includeChildren || !existsSync6(path2) || !lstatSync4(path2).isDirectory())
3435
+ if (!includeChildren || !existsSync6(path) || !lstatSync4(path).isDirectory())
3393
3436
  return;
3394
- for (const child of readdirSync2(path2))
3395
- this.add(resolve5(path2, child), true);
3437
+ for (const child of readdirSync2(path))
3438
+ this.add(resolve5(path, child), true);
3396
3439
  }
3397
3440
  }
3398
3441
  function snapshotOperations(operations, workspaceRoot) {
@@ -3401,8 +3444,10 @@ function snapshotOperations(operations, workspaceRoot) {
3401
3444
 
3402
3445
  // ../lsp-core/src/lsp/workspace-edit-plan.ts
3403
3446
  class PlanPathIndex {
3404
- firstChangeByPath = new Map;
3405
- reportedPathByCanonical = new Map;
3447
+ constructor() {
3448
+ this.firstChangeByPath = new Map;
3449
+ this.reportedPathByCanonical = new Map;
3450
+ }
3406
3451
  build(operations) {
3407
3452
  for (const operation of operations) {
3408
3453
  switch (operation.kind) {
@@ -3418,11 +3463,11 @@ class PlanPathIndex {
3418
3463
  }
3419
3464
  }
3420
3465
  }
3421
- add(path2, reportedPath2, changeIndex) {
3422
- if (!this.firstChangeByPath.has(path2))
3423
- this.firstChangeByPath.set(path2, changeIndex);
3424
- if (!this.reportedPathByCanonical.has(path2))
3425
- this.reportedPathByCanonical.set(path2, reportedPath2);
3466
+ add(path, reportedPath, changeIndex) {
3467
+ if (!this.firstChangeByPath.has(path))
3468
+ this.firstChangeByPath.set(path, changeIndex);
3469
+ if (!this.reportedPathByCanonical.has(path))
3470
+ this.reportedPathByCanonical.set(path, reportedPath);
3426
3471
  }
3427
3472
  }
3428
3473
  function fingerprintWorkspaceEdit(edit, workspaceRoot) {
@@ -3491,14 +3536,11 @@ function isRecord4(value) {
3491
3536
  }
3492
3537
 
3493
3538
  class WorkspaceMutationController {
3494
- workspaceRoot;
3495
- documents;
3496
- activeLease = null;
3497
- nextLeaseId = 1;
3498
- io;
3499
3539
  constructor(workspaceRoot, documents) {
3500
3540
  this.workspaceRoot = workspaceRoot;
3501
3541
  this.documents = documents;
3542
+ this.activeLease = null;
3543
+ this.nextLeaseId = 1;
3502
3544
  }
3503
3545
  setIo(io) {
3504
3546
  this.io = io;
@@ -3537,15 +3579,15 @@ class WorkspaceMutationController {
3537
3579
  };
3538
3580
  }
3539
3581
  lease.phase = "applying";
3540
- lease.applyCompletion = new Promise((resolve6) => {
3541
- lease.resolveApply = resolve6;
3582
+ lease.applyCompletion = new Promise((resolve) => {
3583
+ lease.resolveApply = resolve;
3542
3584
  });
3543
3585
  const edit = isRecord4(params) ? params["edit"] : undefined;
3544
- const record2 = edit === undefined ? { fingerprint: null, result: failure("workspace/applyEdit params.edit is required", 0) } : await this.applyEdit(edit, lease);
3545
- lease.serverApply = record2;
3586
+ const record = edit === undefined ? { fingerprint: null, result: failure("workspace/applyEdit params.edit is required", 0) } : await this.applyEdit(edit, lease);
3587
+ lease.serverApply = record;
3546
3588
  lease.phase = "settled";
3547
3589
  lease.resolveApply?.();
3548
- return responseFor(record2.result);
3590
+ return responseFor(record.result);
3549
3591
  }
3550
3592
  async reconcileRename(leaseToken, edit) {
3551
3593
  const lease = this.requireActiveLease(leaseToken);
@@ -3561,16 +3603,16 @@ class WorkspaceMutationController {
3561
3603
  const applied = await this.applyEdit(edit, lease);
3562
3604
  return { edit, apply: applied.result };
3563
3605
  }
3564
- reconcileServerApply(record2, edit) {
3606
+ reconcileServerApply(record, edit) {
3565
3607
  if (!edit)
3566
- return { edit, apply: record2.result };
3608
+ return { edit, apply: record.result };
3567
3609
  const fingerprint = fingerprintWorkspaceEdit(edit, this.workspaceRoot);
3568
- if (fingerprint.success && record2.fingerprint !== null && fingerprint.fingerprint === record2.fingerprint) {
3569
- return { edit, apply: record2.result };
3610
+ if (fingerprint.success && record.fingerprint !== null && fingerprint.fingerprint === record.fingerprint) {
3611
+ return { edit, apply: record.result };
3570
3612
  }
3571
3613
  return {
3572
3614
  edit,
3573
- apply: failure("rename result conflicts with server-applied workspace edit", 0, record2.result)
3615
+ apply: failure("rename result conflicts with server-applied workspace edit", 0, record.result)
3574
3616
  };
3575
3617
  }
3576
3618
  async applyEdit(edit, lease) {
@@ -3611,14 +3653,12 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
3611
3653
  var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
3612
3654
 
3613
3655
  class LspClient extends LspClientConnection {
3614
- diagnosticPullErrors = [];
3615
- documents;
3616
- workspaceMutations;
3617
- diagnosticsFreshnessTimeoutMs;
3618
- constructor(root, server2, options = {}) {
3619
- super(root, server2, options);
3656
+ constructor(root, server, options = {}) {
3657
+ super(root, server, options);
3658
+ this.diagnosticPullErrors = [];
3620
3659
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
3621
3660
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
3661
+ timerProvider: this.timerProvider,
3622
3662
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
3623
3663
  });
3624
3664
  this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
@@ -3671,6 +3711,18 @@ class LspClient extends LspClientConnection {
3671
3711
  textDocument: { uri: pathToFileURL3(absPath).href }
3672
3712
  }, options);
3673
3713
  }
3714
+ async formatDocument(filePath, options, signal) {
3715
+ if (!this.isDocumentFormattingSupported())
3716
+ return null;
3717
+ const absPath = this.resolveWorkspacePath(filePath);
3718
+ await this.openFile(absPath);
3719
+ const requestOptions = signal === undefined ? {} : { signal };
3720
+ const edits = await this.sendRequest("textDocument/formatting", {
3721
+ textDocument: { uri: pathToFileURL3(absPath).href },
3722
+ options
3723
+ }, requestOptions);
3724
+ return edits ?? [];
3725
+ }
3674
3726
  async workspaceSymbols(query, signal) {
3675
3727
  const options = signal === undefined ? {} : { signal };
3676
3728
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -3710,7 +3762,7 @@ class LspClient extends LspClientConnection {
3710
3762
  const absPath = this.resolveWorkspacePath(filePath);
3711
3763
  const uri = pathToFileURL3(absPath).href;
3712
3764
  await this.openFile(absPath);
3713
- const deadlineAt = Date.now() + this.diagnosticsFreshnessTimeoutMs;
3765
+ const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
3714
3766
  for (;; ) {
3715
3767
  signal?.throwIfAborted();
3716
3768
  const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
@@ -3723,13 +3775,13 @@ class LspClient extends LspClientConnection {
3723
3775
  if (!pushFallbackOnly) {
3724
3776
  const cached = this.documents.getPullCache(snapshot);
3725
3777
  try {
3726
- const remainingMs2 = deadlineAt - Date.now();
3727
- if (remainingMs2 <= 0)
3778
+ const remainingMs = deadlineAt - this.timerProvider.now();
3779
+ if (remainingMs <= 0)
3728
3780
  return this.freshnessTimeout(absPath);
3729
3781
  const result = await this.sendRequest("textDocument/diagnostic", {
3730
3782
  textDocument: { uri },
3731
3783
  ...cached?.resultId === undefined ? {} : { previousResultId: cached.resultId }
3732
- }, { timeoutMs: remainingMs2, ...signal === undefined ? {} : { signal } });
3784
+ }, { timeoutMs: remainingMs, ...signal === undefined ? {} : { signal } });
3733
3785
  if (!this.documents.isCurrentSnapshot(snapshot))
3734
3786
  continue;
3735
3787
  const report = this.parseDiagnosticPullReport(result);
@@ -3758,7 +3810,7 @@ class LspClient extends LspClientConnection {
3758
3810
  }
3759
3811
  if (!pushFallbackOnly)
3760
3812
  continue;
3761
- const remainingMs = deadlineAt - Date.now();
3813
+ const remainingMs = deadlineAt - this.timerProvider.now();
3762
3814
  if (remainingMs <= 0) {
3763
3815
  if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
3764
3816
  const cached = this.documents.getPullCache(snapshot);
@@ -3810,7 +3862,7 @@ function waitForDiagnosticsActivity(wait, signal) {
3810
3862
  return wait;
3811
3863
  if (signal.aborted)
3812
3864
  return Promise.reject(abortError3(signal));
3813
- return new Promise((resolve7, reject) => {
3865
+ return new Promise((resolve, reject) => {
3814
3866
  const onAbort = () => {
3815
3867
  signal.removeEventListener("abort", onAbort);
3816
3868
  reject(abortError3(signal));
@@ -3818,7 +3870,7 @@ function waitForDiagnosticsActivity(wait, signal) {
3818
3870
  signal.addEventListener("abort", onAbort, { once: true });
3819
3871
  wait.then(() => {
3820
3872
  signal.removeEventListener("abort", onAbort);
3821
- resolve7();
3873
+ resolve();
3822
3874
  }, (error) => {
3823
3875
  signal.removeEventListener("abort", onAbort);
3824
3876
  reject(error);
@@ -3886,7 +3938,7 @@ async function stopClientBestEffort(client) {
3886
3938
  function awaitWithSignal2(promise, signal) {
3887
3939
  if (!signal)
3888
3940
  return promise;
3889
- return new Promise((resolve7, reject) => {
3941
+ return new Promise((resolve, reject) => {
3890
3942
  let settled = false;
3891
3943
  const onAbort = () => {
3892
3944
  if (settled)
@@ -3904,7 +3956,7 @@ function awaitWithSignal2(promise, signal) {
3904
3956
  return;
3905
3957
  settled = true;
3906
3958
  signal.removeEventListener("abort", onAbort);
3907
- resolve7(value);
3959
+ resolve(value);
3908
3960
  }, (err) => {
3909
3961
  if (settled)
3910
3962
  return;
@@ -3916,20 +3968,18 @@ function awaitWithSignal2(promise, signal) {
3916
3968
  }
3917
3969
 
3918
3970
  class LspManager {
3919
- clients = new Map;
3920
- reaperHandle = null;
3921
- signalDisposer = null;
3922
- disposed = false;
3923
- idleTimeoutMs;
3924
- initTimeoutMs;
3925
- reaperIntervalMs;
3926
- clientFactory;
3927
- now;
3928
3971
  constructor(options = {}) {
3972
+ this.clients = new Map;
3973
+ this.pendingStops = new Map;
3974
+ this.respawnBudgets = new Map;
3975
+ this.reaperHandle = null;
3976
+ this.signalDisposer = null;
3977
+ this.disposed = false;
3929
3978
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
3930
3979
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
3980
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
3931
3981
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
3932
- this.clientFactory = options.clientFactory ?? ((root, server2) => new LspClient(root, server2));
3982
+ this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
3933
3983
  this.now = options.now ?? (() => Date.now());
3934
3984
  this.startReaper();
3935
3985
  this.signalDisposer = installProcessSignalCleanup(() => this.stopAll());
@@ -3947,38 +3997,103 @@ class LspManager {
3947
3997
  getKey(root, serverId) {
3948
3998
  return `${root}::${serverId}`;
3949
3999
  }
4000
+ tombstoneStop(key, client) {
4001
+ const stop = stopClientBestEffort(client);
4002
+ this.pendingStops.set(key, stop);
4003
+ stop.finally(() => {
4004
+ if (this.pendingStops.get(key) === stop) {
4005
+ this.pendingStops.delete(key);
4006
+ }
4007
+ });
4008
+ return stop;
4009
+ }
4010
+ recordDeadGeneration(key) {
4011
+ let budget = this.respawnBudgets.get(key);
4012
+ if (budget === undefined) {
4013
+ budget = { deadGenerations: 0, exhaustedAt: null };
4014
+ this.respawnBudgets.set(key, budget);
4015
+ }
4016
+ budget.deadGenerations += 1;
4017
+ }
4018
+ markHealthyGeneration(key) {
4019
+ this.respawnBudgets.delete(key);
4020
+ }
4021
+ ensureRespawnAllowed(key, root, serverId) {
4022
+ const budget = this.respawnBudgets.get(key);
4023
+ if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
4024
+ return;
4025
+ if (budget.exhaustedAt === null) {
4026
+ budget.exhaustedAt = this.now();
4027
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
4028
+ }
4029
+ if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
4030
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
4031
+ }
4032
+ budget.deadGenerations = 0;
4033
+ budget.exhaustedAt = null;
4034
+ }
3950
4035
  reapStale() {
3951
4036
  const t = this.now();
3952
4037
  for (const [key, managed] of this.clients) {
3953
4038
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3954
- stopClientBestEffort(managed.client);
3955
4039
  this.clients.delete(key);
4040
+ this.tombstoneStop(key, managed.client);
3956
4041
  continue;
3957
4042
  }
3958
4043
  if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
3959
- stopClientBestEffort(managed.client);
3960
4044
  this.clients.delete(key);
4045
+ this.tombstoneStop(key, managed.client);
3961
4046
  }
3962
4047
  }
3963
4048
  }
4049
+ evictForAdmission() {
4050
+ while (this.clients.size >= this.maxResidentClients) {
4051
+ const victim = this.leastRecentlyUsedIdleClient();
4052
+ if (!victim)
4053
+ return;
4054
+ this.clients.delete(victim.key);
4055
+ this.tombstoneStop(victim.key, victim.managed.client);
4056
+ }
4057
+ }
4058
+ leastRecentlyUsedIdleClient() {
4059
+ let candidate = null;
4060
+ for (const [key, managed] of this.clients) {
4061
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
4062
+ continue;
4063
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
4064
+ candidate = { key, managed };
4065
+ }
4066
+ }
4067
+ return candidate;
4068
+ }
3964
4069
  async tryDeleteIfOrphaned(key, managed) {
3965
4070
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
3966
4071
  this.clients.delete(key);
3967
- await stopClientBestEffort(managed.client);
4072
+ await this.tombstoneStop(key, managed.client);
3968
4073
  }
3969
4074
  }
3970
- async getClient(root, server2, signal) {
4075
+ async getClient(root, server, signal) {
3971
4076
  if (this.disposed) {
3972
4077
  throw new Error("LspManager has been disposed");
3973
4078
  }
3974
4079
  signal?.throwIfAborted();
3975
- const key = this.getKey(root, server2.id);
4080
+ const key = this.getKey(root, server.id);
4081
+ for (;; ) {
4082
+ const pendingStop = this.pendingStops.get(key);
4083
+ if (pendingStop === undefined)
4084
+ break;
4085
+ await awaitWithSignal2(pendingStop, signal);
4086
+ signal?.throwIfAborted();
4087
+ }
4088
+ if (this.disposed) {
4089
+ throw new Error("LspManager has been disposed");
4090
+ }
3976
4091
  let managed = this.clients.get(key);
3977
4092
  if (managed) {
3978
4093
  const t = this.now();
3979
4094
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3980
- await stopClientBestEffort(managed.client);
3981
4095
  this.clients.delete(key);
4096
+ await this.tombstoneStop(key, managed.client);
3982
4097
  managed = undefined;
3983
4098
  }
3984
4099
  }
@@ -3999,15 +4114,21 @@ class LspManager {
3999
4114
  signal.throwIfAborted();
4000
4115
  }
4001
4116
  if (!managed.client.isAlive()) {
4002
- await stopClientBestEffort(managed.client);
4003
- this.clients.delete(key);
4004
- return this.getClient(root, server2, signal);
4117
+ this.recordDeadGeneration(key);
4118
+ if (this.clients.get(key) === managed) {
4119
+ this.clients.delete(key);
4120
+ }
4121
+ await this.tombstoneStop(key, managed.client);
4122
+ return this.getClient(root, server, signal);
4005
4123
  }
4124
+ this.markHealthyGeneration(key);
4006
4125
  managed.refCount++;
4007
4126
  managed.lastUsedAt = this.now();
4008
4127
  return managed.client;
4009
4128
  }
4010
- const client = this.clientFactory(root, server2);
4129
+ this.evictForAdmission();
4130
+ this.ensureRespawnAllowed(key, root, server.id);
4131
+ const client = this.clientFactory(root, server);
4011
4132
  const initStartedAt = this.now();
4012
4133
  const initPromise = (async () => {
4013
4134
  await client.start();
@@ -4030,7 +4151,7 @@ class LspManager {
4030
4151
  if (this.clients.get(key) === newManaged) {
4031
4152
  this.clients.delete(key);
4032
4153
  }
4033
- await stopClientBestEffort(client);
4154
+ await this.tombstoneStop(key, client);
4034
4155
  throw err;
4035
4156
  }
4036
4157
  newManaged.pendingWaiters--;
@@ -4041,6 +4162,15 @@ class LspManager {
4041
4162
  await this.tryDeleteIfOrphaned(key, newManaged);
4042
4163
  signal.throwIfAborted();
4043
4164
  }
4165
+ if (!client.isAlive()) {
4166
+ this.recordDeadGeneration(key);
4167
+ if (this.clients.get(key) === newManaged) {
4168
+ this.clients.delete(key);
4169
+ }
4170
+ await this.tombstoneStop(key, client);
4171
+ return this.getClient(root, server, signal);
4172
+ }
4173
+ this.markHealthyGeneration(key);
4044
4174
  newManaged.refCount++;
4045
4175
  newManaged.lastUsedAt = this.now();
4046
4176
  return client;
@@ -4061,15 +4191,21 @@ class LspManager {
4061
4191
  if (client && managed.client !== client)
4062
4192
  return;
4063
4193
  this.clients.delete(key);
4064
- stopClientBestEffort(managed.client);
4194
+ this.tombstoneStop(key, managed.client);
4065
4195
  }
4066
- warmupClient(root, server2) {
4196
+ warmupClient(root, server) {
4067
4197
  if (this.disposed)
4068
4198
  return;
4069
- const key = this.getKey(root, server2.id);
4070
- if (this.clients.has(key))
4199
+ const key = this.getKey(root, server.id);
4200
+ if (this.clients.has(key) || this.pendingStops.has(key))
4071
4201
  return;
4072
- const client = this.clientFactory(root, server2);
4202
+ this.evictForAdmission();
4203
+ try {
4204
+ this.ensureRespawnAllowed(key, root, server.id);
4205
+ } catch {
4206
+ return;
4207
+ }
4208
+ const client = this.clientFactory(root, server);
4073
4209
  const initStartedAt = this.now();
4074
4210
  const initPromise = (async () => {
4075
4211
  await client.start();
@@ -4094,7 +4230,7 @@ class LspManager {
4094
4230
  if (this.clients.get(key) === managed) {
4095
4231
  this.clients.delete(key);
4096
4232
  }
4097
- stopClientBestEffort(client);
4233
+ this.tombstoneStop(key, client);
4098
4234
  });
4099
4235
  }
4100
4236
  isServerInitializing(root, serverId) {
@@ -4138,8 +4274,11 @@ class LspManager {
4138
4274
  for (const managed of this.clients.values()) {
4139
4275
  stopPromises.push(stopClientBestEffort(managed.client));
4140
4276
  }
4277
+ const tombstonedStops = [...this.pendingStops.values()];
4141
4278
  this.clients.clear();
4142
- await Promise.allSettled(stopPromises);
4279
+ this.respawnBudgets.clear();
4280
+ await Promise.allSettled([...stopPromises, ...tombstonedStops]);
4281
+ this.pendingStops.clear();
4143
4282
  }
4144
4283
  }
4145
4284
  var _defaultInstance = null;
@@ -4157,57 +4296,52 @@ async function disposeDefaultLspManager() {
4157
4296
  }
4158
4297
  }
4159
4298
 
4160
- // ../lsp-core/src/lsp/server-install-state.ts
4161
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4162
- import { dirname as dirname7 } from "node:path";
4163
- function getInstallDecisionsPath() {
4164
- return lspRequestContext().installDecisionsPath;
4165
- }
4166
- function loadInstallDecisions() {
4167
- const path2 = getInstallDecisionsPath();
4168
- if (!existsSync7(path2))
4169
- return {};
4170
- try {
4171
- const parsed = JSON.parse(readFileSync4(path2, "utf8"));
4172
- return isInstallDecisions(parsed) ? parsed : {};
4173
- } catch {
4174
- return {};
4299
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
4300
+ import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
4301
+ import { dirname as dirname7, join as join3 } from "node:path";
4302
+
4303
+ // ../lsp-core/src/lsp/workspace-markers.ts
4304
+ var GIT_WORKSPACE_MARKER = ".git";
4305
+ var PROJECT_WORKSPACE_MARKERS = [
4306
+ "package.json",
4307
+ "pyproject.toml",
4308
+ "Cargo.toml",
4309
+ "go.mod",
4310
+ "pom.xml",
4311
+ "build.gradle"
4312
+ ];
4313
+ var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
4314
+
4315
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
4316
+ function findWorkspaceRootOutsideContext(directory) {
4317
+ const marked = nearestMarkedAncestor(directory);
4318
+ if (marked !== undefined)
4319
+ return marked;
4320
+ return realpathSync4(nearestExistingAncestor(directory));
4321
+ }
4322
+ function nearestMarkedAncestor(directory) {
4323
+ let current = directory;
4324
+ for (;; ) {
4325
+ if (existsSync7(current) && WORKSPACE_MARKERS.some((marker) => existsSync7(join3(current, marker)))) {
4326
+ return realpathSync4(current);
4327
+ }
4328
+ const parent = dirname7(current);
4329
+ if (parent === current)
4330
+ return;
4331
+ current = parent;
4175
4332
  }
4176
4333
  }
4177
- function loadInstallDecision(serverId) {
4178
- return loadInstallDecisions()[serverId];
4179
- }
4180
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4181
- const decisions = loadInstallDecisions();
4182
- decisions[serverId] = { decision, decidedAt };
4183
- writeInstallDecisions(decisions);
4184
- }
4185
- function isInstallDecision(value) {
4186
- return value === "declined" || value === "allowed";
4187
- }
4188
- function writeInstallDecisions(decisions) {
4189
- const path2 = getInstallDecisionsPath();
4190
- mkdirSync3(dirname7(path2), { recursive: true });
4191
- const tmpPath = `${path2}.tmp`;
4192
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4193
- `, "utf8");
4194
- renameSync2(tmpPath, path2);
4195
- }
4196
- function isInstallDecisions(value) {
4197
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4198
- }
4199
- function isInstallDecisionRecord(value) {
4200
- if (!isRecord5(value))
4201
- return false;
4202
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4203
- }
4204
- function isRecord5(value) {
4205
- return typeof value === "object" && value !== null && !Array.isArray(value);
4334
+ function nearestExistingAncestor(directory) {
4335
+ let current = directory;
4336
+ while (!existsSync7(current)) {
4337
+ const parent = dirname7(current);
4338
+ if (parent === current)
4339
+ return current;
4340
+ current = parent;
4341
+ }
4342
+ return current;
4206
4343
  }
4207
4344
 
4208
- // ../lsp-core/src/lsp/config-loader.ts
4209
- import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
4210
-
4211
4345
  // ../lsp-core/src/lsp/server-definitions.ts
4212
4346
  var LSP_INSTALL_HINTS = {
4213
4347
  typescript: "npm install -g typescript-language-server typescript",
@@ -4253,6 +4387,26 @@ var LSP_INSTALL_HINTS = {
4253
4387
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
4254
4388
  razor: "Razor runs through the Roslyn language server (cohosting). " + "Install: dotnet tool install -g roslyn-language-server --prerelease (requires v5.8.0+). See https://github.com/dotnet/razor"
4255
4389
  };
4390
+ var LSP_LOCAL_INSTALL_HINTS = {
4391
+ typescript: "bun add -d typescript-language-server typescript",
4392
+ vue: "bun add -d @vue/language-server",
4393
+ eslint: "bun add -d vscode-langservers-extracted",
4394
+ oxlint: "bun add -d oxlint",
4395
+ biome: "bun add -d @biomejs/biome",
4396
+ svelte: "bun add -d svelte-language-server",
4397
+ astro: "bun add -d @astrojs/language-server",
4398
+ bash: "bun add -d bash-language-server",
4399
+ "bash-ls": "bun add -d bash-language-server",
4400
+ "yaml-ls": "bun add -d yaml-language-server",
4401
+ php: "bun add -d intelephense",
4402
+ prisma: "bun add -d prisma",
4403
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
4404
+ pyright: "uv add --dev pyright",
4405
+ basedpyright: "uv add --dev basedpyright",
4406
+ ruff: "uv add --dev ruff",
4407
+ ty: "uv add --dev ty",
4408
+ "ruby-lsp": "bundle add ruby-lsp --group development"
4409
+ };
4256
4410
  var BUILTIN_SERVERS = {
4257
4411
  typescript: {
4258
4412
  command: ["typescript-language-server", "--stdio"],
@@ -4355,18 +4509,67 @@ var BUILTIN_SERVERS = {
4355
4509
  }
4356
4510
  };
4357
4511
 
4512
+ // ../lsp-core/src/lsp/server-install-state.ts
4513
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4514
+ import { dirname as dirname8 } from "node:path";
4515
+ function getInstallDecisionsPath() {
4516
+ return lspRequestContext().installDecisionsPath;
4517
+ }
4518
+ function loadInstallDecisions() {
4519
+ const path = getInstallDecisionsPath();
4520
+ if (!existsSync8(path))
4521
+ return {};
4522
+ try {
4523
+ const parsed = JSON.parse(readFileSync4(path, "utf8"));
4524
+ return isInstallDecisions(parsed) ? parsed : {};
4525
+ } catch {
4526
+ return {};
4527
+ }
4528
+ }
4529
+ function loadInstallDecision(serverId) {
4530
+ return loadInstallDecisions()[serverId];
4531
+ }
4532
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4533
+ const decisions = loadInstallDecisions();
4534
+ decisions[serverId] = { decision, decidedAt };
4535
+ writeInstallDecisions(decisions);
4536
+ }
4537
+ function isInstallDecision(value) {
4538
+ return value === "declined" || value === "allowed";
4539
+ }
4540
+ function writeInstallDecisions(decisions) {
4541
+ const path = getInstallDecisionsPath();
4542
+ mkdirSync3(dirname8(path), { recursive: true });
4543
+ const tmpPath = `${path}.tmp`;
4544
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4545
+ `, "utf8");
4546
+ renameSync2(tmpPath, path);
4547
+ }
4548
+ function isInstallDecisions(value) {
4549
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4550
+ }
4551
+ function isInstallDecisionRecord(value) {
4552
+ if (!isRecord5(value))
4553
+ return false;
4554
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4555
+ }
4556
+ function isRecord5(value) {
4557
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4558
+ }
4559
+
4358
4560
  // ../lsp-core/src/lsp/config-loader.ts
4561
+ import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
4359
4562
  function getProjectConfigPaths() {
4360
4563
  return lspRequestContext().projectConfigPaths;
4361
4564
  }
4362
4565
  function getUserConfigPath() {
4363
4566
  return lspRequestContext().userConfigPath;
4364
4567
  }
4365
- function loadJsonFile(path2) {
4366
- if (!existsSync8(path2))
4568
+ function loadJsonFile(path) {
4569
+ if (!existsSync9(path))
4367
4570
  return null;
4368
4571
  try {
4369
- const parsed = JSON.parse(readFileSync5(path2, "utf-8"));
4572
+ const parsed = JSON.parse(readFileSync5(path, "utf-8"));
4370
4573
  return isConfigJson(parsed) ? parsed : null;
4371
4574
  } catch {
4372
4575
  return null;
@@ -4383,8 +4586,8 @@ function loadAllConfigs() {
4383
4586
  return configs;
4384
4587
  }
4385
4588
  function loadFirstJsonFile(paths) {
4386
- for (const path2 of paths) {
4387
- const config = loadJsonFile(path2);
4589
+ for (const path of paths) {
4590
+ const config = loadJsonFile(path);
4388
4591
  if (config)
4389
4592
  return config;
4390
4593
  }
@@ -4410,10 +4613,10 @@ function getMergedServers() {
4410
4613
  }
4411
4614
  if (seen.has(id))
4412
4615
  continue;
4413
- const server2 = createServerFromEntry(id, entry, source);
4414
- if (!server2)
4616
+ const server = createServerFromEntry(id, entry, source);
4617
+ if (!server)
4415
4618
  continue;
4416
- servers.push(server2);
4619
+ servers.push(server);
4417
4620
  seen.add(id);
4418
4621
  }
4419
4622
  }
@@ -4445,7 +4648,7 @@ function createServerFromEntry(id, entry, source) {
4445
4648
  if (source === "project") {
4446
4649
  if (!builtin)
4447
4650
  return null;
4448
- const server3 = createServer({
4651
+ const server = createServer({
4449
4652
  id,
4450
4653
  command: builtin.command,
4451
4654
  extensions: entry.extensions ?? builtin.extensions,
@@ -4453,35 +4656,35 @@ function createServerFromEntry(id, entry, source) {
4453
4656
  source
4454
4657
  });
4455
4658
  if (entry.initialization !== undefined) {
4456
- server3.initialization = entry.initialization;
4659
+ server.initialization = entry.initialization;
4457
4660
  }
4458
- return server3;
4661
+ return server;
4459
4662
  }
4460
4663
  if (entry.command && entry.extensions) {
4461
- const server3 = createServer({
4664
+ const server = createServer({
4462
4665
  id,
4463
4666
  command: entry.command,
4464
4667
  extensions: entry.extensions,
4465
4668
  priority: entry.priority ?? 0,
4466
4669
  source
4467
4670
  });
4468
- applyOptionalServerFields(server3, entry);
4469
- return server3;
4671
+ applyOptionalServerFields(server, entry);
4672
+ return server;
4470
4673
  }
4471
4674
  if (!builtin)
4472
4675
  return null;
4473
- const server2 = createServer({
4676
+ const server = createServer({
4474
4677
  id,
4475
4678
  command: entry.command ?? builtin.command,
4476
4679
  extensions: entry.extensions ?? builtin.extensions,
4477
4680
  priority: entry.priority ?? 0,
4478
4681
  source
4479
4682
  });
4480
- applyOptionalServerFields(server2, entry);
4481
- return server2;
4683
+ applyOptionalServerFields(server, entry);
4684
+ return server;
4482
4685
  }
4483
4686
  function createServer(input) {
4484
- const server2 = {
4687
+ const server = {
4485
4688
  id: input.id,
4486
4689
  command: input.command,
4487
4690
  extensions: input.extensions,
@@ -4489,19 +4692,19 @@ function createServer(input) {
4489
4692
  source: input.source
4490
4693
  };
4491
4694
  if (input.env !== undefined) {
4492
- server2.env = input.env;
4695
+ server.env = input.env;
4493
4696
  }
4494
4697
  if (input.initialization !== undefined) {
4495
- server2.initialization = input.initialization;
4698
+ server.initialization = input.initialization;
4496
4699
  }
4497
- return server2;
4700
+ return server;
4498
4701
  }
4499
- function applyOptionalServerFields(server2, entry) {
4702
+ function applyOptionalServerFields(server, entry) {
4500
4703
  if (entry.env !== undefined) {
4501
- server2.env = entry.env;
4704
+ server.env = entry.env;
4502
4705
  }
4503
4706
  if (entry.initialization !== undefined) {
4504
- server2.initialization = entry.initialization;
4707
+ server.initialization = entry.initialization;
4505
4708
  }
4506
4709
  }
4507
4710
  function isConfigJson(value) {
@@ -4551,64 +4754,165 @@ function getDisabledServerIds() {
4551
4754
  }
4552
4755
 
4553
4756
  // ../lsp-core/src/lsp/server-installation.ts
4554
- import { existsSync as existsSync9 } from "node:fs";
4555
- import { delimiter as delimiter3, join as join3 } from "node:path";
4556
- function isServerInstalled(command, _workingDirectory) {
4557
- if (command.length === 0)
4558
- return false;
4559
- const [cmd] = command;
4560
- if (!cmd)
4561
- return false;
4562
- if (cmd.includes("/") || cmd.includes("\\")) {
4563
- if (existsSync9(cmd))
4564
- return true;
4757
+ import { existsSync as existsSync10 } from "node:fs";
4758
+ import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
4759
+ var LOCAL_BIN_RULES = [
4760
+ {
4761
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
4762
+ binDirs: [join4("node_modules", ".bin")]
4763
+ },
4764
+ {
4765
+ markers: [
4766
+ "pyproject.toml",
4767
+ "ty.toml",
4768
+ "requirements.txt",
4769
+ "setup.py",
4770
+ "setup.cfg",
4771
+ "Pipfile",
4772
+ "pyrightconfig.json",
4773
+ "ruff.toml",
4774
+ ".ruff.toml"
4775
+ ],
4776
+ binDirs: [
4777
+ join4(".venv", "bin"),
4778
+ join4(".venv", "Scripts"),
4779
+ join4("venv", "bin"),
4780
+ join4("venv", "Scripts"),
4781
+ join4(".env", "bin"),
4782
+ join4(".env", "Scripts")
4783
+ ]
4784
+ },
4785
+ {
4786
+ markers: ["Gemfile", "Gemfile.lock"],
4787
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
4788
+ },
4789
+ {
4790
+ markers: ["go.mod", "go.sum", "go.work"],
4791
+ binDirs: ["bin"]
4565
4792
  }
4566
- const isWindows = process.platform === "win32";
4567
- let exts = [""];
4568
- if (isWindows) {
4569
- const pathExt = process.env["PATHEXT"] ?? "";
4570
- if (pathExt) {
4571
- const systemExts = pathExt.split(";").filter(Boolean);
4572
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4573
- } else {
4574
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
4793
+ ];
4794
+ var resolutionCache = new Map;
4795
+ var probeCount = 0;
4796
+ function probe(path) {
4797
+ probeCount += 1;
4798
+ return existsSync10(path);
4799
+ }
4800
+ function executableSuffixes(platform, pathExt) {
4801
+ if (platform !== "win32")
4802
+ return [""];
4803
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
4804
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
4805
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4806
+ }
4807
+ function probeWithSuffixes(directory, command, suffixes) {
4808
+ for (const suffix of suffixes) {
4809
+ const candidate = join4(directory, command + suffix);
4810
+ if (probe(candidate))
4811
+ return candidate;
4812
+ }
4813
+ return null;
4814
+ }
4815
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
4816
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
4817
+ let current = resolve7(workingDirectory);
4818
+ while (true) {
4819
+ for (const rule of LOCAL_BIN_RULES) {
4820
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
4821
+ continue;
4822
+ for (const binDir of rule.binDirs) {
4823
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
4824
+ if (found !== null)
4825
+ return found;
4826
+ }
4575
4827
  }
4828
+ if (probe(join4(current, ".git")))
4829
+ return null;
4830
+ if (boundary !== undefined && current === boundary)
4831
+ return null;
4832
+ const parent = dirname9(current);
4833
+ if (parent === current)
4834
+ return null;
4835
+ current = parent;
4576
4836
  }
4577
- let pathEnv = process.env["PATH"] ?? "";
4578
- if (isWindows && !pathEnv) {
4837
+ }
4838
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
4839
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
4840
+ if (platform === "win32" && !pathEnv) {
4579
4841
  pathEnv = process.env["Path"] ?? "";
4580
4842
  }
4581
- const paths = pathEnv.split(delimiter3);
4582
- for (const p of paths) {
4583
- for (const suffix of exts) {
4584
- if (existsSync9(join3(p, cmd + suffix))) {
4585
- return true;
4586
- }
4587
- }
4843
+ for (const entry of pathEnv.split(delimiter3)) {
4844
+ if (entry.length === 0)
4845
+ continue;
4846
+ const found = probeWithSuffixes(entry, command, suffixes);
4847
+ if (found !== null)
4848
+ return found;
4588
4849
  }
4589
- if (cmd === "node")
4590
- return true;
4591
- return false;
4850
+ return null;
4851
+ }
4852
+ function resolveServerBinary(command, workingDirectory, options = {}) {
4853
+ if (command.length === 0)
4854
+ return null;
4855
+ const [cmd] = command;
4856
+ if (cmd === undefined || cmd.length === 0)
4857
+ return null;
4858
+ const platform = options.platform ?? process.platform;
4859
+ const suffixes = executableSuffixes(platform, options.pathExt);
4860
+ if (cmd.includes("/") || cmd.includes("\\")) {
4861
+ const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
4862
+ return probe(explicit) ? explicit : null;
4863
+ }
4864
+ const cacheKey = JSON.stringify([
4865
+ workingDirectory ?? "",
4866
+ cmd,
4867
+ platform,
4868
+ options.stopAt ?? "",
4869
+ options.pathExt ?? "",
4870
+ options.pathEnv ?? process.env["PATH"] ?? ""
4871
+ ]);
4872
+ const cached = resolutionCache.get(cacheKey);
4873
+ if (cached !== undefined)
4874
+ return cached;
4875
+ let resolved = null;
4876
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
4877
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
4878
+ }
4879
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
4880
+ if (resolved === null && cmd === "node")
4881
+ resolved = cmd;
4882
+ resolutionCache.set(cacheKey, resolved);
4883
+ return resolved;
4884
+ }
4885
+ function isServerInstalled(command, workingDirectory, options = {}) {
4886
+ if (command.length === 0)
4887
+ return false;
4888
+ return resolveServerBinary(command, workingDirectory, options) !== null;
4592
4889
  }
4593
4890
 
4594
4891
  // ../lsp-core/src/lsp/server-resolution.ts
4892
+ function withResolvedCommand(command, binaryPath) {
4893
+ return [binaryPath, ...command.slice(1)];
4894
+ }
4595
4895
  function findServerForExtension(ext) {
4596
4896
  const servers = getMergedServers();
4597
- for (const server2 of servers) {
4598
- if (server2.extensions.includes(ext) && isServerInstalled(server2.command)) {
4897
+ const workingDirectory = contextCwd();
4898
+ for (const server of servers) {
4899
+ if (!server.extensions.includes(ext))
4900
+ continue;
4901
+ const binaryPath = resolveServerBinary(server.command, workingDirectory);
4902
+ if (binaryPath !== null) {
4599
4903
  const resolvedServer = {
4600
- id: server2.id,
4601
- command: server2.command,
4602
- extensions: server2.extensions,
4603
- priority: server2.priority
4904
+ id: server.id,
4905
+ command: withResolvedCommand(server.command, binaryPath),
4906
+ extensions: server.extensions,
4907
+ priority: server.priority
4604
4908
  };
4605
- if (server2.env !== undefined) {
4909
+ if (server.env !== undefined) {
4606
4910
  return {
4607
4911
  status: "found",
4608
4912
  server: {
4609
4913
  ...resolvedServer,
4610
- env: server2.env,
4611
- ...server2.initialization === undefined ? {} : { initialization: server2.initialization }
4914
+ env: server.env,
4915
+ ...server.initialization === undefined ? {} : { initialization: server.initialization }
4612
4916
  }
4613
4917
  };
4614
4918
  }
@@ -4616,20 +4920,20 @@ function findServerForExtension(ext) {
4616
4920
  status: "found",
4617
4921
  server: {
4618
4922
  ...resolvedServer,
4619
- ...server2.initialization === undefined ? {} : { initialization: server2.initialization }
4923
+ ...server.initialization === undefined ? {} : { initialization: server.initialization }
4620
4924
  }
4621
4925
  };
4622
4926
  }
4623
4927
  }
4624
- for (const server2 of servers) {
4625
- if (server2.extensions.includes(ext)) {
4626
- const installHint = LSP_INSTALL_HINTS[server2.id] ?? `Install '${server2.command[0]}' and ensure it's in your PATH`;
4928
+ for (const server of servers) {
4929
+ if (server.extensions.includes(ext)) {
4930
+ const installHint = LSP_INSTALL_HINTS[server.id] ?? `Install '${server.command[0]}' and ensure it's in your PATH`;
4627
4931
  return {
4628
4932
  status: "not_installed",
4629
4933
  server: {
4630
- id: server2.id,
4631
- command: server2.command,
4632
- extensions: server2.extensions
4934
+ id: server.id,
4935
+ command: server.command,
4936
+ extensions: server.extensions
4633
4937
  },
4634
4938
  installHint
4635
4939
  };
@@ -4645,20 +4949,21 @@ function findServerForExtension(ext) {
4645
4949
  function getAllServers() {
4646
4950
  const servers = getMergedServers();
4647
4951
  const disabled = getDisabledServerIds();
4952
+ const workingDirectory = contextCwd();
4648
4953
  const result = [];
4649
4954
  const seen = new Set;
4650
- for (const server2 of servers) {
4651
- if (seen.has(server2.id))
4955
+ for (const server of servers) {
4956
+ if (seen.has(server.id))
4652
4957
  continue;
4653
4958
  result.push({
4654
- id: server2.id,
4655
- installed: isServerInstalled(server2.command),
4656
- extensions: server2.extensions,
4959
+ id: server.id,
4960
+ installed: isServerInstalled(server.command, workingDirectory),
4961
+ extensions: server.extensions,
4657
4962
  disabled: false,
4658
- source: server2.source,
4659
- priority: server2.priority
4963
+ source: server.source,
4964
+ priority: server.priority
4660
4965
  });
4661
- seen.add(server2.id);
4966
+ seen.add(server.id);
4662
4967
  }
4663
4968
  for (const id of disabled) {
4664
4969
  if (seen.has(id))
@@ -4666,7 +4971,7 @@ function getAllServers() {
4666
4971
  const builtin = BUILTIN_SERVERS[id];
4667
4972
  result.push({
4668
4973
  id,
4669
- installed: builtin ? isServerInstalled(builtin.command) : false,
4974
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
4670
4975
  extensions: builtin?.extensions ?? [],
4671
4976
  disabled: true,
4672
4977
  source: "disabled",
@@ -4677,7 +4982,6 @@ function getAllServers() {
4677
4982
  }
4678
4983
 
4679
4984
  // ../lsp-core/src/lsp/client-wrapper.ts
4680
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
4681
4985
  function isDirectoryPath(filePath) {
4682
4986
  try {
4683
4987
  return statSync4(filePath).isDirectory();
@@ -4690,36 +4994,40 @@ function findWorkspaceRoot(filePath) {
4690
4994
  const abs = resolveReadablePathInsideContext(filePath);
4691
4995
  let dir = abs;
4692
4996
  if (!isDirectoryPath(dir)) {
4693
- dir = dirname8(dir);
4997
+ dir = dirname10(dir);
4694
4998
  }
4999
+ if (!isPathInside(cwd, abs))
5000
+ return findWorkspaceRootOutsideContext(dir);
4695
5001
  const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
5002
+ let nearestPackageRoot;
4696
5003
  while (isPathInside(cwd, dir)) {
4697
5004
  const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4698
5005
  if (canonicalDir !== undefined) {
4699
- for (const marker of WORKSPACE_MARKERS) {
4700
- if (existsSync10(join4(dir, marker))) {
4701
- return canonicalDir;
4702
- }
5006
+ if (existsSync11(join5(dir, GIT_WORKSPACE_MARKER))) {
5007
+ return canonicalDir;
5008
+ }
5009
+ if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
5010
+ nearestPackageRoot = canonicalDir;
4703
5011
  }
4704
5012
  }
4705
5013
  if (dir === cwd)
4706
5014
  break;
4707
- dir = dirname8(dir);
5015
+ dir = dirname10(dir);
4708
5016
  }
4709
- return fallbackRoot;
5017
+ return nearestPackageRoot ?? fallbackRoot;
5018
+ }
5019
+ function hasProjectWorkspaceMarker(directory) {
5020
+ return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync11(join5(directory, marker)));
4710
5021
  }
4711
5022
  function resolveReadablePathInsideContext(filePath) {
4712
5023
  const cwd = contextCwd();
4713
- const abs = resolve7(cwd, filePath);
5024
+ const abs = resolve8(cwd, filePath);
4714
5025
  if (isPathInside(cwd, abs))
4715
5026
  return abs;
4716
5027
  const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4717
5028
  if (rebased !== undefined)
4718
5029
  return rebased;
4719
- const canonical = canonicalizeExistingOrNearestAncestor(abs);
4720
- if (isPathInside(cwd, canonical))
4721
- return canonical;
4722
- throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
5030
+ return canonicalizeExistingOrNearestAncestor(abs);
4723
5031
  }
4724
5032
  function resolvePathInsideContext(filePath) {
4725
5033
  const cwd = contextCwd();
@@ -4730,16 +5038,16 @@ function resolvePathInsideContext(filePath) {
4730
5038
  }
4731
5039
  return canonical;
4732
5040
  }
4733
- function rebaseThroughCanonicalAncestor(path2, cwd) {
4734
- let current = path2;
5041
+ function rebaseThroughCanonicalAncestor(path, cwd) {
5042
+ let current = path;
4735
5043
  const suffix = [];
4736
5044
  while (true) {
4737
- if (existsSync10(current)) {
4738
- const canonical = realpathSync4(current);
5045
+ if (existsSync11(current)) {
5046
+ const canonical = realpathSync5(current);
4739
5047
  if (isPathInside(cwd, canonical))
4740
- return suffix.length === 0 ? canonical : join4(canonical, ...suffix);
5048
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
4741
5049
  }
4742
- const parent = dirname8(current);
5050
+ const parent = dirname10(current);
4743
5051
  if (parent === current)
4744
5052
  return;
4745
5053
  suffix.unshift(basename3(current));
@@ -4747,9 +5055,9 @@ function rebaseThroughCanonicalAncestor(path2, cwd) {
4747
5055
  }
4748
5056
  }
4749
5057
  function existingDirectoryInsideContext(directory, cwd) {
4750
- if (!existsSync10(directory))
5058
+ if (!existsSync11(directory))
4751
5059
  return;
4752
- const canonical = realpathSync4(directory);
5060
+ const canonical = realpathSync5(directory);
4753
5061
  if (!statSync4(canonical).isDirectory())
4754
5062
  return;
4755
5063
  return isPathInside(cwd, canonical) ? canonical : undefined;
@@ -4762,7 +5070,7 @@ function nearestExistingDirectoryInsideContext(directory, cwd) {
4762
5070
  return canonical;
4763
5071
  if (current === cwd)
4764
5072
  return;
4765
- current = dirname8(current);
5073
+ current = dirname10(current);
4766
5074
  }
4767
5075
  return;
4768
5076
  }
@@ -4789,33 +5097,46 @@ function formatServerLookupError(result) {
4789
5097
  ].join(`
4790
5098
  `);
4791
5099
  }
5100
+ function formatInstallOptions(serverId, installHint) {
5101
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
5102
+ if (localHint === undefined) {
5103
+ return ["To install, run:", ` ${installHint}`];
5104
+ }
5105
+ return [
5106
+ "To install in THIS repository (preferred — no global install needed):",
5107
+ ` ${localHint}`,
5108
+ "",
5109
+ "Or install it globally:",
5110
+ ` ${installHint}`
5111
+ ];
5112
+ }
4792
5113
  function formatNotInstalled(result) {
4793
- const { server: server2, installHint } = result;
4794
- const extensions = server2.extensions.join(", ");
4795
- const decision = loadInstallDecision(server2.id)?.decision;
5114
+ const { server, installHint } = result;
5115
+ const extensions = server.extensions.join(", ");
5116
+ const decision = loadInstallDecision(server.id)?.decision;
4796
5117
  const context = lspRequestContext();
4797
5118
  if (decision === "declined") {
4798
- return `LSP server '${server2.id}' (${extensions}) is NOT INSTALLED; user previously declined installation — proceed without LSP.`;
5119
+ return `LSP server '${server.id}' (${extensions}) is NOT INSTALLED; user previously declined installation — proceed without LSP.`;
4799
5120
  }
4800
5121
  const header = [
4801
- `LSP server '${server2.id}' for ${extensions} is NOT INSTALLED.`,
5122
+ `LSP server '${server.id}' for ${extensions} is NOT INSTALLED.`,
4802
5123
  "",
4803
- `Command not found: ${server2.command[0]}`,
5124
+ `Command not found: ${server.command[0]}`,
4804
5125
  ""
4805
5126
  ];
5127
+ const installOptions = formatInstallOptions(server.id, installHint);
4806
5128
  if (decision === "allowed") {
4807
5129
  return [
4808
5130
  ...header,
4809
5131
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
4810
- ` ${installHint}`
5132
+ ...installOptions.slice(1)
4811
5133
  ].join(`
4812
5134
  `);
4813
5135
  }
4814
5136
  if (!context.capabilities.installDecisionTool) {
4815
5137
  return [
4816
5138
  ...header,
4817
- "To install, run:",
4818
- ` ${installHint}`,
5139
+ ...installOptions,
4819
5140
  "",
4820
5141
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4821
5142
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -4824,13 +5145,12 @@ function formatNotInstalled(result) {
4824
5145
  }
4825
5146
  return [
4826
5147
  ...header,
4827
- "To install, run:",
4828
- ` ${installHint}`,
5148
+ ...installOptions,
4829
5149
  "",
4830
5150
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4831
5151
  "- If the user agrees: run the install command above, then retry this tool.",
4832
5152
  "- If the user declines, OR has NOT explicitly asked for LSP installation:",
4833
- ` call lsp_install_decision { server_id: "${server2.id}", decision: "declined" },`,
5153
+ ` call lsp_install_decision { server_id: "${server.id}", decision: "declined" },`,
4834
5154
  ` which writes to ${context.installDecisionsPath},`,
4835
5155
  " then ignore this message and proceed WITHOUT LSP."
4836
5156
  ].join(`
@@ -4854,34 +5174,34 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4854
5174
  if (result.status !== "found") {
4855
5175
  throw new LspServerLookupError(formatServerLookupError(result), result);
4856
5176
  }
4857
- const server2 = result.server;
5177
+ const server = result.server;
4858
5178
  const root = findWorkspaceRoot(absPath);
4859
5179
  const manager = options.manager ?? getLspManager();
4860
5180
  const acquireAndCall = async (allowRetry) => {
4861
- const client = await manager.getClient(root, server2, options.signal);
5181
+ const client = await manager.getClient(root, server, options.signal);
4862
5182
  try {
4863
5183
  return await fn(client, root, absPath);
4864
5184
  } catch (err) {
4865
5185
  if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4866
- manager.invalidateClient(root, server2.id, client);
5186
+ manager.invalidateClient(root, server.id, client);
4867
5187
  return acquireAndCall(false);
4868
5188
  }
4869
5189
  if (err instanceof LspRequestTimeoutError) {
4870
- if (manager.isServerInitializing(root, server2.id)) {
5190
+ if (manager.isServerInitializing(root, server.id)) {
4871
5191
  throw new LspServerInitializingError(err);
4872
5192
  }
4873
5193
  }
4874
5194
  throw err;
4875
5195
  } finally {
4876
- manager.releaseClient(root, server2.id);
5196
+ manager.releaseClient(root, server.id);
4877
5197
  }
4878
5198
  };
4879
5199
  return acquireAndCall(true);
4880
5200
  }
4881
5201
 
4882
5202
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4883
- import { existsSync as existsSync11, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
4884
- import { join as join5, resolve as resolve8 } from "node:path";
5203
+ import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
5204
+ import { join as join6, resolve as resolve9 } from "node:path";
4885
5205
 
4886
5206
  // ../lsp-core/src/lsp/formatters.ts
4887
5207
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -4896,10 +5216,10 @@ function uriToPath(uri) {
4896
5216
  }
4897
5217
  function formatLocation(loc) {
4898
5218
  if ("targetUri" in loc) {
4899
- const uri2 = uriToPath(loc.targetUri);
4900
- const line2 = loc.targetRange.start.line + 1;
4901
- const char2 = loc.targetRange.start.character;
4902
- return `${uri2}:${line2}:${char2}`;
5219
+ const uri = uriToPath(loc.targetUri);
5220
+ const line = loc.targetRange.start.line + 1;
5221
+ const char = loc.targetRange.start.character;
5222
+ return `${uri}:${line}:${char}`;
4903
5223
  }
4904
5224
  const uri = uriToPath(loc.uri);
4905
5225
  const line = loc.range.start.line + 1;
@@ -5011,7 +5331,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
5011
5331
  for (const entry of entries) {
5012
5332
  if (files.length >= maxFiles)
5013
5333
  return;
5014
- const fullPath = join5(currentDir, entry);
5334
+ const fullPath = join6(currentDir, entry);
5015
5335
  let stat;
5016
5336
  try {
5017
5337
  stat = lstatSync5(fullPath);
@@ -5036,15 +5356,15 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5036
5356
  if (!extension.startsWith(".")) {
5037
5357
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
5038
5358
  }
5039
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
5040
- if (!existsSync11(absDir)) {
5359
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
5360
+ if (!existsSync12(absDir)) {
5041
5361
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
5042
5362
  }
5043
5363
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
5044
5364
  if (serverResult.status !== "found") {
5045
5365
  throw new LspServerLookupError(formatServerLookupError(serverResult));
5046
5366
  }
5047
- const server2 = serverResult.server;
5367
+ const server = serverResult.server;
5048
5368
  const allFiles = (options.listFiles ?? collectFilesWithExtension)(absDir, extension, maxFiles + 1);
5049
5369
  const wasCapped = allFiles.length > maxFiles;
5050
5370
  const filesToProcess = allFiles.slice(0, maxFiles);
@@ -5064,7 +5384,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5064
5384
  const fileErrors = [];
5065
5385
  const maxConcurrency = Math.max(1, options.maxConcurrency ?? DIRECTORY_DIAGNOSTICS_MAX_CONCURRENCY);
5066
5386
  options.signal?.throwIfAborted();
5067
- const client = await manager.getClient(root, server2, options.signal);
5387
+ const client = await manager.getClient(root, server, options.signal);
5068
5388
  try {
5069
5389
  let nextIndex = 0;
5070
5390
  const workers = Array.from({ length: Math.min(maxConcurrency, filesToProcess.length) }, async () => {
@@ -5092,7 +5412,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5092
5412
  });
5093
5413
  await Promise.all(workers);
5094
5414
  } finally {
5095
- manager.releaseClient(root, server2.id);
5415
+ manager.releaseClient(root, server.id);
5096
5416
  }
5097
5417
  const displayDiagnostics = allDiagnostics.slice(0, DEFAULT_MAX_DIAGNOSTICS);
5098
5418
  const wasDiagCapped = allDiagnostics.length > DEFAULT_MAX_DIAGNOSTICS;
@@ -5124,7 +5444,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5124
5444
 
5125
5445
  // ../lsp-core/src/lsp/infer-extension.ts
5126
5446
  import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
5127
- import { join as join6 } from "node:path";
5447
+ import { join as join7 } from "node:path";
5128
5448
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
5129
5449
  var MAX_SCAN_ENTRIES = 500;
5130
5450
  function inferExtensionFromDirectory(directory) {
@@ -5142,7 +5462,7 @@ function inferExtensionFromDirectory(directory) {
5142
5462
  for (const entry of entries) {
5143
5463
  if (scanned >= MAX_SCAN_ENTRIES)
5144
5464
  return;
5145
- const fullPath = join6(dir, entry);
5465
+ const fullPath = join7(dir, entry);
5146
5466
  let stat;
5147
5467
  try {
5148
5468
  stat = lstatSync6(fullPath);
@@ -5301,8 +5621,8 @@ function clientOptions(signal) {
5301
5621
  }
5302
5622
 
5303
5623
  // ../lsp-core/src/tools/result.ts
5304
- function text(text2, details, isError = false) {
5305
- return { content: [{ type: "text", text: text2 }], details, isError };
5624
+ function text(text, details, isError = false) {
5625
+ return { content: [{ type: "text", text }], details, isError };
5306
5626
  }
5307
5627
 
5308
5628
  // ../lsp-core/src/tools/diagnostics.ts
@@ -5322,7 +5642,7 @@ async function executeLspDiagnostics(params, signal) {
5322
5642
  const extension = inferExtensionFromDirectory(absPath);
5323
5643
  if (!extension) {
5324
5644
  const message = `No supported source files found in directory: ${absPath}`;
5325
- const details3 = {
5645
+ const details = {
5326
5646
  filePath,
5327
5647
  severity,
5328
5648
  mode: "directory",
@@ -5332,24 +5652,24 @@ async function executeLspDiagnostics(params, signal) {
5332
5652
  error: message,
5333
5653
  errorKind: "no_files"
5334
5654
  };
5335
- return text(message, details3);
5655
+ return text(message, details);
5336
5656
  }
5337
- const output2 = await aggregateDiagnosticsForDirectory(absPath, extension, severity, undefined, signal === undefined ? {} : { signal });
5338
- const details2 = {
5657
+ const output = await aggregateDiagnosticsForDirectory(absPath, extension, severity, undefined, signal === undefined ? {} : { signal });
5658
+ const details = {
5339
5659
  filePath,
5340
5660
  severity,
5341
5661
  mode: "directory",
5342
5662
  diagnostics: [],
5343
- totalDiagnostics: output2.totalDiagnostics,
5663
+ totalDiagnostics: output.totalDiagnostics,
5344
5664
  truncated: false,
5345
- fileFailures: [...output2.fileFailures]
5665
+ fileFailures: [...output.fileFailures]
5346
5666
  };
5347
- return text(output2.output, details2);
5667
+ return text(output.output, details);
5348
5668
  }
5349
5669
  const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
5350
5670
  if (result.transientError) {
5351
5671
  const message = result.transientError.message;
5352
- const details2 = {
5672
+ const details = {
5353
5673
  filePath,
5354
5674
  severity,
5355
5675
  mode: "file",
@@ -5359,7 +5679,7 @@ async function executeLspDiagnostics(params, signal) {
5359
5679
  error: message,
5360
5680
  errorKind: result.transientError.kind
5361
5681
  };
5362
- return text(message, details2, true);
5682
+ return text(message, details, true);
5363
5683
  }
5364
5684
  const diagnostics = filterDiagnosticsBySeverity(asDiagnosticArray(result), severity);
5365
5685
  const total = diagnostics.length;
@@ -5393,6 +5713,96 @@ async function executeLspDiagnostics(params, signal) {
5393
5713
  throw error;
5394
5714
  }
5395
5715
  }
5716
+ // ../lsp-core/src/lsp/format-document.ts
5717
+ import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
5718
+ var DEFAULT_FORMATTING_OPTIONS = {
5719
+ tabSize: 4,
5720
+ insertSpaces: false,
5721
+ trimTrailingWhitespace: true,
5722
+ insertFinalNewline: true,
5723
+ trimFinalNewlines: true
5724
+ };
5725
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
5726
+ async function formatDocumentWithClient(client, filePath, options = {}) {
5727
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
5728
+ if (edits === null)
5729
+ return { status: "unavailable", reason: "capability_not_advertised" };
5730
+ if (edits.length === 0)
5731
+ return UNCHANGED;
5732
+ const before = readFileSync6(filePath, "utf-8");
5733
+ const normalized = normalizeTextEdits(before, edits, 0);
5734
+ if (normalized.text === before)
5735
+ return UNCHANGED;
5736
+ writeAtomically(filePath, normalized.text);
5737
+ await client.openFile(filePath);
5738
+ return {
5739
+ status: "formatted",
5740
+ ...lineDelta(normalized.edits)
5741
+ };
5742
+ }
5743
+ function lineDelta(edits) {
5744
+ let linesAdded = 0;
5745
+ let linesRemoved = 0;
5746
+ for (const edit of edits) {
5747
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
5748
+ linesAdded += edit.newText.split(`
5749
+ `).length;
5750
+ }
5751
+ return { linesAdded, linesRemoved };
5752
+ }
5753
+ function writeAtomically(filePath, content) {
5754
+ const tempPath = `${filePath}.omo-format.tmp`;
5755
+ writeFileSync3(tempPath, content, "utf-8");
5756
+ try {
5757
+ renameSync3(tempPath, filePath);
5758
+ } catch (error) {
5759
+ try {
5760
+ unlinkSync2(tempPath);
5761
+ } catch {}
5762
+ throw error;
5763
+ }
5764
+ }
5765
+
5766
+ // ../lsp-core/src/tools/format.ts
5767
+ async function executeLspFormat(params, signal) {
5768
+ const filePath = requireString(params, "filePath");
5769
+ try {
5770
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
5771
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
5772
+ } catch (error) {
5773
+ const missingDependency = missingDependencyResult(error, {
5774
+ filePath,
5775
+ status: "unavailable",
5776
+ reason: "server_unavailable",
5777
+ linesAdded: 0,
5778
+ linesRemoved: 0
5779
+ });
5780
+ if (missingDependency)
5781
+ return missingDependency;
5782
+ throw error;
5783
+ }
5784
+ }
5785
+ function formatDetails(filePath, result) {
5786
+ if (result.status === "unavailable") {
5787
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
5788
+ }
5789
+ return {
5790
+ filePath,
5791
+ status: result.status,
5792
+ linesAdded: result.linesAdded,
5793
+ linesRemoved: result.linesRemoved
5794
+ };
5795
+ }
5796
+ function describeResult(filePath, result) {
5797
+ if (result.status === "unavailable") {
5798
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
5799
+ }
5800
+ if (result.status === "unchanged") {
5801
+ return `Already formatted: ${filePath}`;
5802
+ }
5803
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
5804
+ }
5805
+
5396
5806
  // ../lsp-core/src/tools/install-decision.ts
5397
5807
  async function executeLspInstallDecision(params) {
5398
5808
  const serverId = requireString(params, "server_id");
@@ -5400,7 +5810,7 @@ async function executeLspInstallDecision(params) {
5400
5810
  if (!isInstallDecision(decision)) {
5401
5811
  return text(`Invalid decision '${String(decision)}'. Expected "declined" or "allowed".`, { serverId, errorKind: "invalid_decision" }, true);
5402
5812
  }
5403
- const serverIds = [...new Set(getMergedServers().map((server2) => server2.id))];
5813
+ const serverIds = [...new Set(getMergedServers().map((server) => server.id))];
5404
5814
  if (!serverIds.includes(serverId)) {
5405
5815
  const preview = serverIds.slice(0, 20).join(", ");
5406
5816
  return text(`Unknown LSP server '${serverId}'. Known servers: ${preview}${serverIds.length > 20 ? "..." : ""}`, { serverId, errorKind: "unknown_server" }, true);
@@ -5540,10 +5950,10 @@ function objectSchema(properties, required = []) {
5540
5950
  async function executeLspStatus() {
5541
5951
  const servers = getAllServers();
5542
5952
  const snapshots = getLspManager().getSnapshot();
5543
- const installed = servers.filter((server2) => server2.installed && !server2.disabled);
5544
- const configuredLines = servers.map((server2) => {
5545
- const state = server2.disabled ? "disabled" : server2.installed ? "installed" : "missing";
5546
- return `- ${server2.id}: ${state}; source=${server2.source}; extensions=${server2.extensions.join(", ")}`;
5953
+ const installed = servers.filter((server) => server.installed && !server.disabled);
5954
+ const configuredLines = servers.map((server) => {
5955
+ const state = server.disabled ? "disabled" : server.installed ? "installed" : "missing";
5956
+ return `- ${server.id}: ${state}; source=${server.source}; extensions=${server.extensions.join(", ")}`;
5547
5957
  });
5548
5958
  const activeLines = snapshots.map((snapshot) => {
5549
5959
  const state = snapshot.alive ? snapshot.isInitializing ? "initializing" : "alive" : "dead";
@@ -5586,8 +5996,8 @@ async function executeLspSymbols(params, signal) {
5586
5996
  errorKind: "missing_query"
5587
5997
  });
5588
5998
  }
5589
- const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
5590
- return formatSymbolsResult(filePath, scope, symbols2, limit, query);
5999
+ const symbols = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
6000
+ return formatSymbolsResult(filePath, scope, symbols, limit, query);
5591
6001
  }
5592
6002
  const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
5593
6003
  return formatSymbolsResult(filePath, scope, symbols, limit);
@@ -5725,6 +6135,16 @@ var LSP_MCP_TOOLS = [
5725
6135
  }, ["filePath", "line", "character", "newName"]),
5726
6136
  execute: executeLspRename
5727
6137
  },
6138
+ {
6139
+ name: "format",
6140
+ aliases: ["lsp_format"],
6141
+ title: "LSP Format",
6142
+ description: "Format a source file with its language server and write the returned edits to disk.",
6143
+ inputSchema: objectSchema({
6144
+ filePath: { type: "string", description: "Source file path to format." }
6145
+ }, ["filePath"]),
6146
+ execute: executeLspFormat
6147
+ },
5728
6148
  {
5729
6149
  name: "install_decision",
5730
6150
  aliases: ["lsp_install_decision"],
@@ -5825,7 +6245,10 @@ function requestedProtocolVersion(params) {
5825
6245
  var CONTEXT_KEY = "_context";
5826
6246
 
5827
6247
  class InvalidDaemonRequestError extends Error {
5828
- name = "InvalidDaemonRequestError";
6248
+ constructor() {
6249
+ super(...arguments);
6250
+ this.name = "InvalidDaemonRequestError";
6251
+ }
5829
6252
  }
5830
6253
  function extractRequestContext(raw) {
5831
6254
  if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
@@ -5941,14 +6364,17 @@ async function callToolViaDaemon(name, args, options) {
5941
6364
  function callDiagnosticsViaDaemon(filePath, options) {
5942
6365
  return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
5943
6366
  }
6367
+ function callFormatViaDaemon(filePath, options) {
6368
+ return callToolViaDaemon("format", { filePath }, options);
6369
+ }
5944
6370
  function currentRequestContext(env = process.env) {
5945
6371
  const cwd = process.cwd();
5946
6372
  const home = env["HOME"] ?? homedir3();
5947
6373
  return parseLspRequestContext({
5948
6374
  cwd,
5949
- projectConfigPaths: [join7(cwd, ".codex", "lsp-client.json")],
5950
- userConfigPath: join7(home, ".codex", "lsp-client.json"),
5951
- installDecisionsPath: join7(home, ".codex", "lsp-install-decisions.json"),
6375
+ projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
6376
+ userConfigPath: join8(home, ".codex", "lsp-client.json"),
6377
+ installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
5952
6378
  capabilities: { installDecisionTool: true }
5953
6379
  });
5954
6380
  }
@@ -5963,7 +6389,7 @@ function withContext(args, context) {
5963
6389
  function ensureDaemonAvailable(paths, ensure, signal) {
5964
6390
  if (!signal)
5965
6391
  return ensure(paths);
5966
- return new Promise((resolve9, reject) => {
6392
+ return new Promise((resolve, reject) => {
5967
6393
  let settled = false;
5968
6394
  const finish = (run) => {
5969
6395
  if (settled)
@@ -5978,11 +6404,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
5978
6404
  return;
5979
6405
  }
5980
6406
  signal.addEventListener("abort", onAbort, { once: true });
5981
- Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve9()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
6407
+ Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
5982
6408
  });
5983
6409
  }
5984
6410
  function sendToolCall(paths, token, name, args, options) {
5985
- return new Promise((resolve9, reject) => {
6411
+ return new Promise((resolve, reject) => {
5986
6412
  const socket = connect(paths.socket);
5987
6413
  const requestId = allocateProxyRequestId();
5988
6414
  let settled = false;
@@ -6035,7 +6461,7 @@ function sendToolCall(paths, token, name, args, options) {
6035
6461
  }
6036
6462
  const result = toToolResult(message, requestId);
6037
6463
  if (result)
6038
- finish(() => resolve9(result));
6464
+ finish(() => resolve(result));
6039
6465
  else
6040
6466
  finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
6041
6467
  });
@@ -6081,18 +6507,15 @@ function isRetryableTool(name) {
6081
6507
  }
6082
6508
 
6083
6509
  // src/client.ts
6084
- import { statSync as statSync5 } from "node:fs";
6085
- import { isAbsolute as isAbsolute5 } from "node:path";
6086
6510
  var OMO_LSP_DAEMON_DIR2 = "OMO_LSP_DAEMON_DIR";
6087
6511
  var OMO_LSP_DAEMON_CLI2 = "OMO_LSP_DAEMON_CLI";
6088
6512
  var OMO_LSP_DAEMON_VERSION2 = "OMO_LSP_DAEMON_VERSION";
6089
6513
  var DAEMON_VERSION_PATTERN2 = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
6090
6514
 
6091
6515
  class InvalidRuntimeOverrideError2 extends Error {
6092
- code = "invalid_runtime_override";
6093
- reason;
6094
6516
  constructor(reason, message) {
6095
6517
  super(message);
6518
+ this.code = "invalid_runtime_override";
6096
6519
  this.name = "InvalidRuntimeOverrideError";
6097
6520
  this.reason = reason;
6098
6521
  }
@@ -6112,12 +6535,12 @@ function resolveDaemonRuntime2(env, defaults) {
6112
6535
  throw new InvalidRuntimeOverrideError2("paired_values_required", `${OMO_LSP_DAEMON_CLI2} and ${OMO_LSP_DAEMON_VERSION2} must be set together`);
6113
6536
  }
6114
6537
  if (!hasCliOverride || !hasVersionOverride) {
6115
- if (!isAbsolute5(defaults.cliPath)) {
6538
+ if (!isAbsolute6(defaults.cliPath)) {
6116
6539
  throw new InvalidRuntimeOverrideError2("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
6117
6540
  }
6118
6541
  return { cliPath: defaults.cliPath, version: validateDaemonVersion2(defaults.version) };
6119
6542
  }
6120
- if (!isAbsolute5(cliOverride)) {
6543
+ if (!isAbsolute6(cliOverride)) {
6121
6544
  throw new InvalidRuntimeOverrideError2("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI2} must be an absolute path to an existing regular file`);
6122
6545
  }
6123
6546
  const stat = statSync5(cliOverride, { throwIfNoEntry: false });
@@ -6135,17 +6558,21 @@ function callToolViaDaemon2(name, args, options) {
6135
6558
  function callDiagnosticsViaDaemon2(filePath, options) {
6136
6559
  return callDiagnosticsViaDaemon(filePath, options);
6137
6560
  }
6561
+ function callFormatViaDaemon2(filePath, options) {
6562
+ return callFormatViaDaemon(filePath, options);
6563
+ }
6138
6564
  function currentRequestContext2(env = process.env) {
6139
6565
  return currentRequestContext(env);
6140
6566
  }
6141
6567
  export {
6142
- validateDaemonVersion2 as validateDaemonVersion,
6143
- resolveDaemonRuntime2 as resolveDaemonRuntime,
6144
- currentRequestContext2 as currentRequestContext,
6145
- callToolViaDaemon2 as callToolViaDaemon,
6146
- callDiagnosticsViaDaemon2 as callDiagnosticsViaDaemon,
6147
- OMO_LSP_DAEMON_VERSION2 as OMO_LSP_DAEMON_VERSION,
6148
- OMO_LSP_DAEMON_DIR2 as OMO_LSP_DAEMON_DIR,
6568
+ InvalidRuntimeOverrideError2 as InvalidRuntimeOverrideError,
6149
6569
  OMO_LSP_DAEMON_CLI2 as OMO_LSP_DAEMON_CLI,
6150
- InvalidRuntimeOverrideError2 as InvalidRuntimeOverrideError
6570
+ OMO_LSP_DAEMON_DIR2 as OMO_LSP_DAEMON_DIR,
6571
+ OMO_LSP_DAEMON_VERSION2 as OMO_LSP_DAEMON_VERSION,
6572
+ callDiagnosticsViaDaemon2 as callDiagnosticsViaDaemon,
6573
+ callFormatViaDaemon2 as callFormatViaDaemon,
6574
+ callToolViaDaemon2 as callToolViaDaemon,
6575
+ currentRequestContext2 as currentRequestContext,
6576
+ resolveDaemonRuntime2 as resolveDaemonRuntime,
6577
+ validateDaemonVersion2 as validateDaemonVersion
6151
6578
  };