oh-my-opencode 5.0.0-beta.3 → 5.0.0-beta.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/command/publish.md +44 -16
- package/.agents/skills/publish/SKILL.md +44 -16
- package/.agents/skills/senpi-qa/SKILL.md +80 -0
- package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.mjs +65 -0
- package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.test.mjs +171 -0
- package/.agents/skills/work-with-pr/SKILL.md +37 -23
- package/.opencode/command/publish.md +44 -16
- package/.opencode/skills/work-with-pr/SKILL.md +37 -23
- package/README.ja.md +25 -21
- package/README.ko.md +25 -21
- package/README.md +38 -23
- package/README.ru.md +24 -20
- package/README.zh-cn.md +25 -21
- package/dist/agents/atlas/agent.d.ts +0 -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 +2 -2
- package/dist/cli/config-manager/parse-opencode-config-file.d.ts +2 -1
- package/dist/cli/doctor/checks/system-plugin.d.ts +4 -3
- package/dist/cli/fallback-lane-policy.d.ts +1 -0
- package/dist/cli/index.js +22601 -20302
- 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 +22219 -19897
- 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 -1
- package/dist/config/schema/oh-my-opencode-config.d.ts +5 -1
- package/dist/config/schema/ulw-execute.d.ts +5 -0
- package/dist/config/validate.d.ts +2 -0
- package/dist/create-hooks.d.ts +3 -1
- package/dist/features/background-agent/constants.d.ts +0 -7
- package/dist/features/background-agent/manager.d.ts +2 -1
- package/dist/features/background-agent/parent-wake-dispatched-tracker.d.ts +0 -1
- package/dist/features/background-agent/subagent-spawn-limits.d.ts +8 -0
- package/dist/features/btw-side/btw-command-draft.d.ts +7 -0
- package/dist/features/btw-side/context-injector.d.ts +15 -0
- package/dist/features/btw-side/index.d.ts +8 -0
- package/dist/features/btw-side/metadata.d.ts +15 -0
- package/dist/features/btw-side/parent-context-budget.d.ts +9 -0
- package/dist/features/btw-side/server-session-registry.d.ts +8 -0
- package/dist/features/btw-side/tui-adoption-cache.d.ts +13 -0
- package/dist/features/btw-side/tui-adoption-guard.d.ts +5 -0
- package/dist/features/btw-side/tui-controller-types.d.ts +68 -0
- package/dist/features/btw-side/tui-controller.d.ts +19 -0
- package/dist/features/btw-side/tui-escape-return.d.ts +12 -0
- package/dist/features/btw-side/tui-keymap.d.ts +17 -0
- package/dist/features/btw-side/tui-parent-validator.d.ts +6 -0
- package/dist/features/btw-side/tui-picker-options.d.ts +20 -0
- package/dist/features/btw-side/tui-picker.d.ts +9 -0
- package/dist/features/btw-side/tui-prompt-queue.d.ts +8 -0
- package/dist/features/btw-side/tui-session-bridge.d.ts +11 -0
- package/dist/features/btw-side/tui-session-catalog.d.ts +35 -0
- package/dist/features/btw-side/tui-side-removal.d.ts +11 -0
- package/dist/features/btw-side/tui-side-start.d.ts +9 -0
- package/dist/features/btw-side/tui-wiring.d.ts +8 -0
- package/dist/features/builtin-commands/templates/ulw-execute.d.ts +1 -0
- package/dist/features/builtin-commands/types.d.ts +1 -1
- package/dist/features/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 +15 -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/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/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 -1
- package/dist/hooks/keyword-detector/hook.d.ts +7 -0
- package/dist/hooks/keyword-detector/ultrawork/source-detector.d.ts +0 -1
- package/dist/hooks/model-fallback/hook.d.ts +1 -1
- package/dist/hooks/prometheus-md-only/agent-resolution.d.ts +2 -2
- package/dist/hooks/runtime-fallback/chat-message-handler.d.ts +2 -0
- package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +1 -0
- package/dist/hooks/runtime-fallback/runtime-model-settings.d.ts +6 -0
- package/dist/hooks/runtime-fallback/session-status-handler.d.ts +1 -1
- package/dist/hooks/runtime-fallback/types.d.ts +3 -1
- package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
- package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
- package/dist/hooks/{start-work → ulw-execute}/context-info-builder.d.ts +1 -1
- package/dist/hooks/{start-work → ulw-execute}/index.d.ts +1 -1
- package/dist/hooks/ulw-execute/ulw-execute-hook.d.ts +23 -0
- package/dist/index.js +12989 -7152
- package/dist/oh-my-opencode.schema.json +20 -2
- package/dist/plugin/chat-message/types.d.ts +3 -3
- package/dist/plugin/chat-message/ulw-execute-message.d.ts +5 -0
- package/dist/plugin/event-session-lifecycle.d.ts +1 -0
- package/dist/plugin/hooks/create-core-hooks.d.ts +2 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +2 -2
- package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
- package/dist/plugin/messages-transform.d.ts +1 -0
- package/dist/plugin-dispose.d.ts +3 -0
- package/dist/shared/agent-tool-restrictions.d.ts +0 -1
- package/dist/shared/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/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/coding-agent-sessions/AGENTS.md +62 -0
- package/dist/skills/coding-agent-sessions/SKILL.md +3 -2
- package/dist/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/dist/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/dist/skills/data-scientist/SKILL.md +99 -239
- package/dist/skills/data-scientist/references/execution-surfaces.md +91 -0
- package/dist/skills/data-scientist/references/placement.md +74 -0
- package/dist/skills/data-scientist/references/polars-lane.md +95 -0
- package/dist/skills/data-scientist/references/uv-setup.md +1 -1
- package/dist/skills/data-scientist/references/visualization.md +64 -0
- package/dist/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
- package/dist/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
- package/dist/skills/debugging/SKILL.md +2 -0
- package/dist/skills/debugging/references/methodology/00-setup.md +12 -0
- package/dist/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/dist/skills/debugging/references/runtimes/go.md +15 -1
- package/dist/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/dist/skills/debugging/references/runtimes/node.md +25 -0
- package/dist/skills/debugging/references/runtimes/python.md +13 -0
- package/dist/skills/debugging/references/runtimes/rust.md +41 -0
- package/dist/skills/debugging/references/scripts/dap.mjs +267 -0
- package/dist/skills/debugging/references/scripts/dap.test.ts +86 -0
- package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/dist/skills/debugging/references/tools/dap.md +103 -0
- package/dist/skills/debugging/references/tools/frida.md +193 -0
- package/dist/skills/frontend/SKILL.md +11 -7
- package/dist/skills/frontend/references/design/_INDEX.md +1 -0
- package/dist/skills/frontend/references/design/print-paged-media.md +76 -0
- package/dist/skills/frontend/references/design/stylegallery.md +80 -0
- package/dist/skills/frontend/references/designpowers/README.md +1 -1
- package/dist/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
- package/dist/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
- package/dist/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
- package/dist/skills/frontend/references/designpowers/orchestration.md +1 -1
- package/dist/skills/frontend/references/designpowers/routing.md +5 -5
- package/dist/skills/review-work/SKILL.md +3 -3
- package/dist/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/dist/skills/ultimate-browsing/SKILL.md +2 -0
- package/dist/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/dist/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/dist/skills/{start-work → ulw-execute}/SKILL.md +9 -8
- package/dist/skills/ulw-plan/SKILL.md +6 -6
- package/dist/skills/ulw-plan/references/full-workflow.md +31 -7
- package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
- package/dist/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/dist/skills/ulw-research/SKILL.md +4 -2
- package/dist/skills/visual-qa/AGENTS.md +58 -0
- package/dist/skills/visual-qa/SKILL.md +3 -2
- package/dist/tools/delegate-task/builtin-categories.d.ts +1 -0
- package/dist/tools/delegate-task/builtin-category-definition.d.ts +1 -0
- 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/tui.d.ts +12 -0
- package/dist/tui.js +11522 -11501
- package/package.json +42 -36
- 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 +0 -28
- package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
- package/packages/lsp-core/src/lsp/client-wrapper.test.ts +163 -13
- package/packages/lsp-core/src/lsp/client-wrapper.ts +110 -23
- package/packages/lsp-core/src/lsp/client.ts +26 -0
- 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/errors.ts +15 -0
- 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/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/transport.ts +9 -0
- package/packages/lsp-core/src/lsp/types.ts +8 -0
- package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +20 -1
- package/packages/lsp-core/src/lsp/workspace-markers.ts +18 -0
- package/packages/lsp-core/src/mcp.ts +3 -0
- package/packages/lsp-core/src/request-context.test.ts +29 -0
- package/packages/lsp-core/src/request-context.ts +1 -1
- package/packages/lsp-core/src/tool-surface.test.ts +13 -1
- package/packages/lsp-core/src/tools/definitions.ts +14 -0
- package/packages/lsp-core/src/tools/diagnostics.ts +3 -3
- package/packages/lsp-core/src/tools/format.test.ts +56 -0
- package/packages/lsp-core/src/tools/format.ts +56 -0
- package/packages/lsp-core/src/tools/index.ts +1 -0
- package/packages/lsp-core/src/tools/navigation.ts +4 -2
- package/packages/lsp-core/src/tools/rename.ts +4 -2
- package/packages/lsp-core/src/tools/symbols.ts +1 -1
- package/packages/lsp-core/src/tools/types.ts +10 -0
- package/packages/lsp-daemon/dist/cli.js +752 -307
- package/packages/lsp-daemon/dist/client.d.ts +10 -0
- package/packages/lsp-daemon/dist/client.js +712 -264
- 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.js +1 -0
- package/packages/lsp-daemon/dist/index.js +716 -273
- 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 +671 -228
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +207 -103
- package/packages/lsp-tools-mcp/dist/mcp.js +673 -230
- package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
- package/packages/lsp-tools-mcp/dist/tools.js +677 -238
- package/packages/omo-codex/THIRD-PARTY-NOTICES.md +4 -4
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +4 -4
- package/packages/omo-codex/plugin/AGENTS.md +47 -0
- package/packages/omo-codex/plugin/README.md +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +34 -33
- 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/codegraph/dist/cli.js +323 -117
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +275 -85
- package/packages/omo-codex/plugin/components/codegraph/package.json +4 -4
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +12 -0
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable-idle.test.ts +47 -0
- package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +9 -0
- package/packages/omo-codex/plugin/components/comment-checker/biome.json +2 -2
- package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +2 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +5 -5
- package/packages/omo-codex/plugin/components/comment-checker/src/apply-patch.ts +2 -8
- package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +1 -2
- package/packages/omo-codex/plugin/components/comment-checker/src/request-extractor.ts +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +1 -0
- package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +3 -4
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +1 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +1 -5
- 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 +1 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +4 -21
- 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 +702 -278
- 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/biome.json +2 -2
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +60 -45
- 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 +9 -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 +1 -2
- 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 +5 -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 +3 -9
- 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 +2463 -437
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2467 -441
- 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 +5 -0
- package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +13 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -5
- package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +13 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -6
- 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/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/skill-pointer.test.ts +0 -2
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +5 -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 +5 -5
- 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 +6 -6
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +12 -12
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +28 -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 +3 -3
- 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}/test/boulder-reader.test.ts +3 -3
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +1 -4
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +8 -22
- package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +17 -0
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +13 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +5 -1
- 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 +11 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +124 -68
- 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 +9 -6
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +1 -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 +7 -10
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +50 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -2
- 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 +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +13 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +3 -5
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +16 -5
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +11 -14
- package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +73 -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 +44 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +25 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +26 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +27 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +18 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +7 -3
- 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/quality-gate-roles.test.ts +45 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +20 -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 +4 -5
- 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-codegraph-init-guidance.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/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-checking-codegraph-bootstrap.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-checking-ulw-execute-continuation.json +17 -0
- 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 +3 -3
- package/packages/omo-codex/plugin/package-lock.json +681 -395
- package/packages/omo-codex/plugin/package.json +2 -2
- package/packages/omo-codex/plugin/scripts/AGENTS.md +40 -0
- package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -1
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +3 -3
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +11 -11
- package/packages/omo-codex/plugin/shared/package.json +3 -4
- package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +51 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +62 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
- package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
- package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
- package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
- package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
- package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
- package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +11 -7
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +4 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +179 -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 +13 -11
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +13 -1
- package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +12 -11
- package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -2
- 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 +1 -0
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -6
- 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 +4 -2
- package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +3 -2
- 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 +8 -28
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
- 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 +2 -2
- 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 -1
- package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +2 -2
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +4 -4
- package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
- package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
- package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +12 -12
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +1 -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 +0 -3
- 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/install-config-reasoning.test.mjs +2 -2
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +2637 -549
- package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
- package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
- package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
- package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
- package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
- package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
- package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
- package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
- package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
- package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
- package/packages/shared-skills/skills/debugging/SKILL.md +2 -0
- package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
- package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
- package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
- package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
- package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
- package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
- package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
- package/packages/shared-skills/skills/frontend/SKILL.md +11 -7
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
- package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
- package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
- package/packages/shared-skills/skills/review-work/SKILL.md +3 -3
- package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +179 -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 +13 -11
- package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +9 -8
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +6 -6
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/packages/shared-skills/skills/ulw-research/SKILL.md +4 -2
- package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
- package/packages/shared-skills/skills/visual-qa/SKILL.md +3 -2
- package/script/qa/web-terminal-visual-qa.mjs +2 -0
- package/script/qa/xterm-live-terminal.mjs +18 -2
- package/dist/config/schema/start-work.d.ts +0 -5
- package/dist/features/builtin-commands/templates/start-work.d.ts +0 -1
- 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/plugin/chat-message/start-work-message.d.ts +0 -5
- 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/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/start-work-continuation/hooks/hooks.json +0 -28
- 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/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/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/{start-work-continuation → 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}/src/types.ts +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
import { argv, stderr } from "node:process";
|
|
5
5
|
|
|
6
6
|
// src/proxy.ts
|
|
7
|
-
import { existsSync as
|
|
8
|
-
import { basename as
|
|
7
|
+
import { existsSync as existsSync13, realpathSync as realpathSync6 } from "node:fs";
|
|
8
|
+
import { basename as basename4, delimiter as delimiter4, dirname as dirname11, isAbsolute as isAbsolute6 } from "node:path";
|
|
9
9
|
|
|
10
10
|
// ../mcp-stdio-core/src/record.ts
|
|
11
11
|
function isPlainRecord(value) {
|
|
@@ -184,6 +184,7 @@ async function runJsonRpcStdioServer(config) {
|
|
|
184
184
|
const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
|
|
185
185
|
isClosed = true;
|
|
186
186
|
config.onIdleTimeout?.();
|
|
187
|
+
config.input.destroy();
|
|
187
188
|
});
|
|
188
189
|
const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
|
|
189
190
|
isClosed = true;
|
|
@@ -280,7 +281,11 @@ function createParentWatchdog(config, onDeadParent) {
|
|
|
280
281
|
const probeAlive = config.probeAlive ?? isProcessAlive;
|
|
281
282
|
let fired = false;
|
|
282
283
|
const timer = setInterval(() => {
|
|
283
|
-
if (fired
|
|
284
|
+
if (fired)
|
|
285
|
+
return;
|
|
286
|
+
const alive = probeAlive(parentPid);
|
|
287
|
+
config.onPoll?.(alive);
|
|
288
|
+
if (alive)
|
|
284
289
|
return;
|
|
285
290
|
fired = true;
|
|
286
291
|
onDeadParent(parentPid, pollIntervalMs);
|
|
@@ -315,8 +320,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
|
|
|
315
320
|
};
|
|
316
321
|
}
|
|
317
322
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
318
|
-
import { existsSync as
|
|
319
|
-
import { dirname as
|
|
323
|
+
import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
|
|
324
|
+
import { basename as basename3, dirname as dirname8, join as join5, resolve as resolve8 } from "node:path";
|
|
320
325
|
|
|
321
326
|
// ../lsp-core/src/request-context.ts
|
|
322
327
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -325,18 +330,17 @@ import { homedir } from "node:os";
|
|
|
325
330
|
import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
326
331
|
|
|
327
332
|
class LspRequestContextParseError extends Error {
|
|
328
|
-
code;
|
|
329
|
-
name = "LspRequestContextParseError";
|
|
330
333
|
constructor(code, message) {
|
|
331
334
|
super(message);
|
|
332
335
|
this.code = code;
|
|
336
|
+
this.name = "LspRequestContextParseError";
|
|
333
337
|
}
|
|
334
338
|
}
|
|
335
339
|
|
|
336
340
|
class LspRequestContextUnavailableError extends Error {
|
|
337
|
-
name = "LspRequestContextUnavailableError";
|
|
338
341
|
constructor() {
|
|
339
342
|
super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
|
|
343
|
+
this.name = "LspRequestContextUnavailableError";
|
|
340
344
|
}
|
|
341
345
|
}
|
|
342
346
|
var storage = new AsyncLocalStorage;
|
|
@@ -356,7 +360,7 @@ function contextCwd() {
|
|
|
356
360
|
}
|
|
357
361
|
function createStandaloneMcpRequestContext(input = {}) {
|
|
358
362
|
const env = input.env ?? process.env;
|
|
359
|
-
const cwd = canonicalCwd(input.cwd ?? process.cwd());
|
|
363
|
+
const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
|
|
360
364
|
const home = input.homeDir ?? homedir();
|
|
361
365
|
const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
|
|
362
366
|
const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
|
|
@@ -499,22 +503,15 @@ function effectiveExtension(filePath) {
|
|
|
499
503
|
|
|
500
504
|
// ../lsp-core/src/lsp/errors.ts
|
|
501
505
|
class LspConnectionClosedError extends Error {
|
|
502
|
-
serverId;
|
|
503
|
-
root;
|
|
504
|
-
name = "LspConnectionClosedError";
|
|
505
506
|
constructor(serverId, root, message) {
|
|
506
507
|
super(message ?? `LSP connection closed for ${serverId} at ${root}`);
|
|
507
508
|
this.serverId = serverId;
|
|
508
509
|
this.root = root;
|
|
510
|
+
this.name = "LspConnectionClosedError";
|
|
509
511
|
}
|
|
510
512
|
}
|
|
511
513
|
|
|
512
514
|
class LspProcessExitedError extends Error {
|
|
513
|
-
serverId;
|
|
514
|
-
root;
|
|
515
|
-
exitCode;
|
|
516
|
-
stderrTail;
|
|
517
|
-
name = "LspProcessExitedError";
|
|
518
515
|
constructor(serverId, root, exitCode, stderrTail) {
|
|
519
516
|
const stderrSuffix = stderrTail ? `
|
|
520
517
|
stderr tail: ${stderrTail}` : "";
|
|
@@ -523,46 +520,59 @@ stderr tail: ${stderrTail}` : "";
|
|
|
523
520
|
this.root = root;
|
|
524
521
|
this.exitCode = exitCode;
|
|
525
522
|
this.stderrTail = stderrTail;
|
|
523
|
+
this.name = "LspProcessExitedError";
|
|
526
524
|
}
|
|
527
525
|
}
|
|
528
526
|
|
|
529
527
|
class LspRequestTimeoutError extends Error {
|
|
530
|
-
method;
|
|
531
|
-
stderrTail;
|
|
532
|
-
name = "LspRequestTimeoutError";
|
|
533
528
|
constructor(method, stderrTail) {
|
|
534
529
|
const stderrSuffix = stderrTail ? `
|
|
535
530
|
recent stderr: ${stderrTail}` : "";
|
|
536
531
|
super(`LSP request timeout (method: ${method})${stderrSuffix}`);
|
|
537
532
|
this.method = method;
|
|
538
533
|
this.stderrTail = stderrTail;
|
|
534
|
+
this.name = "LspRequestTimeoutError";
|
|
539
535
|
}
|
|
540
536
|
}
|
|
541
537
|
|
|
542
538
|
class LspInvalidPathError extends Error {
|
|
543
|
-
|
|
539
|
+
constructor() {
|
|
540
|
+
super(...arguments);
|
|
541
|
+
this.name = "LspInvalidPathError";
|
|
542
|
+
}
|
|
544
543
|
}
|
|
545
544
|
|
|
546
545
|
class LspServerLookupError extends Error {
|
|
547
|
-
lookup;
|
|
548
|
-
name = "LspServerLookupError";
|
|
549
546
|
constructor(message, lookup) {
|
|
550
547
|
super(message);
|
|
551
548
|
this.lookup = lookup;
|
|
549
|
+
this.name = "LspServerLookupError";
|
|
552
550
|
}
|
|
553
551
|
}
|
|
554
552
|
|
|
555
553
|
class LspServerInitializingError extends Error {
|
|
556
|
-
originalError;
|
|
557
|
-
name = "LspServerInitializingError";
|
|
558
554
|
constructor(originalError) {
|
|
559
555
|
super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
|
|
560
556
|
this.originalError = originalError;
|
|
557
|
+
this.name = "LspServerInitializingError";
|
|
561
558
|
}
|
|
562
559
|
}
|
|
563
560
|
|
|
564
561
|
class LspProcessSpawnError extends Error {
|
|
565
|
-
|
|
562
|
+
constructor() {
|
|
563
|
+
super(...arguments);
|
|
564
|
+
this.name = "LspProcessSpawnError";
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
class LspClientRespawnBudgetExceededError extends Error {
|
|
569
|
+
constructor(serverId, root, retryLimit) {
|
|
570
|
+
super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
|
|
571
|
+
this.serverId = serverId;
|
|
572
|
+
this.root = root;
|
|
573
|
+
this.retryLimit = retryLimit;
|
|
574
|
+
this.name = "LspClientRespawnBudgetExceededError";
|
|
575
|
+
}
|
|
566
576
|
}
|
|
567
577
|
function isLspDeadConnectionError(err) {
|
|
568
578
|
return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
|
|
@@ -593,9 +603,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
|
|
|
593
603
|
var REQUEST_TIMEOUT_MS = 15000;
|
|
594
604
|
var INIT_TIMEOUT_MS = 60000;
|
|
595
605
|
var IDLE_TIMEOUT_MS = 5 * 60000;
|
|
606
|
+
var MAX_RESIDENT_CLIENTS = 6;
|
|
596
607
|
var REAPER_INTERVAL_MS = 60000;
|
|
597
608
|
var STOP_HARD_KILL_TIMEOUT_MS = 5000;
|
|
598
609
|
var STOP_SIGKILL_GRACE_MS = 1000;
|
|
610
|
+
var CLIENT_RESPAWN_RETRY_LIMIT = 2;
|
|
611
|
+
var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
|
|
599
612
|
|
|
600
613
|
// ../lsp-core/src/lsp/json-rpc-connection.ts
|
|
601
614
|
var HEADER_SEPARATOR2 = `\r
|
|
@@ -607,20 +620,31 @@ var METHOD_NOT_FOUND = -32601;
|
|
|
607
620
|
var INTERNAL_ERROR = -32603;
|
|
608
621
|
|
|
609
622
|
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
623
|
constructor(reader, writer) {
|
|
622
624
|
this.reader = reader;
|
|
623
625
|
this.writer = writer;
|
|
626
|
+
this.pendingRequests = new Map;
|
|
627
|
+
this.notificationHandlers = new Map;
|
|
628
|
+
this.requestHandlers = new Map;
|
|
629
|
+
this.closeHandlers = [];
|
|
630
|
+
this.errorHandlers = [];
|
|
631
|
+
this.inputBuffer = Buffer.alloc(0);
|
|
632
|
+
this.nextRequestId = 1;
|
|
633
|
+
this.listening = false;
|
|
634
|
+
this.disposed = false;
|
|
635
|
+
this.handleData = (chunk) => {
|
|
636
|
+
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
637
|
+
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
638
|
+
this.drainInputBuffer();
|
|
639
|
+
};
|
|
640
|
+
this.handleClose = () => {
|
|
641
|
+
for (const handler of this.closeHandlers) {
|
|
642
|
+
handler();
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
this.handleStreamError = (error) => {
|
|
646
|
+
this.emitError(error);
|
|
647
|
+
};
|
|
624
648
|
}
|
|
625
649
|
listen() {
|
|
626
650
|
if (this.listening)
|
|
@@ -741,19 +765,6 @@ class JsonRpcConnection {
|
|
|
741
765
|
this.notificationHandlers.clear();
|
|
742
766
|
this.requestHandlers.clear();
|
|
743
767
|
}
|
|
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
768
|
drainInputBuffer() {
|
|
758
769
|
while (true) {
|
|
759
770
|
const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
|
|
@@ -1101,31 +1112,26 @@ function isPosition(value) {
|
|
|
1101
1112
|
|
|
1102
1113
|
// ../lsp-core/src/lsp/transport.ts
|
|
1103
1114
|
class LspClientNotStartedError extends Error {
|
|
1104
|
-
serverId;
|
|
1105
|
-
root;
|
|
1106
|
-
name = "LspClientNotStartedError";
|
|
1107
1115
|
constructor(serverId, root) {
|
|
1108
1116
|
super("LSP client not started");
|
|
1109
1117
|
this.serverId = serverId;
|
|
1110
1118
|
this.root = root;
|
|
1119
|
+
this.name = "LspClientNotStartedError";
|
|
1111
1120
|
}
|
|
1112
1121
|
}
|
|
1113
1122
|
|
|
1114
1123
|
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
1124
|
constructor(root, server2, timeouts = {}) {
|
|
1127
1125
|
this.root = root;
|
|
1128
1126
|
this.server = server2;
|
|
1127
|
+
this.proc = null;
|
|
1128
|
+
this.connection = null;
|
|
1129
|
+
this.stderrBuffer = [];
|
|
1130
|
+
this.processExited = false;
|
|
1131
|
+
this.diagnosticsStore = new Map;
|
|
1132
|
+
this.workspaceApplyEditHandler = null;
|
|
1133
|
+
this.diagnosticPullSupported = false;
|
|
1134
|
+
this.documentFormattingSupported = false;
|
|
1129
1135
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
1130
1136
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
1131
1137
|
}
|
|
@@ -1147,6 +1153,12 @@ class LspClientTransport {
|
|
|
1147
1153
|
isDiagnosticPullSupported() {
|
|
1148
1154
|
return this.diagnosticPullSupported;
|
|
1149
1155
|
}
|
|
1156
|
+
setDocumentFormattingSupported(supported) {
|
|
1157
|
+
this.documentFormattingSupported = supported;
|
|
1158
|
+
}
|
|
1159
|
+
isDocumentFormattingSupported() {
|
|
1160
|
+
return this.documentFormattingSupported;
|
|
1161
|
+
}
|
|
1150
1162
|
handlePublishDiagnostics(params) {
|
|
1151
1163
|
this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
|
|
1152
1164
|
}
|
|
@@ -1360,6 +1372,14 @@ function supportsDiagnosticPull(capabilities) {
|
|
|
1360
1372
|
return false;
|
|
1361
1373
|
return Object.hasOwn(capabilities, "diagnosticProvider");
|
|
1362
1374
|
}
|
|
1375
|
+
function supportsDocumentFormatting(capabilities) {
|
|
1376
|
+
if (capabilities === undefined)
|
|
1377
|
+
return false;
|
|
1378
|
+
const provider = capabilities.documentFormattingProvider;
|
|
1379
|
+
if (provider === undefined || provider === null || provider === false)
|
|
1380
|
+
return false;
|
|
1381
|
+
return provider === true || typeof provider === "object";
|
|
1382
|
+
}
|
|
1363
1383
|
|
|
1364
1384
|
class LspClientConnection extends LspClientTransport {
|
|
1365
1385
|
async initialize() {
|
|
@@ -1376,6 +1396,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
1376
1396
|
references: {},
|
|
1377
1397
|
documentSymbol: { hierarchicalDocumentSymbolSupport: true },
|
|
1378
1398
|
publishDiagnostics: {},
|
|
1399
|
+
formatting: { dynamicRegistration: false },
|
|
1379
1400
|
rename: {
|
|
1380
1401
|
prepareSupport: true,
|
|
1381
1402
|
prepareSupportDefaultBehavior: 1
|
|
@@ -1417,6 +1438,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
1417
1438
|
initializationOptions: this.server.initialization
|
|
1418
1439
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
1419
1440
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
1441
|
+
this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
|
|
1420
1442
|
await this.sendNotification("initialized", {});
|
|
1421
1443
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
1422
1444
|
settings: { json: { validate: { enable: true } } }
|
|
@@ -1622,16 +1644,12 @@ function movedPath(candidate, oldPath, newPath) {
|
|
|
1622
1644
|
}
|
|
1623
1645
|
|
|
1624
1646
|
class WorkspaceDocumentState {
|
|
1625
|
-
sendNotification;
|
|
1626
|
-
clearDiagnostics;
|
|
1627
|
-
openDocuments = new Map;
|
|
1628
|
-
openByUri = new Map;
|
|
1629
|
-
openPromises = new Map;
|
|
1630
|
-
now;
|
|
1631
|
-
versionlessPublishQuiescenceMs;
|
|
1632
1647
|
constructor(sendNotification, clearDiagnostics, options = {}) {
|
|
1633
1648
|
this.sendNotification = sendNotification;
|
|
1634
1649
|
this.clearDiagnostics = clearDiagnostics;
|
|
1650
|
+
this.openDocuments = new Map;
|
|
1651
|
+
this.openByUri = new Map;
|
|
1652
|
+
this.openPromises = new Map;
|
|
1635
1653
|
this.now = options.now ?? (() => Date.now());
|
|
1636
1654
|
this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
|
|
1637
1655
|
}
|
|
@@ -1895,13 +1913,11 @@ import { dirname as dirname2, isAbsolute as isAbsolute2, relative as relative3,
|
|
|
1895
1913
|
import { fileURLToPath } from "node:url";
|
|
1896
1914
|
|
|
1897
1915
|
class WorkspaceEditPathError extends Error {
|
|
1898
|
-
path;
|
|
1899
|
-
detail;
|
|
1900
|
-
name = "WorkspaceEditPathError";
|
|
1901
1916
|
constructor(path, detail) {
|
|
1902
1917
|
super(`${detail}: ${path}`);
|
|
1903
1918
|
this.path = path;
|
|
1904
1919
|
this.detail = detail;
|
|
1920
|
+
this.name = "WorkspaceEditPathError";
|
|
1905
1921
|
}
|
|
1906
1922
|
}
|
|
1907
1923
|
function isPathInsideWorkspace(filePath, workspaceRoot) {
|
|
@@ -2193,13 +2209,11 @@ function canonicalFingerprint(operations) {
|
|
|
2193
2209
|
|
|
2194
2210
|
// ../lsp-core/src/lsp/workspace-edit-types.ts
|
|
2195
2211
|
class WorkspaceEditValidationError extends Error {
|
|
2196
|
-
changeIndex;
|
|
2197
|
-
detail;
|
|
2198
|
-
name = "WorkspaceEditValidationError";
|
|
2199
2212
|
constructor(changeIndex, detail) {
|
|
2200
2213
|
super(`change ${changeIndex}: ${detail}`);
|
|
2201
2214
|
this.changeIndex = changeIndex;
|
|
2202
2215
|
this.detail = detail;
|
|
2216
|
+
this.name = "WorkspaceEditValidationError";
|
|
2203
2217
|
}
|
|
2204
2218
|
}
|
|
2205
2219
|
|
|
@@ -2697,10 +2711,9 @@ function simulateDelete(operation, virtual) {
|
|
|
2697
2711
|
import { existsSync as existsSync5, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
|
|
2698
2712
|
import { dirname as dirname4, resolve as resolve5 } from "node:path";
|
|
2699
2713
|
class WorkspaceSnapshotBuilder {
|
|
2700
|
-
workspaceRoot;
|
|
2701
|
-
snapshots = new Map;
|
|
2702
2714
|
constructor(workspaceRoot) {
|
|
2703
2715
|
this.workspaceRoot = workspaceRoot;
|
|
2716
|
+
this.snapshots = new Map;
|
|
2704
2717
|
}
|
|
2705
2718
|
build(operations) {
|
|
2706
2719
|
this.add(this.workspaceRoot, false);
|
|
@@ -2744,8 +2757,10 @@ function snapshotOperations(operations, workspaceRoot) {
|
|
|
2744
2757
|
|
|
2745
2758
|
// ../lsp-core/src/lsp/workspace-edit-plan.ts
|
|
2746
2759
|
class PlanPathIndex {
|
|
2747
|
-
|
|
2748
|
-
|
|
2760
|
+
constructor() {
|
|
2761
|
+
this.firstChangeByPath = new Map;
|
|
2762
|
+
this.reportedPathByCanonical = new Map;
|
|
2763
|
+
}
|
|
2749
2764
|
build(operations) {
|
|
2750
2765
|
for (const operation of operations) {
|
|
2751
2766
|
switch (operation.kind) {
|
|
@@ -2834,14 +2849,11 @@ function isRecord4(value) {
|
|
|
2834
2849
|
}
|
|
2835
2850
|
|
|
2836
2851
|
class WorkspaceMutationController {
|
|
2837
|
-
workspaceRoot;
|
|
2838
|
-
documents;
|
|
2839
|
-
activeLease = null;
|
|
2840
|
-
nextLeaseId = 1;
|
|
2841
|
-
io;
|
|
2842
2852
|
constructor(workspaceRoot, documents) {
|
|
2843
2853
|
this.workspaceRoot = workspaceRoot;
|
|
2844
2854
|
this.documents = documents;
|
|
2855
|
+
this.activeLease = null;
|
|
2856
|
+
this.nextLeaseId = 1;
|
|
2845
2857
|
}
|
|
2846
2858
|
setIo(io) {
|
|
2847
2859
|
this.io = io;
|
|
@@ -2954,12 +2966,9 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
|
|
|
2954
2966
|
var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
|
|
2955
2967
|
|
|
2956
2968
|
class LspClient extends LspClientConnection {
|
|
2957
|
-
diagnosticPullErrors = [];
|
|
2958
|
-
documents;
|
|
2959
|
-
workspaceMutations;
|
|
2960
|
-
diagnosticsFreshnessTimeoutMs;
|
|
2961
2969
|
constructor(root, server2, options = {}) {
|
|
2962
2970
|
super(root, server2, options);
|
|
2971
|
+
this.diagnosticPullErrors = [];
|
|
2963
2972
|
this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
|
|
2964
2973
|
this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
|
|
2965
2974
|
versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
|
|
@@ -3014,6 +3023,18 @@ class LspClient extends LspClientConnection {
|
|
|
3014
3023
|
textDocument: { uri: pathToFileURL3(absPath).href }
|
|
3015
3024
|
}, options);
|
|
3016
3025
|
}
|
|
3026
|
+
async formatDocument(filePath, options, signal) {
|
|
3027
|
+
if (!this.isDocumentFormattingSupported())
|
|
3028
|
+
return null;
|
|
3029
|
+
const absPath = this.resolveWorkspacePath(filePath);
|
|
3030
|
+
await this.openFile(absPath);
|
|
3031
|
+
const requestOptions = signal === undefined ? {} : { signal };
|
|
3032
|
+
const edits = await this.sendRequest("textDocument/formatting", {
|
|
3033
|
+
textDocument: { uri: pathToFileURL3(absPath).href },
|
|
3034
|
+
options
|
|
3035
|
+
}, requestOptions);
|
|
3036
|
+
return edits ?? [];
|
|
3037
|
+
}
|
|
3017
3038
|
async workspaceSymbols(query, signal) {
|
|
3018
3039
|
const options = signal === undefined ? {} : { signal };
|
|
3019
3040
|
return this.sendRequest("workspace/symbol", { query }, options);
|
|
@@ -3259,18 +3280,16 @@ function awaitWithSignal(promise, signal) {
|
|
|
3259
3280
|
}
|
|
3260
3281
|
|
|
3261
3282
|
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
3283
|
constructor(options = {}) {
|
|
3284
|
+
this.clients = new Map;
|
|
3285
|
+
this.pendingStops = new Map;
|
|
3286
|
+
this.respawnBudgets = new Map;
|
|
3287
|
+
this.reaperHandle = null;
|
|
3288
|
+
this.signalDisposer = null;
|
|
3289
|
+
this.disposed = false;
|
|
3272
3290
|
this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
|
|
3273
3291
|
this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
3292
|
+
this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
|
|
3274
3293
|
this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
|
|
3275
3294
|
this.clientFactory = options.clientFactory ?? ((root, server2) => new LspClient(root, server2));
|
|
3276
3295
|
this.now = options.now ?? (() => Date.now());
|
|
@@ -3290,24 +3309,79 @@ class LspManager {
|
|
|
3290
3309
|
getKey(root, serverId) {
|
|
3291
3310
|
return `${root}::${serverId}`;
|
|
3292
3311
|
}
|
|
3312
|
+
tombstoneStop(key, client) {
|
|
3313
|
+
const stop = stopClientBestEffort(client);
|
|
3314
|
+
this.pendingStops.set(key, stop);
|
|
3315
|
+
stop.finally(() => {
|
|
3316
|
+
if (this.pendingStops.get(key) === stop) {
|
|
3317
|
+
this.pendingStops.delete(key);
|
|
3318
|
+
}
|
|
3319
|
+
});
|
|
3320
|
+
return stop;
|
|
3321
|
+
}
|
|
3322
|
+
recordDeadGeneration(key) {
|
|
3323
|
+
let budget = this.respawnBudgets.get(key);
|
|
3324
|
+
if (budget === undefined) {
|
|
3325
|
+
budget = { deadGenerations: 0, exhaustedAt: null };
|
|
3326
|
+
this.respawnBudgets.set(key, budget);
|
|
3327
|
+
}
|
|
3328
|
+
budget.deadGenerations += 1;
|
|
3329
|
+
}
|
|
3330
|
+
markHealthyGeneration(key) {
|
|
3331
|
+
this.respawnBudgets.delete(key);
|
|
3332
|
+
}
|
|
3333
|
+
ensureRespawnAllowed(key, root, serverId) {
|
|
3334
|
+
const budget = this.respawnBudgets.get(key);
|
|
3335
|
+
if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
|
|
3336
|
+
return;
|
|
3337
|
+
if (budget.exhaustedAt === null) {
|
|
3338
|
+
budget.exhaustedAt = this.now();
|
|
3339
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
3340
|
+
}
|
|
3341
|
+
if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
|
|
3342
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
3343
|
+
}
|
|
3344
|
+
budget.deadGenerations = 0;
|
|
3345
|
+
budget.exhaustedAt = null;
|
|
3346
|
+
}
|
|
3293
3347
|
reapStale() {
|
|
3294
3348
|
const t = this.now();
|
|
3295
3349
|
for (const [key, managed] of this.clients) {
|
|
3296
3350
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3297
|
-
stopClientBestEffort(managed.client);
|
|
3298
3351
|
this.clients.delete(key);
|
|
3352
|
+
this.tombstoneStop(key, managed.client);
|
|
3299
3353
|
continue;
|
|
3300
3354
|
}
|
|
3301
3355
|
if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
|
|
3302
|
-
stopClientBestEffort(managed.client);
|
|
3303
3356
|
this.clients.delete(key);
|
|
3357
|
+
this.tombstoneStop(key, managed.client);
|
|
3304
3358
|
}
|
|
3305
3359
|
}
|
|
3306
3360
|
}
|
|
3361
|
+
evictForAdmission() {
|
|
3362
|
+
while (this.clients.size >= this.maxResidentClients) {
|
|
3363
|
+
const victim = this.leastRecentlyUsedIdleClient();
|
|
3364
|
+
if (!victim)
|
|
3365
|
+
return;
|
|
3366
|
+
this.clients.delete(victim.key);
|
|
3367
|
+
this.tombstoneStop(victim.key, victim.managed.client);
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
leastRecentlyUsedIdleClient() {
|
|
3371
|
+
let candidate = null;
|
|
3372
|
+
for (const [key, managed] of this.clients) {
|
|
3373
|
+
if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
|
|
3374
|
+
continue;
|
|
3375
|
+
if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
|
|
3376
|
+
candidate = { key, managed };
|
|
3377
|
+
}
|
|
3378
|
+
}
|
|
3379
|
+
return candidate;
|
|
3380
|
+
}
|
|
3307
3381
|
async tryDeleteIfOrphaned(key, managed) {
|
|
3308
3382
|
if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
|
|
3309
3383
|
this.clients.delete(key);
|
|
3310
|
-
await
|
|
3384
|
+
await this.tombstoneStop(key, managed.client);
|
|
3311
3385
|
}
|
|
3312
3386
|
}
|
|
3313
3387
|
async getClient(root, server2, signal) {
|
|
@@ -3316,12 +3390,22 @@ class LspManager {
|
|
|
3316
3390
|
}
|
|
3317
3391
|
signal?.throwIfAborted();
|
|
3318
3392
|
const key = this.getKey(root, server2.id);
|
|
3393
|
+
for (;; ) {
|
|
3394
|
+
const pendingStop = this.pendingStops.get(key);
|
|
3395
|
+
if (pendingStop === undefined)
|
|
3396
|
+
break;
|
|
3397
|
+
await awaitWithSignal(pendingStop, signal);
|
|
3398
|
+
signal?.throwIfAborted();
|
|
3399
|
+
}
|
|
3400
|
+
if (this.disposed) {
|
|
3401
|
+
throw new Error("LspManager has been disposed");
|
|
3402
|
+
}
|
|
3319
3403
|
let managed = this.clients.get(key);
|
|
3320
3404
|
if (managed) {
|
|
3321
3405
|
const t = this.now();
|
|
3322
3406
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3323
|
-
await stopClientBestEffort(managed.client);
|
|
3324
3407
|
this.clients.delete(key);
|
|
3408
|
+
await this.tombstoneStop(key, managed.client);
|
|
3325
3409
|
managed = undefined;
|
|
3326
3410
|
}
|
|
3327
3411
|
}
|
|
@@ -3342,14 +3426,20 @@ class LspManager {
|
|
|
3342
3426
|
signal.throwIfAborted();
|
|
3343
3427
|
}
|
|
3344
3428
|
if (!managed.client.isAlive()) {
|
|
3345
|
-
|
|
3346
|
-
this.clients.
|
|
3429
|
+
this.recordDeadGeneration(key);
|
|
3430
|
+
if (this.clients.get(key) === managed) {
|
|
3431
|
+
this.clients.delete(key);
|
|
3432
|
+
}
|
|
3433
|
+
await this.tombstoneStop(key, managed.client);
|
|
3347
3434
|
return this.getClient(root, server2, signal);
|
|
3348
3435
|
}
|
|
3436
|
+
this.markHealthyGeneration(key);
|
|
3349
3437
|
managed.refCount++;
|
|
3350
3438
|
managed.lastUsedAt = this.now();
|
|
3351
3439
|
return managed.client;
|
|
3352
3440
|
}
|
|
3441
|
+
this.evictForAdmission();
|
|
3442
|
+
this.ensureRespawnAllowed(key, root, server2.id);
|
|
3353
3443
|
const client = this.clientFactory(root, server2);
|
|
3354
3444
|
const initStartedAt = this.now();
|
|
3355
3445
|
const initPromise = (async () => {
|
|
@@ -3373,7 +3463,7 @@ class LspManager {
|
|
|
3373
3463
|
if (this.clients.get(key) === newManaged) {
|
|
3374
3464
|
this.clients.delete(key);
|
|
3375
3465
|
}
|
|
3376
|
-
await
|
|
3466
|
+
await this.tombstoneStop(key, client);
|
|
3377
3467
|
throw err;
|
|
3378
3468
|
}
|
|
3379
3469
|
newManaged.pendingWaiters--;
|
|
@@ -3384,6 +3474,15 @@ class LspManager {
|
|
|
3384
3474
|
await this.tryDeleteIfOrphaned(key, newManaged);
|
|
3385
3475
|
signal.throwIfAborted();
|
|
3386
3476
|
}
|
|
3477
|
+
if (!client.isAlive()) {
|
|
3478
|
+
this.recordDeadGeneration(key);
|
|
3479
|
+
if (this.clients.get(key) === newManaged) {
|
|
3480
|
+
this.clients.delete(key);
|
|
3481
|
+
}
|
|
3482
|
+
await this.tombstoneStop(key, client);
|
|
3483
|
+
return this.getClient(root, server2, signal);
|
|
3484
|
+
}
|
|
3485
|
+
this.markHealthyGeneration(key);
|
|
3387
3486
|
newManaged.refCount++;
|
|
3388
3487
|
newManaged.lastUsedAt = this.now();
|
|
3389
3488
|
return client;
|
|
@@ -3404,14 +3503,20 @@ class LspManager {
|
|
|
3404
3503
|
if (client && managed.client !== client)
|
|
3405
3504
|
return;
|
|
3406
3505
|
this.clients.delete(key);
|
|
3407
|
-
|
|
3506
|
+
this.tombstoneStop(key, managed.client);
|
|
3408
3507
|
}
|
|
3409
3508
|
warmupClient(root, server2) {
|
|
3410
3509
|
if (this.disposed)
|
|
3411
3510
|
return;
|
|
3412
3511
|
const key = this.getKey(root, server2.id);
|
|
3413
|
-
if (this.clients.has(key))
|
|
3512
|
+
if (this.clients.has(key) || this.pendingStops.has(key))
|
|
3513
|
+
return;
|
|
3514
|
+
this.evictForAdmission();
|
|
3515
|
+
try {
|
|
3516
|
+
this.ensureRespawnAllowed(key, root, server2.id);
|
|
3517
|
+
} catch {
|
|
3414
3518
|
return;
|
|
3519
|
+
}
|
|
3415
3520
|
const client = this.clientFactory(root, server2);
|
|
3416
3521
|
const initStartedAt = this.now();
|
|
3417
3522
|
const initPromise = (async () => {
|
|
@@ -3437,7 +3542,7 @@ class LspManager {
|
|
|
3437
3542
|
if (this.clients.get(key) === managed) {
|
|
3438
3543
|
this.clients.delete(key);
|
|
3439
3544
|
}
|
|
3440
|
-
|
|
3545
|
+
this.tombstoneStop(key, client);
|
|
3441
3546
|
});
|
|
3442
3547
|
}
|
|
3443
3548
|
isServerInitializing(root, serverId) {
|
|
@@ -3481,8 +3586,11 @@ class LspManager {
|
|
|
3481
3586
|
for (const managed of this.clients.values()) {
|
|
3482
3587
|
stopPromises.push(stopClientBestEffort(managed.client));
|
|
3483
3588
|
}
|
|
3589
|
+
const tombstonedStops = [...this.pendingStops.values()];
|
|
3484
3590
|
this.clients.clear();
|
|
3485
|
-
|
|
3591
|
+
this.respawnBudgets.clear();
|
|
3592
|
+
await Promise.allSettled([...stopPromises, ...tombstonedStops]);
|
|
3593
|
+
this.pendingStops.clear();
|
|
3486
3594
|
}
|
|
3487
3595
|
}
|
|
3488
3596
|
var _defaultInstance = null;
|
|
@@ -3500,57 +3608,52 @@ async function disposeDefaultLspManager() {
|
|
|
3500
3608
|
}
|
|
3501
3609
|
}
|
|
3502
3610
|
|
|
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
|
-
|
|
3611
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
3612
|
+
import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
|
|
3613
|
+
import { dirname as dirname5, join as join3 } from "node:path";
|
|
3614
|
+
|
|
3615
|
+
// ../lsp-core/src/lsp/workspace-markers.ts
|
|
3616
|
+
var GIT_WORKSPACE_MARKER = ".git";
|
|
3617
|
+
var PROJECT_WORKSPACE_MARKERS = [
|
|
3618
|
+
"package.json",
|
|
3619
|
+
"pyproject.toml",
|
|
3620
|
+
"Cargo.toml",
|
|
3621
|
+
"go.mod",
|
|
3622
|
+
"pom.xml",
|
|
3623
|
+
"build.gradle"
|
|
3624
|
+
];
|
|
3625
|
+
var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
|
|
3626
|
+
|
|
3627
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
3628
|
+
function findWorkspaceRootOutsideContext(directory) {
|
|
3629
|
+
const marked = nearestMarkedAncestor(directory);
|
|
3630
|
+
if (marked !== undefined)
|
|
3631
|
+
return marked;
|
|
3632
|
+
return realpathSync4(nearestExistingAncestor(directory));
|
|
3633
|
+
}
|
|
3634
|
+
function nearestMarkedAncestor(directory) {
|
|
3635
|
+
let current = directory;
|
|
3636
|
+
for (;; ) {
|
|
3637
|
+
if (existsSync6(current) && WORKSPACE_MARKERS.some((marker) => existsSync6(join3(current, marker)))) {
|
|
3638
|
+
return realpathSync4(current);
|
|
3639
|
+
}
|
|
3640
|
+
const parent = dirname5(current);
|
|
3641
|
+
if (parent === current)
|
|
3642
|
+
return;
|
|
3643
|
+
current = parent;
|
|
3518
3644
|
}
|
|
3519
3645
|
}
|
|
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);
|
|
3646
|
+
function nearestExistingAncestor(directory) {
|
|
3647
|
+
let current = directory;
|
|
3648
|
+
while (!existsSync6(current)) {
|
|
3649
|
+
const parent = dirname5(current);
|
|
3650
|
+
if (parent === current)
|
|
3651
|
+
return current;
|
|
3652
|
+
current = parent;
|
|
3653
|
+
}
|
|
3654
|
+
return current;
|
|
3549
3655
|
}
|
|
3550
3656
|
|
|
3551
|
-
// ../lsp-core/src/lsp/config-loader.ts
|
|
3552
|
-
import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
|
|
3553
|
-
|
|
3554
3657
|
// ../lsp-core/src/lsp/server-definitions.ts
|
|
3555
3658
|
var LSP_INSTALL_HINTS = {
|
|
3556
3659
|
typescript: "npm install -g typescript-language-server typescript",
|
|
@@ -3596,6 +3699,26 @@ var LSP_INSTALL_HINTS = {
|
|
|
3596
3699
|
julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
|
|
3597
3700
|
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
3701
|
};
|
|
3702
|
+
var LSP_LOCAL_INSTALL_HINTS = {
|
|
3703
|
+
typescript: "bun add -d typescript-language-server typescript",
|
|
3704
|
+
vue: "bun add -d @vue/language-server",
|
|
3705
|
+
eslint: "bun add -d vscode-langservers-extracted",
|
|
3706
|
+
oxlint: "bun add -d oxlint",
|
|
3707
|
+
biome: "bun add -d @biomejs/biome",
|
|
3708
|
+
svelte: "bun add -d svelte-language-server",
|
|
3709
|
+
astro: "bun add -d @astrojs/language-server",
|
|
3710
|
+
bash: "bun add -d bash-language-server",
|
|
3711
|
+
"bash-ls": "bun add -d bash-language-server",
|
|
3712
|
+
"yaml-ls": "bun add -d yaml-language-server",
|
|
3713
|
+
php: "bun add -d intelephense",
|
|
3714
|
+
prisma: "bun add -d prisma",
|
|
3715
|
+
dockerfile: "bun add -d dockerfile-language-server-nodejs",
|
|
3716
|
+
pyright: "uv add --dev pyright",
|
|
3717
|
+
basedpyright: "uv add --dev basedpyright",
|
|
3718
|
+
ruff: "uv add --dev ruff",
|
|
3719
|
+
ty: "uv add --dev ty",
|
|
3720
|
+
"ruby-lsp": "bundle add ruby-lsp --group development"
|
|
3721
|
+
};
|
|
3599
3722
|
var BUILTIN_SERVERS = {
|
|
3600
3723
|
typescript: {
|
|
3601
3724
|
command: ["typescript-language-server", "--stdio"],
|
|
@@ -3698,7 +3821,56 @@ var BUILTIN_SERVERS = {
|
|
|
3698
3821
|
}
|
|
3699
3822
|
};
|
|
3700
3823
|
|
|
3824
|
+
// ../lsp-core/src/lsp/server-install-state.ts
|
|
3825
|
+
import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
3826
|
+
import { dirname as dirname6 } from "node:path";
|
|
3827
|
+
function getInstallDecisionsPath() {
|
|
3828
|
+
return lspRequestContext().installDecisionsPath;
|
|
3829
|
+
}
|
|
3830
|
+
function loadInstallDecisions() {
|
|
3831
|
+
const path = getInstallDecisionsPath();
|
|
3832
|
+
if (!existsSync7(path))
|
|
3833
|
+
return {};
|
|
3834
|
+
try {
|
|
3835
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
3836
|
+
return isInstallDecisions(parsed) ? parsed : {};
|
|
3837
|
+
} catch {
|
|
3838
|
+
return {};
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
function loadInstallDecision(serverId) {
|
|
3842
|
+
return loadInstallDecisions()[serverId];
|
|
3843
|
+
}
|
|
3844
|
+
function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
|
|
3845
|
+
const decisions = loadInstallDecisions();
|
|
3846
|
+
decisions[serverId] = { decision, decidedAt };
|
|
3847
|
+
writeInstallDecisions(decisions);
|
|
3848
|
+
}
|
|
3849
|
+
function isInstallDecision(value) {
|
|
3850
|
+
return value === "declined" || value === "allowed";
|
|
3851
|
+
}
|
|
3852
|
+
function writeInstallDecisions(decisions) {
|
|
3853
|
+
const path = getInstallDecisionsPath();
|
|
3854
|
+
mkdirSync(dirname6(path), { recursive: true });
|
|
3855
|
+
const tmpPath = `${path}.tmp`;
|
|
3856
|
+
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
3857
|
+
`, "utf8");
|
|
3858
|
+
renameSync2(tmpPath, path);
|
|
3859
|
+
}
|
|
3860
|
+
function isInstallDecisions(value) {
|
|
3861
|
+
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
3862
|
+
}
|
|
3863
|
+
function isInstallDecisionRecord(value) {
|
|
3864
|
+
if (!isRecord5(value))
|
|
3865
|
+
return false;
|
|
3866
|
+
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
3867
|
+
}
|
|
3868
|
+
function isRecord5(value) {
|
|
3869
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3870
|
+
}
|
|
3871
|
+
|
|
3701
3872
|
// ../lsp-core/src/lsp/config-loader.ts
|
|
3873
|
+
import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
|
|
3702
3874
|
function getProjectConfigPaths() {
|
|
3703
3875
|
return lspRequestContext().projectConfigPaths;
|
|
3704
3876
|
}
|
|
@@ -3706,7 +3878,7 @@ function getUserConfigPath() {
|
|
|
3706
3878
|
return lspRequestContext().userConfigPath;
|
|
3707
3879
|
}
|
|
3708
3880
|
function loadJsonFile(path) {
|
|
3709
|
-
if (!
|
|
3881
|
+
if (!existsSync8(path))
|
|
3710
3882
|
return null;
|
|
3711
3883
|
try {
|
|
3712
3884
|
const parsed = JSON.parse(readFileSync4(path, "utf-8"));
|
|
@@ -3894,54 +4066,155 @@ function getDisabledServerIds() {
|
|
|
3894
4066
|
}
|
|
3895
4067
|
|
|
3896
4068
|
// ../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
|
-
|
|
4069
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
4070
|
+
import { delimiter as delimiter3, dirname as dirname7, isAbsolute as isAbsolute3, join as join4, resolve as resolve7 } from "node:path";
|
|
4071
|
+
var LOCAL_BIN_RULES = [
|
|
4072
|
+
{
|
|
4073
|
+
markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
|
|
4074
|
+
binDirs: [join4("node_modules", ".bin")]
|
|
4075
|
+
},
|
|
4076
|
+
{
|
|
4077
|
+
markers: [
|
|
4078
|
+
"pyproject.toml",
|
|
4079
|
+
"ty.toml",
|
|
4080
|
+
"requirements.txt",
|
|
4081
|
+
"setup.py",
|
|
4082
|
+
"setup.cfg",
|
|
4083
|
+
"Pipfile",
|
|
4084
|
+
"pyrightconfig.json",
|
|
4085
|
+
"ruff.toml",
|
|
4086
|
+
".ruff.toml"
|
|
4087
|
+
],
|
|
4088
|
+
binDirs: [
|
|
4089
|
+
join4(".venv", "bin"),
|
|
4090
|
+
join4(".venv", "Scripts"),
|
|
4091
|
+
join4("venv", "bin"),
|
|
4092
|
+
join4("venv", "Scripts"),
|
|
4093
|
+
join4(".env", "bin"),
|
|
4094
|
+
join4(".env", "Scripts")
|
|
4095
|
+
]
|
|
4096
|
+
},
|
|
4097
|
+
{
|
|
4098
|
+
markers: ["Gemfile", "Gemfile.lock"],
|
|
4099
|
+
binDirs: [join4("vendor", "bundle", "bin"), "bin"]
|
|
4100
|
+
},
|
|
4101
|
+
{
|
|
4102
|
+
markers: ["go.mod", "go.sum", "go.work"],
|
|
4103
|
+
binDirs: ["bin"]
|
|
4104
|
+
}
|
|
4105
|
+
];
|
|
4106
|
+
var resolutionCache = new Map;
|
|
4107
|
+
var probeCount = 0;
|
|
4108
|
+
function probe(path) {
|
|
4109
|
+
probeCount += 1;
|
|
4110
|
+
return existsSync9(path);
|
|
4111
|
+
}
|
|
4112
|
+
function executableSuffixes(platform, pathExt) {
|
|
4113
|
+
if (platform !== "win32")
|
|
4114
|
+
return [""];
|
|
4115
|
+
const configured = pathExt ?? process.env["PATHEXT"] ?? "";
|
|
4116
|
+
const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
|
|
4117
|
+
return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
|
|
4118
|
+
}
|
|
4119
|
+
function probeWithSuffixes(directory, command, suffixes) {
|
|
4120
|
+
for (const suffix of suffixes) {
|
|
4121
|
+
const candidate = join4(directory, command + suffix);
|
|
4122
|
+
if (probe(candidate))
|
|
4123
|
+
return candidate;
|
|
3908
4124
|
}
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
4125
|
+
return null;
|
|
4126
|
+
}
|
|
4127
|
+
function resolveLocal(command, workingDirectory, suffixes, stopAt) {
|
|
4128
|
+
const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
|
|
4129
|
+
let current = resolve7(workingDirectory);
|
|
4130
|
+
while (true) {
|
|
4131
|
+
for (const rule of LOCAL_BIN_RULES) {
|
|
4132
|
+
if (!rule.markers.some((marker) => probe(join4(current, marker))))
|
|
4133
|
+
continue;
|
|
4134
|
+
for (const binDir of rule.binDirs) {
|
|
4135
|
+
const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
|
|
4136
|
+
if (found !== null)
|
|
4137
|
+
return found;
|
|
4138
|
+
}
|
|
3918
4139
|
}
|
|
4140
|
+
if (probe(join4(current, ".git")))
|
|
4141
|
+
return null;
|
|
4142
|
+
if (boundary !== undefined && current === boundary)
|
|
4143
|
+
return null;
|
|
4144
|
+
const parent = dirname7(current);
|
|
4145
|
+
if (parent === current)
|
|
4146
|
+
return null;
|
|
4147
|
+
current = parent;
|
|
3919
4148
|
}
|
|
3920
|
-
|
|
3921
|
-
|
|
4149
|
+
}
|
|
4150
|
+
function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
|
|
4151
|
+
let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
|
|
4152
|
+
if (platform === "win32" && !pathEnv) {
|
|
3922
4153
|
pathEnv = process.env["Path"] ?? "";
|
|
3923
4154
|
}
|
|
3924
|
-
const
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
}
|
|
4155
|
+
for (const entry of pathEnv.split(delimiter3)) {
|
|
4156
|
+
if (entry.length === 0)
|
|
4157
|
+
continue;
|
|
4158
|
+
const found = probeWithSuffixes(entry, command, suffixes);
|
|
4159
|
+
if (found !== null)
|
|
4160
|
+
return found;
|
|
3931
4161
|
}
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
4162
|
+
return null;
|
|
4163
|
+
}
|
|
4164
|
+
function resolveServerBinary(command, workingDirectory, options = {}) {
|
|
4165
|
+
if (command.length === 0)
|
|
4166
|
+
return null;
|
|
4167
|
+
const [cmd] = command;
|
|
4168
|
+
if (cmd === undefined || cmd.length === 0)
|
|
4169
|
+
return null;
|
|
4170
|
+
const platform = options.platform ?? process.platform;
|
|
4171
|
+
const suffixes = executableSuffixes(platform, options.pathExt);
|
|
4172
|
+
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
4173
|
+
const explicit = isAbsolute3(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
|
|
4174
|
+
return probe(explicit) ? explicit : null;
|
|
4175
|
+
}
|
|
4176
|
+
const cacheKey = JSON.stringify([
|
|
4177
|
+
workingDirectory ?? "",
|
|
4178
|
+
cmd,
|
|
4179
|
+
platform,
|
|
4180
|
+
options.stopAt ?? "",
|
|
4181
|
+
options.pathExt ?? "",
|
|
4182
|
+
options.pathEnv ?? process.env["PATH"] ?? ""
|
|
4183
|
+
]);
|
|
4184
|
+
const cached = resolutionCache.get(cacheKey);
|
|
4185
|
+
if (cached !== undefined)
|
|
4186
|
+
return cached;
|
|
4187
|
+
let resolved = null;
|
|
4188
|
+
if (workingDirectory !== undefined && workingDirectory.length > 0) {
|
|
4189
|
+
resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
|
|
4190
|
+
}
|
|
4191
|
+
resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
|
|
4192
|
+
if (resolved === null && cmd === "node")
|
|
4193
|
+
resolved = cmd;
|
|
4194
|
+
resolutionCache.set(cacheKey, resolved);
|
|
4195
|
+
return resolved;
|
|
4196
|
+
}
|
|
4197
|
+
function isServerInstalled(command, workingDirectory, options = {}) {
|
|
4198
|
+
if (command.length === 0)
|
|
4199
|
+
return false;
|
|
4200
|
+
return resolveServerBinary(command, workingDirectory, options) !== null;
|
|
3935
4201
|
}
|
|
3936
4202
|
|
|
3937
4203
|
// ../lsp-core/src/lsp/server-resolution.ts
|
|
4204
|
+
function withResolvedCommand(command, binaryPath) {
|
|
4205
|
+
return [binaryPath, ...command.slice(1)];
|
|
4206
|
+
}
|
|
3938
4207
|
function findServerForExtension(ext) {
|
|
3939
4208
|
const servers = getMergedServers();
|
|
4209
|
+
const workingDirectory = contextCwd();
|
|
3940
4210
|
for (const server2 of servers) {
|
|
3941
|
-
if (server2.extensions.includes(ext)
|
|
4211
|
+
if (!server2.extensions.includes(ext))
|
|
4212
|
+
continue;
|
|
4213
|
+
const binaryPath = resolveServerBinary(server2.command, workingDirectory);
|
|
4214
|
+
if (binaryPath !== null) {
|
|
3942
4215
|
const resolvedServer = {
|
|
3943
4216
|
id: server2.id,
|
|
3944
|
-
command: server2.command,
|
|
4217
|
+
command: withResolvedCommand(server2.command, binaryPath),
|
|
3945
4218
|
extensions: server2.extensions,
|
|
3946
4219
|
priority: server2.priority
|
|
3947
4220
|
};
|
|
@@ -3988,6 +4261,7 @@ function findServerForExtension(ext) {
|
|
|
3988
4261
|
function getAllServers() {
|
|
3989
4262
|
const servers = getMergedServers();
|
|
3990
4263
|
const disabled = getDisabledServerIds();
|
|
4264
|
+
const workingDirectory = contextCwd();
|
|
3991
4265
|
const result = [];
|
|
3992
4266
|
const seen = new Set;
|
|
3993
4267
|
for (const server2 of servers) {
|
|
@@ -3995,7 +4269,7 @@ function getAllServers() {
|
|
|
3995
4269
|
continue;
|
|
3996
4270
|
result.push({
|
|
3997
4271
|
id: server2.id,
|
|
3998
|
-
installed: isServerInstalled(server2.command),
|
|
4272
|
+
installed: isServerInstalled(server2.command, workingDirectory),
|
|
3999
4273
|
extensions: server2.extensions,
|
|
4000
4274
|
disabled: false,
|
|
4001
4275
|
source: server2.source,
|
|
@@ -4009,7 +4283,7 @@ function getAllServers() {
|
|
|
4009
4283
|
const builtin = BUILTIN_SERVERS[id];
|
|
4010
4284
|
result.push({
|
|
4011
4285
|
id,
|
|
4012
|
-
installed: builtin ? isServerInstalled(builtin.command) : false,
|
|
4286
|
+
installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
|
|
4013
4287
|
extensions: builtin?.extensions ?? [],
|
|
4014
4288
|
disabled: true,
|
|
4015
4289
|
source: "disabled",
|
|
@@ -4020,7 +4294,6 @@ function getAllServers() {
|
|
|
4020
4294
|
}
|
|
4021
4295
|
|
|
4022
4296
|
// ../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
4297
|
function isDirectoryPath(filePath) {
|
|
4025
4298
|
try {
|
|
4026
4299
|
return statSync3(filePath).isDirectory();
|
|
@@ -4029,32 +4302,90 @@ function isDirectoryPath(filePath) {
|
|
|
4029
4302
|
}
|
|
4030
4303
|
}
|
|
4031
4304
|
function findWorkspaceRoot(filePath) {
|
|
4032
|
-
const
|
|
4305
|
+
const cwd = contextCwd();
|
|
4306
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4033
4307
|
let dir = abs;
|
|
4034
4308
|
if (!isDirectoryPath(dir)) {
|
|
4035
|
-
dir =
|
|
4036
|
-
}
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4309
|
+
dir = dirname8(dir);
|
|
4310
|
+
}
|
|
4311
|
+
if (!isPathInside(cwd, abs))
|
|
4312
|
+
return findWorkspaceRootOutsideContext(dir);
|
|
4313
|
+
const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
|
|
4314
|
+
let nearestPackageRoot;
|
|
4315
|
+
while (isPathInside(cwd, dir)) {
|
|
4316
|
+
const canonicalDir = existingDirectoryInsideContext(dir, cwd);
|
|
4317
|
+
if (canonicalDir !== undefined) {
|
|
4318
|
+
if (existsSync10(join5(dir, GIT_WORKSPACE_MARKER))) {
|
|
4319
|
+
return canonicalDir;
|
|
4320
|
+
}
|
|
4321
|
+
if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
|
|
4322
|
+
nearestPackageRoot = canonicalDir;
|
|
4042
4323
|
}
|
|
4043
4324
|
}
|
|
4044
|
-
|
|
4045
|
-
|
|
4325
|
+
if (dir === cwd)
|
|
4326
|
+
break;
|
|
4327
|
+
dir = dirname8(dir);
|
|
4046
4328
|
}
|
|
4047
|
-
return
|
|
4329
|
+
return nearestPackageRoot ?? fallbackRoot;
|
|
4330
|
+
}
|
|
4331
|
+
function hasProjectWorkspaceMarker(directory) {
|
|
4332
|
+
return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync10(join5(directory, marker)));
|
|
4333
|
+
}
|
|
4334
|
+
function resolveReadablePathInsideContext(filePath) {
|
|
4335
|
+
const cwd = contextCwd();
|
|
4336
|
+
const abs = resolve8(cwd, filePath);
|
|
4337
|
+
if (isPathInside(cwd, abs))
|
|
4338
|
+
return abs;
|
|
4339
|
+
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
4340
|
+
if (rebased !== undefined)
|
|
4341
|
+
return rebased;
|
|
4342
|
+
return canonicalizeExistingOrNearestAncestor(abs);
|
|
4048
4343
|
}
|
|
4049
4344
|
function resolvePathInsideContext(filePath) {
|
|
4050
4345
|
const cwd = contextCwd();
|
|
4051
|
-
const abs =
|
|
4346
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4052
4347
|
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
4053
4348
|
if (!isPathInside(cwd, canonical)) {
|
|
4054
4349
|
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4055
4350
|
}
|
|
4056
4351
|
return canonical;
|
|
4057
4352
|
}
|
|
4353
|
+
function rebaseThroughCanonicalAncestor(path, cwd) {
|
|
4354
|
+
let current = path;
|
|
4355
|
+
const suffix = [];
|
|
4356
|
+
while (true) {
|
|
4357
|
+
if (existsSync10(current)) {
|
|
4358
|
+
const canonical = realpathSync5(current);
|
|
4359
|
+
if (isPathInside(cwd, canonical))
|
|
4360
|
+
return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
|
|
4361
|
+
}
|
|
4362
|
+
const parent = dirname8(current);
|
|
4363
|
+
if (parent === current)
|
|
4364
|
+
return;
|
|
4365
|
+
suffix.unshift(basename3(current));
|
|
4366
|
+
current = parent;
|
|
4367
|
+
}
|
|
4368
|
+
}
|
|
4369
|
+
function existingDirectoryInsideContext(directory, cwd) {
|
|
4370
|
+
if (!existsSync10(directory))
|
|
4371
|
+
return;
|
|
4372
|
+
const canonical = realpathSync5(directory);
|
|
4373
|
+
if (!statSync3(canonical).isDirectory())
|
|
4374
|
+
return;
|
|
4375
|
+
return isPathInside(cwd, canonical) ? canonical : undefined;
|
|
4376
|
+
}
|
|
4377
|
+
function nearestExistingDirectoryInsideContext(directory, cwd) {
|
|
4378
|
+
let current = directory;
|
|
4379
|
+
while (isPathInside(cwd, current)) {
|
|
4380
|
+
const canonical = existingDirectoryInsideContext(current, cwd);
|
|
4381
|
+
if (canonical !== undefined)
|
|
4382
|
+
return canonical;
|
|
4383
|
+
if (current === cwd)
|
|
4384
|
+
return;
|
|
4385
|
+
current = dirname8(current);
|
|
4386
|
+
}
|
|
4387
|
+
return;
|
|
4388
|
+
}
|
|
4058
4389
|
function formatServerLookupError(result) {
|
|
4059
4390
|
if (result.status === "not_installed") {
|
|
4060
4391
|
return formatNotInstalled(result);
|
|
@@ -4078,6 +4409,19 @@ function formatServerLookupError(result) {
|
|
|
4078
4409
|
].join(`
|
|
4079
4410
|
`);
|
|
4080
4411
|
}
|
|
4412
|
+
function formatInstallOptions(serverId, installHint) {
|
|
4413
|
+
const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
|
|
4414
|
+
if (localHint === undefined) {
|
|
4415
|
+
return ["To install, run:", ` ${installHint}`];
|
|
4416
|
+
}
|
|
4417
|
+
return [
|
|
4418
|
+
"To install in THIS repository (preferred — no global install needed):",
|
|
4419
|
+
` ${localHint}`,
|
|
4420
|
+
"",
|
|
4421
|
+
"Or install it globally:",
|
|
4422
|
+
` ${installHint}`
|
|
4423
|
+
];
|
|
4424
|
+
}
|
|
4081
4425
|
function formatNotInstalled(result) {
|
|
4082
4426
|
const { server: server2, installHint } = result;
|
|
4083
4427
|
const extensions = server2.extensions.join(", ");
|
|
@@ -4092,19 +4436,19 @@ function formatNotInstalled(result) {
|
|
|
4092
4436
|
`Command not found: ${server2.command[0]}`,
|
|
4093
4437
|
""
|
|
4094
4438
|
];
|
|
4439
|
+
const installOptions = formatInstallOptions(server2.id, installHint);
|
|
4095
4440
|
if (decision === "allowed") {
|
|
4096
4441
|
return [
|
|
4097
4442
|
...header,
|
|
4098
4443
|
"The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
|
|
4099
|
-
|
|
4444
|
+
...installOptions.slice(1)
|
|
4100
4445
|
].join(`
|
|
4101
4446
|
`);
|
|
4102
4447
|
}
|
|
4103
4448
|
if (!context.capabilities.installDecisionTool) {
|
|
4104
4449
|
return [
|
|
4105
4450
|
...header,
|
|
4106
|
-
|
|
4107
|
-
` ${installHint}`,
|
|
4451
|
+
...installOptions,
|
|
4108
4452
|
"",
|
|
4109
4453
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4110
4454
|
"Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
|
|
@@ -4113,8 +4457,7 @@ function formatNotInstalled(result) {
|
|
|
4113
4457
|
}
|
|
4114
4458
|
return [
|
|
4115
4459
|
...header,
|
|
4116
|
-
|
|
4117
|
-
` ${installHint}`,
|
|
4460
|
+
...installOptions,
|
|
4118
4461
|
"",
|
|
4119
4462
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4120
4463
|
"- If the user agrees: run the install command above, then retry this tool.",
|
|
@@ -4125,7 +4468,7 @@ function formatNotInstalled(result) {
|
|
|
4125
4468
|
].join(`
|
|
4126
4469
|
`);
|
|
4127
4470
|
}
|
|
4128
|
-
var
|
|
4471
|
+
var READ_ONLY_TOOLS = new Set([
|
|
4129
4472
|
"diagnostics",
|
|
4130
4473
|
"definition",
|
|
4131
4474
|
"references",
|
|
@@ -4134,7 +4477,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
|
|
|
4134
4477
|
"prepareRename"
|
|
4135
4478
|
]);
|
|
4136
4479
|
async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
4137
|
-
const absPath = resolvePathInsideContext(filePath);
|
|
4480
|
+
const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
|
|
4138
4481
|
if (isDirectoryPath(absPath)) {
|
|
4139
4482
|
throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
|
|
4140
4483
|
}
|
|
@@ -4149,9 +4492,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4149
4492
|
const acquireAndCall = async (allowRetry) => {
|
|
4150
4493
|
const client = await manager.getClient(root, server2, options.signal);
|
|
4151
4494
|
try {
|
|
4152
|
-
return await fn(client, root);
|
|
4495
|
+
return await fn(client, root, absPath);
|
|
4153
4496
|
} catch (err) {
|
|
4154
|
-
if (allowRetry &&
|
|
4497
|
+
if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
|
|
4155
4498
|
manager.invalidateClient(root, server2.id, client);
|
|
4156
4499
|
return acquireAndCall(false);
|
|
4157
4500
|
}
|
|
@@ -4169,8 +4512,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4169
4512
|
}
|
|
4170
4513
|
|
|
4171
4514
|
// ../lsp-core/src/lsp/directory-diagnostics.ts
|
|
4172
|
-
import { existsSync as
|
|
4173
|
-
import { join as
|
|
4515
|
+
import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
|
|
4516
|
+
import { join as join6, resolve as resolve9 } from "node:path";
|
|
4174
4517
|
|
|
4175
4518
|
// ../lsp-core/src/lsp/formatters.ts
|
|
4176
4519
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -4300,7 +4643,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
|
|
|
4300
4643
|
for (const entry of entries) {
|
|
4301
4644
|
if (files.length >= maxFiles)
|
|
4302
4645
|
return;
|
|
4303
|
-
const fullPath =
|
|
4646
|
+
const fullPath = join6(currentDir, entry);
|
|
4304
4647
|
let stat;
|
|
4305
4648
|
try {
|
|
4306
4649
|
stat = lstatSync4(fullPath);
|
|
@@ -4325,8 +4668,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4325
4668
|
if (!extension.startsWith(".")) {
|
|
4326
4669
|
throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
|
|
4327
4670
|
}
|
|
4328
|
-
const absDir =
|
|
4329
|
-
if (!
|
|
4671
|
+
const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
|
|
4672
|
+
if (!existsSync11(absDir)) {
|
|
4330
4673
|
throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
|
|
4331
4674
|
}
|
|
4332
4675
|
const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
|
|
@@ -4413,7 +4756,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4413
4756
|
|
|
4414
4757
|
// ../lsp-core/src/lsp/infer-extension.ts
|
|
4415
4758
|
import { lstatSync as lstatSync5, readdirSync as readdirSync4 } from "node:fs";
|
|
4416
|
-
import { join as
|
|
4759
|
+
import { join as join7 } from "node:path";
|
|
4417
4760
|
var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
|
|
4418
4761
|
var MAX_SCAN_ENTRIES = 500;
|
|
4419
4762
|
function inferExtensionFromDirectory(directory) {
|
|
@@ -4431,7 +4774,7 @@ function inferExtensionFromDirectory(directory) {
|
|
|
4431
4774
|
for (const entry of entries) {
|
|
4432
4775
|
if (scanned >= MAX_SCAN_ENTRIES)
|
|
4433
4776
|
return;
|
|
4434
|
-
const fullPath =
|
|
4777
|
+
const fullPath = join7(dir, entry);
|
|
4435
4778
|
let stat;
|
|
4436
4779
|
try {
|
|
4437
4780
|
stat = lstatSync5(fullPath);
|
|
@@ -4606,7 +4949,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4606
4949
|
const filePath = requireString(params, "filePath");
|
|
4607
4950
|
const severity = severityFilter(params);
|
|
4608
4951
|
try {
|
|
4609
|
-
const absPath =
|
|
4952
|
+
const absPath = resolveReadablePathInsideContext(filePath);
|
|
4610
4953
|
if (isDirectoryPath(absPath)) {
|
|
4611
4954
|
const extension = inferExtensionFromDirectory(absPath);
|
|
4612
4955
|
if (!extension) {
|
|
@@ -4635,7 +4978,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4635
4978
|
};
|
|
4636
4979
|
return text(output2.output, details2);
|
|
4637
4980
|
}
|
|
4638
|
-
const result = await withLspClient(filePath, async (client) => client.diagnostics(
|
|
4981
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
|
|
4639
4982
|
if (result.transientError) {
|
|
4640
4983
|
const message = result.transientError.message;
|
|
4641
4984
|
const details2 = {
|
|
@@ -4682,6 +5025,96 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4682
5025
|
throw error;
|
|
4683
5026
|
}
|
|
4684
5027
|
}
|
|
5028
|
+
// ../lsp-core/src/lsp/format-document.ts
|
|
5029
|
+
import { readFileSync as readFileSync5, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
5030
|
+
var DEFAULT_FORMATTING_OPTIONS = {
|
|
5031
|
+
tabSize: 4,
|
|
5032
|
+
insertSpaces: false,
|
|
5033
|
+
trimTrailingWhitespace: true,
|
|
5034
|
+
insertFinalNewline: true,
|
|
5035
|
+
trimFinalNewlines: true
|
|
5036
|
+
};
|
|
5037
|
+
var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
|
|
5038
|
+
async function formatDocumentWithClient(client, filePath, options = {}) {
|
|
5039
|
+
const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
|
|
5040
|
+
if (edits === null)
|
|
5041
|
+
return { status: "unavailable", reason: "capability_not_advertised" };
|
|
5042
|
+
if (edits.length === 0)
|
|
5043
|
+
return UNCHANGED;
|
|
5044
|
+
const before = readFileSync5(filePath, "utf-8");
|
|
5045
|
+
const normalized = normalizeTextEdits(before, edits, 0);
|
|
5046
|
+
if (normalized.text === before)
|
|
5047
|
+
return UNCHANGED;
|
|
5048
|
+
writeAtomically(filePath, normalized.text);
|
|
5049
|
+
await client.openFile(filePath);
|
|
5050
|
+
return {
|
|
5051
|
+
status: "formatted",
|
|
5052
|
+
...lineDelta(normalized.edits)
|
|
5053
|
+
};
|
|
5054
|
+
}
|
|
5055
|
+
function lineDelta(edits) {
|
|
5056
|
+
let linesAdded = 0;
|
|
5057
|
+
let linesRemoved = 0;
|
|
5058
|
+
for (const edit of edits) {
|
|
5059
|
+
linesRemoved += edit.range.end.line - edit.range.start.line + 1;
|
|
5060
|
+
linesAdded += edit.newText.split(`
|
|
5061
|
+
`).length;
|
|
5062
|
+
}
|
|
5063
|
+
return { linesAdded, linesRemoved };
|
|
5064
|
+
}
|
|
5065
|
+
function writeAtomically(filePath, content) {
|
|
5066
|
+
const tempPath = `${filePath}.omo-format.tmp`;
|
|
5067
|
+
writeFileSync3(tempPath, content, "utf-8");
|
|
5068
|
+
try {
|
|
5069
|
+
renameSync3(tempPath, filePath);
|
|
5070
|
+
} catch (error) {
|
|
5071
|
+
try {
|
|
5072
|
+
unlinkSync(tempPath);
|
|
5073
|
+
} catch {}
|
|
5074
|
+
throw error;
|
|
5075
|
+
}
|
|
5076
|
+
}
|
|
5077
|
+
|
|
5078
|
+
// ../lsp-core/src/tools/format.ts
|
|
5079
|
+
async function executeLspFormat(params, signal) {
|
|
5080
|
+
const filePath = requireString(params, "filePath");
|
|
5081
|
+
try {
|
|
5082
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
|
|
5083
|
+
return text(describeResult(filePath, result), formatDetails(filePath, result));
|
|
5084
|
+
} catch (error) {
|
|
5085
|
+
const missingDependency = missingDependencyResult(error, {
|
|
5086
|
+
filePath,
|
|
5087
|
+
status: "unavailable",
|
|
5088
|
+
reason: "server_unavailable",
|
|
5089
|
+
linesAdded: 0,
|
|
5090
|
+
linesRemoved: 0
|
|
5091
|
+
});
|
|
5092
|
+
if (missingDependency)
|
|
5093
|
+
return missingDependency;
|
|
5094
|
+
throw error;
|
|
5095
|
+
}
|
|
5096
|
+
}
|
|
5097
|
+
function formatDetails(filePath, result) {
|
|
5098
|
+
if (result.status === "unavailable") {
|
|
5099
|
+
return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
|
|
5100
|
+
}
|
|
5101
|
+
return {
|
|
5102
|
+
filePath,
|
|
5103
|
+
status: result.status,
|
|
5104
|
+
linesAdded: result.linesAdded,
|
|
5105
|
+
linesRemoved: result.linesRemoved
|
|
5106
|
+
};
|
|
5107
|
+
}
|
|
5108
|
+
function describeResult(filePath, result) {
|
|
5109
|
+
if (result.status === "unavailable") {
|
|
5110
|
+
return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
|
|
5111
|
+
}
|
|
5112
|
+
if (result.status === "unchanged") {
|
|
5113
|
+
return `Already formatted: ${filePath}`;
|
|
5114
|
+
}
|
|
5115
|
+
return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
|
|
5116
|
+
}
|
|
5117
|
+
|
|
4685
5118
|
// ../lsp-core/src/tools/install-decision.ts
|
|
4686
5119
|
async function executeLspInstallDecision(params) {
|
|
4687
5120
|
const serverId = requireString(params, "server_id");
|
|
@@ -4710,7 +5143,7 @@ async function executeLspGotoDefinition(params, signal) {
|
|
|
4710
5143
|
const line = requireNumber(params, "line");
|
|
4711
5144
|
const character = requireNumber(params, "character");
|
|
4712
5145
|
try {
|
|
4713
|
-
const result = await withLspClient(filePath, async (client) => client.definition(
|
|
5146
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
|
|
4714
5147
|
const locations = !result ? [] : Array.isArray(result) ? result : [result];
|
|
4715
5148
|
const details = { filePath, line, character, locations };
|
|
4716
5149
|
if (locations.length === 0)
|
|
@@ -4735,7 +5168,7 @@ async function executeLspFindReferences(params, signal) {
|
|
|
4735
5168
|
const character = requireNumber(params, "character");
|
|
4736
5169
|
const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
|
|
4737
5170
|
try {
|
|
4738
|
-
const result = await withLspClient(filePath, async (client) => client.references(
|
|
5171
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
|
|
4739
5172
|
const references = Array.isArray(result) ? result : [];
|
|
4740
5173
|
const total = references.length;
|
|
4741
5174
|
const truncated = total > DEFAULT_MAX_REFERENCES;
|
|
@@ -4777,7 +5210,7 @@ async function executeLspPrepareRename(params, signal) {
|
|
|
4777
5210
|
const line = requireNumber(params, "line");
|
|
4778
5211
|
const character = requireNumber(params, "character");
|
|
4779
5212
|
try {
|
|
4780
|
-
const result = await withLspClient(filePath, async (client) => client.prepareRename(
|
|
5213
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
|
|
4781
5214
|
const details = { filePath, line, character, result };
|
|
4782
5215
|
return text(formatPrepareRenameResult(result), details);
|
|
4783
5216
|
} catch (error) {
|
|
@@ -4798,7 +5231,7 @@ async function executeLspRename(params, signal) {
|
|
|
4798
5231
|
const character = requireNumber(params, "character");
|
|
4799
5232
|
const newName = requireString(params, "newName");
|
|
4800
5233
|
try {
|
|
4801
|
-
const result = await withLspClient(filePath, async (client) => client.rename(
|
|
5234
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
|
|
4802
5235
|
const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
|
|
4803
5236
|
return text(formatApplyResult(result.apply), details, !result.apply.success);
|
|
4804
5237
|
} catch (error) {
|
|
@@ -4878,7 +5311,7 @@ async function executeLspSymbols(params, signal) {
|
|
|
4878
5311
|
const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
|
|
4879
5312
|
return formatSymbolsResult(filePath, scope, symbols2, limit, query);
|
|
4880
5313
|
}
|
|
4881
|
-
const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(
|
|
5314
|
+
const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
|
|
4882
5315
|
return formatSymbolsResult(filePath, scope, symbols, limit);
|
|
4883
5316
|
} catch (error) {
|
|
4884
5317
|
const query = optionalString(params, "query");
|
|
@@ -5014,6 +5447,16 @@ var LSP_MCP_TOOLS = [
|
|
|
5014
5447
|
}, ["filePath", "line", "character", "newName"]),
|
|
5015
5448
|
execute: executeLspRename
|
|
5016
5449
|
},
|
|
5450
|
+
{
|
|
5451
|
+
name: "format",
|
|
5452
|
+
aliases: ["lsp_format"],
|
|
5453
|
+
title: "LSP Format",
|
|
5454
|
+
description: "Format a source file with its language server and write the returned edits to disk.",
|
|
5455
|
+
inputSchema: objectSchema({
|
|
5456
|
+
filePath: { type: "string", description: "Source file path to format." }
|
|
5457
|
+
}, ["filePath"]),
|
|
5458
|
+
execute: executeLspFormat
|
|
5459
|
+
},
|
|
5017
5460
|
{
|
|
5018
5461
|
name: "install_decision",
|
|
5019
5462
|
aliases: ["lsp_install_decision"],
|
|
@@ -5113,11 +5556,10 @@ function requestedProtocolVersion(params) {
|
|
|
5113
5556
|
// src/daemon-client.ts
|
|
5114
5557
|
import { connect } from "node:net";
|
|
5115
5558
|
import { homedir as homedir3 } from "node:os";
|
|
5116
|
-
import { join as
|
|
5559
|
+
import { join as join8 } from "node:path";
|
|
5117
5560
|
|
|
5118
5561
|
// src/daemon-request-error.ts
|
|
5119
5562
|
class DaemonRequestError extends Error {
|
|
5120
|
-
requestWritten;
|
|
5121
5563
|
constructor(message, requestWritten) {
|
|
5122
5564
|
super(message);
|
|
5123
5565
|
this.name = "DaemonRequestError";
|
|
@@ -5140,7 +5582,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
|
|
|
5140
5582
|
}
|
|
5141
5583
|
|
|
5142
5584
|
class DaemonRequestTimedOutError extends DaemonRequestError {
|
|
5143
|
-
timeoutMs;
|
|
5144
5585
|
constructor(requestWritten, timeoutMs) {
|
|
5145
5586
|
super("daemon request timed out", requestWritten);
|
|
5146
5587
|
this.name = "DaemonRequestTimedOutError";
|
|
@@ -5192,9 +5633,9 @@ function errorText(error) {
|
|
|
5192
5633
|
|
|
5193
5634
|
// src/ensure-daemon.ts
|
|
5194
5635
|
import { spawn as spawn2 } from "node:child_process";
|
|
5195
|
-
import { closeSync as closeSync2, existsSync as
|
|
5636
|
+
import { closeSync as closeSync2, existsSync as existsSync12, mkdirSync as mkdirSync3, openSync as openSync2, writeSync as writeSync2 } from "node:fs";
|
|
5196
5637
|
import { Socket } from "node:net";
|
|
5197
|
-
import { dirname as
|
|
5638
|
+
import { dirname as dirname10, isAbsolute as isAbsolute5 } from "node:path";
|
|
5198
5639
|
import { argv0, execPath } from "node:process";
|
|
5199
5640
|
|
|
5200
5641
|
// src/ipc-protocol.ts
|
|
@@ -5208,25 +5649,23 @@ import {
|
|
|
5208
5649
|
lstatSync as lstatSync6,
|
|
5209
5650
|
mkdirSync as mkdirSync2,
|
|
5210
5651
|
openSync,
|
|
5211
|
-
readFileSync as
|
|
5212
|
-
unlinkSync,
|
|
5652
|
+
readFileSync as readFileSync6,
|
|
5653
|
+
unlinkSync as unlinkSync2,
|
|
5213
5654
|
writeSync
|
|
5214
5655
|
} from "node:fs";
|
|
5215
|
-
import { dirname as
|
|
5656
|
+
import { dirname as dirname9 } from "node:path";
|
|
5216
5657
|
var OMO_DAEMON_PROTOCOL_VERSION = 1;
|
|
5217
5658
|
var AUTH_ERROR_CODE = -32001;
|
|
5218
5659
|
var PROTOCOL_ERROR_CODE = -32002;
|
|
5219
5660
|
var AUTH_TOKEN_BYTES = 32;
|
|
5220
5661
|
|
|
5221
5662
|
class UnsafePrivateDirectoryError extends Error {
|
|
5222
|
-
path;
|
|
5223
|
-
reason;
|
|
5224
|
-
name = "UnsafePrivateDirectoryError";
|
|
5225
|
-
code = "unsafe_private_directory";
|
|
5226
5663
|
constructor(path, reason) {
|
|
5227
5664
|
super(`unsafe private directory ${path}: ${reason}`);
|
|
5228
5665
|
this.path = path;
|
|
5229
5666
|
this.reason = reason;
|
|
5667
|
+
this.name = "UnsafePrivateDirectoryError";
|
|
5668
|
+
this.code = "unsafe_private_directory";
|
|
5230
5669
|
}
|
|
5231
5670
|
}
|
|
5232
5671
|
function authEnvelope(token) {
|
|
@@ -5234,7 +5673,7 @@ function authEnvelope(token) {
|
|
|
5234
5673
|
}
|
|
5235
5674
|
function readAuthToken(paths) {
|
|
5236
5675
|
try {
|
|
5237
|
-
const token =
|
|
5676
|
+
const token = readFileSync6(paths.auth, "utf8").trim();
|
|
5238
5677
|
return token.length > 0 ? token : null;
|
|
5239
5678
|
} catch (error) {
|
|
5240
5679
|
if (error instanceof Error)
|
|
@@ -5250,7 +5689,7 @@ function readOrCreateAuthToken(paths) {
|
|
|
5250
5689
|
}
|
|
5251
5690
|
function rotateAuthToken(paths) {
|
|
5252
5691
|
try {
|
|
5253
|
-
|
|
5692
|
+
unlinkSync2(paths.auth);
|
|
5254
5693
|
} catch (error) {
|
|
5255
5694
|
if (!(error instanceof Error))
|
|
5256
5695
|
throw error;
|
|
@@ -5322,7 +5761,7 @@ function setPrivateFileMode(path) {
|
|
|
5322
5761
|
chmodSync(path, 384);
|
|
5323
5762
|
}
|
|
5324
5763
|
function createAuthToken(paths) {
|
|
5325
|
-
ensurePrivateDirectory(
|
|
5764
|
+
ensurePrivateDirectory(dirname9(paths.auth));
|
|
5326
5765
|
const token = randomBytes(AUTH_TOKEN_BYTES).toString("base64url");
|
|
5327
5766
|
let fd;
|
|
5328
5767
|
try {
|
|
@@ -5403,27 +5842,25 @@ import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
|
5403
5842
|
|
|
5404
5843
|
// src/runtime-contract.ts
|
|
5405
5844
|
import { statSync as statSync4 } from "node:fs";
|
|
5406
|
-
import { isAbsolute as
|
|
5845
|
+
import { isAbsolute as isAbsolute4 } from "node:path";
|
|
5407
5846
|
var OMO_LSP_DAEMON_DIR = "OMO_LSP_DAEMON_DIR";
|
|
5408
5847
|
var OMO_LSP_DAEMON_CLI = "OMO_LSP_DAEMON_CLI";
|
|
5409
5848
|
var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
|
|
5410
5849
|
var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
5411
5850
|
|
|
5412
5851
|
class InvalidRuntimeOverrideError extends Error {
|
|
5413
|
-
code = "invalid_runtime_override";
|
|
5414
|
-
reason;
|
|
5415
5852
|
constructor(reason, message) {
|
|
5416
5853
|
super(message);
|
|
5854
|
+
this.code = "invalid_runtime_override";
|
|
5417
5855
|
this.name = "InvalidRuntimeOverrideError";
|
|
5418
5856
|
this.reason = reason;
|
|
5419
5857
|
}
|
|
5420
5858
|
}
|
|
5421
5859
|
|
|
5422
5860
|
class InvalidDaemonVersionError extends Error {
|
|
5423
|
-
code = "invalid_daemon_version";
|
|
5424
|
-
version;
|
|
5425
5861
|
constructor(version) {
|
|
5426
5862
|
super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
|
|
5863
|
+
this.code = "invalid_daemon_version";
|
|
5427
5864
|
this.name = "InvalidDaemonVersionError";
|
|
5428
5865
|
this.version = version;
|
|
5429
5866
|
}
|
|
@@ -5442,12 +5879,12 @@ function resolveDaemonRuntime(env, defaults) {
|
|
|
5442
5879
|
throw new InvalidRuntimeOverrideError("paired_values_required", `${OMO_LSP_DAEMON_CLI} and ${OMO_LSP_DAEMON_VERSION} must be set together`);
|
|
5443
5880
|
}
|
|
5444
5881
|
if (!hasCliOverride || !hasVersionOverride) {
|
|
5445
|
-
if (!
|
|
5882
|
+
if (!isAbsolute4(defaults.cliPath)) {
|
|
5446
5883
|
throw new InvalidRuntimeOverrideError("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
|
|
5447
5884
|
}
|
|
5448
5885
|
return { cliPath: defaults.cliPath, version: validateDaemonVersion(defaults.version) };
|
|
5449
5886
|
}
|
|
5450
|
-
if (!
|
|
5887
|
+
if (!isAbsolute4(cliOverride)) {
|
|
5451
5888
|
throw new InvalidRuntimeOverrideError("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI} must be an absolute path to an existing regular file`);
|
|
5452
5889
|
}
|
|
5453
5890
|
let cliStats;
|
|
@@ -5469,10 +5906,9 @@ var requireFromHere = createRequire(import.meta.url);
|
|
|
5469
5906
|
var MAX_SOCKET_PATH_LENGTH = 100;
|
|
5470
5907
|
|
|
5471
5908
|
class InvalidDaemonDirectoryError extends Error {
|
|
5472
|
-
code = "invalid_daemon_directory";
|
|
5473
|
-
directory;
|
|
5474
5909
|
constructor(directory) {
|
|
5475
5910
|
super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
|
|
5911
|
+
this.code = "invalid_daemon_directory";
|
|
5476
5912
|
this.name = "InvalidDaemonDirectoryError";
|
|
5477
5913
|
this.directory = directory;
|
|
5478
5914
|
}
|
|
@@ -5626,7 +6062,7 @@ async function probeDaemon(paths, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
5626
6062
|
return await pingDaemon(paths, token, timeoutMs, signal) !== null;
|
|
5627
6063
|
}
|
|
5628
6064
|
function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
5629
|
-
return new Promise((
|
|
6065
|
+
return new Promise((resolve10) => {
|
|
5630
6066
|
const socket = new Socket;
|
|
5631
6067
|
let settled = false;
|
|
5632
6068
|
let timer;
|
|
@@ -5638,7 +6074,7 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
5638
6074
|
clearTimeout(timer);
|
|
5639
6075
|
signal?.removeEventListener("abort", onAbort);
|
|
5640
6076
|
socket.destroy();
|
|
5641
|
-
|
|
6077
|
+
resolve10(value);
|
|
5642
6078
|
};
|
|
5643
6079
|
const onAbort = () => finish(null);
|
|
5644
6080
|
const decoder = createLineDecoder((message) => {
|
|
@@ -5662,12 +6098,13 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
5662
6098
|
});
|
|
5663
6099
|
}
|
|
5664
6100
|
function spawnDaemonProcess(paths) {
|
|
5665
|
-
mkdirSync3(
|
|
6101
|
+
mkdirSync3(dirname10(paths.log), { recursive: true });
|
|
5666
6102
|
const logFd = openSync2(paths.log, "a");
|
|
5667
6103
|
try {
|
|
5668
6104
|
const child = spawn2(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
|
|
5669
6105
|
detached: true,
|
|
5670
|
-
stdio: ["ignore", logFd, logFd]
|
|
6106
|
+
stdio: ["ignore", logFd, logFd],
|
|
6107
|
+
windowsHide: true
|
|
5671
6108
|
});
|
|
5672
6109
|
child.once("spawn", () => closeSync2(logFd));
|
|
5673
6110
|
child.once("error", (error) => {
|
|
@@ -5681,10 +6118,10 @@ function spawnDaemonProcess(paths) {
|
|
|
5681
6118
|
throw error;
|
|
5682
6119
|
}
|
|
5683
6120
|
}
|
|
5684
|
-
function resolveDaemonNodeExecutable(cachedExecPath = execPath, originalArgv0 = argv0, pathExists =
|
|
6121
|
+
function resolveDaemonNodeExecutable(cachedExecPath = execPath, originalArgv0 = argv0, pathExists = existsSync12) {
|
|
5685
6122
|
if (pathExists(cachedExecPath))
|
|
5686
6123
|
return cachedExecPath;
|
|
5687
|
-
if (
|
|
6124
|
+
if (isAbsolute5(originalArgv0) && pathExists(originalArgv0))
|
|
5688
6125
|
return originalArgv0;
|
|
5689
6126
|
return "node";
|
|
5690
6127
|
}
|
|
@@ -5697,7 +6134,7 @@ function defaultEnsureDaemonDeps() {
|
|
|
5697
6134
|
};
|
|
5698
6135
|
}
|
|
5699
6136
|
function sleepWithSignal(ms, signal) {
|
|
5700
|
-
return new Promise((
|
|
6137
|
+
return new Promise((resolve10) => {
|
|
5701
6138
|
let settled = false;
|
|
5702
6139
|
const finish = () => {
|
|
5703
6140
|
if (settled)
|
|
@@ -5705,7 +6142,7 @@ function sleepWithSignal(ms, signal) {
|
|
|
5705
6142
|
settled = true;
|
|
5706
6143
|
clearTimeout(timer);
|
|
5707
6144
|
signal?.removeEventListener("abort", finish);
|
|
5708
|
-
|
|
6145
|
+
resolve10();
|
|
5709
6146
|
};
|
|
5710
6147
|
const timer = setTimeout(finish, ms);
|
|
5711
6148
|
if (signal?.aborted) {
|
|
@@ -5720,7 +6157,7 @@ function awaitWithSignal2(promise, signal) {
|
|
|
5720
6157
|
return promise;
|
|
5721
6158
|
if (signal.aborted)
|
|
5722
6159
|
return Promise.reject(abortError3(signal));
|
|
5723
|
-
return new Promise((
|
|
6160
|
+
return new Promise((resolve10, reject) => {
|
|
5724
6161
|
let settled = false;
|
|
5725
6162
|
const finish = (run) => {
|
|
5726
6163
|
if (settled)
|
|
@@ -5731,7 +6168,7 @@ function awaitWithSignal2(promise, signal) {
|
|
|
5731
6168
|
};
|
|
5732
6169
|
const onAbort = () => finish(() => reject(abortError3(signal)));
|
|
5733
6170
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5734
|
-
promise.then((value) => finish(() =>
|
|
6171
|
+
promise.then((value) => finish(() => resolve10(value)), (error) => finish(() => reject(error)));
|
|
5735
6172
|
});
|
|
5736
6173
|
}
|
|
5737
6174
|
function throwIfAborted(signal) {
|
|
@@ -5780,7 +6217,10 @@ function parsePingResponse(message) {
|
|
|
5780
6217
|
var CONTEXT_KEY = "_context";
|
|
5781
6218
|
|
|
5782
6219
|
class InvalidDaemonRequestError extends Error {
|
|
5783
|
-
|
|
6220
|
+
constructor() {
|
|
6221
|
+
super(...arguments);
|
|
6222
|
+
this.name = "InvalidDaemonRequestError";
|
|
6223
|
+
}
|
|
5784
6224
|
}
|
|
5785
6225
|
function extractRequestContext(raw) {
|
|
5786
6226
|
if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
|
|
@@ -5896,14 +6336,17 @@ async function callToolViaDaemon(name, args, options) {
|
|
|
5896
6336
|
function callDiagnosticsViaDaemon(filePath, options) {
|
|
5897
6337
|
return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
|
|
5898
6338
|
}
|
|
6339
|
+
function callFormatViaDaemon(filePath, options) {
|
|
6340
|
+
return callToolViaDaemon("format", { filePath }, options);
|
|
6341
|
+
}
|
|
5899
6342
|
function currentRequestContext(env = process.env) {
|
|
5900
6343
|
const cwd = process.cwd();
|
|
5901
6344
|
const home = env["HOME"] ?? homedir3();
|
|
5902
6345
|
return parseLspRequestContext({
|
|
5903
6346
|
cwd,
|
|
5904
|
-
projectConfigPaths: [
|
|
5905
|
-
userConfigPath:
|
|
5906
|
-
installDecisionsPath:
|
|
6347
|
+
projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
|
|
6348
|
+
userConfigPath: join8(home, ".codex", "lsp-client.json"),
|
|
6349
|
+
installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
|
|
5907
6350
|
capabilities: { installDecisionTool: true }
|
|
5908
6351
|
});
|
|
5909
6352
|
}
|
|
@@ -5918,7 +6361,7 @@ function withContext(args, context) {
|
|
|
5918
6361
|
function ensureDaemonAvailable(paths, ensure, signal) {
|
|
5919
6362
|
if (!signal)
|
|
5920
6363
|
return ensure(paths);
|
|
5921
|
-
return new Promise((
|
|
6364
|
+
return new Promise((resolve10, reject) => {
|
|
5922
6365
|
let settled = false;
|
|
5923
6366
|
const finish = (run) => {
|
|
5924
6367
|
if (settled)
|
|
@@ -5933,11 +6376,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
|
|
|
5933
6376
|
return;
|
|
5934
6377
|
}
|
|
5935
6378
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5936
|
-
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() =>
|
|
6379
|
+
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
|
|
5937
6380
|
});
|
|
5938
6381
|
}
|
|
5939
6382
|
function sendToolCall(paths, token, name, args, options) {
|
|
5940
|
-
return new Promise((
|
|
6383
|
+
return new Promise((resolve10, reject) => {
|
|
5941
6384
|
const socket = connect(paths.socket);
|
|
5942
6385
|
const requestId = allocateProxyRequestId();
|
|
5943
6386
|
let settled = false;
|
|
@@ -5990,7 +6433,7 @@ function sendToolCall(paths, token, name, args, options) {
|
|
|
5990
6433
|
}
|
|
5991
6434
|
const result = toToolResult(message, requestId);
|
|
5992
6435
|
if (result)
|
|
5993
|
-
finish(() =>
|
|
6436
|
+
finish(() => resolve10(result));
|
|
5994
6437
|
else
|
|
5995
6438
|
finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
|
|
5996
6439
|
});
|
|
@@ -6158,18 +6601,18 @@ function canonicalizePathList(value) {
|
|
|
6158
6601
|
return value.split(delimiter4).map((entry) => canonicalizePath(entry) ?? entry).join(delimiter4);
|
|
6159
6602
|
}
|
|
6160
6603
|
function canonicalizePath(value) {
|
|
6161
|
-
if (value === undefined || !
|
|
6604
|
+
if (value === undefined || !isAbsolute6(value) || !existsSync13(value))
|
|
6162
6605
|
return value;
|
|
6163
|
-
return
|
|
6606
|
+
return realpathSync6(value);
|
|
6164
6607
|
}
|
|
6165
6608
|
function projectRootFromOpenCodeConfigPath(path2) {
|
|
6166
|
-
if (
|
|
6609
|
+
if (basename4(path2) !== "lsp.json" && basename4(path2) !== "lsp-client.json")
|
|
6167
6610
|
return;
|
|
6168
|
-
const configDir =
|
|
6169
|
-
const configDirName =
|
|
6611
|
+
const configDir = dirname11(path2);
|
|
6612
|
+
const configDirName = basename4(configDir);
|
|
6170
6613
|
if (configDirName !== ".opencode" && configDirName !== ".omo")
|
|
6171
6614
|
return;
|
|
6172
|
-
return
|
|
6615
|
+
return dirname11(configDir);
|
|
6173
6616
|
}
|
|
6174
6617
|
|
|
6175
6618
|
// src/daemon-server.ts
|
|
@@ -6178,12 +6621,12 @@ import { createServer as createServer2 } from "node:net";
|
|
|
6178
6621
|
|
|
6179
6622
|
// src/ownership.ts
|
|
6180
6623
|
import { randomUUID } from "node:crypto";
|
|
6181
|
-
import { existsSync as
|
|
6182
|
-
import { dirname as
|
|
6624
|
+
import { existsSync as existsSync14, lstatSync as lstatSync7, readFileSync as readFileSync8, statSync as statSync5, unlinkSync as unlinkSync4 } from "node:fs";
|
|
6625
|
+
import { dirname as dirname13 } from "node:path";
|
|
6183
6626
|
|
|
6184
6627
|
// src/lock.ts
|
|
6185
|
-
import { closeSync as closeSync3, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as
|
|
6186
|
-
import { dirname as
|
|
6628
|
+
import { closeSync as closeSync3, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeSync as writeSync3 } from "node:fs";
|
|
6629
|
+
import { dirname as dirname12 } from "node:path";
|
|
6187
6630
|
function isProcessAlive2(pid) {
|
|
6188
6631
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
6189
6632
|
return false;
|
|
@@ -6198,14 +6641,14 @@ function isProcessAlive2(pid) {
|
|
|
6198
6641
|
}
|
|
6199
6642
|
function readLockPid(lockPath) {
|
|
6200
6643
|
try {
|
|
6201
|
-
const pid = Number.parseInt(
|
|
6644
|
+
const pid = Number.parseInt(readFileSync7(lockPath, "utf8").trim(), 10);
|
|
6202
6645
|
return Number.isInteger(pid) ? pid : null;
|
|
6203
6646
|
} catch {
|
|
6204
6647
|
return null;
|
|
6205
6648
|
}
|
|
6206
6649
|
}
|
|
6207
6650
|
function tryAcquireLock(lockPath, ownerPid = process.pid) {
|
|
6208
|
-
mkdirSync4(
|
|
6651
|
+
mkdirSync4(dirname12(lockPath), { recursive: true });
|
|
6209
6652
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
6210
6653
|
const handle = writeLockFile(lockPath, ownerPid);
|
|
6211
6654
|
if (handle)
|
|
@@ -6237,7 +6680,7 @@ function reapStaleLock(lockPath) {
|
|
|
6237
6680
|
}
|
|
6238
6681
|
function unlinkQuietly(path2) {
|
|
6239
6682
|
try {
|
|
6240
|
-
|
|
6683
|
+
unlinkSync3(path2);
|
|
6241
6684
|
} catch (error) {
|
|
6242
6685
|
if (error instanceof Error)
|
|
6243
6686
|
return;
|
|
@@ -6253,17 +6696,19 @@ function errorCode3(error) {
|
|
|
6253
6696
|
|
|
6254
6697
|
// src/ownership.ts
|
|
6255
6698
|
class DaemonAlreadyRunningError extends Error {
|
|
6256
|
-
|
|
6257
|
-
|
|
6699
|
+
constructor() {
|
|
6700
|
+
super(...arguments);
|
|
6701
|
+
this.name = "DaemonAlreadyRunningError";
|
|
6702
|
+
this.code = "daemon_already_running";
|
|
6703
|
+
}
|
|
6258
6704
|
}
|
|
6259
6705
|
|
|
6260
6706
|
class DaemonStartupDeferredError extends Error {
|
|
6261
|
-
reason;
|
|
6262
|
-
name = "DaemonStartupDeferredError";
|
|
6263
|
-
code = "daemon_startup_deferred";
|
|
6264
6707
|
constructor(reason) {
|
|
6265
6708
|
super(`LSP daemon startup deferred: ${reason}`);
|
|
6266
6709
|
this.reason = reason;
|
|
6710
|
+
this.name = "DaemonStartupDeferredError";
|
|
6711
|
+
this.code = "daemon_startup_deferred";
|
|
6267
6712
|
}
|
|
6268
6713
|
}
|
|
6269
6714
|
async function acquireStartupLease(paths, pingOwner) {
|
|
@@ -6286,11 +6731,11 @@ async function acquireStartupLease(paths, pingOwner) {
|
|
|
6286
6731
|
function ensureDaemonDirectories(paths) {
|
|
6287
6732
|
ensurePrivateDirectory(paths.dir);
|
|
6288
6733
|
if (process.platform !== "win32")
|
|
6289
|
-
ensurePrivateDirectory(
|
|
6734
|
+
ensurePrivateDirectory(dirname13(paths.socket));
|
|
6290
6735
|
}
|
|
6291
6736
|
function readDaemonOwner(paths) {
|
|
6292
6737
|
try {
|
|
6293
|
-
return parseOwner(JSON.parse(
|
|
6738
|
+
return parseOwner(JSON.parse(readFileSync8(paths.owner, "utf8")));
|
|
6294
6739
|
} catch (error) {
|
|
6295
6740
|
if (error instanceof Error)
|
|
6296
6741
|
return null;
|
|
@@ -6366,10 +6811,10 @@ async function validateExistingOwner(paths, pingOwner) {
|
|
|
6366
6811
|
throw new DaemonStartupDeferredError("reachable_owner_mismatch");
|
|
6367
6812
|
}
|
|
6368
6813
|
function cleanupDeadOwner(paths, owner) {
|
|
6369
|
-
if (process.platform !== "win32" &&
|
|
6814
|
+
if (process.platform !== "win32" && existsSync14(owner.endpoint.path)) {
|
|
6370
6815
|
const stat = lstatSync7(owner.endpoint.path);
|
|
6371
6816
|
if (stat.isSocket())
|
|
6372
|
-
|
|
6817
|
+
unlinkSync4(owner.endpoint.path);
|
|
6373
6818
|
}
|
|
6374
6819
|
unlinkQuietly(paths.pid);
|
|
6375
6820
|
unlinkQuietly(paths.endpoint);
|
|
@@ -6417,7 +6862,7 @@ function parseEndpoint(value) {
|
|
|
6417
6862
|
// src/version-reap.ts
|
|
6418
6863
|
import { execFile } from "node:child_process";
|
|
6419
6864
|
import { readdir, readFile, rm } from "node:fs/promises";
|
|
6420
|
-
import { basename as
|
|
6865
|
+
import { basename as basename5, dirname as dirname14, join as join9 } from "node:path";
|
|
6421
6866
|
var TERM_GRACE_MS = 5000;
|
|
6422
6867
|
var KILL_GRACE_MS = 1000;
|
|
6423
6868
|
var VERSION_ENTRY_PATTERN = /^v([A-Za-z0-9][A-Za-z0-9._+-]{0,127})$/;
|
|
@@ -6438,7 +6883,7 @@ async function attestDaemonCliProcess(pid, platform, deps = {}) {
|
|
|
6438
6883
|
return isNodeCliDaemonCommand(command.trim());
|
|
6439
6884
|
}
|
|
6440
6885
|
async function reapStaleDaemonVersions(ownPaths, deps = {}) {
|
|
6441
|
-
const baseDir =
|
|
6886
|
+
const baseDir = dirname14(ownPaths.dir);
|
|
6442
6887
|
const platform = deps.platform ?? process.platform;
|
|
6443
6888
|
const isAlive = deps.isAlive ?? isProcessAlive2;
|
|
6444
6889
|
const attest = deps.attest ?? ((pid) => attestDaemonCliProcess(pid, platform));
|
|
@@ -6457,7 +6902,7 @@ async function reapStaleDaemonVersions(ownPaths, deps = {}) {
|
|
|
6457
6902
|
const version = parseVersionEntry(entry.name);
|
|
6458
6903
|
if (version === null || !entry.isDirectory())
|
|
6459
6904
|
continue;
|
|
6460
|
-
const versionDir =
|
|
6905
|
+
const versionDir = join9(baseDir, entry.name);
|
|
6461
6906
|
const siblingPaths = daemonPaths({ [OMO_LSP_DAEMON_DIR]: baseDir }, { cliPath: ownPaths.cliPath, version });
|
|
6462
6907
|
results.push(await reapOneVersion({
|
|
6463
6908
|
version,
|
|
@@ -6481,7 +6926,7 @@ async function reapOneVersion(context) {
|
|
|
6481
6926
|
const { version, versionDir } = context;
|
|
6482
6927
|
const owner = context.readOwner(context.siblingPaths);
|
|
6483
6928
|
if (!owner) {
|
|
6484
|
-
const lockPid = readLockPid(
|
|
6929
|
+
const lockPid = readLockPid(join9(versionDir, "daemon.lock"));
|
|
6485
6930
|
if (lockPid !== null && context.isAlive(lockPid)) {
|
|
6486
6931
|
context.log(`reap: sparing v${version}: owner metadata missing but daemon.lock is held by live pid ${lockPid}`);
|
|
6487
6932
|
return { version, status: "spared", reason: `owner metadata missing but lock held by live pid ${lockPid}` };
|
|
@@ -6547,7 +6992,7 @@ function splitCmdline(buffer) {
|
|
|
6547
6992
|
function isNodeCliDaemonArgv(argv) {
|
|
6548
6993
|
if (argv.length < 2 || !argv.includes("daemon"))
|
|
6549
6994
|
return false;
|
|
6550
|
-
const executable =
|
|
6995
|
+
const executable = basename5(argv[0] ?? "");
|
|
6551
6996
|
if (!/^node(?:\.exe)?$/i.test(executable))
|
|
6552
6997
|
return false;
|
|
6553
6998
|
return argv.some((value) => value === "cli.js" || value.endsWith("/cli.js") || value.endsWith("\\cli.js"));
|
|
@@ -6559,13 +7004,13 @@ function defaultReadProcFile(path2) {
|
|
|
6559
7004
|
return readFile(path2);
|
|
6560
7005
|
}
|
|
6561
7006
|
function defaultExecuteForStdout(file, args) {
|
|
6562
|
-
return new Promise((
|
|
6563
|
-
execFile(file, [...args], { encoding: "utf8", maxBuffer: 1024 * 1024, timeout: 1000 }, (error, stdout) => {
|
|
7007
|
+
return new Promise((resolve10) => {
|
|
7008
|
+
execFile(file, [...args], { encoding: "utf8", maxBuffer: 1024 * 1024, timeout: 1000, windowsHide: true }, (error, stdout) => {
|
|
6564
7009
|
if (error !== null) {
|
|
6565
|
-
|
|
7010
|
+
resolve10(null);
|
|
6566
7011
|
return;
|
|
6567
7012
|
}
|
|
6568
|
-
|
|
7013
|
+
resolve10(stdout);
|
|
6569
7014
|
});
|
|
6570
7015
|
});
|
|
6571
7016
|
}
|
|
@@ -6584,7 +7029,7 @@ async function defaultWaitForExit(pid, timeoutMs) {
|
|
|
6584
7029
|
return true;
|
|
6585
7030
|
if (Date.now() >= deadline)
|
|
6586
7031
|
return false;
|
|
6587
|
-
await new Promise((
|
|
7032
|
+
await new Promise((resolve10) => setTimeout(resolve10, 100));
|
|
6588
7033
|
}
|
|
6589
7034
|
}
|
|
6590
7035
|
function defaultLog(message) {
|
|
@@ -6691,17 +7136,17 @@ async function assertSelfProbe(paths, token, owner) {
|
|
|
6691
7136
|
throw new DaemonStartupDeferredError("self_probe_failed");
|
|
6692
7137
|
}
|
|
6693
7138
|
function listen(server2, socketPath) {
|
|
6694
|
-
return new Promise((
|
|
7139
|
+
return new Promise((resolve10, reject) => {
|
|
6695
7140
|
const onError = (error) => reject(error);
|
|
6696
7141
|
server2.once("error", onError);
|
|
6697
7142
|
server2.listen(socketPath, () => {
|
|
6698
7143
|
server2.removeListener("error", onError);
|
|
6699
|
-
|
|
7144
|
+
resolve10();
|
|
6700
7145
|
});
|
|
6701
7146
|
});
|
|
6702
7147
|
}
|
|
6703
7148
|
function closeServer(server2) {
|
|
6704
|
-
return new Promise((
|
|
7149
|
+
return new Promise((resolve10) => server2.close(() => resolve10()));
|
|
6705
7150
|
}
|
|
6706
7151
|
function installSignalHandlers(close) {
|
|
6707
7152
|
const handler = () => {
|