oh-my-opencode 5.0.0-beta.5 → 5.0.0-beta.51
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/codex-qa/scripts/lsp-e2e.sh +1 -3
- package/.agents/skills/opencode-qa/scripts/lsp-e2e.sh +1 -1
- package/.agents/skills/pre-publish-review/SKILL.md +9 -12
- 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/tech-debt-audit/SKILL.md +6 -76
- package/.agents/skills/work-with-pr/SKILL.md +37 -23
- package/.opencode/command/publish.md +44 -16
- package/.opencode/skills/pre-publish-review/SKILL.md +9 -12
- package/.opencode/skills/work-with-pr/SKILL.md +37 -23
- package/README.ja.md +58 -46
- package/README.ko.md +60 -48
- package/README.md +58 -58
- package/README.ru.md +55 -46
- package/README.zh-cn.md +54 -46
- package/THIRD-PARTY-NOTICES.md +27 -99
- package/dist/agents/atlas/agent.d.ts +0 -1
- package/dist/agents/gpt-prompt-identity.d.ts +1 -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 +4 -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 +51551 -59608
- 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 +51569 -59603
- package/dist/config/index.d.ts +1 -1
- 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 -2
- package/dist/config/schema/oh-my-opencode-config.d.ts +5 -11
- package/dist/config/schema/ulw-execute.d.ts +5 -0
- package/dist/config/schema.d.ts +0 -1
- package/dist/config/validate.d.ts +2 -0
- package/dist/create-hooks.d.ts +3 -2
- package/dist/features/background-agent/compaction-aware-message-resolver.d.ts +1 -0
- package/dist/features/background-agent/constants.d.ts +0 -7
- package/dist/features/background-agent/error-classifier.d.ts +1 -0
- 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/parent-wake-notifier-types.d.ts +1 -1
- package/dist/features/background-agent/parent-wake-prompt-dispatch.d.ts +1 -1
- package/dist/features/background-agent/parent-wake-session-inspector.d.ts +1 -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/monitor/manager-internals.d.ts +1 -1
- package/dist/features/monitor/output-injector-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 +17 -0
- package/dist/features/team-mode/tools/messaging-live-delivery-recipient.d.ts +3 -0
- package/dist/features/team-mode/tools/messaging-runtime.d.ts +7 -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/anthropic-context-window-limit-recovery/tool-result-storage.d.ts +11 -0
- 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/compaction-context-injector/validated-model.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 -2
- 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 +28955 -25346
- package/dist/mcp/index.d.ts +0 -4
- package/dist/mcp/types.d.ts +0 -1
- package/dist/oh-my-opencode.schema.json +21 -47
- 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 -2
- package/dist/plugin/hooks/create-session-hooks.d.ts +2 -3
- 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/compaction-agent-config-checkpoint.d.ts +1 -0
- 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/omo-process-sweep.d.ts +2 -4
- 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/ast-grep/SKILL.md +1 -1
- 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 +3 -1
- 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 +12 -8
- 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/git-master/SKILL.md +1 -1
- package/dist/skills/init-deep/SKILL.md +14 -14
- package/dist/skills/lsp-setup/SKILL.md +1 -1
- package/dist/skills/programming/SKILL.md +1 -1
- package/dist/skills/refactor/SKILL.md +1 -1
- package/dist/skills/remove-ai-slops/SKILL.md +1 -1
- package/dist/skills/review-work/SKILL.md +100 -418
- package/dist/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
- package/dist/skills/ultimate-browsing/SKILL.md +26 -9
- package/dist/skills/ultimate-browsing/engine/AGENTS.md +110 -0
- package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/dist/skills/ultimate-browsing/references/chrome-stealth.md +23 -18
- package/dist/skills/ultimate-browsing/references/insane-search/README.md +9 -2
- package/dist/skills/{start-work → ulw-execute}/SKILL.md +17 -16
- package/dist/skills/ulw-plan/SKILL.md +7 -8
- 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 +8 -3
- package/dist/skills/visual-qa/AGENTS.md +58 -0
- package/dist/skills/visual-qa/SKILL.md +4 -3
- package/dist/tools/delegate-task/builtin-categories.d.ts +3 -1
- package/dist/tools/delegate-task/builtin-category-definition.d.ts +2 -1
- package/dist/tools/delegate-task/constants.d.ts +2 -2
- package/dist/tools/delegate-task/openai-categories.d.ts +7 -2
- 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/tools/session-manager/directory-filter.d.ts +2 -0
- package/dist/tui.d.ts +12 -0
- package/dist/tui.js +37066 -46704
- package/package.json +47 -41
- 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 +57 -48
- package/packages/lsp-core/src/lsp/client-diagnostics-pull-timeout.test.ts +64 -0
- 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 +32 -3
- 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/controlled-clock-test-support.ts +61 -0
- package/packages/lsp-core/src/lsp/errors.ts +15 -0
- package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +10 -3
- 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/json-rpc-connection.ts +11 -6
- 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/timer-provider.ts +13 -0
- package/packages/lsp-core/src/lsp/transport-request-timeout.test.ts +73 -0
- package/packages/lsp-core/src/lsp/transport.ts +16 -2
- package/packages/lsp-core/src/lsp/types.ts +8 -0
- package/packages/lsp-core/src/lsp/workspace-apply-edit-test-support.ts +29 -1
- package/packages/lsp-core/src/lsp/workspace-document-state.test.ts +84 -1
- package/packages/lsp-core/src/lsp/workspace-document-state.ts +30 -11
- 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/parameters.test.ts +51 -0
- 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 +961 -483
- package/packages/lsp-daemon/dist/client.d.ts +10 -0
- package/packages/lsp-daemon/dist/client.js +976 -495
- 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.d.ts +6 -1
- package/packages/lsp-daemon/dist/ensure-daemon.js +10 -2
- package/packages/lsp-daemon/dist/index.js +881 -405
- 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 +820 -345
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +272 -138
- package/packages/lsp-tools-mcp/dist/mcp.js +845 -372
- package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
- package/packages/lsp-tools-mcp/dist/tools.js +775 -306
- package/packages/lsp-tools-mcp/package.json +1 -1
- package/packages/omo-codex/THIRD-PARTY-NOTICES.md +4 -21
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +4 -6
- package/packages/omo-codex/plugin/.mcp.json +0 -6
- package/packages/omo-codex/plugin/AGENTS.md +47 -0
- package/packages/omo-codex/plugin/README.md +6 -2
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +197 -148
- 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/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/AGENTS.md +2 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/directive.md +2 -0
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +36 -29
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +32 -26
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/types.d.ts +3 -0
- 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 +32 -28
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/types.ts +3 -0
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/cli.test.ts +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +137 -28
- package/packages/omo-codex/plugin/components/lcx/skills/lcx-doctor/SKILL.md +4 -2
- 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 +999 -544
- 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/README.md +2 -0
- package/packages/omo-codex/plugin/components/rules/biome.json +2 -2
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-6.md +123 -0
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +91 -68
- 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 +15 -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 +38 -3
- 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 +29 -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 +4 -10
- 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 +2435 -700
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2439 -705
- 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 +10 -4
- package/packages/omo-codex/plugin/components/ultrawork/README.md +2 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/explorer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-low.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/metis.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +490 -4
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -6
- package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +30 -14
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -7
- 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/src/directive-content.ts +4 -0
- package/packages/omo-codex/plugin/components/ultrawork/src/directive.ts +5 -2
- 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/directive-source.test.ts +14 -8
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +12 -1
- 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 +4 -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 +6 -6
- 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 +10 -10
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +16 -16
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +16 -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 +4 -4
- 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}/src/types.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 +4 -11
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +24 -22
- package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +19 -0
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +12 -1
- package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +26 -13
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.d.ts +12 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +45 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +15 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.d.ts +8 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +113 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +40 -39
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +21 -8
- 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 +12 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +1270 -429
- 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 +28 -8
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +13 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +15 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +17 -9
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +13 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +34 -4
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +14 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +29 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.d.ts +12 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +104 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.d.ts +13 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +65 -9
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +5 -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 +72 -117
- package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.d.ts +6 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +195 -29
- package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.d.ts +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.js +227 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +33 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +20 -6
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +19 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +75 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +17 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +6 -6
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +6 -4
- 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 +32 -8
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +81 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +31 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +128 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +38 -71
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +24 -8
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +14 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +8 -6
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +35 -7
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +26 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +19 -9
- package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +25 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +39 -4
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +38 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +11 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +123 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +71 -15
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +6 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +92 -136
- package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +205 -28
- package/packages/omo-codex/plugin/components/ulw-loop/src/state-lock.ts +239 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +36 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +19 -6
- package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +107 -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 +132 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +147 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint.test.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-commands.test.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-complete-goals.test.ts +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +35 -8
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +38 -4
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-json-errors.test.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-scope-required.test.ts +144 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-status-next-actions.test.ts +185 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +8 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +37 -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/cli-session.ts +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +9 -4
- package/packages/omo-codex/plugin/components/ulw-loop/test/guided-recovery.test.ts +105 -0
- 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/plan-io-cross-process.test.ts +106 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +36 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate-basics.test.ts +258 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-cap-and-dedupe.test.ts +22 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-fields-messages.test.ts +98 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-lazycodex-surface.test.ts +93 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-poisoning-cascades.test.ts +97 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +51 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-senpi-surface.test.ts +131 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-single-report.test.ts +241 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +58 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +444 -7
- package/packages/omo-codex/plugin/components/ulw-loop/test/state-lock.test.ts +218 -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 +13 -8
- 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-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/post-tool-use-recording-spawn-admission.json +18 -0
- 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-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-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 +16 -7
- package/packages/omo-codex/plugin/package-lock.json +676 -524
- package/packages/omo-codex/plugin/package.json +2 -3
- package/packages/omo-codex/plugin/scripts/AGENTS.md +39 -0
- package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -2
- package/packages/omo-codex/plugin/scripts/auto-update.mjs +0 -9
- package/packages/omo-codex/plugin/scripts/canonical-ultrawork-directive.mjs +17 -0
- package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +0 -1
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +16 -7
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +8 -4
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +19 -90
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/toml-section-editor.mjs +1 -1
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +94 -55
- package/packages/omo-codex/plugin/shared/package.json +3 -4
- package/packages/omo-codex/plugin/shared/src/config-loader.ts +2 -102
- package/packages/omo-codex/plugin/shared/src/config-migration.ts +0 -1
- package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +41 -130
- package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +51 -0
- package/packages/omo-codex/plugin/skills/ast-grep/SKILL.md +1 -1
- 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 +3 -1
- 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 +12 -8
- 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/git-master/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +18 -16
- package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +4 -2
- package/packages/omo-codex/plugin/skills/lsp-setup/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/programming/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/refactor/SKILL.md +5 -3
- package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +5 -3
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +114 -422
- package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +26 -9
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +110 -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 +23 -18
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -2
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +26 -13
- package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +26 -28
- package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +30 -4
- 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 +32 -8
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -7
- 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 +12 -5
- package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +8 -5
- 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 +16 -51
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +2 -3
- package/packages/omo-codex/plugin/test/aggregate-mcp.test.mjs +2 -7
- package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +14 -4
- 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 +4 -29
- package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +0 -31
- package/packages/omo-codex/plugin/test/canonical-ultrawork-directive.test.mjs +53 -0
- 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 -51
- package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +88 -2
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +5 -6
- package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
- package/packages/omo-codex/plugin/test/mcp-research-servers.test.mjs +1 -3
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +35 -35
- package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
- package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +107 -15
- package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +168 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +54 -24
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +18 -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 +5 -5
- 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/check-model-catalog-parity.mjs +42 -0
- package/packages/omo-codex/scripts/install-cache-copy.test.mjs +27 -1
- package/packages/omo-codex/scripts/install-config-autonomous-features.test.mjs +1 -1
- package/packages/omo-codex/scripts/install-config-autonomous.test.mjs +2 -1
- package/packages/omo-codex/scripts/install-config-git-bash.test.mjs +0 -23
- package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +5 -5
- package/packages/omo-codex/scripts/install-config.test.mjs +15 -17
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +3035 -1395
- package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +3 -4
- package/packages/omo-codex/scripts/install-git-bash-mcp-env.test.mjs +1 -25
- package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
- package/packages/omo-codex/scripts/install-mcp-runtime.test.mjs +0 -36
- package/packages/omo-codex/scripts/install-packaged-local.test.mjs +1 -6
- package/packages/{omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md → prompts-core/prompts/ultrawork/codex.md} +26 -20
- package/packages/shared-skills/package.json +7 -1
- package/packages/shared-skills/skill-source-filter.d.ts +16 -0
- package/packages/shared-skills/skill-source-filter.mjs +44 -0
- package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
- package/packages/shared-skills/skills/ast-grep/SKILL.md +1 -1
- 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 +3 -1
- 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 +12 -8
- 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/git-master/SKILL.md +1 -1
- package/packages/shared-skills/skills/init-deep/SKILL.md +14 -14
- package/packages/shared-skills/skills/lsp-setup/SKILL.md +1 -1
- package/packages/shared-skills/skills/programming/SKILL.md +1 -1
- package/packages/shared-skills/skills/refactor/SKILL.md +1 -1
- package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +1 -1
- package/packages/shared-skills/skills/review-work/SKILL.md +100 -418
- package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +26 -9
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +110 -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 +23 -18
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -2
- package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +17 -16
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +7 -8
- 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 +8 -3
- package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
- package/packages/shared-skills/skills/visual-qa/SKILL.md +4 -3
- package/postinstall.mjs +2 -0
- package/script/qa/web-terminal-visual-qa.mjs +2 -0
- package/script/qa/xterm-live-terminal.mjs +18 -2
- package/dist/config/schema/codegraph.d.ts +0 -12
- package/dist/config/schema/start-work.d.ts +0 -5
- package/dist/features/builtin-commands/templates/start-work.d.ts +0 -1
- package/dist/features/builtin-skills/index.d.ts +0 -1
- package/dist/features/builtin-skills/skill-file-loader.d.ts +0 -1
- package/dist/features/builtin-skills/skills/agent-browser-skill.d.ts +0 -1
- package/dist/features/builtin-skills/skills/agent-browser-template.d.ts +0 -1
- package/dist/features/builtin-skills/skills/debugging.d.ts +0 -1
- package/dist/features/builtin-skills/skills/dev-browser.d.ts +0 -1
- package/dist/features/builtin-skills/skills/frontend.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/commit-atomic-planning.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/commit-context-analysis.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/commit-execution-verification.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/commit-workflow.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/history-search-workflow.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/overview.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/quick-reference.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-sections/rebase-workflow.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master-skill-metadata.d.ts +0 -1
- package/dist/features/builtin-skills/skills/git-master.d.ts +0 -1
- package/dist/features/builtin-skills/skills/index.d.ts +0 -1
- package/dist/features/builtin-skills/skills/init-deep.d.ts +0 -1
- package/dist/features/builtin-skills/skills/playwright-cli.d.ts +0 -1
- package/dist/features/builtin-skills/skills/playwright-mcp-skill.d.ts +0 -1
- package/dist/features/builtin-skills/skills/playwright.d.ts +0 -1
- package/dist/features/builtin-skills/skills/remove-ai-slops.d.ts +0 -1
- package/dist/features/builtin-skills/skills/review-work.d.ts +0 -1
- package/dist/features/builtin-skills/skills/security-research.d.ts +0 -1
- package/dist/features/builtin-skills/skills/security-review.d.ts +0 -1
- package/dist/features/builtin-skills/skills/team-mode.d.ts +0 -1
- package/dist/features/builtin-skills/skills/visual-qa.d.ts +0 -1
- package/dist/features/builtin-skills/skills.d.ts +0 -1
- package/dist/features/builtin-skills/types.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/agent-loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/command-loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/discovery-core.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/discovery-paths.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/discovery.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/hook-loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/index.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/install-path-resolver.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/installed-plugin-database.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/loaded-plugin.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/mcp-server-loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/plugin-key.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/plugin-manifest.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/plugin-path-resolver.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/plugin-settings.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/scope-filter.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/skill-loader.d.ts +0 -1
- package/dist/features/claude-code-plugin-loader/types.d.ts +0 -1
- package/dist/hooks/codegraph-bootstrap/command-runner.d.ts +0 -17
- package/dist/hooks/codegraph-bootstrap/hook.d.ts +0 -35
- package/dist/hooks/codegraph-bootstrap/index.d.ts +0 -1
- package/dist/hooks/codegraph-bootstrap/project-root.d.ts +0 -1
- package/dist/hooks/codegraph-bootstrap/status.d.ts +0 -11
- 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/mcp/codegraph.d.ts +0 -16
- package/dist/plugin/chat-message/start-work-message.d.ts +0 -5
- package/dist/shared/prompt-async-gate/message-inspection-error.d.ts +0 -1
- package/dist/shared/prompt-async-gate/pending-tool-turn.d.ts +0 -1
- package/dist/shared/prompt-async-gate/prompt-message-state.d.ts +0 -1
- package/dist/shared/prompt-async-gate/queue.d.ts +0 -1
- package/dist/shared/prompt-async-gate/recent-dispatches.d.ts +0 -1
- package/dist/shared/prompt-async-gate/reservations.d.ts +0 -1
- package/dist/shared/prompt-async-gate/semantic-dedupe.d.ts +0 -1
- package/dist/shared/prompt-async-gate/session-idle-dispatch.d.ts +0 -1
- package/dist/shared/prompt-async-gate/timing.d.ts +0 -1
- package/dist/shared/prompt-async-gate/types.d.ts +0 -1
- 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/anthropic-categories.d.ts +0 -2
- 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/codegraph/AGENTS.md +0 -58
- package/packages/omo-codex/plugin/components/codegraph/NODE-RUNTIME-LICENSES.md +0 -2951
- package/packages/omo-codex/plugin/components/codegraph/NOTICE +0 -16
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +0 -12136
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +0 -9734
- package/packages/omo-codex/plugin/components/codegraph/package.json +0 -33
- package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +0 -79
- package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +0 -33
- package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +0 -25
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +0 -131
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +0 -258
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +0 -309
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +0 -80
- package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +0 -34
- package/packages/omo-codex/plugin/components/codegraph/src/serve-invocation.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +0 -263
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +0 -106
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +0 -145
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +0 -21
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +0 -139
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +0 -15
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +0 -32
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +0 -109
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +0 -148
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +0 -175
- package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +0 -81
- package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +0 -34
- package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +0 -112
- package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +0 -26
- package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +0 -160
- package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +0 -50
- package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +0 -320
- package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +0 -172
- package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +0 -91
- package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +0 -100
- package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +0 -76
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +0 -133
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +0 -245
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +0 -69
- package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +0 -43
- package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +0 -147
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +0 -175
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +0 -385
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +0 -206
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +0 -58
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +0 -104
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +0 -65
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-availability.test.ts +0 -106
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +0 -116
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +0 -258
- package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +0 -56
- package/packages/omo-codex/plugin/components/codegraph/tsconfig.build.json +0 -13
- package/packages/omo-codex/plugin/components/codegraph/tsconfig.json +0 -25
- package/packages/omo-codex/plugin/components/start-work-continuation/LICENSE +0 -21
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +0 -471
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +0 -18
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +0 -17
- 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/scripts/migrate-omo-sot/editor.mjs +0 -125
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot/jsonc.mjs +0 -43
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot/scaffold.mjs +0 -29
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +0 -121
- 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/component-codegraph-mcp-smoke.test.mjs +0 -76
- package/packages/omo-codex/plugin/test/migrate-omo-sot.test.mjs +0 -179
- 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/{codegraph → 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}/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
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
import { statSync as statSync5 } from "node:fs";
|
|
3
|
+
import { isAbsolute as isAbsolute6 } from "node:path";
|
|
4
|
+
|
|
1
5
|
// src/daemon-client.ts
|
|
2
6
|
import { connect } from "node:net";
|
|
3
7
|
import { homedir as homedir3 } from "node:os";
|
|
4
|
-
import { join as
|
|
8
|
+
import { join as join8 } from "node:path";
|
|
5
9
|
|
|
6
10
|
// ../lsp-core/src/request-context.ts
|
|
7
11
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -10,18 +14,17 @@ import { homedir } from "node:os";
|
|
|
10
14
|
import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
11
15
|
|
|
12
16
|
class LspRequestContextParseError extends Error {
|
|
13
|
-
code;
|
|
14
|
-
name = "LspRequestContextParseError";
|
|
15
17
|
constructor(code, message) {
|
|
16
18
|
super(message);
|
|
17
19
|
this.code = code;
|
|
20
|
+
this.name = "LspRequestContextParseError";
|
|
18
21
|
}
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
class LspRequestContextUnavailableError extends Error {
|
|
22
|
-
name = "LspRequestContextUnavailableError";
|
|
23
25
|
constructor() {
|
|
24
26
|
super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
|
|
27
|
+
this.name = "LspRequestContextUnavailableError";
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
var storage = new AsyncLocalStorage;
|
|
@@ -41,7 +44,7 @@ function contextCwd() {
|
|
|
41
44
|
}
|
|
42
45
|
function createStandaloneMcpRequestContext(input = {}) {
|
|
43
46
|
const env = input.env ?? process.env;
|
|
44
|
-
const cwd = canonicalCwd(input.cwd ?? process.cwd());
|
|
47
|
+
const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
|
|
45
48
|
const home = input.homeDir ?? homedir();
|
|
46
49
|
const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
|
|
47
50
|
const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
|
|
@@ -179,7 +182,6 @@ function isPlainRecord(value) {
|
|
|
179
182
|
|
|
180
183
|
// src/daemon-request-error.ts
|
|
181
184
|
class DaemonRequestError extends Error {
|
|
182
|
-
requestWritten;
|
|
183
185
|
constructor(message, requestWritten) {
|
|
184
186
|
super(message);
|
|
185
187
|
this.name = "DaemonRequestError";
|
|
@@ -202,7 +204,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
|
|
|
202
204
|
}
|
|
203
205
|
|
|
204
206
|
class DaemonRequestTimedOutError extends DaemonRequestError {
|
|
205
|
-
timeoutMs;
|
|
206
207
|
constructor(requestWritten, timeoutMs) {
|
|
207
208
|
super("daemon request timed out", requestWritten);
|
|
208
209
|
this.name = "DaemonRequestTimedOutError";
|
|
@@ -281,14 +282,12 @@ var PROTOCOL_ERROR_CODE = -32002;
|
|
|
281
282
|
var AUTH_TOKEN_BYTES = 32;
|
|
282
283
|
|
|
283
284
|
class UnsafePrivateDirectoryError extends Error {
|
|
284
|
-
path;
|
|
285
|
-
reason;
|
|
286
|
-
name = "UnsafePrivateDirectoryError";
|
|
287
|
-
code = "unsafe_private_directory";
|
|
288
285
|
constructor(path, reason) {
|
|
289
286
|
super(`unsafe private directory ${path}: ${reason}`);
|
|
290
287
|
this.path = path;
|
|
291
288
|
this.reason = reason;
|
|
289
|
+
this.name = "UnsafePrivateDirectoryError";
|
|
290
|
+
this.code = "unsafe_private_directory";
|
|
292
291
|
}
|
|
293
292
|
}
|
|
294
293
|
function authEnvelope(token) {
|
|
@@ -472,20 +471,18 @@ var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
|
|
|
472
471
|
var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
473
472
|
|
|
474
473
|
class InvalidRuntimeOverrideError extends Error {
|
|
475
|
-
code = "invalid_runtime_override";
|
|
476
|
-
reason;
|
|
477
474
|
constructor(reason, message) {
|
|
478
475
|
super(message);
|
|
476
|
+
this.code = "invalid_runtime_override";
|
|
479
477
|
this.name = "InvalidRuntimeOverrideError";
|
|
480
478
|
this.reason = reason;
|
|
481
479
|
}
|
|
482
480
|
}
|
|
483
481
|
|
|
484
482
|
class InvalidDaemonVersionError extends Error {
|
|
485
|
-
code = "invalid_daemon_version";
|
|
486
|
-
version;
|
|
487
483
|
constructor(version) {
|
|
488
484
|
super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
|
|
485
|
+
this.code = "invalid_daemon_version";
|
|
489
486
|
this.name = "InvalidDaemonVersionError";
|
|
490
487
|
this.version = version;
|
|
491
488
|
}
|
|
@@ -531,10 +528,9 @@ var requireFromHere = createRequire(import.meta.url);
|
|
|
531
528
|
var MAX_SOCKET_PATH_LENGTH = 100;
|
|
532
529
|
|
|
533
530
|
class InvalidDaemonDirectoryError extends Error {
|
|
534
|
-
code = "invalid_daemon_directory";
|
|
535
|
-
directory;
|
|
536
531
|
constructor(directory) {
|
|
537
532
|
super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
|
|
533
|
+
this.code = "invalid_daemon_directory";
|
|
538
534
|
this.name = "InvalidDaemonDirectoryError";
|
|
539
535
|
this.directory = directory;
|
|
540
536
|
}
|
|
@@ -688,7 +684,7 @@ async function probeDaemon(paths, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
688
684
|
return await pingDaemon(paths, token, timeoutMs, signal) !== null;
|
|
689
685
|
}
|
|
690
686
|
function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
691
|
-
return new Promise((
|
|
687
|
+
return new Promise((resolve) => {
|
|
692
688
|
const socket = new Socket;
|
|
693
689
|
let settled = false;
|
|
694
690
|
let timer;
|
|
@@ -700,7 +696,7 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
700
696
|
clearTimeout(timer);
|
|
701
697
|
signal?.removeEventListener("abort", onAbort);
|
|
702
698
|
socket.destroy();
|
|
703
|
-
|
|
699
|
+
resolve(value);
|
|
704
700
|
};
|
|
705
701
|
const onAbort = () => finish(null);
|
|
706
702
|
const decoder = createLineDecoder((message) => {
|
|
@@ -723,13 +719,17 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
723
719
|
socket.connect(paths.socket);
|
|
724
720
|
});
|
|
725
721
|
}
|
|
726
|
-
function spawnDaemonProcess(paths) {
|
|
722
|
+
function spawnDaemonProcess(paths, deps = {}) {
|
|
727
723
|
mkdirSync2(dirname3(paths.log), { recursive: true });
|
|
728
724
|
const logFd = openSync2(paths.log, "a");
|
|
729
725
|
try {
|
|
730
|
-
const
|
|
726
|
+
const spawnDaemonChild = deps.spawn ?? spawn;
|
|
727
|
+
const executable = deps.resolveExecutable?.() ?? resolveDaemonNodeExecutable();
|
|
728
|
+
const child = spawnDaemonChild(executable, [paths.cliPath, "daemon"], {
|
|
731
729
|
detached: true,
|
|
732
|
-
stdio: ["ignore", logFd, logFd]
|
|
730
|
+
stdio: ["ignore", logFd, logFd],
|
|
731
|
+
windowsHide: true,
|
|
732
|
+
env: { ...process.env, BUN_BE_BUN: "1" }
|
|
733
733
|
});
|
|
734
734
|
child.once("spawn", () => closeSync2(logFd));
|
|
735
735
|
child.once("error", (error) => {
|
|
@@ -759,7 +759,7 @@ function defaultEnsureDaemonDeps() {
|
|
|
759
759
|
};
|
|
760
760
|
}
|
|
761
761
|
function sleepWithSignal(ms, signal) {
|
|
762
|
-
return new Promise((
|
|
762
|
+
return new Promise((resolve) => {
|
|
763
763
|
let settled = false;
|
|
764
764
|
const finish = () => {
|
|
765
765
|
if (settled)
|
|
@@ -767,7 +767,7 @@ function sleepWithSignal(ms, signal) {
|
|
|
767
767
|
settled = true;
|
|
768
768
|
clearTimeout(timer);
|
|
769
769
|
signal?.removeEventListener("abort", finish);
|
|
770
|
-
|
|
770
|
+
resolve();
|
|
771
771
|
};
|
|
772
772
|
const timer = setTimeout(finish, ms);
|
|
773
773
|
if (signal?.aborted) {
|
|
@@ -782,7 +782,7 @@ function awaitWithSignal(promise, signal) {
|
|
|
782
782
|
return promise;
|
|
783
783
|
if (signal.aborted)
|
|
784
784
|
return Promise.reject(abortError(signal));
|
|
785
|
-
return new Promise((
|
|
785
|
+
return new Promise((resolve, reject) => {
|
|
786
786
|
let settled = false;
|
|
787
787
|
const finish = (run) => {
|
|
788
788
|
if (settled)
|
|
@@ -793,7 +793,7 @@ function awaitWithSignal(promise, signal) {
|
|
|
793
793
|
};
|
|
794
794
|
const onAbort = () => finish(() => reject(abortError(signal)));
|
|
795
795
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
796
|
-
promise.then((value) => finish(() =>
|
|
796
|
+
promise.then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error)));
|
|
797
797
|
});
|
|
798
798
|
}
|
|
799
799
|
function throwIfAborted(signal) {
|
|
@@ -822,18 +822,18 @@ function parsePingResponse(message) {
|
|
|
822
822
|
return null;
|
|
823
823
|
if (!endpoint || typeof endpoint !== "object" || Array.isArray(endpoint))
|
|
824
824
|
return null;
|
|
825
|
-
const
|
|
825
|
+
const path = Reflect.get(endpoint, "path");
|
|
826
826
|
const kind = Reflect.get(endpoint, "kind");
|
|
827
|
-
if (typeof
|
|
827
|
+
if (typeof path !== "string")
|
|
828
828
|
return null;
|
|
829
829
|
if (kind === "windows")
|
|
830
|
-
return { pid, nonce, startedAt, endpoint: { kind, path
|
|
830
|
+
return { pid, nonce, startedAt, endpoint: { kind, path } };
|
|
831
831
|
if (kind === "missing")
|
|
832
|
-
return { pid, nonce, startedAt, endpoint: { kind, path
|
|
832
|
+
return { pid, nonce, startedAt, endpoint: { kind, path } };
|
|
833
833
|
const dev = Reflect.get(endpoint, "dev");
|
|
834
834
|
const ino = Reflect.get(endpoint, "ino");
|
|
835
835
|
if (kind === "unix" && typeof dev === "number" && typeof ino === "number") {
|
|
836
|
-
return { pid, nonce, startedAt, endpoint: { kind, path
|
|
836
|
+
return { pid, nonce, startedAt, endpoint: { kind, path, dev, ino } };
|
|
837
837
|
}
|
|
838
838
|
return null;
|
|
839
839
|
}
|
|
@@ -881,7 +881,7 @@ ${body}` : `${body}
|
|
|
881
881
|
await writeChunk(output, payload);
|
|
882
882
|
}
|
|
883
883
|
function writeChunk(output, chunk) {
|
|
884
|
-
return new Promise((
|
|
884
|
+
return new Promise((resolve, reject) => {
|
|
885
885
|
let settled = false;
|
|
886
886
|
const onError = (error) => {
|
|
887
887
|
if (settled)
|
|
@@ -901,7 +901,7 @@ function writeChunk(output, chunk) {
|
|
|
901
901
|
return;
|
|
902
902
|
}
|
|
903
903
|
output.removeListener("error", onError);
|
|
904
|
-
|
|
904
|
+
resolve();
|
|
905
905
|
});
|
|
906
906
|
} catch (error) {
|
|
907
907
|
output.removeListener("error", onError);
|
|
@@ -1010,6 +1010,7 @@ async function runJsonRpcStdioServer(config) {
|
|
|
1010
1010
|
const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
|
|
1011
1011
|
isClosed = true;
|
|
1012
1012
|
config.onIdleTimeout?.();
|
|
1013
|
+
config.input.destroy();
|
|
1013
1014
|
});
|
|
1014
1015
|
const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
|
|
1015
1016
|
isClosed = true;
|
|
@@ -1106,7 +1107,11 @@ function createParentWatchdog(config, onDeadParent) {
|
|
|
1106
1107
|
const probeAlive = config.probeAlive ?? isProcessAlive;
|
|
1107
1108
|
let fired = false;
|
|
1108
1109
|
const timer = setInterval(() => {
|
|
1109
|
-
if (fired
|
|
1110
|
+
if (fired)
|
|
1111
|
+
return;
|
|
1112
|
+
const alive = probeAlive(parentPid);
|
|
1113
|
+
config.onPoll?.(alive);
|
|
1114
|
+
if (alive)
|
|
1110
1115
|
return;
|
|
1111
1116
|
fired = true;
|
|
1112
1117
|
onDeadParent(parentPid, pollIntervalMs);
|
|
@@ -1141,8 +1146,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
|
|
|
1141
1146
|
};
|
|
1142
1147
|
}
|
|
1143
1148
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
1144
|
-
import { existsSync as
|
|
1145
|
-
import { dirname as
|
|
1149
|
+
import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
|
|
1150
|
+
import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
|
|
1146
1151
|
|
|
1147
1152
|
// ../lsp-core/src/lsp/effective-extension.ts
|
|
1148
1153
|
import { basename as basename2, extname } from "node:path";
|
|
@@ -1156,22 +1161,15 @@ function effectiveExtension(filePath) {
|
|
|
1156
1161
|
|
|
1157
1162
|
// ../lsp-core/src/lsp/errors.ts
|
|
1158
1163
|
class LspConnectionClosedError extends Error {
|
|
1159
|
-
serverId;
|
|
1160
|
-
root;
|
|
1161
|
-
name = "LspConnectionClosedError";
|
|
1162
1164
|
constructor(serverId, root, message) {
|
|
1163
1165
|
super(message ?? `LSP connection closed for ${serverId} at ${root}`);
|
|
1164
1166
|
this.serverId = serverId;
|
|
1165
1167
|
this.root = root;
|
|
1168
|
+
this.name = "LspConnectionClosedError";
|
|
1166
1169
|
}
|
|
1167
1170
|
}
|
|
1168
1171
|
|
|
1169
1172
|
class LspProcessExitedError extends Error {
|
|
1170
|
-
serverId;
|
|
1171
|
-
root;
|
|
1172
|
-
exitCode;
|
|
1173
|
-
stderrTail;
|
|
1174
|
-
name = "LspProcessExitedError";
|
|
1175
1173
|
constructor(serverId, root, exitCode, stderrTail) {
|
|
1176
1174
|
const stderrSuffix = stderrTail ? `
|
|
1177
1175
|
stderr tail: ${stderrTail}` : "";
|
|
@@ -1180,46 +1178,59 @@ stderr tail: ${stderrTail}` : "";
|
|
|
1180
1178
|
this.root = root;
|
|
1181
1179
|
this.exitCode = exitCode;
|
|
1182
1180
|
this.stderrTail = stderrTail;
|
|
1181
|
+
this.name = "LspProcessExitedError";
|
|
1183
1182
|
}
|
|
1184
1183
|
}
|
|
1185
1184
|
|
|
1186
1185
|
class LspRequestTimeoutError extends Error {
|
|
1187
|
-
method;
|
|
1188
|
-
stderrTail;
|
|
1189
|
-
name = "LspRequestTimeoutError";
|
|
1190
1186
|
constructor(method, stderrTail) {
|
|
1191
1187
|
const stderrSuffix = stderrTail ? `
|
|
1192
1188
|
recent stderr: ${stderrTail}` : "";
|
|
1193
1189
|
super(`LSP request timeout (method: ${method})${stderrSuffix}`);
|
|
1194
1190
|
this.method = method;
|
|
1195
1191
|
this.stderrTail = stderrTail;
|
|
1192
|
+
this.name = "LspRequestTimeoutError";
|
|
1196
1193
|
}
|
|
1197
1194
|
}
|
|
1198
1195
|
|
|
1199
1196
|
class LspInvalidPathError extends Error {
|
|
1200
|
-
|
|
1197
|
+
constructor() {
|
|
1198
|
+
super(...arguments);
|
|
1199
|
+
this.name = "LspInvalidPathError";
|
|
1200
|
+
}
|
|
1201
1201
|
}
|
|
1202
1202
|
|
|
1203
1203
|
class LspServerLookupError extends Error {
|
|
1204
|
-
lookup;
|
|
1205
|
-
name = "LspServerLookupError";
|
|
1206
1204
|
constructor(message, lookup) {
|
|
1207
1205
|
super(message);
|
|
1208
1206
|
this.lookup = lookup;
|
|
1207
|
+
this.name = "LspServerLookupError";
|
|
1209
1208
|
}
|
|
1210
1209
|
}
|
|
1211
1210
|
|
|
1212
1211
|
class LspServerInitializingError extends Error {
|
|
1213
|
-
originalError;
|
|
1214
|
-
name = "LspServerInitializingError";
|
|
1215
1212
|
constructor(originalError) {
|
|
1216
1213
|
super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
|
|
1217
1214
|
this.originalError = originalError;
|
|
1215
|
+
this.name = "LspServerInitializingError";
|
|
1218
1216
|
}
|
|
1219
1217
|
}
|
|
1220
1218
|
|
|
1221
1219
|
class LspProcessSpawnError extends Error {
|
|
1222
|
-
|
|
1220
|
+
constructor() {
|
|
1221
|
+
super(...arguments);
|
|
1222
|
+
this.name = "LspProcessSpawnError";
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
class LspClientRespawnBudgetExceededError extends Error {
|
|
1227
|
+
constructor(serverId, root, retryLimit) {
|
|
1228
|
+
super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
|
|
1229
|
+
this.serverId = serverId;
|
|
1230
|
+
this.root = root;
|
|
1231
|
+
this.retryLimit = retryLimit;
|
|
1232
|
+
this.name = "LspClientRespawnBudgetExceededError";
|
|
1233
|
+
}
|
|
1223
1234
|
}
|
|
1224
1235
|
function isLspDeadConnectionError(err) {
|
|
1225
1236
|
return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
|
|
@@ -1242,6 +1253,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
|
1242
1253
|
// ../lsp-core/src/lsp/connection.ts
|
|
1243
1254
|
import { pathToFileURL } from "node:url";
|
|
1244
1255
|
|
|
1256
|
+
// ../lsp-core/src/lsp/timer-provider.ts
|
|
1257
|
+
var realTimerProvider = {
|
|
1258
|
+
now: () => Date.now(),
|
|
1259
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
1260
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
1261
|
+
};
|
|
1262
|
+
|
|
1245
1263
|
// ../lsp-core/src/lsp/constants.ts
|
|
1246
1264
|
var DEFAULT_MAX_REFERENCES = 200;
|
|
1247
1265
|
var DEFAULT_MAX_SYMBOLS = 200;
|
|
@@ -1250,9 +1268,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
|
|
|
1250
1268
|
var REQUEST_TIMEOUT_MS = 15000;
|
|
1251
1269
|
var INIT_TIMEOUT_MS = 60000;
|
|
1252
1270
|
var IDLE_TIMEOUT_MS = 5 * 60000;
|
|
1271
|
+
var MAX_RESIDENT_CLIENTS = 6;
|
|
1253
1272
|
var REAPER_INTERVAL_MS = 60000;
|
|
1254
1273
|
var STOP_HARD_KILL_TIMEOUT_MS = 5000;
|
|
1255
1274
|
var STOP_SIGKILL_GRACE_MS = 1000;
|
|
1275
|
+
var CLIENT_RESPAWN_RETRY_LIMIT = 2;
|
|
1276
|
+
var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
|
|
1256
1277
|
|
|
1257
1278
|
// ../lsp-core/src/lsp/json-rpc-connection.ts
|
|
1258
1279
|
var HEADER_SEPARATOR2 = `\r
|
|
@@ -1264,20 +1285,31 @@ var METHOD_NOT_FOUND = -32601;
|
|
|
1264
1285
|
var INTERNAL_ERROR = -32603;
|
|
1265
1286
|
|
|
1266
1287
|
class JsonRpcConnection {
|
|
1267
|
-
reader;
|
|
1268
|
-
writer;
|
|
1269
|
-
pendingRequests = new Map;
|
|
1270
|
-
notificationHandlers = new Map;
|
|
1271
|
-
requestHandlers = new Map;
|
|
1272
|
-
closeHandlers = [];
|
|
1273
|
-
errorHandlers = [];
|
|
1274
|
-
inputBuffer = Buffer.alloc(0);
|
|
1275
|
-
nextRequestId = 1;
|
|
1276
|
-
listening = false;
|
|
1277
|
-
disposed = false;
|
|
1278
1288
|
constructor(reader, writer) {
|
|
1279
1289
|
this.reader = reader;
|
|
1280
1290
|
this.writer = writer;
|
|
1291
|
+
this.pendingRequests = new Map;
|
|
1292
|
+
this.notificationHandlers = new Map;
|
|
1293
|
+
this.requestHandlers = new Map;
|
|
1294
|
+
this.closeHandlers = [];
|
|
1295
|
+
this.errorHandlers = [];
|
|
1296
|
+
this.inputBuffer = Buffer.alloc(0);
|
|
1297
|
+
this.nextRequestId = 1;
|
|
1298
|
+
this.listening = false;
|
|
1299
|
+
this.disposed = false;
|
|
1300
|
+
this.handleData = (chunk) => {
|
|
1301
|
+
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
1302
|
+
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
1303
|
+
this.drainInputBuffer();
|
|
1304
|
+
};
|
|
1305
|
+
this.handleClose = () => {
|
|
1306
|
+
for (const handler of this.closeHandlers) {
|
|
1307
|
+
handler();
|
|
1308
|
+
}
|
|
1309
|
+
};
|
|
1310
|
+
this.handleStreamError = (error) => {
|
|
1311
|
+
this.emitError(error);
|
|
1312
|
+
};
|
|
1281
1313
|
}
|
|
1282
1314
|
listen() {
|
|
1283
1315
|
if (this.listening)
|
|
@@ -1312,7 +1344,8 @@ class JsonRpcConnection {
|
|
|
1312
1344
|
let cancelAfterWrite = false;
|
|
1313
1345
|
let settled = false;
|
|
1314
1346
|
const writeCancel = () => this.writeMessage({ jsonrpc: "2.0", method: "$/cancelRequest", params: { id } });
|
|
1315
|
-
|
|
1347
|
+
let rejectAfterCancelWrite;
|
|
1348
|
+
const responsePromise = new Promise((resolve, reject) => {
|
|
1316
1349
|
const cleanup = () => {
|
|
1317
1350
|
options.signal?.removeEventListener("abort", onAbort);
|
|
1318
1351
|
};
|
|
@@ -1323,22 +1356,26 @@ class JsonRpcConnection {
|
|
|
1323
1356
|
this.pendingRequests.delete(key);
|
|
1324
1357
|
cleanup();
|
|
1325
1358
|
const rejectCancelled = () => reject(abortError2(options.signal));
|
|
1359
|
+
rejectAfterCancelWrite = async () => {
|
|
1360
|
+
try {
|
|
1361
|
+
await writeCancel();
|
|
1362
|
+
} catch (error) {
|
|
1363
|
+
this.emitError(toError(error));
|
|
1364
|
+
}
|
|
1365
|
+
rejectCancelled();
|
|
1366
|
+
};
|
|
1326
1367
|
if (!requestWritten) {
|
|
1327
1368
|
cancelAfterWrite = true;
|
|
1328
|
-
rejectCancelled();
|
|
1329
1369
|
return;
|
|
1330
1370
|
}
|
|
1331
|
-
|
|
1332
|
-
this.emitError(toError(error));
|
|
1333
|
-
rejectCancelled();
|
|
1334
|
-
});
|
|
1371
|
+
rejectAfterCancelWrite();
|
|
1335
1372
|
};
|
|
1336
1373
|
const onAbort = () => settleCancel();
|
|
1337
1374
|
this.pendingRequests.set(key, {
|
|
1338
1375
|
resolve(result) {
|
|
1339
1376
|
settled = true;
|
|
1340
1377
|
cleanup();
|
|
1341
|
-
|
|
1378
|
+
resolve(result);
|
|
1342
1379
|
},
|
|
1343
1380
|
reject(error) {
|
|
1344
1381
|
settled = true;
|
|
@@ -1359,7 +1396,7 @@ class JsonRpcConnection {
|
|
|
1359
1396
|
await this.writeMessage(message);
|
|
1360
1397
|
requestWritten = true;
|
|
1361
1398
|
if (cancelAfterWrite)
|
|
1362
|
-
await
|
|
1399
|
+
await rejectAfterCancelWrite?.();
|
|
1363
1400
|
} catch (error) {
|
|
1364
1401
|
if (settled)
|
|
1365
1402
|
return responsePromise;
|
|
@@ -1398,19 +1435,6 @@ class JsonRpcConnection {
|
|
|
1398
1435
|
this.notificationHandlers.clear();
|
|
1399
1436
|
this.requestHandlers.clear();
|
|
1400
1437
|
}
|
|
1401
|
-
handleData = (chunk) => {
|
|
1402
|
-
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
1403
|
-
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
1404
|
-
this.drainInputBuffer();
|
|
1405
|
-
};
|
|
1406
|
-
handleClose = () => {
|
|
1407
|
-
for (const handler of this.closeHandlers) {
|
|
1408
|
-
handler();
|
|
1409
|
-
}
|
|
1410
|
-
};
|
|
1411
|
-
handleStreamError = (error) => {
|
|
1412
|
-
this.emitError(error);
|
|
1413
|
-
};
|
|
1414
1438
|
drainInputBuffer() {
|
|
1415
1439
|
while (true) {
|
|
1416
1440
|
const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
|
|
@@ -1510,13 +1534,13 @@ class JsonRpcConnection {
|
|
|
1510
1534
|
const payload = `Content-Length: ${Buffer.byteLength(body, "utf8")}\r
|
|
1511
1535
|
\r
|
|
1512
1536
|
${body}`;
|
|
1513
|
-
return new Promise((
|
|
1537
|
+
return new Promise((resolve, reject) => {
|
|
1514
1538
|
this.writer.write(payload, (error) => {
|
|
1515
1539
|
if (error) {
|
|
1516
1540
|
reject(error);
|
|
1517
1541
|
return;
|
|
1518
1542
|
}
|
|
1519
|
-
|
|
1543
|
+
resolve();
|
|
1520
1544
|
});
|
|
1521
1545
|
});
|
|
1522
1546
|
}
|
|
@@ -1603,9 +1627,9 @@ function validateCwd(cwd) {
|
|
|
1603
1627
|
}
|
|
1604
1628
|
}
|
|
1605
1629
|
function wrap(proc) {
|
|
1606
|
-
const exitedPromise = new Promise((
|
|
1607
|
-
proc.once("close", (code) =>
|
|
1608
|
-
proc.once("error", () =>
|
|
1630
|
+
const exitedPromise = new Promise((resolve) => {
|
|
1631
|
+
proc.once("close", (code) => resolve(code ?? 0));
|
|
1632
|
+
proc.once("error", () => resolve(1));
|
|
1609
1633
|
});
|
|
1610
1634
|
if (!proc.stdin || !proc.stdout || !proc.stderr) {
|
|
1611
1635
|
throw new LspProcessSpawnError("Spawned process is missing one of stdin/stdout/stderr pipes");
|
|
@@ -1758,33 +1782,29 @@ function isPosition(value) {
|
|
|
1758
1782
|
|
|
1759
1783
|
// ../lsp-core/src/lsp/transport.ts
|
|
1760
1784
|
class LspClientNotStartedError extends Error {
|
|
1761
|
-
serverId;
|
|
1762
|
-
root;
|
|
1763
|
-
name = "LspClientNotStartedError";
|
|
1764
1785
|
constructor(serverId, root) {
|
|
1765
1786
|
super("LSP client not started");
|
|
1766
1787
|
this.serverId = serverId;
|
|
1767
1788
|
this.root = root;
|
|
1789
|
+
this.name = "LspClientNotStartedError";
|
|
1768
1790
|
}
|
|
1769
1791
|
}
|
|
1770
1792
|
|
|
1771
1793
|
class LspClientTransport {
|
|
1772
|
-
root
|
|
1773
|
-
server;
|
|
1774
|
-
proc = null;
|
|
1775
|
-
connection = null;
|
|
1776
|
-
stderrBuffer = [];
|
|
1777
|
-
processExited = false;
|
|
1778
|
-
diagnosticsStore = new Map;
|
|
1779
|
-
requestTimeoutMs;
|
|
1780
|
-
initializeTimeoutMs;
|
|
1781
|
-
workspaceApplyEditHandler = null;
|
|
1782
|
-
diagnosticPullSupported = false;
|
|
1783
|
-
constructor(root, server2, timeouts = {}) {
|
|
1794
|
+
constructor(root, server, timeouts = {}) {
|
|
1784
1795
|
this.root = root;
|
|
1785
|
-
this.server =
|
|
1796
|
+
this.server = server;
|
|
1797
|
+
this.proc = null;
|
|
1798
|
+
this.connection = null;
|
|
1799
|
+
this.stderrBuffer = [];
|
|
1800
|
+
this.processExited = false;
|
|
1801
|
+
this.diagnosticsStore = new Map;
|
|
1802
|
+
this.workspaceApplyEditHandler = null;
|
|
1803
|
+
this.diagnosticPullSupported = false;
|
|
1804
|
+
this.documentFormattingSupported = false;
|
|
1786
1805
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
1787
1806
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
1807
|
+
this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
|
|
1788
1808
|
}
|
|
1789
1809
|
pid() {
|
|
1790
1810
|
return this.proc?.pid;
|
|
@@ -1804,6 +1824,12 @@ class LspClientTransport {
|
|
|
1804
1824
|
isDiagnosticPullSupported() {
|
|
1805
1825
|
return this.diagnosticPullSupported;
|
|
1806
1826
|
}
|
|
1827
|
+
setDocumentFormattingSupported(supported) {
|
|
1828
|
+
this.documentFormattingSupported = supported;
|
|
1829
|
+
}
|
|
1830
|
+
isDocumentFormattingSupported() {
|
|
1831
|
+
return this.documentFormattingSupported;
|
|
1832
|
+
}
|
|
1807
1833
|
handlePublishDiagnostics(params) {
|
|
1808
1834
|
this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
|
|
1809
1835
|
}
|
|
@@ -1879,7 +1905,7 @@ class LspClientTransport {
|
|
|
1879
1905
|
const options = args[1];
|
|
1880
1906
|
const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
|
|
1881
1907
|
const timeoutController = new AbortController;
|
|
1882
|
-
const timeoutHandle = setTimeout(() => {
|
|
1908
|
+
const timeoutHandle = this.timerProvider.setTimeout(() => {
|
|
1883
1909
|
const stderrTail = this.stderrBuffer.slice(-5).join(`
|
|
1884
1910
|
`);
|
|
1885
1911
|
timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
|
|
@@ -1898,7 +1924,7 @@ class LspClientTransport {
|
|
|
1898
1924
|
}
|
|
1899
1925
|
throw error;
|
|
1900
1926
|
} finally {
|
|
1901
|
-
clearTimeout(timeoutHandle);
|
|
1927
|
+
this.timerProvider.clearTimeout(timeoutHandle);
|
|
1902
1928
|
combinedSignal.dispose();
|
|
1903
1929
|
}
|
|
1904
1930
|
}
|
|
@@ -1949,8 +1975,8 @@ class LspClientTransport {
|
|
|
1949
1975
|
try {
|
|
1950
1976
|
proc.kill();
|
|
1951
1977
|
let timeoutId;
|
|
1952
|
-
const timeoutPromise = new Promise((
|
|
1953
|
-
timeoutId = setTimeout(
|
|
1978
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
1979
|
+
timeoutId = setTimeout(resolve, STOP_HARD_KILL_TIMEOUT_MS);
|
|
1954
1980
|
});
|
|
1955
1981
|
await Promise.race([
|
|
1956
1982
|
proc.exited.then(() => {
|
|
@@ -1966,7 +1992,7 @@ class LspClientTransport {
|
|
|
1966
1992
|
proc.kill("SIGKILL");
|
|
1967
1993
|
await Promise.race([
|
|
1968
1994
|
proc.exited,
|
|
1969
|
-
new Promise((
|
|
1995
|
+
new Promise((resolve) => setTimeout(resolve, STOP_SIGKILL_GRACE_MS))
|
|
1970
1996
|
]);
|
|
1971
1997
|
} catch (error) {
|
|
1972
1998
|
reportBestEffortCleanupError("hard process kill", error instanceof Error ? error : String(error));
|
|
@@ -2017,6 +2043,14 @@ function supportsDiagnosticPull(capabilities) {
|
|
|
2017
2043
|
return false;
|
|
2018
2044
|
return Object.hasOwn(capabilities, "diagnosticProvider");
|
|
2019
2045
|
}
|
|
2046
|
+
function supportsDocumentFormatting(capabilities) {
|
|
2047
|
+
if (capabilities === undefined)
|
|
2048
|
+
return false;
|
|
2049
|
+
const provider = capabilities.documentFormattingProvider;
|
|
2050
|
+
if (provider === undefined || provider === null || provider === false)
|
|
2051
|
+
return false;
|
|
2052
|
+
return provider === true || typeof provider === "object";
|
|
2053
|
+
}
|
|
2020
2054
|
|
|
2021
2055
|
class LspClientConnection extends LspClientTransport {
|
|
2022
2056
|
async initialize() {
|
|
@@ -2033,6 +2067,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
2033
2067
|
references: {},
|
|
2034
2068
|
documentSymbol: { hierarchicalDocumentSymbolSupport: true },
|
|
2035
2069
|
publishDiagnostics: {},
|
|
2070
|
+
formatting: { dynamicRegistration: false },
|
|
2036
2071
|
rename: {
|
|
2037
2072
|
prepareSupport: true,
|
|
2038
2073
|
prepareSupportDefaultBehavior: 1
|
|
@@ -2074,6 +2109,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
2074
2109
|
initializationOptions: this.server.initialization
|
|
2075
2110
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
2076
2111
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
2112
|
+
this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
|
|
2077
2113
|
await this.sendNotification("initialized", {});
|
|
2078
2114
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
2079
2115
|
settings: { json: { validate: { enable: true } } }
|
|
@@ -2269,6 +2305,17 @@ function canonicalPath(filePath) {
|
|
|
2269
2305
|
return absolute;
|
|
2270
2306
|
}
|
|
2271
2307
|
}
|
|
2308
|
+
function normalizeDocumentUri(uri) {
|
|
2309
|
+
let decoded = uri;
|
|
2310
|
+
try {
|
|
2311
|
+
decoded = decodeURIComponent(uri);
|
|
2312
|
+
} catch {
|
|
2313
|
+
decoded = uri;
|
|
2314
|
+
}
|
|
2315
|
+
if (process.platform !== "win32")
|
|
2316
|
+
return decoded;
|
|
2317
|
+
return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
|
|
2318
|
+
}
|
|
2272
2319
|
function isSameOrDescendant(candidate, parent) {
|
|
2273
2320
|
const suffix = relative2(parent, candidate);
|
|
2274
2321
|
return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
|
|
@@ -2279,30 +2326,31 @@ function movedPath(candidate, oldPath, newPath) {
|
|
|
2279
2326
|
}
|
|
2280
2327
|
|
|
2281
2328
|
class WorkspaceDocumentState {
|
|
2282
|
-
sendNotification;
|
|
2283
|
-
clearDiagnostics;
|
|
2284
|
-
openDocuments = new Map;
|
|
2285
|
-
openByUri = new Map;
|
|
2286
|
-
openPromises = new Map;
|
|
2287
|
-
now;
|
|
2288
|
-
versionlessPublishQuiescenceMs;
|
|
2289
2329
|
constructor(sendNotification, clearDiagnostics, options = {}) {
|
|
2290
2330
|
this.sendNotification = sendNotification;
|
|
2291
2331
|
this.clearDiagnostics = clearDiagnostics;
|
|
2292
|
-
this.
|
|
2332
|
+
this.openDocuments = new Map;
|
|
2333
|
+
this.openByUri = new Map;
|
|
2334
|
+
this.openPromises = new Map;
|
|
2335
|
+
this.timerProvider = options.timerProvider ?? {
|
|
2336
|
+
now: options.now ?? (() => Date.now()),
|
|
2337
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
2338
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
2339
|
+
};
|
|
2340
|
+
this.now = () => this.timerProvider.now();
|
|
2293
2341
|
this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
|
|
2294
2342
|
}
|
|
2295
2343
|
async openFile(filePath) {
|
|
2296
|
-
const
|
|
2297
|
-
const existingOpen = this.openPromises.get(
|
|
2344
|
+
const path = canonicalPath(filePath);
|
|
2345
|
+
const existingOpen = this.openPromises.get(path);
|
|
2298
2346
|
if (existingOpen) {
|
|
2299
2347
|
await existingOpen;
|
|
2300
|
-
return this.openFile(
|
|
2348
|
+
return this.openFile(path);
|
|
2301
2349
|
}
|
|
2302
|
-
const text = readFileSync2(
|
|
2303
|
-
const existing = this.openDocuments.get(
|
|
2350
|
+
const text = readFileSync2(path, "utf-8");
|
|
2351
|
+
const existing = this.openDocuments.get(path);
|
|
2304
2352
|
if (!existing)
|
|
2305
|
-
return this.openDocumentSingleFlight(
|
|
2353
|
+
return this.openDocumentSingleFlight(path, text);
|
|
2306
2354
|
if (existing.text === text)
|
|
2307
2355
|
return;
|
|
2308
2356
|
await this.changeDocument(existing, text);
|
|
@@ -2311,7 +2359,7 @@ class WorkspaceDocumentState {
|
|
|
2311
2359
|
return this.openDocuments.get(canonicalPath(filePath))?.version;
|
|
2312
2360
|
}
|
|
2313
2361
|
getStoredDiagnostics(uri) {
|
|
2314
|
-
const state = this.openByUri.get(uri);
|
|
2362
|
+
const state = this.openByUri.get(normalizeDocumentUri(uri));
|
|
2315
2363
|
if (!state)
|
|
2316
2364
|
return [];
|
|
2317
2365
|
return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
|
|
@@ -2333,13 +2381,13 @@ class WorkspaceDocumentState {
|
|
|
2333
2381
|
return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
|
|
2334
2382
|
}
|
|
2335
2383
|
getPullCache(snapshot) {
|
|
2336
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2384
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2337
2385
|
if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
|
|
2338
2386
|
return null;
|
|
2339
2387
|
return state.pullCache;
|
|
2340
2388
|
}
|
|
2341
2389
|
recordPullDiagnostics(snapshot, report) {
|
|
2342
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2390
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2343
2391
|
if (!state)
|
|
2344
2392
|
return;
|
|
2345
2393
|
state.pullCache = {
|
|
@@ -2349,7 +2397,7 @@ class WorkspaceDocumentState {
|
|
|
2349
2397
|
};
|
|
2350
2398
|
}
|
|
2351
2399
|
recordPublishedDiagnostics(params) {
|
|
2352
|
-
const state = this.openByUri.get(params.uri);
|
|
2400
|
+
const state = this.openByUri.get(normalizeDocumentUri(params.uri));
|
|
2353
2401
|
if (!state)
|
|
2354
2402
|
return;
|
|
2355
2403
|
state.publishGeneration += 1;
|
|
@@ -2363,7 +2411,7 @@ class WorkspaceDocumentState {
|
|
|
2363
2411
|
this.notifyWaiters(state);
|
|
2364
2412
|
}
|
|
2365
2413
|
resolvePushDiagnostics(snapshot) {
|
|
2366
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2414
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2367
2415
|
if (!state?.lastPublish)
|
|
2368
2416
|
return { status: "missing" };
|
|
2369
2417
|
const publish = state.lastPublish;
|
|
@@ -2377,7 +2425,7 @@ class WorkspaceDocumentState {
|
|
|
2377
2425
|
return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
|
|
2378
2426
|
}
|
|
2379
2427
|
waitForDiagnosticsActivity(snapshot, timeoutMs) {
|
|
2380
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2428
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2381
2429
|
if (!state || timeoutMs <= 0)
|
|
2382
2430
|
return Promise.resolve();
|
|
2383
2431
|
return new Promise((resolveActivity) => {
|
|
@@ -2386,18 +2434,18 @@ class WorkspaceDocumentState {
|
|
|
2386
2434
|
if (settled)
|
|
2387
2435
|
return;
|
|
2388
2436
|
settled = true;
|
|
2389
|
-
clearTimeout(timer);
|
|
2437
|
+
this.timerProvider.clearTimeout(timer);
|
|
2390
2438
|
state.waiters.delete(finish);
|
|
2391
2439
|
resolveActivity();
|
|
2392
2440
|
};
|
|
2393
|
-
const timer = setTimeout(finish, timeoutMs);
|
|
2441
|
+
const timer = this.timerProvider.setTimeout(finish, timeoutMs);
|
|
2394
2442
|
if (typeof timer.unref === "function")
|
|
2395
2443
|
timer.unref();
|
|
2396
2444
|
state.waiters.add(finish);
|
|
2397
2445
|
});
|
|
2398
2446
|
}
|
|
2399
2447
|
validateVersions(operations) {
|
|
2400
|
-
const versions = new Map([...this.openDocuments].map(([
|
|
2448
|
+
const versions = new Map([...this.openDocuments].map(([path, state]) => [path, state.version]));
|
|
2401
2449
|
for (const operation of operations) {
|
|
2402
2450
|
if (operation.kind === "text") {
|
|
2403
2451
|
const current = versions.get(operation.path);
|
|
@@ -2413,17 +2461,17 @@ class WorkspaceDocumentState {
|
|
|
2413
2461
|
continue;
|
|
2414
2462
|
}
|
|
2415
2463
|
if (operation.kind === "rename") {
|
|
2416
|
-
const moved = [...versions].filter(([
|
|
2417
|
-
for (const [
|
|
2418
|
-
versions.delete(
|
|
2419
|
-
for (const [
|
|
2420
|
-
versions.set(movedPath(
|
|
2464
|
+
const moved = [...versions].filter(([path]) => isSameOrDescendant(path, operation.oldPath));
|
|
2465
|
+
for (const [path] of moved)
|
|
2466
|
+
versions.delete(path);
|
|
2467
|
+
for (const [path] of moved)
|
|
2468
|
+
versions.set(movedPath(path, operation.oldPath, operation.newPath), 1);
|
|
2421
2469
|
continue;
|
|
2422
2470
|
}
|
|
2423
2471
|
if (operation.kind === "delete") {
|
|
2424
|
-
for (const
|
|
2425
|
-
if (isSameOrDescendant(
|
|
2426
|
-
versions.delete(
|
|
2472
|
+
for (const path of [...versions.keys()]) {
|
|
2473
|
+
if (isSameOrDescendant(path, operation.path))
|
|
2474
|
+
versions.delete(path);
|
|
2427
2475
|
}
|
|
2428
2476
|
continue;
|
|
2429
2477
|
}
|
|
@@ -2467,8 +2515,8 @@ class WorkspaceDocumentState {
|
|
|
2467
2515
|
for (const state of moved)
|
|
2468
2516
|
await this.closeDocument(state);
|
|
2469
2517
|
for (const state of moved) {
|
|
2470
|
-
const
|
|
2471
|
-
await this.openDocumentSingleFlight(
|
|
2518
|
+
const path = movedPath(state.path, mutation.oldPath, mutation.newPath);
|
|
2519
|
+
await this.openDocumentSingleFlight(path, readFileSync2(path, "utf-8"));
|
|
2472
2520
|
}
|
|
2473
2521
|
if (moved.length === 0) {
|
|
2474
2522
|
watched.push({ uri: pathToFileURL2(mutation.oldPath).href, type: 3 });
|
|
@@ -2482,31 +2530,31 @@ class WorkspaceDocumentState {
|
|
|
2482
2530
|
if (removed.length === 0)
|
|
2483
2531
|
watched.push({ uri: pathToFileURL2(mutation.path).href, type: 3 });
|
|
2484
2532
|
}
|
|
2485
|
-
async openDocumentSingleFlight(
|
|
2486
|
-
const existing = this.openPromises.get(
|
|
2533
|
+
async openDocumentSingleFlight(path, text) {
|
|
2534
|
+
const existing = this.openPromises.get(path);
|
|
2487
2535
|
if (existing)
|
|
2488
2536
|
return existing;
|
|
2489
2537
|
const open = (async () => {
|
|
2490
2538
|
const state = {
|
|
2491
|
-
path
|
|
2492
|
-
uri: pathToFileURL2(
|
|
2493
|
-
languageId: getLanguageId(effectiveExtension(
|
|
2539
|
+
path,
|
|
2540
|
+
uri: pathToFileURL2(path).href,
|
|
2541
|
+
languageId: getLanguageId(effectiveExtension(path)),
|
|
2494
2542
|
text,
|
|
2495
2543
|
version: 1,
|
|
2496
2544
|
generation: 1,
|
|
2497
2545
|
publishGeneration: 0,
|
|
2498
2546
|
waiters: new Set
|
|
2499
2547
|
};
|
|
2500
|
-
this.openDocuments.set(
|
|
2501
|
-
this.openByUri.set(state.uri, state);
|
|
2548
|
+
this.openDocuments.set(path, state);
|
|
2549
|
+
this.openByUri.set(normalizeDocumentUri(state.uri), state);
|
|
2502
2550
|
this.notifyWaiters(state);
|
|
2503
2551
|
await this.sendNotification("textDocument/didOpen", {
|
|
2504
2552
|
textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
|
|
2505
2553
|
});
|
|
2506
2554
|
})().finally(() => {
|
|
2507
|
-
this.openPromises.delete(
|
|
2555
|
+
this.openPromises.delete(path);
|
|
2508
2556
|
});
|
|
2509
|
-
this.openPromises.set(
|
|
2557
|
+
this.openPromises.set(path, open);
|
|
2510
2558
|
return open;
|
|
2511
2559
|
}
|
|
2512
2560
|
async changeDocument(state, text) {
|
|
@@ -2523,7 +2571,7 @@ class WorkspaceDocumentState {
|
|
|
2523
2571
|
}
|
|
2524
2572
|
async closeDocument(state) {
|
|
2525
2573
|
this.openDocuments.delete(state.path);
|
|
2526
|
-
this.openByUri.delete(state.uri);
|
|
2574
|
+
this.openByUri.delete(normalizeDocumentUri(state.uri));
|
|
2527
2575
|
this.clearDiagnostics(state.uri);
|
|
2528
2576
|
this.notifyWaiters(state);
|
|
2529
2577
|
await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
|
|
@@ -2552,13 +2600,11 @@ import { dirname as dirname4, isAbsolute as isAbsolute4, relative as relative3,
|
|
|
2552
2600
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
2553
2601
|
|
|
2554
2602
|
class WorkspaceEditPathError extends Error {
|
|
2555
|
-
path
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
constructor(path2, detail) {
|
|
2559
|
-
super(`${detail}: ${path2}`);
|
|
2560
|
-
this.path = path2;
|
|
2603
|
+
constructor(path, detail) {
|
|
2604
|
+
super(`${detail}: ${path}`);
|
|
2605
|
+
this.path = path;
|
|
2561
2606
|
this.detail = detail;
|
|
2607
|
+
this.name = "WorkspaceEditPathError";
|
|
2562
2608
|
}
|
|
2563
2609
|
}
|
|
2564
2610
|
function isPathInsideWorkspace(filePath, workspaceRoot) {
|
|
@@ -2620,28 +2666,28 @@ function uriToCanonicalWorkspacePath(uri, workspaceRoot) {
|
|
|
2620
2666
|
return { success: false, error: `${requestedPath}: ${detail}` };
|
|
2621
2667
|
}
|
|
2622
2668
|
}
|
|
2623
|
-
function snapshotPath(
|
|
2624
|
-
if (!existsSync4(
|
|
2669
|
+
function snapshotPath(path, includeChildren) {
|
|
2670
|
+
if (!existsSync4(path))
|
|
2625
2671
|
return { kind: "missing" };
|
|
2626
|
-
const stats = lstatSync2(
|
|
2672
|
+
const stats = lstatSync2(path);
|
|
2627
2673
|
if (stats.isFile())
|
|
2628
|
-
return { kind: "file", content: readFileSync3(
|
|
2674
|
+
return { kind: "file", content: readFileSync3(path, "utf-8") };
|
|
2629
2675
|
if (stats.isDirectory()) {
|
|
2630
|
-
return includeChildren ? { kind: "directory", children: readdirSync(
|
|
2676
|
+
return includeChildren ? { kind: "directory", children: readdirSync(path).sort() } : { kind: "directory" };
|
|
2631
2677
|
}
|
|
2632
|
-
throw new WorkspaceEditPathError(
|
|
2678
|
+
throw new WorkspaceEditPathError(path, "unsupported filesystem entry");
|
|
2633
2679
|
}
|
|
2634
2680
|
|
|
2635
2681
|
// ../lsp-core/src/lsp/workspace-edit-commit.ts
|
|
2636
2682
|
var DEFAULT_IO = {
|
|
2637
|
-
writeFile(
|
|
2638
|
-
writeFileSync(
|
|
2683
|
+
writeFile(path, content) {
|
|
2684
|
+
writeFileSync(path, content, "utf-8");
|
|
2639
2685
|
},
|
|
2640
2686
|
rename(oldPath, newPath) {
|
|
2641
2687
|
renameSync(oldPath, newPath);
|
|
2642
2688
|
},
|
|
2643
|
-
remove(
|
|
2644
|
-
rmSync(
|
|
2689
|
+
remove(path, recursive) {
|
|
2690
|
+
rmSync(path, { recursive, force: false });
|
|
2645
2691
|
}
|
|
2646
2692
|
};
|
|
2647
2693
|
function snapshotsEqual(expected, actual) {
|
|
@@ -2654,8 +2700,8 @@ function snapshotsEqual(expected, actual) {
|
|
|
2654
2700
|
}
|
|
2655
2701
|
return true;
|
|
2656
2702
|
}
|
|
2657
|
-
function liveSnapshot(
|
|
2658
|
-
return snapshotPath(
|
|
2703
|
+
function liveSnapshot(path, expected) {
|
|
2704
|
+
return snapshotPath(path, expected.kind === "directory" && expected.children !== undefined);
|
|
2659
2705
|
}
|
|
2660
2706
|
function firstOperationIndex(plan) {
|
|
2661
2707
|
return plan.operations[0]?.changeIndex ?? 0;
|
|
@@ -2676,28 +2722,28 @@ function failedCommit(plan, failure) {
|
|
|
2676
2722
|
};
|
|
2677
2723
|
}
|
|
2678
2724
|
function verifySnapshots(plan) {
|
|
2679
|
-
for (const [
|
|
2725
|
+
for (const [path, expected] of plan.snapshots) {
|
|
2680
2726
|
let actual;
|
|
2681
2727
|
try {
|
|
2682
|
-
actual = liveSnapshot(
|
|
2728
|
+
actual = liveSnapshot(path, expected);
|
|
2683
2729
|
} catch (error) {
|
|
2684
|
-
const changeIndex = plan.firstChangeByPath.get(
|
|
2730
|
+
const changeIndex = plan.firstChangeByPath.get(path) ?? firstOperationIndex(plan);
|
|
2685
2731
|
const detail = error instanceof Error ? error.message : String(error);
|
|
2686
|
-
return failedCommit(plan, { message: `cannot verify snapshot for ${
|
|
2732
|
+
return failedCommit(plan, { message: `cannot verify snapshot for ${path}: ${detail}`, changeIndex });
|
|
2687
2733
|
}
|
|
2688
2734
|
if (!snapshotsEqual(expected, actual)) {
|
|
2689
|
-
const changeIndex = plan.firstChangeByPath.get(
|
|
2690
|
-
return failedCommit(plan, { message: `workspace state changed before commit: ${
|
|
2735
|
+
const changeIndex = plan.firstChangeByPath.get(path) ?? firstOperationIndex(plan);
|
|
2736
|
+
return failedCommit(plan, { message: `workspace state changed before commit: ${path}`, changeIndex });
|
|
2691
2737
|
}
|
|
2692
2738
|
}
|
|
2693
2739
|
return null;
|
|
2694
2740
|
}
|
|
2695
|
-
function addModifiedPath(paths,
|
|
2696
|
-
if (!paths.includes(
|
|
2697
|
-
paths.push(
|
|
2741
|
+
function addModifiedPath(paths, path) {
|
|
2742
|
+
if (!paths.includes(path))
|
|
2743
|
+
paths.push(path);
|
|
2698
2744
|
}
|
|
2699
|
-
function reportedPath(plan,
|
|
2700
|
-
return plan.reportedPathByCanonical.get(
|
|
2745
|
+
function reportedPath(plan, path) {
|
|
2746
|
+
return plan.reportedPathByCanonical.get(path) ?? path;
|
|
2701
2747
|
}
|
|
2702
2748
|
function changedPathsForMutation(mutation) {
|
|
2703
2749
|
return mutation.kind === "rename" ? [mutation.oldPath, mutation.newPath] : [mutation.path];
|
|
@@ -2705,8 +2751,8 @@ function changedPathsForMutation(mutation) {
|
|
|
2705
2751
|
function mutationDelta(operations) {
|
|
2706
2752
|
const changedPaths = new Set;
|
|
2707
2753
|
for (const operation of operations) {
|
|
2708
|
-
for (const
|
|
2709
|
-
changedPaths.add(
|
|
2754
|
+
for (const path of changedPathsForMutation(operation))
|
|
2755
|
+
changedPaths.add(path);
|
|
2710
2756
|
}
|
|
2711
2757
|
return { operations, changedPaths: [...changedPaths].sort() };
|
|
2712
2758
|
}
|
|
@@ -2850,13 +2896,11 @@ function canonicalFingerprint(operations) {
|
|
|
2850
2896
|
|
|
2851
2897
|
// ../lsp-core/src/lsp/workspace-edit-types.ts
|
|
2852
2898
|
class WorkspaceEditValidationError extends Error {
|
|
2853
|
-
changeIndex;
|
|
2854
|
-
detail;
|
|
2855
|
-
name = "WorkspaceEditValidationError";
|
|
2856
2899
|
constructor(changeIndex, detail) {
|
|
2857
2900
|
super(`change ${changeIndex}: ${detail}`);
|
|
2858
2901
|
this.changeIndex = changeIndex;
|
|
2859
2902
|
this.detail = detail;
|
|
2903
|
+
this.name = "WorkspaceEditValidationError";
|
|
2860
2904
|
}
|
|
2861
2905
|
}
|
|
2862
2906
|
|
|
@@ -2942,14 +2986,14 @@ function parseSinglePathResource(input, kind) {
|
|
|
2942
2986
|
return;
|
|
2943
2987
|
}
|
|
2944
2988
|
if (kind === "create") {
|
|
2945
|
-
const
|
|
2989
|
+
const options = parseOptions(change["options"], ["overwrite", "ignoreIfExists"], changeIndex);
|
|
2946
2990
|
target.operations.push({
|
|
2947
2991
|
kind,
|
|
2948
2992
|
changeIndex,
|
|
2949
2993
|
path: resolvedPath.path,
|
|
2950
2994
|
reportedPath: resolvedPath.requestedPath,
|
|
2951
|
-
overwrite:
|
|
2952
|
-
ignoreIfExists:
|
|
2995
|
+
overwrite: options["overwrite"] ?? false,
|
|
2996
|
+
ignoreIfExists: options["ignoreIfExists"] ?? false,
|
|
2953
2997
|
followedSymbolicLink: resolvedPath.followedSymbolicLink
|
|
2954
2998
|
});
|
|
2955
2999
|
return;
|
|
@@ -3207,12 +3251,12 @@ function isSameOrDescendant2(candidate, parent) {
|
|
|
3207
3251
|
const relativePath = relative4(parent, candidate);
|
|
3208
3252
|
return relativePath === "" || !relativePath.startsWith("..") && relativePath !== "..";
|
|
3209
3253
|
}
|
|
3210
|
-
function removeVirtualSubtree(virtual,
|
|
3254
|
+
function removeVirtualSubtree(virtual, path) {
|
|
3211
3255
|
for (const candidate of [...virtual.keys()]) {
|
|
3212
|
-
if (isSameOrDescendant2(candidate,
|
|
3256
|
+
if (isSameOrDescendant2(candidate, path))
|
|
3213
3257
|
virtual.delete(candidate);
|
|
3214
3258
|
}
|
|
3215
|
-
virtual.set(
|
|
3259
|
+
virtual.set(path, { kind: "missing" });
|
|
3216
3260
|
}
|
|
3217
3261
|
function moveVirtualSubtree(virtual, oldPath, newPath) {
|
|
3218
3262
|
const moved = [...virtual.entries()].filter(([candidate]) => isSameOrDescendant2(candidate, oldPath));
|
|
@@ -3223,16 +3267,16 @@ function moveVirtualSubtree(virtual, oldPath, newPath) {
|
|
|
3223
3267
|
virtual.set(suffix === "" ? newPath : resolve4(newPath, suffix), entry);
|
|
3224
3268
|
}
|
|
3225
3269
|
}
|
|
3226
|
-
function virtualDirectoryHasChildren(virtual,
|
|
3270
|
+
function virtualDirectoryHasChildren(virtual, path) {
|
|
3227
3271
|
for (const [candidate, entry] of virtual) {
|
|
3228
|
-
if (candidate !==
|
|
3272
|
+
if (candidate !== path && entry.kind !== "missing" && isSameOrDescendant2(candidate, path))
|
|
3229
3273
|
return true;
|
|
3230
3274
|
}
|
|
3231
3275
|
return false;
|
|
3232
3276
|
}
|
|
3233
|
-
function requireVirtualParent(virtual,
|
|
3234
|
-
if (virtual.get(dirname5(
|
|
3235
|
-
throw new WorkspaceEditValidationError(changeIndex, `parent directory does not exist for ${
|
|
3277
|
+
function requireVirtualParent(virtual, path, changeIndex) {
|
|
3278
|
+
if (virtual.get(dirname5(path))?.kind !== "directory") {
|
|
3279
|
+
throw new WorkspaceEditValidationError(changeIndex, `parent directory does not exist for ${path}`);
|
|
3236
3280
|
}
|
|
3237
3281
|
}
|
|
3238
3282
|
function simulateOperations(parsed, snapshots) {
|
|
@@ -3354,10 +3398,9 @@ function simulateDelete(operation, virtual) {
|
|
|
3354
3398
|
import { existsSync as existsSync6, lstatSync as lstatSync4, readdirSync as readdirSync2 } from "node:fs";
|
|
3355
3399
|
import { dirname as dirname6, resolve as resolve5 } from "node:path";
|
|
3356
3400
|
class WorkspaceSnapshotBuilder {
|
|
3357
|
-
workspaceRoot;
|
|
3358
|
-
snapshots = new Map;
|
|
3359
3401
|
constructor(workspaceRoot) {
|
|
3360
3402
|
this.workspaceRoot = workspaceRoot;
|
|
3403
|
+
this.snapshots = new Map;
|
|
3361
3404
|
}
|
|
3362
3405
|
build(operations) {
|
|
3363
3406
|
this.add(this.workspaceRoot, false);
|
|
@@ -3378,21 +3421,21 @@ class WorkspaceSnapshotBuilder {
|
|
|
3378
3421
|
}
|
|
3379
3422
|
return this.snapshots;
|
|
3380
3423
|
}
|
|
3381
|
-
add(
|
|
3382
|
-
let candidate =
|
|
3424
|
+
add(path, includeChildren) {
|
|
3425
|
+
let candidate = path;
|
|
3383
3426
|
while (true) {
|
|
3384
3427
|
const existing = this.snapshots.get(candidate);
|
|
3385
3428
|
if (existing === undefined || includeChildren && existing.kind === "directory" && existing.children === undefined) {
|
|
3386
|
-
this.snapshots.set(candidate, snapshotPath(candidate, includeChildren && candidate ===
|
|
3429
|
+
this.snapshots.set(candidate, snapshotPath(candidate, includeChildren && candidate === path));
|
|
3387
3430
|
}
|
|
3388
3431
|
if (candidate === this.workspaceRoot)
|
|
3389
3432
|
break;
|
|
3390
3433
|
candidate = dirname6(candidate);
|
|
3391
3434
|
}
|
|
3392
|
-
if (!includeChildren || !existsSync6(
|
|
3435
|
+
if (!includeChildren || !existsSync6(path) || !lstatSync4(path).isDirectory())
|
|
3393
3436
|
return;
|
|
3394
|
-
for (const child of readdirSync2(
|
|
3395
|
-
this.add(resolve5(
|
|
3437
|
+
for (const child of readdirSync2(path))
|
|
3438
|
+
this.add(resolve5(path, child), true);
|
|
3396
3439
|
}
|
|
3397
3440
|
}
|
|
3398
3441
|
function snapshotOperations(operations, workspaceRoot) {
|
|
@@ -3401,8 +3444,10 @@ function snapshotOperations(operations, workspaceRoot) {
|
|
|
3401
3444
|
|
|
3402
3445
|
// ../lsp-core/src/lsp/workspace-edit-plan.ts
|
|
3403
3446
|
class PlanPathIndex {
|
|
3404
|
-
|
|
3405
|
-
|
|
3447
|
+
constructor() {
|
|
3448
|
+
this.firstChangeByPath = new Map;
|
|
3449
|
+
this.reportedPathByCanonical = new Map;
|
|
3450
|
+
}
|
|
3406
3451
|
build(operations) {
|
|
3407
3452
|
for (const operation of operations) {
|
|
3408
3453
|
switch (operation.kind) {
|
|
@@ -3418,11 +3463,11 @@ class PlanPathIndex {
|
|
|
3418
3463
|
}
|
|
3419
3464
|
}
|
|
3420
3465
|
}
|
|
3421
|
-
add(
|
|
3422
|
-
if (!this.firstChangeByPath.has(
|
|
3423
|
-
this.firstChangeByPath.set(
|
|
3424
|
-
if (!this.reportedPathByCanonical.has(
|
|
3425
|
-
this.reportedPathByCanonical.set(
|
|
3466
|
+
add(path, reportedPath, changeIndex) {
|
|
3467
|
+
if (!this.firstChangeByPath.has(path))
|
|
3468
|
+
this.firstChangeByPath.set(path, changeIndex);
|
|
3469
|
+
if (!this.reportedPathByCanonical.has(path))
|
|
3470
|
+
this.reportedPathByCanonical.set(path, reportedPath);
|
|
3426
3471
|
}
|
|
3427
3472
|
}
|
|
3428
3473
|
function fingerprintWorkspaceEdit(edit, workspaceRoot) {
|
|
@@ -3491,14 +3536,11 @@ function isRecord4(value) {
|
|
|
3491
3536
|
}
|
|
3492
3537
|
|
|
3493
3538
|
class WorkspaceMutationController {
|
|
3494
|
-
workspaceRoot;
|
|
3495
|
-
documents;
|
|
3496
|
-
activeLease = null;
|
|
3497
|
-
nextLeaseId = 1;
|
|
3498
|
-
io;
|
|
3499
3539
|
constructor(workspaceRoot, documents) {
|
|
3500
3540
|
this.workspaceRoot = workspaceRoot;
|
|
3501
3541
|
this.documents = documents;
|
|
3542
|
+
this.activeLease = null;
|
|
3543
|
+
this.nextLeaseId = 1;
|
|
3502
3544
|
}
|
|
3503
3545
|
setIo(io) {
|
|
3504
3546
|
this.io = io;
|
|
@@ -3537,15 +3579,15 @@ class WorkspaceMutationController {
|
|
|
3537
3579
|
};
|
|
3538
3580
|
}
|
|
3539
3581
|
lease.phase = "applying";
|
|
3540
|
-
lease.applyCompletion = new Promise((
|
|
3541
|
-
lease.resolveApply =
|
|
3582
|
+
lease.applyCompletion = new Promise((resolve) => {
|
|
3583
|
+
lease.resolveApply = resolve;
|
|
3542
3584
|
});
|
|
3543
3585
|
const edit = isRecord4(params) ? params["edit"] : undefined;
|
|
3544
|
-
const
|
|
3545
|
-
lease.serverApply =
|
|
3586
|
+
const record = edit === undefined ? { fingerprint: null, result: failure("workspace/applyEdit params.edit is required", 0) } : await this.applyEdit(edit, lease);
|
|
3587
|
+
lease.serverApply = record;
|
|
3546
3588
|
lease.phase = "settled";
|
|
3547
3589
|
lease.resolveApply?.();
|
|
3548
|
-
return responseFor(
|
|
3590
|
+
return responseFor(record.result);
|
|
3549
3591
|
}
|
|
3550
3592
|
async reconcileRename(leaseToken, edit) {
|
|
3551
3593
|
const lease = this.requireActiveLease(leaseToken);
|
|
@@ -3561,16 +3603,16 @@ class WorkspaceMutationController {
|
|
|
3561
3603
|
const applied = await this.applyEdit(edit, lease);
|
|
3562
3604
|
return { edit, apply: applied.result };
|
|
3563
3605
|
}
|
|
3564
|
-
reconcileServerApply(
|
|
3606
|
+
reconcileServerApply(record, edit) {
|
|
3565
3607
|
if (!edit)
|
|
3566
|
-
return { edit, apply:
|
|
3608
|
+
return { edit, apply: record.result };
|
|
3567
3609
|
const fingerprint = fingerprintWorkspaceEdit(edit, this.workspaceRoot);
|
|
3568
|
-
if (fingerprint.success &&
|
|
3569
|
-
return { edit, apply:
|
|
3610
|
+
if (fingerprint.success && record.fingerprint !== null && fingerprint.fingerprint === record.fingerprint) {
|
|
3611
|
+
return { edit, apply: record.result };
|
|
3570
3612
|
}
|
|
3571
3613
|
return {
|
|
3572
3614
|
edit,
|
|
3573
|
-
apply: failure("rename result conflicts with server-applied workspace edit", 0,
|
|
3615
|
+
apply: failure("rename result conflicts with server-applied workspace edit", 0, record.result)
|
|
3574
3616
|
};
|
|
3575
3617
|
}
|
|
3576
3618
|
async applyEdit(edit, lease) {
|
|
@@ -3611,14 +3653,12 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
|
|
|
3611
3653
|
var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
|
|
3612
3654
|
|
|
3613
3655
|
class LspClient extends LspClientConnection {
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
diagnosticsFreshnessTimeoutMs;
|
|
3618
|
-
constructor(root, server2, options = {}) {
|
|
3619
|
-
super(root, server2, options);
|
|
3656
|
+
constructor(root, server, options = {}) {
|
|
3657
|
+
super(root, server, options);
|
|
3658
|
+
this.diagnosticPullErrors = [];
|
|
3620
3659
|
this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
|
|
3621
3660
|
this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
|
|
3661
|
+
timerProvider: this.timerProvider,
|
|
3622
3662
|
versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
|
|
3623
3663
|
});
|
|
3624
3664
|
this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
|
|
@@ -3671,6 +3711,18 @@ class LspClient extends LspClientConnection {
|
|
|
3671
3711
|
textDocument: { uri: pathToFileURL3(absPath).href }
|
|
3672
3712
|
}, options);
|
|
3673
3713
|
}
|
|
3714
|
+
async formatDocument(filePath, options, signal) {
|
|
3715
|
+
if (!this.isDocumentFormattingSupported())
|
|
3716
|
+
return null;
|
|
3717
|
+
const absPath = this.resolveWorkspacePath(filePath);
|
|
3718
|
+
await this.openFile(absPath);
|
|
3719
|
+
const requestOptions = signal === undefined ? {} : { signal };
|
|
3720
|
+
const edits = await this.sendRequest("textDocument/formatting", {
|
|
3721
|
+
textDocument: { uri: pathToFileURL3(absPath).href },
|
|
3722
|
+
options
|
|
3723
|
+
}, requestOptions);
|
|
3724
|
+
return edits ?? [];
|
|
3725
|
+
}
|
|
3674
3726
|
async workspaceSymbols(query, signal) {
|
|
3675
3727
|
const options = signal === undefined ? {} : { signal };
|
|
3676
3728
|
return this.sendRequest("workspace/symbol", { query }, options);
|
|
@@ -3710,7 +3762,7 @@ class LspClient extends LspClientConnection {
|
|
|
3710
3762
|
const absPath = this.resolveWorkspacePath(filePath);
|
|
3711
3763
|
const uri = pathToFileURL3(absPath).href;
|
|
3712
3764
|
await this.openFile(absPath);
|
|
3713
|
-
const deadlineAt =
|
|
3765
|
+
const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
|
|
3714
3766
|
for (;; ) {
|
|
3715
3767
|
signal?.throwIfAborted();
|
|
3716
3768
|
const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
|
|
@@ -3723,13 +3775,13 @@ class LspClient extends LspClientConnection {
|
|
|
3723
3775
|
if (!pushFallbackOnly) {
|
|
3724
3776
|
const cached = this.documents.getPullCache(snapshot);
|
|
3725
3777
|
try {
|
|
3726
|
-
const
|
|
3727
|
-
if (
|
|
3778
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
3779
|
+
if (remainingMs <= 0)
|
|
3728
3780
|
return this.freshnessTimeout(absPath);
|
|
3729
3781
|
const result = await this.sendRequest("textDocument/diagnostic", {
|
|
3730
3782
|
textDocument: { uri },
|
|
3731
3783
|
...cached?.resultId === undefined ? {} : { previousResultId: cached.resultId }
|
|
3732
|
-
}, { timeoutMs:
|
|
3784
|
+
}, { timeoutMs: remainingMs, ...signal === undefined ? {} : { signal } });
|
|
3733
3785
|
if (!this.documents.isCurrentSnapshot(snapshot))
|
|
3734
3786
|
continue;
|
|
3735
3787
|
const report = this.parseDiagnosticPullReport(result);
|
|
@@ -3758,7 +3810,7 @@ class LspClient extends LspClientConnection {
|
|
|
3758
3810
|
}
|
|
3759
3811
|
if (!pushFallbackOnly)
|
|
3760
3812
|
continue;
|
|
3761
|
-
const remainingMs = deadlineAt -
|
|
3813
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
3762
3814
|
if (remainingMs <= 0) {
|
|
3763
3815
|
if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
|
|
3764
3816
|
const cached = this.documents.getPullCache(snapshot);
|
|
@@ -3810,7 +3862,7 @@ function waitForDiagnosticsActivity(wait, signal) {
|
|
|
3810
3862
|
return wait;
|
|
3811
3863
|
if (signal.aborted)
|
|
3812
3864
|
return Promise.reject(abortError3(signal));
|
|
3813
|
-
return new Promise((
|
|
3865
|
+
return new Promise((resolve, reject) => {
|
|
3814
3866
|
const onAbort = () => {
|
|
3815
3867
|
signal.removeEventListener("abort", onAbort);
|
|
3816
3868
|
reject(abortError3(signal));
|
|
@@ -3818,7 +3870,7 @@ function waitForDiagnosticsActivity(wait, signal) {
|
|
|
3818
3870
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
3819
3871
|
wait.then(() => {
|
|
3820
3872
|
signal.removeEventListener("abort", onAbort);
|
|
3821
|
-
|
|
3873
|
+
resolve();
|
|
3822
3874
|
}, (error) => {
|
|
3823
3875
|
signal.removeEventListener("abort", onAbort);
|
|
3824
3876
|
reject(error);
|
|
@@ -3886,7 +3938,7 @@ async function stopClientBestEffort(client) {
|
|
|
3886
3938
|
function awaitWithSignal2(promise, signal) {
|
|
3887
3939
|
if (!signal)
|
|
3888
3940
|
return promise;
|
|
3889
|
-
return new Promise((
|
|
3941
|
+
return new Promise((resolve, reject) => {
|
|
3890
3942
|
let settled = false;
|
|
3891
3943
|
const onAbort = () => {
|
|
3892
3944
|
if (settled)
|
|
@@ -3904,7 +3956,7 @@ function awaitWithSignal2(promise, signal) {
|
|
|
3904
3956
|
return;
|
|
3905
3957
|
settled = true;
|
|
3906
3958
|
signal.removeEventListener("abort", onAbort);
|
|
3907
|
-
|
|
3959
|
+
resolve(value);
|
|
3908
3960
|
}, (err) => {
|
|
3909
3961
|
if (settled)
|
|
3910
3962
|
return;
|
|
@@ -3916,20 +3968,18 @@ function awaitWithSignal2(promise, signal) {
|
|
|
3916
3968
|
}
|
|
3917
3969
|
|
|
3918
3970
|
class LspManager {
|
|
3919
|
-
clients = new Map;
|
|
3920
|
-
reaperHandle = null;
|
|
3921
|
-
signalDisposer = null;
|
|
3922
|
-
disposed = false;
|
|
3923
|
-
idleTimeoutMs;
|
|
3924
|
-
initTimeoutMs;
|
|
3925
|
-
reaperIntervalMs;
|
|
3926
|
-
clientFactory;
|
|
3927
|
-
now;
|
|
3928
3971
|
constructor(options = {}) {
|
|
3972
|
+
this.clients = new Map;
|
|
3973
|
+
this.pendingStops = new Map;
|
|
3974
|
+
this.respawnBudgets = new Map;
|
|
3975
|
+
this.reaperHandle = null;
|
|
3976
|
+
this.signalDisposer = null;
|
|
3977
|
+
this.disposed = false;
|
|
3929
3978
|
this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
|
|
3930
3979
|
this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
3980
|
+
this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
|
|
3931
3981
|
this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
|
|
3932
|
-
this.clientFactory = options.clientFactory ?? ((root,
|
|
3982
|
+
this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
|
|
3933
3983
|
this.now = options.now ?? (() => Date.now());
|
|
3934
3984
|
this.startReaper();
|
|
3935
3985
|
this.signalDisposer = installProcessSignalCleanup(() => this.stopAll());
|
|
@@ -3947,38 +3997,103 @@ class LspManager {
|
|
|
3947
3997
|
getKey(root, serverId) {
|
|
3948
3998
|
return `${root}::${serverId}`;
|
|
3949
3999
|
}
|
|
4000
|
+
tombstoneStop(key, client) {
|
|
4001
|
+
const stop = stopClientBestEffort(client);
|
|
4002
|
+
this.pendingStops.set(key, stop);
|
|
4003
|
+
stop.finally(() => {
|
|
4004
|
+
if (this.pendingStops.get(key) === stop) {
|
|
4005
|
+
this.pendingStops.delete(key);
|
|
4006
|
+
}
|
|
4007
|
+
});
|
|
4008
|
+
return stop;
|
|
4009
|
+
}
|
|
4010
|
+
recordDeadGeneration(key) {
|
|
4011
|
+
let budget = this.respawnBudgets.get(key);
|
|
4012
|
+
if (budget === undefined) {
|
|
4013
|
+
budget = { deadGenerations: 0, exhaustedAt: null };
|
|
4014
|
+
this.respawnBudgets.set(key, budget);
|
|
4015
|
+
}
|
|
4016
|
+
budget.deadGenerations += 1;
|
|
4017
|
+
}
|
|
4018
|
+
markHealthyGeneration(key) {
|
|
4019
|
+
this.respawnBudgets.delete(key);
|
|
4020
|
+
}
|
|
4021
|
+
ensureRespawnAllowed(key, root, serverId) {
|
|
4022
|
+
const budget = this.respawnBudgets.get(key);
|
|
4023
|
+
if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
|
|
4024
|
+
return;
|
|
4025
|
+
if (budget.exhaustedAt === null) {
|
|
4026
|
+
budget.exhaustedAt = this.now();
|
|
4027
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
4028
|
+
}
|
|
4029
|
+
if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
|
|
4030
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
4031
|
+
}
|
|
4032
|
+
budget.deadGenerations = 0;
|
|
4033
|
+
budget.exhaustedAt = null;
|
|
4034
|
+
}
|
|
3950
4035
|
reapStale() {
|
|
3951
4036
|
const t = this.now();
|
|
3952
4037
|
for (const [key, managed] of this.clients) {
|
|
3953
4038
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3954
|
-
stopClientBestEffort(managed.client);
|
|
3955
4039
|
this.clients.delete(key);
|
|
4040
|
+
this.tombstoneStop(key, managed.client);
|
|
3956
4041
|
continue;
|
|
3957
4042
|
}
|
|
3958
4043
|
if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
|
|
3959
|
-
stopClientBestEffort(managed.client);
|
|
3960
4044
|
this.clients.delete(key);
|
|
4045
|
+
this.tombstoneStop(key, managed.client);
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
evictForAdmission() {
|
|
4050
|
+
while (this.clients.size >= this.maxResidentClients) {
|
|
4051
|
+
const victim = this.leastRecentlyUsedIdleClient();
|
|
4052
|
+
if (!victim)
|
|
4053
|
+
return;
|
|
4054
|
+
this.clients.delete(victim.key);
|
|
4055
|
+
this.tombstoneStop(victim.key, victim.managed.client);
|
|
4056
|
+
}
|
|
4057
|
+
}
|
|
4058
|
+
leastRecentlyUsedIdleClient() {
|
|
4059
|
+
let candidate = null;
|
|
4060
|
+
for (const [key, managed] of this.clients) {
|
|
4061
|
+
if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
|
|
4062
|
+
continue;
|
|
4063
|
+
if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
|
|
4064
|
+
candidate = { key, managed };
|
|
3961
4065
|
}
|
|
3962
4066
|
}
|
|
4067
|
+
return candidate;
|
|
3963
4068
|
}
|
|
3964
4069
|
async tryDeleteIfOrphaned(key, managed) {
|
|
3965
4070
|
if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
|
|
3966
4071
|
this.clients.delete(key);
|
|
3967
|
-
await
|
|
4072
|
+
await this.tombstoneStop(key, managed.client);
|
|
3968
4073
|
}
|
|
3969
4074
|
}
|
|
3970
|
-
async getClient(root,
|
|
4075
|
+
async getClient(root, server, signal) {
|
|
3971
4076
|
if (this.disposed) {
|
|
3972
4077
|
throw new Error("LspManager has been disposed");
|
|
3973
4078
|
}
|
|
3974
4079
|
signal?.throwIfAborted();
|
|
3975
|
-
const key = this.getKey(root,
|
|
4080
|
+
const key = this.getKey(root, server.id);
|
|
4081
|
+
for (;; ) {
|
|
4082
|
+
const pendingStop = this.pendingStops.get(key);
|
|
4083
|
+
if (pendingStop === undefined)
|
|
4084
|
+
break;
|
|
4085
|
+
await awaitWithSignal2(pendingStop, signal);
|
|
4086
|
+
signal?.throwIfAborted();
|
|
4087
|
+
}
|
|
4088
|
+
if (this.disposed) {
|
|
4089
|
+
throw new Error("LspManager has been disposed");
|
|
4090
|
+
}
|
|
3976
4091
|
let managed = this.clients.get(key);
|
|
3977
4092
|
if (managed) {
|
|
3978
4093
|
const t = this.now();
|
|
3979
4094
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3980
|
-
await stopClientBestEffort(managed.client);
|
|
3981
4095
|
this.clients.delete(key);
|
|
4096
|
+
await this.tombstoneStop(key, managed.client);
|
|
3982
4097
|
managed = undefined;
|
|
3983
4098
|
}
|
|
3984
4099
|
}
|
|
@@ -3999,15 +4114,21 @@ class LspManager {
|
|
|
3999
4114
|
signal.throwIfAborted();
|
|
4000
4115
|
}
|
|
4001
4116
|
if (!managed.client.isAlive()) {
|
|
4002
|
-
|
|
4003
|
-
this.clients.
|
|
4004
|
-
|
|
4117
|
+
this.recordDeadGeneration(key);
|
|
4118
|
+
if (this.clients.get(key) === managed) {
|
|
4119
|
+
this.clients.delete(key);
|
|
4120
|
+
}
|
|
4121
|
+
await this.tombstoneStop(key, managed.client);
|
|
4122
|
+
return this.getClient(root, server, signal);
|
|
4005
4123
|
}
|
|
4124
|
+
this.markHealthyGeneration(key);
|
|
4006
4125
|
managed.refCount++;
|
|
4007
4126
|
managed.lastUsedAt = this.now();
|
|
4008
4127
|
return managed.client;
|
|
4009
4128
|
}
|
|
4010
|
-
|
|
4129
|
+
this.evictForAdmission();
|
|
4130
|
+
this.ensureRespawnAllowed(key, root, server.id);
|
|
4131
|
+
const client = this.clientFactory(root, server);
|
|
4011
4132
|
const initStartedAt = this.now();
|
|
4012
4133
|
const initPromise = (async () => {
|
|
4013
4134
|
await client.start();
|
|
@@ -4030,7 +4151,7 @@ class LspManager {
|
|
|
4030
4151
|
if (this.clients.get(key) === newManaged) {
|
|
4031
4152
|
this.clients.delete(key);
|
|
4032
4153
|
}
|
|
4033
|
-
await
|
|
4154
|
+
await this.tombstoneStop(key, client);
|
|
4034
4155
|
throw err;
|
|
4035
4156
|
}
|
|
4036
4157
|
newManaged.pendingWaiters--;
|
|
@@ -4041,6 +4162,15 @@ class LspManager {
|
|
|
4041
4162
|
await this.tryDeleteIfOrphaned(key, newManaged);
|
|
4042
4163
|
signal.throwIfAborted();
|
|
4043
4164
|
}
|
|
4165
|
+
if (!client.isAlive()) {
|
|
4166
|
+
this.recordDeadGeneration(key);
|
|
4167
|
+
if (this.clients.get(key) === newManaged) {
|
|
4168
|
+
this.clients.delete(key);
|
|
4169
|
+
}
|
|
4170
|
+
await this.tombstoneStop(key, client);
|
|
4171
|
+
return this.getClient(root, server, signal);
|
|
4172
|
+
}
|
|
4173
|
+
this.markHealthyGeneration(key);
|
|
4044
4174
|
newManaged.refCount++;
|
|
4045
4175
|
newManaged.lastUsedAt = this.now();
|
|
4046
4176
|
return client;
|
|
@@ -4061,15 +4191,21 @@ class LspManager {
|
|
|
4061
4191
|
if (client && managed.client !== client)
|
|
4062
4192
|
return;
|
|
4063
4193
|
this.clients.delete(key);
|
|
4064
|
-
|
|
4194
|
+
this.tombstoneStop(key, managed.client);
|
|
4065
4195
|
}
|
|
4066
|
-
warmupClient(root,
|
|
4196
|
+
warmupClient(root, server) {
|
|
4067
4197
|
if (this.disposed)
|
|
4068
4198
|
return;
|
|
4069
|
-
const key = this.getKey(root,
|
|
4070
|
-
if (this.clients.has(key))
|
|
4199
|
+
const key = this.getKey(root, server.id);
|
|
4200
|
+
if (this.clients.has(key) || this.pendingStops.has(key))
|
|
4071
4201
|
return;
|
|
4072
|
-
|
|
4202
|
+
this.evictForAdmission();
|
|
4203
|
+
try {
|
|
4204
|
+
this.ensureRespawnAllowed(key, root, server.id);
|
|
4205
|
+
} catch {
|
|
4206
|
+
return;
|
|
4207
|
+
}
|
|
4208
|
+
const client = this.clientFactory(root, server);
|
|
4073
4209
|
const initStartedAt = this.now();
|
|
4074
4210
|
const initPromise = (async () => {
|
|
4075
4211
|
await client.start();
|
|
@@ -4094,7 +4230,7 @@ class LspManager {
|
|
|
4094
4230
|
if (this.clients.get(key) === managed) {
|
|
4095
4231
|
this.clients.delete(key);
|
|
4096
4232
|
}
|
|
4097
|
-
|
|
4233
|
+
this.tombstoneStop(key, client);
|
|
4098
4234
|
});
|
|
4099
4235
|
}
|
|
4100
4236
|
isServerInitializing(root, serverId) {
|
|
@@ -4138,8 +4274,11 @@ class LspManager {
|
|
|
4138
4274
|
for (const managed of this.clients.values()) {
|
|
4139
4275
|
stopPromises.push(stopClientBestEffort(managed.client));
|
|
4140
4276
|
}
|
|
4277
|
+
const tombstonedStops = [...this.pendingStops.values()];
|
|
4141
4278
|
this.clients.clear();
|
|
4142
|
-
|
|
4279
|
+
this.respawnBudgets.clear();
|
|
4280
|
+
await Promise.allSettled([...stopPromises, ...tombstonedStops]);
|
|
4281
|
+
this.pendingStops.clear();
|
|
4143
4282
|
}
|
|
4144
4283
|
}
|
|
4145
4284
|
var _defaultInstance = null;
|
|
@@ -4157,57 +4296,52 @@ async function disposeDefaultLspManager() {
|
|
|
4157
4296
|
}
|
|
4158
4297
|
}
|
|
4159
4298
|
|
|
4160
|
-
// ../lsp-core/src/lsp/
|
|
4161
|
-
import { existsSync as existsSync7,
|
|
4162
|
-
import { dirname as dirname7 } from "node:path";
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4299
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
4300
|
+
import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
|
|
4301
|
+
import { dirname as dirname7, join as join3 } from "node:path";
|
|
4302
|
+
|
|
4303
|
+
// ../lsp-core/src/lsp/workspace-markers.ts
|
|
4304
|
+
var GIT_WORKSPACE_MARKER = ".git";
|
|
4305
|
+
var PROJECT_WORKSPACE_MARKERS = [
|
|
4306
|
+
"package.json",
|
|
4307
|
+
"pyproject.toml",
|
|
4308
|
+
"Cargo.toml",
|
|
4309
|
+
"go.mod",
|
|
4310
|
+
"pom.xml",
|
|
4311
|
+
"build.gradle"
|
|
4312
|
+
];
|
|
4313
|
+
var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
|
|
4314
|
+
|
|
4315
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
4316
|
+
function findWorkspaceRootOutsideContext(directory) {
|
|
4317
|
+
const marked = nearestMarkedAncestor(directory);
|
|
4318
|
+
if (marked !== undefined)
|
|
4319
|
+
return marked;
|
|
4320
|
+
return realpathSync4(nearestExistingAncestor(directory));
|
|
4321
|
+
}
|
|
4322
|
+
function nearestMarkedAncestor(directory) {
|
|
4323
|
+
let current = directory;
|
|
4324
|
+
for (;; ) {
|
|
4325
|
+
if (existsSync7(current) && WORKSPACE_MARKERS.some((marker) => existsSync7(join3(current, marker)))) {
|
|
4326
|
+
return realpathSync4(current);
|
|
4327
|
+
}
|
|
4328
|
+
const parent = dirname7(current);
|
|
4329
|
+
if (parent === current)
|
|
4330
|
+
return;
|
|
4331
|
+
current = parent;
|
|
4175
4332
|
}
|
|
4176
4333
|
}
|
|
4177
|
-
function
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
}
|
|
4185
|
-
|
|
4186
|
-
return value === "declined" || value === "allowed";
|
|
4187
|
-
}
|
|
4188
|
-
function writeInstallDecisions(decisions) {
|
|
4189
|
-
const path2 = getInstallDecisionsPath();
|
|
4190
|
-
mkdirSync3(dirname7(path2), { recursive: true });
|
|
4191
|
-
const tmpPath = `${path2}.tmp`;
|
|
4192
|
-
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
4193
|
-
`, "utf8");
|
|
4194
|
-
renameSync2(tmpPath, path2);
|
|
4195
|
-
}
|
|
4196
|
-
function isInstallDecisions(value) {
|
|
4197
|
-
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
4198
|
-
}
|
|
4199
|
-
function isInstallDecisionRecord(value) {
|
|
4200
|
-
if (!isRecord5(value))
|
|
4201
|
-
return false;
|
|
4202
|
-
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
4203
|
-
}
|
|
4204
|
-
function isRecord5(value) {
|
|
4205
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4334
|
+
function nearestExistingAncestor(directory) {
|
|
4335
|
+
let current = directory;
|
|
4336
|
+
while (!existsSync7(current)) {
|
|
4337
|
+
const parent = dirname7(current);
|
|
4338
|
+
if (parent === current)
|
|
4339
|
+
return current;
|
|
4340
|
+
current = parent;
|
|
4341
|
+
}
|
|
4342
|
+
return current;
|
|
4206
4343
|
}
|
|
4207
4344
|
|
|
4208
|
-
// ../lsp-core/src/lsp/config-loader.ts
|
|
4209
|
-
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
|
|
4210
|
-
|
|
4211
4345
|
// ../lsp-core/src/lsp/server-definitions.ts
|
|
4212
4346
|
var LSP_INSTALL_HINTS = {
|
|
4213
4347
|
typescript: "npm install -g typescript-language-server typescript",
|
|
@@ -4253,6 +4387,26 @@ var LSP_INSTALL_HINTS = {
|
|
|
4253
4387
|
julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
|
|
4254
4388
|
razor: "Razor runs through the Roslyn language server (cohosting). " + "Install: dotnet tool install -g roslyn-language-server --prerelease (requires v5.8.0+). See https://github.com/dotnet/razor"
|
|
4255
4389
|
};
|
|
4390
|
+
var LSP_LOCAL_INSTALL_HINTS = {
|
|
4391
|
+
typescript: "bun add -d typescript-language-server typescript",
|
|
4392
|
+
vue: "bun add -d @vue/language-server",
|
|
4393
|
+
eslint: "bun add -d vscode-langservers-extracted",
|
|
4394
|
+
oxlint: "bun add -d oxlint",
|
|
4395
|
+
biome: "bun add -d @biomejs/biome",
|
|
4396
|
+
svelte: "bun add -d svelte-language-server",
|
|
4397
|
+
astro: "bun add -d @astrojs/language-server",
|
|
4398
|
+
bash: "bun add -d bash-language-server",
|
|
4399
|
+
"bash-ls": "bun add -d bash-language-server",
|
|
4400
|
+
"yaml-ls": "bun add -d yaml-language-server",
|
|
4401
|
+
php: "bun add -d intelephense",
|
|
4402
|
+
prisma: "bun add -d prisma",
|
|
4403
|
+
dockerfile: "bun add -d dockerfile-language-server-nodejs",
|
|
4404
|
+
pyright: "uv add --dev pyright",
|
|
4405
|
+
basedpyright: "uv add --dev basedpyright",
|
|
4406
|
+
ruff: "uv add --dev ruff",
|
|
4407
|
+
ty: "uv add --dev ty",
|
|
4408
|
+
"ruby-lsp": "bundle add ruby-lsp --group development"
|
|
4409
|
+
};
|
|
4256
4410
|
var BUILTIN_SERVERS = {
|
|
4257
4411
|
typescript: {
|
|
4258
4412
|
command: ["typescript-language-server", "--stdio"],
|
|
@@ -4355,18 +4509,67 @@ var BUILTIN_SERVERS = {
|
|
|
4355
4509
|
}
|
|
4356
4510
|
};
|
|
4357
4511
|
|
|
4512
|
+
// ../lsp-core/src/lsp/server-install-state.ts
|
|
4513
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
4514
|
+
import { dirname as dirname8 } from "node:path";
|
|
4515
|
+
function getInstallDecisionsPath() {
|
|
4516
|
+
return lspRequestContext().installDecisionsPath;
|
|
4517
|
+
}
|
|
4518
|
+
function loadInstallDecisions() {
|
|
4519
|
+
const path = getInstallDecisionsPath();
|
|
4520
|
+
if (!existsSync8(path))
|
|
4521
|
+
return {};
|
|
4522
|
+
try {
|
|
4523
|
+
const parsed = JSON.parse(readFileSync4(path, "utf8"));
|
|
4524
|
+
return isInstallDecisions(parsed) ? parsed : {};
|
|
4525
|
+
} catch {
|
|
4526
|
+
return {};
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
function loadInstallDecision(serverId) {
|
|
4530
|
+
return loadInstallDecisions()[serverId];
|
|
4531
|
+
}
|
|
4532
|
+
function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
|
|
4533
|
+
const decisions = loadInstallDecisions();
|
|
4534
|
+
decisions[serverId] = { decision, decidedAt };
|
|
4535
|
+
writeInstallDecisions(decisions);
|
|
4536
|
+
}
|
|
4537
|
+
function isInstallDecision(value) {
|
|
4538
|
+
return value === "declined" || value === "allowed";
|
|
4539
|
+
}
|
|
4540
|
+
function writeInstallDecisions(decisions) {
|
|
4541
|
+
const path = getInstallDecisionsPath();
|
|
4542
|
+
mkdirSync3(dirname8(path), { recursive: true });
|
|
4543
|
+
const tmpPath = `${path}.tmp`;
|
|
4544
|
+
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
4545
|
+
`, "utf8");
|
|
4546
|
+
renameSync2(tmpPath, path);
|
|
4547
|
+
}
|
|
4548
|
+
function isInstallDecisions(value) {
|
|
4549
|
+
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
4550
|
+
}
|
|
4551
|
+
function isInstallDecisionRecord(value) {
|
|
4552
|
+
if (!isRecord5(value))
|
|
4553
|
+
return false;
|
|
4554
|
+
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
4555
|
+
}
|
|
4556
|
+
function isRecord5(value) {
|
|
4557
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4558
|
+
}
|
|
4559
|
+
|
|
4358
4560
|
// ../lsp-core/src/lsp/config-loader.ts
|
|
4561
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
|
|
4359
4562
|
function getProjectConfigPaths() {
|
|
4360
4563
|
return lspRequestContext().projectConfigPaths;
|
|
4361
4564
|
}
|
|
4362
4565
|
function getUserConfigPath() {
|
|
4363
4566
|
return lspRequestContext().userConfigPath;
|
|
4364
4567
|
}
|
|
4365
|
-
function loadJsonFile(
|
|
4366
|
-
if (!
|
|
4568
|
+
function loadJsonFile(path) {
|
|
4569
|
+
if (!existsSync9(path))
|
|
4367
4570
|
return null;
|
|
4368
4571
|
try {
|
|
4369
|
-
const parsed = JSON.parse(readFileSync5(
|
|
4572
|
+
const parsed = JSON.parse(readFileSync5(path, "utf-8"));
|
|
4370
4573
|
return isConfigJson(parsed) ? parsed : null;
|
|
4371
4574
|
} catch {
|
|
4372
4575
|
return null;
|
|
@@ -4383,8 +4586,8 @@ function loadAllConfigs() {
|
|
|
4383
4586
|
return configs;
|
|
4384
4587
|
}
|
|
4385
4588
|
function loadFirstJsonFile(paths) {
|
|
4386
|
-
for (const
|
|
4387
|
-
const config = loadJsonFile(
|
|
4589
|
+
for (const path of paths) {
|
|
4590
|
+
const config = loadJsonFile(path);
|
|
4388
4591
|
if (config)
|
|
4389
4592
|
return config;
|
|
4390
4593
|
}
|
|
@@ -4410,10 +4613,10 @@ function getMergedServers() {
|
|
|
4410
4613
|
}
|
|
4411
4614
|
if (seen.has(id))
|
|
4412
4615
|
continue;
|
|
4413
|
-
const
|
|
4414
|
-
if (!
|
|
4616
|
+
const server = createServerFromEntry(id, entry, source);
|
|
4617
|
+
if (!server)
|
|
4415
4618
|
continue;
|
|
4416
|
-
servers.push(
|
|
4619
|
+
servers.push(server);
|
|
4417
4620
|
seen.add(id);
|
|
4418
4621
|
}
|
|
4419
4622
|
}
|
|
@@ -4445,7 +4648,7 @@ function createServerFromEntry(id, entry, source) {
|
|
|
4445
4648
|
if (source === "project") {
|
|
4446
4649
|
if (!builtin)
|
|
4447
4650
|
return null;
|
|
4448
|
-
const
|
|
4651
|
+
const server = createServer({
|
|
4449
4652
|
id,
|
|
4450
4653
|
command: builtin.command,
|
|
4451
4654
|
extensions: entry.extensions ?? builtin.extensions,
|
|
@@ -4453,35 +4656,35 @@ function createServerFromEntry(id, entry, source) {
|
|
|
4453
4656
|
source
|
|
4454
4657
|
});
|
|
4455
4658
|
if (entry.initialization !== undefined) {
|
|
4456
|
-
|
|
4659
|
+
server.initialization = entry.initialization;
|
|
4457
4660
|
}
|
|
4458
|
-
return
|
|
4661
|
+
return server;
|
|
4459
4662
|
}
|
|
4460
4663
|
if (entry.command && entry.extensions) {
|
|
4461
|
-
const
|
|
4664
|
+
const server = createServer({
|
|
4462
4665
|
id,
|
|
4463
4666
|
command: entry.command,
|
|
4464
4667
|
extensions: entry.extensions,
|
|
4465
4668
|
priority: entry.priority ?? 0,
|
|
4466
4669
|
source
|
|
4467
4670
|
});
|
|
4468
|
-
applyOptionalServerFields(
|
|
4469
|
-
return
|
|
4671
|
+
applyOptionalServerFields(server, entry);
|
|
4672
|
+
return server;
|
|
4470
4673
|
}
|
|
4471
4674
|
if (!builtin)
|
|
4472
4675
|
return null;
|
|
4473
|
-
const
|
|
4676
|
+
const server = createServer({
|
|
4474
4677
|
id,
|
|
4475
4678
|
command: entry.command ?? builtin.command,
|
|
4476
4679
|
extensions: entry.extensions ?? builtin.extensions,
|
|
4477
4680
|
priority: entry.priority ?? 0,
|
|
4478
4681
|
source
|
|
4479
4682
|
});
|
|
4480
|
-
applyOptionalServerFields(
|
|
4481
|
-
return
|
|
4683
|
+
applyOptionalServerFields(server, entry);
|
|
4684
|
+
return server;
|
|
4482
4685
|
}
|
|
4483
4686
|
function createServer(input) {
|
|
4484
|
-
const
|
|
4687
|
+
const server = {
|
|
4485
4688
|
id: input.id,
|
|
4486
4689
|
command: input.command,
|
|
4487
4690
|
extensions: input.extensions,
|
|
@@ -4489,19 +4692,19 @@ function createServer(input) {
|
|
|
4489
4692
|
source: input.source
|
|
4490
4693
|
};
|
|
4491
4694
|
if (input.env !== undefined) {
|
|
4492
|
-
|
|
4695
|
+
server.env = input.env;
|
|
4493
4696
|
}
|
|
4494
4697
|
if (input.initialization !== undefined) {
|
|
4495
|
-
|
|
4698
|
+
server.initialization = input.initialization;
|
|
4496
4699
|
}
|
|
4497
|
-
return
|
|
4700
|
+
return server;
|
|
4498
4701
|
}
|
|
4499
|
-
function applyOptionalServerFields(
|
|
4702
|
+
function applyOptionalServerFields(server, entry) {
|
|
4500
4703
|
if (entry.env !== undefined) {
|
|
4501
|
-
|
|
4704
|
+
server.env = entry.env;
|
|
4502
4705
|
}
|
|
4503
4706
|
if (entry.initialization !== undefined) {
|
|
4504
|
-
|
|
4707
|
+
server.initialization = entry.initialization;
|
|
4505
4708
|
}
|
|
4506
4709
|
}
|
|
4507
4710
|
function isConfigJson(value) {
|
|
@@ -4551,64 +4754,165 @@ function getDisabledServerIds() {
|
|
|
4551
4754
|
}
|
|
4552
4755
|
|
|
4553
4756
|
// ../lsp-core/src/lsp/server-installation.ts
|
|
4554
|
-
import { existsSync as
|
|
4555
|
-
import { delimiter as delimiter3, join as
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4757
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
4758
|
+
import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
|
|
4759
|
+
var LOCAL_BIN_RULES = [
|
|
4760
|
+
{
|
|
4761
|
+
markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
|
|
4762
|
+
binDirs: [join4("node_modules", ".bin")]
|
|
4763
|
+
},
|
|
4764
|
+
{
|
|
4765
|
+
markers: [
|
|
4766
|
+
"pyproject.toml",
|
|
4767
|
+
"ty.toml",
|
|
4768
|
+
"requirements.txt",
|
|
4769
|
+
"setup.py",
|
|
4770
|
+
"setup.cfg",
|
|
4771
|
+
"Pipfile",
|
|
4772
|
+
"pyrightconfig.json",
|
|
4773
|
+
"ruff.toml",
|
|
4774
|
+
".ruff.toml"
|
|
4775
|
+
],
|
|
4776
|
+
binDirs: [
|
|
4777
|
+
join4(".venv", "bin"),
|
|
4778
|
+
join4(".venv", "Scripts"),
|
|
4779
|
+
join4("venv", "bin"),
|
|
4780
|
+
join4("venv", "Scripts"),
|
|
4781
|
+
join4(".env", "bin"),
|
|
4782
|
+
join4(".env", "Scripts")
|
|
4783
|
+
]
|
|
4784
|
+
},
|
|
4785
|
+
{
|
|
4786
|
+
markers: ["Gemfile", "Gemfile.lock"],
|
|
4787
|
+
binDirs: [join4("vendor", "bundle", "bin"), "bin"]
|
|
4788
|
+
},
|
|
4789
|
+
{
|
|
4790
|
+
markers: ["go.mod", "go.sum", "go.work"],
|
|
4791
|
+
binDirs: ["bin"]
|
|
4792
|
+
}
|
|
4793
|
+
];
|
|
4794
|
+
var resolutionCache = new Map;
|
|
4795
|
+
var probeCount = 0;
|
|
4796
|
+
function probe(path) {
|
|
4797
|
+
probeCount += 1;
|
|
4798
|
+
return existsSync10(path);
|
|
4799
|
+
}
|
|
4800
|
+
function executableSuffixes(platform, pathExt) {
|
|
4801
|
+
if (platform !== "win32")
|
|
4802
|
+
return [""];
|
|
4803
|
+
const configured = pathExt ?? process.env["PATHEXT"] ?? "";
|
|
4804
|
+
const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
|
|
4805
|
+
return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
|
|
4806
|
+
}
|
|
4807
|
+
function probeWithSuffixes(directory, command, suffixes) {
|
|
4808
|
+
for (const suffix of suffixes) {
|
|
4809
|
+
const candidate = join4(directory, command + suffix);
|
|
4810
|
+
if (probe(candidate))
|
|
4811
|
+
return candidate;
|
|
4565
4812
|
}
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4813
|
+
return null;
|
|
4814
|
+
}
|
|
4815
|
+
function resolveLocal(command, workingDirectory, suffixes, stopAt) {
|
|
4816
|
+
const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
|
|
4817
|
+
let current = resolve7(workingDirectory);
|
|
4818
|
+
while (true) {
|
|
4819
|
+
for (const rule of LOCAL_BIN_RULES) {
|
|
4820
|
+
if (!rule.markers.some((marker) => probe(join4(current, marker))))
|
|
4821
|
+
continue;
|
|
4822
|
+
for (const binDir of rule.binDirs) {
|
|
4823
|
+
const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
|
|
4824
|
+
if (found !== null)
|
|
4825
|
+
return found;
|
|
4826
|
+
}
|
|
4575
4827
|
}
|
|
4828
|
+
if (probe(join4(current, ".git")))
|
|
4829
|
+
return null;
|
|
4830
|
+
if (boundary !== undefined && current === boundary)
|
|
4831
|
+
return null;
|
|
4832
|
+
const parent = dirname9(current);
|
|
4833
|
+
if (parent === current)
|
|
4834
|
+
return null;
|
|
4835
|
+
current = parent;
|
|
4576
4836
|
}
|
|
4577
|
-
|
|
4578
|
-
|
|
4837
|
+
}
|
|
4838
|
+
function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
|
|
4839
|
+
let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
|
|
4840
|
+
if (platform === "win32" && !pathEnv) {
|
|
4579
4841
|
pathEnv = process.env["Path"] ?? "";
|
|
4580
4842
|
}
|
|
4581
|
-
const
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
}
|
|
4843
|
+
for (const entry of pathEnv.split(delimiter3)) {
|
|
4844
|
+
if (entry.length === 0)
|
|
4845
|
+
continue;
|
|
4846
|
+
const found = probeWithSuffixes(entry, command, suffixes);
|
|
4847
|
+
if (found !== null)
|
|
4848
|
+
return found;
|
|
4588
4849
|
}
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4850
|
+
return null;
|
|
4851
|
+
}
|
|
4852
|
+
function resolveServerBinary(command, workingDirectory, options = {}) {
|
|
4853
|
+
if (command.length === 0)
|
|
4854
|
+
return null;
|
|
4855
|
+
const [cmd] = command;
|
|
4856
|
+
if (cmd === undefined || cmd.length === 0)
|
|
4857
|
+
return null;
|
|
4858
|
+
const platform = options.platform ?? process.platform;
|
|
4859
|
+
const suffixes = executableSuffixes(platform, options.pathExt);
|
|
4860
|
+
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
4861
|
+
const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
|
|
4862
|
+
return probe(explicit) ? explicit : null;
|
|
4863
|
+
}
|
|
4864
|
+
const cacheKey = JSON.stringify([
|
|
4865
|
+
workingDirectory ?? "",
|
|
4866
|
+
cmd,
|
|
4867
|
+
platform,
|
|
4868
|
+
options.stopAt ?? "",
|
|
4869
|
+
options.pathExt ?? "",
|
|
4870
|
+
options.pathEnv ?? process.env["PATH"] ?? ""
|
|
4871
|
+
]);
|
|
4872
|
+
const cached = resolutionCache.get(cacheKey);
|
|
4873
|
+
if (cached !== undefined)
|
|
4874
|
+
return cached;
|
|
4875
|
+
let resolved = null;
|
|
4876
|
+
if (workingDirectory !== undefined && workingDirectory.length > 0) {
|
|
4877
|
+
resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
|
|
4878
|
+
}
|
|
4879
|
+
resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
|
|
4880
|
+
if (resolved === null && cmd === "node")
|
|
4881
|
+
resolved = cmd;
|
|
4882
|
+
resolutionCache.set(cacheKey, resolved);
|
|
4883
|
+
return resolved;
|
|
4884
|
+
}
|
|
4885
|
+
function isServerInstalled(command, workingDirectory, options = {}) {
|
|
4886
|
+
if (command.length === 0)
|
|
4887
|
+
return false;
|
|
4888
|
+
return resolveServerBinary(command, workingDirectory, options) !== null;
|
|
4592
4889
|
}
|
|
4593
4890
|
|
|
4594
4891
|
// ../lsp-core/src/lsp/server-resolution.ts
|
|
4892
|
+
function withResolvedCommand(command, binaryPath) {
|
|
4893
|
+
return [binaryPath, ...command.slice(1)];
|
|
4894
|
+
}
|
|
4595
4895
|
function findServerForExtension(ext) {
|
|
4596
4896
|
const servers = getMergedServers();
|
|
4597
|
-
|
|
4598
|
-
|
|
4897
|
+
const workingDirectory = contextCwd();
|
|
4898
|
+
for (const server of servers) {
|
|
4899
|
+
if (!server.extensions.includes(ext))
|
|
4900
|
+
continue;
|
|
4901
|
+
const binaryPath = resolveServerBinary(server.command, workingDirectory);
|
|
4902
|
+
if (binaryPath !== null) {
|
|
4599
4903
|
const resolvedServer = {
|
|
4600
|
-
id:
|
|
4601
|
-
command:
|
|
4602
|
-
extensions:
|
|
4603
|
-
priority:
|
|
4904
|
+
id: server.id,
|
|
4905
|
+
command: withResolvedCommand(server.command, binaryPath),
|
|
4906
|
+
extensions: server.extensions,
|
|
4907
|
+
priority: server.priority
|
|
4604
4908
|
};
|
|
4605
|
-
if (
|
|
4909
|
+
if (server.env !== undefined) {
|
|
4606
4910
|
return {
|
|
4607
4911
|
status: "found",
|
|
4608
4912
|
server: {
|
|
4609
4913
|
...resolvedServer,
|
|
4610
|
-
env:
|
|
4611
|
-
...
|
|
4914
|
+
env: server.env,
|
|
4915
|
+
...server.initialization === undefined ? {} : { initialization: server.initialization }
|
|
4612
4916
|
}
|
|
4613
4917
|
};
|
|
4614
4918
|
}
|
|
@@ -4616,20 +4920,20 @@ function findServerForExtension(ext) {
|
|
|
4616
4920
|
status: "found",
|
|
4617
4921
|
server: {
|
|
4618
4922
|
...resolvedServer,
|
|
4619
|
-
...
|
|
4923
|
+
...server.initialization === undefined ? {} : { initialization: server.initialization }
|
|
4620
4924
|
}
|
|
4621
4925
|
};
|
|
4622
4926
|
}
|
|
4623
4927
|
}
|
|
4624
|
-
for (const
|
|
4625
|
-
if (
|
|
4626
|
-
const installHint = LSP_INSTALL_HINTS[
|
|
4928
|
+
for (const server of servers) {
|
|
4929
|
+
if (server.extensions.includes(ext)) {
|
|
4930
|
+
const installHint = LSP_INSTALL_HINTS[server.id] ?? `Install '${server.command[0]}' and ensure it's in your PATH`;
|
|
4627
4931
|
return {
|
|
4628
4932
|
status: "not_installed",
|
|
4629
4933
|
server: {
|
|
4630
|
-
id:
|
|
4631
|
-
command:
|
|
4632
|
-
extensions:
|
|
4934
|
+
id: server.id,
|
|
4935
|
+
command: server.command,
|
|
4936
|
+
extensions: server.extensions
|
|
4633
4937
|
},
|
|
4634
4938
|
installHint
|
|
4635
4939
|
};
|
|
@@ -4645,20 +4949,21 @@ function findServerForExtension(ext) {
|
|
|
4645
4949
|
function getAllServers() {
|
|
4646
4950
|
const servers = getMergedServers();
|
|
4647
4951
|
const disabled = getDisabledServerIds();
|
|
4952
|
+
const workingDirectory = contextCwd();
|
|
4648
4953
|
const result = [];
|
|
4649
4954
|
const seen = new Set;
|
|
4650
|
-
for (const
|
|
4651
|
-
if (seen.has(
|
|
4955
|
+
for (const server of servers) {
|
|
4956
|
+
if (seen.has(server.id))
|
|
4652
4957
|
continue;
|
|
4653
4958
|
result.push({
|
|
4654
|
-
id:
|
|
4655
|
-
installed: isServerInstalled(
|
|
4656
|
-
extensions:
|
|
4959
|
+
id: server.id,
|
|
4960
|
+
installed: isServerInstalled(server.command, workingDirectory),
|
|
4961
|
+
extensions: server.extensions,
|
|
4657
4962
|
disabled: false,
|
|
4658
|
-
source:
|
|
4659
|
-
priority:
|
|
4963
|
+
source: server.source,
|
|
4964
|
+
priority: server.priority
|
|
4660
4965
|
});
|
|
4661
|
-
seen.add(
|
|
4966
|
+
seen.add(server.id);
|
|
4662
4967
|
}
|
|
4663
4968
|
for (const id of disabled) {
|
|
4664
4969
|
if (seen.has(id))
|
|
@@ -4666,7 +4971,7 @@ function getAllServers() {
|
|
|
4666
4971
|
const builtin = BUILTIN_SERVERS[id];
|
|
4667
4972
|
result.push({
|
|
4668
4973
|
id,
|
|
4669
|
-
installed: builtin ? isServerInstalled(builtin.command) : false,
|
|
4974
|
+
installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
|
|
4670
4975
|
extensions: builtin?.extensions ?? [],
|
|
4671
4976
|
disabled: true,
|
|
4672
4977
|
source: "disabled",
|
|
@@ -4677,7 +4982,6 @@ function getAllServers() {
|
|
|
4677
4982
|
}
|
|
4678
4983
|
|
|
4679
4984
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
4680
|
-
var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
4681
4985
|
function isDirectoryPath(filePath) {
|
|
4682
4986
|
try {
|
|
4683
4987
|
return statSync4(filePath).isDirectory();
|
|
@@ -4686,32 +4990,90 @@ function isDirectoryPath(filePath) {
|
|
|
4686
4990
|
}
|
|
4687
4991
|
}
|
|
4688
4992
|
function findWorkspaceRoot(filePath) {
|
|
4689
|
-
const
|
|
4993
|
+
const cwd = contextCwd();
|
|
4994
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4690
4995
|
let dir = abs;
|
|
4691
4996
|
if (!isDirectoryPath(dir)) {
|
|
4692
|
-
dir =
|
|
4693
|
-
}
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4997
|
+
dir = dirname10(dir);
|
|
4998
|
+
}
|
|
4999
|
+
if (!isPathInside(cwd, abs))
|
|
5000
|
+
return findWorkspaceRootOutsideContext(dir);
|
|
5001
|
+
const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
|
|
5002
|
+
let nearestPackageRoot;
|
|
5003
|
+
while (isPathInside(cwd, dir)) {
|
|
5004
|
+
const canonicalDir = existingDirectoryInsideContext(dir, cwd);
|
|
5005
|
+
if (canonicalDir !== undefined) {
|
|
5006
|
+
if (existsSync11(join5(dir, GIT_WORKSPACE_MARKER))) {
|
|
5007
|
+
return canonicalDir;
|
|
5008
|
+
}
|
|
5009
|
+
if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
|
|
5010
|
+
nearestPackageRoot = canonicalDir;
|
|
4699
5011
|
}
|
|
4700
5012
|
}
|
|
4701
|
-
|
|
4702
|
-
|
|
5013
|
+
if (dir === cwd)
|
|
5014
|
+
break;
|
|
5015
|
+
dir = dirname10(dir);
|
|
4703
5016
|
}
|
|
4704
|
-
return
|
|
5017
|
+
return nearestPackageRoot ?? fallbackRoot;
|
|
5018
|
+
}
|
|
5019
|
+
function hasProjectWorkspaceMarker(directory) {
|
|
5020
|
+
return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync11(join5(directory, marker)));
|
|
5021
|
+
}
|
|
5022
|
+
function resolveReadablePathInsideContext(filePath) {
|
|
5023
|
+
const cwd = contextCwd();
|
|
5024
|
+
const abs = resolve8(cwd, filePath);
|
|
5025
|
+
if (isPathInside(cwd, abs))
|
|
5026
|
+
return abs;
|
|
5027
|
+
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
5028
|
+
if (rebased !== undefined)
|
|
5029
|
+
return rebased;
|
|
5030
|
+
return canonicalizeExistingOrNearestAncestor(abs);
|
|
4705
5031
|
}
|
|
4706
5032
|
function resolvePathInsideContext(filePath) {
|
|
4707
5033
|
const cwd = contextCwd();
|
|
4708
|
-
const abs =
|
|
5034
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4709
5035
|
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
4710
5036
|
if (!isPathInside(cwd, canonical)) {
|
|
4711
5037
|
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4712
5038
|
}
|
|
4713
5039
|
return canonical;
|
|
4714
5040
|
}
|
|
5041
|
+
function rebaseThroughCanonicalAncestor(path, cwd) {
|
|
5042
|
+
let current = path;
|
|
5043
|
+
const suffix = [];
|
|
5044
|
+
while (true) {
|
|
5045
|
+
if (existsSync11(current)) {
|
|
5046
|
+
const canonical = realpathSync5(current);
|
|
5047
|
+
if (isPathInside(cwd, canonical))
|
|
5048
|
+
return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
|
|
5049
|
+
}
|
|
5050
|
+
const parent = dirname10(current);
|
|
5051
|
+
if (parent === current)
|
|
5052
|
+
return;
|
|
5053
|
+
suffix.unshift(basename3(current));
|
|
5054
|
+
current = parent;
|
|
5055
|
+
}
|
|
5056
|
+
}
|
|
5057
|
+
function existingDirectoryInsideContext(directory, cwd) {
|
|
5058
|
+
if (!existsSync11(directory))
|
|
5059
|
+
return;
|
|
5060
|
+
const canonical = realpathSync5(directory);
|
|
5061
|
+
if (!statSync4(canonical).isDirectory())
|
|
5062
|
+
return;
|
|
5063
|
+
return isPathInside(cwd, canonical) ? canonical : undefined;
|
|
5064
|
+
}
|
|
5065
|
+
function nearestExistingDirectoryInsideContext(directory, cwd) {
|
|
5066
|
+
let current = directory;
|
|
5067
|
+
while (isPathInside(cwd, current)) {
|
|
5068
|
+
const canonical = existingDirectoryInsideContext(current, cwd);
|
|
5069
|
+
if (canonical !== undefined)
|
|
5070
|
+
return canonical;
|
|
5071
|
+
if (current === cwd)
|
|
5072
|
+
return;
|
|
5073
|
+
current = dirname10(current);
|
|
5074
|
+
}
|
|
5075
|
+
return;
|
|
5076
|
+
}
|
|
4715
5077
|
function formatServerLookupError(result) {
|
|
4716
5078
|
if (result.status === "not_installed") {
|
|
4717
5079
|
return formatNotInstalled(result);
|
|
@@ -4735,33 +5097,46 @@ function formatServerLookupError(result) {
|
|
|
4735
5097
|
].join(`
|
|
4736
5098
|
`);
|
|
4737
5099
|
}
|
|
5100
|
+
function formatInstallOptions(serverId, installHint) {
|
|
5101
|
+
const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
|
|
5102
|
+
if (localHint === undefined) {
|
|
5103
|
+
return ["To install, run:", ` ${installHint}`];
|
|
5104
|
+
}
|
|
5105
|
+
return [
|
|
5106
|
+
"To install in THIS repository (preferred — no global install needed):",
|
|
5107
|
+
` ${localHint}`,
|
|
5108
|
+
"",
|
|
5109
|
+
"Or install it globally:",
|
|
5110
|
+
` ${installHint}`
|
|
5111
|
+
];
|
|
5112
|
+
}
|
|
4738
5113
|
function formatNotInstalled(result) {
|
|
4739
|
-
const { server
|
|
4740
|
-
const extensions =
|
|
4741
|
-
const decision = loadInstallDecision(
|
|
5114
|
+
const { server, installHint } = result;
|
|
5115
|
+
const extensions = server.extensions.join(", ");
|
|
5116
|
+
const decision = loadInstallDecision(server.id)?.decision;
|
|
4742
5117
|
const context = lspRequestContext();
|
|
4743
5118
|
if (decision === "declined") {
|
|
4744
|
-
return `LSP server '${
|
|
5119
|
+
return `LSP server '${server.id}' (${extensions}) is NOT INSTALLED; user previously declined installation — proceed without LSP.`;
|
|
4745
5120
|
}
|
|
4746
5121
|
const header = [
|
|
4747
|
-
`LSP server '${
|
|
5122
|
+
`LSP server '${server.id}' for ${extensions} is NOT INSTALLED.`,
|
|
4748
5123
|
"",
|
|
4749
|
-
`Command not found: ${
|
|
5124
|
+
`Command not found: ${server.command[0]}`,
|
|
4750
5125
|
""
|
|
4751
5126
|
];
|
|
5127
|
+
const installOptions = formatInstallOptions(server.id, installHint);
|
|
4752
5128
|
if (decision === "allowed") {
|
|
4753
5129
|
return [
|
|
4754
5130
|
...header,
|
|
4755
5131
|
"The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
|
|
4756
|
-
|
|
5132
|
+
...installOptions.slice(1)
|
|
4757
5133
|
].join(`
|
|
4758
5134
|
`);
|
|
4759
5135
|
}
|
|
4760
5136
|
if (!context.capabilities.installDecisionTool) {
|
|
4761
5137
|
return [
|
|
4762
5138
|
...header,
|
|
4763
|
-
|
|
4764
|
-
` ${installHint}`,
|
|
5139
|
+
...installOptions,
|
|
4765
5140
|
"",
|
|
4766
5141
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4767
5142
|
"Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
|
|
@@ -4770,19 +5145,18 @@ function formatNotInstalled(result) {
|
|
|
4770
5145
|
}
|
|
4771
5146
|
return [
|
|
4772
5147
|
...header,
|
|
4773
|
-
|
|
4774
|
-
` ${installHint}`,
|
|
5148
|
+
...installOptions,
|
|
4775
5149
|
"",
|
|
4776
5150
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4777
5151
|
"- If the user agrees: run the install command above, then retry this tool.",
|
|
4778
5152
|
"- If the user declines, OR has NOT explicitly asked for LSP installation:",
|
|
4779
|
-
` call lsp_install_decision { server_id: "${
|
|
5153
|
+
` call lsp_install_decision { server_id: "${server.id}", decision: "declined" },`,
|
|
4780
5154
|
` which writes to ${context.installDecisionsPath},`,
|
|
4781
5155
|
" then ignore this message and proceed WITHOUT LSP."
|
|
4782
5156
|
].join(`
|
|
4783
5157
|
`);
|
|
4784
5158
|
}
|
|
4785
|
-
var
|
|
5159
|
+
var READ_ONLY_TOOLS = new Set([
|
|
4786
5160
|
"diagnostics",
|
|
4787
5161
|
"definition",
|
|
4788
5162
|
"references",
|
|
@@ -4791,7 +5165,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
|
|
|
4791
5165
|
"prepareRename"
|
|
4792
5166
|
]);
|
|
4793
5167
|
async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
4794
|
-
const absPath = resolvePathInsideContext(filePath);
|
|
5168
|
+
const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
|
|
4795
5169
|
if (isDirectoryPath(absPath)) {
|
|
4796
5170
|
throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
|
|
4797
5171
|
}
|
|
@@ -4800,34 +5174,34 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4800
5174
|
if (result.status !== "found") {
|
|
4801
5175
|
throw new LspServerLookupError(formatServerLookupError(result), result);
|
|
4802
5176
|
}
|
|
4803
|
-
const
|
|
5177
|
+
const server = result.server;
|
|
4804
5178
|
const root = findWorkspaceRoot(absPath);
|
|
4805
5179
|
const manager = options.manager ?? getLspManager();
|
|
4806
5180
|
const acquireAndCall = async (allowRetry) => {
|
|
4807
|
-
const client = await manager.getClient(root,
|
|
5181
|
+
const client = await manager.getClient(root, server, options.signal);
|
|
4808
5182
|
try {
|
|
4809
|
-
return await fn(client, root);
|
|
5183
|
+
return await fn(client, root, absPath);
|
|
4810
5184
|
} catch (err) {
|
|
4811
|
-
if (allowRetry &&
|
|
4812
|
-
manager.invalidateClient(root,
|
|
5185
|
+
if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
|
|
5186
|
+
manager.invalidateClient(root, server.id, client);
|
|
4813
5187
|
return acquireAndCall(false);
|
|
4814
5188
|
}
|
|
4815
5189
|
if (err instanceof LspRequestTimeoutError) {
|
|
4816
|
-
if (manager.isServerInitializing(root,
|
|
5190
|
+
if (manager.isServerInitializing(root, server.id)) {
|
|
4817
5191
|
throw new LspServerInitializingError(err);
|
|
4818
5192
|
}
|
|
4819
5193
|
}
|
|
4820
5194
|
throw err;
|
|
4821
5195
|
} finally {
|
|
4822
|
-
manager.releaseClient(root,
|
|
5196
|
+
manager.releaseClient(root, server.id);
|
|
4823
5197
|
}
|
|
4824
5198
|
};
|
|
4825
5199
|
return acquireAndCall(true);
|
|
4826
5200
|
}
|
|
4827
5201
|
|
|
4828
5202
|
// ../lsp-core/src/lsp/directory-diagnostics.ts
|
|
4829
|
-
import { existsSync as
|
|
4830
|
-
import { join as
|
|
5203
|
+
import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
|
|
5204
|
+
import { join as join6, resolve as resolve9 } from "node:path";
|
|
4831
5205
|
|
|
4832
5206
|
// ../lsp-core/src/lsp/formatters.ts
|
|
4833
5207
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
@@ -4842,10 +5216,10 @@ function uriToPath(uri) {
|
|
|
4842
5216
|
}
|
|
4843
5217
|
function formatLocation(loc) {
|
|
4844
5218
|
if ("targetUri" in loc) {
|
|
4845
|
-
const
|
|
4846
|
-
const
|
|
4847
|
-
const
|
|
4848
|
-
return `${
|
|
5219
|
+
const uri = uriToPath(loc.targetUri);
|
|
5220
|
+
const line = loc.targetRange.start.line + 1;
|
|
5221
|
+
const char = loc.targetRange.start.character;
|
|
5222
|
+
return `${uri}:${line}:${char}`;
|
|
4849
5223
|
}
|
|
4850
5224
|
const uri = uriToPath(loc.uri);
|
|
4851
5225
|
const line = loc.range.start.line + 1;
|
|
@@ -4957,7 +5331,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
|
|
|
4957
5331
|
for (const entry of entries) {
|
|
4958
5332
|
if (files.length >= maxFiles)
|
|
4959
5333
|
return;
|
|
4960
|
-
const fullPath =
|
|
5334
|
+
const fullPath = join6(currentDir, entry);
|
|
4961
5335
|
let stat;
|
|
4962
5336
|
try {
|
|
4963
5337
|
stat = lstatSync5(fullPath);
|
|
@@ -4982,15 +5356,15 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4982
5356
|
if (!extension.startsWith(".")) {
|
|
4983
5357
|
throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
|
|
4984
5358
|
}
|
|
4985
|
-
const absDir =
|
|
4986
|
-
if (!
|
|
5359
|
+
const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
|
|
5360
|
+
if (!existsSync12(absDir)) {
|
|
4987
5361
|
throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
|
|
4988
5362
|
}
|
|
4989
5363
|
const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
|
|
4990
5364
|
if (serverResult.status !== "found") {
|
|
4991
5365
|
throw new LspServerLookupError(formatServerLookupError(serverResult));
|
|
4992
5366
|
}
|
|
4993
|
-
const
|
|
5367
|
+
const server = serverResult.server;
|
|
4994
5368
|
const allFiles = (options.listFiles ?? collectFilesWithExtension)(absDir, extension, maxFiles + 1);
|
|
4995
5369
|
const wasCapped = allFiles.length > maxFiles;
|
|
4996
5370
|
const filesToProcess = allFiles.slice(0, maxFiles);
|
|
@@ -5010,7 +5384,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
5010
5384
|
const fileErrors = [];
|
|
5011
5385
|
const maxConcurrency = Math.max(1, options.maxConcurrency ?? DIRECTORY_DIAGNOSTICS_MAX_CONCURRENCY);
|
|
5012
5386
|
options.signal?.throwIfAborted();
|
|
5013
|
-
const client = await manager.getClient(root,
|
|
5387
|
+
const client = await manager.getClient(root, server, options.signal);
|
|
5014
5388
|
try {
|
|
5015
5389
|
let nextIndex = 0;
|
|
5016
5390
|
const workers = Array.from({ length: Math.min(maxConcurrency, filesToProcess.length) }, async () => {
|
|
@@ -5038,7 +5412,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
5038
5412
|
});
|
|
5039
5413
|
await Promise.all(workers);
|
|
5040
5414
|
} finally {
|
|
5041
|
-
manager.releaseClient(root,
|
|
5415
|
+
manager.releaseClient(root, server.id);
|
|
5042
5416
|
}
|
|
5043
5417
|
const displayDiagnostics = allDiagnostics.slice(0, DEFAULT_MAX_DIAGNOSTICS);
|
|
5044
5418
|
const wasDiagCapped = allDiagnostics.length > DEFAULT_MAX_DIAGNOSTICS;
|
|
@@ -5070,7 +5444,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
5070
5444
|
|
|
5071
5445
|
// ../lsp-core/src/lsp/infer-extension.ts
|
|
5072
5446
|
import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
|
|
5073
|
-
import { join as
|
|
5447
|
+
import { join as join7 } from "node:path";
|
|
5074
5448
|
var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
|
|
5075
5449
|
var MAX_SCAN_ENTRIES = 500;
|
|
5076
5450
|
function inferExtensionFromDirectory(directory) {
|
|
@@ -5088,7 +5462,7 @@ function inferExtensionFromDirectory(directory) {
|
|
|
5088
5462
|
for (const entry of entries) {
|
|
5089
5463
|
if (scanned >= MAX_SCAN_ENTRIES)
|
|
5090
5464
|
return;
|
|
5091
|
-
const fullPath =
|
|
5465
|
+
const fullPath = join7(dir, entry);
|
|
5092
5466
|
let stat;
|
|
5093
5467
|
try {
|
|
5094
5468
|
stat = lstatSync6(fullPath);
|
|
@@ -5247,8 +5621,8 @@ function clientOptions(signal) {
|
|
|
5247
5621
|
}
|
|
5248
5622
|
|
|
5249
5623
|
// ../lsp-core/src/tools/result.ts
|
|
5250
|
-
function text(
|
|
5251
|
-
return { content: [{ type: "text", text
|
|
5624
|
+
function text(text, details, isError = false) {
|
|
5625
|
+
return { content: [{ type: "text", text }], details, isError };
|
|
5252
5626
|
}
|
|
5253
5627
|
|
|
5254
5628
|
// ../lsp-core/src/tools/diagnostics.ts
|
|
@@ -5263,12 +5637,12 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5263
5637
|
const filePath = requireString(params, "filePath");
|
|
5264
5638
|
const severity = severityFilter(params);
|
|
5265
5639
|
try {
|
|
5266
|
-
const absPath =
|
|
5640
|
+
const absPath = resolveReadablePathInsideContext(filePath);
|
|
5267
5641
|
if (isDirectoryPath(absPath)) {
|
|
5268
5642
|
const extension = inferExtensionFromDirectory(absPath);
|
|
5269
5643
|
if (!extension) {
|
|
5270
5644
|
const message = `No supported source files found in directory: ${absPath}`;
|
|
5271
|
-
const
|
|
5645
|
+
const details = {
|
|
5272
5646
|
filePath,
|
|
5273
5647
|
severity,
|
|
5274
5648
|
mode: "directory",
|
|
@@ -5278,24 +5652,24 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5278
5652
|
error: message,
|
|
5279
5653
|
errorKind: "no_files"
|
|
5280
5654
|
};
|
|
5281
|
-
return text(message,
|
|
5655
|
+
return text(message, details);
|
|
5282
5656
|
}
|
|
5283
|
-
const
|
|
5284
|
-
const
|
|
5657
|
+
const output = await aggregateDiagnosticsForDirectory(absPath, extension, severity, undefined, signal === undefined ? {} : { signal });
|
|
5658
|
+
const details = {
|
|
5285
5659
|
filePath,
|
|
5286
5660
|
severity,
|
|
5287
5661
|
mode: "directory",
|
|
5288
5662
|
diagnostics: [],
|
|
5289
|
-
totalDiagnostics:
|
|
5663
|
+
totalDiagnostics: output.totalDiagnostics,
|
|
5290
5664
|
truncated: false,
|
|
5291
|
-
fileFailures: [...
|
|
5665
|
+
fileFailures: [...output.fileFailures]
|
|
5292
5666
|
};
|
|
5293
|
-
return text(
|
|
5667
|
+
return text(output.output, details);
|
|
5294
5668
|
}
|
|
5295
|
-
const result = await withLspClient(filePath, async (client) => client.diagnostics(
|
|
5669
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
|
|
5296
5670
|
if (result.transientError) {
|
|
5297
5671
|
const message = result.transientError.message;
|
|
5298
|
-
const
|
|
5672
|
+
const details = {
|
|
5299
5673
|
filePath,
|
|
5300
5674
|
severity,
|
|
5301
5675
|
mode: "file",
|
|
@@ -5305,7 +5679,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5305
5679
|
error: message,
|
|
5306
5680
|
errorKind: result.transientError.kind
|
|
5307
5681
|
};
|
|
5308
|
-
return text(message,
|
|
5682
|
+
return text(message, details, true);
|
|
5309
5683
|
}
|
|
5310
5684
|
const diagnostics = filterDiagnosticsBySeverity(asDiagnosticArray(result), severity);
|
|
5311
5685
|
const total = diagnostics.length;
|
|
@@ -5339,6 +5713,96 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5339
5713
|
throw error;
|
|
5340
5714
|
}
|
|
5341
5715
|
}
|
|
5716
|
+
// ../lsp-core/src/lsp/format-document.ts
|
|
5717
|
+
import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
5718
|
+
var DEFAULT_FORMATTING_OPTIONS = {
|
|
5719
|
+
tabSize: 4,
|
|
5720
|
+
insertSpaces: false,
|
|
5721
|
+
trimTrailingWhitespace: true,
|
|
5722
|
+
insertFinalNewline: true,
|
|
5723
|
+
trimFinalNewlines: true
|
|
5724
|
+
};
|
|
5725
|
+
var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
|
|
5726
|
+
async function formatDocumentWithClient(client, filePath, options = {}) {
|
|
5727
|
+
const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
|
|
5728
|
+
if (edits === null)
|
|
5729
|
+
return { status: "unavailable", reason: "capability_not_advertised" };
|
|
5730
|
+
if (edits.length === 0)
|
|
5731
|
+
return UNCHANGED;
|
|
5732
|
+
const before = readFileSync6(filePath, "utf-8");
|
|
5733
|
+
const normalized = normalizeTextEdits(before, edits, 0);
|
|
5734
|
+
if (normalized.text === before)
|
|
5735
|
+
return UNCHANGED;
|
|
5736
|
+
writeAtomically(filePath, normalized.text);
|
|
5737
|
+
await client.openFile(filePath);
|
|
5738
|
+
return {
|
|
5739
|
+
status: "formatted",
|
|
5740
|
+
...lineDelta(normalized.edits)
|
|
5741
|
+
};
|
|
5742
|
+
}
|
|
5743
|
+
function lineDelta(edits) {
|
|
5744
|
+
let linesAdded = 0;
|
|
5745
|
+
let linesRemoved = 0;
|
|
5746
|
+
for (const edit of edits) {
|
|
5747
|
+
linesRemoved += edit.range.end.line - edit.range.start.line + 1;
|
|
5748
|
+
linesAdded += edit.newText.split(`
|
|
5749
|
+
`).length;
|
|
5750
|
+
}
|
|
5751
|
+
return { linesAdded, linesRemoved };
|
|
5752
|
+
}
|
|
5753
|
+
function writeAtomically(filePath, content) {
|
|
5754
|
+
const tempPath = `${filePath}.omo-format.tmp`;
|
|
5755
|
+
writeFileSync3(tempPath, content, "utf-8");
|
|
5756
|
+
try {
|
|
5757
|
+
renameSync3(tempPath, filePath);
|
|
5758
|
+
} catch (error) {
|
|
5759
|
+
try {
|
|
5760
|
+
unlinkSync2(tempPath);
|
|
5761
|
+
} catch {}
|
|
5762
|
+
throw error;
|
|
5763
|
+
}
|
|
5764
|
+
}
|
|
5765
|
+
|
|
5766
|
+
// ../lsp-core/src/tools/format.ts
|
|
5767
|
+
async function executeLspFormat(params, signal) {
|
|
5768
|
+
const filePath = requireString(params, "filePath");
|
|
5769
|
+
try {
|
|
5770
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
|
|
5771
|
+
return text(describeResult(filePath, result), formatDetails(filePath, result));
|
|
5772
|
+
} catch (error) {
|
|
5773
|
+
const missingDependency = missingDependencyResult(error, {
|
|
5774
|
+
filePath,
|
|
5775
|
+
status: "unavailable",
|
|
5776
|
+
reason: "server_unavailable",
|
|
5777
|
+
linesAdded: 0,
|
|
5778
|
+
linesRemoved: 0
|
|
5779
|
+
});
|
|
5780
|
+
if (missingDependency)
|
|
5781
|
+
return missingDependency;
|
|
5782
|
+
throw error;
|
|
5783
|
+
}
|
|
5784
|
+
}
|
|
5785
|
+
function formatDetails(filePath, result) {
|
|
5786
|
+
if (result.status === "unavailable") {
|
|
5787
|
+
return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
|
|
5788
|
+
}
|
|
5789
|
+
return {
|
|
5790
|
+
filePath,
|
|
5791
|
+
status: result.status,
|
|
5792
|
+
linesAdded: result.linesAdded,
|
|
5793
|
+
linesRemoved: result.linesRemoved
|
|
5794
|
+
};
|
|
5795
|
+
}
|
|
5796
|
+
function describeResult(filePath, result) {
|
|
5797
|
+
if (result.status === "unavailable") {
|
|
5798
|
+
return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
|
|
5799
|
+
}
|
|
5800
|
+
if (result.status === "unchanged") {
|
|
5801
|
+
return `Already formatted: ${filePath}`;
|
|
5802
|
+
}
|
|
5803
|
+
return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
|
|
5804
|
+
}
|
|
5805
|
+
|
|
5342
5806
|
// ../lsp-core/src/tools/install-decision.ts
|
|
5343
5807
|
async function executeLspInstallDecision(params) {
|
|
5344
5808
|
const serverId = requireString(params, "server_id");
|
|
@@ -5346,7 +5810,7 @@ async function executeLspInstallDecision(params) {
|
|
|
5346
5810
|
if (!isInstallDecision(decision)) {
|
|
5347
5811
|
return text(`Invalid decision '${String(decision)}'. Expected "declined" or "allowed".`, { serverId, errorKind: "invalid_decision" }, true);
|
|
5348
5812
|
}
|
|
5349
|
-
const serverIds = [...new Set(getMergedServers().map((
|
|
5813
|
+
const serverIds = [...new Set(getMergedServers().map((server) => server.id))];
|
|
5350
5814
|
if (!serverIds.includes(serverId)) {
|
|
5351
5815
|
const preview = serverIds.slice(0, 20).join(", ");
|
|
5352
5816
|
return text(`Unknown LSP server '${serverId}'. Known servers: ${preview}${serverIds.length > 20 ? "..." : ""}`, { serverId, errorKind: "unknown_server" }, true);
|
|
@@ -5367,7 +5831,7 @@ async function executeLspGotoDefinition(params, signal) {
|
|
|
5367
5831
|
const line = requireNumber(params, "line");
|
|
5368
5832
|
const character = requireNumber(params, "character");
|
|
5369
5833
|
try {
|
|
5370
|
-
const result = await withLspClient(filePath, async (client) => client.definition(
|
|
5834
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
|
|
5371
5835
|
const locations = !result ? [] : Array.isArray(result) ? result : [result];
|
|
5372
5836
|
const details = { filePath, line, character, locations };
|
|
5373
5837
|
if (locations.length === 0)
|
|
@@ -5392,7 +5856,7 @@ async function executeLspFindReferences(params, signal) {
|
|
|
5392
5856
|
const character = requireNumber(params, "character");
|
|
5393
5857
|
const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
|
|
5394
5858
|
try {
|
|
5395
|
-
const result = await withLspClient(filePath, async (client) => client.references(
|
|
5859
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
|
|
5396
5860
|
const references = Array.isArray(result) ? result : [];
|
|
5397
5861
|
const total = references.length;
|
|
5398
5862
|
const truncated = total > DEFAULT_MAX_REFERENCES;
|
|
@@ -5434,7 +5898,7 @@ async function executeLspPrepareRename(params, signal) {
|
|
|
5434
5898
|
const line = requireNumber(params, "line");
|
|
5435
5899
|
const character = requireNumber(params, "character");
|
|
5436
5900
|
try {
|
|
5437
|
-
const result = await withLspClient(filePath, async (client) => client.prepareRename(
|
|
5901
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
|
|
5438
5902
|
const details = { filePath, line, character, result };
|
|
5439
5903
|
return text(formatPrepareRenameResult(result), details);
|
|
5440
5904
|
} catch (error) {
|
|
@@ -5455,7 +5919,7 @@ async function executeLspRename(params, signal) {
|
|
|
5455
5919
|
const character = requireNumber(params, "character");
|
|
5456
5920
|
const newName = requireString(params, "newName");
|
|
5457
5921
|
try {
|
|
5458
|
-
const result = await withLspClient(filePath, async (client) => client.rename(
|
|
5922
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
|
|
5459
5923
|
const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
|
|
5460
5924
|
return text(formatApplyResult(result.apply), details, !result.apply.success);
|
|
5461
5925
|
} catch (error) {
|
|
@@ -5486,10 +5950,10 @@ function objectSchema(properties, required = []) {
|
|
|
5486
5950
|
async function executeLspStatus() {
|
|
5487
5951
|
const servers = getAllServers();
|
|
5488
5952
|
const snapshots = getLspManager().getSnapshot();
|
|
5489
|
-
const installed = servers.filter((
|
|
5490
|
-
const configuredLines = servers.map((
|
|
5491
|
-
const state =
|
|
5492
|
-
return `- ${
|
|
5953
|
+
const installed = servers.filter((server) => server.installed && !server.disabled);
|
|
5954
|
+
const configuredLines = servers.map((server) => {
|
|
5955
|
+
const state = server.disabled ? "disabled" : server.installed ? "installed" : "missing";
|
|
5956
|
+
return `- ${server.id}: ${state}; source=${server.source}; extensions=${server.extensions.join(", ")}`;
|
|
5493
5957
|
});
|
|
5494
5958
|
const activeLines = snapshots.map((snapshot) => {
|
|
5495
5959
|
const state = snapshot.alive ? snapshot.isInitializing ? "initializing" : "alive" : "dead";
|
|
@@ -5532,10 +5996,10 @@ async function executeLspSymbols(params, signal) {
|
|
|
5532
5996
|
errorKind: "missing_query"
|
|
5533
5997
|
});
|
|
5534
5998
|
}
|
|
5535
|
-
const
|
|
5536
|
-
return formatSymbolsResult(filePath, scope,
|
|
5999
|
+
const symbols = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
|
|
6000
|
+
return formatSymbolsResult(filePath, scope, symbols, limit, query);
|
|
5537
6001
|
}
|
|
5538
|
-
const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(
|
|
6002
|
+
const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
|
|
5539
6003
|
return formatSymbolsResult(filePath, scope, symbols, limit);
|
|
5540
6004
|
} catch (error) {
|
|
5541
6005
|
const query = optionalString(params, "query");
|
|
@@ -5671,6 +6135,16 @@ var LSP_MCP_TOOLS = [
|
|
|
5671
6135
|
}, ["filePath", "line", "character", "newName"]),
|
|
5672
6136
|
execute: executeLspRename
|
|
5673
6137
|
},
|
|
6138
|
+
{
|
|
6139
|
+
name: "format",
|
|
6140
|
+
aliases: ["lsp_format"],
|
|
6141
|
+
title: "LSP Format",
|
|
6142
|
+
description: "Format a source file with its language server and write the returned edits to disk.",
|
|
6143
|
+
inputSchema: objectSchema({
|
|
6144
|
+
filePath: { type: "string", description: "Source file path to format." }
|
|
6145
|
+
}, ["filePath"]),
|
|
6146
|
+
execute: executeLspFormat
|
|
6147
|
+
},
|
|
5674
6148
|
{
|
|
5675
6149
|
name: "install_decision",
|
|
5676
6150
|
aliases: ["lsp_install_decision"],
|
|
@@ -5771,7 +6245,10 @@ function requestedProtocolVersion(params) {
|
|
|
5771
6245
|
var CONTEXT_KEY = "_context";
|
|
5772
6246
|
|
|
5773
6247
|
class InvalidDaemonRequestError extends Error {
|
|
5774
|
-
|
|
6248
|
+
constructor() {
|
|
6249
|
+
super(...arguments);
|
|
6250
|
+
this.name = "InvalidDaemonRequestError";
|
|
6251
|
+
}
|
|
5775
6252
|
}
|
|
5776
6253
|
function extractRequestContext(raw) {
|
|
5777
6254
|
if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
|
|
@@ -5887,14 +6364,17 @@ async function callToolViaDaemon(name, args, options) {
|
|
|
5887
6364
|
function callDiagnosticsViaDaemon(filePath, options) {
|
|
5888
6365
|
return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
|
|
5889
6366
|
}
|
|
6367
|
+
function callFormatViaDaemon(filePath, options) {
|
|
6368
|
+
return callToolViaDaemon("format", { filePath }, options);
|
|
6369
|
+
}
|
|
5890
6370
|
function currentRequestContext(env = process.env) {
|
|
5891
6371
|
const cwd = process.cwd();
|
|
5892
6372
|
const home = env["HOME"] ?? homedir3();
|
|
5893
6373
|
return parseLspRequestContext({
|
|
5894
6374
|
cwd,
|
|
5895
|
-
projectConfigPaths: [
|
|
5896
|
-
userConfigPath:
|
|
5897
|
-
installDecisionsPath:
|
|
6375
|
+
projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
|
|
6376
|
+
userConfigPath: join8(home, ".codex", "lsp-client.json"),
|
|
6377
|
+
installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
|
|
5898
6378
|
capabilities: { installDecisionTool: true }
|
|
5899
6379
|
});
|
|
5900
6380
|
}
|
|
@@ -5909,7 +6389,7 @@ function withContext(args, context) {
|
|
|
5909
6389
|
function ensureDaemonAvailable(paths, ensure, signal) {
|
|
5910
6390
|
if (!signal)
|
|
5911
6391
|
return ensure(paths);
|
|
5912
|
-
return new Promise((
|
|
6392
|
+
return new Promise((resolve, reject) => {
|
|
5913
6393
|
let settled = false;
|
|
5914
6394
|
const finish = (run) => {
|
|
5915
6395
|
if (settled)
|
|
@@ -5924,11 +6404,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
|
|
|
5924
6404
|
return;
|
|
5925
6405
|
}
|
|
5926
6406
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5927
|
-
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() =>
|
|
6407
|
+
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
|
|
5928
6408
|
});
|
|
5929
6409
|
}
|
|
5930
6410
|
function sendToolCall(paths, token, name, args, options) {
|
|
5931
|
-
return new Promise((
|
|
6411
|
+
return new Promise((resolve, reject) => {
|
|
5932
6412
|
const socket = connect(paths.socket);
|
|
5933
6413
|
const requestId = allocateProxyRequestId();
|
|
5934
6414
|
let settled = false;
|
|
@@ -5981,7 +6461,7 @@ function sendToolCall(paths, token, name, args, options) {
|
|
|
5981
6461
|
}
|
|
5982
6462
|
const result = toToolResult(message, requestId);
|
|
5983
6463
|
if (result)
|
|
5984
|
-
finish(() =>
|
|
6464
|
+
finish(() => resolve(result));
|
|
5985
6465
|
else
|
|
5986
6466
|
finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
|
|
5987
6467
|
});
|
|
@@ -6027,18 +6507,15 @@ function isRetryableTool(name) {
|
|
|
6027
6507
|
}
|
|
6028
6508
|
|
|
6029
6509
|
// src/client.ts
|
|
6030
|
-
import { statSync as statSync5 } from "node:fs";
|
|
6031
|
-
import { isAbsolute as isAbsolute5 } from "node:path";
|
|
6032
6510
|
var OMO_LSP_DAEMON_DIR2 = "OMO_LSP_DAEMON_DIR";
|
|
6033
6511
|
var OMO_LSP_DAEMON_CLI2 = "OMO_LSP_DAEMON_CLI";
|
|
6034
6512
|
var OMO_LSP_DAEMON_VERSION2 = "OMO_LSP_DAEMON_VERSION";
|
|
6035
6513
|
var DAEMON_VERSION_PATTERN2 = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
6036
6514
|
|
|
6037
6515
|
class InvalidRuntimeOverrideError2 extends Error {
|
|
6038
|
-
code = "invalid_runtime_override";
|
|
6039
|
-
reason;
|
|
6040
6516
|
constructor(reason, message) {
|
|
6041
6517
|
super(message);
|
|
6518
|
+
this.code = "invalid_runtime_override";
|
|
6042
6519
|
this.name = "InvalidRuntimeOverrideError";
|
|
6043
6520
|
this.reason = reason;
|
|
6044
6521
|
}
|
|
@@ -6058,12 +6535,12 @@ function resolveDaemonRuntime2(env, defaults) {
|
|
|
6058
6535
|
throw new InvalidRuntimeOverrideError2("paired_values_required", `${OMO_LSP_DAEMON_CLI2} and ${OMO_LSP_DAEMON_VERSION2} must be set together`);
|
|
6059
6536
|
}
|
|
6060
6537
|
if (!hasCliOverride || !hasVersionOverride) {
|
|
6061
|
-
if (!
|
|
6538
|
+
if (!isAbsolute6(defaults.cliPath)) {
|
|
6062
6539
|
throw new InvalidRuntimeOverrideError2("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
|
|
6063
6540
|
}
|
|
6064
6541
|
return { cliPath: defaults.cliPath, version: validateDaemonVersion2(defaults.version) };
|
|
6065
6542
|
}
|
|
6066
|
-
if (!
|
|
6543
|
+
if (!isAbsolute6(cliOverride)) {
|
|
6067
6544
|
throw new InvalidRuntimeOverrideError2("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI2} must be an absolute path to an existing regular file`);
|
|
6068
6545
|
}
|
|
6069
6546
|
const stat = statSync5(cliOverride, { throwIfNoEntry: false });
|
|
@@ -6081,17 +6558,21 @@ function callToolViaDaemon2(name, args, options) {
|
|
|
6081
6558
|
function callDiagnosticsViaDaemon2(filePath, options) {
|
|
6082
6559
|
return callDiagnosticsViaDaemon(filePath, options);
|
|
6083
6560
|
}
|
|
6561
|
+
function callFormatViaDaemon2(filePath, options) {
|
|
6562
|
+
return callFormatViaDaemon(filePath, options);
|
|
6563
|
+
}
|
|
6084
6564
|
function currentRequestContext2(env = process.env) {
|
|
6085
6565
|
return currentRequestContext(env);
|
|
6086
6566
|
}
|
|
6087
6567
|
export {
|
|
6088
|
-
|
|
6089
|
-
resolveDaemonRuntime2 as resolveDaemonRuntime,
|
|
6090
|
-
currentRequestContext2 as currentRequestContext,
|
|
6091
|
-
callToolViaDaemon2 as callToolViaDaemon,
|
|
6092
|
-
callDiagnosticsViaDaemon2 as callDiagnosticsViaDaemon,
|
|
6093
|
-
OMO_LSP_DAEMON_VERSION2 as OMO_LSP_DAEMON_VERSION,
|
|
6094
|
-
OMO_LSP_DAEMON_DIR2 as OMO_LSP_DAEMON_DIR,
|
|
6568
|
+
InvalidRuntimeOverrideError2 as InvalidRuntimeOverrideError,
|
|
6095
6569
|
OMO_LSP_DAEMON_CLI2 as OMO_LSP_DAEMON_CLI,
|
|
6096
|
-
|
|
6570
|
+
OMO_LSP_DAEMON_DIR2 as OMO_LSP_DAEMON_DIR,
|
|
6571
|
+
OMO_LSP_DAEMON_VERSION2 as OMO_LSP_DAEMON_VERSION,
|
|
6572
|
+
callDiagnosticsViaDaemon2 as callDiagnosticsViaDaemon,
|
|
6573
|
+
callFormatViaDaemon2 as callFormatViaDaemon,
|
|
6574
|
+
callToolViaDaemon2 as callToolViaDaemon,
|
|
6575
|
+
currentRequestContext2 as currentRequestContext,
|
|
6576
|
+
resolveDaemonRuntime2 as resolveDaemonRuntime,
|
|
6577
|
+
validateDaemonVersion2 as validateDaemonVersion
|
|
6097
6578
|
};
|