lazycodex-ai 5.0.0-beta.4 → 5.0.0-beta.40
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 +25 -21
- package/README.ko.md +25 -21
- package/README.md +38 -23
- package/README.ru.md +24 -20
- package/README.zh-cn.md +25 -21
- package/dist/cli/config-manager/parse-opencode-config-file.d.ts +2 -1
- package/dist/cli/doctor/checks/system-plugin.d.ts +4 -3
- package/dist/cli/fallback-lane-policy.d.ts +1 -0
- package/dist/cli/index.js +66932 -64746
- 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 +66795 -64586
- package/package.json +9 -9
- package/packages/git-bash-mcp/dist/cli.js +6 -1
- package/packages/lsp-daemon/dist/cli.js +793 -323
- package/packages/lsp-daemon/dist/client.d.ts +10 -0
- package/packages/lsp-daemon/dist/client.js +753 -280
- package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
- package/packages/lsp-daemon/dist/daemon-client.js +3 -0
- package/packages/lsp-daemon/dist/ensure-daemon.js +1 -0
- package/packages/lsp-daemon/dist/index.js +757 -289
- 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 +712 -244
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +248 -119
- package/packages/lsp-tools-mcp/dist/mcp.js +714 -246
- package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
- package/packages/lsp-tools-mcp/dist/tools.js +718 -254
- 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 +2 -2
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +45 -49
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +1 -0
- package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +9 -0
- package/packages/omo-codex/plugin/components/comment-checker/biome.json +2 -2
- package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +2 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +5 -5
- package/packages/omo-codex/plugin/components/comment-checker/src/apply-patch.ts +2 -8
- package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +1 -2
- package/packages/omo-codex/plugin/components/comment-checker/src/request-extractor.ts +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +1 -0
- package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +3 -4
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +1 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +1 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +5 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +1 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +4 -21
- package/packages/omo-codex/plugin/components/lcx/skills/lcx-doctor/SKILL.md +1 -1
- 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 +741 -294
- package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.js +1 -1
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +5 -5
- package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
- package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +1 -1
- package/packages/omo-codex/plugin/components/lsp/src/daemon-cli-path.ts +1 -5
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +6 -7
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +1 -2
- package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +11 -1
- package/packages/omo-codex/plugin/components/rules/AGENTS.md +12 -0
- package/packages/omo-codex/plugin/components/rules/biome.json +2 -2
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +60 -45
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +7 -7
- package/packages/omo-codex/plugin/components/rules/src/config.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +9 -5
- package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +1 -4
- package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +4 -9
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +17 -25
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
- package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
- package/packages/omo-codex/plugin/components/rules/test/dynamic-target-fingerprints.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/engine.test.ts +7 -4
- package/packages/omo-codex/plugin/components/rules/test/finder.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +39 -72
- package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/matcher.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +1 -1
- package/packages/omo-codex/plugin/components/rules/test/parser.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +5 -6
- package/packages/omo-codex/plugin/components/rules/test/rules-engine-consumption.test.ts +3 -6
- package/packages/omo-codex/plugin/components/rules/test/scanner.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/sources.test.ts +2 -5
- package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +2 -17
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +5 -5
- package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +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 +2463 -437
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2467 -441
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +5 -5
- package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +1 -4
- package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -14
- package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +1 -1
- package/packages/omo-codex/plugin/components/telemetry/test/diagnostics.test.ts +2 -5
- package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +10 -4
- package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +489 -4
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -6
- package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +30 -14
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -7
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +31 -7
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +4 -0
- package/packages/omo-codex/plugin/components/ultrawork/src/directive.ts +5 -2
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +9 -1
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
- package/packages/omo-codex/plugin/components/ultrawork/test/directive-source.test.ts +14 -8
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +12 -1
- package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +2 -2
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/NOTICE +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/README.md +5 -5
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/biome.json +2 -2
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/directive.md +6 -6
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +12 -12
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +28 -0
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/package.json +12 -12
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/boulder-reader.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/cli.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/codex-hook.ts +3 -3
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/directive.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/index.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/boulder-reader.test.ts +3 -3
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +1 -4
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +8 -22
- package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +19 -0
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +12 -1
- package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +15 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.d.ts +12 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +45 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +15 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.d.ts +8 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +120 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +40 -39
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +7 -2
- 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.js +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +958 -342
- 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 +27 -6
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +13 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +15 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +17 -9
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +17 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +13 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +19 -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 +69 -111
- package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +185 -14
- package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +33 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +18 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +65 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +22 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +81 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +7 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +31 -1
- 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 +38 -71
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +7 -2
- 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 +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +3 -5
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +34 -5
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +26 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +19 -9
- package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +18 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +27 -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 +68 -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 +82 -131
- package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +187 -12
- package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +36 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +95 -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 +133 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +137 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +25 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +26 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-status-next-actions.test.ts +183 -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 +18 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +7 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/guided-recovery.test.ts +105 -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/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-poisoning-cascades.test.ts +97 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +46 -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 +48 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +318 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +8 -5
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/surface.test.ts +74 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +13 -8
- package/packages/omo-codex/plugin/components/ulw-loop/vitest.config.ts +1 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/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-checking-ulw-execute-continuation.json +17 -0
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/model-catalog.json +3 -3
- package/packages/omo-codex/plugin/package-lock.json +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 +3 -3
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +36 -13
- 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/coding-agent-sessions/AGENTS.md +62 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
- package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
- package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
- package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
- package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
- package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
- package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +11 -7
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +13 -13
- package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +4 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +110 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -2
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +15 -3
- package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +19 -26
- package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +22 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -7
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +31 -7
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +4 -2
- package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +3 -2
- package/packages/omo-codex/plugin/test/AGENTS.md +47 -0
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +9 -48
- 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 +1 -1
- package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
- package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
- package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
- package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -27
- 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 +2 -2
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +4 -5
- 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 +8 -8
- package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
- package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +23 -13
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +14 -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 +2817 -913
- package/packages/{omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md → prompts-core/prompts/ultrawork/codex.md} +15 -10
- package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
- package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
- package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
- package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
- package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
- package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
- package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
- package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
- package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
- package/packages/shared-skills/skills/debugging/SKILL.md +2 -0
- package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
- package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
- package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
- package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
- package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
- package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
- package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
- package/packages/shared-skills/skills/frontend/SKILL.md +11 -7
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
- package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
- package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
- package/packages/shared-skills/skills/init-deep/SKILL.md +13 -13
- package/packages/shared-skills/skills/review-work/SKILL.md +3 -3
- package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +110 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -2
- package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +17 -16
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +6 -7
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/packages/shared-skills/skills/ulw-research/SKILL.md +4 -2
- package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
- package/packages/shared-skills/skills/visual-qa/SKILL.md +3 -2
- package/script/qa/web-terminal-visual-qa.mjs +2 -0
- package/script/qa/xterm-live-terminal.mjs +18 -2
- package/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 -12136
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +0 -9734
- package/packages/omo-codex/plugin/components/codegraph/package.json +0 -33
- package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +0 -79
- package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +0 -33
- package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +0 -25
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +0 -131
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +0 -258
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +0 -309
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +0 -80
- package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +0 -34
- package/packages/omo-codex/plugin/components/codegraph/src/serve-invocation.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +0 -263
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +0 -106
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +0 -145
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +0 -21
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +0 -139
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +0 -15
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +0 -32
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +0 -109
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +0 -148
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +0 -175
- package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +0 -81
- package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +0 -34
- package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +0 -112
- package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +0 -26
- package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +0 -160
- package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +0 -50
- package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +0 -320
- package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +0 -172
- package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +0 -91
- package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +0 -100
- package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +0 -76
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +0 -133
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +0 -245
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +0 -69
- package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +0 -43
- package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +0 -147
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +0 -175
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +0 -385
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +0 -206
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +0 -58
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +0 -104
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +0 -65
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-availability.test.ts +0 -106
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +0 -116
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +0 -258
- package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +0 -56
- package/packages/omo-codex/plugin/components/codegraph/tsconfig.build.json +0 -13
- package/packages/omo-codex/plugin/components/codegraph/tsconfig.json +0 -25
- package/packages/omo-codex/plugin/components/start-work-continuation/LICENSE +0 -21
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +0 -471
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +0 -18
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +0 -17
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot/editor.mjs +0 -125
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot/jsonc.mjs +0 -43
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot/scaffold.mjs +0 -29
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +0 -121
- package/packages/omo-codex/plugin/skills/data-scientist/references/common-scenarios.md +0 -176
- package/packages/omo-codex/plugin/skills/data-scientist/references/execution-templates.md +0 -197
- package/packages/omo-codex/plugin/skills/data-scientist/references/integration-patterns.md +0 -153
- package/packages/omo-codex/plugin/skills/data-scientist/references/performance-benchmarks.md +0 -37
- package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
- package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
- package/packages/omo-codex/plugin/test/component-codegraph-mcp-smoke.test.mjs +0 -76
- package/packages/omo-codex/plugin/test/migrate-omo-sot.test.mjs +0 -179
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
- package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
- package/packages/shared-skills/skills/data-scientist/references/common-scenarios.md +0 -176
- package/packages/shared-skills/skills/data-scientist/references/execution-templates.md +0 -197
- package/packages/shared-skills/skills/data-scientist/references/integration-patterns.md +0 -153
- package/packages/shared-skills/skills/data-scientist/references/performance-benchmarks.md +0 -37
- /package/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}/src/types.ts +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
import { statSync as statSync5 } from "node:fs";
|
|
3
|
+
import { isAbsolute as isAbsolute6 } from "node:path";
|
|
4
|
+
|
|
1
5
|
// src/daemon-client.ts
|
|
2
6
|
import { connect } from "node:net";
|
|
3
7
|
import { homedir as homedir3 } from "node:os";
|
|
4
|
-
import { join as
|
|
8
|
+
import { join as join8 } from "node:path";
|
|
5
9
|
|
|
6
10
|
// ../lsp-core/src/request-context.ts
|
|
7
11
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -10,18 +14,17 @@ import { homedir } from "node:os";
|
|
|
10
14
|
import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
11
15
|
|
|
12
16
|
class LspRequestContextParseError extends Error {
|
|
13
|
-
code;
|
|
14
|
-
name = "LspRequestContextParseError";
|
|
15
17
|
constructor(code, message) {
|
|
16
18
|
super(message);
|
|
17
19
|
this.code = code;
|
|
20
|
+
this.name = "LspRequestContextParseError";
|
|
18
21
|
}
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
class LspRequestContextUnavailableError extends Error {
|
|
22
|
-
name = "LspRequestContextUnavailableError";
|
|
23
25
|
constructor() {
|
|
24
26
|
super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
|
|
27
|
+
this.name = "LspRequestContextUnavailableError";
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
var storage = new AsyncLocalStorage;
|
|
@@ -41,7 +44,7 @@ function contextCwd() {
|
|
|
41
44
|
}
|
|
42
45
|
function createStandaloneMcpRequestContext(input = {}) {
|
|
43
46
|
const env = input.env ?? process.env;
|
|
44
|
-
const cwd = canonicalCwd(input.cwd ?? process.cwd());
|
|
47
|
+
const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
|
|
45
48
|
const home = input.homeDir ?? homedir();
|
|
46
49
|
const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
|
|
47
50
|
const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
|
|
@@ -179,7 +182,6 @@ function isPlainRecord(value) {
|
|
|
179
182
|
|
|
180
183
|
// src/daemon-request-error.ts
|
|
181
184
|
class DaemonRequestError extends Error {
|
|
182
|
-
requestWritten;
|
|
183
185
|
constructor(message, requestWritten) {
|
|
184
186
|
super(message);
|
|
185
187
|
this.name = "DaemonRequestError";
|
|
@@ -202,7 +204,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
|
|
|
202
204
|
}
|
|
203
205
|
|
|
204
206
|
class DaemonRequestTimedOutError extends DaemonRequestError {
|
|
205
|
-
timeoutMs;
|
|
206
207
|
constructor(requestWritten, timeoutMs) {
|
|
207
208
|
super("daemon request timed out", requestWritten);
|
|
208
209
|
this.name = "DaemonRequestTimedOutError";
|
|
@@ -281,14 +282,12 @@ var PROTOCOL_ERROR_CODE = -32002;
|
|
|
281
282
|
var AUTH_TOKEN_BYTES = 32;
|
|
282
283
|
|
|
283
284
|
class UnsafePrivateDirectoryError extends Error {
|
|
284
|
-
path;
|
|
285
|
-
reason;
|
|
286
|
-
name = "UnsafePrivateDirectoryError";
|
|
287
|
-
code = "unsafe_private_directory";
|
|
288
285
|
constructor(path, reason) {
|
|
289
286
|
super(`unsafe private directory ${path}: ${reason}`);
|
|
290
287
|
this.path = path;
|
|
291
288
|
this.reason = reason;
|
|
289
|
+
this.name = "UnsafePrivateDirectoryError";
|
|
290
|
+
this.code = "unsafe_private_directory";
|
|
292
291
|
}
|
|
293
292
|
}
|
|
294
293
|
function authEnvelope(token) {
|
|
@@ -472,20 +471,18 @@ var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
|
|
|
472
471
|
var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
473
472
|
|
|
474
473
|
class InvalidRuntimeOverrideError extends Error {
|
|
475
|
-
code = "invalid_runtime_override";
|
|
476
|
-
reason;
|
|
477
474
|
constructor(reason, message) {
|
|
478
475
|
super(message);
|
|
476
|
+
this.code = "invalid_runtime_override";
|
|
479
477
|
this.name = "InvalidRuntimeOverrideError";
|
|
480
478
|
this.reason = reason;
|
|
481
479
|
}
|
|
482
480
|
}
|
|
483
481
|
|
|
484
482
|
class InvalidDaemonVersionError extends Error {
|
|
485
|
-
code = "invalid_daemon_version";
|
|
486
|
-
version;
|
|
487
483
|
constructor(version) {
|
|
488
484
|
super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
|
|
485
|
+
this.code = "invalid_daemon_version";
|
|
489
486
|
this.name = "InvalidDaemonVersionError";
|
|
490
487
|
this.version = version;
|
|
491
488
|
}
|
|
@@ -531,10 +528,9 @@ var requireFromHere = createRequire(import.meta.url);
|
|
|
531
528
|
var MAX_SOCKET_PATH_LENGTH = 100;
|
|
532
529
|
|
|
533
530
|
class InvalidDaemonDirectoryError extends Error {
|
|
534
|
-
code = "invalid_daemon_directory";
|
|
535
|
-
directory;
|
|
536
531
|
constructor(directory) {
|
|
537
532
|
super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
|
|
533
|
+
this.code = "invalid_daemon_directory";
|
|
538
534
|
this.name = "InvalidDaemonDirectoryError";
|
|
539
535
|
this.directory = directory;
|
|
540
536
|
}
|
|
@@ -729,7 +725,8 @@ function spawnDaemonProcess(paths) {
|
|
|
729
725
|
try {
|
|
730
726
|
const child = spawn(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
|
|
731
727
|
detached: true,
|
|
732
|
-
stdio: ["ignore", logFd, logFd]
|
|
728
|
+
stdio: ["ignore", logFd, logFd],
|
|
729
|
+
windowsHide: true
|
|
733
730
|
});
|
|
734
731
|
child.once("spawn", () => closeSync2(logFd));
|
|
735
732
|
child.once("error", (error) => {
|
|
@@ -1010,6 +1007,7 @@ async function runJsonRpcStdioServer(config) {
|
|
|
1010
1007
|
const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
|
|
1011
1008
|
isClosed = true;
|
|
1012
1009
|
config.onIdleTimeout?.();
|
|
1010
|
+
config.input.destroy();
|
|
1013
1011
|
});
|
|
1014
1012
|
const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
|
|
1015
1013
|
isClosed = true;
|
|
@@ -1106,7 +1104,11 @@ function createParentWatchdog(config, onDeadParent) {
|
|
|
1106
1104
|
const probeAlive = config.probeAlive ?? isProcessAlive;
|
|
1107
1105
|
let fired = false;
|
|
1108
1106
|
const timer = setInterval(() => {
|
|
1109
|
-
if (fired
|
|
1107
|
+
if (fired)
|
|
1108
|
+
return;
|
|
1109
|
+
const alive = probeAlive(parentPid);
|
|
1110
|
+
config.onPoll?.(alive);
|
|
1111
|
+
if (alive)
|
|
1110
1112
|
return;
|
|
1111
1113
|
fired = true;
|
|
1112
1114
|
onDeadParent(parentPid, pollIntervalMs);
|
|
@@ -1141,8 +1143,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
|
|
|
1141
1143
|
};
|
|
1142
1144
|
}
|
|
1143
1145
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
1144
|
-
import { existsSync as
|
|
1145
|
-
import { dirname as
|
|
1146
|
+
import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
|
|
1147
|
+
import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
|
|
1146
1148
|
|
|
1147
1149
|
// ../lsp-core/src/lsp/effective-extension.ts
|
|
1148
1150
|
import { basename as basename2, extname } from "node:path";
|
|
@@ -1156,22 +1158,15 @@ function effectiveExtension(filePath) {
|
|
|
1156
1158
|
|
|
1157
1159
|
// ../lsp-core/src/lsp/errors.ts
|
|
1158
1160
|
class LspConnectionClosedError extends Error {
|
|
1159
|
-
serverId;
|
|
1160
|
-
root;
|
|
1161
|
-
name = "LspConnectionClosedError";
|
|
1162
1161
|
constructor(serverId, root, message) {
|
|
1163
1162
|
super(message ?? `LSP connection closed for ${serverId} at ${root}`);
|
|
1164
1163
|
this.serverId = serverId;
|
|
1165
1164
|
this.root = root;
|
|
1165
|
+
this.name = "LspConnectionClosedError";
|
|
1166
1166
|
}
|
|
1167
1167
|
}
|
|
1168
1168
|
|
|
1169
1169
|
class LspProcessExitedError extends Error {
|
|
1170
|
-
serverId;
|
|
1171
|
-
root;
|
|
1172
|
-
exitCode;
|
|
1173
|
-
stderrTail;
|
|
1174
|
-
name = "LspProcessExitedError";
|
|
1175
1170
|
constructor(serverId, root, exitCode, stderrTail) {
|
|
1176
1171
|
const stderrSuffix = stderrTail ? `
|
|
1177
1172
|
stderr tail: ${stderrTail}` : "";
|
|
@@ -1180,46 +1175,59 @@ stderr tail: ${stderrTail}` : "";
|
|
|
1180
1175
|
this.root = root;
|
|
1181
1176
|
this.exitCode = exitCode;
|
|
1182
1177
|
this.stderrTail = stderrTail;
|
|
1178
|
+
this.name = "LspProcessExitedError";
|
|
1183
1179
|
}
|
|
1184
1180
|
}
|
|
1185
1181
|
|
|
1186
1182
|
class LspRequestTimeoutError extends Error {
|
|
1187
|
-
method;
|
|
1188
|
-
stderrTail;
|
|
1189
|
-
name = "LspRequestTimeoutError";
|
|
1190
1183
|
constructor(method, stderrTail) {
|
|
1191
1184
|
const stderrSuffix = stderrTail ? `
|
|
1192
1185
|
recent stderr: ${stderrTail}` : "";
|
|
1193
1186
|
super(`LSP request timeout (method: ${method})${stderrSuffix}`);
|
|
1194
1187
|
this.method = method;
|
|
1195
1188
|
this.stderrTail = stderrTail;
|
|
1189
|
+
this.name = "LspRequestTimeoutError";
|
|
1196
1190
|
}
|
|
1197
1191
|
}
|
|
1198
1192
|
|
|
1199
1193
|
class LspInvalidPathError extends Error {
|
|
1200
|
-
|
|
1194
|
+
constructor() {
|
|
1195
|
+
super(...arguments);
|
|
1196
|
+
this.name = "LspInvalidPathError";
|
|
1197
|
+
}
|
|
1201
1198
|
}
|
|
1202
1199
|
|
|
1203
1200
|
class LspServerLookupError extends Error {
|
|
1204
|
-
lookup;
|
|
1205
|
-
name = "LspServerLookupError";
|
|
1206
1201
|
constructor(message, lookup) {
|
|
1207
1202
|
super(message);
|
|
1208
1203
|
this.lookup = lookup;
|
|
1204
|
+
this.name = "LspServerLookupError";
|
|
1209
1205
|
}
|
|
1210
1206
|
}
|
|
1211
1207
|
|
|
1212
1208
|
class LspServerInitializingError extends Error {
|
|
1213
|
-
originalError;
|
|
1214
|
-
name = "LspServerInitializingError";
|
|
1215
1209
|
constructor(originalError) {
|
|
1216
1210
|
super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
|
|
1217
1211
|
this.originalError = originalError;
|
|
1212
|
+
this.name = "LspServerInitializingError";
|
|
1218
1213
|
}
|
|
1219
1214
|
}
|
|
1220
1215
|
|
|
1221
1216
|
class LspProcessSpawnError extends Error {
|
|
1222
|
-
|
|
1217
|
+
constructor() {
|
|
1218
|
+
super(...arguments);
|
|
1219
|
+
this.name = "LspProcessSpawnError";
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
class LspClientRespawnBudgetExceededError extends Error {
|
|
1224
|
+
constructor(serverId, root, retryLimit) {
|
|
1225
|
+
super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
|
|
1226
|
+
this.serverId = serverId;
|
|
1227
|
+
this.root = root;
|
|
1228
|
+
this.retryLimit = retryLimit;
|
|
1229
|
+
this.name = "LspClientRespawnBudgetExceededError";
|
|
1230
|
+
}
|
|
1223
1231
|
}
|
|
1224
1232
|
function isLspDeadConnectionError(err) {
|
|
1225
1233
|
return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
|
|
@@ -1242,6 +1250,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
|
1242
1250
|
// ../lsp-core/src/lsp/connection.ts
|
|
1243
1251
|
import { pathToFileURL } from "node:url";
|
|
1244
1252
|
|
|
1253
|
+
// ../lsp-core/src/lsp/timer-provider.ts
|
|
1254
|
+
var realTimerProvider = {
|
|
1255
|
+
now: () => Date.now(),
|
|
1256
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
1257
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1245
1260
|
// ../lsp-core/src/lsp/constants.ts
|
|
1246
1261
|
var DEFAULT_MAX_REFERENCES = 200;
|
|
1247
1262
|
var DEFAULT_MAX_SYMBOLS = 200;
|
|
@@ -1250,9 +1265,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
|
|
|
1250
1265
|
var REQUEST_TIMEOUT_MS = 15000;
|
|
1251
1266
|
var INIT_TIMEOUT_MS = 60000;
|
|
1252
1267
|
var IDLE_TIMEOUT_MS = 5 * 60000;
|
|
1268
|
+
var MAX_RESIDENT_CLIENTS = 6;
|
|
1253
1269
|
var REAPER_INTERVAL_MS = 60000;
|
|
1254
1270
|
var STOP_HARD_KILL_TIMEOUT_MS = 5000;
|
|
1255
1271
|
var STOP_SIGKILL_GRACE_MS = 1000;
|
|
1272
|
+
var CLIENT_RESPAWN_RETRY_LIMIT = 2;
|
|
1273
|
+
var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
|
|
1256
1274
|
|
|
1257
1275
|
// ../lsp-core/src/lsp/json-rpc-connection.ts
|
|
1258
1276
|
var HEADER_SEPARATOR2 = `\r
|
|
@@ -1264,20 +1282,31 @@ var METHOD_NOT_FOUND = -32601;
|
|
|
1264
1282
|
var INTERNAL_ERROR = -32603;
|
|
1265
1283
|
|
|
1266
1284
|
class JsonRpcConnection {
|
|
1267
|
-
reader;
|
|
1268
|
-
writer;
|
|
1269
|
-
pendingRequests = new Map;
|
|
1270
|
-
notificationHandlers = new Map;
|
|
1271
|
-
requestHandlers = new Map;
|
|
1272
|
-
closeHandlers = [];
|
|
1273
|
-
errorHandlers = [];
|
|
1274
|
-
inputBuffer = Buffer.alloc(0);
|
|
1275
|
-
nextRequestId = 1;
|
|
1276
|
-
listening = false;
|
|
1277
|
-
disposed = false;
|
|
1278
1285
|
constructor(reader, writer) {
|
|
1279
1286
|
this.reader = reader;
|
|
1280
1287
|
this.writer = writer;
|
|
1288
|
+
this.pendingRequests = new Map;
|
|
1289
|
+
this.notificationHandlers = new Map;
|
|
1290
|
+
this.requestHandlers = new Map;
|
|
1291
|
+
this.closeHandlers = [];
|
|
1292
|
+
this.errorHandlers = [];
|
|
1293
|
+
this.inputBuffer = Buffer.alloc(0);
|
|
1294
|
+
this.nextRequestId = 1;
|
|
1295
|
+
this.listening = false;
|
|
1296
|
+
this.disposed = false;
|
|
1297
|
+
this.handleData = (chunk) => {
|
|
1298
|
+
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
1299
|
+
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
1300
|
+
this.drainInputBuffer();
|
|
1301
|
+
};
|
|
1302
|
+
this.handleClose = () => {
|
|
1303
|
+
for (const handler of this.closeHandlers) {
|
|
1304
|
+
handler();
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
this.handleStreamError = (error) => {
|
|
1308
|
+
this.emitError(error);
|
|
1309
|
+
};
|
|
1281
1310
|
}
|
|
1282
1311
|
listen() {
|
|
1283
1312
|
if (this.listening)
|
|
@@ -1398,19 +1427,6 @@ class JsonRpcConnection {
|
|
|
1398
1427
|
this.notificationHandlers.clear();
|
|
1399
1428
|
this.requestHandlers.clear();
|
|
1400
1429
|
}
|
|
1401
|
-
handleData = (chunk) => {
|
|
1402
|
-
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
1403
|
-
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
1404
|
-
this.drainInputBuffer();
|
|
1405
|
-
};
|
|
1406
|
-
handleClose = () => {
|
|
1407
|
-
for (const handler of this.closeHandlers) {
|
|
1408
|
-
handler();
|
|
1409
|
-
}
|
|
1410
|
-
};
|
|
1411
|
-
handleStreamError = (error) => {
|
|
1412
|
-
this.emitError(error);
|
|
1413
|
-
};
|
|
1414
1430
|
drainInputBuffer() {
|
|
1415
1431
|
while (true) {
|
|
1416
1432
|
const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
|
|
@@ -1758,33 +1774,29 @@ function isPosition(value) {
|
|
|
1758
1774
|
|
|
1759
1775
|
// ../lsp-core/src/lsp/transport.ts
|
|
1760
1776
|
class LspClientNotStartedError extends Error {
|
|
1761
|
-
serverId;
|
|
1762
|
-
root;
|
|
1763
|
-
name = "LspClientNotStartedError";
|
|
1764
1777
|
constructor(serverId, root) {
|
|
1765
1778
|
super("LSP client not started");
|
|
1766
1779
|
this.serverId = serverId;
|
|
1767
1780
|
this.root = root;
|
|
1781
|
+
this.name = "LspClientNotStartedError";
|
|
1768
1782
|
}
|
|
1769
1783
|
}
|
|
1770
1784
|
|
|
1771
1785
|
class LspClientTransport {
|
|
1772
|
-
root;
|
|
1773
|
-
server;
|
|
1774
|
-
proc = null;
|
|
1775
|
-
connection = null;
|
|
1776
|
-
stderrBuffer = [];
|
|
1777
|
-
processExited = false;
|
|
1778
|
-
diagnosticsStore = new Map;
|
|
1779
|
-
requestTimeoutMs;
|
|
1780
|
-
initializeTimeoutMs;
|
|
1781
|
-
workspaceApplyEditHandler = null;
|
|
1782
|
-
diagnosticPullSupported = false;
|
|
1783
1786
|
constructor(root, server2, timeouts = {}) {
|
|
1784
1787
|
this.root = root;
|
|
1785
1788
|
this.server = server2;
|
|
1789
|
+
this.proc = null;
|
|
1790
|
+
this.connection = null;
|
|
1791
|
+
this.stderrBuffer = [];
|
|
1792
|
+
this.processExited = false;
|
|
1793
|
+
this.diagnosticsStore = new Map;
|
|
1794
|
+
this.workspaceApplyEditHandler = null;
|
|
1795
|
+
this.diagnosticPullSupported = false;
|
|
1796
|
+
this.documentFormattingSupported = false;
|
|
1786
1797
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
1787
1798
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
1799
|
+
this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
|
|
1788
1800
|
}
|
|
1789
1801
|
pid() {
|
|
1790
1802
|
return this.proc?.pid;
|
|
@@ -1804,6 +1816,12 @@ class LspClientTransport {
|
|
|
1804
1816
|
isDiagnosticPullSupported() {
|
|
1805
1817
|
return this.diagnosticPullSupported;
|
|
1806
1818
|
}
|
|
1819
|
+
setDocumentFormattingSupported(supported) {
|
|
1820
|
+
this.documentFormattingSupported = supported;
|
|
1821
|
+
}
|
|
1822
|
+
isDocumentFormattingSupported() {
|
|
1823
|
+
return this.documentFormattingSupported;
|
|
1824
|
+
}
|
|
1807
1825
|
handlePublishDiagnostics(params) {
|
|
1808
1826
|
this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
|
|
1809
1827
|
}
|
|
@@ -1879,7 +1897,7 @@ class LspClientTransport {
|
|
|
1879
1897
|
const options = args[1];
|
|
1880
1898
|
const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
|
|
1881
1899
|
const timeoutController = new AbortController;
|
|
1882
|
-
const timeoutHandle = setTimeout(() => {
|
|
1900
|
+
const timeoutHandle = this.timerProvider.setTimeout(() => {
|
|
1883
1901
|
const stderrTail = this.stderrBuffer.slice(-5).join(`
|
|
1884
1902
|
`);
|
|
1885
1903
|
timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
|
|
@@ -1898,7 +1916,7 @@ class LspClientTransport {
|
|
|
1898
1916
|
}
|
|
1899
1917
|
throw error;
|
|
1900
1918
|
} finally {
|
|
1901
|
-
clearTimeout(timeoutHandle);
|
|
1919
|
+
this.timerProvider.clearTimeout(timeoutHandle);
|
|
1902
1920
|
combinedSignal.dispose();
|
|
1903
1921
|
}
|
|
1904
1922
|
}
|
|
@@ -2017,6 +2035,14 @@ function supportsDiagnosticPull(capabilities) {
|
|
|
2017
2035
|
return false;
|
|
2018
2036
|
return Object.hasOwn(capabilities, "diagnosticProvider");
|
|
2019
2037
|
}
|
|
2038
|
+
function supportsDocumentFormatting(capabilities) {
|
|
2039
|
+
if (capabilities === undefined)
|
|
2040
|
+
return false;
|
|
2041
|
+
const provider = capabilities.documentFormattingProvider;
|
|
2042
|
+
if (provider === undefined || provider === null || provider === false)
|
|
2043
|
+
return false;
|
|
2044
|
+
return provider === true || typeof provider === "object";
|
|
2045
|
+
}
|
|
2020
2046
|
|
|
2021
2047
|
class LspClientConnection extends LspClientTransport {
|
|
2022
2048
|
async initialize() {
|
|
@@ -2033,6 +2059,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
2033
2059
|
references: {},
|
|
2034
2060
|
documentSymbol: { hierarchicalDocumentSymbolSupport: true },
|
|
2035
2061
|
publishDiagnostics: {},
|
|
2062
|
+
formatting: { dynamicRegistration: false },
|
|
2036
2063
|
rename: {
|
|
2037
2064
|
prepareSupport: true,
|
|
2038
2065
|
prepareSupportDefaultBehavior: 1
|
|
@@ -2074,6 +2101,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
2074
2101
|
initializationOptions: this.server.initialization
|
|
2075
2102
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
2076
2103
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
2104
|
+
this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
|
|
2077
2105
|
await this.sendNotification("initialized", {});
|
|
2078
2106
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
2079
2107
|
settings: { json: { validate: { enable: true } } }
|
|
@@ -2269,6 +2297,17 @@ function canonicalPath(filePath) {
|
|
|
2269
2297
|
return absolute;
|
|
2270
2298
|
}
|
|
2271
2299
|
}
|
|
2300
|
+
function normalizeDocumentUri(uri) {
|
|
2301
|
+
let decoded = uri;
|
|
2302
|
+
try {
|
|
2303
|
+
decoded = decodeURIComponent(uri);
|
|
2304
|
+
} catch {
|
|
2305
|
+
decoded = uri;
|
|
2306
|
+
}
|
|
2307
|
+
if (process.platform !== "win32")
|
|
2308
|
+
return decoded;
|
|
2309
|
+
return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
|
|
2310
|
+
}
|
|
2272
2311
|
function isSameOrDescendant(candidate, parent) {
|
|
2273
2312
|
const suffix = relative2(parent, candidate);
|
|
2274
2313
|
return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
|
|
@@ -2279,17 +2318,18 @@ function movedPath(candidate, oldPath, newPath) {
|
|
|
2279
2318
|
}
|
|
2280
2319
|
|
|
2281
2320
|
class WorkspaceDocumentState {
|
|
2282
|
-
sendNotification;
|
|
2283
|
-
clearDiagnostics;
|
|
2284
|
-
openDocuments = new Map;
|
|
2285
|
-
openByUri = new Map;
|
|
2286
|
-
openPromises = new Map;
|
|
2287
|
-
now;
|
|
2288
|
-
versionlessPublishQuiescenceMs;
|
|
2289
2321
|
constructor(sendNotification, clearDiagnostics, options = {}) {
|
|
2290
2322
|
this.sendNotification = sendNotification;
|
|
2291
2323
|
this.clearDiagnostics = clearDiagnostics;
|
|
2292
|
-
this.
|
|
2324
|
+
this.openDocuments = new Map;
|
|
2325
|
+
this.openByUri = new Map;
|
|
2326
|
+
this.openPromises = new Map;
|
|
2327
|
+
this.timerProvider = options.timerProvider ?? {
|
|
2328
|
+
now: options.now ?? (() => Date.now()),
|
|
2329
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
2330
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
2331
|
+
};
|
|
2332
|
+
this.now = () => this.timerProvider.now();
|
|
2293
2333
|
this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
|
|
2294
2334
|
}
|
|
2295
2335
|
async openFile(filePath) {
|
|
@@ -2311,7 +2351,7 @@ class WorkspaceDocumentState {
|
|
|
2311
2351
|
return this.openDocuments.get(canonicalPath(filePath))?.version;
|
|
2312
2352
|
}
|
|
2313
2353
|
getStoredDiagnostics(uri) {
|
|
2314
|
-
const state = this.openByUri.get(uri);
|
|
2354
|
+
const state = this.openByUri.get(normalizeDocumentUri(uri));
|
|
2315
2355
|
if (!state)
|
|
2316
2356
|
return [];
|
|
2317
2357
|
return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
|
|
@@ -2333,13 +2373,13 @@ class WorkspaceDocumentState {
|
|
|
2333
2373
|
return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
|
|
2334
2374
|
}
|
|
2335
2375
|
getPullCache(snapshot) {
|
|
2336
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2376
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2337
2377
|
if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
|
|
2338
2378
|
return null;
|
|
2339
2379
|
return state.pullCache;
|
|
2340
2380
|
}
|
|
2341
2381
|
recordPullDiagnostics(snapshot, report) {
|
|
2342
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2382
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2343
2383
|
if (!state)
|
|
2344
2384
|
return;
|
|
2345
2385
|
state.pullCache = {
|
|
@@ -2349,7 +2389,7 @@ class WorkspaceDocumentState {
|
|
|
2349
2389
|
};
|
|
2350
2390
|
}
|
|
2351
2391
|
recordPublishedDiagnostics(params) {
|
|
2352
|
-
const state = this.openByUri.get(params.uri);
|
|
2392
|
+
const state = this.openByUri.get(normalizeDocumentUri(params.uri));
|
|
2353
2393
|
if (!state)
|
|
2354
2394
|
return;
|
|
2355
2395
|
state.publishGeneration += 1;
|
|
@@ -2363,7 +2403,7 @@ class WorkspaceDocumentState {
|
|
|
2363
2403
|
this.notifyWaiters(state);
|
|
2364
2404
|
}
|
|
2365
2405
|
resolvePushDiagnostics(snapshot) {
|
|
2366
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2406
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2367
2407
|
if (!state?.lastPublish)
|
|
2368
2408
|
return { status: "missing" };
|
|
2369
2409
|
const publish = state.lastPublish;
|
|
@@ -2377,7 +2417,7 @@ class WorkspaceDocumentState {
|
|
|
2377
2417
|
return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
|
|
2378
2418
|
}
|
|
2379
2419
|
waitForDiagnosticsActivity(snapshot, timeoutMs) {
|
|
2380
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
2420
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2381
2421
|
if (!state || timeoutMs <= 0)
|
|
2382
2422
|
return Promise.resolve();
|
|
2383
2423
|
return new Promise((resolveActivity) => {
|
|
@@ -2386,11 +2426,11 @@ class WorkspaceDocumentState {
|
|
|
2386
2426
|
if (settled)
|
|
2387
2427
|
return;
|
|
2388
2428
|
settled = true;
|
|
2389
|
-
clearTimeout(timer);
|
|
2429
|
+
this.timerProvider.clearTimeout(timer);
|
|
2390
2430
|
state.waiters.delete(finish);
|
|
2391
2431
|
resolveActivity();
|
|
2392
2432
|
};
|
|
2393
|
-
const timer = setTimeout(finish, timeoutMs);
|
|
2433
|
+
const timer = this.timerProvider.setTimeout(finish, timeoutMs);
|
|
2394
2434
|
if (typeof timer.unref === "function")
|
|
2395
2435
|
timer.unref();
|
|
2396
2436
|
state.waiters.add(finish);
|
|
@@ -2498,7 +2538,7 @@ class WorkspaceDocumentState {
|
|
|
2498
2538
|
waiters: new Set
|
|
2499
2539
|
};
|
|
2500
2540
|
this.openDocuments.set(path2, state);
|
|
2501
|
-
this.openByUri.set(state.uri, state);
|
|
2541
|
+
this.openByUri.set(normalizeDocumentUri(state.uri), state);
|
|
2502
2542
|
this.notifyWaiters(state);
|
|
2503
2543
|
await this.sendNotification("textDocument/didOpen", {
|
|
2504
2544
|
textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
|
|
@@ -2523,7 +2563,7 @@ class WorkspaceDocumentState {
|
|
|
2523
2563
|
}
|
|
2524
2564
|
async closeDocument(state) {
|
|
2525
2565
|
this.openDocuments.delete(state.path);
|
|
2526
|
-
this.openByUri.delete(state.uri);
|
|
2566
|
+
this.openByUri.delete(normalizeDocumentUri(state.uri));
|
|
2527
2567
|
this.clearDiagnostics(state.uri);
|
|
2528
2568
|
this.notifyWaiters(state);
|
|
2529
2569
|
await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
|
|
@@ -2552,13 +2592,11 @@ import { dirname as dirname4, isAbsolute as isAbsolute4, relative as relative3,
|
|
|
2552
2592
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
2553
2593
|
|
|
2554
2594
|
class WorkspaceEditPathError extends Error {
|
|
2555
|
-
path;
|
|
2556
|
-
detail;
|
|
2557
|
-
name = "WorkspaceEditPathError";
|
|
2558
2595
|
constructor(path2, detail) {
|
|
2559
2596
|
super(`${detail}: ${path2}`);
|
|
2560
2597
|
this.path = path2;
|
|
2561
2598
|
this.detail = detail;
|
|
2599
|
+
this.name = "WorkspaceEditPathError";
|
|
2562
2600
|
}
|
|
2563
2601
|
}
|
|
2564
2602
|
function isPathInsideWorkspace(filePath, workspaceRoot) {
|
|
@@ -2850,13 +2888,11 @@ function canonicalFingerprint(operations) {
|
|
|
2850
2888
|
|
|
2851
2889
|
// ../lsp-core/src/lsp/workspace-edit-types.ts
|
|
2852
2890
|
class WorkspaceEditValidationError extends Error {
|
|
2853
|
-
changeIndex;
|
|
2854
|
-
detail;
|
|
2855
|
-
name = "WorkspaceEditValidationError";
|
|
2856
2891
|
constructor(changeIndex, detail) {
|
|
2857
2892
|
super(`change ${changeIndex}: ${detail}`);
|
|
2858
2893
|
this.changeIndex = changeIndex;
|
|
2859
2894
|
this.detail = detail;
|
|
2895
|
+
this.name = "WorkspaceEditValidationError";
|
|
2860
2896
|
}
|
|
2861
2897
|
}
|
|
2862
2898
|
|
|
@@ -3354,10 +3390,9 @@ function simulateDelete(operation, virtual) {
|
|
|
3354
3390
|
import { existsSync as existsSync6, lstatSync as lstatSync4, readdirSync as readdirSync2 } from "node:fs";
|
|
3355
3391
|
import { dirname as dirname6, resolve as resolve5 } from "node:path";
|
|
3356
3392
|
class WorkspaceSnapshotBuilder {
|
|
3357
|
-
workspaceRoot;
|
|
3358
|
-
snapshots = new Map;
|
|
3359
3393
|
constructor(workspaceRoot) {
|
|
3360
3394
|
this.workspaceRoot = workspaceRoot;
|
|
3395
|
+
this.snapshots = new Map;
|
|
3361
3396
|
}
|
|
3362
3397
|
build(operations) {
|
|
3363
3398
|
this.add(this.workspaceRoot, false);
|
|
@@ -3401,8 +3436,10 @@ function snapshotOperations(operations, workspaceRoot) {
|
|
|
3401
3436
|
|
|
3402
3437
|
// ../lsp-core/src/lsp/workspace-edit-plan.ts
|
|
3403
3438
|
class PlanPathIndex {
|
|
3404
|
-
|
|
3405
|
-
|
|
3439
|
+
constructor() {
|
|
3440
|
+
this.firstChangeByPath = new Map;
|
|
3441
|
+
this.reportedPathByCanonical = new Map;
|
|
3442
|
+
}
|
|
3406
3443
|
build(operations) {
|
|
3407
3444
|
for (const operation of operations) {
|
|
3408
3445
|
switch (operation.kind) {
|
|
@@ -3491,14 +3528,11 @@ function isRecord4(value) {
|
|
|
3491
3528
|
}
|
|
3492
3529
|
|
|
3493
3530
|
class WorkspaceMutationController {
|
|
3494
|
-
workspaceRoot;
|
|
3495
|
-
documents;
|
|
3496
|
-
activeLease = null;
|
|
3497
|
-
nextLeaseId = 1;
|
|
3498
|
-
io;
|
|
3499
3531
|
constructor(workspaceRoot, documents) {
|
|
3500
3532
|
this.workspaceRoot = workspaceRoot;
|
|
3501
3533
|
this.documents = documents;
|
|
3534
|
+
this.activeLease = null;
|
|
3535
|
+
this.nextLeaseId = 1;
|
|
3502
3536
|
}
|
|
3503
3537
|
setIo(io) {
|
|
3504
3538
|
this.io = io;
|
|
@@ -3611,14 +3645,12 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
|
|
|
3611
3645
|
var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
|
|
3612
3646
|
|
|
3613
3647
|
class LspClient extends LspClientConnection {
|
|
3614
|
-
diagnosticPullErrors = [];
|
|
3615
|
-
documents;
|
|
3616
|
-
workspaceMutations;
|
|
3617
|
-
diagnosticsFreshnessTimeoutMs;
|
|
3618
3648
|
constructor(root, server2, options = {}) {
|
|
3619
3649
|
super(root, server2, options);
|
|
3650
|
+
this.diagnosticPullErrors = [];
|
|
3620
3651
|
this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
|
|
3621
3652
|
this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
|
|
3653
|
+
timerProvider: this.timerProvider,
|
|
3622
3654
|
versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
|
|
3623
3655
|
});
|
|
3624
3656
|
this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
|
|
@@ -3671,6 +3703,18 @@ class LspClient extends LspClientConnection {
|
|
|
3671
3703
|
textDocument: { uri: pathToFileURL3(absPath).href }
|
|
3672
3704
|
}, options);
|
|
3673
3705
|
}
|
|
3706
|
+
async formatDocument(filePath, options, signal) {
|
|
3707
|
+
if (!this.isDocumentFormattingSupported())
|
|
3708
|
+
return null;
|
|
3709
|
+
const absPath = this.resolveWorkspacePath(filePath);
|
|
3710
|
+
await this.openFile(absPath);
|
|
3711
|
+
const requestOptions = signal === undefined ? {} : { signal };
|
|
3712
|
+
const edits = await this.sendRequest("textDocument/formatting", {
|
|
3713
|
+
textDocument: { uri: pathToFileURL3(absPath).href },
|
|
3714
|
+
options
|
|
3715
|
+
}, requestOptions);
|
|
3716
|
+
return edits ?? [];
|
|
3717
|
+
}
|
|
3674
3718
|
async workspaceSymbols(query, signal) {
|
|
3675
3719
|
const options = signal === undefined ? {} : { signal };
|
|
3676
3720
|
return this.sendRequest("workspace/symbol", { query }, options);
|
|
@@ -3710,7 +3754,7 @@ class LspClient extends LspClientConnection {
|
|
|
3710
3754
|
const absPath = this.resolveWorkspacePath(filePath);
|
|
3711
3755
|
const uri = pathToFileURL3(absPath).href;
|
|
3712
3756
|
await this.openFile(absPath);
|
|
3713
|
-
const deadlineAt =
|
|
3757
|
+
const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
|
|
3714
3758
|
for (;; ) {
|
|
3715
3759
|
signal?.throwIfAborted();
|
|
3716
3760
|
const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
|
|
@@ -3723,7 +3767,7 @@ class LspClient extends LspClientConnection {
|
|
|
3723
3767
|
if (!pushFallbackOnly) {
|
|
3724
3768
|
const cached = this.documents.getPullCache(snapshot);
|
|
3725
3769
|
try {
|
|
3726
|
-
const remainingMs2 = deadlineAt -
|
|
3770
|
+
const remainingMs2 = deadlineAt - this.timerProvider.now();
|
|
3727
3771
|
if (remainingMs2 <= 0)
|
|
3728
3772
|
return this.freshnessTimeout(absPath);
|
|
3729
3773
|
const result = await this.sendRequest("textDocument/diagnostic", {
|
|
@@ -3758,7 +3802,7 @@ class LspClient extends LspClientConnection {
|
|
|
3758
3802
|
}
|
|
3759
3803
|
if (!pushFallbackOnly)
|
|
3760
3804
|
continue;
|
|
3761
|
-
const remainingMs = deadlineAt -
|
|
3805
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
3762
3806
|
if (remainingMs <= 0) {
|
|
3763
3807
|
if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
|
|
3764
3808
|
const cached = this.documents.getPullCache(snapshot);
|
|
@@ -3916,18 +3960,16 @@ function awaitWithSignal2(promise, signal) {
|
|
|
3916
3960
|
}
|
|
3917
3961
|
|
|
3918
3962
|
class LspManager {
|
|
3919
|
-
clients = new Map;
|
|
3920
|
-
reaperHandle = null;
|
|
3921
|
-
signalDisposer = null;
|
|
3922
|
-
disposed = false;
|
|
3923
|
-
idleTimeoutMs;
|
|
3924
|
-
initTimeoutMs;
|
|
3925
|
-
reaperIntervalMs;
|
|
3926
|
-
clientFactory;
|
|
3927
|
-
now;
|
|
3928
3963
|
constructor(options = {}) {
|
|
3964
|
+
this.clients = new Map;
|
|
3965
|
+
this.pendingStops = new Map;
|
|
3966
|
+
this.respawnBudgets = new Map;
|
|
3967
|
+
this.reaperHandle = null;
|
|
3968
|
+
this.signalDisposer = null;
|
|
3969
|
+
this.disposed = false;
|
|
3929
3970
|
this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
|
|
3930
3971
|
this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
3972
|
+
this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
|
|
3931
3973
|
this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
|
|
3932
3974
|
this.clientFactory = options.clientFactory ?? ((root, server2) => new LspClient(root, server2));
|
|
3933
3975
|
this.now = options.now ?? (() => Date.now());
|
|
@@ -3947,24 +3989,79 @@ class LspManager {
|
|
|
3947
3989
|
getKey(root, serverId) {
|
|
3948
3990
|
return `${root}::${serverId}`;
|
|
3949
3991
|
}
|
|
3992
|
+
tombstoneStop(key, client) {
|
|
3993
|
+
const stop = stopClientBestEffort(client);
|
|
3994
|
+
this.pendingStops.set(key, stop);
|
|
3995
|
+
stop.finally(() => {
|
|
3996
|
+
if (this.pendingStops.get(key) === stop) {
|
|
3997
|
+
this.pendingStops.delete(key);
|
|
3998
|
+
}
|
|
3999
|
+
});
|
|
4000
|
+
return stop;
|
|
4001
|
+
}
|
|
4002
|
+
recordDeadGeneration(key) {
|
|
4003
|
+
let budget = this.respawnBudgets.get(key);
|
|
4004
|
+
if (budget === undefined) {
|
|
4005
|
+
budget = { deadGenerations: 0, exhaustedAt: null };
|
|
4006
|
+
this.respawnBudgets.set(key, budget);
|
|
4007
|
+
}
|
|
4008
|
+
budget.deadGenerations += 1;
|
|
4009
|
+
}
|
|
4010
|
+
markHealthyGeneration(key) {
|
|
4011
|
+
this.respawnBudgets.delete(key);
|
|
4012
|
+
}
|
|
4013
|
+
ensureRespawnAllowed(key, root, serverId) {
|
|
4014
|
+
const budget = this.respawnBudgets.get(key);
|
|
4015
|
+
if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
|
|
4016
|
+
return;
|
|
4017
|
+
if (budget.exhaustedAt === null) {
|
|
4018
|
+
budget.exhaustedAt = this.now();
|
|
4019
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
4020
|
+
}
|
|
4021
|
+
if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
|
|
4022
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
4023
|
+
}
|
|
4024
|
+
budget.deadGenerations = 0;
|
|
4025
|
+
budget.exhaustedAt = null;
|
|
4026
|
+
}
|
|
3950
4027
|
reapStale() {
|
|
3951
4028
|
const t = this.now();
|
|
3952
4029
|
for (const [key, managed] of this.clients) {
|
|
3953
4030
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3954
|
-
stopClientBestEffort(managed.client);
|
|
3955
4031
|
this.clients.delete(key);
|
|
4032
|
+
this.tombstoneStop(key, managed.client);
|
|
3956
4033
|
continue;
|
|
3957
4034
|
}
|
|
3958
4035
|
if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
|
|
3959
|
-
stopClientBestEffort(managed.client);
|
|
3960
4036
|
this.clients.delete(key);
|
|
4037
|
+
this.tombstoneStop(key, managed.client);
|
|
4038
|
+
}
|
|
4039
|
+
}
|
|
4040
|
+
}
|
|
4041
|
+
evictForAdmission() {
|
|
4042
|
+
while (this.clients.size >= this.maxResidentClients) {
|
|
4043
|
+
const victim = this.leastRecentlyUsedIdleClient();
|
|
4044
|
+
if (!victim)
|
|
4045
|
+
return;
|
|
4046
|
+
this.clients.delete(victim.key);
|
|
4047
|
+
this.tombstoneStop(victim.key, victim.managed.client);
|
|
4048
|
+
}
|
|
4049
|
+
}
|
|
4050
|
+
leastRecentlyUsedIdleClient() {
|
|
4051
|
+
let candidate = null;
|
|
4052
|
+
for (const [key, managed] of this.clients) {
|
|
4053
|
+
if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
|
|
4054
|
+
continue;
|
|
4055
|
+
if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
|
|
4056
|
+
candidate = { key, managed };
|
|
3961
4057
|
}
|
|
3962
4058
|
}
|
|
4059
|
+
return candidate;
|
|
3963
4060
|
}
|
|
3964
4061
|
async tryDeleteIfOrphaned(key, managed) {
|
|
3965
4062
|
if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
|
|
3966
4063
|
this.clients.delete(key);
|
|
3967
|
-
await
|
|
4064
|
+
await this.tombstoneStop(key, managed.client);
|
|
3968
4065
|
}
|
|
3969
4066
|
}
|
|
3970
4067
|
async getClient(root, server2, signal) {
|
|
@@ -3973,12 +4070,22 @@ class LspManager {
|
|
|
3973
4070
|
}
|
|
3974
4071
|
signal?.throwIfAborted();
|
|
3975
4072
|
const key = this.getKey(root, server2.id);
|
|
4073
|
+
for (;; ) {
|
|
4074
|
+
const pendingStop = this.pendingStops.get(key);
|
|
4075
|
+
if (pendingStop === undefined)
|
|
4076
|
+
break;
|
|
4077
|
+
await awaitWithSignal2(pendingStop, signal);
|
|
4078
|
+
signal?.throwIfAborted();
|
|
4079
|
+
}
|
|
4080
|
+
if (this.disposed) {
|
|
4081
|
+
throw new Error("LspManager has been disposed");
|
|
4082
|
+
}
|
|
3976
4083
|
let managed = this.clients.get(key);
|
|
3977
4084
|
if (managed) {
|
|
3978
4085
|
const t = this.now();
|
|
3979
4086
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3980
|
-
await stopClientBestEffort(managed.client);
|
|
3981
4087
|
this.clients.delete(key);
|
|
4088
|
+
await this.tombstoneStop(key, managed.client);
|
|
3982
4089
|
managed = undefined;
|
|
3983
4090
|
}
|
|
3984
4091
|
}
|
|
@@ -3999,14 +4106,20 @@ class LspManager {
|
|
|
3999
4106
|
signal.throwIfAborted();
|
|
4000
4107
|
}
|
|
4001
4108
|
if (!managed.client.isAlive()) {
|
|
4002
|
-
|
|
4003
|
-
this.clients.
|
|
4109
|
+
this.recordDeadGeneration(key);
|
|
4110
|
+
if (this.clients.get(key) === managed) {
|
|
4111
|
+
this.clients.delete(key);
|
|
4112
|
+
}
|
|
4113
|
+
await this.tombstoneStop(key, managed.client);
|
|
4004
4114
|
return this.getClient(root, server2, signal);
|
|
4005
4115
|
}
|
|
4116
|
+
this.markHealthyGeneration(key);
|
|
4006
4117
|
managed.refCount++;
|
|
4007
4118
|
managed.lastUsedAt = this.now();
|
|
4008
4119
|
return managed.client;
|
|
4009
4120
|
}
|
|
4121
|
+
this.evictForAdmission();
|
|
4122
|
+
this.ensureRespawnAllowed(key, root, server2.id);
|
|
4010
4123
|
const client = this.clientFactory(root, server2);
|
|
4011
4124
|
const initStartedAt = this.now();
|
|
4012
4125
|
const initPromise = (async () => {
|
|
@@ -4030,7 +4143,7 @@ class LspManager {
|
|
|
4030
4143
|
if (this.clients.get(key) === newManaged) {
|
|
4031
4144
|
this.clients.delete(key);
|
|
4032
4145
|
}
|
|
4033
|
-
await
|
|
4146
|
+
await this.tombstoneStop(key, client);
|
|
4034
4147
|
throw err;
|
|
4035
4148
|
}
|
|
4036
4149
|
newManaged.pendingWaiters--;
|
|
@@ -4041,6 +4154,15 @@ class LspManager {
|
|
|
4041
4154
|
await this.tryDeleteIfOrphaned(key, newManaged);
|
|
4042
4155
|
signal.throwIfAborted();
|
|
4043
4156
|
}
|
|
4157
|
+
if (!client.isAlive()) {
|
|
4158
|
+
this.recordDeadGeneration(key);
|
|
4159
|
+
if (this.clients.get(key) === newManaged) {
|
|
4160
|
+
this.clients.delete(key);
|
|
4161
|
+
}
|
|
4162
|
+
await this.tombstoneStop(key, client);
|
|
4163
|
+
return this.getClient(root, server2, signal);
|
|
4164
|
+
}
|
|
4165
|
+
this.markHealthyGeneration(key);
|
|
4044
4166
|
newManaged.refCount++;
|
|
4045
4167
|
newManaged.lastUsedAt = this.now();
|
|
4046
4168
|
return client;
|
|
@@ -4061,14 +4183,20 @@ class LspManager {
|
|
|
4061
4183
|
if (client && managed.client !== client)
|
|
4062
4184
|
return;
|
|
4063
4185
|
this.clients.delete(key);
|
|
4064
|
-
|
|
4186
|
+
this.tombstoneStop(key, managed.client);
|
|
4065
4187
|
}
|
|
4066
4188
|
warmupClient(root, server2) {
|
|
4067
4189
|
if (this.disposed)
|
|
4068
4190
|
return;
|
|
4069
4191
|
const key = this.getKey(root, server2.id);
|
|
4070
|
-
if (this.clients.has(key))
|
|
4192
|
+
if (this.clients.has(key) || this.pendingStops.has(key))
|
|
4193
|
+
return;
|
|
4194
|
+
this.evictForAdmission();
|
|
4195
|
+
try {
|
|
4196
|
+
this.ensureRespawnAllowed(key, root, server2.id);
|
|
4197
|
+
} catch {
|
|
4071
4198
|
return;
|
|
4199
|
+
}
|
|
4072
4200
|
const client = this.clientFactory(root, server2);
|
|
4073
4201
|
const initStartedAt = this.now();
|
|
4074
4202
|
const initPromise = (async () => {
|
|
@@ -4094,7 +4222,7 @@ class LspManager {
|
|
|
4094
4222
|
if (this.clients.get(key) === managed) {
|
|
4095
4223
|
this.clients.delete(key);
|
|
4096
4224
|
}
|
|
4097
|
-
|
|
4225
|
+
this.tombstoneStop(key, client);
|
|
4098
4226
|
});
|
|
4099
4227
|
}
|
|
4100
4228
|
isServerInitializing(root, serverId) {
|
|
@@ -4138,8 +4266,11 @@ class LspManager {
|
|
|
4138
4266
|
for (const managed of this.clients.values()) {
|
|
4139
4267
|
stopPromises.push(stopClientBestEffort(managed.client));
|
|
4140
4268
|
}
|
|
4269
|
+
const tombstonedStops = [...this.pendingStops.values()];
|
|
4141
4270
|
this.clients.clear();
|
|
4142
|
-
|
|
4271
|
+
this.respawnBudgets.clear();
|
|
4272
|
+
await Promise.allSettled([...stopPromises, ...tombstonedStops]);
|
|
4273
|
+
this.pendingStops.clear();
|
|
4143
4274
|
}
|
|
4144
4275
|
}
|
|
4145
4276
|
var _defaultInstance = null;
|
|
@@ -4157,57 +4288,52 @@ async function disposeDefaultLspManager() {
|
|
|
4157
4288
|
}
|
|
4158
4289
|
}
|
|
4159
4290
|
|
|
4160
|
-
// ../lsp-core/src/lsp/
|
|
4161
|
-
import { existsSync as existsSync7,
|
|
4162
|
-
import { dirname as dirname7 } from "node:path";
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4291
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
4292
|
+
import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
|
|
4293
|
+
import { dirname as dirname7, join as join3 } from "node:path";
|
|
4294
|
+
|
|
4295
|
+
// ../lsp-core/src/lsp/workspace-markers.ts
|
|
4296
|
+
var GIT_WORKSPACE_MARKER = ".git";
|
|
4297
|
+
var PROJECT_WORKSPACE_MARKERS = [
|
|
4298
|
+
"package.json",
|
|
4299
|
+
"pyproject.toml",
|
|
4300
|
+
"Cargo.toml",
|
|
4301
|
+
"go.mod",
|
|
4302
|
+
"pom.xml",
|
|
4303
|
+
"build.gradle"
|
|
4304
|
+
];
|
|
4305
|
+
var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
|
|
4306
|
+
|
|
4307
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
4308
|
+
function findWorkspaceRootOutsideContext(directory) {
|
|
4309
|
+
const marked = nearestMarkedAncestor(directory);
|
|
4310
|
+
if (marked !== undefined)
|
|
4311
|
+
return marked;
|
|
4312
|
+
return realpathSync4(nearestExistingAncestor(directory));
|
|
4313
|
+
}
|
|
4314
|
+
function nearestMarkedAncestor(directory) {
|
|
4315
|
+
let current = directory;
|
|
4316
|
+
for (;; ) {
|
|
4317
|
+
if (existsSync7(current) && WORKSPACE_MARKERS.some((marker) => existsSync7(join3(current, marker)))) {
|
|
4318
|
+
return realpathSync4(current);
|
|
4319
|
+
}
|
|
4320
|
+
const parent = dirname7(current);
|
|
4321
|
+
if (parent === current)
|
|
4322
|
+
return;
|
|
4323
|
+
current = parent;
|
|
4175
4324
|
}
|
|
4176
4325
|
}
|
|
4177
|
-
function
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
}
|
|
4185
|
-
|
|
4186
|
-
return value === "declined" || value === "allowed";
|
|
4187
|
-
}
|
|
4188
|
-
function writeInstallDecisions(decisions) {
|
|
4189
|
-
const path2 = getInstallDecisionsPath();
|
|
4190
|
-
mkdirSync3(dirname7(path2), { recursive: true });
|
|
4191
|
-
const tmpPath = `${path2}.tmp`;
|
|
4192
|
-
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
4193
|
-
`, "utf8");
|
|
4194
|
-
renameSync2(tmpPath, path2);
|
|
4195
|
-
}
|
|
4196
|
-
function isInstallDecisions(value) {
|
|
4197
|
-
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
4198
|
-
}
|
|
4199
|
-
function isInstallDecisionRecord(value) {
|
|
4200
|
-
if (!isRecord5(value))
|
|
4201
|
-
return false;
|
|
4202
|
-
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
4203
|
-
}
|
|
4204
|
-
function isRecord5(value) {
|
|
4205
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4326
|
+
function nearestExistingAncestor(directory) {
|
|
4327
|
+
let current = directory;
|
|
4328
|
+
while (!existsSync7(current)) {
|
|
4329
|
+
const parent = dirname7(current);
|
|
4330
|
+
if (parent === current)
|
|
4331
|
+
return current;
|
|
4332
|
+
current = parent;
|
|
4333
|
+
}
|
|
4334
|
+
return current;
|
|
4206
4335
|
}
|
|
4207
4336
|
|
|
4208
|
-
// ../lsp-core/src/lsp/config-loader.ts
|
|
4209
|
-
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
|
|
4210
|
-
|
|
4211
4337
|
// ../lsp-core/src/lsp/server-definitions.ts
|
|
4212
4338
|
var LSP_INSTALL_HINTS = {
|
|
4213
4339
|
typescript: "npm install -g typescript-language-server typescript",
|
|
@@ -4253,6 +4379,26 @@ var LSP_INSTALL_HINTS = {
|
|
|
4253
4379
|
julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
|
|
4254
4380
|
razor: "Razor runs through the Roslyn language server (cohosting). " + "Install: dotnet tool install -g roslyn-language-server --prerelease (requires v5.8.0+). See https://github.com/dotnet/razor"
|
|
4255
4381
|
};
|
|
4382
|
+
var LSP_LOCAL_INSTALL_HINTS = {
|
|
4383
|
+
typescript: "bun add -d typescript-language-server typescript",
|
|
4384
|
+
vue: "bun add -d @vue/language-server",
|
|
4385
|
+
eslint: "bun add -d vscode-langservers-extracted",
|
|
4386
|
+
oxlint: "bun add -d oxlint",
|
|
4387
|
+
biome: "bun add -d @biomejs/biome",
|
|
4388
|
+
svelte: "bun add -d svelte-language-server",
|
|
4389
|
+
astro: "bun add -d @astrojs/language-server",
|
|
4390
|
+
bash: "bun add -d bash-language-server",
|
|
4391
|
+
"bash-ls": "bun add -d bash-language-server",
|
|
4392
|
+
"yaml-ls": "bun add -d yaml-language-server",
|
|
4393
|
+
php: "bun add -d intelephense",
|
|
4394
|
+
prisma: "bun add -d prisma",
|
|
4395
|
+
dockerfile: "bun add -d dockerfile-language-server-nodejs",
|
|
4396
|
+
pyright: "uv add --dev pyright",
|
|
4397
|
+
basedpyright: "uv add --dev basedpyright",
|
|
4398
|
+
ruff: "uv add --dev ruff",
|
|
4399
|
+
ty: "uv add --dev ty",
|
|
4400
|
+
"ruby-lsp": "bundle add ruby-lsp --group development"
|
|
4401
|
+
};
|
|
4256
4402
|
var BUILTIN_SERVERS = {
|
|
4257
4403
|
typescript: {
|
|
4258
4404
|
command: ["typescript-language-server", "--stdio"],
|
|
@@ -4355,7 +4501,56 @@ var BUILTIN_SERVERS = {
|
|
|
4355
4501
|
}
|
|
4356
4502
|
};
|
|
4357
4503
|
|
|
4504
|
+
// ../lsp-core/src/lsp/server-install-state.ts
|
|
4505
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
4506
|
+
import { dirname as dirname8 } from "node:path";
|
|
4507
|
+
function getInstallDecisionsPath() {
|
|
4508
|
+
return lspRequestContext().installDecisionsPath;
|
|
4509
|
+
}
|
|
4510
|
+
function loadInstallDecisions() {
|
|
4511
|
+
const path2 = getInstallDecisionsPath();
|
|
4512
|
+
if (!existsSync8(path2))
|
|
4513
|
+
return {};
|
|
4514
|
+
try {
|
|
4515
|
+
const parsed = JSON.parse(readFileSync4(path2, "utf8"));
|
|
4516
|
+
return isInstallDecisions(parsed) ? parsed : {};
|
|
4517
|
+
} catch {
|
|
4518
|
+
return {};
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
function loadInstallDecision(serverId) {
|
|
4522
|
+
return loadInstallDecisions()[serverId];
|
|
4523
|
+
}
|
|
4524
|
+
function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
|
|
4525
|
+
const decisions = loadInstallDecisions();
|
|
4526
|
+
decisions[serverId] = { decision, decidedAt };
|
|
4527
|
+
writeInstallDecisions(decisions);
|
|
4528
|
+
}
|
|
4529
|
+
function isInstallDecision(value) {
|
|
4530
|
+
return value === "declined" || value === "allowed";
|
|
4531
|
+
}
|
|
4532
|
+
function writeInstallDecisions(decisions) {
|
|
4533
|
+
const path2 = getInstallDecisionsPath();
|
|
4534
|
+
mkdirSync3(dirname8(path2), { recursive: true });
|
|
4535
|
+
const tmpPath = `${path2}.tmp`;
|
|
4536
|
+
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
4537
|
+
`, "utf8");
|
|
4538
|
+
renameSync2(tmpPath, path2);
|
|
4539
|
+
}
|
|
4540
|
+
function isInstallDecisions(value) {
|
|
4541
|
+
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
4542
|
+
}
|
|
4543
|
+
function isInstallDecisionRecord(value) {
|
|
4544
|
+
if (!isRecord5(value))
|
|
4545
|
+
return false;
|
|
4546
|
+
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
4547
|
+
}
|
|
4548
|
+
function isRecord5(value) {
|
|
4549
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4550
|
+
}
|
|
4551
|
+
|
|
4358
4552
|
// ../lsp-core/src/lsp/config-loader.ts
|
|
4553
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
|
|
4359
4554
|
function getProjectConfigPaths() {
|
|
4360
4555
|
return lspRequestContext().projectConfigPaths;
|
|
4361
4556
|
}
|
|
@@ -4363,7 +4558,7 @@ function getUserConfigPath() {
|
|
|
4363
4558
|
return lspRequestContext().userConfigPath;
|
|
4364
4559
|
}
|
|
4365
4560
|
function loadJsonFile(path2) {
|
|
4366
|
-
if (!
|
|
4561
|
+
if (!existsSync9(path2))
|
|
4367
4562
|
return null;
|
|
4368
4563
|
try {
|
|
4369
4564
|
const parsed = JSON.parse(readFileSync5(path2, "utf-8"));
|
|
@@ -4551,54 +4746,155 @@ function getDisabledServerIds() {
|
|
|
4551
4746
|
}
|
|
4552
4747
|
|
|
4553
4748
|
// ../lsp-core/src/lsp/server-installation.ts
|
|
4554
|
-
import { existsSync as
|
|
4555
|
-
import { delimiter as delimiter3, join as
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4749
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
4750
|
+
import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
|
|
4751
|
+
var LOCAL_BIN_RULES = [
|
|
4752
|
+
{
|
|
4753
|
+
markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
|
|
4754
|
+
binDirs: [join4("node_modules", ".bin")]
|
|
4755
|
+
},
|
|
4756
|
+
{
|
|
4757
|
+
markers: [
|
|
4758
|
+
"pyproject.toml",
|
|
4759
|
+
"ty.toml",
|
|
4760
|
+
"requirements.txt",
|
|
4761
|
+
"setup.py",
|
|
4762
|
+
"setup.cfg",
|
|
4763
|
+
"Pipfile",
|
|
4764
|
+
"pyrightconfig.json",
|
|
4765
|
+
"ruff.toml",
|
|
4766
|
+
".ruff.toml"
|
|
4767
|
+
],
|
|
4768
|
+
binDirs: [
|
|
4769
|
+
join4(".venv", "bin"),
|
|
4770
|
+
join4(".venv", "Scripts"),
|
|
4771
|
+
join4("venv", "bin"),
|
|
4772
|
+
join4("venv", "Scripts"),
|
|
4773
|
+
join4(".env", "bin"),
|
|
4774
|
+
join4(".env", "Scripts")
|
|
4775
|
+
]
|
|
4776
|
+
},
|
|
4777
|
+
{
|
|
4778
|
+
markers: ["Gemfile", "Gemfile.lock"],
|
|
4779
|
+
binDirs: [join4("vendor", "bundle", "bin"), "bin"]
|
|
4780
|
+
},
|
|
4781
|
+
{
|
|
4782
|
+
markers: ["go.mod", "go.sum", "go.work"],
|
|
4783
|
+
binDirs: ["bin"]
|
|
4565
4784
|
}
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4785
|
+
];
|
|
4786
|
+
var resolutionCache = new Map;
|
|
4787
|
+
var probeCount = 0;
|
|
4788
|
+
function probe(path2) {
|
|
4789
|
+
probeCount += 1;
|
|
4790
|
+
return existsSync10(path2);
|
|
4791
|
+
}
|
|
4792
|
+
function executableSuffixes(platform, pathExt) {
|
|
4793
|
+
if (platform !== "win32")
|
|
4794
|
+
return [""];
|
|
4795
|
+
const configured = pathExt ?? process.env["PATHEXT"] ?? "";
|
|
4796
|
+
const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
|
|
4797
|
+
return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
|
|
4798
|
+
}
|
|
4799
|
+
function probeWithSuffixes(directory, command, suffixes) {
|
|
4800
|
+
for (const suffix of suffixes) {
|
|
4801
|
+
const candidate = join4(directory, command + suffix);
|
|
4802
|
+
if (probe(candidate))
|
|
4803
|
+
return candidate;
|
|
4804
|
+
}
|
|
4805
|
+
return null;
|
|
4806
|
+
}
|
|
4807
|
+
function resolveLocal(command, workingDirectory, suffixes, stopAt) {
|
|
4808
|
+
const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
|
|
4809
|
+
let current = resolve7(workingDirectory);
|
|
4810
|
+
while (true) {
|
|
4811
|
+
for (const rule of LOCAL_BIN_RULES) {
|
|
4812
|
+
if (!rule.markers.some((marker) => probe(join4(current, marker))))
|
|
4813
|
+
continue;
|
|
4814
|
+
for (const binDir of rule.binDirs) {
|
|
4815
|
+
const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
|
|
4816
|
+
if (found !== null)
|
|
4817
|
+
return found;
|
|
4818
|
+
}
|
|
4575
4819
|
}
|
|
4820
|
+
if (probe(join4(current, ".git")))
|
|
4821
|
+
return null;
|
|
4822
|
+
if (boundary !== undefined && current === boundary)
|
|
4823
|
+
return null;
|
|
4824
|
+
const parent = dirname9(current);
|
|
4825
|
+
if (parent === current)
|
|
4826
|
+
return null;
|
|
4827
|
+
current = parent;
|
|
4576
4828
|
}
|
|
4577
|
-
|
|
4578
|
-
|
|
4829
|
+
}
|
|
4830
|
+
function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
|
|
4831
|
+
let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
|
|
4832
|
+
if (platform === "win32" && !pathEnv) {
|
|
4579
4833
|
pathEnv = process.env["Path"] ?? "";
|
|
4580
4834
|
}
|
|
4581
|
-
const
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
}
|
|
4835
|
+
for (const entry of pathEnv.split(delimiter3)) {
|
|
4836
|
+
if (entry.length === 0)
|
|
4837
|
+
continue;
|
|
4838
|
+
const found = probeWithSuffixes(entry, command, suffixes);
|
|
4839
|
+
if (found !== null)
|
|
4840
|
+
return found;
|
|
4588
4841
|
}
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4842
|
+
return null;
|
|
4843
|
+
}
|
|
4844
|
+
function resolveServerBinary(command, workingDirectory, options = {}) {
|
|
4845
|
+
if (command.length === 0)
|
|
4846
|
+
return null;
|
|
4847
|
+
const [cmd] = command;
|
|
4848
|
+
if (cmd === undefined || cmd.length === 0)
|
|
4849
|
+
return null;
|
|
4850
|
+
const platform = options.platform ?? process.platform;
|
|
4851
|
+
const suffixes = executableSuffixes(platform, options.pathExt);
|
|
4852
|
+
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
4853
|
+
const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
|
|
4854
|
+
return probe(explicit) ? explicit : null;
|
|
4855
|
+
}
|
|
4856
|
+
const cacheKey = JSON.stringify([
|
|
4857
|
+
workingDirectory ?? "",
|
|
4858
|
+
cmd,
|
|
4859
|
+
platform,
|
|
4860
|
+
options.stopAt ?? "",
|
|
4861
|
+
options.pathExt ?? "",
|
|
4862
|
+
options.pathEnv ?? process.env["PATH"] ?? ""
|
|
4863
|
+
]);
|
|
4864
|
+
const cached = resolutionCache.get(cacheKey);
|
|
4865
|
+
if (cached !== undefined)
|
|
4866
|
+
return cached;
|
|
4867
|
+
let resolved = null;
|
|
4868
|
+
if (workingDirectory !== undefined && workingDirectory.length > 0) {
|
|
4869
|
+
resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
|
|
4870
|
+
}
|
|
4871
|
+
resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
|
|
4872
|
+
if (resolved === null && cmd === "node")
|
|
4873
|
+
resolved = cmd;
|
|
4874
|
+
resolutionCache.set(cacheKey, resolved);
|
|
4875
|
+
return resolved;
|
|
4876
|
+
}
|
|
4877
|
+
function isServerInstalled(command, workingDirectory, options = {}) {
|
|
4878
|
+
if (command.length === 0)
|
|
4879
|
+
return false;
|
|
4880
|
+
return resolveServerBinary(command, workingDirectory, options) !== null;
|
|
4592
4881
|
}
|
|
4593
4882
|
|
|
4594
4883
|
// ../lsp-core/src/lsp/server-resolution.ts
|
|
4884
|
+
function withResolvedCommand(command, binaryPath) {
|
|
4885
|
+
return [binaryPath, ...command.slice(1)];
|
|
4886
|
+
}
|
|
4595
4887
|
function findServerForExtension(ext) {
|
|
4596
4888
|
const servers = getMergedServers();
|
|
4889
|
+
const workingDirectory = contextCwd();
|
|
4597
4890
|
for (const server2 of servers) {
|
|
4598
|
-
if (server2.extensions.includes(ext)
|
|
4891
|
+
if (!server2.extensions.includes(ext))
|
|
4892
|
+
continue;
|
|
4893
|
+
const binaryPath = resolveServerBinary(server2.command, workingDirectory);
|
|
4894
|
+
if (binaryPath !== null) {
|
|
4599
4895
|
const resolvedServer = {
|
|
4600
4896
|
id: server2.id,
|
|
4601
|
-
command: server2.command,
|
|
4897
|
+
command: withResolvedCommand(server2.command, binaryPath),
|
|
4602
4898
|
extensions: server2.extensions,
|
|
4603
4899
|
priority: server2.priority
|
|
4604
4900
|
};
|
|
@@ -4645,6 +4941,7 @@ function findServerForExtension(ext) {
|
|
|
4645
4941
|
function getAllServers() {
|
|
4646
4942
|
const servers = getMergedServers();
|
|
4647
4943
|
const disabled = getDisabledServerIds();
|
|
4944
|
+
const workingDirectory = contextCwd();
|
|
4648
4945
|
const result = [];
|
|
4649
4946
|
const seen = new Set;
|
|
4650
4947
|
for (const server2 of servers) {
|
|
@@ -4652,7 +4949,7 @@ function getAllServers() {
|
|
|
4652
4949
|
continue;
|
|
4653
4950
|
result.push({
|
|
4654
4951
|
id: server2.id,
|
|
4655
|
-
installed: isServerInstalled(server2.command),
|
|
4952
|
+
installed: isServerInstalled(server2.command, workingDirectory),
|
|
4656
4953
|
extensions: server2.extensions,
|
|
4657
4954
|
disabled: false,
|
|
4658
4955
|
source: server2.source,
|
|
@@ -4666,7 +4963,7 @@ function getAllServers() {
|
|
|
4666
4963
|
const builtin = BUILTIN_SERVERS[id];
|
|
4667
4964
|
result.push({
|
|
4668
4965
|
id,
|
|
4669
|
-
installed: builtin ? isServerInstalled(builtin.command) : false,
|
|
4966
|
+
installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
|
|
4670
4967
|
extensions: builtin?.extensions ?? [],
|
|
4671
4968
|
disabled: true,
|
|
4672
4969
|
source: "disabled",
|
|
@@ -4677,7 +4974,6 @@ function getAllServers() {
|
|
|
4677
4974
|
}
|
|
4678
4975
|
|
|
4679
4976
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
4680
|
-
var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
4681
4977
|
function isDirectoryPath(filePath) {
|
|
4682
4978
|
try {
|
|
4683
4979
|
return statSync4(filePath).isDirectory();
|
|
@@ -4686,32 +4982,90 @@ function isDirectoryPath(filePath) {
|
|
|
4686
4982
|
}
|
|
4687
4983
|
}
|
|
4688
4984
|
function findWorkspaceRoot(filePath) {
|
|
4689
|
-
const
|
|
4985
|
+
const cwd = contextCwd();
|
|
4986
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4690
4987
|
let dir = abs;
|
|
4691
4988
|
if (!isDirectoryPath(dir)) {
|
|
4692
|
-
dir =
|
|
4693
|
-
}
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4989
|
+
dir = dirname10(dir);
|
|
4990
|
+
}
|
|
4991
|
+
if (!isPathInside(cwd, abs))
|
|
4992
|
+
return findWorkspaceRootOutsideContext(dir);
|
|
4993
|
+
const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
|
|
4994
|
+
let nearestPackageRoot;
|
|
4995
|
+
while (isPathInside(cwd, dir)) {
|
|
4996
|
+
const canonicalDir = existingDirectoryInsideContext(dir, cwd);
|
|
4997
|
+
if (canonicalDir !== undefined) {
|
|
4998
|
+
if (existsSync11(join5(dir, GIT_WORKSPACE_MARKER))) {
|
|
4999
|
+
return canonicalDir;
|
|
5000
|
+
}
|
|
5001
|
+
if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
|
|
5002
|
+
nearestPackageRoot = canonicalDir;
|
|
4699
5003
|
}
|
|
4700
5004
|
}
|
|
4701
|
-
|
|
4702
|
-
|
|
5005
|
+
if (dir === cwd)
|
|
5006
|
+
break;
|
|
5007
|
+
dir = dirname10(dir);
|
|
4703
5008
|
}
|
|
4704
|
-
return
|
|
5009
|
+
return nearestPackageRoot ?? fallbackRoot;
|
|
5010
|
+
}
|
|
5011
|
+
function hasProjectWorkspaceMarker(directory) {
|
|
5012
|
+
return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync11(join5(directory, marker)));
|
|
5013
|
+
}
|
|
5014
|
+
function resolveReadablePathInsideContext(filePath) {
|
|
5015
|
+
const cwd = contextCwd();
|
|
5016
|
+
const abs = resolve8(cwd, filePath);
|
|
5017
|
+
if (isPathInside(cwd, abs))
|
|
5018
|
+
return abs;
|
|
5019
|
+
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
5020
|
+
if (rebased !== undefined)
|
|
5021
|
+
return rebased;
|
|
5022
|
+
return canonicalizeExistingOrNearestAncestor(abs);
|
|
4705
5023
|
}
|
|
4706
5024
|
function resolvePathInsideContext(filePath) {
|
|
4707
5025
|
const cwd = contextCwd();
|
|
4708
|
-
const abs =
|
|
5026
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4709
5027
|
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
4710
5028
|
if (!isPathInside(cwd, canonical)) {
|
|
4711
5029
|
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4712
5030
|
}
|
|
4713
5031
|
return canonical;
|
|
4714
5032
|
}
|
|
5033
|
+
function rebaseThroughCanonicalAncestor(path2, cwd) {
|
|
5034
|
+
let current = path2;
|
|
5035
|
+
const suffix = [];
|
|
5036
|
+
while (true) {
|
|
5037
|
+
if (existsSync11(current)) {
|
|
5038
|
+
const canonical = realpathSync5(current);
|
|
5039
|
+
if (isPathInside(cwd, canonical))
|
|
5040
|
+
return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
|
|
5041
|
+
}
|
|
5042
|
+
const parent = dirname10(current);
|
|
5043
|
+
if (parent === current)
|
|
5044
|
+
return;
|
|
5045
|
+
suffix.unshift(basename3(current));
|
|
5046
|
+
current = parent;
|
|
5047
|
+
}
|
|
5048
|
+
}
|
|
5049
|
+
function existingDirectoryInsideContext(directory, cwd) {
|
|
5050
|
+
if (!existsSync11(directory))
|
|
5051
|
+
return;
|
|
5052
|
+
const canonical = realpathSync5(directory);
|
|
5053
|
+
if (!statSync4(canonical).isDirectory())
|
|
5054
|
+
return;
|
|
5055
|
+
return isPathInside(cwd, canonical) ? canonical : undefined;
|
|
5056
|
+
}
|
|
5057
|
+
function nearestExistingDirectoryInsideContext(directory, cwd) {
|
|
5058
|
+
let current = directory;
|
|
5059
|
+
while (isPathInside(cwd, current)) {
|
|
5060
|
+
const canonical = existingDirectoryInsideContext(current, cwd);
|
|
5061
|
+
if (canonical !== undefined)
|
|
5062
|
+
return canonical;
|
|
5063
|
+
if (current === cwd)
|
|
5064
|
+
return;
|
|
5065
|
+
current = dirname10(current);
|
|
5066
|
+
}
|
|
5067
|
+
return;
|
|
5068
|
+
}
|
|
4715
5069
|
function formatServerLookupError(result) {
|
|
4716
5070
|
if (result.status === "not_installed") {
|
|
4717
5071
|
return formatNotInstalled(result);
|
|
@@ -4735,6 +5089,19 @@ function formatServerLookupError(result) {
|
|
|
4735
5089
|
].join(`
|
|
4736
5090
|
`);
|
|
4737
5091
|
}
|
|
5092
|
+
function formatInstallOptions(serverId, installHint) {
|
|
5093
|
+
const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
|
|
5094
|
+
if (localHint === undefined) {
|
|
5095
|
+
return ["To install, run:", ` ${installHint}`];
|
|
5096
|
+
}
|
|
5097
|
+
return [
|
|
5098
|
+
"To install in THIS repository (preferred — no global install needed):",
|
|
5099
|
+
` ${localHint}`,
|
|
5100
|
+
"",
|
|
5101
|
+
"Or install it globally:",
|
|
5102
|
+
` ${installHint}`
|
|
5103
|
+
];
|
|
5104
|
+
}
|
|
4738
5105
|
function formatNotInstalled(result) {
|
|
4739
5106
|
const { server: server2, installHint } = result;
|
|
4740
5107
|
const extensions = server2.extensions.join(", ");
|
|
@@ -4749,19 +5116,19 @@ function formatNotInstalled(result) {
|
|
|
4749
5116
|
`Command not found: ${server2.command[0]}`,
|
|
4750
5117
|
""
|
|
4751
5118
|
];
|
|
5119
|
+
const installOptions = formatInstallOptions(server2.id, installHint);
|
|
4752
5120
|
if (decision === "allowed") {
|
|
4753
5121
|
return [
|
|
4754
5122
|
...header,
|
|
4755
5123
|
"The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
|
|
4756
|
-
|
|
5124
|
+
...installOptions.slice(1)
|
|
4757
5125
|
].join(`
|
|
4758
5126
|
`);
|
|
4759
5127
|
}
|
|
4760
5128
|
if (!context.capabilities.installDecisionTool) {
|
|
4761
5129
|
return [
|
|
4762
5130
|
...header,
|
|
4763
|
-
|
|
4764
|
-
` ${installHint}`,
|
|
5131
|
+
...installOptions,
|
|
4765
5132
|
"",
|
|
4766
5133
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4767
5134
|
"Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
|
|
@@ -4770,8 +5137,7 @@ function formatNotInstalled(result) {
|
|
|
4770
5137
|
}
|
|
4771
5138
|
return [
|
|
4772
5139
|
...header,
|
|
4773
|
-
|
|
4774
|
-
` ${installHint}`,
|
|
5140
|
+
...installOptions,
|
|
4775
5141
|
"",
|
|
4776
5142
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4777
5143
|
"- If the user agrees: run the install command above, then retry this tool.",
|
|
@@ -4782,7 +5148,7 @@ function formatNotInstalled(result) {
|
|
|
4782
5148
|
].join(`
|
|
4783
5149
|
`);
|
|
4784
5150
|
}
|
|
4785
|
-
var
|
|
5151
|
+
var READ_ONLY_TOOLS = new Set([
|
|
4786
5152
|
"diagnostics",
|
|
4787
5153
|
"definition",
|
|
4788
5154
|
"references",
|
|
@@ -4791,7 +5157,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
|
|
|
4791
5157
|
"prepareRename"
|
|
4792
5158
|
]);
|
|
4793
5159
|
async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
4794
|
-
const absPath = resolvePathInsideContext(filePath);
|
|
5160
|
+
const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
|
|
4795
5161
|
if (isDirectoryPath(absPath)) {
|
|
4796
5162
|
throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
|
|
4797
5163
|
}
|
|
@@ -4806,9 +5172,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4806
5172
|
const acquireAndCall = async (allowRetry) => {
|
|
4807
5173
|
const client = await manager.getClient(root, server2, options.signal);
|
|
4808
5174
|
try {
|
|
4809
|
-
return await fn(client, root);
|
|
5175
|
+
return await fn(client, root, absPath);
|
|
4810
5176
|
} catch (err) {
|
|
4811
|
-
if (allowRetry &&
|
|
5177
|
+
if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
|
|
4812
5178
|
manager.invalidateClient(root, server2.id, client);
|
|
4813
5179
|
return acquireAndCall(false);
|
|
4814
5180
|
}
|
|
@@ -4826,8 +5192,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4826
5192
|
}
|
|
4827
5193
|
|
|
4828
5194
|
// ../lsp-core/src/lsp/directory-diagnostics.ts
|
|
4829
|
-
import { existsSync as
|
|
4830
|
-
import { join as
|
|
5195
|
+
import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
|
|
5196
|
+
import { join as join6, resolve as resolve9 } from "node:path";
|
|
4831
5197
|
|
|
4832
5198
|
// ../lsp-core/src/lsp/formatters.ts
|
|
4833
5199
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
@@ -4957,7 +5323,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
|
|
|
4957
5323
|
for (const entry of entries) {
|
|
4958
5324
|
if (files.length >= maxFiles)
|
|
4959
5325
|
return;
|
|
4960
|
-
const fullPath =
|
|
5326
|
+
const fullPath = join6(currentDir, entry);
|
|
4961
5327
|
let stat;
|
|
4962
5328
|
try {
|
|
4963
5329
|
stat = lstatSync5(fullPath);
|
|
@@ -4982,8 +5348,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4982
5348
|
if (!extension.startsWith(".")) {
|
|
4983
5349
|
throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
|
|
4984
5350
|
}
|
|
4985
|
-
const absDir =
|
|
4986
|
-
if (!
|
|
5351
|
+
const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
|
|
5352
|
+
if (!existsSync12(absDir)) {
|
|
4987
5353
|
throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
|
|
4988
5354
|
}
|
|
4989
5355
|
const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
|
|
@@ -5070,7 +5436,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
5070
5436
|
|
|
5071
5437
|
// ../lsp-core/src/lsp/infer-extension.ts
|
|
5072
5438
|
import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
|
|
5073
|
-
import { join as
|
|
5439
|
+
import { join as join7 } from "node:path";
|
|
5074
5440
|
var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
|
|
5075
5441
|
var MAX_SCAN_ENTRIES = 500;
|
|
5076
5442
|
function inferExtensionFromDirectory(directory) {
|
|
@@ -5088,7 +5454,7 @@ function inferExtensionFromDirectory(directory) {
|
|
|
5088
5454
|
for (const entry of entries) {
|
|
5089
5455
|
if (scanned >= MAX_SCAN_ENTRIES)
|
|
5090
5456
|
return;
|
|
5091
|
-
const fullPath =
|
|
5457
|
+
const fullPath = join7(dir, entry);
|
|
5092
5458
|
let stat;
|
|
5093
5459
|
try {
|
|
5094
5460
|
stat = lstatSync6(fullPath);
|
|
@@ -5263,7 +5629,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5263
5629
|
const filePath = requireString(params, "filePath");
|
|
5264
5630
|
const severity = severityFilter(params);
|
|
5265
5631
|
try {
|
|
5266
|
-
const absPath =
|
|
5632
|
+
const absPath = resolveReadablePathInsideContext(filePath);
|
|
5267
5633
|
if (isDirectoryPath(absPath)) {
|
|
5268
5634
|
const extension = inferExtensionFromDirectory(absPath);
|
|
5269
5635
|
if (!extension) {
|
|
@@ -5292,7 +5658,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5292
5658
|
};
|
|
5293
5659
|
return text(output2.output, details2);
|
|
5294
5660
|
}
|
|
5295
|
-
const result = await withLspClient(filePath, async (client) => client.diagnostics(
|
|
5661
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
|
|
5296
5662
|
if (result.transientError) {
|
|
5297
5663
|
const message = result.transientError.message;
|
|
5298
5664
|
const details2 = {
|
|
@@ -5339,6 +5705,96 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5339
5705
|
throw error;
|
|
5340
5706
|
}
|
|
5341
5707
|
}
|
|
5708
|
+
// ../lsp-core/src/lsp/format-document.ts
|
|
5709
|
+
import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
5710
|
+
var DEFAULT_FORMATTING_OPTIONS = {
|
|
5711
|
+
tabSize: 4,
|
|
5712
|
+
insertSpaces: false,
|
|
5713
|
+
trimTrailingWhitespace: true,
|
|
5714
|
+
insertFinalNewline: true,
|
|
5715
|
+
trimFinalNewlines: true
|
|
5716
|
+
};
|
|
5717
|
+
var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
|
|
5718
|
+
async function formatDocumentWithClient(client, filePath, options = {}) {
|
|
5719
|
+
const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
|
|
5720
|
+
if (edits === null)
|
|
5721
|
+
return { status: "unavailable", reason: "capability_not_advertised" };
|
|
5722
|
+
if (edits.length === 0)
|
|
5723
|
+
return UNCHANGED;
|
|
5724
|
+
const before = readFileSync6(filePath, "utf-8");
|
|
5725
|
+
const normalized = normalizeTextEdits(before, edits, 0);
|
|
5726
|
+
if (normalized.text === before)
|
|
5727
|
+
return UNCHANGED;
|
|
5728
|
+
writeAtomically(filePath, normalized.text);
|
|
5729
|
+
await client.openFile(filePath);
|
|
5730
|
+
return {
|
|
5731
|
+
status: "formatted",
|
|
5732
|
+
...lineDelta(normalized.edits)
|
|
5733
|
+
};
|
|
5734
|
+
}
|
|
5735
|
+
function lineDelta(edits) {
|
|
5736
|
+
let linesAdded = 0;
|
|
5737
|
+
let linesRemoved = 0;
|
|
5738
|
+
for (const edit of edits) {
|
|
5739
|
+
linesRemoved += edit.range.end.line - edit.range.start.line + 1;
|
|
5740
|
+
linesAdded += edit.newText.split(`
|
|
5741
|
+
`).length;
|
|
5742
|
+
}
|
|
5743
|
+
return { linesAdded, linesRemoved };
|
|
5744
|
+
}
|
|
5745
|
+
function writeAtomically(filePath, content) {
|
|
5746
|
+
const tempPath = `${filePath}.omo-format.tmp`;
|
|
5747
|
+
writeFileSync3(tempPath, content, "utf-8");
|
|
5748
|
+
try {
|
|
5749
|
+
renameSync3(tempPath, filePath);
|
|
5750
|
+
} catch (error) {
|
|
5751
|
+
try {
|
|
5752
|
+
unlinkSync2(tempPath);
|
|
5753
|
+
} catch {}
|
|
5754
|
+
throw error;
|
|
5755
|
+
}
|
|
5756
|
+
}
|
|
5757
|
+
|
|
5758
|
+
// ../lsp-core/src/tools/format.ts
|
|
5759
|
+
async function executeLspFormat(params, signal) {
|
|
5760
|
+
const filePath = requireString(params, "filePath");
|
|
5761
|
+
try {
|
|
5762
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
|
|
5763
|
+
return text(describeResult(filePath, result), formatDetails(filePath, result));
|
|
5764
|
+
} catch (error) {
|
|
5765
|
+
const missingDependency = missingDependencyResult(error, {
|
|
5766
|
+
filePath,
|
|
5767
|
+
status: "unavailable",
|
|
5768
|
+
reason: "server_unavailable",
|
|
5769
|
+
linesAdded: 0,
|
|
5770
|
+
linesRemoved: 0
|
|
5771
|
+
});
|
|
5772
|
+
if (missingDependency)
|
|
5773
|
+
return missingDependency;
|
|
5774
|
+
throw error;
|
|
5775
|
+
}
|
|
5776
|
+
}
|
|
5777
|
+
function formatDetails(filePath, result) {
|
|
5778
|
+
if (result.status === "unavailable") {
|
|
5779
|
+
return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
|
|
5780
|
+
}
|
|
5781
|
+
return {
|
|
5782
|
+
filePath,
|
|
5783
|
+
status: result.status,
|
|
5784
|
+
linesAdded: result.linesAdded,
|
|
5785
|
+
linesRemoved: result.linesRemoved
|
|
5786
|
+
};
|
|
5787
|
+
}
|
|
5788
|
+
function describeResult(filePath, result) {
|
|
5789
|
+
if (result.status === "unavailable") {
|
|
5790
|
+
return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
|
|
5791
|
+
}
|
|
5792
|
+
if (result.status === "unchanged") {
|
|
5793
|
+
return `Already formatted: ${filePath}`;
|
|
5794
|
+
}
|
|
5795
|
+
return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
|
|
5796
|
+
}
|
|
5797
|
+
|
|
5342
5798
|
// ../lsp-core/src/tools/install-decision.ts
|
|
5343
5799
|
async function executeLspInstallDecision(params) {
|
|
5344
5800
|
const serverId = requireString(params, "server_id");
|
|
@@ -5367,7 +5823,7 @@ async function executeLspGotoDefinition(params, signal) {
|
|
|
5367
5823
|
const line = requireNumber(params, "line");
|
|
5368
5824
|
const character = requireNumber(params, "character");
|
|
5369
5825
|
try {
|
|
5370
|
-
const result = await withLspClient(filePath, async (client) => client.definition(
|
|
5826
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
|
|
5371
5827
|
const locations = !result ? [] : Array.isArray(result) ? result : [result];
|
|
5372
5828
|
const details = { filePath, line, character, locations };
|
|
5373
5829
|
if (locations.length === 0)
|
|
@@ -5392,7 +5848,7 @@ async function executeLspFindReferences(params, signal) {
|
|
|
5392
5848
|
const character = requireNumber(params, "character");
|
|
5393
5849
|
const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
|
|
5394
5850
|
try {
|
|
5395
|
-
const result = await withLspClient(filePath, async (client) => client.references(
|
|
5851
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
|
|
5396
5852
|
const references = Array.isArray(result) ? result : [];
|
|
5397
5853
|
const total = references.length;
|
|
5398
5854
|
const truncated = total > DEFAULT_MAX_REFERENCES;
|
|
@@ -5434,7 +5890,7 @@ async function executeLspPrepareRename(params, signal) {
|
|
|
5434
5890
|
const line = requireNumber(params, "line");
|
|
5435
5891
|
const character = requireNumber(params, "character");
|
|
5436
5892
|
try {
|
|
5437
|
-
const result = await withLspClient(filePath, async (client) => client.prepareRename(
|
|
5893
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
|
|
5438
5894
|
const details = { filePath, line, character, result };
|
|
5439
5895
|
return text(formatPrepareRenameResult(result), details);
|
|
5440
5896
|
} catch (error) {
|
|
@@ -5455,7 +5911,7 @@ async function executeLspRename(params, signal) {
|
|
|
5455
5911
|
const character = requireNumber(params, "character");
|
|
5456
5912
|
const newName = requireString(params, "newName");
|
|
5457
5913
|
try {
|
|
5458
|
-
const result = await withLspClient(filePath, async (client) => client.rename(
|
|
5914
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
|
|
5459
5915
|
const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
|
|
5460
5916
|
return text(formatApplyResult(result.apply), details, !result.apply.success);
|
|
5461
5917
|
} catch (error) {
|
|
@@ -5535,7 +5991,7 @@ async function executeLspSymbols(params, signal) {
|
|
|
5535
5991
|
const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
|
|
5536
5992
|
return formatSymbolsResult(filePath, scope, symbols2, limit, query);
|
|
5537
5993
|
}
|
|
5538
|
-
const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(
|
|
5994
|
+
const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
|
|
5539
5995
|
return formatSymbolsResult(filePath, scope, symbols, limit);
|
|
5540
5996
|
} catch (error) {
|
|
5541
5997
|
const query = optionalString(params, "query");
|
|
@@ -5671,6 +6127,16 @@ var LSP_MCP_TOOLS = [
|
|
|
5671
6127
|
}, ["filePath", "line", "character", "newName"]),
|
|
5672
6128
|
execute: executeLspRename
|
|
5673
6129
|
},
|
|
6130
|
+
{
|
|
6131
|
+
name: "format",
|
|
6132
|
+
aliases: ["lsp_format"],
|
|
6133
|
+
title: "LSP Format",
|
|
6134
|
+
description: "Format a source file with its language server and write the returned edits to disk.",
|
|
6135
|
+
inputSchema: objectSchema({
|
|
6136
|
+
filePath: { type: "string", description: "Source file path to format." }
|
|
6137
|
+
}, ["filePath"]),
|
|
6138
|
+
execute: executeLspFormat
|
|
6139
|
+
},
|
|
5674
6140
|
{
|
|
5675
6141
|
name: "install_decision",
|
|
5676
6142
|
aliases: ["lsp_install_decision"],
|
|
@@ -5771,7 +6237,10 @@ function requestedProtocolVersion(params) {
|
|
|
5771
6237
|
var CONTEXT_KEY = "_context";
|
|
5772
6238
|
|
|
5773
6239
|
class InvalidDaemonRequestError extends Error {
|
|
5774
|
-
|
|
6240
|
+
constructor() {
|
|
6241
|
+
super(...arguments);
|
|
6242
|
+
this.name = "InvalidDaemonRequestError";
|
|
6243
|
+
}
|
|
5775
6244
|
}
|
|
5776
6245
|
function extractRequestContext(raw) {
|
|
5777
6246
|
if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
|
|
@@ -5887,14 +6356,17 @@ async function callToolViaDaemon(name, args, options) {
|
|
|
5887
6356
|
function callDiagnosticsViaDaemon(filePath, options) {
|
|
5888
6357
|
return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
|
|
5889
6358
|
}
|
|
6359
|
+
function callFormatViaDaemon(filePath, options) {
|
|
6360
|
+
return callToolViaDaemon("format", { filePath }, options);
|
|
6361
|
+
}
|
|
5890
6362
|
function currentRequestContext(env = process.env) {
|
|
5891
6363
|
const cwd = process.cwd();
|
|
5892
6364
|
const home = env["HOME"] ?? homedir3();
|
|
5893
6365
|
return parseLspRequestContext({
|
|
5894
6366
|
cwd,
|
|
5895
|
-
projectConfigPaths: [
|
|
5896
|
-
userConfigPath:
|
|
5897
|
-
installDecisionsPath:
|
|
6367
|
+
projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
|
|
6368
|
+
userConfigPath: join8(home, ".codex", "lsp-client.json"),
|
|
6369
|
+
installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
|
|
5898
6370
|
capabilities: { installDecisionTool: true }
|
|
5899
6371
|
});
|
|
5900
6372
|
}
|
|
@@ -5909,7 +6381,7 @@ function withContext(args, context) {
|
|
|
5909
6381
|
function ensureDaemonAvailable(paths, ensure, signal) {
|
|
5910
6382
|
if (!signal)
|
|
5911
6383
|
return ensure(paths);
|
|
5912
|
-
return new Promise((
|
|
6384
|
+
return new Promise((resolve10, reject) => {
|
|
5913
6385
|
let settled = false;
|
|
5914
6386
|
const finish = (run) => {
|
|
5915
6387
|
if (settled)
|
|
@@ -5924,11 +6396,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
|
|
|
5924
6396
|
return;
|
|
5925
6397
|
}
|
|
5926
6398
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5927
|
-
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() =>
|
|
6399
|
+
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
|
|
5928
6400
|
});
|
|
5929
6401
|
}
|
|
5930
6402
|
function sendToolCall(paths, token, name, args, options) {
|
|
5931
|
-
return new Promise((
|
|
6403
|
+
return new Promise((resolve10, reject) => {
|
|
5932
6404
|
const socket = connect(paths.socket);
|
|
5933
6405
|
const requestId = allocateProxyRequestId();
|
|
5934
6406
|
let settled = false;
|
|
@@ -5981,7 +6453,7 @@ function sendToolCall(paths, token, name, args, options) {
|
|
|
5981
6453
|
}
|
|
5982
6454
|
const result = toToolResult(message, requestId);
|
|
5983
6455
|
if (result)
|
|
5984
|
-
finish(() =>
|
|
6456
|
+
finish(() => resolve10(result));
|
|
5985
6457
|
else
|
|
5986
6458
|
finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
|
|
5987
6459
|
});
|
|
@@ -6027,18 +6499,15 @@ function isRetryableTool(name) {
|
|
|
6027
6499
|
}
|
|
6028
6500
|
|
|
6029
6501
|
// src/client.ts
|
|
6030
|
-
import { statSync as statSync5 } from "node:fs";
|
|
6031
|
-
import { isAbsolute as isAbsolute5 } from "node:path";
|
|
6032
6502
|
var OMO_LSP_DAEMON_DIR2 = "OMO_LSP_DAEMON_DIR";
|
|
6033
6503
|
var OMO_LSP_DAEMON_CLI2 = "OMO_LSP_DAEMON_CLI";
|
|
6034
6504
|
var OMO_LSP_DAEMON_VERSION2 = "OMO_LSP_DAEMON_VERSION";
|
|
6035
6505
|
var DAEMON_VERSION_PATTERN2 = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
6036
6506
|
|
|
6037
6507
|
class InvalidRuntimeOverrideError2 extends Error {
|
|
6038
|
-
code = "invalid_runtime_override";
|
|
6039
|
-
reason;
|
|
6040
6508
|
constructor(reason, message) {
|
|
6041
6509
|
super(message);
|
|
6510
|
+
this.code = "invalid_runtime_override";
|
|
6042
6511
|
this.name = "InvalidRuntimeOverrideError";
|
|
6043
6512
|
this.reason = reason;
|
|
6044
6513
|
}
|
|
@@ -6058,12 +6527,12 @@ function resolveDaemonRuntime2(env, defaults) {
|
|
|
6058
6527
|
throw new InvalidRuntimeOverrideError2("paired_values_required", `${OMO_LSP_DAEMON_CLI2} and ${OMO_LSP_DAEMON_VERSION2} must be set together`);
|
|
6059
6528
|
}
|
|
6060
6529
|
if (!hasCliOverride || !hasVersionOverride) {
|
|
6061
|
-
if (!
|
|
6530
|
+
if (!isAbsolute6(defaults.cliPath)) {
|
|
6062
6531
|
throw new InvalidRuntimeOverrideError2("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
|
|
6063
6532
|
}
|
|
6064
6533
|
return { cliPath: defaults.cliPath, version: validateDaemonVersion2(defaults.version) };
|
|
6065
6534
|
}
|
|
6066
|
-
if (!
|
|
6535
|
+
if (!isAbsolute6(cliOverride)) {
|
|
6067
6536
|
throw new InvalidRuntimeOverrideError2("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI2} must be an absolute path to an existing regular file`);
|
|
6068
6537
|
}
|
|
6069
6538
|
const stat = statSync5(cliOverride, { throwIfNoEntry: false });
|
|
@@ -6081,17 +6550,21 @@ function callToolViaDaemon2(name, args, options) {
|
|
|
6081
6550
|
function callDiagnosticsViaDaemon2(filePath, options) {
|
|
6082
6551
|
return callDiagnosticsViaDaemon(filePath, options);
|
|
6083
6552
|
}
|
|
6553
|
+
function callFormatViaDaemon2(filePath, options) {
|
|
6554
|
+
return callFormatViaDaemon(filePath, options);
|
|
6555
|
+
}
|
|
6084
6556
|
function currentRequestContext2(env = process.env) {
|
|
6085
6557
|
return currentRequestContext(env);
|
|
6086
6558
|
}
|
|
6087
6559
|
export {
|
|
6088
|
-
|
|
6089
|
-
resolveDaemonRuntime2 as resolveDaemonRuntime,
|
|
6090
|
-
currentRequestContext2 as currentRequestContext,
|
|
6091
|
-
callToolViaDaemon2 as callToolViaDaemon,
|
|
6092
|
-
callDiagnosticsViaDaemon2 as callDiagnosticsViaDaemon,
|
|
6093
|
-
OMO_LSP_DAEMON_VERSION2 as OMO_LSP_DAEMON_VERSION,
|
|
6094
|
-
OMO_LSP_DAEMON_DIR2 as OMO_LSP_DAEMON_DIR,
|
|
6560
|
+
InvalidRuntimeOverrideError2 as InvalidRuntimeOverrideError,
|
|
6095
6561
|
OMO_LSP_DAEMON_CLI2 as OMO_LSP_DAEMON_CLI,
|
|
6096
|
-
|
|
6562
|
+
OMO_LSP_DAEMON_DIR2 as OMO_LSP_DAEMON_DIR,
|
|
6563
|
+
OMO_LSP_DAEMON_VERSION2 as OMO_LSP_DAEMON_VERSION,
|
|
6564
|
+
callDiagnosticsViaDaemon2 as callDiagnosticsViaDaemon,
|
|
6565
|
+
callFormatViaDaemon2 as callFormatViaDaemon,
|
|
6566
|
+
callToolViaDaemon2 as callToolViaDaemon,
|
|
6567
|
+
currentRequestContext2 as currentRequestContext,
|
|
6568
|
+
resolveDaemonRuntime2 as resolveDaemonRuntime,
|
|
6569
|
+
validateDaemonVersion2 as validateDaemonVersion
|
|
6097
6570
|
};
|