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
|
@@ -13,6 +13,8 @@ import { homedir as homedir3 } from "node:os";
|
|
|
13
13
|
import { join as join11, resolve as resolve11 } from "node:path";
|
|
14
14
|
|
|
15
15
|
// ../../../../lsp-daemon/dist/client.js
|
|
16
|
+
import { statSync as statSync5 } from "node:fs";
|
|
17
|
+
import { isAbsolute as isAbsolute6 } from "node:path";
|
|
16
18
|
import { connect } from "node:net";
|
|
17
19
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
18
20
|
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
@@ -42,8 +44,8 @@ import * as path from "node:path";
|
|
|
42
44
|
import { fileURLToPath } from "node:url";
|
|
43
45
|
import { statSync as statSync2 } from "node:fs";
|
|
44
46
|
import { isAbsolute as isAbsolute2 } from "node:path";
|
|
45
|
-
import { existsSync as
|
|
46
|
-
import { basename as basename3, dirname as
|
|
47
|
+
import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
|
|
48
|
+
import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
|
|
47
49
|
import { basename as basename2, extname } from "node:path";
|
|
48
50
|
import { resolve as resolve6 } from "node:path";
|
|
49
51
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
@@ -62,32 +64,32 @@ import { createHash as createHash2 } from "node:crypto";
|
|
|
62
64
|
import { dirname as dirname5, relative as relative4, resolve as resolve4 } from "node:path";
|
|
63
65
|
import { existsSync as existsSync6, lstatSync as lstatSync4, readdirSync as readdirSync2 } from "node:fs";
|
|
64
66
|
import { dirname as dirname6, resolve as resolve5 } from "node:path";
|
|
65
|
-
import { existsSync as existsSync7,
|
|
66
|
-
import { dirname as dirname7 } from "node:path";
|
|
67
|
-
import { existsSync as existsSync8, readFileSync as
|
|
68
|
-
import {
|
|
69
|
-
import {
|
|
70
|
-
import { existsSync as
|
|
71
|
-
import { join as
|
|
67
|
+
import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
|
|
68
|
+
import { dirname as dirname7, join as join3 } from "node:path";
|
|
69
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
70
|
+
import { dirname as dirname8 } from "node:path";
|
|
71
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
|
|
72
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
73
|
+
import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
|
|
74
|
+
import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
|
|
75
|
+
import { join as join6, resolve as resolve9 } from "node:path";
|
|
72
76
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
73
77
|
import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
|
|
74
|
-
import { join as
|
|
75
|
-
import {
|
|
76
|
-
import { isAbsolute as isAbsolute5 } from "node:path";
|
|
78
|
+
import { join as join7 } from "node:path";
|
|
79
|
+
import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
77
80
|
|
|
78
81
|
class LspRequestContextParseError extends Error {
|
|
79
|
-
code;
|
|
80
|
-
name = "LspRequestContextParseError";
|
|
81
82
|
constructor(code, message) {
|
|
82
83
|
super(message);
|
|
83
84
|
this.code = code;
|
|
85
|
+
this.name = "LspRequestContextParseError";
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
class LspRequestContextUnavailableError extends Error {
|
|
88
|
-
name = "LspRequestContextUnavailableError";
|
|
89
90
|
constructor() {
|
|
90
91
|
super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
|
|
92
|
+
this.name = "LspRequestContextUnavailableError";
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
var storage = new AsyncLocalStorage;
|
|
@@ -113,18 +115,18 @@ function parseLspRequestContext(value) {
|
|
|
113
115
|
const installDecisionsPath = stringField(value, "installDecisionsPath");
|
|
114
116
|
const capabilities = capabilitiesField(value["capabilities"]);
|
|
115
117
|
const canonical = canonicalCwd(cwd);
|
|
116
|
-
for (const
|
|
117
|
-
requireAbsolutePath(
|
|
118
|
-
const projectPath = canonicalizeExistingOrNearestAncestor(
|
|
118
|
+
for (const path of projectConfigPaths) {
|
|
119
|
+
requireAbsolutePath(path, "projectConfigPaths");
|
|
120
|
+
const projectPath = canonicalizeExistingOrNearestAncestor(path);
|
|
119
121
|
if (!isPathInside(canonical, projectPath)) {
|
|
120
|
-
throw new LspRequestContextParseError("project_config_outside_cwd", `Project LSP config path must be inside cwd: ${
|
|
122
|
+
throw new LspRequestContextParseError("project_config_outside_cwd", `Project LSP config path must be inside cwd: ${path}`);
|
|
121
123
|
}
|
|
122
124
|
}
|
|
123
125
|
requireAbsolutePath(userConfigPath, "userConfigPath");
|
|
124
126
|
requireAbsolutePath(installDecisionsPath, "installDecisionsPath");
|
|
125
127
|
return {
|
|
126
128
|
cwd: canonical,
|
|
127
|
-
projectConfigPaths: projectConfigPaths.map((
|
|
129
|
+
projectConfigPaths: projectConfigPaths.map((path) => canonicalizeExistingOrNearestAncestor(path)),
|
|
128
130
|
userConfigPath,
|
|
129
131
|
installDecisionsPath,
|
|
130
132
|
capabilities
|
|
@@ -137,8 +139,8 @@ function canonicalCwd(cwd) {
|
|
|
137
139
|
}
|
|
138
140
|
return realpathSync(resolved);
|
|
139
141
|
}
|
|
140
|
-
function canonicalizeExistingOrNearestAncestor(
|
|
141
|
-
let current = resolve(
|
|
142
|
+
function canonicalizeExistingOrNearestAncestor(path) {
|
|
143
|
+
let current = resolve(path);
|
|
142
144
|
const suffix = [];
|
|
143
145
|
while (true) {
|
|
144
146
|
try {
|
|
@@ -180,9 +182,9 @@ function stringArrayField(value, field) {
|
|
|
180
182
|
}
|
|
181
183
|
return fieldValue;
|
|
182
184
|
}
|
|
183
|
-
function requireAbsolutePath(
|
|
184
|
-
if (!isAbsolute(
|
|
185
|
-
throw new LspRequestContextParseError("relative_path", `LSP request context.${field} must be absolute: ${
|
|
185
|
+
function requireAbsolutePath(path, field) {
|
|
186
|
+
if (!isAbsolute(path)) {
|
|
187
|
+
throw new LspRequestContextParseError("relative_path", `LSP request context.${field} must be absolute: ${path}`);
|
|
186
188
|
}
|
|
187
189
|
}
|
|
188
190
|
function isPathInside(parent, child) {
|
|
@@ -214,7 +216,6 @@ function isPlainRecord(value) {
|
|
|
214
216
|
}
|
|
215
217
|
|
|
216
218
|
class DaemonRequestError extends Error {
|
|
217
|
-
requestWritten;
|
|
218
219
|
constructor(message, requestWritten) {
|
|
219
220
|
super(message);
|
|
220
221
|
this.name = "DaemonRequestError";
|
|
@@ -237,7 +238,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
|
|
|
237
238
|
}
|
|
238
239
|
|
|
239
240
|
class DaemonRequestTimedOutError extends DaemonRequestError {
|
|
240
|
-
timeoutMs;
|
|
241
241
|
constructor(requestWritten, timeoutMs) {
|
|
242
242
|
super("daemon request timed out", requestWritten);
|
|
243
243
|
this.name = "DaemonRequestTimedOutError";
|
|
@@ -314,20 +314,18 @@ var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
|
|
|
314
314
|
var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
315
315
|
|
|
316
316
|
class InvalidRuntimeOverrideError extends Error {
|
|
317
|
-
code = "invalid_runtime_override";
|
|
318
|
-
reason;
|
|
319
317
|
constructor(reason, message) {
|
|
320
318
|
super(message);
|
|
319
|
+
this.code = "invalid_runtime_override";
|
|
321
320
|
this.name = "InvalidRuntimeOverrideError";
|
|
322
321
|
this.reason = reason;
|
|
323
322
|
}
|
|
324
323
|
}
|
|
325
324
|
|
|
326
325
|
class InvalidDaemonVersionError extends Error {
|
|
327
|
-
code = "invalid_daemon_version";
|
|
328
|
-
version;
|
|
329
326
|
constructor(version) {
|
|
330
327
|
super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
|
|
328
|
+
this.code = "invalid_daemon_version";
|
|
331
329
|
this.name = "InvalidDaemonVersionError";
|
|
332
330
|
this.version = version;
|
|
333
331
|
}
|
|
@@ -371,10 +369,9 @@ var requireFromHere = createRequire(import.meta.url);
|
|
|
371
369
|
var MAX_SOCKET_PATH_LENGTH = 100;
|
|
372
370
|
|
|
373
371
|
class InvalidDaemonDirectoryError extends Error {
|
|
374
|
-
code = "invalid_daemon_directory";
|
|
375
|
-
directory;
|
|
376
372
|
constructor(directory) {
|
|
377
373
|
super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
|
|
374
|
+
this.code = "invalid_daemon_directory";
|
|
378
375
|
this.name = "InvalidDaemonDirectoryError";
|
|
379
376
|
this.directory = directory;
|
|
380
377
|
}
|
|
@@ -524,7 +521,7 @@ async function probeDaemon(paths, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
524
521
|
return await pingDaemon(paths, token, timeoutMs, signal) !== null;
|
|
525
522
|
}
|
|
526
523
|
function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
527
|
-
return new Promise((
|
|
524
|
+
return new Promise((resolve) => {
|
|
528
525
|
const socket = new Socket;
|
|
529
526
|
let settled = false;
|
|
530
527
|
let timer;
|
|
@@ -536,7 +533,7 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
536
533
|
clearTimeout(timer);
|
|
537
534
|
signal?.removeEventListener("abort", onAbort);
|
|
538
535
|
socket.destroy();
|
|
539
|
-
|
|
536
|
+
resolve(value);
|
|
540
537
|
};
|
|
541
538
|
const onAbort = () => finish(null);
|
|
542
539
|
const decoder = createLineDecoder((message) => {
|
|
@@ -559,13 +556,17 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
559
556
|
socket.connect(paths.socket);
|
|
560
557
|
});
|
|
561
558
|
}
|
|
562
|
-
function spawnDaemonProcess(paths) {
|
|
559
|
+
function spawnDaemonProcess(paths, deps = {}) {
|
|
563
560
|
mkdirSync2(dirname3(paths.log), { recursive: true });
|
|
564
561
|
const logFd = openSync2(paths.log, "a");
|
|
565
562
|
try {
|
|
566
|
-
const
|
|
563
|
+
const spawnDaemonChild = deps.spawn ?? spawn;
|
|
564
|
+
const executable = deps.resolveExecutable?.() ?? resolveDaemonNodeExecutable();
|
|
565
|
+
const child = spawnDaemonChild(executable, [paths.cliPath, "daemon"], {
|
|
567
566
|
detached: true,
|
|
568
|
-
stdio: ["ignore", logFd, logFd]
|
|
567
|
+
stdio: ["ignore", logFd, logFd],
|
|
568
|
+
windowsHide: true,
|
|
569
|
+
env: { ...process.env, BUN_BE_BUN: "1" }
|
|
569
570
|
});
|
|
570
571
|
child.once("spawn", () => closeSync2(logFd));
|
|
571
572
|
child.once("error", (error) => {
|
|
@@ -595,7 +596,7 @@ function defaultEnsureDaemonDeps() {
|
|
|
595
596
|
};
|
|
596
597
|
}
|
|
597
598
|
function sleepWithSignal(ms, signal) {
|
|
598
|
-
return new Promise((
|
|
599
|
+
return new Promise((resolve) => {
|
|
599
600
|
let settled = false;
|
|
600
601
|
const finish = () => {
|
|
601
602
|
if (settled)
|
|
@@ -603,7 +604,7 @@ function sleepWithSignal(ms, signal) {
|
|
|
603
604
|
settled = true;
|
|
604
605
|
clearTimeout(timer);
|
|
605
606
|
signal?.removeEventListener("abort", finish);
|
|
606
|
-
|
|
607
|
+
resolve();
|
|
607
608
|
};
|
|
608
609
|
const timer = setTimeout(finish, ms);
|
|
609
610
|
if (signal?.aborted) {
|
|
@@ -618,7 +619,7 @@ function awaitWithSignal(promise, signal) {
|
|
|
618
619
|
return promise;
|
|
619
620
|
if (signal.aborted)
|
|
620
621
|
return Promise.reject(abortError(signal));
|
|
621
|
-
return new Promise((
|
|
622
|
+
return new Promise((resolve, reject) => {
|
|
622
623
|
let settled = false;
|
|
623
624
|
const finish = (run) => {
|
|
624
625
|
if (settled)
|
|
@@ -629,7 +630,7 @@ function awaitWithSignal(promise, signal) {
|
|
|
629
630
|
};
|
|
630
631
|
const onAbort = () => finish(() => reject(abortError(signal)));
|
|
631
632
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
632
|
-
promise.then((value) => finish(() =>
|
|
633
|
+
promise.then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error)));
|
|
633
634
|
});
|
|
634
635
|
}
|
|
635
636
|
function throwIfAborted(signal) {
|
|
@@ -658,18 +659,18 @@ function parsePingResponse(message) {
|
|
|
658
659
|
return null;
|
|
659
660
|
if (!endpoint || typeof endpoint !== "object" || Array.isArray(endpoint))
|
|
660
661
|
return null;
|
|
661
|
-
const
|
|
662
|
+
const path = Reflect.get(endpoint, "path");
|
|
662
663
|
const kind = Reflect.get(endpoint, "kind");
|
|
663
|
-
if (typeof
|
|
664
|
+
if (typeof path !== "string")
|
|
664
665
|
return null;
|
|
665
666
|
if (kind === "windows")
|
|
666
|
-
return { pid, nonce, startedAt, endpoint: { kind, path
|
|
667
|
+
return { pid, nonce, startedAt, endpoint: { kind, path } };
|
|
667
668
|
if (kind === "missing")
|
|
668
|
-
return { pid, nonce, startedAt, endpoint: { kind, path
|
|
669
|
+
return { pid, nonce, startedAt, endpoint: { kind, path } };
|
|
669
670
|
const dev = Reflect.get(endpoint, "dev");
|
|
670
671
|
const ino = Reflect.get(endpoint, "ino");
|
|
671
672
|
if (kind === "unix" && typeof dev === "number" && typeof ino === "number") {
|
|
672
|
-
return { pid, nonce, startedAt, endpoint: { kind, path
|
|
673
|
+
return { pid, nonce, startedAt, endpoint: { kind, path, dev, ino } };
|
|
673
674
|
}
|
|
674
675
|
return null;
|
|
675
676
|
}
|
|
@@ -686,22 +687,15 @@ function effectiveExtension(filePath) {
|
|
|
686
687
|
}
|
|
687
688
|
|
|
688
689
|
class LspConnectionClosedError extends Error {
|
|
689
|
-
serverId;
|
|
690
|
-
root;
|
|
691
|
-
name = "LspConnectionClosedError";
|
|
692
690
|
constructor(serverId, root, message) {
|
|
693
691
|
super(message ?? `LSP connection closed for ${serverId} at ${root}`);
|
|
694
692
|
this.serverId = serverId;
|
|
695
693
|
this.root = root;
|
|
694
|
+
this.name = "LspConnectionClosedError";
|
|
696
695
|
}
|
|
697
696
|
}
|
|
698
697
|
|
|
699
698
|
class LspProcessExitedError extends Error {
|
|
700
|
-
serverId;
|
|
701
|
-
root;
|
|
702
|
-
exitCode;
|
|
703
|
-
stderrTail;
|
|
704
|
-
name = "LspProcessExitedError";
|
|
705
699
|
constructor(serverId, root, exitCode, stderrTail) {
|
|
706
700
|
const stderrSuffix = stderrTail ? `
|
|
707
701
|
stderr tail: ${stderrTail}` : "";
|
|
@@ -710,46 +704,59 @@ stderr tail: ${stderrTail}` : "";
|
|
|
710
704
|
this.root = root;
|
|
711
705
|
this.exitCode = exitCode;
|
|
712
706
|
this.stderrTail = stderrTail;
|
|
707
|
+
this.name = "LspProcessExitedError";
|
|
713
708
|
}
|
|
714
709
|
}
|
|
715
710
|
|
|
716
711
|
class LspRequestTimeoutError extends Error {
|
|
717
|
-
method;
|
|
718
|
-
stderrTail;
|
|
719
|
-
name = "LspRequestTimeoutError";
|
|
720
712
|
constructor(method, stderrTail) {
|
|
721
713
|
const stderrSuffix = stderrTail ? `
|
|
722
714
|
recent stderr: ${stderrTail}` : "";
|
|
723
715
|
super(`LSP request timeout (method: ${method})${stderrSuffix}`);
|
|
724
716
|
this.method = method;
|
|
725
717
|
this.stderrTail = stderrTail;
|
|
718
|
+
this.name = "LspRequestTimeoutError";
|
|
726
719
|
}
|
|
727
720
|
}
|
|
728
721
|
|
|
729
722
|
class LspInvalidPathError extends Error {
|
|
730
|
-
|
|
723
|
+
constructor() {
|
|
724
|
+
super(...arguments);
|
|
725
|
+
this.name = "LspInvalidPathError";
|
|
726
|
+
}
|
|
731
727
|
}
|
|
732
728
|
|
|
733
729
|
class LspServerLookupError extends Error {
|
|
734
|
-
lookup;
|
|
735
|
-
name = "LspServerLookupError";
|
|
736
730
|
constructor(message, lookup) {
|
|
737
731
|
super(message);
|
|
738
732
|
this.lookup = lookup;
|
|
733
|
+
this.name = "LspServerLookupError";
|
|
739
734
|
}
|
|
740
735
|
}
|
|
741
736
|
|
|
742
737
|
class LspServerInitializingError extends Error {
|
|
743
|
-
originalError;
|
|
744
|
-
name = "LspServerInitializingError";
|
|
745
738
|
constructor(originalError) {
|
|
746
739
|
super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
|
|
747
740
|
this.originalError = originalError;
|
|
741
|
+
this.name = "LspServerInitializingError";
|
|
748
742
|
}
|
|
749
743
|
}
|
|
750
744
|
|
|
751
745
|
class LspProcessSpawnError extends Error {
|
|
752
|
-
|
|
746
|
+
constructor() {
|
|
747
|
+
super(...arguments);
|
|
748
|
+
this.name = "LspProcessSpawnError";
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
class LspClientRespawnBudgetExceededError extends Error {
|
|
753
|
+
constructor(serverId, root, retryLimit) {
|
|
754
|
+
super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
|
|
755
|
+
this.serverId = serverId;
|
|
756
|
+
this.root = root;
|
|
757
|
+
this.retryLimit = retryLimit;
|
|
758
|
+
this.name = "LspClientRespawnBudgetExceededError";
|
|
759
|
+
}
|
|
753
760
|
}
|
|
754
761
|
function isLspDeadConnectionError(err) {
|
|
755
762
|
return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
|
|
@@ -762,6 +769,11 @@ function reportBestEffortCleanupError(operation, error, logger = writeCleanupErr
|
|
|
762
769
|
const message = error instanceof Error ? error.message : String(error);
|
|
763
770
|
logger(`[lsp] ignored ${operation} failure during cleanup: ${message}`);
|
|
764
771
|
}
|
|
772
|
+
var realTimerProvider = {
|
|
773
|
+
now: () => Date.now(),
|
|
774
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
775
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
776
|
+
};
|
|
765
777
|
var DEFAULT_MAX_REFERENCES = 200;
|
|
766
778
|
var DEFAULT_MAX_SYMBOLS = 200;
|
|
767
779
|
var DEFAULT_MAX_DIAGNOSTICS = 200;
|
|
@@ -769,9 +781,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
|
|
|
769
781
|
var REQUEST_TIMEOUT_MS = 15000;
|
|
770
782
|
var INIT_TIMEOUT_MS = 60000;
|
|
771
783
|
var IDLE_TIMEOUT_MS = 5 * 60000;
|
|
784
|
+
var MAX_RESIDENT_CLIENTS = 6;
|
|
772
785
|
var REAPER_INTERVAL_MS = 60000;
|
|
773
786
|
var STOP_HARD_KILL_TIMEOUT_MS = 5000;
|
|
774
787
|
var STOP_SIGKILL_GRACE_MS = 1000;
|
|
788
|
+
var CLIENT_RESPAWN_RETRY_LIMIT = 2;
|
|
789
|
+
var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
|
|
775
790
|
var HEADER_SEPARATOR2 = `\r
|
|
776
791
|
\r
|
|
777
792
|
`;
|
|
@@ -781,20 +796,31 @@ var METHOD_NOT_FOUND = -32601;
|
|
|
781
796
|
var INTERNAL_ERROR = -32603;
|
|
782
797
|
|
|
783
798
|
class JsonRpcConnection {
|
|
784
|
-
reader;
|
|
785
|
-
writer;
|
|
786
|
-
pendingRequests = new Map;
|
|
787
|
-
notificationHandlers = new Map;
|
|
788
|
-
requestHandlers = new Map;
|
|
789
|
-
closeHandlers = [];
|
|
790
|
-
errorHandlers = [];
|
|
791
|
-
inputBuffer = Buffer.alloc(0);
|
|
792
|
-
nextRequestId = 1;
|
|
793
|
-
listening = false;
|
|
794
|
-
disposed = false;
|
|
795
799
|
constructor(reader, writer) {
|
|
796
800
|
this.reader = reader;
|
|
797
801
|
this.writer = writer;
|
|
802
|
+
this.pendingRequests = new Map;
|
|
803
|
+
this.notificationHandlers = new Map;
|
|
804
|
+
this.requestHandlers = new Map;
|
|
805
|
+
this.closeHandlers = [];
|
|
806
|
+
this.errorHandlers = [];
|
|
807
|
+
this.inputBuffer = Buffer.alloc(0);
|
|
808
|
+
this.nextRequestId = 1;
|
|
809
|
+
this.listening = false;
|
|
810
|
+
this.disposed = false;
|
|
811
|
+
this.handleData = (chunk) => {
|
|
812
|
+
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
813
|
+
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
814
|
+
this.drainInputBuffer();
|
|
815
|
+
};
|
|
816
|
+
this.handleClose = () => {
|
|
817
|
+
for (const handler of this.closeHandlers) {
|
|
818
|
+
handler();
|
|
819
|
+
}
|
|
820
|
+
};
|
|
821
|
+
this.handleStreamError = (error) => {
|
|
822
|
+
this.emitError(error);
|
|
823
|
+
};
|
|
798
824
|
}
|
|
799
825
|
listen() {
|
|
800
826
|
if (this.listening)
|
|
@@ -829,7 +855,8 @@ class JsonRpcConnection {
|
|
|
829
855
|
let cancelAfterWrite = false;
|
|
830
856
|
let settled = false;
|
|
831
857
|
const writeCancel = () => this.writeMessage({ jsonrpc: "2.0", method: "$/cancelRequest", params: { id } });
|
|
832
|
-
|
|
858
|
+
let rejectAfterCancelWrite;
|
|
859
|
+
const responsePromise = new Promise((resolve, reject) => {
|
|
833
860
|
const cleanup = () => {
|
|
834
861
|
options.signal?.removeEventListener("abort", onAbort);
|
|
835
862
|
};
|
|
@@ -840,22 +867,26 @@ class JsonRpcConnection {
|
|
|
840
867
|
this.pendingRequests.delete(key);
|
|
841
868
|
cleanup();
|
|
842
869
|
const rejectCancelled = () => reject(abortError2(options.signal));
|
|
870
|
+
rejectAfterCancelWrite = async () => {
|
|
871
|
+
try {
|
|
872
|
+
await writeCancel();
|
|
873
|
+
} catch (error) {
|
|
874
|
+
this.emitError(toError(error));
|
|
875
|
+
}
|
|
876
|
+
rejectCancelled();
|
|
877
|
+
};
|
|
843
878
|
if (!requestWritten) {
|
|
844
879
|
cancelAfterWrite = true;
|
|
845
|
-
rejectCancelled();
|
|
846
880
|
return;
|
|
847
881
|
}
|
|
848
|
-
|
|
849
|
-
this.emitError(toError(error));
|
|
850
|
-
rejectCancelled();
|
|
851
|
-
});
|
|
882
|
+
rejectAfterCancelWrite();
|
|
852
883
|
};
|
|
853
884
|
const onAbort = () => settleCancel();
|
|
854
885
|
this.pendingRequests.set(key, {
|
|
855
886
|
resolve(result) {
|
|
856
887
|
settled = true;
|
|
857
888
|
cleanup();
|
|
858
|
-
|
|
889
|
+
resolve(result);
|
|
859
890
|
},
|
|
860
891
|
reject(error) {
|
|
861
892
|
settled = true;
|
|
@@ -876,7 +907,7 @@ class JsonRpcConnection {
|
|
|
876
907
|
await this.writeMessage(message);
|
|
877
908
|
requestWritten = true;
|
|
878
909
|
if (cancelAfterWrite)
|
|
879
|
-
await
|
|
910
|
+
await rejectAfterCancelWrite?.();
|
|
880
911
|
} catch (error) {
|
|
881
912
|
if (settled)
|
|
882
913
|
return responsePromise;
|
|
@@ -915,19 +946,6 @@ class JsonRpcConnection {
|
|
|
915
946
|
this.notificationHandlers.clear();
|
|
916
947
|
this.requestHandlers.clear();
|
|
917
948
|
}
|
|
918
|
-
handleData = (chunk) => {
|
|
919
|
-
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
920
|
-
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
921
|
-
this.drainInputBuffer();
|
|
922
|
-
};
|
|
923
|
-
handleClose = () => {
|
|
924
|
-
for (const handler of this.closeHandlers) {
|
|
925
|
-
handler();
|
|
926
|
-
}
|
|
927
|
-
};
|
|
928
|
-
handleStreamError = (error) => {
|
|
929
|
-
this.emitError(error);
|
|
930
|
-
};
|
|
931
949
|
drainInputBuffer() {
|
|
932
950
|
while (true) {
|
|
933
951
|
const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
|
|
@@ -1027,13 +1045,13 @@ class JsonRpcConnection {
|
|
|
1027
1045
|
const payload = `Content-Length: ${Buffer.byteLength(body, "utf8")}\r
|
|
1028
1046
|
\r
|
|
1029
1047
|
${body}`;
|
|
1030
|
-
return new Promise((
|
|
1048
|
+
return new Promise((resolve, reject) => {
|
|
1031
1049
|
this.writer.write(payload, (error) => {
|
|
1032
1050
|
if (error) {
|
|
1033
1051
|
reject(error);
|
|
1034
1052
|
return;
|
|
1035
1053
|
}
|
|
1036
|
-
|
|
1054
|
+
resolve();
|
|
1037
1055
|
});
|
|
1038
1056
|
});
|
|
1039
1057
|
}
|
|
@@ -1115,9 +1133,9 @@ function validateCwd(cwd) {
|
|
|
1115
1133
|
}
|
|
1116
1134
|
}
|
|
1117
1135
|
function wrap(proc) {
|
|
1118
|
-
const exitedPromise = new Promise((
|
|
1119
|
-
proc.once("close", (code) =>
|
|
1120
|
-
proc.once("error", () =>
|
|
1136
|
+
const exitedPromise = new Promise((resolve) => {
|
|
1137
|
+
proc.once("close", (code) => resolve(code ?? 0));
|
|
1138
|
+
proc.once("error", () => resolve(1));
|
|
1121
1139
|
});
|
|
1122
1140
|
if (!proc.stdin || !proc.stdout || !proc.stderr) {
|
|
1123
1141
|
throw new LspProcessSpawnError("Spawned process is missing one of stdin/stdout/stderr pipes");
|
|
@@ -1267,33 +1285,29 @@ function isPosition(value) {
|
|
|
1267
1285
|
}
|
|
1268
1286
|
|
|
1269
1287
|
class LspClientNotStartedError extends Error {
|
|
1270
|
-
serverId;
|
|
1271
|
-
root;
|
|
1272
|
-
name = "LspClientNotStartedError";
|
|
1273
1288
|
constructor(serverId, root) {
|
|
1274
1289
|
super("LSP client not started");
|
|
1275
1290
|
this.serverId = serverId;
|
|
1276
1291
|
this.root = root;
|
|
1292
|
+
this.name = "LspClientNotStartedError";
|
|
1277
1293
|
}
|
|
1278
1294
|
}
|
|
1279
1295
|
|
|
1280
1296
|
class LspClientTransport {
|
|
1281
|
-
root
|
|
1282
|
-
server;
|
|
1283
|
-
proc = null;
|
|
1284
|
-
connection = null;
|
|
1285
|
-
stderrBuffer = [];
|
|
1286
|
-
processExited = false;
|
|
1287
|
-
diagnosticsStore = new Map;
|
|
1288
|
-
requestTimeoutMs;
|
|
1289
|
-
initializeTimeoutMs;
|
|
1290
|
-
workspaceApplyEditHandler = null;
|
|
1291
|
-
diagnosticPullSupported = false;
|
|
1292
|
-
constructor(root, server2, timeouts = {}) {
|
|
1297
|
+
constructor(root, server, timeouts = {}) {
|
|
1293
1298
|
this.root = root;
|
|
1294
|
-
this.server =
|
|
1299
|
+
this.server = server;
|
|
1300
|
+
this.proc = null;
|
|
1301
|
+
this.connection = null;
|
|
1302
|
+
this.stderrBuffer = [];
|
|
1303
|
+
this.processExited = false;
|
|
1304
|
+
this.diagnosticsStore = new Map;
|
|
1305
|
+
this.workspaceApplyEditHandler = null;
|
|
1306
|
+
this.diagnosticPullSupported = false;
|
|
1307
|
+
this.documentFormattingSupported = false;
|
|
1295
1308
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
1296
1309
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
1310
|
+
this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
|
|
1297
1311
|
}
|
|
1298
1312
|
pid() {
|
|
1299
1313
|
return this.proc?.pid;
|
|
@@ -1313,6 +1327,12 @@ class LspClientTransport {
|
|
|
1313
1327
|
isDiagnosticPullSupported() {
|
|
1314
1328
|
return this.diagnosticPullSupported;
|
|
1315
1329
|
}
|
|
1330
|
+
setDocumentFormattingSupported(supported) {
|
|
1331
|
+
this.documentFormattingSupported = supported;
|
|
1332
|
+
}
|
|
1333
|
+
isDocumentFormattingSupported() {
|
|
1334
|
+
return this.documentFormattingSupported;
|
|
1335
|
+
}
|
|
1316
1336
|
handlePublishDiagnostics(params) {
|
|
1317
1337
|
this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
|
|
1318
1338
|
}
|
|
@@ -1388,7 +1408,7 @@ class LspClientTransport {
|
|
|
1388
1408
|
const options = args[1];
|
|
1389
1409
|
const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
|
|
1390
1410
|
const timeoutController = new AbortController;
|
|
1391
|
-
const timeoutHandle = setTimeout(() => {
|
|
1411
|
+
const timeoutHandle = this.timerProvider.setTimeout(() => {
|
|
1392
1412
|
const stderrTail = this.stderrBuffer.slice(-5).join(`
|
|
1393
1413
|
`);
|
|
1394
1414
|
timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
|
|
@@ -1407,7 +1427,7 @@ class LspClientTransport {
|
|
|
1407
1427
|
}
|
|
1408
1428
|
throw error;
|
|
1409
1429
|
} finally {
|
|
1410
|
-
clearTimeout(timeoutHandle);
|
|
1430
|
+
this.timerProvider.clearTimeout(timeoutHandle);
|
|
1411
1431
|
combinedSignal.dispose();
|
|
1412
1432
|
}
|
|
1413
1433
|
}
|
|
@@ -1458,8 +1478,8 @@ class LspClientTransport {
|
|
|
1458
1478
|
try {
|
|
1459
1479
|
proc.kill();
|
|
1460
1480
|
let timeoutId;
|
|
1461
|
-
const timeoutPromise = new Promise((
|
|
1462
|
-
timeoutId = setTimeout(
|
|
1481
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
1482
|
+
timeoutId = setTimeout(resolve, STOP_HARD_KILL_TIMEOUT_MS);
|
|
1463
1483
|
});
|
|
1464
1484
|
await Promise.race([
|
|
1465
1485
|
proc.exited.then(() => {
|
|
@@ -1475,7 +1495,7 @@ class LspClientTransport {
|
|
|
1475
1495
|
proc.kill("SIGKILL");
|
|
1476
1496
|
await Promise.race([
|
|
1477
1497
|
proc.exited,
|
|
1478
|
-
new Promise((
|
|
1498
|
+
new Promise((resolve) => setTimeout(resolve, STOP_SIGKILL_GRACE_MS))
|
|
1479
1499
|
]);
|
|
1480
1500
|
} catch (error) {
|
|
1481
1501
|
reportBestEffortCleanupError("hard process kill", error instanceof Error ? error : String(error));
|
|
@@ -1524,6 +1544,14 @@ function supportsDiagnosticPull(capabilities) {
|
|
|
1524
1544
|
return false;
|
|
1525
1545
|
return Object.hasOwn(capabilities, "diagnosticProvider");
|
|
1526
1546
|
}
|
|
1547
|
+
function supportsDocumentFormatting(capabilities) {
|
|
1548
|
+
if (capabilities === undefined)
|
|
1549
|
+
return false;
|
|
1550
|
+
const provider = capabilities.documentFormattingProvider;
|
|
1551
|
+
if (provider === undefined || provider === null || provider === false)
|
|
1552
|
+
return false;
|
|
1553
|
+
return provider === true || typeof provider === "object";
|
|
1554
|
+
}
|
|
1527
1555
|
|
|
1528
1556
|
class LspClientConnection extends LspClientTransport {
|
|
1529
1557
|
async initialize() {
|
|
@@ -1540,6 +1568,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
1540
1568
|
references: {},
|
|
1541
1569
|
documentSymbol: { hierarchicalDocumentSymbolSupport: true },
|
|
1542
1570
|
publishDiagnostics: {},
|
|
1571
|
+
formatting: { dynamicRegistration: false },
|
|
1543
1572
|
rename: {
|
|
1544
1573
|
prepareSupport: true,
|
|
1545
1574
|
prepareSupportDefaultBehavior: 1
|
|
@@ -1581,6 +1610,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
1581
1610
|
initializationOptions: this.server.initialization
|
|
1582
1611
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
1583
1612
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
1613
|
+
this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
|
|
1584
1614
|
await this.sendNotification("initialized", {});
|
|
1585
1615
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
1586
1616
|
settings: { json: { validate: { enable: true } } }
|
|
@@ -1767,6 +1797,17 @@ function canonicalPath(filePath) {
|
|
|
1767
1797
|
return absolute;
|
|
1768
1798
|
}
|
|
1769
1799
|
}
|
|
1800
|
+
function normalizeDocumentUri(uri) {
|
|
1801
|
+
let decoded = uri;
|
|
1802
|
+
try {
|
|
1803
|
+
decoded = decodeURIComponent(uri);
|
|
1804
|
+
} catch {
|
|
1805
|
+
decoded = uri;
|
|
1806
|
+
}
|
|
1807
|
+
if (process.platform !== "win32")
|
|
1808
|
+
return decoded;
|
|
1809
|
+
return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
|
|
1810
|
+
}
|
|
1770
1811
|
function isSameOrDescendant(candidate, parent) {
|
|
1771
1812
|
const suffix = relative2(parent, candidate);
|
|
1772
1813
|
return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
|
|
@@ -1777,30 +1818,31 @@ function movedPath(candidate, oldPath, newPath) {
|
|
|
1777
1818
|
}
|
|
1778
1819
|
|
|
1779
1820
|
class WorkspaceDocumentState {
|
|
1780
|
-
sendNotification;
|
|
1781
|
-
clearDiagnostics;
|
|
1782
|
-
openDocuments = new Map;
|
|
1783
|
-
openByUri = new Map;
|
|
1784
|
-
openPromises = new Map;
|
|
1785
|
-
now;
|
|
1786
|
-
versionlessPublishQuiescenceMs;
|
|
1787
1821
|
constructor(sendNotification, clearDiagnostics, options = {}) {
|
|
1788
1822
|
this.sendNotification = sendNotification;
|
|
1789
1823
|
this.clearDiagnostics = clearDiagnostics;
|
|
1790
|
-
this.
|
|
1824
|
+
this.openDocuments = new Map;
|
|
1825
|
+
this.openByUri = new Map;
|
|
1826
|
+
this.openPromises = new Map;
|
|
1827
|
+
this.timerProvider = options.timerProvider ?? {
|
|
1828
|
+
now: options.now ?? (() => Date.now()),
|
|
1829
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
1830
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
1831
|
+
};
|
|
1832
|
+
this.now = () => this.timerProvider.now();
|
|
1791
1833
|
this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
|
|
1792
1834
|
}
|
|
1793
1835
|
async openFile(filePath) {
|
|
1794
|
-
const
|
|
1795
|
-
const existingOpen = this.openPromises.get(
|
|
1836
|
+
const path = canonicalPath(filePath);
|
|
1837
|
+
const existingOpen = this.openPromises.get(path);
|
|
1796
1838
|
if (existingOpen) {
|
|
1797
1839
|
await existingOpen;
|
|
1798
|
-
return this.openFile(
|
|
1840
|
+
return this.openFile(path);
|
|
1799
1841
|
}
|
|
1800
|
-
const text = readFileSync2(
|
|
1801
|
-
const existing = this.openDocuments.get(
|
|
1842
|
+
const text = readFileSync2(path, "utf-8");
|
|
1843
|
+
const existing = this.openDocuments.get(path);
|
|
1802
1844
|
if (!existing)
|
|
1803
|
-
return this.openDocumentSingleFlight(
|
|
1845
|
+
return this.openDocumentSingleFlight(path, text);
|
|
1804
1846
|
if (existing.text === text)
|
|
1805
1847
|
return;
|
|
1806
1848
|
await this.changeDocument(existing, text);
|
|
@@ -1809,7 +1851,7 @@ class WorkspaceDocumentState {
|
|
|
1809
1851
|
return this.openDocuments.get(canonicalPath(filePath))?.version;
|
|
1810
1852
|
}
|
|
1811
1853
|
getStoredDiagnostics(uri) {
|
|
1812
|
-
const state = this.openByUri.get(uri);
|
|
1854
|
+
const state = this.openByUri.get(normalizeDocumentUri(uri));
|
|
1813
1855
|
if (!state)
|
|
1814
1856
|
return [];
|
|
1815
1857
|
return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
|
|
@@ -1831,13 +1873,13 @@ class WorkspaceDocumentState {
|
|
|
1831
1873
|
return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
|
|
1832
1874
|
}
|
|
1833
1875
|
getPullCache(snapshot) {
|
|
1834
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1876
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1835
1877
|
if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
|
|
1836
1878
|
return null;
|
|
1837
1879
|
return state.pullCache;
|
|
1838
1880
|
}
|
|
1839
1881
|
recordPullDiagnostics(snapshot, report) {
|
|
1840
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1882
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1841
1883
|
if (!state)
|
|
1842
1884
|
return;
|
|
1843
1885
|
state.pullCache = {
|
|
@@ -1847,7 +1889,7 @@ class WorkspaceDocumentState {
|
|
|
1847
1889
|
};
|
|
1848
1890
|
}
|
|
1849
1891
|
recordPublishedDiagnostics(params) {
|
|
1850
|
-
const state = this.openByUri.get(params.uri);
|
|
1892
|
+
const state = this.openByUri.get(normalizeDocumentUri(params.uri));
|
|
1851
1893
|
if (!state)
|
|
1852
1894
|
return;
|
|
1853
1895
|
state.publishGeneration += 1;
|
|
@@ -1861,7 +1903,7 @@ class WorkspaceDocumentState {
|
|
|
1861
1903
|
this.notifyWaiters(state);
|
|
1862
1904
|
}
|
|
1863
1905
|
resolvePushDiagnostics(snapshot) {
|
|
1864
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1906
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1865
1907
|
if (!state?.lastPublish)
|
|
1866
1908
|
return { status: "missing" };
|
|
1867
1909
|
const publish = state.lastPublish;
|
|
@@ -1875,7 +1917,7 @@ class WorkspaceDocumentState {
|
|
|
1875
1917
|
return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
|
|
1876
1918
|
}
|
|
1877
1919
|
waitForDiagnosticsActivity(snapshot, timeoutMs) {
|
|
1878
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1920
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1879
1921
|
if (!state || timeoutMs <= 0)
|
|
1880
1922
|
return Promise.resolve();
|
|
1881
1923
|
return new Promise((resolveActivity) => {
|
|
@@ -1884,18 +1926,18 @@ class WorkspaceDocumentState {
|
|
|
1884
1926
|
if (settled)
|
|
1885
1927
|
return;
|
|
1886
1928
|
settled = true;
|
|
1887
|
-
clearTimeout(timer);
|
|
1929
|
+
this.timerProvider.clearTimeout(timer);
|
|
1888
1930
|
state.waiters.delete(finish);
|
|
1889
1931
|
resolveActivity();
|
|
1890
1932
|
};
|
|
1891
|
-
const timer = setTimeout(finish, timeoutMs);
|
|
1933
|
+
const timer = this.timerProvider.setTimeout(finish, timeoutMs);
|
|
1892
1934
|
if (typeof timer.unref === "function")
|
|
1893
1935
|
timer.unref();
|
|
1894
1936
|
state.waiters.add(finish);
|
|
1895
1937
|
});
|
|
1896
1938
|
}
|
|
1897
1939
|
validateVersions(operations) {
|
|
1898
|
-
const versions = new Map([...this.openDocuments].map(([
|
|
1940
|
+
const versions = new Map([...this.openDocuments].map(([path, state]) => [path, state.version]));
|
|
1899
1941
|
for (const operation of operations) {
|
|
1900
1942
|
if (operation.kind === "text") {
|
|
1901
1943
|
const current = versions.get(operation.path);
|
|
@@ -1911,17 +1953,17 @@ class WorkspaceDocumentState {
|
|
|
1911
1953
|
continue;
|
|
1912
1954
|
}
|
|
1913
1955
|
if (operation.kind === "rename") {
|
|
1914
|
-
const moved = [...versions].filter(([
|
|
1915
|
-
for (const [
|
|
1916
|
-
versions.delete(
|
|
1917
|
-
for (const [
|
|
1918
|
-
versions.set(movedPath(
|
|
1956
|
+
const moved = [...versions].filter(([path]) => isSameOrDescendant(path, operation.oldPath));
|
|
1957
|
+
for (const [path] of moved)
|
|
1958
|
+
versions.delete(path);
|
|
1959
|
+
for (const [path] of moved)
|
|
1960
|
+
versions.set(movedPath(path, operation.oldPath, operation.newPath), 1);
|
|
1919
1961
|
continue;
|
|
1920
1962
|
}
|
|
1921
1963
|
if (operation.kind === "delete") {
|
|
1922
|
-
for (const
|
|
1923
|
-
if (isSameOrDescendant(
|
|
1924
|
-
versions.delete(
|
|
1964
|
+
for (const path of [...versions.keys()]) {
|
|
1965
|
+
if (isSameOrDescendant(path, operation.path))
|
|
1966
|
+
versions.delete(path);
|
|
1925
1967
|
}
|
|
1926
1968
|
continue;
|
|
1927
1969
|
}
|
|
@@ -1965,8 +2007,8 @@ class WorkspaceDocumentState {
|
|
|
1965
2007
|
for (const state of moved)
|
|
1966
2008
|
await this.closeDocument(state);
|
|
1967
2009
|
for (const state of moved) {
|
|
1968
|
-
const
|
|
1969
|
-
await this.openDocumentSingleFlight(
|
|
2010
|
+
const path = movedPath(state.path, mutation.oldPath, mutation.newPath);
|
|
2011
|
+
await this.openDocumentSingleFlight(path, readFileSync2(path, "utf-8"));
|
|
1970
2012
|
}
|
|
1971
2013
|
if (moved.length === 0) {
|
|
1972
2014
|
watched.push({ uri: pathToFileURL2(mutation.oldPath).href, type: 3 });
|
|
@@ -1980,31 +2022,31 @@ class WorkspaceDocumentState {
|
|
|
1980
2022
|
if (removed.length === 0)
|
|
1981
2023
|
watched.push({ uri: pathToFileURL2(mutation.path).href, type: 3 });
|
|
1982
2024
|
}
|
|
1983
|
-
async openDocumentSingleFlight(
|
|
1984
|
-
const existing = this.openPromises.get(
|
|
2025
|
+
async openDocumentSingleFlight(path, text) {
|
|
2026
|
+
const existing = this.openPromises.get(path);
|
|
1985
2027
|
if (existing)
|
|
1986
2028
|
return existing;
|
|
1987
2029
|
const open = (async () => {
|
|
1988
2030
|
const state = {
|
|
1989
|
-
path
|
|
1990
|
-
uri: pathToFileURL2(
|
|
1991
|
-
languageId: getLanguageId(effectiveExtension(
|
|
2031
|
+
path,
|
|
2032
|
+
uri: pathToFileURL2(path).href,
|
|
2033
|
+
languageId: getLanguageId(effectiveExtension(path)),
|
|
1992
2034
|
text,
|
|
1993
2035
|
version: 1,
|
|
1994
2036
|
generation: 1,
|
|
1995
2037
|
publishGeneration: 0,
|
|
1996
2038
|
waiters: new Set
|
|
1997
2039
|
};
|
|
1998
|
-
this.openDocuments.set(
|
|
1999
|
-
this.openByUri.set(state.uri, state);
|
|
2040
|
+
this.openDocuments.set(path, state);
|
|
2041
|
+
this.openByUri.set(normalizeDocumentUri(state.uri), state);
|
|
2000
2042
|
this.notifyWaiters(state);
|
|
2001
2043
|
await this.sendNotification("textDocument/didOpen", {
|
|
2002
2044
|
textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
|
|
2003
2045
|
});
|
|
2004
2046
|
})().finally(() => {
|
|
2005
|
-
this.openPromises.delete(
|
|
2047
|
+
this.openPromises.delete(path);
|
|
2006
2048
|
});
|
|
2007
|
-
this.openPromises.set(
|
|
2049
|
+
this.openPromises.set(path, open);
|
|
2008
2050
|
return open;
|
|
2009
2051
|
}
|
|
2010
2052
|
async changeDocument(state, text) {
|
|
@@ -2021,7 +2063,7 @@ class WorkspaceDocumentState {
|
|
|
2021
2063
|
}
|
|
2022
2064
|
async closeDocument(state) {
|
|
2023
2065
|
this.openDocuments.delete(state.path);
|
|
2024
|
-
this.openByUri.delete(state.uri);
|
|
2066
|
+
this.openByUri.delete(normalizeDocumentUri(state.uri));
|
|
2025
2067
|
this.clearDiagnostics(state.uri);
|
|
2026
2068
|
this.notifyWaiters(state);
|
|
2027
2069
|
await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
|
|
@@ -2040,13 +2082,11 @@ function workspaceApplyEditConcurrentFailureReason(phase) {
|
|
|
2040
2082
|
}
|
|
2041
2083
|
|
|
2042
2084
|
class WorkspaceEditPathError extends Error {
|
|
2043
|
-
path
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
constructor(path2, detail) {
|
|
2047
|
-
super(`${detail}: ${path2}`);
|
|
2048
|
-
this.path = path2;
|
|
2085
|
+
constructor(path, detail) {
|
|
2086
|
+
super(`${detail}: ${path}`);
|
|
2087
|
+
this.path = path;
|
|
2049
2088
|
this.detail = detail;
|
|
2089
|
+
this.name = "WorkspaceEditPathError";
|
|
2050
2090
|
}
|
|
2051
2091
|
}
|
|
2052
2092
|
function isPathInsideWorkspace(filePath, workspaceRoot) {
|
|
@@ -2108,26 +2148,26 @@ function uriToCanonicalWorkspacePath(uri, workspaceRoot) {
|
|
|
2108
2148
|
return { success: false, error: `${requestedPath}: ${detail}` };
|
|
2109
2149
|
}
|
|
2110
2150
|
}
|
|
2111
|
-
function snapshotPath(
|
|
2112
|
-
if (!existsSync4(
|
|
2151
|
+
function snapshotPath(path, includeChildren) {
|
|
2152
|
+
if (!existsSync4(path))
|
|
2113
2153
|
return { kind: "missing" };
|
|
2114
|
-
const stats = lstatSync2(
|
|
2154
|
+
const stats = lstatSync2(path);
|
|
2115
2155
|
if (stats.isFile())
|
|
2116
|
-
return { kind: "file", content: readFileSync3(
|
|
2156
|
+
return { kind: "file", content: readFileSync3(path, "utf-8") };
|
|
2117
2157
|
if (stats.isDirectory()) {
|
|
2118
|
-
return includeChildren ? { kind: "directory", children: readdirSync(
|
|
2158
|
+
return includeChildren ? { kind: "directory", children: readdirSync(path).sort() } : { kind: "directory" };
|
|
2119
2159
|
}
|
|
2120
|
-
throw new WorkspaceEditPathError(
|
|
2160
|
+
throw new WorkspaceEditPathError(path, "unsupported filesystem entry");
|
|
2121
2161
|
}
|
|
2122
2162
|
var DEFAULT_IO = {
|
|
2123
|
-
writeFile(
|
|
2124
|
-
writeFileSync(
|
|
2163
|
+
writeFile(path, content) {
|
|
2164
|
+
writeFileSync(path, content, "utf-8");
|
|
2125
2165
|
},
|
|
2126
2166
|
rename(oldPath, newPath) {
|
|
2127
2167
|
renameSync(oldPath, newPath);
|
|
2128
2168
|
},
|
|
2129
|
-
remove(
|
|
2130
|
-
rmSync(
|
|
2169
|
+
remove(path, recursive) {
|
|
2170
|
+
rmSync(path, { recursive, force: false });
|
|
2131
2171
|
}
|
|
2132
2172
|
};
|
|
2133
2173
|
function snapshotsEqual(expected, actual) {
|
|
@@ -2140,8 +2180,8 @@ function snapshotsEqual(expected, actual) {
|
|
|
2140
2180
|
}
|
|
2141
2181
|
return true;
|
|
2142
2182
|
}
|
|
2143
|
-
function liveSnapshot(
|
|
2144
|
-
return snapshotPath(
|
|
2183
|
+
function liveSnapshot(path, expected) {
|
|
2184
|
+
return snapshotPath(path, expected.kind === "directory" && expected.children !== undefined);
|
|
2145
2185
|
}
|
|
2146
2186
|
function firstOperationIndex(plan) {
|
|
2147
2187
|
return plan.operations[0]?.changeIndex ?? 0;
|
|
@@ -2162,28 +2202,28 @@ function failedCommit(plan, failure) {
|
|
|
2162
2202
|
};
|
|
2163
2203
|
}
|
|
2164
2204
|
function verifySnapshots(plan) {
|
|
2165
|
-
for (const [
|
|
2205
|
+
for (const [path, expected] of plan.snapshots) {
|
|
2166
2206
|
let actual;
|
|
2167
2207
|
try {
|
|
2168
|
-
actual = liveSnapshot(
|
|
2208
|
+
actual = liveSnapshot(path, expected);
|
|
2169
2209
|
} catch (error) {
|
|
2170
|
-
const changeIndex = plan.firstChangeByPath.get(
|
|
2210
|
+
const changeIndex = plan.firstChangeByPath.get(path) ?? firstOperationIndex(plan);
|
|
2171
2211
|
const detail = error instanceof Error ? error.message : String(error);
|
|
2172
|
-
return failedCommit(plan, { message: `cannot verify snapshot for ${
|
|
2212
|
+
return failedCommit(plan, { message: `cannot verify snapshot for ${path}: ${detail}`, changeIndex });
|
|
2173
2213
|
}
|
|
2174
2214
|
if (!snapshotsEqual(expected, actual)) {
|
|
2175
|
-
const changeIndex = plan.firstChangeByPath.get(
|
|
2176
|
-
return failedCommit(plan, { message: `workspace state changed before commit: ${
|
|
2215
|
+
const changeIndex = plan.firstChangeByPath.get(path) ?? firstOperationIndex(plan);
|
|
2216
|
+
return failedCommit(plan, { message: `workspace state changed before commit: ${path}`, changeIndex });
|
|
2177
2217
|
}
|
|
2178
2218
|
}
|
|
2179
2219
|
return null;
|
|
2180
2220
|
}
|
|
2181
|
-
function addModifiedPath(paths,
|
|
2182
|
-
if (!paths.includes(
|
|
2183
|
-
paths.push(
|
|
2221
|
+
function addModifiedPath(paths, path) {
|
|
2222
|
+
if (!paths.includes(path))
|
|
2223
|
+
paths.push(path);
|
|
2184
2224
|
}
|
|
2185
|
-
function reportedPath(plan,
|
|
2186
|
-
return plan.reportedPathByCanonical.get(
|
|
2225
|
+
function reportedPath(plan, path) {
|
|
2226
|
+
return plan.reportedPathByCanonical.get(path) ?? path;
|
|
2187
2227
|
}
|
|
2188
2228
|
function changedPathsForMutation(mutation) {
|
|
2189
2229
|
return mutation.kind === "rename" ? [mutation.oldPath, mutation.newPath] : [mutation.path];
|
|
@@ -2191,8 +2231,8 @@ function changedPathsForMutation(mutation) {
|
|
|
2191
2231
|
function mutationDelta(operations) {
|
|
2192
2232
|
const changedPaths = new Set;
|
|
2193
2233
|
for (const operation of operations) {
|
|
2194
|
-
for (const
|
|
2195
|
-
changedPaths.add(
|
|
2234
|
+
for (const path of changedPathsForMutation(operation))
|
|
2235
|
+
changedPaths.add(path);
|
|
2196
2236
|
}
|
|
2197
2237
|
return { operations, changedPaths: [...changedPaths].sort() };
|
|
2198
2238
|
}
|
|
@@ -2332,13 +2372,11 @@ function canonicalFingerprint(operations) {
|
|
|
2332
2372
|
}
|
|
2333
2373
|
|
|
2334
2374
|
class WorkspaceEditValidationError extends Error {
|
|
2335
|
-
changeIndex;
|
|
2336
|
-
detail;
|
|
2337
|
-
name = "WorkspaceEditValidationError";
|
|
2338
2375
|
constructor(changeIndex, detail) {
|
|
2339
2376
|
super(`change ${changeIndex}: ${detail}`);
|
|
2340
2377
|
this.changeIndex = changeIndex;
|
|
2341
2378
|
this.detail = detail;
|
|
2379
|
+
this.name = "WorkspaceEditValidationError";
|
|
2342
2380
|
}
|
|
2343
2381
|
}
|
|
2344
2382
|
function isRecord3(value) {
|
|
@@ -2420,14 +2458,14 @@ function parseSinglePathResource(input, kind) {
|
|
|
2420
2458
|
return;
|
|
2421
2459
|
}
|
|
2422
2460
|
if (kind === "create") {
|
|
2423
|
-
const
|
|
2461
|
+
const options = parseOptions(change["options"], ["overwrite", "ignoreIfExists"], changeIndex);
|
|
2424
2462
|
target.operations.push({
|
|
2425
2463
|
kind,
|
|
2426
2464
|
changeIndex,
|
|
2427
2465
|
path: resolvedPath.path,
|
|
2428
2466
|
reportedPath: resolvedPath.requestedPath,
|
|
2429
|
-
overwrite:
|
|
2430
|
-
ignoreIfExists:
|
|
2467
|
+
overwrite: options["overwrite"] ?? false,
|
|
2468
|
+
ignoreIfExists: options["ignoreIfExists"] ?? false,
|
|
2431
2469
|
followedSymbolicLink: resolvedPath.followedSymbolicLink
|
|
2432
2470
|
});
|
|
2433
2471
|
return;
|
|
@@ -2676,12 +2714,12 @@ function isSameOrDescendant2(candidate, parent) {
|
|
|
2676
2714
|
const relativePath = relative4(parent, candidate);
|
|
2677
2715
|
return relativePath === "" || !relativePath.startsWith("..") && relativePath !== "..";
|
|
2678
2716
|
}
|
|
2679
|
-
function removeVirtualSubtree(virtual,
|
|
2717
|
+
function removeVirtualSubtree(virtual, path) {
|
|
2680
2718
|
for (const candidate of [...virtual.keys()]) {
|
|
2681
|
-
if (isSameOrDescendant2(candidate,
|
|
2719
|
+
if (isSameOrDescendant2(candidate, path))
|
|
2682
2720
|
virtual.delete(candidate);
|
|
2683
2721
|
}
|
|
2684
|
-
virtual.set(
|
|
2722
|
+
virtual.set(path, { kind: "missing" });
|
|
2685
2723
|
}
|
|
2686
2724
|
function moveVirtualSubtree(virtual, oldPath, newPath) {
|
|
2687
2725
|
const moved = [...virtual.entries()].filter(([candidate]) => isSameOrDescendant2(candidate, oldPath));
|
|
@@ -2692,16 +2730,16 @@ function moveVirtualSubtree(virtual, oldPath, newPath) {
|
|
|
2692
2730
|
virtual.set(suffix === "" ? newPath : resolve4(newPath, suffix), entry);
|
|
2693
2731
|
}
|
|
2694
2732
|
}
|
|
2695
|
-
function virtualDirectoryHasChildren(virtual,
|
|
2733
|
+
function virtualDirectoryHasChildren(virtual, path) {
|
|
2696
2734
|
for (const [candidate, entry] of virtual) {
|
|
2697
|
-
if (candidate !==
|
|
2735
|
+
if (candidate !== path && entry.kind !== "missing" && isSameOrDescendant2(candidate, path))
|
|
2698
2736
|
return true;
|
|
2699
2737
|
}
|
|
2700
2738
|
return false;
|
|
2701
2739
|
}
|
|
2702
|
-
function requireVirtualParent(virtual,
|
|
2703
|
-
if (virtual.get(dirname5(
|
|
2704
|
-
throw new WorkspaceEditValidationError(changeIndex, `parent directory does not exist for ${
|
|
2740
|
+
function requireVirtualParent(virtual, path, changeIndex) {
|
|
2741
|
+
if (virtual.get(dirname5(path))?.kind !== "directory") {
|
|
2742
|
+
throw new WorkspaceEditValidationError(changeIndex, `parent directory does not exist for ${path}`);
|
|
2705
2743
|
}
|
|
2706
2744
|
}
|
|
2707
2745
|
function simulateOperations(parsed, snapshots) {
|
|
@@ -2820,10 +2858,9 @@ function simulateDelete(operation, virtual) {
|
|
|
2820
2858
|
}
|
|
2821
2859
|
|
|
2822
2860
|
class WorkspaceSnapshotBuilder {
|
|
2823
|
-
workspaceRoot;
|
|
2824
|
-
snapshots = new Map;
|
|
2825
2861
|
constructor(workspaceRoot) {
|
|
2826
2862
|
this.workspaceRoot = workspaceRoot;
|
|
2863
|
+
this.snapshots = new Map;
|
|
2827
2864
|
}
|
|
2828
2865
|
build(operations) {
|
|
2829
2866
|
this.add(this.workspaceRoot, false);
|
|
@@ -2844,21 +2881,21 @@ class WorkspaceSnapshotBuilder {
|
|
|
2844
2881
|
}
|
|
2845
2882
|
return this.snapshots;
|
|
2846
2883
|
}
|
|
2847
|
-
add(
|
|
2848
|
-
let candidate =
|
|
2884
|
+
add(path, includeChildren) {
|
|
2885
|
+
let candidate = path;
|
|
2849
2886
|
while (true) {
|
|
2850
2887
|
const existing = this.snapshots.get(candidate);
|
|
2851
2888
|
if (existing === undefined || includeChildren && existing.kind === "directory" && existing.children === undefined) {
|
|
2852
|
-
this.snapshots.set(candidate, snapshotPath(candidate, includeChildren && candidate ===
|
|
2889
|
+
this.snapshots.set(candidate, snapshotPath(candidate, includeChildren && candidate === path));
|
|
2853
2890
|
}
|
|
2854
2891
|
if (candidate === this.workspaceRoot)
|
|
2855
2892
|
break;
|
|
2856
2893
|
candidate = dirname6(candidate);
|
|
2857
2894
|
}
|
|
2858
|
-
if (!includeChildren || !existsSync6(
|
|
2895
|
+
if (!includeChildren || !existsSync6(path) || !lstatSync4(path).isDirectory())
|
|
2859
2896
|
return;
|
|
2860
|
-
for (const child of readdirSync2(
|
|
2861
|
-
this.add(resolve5(
|
|
2897
|
+
for (const child of readdirSync2(path))
|
|
2898
|
+
this.add(resolve5(path, child), true);
|
|
2862
2899
|
}
|
|
2863
2900
|
}
|
|
2864
2901
|
function snapshotOperations(operations, workspaceRoot) {
|
|
@@ -2866,8 +2903,10 @@ function snapshotOperations(operations, workspaceRoot) {
|
|
|
2866
2903
|
}
|
|
2867
2904
|
|
|
2868
2905
|
class PlanPathIndex {
|
|
2869
|
-
|
|
2870
|
-
|
|
2906
|
+
constructor() {
|
|
2907
|
+
this.firstChangeByPath = new Map;
|
|
2908
|
+
this.reportedPathByCanonical = new Map;
|
|
2909
|
+
}
|
|
2871
2910
|
build(operations) {
|
|
2872
2911
|
for (const operation of operations) {
|
|
2873
2912
|
switch (operation.kind) {
|
|
@@ -2883,11 +2922,11 @@ class PlanPathIndex {
|
|
|
2883
2922
|
}
|
|
2884
2923
|
}
|
|
2885
2924
|
}
|
|
2886
|
-
add(
|
|
2887
|
-
if (!this.firstChangeByPath.has(
|
|
2888
|
-
this.firstChangeByPath.set(
|
|
2889
|
-
if (!this.reportedPathByCanonical.has(
|
|
2890
|
-
this.reportedPathByCanonical.set(
|
|
2925
|
+
add(path, reportedPath, changeIndex) {
|
|
2926
|
+
if (!this.firstChangeByPath.has(path))
|
|
2927
|
+
this.firstChangeByPath.set(path, changeIndex);
|
|
2928
|
+
if (!this.reportedPathByCanonical.has(path))
|
|
2929
|
+
this.reportedPathByCanonical.set(path, reportedPath);
|
|
2891
2930
|
}
|
|
2892
2931
|
}
|
|
2893
2932
|
function fingerprintWorkspaceEdit(edit, workspaceRoot) {
|
|
@@ -2954,14 +2993,11 @@ function isRecord4(value) {
|
|
|
2954
2993
|
}
|
|
2955
2994
|
|
|
2956
2995
|
class WorkspaceMutationController {
|
|
2957
|
-
workspaceRoot;
|
|
2958
|
-
documents;
|
|
2959
|
-
activeLease = null;
|
|
2960
|
-
nextLeaseId = 1;
|
|
2961
|
-
io;
|
|
2962
2996
|
constructor(workspaceRoot, documents) {
|
|
2963
2997
|
this.workspaceRoot = workspaceRoot;
|
|
2964
2998
|
this.documents = documents;
|
|
2999
|
+
this.activeLease = null;
|
|
3000
|
+
this.nextLeaseId = 1;
|
|
2965
3001
|
}
|
|
2966
3002
|
setIo(io) {
|
|
2967
3003
|
this.io = io;
|
|
@@ -3000,15 +3036,15 @@ class WorkspaceMutationController {
|
|
|
3000
3036
|
};
|
|
3001
3037
|
}
|
|
3002
3038
|
lease.phase = "applying";
|
|
3003
|
-
lease.applyCompletion = new Promise((
|
|
3004
|
-
lease.resolveApply =
|
|
3039
|
+
lease.applyCompletion = new Promise((resolve) => {
|
|
3040
|
+
lease.resolveApply = resolve;
|
|
3005
3041
|
});
|
|
3006
3042
|
const edit = isRecord4(params) ? params["edit"] : undefined;
|
|
3007
|
-
const
|
|
3008
|
-
lease.serverApply =
|
|
3043
|
+
const record = edit === undefined ? { fingerprint: null, result: failure("workspace/applyEdit params.edit is required", 0) } : await this.applyEdit(edit, lease);
|
|
3044
|
+
lease.serverApply = record;
|
|
3009
3045
|
lease.phase = "settled";
|
|
3010
3046
|
lease.resolveApply?.();
|
|
3011
|
-
return responseFor(
|
|
3047
|
+
return responseFor(record.result);
|
|
3012
3048
|
}
|
|
3013
3049
|
async reconcileRename(leaseToken, edit) {
|
|
3014
3050
|
const lease = this.requireActiveLease(leaseToken);
|
|
@@ -3024,16 +3060,16 @@ class WorkspaceMutationController {
|
|
|
3024
3060
|
const applied = await this.applyEdit(edit, lease);
|
|
3025
3061
|
return { edit, apply: applied.result };
|
|
3026
3062
|
}
|
|
3027
|
-
reconcileServerApply(
|
|
3063
|
+
reconcileServerApply(record, edit) {
|
|
3028
3064
|
if (!edit)
|
|
3029
|
-
return { edit, apply:
|
|
3065
|
+
return { edit, apply: record.result };
|
|
3030
3066
|
const fingerprint = fingerprintWorkspaceEdit(edit, this.workspaceRoot);
|
|
3031
|
-
if (fingerprint.success &&
|
|
3032
|
-
return { edit, apply:
|
|
3067
|
+
if (fingerprint.success && record.fingerprint !== null && fingerprint.fingerprint === record.fingerprint) {
|
|
3068
|
+
return { edit, apply: record.result };
|
|
3033
3069
|
}
|
|
3034
3070
|
return {
|
|
3035
3071
|
edit,
|
|
3036
|
-
apply: failure("rename result conflicts with server-applied workspace edit", 0,
|
|
3072
|
+
apply: failure("rename result conflicts with server-applied workspace edit", 0, record.result)
|
|
3037
3073
|
};
|
|
3038
3074
|
}
|
|
3039
3075
|
async applyEdit(edit, lease) {
|
|
@@ -3072,14 +3108,12 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
|
|
|
3072
3108
|
var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
|
|
3073
3109
|
|
|
3074
3110
|
class LspClient extends LspClientConnection {
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
diagnosticsFreshnessTimeoutMs;
|
|
3079
|
-
constructor(root, server2, options = {}) {
|
|
3080
|
-
super(root, server2, options);
|
|
3111
|
+
constructor(root, server, options = {}) {
|
|
3112
|
+
super(root, server, options);
|
|
3113
|
+
this.diagnosticPullErrors = [];
|
|
3081
3114
|
this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
|
|
3082
3115
|
this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
|
|
3116
|
+
timerProvider: this.timerProvider,
|
|
3083
3117
|
versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
|
|
3084
3118
|
});
|
|
3085
3119
|
this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
|
|
@@ -3132,6 +3166,18 @@ class LspClient extends LspClientConnection {
|
|
|
3132
3166
|
textDocument: { uri: pathToFileURL3(absPath).href }
|
|
3133
3167
|
}, options);
|
|
3134
3168
|
}
|
|
3169
|
+
async formatDocument(filePath, options, signal) {
|
|
3170
|
+
if (!this.isDocumentFormattingSupported())
|
|
3171
|
+
return null;
|
|
3172
|
+
const absPath = this.resolveWorkspacePath(filePath);
|
|
3173
|
+
await this.openFile(absPath);
|
|
3174
|
+
const requestOptions = signal === undefined ? {} : { signal };
|
|
3175
|
+
const edits = await this.sendRequest("textDocument/formatting", {
|
|
3176
|
+
textDocument: { uri: pathToFileURL3(absPath).href },
|
|
3177
|
+
options
|
|
3178
|
+
}, requestOptions);
|
|
3179
|
+
return edits ?? [];
|
|
3180
|
+
}
|
|
3135
3181
|
async workspaceSymbols(query, signal) {
|
|
3136
3182
|
const options = signal === undefined ? {} : { signal };
|
|
3137
3183
|
return this.sendRequest("workspace/symbol", { query }, options);
|
|
@@ -3171,7 +3217,7 @@ class LspClient extends LspClientConnection {
|
|
|
3171
3217
|
const absPath = this.resolveWorkspacePath(filePath);
|
|
3172
3218
|
const uri = pathToFileURL3(absPath).href;
|
|
3173
3219
|
await this.openFile(absPath);
|
|
3174
|
-
const deadlineAt =
|
|
3220
|
+
const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
|
|
3175
3221
|
for (;; ) {
|
|
3176
3222
|
signal?.throwIfAborted();
|
|
3177
3223
|
const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
|
|
@@ -3184,13 +3230,13 @@ class LspClient extends LspClientConnection {
|
|
|
3184
3230
|
if (!pushFallbackOnly) {
|
|
3185
3231
|
const cached = this.documents.getPullCache(snapshot);
|
|
3186
3232
|
try {
|
|
3187
|
-
const
|
|
3188
|
-
if (
|
|
3233
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
3234
|
+
if (remainingMs <= 0)
|
|
3189
3235
|
return this.freshnessTimeout(absPath);
|
|
3190
3236
|
const result = await this.sendRequest("textDocument/diagnostic", {
|
|
3191
3237
|
textDocument: { uri },
|
|
3192
3238
|
...cached?.resultId === undefined ? {} : { previousResultId: cached.resultId }
|
|
3193
|
-
}, { timeoutMs:
|
|
3239
|
+
}, { timeoutMs: remainingMs, ...signal === undefined ? {} : { signal } });
|
|
3194
3240
|
if (!this.documents.isCurrentSnapshot(snapshot))
|
|
3195
3241
|
continue;
|
|
3196
3242
|
const report = this.parseDiagnosticPullReport(result);
|
|
@@ -3219,7 +3265,7 @@ class LspClient extends LspClientConnection {
|
|
|
3219
3265
|
}
|
|
3220
3266
|
if (!pushFallbackOnly)
|
|
3221
3267
|
continue;
|
|
3222
|
-
const remainingMs = deadlineAt -
|
|
3268
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
3223
3269
|
if (remainingMs <= 0) {
|
|
3224
3270
|
if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
|
|
3225
3271
|
const cached = this.documents.getPullCache(snapshot);
|
|
@@ -3271,7 +3317,7 @@ function waitForDiagnosticsActivity(wait, signal) {
|
|
|
3271
3317
|
return wait;
|
|
3272
3318
|
if (signal.aborted)
|
|
3273
3319
|
return Promise.reject(abortError3(signal));
|
|
3274
|
-
return new Promise((
|
|
3320
|
+
return new Promise((resolve, reject) => {
|
|
3275
3321
|
const onAbort = () => {
|
|
3276
3322
|
signal.removeEventListener("abort", onAbort);
|
|
3277
3323
|
reject(abortError3(signal));
|
|
@@ -3279,7 +3325,7 @@ function waitForDiagnosticsActivity(wait, signal) {
|
|
|
3279
3325
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
3280
3326
|
wait.then(() => {
|
|
3281
3327
|
signal.removeEventListener("abort", onAbort);
|
|
3282
|
-
|
|
3328
|
+
resolve();
|
|
3283
3329
|
}, (error) => {
|
|
3284
3330
|
signal.removeEventListener("abort", onAbort);
|
|
3285
3331
|
reject(error);
|
|
@@ -3343,7 +3389,7 @@ async function stopClientBestEffort(client) {
|
|
|
3343
3389
|
function awaitWithSignal2(promise, signal) {
|
|
3344
3390
|
if (!signal)
|
|
3345
3391
|
return promise;
|
|
3346
|
-
return new Promise((
|
|
3392
|
+
return new Promise((resolve, reject) => {
|
|
3347
3393
|
let settled = false;
|
|
3348
3394
|
const onAbort = () => {
|
|
3349
3395
|
if (settled)
|
|
@@ -3361,7 +3407,7 @@ function awaitWithSignal2(promise, signal) {
|
|
|
3361
3407
|
return;
|
|
3362
3408
|
settled = true;
|
|
3363
3409
|
signal.removeEventListener("abort", onAbort);
|
|
3364
|
-
|
|
3410
|
+
resolve(value);
|
|
3365
3411
|
}, (err) => {
|
|
3366
3412
|
if (settled)
|
|
3367
3413
|
return;
|
|
@@ -3373,20 +3419,18 @@ function awaitWithSignal2(promise, signal) {
|
|
|
3373
3419
|
}
|
|
3374
3420
|
|
|
3375
3421
|
class LspManager {
|
|
3376
|
-
clients = new Map;
|
|
3377
|
-
reaperHandle = null;
|
|
3378
|
-
signalDisposer = null;
|
|
3379
|
-
disposed = false;
|
|
3380
|
-
idleTimeoutMs;
|
|
3381
|
-
initTimeoutMs;
|
|
3382
|
-
reaperIntervalMs;
|
|
3383
|
-
clientFactory;
|
|
3384
|
-
now;
|
|
3385
3422
|
constructor(options = {}) {
|
|
3423
|
+
this.clients = new Map;
|
|
3424
|
+
this.pendingStops = new Map;
|
|
3425
|
+
this.respawnBudgets = new Map;
|
|
3426
|
+
this.reaperHandle = null;
|
|
3427
|
+
this.signalDisposer = null;
|
|
3428
|
+
this.disposed = false;
|
|
3386
3429
|
this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
|
|
3387
3430
|
this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
3431
|
+
this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
|
|
3388
3432
|
this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
|
|
3389
|
-
this.clientFactory = options.clientFactory ?? ((root,
|
|
3433
|
+
this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
|
|
3390
3434
|
this.now = options.now ?? (() => Date.now());
|
|
3391
3435
|
this.startReaper();
|
|
3392
3436
|
this.signalDisposer = installProcessSignalCleanup(() => this.stopAll());
|
|
@@ -3404,38 +3448,103 @@ class LspManager {
|
|
|
3404
3448
|
getKey(root, serverId) {
|
|
3405
3449
|
return `${root}::${serverId}`;
|
|
3406
3450
|
}
|
|
3451
|
+
tombstoneStop(key, client) {
|
|
3452
|
+
const stop = stopClientBestEffort(client);
|
|
3453
|
+
this.pendingStops.set(key, stop);
|
|
3454
|
+
stop.finally(() => {
|
|
3455
|
+
if (this.pendingStops.get(key) === stop) {
|
|
3456
|
+
this.pendingStops.delete(key);
|
|
3457
|
+
}
|
|
3458
|
+
});
|
|
3459
|
+
return stop;
|
|
3460
|
+
}
|
|
3461
|
+
recordDeadGeneration(key) {
|
|
3462
|
+
let budget = this.respawnBudgets.get(key);
|
|
3463
|
+
if (budget === undefined) {
|
|
3464
|
+
budget = { deadGenerations: 0, exhaustedAt: null };
|
|
3465
|
+
this.respawnBudgets.set(key, budget);
|
|
3466
|
+
}
|
|
3467
|
+
budget.deadGenerations += 1;
|
|
3468
|
+
}
|
|
3469
|
+
markHealthyGeneration(key) {
|
|
3470
|
+
this.respawnBudgets.delete(key);
|
|
3471
|
+
}
|
|
3472
|
+
ensureRespawnAllowed(key, root, serverId) {
|
|
3473
|
+
const budget = this.respawnBudgets.get(key);
|
|
3474
|
+
if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
|
|
3475
|
+
return;
|
|
3476
|
+
if (budget.exhaustedAt === null) {
|
|
3477
|
+
budget.exhaustedAt = this.now();
|
|
3478
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
3479
|
+
}
|
|
3480
|
+
if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
|
|
3481
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
3482
|
+
}
|
|
3483
|
+
budget.deadGenerations = 0;
|
|
3484
|
+
budget.exhaustedAt = null;
|
|
3485
|
+
}
|
|
3407
3486
|
reapStale() {
|
|
3408
3487
|
const t = this.now();
|
|
3409
3488
|
for (const [key, managed] of this.clients) {
|
|
3410
3489
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3411
|
-
stopClientBestEffort(managed.client);
|
|
3412
3490
|
this.clients.delete(key);
|
|
3491
|
+
this.tombstoneStop(key, managed.client);
|
|
3413
3492
|
continue;
|
|
3414
3493
|
}
|
|
3415
3494
|
if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
|
|
3416
|
-
stopClientBestEffort(managed.client);
|
|
3417
3495
|
this.clients.delete(key);
|
|
3496
|
+
this.tombstoneStop(key, managed.client);
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
}
|
|
3500
|
+
evictForAdmission() {
|
|
3501
|
+
while (this.clients.size >= this.maxResidentClients) {
|
|
3502
|
+
const victim = this.leastRecentlyUsedIdleClient();
|
|
3503
|
+
if (!victim)
|
|
3504
|
+
return;
|
|
3505
|
+
this.clients.delete(victim.key);
|
|
3506
|
+
this.tombstoneStop(victim.key, victim.managed.client);
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
leastRecentlyUsedIdleClient() {
|
|
3510
|
+
let candidate = null;
|
|
3511
|
+
for (const [key, managed] of this.clients) {
|
|
3512
|
+
if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
|
|
3513
|
+
continue;
|
|
3514
|
+
if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
|
|
3515
|
+
candidate = { key, managed };
|
|
3418
3516
|
}
|
|
3419
3517
|
}
|
|
3518
|
+
return candidate;
|
|
3420
3519
|
}
|
|
3421
3520
|
async tryDeleteIfOrphaned(key, managed) {
|
|
3422
3521
|
if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
|
|
3423
3522
|
this.clients.delete(key);
|
|
3424
|
-
await
|
|
3523
|
+
await this.tombstoneStop(key, managed.client);
|
|
3425
3524
|
}
|
|
3426
3525
|
}
|
|
3427
|
-
async getClient(root,
|
|
3526
|
+
async getClient(root, server, signal) {
|
|
3428
3527
|
if (this.disposed) {
|
|
3429
3528
|
throw new Error("LspManager has been disposed");
|
|
3430
3529
|
}
|
|
3431
3530
|
signal?.throwIfAborted();
|
|
3432
|
-
const key = this.getKey(root,
|
|
3531
|
+
const key = this.getKey(root, server.id);
|
|
3532
|
+
for (;; ) {
|
|
3533
|
+
const pendingStop = this.pendingStops.get(key);
|
|
3534
|
+
if (pendingStop === undefined)
|
|
3535
|
+
break;
|
|
3536
|
+
await awaitWithSignal2(pendingStop, signal);
|
|
3537
|
+
signal?.throwIfAborted();
|
|
3538
|
+
}
|
|
3539
|
+
if (this.disposed) {
|
|
3540
|
+
throw new Error("LspManager has been disposed");
|
|
3541
|
+
}
|
|
3433
3542
|
let managed = this.clients.get(key);
|
|
3434
3543
|
if (managed) {
|
|
3435
3544
|
const t = this.now();
|
|
3436
3545
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3437
|
-
await stopClientBestEffort(managed.client);
|
|
3438
3546
|
this.clients.delete(key);
|
|
3547
|
+
await this.tombstoneStop(key, managed.client);
|
|
3439
3548
|
managed = undefined;
|
|
3440
3549
|
}
|
|
3441
3550
|
}
|
|
@@ -3456,15 +3565,21 @@ class LspManager {
|
|
|
3456
3565
|
signal.throwIfAborted();
|
|
3457
3566
|
}
|
|
3458
3567
|
if (!managed.client.isAlive()) {
|
|
3459
|
-
|
|
3460
|
-
this.clients.
|
|
3461
|
-
|
|
3568
|
+
this.recordDeadGeneration(key);
|
|
3569
|
+
if (this.clients.get(key) === managed) {
|
|
3570
|
+
this.clients.delete(key);
|
|
3571
|
+
}
|
|
3572
|
+
await this.tombstoneStop(key, managed.client);
|
|
3573
|
+
return this.getClient(root, server, signal);
|
|
3462
3574
|
}
|
|
3575
|
+
this.markHealthyGeneration(key);
|
|
3463
3576
|
managed.refCount++;
|
|
3464
3577
|
managed.lastUsedAt = this.now();
|
|
3465
3578
|
return managed.client;
|
|
3466
3579
|
}
|
|
3467
|
-
|
|
3580
|
+
this.evictForAdmission();
|
|
3581
|
+
this.ensureRespawnAllowed(key, root, server.id);
|
|
3582
|
+
const client = this.clientFactory(root, server);
|
|
3468
3583
|
const initStartedAt = this.now();
|
|
3469
3584
|
const initPromise = (async () => {
|
|
3470
3585
|
await client.start();
|
|
@@ -3487,7 +3602,7 @@ class LspManager {
|
|
|
3487
3602
|
if (this.clients.get(key) === newManaged) {
|
|
3488
3603
|
this.clients.delete(key);
|
|
3489
3604
|
}
|
|
3490
|
-
await
|
|
3605
|
+
await this.tombstoneStop(key, client);
|
|
3491
3606
|
throw err;
|
|
3492
3607
|
}
|
|
3493
3608
|
newManaged.pendingWaiters--;
|
|
@@ -3498,6 +3613,15 @@ class LspManager {
|
|
|
3498
3613
|
await this.tryDeleteIfOrphaned(key, newManaged);
|
|
3499
3614
|
signal.throwIfAborted();
|
|
3500
3615
|
}
|
|
3616
|
+
if (!client.isAlive()) {
|
|
3617
|
+
this.recordDeadGeneration(key);
|
|
3618
|
+
if (this.clients.get(key) === newManaged) {
|
|
3619
|
+
this.clients.delete(key);
|
|
3620
|
+
}
|
|
3621
|
+
await this.tombstoneStop(key, client);
|
|
3622
|
+
return this.getClient(root, server, signal);
|
|
3623
|
+
}
|
|
3624
|
+
this.markHealthyGeneration(key);
|
|
3501
3625
|
newManaged.refCount++;
|
|
3502
3626
|
newManaged.lastUsedAt = this.now();
|
|
3503
3627
|
return client;
|
|
@@ -3518,15 +3642,21 @@ class LspManager {
|
|
|
3518
3642
|
if (client && managed.client !== client)
|
|
3519
3643
|
return;
|
|
3520
3644
|
this.clients.delete(key);
|
|
3521
|
-
|
|
3645
|
+
this.tombstoneStop(key, managed.client);
|
|
3522
3646
|
}
|
|
3523
|
-
warmupClient(root,
|
|
3647
|
+
warmupClient(root, server) {
|
|
3524
3648
|
if (this.disposed)
|
|
3525
3649
|
return;
|
|
3526
|
-
const key = this.getKey(root,
|
|
3527
|
-
if (this.clients.has(key))
|
|
3650
|
+
const key = this.getKey(root, server.id);
|
|
3651
|
+
if (this.clients.has(key) || this.pendingStops.has(key))
|
|
3528
3652
|
return;
|
|
3529
|
-
|
|
3653
|
+
this.evictForAdmission();
|
|
3654
|
+
try {
|
|
3655
|
+
this.ensureRespawnAllowed(key, root, server.id);
|
|
3656
|
+
} catch {
|
|
3657
|
+
return;
|
|
3658
|
+
}
|
|
3659
|
+
const client = this.clientFactory(root, server);
|
|
3530
3660
|
const initStartedAt = this.now();
|
|
3531
3661
|
const initPromise = (async () => {
|
|
3532
3662
|
await client.start();
|
|
@@ -3551,7 +3681,7 @@ class LspManager {
|
|
|
3551
3681
|
if (this.clients.get(key) === managed) {
|
|
3552
3682
|
this.clients.delete(key);
|
|
3553
3683
|
}
|
|
3554
|
-
|
|
3684
|
+
this.tombstoneStop(key, client);
|
|
3555
3685
|
});
|
|
3556
3686
|
}
|
|
3557
3687
|
isServerInitializing(root, serverId) {
|
|
@@ -3595,8 +3725,11 @@ class LspManager {
|
|
|
3595
3725
|
for (const managed of this.clients.values()) {
|
|
3596
3726
|
stopPromises.push(stopClientBestEffort(managed.client));
|
|
3597
3727
|
}
|
|
3728
|
+
const tombstonedStops = [...this.pendingStops.values()];
|
|
3598
3729
|
this.clients.clear();
|
|
3599
|
-
|
|
3730
|
+
this.respawnBudgets.clear();
|
|
3731
|
+
await Promise.allSettled([...stopPromises, ...tombstonedStops]);
|
|
3732
|
+
this.pendingStops.clear();
|
|
3600
3733
|
}
|
|
3601
3734
|
}
|
|
3602
3735
|
var _defaultInstance = null;
|
|
@@ -3606,49 +3739,43 @@ function getLspManager() {
|
|
|
3606
3739
|
}
|
|
3607
3740
|
return _defaultInstance;
|
|
3608
3741
|
}
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3742
|
+
var GIT_WORKSPACE_MARKER = ".git";
|
|
3743
|
+
var PROJECT_WORKSPACE_MARKERS = [
|
|
3744
|
+
"package.json",
|
|
3745
|
+
"pyproject.toml",
|
|
3746
|
+
"Cargo.toml",
|
|
3747
|
+
"go.mod",
|
|
3748
|
+
"pom.xml",
|
|
3749
|
+
"build.gradle"
|
|
3750
|
+
];
|
|
3751
|
+
var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
|
|
3752
|
+
function findWorkspaceRootOutsideContext(directory) {
|
|
3753
|
+
const marked = nearestMarkedAncestor(directory);
|
|
3754
|
+
if (marked !== undefined)
|
|
3755
|
+
return marked;
|
|
3756
|
+
return realpathSync4(nearestExistingAncestor(directory));
|
|
3757
|
+
}
|
|
3758
|
+
function nearestMarkedAncestor(directory) {
|
|
3759
|
+
let current = directory;
|
|
3760
|
+
for (;; ) {
|
|
3761
|
+
if (existsSync7(current) && WORKSPACE_MARKERS.some((marker) => existsSync7(join3(current, marker)))) {
|
|
3762
|
+
return realpathSync4(current);
|
|
3763
|
+
}
|
|
3764
|
+
const parent = dirname7(current);
|
|
3765
|
+
if (parent === current)
|
|
3766
|
+
return;
|
|
3767
|
+
current = parent;
|
|
3621
3768
|
}
|
|
3622
3769
|
}
|
|
3623
|
-
function
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
}
|
|
3631
|
-
|
|
3632
|
-
return value === "declined" || value === "allowed";
|
|
3633
|
-
}
|
|
3634
|
-
function writeInstallDecisions(decisions) {
|
|
3635
|
-
const path2 = getInstallDecisionsPath();
|
|
3636
|
-
mkdirSync3(dirname7(path2), { recursive: true });
|
|
3637
|
-
const tmpPath = `${path2}.tmp`;
|
|
3638
|
-
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
3639
|
-
`, "utf8");
|
|
3640
|
-
renameSync2(tmpPath, path2);
|
|
3641
|
-
}
|
|
3642
|
-
function isInstallDecisions(value) {
|
|
3643
|
-
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
3644
|
-
}
|
|
3645
|
-
function isInstallDecisionRecord(value) {
|
|
3646
|
-
if (!isRecord5(value))
|
|
3647
|
-
return false;
|
|
3648
|
-
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
3649
|
-
}
|
|
3650
|
-
function isRecord5(value) {
|
|
3651
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3770
|
+
function nearestExistingAncestor(directory) {
|
|
3771
|
+
let current = directory;
|
|
3772
|
+
while (!existsSync7(current)) {
|
|
3773
|
+
const parent = dirname7(current);
|
|
3774
|
+
if (parent === current)
|
|
3775
|
+
return current;
|
|
3776
|
+
current = parent;
|
|
3777
|
+
}
|
|
3778
|
+
return current;
|
|
3652
3779
|
}
|
|
3653
3780
|
var LSP_INSTALL_HINTS = {
|
|
3654
3781
|
typescript: "npm install -g typescript-language-server typescript",
|
|
@@ -3694,6 +3821,26 @@ var LSP_INSTALL_HINTS = {
|
|
|
3694
3821
|
julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
|
|
3695
3822
|
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"
|
|
3696
3823
|
};
|
|
3824
|
+
var LSP_LOCAL_INSTALL_HINTS = {
|
|
3825
|
+
typescript: "bun add -d typescript-language-server typescript",
|
|
3826
|
+
vue: "bun add -d @vue/language-server",
|
|
3827
|
+
eslint: "bun add -d vscode-langservers-extracted",
|
|
3828
|
+
oxlint: "bun add -d oxlint",
|
|
3829
|
+
biome: "bun add -d @biomejs/biome",
|
|
3830
|
+
svelte: "bun add -d svelte-language-server",
|
|
3831
|
+
astro: "bun add -d @astrojs/language-server",
|
|
3832
|
+
bash: "bun add -d bash-language-server",
|
|
3833
|
+
"bash-ls": "bun add -d bash-language-server",
|
|
3834
|
+
"yaml-ls": "bun add -d yaml-language-server",
|
|
3835
|
+
php: "bun add -d intelephense",
|
|
3836
|
+
prisma: "bun add -d prisma",
|
|
3837
|
+
dockerfile: "bun add -d dockerfile-language-server-nodejs",
|
|
3838
|
+
pyright: "uv add --dev pyright",
|
|
3839
|
+
basedpyright: "uv add --dev basedpyright",
|
|
3840
|
+
ruff: "uv add --dev ruff",
|
|
3841
|
+
ty: "uv add --dev ty",
|
|
3842
|
+
"ruby-lsp": "bundle add ruby-lsp --group development"
|
|
3843
|
+
};
|
|
3697
3844
|
var BUILTIN_SERVERS = {
|
|
3698
3845
|
typescript: {
|
|
3699
3846
|
command: ["typescript-language-server", "--stdio"],
|
|
@@ -3795,17 +3942,61 @@ var BUILTIN_SERVERS = {
|
|
|
3795
3942
|
extensions: [".razor", ".cshtml"]
|
|
3796
3943
|
}
|
|
3797
3944
|
};
|
|
3945
|
+
function getInstallDecisionsPath() {
|
|
3946
|
+
return lspRequestContext().installDecisionsPath;
|
|
3947
|
+
}
|
|
3948
|
+
function loadInstallDecisions() {
|
|
3949
|
+
const path = getInstallDecisionsPath();
|
|
3950
|
+
if (!existsSync8(path))
|
|
3951
|
+
return {};
|
|
3952
|
+
try {
|
|
3953
|
+
const parsed = JSON.parse(readFileSync4(path, "utf8"));
|
|
3954
|
+
return isInstallDecisions(parsed) ? parsed : {};
|
|
3955
|
+
} catch {
|
|
3956
|
+
return {};
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
function loadInstallDecision(serverId) {
|
|
3960
|
+
return loadInstallDecisions()[serverId];
|
|
3961
|
+
}
|
|
3962
|
+
function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
|
|
3963
|
+
const decisions = loadInstallDecisions();
|
|
3964
|
+
decisions[serverId] = { decision, decidedAt };
|
|
3965
|
+
writeInstallDecisions(decisions);
|
|
3966
|
+
}
|
|
3967
|
+
function isInstallDecision(value) {
|
|
3968
|
+
return value === "declined" || value === "allowed";
|
|
3969
|
+
}
|
|
3970
|
+
function writeInstallDecisions(decisions) {
|
|
3971
|
+
const path = getInstallDecisionsPath();
|
|
3972
|
+
mkdirSync3(dirname8(path), { recursive: true });
|
|
3973
|
+
const tmpPath = `${path}.tmp`;
|
|
3974
|
+
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
3975
|
+
`, "utf8");
|
|
3976
|
+
renameSync2(tmpPath, path);
|
|
3977
|
+
}
|
|
3978
|
+
function isInstallDecisions(value) {
|
|
3979
|
+
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
3980
|
+
}
|
|
3981
|
+
function isInstallDecisionRecord(value) {
|
|
3982
|
+
if (!isRecord5(value))
|
|
3983
|
+
return false;
|
|
3984
|
+
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
3985
|
+
}
|
|
3986
|
+
function isRecord5(value) {
|
|
3987
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3988
|
+
}
|
|
3798
3989
|
function getProjectConfigPaths() {
|
|
3799
3990
|
return lspRequestContext().projectConfigPaths;
|
|
3800
3991
|
}
|
|
3801
3992
|
function getUserConfigPath() {
|
|
3802
3993
|
return lspRequestContext().userConfigPath;
|
|
3803
3994
|
}
|
|
3804
|
-
function loadJsonFile(
|
|
3805
|
-
if (!
|
|
3995
|
+
function loadJsonFile(path) {
|
|
3996
|
+
if (!existsSync9(path))
|
|
3806
3997
|
return null;
|
|
3807
3998
|
try {
|
|
3808
|
-
const parsed = JSON.parse(readFileSync5(
|
|
3999
|
+
const parsed = JSON.parse(readFileSync5(path, "utf-8"));
|
|
3809
4000
|
return isConfigJson(parsed) ? parsed : null;
|
|
3810
4001
|
} catch {
|
|
3811
4002
|
return null;
|
|
@@ -3822,8 +4013,8 @@ function loadAllConfigs() {
|
|
|
3822
4013
|
return configs;
|
|
3823
4014
|
}
|
|
3824
4015
|
function loadFirstJsonFile(paths) {
|
|
3825
|
-
for (const
|
|
3826
|
-
const config = loadJsonFile(
|
|
4016
|
+
for (const path of paths) {
|
|
4017
|
+
const config = loadJsonFile(path);
|
|
3827
4018
|
if (config)
|
|
3828
4019
|
return config;
|
|
3829
4020
|
}
|
|
@@ -3849,10 +4040,10 @@ function getMergedServers() {
|
|
|
3849
4040
|
}
|
|
3850
4041
|
if (seen.has(id))
|
|
3851
4042
|
continue;
|
|
3852
|
-
const
|
|
3853
|
-
if (!
|
|
4043
|
+
const server = createServerFromEntry(id, entry, source);
|
|
4044
|
+
if (!server)
|
|
3854
4045
|
continue;
|
|
3855
|
-
servers.push(
|
|
4046
|
+
servers.push(server);
|
|
3856
4047
|
seen.add(id);
|
|
3857
4048
|
}
|
|
3858
4049
|
}
|
|
@@ -3884,7 +4075,7 @@ function createServerFromEntry(id, entry, source) {
|
|
|
3884
4075
|
if (source === "project") {
|
|
3885
4076
|
if (!builtin)
|
|
3886
4077
|
return null;
|
|
3887
|
-
const
|
|
4078
|
+
const server = createServer({
|
|
3888
4079
|
id,
|
|
3889
4080
|
command: builtin.command,
|
|
3890
4081
|
extensions: entry.extensions ?? builtin.extensions,
|
|
@@ -3892,35 +4083,35 @@ function createServerFromEntry(id, entry, source) {
|
|
|
3892
4083
|
source
|
|
3893
4084
|
});
|
|
3894
4085
|
if (entry.initialization !== undefined) {
|
|
3895
|
-
|
|
4086
|
+
server.initialization = entry.initialization;
|
|
3896
4087
|
}
|
|
3897
|
-
return
|
|
4088
|
+
return server;
|
|
3898
4089
|
}
|
|
3899
4090
|
if (entry.command && entry.extensions) {
|
|
3900
|
-
const
|
|
4091
|
+
const server = createServer({
|
|
3901
4092
|
id,
|
|
3902
4093
|
command: entry.command,
|
|
3903
4094
|
extensions: entry.extensions,
|
|
3904
4095
|
priority: entry.priority ?? 0,
|
|
3905
4096
|
source
|
|
3906
4097
|
});
|
|
3907
|
-
applyOptionalServerFields(
|
|
3908
|
-
return
|
|
4098
|
+
applyOptionalServerFields(server, entry);
|
|
4099
|
+
return server;
|
|
3909
4100
|
}
|
|
3910
4101
|
if (!builtin)
|
|
3911
4102
|
return null;
|
|
3912
|
-
const
|
|
4103
|
+
const server = createServer({
|
|
3913
4104
|
id,
|
|
3914
4105
|
command: entry.command ?? builtin.command,
|
|
3915
4106
|
extensions: entry.extensions ?? builtin.extensions,
|
|
3916
4107
|
priority: entry.priority ?? 0,
|
|
3917
4108
|
source
|
|
3918
4109
|
});
|
|
3919
|
-
applyOptionalServerFields(
|
|
3920
|
-
return
|
|
4110
|
+
applyOptionalServerFields(server, entry);
|
|
4111
|
+
return server;
|
|
3921
4112
|
}
|
|
3922
4113
|
function createServer(input) {
|
|
3923
|
-
const
|
|
4114
|
+
const server = {
|
|
3924
4115
|
id: input.id,
|
|
3925
4116
|
command: input.command,
|
|
3926
4117
|
extensions: input.extensions,
|
|
@@ -3928,19 +4119,19 @@ function createServer(input) {
|
|
|
3928
4119
|
source: input.source
|
|
3929
4120
|
};
|
|
3930
4121
|
if (input.env !== undefined) {
|
|
3931
|
-
|
|
4122
|
+
server.env = input.env;
|
|
3932
4123
|
}
|
|
3933
4124
|
if (input.initialization !== undefined) {
|
|
3934
|
-
|
|
4125
|
+
server.initialization = input.initialization;
|
|
3935
4126
|
}
|
|
3936
|
-
return
|
|
4127
|
+
return server;
|
|
3937
4128
|
}
|
|
3938
|
-
function applyOptionalServerFields(
|
|
4129
|
+
function applyOptionalServerFields(server, entry) {
|
|
3939
4130
|
if (entry.env !== undefined) {
|
|
3940
|
-
|
|
4131
|
+
server.env = entry.env;
|
|
3941
4132
|
}
|
|
3942
4133
|
if (entry.initialization !== undefined) {
|
|
3943
|
-
|
|
4134
|
+
server.initialization = entry.initialization;
|
|
3944
4135
|
}
|
|
3945
4136
|
}
|
|
3946
4137
|
function isConfigJson(value) {
|
|
@@ -3988,60 +4179,161 @@ function getDisabledServerIds() {
|
|
|
3988
4179
|
}
|
|
3989
4180
|
return disabled;
|
|
3990
4181
|
}
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4182
|
+
var LOCAL_BIN_RULES = [
|
|
4183
|
+
{
|
|
4184
|
+
markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
|
|
4185
|
+
binDirs: [join4("node_modules", ".bin")]
|
|
4186
|
+
},
|
|
4187
|
+
{
|
|
4188
|
+
markers: [
|
|
4189
|
+
"pyproject.toml",
|
|
4190
|
+
"ty.toml",
|
|
4191
|
+
"requirements.txt",
|
|
4192
|
+
"setup.py",
|
|
4193
|
+
"setup.cfg",
|
|
4194
|
+
"Pipfile",
|
|
4195
|
+
"pyrightconfig.json",
|
|
4196
|
+
"ruff.toml",
|
|
4197
|
+
".ruff.toml"
|
|
4198
|
+
],
|
|
4199
|
+
binDirs: [
|
|
4200
|
+
join4(".venv", "bin"),
|
|
4201
|
+
join4(".venv", "Scripts"),
|
|
4202
|
+
join4("venv", "bin"),
|
|
4203
|
+
join4("venv", "Scripts"),
|
|
4204
|
+
join4(".env", "bin"),
|
|
4205
|
+
join4(".env", "Scripts")
|
|
4206
|
+
]
|
|
4207
|
+
},
|
|
4208
|
+
{
|
|
4209
|
+
markers: ["Gemfile", "Gemfile.lock"],
|
|
4210
|
+
binDirs: [join4("vendor", "bundle", "bin"), "bin"]
|
|
4211
|
+
},
|
|
4212
|
+
{
|
|
4213
|
+
markers: ["go.mod", "go.sum", "go.work"],
|
|
4214
|
+
binDirs: ["bin"]
|
|
4215
|
+
}
|
|
4216
|
+
];
|
|
4217
|
+
var resolutionCache = new Map;
|
|
4218
|
+
var probeCount = 0;
|
|
4219
|
+
function probe(path) {
|
|
4220
|
+
probeCount += 1;
|
|
4221
|
+
return existsSync10(path);
|
|
4222
|
+
}
|
|
4223
|
+
function executableSuffixes(platform, pathExt) {
|
|
4224
|
+
if (platform !== "win32")
|
|
4225
|
+
return [""];
|
|
4226
|
+
const configured = pathExt ?? process.env["PATHEXT"] ?? "";
|
|
4227
|
+
const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
|
|
4228
|
+
return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
|
|
4229
|
+
}
|
|
4230
|
+
function probeWithSuffixes(directory, command, suffixes) {
|
|
4231
|
+
for (const suffix of suffixes) {
|
|
4232
|
+
const candidate = join4(directory, command + suffix);
|
|
4233
|
+
if (probe(candidate))
|
|
4234
|
+
return candidate;
|
|
4000
4235
|
}
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4236
|
+
return null;
|
|
4237
|
+
}
|
|
4238
|
+
function resolveLocal(command, workingDirectory, suffixes, stopAt) {
|
|
4239
|
+
const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
|
|
4240
|
+
let current = resolve7(workingDirectory);
|
|
4241
|
+
while (true) {
|
|
4242
|
+
for (const rule of LOCAL_BIN_RULES) {
|
|
4243
|
+
if (!rule.markers.some((marker) => probe(join4(current, marker))))
|
|
4244
|
+
continue;
|
|
4245
|
+
for (const binDir of rule.binDirs) {
|
|
4246
|
+
const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
|
|
4247
|
+
if (found !== null)
|
|
4248
|
+
return found;
|
|
4249
|
+
}
|
|
4010
4250
|
}
|
|
4251
|
+
if (probe(join4(current, ".git")))
|
|
4252
|
+
return null;
|
|
4253
|
+
if (boundary !== undefined && current === boundary)
|
|
4254
|
+
return null;
|
|
4255
|
+
const parent = dirname9(current);
|
|
4256
|
+
if (parent === current)
|
|
4257
|
+
return null;
|
|
4258
|
+
current = parent;
|
|
4011
4259
|
}
|
|
4012
|
-
|
|
4013
|
-
|
|
4260
|
+
}
|
|
4261
|
+
function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
|
|
4262
|
+
let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
|
|
4263
|
+
if (platform === "win32" && !pathEnv) {
|
|
4014
4264
|
pathEnv = process.env["Path"] ?? "";
|
|
4015
4265
|
}
|
|
4016
|
-
const
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
}
|
|
4266
|
+
for (const entry of pathEnv.split(delimiter3)) {
|
|
4267
|
+
if (entry.length === 0)
|
|
4268
|
+
continue;
|
|
4269
|
+
const found = probeWithSuffixes(entry, command, suffixes);
|
|
4270
|
+
if (found !== null)
|
|
4271
|
+
return found;
|
|
4023
4272
|
}
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4273
|
+
return null;
|
|
4274
|
+
}
|
|
4275
|
+
function resolveServerBinary(command, workingDirectory, options = {}) {
|
|
4276
|
+
if (command.length === 0)
|
|
4277
|
+
return null;
|
|
4278
|
+
const [cmd] = command;
|
|
4279
|
+
if (cmd === undefined || cmd.length === 0)
|
|
4280
|
+
return null;
|
|
4281
|
+
const platform = options.platform ?? process.platform;
|
|
4282
|
+
const suffixes = executableSuffixes(platform, options.pathExt);
|
|
4283
|
+
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
4284
|
+
const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
|
|
4285
|
+
return probe(explicit) ? explicit : null;
|
|
4286
|
+
}
|
|
4287
|
+
const cacheKey = JSON.stringify([
|
|
4288
|
+
workingDirectory ?? "",
|
|
4289
|
+
cmd,
|
|
4290
|
+
platform,
|
|
4291
|
+
options.stopAt ?? "",
|
|
4292
|
+
options.pathExt ?? "",
|
|
4293
|
+
options.pathEnv ?? process.env["PATH"] ?? ""
|
|
4294
|
+
]);
|
|
4295
|
+
const cached = resolutionCache.get(cacheKey);
|
|
4296
|
+
if (cached !== undefined)
|
|
4297
|
+
return cached;
|
|
4298
|
+
let resolved = null;
|
|
4299
|
+
if (workingDirectory !== undefined && workingDirectory.length > 0) {
|
|
4300
|
+
resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
|
|
4301
|
+
}
|
|
4302
|
+
resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
|
|
4303
|
+
if (resolved === null && cmd === "node")
|
|
4304
|
+
resolved = cmd;
|
|
4305
|
+
resolutionCache.set(cacheKey, resolved);
|
|
4306
|
+
return resolved;
|
|
4307
|
+
}
|
|
4308
|
+
function isServerInstalled(command, workingDirectory, options = {}) {
|
|
4309
|
+
if (command.length === 0)
|
|
4310
|
+
return false;
|
|
4311
|
+
return resolveServerBinary(command, workingDirectory, options) !== null;
|
|
4312
|
+
}
|
|
4313
|
+
function withResolvedCommand(command, binaryPath) {
|
|
4314
|
+
return [binaryPath, ...command.slice(1)];
|
|
4027
4315
|
}
|
|
4028
4316
|
function findServerForExtension(ext) {
|
|
4029
4317
|
const servers = getMergedServers();
|
|
4030
|
-
|
|
4031
|
-
|
|
4318
|
+
const workingDirectory = contextCwd();
|
|
4319
|
+
for (const server of servers) {
|
|
4320
|
+
if (!server.extensions.includes(ext))
|
|
4321
|
+
continue;
|
|
4322
|
+
const binaryPath = resolveServerBinary(server.command, workingDirectory);
|
|
4323
|
+
if (binaryPath !== null) {
|
|
4032
4324
|
const resolvedServer = {
|
|
4033
|
-
id:
|
|
4034
|
-
command:
|
|
4035
|
-
extensions:
|
|
4036
|
-
priority:
|
|
4325
|
+
id: server.id,
|
|
4326
|
+
command: withResolvedCommand(server.command, binaryPath),
|
|
4327
|
+
extensions: server.extensions,
|
|
4328
|
+
priority: server.priority
|
|
4037
4329
|
};
|
|
4038
|
-
if (
|
|
4330
|
+
if (server.env !== undefined) {
|
|
4039
4331
|
return {
|
|
4040
4332
|
status: "found",
|
|
4041
4333
|
server: {
|
|
4042
4334
|
...resolvedServer,
|
|
4043
|
-
env:
|
|
4044
|
-
...
|
|
4335
|
+
env: server.env,
|
|
4336
|
+
...server.initialization === undefined ? {} : { initialization: server.initialization }
|
|
4045
4337
|
}
|
|
4046
4338
|
};
|
|
4047
4339
|
}
|
|
@@ -4049,20 +4341,20 @@ function findServerForExtension(ext) {
|
|
|
4049
4341
|
status: "found",
|
|
4050
4342
|
server: {
|
|
4051
4343
|
...resolvedServer,
|
|
4052
|
-
...
|
|
4344
|
+
...server.initialization === undefined ? {} : { initialization: server.initialization }
|
|
4053
4345
|
}
|
|
4054
4346
|
};
|
|
4055
4347
|
}
|
|
4056
4348
|
}
|
|
4057
|
-
for (const
|
|
4058
|
-
if (
|
|
4059
|
-
const installHint = LSP_INSTALL_HINTS[
|
|
4349
|
+
for (const server of servers) {
|
|
4350
|
+
if (server.extensions.includes(ext)) {
|
|
4351
|
+
const installHint = LSP_INSTALL_HINTS[server.id] ?? `Install '${server.command[0]}' and ensure it's in your PATH`;
|
|
4060
4352
|
return {
|
|
4061
4353
|
status: "not_installed",
|
|
4062
4354
|
server: {
|
|
4063
|
-
id:
|
|
4064
|
-
command:
|
|
4065
|
-
extensions:
|
|
4355
|
+
id: server.id,
|
|
4356
|
+
command: server.command,
|
|
4357
|
+
extensions: server.extensions
|
|
4066
4358
|
},
|
|
4067
4359
|
installHint
|
|
4068
4360
|
};
|
|
@@ -4078,20 +4370,21 @@ function findServerForExtension(ext) {
|
|
|
4078
4370
|
function getAllServers() {
|
|
4079
4371
|
const servers = getMergedServers();
|
|
4080
4372
|
const disabled = getDisabledServerIds();
|
|
4373
|
+
const workingDirectory = contextCwd();
|
|
4081
4374
|
const result = [];
|
|
4082
4375
|
const seen = new Set;
|
|
4083
|
-
for (const
|
|
4084
|
-
if (seen.has(
|
|
4376
|
+
for (const server of servers) {
|
|
4377
|
+
if (seen.has(server.id))
|
|
4085
4378
|
continue;
|
|
4086
4379
|
result.push({
|
|
4087
|
-
id:
|
|
4088
|
-
installed: isServerInstalled(
|
|
4089
|
-
extensions:
|
|
4380
|
+
id: server.id,
|
|
4381
|
+
installed: isServerInstalled(server.command, workingDirectory),
|
|
4382
|
+
extensions: server.extensions,
|
|
4090
4383
|
disabled: false,
|
|
4091
|
-
source:
|
|
4092
|
-
priority:
|
|
4384
|
+
source: server.source,
|
|
4385
|
+
priority: server.priority
|
|
4093
4386
|
});
|
|
4094
|
-
seen.add(
|
|
4387
|
+
seen.add(server.id);
|
|
4095
4388
|
}
|
|
4096
4389
|
for (const id of disabled) {
|
|
4097
4390
|
if (seen.has(id))
|
|
@@ -4099,7 +4392,7 @@ function getAllServers() {
|
|
|
4099
4392
|
const builtin = BUILTIN_SERVERS[id];
|
|
4100
4393
|
result.push({
|
|
4101
4394
|
id,
|
|
4102
|
-
installed: builtin ? isServerInstalled(builtin.command) : false,
|
|
4395
|
+
installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
|
|
4103
4396
|
extensions: builtin?.extensions ?? [],
|
|
4104
4397
|
disabled: true,
|
|
4105
4398
|
source: "disabled",
|
|
@@ -4108,7 +4401,6 @@ function getAllServers() {
|
|
|
4108
4401
|
}
|
|
4109
4402
|
return result;
|
|
4110
4403
|
}
|
|
4111
|
-
var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
4112
4404
|
function isDirectoryPath(filePath) {
|
|
4113
4405
|
try {
|
|
4114
4406
|
return statSync4(filePath).isDirectory();
|
|
@@ -4121,36 +4413,40 @@ function findWorkspaceRoot(filePath) {
|
|
|
4121
4413
|
const abs = resolveReadablePathInsideContext(filePath);
|
|
4122
4414
|
let dir = abs;
|
|
4123
4415
|
if (!isDirectoryPath(dir)) {
|
|
4124
|
-
dir =
|
|
4416
|
+
dir = dirname10(dir);
|
|
4125
4417
|
}
|
|
4418
|
+
if (!isPathInside(cwd, abs))
|
|
4419
|
+
return findWorkspaceRootOutsideContext(dir);
|
|
4126
4420
|
const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
|
|
4421
|
+
let nearestPackageRoot;
|
|
4127
4422
|
while (isPathInside(cwd, dir)) {
|
|
4128
4423
|
const canonicalDir = existingDirectoryInsideContext(dir, cwd);
|
|
4129
4424
|
if (canonicalDir !== undefined) {
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4425
|
+
if (existsSync11(join5(dir, GIT_WORKSPACE_MARKER))) {
|
|
4426
|
+
return canonicalDir;
|
|
4427
|
+
}
|
|
4428
|
+
if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
|
|
4429
|
+
nearestPackageRoot = canonicalDir;
|
|
4134
4430
|
}
|
|
4135
4431
|
}
|
|
4136
4432
|
if (dir === cwd)
|
|
4137
4433
|
break;
|
|
4138
|
-
dir =
|
|
4434
|
+
dir = dirname10(dir);
|
|
4139
4435
|
}
|
|
4140
|
-
return fallbackRoot;
|
|
4436
|
+
return nearestPackageRoot ?? fallbackRoot;
|
|
4437
|
+
}
|
|
4438
|
+
function hasProjectWorkspaceMarker(directory) {
|
|
4439
|
+
return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync11(join5(directory, marker)));
|
|
4141
4440
|
}
|
|
4142
4441
|
function resolveReadablePathInsideContext(filePath) {
|
|
4143
4442
|
const cwd = contextCwd();
|
|
4144
|
-
const abs =
|
|
4443
|
+
const abs = resolve8(cwd, filePath);
|
|
4145
4444
|
if (isPathInside(cwd, abs))
|
|
4146
4445
|
return abs;
|
|
4147
4446
|
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
4148
4447
|
if (rebased !== undefined)
|
|
4149
4448
|
return rebased;
|
|
4150
|
-
|
|
4151
|
-
if (isPathInside(cwd, canonical))
|
|
4152
|
-
return canonical;
|
|
4153
|
-
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4449
|
+
return canonicalizeExistingOrNearestAncestor(abs);
|
|
4154
4450
|
}
|
|
4155
4451
|
function resolvePathInsideContext(filePath) {
|
|
4156
4452
|
const cwd = contextCwd();
|
|
@@ -4161,16 +4457,16 @@ function resolvePathInsideContext(filePath) {
|
|
|
4161
4457
|
}
|
|
4162
4458
|
return canonical;
|
|
4163
4459
|
}
|
|
4164
|
-
function rebaseThroughCanonicalAncestor(
|
|
4165
|
-
let current =
|
|
4460
|
+
function rebaseThroughCanonicalAncestor(path, cwd) {
|
|
4461
|
+
let current = path;
|
|
4166
4462
|
const suffix = [];
|
|
4167
4463
|
while (true) {
|
|
4168
|
-
if (
|
|
4169
|
-
const canonical =
|
|
4464
|
+
if (existsSync11(current)) {
|
|
4465
|
+
const canonical = realpathSync5(current);
|
|
4170
4466
|
if (isPathInside(cwd, canonical))
|
|
4171
|
-
return suffix.length === 0 ? canonical :
|
|
4467
|
+
return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
|
|
4172
4468
|
}
|
|
4173
|
-
const parent =
|
|
4469
|
+
const parent = dirname10(current);
|
|
4174
4470
|
if (parent === current)
|
|
4175
4471
|
return;
|
|
4176
4472
|
suffix.unshift(basename3(current));
|
|
@@ -4178,9 +4474,9 @@ function rebaseThroughCanonicalAncestor(path2, cwd) {
|
|
|
4178
4474
|
}
|
|
4179
4475
|
}
|
|
4180
4476
|
function existingDirectoryInsideContext(directory, cwd) {
|
|
4181
|
-
if (!
|
|
4477
|
+
if (!existsSync11(directory))
|
|
4182
4478
|
return;
|
|
4183
|
-
const canonical =
|
|
4479
|
+
const canonical = realpathSync5(directory);
|
|
4184
4480
|
if (!statSync4(canonical).isDirectory())
|
|
4185
4481
|
return;
|
|
4186
4482
|
return isPathInside(cwd, canonical) ? canonical : undefined;
|
|
@@ -4193,7 +4489,7 @@ function nearestExistingDirectoryInsideContext(directory, cwd) {
|
|
|
4193
4489
|
return canonical;
|
|
4194
4490
|
if (current === cwd)
|
|
4195
4491
|
return;
|
|
4196
|
-
current =
|
|
4492
|
+
current = dirname10(current);
|
|
4197
4493
|
}
|
|
4198
4494
|
return;
|
|
4199
4495
|
}
|
|
@@ -4220,33 +4516,46 @@ function formatServerLookupError(result) {
|
|
|
4220
4516
|
].join(`
|
|
4221
4517
|
`);
|
|
4222
4518
|
}
|
|
4519
|
+
function formatInstallOptions(serverId, installHint) {
|
|
4520
|
+
const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
|
|
4521
|
+
if (localHint === undefined) {
|
|
4522
|
+
return ["To install, run:", ` ${installHint}`];
|
|
4523
|
+
}
|
|
4524
|
+
return [
|
|
4525
|
+
"To install in THIS repository (preferred — no global install needed):",
|
|
4526
|
+
` ${localHint}`,
|
|
4527
|
+
"",
|
|
4528
|
+
"Or install it globally:",
|
|
4529
|
+
` ${installHint}`
|
|
4530
|
+
];
|
|
4531
|
+
}
|
|
4223
4532
|
function formatNotInstalled(result) {
|
|
4224
|
-
const { server
|
|
4225
|
-
const extensions =
|
|
4226
|
-
const decision = loadInstallDecision(
|
|
4533
|
+
const { server, installHint } = result;
|
|
4534
|
+
const extensions = server.extensions.join(", ");
|
|
4535
|
+
const decision = loadInstallDecision(server.id)?.decision;
|
|
4227
4536
|
const context = lspRequestContext();
|
|
4228
4537
|
if (decision === "declined") {
|
|
4229
|
-
return `LSP server '${
|
|
4538
|
+
return `LSP server '${server.id}' (${extensions}) is NOT INSTALLED; user previously declined installation — proceed without LSP.`;
|
|
4230
4539
|
}
|
|
4231
4540
|
const header = [
|
|
4232
|
-
`LSP server '${
|
|
4541
|
+
`LSP server '${server.id}' for ${extensions} is NOT INSTALLED.`,
|
|
4233
4542
|
"",
|
|
4234
|
-
`Command not found: ${
|
|
4543
|
+
`Command not found: ${server.command[0]}`,
|
|
4235
4544
|
""
|
|
4236
4545
|
];
|
|
4546
|
+
const installOptions = formatInstallOptions(server.id, installHint);
|
|
4237
4547
|
if (decision === "allowed") {
|
|
4238
4548
|
return [
|
|
4239
4549
|
...header,
|
|
4240
4550
|
"The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
|
|
4241
|
-
|
|
4551
|
+
...installOptions.slice(1)
|
|
4242
4552
|
].join(`
|
|
4243
4553
|
`);
|
|
4244
4554
|
}
|
|
4245
4555
|
if (!context.capabilities.installDecisionTool) {
|
|
4246
4556
|
return [
|
|
4247
4557
|
...header,
|
|
4248
|
-
|
|
4249
|
-
` ${installHint}`,
|
|
4558
|
+
...installOptions,
|
|
4250
4559
|
"",
|
|
4251
4560
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4252
4561
|
"Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
|
|
@@ -4255,13 +4564,12 @@ function formatNotInstalled(result) {
|
|
|
4255
4564
|
}
|
|
4256
4565
|
return [
|
|
4257
4566
|
...header,
|
|
4258
|
-
|
|
4259
|
-
` ${installHint}`,
|
|
4567
|
+
...installOptions,
|
|
4260
4568
|
"",
|
|
4261
4569
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4262
4570
|
"- If the user agrees: run the install command above, then retry this tool.",
|
|
4263
4571
|
"- If the user declines, OR has NOT explicitly asked for LSP installation:",
|
|
4264
|
-
` call lsp_install_decision { server_id: "${
|
|
4572
|
+
` call lsp_install_decision { server_id: "${server.id}", decision: "declined" },`,
|
|
4265
4573
|
` which writes to ${context.installDecisionsPath},`,
|
|
4266
4574
|
" then ignore this message and proceed WITHOUT LSP."
|
|
4267
4575
|
].join(`
|
|
@@ -4285,26 +4593,26 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4285
4593
|
if (result.status !== "found") {
|
|
4286
4594
|
throw new LspServerLookupError(formatServerLookupError(result), result);
|
|
4287
4595
|
}
|
|
4288
|
-
const
|
|
4596
|
+
const server = result.server;
|
|
4289
4597
|
const root = findWorkspaceRoot(absPath);
|
|
4290
4598
|
const manager = options.manager ?? getLspManager();
|
|
4291
4599
|
const acquireAndCall = async (allowRetry) => {
|
|
4292
|
-
const client = await manager.getClient(root,
|
|
4600
|
+
const client = await manager.getClient(root, server, options.signal);
|
|
4293
4601
|
try {
|
|
4294
4602
|
return await fn(client, root, absPath);
|
|
4295
4603
|
} catch (err) {
|
|
4296
4604
|
if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
|
|
4297
|
-
manager.invalidateClient(root,
|
|
4605
|
+
manager.invalidateClient(root, server.id, client);
|
|
4298
4606
|
return acquireAndCall(false);
|
|
4299
4607
|
}
|
|
4300
4608
|
if (err instanceof LspRequestTimeoutError) {
|
|
4301
|
-
if (manager.isServerInitializing(root,
|
|
4609
|
+
if (manager.isServerInitializing(root, server.id)) {
|
|
4302
4610
|
throw new LspServerInitializingError(err);
|
|
4303
4611
|
}
|
|
4304
4612
|
}
|
|
4305
4613
|
throw err;
|
|
4306
4614
|
} finally {
|
|
4307
|
-
manager.releaseClient(root,
|
|
4615
|
+
manager.releaseClient(root, server.id);
|
|
4308
4616
|
}
|
|
4309
4617
|
};
|
|
4310
4618
|
return acquireAndCall(true);
|
|
@@ -4320,10 +4628,10 @@ function uriToPath(uri) {
|
|
|
4320
4628
|
}
|
|
4321
4629
|
function formatLocation(loc) {
|
|
4322
4630
|
if ("targetUri" in loc) {
|
|
4323
|
-
const
|
|
4324
|
-
const
|
|
4325
|
-
const
|
|
4326
|
-
return `${
|
|
4631
|
+
const uri = uriToPath(loc.targetUri);
|
|
4632
|
+
const line = loc.targetRange.start.line + 1;
|
|
4633
|
+
const char = loc.targetRange.start.character;
|
|
4634
|
+
return `${uri}:${line}:${char}`;
|
|
4327
4635
|
}
|
|
4328
4636
|
const uri = uriToPath(loc.uri);
|
|
4329
4637
|
const line = loc.range.start.line + 1;
|
|
@@ -4433,7 +4741,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
|
|
|
4433
4741
|
for (const entry of entries) {
|
|
4434
4742
|
if (files.length >= maxFiles)
|
|
4435
4743
|
return;
|
|
4436
|
-
const fullPath =
|
|
4744
|
+
const fullPath = join6(currentDir, entry);
|
|
4437
4745
|
let stat;
|
|
4438
4746
|
try {
|
|
4439
4747
|
stat = lstatSync5(fullPath);
|
|
@@ -4458,15 +4766,15 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4458
4766
|
if (!extension.startsWith(".")) {
|
|
4459
4767
|
throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
|
|
4460
4768
|
}
|
|
4461
|
-
const absDir =
|
|
4462
|
-
if (!
|
|
4769
|
+
const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
|
|
4770
|
+
if (!existsSync12(absDir)) {
|
|
4463
4771
|
throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
|
|
4464
4772
|
}
|
|
4465
4773
|
const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
|
|
4466
4774
|
if (serverResult.status !== "found") {
|
|
4467
4775
|
throw new LspServerLookupError(formatServerLookupError(serverResult));
|
|
4468
4776
|
}
|
|
4469
|
-
const
|
|
4777
|
+
const server = serverResult.server;
|
|
4470
4778
|
const allFiles = (options.listFiles ?? collectFilesWithExtension)(absDir, extension, maxFiles + 1);
|
|
4471
4779
|
const wasCapped = allFiles.length > maxFiles;
|
|
4472
4780
|
const filesToProcess = allFiles.slice(0, maxFiles);
|
|
@@ -4486,7 +4794,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4486
4794
|
const fileErrors = [];
|
|
4487
4795
|
const maxConcurrency = Math.max(1, options.maxConcurrency ?? DIRECTORY_DIAGNOSTICS_MAX_CONCURRENCY);
|
|
4488
4796
|
options.signal?.throwIfAborted();
|
|
4489
|
-
const client = await manager.getClient(root,
|
|
4797
|
+
const client = await manager.getClient(root, server, options.signal);
|
|
4490
4798
|
try {
|
|
4491
4799
|
let nextIndex = 0;
|
|
4492
4800
|
const workers = Array.from({ length: Math.min(maxConcurrency, filesToProcess.length) }, async () => {
|
|
@@ -4514,7 +4822,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4514
4822
|
});
|
|
4515
4823
|
await Promise.all(workers);
|
|
4516
4824
|
} finally {
|
|
4517
|
-
manager.releaseClient(root,
|
|
4825
|
+
manager.releaseClient(root, server.id);
|
|
4518
4826
|
}
|
|
4519
4827
|
const displayDiagnostics = allDiagnostics.slice(0, DEFAULT_MAX_DIAGNOSTICS);
|
|
4520
4828
|
const wasDiagCapped = allDiagnostics.length > DEFAULT_MAX_DIAGNOSTICS;
|
|
@@ -4560,7 +4868,7 @@ function inferExtensionFromDirectory(directory) {
|
|
|
4560
4868
|
for (const entry of entries) {
|
|
4561
4869
|
if (scanned >= MAX_SCAN_ENTRIES)
|
|
4562
4870
|
return;
|
|
4563
|
-
const fullPath =
|
|
4871
|
+
const fullPath = join7(dir, entry);
|
|
4564
4872
|
let stat;
|
|
4565
4873
|
try {
|
|
4566
4874
|
stat = lstatSync6(fullPath);
|
|
@@ -4709,8 +5017,8 @@ function severityFilter(params) {
|
|
|
4709
5017
|
function clientOptions(signal) {
|
|
4710
5018
|
return signal === undefined ? {} : { signal };
|
|
4711
5019
|
}
|
|
4712
|
-
function text(
|
|
4713
|
-
return { content: [{ type: "text", text
|
|
5020
|
+
function text(text, details, isError = false) {
|
|
5021
|
+
return { content: [{ type: "text", text }], details, isError };
|
|
4714
5022
|
}
|
|
4715
5023
|
function asDiagnosticArray(result) {
|
|
4716
5024
|
if (!result)
|
|
@@ -4728,7 +5036,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4728
5036
|
const extension = inferExtensionFromDirectory(absPath);
|
|
4729
5037
|
if (!extension) {
|
|
4730
5038
|
const message = `No supported source files found in directory: ${absPath}`;
|
|
4731
|
-
const
|
|
5039
|
+
const details = {
|
|
4732
5040
|
filePath,
|
|
4733
5041
|
severity,
|
|
4734
5042
|
mode: "directory",
|
|
@@ -4738,24 +5046,24 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4738
5046
|
error: message,
|
|
4739
5047
|
errorKind: "no_files"
|
|
4740
5048
|
};
|
|
4741
|
-
return text(message,
|
|
5049
|
+
return text(message, details);
|
|
4742
5050
|
}
|
|
4743
|
-
const
|
|
4744
|
-
const
|
|
5051
|
+
const output = await aggregateDiagnosticsForDirectory(absPath, extension, severity, undefined, signal === undefined ? {} : { signal });
|
|
5052
|
+
const details = {
|
|
4745
5053
|
filePath,
|
|
4746
5054
|
severity,
|
|
4747
5055
|
mode: "directory",
|
|
4748
5056
|
diagnostics: [],
|
|
4749
|
-
totalDiagnostics:
|
|
5057
|
+
totalDiagnostics: output.totalDiagnostics,
|
|
4750
5058
|
truncated: false,
|
|
4751
|
-
fileFailures: [...
|
|
5059
|
+
fileFailures: [...output.fileFailures]
|
|
4752
5060
|
};
|
|
4753
|
-
return text(
|
|
5061
|
+
return text(output.output, details);
|
|
4754
5062
|
}
|
|
4755
5063
|
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
|
|
4756
5064
|
if (result.transientError) {
|
|
4757
5065
|
const message = result.transientError.message;
|
|
4758
|
-
const
|
|
5066
|
+
const details = {
|
|
4759
5067
|
filePath,
|
|
4760
5068
|
severity,
|
|
4761
5069
|
mode: "file",
|
|
@@ -4765,7 +5073,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4765
5073
|
error: message,
|
|
4766
5074
|
errorKind: result.transientError.kind
|
|
4767
5075
|
};
|
|
4768
|
-
return text(message,
|
|
5076
|
+
return text(message, details, true);
|
|
4769
5077
|
}
|
|
4770
5078
|
const diagnostics = filterDiagnosticsBySeverity(asDiagnosticArray(result), severity);
|
|
4771
5079
|
const total = diagnostics.length;
|
|
@@ -4799,13 +5107,98 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4799
5107
|
throw error;
|
|
4800
5108
|
}
|
|
4801
5109
|
}
|
|
5110
|
+
var DEFAULT_FORMATTING_OPTIONS = {
|
|
5111
|
+
tabSize: 4,
|
|
5112
|
+
insertSpaces: false,
|
|
5113
|
+
trimTrailingWhitespace: true,
|
|
5114
|
+
insertFinalNewline: true,
|
|
5115
|
+
trimFinalNewlines: true
|
|
5116
|
+
};
|
|
5117
|
+
var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
|
|
5118
|
+
async function formatDocumentWithClient(client, filePath, options = {}) {
|
|
5119
|
+
const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
|
|
5120
|
+
if (edits === null)
|
|
5121
|
+
return { status: "unavailable", reason: "capability_not_advertised" };
|
|
5122
|
+
if (edits.length === 0)
|
|
5123
|
+
return UNCHANGED;
|
|
5124
|
+
const before = readFileSync6(filePath, "utf-8");
|
|
5125
|
+
const normalized = normalizeTextEdits(before, edits, 0);
|
|
5126
|
+
if (normalized.text === before)
|
|
5127
|
+
return UNCHANGED;
|
|
5128
|
+
writeAtomically(filePath, normalized.text);
|
|
5129
|
+
await client.openFile(filePath);
|
|
5130
|
+
return {
|
|
5131
|
+
status: "formatted",
|
|
5132
|
+
...lineDelta(normalized.edits)
|
|
5133
|
+
};
|
|
5134
|
+
}
|
|
5135
|
+
function lineDelta(edits) {
|
|
5136
|
+
let linesAdded = 0;
|
|
5137
|
+
let linesRemoved = 0;
|
|
5138
|
+
for (const edit of edits) {
|
|
5139
|
+
linesRemoved += edit.range.end.line - edit.range.start.line + 1;
|
|
5140
|
+
linesAdded += edit.newText.split(`
|
|
5141
|
+
`).length;
|
|
5142
|
+
}
|
|
5143
|
+
return { linesAdded, linesRemoved };
|
|
5144
|
+
}
|
|
5145
|
+
function writeAtomically(filePath, content) {
|
|
5146
|
+
const tempPath = `${filePath}.omo-format.tmp`;
|
|
5147
|
+
writeFileSync3(tempPath, content, "utf-8");
|
|
5148
|
+
try {
|
|
5149
|
+
renameSync3(tempPath, filePath);
|
|
5150
|
+
} catch (error) {
|
|
5151
|
+
try {
|
|
5152
|
+
unlinkSync2(tempPath);
|
|
5153
|
+
} catch {}
|
|
5154
|
+
throw error;
|
|
5155
|
+
}
|
|
5156
|
+
}
|
|
5157
|
+
async function executeLspFormat(params, signal) {
|
|
5158
|
+
const filePath = requireString(params, "filePath");
|
|
5159
|
+
try {
|
|
5160
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
|
|
5161
|
+
return text(describeResult(filePath, result), formatDetails(filePath, result));
|
|
5162
|
+
} catch (error) {
|
|
5163
|
+
const missingDependency = missingDependencyResult(error, {
|
|
5164
|
+
filePath,
|
|
5165
|
+
status: "unavailable",
|
|
5166
|
+
reason: "server_unavailable",
|
|
5167
|
+
linesAdded: 0,
|
|
5168
|
+
linesRemoved: 0
|
|
5169
|
+
});
|
|
5170
|
+
if (missingDependency)
|
|
5171
|
+
return missingDependency;
|
|
5172
|
+
throw error;
|
|
5173
|
+
}
|
|
5174
|
+
}
|
|
5175
|
+
function formatDetails(filePath, result) {
|
|
5176
|
+
if (result.status === "unavailable") {
|
|
5177
|
+
return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
|
|
5178
|
+
}
|
|
5179
|
+
return {
|
|
5180
|
+
filePath,
|
|
5181
|
+
status: result.status,
|
|
5182
|
+
linesAdded: result.linesAdded,
|
|
5183
|
+
linesRemoved: result.linesRemoved
|
|
5184
|
+
};
|
|
5185
|
+
}
|
|
5186
|
+
function describeResult(filePath, result) {
|
|
5187
|
+
if (result.status === "unavailable") {
|
|
5188
|
+
return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
|
|
5189
|
+
}
|
|
5190
|
+
if (result.status === "unchanged") {
|
|
5191
|
+
return `Already formatted: ${filePath}`;
|
|
5192
|
+
}
|
|
5193
|
+
return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
|
|
5194
|
+
}
|
|
4802
5195
|
async function executeLspInstallDecision(params) {
|
|
4803
5196
|
const serverId = requireString(params, "server_id");
|
|
4804
5197
|
const decision = params["decision"];
|
|
4805
5198
|
if (!isInstallDecision(decision)) {
|
|
4806
5199
|
return text(`Invalid decision '${String(decision)}'. Expected "declined" or "allowed".`, { serverId, errorKind: "invalid_decision" }, true);
|
|
4807
5200
|
}
|
|
4808
|
-
const serverIds = [...new Set(getMergedServers().map((
|
|
5201
|
+
const serverIds = [...new Set(getMergedServers().map((server) => server.id))];
|
|
4809
5202
|
if (!serverIds.includes(serverId)) {
|
|
4810
5203
|
const preview = serverIds.slice(0, 20).join(", ");
|
|
4811
5204
|
return text(`Unknown LSP server '${serverId}'. Known servers: ${preview}${serverIds.length > 20 ? "..." : ""}`, { serverId, errorKind: "unknown_server" }, true);
|
|
@@ -4937,10 +5330,10 @@ function objectSchema(properties, required = []) {
|
|
|
4937
5330
|
async function executeLspStatus() {
|
|
4938
5331
|
const servers = getAllServers();
|
|
4939
5332
|
const snapshots = getLspManager().getSnapshot();
|
|
4940
|
-
const installed = servers.filter((
|
|
4941
|
-
const configuredLines = servers.map((
|
|
4942
|
-
const state =
|
|
4943
|
-
return `- ${
|
|
5333
|
+
const installed = servers.filter((server) => server.installed && !server.disabled);
|
|
5334
|
+
const configuredLines = servers.map((server) => {
|
|
5335
|
+
const state = server.disabled ? "disabled" : server.installed ? "installed" : "missing";
|
|
5336
|
+
return `- ${server.id}: ${state}; source=${server.source}; extensions=${server.extensions.join(", ")}`;
|
|
4944
5337
|
});
|
|
4945
5338
|
const activeLines = snapshots.map((snapshot) => {
|
|
4946
5339
|
const state = snapshot.alive ? snapshot.isInitializing ? "initializing" : "alive" : "dead";
|
|
@@ -4981,8 +5374,8 @@ async function executeLspSymbols(params, signal) {
|
|
|
4981
5374
|
errorKind: "missing_query"
|
|
4982
5375
|
});
|
|
4983
5376
|
}
|
|
4984
|
-
const
|
|
4985
|
-
return formatSymbolsResult(filePath, scope,
|
|
5377
|
+
const symbols = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
|
|
5378
|
+
return formatSymbolsResult(filePath, scope, symbols, limit, query);
|
|
4986
5379
|
}
|
|
4987
5380
|
const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
|
|
4988
5381
|
return formatSymbolsResult(filePath, scope, symbols, limit);
|
|
@@ -5118,6 +5511,16 @@ var LSP_MCP_TOOLS = [
|
|
|
5118
5511
|
}, ["filePath", "line", "character", "newName"]),
|
|
5119
5512
|
execute: executeLspRename
|
|
5120
5513
|
},
|
|
5514
|
+
{
|
|
5515
|
+
name: "format",
|
|
5516
|
+
aliases: ["lsp_format"],
|
|
5517
|
+
title: "LSP Format",
|
|
5518
|
+
description: "Format a source file with its language server and write the returned edits to disk.",
|
|
5519
|
+
inputSchema: objectSchema({
|
|
5520
|
+
filePath: { type: "string", description: "Source file path to format." }
|
|
5521
|
+
}, ["filePath"]),
|
|
5522
|
+
execute: executeLspFormat
|
|
5523
|
+
},
|
|
5121
5524
|
{
|
|
5122
5525
|
name: "install_decision",
|
|
5123
5526
|
aliases: ["lsp_install_decision"],
|
|
@@ -5184,7 +5587,7 @@ function withContext(args, context) {
|
|
|
5184
5587
|
function ensureDaemonAvailable(paths, ensure, signal) {
|
|
5185
5588
|
if (!signal)
|
|
5186
5589
|
return ensure(paths);
|
|
5187
|
-
return new Promise((
|
|
5590
|
+
return new Promise((resolve, reject) => {
|
|
5188
5591
|
let settled = false;
|
|
5189
5592
|
const finish = (run) => {
|
|
5190
5593
|
if (settled)
|
|
@@ -5199,11 +5602,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
|
|
|
5199
5602
|
return;
|
|
5200
5603
|
}
|
|
5201
5604
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5202
|
-
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() =>
|
|
5605
|
+
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
|
|
5203
5606
|
});
|
|
5204
5607
|
}
|
|
5205
5608
|
function sendToolCall(paths, token, name, args, options) {
|
|
5206
|
-
return new Promise((
|
|
5609
|
+
return new Promise((resolve, reject) => {
|
|
5207
5610
|
const socket = connect(paths.socket);
|
|
5208
5611
|
const requestId = allocateProxyRequestId();
|
|
5209
5612
|
let settled = false;
|
|
@@ -5256,7 +5659,7 @@ function sendToolCall(paths, token, name, args, options) {
|
|
|
5256
5659
|
}
|
|
5257
5660
|
const result = toToolResult(message, requestId);
|
|
5258
5661
|
if (result)
|
|
5259
|
-
finish(() =>
|
|
5662
|
+
finish(() => resolve(result));
|
|
5260
5663
|
else
|
|
5261
5664
|
finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
|
|
5262
5665
|
});
|
|
@@ -5305,10 +5708,9 @@ var OMO_LSP_DAEMON_VERSION2 = "OMO_LSP_DAEMON_VERSION";
|
|
|
5305
5708
|
var DAEMON_VERSION_PATTERN2 = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
5306
5709
|
|
|
5307
5710
|
class InvalidRuntimeOverrideError2 extends Error {
|
|
5308
|
-
code = "invalid_runtime_override";
|
|
5309
|
-
reason;
|
|
5310
5711
|
constructor(reason, message) {
|
|
5311
5712
|
super(message);
|
|
5713
|
+
this.code = "invalid_runtime_override";
|
|
5312
5714
|
this.name = "InvalidRuntimeOverrideError";
|
|
5313
5715
|
this.reason = reason;
|
|
5314
5716
|
}
|
|
@@ -5328,12 +5730,12 @@ function resolveDaemonRuntime2(env, defaults) {
|
|
|
5328
5730
|
throw new InvalidRuntimeOverrideError2("paired_values_required", `${OMO_LSP_DAEMON_CLI2} and ${OMO_LSP_DAEMON_VERSION2} must be set together`);
|
|
5329
5731
|
}
|
|
5330
5732
|
if (!hasCliOverride || !hasVersionOverride) {
|
|
5331
|
-
if (!
|
|
5733
|
+
if (!isAbsolute6(defaults.cliPath)) {
|
|
5332
5734
|
throw new InvalidRuntimeOverrideError2("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
|
|
5333
5735
|
}
|
|
5334
5736
|
return { cliPath: defaults.cliPath, version: validateDaemonVersion2(defaults.version) };
|
|
5335
5737
|
}
|
|
5336
|
-
if (!
|
|
5738
|
+
if (!isAbsolute6(cliOverride)) {
|
|
5337
5739
|
throw new InvalidRuntimeOverrideError2("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI2} must be an absolute path to an existing regular file`);
|
|
5338
5740
|
}
|
|
5339
5741
|
const stat = statSync5(cliOverride, { throwIfNoEntry: false });
|
|
@@ -5432,8 +5834,8 @@ function normalizeDiagnosticsOutcome(outcome) {
|
|
|
5432
5834
|
return normalizeDiagnosticsText(outcome);
|
|
5433
5835
|
return outcome;
|
|
5434
5836
|
}
|
|
5435
|
-
function normalizeDiagnosticsText(
|
|
5436
|
-
return
|
|
5837
|
+
function normalizeDiagnosticsText(text) {
|
|
5838
|
+
return text.trim();
|
|
5437
5839
|
}
|
|
5438
5840
|
function formatDiagnosticsError(error) {
|
|
5439
5841
|
const message = normalizeDiagnosticsText(error.message);
|
|
@@ -5454,15 +5856,14 @@ function extensionKey(filePath) {
|
|
|
5454
5856
|
}
|
|
5455
5857
|
// ../../../../lsp-core/src/request-context.ts
|
|
5456
5858
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
5457
|
-
import { existsSync as
|
|
5458
|
-
import { basename as basename4, delimiter as delimiter4, dirname as dirname2, isAbsolute as
|
|
5859
|
+
import { existsSync as existsSync13, realpathSync as realpathSync6, statSync as statSync6 } from "node:fs";
|
|
5860
|
+
import { basename as basename4, delimiter as delimiter4, dirname as dirname2, isAbsolute as isAbsolute7, join as join8, relative as relative5, resolve as resolve10 } from "node:path";
|
|
5459
5861
|
|
|
5460
5862
|
class LspRequestContextParseError2 extends Error {
|
|
5461
|
-
code;
|
|
5462
|
-
name = "LspRequestContextParseError";
|
|
5463
5863
|
constructor(code, message) {
|
|
5464
5864
|
super(message);
|
|
5465
5865
|
this.code = code;
|
|
5866
|
+
this.name = "LspRequestContextParseError";
|
|
5466
5867
|
}
|
|
5467
5868
|
}
|
|
5468
5869
|
var storage2 = new AsyncLocalStorage2;
|
|
@@ -5479,37 +5880,37 @@ function parseLspRequestContext2(value) {
|
|
|
5479
5880
|
const installDecisionsPath = stringField2(value, "installDecisionsPath");
|
|
5480
5881
|
const capabilities = capabilitiesField2(value["capabilities"]);
|
|
5481
5882
|
const canonical = canonicalCwd2(cwd);
|
|
5482
|
-
for (const
|
|
5483
|
-
requireAbsolutePath2(
|
|
5484
|
-
const projectPath = canonicalizeExistingOrNearestAncestor2(
|
|
5883
|
+
for (const path of projectConfigPaths) {
|
|
5884
|
+
requireAbsolutePath2(path, "projectConfigPaths");
|
|
5885
|
+
const projectPath = canonicalizeExistingOrNearestAncestor2(path);
|
|
5485
5886
|
if (!isPathInside2(canonical, projectPath)) {
|
|
5486
|
-
throw new LspRequestContextParseError2("project_config_outside_cwd", `Project LSP config path must be inside cwd: ${
|
|
5887
|
+
throw new LspRequestContextParseError2("project_config_outside_cwd", `Project LSP config path must be inside cwd: ${path}`);
|
|
5487
5888
|
}
|
|
5488
5889
|
}
|
|
5489
5890
|
requireAbsolutePath2(userConfigPath, "userConfigPath");
|
|
5490
5891
|
requireAbsolutePath2(installDecisionsPath, "installDecisionsPath");
|
|
5491
5892
|
return {
|
|
5492
5893
|
cwd: canonical,
|
|
5493
|
-
projectConfigPaths: projectConfigPaths.map((
|
|
5894
|
+
projectConfigPaths: projectConfigPaths.map((path) => canonicalizeExistingOrNearestAncestor2(path)),
|
|
5494
5895
|
userConfigPath,
|
|
5495
5896
|
installDecisionsPath,
|
|
5496
5897
|
capabilities
|
|
5497
5898
|
};
|
|
5498
5899
|
}
|
|
5499
5900
|
function canonicalCwd2(cwd) {
|
|
5500
|
-
const resolved =
|
|
5501
|
-
if (!
|
|
5901
|
+
const resolved = resolve10(cwd);
|
|
5902
|
+
if (!existsSync13(resolved) || !statSync6(resolved).isDirectory()) {
|
|
5502
5903
|
throw new LspRequestContextParseError2("invalid_cwd", `LSP request cwd must be an existing directory: ${cwd}`);
|
|
5503
5904
|
}
|
|
5504
|
-
return
|
|
5905
|
+
return realpathSync6(resolved);
|
|
5505
5906
|
}
|
|
5506
|
-
function canonicalizeExistingOrNearestAncestor2(
|
|
5507
|
-
let current =
|
|
5907
|
+
function canonicalizeExistingOrNearestAncestor2(path) {
|
|
5908
|
+
let current = resolve10(path);
|
|
5508
5909
|
const suffix = [];
|
|
5509
5910
|
while (true) {
|
|
5510
5911
|
try {
|
|
5511
|
-
const existing =
|
|
5512
|
-
return suffix.length === 0 ? existing :
|
|
5912
|
+
const existing = realpathSync6(current);
|
|
5913
|
+
return suffix.length === 0 ? existing : join8(existing, ...suffix);
|
|
5513
5914
|
} catch (error) {
|
|
5514
5915
|
if (!isMissingPathError2(error))
|
|
5515
5916
|
throw error;
|
|
@@ -5546,15 +5947,15 @@ function stringArrayField2(value, field) {
|
|
|
5546
5947
|
}
|
|
5547
5948
|
return fieldValue;
|
|
5548
5949
|
}
|
|
5549
|
-
function requireAbsolutePath2(
|
|
5550
|
-
if (!
|
|
5551
|
-
throw new LspRequestContextParseError2("relative_path", `LSP request context.${field} must be absolute: ${
|
|
5950
|
+
function requireAbsolutePath2(path, field) {
|
|
5951
|
+
if (!isAbsolute7(path)) {
|
|
5952
|
+
throw new LspRequestContextParseError2("relative_path", `LSP request context.${field} must be absolute: ${path}`);
|
|
5552
5953
|
}
|
|
5553
5954
|
}
|
|
5554
5955
|
function isPathInside2(parent, child) {
|
|
5555
|
-
const childPath =
|
|
5956
|
+
const childPath = resolve10(child);
|
|
5556
5957
|
const relativePath = relative5(parent, childPath);
|
|
5557
|
-
return relativePath === "" || !relativePath.startsWith("..") && !
|
|
5958
|
+
return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute7(relativePath);
|
|
5558
5959
|
}
|
|
5559
5960
|
function isMissingPathError2(error) {
|
|
5560
5961
|
const code = errorCode2(error);
|
|
@@ -5577,9 +5978,9 @@ function errorCode2(error) {
|
|
|
5577
5978
|
}
|
|
5578
5979
|
|
|
5579
5980
|
// src/daemon-cli-path.ts
|
|
5580
|
-
import { existsSync as existsSync14, readFileSync as
|
|
5981
|
+
import { existsSync as existsSync14, readFileSync as readFileSync7 } from "node:fs";
|
|
5581
5982
|
import { createRequire as createRequire2 } from "node:module";
|
|
5582
|
-
import { dirname as
|
|
5983
|
+
import { dirname as dirname11, join as join9 } from "node:path";
|
|
5583
5984
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
5584
5985
|
var requireFromHere2 = createRequire2(import.meta.url);
|
|
5585
5986
|
var PACKAGE_LSP_DAEMON_CLI = "@code-yeongyu/lsp-daemon/cli";
|
|
@@ -5626,8 +6027,8 @@ function resolveConfiguredLspDaemonCli(cliPath) {
|
|
|
5626
6027
|
}
|
|
5627
6028
|
function readDaemonPackageVersion(cliPath) {
|
|
5628
6029
|
try {
|
|
5629
|
-
const parsed = JSON.parse(
|
|
5630
|
-
if (
|
|
6030
|
+
const parsed = JSON.parse(readFileSync7(join9(dirname11(cliPath), "package.json"), "utf8"));
|
|
6031
|
+
if (isRecord8(parsed) && typeof parsed["version"] === "string" && parsed["version"].length > 0) {
|
|
5631
6032
|
return parsed["version"];
|
|
5632
6033
|
}
|
|
5633
6034
|
} catch (error) {
|
|
@@ -5636,14 +6037,14 @@ function readDaemonPackageVersion(cliPath) {
|
|
|
5636
6037
|
}
|
|
5637
6038
|
return null;
|
|
5638
6039
|
}
|
|
5639
|
-
function
|
|
6040
|
+
function isRecord8(value) {
|
|
5640
6041
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5641
6042
|
}
|
|
5642
6043
|
|
|
5643
6044
|
// src/lsp-session-state.ts
|
|
5644
|
-
import { mkdirSync as mkdirSync4, readFileSync as readFileSync8, writeFileSync as
|
|
6045
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "node:fs";
|
|
5645
6046
|
import { homedir } from "node:os";
|
|
5646
|
-
import { dirname as
|
|
6047
|
+
import { dirname as dirname12, join as join10 } from "node:path";
|
|
5647
6048
|
function sessionIdFrom(input) {
|
|
5648
6049
|
return typeof input.session_id === "string" && input.session_id.length > 0 ? input.session_id : undefined;
|
|
5649
6050
|
}
|
|
@@ -5672,21 +6073,21 @@ function sessionStatePath(sessionId) {
|
|
|
5672
6073
|
const root = process.env["PLUGIN_DATA"] ?? join10(homedir(), ".codex", "codex-lsp");
|
|
5673
6074
|
return join10(root, "sessions", `${safePathSegment(sessionId)}.json`);
|
|
5674
6075
|
}
|
|
5675
|
-
function readSessionState(
|
|
6076
|
+
function readSessionState(path) {
|
|
5676
6077
|
try {
|
|
5677
|
-
const parsed = JSON.parse(readFileSync8(
|
|
5678
|
-
if (
|
|
6078
|
+
const parsed = JSON.parse(readFileSync8(path, "utf8"));
|
|
6079
|
+
if (isRecord9(parsed) && isLspSessionState(parsed))
|
|
5679
6080
|
return normalizeSessionState(parsed);
|
|
5680
6081
|
return emptyState();
|
|
5681
6082
|
} catch (error) {
|
|
5682
|
-
if (error instanceof SyntaxError ||
|
|
6083
|
+
if (error instanceof SyntaxError || isRecord9(error) && error["code"] === "ENOENT")
|
|
5683
6084
|
return emptyState();
|
|
5684
6085
|
throw error;
|
|
5685
6086
|
}
|
|
5686
6087
|
}
|
|
5687
|
-
function writeSessionState(
|
|
5688
|
-
mkdirSync4(
|
|
5689
|
-
|
|
6088
|
+
function writeSessionState(path, state) {
|
|
6089
|
+
mkdirSync4(dirname12(path), { recursive: true });
|
|
6090
|
+
writeFileSync4(path, `${JSON.stringify(state)}
|
|
5690
6091
|
`);
|
|
5691
6092
|
}
|
|
5692
6093
|
function emptyState() {
|
|
@@ -5705,7 +6106,7 @@ function normalizeSessionState(value) {
|
|
|
5705
6106
|
notConfiguredExtensions: Array.isArray(notConfiguredExtensions) ? notConfiguredExtensions.filter((item) => typeof item === "string").sort() : []
|
|
5706
6107
|
};
|
|
5707
6108
|
}
|
|
5708
|
-
function
|
|
6109
|
+
function isRecord9(value) {
|
|
5709
6110
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5710
6111
|
}
|
|
5711
6112
|
|
|
@@ -5716,7 +6117,7 @@ function extractMutatedFilePaths(input) {
|
|
|
5716
6117
|
return [];
|
|
5717
6118
|
if (isFailedToolResponse(input.tool_response))
|
|
5718
6119
|
return [];
|
|
5719
|
-
const toolInput =
|
|
6120
|
+
const toolInput = isRecord10(input.tool_input) ? input.tool_input : {};
|
|
5720
6121
|
const paths = new Set;
|
|
5721
6122
|
addStringValue(paths, toolInput["path"]);
|
|
5722
6123
|
addStringValue(paths, toolInput["filePath"]);
|
|
@@ -5735,7 +6136,7 @@ function isMutationTool(value) {
|
|
|
5735
6136
|
return MUTATION_TOOL_NAMES.has(value.toLowerCase());
|
|
5736
6137
|
}
|
|
5737
6138
|
function isFailedToolResponse(value) {
|
|
5738
|
-
if (!
|
|
6139
|
+
if (!isRecord10(value))
|
|
5739
6140
|
return false;
|
|
5740
6141
|
return value["isError"] === true || value["is_error"] === true || value["error"] === true || value["status"] === "error";
|
|
5741
6142
|
}
|
|
@@ -5761,9 +6162,9 @@ function addPatchInput(paths, value) {
|
|
|
5761
6162
|
return;
|
|
5762
6163
|
for (const line of value.split(`
|
|
5763
6164
|
`)) {
|
|
5764
|
-
const
|
|
5765
|
-
if (
|
|
5766
|
-
paths.add(
|
|
6165
|
+
const path = extractPatchHeaderPath(line);
|
|
6166
|
+
if (path !== undefined)
|
|
6167
|
+
paths.add(path);
|
|
5767
6168
|
}
|
|
5768
6169
|
}
|
|
5769
6170
|
function extractPatchHeaderPath(line) {
|
|
@@ -5778,7 +6179,7 @@ function addPatchFiles(paths, value) {
|
|
|
5778
6179
|
if (!Array.isArray(value))
|
|
5779
6180
|
return;
|
|
5780
6181
|
for (const item of value) {
|
|
5781
|
-
if (!
|
|
6182
|
+
if (!isRecord10(item))
|
|
5782
6183
|
continue;
|
|
5783
6184
|
addStringValue(paths, item["path"]);
|
|
5784
6185
|
addStringValue(paths, item["filePath"]);
|
|
@@ -5787,7 +6188,7 @@ function addPatchFiles(paths, value) {
|
|
|
5787
6188
|
addStringValue(paths, item["move_path"]);
|
|
5788
6189
|
}
|
|
5789
6190
|
}
|
|
5790
|
-
function
|
|
6191
|
+
function isRecord10(value) {
|
|
5791
6192
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5792
6193
|
}
|
|
5793
6194
|
|
|
@@ -5818,10 +6219,10 @@ function postEditOutcomeFromDaemonResult(result) {
|
|
|
5818
6219
|
`);
|
|
5819
6220
|
}
|
|
5820
6221
|
function notConfiguredAvailability(details) {
|
|
5821
|
-
if (!
|
|
6222
|
+
if (!isRecord11(details))
|
|
5822
6223
|
return;
|
|
5823
6224
|
const availability = details["availability"];
|
|
5824
|
-
if (!
|
|
6225
|
+
if (!isRecord11(availability))
|
|
5825
6226
|
return;
|
|
5826
6227
|
if (availability["kind"] !== "not_configured")
|
|
5827
6228
|
return;
|
|
@@ -5829,11 +6230,11 @@ function notConfiguredAvailability(details) {
|
|
|
5829
6230
|
return typeof extension === "string" && extension.length > 0 ? { extension } : undefined;
|
|
5830
6231
|
}
|
|
5831
6232
|
function codexLspRequestContext(env = process.env, cwd = process.cwd()) {
|
|
5832
|
-
const
|
|
6233
|
+
const canonicalCwd = realpathSync7(resolve11(cwd));
|
|
5833
6234
|
const codexHome = resolve11(env["CODEX_HOME"]?.trim() || join11(homedir3(), ".codex"));
|
|
5834
6235
|
return parseLspRequestContext2({
|
|
5835
|
-
cwd:
|
|
5836
|
-
projectConfigPaths: [join11(
|
|
6236
|
+
cwd: canonicalCwd,
|
|
6237
|
+
projectConfigPaths: [join11(canonicalCwd, ".codex", "lsp-client.json")],
|
|
5837
6238
|
userConfigPath: join11(codexHome, "lsp-client.json"),
|
|
5838
6239
|
installDecisionsPath: join11(codexHome, "lsp-install-decisions.json"),
|
|
5839
6240
|
capabilities: { installDecisionTool: true }
|
|
@@ -5936,22 +6337,22 @@ function isContextPressureTranscript(transcriptPath) {
|
|
|
5936
6337
|
throw error;
|
|
5937
6338
|
}
|
|
5938
6339
|
}
|
|
5939
|
-
function hasContextPressureMarker(
|
|
5940
|
-
const normalizedText =
|
|
6340
|
+
function hasContextPressureMarker(text) {
|
|
6341
|
+
const normalizedText = text.toLowerCase();
|
|
5941
6342
|
return CONTEXT_PRESSURE_MARKERS.some((marker) => normalizedText.includes(marker));
|
|
5942
6343
|
}
|
|
5943
|
-
function limitHookText(
|
|
5944
|
-
if (
|
|
5945
|
-
return
|
|
6344
|
+
function limitHookText(text, maxChars) {
|
|
6345
|
+
if (text.length <= maxChars)
|
|
6346
|
+
return text;
|
|
5946
6347
|
const marker = `
|
|
5947
6348
|
|
|
5948
6349
|
[Truncated hook output to ${maxChars} chars to avoid Codex context overflow.]`;
|
|
5949
6350
|
if (marker.length >= maxChars)
|
|
5950
6351
|
return marker.slice(0, maxChars);
|
|
5951
|
-
const head =
|
|
6352
|
+
const head = text.slice(0, maxChars - marker.length).replace(/[ \t\r\n]+$/, "");
|
|
5952
6353
|
return `${head}${marker}`;
|
|
5953
6354
|
}
|
|
5954
|
-
function
|
|
6355
|
+
function isRecord11(value) {
|
|
5955
6356
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5956
6357
|
}
|
|
5957
6358
|
|
|
@@ -5968,7 +6369,7 @@ async function runHookCli(runHook, stdin) {
|
|
|
5968
6369
|
if (!raw.trim())
|
|
5969
6370
|
return;
|
|
5970
6371
|
const parsed = JSON.parse(raw);
|
|
5971
|
-
const input =
|
|
6372
|
+
const input = isRecord11(parsed) ? parsed : {};
|
|
5972
6373
|
const output = await runHook(input);
|
|
5973
6374
|
if (output)
|
|
5974
6375
|
process.stdout.write(output);
|
|
@@ -6011,15 +6412,15 @@ main().catch((error) => {
|
|
|
6011
6412
|
});
|
|
6012
6413
|
async function runPackageLspMcpCli() {
|
|
6013
6414
|
const cliPath = resolveLspDaemonCliPath();
|
|
6014
|
-
const child = spawn3(execPath2, [cliPath, "mcp"], { stdio: "inherit" });
|
|
6015
|
-
await new Promise((
|
|
6415
|
+
const child = spawn3(execPath2, [cliPath, "mcp"], { stdio: "inherit", windowsHide: true });
|
|
6416
|
+
await new Promise((resolve, reject) => {
|
|
6016
6417
|
child.once("error", reject);
|
|
6017
6418
|
child.once("exit", (code, signal) => {
|
|
6018
6419
|
if (code !== null && code !== 0)
|
|
6019
6420
|
process.exitCode = code;
|
|
6020
6421
|
if (code === null && signal !== null)
|
|
6021
6422
|
process.exitCode = 1;
|
|
6022
|
-
|
|
6423
|
+
resolve();
|
|
6023
6424
|
});
|
|
6024
6425
|
});
|
|
6025
6426
|
}
|