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

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 (997) 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 +52548 -60412
  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 +51202 -59043
  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 +7093 -408
  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/bootstrap/src/setup.ts +7 -1
  307. package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +9 -0
  308. package/packages/omo-codex/plugin/components/comment-checker/biome.json +2 -2
  309. package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +2 -1
  310. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  311. package/packages/omo-codex/plugin/components/comment-checker/package.json +5 -5
  312. package/packages/omo-codex/plugin/components/comment-checker/src/apply-patch.ts +2 -8
  313. package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +1 -2
  314. package/packages/omo-codex/plugin/components/comment-checker/src/request-extractor.ts +1 -1
  315. package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +1 -0
  316. package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +1 -1
  317. package/packages/omo-codex/plugin/components/git-bash/dist/cli.js +1 -1
  318. package/packages/omo-codex/plugin/components/git-bash/dist/codex-hook.js +2 -1
  319. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  320. package/packages/omo-codex/plugin/components/git-bash/package.json +3 -4
  321. package/packages/omo-codex/plugin/components/git-bash/src/codex-hook.ts +2 -1
  322. package/packages/omo-codex/plugin/components/git-bash/test/codex-hook.test.ts +6 -7
  323. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/AGENTS.md +2 -2
  324. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
  325. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/directive.md +2 -0
  326. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +36 -29
  327. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +32 -26
  328. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/types.d.ts +3 -0
  329. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  330. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +5 -5
  331. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +32 -28
  332. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/types.ts +3 -0
  333. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/cli.test.ts +1 -1
  334. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +137 -28
  335. package/packages/omo-codex/plugin/components/lcx/skills/lcx-doctor/SKILL.md +4 -2
  336. package/packages/omo-codex/plugin/components/lsp/AGENTS.md +30 -15
  337. package/packages/omo-codex/plugin/components/lsp/biome.json +2 -2
  338. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +4 -4
  339. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +941 -540
  340. package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.js +1 -1
  341. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  342. package/packages/omo-codex/plugin/components/lsp/package.json +5 -5
  343. package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
  344. package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +1 -1
  345. package/packages/omo-codex/plugin/components/lsp/src/daemon-cli-path.ts +1 -5
  346. package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +6 -7
  347. package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +1 -2
  348. package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +11 -1
  349. package/packages/omo-codex/plugin/components/rules/AGENTS.md +12 -0
  350. package/packages/omo-codex/plugin/components/rules/README.md +2 -0
  351. package/packages/omo-codex/plugin/components/rules/biome.json +2 -2
  352. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-6.md +123 -0
  353. package/packages/omo-codex/plugin/components/rules/dist/cli.js +91 -68
  354. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  355. package/packages/omo-codex/plugin/components/rules/package.json +7 -7
  356. package/packages/omo-codex/plugin/components/rules/src/config.ts +1 -2
  357. package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +1 -2
  358. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +15 -5
  359. package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +1 -4
  360. package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +4 -9
  361. package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
  362. package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +17 -25
  363. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
  364. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
  365. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
  366. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
  367. package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
  368. package/packages/omo-codex/plugin/components/rules/test/dynamic-target-fingerprints.test.ts +1 -2
  369. package/packages/omo-codex/plugin/components/rules/test/engine.test.ts +7 -4
  370. package/packages/omo-codex/plugin/components/rules/test/finder.test.ts +2 -3
  371. package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +39 -72
  372. package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +38 -3
  373. package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
  374. package/packages/omo-codex/plugin/components/rules/test/matcher.test.ts +2 -3
  375. package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +1 -1
  376. package/packages/omo-codex/plugin/components/rules/test/parser.test.ts +1 -2
  377. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +29 -6
  378. package/packages/omo-codex/plugin/components/rules/test/rules-engine-consumption.test.ts +3 -6
  379. package/packages/omo-codex/plugin/components/rules/test/scanner.test.ts +1 -2
  380. package/packages/omo-codex/plugin/components/rules/test/sources.test.ts +2 -5
  381. package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +2 -17
  382. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  383. package/packages/omo-codex/plugin/components/teammode/package.json +5 -5
  384. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +4 -10
  385. package/packages/omo-codex/plugin/components/telemetry/AGENTS.md +8 -0
  386. package/packages/omo-codex/plugin/components/telemetry/biome.json +2 -2
  387. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2407 -684
  388. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2411 -689
  389. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  390. package/packages/omo-codex/plugin/components/telemetry/package.json +5 -5
  391. package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +1 -4
  392. package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -14
  393. package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +1 -1
  394. package/packages/omo-codex/plugin/components/telemetry/test/diagnostics.test.ts +2 -5
  395. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +10 -4
  396. package/packages/omo-codex/plugin/components/ultrawork/README.md +2 -0
  397. package/packages/omo-codex/plugin/components/ultrawork/agents/explorer.toml +1 -1
  398. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +1 -1
  399. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +1 -1
  400. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
  401. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.toml +1 -1
  402. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
  403. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-low.toml +1 -1
  404. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +1 -1
  405. package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +1 -1
  406. package/packages/omo-codex/plugin/components/ultrawork/agents/metis.toml +1 -1
  407. package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +1 -1
  408. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
  409. package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
  410. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +499 -4
  411. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  412. package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -6
  413. package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +30 -14
  414. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -7
  415. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +31 -7
  416. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
  417. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +5 -5
  418. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +4 -0
  419. package/packages/omo-codex/plugin/components/ultrawork/src/directive.ts +5 -2
  420. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +9 -1
  421. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
  422. package/packages/omo-codex/plugin/components/ultrawork/test/directive-source.test.ts +14 -8
  423. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +12 -1
  424. package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
  425. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +4 -4
  426. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/NOTICE +1 -1
  427. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/README.md +6 -6
  428. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/biome.json +2 -2
  429. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/directive.md +10 -10
  430. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +16 -16
  431. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +16 -0
  432. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/package.json +12 -12
  433. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/boulder-reader.ts +1 -1
  434. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/cli.ts +1 -1
  435. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/codex-hook.ts +4 -4
  436. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/directive.ts +1 -1
  437. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/index.ts +1 -1
  438. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/types.ts +1 -1
  439. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/boulder-reader.test.ts +3 -3
  440. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +4 -11
  441. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +24 -22
  442. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +19 -0
  443. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +3 -1
  444. package/packages/omo-codex/plugin/components/ulw-loop/README.md +12 -1
  445. package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
  446. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +46 -24
  447. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.d.ts +16 -0
  448. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +25 -0
  449. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +10 -4
  450. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +2 -5
  451. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +5 -78
  452. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.d.ts +12 -0
  453. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +114 -0
  454. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.d.ts +7 -1
  455. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +50 -42
  456. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +2 -2
  457. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +21 -8
  458. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
  459. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +12 -1
  460. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +1 -1
  461. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +40 -37
  462. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +1468 -535
  463. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.d.ts +2 -0
  464. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +28 -8
  465. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +2 -5
  466. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +24 -20
  467. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -0
  468. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +1 -0
  469. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +17 -9
  470. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.d.ts +1 -0
  471. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +13 -4
  472. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
  473. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +34 -4
  474. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +14 -0
  475. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +29 -0
  476. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +7 -0
  477. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +9 -0
  478. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.d.ts +12 -0
  479. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +104 -0
  480. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.d.ts +13 -1
  481. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +65 -9
  482. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +5 -1
  483. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +4 -2
  484. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +72 -117
  485. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.d.ts +2 -0
  486. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +16 -7
  487. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/factory.d.ts +2 -0
  488. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/factory.js +141 -0
  489. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/manifest.d.ts +46 -0
  490. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/manifest.js +28 -0
  491. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/types.d.ts +127 -0
  492. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/types.js +1 -0
  493. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk.d.ts +3 -0
  494. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk.js +3 -0
  495. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.d.ts +7 -1
  496. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +216 -33
  497. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-role-guard.d.ts +2 -0
  498. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-role-guard.js +22 -0
  499. package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.d.ts +9 -0
  500. package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.js +227 -0
  501. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +6 -0
  502. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +33 -0
  503. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +20 -6
  504. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +19 -0
  505. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +75 -0
  506. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +18 -5
  507. package/packages/omo-codex/plugin/components/ulw-loop/package.json +6 -6
  508. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +10 -4
  509. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
  510. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +32 -8
  511. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +40 -0
  512. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +8 -6
  513. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +5 -98
  514. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +134 -0
  515. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +52 -73
  516. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +10 -4
  517. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +24 -8
  518. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +14 -1
  519. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +52 -46
  520. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +8 -6
  521. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +35 -7
  522. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +34 -28
  523. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
  524. package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +1 -0
  525. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +19 -9
  526. package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +25 -4
  527. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +39 -4
  528. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +38 -0
  529. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +11 -0
  530. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +123 -0
  531. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +71 -15
  532. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +6 -1
  533. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +92 -136
  534. package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +29 -8
  535. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/factory.ts +183 -0
  536. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/manifest.ts +42 -0
  537. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/types.ts +140 -0
  538. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk.ts +3 -0
  539. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +226 -31
  540. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-role-guard.ts +22 -0
  541. package/packages/omo-codex/plugin/components/ulw-loop/src/state-lock.ts +239 -0
  542. package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +36 -0
  543. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +19 -6
  544. package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +107 -0
  545. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
  546. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +131 -82
  547. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +147 -0
  548. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint.test.ts +16 -22
  549. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +4 -2
  550. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint.test.ts +31 -2
  551. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-commands.test.ts +2 -0
  552. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-complete-goals.test.ts +3 -1
  553. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +35 -8
  554. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +38 -4
  555. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-json-errors.test.ts +27 -0
  556. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-scope-required.test.ts +144 -0
  557. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-status-next-actions.test.ts +185 -0
  558. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +8 -3
  559. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +6 -0
  560. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +37 -2
  561. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +52 -11
  562. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
  563. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/cli-session.ts +4 -0
  564. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +9 -4
  565. package/packages/omo-codex/plugin/components/ulw-loop/test/guided-recovery.test.ts +67 -0
  566. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -37
  567. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +9 -0
  568. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io-cross-process.test.ts +106 -0
  569. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +36 -2
  570. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate-basics.test.ts +258 -0
  571. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-cap-and-dedupe.test.ts +22 -0
  572. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-fields-messages.test.ts +98 -0
  573. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-lazycodex-surface.test.ts +93 -0
  574. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-poisoning-cascades.test.ts +97 -0
  575. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +51 -2
  576. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-senpi-surface.test.ts +131 -0
  577. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-single-report.test.ts +241 -0
  578. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +58 -3
  579. package/packages/omo-codex/plugin/components/ulw-loop/test/review-blockers.test.ts +9 -7
  580. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-contract.test.ts +137 -0
  581. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-driver-states.test.ts +145 -0
  582. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-session-context.test.ts +148 -0
  583. package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +450 -7
  584. package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-role-matrix.test.ts +113 -0
  585. package/packages/omo-codex/plugin/components/ulw-loop/test/state-lock.test.ts +218 -0
  586. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +8 -5
  587. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
  588. package/packages/omo-codex/plugin/components/ulw-loop/test/surface.test.ts +74 -0
  589. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +13 -8
  590. package/packages/omo-codex/plugin/components/ulw-loop/vitest.config.ts +1 -0
  591. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  592. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  593. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  594. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  595. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  596. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  597. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  598. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +18 -0
  599. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  600. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  601. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  602. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  603. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  604. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  605. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  606. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +17 -0
  607. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  608. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  609. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  610. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  611. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  612. package/packages/omo-codex/plugin/model-catalog.json +16 -7
  613. package/packages/omo-codex/plugin/package-lock.json +676 -524
  614. package/packages/omo-codex/plugin/package.json +2 -3
  615. package/packages/omo-codex/plugin/scripts/AGENTS.md +39 -0
  616. package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -2
  617. package/packages/omo-codex/plugin/scripts/auto-update.mjs +0 -9
  618. package/packages/omo-codex/plugin/scripts/canonical-ultrawork-directive.mjs +17 -0
  619. package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +0 -1
  620. package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +16 -7
  621. package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +8 -4
  622. package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +19 -90
  623. package/packages/omo-codex/plugin/scripts/migrate-codex-config/toml-section-editor.mjs +1 -1
  624. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +96 -57
  625. package/packages/omo-codex/plugin/shared/package.json +3 -4
  626. package/packages/omo-codex/plugin/shared/src/config-loader.ts +2 -102
  627. package/packages/omo-codex/plugin/shared/src/config-migration.ts +0 -1
  628. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +41 -130
  629. package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +51 -0
  630. package/packages/omo-codex/plugin/skills/ast-grep/SKILL.md +1 -1
  631. package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +62 -0
  632. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +1 -1
  633. package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
  634. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
  635. package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
  636. package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
  637. package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
  638. package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
  639. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  640. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  641. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +3 -1
  642. package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
  643. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
  644. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
  645. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
  646. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
  647. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
  648. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
  649. package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
  650. package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  651. package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
  652. package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
  653. package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +10 -0
  654. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +15 -8
  655. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +10 -2
  656. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +2 -0
  657. package/packages/omo-codex/plugin/skills/frontend/references/design/ambience-skill.md +145 -0
  658. package/packages/omo-codex/plugin/skills/frontend/references/design/interaction-skill.md +2 -0
  659. package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
  660. package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
  661. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
  662. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  663. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  664. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  665. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
  666. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
  667. package/packages/omo-codex/plugin/skills/git-master/SKILL.md +1 -1
  668. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +20 -18
  669. package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +4 -2
  670. package/packages/omo-codex/plugin/skills/lsp-setup/SKILL.md +1 -1
  671. package/packages/omo-codex/plugin/skills/programming/SKILL.md +1 -1
  672. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +10 -8
  673. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +7 -5
  674. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +116 -424
  675. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
  676. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +26 -9
  677. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  678. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
  679. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +23 -18
  680. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  681. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +46 -24
  682. package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +31 -33
  683. package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
  684. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +34 -4
  685. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
  686. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +32 -8
  687. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -7
  688. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +31 -7
  689. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
  690. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +5 -5
  691. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +14 -7
  692. package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
  693. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +10 -7
  694. package/packages/omo-codex/plugin/test/AGENTS.md +47 -0
  695. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
  696. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +16 -51
  697. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +2 -3
  698. package/packages/omo-codex/plugin/test/aggregate-mcp.test.mjs +2 -7
  699. package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +14 -4
  700. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
  701. package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
  702. package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
  703. package/packages/omo-codex/plugin/test/auto-update.test.mjs +4 -29
  704. package/packages/omo-codex/plugin/test/bootstrap-default-role.test.mjs +66 -0
  705. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +0 -31
  706. package/packages/omo-codex/plugin/test/canonical-ultrawork-directive.test.mjs +53 -0
  707. package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +2 -2
  708. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +1 -51
  709. package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +100 -2
  710. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +5 -6
  711. package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
  712. package/packages/omo-codex/plugin/test/mcp-research-servers.test.mjs +1 -3
  713. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +35 -35
  714. package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +1 -1
  715. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
  716. package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +107 -15
  717. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +168 -0
  718. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +54 -24
  719. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +18 -119
  720. package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
  721. package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
  722. package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
  723. package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
  724. package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
  725. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +5 -5
  726. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
  727. package/packages/omo-codex/scripts/AGENTS.md +36 -0
  728. package/packages/omo-codex/scripts/check-model-catalog-parity.mjs +42 -0
  729. package/packages/omo-codex/scripts/install-cache-copy.test.mjs +27 -1
  730. package/packages/omo-codex/scripts/install-config-autonomous-features.test.mjs +1 -1
  731. package/packages/omo-codex/scripts/install-config-autonomous.test.mjs +2 -1
  732. package/packages/omo-codex/scripts/install-config-git-bash.test.mjs +0 -23
  733. package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +5 -5
  734. package/packages/omo-codex/scripts/install-config.test.mjs +15 -17
  735. package/packages/omo-codex/scripts/install-dist/install-local.mjs +9652 -1394
  736. package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +3 -4
  737. package/packages/omo-codex/scripts/install-git-bash-mcp-env.test.mjs +1 -25
  738. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
  739. package/packages/omo-codex/scripts/install-mcp-runtime.test.mjs +0 -36
  740. package/packages/omo-codex/scripts/install-packaged-local.test.mjs +1 -6
  741. package/packages/{omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md → prompts-core/prompts/ultrawork/codex.md} +46 -31
  742. package/packages/shared-skills/package.json +7 -1
  743. package/packages/shared-skills/skill-source-filter.d.ts +16 -0
  744. package/packages/shared-skills/skill-source-filter.mjs +44 -0
  745. package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
  746. package/packages/shared-skills/skills/ast-grep/SKILL.md +1 -1
  747. package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
  748. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +1 -1
  749. package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
  750. package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
  751. package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
  752. package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
  753. package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
  754. package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
  755. package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  756. package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  757. package/packages/shared-skills/skills/debugging/SKILL.md +3 -1
  758. package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
  759. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
  760. package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
  761. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
  762. package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
  763. package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
  764. package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
  765. package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
  766. package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
  767. package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  768. package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
  769. package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
  770. package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +10 -0
  771. package/packages/shared-skills/skills/frontend/SKILL.md +15 -8
  772. package/packages/shared-skills/skills/frontend/references/design/README.md +10 -2
  773. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +2 -0
  774. package/packages/shared-skills/skills/frontend/references/design/ambience-skill.md +145 -0
  775. package/packages/shared-skills/skills/frontend/references/design/interaction-skill.md +2 -0
  776. package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
  777. package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
  778. package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
  779. package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  780. package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  781. package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  782. package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
  783. package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
  784. package/packages/shared-skills/skills/git-master/SKILL.md +1 -1
  785. package/packages/shared-skills/skills/init-deep/SKILL.md +14 -14
  786. package/packages/shared-skills/skills/lsp-setup/SKILL.md +1 -1
  787. package/packages/shared-skills/skills/programming/SKILL.md +1 -1
  788. package/packages/shared-skills/skills/refactor/SKILL.md +4 -4
  789. package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +1 -1
  790. package/packages/shared-skills/skills/review-work/SKILL.md +101 -419
  791. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
  792. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +26 -9
  793. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  794. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
  795. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +23 -18
  796. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  797. package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +20 -19
  798. package/packages/shared-skills/skills/ulw-plan/SKILL.md +7 -8
  799. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
  800. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
  801. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
  802. package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  803. package/packages/shared-skills/skills/ulw-research/SKILL.md +8 -3
  804. package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
  805. package/packages/shared-skills/skills/visual-qa/SKILL.md +4 -3
  806. package/postinstall.mjs +2 -0
  807. package/script/qa/web-terminal-visual-qa.mjs +2 -0
  808. package/script/qa/xterm-live-terminal.mjs +18 -2
  809. package/dist/config/schema/codegraph.d.ts +0 -12
  810. package/dist/config/schema/start-work.d.ts +0 -5
  811. package/dist/features/builtin-commands/templates/start-work.d.ts +0 -1
  812. package/dist/features/builtin-skills/index.d.ts +0 -1
  813. package/dist/features/builtin-skills/skill-file-loader.d.ts +0 -1
  814. package/dist/features/builtin-skills/skills/agent-browser-skill.d.ts +0 -1
  815. package/dist/features/builtin-skills/skills/agent-browser-template.d.ts +0 -1
  816. package/dist/features/builtin-skills/skills/debugging.d.ts +0 -1
  817. package/dist/features/builtin-skills/skills/dev-browser.d.ts +0 -1
  818. package/dist/features/builtin-skills/skills/frontend.d.ts +0 -1
  819. package/dist/features/builtin-skills/skills/git-master-sections/commit-atomic-planning.d.ts +0 -1
  820. package/dist/features/builtin-skills/skills/git-master-sections/commit-context-analysis.d.ts +0 -1
  821. package/dist/features/builtin-skills/skills/git-master-sections/commit-execution-verification.d.ts +0 -1
  822. package/dist/features/builtin-skills/skills/git-master-sections/commit-workflow.d.ts +0 -1
  823. package/dist/features/builtin-skills/skills/git-master-sections/history-search-workflow.d.ts +0 -1
  824. package/dist/features/builtin-skills/skills/git-master-sections/overview.d.ts +0 -1
  825. package/dist/features/builtin-skills/skills/git-master-sections/quick-reference.d.ts +0 -1
  826. package/dist/features/builtin-skills/skills/git-master-sections/rebase-workflow.d.ts +0 -1
  827. package/dist/features/builtin-skills/skills/git-master-skill-metadata.d.ts +0 -1
  828. package/dist/features/builtin-skills/skills/git-master.d.ts +0 -1
  829. package/dist/features/builtin-skills/skills/index.d.ts +0 -1
  830. package/dist/features/builtin-skills/skills/init-deep.d.ts +0 -1
  831. package/dist/features/builtin-skills/skills/playwright-cli.d.ts +0 -1
  832. package/dist/features/builtin-skills/skills/playwright-mcp-skill.d.ts +0 -1
  833. package/dist/features/builtin-skills/skills/playwright.d.ts +0 -1
  834. package/dist/features/builtin-skills/skills/remove-ai-slops.d.ts +0 -1
  835. package/dist/features/builtin-skills/skills/review-work.d.ts +0 -1
  836. package/dist/features/builtin-skills/skills/security-research.d.ts +0 -1
  837. package/dist/features/builtin-skills/skills/security-review.d.ts +0 -1
  838. package/dist/features/builtin-skills/skills/team-mode.d.ts +0 -1
  839. package/dist/features/builtin-skills/skills/visual-qa.d.ts +0 -1
  840. package/dist/features/builtin-skills/skills.d.ts +0 -1
  841. package/dist/features/builtin-skills/types.d.ts +0 -1
  842. package/dist/features/claude-code-plugin-loader/agent-loader.d.ts +0 -1
  843. package/dist/features/claude-code-plugin-loader/command-loader.d.ts +0 -1
  844. package/dist/features/claude-code-plugin-loader/discovery-core.d.ts +0 -1
  845. package/dist/features/claude-code-plugin-loader/discovery-paths.d.ts +0 -1
  846. package/dist/features/claude-code-plugin-loader/discovery.d.ts +0 -1
  847. package/dist/features/claude-code-plugin-loader/hook-loader.d.ts +0 -1
  848. package/dist/features/claude-code-plugin-loader/index.d.ts +0 -1
  849. package/dist/features/claude-code-plugin-loader/install-path-resolver.d.ts +0 -1
  850. package/dist/features/claude-code-plugin-loader/installed-plugin-database.d.ts +0 -1
  851. package/dist/features/claude-code-plugin-loader/loaded-plugin.d.ts +0 -1
  852. package/dist/features/claude-code-plugin-loader/loader.d.ts +0 -1
  853. package/dist/features/claude-code-plugin-loader/mcp-server-loader.d.ts +0 -1
  854. package/dist/features/claude-code-plugin-loader/plugin-key.d.ts +0 -1
  855. package/dist/features/claude-code-plugin-loader/plugin-manifest.d.ts +0 -1
  856. package/dist/features/claude-code-plugin-loader/plugin-path-resolver.d.ts +0 -1
  857. package/dist/features/claude-code-plugin-loader/plugin-settings.d.ts +0 -1
  858. package/dist/features/claude-code-plugin-loader/scope-filter.d.ts +0 -1
  859. package/dist/features/claude-code-plugin-loader/skill-loader.d.ts +0 -1
  860. package/dist/features/claude-code-plugin-loader/types.d.ts +0 -1
  861. package/dist/hooks/codegraph-bootstrap/command-runner.d.ts +0 -17
  862. package/dist/hooks/codegraph-bootstrap/hook.d.ts +0 -35
  863. package/dist/hooks/codegraph-bootstrap/index.d.ts +0 -1
  864. package/dist/hooks/codegraph-bootstrap/project-root.d.ts +0 -1
  865. package/dist/hooks/codegraph-bootstrap/status.d.ts +0 -11
  866. package/dist/hooks/ralph-loop/completion-promise-detector-test-input.d.ts +0 -11
  867. package/dist/hooks/ralph-loop/loop-session-recovery.d.ts +0 -7
  868. package/dist/hooks/start-work/start-work-hook.d.ts +0 -23
  869. package/dist/mcp/codegraph.d.ts +0 -16
  870. package/dist/plugin/chat-message/start-work-message.d.ts +0 -5
  871. package/dist/shared/prompt-async-gate/message-inspection-error.d.ts +0 -1
  872. package/dist/shared/prompt-async-gate/pending-tool-turn.d.ts +0 -1
  873. package/dist/shared/prompt-async-gate/prompt-message-state.d.ts +0 -1
  874. package/dist/shared/prompt-async-gate/queue.d.ts +0 -1
  875. package/dist/shared/prompt-async-gate/recent-dispatches.d.ts +0 -1
  876. package/dist/shared/prompt-async-gate/reservations.d.ts +0 -1
  877. package/dist/shared/prompt-async-gate/semantic-dedupe.d.ts +0 -1
  878. package/dist/shared/prompt-async-gate/session-idle-dispatch.d.ts +0 -1
  879. package/dist/shared/prompt-async-gate/timing.d.ts +0 -1
  880. package/dist/shared/prompt-async-gate/types.d.ts +0 -1
  881. package/dist/skills/data-scientist/references/common-scenarios.md +0 -176
  882. package/dist/skills/data-scientist/references/execution-templates.md +0 -197
  883. package/dist/skills/data-scientist/references/integration-patterns.md +0 -153
  884. package/dist/skills/data-scientist/references/performance-benchmarks.md +0 -37
  885. package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
  886. package/dist/tools/call-omo-agent/message-storage-directory.d.ts +0 -1
  887. package/dist/tools/delegate-task/anthropic-categories.d.ts +0 -2
  888. package/dist/tools/delegate-task/model-string-parser.d.ts +0 -1
  889. package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts +0 -1
  890. package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts +0 -1
  891. package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts +0 -1
  892. package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.d.ts +0 -1
  893. package/packages/lsp-tools-mcp/dist/missing-dependency-result.d.ts +0 -1
  894. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +0 -58
  895. package/packages/omo-codex/plugin/components/codegraph/NODE-RUNTIME-LICENSES.md +0 -2951
  896. package/packages/omo-codex/plugin/components/codegraph/NOTICE +0 -16
  897. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +0 -12149
  898. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +0 -9747
  899. package/packages/omo-codex/plugin/components/codegraph/package.json +0 -33
  900. package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +0 -29
  901. package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +0 -79
  902. package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +0 -33
  903. package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +0 -25
  904. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +0 -131
  905. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +0 -258
  906. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +0 -309
  907. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +0 -80
  908. package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +0 -34
  909. package/packages/omo-codex/plugin/components/codegraph/src/serve-invocation.ts +0 -29
  910. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +0 -263
  911. package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +0 -106
  912. package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +0 -145
  913. package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +0 -21
  914. package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +0 -139
  915. package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +0 -15
  916. package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +0 -32
  917. package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +0 -109
  918. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +0 -148
  919. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +0 -175
  920. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +0 -81
  921. package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +0 -34
  922. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +0 -112
  923. package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +0 -26
  924. package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +0 -160
  925. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +0 -50
  926. package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +0 -29
  927. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +0 -320
  928. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +0 -172
  929. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +0 -91
  930. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +0 -100
  931. package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +0 -76
  932. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +0 -133
  933. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +0 -245
  934. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +0 -69
  935. package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +0 -43
  936. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +0 -147
  937. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +0 -175
  938. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +0 -385
  939. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +0 -206
  940. package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +0 -58
  941. package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +0 -104
  942. package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +0 -65
  943. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-availability.test.ts +0 -106
  944. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +0 -116
  945. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +0 -258
  946. package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +0 -56
  947. package/packages/omo-codex/plugin/components/codegraph/tsconfig.build.json +0 -13
  948. package/packages/omo-codex/plugin/components/codegraph/tsconfig.json +0 -25
  949. package/packages/omo-codex/plugin/components/start-work-continuation/LICENSE +0 -21
  950. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
  951. package/packages/omo-codex/plugin/components/ultrawork/directive.md +0 -471
  952. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +0 -18
  953. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +0 -17
  954. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
  955. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
  956. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/editor.mjs +0 -125
  957. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/jsonc.mjs +0 -43
  958. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/scaffold.mjs +0 -29
  959. package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +0 -121
  960. package/packages/omo-codex/plugin/skills/data-scientist/references/common-scenarios.md +0 -176
  961. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-templates.md +0 -197
  962. package/packages/omo-codex/plugin/skills/data-scientist/references/integration-patterns.md +0 -153
  963. package/packages/omo-codex/plugin/skills/data-scientist/references/performance-benchmarks.md +0 -37
  964. package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
  965. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
  966. package/packages/omo-codex/plugin/test/component-codegraph-mcp-smoke.test.mjs +0 -76
  967. package/packages/omo-codex/plugin/test/migrate-omo-sot.test.mjs +0 -179
  968. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
  969. package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
  970. package/packages/shared-skills/skills/data-scientist/references/common-scenarios.md +0 -176
  971. package/packages/shared-skills/skills/data-scientist/references/execution-templates.md +0 -197
  972. package/packages/shared-skills/skills/data-scientist/references/integration-patterns.md +0 -153
  973. package/packages/shared-skills/skills/data-scientist/references/performance-benchmarks.md +0 -37
  974. /package/dist/hooks/{start-work → ulw-execute}/context-info-formatters.d.ts +0 -0
  975. /package/dist/hooks/{start-work → ulw-execute}/explicit-plan-context.d.ts +0 -0
  976. /package/dist/hooks/{start-work → ulw-execute}/notepad-scaffold.d.ts +0 -0
  977. /package/dist/hooks/{start-work → ulw-execute}/parse-user-request.d.ts +0 -0
  978. /package/dist/hooks/{start-work → ulw-execute}/plan-discovery-context.d.ts +0 -0
  979. /package/dist/hooks/{start-work → ulw-execute}/plan-selection.d.ts +0 -0
  980. /package/dist/hooks/{start-work → ulw-execute}/session-plan-affinity.d.ts +0 -0
  981. /package/dist/hooks/{start-work → ulw-execute}/work-initializer.d.ts +0 -0
  982. /package/dist/hooks/{start-work → ulw-execute}/worktree-block.d.ts +0 -0
  983. /package/dist/hooks/{start-work → ulw-execute}/worktree-detector.d.ts +0 -0
  984. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/.gitattributes +0 -0
  985. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/CHANGELOG.md +0 -0
  986. /package/packages/omo-codex/plugin/components/{codegraph → ulw-execute-continuation}/LICENSE +0 -0
  987. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/plan-checklist.ts +0 -0
  988. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
  989. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
  990. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
  991. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
  992. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
  993. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
  994. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
  995. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
  996. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
  997. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
@@ -15,6 +15,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
15
15
  // ../lsp-core/src/lsp/connection.ts
16
16
  import { pathToFileURL } from "node:url";
17
17
 
18
+ // ../lsp-core/src/lsp/timer-provider.ts
19
+ var realTimerProvider = {
20
+ now: () => Date.now(),
21
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
22
+ clearTimeout: (handle) => clearTimeout(handle)
23
+ };
24
+
18
25
  // ../lsp-core/src/lsp/constants.ts
19
26
  var DEFAULT_MAX_REFERENCES = 200;
20
27
  var DEFAULT_MAX_SYMBOLS = 200;
@@ -23,28 +30,24 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
23
30
  var REQUEST_TIMEOUT_MS = 15000;
24
31
  var INIT_TIMEOUT_MS = 60000;
25
32
  var IDLE_TIMEOUT_MS = 5 * 60000;
33
+ var MAX_RESIDENT_CLIENTS = 6;
26
34
  var REAPER_INTERVAL_MS = 60000;
27
35
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
28
36
  var STOP_SIGKILL_GRACE_MS = 1000;
37
+ var CLIENT_RESPAWN_RETRY_LIMIT = 2;
38
+ var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
29
39
 
30
40
  // ../lsp-core/src/lsp/errors.ts
31
41
  class LspConnectionClosedError extends Error {
32
- serverId;
33
- root;
34
- name = "LspConnectionClosedError";
35
42
  constructor(serverId, root, message) {
36
43
  super(message ?? `LSP connection closed for ${serverId} at ${root}`);
37
44
  this.serverId = serverId;
38
45
  this.root = root;
46
+ this.name = "LspConnectionClosedError";
39
47
  }
40
48
  }
41
49
 
42
50
  class LspProcessExitedError extends Error {
43
- serverId;
44
- root;
45
- exitCode;
46
- stderrTail;
47
- name = "LspProcessExitedError";
48
51
  constructor(serverId, root, exitCode, stderrTail) {
49
52
  const stderrSuffix = stderrTail ? `
50
53
  stderr tail: ${stderrTail}` : "";
@@ -53,46 +56,59 @@ stderr tail: ${stderrTail}` : "";
53
56
  this.root = root;
54
57
  this.exitCode = exitCode;
55
58
  this.stderrTail = stderrTail;
59
+ this.name = "LspProcessExitedError";
56
60
  }
57
61
  }
58
62
 
59
63
  class LspRequestTimeoutError extends Error {
60
- method;
61
- stderrTail;
62
- name = "LspRequestTimeoutError";
63
64
  constructor(method, stderrTail) {
64
65
  const stderrSuffix = stderrTail ? `
65
66
  recent stderr: ${stderrTail}` : "";
66
67
  super(`LSP request timeout (method: ${method})${stderrSuffix}`);
67
68
  this.method = method;
68
69
  this.stderrTail = stderrTail;
70
+ this.name = "LspRequestTimeoutError";
69
71
  }
70
72
  }
71
73
 
72
74
  class LspInvalidPathError extends Error {
73
- name = "LspInvalidPathError";
75
+ constructor() {
76
+ super(...arguments);
77
+ this.name = "LspInvalidPathError";
78
+ }
74
79
  }
75
80
 
76
81
  class LspServerLookupError extends Error {
77
- lookup;
78
- name = "LspServerLookupError";
79
82
  constructor(message, lookup) {
80
83
  super(message);
81
84
  this.lookup = lookup;
85
+ this.name = "LspServerLookupError";
82
86
  }
83
87
  }
84
88
 
85
89
  class LspServerInitializingError extends Error {
86
- originalError;
87
- name = "LspServerInitializingError";
88
90
  constructor(originalError) {
89
91
  super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
90
92
  this.originalError = originalError;
93
+ this.name = "LspServerInitializingError";
91
94
  }
92
95
  }
93
96
 
94
97
  class LspProcessSpawnError extends Error {
95
- name = "LspProcessSpawnError";
98
+ constructor() {
99
+ super(...arguments);
100
+ this.name = "LspProcessSpawnError";
101
+ }
102
+ }
103
+
104
+ class LspClientRespawnBudgetExceededError extends Error {
105
+ constructor(serverId, root, retryLimit) {
106
+ super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
107
+ this.serverId = serverId;
108
+ this.root = root;
109
+ this.retryLimit = retryLimit;
110
+ this.name = "LspClientRespawnBudgetExceededError";
111
+ }
96
112
  }
97
113
  function isLspDeadConnectionError(err) {
98
114
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
@@ -108,20 +124,31 @@ var METHOD_NOT_FOUND = -32601;
108
124
  var INTERNAL_ERROR = -32603;
109
125
 
110
126
  class JsonRpcConnection {
111
- reader;
112
- writer;
113
- pendingRequests = new Map;
114
- notificationHandlers = new Map;
115
- requestHandlers = new Map;
116
- closeHandlers = [];
117
- errorHandlers = [];
118
- inputBuffer = Buffer.alloc(0);
119
- nextRequestId = 1;
120
- listening = false;
121
- disposed = false;
122
127
  constructor(reader, writer) {
123
128
  this.reader = reader;
124
129
  this.writer = writer;
130
+ this.pendingRequests = new Map;
131
+ this.notificationHandlers = new Map;
132
+ this.requestHandlers = new Map;
133
+ this.closeHandlers = [];
134
+ this.errorHandlers = [];
135
+ this.inputBuffer = Buffer.alloc(0);
136
+ this.nextRequestId = 1;
137
+ this.listening = false;
138
+ this.disposed = false;
139
+ this.handleData = (chunk) => {
140
+ const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
141
+ this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
142
+ this.drainInputBuffer();
143
+ };
144
+ this.handleClose = () => {
145
+ for (const handler of this.closeHandlers) {
146
+ handler();
147
+ }
148
+ };
149
+ this.handleStreamError = (error) => {
150
+ this.emitError(error);
151
+ };
125
152
  }
126
153
  listen() {
127
154
  if (this.listening)
@@ -156,6 +183,7 @@ class JsonRpcConnection {
156
183
  let cancelAfterWrite = false;
157
184
  let settled = false;
158
185
  const writeCancel = () => this.writeMessage({ jsonrpc: "2.0", method: "$/cancelRequest", params: { id } });
186
+ let rejectAfterCancelWrite;
159
187
  const responsePromise = new Promise((resolve, reject) => {
160
188
  const cleanup = () => {
161
189
  options.signal?.removeEventListener("abort", onAbort);
@@ -167,15 +195,19 @@ class JsonRpcConnection {
167
195
  this.pendingRequests.delete(key);
168
196
  cleanup();
169
197
  const rejectCancelled = () => reject(abortError(options.signal));
198
+ rejectAfterCancelWrite = async () => {
199
+ try {
200
+ await writeCancel();
201
+ } catch (error) {
202
+ this.emitError(toError(error));
203
+ }
204
+ rejectCancelled();
205
+ };
170
206
  if (!requestWritten) {
171
207
  cancelAfterWrite = true;
172
- rejectCancelled();
173
208
  return;
174
209
  }
175
- writeCancel().then(rejectCancelled, (error) => {
176
- this.emitError(toError(error));
177
- rejectCancelled();
178
- });
210
+ rejectAfterCancelWrite();
179
211
  };
180
212
  const onAbort = () => settleCancel();
181
213
  this.pendingRequests.set(key, {
@@ -203,7 +235,7 @@ class JsonRpcConnection {
203
235
  await this.writeMessage(message);
204
236
  requestWritten = true;
205
237
  if (cancelAfterWrite)
206
- await writeCancel();
238
+ await rejectAfterCancelWrite?.();
207
239
  } catch (error) {
208
240
  if (settled)
209
241
  return responsePromise;
@@ -242,19 +274,6 @@ class JsonRpcConnection {
242
274
  this.notificationHandlers.clear();
243
275
  this.requestHandlers.clear();
244
276
  }
245
- handleData = (chunk) => {
246
- const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
247
- this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
248
- this.drainInputBuffer();
249
- };
250
- handleClose = () => {
251
- for (const handler of this.closeHandlers) {
252
- handler();
253
- }
254
- };
255
- handleStreamError = (error) => {
256
- this.emitError(error);
257
- };
258
277
  drainInputBuffer() {
259
278
  while (true) {
260
279
  const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR);
@@ -602,33 +621,29 @@ function isPosition(value) {
602
621
 
603
622
  // ../lsp-core/src/lsp/transport.ts
604
623
  class LspClientNotStartedError extends Error {
605
- serverId;
606
- root;
607
- name = "LspClientNotStartedError";
608
624
  constructor(serverId, root) {
609
625
  super("LSP client not started");
610
626
  this.serverId = serverId;
611
627
  this.root = root;
628
+ this.name = "LspClientNotStartedError";
612
629
  }
613
630
  }
614
631
 
615
632
  class LspClientTransport {
616
- root;
617
- server;
618
- proc = null;
619
- connection = null;
620
- stderrBuffer = [];
621
- processExited = false;
622
- diagnosticsStore = new Map;
623
- requestTimeoutMs;
624
- initializeTimeoutMs;
625
- workspaceApplyEditHandler = null;
626
- diagnosticPullSupported = false;
627
633
  constructor(root, server, timeouts = {}) {
628
634
  this.root = root;
629
635
  this.server = server;
636
+ this.proc = null;
637
+ this.connection = null;
638
+ this.stderrBuffer = [];
639
+ this.processExited = false;
640
+ this.diagnosticsStore = new Map;
641
+ this.workspaceApplyEditHandler = null;
642
+ this.diagnosticPullSupported = false;
643
+ this.documentFormattingSupported = false;
630
644
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
631
645
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
646
+ this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
632
647
  }
633
648
  pid() {
634
649
  return this.proc?.pid;
@@ -648,6 +663,12 @@ class LspClientTransport {
648
663
  isDiagnosticPullSupported() {
649
664
  return this.diagnosticPullSupported;
650
665
  }
666
+ setDocumentFormattingSupported(supported) {
667
+ this.documentFormattingSupported = supported;
668
+ }
669
+ isDocumentFormattingSupported() {
670
+ return this.documentFormattingSupported;
671
+ }
651
672
  handlePublishDiagnostics(params) {
652
673
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
653
674
  }
@@ -723,7 +744,7 @@ class LspClientTransport {
723
744
  const options = args[1];
724
745
  const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
725
746
  const timeoutController = new AbortController;
726
- const timeoutHandle = setTimeout(() => {
747
+ const timeoutHandle = this.timerProvider.setTimeout(() => {
727
748
  const stderrTail = this.stderrBuffer.slice(-5).join(`
728
749
  `);
729
750
  timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
@@ -742,7 +763,7 @@ class LspClientTransport {
742
763
  }
743
764
  throw error;
744
765
  } finally {
745
- clearTimeout(timeoutHandle);
766
+ this.timerProvider.clearTimeout(timeoutHandle);
746
767
  combinedSignal.dispose();
747
768
  }
748
769
  }
@@ -861,6 +882,14 @@ function supportsDiagnosticPull(capabilities) {
861
882
  return false;
862
883
  return Object.hasOwn(capabilities, "diagnosticProvider");
863
884
  }
885
+ function supportsDocumentFormatting(capabilities) {
886
+ if (capabilities === undefined)
887
+ return false;
888
+ const provider = capabilities.documentFormattingProvider;
889
+ if (provider === undefined || provider === null || provider === false)
890
+ return false;
891
+ return provider === true || typeof provider === "object";
892
+ }
864
893
 
865
894
  class LspClientConnection extends LspClientTransport {
866
895
  async initialize() {
@@ -877,6 +906,7 @@ class LspClientConnection extends LspClientTransport {
877
906
  references: {},
878
907
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
879
908
  publishDiagnostics: {},
909
+ formatting: { dynamicRegistration: false },
880
910
  rename: {
881
911
  prepareSupport: true,
882
912
  prepareSupportDefaultBehavior: 1
@@ -918,6 +948,7 @@ class LspClientConnection extends LspClientTransport {
918
948
  initializationOptions: this.server.initialization
919
949
  }, { timeoutMs: this.initializeTimeoutMs });
920
950
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
951
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
921
952
  await this.sendNotification("initialized", {});
922
953
  await this.sendNotification("workspace/didChangeConfiguration", {
923
954
  settings: { json: { validate: { enable: true } } }
@@ -1123,6 +1154,17 @@ function canonicalPath(filePath) {
1123
1154
  return absolute;
1124
1155
  }
1125
1156
  }
1157
+ function normalizeDocumentUri(uri) {
1158
+ let decoded = uri;
1159
+ try {
1160
+ decoded = decodeURIComponent(uri);
1161
+ } catch {
1162
+ decoded = uri;
1163
+ }
1164
+ if (process.platform !== "win32")
1165
+ return decoded;
1166
+ return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
1167
+ }
1126
1168
  function isSameOrDescendant(candidate, parent) {
1127
1169
  const suffix = relative(parent, candidate);
1128
1170
  return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
@@ -1133,17 +1175,18 @@ function movedPath(candidate, oldPath, newPath) {
1133
1175
  }
1134
1176
 
1135
1177
  class WorkspaceDocumentState {
1136
- sendNotification;
1137
- clearDiagnostics;
1138
- openDocuments = new Map;
1139
- openByUri = new Map;
1140
- openPromises = new Map;
1141
- now;
1142
- versionlessPublishQuiescenceMs;
1143
1178
  constructor(sendNotification, clearDiagnostics, options = {}) {
1144
1179
  this.sendNotification = sendNotification;
1145
1180
  this.clearDiagnostics = clearDiagnostics;
1146
- this.now = options.now ?? (() => Date.now());
1181
+ this.openDocuments = new Map;
1182
+ this.openByUri = new Map;
1183
+ this.openPromises = new Map;
1184
+ this.timerProvider = options.timerProvider ?? {
1185
+ now: options.now ?? (() => Date.now()),
1186
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
1187
+ clearTimeout: (handle) => clearTimeout(handle)
1188
+ };
1189
+ this.now = () => this.timerProvider.now();
1147
1190
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1148
1191
  }
1149
1192
  async openFile(filePath) {
@@ -1165,7 +1208,7 @@ class WorkspaceDocumentState {
1165
1208
  return this.openDocuments.get(canonicalPath(filePath))?.version;
1166
1209
  }
1167
1210
  getStoredDiagnostics(uri) {
1168
- const state = this.openByUri.get(uri);
1211
+ const state = this.openByUri.get(normalizeDocumentUri(uri));
1169
1212
  if (!state)
1170
1213
  return [];
1171
1214
  return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
@@ -1187,13 +1230,13 @@ class WorkspaceDocumentState {
1187
1230
  return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
1188
1231
  }
1189
1232
  getPullCache(snapshot) {
1190
- const state = this.openByUri.get(snapshot.uri);
1233
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1191
1234
  if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
1192
1235
  return null;
1193
1236
  return state.pullCache;
1194
1237
  }
1195
1238
  recordPullDiagnostics(snapshot, report) {
1196
- const state = this.openByUri.get(snapshot.uri);
1239
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1197
1240
  if (!state)
1198
1241
  return;
1199
1242
  state.pullCache = {
@@ -1203,7 +1246,7 @@ class WorkspaceDocumentState {
1203
1246
  };
1204
1247
  }
1205
1248
  recordPublishedDiagnostics(params) {
1206
- const state = this.openByUri.get(params.uri);
1249
+ const state = this.openByUri.get(normalizeDocumentUri(params.uri));
1207
1250
  if (!state)
1208
1251
  return;
1209
1252
  state.publishGeneration += 1;
@@ -1217,7 +1260,7 @@ class WorkspaceDocumentState {
1217
1260
  this.notifyWaiters(state);
1218
1261
  }
1219
1262
  resolvePushDiagnostics(snapshot) {
1220
- const state = this.openByUri.get(snapshot.uri);
1263
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1221
1264
  if (!state?.lastPublish)
1222
1265
  return { status: "missing" };
1223
1266
  const publish = state.lastPublish;
@@ -1231,7 +1274,7 @@ class WorkspaceDocumentState {
1231
1274
  return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
1232
1275
  }
1233
1276
  waitForDiagnosticsActivity(snapshot, timeoutMs) {
1234
- const state = this.openByUri.get(snapshot.uri);
1277
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1235
1278
  if (!state || timeoutMs <= 0)
1236
1279
  return Promise.resolve();
1237
1280
  return new Promise((resolveActivity) => {
@@ -1240,11 +1283,11 @@ class WorkspaceDocumentState {
1240
1283
  if (settled)
1241
1284
  return;
1242
1285
  settled = true;
1243
- clearTimeout(timer);
1286
+ this.timerProvider.clearTimeout(timer);
1244
1287
  state.waiters.delete(finish);
1245
1288
  resolveActivity();
1246
1289
  };
1247
- const timer = setTimeout(finish, timeoutMs);
1290
+ const timer = this.timerProvider.setTimeout(finish, timeoutMs);
1248
1291
  if (typeof timer.unref === "function")
1249
1292
  timer.unref();
1250
1293
  state.waiters.add(finish);
@@ -1352,7 +1395,7 @@ class WorkspaceDocumentState {
1352
1395
  waiters: new Set
1353
1396
  };
1354
1397
  this.openDocuments.set(path, state);
1355
- this.openByUri.set(state.uri, state);
1398
+ this.openByUri.set(normalizeDocumentUri(state.uri), state);
1356
1399
  this.notifyWaiters(state);
1357
1400
  await this.sendNotification("textDocument/didOpen", {
1358
1401
  textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
@@ -1377,7 +1420,7 @@ class WorkspaceDocumentState {
1377
1420
  }
1378
1421
  async closeDocument(state) {
1379
1422
  this.openDocuments.delete(state.path);
1380
- this.openByUri.delete(state.uri);
1423
+ this.openByUri.delete(normalizeDocumentUri(state.uri));
1381
1424
  this.clearDiagnostics(state.uri);
1382
1425
  this.notifyWaiters(state);
1383
1426
  await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
@@ -1406,13 +1449,11 @@ import { dirname, isAbsolute, relative as relative2, resolve as resolve2 } from
1406
1449
  import { fileURLToPath } from "node:url";
1407
1450
 
1408
1451
  class WorkspaceEditPathError extends Error {
1409
- path;
1410
- detail;
1411
- name = "WorkspaceEditPathError";
1412
1452
  constructor(path, detail) {
1413
1453
  super(`${detail}: ${path}`);
1414
1454
  this.path = path;
1415
1455
  this.detail = detail;
1456
+ this.name = "WorkspaceEditPathError";
1416
1457
  }
1417
1458
  }
1418
1459
  function isPathInsideWorkspace(filePath, workspaceRoot) {
@@ -1704,13 +1745,11 @@ function canonicalFingerprint(operations) {
1704
1745
 
1705
1746
  // ../lsp-core/src/lsp/workspace-edit-types.ts
1706
1747
  class WorkspaceEditValidationError extends Error {
1707
- changeIndex;
1708
- detail;
1709
- name = "WorkspaceEditValidationError";
1710
1748
  constructor(changeIndex, detail) {
1711
1749
  super(`change ${changeIndex}: ${detail}`);
1712
1750
  this.changeIndex = changeIndex;
1713
1751
  this.detail = detail;
1752
+ this.name = "WorkspaceEditValidationError";
1714
1753
  }
1715
1754
  }
1716
1755
 
@@ -1796,14 +1835,14 @@ function parseSinglePathResource(input, kind) {
1796
1835
  return;
1797
1836
  }
1798
1837
  if (kind === "create") {
1799
- const options2 = parseOptions(change["options"], ["overwrite", "ignoreIfExists"], changeIndex);
1838
+ const options = parseOptions(change["options"], ["overwrite", "ignoreIfExists"], changeIndex);
1800
1839
  target.operations.push({
1801
1840
  kind,
1802
1841
  changeIndex,
1803
1842
  path: resolvedPath.path,
1804
1843
  reportedPath: resolvedPath.requestedPath,
1805
- overwrite: options2["overwrite"] ?? false,
1806
- ignoreIfExists: options2["ignoreIfExists"] ?? false,
1844
+ overwrite: options["overwrite"] ?? false,
1845
+ ignoreIfExists: options["ignoreIfExists"] ?? false,
1807
1846
  followedSymbolicLink: resolvedPath.followedSymbolicLink
1808
1847
  });
1809
1848
  return;
@@ -2208,10 +2247,9 @@ function simulateDelete(operation, virtual) {
2208
2247
  import { existsSync as existsSync4, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
2209
2248
  import { dirname as dirname3, resolve as resolve4 } from "node:path";
2210
2249
  class WorkspaceSnapshotBuilder {
2211
- workspaceRoot;
2212
- snapshots = new Map;
2213
2250
  constructor(workspaceRoot) {
2214
2251
  this.workspaceRoot = workspaceRoot;
2252
+ this.snapshots = new Map;
2215
2253
  }
2216
2254
  build(operations) {
2217
2255
  this.add(this.workspaceRoot, false);
@@ -2255,8 +2293,10 @@ function snapshotOperations(operations, workspaceRoot) {
2255
2293
 
2256
2294
  // ../lsp-core/src/lsp/workspace-edit-plan.ts
2257
2295
  class PlanPathIndex {
2258
- firstChangeByPath = new Map;
2259
- reportedPathByCanonical = new Map;
2296
+ constructor() {
2297
+ this.firstChangeByPath = new Map;
2298
+ this.reportedPathByCanonical = new Map;
2299
+ }
2260
2300
  build(operations) {
2261
2301
  for (const operation of operations) {
2262
2302
  switch (operation.kind) {
@@ -2272,11 +2312,11 @@ class PlanPathIndex {
2272
2312
  }
2273
2313
  }
2274
2314
  }
2275
- add(path, reportedPath2, changeIndex) {
2315
+ add(path, reportedPath, changeIndex) {
2276
2316
  if (!this.firstChangeByPath.has(path))
2277
2317
  this.firstChangeByPath.set(path, changeIndex);
2278
2318
  if (!this.reportedPathByCanonical.has(path))
2279
- this.reportedPathByCanonical.set(path, reportedPath2);
2319
+ this.reportedPathByCanonical.set(path, reportedPath);
2280
2320
  }
2281
2321
  }
2282
2322
  function fingerprintWorkspaceEdit(edit, workspaceRoot) {
@@ -2345,14 +2385,11 @@ function isRecord3(value) {
2345
2385
  }
2346
2386
 
2347
2387
  class WorkspaceMutationController {
2348
- workspaceRoot;
2349
- documents;
2350
- activeLease = null;
2351
- nextLeaseId = 1;
2352
- io;
2353
2388
  constructor(workspaceRoot, documents) {
2354
2389
  this.workspaceRoot = workspaceRoot;
2355
2390
  this.documents = documents;
2391
+ this.activeLease = null;
2392
+ this.nextLeaseId = 1;
2356
2393
  }
2357
2394
  setIo(io) {
2358
2395
  this.io = io;
@@ -2391,8 +2428,8 @@ class WorkspaceMutationController {
2391
2428
  };
2392
2429
  }
2393
2430
  lease.phase = "applying";
2394
- lease.applyCompletion = new Promise((resolve5) => {
2395
- lease.resolveApply = resolve5;
2431
+ lease.applyCompletion = new Promise((resolve) => {
2432
+ lease.resolveApply = resolve;
2396
2433
  });
2397
2434
  const edit = isRecord3(params) ? params["edit"] : undefined;
2398
2435
  const record = edit === undefined ? { fingerprint: null, result: failure("workspace/applyEdit params.edit is required", 0) } : await this.applyEdit(edit, lease);
@@ -2465,14 +2502,12 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
2465
2502
  var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
2466
2503
 
2467
2504
  class LspClient extends LspClientConnection {
2468
- diagnosticPullErrors = [];
2469
- documents;
2470
- workspaceMutations;
2471
- diagnosticsFreshnessTimeoutMs;
2472
2505
  constructor(root, server, options = {}) {
2473
2506
  super(root, server, options);
2507
+ this.diagnosticPullErrors = [];
2474
2508
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2475
2509
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2510
+ timerProvider: this.timerProvider,
2476
2511
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
2477
2512
  });
2478
2513
  this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
@@ -2525,6 +2560,18 @@ class LspClient extends LspClientConnection {
2525
2560
  textDocument: { uri: pathToFileURL3(absPath).href }
2526
2561
  }, options);
2527
2562
  }
2563
+ async formatDocument(filePath, options, signal) {
2564
+ if (!this.isDocumentFormattingSupported())
2565
+ return null;
2566
+ const absPath = this.resolveWorkspacePath(filePath);
2567
+ await this.openFile(absPath);
2568
+ const requestOptions = signal === undefined ? {} : { signal };
2569
+ const edits = await this.sendRequest("textDocument/formatting", {
2570
+ textDocument: { uri: pathToFileURL3(absPath).href },
2571
+ options
2572
+ }, requestOptions);
2573
+ return edits ?? [];
2574
+ }
2528
2575
  async workspaceSymbols(query, signal) {
2529
2576
  const options = signal === undefined ? {} : { signal };
2530
2577
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -2564,7 +2611,7 @@ class LspClient extends LspClientConnection {
2564
2611
  const absPath = this.resolveWorkspacePath(filePath);
2565
2612
  const uri = pathToFileURL3(absPath).href;
2566
2613
  await this.openFile(absPath);
2567
- const deadlineAt = Date.now() + this.diagnosticsFreshnessTimeoutMs;
2614
+ const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
2568
2615
  for (;; ) {
2569
2616
  signal?.throwIfAborted();
2570
2617
  const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
@@ -2577,13 +2624,13 @@ class LspClient extends LspClientConnection {
2577
2624
  if (!pushFallbackOnly) {
2578
2625
  const cached = this.documents.getPullCache(snapshot);
2579
2626
  try {
2580
- const remainingMs2 = deadlineAt - Date.now();
2581
- if (remainingMs2 <= 0)
2627
+ const remainingMs = deadlineAt - this.timerProvider.now();
2628
+ if (remainingMs <= 0)
2582
2629
  return this.freshnessTimeout(absPath);
2583
2630
  const result = await this.sendRequest("textDocument/diagnostic", {
2584
2631
  textDocument: { uri },
2585
2632
  ...cached?.resultId === undefined ? {} : { previousResultId: cached.resultId }
2586
- }, { timeoutMs: remainingMs2, ...signal === undefined ? {} : { signal } });
2633
+ }, { timeoutMs: remainingMs, ...signal === undefined ? {} : { signal } });
2587
2634
  if (!this.documents.isCurrentSnapshot(snapshot))
2588
2635
  continue;
2589
2636
  const report = this.parseDiagnosticPullReport(result);
@@ -2612,7 +2659,7 @@ class LspClient extends LspClientConnection {
2612
2659
  }
2613
2660
  if (!pushFallbackOnly)
2614
2661
  continue;
2615
- const remainingMs = deadlineAt - Date.now();
2662
+ const remainingMs = deadlineAt - this.timerProvider.now();
2616
2663
  if (remainingMs <= 0) {
2617
2664
  if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
2618
2665
  const cached = this.documents.getPullCache(snapshot);
@@ -2664,7 +2711,7 @@ function waitForDiagnosticsActivity(wait, signal) {
2664
2711
  return wait;
2665
2712
  if (signal.aborted)
2666
2713
  return Promise.reject(abortError2(signal));
2667
- return new Promise((resolve6, reject) => {
2714
+ return new Promise((resolve, reject) => {
2668
2715
  const onAbort = () => {
2669
2716
  signal.removeEventListener("abort", onAbort);
2670
2717
  reject(abortError2(signal));
@@ -2672,7 +2719,7 @@ function waitForDiagnosticsActivity(wait, signal) {
2672
2719
  signal.addEventListener("abort", onAbort, { once: true });
2673
2720
  wait.then(() => {
2674
2721
  signal.removeEventListener("abort", onAbort);
2675
- resolve6();
2722
+ resolve();
2676
2723
  }, (error) => {
2677
2724
  signal.removeEventListener("abort", onAbort);
2678
2725
  reject(error);
@@ -2740,7 +2787,7 @@ async function stopClientBestEffort(client) {
2740
2787
  function awaitWithSignal(promise, signal) {
2741
2788
  if (!signal)
2742
2789
  return promise;
2743
- return new Promise((resolve6, reject) => {
2790
+ return new Promise((resolve, reject) => {
2744
2791
  let settled = false;
2745
2792
  const onAbort = () => {
2746
2793
  if (settled)
@@ -2758,7 +2805,7 @@ function awaitWithSignal(promise, signal) {
2758
2805
  return;
2759
2806
  settled = true;
2760
2807
  signal.removeEventListener("abort", onAbort);
2761
- resolve6(value);
2808
+ resolve(value);
2762
2809
  }, (err) => {
2763
2810
  if (settled)
2764
2811
  return;
@@ -2770,18 +2817,16 @@ function awaitWithSignal(promise, signal) {
2770
2817
  }
2771
2818
 
2772
2819
  class LspManager {
2773
- clients = new Map;
2774
- reaperHandle = null;
2775
- signalDisposer = null;
2776
- disposed = false;
2777
- idleTimeoutMs;
2778
- initTimeoutMs;
2779
- reaperIntervalMs;
2780
- clientFactory;
2781
- now;
2782
2820
  constructor(options = {}) {
2821
+ this.clients = new Map;
2822
+ this.pendingStops = new Map;
2823
+ this.respawnBudgets = new Map;
2824
+ this.reaperHandle = null;
2825
+ this.signalDisposer = null;
2826
+ this.disposed = false;
2783
2827
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
2784
2828
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
2829
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
2785
2830
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
2786
2831
  this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
2787
2832
  this.now = options.now ?? (() => Date.now());
@@ -2801,24 +2846,79 @@ class LspManager {
2801
2846
  getKey(root, serverId) {
2802
2847
  return `${root}::${serverId}`;
2803
2848
  }
2849
+ tombstoneStop(key, client) {
2850
+ const stop = stopClientBestEffort(client);
2851
+ this.pendingStops.set(key, stop);
2852
+ stop.finally(() => {
2853
+ if (this.pendingStops.get(key) === stop) {
2854
+ this.pendingStops.delete(key);
2855
+ }
2856
+ });
2857
+ return stop;
2858
+ }
2859
+ recordDeadGeneration(key) {
2860
+ let budget = this.respawnBudgets.get(key);
2861
+ if (budget === undefined) {
2862
+ budget = { deadGenerations: 0, exhaustedAt: null };
2863
+ this.respawnBudgets.set(key, budget);
2864
+ }
2865
+ budget.deadGenerations += 1;
2866
+ }
2867
+ markHealthyGeneration(key) {
2868
+ this.respawnBudgets.delete(key);
2869
+ }
2870
+ ensureRespawnAllowed(key, root, serverId) {
2871
+ const budget = this.respawnBudgets.get(key);
2872
+ if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
2873
+ return;
2874
+ if (budget.exhaustedAt === null) {
2875
+ budget.exhaustedAt = this.now();
2876
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
2877
+ }
2878
+ if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
2879
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
2880
+ }
2881
+ budget.deadGenerations = 0;
2882
+ budget.exhaustedAt = null;
2883
+ }
2804
2884
  reapStale() {
2805
2885
  const t = this.now();
2806
2886
  for (const [key, managed] of this.clients) {
2807
2887
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
2808
- stopClientBestEffort(managed.client);
2809
2888
  this.clients.delete(key);
2889
+ this.tombstoneStop(key, managed.client);
2810
2890
  continue;
2811
2891
  }
2812
2892
  if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
2813
- stopClientBestEffort(managed.client);
2814
2893
  this.clients.delete(key);
2894
+ this.tombstoneStop(key, managed.client);
2895
+ }
2896
+ }
2897
+ }
2898
+ evictForAdmission() {
2899
+ while (this.clients.size >= this.maxResidentClients) {
2900
+ const victim = this.leastRecentlyUsedIdleClient();
2901
+ if (!victim)
2902
+ return;
2903
+ this.clients.delete(victim.key);
2904
+ this.tombstoneStop(victim.key, victim.managed.client);
2905
+ }
2906
+ }
2907
+ leastRecentlyUsedIdleClient() {
2908
+ let candidate = null;
2909
+ for (const [key, managed] of this.clients) {
2910
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
2911
+ continue;
2912
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
2913
+ candidate = { key, managed };
2815
2914
  }
2816
2915
  }
2916
+ return candidate;
2817
2917
  }
2818
2918
  async tryDeleteIfOrphaned(key, managed) {
2819
2919
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
2820
2920
  this.clients.delete(key);
2821
- await stopClientBestEffort(managed.client);
2921
+ await this.tombstoneStop(key, managed.client);
2822
2922
  }
2823
2923
  }
2824
2924
  async getClient(root, server, signal) {
@@ -2827,12 +2927,22 @@ class LspManager {
2827
2927
  }
2828
2928
  signal?.throwIfAborted();
2829
2929
  const key = this.getKey(root, server.id);
2930
+ for (;; ) {
2931
+ const pendingStop = this.pendingStops.get(key);
2932
+ if (pendingStop === undefined)
2933
+ break;
2934
+ await awaitWithSignal(pendingStop, signal);
2935
+ signal?.throwIfAborted();
2936
+ }
2937
+ if (this.disposed) {
2938
+ throw new Error("LspManager has been disposed");
2939
+ }
2830
2940
  let managed = this.clients.get(key);
2831
2941
  if (managed) {
2832
2942
  const t = this.now();
2833
2943
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
2834
- await stopClientBestEffort(managed.client);
2835
2944
  this.clients.delete(key);
2945
+ await this.tombstoneStop(key, managed.client);
2836
2946
  managed = undefined;
2837
2947
  }
2838
2948
  }
@@ -2853,14 +2963,20 @@ class LspManager {
2853
2963
  signal.throwIfAborted();
2854
2964
  }
2855
2965
  if (!managed.client.isAlive()) {
2856
- await stopClientBestEffort(managed.client);
2857
- this.clients.delete(key);
2966
+ this.recordDeadGeneration(key);
2967
+ if (this.clients.get(key) === managed) {
2968
+ this.clients.delete(key);
2969
+ }
2970
+ await this.tombstoneStop(key, managed.client);
2858
2971
  return this.getClient(root, server, signal);
2859
2972
  }
2973
+ this.markHealthyGeneration(key);
2860
2974
  managed.refCount++;
2861
2975
  managed.lastUsedAt = this.now();
2862
2976
  return managed.client;
2863
2977
  }
2978
+ this.evictForAdmission();
2979
+ this.ensureRespawnAllowed(key, root, server.id);
2864
2980
  const client = this.clientFactory(root, server);
2865
2981
  const initStartedAt = this.now();
2866
2982
  const initPromise = (async () => {
@@ -2884,7 +3000,7 @@ class LspManager {
2884
3000
  if (this.clients.get(key) === newManaged) {
2885
3001
  this.clients.delete(key);
2886
3002
  }
2887
- await stopClientBestEffort(client);
3003
+ await this.tombstoneStop(key, client);
2888
3004
  throw err;
2889
3005
  }
2890
3006
  newManaged.pendingWaiters--;
@@ -2895,6 +3011,15 @@ class LspManager {
2895
3011
  await this.tryDeleteIfOrphaned(key, newManaged);
2896
3012
  signal.throwIfAborted();
2897
3013
  }
3014
+ if (!client.isAlive()) {
3015
+ this.recordDeadGeneration(key);
3016
+ if (this.clients.get(key) === newManaged) {
3017
+ this.clients.delete(key);
3018
+ }
3019
+ await this.tombstoneStop(key, client);
3020
+ return this.getClient(root, server, signal);
3021
+ }
3022
+ this.markHealthyGeneration(key);
2898
3023
  newManaged.refCount++;
2899
3024
  newManaged.lastUsedAt = this.now();
2900
3025
  return client;
@@ -2915,14 +3040,20 @@ class LspManager {
2915
3040
  if (client && managed.client !== client)
2916
3041
  return;
2917
3042
  this.clients.delete(key);
2918
- stopClientBestEffort(managed.client);
3043
+ this.tombstoneStop(key, managed.client);
2919
3044
  }
2920
3045
  warmupClient(root, server) {
2921
3046
  if (this.disposed)
2922
3047
  return;
2923
3048
  const key = this.getKey(root, server.id);
2924
- if (this.clients.has(key))
3049
+ if (this.clients.has(key) || this.pendingStops.has(key))
2925
3050
  return;
3051
+ this.evictForAdmission();
3052
+ try {
3053
+ this.ensureRespawnAllowed(key, root, server.id);
3054
+ } catch {
3055
+ return;
3056
+ }
2926
3057
  const client = this.clientFactory(root, server);
2927
3058
  const initStartedAt = this.now();
2928
3059
  const initPromise = (async () => {
@@ -2948,7 +3079,7 @@ class LspManager {
2948
3079
  if (this.clients.get(key) === managed) {
2949
3080
  this.clients.delete(key);
2950
3081
  }
2951
- stopClientBestEffort(client);
3082
+ this.tombstoneStop(key, client);
2952
3083
  });
2953
3084
  }
2954
3085
  isServerInitializing(root, serverId) {
@@ -2992,8 +3123,11 @@ class LspManager {
2992
3123
  for (const managed of this.clients.values()) {
2993
3124
  stopPromises.push(stopClientBestEffort(managed.client));
2994
3125
  }
3126
+ const tombstonedStops = [...this.pendingStops.values()];
2995
3127
  this.clients.clear();
2996
- await Promise.allSettled(stopPromises);
3128
+ this.respawnBudgets.clear();
3129
+ await Promise.allSettled([...stopPromises, ...tombstonedStops]);
3130
+ this.pendingStops.clear();
2997
3131
  }
2998
3132
  }
2999
3133
  var _defaultInstance = null;
@@ -3013,7 +3147,7 @@ async function disposeDefaultLspManager() {
3013
3147
  // src/daemon-client.ts
3014
3148
  import { connect } from "node:net";
3015
3149
  import { homedir as homedir3 } from "node:os";
3016
- import { join as join7 } from "node:path";
3150
+ import { join as join8 } from "node:path";
3017
3151
 
3018
3152
  // ../lsp-core/src/request-context.ts
3019
3153
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -3022,18 +3156,17 @@ import { homedir } from "node:os";
3022
3156
  import { basename as basename2, delimiter as delimiter2, dirname as dirname4, isAbsolute as isAbsolute2, join as join2, relative as relative4, resolve as resolve6 } from "node:path";
3023
3157
 
3024
3158
  class LspRequestContextParseError extends Error {
3025
- code;
3026
- name = "LspRequestContextParseError";
3027
3159
  constructor(code, message) {
3028
3160
  super(message);
3029
3161
  this.code = code;
3162
+ this.name = "LspRequestContextParseError";
3030
3163
  }
3031
3164
  }
3032
3165
 
3033
3166
  class LspRequestContextUnavailableError extends Error {
3034
- name = "LspRequestContextUnavailableError";
3035
3167
  constructor() {
3036
3168
  super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
3169
+ this.name = "LspRequestContextUnavailableError";
3037
3170
  }
3038
3171
  }
3039
3172
  var storage = new AsyncLocalStorage;
@@ -3053,7 +3186,7 @@ function contextCwd() {
3053
3186
  }
3054
3187
  function createStandaloneMcpRequestContext(input = {}) {
3055
3188
  const env = input.env ?? process.env;
3056
- const cwd = canonicalCwd(input.cwd ?? process.cwd());
3189
+ const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
3057
3190
  const home = input.homeDir ?? homedir();
3058
3191
  const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
3059
3192
  const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
@@ -3191,7 +3324,6 @@ function isPlainRecord(value) {
3191
3324
 
3192
3325
  // src/daemon-request-error.ts
3193
3326
  class DaemonRequestError extends Error {
3194
- requestWritten;
3195
3327
  constructor(message, requestWritten) {
3196
3328
  super(message);
3197
3329
  this.name = "DaemonRequestError";
@@ -3214,7 +3346,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
3214
3346
  }
3215
3347
 
3216
3348
  class DaemonRequestTimedOutError extends DaemonRequestError {
3217
- timeoutMs;
3218
3349
  constructor(requestWritten, timeoutMs) {
3219
3350
  super("daemon request timed out", requestWritten);
3220
3351
  this.name = "DaemonRequestTimedOutError";
@@ -3293,14 +3424,12 @@ var PROTOCOL_ERROR_CODE = -32002;
3293
3424
  var AUTH_TOKEN_BYTES = 32;
3294
3425
 
3295
3426
  class UnsafePrivateDirectoryError extends Error {
3296
- path;
3297
- reason;
3298
- name = "UnsafePrivateDirectoryError";
3299
- code = "unsafe_private_directory";
3300
3427
  constructor(path, reason) {
3301
3428
  super(`unsafe private directory ${path}: ${reason}`);
3302
3429
  this.path = path;
3303
3430
  this.reason = reason;
3431
+ this.name = "UnsafePrivateDirectoryError";
3432
+ this.code = "unsafe_private_directory";
3304
3433
  }
3305
3434
  }
3306
3435
  function authEnvelope(token) {
@@ -3484,20 +3613,18 @@ var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
3484
3613
  var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
3485
3614
 
3486
3615
  class InvalidRuntimeOverrideError extends Error {
3487
- code = "invalid_runtime_override";
3488
- reason;
3489
3616
  constructor(reason, message) {
3490
3617
  super(message);
3618
+ this.code = "invalid_runtime_override";
3491
3619
  this.name = "InvalidRuntimeOverrideError";
3492
3620
  this.reason = reason;
3493
3621
  }
3494
3622
  }
3495
3623
 
3496
3624
  class InvalidDaemonVersionError extends Error {
3497
- code = "invalid_daemon_version";
3498
- version;
3499
3625
  constructor(version) {
3500
3626
  super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
3627
+ this.code = "invalid_daemon_version";
3501
3628
  this.name = "InvalidDaemonVersionError";
3502
3629
  this.version = version;
3503
3630
  }
@@ -3543,10 +3670,9 @@ var requireFromHere = createRequire(import.meta.url);
3543
3670
  var MAX_SOCKET_PATH_LENGTH = 100;
3544
3671
 
3545
3672
  class InvalidDaemonDirectoryError extends Error {
3546
- code = "invalid_daemon_directory";
3547
- directory;
3548
3673
  constructor(directory) {
3549
3674
  super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
3675
+ this.code = "invalid_daemon_directory";
3550
3676
  this.name = "InvalidDaemonDirectoryError";
3551
3677
  this.directory = directory;
3552
3678
  }
@@ -3700,7 +3826,7 @@ async function probeDaemon(paths, timeoutMs = PROBE_TIMEOUT_MS, signal) {
3700
3826
  return await pingDaemon(paths, token, timeoutMs, signal) !== null;
3701
3827
  }
3702
3828
  function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
3703
- return new Promise((resolve7) => {
3829
+ return new Promise((resolve) => {
3704
3830
  const socket = new Socket;
3705
3831
  let settled = false;
3706
3832
  let timer;
@@ -3712,7 +3838,7 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
3712
3838
  clearTimeout(timer);
3713
3839
  signal?.removeEventListener("abort", onAbort);
3714
3840
  socket.destroy();
3715
- resolve7(value);
3841
+ resolve(value);
3716
3842
  };
3717
3843
  const onAbort = () => finish(null);
3718
3844
  const decoder = createLineDecoder((message) => {
@@ -3735,13 +3861,17 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
3735
3861
  socket.connect(paths.socket);
3736
3862
  });
3737
3863
  }
3738
- function spawnDaemonProcess(paths) {
3864
+ function spawnDaemonProcess(paths, deps = {}) {
3739
3865
  mkdirSync2(dirname6(paths.log), { recursive: true });
3740
3866
  const logFd = openSync2(paths.log, "a");
3741
3867
  try {
3742
- const child = spawn2(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
3868
+ const spawnDaemonChild = deps.spawn ?? spawn2;
3869
+ const executable = deps.resolveExecutable?.() ?? resolveDaemonNodeExecutable();
3870
+ const child = spawnDaemonChild(executable, [paths.cliPath, "daemon"], {
3743
3871
  detached: true,
3744
- stdio: ["ignore", logFd, logFd]
3872
+ stdio: ["ignore", logFd, logFd],
3873
+ windowsHide: true,
3874
+ env: { ...process.env, BUN_BE_BUN: "1" }
3745
3875
  });
3746
3876
  child.once("spawn", () => closeSync2(logFd));
3747
3877
  child.once("error", (error) => {
@@ -3771,7 +3901,7 @@ function defaultEnsureDaemonDeps() {
3771
3901
  };
3772
3902
  }
3773
3903
  function sleepWithSignal(ms, signal) {
3774
- return new Promise((resolve7) => {
3904
+ return new Promise((resolve) => {
3775
3905
  let settled = false;
3776
3906
  const finish = () => {
3777
3907
  if (settled)
@@ -3779,7 +3909,7 @@ function sleepWithSignal(ms, signal) {
3779
3909
  settled = true;
3780
3910
  clearTimeout(timer);
3781
3911
  signal?.removeEventListener("abort", finish);
3782
- resolve7();
3912
+ resolve();
3783
3913
  };
3784
3914
  const timer = setTimeout(finish, ms);
3785
3915
  if (signal?.aborted) {
@@ -3794,7 +3924,7 @@ function awaitWithSignal2(promise, signal) {
3794
3924
  return promise;
3795
3925
  if (signal.aborted)
3796
3926
  return Promise.reject(abortError3(signal));
3797
- return new Promise((resolve7, reject) => {
3927
+ return new Promise((resolve, reject) => {
3798
3928
  let settled = false;
3799
3929
  const finish = (run) => {
3800
3930
  if (settled)
@@ -3805,7 +3935,7 @@ function awaitWithSignal2(promise, signal) {
3805
3935
  };
3806
3936
  const onAbort = () => finish(() => reject(abortError3(signal)));
3807
3937
  signal.addEventListener("abort", onAbort, { once: true });
3808
- promise.then((value) => finish(() => resolve7(value)), (error) => finish(() => reject(error)));
3938
+ promise.then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error)));
3809
3939
  });
3810
3940
  }
3811
3941
  function throwIfAborted(signal) {
@@ -3834,18 +3964,18 @@ function parsePingResponse(message) {
3834
3964
  return null;
3835
3965
  if (!endpoint || typeof endpoint !== "object" || Array.isArray(endpoint))
3836
3966
  return null;
3837
- const path2 = Reflect.get(endpoint, "path");
3967
+ const path = Reflect.get(endpoint, "path");
3838
3968
  const kind = Reflect.get(endpoint, "kind");
3839
- if (typeof path2 !== "string")
3969
+ if (typeof path !== "string")
3840
3970
  return null;
3841
3971
  if (kind === "windows")
3842
- return { pid, nonce, startedAt, endpoint: { kind, path: path2 } };
3972
+ return { pid, nonce, startedAt, endpoint: { kind, path } };
3843
3973
  if (kind === "missing")
3844
- return { pid, nonce, startedAt, endpoint: { kind, path: path2 } };
3974
+ return { pid, nonce, startedAt, endpoint: { kind, path } };
3845
3975
  const dev = Reflect.get(endpoint, "dev");
3846
3976
  const ino = Reflect.get(endpoint, "ino");
3847
3977
  if (kind === "unix" && typeof dev === "number" && typeof ino === "number") {
3848
- return { pid, nonce, startedAt, endpoint: { kind, path: path2, dev, ino } };
3978
+ return { pid, nonce, startedAt, endpoint: { kind, path, dev, ino } };
3849
3979
  }
3850
3980
  return null;
3851
3981
  }
@@ -3893,7 +4023,7 @@ ${body}` : `${body}
3893
4023
  await writeChunk(output, payload);
3894
4024
  }
3895
4025
  function writeChunk(output, chunk) {
3896
- return new Promise((resolve7, reject) => {
4026
+ return new Promise((resolve, reject) => {
3897
4027
  let settled = false;
3898
4028
  const onError = (error) => {
3899
4029
  if (settled)
@@ -3913,7 +4043,7 @@ function writeChunk(output, chunk) {
3913
4043
  return;
3914
4044
  }
3915
4045
  output.removeListener("error", onError);
3916
- resolve7();
4046
+ resolve();
3917
4047
  });
3918
4048
  } catch (error) {
3919
4049
  output.removeListener("error", onError);
@@ -4022,6 +4152,7 @@ async function runJsonRpcStdioServer(config) {
4022
4152
  const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
4023
4153
  isClosed = true;
4024
4154
  config.onIdleTimeout?.();
4155
+ config.input.destroy();
4025
4156
  });
4026
4157
  const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
4027
4158
  isClosed = true;
@@ -4118,7 +4249,11 @@ function createParentWatchdog(config, onDeadParent) {
4118
4249
  const probeAlive = config.probeAlive ?? isProcessAlive;
4119
4250
  let fired = false;
4120
4251
  const timer = setInterval(() => {
4121
- if (fired || probeAlive(parentPid))
4252
+ if (fired)
4253
+ return;
4254
+ const alive = probeAlive(parentPid);
4255
+ config.onPoll?.(alive);
4256
+ if (alive)
4122
4257
  return;
4123
4258
  fired = true;
4124
4259
  onDeadParent(parentPid, pollIntervalMs);
@@ -4153,60 +4288,55 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
4153
4288
  };
4154
4289
  }
4155
4290
  // ../lsp-core/src/lsp/client-wrapper.ts
4156
- import { existsSync as existsSync10, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
4157
- import { basename as basename3, dirname as dirname8, join as join4, resolve as resolve7 } from "node:path";
4291
+ import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
4292
+ import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
4158
4293
 
4159
- // ../lsp-core/src/lsp/server-install-state.ts
4160
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4161
- import { dirname as dirname7 } from "node:path";
4162
- function getInstallDecisionsPath() {
4163
- return lspRequestContext().installDecisionsPath;
4164
- }
4165
- function loadInstallDecisions() {
4166
- const path2 = getInstallDecisionsPath();
4167
- if (!existsSync7(path2))
4168
- return {};
4169
- try {
4170
- const parsed = JSON.parse(readFileSync4(path2, "utf8"));
4171
- return isInstallDecisions(parsed) ? parsed : {};
4172
- } catch {
4173
- return {};
4294
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
4295
+ import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
4296
+ import { dirname as dirname7, join as join3 } from "node:path";
4297
+
4298
+ // ../lsp-core/src/lsp/workspace-markers.ts
4299
+ var GIT_WORKSPACE_MARKER = ".git";
4300
+ var PROJECT_WORKSPACE_MARKERS = [
4301
+ "package.json",
4302
+ "pyproject.toml",
4303
+ "Cargo.toml",
4304
+ "go.mod",
4305
+ "pom.xml",
4306
+ "build.gradle"
4307
+ ];
4308
+ var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
4309
+
4310
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
4311
+ function findWorkspaceRootOutsideContext(directory) {
4312
+ const marked = nearestMarkedAncestor(directory);
4313
+ if (marked !== undefined)
4314
+ return marked;
4315
+ return realpathSync4(nearestExistingAncestor(directory));
4316
+ }
4317
+ function nearestMarkedAncestor(directory) {
4318
+ let current = directory;
4319
+ for (;; ) {
4320
+ if (existsSync7(current) && WORKSPACE_MARKERS.some((marker) => existsSync7(join3(current, marker)))) {
4321
+ return realpathSync4(current);
4322
+ }
4323
+ const parent = dirname7(current);
4324
+ if (parent === current)
4325
+ return;
4326
+ current = parent;
4174
4327
  }
4175
4328
  }
4176
- function loadInstallDecision(serverId) {
4177
- return loadInstallDecisions()[serverId];
4178
- }
4179
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4180
- const decisions = loadInstallDecisions();
4181
- decisions[serverId] = { decision, decidedAt };
4182
- writeInstallDecisions(decisions);
4183
- }
4184
- function isInstallDecision(value) {
4185
- return value === "declined" || value === "allowed";
4186
- }
4187
- function writeInstallDecisions(decisions) {
4188
- const path2 = getInstallDecisionsPath();
4189
- mkdirSync3(dirname7(path2), { recursive: true });
4190
- const tmpPath = `${path2}.tmp`;
4191
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4192
- `, "utf8");
4193
- renameSync2(tmpPath, path2);
4194
- }
4195
- function isInstallDecisions(value) {
4196
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4197
- }
4198
- function isInstallDecisionRecord(value) {
4199
- if (!isRecord5(value))
4200
- return false;
4201
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4202
- }
4203
- function isRecord5(value) {
4204
- return typeof value === "object" && value !== null && !Array.isArray(value);
4329
+ function nearestExistingAncestor(directory) {
4330
+ let current = directory;
4331
+ while (!existsSync7(current)) {
4332
+ const parent = dirname7(current);
4333
+ if (parent === current)
4334
+ return current;
4335
+ current = parent;
4336
+ }
4337
+ return current;
4205
4338
  }
4206
4339
 
4207
- // ../lsp-core/src/lsp/config-loader.ts
4208
- import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
4209
-
4210
4340
  // ../lsp-core/src/lsp/server-definitions.ts
4211
4341
  var LSP_INSTALL_HINTS = {
4212
4342
  typescript: "npm install -g typescript-language-server typescript",
@@ -4252,6 +4382,26 @@ var LSP_INSTALL_HINTS = {
4252
4382
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
4253
4383
  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"
4254
4384
  };
4385
+ var LSP_LOCAL_INSTALL_HINTS = {
4386
+ typescript: "bun add -d typescript-language-server typescript",
4387
+ vue: "bun add -d @vue/language-server",
4388
+ eslint: "bun add -d vscode-langservers-extracted",
4389
+ oxlint: "bun add -d oxlint",
4390
+ biome: "bun add -d @biomejs/biome",
4391
+ svelte: "bun add -d svelte-language-server",
4392
+ astro: "bun add -d @astrojs/language-server",
4393
+ bash: "bun add -d bash-language-server",
4394
+ "bash-ls": "bun add -d bash-language-server",
4395
+ "yaml-ls": "bun add -d yaml-language-server",
4396
+ php: "bun add -d intelephense",
4397
+ prisma: "bun add -d prisma",
4398
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
4399
+ pyright: "uv add --dev pyright",
4400
+ basedpyright: "uv add --dev basedpyright",
4401
+ ruff: "uv add --dev ruff",
4402
+ ty: "uv add --dev ty",
4403
+ "ruby-lsp": "bundle add ruby-lsp --group development"
4404
+ };
4255
4405
  var BUILTIN_SERVERS = {
4256
4406
  typescript: {
4257
4407
  command: ["typescript-language-server", "--stdio"],
@@ -4354,18 +4504,67 @@ var BUILTIN_SERVERS = {
4354
4504
  }
4355
4505
  };
4356
4506
 
4507
+ // ../lsp-core/src/lsp/server-install-state.ts
4508
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4509
+ import { dirname as dirname8 } from "node:path";
4510
+ function getInstallDecisionsPath() {
4511
+ return lspRequestContext().installDecisionsPath;
4512
+ }
4513
+ function loadInstallDecisions() {
4514
+ const path = getInstallDecisionsPath();
4515
+ if (!existsSync8(path))
4516
+ return {};
4517
+ try {
4518
+ const parsed = JSON.parse(readFileSync4(path, "utf8"));
4519
+ return isInstallDecisions(parsed) ? parsed : {};
4520
+ } catch {
4521
+ return {};
4522
+ }
4523
+ }
4524
+ function loadInstallDecision(serverId) {
4525
+ return loadInstallDecisions()[serverId];
4526
+ }
4527
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4528
+ const decisions = loadInstallDecisions();
4529
+ decisions[serverId] = { decision, decidedAt };
4530
+ writeInstallDecisions(decisions);
4531
+ }
4532
+ function isInstallDecision(value) {
4533
+ return value === "declined" || value === "allowed";
4534
+ }
4535
+ function writeInstallDecisions(decisions) {
4536
+ const path = getInstallDecisionsPath();
4537
+ mkdirSync3(dirname8(path), { recursive: true });
4538
+ const tmpPath = `${path}.tmp`;
4539
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4540
+ `, "utf8");
4541
+ renameSync2(tmpPath, path);
4542
+ }
4543
+ function isInstallDecisions(value) {
4544
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4545
+ }
4546
+ function isInstallDecisionRecord(value) {
4547
+ if (!isRecord5(value))
4548
+ return false;
4549
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4550
+ }
4551
+ function isRecord5(value) {
4552
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4553
+ }
4554
+
4357
4555
  // ../lsp-core/src/lsp/config-loader.ts
4556
+ import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
4358
4557
  function getProjectConfigPaths() {
4359
4558
  return lspRequestContext().projectConfigPaths;
4360
4559
  }
4361
4560
  function getUserConfigPath() {
4362
4561
  return lspRequestContext().userConfigPath;
4363
4562
  }
4364
- function loadJsonFile(path2) {
4365
- if (!existsSync8(path2))
4563
+ function loadJsonFile(path) {
4564
+ if (!existsSync9(path))
4366
4565
  return null;
4367
4566
  try {
4368
- const parsed = JSON.parse(readFileSync5(path2, "utf-8"));
4567
+ const parsed = JSON.parse(readFileSync5(path, "utf-8"));
4369
4568
  return isConfigJson(parsed) ? parsed : null;
4370
4569
  } catch {
4371
4570
  return null;
@@ -4382,8 +4581,8 @@ function loadAllConfigs() {
4382
4581
  return configs;
4383
4582
  }
4384
4583
  function loadFirstJsonFile(paths) {
4385
- for (const path2 of paths) {
4386
- const config = loadJsonFile(path2);
4584
+ for (const path of paths) {
4585
+ const config = loadJsonFile(path);
4387
4586
  if (config)
4388
4587
  return config;
4389
4588
  }
@@ -4409,10 +4608,10 @@ function getMergedServers() {
4409
4608
  }
4410
4609
  if (seen.has(id))
4411
4610
  continue;
4412
- const server2 = createServerFromEntry(id, entry, source);
4413
- if (!server2)
4611
+ const server = createServerFromEntry(id, entry, source);
4612
+ if (!server)
4414
4613
  continue;
4415
- servers.push(server2);
4614
+ servers.push(server);
4416
4615
  seen.add(id);
4417
4616
  }
4418
4617
  }
@@ -4444,7 +4643,7 @@ function createServerFromEntry(id, entry, source) {
4444
4643
  if (source === "project") {
4445
4644
  if (!builtin)
4446
4645
  return null;
4447
- const server3 = createServer({
4646
+ const server = createServer({
4448
4647
  id,
4449
4648
  command: builtin.command,
4450
4649
  extensions: entry.extensions ?? builtin.extensions,
@@ -4452,35 +4651,35 @@ function createServerFromEntry(id, entry, source) {
4452
4651
  source
4453
4652
  });
4454
4653
  if (entry.initialization !== undefined) {
4455
- server3.initialization = entry.initialization;
4654
+ server.initialization = entry.initialization;
4456
4655
  }
4457
- return server3;
4656
+ return server;
4458
4657
  }
4459
4658
  if (entry.command && entry.extensions) {
4460
- const server3 = createServer({
4659
+ const server = createServer({
4461
4660
  id,
4462
4661
  command: entry.command,
4463
4662
  extensions: entry.extensions,
4464
4663
  priority: entry.priority ?? 0,
4465
4664
  source
4466
4665
  });
4467
- applyOptionalServerFields(server3, entry);
4468
- return server3;
4666
+ applyOptionalServerFields(server, entry);
4667
+ return server;
4469
4668
  }
4470
4669
  if (!builtin)
4471
4670
  return null;
4472
- const server2 = createServer({
4671
+ const server = createServer({
4473
4672
  id,
4474
4673
  command: entry.command ?? builtin.command,
4475
4674
  extensions: entry.extensions ?? builtin.extensions,
4476
4675
  priority: entry.priority ?? 0,
4477
4676
  source
4478
4677
  });
4479
- applyOptionalServerFields(server2, entry);
4480
- return server2;
4678
+ applyOptionalServerFields(server, entry);
4679
+ return server;
4481
4680
  }
4482
4681
  function createServer(input) {
4483
- const server2 = {
4682
+ const server = {
4484
4683
  id: input.id,
4485
4684
  command: input.command,
4486
4685
  extensions: input.extensions,
@@ -4488,19 +4687,19 @@ function createServer(input) {
4488
4687
  source: input.source
4489
4688
  };
4490
4689
  if (input.env !== undefined) {
4491
- server2.env = input.env;
4690
+ server.env = input.env;
4492
4691
  }
4493
4692
  if (input.initialization !== undefined) {
4494
- server2.initialization = input.initialization;
4693
+ server.initialization = input.initialization;
4495
4694
  }
4496
- return server2;
4695
+ return server;
4497
4696
  }
4498
- function applyOptionalServerFields(server2, entry) {
4697
+ function applyOptionalServerFields(server, entry) {
4499
4698
  if (entry.env !== undefined) {
4500
- server2.env = entry.env;
4699
+ server.env = entry.env;
4501
4700
  }
4502
4701
  if (entry.initialization !== undefined) {
4503
- server2.initialization = entry.initialization;
4702
+ server.initialization = entry.initialization;
4504
4703
  }
4505
4704
  }
4506
4705
  function isConfigJson(value) {
@@ -4550,64 +4749,165 @@ function getDisabledServerIds() {
4550
4749
  }
4551
4750
 
4552
4751
  // ../lsp-core/src/lsp/server-installation.ts
4553
- import { existsSync as existsSync9 } from "node:fs";
4554
- import { delimiter as delimiter3, join as join3 } from "node:path";
4555
- function isServerInstalled(command, _workingDirectory) {
4556
- if (command.length === 0)
4557
- return false;
4558
- const [cmd] = command;
4559
- if (!cmd)
4560
- return false;
4561
- if (cmd.includes("/") || cmd.includes("\\")) {
4562
- if (existsSync9(cmd))
4563
- return true;
4752
+ import { existsSync as existsSync10 } from "node:fs";
4753
+ import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
4754
+ var LOCAL_BIN_RULES = [
4755
+ {
4756
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
4757
+ binDirs: [join4("node_modules", ".bin")]
4758
+ },
4759
+ {
4760
+ markers: [
4761
+ "pyproject.toml",
4762
+ "ty.toml",
4763
+ "requirements.txt",
4764
+ "setup.py",
4765
+ "setup.cfg",
4766
+ "Pipfile",
4767
+ "pyrightconfig.json",
4768
+ "ruff.toml",
4769
+ ".ruff.toml"
4770
+ ],
4771
+ binDirs: [
4772
+ join4(".venv", "bin"),
4773
+ join4(".venv", "Scripts"),
4774
+ join4("venv", "bin"),
4775
+ join4("venv", "Scripts"),
4776
+ join4(".env", "bin"),
4777
+ join4(".env", "Scripts")
4778
+ ]
4779
+ },
4780
+ {
4781
+ markers: ["Gemfile", "Gemfile.lock"],
4782
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
4783
+ },
4784
+ {
4785
+ markers: ["go.mod", "go.sum", "go.work"],
4786
+ binDirs: ["bin"]
4564
4787
  }
4565
- const isWindows = process.platform === "win32";
4566
- let exts = [""];
4567
- if (isWindows) {
4568
- const pathExt = process.env["PATHEXT"] ?? "";
4569
- if (pathExt) {
4570
- const systemExts = pathExt.split(";").filter(Boolean);
4571
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4572
- } else {
4573
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
4788
+ ];
4789
+ var resolutionCache = new Map;
4790
+ var probeCount = 0;
4791
+ function probe(path) {
4792
+ probeCount += 1;
4793
+ return existsSync10(path);
4794
+ }
4795
+ function executableSuffixes(platform, pathExt) {
4796
+ if (platform !== "win32")
4797
+ return [""];
4798
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
4799
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
4800
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4801
+ }
4802
+ function probeWithSuffixes(directory, command, suffixes) {
4803
+ for (const suffix of suffixes) {
4804
+ const candidate = join4(directory, command + suffix);
4805
+ if (probe(candidate))
4806
+ return candidate;
4807
+ }
4808
+ return null;
4809
+ }
4810
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
4811
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
4812
+ let current = resolve7(workingDirectory);
4813
+ while (true) {
4814
+ for (const rule of LOCAL_BIN_RULES) {
4815
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
4816
+ continue;
4817
+ for (const binDir of rule.binDirs) {
4818
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
4819
+ if (found !== null)
4820
+ return found;
4821
+ }
4574
4822
  }
4823
+ if (probe(join4(current, ".git")))
4824
+ return null;
4825
+ if (boundary !== undefined && current === boundary)
4826
+ return null;
4827
+ const parent = dirname9(current);
4828
+ if (parent === current)
4829
+ return null;
4830
+ current = parent;
4575
4831
  }
4576
- let pathEnv = process.env["PATH"] ?? "";
4577
- if (isWindows && !pathEnv) {
4832
+ }
4833
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
4834
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
4835
+ if (platform === "win32" && !pathEnv) {
4578
4836
  pathEnv = process.env["Path"] ?? "";
4579
4837
  }
4580
- const paths = pathEnv.split(delimiter3);
4581
- for (const p of paths) {
4582
- for (const suffix of exts) {
4583
- if (existsSync9(join3(p, cmd + suffix))) {
4584
- return true;
4585
- }
4586
- }
4838
+ for (const entry of pathEnv.split(delimiter3)) {
4839
+ if (entry.length === 0)
4840
+ continue;
4841
+ const found = probeWithSuffixes(entry, command, suffixes);
4842
+ if (found !== null)
4843
+ return found;
4587
4844
  }
4588
- if (cmd === "node")
4589
- return true;
4590
- return false;
4845
+ return null;
4846
+ }
4847
+ function resolveServerBinary(command, workingDirectory, options = {}) {
4848
+ if (command.length === 0)
4849
+ return null;
4850
+ const [cmd] = command;
4851
+ if (cmd === undefined || cmd.length === 0)
4852
+ return null;
4853
+ const platform = options.platform ?? process.platform;
4854
+ const suffixes = executableSuffixes(platform, options.pathExt);
4855
+ if (cmd.includes("/") || cmd.includes("\\")) {
4856
+ const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
4857
+ return probe(explicit) ? explicit : null;
4858
+ }
4859
+ const cacheKey = JSON.stringify([
4860
+ workingDirectory ?? "",
4861
+ cmd,
4862
+ platform,
4863
+ options.stopAt ?? "",
4864
+ options.pathExt ?? "",
4865
+ options.pathEnv ?? process.env["PATH"] ?? ""
4866
+ ]);
4867
+ const cached = resolutionCache.get(cacheKey);
4868
+ if (cached !== undefined)
4869
+ return cached;
4870
+ let resolved = null;
4871
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
4872
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
4873
+ }
4874
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
4875
+ if (resolved === null && cmd === "node")
4876
+ resolved = cmd;
4877
+ resolutionCache.set(cacheKey, resolved);
4878
+ return resolved;
4879
+ }
4880
+ function isServerInstalled(command, workingDirectory, options = {}) {
4881
+ if (command.length === 0)
4882
+ return false;
4883
+ return resolveServerBinary(command, workingDirectory, options) !== null;
4591
4884
  }
4592
4885
 
4593
4886
  // ../lsp-core/src/lsp/server-resolution.ts
4887
+ function withResolvedCommand(command, binaryPath) {
4888
+ return [binaryPath, ...command.slice(1)];
4889
+ }
4594
4890
  function findServerForExtension(ext) {
4595
4891
  const servers = getMergedServers();
4596
- for (const server2 of servers) {
4597
- if (server2.extensions.includes(ext) && isServerInstalled(server2.command)) {
4892
+ const workingDirectory = contextCwd();
4893
+ for (const server of servers) {
4894
+ if (!server.extensions.includes(ext))
4895
+ continue;
4896
+ const binaryPath = resolveServerBinary(server.command, workingDirectory);
4897
+ if (binaryPath !== null) {
4598
4898
  const resolvedServer = {
4599
- id: server2.id,
4600
- command: server2.command,
4601
- extensions: server2.extensions,
4602
- priority: server2.priority
4899
+ id: server.id,
4900
+ command: withResolvedCommand(server.command, binaryPath),
4901
+ extensions: server.extensions,
4902
+ priority: server.priority
4603
4903
  };
4604
- if (server2.env !== undefined) {
4904
+ if (server.env !== undefined) {
4605
4905
  return {
4606
4906
  status: "found",
4607
4907
  server: {
4608
4908
  ...resolvedServer,
4609
- env: server2.env,
4610
- ...server2.initialization === undefined ? {} : { initialization: server2.initialization }
4909
+ env: server.env,
4910
+ ...server.initialization === undefined ? {} : { initialization: server.initialization }
4611
4911
  }
4612
4912
  };
4613
4913
  }
@@ -4615,20 +4915,20 @@ function findServerForExtension(ext) {
4615
4915
  status: "found",
4616
4916
  server: {
4617
4917
  ...resolvedServer,
4618
- ...server2.initialization === undefined ? {} : { initialization: server2.initialization }
4918
+ ...server.initialization === undefined ? {} : { initialization: server.initialization }
4619
4919
  }
4620
4920
  };
4621
4921
  }
4622
4922
  }
4623
- for (const server2 of servers) {
4624
- if (server2.extensions.includes(ext)) {
4625
- const installHint = LSP_INSTALL_HINTS[server2.id] ?? `Install '${server2.command[0]}' and ensure it's in your PATH`;
4923
+ for (const server of servers) {
4924
+ if (server.extensions.includes(ext)) {
4925
+ const installHint = LSP_INSTALL_HINTS[server.id] ?? `Install '${server.command[0]}' and ensure it's in your PATH`;
4626
4926
  return {
4627
4927
  status: "not_installed",
4628
4928
  server: {
4629
- id: server2.id,
4630
- command: server2.command,
4631
- extensions: server2.extensions
4929
+ id: server.id,
4930
+ command: server.command,
4931
+ extensions: server.extensions
4632
4932
  },
4633
4933
  installHint
4634
4934
  };
@@ -4644,20 +4944,21 @@ function findServerForExtension(ext) {
4644
4944
  function getAllServers() {
4645
4945
  const servers = getMergedServers();
4646
4946
  const disabled = getDisabledServerIds();
4947
+ const workingDirectory = contextCwd();
4647
4948
  const result = [];
4648
4949
  const seen = new Set;
4649
- for (const server2 of servers) {
4650
- if (seen.has(server2.id))
4950
+ for (const server of servers) {
4951
+ if (seen.has(server.id))
4651
4952
  continue;
4652
4953
  result.push({
4653
- id: server2.id,
4654
- installed: isServerInstalled(server2.command),
4655
- extensions: server2.extensions,
4954
+ id: server.id,
4955
+ installed: isServerInstalled(server.command, workingDirectory),
4956
+ extensions: server.extensions,
4656
4957
  disabled: false,
4657
- source: server2.source,
4658
- priority: server2.priority
4958
+ source: server.source,
4959
+ priority: server.priority
4659
4960
  });
4660
- seen.add(server2.id);
4961
+ seen.add(server.id);
4661
4962
  }
4662
4963
  for (const id of disabled) {
4663
4964
  if (seen.has(id))
@@ -4665,7 +4966,7 @@ function getAllServers() {
4665
4966
  const builtin = BUILTIN_SERVERS[id];
4666
4967
  result.push({
4667
4968
  id,
4668
- installed: builtin ? isServerInstalled(builtin.command) : false,
4969
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
4669
4970
  extensions: builtin?.extensions ?? [],
4670
4971
  disabled: true,
4671
4972
  source: "disabled",
@@ -4676,7 +4977,6 @@ function getAllServers() {
4676
4977
  }
4677
4978
 
4678
4979
  // ../lsp-core/src/lsp/client-wrapper.ts
4679
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
4680
4980
  function isDirectoryPath(filePath) {
4681
4981
  try {
4682
4982
  return statSync4(filePath).isDirectory();
@@ -4689,36 +4989,40 @@ function findWorkspaceRoot(filePath) {
4689
4989
  const abs = resolveReadablePathInsideContext(filePath);
4690
4990
  let dir = abs;
4691
4991
  if (!isDirectoryPath(dir)) {
4692
- dir = dirname8(dir);
4992
+ dir = dirname10(dir);
4693
4993
  }
4994
+ if (!isPathInside(cwd, abs))
4995
+ return findWorkspaceRootOutsideContext(dir);
4694
4996
  const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4997
+ let nearestPackageRoot;
4695
4998
  while (isPathInside(cwd, dir)) {
4696
4999
  const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4697
5000
  if (canonicalDir !== undefined) {
4698
- for (const marker of WORKSPACE_MARKERS) {
4699
- if (existsSync10(join4(dir, marker))) {
4700
- return canonicalDir;
4701
- }
5001
+ if (existsSync11(join5(dir, GIT_WORKSPACE_MARKER))) {
5002
+ return canonicalDir;
5003
+ }
5004
+ if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
5005
+ nearestPackageRoot = canonicalDir;
4702
5006
  }
4703
5007
  }
4704
5008
  if (dir === cwd)
4705
5009
  break;
4706
- dir = dirname8(dir);
5010
+ dir = dirname10(dir);
4707
5011
  }
4708
- return fallbackRoot;
5012
+ return nearestPackageRoot ?? fallbackRoot;
5013
+ }
5014
+ function hasProjectWorkspaceMarker(directory) {
5015
+ return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync11(join5(directory, marker)));
4709
5016
  }
4710
5017
  function resolveReadablePathInsideContext(filePath) {
4711
5018
  const cwd = contextCwd();
4712
- const abs = resolve7(cwd, filePath);
5019
+ const abs = resolve8(cwd, filePath);
4713
5020
  if (isPathInside(cwd, abs))
4714
5021
  return abs;
4715
5022
  const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4716
5023
  if (rebased !== undefined)
4717
5024
  return rebased;
4718
- const canonical = canonicalizeExistingOrNearestAncestor(abs);
4719
- if (isPathInside(cwd, canonical))
4720
- return canonical;
4721
- throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
5025
+ return canonicalizeExistingOrNearestAncestor(abs);
4722
5026
  }
4723
5027
  function resolvePathInsideContext(filePath) {
4724
5028
  const cwd = contextCwd();
@@ -4729,16 +5033,16 @@ function resolvePathInsideContext(filePath) {
4729
5033
  }
4730
5034
  return canonical;
4731
5035
  }
4732
- function rebaseThroughCanonicalAncestor(path2, cwd) {
4733
- let current = path2;
5036
+ function rebaseThroughCanonicalAncestor(path, cwd) {
5037
+ let current = path;
4734
5038
  const suffix = [];
4735
5039
  while (true) {
4736
- if (existsSync10(current)) {
4737
- const canonical = realpathSync4(current);
5040
+ if (existsSync11(current)) {
5041
+ const canonical = realpathSync5(current);
4738
5042
  if (isPathInside(cwd, canonical))
4739
- return suffix.length === 0 ? canonical : join4(canonical, ...suffix);
5043
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
4740
5044
  }
4741
- const parent = dirname8(current);
5045
+ const parent = dirname10(current);
4742
5046
  if (parent === current)
4743
5047
  return;
4744
5048
  suffix.unshift(basename3(current));
@@ -4746,9 +5050,9 @@ function rebaseThroughCanonicalAncestor(path2, cwd) {
4746
5050
  }
4747
5051
  }
4748
5052
  function existingDirectoryInsideContext(directory, cwd) {
4749
- if (!existsSync10(directory))
5053
+ if (!existsSync11(directory))
4750
5054
  return;
4751
- const canonical = realpathSync4(directory);
5055
+ const canonical = realpathSync5(directory);
4752
5056
  if (!statSync4(canonical).isDirectory())
4753
5057
  return;
4754
5058
  return isPathInside(cwd, canonical) ? canonical : undefined;
@@ -4761,7 +5065,7 @@ function nearestExistingDirectoryInsideContext(directory, cwd) {
4761
5065
  return canonical;
4762
5066
  if (current === cwd)
4763
5067
  return;
4764
- current = dirname8(current);
5068
+ current = dirname10(current);
4765
5069
  }
4766
5070
  return;
4767
5071
  }
@@ -4788,33 +5092,46 @@ function formatServerLookupError(result) {
4788
5092
  ].join(`
4789
5093
  `);
4790
5094
  }
5095
+ function formatInstallOptions(serverId, installHint) {
5096
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
5097
+ if (localHint === undefined) {
5098
+ return ["To install, run:", ` ${installHint}`];
5099
+ }
5100
+ return [
5101
+ "To install in THIS repository (preferred — no global install needed):",
5102
+ ` ${localHint}`,
5103
+ "",
5104
+ "Or install it globally:",
5105
+ ` ${installHint}`
5106
+ ];
5107
+ }
4791
5108
  function formatNotInstalled(result) {
4792
- const { server: server2, installHint } = result;
4793
- const extensions = server2.extensions.join(", ");
4794
- const decision = loadInstallDecision(server2.id)?.decision;
5109
+ const { server, installHint } = result;
5110
+ const extensions = server.extensions.join(", ");
5111
+ const decision = loadInstallDecision(server.id)?.decision;
4795
5112
  const context = lspRequestContext();
4796
5113
  if (decision === "declined") {
4797
- return `LSP server '${server2.id}' (${extensions}) is NOT INSTALLED; user previously declined installation — proceed without LSP.`;
5114
+ return `LSP server '${server.id}' (${extensions}) is NOT INSTALLED; user previously declined installation — proceed without LSP.`;
4798
5115
  }
4799
5116
  const header = [
4800
- `LSP server '${server2.id}' for ${extensions} is NOT INSTALLED.`,
5117
+ `LSP server '${server.id}' for ${extensions} is NOT INSTALLED.`,
4801
5118
  "",
4802
- `Command not found: ${server2.command[0]}`,
5119
+ `Command not found: ${server.command[0]}`,
4803
5120
  ""
4804
5121
  ];
5122
+ const installOptions = formatInstallOptions(server.id, installHint);
4805
5123
  if (decision === "allowed") {
4806
5124
  return [
4807
5125
  ...header,
4808
5126
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
4809
- ` ${installHint}`
5127
+ ...installOptions.slice(1)
4810
5128
  ].join(`
4811
5129
  `);
4812
5130
  }
4813
5131
  if (!context.capabilities.installDecisionTool) {
4814
5132
  return [
4815
5133
  ...header,
4816
- "To install, run:",
4817
- ` ${installHint}`,
5134
+ ...installOptions,
4818
5135
  "",
4819
5136
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4820
5137
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -4823,13 +5140,12 @@ function formatNotInstalled(result) {
4823
5140
  }
4824
5141
  return [
4825
5142
  ...header,
4826
- "To install, run:",
4827
- ` ${installHint}`,
5143
+ ...installOptions,
4828
5144
  "",
4829
5145
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4830
5146
  "- If the user agrees: run the install command above, then retry this tool.",
4831
5147
  "- If the user declines, OR has NOT explicitly asked for LSP installation:",
4832
- ` call lsp_install_decision { server_id: "${server2.id}", decision: "declined" },`,
5148
+ ` call lsp_install_decision { server_id: "${server.id}", decision: "declined" },`,
4833
5149
  ` which writes to ${context.installDecisionsPath},`,
4834
5150
  " then ignore this message and proceed WITHOUT LSP."
4835
5151
  ].join(`
@@ -4853,34 +5169,34 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4853
5169
  if (result.status !== "found") {
4854
5170
  throw new LspServerLookupError(formatServerLookupError(result), result);
4855
5171
  }
4856
- const server2 = result.server;
5172
+ const server = result.server;
4857
5173
  const root = findWorkspaceRoot(absPath);
4858
5174
  const manager = options.manager ?? getLspManager();
4859
5175
  const acquireAndCall = async (allowRetry) => {
4860
- const client = await manager.getClient(root, server2, options.signal);
5176
+ const client = await manager.getClient(root, server, options.signal);
4861
5177
  try {
4862
5178
  return await fn(client, root, absPath);
4863
5179
  } catch (err) {
4864
5180
  if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4865
- manager.invalidateClient(root, server2.id, client);
5181
+ manager.invalidateClient(root, server.id, client);
4866
5182
  return acquireAndCall(false);
4867
5183
  }
4868
5184
  if (err instanceof LspRequestTimeoutError) {
4869
- if (manager.isServerInitializing(root, server2.id)) {
5185
+ if (manager.isServerInitializing(root, server.id)) {
4870
5186
  throw new LspServerInitializingError(err);
4871
5187
  }
4872
5188
  }
4873
5189
  throw err;
4874
5190
  } finally {
4875
- manager.releaseClient(root, server2.id);
5191
+ manager.releaseClient(root, server.id);
4876
5192
  }
4877
5193
  };
4878
5194
  return acquireAndCall(true);
4879
5195
  }
4880
5196
 
4881
5197
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4882
- import { existsSync as existsSync11, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
4883
- import { join as join5, resolve as resolve8 } from "node:path";
5198
+ import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
5199
+ import { join as join6, resolve as resolve9 } from "node:path";
4884
5200
 
4885
5201
  // ../lsp-core/src/lsp/formatters.ts
4886
5202
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -4895,10 +5211,10 @@ function uriToPath(uri) {
4895
5211
  }
4896
5212
  function formatLocation(loc) {
4897
5213
  if ("targetUri" in loc) {
4898
- const uri2 = uriToPath(loc.targetUri);
4899
- const line2 = loc.targetRange.start.line + 1;
4900
- const char2 = loc.targetRange.start.character;
4901
- return `${uri2}:${line2}:${char2}`;
5214
+ const uri = uriToPath(loc.targetUri);
5215
+ const line = loc.targetRange.start.line + 1;
5216
+ const char = loc.targetRange.start.character;
5217
+ return `${uri}:${line}:${char}`;
4902
5218
  }
4903
5219
  const uri = uriToPath(loc.uri);
4904
5220
  const line = loc.range.start.line + 1;
@@ -5010,7 +5326,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
5010
5326
  for (const entry of entries) {
5011
5327
  if (files.length >= maxFiles)
5012
5328
  return;
5013
- const fullPath = join5(currentDir, entry);
5329
+ const fullPath = join6(currentDir, entry);
5014
5330
  let stat;
5015
5331
  try {
5016
5332
  stat = lstatSync5(fullPath);
@@ -5035,15 +5351,15 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5035
5351
  if (!extension.startsWith(".")) {
5036
5352
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
5037
5353
  }
5038
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
5039
- if (!existsSync11(absDir)) {
5354
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
5355
+ if (!existsSync12(absDir)) {
5040
5356
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
5041
5357
  }
5042
5358
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
5043
5359
  if (serverResult.status !== "found") {
5044
5360
  throw new LspServerLookupError(formatServerLookupError(serverResult));
5045
5361
  }
5046
- const server2 = serverResult.server;
5362
+ const server = serverResult.server;
5047
5363
  const allFiles = (options.listFiles ?? collectFilesWithExtension)(absDir, extension, maxFiles + 1);
5048
5364
  const wasCapped = allFiles.length > maxFiles;
5049
5365
  const filesToProcess = allFiles.slice(0, maxFiles);
@@ -5063,7 +5379,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5063
5379
  const fileErrors = [];
5064
5380
  const maxConcurrency = Math.max(1, options.maxConcurrency ?? DIRECTORY_DIAGNOSTICS_MAX_CONCURRENCY);
5065
5381
  options.signal?.throwIfAborted();
5066
- const client = await manager.getClient(root, server2, options.signal);
5382
+ const client = await manager.getClient(root, server, options.signal);
5067
5383
  try {
5068
5384
  let nextIndex = 0;
5069
5385
  const workers = Array.from({ length: Math.min(maxConcurrency, filesToProcess.length) }, async () => {
@@ -5091,7 +5407,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5091
5407
  });
5092
5408
  await Promise.all(workers);
5093
5409
  } finally {
5094
- manager.releaseClient(root, server2.id);
5410
+ manager.releaseClient(root, server.id);
5095
5411
  }
5096
5412
  const displayDiagnostics = allDiagnostics.slice(0, DEFAULT_MAX_DIAGNOSTICS);
5097
5413
  const wasDiagCapped = allDiagnostics.length > DEFAULT_MAX_DIAGNOSTICS;
@@ -5123,7 +5439,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5123
5439
 
5124
5440
  // ../lsp-core/src/lsp/infer-extension.ts
5125
5441
  import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
5126
- import { join as join6 } from "node:path";
5442
+ import { join as join7 } from "node:path";
5127
5443
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
5128
5444
  var MAX_SCAN_ENTRIES = 500;
5129
5445
  function inferExtensionFromDirectory(directory) {
@@ -5141,7 +5457,7 @@ function inferExtensionFromDirectory(directory) {
5141
5457
  for (const entry of entries) {
5142
5458
  if (scanned >= MAX_SCAN_ENTRIES)
5143
5459
  return;
5144
- const fullPath = join6(dir, entry);
5460
+ const fullPath = join7(dir, entry);
5145
5461
  let stat;
5146
5462
  try {
5147
5463
  stat = lstatSync6(fullPath);
@@ -5300,8 +5616,8 @@ function clientOptions(signal) {
5300
5616
  }
5301
5617
 
5302
5618
  // ../lsp-core/src/tools/result.ts
5303
- function text(text2, details, isError = false) {
5304
- return { content: [{ type: "text", text: text2 }], details, isError };
5619
+ function text(text, details, isError = false) {
5620
+ return { content: [{ type: "text", text }], details, isError };
5305
5621
  }
5306
5622
 
5307
5623
  // ../lsp-core/src/tools/diagnostics.ts
@@ -5321,7 +5637,7 @@ async function executeLspDiagnostics(params, signal) {
5321
5637
  const extension = inferExtensionFromDirectory(absPath);
5322
5638
  if (!extension) {
5323
5639
  const message = `No supported source files found in directory: ${absPath}`;
5324
- const details3 = {
5640
+ const details = {
5325
5641
  filePath,
5326
5642
  severity,
5327
5643
  mode: "directory",
@@ -5331,24 +5647,24 @@ async function executeLspDiagnostics(params, signal) {
5331
5647
  error: message,
5332
5648
  errorKind: "no_files"
5333
5649
  };
5334
- return text(message, details3);
5650
+ return text(message, details);
5335
5651
  }
5336
- const output2 = await aggregateDiagnosticsForDirectory(absPath, extension, severity, undefined, signal === undefined ? {} : { signal });
5337
- const details2 = {
5652
+ const output = await aggregateDiagnosticsForDirectory(absPath, extension, severity, undefined, signal === undefined ? {} : { signal });
5653
+ const details = {
5338
5654
  filePath,
5339
5655
  severity,
5340
5656
  mode: "directory",
5341
5657
  diagnostics: [],
5342
- totalDiagnostics: output2.totalDiagnostics,
5658
+ totalDiagnostics: output.totalDiagnostics,
5343
5659
  truncated: false,
5344
- fileFailures: [...output2.fileFailures]
5660
+ fileFailures: [...output.fileFailures]
5345
5661
  };
5346
- return text(output2.output, details2);
5662
+ return text(output.output, details);
5347
5663
  }
5348
5664
  const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
5349
5665
  if (result.transientError) {
5350
5666
  const message = result.transientError.message;
5351
- const details2 = {
5667
+ const details = {
5352
5668
  filePath,
5353
5669
  severity,
5354
5670
  mode: "file",
@@ -5358,7 +5674,7 @@ async function executeLspDiagnostics(params, signal) {
5358
5674
  error: message,
5359
5675
  errorKind: result.transientError.kind
5360
5676
  };
5361
- return text(message, details2, true);
5677
+ return text(message, details, true);
5362
5678
  }
5363
5679
  const diagnostics = filterDiagnosticsBySeverity(asDiagnosticArray(result), severity);
5364
5680
  const total = diagnostics.length;
@@ -5392,6 +5708,96 @@ async function executeLspDiagnostics(params, signal) {
5392
5708
  throw error;
5393
5709
  }
5394
5710
  }
5711
+ // ../lsp-core/src/lsp/format-document.ts
5712
+ import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
5713
+ var DEFAULT_FORMATTING_OPTIONS = {
5714
+ tabSize: 4,
5715
+ insertSpaces: false,
5716
+ trimTrailingWhitespace: true,
5717
+ insertFinalNewline: true,
5718
+ trimFinalNewlines: true
5719
+ };
5720
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
5721
+ async function formatDocumentWithClient(client, filePath, options = {}) {
5722
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
5723
+ if (edits === null)
5724
+ return { status: "unavailable", reason: "capability_not_advertised" };
5725
+ if (edits.length === 0)
5726
+ return UNCHANGED;
5727
+ const before = readFileSync6(filePath, "utf-8");
5728
+ const normalized = normalizeTextEdits(before, edits, 0);
5729
+ if (normalized.text === before)
5730
+ return UNCHANGED;
5731
+ writeAtomically(filePath, normalized.text);
5732
+ await client.openFile(filePath);
5733
+ return {
5734
+ status: "formatted",
5735
+ ...lineDelta(normalized.edits)
5736
+ };
5737
+ }
5738
+ function lineDelta(edits) {
5739
+ let linesAdded = 0;
5740
+ let linesRemoved = 0;
5741
+ for (const edit of edits) {
5742
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
5743
+ linesAdded += edit.newText.split(`
5744
+ `).length;
5745
+ }
5746
+ return { linesAdded, linesRemoved };
5747
+ }
5748
+ function writeAtomically(filePath, content) {
5749
+ const tempPath = `${filePath}.omo-format.tmp`;
5750
+ writeFileSync3(tempPath, content, "utf-8");
5751
+ try {
5752
+ renameSync3(tempPath, filePath);
5753
+ } catch (error) {
5754
+ try {
5755
+ unlinkSync2(tempPath);
5756
+ } catch {}
5757
+ throw error;
5758
+ }
5759
+ }
5760
+
5761
+ // ../lsp-core/src/tools/format.ts
5762
+ async function executeLspFormat(params, signal) {
5763
+ const filePath = requireString(params, "filePath");
5764
+ try {
5765
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
5766
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
5767
+ } catch (error) {
5768
+ const missingDependency = missingDependencyResult(error, {
5769
+ filePath,
5770
+ status: "unavailable",
5771
+ reason: "server_unavailable",
5772
+ linesAdded: 0,
5773
+ linesRemoved: 0
5774
+ });
5775
+ if (missingDependency)
5776
+ return missingDependency;
5777
+ throw error;
5778
+ }
5779
+ }
5780
+ function formatDetails(filePath, result) {
5781
+ if (result.status === "unavailable") {
5782
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
5783
+ }
5784
+ return {
5785
+ filePath,
5786
+ status: result.status,
5787
+ linesAdded: result.linesAdded,
5788
+ linesRemoved: result.linesRemoved
5789
+ };
5790
+ }
5791
+ function describeResult(filePath, result) {
5792
+ if (result.status === "unavailable") {
5793
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
5794
+ }
5795
+ if (result.status === "unchanged") {
5796
+ return `Already formatted: ${filePath}`;
5797
+ }
5798
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
5799
+ }
5800
+
5395
5801
  // ../lsp-core/src/tools/install-decision.ts
5396
5802
  async function executeLspInstallDecision(params) {
5397
5803
  const serverId = requireString(params, "server_id");
@@ -5399,7 +5805,7 @@ async function executeLspInstallDecision(params) {
5399
5805
  if (!isInstallDecision(decision)) {
5400
5806
  return text(`Invalid decision '${String(decision)}'. Expected "declined" or "allowed".`, { serverId, errorKind: "invalid_decision" }, true);
5401
5807
  }
5402
- const serverIds = [...new Set(getMergedServers().map((server2) => server2.id))];
5808
+ const serverIds = [...new Set(getMergedServers().map((server) => server.id))];
5403
5809
  if (!serverIds.includes(serverId)) {
5404
5810
  const preview = serverIds.slice(0, 20).join(", ");
5405
5811
  return text(`Unknown LSP server '${serverId}'. Known servers: ${preview}${serverIds.length > 20 ? "..." : ""}`, { serverId, errorKind: "unknown_server" }, true);
@@ -5539,10 +5945,10 @@ function objectSchema(properties, required = []) {
5539
5945
  async function executeLspStatus() {
5540
5946
  const servers = getAllServers();
5541
5947
  const snapshots = getLspManager().getSnapshot();
5542
- const installed = servers.filter((server2) => server2.installed && !server2.disabled);
5543
- const configuredLines = servers.map((server2) => {
5544
- const state = server2.disabled ? "disabled" : server2.installed ? "installed" : "missing";
5545
- return `- ${server2.id}: ${state}; source=${server2.source}; extensions=${server2.extensions.join(", ")}`;
5948
+ const installed = servers.filter((server) => server.installed && !server.disabled);
5949
+ const configuredLines = servers.map((server) => {
5950
+ const state = server.disabled ? "disabled" : server.installed ? "installed" : "missing";
5951
+ return `- ${server.id}: ${state}; source=${server.source}; extensions=${server.extensions.join(", ")}`;
5546
5952
  });
5547
5953
  const activeLines = snapshots.map((snapshot) => {
5548
5954
  const state = snapshot.alive ? snapshot.isInitializing ? "initializing" : "alive" : "dead";
@@ -5585,8 +5991,8 @@ async function executeLspSymbols(params, signal) {
5585
5991
  errorKind: "missing_query"
5586
5992
  });
5587
5993
  }
5588
- const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
5589
- return formatSymbolsResult(filePath, scope, symbols2, limit, query);
5994
+ const symbols = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
5995
+ return formatSymbolsResult(filePath, scope, symbols, limit, query);
5590
5996
  }
5591
5997
  const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
5592
5998
  return formatSymbolsResult(filePath, scope, symbols, limit);
@@ -5724,6 +6130,16 @@ var LSP_MCP_TOOLS = [
5724
6130
  }, ["filePath", "line", "character", "newName"]),
5725
6131
  execute: executeLspRename
5726
6132
  },
6133
+ {
6134
+ name: "format",
6135
+ aliases: ["lsp_format"],
6136
+ title: "LSP Format",
6137
+ description: "Format a source file with its language server and write the returned edits to disk.",
6138
+ inputSchema: objectSchema({
6139
+ filePath: { type: "string", description: "Source file path to format." }
6140
+ }, ["filePath"]),
6141
+ execute: executeLspFormat
6142
+ },
5727
6143
  {
5728
6144
  name: "install_decision",
5729
6145
  aliases: ["lsp_install_decision"],
@@ -5824,7 +6240,10 @@ function requestedProtocolVersion(params) {
5824
6240
  var CONTEXT_KEY = "_context";
5825
6241
 
5826
6242
  class InvalidDaemonRequestError extends Error {
5827
- name = "InvalidDaemonRequestError";
6243
+ constructor() {
6244
+ super(...arguments);
6245
+ this.name = "InvalidDaemonRequestError";
6246
+ }
5828
6247
  }
5829
6248
  function extractRequestContext(raw) {
5830
6249
  if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
@@ -5940,14 +6359,17 @@ async function callToolViaDaemon(name, args, options) {
5940
6359
  function callDiagnosticsViaDaemon(filePath, options) {
5941
6360
  return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
5942
6361
  }
6362
+ function callFormatViaDaemon(filePath, options) {
6363
+ return callToolViaDaemon("format", { filePath }, options);
6364
+ }
5943
6365
  function currentRequestContext(env = process.env) {
5944
6366
  const cwd = process.cwd();
5945
6367
  const home = env["HOME"] ?? homedir3();
5946
6368
  return parseLspRequestContext({
5947
6369
  cwd,
5948
- projectConfigPaths: [join7(cwd, ".codex", "lsp-client.json")],
5949
- userConfigPath: join7(home, ".codex", "lsp-client.json"),
5950
- installDecisionsPath: join7(home, ".codex", "lsp-install-decisions.json"),
6370
+ projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
6371
+ userConfigPath: join8(home, ".codex", "lsp-client.json"),
6372
+ installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
5951
6373
  capabilities: { installDecisionTool: true }
5952
6374
  });
5953
6375
  }
@@ -5962,7 +6384,7 @@ function withContext(args, context) {
5962
6384
  function ensureDaemonAvailable(paths, ensure, signal) {
5963
6385
  if (!signal)
5964
6386
  return ensure(paths);
5965
- return new Promise((resolve9, reject) => {
6387
+ return new Promise((resolve, reject) => {
5966
6388
  let settled = false;
5967
6389
  const finish = (run) => {
5968
6390
  if (settled)
@@ -5977,11 +6399,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
5977
6399
  return;
5978
6400
  }
5979
6401
  signal.addEventListener("abort", onAbort, { once: true });
5980
- Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve9()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
6402
+ Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
5981
6403
  });
5982
6404
  }
5983
6405
  function sendToolCall(paths, token, name, args, options) {
5984
- return new Promise((resolve9, reject) => {
6406
+ return new Promise((resolve, reject) => {
5985
6407
  const socket = connect(paths.socket);
5986
6408
  const requestId = allocateProxyRequestId();
5987
6409
  let settled = false;
@@ -6034,7 +6456,7 @@ function sendToolCall(paths, token, name, args, options) {
6034
6456
  }
6035
6457
  const result = toToolResult(message, requestId);
6036
6458
  if (result)
6037
- finish(() => resolve9(result));
6459
+ finish(() => resolve(result));
6038
6460
  else
6039
6461
  finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
6040
6462
  });
@@ -6079,8 +6501,8 @@ function isRetryableTool(name) {
6079
6501
  return name !== "rename" && name !== "lsp_rename";
6080
6502
  }
6081
6503
  // src/proxy.ts
6082
- import { existsSync as existsSync12, realpathSync as realpathSync5 } from "node:fs";
6083
- import { basename as basename4, delimiter as delimiter4, dirname as dirname9, isAbsolute as isAbsolute5 } from "node:path";
6504
+ import { existsSync as existsSync13, realpathSync as realpathSync6 } from "node:fs";
6505
+ import { basename as basename4, delimiter as delimiter4, dirname as dirname11, isAbsolute as isAbsolute6 } from "node:path";
6084
6506
  var DEFAULT_STARTUP_TIMEOUT_MS = 1e4;
6085
6507
  async function runMcpStdioProxy(options = {}) {
6086
6508
  const input = options.input ?? process.stdin;
@@ -6203,34 +6625,34 @@ function canonicalizePathList(value) {
6203
6625
  return value.split(delimiter4).map((entry) => canonicalizePath(entry) ?? entry).join(delimiter4);
6204
6626
  }
6205
6627
  function canonicalizePath(value) {
6206
- if (value === undefined || !isAbsolute5(value) || !existsSync12(value))
6628
+ if (value === undefined || !isAbsolute6(value) || !existsSync13(value))
6207
6629
  return value;
6208
- return realpathSync5(value);
6630
+ return realpathSync6(value);
6209
6631
  }
6210
- function projectRootFromOpenCodeConfigPath(path2) {
6211
- if (basename4(path2) !== "lsp.json" && basename4(path2) !== "lsp-client.json")
6632
+ function projectRootFromOpenCodeConfigPath(path) {
6633
+ if (basename4(path) !== "lsp.json" && basename4(path) !== "lsp-client.json")
6212
6634
  return;
6213
- const configDir = dirname9(path2);
6635
+ const configDir = dirname11(path);
6214
6636
  const configDirName = basename4(configDir);
6215
6637
  if (configDirName !== ".opencode" && configDirName !== ".omo")
6216
6638
  return;
6217
- return dirname9(configDir);
6639
+ return dirname11(configDir);
6218
6640
  }
6219
6641
  export {
6220
- validateDaemonVersion,
6221
- runMcpStdioProxy,
6222
- resolveDaemonRuntime,
6223
- probeDaemon,
6224
- ensureDaemonRunning,
6225
- disposeDefaultLspManager,
6226
- daemonPaths,
6227
- currentRequestContext,
6228
- callToolViaDaemon,
6229
- callDiagnosticsViaDaemon,
6230
- OMO_LSP_DAEMON_VERSION,
6231
- OMO_LSP_DAEMON_DIR,
6232
- OMO_LSP_DAEMON_CLI,
6233
- InvalidRuntimeOverrideError,
6642
+ InvalidDaemonDirectoryError,
6234
6643
  InvalidDaemonVersionError,
6235
- InvalidDaemonDirectoryError
6644
+ InvalidRuntimeOverrideError,
6645
+ OMO_LSP_DAEMON_CLI,
6646
+ OMO_LSP_DAEMON_DIR,
6647
+ OMO_LSP_DAEMON_VERSION,
6648
+ callDiagnosticsViaDaemon,
6649
+ callToolViaDaemon,
6650
+ currentRequestContext,
6651
+ daemonPaths,
6652
+ disposeDefaultLspManager,
6653
+ ensureDaemonRunning,
6654
+ probeDaemon,
6655
+ resolveDaemonRuntime,
6656
+ runMcpStdioProxy,
6657
+ validateDaemonVersion
6236
6658
  };