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
@@ -1,6 +1,6 @@
1
1
  // ../lsp-core/src/lsp/client-wrapper.ts
2
- import { existsSync as existsSync9, statSync as statSync3 } from "node:fs";
3
- import { dirname as dirname6, join as join4, resolve as resolve7 } from "node:path";
2
+ import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
3
+ import { basename as basename3, dirname as dirname8, join as join5, resolve as resolve8 } from "node:path";
4
4
 
5
5
  // ../lsp-core/src/request-context.ts
6
6
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -9,18 +9,17 @@ import { homedir } from "node:os";
9
9
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
10
10
 
11
11
  class LspRequestContextParseError extends Error {
12
- code;
13
- name = "LspRequestContextParseError";
14
12
  constructor(code, message) {
15
13
  super(message);
16
14
  this.code = code;
15
+ this.name = "LspRequestContextParseError";
17
16
  }
18
17
  }
19
18
 
20
19
  class LspRequestContextUnavailableError extends Error {
21
- name = "LspRequestContextUnavailableError";
22
20
  constructor() {
23
21
  super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
22
+ this.name = "LspRequestContextUnavailableError";
24
23
  }
25
24
  }
26
25
  var storage = new AsyncLocalStorage;
@@ -50,7 +49,7 @@ function contextEnv(key) {
50
49
  }
51
50
  function createStandaloneMcpRequestContext(input = {}) {
52
51
  const env = input.env ?? process.env;
53
- const cwd = canonicalCwd(input.cwd ?? process.cwd());
52
+ const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
54
53
  const home = input.homeDir ?? homedir();
55
54
  const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
56
55
  const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
@@ -193,22 +192,15 @@ function effectiveExtension(filePath) {
193
192
 
194
193
  // ../lsp-core/src/lsp/errors.ts
195
194
  class LspConnectionClosedError extends Error {
196
- serverId;
197
- root;
198
- name = "LspConnectionClosedError";
199
195
  constructor(serverId, root, message) {
200
196
  super(message ?? `LSP connection closed for ${serverId} at ${root}`);
201
197
  this.serverId = serverId;
202
198
  this.root = root;
199
+ this.name = "LspConnectionClosedError";
203
200
  }
204
201
  }
205
202
 
206
203
  class LspProcessExitedError extends Error {
207
- serverId;
208
- root;
209
- exitCode;
210
- stderrTail;
211
- name = "LspProcessExitedError";
212
204
  constructor(serverId, root, exitCode, stderrTail) {
213
205
  const stderrSuffix = stderrTail ? `
214
206
  stderr tail: ${stderrTail}` : "";
@@ -217,46 +209,49 @@ stderr tail: ${stderrTail}` : "";
217
209
  this.root = root;
218
210
  this.exitCode = exitCode;
219
211
  this.stderrTail = stderrTail;
212
+ this.name = "LspProcessExitedError";
220
213
  }
221
214
  }
222
215
 
223
216
  class LspRequestTimeoutError extends Error {
224
- method;
225
- stderrTail;
226
- name = "LspRequestTimeoutError";
227
217
  constructor(method, stderrTail) {
228
218
  const stderrSuffix = stderrTail ? `
229
219
  recent stderr: ${stderrTail}` : "";
230
220
  super(`LSP request timeout (method: ${method})${stderrSuffix}`);
231
221
  this.method = method;
232
222
  this.stderrTail = stderrTail;
223
+ this.name = "LspRequestTimeoutError";
233
224
  }
234
225
  }
235
226
 
236
227
  class LspInvalidPathError extends Error {
237
- name = "LspInvalidPathError";
228
+ constructor() {
229
+ super(...arguments);
230
+ this.name = "LspInvalidPathError";
231
+ }
238
232
  }
239
233
 
240
234
  class LspServerLookupError extends Error {
241
- lookup;
242
- name = "LspServerLookupError";
243
235
  constructor(message, lookup) {
244
236
  super(message);
245
237
  this.lookup = lookup;
238
+ this.name = "LspServerLookupError";
246
239
  }
247
240
  }
248
241
 
249
242
  class LspServerInitializingError extends Error {
250
- originalError;
251
- name = "LspServerInitializingError";
252
243
  constructor(originalError) {
253
244
  super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
254
245
  this.originalError = originalError;
246
+ this.name = "LspServerInitializingError";
255
247
  }
256
248
  }
257
249
 
258
250
  class LspProcessSpawnError extends Error {
259
- name = "LspProcessSpawnError";
251
+ constructor() {
252
+ super(...arguments);
253
+ this.name = "LspProcessSpawnError";
254
+ }
260
255
  }
261
256
  function isLspDeadConnectionError(err) {
262
257
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
@@ -287,6 +282,7 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
287
282
  var REQUEST_TIMEOUT_MS = 15000;
288
283
  var INIT_TIMEOUT_MS = 60000;
289
284
  var IDLE_TIMEOUT_MS = 5 * 60000;
285
+ var MAX_RESIDENT_CLIENTS = 6;
290
286
  var REAPER_INTERVAL_MS = 60000;
291
287
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
292
288
  var STOP_SIGKILL_GRACE_MS = 1000;
@@ -301,20 +297,31 @@ var METHOD_NOT_FOUND = -32601;
301
297
  var INTERNAL_ERROR = -32603;
302
298
 
303
299
  class JsonRpcConnection {
304
- reader;
305
- writer;
306
- pendingRequests = new Map;
307
- notificationHandlers = new Map;
308
- requestHandlers = new Map;
309
- closeHandlers = [];
310
- errorHandlers = [];
311
- inputBuffer = Buffer.alloc(0);
312
- nextRequestId = 1;
313
- listening = false;
314
- disposed = false;
315
300
  constructor(reader, writer) {
316
301
  this.reader = reader;
317
302
  this.writer = writer;
303
+ this.pendingRequests = new Map;
304
+ this.notificationHandlers = new Map;
305
+ this.requestHandlers = new Map;
306
+ this.closeHandlers = [];
307
+ this.errorHandlers = [];
308
+ this.inputBuffer = Buffer.alloc(0);
309
+ this.nextRequestId = 1;
310
+ this.listening = false;
311
+ this.disposed = false;
312
+ this.handleData = (chunk) => {
313
+ const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
314
+ this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
315
+ this.drainInputBuffer();
316
+ };
317
+ this.handleClose = () => {
318
+ for (const handler of this.closeHandlers) {
319
+ handler();
320
+ }
321
+ };
322
+ this.handleStreamError = (error) => {
323
+ this.emitError(error);
324
+ };
318
325
  }
319
326
  listen() {
320
327
  if (this.listening)
@@ -435,19 +442,6 @@ class JsonRpcConnection {
435
442
  this.notificationHandlers.clear();
436
443
  this.requestHandlers.clear();
437
444
  }
438
- handleData = (chunk) => {
439
- const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
440
- this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
441
- this.drainInputBuffer();
442
- };
443
- handleClose = () => {
444
- for (const handler of this.closeHandlers) {
445
- handler();
446
- }
447
- };
448
- handleStreamError = (error) => {
449
- this.emitError(error);
450
- };
451
445
  drainInputBuffer() {
452
446
  while (true) {
453
447
  const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR);
@@ -795,31 +789,26 @@ function isPosition(value) {
795
789
 
796
790
  // ../lsp-core/src/lsp/transport.ts
797
791
  class LspClientNotStartedError extends Error {
798
- serverId;
799
- root;
800
- name = "LspClientNotStartedError";
801
792
  constructor(serverId, root) {
802
793
  super("LSP client not started");
803
794
  this.serverId = serverId;
804
795
  this.root = root;
796
+ this.name = "LspClientNotStartedError";
805
797
  }
806
798
  }
807
799
 
808
800
  class LspClientTransport {
809
- root;
810
- server;
811
- proc = null;
812
- connection = null;
813
- stderrBuffer = [];
814
- processExited = false;
815
- diagnosticsStore = new Map;
816
- requestTimeoutMs;
817
- initializeTimeoutMs;
818
- workspaceApplyEditHandler = null;
819
- diagnosticPullSupported = false;
820
801
  constructor(root, server, timeouts = {}) {
821
802
  this.root = root;
822
803
  this.server = server;
804
+ this.proc = null;
805
+ this.connection = null;
806
+ this.stderrBuffer = [];
807
+ this.processExited = false;
808
+ this.diagnosticsStore = new Map;
809
+ this.workspaceApplyEditHandler = null;
810
+ this.diagnosticPullSupported = false;
811
+ this.documentFormattingSupported = false;
823
812
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
824
813
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
825
814
  }
@@ -841,6 +830,12 @@ class LspClientTransport {
841
830
  isDiagnosticPullSupported() {
842
831
  return this.diagnosticPullSupported;
843
832
  }
833
+ setDocumentFormattingSupported(supported) {
834
+ this.documentFormattingSupported = supported;
835
+ }
836
+ isDocumentFormattingSupported() {
837
+ return this.documentFormattingSupported;
838
+ }
844
839
  handlePublishDiagnostics(params) {
845
840
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
846
841
  }
@@ -1054,6 +1049,14 @@ function supportsDiagnosticPull(capabilities) {
1054
1049
  return false;
1055
1050
  return Object.hasOwn(capabilities, "diagnosticProvider");
1056
1051
  }
1052
+ function supportsDocumentFormatting(capabilities) {
1053
+ if (capabilities === undefined)
1054
+ return false;
1055
+ const provider = capabilities.documentFormattingProvider;
1056
+ if (provider === undefined || provider === null || provider === false)
1057
+ return false;
1058
+ return provider === true || typeof provider === "object";
1059
+ }
1057
1060
 
1058
1061
  class LspClientConnection extends LspClientTransport {
1059
1062
  async initialize() {
@@ -1070,6 +1073,7 @@ class LspClientConnection extends LspClientTransport {
1070
1073
  references: {},
1071
1074
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
1072
1075
  publishDiagnostics: {},
1076
+ formatting: { dynamicRegistration: false },
1073
1077
  rename: {
1074
1078
  prepareSupport: true,
1075
1079
  prepareSupportDefaultBehavior: 1
@@ -1111,6 +1115,7 @@ class LspClientConnection extends LspClientTransport {
1111
1115
  initializationOptions: this.server.initialization
1112
1116
  }, { timeoutMs: this.initializeTimeoutMs });
1113
1117
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
1118
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
1114
1119
  await this.sendNotification("initialized", {});
1115
1120
  await this.sendNotification("workspace/didChangeConfiguration", {
1116
1121
  settings: { json: { validate: { enable: true } } }
@@ -1316,16 +1321,12 @@ function movedPath(candidate, oldPath, newPath) {
1316
1321
  }
1317
1322
 
1318
1323
  class WorkspaceDocumentState {
1319
- sendNotification;
1320
- clearDiagnostics;
1321
- openDocuments = new Map;
1322
- openByUri = new Map;
1323
- openPromises = new Map;
1324
- now;
1325
- versionlessPublishQuiescenceMs;
1326
1324
  constructor(sendNotification, clearDiagnostics, options = {}) {
1327
1325
  this.sendNotification = sendNotification;
1328
1326
  this.clearDiagnostics = clearDiagnostics;
1327
+ this.openDocuments = new Map;
1328
+ this.openByUri = new Map;
1329
+ this.openPromises = new Map;
1329
1330
  this.now = options.now ?? (() => Date.now());
1330
1331
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1331
1332
  }
@@ -1589,13 +1590,11 @@ import { dirname as dirname2, isAbsolute as isAbsolute2, relative as relative3,
1589
1590
  import { fileURLToPath } from "node:url";
1590
1591
 
1591
1592
  class WorkspaceEditPathError extends Error {
1592
- path;
1593
- detail;
1594
- name = "WorkspaceEditPathError";
1595
1593
  constructor(path, detail) {
1596
1594
  super(`${detail}: ${path}`);
1597
1595
  this.path = path;
1598
1596
  this.detail = detail;
1597
+ this.name = "WorkspaceEditPathError";
1599
1598
  }
1600
1599
  }
1601
1600
  function isPathInsideWorkspace(filePath, workspaceRoot) {
@@ -1887,13 +1886,11 @@ function canonicalFingerprint(operations) {
1887
1886
 
1888
1887
  // ../lsp-core/src/lsp/workspace-edit-types.ts
1889
1888
  class WorkspaceEditValidationError extends Error {
1890
- changeIndex;
1891
- detail;
1892
- name = "WorkspaceEditValidationError";
1893
1889
  constructor(changeIndex, detail) {
1894
1890
  super(`change ${changeIndex}: ${detail}`);
1895
1891
  this.changeIndex = changeIndex;
1896
1892
  this.detail = detail;
1893
+ this.name = "WorkspaceEditValidationError";
1897
1894
  }
1898
1895
  }
1899
1896
 
@@ -2391,10 +2388,9 @@ function simulateDelete(operation, virtual) {
2391
2388
  import { existsSync as existsSync5, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
2392
2389
  import { dirname as dirname4, resolve as resolve5 } from "node:path";
2393
2390
  class WorkspaceSnapshotBuilder {
2394
- workspaceRoot;
2395
- snapshots = new Map;
2396
2391
  constructor(workspaceRoot) {
2397
2392
  this.workspaceRoot = workspaceRoot;
2393
+ this.snapshots = new Map;
2398
2394
  }
2399
2395
  build(operations) {
2400
2396
  this.add(this.workspaceRoot, false);
@@ -2438,8 +2434,10 @@ function snapshotOperations(operations, workspaceRoot) {
2438
2434
 
2439
2435
  // ../lsp-core/src/lsp/workspace-edit-plan.ts
2440
2436
  class PlanPathIndex {
2441
- firstChangeByPath = new Map;
2442
- reportedPathByCanonical = new Map;
2437
+ constructor() {
2438
+ this.firstChangeByPath = new Map;
2439
+ this.reportedPathByCanonical = new Map;
2440
+ }
2443
2441
  build(operations) {
2444
2442
  for (const operation of operations) {
2445
2443
  switch (operation.kind) {
@@ -2528,14 +2526,11 @@ function isRecord4(value) {
2528
2526
  }
2529
2527
 
2530
2528
  class WorkspaceMutationController {
2531
- workspaceRoot;
2532
- documents;
2533
- activeLease = null;
2534
- nextLeaseId = 1;
2535
- io;
2536
2529
  constructor(workspaceRoot, documents) {
2537
2530
  this.workspaceRoot = workspaceRoot;
2538
2531
  this.documents = documents;
2532
+ this.activeLease = null;
2533
+ this.nextLeaseId = 1;
2539
2534
  }
2540
2535
  setIo(io) {
2541
2536
  this.io = io;
@@ -2648,12 +2643,9 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
2648
2643
  var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
2649
2644
 
2650
2645
  class LspClient extends LspClientConnection {
2651
- diagnosticPullErrors = [];
2652
- documents;
2653
- workspaceMutations;
2654
- diagnosticsFreshnessTimeoutMs;
2655
2646
  constructor(root, server, options = {}) {
2656
2647
  super(root, server, options);
2648
+ this.diagnosticPullErrors = [];
2657
2649
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2658
2650
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2659
2651
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
@@ -2708,6 +2700,18 @@ class LspClient extends LspClientConnection {
2708
2700
  textDocument: { uri: pathToFileURL3(absPath).href }
2709
2701
  }, options);
2710
2702
  }
2703
+ async formatDocument(filePath, options, signal) {
2704
+ if (!this.isDocumentFormattingSupported())
2705
+ return null;
2706
+ const absPath = this.resolveWorkspacePath(filePath);
2707
+ await this.openFile(absPath);
2708
+ const requestOptions = signal === undefined ? {} : { signal };
2709
+ const edits = await this.sendRequest("textDocument/formatting", {
2710
+ textDocument: { uri: pathToFileURL3(absPath).href },
2711
+ options
2712
+ }, requestOptions);
2713
+ return edits ?? [];
2714
+ }
2711
2715
  async workspaceSymbols(query, signal) {
2712
2716
  const options = signal === undefined ? {} : { signal };
2713
2717
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -2953,18 +2957,14 @@ function awaitWithSignal(promise, signal) {
2953
2957
  }
2954
2958
 
2955
2959
  class LspManager {
2956
- clients = new Map;
2957
- reaperHandle = null;
2958
- signalDisposer = null;
2959
- disposed = false;
2960
- idleTimeoutMs;
2961
- initTimeoutMs;
2962
- reaperIntervalMs;
2963
- clientFactory;
2964
- now;
2965
2960
  constructor(options = {}) {
2961
+ this.clients = new Map;
2962
+ this.reaperHandle = null;
2963
+ this.signalDisposer = null;
2964
+ this.disposed = false;
2966
2965
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
2967
2966
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
2967
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
2968
2968
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
2969
2969
  this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
2970
2970
  this.now = options.now ?? (() => Date.now());
@@ -2998,6 +2998,26 @@ class LspManager {
2998
2998
  }
2999
2999
  }
3000
3000
  }
3001
+ evictForAdmission() {
3002
+ while (this.clients.size >= this.maxResidentClients) {
3003
+ const victim = this.leastRecentlyUsedIdleClient();
3004
+ if (!victim)
3005
+ return;
3006
+ this.clients.delete(victim.key);
3007
+ stopClientBestEffort(victim.managed.client);
3008
+ }
3009
+ }
3010
+ leastRecentlyUsedIdleClient() {
3011
+ let candidate = null;
3012
+ for (const [key, managed] of this.clients) {
3013
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
3014
+ continue;
3015
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
3016
+ candidate = { key, managed };
3017
+ }
3018
+ }
3019
+ return candidate;
3020
+ }
3001
3021
  async tryDeleteIfOrphaned(key, managed) {
3002
3022
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
3003
3023
  this.clients.delete(key);
@@ -3044,6 +3064,7 @@ class LspManager {
3044
3064
  managed.lastUsedAt = this.now();
3045
3065
  return managed.client;
3046
3066
  }
3067
+ this.evictForAdmission();
3047
3068
  const client = this.clientFactory(root, server);
3048
3069
  const initStartedAt = this.now();
3049
3070
  const initPromise = (async () => {
@@ -3106,6 +3127,7 @@ class LspManager {
3106
3127
  const key = this.getKey(root, server.id);
3107
3128
  if (this.clients.has(key))
3108
3129
  return;
3130
+ this.evictForAdmission();
3109
3131
  const client = this.clientFactory(root, server);
3110
3132
  const initStartedAt = this.now();
3111
3133
  const initPromise = (async () => {
@@ -3194,57 +3216,43 @@ async function disposeDefaultLspManager() {
3194
3216
  }
3195
3217
  }
3196
3218
 
3197
- // ../lsp-core/src/lsp/server-install-state.ts
3198
- import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3199
- import { dirname as dirname5 } from "node:path";
3200
- function getInstallDecisionsPath() {
3201
- return lspRequestContext().installDecisionsPath;
3202
- }
3203
- function loadInstallDecisions() {
3204
- const path = getInstallDecisionsPath();
3205
- if (!existsSync6(path))
3206
- return {};
3207
- try {
3208
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
3209
- return isInstallDecisions(parsed) ? parsed : {};
3210
- } catch {
3211
- return {};
3219
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3220
+ import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
3221
+ import { dirname as dirname5, join as join3 } from "node:path";
3222
+
3223
+ // ../lsp-core/src/lsp/workspace-markers.ts
3224
+ var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
3225
+
3226
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3227
+ function findWorkspaceRootOutsideContext(directory) {
3228
+ const marked = nearestMarkedAncestor(directory);
3229
+ if (marked !== undefined)
3230
+ return marked;
3231
+ return realpathSync4(nearestExistingAncestor(directory));
3232
+ }
3233
+ function nearestMarkedAncestor(directory) {
3234
+ let current = directory;
3235
+ for (;; ) {
3236
+ if (existsSync6(current) && WORKSPACE_MARKERS.some((marker) => existsSync6(join3(current, marker)))) {
3237
+ return realpathSync4(current);
3238
+ }
3239
+ const parent = dirname5(current);
3240
+ if (parent === current)
3241
+ return;
3242
+ current = parent;
3212
3243
  }
3213
3244
  }
3214
- function loadInstallDecision(serverId) {
3215
- return loadInstallDecisions()[serverId];
3216
- }
3217
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3218
- const decisions = loadInstallDecisions();
3219
- decisions[serverId] = { decision, decidedAt };
3220
- writeInstallDecisions(decisions);
3221
- }
3222
- function isInstallDecision(value) {
3223
- return value === "declined" || value === "allowed";
3224
- }
3225
- function writeInstallDecisions(decisions) {
3226
- const path = getInstallDecisionsPath();
3227
- mkdirSync(dirname5(path), { recursive: true });
3228
- const tmpPath = `${path}.tmp`;
3229
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3230
- `, "utf8");
3231
- renameSync2(tmpPath, path);
3232
- }
3233
- function isInstallDecisions(value) {
3234
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3235
- }
3236
- function isInstallDecisionRecord(value) {
3237
- if (!isRecord5(value))
3238
- return false;
3239
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3240
- }
3241
- function isRecord5(value) {
3242
- return typeof value === "object" && value !== null && !Array.isArray(value);
3245
+ function nearestExistingAncestor(directory) {
3246
+ let current = directory;
3247
+ while (!existsSync6(current)) {
3248
+ const parent = dirname5(current);
3249
+ if (parent === current)
3250
+ return current;
3251
+ current = parent;
3252
+ }
3253
+ return current;
3243
3254
  }
3244
3255
 
3245
- // ../lsp-core/src/lsp/config-loader.ts
3246
- import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
3247
-
3248
3256
  // ../lsp-core/src/lsp/server-definitions.ts
3249
3257
  var LSP_INSTALL_HINTS = {
3250
3258
  typescript: "npm install -g typescript-language-server typescript",
@@ -3290,6 +3298,26 @@ var LSP_INSTALL_HINTS = {
3290
3298
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
3291
3299
  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"
3292
3300
  };
3301
+ var LSP_LOCAL_INSTALL_HINTS = {
3302
+ typescript: "bun add -d typescript-language-server typescript",
3303
+ vue: "bun add -d @vue/language-server",
3304
+ eslint: "bun add -d vscode-langservers-extracted",
3305
+ oxlint: "bun add -d oxlint",
3306
+ biome: "bun add -d @biomejs/biome",
3307
+ svelte: "bun add -d svelte-language-server",
3308
+ astro: "bun add -d @astrojs/language-server",
3309
+ bash: "bun add -d bash-language-server",
3310
+ "bash-ls": "bun add -d bash-language-server",
3311
+ "yaml-ls": "bun add -d yaml-language-server",
3312
+ php: "bun add -d intelephense",
3313
+ prisma: "bun add -d prisma",
3314
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
3315
+ pyright: "uv add --dev pyright",
3316
+ basedpyright: "uv add --dev basedpyright",
3317
+ ruff: "uv add --dev ruff",
3318
+ ty: "uv add --dev ty",
3319
+ "ruby-lsp": "bundle add ruby-lsp --group development"
3320
+ };
3293
3321
  var BUILTIN_SERVERS = {
3294
3322
  typescript: {
3295
3323
  command: ["typescript-language-server", "--stdio"],
@@ -3392,7 +3420,56 @@ var BUILTIN_SERVERS = {
3392
3420
  }
3393
3421
  };
3394
3422
 
3423
+ // ../lsp-core/src/lsp/server-install-state.ts
3424
+ import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3425
+ import { dirname as dirname6 } from "node:path";
3426
+ function getInstallDecisionsPath() {
3427
+ return lspRequestContext().installDecisionsPath;
3428
+ }
3429
+ function loadInstallDecisions() {
3430
+ const path = getInstallDecisionsPath();
3431
+ if (!existsSync7(path))
3432
+ return {};
3433
+ try {
3434
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
3435
+ return isInstallDecisions(parsed) ? parsed : {};
3436
+ } catch {
3437
+ return {};
3438
+ }
3439
+ }
3440
+ function loadInstallDecision(serverId) {
3441
+ return loadInstallDecisions()[serverId];
3442
+ }
3443
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3444
+ const decisions = loadInstallDecisions();
3445
+ decisions[serverId] = { decision, decidedAt };
3446
+ writeInstallDecisions(decisions);
3447
+ }
3448
+ function isInstallDecision(value) {
3449
+ return value === "declined" || value === "allowed";
3450
+ }
3451
+ function writeInstallDecisions(decisions) {
3452
+ const path = getInstallDecisionsPath();
3453
+ mkdirSync(dirname6(path), { recursive: true });
3454
+ const tmpPath = `${path}.tmp`;
3455
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3456
+ `, "utf8");
3457
+ renameSync2(tmpPath, path);
3458
+ }
3459
+ function isInstallDecisions(value) {
3460
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3461
+ }
3462
+ function isInstallDecisionRecord(value) {
3463
+ if (!isRecord5(value))
3464
+ return false;
3465
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3466
+ }
3467
+ function isRecord5(value) {
3468
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3469
+ }
3470
+
3395
3471
  // ../lsp-core/src/lsp/config-loader.ts
3472
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
3396
3473
  function getProjectConfigPaths() {
3397
3474
  return lspRequestContext().projectConfigPaths;
3398
3475
  }
@@ -3400,7 +3477,7 @@ function getUserConfigPath() {
3400
3477
  return lspRequestContext().userConfigPath;
3401
3478
  }
3402
3479
  function loadJsonFile(path) {
3403
- if (!existsSync7(path))
3480
+ if (!existsSync8(path))
3404
3481
  return null;
3405
3482
  try {
3406
3483
  const parsed = JSON.parse(readFileSync4(path, "utf-8"));
@@ -3588,54 +3665,155 @@ function getDisabledServerIds() {
3588
3665
  }
3589
3666
 
3590
3667
  // ../lsp-core/src/lsp/server-installation.ts
3591
- import { existsSync as existsSync8 } from "node:fs";
3592
- import { delimiter as delimiter3, join as join3 } from "node:path";
3593
- function isServerInstalled(command, _workingDirectory) {
3594
- if (command.length === 0)
3595
- return false;
3596
- const [cmd] = command;
3597
- if (!cmd)
3598
- return false;
3599
- if (cmd.includes("/") || cmd.includes("\\")) {
3600
- if (existsSync8(cmd))
3601
- return true;
3668
+ import { existsSync as existsSync9 } from "node:fs";
3669
+ import { delimiter as delimiter3, dirname as dirname7, isAbsolute as isAbsolute3, join as join4, resolve as resolve7 } from "node:path";
3670
+ var LOCAL_BIN_RULES = [
3671
+ {
3672
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
3673
+ binDirs: [join4("node_modules", ".bin")]
3674
+ },
3675
+ {
3676
+ markers: [
3677
+ "pyproject.toml",
3678
+ "ty.toml",
3679
+ "requirements.txt",
3680
+ "setup.py",
3681
+ "setup.cfg",
3682
+ "Pipfile",
3683
+ "pyrightconfig.json",
3684
+ "ruff.toml",
3685
+ ".ruff.toml"
3686
+ ],
3687
+ binDirs: [
3688
+ join4(".venv", "bin"),
3689
+ join4(".venv", "Scripts"),
3690
+ join4("venv", "bin"),
3691
+ join4("venv", "Scripts"),
3692
+ join4(".env", "bin"),
3693
+ join4(".env", "Scripts")
3694
+ ]
3695
+ },
3696
+ {
3697
+ markers: ["Gemfile", "Gemfile.lock"],
3698
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
3699
+ },
3700
+ {
3701
+ markers: ["go.mod", "go.sum", "go.work"],
3702
+ binDirs: ["bin"]
3703
+ }
3704
+ ];
3705
+ var resolutionCache = new Map;
3706
+ var probeCount = 0;
3707
+ function probe(path) {
3708
+ probeCount += 1;
3709
+ return existsSync9(path);
3710
+ }
3711
+ function executableSuffixes(platform, pathExt) {
3712
+ if (platform !== "win32")
3713
+ return [""];
3714
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
3715
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
3716
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
3717
+ }
3718
+ function probeWithSuffixes(directory, command, suffixes) {
3719
+ for (const suffix of suffixes) {
3720
+ const candidate = join4(directory, command + suffix);
3721
+ if (probe(candidate))
3722
+ return candidate;
3602
3723
  }
3603
- const isWindows = process.platform === "win32";
3604
- let exts = [""];
3605
- if (isWindows) {
3606
- const pathExt = process.env["PATHEXT"] ?? "";
3607
- if (pathExt) {
3608
- const systemExts = pathExt.split(";").filter(Boolean);
3609
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
3610
- } else {
3611
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
3724
+ return null;
3725
+ }
3726
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
3727
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
3728
+ let current = resolve7(workingDirectory);
3729
+ while (true) {
3730
+ for (const rule of LOCAL_BIN_RULES) {
3731
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
3732
+ continue;
3733
+ for (const binDir of rule.binDirs) {
3734
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
3735
+ if (found !== null)
3736
+ return found;
3737
+ }
3612
3738
  }
3739
+ if (probe(join4(current, ".git")))
3740
+ return null;
3741
+ if (boundary !== undefined && current === boundary)
3742
+ return null;
3743
+ const parent = dirname7(current);
3744
+ if (parent === current)
3745
+ return null;
3746
+ current = parent;
3613
3747
  }
3614
- let pathEnv = process.env["PATH"] ?? "";
3615
- if (isWindows && !pathEnv) {
3748
+ }
3749
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
3750
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
3751
+ if (platform === "win32" && !pathEnv) {
3616
3752
  pathEnv = process.env["Path"] ?? "";
3617
3753
  }
3618
- const paths = pathEnv.split(delimiter3);
3619
- for (const p of paths) {
3620
- for (const suffix of exts) {
3621
- if (existsSync8(join3(p, cmd + suffix))) {
3622
- return true;
3623
- }
3624
- }
3754
+ for (const entry of pathEnv.split(delimiter3)) {
3755
+ if (entry.length === 0)
3756
+ continue;
3757
+ const found = probeWithSuffixes(entry, command, suffixes);
3758
+ if (found !== null)
3759
+ return found;
3625
3760
  }
3626
- if (cmd === "node")
3627
- return true;
3628
- return false;
3761
+ return null;
3762
+ }
3763
+ function resolveServerBinary(command, workingDirectory, options = {}) {
3764
+ if (command.length === 0)
3765
+ return null;
3766
+ const [cmd] = command;
3767
+ if (cmd === undefined || cmd.length === 0)
3768
+ return null;
3769
+ const platform = options.platform ?? process.platform;
3770
+ const suffixes = executableSuffixes(platform, options.pathExt);
3771
+ if (cmd.includes("/") || cmd.includes("\\")) {
3772
+ const explicit = isAbsolute3(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
3773
+ return probe(explicit) ? explicit : null;
3774
+ }
3775
+ const cacheKey = JSON.stringify([
3776
+ workingDirectory ?? "",
3777
+ cmd,
3778
+ platform,
3779
+ options.stopAt ?? "",
3780
+ options.pathExt ?? "",
3781
+ options.pathEnv ?? process.env["PATH"] ?? ""
3782
+ ]);
3783
+ const cached = resolutionCache.get(cacheKey);
3784
+ if (cached !== undefined)
3785
+ return cached;
3786
+ let resolved = null;
3787
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
3788
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
3789
+ }
3790
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
3791
+ if (resolved === null && cmd === "node")
3792
+ resolved = cmd;
3793
+ resolutionCache.set(cacheKey, resolved);
3794
+ return resolved;
3795
+ }
3796
+ function isServerInstalled(command, workingDirectory, options = {}) {
3797
+ if (command.length === 0)
3798
+ return false;
3799
+ return resolveServerBinary(command, workingDirectory, options) !== null;
3629
3800
  }
3630
3801
 
3631
3802
  // ../lsp-core/src/lsp/server-resolution.ts
3803
+ function withResolvedCommand(command, binaryPath) {
3804
+ return [binaryPath, ...command.slice(1)];
3805
+ }
3632
3806
  function findServerForExtension(ext) {
3633
3807
  const servers = getMergedServers();
3808
+ const workingDirectory = contextCwd();
3634
3809
  for (const server of servers) {
3635
- if (server.extensions.includes(ext) && isServerInstalled(server.command)) {
3810
+ if (!server.extensions.includes(ext))
3811
+ continue;
3812
+ const binaryPath = resolveServerBinary(server.command, workingDirectory);
3813
+ if (binaryPath !== null) {
3636
3814
  const resolvedServer = {
3637
3815
  id: server.id,
3638
- command: server.command,
3816
+ command: withResolvedCommand(server.command, binaryPath),
3639
3817
  extensions: server.extensions,
3640
3818
  priority: server.priority
3641
3819
  };
@@ -3682,6 +3860,7 @@ function findServerForExtension(ext) {
3682
3860
  function getAllServers() {
3683
3861
  const servers = getMergedServers();
3684
3862
  const disabled = getDisabledServerIds();
3863
+ const workingDirectory = contextCwd();
3685
3864
  const result = [];
3686
3865
  const seen = new Set;
3687
3866
  for (const server of servers) {
@@ -3689,7 +3868,7 @@ function getAllServers() {
3689
3868
  continue;
3690
3869
  result.push({
3691
3870
  id: server.id,
3692
- installed: isServerInstalled(server.command),
3871
+ installed: isServerInstalled(server.command, workingDirectory),
3693
3872
  extensions: server.extensions,
3694
3873
  disabled: false,
3695
3874
  source: server.source,
@@ -3703,7 +3882,7 @@ function getAllServers() {
3703
3882
  const builtin = BUILTIN_SERVERS[id];
3704
3883
  result.push({
3705
3884
  id,
3706
- installed: builtin ? isServerInstalled(builtin.command) : false,
3885
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
3707
3886
  extensions: builtin?.extensions ?? [],
3708
3887
  disabled: true,
3709
3888
  source: "disabled",
@@ -3714,7 +3893,6 @@ function getAllServers() {
3714
3893
  }
3715
3894
 
3716
3895
  // ../lsp-core/src/lsp/client-wrapper.ts
3717
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
3718
3896
  function isDirectoryPath(filePath) {
3719
3897
  try {
3720
3898
  return statSync3(filePath).isDirectory();
@@ -3723,32 +3901,85 @@ function isDirectoryPath(filePath) {
3723
3901
  }
3724
3902
  }
3725
3903
  function findWorkspaceRoot(filePath) {
3726
- const abs = resolvePathInsideContext(filePath);
3904
+ const cwd = contextCwd();
3905
+ const abs = resolveReadablePathInsideContext(filePath);
3727
3906
  let dir = abs;
3728
3907
  if (!isDirectoryPath(dir)) {
3729
- dir = dirname6(dir);
3730
- }
3731
- let prevDir = "";
3732
- while (dir !== prevDir) {
3733
- for (const marker of WORKSPACE_MARKERS) {
3734
- if (existsSync9(join4(dir, marker))) {
3735
- return dir;
3908
+ dir = dirname8(dir);
3909
+ }
3910
+ if (!isPathInside(cwd, abs))
3911
+ return findWorkspaceRootOutsideContext(dir);
3912
+ const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
3913
+ while (isPathInside(cwd, dir)) {
3914
+ const canonicalDir = existingDirectoryInsideContext(dir, cwd);
3915
+ if (canonicalDir !== undefined) {
3916
+ for (const marker of WORKSPACE_MARKERS) {
3917
+ if (existsSync10(join5(dir, marker))) {
3918
+ return canonicalDir;
3919
+ }
3736
3920
  }
3737
3921
  }
3738
- prevDir = dir;
3739
- dir = dirname6(dir);
3922
+ if (dir === cwd)
3923
+ break;
3924
+ dir = dirname8(dir);
3740
3925
  }
3741
- return dirname6(abs);
3926
+ return fallbackRoot;
3927
+ }
3928
+ function resolveReadablePathInsideContext(filePath) {
3929
+ const cwd = contextCwd();
3930
+ const abs = resolve8(cwd, filePath);
3931
+ if (isPathInside(cwd, abs))
3932
+ return abs;
3933
+ const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
3934
+ if (rebased !== undefined)
3935
+ return rebased;
3936
+ return canonicalizeExistingOrNearestAncestor(abs);
3742
3937
  }
3743
3938
  function resolvePathInsideContext(filePath) {
3744
3939
  const cwd = contextCwd();
3745
- const abs = resolve7(cwd, filePath);
3940
+ const abs = resolveReadablePathInsideContext(filePath);
3746
3941
  const canonical = canonicalizeExistingOrNearestAncestor(abs);
3747
3942
  if (!isPathInside(cwd, canonical)) {
3748
3943
  throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
3749
3944
  }
3750
3945
  return canonical;
3751
3946
  }
3947
+ function rebaseThroughCanonicalAncestor(path, cwd) {
3948
+ let current = path;
3949
+ const suffix = [];
3950
+ while (true) {
3951
+ if (existsSync10(current)) {
3952
+ const canonical = realpathSync5(current);
3953
+ if (isPathInside(cwd, canonical))
3954
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
3955
+ }
3956
+ const parent = dirname8(current);
3957
+ if (parent === current)
3958
+ return;
3959
+ suffix.unshift(basename3(current));
3960
+ current = parent;
3961
+ }
3962
+ }
3963
+ function existingDirectoryInsideContext(directory, cwd) {
3964
+ if (!existsSync10(directory))
3965
+ return;
3966
+ const canonical = realpathSync5(directory);
3967
+ if (!statSync3(canonical).isDirectory())
3968
+ return;
3969
+ return isPathInside(cwd, canonical) ? canonical : undefined;
3970
+ }
3971
+ function nearestExistingDirectoryInsideContext(directory, cwd) {
3972
+ let current = directory;
3973
+ while (isPathInside(cwd, current)) {
3974
+ const canonical = existingDirectoryInsideContext(current, cwd);
3975
+ if (canonical !== undefined)
3976
+ return canonical;
3977
+ if (current === cwd)
3978
+ return;
3979
+ current = dirname8(current);
3980
+ }
3981
+ return;
3982
+ }
3752
3983
  function formatServerLookupError(result) {
3753
3984
  if (result.status === "not_installed") {
3754
3985
  return formatNotInstalled(result);
@@ -3772,6 +4003,19 @@ function formatServerLookupError(result) {
3772
4003
  ].join(`
3773
4004
  `);
3774
4005
  }
4006
+ function formatInstallOptions(serverId, installHint) {
4007
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
4008
+ if (localHint === undefined) {
4009
+ return ["To install, run:", ` ${installHint}`];
4010
+ }
4011
+ return [
4012
+ "To install in THIS repository (preferred — no global install needed):",
4013
+ ` ${localHint}`,
4014
+ "",
4015
+ "Or install it globally:",
4016
+ ` ${installHint}`
4017
+ ];
4018
+ }
3775
4019
  function formatNotInstalled(result) {
3776
4020
  const { server, installHint } = result;
3777
4021
  const extensions = server.extensions.join(", ");
@@ -3786,19 +4030,19 @@ function formatNotInstalled(result) {
3786
4030
  `Command not found: ${server.command[0]}`,
3787
4031
  ""
3788
4032
  ];
4033
+ const installOptions = formatInstallOptions(server.id, installHint);
3789
4034
  if (decision === "allowed") {
3790
4035
  return [
3791
4036
  ...header,
3792
4037
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
3793
- ` ${installHint}`
4038
+ ...installOptions.slice(1)
3794
4039
  ].join(`
3795
4040
  `);
3796
4041
  }
3797
4042
  if (!context.capabilities.installDecisionTool) {
3798
4043
  return [
3799
4044
  ...header,
3800
- "To install, run:",
3801
- ` ${installHint}`,
4045
+ ...installOptions,
3802
4046
  "",
3803
4047
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
3804
4048
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -3807,8 +4051,7 @@ function formatNotInstalled(result) {
3807
4051
  }
3808
4052
  return [
3809
4053
  ...header,
3810
- "To install, run:",
3811
- ` ${installHint}`,
4054
+ ...installOptions,
3812
4055
  "",
3813
4056
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
3814
4057
  "- If the user agrees: run the install command above, then retry this tool.",
@@ -3819,7 +4062,7 @@ function formatNotInstalled(result) {
3819
4062
  ].join(`
3820
4063
  `);
3821
4064
  }
3822
- var READ_ONLY_RETRY_TOOLS = new Set([
4065
+ var READ_ONLY_TOOLS = new Set([
3823
4066
  "diagnostics",
3824
4067
  "definition",
3825
4068
  "references",
@@ -3828,7 +4071,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
3828
4071
  "prepareRename"
3829
4072
  ]);
3830
4073
  async function withLspClient(filePath, fn, toolName, options = {}) {
3831
- const absPath = resolvePathInsideContext(filePath);
4074
+ const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
3832
4075
  if (isDirectoryPath(absPath)) {
3833
4076
  throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
3834
4077
  }
@@ -3843,9 +4086,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
3843
4086
  const acquireAndCall = async (allowRetry) => {
3844
4087
  const client = await manager.getClient(root, server, options.signal);
3845
4088
  try {
3846
- return await fn(client, root);
4089
+ return await fn(client, root, absPath);
3847
4090
  } catch (err) {
3848
- if (allowRetry && READ_ONLY_RETRY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4091
+ if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
3849
4092
  manager.invalidateClient(root, server.id, client);
3850
4093
  return acquireAndCall(false);
3851
4094
  }
@@ -3863,8 +4106,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
3863
4106
  }
3864
4107
 
3865
4108
  // ../lsp-core/src/lsp/directory-diagnostics.ts
3866
- import { existsSync as existsSync10, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
3867
- import { join as join5, resolve as resolve8 } from "node:path";
4109
+ import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4110
+ import { join as join6, resolve as resolve9 } from "node:path";
3868
4111
 
3869
4112
  // ../lsp-core/src/lsp/formatters.ts
3870
4113
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -3994,7 +4237,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
3994
4237
  for (const entry of entries) {
3995
4238
  if (files.length >= maxFiles)
3996
4239
  return;
3997
- const fullPath = join5(currentDir, entry);
4240
+ const fullPath = join6(currentDir, entry);
3998
4241
  let stat;
3999
4242
  try {
4000
4243
  stat = lstatSync4(fullPath);
@@ -4019,8 +4262,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4019
4262
  if (!extension.startsWith(".")) {
4020
4263
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4021
4264
  }
4022
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4023
- if (!existsSync10(absDir)) {
4265
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
4266
+ if (!existsSync11(absDir)) {
4024
4267
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4025
4268
  }
4026
4269
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
@@ -4107,7 +4350,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4107
4350
 
4108
4351
  // ../lsp-core/src/lsp/infer-extension.ts
4109
4352
  import { lstatSync as lstatSync5, readdirSync as readdirSync4 } from "node:fs";
4110
- import { join as join6 } from "node:path";
4353
+ import { join as join7 } from "node:path";
4111
4354
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
4112
4355
  var MAX_SCAN_ENTRIES = 500;
4113
4356
  function inferExtensionFromDirectory(directory) {
@@ -4125,7 +4368,7 @@ function inferExtensionFromDirectory(directory) {
4125
4368
  for (const entry of entries) {
4126
4369
  if (scanned >= MAX_SCAN_ENTRIES)
4127
4370
  return;
4128
- const fullPath = join6(dir, entry);
4371
+ const fullPath = join7(dir, entry);
4129
4372
  let stat;
4130
4373
  try {
4131
4374
  stat = lstatSync5(fullPath);
@@ -4300,7 +4543,7 @@ async function executeLspDiagnostics(params, signal) {
4300
4543
  const filePath = requireString(params, "filePath");
4301
4544
  const severity = severityFilter(params);
4302
4545
  try {
4303
- const absPath = resolvePathInsideContext(filePath);
4546
+ const absPath = resolveReadablePathInsideContext(filePath);
4304
4547
  if (isDirectoryPath(absPath)) {
4305
4548
  const extension = inferExtensionFromDirectory(absPath);
4306
4549
  if (!extension) {
@@ -4329,7 +4572,7 @@ async function executeLspDiagnostics(params, signal) {
4329
4572
  };
4330
4573
  return text(output2.output, details2);
4331
4574
  }
4332
- const result = await withLspClient(filePath, async (client) => client.diagnostics(filePath, signal), "diagnostics", clientOptions(signal));
4575
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
4333
4576
  if (result.transientError) {
4334
4577
  const message = result.transientError.message;
4335
4578
  const details2 = {
@@ -4376,6 +4619,96 @@ async function executeLspDiagnostics(params, signal) {
4376
4619
  throw error;
4377
4620
  }
4378
4621
  }
4622
+ // ../lsp-core/src/lsp/format-document.ts
4623
+ import { readFileSync as readFileSync5, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
4624
+ var DEFAULT_FORMATTING_OPTIONS = {
4625
+ tabSize: 4,
4626
+ insertSpaces: false,
4627
+ trimTrailingWhitespace: true,
4628
+ insertFinalNewline: true,
4629
+ trimFinalNewlines: true
4630
+ };
4631
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
4632
+ async function formatDocumentWithClient(client, filePath, options = {}) {
4633
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
4634
+ if (edits === null)
4635
+ return { status: "unavailable", reason: "capability_not_advertised" };
4636
+ if (edits.length === 0)
4637
+ return UNCHANGED;
4638
+ const before = readFileSync5(filePath, "utf-8");
4639
+ const normalized = normalizeTextEdits(before, edits, 0);
4640
+ if (normalized.text === before)
4641
+ return UNCHANGED;
4642
+ writeAtomically(filePath, normalized.text);
4643
+ await client.openFile(filePath);
4644
+ return {
4645
+ status: "formatted",
4646
+ ...lineDelta(normalized.edits)
4647
+ };
4648
+ }
4649
+ function lineDelta(edits) {
4650
+ let linesAdded = 0;
4651
+ let linesRemoved = 0;
4652
+ for (const edit of edits) {
4653
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
4654
+ linesAdded += edit.newText.split(`
4655
+ `).length;
4656
+ }
4657
+ return { linesAdded, linesRemoved };
4658
+ }
4659
+ function writeAtomically(filePath, content) {
4660
+ const tempPath = `${filePath}.omo-format.tmp`;
4661
+ writeFileSync3(tempPath, content, "utf-8");
4662
+ try {
4663
+ renameSync3(tempPath, filePath);
4664
+ } catch (error) {
4665
+ try {
4666
+ unlinkSync(tempPath);
4667
+ } catch {}
4668
+ throw error;
4669
+ }
4670
+ }
4671
+
4672
+ // ../lsp-core/src/tools/format.ts
4673
+ async function executeLspFormat(params, signal) {
4674
+ const filePath = requireString(params, "filePath");
4675
+ try {
4676
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
4677
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
4678
+ } catch (error) {
4679
+ const missingDependency = missingDependencyResult(error, {
4680
+ filePath,
4681
+ status: "unavailable",
4682
+ reason: "server_unavailable",
4683
+ linesAdded: 0,
4684
+ linesRemoved: 0
4685
+ });
4686
+ if (missingDependency)
4687
+ return missingDependency;
4688
+ throw error;
4689
+ }
4690
+ }
4691
+ function formatDetails(filePath, result) {
4692
+ if (result.status === "unavailable") {
4693
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
4694
+ }
4695
+ return {
4696
+ filePath,
4697
+ status: result.status,
4698
+ linesAdded: result.linesAdded,
4699
+ linesRemoved: result.linesRemoved
4700
+ };
4701
+ }
4702
+ function describeResult(filePath, result) {
4703
+ if (result.status === "unavailable") {
4704
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
4705
+ }
4706
+ if (result.status === "unchanged") {
4707
+ return `Already formatted: ${filePath}`;
4708
+ }
4709
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
4710
+ }
4711
+
4379
4712
  // ../lsp-core/src/tools/install-decision.ts
4380
4713
  async function executeLspInstallDecision(params) {
4381
4714
  const serverId = requireString(params, "server_id");
@@ -4404,7 +4737,7 @@ async function executeLspGotoDefinition(params, signal) {
4404
4737
  const line = requireNumber(params, "line");
4405
4738
  const character = requireNumber(params, "character");
4406
4739
  try {
4407
- const result = await withLspClient(filePath, async (client) => client.definition(filePath, line, character, signal), "definition", clientOptions(signal));
4740
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
4408
4741
  const locations = !result ? [] : Array.isArray(result) ? result : [result];
4409
4742
  const details = { filePath, line, character, locations };
4410
4743
  if (locations.length === 0)
@@ -4429,7 +4762,7 @@ async function executeLspFindReferences(params, signal) {
4429
4762
  const character = requireNumber(params, "character");
4430
4763
  const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
4431
4764
  try {
4432
- const result = await withLspClient(filePath, async (client) => client.references(filePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
4765
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
4433
4766
  const references = Array.isArray(result) ? result : [];
4434
4767
  const total = references.length;
4435
4768
  const truncated = total > DEFAULT_MAX_REFERENCES;
@@ -4471,7 +4804,7 @@ async function executeLspPrepareRename(params, signal) {
4471
4804
  const line = requireNumber(params, "line");
4472
4805
  const character = requireNumber(params, "character");
4473
4806
  try {
4474
- const result = await withLspClient(filePath, async (client) => client.prepareRename(filePath, line, character, signal), "prepareRename", clientOptions(signal));
4807
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
4475
4808
  const details = { filePath, line, character, result };
4476
4809
  return text(formatPrepareRenameResult(result), details);
4477
4810
  } catch (error) {
@@ -4492,7 +4825,7 @@ async function executeLspRename(params, signal) {
4492
4825
  const character = requireNumber(params, "character");
4493
4826
  const newName = requireString(params, "newName");
4494
4827
  try {
4495
- const result = await withLspClient(filePath, async (client) => client.rename(filePath, line, character, newName, signal), "rename", clientOptions(signal));
4828
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
4496
4829
  const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
4497
4830
  return text(formatApplyResult(result.apply), details, !result.apply.success);
4498
4831
  } catch (error) {
@@ -4572,7 +4905,7 @@ async function executeLspSymbols(params, signal) {
4572
4905
  const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
4573
4906
  return formatSymbolsResult(filePath, scope, symbols2, limit, query);
4574
4907
  }
4575
- const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(filePath, signal), "documentSymbols", clientOptions(signal));
4908
+ const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
4576
4909
  return formatSymbolsResult(filePath, scope, symbols, limit);
4577
4910
  } catch (error) {
4578
4911
  const query = optionalString(params, "query");
@@ -4708,6 +5041,16 @@ var LSP_MCP_TOOLS = [
4708
5041
  }, ["filePath", "line", "character", "newName"]),
4709
5042
  execute: executeLspRename
4710
5043
  },
5044
+ {
5045
+ name: "format",
5046
+ aliases: ["lsp_format"],
5047
+ title: "LSP Format",
5048
+ description: "Format a source file with its language server and write the returned edits to disk.",
5049
+ inputSchema: objectSchema({
5050
+ filePath: { type: "string", description: "Source file path to format." }
5051
+ }, ["filePath"]),
5052
+ execute: executeLspFormat
5053
+ },
4711
5054
  {
4712
5055
  name: "install_decision",
4713
5056
  aliases: ["lsp_install_decision"],
@@ -4741,16 +5084,17 @@ function coerceToolArguments(value) {
4741
5084
  return isRecord7(value) ? value : {};
4742
5085
  }
4743
5086
  export {
4744
- isRecord7 as isRecord,
4745
- executeLspTool,
4746
- executeLspSymbols,
4747
- executeLspStatus,
4748
- executeLspRename,
4749
- executeLspPrepareRename,
4750
- executeLspInstallDecision,
4751
- executeLspGotoDefinition,
4752
- executeLspFindReferences,
4753
- executeLspDiagnostics,
5087
+ LSP_MCP_TOOLS,
4754
5088
  coerceToolArguments,
4755
- LSP_MCP_TOOLS
5089
+ executeLspDiagnostics,
5090
+ executeLspFindReferences,
5091
+ executeLspFormat,
5092
+ executeLspGotoDefinition,
5093
+ executeLspInstallDecision,
5094
+ executeLspPrepareRename,
5095
+ executeLspRename,
5096
+ executeLspStatus,
5097
+ executeLspSymbols,
5098
+ executeLspTool,
5099
+ isRecord7 as isRecord
4756
5100
  };