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
@@ -1,7 +1,11 @@
1
+ // src/client.ts
2
+ import { statSync as statSync5 } from "node:fs";
3
+ import { isAbsolute as isAbsolute6 } from "node:path";
4
+
1
5
  // src/daemon-client.ts
2
6
  import { connect } from "node:net";
3
7
  import { homedir as homedir3 } from "node:os";
4
- import { join as join7 } from "node:path";
8
+ import { join as join8 } from "node:path";
5
9
 
6
10
  // ../lsp-core/src/request-context.ts
7
11
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -10,18 +14,17 @@ import { homedir } from "node:os";
10
14
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
11
15
 
12
16
  class LspRequestContextParseError extends Error {
13
- code;
14
- name = "LspRequestContextParseError";
15
17
  constructor(code, message) {
16
18
  super(message);
17
19
  this.code = code;
20
+ this.name = "LspRequestContextParseError";
18
21
  }
19
22
  }
20
23
 
21
24
  class LspRequestContextUnavailableError extends Error {
22
- name = "LspRequestContextUnavailableError";
23
25
  constructor() {
24
26
  super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
27
+ this.name = "LspRequestContextUnavailableError";
25
28
  }
26
29
  }
27
30
  var storage = new AsyncLocalStorage;
@@ -41,7 +44,7 @@ function contextCwd() {
41
44
  }
42
45
  function createStandaloneMcpRequestContext(input = {}) {
43
46
  const env = input.env ?? process.env;
44
- const cwd = canonicalCwd(input.cwd ?? process.cwd());
47
+ const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
45
48
  const home = input.homeDir ?? homedir();
46
49
  const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
47
50
  const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
@@ -179,7 +182,6 @@ function isPlainRecord(value) {
179
182
 
180
183
  // src/daemon-request-error.ts
181
184
  class DaemonRequestError extends Error {
182
- requestWritten;
183
185
  constructor(message, requestWritten) {
184
186
  super(message);
185
187
  this.name = "DaemonRequestError";
@@ -202,7 +204,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
202
204
  }
203
205
 
204
206
  class DaemonRequestTimedOutError extends DaemonRequestError {
205
- timeoutMs;
206
207
  constructor(requestWritten, timeoutMs) {
207
208
  super("daemon request timed out", requestWritten);
208
209
  this.name = "DaemonRequestTimedOutError";
@@ -281,14 +282,12 @@ var PROTOCOL_ERROR_CODE = -32002;
281
282
  var AUTH_TOKEN_BYTES = 32;
282
283
 
283
284
  class UnsafePrivateDirectoryError extends Error {
284
- path;
285
- reason;
286
- name = "UnsafePrivateDirectoryError";
287
- code = "unsafe_private_directory";
288
285
  constructor(path, reason) {
289
286
  super(`unsafe private directory ${path}: ${reason}`);
290
287
  this.path = path;
291
288
  this.reason = reason;
289
+ this.name = "UnsafePrivateDirectoryError";
290
+ this.code = "unsafe_private_directory";
292
291
  }
293
292
  }
294
293
  function authEnvelope(token) {
@@ -472,20 +471,18 @@ var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
472
471
  var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
473
472
 
474
473
  class InvalidRuntimeOverrideError extends Error {
475
- code = "invalid_runtime_override";
476
- reason;
477
474
  constructor(reason, message) {
478
475
  super(message);
476
+ this.code = "invalid_runtime_override";
479
477
  this.name = "InvalidRuntimeOverrideError";
480
478
  this.reason = reason;
481
479
  }
482
480
  }
483
481
 
484
482
  class InvalidDaemonVersionError extends Error {
485
- code = "invalid_daemon_version";
486
- version;
487
483
  constructor(version) {
488
484
  super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
485
+ this.code = "invalid_daemon_version";
489
486
  this.name = "InvalidDaemonVersionError";
490
487
  this.version = version;
491
488
  }
@@ -531,10 +528,9 @@ var requireFromHere = createRequire(import.meta.url);
531
528
  var MAX_SOCKET_PATH_LENGTH = 100;
532
529
 
533
530
  class InvalidDaemonDirectoryError extends Error {
534
- code = "invalid_daemon_directory";
535
- directory;
536
531
  constructor(directory) {
537
532
  super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
533
+ this.code = "invalid_daemon_directory";
538
534
  this.name = "InvalidDaemonDirectoryError";
539
535
  this.directory = directory;
540
536
  }
@@ -729,7 +725,8 @@ function spawnDaemonProcess(paths) {
729
725
  try {
730
726
  const child = spawn(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
731
727
  detached: true,
732
- stdio: ["ignore", logFd, logFd]
728
+ stdio: ["ignore", logFd, logFd],
729
+ windowsHide: true
733
730
  });
734
731
  child.once("spawn", () => closeSync2(logFd));
735
732
  child.once("error", (error) => {
@@ -1010,6 +1007,7 @@ async function runJsonRpcStdioServer(config) {
1010
1007
  const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
1011
1008
  isClosed = true;
1012
1009
  config.onIdleTimeout?.();
1010
+ config.input.destroy();
1013
1011
  });
1014
1012
  const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
1015
1013
  isClosed = true;
@@ -1106,7 +1104,11 @@ function createParentWatchdog(config, onDeadParent) {
1106
1104
  const probeAlive = config.probeAlive ?? isProcessAlive;
1107
1105
  let fired = false;
1108
1106
  const timer = setInterval(() => {
1109
- if (fired || probeAlive(parentPid))
1107
+ if (fired)
1108
+ return;
1109
+ const alive = probeAlive(parentPid);
1110
+ config.onPoll?.(alive);
1111
+ if (alive)
1110
1112
  return;
1111
1113
  fired = true;
1112
1114
  onDeadParent(parentPid, pollIntervalMs);
@@ -1141,8 +1143,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
1141
1143
  };
1142
1144
  }
1143
1145
  // ../lsp-core/src/lsp/client-wrapper.ts
1144
- import { existsSync as existsSync10, statSync as statSync4 } from "node:fs";
1145
- import { dirname as dirname8, join as join4, resolve as resolve7 } from "node:path";
1146
+ import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
1147
+ import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
1146
1148
 
1147
1149
  // ../lsp-core/src/lsp/effective-extension.ts
1148
1150
  import { basename as basename2, extname } from "node:path";
@@ -1156,22 +1158,15 @@ function effectiveExtension(filePath) {
1156
1158
 
1157
1159
  // ../lsp-core/src/lsp/errors.ts
1158
1160
  class LspConnectionClosedError extends Error {
1159
- serverId;
1160
- root;
1161
- name = "LspConnectionClosedError";
1162
1161
  constructor(serverId, root, message) {
1163
1162
  super(message ?? `LSP connection closed for ${serverId} at ${root}`);
1164
1163
  this.serverId = serverId;
1165
1164
  this.root = root;
1165
+ this.name = "LspConnectionClosedError";
1166
1166
  }
1167
1167
  }
1168
1168
 
1169
1169
  class LspProcessExitedError extends Error {
1170
- serverId;
1171
- root;
1172
- exitCode;
1173
- stderrTail;
1174
- name = "LspProcessExitedError";
1175
1170
  constructor(serverId, root, exitCode, stderrTail) {
1176
1171
  const stderrSuffix = stderrTail ? `
1177
1172
  stderr tail: ${stderrTail}` : "";
@@ -1180,46 +1175,59 @@ stderr tail: ${stderrTail}` : "";
1180
1175
  this.root = root;
1181
1176
  this.exitCode = exitCode;
1182
1177
  this.stderrTail = stderrTail;
1178
+ this.name = "LspProcessExitedError";
1183
1179
  }
1184
1180
  }
1185
1181
 
1186
1182
  class LspRequestTimeoutError extends Error {
1187
- method;
1188
- stderrTail;
1189
- name = "LspRequestTimeoutError";
1190
1183
  constructor(method, stderrTail) {
1191
1184
  const stderrSuffix = stderrTail ? `
1192
1185
  recent stderr: ${stderrTail}` : "";
1193
1186
  super(`LSP request timeout (method: ${method})${stderrSuffix}`);
1194
1187
  this.method = method;
1195
1188
  this.stderrTail = stderrTail;
1189
+ this.name = "LspRequestTimeoutError";
1196
1190
  }
1197
1191
  }
1198
1192
 
1199
1193
  class LspInvalidPathError extends Error {
1200
- name = "LspInvalidPathError";
1194
+ constructor() {
1195
+ super(...arguments);
1196
+ this.name = "LspInvalidPathError";
1197
+ }
1201
1198
  }
1202
1199
 
1203
1200
  class LspServerLookupError extends Error {
1204
- lookup;
1205
- name = "LspServerLookupError";
1206
1201
  constructor(message, lookup) {
1207
1202
  super(message);
1208
1203
  this.lookup = lookup;
1204
+ this.name = "LspServerLookupError";
1209
1205
  }
1210
1206
  }
1211
1207
 
1212
1208
  class LspServerInitializingError extends Error {
1213
- originalError;
1214
- name = "LspServerInitializingError";
1215
1209
  constructor(originalError) {
1216
1210
  super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
1217
1211
  this.originalError = originalError;
1212
+ this.name = "LspServerInitializingError";
1218
1213
  }
1219
1214
  }
1220
1215
 
1221
1216
  class LspProcessSpawnError extends Error {
1222
- name = "LspProcessSpawnError";
1217
+ constructor() {
1218
+ super(...arguments);
1219
+ this.name = "LspProcessSpawnError";
1220
+ }
1221
+ }
1222
+
1223
+ class LspClientRespawnBudgetExceededError extends Error {
1224
+ constructor(serverId, root, retryLimit) {
1225
+ super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
1226
+ this.serverId = serverId;
1227
+ this.root = root;
1228
+ this.retryLimit = retryLimit;
1229
+ this.name = "LspClientRespawnBudgetExceededError";
1230
+ }
1223
1231
  }
1224
1232
  function isLspDeadConnectionError(err) {
1225
1233
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
@@ -1250,9 +1258,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
1250
1258
  var REQUEST_TIMEOUT_MS = 15000;
1251
1259
  var INIT_TIMEOUT_MS = 60000;
1252
1260
  var IDLE_TIMEOUT_MS = 5 * 60000;
1261
+ var MAX_RESIDENT_CLIENTS = 6;
1253
1262
  var REAPER_INTERVAL_MS = 60000;
1254
1263
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
1255
1264
  var STOP_SIGKILL_GRACE_MS = 1000;
1265
+ var CLIENT_RESPAWN_RETRY_LIMIT = 2;
1266
+ var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
1256
1267
 
1257
1268
  // ../lsp-core/src/lsp/json-rpc-connection.ts
1258
1269
  var HEADER_SEPARATOR2 = `\r
@@ -1264,20 +1275,31 @@ var METHOD_NOT_FOUND = -32601;
1264
1275
  var INTERNAL_ERROR = -32603;
1265
1276
 
1266
1277
  class JsonRpcConnection {
1267
- reader;
1268
- writer;
1269
- pendingRequests = new Map;
1270
- notificationHandlers = new Map;
1271
- requestHandlers = new Map;
1272
- closeHandlers = [];
1273
- errorHandlers = [];
1274
- inputBuffer = Buffer.alloc(0);
1275
- nextRequestId = 1;
1276
- listening = false;
1277
- disposed = false;
1278
1278
  constructor(reader, writer) {
1279
1279
  this.reader = reader;
1280
1280
  this.writer = writer;
1281
+ this.pendingRequests = new Map;
1282
+ this.notificationHandlers = new Map;
1283
+ this.requestHandlers = new Map;
1284
+ this.closeHandlers = [];
1285
+ this.errorHandlers = [];
1286
+ this.inputBuffer = Buffer.alloc(0);
1287
+ this.nextRequestId = 1;
1288
+ this.listening = false;
1289
+ this.disposed = false;
1290
+ this.handleData = (chunk) => {
1291
+ const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
1292
+ this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
1293
+ this.drainInputBuffer();
1294
+ };
1295
+ this.handleClose = () => {
1296
+ for (const handler of this.closeHandlers) {
1297
+ handler();
1298
+ }
1299
+ };
1300
+ this.handleStreamError = (error) => {
1301
+ this.emitError(error);
1302
+ };
1281
1303
  }
1282
1304
  listen() {
1283
1305
  if (this.listening)
@@ -1398,19 +1420,6 @@ class JsonRpcConnection {
1398
1420
  this.notificationHandlers.clear();
1399
1421
  this.requestHandlers.clear();
1400
1422
  }
1401
- handleData = (chunk) => {
1402
- const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
1403
- this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
1404
- this.drainInputBuffer();
1405
- };
1406
- handleClose = () => {
1407
- for (const handler of this.closeHandlers) {
1408
- handler();
1409
- }
1410
- };
1411
- handleStreamError = (error) => {
1412
- this.emitError(error);
1413
- };
1414
1423
  drainInputBuffer() {
1415
1424
  while (true) {
1416
1425
  const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
@@ -1758,31 +1767,26 @@ function isPosition(value) {
1758
1767
 
1759
1768
  // ../lsp-core/src/lsp/transport.ts
1760
1769
  class LspClientNotStartedError extends Error {
1761
- serverId;
1762
- root;
1763
- name = "LspClientNotStartedError";
1764
1770
  constructor(serverId, root) {
1765
1771
  super("LSP client not started");
1766
1772
  this.serverId = serverId;
1767
1773
  this.root = root;
1774
+ this.name = "LspClientNotStartedError";
1768
1775
  }
1769
1776
  }
1770
1777
 
1771
1778
  class LspClientTransport {
1772
- root;
1773
- server;
1774
- proc = null;
1775
- connection = null;
1776
- stderrBuffer = [];
1777
- processExited = false;
1778
- diagnosticsStore = new Map;
1779
- requestTimeoutMs;
1780
- initializeTimeoutMs;
1781
- workspaceApplyEditHandler = null;
1782
- diagnosticPullSupported = false;
1783
1779
  constructor(root, server2, timeouts = {}) {
1784
1780
  this.root = root;
1785
1781
  this.server = server2;
1782
+ this.proc = null;
1783
+ this.connection = null;
1784
+ this.stderrBuffer = [];
1785
+ this.processExited = false;
1786
+ this.diagnosticsStore = new Map;
1787
+ this.workspaceApplyEditHandler = null;
1788
+ this.diagnosticPullSupported = false;
1789
+ this.documentFormattingSupported = false;
1786
1790
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
1787
1791
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
1788
1792
  }
@@ -1804,6 +1808,12 @@ class LspClientTransport {
1804
1808
  isDiagnosticPullSupported() {
1805
1809
  return this.diagnosticPullSupported;
1806
1810
  }
1811
+ setDocumentFormattingSupported(supported) {
1812
+ this.documentFormattingSupported = supported;
1813
+ }
1814
+ isDocumentFormattingSupported() {
1815
+ return this.documentFormattingSupported;
1816
+ }
1807
1817
  handlePublishDiagnostics(params) {
1808
1818
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
1809
1819
  }
@@ -2017,6 +2027,14 @@ function supportsDiagnosticPull(capabilities) {
2017
2027
  return false;
2018
2028
  return Object.hasOwn(capabilities, "diagnosticProvider");
2019
2029
  }
2030
+ function supportsDocumentFormatting(capabilities) {
2031
+ if (capabilities === undefined)
2032
+ return false;
2033
+ const provider = capabilities.documentFormattingProvider;
2034
+ if (provider === undefined || provider === null || provider === false)
2035
+ return false;
2036
+ return provider === true || typeof provider === "object";
2037
+ }
2020
2038
 
2021
2039
  class LspClientConnection extends LspClientTransport {
2022
2040
  async initialize() {
@@ -2033,6 +2051,7 @@ class LspClientConnection extends LspClientTransport {
2033
2051
  references: {},
2034
2052
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
2035
2053
  publishDiagnostics: {},
2054
+ formatting: { dynamicRegistration: false },
2036
2055
  rename: {
2037
2056
  prepareSupport: true,
2038
2057
  prepareSupportDefaultBehavior: 1
@@ -2074,6 +2093,7 @@ class LspClientConnection extends LspClientTransport {
2074
2093
  initializationOptions: this.server.initialization
2075
2094
  }, { timeoutMs: this.initializeTimeoutMs });
2076
2095
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
2096
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
2077
2097
  await this.sendNotification("initialized", {});
2078
2098
  await this.sendNotification("workspace/didChangeConfiguration", {
2079
2099
  settings: { json: { validate: { enable: true } } }
@@ -2279,16 +2299,12 @@ function movedPath(candidate, oldPath, newPath) {
2279
2299
  }
2280
2300
 
2281
2301
  class WorkspaceDocumentState {
2282
- sendNotification;
2283
- clearDiagnostics;
2284
- openDocuments = new Map;
2285
- openByUri = new Map;
2286
- openPromises = new Map;
2287
- now;
2288
- versionlessPublishQuiescenceMs;
2289
2302
  constructor(sendNotification, clearDiagnostics, options = {}) {
2290
2303
  this.sendNotification = sendNotification;
2291
2304
  this.clearDiagnostics = clearDiagnostics;
2305
+ this.openDocuments = new Map;
2306
+ this.openByUri = new Map;
2307
+ this.openPromises = new Map;
2292
2308
  this.now = options.now ?? (() => Date.now());
2293
2309
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
2294
2310
  }
@@ -2552,13 +2568,11 @@ import { dirname as dirname4, isAbsolute as isAbsolute4, relative as relative3,
2552
2568
  import { fileURLToPath as fileURLToPath2 } from "node:url";
2553
2569
 
2554
2570
  class WorkspaceEditPathError extends Error {
2555
- path;
2556
- detail;
2557
- name = "WorkspaceEditPathError";
2558
2571
  constructor(path2, detail) {
2559
2572
  super(`${detail}: ${path2}`);
2560
2573
  this.path = path2;
2561
2574
  this.detail = detail;
2575
+ this.name = "WorkspaceEditPathError";
2562
2576
  }
2563
2577
  }
2564
2578
  function isPathInsideWorkspace(filePath, workspaceRoot) {
@@ -2850,13 +2864,11 @@ function canonicalFingerprint(operations) {
2850
2864
 
2851
2865
  // ../lsp-core/src/lsp/workspace-edit-types.ts
2852
2866
  class WorkspaceEditValidationError extends Error {
2853
- changeIndex;
2854
- detail;
2855
- name = "WorkspaceEditValidationError";
2856
2867
  constructor(changeIndex, detail) {
2857
2868
  super(`change ${changeIndex}: ${detail}`);
2858
2869
  this.changeIndex = changeIndex;
2859
2870
  this.detail = detail;
2871
+ this.name = "WorkspaceEditValidationError";
2860
2872
  }
2861
2873
  }
2862
2874
 
@@ -3354,10 +3366,9 @@ function simulateDelete(operation, virtual) {
3354
3366
  import { existsSync as existsSync6, lstatSync as lstatSync4, readdirSync as readdirSync2 } from "node:fs";
3355
3367
  import { dirname as dirname6, resolve as resolve5 } from "node:path";
3356
3368
  class WorkspaceSnapshotBuilder {
3357
- workspaceRoot;
3358
- snapshots = new Map;
3359
3369
  constructor(workspaceRoot) {
3360
3370
  this.workspaceRoot = workspaceRoot;
3371
+ this.snapshots = new Map;
3361
3372
  }
3362
3373
  build(operations) {
3363
3374
  this.add(this.workspaceRoot, false);
@@ -3401,8 +3412,10 @@ function snapshotOperations(operations, workspaceRoot) {
3401
3412
 
3402
3413
  // ../lsp-core/src/lsp/workspace-edit-plan.ts
3403
3414
  class PlanPathIndex {
3404
- firstChangeByPath = new Map;
3405
- reportedPathByCanonical = new Map;
3415
+ constructor() {
3416
+ this.firstChangeByPath = new Map;
3417
+ this.reportedPathByCanonical = new Map;
3418
+ }
3406
3419
  build(operations) {
3407
3420
  for (const operation of operations) {
3408
3421
  switch (operation.kind) {
@@ -3491,14 +3504,11 @@ function isRecord4(value) {
3491
3504
  }
3492
3505
 
3493
3506
  class WorkspaceMutationController {
3494
- workspaceRoot;
3495
- documents;
3496
- activeLease = null;
3497
- nextLeaseId = 1;
3498
- io;
3499
3507
  constructor(workspaceRoot, documents) {
3500
3508
  this.workspaceRoot = workspaceRoot;
3501
3509
  this.documents = documents;
3510
+ this.activeLease = null;
3511
+ this.nextLeaseId = 1;
3502
3512
  }
3503
3513
  setIo(io) {
3504
3514
  this.io = io;
@@ -3611,12 +3621,9 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
3611
3621
  var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
3612
3622
 
3613
3623
  class LspClient extends LspClientConnection {
3614
- diagnosticPullErrors = [];
3615
- documents;
3616
- workspaceMutations;
3617
- diagnosticsFreshnessTimeoutMs;
3618
3624
  constructor(root, server2, options = {}) {
3619
3625
  super(root, server2, options);
3626
+ this.diagnosticPullErrors = [];
3620
3627
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
3621
3628
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
3622
3629
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
@@ -3671,6 +3678,18 @@ class LspClient extends LspClientConnection {
3671
3678
  textDocument: { uri: pathToFileURL3(absPath).href }
3672
3679
  }, options);
3673
3680
  }
3681
+ async formatDocument(filePath, options, signal) {
3682
+ if (!this.isDocumentFormattingSupported())
3683
+ return null;
3684
+ const absPath = this.resolveWorkspacePath(filePath);
3685
+ await this.openFile(absPath);
3686
+ const requestOptions = signal === undefined ? {} : { signal };
3687
+ const edits = await this.sendRequest("textDocument/formatting", {
3688
+ textDocument: { uri: pathToFileURL3(absPath).href },
3689
+ options
3690
+ }, requestOptions);
3691
+ return edits ?? [];
3692
+ }
3674
3693
  async workspaceSymbols(query, signal) {
3675
3694
  const options = signal === undefined ? {} : { signal };
3676
3695
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -3916,18 +3935,16 @@ function awaitWithSignal2(promise, signal) {
3916
3935
  }
3917
3936
 
3918
3937
  class LspManager {
3919
- clients = new Map;
3920
- reaperHandle = null;
3921
- signalDisposer = null;
3922
- disposed = false;
3923
- idleTimeoutMs;
3924
- initTimeoutMs;
3925
- reaperIntervalMs;
3926
- clientFactory;
3927
- now;
3928
3938
  constructor(options = {}) {
3939
+ this.clients = new Map;
3940
+ this.pendingStops = new Map;
3941
+ this.respawnBudgets = new Map;
3942
+ this.reaperHandle = null;
3943
+ this.signalDisposer = null;
3944
+ this.disposed = false;
3929
3945
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
3930
3946
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
3947
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
3931
3948
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
3932
3949
  this.clientFactory = options.clientFactory ?? ((root, server2) => new LspClient(root, server2));
3933
3950
  this.now = options.now ?? (() => Date.now());
@@ -3947,24 +3964,79 @@ class LspManager {
3947
3964
  getKey(root, serverId) {
3948
3965
  return `${root}::${serverId}`;
3949
3966
  }
3967
+ tombstoneStop(key, client) {
3968
+ const stop = stopClientBestEffort(client);
3969
+ this.pendingStops.set(key, stop);
3970
+ stop.finally(() => {
3971
+ if (this.pendingStops.get(key) === stop) {
3972
+ this.pendingStops.delete(key);
3973
+ }
3974
+ });
3975
+ return stop;
3976
+ }
3977
+ recordDeadGeneration(key) {
3978
+ let budget = this.respawnBudgets.get(key);
3979
+ if (budget === undefined) {
3980
+ budget = { deadGenerations: 0, exhaustedAt: null };
3981
+ this.respawnBudgets.set(key, budget);
3982
+ }
3983
+ budget.deadGenerations += 1;
3984
+ }
3985
+ markHealthyGeneration(key) {
3986
+ this.respawnBudgets.delete(key);
3987
+ }
3988
+ ensureRespawnAllowed(key, root, serverId) {
3989
+ const budget = this.respawnBudgets.get(key);
3990
+ if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
3991
+ return;
3992
+ if (budget.exhaustedAt === null) {
3993
+ budget.exhaustedAt = this.now();
3994
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3995
+ }
3996
+ if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
3997
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3998
+ }
3999
+ budget.deadGenerations = 0;
4000
+ budget.exhaustedAt = null;
4001
+ }
3950
4002
  reapStale() {
3951
4003
  const t = this.now();
3952
4004
  for (const [key, managed] of this.clients) {
3953
4005
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3954
- stopClientBestEffort(managed.client);
3955
4006
  this.clients.delete(key);
4007
+ this.tombstoneStop(key, managed.client);
3956
4008
  continue;
3957
4009
  }
3958
4010
  if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
3959
- stopClientBestEffort(managed.client);
3960
4011
  this.clients.delete(key);
4012
+ this.tombstoneStop(key, managed.client);
4013
+ }
4014
+ }
4015
+ }
4016
+ evictForAdmission() {
4017
+ while (this.clients.size >= this.maxResidentClients) {
4018
+ const victim = this.leastRecentlyUsedIdleClient();
4019
+ if (!victim)
4020
+ return;
4021
+ this.clients.delete(victim.key);
4022
+ this.tombstoneStop(victim.key, victim.managed.client);
4023
+ }
4024
+ }
4025
+ leastRecentlyUsedIdleClient() {
4026
+ let candidate = null;
4027
+ for (const [key, managed] of this.clients) {
4028
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
4029
+ continue;
4030
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
4031
+ candidate = { key, managed };
3961
4032
  }
3962
4033
  }
4034
+ return candidate;
3963
4035
  }
3964
4036
  async tryDeleteIfOrphaned(key, managed) {
3965
4037
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
3966
4038
  this.clients.delete(key);
3967
- await stopClientBestEffort(managed.client);
4039
+ await this.tombstoneStop(key, managed.client);
3968
4040
  }
3969
4041
  }
3970
4042
  async getClient(root, server2, signal) {
@@ -3973,12 +4045,22 @@ class LspManager {
3973
4045
  }
3974
4046
  signal?.throwIfAborted();
3975
4047
  const key = this.getKey(root, server2.id);
4048
+ for (;; ) {
4049
+ const pendingStop = this.pendingStops.get(key);
4050
+ if (pendingStop === undefined)
4051
+ break;
4052
+ await awaitWithSignal2(pendingStop, signal);
4053
+ signal?.throwIfAborted();
4054
+ }
4055
+ if (this.disposed) {
4056
+ throw new Error("LspManager has been disposed");
4057
+ }
3976
4058
  let managed = this.clients.get(key);
3977
4059
  if (managed) {
3978
4060
  const t = this.now();
3979
4061
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3980
- await stopClientBestEffort(managed.client);
3981
4062
  this.clients.delete(key);
4063
+ await this.tombstoneStop(key, managed.client);
3982
4064
  managed = undefined;
3983
4065
  }
3984
4066
  }
@@ -3999,14 +4081,20 @@ class LspManager {
3999
4081
  signal.throwIfAborted();
4000
4082
  }
4001
4083
  if (!managed.client.isAlive()) {
4002
- await stopClientBestEffort(managed.client);
4003
- this.clients.delete(key);
4084
+ this.recordDeadGeneration(key);
4085
+ if (this.clients.get(key) === managed) {
4086
+ this.clients.delete(key);
4087
+ }
4088
+ await this.tombstoneStop(key, managed.client);
4004
4089
  return this.getClient(root, server2, signal);
4005
4090
  }
4091
+ this.markHealthyGeneration(key);
4006
4092
  managed.refCount++;
4007
4093
  managed.lastUsedAt = this.now();
4008
4094
  return managed.client;
4009
4095
  }
4096
+ this.evictForAdmission();
4097
+ this.ensureRespawnAllowed(key, root, server2.id);
4010
4098
  const client = this.clientFactory(root, server2);
4011
4099
  const initStartedAt = this.now();
4012
4100
  const initPromise = (async () => {
@@ -4030,7 +4118,7 @@ class LspManager {
4030
4118
  if (this.clients.get(key) === newManaged) {
4031
4119
  this.clients.delete(key);
4032
4120
  }
4033
- await stopClientBestEffort(client);
4121
+ await this.tombstoneStop(key, client);
4034
4122
  throw err;
4035
4123
  }
4036
4124
  newManaged.pendingWaiters--;
@@ -4041,6 +4129,15 @@ class LspManager {
4041
4129
  await this.tryDeleteIfOrphaned(key, newManaged);
4042
4130
  signal.throwIfAborted();
4043
4131
  }
4132
+ if (!client.isAlive()) {
4133
+ this.recordDeadGeneration(key);
4134
+ if (this.clients.get(key) === newManaged) {
4135
+ this.clients.delete(key);
4136
+ }
4137
+ await this.tombstoneStop(key, client);
4138
+ return this.getClient(root, server2, signal);
4139
+ }
4140
+ this.markHealthyGeneration(key);
4044
4141
  newManaged.refCount++;
4045
4142
  newManaged.lastUsedAt = this.now();
4046
4143
  return client;
@@ -4061,14 +4158,20 @@ class LspManager {
4061
4158
  if (client && managed.client !== client)
4062
4159
  return;
4063
4160
  this.clients.delete(key);
4064
- stopClientBestEffort(managed.client);
4161
+ this.tombstoneStop(key, managed.client);
4065
4162
  }
4066
4163
  warmupClient(root, server2) {
4067
4164
  if (this.disposed)
4068
4165
  return;
4069
4166
  const key = this.getKey(root, server2.id);
4070
- if (this.clients.has(key))
4167
+ if (this.clients.has(key) || this.pendingStops.has(key))
4071
4168
  return;
4169
+ this.evictForAdmission();
4170
+ try {
4171
+ this.ensureRespawnAllowed(key, root, server2.id);
4172
+ } catch {
4173
+ return;
4174
+ }
4072
4175
  const client = this.clientFactory(root, server2);
4073
4176
  const initStartedAt = this.now();
4074
4177
  const initPromise = (async () => {
@@ -4094,7 +4197,7 @@ class LspManager {
4094
4197
  if (this.clients.get(key) === managed) {
4095
4198
  this.clients.delete(key);
4096
4199
  }
4097
- stopClientBestEffort(client);
4200
+ this.tombstoneStop(key, client);
4098
4201
  });
4099
4202
  }
4100
4203
  isServerInitializing(root, serverId) {
@@ -4138,8 +4241,11 @@ class LspManager {
4138
4241
  for (const managed of this.clients.values()) {
4139
4242
  stopPromises.push(stopClientBestEffort(managed.client));
4140
4243
  }
4244
+ const tombstonedStops = [...this.pendingStops.values()];
4141
4245
  this.clients.clear();
4142
- await Promise.allSettled(stopPromises);
4246
+ this.respawnBudgets.clear();
4247
+ await Promise.allSettled([...stopPromises, ...tombstonedStops]);
4248
+ this.pendingStops.clear();
4143
4249
  }
4144
4250
  }
4145
4251
  var _defaultInstance = null;
@@ -4157,57 +4263,52 @@ async function disposeDefaultLspManager() {
4157
4263
  }
4158
4264
  }
4159
4265
 
4160
- // ../lsp-core/src/lsp/server-install-state.ts
4161
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4162
- import { dirname as dirname7 } from "node:path";
4163
- function getInstallDecisionsPath() {
4164
- return lspRequestContext().installDecisionsPath;
4165
- }
4166
- function loadInstallDecisions() {
4167
- const path2 = getInstallDecisionsPath();
4168
- if (!existsSync7(path2))
4169
- return {};
4170
- try {
4171
- const parsed = JSON.parse(readFileSync4(path2, "utf8"));
4172
- return isInstallDecisions(parsed) ? parsed : {};
4173
- } catch {
4174
- return {};
4266
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
4267
+ import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
4268
+ import { dirname as dirname7, join as join3 } from "node:path";
4269
+
4270
+ // ../lsp-core/src/lsp/workspace-markers.ts
4271
+ var GIT_WORKSPACE_MARKER = ".git";
4272
+ var PROJECT_WORKSPACE_MARKERS = [
4273
+ "package.json",
4274
+ "pyproject.toml",
4275
+ "Cargo.toml",
4276
+ "go.mod",
4277
+ "pom.xml",
4278
+ "build.gradle"
4279
+ ];
4280
+ var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
4281
+
4282
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
4283
+ function findWorkspaceRootOutsideContext(directory) {
4284
+ const marked = nearestMarkedAncestor(directory);
4285
+ if (marked !== undefined)
4286
+ return marked;
4287
+ return realpathSync4(nearestExistingAncestor(directory));
4288
+ }
4289
+ function nearestMarkedAncestor(directory) {
4290
+ let current = directory;
4291
+ for (;; ) {
4292
+ if (existsSync7(current) && WORKSPACE_MARKERS.some((marker) => existsSync7(join3(current, marker)))) {
4293
+ return realpathSync4(current);
4294
+ }
4295
+ const parent = dirname7(current);
4296
+ if (parent === current)
4297
+ return;
4298
+ current = parent;
4175
4299
  }
4176
4300
  }
4177
- function loadInstallDecision(serverId) {
4178
- return loadInstallDecisions()[serverId];
4179
- }
4180
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4181
- const decisions = loadInstallDecisions();
4182
- decisions[serverId] = { decision, decidedAt };
4183
- writeInstallDecisions(decisions);
4184
- }
4185
- function isInstallDecision(value) {
4186
- return value === "declined" || value === "allowed";
4187
- }
4188
- function writeInstallDecisions(decisions) {
4189
- const path2 = getInstallDecisionsPath();
4190
- mkdirSync3(dirname7(path2), { recursive: true });
4191
- const tmpPath = `${path2}.tmp`;
4192
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4193
- `, "utf8");
4194
- renameSync2(tmpPath, path2);
4195
- }
4196
- function isInstallDecisions(value) {
4197
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4198
- }
4199
- function isInstallDecisionRecord(value) {
4200
- if (!isRecord5(value))
4201
- return false;
4202
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4203
- }
4204
- function isRecord5(value) {
4205
- return typeof value === "object" && value !== null && !Array.isArray(value);
4301
+ function nearestExistingAncestor(directory) {
4302
+ let current = directory;
4303
+ while (!existsSync7(current)) {
4304
+ const parent = dirname7(current);
4305
+ if (parent === current)
4306
+ return current;
4307
+ current = parent;
4308
+ }
4309
+ return current;
4206
4310
  }
4207
4311
 
4208
- // ../lsp-core/src/lsp/config-loader.ts
4209
- import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
4210
-
4211
4312
  // ../lsp-core/src/lsp/server-definitions.ts
4212
4313
  var LSP_INSTALL_HINTS = {
4213
4314
  typescript: "npm install -g typescript-language-server typescript",
@@ -4253,6 +4354,26 @@ var LSP_INSTALL_HINTS = {
4253
4354
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
4254
4355
  razor: "Razor runs through the Roslyn language server (cohosting). " + "Install: dotnet tool install -g roslyn-language-server --prerelease (requires v5.8.0+). See https://github.com/dotnet/razor"
4255
4356
  };
4357
+ var LSP_LOCAL_INSTALL_HINTS = {
4358
+ typescript: "bun add -d typescript-language-server typescript",
4359
+ vue: "bun add -d @vue/language-server",
4360
+ eslint: "bun add -d vscode-langservers-extracted",
4361
+ oxlint: "bun add -d oxlint",
4362
+ biome: "bun add -d @biomejs/biome",
4363
+ svelte: "bun add -d svelte-language-server",
4364
+ astro: "bun add -d @astrojs/language-server",
4365
+ bash: "bun add -d bash-language-server",
4366
+ "bash-ls": "bun add -d bash-language-server",
4367
+ "yaml-ls": "bun add -d yaml-language-server",
4368
+ php: "bun add -d intelephense",
4369
+ prisma: "bun add -d prisma",
4370
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
4371
+ pyright: "uv add --dev pyright",
4372
+ basedpyright: "uv add --dev basedpyright",
4373
+ ruff: "uv add --dev ruff",
4374
+ ty: "uv add --dev ty",
4375
+ "ruby-lsp": "bundle add ruby-lsp --group development"
4376
+ };
4256
4377
  var BUILTIN_SERVERS = {
4257
4378
  typescript: {
4258
4379
  command: ["typescript-language-server", "--stdio"],
@@ -4355,7 +4476,56 @@ var BUILTIN_SERVERS = {
4355
4476
  }
4356
4477
  };
4357
4478
 
4479
+ // ../lsp-core/src/lsp/server-install-state.ts
4480
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4481
+ import { dirname as dirname8 } from "node:path";
4482
+ function getInstallDecisionsPath() {
4483
+ return lspRequestContext().installDecisionsPath;
4484
+ }
4485
+ function loadInstallDecisions() {
4486
+ const path2 = getInstallDecisionsPath();
4487
+ if (!existsSync8(path2))
4488
+ return {};
4489
+ try {
4490
+ const parsed = JSON.parse(readFileSync4(path2, "utf8"));
4491
+ return isInstallDecisions(parsed) ? parsed : {};
4492
+ } catch {
4493
+ return {};
4494
+ }
4495
+ }
4496
+ function loadInstallDecision(serverId) {
4497
+ return loadInstallDecisions()[serverId];
4498
+ }
4499
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4500
+ const decisions = loadInstallDecisions();
4501
+ decisions[serverId] = { decision, decidedAt };
4502
+ writeInstallDecisions(decisions);
4503
+ }
4504
+ function isInstallDecision(value) {
4505
+ return value === "declined" || value === "allowed";
4506
+ }
4507
+ function writeInstallDecisions(decisions) {
4508
+ const path2 = getInstallDecisionsPath();
4509
+ mkdirSync3(dirname8(path2), { recursive: true });
4510
+ const tmpPath = `${path2}.tmp`;
4511
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4512
+ `, "utf8");
4513
+ renameSync2(tmpPath, path2);
4514
+ }
4515
+ function isInstallDecisions(value) {
4516
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4517
+ }
4518
+ function isInstallDecisionRecord(value) {
4519
+ if (!isRecord5(value))
4520
+ return false;
4521
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4522
+ }
4523
+ function isRecord5(value) {
4524
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4525
+ }
4526
+
4358
4527
  // ../lsp-core/src/lsp/config-loader.ts
4528
+ import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
4359
4529
  function getProjectConfigPaths() {
4360
4530
  return lspRequestContext().projectConfigPaths;
4361
4531
  }
@@ -4363,7 +4533,7 @@ function getUserConfigPath() {
4363
4533
  return lspRequestContext().userConfigPath;
4364
4534
  }
4365
4535
  function loadJsonFile(path2) {
4366
- if (!existsSync8(path2))
4536
+ if (!existsSync9(path2))
4367
4537
  return null;
4368
4538
  try {
4369
4539
  const parsed = JSON.parse(readFileSync5(path2, "utf-8"));
@@ -4551,54 +4721,155 @@ function getDisabledServerIds() {
4551
4721
  }
4552
4722
 
4553
4723
  // ../lsp-core/src/lsp/server-installation.ts
4554
- import { existsSync as existsSync9 } from "node:fs";
4555
- import { delimiter as delimiter3, join as join3 } from "node:path";
4556
- function isServerInstalled(command, _workingDirectory) {
4557
- if (command.length === 0)
4558
- return false;
4559
- const [cmd] = command;
4560
- if (!cmd)
4561
- return false;
4562
- if (cmd.includes("/") || cmd.includes("\\")) {
4563
- if (existsSync9(cmd))
4564
- return true;
4724
+ import { existsSync as existsSync10 } from "node:fs";
4725
+ import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
4726
+ var LOCAL_BIN_RULES = [
4727
+ {
4728
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
4729
+ binDirs: [join4("node_modules", ".bin")]
4730
+ },
4731
+ {
4732
+ markers: [
4733
+ "pyproject.toml",
4734
+ "ty.toml",
4735
+ "requirements.txt",
4736
+ "setup.py",
4737
+ "setup.cfg",
4738
+ "Pipfile",
4739
+ "pyrightconfig.json",
4740
+ "ruff.toml",
4741
+ ".ruff.toml"
4742
+ ],
4743
+ binDirs: [
4744
+ join4(".venv", "bin"),
4745
+ join4(".venv", "Scripts"),
4746
+ join4("venv", "bin"),
4747
+ join4("venv", "Scripts"),
4748
+ join4(".env", "bin"),
4749
+ join4(".env", "Scripts")
4750
+ ]
4751
+ },
4752
+ {
4753
+ markers: ["Gemfile", "Gemfile.lock"],
4754
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
4755
+ },
4756
+ {
4757
+ markers: ["go.mod", "go.sum", "go.work"],
4758
+ binDirs: ["bin"]
4565
4759
  }
4566
- const isWindows = process.platform === "win32";
4567
- let exts = [""];
4568
- if (isWindows) {
4569
- const pathExt = process.env["PATHEXT"] ?? "";
4570
- if (pathExt) {
4571
- const systemExts = pathExt.split(";").filter(Boolean);
4572
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4573
- } else {
4574
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
4760
+ ];
4761
+ var resolutionCache = new Map;
4762
+ var probeCount = 0;
4763
+ function probe(path2) {
4764
+ probeCount += 1;
4765
+ return existsSync10(path2);
4766
+ }
4767
+ function executableSuffixes(platform, pathExt) {
4768
+ if (platform !== "win32")
4769
+ return [""];
4770
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
4771
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
4772
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4773
+ }
4774
+ function probeWithSuffixes(directory, command, suffixes) {
4775
+ for (const suffix of suffixes) {
4776
+ const candidate = join4(directory, command + suffix);
4777
+ if (probe(candidate))
4778
+ return candidate;
4779
+ }
4780
+ return null;
4781
+ }
4782
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
4783
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
4784
+ let current = resolve7(workingDirectory);
4785
+ while (true) {
4786
+ for (const rule of LOCAL_BIN_RULES) {
4787
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
4788
+ continue;
4789
+ for (const binDir of rule.binDirs) {
4790
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
4791
+ if (found !== null)
4792
+ return found;
4793
+ }
4575
4794
  }
4795
+ if (probe(join4(current, ".git")))
4796
+ return null;
4797
+ if (boundary !== undefined && current === boundary)
4798
+ return null;
4799
+ const parent = dirname9(current);
4800
+ if (parent === current)
4801
+ return null;
4802
+ current = parent;
4576
4803
  }
4577
- let pathEnv = process.env["PATH"] ?? "";
4578
- if (isWindows && !pathEnv) {
4804
+ }
4805
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
4806
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
4807
+ if (platform === "win32" && !pathEnv) {
4579
4808
  pathEnv = process.env["Path"] ?? "";
4580
4809
  }
4581
- const paths = pathEnv.split(delimiter3);
4582
- for (const p of paths) {
4583
- for (const suffix of exts) {
4584
- if (existsSync9(join3(p, cmd + suffix))) {
4585
- return true;
4586
- }
4587
- }
4810
+ for (const entry of pathEnv.split(delimiter3)) {
4811
+ if (entry.length === 0)
4812
+ continue;
4813
+ const found = probeWithSuffixes(entry, command, suffixes);
4814
+ if (found !== null)
4815
+ return found;
4588
4816
  }
4589
- if (cmd === "node")
4590
- return true;
4591
- return false;
4817
+ return null;
4818
+ }
4819
+ function resolveServerBinary(command, workingDirectory, options = {}) {
4820
+ if (command.length === 0)
4821
+ return null;
4822
+ const [cmd] = command;
4823
+ if (cmd === undefined || cmd.length === 0)
4824
+ return null;
4825
+ const platform = options.platform ?? process.platform;
4826
+ const suffixes = executableSuffixes(platform, options.pathExt);
4827
+ if (cmd.includes("/") || cmd.includes("\\")) {
4828
+ const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
4829
+ return probe(explicit) ? explicit : null;
4830
+ }
4831
+ const cacheKey = JSON.stringify([
4832
+ workingDirectory ?? "",
4833
+ cmd,
4834
+ platform,
4835
+ options.stopAt ?? "",
4836
+ options.pathExt ?? "",
4837
+ options.pathEnv ?? process.env["PATH"] ?? ""
4838
+ ]);
4839
+ const cached = resolutionCache.get(cacheKey);
4840
+ if (cached !== undefined)
4841
+ return cached;
4842
+ let resolved = null;
4843
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
4844
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
4845
+ }
4846
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
4847
+ if (resolved === null && cmd === "node")
4848
+ resolved = cmd;
4849
+ resolutionCache.set(cacheKey, resolved);
4850
+ return resolved;
4851
+ }
4852
+ function isServerInstalled(command, workingDirectory, options = {}) {
4853
+ if (command.length === 0)
4854
+ return false;
4855
+ return resolveServerBinary(command, workingDirectory, options) !== null;
4592
4856
  }
4593
4857
 
4594
4858
  // ../lsp-core/src/lsp/server-resolution.ts
4859
+ function withResolvedCommand(command, binaryPath) {
4860
+ return [binaryPath, ...command.slice(1)];
4861
+ }
4595
4862
  function findServerForExtension(ext) {
4596
4863
  const servers = getMergedServers();
4864
+ const workingDirectory = contextCwd();
4597
4865
  for (const server2 of servers) {
4598
- if (server2.extensions.includes(ext) && isServerInstalled(server2.command)) {
4866
+ if (!server2.extensions.includes(ext))
4867
+ continue;
4868
+ const binaryPath = resolveServerBinary(server2.command, workingDirectory);
4869
+ if (binaryPath !== null) {
4599
4870
  const resolvedServer = {
4600
4871
  id: server2.id,
4601
- command: server2.command,
4872
+ command: withResolvedCommand(server2.command, binaryPath),
4602
4873
  extensions: server2.extensions,
4603
4874
  priority: server2.priority
4604
4875
  };
@@ -4645,6 +4916,7 @@ function findServerForExtension(ext) {
4645
4916
  function getAllServers() {
4646
4917
  const servers = getMergedServers();
4647
4918
  const disabled = getDisabledServerIds();
4919
+ const workingDirectory = contextCwd();
4648
4920
  const result = [];
4649
4921
  const seen = new Set;
4650
4922
  for (const server2 of servers) {
@@ -4652,7 +4924,7 @@ function getAllServers() {
4652
4924
  continue;
4653
4925
  result.push({
4654
4926
  id: server2.id,
4655
- installed: isServerInstalled(server2.command),
4927
+ installed: isServerInstalled(server2.command, workingDirectory),
4656
4928
  extensions: server2.extensions,
4657
4929
  disabled: false,
4658
4930
  source: server2.source,
@@ -4666,7 +4938,7 @@ function getAllServers() {
4666
4938
  const builtin = BUILTIN_SERVERS[id];
4667
4939
  result.push({
4668
4940
  id,
4669
- installed: builtin ? isServerInstalled(builtin.command) : false,
4941
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
4670
4942
  extensions: builtin?.extensions ?? [],
4671
4943
  disabled: true,
4672
4944
  source: "disabled",
@@ -4677,7 +4949,6 @@ function getAllServers() {
4677
4949
  }
4678
4950
 
4679
4951
  // ../lsp-core/src/lsp/client-wrapper.ts
4680
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
4681
4952
  function isDirectoryPath(filePath) {
4682
4953
  try {
4683
4954
  return statSync4(filePath).isDirectory();
@@ -4686,32 +4957,90 @@ function isDirectoryPath(filePath) {
4686
4957
  }
4687
4958
  }
4688
4959
  function findWorkspaceRoot(filePath) {
4689
- const abs = resolvePathInsideContext(filePath);
4960
+ const cwd = contextCwd();
4961
+ const abs = resolveReadablePathInsideContext(filePath);
4690
4962
  let dir = abs;
4691
4963
  if (!isDirectoryPath(dir)) {
4692
- dir = dirname8(dir);
4693
- }
4694
- let prevDir = "";
4695
- while (dir !== prevDir) {
4696
- for (const marker of WORKSPACE_MARKERS) {
4697
- if (existsSync10(join4(dir, marker))) {
4698
- return dir;
4964
+ dir = dirname10(dir);
4965
+ }
4966
+ if (!isPathInside(cwd, abs))
4967
+ return findWorkspaceRootOutsideContext(dir);
4968
+ const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4969
+ let nearestPackageRoot;
4970
+ while (isPathInside(cwd, dir)) {
4971
+ const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4972
+ if (canonicalDir !== undefined) {
4973
+ if (existsSync11(join5(dir, GIT_WORKSPACE_MARKER))) {
4974
+ return canonicalDir;
4975
+ }
4976
+ if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
4977
+ nearestPackageRoot = canonicalDir;
4699
4978
  }
4700
4979
  }
4701
- prevDir = dir;
4702
- dir = dirname8(dir);
4980
+ if (dir === cwd)
4981
+ break;
4982
+ dir = dirname10(dir);
4703
4983
  }
4704
- return dirname8(abs);
4984
+ return nearestPackageRoot ?? fallbackRoot;
4985
+ }
4986
+ function hasProjectWorkspaceMarker(directory) {
4987
+ return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync11(join5(directory, marker)));
4988
+ }
4989
+ function resolveReadablePathInsideContext(filePath) {
4990
+ const cwd = contextCwd();
4991
+ const abs = resolve8(cwd, filePath);
4992
+ if (isPathInside(cwd, abs))
4993
+ return abs;
4994
+ const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4995
+ if (rebased !== undefined)
4996
+ return rebased;
4997
+ return canonicalizeExistingOrNearestAncestor(abs);
4705
4998
  }
4706
4999
  function resolvePathInsideContext(filePath) {
4707
5000
  const cwd = contextCwd();
4708
- const abs = resolve7(cwd, filePath);
5001
+ const abs = resolveReadablePathInsideContext(filePath);
4709
5002
  const canonical = canonicalizeExistingOrNearestAncestor(abs);
4710
5003
  if (!isPathInside(cwd, canonical)) {
4711
5004
  throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
4712
5005
  }
4713
5006
  return canonical;
4714
5007
  }
5008
+ function rebaseThroughCanonicalAncestor(path2, cwd) {
5009
+ let current = path2;
5010
+ const suffix = [];
5011
+ while (true) {
5012
+ if (existsSync11(current)) {
5013
+ const canonical = realpathSync5(current);
5014
+ if (isPathInside(cwd, canonical))
5015
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
5016
+ }
5017
+ const parent = dirname10(current);
5018
+ if (parent === current)
5019
+ return;
5020
+ suffix.unshift(basename3(current));
5021
+ current = parent;
5022
+ }
5023
+ }
5024
+ function existingDirectoryInsideContext(directory, cwd) {
5025
+ if (!existsSync11(directory))
5026
+ return;
5027
+ const canonical = realpathSync5(directory);
5028
+ if (!statSync4(canonical).isDirectory())
5029
+ return;
5030
+ return isPathInside(cwd, canonical) ? canonical : undefined;
5031
+ }
5032
+ function nearestExistingDirectoryInsideContext(directory, cwd) {
5033
+ let current = directory;
5034
+ while (isPathInside(cwd, current)) {
5035
+ const canonical = existingDirectoryInsideContext(current, cwd);
5036
+ if (canonical !== undefined)
5037
+ return canonical;
5038
+ if (current === cwd)
5039
+ return;
5040
+ current = dirname10(current);
5041
+ }
5042
+ return;
5043
+ }
4715
5044
  function formatServerLookupError(result) {
4716
5045
  if (result.status === "not_installed") {
4717
5046
  return formatNotInstalled(result);
@@ -4735,6 +5064,19 @@ function formatServerLookupError(result) {
4735
5064
  ].join(`
4736
5065
  `);
4737
5066
  }
5067
+ function formatInstallOptions(serverId, installHint) {
5068
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
5069
+ if (localHint === undefined) {
5070
+ return ["To install, run:", ` ${installHint}`];
5071
+ }
5072
+ return [
5073
+ "To install in THIS repository (preferred — no global install needed):",
5074
+ ` ${localHint}`,
5075
+ "",
5076
+ "Or install it globally:",
5077
+ ` ${installHint}`
5078
+ ];
5079
+ }
4738
5080
  function formatNotInstalled(result) {
4739
5081
  const { server: server2, installHint } = result;
4740
5082
  const extensions = server2.extensions.join(", ");
@@ -4749,19 +5091,19 @@ function formatNotInstalled(result) {
4749
5091
  `Command not found: ${server2.command[0]}`,
4750
5092
  ""
4751
5093
  ];
5094
+ const installOptions = formatInstallOptions(server2.id, installHint);
4752
5095
  if (decision === "allowed") {
4753
5096
  return [
4754
5097
  ...header,
4755
5098
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
4756
- ` ${installHint}`
5099
+ ...installOptions.slice(1)
4757
5100
  ].join(`
4758
5101
  `);
4759
5102
  }
4760
5103
  if (!context.capabilities.installDecisionTool) {
4761
5104
  return [
4762
5105
  ...header,
4763
- "To install, run:",
4764
- ` ${installHint}`,
5106
+ ...installOptions,
4765
5107
  "",
4766
5108
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4767
5109
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -4770,8 +5112,7 @@ function formatNotInstalled(result) {
4770
5112
  }
4771
5113
  return [
4772
5114
  ...header,
4773
- "To install, run:",
4774
- ` ${installHint}`,
5115
+ ...installOptions,
4775
5116
  "",
4776
5117
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4777
5118
  "- If the user agrees: run the install command above, then retry this tool.",
@@ -4782,7 +5123,7 @@ function formatNotInstalled(result) {
4782
5123
  ].join(`
4783
5124
  `);
4784
5125
  }
4785
- var READ_ONLY_RETRY_TOOLS = new Set([
5126
+ var READ_ONLY_TOOLS = new Set([
4786
5127
  "diagnostics",
4787
5128
  "definition",
4788
5129
  "references",
@@ -4791,7 +5132,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
4791
5132
  "prepareRename"
4792
5133
  ]);
4793
5134
  async function withLspClient(filePath, fn, toolName, options = {}) {
4794
- const absPath = resolvePathInsideContext(filePath);
5135
+ const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
4795
5136
  if (isDirectoryPath(absPath)) {
4796
5137
  throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
4797
5138
  }
@@ -4806,9 +5147,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4806
5147
  const acquireAndCall = async (allowRetry) => {
4807
5148
  const client = await manager.getClient(root, server2, options.signal);
4808
5149
  try {
4809
- return await fn(client, root);
5150
+ return await fn(client, root, absPath);
4810
5151
  } catch (err) {
4811
- if (allowRetry && READ_ONLY_RETRY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
5152
+ if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4812
5153
  manager.invalidateClient(root, server2.id, client);
4813
5154
  return acquireAndCall(false);
4814
5155
  }
@@ -4826,8 +5167,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4826
5167
  }
4827
5168
 
4828
5169
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4829
- import { existsSync as existsSync11, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
4830
- import { join as join5, resolve as resolve8 } from "node:path";
5170
+ import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
5171
+ import { join as join6, resolve as resolve9 } from "node:path";
4831
5172
 
4832
5173
  // ../lsp-core/src/lsp/formatters.ts
4833
5174
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -4957,7 +5298,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
4957
5298
  for (const entry of entries) {
4958
5299
  if (files.length >= maxFiles)
4959
5300
  return;
4960
- const fullPath = join5(currentDir, entry);
5301
+ const fullPath = join6(currentDir, entry);
4961
5302
  let stat;
4962
5303
  try {
4963
5304
  stat = lstatSync5(fullPath);
@@ -4982,8 +5323,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4982
5323
  if (!extension.startsWith(".")) {
4983
5324
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4984
5325
  }
4985
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4986
- if (!existsSync11(absDir)) {
5326
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
5327
+ if (!existsSync12(absDir)) {
4987
5328
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4988
5329
  }
4989
5330
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
@@ -5070,7 +5411,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5070
5411
 
5071
5412
  // ../lsp-core/src/lsp/infer-extension.ts
5072
5413
  import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
5073
- import { join as join6 } from "node:path";
5414
+ import { join as join7 } from "node:path";
5074
5415
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
5075
5416
  var MAX_SCAN_ENTRIES = 500;
5076
5417
  function inferExtensionFromDirectory(directory) {
@@ -5088,7 +5429,7 @@ function inferExtensionFromDirectory(directory) {
5088
5429
  for (const entry of entries) {
5089
5430
  if (scanned >= MAX_SCAN_ENTRIES)
5090
5431
  return;
5091
- const fullPath = join6(dir, entry);
5432
+ const fullPath = join7(dir, entry);
5092
5433
  let stat;
5093
5434
  try {
5094
5435
  stat = lstatSync6(fullPath);
@@ -5263,7 +5604,7 @@ async function executeLspDiagnostics(params, signal) {
5263
5604
  const filePath = requireString(params, "filePath");
5264
5605
  const severity = severityFilter(params);
5265
5606
  try {
5266
- const absPath = resolvePathInsideContext(filePath);
5607
+ const absPath = resolveReadablePathInsideContext(filePath);
5267
5608
  if (isDirectoryPath(absPath)) {
5268
5609
  const extension = inferExtensionFromDirectory(absPath);
5269
5610
  if (!extension) {
@@ -5292,7 +5633,7 @@ async function executeLspDiagnostics(params, signal) {
5292
5633
  };
5293
5634
  return text(output2.output, details2);
5294
5635
  }
5295
- const result = await withLspClient(filePath, async (client) => client.diagnostics(filePath, signal), "diagnostics", clientOptions(signal));
5636
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
5296
5637
  if (result.transientError) {
5297
5638
  const message = result.transientError.message;
5298
5639
  const details2 = {
@@ -5339,6 +5680,96 @@ async function executeLspDiagnostics(params, signal) {
5339
5680
  throw error;
5340
5681
  }
5341
5682
  }
5683
+ // ../lsp-core/src/lsp/format-document.ts
5684
+ import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
5685
+ var DEFAULT_FORMATTING_OPTIONS = {
5686
+ tabSize: 4,
5687
+ insertSpaces: false,
5688
+ trimTrailingWhitespace: true,
5689
+ insertFinalNewline: true,
5690
+ trimFinalNewlines: true
5691
+ };
5692
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
5693
+ async function formatDocumentWithClient(client, filePath, options = {}) {
5694
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
5695
+ if (edits === null)
5696
+ return { status: "unavailable", reason: "capability_not_advertised" };
5697
+ if (edits.length === 0)
5698
+ return UNCHANGED;
5699
+ const before = readFileSync6(filePath, "utf-8");
5700
+ const normalized = normalizeTextEdits(before, edits, 0);
5701
+ if (normalized.text === before)
5702
+ return UNCHANGED;
5703
+ writeAtomically(filePath, normalized.text);
5704
+ await client.openFile(filePath);
5705
+ return {
5706
+ status: "formatted",
5707
+ ...lineDelta(normalized.edits)
5708
+ };
5709
+ }
5710
+ function lineDelta(edits) {
5711
+ let linesAdded = 0;
5712
+ let linesRemoved = 0;
5713
+ for (const edit of edits) {
5714
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
5715
+ linesAdded += edit.newText.split(`
5716
+ `).length;
5717
+ }
5718
+ return { linesAdded, linesRemoved };
5719
+ }
5720
+ function writeAtomically(filePath, content) {
5721
+ const tempPath = `${filePath}.omo-format.tmp`;
5722
+ writeFileSync3(tempPath, content, "utf-8");
5723
+ try {
5724
+ renameSync3(tempPath, filePath);
5725
+ } catch (error) {
5726
+ try {
5727
+ unlinkSync2(tempPath);
5728
+ } catch {}
5729
+ throw error;
5730
+ }
5731
+ }
5732
+
5733
+ // ../lsp-core/src/tools/format.ts
5734
+ async function executeLspFormat(params, signal) {
5735
+ const filePath = requireString(params, "filePath");
5736
+ try {
5737
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
5738
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
5739
+ } catch (error) {
5740
+ const missingDependency = missingDependencyResult(error, {
5741
+ filePath,
5742
+ status: "unavailable",
5743
+ reason: "server_unavailable",
5744
+ linesAdded: 0,
5745
+ linesRemoved: 0
5746
+ });
5747
+ if (missingDependency)
5748
+ return missingDependency;
5749
+ throw error;
5750
+ }
5751
+ }
5752
+ function formatDetails(filePath, result) {
5753
+ if (result.status === "unavailable") {
5754
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
5755
+ }
5756
+ return {
5757
+ filePath,
5758
+ status: result.status,
5759
+ linesAdded: result.linesAdded,
5760
+ linesRemoved: result.linesRemoved
5761
+ };
5762
+ }
5763
+ function describeResult(filePath, result) {
5764
+ if (result.status === "unavailable") {
5765
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
5766
+ }
5767
+ if (result.status === "unchanged") {
5768
+ return `Already formatted: ${filePath}`;
5769
+ }
5770
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
5771
+ }
5772
+
5342
5773
  // ../lsp-core/src/tools/install-decision.ts
5343
5774
  async function executeLspInstallDecision(params) {
5344
5775
  const serverId = requireString(params, "server_id");
@@ -5367,7 +5798,7 @@ async function executeLspGotoDefinition(params, signal) {
5367
5798
  const line = requireNumber(params, "line");
5368
5799
  const character = requireNumber(params, "character");
5369
5800
  try {
5370
- const result = await withLspClient(filePath, async (client) => client.definition(filePath, line, character, signal), "definition", clientOptions(signal));
5801
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
5371
5802
  const locations = !result ? [] : Array.isArray(result) ? result : [result];
5372
5803
  const details = { filePath, line, character, locations };
5373
5804
  if (locations.length === 0)
@@ -5392,7 +5823,7 @@ async function executeLspFindReferences(params, signal) {
5392
5823
  const character = requireNumber(params, "character");
5393
5824
  const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
5394
5825
  try {
5395
- const result = await withLspClient(filePath, async (client) => client.references(filePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5826
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5396
5827
  const references = Array.isArray(result) ? result : [];
5397
5828
  const total = references.length;
5398
5829
  const truncated = total > DEFAULT_MAX_REFERENCES;
@@ -5434,7 +5865,7 @@ async function executeLspPrepareRename(params, signal) {
5434
5865
  const line = requireNumber(params, "line");
5435
5866
  const character = requireNumber(params, "character");
5436
5867
  try {
5437
- const result = await withLspClient(filePath, async (client) => client.prepareRename(filePath, line, character, signal), "prepareRename", clientOptions(signal));
5868
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
5438
5869
  const details = { filePath, line, character, result };
5439
5870
  return text(formatPrepareRenameResult(result), details);
5440
5871
  } catch (error) {
@@ -5455,7 +5886,7 @@ async function executeLspRename(params, signal) {
5455
5886
  const character = requireNumber(params, "character");
5456
5887
  const newName = requireString(params, "newName");
5457
5888
  try {
5458
- const result = await withLspClient(filePath, async (client) => client.rename(filePath, line, character, newName, signal), "rename", clientOptions(signal));
5889
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
5459
5890
  const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
5460
5891
  return text(formatApplyResult(result.apply), details, !result.apply.success);
5461
5892
  } catch (error) {
@@ -5535,7 +5966,7 @@ async function executeLspSymbols(params, signal) {
5535
5966
  const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
5536
5967
  return formatSymbolsResult(filePath, scope, symbols2, limit, query);
5537
5968
  }
5538
- const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(filePath, signal), "documentSymbols", clientOptions(signal));
5969
+ const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
5539
5970
  return formatSymbolsResult(filePath, scope, symbols, limit);
5540
5971
  } catch (error) {
5541
5972
  const query = optionalString(params, "query");
@@ -5671,6 +6102,16 @@ var LSP_MCP_TOOLS = [
5671
6102
  }, ["filePath", "line", "character", "newName"]),
5672
6103
  execute: executeLspRename
5673
6104
  },
6105
+ {
6106
+ name: "format",
6107
+ aliases: ["lsp_format"],
6108
+ title: "LSP Format",
6109
+ description: "Format a source file with its language server and write the returned edits to disk.",
6110
+ inputSchema: objectSchema({
6111
+ filePath: { type: "string", description: "Source file path to format." }
6112
+ }, ["filePath"]),
6113
+ execute: executeLspFormat
6114
+ },
5674
6115
  {
5675
6116
  name: "install_decision",
5676
6117
  aliases: ["lsp_install_decision"],
@@ -5771,7 +6212,10 @@ function requestedProtocolVersion(params) {
5771
6212
  var CONTEXT_KEY = "_context";
5772
6213
 
5773
6214
  class InvalidDaemonRequestError extends Error {
5774
- name = "InvalidDaemonRequestError";
6215
+ constructor() {
6216
+ super(...arguments);
6217
+ this.name = "InvalidDaemonRequestError";
6218
+ }
5775
6219
  }
5776
6220
  function extractRequestContext(raw) {
5777
6221
  if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
@@ -5887,14 +6331,17 @@ async function callToolViaDaemon(name, args, options) {
5887
6331
  function callDiagnosticsViaDaemon(filePath, options) {
5888
6332
  return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
5889
6333
  }
6334
+ function callFormatViaDaemon(filePath, options) {
6335
+ return callToolViaDaemon("format", { filePath }, options);
6336
+ }
5890
6337
  function currentRequestContext(env = process.env) {
5891
6338
  const cwd = process.cwd();
5892
6339
  const home = env["HOME"] ?? homedir3();
5893
6340
  return parseLspRequestContext({
5894
6341
  cwd,
5895
- projectConfigPaths: [join7(cwd, ".codex", "lsp-client.json")],
5896
- userConfigPath: join7(home, ".codex", "lsp-client.json"),
5897
- installDecisionsPath: join7(home, ".codex", "lsp-install-decisions.json"),
6342
+ projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
6343
+ userConfigPath: join8(home, ".codex", "lsp-client.json"),
6344
+ installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
5898
6345
  capabilities: { installDecisionTool: true }
5899
6346
  });
5900
6347
  }
@@ -5909,7 +6356,7 @@ function withContext(args, context) {
5909
6356
  function ensureDaemonAvailable(paths, ensure, signal) {
5910
6357
  if (!signal)
5911
6358
  return ensure(paths);
5912
- return new Promise((resolve9, reject) => {
6359
+ return new Promise((resolve10, reject) => {
5913
6360
  let settled = false;
5914
6361
  const finish = (run) => {
5915
6362
  if (settled)
@@ -5924,11 +6371,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
5924
6371
  return;
5925
6372
  }
5926
6373
  signal.addEventListener("abort", onAbort, { once: true });
5927
- Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve9()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
6374
+ Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
5928
6375
  });
5929
6376
  }
5930
6377
  function sendToolCall(paths, token, name, args, options) {
5931
- return new Promise((resolve9, reject) => {
6378
+ return new Promise((resolve10, reject) => {
5932
6379
  const socket = connect(paths.socket);
5933
6380
  const requestId = allocateProxyRequestId();
5934
6381
  let settled = false;
@@ -5981,7 +6428,7 @@ function sendToolCall(paths, token, name, args, options) {
5981
6428
  }
5982
6429
  const result = toToolResult(message, requestId);
5983
6430
  if (result)
5984
- finish(() => resolve9(result));
6431
+ finish(() => resolve10(result));
5985
6432
  else
5986
6433
  finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
5987
6434
  });
@@ -6027,18 +6474,15 @@ function isRetryableTool(name) {
6027
6474
  }
6028
6475
 
6029
6476
  // src/client.ts
6030
- import { statSync as statSync5 } from "node:fs";
6031
- import { isAbsolute as isAbsolute5 } from "node:path";
6032
6477
  var OMO_LSP_DAEMON_DIR2 = "OMO_LSP_DAEMON_DIR";
6033
6478
  var OMO_LSP_DAEMON_CLI2 = "OMO_LSP_DAEMON_CLI";
6034
6479
  var OMO_LSP_DAEMON_VERSION2 = "OMO_LSP_DAEMON_VERSION";
6035
6480
  var DAEMON_VERSION_PATTERN2 = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
6036
6481
 
6037
6482
  class InvalidRuntimeOverrideError2 extends Error {
6038
- code = "invalid_runtime_override";
6039
- reason;
6040
6483
  constructor(reason, message) {
6041
6484
  super(message);
6485
+ this.code = "invalid_runtime_override";
6042
6486
  this.name = "InvalidRuntimeOverrideError";
6043
6487
  this.reason = reason;
6044
6488
  }
@@ -6058,12 +6502,12 @@ function resolveDaemonRuntime2(env, defaults) {
6058
6502
  throw new InvalidRuntimeOverrideError2("paired_values_required", `${OMO_LSP_DAEMON_CLI2} and ${OMO_LSP_DAEMON_VERSION2} must be set together`);
6059
6503
  }
6060
6504
  if (!hasCliOverride || !hasVersionOverride) {
6061
- if (!isAbsolute5(defaults.cliPath)) {
6505
+ if (!isAbsolute6(defaults.cliPath)) {
6062
6506
  throw new InvalidRuntimeOverrideError2("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
6063
6507
  }
6064
6508
  return { cliPath: defaults.cliPath, version: validateDaemonVersion2(defaults.version) };
6065
6509
  }
6066
- if (!isAbsolute5(cliOverride)) {
6510
+ if (!isAbsolute6(cliOverride)) {
6067
6511
  throw new InvalidRuntimeOverrideError2("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI2} must be an absolute path to an existing regular file`);
6068
6512
  }
6069
6513
  const stat = statSync5(cliOverride, { throwIfNoEntry: false });
@@ -6081,17 +6525,21 @@ function callToolViaDaemon2(name, args, options) {
6081
6525
  function callDiagnosticsViaDaemon2(filePath, options) {
6082
6526
  return callDiagnosticsViaDaemon(filePath, options);
6083
6527
  }
6528
+ function callFormatViaDaemon2(filePath, options) {
6529
+ return callFormatViaDaemon(filePath, options);
6530
+ }
6084
6531
  function currentRequestContext2(env = process.env) {
6085
6532
  return currentRequestContext(env);
6086
6533
  }
6087
6534
  export {
6088
- validateDaemonVersion2 as validateDaemonVersion,
6089
- resolveDaemonRuntime2 as resolveDaemonRuntime,
6090
- currentRequestContext2 as currentRequestContext,
6091
- callToolViaDaemon2 as callToolViaDaemon,
6092
- callDiagnosticsViaDaemon2 as callDiagnosticsViaDaemon,
6093
- OMO_LSP_DAEMON_VERSION2 as OMO_LSP_DAEMON_VERSION,
6094
- OMO_LSP_DAEMON_DIR2 as OMO_LSP_DAEMON_DIR,
6535
+ InvalidRuntimeOverrideError2 as InvalidRuntimeOverrideError,
6095
6536
  OMO_LSP_DAEMON_CLI2 as OMO_LSP_DAEMON_CLI,
6096
- InvalidRuntimeOverrideError2 as InvalidRuntimeOverrideError
6537
+ OMO_LSP_DAEMON_DIR2 as OMO_LSP_DAEMON_DIR,
6538
+ OMO_LSP_DAEMON_VERSION2 as OMO_LSP_DAEMON_VERSION,
6539
+ callDiagnosticsViaDaemon2 as callDiagnosticsViaDaemon,
6540
+ callFormatViaDaemon2 as callFormatViaDaemon,
6541
+ callToolViaDaemon2 as callToolViaDaemon,
6542
+ currentRequestContext2 as currentRequestContext,
6543
+ resolveDaemonRuntime2 as resolveDaemonRuntime,
6544
+ validateDaemonVersion2 as validateDaemonVersion
6097
6545
  };