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
|
@@ -8,11 +8,13 @@ import { argv, execPath as execPath2, stderr } from "node:process";
|
|
|
8
8
|
import { stdin as processStdin } from "node:process";
|
|
9
9
|
|
|
10
10
|
// src/codex-hook.ts
|
|
11
|
-
import { readFileSync as
|
|
11
|
+
import { readFileSync as readFileSync10, realpathSync as realpathSync8 } from "node:fs";
|
|
12
12
|
import { homedir as homedir3 } from "node:os";
|
|
13
|
-
import { join as
|
|
13
|
+
import { join as join12, resolve as resolve12 } from "node:path";
|
|
14
14
|
|
|
15
15
|
// ../../../../lsp-daemon/dist/client.js
|
|
16
|
+
import { statSync as statSync5 } from "node:fs";
|
|
17
|
+
import { isAbsolute as isAbsolute6 } from "node:path";
|
|
16
18
|
import { connect } from "node:net";
|
|
17
19
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
18
20
|
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
@@ -42,8 +44,8 @@ import * as path from "node:path";
|
|
|
42
44
|
import { fileURLToPath } from "node:url";
|
|
43
45
|
import { statSync as statSync2 } from "node:fs";
|
|
44
46
|
import { isAbsolute as isAbsolute2 } from "node:path";
|
|
45
|
-
import { existsSync as
|
|
46
|
-
import { dirname as
|
|
47
|
+
import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
|
|
48
|
+
import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
|
|
47
49
|
import { basename as basename2, extname } from "node:path";
|
|
48
50
|
import { resolve as resolve6 } from "node:path";
|
|
49
51
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
@@ -62,32 +64,32 @@ import { createHash as createHash2 } from "node:crypto";
|
|
|
62
64
|
import { dirname as dirname5, relative as relative4, resolve as resolve4 } from "node:path";
|
|
63
65
|
import { existsSync as existsSync6, lstatSync as lstatSync4, readdirSync as readdirSync2 } from "node:fs";
|
|
64
66
|
import { dirname as dirname6, resolve as resolve5 } from "node:path";
|
|
65
|
-
import { existsSync as existsSync7,
|
|
66
|
-
import { dirname as dirname7 } from "node:path";
|
|
67
|
-
import { existsSync as existsSync8, readFileSync as
|
|
68
|
-
import {
|
|
69
|
-
import {
|
|
70
|
-
import { existsSync as
|
|
71
|
-
import { join as
|
|
67
|
+
import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
|
|
68
|
+
import { dirname as dirname7, join as join3 } from "node:path";
|
|
69
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
70
|
+
import { dirname as dirname8 } from "node:path";
|
|
71
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
|
|
72
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
73
|
+
import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
|
|
74
|
+
import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
|
|
75
|
+
import { join as join6, resolve as resolve9 } from "node:path";
|
|
72
76
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
73
77
|
import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
|
|
74
|
-
import { join as
|
|
75
|
-
import {
|
|
76
|
-
import { isAbsolute as isAbsolute5 } from "node:path";
|
|
78
|
+
import { join as join7 } from "node:path";
|
|
79
|
+
import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
77
80
|
|
|
78
81
|
class LspRequestContextParseError extends Error {
|
|
79
|
-
code;
|
|
80
|
-
name = "LspRequestContextParseError";
|
|
81
82
|
constructor(code, message) {
|
|
82
83
|
super(message);
|
|
83
84
|
this.code = code;
|
|
85
|
+
this.name = "LspRequestContextParseError";
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
class LspRequestContextUnavailableError extends Error {
|
|
88
|
-
name = "LspRequestContextUnavailableError";
|
|
89
90
|
constructor() {
|
|
90
91
|
super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
|
|
92
|
+
this.name = "LspRequestContextUnavailableError";
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
var storage = new AsyncLocalStorage;
|
|
@@ -214,7 +216,6 @@ function isPlainRecord(value) {
|
|
|
214
216
|
}
|
|
215
217
|
|
|
216
218
|
class DaemonRequestError extends Error {
|
|
217
|
-
requestWritten;
|
|
218
219
|
constructor(message, requestWritten) {
|
|
219
220
|
super(message);
|
|
220
221
|
this.name = "DaemonRequestError";
|
|
@@ -237,7 +238,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
|
|
|
237
238
|
}
|
|
238
239
|
|
|
239
240
|
class DaemonRequestTimedOutError extends DaemonRequestError {
|
|
240
|
-
timeoutMs;
|
|
241
241
|
constructor(requestWritten, timeoutMs) {
|
|
242
242
|
super("daemon request timed out", requestWritten);
|
|
243
243
|
this.name = "DaemonRequestTimedOutError";
|
|
@@ -314,20 +314,18 @@ var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
|
|
|
314
314
|
var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
315
315
|
|
|
316
316
|
class InvalidRuntimeOverrideError extends Error {
|
|
317
|
-
code = "invalid_runtime_override";
|
|
318
|
-
reason;
|
|
319
317
|
constructor(reason, message) {
|
|
320
318
|
super(message);
|
|
319
|
+
this.code = "invalid_runtime_override";
|
|
321
320
|
this.name = "InvalidRuntimeOverrideError";
|
|
322
321
|
this.reason = reason;
|
|
323
322
|
}
|
|
324
323
|
}
|
|
325
324
|
|
|
326
325
|
class InvalidDaemonVersionError extends Error {
|
|
327
|
-
code = "invalid_daemon_version";
|
|
328
|
-
version;
|
|
329
326
|
constructor(version) {
|
|
330
327
|
super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
|
|
328
|
+
this.code = "invalid_daemon_version";
|
|
331
329
|
this.name = "InvalidDaemonVersionError";
|
|
332
330
|
this.version = version;
|
|
333
331
|
}
|
|
@@ -371,10 +369,9 @@ var requireFromHere = createRequire(import.meta.url);
|
|
|
371
369
|
var MAX_SOCKET_PATH_LENGTH = 100;
|
|
372
370
|
|
|
373
371
|
class InvalidDaemonDirectoryError extends Error {
|
|
374
|
-
code = "invalid_daemon_directory";
|
|
375
|
-
directory;
|
|
376
372
|
constructor(directory) {
|
|
377
373
|
super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
|
|
374
|
+
this.code = "invalid_daemon_directory";
|
|
378
375
|
this.name = "InvalidDaemonDirectoryError";
|
|
379
376
|
this.directory = directory;
|
|
380
377
|
}
|
|
@@ -565,7 +562,8 @@ function spawnDaemonProcess(paths) {
|
|
|
565
562
|
try {
|
|
566
563
|
const child = spawn(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
|
|
567
564
|
detached: true,
|
|
568
|
-
stdio: ["ignore", logFd, logFd]
|
|
565
|
+
stdio: ["ignore", logFd, logFd],
|
|
566
|
+
windowsHide: true
|
|
569
567
|
});
|
|
570
568
|
child.once("spawn", () => closeSync2(logFd));
|
|
571
569
|
child.once("error", (error) => {
|
|
@@ -686,22 +684,15 @@ function effectiveExtension(filePath) {
|
|
|
686
684
|
}
|
|
687
685
|
|
|
688
686
|
class LspConnectionClosedError extends Error {
|
|
689
|
-
serverId;
|
|
690
|
-
root;
|
|
691
|
-
name = "LspConnectionClosedError";
|
|
692
687
|
constructor(serverId, root, message) {
|
|
693
688
|
super(message ?? `LSP connection closed for ${serverId} at ${root}`);
|
|
694
689
|
this.serverId = serverId;
|
|
695
690
|
this.root = root;
|
|
691
|
+
this.name = "LspConnectionClosedError";
|
|
696
692
|
}
|
|
697
693
|
}
|
|
698
694
|
|
|
699
695
|
class LspProcessExitedError extends Error {
|
|
700
|
-
serverId;
|
|
701
|
-
root;
|
|
702
|
-
exitCode;
|
|
703
|
-
stderrTail;
|
|
704
|
-
name = "LspProcessExitedError";
|
|
705
696
|
constructor(serverId, root, exitCode, stderrTail) {
|
|
706
697
|
const stderrSuffix = stderrTail ? `
|
|
707
698
|
stderr tail: ${stderrTail}` : "";
|
|
@@ -710,46 +701,59 @@ stderr tail: ${stderrTail}` : "";
|
|
|
710
701
|
this.root = root;
|
|
711
702
|
this.exitCode = exitCode;
|
|
712
703
|
this.stderrTail = stderrTail;
|
|
704
|
+
this.name = "LspProcessExitedError";
|
|
713
705
|
}
|
|
714
706
|
}
|
|
715
707
|
|
|
716
708
|
class LspRequestTimeoutError extends Error {
|
|
717
|
-
method;
|
|
718
|
-
stderrTail;
|
|
719
|
-
name = "LspRequestTimeoutError";
|
|
720
709
|
constructor(method, stderrTail) {
|
|
721
710
|
const stderrSuffix = stderrTail ? `
|
|
722
711
|
recent stderr: ${stderrTail}` : "";
|
|
723
712
|
super(`LSP request timeout (method: ${method})${stderrSuffix}`);
|
|
724
713
|
this.method = method;
|
|
725
714
|
this.stderrTail = stderrTail;
|
|
715
|
+
this.name = "LspRequestTimeoutError";
|
|
726
716
|
}
|
|
727
717
|
}
|
|
728
718
|
|
|
729
719
|
class LspInvalidPathError extends Error {
|
|
730
|
-
|
|
720
|
+
constructor() {
|
|
721
|
+
super(...arguments);
|
|
722
|
+
this.name = "LspInvalidPathError";
|
|
723
|
+
}
|
|
731
724
|
}
|
|
732
725
|
|
|
733
726
|
class LspServerLookupError extends Error {
|
|
734
|
-
lookup;
|
|
735
|
-
name = "LspServerLookupError";
|
|
736
727
|
constructor(message, lookup) {
|
|
737
728
|
super(message);
|
|
738
729
|
this.lookup = lookup;
|
|
730
|
+
this.name = "LspServerLookupError";
|
|
739
731
|
}
|
|
740
732
|
}
|
|
741
733
|
|
|
742
734
|
class LspServerInitializingError extends Error {
|
|
743
|
-
originalError;
|
|
744
|
-
name = "LspServerInitializingError";
|
|
745
735
|
constructor(originalError) {
|
|
746
736
|
super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
|
|
747
737
|
this.originalError = originalError;
|
|
738
|
+
this.name = "LspServerInitializingError";
|
|
748
739
|
}
|
|
749
740
|
}
|
|
750
741
|
|
|
751
742
|
class LspProcessSpawnError extends Error {
|
|
752
|
-
|
|
743
|
+
constructor() {
|
|
744
|
+
super(...arguments);
|
|
745
|
+
this.name = "LspProcessSpawnError";
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
class LspClientRespawnBudgetExceededError extends Error {
|
|
750
|
+
constructor(serverId, root, retryLimit) {
|
|
751
|
+
super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
|
|
752
|
+
this.serverId = serverId;
|
|
753
|
+
this.root = root;
|
|
754
|
+
this.retryLimit = retryLimit;
|
|
755
|
+
this.name = "LspClientRespawnBudgetExceededError";
|
|
756
|
+
}
|
|
753
757
|
}
|
|
754
758
|
function isLspDeadConnectionError(err) {
|
|
755
759
|
return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
|
|
@@ -762,6 +766,11 @@ function reportBestEffortCleanupError(operation, error, logger = writeCleanupErr
|
|
|
762
766
|
const message = error instanceof Error ? error.message : String(error);
|
|
763
767
|
logger(`[lsp] ignored ${operation} failure during cleanup: ${message}`);
|
|
764
768
|
}
|
|
769
|
+
var realTimerProvider = {
|
|
770
|
+
now: () => Date.now(),
|
|
771
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
772
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
773
|
+
};
|
|
765
774
|
var DEFAULT_MAX_REFERENCES = 200;
|
|
766
775
|
var DEFAULT_MAX_SYMBOLS = 200;
|
|
767
776
|
var DEFAULT_MAX_DIAGNOSTICS = 200;
|
|
@@ -769,9 +778,12 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
|
|
|
769
778
|
var REQUEST_TIMEOUT_MS = 15000;
|
|
770
779
|
var INIT_TIMEOUT_MS = 60000;
|
|
771
780
|
var IDLE_TIMEOUT_MS = 5 * 60000;
|
|
781
|
+
var MAX_RESIDENT_CLIENTS = 6;
|
|
772
782
|
var REAPER_INTERVAL_MS = 60000;
|
|
773
783
|
var STOP_HARD_KILL_TIMEOUT_MS = 5000;
|
|
774
784
|
var STOP_SIGKILL_GRACE_MS = 1000;
|
|
785
|
+
var CLIENT_RESPAWN_RETRY_LIMIT = 2;
|
|
786
|
+
var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
|
|
775
787
|
var HEADER_SEPARATOR2 = `\r
|
|
776
788
|
\r
|
|
777
789
|
`;
|
|
@@ -781,20 +793,31 @@ var METHOD_NOT_FOUND = -32601;
|
|
|
781
793
|
var INTERNAL_ERROR = -32603;
|
|
782
794
|
|
|
783
795
|
class JsonRpcConnection {
|
|
784
|
-
reader;
|
|
785
|
-
writer;
|
|
786
|
-
pendingRequests = new Map;
|
|
787
|
-
notificationHandlers = new Map;
|
|
788
|
-
requestHandlers = new Map;
|
|
789
|
-
closeHandlers = [];
|
|
790
|
-
errorHandlers = [];
|
|
791
|
-
inputBuffer = Buffer.alloc(0);
|
|
792
|
-
nextRequestId = 1;
|
|
793
|
-
listening = false;
|
|
794
|
-
disposed = false;
|
|
795
796
|
constructor(reader, writer) {
|
|
796
797
|
this.reader = reader;
|
|
797
798
|
this.writer = writer;
|
|
799
|
+
this.pendingRequests = new Map;
|
|
800
|
+
this.notificationHandlers = new Map;
|
|
801
|
+
this.requestHandlers = new Map;
|
|
802
|
+
this.closeHandlers = [];
|
|
803
|
+
this.errorHandlers = [];
|
|
804
|
+
this.inputBuffer = Buffer.alloc(0);
|
|
805
|
+
this.nextRequestId = 1;
|
|
806
|
+
this.listening = false;
|
|
807
|
+
this.disposed = false;
|
|
808
|
+
this.handleData = (chunk) => {
|
|
809
|
+
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
810
|
+
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
811
|
+
this.drainInputBuffer();
|
|
812
|
+
};
|
|
813
|
+
this.handleClose = () => {
|
|
814
|
+
for (const handler of this.closeHandlers) {
|
|
815
|
+
handler();
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
this.handleStreamError = (error) => {
|
|
819
|
+
this.emitError(error);
|
|
820
|
+
};
|
|
798
821
|
}
|
|
799
822
|
listen() {
|
|
800
823
|
if (this.listening)
|
|
@@ -915,19 +938,6 @@ class JsonRpcConnection {
|
|
|
915
938
|
this.notificationHandlers.clear();
|
|
916
939
|
this.requestHandlers.clear();
|
|
917
940
|
}
|
|
918
|
-
handleData = (chunk) => {
|
|
919
|
-
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
920
|
-
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
921
|
-
this.drainInputBuffer();
|
|
922
|
-
};
|
|
923
|
-
handleClose = () => {
|
|
924
|
-
for (const handler of this.closeHandlers) {
|
|
925
|
-
handler();
|
|
926
|
-
}
|
|
927
|
-
};
|
|
928
|
-
handleStreamError = (error) => {
|
|
929
|
-
this.emitError(error);
|
|
930
|
-
};
|
|
931
941
|
drainInputBuffer() {
|
|
932
942
|
while (true) {
|
|
933
943
|
const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR2);
|
|
@@ -1267,33 +1277,29 @@ function isPosition(value) {
|
|
|
1267
1277
|
}
|
|
1268
1278
|
|
|
1269
1279
|
class LspClientNotStartedError extends Error {
|
|
1270
|
-
serverId;
|
|
1271
|
-
root;
|
|
1272
|
-
name = "LspClientNotStartedError";
|
|
1273
1280
|
constructor(serverId, root) {
|
|
1274
1281
|
super("LSP client not started");
|
|
1275
1282
|
this.serverId = serverId;
|
|
1276
1283
|
this.root = root;
|
|
1284
|
+
this.name = "LspClientNotStartedError";
|
|
1277
1285
|
}
|
|
1278
1286
|
}
|
|
1279
1287
|
|
|
1280
1288
|
class LspClientTransport {
|
|
1281
|
-
root;
|
|
1282
|
-
server;
|
|
1283
|
-
proc = null;
|
|
1284
|
-
connection = null;
|
|
1285
|
-
stderrBuffer = [];
|
|
1286
|
-
processExited = false;
|
|
1287
|
-
diagnosticsStore = new Map;
|
|
1288
|
-
requestTimeoutMs;
|
|
1289
|
-
initializeTimeoutMs;
|
|
1290
|
-
workspaceApplyEditHandler = null;
|
|
1291
|
-
diagnosticPullSupported = false;
|
|
1292
1289
|
constructor(root, server2, timeouts = {}) {
|
|
1293
1290
|
this.root = root;
|
|
1294
1291
|
this.server = server2;
|
|
1292
|
+
this.proc = null;
|
|
1293
|
+
this.connection = null;
|
|
1294
|
+
this.stderrBuffer = [];
|
|
1295
|
+
this.processExited = false;
|
|
1296
|
+
this.diagnosticsStore = new Map;
|
|
1297
|
+
this.workspaceApplyEditHandler = null;
|
|
1298
|
+
this.diagnosticPullSupported = false;
|
|
1299
|
+
this.documentFormattingSupported = false;
|
|
1295
1300
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
1296
1301
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
1302
|
+
this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
|
|
1297
1303
|
}
|
|
1298
1304
|
pid() {
|
|
1299
1305
|
return this.proc?.pid;
|
|
@@ -1313,6 +1319,12 @@ class LspClientTransport {
|
|
|
1313
1319
|
isDiagnosticPullSupported() {
|
|
1314
1320
|
return this.diagnosticPullSupported;
|
|
1315
1321
|
}
|
|
1322
|
+
setDocumentFormattingSupported(supported) {
|
|
1323
|
+
this.documentFormattingSupported = supported;
|
|
1324
|
+
}
|
|
1325
|
+
isDocumentFormattingSupported() {
|
|
1326
|
+
return this.documentFormattingSupported;
|
|
1327
|
+
}
|
|
1316
1328
|
handlePublishDiagnostics(params) {
|
|
1317
1329
|
this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
|
|
1318
1330
|
}
|
|
@@ -1388,7 +1400,7 @@ class LspClientTransport {
|
|
|
1388
1400
|
const options = args[1];
|
|
1389
1401
|
const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
|
|
1390
1402
|
const timeoutController = new AbortController;
|
|
1391
|
-
const timeoutHandle = setTimeout(() => {
|
|
1403
|
+
const timeoutHandle = this.timerProvider.setTimeout(() => {
|
|
1392
1404
|
const stderrTail = this.stderrBuffer.slice(-5).join(`
|
|
1393
1405
|
`);
|
|
1394
1406
|
timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
|
|
@@ -1407,7 +1419,7 @@ class LspClientTransport {
|
|
|
1407
1419
|
}
|
|
1408
1420
|
throw error;
|
|
1409
1421
|
} finally {
|
|
1410
|
-
clearTimeout(timeoutHandle);
|
|
1422
|
+
this.timerProvider.clearTimeout(timeoutHandle);
|
|
1411
1423
|
combinedSignal.dispose();
|
|
1412
1424
|
}
|
|
1413
1425
|
}
|
|
@@ -1524,6 +1536,14 @@ function supportsDiagnosticPull(capabilities) {
|
|
|
1524
1536
|
return false;
|
|
1525
1537
|
return Object.hasOwn(capabilities, "diagnosticProvider");
|
|
1526
1538
|
}
|
|
1539
|
+
function supportsDocumentFormatting(capabilities) {
|
|
1540
|
+
if (capabilities === undefined)
|
|
1541
|
+
return false;
|
|
1542
|
+
const provider = capabilities.documentFormattingProvider;
|
|
1543
|
+
if (provider === undefined || provider === null || provider === false)
|
|
1544
|
+
return false;
|
|
1545
|
+
return provider === true || typeof provider === "object";
|
|
1546
|
+
}
|
|
1527
1547
|
|
|
1528
1548
|
class LspClientConnection extends LspClientTransport {
|
|
1529
1549
|
async initialize() {
|
|
@@ -1540,6 +1560,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
1540
1560
|
references: {},
|
|
1541
1561
|
documentSymbol: { hierarchicalDocumentSymbolSupport: true },
|
|
1542
1562
|
publishDiagnostics: {},
|
|
1563
|
+
formatting: { dynamicRegistration: false },
|
|
1543
1564
|
rename: {
|
|
1544
1565
|
prepareSupport: true,
|
|
1545
1566
|
prepareSupportDefaultBehavior: 1
|
|
@@ -1581,6 +1602,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
1581
1602
|
initializationOptions: this.server.initialization
|
|
1582
1603
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
1583
1604
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
1605
|
+
this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
|
|
1584
1606
|
await this.sendNotification("initialized", {});
|
|
1585
1607
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
1586
1608
|
settings: { json: { validate: { enable: true } } }
|
|
@@ -1767,6 +1789,17 @@ function canonicalPath(filePath) {
|
|
|
1767
1789
|
return absolute;
|
|
1768
1790
|
}
|
|
1769
1791
|
}
|
|
1792
|
+
function normalizeDocumentUri(uri) {
|
|
1793
|
+
let decoded = uri;
|
|
1794
|
+
try {
|
|
1795
|
+
decoded = decodeURIComponent(uri);
|
|
1796
|
+
} catch {
|
|
1797
|
+
decoded = uri;
|
|
1798
|
+
}
|
|
1799
|
+
if (process.platform !== "win32")
|
|
1800
|
+
return decoded;
|
|
1801
|
+
return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
|
|
1802
|
+
}
|
|
1770
1803
|
function isSameOrDescendant(candidate, parent) {
|
|
1771
1804
|
const suffix = relative2(parent, candidate);
|
|
1772
1805
|
return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
|
|
@@ -1777,17 +1810,18 @@ function movedPath(candidate, oldPath, newPath) {
|
|
|
1777
1810
|
}
|
|
1778
1811
|
|
|
1779
1812
|
class WorkspaceDocumentState {
|
|
1780
|
-
sendNotification;
|
|
1781
|
-
clearDiagnostics;
|
|
1782
|
-
openDocuments = new Map;
|
|
1783
|
-
openByUri = new Map;
|
|
1784
|
-
openPromises = new Map;
|
|
1785
|
-
now;
|
|
1786
|
-
versionlessPublishQuiescenceMs;
|
|
1787
1813
|
constructor(sendNotification, clearDiagnostics, options = {}) {
|
|
1788
1814
|
this.sendNotification = sendNotification;
|
|
1789
1815
|
this.clearDiagnostics = clearDiagnostics;
|
|
1790
|
-
this.
|
|
1816
|
+
this.openDocuments = new Map;
|
|
1817
|
+
this.openByUri = new Map;
|
|
1818
|
+
this.openPromises = new Map;
|
|
1819
|
+
this.timerProvider = options.timerProvider ?? {
|
|
1820
|
+
now: options.now ?? (() => Date.now()),
|
|
1821
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
1822
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
1823
|
+
};
|
|
1824
|
+
this.now = () => this.timerProvider.now();
|
|
1791
1825
|
this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
|
|
1792
1826
|
}
|
|
1793
1827
|
async openFile(filePath) {
|
|
@@ -1809,7 +1843,7 @@ class WorkspaceDocumentState {
|
|
|
1809
1843
|
return this.openDocuments.get(canonicalPath(filePath))?.version;
|
|
1810
1844
|
}
|
|
1811
1845
|
getStoredDiagnostics(uri) {
|
|
1812
|
-
const state = this.openByUri.get(uri);
|
|
1846
|
+
const state = this.openByUri.get(normalizeDocumentUri(uri));
|
|
1813
1847
|
if (!state)
|
|
1814
1848
|
return [];
|
|
1815
1849
|
return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
|
|
@@ -1831,13 +1865,13 @@ class WorkspaceDocumentState {
|
|
|
1831
1865
|
return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
|
|
1832
1866
|
}
|
|
1833
1867
|
getPullCache(snapshot) {
|
|
1834
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1868
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1835
1869
|
if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
|
|
1836
1870
|
return null;
|
|
1837
1871
|
return state.pullCache;
|
|
1838
1872
|
}
|
|
1839
1873
|
recordPullDiagnostics(snapshot, report) {
|
|
1840
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1874
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1841
1875
|
if (!state)
|
|
1842
1876
|
return;
|
|
1843
1877
|
state.pullCache = {
|
|
@@ -1847,7 +1881,7 @@ class WorkspaceDocumentState {
|
|
|
1847
1881
|
};
|
|
1848
1882
|
}
|
|
1849
1883
|
recordPublishedDiagnostics(params) {
|
|
1850
|
-
const state = this.openByUri.get(params.uri);
|
|
1884
|
+
const state = this.openByUri.get(normalizeDocumentUri(params.uri));
|
|
1851
1885
|
if (!state)
|
|
1852
1886
|
return;
|
|
1853
1887
|
state.publishGeneration += 1;
|
|
@@ -1861,7 +1895,7 @@ class WorkspaceDocumentState {
|
|
|
1861
1895
|
this.notifyWaiters(state);
|
|
1862
1896
|
}
|
|
1863
1897
|
resolvePushDiagnostics(snapshot) {
|
|
1864
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1898
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1865
1899
|
if (!state?.lastPublish)
|
|
1866
1900
|
return { status: "missing" };
|
|
1867
1901
|
const publish = state.lastPublish;
|
|
@@ -1875,7 +1909,7 @@ class WorkspaceDocumentState {
|
|
|
1875
1909
|
return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
|
|
1876
1910
|
}
|
|
1877
1911
|
waitForDiagnosticsActivity(snapshot, timeoutMs) {
|
|
1878
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1912
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1879
1913
|
if (!state || timeoutMs <= 0)
|
|
1880
1914
|
return Promise.resolve();
|
|
1881
1915
|
return new Promise((resolveActivity) => {
|
|
@@ -1884,11 +1918,11 @@ class WorkspaceDocumentState {
|
|
|
1884
1918
|
if (settled)
|
|
1885
1919
|
return;
|
|
1886
1920
|
settled = true;
|
|
1887
|
-
clearTimeout(timer);
|
|
1921
|
+
this.timerProvider.clearTimeout(timer);
|
|
1888
1922
|
state.waiters.delete(finish);
|
|
1889
1923
|
resolveActivity();
|
|
1890
1924
|
};
|
|
1891
|
-
const timer = setTimeout(finish, timeoutMs);
|
|
1925
|
+
const timer = this.timerProvider.setTimeout(finish, timeoutMs);
|
|
1892
1926
|
if (typeof timer.unref === "function")
|
|
1893
1927
|
timer.unref();
|
|
1894
1928
|
state.waiters.add(finish);
|
|
@@ -1996,7 +2030,7 @@ class WorkspaceDocumentState {
|
|
|
1996
2030
|
waiters: new Set
|
|
1997
2031
|
};
|
|
1998
2032
|
this.openDocuments.set(path2, state);
|
|
1999
|
-
this.openByUri.set(state.uri, state);
|
|
2033
|
+
this.openByUri.set(normalizeDocumentUri(state.uri), state);
|
|
2000
2034
|
this.notifyWaiters(state);
|
|
2001
2035
|
await this.sendNotification("textDocument/didOpen", {
|
|
2002
2036
|
textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
|
|
@@ -2021,7 +2055,7 @@ class WorkspaceDocumentState {
|
|
|
2021
2055
|
}
|
|
2022
2056
|
async closeDocument(state) {
|
|
2023
2057
|
this.openDocuments.delete(state.path);
|
|
2024
|
-
this.openByUri.delete(state.uri);
|
|
2058
|
+
this.openByUri.delete(normalizeDocumentUri(state.uri));
|
|
2025
2059
|
this.clearDiagnostics(state.uri);
|
|
2026
2060
|
this.notifyWaiters(state);
|
|
2027
2061
|
await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
|
|
@@ -2040,13 +2074,11 @@ function workspaceApplyEditConcurrentFailureReason(phase) {
|
|
|
2040
2074
|
}
|
|
2041
2075
|
|
|
2042
2076
|
class WorkspaceEditPathError extends Error {
|
|
2043
|
-
path;
|
|
2044
|
-
detail;
|
|
2045
|
-
name = "WorkspaceEditPathError";
|
|
2046
2077
|
constructor(path2, detail) {
|
|
2047
2078
|
super(`${detail}: ${path2}`);
|
|
2048
2079
|
this.path = path2;
|
|
2049
2080
|
this.detail = detail;
|
|
2081
|
+
this.name = "WorkspaceEditPathError";
|
|
2050
2082
|
}
|
|
2051
2083
|
}
|
|
2052
2084
|
function isPathInsideWorkspace(filePath, workspaceRoot) {
|
|
@@ -2332,13 +2364,11 @@ function canonicalFingerprint(operations) {
|
|
|
2332
2364
|
}
|
|
2333
2365
|
|
|
2334
2366
|
class WorkspaceEditValidationError extends Error {
|
|
2335
|
-
changeIndex;
|
|
2336
|
-
detail;
|
|
2337
|
-
name = "WorkspaceEditValidationError";
|
|
2338
2367
|
constructor(changeIndex, detail) {
|
|
2339
2368
|
super(`change ${changeIndex}: ${detail}`);
|
|
2340
2369
|
this.changeIndex = changeIndex;
|
|
2341
2370
|
this.detail = detail;
|
|
2371
|
+
this.name = "WorkspaceEditValidationError";
|
|
2342
2372
|
}
|
|
2343
2373
|
}
|
|
2344
2374
|
function isRecord3(value) {
|
|
@@ -2820,10 +2850,9 @@ function simulateDelete(operation, virtual) {
|
|
|
2820
2850
|
}
|
|
2821
2851
|
|
|
2822
2852
|
class WorkspaceSnapshotBuilder {
|
|
2823
|
-
workspaceRoot;
|
|
2824
|
-
snapshots = new Map;
|
|
2825
2853
|
constructor(workspaceRoot) {
|
|
2826
2854
|
this.workspaceRoot = workspaceRoot;
|
|
2855
|
+
this.snapshots = new Map;
|
|
2827
2856
|
}
|
|
2828
2857
|
build(operations) {
|
|
2829
2858
|
this.add(this.workspaceRoot, false);
|
|
@@ -2866,8 +2895,10 @@ function snapshotOperations(operations, workspaceRoot) {
|
|
|
2866
2895
|
}
|
|
2867
2896
|
|
|
2868
2897
|
class PlanPathIndex {
|
|
2869
|
-
|
|
2870
|
-
|
|
2898
|
+
constructor() {
|
|
2899
|
+
this.firstChangeByPath = new Map;
|
|
2900
|
+
this.reportedPathByCanonical = new Map;
|
|
2901
|
+
}
|
|
2871
2902
|
build(operations) {
|
|
2872
2903
|
for (const operation of operations) {
|
|
2873
2904
|
switch (operation.kind) {
|
|
@@ -2954,14 +2985,11 @@ function isRecord4(value) {
|
|
|
2954
2985
|
}
|
|
2955
2986
|
|
|
2956
2987
|
class WorkspaceMutationController {
|
|
2957
|
-
workspaceRoot;
|
|
2958
|
-
documents;
|
|
2959
|
-
activeLease = null;
|
|
2960
|
-
nextLeaseId = 1;
|
|
2961
|
-
io;
|
|
2962
2988
|
constructor(workspaceRoot, documents) {
|
|
2963
2989
|
this.workspaceRoot = workspaceRoot;
|
|
2964
2990
|
this.documents = documents;
|
|
2991
|
+
this.activeLease = null;
|
|
2992
|
+
this.nextLeaseId = 1;
|
|
2965
2993
|
}
|
|
2966
2994
|
setIo(io) {
|
|
2967
2995
|
this.io = io;
|
|
@@ -3072,14 +3100,12 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
|
|
|
3072
3100
|
var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
|
|
3073
3101
|
|
|
3074
3102
|
class LspClient extends LspClientConnection {
|
|
3075
|
-
diagnosticPullErrors = [];
|
|
3076
|
-
documents;
|
|
3077
|
-
workspaceMutations;
|
|
3078
|
-
diagnosticsFreshnessTimeoutMs;
|
|
3079
3103
|
constructor(root, server2, options = {}) {
|
|
3080
3104
|
super(root, server2, options);
|
|
3105
|
+
this.diagnosticPullErrors = [];
|
|
3081
3106
|
this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
|
|
3082
3107
|
this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
|
|
3108
|
+
timerProvider: this.timerProvider,
|
|
3083
3109
|
versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
|
|
3084
3110
|
});
|
|
3085
3111
|
this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
|
|
@@ -3132,6 +3158,18 @@ class LspClient extends LspClientConnection {
|
|
|
3132
3158
|
textDocument: { uri: pathToFileURL3(absPath).href }
|
|
3133
3159
|
}, options);
|
|
3134
3160
|
}
|
|
3161
|
+
async formatDocument(filePath, options, signal) {
|
|
3162
|
+
if (!this.isDocumentFormattingSupported())
|
|
3163
|
+
return null;
|
|
3164
|
+
const absPath = this.resolveWorkspacePath(filePath);
|
|
3165
|
+
await this.openFile(absPath);
|
|
3166
|
+
const requestOptions = signal === undefined ? {} : { signal };
|
|
3167
|
+
const edits = await this.sendRequest("textDocument/formatting", {
|
|
3168
|
+
textDocument: { uri: pathToFileURL3(absPath).href },
|
|
3169
|
+
options
|
|
3170
|
+
}, requestOptions);
|
|
3171
|
+
return edits ?? [];
|
|
3172
|
+
}
|
|
3135
3173
|
async workspaceSymbols(query, signal) {
|
|
3136
3174
|
const options = signal === undefined ? {} : { signal };
|
|
3137
3175
|
return this.sendRequest("workspace/symbol", { query }, options);
|
|
@@ -3171,7 +3209,7 @@ class LspClient extends LspClientConnection {
|
|
|
3171
3209
|
const absPath = this.resolveWorkspacePath(filePath);
|
|
3172
3210
|
const uri = pathToFileURL3(absPath).href;
|
|
3173
3211
|
await this.openFile(absPath);
|
|
3174
|
-
const deadlineAt =
|
|
3212
|
+
const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
|
|
3175
3213
|
for (;; ) {
|
|
3176
3214
|
signal?.throwIfAborted();
|
|
3177
3215
|
const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
|
|
@@ -3184,7 +3222,7 @@ class LspClient extends LspClientConnection {
|
|
|
3184
3222
|
if (!pushFallbackOnly) {
|
|
3185
3223
|
const cached = this.documents.getPullCache(snapshot);
|
|
3186
3224
|
try {
|
|
3187
|
-
const remainingMs2 = deadlineAt -
|
|
3225
|
+
const remainingMs2 = deadlineAt - this.timerProvider.now();
|
|
3188
3226
|
if (remainingMs2 <= 0)
|
|
3189
3227
|
return this.freshnessTimeout(absPath);
|
|
3190
3228
|
const result = await this.sendRequest("textDocument/diagnostic", {
|
|
@@ -3219,7 +3257,7 @@ class LspClient extends LspClientConnection {
|
|
|
3219
3257
|
}
|
|
3220
3258
|
if (!pushFallbackOnly)
|
|
3221
3259
|
continue;
|
|
3222
|
-
const remainingMs = deadlineAt -
|
|
3260
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
3223
3261
|
if (remainingMs <= 0) {
|
|
3224
3262
|
if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
|
|
3225
3263
|
const cached = this.documents.getPullCache(snapshot);
|
|
@@ -3373,18 +3411,16 @@ function awaitWithSignal2(promise, signal) {
|
|
|
3373
3411
|
}
|
|
3374
3412
|
|
|
3375
3413
|
class LspManager {
|
|
3376
|
-
clients = new Map;
|
|
3377
|
-
reaperHandle = null;
|
|
3378
|
-
signalDisposer = null;
|
|
3379
|
-
disposed = false;
|
|
3380
|
-
idleTimeoutMs;
|
|
3381
|
-
initTimeoutMs;
|
|
3382
|
-
reaperIntervalMs;
|
|
3383
|
-
clientFactory;
|
|
3384
|
-
now;
|
|
3385
3414
|
constructor(options = {}) {
|
|
3415
|
+
this.clients = new Map;
|
|
3416
|
+
this.pendingStops = new Map;
|
|
3417
|
+
this.respawnBudgets = new Map;
|
|
3418
|
+
this.reaperHandle = null;
|
|
3419
|
+
this.signalDisposer = null;
|
|
3420
|
+
this.disposed = false;
|
|
3386
3421
|
this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
|
|
3387
3422
|
this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
3423
|
+
this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
|
|
3388
3424
|
this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
|
|
3389
3425
|
this.clientFactory = options.clientFactory ?? ((root, server2) => new LspClient(root, server2));
|
|
3390
3426
|
this.now = options.now ?? (() => Date.now());
|
|
@@ -3404,24 +3440,79 @@ class LspManager {
|
|
|
3404
3440
|
getKey(root, serverId) {
|
|
3405
3441
|
return `${root}::${serverId}`;
|
|
3406
3442
|
}
|
|
3443
|
+
tombstoneStop(key, client) {
|
|
3444
|
+
const stop = stopClientBestEffort(client);
|
|
3445
|
+
this.pendingStops.set(key, stop);
|
|
3446
|
+
stop.finally(() => {
|
|
3447
|
+
if (this.pendingStops.get(key) === stop) {
|
|
3448
|
+
this.pendingStops.delete(key);
|
|
3449
|
+
}
|
|
3450
|
+
});
|
|
3451
|
+
return stop;
|
|
3452
|
+
}
|
|
3453
|
+
recordDeadGeneration(key) {
|
|
3454
|
+
let budget = this.respawnBudgets.get(key);
|
|
3455
|
+
if (budget === undefined) {
|
|
3456
|
+
budget = { deadGenerations: 0, exhaustedAt: null };
|
|
3457
|
+
this.respawnBudgets.set(key, budget);
|
|
3458
|
+
}
|
|
3459
|
+
budget.deadGenerations += 1;
|
|
3460
|
+
}
|
|
3461
|
+
markHealthyGeneration(key) {
|
|
3462
|
+
this.respawnBudgets.delete(key);
|
|
3463
|
+
}
|
|
3464
|
+
ensureRespawnAllowed(key, root, serverId) {
|
|
3465
|
+
const budget = this.respawnBudgets.get(key);
|
|
3466
|
+
if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
|
|
3467
|
+
return;
|
|
3468
|
+
if (budget.exhaustedAt === null) {
|
|
3469
|
+
budget.exhaustedAt = this.now();
|
|
3470
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
3471
|
+
}
|
|
3472
|
+
if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
|
|
3473
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
3474
|
+
}
|
|
3475
|
+
budget.deadGenerations = 0;
|
|
3476
|
+
budget.exhaustedAt = null;
|
|
3477
|
+
}
|
|
3407
3478
|
reapStale() {
|
|
3408
3479
|
const t = this.now();
|
|
3409
3480
|
for (const [key, managed] of this.clients) {
|
|
3410
3481
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3411
|
-
stopClientBestEffort(managed.client);
|
|
3412
3482
|
this.clients.delete(key);
|
|
3483
|
+
this.tombstoneStop(key, managed.client);
|
|
3413
3484
|
continue;
|
|
3414
3485
|
}
|
|
3415
3486
|
if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
|
|
3416
|
-
stopClientBestEffort(managed.client);
|
|
3417
3487
|
this.clients.delete(key);
|
|
3488
|
+
this.tombstoneStop(key, managed.client);
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
evictForAdmission() {
|
|
3493
|
+
while (this.clients.size >= this.maxResidentClients) {
|
|
3494
|
+
const victim = this.leastRecentlyUsedIdleClient();
|
|
3495
|
+
if (!victim)
|
|
3496
|
+
return;
|
|
3497
|
+
this.clients.delete(victim.key);
|
|
3498
|
+
this.tombstoneStop(victim.key, victim.managed.client);
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
leastRecentlyUsedIdleClient() {
|
|
3502
|
+
let candidate = null;
|
|
3503
|
+
for (const [key, managed] of this.clients) {
|
|
3504
|
+
if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
|
|
3505
|
+
continue;
|
|
3506
|
+
if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
|
|
3507
|
+
candidate = { key, managed };
|
|
3418
3508
|
}
|
|
3419
3509
|
}
|
|
3510
|
+
return candidate;
|
|
3420
3511
|
}
|
|
3421
3512
|
async tryDeleteIfOrphaned(key, managed) {
|
|
3422
3513
|
if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
|
|
3423
3514
|
this.clients.delete(key);
|
|
3424
|
-
await
|
|
3515
|
+
await this.tombstoneStop(key, managed.client);
|
|
3425
3516
|
}
|
|
3426
3517
|
}
|
|
3427
3518
|
async getClient(root, server2, signal) {
|
|
@@ -3430,12 +3521,22 @@ class LspManager {
|
|
|
3430
3521
|
}
|
|
3431
3522
|
signal?.throwIfAborted();
|
|
3432
3523
|
const key = this.getKey(root, server2.id);
|
|
3524
|
+
for (;; ) {
|
|
3525
|
+
const pendingStop = this.pendingStops.get(key);
|
|
3526
|
+
if (pendingStop === undefined)
|
|
3527
|
+
break;
|
|
3528
|
+
await awaitWithSignal2(pendingStop, signal);
|
|
3529
|
+
signal?.throwIfAborted();
|
|
3530
|
+
}
|
|
3531
|
+
if (this.disposed) {
|
|
3532
|
+
throw new Error("LspManager has been disposed");
|
|
3533
|
+
}
|
|
3433
3534
|
let managed = this.clients.get(key);
|
|
3434
3535
|
if (managed) {
|
|
3435
3536
|
const t = this.now();
|
|
3436
3537
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
3437
|
-
await stopClientBestEffort(managed.client);
|
|
3438
3538
|
this.clients.delete(key);
|
|
3539
|
+
await this.tombstoneStop(key, managed.client);
|
|
3439
3540
|
managed = undefined;
|
|
3440
3541
|
}
|
|
3441
3542
|
}
|
|
@@ -3456,14 +3557,20 @@ class LspManager {
|
|
|
3456
3557
|
signal.throwIfAborted();
|
|
3457
3558
|
}
|
|
3458
3559
|
if (!managed.client.isAlive()) {
|
|
3459
|
-
|
|
3460
|
-
this.clients.
|
|
3560
|
+
this.recordDeadGeneration(key);
|
|
3561
|
+
if (this.clients.get(key) === managed) {
|
|
3562
|
+
this.clients.delete(key);
|
|
3563
|
+
}
|
|
3564
|
+
await this.tombstoneStop(key, managed.client);
|
|
3461
3565
|
return this.getClient(root, server2, signal);
|
|
3462
3566
|
}
|
|
3567
|
+
this.markHealthyGeneration(key);
|
|
3463
3568
|
managed.refCount++;
|
|
3464
3569
|
managed.lastUsedAt = this.now();
|
|
3465
3570
|
return managed.client;
|
|
3466
3571
|
}
|
|
3572
|
+
this.evictForAdmission();
|
|
3573
|
+
this.ensureRespawnAllowed(key, root, server2.id);
|
|
3467
3574
|
const client = this.clientFactory(root, server2);
|
|
3468
3575
|
const initStartedAt = this.now();
|
|
3469
3576
|
const initPromise = (async () => {
|
|
@@ -3487,7 +3594,7 @@ class LspManager {
|
|
|
3487
3594
|
if (this.clients.get(key) === newManaged) {
|
|
3488
3595
|
this.clients.delete(key);
|
|
3489
3596
|
}
|
|
3490
|
-
await
|
|
3597
|
+
await this.tombstoneStop(key, client);
|
|
3491
3598
|
throw err;
|
|
3492
3599
|
}
|
|
3493
3600
|
newManaged.pendingWaiters--;
|
|
@@ -3498,6 +3605,15 @@ class LspManager {
|
|
|
3498
3605
|
await this.tryDeleteIfOrphaned(key, newManaged);
|
|
3499
3606
|
signal.throwIfAborted();
|
|
3500
3607
|
}
|
|
3608
|
+
if (!client.isAlive()) {
|
|
3609
|
+
this.recordDeadGeneration(key);
|
|
3610
|
+
if (this.clients.get(key) === newManaged) {
|
|
3611
|
+
this.clients.delete(key);
|
|
3612
|
+
}
|
|
3613
|
+
await this.tombstoneStop(key, client);
|
|
3614
|
+
return this.getClient(root, server2, signal);
|
|
3615
|
+
}
|
|
3616
|
+
this.markHealthyGeneration(key);
|
|
3501
3617
|
newManaged.refCount++;
|
|
3502
3618
|
newManaged.lastUsedAt = this.now();
|
|
3503
3619
|
return client;
|
|
@@ -3518,14 +3634,20 @@ class LspManager {
|
|
|
3518
3634
|
if (client && managed.client !== client)
|
|
3519
3635
|
return;
|
|
3520
3636
|
this.clients.delete(key);
|
|
3521
|
-
|
|
3637
|
+
this.tombstoneStop(key, managed.client);
|
|
3522
3638
|
}
|
|
3523
3639
|
warmupClient(root, server2) {
|
|
3524
3640
|
if (this.disposed)
|
|
3525
3641
|
return;
|
|
3526
3642
|
const key = this.getKey(root, server2.id);
|
|
3527
|
-
if (this.clients.has(key))
|
|
3643
|
+
if (this.clients.has(key) || this.pendingStops.has(key))
|
|
3644
|
+
return;
|
|
3645
|
+
this.evictForAdmission();
|
|
3646
|
+
try {
|
|
3647
|
+
this.ensureRespawnAllowed(key, root, server2.id);
|
|
3648
|
+
} catch {
|
|
3528
3649
|
return;
|
|
3650
|
+
}
|
|
3529
3651
|
const client = this.clientFactory(root, server2);
|
|
3530
3652
|
const initStartedAt = this.now();
|
|
3531
3653
|
const initPromise = (async () => {
|
|
@@ -3551,7 +3673,7 @@ class LspManager {
|
|
|
3551
3673
|
if (this.clients.get(key) === managed) {
|
|
3552
3674
|
this.clients.delete(key);
|
|
3553
3675
|
}
|
|
3554
|
-
|
|
3676
|
+
this.tombstoneStop(key, client);
|
|
3555
3677
|
});
|
|
3556
3678
|
}
|
|
3557
3679
|
isServerInitializing(root, serverId) {
|
|
@@ -3595,8 +3717,11 @@ class LspManager {
|
|
|
3595
3717
|
for (const managed of this.clients.values()) {
|
|
3596
3718
|
stopPromises.push(stopClientBestEffort(managed.client));
|
|
3597
3719
|
}
|
|
3720
|
+
const tombstonedStops = [...this.pendingStops.values()];
|
|
3598
3721
|
this.clients.clear();
|
|
3599
|
-
|
|
3722
|
+
this.respawnBudgets.clear();
|
|
3723
|
+
await Promise.allSettled([...stopPromises, ...tombstonedStops]);
|
|
3724
|
+
this.pendingStops.clear();
|
|
3600
3725
|
}
|
|
3601
3726
|
}
|
|
3602
3727
|
var _defaultInstance = null;
|
|
@@ -3606,49 +3731,43 @@ function getLspManager() {
|
|
|
3606
3731
|
}
|
|
3607
3732
|
return _defaultInstance;
|
|
3608
3733
|
}
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3734
|
+
var GIT_WORKSPACE_MARKER = ".git";
|
|
3735
|
+
var PROJECT_WORKSPACE_MARKERS = [
|
|
3736
|
+
"package.json",
|
|
3737
|
+
"pyproject.toml",
|
|
3738
|
+
"Cargo.toml",
|
|
3739
|
+
"go.mod",
|
|
3740
|
+
"pom.xml",
|
|
3741
|
+
"build.gradle"
|
|
3742
|
+
];
|
|
3743
|
+
var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
|
|
3744
|
+
function findWorkspaceRootOutsideContext(directory) {
|
|
3745
|
+
const marked = nearestMarkedAncestor(directory);
|
|
3746
|
+
if (marked !== undefined)
|
|
3747
|
+
return marked;
|
|
3748
|
+
return realpathSync4(nearestExistingAncestor(directory));
|
|
3749
|
+
}
|
|
3750
|
+
function nearestMarkedAncestor(directory) {
|
|
3751
|
+
let current = directory;
|
|
3752
|
+
for (;; ) {
|
|
3753
|
+
if (existsSync7(current) && WORKSPACE_MARKERS.some((marker) => existsSync7(join3(current, marker)))) {
|
|
3754
|
+
return realpathSync4(current);
|
|
3755
|
+
}
|
|
3756
|
+
const parent = dirname7(current);
|
|
3757
|
+
if (parent === current)
|
|
3758
|
+
return;
|
|
3759
|
+
current = parent;
|
|
3621
3760
|
}
|
|
3622
3761
|
}
|
|
3623
|
-
function
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
}
|
|
3631
|
-
|
|
3632
|
-
return value === "declined" || value === "allowed";
|
|
3633
|
-
}
|
|
3634
|
-
function writeInstallDecisions(decisions) {
|
|
3635
|
-
const path2 = getInstallDecisionsPath();
|
|
3636
|
-
mkdirSync3(dirname7(path2), { recursive: true });
|
|
3637
|
-
const tmpPath = `${path2}.tmp`;
|
|
3638
|
-
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
3639
|
-
`, "utf8");
|
|
3640
|
-
renameSync2(tmpPath, path2);
|
|
3641
|
-
}
|
|
3642
|
-
function isInstallDecisions(value) {
|
|
3643
|
-
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
3644
|
-
}
|
|
3645
|
-
function isInstallDecisionRecord(value) {
|
|
3646
|
-
if (!isRecord5(value))
|
|
3647
|
-
return false;
|
|
3648
|
-
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
3649
|
-
}
|
|
3650
|
-
function isRecord5(value) {
|
|
3651
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3762
|
+
function nearestExistingAncestor(directory) {
|
|
3763
|
+
let current = directory;
|
|
3764
|
+
while (!existsSync7(current)) {
|
|
3765
|
+
const parent = dirname7(current);
|
|
3766
|
+
if (parent === current)
|
|
3767
|
+
return current;
|
|
3768
|
+
current = parent;
|
|
3769
|
+
}
|
|
3770
|
+
return current;
|
|
3652
3771
|
}
|
|
3653
3772
|
var LSP_INSTALL_HINTS = {
|
|
3654
3773
|
typescript: "npm install -g typescript-language-server typescript",
|
|
@@ -3694,6 +3813,26 @@ var LSP_INSTALL_HINTS = {
|
|
|
3694
3813
|
julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
|
|
3695
3814
|
razor: "Razor runs through the Roslyn language server (cohosting). " + "Install: dotnet tool install -g roslyn-language-server --prerelease (requires v5.8.0+). See https://github.com/dotnet/razor"
|
|
3696
3815
|
};
|
|
3816
|
+
var LSP_LOCAL_INSTALL_HINTS = {
|
|
3817
|
+
typescript: "bun add -d typescript-language-server typescript",
|
|
3818
|
+
vue: "bun add -d @vue/language-server",
|
|
3819
|
+
eslint: "bun add -d vscode-langservers-extracted",
|
|
3820
|
+
oxlint: "bun add -d oxlint",
|
|
3821
|
+
biome: "bun add -d @biomejs/biome",
|
|
3822
|
+
svelte: "bun add -d svelte-language-server",
|
|
3823
|
+
astro: "bun add -d @astrojs/language-server",
|
|
3824
|
+
bash: "bun add -d bash-language-server",
|
|
3825
|
+
"bash-ls": "bun add -d bash-language-server",
|
|
3826
|
+
"yaml-ls": "bun add -d yaml-language-server",
|
|
3827
|
+
php: "bun add -d intelephense",
|
|
3828
|
+
prisma: "bun add -d prisma",
|
|
3829
|
+
dockerfile: "bun add -d dockerfile-language-server-nodejs",
|
|
3830
|
+
pyright: "uv add --dev pyright",
|
|
3831
|
+
basedpyright: "uv add --dev basedpyright",
|
|
3832
|
+
ruff: "uv add --dev ruff",
|
|
3833
|
+
ty: "uv add --dev ty",
|
|
3834
|
+
"ruby-lsp": "bundle add ruby-lsp --group development"
|
|
3835
|
+
};
|
|
3697
3836
|
var BUILTIN_SERVERS = {
|
|
3698
3837
|
typescript: {
|
|
3699
3838
|
command: ["typescript-language-server", "--stdio"],
|
|
@@ -3795,6 +3934,50 @@ var BUILTIN_SERVERS = {
|
|
|
3795
3934
|
extensions: [".razor", ".cshtml"]
|
|
3796
3935
|
}
|
|
3797
3936
|
};
|
|
3937
|
+
function getInstallDecisionsPath() {
|
|
3938
|
+
return lspRequestContext().installDecisionsPath;
|
|
3939
|
+
}
|
|
3940
|
+
function loadInstallDecisions() {
|
|
3941
|
+
const path2 = getInstallDecisionsPath();
|
|
3942
|
+
if (!existsSync8(path2))
|
|
3943
|
+
return {};
|
|
3944
|
+
try {
|
|
3945
|
+
const parsed = JSON.parse(readFileSync4(path2, "utf8"));
|
|
3946
|
+
return isInstallDecisions(parsed) ? parsed : {};
|
|
3947
|
+
} catch {
|
|
3948
|
+
return {};
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
function loadInstallDecision(serverId) {
|
|
3952
|
+
return loadInstallDecisions()[serverId];
|
|
3953
|
+
}
|
|
3954
|
+
function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
|
|
3955
|
+
const decisions = loadInstallDecisions();
|
|
3956
|
+
decisions[serverId] = { decision, decidedAt };
|
|
3957
|
+
writeInstallDecisions(decisions);
|
|
3958
|
+
}
|
|
3959
|
+
function isInstallDecision(value) {
|
|
3960
|
+
return value === "declined" || value === "allowed";
|
|
3961
|
+
}
|
|
3962
|
+
function writeInstallDecisions(decisions) {
|
|
3963
|
+
const path2 = getInstallDecisionsPath();
|
|
3964
|
+
mkdirSync3(dirname8(path2), { recursive: true });
|
|
3965
|
+
const tmpPath = `${path2}.tmp`;
|
|
3966
|
+
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
3967
|
+
`, "utf8");
|
|
3968
|
+
renameSync2(tmpPath, path2);
|
|
3969
|
+
}
|
|
3970
|
+
function isInstallDecisions(value) {
|
|
3971
|
+
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
3972
|
+
}
|
|
3973
|
+
function isInstallDecisionRecord(value) {
|
|
3974
|
+
if (!isRecord5(value))
|
|
3975
|
+
return false;
|
|
3976
|
+
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
3977
|
+
}
|
|
3978
|
+
function isRecord5(value) {
|
|
3979
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3980
|
+
}
|
|
3798
3981
|
function getProjectConfigPaths() {
|
|
3799
3982
|
return lspRequestContext().projectConfigPaths;
|
|
3800
3983
|
}
|
|
@@ -3802,7 +3985,7 @@ function getUserConfigPath() {
|
|
|
3802
3985
|
return lspRequestContext().userConfigPath;
|
|
3803
3986
|
}
|
|
3804
3987
|
function loadJsonFile(path2) {
|
|
3805
|
-
if (!
|
|
3988
|
+
if (!existsSync9(path2))
|
|
3806
3989
|
return null;
|
|
3807
3990
|
try {
|
|
3808
3991
|
const parsed = JSON.parse(readFileSync5(path2, "utf-8"));
|
|
@@ -3988,50 +4171,151 @@ function getDisabledServerIds() {
|
|
|
3988
4171
|
}
|
|
3989
4172
|
return disabled;
|
|
3990
4173
|
}
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4174
|
+
var LOCAL_BIN_RULES = [
|
|
4175
|
+
{
|
|
4176
|
+
markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
|
|
4177
|
+
binDirs: [join4("node_modules", ".bin")]
|
|
4178
|
+
},
|
|
4179
|
+
{
|
|
4180
|
+
markers: [
|
|
4181
|
+
"pyproject.toml",
|
|
4182
|
+
"ty.toml",
|
|
4183
|
+
"requirements.txt",
|
|
4184
|
+
"setup.py",
|
|
4185
|
+
"setup.cfg",
|
|
4186
|
+
"Pipfile",
|
|
4187
|
+
"pyrightconfig.json",
|
|
4188
|
+
"ruff.toml",
|
|
4189
|
+
".ruff.toml"
|
|
4190
|
+
],
|
|
4191
|
+
binDirs: [
|
|
4192
|
+
join4(".venv", "bin"),
|
|
4193
|
+
join4(".venv", "Scripts"),
|
|
4194
|
+
join4("venv", "bin"),
|
|
4195
|
+
join4("venv", "Scripts"),
|
|
4196
|
+
join4(".env", "bin"),
|
|
4197
|
+
join4(".env", "Scripts")
|
|
4198
|
+
]
|
|
4199
|
+
},
|
|
4200
|
+
{
|
|
4201
|
+
markers: ["Gemfile", "Gemfile.lock"],
|
|
4202
|
+
binDirs: [join4("vendor", "bundle", "bin"), "bin"]
|
|
4203
|
+
},
|
|
4204
|
+
{
|
|
4205
|
+
markers: ["go.mod", "go.sum", "go.work"],
|
|
4206
|
+
binDirs: ["bin"]
|
|
4207
|
+
}
|
|
4208
|
+
];
|
|
4209
|
+
var resolutionCache = new Map;
|
|
4210
|
+
var probeCount = 0;
|
|
4211
|
+
function probe(path2) {
|
|
4212
|
+
probeCount += 1;
|
|
4213
|
+
return existsSync10(path2);
|
|
4214
|
+
}
|
|
4215
|
+
function executableSuffixes(platform, pathExt) {
|
|
4216
|
+
if (platform !== "win32")
|
|
4217
|
+
return [""];
|
|
4218
|
+
const configured = pathExt ?? process.env["PATHEXT"] ?? "";
|
|
4219
|
+
const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
|
|
4220
|
+
return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
|
|
4221
|
+
}
|
|
4222
|
+
function probeWithSuffixes(directory, command, suffixes) {
|
|
4223
|
+
for (const suffix of suffixes) {
|
|
4224
|
+
const candidate = join4(directory, command + suffix);
|
|
4225
|
+
if (probe(candidate))
|
|
4226
|
+
return candidate;
|
|
4000
4227
|
}
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4228
|
+
return null;
|
|
4229
|
+
}
|
|
4230
|
+
function resolveLocal(command, workingDirectory, suffixes, stopAt) {
|
|
4231
|
+
const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
|
|
4232
|
+
let current = resolve7(workingDirectory);
|
|
4233
|
+
while (true) {
|
|
4234
|
+
for (const rule of LOCAL_BIN_RULES) {
|
|
4235
|
+
if (!rule.markers.some((marker) => probe(join4(current, marker))))
|
|
4236
|
+
continue;
|
|
4237
|
+
for (const binDir of rule.binDirs) {
|
|
4238
|
+
const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
|
|
4239
|
+
if (found !== null)
|
|
4240
|
+
return found;
|
|
4241
|
+
}
|
|
4010
4242
|
}
|
|
4243
|
+
if (probe(join4(current, ".git")))
|
|
4244
|
+
return null;
|
|
4245
|
+
if (boundary !== undefined && current === boundary)
|
|
4246
|
+
return null;
|
|
4247
|
+
const parent = dirname9(current);
|
|
4248
|
+
if (parent === current)
|
|
4249
|
+
return null;
|
|
4250
|
+
current = parent;
|
|
4011
4251
|
}
|
|
4012
|
-
|
|
4013
|
-
|
|
4252
|
+
}
|
|
4253
|
+
function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
|
|
4254
|
+
let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
|
|
4255
|
+
if (platform === "win32" && !pathEnv) {
|
|
4014
4256
|
pathEnv = process.env["Path"] ?? "";
|
|
4015
4257
|
}
|
|
4016
|
-
const
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
}
|
|
4258
|
+
for (const entry of pathEnv.split(delimiter3)) {
|
|
4259
|
+
if (entry.length === 0)
|
|
4260
|
+
continue;
|
|
4261
|
+
const found = probeWithSuffixes(entry, command, suffixes);
|
|
4262
|
+
if (found !== null)
|
|
4263
|
+
return found;
|
|
4023
4264
|
}
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4265
|
+
return null;
|
|
4266
|
+
}
|
|
4267
|
+
function resolveServerBinary(command, workingDirectory, options = {}) {
|
|
4268
|
+
if (command.length === 0)
|
|
4269
|
+
return null;
|
|
4270
|
+
const [cmd] = command;
|
|
4271
|
+
if (cmd === undefined || cmd.length === 0)
|
|
4272
|
+
return null;
|
|
4273
|
+
const platform = options.platform ?? process.platform;
|
|
4274
|
+
const suffixes = executableSuffixes(platform, options.pathExt);
|
|
4275
|
+
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
4276
|
+
const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
|
|
4277
|
+
return probe(explicit) ? explicit : null;
|
|
4278
|
+
}
|
|
4279
|
+
const cacheKey = JSON.stringify([
|
|
4280
|
+
workingDirectory ?? "",
|
|
4281
|
+
cmd,
|
|
4282
|
+
platform,
|
|
4283
|
+
options.stopAt ?? "",
|
|
4284
|
+
options.pathExt ?? "",
|
|
4285
|
+
options.pathEnv ?? process.env["PATH"] ?? ""
|
|
4286
|
+
]);
|
|
4287
|
+
const cached = resolutionCache.get(cacheKey);
|
|
4288
|
+
if (cached !== undefined)
|
|
4289
|
+
return cached;
|
|
4290
|
+
let resolved = null;
|
|
4291
|
+
if (workingDirectory !== undefined && workingDirectory.length > 0) {
|
|
4292
|
+
resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
|
|
4293
|
+
}
|
|
4294
|
+
resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
|
|
4295
|
+
if (resolved === null && cmd === "node")
|
|
4296
|
+
resolved = cmd;
|
|
4297
|
+
resolutionCache.set(cacheKey, resolved);
|
|
4298
|
+
return resolved;
|
|
4299
|
+
}
|
|
4300
|
+
function isServerInstalled(command, workingDirectory, options = {}) {
|
|
4301
|
+
if (command.length === 0)
|
|
4302
|
+
return false;
|
|
4303
|
+
return resolveServerBinary(command, workingDirectory, options) !== null;
|
|
4304
|
+
}
|
|
4305
|
+
function withResolvedCommand(command, binaryPath) {
|
|
4306
|
+
return [binaryPath, ...command.slice(1)];
|
|
4027
4307
|
}
|
|
4028
4308
|
function findServerForExtension(ext) {
|
|
4029
4309
|
const servers = getMergedServers();
|
|
4310
|
+
const workingDirectory = contextCwd();
|
|
4030
4311
|
for (const server2 of servers) {
|
|
4031
|
-
if (server2.extensions.includes(ext)
|
|
4312
|
+
if (!server2.extensions.includes(ext))
|
|
4313
|
+
continue;
|
|
4314
|
+
const binaryPath = resolveServerBinary(server2.command, workingDirectory);
|
|
4315
|
+
if (binaryPath !== null) {
|
|
4032
4316
|
const resolvedServer = {
|
|
4033
4317
|
id: server2.id,
|
|
4034
|
-
command: server2.command,
|
|
4318
|
+
command: withResolvedCommand(server2.command, binaryPath),
|
|
4035
4319
|
extensions: server2.extensions,
|
|
4036
4320
|
priority: server2.priority
|
|
4037
4321
|
};
|
|
@@ -4078,6 +4362,7 @@ function findServerForExtension(ext) {
|
|
|
4078
4362
|
function getAllServers() {
|
|
4079
4363
|
const servers = getMergedServers();
|
|
4080
4364
|
const disabled = getDisabledServerIds();
|
|
4365
|
+
const workingDirectory = contextCwd();
|
|
4081
4366
|
const result = [];
|
|
4082
4367
|
const seen = new Set;
|
|
4083
4368
|
for (const server2 of servers) {
|
|
@@ -4085,7 +4370,7 @@ function getAllServers() {
|
|
|
4085
4370
|
continue;
|
|
4086
4371
|
result.push({
|
|
4087
4372
|
id: server2.id,
|
|
4088
|
-
installed: isServerInstalled(server2.command),
|
|
4373
|
+
installed: isServerInstalled(server2.command, workingDirectory),
|
|
4089
4374
|
extensions: server2.extensions,
|
|
4090
4375
|
disabled: false,
|
|
4091
4376
|
source: server2.source,
|
|
@@ -4099,7 +4384,7 @@ function getAllServers() {
|
|
|
4099
4384
|
const builtin = BUILTIN_SERVERS[id];
|
|
4100
4385
|
result.push({
|
|
4101
4386
|
id,
|
|
4102
|
-
installed: builtin ? isServerInstalled(builtin.command) : false,
|
|
4387
|
+
installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
|
|
4103
4388
|
extensions: builtin?.extensions ?? [],
|
|
4104
4389
|
disabled: true,
|
|
4105
4390
|
source: "disabled",
|
|
@@ -4108,7 +4393,6 @@ function getAllServers() {
|
|
|
4108
4393
|
}
|
|
4109
4394
|
return result;
|
|
4110
4395
|
}
|
|
4111
|
-
var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
4112
4396
|
function isDirectoryPath(filePath) {
|
|
4113
4397
|
try {
|
|
4114
4398
|
return statSync4(filePath).isDirectory();
|
|
@@ -4117,32 +4401,90 @@ function isDirectoryPath(filePath) {
|
|
|
4117
4401
|
}
|
|
4118
4402
|
}
|
|
4119
4403
|
function findWorkspaceRoot(filePath) {
|
|
4120
|
-
const
|
|
4404
|
+
const cwd = contextCwd();
|
|
4405
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4121
4406
|
let dir = abs;
|
|
4122
4407
|
if (!isDirectoryPath(dir)) {
|
|
4123
|
-
dir =
|
|
4124
|
-
}
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4408
|
+
dir = dirname10(dir);
|
|
4409
|
+
}
|
|
4410
|
+
if (!isPathInside(cwd, abs))
|
|
4411
|
+
return findWorkspaceRootOutsideContext(dir);
|
|
4412
|
+
const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
|
|
4413
|
+
let nearestPackageRoot;
|
|
4414
|
+
while (isPathInside(cwd, dir)) {
|
|
4415
|
+
const canonicalDir = existingDirectoryInsideContext(dir, cwd);
|
|
4416
|
+
if (canonicalDir !== undefined) {
|
|
4417
|
+
if (existsSync11(join5(dir, GIT_WORKSPACE_MARKER))) {
|
|
4418
|
+
return canonicalDir;
|
|
4419
|
+
}
|
|
4420
|
+
if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
|
|
4421
|
+
nearestPackageRoot = canonicalDir;
|
|
4130
4422
|
}
|
|
4131
4423
|
}
|
|
4132
|
-
|
|
4133
|
-
|
|
4424
|
+
if (dir === cwd)
|
|
4425
|
+
break;
|
|
4426
|
+
dir = dirname10(dir);
|
|
4134
4427
|
}
|
|
4135
|
-
return
|
|
4428
|
+
return nearestPackageRoot ?? fallbackRoot;
|
|
4429
|
+
}
|
|
4430
|
+
function hasProjectWorkspaceMarker(directory) {
|
|
4431
|
+
return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync11(join5(directory, marker)));
|
|
4432
|
+
}
|
|
4433
|
+
function resolveReadablePathInsideContext(filePath) {
|
|
4434
|
+
const cwd = contextCwd();
|
|
4435
|
+
const abs = resolve8(cwd, filePath);
|
|
4436
|
+
if (isPathInside(cwd, abs))
|
|
4437
|
+
return abs;
|
|
4438
|
+
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
4439
|
+
if (rebased !== undefined)
|
|
4440
|
+
return rebased;
|
|
4441
|
+
return canonicalizeExistingOrNearestAncestor(abs);
|
|
4136
4442
|
}
|
|
4137
4443
|
function resolvePathInsideContext(filePath) {
|
|
4138
4444
|
const cwd = contextCwd();
|
|
4139
|
-
const abs =
|
|
4445
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4140
4446
|
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
4141
4447
|
if (!isPathInside(cwd, canonical)) {
|
|
4142
4448
|
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4143
4449
|
}
|
|
4144
4450
|
return canonical;
|
|
4145
4451
|
}
|
|
4452
|
+
function rebaseThroughCanonicalAncestor(path2, cwd) {
|
|
4453
|
+
let current = path2;
|
|
4454
|
+
const suffix = [];
|
|
4455
|
+
while (true) {
|
|
4456
|
+
if (existsSync11(current)) {
|
|
4457
|
+
const canonical = realpathSync5(current);
|
|
4458
|
+
if (isPathInside(cwd, canonical))
|
|
4459
|
+
return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
|
|
4460
|
+
}
|
|
4461
|
+
const parent = dirname10(current);
|
|
4462
|
+
if (parent === current)
|
|
4463
|
+
return;
|
|
4464
|
+
suffix.unshift(basename3(current));
|
|
4465
|
+
current = parent;
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
function existingDirectoryInsideContext(directory, cwd) {
|
|
4469
|
+
if (!existsSync11(directory))
|
|
4470
|
+
return;
|
|
4471
|
+
const canonical = realpathSync5(directory);
|
|
4472
|
+
if (!statSync4(canonical).isDirectory())
|
|
4473
|
+
return;
|
|
4474
|
+
return isPathInside(cwd, canonical) ? canonical : undefined;
|
|
4475
|
+
}
|
|
4476
|
+
function nearestExistingDirectoryInsideContext(directory, cwd) {
|
|
4477
|
+
let current = directory;
|
|
4478
|
+
while (isPathInside(cwd, current)) {
|
|
4479
|
+
const canonical = existingDirectoryInsideContext(current, cwd);
|
|
4480
|
+
if (canonical !== undefined)
|
|
4481
|
+
return canonical;
|
|
4482
|
+
if (current === cwd)
|
|
4483
|
+
return;
|
|
4484
|
+
current = dirname10(current);
|
|
4485
|
+
}
|
|
4486
|
+
return;
|
|
4487
|
+
}
|
|
4146
4488
|
function formatServerLookupError(result) {
|
|
4147
4489
|
if (result.status === "not_installed") {
|
|
4148
4490
|
return formatNotInstalled(result);
|
|
@@ -4166,6 +4508,19 @@ function formatServerLookupError(result) {
|
|
|
4166
4508
|
].join(`
|
|
4167
4509
|
`);
|
|
4168
4510
|
}
|
|
4511
|
+
function formatInstallOptions(serverId, installHint) {
|
|
4512
|
+
const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
|
|
4513
|
+
if (localHint === undefined) {
|
|
4514
|
+
return ["To install, run:", ` ${installHint}`];
|
|
4515
|
+
}
|
|
4516
|
+
return [
|
|
4517
|
+
"To install in THIS repository (preferred — no global install needed):",
|
|
4518
|
+
` ${localHint}`,
|
|
4519
|
+
"",
|
|
4520
|
+
"Or install it globally:",
|
|
4521
|
+
` ${installHint}`
|
|
4522
|
+
];
|
|
4523
|
+
}
|
|
4169
4524
|
function formatNotInstalled(result) {
|
|
4170
4525
|
const { server: server2, installHint } = result;
|
|
4171
4526
|
const extensions = server2.extensions.join(", ");
|
|
@@ -4180,19 +4535,19 @@ function formatNotInstalled(result) {
|
|
|
4180
4535
|
`Command not found: ${server2.command[0]}`,
|
|
4181
4536
|
""
|
|
4182
4537
|
];
|
|
4538
|
+
const installOptions = formatInstallOptions(server2.id, installHint);
|
|
4183
4539
|
if (decision === "allowed") {
|
|
4184
4540
|
return [
|
|
4185
4541
|
...header,
|
|
4186
4542
|
"The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
|
|
4187
|
-
|
|
4543
|
+
...installOptions.slice(1)
|
|
4188
4544
|
].join(`
|
|
4189
4545
|
`);
|
|
4190
4546
|
}
|
|
4191
4547
|
if (!context.capabilities.installDecisionTool) {
|
|
4192
4548
|
return [
|
|
4193
4549
|
...header,
|
|
4194
|
-
|
|
4195
|
-
` ${installHint}`,
|
|
4550
|
+
...installOptions,
|
|
4196
4551
|
"",
|
|
4197
4552
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4198
4553
|
"Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
|
|
@@ -4201,8 +4556,7 @@ function formatNotInstalled(result) {
|
|
|
4201
4556
|
}
|
|
4202
4557
|
return [
|
|
4203
4558
|
...header,
|
|
4204
|
-
|
|
4205
|
-
` ${installHint}`,
|
|
4559
|
+
...installOptions,
|
|
4206
4560
|
"",
|
|
4207
4561
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4208
4562
|
"- If the user agrees: run the install command above, then retry this tool.",
|
|
@@ -4213,7 +4567,7 @@ function formatNotInstalled(result) {
|
|
|
4213
4567
|
].join(`
|
|
4214
4568
|
`);
|
|
4215
4569
|
}
|
|
4216
|
-
var
|
|
4570
|
+
var READ_ONLY_TOOLS = new Set([
|
|
4217
4571
|
"diagnostics",
|
|
4218
4572
|
"definition",
|
|
4219
4573
|
"references",
|
|
@@ -4222,7 +4576,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
|
|
|
4222
4576
|
"prepareRename"
|
|
4223
4577
|
]);
|
|
4224
4578
|
async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
4225
|
-
const absPath = resolvePathInsideContext(filePath);
|
|
4579
|
+
const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
|
|
4226
4580
|
if (isDirectoryPath(absPath)) {
|
|
4227
4581
|
throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
|
|
4228
4582
|
}
|
|
@@ -4237,9 +4591,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4237
4591
|
const acquireAndCall = async (allowRetry) => {
|
|
4238
4592
|
const client = await manager.getClient(root, server2, options.signal);
|
|
4239
4593
|
try {
|
|
4240
|
-
return await fn(client, root);
|
|
4594
|
+
return await fn(client, root, absPath);
|
|
4241
4595
|
} catch (err) {
|
|
4242
|
-
if (allowRetry &&
|
|
4596
|
+
if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
|
|
4243
4597
|
manager.invalidateClient(root, server2.id, client);
|
|
4244
4598
|
return acquireAndCall(false);
|
|
4245
4599
|
}
|
|
@@ -4379,7 +4733,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
|
|
|
4379
4733
|
for (const entry of entries) {
|
|
4380
4734
|
if (files.length >= maxFiles)
|
|
4381
4735
|
return;
|
|
4382
|
-
const fullPath =
|
|
4736
|
+
const fullPath = join6(currentDir, entry);
|
|
4383
4737
|
let stat;
|
|
4384
4738
|
try {
|
|
4385
4739
|
stat = lstatSync5(fullPath);
|
|
@@ -4404,8 +4758,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4404
4758
|
if (!extension.startsWith(".")) {
|
|
4405
4759
|
throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
|
|
4406
4760
|
}
|
|
4407
|
-
const absDir =
|
|
4408
|
-
if (!
|
|
4761
|
+
const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
|
|
4762
|
+
if (!existsSync12(absDir)) {
|
|
4409
4763
|
throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
|
|
4410
4764
|
}
|
|
4411
4765
|
const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
|
|
@@ -4506,7 +4860,7 @@ function inferExtensionFromDirectory(directory) {
|
|
|
4506
4860
|
for (const entry of entries) {
|
|
4507
4861
|
if (scanned >= MAX_SCAN_ENTRIES)
|
|
4508
4862
|
return;
|
|
4509
|
-
const fullPath =
|
|
4863
|
+
const fullPath = join7(dir, entry);
|
|
4510
4864
|
let stat;
|
|
4511
4865
|
try {
|
|
4512
4866
|
stat = lstatSync6(fullPath);
|
|
@@ -4669,7 +5023,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4669
5023
|
const filePath = requireString(params, "filePath");
|
|
4670
5024
|
const severity = severityFilter(params);
|
|
4671
5025
|
try {
|
|
4672
|
-
const absPath =
|
|
5026
|
+
const absPath = resolveReadablePathInsideContext(filePath);
|
|
4673
5027
|
if (isDirectoryPath(absPath)) {
|
|
4674
5028
|
const extension = inferExtensionFromDirectory(absPath);
|
|
4675
5029
|
if (!extension) {
|
|
@@ -4698,7 +5052,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4698
5052
|
};
|
|
4699
5053
|
return text(output2.output, details2);
|
|
4700
5054
|
}
|
|
4701
|
-
const result = await withLspClient(filePath, async (client) => client.diagnostics(
|
|
5055
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
|
|
4702
5056
|
if (result.transientError) {
|
|
4703
5057
|
const message = result.transientError.message;
|
|
4704
5058
|
const details2 = {
|
|
@@ -4745,6 +5099,91 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4745
5099
|
throw error;
|
|
4746
5100
|
}
|
|
4747
5101
|
}
|
|
5102
|
+
var DEFAULT_FORMATTING_OPTIONS = {
|
|
5103
|
+
tabSize: 4,
|
|
5104
|
+
insertSpaces: false,
|
|
5105
|
+
trimTrailingWhitespace: true,
|
|
5106
|
+
insertFinalNewline: true,
|
|
5107
|
+
trimFinalNewlines: true
|
|
5108
|
+
};
|
|
5109
|
+
var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
|
|
5110
|
+
async function formatDocumentWithClient(client, filePath, options = {}) {
|
|
5111
|
+
const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
|
|
5112
|
+
if (edits === null)
|
|
5113
|
+
return { status: "unavailable", reason: "capability_not_advertised" };
|
|
5114
|
+
if (edits.length === 0)
|
|
5115
|
+
return UNCHANGED;
|
|
5116
|
+
const before = readFileSync6(filePath, "utf-8");
|
|
5117
|
+
const normalized = normalizeTextEdits(before, edits, 0);
|
|
5118
|
+
if (normalized.text === before)
|
|
5119
|
+
return UNCHANGED;
|
|
5120
|
+
writeAtomically(filePath, normalized.text);
|
|
5121
|
+
await client.openFile(filePath);
|
|
5122
|
+
return {
|
|
5123
|
+
status: "formatted",
|
|
5124
|
+
...lineDelta(normalized.edits)
|
|
5125
|
+
};
|
|
5126
|
+
}
|
|
5127
|
+
function lineDelta(edits) {
|
|
5128
|
+
let linesAdded = 0;
|
|
5129
|
+
let linesRemoved = 0;
|
|
5130
|
+
for (const edit of edits) {
|
|
5131
|
+
linesRemoved += edit.range.end.line - edit.range.start.line + 1;
|
|
5132
|
+
linesAdded += edit.newText.split(`
|
|
5133
|
+
`).length;
|
|
5134
|
+
}
|
|
5135
|
+
return { linesAdded, linesRemoved };
|
|
5136
|
+
}
|
|
5137
|
+
function writeAtomically(filePath, content) {
|
|
5138
|
+
const tempPath = `${filePath}.omo-format.tmp`;
|
|
5139
|
+
writeFileSync3(tempPath, content, "utf-8");
|
|
5140
|
+
try {
|
|
5141
|
+
renameSync3(tempPath, filePath);
|
|
5142
|
+
} catch (error) {
|
|
5143
|
+
try {
|
|
5144
|
+
unlinkSync2(tempPath);
|
|
5145
|
+
} catch {}
|
|
5146
|
+
throw error;
|
|
5147
|
+
}
|
|
5148
|
+
}
|
|
5149
|
+
async function executeLspFormat(params, signal) {
|
|
5150
|
+
const filePath = requireString(params, "filePath");
|
|
5151
|
+
try {
|
|
5152
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
|
|
5153
|
+
return text(describeResult(filePath, result), formatDetails(filePath, result));
|
|
5154
|
+
} catch (error) {
|
|
5155
|
+
const missingDependency = missingDependencyResult(error, {
|
|
5156
|
+
filePath,
|
|
5157
|
+
status: "unavailable",
|
|
5158
|
+
reason: "server_unavailable",
|
|
5159
|
+
linesAdded: 0,
|
|
5160
|
+
linesRemoved: 0
|
|
5161
|
+
});
|
|
5162
|
+
if (missingDependency)
|
|
5163
|
+
return missingDependency;
|
|
5164
|
+
throw error;
|
|
5165
|
+
}
|
|
5166
|
+
}
|
|
5167
|
+
function formatDetails(filePath, result) {
|
|
5168
|
+
if (result.status === "unavailable") {
|
|
5169
|
+
return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
|
|
5170
|
+
}
|
|
5171
|
+
return {
|
|
5172
|
+
filePath,
|
|
5173
|
+
status: result.status,
|
|
5174
|
+
linesAdded: result.linesAdded,
|
|
5175
|
+
linesRemoved: result.linesRemoved
|
|
5176
|
+
};
|
|
5177
|
+
}
|
|
5178
|
+
function describeResult(filePath, result) {
|
|
5179
|
+
if (result.status === "unavailable") {
|
|
5180
|
+
return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
|
|
5181
|
+
}
|
|
5182
|
+
if (result.status === "unchanged") {
|
|
5183
|
+
return `Already formatted: ${filePath}`;
|
|
5184
|
+
}
|
|
5185
|
+
return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
|
|
5186
|
+
}
|
|
4748
5187
|
async function executeLspInstallDecision(params) {
|
|
4749
5188
|
const serverId = requireString(params, "server_id");
|
|
4750
5189
|
const decision = params["decision"];
|
|
@@ -4770,7 +5209,7 @@ async function executeLspGotoDefinition(params, signal) {
|
|
|
4770
5209
|
const line = requireNumber(params, "line");
|
|
4771
5210
|
const character = requireNumber(params, "character");
|
|
4772
5211
|
try {
|
|
4773
|
-
const result = await withLspClient(filePath, async (client) => client.definition(
|
|
5212
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
|
|
4774
5213
|
const locations = !result ? [] : Array.isArray(result) ? result : [result];
|
|
4775
5214
|
const details = { filePath, line, character, locations };
|
|
4776
5215
|
if (locations.length === 0)
|
|
@@ -4795,7 +5234,7 @@ async function executeLspFindReferences(params, signal) {
|
|
|
4795
5234
|
const character = requireNumber(params, "character");
|
|
4796
5235
|
const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
|
|
4797
5236
|
try {
|
|
4798
|
-
const result = await withLspClient(filePath, async (client) => client.references(
|
|
5237
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
|
|
4799
5238
|
const references = Array.isArray(result) ? result : [];
|
|
4800
5239
|
const total = references.length;
|
|
4801
5240
|
const truncated = total > DEFAULT_MAX_REFERENCES;
|
|
@@ -4835,7 +5274,7 @@ async function executeLspPrepareRename(params, signal) {
|
|
|
4835
5274
|
const line = requireNumber(params, "line");
|
|
4836
5275
|
const character = requireNumber(params, "character");
|
|
4837
5276
|
try {
|
|
4838
|
-
const result = await withLspClient(filePath, async (client) => client.prepareRename(
|
|
5277
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
|
|
4839
5278
|
const details = { filePath, line, character, result };
|
|
4840
5279
|
return text(formatPrepareRenameResult(result), details);
|
|
4841
5280
|
} catch (error) {
|
|
@@ -4856,7 +5295,7 @@ async function executeLspRename(params, signal) {
|
|
|
4856
5295
|
const character = requireNumber(params, "character");
|
|
4857
5296
|
const newName = requireString(params, "newName");
|
|
4858
5297
|
try {
|
|
4859
|
-
const result = await withLspClient(filePath, async (client) => client.rename(
|
|
5298
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
|
|
4860
5299
|
const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
|
|
4861
5300
|
return text(formatApplyResult(result.apply), details, !result.apply.success);
|
|
4862
5301
|
} catch (error) {
|
|
@@ -4930,7 +5369,7 @@ async function executeLspSymbols(params, signal) {
|
|
|
4930
5369
|
const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
|
|
4931
5370
|
return formatSymbolsResult(filePath, scope, symbols2, limit, query);
|
|
4932
5371
|
}
|
|
4933
|
-
const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(
|
|
5372
|
+
const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
|
|
4934
5373
|
return formatSymbolsResult(filePath, scope, symbols, limit);
|
|
4935
5374
|
} catch (error) {
|
|
4936
5375
|
const query = optionalString(params, "query");
|
|
@@ -5064,6 +5503,16 @@ var LSP_MCP_TOOLS = [
|
|
|
5064
5503
|
}, ["filePath", "line", "character", "newName"]),
|
|
5065
5504
|
execute: executeLspRename
|
|
5066
5505
|
},
|
|
5506
|
+
{
|
|
5507
|
+
name: "format",
|
|
5508
|
+
aliases: ["lsp_format"],
|
|
5509
|
+
title: "LSP Format",
|
|
5510
|
+
description: "Format a source file with its language server and write the returned edits to disk.",
|
|
5511
|
+
inputSchema: objectSchema({
|
|
5512
|
+
filePath: { type: "string", description: "Source file path to format." }
|
|
5513
|
+
}, ["filePath"]),
|
|
5514
|
+
execute: executeLspFormat
|
|
5515
|
+
},
|
|
5067
5516
|
{
|
|
5068
5517
|
name: "install_decision",
|
|
5069
5518
|
aliases: ["lsp_install_decision"],
|
|
@@ -5130,7 +5579,7 @@ function withContext(args, context) {
|
|
|
5130
5579
|
function ensureDaemonAvailable(paths, ensure, signal) {
|
|
5131
5580
|
if (!signal)
|
|
5132
5581
|
return ensure(paths);
|
|
5133
|
-
return new Promise((
|
|
5582
|
+
return new Promise((resolve10, reject) => {
|
|
5134
5583
|
let settled = false;
|
|
5135
5584
|
const finish = (run) => {
|
|
5136
5585
|
if (settled)
|
|
@@ -5145,11 +5594,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
|
|
|
5145
5594
|
return;
|
|
5146
5595
|
}
|
|
5147
5596
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5148
|
-
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() =>
|
|
5597
|
+
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
|
|
5149
5598
|
});
|
|
5150
5599
|
}
|
|
5151
5600
|
function sendToolCall(paths, token, name, args, options) {
|
|
5152
|
-
return new Promise((
|
|
5601
|
+
return new Promise((resolve10, reject) => {
|
|
5153
5602
|
const socket = connect(paths.socket);
|
|
5154
5603
|
const requestId = allocateProxyRequestId();
|
|
5155
5604
|
let settled = false;
|
|
@@ -5202,7 +5651,7 @@ function sendToolCall(paths, token, name, args, options) {
|
|
|
5202
5651
|
}
|
|
5203
5652
|
const result = toToolResult(message, requestId);
|
|
5204
5653
|
if (result)
|
|
5205
|
-
finish(() =>
|
|
5654
|
+
finish(() => resolve10(result));
|
|
5206
5655
|
else
|
|
5207
5656
|
finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
|
|
5208
5657
|
});
|
|
@@ -5251,10 +5700,9 @@ var OMO_LSP_DAEMON_VERSION2 = "OMO_LSP_DAEMON_VERSION";
|
|
|
5251
5700
|
var DAEMON_VERSION_PATTERN2 = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
5252
5701
|
|
|
5253
5702
|
class InvalidRuntimeOverrideError2 extends Error {
|
|
5254
|
-
code = "invalid_runtime_override";
|
|
5255
|
-
reason;
|
|
5256
5703
|
constructor(reason, message) {
|
|
5257
5704
|
super(message);
|
|
5705
|
+
this.code = "invalid_runtime_override";
|
|
5258
5706
|
this.name = "InvalidRuntimeOverrideError";
|
|
5259
5707
|
this.reason = reason;
|
|
5260
5708
|
}
|
|
@@ -5274,12 +5722,12 @@ function resolveDaemonRuntime2(env, defaults) {
|
|
|
5274
5722
|
throw new InvalidRuntimeOverrideError2("paired_values_required", `${OMO_LSP_DAEMON_CLI2} and ${OMO_LSP_DAEMON_VERSION2} must be set together`);
|
|
5275
5723
|
}
|
|
5276
5724
|
if (!hasCliOverride || !hasVersionOverride) {
|
|
5277
|
-
if (!
|
|
5725
|
+
if (!isAbsolute6(defaults.cliPath)) {
|
|
5278
5726
|
throw new InvalidRuntimeOverrideError2("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
|
|
5279
5727
|
}
|
|
5280
5728
|
return { cliPath: defaults.cliPath, version: validateDaemonVersion2(defaults.version) };
|
|
5281
5729
|
}
|
|
5282
|
-
if (!
|
|
5730
|
+
if (!isAbsolute6(cliOverride)) {
|
|
5283
5731
|
throw new InvalidRuntimeOverrideError2("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI2} must be an absolute path to an existing regular file`);
|
|
5284
5732
|
}
|
|
5285
5733
|
const stat = statSync5(cliOverride, { throwIfNoEntry: false });
|
|
@@ -5400,15 +5848,14 @@ function extensionKey(filePath) {
|
|
|
5400
5848
|
}
|
|
5401
5849
|
// ../../../../lsp-core/src/request-context.ts
|
|
5402
5850
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
5403
|
-
import { existsSync as
|
|
5404
|
-
import { basename as
|
|
5851
|
+
import { existsSync as existsSync13, realpathSync as realpathSync6, statSync as statSync6 } from "node:fs";
|
|
5852
|
+
import { basename as basename4, delimiter as delimiter4, dirname as dirname2, isAbsolute as isAbsolute7, join as join8, relative as relative5, resolve as resolve10 } from "node:path";
|
|
5405
5853
|
|
|
5406
5854
|
class LspRequestContextParseError2 extends Error {
|
|
5407
|
-
code;
|
|
5408
|
-
name = "LspRequestContextParseError";
|
|
5409
5855
|
constructor(code, message) {
|
|
5410
5856
|
super(message);
|
|
5411
5857
|
this.code = code;
|
|
5858
|
+
this.name = "LspRequestContextParseError";
|
|
5412
5859
|
}
|
|
5413
5860
|
}
|
|
5414
5861
|
var storage2 = new AsyncLocalStorage2;
|
|
@@ -5443,26 +5890,26 @@ function parseLspRequestContext2(value) {
|
|
|
5443
5890
|
};
|
|
5444
5891
|
}
|
|
5445
5892
|
function canonicalCwd2(cwd) {
|
|
5446
|
-
const resolved =
|
|
5447
|
-
if (!
|
|
5893
|
+
const resolved = resolve10(cwd);
|
|
5894
|
+
if (!existsSync13(resolved) || !statSync6(resolved).isDirectory()) {
|
|
5448
5895
|
throw new LspRequestContextParseError2("invalid_cwd", `LSP request cwd must be an existing directory: ${cwd}`);
|
|
5449
5896
|
}
|
|
5450
|
-
return
|
|
5897
|
+
return realpathSync6(resolved);
|
|
5451
5898
|
}
|
|
5452
5899
|
function canonicalizeExistingOrNearestAncestor2(path2) {
|
|
5453
|
-
let current =
|
|
5900
|
+
let current = resolve10(path2);
|
|
5454
5901
|
const suffix = [];
|
|
5455
5902
|
while (true) {
|
|
5456
5903
|
try {
|
|
5457
|
-
const existing =
|
|
5458
|
-
return suffix.length === 0 ? existing :
|
|
5904
|
+
const existing = realpathSync6(current);
|
|
5905
|
+
return suffix.length === 0 ? existing : join8(existing, ...suffix);
|
|
5459
5906
|
} catch (error) {
|
|
5460
5907
|
if (!isMissingPathError2(error))
|
|
5461
5908
|
throw error;
|
|
5462
5909
|
const parent = dirname2(current);
|
|
5463
5910
|
if (parent === current)
|
|
5464
5911
|
throw error;
|
|
5465
|
-
suffix.unshift(
|
|
5912
|
+
suffix.unshift(basename4(current));
|
|
5466
5913
|
current = parent;
|
|
5467
5914
|
}
|
|
5468
5915
|
}
|
|
@@ -5493,14 +5940,14 @@ function stringArrayField2(value, field) {
|
|
|
5493
5940
|
return fieldValue;
|
|
5494
5941
|
}
|
|
5495
5942
|
function requireAbsolutePath2(path2, field) {
|
|
5496
|
-
if (!
|
|
5943
|
+
if (!isAbsolute7(path2)) {
|
|
5497
5944
|
throw new LspRequestContextParseError2("relative_path", `LSP request context.${field} must be absolute: ${path2}`);
|
|
5498
5945
|
}
|
|
5499
5946
|
}
|
|
5500
5947
|
function isPathInside2(parent, child) {
|
|
5501
|
-
const childPath =
|
|
5948
|
+
const childPath = resolve10(child);
|
|
5502
5949
|
const relativePath = relative5(parent, childPath);
|
|
5503
|
-
return relativePath === "" || !relativePath.startsWith("..") && !
|
|
5950
|
+
return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute7(relativePath);
|
|
5504
5951
|
}
|
|
5505
5952
|
function isMissingPathError2(error) {
|
|
5506
5953
|
const code = errorCode2(error);
|
|
@@ -5523,9 +5970,9 @@ function errorCode2(error) {
|
|
|
5523
5970
|
}
|
|
5524
5971
|
|
|
5525
5972
|
// src/daemon-cli-path.ts
|
|
5526
|
-
import { existsSync as
|
|
5973
|
+
import { existsSync as existsSync15, readFileSync as readFileSync7 } from "node:fs";
|
|
5527
5974
|
import { createRequire as createRequire2 } from "node:module";
|
|
5528
|
-
import { dirname as
|
|
5975
|
+
import { dirname as dirname11, join as join10 } from "node:path";
|
|
5529
5976
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
5530
5977
|
var requireFromHere2 = createRequire2(import.meta.url);
|
|
5531
5978
|
var PACKAGE_LSP_DAEMON_CLI = "@code-yeongyu/lsp-daemon/cli";
|
|
@@ -5547,7 +5994,7 @@ function resolveLspDaemonCli() {
|
|
|
5547
5994
|
if (packageCli !== null)
|
|
5548
5995
|
return resolveConfiguredLspDaemonCli(packageCli);
|
|
5549
5996
|
const bundledCli = fileURLToPath4(new URL("../../lsp-daemon/dist/cli.js", import.meta.url));
|
|
5550
|
-
if (
|
|
5997
|
+
if (existsSync15(bundledCli))
|
|
5551
5998
|
return resolveConfiguredLspDaemonCli(bundledCli);
|
|
5552
5999
|
return resolveConfiguredLspDaemonCli(bundledCli);
|
|
5553
6000
|
}
|
|
@@ -5572,7 +6019,7 @@ function resolveConfiguredLspDaemonCli(cliPath) {
|
|
|
5572
6019
|
}
|
|
5573
6020
|
function readDaemonPackageVersion(cliPath) {
|
|
5574
6021
|
try {
|
|
5575
|
-
const parsed = JSON.parse(
|
|
6022
|
+
const parsed = JSON.parse(readFileSync7(join10(dirname11(cliPath), "package.json"), "utf8"));
|
|
5576
6023
|
if (isRecord9(parsed) && typeof parsed["version"] === "string" && parsed["version"].length > 0) {
|
|
5577
6024
|
return parsed["version"];
|
|
5578
6025
|
}
|
|
@@ -5587,9 +6034,9 @@ function isRecord9(value) {
|
|
|
5587
6034
|
}
|
|
5588
6035
|
|
|
5589
6036
|
// src/lsp-session-state.ts
|
|
5590
|
-
import { mkdirSync as mkdirSync4, readFileSync as
|
|
6037
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "node:fs";
|
|
5591
6038
|
import { homedir } from "node:os";
|
|
5592
|
-
import { dirname as
|
|
6039
|
+
import { dirname as dirname13, join as join11 } from "node:path";
|
|
5593
6040
|
function sessionIdFrom(input) {
|
|
5594
6041
|
return typeof input.session_id === "string" && input.session_id.length > 0 ? input.session_id : undefined;
|
|
5595
6042
|
}
|
|
@@ -5615,12 +6062,12 @@ function isLspDaemonUnreachableDiagnostics(diagnostics) {
|
|
|
5615
6062
|
return diagnostics.includes("LSP daemon unreachable");
|
|
5616
6063
|
}
|
|
5617
6064
|
function sessionStatePath(sessionId) {
|
|
5618
|
-
const root = process.env["PLUGIN_DATA"] ??
|
|
5619
|
-
return
|
|
6065
|
+
const root = process.env["PLUGIN_DATA"] ?? join11(homedir(), ".codex", "codex-lsp");
|
|
6066
|
+
return join11(root, "sessions", `${safePathSegment(sessionId)}.json`);
|
|
5620
6067
|
}
|
|
5621
6068
|
function readSessionState(path2) {
|
|
5622
6069
|
try {
|
|
5623
|
-
const parsed = JSON.parse(
|
|
6070
|
+
const parsed = JSON.parse(readFileSync9(path2, "utf8"));
|
|
5624
6071
|
if (isRecord10(parsed) && isLspSessionState(parsed))
|
|
5625
6072
|
return normalizeSessionState(parsed);
|
|
5626
6073
|
return emptyState();
|
|
@@ -5631,8 +6078,8 @@ function readSessionState(path2) {
|
|
|
5631
6078
|
}
|
|
5632
6079
|
}
|
|
5633
6080
|
function writeSessionState(path2, state) {
|
|
5634
|
-
mkdirSync4(
|
|
5635
|
-
|
|
6081
|
+
mkdirSync4(dirname13(path2), { recursive: true });
|
|
6082
|
+
writeFileSync4(path2, `${JSON.stringify(state)}
|
|
5636
6083
|
`);
|
|
5637
6084
|
}
|
|
5638
6085
|
function emptyState() {
|
|
@@ -5775,13 +6222,13 @@ function notConfiguredAvailability(details) {
|
|
|
5775
6222
|
return typeof extension === "string" && extension.length > 0 ? { extension } : undefined;
|
|
5776
6223
|
}
|
|
5777
6224
|
function codexLspRequestContext(env = process.env, cwd = process.cwd()) {
|
|
5778
|
-
const canonicalCwd3 =
|
|
5779
|
-
const codexHome =
|
|
6225
|
+
const canonicalCwd3 = realpathSync8(resolve12(cwd));
|
|
6226
|
+
const codexHome = resolve12(env["CODEX_HOME"]?.trim() || join12(homedir3(), ".codex"));
|
|
5780
6227
|
return parseLspRequestContext2({
|
|
5781
6228
|
cwd: canonicalCwd3,
|
|
5782
|
-
projectConfigPaths: [
|
|
5783
|
-
userConfigPath:
|
|
5784
|
-
installDecisionsPath:
|
|
6229
|
+
projectConfigPaths: [join12(canonicalCwd3, ".codex", "lsp-client.json")],
|
|
6230
|
+
userConfigPath: join12(codexHome, "lsp-client.json"),
|
|
6231
|
+
installDecisionsPath: join12(codexHome, "lsp-install-decisions.json"),
|
|
5785
6232
|
capabilities: { installDecisionTool: true }
|
|
5786
6233
|
});
|
|
5787
6234
|
}
|
|
@@ -5875,7 +6322,7 @@ function isContextPressureTranscript(transcriptPath) {
|
|
|
5875
6322
|
if (typeof transcriptPath !== "string")
|
|
5876
6323
|
return false;
|
|
5877
6324
|
try {
|
|
5878
|
-
return hasContextPressureMarker(
|
|
6325
|
+
return hasContextPressureMarker(readFileSync10(transcriptPath, "utf8"));
|
|
5879
6326
|
} catch (error) {
|
|
5880
6327
|
if (error instanceof Error)
|
|
5881
6328
|
return false;
|
|
@@ -5957,15 +6404,15 @@ main().catch((error) => {
|
|
|
5957
6404
|
});
|
|
5958
6405
|
async function runPackageLspMcpCli() {
|
|
5959
6406
|
const cliPath = resolveLspDaemonCliPath();
|
|
5960
|
-
const child = spawn3(execPath2, [cliPath, "mcp"], { stdio: "inherit" });
|
|
5961
|
-
await new Promise((
|
|
6407
|
+
const child = spawn3(execPath2, [cliPath, "mcp"], { stdio: "inherit", windowsHide: true });
|
|
6408
|
+
await new Promise((resolve11, reject) => {
|
|
5962
6409
|
child.once("error", reject);
|
|
5963
6410
|
child.once("exit", (code, signal) => {
|
|
5964
6411
|
if (code !== null && code !== 0)
|
|
5965
6412
|
process.exitCode = code;
|
|
5966
6413
|
if (code === null && signal !== null)
|
|
5967
6414
|
process.exitCode = 1;
|
|
5968
|
-
|
|
6415
|
+
resolve11();
|
|
5969
6416
|
});
|
|
5970
6417
|
});
|
|
5971
6418
|
}
|