@herbertgao/pi-extensions 2026.10.1 → 2026.10.3
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.md +14 -17
- package/THIRD_PARTY_NOTICES.md +2 -2
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-audit.md +2 -2
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-debt.md +2 -2
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-gain.md +1 -1
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-help.md +1 -1
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-review.md +2 -2
- package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail.md +1 -1
- package/node_modules/@dietrichgebert/ponytail/.qoder/rules/ponytail.md +21 -21
- package/node_modules/@dietrichgebert/ponytail/.qoder-plugin/plugin.json +1 -1
- package/node_modules/@dietrichgebert/ponytail/AGENTS.md +21 -21
- package/node_modules/@dietrichgebert/ponytail/README.md +68 -72
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-activate.js +7 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-instructions.js +30 -30
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-map.js +103 -0
- package/node_modules/@dietrichgebert/ponytail/package.json +2 -2
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail/SKILL.md +33 -101
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-audit/SKILL.md +89 -32
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-debt/SKILL.md +13 -12
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-gain/SKILL.md +17 -16
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-help/SKILL.md +9 -10
- package/node_modules/@dietrichgebert/ponytail/skills/ponytail-review/SKILL.md +96 -57
- package/node_modules/{remote-pi → @herbertgao/pi-agency}/LICENSE +1 -1
- package/node_modules/@herbertgao/pi-agency/README.md +40 -0
- package/node_modules/@herbertgao/pi-agency/package.json +53 -0
- package/node_modules/@herbertgao/pi-agency/src/index.ts +441 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +12 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +30 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +15 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +27 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/codemode.ts +4 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +2 -2
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +8 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +1 -1
- package/node_modules/@herbertgao/pi-subagents/package.json +4 -5
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +1 -1
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +1 -1
- package/node_modules/@herbertgao/pi-subagents/src/mention-clone.ts +48 -72
- package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +1 -1
- package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +15 -6
- package/node_modules/@herbertgao/pi-subagents/src/workflow/collisions.ts +4 -1
- package/node_modules/@herbertgao/pi-subagents/src/workflow/json-schema.ts +9 -8
- package/node_modules/@narumitw/pi-caffeinate/dist/index.ts +6 -1
- package/node_modules/@narumitw/pi-caffeinate/dist/index.ts.map +2 -2
- package/node_modules/@narumitw/pi-caffeinate/package.json +3 -3
- package/node_modules/@narumitw/pi-caffeinate/src/dbus-inhibit.ts +13 -1
- package/node_modules/@tifan/pi-mermaid-open/package.json +5 -1
- package/node_modules/@tifan/pi-mermaid-open/src/index.ts +26 -9
- package/node_modules/@tifan/pi-recap/package.json +1 -1
- package/node_modules/@tifan/pi-recap/src/index.ts +104 -20
- package/node_modules/@tifan/pi-recap/src/models.ts +46 -4
- package/node_modules/pi-antigravity/README.md +23 -2
- package/node_modules/pi-antigravity/package.json +5 -3
- package/node_modules/pi-antigravity/src/diagnostics/diagnostics.ts +3 -2
- package/node_modules/pi-antigravity/src/features/generate-image.ts +72 -0
- package/node_modules/pi-antigravity/src/features/google-search.ts +71 -0
- package/node_modules/pi-antigravity/src/image/image.ts +86 -47
- package/node_modules/pi-antigravity/src/image/native.ts +69 -0
- package/node_modules/pi-antigravity/src/index.ts +52 -137
- package/node_modules/pi-antigravity/src/search/search.ts +130 -31
- package/node_modules/pi-antigravity/src/stream/stream.ts +162 -113
- package/node_modules/pi-antigravity/src/types/enums.ts +1 -0
- package/node_modules/pi-antigravity/src/types/types.ts +1 -1
- package/node_modules/pi-antigravity/src/utils/security.ts +47 -1
- package/node_modules/pi-antigravity/src/utils/util.ts +38 -6
- package/node_modules/pi-lens/CHANGELOG.md +1159 -0
- package/node_modules/pi-lens/README.md +116 -25
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +6 -2
- package/node_modules/pi-lens/dist/chunk-2BEMIWEW.js +51 -0
- package/node_modules/pi-lens/dist/chunk-2EECBNC5.js +89 -0
- package/node_modules/pi-lens/dist/chunk-2FQ62SPM.js +83 -0
- package/node_modules/pi-lens/dist/chunk-2UMYMRI3.js +118 -0
- package/node_modules/pi-lens/dist/chunk-34OCDWOS.js +48 -0
- package/node_modules/pi-lens/dist/chunk-3FERWMCH.js +144 -0
- package/node_modules/pi-lens/dist/chunk-3JL6IFD7.js +97 -0
- package/node_modules/pi-lens/dist/chunk-3JSEWUWI.js +327 -0
- package/node_modules/pi-lens/dist/chunk-3MED75HT.js +37 -0
- package/node_modules/pi-lens/dist/chunk-3MRXIJ6I.js +79 -0
- package/node_modules/pi-lens/dist/chunk-3P4PF2BX.js +2250 -0
- package/node_modules/pi-lens/dist/chunk-3PNFWVHT.js +201 -0
- package/node_modules/pi-lens/dist/chunk-3TTPKMEF.js +162 -0
- package/node_modules/pi-lens/dist/chunk-5JHXUETW.js +326 -0
- package/node_modules/pi-lens/dist/chunk-5W3R6LFT.js +24 -0
- package/node_modules/pi-lens/dist/chunk-64LU2OVH.js +341 -0
- package/node_modules/pi-lens/dist/chunk-6B5I6ICN.js +44 -0
- package/node_modules/pi-lens/dist/chunk-6P54TMWL.js +274 -0
- package/node_modules/pi-lens/dist/chunk-6UYA642J.js +145 -0
- package/node_modules/pi-lens/dist/chunk-6XX5HCLK.js +398 -0
- package/node_modules/pi-lens/dist/chunk-7AXO3ZDF.js +30 -0
- package/node_modules/pi-lens/dist/chunk-7BX5DWSA.js +1907 -0
- package/node_modules/pi-lens/dist/chunk-7ELY2CSM.js +902 -0
- package/node_modules/pi-lens/dist/chunk-7M4T5N3V.js +38 -0
- package/node_modules/pi-lens/dist/chunk-7U2IDNXN.js +37 -0
- package/node_modules/pi-lens/dist/chunk-ABBOA7UD.js +157 -0
- package/node_modules/pi-lens/dist/chunk-AFZYMAIV.js +756 -0
- package/node_modules/pi-lens/dist/chunk-ALQRYH6O.js +112 -0
- package/node_modules/pi-lens/dist/chunk-AXKPQ6ZI.js +1610 -0
- package/node_modules/pi-lens/dist/chunk-BHWHXMQ2.js +62 -0
- package/node_modules/pi-lens/dist/chunk-BJF25SUG.js +22 -0
- package/node_modules/pi-lens/dist/chunk-BNKLYOOO.js +18 -0
- package/node_modules/pi-lens/dist/chunk-BW5KFIQC.js +59 -0
- package/node_modules/pi-lens/dist/chunk-CBD2B5CP.js +599 -0
- package/node_modules/pi-lens/dist/chunk-CFYISHUW.js +42 -0
- package/node_modules/pi-lens/dist/chunk-CMU4RMJB.js +30 -0
- package/node_modules/pi-lens/dist/chunk-CULQYFLU.js +14 -0
- package/node_modules/pi-lens/dist/chunk-D65GOCJB.js +289 -0
- package/node_modules/pi-lens/dist/chunk-D6YF5HKX.js +59 -0
- package/node_modules/pi-lens/dist/chunk-DMS52BEP.js +342 -0
- package/node_modules/pi-lens/dist/chunk-ELVWJYRV.js +211 -0
- package/node_modules/pi-lens/dist/chunk-EUT3B22Y.js +27 -0
- package/node_modules/pi-lens/dist/chunk-F5VLZHUW.js +146 -0
- package/node_modules/pi-lens/dist/chunk-FC4RP4I2.js +12 -0
- package/node_modules/pi-lens/dist/chunk-FGALODG3.js +55 -0
- package/node_modules/pi-lens/dist/chunk-G3RLJYA2.js +2358 -0
- package/node_modules/pi-lens/dist/chunk-GAYGGICG.js +32 -0
- package/node_modules/pi-lens/dist/chunk-H2W2AXD3.js +419 -0
- package/node_modules/pi-lens/dist/chunk-H5EV3VMF.js +114 -0
- package/node_modules/pi-lens/dist/chunk-HREZQCT3.js +106 -0
- package/node_modules/pi-lens/dist/chunk-HSIRMK2D.js +517 -0
- package/node_modules/pi-lens/dist/chunk-IMSQR4WO.js +184 -0
- package/node_modules/pi-lens/dist/chunk-IQZXOZ7S.js +4816 -0
- package/node_modules/pi-lens/dist/chunk-IR6XFA5P.js +37 -0
- package/node_modules/pi-lens/dist/chunk-IUKPRZER.js +78 -0
- package/node_modules/pi-lens/dist/chunk-IUR76K6A.js +262 -0
- package/node_modules/pi-lens/dist/chunk-J3FZR3YY.js +98 -0
- package/node_modules/pi-lens/dist/chunk-J6DFZDFA.js +562 -0
- package/node_modules/pi-lens/dist/chunk-J7WJZ6W7.js +50 -0
- package/node_modules/pi-lens/dist/chunk-JONGANYH.js +202 -0
- package/node_modules/pi-lens/dist/chunk-KJCWXUUS.js +425 -0
- package/node_modules/pi-lens/dist/chunk-KJN4IOEJ.js +17 -0
- package/node_modules/pi-lens/dist/chunk-KMGPUKFD.js +25 -0
- package/node_modules/pi-lens/dist/chunk-LD7WFTRX.js +4533 -0
- package/node_modules/pi-lens/dist/chunk-LJDODBBZ.js +78 -0
- package/node_modules/pi-lens/dist/chunk-LNOMA3MP.js +169 -0
- package/node_modules/pi-lens/dist/chunk-MGIWSROG.js +2334 -0
- package/node_modules/pi-lens/dist/chunk-MQA2YBAH.js +308 -0
- package/node_modules/pi-lens/dist/chunk-MTDRLSI7.js +21720 -0
- package/node_modules/pi-lens/dist/chunk-N2IRDBZI.js +2355 -0
- package/node_modules/pi-lens/dist/chunk-N77WFUL7.js +50 -0
- package/node_modules/pi-lens/dist/chunk-N7YNJE5R.js +466 -0
- package/node_modules/pi-lens/dist/chunk-NABLC7W3.js +148 -0
- package/node_modules/pi-lens/dist/chunk-NFXP47RV.js +999 -0
- package/node_modules/pi-lens/dist/chunk-NJF2X5XF.js +45 -0
- package/node_modules/pi-lens/dist/chunk-NXL4FFQQ.js +47 -0
- package/node_modules/pi-lens/dist/chunk-O7HZX7CA.js +309 -0
- package/node_modules/pi-lens/dist/chunk-OC7LYAU5.js +708 -0
- package/node_modules/pi-lens/dist/chunk-OEX24ECI.js +348 -0
- package/node_modules/pi-lens/dist/chunk-OYOB3ZFG.js +78 -0
- package/node_modules/pi-lens/dist/chunk-OYTMZXRF.js +41 -0
- package/node_modules/pi-lens/dist/chunk-OZJINN4O.js +84 -0
- package/node_modules/pi-lens/dist/chunk-PCHDGUKT.js +23 -0
- package/node_modules/pi-lens/dist/chunk-QOZXJ4NA.js +3364 -0
- package/node_modules/pi-lens/dist/chunk-QYF5S6P6.js +45 -0
- package/node_modules/pi-lens/dist/chunk-RJFED73B.js +79 -0
- package/node_modules/pi-lens/dist/chunk-RTQNRM5X.js +27 -0
- package/node_modules/pi-lens/dist/chunk-S6AMWKPC.js +189 -0
- package/node_modules/pi-lens/dist/chunk-T4QZ6FEH.js +308 -0
- package/node_modules/pi-lens/dist/chunk-T54VJRAD.js +5456 -0
- package/node_modules/pi-lens/dist/chunk-TA5L5KWQ.js +167 -0
- package/node_modules/pi-lens/dist/chunk-TQFBZVCG.js +27 -0
- package/node_modules/pi-lens/dist/chunk-U52SAGRM.js +62 -0
- package/node_modules/pi-lens/dist/chunk-UEAHAMEI.js +5814 -0
- package/node_modules/pi-lens/dist/chunk-UGSMCQ4D.js +327 -0
- package/node_modules/pi-lens/dist/chunk-UOPVJQ4N.js +103 -0
- package/node_modules/pi-lens/dist/chunk-USHG4DLH.js +459 -0
- package/node_modules/pi-lens/dist/chunk-UXVNL3D7.js +23 -0
- package/node_modules/pi-lens/dist/chunk-V5MEBST3.js +4139 -0
- package/node_modules/pi-lens/dist/chunk-VGEVL5EQ.js +29 -0
- package/node_modules/pi-lens/dist/chunk-VPWKF3GN.js +87 -0
- package/node_modules/pi-lens/dist/chunk-VSMJK3ZJ.js +1250 -0
- package/node_modules/pi-lens/dist/chunk-VYKKMYVT.js +560 -0
- package/node_modules/pi-lens/dist/chunk-VZHJS6DR.js +442 -0
- package/node_modules/pi-lens/dist/chunk-WATC3IQR.js +213 -0
- package/node_modules/pi-lens/dist/chunk-WPE5FPGR.js +54 -0
- package/node_modules/pi-lens/dist/chunk-WSEWKCXU.js +188 -0
- package/node_modules/pi-lens/dist/chunk-WW5BLB74.js +659 -0
- package/node_modules/pi-lens/dist/chunk-XGUL4SLQ.js +406 -0
- package/node_modules/pi-lens/dist/chunk-XHSCVSOL.js +170 -0
- package/node_modules/pi-lens/dist/chunk-XIMYZ3JA.js +27 -0
- package/node_modules/pi-lens/dist/chunk-YLN4K6WD.js +385 -0
- package/node_modules/pi-lens/dist/chunk-Z3CCVDUB.js +76 -0
- package/node_modules/pi-lens/dist/chunk-Z54ZSOBZ.js +61 -0
- package/node_modules/pi-lens/dist/chunk-Z6BB4JLQ.js +478 -0
- package/node_modules/pi-lens/dist/chunk-Z7QQA2KT.js +27 -0
- package/node_modules/pi-lens/dist/chunk-ZETYB3XG.js +2626 -0
- package/node_modules/pi-lens/dist/chunk-ZMOMPX2Z.js +87 -0
- package/node_modules/pi-lens/dist/chunk-ZOEYVXSV.js +149 -0
- package/node_modules/pi-lens/dist/chunk-ZZUFZUQZ.js +12120 -0
- package/node_modules/pi-lens/dist/index.js +39712 -29876
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +186 -232
- package/node_modules/pi-lens/dist/mcp/cli.js +137 -98
- package/node_modules/pi-lens/dist/mcp/server.js +22688 -1573
- package/node_modules/pi-lens/dist/mcp/worker.js +97 -38
- package/node_modules/pi-lens/dist/probes/installer.js +135 -0
- package/node_modules/pi-lens/dist/workers/project-snapshot-persist-worker.js +22 -0
- package/node_modules/pi-lens/dist/workers/review-graph-persist-worker.js +15 -0
- package/node_modules/pi-lens/docs/agent-guide.md +13 -4
- package/node_modules/pi-lens/docs/agent-tools.md +42 -0
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +5 -4
- package/node_modules/pi-lens/docs/configuration.md +28 -2
- package/node_modules/pi-lens/docs/custom-rules.md +25 -2
- package/node_modules/pi-lens/docs/environment-variables.md +86 -8
- package/node_modules/pi-lens/docs/features.md +45 -5
- package/node_modules/pi-lens/docs/globalconfig.md +2 -1
- package/node_modules/pi-lens/docs/io-bridge-v2-migration.md +94 -0
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +37 -4
- package/node_modules/pi-lens/docs/lsp-idle-eviction.md +124 -0
- package/node_modules/pi-lens/docs/mcp.md +21 -5
- package/node_modules/pi-lens/docs/merge-queue-rollout.md +77 -0
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +160 -88
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +74 -26
- package/node_modules/pi-lens/docs/pi-lens-merge-policy.md +736 -0
- package/node_modules/pi-lens/docs/pi-lens-monitor.md +75 -7
- package/node_modules/pi-lens/docs/pi-lens-retro.md +6 -4
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +189 -48
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +246 -45
- package/node_modules/pi-lens/docs/pi-lens-warden.md +18 -7
- package/node_modules/pi-lens/docs/public-api-stability.md +55 -0
- package/node_modules/pi-lens/docs/release-qa-baseline.md +84 -17
- package/node_modules/pi-lens/docs/rfcs/3654-unified-io-bridge-v2.md +316 -0
- package/node_modules/pi-lens/docs/schema/pi-lens-config-v1.json +530 -0
- package/node_modules/pi-lens/docs/servercapabilities.md +56 -49
- package/node_modules/pi-lens/docs/settings.md +1 -0
- package/node_modules/pi-lens/docs/usage.md +5 -1
- package/node_modules/pi-lens/docs/word-index.md +6 -0
- package/node_modules/pi-lens/grammars/tree-sitter-bash.wasm +0 -0
- package/node_modules/pi-lens/grammars/tree-sitter-bash.wasm.json +3 -3
- package/node_modules/pi-lens/package.json +18 -6
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/advisory-registry-subset-test.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-identity-operator-on-literals-test.yml +12 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/throw-new-error-js-test.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/throw-new-error-test.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/advisory-registry-subset.yml +50 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-identity-operator-on-literals.yml +20 -12
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/throw-new-error-js.yml +2 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/throw-new-error.yml +2 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +1275 -62
- package/node_modules/pi-lens/scripts/download-grammars.js +5 -0
- package/node_modules/pi-lens/scripts/grammars.lock.json +6 -1
- package/node_modules/pi-lens/scripts/install-selftest.mjs +33 -34
- package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +13 -4
- package/node_modules/pi-lens/scripts/lib/web-tree-sitter-dir.mjs +18 -0
- package/node_modules/pi-web-access/CHANGELOG.md +28 -0
- package/node_modules/pi-web-access/README.md +10 -6
- package/node_modules/pi-web-access/ceramic.ts +219 -0
- package/node_modules/pi-web-access/curator-page.ts +3 -1
- package/node_modules/pi-web-access/curator-server.ts +1 -0
- package/node_modules/pi-web-access/dist/index.js +846 -588
- package/node_modules/pi-web-access/dist/mcp-cli.js +725 -516
- package/node_modules/pi-web-access/gemini-search.ts +8 -4
- package/node_modules/pi-web-access/github-extract.ts +34 -2
- package/node_modules/pi-web-access/index.ts +72 -30
- package/node_modules/pi-web-access/openai-search.ts +3 -3
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/page-query.ts +6 -9
- package/node_modules/pi-web-access/parallel-mcp.ts +2 -0
- package/node_modules/pi-web-access/query-rewrite.ts +2 -2
- package/node_modules/pi-web-access/storage.ts +49 -0
- package/node_modules/pi-web-access/summary-review.ts +7 -6
- package/node_modules/pi-web-access/utils.ts +21 -6
- package/node_modules/pi-web-access/web-tool-core.ts +1 -0
- package/package.json +19 -19
- package/node_modules/@dietrichgebert/ponytail/README.es.md +0 -212
- package/node_modules/@dietrichgebert/ponytail/README.ja.md +0 -212
- package/node_modules/@dietrichgebert/ponytail/README.ko.md +0 -212
- package/node_modules/@dietrichgebert/ponytail/README.zh-CN.md +0 -212
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +0 -35
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +0 -1610
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +0 -593
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +0 -147
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +0 -325
- package/node_modules/pi-lens/dist/clients/analysed-root.js +0 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +0 -731
- package/node_modules/pi-lens/dist/clients/ast-grep-rule-manager.js +0 -146
- package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +0 -118
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -10
- package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +0 -154
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +0 -75
- package/node_modules/pi-lens/dist/clients/atomic-write.js +0 -189
- package/node_modules/pi-lens/dist/clients/availability-probe-flight.js +0 -12
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +0 -1056
- package/node_modules/pi-lens/dist/clients/biome-client.js +0 -357
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +0 -837
- package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +0 -129
- package/node_modules/pi-lens/dist/clients/bootstrap.js +0 -569
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +0 -190
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +0 -202
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +0 -295
- package/node_modules/pi-lens/dist/clients/build-identity.js +0 -95
- package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +0 -113
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +0 -105
- package/node_modules/pi-lens/dist/clients/bus-publish.js +0 -171
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +0 -190
- package/node_modules/pi-lens/dist/clients/cache-manager.js +0 -524
- package/node_modules/pi-lens/dist/clients/cache-observability.js +0 -1313
- package/node_modules/pi-lens/dist/clients/call-graph.js +0 -852
- package/node_modules/pi-lens/dist/clients/cargo-manifest.js +0 -422
- package/node_modules/pi-lens/dist/clients/cascade-budget.js +0 -196
- package/node_modules/pi-lens/dist/clients/cascade-format.js +0 -315
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +0 -31
- package/node_modules/pi-lens/dist/clients/cascade-types.js +0 -9
- package/node_modules/pi-lens/dist/clients/child-unref.js +0 -124
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +0 -286
- package/node_modules/pi-lens/dist/clients/codebase-model.js +0 -173
- package/node_modules/pi-lens/dist/clients/collateral-test-role.js +0 -40
- package/node_modules/pi-lens/dist/clients/complexity-client.js +0 -462
- package/node_modules/pi-lens/dist/clients/config-core/deny.js +0 -221
- package/node_modules/pi-lens/dist/clients/config-core/index.js +0 -50
- package/node_modules/pi-lens/dist/clients/config-core/merge.js +0 -357
- package/node_modules/pi-lens/dist/clients/config-core/normalize.js +0 -340
- package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +0 -248
- package/node_modules/pi-lens/dist/clients/config-core/provenance.js +0 -164
- package/node_modules/pi-lens/dist/clients/config-core/records.js +0 -218
- package/node_modules/pi-lens/dist/clients/config-core/resolve.js +0 -125
- package/node_modules/pi-lens/dist/clients/config-core/safe-object.js +0 -78
- package/node_modules/pi-lens/dist/clients/config-core/schema.js +0 -165
- package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +0 -285
- package/node_modules/pi-lens/dist/clients/config-locations.js +0 -388
- package/node_modules/pi-lens/dist/clients/config-resolve.js +0 -798
- package/node_modules/pi-lens/dist/clients/config-schema.js +0 -251
- package/node_modules/pi-lens/dist/clients/config-warn.js +0 -407
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +0 -26
- package/node_modules/pi-lens/dist/clients/cooperative-budget.js +0 -42
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +0 -510
- package/node_modules/pi-lens/dist/clients/dead-code-logger.js +0 -30
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +0 -280
- package/node_modules/pi-lens/dist/clients/debug-handles.js +0 -211
- package/node_modules/pi-lens/dist/clients/debug-heap.js +0 -174
- package/node_modules/pi-lens/dist/clients/deferred-lsp-work.js +0 -106
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +0 -426
- package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +0 -169
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +0 -885
- package/node_modules/pi-lens/dist/clients/deps/ast-grep-napi.js +0 -22
- package/node_modules/pi-lens/dist/clients/deps/js-yaml.js +0 -9
- package/node_modules/pi-lens/dist/clients/deps/minimatch.js +0 -4
- package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +0 -14
- package/node_modules/pi-lens/dist/clients/deps/typebox.js +0 -14
- package/node_modules/pi-lens/dist/clients/deps/vscode-jsonrpc.js +0 -1
- package/node_modules/pi-lens/dist/clients/deps/web-tree-sitter.js +0 -24
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +0 -630
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +0 -305
- package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +0 -73
- package/node_modules/pi-lens/dist/clients/diagnostic-tracker.js +0 -105
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +0 -230
- package/node_modules/pi-lens/dist/clients/dispatch/ast-grep-catalog.js +0 -65
- package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +0 -343
- package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -35
- package/node_modules/pi-lens/dist/clients/dispatch/diagnostic-taxonomy.js +0 -66
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +0 -1269
- package/node_modules/pi-lens/dist/clients/dispatch/fact-provider-types.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/fact-rule-runner.js +0 -17
- package/node_modules/pi-lens/dist/clients/dispatch/fact-runner.js +0 -30
- package/node_modules/pi-lens/dist/clients/dispatch/fact-scheduler.js +0 -68
- package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +0 -377
- package/node_modules/pi-lens/dist/clients/dispatch/facts/comment-facts.js +0 -22
- package/node_modules/pi-lens/dist/clients/dispatch/facts/file-content.js +0 -19
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +0 -348
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +0 -204
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +0 -34
- package/node_modules/pi-lens/dist/clients/dispatch/facts/try-catch-facts.js +0 -119
- package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +0 -339
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +0 -417
- package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +0 -89
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +0 -2377
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +0 -11
- package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +0 -87
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +0 -278
- package/node_modules/pi-lens/dist/clients/dispatch/priorities.js +0 -20
- package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +0 -50
- package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +0 -69
- package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +0 -135
- package/node_modules/pi-lens/dist/clients/dispatch/rules/async-noise.js +0 -40
- package/node_modules/pi-lens/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +0 -27
- package/node_modules/pi-lens/dist/clients/dispatch/rules/cors-wildcard.js +0 -54
- package/node_modules/pi-lens/dist/clients/dispatch/rules/error-obscuring.js +0 -32
- package/node_modules/pi-lens/dist/clients/dispatch/rules/error-swallowing.js +0 -31
- package/node_modules/pi-lens/dist/clients/dispatch/rules/framework-call-noise.js +0 -67
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-complexity.js +0 -72
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-fan-out.js +0 -74
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-import-coupling.js +0 -37
- package/node_modules/pi-lens/dist/clients/dispatch/rules/missing-error-propagation.js +0 -62
- package/node_modules/pi-lens/dist/clients/dispatch/rules/no-commented-credentials.js +0 -52
- package/node_modules/pi-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +0 -42
- package/node_modules/pi-lens/dist/clients/dispatch/rules/placeholder-comments.js +0 -40
- package/node_modules/pi-lens/dist/clients/dispatch/rules/unsafe-boundary.js +0 -126
- package/node_modules/pi-lens/dist/clients/dispatch/runner-context.js +0 -52
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +0 -111
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +0 -1196
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +0 -296
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +0 -219
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +0 -82
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +0 -416
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -183
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +0 -176
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -164
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +0 -195
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +0 -137
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fact-rules.js +0 -29
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +0 -69
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +0 -167
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +0 -104
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -135
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +0 -91
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +0 -171
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +0 -940
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +0 -117
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +0 -108
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +0 -99
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +0 -110
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +0 -379
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +0 -167
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +0 -102
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +0 -414
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +0 -85
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +0 -120
- package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -62
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -445
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +0 -169
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +0 -99
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +0 -88
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +0 -256
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +0 -173
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -102
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +0 -128
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +0 -259
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -183
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +0 -166
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +0 -163
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +0 -174
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +0 -168
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +0 -125
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -643
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +0 -253
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +0 -496
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +0 -90
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -95
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +0 -274
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +0 -1701
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +0 -101
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +0 -235
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +0 -169
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils.js +0 -15
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -128
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +0 -242
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +0 -95
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -79
- package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +0 -79
- package/node_modules/pi-lens/dist/clients/dispatch/tool-profile.js +0 -30
- package/node_modules/pi-lens/dist/clients/dispatch/types.js +0 -21
- package/node_modules/pi-lens/dist/clients/dispatch/utils/format-utils.js +0 -45
- package/node_modules/pi-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +0 -35
- package/node_modules/pi-lens/dist/clients/disposition-logger.js +0 -32
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +0 -124
- package/node_modules/pi-lens/dist/clients/durable-store.js +0 -97
- package/node_modules/pi-lens/dist/clients/effective-config.js +0 -415
- package/node_modules/pi-lens/dist/clients/env-utils.js +0 -83
- package/node_modules/pi-lens/dist/clients/error-class.js +0 -23
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +0 -17
- package/node_modules/pi-lens/dist/clients/event-loop-hold.js +0 -274
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +0 -250
- package/node_modules/pi-lens/dist/clients/extension-log.js +0 -504
- package/node_modules/pi-lens/dist/clients/extension-mode.js +0 -73
- package/node_modules/pi-lens/dist/clients/feature-hints.js +0 -103
- package/node_modules/pi-lens/dist/clients/file-kinds.js +0 -412
- package/node_modules/pi-lens/dist/clients/file-role.js +0 -134
- package/node_modules/pi-lens/dist/clients/file-time.js +0 -160
- package/node_modules/pi-lens/dist/clients/file-utils.js +0 -1032
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +0 -494
- package/node_modules/pi-lens/dist/clients/finding-identity.js +0 -88
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +0 -103
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +0 -343
- package/node_modules/pi-lens/dist/clients/format-service.js +0 -222
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +0 -9
- package/node_modules/pi-lens/dist/clients/formatters.js +0 -2032
- package/node_modules/pi-lens/dist/clients/freshness-cadence.js +0 -17
- package/node_modules/pi-lens/dist/clients/freshness.js +0 -38
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +0 -394
- package/node_modules/pi-lens/dist/clients/generation-guard.js +0 -215
- package/node_modules/pi-lens/dist/clients/git-guard.js +0 -1136
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +0 -243
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +0 -509
- package/node_modules/pi-lens/dist/clients/go-client.js +0 -104
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +0 -605
- package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +0 -348
- package/node_modules/pi-lens/dist/clients/grammar-source.js +0 -465
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +0 -135
- package/node_modules/pi-lens/dist/clients/hashline-anchor.js +0 -424
- package/node_modules/pi-lens/dist/clients/hook-budgets.js +0 -76
- package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +0 -140
- package/node_modules/pi-lens/dist/clients/host-ports.js +0 -39
- package/node_modules/pi-lens/dist/clients/indent-retarget.js +0 -154
- package/node_modules/pi-lens/dist/clients/inline-blocker-dispositions.js +0 -186
- package/node_modules/pi-lens/dist/clients/install-diagnostics.js +0 -156
- package/node_modules/pi-lens/dist/clients/installer/index.js +0 -5416
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +0 -58
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +0 -783
- package/node_modules/pi-lens/dist/clients/instance-reaper-state.js +0 -7
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +0 -1137
- package/node_modules/pi-lens/dist/clients/instance-registry-lock.js +0 -145
- package/node_modules/pi-lens/dist/clients/instance-registry.js +0 -773
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +0 -378
- package/node_modules/pi-lens/dist/clients/json-cache-read.js +0 -65
- package/node_modules/pi-lens/dist/clients/knip-client.js +0 -788
- package/node_modules/pi-lens/dist/clients/language-policy.js +0 -252
- package/node_modules/pi-lens/dist/clients/language-profile.js +0 -361
- package/node_modules/pi-lens/dist/clients/language-registry.js +0 -603
- package/node_modules/pi-lens/dist/clients/latency-logger.js +0 -727
- package/node_modules/pi-lens/dist/clients/lazy-import.js +0 -21
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +0 -54
- package/node_modules/pi-lens/dist/clients/lens-config.js +0 -404
- package/node_modules/pi-lens/dist/clients/lens-engine.js +0 -358
- package/node_modules/pi-lens/dist/clients/lens-events.js +0 -125
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +0 -467
- package/node_modules/pi-lens/dist/clients/lens-map.js +0 -1156
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +0 -74
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +0 -222
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +0 -178
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +0 -421
- package/node_modules/pi-lens/dist/clients/lsp/client.js +0 -4593
- package/node_modules/pi-lens/dist/clients/lsp/config.js +0 -691
- package/node_modules/pi-lens/dist/clients/lsp/content-limits.js +0 -41
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +0 -225
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +0 -467
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +0 -1219
- package/node_modules/pi-lens/dist/clients/lsp/index.js +0 -8305
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +0 -216
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +0 -298
- package/node_modules/pi-lens/dist/clients/lsp/language.js +0 -63
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +0 -746
- package/node_modules/pi-lens/dist/clients/lsp/lombok.js +0 -158
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +0 -5
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +0 -251
- package/node_modules/pi-lens/dist/clients/lsp/position-encoding.js +0 -61
- package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +0 -83
- package/node_modules/pi-lens/dist/clients/lsp/server.js +0 -3290
- package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +0 -192
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +0 -17
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +0 -56
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +0 -332
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/capability-snapshot.js +0 -1
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +0 -85
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/index.js +0 -10
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +0 -392
- package/node_modules/pi-lens/dist/clients/lsp/watch-queue.js +0 -61
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +0 -639
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +0 -30
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +0 -184
- package/node_modules/pi-lens/dist/clients/lsp-budget.js +0 -186
- package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +0 -110
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +0 -9
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +0 -396
- package/node_modules/pi-lens/dist/clients/lsp-status.js +0 -59
- package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +0 -40
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +0 -420
- package/node_modules/pi-lens/dist/clients/mcp/host-shim.js +0 -31
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +0 -523
- package/node_modules/pi-lens/dist/clients/mcp/review.js +0 -197
- package/node_modules/pi-lens/dist/clients/mcp/session.js +0 -412
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +0 -208
- package/node_modules/pi-lens/dist/clients/message-end-attribution.js +0 -30
- package/node_modules/pi-lens/dist/clients/metrics-client.js +0 -107
- package/node_modules/pi-lens/dist/clients/metrics-history.js +0 -327
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +0 -263
- package/node_modules/pi-lens/dist/clients/model-provider.js +0 -53
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +0 -189
- package/node_modules/pi-lens/dist/clients/module-report.js +0 -2150
- package/node_modules/pi-lens/dist/clients/mutating-tool.js +0 -651
- package/node_modules/pi-lens/dist/clients/mutation-attribution.js +0 -368
- package/node_modules/pi-lens/dist/clients/mutation-bridge.js +0 -240
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +0 -734
- package/node_modules/pi-lens/dist/clients/observed-mutation-sources.js +0 -101
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +0 -1253
- package/node_modules/pi-lens/dist/clients/oldtext-autopatch.js +0 -128
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +0 -496
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +0 -333
- package/node_modules/pi-lens/dist/clients/opengrep-config.js +0 -76
- package/node_modules/pi-lens/dist/clients/package-manager.js +0 -607
- package/node_modules/pi-lens/dist/clients/package-root.js +0 -38
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +0 -439
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +0 -43
- package/node_modules/pi-lens/dist/clients/path-keyed-map.js +0 -108
- package/node_modules/pi-lens/dist/clients/path-utils.js +0 -1244
- package/node_modules/pi-lens/dist/clients/performance-report.js +0 -331
- package/node_modules/pi-lens/dist/clients/persist-debounce.js +0 -70
- package/node_modules/pi-lens/dist/clients/persistent-reverify.js +0 -271
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +0 -119
- package/node_modules/pi-lens/dist/clients/pipeline.js +0 -1480
- package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +0 -37
- package/node_modules/pi-lens/dist/clients/print-mode.js +0 -21
- package/node_modules/pi-lens/dist/clients/probe-home-state.js +0 -228
- package/node_modules/pi-lens/dist/clients/process-bridge.js +0 -66
- package/node_modules/pi-lens/dist/clients/process-singletons.js +0 -210
- package/node_modules/pi-lens/dist/clients/process-snapshot.js +0 -68
- package/node_modules/pi-lens/dist/clients/project-changes.js +0 -181
- package/node_modules/pi-lens/dist/clients/project-conventions.js +0 -171
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +0 -137
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +0 -109
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +0 -668
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +0 -118
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +0 -47
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +0 -40
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +0 -34
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +0 -38
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +0 -47
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +0 -48
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +0 -40
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +0 -127
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +0 -81
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +0 -520
- package/node_modules/pi-lens/dist/clients/project-diagnostics/types.js +0 -1
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +0 -807
- package/node_modules/pi-lens/dist/clients/project-report.js +0 -701
- package/node_modules/pi-lens/dist/clients/project-scale.js +0 -237
- package/node_modules/pi-lens/dist/clients/project-scan-policy.js +0 -11
- package/node_modules/pi-lens/dist/clients/project-snapshot-fingerprint.js +0 -48
- package/node_modules/pi-lens/dist/clients/project-snapshot-persist-worker.js +0 -20
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +0 -1653
- package/node_modules/pi-lens/dist/clients/project-trust.js +0 -181
- package/node_modules/pi-lens/dist/clients/python-environment.js +0 -217
- package/node_modules/pi-lens/dist/clients/python-provenance.js +0 -639
- package/node_modules/pi-lens/dist/clients/quiet-window-config.js +0 -47
- package/node_modules/pi-lens/dist/clients/quiet-window.js +0 -236
- package/node_modules/pi-lens/dist/clients/read-bridge.js +0 -139
- package/node_modules/pi-lens/dist/clients/read-expansion.js +0 -266
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +0 -251
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +0 -1306
- package/node_modules/pi-lens/dist/clients/read-guard.js +0 -1561
- package/node_modules/pi-lens/dist/clients/recent-touches.js +0 -240
- package/node_modules/pi-lens/dist/clients/redact/secrets.js +0 -449
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +0 -628
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +0 -270
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +0 -5126
- package/node_modules/pi-lens/dist/clients/review-graph/format.js +0 -33
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +0 -163
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +0 -481
- package/node_modules/pi-lens/dist/clients/review-graph/persist-worker.js +0 -10
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +0 -244
- package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +0 -21
- package/node_modules/pi-lens/dist/clients/review-graph/service.js +0 -96
- package/node_modules/pi-lens/dist/clients/review-graph/shared-extraction-ir.js +0 -82
- package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +0 -103
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +0 -299
- package/node_modules/pi-lens/dist/clients/review-graph/types.js +0 -1
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +0 -449
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +0 -81
- package/node_modules/pi-lens/dist/clients/ruff-client.js +0 -179
- package/node_modules/pi-lens/dist/clients/rules-scanner.js +0 -131
- package/node_modules/pi-lens/dist/clients/run-duration.js +0 -55
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +0 -746
- package/node_modules/pi-lens/dist/clients/runtime-config.js +0 -77
- package/node_modules/pi-lens/dist/clients/runtime-context.js +0 -211
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +0 -1324
- package/node_modules/pi-lens/dist/clients/runtime-session.js +0 -2485
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +0 -1295
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +0 -2049
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +0 -3767
- package/node_modules/pi-lens/dist/clients/rust-client.js +0 -97
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +0 -2357
- package/node_modules/pi-lens/dist/clients/sanitize.js +0 -286
- package/node_modules/pi-lens/dist/clients/scan-utils.js +0 -25
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +0 -165
- package/node_modules/pi-lens/dist/clients/search-read-registration.js +0 -94
- package/node_modules/pi-lens/dist/clients/secret-findings.js +0 -114
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +0 -352
- package/node_modules/pi-lens/dist/clients/session-event-guard.js +0 -297
- package/node_modules/pi-lens/dist/clients/session-lifecycle.js +0 -484
- package/node_modules/pi-lens/dist/clients/session-start-observability.js +0 -94
- package/node_modules/pi-lens/dist/clients/session-state-store.js +0 -101
- package/node_modules/pi-lens/dist/clients/session-summary.js +0 -15
- package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +0 -27
- package/node_modules/pi-lens/dist/clients/sg-runner.js +0 -876
- package/node_modules/pi-lens/dist/clients/sgconfig.js +0 -347
- package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +0 -338
- package/node_modules/pi-lens/dist/clients/single-flight.js +0 -158
- package/node_modules/pi-lens/dist/clients/situational-tool-telemetry.js +0 -108
- package/node_modules/pi-lens/dist/clients/skills-resolver.js +0 -141
- package/node_modules/pi-lens/dist/clients/slow-fs.js +0 -138
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +0 -231
- package/node_modules/pi-lens/dist/clients/source-filter.js +0 -596
- package/node_modules/pi-lens/dist/clients/source-walker.js +0 -211
- package/node_modules/pi-lens/dist/clients/spawn-output-cap.js +0 -120
- package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +0 -110
- package/node_modules/pi-lens/dist/clients/stale-marker.js +0 -17
- package/node_modules/pi-lens/dist/clients/startup-scan.js +0 -400
- package/node_modules/pi-lens/dist/clients/startup-timing.js +0 -130
- package/node_modules/pi-lens/dist/clients/string-utils.js +0 -33
- package/node_modules/pi-lens/dist/clients/subagent-mode.js +0 -111
- package/node_modules/pi-lens/dist/clients/symbol-containment.js +0 -24
- package/node_modules/pi-lens/dist/clients/symbol-types.js +0 -5
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +0 -2507
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +0 -287
- package/node_modules/pi-lens/dist/clients/todo-scanner.js +0 -229
- package/node_modules/pi-lens/dist/clients/tool-agreement.js +0 -423
- package/node_modules/pi-lens/dist/clients/tool-config.js +0 -249
- package/node_modules/pi-lens/dist/clients/tool-cwd.js +0 -270
- package/node_modules/pi-lens/dist/clients/tool-definition.js +0 -47
- package/node_modules/pi-lens/dist/clients/tool-event.js +0 -105
- package/node_modules/pi-lens/dist/clients/tool-policy.js +0 -2755
- package/node_modules/pi-lens/dist/clients/tool-probe.js +0 -53
- package/node_modules/pi-lens/dist/clients/tool-render.js +0 -156
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +0 -118
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +0 -364
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +0 -4195
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +0 -100
- package/node_modules/pi-lens/dist/clients/tree-sitter-navigator.js +0 -269
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +0 -569
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +0 -158
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +0 -1265
- package/node_modules/pi-lens/dist/clients/trivy-client.js +0 -467
- package/node_modules/pi-lens/dist/clients/tui-fit.js +0 -50
- package/node_modules/pi-lens/dist/clients/turn-context.js +0 -52
- package/node_modules/pi-lens/dist/clients/turn-end/lane.js +0 -51
- package/node_modules/pi-lens/dist/clients/turn-end/lanes/govulncheck.js +0 -112
- package/node_modules/pi-lens/dist/clients/turn-end/lanes/secrets.js +0 -204
- package/node_modules/pi-lens/dist/clients/turn-summary-render.js +0 -72
- package/node_modules/pi-lens/dist/clients/turn-summary.js +0 -132
- package/node_modules/pi-lens/dist/clients/typos-config.js +0 -29
- package/node_modules/pi-lens/dist/clients/user-notify.js +0 -51
- package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +0 -57
- package/node_modules/pi-lens/dist/clients/warm-attach.js +0 -305
- package/node_modules/pi-lens/dist/clients/widget-state.js +0 -1808
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +0 -49
- package/node_modules/pi-lens/dist/clients/word-index-store.js +0 -459
- package/node_modules/pi-lens/dist/clients/word-index.js +0 -2080
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +0 -443
- package/node_modules/pi-lens/dist/clients/write-ordering-guard.js +0 -65
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +0 -340
- package/node_modules/pi-lens/dist/i18n.js +0 -69
- package/node_modules/pi-lens/dist/mcp/build-staleness.js +0 -124
- package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +0 -583
- package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +0 -129
- package/node_modules/pi-lens/dist/scripts/lib/web-tree-sitter-dir.mjs +0 -123
- package/node_modules/pi-lens/dist/tools/activate-tools.js +0 -87
- package/node_modules/pi-lens/dist/tools/ast-grep-outline.js +0 -137
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +0 -244
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +0 -762
- package/node_modules/pi-lens/dist/tools/effective-config.js +0 -90
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +0 -375
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +0 -2571
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +0 -1745
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +0 -1367
- package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +0 -294
- package/node_modules/pi-lens/dist/tools/module-report.js +0 -382
- package/node_modules/pi-lens/dist/tools/project-report.js +0 -86
- package/node_modules/pi-lens/dist/tools/render-compact.js +0 -374
- package/node_modules/pi-lens/dist/tools/scan-progress.js +0 -53
- package/node_modules/pi-lens/dist/tools/shared.js +0 -29
- package/node_modules/pi-lens/dist/tools/symbol-search.js +0 -155
- package/node_modules/pi-web-access/opencode-session-headers.ts +0 -24
- package/node_modules/remote-pi/README.md +0 -675
- package/node_modules/remote-pi/dist/actions/handlers.d.ts +0 -122
- package/node_modules/remote-pi/dist/actions/handlers.js +0 -160
- package/node_modules/remote-pi/dist/actions/handlers.js.map +0 -1
- package/node_modules/remote-pi/dist/actions/registry.d.ts +0 -39
- package/node_modules/remote-pi/dist/actions/registry.js +0 -58
- package/node_modules/remote-pi/dist/actions/registry.js.map +0 -1
- package/node_modules/remote-pi/dist/bin/supervisord.d.ts +0 -2
- package/node_modules/remote-pi/dist/bin/supervisord.js +0 -86
- package/node_modules/remote-pi/dist/bin/supervisord.js.map +0 -1
- package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +0 -58
- package/node_modules/remote-pi/dist/commands/builtin_mirror.js +0 -71
- package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +0 -1
- package/node_modules/remote-pi/dist/commands/list_commands.d.ts +0 -60
- package/node_modules/remote-pi/dist/commands/list_commands.js +0 -73
- package/node_modules/remote-pi/dist/commands/list_commands.js.map +0 -1
- package/node_modules/remote-pi/dist/config.d.ts +0 -62
- package/node_modules/remote-pi/dist/config.js +0 -115
- package/node_modules/remote-pi/dist/config.js.map +0 -1
- package/node_modules/remote-pi/dist/daemon/client.d.ts +0 -20
- package/node_modules/remote-pi/dist/daemon/client.js +0 -131
- package/node_modules/remote-pi/dist/daemon/client.js.map +0 -1
- package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +0 -176
- package/node_modules/remote-pi/dist/daemon/control_protocol.js +0 -63
- package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +0 -1
- package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +0 -45
- package/node_modules/remote-pi/dist/daemon/cron_log.js +0 -72
- package/node_modules/remote-pi/dist/daemon/cron_log.js.map +0 -1
- package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +0 -80
- package/node_modules/remote-pi/dist/daemon/cron_registry.js +0 -194
- package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +0 -1
- package/node_modules/remote-pi/dist/daemon/id.d.ts +0 -24
- package/node_modules/remote-pi/dist/daemon/id.js +0 -36
- package/node_modules/remote-pi/dist/daemon/id.js.map +0 -1
- package/node_modules/remote-pi/dist/daemon/install.d.ts +0 -170
- package/node_modules/remote-pi/dist/daemon/install.js +0 -547
- package/node_modules/remote-pi/dist/daemon/install.js.map +0 -1
- package/node_modules/remote-pi/dist/daemon/registry.d.ts +0 -63
- package/node_modules/remote-pi/dist/daemon/registry.js +0 -153
- package/node_modules/remote-pi/dist/daemon/registry.js.map +0 -1
- package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +0 -194
- package/node_modules/remote-pi/dist/daemon/rpc_child.js +0 -389
- package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +0 -1
- package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +0 -93
- package/node_modules/remote-pi/dist/daemon/supervisor.js +0 -596
- package/node_modules/remote-pi/dist/daemon/supervisor.js.map +0 -1
- package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +0 -26
- package/node_modules/remote-pi/dist/extension_ui_bridge.js +0 -341
- package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +0 -1
- package/node_modules/remote-pi/dist/index.d.ts +0 -213
- package/node_modules/remote-pi/dist/index.js +0 -4996
- package/node_modules/remote-pi/dist/index.js.map +0 -1
- package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +0 -10
- package/node_modules/remote-pi/dist/mcp/mesh_result.js +0 -42
- package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +0 -1
- package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +0 -16
- package/node_modules/remote-pi/dist/mcp/mesh_server.js +0 -327
- package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +0 -1
- package/node_modules/remote-pi/dist/mesh/canonical.d.ts +0 -30
- package/node_modules/remote-pi/dist/mesh/canonical.js +0 -61
- package/node_modules/remote-pi/dist/mesh/canonical.js.map +0 -1
- package/node_modules/remote-pi/dist/mesh/client.d.ts +0 -18
- package/node_modules/remote-pi/dist/mesh/client.js +0 -125
- package/node_modules/remote-pi/dist/mesh/client.js.map +0 -1
- package/node_modules/remote-pi/dist/mesh/encoding.d.ts +0 -38
- package/node_modules/remote-pi/dist/mesh/encoding.js +0 -216
- package/node_modules/remote-pi/dist/mesh/encoding.js.map +0 -1
- package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +0 -73
- package/node_modules/remote-pi/dist/mesh/self_revoke.js +0 -401
- package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +0 -1
- package/node_modules/remote-pi/dist/mesh/siblings.d.ts +0 -49
- package/node_modules/remote-pi/dist/mesh/siblings.js +0 -159
- package/node_modules/remote-pi/dist/mesh/siblings.js.map +0 -1
- package/node_modules/remote-pi/dist/mesh/types.d.ts +0 -34
- package/node_modules/remote-pi/dist/mesh/types.js +0 -11
- package/node_modules/remote-pi/dist/mesh/types.js.map +0 -1
- package/node_modules/remote-pi/dist/mesh/verify.d.ts +0 -17
- package/node_modules/remote-pi/dist/mesh/verify.js +0 -86
- package/node_modules/remote-pi/dist/mesh/verify.js.map +0 -1
- package/node_modules/remote-pi/dist/pairing/crypto.d.ts +0 -8
- package/node_modules/remote-pi/dist/pairing/crypto.js +0 -22
- package/node_modules/remote-pi/dist/pairing/crypto.js.map +0 -1
- package/node_modules/remote-pi/dist/pairing/handshake.d.ts +0 -28
- package/node_modules/remote-pi/dist/pairing/handshake.js +0 -113
- package/node_modules/remote-pi/dist/pairing/handshake.js.map +0 -1
- package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +0 -16
- package/node_modules/remote-pi/dist/pairing/noise-sha256.js +0 -103
- package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +0 -1
- package/node_modules/remote-pi/dist/pairing/qr.d.ts +0 -59
- package/node_modules/remote-pi/dist/pairing/qr.js +0 -125
- package/node_modules/remote-pi/dist/pairing/qr.js.map +0 -1
- package/node_modules/remote-pi/dist/pairing/storage.d.ts +0 -120
- package/node_modules/remote-pi/dist/pairing/storage.js +0 -604
- package/node_modules/remote-pi/dist/pairing/storage.js.map +0 -1
- package/node_modules/remote-pi/dist/protocol/codec.d.ts +0 -7
- package/node_modules/remote-pi/dist/protocol/codec.js +0 -49
- package/node_modules/remote-pi/dist/protocol/codec.js.map +0 -1
- package/node_modules/remote-pi/dist/protocol/types.d.ts +0 -393
- package/node_modules/remote-pi/dist/protocol/types.js +0 -2
- package/node_modules/remote-pi/dist/protocol/types.js.map +0 -1
- package/node_modules/remote-pi/dist/rooms.d.ts +0 -29
- package/node_modules/remote-pi/dist/rooms.js +0 -57
- package/node_modules/remote-pi/dist/rooms.js.map +0 -1
- package/node_modules/remote-pi/dist/session/address.d.ts +0 -49
- package/node_modules/remote-pi/dist/session/address.js +0 -58
- package/node_modules/remote-pi/dist/session/address.js.map +0 -1
- package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +0 -55
- package/node_modules/remote-pi/dist/session/agent_bridge.js +0 -146
- package/node_modules/remote-pi/dist/session/agent_bridge.js.map +0 -1
- package/node_modules/remote-pi/dist/session/bridge.d.ts +0 -37
- package/node_modules/remote-pi/dist/session/bridge.js +0 -130
- package/node_modules/remote-pi/dist/session/bridge.js.map +0 -1
- package/node_modules/remote-pi/dist/session/broker.d.ts +0 -189
- package/node_modules/remote-pi/dist/session/broker.js +0 -507
- package/node_modules/remote-pi/dist/session/broker.js.map +0 -1
- package/node_modules/remote-pi/dist/session/broker_remote.d.ts +0 -74
- package/node_modules/remote-pi/dist/session/broker_remote.js +0 -583
- package/node_modules/remote-pi/dist/session/broker_remote.js.map +0 -1
- package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +0 -33
- package/node_modules/remote-pi/dist/session/cwd_lock.js +0 -126
- package/node_modules/remote-pi/dist/session/cwd_lock.js.map +0 -1
- package/node_modules/remote-pi/dist/session/envelope.d.ts +0 -33
- package/node_modules/remote-pi/dist/session/envelope.js +0 -117
- package/node_modules/remote-pi/dist/session/envelope.js.map +0 -1
- package/node_modules/remote-pi/dist/session/global_config.d.ts +0 -33
- package/node_modules/remote-pi/dist/session/global_config.js +0 -73
- package/node_modules/remote-pi/dist/session/global_config.js.map +0 -1
- package/node_modules/remote-pi/dist/session/ipc.d.ts +0 -27
- package/node_modules/remote-pi/dist/session/ipc.js +0 -22
- package/node_modules/remote-pi/dist/session/ipc.js.map +0 -1
- package/node_modules/remote-pi/dist/session/leader_election.d.ts +0 -32
- package/node_modules/remote-pi/dist/session/leader_election.js +0 -106
- package/node_modules/remote-pi/dist/session/leader_election.js.map +0 -1
- package/node_modules/remote-pi/dist/session/local_config.d.ts +0 -55
- package/node_modules/remote-pi/dist/session/local_config.js +0 -157
- package/node_modules/remote-pi/dist/session/local_config.js.map +0 -1
- package/node_modules/remote-pi/dist/session/mesh_message.d.ts +0 -20
- package/node_modules/remote-pi/dist/session/mesh_message.js +0 -28
- package/node_modules/remote-pi/dist/session/mesh_message.js.map +0 -1
- package/node_modules/remote-pi/dist/session/mesh_node.d.ts +0 -116
- package/node_modules/remote-pi/dist/session/mesh_node.js +0 -573
- package/node_modules/remote-pi/dist/session/mesh_node.js.map +0 -1
- package/node_modules/remote-pi/dist/session/peer.d.ts +0 -139
- package/node_modules/remote-pi/dist/session/peer.js +0 -451
- package/node_modules/remote-pi/dist/session/peer.js.map +0 -1
- package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +0 -13
- package/node_modules/remote-pi/dist/session/peer_inventory.js +0 -48
- package/node_modules/remote-pi/dist/session/peer_inventory.js.map +0 -1
- package/node_modules/remote-pi/dist/session/peer_limits.d.ts +0 -9
- package/node_modules/remote-pi/dist/session/peer_limits.js +0 -21
- package/node_modules/remote-pi/dist/session/peer_limits.js.map +0 -1
- package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +0 -39
- package/node_modules/remote-pi/dist/session/setup_wizard.js +0 -63
- package/node_modules/remote-pi/dist/session/setup_wizard.js.map +0 -1
- package/node_modules/remote-pi/dist/session/tool_gate.d.ts +0 -5
- package/node_modules/remote-pi/dist/session/tool_gate.js +0 -11
- package/node_modules/remote-pi/dist/session/tool_gate.js.map +0 -1
- package/node_modules/remote-pi/dist/session/tools.d.ts +0 -24
- package/node_modules/remote-pi/dist/session/tools.js +0 -252
- package/node_modules/remote-pi/dist/session/tools.js.map +0 -1
- package/node_modules/remote-pi/dist/session/wizard.d.ts +0 -13
- package/node_modules/remote-pi/dist/session/wizard.js +0 -20
- package/node_modules/remote-pi/dist/session/wizard.js.map +0 -1
- package/node_modules/remote-pi/dist/settings.d.ts +0 -15
- package/node_modules/remote-pi/dist/settings.js +0 -52
- package/node_modules/remote-pi/dist/settings.js.map +0 -1
- package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +0 -37
- package/node_modules/remote-pi/dist/transport/peer_channel.js +0 -98
- package/node_modules/remote-pi/dist/transport/peer_channel.js.map +0 -1
- package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +0 -29
- package/node_modules/remote-pi/dist/transport/pi_forward_client.js +0 -62
- package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +0 -1
- package/node_modules/remote-pi/dist/transport/relay_client.d.ts +0 -91
- package/node_modules/remote-pi/dist/transport/relay_client.js +0 -206
- package/node_modules/remote-pi/dist/transport/relay_client.js.map +0 -1
- package/node_modules/remote-pi/dist/ui/footer.d.ts +0 -32
- package/node_modules/remote-pi/dist/ui/footer.js +0 -34
- package/node_modules/remote-pi/dist/ui/footer.js.map +0 -1
- package/node_modules/remote-pi/docs/daemon.md +0 -289
- package/node_modules/remote-pi/package.json +0 -92
- package/node_modules/remote-pi/service-templates/launchd.plist.template +0 -35
- package/node_modules/remote-pi/service-templates/systemd.service.template +0 -19
- package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +0 -10
- package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +0 -38
- package/node_modules/remote-pi/skills/agent-network/SKILL.md +0 -310
|
@@ -0,0 +1,4816 @@
|
|
|
1
|
+
import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
augmentPythonEnvironment,
|
|
4
|
+
detectPythonEnvironment,
|
|
5
|
+
detectPythonVenv,
|
|
6
|
+
pythonEnvironmentToolCandidates
|
|
7
|
+
} from "./chunk-LNOMA3MP.js";
|
|
8
|
+
import {
|
|
9
|
+
resolveOpengrepConfig
|
|
10
|
+
} from "./chunk-U52SAGRM.js";
|
|
11
|
+
import {
|
|
12
|
+
extensionsForLanguage,
|
|
13
|
+
getUserRuleRoot,
|
|
14
|
+
ruleCorpusFingerprintForCycle
|
|
15
|
+
} from "./chunk-KJCWXUUS.js";
|
|
16
|
+
import {
|
|
17
|
+
load,
|
|
18
|
+
resolvePackagePath
|
|
19
|
+
} from "./chunk-QOZXJ4NA.js";
|
|
20
|
+
import {
|
|
21
|
+
hasCargoWorkspaceTable,
|
|
22
|
+
readCargoWorkspaceExclude,
|
|
23
|
+
readCargoWorkspaceMembers,
|
|
24
|
+
readTextFileOrUndefined
|
|
25
|
+
} from "./chunk-S6AMWKPC.js";
|
|
26
|
+
import {
|
|
27
|
+
HOOK_WALL_BUDGET_MS,
|
|
28
|
+
bounded
|
|
29
|
+
} from "./chunk-F5VLZHUW.js";
|
|
30
|
+
import {
|
|
31
|
+
ensureTool,
|
|
32
|
+
findManagedToolBinary,
|
|
33
|
+
getInstallAttempt,
|
|
34
|
+
getToolEnvironment,
|
|
35
|
+
getToolPath,
|
|
36
|
+
isZizmorAuditTarget,
|
|
37
|
+
logSessionStart,
|
|
38
|
+
resolveZizmorGitHubToken
|
|
39
|
+
} from "./chunk-LD7WFTRX.js";
|
|
40
|
+
import {
|
|
41
|
+
resolveToolCwd
|
|
42
|
+
} from "./chunk-IUR76K6A.js";
|
|
43
|
+
import {
|
|
44
|
+
findGlobalBinary
|
|
45
|
+
} from "./chunk-T4QZ6FEH.js";
|
|
46
|
+
import {
|
|
47
|
+
classifyProbeFailure,
|
|
48
|
+
createAvailabilityLatch,
|
|
49
|
+
describeInstallAttempt,
|
|
50
|
+
logAvailabilityDecision,
|
|
51
|
+
startHostStallSampler
|
|
52
|
+
} from "./chunk-O7HZX7CA.js";
|
|
53
|
+
import {
|
|
54
|
+
OWNER_TAG_ENV,
|
|
55
|
+
SpawnFailureError,
|
|
56
|
+
classifySpawnFailure,
|
|
57
|
+
createGenerationSource,
|
|
58
|
+
ephemeralStagingRoot,
|
|
59
|
+
getGlobalPiLensDir,
|
|
60
|
+
getProjectIgnoreGlobs,
|
|
61
|
+
hasSpawnFailureKind,
|
|
62
|
+
holdOwnChildPid,
|
|
63
|
+
isCommandAvailableAsync,
|
|
64
|
+
isPathIgnoredByProject,
|
|
65
|
+
ownerTagForChildren,
|
|
66
|
+
safeSpawnAsync
|
|
67
|
+
} from "./chunk-T54VJRAD.js";
|
|
68
|
+
import {
|
|
69
|
+
DOTNET_CSHARP_ROOT_MARKERS,
|
|
70
|
+
DOTNET_FSHARP_ROOT_MARKERS,
|
|
71
|
+
KIND_EXTENSIONS
|
|
72
|
+
} from "./chunk-64LU2OVH.js";
|
|
73
|
+
import {
|
|
74
|
+
lspSectionOf,
|
|
75
|
+
migrationSubject,
|
|
76
|
+
reportConfigReadFailure,
|
|
77
|
+
reportPiLensConfigRecords,
|
|
78
|
+
resolvePiLensConfig,
|
|
79
|
+
summarizeConfigResolution
|
|
80
|
+
} from "./chunk-N2IRDBZI.js";
|
|
81
|
+
import {
|
|
82
|
+
FRESHNESS_CADENCE_MS,
|
|
83
|
+
LSP_NAMESPACE_KEY,
|
|
84
|
+
dirMtimeRecordsAsync,
|
|
85
|
+
dirMtimesStillFreshAsync,
|
|
86
|
+
getPiLensGlobalConfigPath,
|
|
87
|
+
unknownDirMtimeRecords
|
|
88
|
+
} from "./chunk-Z6BB4JLQ.js";
|
|
89
|
+
import {
|
|
90
|
+
incrementDegradationCount,
|
|
91
|
+
recordDegradationOnce
|
|
92
|
+
} from "./chunk-7ELY2CSM.js";
|
|
93
|
+
import {
|
|
94
|
+
claimPhaseOncePerSession,
|
|
95
|
+
currentSessionRecordId,
|
|
96
|
+
logLatency,
|
|
97
|
+
releasePhaseClaim
|
|
98
|
+
} from "./chunk-3PNFWVHT.js";
|
|
99
|
+
import {
|
|
100
|
+
getGlobalPiLensLogDir,
|
|
101
|
+
getProcessSingleton,
|
|
102
|
+
isTestMode,
|
|
103
|
+
redactSecrets
|
|
104
|
+
} from "./chunk-VSMJK3ZJ.js";
|
|
105
|
+
import {
|
|
106
|
+
STAGE_TMP_PATTERN
|
|
107
|
+
} from "./chunk-LJDODBBZ.js";
|
|
108
|
+
import {
|
|
109
|
+
BoundedFifoMap,
|
|
110
|
+
BoundedLruCache
|
|
111
|
+
} from "./chunk-ABBOA7UD.js";
|
|
112
|
+
import {
|
|
113
|
+
CARGO_WORKSPACE_MEMBER_DIALECT,
|
|
114
|
+
direntsHaveMarkerGlobMatch,
|
|
115
|
+
findLocalToolConfig,
|
|
116
|
+
isAtOrAboveHomeDir,
|
|
117
|
+
isFullyQualified,
|
|
118
|
+
isWindowsPath,
|
|
119
|
+
matchesWorkspaceMemberPattern,
|
|
120
|
+
normalizeEphemeralMapKey,
|
|
121
|
+
normalizeFilePath,
|
|
122
|
+
normalizeMapKey,
|
|
123
|
+
pathsEqual,
|
|
124
|
+
toPosix
|
|
125
|
+
} from "./chunk-G3RLJYA2.js";
|
|
126
|
+
import {
|
|
127
|
+
__require
|
|
128
|
+
} from "./chunk-NXL4FFQQ.js";
|
|
129
|
+
|
|
130
|
+
// dist/clients/lsp/server-traits.js
|
|
131
|
+
var ROLE_MEMBERS = {
|
|
132
|
+
language: "language",
|
|
133
|
+
auxiliary: "auxiliary"
|
|
134
|
+
};
|
|
135
|
+
var DEFAULT_LSP_SERVER_ROLE = "language";
|
|
136
|
+
function isAuxiliary(bearer) {
|
|
137
|
+
const declared = bearer?.role;
|
|
138
|
+
const role = typeof declared === "string" && Object.hasOwn(ROLE_MEMBERS, declared) ? ROLE_MEMBERS[declared] : DEFAULT_LSP_SERVER_ROLE;
|
|
139
|
+
switch (role) {
|
|
140
|
+
case "auxiliary":
|
|
141
|
+
return true;
|
|
142
|
+
case "language":
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
var DEFAULT_NOTIFY_INFLIGHT_LIMIT = 8;
|
|
147
|
+
var DEFAULT_REPLY_ORDERING = "unmeasured";
|
|
148
|
+
function serverTraits(declaration) {
|
|
149
|
+
const declaredLimit = declaration.notifyInflightLimit;
|
|
150
|
+
if (typeof declaredLimit === "number" && Number.isFinite(declaredLimit) && declaredLimit > 0) {
|
|
151
|
+
return {
|
|
152
|
+
role: declaration.role,
|
|
153
|
+
notifyInflightLimit: Math.floor(declaredLimit),
|
|
154
|
+
replyOrdering: declaration.replyOrdering ?? DEFAULT_REPLY_ORDERING
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const envLimit = Number(process.env.PI_LENS_LSP_AUX_NOTIFY_INFLIGHT);
|
|
158
|
+
return {
|
|
159
|
+
role: declaration.role,
|
|
160
|
+
notifyInflightLimit: Number.isFinite(envLimit) && envLimit > 0 ? Math.floor(envLimit) : DEFAULT_NOTIFY_INFLIGHT_LIMIT,
|
|
161
|
+
replyOrdering: declaration.replyOrdering ?? DEFAULT_REPLY_ORDERING
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// dist/clients/lsp/server.js
|
|
166
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, statSync as statSync3 } from "node:fs";
|
|
167
|
+
import { access, readFile, readdir, stat } from "node:fs/promises";
|
|
168
|
+
import os6 from "node:os";
|
|
169
|
+
import path7 from "node:path";
|
|
170
|
+
|
|
171
|
+
// dist/clients/sgconfig.js
|
|
172
|
+
import { createHash } from "node:crypto";
|
|
173
|
+
import * as fs from "node:fs";
|
|
174
|
+
import * as os from "node:os";
|
|
175
|
+
import * as path from "node:path";
|
|
176
|
+
var SGCONFIG_NAMES = ["sgconfig.yml", "sgconfig.yaml"];
|
|
177
|
+
function findLocalSgconfig(startDir) {
|
|
178
|
+
return findLocalToolConfig(startDir, SGCONFIG_NAMES);
|
|
179
|
+
}
|
|
180
|
+
function canonicalDir(dir) {
|
|
181
|
+
try {
|
|
182
|
+
return fs.realpathSync.native(dir);
|
|
183
|
+
} catch {
|
|
184
|
+
return path.resolve(dir);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function getAstGrepRuleSources(projectRoot = process.cwd()) {
|
|
188
|
+
const root = path.resolve(projectRoot || process.cwd());
|
|
189
|
+
const packageRoot = resolvePackagePath(import.meta.url);
|
|
190
|
+
const candidates = [];
|
|
191
|
+
if (canonicalDir(root) !== canonicalDir(packageRoot)) {
|
|
192
|
+
candidates.push({
|
|
193
|
+
dir: path.join(root, "rules", "ast-grep-rules", "rules"),
|
|
194
|
+
origin: "project",
|
|
195
|
+
tier: "primary"
|
|
196
|
+
}, {
|
|
197
|
+
dir: path.join(root, "rules", "ast-grep-rules", "coderabbit", "rules"),
|
|
198
|
+
origin: "project",
|
|
199
|
+
tier: "secondary"
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
const userRoot = getUserRuleRoot();
|
|
203
|
+
if (canonicalDir(userRoot) !== canonicalDir(root)) {
|
|
204
|
+
candidates.push({
|
|
205
|
+
dir: path.join(userRoot, "ast-grep-rules", "rules"),
|
|
206
|
+
origin: "user",
|
|
207
|
+
tier: "primary"
|
|
208
|
+
}, {
|
|
209
|
+
dir: path.join(userRoot, "ast-grep-rules", "coderabbit", "rules"),
|
|
210
|
+
origin: "user",
|
|
211
|
+
tier: "secondary"
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
candidates.push({
|
|
215
|
+
dir: path.join(packageRoot, "rules", "ast-grep-rules", "rules"),
|
|
216
|
+
origin: "bundled",
|
|
217
|
+
tier: "primary"
|
|
218
|
+
}, {
|
|
219
|
+
dir: path.join(packageRoot, "rules", "ast-grep-rules", "coderabbit", "rules"),
|
|
220
|
+
origin: "bundled",
|
|
221
|
+
tier: "secondary"
|
|
222
|
+
});
|
|
223
|
+
const seen = /* @__PURE__ */ new Set();
|
|
224
|
+
return candidates.filter((source) => {
|
|
225
|
+
if (!fs.existsSync(source.dir))
|
|
226
|
+
return false;
|
|
227
|
+
const key = canonicalDir(source.dir);
|
|
228
|
+
if (seen.has(key))
|
|
229
|
+
return false;
|
|
230
|
+
seen.add(key);
|
|
231
|
+
return true;
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
function findYamlFiles(dir) {
|
|
235
|
+
const files = [];
|
|
236
|
+
let entries;
|
|
237
|
+
try {
|
|
238
|
+
entries = fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
239
|
+
} catch {
|
|
240
|
+
return files;
|
|
241
|
+
}
|
|
242
|
+
for (const entry of entries) {
|
|
243
|
+
const full = path.join(dir, entry.name);
|
|
244
|
+
if (entry.isDirectory()) {
|
|
245
|
+
files.push(...findYamlFiles(full));
|
|
246
|
+
} else if (entry.isFile() && /\.ya?ml$/i.test(entry.name)) {
|
|
247
|
+
files.push(full);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return files;
|
|
251
|
+
}
|
|
252
|
+
function parseRuleId(raw) {
|
|
253
|
+
const scalar = raw.match(/^id:\s*(.*?)\s*$/m)?.[1];
|
|
254
|
+
if (!scalar)
|
|
255
|
+
return void 0;
|
|
256
|
+
const withoutComment = scalar.replace(/\s+#.*$/, "").trim();
|
|
257
|
+
const unquoted = withoutComment.startsWith('"') && withoutComment.endsWith('"') || withoutComment.startsWith("'") && withoutComment.endsWith("'") ? withoutComment.slice(1, -1) : withoutComment;
|
|
258
|
+
if (/^[A-Za-z0-9_.:-]+$/.test(unquoted))
|
|
259
|
+
return unquoted;
|
|
260
|
+
try {
|
|
261
|
+
const parsed = load(raw);
|
|
262
|
+
if (!parsed || typeof parsed !== "object" || !("id" in parsed)) {
|
|
263
|
+
return void 0;
|
|
264
|
+
}
|
|
265
|
+
const id = parsed.id;
|
|
266
|
+
return typeof id === "string" ? id : void 0;
|
|
267
|
+
} catch {
|
|
268
|
+
return void 0;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function parseRuleDocuments(content) {
|
|
272
|
+
return content.split(/^---\s*$/m).filter((document) => document.trim()).map((raw) => ({ raw, id: parseRuleId(raw) }));
|
|
273
|
+
}
|
|
274
|
+
var bundledSnapshots = /* @__PURE__ */ new Map();
|
|
275
|
+
function snapshotRuleSource(source) {
|
|
276
|
+
const cacheKey = canonicalDir(source.dir);
|
|
277
|
+
if (source.origin === "bundled") {
|
|
278
|
+
const cached = bundledSnapshots.get(cacheKey);
|
|
279
|
+
if (cached)
|
|
280
|
+
return cached;
|
|
281
|
+
}
|
|
282
|
+
const hash = createHash("sha256");
|
|
283
|
+
const files = [];
|
|
284
|
+
for (const file of findYamlFiles(source.dir)) {
|
|
285
|
+
const relativePath = path.relative(source.dir, file);
|
|
286
|
+
hash.update(relativePath);
|
|
287
|
+
hash.update("\0");
|
|
288
|
+
let content;
|
|
289
|
+
try {
|
|
290
|
+
content = fs.readFileSync(file, "utf8");
|
|
291
|
+
} catch {
|
|
292
|
+
hash.update("missing");
|
|
293
|
+
hash.update("\0");
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
hash.update(content);
|
|
297
|
+
hash.update("\0");
|
|
298
|
+
const documents = parseRuleDocuments(content);
|
|
299
|
+
if (source.origin === "user" && documents.some((document) => !document.id)) {
|
|
300
|
+
recordDegradationOnce({
|
|
301
|
+
kind: "ast-grep-rule-invalid",
|
|
302
|
+
subject: file,
|
|
303
|
+
reason: "user ast-grep rule has no valid rule id"
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
files.push({ file, relativePath, documents });
|
|
307
|
+
}
|
|
308
|
+
const snapshot = { ...source, files, digest: hash.digest("hex") };
|
|
309
|
+
if (source.origin === "bundled")
|
|
310
|
+
bundledSnapshots.set(cacheKey, snapshot);
|
|
311
|
+
return snapshot;
|
|
312
|
+
}
|
|
313
|
+
function sourceFingerprint(sources) {
|
|
314
|
+
const hash = createHash("sha256");
|
|
315
|
+
for (const source of sources) {
|
|
316
|
+
hash.update(source.origin);
|
|
317
|
+
hash.update("\0");
|
|
318
|
+
hash.update(source.tier);
|
|
319
|
+
hash.update("\0");
|
|
320
|
+
hash.update(canonicalDir(source.dir));
|
|
321
|
+
hash.update("\0");
|
|
322
|
+
hash.update(source.digest);
|
|
323
|
+
hash.update("\0");
|
|
324
|
+
}
|
|
325
|
+
return hash.digest("hex");
|
|
326
|
+
}
|
|
327
|
+
function getAstGrepRuleFingerprint(projectRoot = process.cwd(), options = {}) {
|
|
328
|
+
const root = path.resolve(projectRoot || process.cwd());
|
|
329
|
+
return ruleCorpusFingerprintForCycle("ast-grep", root, (fingerprintRoot) => sourceFingerprint(getAstGrepRuleSources(fingerprintRoot).map(snapshotRuleSource)), options.force);
|
|
330
|
+
}
|
|
331
|
+
function materializeMergedRuleDir(sources, mergedDir) {
|
|
332
|
+
fs.rmSync(mergedDir, { recursive: true, force: true });
|
|
333
|
+
fs.mkdirSync(mergedDir, { recursive: true });
|
|
334
|
+
const claimedByEarlierSource = /* @__PURE__ */ new Set();
|
|
335
|
+
for (const [sourceIndex, source] of sources.entries()) {
|
|
336
|
+
const claimedThisSource = /* @__PURE__ */ new Set();
|
|
337
|
+
for (const [fileIndex, file] of source.files.entries()) {
|
|
338
|
+
const survivingDocuments = file.documents.filter((document) => {
|
|
339
|
+
if (!document.id)
|
|
340
|
+
return true;
|
|
341
|
+
if (claimedByEarlierSource.has(document.id))
|
|
342
|
+
return false;
|
|
343
|
+
claimedThisSource.add(document.id);
|
|
344
|
+
return true;
|
|
345
|
+
});
|
|
346
|
+
if (survivingDocuments.length === 0)
|
|
347
|
+
continue;
|
|
348
|
+
const destination = path.join(mergedDir, `source${sourceIndex}-${String(fileIndex).padStart(5, "0")}.yml`);
|
|
349
|
+
if (survivingDocuments.length === file.documents.length) {
|
|
350
|
+
fs.copyFileSync(file.file, destination);
|
|
351
|
+
} else {
|
|
352
|
+
fs.writeFileSync(destination, `${survivingDocuments.map((document) => document.raw.trim()).join("\n---\n")}
|
|
353
|
+
`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
for (const id of claimedThisSource)
|
|
357
|
+
claimedByEarlierSource.add(id);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
var cachedBaselines = /* @__PURE__ */ new Map();
|
|
361
|
+
function rootArtifactKey(root) {
|
|
362
|
+
return createHash("sha256").update(root).digest("hex").slice(0, 12);
|
|
363
|
+
}
|
|
364
|
+
function resolveBaselineSgconfig(projectRoot = process.cwd()) {
|
|
365
|
+
const root = canonicalDir(path.resolve(projectRoot || process.cwd()));
|
|
366
|
+
const fingerprint = getAstGrepRuleFingerprint(root, { force: true });
|
|
367
|
+
const cached = cachedBaselines.get(root);
|
|
368
|
+
if (cached?.fingerprint === fingerprint && fs.existsSync(cached.path) && fs.existsSync(cached.mergedDir)) {
|
|
369
|
+
return cached.path;
|
|
370
|
+
}
|
|
371
|
+
const sources = getAstGrepRuleSources(root).map(snapshotRuleSource);
|
|
372
|
+
if (sources.length === 0)
|
|
373
|
+
return void 0;
|
|
374
|
+
const dir = path.join(os.tmpdir(), "pi-lens-ast-grep");
|
|
375
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
376
|
+
const artifactKey = rootArtifactKey(root);
|
|
377
|
+
const file = path.join(dir, `baseline-${process.pid}-${artifactKey}.sgconfig.yml`);
|
|
378
|
+
const mergedDir = path.join(dir, `baseline-${process.pid}-${artifactKey}.rules`);
|
|
379
|
+
const protectedArtifacts = /* @__PURE__ */ new Set([file, mergedDir]);
|
|
380
|
+
for (const baseline of cachedBaselines.values()) {
|
|
381
|
+
protectedArtifacts.add(baseline.path);
|
|
382
|
+
protectedArtifacts.add(baseline.mergedDir);
|
|
383
|
+
}
|
|
384
|
+
cleanupStaleBaselines(dir, protectedArtifacts);
|
|
385
|
+
materializeMergedRuleDir(sources, mergedDir);
|
|
386
|
+
const ruleDirForYaml = mergedDir.split(path.sep).join("/");
|
|
387
|
+
fs.writeFileSync(file, `ruleDirs:
|
|
388
|
+
- ${JSON.stringify(ruleDirForYaml)}
|
|
389
|
+
`);
|
|
390
|
+
cachedBaselines.set(root, { fingerprint, path: file, mergedDir });
|
|
391
|
+
enforceBaselineEntryCap(dir, /* @__PURE__ */ new Set([file, mergedDir]));
|
|
392
|
+
return file;
|
|
393
|
+
}
|
|
394
|
+
var SG_BASELINE_RETAINED_ENTRIES = 24;
|
|
395
|
+
function enforceBaselineEntryCap(dir, keep) {
|
|
396
|
+
let names;
|
|
397
|
+
try {
|
|
398
|
+
names = fs.readdirSync(dir);
|
|
399
|
+
} catch {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
const candidates = [];
|
|
403
|
+
for (const name of names) {
|
|
404
|
+
const isConfig = /^baseline(?:-\d+(?:-[a-f0-9]+)?)?\.sgconfig\.yml$/.test(name);
|
|
405
|
+
const isMergedDir = /^baseline-\d+(?:-[a-f0-9]+)?\.rules$/.test(name);
|
|
406
|
+
if (!isConfig && !isMergedDir)
|
|
407
|
+
continue;
|
|
408
|
+
const full = path.join(dir, name);
|
|
409
|
+
if (keep.has(full))
|
|
410
|
+
continue;
|
|
411
|
+
try {
|
|
412
|
+
candidates.push({
|
|
413
|
+
full,
|
|
414
|
+
mtimeMs: fs.statSync(full).mtimeMs,
|
|
415
|
+
recursive: isMergedDir
|
|
416
|
+
});
|
|
417
|
+
} catch {
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
const over = candidates.length + keep.size - SG_BASELINE_RETAINED_ENTRIES;
|
|
421
|
+
if (over <= 0)
|
|
422
|
+
return;
|
|
423
|
+
candidates.sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
424
|
+
let evicted = 0;
|
|
425
|
+
for (const candidate of candidates.slice(0, over)) {
|
|
426
|
+
try {
|
|
427
|
+
fs.rmSync(candidate.full, {
|
|
428
|
+
recursive: candidate.recursive,
|
|
429
|
+
force: true
|
|
430
|
+
});
|
|
431
|
+
evicted += 1;
|
|
432
|
+
for (const [root, baseline] of cachedBaselines) {
|
|
433
|
+
if (baseline.path === candidate.full || baseline.mergedDir === candidate.full) {
|
|
434
|
+
cachedBaselines.delete(root);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
} catch {
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if (evicted > 0) {
|
|
441
|
+
recordDegradationOnce({
|
|
442
|
+
kind: "sgconfig-baseline-cap-evict",
|
|
443
|
+
subject: dir,
|
|
444
|
+
reason: `evicted ${evicted} oldest baseline entries over the ${SG_BASELINE_RETAINED_ENTRIES}-entry cap`
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
function cleanupStaleBaselines(dir, keep) {
|
|
449
|
+
try {
|
|
450
|
+
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
451
|
+
for (const name of fs.readdirSync(dir)) {
|
|
452
|
+
const isConfig = /^baseline(?:-\d+(?:-[a-f0-9]+)?)?\.sgconfig\.yml$/.test(name);
|
|
453
|
+
const isMergedDir = /^baseline-\d+(?:-[a-f0-9]+)?\.rules$/.test(name);
|
|
454
|
+
if (!isConfig && !isMergedDir)
|
|
455
|
+
continue;
|
|
456
|
+
const full = path.join(dir, name);
|
|
457
|
+
if (keep.has(full))
|
|
458
|
+
continue;
|
|
459
|
+
try {
|
|
460
|
+
const stat2 = fs.statSync(full);
|
|
461
|
+
if (stat2.mtimeMs < cutoff) {
|
|
462
|
+
fs.rmSync(full, { recursive: stat2.isDirectory(), force: true });
|
|
463
|
+
}
|
|
464
|
+
} catch {
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
} catch {
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// dist/clients/typos-config.js
|
|
472
|
+
var LOCAL_TYPOS_CONFIG_NAMES = [
|
|
473
|
+
"typos.toml",
|
|
474
|
+
"_typos.toml",
|
|
475
|
+
".typos.toml"
|
|
476
|
+
];
|
|
477
|
+
function findLocalTyposConfig(startDir) {
|
|
478
|
+
return findLocalToolConfig(startDir, LOCAL_TYPOS_CONFIG_NAMES);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// dist/clients/lsp/config.js
|
|
482
|
+
import * as os3 from "node:os";
|
|
483
|
+
import path4 from "node:path";
|
|
484
|
+
|
|
485
|
+
// dist/clients/dispatch/known-runner-ids.js
|
|
486
|
+
var knownRunnerIds = /* @__PURE__ */ new Set();
|
|
487
|
+
function registerRunnerId(id) {
|
|
488
|
+
knownRunnerIds.add(id);
|
|
489
|
+
}
|
|
490
|
+
function runnerIdentityPopulated() {
|
|
491
|
+
return knownRunnerIds.size > 0;
|
|
492
|
+
}
|
|
493
|
+
function isKnownRunnerId(id) {
|
|
494
|
+
return knownRunnerIds.has(id);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// dist/clients/lsp/launch.js
|
|
498
|
+
import { execFileSync, spawn as nodeSpawn } from "node:child_process";
|
|
499
|
+
import fs3 from "node:fs";
|
|
500
|
+
import os2 from "node:os";
|
|
501
|
+
import path2 from "node:path";
|
|
502
|
+
|
|
503
|
+
// dist/clients/lsp/ruby-drive-dirs.js
|
|
504
|
+
import * as fs2 from "node:fs";
|
|
505
|
+
var RUBY_VERSION_DIR = /^ruby\d/i;
|
|
506
|
+
var rubyDirNamesCache = new BoundedLruCache(16);
|
|
507
|
+
function rubyDriveKey(driveRoot) {
|
|
508
|
+
return normalizeMapKey(driveRoot);
|
|
509
|
+
}
|
|
510
|
+
function filterRubyDirNames(entries) {
|
|
511
|
+
return entries.filter((name) => RUBY_VERSION_DIR.test(name));
|
|
512
|
+
}
|
|
513
|
+
function getRubyVersionDirNamesSync(driveRoot) {
|
|
514
|
+
const key = rubyDriveKey(driveRoot);
|
|
515
|
+
const cached = rubyDirNamesCache.get(key);
|
|
516
|
+
if (cached !== void 0)
|
|
517
|
+
return cached;
|
|
518
|
+
let names;
|
|
519
|
+
try {
|
|
520
|
+
names = filterRubyDirNames(fs2.readdirSync(driveRoot));
|
|
521
|
+
} catch {
|
|
522
|
+
names = [];
|
|
523
|
+
}
|
|
524
|
+
rubyDirNamesCache.set(key, names);
|
|
525
|
+
return names;
|
|
526
|
+
}
|
|
527
|
+
async function getRubyVersionDirNamesAsync(driveRoot) {
|
|
528
|
+
const key = rubyDriveKey(driveRoot);
|
|
529
|
+
const cached = rubyDirNamesCache.get(key);
|
|
530
|
+
if (cached !== void 0)
|
|
531
|
+
return cached;
|
|
532
|
+
let names;
|
|
533
|
+
try {
|
|
534
|
+
names = filterRubyDirNames(await fs2.promises.readdir(driveRoot));
|
|
535
|
+
} catch {
|
|
536
|
+
names = [];
|
|
537
|
+
}
|
|
538
|
+
rubyDirNamesCache.set(key, names);
|
|
539
|
+
return names;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// dist/clients/lsp/launch.js
|
|
543
|
+
var isWindows = process.platform === "win32";
|
|
544
|
+
var OWNER_TAG_READ_MS = 5e3;
|
|
545
|
+
function computeNeedsShell(resolvedCommand) {
|
|
546
|
+
return isWindows && (resolvedCommand.includes(" ") || /\.(cmd|bat)$/i.test(resolvedCommand) || !/\.(exe|cmd|bat)$/i.test(resolvedCommand));
|
|
547
|
+
}
|
|
548
|
+
var DEFAULT_STARTUP_FAILURE_WINDOW_MS = 50;
|
|
549
|
+
var WINDOWS_NAV_STARTUP_FAILURE_WINDOW_MS = 500;
|
|
550
|
+
var SESSIONSTART_LOG_DIR = getGlobalPiLensLogDir();
|
|
551
|
+
var SESSIONSTART_LOG = path2.join(SESSIONSTART_LOG_DIR, "sessionstart.log");
|
|
552
|
+
var PI_LENS_BIN_DIR = path2.join(getGlobalPiLensDir(), "bin");
|
|
553
|
+
var PI_LENS_TOOLS_BIN_DIR = path2.join(getGlobalPiLensDir(), "tools", "node_modules", ".bin");
|
|
554
|
+
function logSessionStart2(msg) {
|
|
555
|
+
if (isTestMode()) {
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
const line = redactSecrets(`[${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}
|
|
559
|
+
`);
|
|
560
|
+
try {
|
|
561
|
+
fs3.mkdirSync(SESSIONSTART_LOG_DIR, { recursive: true });
|
|
562
|
+
fs3.appendFileSync(SESSIONSTART_LOG, line);
|
|
563
|
+
} catch {
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
function compactLogValue(value, max = 280) {
|
|
567
|
+
const normalized = value.replace(/\s+/g, " ").trim();
|
|
568
|
+
if (!normalized)
|
|
569
|
+
return "";
|
|
570
|
+
return normalized.length > max ? `${normalized.slice(0, max)}...` : normalized;
|
|
571
|
+
}
|
|
572
|
+
function delimiterForPlatform(platform) {
|
|
573
|
+
return platform === "win32" ? ";" : ":";
|
|
574
|
+
}
|
|
575
|
+
function splitPathEntries(value, delimiter) {
|
|
576
|
+
if (!value)
|
|
577
|
+
return [];
|
|
578
|
+
return value.split(delimiter).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
579
|
+
}
|
|
580
|
+
function normalizePathEntry(entry, platform) {
|
|
581
|
+
if (platform !== "win32")
|
|
582
|
+
return path2.posix.normalize(entry);
|
|
583
|
+
return path2.win32.normalize(entry).toLowerCase();
|
|
584
|
+
}
|
|
585
|
+
function combinePathValuesForPlatform(values, platform = process.platform) {
|
|
586
|
+
const unique = [];
|
|
587
|
+
const seen = /* @__PURE__ */ new Set();
|
|
588
|
+
const delimiter = delimiterForPlatform(platform);
|
|
589
|
+
for (const value of values) {
|
|
590
|
+
for (const entry of splitPathEntries(value, delimiter)) {
|
|
591
|
+
const key = normalizePathEntry(entry, platform);
|
|
592
|
+
if (seen.has(key))
|
|
593
|
+
continue;
|
|
594
|
+
seen.add(key);
|
|
595
|
+
unique.push(entry);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return unique.join(delimiter);
|
|
599
|
+
}
|
|
600
|
+
function resolvePathValue(env) {
|
|
601
|
+
return combinePathValuesForPlatform([env.PATH, env.Path, env.path]);
|
|
602
|
+
}
|
|
603
|
+
function runStderrGuardedProbe(command, args) {
|
|
604
|
+
try {
|
|
605
|
+
const { execFileSync: execFileSync2 } = __require("node:child_process");
|
|
606
|
+
const out = execFileSync2(command, args, {
|
|
607
|
+
timeout: 3e3,
|
|
608
|
+
encoding: "utf8",
|
|
609
|
+
// #2095 sibling: execFileSync inherits stderr to the parent by
|
|
610
|
+
// default (only stdout is captured into `out`), so a failed
|
|
611
|
+
// powershell.exe launch would print raw diagnostics into the pi
|
|
612
|
+
// TUI even though the surrounding catch already returns "" (read as
|
|
613
|
+
// "unknown" PATH by every caller). Pipe stderr instead of inheriting it.
|
|
614
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
615
|
+
});
|
|
616
|
+
return out.trim();
|
|
617
|
+
} catch {
|
|
618
|
+
return "";
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
function readWindowsRegistryPath() {
|
|
622
|
+
return runStderrGuardedProbe("powershell.exe", [
|
|
623
|
+
"-NoProfile",
|
|
624
|
+
"-NonInteractive",
|
|
625
|
+
"-Command",
|
|
626
|
+
"[System.Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [System.Environment]::GetEnvironmentVariable('Path','User')"
|
|
627
|
+
]);
|
|
628
|
+
}
|
|
629
|
+
var _liveWindowsPath = null;
|
|
630
|
+
function getLiveWindowsPath() {
|
|
631
|
+
if (_liveWindowsPath === null) {
|
|
632
|
+
_liveWindowsPath = readWindowsRegistryPath();
|
|
633
|
+
}
|
|
634
|
+
return _liveWindowsPath;
|
|
635
|
+
}
|
|
636
|
+
async function buildAugmentedPath(basePath) {
|
|
637
|
+
const candidates = [];
|
|
638
|
+
const nodeDir = path2.dirname(process.execPath);
|
|
639
|
+
if (nodeDir) {
|
|
640
|
+
candidates.push(nodeDir);
|
|
641
|
+
}
|
|
642
|
+
if (isWindows) {
|
|
643
|
+
const home = os2.homedir();
|
|
644
|
+
const driveRoot = path2.parse(home).root;
|
|
645
|
+
candidates.push(path2.join(home, ".cargo", "bin"));
|
|
646
|
+
candidates.push(path2.join(home, "go", "bin"));
|
|
647
|
+
candidates.push(path2.join(home, ".dotnet", "tools"));
|
|
648
|
+
candidates.push(PI_LENS_BIN_DIR);
|
|
649
|
+
candidates.push(PI_LENS_TOOLS_BIN_DIR);
|
|
650
|
+
candidates.push(path2.join(driveRoot, "Program Files", "Go", "bin"));
|
|
651
|
+
candidates.push(path2.join(driveRoot, "Go", "bin"));
|
|
652
|
+
for (const entry of await getRubyVersionDirNamesAsync(driveRoot)) {
|
|
653
|
+
candidates.push(path2.join(driveRoot, entry, "bin"));
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
const effectiveBase = isWindows ? combinePathValuesForPlatform([basePath, getLiveWindowsPath()]) : basePath;
|
|
657
|
+
const existing = /* @__PURE__ */ new Set();
|
|
658
|
+
for (const entry of splitPathEntries(effectiveBase, path2.delimiter)) {
|
|
659
|
+
if (!entry)
|
|
660
|
+
continue;
|
|
661
|
+
existing.add(normalizePathEntry(entry, process.platform));
|
|
662
|
+
}
|
|
663
|
+
const toAppend = [];
|
|
664
|
+
for (const candidate of candidates) {
|
|
665
|
+
if (!candidate || !fs3.existsSync(candidate))
|
|
666
|
+
continue;
|
|
667
|
+
const normalized = normalizePathEntry(candidate, process.platform);
|
|
668
|
+
if (existing.has(normalized))
|
|
669
|
+
continue;
|
|
670
|
+
toAppend.push(candidate);
|
|
671
|
+
existing.add(normalized);
|
|
672
|
+
}
|
|
673
|
+
if (toAppend.length === 0)
|
|
674
|
+
return basePath ?? "";
|
|
675
|
+
if (!basePath)
|
|
676
|
+
return toAppend.join(path2.delimiter);
|
|
677
|
+
return `${basePath}${path2.delimiter}${toAppend.join(path2.delimiter)}`;
|
|
678
|
+
}
|
|
679
|
+
function isCmdShimValid(cmdPath) {
|
|
680
|
+
try {
|
|
681
|
+
const content = fs3.readFileSync(cmdPath, "utf-8");
|
|
682
|
+
const match = content.match(/"%~dp0[/\\]\.\.[/\\]((?:[\w./@-]|\\)+\.(?:mjs|cjs|js))"/i);
|
|
683
|
+
if (!match)
|
|
684
|
+
return true;
|
|
685
|
+
const relPath = match[1].replace(/[/\\]/g, path2.sep);
|
|
686
|
+
const target = path2.resolve(path2.dirname(cmdPath), "..", relPath);
|
|
687
|
+
return fs3.existsSync(target);
|
|
688
|
+
} catch {
|
|
689
|
+
return true;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
function bypassPs1OnWindows(ps1Path, args) {
|
|
693
|
+
const cmdPath = `${ps1Path.slice(0, -4)}.cmd`;
|
|
694
|
+
if (fs3.existsSync(cmdPath)) {
|
|
695
|
+
return { command: cmdPath, args, needsShell: true };
|
|
696
|
+
}
|
|
697
|
+
try {
|
|
698
|
+
const content = fs3.readFileSync(ps1Path, "utf-8");
|
|
699
|
+
const match = content.match(/"\$basedir[/\\]\.\.[/\\]((?:[\w./@-]|\\)+\.(?:mjs|cjs|js))"/i);
|
|
700
|
+
if (match) {
|
|
701
|
+
const relPath = match[1].replace(/[/\\]/g, path2.sep);
|
|
702
|
+
const jsPath = path2.resolve(path2.dirname(ps1Path), "..", relPath);
|
|
703
|
+
if (fs3.existsSync(jsPath)) {
|
|
704
|
+
return {
|
|
705
|
+
command: process.execPath,
|
|
706
|
+
args: [jsPath, ...args],
|
|
707
|
+
needsShell: false
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
} catch {
|
|
712
|
+
}
|
|
713
|
+
return void 0;
|
|
714
|
+
}
|
|
715
|
+
function findBinaryOnPath(command, env) {
|
|
716
|
+
try {
|
|
717
|
+
const result = execFileSync(isWindows ? "where" : "which", [command], {
|
|
718
|
+
encoding: "utf-8",
|
|
719
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
720
|
+
env,
|
|
721
|
+
// #1980 population sweep: this was the one synchronous
|
|
722
|
+
// child-process site in the repo with no bound at all. It runs on
|
|
723
|
+
// the LSP server spawn path, so an unresponsive `where`/`which` — a
|
|
724
|
+
// stale network PATH entry is the classic cause — parked the event
|
|
725
|
+
// loop with no ceiling, and read as ordinary compute in
|
|
726
|
+
// `loop_block`. 5s matches `isCommandAvailable`/`findCommand` in
|
|
727
|
+
// clients/safe-spawn.ts, which run these same two binaries.
|
|
728
|
+
timeout: 5e3
|
|
729
|
+
}).split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
730
|
+
for (const candidate of result) {
|
|
731
|
+
if (fs3.existsSync(candidate)) {
|
|
732
|
+
return candidate;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
} catch {
|
|
736
|
+
}
|
|
737
|
+
return void 0;
|
|
738
|
+
}
|
|
739
|
+
function trySpawn(command, args, cwd, env, needsShell) {
|
|
740
|
+
let proc;
|
|
741
|
+
if (needsShell) {
|
|
742
|
+
const escapeCmdArg = (s) => {
|
|
743
|
+
const escaped = s.replace(/([&|<>^()!])/g, "^$1");
|
|
744
|
+
return /[\s"]/.test(escaped) ? `"${escaped.replace(/"/g, '""')}"` : escaped;
|
|
745
|
+
};
|
|
746
|
+
const shellCommand = `"${command}" ${args.map(escapeCmdArg).join(" ")}`;
|
|
747
|
+
proc = nodeSpawn(shellCommand, [], {
|
|
748
|
+
cwd,
|
|
749
|
+
env,
|
|
750
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
751
|
+
detached: !isWindows,
|
|
752
|
+
windowsHide: true,
|
|
753
|
+
shell: true
|
|
754
|
+
});
|
|
755
|
+
} else {
|
|
756
|
+
proc = nodeSpawn(command, args, {
|
|
757
|
+
cwd,
|
|
758
|
+
env,
|
|
759
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
760
|
+
detached: !isWindows,
|
|
761
|
+
windowsHide: isWindows
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
if (!proc.stdin || !proc.stdout || !proc.stderr) {
|
|
765
|
+
throw new Error(`Failed to spawn LSP server: ${command}`);
|
|
766
|
+
}
|
|
767
|
+
if (proc.exitCode !== null || proc.killed) {
|
|
768
|
+
throw new Error(`LSP server ${command} exited immediately (code: ${proc.exitCode}). The binary may be missing or corrupted.`);
|
|
769
|
+
}
|
|
770
|
+
holdOwnChildPid(proc.pid, "lsp-spawn");
|
|
771
|
+
return proc;
|
|
772
|
+
}
|
|
773
|
+
function unrefLspProcessHandles(proc) {
|
|
774
|
+
try {
|
|
775
|
+
proc.unref();
|
|
776
|
+
} catch {
|
|
777
|
+
}
|
|
778
|
+
for (const stream of [proc.stdin, proc.stdout, proc.stderr]) {
|
|
779
|
+
try {
|
|
780
|
+
stream?.unref?.();
|
|
781
|
+
} catch {
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
function _attachErrorHandler(proc, context, logContext, rejectOnImmediateError) {
|
|
786
|
+
let stderrPreview = "";
|
|
787
|
+
let closeLogged = false;
|
|
788
|
+
const onStderr = (chunk) => {
|
|
789
|
+
if (stderrPreview.length >= 4e3)
|
|
790
|
+
return;
|
|
791
|
+
stderrPreview += chunk.toString();
|
|
792
|
+
};
|
|
793
|
+
proc.stderr?.on("data", onStderr);
|
|
794
|
+
proc.on("error", (err) => {
|
|
795
|
+
if (logContext) {
|
|
796
|
+
logSessionStart2("lsp process " + context + ": spawn-error command=" + logContext.command + " args=" + JSON.stringify(logContext.args) + " cwd=" + logContext.cwd + " pid=" + (logContext.pid ?? 0) + " error=" + err.message + (stderrPreview ? " stderr=" + compactLogValue(stderrPreview) : ""));
|
|
797
|
+
}
|
|
798
|
+
if (rejectOnImmediateError && logContext) {
|
|
799
|
+
void classifySpawnFailure(err, {
|
|
800
|
+
command: logContext.command,
|
|
801
|
+
cwd: logContext.cwd
|
|
802
|
+
}).then(rejectOnImmediateError);
|
|
803
|
+
}
|
|
804
|
+
});
|
|
805
|
+
proc.on("close", (code, signal) => {
|
|
806
|
+
if (closeLogged)
|
|
807
|
+
return;
|
|
808
|
+
closeLogged = true;
|
|
809
|
+
proc.stderr?.off("data", onStderr);
|
|
810
|
+
if (code !== 0 && code !== null) {
|
|
811
|
+
if (logContext) {
|
|
812
|
+
logSessionStart2("lsp process " + context + ": closed code=" + code + (signal ? " signal=" + signal : "") + " command=" + logContext.command + " args=" + JSON.stringify(logContext.args) + " cwd=" + logContext.cwd + " pid=" + (logContext.pid ?? 0) + (stderrPreview ? " stderr=" + compactLogValue(stderrPreview) : ""));
|
|
813
|
+
}
|
|
814
|
+
} else if (signal && logContext) {
|
|
815
|
+
logSessionStart2("lsp process " + context + ": closed signal=" + signal + " command=" + logContext.command + " args=" + JSON.stringify(logContext.args) + " cwd=" + logContext.cwd + " pid=" + (logContext.pid ?? 0) + (stderrPreview ? " stderr=" + compactLogValue(stderrPreview) : ""));
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
async function launchLSP(command, args = [], options = {}) {
|
|
820
|
+
const cwd = String(options.cwd ?? process.cwd());
|
|
821
|
+
const mergedEnv = { ...process.env, ...options.env };
|
|
822
|
+
const augmentedPath = await buildAugmentedPath(resolvePathValue(mergedEnv));
|
|
823
|
+
const ownerTag = await ownerTagForChildren({ timeoutMs: OWNER_TAG_READ_MS });
|
|
824
|
+
const env = {
|
|
825
|
+
...mergedEnv,
|
|
826
|
+
PATH: augmentedPath,
|
|
827
|
+
...isWindows ? { Path: augmentedPath } : {}
|
|
828
|
+
};
|
|
829
|
+
if (ownerTag === void 0)
|
|
830
|
+
delete env[OWNER_TAG_ENV];
|
|
831
|
+
else
|
|
832
|
+
env[OWNER_TAG_ENV] = ownerTag;
|
|
833
|
+
const isRelativePath = !isFullyQualified(command) && (command.includes(path2.sep) || command.includes("/"));
|
|
834
|
+
const explicitCommand = isRelativePath ? path2.resolve(cwd, command) : command;
|
|
835
|
+
const resolvedCommand = !isFullyQualified(command) && !command.includes(path2.sep) && !command.includes("/") ? findBinaryOnPath(command, env) ?? explicitCommand : explicitCommand;
|
|
836
|
+
let needsShell = computeNeedsShell(resolvedCommand);
|
|
837
|
+
let spawnCommand = resolvedCommand;
|
|
838
|
+
if (!isFullyQualified(command) && !command.includes(path2.sep) && !command.includes("/")) {
|
|
839
|
+
const globalBinPath = await findGlobalBinary(command);
|
|
840
|
+
if (globalBinPath) {
|
|
841
|
+
spawnCommand = globalBinPath;
|
|
842
|
+
needsShell = computeNeedsShell(spawnCommand);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
if (isWindows && /\.(cmd|bat)$/i.test(spawnCommand) && !isCmdShimValid(spawnCommand)) {
|
|
846
|
+
logSessionStart2(`lsp cmd-shim-invalid: ${spawnCommand} target missing \u2014 skipping candidate`);
|
|
847
|
+
const cause = Object.assign(new Error(`LSP .cmd shim target not found: ${spawnCommand}`), { code: "ENOENT" });
|
|
848
|
+
throw await classifySpawnFailure(cause, { command, cwd });
|
|
849
|
+
}
|
|
850
|
+
if (isWindows && /\.ps1$/i.test(spawnCommand)) {
|
|
851
|
+
const bypass = bypassPs1OnWindows(spawnCommand, args);
|
|
852
|
+
if (bypass) {
|
|
853
|
+
logSessionStart2(`lsp ps1-bypass: ${spawnCommand} \u2192 ${bypass.command} shell=${bypass.needsShell}`);
|
|
854
|
+
spawnCommand = bypass.command;
|
|
855
|
+
args = bypass.args;
|
|
856
|
+
needsShell = bypass.needsShell;
|
|
857
|
+
} else {
|
|
858
|
+
logSessionStart2(`lsp ps1-bypass: no .cmd or JS entry found for ${spawnCommand}, spawn may hang`);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
let proc;
|
|
862
|
+
try {
|
|
863
|
+
proc = trySpawn(spawnCommand, args, cwd, env, needsShell);
|
|
864
|
+
} catch (err) {
|
|
865
|
+
if (!isFullyQualified(command) && !command.includes(path2.sep) && !command.includes("/")) {
|
|
866
|
+
const globalBinPath = await findGlobalBinary(command);
|
|
867
|
+
if (globalBinPath && globalBinPath !== spawnCommand) {
|
|
868
|
+
const needsShellGlobal = computeNeedsShell(globalBinPath);
|
|
869
|
+
proc = trySpawn(globalBinPath, args, cwd, env, needsShellGlobal);
|
|
870
|
+
} else {
|
|
871
|
+
throw await classifySpawnFailure(err, { command, cwd });
|
|
872
|
+
}
|
|
873
|
+
} else {
|
|
874
|
+
throw await classifySpawnFailure(err, { command, cwd });
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
if (!proc.stdin || !proc.stdout || !proc.stderr) {
|
|
878
|
+
throw new Error(`Failed to spawn LSP server: ${command}`);
|
|
879
|
+
}
|
|
880
|
+
if (proc.exitCode !== null || proc.killed) {
|
|
881
|
+
throw new Error(`LSP server ${command} exited immediately (code: ${proc.exitCode}). The binary may be missing or corrupted.`);
|
|
882
|
+
}
|
|
883
|
+
logSessionStart2(`lsp launch: command=${command} resolved=${spawnCommand} args=${JSON.stringify(args)} cwd=${cwd} shell=${needsShell ? "true" : "false"} pid=${proc.pid ?? 0}`);
|
|
884
|
+
const formatStartupStderr = (stderr) => {
|
|
885
|
+
const normalized = compactLogValue(stderr);
|
|
886
|
+
if (!normalized)
|
|
887
|
+
return "";
|
|
888
|
+
return ` stderr=${normalized}`;
|
|
889
|
+
};
|
|
890
|
+
let startupStderr = "";
|
|
891
|
+
const onStartupStderr = (chunk) => {
|
|
892
|
+
if (startupStderr.length >= 4e3)
|
|
893
|
+
return;
|
|
894
|
+
startupStderr += chunk.toString();
|
|
895
|
+
};
|
|
896
|
+
proc.stderr?.on("data", onStartupStderr);
|
|
897
|
+
try {
|
|
898
|
+
await new Promise((resolve3, reject) => {
|
|
899
|
+
let settled = false;
|
|
900
|
+
proc.on("error", (err) => {
|
|
901
|
+
if (!settled) {
|
|
902
|
+
settled = true;
|
|
903
|
+
void classifySpawnFailure(err, { command, cwd }).then((failure) => {
|
|
904
|
+
const detail = formatStartupStderr(startupStderr);
|
|
905
|
+
reject(detail ? new SpawnFailureError(failure.kind, `${failure.message}${detail}`, failure.cause) : failure);
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
});
|
|
909
|
+
proc.on("exit", (code) => {
|
|
910
|
+
if (!settled && code !== null) {
|
|
911
|
+
settled = true;
|
|
912
|
+
const isWindowsCmd = isWindows && command.endsWith(".cmd");
|
|
913
|
+
const errorMsg = isWindowsCmd && code === 1 ? `npm .cmd shim failed (underlying binary not installed). Run 'npm install' in this project or use a global installation.` : `The binary may be missing or corrupted.`;
|
|
914
|
+
reject(new Error(`LSP server ${command} exited immediately with code ${code}. ${errorMsg}${formatStartupStderr(startupStderr)}`));
|
|
915
|
+
}
|
|
916
|
+
});
|
|
917
|
+
const startupFailureWindowMs = (() => {
|
|
918
|
+
if (options?.startupFailureWindowMs) {
|
|
919
|
+
return options.startupFailureWindowMs;
|
|
920
|
+
}
|
|
921
|
+
if (isWindows && needsShell) {
|
|
922
|
+
return WINDOWS_NAV_STARTUP_FAILURE_WINDOW_MS;
|
|
923
|
+
}
|
|
924
|
+
return DEFAULT_STARTUP_FAILURE_WINDOW_MS;
|
|
925
|
+
})();
|
|
926
|
+
setTimeout(() => {
|
|
927
|
+
if (!settled) {
|
|
928
|
+
settled = true;
|
|
929
|
+
resolve3();
|
|
930
|
+
}
|
|
931
|
+
}, startupFailureWindowMs);
|
|
932
|
+
});
|
|
933
|
+
} finally {
|
|
934
|
+
proc.stderr?.off("data", onStartupStderr);
|
|
935
|
+
}
|
|
936
|
+
_attachErrorHandler(proc, command, {
|
|
937
|
+
command: spawnCommand,
|
|
938
|
+
args,
|
|
939
|
+
cwd,
|
|
940
|
+
pid: proc.pid ?? 0
|
|
941
|
+
});
|
|
942
|
+
unrefLspProcessHandles(proc);
|
|
943
|
+
return {
|
|
944
|
+
process: proc,
|
|
945
|
+
stdin: proc.stdin,
|
|
946
|
+
stdout: proc.stdout,
|
|
947
|
+
stderr: proc.stderr,
|
|
948
|
+
pid: proc.pid ?? 0,
|
|
949
|
+
command: spawnCommand,
|
|
950
|
+
args
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// dist/clients/lsp/session-roots.js
|
|
955
|
+
import path3 from "node:path";
|
|
956
|
+
var SESSION_ROOT_CAP = 128;
|
|
957
|
+
var sessionRoots = new BoundedFifoMap(SESSION_ROOT_CAP);
|
|
958
|
+
function noteEvictedRoots(evicted) {
|
|
959
|
+
const roots = evicted.map(([root]) => root);
|
|
960
|
+
if (roots.length > 0) {
|
|
961
|
+
incrementDegradationCount({
|
|
962
|
+
kind: "lsp-session-root-evicted",
|
|
963
|
+
subject: `cap=${SESSION_ROOT_CAP}`,
|
|
964
|
+
reason: `session root registry at capacity; will load the dropped root again on the next session start or tool call naming it (dropped: ${roots[0]})`
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
return roots;
|
|
968
|
+
}
|
|
969
|
+
function registerSessionRoot(cwd) {
|
|
970
|
+
const root = path3.resolve(cwd);
|
|
971
|
+
if (sessionRoots.has(root))
|
|
972
|
+
return [];
|
|
973
|
+
return noteEvictedRoots(sessionRoots.set(root, void 0));
|
|
974
|
+
}
|
|
975
|
+
function setSessionRootConfig(cwd, config) {
|
|
976
|
+
return noteEvictedRoots(sessionRoots.set(path3.resolve(cwd), config));
|
|
977
|
+
}
|
|
978
|
+
function sessionRootConfigEntries() {
|
|
979
|
+
return sessionRoots;
|
|
980
|
+
}
|
|
981
|
+
function isSessionRootRegistered(cwd) {
|
|
982
|
+
return sessionRoots.has(path3.resolve(cwd));
|
|
983
|
+
}
|
|
984
|
+
function shouldInitializeSessionRoot(cwd, readyRoots) {
|
|
985
|
+
const normalized = path3.resolve(cwd);
|
|
986
|
+
return !readyRoots.has(normalized) || !isSessionRootRegistered(normalized);
|
|
987
|
+
}
|
|
988
|
+
function isOutsideAllSessionRoots(filePath) {
|
|
989
|
+
if (sessionRoots.size === 0)
|
|
990
|
+
return false;
|
|
991
|
+
const resolved = path3.resolve(filePath);
|
|
992
|
+
for (const root of sessionRoots.keys()) {
|
|
993
|
+
if (isSameOrWithin(root, resolved))
|
|
994
|
+
return false;
|
|
995
|
+
}
|
|
996
|
+
return true;
|
|
997
|
+
}
|
|
998
|
+
function getSessionRootsForTelemetry(limit = 4) {
|
|
999
|
+
return [...sessionRoots.keys()].sort((a, b) => Number(a > b) - Number(a < b)).slice(0, limit);
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
// dist/clients/lsp/config.js
|
|
1003
|
+
function asRecord(value) {
|
|
1004
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
1005
|
+
}
|
|
1006
|
+
var CONFIG_RESOLVED_PHASE = "config_resolved";
|
|
1007
|
+
function configResolutionKey(cwd) {
|
|
1008
|
+
return normalizeFilePath(path4.resolve(normalizeFilePath(cwd)));
|
|
1009
|
+
}
|
|
1010
|
+
function publishConfigResolutionPending(cwd) {
|
|
1011
|
+
logSessionStart(`session_start config_resolution_pending session=${currentSessionRecordId()} root=${configResolutionKey(cwd)}`);
|
|
1012
|
+
}
|
|
1013
|
+
function recordConfigResolved(cwd, resolution, lspConfig, homeDir, resolveMs) {
|
|
1014
|
+
const root = configResolutionKey(cwd);
|
|
1015
|
+
if (!claimPhaseOncePerSession(CONFIG_RESOLVED_PHASE, root)) {
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
const summary = summarizeConfigResolution(resolution, homeDir);
|
|
1019
|
+
const sessionId = currentSessionRecordId();
|
|
1020
|
+
const deniedServers = lspConfig.disabledServers?.length ?? 0;
|
|
1021
|
+
const legacyDocuments = summary.documents.filter((document) => document.legacy).length;
|
|
1022
|
+
logLatency({
|
|
1023
|
+
type: "phase",
|
|
1024
|
+
phase: CONFIG_RESOLVED_PHASE,
|
|
1025
|
+
filePath: root,
|
|
1026
|
+
durationMs: resolveMs,
|
|
1027
|
+
metadata: {
|
|
1028
|
+
sessionId,
|
|
1029
|
+
documents: summary.documents,
|
|
1030
|
+
countsByTier: summary.countsByTier,
|
|
1031
|
+
recordCount: summary.recordCount,
|
|
1032
|
+
deniedServers,
|
|
1033
|
+
resolveMs
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
1036
|
+
logSessionStart(`config resolved documents=${summary.documents.length} legacy=${legacyDocuments} records=${summary.recordCount} deniedServers=${deniedServers} resolveMs=${resolveMs} session=${sessionId} root=${root}`);
|
|
1037
|
+
}
|
|
1038
|
+
async function loadLSPConfig(cwd, homeDir = os3.homedir(), options = {}) {
|
|
1039
|
+
const reporting = options.report !== false;
|
|
1040
|
+
publishConfigResolutionPending(cwd);
|
|
1041
|
+
const resolveStartedAt = Date.now();
|
|
1042
|
+
const resolution = resolvePiLensConfig({
|
|
1043
|
+
cwd,
|
|
1044
|
+
globalDir: getGlobalPiLensDir(),
|
|
1045
|
+
// The global tier reads the PRODUCTION resolution (global-config-location
|
|
1046
|
+
// PR, refs #2457): which file supplies it is an env fact (PI_LENS_CONFIG_PATH,
|
|
1047
|
+
// then a legacy default, then PI_CODING_AGENT_DIR, then the
|
|
1048
|
+
// PI_LENS_HOME-relocated canonical default), not a property of the
|
|
1049
|
+
// `$HOME` this call's project walk is ceiling-bounded by. `homeDir`
|
|
1050
|
+
// stays threaded below for the walk and `globalDir`; a test redirecting
|
|
1051
|
+
// the global tier does it through the env, the same way production is
|
|
1052
|
+
// controlled.
|
|
1053
|
+
globalConfigPath: getPiLensGlobalConfigPath(),
|
|
1054
|
+
homeDir,
|
|
1055
|
+
// The subsystem comes from the failing DOCUMENT, not from this loader
|
|
1056
|
+
// (#2445). This resolution opens `~/.pi-lens/config.json` and
|
|
1057
|
+
// `.pi-lens.json` as well as the LSP-scoped files, and reporting all of
|
|
1058
|
+
// them as `lsp-config` announced an "invalid LSP config" for a file whose
|
|
1059
|
+
// contents are pi-lens settings. An LSP-scoped file still reports here.
|
|
1060
|
+
...reporting ? { onReadError: reportConfigReadFailure } : {}
|
|
1061
|
+
});
|
|
1062
|
+
const coversProblems = newCoversClaimProblems();
|
|
1063
|
+
const config = lspConfigOf(resolution.value, coversProblems);
|
|
1064
|
+
if (reporting) {
|
|
1065
|
+
reportPiLensConfigRecords([
|
|
1066
|
+
...resolution.records,
|
|
1067
|
+
...coversClaimRecords(resolution, coversProblems)
|
|
1068
|
+
]);
|
|
1069
|
+
}
|
|
1070
|
+
recordCoversUnvalidated(resolution, coversProblems);
|
|
1071
|
+
recordConfigResolved(cwd, resolution, config, homeDir, Date.now() - resolveStartedAt);
|
|
1072
|
+
return config;
|
|
1073
|
+
}
|
|
1074
|
+
function newCoversClaimProblems() {
|
|
1075
|
+
return { refusals: [], unvalidated: [] };
|
|
1076
|
+
}
|
|
1077
|
+
function coversPointer(serverId) {
|
|
1078
|
+
return `/${LSP_NAMESPACE_KEY}/servers/${serverId}/covers`;
|
|
1079
|
+
}
|
|
1080
|
+
function coversClaimSource(resolution, pointer) {
|
|
1081
|
+
let candidate = pointer;
|
|
1082
|
+
while (candidate !== void 0) {
|
|
1083
|
+
const entry = resolution.provenance.get(candidate);
|
|
1084
|
+
if (entry) {
|
|
1085
|
+
return {
|
|
1086
|
+
file: entry.file ?? "",
|
|
1087
|
+
...entry.tier ? { tier: entry.tier } : {}
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
const cut = candidate.lastIndexOf("/");
|
|
1091
|
+
candidate = cut > 0 ? candidate.slice(0, cut) : void 0;
|
|
1092
|
+
}
|
|
1093
|
+
return { file: resolution.documents.at(-1)?.file ?? "" };
|
|
1094
|
+
}
|
|
1095
|
+
function coversClaimRecords(resolution, problems) {
|
|
1096
|
+
return problems.refusals.map((refusal) => {
|
|
1097
|
+
const pointer = coversPointer(refusal.serverId);
|
|
1098
|
+
const { file, tier } = coversClaimSource(resolution, pointer);
|
|
1099
|
+
const dropped = refusal.declaredCount - refusal.keptCount;
|
|
1100
|
+
return {
|
|
1101
|
+
code: "PILENS_CFG_0005",
|
|
1102
|
+
file,
|
|
1103
|
+
key: pointer,
|
|
1104
|
+
subject: migrationSubject(file, pointer),
|
|
1105
|
+
reason: `lsp.servers.${refusal.serverId}.covers declares member(s) that are not recognized dispatch runner ids; ${dropped} of ${refusal.declaredCount} member(s) dropped, the server still ` + keptTail(refusal.keptCount),
|
|
1106
|
+
...tier ? { tier } : {}
|
|
1107
|
+
};
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
function keptTail(keptCount) {
|
|
1111
|
+
return keptCount > 0 ? "registers with the remaining covers claim" : "registers with no covers claim";
|
|
1112
|
+
}
|
|
1113
|
+
function recordCoversUnvalidated(resolution, problems) {
|
|
1114
|
+
for (const unvalidated of problems.unvalidated) {
|
|
1115
|
+
const pointer = coversPointer(unvalidated.serverId);
|
|
1116
|
+
const { file } = coversClaimSource(resolution, pointer);
|
|
1117
|
+
recordDegradationOnce({
|
|
1118
|
+
kind: "lsp-covers-unvalidated",
|
|
1119
|
+
subject: `${file}\0${pointer}`,
|
|
1120
|
+
reason: "no runner registry has populated this process yet; the covers claim was accepted without runner-id validation and the next config load validates it",
|
|
1121
|
+
metadata: { pointer }
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
function coversValidatedServers(servers, problems = void 0) {
|
|
1126
|
+
const out = {};
|
|
1127
|
+
for (const [id, raw] of Object.entries(servers)) {
|
|
1128
|
+
const entry = raw;
|
|
1129
|
+
if (!entry.covers?.length) {
|
|
1130
|
+
out[id] = entry;
|
|
1131
|
+
continue;
|
|
1132
|
+
}
|
|
1133
|
+
if (!runnerIdentityPopulated()) {
|
|
1134
|
+
problems?.unvalidated.push({ serverId: id });
|
|
1135
|
+
out[id] = entry;
|
|
1136
|
+
continue;
|
|
1137
|
+
}
|
|
1138
|
+
const kept = [];
|
|
1139
|
+
for (const member of entry.covers) {
|
|
1140
|
+
if (isKnownRunnerId(member))
|
|
1141
|
+
kept.push(member);
|
|
1142
|
+
}
|
|
1143
|
+
if (kept.length === entry.covers.length) {
|
|
1144
|
+
out[id] = entry;
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1147
|
+
problems?.refusals.push({
|
|
1148
|
+
serverId: id,
|
|
1149
|
+
declaredCount: entry.covers.length,
|
|
1150
|
+
keptCount: kept.length
|
|
1151
|
+
});
|
|
1152
|
+
const { covers: _dropped, ...rest } = entry;
|
|
1153
|
+
out[id] = kept.length > 0 ? { ...rest, covers: kept } : rest;
|
|
1154
|
+
}
|
|
1155
|
+
return out;
|
|
1156
|
+
}
|
|
1157
|
+
function customServerSpecsOf(value) {
|
|
1158
|
+
const servers = asRecord(lspSectionOf(value).servers);
|
|
1159
|
+
return servers ? coversValidatedServers(servers) : {};
|
|
1160
|
+
}
|
|
1161
|
+
function lspConfigOf(value, problems) {
|
|
1162
|
+
const section = lspSectionOf(value);
|
|
1163
|
+
const config = {};
|
|
1164
|
+
const servers = asRecord(section.servers);
|
|
1165
|
+
if (servers)
|
|
1166
|
+
config.servers = coversValidatedServers(servers, problems);
|
|
1167
|
+
const serverOverrides = asRecord(section.serverOverrides);
|
|
1168
|
+
if (serverOverrides) {
|
|
1169
|
+
config.serverOverrides = serverOverrides;
|
|
1170
|
+
}
|
|
1171
|
+
if (Array.isArray(section.disabledServers)) {
|
|
1172
|
+
config.disabledServers = section.disabledServers;
|
|
1173
|
+
}
|
|
1174
|
+
if (Array.isArray(section.warmFiles)) {
|
|
1175
|
+
config.warmFiles = section.warmFiles;
|
|
1176
|
+
}
|
|
1177
|
+
return config;
|
|
1178
|
+
}
|
|
1179
|
+
function createCustomServer(config, id) {
|
|
1180
|
+
return {
|
|
1181
|
+
id,
|
|
1182
|
+
name: config.name,
|
|
1183
|
+
custom: true,
|
|
1184
|
+
// The own-command token the runner-coverage seam gates this row's
|
|
1185
|
+
// covers claim on (#3968 F2): the declared covering lane's binary must
|
|
1186
|
+
// be probeable before the claim can defer a CLI runner.
|
|
1187
|
+
command: config.command,
|
|
1188
|
+
extensions: config.extensions,
|
|
1189
|
+
// A config-declared server is a language server. The public
|
|
1190
|
+
// `lsp.servers.<id>.role` field is validated and projected by
|
|
1191
|
+
// `ResolvedLspConfig` (clients/lsp/resolved-config.ts) but stays
|
|
1192
|
+
// RESERVED and inert here: honouring it would change which servers a
|
|
1193
|
+
// file selects as primary, and that is the catalog slice's call, not
|
|
1194
|
+
// this loader's (#2416 slice 1). The stated default is applied rather
|
|
1195
|
+
// than left absent (#1488).
|
|
1196
|
+
role: DEFAULT_LSP_SERVER_ROLE,
|
|
1197
|
+
idleEviction: "unmeasured",
|
|
1198
|
+
// The config-declared covers channel (#3968): the claim the loader
|
|
1199
|
+
// validated (`lspConfigOf`'s projection drops unknown runner ids) rides
|
|
1200
|
+
// the server entry into the runner-coverage seam.
|
|
1201
|
+
...config.covers ? { covers: config.covers } : {},
|
|
1202
|
+
...config.rootMarkers ? { rootMarkers: config.rootMarkers } : {},
|
|
1203
|
+
root: config.rootMarkers ? async (file) => resolveToolCwd("lsp", id, file, {
|
|
1204
|
+
cwd: process.cwd(),
|
|
1205
|
+
...config.rootMarkers ? { rootMarkers: config.rootMarkers } : {}
|
|
1206
|
+
}).cwd : async (file) => resolveToolCwd("lsp", id, file, { cwd: process.cwd() }).cwd,
|
|
1207
|
+
async spawn(root) {
|
|
1208
|
+
const proc = await launchLSP(config.command, config.args ?? ["--stdio"], {
|
|
1209
|
+
cwd: root,
|
|
1210
|
+
env: config.env ? { ...process.env, ...config.env } : process.env
|
|
1211
|
+
});
|
|
1212
|
+
return { process: proc };
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
var EMPTY_CONFIG = {
|
|
1217
|
+
customServers: [],
|
|
1218
|
+
disabledServerIds: /* @__PURE__ */ new Set(),
|
|
1219
|
+
serverOverrides: /* @__PURE__ */ new Map()
|
|
1220
|
+
};
|
|
1221
|
+
var configInFlight = /* @__PURE__ */ new Map();
|
|
1222
|
+
function normalizeWorkspacePath(cwd) {
|
|
1223
|
+
return path4.resolve(cwd);
|
|
1224
|
+
}
|
|
1225
|
+
function isSameOrChildPath(filePath, candidateRoot) {
|
|
1226
|
+
if (filePath === candidateRoot)
|
|
1227
|
+
return true;
|
|
1228
|
+
return filePath.startsWith(`${candidateRoot}${path4.sep}`);
|
|
1229
|
+
}
|
|
1230
|
+
function getConfigForFile(filePath) {
|
|
1231
|
+
const resolvedFilePath = path4.resolve(filePath);
|
|
1232
|
+
let bestMatch;
|
|
1233
|
+
for (const [root, config] of sessionRootConfigEntries()) {
|
|
1234
|
+
if (config === void 0)
|
|
1235
|
+
continue;
|
|
1236
|
+
if (!isSameOrChildPath(resolvedFilePath, root))
|
|
1237
|
+
continue;
|
|
1238
|
+
if (!bestMatch || root.length > bestMatch.root.length) {
|
|
1239
|
+
bestMatch = { root, config };
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
return bestMatch?.config ?? EMPTY_CONFIG;
|
|
1243
|
+
}
|
|
1244
|
+
function registerLSPConfig(config) {
|
|
1245
|
+
const customServers = [];
|
|
1246
|
+
const disabledServerIds = new Set(config.disabledServers ?? []);
|
|
1247
|
+
if (config.servers) {
|
|
1248
|
+
for (const [id, serverConfig] of Object.entries(config.servers)) {
|
|
1249
|
+
try {
|
|
1250
|
+
const server = createCustomServer(serverConfig, id);
|
|
1251
|
+
customServers.push(server);
|
|
1252
|
+
} catch {
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
const serverOverrides = /* @__PURE__ */ new Map();
|
|
1257
|
+
if (config.serverOverrides) {
|
|
1258
|
+
for (const [id, entry] of Object.entries(config.serverOverrides)) {
|
|
1259
|
+
if (entry && typeof entry === "object" && !Array.isArray(entry)) {
|
|
1260
|
+
const initOpts = entry.initializationOptions;
|
|
1261
|
+
if (initOpts !== void 0 && typeof initOpts === "object" && initOpts !== null && !Array.isArray(initOpts)) {
|
|
1262
|
+
serverOverrides.set(id, {
|
|
1263
|
+
initializationOptions: initOpts
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
return { customServers, disabledServerIds, serverOverrides };
|
|
1270
|
+
}
|
|
1271
|
+
function forgetConfigResolvedClaims(evictedRoots) {
|
|
1272
|
+
for (const root of evictedRoots) {
|
|
1273
|
+
releasePhaseClaim(CONFIG_RESOLVED_PHASE, configResolutionKey(root));
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
async function initLSPConfig(cwd) {
|
|
1277
|
+
const normalizedCwd = normalizeWorkspacePath(cwd);
|
|
1278
|
+
forgetConfigResolvedClaims(registerSessionRoot(normalizedCwd));
|
|
1279
|
+
const existing = configInFlight.get(normalizedCwd);
|
|
1280
|
+
if (existing)
|
|
1281
|
+
return existing;
|
|
1282
|
+
const promise = (async () => {
|
|
1283
|
+
const config = registerLSPConfig(await loadLSPConfig(cwd, os3.homedir()));
|
|
1284
|
+
forgetConfigResolvedClaims(setSessionRootConfig(normalizedCwd, config));
|
|
1285
|
+
})();
|
|
1286
|
+
configInFlight.set(normalizedCwd, promise);
|
|
1287
|
+
try {
|
|
1288
|
+
await promise;
|
|
1289
|
+
} finally {
|
|
1290
|
+
if (configInFlight.get(normalizedCwd) === promise) {
|
|
1291
|
+
configInFlight.delete(normalizedCwd);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
function registeredServers(config) {
|
|
1296
|
+
return [...LSP_SERVERS, ...config.customServers];
|
|
1297
|
+
}
|
|
1298
|
+
function selectionReason(server, config, filePath, ext, base) {
|
|
1299
|
+
if (config.disabledServerIds.has(server.id))
|
|
1300
|
+
return "disabled-by-config";
|
|
1301
|
+
let matched = false;
|
|
1302
|
+
for (const value of server.extensions) {
|
|
1303
|
+
const lower = value.toLowerCase();
|
|
1304
|
+
if (lower === ext || lower === base) {
|
|
1305
|
+
matched = true;
|
|
1306
|
+
break;
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
if (!matched)
|
|
1310
|
+
return "extension-mismatch";
|
|
1311
|
+
if (server.pathFilter && !server.pathFilter(filePath))
|
|
1312
|
+
return "path-filter";
|
|
1313
|
+
return "selected";
|
|
1314
|
+
}
|
|
1315
|
+
function explainServersForFile(filePath, config = getConfigForFile(filePath)) {
|
|
1316
|
+
const ext = path4.extname(filePath).toLowerCase();
|
|
1317
|
+
const base = path4.basename(filePath).toLowerCase();
|
|
1318
|
+
return registeredServers(config).map((server) => {
|
|
1319
|
+
const reason = selectionReason(server, config, filePath, ext, base);
|
|
1320
|
+
return { server, selected: reason === "selected", reason };
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
function getServersForFileWithConfig(filePath) {
|
|
1324
|
+
const config = getConfigForFile(filePath);
|
|
1325
|
+
const ext = path4.extname(filePath).toLowerCase();
|
|
1326
|
+
const base = path4.basename(filePath).toLowerCase();
|
|
1327
|
+
return registeredServers(config).filter((server) => selectionReason(server, config, filePath, ext, base) === "selected");
|
|
1328
|
+
}
|
|
1329
|
+
function primaryServerEntry(filePath) {
|
|
1330
|
+
return getServersForFileWithConfig(filePath).find((s) => !isAuxiliary(s));
|
|
1331
|
+
}
|
|
1332
|
+
function primaryServerId(filePath) {
|
|
1333
|
+
return primaryServerEntry(filePath)?.id;
|
|
1334
|
+
}
|
|
1335
|
+
async function resolveLspCwdForFile(filePath, sessionCwd, onRootFallback) {
|
|
1336
|
+
const primary = primaryServerEntry(filePath);
|
|
1337
|
+
if (!primary)
|
|
1338
|
+
return void 0;
|
|
1339
|
+
return resolveLspServerCwd(primary, filePath, sessionCwd, void 0, onRootFallback);
|
|
1340
|
+
}
|
|
1341
|
+
function getServerInitOverride(serverId, filePath) {
|
|
1342
|
+
return getConfigForFile(filePath).serverOverrides.get(serverId);
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
// dist/clients/lsp/wait-policy/strategies.js
|
|
1346
|
+
import { createRequire } from "node:module";
|
|
1347
|
+
var _require = createRequire(import.meta.url);
|
|
1348
|
+
function astGrepNativePackageName(platform, arch) {
|
|
1349
|
+
switch (platform) {
|
|
1350
|
+
case "win32":
|
|
1351
|
+
if (arch === "x64")
|
|
1352
|
+
return "@ast-grep/cli-win32-x64-msvc";
|
|
1353
|
+
if (arch === "arm64")
|
|
1354
|
+
return "@ast-grep/cli-win32-arm64-msvc";
|
|
1355
|
+
if (arch === "ia32")
|
|
1356
|
+
return "@ast-grep/cli-win32-ia32-msvc";
|
|
1357
|
+
return void 0;
|
|
1358
|
+
case "darwin":
|
|
1359
|
+
if (arch === "arm64")
|
|
1360
|
+
return "@ast-grep/cli-darwin-arm64";
|
|
1361
|
+
if (arch === "x64")
|
|
1362
|
+
return "@ast-grep/cli-darwin-x64";
|
|
1363
|
+
return void 0;
|
|
1364
|
+
case "linux":
|
|
1365
|
+
if (arch === "x64")
|
|
1366
|
+
return "@ast-grep/cli-linux-x64-gnu";
|
|
1367
|
+
if (arch === "arm64")
|
|
1368
|
+
return "@ast-grep/cli-linux-arm64-gnu";
|
|
1369
|
+
return void 0;
|
|
1370
|
+
default:
|
|
1371
|
+
return void 0;
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
function resolveAstGrepNativeExe(platform = process.platform, arch = process.arch) {
|
|
1375
|
+
const pkgName = astGrepNativePackageName(platform, arch);
|
|
1376
|
+
if (!pkgName)
|
|
1377
|
+
return void 0;
|
|
1378
|
+
const binaryName = platform === "win32" ? "ast-grep.exe" : "ast-grep";
|
|
1379
|
+
try {
|
|
1380
|
+
return _require.resolve(`${pkgName}/${binaryName}`);
|
|
1381
|
+
} catch {
|
|
1382
|
+
return void 0;
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
var SERVER_DIAGNOSTIC_STRATEGIES = {
|
|
1386
|
+
typescript: {
|
|
1387
|
+
seedFirstPush: true,
|
|
1388
|
+
pullRetryBudgetMs: 0,
|
|
1389
|
+
debounceMs: 50,
|
|
1390
|
+
aggregateWaitMs: 1e3,
|
|
1391
|
+
expectSemanticSecondPush: false,
|
|
1392
|
+
// Tier 3 (#458): typescript-language-server publishes nothing on a
|
|
1393
|
+
// clean→clean edit (docs/lsp-capability-matrix.md, re-confirmed
|
|
1394
|
+
// 2026-07-12). It's the lone core-set tier-3 server, which is exactly
|
|
1395
|
+
// why the cascade lane's in-lane wait is worth skipping for it
|
|
1396
|
+
// specifically. Applies to the CLASSIC server only (#524/#529/#558)
|
|
1397
|
+
// — TS7's native `tsc --lsp --stdio` variant shares this
|
|
1398
|
+
// "typescript" server id but the 2026-07-12 dual-environment
|
|
1399
|
+
// re-measurement found it now publishes on clean (a drift from the
|
|
1400
|
+
// #541 measurement); wait-policy/classification.ts's classifier checks the live
|
|
1401
|
+
// snapshot's launchVariant and never applies this flag to a
|
|
1402
|
+
// native-ts7 instance.
|
|
1403
|
+
silentOnClean: true
|
|
1404
|
+
},
|
|
1405
|
+
"rust-analyzer": {
|
|
1406
|
+
seedFirstPush: false,
|
|
1407
|
+
pullRetryBudgetMs: 500,
|
|
1408
|
+
debounceMs: 150,
|
|
1409
|
+
aggregateWaitMs: 3e3,
|
|
1410
|
+
expectSemanticSecondPush: true
|
|
1411
|
+
},
|
|
1412
|
+
// PythonServer (pyright / basedpyright) — openFilesOnly mode: lazy per-file
|
|
1413
|
+
// analysis, startup similar to jedi. seedFirstPush: true because pyright's
|
|
1414
|
+
// first publishDiagnostics after didOpen is the complete result for that file.
|
|
1415
|
+
python: {
|
|
1416
|
+
seedFirstPush: true,
|
|
1417
|
+
pullRetryBudgetMs: 0,
|
|
1418
|
+
debounceMs: 100,
|
|
1419
|
+
aggregateWaitMs: 1500,
|
|
1420
|
+
expectSemanticSecondPush: false
|
|
1421
|
+
},
|
|
1422
|
+
// jedi-language-server is push-only (no pull diagnostics) and its FIRST
|
|
1423
|
+
// publishDiagnostics is the complete result (seedFirstPush). But that first
|
|
1424
|
+
// push lands just after didOpen+~1s on cold start (Python/parso import) —
|
|
1425
|
+
// measured ~1011ms — so a 1000ms aggregate budget misses it by a hair and
|
|
1426
|
+
// returns zero. 3000ms gives cold-start headroom without stalling the warm path.
|
|
1427
|
+
"python-jedi": {
|
|
1428
|
+
seedFirstPush: true,
|
|
1429
|
+
pullRetryBudgetMs: 0,
|
|
1430
|
+
debounceMs: 100,
|
|
1431
|
+
aggregateWaitMs: 3e3,
|
|
1432
|
+
expectSemanticSecondPush: false
|
|
1433
|
+
},
|
|
1434
|
+
eslint: {
|
|
1435
|
+
seedFirstPush: true,
|
|
1436
|
+
pullRetryBudgetMs: 0,
|
|
1437
|
+
debounceMs: 200,
|
|
1438
|
+
aggregateWaitMs: 2e3,
|
|
1439
|
+
expectSemanticSecondPush: false
|
|
1440
|
+
},
|
|
1441
|
+
// Opengrep security scanner (cross-language LSP). It pushes an EMPTY result
|
|
1442
|
+
// during the one-time rule-load window at startup, then the real scan after
|
|
1443
|
+
// `semgrep/rulesRefreshed` — so never seed the first push. Push-only (no pull
|
|
1444
|
+
// diagnostics). Warm per-file scan ~1.3s; the first touch in a session may
|
|
1445
|
+
// also pay rule-load (~3.5s cold). aggregateWaitMs is 3500: it's this
|
|
1446
|
+
// server's OWN deadline, bounded by the per-edit caller cap as a ceiling
|
|
1447
|
+
// (#242), so on a 2500ms-capped edit opengrep waits min(2500, 3500)=2500
|
|
1448
|
+
// and on uncapped paths it gets its full 3500. 3500 covers warm and most
|
|
1449
|
+
// cold; a cold scan that overruns isn't lost — late diagnostics are cached
|
|
1450
|
+
// and surface on the next unchanged-content read through the content-bound
|
|
1451
|
+
// auxiliary carry-over path.
|
|
1452
|
+
opengrep: {
|
|
1453
|
+
seedFirstPush: false,
|
|
1454
|
+
pullRetryBudgetMs: 0,
|
|
1455
|
+
debounceMs: 250,
|
|
1456
|
+
aggregateWaitMs: 3500,
|
|
1457
|
+
expectSemanticSecondPush: false,
|
|
1458
|
+
// Opengrep re-scans only on a fresh didOpen — didChange is a no-op for it.
|
|
1459
|
+
reopenOnResync: true,
|
|
1460
|
+
rescansOnSave: true
|
|
1461
|
+
},
|
|
1462
|
+
// ast-grep structural linter (sgconfig-gated auxiliary LSP). Push-only,
|
|
1463
|
+
// compiles the project rules on the first scan of a session, and — like
|
|
1464
|
+
// Opengrep — is re-synced via didClose+didOpen so edits trigger a re-scan.
|
|
1465
|
+
// Conservative budget until measured against real projects (#239).
|
|
1466
|
+
// ast-grep re-scans on didChange (verified: toggling the violation count
|
|
1467
|
+
// 3→1→4→2 returns the correct fresh count each touch, with matching doc
|
|
1468
|
+
// versions), so reopen isn't needed and didChange is the lighter path.
|
|
1469
|
+
// aggregateWaitMs is 1800: its warm scan is ~1.3s, so 1000 was under-budgeted
|
|
1470
|
+
// (only masked before because the old with-auxiliary deadline was a global
|
|
1471
|
+
// max() floor; now each server has its own caller-cap-bounded deadline, #242,
|
|
1472
|
+
// so the budget must actually cover the scan).
|
|
1473
|
+
"ast-grep": {
|
|
1474
|
+
seedFirstPush: false,
|
|
1475
|
+
pullRetryBudgetMs: 0,
|
|
1476
|
+
debounceMs: 150,
|
|
1477
|
+
aggregateWaitMs: 1800,
|
|
1478
|
+
expectSemanticSecondPush: false,
|
|
1479
|
+
reopenOnResync: false
|
|
1480
|
+
},
|
|
1481
|
+
// zizmor (GitHub Actions security scanner, auxiliary LSP #272). Push-only
|
|
1482
|
+
// (no pull diagnostics). Its audit set is compiled-in — there's no rule-load
|
|
1483
|
+
// window like Opengrep — so the FIRST publishDiagnostics after didOpen IS the
|
|
1484
|
+
// complete result: seedFirstPush. It re-scans on didChange (FULL sync), so no
|
|
1485
|
+
// reopen-on-resync. A native single-workflow audit is sub-second offline;
|
|
1486
|
+
// online mode may add a GitHub-API round-trip, so 2000ms gives headroom
|
|
1487
|
+
// (bounded by the per-edit caller cap as a ceiling, #242), and any late online
|
|
1488
|
+
// finding can surface on the next unchanged-content read through the
|
|
1489
|
+
// content-bound auxiliary carry-over path.
|
|
1490
|
+
zizmor: {
|
|
1491
|
+
seedFirstPush: true,
|
|
1492
|
+
pullRetryBudgetMs: 0,
|
|
1493
|
+
debounceMs: 150,
|
|
1494
|
+
aggregateWaitMs: 2e3,
|
|
1495
|
+
expectSemanticSecondPush: false,
|
|
1496
|
+
reopenOnResync: false,
|
|
1497
|
+
// #3548: zizmor@main `crates/zizmor/src/lsp.rs` `initialized()`
|
|
1498
|
+
// registers `textDocument/didSave` DYNAMICALLY (`include_text: true`),
|
|
1499
|
+
// and `did_save` re-audits and republishes with `version: None` — the
|
|
1500
|
+
// same surplus shape as opengrep's static save rescan (#3482). This is
|
|
1501
|
+
// presently INERT: `applyDynamicCapabilities` (client.ts) does not map
|
|
1502
|
+
// a dynamic didSave registration to anything, and `negotiateSaveOptions`
|
|
1503
|
+
// (sync-kind.ts) reads only the static `initialize` reply, so
|
|
1504
|
+
// `state.saveOptions` never gets set for zizmor and `sendDidSave` never
|
|
1505
|
+
// fires (its `if (!save) return;` guard). Set now anyway, measured
|
|
1506
|
+
// fact style (like `silentOnClean`'s launch-variant scoping above): the
|
|
1507
|
+
// day dynamic registration is honoured, this is the correct value with
|
|
1508
|
+
// no further plumbing, and `expectSaveRescan`/`rescansOnSave`'s
|
|
1509
|
+
// counting logic does not care how `saveOptions` got set — proven by
|
|
1510
|
+
// `ZIZMOR-SAVE-RESCAN-EXPECTED` in
|
|
1511
|
+
// tests/clients/lsp/late-auxiliary-findings.test.ts, which sets
|
|
1512
|
+
// `state.saveOptions` directly (the same shape as the pre-existing
|
|
1513
|
+
// `SAVE-RESCAN-EXPECTED` opengrep test) rather than through the
|
|
1514
|
+
// unbuilt dynamic-capability path.
|
|
1515
|
+
rescansOnSave: true
|
|
1516
|
+
},
|
|
1517
|
+
// typos (source-code spell checker, auxiliary LSP #283). Push-only (no pull
|
|
1518
|
+
// diagnostics). Its dictionary is compiled in — there's NO rule-load window
|
|
1519
|
+
// like Opengrep — so the FIRST publishDiagnostics after didOpen IS the
|
|
1520
|
+
// complete result: seedFirstPush. It re-scans on didChange (FULL sync), so no
|
|
1521
|
+
// reopen-on-resync. A native single-file spell scan is sub-100ms, so the seed
|
|
1522
|
+
// arrives near-instantly; aggregateWaitMs is a generous ceiling (bounded by
|
|
1523
|
+
// the per-edit caller cap, #242) that the early seed resolves well under.
|
|
1524
|
+
typos: {
|
|
1525
|
+
seedFirstPush: true,
|
|
1526
|
+
pullRetryBudgetMs: 0,
|
|
1527
|
+
debounceMs: 150,
|
|
1528
|
+
aggregateWaitMs: 1500,
|
|
1529
|
+
expectSemanticSecondPush: false,
|
|
1530
|
+
reopenOnResync: false,
|
|
1531
|
+
// #3548: see `publishesOnClose`'s doc comment above — typos'
|
|
1532
|
+
// `did_close` always publishes an empty, version-less set.
|
|
1533
|
+
publishesOnClose: true
|
|
1534
|
+
},
|
|
1535
|
+
// marksman (Markdown LSP, #274). Push-based; native binary so the per-file
|
|
1536
|
+
// parse is fast, but its value is CROSS-file (broken intra-repo links,
|
|
1537
|
+
// missing anchors/heading refs) which needs the workspace index — so the
|
|
1538
|
+
// first push after didOpen can be empty before indexing completes. Don't
|
|
1539
|
+
// seed it (like opengrep/rust-analyzer); a modest 1500ms aggregate covers
|
|
1540
|
+
// warm edits, and any late cross-file finding surfaces on the next touch.
|
|
1541
|
+
marksman: {
|
|
1542
|
+
seedFirstPush: false,
|
|
1543
|
+
pullRetryBudgetMs: 0,
|
|
1544
|
+
debounceMs: 150,
|
|
1545
|
+
aggregateWaitMs: 1500,
|
|
1546
|
+
expectSemanticSecondPush: false,
|
|
1547
|
+
// #645: a full-tree sweep opens every markdown file, all racing the
|
|
1548
|
+
// SAME one-time workspace index build — pay the 1500ms budget once
|
|
1549
|
+
// per sweep (the first markdown file touched), not once per file.
|
|
1550
|
+
// 250ms covers a warm per-file publish (native binary, fast parse)
|
|
1551
|
+
// once the index has already had a full aggregateWaitMs window.
|
|
1552
|
+
workspaceIndexing: true,
|
|
1553
|
+
workspaceIndexingWarmWaitMs: 250,
|
|
1554
|
+
// #799 / run 35914033696: marksman is push-only and publishes NOTHING on
|
|
1555
|
+
// a clean transition — there is no pull fallback and no sync-confirm protocol (unlike
|
|
1556
|
+
// typescript's tsserver commands), so a clean markdown file's touch
|
|
1557
|
+
// waits its full budget with zero signal either way. Marking it
|
|
1558
|
+
// `silentOnClean` lets the generic push-only clean-confirm gate
|
|
1559
|
+
// (`touchFile`, the `classifyCascadeWaitTier`-driven fallback next to
|
|
1560
|
+
// the tsserver sync-confirm block) treat "no publish within budget,
|
|
1561
|
+
// notify succeeded" as CONFIRMED clean instead of inconclusive/timed
|
|
1562
|
+
// out — closing the observed 2x20s-per-sweep burn on clean markdown
|
|
1563
|
+
// (evidence: agents.md timed out at 20009ms/20014ms on both the
|
|
1564
|
+
// warm-up attempt and its retry, with zero diagnostics either time).
|
|
1565
|
+
silentOnClean: true
|
|
1566
|
+
},
|
|
1567
|
+
// cue lsp serve (#1522, #1519, #1520). Measured directly against the real
|
|
1568
|
+
// v0.17.1 binary (`getWorkspaceDiagnosticsSupport` reports
|
|
1569
|
+
// `mode: "push-only"`; no pull support advertised).
|
|
1570
|
+
//
|
|
1571
|
+
// It reports load/parse (syntax) errors as you type, but leaves
|
|
1572
|
+
// conflicting-value/constraint-failure (evaluation) errors to `cue vet`
|
|
1573
|
+
// — the #1522 cue-vet auxiliary runner covers that gap. So the syntax
|
|
1574
|
+
// diagnostics this strategy governs are a REAL but PARTIAL signal, not
|
|
1575
|
+
// full CUE validation.
|
|
1576
|
+
//
|
|
1577
|
+
// The repaired clean-signal probe measured cue as publishing a versioned
|
|
1578
|
+
// clean-transition set (run 35914033696), so this marker stays absent:
|
|
1579
|
+
// the cascade must retain its normal early-publish path.
|
|
1580
|
+
//
|
|
1581
|
+
// seedFirstPush: true — the one cold-open case that DOES publish (a
|
|
1582
|
+
// file that is already broken) sends the complete single diagnostic on
|
|
1583
|
+
// its first push; there is no observed partial-then-complete sequence to
|
|
1584
|
+
// wait out.
|
|
1585
|
+
//
|
|
1586
|
+
// aggregateWaitMs: 2000 covers the measured warm edit-to-publish latency
|
|
1587
|
+
// (~930ms, syntax reparse) with margin; a cold spawn's first push (~2.1s
|
|
1588
|
+
// end-to-end including process start) is bounded separately by
|
|
1589
|
+
// maxClientWaitMs, not this per-diagnostics budget.
|
|
1590
|
+
// intelephense (php, #3310). Measured directly against the real v1.18.5
|
|
1591
|
+
// binary over a raw JSON-RPC session answering `workspace/configuration`
|
|
1592
|
+
// the way pi-lens does (2026-09-23, linux):
|
|
1593
|
+
//
|
|
1594
|
+
// +284ms initialize response — NO diagnosticProvider (push-only)
|
|
1595
|
+
// +295ms publishDiagnostics diags=0 version=undefined <- pre-index
|
|
1596
|
+
// +301ms indexingStarted
|
|
1597
|
+
// +689ms indexingEnded
|
|
1598
|
+
// +696ms publishDiagnostics diags=2 version=undefined <- the answer
|
|
1599
|
+
//
|
|
1600
|
+
// so `emptyFirstPublish: "indexing"`: the first publish is an artifact of
|
|
1601
|
+
// the cold index, not an answer. The same session on a genuinely CLEAN
|
|
1602
|
+
// file publishes `[]` at +304ms and `[]` AGAIN at +663ms (right after
|
|
1603
|
+
// `indexingEnded`), which is what lets the held publish be released by
|
|
1604
|
+
// the server's own second publish instead of by a timer — and a WARM
|
|
1605
|
+
// touch (a second file, index already built) publishes the real set
|
|
1606
|
+
// FIRST at +5ms, so the hold costs nothing once the session is warm.
|
|
1607
|
+
//
|
|
1608
|
+
// seedFirstPush: false — the measurement above is the direct refutation
|
|
1609
|
+
// of "the first push is complete" for this server.
|
|
1610
|
+
// pullRetryBudgetMs: 0 — no pull provider is advertised at all.
|
|
1611
|
+
// aggregateWaitMs: 8000 — the budget must cover the cold index window,
|
|
1612
|
+
// which is what the second (real) publish waits on: ~0.4s for a 139-file
|
|
1613
|
+
// index on the dev box, ~5s on the nightly ubuntu runner (#3217's
|
|
1614
|
+
// transcript). Per-edit callers cap this as a CEILING (#242), so an
|
|
1615
|
+
// interactive edit still waits only its own cap; the uncapped paths (the
|
|
1616
|
+
// tool-smoke LSP gate, which itself caps at 8000ms) get the full budget,
|
|
1617
|
+
// and the cold index is paid once per session, not once per touch.
|
|
1618
|
+
php: {
|
|
1619
|
+
seedFirstPush: false,
|
|
1620
|
+
pullRetryBudgetMs: 0,
|
|
1621
|
+
debounceMs: 150,
|
|
1622
|
+
aggregateWaitMs: 8e3,
|
|
1623
|
+
expectSemanticSecondPush: false,
|
|
1624
|
+
emptyFirstPublish: "indexing",
|
|
1625
|
+
// #3484: the fence reply (+2..4 ms) precedes the publish (~+1 s).
|
|
1626
|
+
diagnosticsFence: "reply-first"
|
|
1627
|
+
},
|
|
1628
|
+
// terraform-ls (#3310). The nightly tool-smoke measurement was identical
|
|
1629
|
+
// on 2026-09-27, 2026-09-28, and 2026-09-29:
|
|
1630
|
+
//
|
|
1631
|
+
// [terraform] clean-behavior=publishes-unversioned (tier 2*)
|
|
1632
|
+
// dirtyPubs=2(v:0) cleanPubs=2(v:0) first-publish=empty-first
|
|
1633
|
+
// provisional pre-index publish
|
|
1634
|
+
//
|
|
1635
|
+
// The first empty, unversioned publish is the cold-index artifact, so hold
|
|
1636
|
+
// it once and let terraform-ls's next publish resolve the wait. A held
|
|
1637
|
+
// clean-only trace therefore reaches the caller as unanswered/indeterminate
|
|
1638
|
+
// at the wait ceiling rather than a false clean, by design (#3310). The
|
|
1639
|
+
// marker is measured policy, not a blanket rule for Tier 2* push servers.
|
|
1640
|
+
terraform: {
|
|
1641
|
+
seedFirstPush: false,
|
|
1642
|
+
pullRetryBudgetMs: 0,
|
|
1643
|
+
debounceMs: 150,
|
|
1644
|
+
aggregateWaitMs: 1500,
|
|
1645
|
+
expectSemanticSecondPush: false,
|
|
1646
|
+
emptyFirstPublish: "indexing"
|
|
1647
|
+
},
|
|
1648
|
+
// yaml-language-server (#3484): the default strategy plus the measured
|
|
1649
|
+
// fence order — reply +3..6 ms, publish +207..242 ms after didChange.
|
|
1650
|
+
yaml: {
|
|
1651
|
+
seedFirstPush: false,
|
|
1652
|
+
pullRetryBudgetMs: 250,
|
|
1653
|
+
debounceMs: 150,
|
|
1654
|
+
aggregateWaitMs: 1500,
|
|
1655
|
+
expectSemanticSecondPush: false,
|
|
1656
|
+
diagnosticsFence: "reply-first"
|
|
1657
|
+
},
|
|
1658
|
+
// Svelte's pull diagnostics settle after the default 1500ms budget on a
|
|
1659
|
+
// cold server. The tool-smoke gate caps waits at 8000ms, so give this
|
|
1660
|
+
// server enough aggregate budget to return its seeded findings (#3311).
|
|
1661
|
+
svelte: {
|
|
1662
|
+
seedFirstPush: false,
|
|
1663
|
+
pullRetryBudgetMs: 0,
|
|
1664
|
+
debounceMs: 150,
|
|
1665
|
+
aggregateWaitMs: 4e3,
|
|
1666
|
+
expectSemanticSecondPush: false
|
|
1667
|
+
},
|
|
1668
|
+
// csharp-ls loads (design-time-builds) the restored project AFTER
|
|
1669
|
+
// `initialize` returns, so the publish for a seeded CS0029 lands inside
|
|
1670
|
+
// `waitForDiagnostics`, not inside the client wait. MEASURED A/B over two
|
|
1671
|
+
// nightly Tool-smoke runs of the same fixture with `dotnet restore` already
|
|
1672
|
+
// done — the ONLY difference between them was this budget:
|
|
1673
|
+
// * `aggregateWaitMs` 1500 (the default): run 36054901266 →
|
|
1674
|
+
// `[csharp] touched=0`, 4.05s after `Restored …/toolsmoke.csproj`.
|
|
1675
|
+
// A real compiler error read as clean.
|
|
1676
|
+
// * 8000: run 36058292424 → `[csharp] touched=1`, 6.49s after the same
|
|
1677
|
+
// line; gate run 36059988117 → `lsp_diagnostics returned 1 primary
|
|
1678
|
+
// finding`, 4.86s after it.
|
|
1679
|
+
// Both windows INCLUDE workspace bootstrap + spawn + initialize, so they
|
|
1680
|
+
// bound the wait from above: the required budget is in (1500, 4860] ms.
|
|
1681
|
+
// 6000 covers the measured gate window with margin and stays under the
|
|
1682
|
+
// tool-smoke gate's own 8000ms ceiling (that relation is pinned by
|
|
1683
|
+
// tests/config/lsp-gate-population.test.ts), so the gate can still witness
|
|
1684
|
+
// this budget. CONFIRMED at 6000 by run 36064829436: `✓ csharp csharp-ls 1
|
|
1685
|
+
// lsp_diagnostics returned 1 primary finding`, 4.78s after `Restored
|
|
1686
|
+
// …csproj`, census unchanged at gated 31 / handshake-only 8 / unavailable 6
|
|
1687
|
+
// — so 6000 is measured as sufficient, not merely inferred from the 8000
|
|
1688
|
+
// runs above. It is deliberately NOT the ceiling: an `lsp_diagnostics` call
|
|
1689
|
+
// that passes no `waitMs` pays this budget in full on a file the server never
|
|
1690
|
+
// publishes for (`tools/lsp-diagnostics.ts` leaves `maxClientWaitMs`
|
|
1691
|
+
// undefined → `perServerTimeout` has no caller cap), so every 1000ms here
|
|
1692
|
+
// is 1000ms of turn latency on the no-publication path (#3402 review r2).
|
|
1693
|
+
// Every other field is DEFAULT_STRATEGY's value on purpose: csharp-ls is
|
|
1694
|
+
// `mode=pull`/tier-1 authoritative-clean (#3311 investigator table), and
|
|
1695
|
+
// nothing has measured its pull retry, so this entry moves the one field
|
|
1696
|
+
// that was measured and no other (pinned in
|
|
1697
|
+
// tests/clients/lsp/server-strategies.test.ts).
|
|
1698
|
+
// fsharp/expert/vue deliberately have NO entry: the same two runs show
|
|
1699
|
+
// `touched=0` at BOTH 1500 and 8000, so the budget is not what stops them
|
|
1700
|
+
// publishing and an 8000 entry would buy nothing while costing every
|
|
1701
|
+
// uncapped production call 6.5 extra seconds. Their fixture rows carry the
|
|
1702
|
+
// observed-behavior exemption instead (`scripts/smoke-tools.mjs`), and a
|
|
1703
|
+
// probe that wants a long window sets `PI_LENS_LSP_DIAGNOSTICS_MAX_WAIT_MS`
|
|
1704
|
+
// — a flat harness override that needs no production budget.
|
|
1705
|
+
csharp: {
|
|
1706
|
+
seedFirstPush: false,
|
|
1707
|
+
pullRetryBudgetMs: 250,
|
|
1708
|
+
debounceMs: 150,
|
|
1709
|
+
aggregateWaitMs: 6e3,
|
|
1710
|
+
expectSemanticSecondPush: false
|
|
1711
|
+
},
|
|
1712
|
+
cue: {
|
|
1713
|
+
seedFirstPush: true,
|
|
1714
|
+
pullRetryBudgetMs: 0,
|
|
1715
|
+
debounceMs: 150,
|
|
1716
|
+
aggregateWaitMs: 2e3,
|
|
1717
|
+
expectSemanticSecondPush: false,
|
|
1718
|
+
reopenOnResync: false
|
|
1719
|
+
},
|
|
1720
|
+
// lua-language-server is push-only and was silent on clean transitions in
|
|
1721
|
+
// the repaired probe (run 35914033696). Keep the marker on the measured
|
|
1722
|
+
// server id so the cascade can skip its in-lane wait safely.
|
|
1723
|
+
lua: {
|
|
1724
|
+
seedFirstPush: true,
|
|
1725
|
+
pullRetryBudgetMs: 0,
|
|
1726
|
+
debounceMs: 150,
|
|
1727
|
+
aggregateWaitMs: 2e3,
|
|
1728
|
+
expectSemanticSecondPush: false,
|
|
1729
|
+
silentOnClean: true
|
|
1730
|
+
}
|
|
1731
|
+
};
|
|
1732
|
+
var NATIVE_TS7_DIAGNOSTIC_STRATEGY = {
|
|
1733
|
+
...SERVER_DIAGNOSTIC_STRATEGIES.typescript,
|
|
1734
|
+
seedFirstPush: false,
|
|
1735
|
+
// Native TS7 demonstrably publishes on clean, so the classic-only marker
|
|
1736
|
+
// must not leak through the shared server id.
|
|
1737
|
+
silentOnClean: false
|
|
1738
|
+
};
|
|
1739
|
+
var DEFAULT_STRATEGY = {
|
|
1740
|
+
seedFirstPush: false,
|
|
1741
|
+
pullRetryBudgetMs: 250,
|
|
1742
|
+
debounceMs: 150,
|
|
1743
|
+
aggregateWaitMs: 1500,
|
|
1744
|
+
expectSemanticSecondPush: false
|
|
1745
|
+
};
|
|
1746
|
+
function getStrategy(serverId, launchVariant) {
|
|
1747
|
+
if (serverId === "typescript" && launchVariant === "native-ts7") {
|
|
1748
|
+
return NATIVE_TS7_DIAGNOSTIC_STRATEGY;
|
|
1749
|
+
}
|
|
1750
|
+
return SERVER_DIAGNOSTIC_STRATEGIES[serverId] ?? DEFAULT_STRATEGY;
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
// dist/clients/lsp/wait-policy/classification.js
|
|
1754
|
+
function classifyServerWaitTier(serverId, snapshot) {
|
|
1755
|
+
if (!snapshot)
|
|
1756
|
+
return "waits";
|
|
1757
|
+
const mode = snapshot.workspaceDiagnosticsSupport?.mode;
|
|
1758
|
+
if (mode === "pull")
|
|
1759
|
+
return "pull-capable";
|
|
1760
|
+
if (snapshot.customServer === true && mode === "push-only" && snapshot.diagnosticsUnsupported === true && snapshot.diagnosticsPublished !== true) {
|
|
1761
|
+
return "diagnostics-unsupported";
|
|
1762
|
+
}
|
|
1763
|
+
if (mode !== "push-only")
|
|
1764
|
+
return "waits";
|
|
1765
|
+
const strategy = getStrategy(serverId, snapshot.launchVariant);
|
|
1766
|
+
if (strategy.silentOnClean !== true)
|
|
1767
|
+
return "waits";
|
|
1768
|
+
if (snapshot.launchVariant === "native-ts7")
|
|
1769
|
+
return "waits";
|
|
1770
|
+
return "tier3-silent";
|
|
1771
|
+
}
|
|
1772
|
+
function resolvePrimaryServerForWaitPolicy(filePath, snapshots) {
|
|
1773
|
+
const servers = getServersForFileWithConfig(filePath).filter((s) => !isAuxiliary(s));
|
|
1774
|
+
const primary = servers[0];
|
|
1775
|
+
if (!primary)
|
|
1776
|
+
return void 0;
|
|
1777
|
+
return {
|
|
1778
|
+
serverId: primary.id,
|
|
1779
|
+
snapshot: snapshots.find((s) => s.serverId === primary.id)
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
function classifyCascadeWaitTier(lspService, filePath, snapshots) {
|
|
1783
|
+
void lspService;
|
|
1784
|
+
const primary = resolvePrimaryServerForWaitPolicy(filePath, snapshots);
|
|
1785
|
+
if (!primary)
|
|
1786
|
+
return "waits";
|
|
1787
|
+
return classifyServerWaitTier(primary.serverId, primary.snapshot);
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
// dist/clients/lsp/lombok.js
|
|
1791
|
+
import * as fs4 from "node:fs";
|
|
1792
|
+
import * as os4 from "node:os";
|
|
1793
|
+
import * as path5 from "node:path";
|
|
1794
|
+
var LOMBOK_ENV_KEYS = ["PI_LENS_LOMBOK_JAR", "LOMBOK_JAR"];
|
|
1795
|
+
var LOMBOK_PROJECT_FILES = [
|
|
1796
|
+
"lombok.config",
|
|
1797
|
+
"pom.xml",
|
|
1798
|
+
"build.gradle",
|
|
1799
|
+
"build.gradle.kts",
|
|
1800
|
+
path5.join("gradle", "libs.versions.toml")
|
|
1801
|
+
];
|
|
1802
|
+
function fileExists(filePath) {
|
|
1803
|
+
if (!filePath)
|
|
1804
|
+
return false;
|
|
1805
|
+
try {
|
|
1806
|
+
return fs4.statSync(filePath).isFile();
|
|
1807
|
+
} catch {
|
|
1808
|
+
return false;
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
function readTextIfSmall(filePath, maxBytes = 512 * 1024) {
|
|
1812
|
+
try {
|
|
1813
|
+
const stat2 = fs4.statSync(filePath);
|
|
1814
|
+
if (!stat2.isFile() || stat2.size > maxBytes)
|
|
1815
|
+
return "";
|
|
1816
|
+
return fs4.readFileSync(filePath, "utf-8");
|
|
1817
|
+
} catch {
|
|
1818
|
+
return "";
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
function containsLombokDependency(text) {
|
|
1822
|
+
return /\borg\.projectlombok\b/i.test(text) || /<artifactId>\s*lombok\s*<\/artifactId>/i.test(text) || /\b(annotationProcessor|compileOnly|testCompileOnly|testAnnotationProcessor)\b[^\n]*\blombok\b/i.test(text);
|
|
1823
|
+
}
|
|
1824
|
+
function hasLombokProject(root) {
|
|
1825
|
+
const lombokConfig = path5.join(root, "lombok.config");
|
|
1826
|
+
if (fileExists(lombokConfig))
|
|
1827
|
+
return true;
|
|
1828
|
+
for (const name of LOMBOK_PROJECT_FILES) {
|
|
1829
|
+
if (name === "lombok.config")
|
|
1830
|
+
continue;
|
|
1831
|
+
const text = readTextIfSmall(path5.join(root, name));
|
|
1832
|
+
if (text && containsLombokDependency(text))
|
|
1833
|
+
return true;
|
|
1834
|
+
}
|
|
1835
|
+
return false;
|
|
1836
|
+
}
|
|
1837
|
+
function envJarCandidate(env) {
|
|
1838
|
+
for (const key of LOMBOK_ENV_KEYS) {
|
|
1839
|
+
const value = env[key]?.trim();
|
|
1840
|
+
if (fileExists(value))
|
|
1841
|
+
return path5.resolve(value);
|
|
1842
|
+
}
|
|
1843
|
+
return void 0;
|
|
1844
|
+
}
|
|
1845
|
+
function localJarCandidates(root) {
|
|
1846
|
+
return [
|
|
1847
|
+
path5.join(root, "lombok.jar"),
|
|
1848
|
+
path5.join(root, ".lombok", "lombok.jar"),
|
|
1849
|
+
path5.join(root, "lib", "lombok.jar"),
|
|
1850
|
+
path5.join(root, "libs", "lombok.jar")
|
|
1851
|
+
];
|
|
1852
|
+
}
|
|
1853
|
+
function newestExistingJar(candidates) {
|
|
1854
|
+
let best;
|
|
1855
|
+
for (const candidate of candidates) {
|
|
1856
|
+
try {
|
|
1857
|
+
const stat2 = fs4.statSync(candidate);
|
|
1858
|
+
if (!stat2.isFile())
|
|
1859
|
+
continue;
|
|
1860
|
+
if (!best || stat2.mtimeMs > best.mtimeMs) {
|
|
1861
|
+
best = { filePath: candidate, mtimeMs: stat2.mtimeMs };
|
|
1862
|
+
}
|
|
1863
|
+
} catch {
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
return best?.filePath;
|
|
1867
|
+
}
|
|
1868
|
+
function mavenLocalLombokJar(home = os4.homedir()) {
|
|
1869
|
+
const base = path5.join(home, ".m2", "repository", "org", "projectlombok", "lombok");
|
|
1870
|
+
let versions = [];
|
|
1871
|
+
try {
|
|
1872
|
+
versions = fs4.readdirSync(base);
|
|
1873
|
+
} catch {
|
|
1874
|
+
return void 0;
|
|
1875
|
+
}
|
|
1876
|
+
return newestExistingJar(versions.map((version) => path5.join(base, version, `lombok-${version}.jar`)));
|
|
1877
|
+
}
|
|
1878
|
+
function gradleCacheLombokJar(home = os4.homedir()) {
|
|
1879
|
+
const base = path5.join(home, ".gradle", "caches", "modules-2", "files-2.1", "org.projectlombok", "lombok");
|
|
1880
|
+
const candidates = [];
|
|
1881
|
+
let versions = [];
|
|
1882
|
+
try {
|
|
1883
|
+
versions = fs4.readdirSync(base);
|
|
1884
|
+
} catch {
|
|
1885
|
+
return void 0;
|
|
1886
|
+
}
|
|
1887
|
+
for (const version of versions) {
|
|
1888
|
+
const versionDir = path5.join(base, version);
|
|
1889
|
+
let hashes = [];
|
|
1890
|
+
try {
|
|
1891
|
+
hashes = fs4.readdirSync(versionDir);
|
|
1892
|
+
} catch {
|
|
1893
|
+
continue;
|
|
1894
|
+
}
|
|
1895
|
+
for (const hash of hashes) {
|
|
1896
|
+
candidates.push(path5.join(versionDir, hash, `lombok-${version}.jar`));
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
return newestExistingJar(candidates);
|
|
1900
|
+
}
|
|
1901
|
+
function resolveLombokJar(root, env = process.env) {
|
|
1902
|
+
const explicit = envJarCandidate(env);
|
|
1903
|
+
if (explicit)
|
|
1904
|
+
return explicit;
|
|
1905
|
+
return newestExistingJar(localJarCandidates(root)) ?? mavenLocalLombokJar() ?? gradleCacheLombokJar();
|
|
1906
|
+
}
|
|
1907
|
+
function hasLombokJavaAgent(jvmArgs) {
|
|
1908
|
+
return /(^|\s)-javaagent:(?:"[^"]*lombok[^"]*\.jar"|\S*lombok\S*\.jar)/i.test(jvmArgs ?? "");
|
|
1909
|
+
}
|
|
1910
|
+
function resolveLombokJavaAgentArg(root, baseEnv = process.env) {
|
|
1911
|
+
if (baseEnv.PI_LENS_JAVA_LOMBOK === "0")
|
|
1912
|
+
return void 0;
|
|
1913
|
+
if (hasLombokJavaAgent(baseEnv.JDTLS_JVM_ARGS))
|
|
1914
|
+
return void 0;
|
|
1915
|
+
const explicitJar = envJarCandidate(baseEnv);
|
|
1916
|
+
if (!explicitJar && !hasLombokProject(root))
|
|
1917
|
+
return void 0;
|
|
1918
|
+
const jar = explicitJar ?? resolveLombokJar(root, baseEnv);
|
|
1919
|
+
return jar ? `-javaagent:${jar}` : void 0;
|
|
1920
|
+
}
|
|
1921
|
+
function createLombokJdtlsArgs(root, baseEnv = process.env) {
|
|
1922
|
+
const javaAgent = resolveLombokJavaAgentArg(root, baseEnv);
|
|
1923
|
+
return javaAgent ? [`--jvm-arg=${javaAgent}`] : [];
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
// dist/clients/lsp/jvm-runtime.js
|
|
1927
|
+
import { existsSync as existsSync2, readdirSync as readdirSync4 } from "node:fs";
|
|
1928
|
+
import os5 from "node:os";
|
|
1929
|
+
import path6 from "node:path";
|
|
1930
|
+
var JAVA_EXE = process.platform === "win32" ? "java.exe" : "java";
|
|
1931
|
+
var JAVA_PROBE_TIMEOUT_MS = 5e3;
|
|
1932
|
+
var MIN_JAVA_MAJOR = 17;
|
|
1933
|
+
function jdkHomeFrom(dir) {
|
|
1934
|
+
if (existsSync2(path6.join(dir, "bin", JAVA_EXE)))
|
|
1935
|
+
return dir;
|
|
1936
|
+
const macHome = path6.join(dir, "Contents", "Home");
|
|
1937
|
+
if (existsSync2(path6.join(macHome, "bin", JAVA_EXE)))
|
|
1938
|
+
return macHome;
|
|
1939
|
+
return void 0;
|
|
1940
|
+
}
|
|
1941
|
+
function parseMajorVersion(name) {
|
|
1942
|
+
const legacy = name.match(/(?<!\d)1\.(\d+)/);
|
|
1943
|
+
if (legacy)
|
|
1944
|
+
return Number.parseInt(legacy[1], 10);
|
|
1945
|
+
const modern = name.match(/(?<!\d)(\d{1,2})/);
|
|
1946
|
+
return modern ? Number.parseInt(modern[1], 10) : 0;
|
|
1947
|
+
}
|
|
1948
|
+
function childDirs(base) {
|
|
1949
|
+
try {
|
|
1950
|
+
return readdirSync4(base, { withFileTypes: true }).filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) => path6.join(base, e.name));
|
|
1951
|
+
} catch {
|
|
1952
|
+
return [];
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
function candidateRoots() {
|
|
1956
|
+
const home = os5.homedir();
|
|
1957
|
+
const roots = [];
|
|
1958
|
+
roots.push(path6.join(home, ".jdks"));
|
|
1959
|
+
roots.push(path6.join(getGlobalPiLensDir(), "tools"));
|
|
1960
|
+
if (process.platform === "win32") {
|
|
1961
|
+
const progFiles = [
|
|
1962
|
+
process.env.ProgramFiles,
|
|
1963
|
+
process.env["ProgramFiles(x86)"],
|
|
1964
|
+
process.env.ProgramW6432,
|
|
1965
|
+
path6.join(process.env.LOCALAPPDATA ?? path6.join(home, "AppData", "Local"), "Programs")
|
|
1966
|
+
].filter((p) => Boolean(p));
|
|
1967
|
+
for (const base of progFiles) {
|
|
1968
|
+
roots.push(path6.join(base, "Eclipse Adoptium"));
|
|
1969
|
+
roots.push(path6.join(base, "Java"));
|
|
1970
|
+
roots.push(path6.join(base, "Microsoft"));
|
|
1971
|
+
roots.push(path6.join(base, "Zulu"));
|
|
1972
|
+
roots.push(path6.join(base, "Amazon Corretto"));
|
|
1973
|
+
roots.push(path6.join(base, "BellSoft"));
|
|
1974
|
+
}
|
|
1975
|
+
} else if (process.platform === "darwin") {
|
|
1976
|
+
roots.push("/Library/Java/JavaVirtualMachines");
|
|
1977
|
+
roots.push(path6.join(home, "Library", "Java", "JavaVirtualMachines"));
|
|
1978
|
+
roots.push("/opt/homebrew/opt");
|
|
1979
|
+
roots.push("/usr/local/opt");
|
|
1980
|
+
} else {
|
|
1981
|
+
roots.push("/usr/lib/jvm");
|
|
1982
|
+
roots.push("/usr/java");
|
|
1983
|
+
roots.push("/opt/java");
|
|
1984
|
+
}
|
|
1985
|
+
return roots;
|
|
1986
|
+
}
|
|
1987
|
+
function discoverJdkHome(roots = candidateRoots(), javaHome = process.env.JAVA_HOME) {
|
|
1988
|
+
const found = [];
|
|
1989
|
+
if (javaHome) {
|
|
1990
|
+
const resolved = jdkHomeFrom(javaHome);
|
|
1991
|
+
if (resolved)
|
|
1992
|
+
found.push({ home: resolved, major: Number.MAX_SAFE_INTEGER });
|
|
1993
|
+
}
|
|
1994
|
+
for (const root of roots) {
|
|
1995
|
+
for (const dir of childDirs(root)) {
|
|
1996
|
+
const resolved = jdkHomeFrom(dir);
|
|
1997
|
+
if (!resolved)
|
|
1998
|
+
continue;
|
|
1999
|
+
found.push({
|
|
2000
|
+
home: resolved,
|
|
2001
|
+
major: parseMajorVersion(path6.basename(dir))
|
|
2002
|
+
});
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
const usable = found.filter((c) => c.major >= MIN_JAVA_MAJOR);
|
|
2006
|
+
if (usable.length === 0)
|
|
2007
|
+
return void 0;
|
|
2008
|
+
usable.sort((a, b) => b.major - a.major);
|
|
2009
|
+
return usable[0].home;
|
|
2010
|
+
}
|
|
2011
|
+
var _cachedEnv;
|
|
2012
|
+
var javaAvailabilityLatch = createAvailabilityLatch();
|
|
2013
|
+
var inFlightJavaProbe = null;
|
|
2014
|
+
function probeJavaOnPath() {
|
|
2015
|
+
const memo = javaAvailabilityLatch.read();
|
|
2016
|
+
if (memo !== null) {
|
|
2017
|
+
if (javaAvailabilityLatch.getOutcome() === "transient") {
|
|
2018
|
+
logAvailabilityDecision({
|
|
2019
|
+
tool: "java",
|
|
2020
|
+
verdict: "unavailable",
|
|
2021
|
+
outcome: "transient",
|
|
2022
|
+
cause: javaAvailabilityLatch.getCause() ?? "probe-timeout",
|
|
2023
|
+
elapsedMs: 0,
|
|
2024
|
+
latched: false,
|
|
2025
|
+
retryAfterMs: Math.max(0, javaAvailabilityLatch.getRetryAtMs() - Date.now()),
|
|
2026
|
+
budgetMs: JAVA_PROBE_TIMEOUT_MS,
|
|
2027
|
+
// No probe ran here: the latch's own remembered cause is replayed
|
|
2028
|
+
// as-is, so the call site is the one asserting it (#2209).
|
|
2029
|
+
classifiedBy: "caller"
|
|
2030
|
+
});
|
|
2031
|
+
return Promise.resolve(void 0);
|
|
2032
|
+
}
|
|
2033
|
+
return Promise.resolve(memo);
|
|
2034
|
+
}
|
|
2035
|
+
if (inFlightJavaProbe)
|
|
2036
|
+
return inFlightJavaProbe;
|
|
2037
|
+
inFlightJavaProbe = runJavaProbe().finally(() => {
|
|
2038
|
+
inFlightJavaProbe = null;
|
|
2039
|
+
});
|
|
2040
|
+
return inFlightJavaProbe;
|
|
2041
|
+
}
|
|
2042
|
+
async function runJavaProbe() {
|
|
2043
|
+
const finder = process.platform === "win32" ? "where" : "which";
|
|
2044
|
+
const startedAt = Date.now();
|
|
2045
|
+
const sampler = startHostStallSampler();
|
|
2046
|
+
let result;
|
|
2047
|
+
let hostStallMs;
|
|
2048
|
+
try {
|
|
2049
|
+
result = await safeSpawnAsync(finder, ["java"], {
|
|
2050
|
+
timeout: JAVA_PROBE_TIMEOUT_MS
|
|
2051
|
+
});
|
|
2052
|
+
} finally {
|
|
2053
|
+
hostStallMs = sampler.stop();
|
|
2054
|
+
}
|
|
2055
|
+
const elapsedMs = Date.now() - startedAt;
|
|
2056
|
+
if (result.status === 0 && !result.error) {
|
|
2057
|
+
javaAvailabilityLatch.noteAvailable();
|
|
2058
|
+
logAvailabilityDecision({
|
|
2059
|
+
tool: "java",
|
|
2060
|
+
verdict: "available",
|
|
2061
|
+
outcome: "success",
|
|
2062
|
+
cause: "ok",
|
|
2063
|
+
elapsedMs,
|
|
2064
|
+
latched: true,
|
|
2065
|
+
hostStallMs,
|
|
2066
|
+
budgetMs: JAVA_PROBE_TIMEOUT_MS,
|
|
2067
|
+
classifiedBy: "probe"
|
|
2068
|
+
});
|
|
2069
|
+
return true;
|
|
2070
|
+
}
|
|
2071
|
+
const { outcome, cause } = classifyProbeFailure(result, {
|
|
2072
|
+
hostStallMs,
|
|
2073
|
+
unclassifiedFailureOutcome: "missing"
|
|
2074
|
+
});
|
|
2075
|
+
const retryAfterMs = javaAvailabilityLatch.noteUnavailable(outcome, cause);
|
|
2076
|
+
logAvailabilityDecision({
|
|
2077
|
+
tool: "java",
|
|
2078
|
+
verdict: "unavailable",
|
|
2079
|
+
outcome,
|
|
2080
|
+
cause,
|
|
2081
|
+
elapsedMs,
|
|
2082
|
+
latched: outcome !== "transient",
|
|
2083
|
+
hostStallMs,
|
|
2084
|
+
...retryAfterMs > 0 && { retryAfterMs },
|
|
2085
|
+
budgetMs: JAVA_PROBE_TIMEOUT_MS,
|
|
2086
|
+
classifiedBy: "probe"
|
|
2087
|
+
});
|
|
2088
|
+
return outcome === "transient" ? void 0 : false;
|
|
2089
|
+
}
|
|
2090
|
+
async function resolveJavaRuntimeEnv() {
|
|
2091
|
+
if (_cachedEnv)
|
|
2092
|
+
return _cachedEnv.value;
|
|
2093
|
+
const javaOnPath = await probeJavaOnPath();
|
|
2094
|
+
if (javaOnPath === true) {
|
|
2095
|
+
_cachedEnv = { value: void 0 };
|
|
2096
|
+
return void 0;
|
|
2097
|
+
}
|
|
2098
|
+
const home = discoverJdkHome();
|
|
2099
|
+
if (home) {
|
|
2100
|
+
const binDir = path6.join(home, "bin");
|
|
2101
|
+
const currentPath = process.env.PATH ?? process.env.Path ?? "";
|
|
2102
|
+
_cachedEnv = {
|
|
2103
|
+
value: {
|
|
2104
|
+
JAVA_HOME: home,
|
|
2105
|
+
PATH: binDir + path6.delimiter + currentPath
|
|
2106
|
+
}
|
|
2107
|
+
};
|
|
2108
|
+
return _cachedEnv.value;
|
|
2109
|
+
}
|
|
2110
|
+
if (javaOnPath === false) {
|
|
2111
|
+
_cachedEnv = { value: void 0 };
|
|
2112
|
+
}
|
|
2113
|
+
return void 0;
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
// dist/clients/lsp/server-covers.js
|
|
2117
|
+
var BUILTIN_SERVER_RUNNER_COVERS = /* @__PURE__ */ new Map([
|
|
2118
|
+
[
|
|
2119
|
+
"bash",
|
|
2120
|
+
{ runnerIds: ["shellcheck"], gateCommands: ["bash-language-server"] }
|
|
2121
|
+
],
|
|
2122
|
+
["shuck", { runnerIds: ["shellcheck"], gateCommands: ["shuck"] }],
|
|
2123
|
+
["toml", { runnerIds: ["taplo"], gateCommands: ["taplo"] }]
|
|
2124
|
+
]);
|
|
2125
|
+
|
|
2126
|
+
// dist/clients/lsp/server.js
|
|
2127
|
+
function withRootMarkers(root, markers) {
|
|
2128
|
+
root.rootMarkers = markers;
|
|
2129
|
+
return root;
|
|
2130
|
+
}
|
|
2131
|
+
function describeRootFallback(fallback) {
|
|
2132
|
+
const tail = "so pi-lens cannot confirm the server analysed the file";
|
|
2133
|
+
if (fallback.cause === "failed") {
|
|
2134
|
+
return `${fallback.serverName}: resolving the project root for this file failed, ${tail}`;
|
|
2135
|
+
}
|
|
2136
|
+
if (fallback.cause === "unselected") {
|
|
2137
|
+
return `${fallback.serverName}: found ${fallback.marker} for this file but pi-lens did not select it as the project root (a test-fixture or git-ignored directory is never used as one), ${tail}`;
|
|
2138
|
+
}
|
|
2139
|
+
return `${fallback.serverName}: no project root found for this file (looked for ${fallback.rootMarkers.join(" / ")}); the server was started at the file's directory and may not have analysed it`;
|
|
2140
|
+
}
|
|
2141
|
+
async function resolveLspServerCwd(server, filePath, sessionCwd, onRootFailure, onRootFallback) {
|
|
2142
|
+
const stagingRoot = ephemeralStagingRoot(filePath);
|
|
2143
|
+
if (stagingRoot) {
|
|
2144
|
+
recordDegradationOnce({
|
|
2145
|
+
kind: "lsp-root-declined",
|
|
2146
|
+
subject: stagingRoot,
|
|
2147
|
+
reason: "LSP root declined for host pi-agent staging directory"
|
|
2148
|
+
});
|
|
2149
|
+
return void 0;
|
|
2150
|
+
}
|
|
2151
|
+
const rootMarkers = server.rootMarkers ?? server.root.rootMarkers;
|
|
2152
|
+
let serverRoot;
|
|
2153
|
+
let rootFailed = false;
|
|
2154
|
+
try {
|
|
2155
|
+
serverRoot = await server.root(filePath);
|
|
2156
|
+
} catch (error) {
|
|
2157
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
2158
|
+
rootFailed = true;
|
|
2159
|
+
onRootFailure?.(reason);
|
|
2160
|
+
}
|
|
2161
|
+
const isFileDirFallback = serverRoot !== void 0 && rootMarkers?.length && path7.resolve(serverRoot) === path7.resolve(path7.dirname(filePath));
|
|
2162
|
+
if (!serverRoot || isFileDirFallback) {
|
|
2163
|
+
const probedMarker = onRootFallback && !rootFailed && rootMarkers?.length ? resolveToolCwd("lsp", server.id, filePath, {
|
|
2164
|
+
cwd: sessionCwd,
|
|
2165
|
+
rootMarkers,
|
|
2166
|
+
suppressTelemetry: true
|
|
2167
|
+
}).marker : void 0;
|
|
2168
|
+
const refusedMarker = probedMarker !== void 0 && rootMarkers?.includes(probedMarker) ? probedMarker : void 0;
|
|
2169
|
+
const fallbackCwd = rootMarkers?.length ? resolveToolCwd("lsp", server.id, filePath, {
|
|
2170
|
+
cwd: path7.dirname(path7.resolve(filePath)),
|
|
2171
|
+
rootMarkers
|
|
2172
|
+
}) : void 0;
|
|
2173
|
+
if (!serverRoot) {
|
|
2174
|
+
recordDegradationOnce({
|
|
2175
|
+
kind: "tool-cwd-resolution",
|
|
2176
|
+
subject: server.id,
|
|
2177
|
+
reason: `lsp:server-root-${rootFailed ? "failed" : "fallback"}:${filePath}`
|
|
2178
|
+
});
|
|
2179
|
+
onRootFallback?.({
|
|
2180
|
+
serverId: server.id,
|
|
2181
|
+
serverName: server.name ?? server.id,
|
|
2182
|
+
rootMarkers: rootMarkers ?? [],
|
|
2183
|
+
requiresProjectRoot: server.requiresProjectRoot === true,
|
|
2184
|
+
cause: rootFailed ? "failed" : refusedMarker !== void 0 ? "unselected" : "none",
|
|
2185
|
+
...refusedMarker !== void 0 && { marker: refusedMarker }
|
|
2186
|
+
});
|
|
2187
|
+
}
|
|
2188
|
+
return fallbackCwd?.cwd;
|
|
2189
|
+
}
|
|
2190
|
+
const boundedServerRoot = enforceLspRootCeiling(serverRoot, sessionCwd, filePath);
|
|
2191
|
+
return resolveToolCwd("lsp", server.id, filePath, {
|
|
2192
|
+
cwd: sessionCwd,
|
|
2193
|
+
rootMarkers,
|
|
2194
|
+
serverRoot: boundedServerRoot
|
|
2195
|
+
}).cwd;
|
|
2196
|
+
}
|
|
2197
|
+
var FIXTURE_ROOT_SEGMENTS = /* @__PURE__ */ new Set(["__fixtures__", "testdata"]);
|
|
2198
|
+
var FALLBACK_PROJECT_MARKERS = [
|
|
2199
|
+
".git",
|
|
2200
|
+
"package.json",
|
|
2201
|
+
"go.work",
|
|
2202
|
+
"go.mod",
|
|
2203
|
+
"Cargo.toml",
|
|
2204
|
+
"pyproject.toml",
|
|
2205
|
+
"pom.xml",
|
|
2206
|
+
"build.gradle",
|
|
2207
|
+
"build.gradle.kts",
|
|
2208
|
+
"mix.exs",
|
|
2209
|
+
"pubspec.yaml",
|
|
2210
|
+
"Package.swift"
|
|
2211
|
+
];
|
|
2212
|
+
var PROJECT_BOUNDARY_MARKERS = [
|
|
2213
|
+
"package.json",
|
|
2214
|
+
"package-lock.json",
|
|
2215
|
+
"pnpm-lock.yaml",
|
|
2216
|
+
"yarn.lock",
|
|
2217
|
+
"bun.lock",
|
|
2218
|
+
"bun.lockb",
|
|
2219
|
+
"go.work",
|
|
2220
|
+
"go.mod",
|
|
2221
|
+
"Cargo.toml",
|
|
2222
|
+
"Cargo.lock",
|
|
2223
|
+
"pyproject.toml",
|
|
2224
|
+
"uv.lock",
|
|
2225
|
+
"poetry.lock",
|
|
2226
|
+
"Pipfile",
|
|
2227
|
+
"Pipfile.lock",
|
|
2228
|
+
"pom.xml",
|
|
2229
|
+
"build.gradle",
|
|
2230
|
+
"build.gradle.kts",
|
|
2231
|
+
"settings.gradle",
|
|
2232
|
+
"settings.gradle.kts",
|
|
2233
|
+
"mix.exs",
|
|
2234
|
+
"pubspec.yaml",
|
|
2235
|
+
"Package.swift"
|
|
2236
|
+
];
|
|
2237
|
+
var loggedRootCeilingClamps = /* @__PURE__ */ new Set();
|
|
2238
|
+
var posixCaseInsensitiveByPath = /* @__PURE__ */ new Map();
|
|
2239
|
+
function posixFilesystemIsCaseInsensitive(root) {
|
|
2240
|
+
const resolved = path7.resolve(root);
|
|
2241
|
+
const cached = posixCaseInsensitiveByPath.get(resolved);
|
|
2242
|
+
if (cached !== void 0)
|
|
2243
|
+
return cached;
|
|
2244
|
+
if (!existsSync3(resolved)) {
|
|
2245
|
+
return false;
|
|
2246
|
+
}
|
|
2247
|
+
const name = path7.basename(resolved);
|
|
2248
|
+
const alternate = name.toLowerCase() === name ? name.toUpperCase() : name.toLowerCase();
|
|
2249
|
+
let insensitive = false;
|
|
2250
|
+
const alternatePath = path7.join(path7.dirname(resolved), alternate);
|
|
2251
|
+
if (alternate !== name && existsSync3(alternatePath)) {
|
|
2252
|
+
try {
|
|
2253
|
+
const actual = statSync3(resolved);
|
|
2254
|
+
const alternateStat = statSync3(alternatePath);
|
|
2255
|
+
insensitive = actual.dev === alternateStat.dev && actual.ino === alternateStat.ino;
|
|
2256
|
+
} catch {
|
|
2257
|
+
insensitive = false;
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
posixCaseInsensitiveByPath.set(resolved, insensitive);
|
|
2261
|
+
return insensitive;
|
|
2262
|
+
}
|
|
2263
|
+
function resetLSPCaseSensitivityState() {
|
|
2264
|
+
posixCaseInsensitiveByPath.clear();
|
|
2265
|
+
}
|
|
2266
|
+
function isSameOrWithin(ancestor, candidate, deps = {}) {
|
|
2267
|
+
const windowsShaped = isWindowsPath(ancestor) || isWindowsPath(candidate);
|
|
2268
|
+
const pathApi = windowsShaped ? path7.win32 : path7;
|
|
2269
|
+
const resolvedAncestor = pathApi.resolve(ancestor);
|
|
2270
|
+
const resolvedCandidate = pathApi.resolve(candidate);
|
|
2271
|
+
let caseInsensitive = false;
|
|
2272
|
+
if (!windowsShaped) {
|
|
2273
|
+
if (deps.caseInsensitiveProbe) {
|
|
2274
|
+
const cached = posixCaseInsensitiveByPath.get(resolvedAncestor);
|
|
2275
|
+
caseInsensitive = cached ?? deps.caseInsensitiveProbe(resolvedAncestor);
|
|
2276
|
+
if (cached === void 0) {
|
|
2277
|
+
posixCaseInsensitiveByPath.set(resolvedAncestor, caseInsensitive);
|
|
2278
|
+
}
|
|
2279
|
+
} else {
|
|
2280
|
+
caseInsensitive = posixFilesystemIsCaseInsensitive(resolvedAncestor);
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
const relative2 = pathApi.relative(caseInsensitive ? resolvedAncestor.toLowerCase() : resolvedAncestor, caseInsensitive ? resolvedCandidate.toLowerCase() : resolvedCandidate);
|
|
2284
|
+
return relative2 === "" || !relative2.startsWith("..") && !pathApi.isAbsolute(relative2);
|
|
2285
|
+
}
|
|
2286
|
+
function enforceLspRootCeiling(root, sessionCwd, filePath) {
|
|
2287
|
+
const windowsShaped = isWindowsPath(root) || isWindowsPath(sessionCwd);
|
|
2288
|
+
const pathApi = windowsShaped ? path7.win32 : path7;
|
|
2289
|
+
const resolvedRoot = pathApi.resolve(root);
|
|
2290
|
+
const resolvedCwd = pathApi.resolve(sessionCwd);
|
|
2291
|
+
if (filePath && !isSameOrWithin(resolvedCwd, pathApi.resolve(filePath))) {
|
|
2292
|
+
return resolvedRoot;
|
|
2293
|
+
}
|
|
2294
|
+
if (isSameOrWithin(resolvedCwd, resolvedRoot))
|
|
2295
|
+
return resolvedRoot;
|
|
2296
|
+
const logKey = `${normalizeMapKey(resolvedCwd)}:${normalizeMapKey(resolvedRoot)}`;
|
|
2297
|
+
if (!loggedRootCeilingClamps.has(logKey)) {
|
|
2298
|
+
loggedRootCeilingClamps.add(logKey);
|
|
2299
|
+
logSessionStart(`lsp root clamped to session cwd: candidate=${resolvedRoot} cwd=${resolvedCwd}`);
|
|
2300
|
+
}
|
|
2301
|
+
return resolvedCwd;
|
|
2302
|
+
}
|
|
2303
|
+
async function hasProjectBoundaryMarker(dir) {
|
|
2304
|
+
if (await markerExists(dir, ".git"))
|
|
2305
|
+
return true;
|
|
2306
|
+
for (const marker of PROJECT_BOUNDARY_MARKERS) {
|
|
2307
|
+
if (await markerExists(dir, marker))
|
|
2308
|
+
return true;
|
|
2309
|
+
}
|
|
2310
|
+
return false;
|
|
2311
|
+
}
|
|
2312
|
+
function pathSegments(dir) {
|
|
2313
|
+
const parsed = path7.parse(path7.resolve(dir));
|
|
2314
|
+
return path7.relative(parsed.root, path7.resolve(dir)).split(path7.sep).filter(Boolean).map((segment) => segment.toLowerCase());
|
|
2315
|
+
}
|
|
2316
|
+
function hasFixtureConvention(dir) {
|
|
2317
|
+
const segments = pathSegments(dir);
|
|
2318
|
+
if (segments.some((segment) => FIXTURE_ROOT_SEGMENTS.has(segment)))
|
|
2319
|
+
return true;
|
|
2320
|
+
return segments.some((segment, index) => segment === "tests" && segments[index + 1] === "fixtures");
|
|
2321
|
+
}
|
|
2322
|
+
function hasAtomicStageSegment(dir) {
|
|
2323
|
+
return pathSegments(dir).some((segment) => STAGE_TMP_PATTERN.test(segment));
|
|
2324
|
+
}
|
|
2325
|
+
async function findGitBoundary(dir) {
|
|
2326
|
+
let current = path7.resolve(dir);
|
|
2327
|
+
const fsRoot = path7.parse(current).root;
|
|
2328
|
+
while (true) {
|
|
2329
|
+
if (await markerExists(current, ".git"))
|
|
2330
|
+
return current;
|
|
2331
|
+
if (current === fsRoot)
|
|
2332
|
+
return void 0;
|
|
2333
|
+
current = path7.dirname(current);
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
async function isExcludedLspRoot(dir) {
|
|
2337
|
+
const candidate = path7.resolve(dir);
|
|
2338
|
+
if (hasFixtureConvention(candidate) || hasAtomicStageSegment(candidate))
|
|
2339
|
+
return true;
|
|
2340
|
+
const gitRoot = await findGitBoundary(candidate);
|
|
2341
|
+
if (!gitRoot || gitRoot === candidate)
|
|
2342
|
+
return false;
|
|
2343
|
+
if (getProjectIgnoreGlobs(gitRoot).length === 0)
|
|
2344
|
+
return false;
|
|
2345
|
+
return isPathIgnoredByProject(candidate, gitRoot, true);
|
|
2346
|
+
}
|
|
2347
|
+
async function nearestNonExcludedFallbackRoot(candidate) {
|
|
2348
|
+
if (!await isExcludedLspRoot(candidate))
|
|
2349
|
+
return path7.resolve(candidate);
|
|
2350
|
+
let current = path7.dirname(path7.resolve(candidate));
|
|
2351
|
+
const fsRoot = path7.parse(current).root;
|
|
2352
|
+
let nearestAllowed;
|
|
2353
|
+
while (true) {
|
|
2354
|
+
if (!await isExcludedLspRoot(current)) {
|
|
2355
|
+
nearestAllowed ??= current;
|
|
2356
|
+
for (const marker of FALLBACK_PROJECT_MARKERS) {
|
|
2357
|
+
if (await markerExists(current, marker))
|
|
2358
|
+
return current;
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
if (current === fsRoot)
|
|
2362
|
+
break;
|
|
2363
|
+
current = path7.dirname(current);
|
|
2364
|
+
}
|
|
2365
|
+
return nearestAllowed ?? fsRoot;
|
|
2366
|
+
}
|
|
2367
|
+
function isLspInstallDisabled() {
|
|
2368
|
+
return process.env.PI_LENS_DISABLE_LSP_INSTALL === "1";
|
|
2369
|
+
}
|
|
2370
|
+
function canInstall(allowInstall) {
|
|
2371
|
+
return allowInstall !== false && !isLspInstallDisabled();
|
|
2372
|
+
}
|
|
2373
|
+
var DIRECT_LSP_NEGATIVE_TTL_MS = Math.max(3e4, Number.parseInt(process.env.PI_LENS_DIRECT_LSP_NEGATIVE_TTL_MS ?? "600000", 10) || 6e5);
|
|
2374
|
+
var directLspCommandUnavailableUntil = /* @__PURE__ */ new Map();
|
|
2375
|
+
var directLspCommandSkipLoggedUntil = /* @__PURE__ */ new Map();
|
|
2376
|
+
var LSP_SERVICE_GENERATION_FAMILY = "lsp.service.generation";
|
|
2377
|
+
var LSP_SERVICE_GENERATION_VERSION = 1;
|
|
2378
|
+
function lspServiceGenerationCell() {
|
|
2379
|
+
let seed = 0;
|
|
2380
|
+
return getProcessSingleton(LSP_SERVICE_GENERATION_FAMILY, LSP_SERVICE_GENERATION_VERSION, () => ({ generation: seed }), (previous) => {
|
|
2381
|
+
const value = previous?.generation;
|
|
2382
|
+
seed = typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : 0;
|
|
2383
|
+
});
|
|
2384
|
+
}
|
|
2385
|
+
var lspLaunchAvailabilityGeneration = createGenerationSource("lsp-launch-availability", lspServiceGenerationCell);
|
|
2386
|
+
function resetLspLaunchAvailabilityGeneration() {
|
|
2387
|
+
lspLaunchAvailabilityGeneration.bump();
|
|
2388
|
+
}
|
|
2389
|
+
function staleLaunch(generation, subject, proc) {
|
|
2390
|
+
if (generation.isCurrent())
|
|
2391
|
+
return false;
|
|
2392
|
+
try {
|
|
2393
|
+
proc?.process?.kill();
|
|
2394
|
+
} catch {
|
|
2395
|
+
}
|
|
2396
|
+
generation.guardedWrite(subject, () => void 0);
|
|
2397
|
+
return true;
|
|
2398
|
+
}
|
|
2399
|
+
async function installEvidenceForLaunch(toolId, installed, attempt) {
|
|
2400
|
+
const evidence = describeInstallAttempt(attempt);
|
|
2401
|
+
const confirmedManagedPath = await findManagedToolBinary(toolId);
|
|
2402
|
+
return {
|
|
2403
|
+
...evidence,
|
|
2404
|
+
binary: path7.basename(installed),
|
|
2405
|
+
...confirmedManagedPath !== void 0 && pathsEqual(confirmedManagedPath, installed) && {
|
|
2406
|
+
source: "managed-dir"
|
|
2407
|
+
}
|
|
2408
|
+
};
|
|
2409
|
+
}
|
|
2410
|
+
function captureInstallAttempt(toolId) {
|
|
2411
|
+
try {
|
|
2412
|
+
return getInstallAttempt?.(toolId);
|
|
2413
|
+
} catch {
|
|
2414
|
+
}
|
|
2415
|
+
return void 0;
|
|
2416
|
+
}
|
|
2417
|
+
function resetDirectLspCommandAvailability() {
|
|
2418
|
+
directLspCommandUnavailableUntil.clear();
|
|
2419
|
+
directLspCommandSkipLoggedUntil.clear();
|
|
2420
|
+
}
|
|
2421
|
+
function pruneExpiredDirectLspNegativeEntries(now = Date.now()) {
|
|
2422
|
+
for (const [command, until] of directLspCommandUnavailableUntil) {
|
|
2423
|
+
if (until <= now) {
|
|
2424
|
+
directLspCommandUnavailableUntil.delete(command);
|
|
2425
|
+
directLspCommandSkipLoggedUntil.delete(command);
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
for (const [command, until] of directLspCommandSkipLoggedUntil) {
|
|
2429
|
+
if (until <= now)
|
|
2430
|
+
directLspCommandSkipLoggedUntil.delete(command);
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
function isSimpleCommand(command) {
|
|
2434
|
+
return !isFullyQualified(command) && !command.includes("/") && !command.includes("\\");
|
|
2435
|
+
}
|
|
2436
|
+
function isDirectLspCommandTemporarilyUnavailable(command) {
|
|
2437
|
+
const now = Date.now();
|
|
2438
|
+
pruneExpiredDirectLspNegativeEntries(now);
|
|
2439
|
+
const until = directLspCommandUnavailableUntil.get(command);
|
|
2440
|
+
if (!until || until <= now) {
|
|
2441
|
+
directLspCommandUnavailableUntil.delete(command);
|
|
2442
|
+
return false;
|
|
2443
|
+
}
|
|
2444
|
+
const loggedUntil = directLspCommandSkipLoggedUntil.get(command) ?? 0;
|
|
2445
|
+
if (loggedUntil <= now) {
|
|
2446
|
+
logSessionStart(`lsp direct command ${command}: skipped by negative availability cache (${Math.max(0, until - now)}ms remaining)`);
|
|
2447
|
+
directLspCommandSkipLoggedUntil.set(command, until);
|
|
2448
|
+
}
|
|
2449
|
+
return true;
|
|
2450
|
+
}
|
|
2451
|
+
function markDirectLspCommandUnavailable(command) {
|
|
2452
|
+
if (!isSimpleCommand(command))
|
|
2453
|
+
return;
|
|
2454
|
+
directLspCommandUnavailableUntil.set(command, Date.now() + DIRECT_LSP_NEGATIVE_TTL_MS);
|
|
2455
|
+
directLspCommandSkipLoggedUntil.delete(command);
|
|
2456
|
+
}
|
|
2457
|
+
var PI_LENS_BIN_DIR2 = path7.join(getGlobalPiLensDir(), "bin");
|
|
2458
|
+
async function resolveAndLaunch(spec, allowInstall) {
|
|
2459
|
+
const generation = lspLaunchAvailabilityGeneration.capture();
|
|
2460
|
+
const toolLabel = spec.managedToolId ?? spec.candidates[spec.candidates.length - 1] ?? "unknown";
|
|
2461
|
+
let lastRuntimeFailure;
|
|
2462
|
+
const trackRuntimeFailure = (err) => {
|
|
2463
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2464
|
+
if (!hasSpawnFailureKind(err, "tool-not-found")) {
|
|
2465
|
+
lastRuntimeFailure = err instanceof Error ? err : new Error(message);
|
|
2466
|
+
}
|
|
2467
|
+
};
|
|
2468
|
+
const managedProbeStartedAt = Date.now();
|
|
2469
|
+
const managedCandidate = spec.managedToolId ? await findManagedToolBinary(spec.managedToolId) : void 0;
|
|
2470
|
+
if (staleLaunch(generation, `${toolLabel}:findManagedToolBinary`)) {
|
|
2471
|
+
return void 0;
|
|
2472
|
+
}
|
|
2473
|
+
const candidates = managedCandidate && !spec.candidates.includes(managedCandidate) ? [managedCandidate, ...spec.candidates] : spec.candidates;
|
|
2474
|
+
const candidateFailures = [];
|
|
2475
|
+
for (const [index, command] of candidates.entries()) {
|
|
2476
|
+
logLatency({
|
|
2477
|
+
type: "phase",
|
|
2478
|
+
phase: "lsp_launch_candidate_attempt",
|
|
2479
|
+
filePath: spec.cwd,
|
|
2480
|
+
durationMs: 0,
|
|
2481
|
+
metadata: {
|
|
2482
|
+
tool: toolLabel,
|
|
2483
|
+
command,
|
|
2484
|
+
index,
|
|
2485
|
+
totalCandidates: candidates.length,
|
|
2486
|
+
allowInstall: canInstall(allowInstall)
|
|
2487
|
+
}
|
|
2488
|
+
});
|
|
2489
|
+
logSessionStart(`lsp launch candidate attempt tool=${toolLabel} idx=${index}/${candidates.length - 1} command=${command} cwd=${spec.cwd}`);
|
|
2490
|
+
try {
|
|
2491
|
+
const proc = await launchLSP(command, spec.args, {
|
|
2492
|
+
cwd: spec.cwd,
|
|
2493
|
+
env: spec.env
|
|
2494
|
+
});
|
|
2495
|
+
if (staleLaunch(generation, `${toolLabel}:launchLSP:${command}`, proc)) {
|
|
2496
|
+
return void 0;
|
|
2497
|
+
}
|
|
2498
|
+
logLatency({
|
|
2499
|
+
type: "phase",
|
|
2500
|
+
phase: "lsp_launch_candidate_success",
|
|
2501
|
+
filePath: spec.cwd,
|
|
2502
|
+
durationMs: 0,
|
|
2503
|
+
metadata: {
|
|
2504
|
+
tool: toolLabel,
|
|
2505
|
+
command,
|
|
2506
|
+
index,
|
|
2507
|
+
source: "direct"
|
|
2508
|
+
}
|
|
2509
|
+
});
|
|
2510
|
+
logSessionStart(`lsp launch candidate success tool=${toolLabel} idx=${index} command=${command} source=direct`);
|
|
2511
|
+
if (managedCandidate !== void 0 && command === managedCandidate) {
|
|
2512
|
+
logAvailabilityDecision({
|
|
2513
|
+
tool: toolLabel,
|
|
2514
|
+
verdict: "available",
|
|
2515
|
+
outcome: "success",
|
|
2516
|
+
cause: "ok",
|
|
2517
|
+
elapsedMs: Date.now() - managedProbeStartedAt,
|
|
2518
|
+
latched: false,
|
|
2519
|
+
producer: "lsp-launch",
|
|
2520
|
+
classifiedBy: "probe",
|
|
2521
|
+
evidence: {
|
|
2522
|
+
binary: path7.basename(managedCandidate),
|
|
2523
|
+
source: "managed-dir",
|
|
2524
|
+
correctsLatchedRow: false
|
|
2525
|
+
}
|
|
2526
|
+
});
|
|
2527
|
+
}
|
|
2528
|
+
return { process: proc, source: "direct" };
|
|
2529
|
+
} catch (err) {
|
|
2530
|
+
if (staleLaunch(generation, `${toolLabel}:launchLSP:${command}`)) {
|
|
2531
|
+
return void 0;
|
|
2532
|
+
}
|
|
2533
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2534
|
+
candidateFailures.push({ index, command, message, err });
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
for (const failure of candidateFailures) {
|
|
2538
|
+
logLatency({
|
|
2539
|
+
type: "phase",
|
|
2540
|
+
phase: "lsp_launch_candidate_failed",
|
|
2541
|
+
filePath: spec.cwd,
|
|
2542
|
+
durationMs: 0,
|
|
2543
|
+
metadata: {
|
|
2544
|
+
tool: toolLabel,
|
|
2545
|
+
command: failure.command,
|
|
2546
|
+
index: failure.index,
|
|
2547
|
+
error: failure.message
|
|
2548
|
+
}
|
|
2549
|
+
});
|
|
2550
|
+
logSessionStart(`lsp launch candidate failed tool=${toolLabel} idx=${failure.index} command=${failure.command} error=${failure.message}`);
|
|
2551
|
+
trackRuntimeFailure(failure.err);
|
|
2552
|
+
}
|
|
2553
|
+
const hasOnlyRepairableCandidateFailures = candidateFailures.every((failure) => hasSpawnFailureKind(failure.err, "tool-not-found"));
|
|
2554
|
+
if (!hasOnlyRepairableCandidateFailures) {
|
|
2555
|
+
if (lastRuntimeFailure)
|
|
2556
|
+
throw lastRuntimeFailure;
|
|
2557
|
+
return void 0;
|
|
2558
|
+
}
|
|
2559
|
+
if (!canInstall(allowInstall)) {
|
|
2560
|
+
logSessionStart(`lsp launch install blocked tool=${toolLabel} cwd=${spec.cwd} allowInstall=${allowInstall !== false} globalDisabled=${isLspInstallDisabled()}`);
|
|
2561
|
+
logLatency({
|
|
2562
|
+
type: "phase",
|
|
2563
|
+
phase: "lsp_launch_install_blocked",
|
|
2564
|
+
filePath: spec.cwd,
|
|
2565
|
+
durationMs: 0,
|
|
2566
|
+
metadata: {
|
|
2567
|
+
tool: toolLabel,
|
|
2568
|
+
allowInstall,
|
|
2569
|
+
globalInstallDisabled: isLspInstallDisabled()
|
|
2570
|
+
}
|
|
2571
|
+
});
|
|
2572
|
+
return void 0;
|
|
2573
|
+
}
|
|
2574
|
+
if (spec.managedToolId) {
|
|
2575
|
+
const failedCandidate = candidateFailures.at(-1);
|
|
2576
|
+
const classifiedFailure = classifyProbeFailure({
|
|
2577
|
+
error: failedCandidate?.err instanceof Error ? failedCandidate.err : void 0,
|
|
2578
|
+
spawnFailure: {
|
|
2579
|
+
kind: hasSpawnFailureKind(failedCandidate?.err, "tool-not-found") ? "tool-not-found" : void 0
|
|
2580
|
+
}
|
|
2581
|
+
}, { command: failedCandidate?.command });
|
|
2582
|
+
logAvailabilityDecision({
|
|
2583
|
+
tool: spec.managedToolId,
|
|
2584
|
+
verdict: "unavailable",
|
|
2585
|
+
outcome: classifiedFailure.outcome,
|
|
2586
|
+
cause: classifiedFailure.cause,
|
|
2587
|
+
elapsedMs: Date.now() - managedProbeStartedAt,
|
|
2588
|
+
latched: false,
|
|
2589
|
+
classifiedBy: "probe",
|
|
2590
|
+
producer: "lsp-launch",
|
|
2591
|
+
evidence: classifiedFailure.evidence
|
|
2592
|
+
});
|
|
2593
|
+
logSessionStart(`lsp launch ensure-tool start tool=${spec.managedToolId} cwd=${spec.cwd}`);
|
|
2594
|
+
const installStartedAt = Date.now();
|
|
2595
|
+
const installed = await ensureTool(spec.managedToolId);
|
|
2596
|
+
const installAttempt = captureInstallAttempt(spec.managedToolId);
|
|
2597
|
+
if (staleLaunch(generation, `${toolLabel}:ensureTool`)) {
|
|
2598
|
+
return void 0;
|
|
2599
|
+
}
|
|
2600
|
+
logSessionStart(`lsp launch ensure-tool result tool=${spec.managedToolId} installed=${installed ? "yes" : "no"} path=${installed ?? ""}`);
|
|
2601
|
+
logLatency({
|
|
2602
|
+
type: "phase",
|
|
2603
|
+
phase: "lsp_launch_ensure_tool_result",
|
|
2604
|
+
filePath: spec.cwd,
|
|
2605
|
+
durationMs: 0,
|
|
2606
|
+
metadata: {
|
|
2607
|
+
tool: spec.managedToolId,
|
|
2608
|
+
installed: Boolean(installed),
|
|
2609
|
+
path: installed
|
|
2610
|
+
}
|
|
2611
|
+
});
|
|
2612
|
+
if (installed) {
|
|
2613
|
+
try {
|
|
2614
|
+
const proc = await launchLSP(installed, spec.args, {
|
|
2615
|
+
cwd: spec.cwd,
|
|
2616
|
+
env: spec.env
|
|
2617
|
+
});
|
|
2618
|
+
if (staleLaunch(generation, `${toolLabel}:launchLSP:managed`, proc)) {
|
|
2619
|
+
return void 0;
|
|
2620
|
+
}
|
|
2621
|
+
logSessionStart(`lsp launch managed success tool=${spec.managedToolId} command=${installed} source=managed`);
|
|
2622
|
+
logLatency({
|
|
2623
|
+
type: "phase",
|
|
2624
|
+
phase: "lsp_launch_managed_success",
|
|
2625
|
+
filePath: spec.cwd,
|
|
2626
|
+
durationMs: 0,
|
|
2627
|
+
metadata: {
|
|
2628
|
+
tool: spec.managedToolId,
|
|
2629
|
+
command: installed
|
|
2630
|
+
}
|
|
2631
|
+
});
|
|
2632
|
+
const evidence = await installEvidenceForLaunch(spec.managedToolId, installed, installAttempt);
|
|
2633
|
+
if (staleLaunch(generation, `${toolLabel}:managed-evidence`, proc)) {
|
|
2634
|
+
return void 0;
|
|
2635
|
+
}
|
|
2636
|
+
logAvailabilityDecision({
|
|
2637
|
+
tool: spec.managedToolId,
|
|
2638
|
+
verdict: "available",
|
|
2639
|
+
outcome: "success",
|
|
2640
|
+
cause: "ok",
|
|
2641
|
+
elapsedMs: Date.now() - installStartedAt,
|
|
2642
|
+
latched: false,
|
|
2643
|
+
classifiedBy: "caller",
|
|
2644
|
+
producer: "lsp-launch",
|
|
2645
|
+
evidence: {
|
|
2646
|
+
...evidence,
|
|
2647
|
+
correctsLatchedRow: false
|
|
2648
|
+
}
|
|
2649
|
+
});
|
|
2650
|
+
return { process: proc, source: "managed" };
|
|
2651
|
+
} catch (err) {
|
|
2652
|
+
if (staleLaunch(generation, `${toolLabel}:launchLSP:managed-rejection`)) {
|
|
2653
|
+
return void 0;
|
|
2654
|
+
}
|
|
2655
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2656
|
+
logSessionStart(`lsp launch managed failed tool=${spec.managedToolId} command=${installed} error=${message}`);
|
|
2657
|
+
logLatency({
|
|
2658
|
+
type: "phase",
|
|
2659
|
+
phase: "lsp_launch_managed_failed",
|
|
2660
|
+
filePath: spec.cwd,
|
|
2661
|
+
durationMs: 0,
|
|
2662
|
+
metadata: {
|
|
2663
|
+
tool: spec.managedToolId,
|
|
2664
|
+
command: installed,
|
|
2665
|
+
error: message
|
|
2666
|
+
}
|
|
2667
|
+
});
|
|
2668
|
+
trackRuntimeFailure(err);
|
|
2669
|
+
const looksPathResolved = !installed.includes("/") && !installed.includes("\\");
|
|
2670
|
+
if (looksPathResolved && hasSpawnFailureKind(err, "tool-not-found")) {
|
|
2671
|
+
logSessionStart(`lsp launch managed retry force-reinstall tool=${spec.managedToolId}`);
|
|
2672
|
+
const reinstalled = await ensureTool(spec.managedToolId, {
|
|
2673
|
+
forceReinstall: true
|
|
2674
|
+
});
|
|
2675
|
+
const reinstallAttempt = captureInstallAttempt(spec.managedToolId);
|
|
2676
|
+
if (staleLaunch(generation, `${toolLabel}:forceReinstall`)) {
|
|
2677
|
+
return void 0;
|
|
2678
|
+
}
|
|
2679
|
+
if (reinstalled) {
|
|
2680
|
+
try {
|
|
2681
|
+
const proc = await launchLSP(reinstalled, spec.args, {
|
|
2682
|
+
cwd: spec.cwd,
|
|
2683
|
+
env: spec.env
|
|
2684
|
+
});
|
|
2685
|
+
if (staleLaunch(generation, `${toolLabel}:launchLSP:forceReinstall`, proc)) {
|
|
2686
|
+
return void 0;
|
|
2687
|
+
}
|
|
2688
|
+
logSessionStart(`lsp launch managed force-reinstall success tool=${spec.managedToolId} command=${reinstalled}`);
|
|
2689
|
+
logLatency({
|
|
2690
|
+
type: "phase",
|
|
2691
|
+
phase: "lsp_launch_managed_force_reinstall_success",
|
|
2692
|
+
filePath: spec.cwd,
|
|
2693
|
+
durationMs: 0,
|
|
2694
|
+
metadata: {
|
|
2695
|
+
tool: spec.managedToolId,
|
|
2696
|
+
command: reinstalled
|
|
2697
|
+
}
|
|
2698
|
+
});
|
|
2699
|
+
const evidence = await installEvidenceForLaunch(spec.managedToolId, reinstalled, reinstallAttempt);
|
|
2700
|
+
if (staleLaunch(generation, `${toolLabel}:forceReinstall-evidence`, proc)) {
|
|
2701
|
+
return void 0;
|
|
2702
|
+
}
|
|
2703
|
+
logAvailabilityDecision({
|
|
2704
|
+
tool: spec.managedToolId,
|
|
2705
|
+
verdict: "available",
|
|
2706
|
+
outcome: "success",
|
|
2707
|
+
cause: "ok",
|
|
2708
|
+
elapsedMs: Date.now() - installStartedAt,
|
|
2709
|
+
latched: false,
|
|
2710
|
+
classifiedBy: "caller",
|
|
2711
|
+
producer: "lsp-launch",
|
|
2712
|
+
evidence: {
|
|
2713
|
+
...evidence,
|
|
2714
|
+
correctsLatchedRow: false
|
|
2715
|
+
}
|
|
2716
|
+
});
|
|
2717
|
+
return { process: proc, source: "managed" };
|
|
2718
|
+
} catch (retryErr) {
|
|
2719
|
+
logSessionStart(`lsp launch managed force-reinstall failed tool=${spec.managedToolId} error=${retryErr instanceof Error ? retryErr.message : String(retryErr)}`);
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
const runtimeInstall = spec.runtimeInstall;
|
|
2727
|
+
const runtimeAvailable = runtimeInstall ? await isOnPath(runtimeInstall.runtimeCommand) : false;
|
|
2728
|
+
if (staleLaunch(generation, `${toolLabel}:runtimeAvailability`)) {
|
|
2729
|
+
return void 0;
|
|
2730
|
+
}
|
|
2731
|
+
if (runtimeInstall && runtimeAvailable) {
|
|
2732
|
+
const ok = await runtimeInstall.install();
|
|
2733
|
+
if (staleLaunch(generation, `${toolLabel}:runtimeInstall`)) {
|
|
2734
|
+
return void 0;
|
|
2735
|
+
}
|
|
2736
|
+
if (ok) {
|
|
2737
|
+
const retry = runtimeInstall.retryCandidates ?? spec.candidates;
|
|
2738
|
+
for (const command of retry) {
|
|
2739
|
+
try {
|
|
2740
|
+
const proc = await launchLSP(command, spec.args, {
|
|
2741
|
+
cwd: spec.cwd,
|
|
2742
|
+
env: spec.env
|
|
2743
|
+
});
|
|
2744
|
+
if (staleLaunch(generation, `${toolLabel}:launchLSP:runtime`, proc)) {
|
|
2745
|
+
return void 0;
|
|
2746
|
+
}
|
|
2747
|
+
return { process: proc, source: "managed" };
|
|
2748
|
+
} catch (err) {
|
|
2749
|
+
if (staleLaunch(generation, `${toolLabel}:launchLSP:runtime`)) {
|
|
2750
|
+
return void 0;
|
|
2751
|
+
}
|
|
2752
|
+
trackRuntimeFailure(err);
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
if (lastRuntimeFailure) {
|
|
2758
|
+
throw lastRuntimeFailure;
|
|
2759
|
+
}
|
|
2760
|
+
return void 0;
|
|
2761
|
+
}
|
|
2762
|
+
async function resolveAndLaunchBundle(spec, allowInstall) {
|
|
2763
|
+
let runtime;
|
|
2764
|
+
for (const candidate of spec.runtimeCandidates) {
|
|
2765
|
+
if (await isOnPath(candidate)) {
|
|
2766
|
+
runtime = candidate;
|
|
2767
|
+
break;
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
if (!runtime) {
|
|
2771
|
+
logSessionStart(`lsp launch bundle skip tool=${spec.bundleToolId}: no runtime on PATH (tried ${spec.runtimeCandidates.join(", ")})`);
|
|
2772
|
+
return void 0;
|
|
2773
|
+
}
|
|
2774
|
+
let bundleDir = await getToolPath(spec.bundleToolId);
|
|
2775
|
+
if (!bundleDir && canInstall(allowInstall)) {
|
|
2776
|
+
bundleDir = await ensureTool(spec.bundleToolId);
|
|
2777
|
+
}
|
|
2778
|
+
if (!bundleDir) {
|
|
2779
|
+
logSessionStart(`lsp launch bundle skip tool=${spec.bundleToolId}: bundle not installed (allowInstall=${allowInstall !== false})`);
|
|
2780
|
+
return void 0;
|
|
2781
|
+
}
|
|
2782
|
+
try {
|
|
2783
|
+
const proc = await launchLSP(runtime, spec.args(bundleDir), {
|
|
2784
|
+
cwd: spec.cwd,
|
|
2785
|
+
env: spec.env
|
|
2786
|
+
});
|
|
2787
|
+
logSessionStart(`lsp launch bundle success tool=${spec.bundleToolId} runtime=${runtime} bundle=${bundleDir}`);
|
|
2788
|
+
return { process: proc, source: "managed" };
|
|
2789
|
+
} catch (err) {
|
|
2790
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2791
|
+
logSessionStart(`lsp launch bundle failed tool=${spec.bundleToolId} runtime=${runtime} error=${message}`);
|
|
2792
|
+
return void 0;
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
async function resolveAndLaunchTreeBinary(spec, allowInstall) {
|
|
2796
|
+
for (const command of spec.candidates) {
|
|
2797
|
+
try {
|
|
2798
|
+
const proc = await launchLSP(command, spec.args, {
|
|
2799
|
+
cwd: spec.cwd,
|
|
2800
|
+
env: spec.env
|
|
2801
|
+
});
|
|
2802
|
+
return { process: proc, source: "direct" };
|
|
2803
|
+
} catch {
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
let bundleDir = await getToolPath(spec.bundleToolId);
|
|
2807
|
+
if (!bundleDir && canInstall(allowInstall)) {
|
|
2808
|
+
bundleDir = await ensureTool(spec.bundleToolId);
|
|
2809
|
+
}
|
|
2810
|
+
if (!bundleDir) {
|
|
2811
|
+
logSessionStart(`lsp launch tree-bin skip tool=${spec.bundleToolId}: not on PATH and bundle not installed (allowInstall=${allowInstall !== false})`);
|
|
2812
|
+
return void 0;
|
|
2813
|
+
}
|
|
2814
|
+
const suffix = process.platform === "win32" ? ".exe" : "";
|
|
2815
|
+
const binPath = path7.join(bundleDir, ...spec.binRelPath.split("/")) + suffix;
|
|
2816
|
+
try {
|
|
2817
|
+
const proc = await launchLSP(binPath, spec.args, {
|
|
2818
|
+
cwd: spec.cwd,
|
|
2819
|
+
env: spec.env
|
|
2820
|
+
});
|
|
2821
|
+
logSessionStart(`lsp launch tree-bin success tool=${spec.bundleToolId} bin=${binPath}`);
|
|
2822
|
+
return { process: proc, source: "managed" };
|
|
2823
|
+
} catch (err) {
|
|
2824
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2825
|
+
logSessionStart(`lsp launch tree-bin failed tool=${spec.bundleToolId} bin=${binPath} error=${message}`);
|
|
2826
|
+
return void 0;
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
function nodeBinLocalCandidates(root, baseName) {
|
|
2830
|
+
const localBase = path7.join(root, "node_modules", ".bin", baseName);
|
|
2831
|
+
if (process.platform === "win32") {
|
|
2832
|
+
return [`${localBase}.cmd`, `${localBase}.exe`];
|
|
2833
|
+
}
|
|
2834
|
+
return [localBase];
|
|
2835
|
+
}
|
|
2836
|
+
function nodeBinCandidates(root, baseName) {
|
|
2837
|
+
return [...nodeBinLocalCandidates(root, baseName), baseName];
|
|
2838
|
+
}
|
|
2839
|
+
function piAgentExtensionsRootKey(file) {
|
|
2840
|
+
const dirKey = normalizeEphemeralMapKey(path7.dirname(path7.resolve(file)));
|
|
2841
|
+
const marker = "/.pi/agent/extensions";
|
|
2842
|
+
const index = dirKey.indexOf(marker);
|
|
2843
|
+
if (index === -1)
|
|
2844
|
+
return void 0;
|
|
2845
|
+
return dirKey.slice(0, index + marker.length);
|
|
2846
|
+
}
|
|
2847
|
+
function IgnoreHomeRoot(primary) {
|
|
2848
|
+
const homeKey = normalizeEphemeralMapKey(path7.resolve(os6.homedir()));
|
|
2849
|
+
return withRootMarkers(async (file) => {
|
|
2850
|
+
const root = await primary(file);
|
|
2851
|
+
if (!root)
|
|
2852
|
+
return void 0;
|
|
2853
|
+
return normalizeEphemeralMapKey(path7.resolve(root)) === homeKey ? void 0 : root;
|
|
2854
|
+
}, primary.rootMarkers ?? []);
|
|
2855
|
+
}
|
|
2856
|
+
function rubyBinCandidates(baseName) {
|
|
2857
|
+
const candidates = [];
|
|
2858
|
+
const home = os6.homedir();
|
|
2859
|
+
const isWin = process.platform === "win32";
|
|
2860
|
+
const ext = isWin ? ".bat" : "";
|
|
2861
|
+
candidates.push(path7.join(home, ".local", "share", "mise", "installs", "ruby", "bin", `${baseName}${ext}`));
|
|
2862
|
+
candidates.push(path7.join(home, ".asdf", "installs", "ruby", "bin", `${baseName}${ext}`));
|
|
2863
|
+
if (isWin) {
|
|
2864
|
+
const driveRoot = path7.parse(home).root;
|
|
2865
|
+
for (const entry of getRubyVersionDirNamesSync(driveRoot)) {
|
|
2866
|
+
candidates.push(path7.join(driveRoot, entry, "bin", `${baseName}.bat`));
|
|
2867
|
+
candidates.push(path7.join(driveRoot, entry, "bin", baseName));
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
return candidates;
|
|
2871
|
+
}
|
|
2872
|
+
function createInteractiveServer(spec) {
|
|
2873
|
+
return {
|
|
2874
|
+
id: spec.id,
|
|
2875
|
+
name: spec.name,
|
|
2876
|
+
extensions: spec.extensions,
|
|
2877
|
+
idleEviction: "unmeasured",
|
|
2878
|
+
// `InteractiveServerSpec` declares no role, so the factory applies the
|
|
2879
|
+
// stated default rather than leaving `role` absent for each consumer to
|
|
2880
|
+
// read by negation (#1488). An auxiliary would declare its role on a
|
|
2881
|
+
// row of its own, the way the four scanner rows do.
|
|
2882
|
+
role: DEFAULT_LSP_SERVER_ROLE,
|
|
2883
|
+
root: spec.root,
|
|
2884
|
+
rootMarkers: spec.root.rootMarkers,
|
|
2885
|
+
fallbackFor: spec.fallbackFor,
|
|
2886
|
+
requiresProjectRoot: spec.requiresProjectRoot,
|
|
2887
|
+
availabilityKey: typeof spec.command === "string" && isSimpleCommand(spec.command) ? spec.command : void 0,
|
|
2888
|
+
async spawn(root) {
|
|
2889
|
+
const command = typeof spec.command === "function" ? spec.command(root) : spec.command;
|
|
2890
|
+
const args = typeof spec.args === "function" ? spec.args(root) : spec.args || [];
|
|
2891
|
+
if (isSimpleCommand(command) && isDirectLspCommandTemporarilyUnavailable(command)) {
|
|
2892
|
+
return void 0;
|
|
2893
|
+
}
|
|
2894
|
+
const runtimeEnv = spec.runtime === "java" ? await resolveJavaRuntimeEnv() : void 0;
|
|
2895
|
+
try {
|
|
2896
|
+
const proc = await launchLSP(command, args, {
|
|
2897
|
+
cwd: root,
|
|
2898
|
+
...runtimeEnv ? { env: runtimeEnv } : {}
|
|
2899
|
+
});
|
|
2900
|
+
const initialization = typeof spec.initialization === "function" ? spec.initialization(root) : spec.initialization;
|
|
2901
|
+
return { process: proc, source: "direct", initialization };
|
|
2902
|
+
} catch (err) {
|
|
2903
|
+
if (hasSpawnFailureKind(err, "tool-not-found")) {
|
|
2904
|
+
markDirectLspCommandUnavailable(command);
|
|
2905
|
+
}
|
|
2906
|
+
return void 0;
|
|
2907
|
+
}
|
|
2908
|
+
}
|
|
2909
|
+
};
|
|
2910
|
+
}
|
|
2911
|
+
function PriorityRoot(markerGroups, excludePatterns, stopDir) {
|
|
2912
|
+
const resolvers = markerGroups.map((markers) => NearestRoot(markers, excludePatterns, stopDir));
|
|
2913
|
+
return withRootMarkers(async (file) => {
|
|
2914
|
+
for (const resolve3 of resolvers) {
|
|
2915
|
+
const root = await resolve3(file);
|
|
2916
|
+
if (root)
|
|
2917
|
+
return root;
|
|
2918
|
+
}
|
|
2919
|
+
return void 0;
|
|
2920
|
+
}, markerGroups.flat());
|
|
2921
|
+
}
|
|
2922
|
+
var FileDirRoot = async (file) => {
|
|
2923
|
+
const candidate = path7.resolve(path7.dirname(file));
|
|
2924
|
+
return nearestNonExcludedFallbackRoot(candidate);
|
|
2925
|
+
};
|
|
2926
|
+
function RootWithFallback(primary, fallback = FileDirRoot) {
|
|
2927
|
+
return withRootMarkers(async (file) => {
|
|
2928
|
+
const primaryRoot = await primary(file);
|
|
2929
|
+
if (primaryRoot)
|
|
2930
|
+
return primaryRoot;
|
|
2931
|
+
return fallback(file);
|
|
2932
|
+
}, primary.rootMarkers ?? []);
|
|
2933
|
+
}
|
|
2934
|
+
function WorkspacePriorityRoot(markerGroups, excludePatterns) {
|
|
2935
|
+
return withRootMarkers(async (file) => PriorityRoot(markerGroups, excludePatterns, process.cwd())(file), markerGroups.flat());
|
|
2936
|
+
}
|
|
2937
|
+
function isPermissionFsError(err) {
|
|
2938
|
+
const code = err?.code;
|
|
2939
|
+
return code === "EACCES" || code === "EPERM";
|
|
2940
|
+
}
|
|
2941
|
+
function markerProbeDir(dir, pattern) {
|
|
2942
|
+
const normalized = toPosix(pattern);
|
|
2943
|
+
const slash = normalized.lastIndexOf("/");
|
|
2944
|
+
const parentPattern = slash >= 0 ? normalized.slice(0, slash) : "";
|
|
2945
|
+
return parentPattern ? path7.join(dir, ...parentPattern.split("/").filter(Boolean)) : dir;
|
|
2946
|
+
}
|
|
2947
|
+
async function markerExists(dir, pattern) {
|
|
2948
|
+
if (!pattern.includes("*")) {
|
|
2949
|
+
try {
|
|
2950
|
+
await stat(path7.join(dir, pattern));
|
|
2951
|
+
return true;
|
|
2952
|
+
} catch (err) {
|
|
2953
|
+
if (isPermissionFsError(err)) {
|
|
2954
|
+
logSessionStart(`lsp root marker skipped: permission error stat ${path7.join(dir, pattern)}`);
|
|
2955
|
+
}
|
|
2956
|
+
return false;
|
|
2957
|
+
}
|
|
2958
|
+
}
|
|
2959
|
+
const normalized = pattern.replace(/\\/g, "/");
|
|
2960
|
+
const slash = normalized.lastIndexOf("/");
|
|
2961
|
+
const basenamePattern = slash >= 0 ? normalized.slice(slash + 1) : normalized;
|
|
2962
|
+
if (!basenamePattern)
|
|
2963
|
+
return false;
|
|
2964
|
+
const targetDir = markerProbeDir(dir, normalized);
|
|
2965
|
+
try {
|
|
2966
|
+
const entries = await readdir(targetDir, { withFileTypes: true });
|
|
2967
|
+
return direntsHaveMarkerGlobMatch(entries, basenamePattern);
|
|
2968
|
+
} catch (err) {
|
|
2969
|
+
if (isPermissionFsError(err)) {
|
|
2970
|
+
logSessionStart(`lsp root marker skipped: permission error read ${targetDir}`);
|
|
2971
|
+
}
|
|
2972
|
+
return false;
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
var rootMtimeBound = (label) => ({
|
|
2976
|
+
ms: HOOK_WALL_BUDGET_MS.tool_result_edit,
|
|
2977
|
+
signal: void 0,
|
|
2978
|
+
hook: "tool_result_edit",
|
|
2979
|
+
label
|
|
2980
|
+
});
|
|
2981
|
+
function NearestRoot(includePatterns, excludePatterns, stopDir) {
|
|
2982
|
+
const cache = /* @__PURE__ */ new Map();
|
|
2983
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
2984
|
+
const subdirPatterns = [];
|
|
2985
|
+
for (const pattern of [...includePatterns, ...excludePatterns ?? []]) {
|
|
2986
|
+
if (markerProbeDir("", pattern))
|
|
2987
|
+
subdirPatterns.push(pattern);
|
|
2988
|
+
}
|
|
2989
|
+
return withRootMarkers(async (file) => {
|
|
2990
|
+
const startDir = path7.resolve(path7.dirname(file));
|
|
2991
|
+
const dirKey = normalizeMapKey(startDir);
|
|
2992
|
+
const cached = cache.get(dirKey);
|
|
2993
|
+
if (cached !== void 0 && Date.now() - cached.walkedAt < FRESHNESS_CADENCE_MS && await bounded(dirMtimesStillFreshAsync(cached.probedDirs), rootMtimeBound("lsp-root-memo-freshness")) === true)
|
|
2994
|
+
return cached.root;
|
|
2995
|
+
const flying = inFlight.get(dirKey);
|
|
2996
|
+
if (flying)
|
|
2997
|
+
return flying;
|
|
2998
|
+
const probedDirs = [];
|
|
2999
|
+
const walkedAt = Date.now();
|
|
3000
|
+
const promise = (async () => {
|
|
3001
|
+
let currentDir = startDir;
|
|
3002
|
+
const fsRoot = path7.parse(currentDir).root;
|
|
3003
|
+
const stop = stopDir ? path7.resolve(stopDir) : fsRoot;
|
|
3004
|
+
while (true) {
|
|
3005
|
+
if (stop !== fsRoot && currentDir.startsWith(stop + path7.sep) === false && currentDir !== stop) {
|
|
3006
|
+
break;
|
|
3007
|
+
}
|
|
3008
|
+
const stepDirs = [
|
|
3009
|
+
currentDir,
|
|
3010
|
+
...subdirPatterns.map((pattern) => markerProbeDir(currentDir, pattern))
|
|
3011
|
+
];
|
|
3012
|
+
const stepRecords = await bounded(dirMtimeRecordsAsync(stepDirs), rootMtimeBound("lsp-root-walk-dir-mtimes"));
|
|
3013
|
+
probedDirs.push(...stepRecords ?? unknownDirMtimeRecords(stepDirs));
|
|
3014
|
+
if (excludePatterns) {
|
|
3015
|
+
let excluded = false;
|
|
3016
|
+
for (const pattern of excludePatterns) {
|
|
3017
|
+
if (await markerExists(currentDir, pattern)) {
|
|
3018
|
+
excluded = true;
|
|
3019
|
+
break;
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
if (excluded) {
|
|
3023
|
+
currentDir = path7.dirname(currentDir);
|
|
3024
|
+
continue;
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
3027
|
+
for (const pattern of includePatterns) {
|
|
3028
|
+
if (await markerExists(currentDir, pattern) && (pattern !== ".git" || currentDir !== os6.tmpdir()) && !await isExcludedLspRoot(currentDir)) {
|
|
3029
|
+
return enforceLspRootCeiling(currentDir, process.cwd(), file);
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
if (currentDir === stop || currentDir === fsRoot) {
|
|
3033
|
+
break;
|
|
3034
|
+
}
|
|
3035
|
+
currentDir = path7.dirname(currentDir);
|
|
3036
|
+
}
|
|
3037
|
+
return void 0;
|
|
3038
|
+
})();
|
|
3039
|
+
inFlight.set(dirKey, promise);
|
|
3040
|
+
try {
|
|
3041
|
+
const result = await promise;
|
|
3042
|
+
if (result !== void 0)
|
|
3043
|
+
cache.set(dirKey, { root: result, probedDirs, walkedAt });
|
|
3044
|
+
return result;
|
|
3045
|
+
} finally {
|
|
3046
|
+
inFlight.delete(dirKey);
|
|
3047
|
+
}
|
|
3048
|
+
}, includePatterns);
|
|
3049
|
+
}
|
|
3050
|
+
var createRootDetector = NearestRoot;
|
|
3051
|
+
function isOnPath(command) {
|
|
3052
|
+
return isCommandAvailableAsync(command);
|
|
3053
|
+
}
|
|
3054
|
+
async function tryGoInstallGopls() {
|
|
3055
|
+
const isWindows2 = process.platform === "win32";
|
|
3056
|
+
const result = await safeSpawnAsync(isWindows2 ? "go.exe" : "go", ["install", "golang.org/x/tools/gopls@latest"], { timeout: 18e4, ignoreAmbientSignal: true });
|
|
3057
|
+
return !result.error && result.status === 0;
|
|
3058
|
+
}
|
|
3059
|
+
async function tryDotnetToolInstall(tool) {
|
|
3060
|
+
mkdirSync2(PI_LENS_BIN_DIR2, { recursive: true });
|
|
3061
|
+
const result = await safeSpawnAsync("dotnet", ["tool", "install", "--tool-path", PI_LENS_BIN_DIR2, tool], { timeout: 18e4, ignoreAmbientSignal: true });
|
|
3062
|
+
if (!result.error && result.status === 0)
|
|
3063
|
+
return true;
|
|
3064
|
+
const stderr = result.stderr ?? "";
|
|
3065
|
+
if (stderr.includes("No NuGet sources are defined or enabled")) {
|
|
3066
|
+
logSessionStart(`lsp dotnet-install: NuGet sources missing \u2014 cannot install ${tool}. Run: dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org`);
|
|
3067
|
+
return false;
|
|
3068
|
+
}
|
|
3069
|
+
const updateResult = await safeSpawnAsync("dotnet", ["tool", "update", "--tool-path", PI_LENS_BIN_DIR2, tool], { timeout: 18e4, ignoreAmbientSignal: true });
|
|
3070
|
+
return !updateResult.error && updateResult.status === 0;
|
|
3071
|
+
}
|
|
3072
|
+
async function findAncestorFile(startDir, ...relativeSegments) {
|
|
3073
|
+
return findAncestorFileAmong(startDir, [relativeSegments]);
|
|
3074
|
+
}
|
|
3075
|
+
async function findAncestorFileAmong(startDir, candidateSegmentLists) {
|
|
3076
|
+
const fs5 = await import("node:fs/promises");
|
|
3077
|
+
let currentDir = path7.resolve(startDir);
|
|
3078
|
+
while (!isAtOrAboveHomeDir(currentDir)) {
|
|
3079
|
+
for (const segments of candidateSegmentLists) {
|
|
3080
|
+
const candidate = path7.join(currentDir, ...segments);
|
|
3081
|
+
try {
|
|
3082
|
+
await fs5.access(candidate);
|
|
3083
|
+
return candidate;
|
|
3084
|
+
} catch {
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
const parent = path7.dirname(currentDir);
|
|
3088
|
+
if (parent === currentDir)
|
|
3089
|
+
break;
|
|
3090
|
+
currentDir = parent;
|
|
3091
|
+
}
|
|
3092
|
+
return void 0;
|
|
3093
|
+
}
|
|
3094
|
+
var CLASSIC_TS_REPAIR_FAMILY = "lsp.classic-ts-repair-guard";
|
|
3095
|
+
var CLASSIC_TS_REPAIR_VERSION = 1;
|
|
3096
|
+
function classicTsRepairState() {
|
|
3097
|
+
return getProcessSingleton(CLASSIC_TS_REPAIR_FAMILY, CLASSIC_TS_REPAIR_VERSION, () => ({ attempted: false }));
|
|
3098
|
+
}
|
|
3099
|
+
function resetClassicTsRepairGuard() {
|
|
3100
|
+
classicTsRepairState().attempted = false;
|
|
3101
|
+
}
|
|
3102
|
+
function typescriptDirsForTsc(tscPath) {
|
|
3103
|
+
const binDir = path7.dirname(tscPath);
|
|
3104
|
+
return [
|
|
3105
|
+
path7.join(binDir, "..", "typescript"),
|
|
3106
|
+
path7.join(binDir, "..", "..", "typescript")
|
|
3107
|
+
];
|
|
3108
|
+
}
|
|
3109
|
+
async function typescriptVersionForTsc(tscPath) {
|
|
3110
|
+
if (!path7.isAbsolute(tscPath))
|
|
3111
|
+
return void 0;
|
|
3112
|
+
for (const dir of typescriptDirsForTsc(tscPath)) {
|
|
3113
|
+
let manifest;
|
|
3114
|
+
try {
|
|
3115
|
+
manifest = await readFile(path7.join(dir, "package.json"), "utf8");
|
|
3116
|
+
} catch {
|
|
3117
|
+
continue;
|
|
3118
|
+
}
|
|
3119
|
+
let version;
|
|
3120
|
+
try {
|
|
3121
|
+
const parsed = JSON.parse(manifest);
|
|
3122
|
+
if (typeof parsed !== "object" || parsed === null || !("version" in parsed) || typeof parsed.version !== "string") {
|
|
3123
|
+
return void 0;
|
|
3124
|
+
}
|
|
3125
|
+
version = parsed.version;
|
|
3126
|
+
} catch {
|
|
3127
|
+
return void 0;
|
|
3128
|
+
}
|
|
3129
|
+
const majorText = version.split(".", 1)[0] ?? "";
|
|
3130
|
+
const major = /^\d+$/.test(majorText) ? Number(majorText) : Number.NaN;
|
|
3131
|
+
if (!Number.isFinite(major))
|
|
3132
|
+
return void 0;
|
|
3133
|
+
return { version, major };
|
|
3134
|
+
}
|
|
3135
|
+
return void 0;
|
|
3136
|
+
}
|
|
3137
|
+
async function findTsserverPath(root, allowInstall) {
|
|
3138
|
+
const fs5 = await import("node:fs/promises");
|
|
3139
|
+
const ancestorHit = await findAncestorFile(root, "node_modules", "typescript", "lib", "tsserver.js");
|
|
3140
|
+
if (ancestorHit)
|
|
3141
|
+
return ancestorHit;
|
|
3142
|
+
const cwdCandidate = path7.join(process.cwd(), "node_modules", "typescript", "lib", "tsserver.js");
|
|
3143
|
+
try {
|
|
3144
|
+
await fs5.access(cwdCandidate);
|
|
3145
|
+
return cwdCandidate;
|
|
3146
|
+
} catch {
|
|
3147
|
+
}
|
|
3148
|
+
const tsserverForTsc = async (tscPath) => {
|
|
3149
|
+
if (!tscPath)
|
|
3150
|
+
return void 0;
|
|
3151
|
+
for (const dir of typescriptDirsForTsc(tscPath)) {
|
|
3152
|
+
const candidate = path7.join(dir, "lib", "tsserver.js");
|
|
3153
|
+
try {
|
|
3154
|
+
await fs5.access(candidate);
|
|
3155
|
+
return candidate;
|
|
3156
|
+
} catch {
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
return void 0;
|
|
3160
|
+
};
|
|
3161
|
+
const installAllowed = canInstall(allowInstall);
|
|
3162
|
+
const discoveredTsc = await ensureTool("typescript", {
|
|
3163
|
+
allowInstall: installAllowed
|
|
3164
|
+
});
|
|
3165
|
+
const discoveredTsserver = await tsserverForTsc(discoveredTsc);
|
|
3166
|
+
if (discoveredTsserver || !discoveredTsc || !installAllowed || classicTsRepairState().attempted) {
|
|
3167
|
+
return discoveredTsserver;
|
|
3168
|
+
}
|
|
3169
|
+
const discoveredVersion = await typescriptVersionForTsc(discoveredTsc);
|
|
3170
|
+
if (!discoveredVersion || discoveredVersion.major < 7)
|
|
3171
|
+
return void 0;
|
|
3172
|
+
classicTsRepairState().attempted = true;
|
|
3173
|
+
logSessionStart(`lsp typescript: managed compiler resolved to TypeScript ${discoveredVersion.version}, which ships no tsserver.js; reinstalling pinned classic fallback`);
|
|
3174
|
+
const repairedTsc = await ensureTool("typescript", {
|
|
3175
|
+
allowInstall: true,
|
|
3176
|
+
forceReinstall: true
|
|
3177
|
+
});
|
|
3178
|
+
return tsserverForTsc(repairedTsc);
|
|
3179
|
+
}
|
|
3180
|
+
async function findNativeTypeScriptLsp(root) {
|
|
3181
|
+
let currentDir = path7.resolve(root);
|
|
3182
|
+
while (!isAtOrAboveHomeDir(currentDir)) {
|
|
3183
|
+
const typescriptDir = path7.join(currentDir, "node_modules", "typescript");
|
|
3184
|
+
const packageJsonPath = path7.join(typescriptDir, "package.json");
|
|
3185
|
+
let packageJsonText;
|
|
3186
|
+
try {
|
|
3187
|
+
packageJsonText = await readFile(packageJsonPath, "utf8");
|
|
3188
|
+
} catch (error) {
|
|
3189
|
+
if (error.code !== "ENOENT") {
|
|
3190
|
+
return void 0;
|
|
3191
|
+
}
|
|
3192
|
+
try {
|
|
3193
|
+
const dirStat = await stat(typescriptDir);
|
|
3194
|
+
if (dirStat.isDirectory())
|
|
3195
|
+
return void 0;
|
|
3196
|
+
} catch {
|
|
3197
|
+
}
|
|
3198
|
+
const parent = path7.dirname(currentDir);
|
|
3199
|
+
if (parent === currentDir)
|
|
3200
|
+
return void 0;
|
|
3201
|
+
currentDir = parent;
|
|
3202
|
+
continue;
|
|
3203
|
+
}
|
|
3204
|
+
let version;
|
|
3205
|
+
try {
|
|
3206
|
+
const parsed = JSON.parse(packageJsonText);
|
|
3207
|
+
if (typeof parsed !== "object" || parsed === null || !("version" in parsed) || typeof parsed.version !== "string") {
|
|
3208
|
+
return void 0;
|
|
3209
|
+
}
|
|
3210
|
+
version = parsed.version;
|
|
3211
|
+
} catch {
|
|
3212
|
+
return void 0;
|
|
3213
|
+
}
|
|
3214
|
+
const majorText = version.split(".", 1)[0] ?? "";
|
|
3215
|
+
const major = /^\d+$/.test(majorText) ? Number(majorText) : Number.NaN;
|
|
3216
|
+
if (!Number.isFinite(major) || major < 7)
|
|
3217
|
+
return void 0;
|
|
3218
|
+
const localTsc = path7.join(currentDir, "node_modules", ".bin", "tsc");
|
|
3219
|
+
const candidates = process.platform === "win32" ? [`${localTsc}.cmd`, `${localTsc}.exe`, localTsc] : [localTsc];
|
|
3220
|
+
for (const command of candidates) {
|
|
3221
|
+
try {
|
|
3222
|
+
await access(command);
|
|
3223
|
+
return { command, version };
|
|
3224
|
+
} catch {
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3227
|
+
return void 0;
|
|
3228
|
+
}
|
|
3229
|
+
return void 0;
|
|
3230
|
+
}
|
|
3231
|
+
function dotnetToolCandidates(tool) {
|
|
3232
|
+
const home = os6.homedir();
|
|
3233
|
+
return [
|
|
3234
|
+
path7.join(PI_LENS_BIN_DIR2, `${tool}.exe`),
|
|
3235
|
+
path7.join(PI_LENS_BIN_DIR2, tool),
|
|
3236
|
+
path7.join(home, ".dotnet", "tools", `${tool}.exe`),
|
|
3237
|
+
path7.join(home, ".dotnet", "tools", tool),
|
|
3238
|
+
tool
|
|
3239
|
+
].filter(Boolean);
|
|
3240
|
+
}
|
|
3241
|
+
function binExeVariants(dir, tool) {
|
|
3242
|
+
return process.platform === "win32" ? [path7.join(dir, `${tool}.exe`), path7.join(dir, tool)] : [path7.join(dir, tool)];
|
|
3243
|
+
}
|
|
3244
|
+
function goBinCandidates(tool) {
|
|
3245
|
+
const gopath = process.env.GOPATH?.split(path7.delimiter)[0] || path7.join(os6.homedir(), "go");
|
|
3246
|
+
return [tool, ...binExeVariants(path7.join(gopath, "bin"), tool)];
|
|
3247
|
+
}
|
|
3248
|
+
function cargoBinCandidates(tool) {
|
|
3249
|
+
const cargoHome = process.env.CARGO_HOME || path7.join(os6.homedir(), ".cargo");
|
|
3250
|
+
return [tool, ...binExeVariants(path7.join(cargoHome, "bin"), tool)];
|
|
3251
|
+
}
|
|
3252
|
+
async function tryGemInstall(gem) {
|
|
3253
|
+
const { join: join3 } = await import("node:path");
|
|
3254
|
+
const binDir = join3(getGlobalPiLensDir(), "bin");
|
|
3255
|
+
const { mkdir } = await import("node:fs/promises");
|
|
3256
|
+
await mkdir(binDir, { recursive: true });
|
|
3257
|
+
const result = await safeSpawnAsync("gem", ["install", gem, "--bindir", binDir, "--no-document"], { timeout: 18e4, ignoreAmbientSignal: true });
|
|
3258
|
+
const ok = !result.error && result.status === 0;
|
|
3259
|
+
if (ok) {
|
|
3260
|
+
const sep2 = process.platform === "win32" ? ";" : ":";
|
|
3261
|
+
if (!process.env.PATH?.includes(binDir)) {
|
|
3262
|
+
process.env.PATH = `${binDir}${sep2}${process.env.PATH ?? ""}`;
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
return ok;
|
|
3266
|
+
}
|
|
3267
|
+
function DenoExcludeRoot(primary) {
|
|
3268
|
+
const denoDetector = createRootDetector(["deno.json", "deno.jsonc"]);
|
|
3269
|
+
return async (file) => {
|
|
3270
|
+
const denoRoot = await denoDetector(file);
|
|
3271
|
+
if (denoRoot)
|
|
3272
|
+
return void 0;
|
|
3273
|
+
return primary(file);
|
|
3274
|
+
};
|
|
3275
|
+
}
|
|
3276
|
+
var JS_TS_LSP_EXTENSIONS = KIND_EXTENSIONS["jsts"].filter((ext) => ext !== ".svelte" && ext !== ".vue");
|
|
3277
|
+
var TS_CONFIG_MARKERS = ["tsconfig.json", "jsconfig.json"];
|
|
3278
|
+
var TS_TOOLING_MARKERS = [
|
|
3279
|
+
"package-lock.json",
|
|
3280
|
+
"bun.lockb",
|
|
3281
|
+
"bun.lock",
|
|
3282
|
+
"pnpm-lock.yaml",
|
|
3283
|
+
"yarn.lock",
|
|
3284
|
+
"package.json"
|
|
3285
|
+
];
|
|
3286
|
+
var TS_FAMILY_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts"]);
|
|
3287
|
+
function isTsFamilyFile(file) {
|
|
3288
|
+
return TS_FAMILY_EXTENSIONS.has(path7.extname(file).toLowerCase());
|
|
3289
|
+
}
|
|
3290
|
+
function tsConfigMarkersForFile(file) {
|
|
3291
|
+
return isTsFamilyFile(file) ? ["tsconfig.json"] : TS_CONFIG_MARKERS;
|
|
3292
|
+
}
|
|
3293
|
+
var TypeScriptConfigRootTsOnly = IgnoreHomeRoot(createRootDetector(["tsconfig.json"]));
|
|
3294
|
+
var TypeScriptConfigRootEither = IgnoreHomeRoot(createRootDetector([...TS_CONFIG_MARKERS]));
|
|
3295
|
+
var TypeScriptToolingRoot = IgnoreHomeRoot(createRootDetector([...TS_TOOLING_MARKERS]));
|
|
3296
|
+
async function findTypeScriptProjectRoot(file) {
|
|
3297
|
+
const configDetector = isTsFamilyFile(file) ? TypeScriptConfigRootTsOnly : TypeScriptConfigRootEither;
|
|
3298
|
+
const [configRoot, toolingRoot] = await Promise.all([
|
|
3299
|
+
configDetector(file),
|
|
3300
|
+
TypeScriptToolingRoot(file)
|
|
3301
|
+
]);
|
|
3302
|
+
if (!configRoot)
|
|
3303
|
+
return toolingRoot;
|
|
3304
|
+
if (!toolingRoot)
|
|
3305
|
+
return configRoot;
|
|
3306
|
+
return isSameOrWithin(toolingRoot, configRoot) ? configRoot : toolingRoot;
|
|
3307
|
+
}
|
|
3308
|
+
async function findExtensionBoundedRoot(file, extensionRootKey) {
|
|
3309
|
+
const startDir = path7.resolve(path7.dirname(file));
|
|
3310
|
+
let currentDir = startDir;
|
|
3311
|
+
const configMarkers = tsConfigMarkersForFile(file);
|
|
3312
|
+
while (true) {
|
|
3313
|
+
for (const pattern of configMarkers) {
|
|
3314
|
+
try {
|
|
3315
|
+
await stat(path7.join(currentDir, pattern));
|
|
3316
|
+
return currentDir;
|
|
3317
|
+
} catch {
|
|
3318
|
+
}
|
|
3319
|
+
}
|
|
3320
|
+
for (const pattern of TS_TOOLING_MARKERS) {
|
|
3321
|
+
try {
|
|
3322
|
+
await stat(path7.join(currentDir, pattern));
|
|
3323
|
+
return currentDir;
|
|
3324
|
+
} catch {
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
const currentKey = normalizeEphemeralMapKey(path7.resolve(currentDir));
|
|
3328
|
+
if (currentKey === extensionRootKey)
|
|
3329
|
+
return void 0;
|
|
3330
|
+
const parent = path7.dirname(currentDir);
|
|
3331
|
+
if (parent === currentDir)
|
|
3332
|
+
return void 0;
|
|
3333
|
+
currentDir = parent;
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
async function hasAgentLevelProjectMarker(extensionRootKey) {
|
|
3337
|
+
const agentDir = path7.dirname(extensionRootKey);
|
|
3338
|
+
if (!agentDir || agentDir === extensionRootKey)
|
|
3339
|
+
return false;
|
|
3340
|
+
for (const pattern of [...TS_CONFIG_MARKERS, ...TS_TOOLING_MARKERS]) {
|
|
3341
|
+
try {
|
|
3342
|
+
await stat(path7.join(agentDir, pattern));
|
|
3343
|
+
return true;
|
|
3344
|
+
} catch {
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
3347
|
+
return false;
|
|
3348
|
+
}
|
|
3349
|
+
var TypeScriptRoot = withRootMarkers(DenoExcludeRoot(async (file) => {
|
|
3350
|
+
const extensionRootKey = piAgentExtensionsRootKey(file);
|
|
3351
|
+
if (extensionRootKey) {
|
|
3352
|
+
const bounded2 = await findExtensionBoundedRoot(file, extensionRootKey);
|
|
3353
|
+
if (bounded2)
|
|
3354
|
+
return bounded2;
|
|
3355
|
+
if (await hasAgentLevelProjectMarker(extensionRootKey)) {
|
|
3356
|
+
return FileDirRoot(file);
|
|
3357
|
+
}
|
|
3358
|
+
return void 0;
|
|
3359
|
+
}
|
|
3360
|
+
const projectRoot = await findTypeScriptProjectRoot(file);
|
|
3361
|
+
if (projectRoot)
|
|
3362
|
+
return projectRoot;
|
|
3363
|
+
return FileDirRoot(file);
|
|
3364
|
+
}), [...TS_CONFIG_MARKERS, ...TS_TOOLING_MARKERS]);
|
|
3365
|
+
var TypeScriptServer = {
|
|
3366
|
+
id: "typescript",
|
|
3367
|
+
idleEviction: "transparent",
|
|
3368
|
+
role: "language",
|
|
3369
|
+
name: "TypeScript Language Server",
|
|
3370
|
+
extensions: JS_TS_LSP_EXTENSIONS,
|
|
3371
|
+
autoPropagateDiagnostics: true,
|
|
3372
|
+
root: TypeScriptRoot,
|
|
3373
|
+
rootMarkers: TypeScriptRoot.rootMarkers,
|
|
3374
|
+
async spawn(root, options) {
|
|
3375
|
+
const fs5 = await import("node:fs/promises");
|
|
3376
|
+
const nativeLsp = await findNativeTypeScriptLsp(root);
|
|
3377
|
+
if (nativeLsp) {
|
|
3378
|
+
const env2 = await getToolEnvironment();
|
|
3379
|
+
logSessionStart(`lsp typescript-native: version=${nativeLsp.version} command=${nativeLsp.command}`);
|
|
3380
|
+
const proc2 = await launchLSP(nativeLsp.command, ["--lsp", "--stdio"], {
|
|
3381
|
+
cwd: root,
|
|
3382
|
+
env: env2
|
|
3383
|
+
});
|
|
3384
|
+
return { process: proc2, source: "direct", launchVariant: "native-ts7" };
|
|
3385
|
+
}
|
|
3386
|
+
let source = "direct";
|
|
3387
|
+
let lspPath = await findAncestorFileAmong(root, [
|
|
3388
|
+
["node_modules", ".bin", "typescript-language-server.cmd"],
|
|
3389
|
+
["node_modules", ".bin", "typescript-language-server"]
|
|
3390
|
+
]);
|
|
3391
|
+
if (!lspPath) {
|
|
3392
|
+
lspPath = await ensureTool("typescript-language-server", {
|
|
3393
|
+
allowInstall: canInstall(options?.allowInstall)
|
|
3394
|
+
});
|
|
3395
|
+
if (lspPath)
|
|
3396
|
+
source = "managed";
|
|
3397
|
+
if (!lspPath) {
|
|
3398
|
+
return void 0;
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
let tsserverPath = await findTsserverPath(root, options?.allowInstall);
|
|
3402
|
+
if (!tsserverPath) {
|
|
3403
|
+
const localCandidate = path7.join(path7.dirname(lspPath), "..", "typescript", "lib", "tsserver.js");
|
|
3404
|
+
try {
|
|
3405
|
+
await fs5.access(localCandidate);
|
|
3406
|
+
tsserverPath = localCandidate;
|
|
3407
|
+
} catch {
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
if (tsserverPath)
|
|
3411
|
+
source = "managed";
|
|
3412
|
+
const env = await getToolEnvironment();
|
|
3413
|
+
const proc = await launchLSP(lspPath, ["--stdio"], {
|
|
3414
|
+
cwd: root,
|
|
3415
|
+
env: {
|
|
3416
|
+
...env,
|
|
3417
|
+
TSSERVER_PATH: tsserverPath
|
|
3418
|
+
}
|
|
3419
|
+
});
|
|
3420
|
+
return {
|
|
3421
|
+
process: proc,
|
|
3422
|
+
source,
|
|
3423
|
+
initialization: tsserverPath ? { tsserver: { path: tsserverPath } } : void 0,
|
|
3424
|
+
launchVariant: "classic"
|
|
3425
|
+
};
|
|
3426
|
+
}
|
|
3427
|
+
};
|
|
3428
|
+
var DenoServer = {
|
|
3429
|
+
id: "deno",
|
|
3430
|
+
idleEviction: "transparent",
|
|
3431
|
+
role: "language",
|
|
3432
|
+
name: "Deno Language Server",
|
|
3433
|
+
fallbackFor: "typescript",
|
|
3434
|
+
extensions: JS_TS_LSP_EXTENSIONS,
|
|
3435
|
+
autoPropagateDiagnostics: true,
|
|
3436
|
+
root: createRootDetector(["deno.json", "deno.jsonc"]),
|
|
3437
|
+
async spawn(root, options) {
|
|
3438
|
+
return resolveAndLaunch({
|
|
3439
|
+
candidates: ["deno"],
|
|
3440
|
+
args: ["lsp"],
|
|
3441
|
+
cwd: root,
|
|
3442
|
+
managedToolId: "deno"
|
|
3443
|
+
}, options?.allowInstall);
|
|
3444
|
+
}
|
|
3445
|
+
};
|
|
3446
|
+
var PythonServer = {
|
|
3447
|
+
id: "python",
|
|
3448
|
+
idleEviction: "transparent",
|
|
3449
|
+
role: "language",
|
|
3450
|
+
name: "Pyright Language Server",
|
|
3451
|
+
extensions: KIND_EXTENSIONS["python"],
|
|
3452
|
+
root: RootWithFallback(createRootDetector([
|
|
3453
|
+
".git",
|
|
3454
|
+
"pyproject.toml",
|
|
3455
|
+
"setup.py",
|
|
3456
|
+
"setup.cfg",
|
|
3457
|
+
"requirements.txt",
|
|
3458
|
+
"Pipfile",
|
|
3459
|
+
"poetry.lock"
|
|
3460
|
+
])),
|
|
3461
|
+
async spawn(root, options) {
|
|
3462
|
+
const pythonEnvironment = await detectPythonEnvironment(root);
|
|
3463
|
+
const env = augmentPythonEnvironment(await getToolEnvironment(), pythonEnvironment);
|
|
3464
|
+
let source = "direct";
|
|
3465
|
+
const pyrightInit = (pythonPath) => ({
|
|
3466
|
+
...pythonPath ? { pythonPath } : {},
|
|
3467
|
+
openFilesOnly: true
|
|
3468
|
+
});
|
|
3469
|
+
const projectPyright = await resolveAndLaunch({
|
|
3470
|
+
candidates: [
|
|
3471
|
+
...pythonEnvironmentToolCandidates(pythonEnvironment, "pyright-langserver"),
|
|
3472
|
+
...nodeBinLocalCandidates(root, "pyright-langserver"),
|
|
3473
|
+
...pythonEnvironmentToolCandidates(pythonEnvironment, "basedpyright-langserver"),
|
|
3474
|
+
...nodeBinLocalCandidates(root, "basedpyright-langserver")
|
|
3475
|
+
],
|
|
3476
|
+
args: ["--stdio"],
|
|
3477
|
+
cwd: root,
|
|
3478
|
+
env
|
|
3479
|
+
}, false);
|
|
3480
|
+
if (projectPyright) {
|
|
3481
|
+
return {
|
|
3482
|
+
process: projectPyright.process,
|
|
3483
|
+
source: projectPyright.source,
|
|
3484
|
+
initialization: pyrightInit(pythonEnvironment?.pythonPath)
|
|
3485
|
+
};
|
|
3486
|
+
}
|
|
3487
|
+
const projectTy = await resolveAndLaunch({
|
|
3488
|
+
candidates: pythonEnvironmentToolCandidates(pythonEnvironment, "ty"),
|
|
3489
|
+
args: ["server"],
|
|
3490
|
+
cwd: root,
|
|
3491
|
+
env
|
|
3492
|
+
}, false);
|
|
3493
|
+
if (projectTy) {
|
|
3494
|
+
return { process: projectTy.process, source: projectTy.source };
|
|
3495
|
+
}
|
|
3496
|
+
const pathPyright = await resolveAndLaunch({
|
|
3497
|
+
candidates: ["pyright-langserver", "basedpyright-langserver"],
|
|
3498
|
+
args: ["--stdio"],
|
|
3499
|
+
cwd: root,
|
|
3500
|
+
env
|
|
3501
|
+
}, false);
|
|
3502
|
+
if (pathPyright) {
|
|
3503
|
+
return {
|
|
3504
|
+
process: pathPyright.process,
|
|
3505
|
+
source: pathPyright.source,
|
|
3506
|
+
initialization: pyrightInit(pythonEnvironment?.pythonPath)
|
|
3507
|
+
};
|
|
3508
|
+
}
|
|
3509
|
+
const pathTy = await resolveAndLaunch({
|
|
3510
|
+
candidates: ["ty"],
|
|
3511
|
+
args: ["server"],
|
|
3512
|
+
cwd: root,
|
|
3513
|
+
env
|
|
3514
|
+
}, false);
|
|
3515
|
+
if (pathTy) {
|
|
3516
|
+
return { process: pathTy.process, source: pathTy.source };
|
|
3517
|
+
}
|
|
3518
|
+
const pyrightPath = await ensureTool("pyright", {
|
|
3519
|
+
allowInstall: canInstall(options?.allowInstall)
|
|
3520
|
+
});
|
|
3521
|
+
if (!pyrightPath)
|
|
3522
|
+
return void 0;
|
|
3523
|
+
source = "managed";
|
|
3524
|
+
const binDir = path7.dirname(pyrightPath);
|
|
3525
|
+
const isWindows2 = process.platform === "win32";
|
|
3526
|
+
const managedCandidates = isWindows2 ? [
|
|
3527
|
+
path7.join(binDir, "pyright-langserver.cmd"),
|
|
3528
|
+
path7.join(binDir, "pyright-langserver"),
|
|
3529
|
+
"pyright-langserver"
|
|
3530
|
+
] : [path7.join(binDir, "pyright-langserver"), "pyright-langserver"];
|
|
3531
|
+
const resolved = await resolveAndLaunch({ candidates: managedCandidates, args: ["--stdio"], cwd: root, env }, false);
|
|
3532
|
+
if (!resolved)
|
|
3533
|
+
return void 0;
|
|
3534
|
+
return {
|
|
3535
|
+
process: resolved.process,
|
|
3536
|
+
source,
|
|
3537
|
+
initialization: pyrightInit(pythonEnvironment?.pythonPath)
|
|
3538
|
+
};
|
|
3539
|
+
}
|
|
3540
|
+
};
|
|
3541
|
+
var PythonJediServer = {
|
|
3542
|
+
id: "python-jedi",
|
|
3543
|
+
idleEviction: "transparent",
|
|
3544
|
+
role: "language",
|
|
3545
|
+
name: "Jedi Language Server",
|
|
3546
|
+
fallbackFor: "python",
|
|
3547
|
+
extensions: KIND_EXTENSIONS["python"],
|
|
3548
|
+
root: RootWithFallback(createRootDetector([
|
|
3549
|
+
".git",
|
|
3550
|
+
"pyproject.toml",
|
|
3551
|
+
"setup.py",
|
|
3552
|
+
"setup.cfg",
|
|
3553
|
+
"requirements.txt",
|
|
3554
|
+
"Pipfile",
|
|
3555
|
+
"poetry.lock"
|
|
3556
|
+
])),
|
|
3557
|
+
async spawn(root, options) {
|
|
3558
|
+
const launched = await resolveAndLaunch({
|
|
3559
|
+
candidates: ["jedi-language-server"],
|
|
3560
|
+
args: [],
|
|
3561
|
+
cwd: root,
|
|
3562
|
+
managedToolId: "jedi-language-server"
|
|
3563
|
+
}, options?.allowInstall);
|
|
3564
|
+
if (!launched)
|
|
3565
|
+
return void 0;
|
|
3566
|
+
const pythonPath = await detectPythonVenv(root);
|
|
3567
|
+
return {
|
|
3568
|
+
...launched,
|
|
3569
|
+
initialization: pythonPath ? { workspace: { environmentPath: pythonPath } } : {}
|
|
3570
|
+
};
|
|
3571
|
+
}
|
|
3572
|
+
};
|
|
3573
|
+
var GoServer = {
|
|
3574
|
+
id: "go",
|
|
3575
|
+
idleEviction: "unmeasured",
|
|
3576
|
+
role: "language",
|
|
3577
|
+
name: "gopls",
|
|
3578
|
+
extensions: KIND_EXTENSIONS["go"],
|
|
3579
|
+
root: RootWithFallback(WorkspacePriorityRoot([["go.work"], ["go.mod", "go.sum"], [".git"]])),
|
|
3580
|
+
async spawn(root, options) {
|
|
3581
|
+
const result = await resolveAndLaunch({
|
|
3582
|
+
// Canonical-bin discovery (#241): include $GOPATH/bin so a gopls that
|
|
3583
|
+
// `go install` dropped there resolves even when it isn't on PATH —
|
|
3584
|
+
// which is also the retry target after the runtimeInstall below.
|
|
3585
|
+
candidates: goBinCandidates("gopls"),
|
|
3586
|
+
args: [],
|
|
3587
|
+
cwd: root,
|
|
3588
|
+
runtimeInstall: {
|
|
3589
|
+
runtimeCommand: "go",
|
|
3590
|
+
install: tryGoInstallGopls
|
|
3591
|
+
}
|
|
3592
|
+
}, options?.allowInstall);
|
|
3593
|
+
if (!result)
|
|
3594
|
+
return void 0;
|
|
3595
|
+
return { ...result, initialization: { ui: { semanticTokens: true } } };
|
|
3596
|
+
}
|
|
3597
|
+
};
|
|
3598
|
+
function cargoWorkspaceDeclaresMember(workspaceContent, parentDir, childDir) {
|
|
3599
|
+
const relativePath = path7.relative(parentDir, childDir).split(path7.sep).join("/");
|
|
3600
|
+
if (relativePath === "" || relativePath.startsWith(".."))
|
|
3601
|
+
return false;
|
|
3602
|
+
const matches = (pattern) => matchesWorkspaceMemberPattern(pattern, relativePath, CARGO_WORKSPACE_MEMBER_DIALECT, () => recordDegradationOnce({
|
|
3603
|
+
kind: "workspace-glob-cap",
|
|
3604
|
+
subject: String(pattern.length),
|
|
3605
|
+
reason: "workspace glob matcher exceeded its memo-table cell cap"
|
|
3606
|
+
}));
|
|
3607
|
+
const excluded = readCargoWorkspaceExclude(workspaceContent);
|
|
3608
|
+
if (excluded.some(matches))
|
|
3609
|
+
return false;
|
|
3610
|
+
return readCargoWorkspaceMembers(workspaceContent).some(matches);
|
|
3611
|
+
}
|
|
3612
|
+
function sessionHoistCeiling(sessionCwd, file) {
|
|
3613
|
+
return isSameOrWithin(path7.resolve(sessionCwd), path7.resolve(file)) ? path7.resolve(sessionCwd) : void 0;
|
|
3614
|
+
}
|
|
3615
|
+
function RustWorkspaceRoot() {
|
|
3616
|
+
const crateRoot = createRootDetector(["Cargo.toml", "Cargo.lock"]);
|
|
3617
|
+
return withRootMarkers(async (file) => {
|
|
3618
|
+
const root = await crateRoot(file);
|
|
3619
|
+
if (!root)
|
|
3620
|
+
return void 0;
|
|
3621
|
+
const sessionCwd = process.cwd();
|
|
3622
|
+
const stop = sessionHoistCeiling(sessionCwd, file);
|
|
3623
|
+
let current = root;
|
|
3624
|
+
const fsRoot = path7.parse(current).root;
|
|
3625
|
+
while (true) {
|
|
3626
|
+
if (stop !== void 0 && current === stop)
|
|
3627
|
+
break;
|
|
3628
|
+
const parent = path7.dirname(current);
|
|
3629
|
+
if (parent === current || parent === fsRoot)
|
|
3630
|
+
break;
|
|
3631
|
+
const parentCargoPath = path7.join(parent, "Cargo.toml");
|
|
3632
|
+
const parentCargoContent = await readTextFileOrUndefined(parentCargoPath);
|
|
3633
|
+
if (parentCargoContent !== void 0 && hasCargoWorkspaceTable(parentCargoContent)) {
|
|
3634
|
+
if (cargoWorkspaceDeclaresMember(parentCargoContent, parent, root)) {
|
|
3635
|
+
return enforceLspRootCeiling(parent, sessionCwd, file);
|
|
3636
|
+
}
|
|
3637
|
+
break;
|
|
3638
|
+
}
|
|
3639
|
+
current = parent;
|
|
3640
|
+
}
|
|
3641
|
+
return root;
|
|
3642
|
+
}, crateRoot.rootMarkers ?? []);
|
|
3643
|
+
}
|
|
3644
|
+
function stripXmlComments(content) {
|
|
3645
|
+
let result = content;
|
|
3646
|
+
let previous;
|
|
3647
|
+
do {
|
|
3648
|
+
previous = result;
|
|
3649
|
+
result = result.replace(/<!--[\s\S]*?-->/g, "");
|
|
3650
|
+
} while (result !== previous);
|
|
3651
|
+
return result;
|
|
3652
|
+
}
|
|
3653
|
+
async function declaresMavenModule(parentDir, parentPomPath, childDir) {
|
|
3654
|
+
try {
|
|
3655
|
+
const content = stripXmlComments(await readFile(parentPomPath, "utf-8"));
|
|
3656
|
+
const modulesBlock = content.match(/<modules>([\s\S]*?)<\/modules>/);
|
|
3657
|
+
if (!modulesBlock)
|
|
3658
|
+
return false;
|
|
3659
|
+
const resolvedChild = path7.resolve(childDir);
|
|
3660
|
+
for (const match of modulesBlock[1].matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)) {
|
|
3661
|
+
if (pathsEqual(path7.resolve(parentDir, match[1]), resolvedChild))
|
|
3662
|
+
return true;
|
|
3663
|
+
}
|
|
3664
|
+
return false;
|
|
3665
|
+
} catch {
|
|
3666
|
+
return false;
|
|
3667
|
+
}
|
|
3668
|
+
}
|
|
3669
|
+
function JavaWorkspaceRoot() {
|
|
3670
|
+
const moduleRoot = createRootDetector([
|
|
3671
|
+
"pom.xml",
|
|
3672
|
+
"build.gradle",
|
|
3673
|
+
".classpath"
|
|
3674
|
+
]);
|
|
3675
|
+
return withRootMarkers(async (file) => {
|
|
3676
|
+
const root = await moduleRoot(file);
|
|
3677
|
+
if (!root)
|
|
3678
|
+
return void 0;
|
|
3679
|
+
if (!await markerExists(root, "pom.xml"))
|
|
3680
|
+
return root;
|
|
3681
|
+
const sessionCwd = process.cwd();
|
|
3682
|
+
const stop = sessionHoistCeiling(sessionCwd, file);
|
|
3683
|
+
let current = root;
|
|
3684
|
+
let lastHop = root;
|
|
3685
|
+
const fsRoot = path7.parse(current).root;
|
|
3686
|
+
while (true) {
|
|
3687
|
+
if (stop !== void 0 && current === stop)
|
|
3688
|
+
break;
|
|
3689
|
+
const parent = path7.dirname(current);
|
|
3690
|
+
if (parent === current || parent === fsRoot)
|
|
3691
|
+
break;
|
|
3692
|
+
if (await markerExists(parent, "pom.xml")) {
|
|
3693
|
+
const parentPom = path7.join(parent, "pom.xml");
|
|
3694
|
+
if (!await declaresMavenModule(parent, parentPom, lastHop))
|
|
3695
|
+
break;
|
|
3696
|
+
current = parent;
|
|
3697
|
+
lastHop = parent;
|
|
3698
|
+
continue;
|
|
3699
|
+
}
|
|
3700
|
+
current = parent;
|
|
3701
|
+
}
|
|
3702
|
+
return enforceLspRootCeiling(lastHop, sessionCwd, file);
|
|
3703
|
+
}, moduleRoot.rootMarkers ?? []);
|
|
3704
|
+
}
|
|
3705
|
+
var RustServer = {
|
|
3706
|
+
id: "rust",
|
|
3707
|
+
idleEviction: "unmeasured",
|
|
3708
|
+
role: "language",
|
|
3709
|
+
// Measured (#3750): rust-analyzer answers an empty result for a detached file.
|
|
3710
|
+
requiresProjectRoot: true,
|
|
3711
|
+
name: "rust-analyzer",
|
|
3712
|
+
extensions: KIND_EXTENSIONS["rust"],
|
|
3713
|
+
// No FileDirRoot fallback (#201): rust-analyzer is a heavy workspace server
|
|
3714
|
+
// that is useless without a Cargo manifest. With the fallback, every .rs file
|
|
3715
|
+
// written before a Cargo.toml exists resolved to its OWN directory as the
|
|
3716
|
+
// root, and since clients dedup by `${serverId}:${root}`, each directory
|
|
3717
|
+
// spawned a separate rust-analyzer (one per file/dir during scaffolding).
|
|
3718
|
+
// Returning undefined here skips the spawn until a Cargo.toml gives a stable,
|
|
3719
|
+
// shared crate root — then all files share one server.
|
|
3720
|
+
root: RustWorkspaceRoot(),
|
|
3721
|
+
async spawn(root, options) {
|
|
3722
|
+
const result = await resolveAndLaunch({
|
|
3723
|
+
candidates: cargoBinCandidates("rust-analyzer"),
|
|
3724
|
+
args: [],
|
|
3725
|
+
cwd: root,
|
|
3726
|
+
managedToolId: "rust-analyzer"
|
|
3727
|
+
}, options?.allowInstall);
|
|
3728
|
+
if (!result)
|
|
3729
|
+
return void 0;
|
|
3730
|
+
return {
|
|
3731
|
+
...result,
|
|
3732
|
+
initialization: {
|
|
3733
|
+
cargo: { buildScripts: { enable: true } },
|
|
3734
|
+
procMacro: { enable: true },
|
|
3735
|
+
diagnostics: { enable: true }
|
|
3736
|
+
}
|
|
3737
|
+
};
|
|
3738
|
+
}
|
|
3739
|
+
};
|
|
3740
|
+
var RubyServer = {
|
|
3741
|
+
id: "ruby",
|
|
3742
|
+
idleEviction: "unmeasured",
|
|
3743
|
+
role: "language",
|
|
3744
|
+
name: "Ruby LSP",
|
|
3745
|
+
extensions: KIND_EXTENSIONS["ruby"],
|
|
3746
|
+
root: RootWithFallback(PriorityRoot([["Gemfile", ".ruby-version"], [".git"]])),
|
|
3747
|
+
// Ruby LSP may need extra time to finish composed-bundle setup before it can
|
|
3748
|
+
// answer initialize/documentSymbol on cold start.
|
|
3749
|
+
initializeTimeoutMs: 3e4,
|
|
3750
|
+
clientWaitTimeoutMs: 3e4,
|
|
3751
|
+
async spawn(root, options) {
|
|
3752
|
+
const rubylsp = await resolveAndLaunch({
|
|
3753
|
+
candidates: ["ruby-lsp", ...rubyBinCandidates("ruby-lsp")],
|
|
3754
|
+
args: [],
|
|
3755
|
+
cwd: root,
|
|
3756
|
+
runtimeInstall: {
|
|
3757
|
+
runtimeCommand: "gem",
|
|
3758
|
+
install: () => tryGemInstall("ruby-lsp"),
|
|
3759
|
+
retryCandidates: ["ruby-lsp", ...rubyBinCandidates("ruby-lsp")]
|
|
3760
|
+
}
|
|
3761
|
+
}, options?.allowInstall);
|
|
3762
|
+
if (rubylsp)
|
|
3763
|
+
return rubylsp;
|
|
3764
|
+
const solargraph = await resolveAndLaunch({
|
|
3765
|
+
candidates: ["solargraph", ...rubyBinCandidates("solargraph")],
|
|
3766
|
+
args: ["stdio"],
|
|
3767
|
+
cwd: root
|
|
3768
|
+
}, false);
|
|
3769
|
+
if (solargraph)
|
|
3770
|
+
return solargraph;
|
|
3771
|
+
return resolveAndLaunch({
|
|
3772
|
+
candidates: ["rubocop", ...rubyBinCandidates("rubocop")],
|
|
3773
|
+
args: ["--lsp"],
|
|
3774
|
+
cwd: root
|
|
3775
|
+
}, false);
|
|
3776
|
+
}
|
|
3777
|
+
};
|
|
3778
|
+
var PHPServer = {
|
|
3779
|
+
id: "php",
|
|
3780
|
+
idleEviction: "transparent",
|
|
3781
|
+
role: "language",
|
|
3782
|
+
name: "Intelephense",
|
|
3783
|
+
extensions: KIND_EXTENSIONS["php"],
|
|
3784
|
+
root: RootWithFallback(createRootDetector(["composer.json", "composer.lock"])),
|
|
3785
|
+
async spawn(root, options) {
|
|
3786
|
+
const result = await resolveAndLaunch({
|
|
3787
|
+
candidates: nodeBinCandidates(root, "intelephense"),
|
|
3788
|
+
args: ["--stdio"],
|
|
3789
|
+
cwd: root,
|
|
3790
|
+
managedToolId: "intelephense"
|
|
3791
|
+
}, options?.allowInstall);
|
|
3792
|
+
if (!result)
|
|
3793
|
+
return void 0;
|
|
3794
|
+
return {
|
|
3795
|
+
...result,
|
|
3796
|
+
initialization: {
|
|
3797
|
+
storagePath: path7.join(getGlobalPiLensDir(), "intelephense")
|
|
3798
|
+
}
|
|
3799
|
+
};
|
|
3800
|
+
}
|
|
3801
|
+
};
|
|
3802
|
+
function buildPsesArgs(bundleDir) {
|
|
3803
|
+
const script = path7.join(bundleDir, "PowerShellEditorServices", "Start-EditorServices.ps1");
|
|
3804
|
+
const sessionDir = path7.join(getGlobalPiLensDir(), "pses", `${process.pid}-${Date.now()}`);
|
|
3805
|
+
mkdirSync2(sessionDir, { recursive: true });
|
|
3806
|
+
const logPath = path7.join(sessionDir, "pses.log");
|
|
3807
|
+
const sessionDetailsPath = path7.join(sessionDir, "session.json");
|
|
3808
|
+
return [
|
|
3809
|
+
"-NoLogo",
|
|
3810
|
+
"-NoProfile",
|
|
3811
|
+
"-NonInteractive",
|
|
3812
|
+
// Unsigned bundled script + mark-of-the-web on Windows — Bypass so it runs;
|
|
3813
|
+
// ignored by non-Windows pwsh.
|
|
3814
|
+
"-ExecutionPolicy",
|
|
3815
|
+
"Bypass",
|
|
3816
|
+
"-File",
|
|
3817
|
+
script,
|
|
3818
|
+
"-HostName",
|
|
3819
|
+
"pi-lens",
|
|
3820
|
+
"-HostProfileId",
|
|
3821
|
+
"pi-lens",
|
|
3822
|
+
"-HostVersion",
|
|
3823
|
+
"1.0.0",
|
|
3824
|
+
"-BundledModulesPath",
|
|
3825
|
+
bundleDir,
|
|
3826
|
+
"-LogPath",
|
|
3827
|
+
logPath,
|
|
3828
|
+
"-LogLevel",
|
|
3829
|
+
"Warning",
|
|
3830
|
+
"-SessionDetailsPath",
|
|
3831
|
+
sessionDetailsPath,
|
|
3832
|
+
"-Stdio",
|
|
3833
|
+
"-LanguageServiceOnly"
|
|
3834
|
+
];
|
|
3835
|
+
}
|
|
3836
|
+
var PowerShellServer = {
|
|
3837
|
+
id: "powershell",
|
|
3838
|
+
idleEviction: "unmeasured",
|
|
3839
|
+
role: "language",
|
|
3840
|
+
name: "PowerShell Editor Services",
|
|
3841
|
+
extensions: KIND_EXTENSIONS["powershell"],
|
|
3842
|
+
// Index at the workspace (script modules reference siblings); fall back to the
|
|
3843
|
+
// file dir.
|
|
3844
|
+
root: RootWithFallback(createRootDetector([".git"])),
|
|
3845
|
+
spawn(root, options) {
|
|
3846
|
+
return resolveAndLaunchBundle({
|
|
3847
|
+
runtimeCandidates: ["pwsh", "powershell"],
|
|
3848
|
+
bundleToolId: "powershell-editor-services",
|
|
3849
|
+
cwd: root,
|
|
3850
|
+
args: buildPsesArgs
|
|
3851
|
+
}, options?.allowInstall);
|
|
3852
|
+
}
|
|
3853
|
+
};
|
|
3854
|
+
var CSharpServer = {
|
|
3855
|
+
id: "csharp",
|
|
3856
|
+
idleEviction: "unmeasured",
|
|
3857
|
+
role: "language",
|
|
3858
|
+
// Documented (#3750): csharp-ls needs a solution or project.
|
|
3859
|
+
requiresProjectRoot: true,
|
|
3860
|
+
name: "csharp-ls",
|
|
3861
|
+
extensions: KIND_EXTENSIONS["csharp"],
|
|
3862
|
+
// No FileDirRoot fallback (#201): csharp-ls is a workspace server and should
|
|
3863
|
+
// not spawn once per source directory before a .sln/.csproj exists. Glob root
|
|
3864
|
+
// markers match real project filenames such as `App.csproj` / `App.sln`
|
|
3865
|
+
// (shared marker list — see file-kinds.ts, refs #895).
|
|
3866
|
+
root: createRootDetector([...DOTNET_CSHARP_ROOT_MARKERS]),
|
|
3867
|
+
async spawn(root, options) {
|
|
3868
|
+
const candidates = dotnetToolCandidates("csharp-ls");
|
|
3869
|
+
return resolveAndLaunch({
|
|
3870
|
+
candidates,
|
|
3871
|
+
args: [],
|
|
3872
|
+
cwd: root,
|
|
3873
|
+
runtimeInstall: {
|
|
3874
|
+
runtimeCommand: "dotnet",
|
|
3875
|
+
install: () => tryDotnetToolInstall("csharp-ls"),
|
|
3876
|
+
retryCandidates: candidates
|
|
3877
|
+
}
|
|
3878
|
+
}, options?.allowInstall);
|
|
3879
|
+
}
|
|
3880
|
+
};
|
|
3881
|
+
var OmniSharpServer = createInteractiveServer({
|
|
3882
|
+
id: "omnisharp",
|
|
3883
|
+
name: "OmniSharp",
|
|
3884
|
+
// Documented (#3750): OmniSharp needs a solution or project.
|
|
3885
|
+
requiresProjectRoot: true,
|
|
3886
|
+
fallbackFor: "csharp",
|
|
3887
|
+
extensions: KIND_EXTENSIONS["csharp"],
|
|
3888
|
+
root: createRootDetector([...DOTNET_CSHARP_ROOT_MARKERS]),
|
|
3889
|
+
language: "csharp",
|
|
3890
|
+
command: "OmniSharp",
|
|
3891
|
+
args: ["--languageserver"]
|
|
3892
|
+
});
|
|
3893
|
+
var FSharpServer = {
|
|
3894
|
+
id: "fsharp",
|
|
3895
|
+
idleEviction: "unmeasured",
|
|
3896
|
+
role: "language",
|
|
3897
|
+
// Documented (#3750): FSAutocomplete needs a project.
|
|
3898
|
+
requiresProjectRoot: true,
|
|
3899
|
+
name: "FSAutocomplete",
|
|
3900
|
+
extensions: KIND_EXTENSIONS["fsharp"],
|
|
3901
|
+
root: createRootDetector([...DOTNET_FSHARP_ROOT_MARKERS]),
|
|
3902
|
+
async spawn(root, options) {
|
|
3903
|
+
const candidates = dotnetToolCandidates("fsautocomplete");
|
|
3904
|
+
return resolveAndLaunch({
|
|
3905
|
+
candidates,
|
|
3906
|
+
args: [],
|
|
3907
|
+
cwd: root,
|
|
3908
|
+
runtimeInstall: {
|
|
3909
|
+
runtimeCommand: "dotnet",
|
|
3910
|
+
install: () => tryDotnetToolInstall("fsautocomplete"),
|
|
3911
|
+
retryCandidates: candidates
|
|
3912
|
+
}
|
|
3913
|
+
}, options?.allowInstall);
|
|
3914
|
+
}
|
|
3915
|
+
};
|
|
3916
|
+
var JavaServer = createInteractiveServer({
|
|
3917
|
+
id: "java",
|
|
3918
|
+
name: "JDT Language Server",
|
|
3919
|
+
extensions: KIND_EXTENSIONS["java"],
|
|
3920
|
+
root: RootWithFallback(JavaWorkspaceRoot()),
|
|
3921
|
+
language: "java",
|
|
3922
|
+
command: () => process.env.JDTLS_PATH || "jdtls",
|
|
3923
|
+
args: (root) => createLombokJdtlsArgs(root),
|
|
3924
|
+
runtime: "java"
|
|
3925
|
+
});
|
|
3926
|
+
var KotlinServer = {
|
|
3927
|
+
id: "kotlin",
|
|
3928
|
+
idleEviction: "unmeasured",
|
|
3929
|
+
role: "language",
|
|
3930
|
+
name: "Kotlin Language Server",
|
|
3931
|
+
extensions: KIND_EXTENSIONS["kotlin"],
|
|
3932
|
+
root: RootWithFallback(createRootDetector(["build.gradle.kts", "build.gradle", "pom.xml"])),
|
|
3933
|
+
async spawn(root, options) {
|
|
3934
|
+
return resolveAndLaunch({
|
|
3935
|
+
candidates: ["kotlin-lsp", "kotlin-language-server"],
|
|
3936
|
+
args: [],
|
|
3937
|
+
cwd: root,
|
|
3938
|
+
// #3400: a managed fwcd install when no PATH candidate launches. The
|
|
3939
|
+
// managed shim is consulted FIRST, but only exists once no PATH
|
|
3940
|
+
// candidate answered, so a PATH `kotlin-lsp` wins on a box that had
|
|
3941
|
+
// it before the managed install; one added afterwards does not.
|
|
3942
|
+
managedToolId: "kotlin-language-server"
|
|
3943
|
+
}, options?.allowInstall);
|
|
3944
|
+
}
|
|
3945
|
+
};
|
|
3946
|
+
var SwiftServer = createInteractiveServer({
|
|
3947
|
+
id: "swift",
|
|
3948
|
+
name: "SourceKit-LSP",
|
|
3949
|
+
extensions: KIND_EXTENSIONS["swift"],
|
|
3950
|
+
root: createRootDetector(["Package.swift"]),
|
|
3951
|
+
language: "swift",
|
|
3952
|
+
command: "sourcekit-lsp"
|
|
3953
|
+
});
|
|
3954
|
+
var DartServer = createInteractiveServer({
|
|
3955
|
+
id: "dart",
|
|
3956
|
+
name: "Dart Analysis Server",
|
|
3957
|
+
extensions: KIND_EXTENSIONS["dart"],
|
|
3958
|
+
root: RootWithFallback(createRootDetector(["pubspec.yaml"])),
|
|
3959
|
+
language: "dart",
|
|
3960
|
+
command: "dart",
|
|
3961
|
+
args: ["language-server", "--protocol=lsp"]
|
|
3962
|
+
});
|
|
3963
|
+
function createTreeBinaryServer(spec) {
|
|
3964
|
+
return {
|
|
3965
|
+
id: spec.id,
|
|
3966
|
+
name: spec.name,
|
|
3967
|
+
extensions: spec.extensions,
|
|
3968
|
+
idleEviction: spec.idleEviction ?? "unmeasured",
|
|
3969
|
+
// The spec declares no role, so the factory applies the stated default
|
|
3970
|
+
// (#1488) — see `createInteractiveServer`.
|
|
3971
|
+
role: DEFAULT_LSP_SERVER_ROLE,
|
|
3972
|
+
root: spec.root,
|
|
3973
|
+
spawn(root, options) {
|
|
3974
|
+
return resolveAndLaunchTreeBinary({
|
|
3975
|
+
candidates: [spec.binaryName],
|
|
3976
|
+
bundleToolId: spec.binaryName,
|
|
3977
|
+
binRelPath: spec.binRelPath,
|
|
3978
|
+
cwd: root,
|
|
3979
|
+
args: spec.args ?? []
|
|
3980
|
+
}, options?.allowInstall);
|
|
3981
|
+
}
|
|
3982
|
+
};
|
|
3983
|
+
}
|
|
3984
|
+
var LuaServer = createTreeBinaryServer({
|
|
3985
|
+
id: "lua",
|
|
3986
|
+
name: "Lua Language Server",
|
|
3987
|
+
extensions: KIND_EXTENSIONS["lua"],
|
|
3988
|
+
root: createRootDetector([".luarc.json", ".luacheckrc"]),
|
|
3989
|
+
binaryName: "lua-language-server",
|
|
3990
|
+
binRelPath: "bin/lua-language-server"
|
|
3991
|
+
});
|
|
3992
|
+
var CppServer = createTreeBinaryServer({
|
|
3993
|
+
id: "cpp",
|
|
3994
|
+
idleEviction: "transparent",
|
|
3995
|
+
name: "clangd",
|
|
3996
|
+
extensions: KIND_EXTENSIONS["cxx"],
|
|
3997
|
+
root: RootWithFallback(createRootDetector([
|
|
3998
|
+
"compile_commands.json",
|
|
3999
|
+
".clangd",
|
|
4000
|
+
"CMakeLists.txt",
|
|
4001
|
+
"Makefile"
|
|
4002
|
+
])),
|
|
4003
|
+
binaryName: "clangd",
|
|
4004
|
+
binRelPath: "bin/clangd",
|
|
4005
|
+
args: ["--background-index"]
|
|
4006
|
+
});
|
|
4007
|
+
var ZigServer = {
|
|
4008
|
+
id: "zig",
|
|
4009
|
+
idleEviction: "unmeasured",
|
|
4010
|
+
role: "language",
|
|
4011
|
+
name: "ZLS",
|
|
4012
|
+
extensions: KIND_EXTENSIONS["zig"],
|
|
4013
|
+
root: RootWithFallback(createRootDetector(["build.zig"])),
|
|
4014
|
+
spawn(root, options) {
|
|
4015
|
+
return resolveAndLaunch({
|
|
4016
|
+
candidates: ["zls"],
|
|
4017
|
+
args: [],
|
|
4018
|
+
cwd: root,
|
|
4019
|
+
managedToolId: "zls"
|
|
4020
|
+
}, options?.allowInstall);
|
|
4021
|
+
}
|
|
4022
|
+
};
|
|
4023
|
+
var HaskellServer = createInteractiveServer({
|
|
4024
|
+
id: "haskell",
|
|
4025
|
+
name: "Haskell Language Server",
|
|
4026
|
+
extensions: KIND_EXTENSIONS["haskell"],
|
|
4027
|
+
root: createRootDetector(["stack.yaml", "cabal.project", "*.cabal"]),
|
|
4028
|
+
language: "haskell",
|
|
4029
|
+
command: "haskell-language-server-wrapper",
|
|
4030
|
+
args: ["--lsp"]
|
|
4031
|
+
});
|
|
4032
|
+
var ElixirServer = createInteractiveServer({
|
|
4033
|
+
id: "elixir",
|
|
4034
|
+
name: "ElixirLS",
|
|
4035
|
+
extensions: KIND_EXTENSIONS["elixir"],
|
|
4036
|
+
root: RootWithFallback(createRootDetector(["mix.exs"])),
|
|
4037
|
+
language: "elixir",
|
|
4038
|
+
command: "elixir-ls"
|
|
4039
|
+
});
|
|
4040
|
+
var ElixirExpertServer = {
|
|
4041
|
+
id: "expert",
|
|
4042
|
+
idleEviction: "unmeasured",
|
|
4043
|
+
role: "language",
|
|
4044
|
+
name: "Expert",
|
|
4045
|
+
fallbackFor: "elixir",
|
|
4046
|
+
extensions: KIND_EXTENSIONS["elixir"],
|
|
4047
|
+
root: RootWithFallback(createRootDetector(["mix.exs"])),
|
|
4048
|
+
availabilityKey: "expert",
|
|
4049
|
+
async spawn(root, options) {
|
|
4050
|
+
return resolveAndLaunch({
|
|
4051
|
+
candidates: ["expert"],
|
|
4052
|
+
args: ["--stdio"],
|
|
4053
|
+
cwd: root,
|
|
4054
|
+
managedToolId: "expert"
|
|
4055
|
+
}, options?.allowInstall);
|
|
4056
|
+
},
|
|
4057
|
+
autoInstall: async () => Boolean(await ensureTool("expert"))
|
|
4058
|
+
};
|
|
4059
|
+
var GleamServer = {
|
|
4060
|
+
id: "gleam",
|
|
4061
|
+
idleEviction: "unmeasured",
|
|
4062
|
+
role: "language",
|
|
4063
|
+
name: "Gleam LSP",
|
|
4064
|
+
extensions: KIND_EXTENSIONS["gleam"],
|
|
4065
|
+
root: RootWithFallback(createRootDetector(["gleam.toml"])),
|
|
4066
|
+
async spawn(root, options) {
|
|
4067
|
+
return resolveAndLaunch({
|
|
4068
|
+
candidates: ["gleam"],
|
|
4069
|
+
args: ["lsp"],
|
|
4070
|
+
cwd: root,
|
|
4071
|
+
managedToolId: "gleam"
|
|
4072
|
+
}, options?.allowInstall);
|
|
4073
|
+
}
|
|
4074
|
+
};
|
|
4075
|
+
var TinymistServer = {
|
|
4076
|
+
id: "tinymist",
|
|
4077
|
+
idleEviction: "unmeasured",
|
|
4078
|
+
role: "language",
|
|
4079
|
+
name: "Tinymist",
|
|
4080
|
+
extensions: extensionsForLanguage("typst"),
|
|
4081
|
+
root: RootWithFallback(createRootDetector(["typst.toml", ".git"])),
|
|
4082
|
+
availabilityKey: "tinymist",
|
|
4083
|
+
async spawn(root, options) {
|
|
4084
|
+
return resolveAndLaunch({
|
|
4085
|
+
candidates: ["tinymist"],
|
|
4086
|
+
args: ["lsp"],
|
|
4087
|
+
cwd: root,
|
|
4088
|
+
managedToolId: "tinymist"
|
|
4089
|
+
}, options?.allowInstall);
|
|
4090
|
+
}
|
|
4091
|
+
};
|
|
4092
|
+
var MarksmanServer = {
|
|
4093
|
+
id: "marksman",
|
|
4094
|
+
idleEviction: "transparent",
|
|
4095
|
+
role: "language",
|
|
4096
|
+
name: "Marksman",
|
|
4097
|
+
extensions: KIND_EXTENSIONS["markdown"],
|
|
4098
|
+
// Index at the workspace root so cross-file checks (broken intra-repo links,
|
|
4099
|
+
// missing/renamed anchors, heading refs) see the whole tree; fall back to the
|
|
4100
|
+
// file's directory when there's no project marker.
|
|
4101
|
+
root: RootWithFallback(createRootDetector([".marksman.toml", ".git"])),
|
|
4102
|
+
spawn(root, options) {
|
|
4103
|
+
return resolveAndLaunch({
|
|
4104
|
+
candidates: ["marksman"],
|
|
4105
|
+
args: ["server"],
|
|
4106
|
+
cwd: root,
|
|
4107
|
+
managedToolId: "marksman"
|
|
4108
|
+
}, options?.allowInstall);
|
|
4109
|
+
}
|
|
4110
|
+
};
|
|
4111
|
+
var OCamlServer = createInteractiveServer({
|
|
4112
|
+
id: "ocaml",
|
|
4113
|
+
name: "ocamllsp",
|
|
4114
|
+
extensions: KIND_EXTENSIONS["ocaml"],
|
|
4115
|
+
root: createRootDetector(["dune-project", "opam"]),
|
|
4116
|
+
language: "ocaml",
|
|
4117
|
+
command: "ocamllsp"
|
|
4118
|
+
});
|
|
4119
|
+
var ClojureServer = {
|
|
4120
|
+
id: "clojure",
|
|
4121
|
+
idleEviction: "transparent",
|
|
4122
|
+
role: "language",
|
|
4123
|
+
name: "Clojure LSP",
|
|
4124
|
+
extensions: KIND_EXTENSIONS["clojure"],
|
|
4125
|
+
root: createRootDetector(["deps.edn", "project.clj"]),
|
|
4126
|
+
async spawn(root, options) {
|
|
4127
|
+
return resolveAndLaunch({
|
|
4128
|
+
candidates: ["clojure-lsp"],
|
|
4129
|
+
args: [],
|
|
4130
|
+
cwd: root,
|
|
4131
|
+
managedToolId: "clojure-lsp"
|
|
4132
|
+
}, options?.allowInstall);
|
|
4133
|
+
}
|
|
4134
|
+
};
|
|
4135
|
+
var CueServer = {
|
|
4136
|
+
id: "cue",
|
|
4137
|
+
idleEviction: "unmeasured",
|
|
4138
|
+
role: "language",
|
|
4139
|
+
name: "CUE Language Server",
|
|
4140
|
+
extensions: KIND_EXTENSIONS["cue"],
|
|
4141
|
+
root: RootWithFallback(createRootDetector(["cue.mod", ".git"])),
|
|
4142
|
+
async spawn(root, options) {
|
|
4143
|
+
return resolveAndLaunch({
|
|
4144
|
+
candidates: ["cue"],
|
|
4145
|
+
args: ["lsp", "serve"],
|
|
4146
|
+
cwd: root,
|
|
4147
|
+
managedToolId: "cue"
|
|
4148
|
+
}, options?.allowInstall);
|
|
4149
|
+
}
|
|
4150
|
+
};
|
|
4151
|
+
var TerraformServer = {
|
|
4152
|
+
id: "terraform",
|
|
4153
|
+
idleEviction: "unmeasured",
|
|
4154
|
+
role: "language",
|
|
4155
|
+
name: "Terraform LSP",
|
|
4156
|
+
extensions: KIND_EXTENSIONS["terraform"],
|
|
4157
|
+
root: RootWithFallback(createRootDetector([".terraform.lock.hcl", ".terraform"])),
|
|
4158
|
+
spawn(root, options) {
|
|
4159
|
+
return resolveAndLaunch({
|
|
4160
|
+
candidates: ["terraform-ls"],
|
|
4161
|
+
args: ["serve"],
|
|
4162
|
+
cwd: root,
|
|
4163
|
+
managedToolId: "terraform-ls"
|
|
4164
|
+
}, options?.allowInstall);
|
|
4165
|
+
}
|
|
4166
|
+
};
|
|
4167
|
+
var NixServer = createInteractiveServer({
|
|
4168
|
+
id: "nix",
|
|
4169
|
+
name: "nixd",
|
|
4170
|
+
extensions: KIND_EXTENSIONS["nix"],
|
|
4171
|
+
root: createRootDetector(["flake.nix"]),
|
|
4172
|
+
language: "nix",
|
|
4173
|
+
command: "nixd"
|
|
4174
|
+
});
|
|
4175
|
+
var BashServer = {
|
|
4176
|
+
id: "bash",
|
|
4177
|
+
idleEviction: "transparent",
|
|
4178
|
+
role: "language",
|
|
4179
|
+
name: "Bash Language Server",
|
|
4180
|
+
// #3968: narrowed from [".bash", ".sh", ".zsh"] — bash-language-server does
|
|
4181
|
+
// not support zsh (its own analyzer refuses the dialect), and its ≥5.7.0
|
|
4182
|
+
// lint flow even feeds shebang'd zsh to its embedded shellcheck, importing
|
|
4183
|
+
// SC1071-class noise through the LSP lane. `shuck` owns `.zsh` when
|
|
4184
|
+
// installed; when it is not, the shellcheck runner's dialect gate keeps
|
|
4185
|
+
// zsh quiet instead of falling back to a zsh-illiterate analyzer.
|
|
4186
|
+
extensions: [".bash", ".sh"],
|
|
4187
|
+
root: FileDirRoot,
|
|
4188
|
+
// #2194 bounded the installer's own verification at 20s; the dispatch
|
|
4189
|
+
// touch's client-wait floor stayed at the shared 5s default, so a cold
|
|
4190
|
+
// spawn could still race that budget and read as unavailable even after
|
|
4191
|
+
// installer verification cleared it. Match the installer bound (#2169).
|
|
4192
|
+
// `initializeTimeoutMs` matches it too: the measured cold start
|
|
4193
|
+
// (9,667ms, #2194) has headroom under the unraised 15s default, but
|
|
4194
|
+
// leaving the two fields mismatched is the same latent shape that made
|
|
4195
|
+
// the Prisma/Vue raise a no-op (fix-round F1, #2233) — a slower host
|
|
4196
|
+
// than the one measured would still hit the 15s inner kill despite the
|
|
4197
|
+
// caller being willing to wait 20s. Equalizing costs nothing on the
|
|
4198
|
+
// success path and removes the mismatch outright.
|
|
4199
|
+
clientWaitTimeoutMs: 2e4,
|
|
4200
|
+
initializeTimeoutMs: 2e4,
|
|
4201
|
+
spawn(root, options) {
|
|
4202
|
+
return resolveAndLaunch({
|
|
4203
|
+
candidates: nodeBinCandidates(root, "bash-language-server"),
|
|
4204
|
+
args: ["start"],
|
|
4205
|
+
cwd: root,
|
|
4206
|
+
managedToolId: "bash-language-server"
|
|
4207
|
+
}, options?.allowInstall);
|
|
4208
|
+
}
|
|
4209
|
+
};
|
|
4210
|
+
var ShuckServer = createInteractiveServer({
|
|
4211
|
+
id: "shuck",
|
|
4212
|
+
name: "Shuck",
|
|
4213
|
+
extensions: [".zsh"],
|
|
4214
|
+
root: FileDirRoot,
|
|
4215
|
+
language: "shell",
|
|
4216
|
+
command: "shuck",
|
|
4217
|
+
args: ["server"]
|
|
4218
|
+
});
|
|
4219
|
+
var FishServer = {
|
|
4220
|
+
id: "fish",
|
|
4221
|
+
idleEviction: "transparent",
|
|
4222
|
+
role: "language",
|
|
4223
|
+
name: "Fish Language Server",
|
|
4224
|
+
extensions: KIND_EXTENSIONS["fish"],
|
|
4225
|
+
root: RootWithFallback(createRootDetector([".git"])),
|
|
4226
|
+
spawn(root, options) {
|
|
4227
|
+
return resolveAndLaunch({
|
|
4228
|
+
candidates: nodeBinCandidates(root, "fish-lsp"),
|
|
4229
|
+
args: ["start", "--stdio"],
|
|
4230
|
+
cwd: root,
|
|
4231
|
+
managedToolId: "fish-lsp"
|
|
4232
|
+
}, options?.allowInstall);
|
|
4233
|
+
}
|
|
4234
|
+
};
|
|
4235
|
+
var CMakeServer = {
|
|
4236
|
+
id: "cmake",
|
|
4237
|
+
idleEviction: "unmeasured",
|
|
4238
|
+
role: "language",
|
|
4239
|
+
name: "CMake Language Server",
|
|
4240
|
+
// CMake's canonical project file has no .cmake suffix. The configured-server
|
|
4241
|
+
// matcher supports exact basenames as well as extensions.
|
|
4242
|
+
extensions: [...KIND_EXTENSIONS["cmake"], "CMakeLists.txt"],
|
|
4243
|
+
root: RootWithFallback(createRootDetector(["CMakeLists.txt", ".git"])),
|
|
4244
|
+
spawn(root, options) {
|
|
4245
|
+
return resolveAndLaunch({
|
|
4246
|
+
candidates: ["cmake-language-server"],
|
|
4247
|
+
args: [],
|
|
4248
|
+
cwd: root,
|
|
4249
|
+
managedToolId: "cmake-language-server"
|
|
4250
|
+
}, options?.allowInstall);
|
|
4251
|
+
}
|
|
4252
|
+
};
|
|
4253
|
+
var DockerServer = {
|
|
4254
|
+
id: "docker",
|
|
4255
|
+
idleEviction: "transparent",
|
|
4256
|
+
role: "language",
|
|
4257
|
+
name: "Dockerfile Language Server",
|
|
4258
|
+
extensions: [".dockerfile", "Dockerfile"],
|
|
4259
|
+
root: RootWithFallback(PriorityRoot([
|
|
4260
|
+
[
|
|
4261
|
+
"docker-compose.yml",
|
|
4262
|
+
"docker-compose.yaml",
|
|
4263
|
+
"compose.yml",
|
|
4264
|
+
"compose.yaml"
|
|
4265
|
+
],
|
|
4266
|
+
[".git"]
|
|
4267
|
+
])),
|
|
4268
|
+
spawn(root, options) {
|
|
4269
|
+
return resolveAndLaunch({
|
|
4270
|
+
candidates: nodeBinCandidates(root, "docker-langserver"),
|
|
4271
|
+
args: ["--stdio"],
|
|
4272
|
+
cwd: root,
|
|
4273
|
+
managedToolId: "dockerfile-language-server-nodejs"
|
|
4274
|
+
}, options?.allowInstall);
|
|
4275
|
+
}
|
|
4276
|
+
};
|
|
4277
|
+
var DockerOfficialServer = {
|
|
4278
|
+
id: "docker-official",
|
|
4279
|
+
idleEviction: "unmeasured",
|
|
4280
|
+
role: "language",
|
|
4281
|
+
name: "Docker Language Server (official)",
|
|
4282
|
+
fallbackFor: "docker",
|
|
4283
|
+
extensions: [".dockerfile", "Dockerfile"],
|
|
4284
|
+
root: RootWithFallback(PriorityRoot([
|
|
4285
|
+
[
|
|
4286
|
+
"docker-compose.yml",
|
|
4287
|
+
"docker-compose.yaml",
|
|
4288
|
+
"compose.yml",
|
|
4289
|
+
"compose.yaml"
|
|
4290
|
+
],
|
|
4291
|
+
[".git"]
|
|
4292
|
+
])),
|
|
4293
|
+
spawn(root, options) {
|
|
4294
|
+
return resolveAndLaunch({
|
|
4295
|
+
candidates: nodeBinCandidates(root, "docker-language-server"),
|
|
4296
|
+
args: ["start", "--stdio"],
|
|
4297
|
+
cwd: root
|
|
4298
|
+
}, options?.allowInstall);
|
|
4299
|
+
}
|
|
4300
|
+
};
|
|
4301
|
+
var YamlServer = {
|
|
4302
|
+
id: "yaml",
|
|
4303
|
+
idleEviction: "transparent",
|
|
4304
|
+
role: "language",
|
|
4305
|
+
name: "YAML Language Server",
|
|
4306
|
+
extensions: KIND_EXTENSIONS["yaml"],
|
|
4307
|
+
root: RootWithFallback(PriorityRoot([
|
|
4308
|
+
[".yamllint", "yamllint.yml", "yamllint.yaml", "pyproject.toml"],
|
|
4309
|
+
[".git"]
|
|
4310
|
+
])),
|
|
4311
|
+
spawn(root, options) {
|
|
4312
|
+
return resolveAndLaunch({
|
|
4313
|
+
candidates: nodeBinCandidates(root, "yaml-language-server"),
|
|
4314
|
+
args: ["--stdio"],
|
|
4315
|
+
cwd: root,
|
|
4316
|
+
managedToolId: "yaml-language-server"
|
|
4317
|
+
}, options?.allowInstall);
|
|
4318
|
+
}
|
|
4319
|
+
};
|
|
4320
|
+
var JsonServer = {
|
|
4321
|
+
id: "json",
|
|
4322
|
+
idleEviction: "transparent",
|
|
4323
|
+
role: "language",
|
|
4324
|
+
name: "VSCode JSON Language Server",
|
|
4325
|
+
extensions: KIND_EXTENSIONS["json"],
|
|
4326
|
+
root: RootWithFallback(WorkspacePriorityRoot([
|
|
4327
|
+
["package.json", "tsconfig.json", "jsconfig.json"],
|
|
4328
|
+
[".git"]
|
|
4329
|
+
])),
|
|
4330
|
+
// See BashServer above: the installer's 20s verification bound (#2194)
|
|
4331
|
+
// does not, on its own, raise the dispatch touch's cold-spawn wait floor.
|
|
4332
|
+
// Mirror it here so a cold spawn cannot lose that race either (#2169).
|
|
4333
|
+
// `initializeTimeoutMs` matches it for the same reason as BashServer
|
|
4334
|
+
// above (fix-round F1, #2233).
|
|
4335
|
+
clientWaitTimeoutMs: 2e4,
|
|
4336
|
+
initializeTimeoutMs: 2e4,
|
|
4337
|
+
spawn(root, options) {
|
|
4338
|
+
return resolveAndLaunch({
|
|
4339
|
+
candidates: ["vscode-json-language-server"],
|
|
4340
|
+
args: ["--stdio"],
|
|
4341
|
+
cwd: root,
|
|
4342
|
+
managedToolId: "vscode-json-language-server"
|
|
4343
|
+
}, options?.allowInstall);
|
|
4344
|
+
}
|
|
4345
|
+
};
|
|
4346
|
+
var HtmlServer = {
|
|
4347
|
+
id: "html",
|
|
4348
|
+
idleEviction: "transparent",
|
|
4349
|
+
role: "language",
|
|
4350
|
+
name: "VSCode HTML Language Server",
|
|
4351
|
+
extensions: KIND_EXTENSIONS["html"],
|
|
4352
|
+
root: RootWithFallback(IgnoreHomeRoot(PriorityRoot([["package.json", "index.html", "vite.config.ts"]]))),
|
|
4353
|
+
spawn(root, options) {
|
|
4354
|
+
return resolveAndLaunch({
|
|
4355
|
+
candidates: nodeBinCandidates(root, "vscode-html-language-server"),
|
|
4356
|
+
args: ["--stdio"],
|
|
4357
|
+
cwd: root,
|
|
4358
|
+
managedToolId: "vscode-html-languageserver-bin"
|
|
4359
|
+
}, options?.allowInstall);
|
|
4360
|
+
}
|
|
4361
|
+
};
|
|
4362
|
+
var TomlServer = {
|
|
4363
|
+
id: "toml",
|
|
4364
|
+
idleEviction: "unmeasured",
|
|
4365
|
+
role: "language",
|
|
4366
|
+
name: "Taplo",
|
|
4367
|
+
extensions: KIND_EXTENSIONS["toml"],
|
|
4368
|
+
root: RootWithFallback(PriorityRoot([["pyproject.toml", "Cargo.toml", "taplo.toml"], [".git"]])),
|
|
4369
|
+
spawn(root, options) {
|
|
4370
|
+
return resolveAndLaunch({
|
|
4371
|
+
candidates: ["taplo"],
|
|
4372
|
+
args: ["lsp", "stdio"],
|
|
4373
|
+
cwd: root,
|
|
4374
|
+
managedToolId: "taplo"
|
|
4375
|
+
}, options?.allowInstall);
|
|
4376
|
+
}
|
|
4377
|
+
};
|
|
4378
|
+
var PrismaServer = {
|
|
4379
|
+
id: "prisma",
|
|
4380
|
+
idleEviction: "transparent",
|
|
4381
|
+
role: "language",
|
|
4382
|
+
name: "Prisma Language Server",
|
|
4383
|
+
extensions: KIND_EXTENSIONS["prisma"],
|
|
4384
|
+
root: RootWithFallback(createRootDetector(["prisma/schema.prisma", "schema.prisma"])),
|
|
4385
|
+
// Matches the installer's 40s verification bound above (#2169): the
|
|
4386
|
+
// dispatch touch's cold-spawn wait floor defaults to 5s and would
|
|
4387
|
+
// otherwise time the client out well before the binary answers.
|
|
4388
|
+
// `initializeTimeoutMs` MUST be set alongside it (RubyServer's own
|
|
4389
|
+
// precedent below): unset, it falls back to the 15s
|
|
4390
|
+
// `INITIALIZE_TIMEOUT_MS` default in `clients/lsp/client.ts`, which
|
|
4391
|
+
// hard-kills the child mid-handshake — a real cold Prisma run measured
|
|
4392
|
+
// up to 27.3s, so the spawn would die there before this wait ever gets
|
|
4393
|
+
// a chance to matter (fix-round F1, #2233).
|
|
4394
|
+
clientWaitTimeoutMs: 4e4,
|
|
4395
|
+
initializeTimeoutMs: 4e4,
|
|
4396
|
+
spawn(root, options) {
|
|
4397
|
+
return resolveAndLaunch({
|
|
4398
|
+
candidates: nodeBinCandidates(root, "prisma-language-server"),
|
|
4399
|
+
args: ["--stdio"],
|
|
4400
|
+
cwd: root,
|
|
4401
|
+
managedToolId: "@prisma/language-server"
|
|
4402
|
+
}, options?.allowInstall);
|
|
4403
|
+
}
|
|
4404
|
+
};
|
|
4405
|
+
var VueServer = {
|
|
4406
|
+
id: "vue",
|
|
4407
|
+
idleEviction: "unmeasured",
|
|
4408
|
+
role: "language",
|
|
4409
|
+
name: "Vue Language Server",
|
|
4410
|
+
extensions: [".vue"],
|
|
4411
|
+
root: RootWithFallback(IgnoreHomeRoot(createRootDetector([
|
|
4412
|
+
"package.json",
|
|
4413
|
+
"package-lock.json",
|
|
4414
|
+
"bun.lockb",
|
|
4415
|
+
"bun.lock",
|
|
4416
|
+
"pnpm-lock.yaml",
|
|
4417
|
+
"yarn.lock"
|
|
4418
|
+
]))),
|
|
4419
|
+
// Vue's launcher loads the full language-service bundle before answering,
|
|
4420
|
+
// matching the installer's 30s verification bound (#2176). The dispatch
|
|
4421
|
+
// touch's cold-spawn wait floor defaults to 5s and needs the same raise so
|
|
4422
|
+
// a cold spawn cannot time out there instead. `initializeTimeoutMs` MUST
|
|
4423
|
+
// match: unset, it falls back to the 15s default in `clients/lsp/client.ts`
|
|
4424
|
+
// and hard-kills a cold spawn (measured up to 22.6s in #2188, 16.2s here)
|
|
4425
|
+
// mid-handshake before this wait can matter (fix-round F1, #2233).
|
|
4426
|
+
clientWaitTimeoutMs: 3e4,
|
|
4427
|
+
initializeTimeoutMs: 3e4,
|
|
4428
|
+
async spawn(root, options) {
|
|
4429
|
+
const tsserverPath = await findTsserverPath(root, options?.allowInstall);
|
|
4430
|
+
const hasPackageJson = existsSync3(path7.join(root, "package.json"));
|
|
4431
|
+
const hasNodeModules = existsSync3(path7.join(root, "node_modules"));
|
|
4432
|
+
if (hasPackageJson && !hasNodeModules) {
|
|
4433
|
+
logSessionStart(`lsp vue: node_modules missing in ${root} \u2014 Vue navigation may be limited. Run: npm install (or pnpm/yarn install) in this project.`);
|
|
4434
|
+
}
|
|
4435
|
+
const proc = await resolveAndLaunch({
|
|
4436
|
+
candidates: nodeBinCandidates(root, "vue-language-server"),
|
|
4437
|
+
args: ["--stdio"],
|
|
4438
|
+
cwd: root,
|
|
4439
|
+
managedToolId: "@vue/language-server"
|
|
4440
|
+
}, options?.allowInstall);
|
|
4441
|
+
if (!proc)
|
|
4442
|
+
return void 0;
|
|
4443
|
+
return {
|
|
4444
|
+
process: proc.process,
|
|
4445
|
+
source: proc.source,
|
|
4446
|
+
initialization: tsserverPath ? { typescript: { tsdk: path7.dirname(tsserverPath) } } : void 0
|
|
4447
|
+
};
|
|
4448
|
+
}
|
|
4449
|
+
};
|
|
4450
|
+
var SvelteServer = {
|
|
4451
|
+
id: "svelte",
|
|
4452
|
+
idleEviction: "unmeasured",
|
|
4453
|
+
role: "language",
|
|
4454
|
+
name: "Svelte Language Server",
|
|
4455
|
+
extensions: [".svelte"],
|
|
4456
|
+
root: RootWithFallback(IgnoreHomeRoot(createRootDetector([
|
|
4457
|
+
"package.json",
|
|
4458
|
+
"package-lock.json",
|
|
4459
|
+
"bun.lockb",
|
|
4460
|
+
"bun.lock",
|
|
4461
|
+
"pnpm-lock.yaml",
|
|
4462
|
+
"yarn.lock"
|
|
4463
|
+
]))),
|
|
4464
|
+
// Matches the installer's 20s verification bound above (#2169): the
|
|
4465
|
+
// dispatch touch's cold-spawn wait floor defaults to 5s and would
|
|
4466
|
+
// otherwise time the client out well before the binary answers.
|
|
4467
|
+
// `initializeTimeoutMs` matches it for the same reason as BashServer
|
|
4468
|
+
// above (fix-round F1, #2233).
|
|
4469
|
+
clientWaitTimeoutMs: 2e4,
|
|
4470
|
+
initializeTimeoutMs: 2e4,
|
|
4471
|
+
async spawn(root, options) {
|
|
4472
|
+
const tsserverPath = await findTsserverPath(root, options?.allowInstall);
|
|
4473
|
+
const proc = await resolveAndLaunch({
|
|
4474
|
+
candidates: [
|
|
4475
|
+
...nodeBinCandidates(root, "svelteserver"),
|
|
4476
|
+
...nodeBinCandidates(root, "svelte-language-server")
|
|
4477
|
+
],
|
|
4478
|
+
args: ["--stdio"],
|
|
4479
|
+
cwd: root,
|
|
4480
|
+
managedToolId: "svelte-language-server"
|
|
4481
|
+
}, options?.allowInstall);
|
|
4482
|
+
if (!proc)
|
|
4483
|
+
return void 0;
|
|
4484
|
+
return {
|
|
4485
|
+
process: proc.process,
|
|
4486
|
+
source: proc.source,
|
|
4487
|
+
initialization: tsserverPath ? { typescript: { tsdk: path7.dirname(tsserverPath) } } : void 0
|
|
4488
|
+
};
|
|
4489
|
+
}
|
|
4490
|
+
};
|
|
4491
|
+
var CssServer = {
|
|
4492
|
+
id: "css",
|
|
4493
|
+
idleEviction: "transparent",
|
|
4494
|
+
role: "language",
|
|
4495
|
+
name: "CSS Language Server",
|
|
4496
|
+
extensions: KIND_EXTENSIONS["css"],
|
|
4497
|
+
root: RootWithFallback(IgnoreHomeRoot(PriorityRoot([
|
|
4498
|
+
[
|
|
4499
|
+
"package.json",
|
|
4500
|
+
"postcss.config.js",
|
|
4501
|
+
"tailwind.config.js",
|
|
4502
|
+
"vite.config.ts"
|
|
4503
|
+
]
|
|
4504
|
+
]))),
|
|
4505
|
+
spawn(root, options) {
|
|
4506
|
+
return resolveAndLaunch({
|
|
4507
|
+
candidates: nodeBinCandidates(root, "vscode-css-language-server"),
|
|
4508
|
+
args: ["--stdio"],
|
|
4509
|
+
cwd: root,
|
|
4510
|
+
managedToolId: "vscode-css-languageserver"
|
|
4511
|
+
}, options?.allowInstall);
|
|
4512
|
+
}
|
|
4513
|
+
};
|
|
4514
|
+
var OPENGREP_KINDS = [
|
|
4515
|
+
"csharp",
|
|
4516
|
+
"css",
|
|
4517
|
+
"cxx",
|
|
4518
|
+
"dart",
|
|
4519
|
+
"docker",
|
|
4520
|
+
"go",
|
|
4521
|
+
"html",
|
|
4522
|
+
"java",
|
|
4523
|
+
"json",
|
|
4524
|
+
"jsts",
|
|
4525
|
+
"kotlin",
|
|
4526
|
+
"lua",
|
|
4527
|
+
"php",
|
|
4528
|
+
"python",
|
|
4529
|
+
"ruby",
|
|
4530
|
+
"rust",
|
|
4531
|
+
"shell",
|
|
4532
|
+
"swift",
|
|
4533
|
+
"terraform",
|
|
4534
|
+
"yaml"
|
|
4535
|
+
];
|
|
4536
|
+
var OPENGREP_EXTENSIONS = Array.from(new Set(OPENGREP_KINDS.flatMap((k) => KIND_EXTENSIONS[k] ?? [])));
|
|
4537
|
+
function opengrepInitialization(root) {
|
|
4538
|
+
const resolved = resolveOpengrepConfig(root, { enabled: true });
|
|
4539
|
+
return {
|
|
4540
|
+
scan: {
|
|
4541
|
+
configuration: [resolved.configArg ?? "auto"],
|
|
4542
|
+
onlyGitDirty: false,
|
|
4543
|
+
jobs: 16
|
|
4544
|
+
},
|
|
4545
|
+
metrics: { enabled: false },
|
|
4546
|
+
doHover: false
|
|
4547
|
+
};
|
|
4548
|
+
}
|
|
4549
|
+
var OpengrepServer = {
|
|
4550
|
+
id: "opengrep",
|
|
4551
|
+
idleEviction: "transparent",
|
|
4552
|
+
role: "auxiliary",
|
|
4553
|
+
name: "Opengrep Security Scanner",
|
|
4554
|
+
extensions: OPENGREP_EXTENSIONS,
|
|
4555
|
+
// Stable per-repo root so ONE warm server serves the whole project (a
|
|
4556
|
+
// per-directory root would spawn a fresh server — and re-pay rule load —
|
|
4557
|
+
// for every folder).
|
|
4558
|
+
root: RootWithFallback(NearestRoot([".git"]), async () => process.cwd()),
|
|
4559
|
+
availabilityKey: "opengrep",
|
|
4560
|
+
// Rule compilation can take a few seconds on the first scan of a session.
|
|
4561
|
+
initializeTimeoutMs: 15e3,
|
|
4562
|
+
async spawn(root, options) {
|
|
4563
|
+
const launched = await resolveAndLaunch({
|
|
4564
|
+
candidates: ["opengrep"],
|
|
4565
|
+
args: ["lsp", "--experimental"],
|
|
4566
|
+
cwd: root,
|
|
4567
|
+
managedToolId: "opengrep"
|
|
4568
|
+
}, options?.allowInstall);
|
|
4569
|
+
if (!launched)
|
|
4570
|
+
return void 0;
|
|
4571
|
+
return { ...launched, initialization: opengrepInitialization(root) };
|
|
4572
|
+
},
|
|
4573
|
+
autoInstall: async () => Boolean(await ensureTool("opengrep"))
|
|
4574
|
+
};
|
|
4575
|
+
var AST_GREP_KINDS = [
|
|
4576
|
+
"csharp",
|
|
4577
|
+
"cxx",
|
|
4578
|
+
"css",
|
|
4579
|
+
"elixir",
|
|
4580
|
+
"go",
|
|
4581
|
+
"haskell",
|
|
4582
|
+
"html",
|
|
4583
|
+
"java",
|
|
4584
|
+
"json",
|
|
4585
|
+
"jsts",
|
|
4586
|
+
"kotlin",
|
|
4587
|
+
"lua",
|
|
4588
|
+
"nix",
|
|
4589
|
+
"php",
|
|
4590
|
+
"python",
|
|
4591
|
+
"ruby",
|
|
4592
|
+
"rust",
|
|
4593
|
+
"scala",
|
|
4594
|
+
"shell",
|
|
4595
|
+
"swift",
|
|
4596
|
+
"yaml"
|
|
4597
|
+
];
|
|
4598
|
+
var AST_GREP_EXTENSIONS = Array.from(new Set(AST_GREP_KINDS.flatMap((k) => KIND_EXTENSIONS[k] ?? [])));
|
|
4599
|
+
var AstGrepServer = {
|
|
4600
|
+
id: "ast-grep",
|
|
4601
|
+
idleEviction: "unmeasured",
|
|
4602
|
+
role: "auxiliary",
|
|
4603
|
+
name: "ast-grep structural linter",
|
|
4604
|
+
extensions: AST_GREP_EXTENSIONS,
|
|
4605
|
+
// Attaches everywhere (#239 Phase 2): prefer a project `sgconfig.y[a]ml` root,
|
|
4606
|
+
// else the repo root (.git) or cwd — like Opengrep. When there's no project
|
|
4607
|
+
// sgconfig the spawn launches with `--config <shipped baseline>` so the team's
|
|
4608
|
+
// rules still run; the napi runner steps aside when this server is available
|
|
4609
|
+
// (it falls back to napi when the ast-grep binary is absent — Gate B).
|
|
4610
|
+
root: RootWithFallback(createRootDetector(["sgconfig.yml", "sgconfig.yaml"]), RootWithFallback(NearestRoot([".git"]), async () => process.cwd())),
|
|
4611
|
+
availabilityKey: "ast-grep",
|
|
4612
|
+
// #1714: the one auxiliary with a measured wedge ceiling. A `lens_diagnostics
|
|
4613
|
+
// mode=full` sweep of 225 files drove this server into an unrecoverable stall
|
|
4614
|
+
// twice in two exposures (writes outstanding 5.9 s and 9.4 s, then a forced
|
|
4615
|
+
// shutdown that timed out both the request and the exit notify). It re-parses
|
|
4616
|
+
// the whole file on every didOpen, so it absorbs a sweep more slowly than the
|
|
4617
|
+
// other scanners — hold it to half the shared default.
|
|
4618
|
+
notifyInflightLimit: 4,
|
|
4619
|
+
// #1722, measured against the real binary over 30 repository files rather
|
|
4620
|
+
// than assumed: ast-grep-lsp is tower-lsp-server and drains its message
|
|
4621
|
+
// stream in order on one task, so the notify barrier's round-trip proves
|
|
4622
|
+
// the backlog was scanned. Declared here because the barrier's soundness
|
|
4623
|
+
// rests on it (#1756 stage 1); the evidence table is on
|
|
4624
|
+
// `LspReplyOrdering`.
|
|
4625
|
+
replyOrdering: "single-task-ordered",
|
|
4626
|
+
// First scan of a session compiles the rules.
|
|
4627
|
+
initializeTimeoutMs: 15e3,
|
|
4628
|
+
async spawn(root, options) {
|
|
4629
|
+
const projectSgconfig = findLocalSgconfig(root);
|
|
4630
|
+
let args = ["lsp"];
|
|
4631
|
+
if (!projectSgconfig) {
|
|
4632
|
+
const baseline = resolveBaselineSgconfig(root);
|
|
4633
|
+
if (baseline)
|
|
4634
|
+
args = ["lsp", "--config", baseline];
|
|
4635
|
+
}
|
|
4636
|
+
const nativeExe = resolveAstGrepNativeExe();
|
|
4637
|
+
const candidates = nativeExe ? [nativeExe, "ast-grep"] : ["ast-grep"];
|
|
4638
|
+
return resolveAndLaunch({
|
|
4639
|
+
candidates,
|
|
4640
|
+
args,
|
|
4641
|
+
cwd: root,
|
|
4642
|
+
managedToolId: "ast-grep"
|
|
4643
|
+
}, options?.allowInstall);
|
|
4644
|
+
},
|
|
4645
|
+
autoInstall: async () => Boolean(await ensureTool("ast-grep"))
|
|
4646
|
+
};
|
|
4647
|
+
var ZIZMOR_EXTENSIONS = KIND_EXTENSIONS["yaml"];
|
|
4648
|
+
var ZizmorServer = {
|
|
4649
|
+
id: "zizmor",
|
|
4650
|
+
idleEviction: "unmeasured",
|
|
4651
|
+
role: "auxiliary",
|
|
4652
|
+
name: "zizmor Actions Security Scanner",
|
|
4653
|
+
extensions: ZIZMOR_EXTENSIONS,
|
|
4654
|
+
pathFilter: isZizmorAuditTarget,
|
|
4655
|
+
// Stable per-repo root so ONE warm server serves the whole project (like
|
|
4656
|
+
// Opengrep) — config + workflow discovery is repo-relative.
|
|
4657
|
+
root: RootWithFallback(NearestRoot([".git"]), async () => process.cwd()),
|
|
4658
|
+
availabilityKey: "zizmor",
|
|
4659
|
+
async spawn(root, options) {
|
|
4660
|
+
const ghToken = await resolveZizmorGitHubToken();
|
|
4661
|
+
return resolveAndLaunch({
|
|
4662
|
+
candidates: ["zizmor"],
|
|
4663
|
+
args: ["--lsp"],
|
|
4664
|
+
cwd: root,
|
|
4665
|
+
managedToolId: "zizmor",
|
|
4666
|
+
...ghToken ? { env: { GH_TOKEN: ghToken } } : {}
|
|
4667
|
+
}, options?.allowInstall);
|
|
4668
|
+
},
|
|
4669
|
+
autoInstall: async () => Boolean(await ensureTool("zizmor"))
|
|
4670
|
+
};
|
|
4671
|
+
var TYPOS_EXTENSIONS = Array.from(/* @__PURE__ */ new Set([...OPENGREP_EXTENSIONS, ...KIND_EXTENSIONS["markdown"]]));
|
|
4672
|
+
function typosInitialization(root) {
|
|
4673
|
+
const localConfig = findLocalTyposConfig(root);
|
|
4674
|
+
if (localConfig) {
|
|
4675
|
+
logLatency({
|
|
4676
|
+
type: "phase",
|
|
4677
|
+
phase: "typos_config_resolved",
|
|
4678
|
+
filePath: root,
|
|
4679
|
+
durationMs: 0,
|
|
4680
|
+
metadata: { mode: "project_config", configPath: localConfig }
|
|
4681
|
+
});
|
|
4682
|
+
logSessionStart(`typos config resolved mode=project_config configPath=${localConfig}`);
|
|
4683
|
+
return void 0;
|
|
4684
|
+
}
|
|
4685
|
+
const configPath = resolvePackagePath(import.meta.url, "rules", "typos", "_typos.toml");
|
|
4686
|
+
logLatency({
|
|
4687
|
+
type: "phase",
|
|
4688
|
+
phase: "typos_config_resolved",
|
|
4689
|
+
filePath: root,
|
|
4690
|
+
durationMs: 0,
|
|
4691
|
+
metadata: { mode: "injected_default", configPath }
|
|
4692
|
+
});
|
|
4693
|
+
logSessionStart(`typos config resolved mode=injected_default configPath=${configPath}`);
|
|
4694
|
+
return { config: configPath };
|
|
4695
|
+
}
|
|
4696
|
+
var TyposServer = {
|
|
4697
|
+
id: "typos",
|
|
4698
|
+
idleEviction: "unmeasured",
|
|
4699
|
+
role: "auxiliary",
|
|
4700
|
+
name: "typos Spell Checker",
|
|
4701
|
+
extensions: TYPOS_EXTENSIONS,
|
|
4702
|
+
// Stable per-repo root so ONE warm server serves the whole project (like the
|
|
4703
|
+
// other auxiliaries) — typos.toml discovery is repo-relative.
|
|
4704
|
+
root: RootWithFallback(NearestRoot([".git"]), async () => process.cwd()),
|
|
4705
|
+
availabilityKey: "typos-lsp",
|
|
4706
|
+
async spawn(root, options) {
|
|
4707
|
+
const launched = await resolveAndLaunch({
|
|
4708
|
+
candidates: ["typos-lsp"],
|
|
4709
|
+
args: [],
|
|
4710
|
+
cwd: root,
|
|
4711
|
+
managedToolId: "typos-lsp"
|
|
4712
|
+
}, options?.allowInstall);
|
|
4713
|
+
if (!launched)
|
|
4714
|
+
return void 0;
|
|
4715
|
+
const initialization = typosInitialization(root);
|
|
4716
|
+
return initialization ? { ...launched, initialization } : launched;
|
|
4717
|
+
},
|
|
4718
|
+
autoInstall: async () => Boolean(await ensureTool("typos-lsp"))
|
|
4719
|
+
};
|
|
4720
|
+
var LSP_SERVERS = [
|
|
4721
|
+
TypeScriptServer,
|
|
4722
|
+
DenoServer,
|
|
4723
|
+
PythonServer,
|
|
4724
|
+
// pyright / basedpyright — preferred; openFilesOnly avoids cold-start; ty (#717) is a local-only opt-in fallback
|
|
4725
|
+
PythonJediServer,
|
|
4726
|
+
// fallback when neither pyright nor basedpyright is available
|
|
4727
|
+
GoServer,
|
|
4728
|
+
RustServer,
|
|
4729
|
+
RubyServer,
|
|
4730
|
+
PHPServer,
|
|
4731
|
+
PowerShellServer,
|
|
4732
|
+
// PowerShell Editor Services — pwsh-bootstrapped module bundle (#278)
|
|
4733
|
+
CSharpServer,
|
|
4734
|
+
OmniSharpServer,
|
|
4735
|
+
FSharpServer,
|
|
4736
|
+
JavaServer,
|
|
4737
|
+
KotlinServer,
|
|
4738
|
+
SwiftServer,
|
|
4739
|
+
DartServer,
|
|
4740
|
+
LuaServer,
|
|
4741
|
+
CppServer,
|
|
4742
|
+
ZigServer,
|
|
4743
|
+
HaskellServer,
|
|
4744
|
+
ElixirServer,
|
|
4745
|
+
ElixirExpertServer,
|
|
4746
|
+
GleamServer,
|
|
4747
|
+
TinymistServer,
|
|
4748
|
+
MarksmanServer,
|
|
4749
|
+
OCamlServer,
|
|
4750
|
+
ClojureServer,
|
|
4751
|
+
CueServer,
|
|
4752
|
+
TerraformServer,
|
|
4753
|
+
NixServer,
|
|
4754
|
+
BashServer,
|
|
4755
|
+
ShuckServer,
|
|
4756
|
+
FishServer,
|
|
4757
|
+
CMakeServer,
|
|
4758
|
+
DockerServer,
|
|
4759
|
+
DockerOfficialServer,
|
|
4760
|
+
// alternate of docker; acquired only when docker declines (#3939)
|
|
4761
|
+
YamlServer,
|
|
4762
|
+
JsonServer,
|
|
4763
|
+
HtmlServer,
|
|
4764
|
+
TomlServer,
|
|
4765
|
+
PrismaServer,
|
|
4766
|
+
// Web frameworks & styling
|
|
4767
|
+
VueServer,
|
|
4768
|
+
SvelteServer,
|
|
4769
|
+
CssServer,
|
|
4770
|
+
// Auxiliary (cross-cutting, diagnostic-only) servers go last — never primary.
|
|
4771
|
+
OpengrepServer,
|
|
4772
|
+
AstGrepServer,
|
|
4773
|
+
ZizmorServer,
|
|
4774
|
+
TyposServer
|
|
4775
|
+
];
|
|
4776
|
+
function getServerById(id) {
|
|
4777
|
+
return LSP_SERVERS.find((server) => server.id === id);
|
|
4778
|
+
}
|
|
4779
|
+
|
|
4780
|
+
export {
|
|
4781
|
+
findLocalTyposConfig,
|
|
4782
|
+
getAstGrepRuleSources,
|
|
4783
|
+
getAstGrepRuleFingerprint,
|
|
4784
|
+
isAuxiliary,
|
|
4785
|
+
serverTraits,
|
|
4786
|
+
registerRunnerId,
|
|
4787
|
+
BUILTIN_SERVER_RUNNER_COVERS,
|
|
4788
|
+
describeRootFallback,
|
|
4789
|
+
resolveLspServerCwd,
|
|
4790
|
+
resetLSPCaseSensitivityState,
|
|
4791
|
+
isSameOrWithin,
|
|
4792
|
+
enforceLspRootCeiling,
|
|
4793
|
+
hasProjectBoundaryMarker,
|
|
4794
|
+
resetLspLaunchAvailabilityGeneration,
|
|
4795
|
+
resetDirectLspCommandAvailability,
|
|
4796
|
+
isDirectLspCommandTemporarilyUnavailable,
|
|
4797
|
+
resetClassicTsRepairGuard,
|
|
4798
|
+
LSP_SERVERS,
|
|
4799
|
+
getServerById,
|
|
4800
|
+
shouldInitializeSessionRoot,
|
|
4801
|
+
isOutsideAllSessionRoots,
|
|
4802
|
+
getSessionRootsForTelemetry,
|
|
4803
|
+
loadLSPConfig,
|
|
4804
|
+
customServerSpecsOf,
|
|
4805
|
+
lspConfigOf,
|
|
4806
|
+
registerLSPConfig,
|
|
4807
|
+
initLSPConfig,
|
|
4808
|
+
explainServersForFile,
|
|
4809
|
+
getServersForFileWithConfig,
|
|
4810
|
+
primaryServerId,
|
|
4811
|
+
resolveLspCwdForFile,
|
|
4812
|
+
getServerInitOverride,
|
|
4813
|
+
getStrategy,
|
|
4814
|
+
classifyServerWaitTier,
|
|
4815
|
+
classifyCascadeWaitTier
|
|
4816
|
+
};
|