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
@@ -175,6 +175,7 @@ async function runJsonRpcStdioServer(config) {
175
175
  const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
176
176
  isClosed = true;
177
177
  config.onIdleTimeout?.();
178
+ config.input.destroy();
178
179
  });
179
180
  const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
180
181
  isClosed = true;
@@ -271,7 +272,11 @@ function createParentWatchdog(config, onDeadParent) {
271
272
  const probeAlive = config.probeAlive ?? isProcessAlive;
272
273
  let fired = false;
273
274
  const timer = setInterval(() => {
274
- if (fired || probeAlive(parentPid))
275
+ if (fired)
276
+ return;
277
+ const alive = probeAlive(parentPid);
278
+ config.onPoll?.(alive);
279
+ if (alive)
275
280
  return;
276
281
  fired = true;
277
282
  onDeadParent(parentPid, pollIntervalMs);
@@ -306,8 +311,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
306
311
  };
307
312
  }
308
313
  // ../lsp-core/src/lsp/client-wrapper.ts
309
- import { existsSync as existsSync9, statSync as statSync3 } from "node:fs";
310
- import { dirname as dirname6, join as join4, resolve as resolve7 } from "node:path";
314
+ import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
315
+ import { basename as basename3, dirname as dirname8, join as join5, resolve as resolve8 } from "node:path";
311
316
 
312
317
  // ../lsp-core/src/request-context.ts
313
318
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -316,18 +321,17 @@ import { homedir } from "node:os";
316
321
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
317
322
 
318
323
  class LspRequestContextParseError extends Error {
319
- code;
320
- name = "LspRequestContextParseError";
321
324
  constructor(code, message) {
322
325
  super(message);
323
326
  this.code = code;
327
+ this.name = "LspRequestContextParseError";
324
328
  }
325
329
  }
326
330
 
327
331
  class LspRequestContextUnavailableError extends Error {
328
- name = "LspRequestContextUnavailableError";
329
332
  constructor() {
330
333
  super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
334
+ this.name = "LspRequestContextUnavailableError";
331
335
  }
332
336
  }
333
337
  var storage = new AsyncLocalStorage;
@@ -357,7 +361,7 @@ function contextEnv(key) {
357
361
  }
358
362
  function createStandaloneMcpRequestContext(input = {}) {
359
363
  const env = input.env ?? process.env;
360
- const cwd = canonicalCwd(input.cwd ?? process.cwd());
364
+ const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
361
365
  const home = input.homeDir ?? homedir();
362
366
  const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
363
367
  const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
@@ -500,22 +504,15 @@ function effectiveExtension(filePath) {
500
504
 
501
505
  // ../lsp-core/src/lsp/errors.ts
502
506
  class LspConnectionClosedError extends Error {
503
- serverId;
504
- root;
505
- name = "LspConnectionClosedError";
506
507
  constructor(serverId, root, message) {
507
508
  super(message ?? `LSP connection closed for ${serverId} at ${root}`);
508
509
  this.serverId = serverId;
509
510
  this.root = root;
511
+ this.name = "LspConnectionClosedError";
510
512
  }
511
513
  }
512
514
 
513
515
  class LspProcessExitedError extends Error {
514
- serverId;
515
- root;
516
- exitCode;
517
- stderrTail;
518
- name = "LspProcessExitedError";
519
516
  constructor(serverId, root, exitCode, stderrTail) {
520
517
  const stderrSuffix = stderrTail ? `
521
518
  stderr tail: ${stderrTail}` : "";
@@ -524,46 +521,59 @@ stderr tail: ${stderrTail}` : "";
524
521
  this.root = root;
525
522
  this.exitCode = exitCode;
526
523
  this.stderrTail = stderrTail;
524
+ this.name = "LspProcessExitedError";
527
525
  }
528
526
  }
529
527
 
530
528
  class LspRequestTimeoutError extends Error {
531
- method;
532
- stderrTail;
533
- name = "LspRequestTimeoutError";
534
529
  constructor(method, stderrTail) {
535
530
  const stderrSuffix = stderrTail ? `
536
531
  recent stderr: ${stderrTail}` : "";
537
532
  super(`LSP request timeout (method: ${method})${stderrSuffix}`);
538
533
  this.method = method;
539
534
  this.stderrTail = stderrTail;
535
+ this.name = "LspRequestTimeoutError";
540
536
  }
541
537
  }
542
538
 
543
539
  class LspInvalidPathError extends Error {
544
- name = "LspInvalidPathError";
540
+ constructor() {
541
+ super(...arguments);
542
+ this.name = "LspInvalidPathError";
543
+ }
545
544
  }
546
545
 
547
546
  class LspServerLookupError extends Error {
548
- lookup;
549
- name = "LspServerLookupError";
550
547
  constructor(message, lookup) {
551
548
  super(message);
552
549
  this.lookup = lookup;
550
+ this.name = "LspServerLookupError";
553
551
  }
554
552
  }
555
553
 
556
554
  class LspServerInitializingError extends Error {
557
- originalError;
558
- name = "LspServerInitializingError";
559
555
  constructor(originalError) {
560
556
  super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
561
557
  this.originalError = originalError;
558
+ this.name = "LspServerInitializingError";
562
559
  }
563
560
  }
564
561
 
565
562
  class LspProcessSpawnError extends Error {
566
- name = "LspProcessSpawnError";
563
+ constructor() {
564
+ super(...arguments);
565
+ this.name = "LspProcessSpawnError";
566
+ }
567
+ }
568
+
569
+ class LspClientRespawnBudgetExceededError extends Error {
570
+ constructor(serverId, root, retryLimit) {
571
+ super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
572
+ this.serverId = serverId;
573
+ this.root = root;
574
+ this.retryLimit = retryLimit;
575
+ this.name = "LspClientRespawnBudgetExceededError";
576
+ }
567
577
  }
568
578
  function isLspDeadConnectionError(err) {
569
579
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
@@ -594,9 +604,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
594
604
  var REQUEST_TIMEOUT_MS = 15000;
595
605
  var INIT_TIMEOUT_MS = 60000;
596
606
  var IDLE_TIMEOUT_MS = 5 * 60000;
607
+ var MAX_RESIDENT_CLIENTS = 6;
597
608
  var REAPER_INTERVAL_MS = 60000;
598
609
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
599
610
  var STOP_SIGKILL_GRACE_MS = 1000;
611
+ var CLIENT_RESPAWN_RETRY_LIMIT = 2;
612
+ var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
600
613
 
601
614
  // ../lsp-core/src/lsp/json-rpc-connection.ts
602
615
  var HEADER_SEPARATOR2 = `\r
@@ -608,20 +621,31 @@ var METHOD_NOT_FOUND = -32601;
608
621
  var INTERNAL_ERROR = -32603;
609
622
 
610
623
  class JsonRpcConnection {
611
- reader;
612
- writer;
613
- pendingRequests = new Map;
614
- notificationHandlers = new Map;
615
- requestHandlers = new Map;
616
- closeHandlers = [];
617
- errorHandlers = [];
618
- inputBuffer = Buffer.alloc(0);
619
- nextRequestId = 1;
620
- listening = false;
621
- disposed = false;
622
624
  constructor(reader, writer) {
623
625
  this.reader = reader;
624
626
  this.writer = writer;
627
+ this.pendingRequests = new Map;
628
+ this.notificationHandlers = new Map;
629
+ this.requestHandlers = new Map;
630
+ this.closeHandlers = [];
631
+ this.errorHandlers = [];
632
+ this.inputBuffer = Buffer.alloc(0);
633
+ this.nextRequestId = 1;
634
+ this.listening = false;
635
+ this.disposed = false;
636
+ this.handleData = (chunk) => {
637
+ const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
638
+ this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
639
+ this.drainInputBuffer();
640
+ };
641
+ this.handleClose = () => {
642
+ for (const handler of this.closeHandlers) {
643
+ handler();
644
+ }
645
+ };
646
+ this.handleStreamError = (error) => {
647
+ this.emitError(error);
648
+ };
625
649
  }
626
650
  listen() {
627
651
  if (this.listening)
@@ -742,19 +766,6 @@ class JsonRpcConnection {
742
766
  this.notificationHandlers.clear();
743
767
  this.requestHandlers.clear();
744
768
  }
745
- handleData = (chunk) => {
746
- const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
747
- this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
748
- this.drainInputBuffer();
749
- };
750
- handleClose = () => {
751
- for (const handler of this.closeHandlers) {
752
- handler();
753
- }
754
- };
755
- handleStreamError = (error) => {
756
- this.emitError(error);
757
- };
758
769
  drainInputBuffer() {
759
770
  while (true) {
760
771
  const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
@@ -1102,31 +1113,26 @@ function isPosition(value) {
1102
1113
 
1103
1114
  // ../lsp-core/src/lsp/transport.ts
1104
1115
  class LspClientNotStartedError extends Error {
1105
- serverId;
1106
- root;
1107
- name = "LspClientNotStartedError";
1108
1116
  constructor(serverId, root) {
1109
1117
  super("LSP client not started");
1110
1118
  this.serverId = serverId;
1111
1119
  this.root = root;
1120
+ this.name = "LspClientNotStartedError";
1112
1121
  }
1113
1122
  }
1114
1123
 
1115
1124
  class LspClientTransport {
1116
- root;
1117
- server;
1118
- proc = null;
1119
- connection = null;
1120
- stderrBuffer = [];
1121
- processExited = false;
1122
- diagnosticsStore = new Map;
1123
- requestTimeoutMs;
1124
- initializeTimeoutMs;
1125
- workspaceApplyEditHandler = null;
1126
- diagnosticPullSupported = false;
1127
1125
  constructor(root, server2, timeouts = {}) {
1128
1126
  this.root = root;
1129
1127
  this.server = server2;
1128
+ this.proc = null;
1129
+ this.connection = null;
1130
+ this.stderrBuffer = [];
1131
+ this.processExited = false;
1132
+ this.diagnosticsStore = new Map;
1133
+ this.workspaceApplyEditHandler = null;
1134
+ this.diagnosticPullSupported = false;
1135
+ this.documentFormattingSupported = false;
1130
1136
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
1131
1137
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
1132
1138
  }
@@ -1148,6 +1154,12 @@ class LspClientTransport {
1148
1154
  isDiagnosticPullSupported() {
1149
1155
  return this.diagnosticPullSupported;
1150
1156
  }
1157
+ setDocumentFormattingSupported(supported) {
1158
+ this.documentFormattingSupported = supported;
1159
+ }
1160
+ isDocumentFormattingSupported() {
1161
+ return this.documentFormattingSupported;
1162
+ }
1151
1163
  handlePublishDiagnostics(params) {
1152
1164
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
1153
1165
  }
@@ -1361,6 +1373,14 @@ function supportsDiagnosticPull(capabilities) {
1361
1373
  return false;
1362
1374
  return Object.hasOwn(capabilities, "diagnosticProvider");
1363
1375
  }
1376
+ function supportsDocumentFormatting(capabilities) {
1377
+ if (capabilities === undefined)
1378
+ return false;
1379
+ const provider = capabilities.documentFormattingProvider;
1380
+ if (provider === undefined || provider === null || provider === false)
1381
+ return false;
1382
+ return provider === true || typeof provider === "object";
1383
+ }
1364
1384
 
1365
1385
  class LspClientConnection extends LspClientTransport {
1366
1386
  async initialize() {
@@ -1377,6 +1397,7 @@ class LspClientConnection extends LspClientTransport {
1377
1397
  references: {},
1378
1398
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
1379
1399
  publishDiagnostics: {},
1400
+ formatting: { dynamicRegistration: false },
1380
1401
  rename: {
1381
1402
  prepareSupport: true,
1382
1403
  prepareSupportDefaultBehavior: 1
@@ -1418,6 +1439,7 @@ class LspClientConnection extends LspClientTransport {
1418
1439
  initializationOptions: this.server.initialization
1419
1440
  }, { timeoutMs: this.initializeTimeoutMs });
1420
1441
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
1442
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
1421
1443
  await this.sendNotification("initialized", {});
1422
1444
  await this.sendNotification("workspace/didChangeConfiguration", {
1423
1445
  settings: { json: { validate: { enable: true } } }
@@ -1623,16 +1645,12 @@ function movedPath(candidate, oldPath, newPath) {
1623
1645
  }
1624
1646
 
1625
1647
  class WorkspaceDocumentState {
1626
- sendNotification;
1627
- clearDiagnostics;
1628
- openDocuments = new Map;
1629
- openByUri = new Map;
1630
- openPromises = new Map;
1631
- now;
1632
- versionlessPublishQuiescenceMs;
1633
1648
  constructor(sendNotification, clearDiagnostics, options = {}) {
1634
1649
  this.sendNotification = sendNotification;
1635
1650
  this.clearDiagnostics = clearDiagnostics;
1651
+ this.openDocuments = new Map;
1652
+ this.openByUri = new Map;
1653
+ this.openPromises = new Map;
1636
1654
  this.now = options.now ?? (() => Date.now());
1637
1655
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1638
1656
  }
@@ -1896,13 +1914,11 @@ import { dirname as dirname2, isAbsolute as isAbsolute2, relative as relative3,
1896
1914
  import { fileURLToPath } from "node:url";
1897
1915
 
1898
1916
  class WorkspaceEditPathError extends Error {
1899
- path;
1900
- detail;
1901
- name = "WorkspaceEditPathError";
1902
1917
  constructor(path, detail) {
1903
1918
  super(`${detail}: ${path}`);
1904
1919
  this.path = path;
1905
1920
  this.detail = detail;
1921
+ this.name = "WorkspaceEditPathError";
1906
1922
  }
1907
1923
  }
1908
1924
  function isPathInsideWorkspace(filePath, workspaceRoot) {
@@ -2194,13 +2210,11 @@ function canonicalFingerprint(operations) {
2194
2210
 
2195
2211
  // ../lsp-core/src/lsp/workspace-edit-types.ts
2196
2212
  class WorkspaceEditValidationError extends Error {
2197
- changeIndex;
2198
- detail;
2199
- name = "WorkspaceEditValidationError";
2200
2213
  constructor(changeIndex, detail) {
2201
2214
  super(`change ${changeIndex}: ${detail}`);
2202
2215
  this.changeIndex = changeIndex;
2203
2216
  this.detail = detail;
2217
+ this.name = "WorkspaceEditValidationError";
2204
2218
  }
2205
2219
  }
2206
2220
 
@@ -2698,10 +2712,9 @@ function simulateDelete(operation, virtual) {
2698
2712
  import { existsSync as existsSync5, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
2699
2713
  import { dirname as dirname4, resolve as resolve5 } from "node:path";
2700
2714
  class WorkspaceSnapshotBuilder {
2701
- workspaceRoot;
2702
- snapshots = new Map;
2703
2715
  constructor(workspaceRoot) {
2704
2716
  this.workspaceRoot = workspaceRoot;
2717
+ this.snapshots = new Map;
2705
2718
  }
2706
2719
  build(operations) {
2707
2720
  this.add(this.workspaceRoot, false);
@@ -2745,8 +2758,10 @@ function snapshotOperations(operations, workspaceRoot) {
2745
2758
 
2746
2759
  // ../lsp-core/src/lsp/workspace-edit-plan.ts
2747
2760
  class PlanPathIndex {
2748
- firstChangeByPath = new Map;
2749
- reportedPathByCanonical = new Map;
2761
+ constructor() {
2762
+ this.firstChangeByPath = new Map;
2763
+ this.reportedPathByCanonical = new Map;
2764
+ }
2750
2765
  build(operations) {
2751
2766
  for (const operation of operations) {
2752
2767
  switch (operation.kind) {
@@ -2835,14 +2850,11 @@ function isRecord4(value) {
2835
2850
  }
2836
2851
 
2837
2852
  class WorkspaceMutationController {
2838
- workspaceRoot;
2839
- documents;
2840
- activeLease = null;
2841
- nextLeaseId = 1;
2842
- io;
2843
2853
  constructor(workspaceRoot, documents) {
2844
2854
  this.workspaceRoot = workspaceRoot;
2845
2855
  this.documents = documents;
2856
+ this.activeLease = null;
2857
+ this.nextLeaseId = 1;
2846
2858
  }
2847
2859
  setIo(io) {
2848
2860
  this.io = io;
@@ -2955,12 +2967,9 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
2955
2967
  var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
2956
2968
 
2957
2969
  class LspClient extends LspClientConnection {
2958
- diagnosticPullErrors = [];
2959
- documents;
2960
- workspaceMutations;
2961
- diagnosticsFreshnessTimeoutMs;
2962
2970
  constructor(root, server2, options = {}) {
2963
2971
  super(root, server2, options);
2972
+ this.diagnosticPullErrors = [];
2964
2973
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2965
2974
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2966
2975
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
@@ -3015,6 +3024,18 @@ class LspClient extends LspClientConnection {
3015
3024
  textDocument: { uri: pathToFileURL3(absPath).href }
3016
3025
  }, options);
3017
3026
  }
3027
+ async formatDocument(filePath, options, signal) {
3028
+ if (!this.isDocumentFormattingSupported())
3029
+ return null;
3030
+ const absPath = this.resolveWorkspacePath(filePath);
3031
+ await this.openFile(absPath);
3032
+ const requestOptions = signal === undefined ? {} : { signal };
3033
+ const edits = await this.sendRequest("textDocument/formatting", {
3034
+ textDocument: { uri: pathToFileURL3(absPath).href },
3035
+ options
3036
+ }, requestOptions);
3037
+ return edits ?? [];
3038
+ }
3018
3039
  async workspaceSymbols(query, signal) {
3019
3040
  const options = signal === undefined ? {} : { signal };
3020
3041
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -3260,18 +3281,16 @@ function awaitWithSignal(promise, signal) {
3260
3281
  }
3261
3282
 
3262
3283
  class LspManager {
3263
- clients = new Map;
3264
- reaperHandle = null;
3265
- signalDisposer = null;
3266
- disposed = false;
3267
- idleTimeoutMs;
3268
- initTimeoutMs;
3269
- reaperIntervalMs;
3270
- clientFactory;
3271
- now;
3272
3284
  constructor(options = {}) {
3285
+ this.clients = new Map;
3286
+ this.pendingStops = new Map;
3287
+ this.respawnBudgets = new Map;
3288
+ this.reaperHandle = null;
3289
+ this.signalDisposer = null;
3290
+ this.disposed = false;
3273
3291
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
3274
3292
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
3293
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
3275
3294
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
3276
3295
  this.clientFactory = options.clientFactory ?? ((root, server2) => new LspClient(root, server2));
3277
3296
  this.now = options.now ?? (() => Date.now());
@@ -3291,24 +3310,79 @@ class LspManager {
3291
3310
  getKey(root, serverId) {
3292
3311
  return `${root}::${serverId}`;
3293
3312
  }
3313
+ tombstoneStop(key, client) {
3314
+ const stop = stopClientBestEffort(client);
3315
+ this.pendingStops.set(key, stop);
3316
+ stop.finally(() => {
3317
+ if (this.pendingStops.get(key) === stop) {
3318
+ this.pendingStops.delete(key);
3319
+ }
3320
+ });
3321
+ return stop;
3322
+ }
3323
+ recordDeadGeneration(key) {
3324
+ let budget = this.respawnBudgets.get(key);
3325
+ if (budget === undefined) {
3326
+ budget = { deadGenerations: 0, exhaustedAt: null };
3327
+ this.respawnBudgets.set(key, budget);
3328
+ }
3329
+ budget.deadGenerations += 1;
3330
+ }
3331
+ markHealthyGeneration(key) {
3332
+ this.respawnBudgets.delete(key);
3333
+ }
3334
+ ensureRespawnAllowed(key, root, serverId) {
3335
+ const budget = this.respawnBudgets.get(key);
3336
+ if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
3337
+ return;
3338
+ if (budget.exhaustedAt === null) {
3339
+ budget.exhaustedAt = this.now();
3340
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3341
+ }
3342
+ if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
3343
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3344
+ }
3345
+ budget.deadGenerations = 0;
3346
+ budget.exhaustedAt = null;
3347
+ }
3294
3348
  reapStale() {
3295
3349
  const t = this.now();
3296
3350
  for (const [key, managed] of this.clients) {
3297
3351
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3298
- stopClientBestEffort(managed.client);
3299
3352
  this.clients.delete(key);
3353
+ this.tombstoneStop(key, managed.client);
3300
3354
  continue;
3301
3355
  }
3302
3356
  if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
3303
- stopClientBestEffort(managed.client);
3304
3357
  this.clients.delete(key);
3358
+ this.tombstoneStop(key, managed.client);
3359
+ }
3360
+ }
3361
+ }
3362
+ evictForAdmission() {
3363
+ while (this.clients.size >= this.maxResidentClients) {
3364
+ const victim = this.leastRecentlyUsedIdleClient();
3365
+ if (!victim)
3366
+ return;
3367
+ this.clients.delete(victim.key);
3368
+ this.tombstoneStop(victim.key, victim.managed.client);
3369
+ }
3370
+ }
3371
+ leastRecentlyUsedIdleClient() {
3372
+ let candidate = null;
3373
+ for (const [key, managed] of this.clients) {
3374
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
3375
+ continue;
3376
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
3377
+ candidate = { key, managed };
3305
3378
  }
3306
3379
  }
3380
+ return candidate;
3307
3381
  }
3308
3382
  async tryDeleteIfOrphaned(key, managed) {
3309
3383
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
3310
3384
  this.clients.delete(key);
3311
- await stopClientBestEffort(managed.client);
3385
+ await this.tombstoneStop(key, managed.client);
3312
3386
  }
3313
3387
  }
3314
3388
  async getClient(root, server2, signal) {
@@ -3317,12 +3391,22 @@ class LspManager {
3317
3391
  }
3318
3392
  signal?.throwIfAborted();
3319
3393
  const key = this.getKey(root, server2.id);
3394
+ for (;; ) {
3395
+ const pendingStop = this.pendingStops.get(key);
3396
+ if (pendingStop === undefined)
3397
+ break;
3398
+ await awaitWithSignal(pendingStop, signal);
3399
+ signal?.throwIfAborted();
3400
+ }
3401
+ if (this.disposed) {
3402
+ throw new Error("LspManager has been disposed");
3403
+ }
3320
3404
  let managed = this.clients.get(key);
3321
3405
  if (managed) {
3322
3406
  const t = this.now();
3323
3407
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3324
- await stopClientBestEffort(managed.client);
3325
3408
  this.clients.delete(key);
3409
+ await this.tombstoneStop(key, managed.client);
3326
3410
  managed = undefined;
3327
3411
  }
3328
3412
  }
@@ -3343,14 +3427,20 @@ class LspManager {
3343
3427
  signal.throwIfAborted();
3344
3428
  }
3345
3429
  if (!managed.client.isAlive()) {
3346
- await stopClientBestEffort(managed.client);
3347
- this.clients.delete(key);
3430
+ this.recordDeadGeneration(key);
3431
+ if (this.clients.get(key) === managed) {
3432
+ this.clients.delete(key);
3433
+ }
3434
+ await this.tombstoneStop(key, managed.client);
3348
3435
  return this.getClient(root, server2, signal);
3349
3436
  }
3437
+ this.markHealthyGeneration(key);
3350
3438
  managed.refCount++;
3351
3439
  managed.lastUsedAt = this.now();
3352
3440
  return managed.client;
3353
3441
  }
3442
+ this.evictForAdmission();
3443
+ this.ensureRespawnAllowed(key, root, server2.id);
3354
3444
  const client = this.clientFactory(root, server2);
3355
3445
  const initStartedAt = this.now();
3356
3446
  const initPromise = (async () => {
@@ -3374,7 +3464,7 @@ class LspManager {
3374
3464
  if (this.clients.get(key) === newManaged) {
3375
3465
  this.clients.delete(key);
3376
3466
  }
3377
- await stopClientBestEffort(client);
3467
+ await this.tombstoneStop(key, client);
3378
3468
  throw err;
3379
3469
  }
3380
3470
  newManaged.pendingWaiters--;
@@ -3385,6 +3475,15 @@ class LspManager {
3385
3475
  await this.tryDeleteIfOrphaned(key, newManaged);
3386
3476
  signal.throwIfAborted();
3387
3477
  }
3478
+ if (!client.isAlive()) {
3479
+ this.recordDeadGeneration(key);
3480
+ if (this.clients.get(key) === newManaged) {
3481
+ this.clients.delete(key);
3482
+ }
3483
+ await this.tombstoneStop(key, client);
3484
+ return this.getClient(root, server2, signal);
3485
+ }
3486
+ this.markHealthyGeneration(key);
3388
3487
  newManaged.refCount++;
3389
3488
  newManaged.lastUsedAt = this.now();
3390
3489
  return client;
@@ -3405,14 +3504,20 @@ class LspManager {
3405
3504
  if (client && managed.client !== client)
3406
3505
  return;
3407
3506
  this.clients.delete(key);
3408
- stopClientBestEffort(managed.client);
3507
+ this.tombstoneStop(key, managed.client);
3409
3508
  }
3410
3509
  warmupClient(root, server2) {
3411
3510
  if (this.disposed)
3412
3511
  return;
3413
3512
  const key = this.getKey(root, server2.id);
3414
- if (this.clients.has(key))
3513
+ if (this.clients.has(key) || this.pendingStops.has(key))
3514
+ return;
3515
+ this.evictForAdmission();
3516
+ try {
3517
+ this.ensureRespawnAllowed(key, root, server2.id);
3518
+ } catch {
3415
3519
  return;
3520
+ }
3416
3521
  const client = this.clientFactory(root, server2);
3417
3522
  const initStartedAt = this.now();
3418
3523
  const initPromise = (async () => {
@@ -3438,7 +3543,7 @@ class LspManager {
3438
3543
  if (this.clients.get(key) === managed) {
3439
3544
  this.clients.delete(key);
3440
3545
  }
3441
- stopClientBestEffort(client);
3546
+ this.tombstoneStop(key, client);
3442
3547
  });
3443
3548
  }
3444
3549
  isServerInitializing(root, serverId) {
@@ -3482,8 +3587,11 @@ class LspManager {
3482
3587
  for (const managed of this.clients.values()) {
3483
3588
  stopPromises.push(stopClientBestEffort(managed.client));
3484
3589
  }
3590
+ const tombstonedStops = [...this.pendingStops.values()];
3485
3591
  this.clients.clear();
3486
- await Promise.allSettled(stopPromises);
3592
+ this.respawnBudgets.clear();
3593
+ await Promise.allSettled([...stopPromises, ...tombstonedStops]);
3594
+ this.pendingStops.clear();
3487
3595
  }
3488
3596
  }
3489
3597
  var _defaultInstance = null;
@@ -3501,57 +3609,52 @@ async function disposeDefaultLspManager() {
3501
3609
  }
3502
3610
  }
3503
3611
 
3504
- // ../lsp-core/src/lsp/server-install-state.ts
3505
- import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3506
- import { dirname as dirname5 } from "node:path";
3507
- function getInstallDecisionsPath() {
3508
- return lspRequestContext().installDecisionsPath;
3509
- }
3510
- function loadInstallDecisions() {
3511
- const path = getInstallDecisionsPath();
3512
- if (!existsSync6(path))
3513
- return {};
3514
- try {
3515
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
3516
- return isInstallDecisions(parsed) ? parsed : {};
3517
- } catch {
3518
- return {};
3612
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3613
+ import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
3614
+ import { dirname as dirname5, join as join3 } from "node:path";
3615
+
3616
+ // ../lsp-core/src/lsp/workspace-markers.ts
3617
+ var GIT_WORKSPACE_MARKER = ".git";
3618
+ var PROJECT_WORKSPACE_MARKERS = [
3619
+ "package.json",
3620
+ "pyproject.toml",
3621
+ "Cargo.toml",
3622
+ "go.mod",
3623
+ "pom.xml",
3624
+ "build.gradle"
3625
+ ];
3626
+ var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
3627
+
3628
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3629
+ function findWorkspaceRootOutsideContext(directory) {
3630
+ const marked = nearestMarkedAncestor(directory);
3631
+ if (marked !== undefined)
3632
+ return marked;
3633
+ return realpathSync4(nearestExistingAncestor(directory));
3634
+ }
3635
+ function nearestMarkedAncestor(directory) {
3636
+ let current = directory;
3637
+ for (;; ) {
3638
+ if (existsSync6(current) && WORKSPACE_MARKERS.some((marker) => existsSync6(join3(current, marker)))) {
3639
+ return realpathSync4(current);
3640
+ }
3641
+ const parent = dirname5(current);
3642
+ if (parent === current)
3643
+ return;
3644
+ current = parent;
3519
3645
  }
3520
3646
  }
3521
- function loadInstallDecision(serverId) {
3522
- return loadInstallDecisions()[serverId];
3523
- }
3524
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3525
- const decisions = loadInstallDecisions();
3526
- decisions[serverId] = { decision, decidedAt };
3527
- writeInstallDecisions(decisions);
3528
- }
3529
- function isInstallDecision(value) {
3530
- return value === "declined" || value === "allowed";
3531
- }
3532
- function writeInstallDecisions(decisions) {
3533
- const path = getInstallDecisionsPath();
3534
- mkdirSync(dirname5(path), { recursive: true });
3535
- const tmpPath = `${path}.tmp`;
3536
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3537
- `, "utf8");
3538
- renameSync2(tmpPath, path);
3539
- }
3540
- function isInstallDecisions(value) {
3541
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3542
- }
3543
- function isInstallDecisionRecord(value) {
3544
- if (!isRecord5(value))
3545
- return false;
3546
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3547
- }
3548
- function isRecord5(value) {
3549
- return typeof value === "object" && value !== null && !Array.isArray(value);
3647
+ function nearestExistingAncestor(directory) {
3648
+ let current = directory;
3649
+ while (!existsSync6(current)) {
3650
+ const parent = dirname5(current);
3651
+ if (parent === current)
3652
+ return current;
3653
+ current = parent;
3654
+ }
3655
+ return current;
3550
3656
  }
3551
3657
 
3552
- // ../lsp-core/src/lsp/config-loader.ts
3553
- import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
3554
-
3555
3658
  // ../lsp-core/src/lsp/server-definitions.ts
3556
3659
  var LSP_INSTALL_HINTS = {
3557
3660
  typescript: "npm install -g typescript-language-server typescript",
@@ -3597,6 +3700,26 @@ var LSP_INSTALL_HINTS = {
3597
3700
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
3598
3701
  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"
3599
3702
  };
3703
+ var LSP_LOCAL_INSTALL_HINTS = {
3704
+ typescript: "bun add -d typescript-language-server typescript",
3705
+ vue: "bun add -d @vue/language-server",
3706
+ eslint: "bun add -d vscode-langservers-extracted",
3707
+ oxlint: "bun add -d oxlint",
3708
+ biome: "bun add -d @biomejs/biome",
3709
+ svelte: "bun add -d svelte-language-server",
3710
+ astro: "bun add -d @astrojs/language-server",
3711
+ bash: "bun add -d bash-language-server",
3712
+ "bash-ls": "bun add -d bash-language-server",
3713
+ "yaml-ls": "bun add -d yaml-language-server",
3714
+ php: "bun add -d intelephense",
3715
+ prisma: "bun add -d prisma",
3716
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
3717
+ pyright: "uv add --dev pyright",
3718
+ basedpyright: "uv add --dev basedpyright",
3719
+ ruff: "uv add --dev ruff",
3720
+ ty: "uv add --dev ty",
3721
+ "ruby-lsp": "bundle add ruby-lsp --group development"
3722
+ };
3600
3723
  var BUILTIN_SERVERS = {
3601
3724
  typescript: {
3602
3725
  command: ["typescript-language-server", "--stdio"],
@@ -3699,7 +3822,56 @@ var BUILTIN_SERVERS = {
3699
3822
  }
3700
3823
  };
3701
3824
 
3825
+ // ../lsp-core/src/lsp/server-install-state.ts
3826
+ import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3827
+ import { dirname as dirname6 } from "node:path";
3828
+ function getInstallDecisionsPath() {
3829
+ return lspRequestContext().installDecisionsPath;
3830
+ }
3831
+ function loadInstallDecisions() {
3832
+ const path = getInstallDecisionsPath();
3833
+ if (!existsSync7(path))
3834
+ return {};
3835
+ try {
3836
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
3837
+ return isInstallDecisions(parsed) ? parsed : {};
3838
+ } catch {
3839
+ return {};
3840
+ }
3841
+ }
3842
+ function loadInstallDecision(serverId) {
3843
+ return loadInstallDecisions()[serverId];
3844
+ }
3845
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3846
+ const decisions = loadInstallDecisions();
3847
+ decisions[serverId] = { decision, decidedAt };
3848
+ writeInstallDecisions(decisions);
3849
+ }
3850
+ function isInstallDecision(value) {
3851
+ return value === "declined" || value === "allowed";
3852
+ }
3853
+ function writeInstallDecisions(decisions) {
3854
+ const path = getInstallDecisionsPath();
3855
+ mkdirSync(dirname6(path), { recursive: true });
3856
+ const tmpPath = `${path}.tmp`;
3857
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3858
+ `, "utf8");
3859
+ renameSync2(tmpPath, path);
3860
+ }
3861
+ function isInstallDecisions(value) {
3862
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3863
+ }
3864
+ function isInstallDecisionRecord(value) {
3865
+ if (!isRecord5(value))
3866
+ return false;
3867
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3868
+ }
3869
+ function isRecord5(value) {
3870
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3871
+ }
3872
+
3702
3873
  // ../lsp-core/src/lsp/config-loader.ts
3874
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
3703
3875
  function getProjectConfigPaths() {
3704
3876
  return lspRequestContext().projectConfigPaths;
3705
3877
  }
@@ -3707,7 +3879,7 @@ function getUserConfigPath() {
3707
3879
  return lspRequestContext().userConfigPath;
3708
3880
  }
3709
3881
  function loadJsonFile(path) {
3710
- if (!existsSync7(path))
3882
+ if (!existsSync8(path))
3711
3883
  return null;
3712
3884
  try {
3713
3885
  const parsed = JSON.parse(readFileSync4(path, "utf-8"));
@@ -3895,54 +4067,155 @@ function getDisabledServerIds() {
3895
4067
  }
3896
4068
 
3897
4069
  // ../lsp-core/src/lsp/server-installation.ts
3898
- import { existsSync as existsSync8 } from "node:fs";
3899
- import { delimiter as delimiter3, join as join3 } from "node:path";
3900
- function isServerInstalled(command, _workingDirectory) {
3901
- if (command.length === 0)
3902
- return false;
3903
- const [cmd] = command;
3904
- if (!cmd)
3905
- return false;
3906
- if (cmd.includes("/") || cmd.includes("\\")) {
3907
- if (existsSync8(cmd))
3908
- return true;
4070
+ import { existsSync as existsSync9 } from "node:fs";
4071
+ import { delimiter as delimiter3, dirname as dirname7, isAbsolute as isAbsolute3, join as join4, resolve as resolve7 } from "node:path";
4072
+ var LOCAL_BIN_RULES = [
4073
+ {
4074
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
4075
+ binDirs: [join4("node_modules", ".bin")]
4076
+ },
4077
+ {
4078
+ markers: [
4079
+ "pyproject.toml",
4080
+ "ty.toml",
4081
+ "requirements.txt",
4082
+ "setup.py",
4083
+ "setup.cfg",
4084
+ "Pipfile",
4085
+ "pyrightconfig.json",
4086
+ "ruff.toml",
4087
+ ".ruff.toml"
4088
+ ],
4089
+ binDirs: [
4090
+ join4(".venv", "bin"),
4091
+ join4(".venv", "Scripts"),
4092
+ join4("venv", "bin"),
4093
+ join4("venv", "Scripts"),
4094
+ join4(".env", "bin"),
4095
+ join4(".env", "Scripts")
4096
+ ]
4097
+ },
4098
+ {
4099
+ markers: ["Gemfile", "Gemfile.lock"],
4100
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
4101
+ },
4102
+ {
4103
+ markers: ["go.mod", "go.sum", "go.work"],
4104
+ binDirs: ["bin"]
4105
+ }
4106
+ ];
4107
+ var resolutionCache = new Map;
4108
+ var probeCount = 0;
4109
+ function probe(path) {
4110
+ probeCount += 1;
4111
+ return existsSync9(path);
4112
+ }
4113
+ function executableSuffixes(platform, pathExt) {
4114
+ if (platform !== "win32")
4115
+ return [""];
4116
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
4117
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
4118
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4119
+ }
4120
+ function probeWithSuffixes(directory, command, suffixes) {
4121
+ for (const suffix of suffixes) {
4122
+ const candidate = join4(directory, command + suffix);
4123
+ if (probe(candidate))
4124
+ return candidate;
3909
4125
  }
3910
- const isWindows = process.platform === "win32";
3911
- let exts = [""];
3912
- if (isWindows) {
3913
- const pathExt = process.env["PATHEXT"] ?? "";
3914
- if (pathExt) {
3915
- const systemExts = pathExt.split(";").filter(Boolean);
3916
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
3917
- } else {
3918
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
4126
+ return null;
4127
+ }
4128
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
4129
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
4130
+ let current = resolve7(workingDirectory);
4131
+ while (true) {
4132
+ for (const rule of LOCAL_BIN_RULES) {
4133
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
4134
+ continue;
4135
+ for (const binDir of rule.binDirs) {
4136
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
4137
+ if (found !== null)
4138
+ return found;
4139
+ }
3919
4140
  }
4141
+ if (probe(join4(current, ".git")))
4142
+ return null;
4143
+ if (boundary !== undefined && current === boundary)
4144
+ return null;
4145
+ const parent = dirname7(current);
4146
+ if (parent === current)
4147
+ return null;
4148
+ current = parent;
3920
4149
  }
3921
- let pathEnv = process.env["PATH"] ?? "";
3922
- if (isWindows && !pathEnv) {
4150
+ }
4151
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
4152
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
4153
+ if (platform === "win32" && !pathEnv) {
3923
4154
  pathEnv = process.env["Path"] ?? "";
3924
4155
  }
3925
- const paths = pathEnv.split(delimiter3);
3926
- for (const p of paths) {
3927
- for (const suffix of exts) {
3928
- if (existsSync8(join3(p, cmd + suffix))) {
3929
- return true;
3930
- }
3931
- }
4156
+ for (const entry of pathEnv.split(delimiter3)) {
4157
+ if (entry.length === 0)
4158
+ continue;
4159
+ const found = probeWithSuffixes(entry, command, suffixes);
4160
+ if (found !== null)
4161
+ return found;
3932
4162
  }
3933
- if (cmd === "node")
3934
- return true;
3935
- return false;
4163
+ return null;
4164
+ }
4165
+ function resolveServerBinary(command, workingDirectory, options = {}) {
4166
+ if (command.length === 0)
4167
+ return null;
4168
+ const [cmd] = command;
4169
+ if (cmd === undefined || cmd.length === 0)
4170
+ return null;
4171
+ const platform = options.platform ?? process.platform;
4172
+ const suffixes = executableSuffixes(platform, options.pathExt);
4173
+ if (cmd.includes("/") || cmd.includes("\\")) {
4174
+ const explicit = isAbsolute3(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
4175
+ return probe(explicit) ? explicit : null;
4176
+ }
4177
+ const cacheKey = JSON.stringify([
4178
+ workingDirectory ?? "",
4179
+ cmd,
4180
+ platform,
4181
+ options.stopAt ?? "",
4182
+ options.pathExt ?? "",
4183
+ options.pathEnv ?? process.env["PATH"] ?? ""
4184
+ ]);
4185
+ const cached = resolutionCache.get(cacheKey);
4186
+ if (cached !== undefined)
4187
+ return cached;
4188
+ let resolved = null;
4189
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
4190
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
4191
+ }
4192
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
4193
+ if (resolved === null && cmd === "node")
4194
+ resolved = cmd;
4195
+ resolutionCache.set(cacheKey, resolved);
4196
+ return resolved;
4197
+ }
4198
+ function isServerInstalled(command, workingDirectory, options = {}) {
4199
+ if (command.length === 0)
4200
+ return false;
4201
+ return resolveServerBinary(command, workingDirectory, options) !== null;
3936
4202
  }
3937
4203
 
3938
4204
  // ../lsp-core/src/lsp/server-resolution.ts
4205
+ function withResolvedCommand(command, binaryPath) {
4206
+ return [binaryPath, ...command.slice(1)];
4207
+ }
3939
4208
  function findServerForExtension(ext) {
3940
4209
  const servers = getMergedServers();
4210
+ const workingDirectory = contextCwd();
3941
4211
  for (const server2 of servers) {
3942
- if (server2.extensions.includes(ext) && isServerInstalled(server2.command)) {
4212
+ if (!server2.extensions.includes(ext))
4213
+ continue;
4214
+ const binaryPath = resolveServerBinary(server2.command, workingDirectory);
4215
+ if (binaryPath !== null) {
3943
4216
  const resolvedServer = {
3944
4217
  id: server2.id,
3945
- command: server2.command,
4218
+ command: withResolvedCommand(server2.command, binaryPath),
3946
4219
  extensions: server2.extensions,
3947
4220
  priority: server2.priority
3948
4221
  };
@@ -3989,6 +4262,7 @@ function findServerForExtension(ext) {
3989
4262
  function getAllServers() {
3990
4263
  const servers = getMergedServers();
3991
4264
  const disabled = getDisabledServerIds();
4265
+ const workingDirectory = contextCwd();
3992
4266
  const result = [];
3993
4267
  const seen = new Set;
3994
4268
  for (const server2 of servers) {
@@ -3996,7 +4270,7 @@ function getAllServers() {
3996
4270
  continue;
3997
4271
  result.push({
3998
4272
  id: server2.id,
3999
- installed: isServerInstalled(server2.command),
4273
+ installed: isServerInstalled(server2.command, workingDirectory),
4000
4274
  extensions: server2.extensions,
4001
4275
  disabled: false,
4002
4276
  source: server2.source,
@@ -4010,7 +4284,7 @@ function getAllServers() {
4010
4284
  const builtin = BUILTIN_SERVERS[id];
4011
4285
  result.push({
4012
4286
  id,
4013
- installed: builtin ? isServerInstalled(builtin.command) : false,
4287
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
4014
4288
  extensions: builtin?.extensions ?? [],
4015
4289
  disabled: true,
4016
4290
  source: "disabled",
@@ -4021,7 +4295,6 @@ function getAllServers() {
4021
4295
  }
4022
4296
 
4023
4297
  // ../lsp-core/src/lsp/client-wrapper.ts
4024
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
4025
4298
  function isDirectoryPath(filePath) {
4026
4299
  try {
4027
4300
  return statSync3(filePath).isDirectory();
@@ -4030,32 +4303,90 @@ function isDirectoryPath(filePath) {
4030
4303
  }
4031
4304
  }
4032
4305
  function findWorkspaceRoot(filePath) {
4033
- const abs = resolvePathInsideContext(filePath);
4306
+ const cwd = contextCwd();
4307
+ const abs = resolveReadablePathInsideContext(filePath);
4034
4308
  let dir = abs;
4035
4309
  if (!isDirectoryPath(dir)) {
4036
- dir = dirname6(dir);
4037
- }
4038
- let prevDir = "";
4039
- while (dir !== prevDir) {
4040
- for (const marker of WORKSPACE_MARKERS) {
4041
- if (existsSync9(join4(dir, marker))) {
4042
- return dir;
4310
+ dir = dirname8(dir);
4311
+ }
4312
+ if (!isPathInside(cwd, abs))
4313
+ return findWorkspaceRootOutsideContext(dir);
4314
+ const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4315
+ let nearestPackageRoot;
4316
+ while (isPathInside(cwd, dir)) {
4317
+ const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4318
+ if (canonicalDir !== undefined) {
4319
+ if (existsSync10(join5(dir, GIT_WORKSPACE_MARKER))) {
4320
+ return canonicalDir;
4321
+ }
4322
+ if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
4323
+ nearestPackageRoot = canonicalDir;
4043
4324
  }
4044
4325
  }
4045
- prevDir = dir;
4046
- dir = dirname6(dir);
4326
+ if (dir === cwd)
4327
+ break;
4328
+ dir = dirname8(dir);
4047
4329
  }
4048
- return dirname6(abs);
4330
+ return nearestPackageRoot ?? fallbackRoot;
4331
+ }
4332
+ function hasProjectWorkspaceMarker(directory) {
4333
+ return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync10(join5(directory, marker)));
4334
+ }
4335
+ function resolveReadablePathInsideContext(filePath) {
4336
+ const cwd = contextCwd();
4337
+ const abs = resolve8(cwd, filePath);
4338
+ if (isPathInside(cwd, abs))
4339
+ return abs;
4340
+ const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4341
+ if (rebased !== undefined)
4342
+ return rebased;
4343
+ return canonicalizeExistingOrNearestAncestor(abs);
4049
4344
  }
4050
4345
  function resolvePathInsideContext(filePath) {
4051
4346
  const cwd = contextCwd();
4052
- const abs = resolve7(cwd, filePath);
4347
+ const abs = resolveReadablePathInsideContext(filePath);
4053
4348
  const canonical = canonicalizeExistingOrNearestAncestor(abs);
4054
4349
  if (!isPathInside(cwd, canonical)) {
4055
4350
  throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
4056
4351
  }
4057
4352
  return canonical;
4058
4353
  }
4354
+ function rebaseThroughCanonicalAncestor(path, cwd) {
4355
+ let current = path;
4356
+ const suffix = [];
4357
+ while (true) {
4358
+ if (existsSync10(current)) {
4359
+ const canonical = realpathSync5(current);
4360
+ if (isPathInside(cwd, canonical))
4361
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
4362
+ }
4363
+ const parent = dirname8(current);
4364
+ if (parent === current)
4365
+ return;
4366
+ suffix.unshift(basename3(current));
4367
+ current = parent;
4368
+ }
4369
+ }
4370
+ function existingDirectoryInsideContext(directory, cwd) {
4371
+ if (!existsSync10(directory))
4372
+ return;
4373
+ const canonical = realpathSync5(directory);
4374
+ if (!statSync3(canonical).isDirectory())
4375
+ return;
4376
+ return isPathInside(cwd, canonical) ? canonical : undefined;
4377
+ }
4378
+ function nearestExistingDirectoryInsideContext(directory, cwd) {
4379
+ let current = directory;
4380
+ while (isPathInside(cwd, current)) {
4381
+ const canonical = existingDirectoryInsideContext(current, cwd);
4382
+ if (canonical !== undefined)
4383
+ return canonical;
4384
+ if (current === cwd)
4385
+ return;
4386
+ current = dirname8(current);
4387
+ }
4388
+ return;
4389
+ }
4059
4390
  function formatServerLookupError(result) {
4060
4391
  if (result.status === "not_installed") {
4061
4392
  return formatNotInstalled(result);
@@ -4079,6 +4410,19 @@ function formatServerLookupError(result) {
4079
4410
  ].join(`
4080
4411
  `);
4081
4412
  }
4413
+ function formatInstallOptions(serverId, installHint) {
4414
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
4415
+ if (localHint === undefined) {
4416
+ return ["To install, run:", ` ${installHint}`];
4417
+ }
4418
+ return [
4419
+ "To install in THIS repository (preferred — no global install needed):",
4420
+ ` ${localHint}`,
4421
+ "",
4422
+ "Or install it globally:",
4423
+ ` ${installHint}`
4424
+ ];
4425
+ }
4082
4426
  function formatNotInstalled(result) {
4083
4427
  const { server: server2, installHint } = result;
4084
4428
  const extensions = server2.extensions.join(", ");
@@ -4093,19 +4437,19 @@ function formatNotInstalled(result) {
4093
4437
  `Command not found: ${server2.command[0]}`,
4094
4438
  ""
4095
4439
  ];
4440
+ const installOptions = formatInstallOptions(server2.id, installHint);
4096
4441
  if (decision === "allowed") {
4097
4442
  return [
4098
4443
  ...header,
4099
4444
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
4100
- ` ${installHint}`
4445
+ ...installOptions.slice(1)
4101
4446
  ].join(`
4102
4447
  `);
4103
4448
  }
4104
4449
  if (!context.capabilities.installDecisionTool) {
4105
4450
  return [
4106
4451
  ...header,
4107
- "To install, run:",
4108
- ` ${installHint}`,
4452
+ ...installOptions,
4109
4453
  "",
4110
4454
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4111
4455
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -4114,8 +4458,7 @@ function formatNotInstalled(result) {
4114
4458
  }
4115
4459
  return [
4116
4460
  ...header,
4117
- "To install, run:",
4118
- ` ${installHint}`,
4461
+ ...installOptions,
4119
4462
  "",
4120
4463
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4121
4464
  "- If the user agrees: run the install command above, then retry this tool.",
@@ -4126,7 +4469,7 @@ function formatNotInstalled(result) {
4126
4469
  ].join(`
4127
4470
  `);
4128
4471
  }
4129
- var READ_ONLY_RETRY_TOOLS = new Set([
4472
+ var READ_ONLY_TOOLS = new Set([
4130
4473
  "diagnostics",
4131
4474
  "definition",
4132
4475
  "references",
@@ -4135,7 +4478,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
4135
4478
  "prepareRename"
4136
4479
  ]);
4137
4480
  async function withLspClient(filePath, fn, toolName, options = {}) {
4138
- const absPath = resolvePathInsideContext(filePath);
4481
+ const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
4139
4482
  if (isDirectoryPath(absPath)) {
4140
4483
  throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
4141
4484
  }
@@ -4150,9 +4493,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4150
4493
  const acquireAndCall = async (allowRetry) => {
4151
4494
  const client = await manager.getClient(root, server2, options.signal);
4152
4495
  try {
4153
- return await fn(client, root);
4496
+ return await fn(client, root, absPath);
4154
4497
  } catch (err) {
4155
- if (allowRetry && READ_ONLY_RETRY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4498
+ if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4156
4499
  manager.invalidateClient(root, server2.id, client);
4157
4500
  return acquireAndCall(false);
4158
4501
  }
@@ -4170,8 +4513,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4170
4513
  }
4171
4514
 
4172
4515
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4173
- import { existsSync as existsSync10, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4174
- import { join as join5, resolve as resolve8 } from "node:path";
4516
+ import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4517
+ import { join as join6, resolve as resolve9 } from "node:path";
4175
4518
 
4176
4519
  // ../lsp-core/src/lsp/formatters.ts
4177
4520
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -4301,7 +4644,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
4301
4644
  for (const entry of entries) {
4302
4645
  if (files.length >= maxFiles)
4303
4646
  return;
4304
- const fullPath = join5(currentDir, entry);
4647
+ const fullPath = join6(currentDir, entry);
4305
4648
  let stat;
4306
4649
  try {
4307
4650
  stat = lstatSync4(fullPath);
@@ -4326,8 +4669,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4326
4669
  if (!extension.startsWith(".")) {
4327
4670
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4328
4671
  }
4329
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4330
- if (!existsSync10(absDir)) {
4672
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
4673
+ if (!existsSync11(absDir)) {
4331
4674
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4332
4675
  }
4333
4676
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
@@ -4414,7 +4757,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4414
4757
 
4415
4758
  // ../lsp-core/src/lsp/infer-extension.ts
4416
4759
  import { lstatSync as lstatSync5, readdirSync as readdirSync4 } from "node:fs";
4417
- import { join as join6 } from "node:path";
4760
+ import { join as join7 } from "node:path";
4418
4761
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
4419
4762
  var MAX_SCAN_ENTRIES = 500;
4420
4763
  function inferExtensionFromDirectory(directory) {
@@ -4432,7 +4775,7 @@ function inferExtensionFromDirectory(directory) {
4432
4775
  for (const entry of entries) {
4433
4776
  if (scanned >= MAX_SCAN_ENTRIES)
4434
4777
  return;
4435
- const fullPath = join6(dir, entry);
4778
+ const fullPath = join7(dir, entry);
4436
4779
  let stat;
4437
4780
  try {
4438
4781
  stat = lstatSync5(fullPath);
@@ -4607,7 +4950,7 @@ async function executeLspDiagnostics(params, signal) {
4607
4950
  const filePath = requireString(params, "filePath");
4608
4951
  const severity = severityFilter(params);
4609
4952
  try {
4610
- const absPath = resolvePathInsideContext(filePath);
4953
+ const absPath = resolveReadablePathInsideContext(filePath);
4611
4954
  if (isDirectoryPath(absPath)) {
4612
4955
  const extension = inferExtensionFromDirectory(absPath);
4613
4956
  if (!extension) {
@@ -4636,7 +4979,7 @@ async function executeLspDiagnostics(params, signal) {
4636
4979
  };
4637
4980
  return text(output2.output, details2);
4638
4981
  }
4639
- const result = await withLspClient(filePath, async (client) => client.diagnostics(filePath, signal), "diagnostics", clientOptions(signal));
4982
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
4640
4983
  if (result.transientError) {
4641
4984
  const message = result.transientError.message;
4642
4985
  const details2 = {
@@ -4683,6 +5026,96 @@ async function executeLspDiagnostics(params, signal) {
4683
5026
  throw error;
4684
5027
  }
4685
5028
  }
5029
+ // ../lsp-core/src/lsp/format-document.ts
5030
+ import { readFileSync as readFileSync5, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
5031
+ var DEFAULT_FORMATTING_OPTIONS = {
5032
+ tabSize: 4,
5033
+ insertSpaces: false,
5034
+ trimTrailingWhitespace: true,
5035
+ insertFinalNewline: true,
5036
+ trimFinalNewlines: true
5037
+ };
5038
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
5039
+ async function formatDocumentWithClient(client, filePath, options = {}) {
5040
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
5041
+ if (edits === null)
5042
+ return { status: "unavailable", reason: "capability_not_advertised" };
5043
+ if (edits.length === 0)
5044
+ return UNCHANGED;
5045
+ const before = readFileSync5(filePath, "utf-8");
5046
+ const normalized = normalizeTextEdits(before, edits, 0);
5047
+ if (normalized.text === before)
5048
+ return UNCHANGED;
5049
+ writeAtomically(filePath, normalized.text);
5050
+ await client.openFile(filePath);
5051
+ return {
5052
+ status: "formatted",
5053
+ ...lineDelta(normalized.edits)
5054
+ };
5055
+ }
5056
+ function lineDelta(edits) {
5057
+ let linesAdded = 0;
5058
+ let linesRemoved = 0;
5059
+ for (const edit of edits) {
5060
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
5061
+ linesAdded += edit.newText.split(`
5062
+ `).length;
5063
+ }
5064
+ return { linesAdded, linesRemoved };
5065
+ }
5066
+ function writeAtomically(filePath, content) {
5067
+ const tempPath = `${filePath}.omo-format.tmp`;
5068
+ writeFileSync3(tempPath, content, "utf-8");
5069
+ try {
5070
+ renameSync3(tempPath, filePath);
5071
+ } catch (error) {
5072
+ try {
5073
+ unlinkSync(tempPath);
5074
+ } catch {}
5075
+ throw error;
5076
+ }
5077
+ }
5078
+
5079
+ // ../lsp-core/src/tools/format.ts
5080
+ async function executeLspFormat(params, signal) {
5081
+ const filePath = requireString(params, "filePath");
5082
+ try {
5083
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
5084
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
5085
+ } catch (error) {
5086
+ const missingDependency = missingDependencyResult(error, {
5087
+ filePath,
5088
+ status: "unavailable",
5089
+ reason: "server_unavailable",
5090
+ linesAdded: 0,
5091
+ linesRemoved: 0
5092
+ });
5093
+ if (missingDependency)
5094
+ return missingDependency;
5095
+ throw error;
5096
+ }
5097
+ }
5098
+ function formatDetails(filePath, result) {
5099
+ if (result.status === "unavailable") {
5100
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
5101
+ }
5102
+ return {
5103
+ filePath,
5104
+ status: result.status,
5105
+ linesAdded: result.linesAdded,
5106
+ linesRemoved: result.linesRemoved
5107
+ };
5108
+ }
5109
+ function describeResult(filePath, result) {
5110
+ if (result.status === "unavailable") {
5111
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
5112
+ }
5113
+ if (result.status === "unchanged") {
5114
+ return `Already formatted: ${filePath}`;
5115
+ }
5116
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
5117
+ }
5118
+
4686
5119
  // ../lsp-core/src/tools/install-decision.ts
4687
5120
  async function executeLspInstallDecision(params) {
4688
5121
  const serverId = requireString(params, "server_id");
@@ -4711,7 +5144,7 @@ async function executeLspGotoDefinition(params, signal) {
4711
5144
  const line = requireNumber(params, "line");
4712
5145
  const character = requireNumber(params, "character");
4713
5146
  try {
4714
- const result = await withLspClient(filePath, async (client) => client.definition(filePath, line, character, signal), "definition", clientOptions(signal));
5147
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
4715
5148
  const locations = !result ? [] : Array.isArray(result) ? result : [result];
4716
5149
  const details = { filePath, line, character, locations };
4717
5150
  if (locations.length === 0)
@@ -4736,7 +5169,7 @@ async function executeLspFindReferences(params, signal) {
4736
5169
  const character = requireNumber(params, "character");
4737
5170
  const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
4738
5171
  try {
4739
- const result = await withLspClient(filePath, async (client) => client.references(filePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5172
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
4740
5173
  const references = Array.isArray(result) ? result : [];
4741
5174
  const total = references.length;
4742
5175
  const truncated = total > DEFAULT_MAX_REFERENCES;
@@ -4778,7 +5211,7 @@ async function executeLspPrepareRename(params, signal) {
4778
5211
  const line = requireNumber(params, "line");
4779
5212
  const character = requireNumber(params, "character");
4780
5213
  try {
4781
- const result = await withLspClient(filePath, async (client) => client.prepareRename(filePath, line, character, signal), "prepareRename", clientOptions(signal));
5214
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
4782
5215
  const details = { filePath, line, character, result };
4783
5216
  return text(formatPrepareRenameResult(result), details);
4784
5217
  } catch (error) {
@@ -4799,7 +5232,7 @@ async function executeLspRename(params, signal) {
4799
5232
  const character = requireNumber(params, "character");
4800
5233
  const newName = requireString(params, "newName");
4801
5234
  try {
4802
- const result = await withLspClient(filePath, async (client) => client.rename(filePath, line, character, newName, signal), "rename", clientOptions(signal));
5235
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
4803
5236
  const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
4804
5237
  return text(formatApplyResult(result.apply), details, !result.apply.success);
4805
5238
  } catch (error) {
@@ -4879,7 +5312,7 @@ async function executeLspSymbols(params, signal) {
4879
5312
  const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
4880
5313
  return formatSymbolsResult(filePath, scope, symbols2, limit, query);
4881
5314
  }
4882
- const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(filePath, signal), "documentSymbols", clientOptions(signal));
5315
+ const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
4883
5316
  return formatSymbolsResult(filePath, scope, symbols, limit);
4884
5317
  } catch (error) {
4885
5318
  const query = optionalString(params, "query");
@@ -5015,6 +5448,16 @@ var LSP_MCP_TOOLS = [
5015
5448
  }, ["filePath", "line", "character", "newName"]),
5016
5449
  execute: executeLspRename
5017
5450
  },
5451
+ {
5452
+ name: "format",
5453
+ aliases: ["lsp_format"],
5454
+ title: "LSP Format",
5455
+ description: "Format a source file with its language server and write the returned edits to disk.",
5456
+ inputSchema: objectSchema({
5457
+ filePath: { type: "string", description: "Source file path to format." }
5458
+ }, ["filePath"]),
5459
+ execute: executeLspFormat
5460
+ },
5018
5461
  {
5019
5462
  name: "install_decision",
5020
5463
  aliases: ["lsp_install_decision"],
@@ -5122,6 +5565,6 @@ function requestedProtocolVersion(params) {
5122
5565
  return params["protocolVersion"];
5123
5566
  }
5124
5567
  export {
5125
- runMcpStdioServer,
5126
- handleLspMcpRequest
5568
+ handleLspMcpRequest,
5569
+ runMcpStdioServer
5127
5570
  };