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