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