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
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
import { argv, stderr } from "node:process";
|
|
5
5
|
|
|
6
6
|
// src/proxy.ts
|
|
7
|
-
import { existsSync as
|
|
8
|
-
import { basename as
|
|
7
|
+
import { existsSync as existsSync13, realpathSync as realpathSync6 } from "node:fs";
|
|
8
|
+
import { basename as basename4, delimiter as delimiter4, dirname as dirname11, isAbsolute as isAbsolute6 } from "node:path";
|
|
9
9
|
|
|
10
10
|
// ../mcp-stdio-core/src/record.ts
|
|
11
11
|
function isPlainRecord(value) {
|
|
@@ -184,6 +184,7 @@ async function runJsonRpcStdioServer(config) {
|
|
|
184
184
|
const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
|
|
185
185
|
isClosed = true;
|
|
186
186
|
config.onIdleTimeout?.();
|
|
187
|
+
config.input.destroy();
|
|
187
188
|
});
|
|
188
189
|
const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
|
|
189
190
|
isClosed = true;
|
|
@@ -280,7 +281,11 @@ function createParentWatchdog(config, onDeadParent) {
|
|
|
280
281
|
const probeAlive = config.probeAlive ?? isProcessAlive;
|
|
281
282
|
let fired = false;
|
|
282
283
|
const timer = setInterval(() => {
|
|
283
|
-
if (fired
|
|
284
|
+
if (fired)
|
|
285
|
+
return;
|
|
286
|
+
const alive = probeAlive(parentPid);
|
|
287
|
+
config.onPoll?.(alive);
|
|
288
|
+
if (alive)
|
|
284
289
|
return;
|
|
285
290
|
fired = true;
|
|
286
291
|
onDeadParent(parentPid, pollIntervalMs);
|
|
@@ -315,8 +320,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
|
|
|
315
320
|
};
|
|
316
321
|
}
|
|
317
322
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
318
|
-
import { existsSync as
|
|
319
|
-
import { dirname as
|
|
323
|
+
import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
|
|
324
|
+
import { basename as basename3, dirname as dirname8, join as join5, resolve as resolve8 } from "node:path";
|
|
320
325
|
|
|
321
326
|
// ../lsp-core/src/request-context.ts
|
|
322
327
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -325,18 +330,17 @@ import { homedir } from "node:os";
|
|
|
325
330
|
import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
326
331
|
|
|
327
332
|
class LspRequestContextParseError extends Error {
|
|
328
|
-
code;
|
|
329
|
-
name = "LspRequestContextParseError";
|
|
330
333
|
constructor(code, message) {
|
|
331
334
|
super(message);
|
|
332
335
|
this.code = code;
|
|
336
|
+
this.name = "LspRequestContextParseError";
|
|
333
337
|
}
|
|
334
338
|
}
|
|
335
339
|
|
|
336
340
|
class LspRequestContextUnavailableError extends Error {
|
|
337
|
-
name = "LspRequestContextUnavailableError";
|
|
338
341
|
constructor() {
|
|
339
342
|
super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
|
|
343
|
+
this.name = "LspRequestContextUnavailableError";
|
|
340
344
|
}
|
|
341
345
|
}
|
|
342
346
|
var storage = new AsyncLocalStorage;
|
|
@@ -356,7 +360,7 @@ function contextCwd() {
|
|
|
356
360
|
}
|
|
357
361
|
function createStandaloneMcpRequestContext(input = {}) {
|
|
358
362
|
const env = input.env ?? process.env;
|
|
359
|
-
const cwd = canonicalCwd(input.cwd ?? process.cwd());
|
|
363
|
+
const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
|
|
360
364
|
const home = input.homeDir ?? homedir();
|
|
361
365
|
const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
|
|
362
366
|
const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
|
|
@@ -499,22 +503,15 @@ function effectiveExtension(filePath) {
|
|
|
499
503
|
|
|
500
504
|
// ../lsp-core/src/lsp/errors.ts
|
|
501
505
|
class LspConnectionClosedError extends Error {
|
|
502
|
-
serverId;
|
|
503
|
-
root;
|
|
504
|
-
name = "LspConnectionClosedError";
|
|
505
506
|
constructor(serverId, root, message) {
|
|
506
507
|
super(message ?? `LSP connection closed for ${serverId} at ${root}`);
|
|
507
508
|
this.serverId = serverId;
|
|
508
509
|
this.root = root;
|
|
510
|
+
this.name = "LspConnectionClosedError";
|
|
509
511
|
}
|
|
510
512
|
}
|
|
511
513
|
|
|
512
514
|
class LspProcessExitedError extends Error {
|
|
513
|
-
serverId;
|
|
514
|
-
root;
|
|
515
|
-
exitCode;
|
|
516
|
-
stderrTail;
|
|
517
|
-
name = "LspProcessExitedError";
|
|
518
515
|
constructor(serverId, root, exitCode, stderrTail) {
|
|
519
516
|
const stderrSuffix = stderrTail ? `
|
|
520
517
|
stderr tail: ${stderrTail}` : "";
|
|
@@ -523,46 +520,59 @@ stderr tail: ${stderrTail}` : "";
|
|
|
523
520
|
this.root = root;
|
|
524
521
|
this.exitCode = exitCode;
|
|
525
522
|
this.stderrTail = stderrTail;
|
|
523
|
+
this.name = "LspProcessExitedError";
|
|
526
524
|
}
|
|
527
525
|
}
|
|
528
526
|
|
|
529
527
|
class LspRequestTimeoutError extends Error {
|
|
530
|
-
method;
|
|
531
|
-
stderrTail;
|
|
532
|
-
name = "LspRequestTimeoutError";
|
|
533
528
|
constructor(method, stderrTail) {
|
|
534
529
|
const stderrSuffix = stderrTail ? `
|
|
535
530
|
recent stderr: ${stderrTail}` : "";
|
|
536
531
|
super(`LSP request timeout (method: ${method})${stderrSuffix}`);
|
|
537
532
|
this.method = method;
|
|
538
533
|
this.stderrTail = stderrTail;
|
|
534
|
+
this.name = "LspRequestTimeoutError";
|
|
539
535
|
}
|
|
540
536
|
}
|
|
541
537
|
|
|
542
538
|
class LspInvalidPathError extends Error {
|
|
543
|
-
|
|
539
|
+
constructor() {
|
|
540
|
+
super(...arguments);
|
|
541
|
+
this.name = "LspInvalidPathError";
|
|
542
|
+
}
|
|
544
543
|
}
|
|
545
544
|
|
|
546
545
|
class LspServerLookupError extends Error {
|
|
547
|
-
lookup;
|
|
548
|
-
name = "LspServerLookupError";
|
|
549
546
|
constructor(message, lookup) {
|
|
550
547
|
super(message);
|
|
551
548
|
this.lookup = lookup;
|
|
549
|
+
this.name = "LspServerLookupError";
|
|
552
550
|
}
|
|
553
551
|
}
|
|
554
552
|
|
|
555
553
|
class LspServerInitializingError extends Error {
|
|
556
|
-
originalError;
|
|
557
|
-
name = "LspServerInitializingError";
|
|
558
554
|
constructor(originalError) {
|
|
559
555
|
super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
|
|
560
556
|
this.originalError = originalError;
|
|
557
|
+
this.name = "LspServerInitializingError";
|
|
561
558
|
}
|
|
562
559
|
}
|
|
563
560
|
|
|
564
561
|
class LspProcessSpawnError extends Error {
|
|
565
|
-
|
|
562
|
+
constructor() {
|
|
563
|
+
super(...arguments);
|
|
564
|
+
this.name = "LspProcessSpawnError";
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
class LspClientRespawnBudgetExceededError extends Error {
|
|
569
|
+
constructor(serverId, root, retryLimit) {
|
|
570
|
+
super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
|
|
571
|
+
this.serverId = serverId;
|
|
572
|
+
this.root = root;
|
|
573
|
+
this.retryLimit = retryLimit;
|
|
574
|
+
this.name = "LspClientRespawnBudgetExceededError";
|
|
575
|
+
}
|
|
566
576
|
}
|
|
567
577
|
function isLspDeadConnectionError(err) {
|
|
568
578
|
return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
|
|
@@ -585,6 +595,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
|
585
595
|
// ../lsp-core/src/lsp/connection.ts
|
|
586
596
|
import { pathToFileURL } from "node:url";
|
|
587
597
|
|
|
598
|
+
// ../lsp-core/src/lsp/timer-provider.ts
|
|
599
|
+
var realTimerProvider = {
|
|
600
|
+
now: () => Date.now(),
|
|
601
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
602
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
603
|
+
};
|
|
604
|
+
|
|
588
605
|
// ../lsp-core/src/lsp/constants.ts
|
|
589
606
|
var DEFAULT_MAX_REFERENCES = 200;
|
|
590
607
|
var DEFAULT_MAX_SYMBOLS = 200;
|
|
@@ -593,9 +610,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
|
|
|
593
610
|
var REQUEST_TIMEOUT_MS = 15000;
|
|
594
611
|
var INIT_TIMEOUT_MS = 60000;
|
|
595
612
|
var IDLE_TIMEOUT_MS = 5 * 60000;
|
|
613
|
+
var MAX_RESIDENT_CLIENTS = 6;
|
|
596
614
|
var REAPER_INTERVAL_MS = 60000;
|
|
597
615
|
var STOP_HARD_KILL_TIMEOUT_MS = 5000;
|
|
598
616
|
var STOP_SIGKILL_GRACE_MS = 1000;
|
|
617
|
+
var CLIENT_RESPAWN_RETRY_LIMIT = 2;
|
|
618
|
+
var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
|
|
599
619
|
|
|
600
620
|
// ../lsp-core/src/lsp/json-rpc-connection.ts
|
|
601
621
|
var HEADER_SEPARATOR2 = `\r
|
|
@@ -607,20 +627,31 @@ var METHOD_NOT_FOUND = -32601;
|
|
|
607
627
|
var INTERNAL_ERROR = -32603;
|
|
608
628
|
|
|
609
629
|
class JsonRpcConnection {
|
|
610
|
-
reader;
|
|
611
|
-
writer;
|
|
612
|
-
pendingRequests = new Map;
|
|
613
|
-
notificationHandlers = new Map;
|
|
614
|
-
requestHandlers = new Map;
|
|
615
|
-
closeHandlers = [];
|
|
616
|
-
errorHandlers = [];
|
|
617
|
-
inputBuffer = Buffer.alloc(0);
|
|
618
|
-
nextRequestId = 1;
|
|
619
|
-
listening = false;
|
|
620
|
-
disposed = false;
|
|
621
630
|
constructor(reader, writer) {
|
|
622
631
|
this.reader = reader;
|
|
623
632
|
this.writer = writer;
|
|
633
|
+
this.pendingRequests = new Map;
|
|
634
|
+
this.notificationHandlers = new Map;
|
|
635
|
+
this.requestHandlers = new Map;
|
|
636
|
+
this.closeHandlers = [];
|
|
637
|
+
this.errorHandlers = [];
|
|
638
|
+
this.inputBuffer = Buffer.alloc(0);
|
|
639
|
+
this.nextRequestId = 1;
|
|
640
|
+
this.listening = false;
|
|
641
|
+
this.disposed = false;
|
|
642
|
+
this.handleData = (chunk) => {
|
|
643
|
+
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
644
|
+
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
645
|
+
this.drainInputBuffer();
|
|
646
|
+
};
|
|
647
|
+
this.handleClose = () => {
|
|
648
|
+
for (const handler of this.closeHandlers) {
|
|
649
|
+
handler();
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
this.handleStreamError = (error) => {
|
|
653
|
+
this.emitError(error);
|
|
654
|
+
};
|
|
624
655
|
}
|
|
625
656
|
listen() {
|
|
626
657
|
if (this.listening)
|
|
@@ -655,7 +686,8 @@ class JsonRpcConnection {
|
|
|
655
686
|
let cancelAfterWrite = false;
|
|
656
687
|
let settled = false;
|
|
657
688
|
const writeCancel = () => this.writeMessage({ jsonrpc: "2.0", method: "$/cancelRequest", params: { id } });
|
|
658
|
-
|
|
689
|
+
let rejectAfterCancelWrite;
|
|
690
|
+
const responsePromise = new Promise((resolve, reject) => {
|
|
659
691
|
const cleanup = () => {
|
|
660
692
|
options.signal?.removeEventListener("abort", onAbort);
|
|
661
693
|
};
|
|
@@ -666,22 +698,26 @@ class JsonRpcConnection {
|
|
|
666
698
|
this.pendingRequests.delete(key);
|
|
667
699
|
cleanup();
|
|
668
700
|
const rejectCancelled = () => reject(abortError(options.signal));
|
|
701
|
+
rejectAfterCancelWrite = async () => {
|
|
702
|
+
try {
|
|
703
|
+
await writeCancel();
|
|
704
|
+
} catch (error) {
|
|
705
|
+
this.emitError(toError(error));
|
|
706
|
+
}
|
|
707
|
+
rejectCancelled();
|
|
708
|
+
};
|
|
669
709
|
if (!requestWritten) {
|
|
670
710
|
cancelAfterWrite = true;
|
|
671
|
-
rejectCancelled();
|
|
672
711
|
return;
|
|
673
712
|
}
|
|
674
|
-
|
|
675
|
-
this.emitError(toError(error));
|
|
676
|
-
rejectCancelled();
|
|
677
|
-
});
|
|
713
|
+
rejectAfterCancelWrite();
|
|
678
714
|
};
|
|
679
715
|
const onAbort = () => settleCancel();
|
|
680
716
|
this.pendingRequests.set(key, {
|
|
681
717
|
resolve(result) {
|
|
682
718
|
settled = true;
|
|
683
719
|
cleanup();
|
|
684
|
-
|
|
720
|
+
resolve(result);
|
|
685
721
|
},
|
|
686
722
|
reject(error) {
|
|
687
723
|
settled = true;
|
|
@@ -702,7 +738,7 @@ class JsonRpcConnection {
|
|
|
702
738
|
await this.writeMessage(message);
|
|
703
739
|
requestWritten = true;
|
|
704
740
|
if (cancelAfterWrite)
|
|
705
|
-
await
|
|
741
|
+
await rejectAfterCancelWrite?.();
|
|
706
742
|
} catch (error) {
|
|
707
743
|
if (settled)
|
|
708
744
|
return responsePromise;
|
|
@@ -741,19 +777,6 @@ class JsonRpcConnection {
|
|
|
741
777
|
this.notificationHandlers.clear();
|
|
742
778
|
this.requestHandlers.clear();
|
|
743
779
|
}
|
|
744
|
-
handleData = (chunk) => {
|
|
745
|
-
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
746
|
-
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
747
|
-
this.drainInputBuffer();
|
|
748
|
-
};
|
|
749
|
-
handleClose = () => {
|
|
750
|
-
for (const handler of this.closeHandlers) {
|
|
751
|
-
handler();
|
|
752
|
-
}
|
|
753
|
-
};
|
|
754
|
-
handleStreamError = (error) => {
|
|
755
|
-
this.emitError(error);
|
|
756
|
-
};
|
|
757
780
|
drainInputBuffer() {
|
|
758
781
|
while (true) {
|
|
759
782
|
const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
|
|
@@ -853,13 +876,13 @@ class JsonRpcConnection {
|
|
|
853
876
|
const payload = `Content-Length: ${Buffer.byteLength(body, "utf8")}\r
|
|
854
877
|
\r
|
|
855
878
|
${body}`;
|
|
856
|
-
return new Promise((
|
|
879
|
+
return new Promise((resolve, reject) => {
|
|
857
880
|
this.writer.write(payload, (error) => {
|
|
858
881
|
if (error) {
|
|
859
882
|
reject(error);
|
|
860
883
|
return;
|
|
861
884
|
}
|
|
862
|
-
|
|
885
|
+
resolve();
|
|
863
886
|
});
|
|
864
887
|
});
|
|
865
888
|
}
|
|
@@ -946,9 +969,9 @@ function validateCwd(cwd) {
|
|
|
946
969
|
}
|
|
947
970
|
}
|
|
948
971
|
function wrap(proc) {
|
|
949
|
-
const exitedPromise = new Promise((
|
|
950
|
-
proc.once("close", (code) =>
|
|
951
|
-
proc.once("error", () =>
|
|
972
|
+
const exitedPromise = new Promise((resolve) => {
|
|
973
|
+
proc.once("close", (code) => resolve(code ?? 0));
|
|
974
|
+
proc.once("error", () => resolve(1));
|
|
952
975
|
});
|
|
953
976
|
if (!proc.stdin || !proc.stdout || !proc.stderr) {
|
|
954
977
|
throw new LspProcessSpawnError("Spawned process is missing one of stdin/stdout/stderr pipes");
|
|
@@ -1101,33 +1124,29 @@ function isPosition(value) {
|
|
|
1101
1124
|
|
|
1102
1125
|
// ../lsp-core/src/lsp/transport.ts
|
|
1103
1126
|
class LspClientNotStartedError extends Error {
|
|
1104
|
-
serverId;
|
|
1105
|
-
root;
|
|
1106
|
-
name = "LspClientNotStartedError";
|
|
1107
1127
|
constructor(serverId, root) {
|
|
1108
1128
|
super("LSP client not started");
|
|
1109
1129
|
this.serverId = serverId;
|
|
1110
1130
|
this.root = root;
|
|
1131
|
+
this.name = "LspClientNotStartedError";
|
|
1111
1132
|
}
|
|
1112
1133
|
}
|
|
1113
1134
|
|
|
1114
1135
|
class LspClientTransport {
|
|
1115
|
-
root
|
|
1116
|
-
server;
|
|
1117
|
-
proc = null;
|
|
1118
|
-
connection = null;
|
|
1119
|
-
stderrBuffer = [];
|
|
1120
|
-
processExited = false;
|
|
1121
|
-
diagnosticsStore = new Map;
|
|
1122
|
-
requestTimeoutMs;
|
|
1123
|
-
initializeTimeoutMs;
|
|
1124
|
-
workspaceApplyEditHandler = null;
|
|
1125
|
-
diagnosticPullSupported = false;
|
|
1126
|
-
constructor(root, server2, timeouts = {}) {
|
|
1136
|
+
constructor(root, server, timeouts = {}) {
|
|
1127
1137
|
this.root = root;
|
|
1128
|
-
this.server =
|
|
1138
|
+
this.server = server;
|
|
1139
|
+
this.proc = null;
|
|
1140
|
+
this.connection = null;
|
|
1141
|
+
this.stderrBuffer = [];
|
|
1142
|
+
this.processExited = false;
|
|
1143
|
+
this.diagnosticsStore = new Map;
|
|
1144
|
+
this.workspaceApplyEditHandler = null;
|
|
1145
|
+
this.diagnosticPullSupported = false;
|
|
1146
|
+
this.documentFormattingSupported = false;
|
|
1129
1147
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
1130
1148
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
1149
|
+
this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
|
|
1131
1150
|
}
|
|
1132
1151
|
pid() {
|
|
1133
1152
|
return this.proc?.pid;
|
|
@@ -1147,6 +1166,12 @@ class LspClientTransport {
|
|
|
1147
1166
|
isDiagnosticPullSupported() {
|
|
1148
1167
|
return this.diagnosticPullSupported;
|
|
1149
1168
|
}
|
|
1169
|
+
setDocumentFormattingSupported(supported) {
|
|
1170
|
+
this.documentFormattingSupported = supported;
|
|
1171
|
+
}
|
|
1172
|
+
isDocumentFormattingSupported() {
|
|
1173
|
+
return this.documentFormattingSupported;
|
|
1174
|
+
}
|
|
1150
1175
|
handlePublishDiagnostics(params) {
|
|
1151
1176
|
this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
|
|
1152
1177
|
}
|
|
@@ -1222,7 +1247,7 @@ class LspClientTransport {
|
|
|
1222
1247
|
const options = args[1];
|
|
1223
1248
|
const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
|
|
1224
1249
|
const timeoutController = new AbortController;
|
|
1225
|
-
const timeoutHandle = setTimeout(() => {
|
|
1250
|
+
const timeoutHandle = this.timerProvider.setTimeout(() => {
|
|
1226
1251
|
const stderrTail = this.stderrBuffer.slice(-5).join(`
|
|
1227
1252
|
`);
|
|
1228
1253
|
timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
|
|
@@ -1241,7 +1266,7 @@ class LspClientTransport {
|
|
|
1241
1266
|
}
|
|
1242
1267
|
throw error;
|
|
1243
1268
|
} finally {
|
|
1244
|
-
clearTimeout(timeoutHandle);
|
|
1269
|
+
this.timerProvider.clearTimeout(timeoutHandle);
|
|
1245
1270
|
combinedSignal.dispose();
|
|
1246
1271
|
}
|
|
1247
1272
|
}
|
|
@@ -1292,8 +1317,8 @@ class LspClientTransport {
|
|
|
1292
1317
|
try {
|
|
1293
1318
|
proc.kill();
|
|
1294
1319
|
let timeoutId;
|
|
1295
|
-
const timeoutPromise = new Promise((
|
|
1296
|
-
timeoutId = setTimeout(
|
|
1320
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
1321
|
+
timeoutId = setTimeout(resolve, STOP_HARD_KILL_TIMEOUT_MS);
|
|
1297
1322
|
});
|
|
1298
1323
|
await Promise.race([
|
|
1299
1324
|
proc.exited.then(() => {
|
|
@@ -1309,7 +1334,7 @@ class LspClientTransport {
|
|
|
1309
1334
|
proc.kill("SIGKILL");
|
|
1310
1335
|
await Promise.race([
|
|
1311
1336
|
proc.exited,
|
|
1312
|
-
new Promise((
|
|
1337
|
+
new Promise((resolve) => setTimeout(resolve, STOP_SIGKILL_GRACE_MS))
|
|
1313
1338
|
]);
|
|
1314
1339
|
} catch (error) {
|
|
1315
1340
|
reportBestEffortCleanupError("hard process kill", error instanceof Error ? error : String(error));
|
|
@@ -1360,6 +1385,14 @@ function supportsDiagnosticPull(capabilities) {
|
|
|
1360
1385
|
return false;
|
|
1361
1386
|
return Object.hasOwn(capabilities, "diagnosticProvider");
|
|
1362
1387
|
}
|
|
1388
|
+
function supportsDocumentFormatting(capabilities) {
|
|
1389
|
+
if (capabilities === undefined)
|
|
1390
|
+
return false;
|
|
1391
|
+
const provider = capabilities.documentFormattingProvider;
|
|
1392
|
+
if (provider === undefined || provider === null || provider === false)
|
|
1393
|
+
return false;
|
|
1394
|
+
return provider === true || typeof provider === "object";
|
|
1395
|
+
}
|
|
1363
1396
|
|
|
1364
1397
|
class LspClientConnection extends LspClientTransport {
|
|
1365
1398
|
async initialize() {
|
|
@@ -1376,6 +1409,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
1376
1409
|
references: {},
|
|
1377
1410
|
documentSymbol: { hierarchicalDocumentSymbolSupport: true },
|
|
1378
1411
|
publishDiagnostics: {},
|
|
1412
|
+
formatting: { dynamicRegistration: false },
|
|
1379
1413
|
rename: {
|
|
1380
1414
|
prepareSupport: true,
|
|
1381
1415
|
prepareSupportDefaultBehavior: 1
|
|
@@ -1417,6 +1451,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
1417
1451
|
initializationOptions: this.server.initialization
|
|
1418
1452
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
1419
1453
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
1454
|
+
this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
|
|
1420
1455
|
await this.sendNotification("initialized", {});
|
|
1421
1456
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
1422
1457
|
settings: { json: { validate: { enable: true } } }
|
|
@@ -1612,6 +1647,17 @@ function canonicalPath(filePath) {
|
|
|
1612
1647
|
return absolute;
|
|
1613
1648
|
}
|
|
1614
1649
|
}
|
|
1650
|
+
function normalizeDocumentUri(uri) {
|
|
1651
|
+
let decoded = uri;
|
|
1652
|
+
try {
|
|
1653
|
+
decoded = decodeURIComponent(uri);
|
|
1654
|
+
} catch {
|
|
1655
|
+
decoded = uri;
|
|
1656
|
+
}
|
|
1657
|
+
if (process.platform !== "win32")
|
|
1658
|
+
return decoded;
|
|
1659
|
+
return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
|
|
1660
|
+
}
|
|
1615
1661
|
function isSameOrDescendant(candidate, parent) {
|
|
1616
1662
|
const suffix = relative2(parent, candidate);
|
|
1617
1663
|
return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
|
|
@@ -1622,17 +1668,18 @@ function movedPath(candidate, oldPath, newPath) {
|
|
|
1622
1668
|
}
|
|
1623
1669
|
|
|
1624
1670
|
class WorkspaceDocumentState {
|
|
1625
|
-
sendNotification;
|
|
1626
|
-
clearDiagnostics;
|
|
1627
|
-
openDocuments = new Map;
|
|
1628
|
-
openByUri = new Map;
|
|
1629
|
-
openPromises = new Map;
|
|
1630
|
-
now;
|
|
1631
|
-
versionlessPublishQuiescenceMs;
|
|
1632
1671
|
constructor(sendNotification, clearDiagnostics, options = {}) {
|
|
1633
1672
|
this.sendNotification = sendNotification;
|
|
1634
1673
|
this.clearDiagnostics = clearDiagnostics;
|
|
1635
|
-
this.
|
|
1674
|
+
this.openDocuments = new Map;
|
|
1675
|
+
this.openByUri = new Map;
|
|
1676
|
+
this.openPromises = new Map;
|
|
1677
|
+
this.timerProvider = options.timerProvider ?? {
|
|
1678
|
+
now: options.now ?? (() => Date.now()),
|
|
1679
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
1680
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
1681
|
+
};
|
|
1682
|
+
this.now = () => this.timerProvider.now();
|
|
1636
1683
|
this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
|
|
1637
1684
|
}
|
|
1638
1685
|
async openFile(filePath) {
|
|
@@ -1654,7 +1701,7 @@ class WorkspaceDocumentState {
|
|
|
1654
1701
|
return this.openDocuments.get(canonicalPath(filePath))?.version;
|
|
1655
1702
|
}
|
|
1656
1703
|
getStoredDiagnostics(uri) {
|
|
1657
|
-
const state = this.openByUri.get(uri);
|
|
1704
|
+
const state = this.openByUri.get(normalizeDocumentUri(uri));
|
|
1658
1705
|
if (!state)
|
|
1659
1706
|
return [];
|
|
1660
1707
|
return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
|
|
@@ -1676,13 +1723,13 @@ class WorkspaceDocumentState {
|
|
|
1676
1723
|
return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
|
|
1677
1724
|
}
|
|
1678
1725
|
getPullCache(snapshot) {
|
|
1679
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1726
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1680
1727
|
if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
|
|
1681
1728
|
return null;
|
|
1682
1729
|
return state.pullCache;
|
|
1683
1730
|
}
|
|
1684
1731
|
recordPullDiagnostics(snapshot, report) {
|
|
1685
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1732
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1686
1733
|
if (!state)
|
|
1687
1734
|
return;
|
|
1688
1735
|
state.pullCache = {
|
|
@@ -1692,7 +1739,7 @@ class WorkspaceDocumentState {
|
|
|
1692
1739
|
};
|
|
1693
1740
|
}
|
|
1694
1741
|
recordPublishedDiagnostics(params) {
|
|
1695
|
-
const state = this.openByUri.get(params.uri);
|
|
1742
|
+
const state = this.openByUri.get(normalizeDocumentUri(params.uri));
|
|
1696
1743
|
if (!state)
|
|
1697
1744
|
return;
|
|
1698
1745
|
state.publishGeneration += 1;
|
|
@@ -1706,7 +1753,7 @@ class WorkspaceDocumentState {
|
|
|
1706
1753
|
this.notifyWaiters(state);
|
|
1707
1754
|
}
|
|
1708
1755
|
resolvePushDiagnostics(snapshot) {
|
|
1709
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1756
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1710
1757
|
if (!state?.lastPublish)
|
|
1711
1758
|
return { status: "missing" };
|
|
1712
1759
|
const publish = state.lastPublish;
|
|
@@ -1720,7 +1767,7 @@ class WorkspaceDocumentState {
|
|
|
1720
1767
|
return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
|
|
1721
1768
|
}
|
|
1722
1769
|
waitForDiagnosticsActivity(snapshot, timeoutMs) {
|
|
1723
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1770
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1724
1771
|
if (!state || timeoutMs <= 0)
|
|
1725
1772
|
return Promise.resolve();
|
|
1726
1773
|
return new Promise((resolveActivity) => {
|
|
@@ -1729,11 +1776,11 @@ class WorkspaceDocumentState {
|
|
|
1729
1776
|
if (settled)
|
|
1730
1777
|
return;
|
|
1731
1778
|
settled = true;
|
|
1732
|
-
clearTimeout(timer);
|
|
1779
|
+
this.timerProvider.clearTimeout(timer);
|
|
1733
1780
|
state.waiters.delete(finish);
|
|
1734
1781
|
resolveActivity();
|
|
1735
1782
|
};
|
|
1736
|
-
const timer = setTimeout(finish, timeoutMs);
|
|
1783
|
+
const timer = this.timerProvider.setTimeout(finish, timeoutMs);
|
|
1737
1784
|
if (typeof timer.unref === "function")
|
|
1738
1785
|
timer.unref();
|
|
1739
1786
|
state.waiters.add(finish);
|
|
@@ -1841,7 +1888,7 @@ class WorkspaceDocumentState {
|
|
|
1841
1888
|
waiters: new Set
|
|
1842
1889
|
};
|
|
1843
1890
|
this.openDocuments.set(path, state);
|
|
1844
|
-
this.openByUri.set(state.uri, state);
|
|
1891
|
+
this.openByUri.set(normalizeDocumentUri(state.uri), state);
|
|
1845
1892
|
this.notifyWaiters(state);
|
|
1846
1893
|
await this.sendNotification("textDocument/didOpen", {
|
|
1847
1894
|
textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
|
|
@@ -1866,7 +1913,7 @@ class WorkspaceDocumentState {
|
|
|
1866
1913
|
}
|
|
1867
1914
|
async closeDocument(state) {
|
|
1868
1915
|
this.openDocuments.delete(state.path);
|
|
1869
|
-
this.openByUri.delete(state.uri);
|
|
1916
|
+
this.openByUri.delete(normalizeDocumentUri(state.uri));
|
|
1870
1917
|
this.clearDiagnostics(state.uri);
|
|
1871
1918
|
this.notifyWaiters(state);
|
|
1872
1919
|
await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
|
|
@@ -1895,13 +1942,11 @@ import { dirname as dirname2, isAbsolute as isAbsolute2, relative as relative3,
|
|
|
1895
1942
|
import { fileURLToPath } from "node:url";
|
|
1896
1943
|
|
|
1897
1944
|
class WorkspaceEditPathError extends Error {
|
|
1898
|
-
path;
|
|
1899
|
-
detail;
|
|
1900
|
-
name = "WorkspaceEditPathError";
|
|
1901
1945
|
constructor(path, detail) {
|
|
1902
1946
|
super(`${detail}: ${path}`);
|
|
1903
1947
|
this.path = path;
|
|
1904
1948
|
this.detail = detail;
|
|
1949
|
+
this.name = "WorkspaceEditPathError";
|
|
1905
1950
|
}
|
|
1906
1951
|
}
|
|
1907
1952
|
function isPathInsideWorkspace(filePath, workspaceRoot) {
|
|
@@ -2193,13 +2238,11 @@ function canonicalFingerprint(operations) {
|
|
|
2193
2238
|
|
|
2194
2239
|
// ../lsp-core/src/lsp/workspace-edit-types.ts
|
|
2195
2240
|
class WorkspaceEditValidationError extends Error {
|
|
2196
|
-
changeIndex;
|
|
2197
|
-
detail;
|
|
2198
|
-
name = "WorkspaceEditValidationError";
|
|
2199
2241
|
constructor(changeIndex, detail) {
|
|
2200
2242
|
super(`change ${changeIndex}: ${detail}`);
|
|
2201
2243
|
this.changeIndex = changeIndex;
|
|
2202
2244
|
this.detail = detail;
|
|
2245
|
+
this.name = "WorkspaceEditValidationError";
|
|
2203
2246
|
}
|
|
2204
2247
|
}
|
|
2205
2248
|
|
|
@@ -2285,14 +2328,14 @@ function parseSinglePathResource(input, kind) {
|
|
|
2285
2328
|
return;
|
|
2286
2329
|
}
|
|
2287
2330
|
if (kind === "create") {
|
|
2288
|
-
const
|
|
2331
|
+
const options = parseOptions(change["options"], ["overwrite", "ignoreIfExists"], changeIndex);
|
|
2289
2332
|
target.operations.push({
|
|
2290
2333
|
kind,
|
|
2291
2334
|
changeIndex,
|
|
2292
2335
|
path: resolvedPath.path,
|
|
2293
2336
|
reportedPath: resolvedPath.requestedPath,
|
|
2294
|
-
overwrite:
|
|
2295
|
-
ignoreIfExists:
|
|
2337
|
+
overwrite: options["overwrite"] ?? false,
|
|
2338
|
+
ignoreIfExists: options["ignoreIfExists"] ?? false,
|
|
2296
2339
|
followedSymbolicLink: resolvedPath.followedSymbolicLink
|
|
2297
2340
|
});
|
|
2298
2341
|
return;
|
|
@@ -2697,10 +2740,9 @@ function simulateDelete(operation, virtual) {
|
|
|
2697
2740
|
import { existsSync as existsSync5, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
|
|
2698
2741
|
import { dirname as dirname4, resolve as resolve5 } from "node:path";
|
|
2699
2742
|
class WorkspaceSnapshotBuilder {
|
|
2700
|
-
workspaceRoot;
|
|
2701
|
-
snapshots = new Map;
|
|
2702
2743
|
constructor(workspaceRoot) {
|
|
2703
2744
|
this.workspaceRoot = workspaceRoot;
|
|
2745
|
+
this.snapshots = new Map;
|
|
2704
2746
|
}
|
|
2705
2747
|
build(operations) {
|
|
2706
2748
|
this.add(this.workspaceRoot, false);
|
|
@@ -2744,8 +2786,10 @@ function snapshotOperations(operations, workspaceRoot) {
|
|
|
2744
2786
|
|
|
2745
2787
|
// ../lsp-core/src/lsp/workspace-edit-plan.ts
|
|
2746
2788
|
class PlanPathIndex {
|
|
2747
|
-
|
|
2748
|
-
|
|
2789
|
+
constructor() {
|
|
2790
|
+
this.firstChangeByPath = new Map;
|
|
2791
|
+
this.reportedPathByCanonical = new Map;
|
|
2792
|
+
}
|
|
2749
2793
|
build(operations) {
|
|
2750
2794
|
for (const operation of operations) {
|
|
2751
2795
|
switch (operation.kind) {
|
|
@@ -2761,11 +2805,11 @@ class PlanPathIndex {
|
|
|
2761
2805
|
}
|
|
2762
2806
|
}
|
|
2763
2807
|
}
|
|
2764
|
-
add(path,
|
|
2808
|
+
add(path, reportedPath, changeIndex) {
|
|
2765
2809
|
if (!this.firstChangeByPath.has(path))
|
|
2766
2810
|
this.firstChangeByPath.set(path, changeIndex);
|
|
2767
2811
|
if (!this.reportedPathByCanonical.has(path))
|
|
2768
|
-
this.reportedPathByCanonical.set(path,
|
|
2812
|
+
this.reportedPathByCanonical.set(path, reportedPath);
|
|
2769
2813
|
}
|
|
2770
2814
|
}
|
|
2771
2815
|
function fingerprintWorkspaceEdit(edit, workspaceRoot) {
|
|
@@ -2834,14 +2878,11 @@ function isRecord4(value) {
|
|
|
2834
2878
|
}
|
|
2835
2879
|
|
|
2836
2880
|
class WorkspaceMutationController {
|
|
2837
|
-
workspaceRoot;
|
|
2838
|
-
documents;
|
|
2839
|
-
activeLease = null;
|
|
2840
|
-
nextLeaseId = 1;
|
|
2841
|
-
io;
|
|
2842
2881
|
constructor(workspaceRoot, documents) {
|
|
2843
2882
|
this.workspaceRoot = workspaceRoot;
|
|
2844
2883
|
this.documents = documents;
|
|
2884
|
+
this.activeLease = null;
|
|
2885
|
+
this.nextLeaseId = 1;
|
|
2845
2886
|
}
|
|
2846
2887
|
setIo(io) {
|
|
2847
2888
|
this.io = io;
|
|
@@ -2880,15 +2921,15 @@ class WorkspaceMutationController {
|
|
|
2880
2921
|
};
|
|
2881
2922
|
}
|
|
2882
2923
|
lease.phase = "applying";
|
|
2883
|
-
lease.applyCompletion = new Promise((
|
|
2884
|
-
lease.resolveApply =
|
|
2924
|
+
lease.applyCompletion = new Promise((resolve) => {
|
|
2925
|
+
lease.resolveApply = resolve;
|
|
2885
2926
|
});
|
|
2886
2927
|
const edit = isRecord4(params) ? params["edit"] : undefined;
|
|
2887
|
-
const
|
|
2888
|
-
lease.serverApply =
|
|
2928
|
+
const record = edit === undefined ? { fingerprint: null, result: failure("workspace/applyEdit params.edit is required", 0) } : await this.applyEdit(edit, lease);
|
|
2929
|
+
lease.serverApply = record;
|
|
2889
2930
|
lease.phase = "settled";
|
|
2890
2931
|
lease.resolveApply?.();
|
|
2891
|
-
return responseFor(
|
|
2932
|
+
return responseFor(record.result);
|
|
2892
2933
|
}
|
|
2893
2934
|
async reconcileRename(leaseToken, edit) {
|
|
2894
2935
|
const lease = this.requireActiveLease(leaseToken);
|
|
@@ -2904,16 +2945,16 @@ class WorkspaceMutationController {
|
|
|
2904
2945
|
const applied = await this.applyEdit(edit, lease);
|
|
2905
2946
|
return { edit, apply: applied.result };
|
|
2906
2947
|
}
|
|
2907
|
-
reconcileServerApply(
|
|
2948
|
+
reconcileServerApply(record, edit) {
|
|
2908
2949
|
if (!edit)
|
|
2909
|
-
return { edit, apply:
|
|
2950
|
+
return { edit, apply: record.result };
|
|
2910
2951
|
const fingerprint = fingerprintWorkspaceEdit(edit, this.workspaceRoot);
|
|
2911
|
-
if (fingerprint.success &&
|
|
2912
|
-
return { edit, apply:
|
|
2952
|
+
if (fingerprint.success && record.fingerprint !== null && fingerprint.fingerprint === record.fingerprint) {
|
|
2953
|
+
return { edit, apply: record.result };
|
|
2913
2954
|
}
|
|
2914
2955
|
return {
|
|
2915
2956
|
edit,
|
|
2916
|
-
apply: failure("rename result conflicts with server-applied workspace edit", 0,
|
|
2957
|
+
apply: failure("rename result conflicts with server-applied workspace edit", 0, record.result)
|
|
2917
2958
|
};
|
|
2918
2959
|
}
|
|
2919
2960
|
async applyEdit(edit, lease) {
|
|
@@ -2954,14 +2995,12 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
|
|
|
2954
2995
|
var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
|
|
2955
2996
|
|
|
2956
2997
|
class LspClient extends LspClientConnection {
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
diagnosticsFreshnessTimeoutMs;
|
|
2961
|
-
constructor(root, server2, options = {}) {
|
|
2962
|
-
super(root, server2, options);
|
|
2998
|
+
constructor(root, server, options = {}) {
|
|
2999
|
+
super(root, server, options);
|
|
3000
|
+
this.diagnosticPullErrors = [];
|
|
2963
3001
|
this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
|
|
2964
3002
|
this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
|
|
3003
|
+
timerProvider: this.timerProvider,
|
|
2965
3004
|
versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
|
|
2966
3005
|
});
|
|
2967
3006
|
this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
|
|
@@ -3014,6 +3053,18 @@ class LspClient extends LspClientConnection {
|
|
|
3014
3053
|
textDocument: { uri: pathToFileURL3(absPath).href }
|
|
3015
3054
|
}, options);
|
|
3016
3055
|
}
|
|
3056
|
+
async formatDocument(filePath, options, signal) {
|
|
3057
|
+
if (!this.isDocumentFormattingSupported())
|
|
3058
|
+
return null;
|
|
3059
|
+
const absPath = this.resolveWorkspacePath(filePath);
|
|
3060
|
+
await this.openFile(absPath);
|
|
3061
|
+
const requestOptions = signal === undefined ? {} : { signal };
|
|
3062
|
+
const edits = await this.sendRequest("textDocument/formatting", {
|
|
3063
|
+
textDocument: { uri: pathToFileURL3(absPath).href },
|
|
3064
|
+
options
|
|
3065
|
+
}, requestOptions);
|
|
3066
|
+
return edits ?? [];
|
|
3067
|
+
}
|
|
3017
3068
|
async workspaceSymbols(query, signal) {
|
|
3018
3069
|
const options = signal === undefined ? {} : { signal };
|
|
3019
3070
|
return this.sendRequest("workspace/symbol", { query }, options);
|
|
@@ -3053,7 +3104,7 @@ class LspClient extends LspClientConnection {
|
|
|
3053
3104
|
const absPath = this.resolveWorkspacePath(filePath);
|
|
3054
3105
|
const uri = pathToFileURL3(absPath).href;
|
|
3055
3106
|
await this.openFile(absPath);
|
|
3056
|
-
const deadlineAt =
|
|
3107
|
+
const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
|
|
3057
3108
|
for (;; ) {
|
|
3058
3109
|
signal?.throwIfAborted();
|
|
3059
3110
|
const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
|
|
@@ -3066,13 +3117,13 @@ class LspClient extends LspClientConnection {
|
|
|
3066
3117
|
if (!pushFallbackOnly) {
|
|
3067
3118
|
const cached = this.documents.getPullCache(snapshot);
|
|
3068
3119
|
try {
|
|
3069
|
-
const
|
|
3070
|
-
if (
|
|
3120
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
3121
|
+
if (remainingMs <= 0)
|
|
3071
3122
|
return this.freshnessTimeout(absPath);
|
|
3072
3123
|
const result = await this.sendRequest("textDocument/diagnostic", {
|
|
3073
3124
|
textDocument: { uri },
|
|
3074
3125
|
...cached?.resultId === undefined ? {} : { previousResultId: cached.resultId }
|
|
3075
|
-
}, { timeoutMs:
|
|
3126
|
+
}, { timeoutMs: remainingMs, ...signal === undefined ? {} : { signal } });
|
|
3076
3127
|
if (!this.documents.isCurrentSnapshot(snapshot))
|
|
3077
3128
|
continue;
|
|
3078
3129
|
const report = this.parseDiagnosticPullReport(result);
|
|
@@ -3101,7 +3152,7 @@ class LspClient extends LspClientConnection {
|
|
|
3101
3152
|
}
|
|
3102
3153
|
if (!pushFallbackOnly)
|
|
3103
3154
|
continue;
|
|
3104
|
-
const remainingMs = deadlineAt -
|
|
3155
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
3105
3156
|
if (remainingMs <= 0) {
|
|
3106
3157
|
if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
|
|
3107
3158
|
const cached = this.documents.getPullCache(snapshot);
|
|
@@ -3153,7 +3204,7 @@ function waitForDiagnosticsActivity(wait, signal) {
|
|
|
3153
3204
|
return wait;
|
|
3154
3205
|
if (signal.aborted)
|
|
3155
3206
|
return Promise.reject(abortError2(signal));
|
|
3156
|
-
return new Promise((
|
|
3207
|
+
return new Promise((resolve, reject) => {
|
|
3157
3208
|
const onAbort = () => {
|
|
3158
3209
|
signal.removeEventListener("abort", onAbort);
|
|
3159
3210
|
reject(abortError2(signal));
|
|
@@ -3161,7 +3212,7 @@ function waitForDiagnosticsActivity(wait, signal) {
|
|
|
3161
3212
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
3162
3213
|
wait.then(() => {
|
|
3163
3214
|
signal.removeEventListener("abort", onAbort);
|
|
3164
|
-
|
|
3215
|
+
resolve();
|
|
3165
3216
|
}, (error) => {
|
|
3166
3217
|
signal.removeEventListener("abort", onAbort);
|
|
3167
3218
|
reject(error);
|
|
@@ -3229,7 +3280,7 @@ async function stopClientBestEffort(client) {
|
|
|
3229
3280
|
function awaitWithSignal(promise, signal) {
|
|
3230
3281
|
if (!signal)
|
|
3231
3282
|
return promise;
|
|
3232
|
-
return new Promise((
|
|
3283
|
+
return new Promise((resolve, reject) => {
|
|
3233
3284
|
let settled = false;
|
|
3234
3285
|
const onAbort = () => {
|
|
3235
3286
|
if (settled)
|
|
@@ -3247,7 +3298,7 @@ function awaitWithSignal(promise, signal) {
|
|
|
3247
3298
|
return;
|
|
3248
3299
|
settled = true;
|
|
3249
3300
|
signal.removeEventListener("abort", onAbort);
|
|
3250
|
-
|
|
3301
|
+
resolve(value);
|
|
3251
3302
|
}, (err) => {
|
|
3252
3303
|
if (settled)
|
|
3253
3304
|
return;
|
|
@@ -3259,20 +3310,18 @@ function awaitWithSignal(promise, signal) {
|
|
|
3259
3310
|
}
|
|
3260
3311
|
|
|
3261
3312
|
class LspManager {
|
|
3262
|
-
clients = new Map;
|
|
3263
|
-
reaperHandle = null;
|
|
3264
|
-
signalDisposer = null;
|
|
3265
|
-
disposed = false;
|
|
3266
|
-
idleTimeoutMs;
|
|
3267
|
-
initTimeoutMs;
|
|
3268
|
-
reaperIntervalMs;
|
|
3269
|
-
clientFactory;
|
|
3270
|
-
now;
|
|
3271
3313
|
constructor(options = {}) {
|
|
3314
|
+
this.clients = new Map;
|
|
3315
|
+
this.pendingStops = new Map;
|
|
3316
|
+
this.respawnBudgets = new Map;
|
|
3317
|
+
this.reaperHandle = null;
|
|
3318
|
+
this.signalDisposer = null;
|
|
3319
|
+
this.disposed = false;
|
|
3272
3320
|
this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
|
|
3273
3321
|
this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
3322
|
+
this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
|
|
3274
3323
|
this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
|
|
3275
|
-
this.clientFactory = options.clientFactory ?? ((root,
|
|
3324
|
+
this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
|
|
3276
3325
|
this.now = options.now ?? (() => Date.now());
|
|
3277
3326
|
this.startReaper();
|
|
3278
3327
|
this.signalDisposer = installProcessSignalCleanup(() => this.stopAll());
|
|
@@ -3290,38 +3339,103 @@ class LspManager {
|
|
|
3290
3339
|
getKey(root, serverId) {
|
|
3291
3340
|
return `${root}::${serverId}`;
|
|
3292
3341
|
}
|
|
3342
|
+
tombstoneStop(key, client) {
|
|
3343
|
+
const stop = stopClientBestEffort(client);
|
|
3344
|
+
this.pendingStops.set(key, stop);
|
|
3345
|
+
stop.finally(() => {
|
|
3346
|
+
if (this.pendingStops.get(key) === stop) {
|
|
3347
|
+
this.pendingStops.delete(key);
|
|
3348
|
+
}
|
|
3349
|
+
});
|
|
3350
|
+
return stop;
|
|
3351
|
+
}
|
|
3352
|
+
recordDeadGeneration(key) {
|
|
3353
|
+
let budget = this.respawnBudgets.get(key);
|
|
3354
|
+
if (budget === undefined) {
|
|
3355
|
+
budget = { deadGenerations: 0, exhaustedAt: null };
|
|
3356
|
+
this.respawnBudgets.set(key, budget);
|
|
3357
|
+
}
|
|
3358
|
+
budget.deadGenerations += 1;
|
|
3359
|
+
}
|
|
3360
|
+
markHealthyGeneration(key) {
|
|
3361
|
+
this.respawnBudgets.delete(key);
|
|
3362
|
+
}
|
|
3363
|
+
ensureRespawnAllowed(key, root, serverId) {
|
|
3364
|
+
const budget = this.respawnBudgets.get(key);
|
|
3365
|
+
if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
|
|
3366
|
+
return;
|
|
3367
|
+
if (budget.exhaustedAt === null) {
|
|
3368
|
+
budget.exhaustedAt = this.now();
|
|
3369
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
3370
|
+
}
|
|
3371
|
+
if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
|
|
3372
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
3373
|
+
}
|
|
3374
|
+
budget.deadGenerations = 0;
|
|
3375
|
+
budget.exhaustedAt = null;
|
|
3376
|
+
}
|
|
3293
3377
|
reapStale() {
|
|
3294
3378
|
const t = this.now();
|
|
3295
3379
|
for (const [key, managed] of this.clients) {
|
|
3296
3380
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3297
|
-
stopClientBestEffort(managed.client);
|
|
3298
3381
|
this.clients.delete(key);
|
|
3382
|
+
this.tombstoneStop(key, managed.client);
|
|
3299
3383
|
continue;
|
|
3300
3384
|
}
|
|
3301
3385
|
if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
|
|
3302
|
-
stopClientBestEffort(managed.client);
|
|
3303
3386
|
this.clients.delete(key);
|
|
3387
|
+
this.tombstoneStop(key, managed.client);
|
|
3388
|
+
}
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3391
|
+
evictForAdmission() {
|
|
3392
|
+
while (this.clients.size >= this.maxResidentClients) {
|
|
3393
|
+
const victim = this.leastRecentlyUsedIdleClient();
|
|
3394
|
+
if (!victim)
|
|
3395
|
+
return;
|
|
3396
|
+
this.clients.delete(victim.key);
|
|
3397
|
+
this.tombstoneStop(victim.key, victim.managed.client);
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3400
|
+
leastRecentlyUsedIdleClient() {
|
|
3401
|
+
let candidate = null;
|
|
3402
|
+
for (const [key, managed] of this.clients) {
|
|
3403
|
+
if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
|
|
3404
|
+
continue;
|
|
3405
|
+
if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
|
|
3406
|
+
candidate = { key, managed };
|
|
3304
3407
|
}
|
|
3305
3408
|
}
|
|
3409
|
+
return candidate;
|
|
3306
3410
|
}
|
|
3307
3411
|
async tryDeleteIfOrphaned(key, managed) {
|
|
3308
3412
|
if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
|
|
3309
3413
|
this.clients.delete(key);
|
|
3310
|
-
await
|
|
3414
|
+
await this.tombstoneStop(key, managed.client);
|
|
3311
3415
|
}
|
|
3312
3416
|
}
|
|
3313
|
-
async getClient(root,
|
|
3417
|
+
async getClient(root, server, signal) {
|
|
3314
3418
|
if (this.disposed) {
|
|
3315
3419
|
throw new Error("LspManager has been disposed");
|
|
3316
3420
|
}
|
|
3317
3421
|
signal?.throwIfAborted();
|
|
3318
|
-
const key = this.getKey(root,
|
|
3422
|
+
const key = this.getKey(root, server.id);
|
|
3423
|
+
for (;; ) {
|
|
3424
|
+
const pendingStop = this.pendingStops.get(key);
|
|
3425
|
+
if (pendingStop === undefined)
|
|
3426
|
+
break;
|
|
3427
|
+
await awaitWithSignal(pendingStop, signal);
|
|
3428
|
+
signal?.throwIfAborted();
|
|
3429
|
+
}
|
|
3430
|
+
if (this.disposed) {
|
|
3431
|
+
throw new Error("LspManager has been disposed");
|
|
3432
|
+
}
|
|
3319
3433
|
let managed = this.clients.get(key);
|
|
3320
3434
|
if (managed) {
|
|
3321
3435
|
const t = this.now();
|
|
3322
3436
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3323
|
-
await stopClientBestEffort(managed.client);
|
|
3324
3437
|
this.clients.delete(key);
|
|
3438
|
+
await this.tombstoneStop(key, managed.client);
|
|
3325
3439
|
managed = undefined;
|
|
3326
3440
|
}
|
|
3327
3441
|
}
|
|
@@ -3342,15 +3456,21 @@ class LspManager {
|
|
|
3342
3456
|
signal.throwIfAborted();
|
|
3343
3457
|
}
|
|
3344
3458
|
if (!managed.client.isAlive()) {
|
|
3345
|
-
|
|
3346
|
-
this.clients.
|
|
3347
|
-
|
|
3459
|
+
this.recordDeadGeneration(key);
|
|
3460
|
+
if (this.clients.get(key) === managed) {
|
|
3461
|
+
this.clients.delete(key);
|
|
3462
|
+
}
|
|
3463
|
+
await this.tombstoneStop(key, managed.client);
|
|
3464
|
+
return this.getClient(root, server, signal);
|
|
3348
3465
|
}
|
|
3466
|
+
this.markHealthyGeneration(key);
|
|
3349
3467
|
managed.refCount++;
|
|
3350
3468
|
managed.lastUsedAt = this.now();
|
|
3351
3469
|
return managed.client;
|
|
3352
3470
|
}
|
|
3353
|
-
|
|
3471
|
+
this.evictForAdmission();
|
|
3472
|
+
this.ensureRespawnAllowed(key, root, server.id);
|
|
3473
|
+
const client = this.clientFactory(root, server);
|
|
3354
3474
|
const initStartedAt = this.now();
|
|
3355
3475
|
const initPromise = (async () => {
|
|
3356
3476
|
await client.start();
|
|
@@ -3373,7 +3493,7 @@ class LspManager {
|
|
|
3373
3493
|
if (this.clients.get(key) === newManaged) {
|
|
3374
3494
|
this.clients.delete(key);
|
|
3375
3495
|
}
|
|
3376
|
-
await
|
|
3496
|
+
await this.tombstoneStop(key, client);
|
|
3377
3497
|
throw err;
|
|
3378
3498
|
}
|
|
3379
3499
|
newManaged.pendingWaiters--;
|
|
@@ -3384,6 +3504,15 @@ class LspManager {
|
|
|
3384
3504
|
await this.tryDeleteIfOrphaned(key, newManaged);
|
|
3385
3505
|
signal.throwIfAborted();
|
|
3386
3506
|
}
|
|
3507
|
+
if (!client.isAlive()) {
|
|
3508
|
+
this.recordDeadGeneration(key);
|
|
3509
|
+
if (this.clients.get(key) === newManaged) {
|
|
3510
|
+
this.clients.delete(key);
|
|
3511
|
+
}
|
|
3512
|
+
await this.tombstoneStop(key, client);
|
|
3513
|
+
return this.getClient(root, server, signal);
|
|
3514
|
+
}
|
|
3515
|
+
this.markHealthyGeneration(key);
|
|
3387
3516
|
newManaged.refCount++;
|
|
3388
3517
|
newManaged.lastUsedAt = this.now();
|
|
3389
3518
|
return client;
|
|
@@ -3404,15 +3533,21 @@ class LspManager {
|
|
|
3404
3533
|
if (client && managed.client !== client)
|
|
3405
3534
|
return;
|
|
3406
3535
|
this.clients.delete(key);
|
|
3407
|
-
|
|
3536
|
+
this.tombstoneStop(key, managed.client);
|
|
3408
3537
|
}
|
|
3409
|
-
warmupClient(root,
|
|
3538
|
+
warmupClient(root, server) {
|
|
3410
3539
|
if (this.disposed)
|
|
3411
3540
|
return;
|
|
3412
|
-
const key = this.getKey(root,
|
|
3413
|
-
if (this.clients.has(key))
|
|
3541
|
+
const key = this.getKey(root, server.id);
|
|
3542
|
+
if (this.clients.has(key) || this.pendingStops.has(key))
|
|
3414
3543
|
return;
|
|
3415
|
-
|
|
3544
|
+
this.evictForAdmission();
|
|
3545
|
+
try {
|
|
3546
|
+
this.ensureRespawnAllowed(key, root, server.id);
|
|
3547
|
+
} catch {
|
|
3548
|
+
return;
|
|
3549
|
+
}
|
|
3550
|
+
const client = this.clientFactory(root, server);
|
|
3416
3551
|
const initStartedAt = this.now();
|
|
3417
3552
|
const initPromise = (async () => {
|
|
3418
3553
|
await client.start();
|
|
@@ -3437,7 +3572,7 @@ class LspManager {
|
|
|
3437
3572
|
if (this.clients.get(key) === managed) {
|
|
3438
3573
|
this.clients.delete(key);
|
|
3439
3574
|
}
|
|
3440
|
-
|
|
3575
|
+
this.tombstoneStop(key, client);
|
|
3441
3576
|
});
|
|
3442
3577
|
}
|
|
3443
3578
|
isServerInitializing(root, serverId) {
|
|
@@ -3481,8 +3616,11 @@ class LspManager {
|
|
|
3481
3616
|
for (const managed of this.clients.values()) {
|
|
3482
3617
|
stopPromises.push(stopClientBestEffort(managed.client));
|
|
3483
3618
|
}
|
|
3619
|
+
const tombstonedStops = [...this.pendingStops.values()];
|
|
3484
3620
|
this.clients.clear();
|
|
3485
|
-
|
|
3621
|
+
this.respawnBudgets.clear();
|
|
3622
|
+
await Promise.allSettled([...stopPromises, ...tombstonedStops]);
|
|
3623
|
+
this.pendingStops.clear();
|
|
3486
3624
|
}
|
|
3487
3625
|
}
|
|
3488
3626
|
var _defaultInstance = null;
|
|
@@ -3500,57 +3638,52 @@ async function disposeDefaultLspManager() {
|
|
|
3500
3638
|
}
|
|
3501
3639
|
}
|
|
3502
3640
|
|
|
3503
|
-
// ../lsp-core/src/lsp/
|
|
3504
|
-
import { existsSync as existsSync6,
|
|
3505
|
-
import { dirname as dirname5 } from "node:path";
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3641
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
3642
|
+
import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
|
|
3643
|
+
import { dirname as dirname5, join as join3 } from "node:path";
|
|
3644
|
+
|
|
3645
|
+
// ../lsp-core/src/lsp/workspace-markers.ts
|
|
3646
|
+
var GIT_WORKSPACE_MARKER = ".git";
|
|
3647
|
+
var PROJECT_WORKSPACE_MARKERS = [
|
|
3648
|
+
"package.json",
|
|
3649
|
+
"pyproject.toml",
|
|
3650
|
+
"Cargo.toml",
|
|
3651
|
+
"go.mod",
|
|
3652
|
+
"pom.xml",
|
|
3653
|
+
"build.gradle"
|
|
3654
|
+
];
|
|
3655
|
+
var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
|
|
3656
|
+
|
|
3657
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
3658
|
+
function findWorkspaceRootOutsideContext(directory) {
|
|
3659
|
+
const marked = nearestMarkedAncestor(directory);
|
|
3660
|
+
if (marked !== undefined)
|
|
3661
|
+
return marked;
|
|
3662
|
+
return realpathSync4(nearestExistingAncestor(directory));
|
|
3663
|
+
}
|
|
3664
|
+
function nearestMarkedAncestor(directory) {
|
|
3665
|
+
let current = directory;
|
|
3666
|
+
for (;; ) {
|
|
3667
|
+
if (existsSync6(current) && WORKSPACE_MARKERS.some((marker) => existsSync6(join3(current, marker)))) {
|
|
3668
|
+
return realpathSync4(current);
|
|
3669
|
+
}
|
|
3670
|
+
const parent = dirname5(current);
|
|
3671
|
+
if (parent === current)
|
|
3672
|
+
return;
|
|
3673
|
+
current = parent;
|
|
3518
3674
|
}
|
|
3519
3675
|
}
|
|
3520
|
-
function
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
}
|
|
3528
|
-
|
|
3529
|
-
return value === "declined" || value === "allowed";
|
|
3530
|
-
}
|
|
3531
|
-
function writeInstallDecisions(decisions) {
|
|
3532
|
-
const path = getInstallDecisionsPath();
|
|
3533
|
-
mkdirSync(dirname5(path), { recursive: true });
|
|
3534
|
-
const tmpPath = `${path}.tmp`;
|
|
3535
|
-
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
3536
|
-
`, "utf8");
|
|
3537
|
-
renameSync2(tmpPath, path);
|
|
3538
|
-
}
|
|
3539
|
-
function isInstallDecisions(value) {
|
|
3540
|
-
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
3541
|
-
}
|
|
3542
|
-
function isInstallDecisionRecord(value) {
|
|
3543
|
-
if (!isRecord5(value))
|
|
3544
|
-
return false;
|
|
3545
|
-
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
3546
|
-
}
|
|
3547
|
-
function isRecord5(value) {
|
|
3548
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3676
|
+
function nearestExistingAncestor(directory) {
|
|
3677
|
+
let current = directory;
|
|
3678
|
+
while (!existsSync6(current)) {
|
|
3679
|
+
const parent = dirname5(current);
|
|
3680
|
+
if (parent === current)
|
|
3681
|
+
return current;
|
|
3682
|
+
current = parent;
|
|
3683
|
+
}
|
|
3684
|
+
return current;
|
|
3549
3685
|
}
|
|
3550
3686
|
|
|
3551
|
-
// ../lsp-core/src/lsp/config-loader.ts
|
|
3552
|
-
import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
|
|
3553
|
-
|
|
3554
3687
|
// ../lsp-core/src/lsp/server-definitions.ts
|
|
3555
3688
|
var LSP_INSTALL_HINTS = {
|
|
3556
3689
|
typescript: "npm install -g typescript-language-server typescript",
|
|
@@ -3596,6 +3729,26 @@ var LSP_INSTALL_HINTS = {
|
|
|
3596
3729
|
julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
|
|
3597
3730
|
razor: "Razor runs through the Roslyn language server (cohosting). " + "Install: dotnet tool install -g roslyn-language-server --prerelease (requires v5.8.0+). See https://github.com/dotnet/razor"
|
|
3598
3731
|
};
|
|
3732
|
+
var LSP_LOCAL_INSTALL_HINTS = {
|
|
3733
|
+
typescript: "bun add -d typescript-language-server typescript",
|
|
3734
|
+
vue: "bun add -d @vue/language-server",
|
|
3735
|
+
eslint: "bun add -d vscode-langservers-extracted",
|
|
3736
|
+
oxlint: "bun add -d oxlint",
|
|
3737
|
+
biome: "bun add -d @biomejs/biome",
|
|
3738
|
+
svelte: "bun add -d svelte-language-server",
|
|
3739
|
+
astro: "bun add -d @astrojs/language-server",
|
|
3740
|
+
bash: "bun add -d bash-language-server",
|
|
3741
|
+
"bash-ls": "bun add -d bash-language-server",
|
|
3742
|
+
"yaml-ls": "bun add -d yaml-language-server",
|
|
3743
|
+
php: "bun add -d intelephense",
|
|
3744
|
+
prisma: "bun add -d prisma",
|
|
3745
|
+
dockerfile: "bun add -d dockerfile-language-server-nodejs",
|
|
3746
|
+
pyright: "uv add --dev pyright",
|
|
3747
|
+
basedpyright: "uv add --dev basedpyright",
|
|
3748
|
+
ruff: "uv add --dev ruff",
|
|
3749
|
+
ty: "uv add --dev ty",
|
|
3750
|
+
"ruby-lsp": "bundle add ruby-lsp --group development"
|
|
3751
|
+
};
|
|
3599
3752
|
var BUILTIN_SERVERS = {
|
|
3600
3753
|
typescript: {
|
|
3601
3754
|
command: ["typescript-language-server", "--stdio"],
|
|
@@ -3698,7 +3851,56 @@ var BUILTIN_SERVERS = {
|
|
|
3698
3851
|
}
|
|
3699
3852
|
};
|
|
3700
3853
|
|
|
3854
|
+
// ../lsp-core/src/lsp/server-install-state.ts
|
|
3855
|
+
import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
3856
|
+
import { dirname as dirname6 } from "node:path";
|
|
3857
|
+
function getInstallDecisionsPath() {
|
|
3858
|
+
return lspRequestContext().installDecisionsPath;
|
|
3859
|
+
}
|
|
3860
|
+
function loadInstallDecisions() {
|
|
3861
|
+
const path = getInstallDecisionsPath();
|
|
3862
|
+
if (!existsSync7(path))
|
|
3863
|
+
return {};
|
|
3864
|
+
try {
|
|
3865
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
3866
|
+
return isInstallDecisions(parsed) ? parsed : {};
|
|
3867
|
+
} catch {
|
|
3868
|
+
return {};
|
|
3869
|
+
}
|
|
3870
|
+
}
|
|
3871
|
+
function loadInstallDecision(serverId) {
|
|
3872
|
+
return loadInstallDecisions()[serverId];
|
|
3873
|
+
}
|
|
3874
|
+
function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
|
|
3875
|
+
const decisions = loadInstallDecisions();
|
|
3876
|
+
decisions[serverId] = { decision, decidedAt };
|
|
3877
|
+
writeInstallDecisions(decisions);
|
|
3878
|
+
}
|
|
3879
|
+
function isInstallDecision(value) {
|
|
3880
|
+
return value === "declined" || value === "allowed";
|
|
3881
|
+
}
|
|
3882
|
+
function writeInstallDecisions(decisions) {
|
|
3883
|
+
const path = getInstallDecisionsPath();
|
|
3884
|
+
mkdirSync(dirname6(path), { recursive: true });
|
|
3885
|
+
const tmpPath = `${path}.tmp`;
|
|
3886
|
+
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
3887
|
+
`, "utf8");
|
|
3888
|
+
renameSync2(tmpPath, path);
|
|
3889
|
+
}
|
|
3890
|
+
function isInstallDecisions(value) {
|
|
3891
|
+
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
3892
|
+
}
|
|
3893
|
+
function isInstallDecisionRecord(value) {
|
|
3894
|
+
if (!isRecord5(value))
|
|
3895
|
+
return false;
|
|
3896
|
+
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
3897
|
+
}
|
|
3898
|
+
function isRecord5(value) {
|
|
3899
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3900
|
+
}
|
|
3901
|
+
|
|
3701
3902
|
// ../lsp-core/src/lsp/config-loader.ts
|
|
3903
|
+
import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
|
|
3702
3904
|
function getProjectConfigPaths() {
|
|
3703
3905
|
return lspRequestContext().projectConfigPaths;
|
|
3704
3906
|
}
|
|
@@ -3706,7 +3908,7 @@ function getUserConfigPath() {
|
|
|
3706
3908
|
return lspRequestContext().userConfigPath;
|
|
3707
3909
|
}
|
|
3708
3910
|
function loadJsonFile(path) {
|
|
3709
|
-
if (!
|
|
3911
|
+
if (!existsSync8(path))
|
|
3710
3912
|
return null;
|
|
3711
3913
|
try {
|
|
3712
3914
|
const parsed = JSON.parse(readFileSync4(path, "utf-8"));
|
|
@@ -3753,10 +3955,10 @@ function getMergedServers() {
|
|
|
3753
3955
|
}
|
|
3754
3956
|
if (seen.has(id))
|
|
3755
3957
|
continue;
|
|
3756
|
-
const
|
|
3757
|
-
if (!
|
|
3958
|
+
const server = createServerFromEntry(id, entry, source);
|
|
3959
|
+
if (!server)
|
|
3758
3960
|
continue;
|
|
3759
|
-
servers.push(
|
|
3961
|
+
servers.push(server);
|
|
3760
3962
|
seen.add(id);
|
|
3761
3963
|
}
|
|
3762
3964
|
}
|
|
@@ -3788,7 +3990,7 @@ function createServerFromEntry(id, entry, source) {
|
|
|
3788
3990
|
if (source === "project") {
|
|
3789
3991
|
if (!builtin)
|
|
3790
3992
|
return null;
|
|
3791
|
-
const
|
|
3993
|
+
const server = createServer({
|
|
3792
3994
|
id,
|
|
3793
3995
|
command: builtin.command,
|
|
3794
3996
|
extensions: entry.extensions ?? builtin.extensions,
|
|
@@ -3796,35 +3998,35 @@ function createServerFromEntry(id, entry, source) {
|
|
|
3796
3998
|
source
|
|
3797
3999
|
});
|
|
3798
4000
|
if (entry.initialization !== undefined) {
|
|
3799
|
-
|
|
4001
|
+
server.initialization = entry.initialization;
|
|
3800
4002
|
}
|
|
3801
|
-
return
|
|
4003
|
+
return server;
|
|
3802
4004
|
}
|
|
3803
4005
|
if (entry.command && entry.extensions) {
|
|
3804
|
-
const
|
|
4006
|
+
const server = createServer({
|
|
3805
4007
|
id,
|
|
3806
4008
|
command: entry.command,
|
|
3807
4009
|
extensions: entry.extensions,
|
|
3808
4010
|
priority: entry.priority ?? 0,
|
|
3809
4011
|
source
|
|
3810
4012
|
});
|
|
3811
|
-
applyOptionalServerFields(
|
|
3812
|
-
return
|
|
4013
|
+
applyOptionalServerFields(server, entry);
|
|
4014
|
+
return server;
|
|
3813
4015
|
}
|
|
3814
4016
|
if (!builtin)
|
|
3815
4017
|
return null;
|
|
3816
|
-
const
|
|
4018
|
+
const server = createServer({
|
|
3817
4019
|
id,
|
|
3818
4020
|
command: entry.command ?? builtin.command,
|
|
3819
4021
|
extensions: entry.extensions ?? builtin.extensions,
|
|
3820
4022
|
priority: entry.priority ?? 0,
|
|
3821
4023
|
source
|
|
3822
4024
|
});
|
|
3823
|
-
applyOptionalServerFields(
|
|
3824
|
-
return
|
|
4025
|
+
applyOptionalServerFields(server, entry);
|
|
4026
|
+
return server;
|
|
3825
4027
|
}
|
|
3826
4028
|
function createServer(input) {
|
|
3827
|
-
const
|
|
4029
|
+
const server = {
|
|
3828
4030
|
id: input.id,
|
|
3829
4031
|
command: input.command,
|
|
3830
4032
|
extensions: input.extensions,
|
|
@@ -3832,19 +4034,19 @@ function createServer(input) {
|
|
|
3832
4034
|
source: input.source
|
|
3833
4035
|
};
|
|
3834
4036
|
if (input.env !== undefined) {
|
|
3835
|
-
|
|
4037
|
+
server.env = input.env;
|
|
3836
4038
|
}
|
|
3837
4039
|
if (input.initialization !== undefined) {
|
|
3838
|
-
|
|
4040
|
+
server.initialization = input.initialization;
|
|
3839
4041
|
}
|
|
3840
|
-
return
|
|
4042
|
+
return server;
|
|
3841
4043
|
}
|
|
3842
|
-
function applyOptionalServerFields(
|
|
4044
|
+
function applyOptionalServerFields(server, entry) {
|
|
3843
4045
|
if (entry.env !== undefined) {
|
|
3844
|
-
|
|
4046
|
+
server.env = entry.env;
|
|
3845
4047
|
}
|
|
3846
4048
|
if (entry.initialization !== undefined) {
|
|
3847
|
-
|
|
4049
|
+
server.initialization = entry.initialization;
|
|
3848
4050
|
}
|
|
3849
4051
|
}
|
|
3850
4052
|
function isConfigJson(value) {
|
|
@@ -3894,64 +4096,165 @@ function getDisabledServerIds() {
|
|
|
3894
4096
|
}
|
|
3895
4097
|
|
|
3896
4098
|
// ../lsp-core/src/lsp/server-installation.ts
|
|
3897
|
-
import { existsSync as
|
|
3898
|
-
import { delimiter as delimiter3, join as
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
4099
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
4100
|
+
import { delimiter as delimiter3, dirname as dirname7, isAbsolute as isAbsolute3, join as join4, resolve as resolve7 } from "node:path";
|
|
4101
|
+
var LOCAL_BIN_RULES = [
|
|
4102
|
+
{
|
|
4103
|
+
markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
|
|
4104
|
+
binDirs: [join4("node_modules", ".bin")]
|
|
4105
|
+
},
|
|
4106
|
+
{
|
|
4107
|
+
markers: [
|
|
4108
|
+
"pyproject.toml",
|
|
4109
|
+
"ty.toml",
|
|
4110
|
+
"requirements.txt",
|
|
4111
|
+
"setup.py",
|
|
4112
|
+
"setup.cfg",
|
|
4113
|
+
"Pipfile",
|
|
4114
|
+
"pyrightconfig.json",
|
|
4115
|
+
"ruff.toml",
|
|
4116
|
+
".ruff.toml"
|
|
4117
|
+
],
|
|
4118
|
+
binDirs: [
|
|
4119
|
+
join4(".venv", "bin"),
|
|
4120
|
+
join4(".venv", "Scripts"),
|
|
4121
|
+
join4("venv", "bin"),
|
|
4122
|
+
join4("venv", "Scripts"),
|
|
4123
|
+
join4(".env", "bin"),
|
|
4124
|
+
join4(".env", "Scripts")
|
|
4125
|
+
]
|
|
4126
|
+
},
|
|
4127
|
+
{
|
|
4128
|
+
markers: ["Gemfile", "Gemfile.lock"],
|
|
4129
|
+
binDirs: [join4("vendor", "bundle", "bin"), "bin"]
|
|
4130
|
+
},
|
|
4131
|
+
{
|
|
4132
|
+
markers: ["go.mod", "go.sum", "go.work"],
|
|
4133
|
+
binDirs: ["bin"]
|
|
3908
4134
|
}
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
4135
|
+
];
|
|
4136
|
+
var resolutionCache = new Map;
|
|
4137
|
+
var probeCount = 0;
|
|
4138
|
+
function probe(path) {
|
|
4139
|
+
probeCount += 1;
|
|
4140
|
+
return existsSync9(path);
|
|
4141
|
+
}
|
|
4142
|
+
function executableSuffixes(platform, pathExt) {
|
|
4143
|
+
if (platform !== "win32")
|
|
4144
|
+
return [""];
|
|
4145
|
+
const configured = pathExt ?? process.env["PATHEXT"] ?? "";
|
|
4146
|
+
const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
|
|
4147
|
+
return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
|
|
4148
|
+
}
|
|
4149
|
+
function probeWithSuffixes(directory, command, suffixes) {
|
|
4150
|
+
for (const suffix of suffixes) {
|
|
4151
|
+
const candidate = join4(directory, command + suffix);
|
|
4152
|
+
if (probe(candidate))
|
|
4153
|
+
return candidate;
|
|
4154
|
+
}
|
|
4155
|
+
return null;
|
|
4156
|
+
}
|
|
4157
|
+
function resolveLocal(command, workingDirectory, suffixes, stopAt) {
|
|
4158
|
+
const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
|
|
4159
|
+
let current = resolve7(workingDirectory);
|
|
4160
|
+
while (true) {
|
|
4161
|
+
for (const rule of LOCAL_BIN_RULES) {
|
|
4162
|
+
if (!rule.markers.some((marker) => probe(join4(current, marker))))
|
|
4163
|
+
continue;
|
|
4164
|
+
for (const binDir of rule.binDirs) {
|
|
4165
|
+
const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
|
|
4166
|
+
if (found !== null)
|
|
4167
|
+
return found;
|
|
4168
|
+
}
|
|
3918
4169
|
}
|
|
4170
|
+
if (probe(join4(current, ".git")))
|
|
4171
|
+
return null;
|
|
4172
|
+
if (boundary !== undefined && current === boundary)
|
|
4173
|
+
return null;
|
|
4174
|
+
const parent = dirname7(current);
|
|
4175
|
+
if (parent === current)
|
|
4176
|
+
return null;
|
|
4177
|
+
current = parent;
|
|
3919
4178
|
}
|
|
3920
|
-
|
|
3921
|
-
|
|
4179
|
+
}
|
|
4180
|
+
function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
|
|
4181
|
+
let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
|
|
4182
|
+
if (platform === "win32" && !pathEnv) {
|
|
3922
4183
|
pathEnv = process.env["Path"] ?? "";
|
|
3923
4184
|
}
|
|
3924
|
-
const
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
}
|
|
4185
|
+
for (const entry of pathEnv.split(delimiter3)) {
|
|
4186
|
+
if (entry.length === 0)
|
|
4187
|
+
continue;
|
|
4188
|
+
const found = probeWithSuffixes(entry, command, suffixes);
|
|
4189
|
+
if (found !== null)
|
|
4190
|
+
return found;
|
|
3931
4191
|
}
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
4192
|
+
return null;
|
|
4193
|
+
}
|
|
4194
|
+
function resolveServerBinary(command, workingDirectory, options = {}) {
|
|
4195
|
+
if (command.length === 0)
|
|
4196
|
+
return null;
|
|
4197
|
+
const [cmd] = command;
|
|
4198
|
+
if (cmd === undefined || cmd.length === 0)
|
|
4199
|
+
return null;
|
|
4200
|
+
const platform = options.platform ?? process.platform;
|
|
4201
|
+
const suffixes = executableSuffixes(platform, options.pathExt);
|
|
4202
|
+
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
4203
|
+
const explicit = isAbsolute3(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
|
|
4204
|
+
return probe(explicit) ? explicit : null;
|
|
4205
|
+
}
|
|
4206
|
+
const cacheKey = JSON.stringify([
|
|
4207
|
+
workingDirectory ?? "",
|
|
4208
|
+
cmd,
|
|
4209
|
+
platform,
|
|
4210
|
+
options.stopAt ?? "",
|
|
4211
|
+
options.pathExt ?? "",
|
|
4212
|
+
options.pathEnv ?? process.env["PATH"] ?? ""
|
|
4213
|
+
]);
|
|
4214
|
+
const cached = resolutionCache.get(cacheKey);
|
|
4215
|
+
if (cached !== undefined)
|
|
4216
|
+
return cached;
|
|
4217
|
+
let resolved = null;
|
|
4218
|
+
if (workingDirectory !== undefined && workingDirectory.length > 0) {
|
|
4219
|
+
resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
|
|
4220
|
+
}
|
|
4221
|
+
resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
|
|
4222
|
+
if (resolved === null && cmd === "node")
|
|
4223
|
+
resolved = cmd;
|
|
4224
|
+
resolutionCache.set(cacheKey, resolved);
|
|
4225
|
+
return resolved;
|
|
4226
|
+
}
|
|
4227
|
+
function isServerInstalled(command, workingDirectory, options = {}) {
|
|
4228
|
+
if (command.length === 0)
|
|
4229
|
+
return false;
|
|
4230
|
+
return resolveServerBinary(command, workingDirectory, options) !== null;
|
|
3935
4231
|
}
|
|
3936
4232
|
|
|
3937
4233
|
// ../lsp-core/src/lsp/server-resolution.ts
|
|
4234
|
+
function withResolvedCommand(command, binaryPath) {
|
|
4235
|
+
return [binaryPath, ...command.slice(1)];
|
|
4236
|
+
}
|
|
3938
4237
|
function findServerForExtension(ext) {
|
|
3939
4238
|
const servers = getMergedServers();
|
|
3940
|
-
|
|
3941
|
-
|
|
4239
|
+
const workingDirectory = contextCwd();
|
|
4240
|
+
for (const server of servers) {
|
|
4241
|
+
if (!server.extensions.includes(ext))
|
|
4242
|
+
continue;
|
|
4243
|
+
const binaryPath = resolveServerBinary(server.command, workingDirectory);
|
|
4244
|
+
if (binaryPath !== null) {
|
|
3942
4245
|
const resolvedServer = {
|
|
3943
|
-
id:
|
|
3944
|
-
command:
|
|
3945
|
-
extensions:
|
|
3946
|
-
priority:
|
|
4246
|
+
id: server.id,
|
|
4247
|
+
command: withResolvedCommand(server.command, binaryPath),
|
|
4248
|
+
extensions: server.extensions,
|
|
4249
|
+
priority: server.priority
|
|
3947
4250
|
};
|
|
3948
|
-
if (
|
|
4251
|
+
if (server.env !== undefined) {
|
|
3949
4252
|
return {
|
|
3950
4253
|
status: "found",
|
|
3951
4254
|
server: {
|
|
3952
4255
|
...resolvedServer,
|
|
3953
|
-
env:
|
|
3954
|
-
...
|
|
4256
|
+
env: server.env,
|
|
4257
|
+
...server.initialization === undefined ? {} : { initialization: server.initialization }
|
|
3955
4258
|
}
|
|
3956
4259
|
};
|
|
3957
4260
|
}
|
|
@@ -3959,20 +4262,20 @@ function findServerForExtension(ext) {
|
|
|
3959
4262
|
status: "found",
|
|
3960
4263
|
server: {
|
|
3961
4264
|
...resolvedServer,
|
|
3962
|
-
...
|
|
4265
|
+
...server.initialization === undefined ? {} : { initialization: server.initialization }
|
|
3963
4266
|
}
|
|
3964
4267
|
};
|
|
3965
4268
|
}
|
|
3966
4269
|
}
|
|
3967
|
-
for (const
|
|
3968
|
-
if (
|
|
3969
|
-
const installHint = LSP_INSTALL_HINTS[
|
|
4270
|
+
for (const server of servers) {
|
|
4271
|
+
if (server.extensions.includes(ext)) {
|
|
4272
|
+
const installHint = LSP_INSTALL_HINTS[server.id] ?? `Install '${server.command[0]}' and ensure it's in your PATH`;
|
|
3970
4273
|
return {
|
|
3971
4274
|
status: "not_installed",
|
|
3972
4275
|
server: {
|
|
3973
|
-
id:
|
|
3974
|
-
command:
|
|
3975
|
-
extensions:
|
|
4276
|
+
id: server.id,
|
|
4277
|
+
command: server.command,
|
|
4278
|
+
extensions: server.extensions
|
|
3976
4279
|
},
|
|
3977
4280
|
installHint
|
|
3978
4281
|
};
|
|
@@ -3988,20 +4291,21 @@ function findServerForExtension(ext) {
|
|
|
3988
4291
|
function getAllServers() {
|
|
3989
4292
|
const servers = getMergedServers();
|
|
3990
4293
|
const disabled = getDisabledServerIds();
|
|
4294
|
+
const workingDirectory = contextCwd();
|
|
3991
4295
|
const result = [];
|
|
3992
4296
|
const seen = new Set;
|
|
3993
|
-
for (const
|
|
3994
|
-
if (seen.has(
|
|
4297
|
+
for (const server of servers) {
|
|
4298
|
+
if (seen.has(server.id))
|
|
3995
4299
|
continue;
|
|
3996
4300
|
result.push({
|
|
3997
|
-
id:
|
|
3998
|
-
installed: isServerInstalled(
|
|
3999
|
-
extensions:
|
|
4301
|
+
id: server.id,
|
|
4302
|
+
installed: isServerInstalled(server.command, workingDirectory),
|
|
4303
|
+
extensions: server.extensions,
|
|
4000
4304
|
disabled: false,
|
|
4001
|
-
source:
|
|
4002
|
-
priority:
|
|
4305
|
+
source: server.source,
|
|
4306
|
+
priority: server.priority
|
|
4003
4307
|
});
|
|
4004
|
-
seen.add(
|
|
4308
|
+
seen.add(server.id);
|
|
4005
4309
|
}
|
|
4006
4310
|
for (const id of disabled) {
|
|
4007
4311
|
if (seen.has(id))
|
|
@@ -4009,7 +4313,7 @@ function getAllServers() {
|
|
|
4009
4313
|
const builtin = BUILTIN_SERVERS[id];
|
|
4010
4314
|
result.push({
|
|
4011
4315
|
id,
|
|
4012
|
-
installed: builtin ? isServerInstalled(builtin.command) : false,
|
|
4316
|
+
installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
|
|
4013
4317
|
extensions: builtin?.extensions ?? [],
|
|
4014
4318
|
disabled: true,
|
|
4015
4319
|
source: "disabled",
|
|
@@ -4020,7 +4324,6 @@ function getAllServers() {
|
|
|
4020
4324
|
}
|
|
4021
4325
|
|
|
4022
4326
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
4023
|
-
var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
4024
4327
|
function isDirectoryPath(filePath) {
|
|
4025
4328
|
try {
|
|
4026
4329
|
return statSync3(filePath).isDirectory();
|
|
@@ -4029,32 +4332,90 @@ function isDirectoryPath(filePath) {
|
|
|
4029
4332
|
}
|
|
4030
4333
|
}
|
|
4031
4334
|
function findWorkspaceRoot(filePath) {
|
|
4032
|
-
const
|
|
4335
|
+
const cwd = contextCwd();
|
|
4336
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4033
4337
|
let dir = abs;
|
|
4034
4338
|
if (!isDirectoryPath(dir)) {
|
|
4035
|
-
dir =
|
|
4036
|
-
}
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4339
|
+
dir = dirname8(dir);
|
|
4340
|
+
}
|
|
4341
|
+
if (!isPathInside(cwd, abs))
|
|
4342
|
+
return findWorkspaceRootOutsideContext(dir);
|
|
4343
|
+
const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
|
|
4344
|
+
let nearestPackageRoot;
|
|
4345
|
+
while (isPathInside(cwd, dir)) {
|
|
4346
|
+
const canonicalDir = existingDirectoryInsideContext(dir, cwd);
|
|
4347
|
+
if (canonicalDir !== undefined) {
|
|
4348
|
+
if (existsSync10(join5(dir, GIT_WORKSPACE_MARKER))) {
|
|
4349
|
+
return canonicalDir;
|
|
4350
|
+
}
|
|
4351
|
+
if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
|
|
4352
|
+
nearestPackageRoot = canonicalDir;
|
|
4042
4353
|
}
|
|
4043
4354
|
}
|
|
4044
|
-
|
|
4045
|
-
|
|
4355
|
+
if (dir === cwd)
|
|
4356
|
+
break;
|
|
4357
|
+
dir = dirname8(dir);
|
|
4046
4358
|
}
|
|
4047
|
-
return
|
|
4359
|
+
return nearestPackageRoot ?? fallbackRoot;
|
|
4360
|
+
}
|
|
4361
|
+
function hasProjectWorkspaceMarker(directory) {
|
|
4362
|
+
return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync10(join5(directory, marker)));
|
|
4363
|
+
}
|
|
4364
|
+
function resolveReadablePathInsideContext(filePath) {
|
|
4365
|
+
const cwd = contextCwd();
|
|
4366
|
+
const abs = resolve8(cwd, filePath);
|
|
4367
|
+
if (isPathInside(cwd, abs))
|
|
4368
|
+
return abs;
|
|
4369
|
+
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
4370
|
+
if (rebased !== undefined)
|
|
4371
|
+
return rebased;
|
|
4372
|
+
return canonicalizeExistingOrNearestAncestor(abs);
|
|
4048
4373
|
}
|
|
4049
4374
|
function resolvePathInsideContext(filePath) {
|
|
4050
4375
|
const cwd = contextCwd();
|
|
4051
|
-
const abs =
|
|
4376
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4052
4377
|
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
4053
4378
|
if (!isPathInside(cwd, canonical)) {
|
|
4054
4379
|
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4055
4380
|
}
|
|
4056
4381
|
return canonical;
|
|
4057
4382
|
}
|
|
4383
|
+
function rebaseThroughCanonicalAncestor(path, cwd) {
|
|
4384
|
+
let current = path;
|
|
4385
|
+
const suffix = [];
|
|
4386
|
+
while (true) {
|
|
4387
|
+
if (existsSync10(current)) {
|
|
4388
|
+
const canonical = realpathSync5(current);
|
|
4389
|
+
if (isPathInside(cwd, canonical))
|
|
4390
|
+
return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
|
|
4391
|
+
}
|
|
4392
|
+
const parent = dirname8(current);
|
|
4393
|
+
if (parent === current)
|
|
4394
|
+
return;
|
|
4395
|
+
suffix.unshift(basename3(current));
|
|
4396
|
+
current = parent;
|
|
4397
|
+
}
|
|
4398
|
+
}
|
|
4399
|
+
function existingDirectoryInsideContext(directory, cwd) {
|
|
4400
|
+
if (!existsSync10(directory))
|
|
4401
|
+
return;
|
|
4402
|
+
const canonical = realpathSync5(directory);
|
|
4403
|
+
if (!statSync3(canonical).isDirectory())
|
|
4404
|
+
return;
|
|
4405
|
+
return isPathInside(cwd, canonical) ? canonical : undefined;
|
|
4406
|
+
}
|
|
4407
|
+
function nearestExistingDirectoryInsideContext(directory, cwd) {
|
|
4408
|
+
let current = directory;
|
|
4409
|
+
while (isPathInside(cwd, current)) {
|
|
4410
|
+
const canonical = existingDirectoryInsideContext(current, cwd);
|
|
4411
|
+
if (canonical !== undefined)
|
|
4412
|
+
return canonical;
|
|
4413
|
+
if (current === cwd)
|
|
4414
|
+
return;
|
|
4415
|
+
current = dirname8(current);
|
|
4416
|
+
}
|
|
4417
|
+
return;
|
|
4418
|
+
}
|
|
4058
4419
|
function formatServerLookupError(result) {
|
|
4059
4420
|
if (result.status === "not_installed") {
|
|
4060
4421
|
return formatNotInstalled(result);
|
|
@@ -4078,33 +4439,46 @@ function formatServerLookupError(result) {
|
|
|
4078
4439
|
].join(`
|
|
4079
4440
|
`);
|
|
4080
4441
|
}
|
|
4442
|
+
function formatInstallOptions(serverId, installHint) {
|
|
4443
|
+
const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
|
|
4444
|
+
if (localHint === undefined) {
|
|
4445
|
+
return ["To install, run:", ` ${installHint}`];
|
|
4446
|
+
}
|
|
4447
|
+
return [
|
|
4448
|
+
"To install in THIS repository (preferred — no global install needed):",
|
|
4449
|
+
` ${localHint}`,
|
|
4450
|
+
"",
|
|
4451
|
+
"Or install it globally:",
|
|
4452
|
+
` ${installHint}`
|
|
4453
|
+
];
|
|
4454
|
+
}
|
|
4081
4455
|
function formatNotInstalled(result) {
|
|
4082
|
-
const { server
|
|
4083
|
-
const extensions =
|
|
4084
|
-
const decision = loadInstallDecision(
|
|
4456
|
+
const { server, installHint } = result;
|
|
4457
|
+
const extensions = server.extensions.join(", ");
|
|
4458
|
+
const decision = loadInstallDecision(server.id)?.decision;
|
|
4085
4459
|
const context = lspRequestContext();
|
|
4086
4460
|
if (decision === "declined") {
|
|
4087
|
-
return `LSP server '${
|
|
4461
|
+
return `LSP server '${server.id}' (${extensions}) is NOT INSTALLED; user previously declined installation — proceed without LSP.`;
|
|
4088
4462
|
}
|
|
4089
4463
|
const header = [
|
|
4090
|
-
`LSP server '${
|
|
4464
|
+
`LSP server '${server.id}' for ${extensions} is NOT INSTALLED.`,
|
|
4091
4465
|
"",
|
|
4092
|
-
`Command not found: ${
|
|
4466
|
+
`Command not found: ${server.command[0]}`,
|
|
4093
4467
|
""
|
|
4094
4468
|
];
|
|
4469
|
+
const installOptions = formatInstallOptions(server.id, installHint);
|
|
4095
4470
|
if (decision === "allowed") {
|
|
4096
4471
|
return [
|
|
4097
4472
|
...header,
|
|
4098
4473
|
"The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
|
|
4099
|
-
|
|
4474
|
+
...installOptions.slice(1)
|
|
4100
4475
|
].join(`
|
|
4101
4476
|
`);
|
|
4102
4477
|
}
|
|
4103
4478
|
if (!context.capabilities.installDecisionTool) {
|
|
4104
4479
|
return [
|
|
4105
4480
|
...header,
|
|
4106
|
-
|
|
4107
|
-
` ${installHint}`,
|
|
4481
|
+
...installOptions,
|
|
4108
4482
|
"",
|
|
4109
4483
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4110
4484
|
"Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
|
|
@@ -4113,19 +4487,18 @@ function formatNotInstalled(result) {
|
|
|
4113
4487
|
}
|
|
4114
4488
|
return [
|
|
4115
4489
|
...header,
|
|
4116
|
-
|
|
4117
|
-
` ${installHint}`,
|
|
4490
|
+
...installOptions,
|
|
4118
4491
|
"",
|
|
4119
4492
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4120
4493
|
"- If the user agrees: run the install command above, then retry this tool.",
|
|
4121
4494
|
"- If the user declines, OR has NOT explicitly asked for LSP installation:",
|
|
4122
|
-
` call lsp_install_decision { server_id: "${
|
|
4495
|
+
` call lsp_install_decision { server_id: "${server.id}", decision: "declined" },`,
|
|
4123
4496
|
` which writes to ${context.installDecisionsPath},`,
|
|
4124
4497
|
" then ignore this message and proceed WITHOUT LSP."
|
|
4125
4498
|
].join(`
|
|
4126
4499
|
`);
|
|
4127
4500
|
}
|
|
4128
|
-
var
|
|
4501
|
+
var READ_ONLY_TOOLS = new Set([
|
|
4129
4502
|
"diagnostics",
|
|
4130
4503
|
"definition",
|
|
4131
4504
|
"references",
|
|
@@ -4134,7 +4507,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
|
|
|
4134
4507
|
"prepareRename"
|
|
4135
4508
|
]);
|
|
4136
4509
|
async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
4137
|
-
const absPath = resolvePathInsideContext(filePath);
|
|
4510
|
+
const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
|
|
4138
4511
|
if (isDirectoryPath(absPath)) {
|
|
4139
4512
|
throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
|
|
4140
4513
|
}
|
|
@@ -4143,34 +4516,34 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4143
4516
|
if (result.status !== "found") {
|
|
4144
4517
|
throw new LspServerLookupError(formatServerLookupError(result), result);
|
|
4145
4518
|
}
|
|
4146
|
-
const
|
|
4519
|
+
const server = result.server;
|
|
4147
4520
|
const root = findWorkspaceRoot(absPath);
|
|
4148
4521
|
const manager = options.manager ?? getLspManager();
|
|
4149
4522
|
const acquireAndCall = async (allowRetry) => {
|
|
4150
|
-
const client = await manager.getClient(root,
|
|
4523
|
+
const client = await manager.getClient(root, server, options.signal);
|
|
4151
4524
|
try {
|
|
4152
|
-
return await fn(client, root);
|
|
4525
|
+
return await fn(client, root, absPath);
|
|
4153
4526
|
} catch (err) {
|
|
4154
|
-
if (allowRetry &&
|
|
4155
|
-
manager.invalidateClient(root,
|
|
4527
|
+
if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
|
|
4528
|
+
manager.invalidateClient(root, server.id, client);
|
|
4156
4529
|
return acquireAndCall(false);
|
|
4157
4530
|
}
|
|
4158
4531
|
if (err instanceof LspRequestTimeoutError) {
|
|
4159
|
-
if (manager.isServerInitializing(root,
|
|
4532
|
+
if (manager.isServerInitializing(root, server.id)) {
|
|
4160
4533
|
throw new LspServerInitializingError(err);
|
|
4161
4534
|
}
|
|
4162
4535
|
}
|
|
4163
4536
|
throw err;
|
|
4164
4537
|
} finally {
|
|
4165
|
-
manager.releaseClient(root,
|
|
4538
|
+
manager.releaseClient(root, server.id);
|
|
4166
4539
|
}
|
|
4167
4540
|
};
|
|
4168
4541
|
return acquireAndCall(true);
|
|
4169
4542
|
}
|
|
4170
4543
|
|
|
4171
4544
|
// ../lsp-core/src/lsp/directory-diagnostics.ts
|
|
4172
|
-
import { existsSync as
|
|
4173
|
-
import { join as
|
|
4545
|
+
import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
|
|
4546
|
+
import { join as join6, resolve as resolve9 } from "node:path";
|
|
4174
4547
|
|
|
4175
4548
|
// ../lsp-core/src/lsp/formatters.ts
|
|
4176
4549
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -4185,10 +4558,10 @@ function uriToPath(uri) {
|
|
|
4185
4558
|
}
|
|
4186
4559
|
function formatLocation(loc) {
|
|
4187
4560
|
if ("targetUri" in loc) {
|
|
4188
|
-
const
|
|
4189
|
-
const
|
|
4190
|
-
const
|
|
4191
|
-
return `${
|
|
4561
|
+
const uri = uriToPath(loc.targetUri);
|
|
4562
|
+
const line = loc.targetRange.start.line + 1;
|
|
4563
|
+
const char = loc.targetRange.start.character;
|
|
4564
|
+
return `${uri}:${line}:${char}`;
|
|
4192
4565
|
}
|
|
4193
4566
|
const uri = uriToPath(loc.uri);
|
|
4194
4567
|
const line = loc.range.start.line + 1;
|
|
@@ -4300,7 +4673,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
|
|
|
4300
4673
|
for (const entry of entries) {
|
|
4301
4674
|
if (files.length >= maxFiles)
|
|
4302
4675
|
return;
|
|
4303
|
-
const fullPath =
|
|
4676
|
+
const fullPath = join6(currentDir, entry);
|
|
4304
4677
|
let stat;
|
|
4305
4678
|
try {
|
|
4306
4679
|
stat = lstatSync4(fullPath);
|
|
@@ -4325,15 +4698,15 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4325
4698
|
if (!extension.startsWith(".")) {
|
|
4326
4699
|
throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
|
|
4327
4700
|
}
|
|
4328
|
-
const absDir =
|
|
4329
|
-
if (!
|
|
4701
|
+
const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
|
|
4702
|
+
if (!existsSync11(absDir)) {
|
|
4330
4703
|
throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
|
|
4331
4704
|
}
|
|
4332
4705
|
const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
|
|
4333
4706
|
if (serverResult.status !== "found") {
|
|
4334
4707
|
throw new LspServerLookupError(formatServerLookupError(serverResult));
|
|
4335
4708
|
}
|
|
4336
|
-
const
|
|
4709
|
+
const server = serverResult.server;
|
|
4337
4710
|
const allFiles = (options.listFiles ?? collectFilesWithExtension)(absDir, extension, maxFiles + 1);
|
|
4338
4711
|
const wasCapped = allFiles.length > maxFiles;
|
|
4339
4712
|
const filesToProcess = allFiles.slice(0, maxFiles);
|
|
@@ -4353,7 +4726,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4353
4726
|
const fileErrors = [];
|
|
4354
4727
|
const maxConcurrency = Math.max(1, options.maxConcurrency ?? DIRECTORY_DIAGNOSTICS_MAX_CONCURRENCY);
|
|
4355
4728
|
options.signal?.throwIfAborted();
|
|
4356
|
-
const client = await manager.getClient(root,
|
|
4729
|
+
const client = await manager.getClient(root, server, options.signal);
|
|
4357
4730
|
try {
|
|
4358
4731
|
let nextIndex = 0;
|
|
4359
4732
|
const workers = Array.from({ length: Math.min(maxConcurrency, filesToProcess.length) }, async () => {
|
|
@@ -4381,7 +4754,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4381
4754
|
});
|
|
4382
4755
|
await Promise.all(workers);
|
|
4383
4756
|
} finally {
|
|
4384
|
-
manager.releaseClient(root,
|
|
4757
|
+
manager.releaseClient(root, server.id);
|
|
4385
4758
|
}
|
|
4386
4759
|
const displayDiagnostics = allDiagnostics.slice(0, DEFAULT_MAX_DIAGNOSTICS);
|
|
4387
4760
|
const wasDiagCapped = allDiagnostics.length > DEFAULT_MAX_DIAGNOSTICS;
|
|
@@ -4413,7 +4786,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4413
4786
|
|
|
4414
4787
|
// ../lsp-core/src/lsp/infer-extension.ts
|
|
4415
4788
|
import { lstatSync as lstatSync5, readdirSync as readdirSync4 } from "node:fs";
|
|
4416
|
-
import { join as
|
|
4789
|
+
import { join as join7 } from "node:path";
|
|
4417
4790
|
var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
|
|
4418
4791
|
var MAX_SCAN_ENTRIES = 500;
|
|
4419
4792
|
function inferExtensionFromDirectory(directory) {
|
|
@@ -4431,7 +4804,7 @@ function inferExtensionFromDirectory(directory) {
|
|
|
4431
4804
|
for (const entry of entries) {
|
|
4432
4805
|
if (scanned >= MAX_SCAN_ENTRIES)
|
|
4433
4806
|
return;
|
|
4434
|
-
const fullPath =
|
|
4807
|
+
const fullPath = join7(dir, entry);
|
|
4435
4808
|
let stat;
|
|
4436
4809
|
try {
|
|
4437
4810
|
stat = lstatSync5(fullPath);
|
|
@@ -4590,8 +4963,8 @@ function clientOptions(signal) {
|
|
|
4590
4963
|
}
|
|
4591
4964
|
|
|
4592
4965
|
// ../lsp-core/src/tools/result.ts
|
|
4593
|
-
function text(
|
|
4594
|
-
return { content: [{ type: "text", text
|
|
4966
|
+
function text(text, details, isError = false) {
|
|
4967
|
+
return { content: [{ type: "text", text }], details, isError };
|
|
4595
4968
|
}
|
|
4596
4969
|
|
|
4597
4970
|
// ../lsp-core/src/tools/diagnostics.ts
|
|
@@ -4606,12 +4979,12 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4606
4979
|
const filePath = requireString(params, "filePath");
|
|
4607
4980
|
const severity = severityFilter(params);
|
|
4608
4981
|
try {
|
|
4609
|
-
const absPath =
|
|
4982
|
+
const absPath = resolveReadablePathInsideContext(filePath);
|
|
4610
4983
|
if (isDirectoryPath(absPath)) {
|
|
4611
4984
|
const extension = inferExtensionFromDirectory(absPath);
|
|
4612
4985
|
if (!extension) {
|
|
4613
4986
|
const message = `No supported source files found in directory: ${absPath}`;
|
|
4614
|
-
const
|
|
4987
|
+
const details = {
|
|
4615
4988
|
filePath,
|
|
4616
4989
|
severity,
|
|
4617
4990
|
mode: "directory",
|
|
@@ -4621,24 +4994,24 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4621
4994
|
error: message,
|
|
4622
4995
|
errorKind: "no_files"
|
|
4623
4996
|
};
|
|
4624
|
-
return text(message,
|
|
4997
|
+
return text(message, details);
|
|
4625
4998
|
}
|
|
4626
|
-
const
|
|
4627
|
-
const
|
|
4999
|
+
const output = await aggregateDiagnosticsForDirectory(absPath, extension, severity, undefined, signal === undefined ? {} : { signal });
|
|
5000
|
+
const details = {
|
|
4628
5001
|
filePath,
|
|
4629
5002
|
severity,
|
|
4630
5003
|
mode: "directory",
|
|
4631
5004
|
diagnostics: [],
|
|
4632
|
-
totalDiagnostics:
|
|
5005
|
+
totalDiagnostics: output.totalDiagnostics,
|
|
4633
5006
|
truncated: false,
|
|
4634
|
-
fileFailures: [...
|
|
5007
|
+
fileFailures: [...output.fileFailures]
|
|
4635
5008
|
};
|
|
4636
|
-
return text(
|
|
5009
|
+
return text(output.output, details);
|
|
4637
5010
|
}
|
|
4638
|
-
const result = await withLspClient(filePath, async (client) => client.diagnostics(
|
|
5011
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
|
|
4639
5012
|
if (result.transientError) {
|
|
4640
5013
|
const message = result.transientError.message;
|
|
4641
|
-
const
|
|
5014
|
+
const details = {
|
|
4642
5015
|
filePath,
|
|
4643
5016
|
severity,
|
|
4644
5017
|
mode: "file",
|
|
@@ -4648,7 +5021,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4648
5021
|
error: message,
|
|
4649
5022
|
errorKind: result.transientError.kind
|
|
4650
5023
|
};
|
|
4651
|
-
return text(message,
|
|
5024
|
+
return text(message, details, true);
|
|
4652
5025
|
}
|
|
4653
5026
|
const diagnostics = filterDiagnosticsBySeverity(asDiagnosticArray(result), severity);
|
|
4654
5027
|
const total = diagnostics.length;
|
|
@@ -4682,6 +5055,96 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4682
5055
|
throw error;
|
|
4683
5056
|
}
|
|
4684
5057
|
}
|
|
5058
|
+
// ../lsp-core/src/lsp/format-document.ts
|
|
5059
|
+
import { readFileSync as readFileSync5, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
5060
|
+
var DEFAULT_FORMATTING_OPTIONS = {
|
|
5061
|
+
tabSize: 4,
|
|
5062
|
+
insertSpaces: false,
|
|
5063
|
+
trimTrailingWhitespace: true,
|
|
5064
|
+
insertFinalNewline: true,
|
|
5065
|
+
trimFinalNewlines: true
|
|
5066
|
+
};
|
|
5067
|
+
var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
|
|
5068
|
+
async function formatDocumentWithClient(client, filePath, options = {}) {
|
|
5069
|
+
const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
|
|
5070
|
+
if (edits === null)
|
|
5071
|
+
return { status: "unavailable", reason: "capability_not_advertised" };
|
|
5072
|
+
if (edits.length === 0)
|
|
5073
|
+
return UNCHANGED;
|
|
5074
|
+
const before = readFileSync5(filePath, "utf-8");
|
|
5075
|
+
const normalized = normalizeTextEdits(before, edits, 0);
|
|
5076
|
+
if (normalized.text === before)
|
|
5077
|
+
return UNCHANGED;
|
|
5078
|
+
writeAtomically(filePath, normalized.text);
|
|
5079
|
+
await client.openFile(filePath);
|
|
5080
|
+
return {
|
|
5081
|
+
status: "formatted",
|
|
5082
|
+
...lineDelta(normalized.edits)
|
|
5083
|
+
};
|
|
5084
|
+
}
|
|
5085
|
+
function lineDelta(edits) {
|
|
5086
|
+
let linesAdded = 0;
|
|
5087
|
+
let linesRemoved = 0;
|
|
5088
|
+
for (const edit of edits) {
|
|
5089
|
+
linesRemoved += edit.range.end.line - edit.range.start.line + 1;
|
|
5090
|
+
linesAdded += edit.newText.split(`
|
|
5091
|
+
`).length;
|
|
5092
|
+
}
|
|
5093
|
+
return { linesAdded, linesRemoved };
|
|
5094
|
+
}
|
|
5095
|
+
function writeAtomically(filePath, content) {
|
|
5096
|
+
const tempPath = `${filePath}.omo-format.tmp`;
|
|
5097
|
+
writeFileSync3(tempPath, content, "utf-8");
|
|
5098
|
+
try {
|
|
5099
|
+
renameSync3(tempPath, filePath);
|
|
5100
|
+
} catch (error) {
|
|
5101
|
+
try {
|
|
5102
|
+
unlinkSync(tempPath);
|
|
5103
|
+
} catch {}
|
|
5104
|
+
throw error;
|
|
5105
|
+
}
|
|
5106
|
+
}
|
|
5107
|
+
|
|
5108
|
+
// ../lsp-core/src/tools/format.ts
|
|
5109
|
+
async function executeLspFormat(params, signal) {
|
|
5110
|
+
const filePath = requireString(params, "filePath");
|
|
5111
|
+
try {
|
|
5112
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
|
|
5113
|
+
return text(describeResult(filePath, result), formatDetails(filePath, result));
|
|
5114
|
+
} catch (error) {
|
|
5115
|
+
const missingDependency = missingDependencyResult(error, {
|
|
5116
|
+
filePath,
|
|
5117
|
+
status: "unavailable",
|
|
5118
|
+
reason: "server_unavailable",
|
|
5119
|
+
linesAdded: 0,
|
|
5120
|
+
linesRemoved: 0
|
|
5121
|
+
});
|
|
5122
|
+
if (missingDependency)
|
|
5123
|
+
return missingDependency;
|
|
5124
|
+
throw error;
|
|
5125
|
+
}
|
|
5126
|
+
}
|
|
5127
|
+
function formatDetails(filePath, result) {
|
|
5128
|
+
if (result.status === "unavailable") {
|
|
5129
|
+
return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
|
|
5130
|
+
}
|
|
5131
|
+
return {
|
|
5132
|
+
filePath,
|
|
5133
|
+
status: result.status,
|
|
5134
|
+
linesAdded: result.linesAdded,
|
|
5135
|
+
linesRemoved: result.linesRemoved
|
|
5136
|
+
};
|
|
5137
|
+
}
|
|
5138
|
+
function describeResult(filePath, result) {
|
|
5139
|
+
if (result.status === "unavailable") {
|
|
5140
|
+
return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
|
|
5141
|
+
}
|
|
5142
|
+
if (result.status === "unchanged") {
|
|
5143
|
+
return `Already formatted: ${filePath}`;
|
|
5144
|
+
}
|
|
5145
|
+
return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
|
|
5146
|
+
}
|
|
5147
|
+
|
|
4685
5148
|
// ../lsp-core/src/tools/install-decision.ts
|
|
4686
5149
|
async function executeLspInstallDecision(params) {
|
|
4687
5150
|
const serverId = requireString(params, "server_id");
|
|
@@ -4689,7 +5152,7 @@ async function executeLspInstallDecision(params) {
|
|
|
4689
5152
|
if (!isInstallDecision(decision)) {
|
|
4690
5153
|
return text(`Invalid decision '${String(decision)}'. Expected "declined" or "allowed".`, { serverId, errorKind: "invalid_decision" }, true);
|
|
4691
5154
|
}
|
|
4692
|
-
const serverIds = [...new Set(getMergedServers().map((
|
|
5155
|
+
const serverIds = [...new Set(getMergedServers().map((server) => server.id))];
|
|
4693
5156
|
if (!serverIds.includes(serverId)) {
|
|
4694
5157
|
const preview = serverIds.slice(0, 20).join(", ");
|
|
4695
5158
|
return text(`Unknown LSP server '${serverId}'. Known servers: ${preview}${serverIds.length > 20 ? "..." : ""}`, { serverId, errorKind: "unknown_server" }, true);
|
|
@@ -4710,7 +5173,7 @@ async function executeLspGotoDefinition(params, signal) {
|
|
|
4710
5173
|
const line = requireNumber(params, "line");
|
|
4711
5174
|
const character = requireNumber(params, "character");
|
|
4712
5175
|
try {
|
|
4713
|
-
const result = await withLspClient(filePath, async (client) => client.definition(
|
|
5176
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
|
|
4714
5177
|
const locations = !result ? [] : Array.isArray(result) ? result : [result];
|
|
4715
5178
|
const details = { filePath, line, character, locations };
|
|
4716
5179
|
if (locations.length === 0)
|
|
@@ -4735,7 +5198,7 @@ async function executeLspFindReferences(params, signal) {
|
|
|
4735
5198
|
const character = requireNumber(params, "character");
|
|
4736
5199
|
const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
|
|
4737
5200
|
try {
|
|
4738
|
-
const result = await withLspClient(filePath, async (client) => client.references(
|
|
5201
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
|
|
4739
5202
|
const references = Array.isArray(result) ? result : [];
|
|
4740
5203
|
const total = references.length;
|
|
4741
5204
|
const truncated = total > DEFAULT_MAX_REFERENCES;
|
|
@@ -4777,7 +5240,7 @@ async function executeLspPrepareRename(params, signal) {
|
|
|
4777
5240
|
const line = requireNumber(params, "line");
|
|
4778
5241
|
const character = requireNumber(params, "character");
|
|
4779
5242
|
try {
|
|
4780
|
-
const result = await withLspClient(filePath, async (client) => client.prepareRename(
|
|
5243
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
|
|
4781
5244
|
const details = { filePath, line, character, result };
|
|
4782
5245
|
return text(formatPrepareRenameResult(result), details);
|
|
4783
5246
|
} catch (error) {
|
|
@@ -4798,7 +5261,7 @@ async function executeLspRename(params, signal) {
|
|
|
4798
5261
|
const character = requireNumber(params, "character");
|
|
4799
5262
|
const newName = requireString(params, "newName");
|
|
4800
5263
|
try {
|
|
4801
|
-
const result = await withLspClient(filePath, async (client) => client.rename(
|
|
5264
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
|
|
4802
5265
|
const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
|
|
4803
5266
|
return text(formatApplyResult(result.apply), details, !result.apply.success);
|
|
4804
5267
|
} catch (error) {
|
|
@@ -4829,10 +5292,10 @@ function objectSchema(properties, required = []) {
|
|
|
4829
5292
|
async function executeLspStatus() {
|
|
4830
5293
|
const servers = getAllServers();
|
|
4831
5294
|
const snapshots = getLspManager().getSnapshot();
|
|
4832
|
-
const installed = servers.filter((
|
|
4833
|
-
const configuredLines = servers.map((
|
|
4834
|
-
const state =
|
|
4835
|
-
return `- ${
|
|
5295
|
+
const installed = servers.filter((server) => server.installed && !server.disabled);
|
|
5296
|
+
const configuredLines = servers.map((server) => {
|
|
5297
|
+
const state = server.disabled ? "disabled" : server.installed ? "installed" : "missing";
|
|
5298
|
+
return `- ${server.id}: ${state}; source=${server.source}; extensions=${server.extensions.join(", ")}`;
|
|
4836
5299
|
});
|
|
4837
5300
|
const activeLines = snapshots.map((snapshot) => {
|
|
4838
5301
|
const state = snapshot.alive ? snapshot.isInitializing ? "initializing" : "alive" : "dead";
|
|
@@ -4875,10 +5338,10 @@ async function executeLspSymbols(params, signal) {
|
|
|
4875
5338
|
errorKind: "missing_query"
|
|
4876
5339
|
});
|
|
4877
5340
|
}
|
|
4878
|
-
const
|
|
4879
|
-
return formatSymbolsResult(filePath, scope,
|
|
5341
|
+
const symbols = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
|
|
5342
|
+
return formatSymbolsResult(filePath, scope, symbols, limit, query);
|
|
4880
5343
|
}
|
|
4881
|
-
const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(
|
|
5344
|
+
const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
|
|
4882
5345
|
return formatSymbolsResult(filePath, scope, symbols, limit);
|
|
4883
5346
|
} catch (error) {
|
|
4884
5347
|
const query = optionalString(params, "query");
|
|
@@ -5014,6 +5477,16 @@ var LSP_MCP_TOOLS = [
|
|
|
5014
5477
|
}, ["filePath", "line", "character", "newName"]),
|
|
5015
5478
|
execute: executeLspRename
|
|
5016
5479
|
},
|
|
5480
|
+
{
|
|
5481
|
+
name: "format",
|
|
5482
|
+
aliases: ["lsp_format"],
|
|
5483
|
+
title: "LSP Format",
|
|
5484
|
+
description: "Format a source file with its language server and write the returned edits to disk.",
|
|
5485
|
+
inputSchema: objectSchema({
|
|
5486
|
+
filePath: { type: "string", description: "Source file path to format." }
|
|
5487
|
+
}, ["filePath"]),
|
|
5488
|
+
execute: executeLspFormat
|
|
5489
|
+
},
|
|
5017
5490
|
{
|
|
5018
5491
|
name: "install_decision",
|
|
5019
5492
|
aliases: ["lsp_install_decision"],
|
|
@@ -5113,11 +5586,10 @@ function requestedProtocolVersion(params) {
|
|
|
5113
5586
|
// src/daemon-client.ts
|
|
5114
5587
|
import { connect } from "node:net";
|
|
5115
5588
|
import { homedir as homedir3 } from "node:os";
|
|
5116
|
-
import { join as
|
|
5589
|
+
import { join as join8 } from "node:path";
|
|
5117
5590
|
|
|
5118
5591
|
// src/daemon-request-error.ts
|
|
5119
5592
|
class DaemonRequestError extends Error {
|
|
5120
|
-
requestWritten;
|
|
5121
5593
|
constructor(message, requestWritten) {
|
|
5122
5594
|
super(message);
|
|
5123
5595
|
this.name = "DaemonRequestError";
|
|
@@ -5140,7 +5612,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
|
|
|
5140
5612
|
}
|
|
5141
5613
|
|
|
5142
5614
|
class DaemonRequestTimedOutError extends DaemonRequestError {
|
|
5143
|
-
timeoutMs;
|
|
5144
5615
|
constructor(requestWritten, timeoutMs) {
|
|
5145
5616
|
super("daemon request timed out", requestWritten);
|
|
5146
5617
|
this.name = "DaemonRequestTimedOutError";
|
|
@@ -5157,26 +5628,26 @@ function daemonFailureResult(paths, error) {
|
|
|
5157
5628
|
return daemonUnreachableResult(paths, error);
|
|
5158
5629
|
}
|
|
5159
5630
|
function daemonCancelledResult(paths) {
|
|
5160
|
-
const
|
|
5631
|
+
const text = [
|
|
5161
5632
|
"LSP daemon request cancelled: the caller aborted this request (for example, the turn was interrupted).",
|
|
5162
5633
|
"The daemon stays available; no LSP work was applied. Retry when you are ready.",
|
|
5163
5634
|
`Socket: ${paths.socket}`
|
|
5164
5635
|
].join(`
|
|
5165
5636
|
`);
|
|
5166
|
-
return { content: [{ type: "text", text
|
|
5637
|
+
return { content: [{ type: "text", text }], isError: true };
|
|
5167
5638
|
}
|
|
5168
5639
|
function daemonTimedOutResult(paths, timeoutMs) {
|
|
5169
|
-
const
|
|
5640
|
+
const text = [
|
|
5170
5641
|
`LSP daemon request timed out after ${timeoutMs}ms: the daemon did not respond in time.`,
|
|
5171
5642
|
"The daemon stays available but may be busy. Retry when you are ready.",
|
|
5172
5643
|
`Socket: ${paths.socket}`,
|
|
5173
5644
|
`Logs: ${paths.log}`
|
|
5174
5645
|
].join(`
|
|
5175
5646
|
`);
|
|
5176
|
-
return { content: [{ type: "text", text
|
|
5647
|
+
return { content: [{ type: "text", text }], isError: true };
|
|
5177
5648
|
}
|
|
5178
5649
|
function daemonUnreachableResult(paths, error) {
|
|
5179
|
-
const
|
|
5650
|
+
const text = [
|
|
5180
5651
|
`LSP daemon unreachable: ${errorText(error)}.`,
|
|
5181
5652
|
"The MCP server is a thin proxy and never runs language servers in-process.",
|
|
5182
5653
|
`Socket: ${paths.socket}`,
|
|
@@ -5184,7 +5655,7 @@ function daemonUnreachableResult(paths, error) {
|
|
|
5184
5655
|
"The daemon is auto-started on demand and will be retried on the next request."
|
|
5185
5656
|
].join(`
|
|
5186
5657
|
`);
|
|
5187
|
-
return { content: [{ type: "text", text
|
|
5658
|
+
return { content: [{ type: "text", text }], isError: true };
|
|
5188
5659
|
}
|
|
5189
5660
|
function errorText(error) {
|
|
5190
5661
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -5192,9 +5663,9 @@ function errorText(error) {
|
|
|
5192
5663
|
|
|
5193
5664
|
// src/ensure-daemon.ts
|
|
5194
5665
|
import { spawn as spawn2 } from "node:child_process";
|
|
5195
|
-
import { closeSync as closeSync2, existsSync as
|
|
5666
|
+
import { closeSync as closeSync2, existsSync as existsSync12, mkdirSync as mkdirSync3, openSync as openSync2, writeSync as writeSync2 } from "node:fs";
|
|
5196
5667
|
import { Socket } from "node:net";
|
|
5197
|
-
import { dirname as
|
|
5668
|
+
import { dirname as dirname10, isAbsolute as isAbsolute5 } from "node:path";
|
|
5198
5669
|
import { argv0, execPath } from "node:process";
|
|
5199
5670
|
|
|
5200
5671
|
// src/ipc-protocol.ts
|
|
@@ -5208,25 +5679,23 @@ import {
|
|
|
5208
5679
|
lstatSync as lstatSync6,
|
|
5209
5680
|
mkdirSync as mkdirSync2,
|
|
5210
5681
|
openSync,
|
|
5211
|
-
readFileSync as
|
|
5212
|
-
unlinkSync,
|
|
5682
|
+
readFileSync as readFileSync6,
|
|
5683
|
+
unlinkSync as unlinkSync2,
|
|
5213
5684
|
writeSync
|
|
5214
5685
|
} from "node:fs";
|
|
5215
|
-
import { dirname as
|
|
5686
|
+
import { dirname as dirname9 } from "node:path";
|
|
5216
5687
|
var OMO_DAEMON_PROTOCOL_VERSION = 1;
|
|
5217
5688
|
var AUTH_ERROR_CODE = -32001;
|
|
5218
5689
|
var PROTOCOL_ERROR_CODE = -32002;
|
|
5219
5690
|
var AUTH_TOKEN_BYTES = 32;
|
|
5220
5691
|
|
|
5221
5692
|
class UnsafePrivateDirectoryError extends Error {
|
|
5222
|
-
path;
|
|
5223
|
-
reason;
|
|
5224
|
-
name = "UnsafePrivateDirectoryError";
|
|
5225
|
-
code = "unsafe_private_directory";
|
|
5226
5693
|
constructor(path, reason) {
|
|
5227
5694
|
super(`unsafe private directory ${path}: ${reason}`);
|
|
5228
5695
|
this.path = path;
|
|
5229
5696
|
this.reason = reason;
|
|
5697
|
+
this.name = "UnsafePrivateDirectoryError";
|
|
5698
|
+
this.code = "unsafe_private_directory";
|
|
5230
5699
|
}
|
|
5231
5700
|
}
|
|
5232
5701
|
function authEnvelope(token) {
|
|
@@ -5234,7 +5703,7 @@ function authEnvelope(token) {
|
|
|
5234
5703
|
}
|
|
5235
5704
|
function readAuthToken(paths) {
|
|
5236
5705
|
try {
|
|
5237
|
-
const token =
|
|
5706
|
+
const token = readFileSync6(paths.auth, "utf8").trim();
|
|
5238
5707
|
return token.length > 0 ? token : null;
|
|
5239
5708
|
} catch (error) {
|
|
5240
5709
|
if (error instanceof Error)
|
|
@@ -5250,7 +5719,7 @@ function readOrCreateAuthToken(paths) {
|
|
|
5250
5719
|
}
|
|
5251
5720
|
function rotateAuthToken(paths) {
|
|
5252
5721
|
try {
|
|
5253
|
-
|
|
5722
|
+
unlinkSync2(paths.auth);
|
|
5254
5723
|
} catch (error) {
|
|
5255
5724
|
if (!(error instanceof Error))
|
|
5256
5725
|
throw error;
|
|
@@ -5322,7 +5791,7 @@ function setPrivateFileMode(path) {
|
|
|
5322
5791
|
chmodSync(path, 384);
|
|
5323
5792
|
}
|
|
5324
5793
|
function createAuthToken(paths) {
|
|
5325
|
-
ensurePrivateDirectory(
|
|
5794
|
+
ensurePrivateDirectory(dirname9(paths.auth));
|
|
5326
5795
|
const token = randomBytes(AUTH_TOKEN_BYTES).toString("base64url");
|
|
5327
5796
|
let fd;
|
|
5328
5797
|
try {
|
|
@@ -5403,27 +5872,25 @@ import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
|
5403
5872
|
|
|
5404
5873
|
// src/runtime-contract.ts
|
|
5405
5874
|
import { statSync as statSync4 } from "node:fs";
|
|
5406
|
-
import { isAbsolute as
|
|
5875
|
+
import { isAbsolute as isAbsolute4 } from "node:path";
|
|
5407
5876
|
var OMO_LSP_DAEMON_DIR = "OMO_LSP_DAEMON_DIR";
|
|
5408
5877
|
var OMO_LSP_DAEMON_CLI = "OMO_LSP_DAEMON_CLI";
|
|
5409
5878
|
var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
|
|
5410
5879
|
var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
5411
5880
|
|
|
5412
5881
|
class InvalidRuntimeOverrideError extends Error {
|
|
5413
|
-
code = "invalid_runtime_override";
|
|
5414
|
-
reason;
|
|
5415
5882
|
constructor(reason, message) {
|
|
5416
5883
|
super(message);
|
|
5884
|
+
this.code = "invalid_runtime_override";
|
|
5417
5885
|
this.name = "InvalidRuntimeOverrideError";
|
|
5418
5886
|
this.reason = reason;
|
|
5419
5887
|
}
|
|
5420
5888
|
}
|
|
5421
5889
|
|
|
5422
5890
|
class InvalidDaemonVersionError extends Error {
|
|
5423
|
-
code = "invalid_daemon_version";
|
|
5424
|
-
version;
|
|
5425
5891
|
constructor(version) {
|
|
5426
5892
|
super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
|
|
5893
|
+
this.code = "invalid_daemon_version";
|
|
5427
5894
|
this.name = "InvalidDaemonVersionError";
|
|
5428
5895
|
this.version = version;
|
|
5429
5896
|
}
|
|
@@ -5442,12 +5909,12 @@ function resolveDaemonRuntime(env, defaults) {
|
|
|
5442
5909
|
throw new InvalidRuntimeOverrideError("paired_values_required", `${OMO_LSP_DAEMON_CLI} and ${OMO_LSP_DAEMON_VERSION} must be set together`);
|
|
5443
5910
|
}
|
|
5444
5911
|
if (!hasCliOverride || !hasVersionOverride) {
|
|
5445
|
-
if (!
|
|
5912
|
+
if (!isAbsolute4(defaults.cliPath)) {
|
|
5446
5913
|
throw new InvalidRuntimeOverrideError("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
|
|
5447
5914
|
}
|
|
5448
5915
|
return { cliPath: defaults.cliPath, version: validateDaemonVersion(defaults.version) };
|
|
5449
5916
|
}
|
|
5450
|
-
if (!
|
|
5917
|
+
if (!isAbsolute4(cliOverride)) {
|
|
5451
5918
|
throw new InvalidRuntimeOverrideError("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI} must be an absolute path to an existing regular file`);
|
|
5452
5919
|
}
|
|
5453
5920
|
let cliStats;
|
|
@@ -5469,10 +5936,9 @@ var requireFromHere = createRequire(import.meta.url);
|
|
|
5469
5936
|
var MAX_SOCKET_PATH_LENGTH = 100;
|
|
5470
5937
|
|
|
5471
5938
|
class InvalidDaemonDirectoryError extends Error {
|
|
5472
|
-
code = "invalid_daemon_directory";
|
|
5473
|
-
directory;
|
|
5474
5939
|
constructor(directory) {
|
|
5475
5940
|
super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
|
|
5941
|
+
this.code = "invalid_daemon_directory";
|
|
5476
5942
|
this.name = "InvalidDaemonDirectoryError";
|
|
5477
5943
|
this.directory = directory;
|
|
5478
5944
|
}
|
|
@@ -5626,7 +6092,7 @@ async function probeDaemon(paths, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
5626
6092
|
return await pingDaemon(paths, token, timeoutMs, signal) !== null;
|
|
5627
6093
|
}
|
|
5628
6094
|
function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
5629
|
-
return new Promise((
|
|
6095
|
+
return new Promise((resolve) => {
|
|
5630
6096
|
const socket = new Socket;
|
|
5631
6097
|
let settled = false;
|
|
5632
6098
|
let timer;
|
|
@@ -5638,7 +6104,7 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
5638
6104
|
clearTimeout(timer);
|
|
5639
6105
|
signal?.removeEventListener("abort", onAbort);
|
|
5640
6106
|
socket.destroy();
|
|
5641
|
-
|
|
6107
|
+
resolve(value);
|
|
5642
6108
|
};
|
|
5643
6109
|
const onAbort = () => finish(null);
|
|
5644
6110
|
const decoder = createLineDecoder((message) => {
|
|
@@ -5661,13 +6127,17 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
5661
6127
|
socket.connect(paths.socket);
|
|
5662
6128
|
});
|
|
5663
6129
|
}
|
|
5664
|
-
function spawnDaemonProcess(paths) {
|
|
5665
|
-
mkdirSync3(
|
|
6130
|
+
function spawnDaemonProcess(paths, deps = {}) {
|
|
6131
|
+
mkdirSync3(dirname10(paths.log), { recursive: true });
|
|
5666
6132
|
const logFd = openSync2(paths.log, "a");
|
|
5667
6133
|
try {
|
|
5668
|
-
const
|
|
6134
|
+
const spawnDaemonChild = deps.spawn ?? spawn2;
|
|
6135
|
+
const executable = deps.resolveExecutable?.() ?? resolveDaemonNodeExecutable();
|
|
6136
|
+
const child = spawnDaemonChild(executable, [paths.cliPath, "daemon"], {
|
|
5669
6137
|
detached: true,
|
|
5670
|
-
stdio: ["ignore", logFd, logFd]
|
|
6138
|
+
stdio: ["ignore", logFd, logFd],
|
|
6139
|
+
windowsHide: true,
|
|
6140
|
+
env: { ...process.env, BUN_BE_BUN: "1" }
|
|
5671
6141
|
});
|
|
5672
6142
|
child.once("spawn", () => closeSync2(logFd));
|
|
5673
6143
|
child.once("error", (error) => {
|
|
@@ -5681,10 +6151,10 @@ function spawnDaemonProcess(paths) {
|
|
|
5681
6151
|
throw error;
|
|
5682
6152
|
}
|
|
5683
6153
|
}
|
|
5684
|
-
function resolveDaemonNodeExecutable(cachedExecPath = execPath, originalArgv0 = argv0, pathExists =
|
|
6154
|
+
function resolveDaemonNodeExecutable(cachedExecPath = execPath, originalArgv0 = argv0, pathExists = existsSync12) {
|
|
5685
6155
|
if (pathExists(cachedExecPath))
|
|
5686
6156
|
return cachedExecPath;
|
|
5687
|
-
if (
|
|
6157
|
+
if (isAbsolute5(originalArgv0) && pathExists(originalArgv0))
|
|
5688
6158
|
return originalArgv0;
|
|
5689
6159
|
return "node";
|
|
5690
6160
|
}
|
|
@@ -5697,7 +6167,7 @@ function defaultEnsureDaemonDeps() {
|
|
|
5697
6167
|
};
|
|
5698
6168
|
}
|
|
5699
6169
|
function sleepWithSignal(ms, signal) {
|
|
5700
|
-
return new Promise((
|
|
6170
|
+
return new Promise((resolve) => {
|
|
5701
6171
|
let settled = false;
|
|
5702
6172
|
const finish = () => {
|
|
5703
6173
|
if (settled)
|
|
@@ -5705,7 +6175,7 @@ function sleepWithSignal(ms, signal) {
|
|
|
5705
6175
|
settled = true;
|
|
5706
6176
|
clearTimeout(timer);
|
|
5707
6177
|
signal?.removeEventListener("abort", finish);
|
|
5708
|
-
|
|
6178
|
+
resolve();
|
|
5709
6179
|
};
|
|
5710
6180
|
const timer = setTimeout(finish, ms);
|
|
5711
6181
|
if (signal?.aborted) {
|
|
@@ -5720,7 +6190,7 @@ function awaitWithSignal2(promise, signal) {
|
|
|
5720
6190
|
return promise;
|
|
5721
6191
|
if (signal.aborted)
|
|
5722
6192
|
return Promise.reject(abortError3(signal));
|
|
5723
|
-
return new Promise((
|
|
6193
|
+
return new Promise((resolve, reject) => {
|
|
5724
6194
|
let settled = false;
|
|
5725
6195
|
const finish = (run) => {
|
|
5726
6196
|
if (settled)
|
|
@@ -5731,7 +6201,7 @@ function awaitWithSignal2(promise, signal) {
|
|
|
5731
6201
|
};
|
|
5732
6202
|
const onAbort = () => finish(() => reject(abortError3(signal)));
|
|
5733
6203
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5734
|
-
promise.then((value) => finish(() =>
|
|
6204
|
+
promise.then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error)));
|
|
5735
6205
|
});
|
|
5736
6206
|
}
|
|
5737
6207
|
function throwIfAborted(signal) {
|
|
@@ -5760,18 +6230,18 @@ function parsePingResponse(message) {
|
|
|
5760
6230
|
return null;
|
|
5761
6231
|
if (!endpoint || typeof endpoint !== "object" || Array.isArray(endpoint))
|
|
5762
6232
|
return null;
|
|
5763
|
-
const
|
|
6233
|
+
const path = Reflect.get(endpoint, "path");
|
|
5764
6234
|
const kind = Reflect.get(endpoint, "kind");
|
|
5765
|
-
if (typeof
|
|
6235
|
+
if (typeof path !== "string")
|
|
5766
6236
|
return null;
|
|
5767
6237
|
if (kind === "windows")
|
|
5768
|
-
return { pid, nonce, startedAt, endpoint: { kind, path
|
|
6238
|
+
return { pid, nonce, startedAt, endpoint: { kind, path } };
|
|
5769
6239
|
if (kind === "missing")
|
|
5770
|
-
return { pid, nonce, startedAt, endpoint: { kind, path
|
|
6240
|
+
return { pid, nonce, startedAt, endpoint: { kind, path } };
|
|
5771
6241
|
const dev = Reflect.get(endpoint, "dev");
|
|
5772
6242
|
const ino = Reflect.get(endpoint, "ino");
|
|
5773
6243
|
if (kind === "unix" && typeof dev === "number" && typeof ino === "number") {
|
|
5774
|
-
return { pid, nonce, startedAt, endpoint: { kind, path
|
|
6244
|
+
return { pid, nonce, startedAt, endpoint: { kind, path, dev, ino } };
|
|
5775
6245
|
}
|
|
5776
6246
|
return null;
|
|
5777
6247
|
}
|
|
@@ -5780,7 +6250,10 @@ function parsePingResponse(message) {
|
|
|
5780
6250
|
var CONTEXT_KEY = "_context";
|
|
5781
6251
|
|
|
5782
6252
|
class InvalidDaemonRequestError extends Error {
|
|
5783
|
-
|
|
6253
|
+
constructor() {
|
|
6254
|
+
super(...arguments);
|
|
6255
|
+
this.name = "InvalidDaemonRequestError";
|
|
6256
|
+
}
|
|
5784
6257
|
}
|
|
5785
6258
|
function extractRequestContext(raw) {
|
|
5786
6259
|
if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
|
|
@@ -5896,14 +6369,17 @@ async function callToolViaDaemon(name, args, options) {
|
|
|
5896
6369
|
function callDiagnosticsViaDaemon(filePath, options) {
|
|
5897
6370
|
return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
|
|
5898
6371
|
}
|
|
6372
|
+
function callFormatViaDaemon(filePath, options) {
|
|
6373
|
+
return callToolViaDaemon("format", { filePath }, options);
|
|
6374
|
+
}
|
|
5899
6375
|
function currentRequestContext(env = process.env) {
|
|
5900
6376
|
const cwd = process.cwd();
|
|
5901
6377
|
const home = env["HOME"] ?? homedir3();
|
|
5902
6378
|
return parseLspRequestContext({
|
|
5903
6379
|
cwd,
|
|
5904
|
-
projectConfigPaths: [
|
|
5905
|
-
userConfigPath:
|
|
5906
|
-
installDecisionsPath:
|
|
6380
|
+
projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
|
|
6381
|
+
userConfigPath: join8(home, ".codex", "lsp-client.json"),
|
|
6382
|
+
installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
|
|
5907
6383
|
capabilities: { installDecisionTool: true }
|
|
5908
6384
|
});
|
|
5909
6385
|
}
|
|
@@ -5918,7 +6394,7 @@ function withContext(args, context) {
|
|
|
5918
6394
|
function ensureDaemonAvailable(paths, ensure, signal) {
|
|
5919
6395
|
if (!signal)
|
|
5920
6396
|
return ensure(paths);
|
|
5921
|
-
return new Promise((
|
|
6397
|
+
return new Promise((resolve, reject) => {
|
|
5922
6398
|
let settled = false;
|
|
5923
6399
|
const finish = (run) => {
|
|
5924
6400
|
if (settled)
|
|
@@ -5933,11 +6409,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
|
|
|
5933
6409
|
return;
|
|
5934
6410
|
}
|
|
5935
6411
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5936
|
-
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() =>
|
|
6412
|
+
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
|
|
5937
6413
|
});
|
|
5938
6414
|
}
|
|
5939
6415
|
function sendToolCall(paths, token, name, args, options) {
|
|
5940
|
-
return new Promise((
|
|
6416
|
+
return new Promise((resolve, reject) => {
|
|
5941
6417
|
const socket = connect(paths.socket);
|
|
5942
6418
|
const requestId = allocateProxyRequestId();
|
|
5943
6419
|
let settled = false;
|
|
@@ -5990,7 +6466,7 @@ function sendToolCall(paths, token, name, args, options) {
|
|
|
5990
6466
|
}
|
|
5991
6467
|
const result = toToolResult(message, requestId);
|
|
5992
6468
|
if (result)
|
|
5993
|
-
finish(() =>
|
|
6469
|
+
finish(() => resolve(result));
|
|
5994
6470
|
else
|
|
5995
6471
|
finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
|
|
5996
6472
|
});
|
|
@@ -6158,18 +6634,18 @@ function canonicalizePathList(value) {
|
|
|
6158
6634
|
return value.split(delimiter4).map((entry) => canonicalizePath(entry) ?? entry).join(delimiter4);
|
|
6159
6635
|
}
|
|
6160
6636
|
function canonicalizePath(value) {
|
|
6161
|
-
if (value === undefined || !
|
|
6637
|
+
if (value === undefined || !isAbsolute6(value) || !existsSync13(value))
|
|
6162
6638
|
return value;
|
|
6163
|
-
return
|
|
6639
|
+
return realpathSync6(value);
|
|
6164
6640
|
}
|
|
6165
|
-
function projectRootFromOpenCodeConfigPath(
|
|
6166
|
-
if (
|
|
6641
|
+
function projectRootFromOpenCodeConfigPath(path) {
|
|
6642
|
+
if (basename4(path) !== "lsp.json" && basename4(path) !== "lsp-client.json")
|
|
6167
6643
|
return;
|
|
6168
|
-
const configDir =
|
|
6169
|
-
const configDirName =
|
|
6644
|
+
const configDir = dirname11(path);
|
|
6645
|
+
const configDirName = basename4(configDir);
|
|
6170
6646
|
if (configDirName !== ".opencode" && configDirName !== ".omo")
|
|
6171
6647
|
return;
|
|
6172
|
-
return
|
|
6648
|
+
return dirname11(configDir);
|
|
6173
6649
|
}
|
|
6174
6650
|
|
|
6175
6651
|
// src/daemon-server.ts
|
|
@@ -6178,12 +6654,12 @@ import { createServer as createServer2 } from "node:net";
|
|
|
6178
6654
|
|
|
6179
6655
|
// src/ownership.ts
|
|
6180
6656
|
import { randomUUID } from "node:crypto";
|
|
6181
|
-
import { existsSync as
|
|
6182
|
-
import { dirname as
|
|
6657
|
+
import { existsSync as existsSync14, lstatSync as lstatSync7, readFileSync as readFileSync8, statSync as statSync5, unlinkSync as unlinkSync4 } from "node:fs";
|
|
6658
|
+
import { dirname as dirname13 } from "node:path";
|
|
6183
6659
|
|
|
6184
6660
|
// src/lock.ts
|
|
6185
|
-
import { closeSync as closeSync3, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as
|
|
6186
|
-
import { dirname as
|
|
6661
|
+
import { closeSync as closeSync3, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeSync as writeSync3 } from "node:fs";
|
|
6662
|
+
import { dirname as dirname12 } from "node:path";
|
|
6187
6663
|
function isProcessAlive2(pid) {
|
|
6188
6664
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
6189
6665
|
return false;
|
|
@@ -6198,14 +6674,14 @@ function isProcessAlive2(pid) {
|
|
|
6198
6674
|
}
|
|
6199
6675
|
function readLockPid(lockPath) {
|
|
6200
6676
|
try {
|
|
6201
|
-
const pid = Number.parseInt(
|
|
6677
|
+
const pid = Number.parseInt(readFileSync7(lockPath, "utf8").trim(), 10);
|
|
6202
6678
|
return Number.isInteger(pid) ? pid : null;
|
|
6203
6679
|
} catch {
|
|
6204
6680
|
return null;
|
|
6205
6681
|
}
|
|
6206
6682
|
}
|
|
6207
6683
|
function tryAcquireLock(lockPath, ownerPid = process.pid) {
|
|
6208
|
-
mkdirSync4(
|
|
6684
|
+
mkdirSync4(dirname12(lockPath), { recursive: true });
|
|
6209
6685
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
6210
6686
|
const handle = writeLockFile(lockPath, ownerPid);
|
|
6211
6687
|
if (handle)
|
|
@@ -6235,9 +6711,9 @@ function reapStaleLock(lockPath) {
|
|
|
6235
6711
|
unlinkQuietly(lockPath);
|
|
6236
6712
|
return true;
|
|
6237
6713
|
}
|
|
6238
|
-
function unlinkQuietly(
|
|
6714
|
+
function unlinkQuietly(path) {
|
|
6239
6715
|
try {
|
|
6240
|
-
|
|
6716
|
+
unlinkSync3(path);
|
|
6241
6717
|
} catch (error) {
|
|
6242
6718
|
if (error instanceof Error)
|
|
6243
6719
|
return;
|
|
@@ -6253,17 +6729,19 @@ function errorCode3(error) {
|
|
|
6253
6729
|
|
|
6254
6730
|
// src/ownership.ts
|
|
6255
6731
|
class DaemonAlreadyRunningError extends Error {
|
|
6256
|
-
|
|
6257
|
-
|
|
6732
|
+
constructor() {
|
|
6733
|
+
super(...arguments);
|
|
6734
|
+
this.name = "DaemonAlreadyRunningError";
|
|
6735
|
+
this.code = "daemon_already_running";
|
|
6736
|
+
}
|
|
6258
6737
|
}
|
|
6259
6738
|
|
|
6260
6739
|
class DaemonStartupDeferredError extends Error {
|
|
6261
|
-
reason;
|
|
6262
|
-
name = "DaemonStartupDeferredError";
|
|
6263
|
-
code = "daemon_startup_deferred";
|
|
6264
6740
|
constructor(reason) {
|
|
6265
6741
|
super(`LSP daemon startup deferred: ${reason}`);
|
|
6266
6742
|
this.reason = reason;
|
|
6743
|
+
this.name = "DaemonStartupDeferredError";
|
|
6744
|
+
this.code = "daemon_startup_deferred";
|
|
6267
6745
|
}
|
|
6268
6746
|
}
|
|
6269
6747
|
async function acquireStartupLease(paths, pingOwner) {
|
|
@@ -6286,11 +6764,11 @@ async function acquireStartupLease(paths, pingOwner) {
|
|
|
6286
6764
|
function ensureDaemonDirectories(paths) {
|
|
6287
6765
|
ensurePrivateDirectory(paths.dir);
|
|
6288
6766
|
if (process.platform !== "win32")
|
|
6289
|
-
ensurePrivateDirectory(
|
|
6767
|
+
ensurePrivateDirectory(dirname13(paths.socket));
|
|
6290
6768
|
}
|
|
6291
6769
|
function readDaemonOwner(paths) {
|
|
6292
6770
|
try {
|
|
6293
|
-
return parseOwner(JSON.parse(
|
|
6771
|
+
return parseOwner(JSON.parse(readFileSync8(paths.owner, "utf8")));
|
|
6294
6772
|
} catch (error) {
|
|
6295
6773
|
if (error instanceof Error)
|
|
6296
6774
|
return null;
|
|
@@ -6366,10 +6844,10 @@ async function validateExistingOwner(paths, pingOwner) {
|
|
|
6366
6844
|
throw new DaemonStartupDeferredError("reachable_owner_mismatch");
|
|
6367
6845
|
}
|
|
6368
6846
|
function cleanupDeadOwner(paths, owner) {
|
|
6369
|
-
if (process.platform !== "win32" &&
|
|
6847
|
+
if (process.platform !== "win32" && existsSync14(owner.endpoint.path)) {
|
|
6370
6848
|
const stat = lstatSync7(owner.endpoint.path);
|
|
6371
6849
|
if (stat.isSocket())
|
|
6372
|
-
|
|
6850
|
+
unlinkSync4(owner.endpoint.path);
|
|
6373
6851
|
}
|
|
6374
6852
|
unlinkQuietly(paths.pid);
|
|
6375
6853
|
unlinkQuietly(paths.endpoint);
|
|
@@ -6398,26 +6876,26 @@ function parseEndpoint(value) {
|
|
|
6398
6876
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
6399
6877
|
return null;
|
|
6400
6878
|
const kind = Reflect.get(value, "kind");
|
|
6401
|
-
const
|
|
6402
|
-
if (typeof
|
|
6879
|
+
const path = Reflect.get(value, "path");
|
|
6880
|
+
if (typeof path !== "string")
|
|
6403
6881
|
return null;
|
|
6404
6882
|
if (kind === undefined)
|
|
6405
|
-
return endpointIdentity(
|
|
6883
|
+
return endpointIdentity(path);
|
|
6406
6884
|
if (kind === "windows")
|
|
6407
|
-
return { kind, path
|
|
6885
|
+
return { kind, path };
|
|
6408
6886
|
if (kind === "missing")
|
|
6409
|
-
return { kind, path
|
|
6887
|
+
return { kind, path };
|
|
6410
6888
|
const dev = Reflect.get(value, "dev");
|
|
6411
6889
|
const ino = Reflect.get(value, "ino");
|
|
6412
6890
|
if (kind === "unix" && typeof dev === "number" && typeof ino === "number")
|
|
6413
|
-
return { kind, path
|
|
6891
|
+
return { kind, path, dev, ino };
|
|
6414
6892
|
return null;
|
|
6415
6893
|
}
|
|
6416
6894
|
|
|
6417
6895
|
// src/version-reap.ts
|
|
6418
6896
|
import { execFile } from "node:child_process";
|
|
6419
6897
|
import { readdir, readFile, rm } from "node:fs/promises";
|
|
6420
|
-
import { basename as
|
|
6898
|
+
import { basename as basename5, dirname as dirname14, join as join9 } from "node:path";
|
|
6421
6899
|
var TERM_GRACE_MS = 5000;
|
|
6422
6900
|
var KILL_GRACE_MS = 1000;
|
|
6423
6901
|
var VERSION_ENTRY_PATTERN = /^v([A-Za-z0-9][A-Za-z0-9._+-]{0,127})$/;
|
|
@@ -6438,13 +6916,13 @@ async function attestDaemonCliProcess(pid, platform, deps = {}) {
|
|
|
6438
6916
|
return isNodeCliDaemonCommand(command.trim());
|
|
6439
6917
|
}
|
|
6440
6918
|
async function reapStaleDaemonVersions(ownPaths, deps = {}) {
|
|
6441
|
-
const baseDir =
|
|
6919
|
+
const baseDir = dirname14(ownPaths.dir);
|
|
6442
6920
|
const platform = deps.platform ?? process.platform;
|
|
6443
6921
|
const isAlive = deps.isAlive ?? isProcessAlive2;
|
|
6444
6922
|
const attest = deps.attest ?? ((pid) => attestDaemonCliProcess(pid, platform));
|
|
6445
6923
|
const sendSignal = deps.sendSignal ?? defaultSendSignal;
|
|
6446
6924
|
const waitForExit = deps.waitForExit ?? defaultWaitForExit;
|
|
6447
|
-
const removeDir = deps.removeDir ?? ((
|
|
6925
|
+
const removeDir = deps.removeDir ?? ((path) => rm(path, { recursive: true, force: true }));
|
|
6448
6926
|
const readOwner = deps.readOwner ?? readDaemonOwner;
|
|
6449
6927
|
const log = deps.log ?? defaultLog;
|
|
6450
6928
|
const termGraceMs = deps.termGraceMs ?? TERM_GRACE_MS;
|
|
@@ -6457,7 +6935,7 @@ async function reapStaleDaemonVersions(ownPaths, deps = {}) {
|
|
|
6457
6935
|
const version = parseVersionEntry(entry.name);
|
|
6458
6936
|
if (version === null || !entry.isDirectory())
|
|
6459
6937
|
continue;
|
|
6460
|
-
const versionDir =
|
|
6938
|
+
const versionDir = join9(baseDir, entry.name);
|
|
6461
6939
|
const siblingPaths = daemonPaths({ [OMO_LSP_DAEMON_DIR]: baseDir }, { cliPath: ownPaths.cliPath, version });
|
|
6462
6940
|
results.push(await reapOneVersion({
|
|
6463
6941
|
version,
|
|
@@ -6481,7 +6959,7 @@ async function reapOneVersion(context) {
|
|
|
6481
6959
|
const { version, versionDir } = context;
|
|
6482
6960
|
const owner = context.readOwner(context.siblingPaths);
|
|
6483
6961
|
if (!owner) {
|
|
6484
|
-
const lockPid = readLockPid(
|
|
6962
|
+
const lockPid = readLockPid(join9(versionDir, "daemon.lock"));
|
|
6485
6963
|
if (lockPid !== null && context.isAlive(lockPid)) {
|
|
6486
6964
|
context.log(`reap: sparing v${version}: owner metadata missing but daemon.lock is held by live pid ${lockPid}`);
|
|
6487
6965
|
return { version, status: "spared", reason: `owner metadata missing but lock held by live pid ${lockPid}` };
|
|
@@ -6547,7 +7025,7 @@ function splitCmdline(buffer) {
|
|
|
6547
7025
|
function isNodeCliDaemonArgv(argv) {
|
|
6548
7026
|
if (argv.length < 2 || !argv.includes("daemon"))
|
|
6549
7027
|
return false;
|
|
6550
|
-
const executable =
|
|
7028
|
+
const executable = basename5(argv[0] ?? "");
|
|
6551
7029
|
if (!/^node(?:\.exe)?$/i.test(executable))
|
|
6552
7030
|
return false;
|
|
6553
7031
|
return argv.some((value) => value === "cli.js" || value.endsWith("/cli.js") || value.endsWith("\\cli.js"));
|
|
@@ -6555,17 +7033,17 @@ function isNodeCliDaemonArgv(argv) {
|
|
|
6555
7033
|
function isNodeCliDaemonCommand(command) {
|
|
6556
7034
|
return /\bnode(?:\.exe)?\b/i.test(command) && /\bcli\.js\b/.test(command) && /\bdaemon\b/.test(command);
|
|
6557
7035
|
}
|
|
6558
|
-
function defaultReadProcFile(
|
|
6559
|
-
return readFile(
|
|
7036
|
+
function defaultReadProcFile(path) {
|
|
7037
|
+
return readFile(path);
|
|
6560
7038
|
}
|
|
6561
7039
|
function defaultExecuteForStdout(file, args) {
|
|
6562
|
-
return new Promise((
|
|
6563
|
-
execFile(file, [...args], { encoding: "utf8", maxBuffer: 1024 * 1024, timeout: 1000 }, (error, stdout) => {
|
|
7040
|
+
return new Promise((resolve) => {
|
|
7041
|
+
execFile(file, [...args], { encoding: "utf8", maxBuffer: 1024 * 1024, timeout: 1000, windowsHide: true }, (error, stdout) => {
|
|
6564
7042
|
if (error !== null) {
|
|
6565
|
-
|
|
7043
|
+
resolve(null);
|
|
6566
7044
|
return;
|
|
6567
7045
|
}
|
|
6568
|
-
|
|
7046
|
+
resolve(stdout);
|
|
6569
7047
|
});
|
|
6570
7048
|
});
|
|
6571
7049
|
}
|
|
@@ -6584,7 +7062,7 @@ async function defaultWaitForExit(pid, timeoutMs) {
|
|
|
6584
7062
|
return true;
|
|
6585
7063
|
if (Date.now() >= deadline)
|
|
6586
7064
|
return false;
|
|
6587
|
-
await new Promise((
|
|
7065
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
6588
7066
|
}
|
|
6589
7067
|
}
|
|
6590
7068
|
function defaultLog(message) {
|
|
@@ -6605,7 +7083,7 @@ async function startDaemonServer(paths, options = {}) {
|
|
|
6605
7083
|
lastActiveAt = Date.now();
|
|
6606
7084
|
};
|
|
6607
7085
|
let routeOwner = lease.owner;
|
|
6608
|
-
const
|
|
7086
|
+
const server = createServer2((socket) => {
|
|
6609
7087
|
connections.add(socket);
|
|
6610
7088
|
const activeRequests = new Map;
|
|
6611
7089
|
touch();
|
|
@@ -6623,10 +7101,10 @@ async function startDaemonServer(paths, options = {}) {
|
|
|
6623
7101
|
touch();
|
|
6624
7102
|
});
|
|
6625
7103
|
});
|
|
6626
|
-
|
|
7104
|
+
server.on("error", (error) => logServerError(error));
|
|
6627
7105
|
let owner;
|
|
6628
7106
|
try {
|
|
6629
|
-
await listen(
|
|
7107
|
+
await listen(server, paths.socket);
|
|
6630
7108
|
if (process.platform !== "win32")
|
|
6631
7109
|
chmodSync2(paths.socket, 384);
|
|
6632
7110
|
owner = { ...lease.owner, endpoint: endpointIdentity(paths.socket) };
|
|
@@ -6648,7 +7126,7 @@ async function startDaemonServer(paths, options = {}) {
|
|
|
6648
7126
|
for (const socket of connections)
|
|
6649
7127
|
socket.destroy();
|
|
6650
7128
|
connections.clear();
|
|
6651
|
-
await closeServer(
|
|
7129
|
+
await closeServer(server);
|
|
6652
7130
|
removeDaemonMetadataForOwner(paths, owner);
|
|
6653
7131
|
await disposeDefaultLspManager();
|
|
6654
7132
|
};
|
|
@@ -6669,7 +7147,7 @@ async function startDaemonServer(paths, options = {}) {
|
|
|
6669
7147
|
}, idleCheckIntervalMs);
|
|
6670
7148
|
idleTimer.unref();
|
|
6671
7149
|
installSignalHandlers(close);
|
|
6672
|
-
return { server
|
|
7150
|
+
return { server, close };
|
|
6673
7151
|
}
|
|
6674
7152
|
async function respond(socket, message, token, owner, activeRequests) {
|
|
6675
7153
|
try {
|
|
@@ -6690,18 +7168,18 @@ async function assertSelfProbe(paths, token, owner) {
|
|
|
6690
7168
|
if (!ping || ping.nonce !== owner.nonce)
|
|
6691
7169
|
throw new DaemonStartupDeferredError("self_probe_failed");
|
|
6692
7170
|
}
|
|
6693
|
-
function listen(
|
|
6694
|
-
return new Promise((
|
|
7171
|
+
function listen(server, socketPath) {
|
|
7172
|
+
return new Promise((resolve, reject) => {
|
|
6695
7173
|
const onError = (error) => reject(error);
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
7174
|
+
server.once("error", onError);
|
|
7175
|
+
server.listen(socketPath, () => {
|
|
7176
|
+
server.removeListener("error", onError);
|
|
7177
|
+
resolve();
|
|
6700
7178
|
});
|
|
6701
7179
|
});
|
|
6702
7180
|
}
|
|
6703
|
-
function closeServer(
|
|
6704
|
-
return new Promise((
|
|
7181
|
+
function closeServer(server) {
|
|
7182
|
+
return new Promise((resolve) => server.close(() => resolve()));
|
|
6705
7183
|
}
|
|
6706
7184
|
function installSignalHandlers(close) {
|
|
6707
7185
|
const handler = () => {
|