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

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 (583) 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 +22572 -20322
  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 +22190 -19917
  38. package/dist/config/schema/commands.d.ts +1 -1
  39. package/dist/config/schema/hooks.d.ts +1 -1
  40. package/dist/config/schema/oh-my-opencode-config.d.ts +4 -1
  41. package/dist/config/schema/ulw-execute.d.ts +5 -0
  42. package/dist/config/validate.d.ts +2 -0
  43. package/dist/create-hooks.d.ts +3 -1
  44. package/dist/features/btw-side/btw-command-draft.d.ts +7 -0
  45. package/dist/features/btw-side/context-injector.d.ts +15 -0
  46. package/dist/features/btw-side/index.d.ts +8 -0
  47. package/dist/features/btw-side/metadata.d.ts +15 -0
  48. package/dist/features/btw-side/parent-context-budget.d.ts +9 -0
  49. package/dist/features/btw-side/server-session-registry.d.ts +8 -0
  50. package/dist/features/btw-side/tui-adoption-cache.d.ts +13 -0
  51. package/dist/features/btw-side/tui-adoption-guard.d.ts +5 -0
  52. package/dist/features/btw-side/tui-controller-types.d.ts +68 -0
  53. package/dist/features/btw-side/tui-controller.d.ts +19 -0
  54. package/dist/features/btw-side/tui-escape-return.d.ts +12 -0
  55. package/dist/features/btw-side/tui-keymap.d.ts +17 -0
  56. package/dist/features/btw-side/tui-parent-validator.d.ts +6 -0
  57. package/dist/features/btw-side/tui-picker-options.d.ts +20 -0
  58. package/dist/features/btw-side/tui-picker.d.ts +9 -0
  59. package/dist/features/btw-side/tui-prompt-queue.d.ts +8 -0
  60. package/dist/features/btw-side/tui-session-bridge.d.ts +11 -0
  61. package/dist/features/btw-side/tui-session-catalog.d.ts +35 -0
  62. package/dist/features/btw-side/tui-side-removal.d.ts +11 -0
  63. package/dist/features/btw-side/tui-side-start.d.ts +9 -0
  64. package/dist/features/btw-side/tui-wiring.d.ts +8 -0
  65. package/dist/features/builtin-commands/templates/ulw-execute.d.ts +1 -0
  66. package/dist/features/builtin-commands/types.d.ts +1 -1
  67. package/dist/features/opengateway-provider/index.d.ts +13 -0
  68. package/dist/features/team-mode/tools/messaging-fallback-wake.d.ts +15 -0
  69. package/dist/hooks/atlas/atlas-hook.d.ts +1 -0
  70. package/dist/hooks/atlas/atlas-lifecycle-store.d.ts +50 -0
  71. package/dist/hooks/atlas/event-handler.d.ts +1 -0
  72. package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
  73. package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
  74. package/dist/hooks/atlas/tool-execute-before.d.ts +3 -0
  75. package/dist/hooks/atlas/types.d.ts +1 -0
  76. package/dist/hooks/index.d.ts +1 -1
  77. package/dist/hooks/prometheus-md-only/agent-resolution.d.ts +2 -2
  78. package/dist/hooks/runtime-fallback/chat-message-handler.d.ts +2 -0
  79. package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +1 -0
  80. package/dist/hooks/runtime-fallback/runtime-model-settings.d.ts +6 -0
  81. package/dist/hooks/runtime-fallback/session-status-handler.d.ts +1 -1
  82. package/dist/hooks/runtime-fallback/types.d.ts +3 -1
  83. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  84. package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
  85. package/dist/hooks/{start-work → ulw-execute}/context-info-builder.d.ts +1 -1
  86. package/dist/hooks/{start-work → ulw-execute}/index.d.ts +1 -1
  87. package/dist/hooks/ulw-execute/ulw-execute-hook.d.ts +23 -0
  88. package/dist/index.js +12573 -6957
  89. package/dist/oh-my-opencode.schema.json +15 -2
  90. package/dist/plugin/chat-message/types.d.ts +3 -3
  91. package/dist/plugin/chat-message/ulw-execute-message.d.ts +5 -0
  92. package/dist/plugin/event-session-lifecycle.d.ts +1 -0
  93. package/dist/plugin/hooks/create-core-hooks.d.ts +2 -1
  94. package/dist/plugin/hooks/create-session-hooks.d.ts +2 -2
  95. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
  96. package/dist/plugin/messages-transform.d.ts +1 -0
  97. package/dist/shared/index.d.ts +2 -0
  98. package/dist/shared/legacy-plugin-warning.d.ts +2 -1
  99. package/dist/shared/normalize-sdk-response.d.ts +1 -0
  100. package/dist/shared/plugin-entry-migrator.d.ts +4 -3
  101. package/dist/shared/plugin-entry-shape.d.ts +6 -0
  102. package/dist/shared/runtime-fallback-retry-marker.d.ts +16 -0
  103. package/dist/shared/shell-env.d.ts +1 -1
  104. package/dist/skills/ast-grep/AGENTS.md +51 -0
  105. package/dist/skills/coding-agent-sessions/AGENTS.md +62 -0
  106. package/dist/skills/coding-agent-sessions/SKILL.md +3 -2
  107. package/dist/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  108. package/dist/skills/coding-agent-sessions/references/senpi.md +4 -4
  109. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  110. package/dist/skills/data-scientist/SKILL.md +99 -239
  111. package/dist/skills/data-scientist/references/execution-surfaces.md +91 -0
  112. package/dist/skills/data-scientist/references/placement.md +74 -0
  113. package/dist/skills/data-scientist/references/polars-lane.md +95 -0
  114. package/dist/skills/data-scientist/references/uv-setup.md +1 -1
  115. package/dist/skills/data-scientist/references/visualization.md +64 -0
  116. package/dist/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  117. package/dist/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  118. package/dist/skills/debugging/SKILL.md +2 -0
  119. package/dist/skills/debugging/references/methodology/00-setup.md +12 -0
  120. package/dist/skills/debugging/references/methodology/02-investigate.md +21 -0
  121. package/dist/skills/debugging/references/runtimes/go.md +15 -1
  122. package/dist/skills/debugging/references/runtimes/native-binary.md +38 -0
  123. package/dist/skills/debugging/references/runtimes/node.md +25 -0
  124. package/dist/skills/debugging/references/runtimes/python.md +13 -0
  125. package/dist/skills/debugging/references/runtimes/rust.md +41 -0
  126. package/dist/skills/debugging/references/scripts/dap.mjs +267 -0
  127. package/dist/skills/debugging/references/scripts/dap.test.ts +86 -0
  128. package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  129. package/dist/skills/debugging/references/tools/dap.md +103 -0
  130. package/dist/skills/debugging/references/tools/frida.md +193 -0
  131. package/dist/skills/frontend/SKILL.md +11 -7
  132. package/dist/skills/frontend/references/design/_INDEX.md +1 -0
  133. package/dist/skills/frontend/references/design/print-paged-media.md +76 -0
  134. package/dist/skills/frontend/references/design/stylegallery.md +80 -0
  135. package/dist/skills/frontend/references/designpowers/README.md +1 -1
  136. package/dist/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  137. package/dist/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  138. package/dist/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  139. package/dist/skills/frontend/references/designpowers/orchestration.md +1 -1
  140. package/dist/skills/frontend/references/designpowers/routing.md +5 -5
  141. package/dist/skills/review-work/SKILL.md +3 -3
  142. package/dist/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  143. package/dist/skills/ultimate-browsing/SKILL.md +2 -0
  144. package/dist/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  145. package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
  146. package/dist/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  147. package/dist/skills/{start-work → ulw-execute}/SKILL.md +9 -8
  148. package/dist/skills/ulw-plan/SKILL.md +6 -6
  149. package/dist/skills/ulw-plan/references/full-workflow.md +31 -7
  150. package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
  151. package/dist/skills/ulw-plan/references/intent-unclear.md +5 -5
  152. package/dist/skills/ulw-research/SKILL.md +4 -2
  153. package/dist/skills/visual-qa/AGENTS.md +58 -0
  154. package/dist/skills/visual-qa/SKILL.md +3 -2
  155. package/dist/tools/delegate-task/builtin-categories.d.ts +1 -0
  156. package/dist/tools/delegate-task/builtin-category-definition.d.ts +1 -0
  157. package/dist/tools/delegate-task/tool-description.d.ts +3 -1
  158. package/dist/tools/delegate-task/types.d.ts +3 -0
  159. package/dist/tui.d.ts +12 -0
  160. package/dist/tui.js +11480 -11512
  161. package/package.json +42 -36
  162. package/packages/git-bash-mcp/dist/cli.js +5 -1
  163. package/packages/git-bash-mcp/package.json +1 -1
  164. package/packages/lsp-core/src/index.ts +1 -0
  165. package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
  166. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +0 -28
  167. package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
  168. package/packages/lsp-core/src/lsp/client-wrapper.test.ts +66 -13
  169. package/packages/lsp-core/src/lsp/client-wrapper.ts +95 -23
  170. package/packages/lsp-core/src/lsp/client.ts +26 -0
  171. package/packages/lsp-core/src/lsp/connection.ts +16 -0
  172. package/packages/lsp-core/src/lsp/constants.ts +1 -0
  173. package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
  174. package/packages/lsp-core/src/lsp/format-document.ts +90 -0
  175. package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
  176. package/packages/lsp-core/src/lsp/manager.ts +34 -1
  177. package/packages/lsp-core/src/lsp/outside-context-workspace.ts +33 -0
  178. package/packages/lsp-core/src/lsp/server-definitions.ts +29 -0
  179. package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
  180. package/packages/lsp-core/src/lsp/server-installation.ts +200 -27
  181. package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
  182. package/packages/lsp-core/src/lsp/server-resolution.ts +18 -5
  183. package/packages/lsp-core/src/lsp/transport.ts +9 -0
  184. package/packages/lsp-core/src/lsp/types.ts +8 -0
  185. package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +20 -1
  186. package/packages/lsp-core/src/lsp/workspace-markers.ts +1 -0
  187. package/packages/lsp-core/src/request-context.test.ts +29 -0
  188. package/packages/lsp-core/src/request-context.ts +1 -1
  189. package/packages/lsp-core/src/tool-surface.test.ts +13 -1
  190. package/packages/lsp-core/src/tools/definitions.ts +14 -0
  191. package/packages/lsp-core/src/tools/diagnostics.ts +3 -3
  192. package/packages/lsp-core/src/tools/format.test.ts +56 -0
  193. package/packages/lsp-core/src/tools/format.ts +56 -0
  194. package/packages/lsp-core/src/tools/index.ts +1 -0
  195. package/packages/lsp-core/src/tools/navigation.ts +4 -2
  196. package/packages/lsp-core/src/tools/rename.ts +4 -2
  197. package/packages/lsp-core/src/tools/symbols.ts +1 -1
  198. package/packages/lsp-core/src/tools/types.ts +10 -0
  199. package/packages/lsp-daemon/dist/cli.js +645 -296
  200. package/packages/lsp-daemon/dist/client.d.ts +10 -0
  201. package/packages/lsp-daemon/dist/client.js +605 -253
  202. package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
  203. package/packages/lsp-daemon/dist/daemon-client.js +3 -0
  204. package/packages/lsp-daemon/dist/ensure-daemon.js +1 -0
  205. package/packages/lsp-daemon/dist/index.js +609 -262
  206. package/packages/lsp-daemon/dist/version-reap.js +1 -1
  207. package/packages/lsp-daemon/package.json +1 -1
  208. package/packages/lsp-tools-mcp/dist/cli.js +564 -217
  209. package/packages/lsp-tools-mcp/dist/lsp/manager.js +115 -92
  210. package/packages/lsp-tools-mcp/dist/mcp.js +566 -219
  211. package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
  212. package/packages/lsp-tools-mcp/dist/tools.js +571 -227
  213. package/packages/omo-codex/THIRD-PARTY-NOTICES.md +4 -4
  214. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +4 -4
  215. package/packages/omo-codex/plugin/AGENTS.md +47 -0
  216. package/packages/omo-codex/plugin/README.md +1 -1
  217. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +34 -33
  218. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  219. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  220. package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +1 -0
  221. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +293 -116
  222. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +245 -84
  223. package/packages/omo-codex/plugin/components/codegraph/package.json +4 -4
  224. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +1 -0
  225. package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +1 -0
  226. package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +9 -0
  227. package/packages/omo-codex/plugin/components/comment-checker/biome.json +2 -2
  228. package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +2 -1
  229. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  230. package/packages/omo-codex/plugin/components/comment-checker/package.json +5 -5
  231. package/packages/omo-codex/plugin/components/comment-checker/src/apply-patch.ts +2 -8
  232. package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +1 -2
  233. package/packages/omo-codex/plugin/components/comment-checker/src/request-extractor.ts +1 -1
  234. package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +1 -0
  235. package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +1 -1
  236. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  237. package/packages/omo-codex/plugin/components/git-bash/package.json +3 -4
  238. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
  239. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +1 -5
  240. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +1 -5
  241. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  242. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +5 -5
  243. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +1 -5
  244. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +4 -21
  245. package/packages/omo-codex/plugin/components/lsp/AGENTS.md +30 -15
  246. package/packages/omo-codex/plugin/components/lsp/biome.json +2 -2
  247. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +4 -4
  248. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +596 -267
  249. package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.js +1 -1
  250. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  251. package/packages/omo-codex/plugin/components/lsp/package.json +5 -5
  252. package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
  253. package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +1 -1
  254. package/packages/omo-codex/plugin/components/lsp/src/daemon-cli-path.ts +1 -5
  255. package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +6 -7
  256. package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +1 -2
  257. package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +11 -1
  258. package/packages/omo-codex/plugin/components/rules/AGENTS.md +12 -0
  259. package/packages/omo-codex/plugin/components/rules/biome.json +2 -2
  260. package/packages/omo-codex/plugin/components/rules/dist/cli.js +60 -45
  261. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  262. package/packages/omo-codex/plugin/components/rules/package.json +7 -7
  263. package/packages/omo-codex/plugin/components/rules/src/config.ts +1 -2
  264. package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +1 -2
  265. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +9 -5
  266. package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +1 -4
  267. package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +4 -9
  268. package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
  269. package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +17 -25
  270. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
  271. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
  272. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
  273. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
  274. package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
  275. package/packages/omo-codex/plugin/components/rules/test/dynamic-target-fingerprints.test.ts +1 -2
  276. package/packages/omo-codex/plugin/components/rules/test/engine.test.ts +7 -4
  277. package/packages/omo-codex/plugin/components/rules/test/finder.test.ts +2 -3
  278. package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +39 -72
  279. package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +1 -2
  280. package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
  281. package/packages/omo-codex/plugin/components/rules/test/matcher.test.ts +2 -3
  282. package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +1 -1
  283. package/packages/omo-codex/plugin/components/rules/test/parser.test.ts +1 -2
  284. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +5 -6
  285. package/packages/omo-codex/plugin/components/rules/test/rules-engine-consumption.test.ts +3 -6
  286. package/packages/omo-codex/plugin/components/rules/test/scanner.test.ts +1 -2
  287. package/packages/omo-codex/plugin/components/rules/test/sources.test.ts +2 -5
  288. package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +2 -17
  289. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  290. package/packages/omo-codex/plugin/components/teammode/package.json +5 -5
  291. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +3 -9
  292. package/packages/omo-codex/plugin/components/telemetry/AGENTS.md +8 -0
  293. package/packages/omo-codex/plugin/components/telemetry/biome.json +2 -2
  294. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2463 -437
  295. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2467 -441
  296. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  297. package/packages/omo-codex/plugin/components/telemetry/package.json +5 -5
  298. package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +1 -4
  299. package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -14
  300. package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +1 -1
  301. package/packages/omo-codex/plugin/components/telemetry/test/diagnostics.test.ts +2 -5
  302. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +5 -0
  303. package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
  304. package/packages/omo-codex/plugin/components/ultrawork/directive.md +13 -1
  305. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  306. package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -5
  307. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +13 -1
  308. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -6
  309. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +31 -7
  310. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
  311. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +5 -5
  312. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +9 -1
  313. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
  314. package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
  315. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +5 -4
  316. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/NOTICE +1 -1
  317. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/README.md +5 -5
  318. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/biome.json +2 -2
  319. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/directive.md +6 -6
  320. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +12 -12
  321. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +28 -0
  322. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/package.json +12 -12
  323. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/boulder-reader.ts +1 -1
  324. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/cli.ts +1 -1
  325. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/codex-hook.ts +3 -3
  326. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/directive.ts +1 -1
  327. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/index.ts +1 -1
  328. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/boulder-reader.test.ts +3 -3
  329. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +1 -4
  330. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +8 -22
  331. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +16 -0
  332. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
  333. package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
  334. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +13 -1
  335. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +5 -1
  336. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
  337. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +11 -1
  338. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +24 -14
  339. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +1 -1
  340. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +1 -1
  341. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +3 -3
  342. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  343. package/packages/omo-codex/plugin/components/ulw-loop/package.json +5 -5
  344. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -2
  345. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
  346. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -0
  347. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +5 -1
  348. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +13 -1
  349. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +3 -5
  350. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +3 -1
  351. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
  352. package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +1 -1
  353. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +3 -3
  354. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
  355. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +25 -0
  356. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +26 -2
  357. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +2 -2
  358. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +18 -0
  359. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
  360. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -37
  361. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +9 -0
  362. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +8 -5
  363. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
  364. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +4 -5
  365. package/packages/omo-codex/plugin/components/ulw-loop/vitest.config.ts +1 -0
  366. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  367. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  368. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  369. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  370. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  371. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  372. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  373. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  374. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  375. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  376. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  377. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  378. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  379. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  380. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  381. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  382. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +17 -0
  383. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  384. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +17 -0
  385. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  386. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  387. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  388. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  389. package/packages/omo-codex/plugin/model-catalog.json +3 -3
  390. package/packages/omo-codex/plugin/package-lock.json +681 -395
  391. package/packages/omo-codex/plugin/package.json +2 -2
  392. package/packages/omo-codex/plugin/scripts/AGENTS.md +40 -0
  393. package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -1
  394. package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +3 -3
  395. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +11 -11
  396. package/packages/omo-codex/plugin/shared/package.json +3 -4
  397. package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +51 -0
  398. package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +62 -0
  399. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
  400. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  401. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
  402. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  403. package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
  404. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
  405. package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
  406. package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
  407. package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
  408. package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
  409. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  410. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  411. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -0
  412. package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
  413. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
  414. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
  415. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
  416. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
  417. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
  418. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
  419. package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
  420. package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  421. package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
  422. package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
  423. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +11 -7
  424. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
  425. package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
  426. package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
  427. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
  428. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  429. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  430. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  431. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
  432. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
  433. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +4 -4
  434. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  435. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -0
  436. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  437. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
  438. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  439. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +13 -1
  440. package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +12 -11
  441. package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
  442. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -2
  443. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
  444. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -0
  445. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -6
  446. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +31 -7
  447. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
  448. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +5 -5
  449. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +4 -2
  450. package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
  451. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +3 -2
  452. package/packages/omo-codex/plugin/test/AGENTS.md +47 -0
  453. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
  454. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +8 -28
  455. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -1
  456. package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
  457. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
  458. package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
  459. package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
  460. package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -2
  461. package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +2 -2
  462. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +1 -1
  463. package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +2 -2
  464. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +4 -4
  465. package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
  466. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
  467. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
  468. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
  469. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +12 -12
  470. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +1 -119
  471. package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
  472. package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
  473. package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
  474. package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
  475. package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
  476. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +0 -3
  477. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
  478. package/packages/omo-codex/scripts/AGENTS.md +36 -0
  479. package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +2 -2
  480. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2637 -549
  481. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
  482. package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
  483. package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
  484. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
  485. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  486. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
  487. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  488. package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
  489. package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
  490. package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
  491. package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
  492. package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
  493. package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
  494. package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  495. package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  496. package/packages/shared-skills/skills/debugging/SKILL.md +2 -0
  497. package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
  498. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
  499. package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
  500. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
  501. package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
  502. package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
  503. package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
  504. package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
  505. package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
  506. package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  507. package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
  508. package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
  509. package/packages/shared-skills/skills/frontend/SKILL.md +11 -7
  510. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
  511. package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
  512. package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
  513. package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
  514. package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  515. package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  516. package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  517. package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
  518. package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
  519. package/packages/shared-skills/skills/review-work/SKILL.md +3 -3
  520. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  521. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -0
  522. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  523. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
  524. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  525. package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +9 -8
  526. package/packages/shared-skills/skills/ulw-plan/SKILL.md +6 -6
  527. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
  528. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
  529. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
  530. package/packages/shared-skills/skills/ulw-research/SKILL.md +4 -2
  531. package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
  532. package/packages/shared-skills/skills/visual-qa/SKILL.md +3 -2
  533. package/script/qa/web-terminal-visual-qa.mjs +2 -0
  534. package/script/qa/xterm-live-terminal.mjs +18 -2
  535. package/dist/config/schema/start-work.d.ts +0 -5
  536. package/dist/features/builtin-commands/templates/start-work.d.ts +0 -1
  537. package/dist/hooks/start-work/start-work-hook.d.ts +0 -23
  538. package/dist/plugin/chat-message/start-work-message.d.ts +0 -5
  539. package/dist/skills/data-scientist/references/common-scenarios.md +0 -176
  540. package/dist/skills/data-scientist/references/execution-templates.md +0 -197
  541. package/dist/skills/data-scientist/references/integration-patterns.md +0 -153
  542. package/dist/skills/data-scientist/references/performance-benchmarks.md +0 -37
  543. package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
  544. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
  545. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
  546. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
  547. package/packages/omo-codex/plugin/skills/data-scientist/references/common-scenarios.md +0 -176
  548. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-templates.md +0 -197
  549. package/packages/omo-codex/plugin/skills/data-scientist/references/integration-patterns.md +0 -153
  550. package/packages/omo-codex/plugin/skills/data-scientist/references/performance-benchmarks.md +0 -37
  551. package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
  552. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
  553. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
  554. package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
  555. package/packages/shared-skills/skills/data-scientist/references/common-scenarios.md +0 -176
  556. package/packages/shared-skills/skills/data-scientist/references/execution-templates.md +0 -197
  557. package/packages/shared-skills/skills/data-scientist/references/integration-patterns.md +0 -153
  558. package/packages/shared-skills/skills/data-scientist/references/performance-benchmarks.md +0 -37
  559. /package/dist/hooks/{start-work → ulw-execute}/context-info-formatters.d.ts +0 -0
  560. /package/dist/hooks/{start-work → ulw-execute}/explicit-plan-context.d.ts +0 -0
  561. /package/dist/hooks/{start-work → ulw-execute}/notepad-scaffold.d.ts +0 -0
  562. /package/dist/hooks/{start-work → ulw-execute}/parse-user-request.d.ts +0 -0
  563. /package/dist/hooks/{start-work → ulw-execute}/plan-discovery-context.d.ts +0 -0
  564. /package/dist/hooks/{start-work → ulw-execute}/plan-selection.d.ts +0 -0
  565. /package/dist/hooks/{start-work → ulw-execute}/session-plan-affinity.d.ts +0 -0
  566. /package/dist/hooks/{start-work → ulw-execute}/work-initializer.d.ts +0 -0
  567. /package/dist/hooks/{start-work → ulw-execute}/worktree-block.d.ts +0 -0
  568. /package/dist/hooks/{start-work → ulw-execute}/worktree-detector.d.ts +0 -0
  569. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/.gitattributes +0 -0
  570. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/CHANGELOG.md +0 -0
  571. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/LICENSE +0 -0
  572. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/plan-checklist.ts +0 -0
  573. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/types.ts +0 -0
  574. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
  575. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
  576. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
  577. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
  578. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
  579. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
  580. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
  581. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
  582. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
  583. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
@@ -4,8 +4,8 @@
4
4
  import { argv, stderr } from "node:process";
5
5
 
6
6
  // src/proxy.ts
7
- import { existsSync as existsSync12, realpathSync as realpathSync4 } from "node:fs";
8
- import { basename as basename3, delimiter as delimiter4, dirname as dirname9, isAbsolute as isAbsolute5 } from "node:path";
7
+ import { existsSync as existsSync13, realpathSync as realpathSync6 } from "node:fs";
8
+ import { basename as basename4, delimiter as delimiter4, dirname as dirname11, isAbsolute as isAbsolute6 } from "node:path";
9
9
 
10
10
  // ../mcp-stdio-core/src/record.ts
11
11
  function isPlainRecord(value) {
@@ -280,7 +280,11 @@ function createParentWatchdog(config, onDeadParent) {
280
280
  const probeAlive = config.probeAlive ?? isProcessAlive;
281
281
  let fired = false;
282
282
  const timer = setInterval(() => {
283
- if (fired || probeAlive(parentPid))
283
+ if (fired)
284
+ return;
285
+ const alive = probeAlive(parentPid);
286
+ config.onPoll?.(alive);
287
+ if (alive)
284
288
  return;
285
289
  fired = true;
286
290
  onDeadParent(parentPid, pollIntervalMs);
@@ -315,8 +319,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
315
319
  };
316
320
  }
317
321
  // ../lsp-core/src/lsp/client-wrapper.ts
318
- import { existsSync as existsSync9, statSync as statSync3 } from "node:fs";
319
- import { dirname as dirname6, join as join4, resolve as resolve7 } from "node:path";
322
+ import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
323
+ import { basename as basename3, dirname as dirname8, join as join5, resolve as resolve8 } from "node:path";
320
324
 
321
325
  // ../lsp-core/src/request-context.ts
322
326
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -325,18 +329,17 @@ import { homedir } from "node:os";
325
329
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
326
330
 
327
331
  class LspRequestContextParseError extends Error {
328
- code;
329
- name = "LspRequestContextParseError";
330
332
  constructor(code, message) {
331
333
  super(message);
332
334
  this.code = code;
335
+ this.name = "LspRequestContextParseError";
333
336
  }
334
337
  }
335
338
 
336
339
  class LspRequestContextUnavailableError extends Error {
337
- name = "LspRequestContextUnavailableError";
338
340
  constructor() {
339
341
  super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
342
+ this.name = "LspRequestContextUnavailableError";
340
343
  }
341
344
  }
342
345
  var storage = new AsyncLocalStorage;
@@ -356,7 +359,7 @@ function contextCwd() {
356
359
  }
357
360
  function createStandaloneMcpRequestContext(input = {}) {
358
361
  const env = input.env ?? process.env;
359
- const cwd = canonicalCwd(input.cwd ?? process.cwd());
362
+ const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
360
363
  const home = input.homeDir ?? homedir();
361
364
  const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
362
365
  const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
@@ -499,22 +502,15 @@ function effectiveExtension(filePath) {
499
502
 
500
503
  // ../lsp-core/src/lsp/errors.ts
501
504
  class LspConnectionClosedError extends Error {
502
- serverId;
503
- root;
504
- name = "LspConnectionClosedError";
505
505
  constructor(serverId, root, message) {
506
506
  super(message ?? `LSP connection closed for ${serverId} at ${root}`);
507
507
  this.serverId = serverId;
508
508
  this.root = root;
509
+ this.name = "LspConnectionClosedError";
509
510
  }
510
511
  }
511
512
 
512
513
  class LspProcessExitedError extends Error {
513
- serverId;
514
- root;
515
- exitCode;
516
- stderrTail;
517
- name = "LspProcessExitedError";
518
514
  constructor(serverId, root, exitCode, stderrTail) {
519
515
  const stderrSuffix = stderrTail ? `
520
516
  stderr tail: ${stderrTail}` : "";
@@ -523,46 +519,49 @@ stderr tail: ${stderrTail}` : "";
523
519
  this.root = root;
524
520
  this.exitCode = exitCode;
525
521
  this.stderrTail = stderrTail;
522
+ this.name = "LspProcessExitedError";
526
523
  }
527
524
  }
528
525
 
529
526
  class LspRequestTimeoutError extends Error {
530
- method;
531
- stderrTail;
532
- name = "LspRequestTimeoutError";
533
527
  constructor(method, stderrTail) {
534
528
  const stderrSuffix = stderrTail ? `
535
529
  recent stderr: ${stderrTail}` : "";
536
530
  super(`LSP request timeout (method: ${method})${stderrSuffix}`);
537
531
  this.method = method;
538
532
  this.stderrTail = stderrTail;
533
+ this.name = "LspRequestTimeoutError";
539
534
  }
540
535
  }
541
536
 
542
537
  class LspInvalidPathError extends Error {
543
- name = "LspInvalidPathError";
538
+ constructor() {
539
+ super(...arguments);
540
+ this.name = "LspInvalidPathError";
541
+ }
544
542
  }
545
543
 
546
544
  class LspServerLookupError extends Error {
547
- lookup;
548
- name = "LspServerLookupError";
549
545
  constructor(message, lookup) {
550
546
  super(message);
551
547
  this.lookup = lookup;
548
+ this.name = "LspServerLookupError";
552
549
  }
553
550
  }
554
551
 
555
552
  class LspServerInitializingError extends Error {
556
- originalError;
557
- name = "LspServerInitializingError";
558
553
  constructor(originalError) {
559
554
  super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
560
555
  this.originalError = originalError;
556
+ this.name = "LspServerInitializingError";
561
557
  }
562
558
  }
563
559
 
564
560
  class LspProcessSpawnError extends Error {
565
- name = "LspProcessSpawnError";
561
+ constructor() {
562
+ super(...arguments);
563
+ this.name = "LspProcessSpawnError";
564
+ }
566
565
  }
567
566
  function isLspDeadConnectionError(err) {
568
567
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
@@ -593,6 +592,7 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
593
592
  var REQUEST_TIMEOUT_MS = 15000;
594
593
  var INIT_TIMEOUT_MS = 60000;
595
594
  var IDLE_TIMEOUT_MS = 5 * 60000;
595
+ var MAX_RESIDENT_CLIENTS = 6;
596
596
  var REAPER_INTERVAL_MS = 60000;
597
597
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
598
598
  var STOP_SIGKILL_GRACE_MS = 1000;
@@ -607,20 +607,31 @@ var METHOD_NOT_FOUND = -32601;
607
607
  var INTERNAL_ERROR = -32603;
608
608
 
609
609
  class JsonRpcConnection {
610
- reader;
611
- writer;
612
- pendingRequests = new Map;
613
- notificationHandlers = new Map;
614
- requestHandlers = new Map;
615
- closeHandlers = [];
616
- errorHandlers = [];
617
- inputBuffer = Buffer.alloc(0);
618
- nextRequestId = 1;
619
- listening = false;
620
- disposed = false;
621
610
  constructor(reader, writer) {
622
611
  this.reader = reader;
623
612
  this.writer = writer;
613
+ this.pendingRequests = new Map;
614
+ this.notificationHandlers = new Map;
615
+ this.requestHandlers = new Map;
616
+ this.closeHandlers = [];
617
+ this.errorHandlers = [];
618
+ this.inputBuffer = Buffer.alloc(0);
619
+ this.nextRequestId = 1;
620
+ this.listening = false;
621
+ this.disposed = false;
622
+ this.handleData = (chunk) => {
623
+ const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
624
+ this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
625
+ this.drainInputBuffer();
626
+ };
627
+ this.handleClose = () => {
628
+ for (const handler of this.closeHandlers) {
629
+ handler();
630
+ }
631
+ };
632
+ this.handleStreamError = (error) => {
633
+ this.emitError(error);
634
+ };
624
635
  }
625
636
  listen() {
626
637
  if (this.listening)
@@ -741,19 +752,6 @@ class JsonRpcConnection {
741
752
  this.notificationHandlers.clear();
742
753
  this.requestHandlers.clear();
743
754
  }
744
- handleData = (chunk) => {
745
- const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
746
- this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
747
- this.drainInputBuffer();
748
- };
749
- handleClose = () => {
750
- for (const handler of this.closeHandlers) {
751
- handler();
752
- }
753
- };
754
- handleStreamError = (error) => {
755
- this.emitError(error);
756
- };
757
755
  drainInputBuffer() {
758
756
  while (true) {
759
757
  const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
@@ -1101,31 +1099,26 @@ function isPosition(value) {
1101
1099
 
1102
1100
  // ../lsp-core/src/lsp/transport.ts
1103
1101
  class LspClientNotStartedError extends Error {
1104
- serverId;
1105
- root;
1106
- name = "LspClientNotStartedError";
1107
1102
  constructor(serverId, root) {
1108
1103
  super("LSP client not started");
1109
1104
  this.serverId = serverId;
1110
1105
  this.root = root;
1106
+ this.name = "LspClientNotStartedError";
1111
1107
  }
1112
1108
  }
1113
1109
 
1114
1110
  class LspClientTransport {
1115
- root;
1116
- server;
1117
- proc = null;
1118
- connection = null;
1119
- stderrBuffer = [];
1120
- processExited = false;
1121
- diagnosticsStore = new Map;
1122
- requestTimeoutMs;
1123
- initializeTimeoutMs;
1124
- workspaceApplyEditHandler = null;
1125
- diagnosticPullSupported = false;
1126
1111
  constructor(root, server2, timeouts = {}) {
1127
1112
  this.root = root;
1128
1113
  this.server = server2;
1114
+ this.proc = null;
1115
+ this.connection = null;
1116
+ this.stderrBuffer = [];
1117
+ this.processExited = false;
1118
+ this.diagnosticsStore = new Map;
1119
+ this.workspaceApplyEditHandler = null;
1120
+ this.diagnosticPullSupported = false;
1121
+ this.documentFormattingSupported = false;
1129
1122
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
1130
1123
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
1131
1124
  }
@@ -1147,6 +1140,12 @@ class LspClientTransport {
1147
1140
  isDiagnosticPullSupported() {
1148
1141
  return this.diagnosticPullSupported;
1149
1142
  }
1143
+ setDocumentFormattingSupported(supported) {
1144
+ this.documentFormattingSupported = supported;
1145
+ }
1146
+ isDocumentFormattingSupported() {
1147
+ return this.documentFormattingSupported;
1148
+ }
1150
1149
  handlePublishDiagnostics(params) {
1151
1150
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
1152
1151
  }
@@ -1360,6 +1359,14 @@ function supportsDiagnosticPull(capabilities) {
1360
1359
  return false;
1361
1360
  return Object.hasOwn(capabilities, "diagnosticProvider");
1362
1361
  }
1362
+ function supportsDocumentFormatting(capabilities) {
1363
+ if (capabilities === undefined)
1364
+ return false;
1365
+ const provider = capabilities.documentFormattingProvider;
1366
+ if (provider === undefined || provider === null || provider === false)
1367
+ return false;
1368
+ return provider === true || typeof provider === "object";
1369
+ }
1363
1370
 
1364
1371
  class LspClientConnection extends LspClientTransport {
1365
1372
  async initialize() {
@@ -1376,6 +1383,7 @@ class LspClientConnection extends LspClientTransport {
1376
1383
  references: {},
1377
1384
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
1378
1385
  publishDiagnostics: {},
1386
+ formatting: { dynamicRegistration: false },
1379
1387
  rename: {
1380
1388
  prepareSupport: true,
1381
1389
  prepareSupportDefaultBehavior: 1
@@ -1417,6 +1425,7 @@ class LspClientConnection extends LspClientTransport {
1417
1425
  initializationOptions: this.server.initialization
1418
1426
  }, { timeoutMs: this.initializeTimeoutMs });
1419
1427
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
1428
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
1420
1429
  await this.sendNotification("initialized", {});
1421
1430
  await this.sendNotification("workspace/didChangeConfiguration", {
1422
1431
  settings: { json: { validate: { enable: true } } }
@@ -1622,16 +1631,12 @@ function movedPath(candidate, oldPath, newPath) {
1622
1631
  }
1623
1632
 
1624
1633
  class WorkspaceDocumentState {
1625
- sendNotification;
1626
- clearDiagnostics;
1627
- openDocuments = new Map;
1628
- openByUri = new Map;
1629
- openPromises = new Map;
1630
- now;
1631
- versionlessPublishQuiescenceMs;
1632
1634
  constructor(sendNotification, clearDiagnostics, options = {}) {
1633
1635
  this.sendNotification = sendNotification;
1634
1636
  this.clearDiagnostics = clearDiagnostics;
1637
+ this.openDocuments = new Map;
1638
+ this.openByUri = new Map;
1639
+ this.openPromises = new Map;
1635
1640
  this.now = options.now ?? (() => Date.now());
1636
1641
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1637
1642
  }
@@ -1895,13 +1900,11 @@ import { dirname as dirname2, isAbsolute as isAbsolute2, relative as relative3,
1895
1900
  import { fileURLToPath } from "node:url";
1896
1901
 
1897
1902
  class WorkspaceEditPathError extends Error {
1898
- path;
1899
- detail;
1900
- name = "WorkspaceEditPathError";
1901
1903
  constructor(path, detail) {
1902
1904
  super(`${detail}: ${path}`);
1903
1905
  this.path = path;
1904
1906
  this.detail = detail;
1907
+ this.name = "WorkspaceEditPathError";
1905
1908
  }
1906
1909
  }
1907
1910
  function isPathInsideWorkspace(filePath, workspaceRoot) {
@@ -2193,13 +2196,11 @@ function canonicalFingerprint(operations) {
2193
2196
 
2194
2197
  // ../lsp-core/src/lsp/workspace-edit-types.ts
2195
2198
  class WorkspaceEditValidationError extends Error {
2196
- changeIndex;
2197
- detail;
2198
- name = "WorkspaceEditValidationError";
2199
2199
  constructor(changeIndex, detail) {
2200
2200
  super(`change ${changeIndex}: ${detail}`);
2201
2201
  this.changeIndex = changeIndex;
2202
2202
  this.detail = detail;
2203
+ this.name = "WorkspaceEditValidationError";
2203
2204
  }
2204
2205
  }
2205
2206
 
@@ -2697,10 +2698,9 @@ function simulateDelete(operation, virtual) {
2697
2698
  import { existsSync as existsSync5, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
2698
2699
  import { dirname as dirname4, resolve as resolve5 } from "node:path";
2699
2700
  class WorkspaceSnapshotBuilder {
2700
- workspaceRoot;
2701
- snapshots = new Map;
2702
2701
  constructor(workspaceRoot) {
2703
2702
  this.workspaceRoot = workspaceRoot;
2703
+ this.snapshots = new Map;
2704
2704
  }
2705
2705
  build(operations) {
2706
2706
  this.add(this.workspaceRoot, false);
@@ -2744,8 +2744,10 @@ function snapshotOperations(operations, workspaceRoot) {
2744
2744
 
2745
2745
  // ../lsp-core/src/lsp/workspace-edit-plan.ts
2746
2746
  class PlanPathIndex {
2747
- firstChangeByPath = new Map;
2748
- reportedPathByCanonical = new Map;
2747
+ constructor() {
2748
+ this.firstChangeByPath = new Map;
2749
+ this.reportedPathByCanonical = new Map;
2750
+ }
2749
2751
  build(operations) {
2750
2752
  for (const operation of operations) {
2751
2753
  switch (operation.kind) {
@@ -2834,14 +2836,11 @@ function isRecord4(value) {
2834
2836
  }
2835
2837
 
2836
2838
  class WorkspaceMutationController {
2837
- workspaceRoot;
2838
- documents;
2839
- activeLease = null;
2840
- nextLeaseId = 1;
2841
- io;
2842
2839
  constructor(workspaceRoot, documents) {
2843
2840
  this.workspaceRoot = workspaceRoot;
2844
2841
  this.documents = documents;
2842
+ this.activeLease = null;
2843
+ this.nextLeaseId = 1;
2845
2844
  }
2846
2845
  setIo(io) {
2847
2846
  this.io = io;
@@ -2954,12 +2953,9 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
2954
2953
  var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
2955
2954
 
2956
2955
  class LspClient extends LspClientConnection {
2957
- diagnosticPullErrors = [];
2958
- documents;
2959
- workspaceMutations;
2960
- diagnosticsFreshnessTimeoutMs;
2961
2956
  constructor(root, server2, options = {}) {
2962
2957
  super(root, server2, options);
2958
+ this.diagnosticPullErrors = [];
2963
2959
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2964
2960
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2965
2961
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
@@ -3014,6 +3010,18 @@ class LspClient extends LspClientConnection {
3014
3010
  textDocument: { uri: pathToFileURL3(absPath).href }
3015
3011
  }, options);
3016
3012
  }
3013
+ async formatDocument(filePath, options, signal) {
3014
+ if (!this.isDocumentFormattingSupported())
3015
+ return null;
3016
+ const absPath = this.resolveWorkspacePath(filePath);
3017
+ await this.openFile(absPath);
3018
+ const requestOptions = signal === undefined ? {} : { signal };
3019
+ const edits = await this.sendRequest("textDocument/formatting", {
3020
+ textDocument: { uri: pathToFileURL3(absPath).href },
3021
+ options
3022
+ }, requestOptions);
3023
+ return edits ?? [];
3024
+ }
3017
3025
  async workspaceSymbols(query, signal) {
3018
3026
  const options = signal === undefined ? {} : { signal };
3019
3027
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -3259,18 +3267,14 @@ function awaitWithSignal(promise, signal) {
3259
3267
  }
3260
3268
 
3261
3269
  class LspManager {
3262
- clients = new Map;
3263
- reaperHandle = null;
3264
- signalDisposer = null;
3265
- disposed = false;
3266
- idleTimeoutMs;
3267
- initTimeoutMs;
3268
- reaperIntervalMs;
3269
- clientFactory;
3270
- now;
3271
3270
  constructor(options = {}) {
3271
+ this.clients = new Map;
3272
+ this.reaperHandle = null;
3273
+ this.signalDisposer = null;
3274
+ this.disposed = false;
3272
3275
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
3273
3276
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
3277
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
3274
3278
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
3275
3279
  this.clientFactory = options.clientFactory ?? ((root, server2) => new LspClient(root, server2));
3276
3280
  this.now = options.now ?? (() => Date.now());
@@ -3304,6 +3308,26 @@ class LspManager {
3304
3308
  }
3305
3309
  }
3306
3310
  }
3311
+ evictForAdmission() {
3312
+ while (this.clients.size >= this.maxResidentClients) {
3313
+ const victim = this.leastRecentlyUsedIdleClient();
3314
+ if (!victim)
3315
+ return;
3316
+ this.clients.delete(victim.key);
3317
+ stopClientBestEffort(victim.managed.client);
3318
+ }
3319
+ }
3320
+ leastRecentlyUsedIdleClient() {
3321
+ let candidate = null;
3322
+ for (const [key, managed] of this.clients) {
3323
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
3324
+ continue;
3325
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
3326
+ candidate = { key, managed };
3327
+ }
3328
+ }
3329
+ return candidate;
3330
+ }
3307
3331
  async tryDeleteIfOrphaned(key, managed) {
3308
3332
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
3309
3333
  this.clients.delete(key);
@@ -3350,6 +3374,7 @@ class LspManager {
3350
3374
  managed.lastUsedAt = this.now();
3351
3375
  return managed.client;
3352
3376
  }
3377
+ this.evictForAdmission();
3353
3378
  const client = this.clientFactory(root, server2);
3354
3379
  const initStartedAt = this.now();
3355
3380
  const initPromise = (async () => {
@@ -3412,6 +3437,7 @@ class LspManager {
3412
3437
  const key = this.getKey(root, server2.id);
3413
3438
  if (this.clients.has(key))
3414
3439
  return;
3440
+ this.evictForAdmission();
3415
3441
  const client = this.clientFactory(root, server2);
3416
3442
  const initStartedAt = this.now();
3417
3443
  const initPromise = (async () => {
@@ -3500,57 +3526,43 @@ async function disposeDefaultLspManager() {
3500
3526
  }
3501
3527
  }
3502
3528
 
3503
- // ../lsp-core/src/lsp/server-install-state.ts
3504
- import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3505
- import { dirname as dirname5 } from "node:path";
3506
- function getInstallDecisionsPath() {
3507
- return lspRequestContext().installDecisionsPath;
3508
- }
3509
- function loadInstallDecisions() {
3510
- const path = getInstallDecisionsPath();
3511
- if (!existsSync6(path))
3512
- return {};
3513
- try {
3514
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
3515
- return isInstallDecisions(parsed) ? parsed : {};
3516
- } catch {
3517
- return {};
3529
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3530
+ import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
3531
+ import { dirname as dirname5, join as join3 } from "node:path";
3532
+
3533
+ // ../lsp-core/src/lsp/workspace-markers.ts
3534
+ var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
3535
+
3536
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3537
+ function findWorkspaceRootOutsideContext(directory) {
3538
+ const marked = nearestMarkedAncestor(directory);
3539
+ if (marked !== undefined)
3540
+ return marked;
3541
+ return realpathSync4(nearestExistingAncestor(directory));
3542
+ }
3543
+ function nearestMarkedAncestor(directory) {
3544
+ let current = directory;
3545
+ for (;; ) {
3546
+ if (existsSync6(current) && WORKSPACE_MARKERS.some((marker) => existsSync6(join3(current, marker)))) {
3547
+ return realpathSync4(current);
3548
+ }
3549
+ const parent = dirname5(current);
3550
+ if (parent === current)
3551
+ return;
3552
+ current = parent;
3518
3553
  }
3519
3554
  }
3520
- function loadInstallDecision(serverId) {
3521
- return loadInstallDecisions()[serverId];
3522
- }
3523
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3524
- const decisions = loadInstallDecisions();
3525
- decisions[serverId] = { decision, decidedAt };
3526
- writeInstallDecisions(decisions);
3527
- }
3528
- function isInstallDecision(value) {
3529
- return value === "declined" || value === "allowed";
3530
- }
3531
- function writeInstallDecisions(decisions) {
3532
- const path = getInstallDecisionsPath();
3533
- mkdirSync(dirname5(path), { recursive: true });
3534
- const tmpPath = `${path}.tmp`;
3535
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3536
- `, "utf8");
3537
- renameSync2(tmpPath, path);
3538
- }
3539
- function isInstallDecisions(value) {
3540
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3541
- }
3542
- function isInstallDecisionRecord(value) {
3543
- if (!isRecord5(value))
3544
- return false;
3545
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3546
- }
3547
- function isRecord5(value) {
3548
- return typeof value === "object" && value !== null && !Array.isArray(value);
3555
+ function nearestExistingAncestor(directory) {
3556
+ let current = directory;
3557
+ while (!existsSync6(current)) {
3558
+ const parent = dirname5(current);
3559
+ if (parent === current)
3560
+ return current;
3561
+ current = parent;
3562
+ }
3563
+ return current;
3549
3564
  }
3550
3565
 
3551
- // ../lsp-core/src/lsp/config-loader.ts
3552
- import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
3553
-
3554
3566
  // ../lsp-core/src/lsp/server-definitions.ts
3555
3567
  var LSP_INSTALL_HINTS = {
3556
3568
  typescript: "npm install -g typescript-language-server typescript",
@@ -3596,6 +3608,26 @@ var LSP_INSTALL_HINTS = {
3596
3608
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
3597
3609
  razor: "Razor runs through the Roslyn language server (cohosting). " + "Install: dotnet tool install -g roslyn-language-server --prerelease (requires v5.8.0+). See https://github.com/dotnet/razor"
3598
3610
  };
3611
+ var LSP_LOCAL_INSTALL_HINTS = {
3612
+ typescript: "bun add -d typescript-language-server typescript",
3613
+ vue: "bun add -d @vue/language-server",
3614
+ eslint: "bun add -d vscode-langservers-extracted",
3615
+ oxlint: "bun add -d oxlint",
3616
+ biome: "bun add -d @biomejs/biome",
3617
+ svelte: "bun add -d svelte-language-server",
3618
+ astro: "bun add -d @astrojs/language-server",
3619
+ bash: "bun add -d bash-language-server",
3620
+ "bash-ls": "bun add -d bash-language-server",
3621
+ "yaml-ls": "bun add -d yaml-language-server",
3622
+ php: "bun add -d intelephense",
3623
+ prisma: "bun add -d prisma",
3624
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
3625
+ pyright: "uv add --dev pyright",
3626
+ basedpyright: "uv add --dev basedpyright",
3627
+ ruff: "uv add --dev ruff",
3628
+ ty: "uv add --dev ty",
3629
+ "ruby-lsp": "bundle add ruby-lsp --group development"
3630
+ };
3599
3631
  var BUILTIN_SERVERS = {
3600
3632
  typescript: {
3601
3633
  command: ["typescript-language-server", "--stdio"],
@@ -3698,7 +3730,56 @@ var BUILTIN_SERVERS = {
3698
3730
  }
3699
3731
  };
3700
3732
 
3733
+ // ../lsp-core/src/lsp/server-install-state.ts
3734
+ import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3735
+ import { dirname as dirname6 } from "node:path";
3736
+ function getInstallDecisionsPath() {
3737
+ return lspRequestContext().installDecisionsPath;
3738
+ }
3739
+ function loadInstallDecisions() {
3740
+ const path = getInstallDecisionsPath();
3741
+ if (!existsSync7(path))
3742
+ return {};
3743
+ try {
3744
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
3745
+ return isInstallDecisions(parsed) ? parsed : {};
3746
+ } catch {
3747
+ return {};
3748
+ }
3749
+ }
3750
+ function loadInstallDecision(serverId) {
3751
+ return loadInstallDecisions()[serverId];
3752
+ }
3753
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3754
+ const decisions = loadInstallDecisions();
3755
+ decisions[serverId] = { decision, decidedAt };
3756
+ writeInstallDecisions(decisions);
3757
+ }
3758
+ function isInstallDecision(value) {
3759
+ return value === "declined" || value === "allowed";
3760
+ }
3761
+ function writeInstallDecisions(decisions) {
3762
+ const path = getInstallDecisionsPath();
3763
+ mkdirSync(dirname6(path), { recursive: true });
3764
+ const tmpPath = `${path}.tmp`;
3765
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3766
+ `, "utf8");
3767
+ renameSync2(tmpPath, path);
3768
+ }
3769
+ function isInstallDecisions(value) {
3770
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3771
+ }
3772
+ function isInstallDecisionRecord(value) {
3773
+ if (!isRecord5(value))
3774
+ return false;
3775
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3776
+ }
3777
+ function isRecord5(value) {
3778
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3779
+ }
3780
+
3701
3781
  // ../lsp-core/src/lsp/config-loader.ts
3782
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
3702
3783
  function getProjectConfigPaths() {
3703
3784
  return lspRequestContext().projectConfigPaths;
3704
3785
  }
@@ -3706,7 +3787,7 @@ function getUserConfigPath() {
3706
3787
  return lspRequestContext().userConfigPath;
3707
3788
  }
3708
3789
  function loadJsonFile(path) {
3709
- if (!existsSync7(path))
3790
+ if (!existsSync8(path))
3710
3791
  return null;
3711
3792
  try {
3712
3793
  const parsed = JSON.parse(readFileSync4(path, "utf-8"));
@@ -3894,54 +3975,155 @@ function getDisabledServerIds() {
3894
3975
  }
3895
3976
 
3896
3977
  // ../lsp-core/src/lsp/server-installation.ts
3897
- import { existsSync as existsSync8 } from "node:fs";
3898
- import { delimiter as delimiter3, join as join3 } from "node:path";
3899
- function isServerInstalled(command, _workingDirectory) {
3900
- if (command.length === 0)
3901
- return false;
3902
- const [cmd] = command;
3903
- if (!cmd)
3904
- return false;
3905
- if (cmd.includes("/") || cmd.includes("\\")) {
3906
- if (existsSync8(cmd))
3907
- return true;
3978
+ import { existsSync as existsSync9 } from "node:fs";
3979
+ import { delimiter as delimiter3, dirname as dirname7, isAbsolute as isAbsolute3, join as join4, resolve as resolve7 } from "node:path";
3980
+ var LOCAL_BIN_RULES = [
3981
+ {
3982
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
3983
+ binDirs: [join4("node_modules", ".bin")]
3984
+ },
3985
+ {
3986
+ markers: [
3987
+ "pyproject.toml",
3988
+ "ty.toml",
3989
+ "requirements.txt",
3990
+ "setup.py",
3991
+ "setup.cfg",
3992
+ "Pipfile",
3993
+ "pyrightconfig.json",
3994
+ "ruff.toml",
3995
+ ".ruff.toml"
3996
+ ],
3997
+ binDirs: [
3998
+ join4(".venv", "bin"),
3999
+ join4(".venv", "Scripts"),
4000
+ join4("venv", "bin"),
4001
+ join4("venv", "Scripts"),
4002
+ join4(".env", "bin"),
4003
+ join4(".env", "Scripts")
4004
+ ]
4005
+ },
4006
+ {
4007
+ markers: ["Gemfile", "Gemfile.lock"],
4008
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
4009
+ },
4010
+ {
4011
+ markers: ["go.mod", "go.sum", "go.work"],
4012
+ binDirs: ["bin"]
4013
+ }
4014
+ ];
4015
+ var resolutionCache = new Map;
4016
+ var probeCount = 0;
4017
+ function probe(path) {
4018
+ probeCount += 1;
4019
+ return existsSync9(path);
4020
+ }
4021
+ function executableSuffixes(platform, pathExt) {
4022
+ if (platform !== "win32")
4023
+ return [""];
4024
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
4025
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
4026
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4027
+ }
4028
+ function probeWithSuffixes(directory, command, suffixes) {
4029
+ for (const suffix of suffixes) {
4030
+ const candidate = join4(directory, command + suffix);
4031
+ if (probe(candidate))
4032
+ return candidate;
3908
4033
  }
3909
- const isWindows = process.platform === "win32";
3910
- let exts = [""];
3911
- if (isWindows) {
3912
- const pathExt = process.env["PATHEXT"] ?? "";
3913
- if (pathExt) {
3914
- const systemExts = pathExt.split(";").filter(Boolean);
3915
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
3916
- } else {
3917
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
4034
+ return null;
4035
+ }
4036
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
4037
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
4038
+ let current = resolve7(workingDirectory);
4039
+ while (true) {
4040
+ for (const rule of LOCAL_BIN_RULES) {
4041
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
4042
+ continue;
4043
+ for (const binDir of rule.binDirs) {
4044
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
4045
+ if (found !== null)
4046
+ return found;
4047
+ }
3918
4048
  }
4049
+ if (probe(join4(current, ".git")))
4050
+ return null;
4051
+ if (boundary !== undefined && current === boundary)
4052
+ return null;
4053
+ const parent = dirname7(current);
4054
+ if (parent === current)
4055
+ return null;
4056
+ current = parent;
3919
4057
  }
3920
- let pathEnv = process.env["PATH"] ?? "";
3921
- if (isWindows && !pathEnv) {
4058
+ }
4059
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
4060
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
4061
+ if (platform === "win32" && !pathEnv) {
3922
4062
  pathEnv = process.env["Path"] ?? "";
3923
4063
  }
3924
- const paths = pathEnv.split(delimiter3);
3925
- for (const p of paths) {
3926
- for (const suffix of exts) {
3927
- if (existsSync8(join3(p, cmd + suffix))) {
3928
- return true;
3929
- }
3930
- }
4064
+ for (const entry of pathEnv.split(delimiter3)) {
4065
+ if (entry.length === 0)
4066
+ continue;
4067
+ const found = probeWithSuffixes(entry, command, suffixes);
4068
+ if (found !== null)
4069
+ return found;
3931
4070
  }
3932
- if (cmd === "node")
3933
- return true;
3934
- return false;
4071
+ return null;
4072
+ }
4073
+ function resolveServerBinary(command, workingDirectory, options = {}) {
4074
+ if (command.length === 0)
4075
+ return null;
4076
+ const [cmd] = command;
4077
+ if (cmd === undefined || cmd.length === 0)
4078
+ return null;
4079
+ const platform = options.platform ?? process.platform;
4080
+ const suffixes = executableSuffixes(platform, options.pathExt);
4081
+ if (cmd.includes("/") || cmd.includes("\\")) {
4082
+ const explicit = isAbsolute3(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
4083
+ return probe(explicit) ? explicit : null;
4084
+ }
4085
+ const cacheKey = JSON.stringify([
4086
+ workingDirectory ?? "",
4087
+ cmd,
4088
+ platform,
4089
+ options.stopAt ?? "",
4090
+ options.pathExt ?? "",
4091
+ options.pathEnv ?? process.env["PATH"] ?? ""
4092
+ ]);
4093
+ const cached = resolutionCache.get(cacheKey);
4094
+ if (cached !== undefined)
4095
+ return cached;
4096
+ let resolved = null;
4097
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
4098
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
4099
+ }
4100
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
4101
+ if (resolved === null && cmd === "node")
4102
+ resolved = cmd;
4103
+ resolutionCache.set(cacheKey, resolved);
4104
+ return resolved;
4105
+ }
4106
+ function isServerInstalled(command, workingDirectory, options = {}) {
4107
+ if (command.length === 0)
4108
+ return false;
4109
+ return resolveServerBinary(command, workingDirectory, options) !== null;
3935
4110
  }
3936
4111
 
3937
4112
  // ../lsp-core/src/lsp/server-resolution.ts
4113
+ function withResolvedCommand(command, binaryPath) {
4114
+ return [binaryPath, ...command.slice(1)];
4115
+ }
3938
4116
  function findServerForExtension(ext) {
3939
4117
  const servers = getMergedServers();
4118
+ const workingDirectory = contextCwd();
3940
4119
  for (const server2 of servers) {
3941
- if (server2.extensions.includes(ext) && isServerInstalled(server2.command)) {
4120
+ if (!server2.extensions.includes(ext))
4121
+ continue;
4122
+ const binaryPath = resolveServerBinary(server2.command, workingDirectory);
4123
+ if (binaryPath !== null) {
3942
4124
  const resolvedServer = {
3943
4125
  id: server2.id,
3944
- command: server2.command,
4126
+ command: withResolvedCommand(server2.command, binaryPath),
3945
4127
  extensions: server2.extensions,
3946
4128
  priority: server2.priority
3947
4129
  };
@@ -3988,6 +4170,7 @@ function findServerForExtension(ext) {
3988
4170
  function getAllServers() {
3989
4171
  const servers = getMergedServers();
3990
4172
  const disabled = getDisabledServerIds();
4173
+ const workingDirectory = contextCwd();
3991
4174
  const result = [];
3992
4175
  const seen = new Set;
3993
4176
  for (const server2 of servers) {
@@ -3995,7 +4178,7 @@ function getAllServers() {
3995
4178
  continue;
3996
4179
  result.push({
3997
4180
  id: server2.id,
3998
- installed: isServerInstalled(server2.command),
4181
+ installed: isServerInstalled(server2.command, workingDirectory),
3999
4182
  extensions: server2.extensions,
4000
4183
  disabled: false,
4001
4184
  source: server2.source,
@@ -4009,7 +4192,7 @@ function getAllServers() {
4009
4192
  const builtin = BUILTIN_SERVERS[id];
4010
4193
  result.push({
4011
4194
  id,
4012
- installed: builtin ? isServerInstalled(builtin.command) : false,
4195
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
4013
4196
  extensions: builtin?.extensions ?? [],
4014
4197
  disabled: true,
4015
4198
  source: "disabled",
@@ -4020,7 +4203,6 @@ function getAllServers() {
4020
4203
  }
4021
4204
 
4022
4205
  // ../lsp-core/src/lsp/client-wrapper.ts
4023
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
4024
4206
  function isDirectoryPath(filePath) {
4025
4207
  try {
4026
4208
  return statSync3(filePath).isDirectory();
@@ -4029,32 +4211,85 @@ function isDirectoryPath(filePath) {
4029
4211
  }
4030
4212
  }
4031
4213
  function findWorkspaceRoot(filePath) {
4032
- const abs = resolvePathInsideContext(filePath);
4214
+ const cwd = contextCwd();
4215
+ const abs = resolveReadablePathInsideContext(filePath);
4033
4216
  let dir = abs;
4034
4217
  if (!isDirectoryPath(dir)) {
4035
- dir = dirname6(dir);
4036
- }
4037
- let prevDir = "";
4038
- while (dir !== prevDir) {
4039
- for (const marker of WORKSPACE_MARKERS) {
4040
- if (existsSync9(join4(dir, marker))) {
4041
- return dir;
4218
+ dir = dirname8(dir);
4219
+ }
4220
+ if (!isPathInside(cwd, abs))
4221
+ return findWorkspaceRootOutsideContext(dir);
4222
+ const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4223
+ while (isPathInside(cwd, dir)) {
4224
+ const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4225
+ if (canonicalDir !== undefined) {
4226
+ for (const marker of WORKSPACE_MARKERS) {
4227
+ if (existsSync10(join5(dir, marker))) {
4228
+ return canonicalDir;
4229
+ }
4042
4230
  }
4043
4231
  }
4044
- prevDir = dir;
4045
- dir = dirname6(dir);
4232
+ if (dir === cwd)
4233
+ break;
4234
+ dir = dirname8(dir);
4046
4235
  }
4047
- return dirname6(abs);
4236
+ return fallbackRoot;
4237
+ }
4238
+ function resolveReadablePathInsideContext(filePath) {
4239
+ const cwd = contextCwd();
4240
+ const abs = resolve8(cwd, filePath);
4241
+ if (isPathInside(cwd, abs))
4242
+ return abs;
4243
+ const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4244
+ if (rebased !== undefined)
4245
+ return rebased;
4246
+ return canonicalizeExistingOrNearestAncestor(abs);
4048
4247
  }
4049
4248
  function resolvePathInsideContext(filePath) {
4050
4249
  const cwd = contextCwd();
4051
- const abs = resolve7(cwd, filePath);
4250
+ const abs = resolveReadablePathInsideContext(filePath);
4052
4251
  const canonical = canonicalizeExistingOrNearestAncestor(abs);
4053
4252
  if (!isPathInside(cwd, canonical)) {
4054
4253
  throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
4055
4254
  }
4056
4255
  return canonical;
4057
4256
  }
4257
+ function rebaseThroughCanonicalAncestor(path, cwd) {
4258
+ let current = path;
4259
+ const suffix = [];
4260
+ while (true) {
4261
+ if (existsSync10(current)) {
4262
+ const canonical = realpathSync5(current);
4263
+ if (isPathInside(cwd, canonical))
4264
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
4265
+ }
4266
+ const parent = dirname8(current);
4267
+ if (parent === current)
4268
+ return;
4269
+ suffix.unshift(basename3(current));
4270
+ current = parent;
4271
+ }
4272
+ }
4273
+ function existingDirectoryInsideContext(directory, cwd) {
4274
+ if (!existsSync10(directory))
4275
+ return;
4276
+ const canonical = realpathSync5(directory);
4277
+ if (!statSync3(canonical).isDirectory())
4278
+ return;
4279
+ return isPathInside(cwd, canonical) ? canonical : undefined;
4280
+ }
4281
+ function nearestExistingDirectoryInsideContext(directory, cwd) {
4282
+ let current = directory;
4283
+ while (isPathInside(cwd, current)) {
4284
+ const canonical = existingDirectoryInsideContext(current, cwd);
4285
+ if (canonical !== undefined)
4286
+ return canonical;
4287
+ if (current === cwd)
4288
+ return;
4289
+ current = dirname8(current);
4290
+ }
4291
+ return;
4292
+ }
4058
4293
  function formatServerLookupError(result) {
4059
4294
  if (result.status === "not_installed") {
4060
4295
  return formatNotInstalled(result);
@@ -4078,6 +4313,19 @@ function formatServerLookupError(result) {
4078
4313
  ].join(`
4079
4314
  `);
4080
4315
  }
4316
+ function formatInstallOptions(serverId, installHint) {
4317
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
4318
+ if (localHint === undefined) {
4319
+ return ["To install, run:", ` ${installHint}`];
4320
+ }
4321
+ return [
4322
+ "To install in THIS repository (preferred — no global install needed):",
4323
+ ` ${localHint}`,
4324
+ "",
4325
+ "Or install it globally:",
4326
+ ` ${installHint}`
4327
+ ];
4328
+ }
4081
4329
  function formatNotInstalled(result) {
4082
4330
  const { server: server2, installHint } = result;
4083
4331
  const extensions = server2.extensions.join(", ");
@@ -4092,19 +4340,19 @@ function formatNotInstalled(result) {
4092
4340
  `Command not found: ${server2.command[0]}`,
4093
4341
  ""
4094
4342
  ];
4343
+ const installOptions = formatInstallOptions(server2.id, installHint);
4095
4344
  if (decision === "allowed") {
4096
4345
  return [
4097
4346
  ...header,
4098
4347
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
4099
- ` ${installHint}`
4348
+ ...installOptions.slice(1)
4100
4349
  ].join(`
4101
4350
  `);
4102
4351
  }
4103
4352
  if (!context.capabilities.installDecisionTool) {
4104
4353
  return [
4105
4354
  ...header,
4106
- "To install, run:",
4107
- ` ${installHint}`,
4355
+ ...installOptions,
4108
4356
  "",
4109
4357
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4110
4358
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -4113,8 +4361,7 @@ function formatNotInstalled(result) {
4113
4361
  }
4114
4362
  return [
4115
4363
  ...header,
4116
- "To install, run:",
4117
- ` ${installHint}`,
4364
+ ...installOptions,
4118
4365
  "",
4119
4366
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4120
4367
  "- If the user agrees: run the install command above, then retry this tool.",
@@ -4125,7 +4372,7 @@ function formatNotInstalled(result) {
4125
4372
  ].join(`
4126
4373
  `);
4127
4374
  }
4128
- var READ_ONLY_RETRY_TOOLS = new Set([
4375
+ var READ_ONLY_TOOLS = new Set([
4129
4376
  "diagnostics",
4130
4377
  "definition",
4131
4378
  "references",
@@ -4134,7 +4381,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
4134
4381
  "prepareRename"
4135
4382
  ]);
4136
4383
  async function withLspClient(filePath, fn, toolName, options = {}) {
4137
- const absPath = resolvePathInsideContext(filePath);
4384
+ const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
4138
4385
  if (isDirectoryPath(absPath)) {
4139
4386
  throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
4140
4387
  }
@@ -4149,9 +4396,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4149
4396
  const acquireAndCall = async (allowRetry) => {
4150
4397
  const client = await manager.getClient(root, server2, options.signal);
4151
4398
  try {
4152
- return await fn(client, root);
4399
+ return await fn(client, root, absPath);
4153
4400
  } catch (err) {
4154
- if (allowRetry && READ_ONLY_RETRY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4401
+ if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4155
4402
  manager.invalidateClient(root, server2.id, client);
4156
4403
  return acquireAndCall(false);
4157
4404
  }
@@ -4169,8 +4416,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4169
4416
  }
4170
4417
 
4171
4418
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4172
- import { existsSync as existsSync10, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4173
- import { join as join5, resolve as resolve8 } from "node:path";
4419
+ import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4420
+ import { join as join6, resolve as resolve9 } from "node:path";
4174
4421
 
4175
4422
  // ../lsp-core/src/lsp/formatters.ts
4176
4423
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -4300,7 +4547,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
4300
4547
  for (const entry of entries) {
4301
4548
  if (files.length >= maxFiles)
4302
4549
  return;
4303
- const fullPath = join5(currentDir, entry);
4550
+ const fullPath = join6(currentDir, entry);
4304
4551
  let stat;
4305
4552
  try {
4306
4553
  stat = lstatSync4(fullPath);
@@ -4325,8 +4572,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4325
4572
  if (!extension.startsWith(".")) {
4326
4573
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4327
4574
  }
4328
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4329
- if (!existsSync10(absDir)) {
4575
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
4576
+ if (!existsSync11(absDir)) {
4330
4577
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4331
4578
  }
4332
4579
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
@@ -4413,7 +4660,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4413
4660
 
4414
4661
  // ../lsp-core/src/lsp/infer-extension.ts
4415
4662
  import { lstatSync as lstatSync5, readdirSync as readdirSync4 } from "node:fs";
4416
- import { join as join6 } from "node:path";
4663
+ import { join as join7 } from "node:path";
4417
4664
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
4418
4665
  var MAX_SCAN_ENTRIES = 500;
4419
4666
  function inferExtensionFromDirectory(directory) {
@@ -4431,7 +4678,7 @@ function inferExtensionFromDirectory(directory) {
4431
4678
  for (const entry of entries) {
4432
4679
  if (scanned >= MAX_SCAN_ENTRIES)
4433
4680
  return;
4434
- const fullPath = join6(dir, entry);
4681
+ const fullPath = join7(dir, entry);
4435
4682
  let stat;
4436
4683
  try {
4437
4684
  stat = lstatSync5(fullPath);
@@ -4606,7 +4853,7 @@ async function executeLspDiagnostics(params, signal) {
4606
4853
  const filePath = requireString(params, "filePath");
4607
4854
  const severity = severityFilter(params);
4608
4855
  try {
4609
- const absPath = resolvePathInsideContext(filePath);
4856
+ const absPath = resolveReadablePathInsideContext(filePath);
4610
4857
  if (isDirectoryPath(absPath)) {
4611
4858
  const extension = inferExtensionFromDirectory(absPath);
4612
4859
  if (!extension) {
@@ -4635,7 +4882,7 @@ async function executeLspDiagnostics(params, signal) {
4635
4882
  };
4636
4883
  return text(output2.output, details2);
4637
4884
  }
4638
- const result = await withLspClient(filePath, async (client) => client.diagnostics(filePath, signal), "diagnostics", clientOptions(signal));
4885
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
4639
4886
  if (result.transientError) {
4640
4887
  const message = result.transientError.message;
4641
4888
  const details2 = {
@@ -4682,6 +4929,96 @@ async function executeLspDiagnostics(params, signal) {
4682
4929
  throw error;
4683
4930
  }
4684
4931
  }
4932
+ // ../lsp-core/src/lsp/format-document.ts
4933
+ import { readFileSync as readFileSync5, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
4934
+ var DEFAULT_FORMATTING_OPTIONS = {
4935
+ tabSize: 4,
4936
+ insertSpaces: false,
4937
+ trimTrailingWhitespace: true,
4938
+ insertFinalNewline: true,
4939
+ trimFinalNewlines: true
4940
+ };
4941
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
4942
+ async function formatDocumentWithClient(client, filePath, options = {}) {
4943
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
4944
+ if (edits === null)
4945
+ return { status: "unavailable", reason: "capability_not_advertised" };
4946
+ if (edits.length === 0)
4947
+ return UNCHANGED;
4948
+ const before = readFileSync5(filePath, "utf-8");
4949
+ const normalized = normalizeTextEdits(before, edits, 0);
4950
+ if (normalized.text === before)
4951
+ return UNCHANGED;
4952
+ writeAtomically(filePath, normalized.text);
4953
+ await client.openFile(filePath);
4954
+ return {
4955
+ status: "formatted",
4956
+ ...lineDelta(normalized.edits)
4957
+ };
4958
+ }
4959
+ function lineDelta(edits) {
4960
+ let linesAdded = 0;
4961
+ let linesRemoved = 0;
4962
+ for (const edit of edits) {
4963
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
4964
+ linesAdded += edit.newText.split(`
4965
+ `).length;
4966
+ }
4967
+ return { linesAdded, linesRemoved };
4968
+ }
4969
+ function writeAtomically(filePath, content) {
4970
+ const tempPath = `${filePath}.omo-format.tmp`;
4971
+ writeFileSync3(tempPath, content, "utf-8");
4972
+ try {
4973
+ renameSync3(tempPath, filePath);
4974
+ } catch (error) {
4975
+ try {
4976
+ unlinkSync(tempPath);
4977
+ } catch {}
4978
+ throw error;
4979
+ }
4980
+ }
4981
+
4982
+ // ../lsp-core/src/tools/format.ts
4983
+ async function executeLspFormat(params, signal) {
4984
+ const filePath = requireString(params, "filePath");
4985
+ try {
4986
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
4987
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
4988
+ } catch (error) {
4989
+ const missingDependency = missingDependencyResult(error, {
4990
+ filePath,
4991
+ status: "unavailable",
4992
+ reason: "server_unavailable",
4993
+ linesAdded: 0,
4994
+ linesRemoved: 0
4995
+ });
4996
+ if (missingDependency)
4997
+ return missingDependency;
4998
+ throw error;
4999
+ }
5000
+ }
5001
+ function formatDetails(filePath, result) {
5002
+ if (result.status === "unavailable") {
5003
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
5004
+ }
5005
+ return {
5006
+ filePath,
5007
+ status: result.status,
5008
+ linesAdded: result.linesAdded,
5009
+ linesRemoved: result.linesRemoved
5010
+ };
5011
+ }
5012
+ function describeResult(filePath, result) {
5013
+ if (result.status === "unavailable") {
5014
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
5015
+ }
5016
+ if (result.status === "unchanged") {
5017
+ return `Already formatted: ${filePath}`;
5018
+ }
5019
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
5020
+ }
5021
+
4685
5022
  // ../lsp-core/src/tools/install-decision.ts
4686
5023
  async function executeLspInstallDecision(params) {
4687
5024
  const serverId = requireString(params, "server_id");
@@ -4710,7 +5047,7 @@ async function executeLspGotoDefinition(params, signal) {
4710
5047
  const line = requireNumber(params, "line");
4711
5048
  const character = requireNumber(params, "character");
4712
5049
  try {
4713
- const result = await withLspClient(filePath, async (client) => client.definition(filePath, line, character, signal), "definition", clientOptions(signal));
5050
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
4714
5051
  const locations = !result ? [] : Array.isArray(result) ? result : [result];
4715
5052
  const details = { filePath, line, character, locations };
4716
5053
  if (locations.length === 0)
@@ -4735,7 +5072,7 @@ async function executeLspFindReferences(params, signal) {
4735
5072
  const character = requireNumber(params, "character");
4736
5073
  const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
4737
5074
  try {
4738
- const result = await withLspClient(filePath, async (client) => client.references(filePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5075
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
4739
5076
  const references = Array.isArray(result) ? result : [];
4740
5077
  const total = references.length;
4741
5078
  const truncated = total > DEFAULT_MAX_REFERENCES;
@@ -4777,7 +5114,7 @@ async function executeLspPrepareRename(params, signal) {
4777
5114
  const line = requireNumber(params, "line");
4778
5115
  const character = requireNumber(params, "character");
4779
5116
  try {
4780
- const result = await withLspClient(filePath, async (client) => client.prepareRename(filePath, line, character, signal), "prepareRename", clientOptions(signal));
5117
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
4781
5118
  const details = { filePath, line, character, result };
4782
5119
  return text(formatPrepareRenameResult(result), details);
4783
5120
  } catch (error) {
@@ -4798,7 +5135,7 @@ async function executeLspRename(params, signal) {
4798
5135
  const character = requireNumber(params, "character");
4799
5136
  const newName = requireString(params, "newName");
4800
5137
  try {
4801
- const result = await withLspClient(filePath, async (client) => client.rename(filePath, line, character, newName, signal), "rename", clientOptions(signal));
5138
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
4802
5139
  const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
4803
5140
  return text(formatApplyResult(result.apply), details, !result.apply.success);
4804
5141
  } catch (error) {
@@ -4878,7 +5215,7 @@ async function executeLspSymbols(params, signal) {
4878
5215
  const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
4879
5216
  return formatSymbolsResult(filePath, scope, symbols2, limit, query);
4880
5217
  }
4881
- const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(filePath, signal), "documentSymbols", clientOptions(signal));
5218
+ const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
4882
5219
  return formatSymbolsResult(filePath, scope, symbols, limit);
4883
5220
  } catch (error) {
4884
5221
  const query = optionalString(params, "query");
@@ -5014,6 +5351,16 @@ var LSP_MCP_TOOLS = [
5014
5351
  }, ["filePath", "line", "character", "newName"]),
5015
5352
  execute: executeLspRename
5016
5353
  },
5354
+ {
5355
+ name: "format",
5356
+ aliases: ["lsp_format"],
5357
+ title: "LSP Format",
5358
+ description: "Format a source file with its language server and write the returned edits to disk.",
5359
+ inputSchema: objectSchema({
5360
+ filePath: { type: "string", description: "Source file path to format." }
5361
+ }, ["filePath"]),
5362
+ execute: executeLspFormat
5363
+ },
5017
5364
  {
5018
5365
  name: "install_decision",
5019
5366
  aliases: ["lsp_install_decision"],
@@ -5113,11 +5460,10 @@ function requestedProtocolVersion(params) {
5113
5460
  // src/daemon-client.ts
5114
5461
  import { connect } from "node:net";
5115
5462
  import { homedir as homedir3 } from "node:os";
5116
- import { join as join7 } from "node:path";
5463
+ import { join as join8 } from "node:path";
5117
5464
 
5118
5465
  // src/daemon-request-error.ts
5119
5466
  class DaemonRequestError extends Error {
5120
- requestWritten;
5121
5467
  constructor(message, requestWritten) {
5122
5468
  super(message);
5123
5469
  this.name = "DaemonRequestError";
@@ -5140,7 +5486,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
5140
5486
  }
5141
5487
 
5142
5488
  class DaemonRequestTimedOutError extends DaemonRequestError {
5143
- timeoutMs;
5144
5489
  constructor(requestWritten, timeoutMs) {
5145
5490
  super("daemon request timed out", requestWritten);
5146
5491
  this.name = "DaemonRequestTimedOutError";
@@ -5192,9 +5537,9 @@ function errorText(error) {
5192
5537
 
5193
5538
  // src/ensure-daemon.ts
5194
5539
  import { spawn as spawn2 } from "node:child_process";
5195
- import { closeSync as closeSync2, existsSync as existsSync11, mkdirSync as mkdirSync3, openSync as openSync2, writeSync as writeSync2 } from "node:fs";
5540
+ import { closeSync as closeSync2, existsSync as existsSync12, mkdirSync as mkdirSync3, openSync as openSync2, writeSync as writeSync2 } from "node:fs";
5196
5541
  import { Socket } from "node:net";
5197
- import { dirname as dirname8, isAbsolute as isAbsolute4 } from "node:path";
5542
+ import { dirname as dirname10, isAbsolute as isAbsolute5 } from "node:path";
5198
5543
  import { argv0, execPath } from "node:process";
5199
5544
 
5200
5545
  // src/ipc-protocol.ts
@@ -5208,25 +5553,23 @@ import {
5208
5553
  lstatSync as lstatSync6,
5209
5554
  mkdirSync as mkdirSync2,
5210
5555
  openSync,
5211
- readFileSync as readFileSync5,
5212
- unlinkSync,
5556
+ readFileSync as readFileSync6,
5557
+ unlinkSync as unlinkSync2,
5213
5558
  writeSync
5214
5559
  } from "node:fs";
5215
- import { dirname as dirname7 } from "node:path";
5560
+ import { dirname as dirname9 } from "node:path";
5216
5561
  var OMO_DAEMON_PROTOCOL_VERSION = 1;
5217
5562
  var AUTH_ERROR_CODE = -32001;
5218
5563
  var PROTOCOL_ERROR_CODE = -32002;
5219
5564
  var AUTH_TOKEN_BYTES = 32;
5220
5565
 
5221
5566
  class UnsafePrivateDirectoryError extends Error {
5222
- path;
5223
- reason;
5224
- name = "UnsafePrivateDirectoryError";
5225
- code = "unsafe_private_directory";
5226
5567
  constructor(path, reason) {
5227
5568
  super(`unsafe private directory ${path}: ${reason}`);
5228
5569
  this.path = path;
5229
5570
  this.reason = reason;
5571
+ this.name = "UnsafePrivateDirectoryError";
5572
+ this.code = "unsafe_private_directory";
5230
5573
  }
5231
5574
  }
5232
5575
  function authEnvelope(token) {
@@ -5234,7 +5577,7 @@ function authEnvelope(token) {
5234
5577
  }
5235
5578
  function readAuthToken(paths) {
5236
5579
  try {
5237
- const token = readFileSync5(paths.auth, "utf8").trim();
5580
+ const token = readFileSync6(paths.auth, "utf8").trim();
5238
5581
  return token.length > 0 ? token : null;
5239
5582
  } catch (error) {
5240
5583
  if (error instanceof Error)
@@ -5250,7 +5593,7 @@ function readOrCreateAuthToken(paths) {
5250
5593
  }
5251
5594
  function rotateAuthToken(paths) {
5252
5595
  try {
5253
- unlinkSync(paths.auth);
5596
+ unlinkSync2(paths.auth);
5254
5597
  } catch (error) {
5255
5598
  if (!(error instanceof Error))
5256
5599
  throw error;
@@ -5322,7 +5665,7 @@ function setPrivateFileMode(path) {
5322
5665
  chmodSync(path, 384);
5323
5666
  }
5324
5667
  function createAuthToken(paths) {
5325
- ensurePrivateDirectory(dirname7(paths.auth));
5668
+ ensurePrivateDirectory(dirname9(paths.auth));
5326
5669
  const token = randomBytes(AUTH_TOKEN_BYTES).toString("base64url");
5327
5670
  let fd;
5328
5671
  try {
@@ -5403,27 +5746,25 @@ import { fileURLToPath as fileURLToPath3 } from "node:url";
5403
5746
 
5404
5747
  // src/runtime-contract.ts
5405
5748
  import { statSync as statSync4 } from "node:fs";
5406
- import { isAbsolute as isAbsolute3 } from "node:path";
5749
+ import { isAbsolute as isAbsolute4 } from "node:path";
5407
5750
  var OMO_LSP_DAEMON_DIR = "OMO_LSP_DAEMON_DIR";
5408
5751
  var OMO_LSP_DAEMON_CLI = "OMO_LSP_DAEMON_CLI";
5409
5752
  var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
5410
5753
  var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
5411
5754
 
5412
5755
  class InvalidRuntimeOverrideError extends Error {
5413
- code = "invalid_runtime_override";
5414
- reason;
5415
5756
  constructor(reason, message) {
5416
5757
  super(message);
5758
+ this.code = "invalid_runtime_override";
5417
5759
  this.name = "InvalidRuntimeOverrideError";
5418
5760
  this.reason = reason;
5419
5761
  }
5420
5762
  }
5421
5763
 
5422
5764
  class InvalidDaemonVersionError extends Error {
5423
- code = "invalid_daemon_version";
5424
- version;
5425
5765
  constructor(version) {
5426
5766
  super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
5767
+ this.code = "invalid_daemon_version";
5427
5768
  this.name = "InvalidDaemonVersionError";
5428
5769
  this.version = version;
5429
5770
  }
@@ -5442,12 +5783,12 @@ function resolveDaemonRuntime(env, defaults) {
5442
5783
  throw new InvalidRuntimeOverrideError("paired_values_required", `${OMO_LSP_DAEMON_CLI} and ${OMO_LSP_DAEMON_VERSION} must be set together`);
5443
5784
  }
5444
5785
  if (!hasCliOverride || !hasVersionOverride) {
5445
- if (!isAbsolute3(defaults.cliPath)) {
5786
+ if (!isAbsolute4(defaults.cliPath)) {
5446
5787
  throw new InvalidRuntimeOverrideError("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
5447
5788
  }
5448
5789
  return { cliPath: defaults.cliPath, version: validateDaemonVersion(defaults.version) };
5449
5790
  }
5450
- if (!isAbsolute3(cliOverride)) {
5791
+ if (!isAbsolute4(cliOverride)) {
5451
5792
  throw new InvalidRuntimeOverrideError("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI} must be an absolute path to an existing regular file`);
5452
5793
  }
5453
5794
  let cliStats;
@@ -5469,10 +5810,9 @@ var requireFromHere = createRequire(import.meta.url);
5469
5810
  var MAX_SOCKET_PATH_LENGTH = 100;
5470
5811
 
5471
5812
  class InvalidDaemonDirectoryError extends Error {
5472
- code = "invalid_daemon_directory";
5473
- directory;
5474
5813
  constructor(directory) {
5475
5814
  super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
5815
+ this.code = "invalid_daemon_directory";
5476
5816
  this.name = "InvalidDaemonDirectoryError";
5477
5817
  this.directory = directory;
5478
5818
  }
@@ -5626,7 +5966,7 @@ async function probeDaemon(paths, timeoutMs = PROBE_TIMEOUT_MS, signal) {
5626
5966
  return await pingDaemon(paths, token, timeoutMs, signal) !== null;
5627
5967
  }
5628
5968
  function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
5629
- return new Promise((resolve9) => {
5969
+ return new Promise((resolve10) => {
5630
5970
  const socket = new Socket;
5631
5971
  let settled = false;
5632
5972
  let timer;
@@ -5638,7 +5978,7 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
5638
5978
  clearTimeout(timer);
5639
5979
  signal?.removeEventListener("abort", onAbort);
5640
5980
  socket.destroy();
5641
- resolve9(value);
5981
+ resolve10(value);
5642
5982
  };
5643
5983
  const onAbort = () => finish(null);
5644
5984
  const decoder = createLineDecoder((message) => {
@@ -5662,12 +6002,13 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
5662
6002
  });
5663
6003
  }
5664
6004
  function spawnDaemonProcess(paths) {
5665
- mkdirSync3(dirname8(paths.log), { recursive: true });
6005
+ mkdirSync3(dirname10(paths.log), { recursive: true });
5666
6006
  const logFd = openSync2(paths.log, "a");
5667
6007
  try {
5668
6008
  const child = spawn2(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
5669
6009
  detached: true,
5670
- stdio: ["ignore", logFd, logFd]
6010
+ stdio: ["ignore", logFd, logFd],
6011
+ windowsHide: true
5671
6012
  });
5672
6013
  child.once("spawn", () => closeSync2(logFd));
5673
6014
  child.once("error", (error) => {
@@ -5681,10 +6022,10 @@ function spawnDaemonProcess(paths) {
5681
6022
  throw error;
5682
6023
  }
5683
6024
  }
5684
- function resolveDaemonNodeExecutable(cachedExecPath = execPath, originalArgv0 = argv0, pathExists = existsSync11) {
6025
+ function resolveDaemonNodeExecutable(cachedExecPath = execPath, originalArgv0 = argv0, pathExists = existsSync12) {
5685
6026
  if (pathExists(cachedExecPath))
5686
6027
  return cachedExecPath;
5687
- if (isAbsolute4(originalArgv0) && pathExists(originalArgv0))
6028
+ if (isAbsolute5(originalArgv0) && pathExists(originalArgv0))
5688
6029
  return originalArgv0;
5689
6030
  return "node";
5690
6031
  }
@@ -5697,7 +6038,7 @@ function defaultEnsureDaemonDeps() {
5697
6038
  };
5698
6039
  }
5699
6040
  function sleepWithSignal(ms, signal) {
5700
- return new Promise((resolve9) => {
6041
+ return new Promise((resolve10) => {
5701
6042
  let settled = false;
5702
6043
  const finish = () => {
5703
6044
  if (settled)
@@ -5705,7 +6046,7 @@ function sleepWithSignal(ms, signal) {
5705
6046
  settled = true;
5706
6047
  clearTimeout(timer);
5707
6048
  signal?.removeEventListener("abort", finish);
5708
- resolve9();
6049
+ resolve10();
5709
6050
  };
5710
6051
  const timer = setTimeout(finish, ms);
5711
6052
  if (signal?.aborted) {
@@ -5720,7 +6061,7 @@ function awaitWithSignal2(promise, signal) {
5720
6061
  return promise;
5721
6062
  if (signal.aborted)
5722
6063
  return Promise.reject(abortError3(signal));
5723
- return new Promise((resolve9, reject) => {
6064
+ return new Promise((resolve10, reject) => {
5724
6065
  let settled = false;
5725
6066
  const finish = (run) => {
5726
6067
  if (settled)
@@ -5731,7 +6072,7 @@ function awaitWithSignal2(promise, signal) {
5731
6072
  };
5732
6073
  const onAbort = () => finish(() => reject(abortError3(signal)));
5733
6074
  signal.addEventListener("abort", onAbort, { once: true });
5734
- promise.then((value) => finish(() => resolve9(value)), (error) => finish(() => reject(error)));
6075
+ promise.then((value) => finish(() => resolve10(value)), (error) => finish(() => reject(error)));
5735
6076
  });
5736
6077
  }
5737
6078
  function throwIfAborted(signal) {
@@ -5780,7 +6121,10 @@ function parsePingResponse(message) {
5780
6121
  var CONTEXT_KEY = "_context";
5781
6122
 
5782
6123
  class InvalidDaemonRequestError extends Error {
5783
- name = "InvalidDaemonRequestError";
6124
+ constructor() {
6125
+ super(...arguments);
6126
+ this.name = "InvalidDaemonRequestError";
6127
+ }
5784
6128
  }
5785
6129
  function extractRequestContext(raw) {
5786
6130
  if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
@@ -5896,14 +6240,17 @@ async function callToolViaDaemon(name, args, options) {
5896
6240
  function callDiagnosticsViaDaemon(filePath, options) {
5897
6241
  return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
5898
6242
  }
6243
+ function callFormatViaDaemon(filePath, options) {
6244
+ return callToolViaDaemon("format", { filePath }, options);
6245
+ }
5899
6246
  function currentRequestContext(env = process.env) {
5900
6247
  const cwd = process.cwd();
5901
6248
  const home = env["HOME"] ?? homedir3();
5902
6249
  return parseLspRequestContext({
5903
6250
  cwd,
5904
- projectConfigPaths: [join7(cwd, ".codex", "lsp-client.json")],
5905
- userConfigPath: join7(home, ".codex", "lsp-client.json"),
5906
- installDecisionsPath: join7(home, ".codex", "lsp-install-decisions.json"),
6251
+ projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
6252
+ userConfigPath: join8(home, ".codex", "lsp-client.json"),
6253
+ installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
5907
6254
  capabilities: { installDecisionTool: true }
5908
6255
  });
5909
6256
  }
@@ -5918,7 +6265,7 @@ function withContext(args, context) {
5918
6265
  function ensureDaemonAvailable(paths, ensure, signal) {
5919
6266
  if (!signal)
5920
6267
  return ensure(paths);
5921
- return new Promise((resolve9, reject) => {
6268
+ return new Promise((resolve10, reject) => {
5922
6269
  let settled = false;
5923
6270
  const finish = (run) => {
5924
6271
  if (settled)
@@ -5933,11 +6280,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
5933
6280
  return;
5934
6281
  }
5935
6282
  signal.addEventListener("abort", onAbort, { once: true });
5936
- Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve9()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
6283
+ Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
5937
6284
  });
5938
6285
  }
5939
6286
  function sendToolCall(paths, token, name, args, options) {
5940
- return new Promise((resolve9, reject) => {
6287
+ return new Promise((resolve10, reject) => {
5941
6288
  const socket = connect(paths.socket);
5942
6289
  const requestId = allocateProxyRequestId();
5943
6290
  let settled = false;
@@ -5990,7 +6337,7 @@ function sendToolCall(paths, token, name, args, options) {
5990
6337
  }
5991
6338
  const result = toToolResult(message, requestId);
5992
6339
  if (result)
5993
- finish(() => resolve9(result));
6340
+ finish(() => resolve10(result));
5994
6341
  else
5995
6342
  finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
5996
6343
  });
@@ -6158,18 +6505,18 @@ function canonicalizePathList(value) {
6158
6505
  return value.split(delimiter4).map((entry) => canonicalizePath(entry) ?? entry).join(delimiter4);
6159
6506
  }
6160
6507
  function canonicalizePath(value) {
6161
- if (value === undefined || !isAbsolute5(value) || !existsSync12(value))
6508
+ if (value === undefined || !isAbsolute6(value) || !existsSync13(value))
6162
6509
  return value;
6163
- return realpathSync4(value);
6510
+ return realpathSync6(value);
6164
6511
  }
6165
6512
  function projectRootFromOpenCodeConfigPath(path2) {
6166
- if (basename3(path2) !== "lsp.json" && basename3(path2) !== "lsp-client.json")
6513
+ if (basename4(path2) !== "lsp.json" && basename4(path2) !== "lsp-client.json")
6167
6514
  return;
6168
- const configDir = dirname9(path2);
6169
- const configDirName = basename3(configDir);
6515
+ const configDir = dirname11(path2);
6516
+ const configDirName = basename4(configDir);
6170
6517
  if (configDirName !== ".opencode" && configDirName !== ".omo")
6171
6518
  return;
6172
- return dirname9(configDir);
6519
+ return dirname11(configDir);
6173
6520
  }
6174
6521
 
6175
6522
  // src/daemon-server.ts
@@ -6178,12 +6525,12 @@ import { createServer as createServer2 } from "node:net";
6178
6525
 
6179
6526
  // src/ownership.ts
6180
6527
  import { randomUUID } from "node:crypto";
6181
- import { existsSync as existsSync13, lstatSync as lstatSync7, readFileSync as readFileSync7, statSync as statSync5, unlinkSync as unlinkSync3 } from "node:fs";
6182
- import { dirname as dirname11 } from "node:path";
6528
+ import { existsSync as existsSync14, lstatSync as lstatSync7, readFileSync as readFileSync8, statSync as statSync5, unlinkSync as unlinkSync4 } from "node:fs";
6529
+ import { dirname as dirname13 } from "node:path";
6183
6530
 
6184
6531
  // src/lock.ts
6185
- import { closeSync as closeSync3, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeSync as writeSync3 } from "node:fs";
6186
- import { dirname as dirname10 } from "node:path";
6532
+ import { closeSync as closeSync3, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeSync as writeSync3 } from "node:fs";
6533
+ import { dirname as dirname12 } from "node:path";
6187
6534
  function isProcessAlive2(pid) {
6188
6535
  if (!Number.isInteger(pid) || pid <= 0)
6189
6536
  return false;
@@ -6198,14 +6545,14 @@ function isProcessAlive2(pid) {
6198
6545
  }
6199
6546
  function readLockPid(lockPath) {
6200
6547
  try {
6201
- const pid = Number.parseInt(readFileSync6(lockPath, "utf8").trim(), 10);
6548
+ const pid = Number.parseInt(readFileSync7(lockPath, "utf8").trim(), 10);
6202
6549
  return Number.isInteger(pid) ? pid : null;
6203
6550
  } catch {
6204
6551
  return null;
6205
6552
  }
6206
6553
  }
6207
6554
  function tryAcquireLock(lockPath, ownerPid = process.pid) {
6208
- mkdirSync4(dirname10(lockPath), { recursive: true });
6555
+ mkdirSync4(dirname12(lockPath), { recursive: true });
6209
6556
  for (let attempt = 0;attempt < 2; attempt += 1) {
6210
6557
  const handle = writeLockFile(lockPath, ownerPid);
6211
6558
  if (handle)
@@ -6237,7 +6584,7 @@ function reapStaleLock(lockPath) {
6237
6584
  }
6238
6585
  function unlinkQuietly(path2) {
6239
6586
  try {
6240
- unlinkSync2(path2);
6587
+ unlinkSync3(path2);
6241
6588
  } catch (error) {
6242
6589
  if (error instanceof Error)
6243
6590
  return;
@@ -6253,17 +6600,19 @@ function errorCode3(error) {
6253
6600
 
6254
6601
  // src/ownership.ts
6255
6602
  class DaemonAlreadyRunningError extends Error {
6256
- name = "DaemonAlreadyRunningError";
6257
- code = "daemon_already_running";
6603
+ constructor() {
6604
+ super(...arguments);
6605
+ this.name = "DaemonAlreadyRunningError";
6606
+ this.code = "daemon_already_running";
6607
+ }
6258
6608
  }
6259
6609
 
6260
6610
  class DaemonStartupDeferredError extends Error {
6261
- reason;
6262
- name = "DaemonStartupDeferredError";
6263
- code = "daemon_startup_deferred";
6264
6611
  constructor(reason) {
6265
6612
  super(`LSP daemon startup deferred: ${reason}`);
6266
6613
  this.reason = reason;
6614
+ this.name = "DaemonStartupDeferredError";
6615
+ this.code = "daemon_startup_deferred";
6267
6616
  }
6268
6617
  }
6269
6618
  async function acquireStartupLease(paths, pingOwner) {
@@ -6286,11 +6635,11 @@ async function acquireStartupLease(paths, pingOwner) {
6286
6635
  function ensureDaemonDirectories(paths) {
6287
6636
  ensurePrivateDirectory(paths.dir);
6288
6637
  if (process.platform !== "win32")
6289
- ensurePrivateDirectory(dirname11(paths.socket));
6638
+ ensurePrivateDirectory(dirname13(paths.socket));
6290
6639
  }
6291
6640
  function readDaemonOwner(paths) {
6292
6641
  try {
6293
- return parseOwner(JSON.parse(readFileSync7(paths.owner, "utf8")));
6642
+ return parseOwner(JSON.parse(readFileSync8(paths.owner, "utf8")));
6294
6643
  } catch (error) {
6295
6644
  if (error instanceof Error)
6296
6645
  return null;
@@ -6366,10 +6715,10 @@ async function validateExistingOwner(paths, pingOwner) {
6366
6715
  throw new DaemonStartupDeferredError("reachable_owner_mismatch");
6367
6716
  }
6368
6717
  function cleanupDeadOwner(paths, owner) {
6369
- if (process.platform !== "win32" && existsSync13(owner.endpoint.path)) {
6718
+ if (process.platform !== "win32" && existsSync14(owner.endpoint.path)) {
6370
6719
  const stat = lstatSync7(owner.endpoint.path);
6371
6720
  if (stat.isSocket())
6372
- unlinkSync3(owner.endpoint.path);
6721
+ unlinkSync4(owner.endpoint.path);
6373
6722
  }
6374
6723
  unlinkQuietly(paths.pid);
6375
6724
  unlinkQuietly(paths.endpoint);
@@ -6417,7 +6766,7 @@ function parseEndpoint(value) {
6417
6766
  // src/version-reap.ts
6418
6767
  import { execFile } from "node:child_process";
6419
6768
  import { readdir, readFile, rm } from "node:fs/promises";
6420
- import { basename as basename4, dirname as dirname12, join as join8 } from "node:path";
6769
+ import { basename as basename5, dirname as dirname14, join as join9 } from "node:path";
6421
6770
  var TERM_GRACE_MS = 5000;
6422
6771
  var KILL_GRACE_MS = 1000;
6423
6772
  var VERSION_ENTRY_PATTERN = /^v([A-Za-z0-9][A-Za-z0-9._+-]{0,127})$/;
@@ -6438,7 +6787,7 @@ async function attestDaemonCliProcess(pid, platform, deps = {}) {
6438
6787
  return isNodeCliDaemonCommand(command.trim());
6439
6788
  }
6440
6789
  async function reapStaleDaemonVersions(ownPaths, deps = {}) {
6441
- const baseDir = dirname12(ownPaths.dir);
6790
+ const baseDir = dirname14(ownPaths.dir);
6442
6791
  const platform = deps.platform ?? process.platform;
6443
6792
  const isAlive = deps.isAlive ?? isProcessAlive2;
6444
6793
  const attest = deps.attest ?? ((pid) => attestDaemonCliProcess(pid, platform));
@@ -6457,7 +6806,7 @@ async function reapStaleDaemonVersions(ownPaths, deps = {}) {
6457
6806
  const version = parseVersionEntry(entry.name);
6458
6807
  if (version === null || !entry.isDirectory())
6459
6808
  continue;
6460
- const versionDir = join8(baseDir, entry.name);
6809
+ const versionDir = join9(baseDir, entry.name);
6461
6810
  const siblingPaths = daemonPaths({ [OMO_LSP_DAEMON_DIR]: baseDir }, { cliPath: ownPaths.cliPath, version });
6462
6811
  results.push(await reapOneVersion({
6463
6812
  version,
@@ -6481,7 +6830,7 @@ async function reapOneVersion(context) {
6481
6830
  const { version, versionDir } = context;
6482
6831
  const owner = context.readOwner(context.siblingPaths);
6483
6832
  if (!owner) {
6484
- const lockPid = readLockPid(join8(versionDir, "daemon.lock"));
6833
+ const lockPid = readLockPid(join9(versionDir, "daemon.lock"));
6485
6834
  if (lockPid !== null && context.isAlive(lockPid)) {
6486
6835
  context.log(`reap: sparing v${version}: owner metadata missing but daemon.lock is held by live pid ${lockPid}`);
6487
6836
  return { version, status: "spared", reason: `owner metadata missing but lock held by live pid ${lockPid}` };
@@ -6547,7 +6896,7 @@ function splitCmdline(buffer) {
6547
6896
  function isNodeCliDaemonArgv(argv) {
6548
6897
  if (argv.length < 2 || !argv.includes("daemon"))
6549
6898
  return false;
6550
- const executable = basename4(argv[0] ?? "");
6899
+ const executable = basename5(argv[0] ?? "");
6551
6900
  if (!/^node(?:\.exe)?$/i.test(executable))
6552
6901
  return false;
6553
6902
  return argv.some((value) => value === "cli.js" || value.endsWith("/cli.js") || value.endsWith("\\cli.js"));
@@ -6559,13 +6908,13 @@ function defaultReadProcFile(path2) {
6559
6908
  return readFile(path2);
6560
6909
  }
6561
6910
  function defaultExecuteForStdout(file, args) {
6562
- return new Promise((resolve9) => {
6563
- execFile(file, [...args], { encoding: "utf8", maxBuffer: 1024 * 1024, timeout: 1000 }, (error, stdout) => {
6911
+ return new Promise((resolve10) => {
6912
+ execFile(file, [...args], { encoding: "utf8", maxBuffer: 1024 * 1024, timeout: 1000, windowsHide: true }, (error, stdout) => {
6564
6913
  if (error !== null) {
6565
- resolve9(null);
6914
+ resolve10(null);
6566
6915
  return;
6567
6916
  }
6568
- resolve9(stdout);
6917
+ resolve10(stdout);
6569
6918
  });
6570
6919
  });
6571
6920
  }
@@ -6584,7 +6933,7 @@ async function defaultWaitForExit(pid, timeoutMs) {
6584
6933
  return true;
6585
6934
  if (Date.now() >= deadline)
6586
6935
  return false;
6587
- await new Promise((resolve9) => setTimeout(resolve9, 100));
6936
+ await new Promise((resolve10) => setTimeout(resolve10, 100));
6588
6937
  }
6589
6938
  }
6590
6939
  function defaultLog(message) {
@@ -6691,17 +7040,17 @@ async function assertSelfProbe(paths, token, owner) {
6691
7040
  throw new DaemonStartupDeferredError("self_probe_failed");
6692
7041
  }
6693
7042
  function listen(server2, socketPath) {
6694
- return new Promise((resolve9, reject) => {
7043
+ return new Promise((resolve10, reject) => {
6695
7044
  const onError = (error) => reject(error);
6696
7045
  server2.once("error", onError);
6697
7046
  server2.listen(socketPath, () => {
6698
7047
  server2.removeListener("error", onError);
6699
- resolve9();
7048
+ resolve10();
6700
7049
  });
6701
7050
  });
6702
7051
  }
6703
7052
  function closeServer(server2) {
6704
- return new Promise((resolve9) => server2.close(() => resolve9()));
7053
+ return new Promise((resolve10) => server2.close(() => resolve10()));
6705
7054
  }
6706
7055
  function installSignalHandlers(close) {
6707
7056
  const handler = () => {