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