oh-my-opencode 5.0.0-beta.3 → 5.0.0-beta.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/command/publish.md +44 -16
- package/.agents/skills/publish/SKILL.md +44 -16
- package/.agents/skills/senpi-qa/SKILL.md +80 -0
- package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.mjs +65 -0
- package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.test.mjs +171 -0
- package/.agents/skills/work-with-pr/SKILL.md +37 -23
- package/.opencode/command/publish.md +44 -16
- package/.opencode/skills/work-with-pr/SKILL.md +37 -23
- package/README.ja.md +25 -21
- package/README.ko.md +25 -21
- package/README.md +38 -23
- package/README.ru.md +24 -20
- package/README.zh-cn.md +25 -21
- package/dist/agents/atlas/agent.d.ts +0 -1
- package/dist/agents/sisyphus/grok-4.d.ts +20 -0
- package/dist/agents/sisyphus/index.d.ts +2 -0
- package/dist/agents/sisyphus-agent-config.d.ts +6 -0
- package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
- package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +15 -4
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/config-manager/parse-opencode-config-file.d.ts +2 -1
- package/dist/cli/doctor/checks/system-plugin.d.ts +4 -3
- package/dist/cli/fallback-lane-policy.d.ts +1 -0
- package/dist/cli/index.js +22601 -20302
- package/dist/cli/install-codex/install-codex-test-fixtures.d.ts +1 -1
- package/dist/cli/run/on-complete-hook.d.ts +2 -0
- package/dist/cli/runtime-commands.d.ts +1 -1
- package/dist/cli/worktree-sweep/classify.d.ts +16 -0
- package/dist/cli/worktree-sweep/format.d.ts +8 -0
- package/dist/cli/worktree-sweep/git.d.ts +19 -0
- package/dist/cli/worktree-sweep/index.d.ts +7 -0
- package/dist/cli/worktree-sweep/options.d.ts +2 -0
- package/dist/cli/worktree-sweep/parse-worktree-list.d.ts +8 -0
- package/dist/cli/worktree-sweep/sweep.d.ts +2 -0
- package/dist/cli/worktree-sweep/types.d.ts +65 -0
- package/dist/cli/worktree-sweep/worktree-sweep.d.ts +2 -0
- package/dist/cli-node/index.js +22219 -19897
- package/dist/config/schema/background-task.d.ts +1 -0
- package/dist/config/schema/commands.d.ts +1 -1
- package/dist/config/schema/hooks.d.ts +1 -1
- package/dist/config/schema/oh-my-opencode-config.d.ts +5 -1
- package/dist/config/schema/ulw-execute.d.ts +5 -0
- package/dist/config/validate.d.ts +2 -0
- package/dist/create-hooks.d.ts +3 -1
- package/dist/features/background-agent/constants.d.ts +0 -7
- package/dist/features/background-agent/manager.d.ts +2 -1
- package/dist/features/background-agent/parent-wake-dispatched-tracker.d.ts +0 -1
- package/dist/features/background-agent/subagent-spawn-limits.d.ts +8 -0
- package/dist/features/btw-side/btw-command-draft.d.ts +7 -0
- package/dist/features/btw-side/context-injector.d.ts +15 -0
- package/dist/features/btw-side/index.d.ts +8 -0
- package/dist/features/btw-side/metadata.d.ts +15 -0
- package/dist/features/btw-side/parent-context-budget.d.ts +9 -0
- package/dist/features/btw-side/server-session-registry.d.ts +8 -0
- package/dist/features/btw-side/tui-adoption-cache.d.ts +13 -0
- package/dist/features/btw-side/tui-adoption-guard.d.ts +5 -0
- package/dist/features/btw-side/tui-controller-types.d.ts +68 -0
- package/dist/features/btw-side/tui-controller.d.ts +19 -0
- package/dist/features/btw-side/tui-escape-return.d.ts +12 -0
- package/dist/features/btw-side/tui-keymap.d.ts +17 -0
- package/dist/features/btw-side/tui-parent-validator.d.ts +6 -0
- package/dist/features/btw-side/tui-picker-options.d.ts +20 -0
- package/dist/features/btw-side/tui-picker.d.ts +9 -0
- package/dist/features/btw-side/tui-prompt-queue.d.ts +8 -0
- package/dist/features/btw-side/tui-session-bridge.d.ts +11 -0
- package/dist/features/btw-side/tui-session-catalog.d.ts +35 -0
- package/dist/features/btw-side/tui-side-removal.d.ts +11 -0
- package/dist/features/btw-side/tui-side-start.d.ts +9 -0
- package/dist/features/btw-side/tui-wiring.d.ts +8 -0
- package/dist/features/builtin-commands/templates/ulw-execute.d.ts +1 -0
- package/dist/features/builtin-commands/types.d.ts +1 -1
- package/dist/features/opengateway-provider/index.d.ts +13 -0
- package/dist/features/task-toast-manager/manager.d.ts +0 -24
- package/dist/features/team-mode/tools/messaging-fallback-wake.d.ts +15 -0
- package/dist/hooks/anthropic-context-window-limit-recovery/message-storage-directory.d.ts +0 -3
- package/dist/hooks/anthropic-context-window-limit-recovery/state.d.ts +1 -0
- package/dist/hooks/anthropic-context-window-limit-recovery/storage/empty-messages.d.ts +0 -1
- package/dist/hooks/atlas/atlas-hook.d.ts +1 -0
- package/dist/hooks/atlas/atlas-lifecycle-store.d.ts +50 -0
- package/dist/hooks/atlas/event-handler.d.ts +1 -0
- package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
- package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
- package/dist/hooks/atlas/tool-execute-before.d.ts +3 -0
- package/dist/hooks/atlas/types.d.ts +1 -0
- package/dist/hooks/claude-code-hooks/session-hook-state.d.ts +1 -0
- package/dist/hooks/claude-code-hooks/stop.d.ts +2 -0
- package/dist/hooks/claude-code-hooks/todo.d.ts +0 -1
- package/dist/hooks/claude-code-hooks/transcript.d.ts +2 -0
- package/dist/hooks/fsync-skip-warning/index.d.ts +4 -0
- package/dist/hooks/hashline-edit-diff-enhancer/hook.d.ts +1 -0
- package/dist/hooks/hashline-edit-diff-enhancer/pending-captures.d.ts +13 -0
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/keyword-detector/hook.d.ts +7 -0
- package/dist/hooks/keyword-detector/ultrawork/source-detector.d.ts +0 -1
- package/dist/hooks/model-fallback/hook.d.ts +1 -1
- package/dist/hooks/prometheus-md-only/agent-resolution.d.ts +2 -2
- package/dist/hooks/runtime-fallback/chat-message-handler.d.ts +2 -0
- package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +1 -0
- package/dist/hooks/runtime-fallback/runtime-model-settings.d.ts +6 -0
- package/dist/hooks/runtime-fallback/session-status-handler.d.ts +1 -1
- package/dist/hooks/runtime-fallback/types.d.ts +3 -1
- package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
- package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
- package/dist/hooks/{start-work → ulw-execute}/context-info-builder.d.ts +1 -1
- package/dist/hooks/{start-work → ulw-execute}/index.d.ts +1 -1
- package/dist/hooks/ulw-execute/ulw-execute-hook.d.ts +23 -0
- package/dist/index.js +12989 -7152
- package/dist/oh-my-opencode.schema.json +20 -2
- package/dist/plugin/chat-message/types.d.ts +3 -3
- package/dist/plugin/chat-message/ulw-execute-message.d.ts +5 -0
- package/dist/plugin/event-session-lifecycle.d.ts +1 -0
- package/dist/plugin/hooks/create-core-hooks.d.ts +2 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +2 -2
- package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
- package/dist/plugin/messages-transform.d.ts +1 -0
- package/dist/plugin-dispose.d.ts +3 -0
- package/dist/shared/agent-tool-restrictions.d.ts +0 -1
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/legacy-plugin-warning.d.ts +2 -1
- package/dist/shared/normalize-sdk-response.d.ts +1 -0
- package/dist/shared/plugin-entry-migrator.d.ts +4 -3
- package/dist/shared/plugin-entry-shape.d.ts +6 -0
- package/dist/shared/runtime-fallback-retry-marker.d.ts +16 -0
- package/dist/shared/shell-env.d.ts +1 -1
- package/dist/skills/ast-grep/AGENTS.md +51 -0
- package/dist/skills/coding-agent-sessions/AGENTS.md +62 -0
- package/dist/skills/coding-agent-sessions/SKILL.md +3 -2
- package/dist/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/dist/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/dist/skills/data-scientist/SKILL.md +99 -239
- package/dist/skills/data-scientist/references/execution-surfaces.md +91 -0
- package/dist/skills/data-scientist/references/placement.md +74 -0
- package/dist/skills/data-scientist/references/polars-lane.md +95 -0
- package/dist/skills/data-scientist/references/uv-setup.md +1 -1
- package/dist/skills/data-scientist/references/visualization.md +64 -0
- package/dist/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
- package/dist/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
- package/dist/skills/debugging/SKILL.md +2 -0
- package/dist/skills/debugging/references/methodology/00-setup.md +12 -0
- package/dist/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/dist/skills/debugging/references/runtimes/go.md +15 -1
- package/dist/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/dist/skills/debugging/references/runtimes/node.md +25 -0
- package/dist/skills/debugging/references/runtimes/python.md +13 -0
- package/dist/skills/debugging/references/runtimes/rust.md +41 -0
- package/dist/skills/debugging/references/scripts/dap.mjs +267 -0
- package/dist/skills/debugging/references/scripts/dap.test.ts +86 -0
- package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/dist/skills/debugging/references/tools/dap.md +103 -0
- package/dist/skills/debugging/references/tools/frida.md +193 -0
- package/dist/skills/frontend/SKILL.md +11 -7
- package/dist/skills/frontend/references/design/_INDEX.md +1 -0
- package/dist/skills/frontend/references/design/print-paged-media.md +76 -0
- package/dist/skills/frontend/references/design/stylegallery.md +80 -0
- package/dist/skills/frontend/references/designpowers/README.md +1 -1
- package/dist/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
- package/dist/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
- package/dist/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
- package/dist/skills/frontend/references/designpowers/orchestration.md +1 -1
- package/dist/skills/frontend/references/designpowers/routing.md +5 -5
- package/dist/skills/review-work/SKILL.md +3 -3
- package/dist/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/dist/skills/ultimate-browsing/SKILL.md +2 -0
- package/dist/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/dist/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/dist/skills/{start-work → ulw-execute}/SKILL.md +9 -8
- package/dist/skills/ulw-plan/SKILL.md +6 -6
- package/dist/skills/ulw-plan/references/full-workflow.md +31 -7
- package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
- package/dist/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/dist/skills/ulw-research/SKILL.md +4 -2
- package/dist/skills/visual-qa/AGENTS.md +58 -0
- package/dist/skills/visual-qa/SKILL.md +3 -2
- package/dist/tools/delegate-task/builtin-categories.d.ts +1 -0
- package/dist/tools/delegate-task/builtin-category-definition.d.ts +1 -0
- package/dist/tools/delegate-task/sync-session-cleanup.d.ts +3 -0
- package/dist/tools/delegate-task/sync-session-poller.d.ts +1 -0
- package/dist/tools/delegate-task/tool-description.d.ts +3 -1
- package/dist/tools/delegate-task/types.d.ts +4 -0
- package/dist/tui.d.ts +12 -0
- package/dist/tui.js +11522 -11501
- package/package.json +42 -36
- package/packages/git-bash-mcp/dist/cli.js +6 -1
- package/packages/git-bash-mcp/package.json +1 -1
- package/packages/lsp-core/src/index.ts +1 -0
- package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +0 -28
- package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
- package/packages/lsp-core/src/lsp/client-wrapper.test.ts +163 -13
- package/packages/lsp-core/src/lsp/client-wrapper.ts +110 -23
- package/packages/lsp-core/src/lsp/client.ts +26 -0
- package/packages/lsp-core/src/lsp/connection.ts +16 -0
- package/packages/lsp-core/src/lsp/constants.ts +6 -0
- package/packages/lsp-core/src/lsp/errors.ts +15 -0
- package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
- package/packages/lsp-core/src/lsp/format-document.ts +90 -0
- package/packages/lsp-core/src/lsp/manager-lifecycle.test.ts +262 -0
- package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
- package/packages/lsp-core/src/lsp/manager.ts +138 -12
- package/packages/lsp-core/src/lsp/outside-context-workspace.ts +33 -0
- package/packages/lsp-core/src/lsp/server-definitions.ts +29 -0
- package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
- package/packages/lsp-core/src/lsp/server-installation.ts +200 -27
- package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
- package/packages/lsp-core/src/lsp/server-resolution.ts +18 -5
- package/packages/lsp-core/src/lsp/transport.ts +9 -0
- package/packages/lsp-core/src/lsp/types.ts +8 -0
- package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +20 -1
- package/packages/lsp-core/src/lsp/workspace-markers.ts +18 -0
- package/packages/lsp-core/src/mcp.ts +3 -0
- package/packages/lsp-core/src/request-context.test.ts +29 -0
- package/packages/lsp-core/src/request-context.ts +1 -1
- package/packages/lsp-core/src/tool-surface.test.ts +13 -1
- package/packages/lsp-core/src/tools/definitions.ts +14 -0
- package/packages/lsp-core/src/tools/diagnostics.ts +3 -3
- package/packages/lsp-core/src/tools/format.test.ts +56 -0
- package/packages/lsp-core/src/tools/format.ts +56 -0
- package/packages/lsp-core/src/tools/index.ts +1 -0
- package/packages/lsp-core/src/tools/navigation.ts +4 -2
- package/packages/lsp-core/src/tools/rename.ts +4 -2
- package/packages/lsp-core/src/tools/symbols.ts +1 -1
- package/packages/lsp-core/src/tools/types.ts +10 -0
- package/packages/lsp-daemon/dist/cli.js +752 -307
- package/packages/lsp-daemon/dist/client.d.ts +10 -0
- package/packages/lsp-daemon/dist/client.js +712 -264
- package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
- package/packages/lsp-daemon/dist/daemon-client.js +3 -0
- package/packages/lsp-daemon/dist/ensure-daemon.js +1 -0
- package/packages/lsp-daemon/dist/index.js +716 -273
- package/packages/lsp-daemon/dist/proxy.js +3 -0
- package/packages/lsp-daemon/dist/version-reap.js +1 -1
- package/packages/lsp-daemon/package.json +1 -1
- package/packages/lsp-tools-mcp/dist/cli.js +671 -228
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +207 -103
- package/packages/lsp-tools-mcp/dist/mcp.js +673 -230
- package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
- package/packages/lsp-tools-mcp/dist/tools.js +677 -238
- package/packages/omo-codex/THIRD-PARTY-NOTICES.md +4 -4
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +4 -4
- package/packages/omo-codex/plugin/AGENTS.md +47 -0
- package/packages/omo-codex/plugin/README.md +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +34 -33
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +323 -117
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +275 -85
- package/packages/omo-codex/plugin/components/codegraph/package.json +4 -4
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +12 -0
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable-idle.test.ts +47 -0
- package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +9 -0
- package/packages/omo-codex/plugin/components/comment-checker/biome.json +2 -2
- package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +2 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +5 -5
- package/packages/omo-codex/plugin/components/comment-checker/src/apply-patch.ts +2 -8
- package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +1 -2
- package/packages/omo-codex/plugin/components/comment-checker/src/request-extractor.ts +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +1 -0
- package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +3 -4
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +1 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +1 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +5 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +1 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +4 -21
- package/packages/omo-codex/plugin/components/lsp/AGENTS.md +30 -15
- package/packages/omo-codex/plugin/components/lsp/biome.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +4 -4
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +702 -278
- package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.js +1 -1
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +5 -5
- package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
- package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +1 -1
- package/packages/omo-codex/plugin/components/lsp/src/daemon-cli-path.ts +1 -5
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +6 -7
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +1 -2
- package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +11 -1
- package/packages/omo-codex/plugin/components/rules/AGENTS.md +12 -0
- package/packages/omo-codex/plugin/components/rules/biome.json +2 -2
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +60 -45
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +7 -7
- package/packages/omo-codex/plugin/components/rules/src/config.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +9 -5
- package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +1 -4
- package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +4 -9
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +17 -25
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
- package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
- package/packages/omo-codex/plugin/components/rules/test/dynamic-target-fingerprints.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/engine.test.ts +7 -4
- package/packages/omo-codex/plugin/components/rules/test/finder.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +39 -72
- package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/matcher.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +1 -1
- package/packages/omo-codex/plugin/components/rules/test/parser.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +5 -6
- package/packages/omo-codex/plugin/components/rules/test/rules-engine-consumption.test.ts +3 -6
- package/packages/omo-codex/plugin/components/rules/test/scanner.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/sources.test.ts +2 -5
- package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +2 -17
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +5 -5
- package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +3 -9
- package/packages/omo-codex/plugin/components/telemetry/AGENTS.md +8 -0
- package/packages/omo-codex/plugin/components/telemetry/biome.json +2 -2
- package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2463 -437
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2467 -441
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +5 -5
- package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +1 -4
- package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -14
- package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +1 -1
- package/packages/omo-codex/plugin/components/telemetry/test/diagnostics.test.ts +2 -5
- package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +5 -0
- package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +13 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -5
- package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +13 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -6
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +31 -7
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +9 -1
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
- package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +5 -4
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/NOTICE +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/README.md +5 -5
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/biome.json +2 -2
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/directive.md +6 -6
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +12 -12
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +28 -0
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/package.json +12 -12
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/boulder-reader.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/cli.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/codex-hook.ts +3 -3
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/directive.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/index.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/boulder-reader.test.ts +3 -3
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +1 -4
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +8 -22
- package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +17 -0
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +13 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +11 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +124 -68
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.d.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +9 -6
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +7 -10
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +50 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +13 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +3 -5
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +16 -5
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +11 -14
- package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +73 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +44 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +25 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +26 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +27 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +18 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +7 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -37
- package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +45 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +20 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +8 -5
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/surface.test.ts +74 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +4 -5
- package/packages/omo-codex/plugin/components/ulw-loop/vitest.config.ts +1 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +17 -0
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +17 -0
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/model-catalog.json +3 -3
- package/packages/omo-codex/plugin/package-lock.json +681 -395
- package/packages/omo-codex/plugin/package.json +2 -2
- package/packages/omo-codex/plugin/scripts/AGENTS.md +40 -0
- package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -1
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +3 -3
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +11 -11
- package/packages/omo-codex/plugin/shared/package.json +3 -4
- package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +51 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +62 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
- package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
- package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
- package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
- package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
- package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
- package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +11 -7
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +4 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +13 -1
- package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +12 -11
- package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -0
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +31 -7
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +4 -2
- package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +3 -2
- package/packages/omo-codex/plugin/test/AGENTS.md +47 -0
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +8 -28
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
- package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
- package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
- package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -2
- package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +2 -2
- package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +2 -2
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +4 -4
- package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
- package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
- package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +12 -12
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +1 -119
- package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
- package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
- package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
- package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
- package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
- package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +0 -3
- package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
- package/packages/omo-codex/scripts/AGENTS.md +36 -0
- package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +2 -2
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +2637 -549
- package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
- package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
- package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
- package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
- package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
- package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
- package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
- package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
- package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
- package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
- package/packages/shared-skills/skills/debugging/SKILL.md +2 -0
- package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
- package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
- package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
- package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
- package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
- package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
- package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
- package/packages/shared-skills/skills/frontend/SKILL.md +11 -7
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
- package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
- package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
- package/packages/shared-skills/skills/review-work/SKILL.md +3 -3
- package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +9 -8
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +6 -6
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/packages/shared-skills/skills/ulw-research/SKILL.md +4 -2
- package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
- package/packages/shared-skills/skills/visual-qa/SKILL.md +3 -2
- package/script/qa/web-terminal-visual-qa.mjs +2 -0
- package/script/qa/xterm-live-terminal.mjs +18 -2
- package/dist/config/schema/start-work.d.ts +0 -5
- package/dist/features/builtin-commands/templates/start-work.d.ts +0 -1
- package/dist/hooks/ralph-loop/completion-promise-detector-test-input.d.ts +0 -11
- package/dist/hooks/ralph-loop/loop-session-recovery.d.ts +0 -7
- package/dist/hooks/start-work/start-work-hook.d.ts +0 -23
- package/dist/plugin/chat-message/start-work-message.d.ts +0 -5
- package/dist/skills/data-scientist/references/common-scenarios.md +0 -176
- package/dist/skills/data-scientist/references/execution-templates.md +0 -197
- package/dist/skills/data-scientist/references/integration-patterns.md +0 -153
- package/dist/skills/data-scientist/references/performance-benchmarks.md +0 -37
- package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
- package/dist/tools/call-omo-agent/message-storage-directory.d.ts +0 -1
- package/dist/tools/delegate-task/model-string-parser.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/missing-dependency-result.d.ts +0 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
- package/packages/omo-codex/plugin/skills/data-scientist/references/common-scenarios.md +0 -176
- package/packages/omo-codex/plugin/skills/data-scientist/references/execution-templates.md +0 -197
- package/packages/omo-codex/plugin/skills/data-scientist/references/integration-patterns.md +0 -153
- package/packages/omo-codex/plugin/skills/data-scientist/references/performance-benchmarks.md +0 -37
- package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
- package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
- package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
- package/packages/shared-skills/skills/data-scientist/references/common-scenarios.md +0 -176
- package/packages/shared-skills/skills/data-scientist/references/execution-templates.md +0 -197
- package/packages/shared-skills/skills/data-scientist/references/integration-patterns.md +0 -153
- package/packages/shared-skills/skills/data-scientist/references/performance-benchmarks.md +0 -37
- /package/dist/hooks/{start-work → ulw-execute}/context-info-formatters.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/explicit-plan-context.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/notepad-scaffold.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/parse-user-request.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/plan-discovery-context.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/plan-selection.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/session-plan-affinity.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/work-initializer.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/worktree-block.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/worktree-detector.d.ts +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/.gitattributes +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/CHANGELOG.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/LICENSE +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/plan-checklist.ts +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/types.ts +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
|
@@ -25,28 +25,24 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
|
|
|
25
25
|
var REQUEST_TIMEOUT_MS = 15000;
|
|
26
26
|
var INIT_TIMEOUT_MS = 60000;
|
|
27
27
|
var IDLE_TIMEOUT_MS = 5 * 60000;
|
|
28
|
+
var MAX_RESIDENT_CLIENTS = 6;
|
|
28
29
|
var REAPER_INTERVAL_MS = 60000;
|
|
29
30
|
var STOP_HARD_KILL_TIMEOUT_MS = 5000;
|
|
30
31
|
var STOP_SIGKILL_GRACE_MS = 1000;
|
|
32
|
+
var CLIENT_RESPAWN_RETRY_LIMIT = 2;
|
|
33
|
+
var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
|
|
31
34
|
|
|
32
35
|
// ../lsp-core/src/lsp/errors.ts
|
|
33
36
|
class LspConnectionClosedError extends Error {
|
|
34
|
-
serverId;
|
|
35
|
-
root;
|
|
36
|
-
name = "LspConnectionClosedError";
|
|
37
37
|
constructor(serverId, root, message) {
|
|
38
38
|
super(message ?? `LSP connection closed for ${serverId} at ${root}`);
|
|
39
39
|
this.serverId = serverId;
|
|
40
40
|
this.root = root;
|
|
41
|
+
this.name = "LspConnectionClosedError";
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
class LspProcessExitedError extends Error {
|
|
45
|
-
serverId;
|
|
46
|
-
root;
|
|
47
|
-
exitCode;
|
|
48
|
-
stderrTail;
|
|
49
|
-
name = "LspProcessExitedError";
|
|
50
46
|
constructor(serverId, root, exitCode, stderrTail) {
|
|
51
47
|
const stderrSuffix = stderrTail ? `
|
|
52
48
|
stderr tail: ${stderrTail}` : "";
|
|
@@ -55,46 +51,59 @@ stderr tail: ${stderrTail}` : "";
|
|
|
55
51
|
this.root = root;
|
|
56
52
|
this.exitCode = exitCode;
|
|
57
53
|
this.stderrTail = stderrTail;
|
|
54
|
+
this.name = "LspProcessExitedError";
|
|
58
55
|
}
|
|
59
56
|
}
|
|
60
57
|
|
|
61
58
|
class LspRequestTimeoutError extends Error {
|
|
62
|
-
method;
|
|
63
|
-
stderrTail;
|
|
64
|
-
name = "LspRequestTimeoutError";
|
|
65
59
|
constructor(method, stderrTail) {
|
|
66
60
|
const stderrSuffix = stderrTail ? `
|
|
67
61
|
recent stderr: ${stderrTail}` : "";
|
|
68
62
|
super(`LSP request timeout (method: ${method})${stderrSuffix}`);
|
|
69
63
|
this.method = method;
|
|
70
64
|
this.stderrTail = stderrTail;
|
|
65
|
+
this.name = "LspRequestTimeoutError";
|
|
71
66
|
}
|
|
72
67
|
}
|
|
73
68
|
|
|
74
69
|
class LspInvalidPathError extends Error {
|
|
75
|
-
|
|
70
|
+
constructor() {
|
|
71
|
+
super(...arguments);
|
|
72
|
+
this.name = "LspInvalidPathError";
|
|
73
|
+
}
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
class LspServerLookupError extends Error {
|
|
79
|
-
lookup;
|
|
80
|
-
name = "LspServerLookupError";
|
|
81
77
|
constructor(message, lookup) {
|
|
82
78
|
super(message);
|
|
83
79
|
this.lookup = lookup;
|
|
80
|
+
this.name = "LspServerLookupError";
|
|
84
81
|
}
|
|
85
82
|
}
|
|
86
83
|
|
|
87
84
|
class LspServerInitializingError extends Error {
|
|
88
|
-
originalError;
|
|
89
|
-
name = "LspServerInitializingError";
|
|
90
85
|
constructor(originalError) {
|
|
91
86
|
super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
|
|
92
87
|
this.originalError = originalError;
|
|
88
|
+
this.name = "LspServerInitializingError";
|
|
93
89
|
}
|
|
94
90
|
}
|
|
95
91
|
|
|
96
92
|
class LspProcessSpawnError extends Error {
|
|
97
|
-
|
|
93
|
+
constructor() {
|
|
94
|
+
super(...arguments);
|
|
95
|
+
this.name = "LspProcessSpawnError";
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
class LspClientRespawnBudgetExceededError extends Error {
|
|
100
|
+
constructor(serverId, root, retryLimit) {
|
|
101
|
+
super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
|
|
102
|
+
this.serverId = serverId;
|
|
103
|
+
this.root = root;
|
|
104
|
+
this.retryLimit = retryLimit;
|
|
105
|
+
this.name = "LspClientRespawnBudgetExceededError";
|
|
106
|
+
}
|
|
98
107
|
}
|
|
99
108
|
function isLspDeadConnectionError(err) {
|
|
100
109
|
return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
|
|
@@ -110,20 +119,31 @@ var METHOD_NOT_FOUND = -32601;
|
|
|
110
119
|
var INTERNAL_ERROR = -32603;
|
|
111
120
|
|
|
112
121
|
class JsonRpcConnection {
|
|
113
|
-
reader;
|
|
114
|
-
writer;
|
|
115
|
-
pendingRequests = new Map;
|
|
116
|
-
notificationHandlers = new Map;
|
|
117
|
-
requestHandlers = new Map;
|
|
118
|
-
closeHandlers = [];
|
|
119
|
-
errorHandlers = [];
|
|
120
|
-
inputBuffer = Buffer.alloc(0);
|
|
121
|
-
nextRequestId = 1;
|
|
122
|
-
listening = false;
|
|
123
|
-
disposed = false;
|
|
124
122
|
constructor(reader, writer) {
|
|
125
123
|
this.reader = reader;
|
|
126
124
|
this.writer = writer;
|
|
125
|
+
this.pendingRequests = new Map;
|
|
126
|
+
this.notificationHandlers = new Map;
|
|
127
|
+
this.requestHandlers = new Map;
|
|
128
|
+
this.closeHandlers = [];
|
|
129
|
+
this.errorHandlers = [];
|
|
130
|
+
this.inputBuffer = Buffer.alloc(0);
|
|
131
|
+
this.nextRequestId = 1;
|
|
132
|
+
this.listening = false;
|
|
133
|
+
this.disposed = false;
|
|
134
|
+
this.handleData = (chunk) => {
|
|
135
|
+
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
136
|
+
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
137
|
+
this.drainInputBuffer();
|
|
138
|
+
};
|
|
139
|
+
this.handleClose = () => {
|
|
140
|
+
for (const handler of this.closeHandlers) {
|
|
141
|
+
handler();
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
this.handleStreamError = (error) => {
|
|
145
|
+
this.emitError(error);
|
|
146
|
+
};
|
|
127
147
|
}
|
|
128
148
|
listen() {
|
|
129
149
|
if (this.listening)
|
|
@@ -244,19 +264,6 @@ class JsonRpcConnection {
|
|
|
244
264
|
this.notificationHandlers.clear();
|
|
245
265
|
this.requestHandlers.clear();
|
|
246
266
|
}
|
|
247
|
-
handleData = (chunk) => {
|
|
248
|
-
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
249
|
-
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
250
|
-
this.drainInputBuffer();
|
|
251
|
-
};
|
|
252
|
-
handleClose = () => {
|
|
253
|
-
for (const handler of this.closeHandlers) {
|
|
254
|
-
handler();
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
handleStreamError = (error) => {
|
|
258
|
-
this.emitError(error);
|
|
259
|
-
};
|
|
260
267
|
drainInputBuffer() {
|
|
261
268
|
while (true) {
|
|
262
269
|
const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR);
|
|
@@ -604,31 +611,26 @@ function isPosition(value) {
|
|
|
604
611
|
|
|
605
612
|
// ../lsp-core/src/lsp/transport.ts
|
|
606
613
|
class LspClientNotStartedError extends Error {
|
|
607
|
-
serverId;
|
|
608
|
-
root;
|
|
609
|
-
name = "LspClientNotStartedError";
|
|
610
614
|
constructor(serverId, root) {
|
|
611
615
|
super("LSP client not started");
|
|
612
616
|
this.serverId = serverId;
|
|
613
617
|
this.root = root;
|
|
618
|
+
this.name = "LspClientNotStartedError";
|
|
614
619
|
}
|
|
615
620
|
}
|
|
616
621
|
|
|
617
622
|
class LspClientTransport {
|
|
618
|
-
root;
|
|
619
|
-
server;
|
|
620
|
-
proc = null;
|
|
621
|
-
connection = null;
|
|
622
|
-
stderrBuffer = [];
|
|
623
|
-
processExited = false;
|
|
624
|
-
diagnosticsStore = new Map;
|
|
625
|
-
requestTimeoutMs;
|
|
626
|
-
initializeTimeoutMs;
|
|
627
|
-
workspaceApplyEditHandler = null;
|
|
628
|
-
diagnosticPullSupported = false;
|
|
629
623
|
constructor(root, server, timeouts = {}) {
|
|
630
624
|
this.root = root;
|
|
631
625
|
this.server = server;
|
|
626
|
+
this.proc = null;
|
|
627
|
+
this.connection = null;
|
|
628
|
+
this.stderrBuffer = [];
|
|
629
|
+
this.processExited = false;
|
|
630
|
+
this.diagnosticsStore = new Map;
|
|
631
|
+
this.workspaceApplyEditHandler = null;
|
|
632
|
+
this.diagnosticPullSupported = false;
|
|
633
|
+
this.documentFormattingSupported = false;
|
|
632
634
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
633
635
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
634
636
|
}
|
|
@@ -650,6 +652,12 @@ class LspClientTransport {
|
|
|
650
652
|
isDiagnosticPullSupported() {
|
|
651
653
|
return this.diagnosticPullSupported;
|
|
652
654
|
}
|
|
655
|
+
setDocumentFormattingSupported(supported) {
|
|
656
|
+
this.documentFormattingSupported = supported;
|
|
657
|
+
}
|
|
658
|
+
isDocumentFormattingSupported() {
|
|
659
|
+
return this.documentFormattingSupported;
|
|
660
|
+
}
|
|
653
661
|
handlePublishDiagnostics(params) {
|
|
654
662
|
this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
|
|
655
663
|
}
|
|
@@ -863,6 +871,14 @@ function supportsDiagnosticPull(capabilities) {
|
|
|
863
871
|
return false;
|
|
864
872
|
return Object.hasOwn(capabilities, "diagnosticProvider");
|
|
865
873
|
}
|
|
874
|
+
function supportsDocumentFormatting(capabilities) {
|
|
875
|
+
if (capabilities === undefined)
|
|
876
|
+
return false;
|
|
877
|
+
const provider = capabilities.documentFormattingProvider;
|
|
878
|
+
if (provider === undefined || provider === null || provider === false)
|
|
879
|
+
return false;
|
|
880
|
+
return provider === true || typeof provider === "object";
|
|
881
|
+
}
|
|
866
882
|
|
|
867
883
|
class LspClientConnection extends LspClientTransport {
|
|
868
884
|
async initialize() {
|
|
@@ -879,6 +895,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
879
895
|
references: {},
|
|
880
896
|
documentSymbol: { hierarchicalDocumentSymbolSupport: true },
|
|
881
897
|
publishDiagnostics: {},
|
|
898
|
+
formatting: { dynamicRegistration: false },
|
|
882
899
|
rename: {
|
|
883
900
|
prepareSupport: true,
|
|
884
901
|
prepareSupportDefaultBehavior: 1
|
|
@@ -920,6 +937,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
920
937
|
initializationOptions: this.server.initialization
|
|
921
938
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
922
939
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
940
|
+
this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
|
|
923
941
|
await this.sendNotification("initialized", {});
|
|
924
942
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
925
943
|
settings: { json: { validate: { enable: true } } }
|
|
@@ -1135,16 +1153,12 @@ function movedPath(candidate, oldPath, newPath) {
|
|
|
1135
1153
|
}
|
|
1136
1154
|
|
|
1137
1155
|
class WorkspaceDocumentState {
|
|
1138
|
-
sendNotification;
|
|
1139
|
-
clearDiagnostics;
|
|
1140
|
-
openDocuments = new Map;
|
|
1141
|
-
openByUri = new Map;
|
|
1142
|
-
openPromises = new Map;
|
|
1143
|
-
now;
|
|
1144
|
-
versionlessPublishQuiescenceMs;
|
|
1145
1156
|
constructor(sendNotification, clearDiagnostics, options = {}) {
|
|
1146
1157
|
this.sendNotification = sendNotification;
|
|
1147
1158
|
this.clearDiagnostics = clearDiagnostics;
|
|
1159
|
+
this.openDocuments = new Map;
|
|
1160
|
+
this.openByUri = new Map;
|
|
1161
|
+
this.openPromises = new Map;
|
|
1148
1162
|
this.now = options.now ?? (() => Date.now());
|
|
1149
1163
|
this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
|
|
1150
1164
|
}
|
|
@@ -1408,13 +1422,11 @@ import { dirname, isAbsolute, relative as relative2, resolve as resolve2 } from
|
|
|
1408
1422
|
import { fileURLToPath } from "node:url";
|
|
1409
1423
|
|
|
1410
1424
|
class WorkspaceEditPathError extends Error {
|
|
1411
|
-
path;
|
|
1412
|
-
detail;
|
|
1413
|
-
name = "WorkspaceEditPathError";
|
|
1414
1425
|
constructor(path, detail) {
|
|
1415
1426
|
super(`${detail}: ${path}`);
|
|
1416
1427
|
this.path = path;
|
|
1417
1428
|
this.detail = detail;
|
|
1429
|
+
this.name = "WorkspaceEditPathError";
|
|
1418
1430
|
}
|
|
1419
1431
|
}
|
|
1420
1432
|
function isPathInsideWorkspace(filePath, workspaceRoot) {
|
|
@@ -1706,13 +1718,11 @@ function canonicalFingerprint(operations) {
|
|
|
1706
1718
|
|
|
1707
1719
|
// ../lsp-core/src/lsp/workspace-edit-types.ts
|
|
1708
1720
|
class WorkspaceEditValidationError extends Error {
|
|
1709
|
-
changeIndex;
|
|
1710
|
-
detail;
|
|
1711
|
-
name = "WorkspaceEditValidationError";
|
|
1712
1721
|
constructor(changeIndex, detail) {
|
|
1713
1722
|
super(`change ${changeIndex}: ${detail}`);
|
|
1714
1723
|
this.changeIndex = changeIndex;
|
|
1715
1724
|
this.detail = detail;
|
|
1725
|
+
this.name = "WorkspaceEditValidationError";
|
|
1716
1726
|
}
|
|
1717
1727
|
}
|
|
1718
1728
|
|
|
@@ -2210,10 +2220,9 @@ function simulateDelete(operation, virtual) {
|
|
|
2210
2220
|
import { existsSync as existsSync4, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
|
|
2211
2221
|
import { dirname as dirname3, resolve as resolve4 } from "node:path";
|
|
2212
2222
|
class WorkspaceSnapshotBuilder {
|
|
2213
|
-
workspaceRoot;
|
|
2214
|
-
snapshots = new Map;
|
|
2215
2223
|
constructor(workspaceRoot) {
|
|
2216
2224
|
this.workspaceRoot = workspaceRoot;
|
|
2225
|
+
this.snapshots = new Map;
|
|
2217
2226
|
}
|
|
2218
2227
|
build(operations) {
|
|
2219
2228
|
this.add(this.workspaceRoot, false);
|
|
@@ -2257,8 +2266,10 @@ function snapshotOperations(operations, workspaceRoot) {
|
|
|
2257
2266
|
|
|
2258
2267
|
// ../lsp-core/src/lsp/workspace-edit-plan.ts
|
|
2259
2268
|
class PlanPathIndex {
|
|
2260
|
-
|
|
2261
|
-
|
|
2269
|
+
constructor() {
|
|
2270
|
+
this.firstChangeByPath = new Map;
|
|
2271
|
+
this.reportedPathByCanonical = new Map;
|
|
2272
|
+
}
|
|
2262
2273
|
build(operations) {
|
|
2263
2274
|
for (const operation of operations) {
|
|
2264
2275
|
switch (operation.kind) {
|
|
@@ -2347,14 +2358,11 @@ function isRecord3(value) {
|
|
|
2347
2358
|
}
|
|
2348
2359
|
|
|
2349
2360
|
class WorkspaceMutationController {
|
|
2350
|
-
workspaceRoot;
|
|
2351
|
-
documents;
|
|
2352
|
-
activeLease = null;
|
|
2353
|
-
nextLeaseId = 1;
|
|
2354
|
-
io;
|
|
2355
2361
|
constructor(workspaceRoot, documents) {
|
|
2356
2362
|
this.workspaceRoot = workspaceRoot;
|
|
2357
2363
|
this.documents = documents;
|
|
2364
|
+
this.activeLease = null;
|
|
2365
|
+
this.nextLeaseId = 1;
|
|
2358
2366
|
}
|
|
2359
2367
|
setIo(io) {
|
|
2360
2368
|
this.io = io;
|
|
@@ -2467,12 +2475,9 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
|
|
|
2467
2475
|
var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
|
|
2468
2476
|
|
|
2469
2477
|
class LspClient extends LspClientConnection {
|
|
2470
|
-
diagnosticPullErrors = [];
|
|
2471
|
-
documents;
|
|
2472
|
-
workspaceMutations;
|
|
2473
|
-
diagnosticsFreshnessTimeoutMs;
|
|
2474
2478
|
constructor(root, server, options = {}) {
|
|
2475
2479
|
super(root, server, options);
|
|
2480
|
+
this.diagnosticPullErrors = [];
|
|
2476
2481
|
this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
|
|
2477
2482
|
this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
|
|
2478
2483
|
versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
|
|
@@ -2527,6 +2532,18 @@ class LspClient extends LspClientConnection {
|
|
|
2527
2532
|
textDocument: { uri: pathToFileURL3(absPath).href }
|
|
2528
2533
|
}, options);
|
|
2529
2534
|
}
|
|
2535
|
+
async formatDocument(filePath, options, signal) {
|
|
2536
|
+
if (!this.isDocumentFormattingSupported())
|
|
2537
|
+
return null;
|
|
2538
|
+
const absPath = this.resolveWorkspacePath(filePath);
|
|
2539
|
+
await this.openFile(absPath);
|
|
2540
|
+
const requestOptions = signal === undefined ? {} : { signal };
|
|
2541
|
+
const edits = await this.sendRequest("textDocument/formatting", {
|
|
2542
|
+
textDocument: { uri: pathToFileURL3(absPath).href },
|
|
2543
|
+
options
|
|
2544
|
+
}, requestOptions);
|
|
2545
|
+
return edits ?? [];
|
|
2546
|
+
}
|
|
2530
2547
|
async workspaceSymbols(query, signal) {
|
|
2531
2548
|
const options = signal === undefined ? {} : { signal };
|
|
2532
2549
|
return this.sendRequest("workspace/symbol", { query }, options);
|
|
@@ -2772,18 +2789,16 @@ function awaitWithSignal(promise, signal) {
|
|
|
2772
2789
|
}
|
|
2773
2790
|
|
|
2774
2791
|
class LspManager {
|
|
2775
|
-
clients = new Map;
|
|
2776
|
-
reaperHandle = null;
|
|
2777
|
-
signalDisposer = null;
|
|
2778
|
-
disposed = false;
|
|
2779
|
-
idleTimeoutMs;
|
|
2780
|
-
initTimeoutMs;
|
|
2781
|
-
reaperIntervalMs;
|
|
2782
|
-
clientFactory;
|
|
2783
|
-
now;
|
|
2784
2792
|
constructor(options = {}) {
|
|
2793
|
+
this.clients = new Map;
|
|
2794
|
+
this.pendingStops = new Map;
|
|
2795
|
+
this.respawnBudgets = new Map;
|
|
2796
|
+
this.reaperHandle = null;
|
|
2797
|
+
this.signalDisposer = null;
|
|
2798
|
+
this.disposed = false;
|
|
2785
2799
|
this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
|
|
2786
2800
|
this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
2801
|
+
this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
|
|
2787
2802
|
this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
|
|
2788
2803
|
this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
|
|
2789
2804
|
this.now = options.now ?? (() => Date.now());
|
|
@@ -2803,24 +2818,79 @@ class LspManager {
|
|
|
2803
2818
|
getKey(root, serverId) {
|
|
2804
2819
|
return `${root}::${serverId}`;
|
|
2805
2820
|
}
|
|
2821
|
+
tombstoneStop(key, client) {
|
|
2822
|
+
const stop = stopClientBestEffort(client);
|
|
2823
|
+
this.pendingStops.set(key, stop);
|
|
2824
|
+
stop.finally(() => {
|
|
2825
|
+
if (this.pendingStops.get(key) === stop) {
|
|
2826
|
+
this.pendingStops.delete(key);
|
|
2827
|
+
}
|
|
2828
|
+
});
|
|
2829
|
+
return stop;
|
|
2830
|
+
}
|
|
2831
|
+
recordDeadGeneration(key) {
|
|
2832
|
+
let budget = this.respawnBudgets.get(key);
|
|
2833
|
+
if (budget === undefined) {
|
|
2834
|
+
budget = { deadGenerations: 0, exhaustedAt: null };
|
|
2835
|
+
this.respawnBudgets.set(key, budget);
|
|
2836
|
+
}
|
|
2837
|
+
budget.deadGenerations += 1;
|
|
2838
|
+
}
|
|
2839
|
+
markHealthyGeneration(key) {
|
|
2840
|
+
this.respawnBudgets.delete(key);
|
|
2841
|
+
}
|
|
2842
|
+
ensureRespawnAllowed(key, root, serverId) {
|
|
2843
|
+
const budget = this.respawnBudgets.get(key);
|
|
2844
|
+
if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
|
|
2845
|
+
return;
|
|
2846
|
+
if (budget.exhaustedAt === null) {
|
|
2847
|
+
budget.exhaustedAt = this.now();
|
|
2848
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
2849
|
+
}
|
|
2850
|
+
if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
|
|
2851
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
2852
|
+
}
|
|
2853
|
+
budget.deadGenerations = 0;
|
|
2854
|
+
budget.exhaustedAt = null;
|
|
2855
|
+
}
|
|
2806
2856
|
reapStale() {
|
|
2807
2857
|
const t = this.now();
|
|
2808
2858
|
for (const [key, managed] of this.clients) {
|
|
2809
2859
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
2810
|
-
stopClientBestEffort(managed.client);
|
|
2811
2860
|
this.clients.delete(key);
|
|
2861
|
+
this.tombstoneStop(key, managed.client);
|
|
2812
2862
|
continue;
|
|
2813
2863
|
}
|
|
2814
2864
|
if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
|
|
2815
|
-
stopClientBestEffort(managed.client);
|
|
2816
2865
|
this.clients.delete(key);
|
|
2866
|
+
this.tombstoneStop(key, managed.client);
|
|
2817
2867
|
}
|
|
2818
2868
|
}
|
|
2819
2869
|
}
|
|
2870
|
+
evictForAdmission() {
|
|
2871
|
+
while (this.clients.size >= this.maxResidentClients) {
|
|
2872
|
+
const victim = this.leastRecentlyUsedIdleClient();
|
|
2873
|
+
if (!victim)
|
|
2874
|
+
return;
|
|
2875
|
+
this.clients.delete(victim.key);
|
|
2876
|
+
this.tombstoneStop(victim.key, victim.managed.client);
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
leastRecentlyUsedIdleClient() {
|
|
2880
|
+
let candidate = null;
|
|
2881
|
+
for (const [key, managed] of this.clients) {
|
|
2882
|
+
if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
|
|
2883
|
+
continue;
|
|
2884
|
+
if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
|
|
2885
|
+
candidate = { key, managed };
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2888
|
+
return candidate;
|
|
2889
|
+
}
|
|
2820
2890
|
async tryDeleteIfOrphaned(key, managed) {
|
|
2821
2891
|
if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
|
|
2822
2892
|
this.clients.delete(key);
|
|
2823
|
-
await
|
|
2893
|
+
await this.tombstoneStop(key, managed.client);
|
|
2824
2894
|
}
|
|
2825
2895
|
}
|
|
2826
2896
|
async getClient(root, server, signal) {
|
|
@@ -2829,12 +2899,22 @@ class LspManager {
|
|
|
2829
2899
|
}
|
|
2830
2900
|
signal?.throwIfAborted();
|
|
2831
2901
|
const key = this.getKey(root, server.id);
|
|
2902
|
+
for (;; ) {
|
|
2903
|
+
const pendingStop = this.pendingStops.get(key);
|
|
2904
|
+
if (pendingStop === undefined)
|
|
2905
|
+
break;
|
|
2906
|
+
await awaitWithSignal(pendingStop, signal);
|
|
2907
|
+
signal?.throwIfAborted();
|
|
2908
|
+
}
|
|
2909
|
+
if (this.disposed) {
|
|
2910
|
+
throw new Error("LspManager has been disposed");
|
|
2911
|
+
}
|
|
2832
2912
|
let managed = this.clients.get(key);
|
|
2833
2913
|
if (managed) {
|
|
2834
2914
|
const t = this.now();
|
|
2835
2915
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
2836
|
-
await stopClientBestEffort(managed.client);
|
|
2837
2916
|
this.clients.delete(key);
|
|
2917
|
+
await this.tombstoneStop(key, managed.client);
|
|
2838
2918
|
managed = undefined;
|
|
2839
2919
|
}
|
|
2840
2920
|
}
|
|
@@ -2855,14 +2935,20 @@ class LspManager {
|
|
|
2855
2935
|
signal.throwIfAborted();
|
|
2856
2936
|
}
|
|
2857
2937
|
if (!managed.client.isAlive()) {
|
|
2858
|
-
|
|
2859
|
-
this.clients.
|
|
2938
|
+
this.recordDeadGeneration(key);
|
|
2939
|
+
if (this.clients.get(key) === managed) {
|
|
2940
|
+
this.clients.delete(key);
|
|
2941
|
+
}
|
|
2942
|
+
await this.tombstoneStop(key, managed.client);
|
|
2860
2943
|
return this.getClient(root, server, signal);
|
|
2861
2944
|
}
|
|
2945
|
+
this.markHealthyGeneration(key);
|
|
2862
2946
|
managed.refCount++;
|
|
2863
2947
|
managed.lastUsedAt = this.now();
|
|
2864
2948
|
return managed.client;
|
|
2865
2949
|
}
|
|
2950
|
+
this.evictForAdmission();
|
|
2951
|
+
this.ensureRespawnAllowed(key, root, server.id);
|
|
2866
2952
|
const client = this.clientFactory(root, server);
|
|
2867
2953
|
const initStartedAt = this.now();
|
|
2868
2954
|
const initPromise = (async () => {
|
|
@@ -2886,7 +2972,7 @@ class LspManager {
|
|
|
2886
2972
|
if (this.clients.get(key) === newManaged) {
|
|
2887
2973
|
this.clients.delete(key);
|
|
2888
2974
|
}
|
|
2889
|
-
await
|
|
2975
|
+
await this.tombstoneStop(key, client);
|
|
2890
2976
|
throw err;
|
|
2891
2977
|
}
|
|
2892
2978
|
newManaged.pendingWaiters--;
|
|
@@ -2897,6 +2983,15 @@ class LspManager {
|
|
|
2897
2983
|
await this.tryDeleteIfOrphaned(key, newManaged);
|
|
2898
2984
|
signal.throwIfAborted();
|
|
2899
2985
|
}
|
|
2986
|
+
if (!client.isAlive()) {
|
|
2987
|
+
this.recordDeadGeneration(key);
|
|
2988
|
+
if (this.clients.get(key) === newManaged) {
|
|
2989
|
+
this.clients.delete(key);
|
|
2990
|
+
}
|
|
2991
|
+
await this.tombstoneStop(key, client);
|
|
2992
|
+
return this.getClient(root, server, signal);
|
|
2993
|
+
}
|
|
2994
|
+
this.markHealthyGeneration(key);
|
|
2900
2995
|
newManaged.refCount++;
|
|
2901
2996
|
newManaged.lastUsedAt = this.now();
|
|
2902
2997
|
return client;
|
|
@@ -2917,14 +3012,20 @@ class LspManager {
|
|
|
2917
3012
|
if (client && managed.client !== client)
|
|
2918
3013
|
return;
|
|
2919
3014
|
this.clients.delete(key);
|
|
2920
|
-
|
|
3015
|
+
this.tombstoneStop(key, managed.client);
|
|
2921
3016
|
}
|
|
2922
3017
|
warmupClient(root, server) {
|
|
2923
3018
|
if (this.disposed)
|
|
2924
3019
|
return;
|
|
2925
3020
|
const key = this.getKey(root, server.id);
|
|
2926
|
-
if (this.clients.has(key))
|
|
3021
|
+
if (this.clients.has(key) || this.pendingStops.has(key))
|
|
3022
|
+
return;
|
|
3023
|
+
this.evictForAdmission();
|
|
3024
|
+
try {
|
|
3025
|
+
this.ensureRespawnAllowed(key, root, server.id);
|
|
3026
|
+
} catch {
|
|
2927
3027
|
return;
|
|
3028
|
+
}
|
|
2928
3029
|
const client = this.clientFactory(root, server);
|
|
2929
3030
|
const initStartedAt = this.now();
|
|
2930
3031
|
const initPromise = (async () => {
|
|
@@ -2950,7 +3051,7 @@ class LspManager {
|
|
|
2950
3051
|
if (this.clients.get(key) === managed) {
|
|
2951
3052
|
this.clients.delete(key);
|
|
2952
3053
|
}
|
|
2953
|
-
|
|
3054
|
+
this.tombstoneStop(key, client);
|
|
2954
3055
|
});
|
|
2955
3056
|
}
|
|
2956
3057
|
isServerInitializing(root, serverId) {
|
|
@@ -2994,8 +3095,11 @@ class LspManager {
|
|
|
2994
3095
|
for (const managed of this.clients.values()) {
|
|
2995
3096
|
stopPromises.push(stopClientBestEffort(managed.client));
|
|
2996
3097
|
}
|
|
3098
|
+
const tombstonedStops = [...this.pendingStops.values()];
|
|
2997
3099
|
this.clients.clear();
|
|
2998
|
-
|
|
3100
|
+
this.respawnBudgets.clear();
|
|
3101
|
+
await Promise.allSettled([...stopPromises, ...tombstonedStops]);
|
|
3102
|
+
this.pendingStops.clear();
|
|
2999
3103
|
}
|
|
3000
3104
|
}
|
|
3001
3105
|
var _defaultInstance = null;
|
|
@@ -3189,6 +3293,7 @@ async function runJsonRpcStdioServer(config) {
|
|
|
3189
3293
|
const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
|
|
3190
3294
|
isClosed = true;
|
|
3191
3295
|
config.onIdleTimeout?.();
|
|
3296
|
+
config.input.destroy();
|
|
3192
3297
|
});
|
|
3193
3298
|
const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
|
|
3194
3299
|
isClosed = true;
|
|
@@ -3285,7 +3390,11 @@ function createParentWatchdog(config, onDeadParent) {
|
|
|
3285
3390
|
const probeAlive = config.probeAlive ?? isProcessAlive;
|
|
3286
3391
|
let fired = false;
|
|
3287
3392
|
const timer = setInterval(() => {
|
|
3288
|
-
if (fired
|
|
3393
|
+
if (fired)
|
|
3394
|
+
return;
|
|
3395
|
+
const alive = probeAlive(parentPid);
|
|
3396
|
+
config.onPoll?.(alive);
|
|
3397
|
+
if (alive)
|
|
3289
3398
|
return;
|
|
3290
3399
|
fired = true;
|
|
3291
3400
|
onDeadParent(parentPid, pollIntervalMs);
|
|
@@ -3320,8 +3429,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
|
|
|
3320
3429
|
};
|
|
3321
3430
|
}
|
|
3322
3431
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
3323
|
-
import { existsSync as
|
|
3324
|
-
import { dirname as
|
|
3432
|
+
import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
|
|
3433
|
+
import { basename as basename3, dirname as dirname8, join as join5, resolve as resolve8 } from "node:path";
|
|
3325
3434
|
|
|
3326
3435
|
// ../lsp-core/src/request-context.ts
|
|
3327
3436
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -3330,18 +3439,17 @@ import { homedir } from "node:os";
|
|
|
3330
3439
|
import { basename as basename2, delimiter as delimiter2, dirname as dirname4, isAbsolute as isAbsolute2, join as join2, relative as relative4, resolve as resolve6 } from "node:path";
|
|
3331
3440
|
|
|
3332
3441
|
class LspRequestContextParseError extends Error {
|
|
3333
|
-
code;
|
|
3334
|
-
name = "LspRequestContextParseError";
|
|
3335
3442
|
constructor(code, message) {
|
|
3336
3443
|
super(message);
|
|
3337
3444
|
this.code = code;
|
|
3445
|
+
this.name = "LspRequestContextParseError";
|
|
3338
3446
|
}
|
|
3339
3447
|
}
|
|
3340
3448
|
|
|
3341
3449
|
class LspRequestContextUnavailableError extends Error {
|
|
3342
|
-
name = "LspRequestContextUnavailableError";
|
|
3343
3450
|
constructor() {
|
|
3344
3451
|
super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
|
|
3452
|
+
this.name = "LspRequestContextUnavailableError";
|
|
3345
3453
|
}
|
|
3346
3454
|
}
|
|
3347
3455
|
var storage = new AsyncLocalStorage;
|
|
@@ -3371,7 +3479,7 @@ function contextEnv(key) {
|
|
|
3371
3479
|
}
|
|
3372
3480
|
function createStandaloneMcpRequestContext(input = {}) {
|
|
3373
3481
|
const env = input.env ?? process.env;
|
|
3374
|
-
const cwd = canonicalCwd(input.cwd ?? process.cwd());
|
|
3482
|
+
const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
|
|
3375
3483
|
const home = input.homeDir ?? homedir();
|
|
3376
3484
|
const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
|
|
3377
3485
|
const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
|
|
@@ -3502,57 +3610,52 @@ function errorCode(error) {
|
|
|
3502
3610
|
return typeof code === "string" ? code : undefined;
|
|
3503
3611
|
}
|
|
3504
3612
|
|
|
3505
|
-
// ../lsp-core/src/lsp/
|
|
3506
|
-
import { existsSync as existsSync6,
|
|
3507
|
-
import { dirname as dirname5 } from "node:path";
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3613
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
3614
|
+
import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
|
|
3615
|
+
import { dirname as dirname5, join as join3 } from "node:path";
|
|
3616
|
+
|
|
3617
|
+
// ../lsp-core/src/lsp/workspace-markers.ts
|
|
3618
|
+
var GIT_WORKSPACE_MARKER = ".git";
|
|
3619
|
+
var PROJECT_WORKSPACE_MARKERS = [
|
|
3620
|
+
"package.json",
|
|
3621
|
+
"pyproject.toml",
|
|
3622
|
+
"Cargo.toml",
|
|
3623
|
+
"go.mod",
|
|
3624
|
+
"pom.xml",
|
|
3625
|
+
"build.gradle"
|
|
3626
|
+
];
|
|
3627
|
+
var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
|
|
3628
|
+
|
|
3629
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
3630
|
+
function findWorkspaceRootOutsideContext(directory) {
|
|
3631
|
+
const marked = nearestMarkedAncestor(directory);
|
|
3632
|
+
if (marked !== undefined)
|
|
3633
|
+
return marked;
|
|
3634
|
+
return realpathSync4(nearestExistingAncestor(directory));
|
|
3635
|
+
}
|
|
3636
|
+
function nearestMarkedAncestor(directory) {
|
|
3637
|
+
let current = directory;
|
|
3638
|
+
for (;; ) {
|
|
3639
|
+
if (existsSync6(current) && WORKSPACE_MARKERS.some((marker) => existsSync6(join3(current, marker)))) {
|
|
3640
|
+
return realpathSync4(current);
|
|
3641
|
+
}
|
|
3642
|
+
const parent = dirname5(current);
|
|
3643
|
+
if (parent === current)
|
|
3644
|
+
return;
|
|
3645
|
+
current = parent;
|
|
3520
3646
|
}
|
|
3521
3647
|
}
|
|
3522
|
-
function
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
}
|
|
3530
|
-
|
|
3531
|
-
return value === "declined" || value === "allowed";
|
|
3532
|
-
}
|
|
3533
|
-
function writeInstallDecisions(decisions) {
|
|
3534
|
-
const path = getInstallDecisionsPath();
|
|
3535
|
-
mkdirSync(dirname5(path), { recursive: true });
|
|
3536
|
-
const tmpPath = `${path}.tmp`;
|
|
3537
|
-
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
3538
|
-
`, "utf8");
|
|
3539
|
-
renameSync2(tmpPath, path);
|
|
3540
|
-
}
|
|
3541
|
-
function isInstallDecisions(value) {
|
|
3542
|
-
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
3543
|
-
}
|
|
3544
|
-
function isInstallDecisionRecord(value) {
|
|
3545
|
-
if (!isRecord5(value))
|
|
3546
|
-
return false;
|
|
3547
|
-
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
3548
|
-
}
|
|
3549
|
-
function isRecord5(value) {
|
|
3550
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3648
|
+
function nearestExistingAncestor(directory) {
|
|
3649
|
+
let current = directory;
|
|
3650
|
+
while (!existsSync6(current)) {
|
|
3651
|
+
const parent = dirname5(current);
|
|
3652
|
+
if (parent === current)
|
|
3653
|
+
return current;
|
|
3654
|
+
current = parent;
|
|
3655
|
+
}
|
|
3656
|
+
return current;
|
|
3551
3657
|
}
|
|
3552
3658
|
|
|
3553
|
-
// ../lsp-core/src/lsp/config-loader.ts
|
|
3554
|
-
import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
|
|
3555
|
-
|
|
3556
3659
|
// ../lsp-core/src/lsp/server-definitions.ts
|
|
3557
3660
|
var LSP_INSTALL_HINTS = {
|
|
3558
3661
|
typescript: "npm install -g typescript-language-server typescript",
|
|
@@ -3598,6 +3701,26 @@ var LSP_INSTALL_HINTS = {
|
|
|
3598
3701
|
julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
|
|
3599
3702
|
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"
|
|
3600
3703
|
};
|
|
3704
|
+
var LSP_LOCAL_INSTALL_HINTS = {
|
|
3705
|
+
typescript: "bun add -d typescript-language-server typescript",
|
|
3706
|
+
vue: "bun add -d @vue/language-server",
|
|
3707
|
+
eslint: "bun add -d vscode-langservers-extracted",
|
|
3708
|
+
oxlint: "bun add -d oxlint",
|
|
3709
|
+
biome: "bun add -d @biomejs/biome",
|
|
3710
|
+
svelte: "bun add -d svelte-language-server",
|
|
3711
|
+
astro: "bun add -d @astrojs/language-server",
|
|
3712
|
+
bash: "bun add -d bash-language-server",
|
|
3713
|
+
"bash-ls": "bun add -d bash-language-server",
|
|
3714
|
+
"yaml-ls": "bun add -d yaml-language-server",
|
|
3715
|
+
php: "bun add -d intelephense",
|
|
3716
|
+
prisma: "bun add -d prisma",
|
|
3717
|
+
dockerfile: "bun add -d dockerfile-language-server-nodejs",
|
|
3718
|
+
pyright: "uv add --dev pyright",
|
|
3719
|
+
basedpyright: "uv add --dev basedpyright",
|
|
3720
|
+
ruff: "uv add --dev ruff",
|
|
3721
|
+
ty: "uv add --dev ty",
|
|
3722
|
+
"ruby-lsp": "bundle add ruby-lsp --group development"
|
|
3723
|
+
};
|
|
3601
3724
|
var BUILTIN_SERVERS = {
|
|
3602
3725
|
typescript: {
|
|
3603
3726
|
command: ["typescript-language-server", "--stdio"],
|
|
@@ -3700,7 +3823,56 @@ var BUILTIN_SERVERS = {
|
|
|
3700
3823
|
}
|
|
3701
3824
|
};
|
|
3702
3825
|
|
|
3826
|
+
// ../lsp-core/src/lsp/server-install-state.ts
|
|
3827
|
+
import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
3828
|
+
import { dirname as dirname6 } from "node:path";
|
|
3829
|
+
function getInstallDecisionsPath() {
|
|
3830
|
+
return lspRequestContext().installDecisionsPath;
|
|
3831
|
+
}
|
|
3832
|
+
function loadInstallDecisions() {
|
|
3833
|
+
const path = getInstallDecisionsPath();
|
|
3834
|
+
if (!existsSync7(path))
|
|
3835
|
+
return {};
|
|
3836
|
+
try {
|
|
3837
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
3838
|
+
return isInstallDecisions(parsed) ? parsed : {};
|
|
3839
|
+
} catch {
|
|
3840
|
+
return {};
|
|
3841
|
+
}
|
|
3842
|
+
}
|
|
3843
|
+
function loadInstallDecision(serverId) {
|
|
3844
|
+
return loadInstallDecisions()[serverId];
|
|
3845
|
+
}
|
|
3846
|
+
function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
|
|
3847
|
+
const decisions = loadInstallDecisions();
|
|
3848
|
+
decisions[serverId] = { decision, decidedAt };
|
|
3849
|
+
writeInstallDecisions(decisions);
|
|
3850
|
+
}
|
|
3851
|
+
function isInstallDecision(value) {
|
|
3852
|
+
return value === "declined" || value === "allowed";
|
|
3853
|
+
}
|
|
3854
|
+
function writeInstallDecisions(decisions) {
|
|
3855
|
+
const path = getInstallDecisionsPath();
|
|
3856
|
+
mkdirSync(dirname6(path), { recursive: true });
|
|
3857
|
+
const tmpPath = `${path}.tmp`;
|
|
3858
|
+
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
3859
|
+
`, "utf8");
|
|
3860
|
+
renameSync2(tmpPath, path);
|
|
3861
|
+
}
|
|
3862
|
+
function isInstallDecisions(value) {
|
|
3863
|
+
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
3864
|
+
}
|
|
3865
|
+
function isInstallDecisionRecord(value) {
|
|
3866
|
+
if (!isRecord5(value))
|
|
3867
|
+
return false;
|
|
3868
|
+
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
3869
|
+
}
|
|
3870
|
+
function isRecord5(value) {
|
|
3871
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3872
|
+
}
|
|
3873
|
+
|
|
3703
3874
|
// ../lsp-core/src/lsp/config-loader.ts
|
|
3875
|
+
import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
|
|
3704
3876
|
function getProjectConfigPaths() {
|
|
3705
3877
|
return lspRequestContext().projectConfigPaths;
|
|
3706
3878
|
}
|
|
@@ -3708,7 +3880,7 @@ function getUserConfigPath() {
|
|
|
3708
3880
|
return lspRequestContext().userConfigPath;
|
|
3709
3881
|
}
|
|
3710
3882
|
function loadJsonFile(path) {
|
|
3711
|
-
if (!
|
|
3883
|
+
if (!existsSync8(path))
|
|
3712
3884
|
return null;
|
|
3713
3885
|
try {
|
|
3714
3886
|
const parsed = JSON.parse(readFileSync4(path, "utf-8"));
|
|
@@ -3896,54 +4068,155 @@ function getDisabledServerIds() {
|
|
|
3896
4068
|
}
|
|
3897
4069
|
|
|
3898
4070
|
// ../lsp-core/src/lsp/server-installation.ts
|
|
3899
|
-
import { existsSync as
|
|
3900
|
-
import { delimiter as delimiter3, join as
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
4071
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
4072
|
+
import { delimiter as delimiter3, dirname as dirname7, isAbsolute as isAbsolute3, join as join4, resolve as resolve7 } from "node:path";
|
|
4073
|
+
var LOCAL_BIN_RULES = [
|
|
4074
|
+
{
|
|
4075
|
+
markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
|
|
4076
|
+
binDirs: [join4("node_modules", ".bin")]
|
|
4077
|
+
},
|
|
4078
|
+
{
|
|
4079
|
+
markers: [
|
|
4080
|
+
"pyproject.toml",
|
|
4081
|
+
"ty.toml",
|
|
4082
|
+
"requirements.txt",
|
|
4083
|
+
"setup.py",
|
|
4084
|
+
"setup.cfg",
|
|
4085
|
+
"Pipfile",
|
|
4086
|
+
"pyrightconfig.json",
|
|
4087
|
+
"ruff.toml",
|
|
4088
|
+
".ruff.toml"
|
|
4089
|
+
],
|
|
4090
|
+
binDirs: [
|
|
4091
|
+
join4(".venv", "bin"),
|
|
4092
|
+
join4(".venv", "Scripts"),
|
|
4093
|
+
join4("venv", "bin"),
|
|
4094
|
+
join4("venv", "Scripts"),
|
|
4095
|
+
join4(".env", "bin"),
|
|
4096
|
+
join4(".env", "Scripts")
|
|
4097
|
+
]
|
|
4098
|
+
},
|
|
4099
|
+
{
|
|
4100
|
+
markers: ["Gemfile", "Gemfile.lock"],
|
|
4101
|
+
binDirs: [join4("vendor", "bundle", "bin"), "bin"]
|
|
4102
|
+
},
|
|
4103
|
+
{
|
|
4104
|
+
markers: ["go.mod", "go.sum", "go.work"],
|
|
4105
|
+
binDirs: ["bin"]
|
|
4106
|
+
}
|
|
4107
|
+
];
|
|
4108
|
+
var resolutionCache = new Map;
|
|
4109
|
+
var probeCount = 0;
|
|
4110
|
+
function probe(path) {
|
|
4111
|
+
probeCount += 1;
|
|
4112
|
+
return existsSync9(path);
|
|
4113
|
+
}
|
|
4114
|
+
function executableSuffixes(platform, pathExt) {
|
|
4115
|
+
if (platform !== "win32")
|
|
4116
|
+
return [""];
|
|
4117
|
+
const configured = pathExt ?? process.env["PATHEXT"] ?? "";
|
|
4118
|
+
const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
|
|
4119
|
+
return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
|
|
4120
|
+
}
|
|
4121
|
+
function probeWithSuffixes(directory, command, suffixes) {
|
|
4122
|
+
for (const suffix of suffixes) {
|
|
4123
|
+
const candidate = join4(directory, command + suffix);
|
|
4124
|
+
if (probe(candidate))
|
|
4125
|
+
return candidate;
|
|
3910
4126
|
}
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
4127
|
+
return null;
|
|
4128
|
+
}
|
|
4129
|
+
function resolveLocal(command, workingDirectory, suffixes, stopAt) {
|
|
4130
|
+
const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
|
|
4131
|
+
let current = resolve7(workingDirectory);
|
|
4132
|
+
while (true) {
|
|
4133
|
+
for (const rule of LOCAL_BIN_RULES) {
|
|
4134
|
+
if (!rule.markers.some((marker) => probe(join4(current, marker))))
|
|
4135
|
+
continue;
|
|
4136
|
+
for (const binDir of rule.binDirs) {
|
|
4137
|
+
const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
|
|
4138
|
+
if (found !== null)
|
|
4139
|
+
return found;
|
|
4140
|
+
}
|
|
3920
4141
|
}
|
|
4142
|
+
if (probe(join4(current, ".git")))
|
|
4143
|
+
return null;
|
|
4144
|
+
if (boundary !== undefined && current === boundary)
|
|
4145
|
+
return null;
|
|
4146
|
+
const parent = dirname7(current);
|
|
4147
|
+
if (parent === current)
|
|
4148
|
+
return null;
|
|
4149
|
+
current = parent;
|
|
3921
4150
|
}
|
|
3922
|
-
|
|
3923
|
-
|
|
4151
|
+
}
|
|
4152
|
+
function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
|
|
4153
|
+
let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
|
|
4154
|
+
if (platform === "win32" && !pathEnv) {
|
|
3924
4155
|
pathEnv = process.env["Path"] ?? "";
|
|
3925
4156
|
}
|
|
3926
|
-
const
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
}
|
|
4157
|
+
for (const entry of pathEnv.split(delimiter3)) {
|
|
4158
|
+
if (entry.length === 0)
|
|
4159
|
+
continue;
|
|
4160
|
+
const found = probeWithSuffixes(entry, command, suffixes);
|
|
4161
|
+
if (found !== null)
|
|
4162
|
+
return found;
|
|
3933
4163
|
}
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
4164
|
+
return null;
|
|
4165
|
+
}
|
|
4166
|
+
function resolveServerBinary(command, workingDirectory, options = {}) {
|
|
4167
|
+
if (command.length === 0)
|
|
4168
|
+
return null;
|
|
4169
|
+
const [cmd] = command;
|
|
4170
|
+
if (cmd === undefined || cmd.length === 0)
|
|
4171
|
+
return null;
|
|
4172
|
+
const platform = options.platform ?? process.platform;
|
|
4173
|
+
const suffixes = executableSuffixes(platform, options.pathExt);
|
|
4174
|
+
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
4175
|
+
const explicit = isAbsolute3(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
|
|
4176
|
+
return probe(explicit) ? explicit : null;
|
|
4177
|
+
}
|
|
4178
|
+
const cacheKey = JSON.stringify([
|
|
4179
|
+
workingDirectory ?? "",
|
|
4180
|
+
cmd,
|
|
4181
|
+
platform,
|
|
4182
|
+
options.stopAt ?? "",
|
|
4183
|
+
options.pathExt ?? "",
|
|
4184
|
+
options.pathEnv ?? process.env["PATH"] ?? ""
|
|
4185
|
+
]);
|
|
4186
|
+
const cached = resolutionCache.get(cacheKey);
|
|
4187
|
+
if (cached !== undefined)
|
|
4188
|
+
return cached;
|
|
4189
|
+
let resolved = null;
|
|
4190
|
+
if (workingDirectory !== undefined && workingDirectory.length > 0) {
|
|
4191
|
+
resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
|
|
4192
|
+
}
|
|
4193
|
+
resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
|
|
4194
|
+
if (resolved === null && cmd === "node")
|
|
4195
|
+
resolved = cmd;
|
|
4196
|
+
resolutionCache.set(cacheKey, resolved);
|
|
4197
|
+
return resolved;
|
|
4198
|
+
}
|
|
4199
|
+
function isServerInstalled(command, workingDirectory, options = {}) {
|
|
4200
|
+
if (command.length === 0)
|
|
4201
|
+
return false;
|
|
4202
|
+
return resolveServerBinary(command, workingDirectory, options) !== null;
|
|
3937
4203
|
}
|
|
3938
4204
|
|
|
3939
4205
|
// ../lsp-core/src/lsp/server-resolution.ts
|
|
4206
|
+
function withResolvedCommand(command, binaryPath) {
|
|
4207
|
+
return [binaryPath, ...command.slice(1)];
|
|
4208
|
+
}
|
|
3940
4209
|
function findServerForExtension(ext) {
|
|
3941
4210
|
const servers = getMergedServers();
|
|
4211
|
+
const workingDirectory = contextCwd();
|
|
3942
4212
|
for (const server2 of servers) {
|
|
3943
|
-
if (server2.extensions.includes(ext)
|
|
4213
|
+
if (!server2.extensions.includes(ext))
|
|
4214
|
+
continue;
|
|
4215
|
+
const binaryPath = resolveServerBinary(server2.command, workingDirectory);
|
|
4216
|
+
if (binaryPath !== null) {
|
|
3944
4217
|
const resolvedServer = {
|
|
3945
4218
|
id: server2.id,
|
|
3946
|
-
command: server2.command,
|
|
4219
|
+
command: withResolvedCommand(server2.command, binaryPath),
|
|
3947
4220
|
extensions: server2.extensions,
|
|
3948
4221
|
priority: server2.priority
|
|
3949
4222
|
};
|
|
@@ -3990,6 +4263,7 @@ function findServerForExtension(ext) {
|
|
|
3990
4263
|
function getAllServers() {
|
|
3991
4264
|
const servers = getMergedServers();
|
|
3992
4265
|
const disabled = getDisabledServerIds();
|
|
4266
|
+
const workingDirectory = contextCwd();
|
|
3993
4267
|
const result = [];
|
|
3994
4268
|
const seen = new Set;
|
|
3995
4269
|
for (const server2 of servers) {
|
|
@@ -3997,7 +4271,7 @@ function getAllServers() {
|
|
|
3997
4271
|
continue;
|
|
3998
4272
|
result.push({
|
|
3999
4273
|
id: server2.id,
|
|
4000
|
-
installed: isServerInstalled(server2.command),
|
|
4274
|
+
installed: isServerInstalled(server2.command, workingDirectory),
|
|
4001
4275
|
extensions: server2.extensions,
|
|
4002
4276
|
disabled: false,
|
|
4003
4277
|
source: server2.source,
|
|
@@ -4011,7 +4285,7 @@ function getAllServers() {
|
|
|
4011
4285
|
const builtin = BUILTIN_SERVERS[id];
|
|
4012
4286
|
result.push({
|
|
4013
4287
|
id,
|
|
4014
|
-
installed: builtin ? isServerInstalled(builtin.command) : false,
|
|
4288
|
+
installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
|
|
4015
4289
|
extensions: builtin?.extensions ?? [],
|
|
4016
4290
|
disabled: true,
|
|
4017
4291
|
source: "disabled",
|
|
@@ -4022,7 +4296,6 @@ function getAllServers() {
|
|
|
4022
4296
|
}
|
|
4023
4297
|
|
|
4024
4298
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
4025
|
-
var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
4026
4299
|
function isDirectoryPath(filePath) {
|
|
4027
4300
|
try {
|
|
4028
4301
|
return statSync3(filePath).isDirectory();
|
|
@@ -4031,32 +4304,90 @@ function isDirectoryPath(filePath) {
|
|
|
4031
4304
|
}
|
|
4032
4305
|
}
|
|
4033
4306
|
function findWorkspaceRoot(filePath) {
|
|
4034
|
-
const
|
|
4307
|
+
const cwd = contextCwd();
|
|
4308
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4035
4309
|
let dir = abs;
|
|
4036
4310
|
if (!isDirectoryPath(dir)) {
|
|
4037
|
-
dir =
|
|
4038
|
-
}
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4311
|
+
dir = dirname8(dir);
|
|
4312
|
+
}
|
|
4313
|
+
if (!isPathInside(cwd, abs))
|
|
4314
|
+
return findWorkspaceRootOutsideContext(dir);
|
|
4315
|
+
const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
|
|
4316
|
+
let nearestPackageRoot;
|
|
4317
|
+
while (isPathInside(cwd, dir)) {
|
|
4318
|
+
const canonicalDir = existingDirectoryInsideContext(dir, cwd);
|
|
4319
|
+
if (canonicalDir !== undefined) {
|
|
4320
|
+
if (existsSync10(join5(dir, GIT_WORKSPACE_MARKER))) {
|
|
4321
|
+
return canonicalDir;
|
|
4322
|
+
}
|
|
4323
|
+
if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
|
|
4324
|
+
nearestPackageRoot = canonicalDir;
|
|
4044
4325
|
}
|
|
4045
4326
|
}
|
|
4046
|
-
|
|
4047
|
-
|
|
4327
|
+
if (dir === cwd)
|
|
4328
|
+
break;
|
|
4329
|
+
dir = dirname8(dir);
|
|
4048
4330
|
}
|
|
4049
|
-
return
|
|
4331
|
+
return nearestPackageRoot ?? fallbackRoot;
|
|
4332
|
+
}
|
|
4333
|
+
function hasProjectWorkspaceMarker(directory) {
|
|
4334
|
+
return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync10(join5(directory, marker)));
|
|
4335
|
+
}
|
|
4336
|
+
function resolveReadablePathInsideContext(filePath) {
|
|
4337
|
+
const cwd = contextCwd();
|
|
4338
|
+
const abs = resolve8(cwd, filePath);
|
|
4339
|
+
if (isPathInside(cwd, abs))
|
|
4340
|
+
return abs;
|
|
4341
|
+
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
4342
|
+
if (rebased !== undefined)
|
|
4343
|
+
return rebased;
|
|
4344
|
+
return canonicalizeExistingOrNearestAncestor(abs);
|
|
4050
4345
|
}
|
|
4051
4346
|
function resolvePathInsideContext(filePath) {
|
|
4052
4347
|
const cwd = contextCwd();
|
|
4053
|
-
const abs =
|
|
4348
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4054
4349
|
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
4055
4350
|
if (!isPathInside(cwd, canonical)) {
|
|
4056
4351
|
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4057
4352
|
}
|
|
4058
4353
|
return canonical;
|
|
4059
4354
|
}
|
|
4355
|
+
function rebaseThroughCanonicalAncestor(path, cwd) {
|
|
4356
|
+
let current = path;
|
|
4357
|
+
const suffix = [];
|
|
4358
|
+
while (true) {
|
|
4359
|
+
if (existsSync10(current)) {
|
|
4360
|
+
const canonical = realpathSync5(current);
|
|
4361
|
+
if (isPathInside(cwd, canonical))
|
|
4362
|
+
return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
|
|
4363
|
+
}
|
|
4364
|
+
const parent = dirname8(current);
|
|
4365
|
+
if (parent === current)
|
|
4366
|
+
return;
|
|
4367
|
+
suffix.unshift(basename3(current));
|
|
4368
|
+
current = parent;
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
function existingDirectoryInsideContext(directory, cwd) {
|
|
4372
|
+
if (!existsSync10(directory))
|
|
4373
|
+
return;
|
|
4374
|
+
const canonical = realpathSync5(directory);
|
|
4375
|
+
if (!statSync3(canonical).isDirectory())
|
|
4376
|
+
return;
|
|
4377
|
+
return isPathInside(cwd, canonical) ? canonical : undefined;
|
|
4378
|
+
}
|
|
4379
|
+
function nearestExistingDirectoryInsideContext(directory, cwd) {
|
|
4380
|
+
let current = directory;
|
|
4381
|
+
while (isPathInside(cwd, current)) {
|
|
4382
|
+
const canonical = existingDirectoryInsideContext(current, cwd);
|
|
4383
|
+
if (canonical !== undefined)
|
|
4384
|
+
return canonical;
|
|
4385
|
+
if (current === cwd)
|
|
4386
|
+
return;
|
|
4387
|
+
current = dirname8(current);
|
|
4388
|
+
}
|
|
4389
|
+
return;
|
|
4390
|
+
}
|
|
4060
4391
|
function formatServerLookupError(result) {
|
|
4061
4392
|
if (result.status === "not_installed") {
|
|
4062
4393
|
return formatNotInstalled(result);
|
|
@@ -4080,6 +4411,19 @@ function formatServerLookupError(result) {
|
|
|
4080
4411
|
].join(`
|
|
4081
4412
|
`);
|
|
4082
4413
|
}
|
|
4414
|
+
function formatInstallOptions(serverId, installHint) {
|
|
4415
|
+
const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
|
|
4416
|
+
if (localHint === undefined) {
|
|
4417
|
+
return ["To install, run:", ` ${installHint}`];
|
|
4418
|
+
}
|
|
4419
|
+
return [
|
|
4420
|
+
"To install in THIS repository (preferred — no global install needed):",
|
|
4421
|
+
` ${localHint}`,
|
|
4422
|
+
"",
|
|
4423
|
+
"Or install it globally:",
|
|
4424
|
+
` ${installHint}`
|
|
4425
|
+
];
|
|
4426
|
+
}
|
|
4083
4427
|
function formatNotInstalled(result) {
|
|
4084
4428
|
const { server: server2, installHint } = result;
|
|
4085
4429
|
const extensions = server2.extensions.join(", ");
|
|
@@ -4094,19 +4438,19 @@ function formatNotInstalled(result) {
|
|
|
4094
4438
|
`Command not found: ${server2.command[0]}`,
|
|
4095
4439
|
""
|
|
4096
4440
|
];
|
|
4441
|
+
const installOptions = formatInstallOptions(server2.id, installHint);
|
|
4097
4442
|
if (decision === "allowed") {
|
|
4098
4443
|
return [
|
|
4099
4444
|
...header,
|
|
4100
4445
|
"The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
|
|
4101
|
-
|
|
4446
|
+
...installOptions.slice(1)
|
|
4102
4447
|
].join(`
|
|
4103
4448
|
`);
|
|
4104
4449
|
}
|
|
4105
4450
|
if (!context.capabilities.installDecisionTool) {
|
|
4106
4451
|
return [
|
|
4107
4452
|
...header,
|
|
4108
|
-
|
|
4109
|
-
` ${installHint}`,
|
|
4453
|
+
...installOptions,
|
|
4110
4454
|
"",
|
|
4111
4455
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4112
4456
|
"Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
|
|
@@ -4115,8 +4459,7 @@ function formatNotInstalled(result) {
|
|
|
4115
4459
|
}
|
|
4116
4460
|
return [
|
|
4117
4461
|
...header,
|
|
4118
|
-
|
|
4119
|
-
` ${installHint}`,
|
|
4462
|
+
...installOptions,
|
|
4120
4463
|
"",
|
|
4121
4464
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4122
4465
|
"- If the user agrees: run the install command above, then retry this tool.",
|
|
@@ -4127,7 +4470,7 @@ function formatNotInstalled(result) {
|
|
|
4127
4470
|
].join(`
|
|
4128
4471
|
`);
|
|
4129
4472
|
}
|
|
4130
|
-
var
|
|
4473
|
+
var READ_ONLY_TOOLS = new Set([
|
|
4131
4474
|
"diagnostics",
|
|
4132
4475
|
"definition",
|
|
4133
4476
|
"references",
|
|
@@ -4136,7 +4479,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
|
|
|
4136
4479
|
"prepareRename"
|
|
4137
4480
|
]);
|
|
4138
4481
|
async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
4139
|
-
const absPath = resolvePathInsideContext(filePath);
|
|
4482
|
+
const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
|
|
4140
4483
|
if (isDirectoryPath(absPath)) {
|
|
4141
4484
|
throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
|
|
4142
4485
|
}
|
|
@@ -4151,9 +4494,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4151
4494
|
const acquireAndCall = async (allowRetry) => {
|
|
4152
4495
|
const client = await manager2.getClient(root, server2, options.signal);
|
|
4153
4496
|
try {
|
|
4154
|
-
return await fn(client, root);
|
|
4497
|
+
return await fn(client, root, absPath);
|
|
4155
4498
|
} catch (err) {
|
|
4156
|
-
if (allowRetry &&
|
|
4499
|
+
if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
|
|
4157
4500
|
manager2.invalidateClient(root, server2.id, client);
|
|
4158
4501
|
return acquireAndCall(false);
|
|
4159
4502
|
}
|
|
@@ -4171,8 +4514,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4171
4514
|
}
|
|
4172
4515
|
|
|
4173
4516
|
// ../lsp-core/src/lsp/directory-diagnostics.ts
|
|
4174
|
-
import { existsSync as
|
|
4175
|
-
import { join as
|
|
4517
|
+
import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
|
|
4518
|
+
import { join as join6, resolve as resolve9 } from "node:path";
|
|
4176
4519
|
|
|
4177
4520
|
// ../lsp-core/src/lsp/formatters.ts
|
|
4178
4521
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -4302,7 +4645,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
|
|
|
4302
4645
|
for (const entry of entries) {
|
|
4303
4646
|
if (files.length >= maxFiles)
|
|
4304
4647
|
return;
|
|
4305
|
-
const fullPath =
|
|
4648
|
+
const fullPath = join6(currentDir, entry);
|
|
4306
4649
|
let stat;
|
|
4307
4650
|
try {
|
|
4308
4651
|
stat = lstatSync4(fullPath);
|
|
@@ -4327,8 +4670,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4327
4670
|
if (!extension.startsWith(".")) {
|
|
4328
4671
|
throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
|
|
4329
4672
|
}
|
|
4330
|
-
const absDir =
|
|
4331
|
-
if (!
|
|
4673
|
+
const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
|
|
4674
|
+
if (!existsSync11(absDir)) {
|
|
4332
4675
|
throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
|
|
4333
4676
|
}
|
|
4334
4677
|
const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
|
|
@@ -4415,7 +4758,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4415
4758
|
|
|
4416
4759
|
// ../lsp-core/src/lsp/infer-extension.ts
|
|
4417
4760
|
import { lstatSync as lstatSync5, readdirSync as readdirSync4 } from "node:fs";
|
|
4418
|
-
import { join as
|
|
4761
|
+
import { join as join7 } from "node:path";
|
|
4419
4762
|
var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
|
|
4420
4763
|
var MAX_SCAN_ENTRIES = 500;
|
|
4421
4764
|
function inferExtensionFromDirectory(directory) {
|
|
@@ -4433,7 +4776,7 @@ function inferExtensionFromDirectory(directory) {
|
|
|
4433
4776
|
for (const entry of entries) {
|
|
4434
4777
|
if (scanned >= MAX_SCAN_ENTRIES)
|
|
4435
4778
|
return;
|
|
4436
|
-
const fullPath =
|
|
4779
|
+
const fullPath = join7(dir, entry);
|
|
4437
4780
|
let stat;
|
|
4438
4781
|
try {
|
|
4439
4782
|
stat = lstatSync5(fullPath);
|
|
@@ -4608,7 +4951,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4608
4951
|
const filePath = requireString(params, "filePath");
|
|
4609
4952
|
const severity = severityFilter(params);
|
|
4610
4953
|
try {
|
|
4611
|
-
const absPath =
|
|
4954
|
+
const absPath = resolveReadablePathInsideContext(filePath);
|
|
4612
4955
|
if (isDirectoryPath(absPath)) {
|
|
4613
4956
|
const extension = inferExtensionFromDirectory(absPath);
|
|
4614
4957
|
if (!extension) {
|
|
@@ -4637,7 +4980,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4637
4980
|
};
|
|
4638
4981
|
return text(output2.output, details2);
|
|
4639
4982
|
}
|
|
4640
|
-
const result = await withLspClient(filePath, async (client) => client.diagnostics(
|
|
4983
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
|
|
4641
4984
|
if (result.transientError) {
|
|
4642
4985
|
const message = result.transientError.message;
|
|
4643
4986
|
const details2 = {
|
|
@@ -4684,6 +5027,96 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4684
5027
|
throw error;
|
|
4685
5028
|
}
|
|
4686
5029
|
}
|
|
5030
|
+
// ../lsp-core/src/lsp/format-document.ts
|
|
5031
|
+
import { readFileSync as readFileSync5, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
5032
|
+
var DEFAULT_FORMATTING_OPTIONS = {
|
|
5033
|
+
tabSize: 4,
|
|
5034
|
+
insertSpaces: false,
|
|
5035
|
+
trimTrailingWhitespace: true,
|
|
5036
|
+
insertFinalNewline: true,
|
|
5037
|
+
trimFinalNewlines: true
|
|
5038
|
+
};
|
|
5039
|
+
var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
|
|
5040
|
+
async function formatDocumentWithClient(client, filePath, options = {}) {
|
|
5041
|
+
const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
|
|
5042
|
+
if (edits === null)
|
|
5043
|
+
return { status: "unavailable", reason: "capability_not_advertised" };
|
|
5044
|
+
if (edits.length === 0)
|
|
5045
|
+
return UNCHANGED;
|
|
5046
|
+
const before = readFileSync5(filePath, "utf-8");
|
|
5047
|
+
const normalized = normalizeTextEdits(before, edits, 0);
|
|
5048
|
+
if (normalized.text === before)
|
|
5049
|
+
return UNCHANGED;
|
|
5050
|
+
writeAtomically(filePath, normalized.text);
|
|
5051
|
+
await client.openFile(filePath);
|
|
5052
|
+
return {
|
|
5053
|
+
status: "formatted",
|
|
5054
|
+
...lineDelta(normalized.edits)
|
|
5055
|
+
};
|
|
5056
|
+
}
|
|
5057
|
+
function lineDelta(edits) {
|
|
5058
|
+
let linesAdded = 0;
|
|
5059
|
+
let linesRemoved = 0;
|
|
5060
|
+
for (const edit of edits) {
|
|
5061
|
+
linesRemoved += edit.range.end.line - edit.range.start.line + 1;
|
|
5062
|
+
linesAdded += edit.newText.split(`
|
|
5063
|
+
`).length;
|
|
5064
|
+
}
|
|
5065
|
+
return { linesAdded, linesRemoved };
|
|
5066
|
+
}
|
|
5067
|
+
function writeAtomically(filePath, content) {
|
|
5068
|
+
const tempPath = `${filePath}.omo-format.tmp`;
|
|
5069
|
+
writeFileSync3(tempPath, content, "utf-8");
|
|
5070
|
+
try {
|
|
5071
|
+
renameSync3(tempPath, filePath);
|
|
5072
|
+
} catch (error) {
|
|
5073
|
+
try {
|
|
5074
|
+
unlinkSync(tempPath);
|
|
5075
|
+
} catch {}
|
|
5076
|
+
throw error;
|
|
5077
|
+
}
|
|
5078
|
+
}
|
|
5079
|
+
|
|
5080
|
+
// ../lsp-core/src/tools/format.ts
|
|
5081
|
+
async function executeLspFormat(params, signal) {
|
|
5082
|
+
const filePath = requireString(params, "filePath");
|
|
5083
|
+
try {
|
|
5084
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
|
|
5085
|
+
return text(describeResult(filePath, result), formatDetails(filePath, result));
|
|
5086
|
+
} catch (error) {
|
|
5087
|
+
const missingDependency = missingDependencyResult(error, {
|
|
5088
|
+
filePath,
|
|
5089
|
+
status: "unavailable",
|
|
5090
|
+
reason: "server_unavailable",
|
|
5091
|
+
linesAdded: 0,
|
|
5092
|
+
linesRemoved: 0
|
|
5093
|
+
});
|
|
5094
|
+
if (missingDependency)
|
|
5095
|
+
return missingDependency;
|
|
5096
|
+
throw error;
|
|
5097
|
+
}
|
|
5098
|
+
}
|
|
5099
|
+
function formatDetails(filePath, result) {
|
|
5100
|
+
if (result.status === "unavailable") {
|
|
5101
|
+
return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
|
|
5102
|
+
}
|
|
5103
|
+
return {
|
|
5104
|
+
filePath,
|
|
5105
|
+
status: result.status,
|
|
5106
|
+
linesAdded: result.linesAdded,
|
|
5107
|
+
linesRemoved: result.linesRemoved
|
|
5108
|
+
};
|
|
5109
|
+
}
|
|
5110
|
+
function describeResult(filePath, result) {
|
|
5111
|
+
if (result.status === "unavailable") {
|
|
5112
|
+
return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
|
|
5113
|
+
}
|
|
5114
|
+
if (result.status === "unchanged") {
|
|
5115
|
+
return `Already formatted: ${filePath}`;
|
|
5116
|
+
}
|
|
5117
|
+
return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
|
|
5118
|
+
}
|
|
5119
|
+
|
|
4687
5120
|
// ../lsp-core/src/tools/install-decision.ts
|
|
4688
5121
|
async function executeLspInstallDecision(params) {
|
|
4689
5122
|
const serverId = requireString(params, "server_id");
|
|
@@ -4712,7 +5145,7 @@ async function executeLspGotoDefinition(params, signal) {
|
|
|
4712
5145
|
const line = requireNumber(params, "line");
|
|
4713
5146
|
const character = requireNumber(params, "character");
|
|
4714
5147
|
try {
|
|
4715
|
-
const result = await withLspClient(filePath, async (client) => client.definition(
|
|
5148
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
|
|
4716
5149
|
const locations = !result ? [] : Array.isArray(result) ? result : [result];
|
|
4717
5150
|
const details = { filePath, line, character, locations };
|
|
4718
5151
|
if (locations.length === 0)
|
|
@@ -4737,7 +5170,7 @@ async function executeLspFindReferences(params, signal) {
|
|
|
4737
5170
|
const character = requireNumber(params, "character");
|
|
4738
5171
|
const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
|
|
4739
5172
|
try {
|
|
4740
|
-
const result = await withLspClient(filePath, async (client) => client.references(
|
|
5173
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
|
|
4741
5174
|
const references = Array.isArray(result) ? result : [];
|
|
4742
5175
|
const total = references.length;
|
|
4743
5176
|
const truncated = total > DEFAULT_MAX_REFERENCES;
|
|
@@ -4779,7 +5212,7 @@ async function executeLspPrepareRename(params, signal) {
|
|
|
4779
5212
|
const line = requireNumber(params, "line");
|
|
4780
5213
|
const character = requireNumber(params, "character");
|
|
4781
5214
|
try {
|
|
4782
|
-
const result = await withLspClient(filePath, async (client) => client.prepareRename(
|
|
5215
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
|
|
4783
5216
|
const details = { filePath, line, character, result };
|
|
4784
5217
|
return text(formatPrepareRenameResult(result), details);
|
|
4785
5218
|
} catch (error) {
|
|
@@ -4800,7 +5233,7 @@ async function executeLspRename(params, signal) {
|
|
|
4800
5233
|
const character = requireNumber(params, "character");
|
|
4801
5234
|
const newName = requireString(params, "newName");
|
|
4802
5235
|
try {
|
|
4803
|
-
const result = await withLspClient(filePath, async (client) => client.rename(
|
|
5236
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
|
|
4804
5237
|
const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
|
|
4805
5238
|
return text(formatApplyResult(result.apply), details, !result.apply.success);
|
|
4806
5239
|
} catch (error) {
|
|
@@ -4880,7 +5313,7 @@ async function executeLspSymbols(params, signal) {
|
|
|
4880
5313
|
const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
|
|
4881
5314
|
return formatSymbolsResult(filePath, scope, symbols2, limit, query);
|
|
4882
5315
|
}
|
|
4883
|
-
const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(
|
|
5316
|
+
const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
|
|
4884
5317
|
return formatSymbolsResult(filePath, scope, symbols, limit);
|
|
4885
5318
|
} catch (error) {
|
|
4886
5319
|
const query = optionalString(params, "query");
|
|
@@ -5016,6 +5449,16 @@ var LSP_MCP_TOOLS = [
|
|
|
5016
5449
|
}, ["filePath", "line", "character", "newName"]),
|
|
5017
5450
|
execute: executeLspRename
|
|
5018
5451
|
},
|
|
5452
|
+
{
|
|
5453
|
+
name: "format",
|
|
5454
|
+
aliases: ["lsp_format"],
|
|
5455
|
+
title: "LSP Format",
|
|
5456
|
+
description: "Format a source file with its language server and write the returned edits to disk.",
|
|
5457
|
+
inputSchema: objectSchema({
|
|
5458
|
+
filePath: { type: "string", description: "Source file path to format." }
|
|
5459
|
+
}, ["filePath"]),
|
|
5460
|
+
execute: executeLspFormat
|
|
5461
|
+
},
|
|
5019
5462
|
{
|
|
5020
5463
|
name: "install_decision",
|
|
5021
5464
|
aliases: ["lsp_install_decision"],
|