oh-my-opencode 5.0.0-beta.3 → 5.0.0-beta.31

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 (639) hide show
  1. package/.agents/command/publish.md +44 -16
  2. package/.agents/skills/publish/SKILL.md +44 -16
  3. package/.agents/skills/senpi-qa/SKILL.md +80 -0
  4. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.mjs +65 -0
  5. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.test.mjs +171 -0
  6. package/.agents/skills/work-with-pr/SKILL.md +37 -23
  7. package/.opencode/command/publish.md +44 -16
  8. package/.opencode/skills/work-with-pr/SKILL.md +37 -23
  9. package/README.ja.md +25 -21
  10. package/README.ko.md +25 -21
  11. package/README.md +38 -23
  12. package/README.ru.md +24 -20
  13. package/README.zh-cn.md +25 -21
  14. package/dist/agents/atlas/agent.d.ts +0 -1
  15. package/dist/agents/sisyphus/grok-4.d.ts +20 -0
  16. package/dist/agents/sisyphus/index.d.ts +2 -0
  17. package/dist/agents/sisyphus-agent-config.d.ts +6 -0
  18. package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
  19. package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +15 -4
  20. package/dist/agents/types.d.ts +2 -2
  21. package/dist/cli/config-manager/parse-opencode-config-file.d.ts +2 -1
  22. package/dist/cli/doctor/checks/system-plugin.d.ts +4 -3
  23. package/dist/cli/fallback-lane-policy.d.ts +1 -0
  24. package/dist/cli/index.js +22601 -20302
  25. package/dist/cli/install-codex/install-codex-test-fixtures.d.ts +1 -1
  26. package/dist/cli/run/on-complete-hook.d.ts +2 -0
  27. package/dist/cli/runtime-commands.d.ts +1 -1
  28. package/dist/cli/worktree-sweep/classify.d.ts +16 -0
  29. package/dist/cli/worktree-sweep/format.d.ts +8 -0
  30. package/dist/cli/worktree-sweep/git.d.ts +19 -0
  31. package/dist/cli/worktree-sweep/index.d.ts +7 -0
  32. package/dist/cli/worktree-sweep/options.d.ts +2 -0
  33. package/dist/cli/worktree-sweep/parse-worktree-list.d.ts +8 -0
  34. package/dist/cli/worktree-sweep/sweep.d.ts +2 -0
  35. package/dist/cli/worktree-sweep/types.d.ts +65 -0
  36. package/dist/cli/worktree-sweep/worktree-sweep.d.ts +2 -0
  37. package/dist/cli-node/index.js +22219 -19897
  38. package/dist/config/schema/background-task.d.ts +1 -0
  39. package/dist/config/schema/commands.d.ts +1 -1
  40. package/dist/config/schema/hooks.d.ts +1 -1
  41. package/dist/config/schema/oh-my-opencode-config.d.ts +5 -1
  42. package/dist/config/schema/ulw-execute.d.ts +5 -0
  43. package/dist/config/validate.d.ts +2 -0
  44. package/dist/create-hooks.d.ts +3 -1
  45. package/dist/features/background-agent/constants.d.ts +0 -7
  46. package/dist/features/background-agent/manager.d.ts +2 -1
  47. package/dist/features/background-agent/parent-wake-dispatched-tracker.d.ts +0 -1
  48. package/dist/features/background-agent/subagent-spawn-limits.d.ts +8 -0
  49. package/dist/features/btw-side/btw-command-draft.d.ts +7 -0
  50. package/dist/features/btw-side/context-injector.d.ts +15 -0
  51. package/dist/features/btw-side/index.d.ts +8 -0
  52. package/dist/features/btw-side/metadata.d.ts +15 -0
  53. package/dist/features/btw-side/parent-context-budget.d.ts +9 -0
  54. package/dist/features/btw-side/server-session-registry.d.ts +8 -0
  55. package/dist/features/btw-side/tui-adoption-cache.d.ts +13 -0
  56. package/dist/features/btw-side/tui-adoption-guard.d.ts +5 -0
  57. package/dist/features/btw-side/tui-controller-types.d.ts +68 -0
  58. package/dist/features/btw-side/tui-controller.d.ts +19 -0
  59. package/dist/features/btw-side/tui-escape-return.d.ts +12 -0
  60. package/dist/features/btw-side/tui-keymap.d.ts +17 -0
  61. package/dist/features/btw-side/tui-parent-validator.d.ts +6 -0
  62. package/dist/features/btw-side/tui-picker-options.d.ts +20 -0
  63. package/dist/features/btw-side/tui-picker.d.ts +9 -0
  64. package/dist/features/btw-side/tui-prompt-queue.d.ts +8 -0
  65. package/dist/features/btw-side/tui-session-bridge.d.ts +11 -0
  66. package/dist/features/btw-side/tui-session-catalog.d.ts +35 -0
  67. package/dist/features/btw-side/tui-side-removal.d.ts +11 -0
  68. package/dist/features/btw-side/tui-side-start.d.ts +9 -0
  69. package/dist/features/btw-side/tui-wiring.d.ts +8 -0
  70. package/dist/features/builtin-commands/templates/ulw-execute.d.ts +1 -0
  71. package/dist/features/builtin-commands/types.d.ts +1 -1
  72. package/dist/features/opengateway-provider/index.d.ts +13 -0
  73. package/dist/features/task-toast-manager/manager.d.ts +0 -24
  74. package/dist/features/team-mode/tools/messaging-fallback-wake.d.ts +15 -0
  75. package/dist/hooks/anthropic-context-window-limit-recovery/message-storage-directory.d.ts +0 -3
  76. package/dist/hooks/anthropic-context-window-limit-recovery/state.d.ts +1 -0
  77. package/dist/hooks/anthropic-context-window-limit-recovery/storage/empty-messages.d.ts +0 -1
  78. package/dist/hooks/atlas/atlas-hook.d.ts +1 -0
  79. package/dist/hooks/atlas/atlas-lifecycle-store.d.ts +50 -0
  80. package/dist/hooks/atlas/event-handler.d.ts +1 -0
  81. package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
  82. package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
  83. package/dist/hooks/atlas/tool-execute-before.d.ts +3 -0
  84. package/dist/hooks/atlas/types.d.ts +1 -0
  85. package/dist/hooks/claude-code-hooks/session-hook-state.d.ts +1 -0
  86. package/dist/hooks/claude-code-hooks/stop.d.ts +2 -0
  87. package/dist/hooks/claude-code-hooks/todo.d.ts +0 -1
  88. package/dist/hooks/claude-code-hooks/transcript.d.ts +2 -0
  89. package/dist/hooks/fsync-skip-warning/index.d.ts +4 -0
  90. package/dist/hooks/hashline-edit-diff-enhancer/hook.d.ts +1 -0
  91. package/dist/hooks/hashline-edit-diff-enhancer/pending-captures.d.ts +13 -0
  92. package/dist/hooks/index.d.ts +1 -1
  93. package/dist/hooks/keyword-detector/hook.d.ts +7 -0
  94. package/dist/hooks/keyword-detector/ultrawork/source-detector.d.ts +0 -1
  95. package/dist/hooks/model-fallback/hook.d.ts +1 -1
  96. package/dist/hooks/prometheus-md-only/agent-resolution.d.ts +2 -2
  97. package/dist/hooks/runtime-fallback/chat-message-handler.d.ts +2 -0
  98. package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +1 -0
  99. package/dist/hooks/runtime-fallback/runtime-model-settings.d.ts +6 -0
  100. package/dist/hooks/runtime-fallback/session-status-handler.d.ts +1 -1
  101. package/dist/hooks/runtime-fallback/types.d.ts +3 -1
  102. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  103. package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
  104. package/dist/hooks/{start-work → ulw-execute}/context-info-builder.d.ts +1 -1
  105. package/dist/hooks/{start-work → ulw-execute}/index.d.ts +1 -1
  106. package/dist/hooks/ulw-execute/ulw-execute-hook.d.ts +23 -0
  107. package/dist/index.js +12989 -7152
  108. package/dist/oh-my-opencode.schema.json +20 -2
  109. package/dist/plugin/chat-message/types.d.ts +3 -3
  110. package/dist/plugin/chat-message/ulw-execute-message.d.ts +5 -0
  111. package/dist/plugin/event-session-lifecycle.d.ts +1 -0
  112. package/dist/plugin/hooks/create-core-hooks.d.ts +2 -1
  113. package/dist/plugin/hooks/create-session-hooks.d.ts +2 -2
  114. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
  115. package/dist/plugin/messages-transform.d.ts +1 -0
  116. package/dist/plugin-dispose.d.ts +3 -0
  117. package/dist/shared/agent-tool-restrictions.d.ts +0 -1
  118. package/dist/shared/index.d.ts +2 -0
  119. package/dist/shared/legacy-plugin-warning.d.ts +2 -1
  120. package/dist/shared/normalize-sdk-response.d.ts +1 -0
  121. package/dist/shared/plugin-entry-migrator.d.ts +4 -3
  122. package/dist/shared/plugin-entry-shape.d.ts +6 -0
  123. package/dist/shared/runtime-fallback-retry-marker.d.ts +16 -0
  124. package/dist/shared/shell-env.d.ts +1 -1
  125. package/dist/skills/ast-grep/AGENTS.md +51 -0
  126. package/dist/skills/coding-agent-sessions/AGENTS.md +62 -0
  127. package/dist/skills/coding-agent-sessions/SKILL.md +3 -2
  128. package/dist/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  129. package/dist/skills/coding-agent-sessions/references/senpi.md +4 -4
  130. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  131. package/dist/skills/data-scientist/SKILL.md +99 -239
  132. package/dist/skills/data-scientist/references/execution-surfaces.md +91 -0
  133. package/dist/skills/data-scientist/references/placement.md +74 -0
  134. package/dist/skills/data-scientist/references/polars-lane.md +95 -0
  135. package/dist/skills/data-scientist/references/uv-setup.md +1 -1
  136. package/dist/skills/data-scientist/references/visualization.md +64 -0
  137. package/dist/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  138. package/dist/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  139. package/dist/skills/debugging/SKILL.md +2 -0
  140. package/dist/skills/debugging/references/methodology/00-setup.md +12 -0
  141. package/dist/skills/debugging/references/methodology/02-investigate.md +21 -0
  142. package/dist/skills/debugging/references/runtimes/go.md +15 -1
  143. package/dist/skills/debugging/references/runtimes/native-binary.md +38 -0
  144. package/dist/skills/debugging/references/runtimes/node.md +25 -0
  145. package/dist/skills/debugging/references/runtimes/python.md +13 -0
  146. package/dist/skills/debugging/references/runtimes/rust.md +41 -0
  147. package/dist/skills/debugging/references/scripts/dap.mjs +267 -0
  148. package/dist/skills/debugging/references/scripts/dap.test.ts +86 -0
  149. package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  150. package/dist/skills/debugging/references/tools/dap.md +103 -0
  151. package/dist/skills/debugging/references/tools/frida.md +193 -0
  152. package/dist/skills/frontend/SKILL.md +11 -7
  153. package/dist/skills/frontend/references/design/_INDEX.md +1 -0
  154. package/dist/skills/frontend/references/design/print-paged-media.md +76 -0
  155. package/dist/skills/frontend/references/design/stylegallery.md +80 -0
  156. package/dist/skills/frontend/references/designpowers/README.md +1 -1
  157. package/dist/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  158. package/dist/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  159. package/dist/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  160. package/dist/skills/frontend/references/designpowers/orchestration.md +1 -1
  161. package/dist/skills/frontend/references/designpowers/routing.md +5 -5
  162. package/dist/skills/review-work/SKILL.md +3 -3
  163. package/dist/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  164. package/dist/skills/ultimate-browsing/SKILL.md +2 -0
  165. package/dist/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  166. package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
  167. package/dist/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  168. package/dist/skills/{start-work → ulw-execute}/SKILL.md +9 -8
  169. package/dist/skills/ulw-plan/SKILL.md +6 -6
  170. package/dist/skills/ulw-plan/references/full-workflow.md +31 -7
  171. package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
  172. package/dist/skills/ulw-plan/references/intent-unclear.md +5 -5
  173. package/dist/skills/ulw-research/SKILL.md +4 -2
  174. package/dist/skills/visual-qa/AGENTS.md +58 -0
  175. package/dist/skills/visual-qa/SKILL.md +3 -2
  176. package/dist/tools/delegate-task/builtin-categories.d.ts +1 -0
  177. package/dist/tools/delegate-task/builtin-category-definition.d.ts +1 -0
  178. package/dist/tools/delegate-task/sync-session-cleanup.d.ts +3 -0
  179. package/dist/tools/delegate-task/sync-session-poller.d.ts +1 -0
  180. package/dist/tools/delegate-task/tool-description.d.ts +3 -1
  181. package/dist/tools/delegate-task/types.d.ts +4 -0
  182. package/dist/tui.d.ts +12 -0
  183. package/dist/tui.js +11522 -11501
  184. package/package.json +42 -36
  185. package/packages/git-bash-mcp/dist/cli.js +6 -1
  186. package/packages/git-bash-mcp/package.json +1 -1
  187. package/packages/lsp-core/src/index.ts +1 -0
  188. package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
  189. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +0 -28
  190. package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
  191. package/packages/lsp-core/src/lsp/client-wrapper.test.ts +163 -13
  192. package/packages/lsp-core/src/lsp/client-wrapper.ts +110 -23
  193. package/packages/lsp-core/src/lsp/client.ts +26 -0
  194. package/packages/lsp-core/src/lsp/connection.ts +16 -0
  195. package/packages/lsp-core/src/lsp/constants.ts +6 -0
  196. package/packages/lsp-core/src/lsp/errors.ts +15 -0
  197. package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
  198. package/packages/lsp-core/src/lsp/format-document.ts +90 -0
  199. package/packages/lsp-core/src/lsp/manager-lifecycle.test.ts +262 -0
  200. package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
  201. package/packages/lsp-core/src/lsp/manager.ts +138 -12
  202. package/packages/lsp-core/src/lsp/outside-context-workspace.ts +33 -0
  203. package/packages/lsp-core/src/lsp/server-definitions.ts +29 -0
  204. package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
  205. package/packages/lsp-core/src/lsp/server-installation.ts +200 -27
  206. package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
  207. package/packages/lsp-core/src/lsp/server-resolution.ts +18 -5
  208. package/packages/lsp-core/src/lsp/transport.ts +9 -0
  209. package/packages/lsp-core/src/lsp/types.ts +8 -0
  210. package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +20 -1
  211. package/packages/lsp-core/src/lsp/workspace-markers.ts +18 -0
  212. package/packages/lsp-core/src/mcp.ts +3 -0
  213. package/packages/lsp-core/src/request-context.test.ts +29 -0
  214. package/packages/lsp-core/src/request-context.ts +1 -1
  215. package/packages/lsp-core/src/tool-surface.test.ts +13 -1
  216. package/packages/lsp-core/src/tools/definitions.ts +14 -0
  217. package/packages/lsp-core/src/tools/diagnostics.ts +3 -3
  218. package/packages/lsp-core/src/tools/format.test.ts +56 -0
  219. package/packages/lsp-core/src/tools/format.ts +56 -0
  220. package/packages/lsp-core/src/tools/index.ts +1 -0
  221. package/packages/lsp-core/src/tools/navigation.ts +4 -2
  222. package/packages/lsp-core/src/tools/rename.ts +4 -2
  223. package/packages/lsp-core/src/tools/symbols.ts +1 -1
  224. package/packages/lsp-core/src/tools/types.ts +10 -0
  225. package/packages/lsp-daemon/dist/cli.js +752 -307
  226. package/packages/lsp-daemon/dist/client.d.ts +10 -0
  227. package/packages/lsp-daemon/dist/client.js +712 -264
  228. package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
  229. package/packages/lsp-daemon/dist/daemon-client.js +3 -0
  230. package/packages/lsp-daemon/dist/ensure-daemon.js +1 -0
  231. package/packages/lsp-daemon/dist/index.js +716 -273
  232. package/packages/lsp-daemon/dist/proxy.js +3 -0
  233. package/packages/lsp-daemon/dist/version-reap.js +1 -1
  234. package/packages/lsp-daemon/package.json +1 -1
  235. package/packages/lsp-tools-mcp/dist/cli.js +671 -228
  236. package/packages/lsp-tools-mcp/dist/lsp/manager.js +207 -103
  237. package/packages/lsp-tools-mcp/dist/mcp.js +673 -230
  238. package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
  239. package/packages/lsp-tools-mcp/dist/tools.js +677 -238
  240. package/packages/omo-codex/THIRD-PARTY-NOTICES.md +4 -4
  241. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +4 -4
  242. package/packages/omo-codex/plugin/AGENTS.md +47 -0
  243. package/packages/omo-codex/plugin/README.md +1 -1
  244. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +34 -33
  245. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  246. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  247. package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +1 -0
  248. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +323 -117
  249. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +275 -85
  250. package/packages/omo-codex/plugin/components/codegraph/package.json +4 -4
  251. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +1 -0
  252. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +12 -0
  253. package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +1 -0
  254. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable-idle.test.ts +47 -0
  255. package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +9 -0
  256. package/packages/omo-codex/plugin/components/comment-checker/biome.json +2 -2
  257. package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +2 -1
  258. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  259. package/packages/omo-codex/plugin/components/comment-checker/package.json +5 -5
  260. package/packages/omo-codex/plugin/components/comment-checker/src/apply-patch.ts +2 -8
  261. package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +1 -2
  262. package/packages/omo-codex/plugin/components/comment-checker/src/request-extractor.ts +1 -1
  263. package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +1 -0
  264. package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +1 -1
  265. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  266. package/packages/omo-codex/plugin/components/git-bash/package.json +3 -4
  267. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
  268. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +1 -5
  269. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +1 -5
  270. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  271. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +5 -5
  272. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +1 -5
  273. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +4 -21
  274. package/packages/omo-codex/plugin/components/lsp/AGENTS.md +30 -15
  275. package/packages/omo-codex/plugin/components/lsp/biome.json +2 -2
  276. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +4 -4
  277. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +702 -278
  278. package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.js +1 -1
  279. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  280. package/packages/omo-codex/plugin/components/lsp/package.json +5 -5
  281. package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
  282. package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +1 -1
  283. package/packages/omo-codex/plugin/components/lsp/src/daemon-cli-path.ts +1 -5
  284. package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +6 -7
  285. package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +1 -2
  286. package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +11 -1
  287. package/packages/omo-codex/plugin/components/rules/AGENTS.md +12 -0
  288. package/packages/omo-codex/plugin/components/rules/biome.json +2 -2
  289. package/packages/omo-codex/plugin/components/rules/dist/cli.js +60 -45
  290. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  291. package/packages/omo-codex/plugin/components/rules/package.json +7 -7
  292. package/packages/omo-codex/plugin/components/rules/src/config.ts +1 -2
  293. package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +1 -2
  294. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +9 -5
  295. package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +1 -4
  296. package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +4 -9
  297. package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
  298. package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +17 -25
  299. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
  300. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
  301. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
  302. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
  303. package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
  304. package/packages/omo-codex/plugin/components/rules/test/dynamic-target-fingerprints.test.ts +1 -2
  305. package/packages/omo-codex/plugin/components/rules/test/engine.test.ts +7 -4
  306. package/packages/omo-codex/plugin/components/rules/test/finder.test.ts +2 -3
  307. package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +39 -72
  308. package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +1 -2
  309. package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
  310. package/packages/omo-codex/plugin/components/rules/test/matcher.test.ts +2 -3
  311. package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +1 -1
  312. package/packages/omo-codex/plugin/components/rules/test/parser.test.ts +1 -2
  313. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +5 -6
  314. package/packages/omo-codex/plugin/components/rules/test/rules-engine-consumption.test.ts +3 -6
  315. package/packages/omo-codex/plugin/components/rules/test/scanner.test.ts +1 -2
  316. package/packages/omo-codex/plugin/components/rules/test/sources.test.ts +2 -5
  317. package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +2 -17
  318. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  319. package/packages/omo-codex/plugin/components/teammode/package.json +5 -5
  320. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +3 -9
  321. package/packages/omo-codex/plugin/components/telemetry/AGENTS.md +8 -0
  322. package/packages/omo-codex/plugin/components/telemetry/biome.json +2 -2
  323. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2463 -437
  324. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2467 -441
  325. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  326. package/packages/omo-codex/plugin/components/telemetry/package.json +5 -5
  327. package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +1 -4
  328. package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -14
  329. package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +1 -1
  330. package/packages/omo-codex/plugin/components/telemetry/test/diagnostics.test.ts +2 -5
  331. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +5 -0
  332. package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
  333. package/packages/omo-codex/plugin/components/ultrawork/directive.md +13 -1
  334. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  335. package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -5
  336. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +13 -1
  337. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -6
  338. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +31 -7
  339. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
  340. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +5 -5
  341. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +9 -1
  342. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
  343. package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
  344. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +5 -4
  345. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/NOTICE +1 -1
  346. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/README.md +5 -5
  347. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/biome.json +2 -2
  348. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/directive.md +6 -6
  349. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +12 -12
  350. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +28 -0
  351. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/package.json +12 -12
  352. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/boulder-reader.ts +1 -1
  353. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/cli.ts +1 -1
  354. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/codex-hook.ts +3 -3
  355. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/directive.ts +1 -1
  356. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/index.ts +1 -1
  357. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/boulder-reader.test.ts +3 -3
  358. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +1 -4
  359. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +8 -22
  360. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +17 -0
  361. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
  362. package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
  363. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +13 -1
  364. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +2 -0
  365. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +5 -1
  366. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
  367. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +11 -1
  368. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +124 -68
  369. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.d.ts +2 -0
  370. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +9 -6
  371. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +1 -1
  372. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +1 -1
  373. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +4 -2
  374. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +7 -10
  375. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +3 -2
  376. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +3 -3
  377. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +15 -0
  378. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +50 -0
  379. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  380. package/packages/omo-codex/plugin/components/ulw-loop/package.json +5 -5
  381. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -2
  382. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
  383. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -0
  384. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +2 -0
  385. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +5 -1
  386. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +13 -1
  387. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +3 -5
  388. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +16 -5
  389. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +3 -1
  390. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
  391. package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +1 -1
  392. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +11 -14
  393. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +3 -2
  394. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +3 -3
  395. package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +73 -0
  396. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
  397. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +44 -1
  398. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +25 -0
  399. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +26 -2
  400. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +27 -2
  401. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +18 -0
  402. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
  403. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +7 -3
  404. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -37
  405. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +9 -0
  406. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +45 -2
  407. package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +20 -0
  408. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +8 -5
  409. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
  410. package/packages/omo-codex/plugin/components/ulw-loop/test/surface.test.ts +74 -0
  411. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +4 -5
  412. package/packages/omo-codex/plugin/components/ulw-loop/vitest.config.ts +1 -0
  413. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  414. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  415. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  416. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  417. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  418. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  419. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  420. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  421. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  422. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  423. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  424. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  425. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  426. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  427. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  428. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  429. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +17 -0
  430. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  431. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +17 -0
  432. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  433. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  434. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  435. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  436. package/packages/omo-codex/plugin/model-catalog.json +3 -3
  437. package/packages/omo-codex/plugin/package-lock.json +681 -395
  438. package/packages/omo-codex/plugin/package.json +2 -2
  439. package/packages/omo-codex/plugin/scripts/AGENTS.md +40 -0
  440. package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -1
  441. package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +3 -3
  442. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +11 -11
  443. package/packages/omo-codex/plugin/shared/package.json +3 -4
  444. package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +51 -0
  445. package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +62 -0
  446. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
  447. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  448. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
  449. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  450. package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
  451. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
  452. package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
  453. package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
  454. package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
  455. package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
  456. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  457. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  458. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -0
  459. package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
  460. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
  461. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
  462. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
  463. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
  464. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
  465. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
  466. package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
  467. package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  468. package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
  469. package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
  470. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +11 -7
  471. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
  472. package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
  473. package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
  474. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
  475. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  476. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  477. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  478. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
  479. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
  480. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +4 -4
  481. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  482. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -0
  483. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  484. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
  485. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  486. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +13 -1
  487. package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +12 -11
  488. package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
  489. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -2
  490. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
  491. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -0
  492. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -6
  493. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +31 -7
  494. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
  495. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +5 -5
  496. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +4 -2
  497. package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
  498. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +3 -2
  499. package/packages/omo-codex/plugin/test/AGENTS.md +47 -0
  500. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
  501. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +8 -28
  502. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -1
  503. package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
  504. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
  505. package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
  506. package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
  507. package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -2
  508. package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +2 -2
  509. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +1 -1
  510. package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +2 -2
  511. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +4 -4
  512. package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
  513. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
  514. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
  515. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
  516. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +12 -12
  517. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +1 -119
  518. package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
  519. package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
  520. package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
  521. package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
  522. package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
  523. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +0 -3
  524. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
  525. package/packages/omo-codex/scripts/AGENTS.md +36 -0
  526. package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +2 -2
  527. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2637 -549
  528. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
  529. package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
  530. package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
  531. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
  532. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  533. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
  534. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  535. package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
  536. package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
  537. package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
  538. package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
  539. package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
  540. package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
  541. package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  542. package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  543. package/packages/shared-skills/skills/debugging/SKILL.md +2 -0
  544. package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
  545. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
  546. package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
  547. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
  548. package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
  549. package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
  550. package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
  551. package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
  552. package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
  553. package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  554. package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
  555. package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
  556. package/packages/shared-skills/skills/frontend/SKILL.md +11 -7
  557. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
  558. package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
  559. package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
  560. package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
  561. package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  562. package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  563. package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  564. package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
  565. package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
  566. package/packages/shared-skills/skills/review-work/SKILL.md +3 -3
  567. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  568. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -0
  569. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  570. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
  571. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  572. package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +9 -8
  573. package/packages/shared-skills/skills/ulw-plan/SKILL.md +6 -6
  574. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
  575. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
  576. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
  577. package/packages/shared-skills/skills/ulw-research/SKILL.md +4 -2
  578. package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
  579. package/packages/shared-skills/skills/visual-qa/SKILL.md +3 -2
  580. package/script/qa/web-terminal-visual-qa.mjs +2 -0
  581. package/script/qa/xterm-live-terminal.mjs +18 -2
  582. package/dist/config/schema/start-work.d.ts +0 -5
  583. package/dist/features/builtin-commands/templates/start-work.d.ts +0 -1
  584. package/dist/hooks/ralph-loop/completion-promise-detector-test-input.d.ts +0 -11
  585. package/dist/hooks/ralph-loop/loop-session-recovery.d.ts +0 -7
  586. package/dist/hooks/start-work/start-work-hook.d.ts +0 -23
  587. package/dist/plugin/chat-message/start-work-message.d.ts +0 -5
  588. package/dist/skills/data-scientist/references/common-scenarios.md +0 -176
  589. package/dist/skills/data-scientist/references/execution-templates.md +0 -197
  590. package/dist/skills/data-scientist/references/integration-patterns.md +0 -153
  591. package/dist/skills/data-scientist/references/performance-benchmarks.md +0 -37
  592. package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
  593. package/dist/tools/call-omo-agent/message-storage-directory.d.ts +0 -1
  594. package/dist/tools/delegate-task/model-string-parser.d.ts +0 -1
  595. package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts +0 -1
  596. package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts +0 -1
  597. package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts +0 -1
  598. package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.d.ts +0 -1
  599. package/packages/lsp-tools-mcp/dist/missing-dependency-result.d.ts +0 -1
  600. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
  601. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
  602. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
  603. package/packages/omo-codex/plugin/skills/data-scientist/references/common-scenarios.md +0 -176
  604. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-templates.md +0 -197
  605. package/packages/omo-codex/plugin/skills/data-scientist/references/integration-patterns.md +0 -153
  606. package/packages/omo-codex/plugin/skills/data-scientist/references/performance-benchmarks.md +0 -37
  607. package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
  608. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
  609. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
  610. package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
  611. package/packages/shared-skills/skills/data-scientist/references/common-scenarios.md +0 -176
  612. package/packages/shared-skills/skills/data-scientist/references/execution-templates.md +0 -197
  613. package/packages/shared-skills/skills/data-scientist/references/integration-patterns.md +0 -153
  614. package/packages/shared-skills/skills/data-scientist/references/performance-benchmarks.md +0 -37
  615. /package/dist/hooks/{start-work → ulw-execute}/context-info-formatters.d.ts +0 -0
  616. /package/dist/hooks/{start-work → ulw-execute}/explicit-plan-context.d.ts +0 -0
  617. /package/dist/hooks/{start-work → ulw-execute}/notepad-scaffold.d.ts +0 -0
  618. /package/dist/hooks/{start-work → ulw-execute}/parse-user-request.d.ts +0 -0
  619. /package/dist/hooks/{start-work → ulw-execute}/plan-discovery-context.d.ts +0 -0
  620. /package/dist/hooks/{start-work → ulw-execute}/plan-selection.d.ts +0 -0
  621. /package/dist/hooks/{start-work → ulw-execute}/session-plan-affinity.d.ts +0 -0
  622. /package/dist/hooks/{start-work → ulw-execute}/work-initializer.d.ts +0 -0
  623. /package/dist/hooks/{start-work → ulw-execute}/worktree-block.d.ts +0 -0
  624. /package/dist/hooks/{start-work → ulw-execute}/worktree-detector.d.ts +0 -0
  625. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/.gitattributes +0 -0
  626. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/CHANGELOG.md +0 -0
  627. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/LICENSE +0 -0
  628. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/plan-checklist.ts +0 -0
  629. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/types.ts +0 -0
  630. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
  631. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
  632. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
  633. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
  634. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
  635. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
  636. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
  637. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
  638. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
  639. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
@@ -4,8 +4,8 @@
4
4
  import { argv, stderr } from "node:process";
5
5
 
6
6
  // src/proxy.ts
7
- import { existsSync as existsSync12, realpathSync as realpathSync4 } from "node:fs";
8
- import { basename as basename3, delimiter as delimiter4, dirname as dirname9, isAbsolute as isAbsolute5 } from "node:path";
7
+ import { existsSync as existsSync13, realpathSync as realpathSync6 } from "node:fs";
8
+ import { basename as basename4, delimiter as delimiter4, dirname as dirname11, isAbsolute as isAbsolute6 } from "node:path";
9
9
 
10
10
  // ../mcp-stdio-core/src/record.ts
11
11
  function isPlainRecord(value) {
@@ -184,6 +184,7 @@ async function runJsonRpcStdioServer(config) {
184
184
  const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
185
185
  isClosed = true;
186
186
  config.onIdleTimeout?.();
187
+ config.input.destroy();
187
188
  });
188
189
  const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
189
190
  isClosed = true;
@@ -280,7 +281,11 @@ function createParentWatchdog(config, onDeadParent) {
280
281
  const probeAlive = config.probeAlive ?? isProcessAlive;
281
282
  let fired = false;
282
283
  const timer = setInterval(() => {
283
- if (fired || probeAlive(parentPid))
284
+ if (fired)
285
+ return;
286
+ const alive = probeAlive(parentPid);
287
+ config.onPoll?.(alive);
288
+ if (alive)
284
289
  return;
285
290
  fired = true;
286
291
  onDeadParent(parentPid, pollIntervalMs);
@@ -315,8 +320,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
315
320
  };
316
321
  }
317
322
  // ../lsp-core/src/lsp/client-wrapper.ts
318
- import { existsSync as existsSync9, statSync as statSync3 } from "node:fs";
319
- import { dirname as dirname6, join as join4, resolve as resolve7 } from "node:path";
323
+ import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
324
+ import { basename as basename3, dirname as dirname8, join as join5, resolve as resolve8 } from "node:path";
320
325
 
321
326
  // ../lsp-core/src/request-context.ts
322
327
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -325,18 +330,17 @@ import { homedir } from "node:os";
325
330
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
326
331
 
327
332
  class LspRequestContextParseError extends Error {
328
- code;
329
- name = "LspRequestContextParseError";
330
333
  constructor(code, message) {
331
334
  super(message);
332
335
  this.code = code;
336
+ this.name = "LspRequestContextParseError";
333
337
  }
334
338
  }
335
339
 
336
340
  class LspRequestContextUnavailableError extends Error {
337
- name = "LspRequestContextUnavailableError";
338
341
  constructor() {
339
342
  super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
343
+ this.name = "LspRequestContextUnavailableError";
340
344
  }
341
345
  }
342
346
  var storage = new AsyncLocalStorage;
@@ -356,7 +360,7 @@ function contextCwd() {
356
360
  }
357
361
  function createStandaloneMcpRequestContext(input = {}) {
358
362
  const env = input.env ?? process.env;
359
- const cwd = canonicalCwd(input.cwd ?? process.cwd());
363
+ const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
360
364
  const home = input.homeDir ?? homedir();
361
365
  const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
362
366
  const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
@@ -499,22 +503,15 @@ function effectiveExtension(filePath) {
499
503
 
500
504
  // ../lsp-core/src/lsp/errors.ts
501
505
  class LspConnectionClosedError extends Error {
502
- serverId;
503
- root;
504
- name = "LspConnectionClosedError";
505
506
  constructor(serverId, root, message) {
506
507
  super(message ?? `LSP connection closed for ${serverId} at ${root}`);
507
508
  this.serverId = serverId;
508
509
  this.root = root;
510
+ this.name = "LspConnectionClosedError";
509
511
  }
510
512
  }
511
513
 
512
514
  class LspProcessExitedError extends Error {
513
- serverId;
514
- root;
515
- exitCode;
516
- stderrTail;
517
- name = "LspProcessExitedError";
518
515
  constructor(serverId, root, exitCode, stderrTail) {
519
516
  const stderrSuffix = stderrTail ? `
520
517
  stderr tail: ${stderrTail}` : "";
@@ -523,46 +520,59 @@ stderr tail: ${stderrTail}` : "";
523
520
  this.root = root;
524
521
  this.exitCode = exitCode;
525
522
  this.stderrTail = stderrTail;
523
+ this.name = "LspProcessExitedError";
526
524
  }
527
525
  }
528
526
 
529
527
  class LspRequestTimeoutError extends Error {
530
- method;
531
- stderrTail;
532
- name = "LspRequestTimeoutError";
533
528
  constructor(method, stderrTail) {
534
529
  const stderrSuffix = stderrTail ? `
535
530
  recent stderr: ${stderrTail}` : "";
536
531
  super(`LSP request timeout (method: ${method})${stderrSuffix}`);
537
532
  this.method = method;
538
533
  this.stderrTail = stderrTail;
534
+ this.name = "LspRequestTimeoutError";
539
535
  }
540
536
  }
541
537
 
542
538
  class LspInvalidPathError extends Error {
543
- name = "LspInvalidPathError";
539
+ constructor() {
540
+ super(...arguments);
541
+ this.name = "LspInvalidPathError";
542
+ }
544
543
  }
545
544
 
546
545
  class LspServerLookupError extends Error {
547
- lookup;
548
- name = "LspServerLookupError";
549
546
  constructor(message, lookup) {
550
547
  super(message);
551
548
  this.lookup = lookup;
549
+ this.name = "LspServerLookupError";
552
550
  }
553
551
  }
554
552
 
555
553
  class LspServerInitializingError extends Error {
556
- originalError;
557
- name = "LspServerInitializingError";
558
554
  constructor(originalError) {
559
555
  super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
560
556
  this.originalError = originalError;
557
+ this.name = "LspServerInitializingError";
561
558
  }
562
559
  }
563
560
 
564
561
  class LspProcessSpawnError extends Error {
565
- name = "LspProcessSpawnError";
562
+ constructor() {
563
+ super(...arguments);
564
+ this.name = "LspProcessSpawnError";
565
+ }
566
+ }
567
+
568
+ class LspClientRespawnBudgetExceededError extends Error {
569
+ constructor(serverId, root, retryLimit) {
570
+ super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
571
+ this.serverId = serverId;
572
+ this.root = root;
573
+ this.retryLimit = retryLimit;
574
+ this.name = "LspClientRespawnBudgetExceededError";
575
+ }
566
576
  }
567
577
  function isLspDeadConnectionError(err) {
568
578
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
@@ -593,9 +603,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
593
603
  var REQUEST_TIMEOUT_MS = 15000;
594
604
  var INIT_TIMEOUT_MS = 60000;
595
605
  var IDLE_TIMEOUT_MS = 5 * 60000;
606
+ var MAX_RESIDENT_CLIENTS = 6;
596
607
  var REAPER_INTERVAL_MS = 60000;
597
608
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
598
609
  var STOP_SIGKILL_GRACE_MS = 1000;
610
+ var CLIENT_RESPAWN_RETRY_LIMIT = 2;
611
+ var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
599
612
 
600
613
  // ../lsp-core/src/lsp/json-rpc-connection.ts
601
614
  var HEADER_SEPARATOR2 = `\r
@@ -607,20 +620,31 @@ var METHOD_NOT_FOUND = -32601;
607
620
  var INTERNAL_ERROR = -32603;
608
621
 
609
622
  class JsonRpcConnection {
610
- reader;
611
- writer;
612
- pendingRequests = new Map;
613
- notificationHandlers = new Map;
614
- requestHandlers = new Map;
615
- closeHandlers = [];
616
- errorHandlers = [];
617
- inputBuffer = Buffer.alloc(0);
618
- nextRequestId = 1;
619
- listening = false;
620
- disposed = false;
621
623
  constructor(reader, writer) {
622
624
  this.reader = reader;
623
625
  this.writer = writer;
626
+ this.pendingRequests = new Map;
627
+ this.notificationHandlers = new Map;
628
+ this.requestHandlers = new Map;
629
+ this.closeHandlers = [];
630
+ this.errorHandlers = [];
631
+ this.inputBuffer = Buffer.alloc(0);
632
+ this.nextRequestId = 1;
633
+ this.listening = false;
634
+ this.disposed = false;
635
+ this.handleData = (chunk) => {
636
+ const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
637
+ this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
638
+ this.drainInputBuffer();
639
+ };
640
+ this.handleClose = () => {
641
+ for (const handler of this.closeHandlers) {
642
+ handler();
643
+ }
644
+ };
645
+ this.handleStreamError = (error) => {
646
+ this.emitError(error);
647
+ };
624
648
  }
625
649
  listen() {
626
650
  if (this.listening)
@@ -741,19 +765,6 @@ class JsonRpcConnection {
741
765
  this.notificationHandlers.clear();
742
766
  this.requestHandlers.clear();
743
767
  }
744
- handleData = (chunk) => {
745
- const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
746
- this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
747
- this.drainInputBuffer();
748
- };
749
- handleClose = () => {
750
- for (const handler of this.closeHandlers) {
751
- handler();
752
- }
753
- };
754
- handleStreamError = (error) => {
755
- this.emitError(error);
756
- };
757
768
  drainInputBuffer() {
758
769
  while (true) {
759
770
  const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
@@ -1101,31 +1112,26 @@ function isPosition(value) {
1101
1112
 
1102
1113
  // ../lsp-core/src/lsp/transport.ts
1103
1114
  class LspClientNotStartedError extends Error {
1104
- serverId;
1105
- root;
1106
- name = "LspClientNotStartedError";
1107
1115
  constructor(serverId, root) {
1108
1116
  super("LSP client not started");
1109
1117
  this.serverId = serverId;
1110
1118
  this.root = root;
1119
+ this.name = "LspClientNotStartedError";
1111
1120
  }
1112
1121
  }
1113
1122
 
1114
1123
  class LspClientTransport {
1115
- root;
1116
- server;
1117
- proc = null;
1118
- connection = null;
1119
- stderrBuffer = [];
1120
- processExited = false;
1121
- diagnosticsStore = new Map;
1122
- requestTimeoutMs;
1123
- initializeTimeoutMs;
1124
- workspaceApplyEditHandler = null;
1125
- diagnosticPullSupported = false;
1126
1124
  constructor(root, server2, timeouts = {}) {
1127
1125
  this.root = root;
1128
1126
  this.server = server2;
1127
+ this.proc = null;
1128
+ this.connection = null;
1129
+ this.stderrBuffer = [];
1130
+ this.processExited = false;
1131
+ this.diagnosticsStore = new Map;
1132
+ this.workspaceApplyEditHandler = null;
1133
+ this.diagnosticPullSupported = false;
1134
+ this.documentFormattingSupported = false;
1129
1135
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
1130
1136
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
1131
1137
  }
@@ -1147,6 +1153,12 @@ class LspClientTransport {
1147
1153
  isDiagnosticPullSupported() {
1148
1154
  return this.diagnosticPullSupported;
1149
1155
  }
1156
+ setDocumentFormattingSupported(supported) {
1157
+ this.documentFormattingSupported = supported;
1158
+ }
1159
+ isDocumentFormattingSupported() {
1160
+ return this.documentFormattingSupported;
1161
+ }
1150
1162
  handlePublishDiagnostics(params) {
1151
1163
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
1152
1164
  }
@@ -1360,6 +1372,14 @@ function supportsDiagnosticPull(capabilities) {
1360
1372
  return false;
1361
1373
  return Object.hasOwn(capabilities, "diagnosticProvider");
1362
1374
  }
1375
+ function supportsDocumentFormatting(capabilities) {
1376
+ if (capabilities === undefined)
1377
+ return false;
1378
+ const provider = capabilities.documentFormattingProvider;
1379
+ if (provider === undefined || provider === null || provider === false)
1380
+ return false;
1381
+ return provider === true || typeof provider === "object";
1382
+ }
1363
1383
 
1364
1384
  class LspClientConnection extends LspClientTransport {
1365
1385
  async initialize() {
@@ -1376,6 +1396,7 @@ class LspClientConnection extends LspClientTransport {
1376
1396
  references: {},
1377
1397
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
1378
1398
  publishDiagnostics: {},
1399
+ formatting: { dynamicRegistration: false },
1379
1400
  rename: {
1380
1401
  prepareSupport: true,
1381
1402
  prepareSupportDefaultBehavior: 1
@@ -1417,6 +1438,7 @@ class LspClientConnection extends LspClientTransport {
1417
1438
  initializationOptions: this.server.initialization
1418
1439
  }, { timeoutMs: this.initializeTimeoutMs });
1419
1440
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
1441
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
1420
1442
  await this.sendNotification("initialized", {});
1421
1443
  await this.sendNotification("workspace/didChangeConfiguration", {
1422
1444
  settings: { json: { validate: { enable: true } } }
@@ -1622,16 +1644,12 @@ function movedPath(candidate, oldPath, newPath) {
1622
1644
  }
1623
1645
 
1624
1646
  class WorkspaceDocumentState {
1625
- sendNotification;
1626
- clearDiagnostics;
1627
- openDocuments = new Map;
1628
- openByUri = new Map;
1629
- openPromises = new Map;
1630
- now;
1631
- versionlessPublishQuiescenceMs;
1632
1647
  constructor(sendNotification, clearDiagnostics, options = {}) {
1633
1648
  this.sendNotification = sendNotification;
1634
1649
  this.clearDiagnostics = clearDiagnostics;
1650
+ this.openDocuments = new Map;
1651
+ this.openByUri = new Map;
1652
+ this.openPromises = new Map;
1635
1653
  this.now = options.now ?? (() => Date.now());
1636
1654
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1637
1655
  }
@@ -1895,13 +1913,11 @@ import { dirname as dirname2, isAbsolute as isAbsolute2, relative as relative3,
1895
1913
  import { fileURLToPath } from "node:url";
1896
1914
 
1897
1915
  class WorkspaceEditPathError extends Error {
1898
- path;
1899
- detail;
1900
- name = "WorkspaceEditPathError";
1901
1916
  constructor(path, detail) {
1902
1917
  super(`${detail}: ${path}`);
1903
1918
  this.path = path;
1904
1919
  this.detail = detail;
1920
+ this.name = "WorkspaceEditPathError";
1905
1921
  }
1906
1922
  }
1907
1923
  function isPathInsideWorkspace(filePath, workspaceRoot) {
@@ -2193,13 +2209,11 @@ function canonicalFingerprint(operations) {
2193
2209
 
2194
2210
  // ../lsp-core/src/lsp/workspace-edit-types.ts
2195
2211
  class WorkspaceEditValidationError extends Error {
2196
- changeIndex;
2197
- detail;
2198
- name = "WorkspaceEditValidationError";
2199
2212
  constructor(changeIndex, detail) {
2200
2213
  super(`change ${changeIndex}: ${detail}`);
2201
2214
  this.changeIndex = changeIndex;
2202
2215
  this.detail = detail;
2216
+ this.name = "WorkspaceEditValidationError";
2203
2217
  }
2204
2218
  }
2205
2219
 
@@ -2697,10 +2711,9 @@ function simulateDelete(operation, virtual) {
2697
2711
  import { existsSync as existsSync5, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
2698
2712
  import { dirname as dirname4, resolve as resolve5 } from "node:path";
2699
2713
  class WorkspaceSnapshotBuilder {
2700
- workspaceRoot;
2701
- snapshots = new Map;
2702
2714
  constructor(workspaceRoot) {
2703
2715
  this.workspaceRoot = workspaceRoot;
2716
+ this.snapshots = new Map;
2704
2717
  }
2705
2718
  build(operations) {
2706
2719
  this.add(this.workspaceRoot, false);
@@ -2744,8 +2757,10 @@ function snapshotOperations(operations, workspaceRoot) {
2744
2757
 
2745
2758
  // ../lsp-core/src/lsp/workspace-edit-plan.ts
2746
2759
  class PlanPathIndex {
2747
- firstChangeByPath = new Map;
2748
- reportedPathByCanonical = new Map;
2760
+ constructor() {
2761
+ this.firstChangeByPath = new Map;
2762
+ this.reportedPathByCanonical = new Map;
2763
+ }
2749
2764
  build(operations) {
2750
2765
  for (const operation of operations) {
2751
2766
  switch (operation.kind) {
@@ -2834,14 +2849,11 @@ function isRecord4(value) {
2834
2849
  }
2835
2850
 
2836
2851
  class WorkspaceMutationController {
2837
- workspaceRoot;
2838
- documents;
2839
- activeLease = null;
2840
- nextLeaseId = 1;
2841
- io;
2842
2852
  constructor(workspaceRoot, documents) {
2843
2853
  this.workspaceRoot = workspaceRoot;
2844
2854
  this.documents = documents;
2855
+ this.activeLease = null;
2856
+ this.nextLeaseId = 1;
2845
2857
  }
2846
2858
  setIo(io) {
2847
2859
  this.io = io;
@@ -2954,12 +2966,9 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
2954
2966
  var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
2955
2967
 
2956
2968
  class LspClient extends LspClientConnection {
2957
- diagnosticPullErrors = [];
2958
- documents;
2959
- workspaceMutations;
2960
- diagnosticsFreshnessTimeoutMs;
2961
2969
  constructor(root, server2, options = {}) {
2962
2970
  super(root, server2, options);
2971
+ this.diagnosticPullErrors = [];
2963
2972
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2964
2973
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2965
2974
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
@@ -3014,6 +3023,18 @@ class LspClient extends LspClientConnection {
3014
3023
  textDocument: { uri: pathToFileURL3(absPath).href }
3015
3024
  }, options);
3016
3025
  }
3026
+ async formatDocument(filePath, options, signal) {
3027
+ if (!this.isDocumentFormattingSupported())
3028
+ return null;
3029
+ const absPath = this.resolveWorkspacePath(filePath);
3030
+ await this.openFile(absPath);
3031
+ const requestOptions = signal === undefined ? {} : { signal };
3032
+ const edits = await this.sendRequest("textDocument/formatting", {
3033
+ textDocument: { uri: pathToFileURL3(absPath).href },
3034
+ options
3035
+ }, requestOptions);
3036
+ return edits ?? [];
3037
+ }
3017
3038
  async workspaceSymbols(query, signal) {
3018
3039
  const options = signal === undefined ? {} : { signal };
3019
3040
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -3259,18 +3280,16 @@ function awaitWithSignal(promise, signal) {
3259
3280
  }
3260
3281
 
3261
3282
  class LspManager {
3262
- clients = new Map;
3263
- reaperHandle = null;
3264
- signalDisposer = null;
3265
- disposed = false;
3266
- idleTimeoutMs;
3267
- initTimeoutMs;
3268
- reaperIntervalMs;
3269
- clientFactory;
3270
- now;
3271
3283
  constructor(options = {}) {
3284
+ this.clients = new Map;
3285
+ this.pendingStops = new Map;
3286
+ this.respawnBudgets = new Map;
3287
+ this.reaperHandle = null;
3288
+ this.signalDisposer = null;
3289
+ this.disposed = false;
3272
3290
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
3273
3291
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
3292
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
3274
3293
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
3275
3294
  this.clientFactory = options.clientFactory ?? ((root, server2) => new LspClient(root, server2));
3276
3295
  this.now = options.now ?? (() => Date.now());
@@ -3290,24 +3309,79 @@ class LspManager {
3290
3309
  getKey(root, serverId) {
3291
3310
  return `${root}::${serverId}`;
3292
3311
  }
3312
+ tombstoneStop(key, client) {
3313
+ const stop = stopClientBestEffort(client);
3314
+ this.pendingStops.set(key, stop);
3315
+ stop.finally(() => {
3316
+ if (this.pendingStops.get(key) === stop) {
3317
+ this.pendingStops.delete(key);
3318
+ }
3319
+ });
3320
+ return stop;
3321
+ }
3322
+ recordDeadGeneration(key) {
3323
+ let budget = this.respawnBudgets.get(key);
3324
+ if (budget === undefined) {
3325
+ budget = { deadGenerations: 0, exhaustedAt: null };
3326
+ this.respawnBudgets.set(key, budget);
3327
+ }
3328
+ budget.deadGenerations += 1;
3329
+ }
3330
+ markHealthyGeneration(key) {
3331
+ this.respawnBudgets.delete(key);
3332
+ }
3333
+ ensureRespawnAllowed(key, root, serverId) {
3334
+ const budget = this.respawnBudgets.get(key);
3335
+ if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
3336
+ return;
3337
+ if (budget.exhaustedAt === null) {
3338
+ budget.exhaustedAt = this.now();
3339
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3340
+ }
3341
+ if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
3342
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3343
+ }
3344
+ budget.deadGenerations = 0;
3345
+ budget.exhaustedAt = null;
3346
+ }
3293
3347
  reapStale() {
3294
3348
  const t = this.now();
3295
3349
  for (const [key, managed] of this.clients) {
3296
3350
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3297
- stopClientBestEffort(managed.client);
3298
3351
  this.clients.delete(key);
3352
+ this.tombstoneStop(key, managed.client);
3299
3353
  continue;
3300
3354
  }
3301
3355
  if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
3302
- stopClientBestEffort(managed.client);
3303
3356
  this.clients.delete(key);
3357
+ this.tombstoneStop(key, managed.client);
3304
3358
  }
3305
3359
  }
3306
3360
  }
3361
+ evictForAdmission() {
3362
+ while (this.clients.size >= this.maxResidentClients) {
3363
+ const victim = this.leastRecentlyUsedIdleClient();
3364
+ if (!victim)
3365
+ return;
3366
+ this.clients.delete(victim.key);
3367
+ this.tombstoneStop(victim.key, victim.managed.client);
3368
+ }
3369
+ }
3370
+ leastRecentlyUsedIdleClient() {
3371
+ let candidate = null;
3372
+ for (const [key, managed] of this.clients) {
3373
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
3374
+ continue;
3375
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
3376
+ candidate = { key, managed };
3377
+ }
3378
+ }
3379
+ return candidate;
3380
+ }
3307
3381
  async tryDeleteIfOrphaned(key, managed) {
3308
3382
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
3309
3383
  this.clients.delete(key);
3310
- await stopClientBestEffort(managed.client);
3384
+ await this.tombstoneStop(key, managed.client);
3311
3385
  }
3312
3386
  }
3313
3387
  async getClient(root, server2, signal) {
@@ -3316,12 +3390,22 @@ class LspManager {
3316
3390
  }
3317
3391
  signal?.throwIfAborted();
3318
3392
  const key = this.getKey(root, server2.id);
3393
+ for (;; ) {
3394
+ const pendingStop = this.pendingStops.get(key);
3395
+ if (pendingStop === undefined)
3396
+ break;
3397
+ await awaitWithSignal(pendingStop, signal);
3398
+ signal?.throwIfAborted();
3399
+ }
3400
+ if (this.disposed) {
3401
+ throw new Error("LspManager has been disposed");
3402
+ }
3319
3403
  let managed = this.clients.get(key);
3320
3404
  if (managed) {
3321
3405
  const t = this.now();
3322
3406
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3323
- await stopClientBestEffort(managed.client);
3324
3407
  this.clients.delete(key);
3408
+ await this.tombstoneStop(key, managed.client);
3325
3409
  managed = undefined;
3326
3410
  }
3327
3411
  }
@@ -3342,14 +3426,20 @@ class LspManager {
3342
3426
  signal.throwIfAborted();
3343
3427
  }
3344
3428
  if (!managed.client.isAlive()) {
3345
- await stopClientBestEffort(managed.client);
3346
- this.clients.delete(key);
3429
+ this.recordDeadGeneration(key);
3430
+ if (this.clients.get(key) === managed) {
3431
+ this.clients.delete(key);
3432
+ }
3433
+ await this.tombstoneStop(key, managed.client);
3347
3434
  return this.getClient(root, server2, signal);
3348
3435
  }
3436
+ this.markHealthyGeneration(key);
3349
3437
  managed.refCount++;
3350
3438
  managed.lastUsedAt = this.now();
3351
3439
  return managed.client;
3352
3440
  }
3441
+ this.evictForAdmission();
3442
+ this.ensureRespawnAllowed(key, root, server2.id);
3353
3443
  const client = this.clientFactory(root, server2);
3354
3444
  const initStartedAt = this.now();
3355
3445
  const initPromise = (async () => {
@@ -3373,7 +3463,7 @@ class LspManager {
3373
3463
  if (this.clients.get(key) === newManaged) {
3374
3464
  this.clients.delete(key);
3375
3465
  }
3376
- await stopClientBestEffort(client);
3466
+ await this.tombstoneStop(key, client);
3377
3467
  throw err;
3378
3468
  }
3379
3469
  newManaged.pendingWaiters--;
@@ -3384,6 +3474,15 @@ class LspManager {
3384
3474
  await this.tryDeleteIfOrphaned(key, newManaged);
3385
3475
  signal.throwIfAborted();
3386
3476
  }
3477
+ if (!client.isAlive()) {
3478
+ this.recordDeadGeneration(key);
3479
+ if (this.clients.get(key) === newManaged) {
3480
+ this.clients.delete(key);
3481
+ }
3482
+ await this.tombstoneStop(key, client);
3483
+ return this.getClient(root, server2, signal);
3484
+ }
3485
+ this.markHealthyGeneration(key);
3387
3486
  newManaged.refCount++;
3388
3487
  newManaged.lastUsedAt = this.now();
3389
3488
  return client;
@@ -3404,14 +3503,20 @@ class LspManager {
3404
3503
  if (client && managed.client !== client)
3405
3504
  return;
3406
3505
  this.clients.delete(key);
3407
- stopClientBestEffort(managed.client);
3506
+ this.tombstoneStop(key, managed.client);
3408
3507
  }
3409
3508
  warmupClient(root, server2) {
3410
3509
  if (this.disposed)
3411
3510
  return;
3412
3511
  const key = this.getKey(root, server2.id);
3413
- if (this.clients.has(key))
3512
+ if (this.clients.has(key) || this.pendingStops.has(key))
3513
+ return;
3514
+ this.evictForAdmission();
3515
+ try {
3516
+ this.ensureRespawnAllowed(key, root, server2.id);
3517
+ } catch {
3414
3518
  return;
3519
+ }
3415
3520
  const client = this.clientFactory(root, server2);
3416
3521
  const initStartedAt = this.now();
3417
3522
  const initPromise = (async () => {
@@ -3437,7 +3542,7 @@ class LspManager {
3437
3542
  if (this.clients.get(key) === managed) {
3438
3543
  this.clients.delete(key);
3439
3544
  }
3440
- stopClientBestEffort(client);
3545
+ this.tombstoneStop(key, client);
3441
3546
  });
3442
3547
  }
3443
3548
  isServerInitializing(root, serverId) {
@@ -3481,8 +3586,11 @@ class LspManager {
3481
3586
  for (const managed of this.clients.values()) {
3482
3587
  stopPromises.push(stopClientBestEffort(managed.client));
3483
3588
  }
3589
+ const tombstonedStops = [...this.pendingStops.values()];
3484
3590
  this.clients.clear();
3485
- await Promise.allSettled(stopPromises);
3591
+ this.respawnBudgets.clear();
3592
+ await Promise.allSettled([...stopPromises, ...tombstonedStops]);
3593
+ this.pendingStops.clear();
3486
3594
  }
3487
3595
  }
3488
3596
  var _defaultInstance = null;
@@ -3500,57 +3608,52 @@ async function disposeDefaultLspManager() {
3500
3608
  }
3501
3609
  }
3502
3610
 
3503
- // ../lsp-core/src/lsp/server-install-state.ts
3504
- import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3505
- import { dirname as dirname5 } from "node:path";
3506
- function getInstallDecisionsPath() {
3507
- return lspRequestContext().installDecisionsPath;
3508
- }
3509
- function loadInstallDecisions() {
3510
- const path = getInstallDecisionsPath();
3511
- if (!existsSync6(path))
3512
- return {};
3513
- try {
3514
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
3515
- return isInstallDecisions(parsed) ? parsed : {};
3516
- } catch {
3517
- return {};
3611
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3612
+ import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
3613
+ import { dirname as dirname5, join as join3 } from "node:path";
3614
+
3615
+ // ../lsp-core/src/lsp/workspace-markers.ts
3616
+ var GIT_WORKSPACE_MARKER = ".git";
3617
+ var PROJECT_WORKSPACE_MARKERS = [
3618
+ "package.json",
3619
+ "pyproject.toml",
3620
+ "Cargo.toml",
3621
+ "go.mod",
3622
+ "pom.xml",
3623
+ "build.gradle"
3624
+ ];
3625
+ var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
3626
+
3627
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3628
+ function findWorkspaceRootOutsideContext(directory) {
3629
+ const marked = nearestMarkedAncestor(directory);
3630
+ if (marked !== undefined)
3631
+ return marked;
3632
+ return realpathSync4(nearestExistingAncestor(directory));
3633
+ }
3634
+ function nearestMarkedAncestor(directory) {
3635
+ let current = directory;
3636
+ for (;; ) {
3637
+ if (existsSync6(current) && WORKSPACE_MARKERS.some((marker) => existsSync6(join3(current, marker)))) {
3638
+ return realpathSync4(current);
3639
+ }
3640
+ const parent = dirname5(current);
3641
+ if (parent === current)
3642
+ return;
3643
+ current = parent;
3518
3644
  }
3519
3645
  }
3520
- function loadInstallDecision(serverId) {
3521
- return loadInstallDecisions()[serverId];
3522
- }
3523
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3524
- const decisions = loadInstallDecisions();
3525
- decisions[serverId] = { decision, decidedAt };
3526
- writeInstallDecisions(decisions);
3527
- }
3528
- function isInstallDecision(value) {
3529
- return value === "declined" || value === "allowed";
3530
- }
3531
- function writeInstallDecisions(decisions) {
3532
- const path = getInstallDecisionsPath();
3533
- mkdirSync(dirname5(path), { recursive: true });
3534
- const tmpPath = `${path}.tmp`;
3535
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3536
- `, "utf8");
3537
- renameSync2(tmpPath, path);
3538
- }
3539
- function isInstallDecisions(value) {
3540
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3541
- }
3542
- function isInstallDecisionRecord(value) {
3543
- if (!isRecord5(value))
3544
- return false;
3545
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3546
- }
3547
- function isRecord5(value) {
3548
- return typeof value === "object" && value !== null && !Array.isArray(value);
3646
+ function nearestExistingAncestor(directory) {
3647
+ let current = directory;
3648
+ while (!existsSync6(current)) {
3649
+ const parent = dirname5(current);
3650
+ if (parent === current)
3651
+ return current;
3652
+ current = parent;
3653
+ }
3654
+ return current;
3549
3655
  }
3550
3656
 
3551
- // ../lsp-core/src/lsp/config-loader.ts
3552
- import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
3553
-
3554
3657
  // ../lsp-core/src/lsp/server-definitions.ts
3555
3658
  var LSP_INSTALL_HINTS = {
3556
3659
  typescript: "npm install -g typescript-language-server typescript",
@@ -3596,6 +3699,26 @@ var LSP_INSTALL_HINTS = {
3596
3699
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
3597
3700
  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"
3598
3701
  };
3702
+ var LSP_LOCAL_INSTALL_HINTS = {
3703
+ typescript: "bun add -d typescript-language-server typescript",
3704
+ vue: "bun add -d @vue/language-server",
3705
+ eslint: "bun add -d vscode-langservers-extracted",
3706
+ oxlint: "bun add -d oxlint",
3707
+ biome: "bun add -d @biomejs/biome",
3708
+ svelte: "bun add -d svelte-language-server",
3709
+ astro: "bun add -d @astrojs/language-server",
3710
+ bash: "bun add -d bash-language-server",
3711
+ "bash-ls": "bun add -d bash-language-server",
3712
+ "yaml-ls": "bun add -d yaml-language-server",
3713
+ php: "bun add -d intelephense",
3714
+ prisma: "bun add -d prisma",
3715
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
3716
+ pyright: "uv add --dev pyright",
3717
+ basedpyright: "uv add --dev basedpyright",
3718
+ ruff: "uv add --dev ruff",
3719
+ ty: "uv add --dev ty",
3720
+ "ruby-lsp": "bundle add ruby-lsp --group development"
3721
+ };
3599
3722
  var BUILTIN_SERVERS = {
3600
3723
  typescript: {
3601
3724
  command: ["typescript-language-server", "--stdio"],
@@ -3698,7 +3821,56 @@ var BUILTIN_SERVERS = {
3698
3821
  }
3699
3822
  };
3700
3823
 
3824
+ // ../lsp-core/src/lsp/server-install-state.ts
3825
+ import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3826
+ import { dirname as dirname6 } from "node:path";
3827
+ function getInstallDecisionsPath() {
3828
+ return lspRequestContext().installDecisionsPath;
3829
+ }
3830
+ function loadInstallDecisions() {
3831
+ const path = getInstallDecisionsPath();
3832
+ if (!existsSync7(path))
3833
+ return {};
3834
+ try {
3835
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
3836
+ return isInstallDecisions(parsed) ? parsed : {};
3837
+ } catch {
3838
+ return {};
3839
+ }
3840
+ }
3841
+ function loadInstallDecision(serverId) {
3842
+ return loadInstallDecisions()[serverId];
3843
+ }
3844
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3845
+ const decisions = loadInstallDecisions();
3846
+ decisions[serverId] = { decision, decidedAt };
3847
+ writeInstallDecisions(decisions);
3848
+ }
3849
+ function isInstallDecision(value) {
3850
+ return value === "declined" || value === "allowed";
3851
+ }
3852
+ function writeInstallDecisions(decisions) {
3853
+ const path = getInstallDecisionsPath();
3854
+ mkdirSync(dirname6(path), { recursive: true });
3855
+ const tmpPath = `${path}.tmp`;
3856
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3857
+ `, "utf8");
3858
+ renameSync2(tmpPath, path);
3859
+ }
3860
+ function isInstallDecisions(value) {
3861
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3862
+ }
3863
+ function isInstallDecisionRecord(value) {
3864
+ if (!isRecord5(value))
3865
+ return false;
3866
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3867
+ }
3868
+ function isRecord5(value) {
3869
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3870
+ }
3871
+
3701
3872
  // ../lsp-core/src/lsp/config-loader.ts
3873
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
3702
3874
  function getProjectConfigPaths() {
3703
3875
  return lspRequestContext().projectConfigPaths;
3704
3876
  }
@@ -3706,7 +3878,7 @@ function getUserConfigPath() {
3706
3878
  return lspRequestContext().userConfigPath;
3707
3879
  }
3708
3880
  function loadJsonFile(path) {
3709
- if (!existsSync7(path))
3881
+ if (!existsSync8(path))
3710
3882
  return null;
3711
3883
  try {
3712
3884
  const parsed = JSON.parse(readFileSync4(path, "utf-8"));
@@ -3894,54 +4066,155 @@ function getDisabledServerIds() {
3894
4066
  }
3895
4067
 
3896
4068
  // ../lsp-core/src/lsp/server-installation.ts
3897
- import { existsSync as existsSync8 } from "node:fs";
3898
- import { delimiter as delimiter3, join as join3 } from "node:path";
3899
- function isServerInstalled(command, _workingDirectory) {
3900
- if (command.length === 0)
3901
- return false;
3902
- const [cmd] = command;
3903
- if (!cmd)
3904
- return false;
3905
- if (cmd.includes("/") || cmd.includes("\\")) {
3906
- if (existsSync8(cmd))
3907
- return true;
4069
+ import { existsSync as existsSync9 } from "node:fs";
4070
+ import { delimiter as delimiter3, dirname as dirname7, isAbsolute as isAbsolute3, join as join4, resolve as resolve7 } from "node:path";
4071
+ var LOCAL_BIN_RULES = [
4072
+ {
4073
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
4074
+ binDirs: [join4("node_modules", ".bin")]
4075
+ },
4076
+ {
4077
+ markers: [
4078
+ "pyproject.toml",
4079
+ "ty.toml",
4080
+ "requirements.txt",
4081
+ "setup.py",
4082
+ "setup.cfg",
4083
+ "Pipfile",
4084
+ "pyrightconfig.json",
4085
+ "ruff.toml",
4086
+ ".ruff.toml"
4087
+ ],
4088
+ binDirs: [
4089
+ join4(".venv", "bin"),
4090
+ join4(".venv", "Scripts"),
4091
+ join4("venv", "bin"),
4092
+ join4("venv", "Scripts"),
4093
+ join4(".env", "bin"),
4094
+ join4(".env", "Scripts")
4095
+ ]
4096
+ },
4097
+ {
4098
+ markers: ["Gemfile", "Gemfile.lock"],
4099
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
4100
+ },
4101
+ {
4102
+ markers: ["go.mod", "go.sum", "go.work"],
4103
+ binDirs: ["bin"]
4104
+ }
4105
+ ];
4106
+ var resolutionCache = new Map;
4107
+ var probeCount = 0;
4108
+ function probe(path) {
4109
+ probeCount += 1;
4110
+ return existsSync9(path);
4111
+ }
4112
+ function executableSuffixes(platform, pathExt) {
4113
+ if (platform !== "win32")
4114
+ return [""];
4115
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
4116
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
4117
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4118
+ }
4119
+ function probeWithSuffixes(directory, command, suffixes) {
4120
+ for (const suffix of suffixes) {
4121
+ const candidate = join4(directory, command + suffix);
4122
+ if (probe(candidate))
4123
+ return candidate;
3908
4124
  }
3909
- const isWindows = process.platform === "win32";
3910
- let exts = [""];
3911
- if (isWindows) {
3912
- const pathExt = process.env["PATHEXT"] ?? "";
3913
- if (pathExt) {
3914
- const systemExts = pathExt.split(";").filter(Boolean);
3915
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
3916
- } else {
3917
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
4125
+ return null;
4126
+ }
4127
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
4128
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
4129
+ let current = resolve7(workingDirectory);
4130
+ while (true) {
4131
+ for (const rule of LOCAL_BIN_RULES) {
4132
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
4133
+ continue;
4134
+ for (const binDir of rule.binDirs) {
4135
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
4136
+ if (found !== null)
4137
+ return found;
4138
+ }
3918
4139
  }
4140
+ if (probe(join4(current, ".git")))
4141
+ return null;
4142
+ if (boundary !== undefined && current === boundary)
4143
+ return null;
4144
+ const parent = dirname7(current);
4145
+ if (parent === current)
4146
+ return null;
4147
+ current = parent;
3919
4148
  }
3920
- let pathEnv = process.env["PATH"] ?? "";
3921
- if (isWindows && !pathEnv) {
4149
+ }
4150
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
4151
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
4152
+ if (platform === "win32" && !pathEnv) {
3922
4153
  pathEnv = process.env["Path"] ?? "";
3923
4154
  }
3924
- const paths = pathEnv.split(delimiter3);
3925
- for (const p of paths) {
3926
- for (const suffix of exts) {
3927
- if (existsSync8(join3(p, cmd + suffix))) {
3928
- return true;
3929
- }
3930
- }
4155
+ for (const entry of pathEnv.split(delimiter3)) {
4156
+ if (entry.length === 0)
4157
+ continue;
4158
+ const found = probeWithSuffixes(entry, command, suffixes);
4159
+ if (found !== null)
4160
+ return found;
3931
4161
  }
3932
- if (cmd === "node")
3933
- return true;
3934
- return false;
4162
+ return null;
4163
+ }
4164
+ function resolveServerBinary(command, workingDirectory, options = {}) {
4165
+ if (command.length === 0)
4166
+ return null;
4167
+ const [cmd] = command;
4168
+ if (cmd === undefined || cmd.length === 0)
4169
+ return null;
4170
+ const platform = options.platform ?? process.platform;
4171
+ const suffixes = executableSuffixes(platform, options.pathExt);
4172
+ if (cmd.includes("/") || cmd.includes("\\")) {
4173
+ const explicit = isAbsolute3(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
4174
+ return probe(explicit) ? explicit : null;
4175
+ }
4176
+ const cacheKey = JSON.stringify([
4177
+ workingDirectory ?? "",
4178
+ cmd,
4179
+ platform,
4180
+ options.stopAt ?? "",
4181
+ options.pathExt ?? "",
4182
+ options.pathEnv ?? process.env["PATH"] ?? ""
4183
+ ]);
4184
+ const cached = resolutionCache.get(cacheKey);
4185
+ if (cached !== undefined)
4186
+ return cached;
4187
+ let resolved = null;
4188
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
4189
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
4190
+ }
4191
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
4192
+ if (resolved === null && cmd === "node")
4193
+ resolved = cmd;
4194
+ resolutionCache.set(cacheKey, resolved);
4195
+ return resolved;
4196
+ }
4197
+ function isServerInstalled(command, workingDirectory, options = {}) {
4198
+ if (command.length === 0)
4199
+ return false;
4200
+ return resolveServerBinary(command, workingDirectory, options) !== null;
3935
4201
  }
3936
4202
 
3937
4203
  // ../lsp-core/src/lsp/server-resolution.ts
4204
+ function withResolvedCommand(command, binaryPath) {
4205
+ return [binaryPath, ...command.slice(1)];
4206
+ }
3938
4207
  function findServerForExtension(ext) {
3939
4208
  const servers = getMergedServers();
4209
+ const workingDirectory = contextCwd();
3940
4210
  for (const server2 of servers) {
3941
- if (server2.extensions.includes(ext) && isServerInstalled(server2.command)) {
4211
+ if (!server2.extensions.includes(ext))
4212
+ continue;
4213
+ const binaryPath = resolveServerBinary(server2.command, workingDirectory);
4214
+ if (binaryPath !== null) {
3942
4215
  const resolvedServer = {
3943
4216
  id: server2.id,
3944
- command: server2.command,
4217
+ command: withResolvedCommand(server2.command, binaryPath),
3945
4218
  extensions: server2.extensions,
3946
4219
  priority: server2.priority
3947
4220
  };
@@ -3988,6 +4261,7 @@ function findServerForExtension(ext) {
3988
4261
  function getAllServers() {
3989
4262
  const servers = getMergedServers();
3990
4263
  const disabled = getDisabledServerIds();
4264
+ const workingDirectory = contextCwd();
3991
4265
  const result = [];
3992
4266
  const seen = new Set;
3993
4267
  for (const server2 of servers) {
@@ -3995,7 +4269,7 @@ function getAllServers() {
3995
4269
  continue;
3996
4270
  result.push({
3997
4271
  id: server2.id,
3998
- installed: isServerInstalled(server2.command),
4272
+ installed: isServerInstalled(server2.command, workingDirectory),
3999
4273
  extensions: server2.extensions,
4000
4274
  disabled: false,
4001
4275
  source: server2.source,
@@ -4009,7 +4283,7 @@ function getAllServers() {
4009
4283
  const builtin = BUILTIN_SERVERS[id];
4010
4284
  result.push({
4011
4285
  id,
4012
- installed: builtin ? isServerInstalled(builtin.command) : false,
4286
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
4013
4287
  extensions: builtin?.extensions ?? [],
4014
4288
  disabled: true,
4015
4289
  source: "disabled",
@@ -4020,7 +4294,6 @@ function getAllServers() {
4020
4294
  }
4021
4295
 
4022
4296
  // ../lsp-core/src/lsp/client-wrapper.ts
4023
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
4024
4297
  function isDirectoryPath(filePath) {
4025
4298
  try {
4026
4299
  return statSync3(filePath).isDirectory();
@@ -4029,32 +4302,90 @@ function isDirectoryPath(filePath) {
4029
4302
  }
4030
4303
  }
4031
4304
  function findWorkspaceRoot(filePath) {
4032
- const abs = resolvePathInsideContext(filePath);
4305
+ const cwd = contextCwd();
4306
+ const abs = resolveReadablePathInsideContext(filePath);
4033
4307
  let dir = abs;
4034
4308
  if (!isDirectoryPath(dir)) {
4035
- dir = dirname6(dir);
4036
- }
4037
- let prevDir = "";
4038
- while (dir !== prevDir) {
4039
- for (const marker of WORKSPACE_MARKERS) {
4040
- if (existsSync9(join4(dir, marker))) {
4041
- return dir;
4309
+ dir = dirname8(dir);
4310
+ }
4311
+ if (!isPathInside(cwd, abs))
4312
+ return findWorkspaceRootOutsideContext(dir);
4313
+ const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4314
+ let nearestPackageRoot;
4315
+ while (isPathInside(cwd, dir)) {
4316
+ const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4317
+ if (canonicalDir !== undefined) {
4318
+ if (existsSync10(join5(dir, GIT_WORKSPACE_MARKER))) {
4319
+ return canonicalDir;
4320
+ }
4321
+ if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
4322
+ nearestPackageRoot = canonicalDir;
4042
4323
  }
4043
4324
  }
4044
- prevDir = dir;
4045
- dir = dirname6(dir);
4325
+ if (dir === cwd)
4326
+ break;
4327
+ dir = dirname8(dir);
4046
4328
  }
4047
- return dirname6(abs);
4329
+ return nearestPackageRoot ?? fallbackRoot;
4330
+ }
4331
+ function hasProjectWorkspaceMarker(directory) {
4332
+ return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync10(join5(directory, marker)));
4333
+ }
4334
+ function resolveReadablePathInsideContext(filePath) {
4335
+ const cwd = contextCwd();
4336
+ const abs = resolve8(cwd, filePath);
4337
+ if (isPathInside(cwd, abs))
4338
+ return abs;
4339
+ const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4340
+ if (rebased !== undefined)
4341
+ return rebased;
4342
+ return canonicalizeExistingOrNearestAncestor(abs);
4048
4343
  }
4049
4344
  function resolvePathInsideContext(filePath) {
4050
4345
  const cwd = contextCwd();
4051
- const abs = resolve7(cwd, filePath);
4346
+ const abs = resolveReadablePathInsideContext(filePath);
4052
4347
  const canonical = canonicalizeExistingOrNearestAncestor(abs);
4053
4348
  if (!isPathInside(cwd, canonical)) {
4054
4349
  throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
4055
4350
  }
4056
4351
  return canonical;
4057
4352
  }
4353
+ function rebaseThroughCanonicalAncestor(path, cwd) {
4354
+ let current = path;
4355
+ const suffix = [];
4356
+ while (true) {
4357
+ if (existsSync10(current)) {
4358
+ const canonical = realpathSync5(current);
4359
+ if (isPathInside(cwd, canonical))
4360
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
4361
+ }
4362
+ const parent = dirname8(current);
4363
+ if (parent === current)
4364
+ return;
4365
+ suffix.unshift(basename3(current));
4366
+ current = parent;
4367
+ }
4368
+ }
4369
+ function existingDirectoryInsideContext(directory, cwd) {
4370
+ if (!existsSync10(directory))
4371
+ return;
4372
+ const canonical = realpathSync5(directory);
4373
+ if (!statSync3(canonical).isDirectory())
4374
+ return;
4375
+ return isPathInside(cwd, canonical) ? canonical : undefined;
4376
+ }
4377
+ function nearestExistingDirectoryInsideContext(directory, cwd) {
4378
+ let current = directory;
4379
+ while (isPathInside(cwd, current)) {
4380
+ const canonical = existingDirectoryInsideContext(current, cwd);
4381
+ if (canonical !== undefined)
4382
+ return canonical;
4383
+ if (current === cwd)
4384
+ return;
4385
+ current = dirname8(current);
4386
+ }
4387
+ return;
4388
+ }
4058
4389
  function formatServerLookupError(result) {
4059
4390
  if (result.status === "not_installed") {
4060
4391
  return formatNotInstalled(result);
@@ -4078,6 +4409,19 @@ function formatServerLookupError(result) {
4078
4409
  ].join(`
4079
4410
  `);
4080
4411
  }
4412
+ function formatInstallOptions(serverId, installHint) {
4413
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
4414
+ if (localHint === undefined) {
4415
+ return ["To install, run:", ` ${installHint}`];
4416
+ }
4417
+ return [
4418
+ "To install in THIS repository (preferred — no global install needed):",
4419
+ ` ${localHint}`,
4420
+ "",
4421
+ "Or install it globally:",
4422
+ ` ${installHint}`
4423
+ ];
4424
+ }
4081
4425
  function formatNotInstalled(result) {
4082
4426
  const { server: server2, installHint } = result;
4083
4427
  const extensions = server2.extensions.join(", ");
@@ -4092,19 +4436,19 @@ function formatNotInstalled(result) {
4092
4436
  `Command not found: ${server2.command[0]}`,
4093
4437
  ""
4094
4438
  ];
4439
+ const installOptions = formatInstallOptions(server2.id, installHint);
4095
4440
  if (decision === "allowed") {
4096
4441
  return [
4097
4442
  ...header,
4098
4443
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
4099
- ` ${installHint}`
4444
+ ...installOptions.slice(1)
4100
4445
  ].join(`
4101
4446
  `);
4102
4447
  }
4103
4448
  if (!context.capabilities.installDecisionTool) {
4104
4449
  return [
4105
4450
  ...header,
4106
- "To install, run:",
4107
- ` ${installHint}`,
4451
+ ...installOptions,
4108
4452
  "",
4109
4453
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4110
4454
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -4113,8 +4457,7 @@ function formatNotInstalled(result) {
4113
4457
  }
4114
4458
  return [
4115
4459
  ...header,
4116
- "To install, run:",
4117
- ` ${installHint}`,
4460
+ ...installOptions,
4118
4461
  "",
4119
4462
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4120
4463
  "- If the user agrees: run the install command above, then retry this tool.",
@@ -4125,7 +4468,7 @@ function formatNotInstalled(result) {
4125
4468
  ].join(`
4126
4469
  `);
4127
4470
  }
4128
- var READ_ONLY_RETRY_TOOLS = new Set([
4471
+ var READ_ONLY_TOOLS = new Set([
4129
4472
  "diagnostics",
4130
4473
  "definition",
4131
4474
  "references",
@@ -4134,7 +4477,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
4134
4477
  "prepareRename"
4135
4478
  ]);
4136
4479
  async function withLspClient(filePath, fn, toolName, options = {}) {
4137
- const absPath = resolvePathInsideContext(filePath);
4480
+ const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
4138
4481
  if (isDirectoryPath(absPath)) {
4139
4482
  throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
4140
4483
  }
@@ -4149,9 +4492,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4149
4492
  const acquireAndCall = async (allowRetry) => {
4150
4493
  const client = await manager.getClient(root, server2, options.signal);
4151
4494
  try {
4152
- return await fn(client, root);
4495
+ return await fn(client, root, absPath);
4153
4496
  } catch (err) {
4154
- if (allowRetry && READ_ONLY_RETRY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4497
+ if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4155
4498
  manager.invalidateClient(root, server2.id, client);
4156
4499
  return acquireAndCall(false);
4157
4500
  }
@@ -4169,8 +4512,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4169
4512
  }
4170
4513
 
4171
4514
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4172
- import { existsSync as existsSync10, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4173
- import { join as join5, resolve as resolve8 } from "node:path";
4515
+ import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4516
+ import { join as join6, resolve as resolve9 } from "node:path";
4174
4517
 
4175
4518
  // ../lsp-core/src/lsp/formatters.ts
4176
4519
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -4300,7 +4643,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
4300
4643
  for (const entry of entries) {
4301
4644
  if (files.length >= maxFiles)
4302
4645
  return;
4303
- const fullPath = join5(currentDir, entry);
4646
+ const fullPath = join6(currentDir, entry);
4304
4647
  let stat;
4305
4648
  try {
4306
4649
  stat = lstatSync4(fullPath);
@@ -4325,8 +4668,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4325
4668
  if (!extension.startsWith(".")) {
4326
4669
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4327
4670
  }
4328
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4329
- if (!existsSync10(absDir)) {
4671
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
4672
+ if (!existsSync11(absDir)) {
4330
4673
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4331
4674
  }
4332
4675
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
@@ -4413,7 +4756,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4413
4756
 
4414
4757
  // ../lsp-core/src/lsp/infer-extension.ts
4415
4758
  import { lstatSync as lstatSync5, readdirSync as readdirSync4 } from "node:fs";
4416
- import { join as join6 } from "node:path";
4759
+ import { join as join7 } from "node:path";
4417
4760
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
4418
4761
  var MAX_SCAN_ENTRIES = 500;
4419
4762
  function inferExtensionFromDirectory(directory) {
@@ -4431,7 +4774,7 @@ function inferExtensionFromDirectory(directory) {
4431
4774
  for (const entry of entries) {
4432
4775
  if (scanned >= MAX_SCAN_ENTRIES)
4433
4776
  return;
4434
- const fullPath = join6(dir, entry);
4777
+ const fullPath = join7(dir, entry);
4435
4778
  let stat;
4436
4779
  try {
4437
4780
  stat = lstatSync5(fullPath);
@@ -4606,7 +4949,7 @@ async function executeLspDiagnostics(params, signal) {
4606
4949
  const filePath = requireString(params, "filePath");
4607
4950
  const severity = severityFilter(params);
4608
4951
  try {
4609
- const absPath = resolvePathInsideContext(filePath);
4952
+ const absPath = resolveReadablePathInsideContext(filePath);
4610
4953
  if (isDirectoryPath(absPath)) {
4611
4954
  const extension = inferExtensionFromDirectory(absPath);
4612
4955
  if (!extension) {
@@ -4635,7 +4978,7 @@ async function executeLspDiagnostics(params, signal) {
4635
4978
  };
4636
4979
  return text(output2.output, details2);
4637
4980
  }
4638
- const result = await withLspClient(filePath, async (client) => client.diagnostics(filePath, signal), "diagnostics", clientOptions(signal));
4981
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
4639
4982
  if (result.transientError) {
4640
4983
  const message = result.transientError.message;
4641
4984
  const details2 = {
@@ -4682,6 +5025,96 @@ async function executeLspDiagnostics(params, signal) {
4682
5025
  throw error;
4683
5026
  }
4684
5027
  }
5028
+ // ../lsp-core/src/lsp/format-document.ts
5029
+ import { readFileSync as readFileSync5, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
5030
+ var DEFAULT_FORMATTING_OPTIONS = {
5031
+ tabSize: 4,
5032
+ insertSpaces: false,
5033
+ trimTrailingWhitespace: true,
5034
+ insertFinalNewline: true,
5035
+ trimFinalNewlines: true
5036
+ };
5037
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
5038
+ async function formatDocumentWithClient(client, filePath, options = {}) {
5039
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
5040
+ if (edits === null)
5041
+ return { status: "unavailable", reason: "capability_not_advertised" };
5042
+ if (edits.length === 0)
5043
+ return UNCHANGED;
5044
+ const before = readFileSync5(filePath, "utf-8");
5045
+ const normalized = normalizeTextEdits(before, edits, 0);
5046
+ if (normalized.text === before)
5047
+ return UNCHANGED;
5048
+ writeAtomically(filePath, normalized.text);
5049
+ await client.openFile(filePath);
5050
+ return {
5051
+ status: "formatted",
5052
+ ...lineDelta(normalized.edits)
5053
+ };
5054
+ }
5055
+ function lineDelta(edits) {
5056
+ let linesAdded = 0;
5057
+ let linesRemoved = 0;
5058
+ for (const edit of edits) {
5059
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
5060
+ linesAdded += edit.newText.split(`
5061
+ `).length;
5062
+ }
5063
+ return { linesAdded, linesRemoved };
5064
+ }
5065
+ function writeAtomically(filePath, content) {
5066
+ const tempPath = `${filePath}.omo-format.tmp`;
5067
+ writeFileSync3(tempPath, content, "utf-8");
5068
+ try {
5069
+ renameSync3(tempPath, filePath);
5070
+ } catch (error) {
5071
+ try {
5072
+ unlinkSync(tempPath);
5073
+ } catch {}
5074
+ throw error;
5075
+ }
5076
+ }
5077
+
5078
+ // ../lsp-core/src/tools/format.ts
5079
+ async function executeLspFormat(params, signal) {
5080
+ const filePath = requireString(params, "filePath");
5081
+ try {
5082
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
5083
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
5084
+ } catch (error) {
5085
+ const missingDependency = missingDependencyResult(error, {
5086
+ filePath,
5087
+ status: "unavailable",
5088
+ reason: "server_unavailable",
5089
+ linesAdded: 0,
5090
+ linesRemoved: 0
5091
+ });
5092
+ if (missingDependency)
5093
+ return missingDependency;
5094
+ throw error;
5095
+ }
5096
+ }
5097
+ function formatDetails(filePath, result) {
5098
+ if (result.status === "unavailable") {
5099
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
5100
+ }
5101
+ return {
5102
+ filePath,
5103
+ status: result.status,
5104
+ linesAdded: result.linesAdded,
5105
+ linesRemoved: result.linesRemoved
5106
+ };
5107
+ }
5108
+ function describeResult(filePath, result) {
5109
+ if (result.status === "unavailable") {
5110
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
5111
+ }
5112
+ if (result.status === "unchanged") {
5113
+ return `Already formatted: ${filePath}`;
5114
+ }
5115
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
5116
+ }
5117
+
4685
5118
  // ../lsp-core/src/tools/install-decision.ts
4686
5119
  async function executeLspInstallDecision(params) {
4687
5120
  const serverId = requireString(params, "server_id");
@@ -4710,7 +5143,7 @@ async function executeLspGotoDefinition(params, signal) {
4710
5143
  const line = requireNumber(params, "line");
4711
5144
  const character = requireNumber(params, "character");
4712
5145
  try {
4713
- const result = await withLspClient(filePath, async (client) => client.definition(filePath, line, character, signal), "definition", clientOptions(signal));
5146
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
4714
5147
  const locations = !result ? [] : Array.isArray(result) ? result : [result];
4715
5148
  const details = { filePath, line, character, locations };
4716
5149
  if (locations.length === 0)
@@ -4735,7 +5168,7 @@ async function executeLspFindReferences(params, signal) {
4735
5168
  const character = requireNumber(params, "character");
4736
5169
  const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
4737
5170
  try {
4738
- const result = await withLspClient(filePath, async (client) => client.references(filePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5171
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
4739
5172
  const references = Array.isArray(result) ? result : [];
4740
5173
  const total = references.length;
4741
5174
  const truncated = total > DEFAULT_MAX_REFERENCES;
@@ -4777,7 +5210,7 @@ async function executeLspPrepareRename(params, signal) {
4777
5210
  const line = requireNumber(params, "line");
4778
5211
  const character = requireNumber(params, "character");
4779
5212
  try {
4780
- const result = await withLspClient(filePath, async (client) => client.prepareRename(filePath, line, character, signal), "prepareRename", clientOptions(signal));
5213
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
4781
5214
  const details = { filePath, line, character, result };
4782
5215
  return text(formatPrepareRenameResult(result), details);
4783
5216
  } catch (error) {
@@ -4798,7 +5231,7 @@ async function executeLspRename(params, signal) {
4798
5231
  const character = requireNumber(params, "character");
4799
5232
  const newName = requireString(params, "newName");
4800
5233
  try {
4801
- const result = await withLspClient(filePath, async (client) => client.rename(filePath, line, character, newName, signal), "rename", clientOptions(signal));
5234
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
4802
5235
  const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
4803
5236
  return text(formatApplyResult(result.apply), details, !result.apply.success);
4804
5237
  } catch (error) {
@@ -4878,7 +5311,7 @@ async function executeLspSymbols(params, signal) {
4878
5311
  const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
4879
5312
  return formatSymbolsResult(filePath, scope, symbols2, limit, query);
4880
5313
  }
4881
- const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(filePath, signal), "documentSymbols", clientOptions(signal));
5314
+ const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
4882
5315
  return formatSymbolsResult(filePath, scope, symbols, limit);
4883
5316
  } catch (error) {
4884
5317
  const query = optionalString(params, "query");
@@ -5014,6 +5447,16 @@ var LSP_MCP_TOOLS = [
5014
5447
  }, ["filePath", "line", "character", "newName"]),
5015
5448
  execute: executeLspRename
5016
5449
  },
5450
+ {
5451
+ name: "format",
5452
+ aliases: ["lsp_format"],
5453
+ title: "LSP Format",
5454
+ description: "Format a source file with its language server and write the returned edits to disk.",
5455
+ inputSchema: objectSchema({
5456
+ filePath: { type: "string", description: "Source file path to format." }
5457
+ }, ["filePath"]),
5458
+ execute: executeLspFormat
5459
+ },
5017
5460
  {
5018
5461
  name: "install_decision",
5019
5462
  aliases: ["lsp_install_decision"],
@@ -5113,11 +5556,10 @@ function requestedProtocolVersion(params) {
5113
5556
  // src/daemon-client.ts
5114
5557
  import { connect } from "node:net";
5115
5558
  import { homedir as homedir3 } from "node:os";
5116
- import { join as join7 } from "node:path";
5559
+ import { join as join8 } from "node:path";
5117
5560
 
5118
5561
  // src/daemon-request-error.ts
5119
5562
  class DaemonRequestError extends Error {
5120
- requestWritten;
5121
5563
  constructor(message, requestWritten) {
5122
5564
  super(message);
5123
5565
  this.name = "DaemonRequestError";
@@ -5140,7 +5582,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
5140
5582
  }
5141
5583
 
5142
5584
  class DaemonRequestTimedOutError extends DaemonRequestError {
5143
- timeoutMs;
5144
5585
  constructor(requestWritten, timeoutMs) {
5145
5586
  super("daemon request timed out", requestWritten);
5146
5587
  this.name = "DaemonRequestTimedOutError";
@@ -5192,9 +5633,9 @@ function errorText(error) {
5192
5633
 
5193
5634
  // src/ensure-daemon.ts
5194
5635
  import { spawn as spawn2 } from "node:child_process";
5195
- import { closeSync as closeSync2, existsSync as existsSync11, mkdirSync as mkdirSync3, openSync as openSync2, writeSync as writeSync2 } from "node:fs";
5636
+ import { closeSync as closeSync2, existsSync as existsSync12, mkdirSync as mkdirSync3, openSync as openSync2, writeSync as writeSync2 } from "node:fs";
5196
5637
  import { Socket } from "node:net";
5197
- import { dirname as dirname8, isAbsolute as isAbsolute4 } from "node:path";
5638
+ import { dirname as dirname10, isAbsolute as isAbsolute5 } from "node:path";
5198
5639
  import { argv0, execPath } from "node:process";
5199
5640
 
5200
5641
  // src/ipc-protocol.ts
@@ -5208,25 +5649,23 @@ import {
5208
5649
  lstatSync as lstatSync6,
5209
5650
  mkdirSync as mkdirSync2,
5210
5651
  openSync,
5211
- readFileSync as readFileSync5,
5212
- unlinkSync,
5652
+ readFileSync as readFileSync6,
5653
+ unlinkSync as unlinkSync2,
5213
5654
  writeSync
5214
5655
  } from "node:fs";
5215
- import { dirname as dirname7 } from "node:path";
5656
+ import { dirname as dirname9 } from "node:path";
5216
5657
  var OMO_DAEMON_PROTOCOL_VERSION = 1;
5217
5658
  var AUTH_ERROR_CODE = -32001;
5218
5659
  var PROTOCOL_ERROR_CODE = -32002;
5219
5660
  var AUTH_TOKEN_BYTES = 32;
5220
5661
 
5221
5662
  class UnsafePrivateDirectoryError extends Error {
5222
- path;
5223
- reason;
5224
- name = "UnsafePrivateDirectoryError";
5225
- code = "unsafe_private_directory";
5226
5663
  constructor(path, reason) {
5227
5664
  super(`unsafe private directory ${path}: ${reason}`);
5228
5665
  this.path = path;
5229
5666
  this.reason = reason;
5667
+ this.name = "UnsafePrivateDirectoryError";
5668
+ this.code = "unsafe_private_directory";
5230
5669
  }
5231
5670
  }
5232
5671
  function authEnvelope(token) {
@@ -5234,7 +5673,7 @@ function authEnvelope(token) {
5234
5673
  }
5235
5674
  function readAuthToken(paths) {
5236
5675
  try {
5237
- const token = readFileSync5(paths.auth, "utf8").trim();
5676
+ const token = readFileSync6(paths.auth, "utf8").trim();
5238
5677
  return token.length > 0 ? token : null;
5239
5678
  } catch (error) {
5240
5679
  if (error instanceof Error)
@@ -5250,7 +5689,7 @@ function readOrCreateAuthToken(paths) {
5250
5689
  }
5251
5690
  function rotateAuthToken(paths) {
5252
5691
  try {
5253
- unlinkSync(paths.auth);
5692
+ unlinkSync2(paths.auth);
5254
5693
  } catch (error) {
5255
5694
  if (!(error instanceof Error))
5256
5695
  throw error;
@@ -5322,7 +5761,7 @@ function setPrivateFileMode(path) {
5322
5761
  chmodSync(path, 384);
5323
5762
  }
5324
5763
  function createAuthToken(paths) {
5325
- ensurePrivateDirectory(dirname7(paths.auth));
5764
+ ensurePrivateDirectory(dirname9(paths.auth));
5326
5765
  const token = randomBytes(AUTH_TOKEN_BYTES).toString("base64url");
5327
5766
  let fd;
5328
5767
  try {
@@ -5403,27 +5842,25 @@ import { fileURLToPath as fileURLToPath3 } from "node:url";
5403
5842
 
5404
5843
  // src/runtime-contract.ts
5405
5844
  import { statSync as statSync4 } from "node:fs";
5406
- import { isAbsolute as isAbsolute3 } from "node:path";
5845
+ import { isAbsolute as isAbsolute4 } from "node:path";
5407
5846
  var OMO_LSP_DAEMON_DIR = "OMO_LSP_DAEMON_DIR";
5408
5847
  var OMO_LSP_DAEMON_CLI = "OMO_LSP_DAEMON_CLI";
5409
5848
  var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
5410
5849
  var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
5411
5850
 
5412
5851
  class InvalidRuntimeOverrideError extends Error {
5413
- code = "invalid_runtime_override";
5414
- reason;
5415
5852
  constructor(reason, message) {
5416
5853
  super(message);
5854
+ this.code = "invalid_runtime_override";
5417
5855
  this.name = "InvalidRuntimeOverrideError";
5418
5856
  this.reason = reason;
5419
5857
  }
5420
5858
  }
5421
5859
 
5422
5860
  class InvalidDaemonVersionError extends Error {
5423
- code = "invalid_daemon_version";
5424
- version;
5425
5861
  constructor(version) {
5426
5862
  super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
5863
+ this.code = "invalid_daemon_version";
5427
5864
  this.name = "InvalidDaemonVersionError";
5428
5865
  this.version = version;
5429
5866
  }
@@ -5442,12 +5879,12 @@ function resolveDaemonRuntime(env, defaults) {
5442
5879
  throw new InvalidRuntimeOverrideError("paired_values_required", `${OMO_LSP_DAEMON_CLI} and ${OMO_LSP_DAEMON_VERSION} must be set together`);
5443
5880
  }
5444
5881
  if (!hasCliOverride || !hasVersionOverride) {
5445
- if (!isAbsolute3(defaults.cliPath)) {
5882
+ if (!isAbsolute4(defaults.cliPath)) {
5446
5883
  throw new InvalidRuntimeOverrideError("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
5447
5884
  }
5448
5885
  return { cliPath: defaults.cliPath, version: validateDaemonVersion(defaults.version) };
5449
5886
  }
5450
- if (!isAbsolute3(cliOverride)) {
5887
+ if (!isAbsolute4(cliOverride)) {
5451
5888
  throw new InvalidRuntimeOverrideError("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI} must be an absolute path to an existing regular file`);
5452
5889
  }
5453
5890
  let cliStats;
@@ -5469,10 +5906,9 @@ var requireFromHere = createRequire(import.meta.url);
5469
5906
  var MAX_SOCKET_PATH_LENGTH = 100;
5470
5907
 
5471
5908
  class InvalidDaemonDirectoryError extends Error {
5472
- code = "invalid_daemon_directory";
5473
- directory;
5474
5909
  constructor(directory) {
5475
5910
  super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
5911
+ this.code = "invalid_daemon_directory";
5476
5912
  this.name = "InvalidDaemonDirectoryError";
5477
5913
  this.directory = directory;
5478
5914
  }
@@ -5626,7 +6062,7 @@ async function probeDaemon(paths, timeoutMs = PROBE_TIMEOUT_MS, signal) {
5626
6062
  return await pingDaemon(paths, token, timeoutMs, signal) !== null;
5627
6063
  }
5628
6064
  function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
5629
- return new Promise((resolve9) => {
6065
+ return new Promise((resolve10) => {
5630
6066
  const socket = new Socket;
5631
6067
  let settled = false;
5632
6068
  let timer;
@@ -5638,7 +6074,7 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
5638
6074
  clearTimeout(timer);
5639
6075
  signal?.removeEventListener("abort", onAbort);
5640
6076
  socket.destroy();
5641
- resolve9(value);
6077
+ resolve10(value);
5642
6078
  };
5643
6079
  const onAbort = () => finish(null);
5644
6080
  const decoder = createLineDecoder((message) => {
@@ -5662,12 +6098,13 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
5662
6098
  });
5663
6099
  }
5664
6100
  function spawnDaemonProcess(paths) {
5665
- mkdirSync3(dirname8(paths.log), { recursive: true });
6101
+ mkdirSync3(dirname10(paths.log), { recursive: true });
5666
6102
  const logFd = openSync2(paths.log, "a");
5667
6103
  try {
5668
6104
  const child = spawn2(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
5669
6105
  detached: true,
5670
- stdio: ["ignore", logFd, logFd]
6106
+ stdio: ["ignore", logFd, logFd],
6107
+ windowsHide: true
5671
6108
  });
5672
6109
  child.once("spawn", () => closeSync2(logFd));
5673
6110
  child.once("error", (error) => {
@@ -5681,10 +6118,10 @@ function spawnDaemonProcess(paths) {
5681
6118
  throw error;
5682
6119
  }
5683
6120
  }
5684
- function resolveDaemonNodeExecutable(cachedExecPath = execPath, originalArgv0 = argv0, pathExists = existsSync11) {
6121
+ function resolveDaemonNodeExecutable(cachedExecPath = execPath, originalArgv0 = argv0, pathExists = existsSync12) {
5685
6122
  if (pathExists(cachedExecPath))
5686
6123
  return cachedExecPath;
5687
- if (isAbsolute4(originalArgv0) && pathExists(originalArgv0))
6124
+ if (isAbsolute5(originalArgv0) && pathExists(originalArgv0))
5688
6125
  return originalArgv0;
5689
6126
  return "node";
5690
6127
  }
@@ -5697,7 +6134,7 @@ function defaultEnsureDaemonDeps() {
5697
6134
  };
5698
6135
  }
5699
6136
  function sleepWithSignal(ms, signal) {
5700
- return new Promise((resolve9) => {
6137
+ return new Promise((resolve10) => {
5701
6138
  let settled = false;
5702
6139
  const finish = () => {
5703
6140
  if (settled)
@@ -5705,7 +6142,7 @@ function sleepWithSignal(ms, signal) {
5705
6142
  settled = true;
5706
6143
  clearTimeout(timer);
5707
6144
  signal?.removeEventListener("abort", finish);
5708
- resolve9();
6145
+ resolve10();
5709
6146
  };
5710
6147
  const timer = setTimeout(finish, ms);
5711
6148
  if (signal?.aborted) {
@@ -5720,7 +6157,7 @@ function awaitWithSignal2(promise, signal) {
5720
6157
  return promise;
5721
6158
  if (signal.aborted)
5722
6159
  return Promise.reject(abortError3(signal));
5723
- return new Promise((resolve9, reject) => {
6160
+ return new Promise((resolve10, reject) => {
5724
6161
  let settled = false;
5725
6162
  const finish = (run) => {
5726
6163
  if (settled)
@@ -5731,7 +6168,7 @@ function awaitWithSignal2(promise, signal) {
5731
6168
  };
5732
6169
  const onAbort = () => finish(() => reject(abortError3(signal)));
5733
6170
  signal.addEventListener("abort", onAbort, { once: true });
5734
- promise.then((value) => finish(() => resolve9(value)), (error) => finish(() => reject(error)));
6171
+ promise.then((value) => finish(() => resolve10(value)), (error) => finish(() => reject(error)));
5735
6172
  });
5736
6173
  }
5737
6174
  function throwIfAborted(signal) {
@@ -5780,7 +6217,10 @@ function parsePingResponse(message) {
5780
6217
  var CONTEXT_KEY = "_context";
5781
6218
 
5782
6219
  class InvalidDaemonRequestError extends Error {
5783
- name = "InvalidDaemonRequestError";
6220
+ constructor() {
6221
+ super(...arguments);
6222
+ this.name = "InvalidDaemonRequestError";
6223
+ }
5784
6224
  }
5785
6225
  function extractRequestContext(raw) {
5786
6226
  if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
@@ -5896,14 +6336,17 @@ async function callToolViaDaemon(name, args, options) {
5896
6336
  function callDiagnosticsViaDaemon(filePath, options) {
5897
6337
  return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
5898
6338
  }
6339
+ function callFormatViaDaemon(filePath, options) {
6340
+ return callToolViaDaemon("format", { filePath }, options);
6341
+ }
5899
6342
  function currentRequestContext(env = process.env) {
5900
6343
  const cwd = process.cwd();
5901
6344
  const home = env["HOME"] ?? homedir3();
5902
6345
  return parseLspRequestContext({
5903
6346
  cwd,
5904
- projectConfigPaths: [join7(cwd, ".codex", "lsp-client.json")],
5905
- userConfigPath: join7(home, ".codex", "lsp-client.json"),
5906
- installDecisionsPath: join7(home, ".codex", "lsp-install-decisions.json"),
6347
+ projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
6348
+ userConfigPath: join8(home, ".codex", "lsp-client.json"),
6349
+ installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
5907
6350
  capabilities: { installDecisionTool: true }
5908
6351
  });
5909
6352
  }
@@ -5918,7 +6361,7 @@ function withContext(args, context) {
5918
6361
  function ensureDaemonAvailable(paths, ensure, signal) {
5919
6362
  if (!signal)
5920
6363
  return ensure(paths);
5921
- return new Promise((resolve9, reject) => {
6364
+ return new Promise((resolve10, reject) => {
5922
6365
  let settled = false;
5923
6366
  const finish = (run) => {
5924
6367
  if (settled)
@@ -5933,11 +6376,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
5933
6376
  return;
5934
6377
  }
5935
6378
  signal.addEventListener("abort", onAbort, { once: true });
5936
- Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve9()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
6379
+ Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
5937
6380
  });
5938
6381
  }
5939
6382
  function sendToolCall(paths, token, name, args, options) {
5940
- return new Promise((resolve9, reject) => {
6383
+ return new Promise((resolve10, reject) => {
5941
6384
  const socket = connect(paths.socket);
5942
6385
  const requestId = allocateProxyRequestId();
5943
6386
  let settled = false;
@@ -5990,7 +6433,7 @@ function sendToolCall(paths, token, name, args, options) {
5990
6433
  }
5991
6434
  const result = toToolResult(message, requestId);
5992
6435
  if (result)
5993
- finish(() => resolve9(result));
6436
+ finish(() => resolve10(result));
5994
6437
  else
5995
6438
  finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
5996
6439
  });
@@ -6158,18 +6601,18 @@ function canonicalizePathList(value) {
6158
6601
  return value.split(delimiter4).map((entry) => canonicalizePath(entry) ?? entry).join(delimiter4);
6159
6602
  }
6160
6603
  function canonicalizePath(value) {
6161
- if (value === undefined || !isAbsolute5(value) || !existsSync12(value))
6604
+ if (value === undefined || !isAbsolute6(value) || !existsSync13(value))
6162
6605
  return value;
6163
- return realpathSync4(value);
6606
+ return realpathSync6(value);
6164
6607
  }
6165
6608
  function projectRootFromOpenCodeConfigPath(path2) {
6166
- if (basename3(path2) !== "lsp.json" && basename3(path2) !== "lsp-client.json")
6609
+ if (basename4(path2) !== "lsp.json" && basename4(path2) !== "lsp-client.json")
6167
6610
  return;
6168
- const configDir = dirname9(path2);
6169
- const configDirName = basename3(configDir);
6611
+ const configDir = dirname11(path2);
6612
+ const configDirName = basename4(configDir);
6170
6613
  if (configDirName !== ".opencode" && configDirName !== ".omo")
6171
6614
  return;
6172
- return dirname9(configDir);
6615
+ return dirname11(configDir);
6173
6616
  }
6174
6617
 
6175
6618
  // src/daemon-server.ts
@@ -6178,12 +6621,12 @@ import { createServer as createServer2 } from "node:net";
6178
6621
 
6179
6622
  // src/ownership.ts
6180
6623
  import { randomUUID } from "node:crypto";
6181
- import { existsSync as existsSync13, lstatSync as lstatSync7, readFileSync as readFileSync7, statSync as statSync5, unlinkSync as unlinkSync3 } from "node:fs";
6182
- import { dirname as dirname11 } from "node:path";
6624
+ import { existsSync as existsSync14, lstatSync as lstatSync7, readFileSync as readFileSync8, statSync as statSync5, unlinkSync as unlinkSync4 } from "node:fs";
6625
+ import { dirname as dirname13 } from "node:path";
6183
6626
 
6184
6627
  // src/lock.ts
6185
- import { closeSync as closeSync3, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeSync as writeSync3 } from "node:fs";
6186
- import { dirname as dirname10 } from "node:path";
6628
+ import { closeSync as closeSync3, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeSync as writeSync3 } from "node:fs";
6629
+ import { dirname as dirname12 } from "node:path";
6187
6630
  function isProcessAlive2(pid) {
6188
6631
  if (!Number.isInteger(pid) || pid <= 0)
6189
6632
  return false;
@@ -6198,14 +6641,14 @@ function isProcessAlive2(pid) {
6198
6641
  }
6199
6642
  function readLockPid(lockPath) {
6200
6643
  try {
6201
- const pid = Number.parseInt(readFileSync6(lockPath, "utf8").trim(), 10);
6644
+ const pid = Number.parseInt(readFileSync7(lockPath, "utf8").trim(), 10);
6202
6645
  return Number.isInteger(pid) ? pid : null;
6203
6646
  } catch {
6204
6647
  return null;
6205
6648
  }
6206
6649
  }
6207
6650
  function tryAcquireLock(lockPath, ownerPid = process.pid) {
6208
- mkdirSync4(dirname10(lockPath), { recursive: true });
6651
+ mkdirSync4(dirname12(lockPath), { recursive: true });
6209
6652
  for (let attempt = 0;attempt < 2; attempt += 1) {
6210
6653
  const handle = writeLockFile(lockPath, ownerPid);
6211
6654
  if (handle)
@@ -6237,7 +6680,7 @@ function reapStaleLock(lockPath) {
6237
6680
  }
6238
6681
  function unlinkQuietly(path2) {
6239
6682
  try {
6240
- unlinkSync2(path2);
6683
+ unlinkSync3(path2);
6241
6684
  } catch (error) {
6242
6685
  if (error instanceof Error)
6243
6686
  return;
@@ -6253,17 +6696,19 @@ function errorCode3(error) {
6253
6696
 
6254
6697
  // src/ownership.ts
6255
6698
  class DaemonAlreadyRunningError extends Error {
6256
- name = "DaemonAlreadyRunningError";
6257
- code = "daemon_already_running";
6699
+ constructor() {
6700
+ super(...arguments);
6701
+ this.name = "DaemonAlreadyRunningError";
6702
+ this.code = "daemon_already_running";
6703
+ }
6258
6704
  }
6259
6705
 
6260
6706
  class DaemonStartupDeferredError extends Error {
6261
- reason;
6262
- name = "DaemonStartupDeferredError";
6263
- code = "daemon_startup_deferred";
6264
6707
  constructor(reason) {
6265
6708
  super(`LSP daemon startup deferred: ${reason}`);
6266
6709
  this.reason = reason;
6710
+ this.name = "DaemonStartupDeferredError";
6711
+ this.code = "daemon_startup_deferred";
6267
6712
  }
6268
6713
  }
6269
6714
  async function acquireStartupLease(paths, pingOwner) {
@@ -6286,11 +6731,11 @@ async function acquireStartupLease(paths, pingOwner) {
6286
6731
  function ensureDaemonDirectories(paths) {
6287
6732
  ensurePrivateDirectory(paths.dir);
6288
6733
  if (process.platform !== "win32")
6289
- ensurePrivateDirectory(dirname11(paths.socket));
6734
+ ensurePrivateDirectory(dirname13(paths.socket));
6290
6735
  }
6291
6736
  function readDaemonOwner(paths) {
6292
6737
  try {
6293
- return parseOwner(JSON.parse(readFileSync7(paths.owner, "utf8")));
6738
+ return parseOwner(JSON.parse(readFileSync8(paths.owner, "utf8")));
6294
6739
  } catch (error) {
6295
6740
  if (error instanceof Error)
6296
6741
  return null;
@@ -6366,10 +6811,10 @@ async function validateExistingOwner(paths, pingOwner) {
6366
6811
  throw new DaemonStartupDeferredError("reachable_owner_mismatch");
6367
6812
  }
6368
6813
  function cleanupDeadOwner(paths, owner) {
6369
- if (process.platform !== "win32" && existsSync13(owner.endpoint.path)) {
6814
+ if (process.platform !== "win32" && existsSync14(owner.endpoint.path)) {
6370
6815
  const stat = lstatSync7(owner.endpoint.path);
6371
6816
  if (stat.isSocket())
6372
- unlinkSync3(owner.endpoint.path);
6817
+ unlinkSync4(owner.endpoint.path);
6373
6818
  }
6374
6819
  unlinkQuietly(paths.pid);
6375
6820
  unlinkQuietly(paths.endpoint);
@@ -6417,7 +6862,7 @@ function parseEndpoint(value) {
6417
6862
  // src/version-reap.ts
6418
6863
  import { execFile } from "node:child_process";
6419
6864
  import { readdir, readFile, rm } from "node:fs/promises";
6420
- import { basename as basename4, dirname as dirname12, join as join8 } from "node:path";
6865
+ import { basename as basename5, dirname as dirname14, join as join9 } from "node:path";
6421
6866
  var TERM_GRACE_MS = 5000;
6422
6867
  var KILL_GRACE_MS = 1000;
6423
6868
  var VERSION_ENTRY_PATTERN = /^v([A-Za-z0-9][A-Za-z0-9._+-]{0,127})$/;
@@ -6438,7 +6883,7 @@ async function attestDaemonCliProcess(pid, platform, deps = {}) {
6438
6883
  return isNodeCliDaemonCommand(command.trim());
6439
6884
  }
6440
6885
  async function reapStaleDaemonVersions(ownPaths, deps = {}) {
6441
- const baseDir = dirname12(ownPaths.dir);
6886
+ const baseDir = dirname14(ownPaths.dir);
6442
6887
  const platform = deps.platform ?? process.platform;
6443
6888
  const isAlive = deps.isAlive ?? isProcessAlive2;
6444
6889
  const attest = deps.attest ?? ((pid) => attestDaemonCliProcess(pid, platform));
@@ -6457,7 +6902,7 @@ async function reapStaleDaemonVersions(ownPaths, deps = {}) {
6457
6902
  const version = parseVersionEntry(entry.name);
6458
6903
  if (version === null || !entry.isDirectory())
6459
6904
  continue;
6460
- const versionDir = join8(baseDir, entry.name);
6905
+ const versionDir = join9(baseDir, entry.name);
6461
6906
  const siblingPaths = daemonPaths({ [OMO_LSP_DAEMON_DIR]: baseDir }, { cliPath: ownPaths.cliPath, version });
6462
6907
  results.push(await reapOneVersion({
6463
6908
  version,
@@ -6481,7 +6926,7 @@ async function reapOneVersion(context) {
6481
6926
  const { version, versionDir } = context;
6482
6927
  const owner = context.readOwner(context.siblingPaths);
6483
6928
  if (!owner) {
6484
- const lockPid = readLockPid(join8(versionDir, "daemon.lock"));
6929
+ const lockPid = readLockPid(join9(versionDir, "daemon.lock"));
6485
6930
  if (lockPid !== null && context.isAlive(lockPid)) {
6486
6931
  context.log(`reap: sparing v${version}: owner metadata missing but daemon.lock is held by live pid ${lockPid}`);
6487
6932
  return { version, status: "spared", reason: `owner metadata missing but lock held by live pid ${lockPid}` };
@@ -6547,7 +6992,7 @@ function splitCmdline(buffer) {
6547
6992
  function isNodeCliDaemonArgv(argv) {
6548
6993
  if (argv.length < 2 || !argv.includes("daemon"))
6549
6994
  return false;
6550
- const executable = basename4(argv[0] ?? "");
6995
+ const executable = basename5(argv[0] ?? "");
6551
6996
  if (!/^node(?:\.exe)?$/i.test(executable))
6552
6997
  return false;
6553
6998
  return argv.some((value) => value === "cli.js" || value.endsWith("/cli.js") || value.endsWith("\\cli.js"));
@@ -6559,13 +7004,13 @@ function defaultReadProcFile(path2) {
6559
7004
  return readFile(path2);
6560
7005
  }
6561
7006
  function defaultExecuteForStdout(file, args) {
6562
- return new Promise((resolve9) => {
6563
- execFile(file, [...args], { encoding: "utf8", maxBuffer: 1024 * 1024, timeout: 1000 }, (error, stdout) => {
7007
+ return new Promise((resolve10) => {
7008
+ execFile(file, [...args], { encoding: "utf8", maxBuffer: 1024 * 1024, timeout: 1000, windowsHide: true }, (error, stdout) => {
6564
7009
  if (error !== null) {
6565
- resolve9(null);
7010
+ resolve10(null);
6566
7011
  return;
6567
7012
  }
6568
- resolve9(stdout);
7013
+ resolve10(stdout);
6569
7014
  });
6570
7015
  });
6571
7016
  }
@@ -6584,7 +7029,7 @@ async function defaultWaitForExit(pid, timeoutMs) {
6584
7029
  return true;
6585
7030
  if (Date.now() >= deadline)
6586
7031
  return false;
6587
- await new Promise((resolve9) => setTimeout(resolve9, 100));
7032
+ await new Promise((resolve10) => setTimeout(resolve10, 100));
6588
7033
  }
6589
7034
  }
6590
7035
  function defaultLog(message) {
@@ -6691,17 +7136,17 @@ async function assertSelfProbe(paths, token, owner) {
6691
7136
  throw new DaemonStartupDeferredError("self_probe_failed");
6692
7137
  }
6693
7138
  function listen(server2, socketPath) {
6694
- return new Promise((resolve9, reject) => {
7139
+ return new Promise((resolve10, reject) => {
6695
7140
  const onError = (error) => reject(error);
6696
7141
  server2.once("error", onError);
6697
7142
  server2.listen(socketPath, () => {
6698
7143
  server2.removeListener("error", onError);
6699
- resolve9();
7144
+ resolve10();
6700
7145
  });
6701
7146
  });
6702
7147
  }
6703
7148
  function closeServer(server2) {
6704
- return new Promise((resolve9) => server2.close(() => resolve9()));
7149
+ return new Promise((resolve10) => server2.close(() => resolve10()));
6705
7150
  }
6706
7151
  function installSignalHandlers(close) {
6707
7152
  const handler = () => {