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
|
@@ -15,6 +15,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
|
15
15
|
// ../lsp-core/src/lsp/connection.ts
|
|
16
16
|
import { pathToFileURL } from "node:url";
|
|
17
17
|
|
|
18
|
+
// ../lsp-core/src/lsp/timer-provider.ts
|
|
19
|
+
var realTimerProvider = {
|
|
20
|
+
now: () => Date.now(),
|
|
21
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
22
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
23
|
+
};
|
|
24
|
+
|
|
18
25
|
// ../lsp-core/src/lsp/constants.ts
|
|
19
26
|
var DEFAULT_MAX_REFERENCES = 200;
|
|
20
27
|
var DEFAULT_MAX_SYMBOLS = 200;
|
|
@@ -23,28 +30,24 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
|
|
|
23
30
|
var REQUEST_TIMEOUT_MS = 15000;
|
|
24
31
|
var INIT_TIMEOUT_MS = 60000;
|
|
25
32
|
var IDLE_TIMEOUT_MS = 5 * 60000;
|
|
33
|
+
var MAX_RESIDENT_CLIENTS = 6;
|
|
26
34
|
var REAPER_INTERVAL_MS = 60000;
|
|
27
35
|
var STOP_HARD_KILL_TIMEOUT_MS = 5000;
|
|
28
36
|
var STOP_SIGKILL_GRACE_MS = 1000;
|
|
37
|
+
var CLIENT_RESPAWN_RETRY_LIMIT = 2;
|
|
38
|
+
var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
|
|
29
39
|
|
|
30
40
|
// ../lsp-core/src/lsp/errors.ts
|
|
31
41
|
class LspConnectionClosedError extends Error {
|
|
32
|
-
serverId;
|
|
33
|
-
root;
|
|
34
|
-
name = "LspConnectionClosedError";
|
|
35
42
|
constructor(serverId, root, message) {
|
|
36
43
|
super(message ?? `LSP connection closed for ${serverId} at ${root}`);
|
|
37
44
|
this.serverId = serverId;
|
|
38
45
|
this.root = root;
|
|
46
|
+
this.name = "LspConnectionClosedError";
|
|
39
47
|
}
|
|
40
48
|
}
|
|
41
49
|
|
|
42
50
|
class LspProcessExitedError extends Error {
|
|
43
|
-
serverId;
|
|
44
|
-
root;
|
|
45
|
-
exitCode;
|
|
46
|
-
stderrTail;
|
|
47
|
-
name = "LspProcessExitedError";
|
|
48
51
|
constructor(serverId, root, exitCode, stderrTail) {
|
|
49
52
|
const stderrSuffix = stderrTail ? `
|
|
50
53
|
stderr tail: ${stderrTail}` : "";
|
|
@@ -53,46 +56,59 @@ stderr tail: ${stderrTail}` : "";
|
|
|
53
56
|
this.root = root;
|
|
54
57
|
this.exitCode = exitCode;
|
|
55
58
|
this.stderrTail = stderrTail;
|
|
59
|
+
this.name = "LspProcessExitedError";
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
class LspRequestTimeoutError extends Error {
|
|
60
|
-
method;
|
|
61
|
-
stderrTail;
|
|
62
|
-
name = "LspRequestTimeoutError";
|
|
63
64
|
constructor(method, stderrTail) {
|
|
64
65
|
const stderrSuffix = stderrTail ? `
|
|
65
66
|
recent stderr: ${stderrTail}` : "";
|
|
66
67
|
super(`LSP request timeout (method: ${method})${stderrSuffix}`);
|
|
67
68
|
this.method = method;
|
|
68
69
|
this.stderrTail = stderrTail;
|
|
70
|
+
this.name = "LspRequestTimeoutError";
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
class LspInvalidPathError extends Error {
|
|
73
|
-
|
|
75
|
+
constructor() {
|
|
76
|
+
super(...arguments);
|
|
77
|
+
this.name = "LspInvalidPathError";
|
|
78
|
+
}
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
class LspServerLookupError extends Error {
|
|
77
|
-
lookup;
|
|
78
|
-
name = "LspServerLookupError";
|
|
79
82
|
constructor(message, lookup) {
|
|
80
83
|
super(message);
|
|
81
84
|
this.lookup = lookup;
|
|
85
|
+
this.name = "LspServerLookupError";
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
class LspServerInitializingError extends Error {
|
|
86
|
-
originalError;
|
|
87
|
-
name = "LspServerInitializingError";
|
|
88
90
|
constructor(originalError) {
|
|
89
91
|
super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
|
|
90
92
|
this.originalError = originalError;
|
|
93
|
+
this.name = "LspServerInitializingError";
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
class LspProcessSpawnError extends Error {
|
|
95
|
-
|
|
98
|
+
constructor() {
|
|
99
|
+
super(...arguments);
|
|
100
|
+
this.name = "LspProcessSpawnError";
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
class LspClientRespawnBudgetExceededError extends Error {
|
|
105
|
+
constructor(serverId, root, retryLimit) {
|
|
106
|
+
super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
|
|
107
|
+
this.serverId = serverId;
|
|
108
|
+
this.root = root;
|
|
109
|
+
this.retryLimit = retryLimit;
|
|
110
|
+
this.name = "LspClientRespawnBudgetExceededError";
|
|
111
|
+
}
|
|
96
112
|
}
|
|
97
113
|
function isLspDeadConnectionError(err) {
|
|
98
114
|
return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
|
|
@@ -108,20 +124,31 @@ var METHOD_NOT_FOUND = -32601;
|
|
|
108
124
|
var INTERNAL_ERROR = -32603;
|
|
109
125
|
|
|
110
126
|
class JsonRpcConnection {
|
|
111
|
-
reader;
|
|
112
|
-
writer;
|
|
113
|
-
pendingRequests = new Map;
|
|
114
|
-
notificationHandlers = new Map;
|
|
115
|
-
requestHandlers = new Map;
|
|
116
|
-
closeHandlers = [];
|
|
117
|
-
errorHandlers = [];
|
|
118
|
-
inputBuffer = Buffer.alloc(0);
|
|
119
|
-
nextRequestId = 1;
|
|
120
|
-
listening = false;
|
|
121
|
-
disposed = false;
|
|
122
127
|
constructor(reader, writer) {
|
|
123
128
|
this.reader = reader;
|
|
124
129
|
this.writer = writer;
|
|
130
|
+
this.pendingRequests = new Map;
|
|
131
|
+
this.notificationHandlers = new Map;
|
|
132
|
+
this.requestHandlers = new Map;
|
|
133
|
+
this.closeHandlers = [];
|
|
134
|
+
this.errorHandlers = [];
|
|
135
|
+
this.inputBuffer = Buffer.alloc(0);
|
|
136
|
+
this.nextRequestId = 1;
|
|
137
|
+
this.listening = false;
|
|
138
|
+
this.disposed = false;
|
|
139
|
+
this.handleData = (chunk) => {
|
|
140
|
+
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
141
|
+
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
142
|
+
this.drainInputBuffer();
|
|
143
|
+
};
|
|
144
|
+
this.handleClose = () => {
|
|
145
|
+
for (const handler of this.closeHandlers) {
|
|
146
|
+
handler();
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
this.handleStreamError = (error) => {
|
|
150
|
+
this.emitError(error);
|
|
151
|
+
};
|
|
125
152
|
}
|
|
126
153
|
listen() {
|
|
127
154
|
if (this.listening)
|
|
@@ -242,19 +269,6 @@ class JsonRpcConnection {
|
|
|
242
269
|
this.notificationHandlers.clear();
|
|
243
270
|
this.requestHandlers.clear();
|
|
244
271
|
}
|
|
245
|
-
handleData = (chunk) => {
|
|
246
|
-
const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
|
|
247
|
-
this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
|
|
248
|
-
this.drainInputBuffer();
|
|
249
|
-
};
|
|
250
|
-
handleClose = () => {
|
|
251
|
-
for (const handler of this.closeHandlers) {
|
|
252
|
-
handler();
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
|
-
handleStreamError = (error) => {
|
|
256
|
-
this.emitError(error);
|
|
257
|
-
};
|
|
258
272
|
drainInputBuffer() {
|
|
259
273
|
while (true) {
|
|
260
274
|
const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR);
|
|
@@ -602,33 +616,29 @@ function isPosition(value) {
|
|
|
602
616
|
|
|
603
617
|
// ../lsp-core/src/lsp/transport.ts
|
|
604
618
|
class LspClientNotStartedError extends Error {
|
|
605
|
-
serverId;
|
|
606
|
-
root;
|
|
607
|
-
name = "LspClientNotStartedError";
|
|
608
619
|
constructor(serverId, root) {
|
|
609
620
|
super("LSP client not started");
|
|
610
621
|
this.serverId = serverId;
|
|
611
622
|
this.root = root;
|
|
623
|
+
this.name = "LspClientNotStartedError";
|
|
612
624
|
}
|
|
613
625
|
}
|
|
614
626
|
|
|
615
627
|
class LspClientTransport {
|
|
616
|
-
root;
|
|
617
|
-
server;
|
|
618
|
-
proc = null;
|
|
619
|
-
connection = null;
|
|
620
|
-
stderrBuffer = [];
|
|
621
|
-
processExited = false;
|
|
622
|
-
diagnosticsStore = new Map;
|
|
623
|
-
requestTimeoutMs;
|
|
624
|
-
initializeTimeoutMs;
|
|
625
|
-
workspaceApplyEditHandler = null;
|
|
626
|
-
diagnosticPullSupported = false;
|
|
627
628
|
constructor(root, server, timeouts = {}) {
|
|
628
629
|
this.root = root;
|
|
629
630
|
this.server = server;
|
|
631
|
+
this.proc = null;
|
|
632
|
+
this.connection = null;
|
|
633
|
+
this.stderrBuffer = [];
|
|
634
|
+
this.processExited = false;
|
|
635
|
+
this.diagnosticsStore = new Map;
|
|
636
|
+
this.workspaceApplyEditHandler = null;
|
|
637
|
+
this.diagnosticPullSupported = false;
|
|
638
|
+
this.documentFormattingSupported = false;
|
|
630
639
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
631
640
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
641
|
+
this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
|
|
632
642
|
}
|
|
633
643
|
pid() {
|
|
634
644
|
return this.proc?.pid;
|
|
@@ -648,6 +658,12 @@ class LspClientTransport {
|
|
|
648
658
|
isDiagnosticPullSupported() {
|
|
649
659
|
return this.diagnosticPullSupported;
|
|
650
660
|
}
|
|
661
|
+
setDocumentFormattingSupported(supported) {
|
|
662
|
+
this.documentFormattingSupported = supported;
|
|
663
|
+
}
|
|
664
|
+
isDocumentFormattingSupported() {
|
|
665
|
+
return this.documentFormattingSupported;
|
|
666
|
+
}
|
|
651
667
|
handlePublishDiagnostics(params) {
|
|
652
668
|
this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
|
|
653
669
|
}
|
|
@@ -723,7 +739,7 @@ class LspClientTransport {
|
|
|
723
739
|
const options = args[1];
|
|
724
740
|
const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
|
|
725
741
|
const timeoutController = new AbortController;
|
|
726
|
-
const timeoutHandle = setTimeout(() => {
|
|
742
|
+
const timeoutHandle = this.timerProvider.setTimeout(() => {
|
|
727
743
|
const stderrTail = this.stderrBuffer.slice(-5).join(`
|
|
728
744
|
`);
|
|
729
745
|
timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
|
|
@@ -742,7 +758,7 @@ class LspClientTransport {
|
|
|
742
758
|
}
|
|
743
759
|
throw error;
|
|
744
760
|
} finally {
|
|
745
|
-
clearTimeout(timeoutHandle);
|
|
761
|
+
this.timerProvider.clearTimeout(timeoutHandle);
|
|
746
762
|
combinedSignal.dispose();
|
|
747
763
|
}
|
|
748
764
|
}
|
|
@@ -861,6 +877,14 @@ function supportsDiagnosticPull(capabilities) {
|
|
|
861
877
|
return false;
|
|
862
878
|
return Object.hasOwn(capabilities, "diagnosticProvider");
|
|
863
879
|
}
|
|
880
|
+
function supportsDocumentFormatting(capabilities) {
|
|
881
|
+
if (capabilities === undefined)
|
|
882
|
+
return false;
|
|
883
|
+
const provider = capabilities.documentFormattingProvider;
|
|
884
|
+
if (provider === undefined || provider === null || provider === false)
|
|
885
|
+
return false;
|
|
886
|
+
return provider === true || typeof provider === "object";
|
|
887
|
+
}
|
|
864
888
|
|
|
865
889
|
class LspClientConnection extends LspClientTransport {
|
|
866
890
|
async initialize() {
|
|
@@ -877,6 +901,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
877
901
|
references: {},
|
|
878
902
|
documentSymbol: { hierarchicalDocumentSymbolSupport: true },
|
|
879
903
|
publishDiagnostics: {},
|
|
904
|
+
formatting: { dynamicRegistration: false },
|
|
880
905
|
rename: {
|
|
881
906
|
prepareSupport: true,
|
|
882
907
|
prepareSupportDefaultBehavior: 1
|
|
@@ -918,6 +943,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
918
943
|
initializationOptions: this.server.initialization
|
|
919
944
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
920
945
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
946
|
+
this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
|
|
921
947
|
await this.sendNotification("initialized", {});
|
|
922
948
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
923
949
|
settings: { json: { validate: { enable: true } } }
|
|
@@ -1123,6 +1149,17 @@ function canonicalPath(filePath) {
|
|
|
1123
1149
|
return absolute;
|
|
1124
1150
|
}
|
|
1125
1151
|
}
|
|
1152
|
+
function normalizeDocumentUri(uri) {
|
|
1153
|
+
let decoded = uri;
|
|
1154
|
+
try {
|
|
1155
|
+
decoded = decodeURIComponent(uri);
|
|
1156
|
+
} catch {
|
|
1157
|
+
decoded = uri;
|
|
1158
|
+
}
|
|
1159
|
+
if (process.platform !== "win32")
|
|
1160
|
+
return decoded;
|
|
1161
|
+
return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
|
|
1162
|
+
}
|
|
1126
1163
|
function isSameOrDescendant(candidate, parent) {
|
|
1127
1164
|
const suffix = relative(parent, candidate);
|
|
1128
1165
|
return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
|
|
@@ -1133,17 +1170,18 @@ function movedPath(candidate, oldPath, newPath) {
|
|
|
1133
1170
|
}
|
|
1134
1171
|
|
|
1135
1172
|
class WorkspaceDocumentState {
|
|
1136
|
-
sendNotification;
|
|
1137
|
-
clearDiagnostics;
|
|
1138
|
-
openDocuments = new Map;
|
|
1139
|
-
openByUri = new Map;
|
|
1140
|
-
openPromises = new Map;
|
|
1141
|
-
now;
|
|
1142
|
-
versionlessPublishQuiescenceMs;
|
|
1143
1173
|
constructor(sendNotification, clearDiagnostics, options = {}) {
|
|
1144
1174
|
this.sendNotification = sendNotification;
|
|
1145
1175
|
this.clearDiagnostics = clearDiagnostics;
|
|
1146
|
-
this.
|
|
1176
|
+
this.openDocuments = new Map;
|
|
1177
|
+
this.openByUri = new Map;
|
|
1178
|
+
this.openPromises = new Map;
|
|
1179
|
+
this.timerProvider = options.timerProvider ?? {
|
|
1180
|
+
now: options.now ?? (() => Date.now()),
|
|
1181
|
+
setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
|
|
1182
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
1183
|
+
};
|
|
1184
|
+
this.now = () => this.timerProvider.now();
|
|
1147
1185
|
this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
|
|
1148
1186
|
}
|
|
1149
1187
|
async openFile(filePath) {
|
|
@@ -1165,7 +1203,7 @@ class WorkspaceDocumentState {
|
|
|
1165
1203
|
return this.openDocuments.get(canonicalPath(filePath))?.version;
|
|
1166
1204
|
}
|
|
1167
1205
|
getStoredDiagnostics(uri) {
|
|
1168
|
-
const state = this.openByUri.get(uri);
|
|
1206
|
+
const state = this.openByUri.get(normalizeDocumentUri(uri));
|
|
1169
1207
|
if (!state)
|
|
1170
1208
|
return [];
|
|
1171
1209
|
return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
|
|
@@ -1187,13 +1225,13 @@ class WorkspaceDocumentState {
|
|
|
1187
1225
|
return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
|
|
1188
1226
|
}
|
|
1189
1227
|
getPullCache(snapshot) {
|
|
1190
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1228
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1191
1229
|
if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
|
|
1192
1230
|
return null;
|
|
1193
1231
|
return state.pullCache;
|
|
1194
1232
|
}
|
|
1195
1233
|
recordPullDiagnostics(snapshot, report) {
|
|
1196
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1234
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1197
1235
|
if (!state)
|
|
1198
1236
|
return;
|
|
1199
1237
|
state.pullCache = {
|
|
@@ -1203,7 +1241,7 @@ class WorkspaceDocumentState {
|
|
|
1203
1241
|
};
|
|
1204
1242
|
}
|
|
1205
1243
|
recordPublishedDiagnostics(params) {
|
|
1206
|
-
const state = this.openByUri.get(params.uri);
|
|
1244
|
+
const state = this.openByUri.get(normalizeDocumentUri(params.uri));
|
|
1207
1245
|
if (!state)
|
|
1208
1246
|
return;
|
|
1209
1247
|
state.publishGeneration += 1;
|
|
@@ -1217,7 +1255,7 @@ class WorkspaceDocumentState {
|
|
|
1217
1255
|
this.notifyWaiters(state);
|
|
1218
1256
|
}
|
|
1219
1257
|
resolvePushDiagnostics(snapshot) {
|
|
1220
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1258
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1221
1259
|
if (!state?.lastPublish)
|
|
1222
1260
|
return { status: "missing" };
|
|
1223
1261
|
const publish = state.lastPublish;
|
|
@@ -1231,7 +1269,7 @@ class WorkspaceDocumentState {
|
|
|
1231
1269
|
return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
|
|
1232
1270
|
}
|
|
1233
1271
|
waitForDiagnosticsActivity(snapshot, timeoutMs) {
|
|
1234
|
-
const state = this.openByUri.get(snapshot.uri);
|
|
1272
|
+
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1235
1273
|
if (!state || timeoutMs <= 0)
|
|
1236
1274
|
return Promise.resolve();
|
|
1237
1275
|
return new Promise((resolveActivity) => {
|
|
@@ -1240,11 +1278,11 @@ class WorkspaceDocumentState {
|
|
|
1240
1278
|
if (settled)
|
|
1241
1279
|
return;
|
|
1242
1280
|
settled = true;
|
|
1243
|
-
clearTimeout(timer);
|
|
1281
|
+
this.timerProvider.clearTimeout(timer);
|
|
1244
1282
|
state.waiters.delete(finish);
|
|
1245
1283
|
resolveActivity();
|
|
1246
1284
|
};
|
|
1247
|
-
const timer = setTimeout(finish, timeoutMs);
|
|
1285
|
+
const timer = this.timerProvider.setTimeout(finish, timeoutMs);
|
|
1248
1286
|
if (typeof timer.unref === "function")
|
|
1249
1287
|
timer.unref();
|
|
1250
1288
|
state.waiters.add(finish);
|
|
@@ -1352,7 +1390,7 @@ class WorkspaceDocumentState {
|
|
|
1352
1390
|
waiters: new Set
|
|
1353
1391
|
};
|
|
1354
1392
|
this.openDocuments.set(path, state);
|
|
1355
|
-
this.openByUri.set(state.uri, state);
|
|
1393
|
+
this.openByUri.set(normalizeDocumentUri(state.uri), state);
|
|
1356
1394
|
this.notifyWaiters(state);
|
|
1357
1395
|
await this.sendNotification("textDocument/didOpen", {
|
|
1358
1396
|
textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
|
|
@@ -1377,7 +1415,7 @@ class WorkspaceDocumentState {
|
|
|
1377
1415
|
}
|
|
1378
1416
|
async closeDocument(state) {
|
|
1379
1417
|
this.openDocuments.delete(state.path);
|
|
1380
|
-
this.openByUri.delete(state.uri);
|
|
1418
|
+
this.openByUri.delete(normalizeDocumentUri(state.uri));
|
|
1381
1419
|
this.clearDiagnostics(state.uri);
|
|
1382
1420
|
this.notifyWaiters(state);
|
|
1383
1421
|
await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
|
|
@@ -1406,13 +1444,11 @@ import { dirname, isAbsolute, relative as relative2, resolve as resolve2 } from
|
|
|
1406
1444
|
import { fileURLToPath } from "node:url";
|
|
1407
1445
|
|
|
1408
1446
|
class WorkspaceEditPathError extends Error {
|
|
1409
|
-
path;
|
|
1410
|
-
detail;
|
|
1411
|
-
name = "WorkspaceEditPathError";
|
|
1412
1447
|
constructor(path, detail) {
|
|
1413
1448
|
super(`${detail}: ${path}`);
|
|
1414
1449
|
this.path = path;
|
|
1415
1450
|
this.detail = detail;
|
|
1451
|
+
this.name = "WorkspaceEditPathError";
|
|
1416
1452
|
}
|
|
1417
1453
|
}
|
|
1418
1454
|
function isPathInsideWorkspace(filePath, workspaceRoot) {
|
|
@@ -1704,13 +1740,11 @@ function canonicalFingerprint(operations) {
|
|
|
1704
1740
|
|
|
1705
1741
|
// ../lsp-core/src/lsp/workspace-edit-types.ts
|
|
1706
1742
|
class WorkspaceEditValidationError extends Error {
|
|
1707
|
-
changeIndex;
|
|
1708
|
-
detail;
|
|
1709
|
-
name = "WorkspaceEditValidationError";
|
|
1710
1743
|
constructor(changeIndex, detail) {
|
|
1711
1744
|
super(`change ${changeIndex}: ${detail}`);
|
|
1712
1745
|
this.changeIndex = changeIndex;
|
|
1713
1746
|
this.detail = detail;
|
|
1747
|
+
this.name = "WorkspaceEditValidationError";
|
|
1714
1748
|
}
|
|
1715
1749
|
}
|
|
1716
1750
|
|
|
@@ -2208,10 +2242,9 @@ function simulateDelete(operation, virtual) {
|
|
|
2208
2242
|
import { existsSync as existsSync4, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
|
|
2209
2243
|
import { dirname as dirname3, resolve as resolve4 } from "node:path";
|
|
2210
2244
|
class WorkspaceSnapshotBuilder {
|
|
2211
|
-
workspaceRoot;
|
|
2212
|
-
snapshots = new Map;
|
|
2213
2245
|
constructor(workspaceRoot) {
|
|
2214
2246
|
this.workspaceRoot = workspaceRoot;
|
|
2247
|
+
this.snapshots = new Map;
|
|
2215
2248
|
}
|
|
2216
2249
|
build(operations) {
|
|
2217
2250
|
this.add(this.workspaceRoot, false);
|
|
@@ -2255,8 +2288,10 @@ function snapshotOperations(operations, workspaceRoot) {
|
|
|
2255
2288
|
|
|
2256
2289
|
// ../lsp-core/src/lsp/workspace-edit-plan.ts
|
|
2257
2290
|
class PlanPathIndex {
|
|
2258
|
-
|
|
2259
|
-
|
|
2291
|
+
constructor() {
|
|
2292
|
+
this.firstChangeByPath = new Map;
|
|
2293
|
+
this.reportedPathByCanonical = new Map;
|
|
2294
|
+
}
|
|
2260
2295
|
build(operations) {
|
|
2261
2296
|
for (const operation of operations) {
|
|
2262
2297
|
switch (operation.kind) {
|
|
@@ -2345,14 +2380,11 @@ function isRecord3(value) {
|
|
|
2345
2380
|
}
|
|
2346
2381
|
|
|
2347
2382
|
class WorkspaceMutationController {
|
|
2348
|
-
workspaceRoot;
|
|
2349
|
-
documents;
|
|
2350
|
-
activeLease = null;
|
|
2351
|
-
nextLeaseId = 1;
|
|
2352
|
-
io;
|
|
2353
2383
|
constructor(workspaceRoot, documents) {
|
|
2354
2384
|
this.workspaceRoot = workspaceRoot;
|
|
2355
2385
|
this.documents = documents;
|
|
2386
|
+
this.activeLease = null;
|
|
2387
|
+
this.nextLeaseId = 1;
|
|
2356
2388
|
}
|
|
2357
2389
|
setIo(io) {
|
|
2358
2390
|
this.io = io;
|
|
@@ -2465,14 +2497,12 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
|
|
|
2465
2497
|
var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
|
|
2466
2498
|
|
|
2467
2499
|
class LspClient extends LspClientConnection {
|
|
2468
|
-
diagnosticPullErrors = [];
|
|
2469
|
-
documents;
|
|
2470
|
-
workspaceMutations;
|
|
2471
|
-
diagnosticsFreshnessTimeoutMs;
|
|
2472
2500
|
constructor(root, server, options = {}) {
|
|
2473
2501
|
super(root, server, options);
|
|
2502
|
+
this.diagnosticPullErrors = [];
|
|
2474
2503
|
this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
|
|
2475
2504
|
this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
|
|
2505
|
+
timerProvider: this.timerProvider,
|
|
2476
2506
|
versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
|
|
2477
2507
|
});
|
|
2478
2508
|
this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
|
|
@@ -2525,6 +2555,18 @@ class LspClient extends LspClientConnection {
|
|
|
2525
2555
|
textDocument: { uri: pathToFileURL3(absPath).href }
|
|
2526
2556
|
}, options);
|
|
2527
2557
|
}
|
|
2558
|
+
async formatDocument(filePath, options, signal) {
|
|
2559
|
+
if (!this.isDocumentFormattingSupported())
|
|
2560
|
+
return null;
|
|
2561
|
+
const absPath = this.resolveWorkspacePath(filePath);
|
|
2562
|
+
await this.openFile(absPath);
|
|
2563
|
+
const requestOptions = signal === undefined ? {} : { signal };
|
|
2564
|
+
const edits = await this.sendRequest("textDocument/formatting", {
|
|
2565
|
+
textDocument: { uri: pathToFileURL3(absPath).href },
|
|
2566
|
+
options
|
|
2567
|
+
}, requestOptions);
|
|
2568
|
+
return edits ?? [];
|
|
2569
|
+
}
|
|
2528
2570
|
async workspaceSymbols(query, signal) {
|
|
2529
2571
|
const options = signal === undefined ? {} : { signal };
|
|
2530
2572
|
return this.sendRequest("workspace/symbol", { query }, options);
|
|
@@ -2564,7 +2606,7 @@ class LspClient extends LspClientConnection {
|
|
|
2564
2606
|
const absPath = this.resolveWorkspacePath(filePath);
|
|
2565
2607
|
const uri = pathToFileURL3(absPath).href;
|
|
2566
2608
|
await this.openFile(absPath);
|
|
2567
|
-
const deadlineAt =
|
|
2609
|
+
const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
|
|
2568
2610
|
for (;; ) {
|
|
2569
2611
|
signal?.throwIfAborted();
|
|
2570
2612
|
const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
|
|
@@ -2577,7 +2619,7 @@ class LspClient extends LspClientConnection {
|
|
|
2577
2619
|
if (!pushFallbackOnly) {
|
|
2578
2620
|
const cached = this.documents.getPullCache(snapshot);
|
|
2579
2621
|
try {
|
|
2580
|
-
const remainingMs2 = deadlineAt -
|
|
2622
|
+
const remainingMs2 = deadlineAt - this.timerProvider.now();
|
|
2581
2623
|
if (remainingMs2 <= 0)
|
|
2582
2624
|
return this.freshnessTimeout(absPath);
|
|
2583
2625
|
const result = await this.sendRequest("textDocument/diagnostic", {
|
|
@@ -2612,7 +2654,7 @@ class LspClient extends LspClientConnection {
|
|
|
2612
2654
|
}
|
|
2613
2655
|
if (!pushFallbackOnly)
|
|
2614
2656
|
continue;
|
|
2615
|
-
const remainingMs = deadlineAt -
|
|
2657
|
+
const remainingMs = deadlineAt - this.timerProvider.now();
|
|
2616
2658
|
if (remainingMs <= 0) {
|
|
2617
2659
|
if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
|
|
2618
2660
|
const cached = this.documents.getPullCache(snapshot);
|
|
@@ -2770,18 +2812,16 @@ function awaitWithSignal(promise, signal) {
|
|
|
2770
2812
|
}
|
|
2771
2813
|
|
|
2772
2814
|
class LspManager {
|
|
2773
|
-
clients = new Map;
|
|
2774
|
-
reaperHandle = null;
|
|
2775
|
-
signalDisposer = null;
|
|
2776
|
-
disposed = false;
|
|
2777
|
-
idleTimeoutMs;
|
|
2778
|
-
initTimeoutMs;
|
|
2779
|
-
reaperIntervalMs;
|
|
2780
|
-
clientFactory;
|
|
2781
|
-
now;
|
|
2782
2815
|
constructor(options = {}) {
|
|
2816
|
+
this.clients = new Map;
|
|
2817
|
+
this.pendingStops = new Map;
|
|
2818
|
+
this.respawnBudgets = new Map;
|
|
2819
|
+
this.reaperHandle = null;
|
|
2820
|
+
this.signalDisposer = null;
|
|
2821
|
+
this.disposed = false;
|
|
2783
2822
|
this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
|
|
2784
2823
|
this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
2824
|
+
this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
|
|
2785
2825
|
this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
|
|
2786
2826
|
this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
|
|
2787
2827
|
this.now = options.now ?? (() => Date.now());
|
|
@@ -2801,24 +2841,79 @@ class LspManager {
|
|
|
2801
2841
|
getKey(root, serverId) {
|
|
2802
2842
|
return `${root}::${serverId}`;
|
|
2803
2843
|
}
|
|
2844
|
+
tombstoneStop(key, client) {
|
|
2845
|
+
const stop = stopClientBestEffort(client);
|
|
2846
|
+
this.pendingStops.set(key, stop);
|
|
2847
|
+
stop.finally(() => {
|
|
2848
|
+
if (this.pendingStops.get(key) === stop) {
|
|
2849
|
+
this.pendingStops.delete(key);
|
|
2850
|
+
}
|
|
2851
|
+
});
|
|
2852
|
+
return stop;
|
|
2853
|
+
}
|
|
2854
|
+
recordDeadGeneration(key) {
|
|
2855
|
+
let budget = this.respawnBudgets.get(key);
|
|
2856
|
+
if (budget === undefined) {
|
|
2857
|
+
budget = { deadGenerations: 0, exhaustedAt: null };
|
|
2858
|
+
this.respawnBudgets.set(key, budget);
|
|
2859
|
+
}
|
|
2860
|
+
budget.deadGenerations += 1;
|
|
2861
|
+
}
|
|
2862
|
+
markHealthyGeneration(key) {
|
|
2863
|
+
this.respawnBudgets.delete(key);
|
|
2864
|
+
}
|
|
2865
|
+
ensureRespawnAllowed(key, root, serverId) {
|
|
2866
|
+
const budget = this.respawnBudgets.get(key);
|
|
2867
|
+
if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
|
|
2868
|
+
return;
|
|
2869
|
+
if (budget.exhaustedAt === null) {
|
|
2870
|
+
budget.exhaustedAt = this.now();
|
|
2871
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
2872
|
+
}
|
|
2873
|
+
if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
|
|
2874
|
+
throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
|
|
2875
|
+
}
|
|
2876
|
+
budget.deadGenerations = 0;
|
|
2877
|
+
budget.exhaustedAt = null;
|
|
2878
|
+
}
|
|
2804
2879
|
reapStale() {
|
|
2805
2880
|
const t = this.now();
|
|
2806
2881
|
for (const [key, managed] of this.clients) {
|
|
2807
2882
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
2808
|
-
stopClientBestEffort(managed.client);
|
|
2809
2883
|
this.clients.delete(key);
|
|
2884
|
+
this.tombstoneStop(key, managed.client);
|
|
2810
2885
|
continue;
|
|
2811
2886
|
}
|
|
2812
2887
|
if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
|
|
2813
|
-
stopClientBestEffort(managed.client);
|
|
2814
2888
|
this.clients.delete(key);
|
|
2889
|
+
this.tombstoneStop(key, managed.client);
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
evictForAdmission() {
|
|
2894
|
+
while (this.clients.size >= this.maxResidentClients) {
|
|
2895
|
+
const victim = this.leastRecentlyUsedIdleClient();
|
|
2896
|
+
if (!victim)
|
|
2897
|
+
return;
|
|
2898
|
+
this.clients.delete(victim.key);
|
|
2899
|
+
this.tombstoneStop(victim.key, victim.managed.client);
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
leastRecentlyUsedIdleClient() {
|
|
2903
|
+
let candidate = null;
|
|
2904
|
+
for (const [key, managed] of this.clients) {
|
|
2905
|
+
if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
|
|
2906
|
+
continue;
|
|
2907
|
+
if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
|
|
2908
|
+
candidate = { key, managed };
|
|
2815
2909
|
}
|
|
2816
2910
|
}
|
|
2911
|
+
return candidate;
|
|
2817
2912
|
}
|
|
2818
2913
|
async tryDeleteIfOrphaned(key, managed) {
|
|
2819
2914
|
if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
|
|
2820
2915
|
this.clients.delete(key);
|
|
2821
|
-
await
|
|
2916
|
+
await this.tombstoneStop(key, managed.client);
|
|
2822
2917
|
}
|
|
2823
2918
|
}
|
|
2824
2919
|
async getClient(root, server, signal) {
|
|
@@ -2827,12 +2922,22 @@ class LspManager {
|
|
|
2827
2922
|
}
|
|
2828
2923
|
signal?.throwIfAborted();
|
|
2829
2924
|
const key = this.getKey(root, server.id);
|
|
2925
|
+
for (;; ) {
|
|
2926
|
+
const pendingStop = this.pendingStops.get(key);
|
|
2927
|
+
if (pendingStop === undefined)
|
|
2928
|
+
break;
|
|
2929
|
+
await awaitWithSignal(pendingStop, signal);
|
|
2930
|
+
signal?.throwIfAborted();
|
|
2931
|
+
}
|
|
2932
|
+
if (this.disposed) {
|
|
2933
|
+
throw new Error("LspManager has been disposed");
|
|
2934
|
+
}
|
|
2830
2935
|
let managed = this.clients.get(key);
|
|
2831
2936
|
if (managed) {
|
|
2832
2937
|
const t = this.now();
|
|
2833
2938
|
if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
|
|
2834
|
-
await stopClientBestEffort(managed.client);
|
|
2835
2939
|
this.clients.delete(key);
|
|
2940
|
+
await this.tombstoneStop(key, managed.client);
|
|
2836
2941
|
managed = undefined;
|
|
2837
2942
|
}
|
|
2838
2943
|
}
|
|
@@ -2853,14 +2958,20 @@ class LspManager {
|
|
|
2853
2958
|
signal.throwIfAborted();
|
|
2854
2959
|
}
|
|
2855
2960
|
if (!managed.client.isAlive()) {
|
|
2856
|
-
|
|
2857
|
-
this.clients.
|
|
2961
|
+
this.recordDeadGeneration(key);
|
|
2962
|
+
if (this.clients.get(key) === managed) {
|
|
2963
|
+
this.clients.delete(key);
|
|
2964
|
+
}
|
|
2965
|
+
await this.tombstoneStop(key, managed.client);
|
|
2858
2966
|
return this.getClient(root, server, signal);
|
|
2859
2967
|
}
|
|
2968
|
+
this.markHealthyGeneration(key);
|
|
2860
2969
|
managed.refCount++;
|
|
2861
2970
|
managed.lastUsedAt = this.now();
|
|
2862
2971
|
return managed.client;
|
|
2863
2972
|
}
|
|
2973
|
+
this.evictForAdmission();
|
|
2974
|
+
this.ensureRespawnAllowed(key, root, server.id);
|
|
2864
2975
|
const client = this.clientFactory(root, server);
|
|
2865
2976
|
const initStartedAt = this.now();
|
|
2866
2977
|
const initPromise = (async () => {
|
|
@@ -2884,7 +2995,7 @@ class LspManager {
|
|
|
2884
2995
|
if (this.clients.get(key) === newManaged) {
|
|
2885
2996
|
this.clients.delete(key);
|
|
2886
2997
|
}
|
|
2887
|
-
await
|
|
2998
|
+
await this.tombstoneStop(key, client);
|
|
2888
2999
|
throw err;
|
|
2889
3000
|
}
|
|
2890
3001
|
newManaged.pendingWaiters--;
|
|
@@ -2895,6 +3006,15 @@ class LspManager {
|
|
|
2895
3006
|
await this.tryDeleteIfOrphaned(key, newManaged);
|
|
2896
3007
|
signal.throwIfAborted();
|
|
2897
3008
|
}
|
|
3009
|
+
if (!client.isAlive()) {
|
|
3010
|
+
this.recordDeadGeneration(key);
|
|
3011
|
+
if (this.clients.get(key) === newManaged) {
|
|
3012
|
+
this.clients.delete(key);
|
|
3013
|
+
}
|
|
3014
|
+
await this.tombstoneStop(key, client);
|
|
3015
|
+
return this.getClient(root, server, signal);
|
|
3016
|
+
}
|
|
3017
|
+
this.markHealthyGeneration(key);
|
|
2898
3018
|
newManaged.refCount++;
|
|
2899
3019
|
newManaged.lastUsedAt = this.now();
|
|
2900
3020
|
return client;
|
|
@@ -2915,14 +3035,20 @@ class LspManager {
|
|
|
2915
3035
|
if (client && managed.client !== client)
|
|
2916
3036
|
return;
|
|
2917
3037
|
this.clients.delete(key);
|
|
2918
|
-
|
|
3038
|
+
this.tombstoneStop(key, managed.client);
|
|
2919
3039
|
}
|
|
2920
3040
|
warmupClient(root, server) {
|
|
2921
3041
|
if (this.disposed)
|
|
2922
3042
|
return;
|
|
2923
3043
|
const key = this.getKey(root, server.id);
|
|
2924
|
-
if (this.clients.has(key))
|
|
3044
|
+
if (this.clients.has(key) || this.pendingStops.has(key))
|
|
2925
3045
|
return;
|
|
3046
|
+
this.evictForAdmission();
|
|
3047
|
+
try {
|
|
3048
|
+
this.ensureRespawnAllowed(key, root, server.id);
|
|
3049
|
+
} catch {
|
|
3050
|
+
return;
|
|
3051
|
+
}
|
|
2926
3052
|
const client = this.clientFactory(root, server);
|
|
2927
3053
|
const initStartedAt = this.now();
|
|
2928
3054
|
const initPromise = (async () => {
|
|
@@ -2948,7 +3074,7 @@ class LspManager {
|
|
|
2948
3074
|
if (this.clients.get(key) === managed) {
|
|
2949
3075
|
this.clients.delete(key);
|
|
2950
3076
|
}
|
|
2951
|
-
|
|
3077
|
+
this.tombstoneStop(key, client);
|
|
2952
3078
|
});
|
|
2953
3079
|
}
|
|
2954
3080
|
isServerInitializing(root, serverId) {
|
|
@@ -2992,8 +3118,11 @@ class LspManager {
|
|
|
2992
3118
|
for (const managed of this.clients.values()) {
|
|
2993
3119
|
stopPromises.push(stopClientBestEffort(managed.client));
|
|
2994
3120
|
}
|
|
3121
|
+
const tombstonedStops = [...this.pendingStops.values()];
|
|
2995
3122
|
this.clients.clear();
|
|
2996
|
-
|
|
3123
|
+
this.respawnBudgets.clear();
|
|
3124
|
+
await Promise.allSettled([...stopPromises, ...tombstonedStops]);
|
|
3125
|
+
this.pendingStops.clear();
|
|
2997
3126
|
}
|
|
2998
3127
|
}
|
|
2999
3128
|
var _defaultInstance = null;
|
|
@@ -3013,7 +3142,7 @@ async function disposeDefaultLspManager() {
|
|
|
3013
3142
|
// src/daemon-client.ts
|
|
3014
3143
|
import { connect } from "node:net";
|
|
3015
3144
|
import { homedir as homedir3 } from "node:os";
|
|
3016
|
-
import { join as
|
|
3145
|
+
import { join as join8 } from "node:path";
|
|
3017
3146
|
|
|
3018
3147
|
// ../lsp-core/src/request-context.ts
|
|
3019
3148
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -3022,18 +3151,17 @@ import { homedir } from "node:os";
|
|
|
3022
3151
|
import { basename as basename2, delimiter as delimiter2, dirname as dirname4, isAbsolute as isAbsolute2, join as join2, relative as relative4, resolve as resolve6 } from "node:path";
|
|
3023
3152
|
|
|
3024
3153
|
class LspRequestContextParseError extends Error {
|
|
3025
|
-
code;
|
|
3026
|
-
name = "LspRequestContextParseError";
|
|
3027
3154
|
constructor(code, message) {
|
|
3028
3155
|
super(message);
|
|
3029
3156
|
this.code = code;
|
|
3157
|
+
this.name = "LspRequestContextParseError";
|
|
3030
3158
|
}
|
|
3031
3159
|
}
|
|
3032
3160
|
|
|
3033
3161
|
class LspRequestContextUnavailableError extends Error {
|
|
3034
|
-
name = "LspRequestContextUnavailableError";
|
|
3035
3162
|
constructor() {
|
|
3036
3163
|
super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
|
|
3164
|
+
this.name = "LspRequestContextUnavailableError";
|
|
3037
3165
|
}
|
|
3038
3166
|
}
|
|
3039
3167
|
var storage = new AsyncLocalStorage;
|
|
@@ -3053,7 +3181,7 @@ function contextCwd() {
|
|
|
3053
3181
|
}
|
|
3054
3182
|
function createStandaloneMcpRequestContext(input = {}) {
|
|
3055
3183
|
const env = input.env ?? process.env;
|
|
3056
|
-
const cwd = canonicalCwd(input.cwd ?? process.cwd());
|
|
3184
|
+
const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
|
|
3057
3185
|
const home = input.homeDir ?? homedir();
|
|
3058
3186
|
const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
|
|
3059
3187
|
const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
|
|
@@ -3191,7 +3319,6 @@ function isPlainRecord(value) {
|
|
|
3191
3319
|
|
|
3192
3320
|
// src/daemon-request-error.ts
|
|
3193
3321
|
class DaemonRequestError extends Error {
|
|
3194
|
-
requestWritten;
|
|
3195
3322
|
constructor(message, requestWritten) {
|
|
3196
3323
|
super(message);
|
|
3197
3324
|
this.name = "DaemonRequestError";
|
|
@@ -3214,7 +3341,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
|
|
|
3214
3341
|
}
|
|
3215
3342
|
|
|
3216
3343
|
class DaemonRequestTimedOutError extends DaemonRequestError {
|
|
3217
|
-
timeoutMs;
|
|
3218
3344
|
constructor(requestWritten, timeoutMs) {
|
|
3219
3345
|
super("daemon request timed out", requestWritten);
|
|
3220
3346
|
this.name = "DaemonRequestTimedOutError";
|
|
@@ -3293,14 +3419,12 @@ var PROTOCOL_ERROR_CODE = -32002;
|
|
|
3293
3419
|
var AUTH_TOKEN_BYTES = 32;
|
|
3294
3420
|
|
|
3295
3421
|
class UnsafePrivateDirectoryError extends Error {
|
|
3296
|
-
path;
|
|
3297
|
-
reason;
|
|
3298
|
-
name = "UnsafePrivateDirectoryError";
|
|
3299
|
-
code = "unsafe_private_directory";
|
|
3300
3422
|
constructor(path, reason) {
|
|
3301
3423
|
super(`unsafe private directory ${path}: ${reason}`);
|
|
3302
3424
|
this.path = path;
|
|
3303
3425
|
this.reason = reason;
|
|
3426
|
+
this.name = "UnsafePrivateDirectoryError";
|
|
3427
|
+
this.code = "unsafe_private_directory";
|
|
3304
3428
|
}
|
|
3305
3429
|
}
|
|
3306
3430
|
function authEnvelope(token) {
|
|
@@ -3484,20 +3608,18 @@ var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
|
|
|
3484
3608
|
var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
3485
3609
|
|
|
3486
3610
|
class InvalidRuntimeOverrideError extends Error {
|
|
3487
|
-
code = "invalid_runtime_override";
|
|
3488
|
-
reason;
|
|
3489
3611
|
constructor(reason, message) {
|
|
3490
3612
|
super(message);
|
|
3613
|
+
this.code = "invalid_runtime_override";
|
|
3491
3614
|
this.name = "InvalidRuntimeOverrideError";
|
|
3492
3615
|
this.reason = reason;
|
|
3493
3616
|
}
|
|
3494
3617
|
}
|
|
3495
3618
|
|
|
3496
3619
|
class InvalidDaemonVersionError extends Error {
|
|
3497
|
-
code = "invalid_daemon_version";
|
|
3498
|
-
version;
|
|
3499
3620
|
constructor(version) {
|
|
3500
3621
|
super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
|
|
3622
|
+
this.code = "invalid_daemon_version";
|
|
3501
3623
|
this.name = "InvalidDaemonVersionError";
|
|
3502
3624
|
this.version = version;
|
|
3503
3625
|
}
|
|
@@ -3543,10 +3665,9 @@ var requireFromHere = createRequire(import.meta.url);
|
|
|
3543
3665
|
var MAX_SOCKET_PATH_LENGTH = 100;
|
|
3544
3666
|
|
|
3545
3667
|
class InvalidDaemonDirectoryError extends Error {
|
|
3546
|
-
code = "invalid_daemon_directory";
|
|
3547
|
-
directory;
|
|
3548
3668
|
constructor(directory) {
|
|
3549
3669
|
super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
|
|
3670
|
+
this.code = "invalid_daemon_directory";
|
|
3550
3671
|
this.name = "InvalidDaemonDirectoryError";
|
|
3551
3672
|
this.directory = directory;
|
|
3552
3673
|
}
|
|
@@ -3741,7 +3862,8 @@ function spawnDaemonProcess(paths) {
|
|
|
3741
3862
|
try {
|
|
3742
3863
|
const child = spawn2(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
|
|
3743
3864
|
detached: true,
|
|
3744
|
-
stdio: ["ignore", logFd, logFd]
|
|
3865
|
+
stdio: ["ignore", logFd, logFd],
|
|
3866
|
+
windowsHide: true
|
|
3745
3867
|
});
|
|
3746
3868
|
child.once("spawn", () => closeSync2(logFd));
|
|
3747
3869
|
child.once("error", (error) => {
|
|
@@ -4022,6 +4144,7 @@ async function runJsonRpcStdioServer(config) {
|
|
|
4022
4144
|
const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
|
|
4023
4145
|
isClosed = true;
|
|
4024
4146
|
config.onIdleTimeout?.();
|
|
4147
|
+
config.input.destroy();
|
|
4025
4148
|
});
|
|
4026
4149
|
const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
|
|
4027
4150
|
isClosed = true;
|
|
@@ -4118,7 +4241,11 @@ function createParentWatchdog(config, onDeadParent) {
|
|
|
4118
4241
|
const probeAlive = config.probeAlive ?? isProcessAlive;
|
|
4119
4242
|
let fired = false;
|
|
4120
4243
|
const timer = setInterval(() => {
|
|
4121
|
-
if (fired
|
|
4244
|
+
if (fired)
|
|
4245
|
+
return;
|
|
4246
|
+
const alive = probeAlive(parentPid);
|
|
4247
|
+
config.onPoll?.(alive);
|
|
4248
|
+
if (alive)
|
|
4122
4249
|
return;
|
|
4123
4250
|
fired = true;
|
|
4124
4251
|
onDeadParent(parentPid, pollIntervalMs);
|
|
@@ -4153,60 +4280,55 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
|
|
|
4153
4280
|
};
|
|
4154
4281
|
}
|
|
4155
4282
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
4156
|
-
import { existsSync as
|
|
4157
|
-
import { dirname as
|
|
4283
|
+
import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
|
|
4284
|
+
import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
|
|
4158
4285
|
|
|
4159
|
-
// ../lsp-core/src/lsp/
|
|
4160
|
-
import { existsSync as existsSync7,
|
|
4161
|
-
import { dirname as dirname7 } from "node:path";
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4286
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
4287
|
+
import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
|
|
4288
|
+
import { dirname as dirname7, join as join3 } from "node:path";
|
|
4289
|
+
|
|
4290
|
+
// ../lsp-core/src/lsp/workspace-markers.ts
|
|
4291
|
+
var GIT_WORKSPACE_MARKER = ".git";
|
|
4292
|
+
var PROJECT_WORKSPACE_MARKERS = [
|
|
4293
|
+
"package.json",
|
|
4294
|
+
"pyproject.toml",
|
|
4295
|
+
"Cargo.toml",
|
|
4296
|
+
"go.mod",
|
|
4297
|
+
"pom.xml",
|
|
4298
|
+
"build.gradle"
|
|
4299
|
+
];
|
|
4300
|
+
var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
|
|
4301
|
+
|
|
4302
|
+
// ../lsp-core/src/lsp/outside-context-workspace.ts
|
|
4303
|
+
function findWorkspaceRootOutsideContext(directory) {
|
|
4304
|
+
const marked = nearestMarkedAncestor(directory);
|
|
4305
|
+
if (marked !== undefined)
|
|
4306
|
+
return marked;
|
|
4307
|
+
return realpathSync4(nearestExistingAncestor(directory));
|
|
4308
|
+
}
|
|
4309
|
+
function nearestMarkedAncestor(directory) {
|
|
4310
|
+
let current = directory;
|
|
4311
|
+
for (;; ) {
|
|
4312
|
+
if (existsSync7(current) && WORKSPACE_MARKERS.some((marker) => existsSync7(join3(current, marker)))) {
|
|
4313
|
+
return realpathSync4(current);
|
|
4314
|
+
}
|
|
4315
|
+
const parent = dirname7(current);
|
|
4316
|
+
if (parent === current)
|
|
4317
|
+
return;
|
|
4318
|
+
current = parent;
|
|
4174
4319
|
}
|
|
4175
4320
|
}
|
|
4176
|
-
function
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
}
|
|
4184
|
-
|
|
4185
|
-
return value === "declined" || value === "allowed";
|
|
4186
|
-
}
|
|
4187
|
-
function writeInstallDecisions(decisions) {
|
|
4188
|
-
const path2 = getInstallDecisionsPath();
|
|
4189
|
-
mkdirSync3(dirname7(path2), { recursive: true });
|
|
4190
|
-
const tmpPath = `${path2}.tmp`;
|
|
4191
|
-
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
4192
|
-
`, "utf8");
|
|
4193
|
-
renameSync2(tmpPath, path2);
|
|
4194
|
-
}
|
|
4195
|
-
function isInstallDecisions(value) {
|
|
4196
|
-
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
4197
|
-
}
|
|
4198
|
-
function isInstallDecisionRecord(value) {
|
|
4199
|
-
if (!isRecord5(value))
|
|
4200
|
-
return false;
|
|
4201
|
-
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
4202
|
-
}
|
|
4203
|
-
function isRecord5(value) {
|
|
4204
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4321
|
+
function nearestExistingAncestor(directory) {
|
|
4322
|
+
let current = directory;
|
|
4323
|
+
while (!existsSync7(current)) {
|
|
4324
|
+
const parent = dirname7(current);
|
|
4325
|
+
if (parent === current)
|
|
4326
|
+
return current;
|
|
4327
|
+
current = parent;
|
|
4328
|
+
}
|
|
4329
|
+
return current;
|
|
4205
4330
|
}
|
|
4206
4331
|
|
|
4207
|
-
// ../lsp-core/src/lsp/config-loader.ts
|
|
4208
|
-
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
|
|
4209
|
-
|
|
4210
4332
|
// ../lsp-core/src/lsp/server-definitions.ts
|
|
4211
4333
|
var LSP_INSTALL_HINTS = {
|
|
4212
4334
|
typescript: "npm install -g typescript-language-server typescript",
|
|
@@ -4252,6 +4374,26 @@ var LSP_INSTALL_HINTS = {
|
|
|
4252
4374
|
julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
|
|
4253
4375
|
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"
|
|
4254
4376
|
};
|
|
4377
|
+
var LSP_LOCAL_INSTALL_HINTS = {
|
|
4378
|
+
typescript: "bun add -d typescript-language-server typescript",
|
|
4379
|
+
vue: "bun add -d @vue/language-server",
|
|
4380
|
+
eslint: "bun add -d vscode-langservers-extracted",
|
|
4381
|
+
oxlint: "bun add -d oxlint",
|
|
4382
|
+
biome: "bun add -d @biomejs/biome",
|
|
4383
|
+
svelte: "bun add -d svelte-language-server",
|
|
4384
|
+
astro: "bun add -d @astrojs/language-server",
|
|
4385
|
+
bash: "bun add -d bash-language-server",
|
|
4386
|
+
"bash-ls": "bun add -d bash-language-server",
|
|
4387
|
+
"yaml-ls": "bun add -d yaml-language-server",
|
|
4388
|
+
php: "bun add -d intelephense",
|
|
4389
|
+
prisma: "bun add -d prisma",
|
|
4390
|
+
dockerfile: "bun add -d dockerfile-language-server-nodejs",
|
|
4391
|
+
pyright: "uv add --dev pyright",
|
|
4392
|
+
basedpyright: "uv add --dev basedpyright",
|
|
4393
|
+
ruff: "uv add --dev ruff",
|
|
4394
|
+
ty: "uv add --dev ty",
|
|
4395
|
+
"ruby-lsp": "bundle add ruby-lsp --group development"
|
|
4396
|
+
};
|
|
4255
4397
|
var BUILTIN_SERVERS = {
|
|
4256
4398
|
typescript: {
|
|
4257
4399
|
command: ["typescript-language-server", "--stdio"],
|
|
@@ -4354,7 +4496,56 @@ var BUILTIN_SERVERS = {
|
|
|
4354
4496
|
}
|
|
4355
4497
|
};
|
|
4356
4498
|
|
|
4499
|
+
// ../lsp-core/src/lsp/server-install-state.ts
|
|
4500
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
4501
|
+
import { dirname as dirname8 } from "node:path";
|
|
4502
|
+
function getInstallDecisionsPath() {
|
|
4503
|
+
return lspRequestContext().installDecisionsPath;
|
|
4504
|
+
}
|
|
4505
|
+
function loadInstallDecisions() {
|
|
4506
|
+
const path2 = getInstallDecisionsPath();
|
|
4507
|
+
if (!existsSync8(path2))
|
|
4508
|
+
return {};
|
|
4509
|
+
try {
|
|
4510
|
+
const parsed = JSON.parse(readFileSync4(path2, "utf8"));
|
|
4511
|
+
return isInstallDecisions(parsed) ? parsed : {};
|
|
4512
|
+
} catch {
|
|
4513
|
+
return {};
|
|
4514
|
+
}
|
|
4515
|
+
}
|
|
4516
|
+
function loadInstallDecision(serverId) {
|
|
4517
|
+
return loadInstallDecisions()[serverId];
|
|
4518
|
+
}
|
|
4519
|
+
function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
|
|
4520
|
+
const decisions = loadInstallDecisions();
|
|
4521
|
+
decisions[serverId] = { decision, decidedAt };
|
|
4522
|
+
writeInstallDecisions(decisions);
|
|
4523
|
+
}
|
|
4524
|
+
function isInstallDecision(value) {
|
|
4525
|
+
return value === "declined" || value === "allowed";
|
|
4526
|
+
}
|
|
4527
|
+
function writeInstallDecisions(decisions) {
|
|
4528
|
+
const path2 = getInstallDecisionsPath();
|
|
4529
|
+
mkdirSync3(dirname8(path2), { recursive: true });
|
|
4530
|
+
const tmpPath = `${path2}.tmp`;
|
|
4531
|
+
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
4532
|
+
`, "utf8");
|
|
4533
|
+
renameSync2(tmpPath, path2);
|
|
4534
|
+
}
|
|
4535
|
+
function isInstallDecisions(value) {
|
|
4536
|
+
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
4537
|
+
}
|
|
4538
|
+
function isInstallDecisionRecord(value) {
|
|
4539
|
+
if (!isRecord5(value))
|
|
4540
|
+
return false;
|
|
4541
|
+
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
4542
|
+
}
|
|
4543
|
+
function isRecord5(value) {
|
|
4544
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4545
|
+
}
|
|
4546
|
+
|
|
4357
4547
|
// ../lsp-core/src/lsp/config-loader.ts
|
|
4548
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
|
|
4358
4549
|
function getProjectConfigPaths() {
|
|
4359
4550
|
return lspRequestContext().projectConfigPaths;
|
|
4360
4551
|
}
|
|
@@ -4362,7 +4553,7 @@ function getUserConfigPath() {
|
|
|
4362
4553
|
return lspRequestContext().userConfigPath;
|
|
4363
4554
|
}
|
|
4364
4555
|
function loadJsonFile(path2) {
|
|
4365
|
-
if (!
|
|
4556
|
+
if (!existsSync9(path2))
|
|
4366
4557
|
return null;
|
|
4367
4558
|
try {
|
|
4368
4559
|
const parsed = JSON.parse(readFileSync5(path2, "utf-8"));
|
|
@@ -4550,54 +4741,155 @@ function getDisabledServerIds() {
|
|
|
4550
4741
|
}
|
|
4551
4742
|
|
|
4552
4743
|
// ../lsp-core/src/lsp/server-installation.ts
|
|
4553
|
-
import { existsSync as
|
|
4554
|
-
import { delimiter as delimiter3, join as
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4744
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
4745
|
+
import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
|
|
4746
|
+
var LOCAL_BIN_RULES = [
|
|
4747
|
+
{
|
|
4748
|
+
markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
|
|
4749
|
+
binDirs: [join4("node_modules", ".bin")]
|
|
4750
|
+
},
|
|
4751
|
+
{
|
|
4752
|
+
markers: [
|
|
4753
|
+
"pyproject.toml",
|
|
4754
|
+
"ty.toml",
|
|
4755
|
+
"requirements.txt",
|
|
4756
|
+
"setup.py",
|
|
4757
|
+
"setup.cfg",
|
|
4758
|
+
"Pipfile",
|
|
4759
|
+
"pyrightconfig.json",
|
|
4760
|
+
"ruff.toml",
|
|
4761
|
+
".ruff.toml"
|
|
4762
|
+
],
|
|
4763
|
+
binDirs: [
|
|
4764
|
+
join4(".venv", "bin"),
|
|
4765
|
+
join4(".venv", "Scripts"),
|
|
4766
|
+
join4("venv", "bin"),
|
|
4767
|
+
join4("venv", "Scripts"),
|
|
4768
|
+
join4(".env", "bin"),
|
|
4769
|
+
join4(".env", "Scripts")
|
|
4770
|
+
]
|
|
4771
|
+
},
|
|
4772
|
+
{
|
|
4773
|
+
markers: ["Gemfile", "Gemfile.lock"],
|
|
4774
|
+
binDirs: [join4("vendor", "bundle", "bin"), "bin"]
|
|
4775
|
+
},
|
|
4776
|
+
{
|
|
4777
|
+
markers: ["go.mod", "go.sum", "go.work"],
|
|
4778
|
+
binDirs: ["bin"]
|
|
4779
|
+
}
|
|
4780
|
+
];
|
|
4781
|
+
var resolutionCache = new Map;
|
|
4782
|
+
var probeCount = 0;
|
|
4783
|
+
function probe(path2) {
|
|
4784
|
+
probeCount += 1;
|
|
4785
|
+
return existsSync10(path2);
|
|
4786
|
+
}
|
|
4787
|
+
function executableSuffixes(platform, pathExt) {
|
|
4788
|
+
if (platform !== "win32")
|
|
4789
|
+
return [""];
|
|
4790
|
+
const configured = pathExt ?? process.env["PATHEXT"] ?? "";
|
|
4791
|
+
const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
|
|
4792
|
+
return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
|
|
4793
|
+
}
|
|
4794
|
+
function probeWithSuffixes(directory, command, suffixes) {
|
|
4795
|
+
for (const suffix of suffixes) {
|
|
4796
|
+
const candidate = join4(directory, command + suffix);
|
|
4797
|
+
if (probe(candidate))
|
|
4798
|
+
return candidate;
|
|
4564
4799
|
}
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4800
|
+
return null;
|
|
4801
|
+
}
|
|
4802
|
+
function resolveLocal(command, workingDirectory, suffixes, stopAt) {
|
|
4803
|
+
const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
|
|
4804
|
+
let current = resolve7(workingDirectory);
|
|
4805
|
+
while (true) {
|
|
4806
|
+
for (const rule of LOCAL_BIN_RULES) {
|
|
4807
|
+
if (!rule.markers.some((marker) => probe(join4(current, marker))))
|
|
4808
|
+
continue;
|
|
4809
|
+
for (const binDir of rule.binDirs) {
|
|
4810
|
+
const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
|
|
4811
|
+
if (found !== null)
|
|
4812
|
+
return found;
|
|
4813
|
+
}
|
|
4574
4814
|
}
|
|
4815
|
+
if (probe(join4(current, ".git")))
|
|
4816
|
+
return null;
|
|
4817
|
+
if (boundary !== undefined && current === boundary)
|
|
4818
|
+
return null;
|
|
4819
|
+
const parent = dirname9(current);
|
|
4820
|
+
if (parent === current)
|
|
4821
|
+
return null;
|
|
4822
|
+
current = parent;
|
|
4575
4823
|
}
|
|
4576
|
-
|
|
4577
|
-
|
|
4824
|
+
}
|
|
4825
|
+
function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
|
|
4826
|
+
let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
|
|
4827
|
+
if (platform === "win32" && !pathEnv) {
|
|
4578
4828
|
pathEnv = process.env["Path"] ?? "";
|
|
4579
4829
|
}
|
|
4580
|
-
const
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
}
|
|
4830
|
+
for (const entry of pathEnv.split(delimiter3)) {
|
|
4831
|
+
if (entry.length === 0)
|
|
4832
|
+
continue;
|
|
4833
|
+
const found = probeWithSuffixes(entry, command, suffixes);
|
|
4834
|
+
if (found !== null)
|
|
4835
|
+
return found;
|
|
4587
4836
|
}
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4837
|
+
return null;
|
|
4838
|
+
}
|
|
4839
|
+
function resolveServerBinary(command, workingDirectory, options = {}) {
|
|
4840
|
+
if (command.length === 0)
|
|
4841
|
+
return null;
|
|
4842
|
+
const [cmd] = command;
|
|
4843
|
+
if (cmd === undefined || cmd.length === 0)
|
|
4844
|
+
return null;
|
|
4845
|
+
const platform = options.platform ?? process.platform;
|
|
4846
|
+
const suffixes = executableSuffixes(platform, options.pathExt);
|
|
4847
|
+
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
4848
|
+
const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
|
|
4849
|
+
return probe(explicit) ? explicit : null;
|
|
4850
|
+
}
|
|
4851
|
+
const cacheKey = JSON.stringify([
|
|
4852
|
+
workingDirectory ?? "",
|
|
4853
|
+
cmd,
|
|
4854
|
+
platform,
|
|
4855
|
+
options.stopAt ?? "",
|
|
4856
|
+
options.pathExt ?? "",
|
|
4857
|
+
options.pathEnv ?? process.env["PATH"] ?? ""
|
|
4858
|
+
]);
|
|
4859
|
+
const cached = resolutionCache.get(cacheKey);
|
|
4860
|
+
if (cached !== undefined)
|
|
4861
|
+
return cached;
|
|
4862
|
+
let resolved = null;
|
|
4863
|
+
if (workingDirectory !== undefined && workingDirectory.length > 0) {
|
|
4864
|
+
resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
|
|
4865
|
+
}
|
|
4866
|
+
resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
|
|
4867
|
+
if (resolved === null && cmd === "node")
|
|
4868
|
+
resolved = cmd;
|
|
4869
|
+
resolutionCache.set(cacheKey, resolved);
|
|
4870
|
+
return resolved;
|
|
4871
|
+
}
|
|
4872
|
+
function isServerInstalled(command, workingDirectory, options = {}) {
|
|
4873
|
+
if (command.length === 0)
|
|
4874
|
+
return false;
|
|
4875
|
+
return resolveServerBinary(command, workingDirectory, options) !== null;
|
|
4591
4876
|
}
|
|
4592
4877
|
|
|
4593
4878
|
// ../lsp-core/src/lsp/server-resolution.ts
|
|
4879
|
+
function withResolvedCommand(command, binaryPath) {
|
|
4880
|
+
return [binaryPath, ...command.slice(1)];
|
|
4881
|
+
}
|
|
4594
4882
|
function findServerForExtension(ext) {
|
|
4595
4883
|
const servers = getMergedServers();
|
|
4884
|
+
const workingDirectory = contextCwd();
|
|
4596
4885
|
for (const server2 of servers) {
|
|
4597
|
-
if (server2.extensions.includes(ext)
|
|
4886
|
+
if (!server2.extensions.includes(ext))
|
|
4887
|
+
continue;
|
|
4888
|
+
const binaryPath = resolveServerBinary(server2.command, workingDirectory);
|
|
4889
|
+
if (binaryPath !== null) {
|
|
4598
4890
|
const resolvedServer = {
|
|
4599
4891
|
id: server2.id,
|
|
4600
|
-
command: server2.command,
|
|
4892
|
+
command: withResolvedCommand(server2.command, binaryPath),
|
|
4601
4893
|
extensions: server2.extensions,
|
|
4602
4894
|
priority: server2.priority
|
|
4603
4895
|
};
|
|
@@ -4644,6 +4936,7 @@ function findServerForExtension(ext) {
|
|
|
4644
4936
|
function getAllServers() {
|
|
4645
4937
|
const servers = getMergedServers();
|
|
4646
4938
|
const disabled = getDisabledServerIds();
|
|
4939
|
+
const workingDirectory = contextCwd();
|
|
4647
4940
|
const result = [];
|
|
4648
4941
|
const seen = new Set;
|
|
4649
4942
|
for (const server2 of servers) {
|
|
@@ -4651,7 +4944,7 @@ function getAllServers() {
|
|
|
4651
4944
|
continue;
|
|
4652
4945
|
result.push({
|
|
4653
4946
|
id: server2.id,
|
|
4654
|
-
installed: isServerInstalled(server2.command),
|
|
4947
|
+
installed: isServerInstalled(server2.command, workingDirectory),
|
|
4655
4948
|
extensions: server2.extensions,
|
|
4656
4949
|
disabled: false,
|
|
4657
4950
|
source: server2.source,
|
|
@@ -4665,7 +4958,7 @@ function getAllServers() {
|
|
|
4665
4958
|
const builtin = BUILTIN_SERVERS[id];
|
|
4666
4959
|
result.push({
|
|
4667
4960
|
id,
|
|
4668
|
-
installed: builtin ? isServerInstalled(builtin.command) : false,
|
|
4961
|
+
installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
|
|
4669
4962
|
extensions: builtin?.extensions ?? [],
|
|
4670
4963
|
disabled: true,
|
|
4671
4964
|
source: "disabled",
|
|
@@ -4676,7 +4969,6 @@ function getAllServers() {
|
|
|
4676
4969
|
}
|
|
4677
4970
|
|
|
4678
4971
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
4679
|
-
var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
4680
4972
|
function isDirectoryPath(filePath) {
|
|
4681
4973
|
try {
|
|
4682
4974
|
return statSync4(filePath).isDirectory();
|
|
@@ -4685,32 +4977,90 @@ function isDirectoryPath(filePath) {
|
|
|
4685
4977
|
}
|
|
4686
4978
|
}
|
|
4687
4979
|
function findWorkspaceRoot(filePath) {
|
|
4688
|
-
const
|
|
4980
|
+
const cwd = contextCwd();
|
|
4981
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4689
4982
|
let dir = abs;
|
|
4690
4983
|
if (!isDirectoryPath(dir)) {
|
|
4691
|
-
dir =
|
|
4692
|
-
}
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4984
|
+
dir = dirname10(dir);
|
|
4985
|
+
}
|
|
4986
|
+
if (!isPathInside(cwd, abs))
|
|
4987
|
+
return findWorkspaceRootOutsideContext(dir);
|
|
4988
|
+
const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
|
|
4989
|
+
let nearestPackageRoot;
|
|
4990
|
+
while (isPathInside(cwd, dir)) {
|
|
4991
|
+
const canonicalDir = existingDirectoryInsideContext(dir, cwd);
|
|
4992
|
+
if (canonicalDir !== undefined) {
|
|
4993
|
+
if (existsSync11(join5(dir, GIT_WORKSPACE_MARKER))) {
|
|
4994
|
+
return canonicalDir;
|
|
4995
|
+
}
|
|
4996
|
+
if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
|
|
4997
|
+
nearestPackageRoot = canonicalDir;
|
|
4698
4998
|
}
|
|
4699
4999
|
}
|
|
4700
|
-
|
|
4701
|
-
|
|
5000
|
+
if (dir === cwd)
|
|
5001
|
+
break;
|
|
5002
|
+
dir = dirname10(dir);
|
|
4702
5003
|
}
|
|
4703
|
-
return
|
|
5004
|
+
return nearestPackageRoot ?? fallbackRoot;
|
|
5005
|
+
}
|
|
5006
|
+
function hasProjectWorkspaceMarker(directory) {
|
|
5007
|
+
return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync11(join5(directory, marker)));
|
|
5008
|
+
}
|
|
5009
|
+
function resolveReadablePathInsideContext(filePath) {
|
|
5010
|
+
const cwd = contextCwd();
|
|
5011
|
+
const abs = resolve8(cwd, filePath);
|
|
5012
|
+
if (isPathInside(cwd, abs))
|
|
5013
|
+
return abs;
|
|
5014
|
+
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
5015
|
+
if (rebased !== undefined)
|
|
5016
|
+
return rebased;
|
|
5017
|
+
return canonicalizeExistingOrNearestAncestor(abs);
|
|
4704
5018
|
}
|
|
4705
5019
|
function resolvePathInsideContext(filePath) {
|
|
4706
5020
|
const cwd = contextCwd();
|
|
4707
|
-
const abs =
|
|
5021
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
4708
5022
|
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
4709
5023
|
if (!isPathInside(cwd, canonical)) {
|
|
4710
5024
|
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
4711
5025
|
}
|
|
4712
5026
|
return canonical;
|
|
4713
5027
|
}
|
|
5028
|
+
function rebaseThroughCanonicalAncestor(path2, cwd) {
|
|
5029
|
+
let current = path2;
|
|
5030
|
+
const suffix = [];
|
|
5031
|
+
while (true) {
|
|
5032
|
+
if (existsSync11(current)) {
|
|
5033
|
+
const canonical = realpathSync5(current);
|
|
5034
|
+
if (isPathInside(cwd, canonical))
|
|
5035
|
+
return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
|
|
5036
|
+
}
|
|
5037
|
+
const parent = dirname10(current);
|
|
5038
|
+
if (parent === current)
|
|
5039
|
+
return;
|
|
5040
|
+
suffix.unshift(basename3(current));
|
|
5041
|
+
current = parent;
|
|
5042
|
+
}
|
|
5043
|
+
}
|
|
5044
|
+
function existingDirectoryInsideContext(directory, cwd) {
|
|
5045
|
+
if (!existsSync11(directory))
|
|
5046
|
+
return;
|
|
5047
|
+
const canonical = realpathSync5(directory);
|
|
5048
|
+
if (!statSync4(canonical).isDirectory())
|
|
5049
|
+
return;
|
|
5050
|
+
return isPathInside(cwd, canonical) ? canonical : undefined;
|
|
5051
|
+
}
|
|
5052
|
+
function nearestExistingDirectoryInsideContext(directory, cwd) {
|
|
5053
|
+
let current = directory;
|
|
5054
|
+
while (isPathInside(cwd, current)) {
|
|
5055
|
+
const canonical = existingDirectoryInsideContext(current, cwd);
|
|
5056
|
+
if (canonical !== undefined)
|
|
5057
|
+
return canonical;
|
|
5058
|
+
if (current === cwd)
|
|
5059
|
+
return;
|
|
5060
|
+
current = dirname10(current);
|
|
5061
|
+
}
|
|
5062
|
+
return;
|
|
5063
|
+
}
|
|
4714
5064
|
function formatServerLookupError(result) {
|
|
4715
5065
|
if (result.status === "not_installed") {
|
|
4716
5066
|
return formatNotInstalled(result);
|
|
@@ -4734,6 +5084,19 @@ function formatServerLookupError(result) {
|
|
|
4734
5084
|
].join(`
|
|
4735
5085
|
`);
|
|
4736
5086
|
}
|
|
5087
|
+
function formatInstallOptions(serverId, installHint) {
|
|
5088
|
+
const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
|
|
5089
|
+
if (localHint === undefined) {
|
|
5090
|
+
return ["To install, run:", ` ${installHint}`];
|
|
5091
|
+
}
|
|
5092
|
+
return [
|
|
5093
|
+
"To install in THIS repository (preferred — no global install needed):",
|
|
5094
|
+
` ${localHint}`,
|
|
5095
|
+
"",
|
|
5096
|
+
"Or install it globally:",
|
|
5097
|
+
` ${installHint}`
|
|
5098
|
+
];
|
|
5099
|
+
}
|
|
4737
5100
|
function formatNotInstalled(result) {
|
|
4738
5101
|
const { server: server2, installHint } = result;
|
|
4739
5102
|
const extensions = server2.extensions.join(", ");
|
|
@@ -4748,19 +5111,19 @@ function formatNotInstalled(result) {
|
|
|
4748
5111
|
`Command not found: ${server2.command[0]}`,
|
|
4749
5112
|
""
|
|
4750
5113
|
];
|
|
5114
|
+
const installOptions = formatInstallOptions(server2.id, installHint);
|
|
4751
5115
|
if (decision === "allowed") {
|
|
4752
5116
|
return [
|
|
4753
5117
|
...header,
|
|
4754
5118
|
"The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
|
|
4755
|
-
|
|
5119
|
+
...installOptions.slice(1)
|
|
4756
5120
|
].join(`
|
|
4757
5121
|
`);
|
|
4758
5122
|
}
|
|
4759
5123
|
if (!context.capabilities.installDecisionTool) {
|
|
4760
5124
|
return [
|
|
4761
5125
|
...header,
|
|
4762
|
-
|
|
4763
|
-
` ${installHint}`,
|
|
5126
|
+
...installOptions,
|
|
4764
5127
|
"",
|
|
4765
5128
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4766
5129
|
"Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
|
|
@@ -4769,8 +5132,7 @@ function formatNotInstalled(result) {
|
|
|
4769
5132
|
}
|
|
4770
5133
|
return [
|
|
4771
5134
|
...header,
|
|
4772
|
-
|
|
4773
|
-
` ${installHint}`,
|
|
5135
|
+
...installOptions,
|
|
4774
5136
|
"",
|
|
4775
5137
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4776
5138
|
"- If the user agrees: run the install command above, then retry this tool.",
|
|
@@ -4781,7 +5143,7 @@ function formatNotInstalled(result) {
|
|
|
4781
5143
|
].join(`
|
|
4782
5144
|
`);
|
|
4783
5145
|
}
|
|
4784
|
-
var
|
|
5146
|
+
var READ_ONLY_TOOLS = new Set([
|
|
4785
5147
|
"diagnostics",
|
|
4786
5148
|
"definition",
|
|
4787
5149
|
"references",
|
|
@@ -4790,7 +5152,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
|
|
|
4790
5152
|
"prepareRename"
|
|
4791
5153
|
]);
|
|
4792
5154
|
async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
4793
|
-
const absPath = resolvePathInsideContext(filePath);
|
|
5155
|
+
const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
|
|
4794
5156
|
if (isDirectoryPath(absPath)) {
|
|
4795
5157
|
throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
|
|
4796
5158
|
}
|
|
@@ -4805,9 +5167,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4805
5167
|
const acquireAndCall = async (allowRetry) => {
|
|
4806
5168
|
const client = await manager.getClient(root, server2, options.signal);
|
|
4807
5169
|
try {
|
|
4808
|
-
return await fn(client, root);
|
|
5170
|
+
return await fn(client, root, absPath);
|
|
4809
5171
|
} catch (err) {
|
|
4810
|
-
if (allowRetry &&
|
|
5172
|
+
if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
|
|
4811
5173
|
manager.invalidateClient(root, server2.id, client);
|
|
4812
5174
|
return acquireAndCall(false);
|
|
4813
5175
|
}
|
|
@@ -4825,8 +5187,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4825
5187
|
}
|
|
4826
5188
|
|
|
4827
5189
|
// ../lsp-core/src/lsp/directory-diagnostics.ts
|
|
4828
|
-
import { existsSync as
|
|
4829
|
-
import { join as
|
|
5190
|
+
import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
|
|
5191
|
+
import { join as join6, resolve as resolve9 } from "node:path";
|
|
4830
5192
|
|
|
4831
5193
|
// ../lsp-core/src/lsp/formatters.ts
|
|
4832
5194
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
@@ -4956,7 +5318,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
|
|
|
4956
5318
|
for (const entry of entries) {
|
|
4957
5319
|
if (files.length >= maxFiles)
|
|
4958
5320
|
return;
|
|
4959
|
-
const fullPath =
|
|
5321
|
+
const fullPath = join6(currentDir, entry);
|
|
4960
5322
|
let stat;
|
|
4961
5323
|
try {
|
|
4962
5324
|
stat = lstatSync5(fullPath);
|
|
@@ -4981,8 +5343,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4981
5343
|
if (!extension.startsWith(".")) {
|
|
4982
5344
|
throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
|
|
4983
5345
|
}
|
|
4984
|
-
const absDir =
|
|
4985
|
-
if (!
|
|
5346
|
+
const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
|
|
5347
|
+
if (!existsSync12(absDir)) {
|
|
4986
5348
|
throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
|
|
4987
5349
|
}
|
|
4988
5350
|
const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
|
|
@@ -5069,7 +5431,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
5069
5431
|
|
|
5070
5432
|
// ../lsp-core/src/lsp/infer-extension.ts
|
|
5071
5433
|
import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
|
|
5072
|
-
import { join as
|
|
5434
|
+
import { join as join7 } from "node:path";
|
|
5073
5435
|
var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
|
|
5074
5436
|
var MAX_SCAN_ENTRIES = 500;
|
|
5075
5437
|
function inferExtensionFromDirectory(directory) {
|
|
@@ -5087,7 +5449,7 @@ function inferExtensionFromDirectory(directory) {
|
|
|
5087
5449
|
for (const entry of entries) {
|
|
5088
5450
|
if (scanned >= MAX_SCAN_ENTRIES)
|
|
5089
5451
|
return;
|
|
5090
|
-
const fullPath =
|
|
5452
|
+
const fullPath = join7(dir, entry);
|
|
5091
5453
|
let stat;
|
|
5092
5454
|
try {
|
|
5093
5455
|
stat = lstatSync6(fullPath);
|
|
@@ -5262,7 +5624,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5262
5624
|
const filePath = requireString(params, "filePath");
|
|
5263
5625
|
const severity = severityFilter(params);
|
|
5264
5626
|
try {
|
|
5265
|
-
const absPath =
|
|
5627
|
+
const absPath = resolveReadablePathInsideContext(filePath);
|
|
5266
5628
|
if (isDirectoryPath(absPath)) {
|
|
5267
5629
|
const extension = inferExtensionFromDirectory(absPath);
|
|
5268
5630
|
if (!extension) {
|
|
@@ -5291,7 +5653,7 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5291
5653
|
};
|
|
5292
5654
|
return text(output2.output, details2);
|
|
5293
5655
|
}
|
|
5294
|
-
const result = await withLspClient(filePath, async (client) => client.diagnostics(
|
|
5656
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
|
|
5295
5657
|
if (result.transientError) {
|
|
5296
5658
|
const message = result.transientError.message;
|
|
5297
5659
|
const details2 = {
|
|
@@ -5338,6 +5700,96 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
5338
5700
|
throw error;
|
|
5339
5701
|
}
|
|
5340
5702
|
}
|
|
5703
|
+
// ../lsp-core/src/lsp/format-document.ts
|
|
5704
|
+
import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
5705
|
+
var DEFAULT_FORMATTING_OPTIONS = {
|
|
5706
|
+
tabSize: 4,
|
|
5707
|
+
insertSpaces: false,
|
|
5708
|
+
trimTrailingWhitespace: true,
|
|
5709
|
+
insertFinalNewline: true,
|
|
5710
|
+
trimFinalNewlines: true
|
|
5711
|
+
};
|
|
5712
|
+
var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
|
|
5713
|
+
async function formatDocumentWithClient(client, filePath, options = {}) {
|
|
5714
|
+
const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
|
|
5715
|
+
if (edits === null)
|
|
5716
|
+
return { status: "unavailable", reason: "capability_not_advertised" };
|
|
5717
|
+
if (edits.length === 0)
|
|
5718
|
+
return UNCHANGED;
|
|
5719
|
+
const before = readFileSync6(filePath, "utf-8");
|
|
5720
|
+
const normalized = normalizeTextEdits(before, edits, 0);
|
|
5721
|
+
if (normalized.text === before)
|
|
5722
|
+
return UNCHANGED;
|
|
5723
|
+
writeAtomically(filePath, normalized.text);
|
|
5724
|
+
await client.openFile(filePath);
|
|
5725
|
+
return {
|
|
5726
|
+
status: "formatted",
|
|
5727
|
+
...lineDelta(normalized.edits)
|
|
5728
|
+
};
|
|
5729
|
+
}
|
|
5730
|
+
function lineDelta(edits) {
|
|
5731
|
+
let linesAdded = 0;
|
|
5732
|
+
let linesRemoved = 0;
|
|
5733
|
+
for (const edit of edits) {
|
|
5734
|
+
linesRemoved += edit.range.end.line - edit.range.start.line + 1;
|
|
5735
|
+
linesAdded += edit.newText.split(`
|
|
5736
|
+
`).length;
|
|
5737
|
+
}
|
|
5738
|
+
return { linesAdded, linesRemoved };
|
|
5739
|
+
}
|
|
5740
|
+
function writeAtomically(filePath, content) {
|
|
5741
|
+
const tempPath = `${filePath}.omo-format.tmp`;
|
|
5742
|
+
writeFileSync3(tempPath, content, "utf-8");
|
|
5743
|
+
try {
|
|
5744
|
+
renameSync3(tempPath, filePath);
|
|
5745
|
+
} catch (error) {
|
|
5746
|
+
try {
|
|
5747
|
+
unlinkSync2(tempPath);
|
|
5748
|
+
} catch {}
|
|
5749
|
+
throw error;
|
|
5750
|
+
}
|
|
5751
|
+
}
|
|
5752
|
+
|
|
5753
|
+
// ../lsp-core/src/tools/format.ts
|
|
5754
|
+
async function executeLspFormat(params, signal) {
|
|
5755
|
+
const filePath = requireString(params, "filePath");
|
|
5756
|
+
try {
|
|
5757
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
|
|
5758
|
+
return text(describeResult(filePath, result), formatDetails(filePath, result));
|
|
5759
|
+
} catch (error) {
|
|
5760
|
+
const missingDependency = missingDependencyResult(error, {
|
|
5761
|
+
filePath,
|
|
5762
|
+
status: "unavailable",
|
|
5763
|
+
reason: "server_unavailable",
|
|
5764
|
+
linesAdded: 0,
|
|
5765
|
+
linesRemoved: 0
|
|
5766
|
+
});
|
|
5767
|
+
if (missingDependency)
|
|
5768
|
+
return missingDependency;
|
|
5769
|
+
throw error;
|
|
5770
|
+
}
|
|
5771
|
+
}
|
|
5772
|
+
function formatDetails(filePath, result) {
|
|
5773
|
+
if (result.status === "unavailable") {
|
|
5774
|
+
return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
|
|
5775
|
+
}
|
|
5776
|
+
return {
|
|
5777
|
+
filePath,
|
|
5778
|
+
status: result.status,
|
|
5779
|
+
linesAdded: result.linesAdded,
|
|
5780
|
+
linesRemoved: result.linesRemoved
|
|
5781
|
+
};
|
|
5782
|
+
}
|
|
5783
|
+
function describeResult(filePath, result) {
|
|
5784
|
+
if (result.status === "unavailable") {
|
|
5785
|
+
return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
|
|
5786
|
+
}
|
|
5787
|
+
if (result.status === "unchanged") {
|
|
5788
|
+
return `Already formatted: ${filePath}`;
|
|
5789
|
+
}
|
|
5790
|
+
return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
|
|
5791
|
+
}
|
|
5792
|
+
|
|
5341
5793
|
// ../lsp-core/src/tools/install-decision.ts
|
|
5342
5794
|
async function executeLspInstallDecision(params) {
|
|
5343
5795
|
const serverId = requireString(params, "server_id");
|
|
@@ -5366,7 +5818,7 @@ async function executeLspGotoDefinition(params, signal) {
|
|
|
5366
5818
|
const line = requireNumber(params, "line");
|
|
5367
5819
|
const character = requireNumber(params, "character");
|
|
5368
5820
|
try {
|
|
5369
|
-
const result = await withLspClient(filePath, async (client) => client.definition(
|
|
5821
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
|
|
5370
5822
|
const locations = !result ? [] : Array.isArray(result) ? result : [result];
|
|
5371
5823
|
const details = { filePath, line, character, locations };
|
|
5372
5824
|
if (locations.length === 0)
|
|
@@ -5391,7 +5843,7 @@ async function executeLspFindReferences(params, signal) {
|
|
|
5391
5843
|
const character = requireNumber(params, "character");
|
|
5392
5844
|
const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
|
|
5393
5845
|
try {
|
|
5394
|
-
const result = await withLspClient(filePath, async (client) => client.references(
|
|
5846
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
|
|
5395
5847
|
const references = Array.isArray(result) ? result : [];
|
|
5396
5848
|
const total = references.length;
|
|
5397
5849
|
const truncated = total > DEFAULT_MAX_REFERENCES;
|
|
@@ -5433,7 +5885,7 @@ async function executeLspPrepareRename(params, signal) {
|
|
|
5433
5885
|
const line = requireNumber(params, "line");
|
|
5434
5886
|
const character = requireNumber(params, "character");
|
|
5435
5887
|
try {
|
|
5436
|
-
const result = await withLspClient(filePath, async (client) => client.prepareRename(
|
|
5888
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
|
|
5437
5889
|
const details = { filePath, line, character, result };
|
|
5438
5890
|
return text(formatPrepareRenameResult(result), details);
|
|
5439
5891
|
} catch (error) {
|
|
@@ -5454,7 +5906,7 @@ async function executeLspRename(params, signal) {
|
|
|
5454
5906
|
const character = requireNumber(params, "character");
|
|
5455
5907
|
const newName = requireString(params, "newName");
|
|
5456
5908
|
try {
|
|
5457
|
-
const result = await withLspClient(filePath, async (client) => client.rename(
|
|
5909
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
|
|
5458
5910
|
const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
|
|
5459
5911
|
return text(formatApplyResult(result.apply), details, !result.apply.success);
|
|
5460
5912
|
} catch (error) {
|
|
@@ -5534,7 +5986,7 @@ async function executeLspSymbols(params, signal) {
|
|
|
5534
5986
|
const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
|
|
5535
5987
|
return formatSymbolsResult(filePath, scope, symbols2, limit, query);
|
|
5536
5988
|
}
|
|
5537
|
-
const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(
|
|
5989
|
+
const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
|
|
5538
5990
|
return formatSymbolsResult(filePath, scope, symbols, limit);
|
|
5539
5991
|
} catch (error) {
|
|
5540
5992
|
const query = optionalString(params, "query");
|
|
@@ -5670,6 +6122,16 @@ var LSP_MCP_TOOLS = [
|
|
|
5670
6122
|
}, ["filePath", "line", "character", "newName"]),
|
|
5671
6123
|
execute: executeLspRename
|
|
5672
6124
|
},
|
|
6125
|
+
{
|
|
6126
|
+
name: "format",
|
|
6127
|
+
aliases: ["lsp_format"],
|
|
6128
|
+
title: "LSP Format",
|
|
6129
|
+
description: "Format a source file with its language server and write the returned edits to disk.",
|
|
6130
|
+
inputSchema: objectSchema({
|
|
6131
|
+
filePath: { type: "string", description: "Source file path to format." }
|
|
6132
|
+
}, ["filePath"]),
|
|
6133
|
+
execute: executeLspFormat
|
|
6134
|
+
},
|
|
5673
6135
|
{
|
|
5674
6136
|
name: "install_decision",
|
|
5675
6137
|
aliases: ["lsp_install_decision"],
|
|
@@ -5770,7 +6232,10 @@ function requestedProtocolVersion(params) {
|
|
|
5770
6232
|
var CONTEXT_KEY = "_context";
|
|
5771
6233
|
|
|
5772
6234
|
class InvalidDaemonRequestError extends Error {
|
|
5773
|
-
|
|
6235
|
+
constructor() {
|
|
6236
|
+
super(...arguments);
|
|
6237
|
+
this.name = "InvalidDaemonRequestError";
|
|
6238
|
+
}
|
|
5774
6239
|
}
|
|
5775
6240
|
function extractRequestContext(raw) {
|
|
5776
6241
|
if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
|
|
@@ -5886,14 +6351,17 @@ async function callToolViaDaemon(name, args, options) {
|
|
|
5886
6351
|
function callDiagnosticsViaDaemon(filePath, options) {
|
|
5887
6352
|
return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
|
|
5888
6353
|
}
|
|
6354
|
+
function callFormatViaDaemon(filePath, options) {
|
|
6355
|
+
return callToolViaDaemon("format", { filePath }, options);
|
|
6356
|
+
}
|
|
5889
6357
|
function currentRequestContext(env = process.env) {
|
|
5890
6358
|
const cwd = process.cwd();
|
|
5891
6359
|
const home = env["HOME"] ?? homedir3();
|
|
5892
6360
|
return parseLspRequestContext({
|
|
5893
6361
|
cwd,
|
|
5894
|
-
projectConfigPaths: [
|
|
5895
|
-
userConfigPath:
|
|
5896
|
-
installDecisionsPath:
|
|
6362
|
+
projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
|
|
6363
|
+
userConfigPath: join8(home, ".codex", "lsp-client.json"),
|
|
6364
|
+
installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
|
|
5897
6365
|
capabilities: { installDecisionTool: true }
|
|
5898
6366
|
});
|
|
5899
6367
|
}
|
|
@@ -5908,7 +6376,7 @@ function withContext(args, context) {
|
|
|
5908
6376
|
function ensureDaemonAvailable(paths, ensure, signal) {
|
|
5909
6377
|
if (!signal)
|
|
5910
6378
|
return ensure(paths);
|
|
5911
|
-
return new Promise((
|
|
6379
|
+
return new Promise((resolve10, reject) => {
|
|
5912
6380
|
let settled = false;
|
|
5913
6381
|
const finish = (run) => {
|
|
5914
6382
|
if (settled)
|
|
@@ -5923,11 +6391,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
|
|
|
5923
6391
|
return;
|
|
5924
6392
|
}
|
|
5925
6393
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5926
|
-
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() =>
|
|
6394
|
+
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
|
|
5927
6395
|
});
|
|
5928
6396
|
}
|
|
5929
6397
|
function sendToolCall(paths, token, name, args, options) {
|
|
5930
|
-
return new Promise((
|
|
6398
|
+
return new Promise((resolve10, reject) => {
|
|
5931
6399
|
const socket = connect(paths.socket);
|
|
5932
6400
|
const requestId = allocateProxyRequestId();
|
|
5933
6401
|
let settled = false;
|
|
@@ -5980,7 +6448,7 @@ function sendToolCall(paths, token, name, args, options) {
|
|
|
5980
6448
|
}
|
|
5981
6449
|
const result = toToolResult(message, requestId);
|
|
5982
6450
|
if (result)
|
|
5983
|
-
finish(() =>
|
|
6451
|
+
finish(() => resolve10(result));
|
|
5984
6452
|
else
|
|
5985
6453
|
finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
|
|
5986
6454
|
});
|
|
@@ -6025,8 +6493,8 @@ function isRetryableTool(name) {
|
|
|
6025
6493
|
return name !== "rename" && name !== "lsp_rename";
|
|
6026
6494
|
}
|
|
6027
6495
|
// src/proxy.ts
|
|
6028
|
-
import { existsSync as
|
|
6029
|
-
import { basename as
|
|
6496
|
+
import { existsSync as existsSync13, realpathSync as realpathSync6 } from "node:fs";
|
|
6497
|
+
import { basename as basename4, delimiter as delimiter4, dirname as dirname11, isAbsolute as isAbsolute6 } from "node:path";
|
|
6030
6498
|
var DEFAULT_STARTUP_TIMEOUT_MS = 1e4;
|
|
6031
6499
|
async function runMcpStdioProxy(options = {}) {
|
|
6032
6500
|
const input = options.input ?? process.stdin;
|
|
@@ -6149,34 +6617,34 @@ function canonicalizePathList(value) {
|
|
|
6149
6617
|
return value.split(delimiter4).map((entry) => canonicalizePath(entry) ?? entry).join(delimiter4);
|
|
6150
6618
|
}
|
|
6151
6619
|
function canonicalizePath(value) {
|
|
6152
|
-
if (value === undefined || !
|
|
6620
|
+
if (value === undefined || !isAbsolute6(value) || !existsSync13(value))
|
|
6153
6621
|
return value;
|
|
6154
|
-
return
|
|
6622
|
+
return realpathSync6(value);
|
|
6155
6623
|
}
|
|
6156
6624
|
function projectRootFromOpenCodeConfigPath(path2) {
|
|
6157
|
-
if (
|
|
6625
|
+
if (basename4(path2) !== "lsp.json" && basename4(path2) !== "lsp-client.json")
|
|
6158
6626
|
return;
|
|
6159
|
-
const configDir =
|
|
6160
|
-
const configDirName =
|
|
6627
|
+
const configDir = dirname11(path2);
|
|
6628
|
+
const configDirName = basename4(configDir);
|
|
6161
6629
|
if (configDirName !== ".opencode" && configDirName !== ".omo")
|
|
6162
6630
|
return;
|
|
6163
|
-
return
|
|
6631
|
+
return dirname11(configDir);
|
|
6164
6632
|
}
|
|
6165
6633
|
export {
|
|
6166
|
-
|
|
6167
|
-
runMcpStdioProxy,
|
|
6168
|
-
resolveDaemonRuntime,
|
|
6169
|
-
probeDaemon,
|
|
6170
|
-
ensureDaemonRunning,
|
|
6171
|
-
disposeDefaultLspManager,
|
|
6172
|
-
daemonPaths,
|
|
6173
|
-
currentRequestContext,
|
|
6174
|
-
callToolViaDaemon,
|
|
6175
|
-
callDiagnosticsViaDaemon,
|
|
6176
|
-
OMO_LSP_DAEMON_VERSION,
|
|
6177
|
-
OMO_LSP_DAEMON_DIR,
|
|
6178
|
-
OMO_LSP_DAEMON_CLI,
|
|
6179
|
-
InvalidRuntimeOverrideError,
|
|
6634
|
+
InvalidDaemonDirectoryError,
|
|
6180
6635
|
InvalidDaemonVersionError,
|
|
6181
|
-
|
|
6636
|
+
InvalidRuntimeOverrideError,
|
|
6637
|
+
OMO_LSP_DAEMON_CLI,
|
|
6638
|
+
OMO_LSP_DAEMON_DIR,
|
|
6639
|
+
OMO_LSP_DAEMON_VERSION,
|
|
6640
|
+
callDiagnosticsViaDaemon,
|
|
6641
|
+
callToolViaDaemon,
|
|
6642
|
+
currentRequestContext,
|
|
6643
|
+
daemonPaths,
|
|
6644
|
+
disposeDefaultLspManager,
|
|
6645
|
+
ensureDaemonRunning,
|
|
6646
|
+
probeDaemon,
|
|
6647
|
+
resolveDaemonRuntime,
|
|
6648
|
+
runMcpStdioProxy,
|
|
6649
|
+
validateDaemonVersion
|
|
6182
6650
|
};
|