pi-lens 4.4.1 → 4.4.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/CHANGELOG.md +88 -0
- package/config/dependency-cruiser-eager-allowlist.json +3 -1
- package/dist/{chunk-BJF25SUG.js → chunk-23WOO7TX.js} +11 -10
- package/dist/{chunk-WATC3IQR.js → chunk-2B73ZPOK.js} +3 -3
- package/dist/{chunk-N2IRDBZI.js → chunk-2BBLFX75.js} +101 -11
- package/dist/{chunk-TA5L5KWQ.js → chunk-2CD5RS6M.js} +2 -2
- package/dist/{chunk-3TTPKMEF.js → chunk-2VUQMUMT.js} +38 -37
- package/dist/{chunk-5JHXUETW.js → chunk-3EFKIGZN.js} +3 -3
- package/dist/chunk-3JNKMP3B.js +17 -0
- package/dist/{chunk-6P54TMWL.js → chunk-3VPVG5SU.js} +6 -6
- package/dist/{chunk-ZETYB3XG.js → chunk-3W7IEVVL.js} +44 -28
- package/dist/chunk-3YN6V5TV.js +85 -0
- package/dist/chunk-466Z26MG.js +30 -0
- package/dist/{chunk-PCHDGUKT.js → chunk-4UNXBNE2.js} +12 -11
- package/dist/{chunk-J7WJZ6W7.js → chunk-4W4VLAPJ.js} +12 -11
- package/dist/{chunk-F5VLZHUW.js → chunk-52FUZI6K.js} +4 -2
- package/dist/{chunk-H5EV3VMF.js → chunk-5NGR67U5.js} +2 -2
- package/dist/{chunk-CBD2B5CP.js → chunk-5UCAH366.js} +21 -20
- package/dist/{chunk-BHWHXMQ2.js → chunk-67WMNWEE.js} +9 -8
- package/dist/{chunk-USHG4DLH.js → chunk-6C7JWPCP.js} +7 -7
- package/dist/{chunk-VPWKF3GN.js → chunk-6GFRNVYR.js} +11 -10
- package/dist/{chunk-3JL6IFD7.js → chunk-6SDEP3AJ.js} +9 -8
- package/dist/{chunk-NJF2X5XF.js → chunk-6STA6Z7I.js} +19 -17
- package/dist/{chunk-KJCWXUUS.js → chunk-724UL2TJ.js} +6 -4
- package/dist/{chunk-MQA2YBAH.js → chunk-76MWC2K6.js} +3 -3
- package/dist/{chunk-YLN4K6WD.js → chunk-77M37OKR.js} +10 -8
- package/dist/{chunk-XHSCVSOL.js → chunk-7DYBLXYA.js} +3 -3
- package/dist/{chunk-OC7LYAU5.js → chunk-AB3YYG6N.js} +24 -10
- package/dist/{chunk-LD7WFTRX.js → chunk-ACXEQZOU.js} +16 -16
- package/dist/{chunk-VSMJK3ZJ.js → chunk-AOHZU2BM.js} +1 -1
- package/dist/{chunk-T4QZ6FEH.js → chunk-AW7R2GWG.js} +65 -8
- package/dist/{chunk-GAYGGICG.js → chunk-BKE7E7TC.js} +10 -9
- package/dist/{chunk-EUT3B22Y.js → chunk-BRGDSBJE.js} +13 -12
- package/dist/{chunk-T54VJRAD.js → chunk-C34ZXZ7O.js} +55 -11
- package/dist/{chunk-UGSMCQ4D.js → chunk-CHOW74WE.js} +1 -1
- package/dist/{chunk-H2W2AXD3.js → chunk-CMMHNUZ2.js} +66 -58
- package/dist/chunk-CSHFH5IN.js +17 -0
- package/dist/chunk-EC47DWFA.js +56 -0
- package/dist/{chunk-KJN4IOEJ.js → chunk-EJIUXPBX.js} +1 -1
- package/dist/{chunk-IQZXOZ7S.js → chunk-EU63SDCG.js} +720 -334
- package/dist/{chunk-LNOMA3MP.js → chunk-FCSOVF55.js} +107 -3
- package/dist/{chunk-CFYISHUW.js → chunk-FLKWCIZH.js} +8 -5
- package/dist/{chunk-OYTMZXRF.js → chunk-FMSO6RDZ.js} +16 -14
- package/dist/{chunk-IUKPRZER.js → chunk-GAEGEPOC.js} +2 -2
- package/dist/{chunk-6XX5HCLK.js → chunk-GBPP5P7X.js} +4 -4
- package/dist/{chunk-TQFBZVCG.js → chunk-GXW6K4YJ.js} +1 -1
- package/dist/{chunk-ZZUFZUQZ.js → chunk-H6MF6EVN.js} +331 -107
- package/dist/{chunk-3JSEWUWI.js → chunk-IBGIOBEE.js} +3 -3
- package/dist/chunk-IZSHAIJ7.js +26 -0
- package/dist/{chunk-7ELY2CSM.js → chunk-JAU72XNY.js} +16 -14
- package/dist/chunk-JMYYOTQG.js +77 -0
- package/dist/{chunk-ELVWJYRV.js → chunk-JSQFTSC6.js} +12 -11
- package/dist/{chunk-J6DFZDFA.js → chunk-KBG47GHP.js} +4 -4
- package/dist/chunk-KDERNTCQ.js +28 -0
- package/dist/chunk-KSX3TXSZ.js +69 -0
- package/dist/{chunk-XGUL4SLQ.js → chunk-L3BLXZG7.js} +2 -2
- package/dist/chunk-LOP6GRPH.js +31 -0
- package/dist/{chunk-MTDRLSI7.js → chunk-M6HSLBWY.js} +1064 -986
- package/dist/chunk-MQLUAEOC.js +162 -0
- package/dist/{chunk-3MRXIJ6I.js → chunk-MRXKYPCS.js} +2 -2
- package/dist/{chunk-D65GOCJB.js → chunk-MXGY6KPT.js} +19 -16
- package/dist/{chunk-G3RLJYA2.js → chunk-N2H3ZPZY.js} +47 -1
- package/dist/{chunk-HREZQCT3.js → chunk-N3X6Q4YT.js} +3 -3
- package/dist/{chunk-HSIRMK2D.js → chunk-OCAGUNBC.js} +15 -15
- package/dist/{chunk-ZOEYVXSV.js → chunk-OXXKQCSV.js} +6 -6
- package/dist/{chunk-S6AMWKPC.js → chunk-P7266HLM.js} +2 -2
- package/dist/{chunk-64LU2OVH.js → chunk-PHDMFAKM.js} +12 -2
- package/dist/{chunk-IMSQR4WO.js → chunk-PNQDPDRC.js} +1 -1
- package/dist/{chunk-IUR76K6A.js → chunk-Q7DUK4LX.js} +5 -5
- package/dist/{chunk-CULQYFLU.js → chunk-QGQ5CCCG.js} +2 -2
- package/dist/{chunk-UEAHAMEI.js → chunk-QHJ6DQ2R.js} +11 -11
- package/dist/{chunk-BNKLYOOO.js → chunk-QILIYSJF.js} +1 -1
- package/dist/{chunk-VYKKMYVT.js → chunk-QOBUHWHX.js} +11 -6
- package/dist/{chunk-3PNFWVHT.js → chunk-QQNQ7SJW.js} +2 -75
- package/dist/{chunk-7M4T5N3V.js → chunk-R3PCY3YS.js} +14 -13
- package/dist/{chunk-MGIWSROG.js → chunk-RPLINGVB.js} +7 -7
- package/dist/{chunk-CMU4RMJB.js → chunk-RWWYJ623.js} +10 -1
- package/dist/{chunk-3FERWMCH.js → chunk-RXCOMYPY.js} +27 -26
- package/dist/{chunk-7BX5DWSA.js → chunk-SAEFPSB6.js} +11 -11
- package/dist/{chunk-N7YNJE5R.js → chunk-SQ4TVJBR.js} +10 -10
- package/dist/{chunk-DMS52BEP.js → chunk-SS36ZX4J.js} +9 -7
- package/dist/{chunk-JONGANYH.js → chunk-T6CPIZNT.js} +32 -30
- package/dist/{chunk-6UYA642J.js → chunk-TYM6OUIT.js} +13 -12
- package/dist/{chunk-ALQRYH6O.js → chunk-UXGETRP4.js} +13 -12
- package/dist/{chunk-FGALODG3.js → chunk-UZ3TUTRV.js} +1 -1
- package/dist/{chunk-J3FZR3YY.js → chunk-VCHXCQFG.js} +3 -3
- package/dist/{chunk-3P4PF2BX.js → chunk-VCO24T4L.js} +34 -22
- package/dist/{chunk-O7HZX7CA.js → chunk-VRZP76YM.js} +1 -1
- package/dist/{chunk-VZHJS6DR.js → chunk-VSSBEUFT.js} +16 -15
- package/dist/{chunk-U52SAGRM.js → chunk-VWCXW2E7.js} +1 -1
- package/dist/{chunk-WW5BLB74.js → chunk-WOA4LN2R.js} +2 -2
- package/dist/{chunk-ZMOMPX2Z.js → chunk-WU567RSC.js} +11 -10
- package/dist/{chunk-N77WFUL7.js → chunk-XAGLWMJ4.js} +23 -22
- package/dist/{chunk-WSEWKCXU.js → chunk-XCJN5IJU.js} +4 -4
- package/dist/{chunk-IR6XFA5P.js → chunk-XIJZVPD5.js} +16 -14
- package/dist/{chunk-OYOB3ZFG.js → chunk-XMSXXAHW.js} +2 -2
- package/dist/{chunk-34OCDWOS.js → chunk-XTMJ7XDT.js} +1 -1
- package/dist/{chunk-Z6BB4JLQ.js → chunk-XVF2VVXP.js} +5 -3
- package/dist/{chunk-AFZYMAIV.js → chunk-YIUAVF7E.js} +37 -35
- package/dist/{chunk-NFXP47RV.js → chunk-YSZNHOBY.js} +85 -31
- package/dist/{chunk-V5MEBST3.js → chunk-YYOIQFRS.js} +21 -21
- package/dist/chunk-Z527N6YQ.js +28 -0
- package/dist/{chunk-D6YF5HKX.js → chunk-ZANLILYD.js} +22 -2
- package/dist/{chunk-2UMYMRI3.js → chunk-ZGDGW2V3.js} +2 -2
- package/dist/{chunk-6B5I6ICN.js → chunk-ZHFZWTZV.js} +12 -11
- package/dist/{chunk-OEX24ECI.js → chunk-ZWFS3OEF.js} +51 -41
- package/dist/{chunk-AXKPQ6ZI.js → chunk-ZXYDQ3TZ.js} +5 -5
- package/dist/index.js +73783 -71033
- package/dist/mcp/analyze-cli.js +18 -8
- package/dist/mcp/cli.js +48 -37
- package/dist/mcp/server.js +568 -397
- package/dist/mcp/worker.js +67 -55
- package/dist/probes/installer.js +20 -19
- package/docs/astplayground.md +1 -1
- package/docs/configuration.md +29 -0
- package/docs/dependencies.md +3 -0
- package/docs/features.md +2 -2
- package/docs/globalconfig.md +2 -0
- package/docs/language-coverage.md +2 -1
- package/docs/lsp-capability-matrix.md +29 -7
- package/docs/lsp-idle-eviction.md +38 -47
- package/docs/pi-lens-fixer.md +4 -0
- package/docs/pi-lens-merge-policy.md +17 -4
- package/docs/pi-lens-retro.md +2 -1
- package/docs/pi-lens-reviewer.md +18 -0
- package/docs/pi-lens-subagent.md +7 -0
- package/docs/real-harness.md +17 -0
- package/docs/schema/pi-lens-config-v1.json +37 -2
- package/docs/servercapabilities.md +15 -4
- package/docs/settings.md +2 -1
- package/package.json +1 -1
- package/dist/chunk-2FQ62SPM.js +0 -83
- package/dist/chunk-7AXO3ZDF.js +0 -30
- package/dist/chunk-KMGPUKFD.js +0 -25
- package/dist/chunk-OZJINN4O.js +0 -84
- package/dist/chunk-RJFED73B.js +0 -79
- package/dist/chunk-RTQNRM5X.js +0 -27
- package/dist/chunk-VGEVL5EQ.js +0 -29
- package/dist/chunk-WPE5FPGR.js +0 -54
- package/dist/chunk-Z7QQA2KT.js +0 -27
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
resolveOpengrepConfig
|
|
4
|
+
} from "./chunk-VWCXW2E7.js";
|
|
2
5
|
import {
|
|
3
6
|
augmentPythonEnvironment,
|
|
4
7
|
detectPythonEnvironment,
|
|
5
8
|
detectPythonVenv,
|
|
6
9
|
pythonEnvironmentToolCandidates
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-FCSOVF55.js";
|
|
8
11
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
resolveGitCheckout,
|
|
13
|
+
resolveLinkedWorktreeOwner
|
|
14
|
+
} from "./chunk-PNQDPDRC.js";
|
|
11
15
|
import {
|
|
12
16
|
extensionsForLanguage,
|
|
13
17
|
getUserRuleRoot,
|
|
14
18
|
ruleCorpusFingerprintForCycle
|
|
15
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-724UL2TJ.js";
|
|
16
20
|
import {
|
|
17
21
|
load,
|
|
18
22
|
resolvePackagePath
|
|
@@ -22,11 +26,11 @@ import {
|
|
|
22
26
|
readCargoWorkspaceExclude,
|
|
23
27
|
readCargoWorkspaceMembers,
|
|
24
28
|
readTextFileOrUndefined
|
|
25
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-P7266HLM.js";
|
|
26
30
|
import {
|
|
27
31
|
HOOK_WALL_BUDGET_MS,
|
|
28
32
|
bounded
|
|
29
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-52FUZI6K.js";
|
|
30
34
|
import {
|
|
31
35
|
ensureTool,
|
|
32
36
|
findManagedToolBinary,
|
|
@@ -36,20 +40,21 @@ import {
|
|
|
36
40
|
isZizmorAuditTarget,
|
|
37
41
|
logSessionStart,
|
|
38
42
|
resolveZizmorGitHubToken
|
|
39
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-ACXEQZOU.js";
|
|
40
44
|
import {
|
|
41
45
|
resolveToolCwd
|
|
42
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-Q7DUK4LX.js";
|
|
43
47
|
import {
|
|
44
|
-
findGlobalBinary
|
|
45
|
-
|
|
48
|
+
findGlobalBinary,
|
|
49
|
+
isProjectLocalBinPath
|
|
50
|
+
} from "./chunk-AW7R2GWG.js";
|
|
46
51
|
import {
|
|
47
52
|
classifyProbeFailure,
|
|
48
53
|
createAvailabilityLatch,
|
|
49
54
|
describeInstallAttempt,
|
|
50
55
|
logAvailabilityDecision,
|
|
51
56
|
startHostStallSampler
|
|
52
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-VRZP76YM.js";
|
|
53
58
|
import {
|
|
54
59
|
OWNER_TAG_ENV,
|
|
55
60
|
SpawnFailureError,
|
|
@@ -62,22 +67,27 @@ import {
|
|
|
62
67
|
holdOwnChildPid,
|
|
63
68
|
isCommandAvailableAsync,
|
|
64
69
|
isPathIgnoredByProject,
|
|
70
|
+
isPiLensInternalPath,
|
|
65
71
|
ownerTagForChildren,
|
|
72
|
+
resolveWindowsCommandForEnvironment,
|
|
66
73
|
safeSpawnAsync
|
|
67
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-C34ZXZ7O.js";
|
|
68
75
|
import {
|
|
69
76
|
DOTNET_CSHARP_ROOT_MARKERS,
|
|
70
77
|
DOTNET_FSHARP_ROOT_MARKERS,
|
|
71
|
-
KIND_EXTENSIONS
|
|
72
|
-
|
|
78
|
+
KIND_EXTENSIONS,
|
|
79
|
+
LEAN_ROOT_MARKERS
|
|
80
|
+
} from "./chunk-PHDMFAKM.js";
|
|
73
81
|
import {
|
|
82
|
+
isRepoTier,
|
|
74
83
|
lspSectionOf,
|
|
75
84
|
migrationSubject,
|
|
85
|
+
provenanceFor,
|
|
76
86
|
reportConfigReadFailure,
|
|
77
87
|
reportPiLensConfigRecords,
|
|
78
88
|
resolvePiLensConfig,
|
|
79
89
|
summarizeConfigResolution
|
|
80
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-2BBLFX75.js";
|
|
81
91
|
import {
|
|
82
92
|
FRESHNESS_CADENCE_MS,
|
|
83
93
|
LSP_NAMESPACE_KEY,
|
|
@@ -85,23 +95,30 @@ import {
|
|
|
85
95
|
dirMtimesStillFreshAsync,
|
|
86
96
|
getPiLensGlobalConfigPath,
|
|
87
97
|
unknownDirMtimeRecords
|
|
88
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-XVF2VVXP.js";
|
|
89
99
|
import {
|
|
100
|
+
getProjectTrustState
|
|
101
|
+
} from "./chunk-ZANLILYD.js";
|
|
102
|
+
import {
|
|
103
|
+
getDegradationLedgerGeneration,
|
|
90
104
|
incrementDegradationCount,
|
|
91
105
|
recordDegradationOnce
|
|
92
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-JAU72XNY.js";
|
|
107
|
+
import {
|
|
108
|
+
logExtension
|
|
109
|
+
} from "./chunk-XTMJ7XDT.js";
|
|
93
110
|
import {
|
|
94
111
|
claimPhaseOncePerSession,
|
|
95
112
|
currentSessionRecordId,
|
|
96
113
|
logLatency,
|
|
97
114
|
releasePhaseClaim
|
|
98
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-QQNQ7SJW.js";
|
|
99
116
|
import {
|
|
100
117
|
getGlobalPiLensLogDir,
|
|
101
118
|
getProcessSingleton,
|
|
102
119
|
isTestMode,
|
|
103
120
|
redactSecrets
|
|
104
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-AOHZU2BM.js";
|
|
105
122
|
import {
|
|
106
123
|
STAGE_TMP_PATTERN
|
|
107
124
|
} from "./chunk-LJDODBBZ.js";
|
|
@@ -115,6 +132,8 @@ import {
|
|
|
115
132
|
findLocalToolConfig,
|
|
116
133
|
isAtOrAboveHomeDir,
|
|
117
134
|
isFullyQualified,
|
|
135
|
+
isUnderDir,
|
|
136
|
+
isVendorPath,
|
|
118
137
|
isWindowsPath,
|
|
119
138
|
matchesWorkspaceMemberPattern,
|
|
120
139
|
normalizeEphemeralMapKey,
|
|
@@ -122,56 +141,120 @@ import {
|
|
|
122
141
|
normalizeMapKey,
|
|
123
142
|
pathsEqual,
|
|
124
143
|
toPosix
|
|
125
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-N2H3ZPZY.js";
|
|
126
145
|
import {
|
|
127
146
|
__require
|
|
128
147
|
} from "./chunk-NXL4FFQQ.js";
|
|
129
148
|
|
|
130
|
-
// dist/clients/
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
149
|
+
// dist/clients/analysis-root.js
|
|
150
|
+
import * as fs from "node:fs";
|
|
151
|
+
import * as os from "node:os";
|
|
152
|
+
import * as nodePath from "node:path";
|
|
153
|
+
var PROJECT_MARKERS = [
|
|
154
|
+
".git",
|
|
155
|
+
"package.json",
|
|
156
|
+
"pyproject.toml",
|
|
157
|
+
"Cargo.toml",
|
|
158
|
+
"go.mod",
|
|
159
|
+
"pom.xml",
|
|
160
|
+
"build.gradle",
|
|
161
|
+
"Gemfile",
|
|
162
|
+
"mix.exs",
|
|
163
|
+
"composer.json"
|
|
164
|
+
];
|
|
165
|
+
function hasProjectMarker(dir) {
|
|
166
|
+
return PROJECT_MARKERS.some((marker) => {
|
|
167
|
+
try {
|
|
168
|
+
const stat2 = fs.statSync(nodePath.join(dir, marker));
|
|
169
|
+
return stat2.isFile() || marker === ".git";
|
|
170
|
+
} catch {
|
|
143
171
|
return false;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
function nearestProjectRoot(filePath) {
|
|
176
|
+
let dir = nodePath.dirname(nodePath.resolve(filePath));
|
|
177
|
+
const filesystemRoot = nodePath.parse(dir).root;
|
|
178
|
+
while (dir !== filesystemRoot) {
|
|
179
|
+
if (hasProjectMarker(dir))
|
|
180
|
+
return dir;
|
|
181
|
+
dir = nodePath.dirname(dir);
|
|
144
182
|
}
|
|
183
|
+
return hasProjectMarker(filesystemRoot) ? filesystemRoot : void 0;
|
|
145
184
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
185
|
+
function realPathOrResolved(filePath) {
|
|
186
|
+
const resolved = nodePath.resolve(filePath);
|
|
187
|
+
let current = resolved;
|
|
188
|
+
const missing = [];
|
|
189
|
+
while (true) {
|
|
190
|
+
try {
|
|
191
|
+
const real = fs.realpathSync.native(current);
|
|
192
|
+
return nodePath.join(real, ...missing.reverse());
|
|
193
|
+
} catch {
|
|
194
|
+
const parent = nodePath.dirname(current);
|
|
195
|
+
if (parent === current)
|
|
196
|
+
return resolved;
|
|
197
|
+
missing.push(nodePath.basename(current));
|
|
198
|
+
current = parent;
|
|
199
|
+
}
|
|
156
200
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
201
|
+
}
|
|
202
|
+
function resolveAnalysisRootPath(filePath, sessionRoot, homeDirOverride) {
|
|
203
|
+
const resolved = realPathOrResolved(filePath);
|
|
204
|
+
const session = realPathOrResolved(sessionRoot);
|
|
205
|
+
const tmp = realPathOrResolved(os.tmpdir());
|
|
206
|
+
const data = process.env.PI_LENS_HOME ? realPathOrResolved(process.env.PI_LENS_HOME) : void 0;
|
|
207
|
+
if (isVendorPath(resolved))
|
|
208
|
+
return void 0;
|
|
209
|
+
if (resolved === tmp || resolved === session || isUnderDir(session, resolved) || !isUnderDir(resolved, session) && (isPiLensInternalPath(resolved, session) || data !== void 0 && (resolved === data || isUnderDir(resolved, data))))
|
|
210
|
+
return void 0;
|
|
211
|
+
if (isUnderDir(resolved, session))
|
|
212
|
+
return session;
|
|
213
|
+
const checkout = resolveGitCheckout(session);
|
|
214
|
+
const linked = checkout && resolveLinkedWorktreeOwner(checkout, resolved);
|
|
215
|
+
if (linked && !isVendorPath(resolved))
|
|
216
|
+
return linked.root;
|
|
217
|
+
const candidate = nearestProjectRoot(resolved);
|
|
218
|
+
if (!candidate || candidate === nodePath.parse(candidate).root)
|
|
219
|
+
return void 0;
|
|
220
|
+
const home = realPathOrResolved(homeDirOverride ?? os.homedir());
|
|
221
|
+
if (isAtOrAboveHomeDir(candidate, home))
|
|
222
|
+
return void 0;
|
|
223
|
+
if (candidate === tmp || isUnderDir(session, candidate))
|
|
224
|
+
return void 0;
|
|
225
|
+
if (isVendorPath(candidate))
|
|
226
|
+
return void 0;
|
|
227
|
+
return candidate;
|
|
228
|
+
}
|
|
229
|
+
function resolveAnalysisRoot(filePath, sessionRoot, homeDirOverride) {
|
|
230
|
+
const resolved = realPathOrResolved(filePath);
|
|
231
|
+
if (isVendorPath(resolved))
|
|
232
|
+
return "none";
|
|
233
|
+
const checkout = resolveGitCheckout(sessionRoot);
|
|
234
|
+
if (checkout && resolveLinkedWorktreeOwner(checkout, resolved)) {
|
|
235
|
+
return "linked-worktree";
|
|
236
|
+
}
|
|
237
|
+
const root = resolveAnalysisRootPath(filePath, sessionRoot, homeDirOverride);
|
|
238
|
+
if (!root)
|
|
239
|
+
return "none";
|
|
240
|
+
if (root === nodePath.resolve(sessionRoot))
|
|
241
|
+
return "session";
|
|
242
|
+
return "adopted";
|
|
243
|
+
}
|
|
244
|
+
function canWriteAnalysisRoot(mode) {
|
|
245
|
+
return mode === "session" || mode === "linked-worktree";
|
|
163
246
|
}
|
|
164
247
|
|
|
165
248
|
// dist/clients/lsp/server.js
|
|
166
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, statSync as
|
|
249
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, statSync as statSync4 } from "node:fs";
|
|
167
250
|
import { access, readFile, readdir, stat } from "node:fs/promises";
|
|
168
|
-
import
|
|
169
|
-
import
|
|
251
|
+
import os7 from "node:os";
|
|
252
|
+
import path6 from "node:path";
|
|
170
253
|
|
|
171
254
|
// dist/clients/sgconfig.js
|
|
172
255
|
import { createHash } from "node:crypto";
|
|
173
|
-
import * as
|
|
174
|
-
import * as
|
|
256
|
+
import * as fs2 from "node:fs";
|
|
257
|
+
import * as os2 from "node:os";
|
|
175
258
|
import * as path from "node:path";
|
|
176
259
|
var SGCONFIG_NAMES = ["sgconfig.yml", "sgconfig.yaml"];
|
|
177
260
|
function findLocalSgconfig(startDir) {
|
|
@@ -179,7 +262,7 @@ function findLocalSgconfig(startDir) {
|
|
|
179
262
|
}
|
|
180
263
|
function canonicalDir(dir) {
|
|
181
264
|
try {
|
|
182
|
-
return
|
|
265
|
+
return fs2.realpathSync.native(dir);
|
|
183
266
|
} catch {
|
|
184
267
|
return path.resolve(dir);
|
|
185
268
|
}
|
|
@@ -222,7 +305,7 @@ function getAstGrepRuleSources(projectRoot = process.cwd()) {
|
|
|
222
305
|
});
|
|
223
306
|
const seen = /* @__PURE__ */ new Set();
|
|
224
307
|
return candidates.filter((source) => {
|
|
225
|
-
if (!
|
|
308
|
+
if (!fs2.existsSync(source.dir))
|
|
226
309
|
return false;
|
|
227
310
|
const key = canonicalDir(source.dir);
|
|
228
311
|
if (seen.has(key))
|
|
@@ -235,7 +318,7 @@ function findYamlFiles(dir) {
|
|
|
235
318
|
const files = [];
|
|
236
319
|
let entries;
|
|
237
320
|
try {
|
|
238
|
-
entries =
|
|
321
|
+
entries = fs2.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
239
322
|
} catch {
|
|
240
323
|
return files;
|
|
241
324
|
}
|
|
@@ -287,7 +370,7 @@ function snapshotRuleSource(source) {
|
|
|
287
370
|
hash.update("\0");
|
|
288
371
|
let content;
|
|
289
372
|
try {
|
|
290
|
-
content =
|
|
373
|
+
content = fs2.readFileSync(file, "utf8");
|
|
291
374
|
} catch {
|
|
292
375
|
hash.update("missing");
|
|
293
376
|
hash.update("\0");
|
|
@@ -329,8 +412,8 @@ function getAstGrepRuleFingerprint(projectRoot = process.cwd(), options = {}) {
|
|
|
329
412
|
return ruleCorpusFingerprintForCycle("ast-grep", root, (fingerprintRoot) => sourceFingerprint(getAstGrepRuleSources(fingerprintRoot).map(snapshotRuleSource)), options.force);
|
|
330
413
|
}
|
|
331
414
|
function materializeMergedRuleDir(sources, mergedDir) {
|
|
332
|
-
|
|
333
|
-
|
|
415
|
+
fs2.rmSync(mergedDir, { recursive: true, force: true });
|
|
416
|
+
fs2.mkdirSync(mergedDir, { recursive: true });
|
|
334
417
|
const claimedByEarlierSource = /* @__PURE__ */ new Set();
|
|
335
418
|
for (const [sourceIndex, source] of sources.entries()) {
|
|
336
419
|
const claimedThisSource = /* @__PURE__ */ new Set();
|
|
@@ -347,9 +430,9 @@ function materializeMergedRuleDir(sources, mergedDir) {
|
|
|
347
430
|
continue;
|
|
348
431
|
const destination = path.join(mergedDir, `source${sourceIndex}-${String(fileIndex).padStart(5, "0")}.yml`);
|
|
349
432
|
if (survivingDocuments.length === file.documents.length) {
|
|
350
|
-
|
|
433
|
+
fs2.copyFileSync(file.file, destination);
|
|
351
434
|
} else {
|
|
352
|
-
|
|
435
|
+
fs2.writeFileSync(destination, `${survivingDocuments.map((document) => document.raw.trim()).join("\n---\n")}
|
|
353
436
|
`);
|
|
354
437
|
}
|
|
355
438
|
}
|
|
@@ -365,14 +448,14 @@ function resolveBaselineSgconfig(projectRoot = process.cwd()) {
|
|
|
365
448
|
const root = canonicalDir(path.resolve(projectRoot || process.cwd()));
|
|
366
449
|
const fingerprint = getAstGrepRuleFingerprint(root, { force: true });
|
|
367
450
|
const cached = cachedBaselines.get(root);
|
|
368
|
-
if (cached?.fingerprint === fingerprint &&
|
|
451
|
+
if (cached?.fingerprint === fingerprint && fs2.existsSync(cached.path) && fs2.existsSync(cached.mergedDir)) {
|
|
369
452
|
return cached.path;
|
|
370
453
|
}
|
|
371
454
|
const sources = getAstGrepRuleSources(root).map(snapshotRuleSource);
|
|
372
455
|
if (sources.length === 0)
|
|
373
456
|
return void 0;
|
|
374
|
-
const dir = path.join(
|
|
375
|
-
|
|
457
|
+
const dir = path.join(os2.tmpdir(), "pi-lens-ast-grep");
|
|
458
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
376
459
|
const artifactKey = rootArtifactKey(root);
|
|
377
460
|
const file = path.join(dir, `baseline-${process.pid}-${artifactKey}.sgconfig.yml`);
|
|
378
461
|
const mergedDir = path.join(dir, `baseline-${process.pid}-${artifactKey}.rules`);
|
|
@@ -384,7 +467,7 @@ function resolveBaselineSgconfig(projectRoot = process.cwd()) {
|
|
|
384
467
|
cleanupStaleBaselines(dir, protectedArtifacts);
|
|
385
468
|
materializeMergedRuleDir(sources, mergedDir);
|
|
386
469
|
const ruleDirForYaml = mergedDir.split(path.sep).join("/");
|
|
387
|
-
|
|
470
|
+
fs2.writeFileSync(file, `ruleDirs:
|
|
388
471
|
- ${JSON.stringify(ruleDirForYaml)}
|
|
389
472
|
`);
|
|
390
473
|
cachedBaselines.set(root, { fingerprint, path: file, mergedDir });
|
|
@@ -395,7 +478,7 @@ var SG_BASELINE_RETAINED_ENTRIES = 24;
|
|
|
395
478
|
function enforceBaselineEntryCap(dir, keep) {
|
|
396
479
|
let names;
|
|
397
480
|
try {
|
|
398
|
-
names =
|
|
481
|
+
names = fs2.readdirSync(dir);
|
|
399
482
|
} catch {
|
|
400
483
|
return;
|
|
401
484
|
}
|
|
@@ -411,7 +494,7 @@ function enforceBaselineEntryCap(dir, keep) {
|
|
|
411
494
|
try {
|
|
412
495
|
candidates.push({
|
|
413
496
|
full,
|
|
414
|
-
mtimeMs:
|
|
497
|
+
mtimeMs: fs2.statSync(full).mtimeMs,
|
|
415
498
|
recursive: isMergedDir
|
|
416
499
|
});
|
|
417
500
|
} catch {
|
|
@@ -424,7 +507,7 @@ function enforceBaselineEntryCap(dir, keep) {
|
|
|
424
507
|
let evicted = 0;
|
|
425
508
|
for (const candidate of candidates.slice(0, over)) {
|
|
426
509
|
try {
|
|
427
|
-
|
|
510
|
+
fs2.rmSync(candidate.full, {
|
|
428
511
|
recursive: candidate.recursive,
|
|
429
512
|
force: true
|
|
430
513
|
});
|
|
@@ -448,7 +531,7 @@ function enforceBaselineEntryCap(dir, keep) {
|
|
|
448
531
|
function cleanupStaleBaselines(dir, keep) {
|
|
449
532
|
try {
|
|
450
533
|
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
451
|
-
for (const name of
|
|
534
|
+
for (const name of fs2.readdirSync(dir)) {
|
|
452
535
|
const isConfig = /^baseline(?:-\d+(?:-[a-f0-9]+)?)?\.sgconfig\.yml$/.test(name);
|
|
453
536
|
const isMergedDir = /^baseline-\d+(?:-[a-f0-9]+)?\.rules$/.test(name);
|
|
454
537
|
if (!isConfig && !isMergedDir)
|
|
@@ -457,9 +540,9 @@ function cleanupStaleBaselines(dir, keep) {
|
|
|
457
540
|
if (keep.has(full))
|
|
458
541
|
continue;
|
|
459
542
|
try {
|
|
460
|
-
const stat2 =
|
|
543
|
+
const stat2 = fs2.statSync(full);
|
|
461
544
|
if (stat2.mtimeMs < cutoff) {
|
|
462
|
-
|
|
545
|
+
fs2.rmSync(full, { recursive: stat2.isDirectory(), force: true });
|
|
463
546
|
}
|
|
464
547
|
} catch {
|
|
465
548
|
}
|
|
@@ -478,9 +561,44 @@ function findLocalTyposConfig(startDir) {
|
|
|
478
561
|
return findLocalToolConfig(startDir, LOCAL_TYPOS_CONFIG_NAMES);
|
|
479
562
|
}
|
|
480
563
|
|
|
564
|
+
// dist/clients/lsp/server-traits.js
|
|
565
|
+
var ROLE_MEMBERS = {
|
|
566
|
+
language: "language",
|
|
567
|
+
auxiliary: "auxiliary"
|
|
568
|
+
};
|
|
569
|
+
var DEFAULT_LSP_SERVER_ROLE = "language";
|
|
570
|
+
function isAuxiliary(bearer) {
|
|
571
|
+
const declared = bearer?.role;
|
|
572
|
+
const role = typeof declared === "string" && Object.hasOwn(ROLE_MEMBERS, declared) ? ROLE_MEMBERS[declared] : DEFAULT_LSP_SERVER_ROLE;
|
|
573
|
+
switch (role) {
|
|
574
|
+
case "auxiliary":
|
|
575
|
+
return true;
|
|
576
|
+
case "language":
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
var DEFAULT_NOTIFY_INFLIGHT_LIMIT = 8;
|
|
581
|
+
var DEFAULT_REPLY_ORDERING = "unmeasured";
|
|
582
|
+
function serverTraits(declaration) {
|
|
583
|
+
const declaredLimit = declaration.notifyInflightLimit;
|
|
584
|
+
if (typeof declaredLimit === "number" && Number.isFinite(declaredLimit) && declaredLimit > 0) {
|
|
585
|
+
return {
|
|
586
|
+
role: declaration.role,
|
|
587
|
+
notifyInflightLimit: Math.floor(declaredLimit),
|
|
588
|
+
replyOrdering: declaration.replyOrdering ?? DEFAULT_REPLY_ORDERING
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
const envLimit = Number(process.env.PI_LENS_LSP_AUX_NOTIFY_INFLIGHT);
|
|
592
|
+
return {
|
|
593
|
+
role: declaration.role,
|
|
594
|
+
notifyInflightLimit: Number.isFinite(envLimit) && envLimit > 0 ? Math.floor(envLimit) : DEFAULT_NOTIFY_INFLIGHT_LIMIT,
|
|
595
|
+
replyOrdering: declaration.replyOrdering ?? DEFAULT_REPLY_ORDERING
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
|
|
481
599
|
// dist/clients/lsp/config.js
|
|
482
|
-
import * as
|
|
483
|
-
import
|
|
600
|
+
import * as os4 from "node:os";
|
|
601
|
+
import path3 from "node:path";
|
|
484
602
|
|
|
485
603
|
// dist/clients/dispatch/known-runner-ids.js
|
|
486
604
|
var knownRunnerIds = /* @__PURE__ */ new Set();
|
|
@@ -495,13 +613,14 @@ function isKnownRunnerId(id) {
|
|
|
495
613
|
}
|
|
496
614
|
|
|
497
615
|
// dist/clients/lsp/launch.js
|
|
616
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
498
617
|
import { execFileSync, spawn as nodeSpawn } from "node:child_process";
|
|
499
|
-
import
|
|
500
|
-
import
|
|
618
|
+
import fs4 from "node:fs";
|
|
619
|
+
import os3 from "node:os";
|
|
501
620
|
import path2 from "node:path";
|
|
502
621
|
|
|
503
622
|
// dist/clients/lsp/ruby-drive-dirs.js
|
|
504
|
-
import * as
|
|
623
|
+
import * as fs3 from "node:fs";
|
|
505
624
|
var RUBY_VERSION_DIR = /^ruby\d/i;
|
|
506
625
|
var rubyDirNamesCache = new BoundedLruCache(16);
|
|
507
626
|
function rubyDriveKey(driveRoot) {
|
|
@@ -517,7 +636,7 @@ function getRubyVersionDirNamesSync(driveRoot) {
|
|
|
517
636
|
return cached;
|
|
518
637
|
let names;
|
|
519
638
|
try {
|
|
520
|
-
names = filterRubyDirNames(
|
|
639
|
+
names = filterRubyDirNames(fs3.readdirSync(driveRoot));
|
|
521
640
|
} catch {
|
|
522
641
|
names = [];
|
|
523
642
|
}
|
|
@@ -531,7 +650,7 @@ async function getRubyVersionDirNamesAsync(driveRoot) {
|
|
|
531
650
|
return cached;
|
|
532
651
|
let names;
|
|
533
652
|
try {
|
|
534
|
-
names = filterRubyDirNames(await
|
|
653
|
+
names = filterRubyDirNames(await fs3.promises.readdir(driveRoot));
|
|
535
654
|
} catch {
|
|
536
655
|
names = [];
|
|
537
656
|
}
|
|
@@ -558,8 +677,8 @@ function logSessionStart2(msg) {
|
|
|
558
677
|
const line = redactSecrets(`[${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}
|
|
559
678
|
`);
|
|
560
679
|
try {
|
|
561
|
-
|
|
562
|
-
|
|
680
|
+
fs4.mkdirSync(SESSIONSTART_LOG_DIR, { recursive: true });
|
|
681
|
+
fs4.appendFileSync(SESSIONSTART_LOG, line);
|
|
563
682
|
} catch {
|
|
564
683
|
}
|
|
565
684
|
}
|
|
@@ -640,7 +759,7 @@ async function buildAugmentedPath(basePath) {
|
|
|
640
759
|
candidates.push(nodeDir);
|
|
641
760
|
}
|
|
642
761
|
if (isWindows) {
|
|
643
|
-
const home =
|
|
762
|
+
const home = os3.homedir();
|
|
644
763
|
const driveRoot = path2.parse(home).root;
|
|
645
764
|
candidates.push(path2.join(home, ".cargo", "bin"));
|
|
646
765
|
candidates.push(path2.join(home, "go", "bin"));
|
|
@@ -662,7 +781,7 @@ async function buildAugmentedPath(basePath) {
|
|
|
662
781
|
}
|
|
663
782
|
const toAppend = [];
|
|
664
783
|
for (const candidate of candidates) {
|
|
665
|
-
if (!candidate || !
|
|
784
|
+
if (!candidate || !fs4.existsSync(candidate))
|
|
666
785
|
continue;
|
|
667
786
|
const normalized = normalizePathEntry(candidate, process.platform);
|
|
668
787
|
if (existing.has(normalized))
|
|
@@ -678,29 +797,39 @@ async function buildAugmentedPath(basePath) {
|
|
|
678
797
|
}
|
|
679
798
|
function isCmdShimValid(cmdPath) {
|
|
680
799
|
try {
|
|
681
|
-
const content =
|
|
800
|
+
const content = fs4.readFileSync(cmdPath, "utf-8");
|
|
682
801
|
const match = content.match(/"%~dp0[/\\]\.\.[/\\]((?:[\w./@-]|\\)+\.(?:mjs|cjs|js))"/i);
|
|
683
802
|
if (!match)
|
|
684
803
|
return true;
|
|
685
804
|
const relPath = match[1].replace(/[/\\]/g, path2.sep);
|
|
686
805
|
const target = path2.resolve(path2.dirname(cmdPath), "..", relPath);
|
|
687
|
-
return
|
|
806
|
+
return fs4.existsSync(target);
|
|
688
807
|
} catch {
|
|
689
808
|
return true;
|
|
690
809
|
}
|
|
691
810
|
}
|
|
811
|
+
function isMissingWindowsStartupCommand(command, spawnCommand, cwd, env) {
|
|
812
|
+
if (!isWindows)
|
|
813
|
+
return false;
|
|
814
|
+
if (/\.(cmd|bat)$/i.test(spawnCommand) && !isCmdShimValid(spawnCommand)) {
|
|
815
|
+
return true;
|
|
816
|
+
}
|
|
817
|
+
if (spawnCommand !== command)
|
|
818
|
+
return false;
|
|
819
|
+
return resolveWindowsCommandForEnvironment(command, cwd, env) === null;
|
|
820
|
+
}
|
|
692
821
|
function bypassPs1OnWindows(ps1Path, args) {
|
|
693
822
|
const cmdPath = `${ps1Path.slice(0, -4)}.cmd`;
|
|
694
|
-
if (
|
|
823
|
+
if (fs4.existsSync(cmdPath)) {
|
|
695
824
|
return { command: cmdPath, args, needsShell: true };
|
|
696
825
|
}
|
|
697
826
|
try {
|
|
698
|
-
const content =
|
|
827
|
+
const content = fs4.readFileSync(ps1Path, "utf-8");
|
|
699
828
|
const match = content.match(/"\$basedir[/\\]\.\.[/\\]((?:[\w./@-]|\\)+\.(?:mjs|cjs|js))"/i);
|
|
700
829
|
if (match) {
|
|
701
830
|
const relPath = match[1].replace(/[/\\]/g, path2.sep);
|
|
702
831
|
const jsPath = path2.resolve(path2.dirname(ps1Path), "..", relPath);
|
|
703
|
-
if (
|
|
832
|
+
if (fs4.existsSync(jsPath)) {
|
|
704
833
|
return {
|
|
705
834
|
command: process.execPath,
|
|
706
835
|
args: [jsPath, ...args],
|
|
@@ -728,7 +857,7 @@ function findBinaryOnPath(command, env) {
|
|
|
728
857
|
timeout: 5e3
|
|
729
858
|
}).split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
730
859
|
for (const candidate of result) {
|
|
731
|
-
if (
|
|
860
|
+
if (fs4.existsSync(candidate)) {
|
|
732
861
|
return candidate;
|
|
733
862
|
}
|
|
734
863
|
}
|
|
@@ -736,6 +865,65 @@ function findBinaryOnPath(command, env) {
|
|
|
736
865
|
}
|
|
737
866
|
return void 0;
|
|
738
867
|
}
|
|
868
|
+
var lspProjectCodePermission = new AsyncLocalStorage();
|
|
869
|
+
function withLspProjectCodePermission(allowed, spawn) {
|
|
870
|
+
return lspProjectCodePermission.run(allowed, spawn);
|
|
871
|
+
}
|
|
872
|
+
var unknownProjectLocalNoticeGeneration = -1;
|
|
873
|
+
function recordUntrustedLspExecution(request, trust) {
|
|
874
|
+
const generation = getDegradationLedgerGeneration();
|
|
875
|
+
const subject = request.kind === "project-code-server" ? `project-code-server:g${generation}:${request.serverId}:${request.root}` : `project-local-binary:g${generation}:${path2.basename(request.command)}`;
|
|
876
|
+
const metadata = request.kind === "project-code-server" ? {
|
|
877
|
+
field: request.kind,
|
|
878
|
+
serverId: request.serverId,
|
|
879
|
+
root: request.root,
|
|
880
|
+
trust
|
|
881
|
+
} : {
|
|
882
|
+
field: request.kind,
|
|
883
|
+
trust
|
|
884
|
+
};
|
|
885
|
+
recordDegradationOnce({
|
|
886
|
+
kind: "lsp-registry-decision",
|
|
887
|
+
subject,
|
|
888
|
+
reason: (request.kind === "project-local-binary" ? request.reason : void 0) ?? `LSP execution refused: ${request.kind} and project trust is ${trust}`,
|
|
889
|
+
metadata
|
|
890
|
+
});
|
|
891
|
+
if (unknownProjectLocalNoticeGeneration !== generation) {
|
|
892
|
+
unknownProjectLocalNoticeGeneration = generation;
|
|
893
|
+
const label = request.kind === "project-code-server" ? "project-code LSP server" : "project-local LSP binary";
|
|
894
|
+
logExtension({
|
|
895
|
+
subsystem: "lsp-registry",
|
|
896
|
+
level: "warn",
|
|
897
|
+
message: `${label} refused: mark the project trusted in pi or upgrade pi`,
|
|
898
|
+
metadata: { field: request.kind }
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
function refuseUntrustedLspExecution(request) {
|
|
903
|
+
const trust = getProjectTrustState();
|
|
904
|
+
const needsTrust = request.kind === "project-code-server" ? trust !== "trusted" : !admitProjectSuppliedTsserver(request.resolvedCommand, request.cwd, true);
|
|
905
|
+
if (!needsTrust)
|
|
906
|
+
return;
|
|
907
|
+
if (request.kind === "project-code-server")
|
|
908
|
+
recordUntrustedLspExecution(request, trust);
|
|
909
|
+
throw new SpawnFailureError("spawn-failed", `LSP ${request.kind === "project-code-server" ? "project-code server" : "project-local binary"} refused: project trust is ${trust}`, new Error(`project trust is ${trust}`));
|
|
910
|
+
}
|
|
911
|
+
function admitProjectSuppliedTsserver(tsserverPath, cwd, projectSupplied, projectCodeAllowed = lspProjectCodePermission.getStore() ?? false) {
|
|
912
|
+
const trust = getProjectTrustState();
|
|
913
|
+
if (tsserverPath && (!projectSupplied || projectCodeAllowed && trust === "trusted"))
|
|
914
|
+
return tsserverPath;
|
|
915
|
+
recordUntrustedLspExecution({
|
|
916
|
+
kind: "project-local-binary",
|
|
917
|
+
command: tsserverPath ?? "tsserver.js",
|
|
918
|
+
resolvedCommand: tsserverPath ?? "tsserver.js",
|
|
919
|
+
cwd,
|
|
920
|
+
reason: tsserverPath ? "LSP execution refused: project compiler requires trusted session ownership" : "LSP execution refused: no admitted absolute TypeScript compiler"
|
|
921
|
+
}, trust);
|
|
922
|
+
return void 0;
|
|
923
|
+
}
|
|
924
|
+
function isProjectLocalLspBinary(resolvedCommand, cwd) {
|
|
925
|
+
return isProjectLocalBinPath(resolvedCommand, cwd);
|
|
926
|
+
}
|
|
739
927
|
function trySpawn(command, args, cwd, env, needsShell) {
|
|
740
928
|
let proc;
|
|
741
929
|
if (needsShell) {
|
|
@@ -764,9 +952,6 @@ function trySpawn(command, args, cwd, env, needsShell) {
|
|
|
764
952
|
if (!proc.stdin || !proc.stdout || !proc.stderr) {
|
|
765
953
|
throw new Error(`Failed to spawn LSP server: ${command}`);
|
|
766
954
|
}
|
|
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
955
|
holdOwnChildPid(proc.pid, "lsp-spawn");
|
|
771
956
|
return proc;
|
|
772
957
|
}
|
|
@@ -842,6 +1027,14 @@ async function launchLSP(command, args = [], options = {}) {
|
|
|
842
1027
|
needsShell = computeNeedsShell(spawnCommand);
|
|
843
1028
|
}
|
|
844
1029
|
}
|
|
1030
|
+
if (isProjectLocalLspBinary(spawnCommand, cwd)) {
|
|
1031
|
+
refuseUntrustedLspExecution({
|
|
1032
|
+
kind: "project-local-binary",
|
|
1033
|
+
command,
|
|
1034
|
+
resolvedCommand: spawnCommand,
|
|
1035
|
+
cwd
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
845
1038
|
if (isWindows && /\.(cmd|bat)$/i.test(spawnCommand) && !isCmdShimValid(spawnCommand)) {
|
|
846
1039
|
logSessionStart2(`lsp cmd-shim-invalid: ${spawnCommand} target missing \u2014 skipping candidate`);
|
|
847
1040
|
const cause = Object.assign(new Error(`LSP .cmd shim target not found: ${spawnCommand}`), { code: "ENOENT" });
|
|
@@ -878,7 +1071,12 @@ async function launchLSP(command, args = [], options = {}) {
|
|
|
878
1071
|
throw new Error(`Failed to spawn LSP server: ${command}`);
|
|
879
1072
|
}
|
|
880
1073
|
if (proc.exitCode !== null || proc.killed) {
|
|
881
|
-
|
|
1074
|
+
const message = `LSP server ${command} exited immediately (code: ${proc.exitCode}). The binary may be missing or corrupted.`;
|
|
1075
|
+
const failure = new Error(message);
|
|
1076
|
+
if (proc.exitCode === 1 && isMissingWindowsStartupCommand(command, spawnCommand, cwd, env)) {
|
|
1077
|
+
throw new SpawnFailureError("tool-not-found", message, failure);
|
|
1078
|
+
}
|
|
1079
|
+
throw failure;
|
|
882
1080
|
}
|
|
883
1081
|
logSessionStart2(`lsp launch: command=${command} resolved=${spawnCommand} args=${JSON.stringify(args)} cwd=${cwd} shell=${needsShell ? "true" : "false"} pid=${proc.pid ?? 0}`);
|
|
884
1082
|
const formatStartupStderr = (stderr) => {
|
|
@@ -895,7 +1093,7 @@ async function launchLSP(command, args = [], options = {}) {
|
|
|
895
1093
|
};
|
|
896
1094
|
proc.stderr?.on("data", onStartupStderr);
|
|
897
1095
|
try {
|
|
898
|
-
await new Promise((
|
|
1096
|
+
await new Promise((resolve4, reject) => {
|
|
899
1097
|
let settled = false;
|
|
900
1098
|
proc.on("error", (err) => {
|
|
901
1099
|
if (!settled) {
|
|
@@ -911,7 +1109,13 @@ async function launchLSP(command, args = [], options = {}) {
|
|
|
911
1109
|
settled = true;
|
|
912
1110
|
const isWindowsCmd = isWindows && command.endsWith(".cmd");
|
|
913
1111
|
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
|
-
|
|
1112
|
+
const message = `LSP server ${command} exited immediately with code ${code}. ${errorMsg}${formatStartupStderr(startupStderr)}`;
|
|
1113
|
+
const failure = new Error(message);
|
|
1114
|
+
if (code === 1 && isMissingWindowsStartupCommand(command, spawnCommand, cwd, env)) {
|
|
1115
|
+
reject(new SpawnFailureError("tool-not-found", message, failure));
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
reject(failure);
|
|
915
1119
|
}
|
|
916
1120
|
});
|
|
917
1121
|
const startupFailureWindowMs = (() => {
|
|
@@ -926,7 +1130,7 @@ async function launchLSP(command, args = [], options = {}) {
|
|
|
926
1130
|
setTimeout(() => {
|
|
927
1131
|
if (!settled) {
|
|
928
1132
|
settled = true;
|
|
929
|
-
|
|
1133
|
+
resolve4();
|
|
930
1134
|
}
|
|
931
1135
|
}, startupFailureWindowMs);
|
|
932
1136
|
});
|
|
@@ -951,61 +1155,13 @@ async function launchLSP(command, args = [], options = {}) {
|
|
|
951
1155
|
};
|
|
952
1156
|
}
|
|
953
1157
|
|
|
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
1158
|
// dist/clients/lsp/config.js
|
|
1003
1159
|
function asRecord(value) {
|
|
1004
1160
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
1005
1161
|
}
|
|
1006
1162
|
var CONFIG_RESOLVED_PHASE = "config_resolved";
|
|
1007
1163
|
function configResolutionKey(cwd) {
|
|
1008
|
-
return normalizeFilePath(
|
|
1164
|
+
return normalizeFilePath(path3.resolve(normalizeFilePath(cwd)));
|
|
1009
1165
|
}
|
|
1010
1166
|
function publishConfigResolutionPending(cwd) {
|
|
1011
1167
|
logSessionStart(`session_start config_resolution_pending session=${currentSessionRecordId()} root=${configResolutionKey(cwd)}`);
|
|
@@ -1035,7 +1191,7 @@ function recordConfigResolved(cwd, resolution, lspConfig, homeDir, resolveMs) {
|
|
|
1035
1191
|
});
|
|
1036
1192
|
logSessionStart(`config resolved documents=${summary.documents.length} legacy=${legacyDocuments} records=${summary.recordCount} deniedServers=${deniedServers} resolveMs=${resolveMs} session=${sessionId} root=${root}`);
|
|
1037
1193
|
}
|
|
1038
|
-
async function loadLSPConfig(cwd, homeDir =
|
|
1194
|
+
async function loadLSPConfig(cwd, homeDir = os4.homedir(), options = {}) {
|
|
1039
1195
|
const reporting = options.report !== false;
|
|
1040
1196
|
publishConfigResolutionPending(cwd);
|
|
1041
1197
|
const resolveStartedAt = Date.now();
|
|
@@ -1061,6 +1217,10 @@ async function loadLSPConfig(cwd, homeDir = os3.homedir(), options = {}) {
|
|
|
1061
1217
|
});
|
|
1062
1218
|
const coversProblems = newCoversClaimProblems();
|
|
1063
1219
|
const config = lspConfigOf(resolution.value, coversProblems);
|
|
1220
|
+
Object.defineProperty(config, "__provenance", {
|
|
1221
|
+
value: resolution.provenance,
|
|
1222
|
+
enumerable: false
|
|
1223
|
+
});
|
|
1064
1224
|
if (reporting) {
|
|
1065
1225
|
reportPiLensConfigRecords([
|
|
1066
1226
|
...resolution.records,
|
|
@@ -1158,7 +1318,7 @@ function customServerSpecsOf(value) {
|
|
|
1158
1318
|
const servers = asRecord(lspSectionOf(value).servers);
|
|
1159
1319
|
return servers ? coversValidatedServers(servers) : {};
|
|
1160
1320
|
}
|
|
1161
|
-
function lspConfigOf(value, problems) {
|
|
1321
|
+
function lspConfigOf(value, problems, provenance) {
|
|
1162
1322
|
const section = lspSectionOf(value);
|
|
1163
1323
|
const config = {};
|
|
1164
1324
|
const servers = asRecord(section.servers);
|
|
@@ -1174,6 +1334,12 @@ function lspConfigOf(value, problems) {
|
|
|
1174
1334
|
if (Array.isArray(section.warmFiles)) {
|
|
1175
1335
|
config.warmFiles = section.warmFiles;
|
|
1176
1336
|
}
|
|
1337
|
+
if (provenance) {
|
|
1338
|
+
Object.defineProperty(config, "__provenance", {
|
|
1339
|
+
value: provenance,
|
|
1340
|
+
enumerable: false
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1177
1343
|
return config;
|
|
1178
1344
|
}
|
|
1179
1345
|
function createCustomServer(config, id) {
|
|
@@ -1209,26 +1375,74 @@ function createCustomServer(config, id) {
|
|
|
1209
1375
|
cwd: root,
|
|
1210
1376
|
env: config.env ? { ...process.env, ...config.env } : process.env
|
|
1211
1377
|
});
|
|
1212
|
-
return {
|
|
1378
|
+
return {
|
|
1379
|
+
process: proc,
|
|
1380
|
+
...config.initializationOptions ? { initialization: config.initializationOptions } : {}
|
|
1381
|
+
};
|
|
1213
1382
|
}
|
|
1214
1383
|
};
|
|
1215
1384
|
}
|
|
1216
1385
|
var EMPTY_CONFIG = {
|
|
1217
1386
|
customServers: [],
|
|
1387
|
+
// Avoid reading LSP_SERVERS during the config/server module cycle. The
|
|
1388
|
+
// selection helper falls back to the live builtin table after evaluation.
|
|
1389
|
+
registeredServers: [],
|
|
1218
1390
|
disabledServerIds: /* @__PURE__ */ new Set(),
|
|
1219
1391
|
serverOverrides: /* @__PURE__ */ new Map()
|
|
1220
1392
|
};
|
|
1221
1393
|
var configInFlight = /* @__PURE__ */ new Map();
|
|
1222
1394
|
function normalizeWorkspacePath(cwd) {
|
|
1223
|
-
return
|
|
1395
|
+
return path3.resolve(cwd);
|
|
1396
|
+
}
|
|
1397
|
+
var unknownTrustNoticeGeneration = -1;
|
|
1398
|
+
function sourceFor(provenance, key) {
|
|
1399
|
+
const direct = provenanceFor({ value: void 0, provenance }, key);
|
|
1400
|
+
if (direct)
|
|
1401
|
+
return direct;
|
|
1402
|
+
let fallback;
|
|
1403
|
+
for (const [candidate, entry] of provenance) {
|
|
1404
|
+
if (!candidate.startsWith(`${key}/`))
|
|
1405
|
+
continue;
|
|
1406
|
+
if (isRepoTier(entry.tier))
|
|
1407
|
+
return entry;
|
|
1408
|
+
fallback ??= entry;
|
|
1409
|
+
}
|
|
1410
|
+
return fallback;
|
|
1411
|
+
}
|
|
1412
|
+
function executableAllowed(provenance, trust) {
|
|
1413
|
+
return !provenance || !isRepoTier(provenance.tier) || trust === "trusted";
|
|
1414
|
+
}
|
|
1415
|
+
function registryDecision(id, field, provenance, trust, allowed) {
|
|
1416
|
+
if (allowed || !provenance || !isRepoTier(provenance.tier))
|
|
1417
|
+
return;
|
|
1418
|
+
const subject = `${id}:${field}:${provenance.tier}`;
|
|
1419
|
+
const reason = `project LSP ${field} refused for ${id}: pi project trust is ${trust}`;
|
|
1420
|
+
recordDegradationOnce({
|
|
1421
|
+
kind: "lsp-registry-decision",
|
|
1422
|
+
subject,
|
|
1423
|
+
reason,
|
|
1424
|
+
metadata: { serverId: id, field, tier: provenance.tier, trust }
|
|
1425
|
+
});
|
|
1426
|
+
if (trust === "unknown") {
|
|
1427
|
+
const generation = getDegradationLedgerGeneration();
|
|
1428
|
+
if (unknownTrustNoticeGeneration !== generation) {
|
|
1429
|
+
unknownTrustNoticeGeneration = generation;
|
|
1430
|
+
logExtension({
|
|
1431
|
+
subsystem: "lsp-registry",
|
|
1432
|
+
level: "warn",
|
|
1433
|
+
message: "project LSP executables refused: mark the project trusted in pi or upgrade pi",
|
|
1434
|
+
metadata: { serverId: id, field }
|
|
1435
|
+
});
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1224
1438
|
}
|
|
1225
1439
|
function isSameOrChildPath(filePath, candidateRoot) {
|
|
1226
1440
|
if (filePath === candidateRoot)
|
|
1227
1441
|
return true;
|
|
1228
|
-
return filePath.startsWith(`${candidateRoot}${
|
|
1442
|
+
return filePath.startsWith(`${candidateRoot}${path3.sep}`);
|
|
1229
1443
|
}
|
|
1230
1444
|
function getConfigForFile(filePath) {
|
|
1231
|
-
const resolvedFilePath =
|
|
1445
|
+
const resolvedFilePath = path3.resolve(filePath);
|
|
1232
1446
|
let bestMatch;
|
|
1233
1447
|
for (const [root, config] of sessionRootConfigEntries()) {
|
|
1234
1448
|
if (config === void 0)
|
|
@@ -1242,13 +1456,33 @@ function getConfigForFile(filePath) {
|
|
|
1242
1456
|
return bestMatch?.config ?? EMPTY_CONFIG;
|
|
1243
1457
|
}
|
|
1244
1458
|
function registerLSPConfig(config) {
|
|
1459
|
+
return compileLspRegistry(config, config.__provenance);
|
|
1460
|
+
}
|
|
1461
|
+
function compileLspRegistry(config, provenance = /* @__PURE__ */ new Map()) {
|
|
1462
|
+
const trust = getProjectTrustState();
|
|
1245
1463
|
const customServers = [];
|
|
1246
1464
|
const disabledServerIds = new Set(config.disabledServers ?? []);
|
|
1247
1465
|
if (config.servers) {
|
|
1248
1466
|
for (const [id, serverConfig] of Object.entries(config.servers)) {
|
|
1467
|
+
const commandSource = sourceFor(provenance, `/lsp/servers/${id}/command`);
|
|
1468
|
+
const commandAllowed = executableAllowed(commandSource, trust);
|
|
1469
|
+
registryDecision(id, "command", commandSource, trust, commandAllowed);
|
|
1470
|
+
if (!commandAllowed)
|
|
1471
|
+
continue;
|
|
1472
|
+
const envSource = sourceFor(provenance, `/lsp/servers/${id}/env`);
|
|
1473
|
+
const initSource = sourceFor(provenance, `/lsp/servers/${id}/initializationOptions`);
|
|
1474
|
+
const envAllowed = executableAllowed(envSource, trust);
|
|
1475
|
+
const initAllowed = executableAllowed(initSource, trust);
|
|
1476
|
+
registryDecision(id, "env", envSource, trust, envAllowed);
|
|
1477
|
+
registryDecision(id, "initializationOptions", initSource, trust, initAllowed);
|
|
1478
|
+
const admitted = { ...serverConfig };
|
|
1479
|
+
if (!envAllowed)
|
|
1480
|
+
delete admitted.env;
|
|
1481
|
+
if (!initAllowed)
|
|
1482
|
+
delete admitted.initializationOptions;
|
|
1249
1483
|
try {
|
|
1250
|
-
const server = createCustomServer(
|
|
1251
|
-
customServers.push(server);
|
|
1484
|
+
const server = createCustomServer(admitted, id);
|
|
1485
|
+
customServers.push({ ...server, trustAllowed: true });
|
|
1252
1486
|
} catch {
|
|
1253
1487
|
}
|
|
1254
1488
|
}
|
|
@@ -1258,15 +1492,53 @@ function registerLSPConfig(config) {
|
|
|
1258
1492
|
for (const [id, entry] of Object.entries(config.serverOverrides)) {
|
|
1259
1493
|
if (entry && typeof entry === "object" && !Array.isArray(entry)) {
|
|
1260
1494
|
const initOpts = entry.initializationOptions;
|
|
1261
|
-
|
|
1495
|
+
const command = entry.command;
|
|
1496
|
+
const commandSource = sourceFor(provenance, `/lsp/serverOverrides/${id}/command`);
|
|
1497
|
+
const envSource = sourceFor(provenance, `/lsp/serverOverrides/${id}/env`);
|
|
1498
|
+
const initSource = sourceFor(provenance, `/lsp/serverOverrides/${id}/initializationOptions`);
|
|
1499
|
+
const commandAllowed = executableAllowed(commandSource, trust);
|
|
1500
|
+
const envAllowed = executableAllowed(envSource, trust);
|
|
1501
|
+
const overrideInitAllowed = executableAllowed(initSource, trust);
|
|
1502
|
+
registryDecision(id, "command override", commandSource, trust, commandAllowed);
|
|
1503
|
+
registryDecision(id, "env override", envSource, trust, envAllowed);
|
|
1504
|
+
registryDecision(id, "initializationOptions", initSource, trust, overrideInitAllowed);
|
|
1505
|
+
if (command !== void 0 || entry.env !== void 0 || initOpts !== void 0 && typeof initOpts === "object" && initOpts !== null && !Array.isArray(initOpts)) {
|
|
1262
1506
|
serverOverrides.set(id, {
|
|
1263
|
-
initializationOptions: initOpts
|
|
1507
|
+
...overrideInitAllowed && initOpts !== void 0 ? { initializationOptions: initOpts } : {},
|
|
1508
|
+
...commandAllowed && command !== void 0 ? { command } : {},
|
|
1509
|
+
...envAllowed && entry.env ? { env: entry.env } : {}
|
|
1264
1510
|
});
|
|
1265
1511
|
}
|
|
1266
1512
|
}
|
|
1267
1513
|
}
|
|
1268
1514
|
}
|
|
1269
|
-
|
|
1515
|
+
const overriddenBuiltins = LSP_SERVERS.map((server) => {
|
|
1516
|
+
const override = serverOverrides.get(server.id);
|
|
1517
|
+
if (!override?.command)
|
|
1518
|
+
return { ...server };
|
|
1519
|
+
const argv = Array.isArray(override.command) ? override.command : [override.command, "--stdio"];
|
|
1520
|
+
return {
|
|
1521
|
+
...server,
|
|
1522
|
+
trustAllowed: true,
|
|
1523
|
+
async spawn(root, options) {
|
|
1524
|
+
void options;
|
|
1525
|
+
const program = argv[0];
|
|
1526
|
+
if (!program)
|
|
1527
|
+
throw new Error(`empty command override for ${server.id}`);
|
|
1528
|
+
const proc = await launchLSP(program, argv.slice(1), {
|
|
1529
|
+
cwd: root,
|
|
1530
|
+
env: override.env ? { ...process.env, ...override.env } : process.env
|
|
1531
|
+
});
|
|
1532
|
+
return { process: proc };
|
|
1533
|
+
}
|
|
1534
|
+
};
|
|
1535
|
+
});
|
|
1536
|
+
return {
|
|
1537
|
+
customServers,
|
|
1538
|
+
registeredServers: overriddenBuiltins,
|
|
1539
|
+
disabledServerIds,
|
|
1540
|
+
serverOverrides
|
|
1541
|
+
};
|
|
1270
1542
|
}
|
|
1271
1543
|
function forgetConfigResolvedClaims(evictedRoots) {
|
|
1272
1544
|
for (const root of evictedRoots) {
|
|
@@ -1280,7 +1552,7 @@ async function initLSPConfig(cwd) {
|
|
|
1280
1552
|
if (existing)
|
|
1281
1553
|
return existing;
|
|
1282
1554
|
const promise = (async () => {
|
|
1283
|
-
const config = registerLSPConfig(await loadLSPConfig(cwd,
|
|
1555
|
+
const config = registerLSPConfig(await loadLSPConfig(cwd, os4.homedir()));
|
|
1284
1556
|
forgetConfigResolvedClaims(setSessionRootConfig(normalizedCwd, config));
|
|
1285
1557
|
})();
|
|
1286
1558
|
configInFlight.set(normalizedCwd, promise);
|
|
@@ -1293,7 +1565,8 @@ async function initLSPConfig(cwd) {
|
|
|
1293
1565
|
}
|
|
1294
1566
|
}
|
|
1295
1567
|
function registeredServers(config) {
|
|
1296
|
-
|
|
1568
|
+
const builtins = config.registeredServers.length ? config.registeredServers : LSP_SERVERS;
|
|
1569
|
+
return [...builtins, ...config.customServers];
|
|
1297
1570
|
}
|
|
1298
1571
|
function selectionReason(server, config, filePath, ext, base) {
|
|
1299
1572
|
if (config.disabledServerIds.has(server.id))
|
|
@@ -1313,8 +1586,8 @@ function selectionReason(server, config, filePath, ext, base) {
|
|
|
1313
1586
|
return "selected";
|
|
1314
1587
|
}
|
|
1315
1588
|
function explainServersForFile(filePath, config = getConfigForFile(filePath)) {
|
|
1316
|
-
const ext =
|
|
1317
|
-
const base =
|
|
1589
|
+
const ext = path3.extname(filePath).toLowerCase();
|
|
1590
|
+
const base = path3.basename(filePath).toLowerCase();
|
|
1318
1591
|
return registeredServers(config).map((server) => {
|
|
1319
1592
|
const reason = selectionReason(server, config, filePath, ext, base);
|
|
1320
1593
|
return { server, selected: reason === "selected", reason };
|
|
@@ -1322,8 +1595,8 @@ function explainServersForFile(filePath, config = getConfigForFile(filePath)) {
|
|
|
1322
1595
|
}
|
|
1323
1596
|
function getServersForFileWithConfig(filePath) {
|
|
1324
1597
|
const config = getConfigForFile(filePath);
|
|
1325
|
-
const ext =
|
|
1326
|
-
const base =
|
|
1598
|
+
const ext = path3.extname(filePath).toLowerCase();
|
|
1599
|
+
const base = path3.basename(filePath).toLowerCase();
|
|
1327
1600
|
return registeredServers(config).filter((server) => selectionReason(server, config, filePath, ext, base) === "selected");
|
|
1328
1601
|
}
|
|
1329
1602
|
function primaryServerEntry(filePath) {
|
|
@@ -1384,11 +1657,15 @@ function resolveAstGrepNativeExe(platform = process.platform, arch = process.arc
|
|
|
1384
1657
|
}
|
|
1385
1658
|
var SERVER_DIAGNOSTIC_STRATEGIES = {
|
|
1386
1659
|
typescript: {
|
|
1387
|
-
seedFirstPush:
|
|
1660
|
+
seedFirstPush: false,
|
|
1388
1661
|
pullRetryBudgetMs: 0,
|
|
1389
1662
|
debounceMs: 50,
|
|
1390
1663
|
aggregateWaitMs: 1e3,
|
|
1391
1664
|
expectSemanticSecondPush: false,
|
|
1665
|
+
// #3310 / nightly run 37930006227: the clean TypeScript fixture
|
|
1666
|
+
// published an empty pre-index result before its settled result.
|
|
1667
|
+
// Hold that first publish so it cannot resolve a push wait as clean.
|
|
1668
|
+
emptyFirstPublish: "indexing",
|
|
1392
1669
|
// Tier 3 (#458): typescript-language-server publishes nothing on a
|
|
1393
1670
|
// clean→clean edit (docs/lsp-capability-matrix.md, re-confirmed
|
|
1394
1671
|
// 2026-07-12). It's the lone core-set tier-3 server, which is exactly
|
|
@@ -1788,32 +2065,32 @@ function classifyCascadeWaitTier(lspService, filePath, snapshots) {
|
|
|
1788
2065
|
}
|
|
1789
2066
|
|
|
1790
2067
|
// dist/clients/lsp/lombok.js
|
|
1791
|
-
import * as
|
|
1792
|
-
import * as
|
|
1793
|
-
import * as
|
|
2068
|
+
import * as fs5 from "node:fs";
|
|
2069
|
+
import * as os5 from "node:os";
|
|
2070
|
+
import * as path4 from "node:path";
|
|
1794
2071
|
var LOMBOK_ENV_KEYS = ["PI_LENS_LOMBOK_JAR", "LOMBOK_JAR"];
|
|
1795
2072
|
var LOMBOK_PROJECT_FILES = [
|
|
1796
2073
|
"lombok.config",
|
|
1797
2074
|
"pom.xml",
|
|
1798
2075
|
"build.gradle",
|
|
1799
2076
|
"build.gradle.kts",
|
|
1800
|
-
|
|
2077
|
+
path4.join("gradle", "libs.versions.toml")
|
|
1801
2078
|
];
|
|
1802
2079
|
function fileExists(filePath) {
|
|
1803
2080
|
if (!filePath)
|
|
1804
2081
|
return false;
|
|
1805
2082
|
try {
|
|
1806
|
-
return
|
|
2083
|
+
return fs5.statSync(filePath).isFile();
|
|
1807
2084
|
} catch {
|
|
1808
2085
|
return false;
|
|
1809
2086
|
}
|
|
1810
2087
|
}
|
|
1811
2088
|
function readTextIfSmall(filePath, maxBytes = 512 * 1024) {
|
|
1812
2089
|
try {
|
|
1813
|
-
const stat2 =
|
|
2090
|
+
const stat2 = fs5.statSync(filePath);
|
|
1814
2091
|
if (!stat2.isFile() || stat2.size > maxBytes)
|
|
1815
2092
|
return "";
|
|
1816
|
-
return
|
|
2093
|
+
return fs5.readFileSync(filePath, "utf-8");
|
|
1817
2094
|
} catch {
|
|
1818
2095
|
return "";
|
|
1819
2096
|
}
|
|
@@ -1822,13 +2099,13 @@ function containsLombokDependency(text) {
|
|
|
1822
2099
|
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
2100
|
}
|
|
1824
2101
|
function hasLombokProject(root) {
|
|
1825
|
-
const lombokConfig =
|
|
2102
|
+
const lombokConfig = path4.join(root, "lombok.config");
|
|
1826
2103
|
if (fileExists(lombokConfig))
|
|
1827
2104
|
return true;
|
|
1828
2105
|
for (const name of LOMBOK_PROJECT_FILES) {
|
|
1829
2106
|
if (name === "lombok.config")
|
|
1830
2107
|
continue;
|
|
1831
|
-
const text = readTextIfSmall(
|
|
2108
|
+
const text = readTextIfSmall(path4.join(root, name));
|
|
1832
2109
|
if (text && containsLombokDependency(text))
|
|
1833
2110
|
return true;
|
|
1834
2111
|
}
|
|
@@ -1838,23 +2115,23 @@ function envJarCandidate(env) {
|
|
|
1838
2115
|
for (const key of LOMBOK_ENV_KEYS) {
|
|
1839
2116
|
const value = env[key]?.trim();
|
|
1840
2117
|
if (fileExists(value))
|
|
1841
|
-
return
|
|
2118
|
+
return path4.resolve(value);
|
|
1842
2119
|
}
|
|
1843
2120
|
return void 0;
|
|
1844
2121
|
}
|
|
1845
2122
|
function localJarCandidates(root) {
|
|
1846
2123
|
return [
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
2124
|
+
path4.join(root, "lombok.jar"),
|
|
2125
|
+
path4.join(root, ".lombok", "lombok.jar"),
|
|
2126
|
+
path4.join(root, "lib", "lombok.jar"),
|
|
2127
|
+
path4.join(root, "libs", "lombok.jar")
|
|
1851
2128
|
];
|
|
1852
2129
|
}
|
|
1853
2130
|
function newestExistingJar(candidates) {
|
|
1854
2131
|
let best;
|
|
1855
2132
|
for (const candidate of candidates) {
|
|
1856
2133
|
try {
|
|
1857
|
-
const stat2 =
|
|
2134
|
+
const stat2 = fs5.statSync(candidate);
|
|
1858
2135
|
if (!stat2.isFile())
|
|
1859
2136
|
continue;
|
|
1860
2137
|
if (!best || stat2.mtimeMs > best.mtimeMs) {
|
|
@@ -1865,35 +2142,35 @@ function newestExistingJar(candidates) {
|
|
|
1865
2142
|
}
|
|
1866
2143
|
return best?.filePath;
|
|
1867
2144
|
}
|
|
1868
|
-
function mavenLocalLombokJar(home =
|
|
1869
|
-
const base =
|
|
2145
|
+
function mavenLocalLombokJar(home = os5.homedir()) {
|
|
2146
|
+
const base = path4.join(home, ".m2", "repository", "org", "projectlombok", "lombok");
|
|
1870
2147
|
let versions = [];
|
|
1871
2148
|
try {
|
|
1872
|
-
versions =
|
|
2149
|
+
versions = fs5.readdirSync(base);
|
|
1873
2150
|
} catch {
|
|
1874
2151
|
return void 0;
|
|
1875
2152
|
}
|
|
1876
|
-
return newestExistingJar(versions.map((version) =>
|
|
2153
|
+
return newestExistingJar(versions.map((version) => path4.join(base, version, `lombok-${version}.jar`)));
|
|
1877
2154
|
}
|
|
1878
|
-
function gradleCacheLombokJar(home =
|
|
1879
|
-
const base =
|
|
2155
|
+
function gradleCacheLombokJar(home = os5.homedir()) {
|
|
2156
|
+
const base = path4.join(home, ".gradle", "caches", "modules-2", "files-2.1", "org.projectlombok", "lombok");
|
|
1880
2157
|
const candidates = [];
|
|
1881
2158
|
let versions = [];
|
|
1882
2159
|
try {
|
|
1883
|
-
versions =
|
|
2160
|
+
versions = fs5.readdirSync(base);
|
|
1884
2161
|
} catch {
|
|
1885
2162
|
return void 0;
|
|
1886
2163
|
}
|
|
1887
2164
|
for (const version of versions) {
|
|
1888
|
-
const versionDir =
|
|
2165
|
+
const versionDir = path4.join(base, version);
|
|
1889
2166
|
let hashes = [];
|
|
1890
2167
|
try {
|
|
1891
|
-
hashes =
|
|
2168
|
+
hashes = fs5.readdirSync(versionDir);
|
|
1892
2169
|
} catch {
|
|
1893
2170
|
continue;
|
|
1894
2171
|
}
|
|
1895
2172
|
for (const hash of hashes) {
|
|
1896
|
-
candidates.push(
|
|
2173
|
+
candidates.push(path4.join(versionDir, hash, `lombok-${version}.jar`));
|
|
1897
2174
|
}
|
|
1898
2175
|
}
|
|
1899
2176
|
return newestExistingJar(candidates);
|
|
@@ -1925,16 +2202,16 @@ function createLombokJdtlsArgs(root, baseEnv = process.env) {
|
|
|
1925
2202
|
|
|
1926
2203
|
// dist/clients/lsp/jvm-runtime.js
|
|
1927
2204
|
import { existsSync as existsSync2, readdirSync as readdirSync4 } from "node:fs";
|
|
1928
|
-
import
|
|
1929
|
-
import
|
|
2205
|
+
import os6 from "node:os";
|
|
2206
|
+
import path5 from "node:path";
|
|
1930
2207
|
var JAVA_EXE = process.platform === "win32" ? "java.exe" : "java";
|
|
1931
2208
|
var JAVA_PROBE_TIMEOUT_MS = 5e3;
|
|
1932
2209
|
var MIN_JAVA_MAJOR = 17;
|
|
1933
2210
|
function jdkHomeFrom(dir) {
|
|
1934
|
-
if (existsSync2(
|
|
2211
|
+
if (existsSync2(path5.join(dir, "bin", JAVA_EXE)))
|
|
1935
2212
|
return dir;
|
|
1936
|
-
const macHome =
|
|
1937
|
-
if (existsSync2(
|
|
2213
|
+
const macHome = path5.join(dir, "Contents", "Home");
|
|
2214
|
+
if (existsSync2(path5.join(macHome, "bin", JAVA_EXE)))
|
|
1938
2215
|
return macHome;
|
|
1939
2216
|
return void 0;
|
|
1940
2217
|
}
|
|
@@ -1947,34 +2224,34 @@ function parseMajorVersion(name) {
|
|
|
1947
2224
|
}
|
|
1948
2225
|
function childDirs(base) {
|
|
1949
2226
|
try {
|
|
1950
|
-
return readdirSync4(base, { withFileTypes: true }).filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) =>
|
|
2227
|
+
return readdirSync4(base, { withFileTypes: true }).filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) => path5.join(base, e.name));
|
|
1951
2228
|
} catch {
|
|
1952
2229
|
return [];
|
|
1953
2230
|
}
|
|
1954
2231
|
}
|
|
1955
2232
|
function candidateRoots() {
|
|
1956
|
-
const home =
|
|
2233
|
+
const home = os6.homedir();
|
|
1957
2234
|
const roots = [];
|
|
1958
|
-
roots.push(
|
|
1959
|
-
roots.push(
|
|
2235
|
+
roots.push(path5.join(home, ".jdks"));
|
|
2236
|
+
roots.push(path5.join(getGlobalPiLensDir(), "tools"));
|
|
1960
2237
|
if (process.platform === "win32") {
|
|
1961
2238
|
const progFiles = [
|
|
1962
2239
|
process.env.ProgramFiles,
|
|
1963
2240
|
process.env["ProgramFiles(x86)"],
|
|
1964
2241
|
process.env.ProgramW6432,
|
|
1965
|
-
|
|
2242
|
+
path5.join(process.env.LOCALAPPDATA ?? path5.join(home, "AppData", "Local"), "Programs")
|
|
1966
2243
|
].filter((p) => Boolean(p));
|
|
1967
2244
|
for (const base of progFiles) {
|
|
1968
|
-
roots.push(
|
|
1969
|
-
roots.push(
|
|
1970
|
-
roots.push(
|
|
1971
|
-
roots.push(
|
|
1972
|
-
roots.push(
|
|
1973
|
-
roots.push(
|
|
2245
|
+
roots.push(path5.join(base, "Eclipse Adoptium"));
|
|
2246
|
+
roots.push(path5.join(base, "Java"));
|
|
2247
|
+
roots.push(path5.join(base, "Microsoft"));
|
|
2248
|
+
roots.push(path5.join(base, "Zulu"));
|
|
2249
|
+
roots.push(path5.join(base, "Amazon Corretto"));
|
|
2250
|
+
roots.push(path5.join(base, "BellSoft"));
|
|
1974
2251
|
}
|
|
1975
2252
|
} else if (process.platform === "darwin") {
|
|
1976
2253
|
roots.push("/Library/Java/JavaVirtualMachines");
|
|
1977
|
-
roots.push(
|
|
2254
|
+
roots.push(path5.join(home, "Library", "Java", "JavaVirtualMachines"));
|
|
1978
2255
|
roots.push("/opt/homebrew/opt");
|
|
1979
2256
|
roots.push("/usr/local/opt");
|
|
1980
2257
|
} else {
|
|
@@ -1998,7 +2275,7 @@ function discoverJdkHome(roots = candidateRoots(), javaHome = process.env.JAVA_H
|
|
|
1998
2275
|
continue;
|
|
1999
2276
|
found.push({
|
|
2000
2277
|
home: resolved,
|
|
2001
|
-
major: parseMajorVersion(
|
|
2278
|
+
major: parseMajorVersion(path5.basename(dir))
|
|
2002
2279
|
});
|
|
2003
2280
|
}
|
|
2004
2281
|
}
|
|
@@ -2097,12 +2374,12 @@ async function resolveJavaRuntimeEnv() {
|
|
|
2097
2374
|
}
|
|
2098
2375
|
const home = discoverJdkHome();
|
|
2099
2376
|
if (home) {
|
|
2100
|
-
const binDir =
|
|
2377
|
+
const binDir = path5.join(home, "bin");
|
|
2101
2378
|
const currentPath = process.env.PATH ?? process.env.Path ?? "";
|
|
2102
2379
|
_cachedEnv = {
|
|
2103
2380
|
value: {
|
|
2104
2381
|
JAVA_HOME: home,
|
|
2105
|
-
PATH: binDir +
|
|
2382
|
+
PATH: binDir + path5.delimiter + currentPath
|
|
2106
2383
|
}
|
|
2107
2384
|
};
|
|
2108
2385
|
return _cachedEnv.value;
|
|
@@ -2158,7 +2435,7 @@ async function resolveLspServerCwd(server, filePath, sessionCwd, onRootFailure,
|
|
|
2158
2435
|
rootFailed = true;
|
|
2159
2436
|
onRootFailure?.(reason);
|
|
2160
2437
|
}
|
|
2161
|
-
const isFileDirFallback = serverRoot !== void 0 && rootMarkers?.length &&
|
|
2438
|
+
const isFileDirFallback = serverRoot !== void 0 && rootMarkers?.length && path6.resolve(serverRoot) === path6.resolve(path6.dirname(filePath));
|
|
2162
2439
|
if (!serverRoot || isFileDirFallback) {
|
|
2163
2440
|
const probedMarker = onRootFallback && !rootFailed && rootMarkers?.length ? resolveToolCwd("lsp", server.id, filePath, {
|
|
2164
2441
|
cwd: sessionCwd,
|
|
@@ -2167,7 +2444,7 @@ async function resolveLspServerCwd(server, filePath, sessionCwd, onRootFailure,
|
|
|
2167
2444
|
}).marker : void 0;
|
|
2168
2445
|
const refusedMarker = probedMarker !== void 0 && rootMarkers?.includes(probedMarker) ? probedMarker : void 0;
|
|
2169
2446
|
const fallbackCwd = rootMarkers?.length ? resolveToolCwd("lsp", server.id, filePath, {
|
|
2170
|
-
cwd:
|
|
2447
|
+
cwd: path6.dirname(path6.resolve(filePath)),
|
|
2171
2448
|
rootMarkers
|
|
2172
2449
|
}) : void 0;
|
|
2173
2450
|
if (!serverRoot) {
|
|
@@ -2237,21 +2514,21 @@ var PROJECT_BOUNDARY_MARKERS = [
|
|
|
2237
2514
|
var loggedRootCeilingClamps = /* @__PURE__ */ new Set();
|
|
2238
2515
|
var posixCaseInsensitiveByPath = /* @__PURE__ */ new Map();
|
|
2239
2516
|
function posixFilesystemIsCaseInsensitive(root) {
|
|
2240
|
-
const resolved =
|
|
2517
|
+
const resolved = path6.resolve(root);
|
|
2241
2518
|
const cached = posixCaseInsensitiveByPath.get(resolved);
|
|
2242
2519
|
if (cached !== void 0)
|
|
2243
2520
|
return cached;
|
|
2244
2521
|
if (!existsSync3(resolved)) {
|
|
2245
2522
|
return false;
|
|
2246
2523
|
}
|
|
2247
|
-
const name =
|
|
2524
|
+
const name = path6.basename(resolved);
|
|
2248
2525
|
const alternate = name.toLowerCase() === name ? name.toUpperCase() : name.toLowerCase();
|
|
2249
2526
|
let insensitive = false;
|
|
2250
|
-
const alternatePath =
|
|
2527
|
+
const alternatePath = path6.join(path6.dirname(resolved), alternate);
|
|
2251
2528
|
if (alternate !== name && existsSync3(alternatePath)) {
|
|
2252
2529
|
try {
|
|
2253
|
-
const actual =
|
|
2254
|
-
const alternateStat =
|
|
2530
|
+
const actual = statSync4(resolved);
|
|
2531
|
+
const alternateStat = statSync4(alternatePath);
|
|
2255
2532
|
insensitive = actual.dev === alternateStat.dev && actual.ino === alternateStat.ino;
|
|
2256
2533
|
} catch {
|
|
2257
2534
|
insensitive = false;
|
|
@@ -2265,7 +2542,7 @@ function resetLSPCaseSensitivityState() {
|
|
|
2265
2542
|
}
|
|
2266
2543
|
function isSameOrWithin(ancestor, candidate, deps = {}) {
|
|
2267
2544
|
const windowsShaped = isWindowsPath(ancestor) || isWindowsPath(candidate);
|
|
2268
|
-
const pathApi = windowsShaped ?
|
|
2545
|
+
const pathApi = windowsShaped ? path6.win32 : path6;
|
|
2269
2546
|
const resolvedAncestor = pathApi.resolve(ancestor);
|
|
2270
2547
|
const resolvedCandidate = pathApi.resolve(candidate);
|
|
2271
2548
|
let caseInsensitive = false;
|
|
@@ -2285,7 +2562,7 @@ function isSameOrWithin(ancestor, candidate, deps = {}) {
|
|
|
2285
2562
|
}
|
|
2286
2563
|
function enforceLspRootCeiling(root, sessionCwd, filePath) {
|
|
2287
2564
|
const windowsShaped = isWindowsPath(root) || isWindowsPath(sessionCwd);
|
|
2288
|
-
const pathApi = windowsShaped ?
|
|
2565
|
+
const pathApi = windowsShaped ? path6.win32 : path6;
|
|
2289
2566
|
const resolvedRoot = pathApi.resolve(root);
|
|
2290
2567
|
const resolvedCwd = pathApi.resolve(sessionCwd);
|
|
2291
2568
|
if (filePath && !isSameOrWithin(resolvedCwd, pathApi.resolve(filePath))) {
|
|
@@ -2310,8 +2587,8 @@ async function hasProjectBoundaryMarker(dir) {
|
|
|
2310
2587
|
return false;
|
|
2311
2588
|
}
|
|
2312
2589
|
function pathSegments(dir) {
|
|
2313
|
-
const parsed =
|
|
2314
|
-
return
|
|
2590
|
+
const parsed = path6.parse(path6.resolve(dir));
|
|
2591
|
+
return path6.relative(parsed.root, path6.resolve(dir)).split(path6.sep).filter(Boolean).map((segment) => segment.toLowerCase());
|
|
2315
2592
|
}
|
|
2316
2593
|
function hasFixtureConvention(dir) {
|
|
2317
2594
|
const segments = pathSegments(dir);
|
|
@@ -2323,18 +2600,18 @@ function hasAtomicStageSegment(dir) {
|
|
|
2323
2600
|
return pathSegments(dir).some((segment) => STAGE_TMP_PATTERN.test(segment));
|
|
2324
2601
|
}
|
|
2325
2602
|
async function findGitBoundary(dir) {
|
|
2326
|
-
let current =
|
|
2327
|
-
const fsRoot =
|
|
2603
|
+
let current = path6.resolve(dir);
|
|
2604
|
+
const fsRoot = path6.parse(current).root;
|
|
2328
2605
|
while (true) {
|
|
2329
2606
|
if (await markerExists(current, ".git"))
|
|
2330
2607
|
return current;
|
|
2331
2608
|
if (current === fsRoot)
|
|
2332
2609
|
return void 0;
|
|
2333
|
-
current =
|
|
2610
|
+
current = path6.dirname(current);
|
|
2334
2611
|
}
|
|
2335
2612
|
}
|
|
2336
2613
|
async function isExcludedLspRoot(dir) {
|
|
2337
|
-
const candidate =
|
|
2614
|
+
const candidate = path6.resolve(dir);
|
|
2338
2615
|
if (hasFixtureConvention(candidate) || hasAtomicStageSegment(candidate))
|
|
2339
2616
|
return true;
|
|
2340
2617
|
const gitRoot = await findGitBoundary(candidate);
|
|
@@ -2346,9 +2623,9 @@ async function isExcludedLspRoot(dir) {
|
|
|
2346
2623
|
}
|
|
2347
2624
|
async function nearestNonExcludedFallbackRoot(candidate) {
|
|
2348
2625
|
if (!await isExcludedLspRoot(candidate))
|
|
2349
|
-
return
|
|
2350
|
-
let current =
|
|
2351
|
-
const fsRoot =
|
|
2626
|
+
return path6.resolve(candidate);
|
|
2627
|
+
let current = path6.dirname(path6.resolve(candidate));
|
|
2628
|
+
const fsRoot = path6.parse(current).root;
|
|
2352
2629
|
let nearestAllowed;
|
|
2353
2630
|
while (true) {
|
|
2354
2631
|
if (!await isExcludedLspRoot(current)) {
|
|
@@ -2360,7 +2637,7 @@ async function nearestNonExcludedFallbackRoot(candidate) {
|
|
|
2360
2637
|
}
|
|
2361
2638
|
if (current === fsRoot)
|
|
2362
2639
|
break;
|
|
2363
|
-
current =
|
|
2640
|
+
current = path6.dirname(current);
|
|
2364
2641
|
}
|
|
2365
2642
|
return nearestAllowed ?? fsRoot;
|
|
2366
2643
|
}
|
|
@@ -2401,7 +2678,7 @@ async function installEvidenceForLaunch(toolId, installed, attempt) {
|
|
|
2401
2678
|
const confirmedManagedPath = await findManagedToolBinary(toolId);
|
|
2402
2679
|
return {
|
|
2403
2680
|
...evidence,
|
|
2404
|
-
binary:
|
|
2681
|
+
binary: path6.basename(installed),
|
|
2405
2682
|
...confirmedManagedPath !== void 0 && pathsEqual(confirmedManagedPath, installed) && {
|
|
2406
2683
|
source: "managed-dir"
|
|
2407
2684
|
}
|
|
@@ -2454,7 +2731,7 @@ function markDirectLspCommandUnavailable(command) {
|
|
|
2454
2731
|
directLspCommandUnavailableUntil.set(command, Date.now() + DIRECT_LSP_NEGATIVE_TTL_MS);
|
|
2455
2732
|
directLspCommandSkipLoggedUntil.delete(command);
|
|
2456
2733
|
}
|
|
2457
|
-
var PI_LENS_BIN_DIR2 =
|
|
2734
|
+
var PI_LENS_BIN_DIR2 = path6.join(getGlobalPiLensDir(), "bin");
|
|
2458
2735
|
async function resolveAndLaunch(spec, allowInstall) {
|
|
2459
2736
|
const generation = lspLaunchAvailabilityGeneration.capture();
|
|
2460
2737
|
const toolLabel = spec.managedToolId ?? spec.candidates[spec.candidates.length - 1] ?? "unknown";
|
|
@@ -2519,7 +2796,7 @@ async function resolveAndLaunch(spec, allowInstall) {
|
|
|
2519
2796
|
producer: "lsp-launch",
|
|
2520
2797
|
classifiedBy: "probe",
|
|
2521
2798
|
evidence: {
|
|
2522
|
-
binary:
|
|
2799
|
+
binary: path6.basename(managedCandidate),
|
|
2523
2800
|
source: "managed-dir",
|
|
2524
2801
|
correctsLatchedRow: false
|
|
2525
2802
|
}
|
|
@@ -2812,7 +3089,7 @@ async function resolveAndLaunchTreeBinary(spec, allowInstall) {
|
|
|
2812
3089
|
return void 0;
|
|
2813
3090
|
}
|
|
2814
3091
|
const suffix = process.platform === "win32" ? ".exe" : "";
|
|
2815
|
-
const binPath =
|
|
3092
|
+
const binPath = path6.join(bundleDir, ...spec.binRelPath.split("/")) + suffix;
|
|
2816
3093
|
try {
|
|
2817
3094
|
const proc = await launchLSP(binPath, spec.args, {
|
|
2818
3095
|
cwd: spec.cwd,
|
|
@@ -2827,7 +3104,7 @@ async function resolveAndLaunchTreeBinary(spec, allowInstall) {
|
|
|
2827
3104
|
}
|
|
2828
3105
|
}
|
|
2829
3106
|
function nodeBinLocalCandidates(root, baseName) {
|
|
2830
|
-
const localBase =
|
|
3107
|
+
const localBase = path6.join(root, "node_modules", ".bin", baseName);
|
|
2831
3108
|
if (process.platform === "win32") {
|
|
2832
3109
|
return [`${localBase}.cmd`, `${localBase}.exe`];
|
|
2833
3110
|
}
|
|
@@ -2837,7 +3114,7 @@ function nodeBinCandidates(root, baseName) {
|
|
|
2837
3114
|
return [...nodeBinLocalCandidates(root, baseName), baseName];
|
|
2838
3115
|
}
|
|
2839
3116
|
function piAgentExtensionsRootKey(file) {
|
|
2840
|
-
const dirKey = normalizeEphemeralMapKey(
|
|
3117
|
+
const dirKey = normalizeEphemeralMapKey(path6.dirname(path6.resolve(file)));
|
|
2841
3118
|
const marker = "/.pi/agent/extensions";
|
|
2842
3119
|
const index = dirKey.indexOf(marker);
|
|
2843
3120
|
if (index === -1)
|
|
@@ -2845,26 +3122,26 @@ function piAgentExtensionsRootKey(file) {
|
|
|
2845
3122
|
return dirKey.slice(0, index + marker.length);
|
|
2846
3123
|
}
|
|
2847
3124
|
function IgnoreHomeRoot(primary) {
|
|
2848
|
-
const homeKey = normalizeEphemeralMapKey(
|
|
3125
|
+
const homeKey = normalizeEphemeralMapKey(path6.resolve(os7.homedir()));
|
|
2849
3126
|
return withRootMarkers(async (file) => {
|
|
2850
3127
|
const root = await primary(file);
|
|
2851
3128
|
if (!root)
|
|
2852
3129
|
return void 0;
|
|
2853
|
-
return normalizeEphemeralMapKey(
|
|
3130
|
+
return normalizeEphemeralMapKey(path6.resolve(root)) === homeKey ? void 0 : root;
|
|
2854
3131
|
}, primary.rootMarkers ?? []);
|
|
2855
3132
|
}
|
|
2856
3133
|
function rubyBinCandidates(baseName) {
|
|
2857
3134
|
const candidates = [];
|
|
2858
|
-
const home =
|
|
3135
|
+
const home = os7.homedir();
|
|
2859
3136
|
const isWin = process.platform === "win32";
|
|
2860
3137
|
const ext = isWin ? ".bat" : "";
|
|
2861
|
-
candidates.push(
|
|
2862
|
-
candidates.push(
|
|
3138
|
+
candidates.push(path6.join(home, ".local", "share", "mise", "installs", "ruby", "bin", `${baseName}${ext}`));
|
|
3139
|
+
candidates.push(path6.join(home, ".asdf", "installs", "ruby", "bin", `${baseName}${ext}`));
|
|
2863
3140
|
if (isWin) {
|
|
2864
|
-
const driveRoot =
|
|
3141
|
+
const driveRoot = path6.parse(home).root;
|
|
2865
3142
|
for (const entry of getRubyVersionDirNamesSync(driveRoot)) {
|
|
2866
|
-
candidates.push(
|
|
2867
|
-
candidates.push(
|
|
3143
|
+
candidates.push(path6.join(driveRoot, entry, "bin", `${baseName}.bat`));
|
|
3144
|
+
candidates.push(path6.join(driveRoot, entry, "bin", baseName));
|
|
2868
3145
|
}
|
|
2869
3146
|
}
|
|
2870
3147
|
return candidates;
|
|
@@ -2884,6 +3161,7 @@ function createInteractiveServer(spec) {
|
|
|
2884
3161
|
rootMarkers: spec.root.rootMarkers,
|
|
2885
3162
|
fallbackFor: spec.fallbackFor,
|
|
2886
3163
|
requiresProjectRoot: spec.requiresProjectRoot,
|
|
3164
|
+
executesProjectCode: spec.executesProjectCode,
|
|
2887
3165
|
availabilityKey: typeof spec.command === "string" && isSimpleCommand(spec.command) ? spec.command : void 0,
|
|
2888
3166
|
async spawn(root) {
|
|
2889
3167
|
const command = typeof spec.command === "function" ? spec.command(root) : spec.command;
|
|
@@ -2911,8 +3189,8 @@ function createInteractiveServer(spec) {
|
|
|
2911
3189
|
function PriorityRoot(markerGroups, excludePatterns, stopDir) {
|
|
2912
3190
|
const resolvers = markerGroups.map((markers) => NearestRoot(markers, excludePatterns, stopDir));
|
|
2913
3191
|
return withRootMarkers(async (file) => {
|
|
2914
|
-
for (const
|
|
2915
|
-
const root = await
|
|
3192
|
+
for (const resolve4 of resolvers) {
|
|
3193
|
+
const root = await resolve4(file);
|
|
2916
3194
|
if (root)
|
|
2917
3195
|
return root;
|
|
2918
3196
|
}
|
|
@@ -2920,7 +3198,7 @@ function PriorityRoot(markerGroups, excludePatterns, stopDir) {
|
|
|
2920
3198
|
}, markerGroups.flat());
|
|
2921
3199
|
}
|
|
2922
3200
|
var FileDirRoot = async (file) => {
|
|
2923
|
-
const candidate =
|
|
3201
|
+
const candidate = path6.resolve(path6.dirname(file));
|
|
2924
3202
|
return nearestNonExcludedFallbackRoot(candidate);
|
|
2925
3203
|
};
|
|
2926
3204
|
function RootWithFallback(primary, fallback = FileDirRoot) {
|
|
@@ -2942,16 +3220,16 @@ function markerProbeDir(dir, pattern) {
|
|
|
2942
3220
|
const normalized = toPosix(pattern);
|
|
2943
3221
|
const slash = normalized.lastIndexOf("/");
|
|
2944
3222
|
const parentPattern = slash >= 0 ? normalized.slice(0, slash) : "";
|
|
2945
|
-
return parentPattern ?
|
|
3223
|
+
return parentPattern ? path6.join(dir, ...parentPattern.split("/").filter(Boolean)) : dir;
|
|
2946
3224
|
}
|
|
2947
3225
|
async function markerExists(dir, pattern) {
|
|
2948
3226
|
if (!pattern.includes("*")) {
|
|
2949
3227
|
try {
|
|
2950
|
-
await stat(
|
|
3228
|
+
await stat(path6.join(dir, pattern));
|
|
2951
3229
|
return true;
|
|
2952
3230
|
} catch (err) {
|
|
2953
3231
|
if (isPermissionFsError(err)) {
|
|
2954
|
-
logSessionStart(`lsp root marker skipped: permission error stat ${
|
|
3232
|
+
logSessionStart(`lsp root marker skipped: permission error stat ${path6.join(dir, pattern)}`);
|
|
2955
3233
|
}
|
|
2956
3234
|
return false;
|
|
2957
3235
|
}
|
|
@@ -2987,7 +3265,7 @@ function NearestRoot(includePatterns, excludePatterns, stopDir) {
|
|
|
2987
3265
|
subdirPatterns.push(pattern);
|
|
2988
3266
|
}
|
|
2989
3267
|
return withRootMarkers(async (file) => {
|
|
2990
|
-
const startDir =
|
|
3268
|
+
const startDir = path6.resolve(path6.dirname(file));
|
|
2991
3269
|
const dirKey = normalizeMapKey(startDir);
|
|
2992
3270
|
const cached = cache.get(dirKey);
|
|
2993
3271
|
if (cached !== void 0 && Date.now() - cached.walkedAt < FRESHNESS_CADENCE_MS && await bounded(dirMtimesStillFreshAsync(cached.probedDirs), rootMtimeBound("lsp-root-memo-freshness")) === true)
|
|
@@ -2999,10 +3277,10 @@ function NearestRoot(includePatterns, excludePatterns, stopDir) {
|
|
|
2999
3277
|
const walkedAt = Date.now();
|
|
3000
3278
|
const promise = (async () => {
|
|
3001
3279
|
let currentDir = startDir;
|
|
3002
|
-
const fsRoot =
|
|
3003
|
-
const stop = stopDir ?
|
|
3280
|
+
const fsRoot = path6.parse(currentDir).root;
|
|
3281
|
+
const stop = stopDir ? path6.resolve(stopDir) : fsRoot;
|
|
3004
3282
|
while (true) {
|
|
3005
|
-
if (stop !== fsRoot && currentDir.startsWith(stop +
|
|
3283
|
+
if (stop !== fsRoot && currentDir.startsWith(stop + path6.sep) === false && currentDir !== stop) {
|
|
3006
3284
|
break;
|
|
3007
3285
|
}
|
|
3008
3286
|
const stepDirs = [
|
|
@@ -3020,19 +3298,19 @@ function NearestRoot(includePatterns, excludePatterns, stopDir) {
|
|
|
3020
3298
|
}
|
|
3021
3299
|
}
|
|
3022
3300
|
if (excluded) {
|
|
3023
|
-
currentDir =
|
|
3301
|
+
currentDir = path6.dirname(currentDir);
|
|
3024
3302
|
continue;
|
|
3025
3303
|
}
|
|
3026
3304
|
}
|
|
3027
3305
|
for (const pattern of includePatterns) {
|
|
3028
|
-
if (await markerExists(currentDir, pattern) && (pattern !== ".git" || currentDir !==
|
|
3306
|
+
if (await markerExists(currentDir, pattern) && (pattern !== ".git" || currentDir !== os7.tmpdir()) && !await isExcludedLspRoot(currentDir)) {
|
|
3029
3307
|
return enforceLspRootCeiling(currentDir, process.cwd(), file);
|
|
3030
3308
|
}
|
|
3031
3309
|
}
|
|
3032
3310
|
if (currentDir === stop || currentDir === fsRoot) {
|
|
3033
3311
|
break;
|
|
3034
3312
|
}
|
|
3035
|
-
currentDir =
|
|
3313
|
+
currentDir = path6.dirname(currentDir);
|
|
3036
3314
|
}
|
|
3037
3315
|
return void 0;
|
|
3038
3316
|
})();
|
|
@@ -3073,18 +3351,18 @@ async function findAncestorFile(startDir, ...relativeSegments) {
|
|
|
3073
3351
|
return findAncestorFileAmong(startDir, [relativeSegments]);
|
|
3074
3352
|
}
|
|
3075
3353
|
async function findAncestorFileAmong(startDir, candidateSegmentLists) {
|
|
3076
|
-
const
|
|
3077
|
-
let currentDir =
|
|
3354
|
+
const fs6 = await import("node:fs/promises");
|
|
3355
|
+
let currentDir = path6.resolve(startDir);
|
|
3078
3356
|
while (!isAtOrAboveHomeDir(currentDir)) {
|
|
3079
3357
|
for (const segments of candidateSegmentLists) {
|
|
3080
|
-
const candidate =
|
|
3358
|
+
const candidate = path6.join(currentDir, ...segments);
|
|
3081
3359
|
try {
|
|
3082
|
-
await
|
|
3360
|
+
await fs6.access(candidate);
|
|
3083
3361
|
return candidate;
|
|
3084
3362
|
} catch {
|
|
3085
3363
|
}
|
|
3086
3364
|
}
|
|
3087
|
-
const parent =
|
|
3365
|
+
const parent = path6.dirname(currentDir);
|
|
3088
3366
|
if (parent === currentDir)
|
|
3089
3367
|
break;
|
|
3090
3368
|
currentDir = parent;
|
|
@@ -3100,19 +3378,19 @@ function resetClassicTsRepairGuard() {
|
|
|
3100
3378
|
classicTsRepairState().attempted = false;
|
|
3101
3379
|
}
|
|
3102
3380
|
function typescriptDirsForTsc(tscPath) {
|
|
3103
|
-
const binDir =
|
|
3381
|
+
const binDir = path6.dirname(tscPath);
|
|
3104
3382
|
return [
|
|
3105
|
-
|
|
3106
|
-
|
|
3383
|
+
path6.join(binDir, "..", "typescript"),
|
|
3384
|
+
path6.join(binDir, "..", "..", "typescript")
|
|
3107
3385
|
];
|
|
3108
3386
|
}
|
|
3109
3387
|
async function typescriptVersionForTsc(tscPath) {
|
|
3110
|
-
if (!
|
|
3388
|
+
if (!path6.isAbsolute(tscPath))
|
|
3111
3389
|
return void 0;
|
|
3112
3390
|
for (const dir of typescriptDirsForTsc(tscPath)) {
|
|
3113
3391
|
let manifest;
|
|
3114
3392
|
try {
|
|
3115
|
-
manifest = await readFile(
|
|
3393
|
+
manifest = await readFile(path6.join(dir, "package.json"), "utf8");
|
|
3116
3394
|
} catch {
|
|
3117
3395
|
continue;
|
|
3118
3396
|
}
|
|
@@ -3134,25 +3412,45 @@ async function typescriptVersionForTsc(tscPath) {
|
|
|
3134
3412
|
}
|
|
3135
3413
|
return void 0;
|
|
3136
3414
|
}
|
|
3137
|
-
async function findTsserverPath(root, allowInstall) {
|
|
3138
|
-
const
|
|
3415
|
+
async function findTsserverPath(root, allowInstall, options) {
|
|
3416
|
+
const fs6 = await import("node:fs/promises");
|
|
3417
|
+
const projectRoots = await Promise.all([root, options?.sessionRoot ?? process.cwd(), process.cwd()].map((dir) => fs6.realpath(dir).catch(() => path6.resolve(dir))));
|
|
3418
|
+
const admitCandidate = async (candidate, projectSupplied) => {
|
|
3419
|
+
try {
|
|
3420
|
+
const real = await fs6.realpath(candidate);
|
|
3421
|
+
if (path6.basename(real) !== "tsserver.js" || !(await fs6.stat(real)).isFile())
|
|
3422
|
+
return void 0;
|
|
3423
|
+
const manifest = JSON.parse(await fs6.readFile(path6.join(path6.dirname(real), "..", "package.json"), "utf8"));
|
|
3424
|
+
if (typeof manifest?.version !== "string" || !manifest.version)
|
|
3425
|
+
return void 0;
|
|
3426
|
+
return admitProjectSuppliedTsserver(real, options?.sessionRoot ?? process.cwd(), projectSupplied || projectRoots.some((dir) => isUnderDir(real, dir)), options?.projectCodeAllowed);
|
|
3427
|
+
} catch {
|
|
3428
|
+
return void 0;
|
|
3429
|
+
}
|
|
3430
|
+
};
|
|
3139
3431
|
const ancestorHit = await findAncestorFile(root, "node_modules", "typescript", "lib", "tsserver.js");
|
|
3140
|
-
if (ancestorHit)
|
|
3141
|
-
|
|
3142
|
-
|
|
3432
|
+
if (ancestorHit) {
|
|
3433
|
+
const admittedAncestor = await admitCandidate(ancestorHit, true);
|
|
3434
|
+
if (admittedAncestor)
|
|
3435
|
+
return admittedAncestor;
|
|
3436
|
+
}
|
|
3437
|
+
const cwdCandidate = path6.join(process.cwd(), "node_modules", "typescript", "lib", "tsserver.js");
|
|
3143
3438
|
try {
|
|
3144
|
-
await
|
|
3145
|
-
|
|
3439
|
+
await fs6.access(cwdCandidate);
|
|
3440
|
+
const admittedCwd = await admitCandidate(cwdCandidate, false);
|
|
3441
|
+
if (admittedCwd)
|
|
3442
|
+
return admittedCwd;
|
|
3146
3443
|
} catch {
|
|
3147
3444
|
}
|
|
3148
3445
|
const tsserverForTsc = async (tscPath) => {
|
|
3149
|
-
if (!tscPath)
|
|
3446
|
+
if (!tscPath || !path6.isAbsolute(tscPath))
|
|
3150
3447
|
return void 0;
|
|
3151
3448
|
for (const dir of typescriptDirsForTsc(tscPath)) {
|
|
3152
|
-
const candidate =
|
|
3449
|
+
const candidate = path6.join(dir, "lib", "tsserver.js");
|
|
3153
3450
|
try {
|
|
3154
|
-
await
|
|
3155
|
-
|
|
3451
|
+
const admitted = await admitCandidate(candidate, false);
|
|
3452
|
+
if (admitted)
|
|
3453
|
+
return admitted;
|
|
3156
3454
|
} catch {
|
|
3157
3455
|
}
|
|
3158
3456
|
}
|
|
@@ -3178,10 +3476,10 @@ async function findTsserverPath(root, allowInstall) {
|
|
|
3178
3476
|
return tsserverForTsc(repairedTsc);
|
|
3179
3477
|
}
|
|
3180
3478
|
async function findNativeTypeScriptLsp(root) {
|
|
3181
|
-
let currentDir =
|
|
3479
|
+
let currentDir = path6.resolve(root);
|
|
3182
3480
|
while (!isAtOrAboveHomeDir(currentDir)) {
|
|
3183
|
-
const typescriptDir =
|
|
3184
|
-
const packageJsonPath =
|
|
3481
|
+
const typescriptDir = path6.join(currentDir, "node_modules", "typescript");
|
|
3482
|
+
const packageJsonPath = path6.join(typescriptDir, "package.json");
|
|
3185
3483
|
let packageJsonText;
|
|
3186
3484
|
try {
|
|
3187
3485
|
packageJsonText = await readFile(packageJsonPath, "utf8");
|
|
@@ -3195,7 +3493,7 @@ async function findNativeTypeScriptLsp(root) {
|
|
|
3195
3493
|
return void 0;
|
|
3196
3494
|
} catch {
|
|
3197
3495
|
}
|
|
3198
|
-
const parent =
|
|
3496
|
+
const parent = path6.dirname(currentDir);
|
|
3199
3497
|
if (parent === currentDir)
|
|
3200
3498
|
return void 0;
|
|
3201
3499
|
currentDir = parent;
|
|
@@ -3215,7 +3513,7 @@ async function findNativeTypeScriptLsp(root) {
|
|
|
3215
3513
|
const major = /^\d+$/.test(majorText) ? Number(majorText) : Number.NaN;
|
|
3216
3514
|
if (!Number.isFinite(major) || major < 7)
|
|
3217
3515
|
return void 0;
|
|
3218
|
-
const localTsc =
|
|
3516
|
+
const localTsc = path6.join(currentDir, "node_modules", ".bin", "tsc");
|
|
3219
3517
|
const candidates = process.platform === "win32" ? [`${localTsc}.cmd`, `${localTsc}.exe`, localTsc] : [localTsc];
|
|
3220
3518
|
for (const command of candidates) {
|
|
3221
3519
|
try {
|
|
@@ -3229,29 +3527,29 @@ async function findNativeTypeScriptLsp(root) {
|
|
|
3229
3527
|
return void 0;
|
|
3230
3528
|
}
|
|
3231
3529
|
function dotnetToolCandidates(tool) {
|
|
3232
|
-
const home =
|
|
3530
|
+
const home = os7.homedir();
|
|
3233
3531
|
return [
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3532
|
+
path6.join(PI_LENS_BIN_DIR2, `${tool}.exe`),
|
|
3533
|
+
path6.join(PI_LENS_BIN_DIR2, tool),
|
|
3534
|
+
path6.join(home, ".dotnet", "tools", `${tool}.exe`),
|
|
3535
|
+
path6.join(home, ".dotnet", "tools", tool),
|
|
3238
3536
|
tool
|
|
3239
3537
|
].filter(Boolean);
|
|
3240
3538
|
}
|
|
3241
3539
|
function binExeVariants(dir, tool) {
|
|
3242
|
-
return process.platform === "win32" ? [
|
|
3540
|
+
return process.platform === "win32" ? [path6.join(dir, `${tool}.exe`), path6.join(dir, tool)] : [path6.join(dir, tool)];
|
|
3243
3541
|
}
|
|
3244
3542
|
function goBinCandidates(tool) {
|
|
3245
|
-
const gopath = process.env.GOPATH?.split(
|
|
3246
|
-
return [tool, ...binExeVariants(
|
|
3543
|
+
const gopath = process.env.GOPATH?.split(path6.delimiter)[0] || path6.join(os7.homedir(), "go");
|
|
3544
|
+
return [tool, ...binExeVariants(path6.join(gopath, "bin"), tool)];
|
|
3247
3545
|
}
|
|
3248
3546
|
function cargoBinCandidates(tool) {
|
|
3249
|
-
const cargoHome = process.env.CARGO_HOME ||
|
|
3250
|
-
return [tool, ...binExeVariants(
|
|
3547
|
+
const cargoHome = process.env.CARGO_HOME || path6.join(os7.homedir(), ".cargo");
|
|
3548
|
+
return [tool, ...binExeVariants(path6.join(cargoHome, "bin"), tool)];
|
|
3251
3549
|
}
|
|
3252
3550
|
async function tryGemInstall(gem) {
|
|
3253
|
-
const { join:
|
|
3254
|
-
const binDir =
|
|
3551
|
+
const { join: join4 } = await import("node:path");
|
|
3552
|
+
const binDir = join4(getGlobalPiLensDir(), "bin");
|
|
3255
3553
|
const { mkdir } = await import("node:fs/promises");
|
|
3256
3554
|
await mkdir(binDir, { recursive: true });
|
|
3257
3555
|
const result = await safeSpawnAsync("gem", ["install", gem, "--bindir", binDir, "--no-document"], { timeout: 18e4, ignoreAmbientSignal: true });
|
|
@@ -3285,7 +3583,7 @@ var TS_TOOLING_MARKERS = [
|
|
|
3285
3583
|
];
|
|
3286
3584
|
var TS_FAMILY_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts"]);
|
|
3287
3585
|
function isTsFamilyFile(file) {
|
|
3288
|
-
return TS_FAMILY_EXTENSIONS.has(
|
|
3586
|
+
return TS_FAMILY_EXTENSIONS.has(path6.extname(file).toLowerCase());
|
|
3289
3587
|
}
|
|
3290
3588
|
function tsConfigMarkersForFile(file) {
|
|
3291
3589
|
return isTsFamilyFile(file) ? ["tsconfig.json"] : TS_CONFIG_MARKERS;
|
|
@@ -3306,40 +3604,40 @@ async function findTypeScriptProjectRoot(file) {
|
|
|
3306
3604
|
return isSameOrWithin(toolingRoot, configRoot) ? configRoot : toolingRoot;
|
|
3307
3605
|
}
|
|
3308
3606
|
async function findExtensionBoundedRoot(file, extensionRootKey) {
|
|
3309
|
-
const startDir =
|
|
3607
|
+
const startDir = path6.resolve(path6.dirname(file));
|
|
3310
3608
|
let currentDir = startDir;
|
|
3311
3609
|
const configMarkers = tsConfigMarkersForFile(file);
|
|
3312
3610
|
while (true) {
|
|
3313
3611
|
for (const pattern of configMarkers) {
|
|
3314
3612
|
try {
|
|
3315
|
-
await stat(
|
|
3613
|
+
await stat(path6.join(currentDir, pattern));
|
|
3316
3614
|
return currentDir;
|
|
3317
3615
|
} catch {
|
|
3318
3616
|
}
|
|
3319
3617
|
}
|
|
3320
3618
|
for (const pattern of TS_TOOLING_MARKERS) {
|
|
3321
3619
|
try {
|
|
3322
|
-
await stat(
|
|
3620
|
+
await stat(path6.join(currentDir, pattern));
|
|
3323
3621
|
return currentDir;
|
|
3324
3622
|
} catch {
|
|
3325
3623
|
}
|
|
3326
3624
|
}
|
|
3327
|
-
const currentKey = normalizeEphemeralMapKey(
|
|
3625
|
+
const currentKey = normalizeEphemeralMapKey(path6.resolve(currentDir));
|
|
3328
3626
|
if (currentKey === extensionRootKey)
|
|
3329
3627
|
return void 0;
|
|
3330
|
-
const parent =
|
|
3628
|
+
const parent = path6.dirname(currentDir);
|
|
3331
3629
|
if (parent === currentDir)
|
|
3332
3630
|
return void 0;
|
|
3333
3631
|
currentDir = parent;
|
|
3334
3632
|
}
|
|
3335
3633
|
}
|
|
3336
3634
|
async function hasAgentLevelProjectMarker(extensionRootKey) {
|
|
3337
|
-
const agentDir =
|
|
3635
|
+
const agentDir = path6.dirname(extensionRootKey);
|
|
3338
3636
|
if (!agentDir || agentDir === extensionRootKey)
|
|
3339
3637
|
return false;
|
|
3340
3638
|
for (const pattern of [...TS_CONFIG_MARKERS, ...TS_TOOLING_MARKERS]) {
|
|
3341
3639
|
try {
|
|
3342
|
-
await stat(
|
|
3640
|
+
await stat(path6.join(agentDir, pattern));
|
|
3343
3641
|
return true;
|
|
3344
3642
|
} catch {
|
|
3345
3643
|
}
|
|
@@ -3367,14 +3665,14 @@ var TypeScriptServer = {
|
|
|
3367
3665
|
idleEviction: "transparent",
|
|
3368
3666
|
role: "language",
|
|
3369
3667
|
name: "TypeScript Language Server",
|
|
3668
|
+
projectLocalCommand: "typescript-language-server",
|
|
3370
3669
|
extensions: JS_TS_LSP_EXTENSIONS,
|
|
3371
3670
|
autoPropagateDiagnostics: true,
|
|
3372
3671
|
root: TypeScriptRoot,
|
|
3373
3672
|
rootMarkers: TypeScriptRoot.rootMarkers,
|
|
3374
3673
|
async spawn(root, options) {
|
|
3375
|
-
const fs5 = await import("node:fs/promises");
|
|
3376
3674
|
const nativeLsp = await findNativeTypeScriptLsp(root);
|
|
3377
|
-
if (nativeLsp) {
|
|
3675
|
+
if (nativeLsp && admitProjectSuppliedTsserver(nativeLsp.command, root, true, options?.projectCodeAllowed)) {
|
|
3378
3676
|
const env2 = await getToolEnvironment();
|
|
3379
3677
|
logSessionStart(`lsp typescript-native: version=${nativeLsp.version} command=${nativeLsp.command}`);
|
|
3380
3678
|
const proc2 = await launchLSP(nativeLsp.command, ["--lsp", "--stdio"], {
|
|
@@ -3398,14 +3696,10 @@ var TypeScriptServer = {
|
|
|
3398
3696
|
return void 0;
|
|
3399
3697
|
}
|
|
3400
3698
|
}
|
|
3401
|
-
|
|
3699
|
+
const tsserverPath = await findTsserverPath(root, options?.allowInstall, options);
|
|
3402
3700
|
if (!tsserverPath) {
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
await fs5.access(localCandidate);
|
|
3406
|
-
tsserverPath = localCandidate;
|
|
3407
|
-
} catch {
|
|
3408
|
-
}
|
|
3701
|
+
admitProjectSuppliedTsserver(void 0, root, true, options?.projectCodeAllowed);
|
|
3702
|
+
return void 0;
|
|
3409
3703
|
}
|
|
3410
3704
|
if (tsserverPath)
|
|
3411
3705
|
source = "managed";
|
|
@@ -3521,13 +3815,13 @@ var PythonServer = {
|
|
|
3521
3815
|
if (!pyrightPath)
|
|
3522
3816
|
return void 0;
|
|
3523
3817
|
source = "managed";
|
|
3524
|
-
const binDir =
|
|
3818
|
+
const binDir = path6.dirname(pyrightPath);
|
|
3525
3819
|
const isWindows2 = process.platform === "win32";
|
|
3526
3820
|
const managedCandidates = isWindows2 ? [
|
|
3527
|
-
|
|
3528
|
-
|
|
3821
|
+
path6.join(binDir, "pyright-langserver.cmd"),
|
|
3822
|
+
path6.join(binDir, "pyright-langserver"),
|
|
3529
3823
|
"pyright-langserver"
|
|
3530
|
-
] : [
|
|
3824
|
+
] : [path6.join(binDir, "pyright-langserver"), "pyright-langserver"];
|
|
3531
3825
|
const resolved = await resolveAndLaunch({ candidates: managedCandidates, args: ["--stdio"], cwd: root, env }, false);
|
|
3532
3826
|
if (!resolved)
|
|
3533
3827
|
return void 0;
|
|
@@ -3596,7 +3890,7 @@ var GoServer = {
|
|
|
3596
3890
|
}
|
|
3597
3891
|
};
|
|
3598
3892
|
function cargoWorkspaceDeclaresMember(workspaceContent, parentDir, childDir) {
|
|
3599
|
-
const relativePath =
|
|
3893
|
+
const relativePath = path6.relative(parentDir, childDir).split(path6.sep).join("/");
|
|
3600
3894
|
if (relativePath === "" || relativePath.startsWith(".."))
|
|
3601
3895
|
return false;
|
|
3602
3896
|
const matches = (pattern) => matchesWorkspaceMemberPattern(pattern, relativePath, CARGO_WORKSPACE_MEMBER_DIALECT, () => recordDegradationOnce({
|
|
@@ -3610,7 +3904,7 @@ function cargoWorkspaceDeclaresMember(workspaceContent, parentDir, childDir) {
|
|
|
3610
3904
|
return readCargoWorkspaceMembers(workspaceContent).some(matches);
|
|
3611
3905
|
}
|
|
3612
3906
|
function sessionHoistCeiling(sessionCwd, file) {
|
|
3613
|
-
return isSameOrWithin(
|
|
3907
|
+
return isSameOrWithin(path6.resolve(sessionCwd), path6.resolve(file)) ? path6.resolve(sessionCwd) : void 0;
|
|
3614
3908
|
}
|
|
3615
3909
|
function RustWorkspaceRoot() {
|
|
3616
3910
|
const crateRoot = createRootDetector(["Cargo.toml", "Cargo.lock"]);
|
|
@@ -3621,14 +3915,14 @@ function RustWorkspaceRoot() {
|
|
|
3621
3915
|
const sessionCwd = process.cwd();
|
|
3622
3916
|
const stop = sessionHoistCeiling(sessionCwd, file);
|
|
3623
3917
|
let current = root;
|
|
3624
|
-
const fsRoot =
|
|
3918
|
+
const fsRoot = path6.parse(current).root;
|
|
3625
3919
|
while (true) {
|
|
3626
3920
|
if (stop !== void 0 && current === stop)
|
|
3627
3921
|
break;
|
|
3628
|
-
const parent =
|
|
3922
|
+
const parent = path6.dirname(current);
|
|
3629
3923
|
if (parent === current || parent === fsRoot)
|
|
3630
3924
|
break;
|
|
3631
|
-
const parentCargoPath =
|
|
3925
|
+
const parentCargoPath = path6.join(parent, "Cargo.toml");
|
|
3632
3926
|
const parentCargoContent = await readTextFileOrUndefined(parentCargoPath);
|
|
3633
3927
|
if (parentCargoContent !== void 0 && hasCargoWorkspaceTable(parentCargoContent)) {
|
|
3634
3928
|
if (cargoWorkspaceDeclaresMember(parentCargoContent, parent, root)) {
|
|
@@ -3656,9 +3950,9 @@ async function declaresMavenModule(parentDir, parentPomPath, childDir) {
|
|
|
3656
3950
|
const modulesBlock = content.match(/<modules>([\s\S]*?)<\/modules>/);
|
|
3657
3951
|
if (!modulesBlock)
|
|
3658
3952
|
return false;
|
|
3659
|
-
const resolvedChild =
|
|
3953
|
+
const resolvedChild = path6.resolve(childDir);
|
|
3660
3954
|
for (const match of modulesBlock[1].matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)) {
|
|
3661
|
-
if (pathsEqual(
|
|
3955
|
+
if (pathsEqual(path6.resolve(parentDir, match[1]), resolvedChild))
|
|
3662
3956
|
return true;
|
|
3663
3957
|
}
|
|
3664
3958
|
return false;
|
|
@@ -3682,15 +3976,15 @@ function JavaWorkspaceRoot() {
|
|
|
3682
3976
|
const stop = sessionHoistCeiling(sessionCwd, file);
|
|
3683
3977
|
let current = root;
|
|
3684
3978
|
let lastHop = root;
|
|
3685
|
-
const fsRoot =
|
|
3979
|
+
const fsRoot = path6.parse(current).root;
|
|
3686
3980
|
while (true) {
|
|
3687
3981
|
if (stop !== void 0 && current === stop)
|
|
3688
3982
|
break;
|
|
3689
|
-
const parent =
|
|
3983
|
+
const parent = path6.dirname(current);
|
|
3690
3984
|
if (parent === current || parent === fsRoot)
|
|
3691
3985
|
break;
|
|
3692
3986
|
if (await markerExists(parent, "pom.xml")) {
|
|
3693
|
-
const parentPom =
|
|
3987
|
+
const parentPom = path6.join(parent, "pom.xml");
|
|
3694
3988
|
if (!await declaresMavenModule(parent, parentPom, lastHop))
|
|
3695
3989
|
break;
|
|
3696
3990
|
current = parent;
|
|
@@ -3709,6 +4003,7 @@ var RustServer = {
|
|
|
3709
4003
|
// Measured (#3750): rust-analyzer answers an empty result for a detached file.
|
|
3710
4004
|
requiresProjectRoot: true,
|
|
3711
4005
|
name: "rust-analyzer",
|
|
4006
|
+
executesProjectCode: true,
|
|
3712
4007
|
extensions: KIND_EXTENSIONS["rust"],
|
|
3713
4008
|
// No FileDirRoot fallback (#201): rust-analyzer is a heavy workspace server
|
|
3714
4009
|
// that is useless without a Cargo manifest. With the fallback, every .rs file
|
|
@@ -3742,6 +4037,7 @@ var RubyServer = {
|
|
|
3742
4037
|
idleEviction: "unmeasured",
|
|
3743
4038
|
role: "language",
|
|
3744
4039
|
name: "Ruby LSP",
|
|
4040
|
+
executesProjectCode: true,
|
|
3745
4041
|
extensions: KIND_EXTENSIONS["ruby"],
|
|
3746
4042
|
root: RootWithFallback(PriorityRoot([["Gemfile", ".ruby-version"], [".git"]])),
|
|
3747
4043
|
// Ruby LSP may need extra time to finish composed-bundle setup before it can
|
|
@@ -3794,17 +4090,17 @@ var PHPServer = {
|
|
|
3794
4090
|
return {
|
|
3795
4091
|
...result,
|
|
3796
4092
|
initialization: {
|
|
3797
|
-
storagePath:
|
|
4093
|
+
storagePath: path6.join(getGlobalPiLensDir(), "intelephense")
|
|
3798
4094
|
}
|
|
3799
4095
|
};
|
|
3800
4096
|
}
|
|
3801
4097
|
};
|
|
3802
4098
|
function buildPsesArgs(bundleDir) {
|
|
3803
|
-
const script =
|
|
3804
|
-
const sessionDir =
|
|
4099
|
+
const script = path6.join(bundleDir, "PowerShellEditorServices", "Start-EditorServices.ps1");
|
|
4100
|
+
const sessionDir = path6.join(getGlobalPiLensDir(), "pses", `${process.pid}-${Date.now()}`);
|
|
3805
4101
|
mkdirSync2(sessionDir, { recursive: true });
|
|
3806
|
-
const logPath =
|
|
3807
|
-
const sessionDetailsPath =
|
|
4102
|
+
const logPath = path6.join(sessionDir, "pses.log");
|
|
4103
|
+
const sessionDetailsPath = path6.join(sessionDir, "session.json");
|
|
3808
4104
|
return [
|
|
3809
4105
|
"-NoLogo",
|
|
3810
4106
|
"-NoProfile",
|
|
@@ -3838,6 +4134,7 @@ var PowerShellServer = {
|
|
|
3838
4134
|
idleEviction: "unmeasured",
|
|
3839
4135
|
role: "language",
|
|
3840
4136
|
name: "PowerShell Editor Services",
|
|
4137
|
+
executesProjectCode: true,
|
|
3841
4138
|
extensions: KIND_EXTENSIONS["powershell"],
|
|
3842
4139
|
// Index at the workspace (script modules reference siblings); fall back to the
|
|
3843
4140
|
// file dir.
|
|
@@ -3858,6 +4155,7 @@ var CSharpServer = {
|
|
|
3858
4155
|
// Documented (#3750): csharp-ls needs a solution or project.
|
|
3859
4156
|
requiresProjectRoot: true,
|
|
3860
4157
|
name: "csharp-ls",
|
|
4158
|
+
executesProjectCode: true,
|
|
3861
4159
|
extensions: KIND_EXTENSIONS["csharp"],
|
|
3862
4160
|
// No FileDirRoot fallback (#201): csharp-ls is a workspace server and should
|
|
3863
4161
|
// not spawn once per source directory before a .sln/.csproj exists. Glob root
|
|
@@ -3881,6 +4179,7 @@ var CSharpServer = {
|
|
|
3881
4179
|
var OmniSharpServer = createInteractiveServer({
|
|
3882
4180
|
id: "omnisharp",
|
|
3883
4181
|
name: "OmniSharp",
|
|
4182
|
+
executesProjectCode: true,
|
|
3884
4183
|
// Documented (#3750): OmniSharp needs a solution or project.
|
|
3885
4184
|
requiresProjectRoot: true,
|
|
3886
4185
|
fallbackFor: "csharp",
|
|
@@ -3897,6 +4196,7 @@ var FSharpServer = {
|
|
|
3897
4196
|
// Documented (#3750): FSAutocomplete needs a project.
|
|
3898
4197
|
requiresProjectRoot: true,
|
|
3899
4198
|
name: "FSAutocomplete",
|
|
4199
|
+
executesProjectCode: true,
|
|
3900
4200
|
extensions: KIND_EXTENSIONS["fsharp"],
|
|
3901
4201
|
root: createRootDetector([...DOTNET_FSHARP_ROOT_MARKERS]),
|
|
3902
4202
|
async spawn(root, options) {
|
|
@@ -3916,6 +4216,7 @@ var FSharpServer = {
|
|
|
3916
4216
|
var JavaServer = createInteractiveServer({
|
|
3917
4217
|
id: "java",
|
|
3918
4218
|
name: "JDT Language Server",
|
|
4219
|
+
executesProjectCode: true,
|
|
3919
4220
|
extensions: KIND_EXTENSIONS["java"],
|
|
3920
4221
|
root: RootWithFallback(JavaWorkspaceRoot()),
|
|
3921
4222
|
language: "java",
|
|
@@ -3928,6 +4229,7 @@ var KotlinServer = {
|
|
|
3928
4229
|
idleEviction: "unmeasured",
|
|
3929
4230
|
role: "language",
|
|
3930
4231
|
name: "Kotlin Language Server",
|
|
4232
|
+
executesProjectCode: true,
|
|
3931
4233
|
extensions: KIND_EXTENSIONS["kotlin"],
|
|
3932
4234
|
root: RootWithFallback(createRootDetector(["build.gradle.kts", "build.gradle", "pom.xml"])),
|
|
3933
4235
|
async spawn(root, options) {
|
|
@@ -3943,9 +4245,26 @@ var KotlinServer = {
|
|
|
3943
4245
|
}, options?.allowInstall);
|
|
3944
4246
|
}
|
|
3945
4247
|
};
|
|
4248
|
+
var LeanServer = createInteractiveServer({
|
|
4249
|
+
id: "lean",
|
|
4250
|
+
name: "Lean 4 Language Server",
|
|
4251
|
+
extensions: KIND_EXTENSIONS.lean,
|
|
4252
|
+
root: RootWithFallback(createRootDetector([...LEAN_ROOT_MARKERS])),
|
|
4253
|
+
language: "lean",
|
|
4254
|
+
// Documented (#3750): `lake serve` analyses a file only when a Lake project
|
|
4255
|
+
// roots it; a root-fallback empty answer is unconfirmed, not clean.
|
|
4256
|
+
requiresProjectRoot: true,
|
|
4257
|
+
// `lake serve` loads and interprets the project's `lakefile.lean` and its
|
|
4258
|
+
// imported build scripts, so it executes project-owned code: refuse it until
|
|
4259
|
+
// the host grants project trust (#4269).
|
|
4260
|
+
executesProjectCode: true,
|
|
4261
|
+
command: "lake",
|
|
4262
|
+
args: ["serve"]
|
|
4263
|
+
});
|
|
3946
4264
|
var SwiftServer = createInteractiveServer({
|
|
3947
4265
|
id: "swift",
|
|
3948
4266
|
name: "SourceKit-LSP",
|
|
4267
|
+
executesProjectCode: true,
|
|
3949
4268
|
extensions: KIND_EXTENSIONS["swift"],
|
|
3950
4269
|
root: createRootDetector(["Package.swift"]),
|
|
3951
4270
|
language: "swift",
|
|
@@ -3953,6 +4272,7 @@ var SwiftServer = createInteractiveServer({
|
|
|
3953
4272
|
});
|
|
3954
4273
|
var DartServer = createInteractiveServer({
|
|
3955
4274
|
id: "dart",
|
|
4275
|
+
executesProjectCode: true,
|
|
3956
4276
|
name: "Dart Analysis Server",
|
|
3957
4277
|
extensions: KIND_EXTENSIONS["dart"],
|
|
3958
4278
|
root: RootWithFallback(createRootDetector(["pubspec.yaml"])),
|
|
@@ -4006,6 +4326,7 @@ var CppServer = createTreeBinaryServer({
|
|
|
4006
4326
|
});
|
|
4007
4327
|
var ZigServer = {
|
|
4008
4328
|
id: "zig",
|
|
4329
|
+
executesProjectCode: true,
|
|
4009
4330
|
idleEviction: "unmeasured",
|
|
4010
4331
|
role: "language",
|
|
4011
4332
|
name: "ZLS",
|
|
@@ -4023,6 +4344,7 @@ var ZigServer = {
|
|
|
4023
4344
|
var HaskellServer = createInteractiveServer({
|
|
4024
4345
|
id: "haskell",
|
|
4025
4346
|
name: "Haskell Language Server",
|
|
4347
|
+
executesProjectCode: true,
|
|
4026
4348
|
extensions: KIND_EXTENSIONS["haskell"],
|
|
4027
4349
|
root: createRootDetector(["stack.yaml", "cabal.project", "*.cabal"]),
|
|
4028
4350
|
language: "haskell",
|
|
@@ -4032,6 +4354,7 @@ var HaskellServer = createInteractiveServer({
|
|
|
4032
4354
|
var ElixirServer = createInteractiveServer({
|
|
4033
4355
|
id: "elixir",
|
|
4034
4356
|
name: "ElixirLS",
|
|
4357
|
+
executesProjectCode: true,
|
|
4035
4358
|
extensions: KIND_EXTENSIONS["elixir"],
|
|
4036
4359
|
root: RootWithFallback(createRootDetector(["mix.exs"])),
|
|
4037
4360
|
language: "elixir",
|
|
@@ -4042,6 +4365,7 @@ var ElixirExpertServer = {
|
|
|
4042
4365
|
idleEviction: "unmeasured",
|
|
4043
4366
|
role: "language",
|
|
4044
4367
|
name: "Expert",
|
|
4368
|
+
executesProjectCode: true,
|
|
4045
4369
|
fallbackFor: "elixir",
|
|
4046
4370
|
extensions: KIND_EXTENSIONS["elixir"],
|
|
4047
4371
|
root: RootWithFallback(createRootDetector(["mix.exs"])),
|
|
@@ -4074,6 +4398,7 @@ var GleamServer = {
|
|
|
4074
4398
|
};
|
|
4075
4399
|
var TinymistServer = {
|
|
4076
4400
|
id: "tinymist",
|
|
4401
|
+
executesProjectCode: true,
|
|
4077
4402
|
idleEviction: "unmeasured",
|
|
4078
4403
|
role: "language",
|
|
4079
4404
|
name: "Tinymist",
|
|
@@ -4110,6 +4435,7 @@ var MarksmanServer = {
|
|
|
4110
4435
|
};
|
|
4111
4436
|
var OCamlServer = createInteractiveServer({
|
|
4112
4437
|
id: "ocaml",
|
|
4438
|
+
executesProjectCode: true,
|
|
4113
4439
|
name: "ocamllsp",
|
|
4114
4440
|
extensions: KIND_EXTENSIONS["ocaml"],
|
|
4115
4441
|
root: createRootDetector(["dune-project", "opam"]),
|
|
@@ -4118,6 +4444,7 @@ var OCamlServer = createInteractiveServer({
|
|
|
4118
4444
|
});
|
|
4119
4445
|
var ClojureServer = {
|
|
4120
4446
|
id: "clojure",
|
|
4447
|
+
executesProjectCode: true,
|
|
4121
4448
|
idleEviction: "transparent",
|
|
4122
4449
|
role: "language",
|
|
4123
4450
|
name: "Clojure LSP",
|
|
@@ -4150,6 +4477,7 @@ var CueServer = {
|
|
|
4150
4477
|
};
|
|
4151
4478
|
var TerraformServer = {
|
|
4152
4479
|
id: "terraform",
|
|
4480
|
+
executesProjectCode: true,
|
|
4153
4481
|
idleEviction: "unmeasured",
|
|
4154
4482
|
role: "language",
|
|
4155
4483
|
name: "Terraform LSP",
|
|
@@ -4166,6 +4494,7 @@ var TerraformServer = {
|
|
|
4166
4494
|
};
|
|
4167
4495
|
var NixServer = createInteractiveServer({
|
|
4168
4496
|
id: "nix",
|
|
4497
|
+
executesProjectCode: true,
|
|
4169
4498
|
name: "nixd",
|
|
4170
4499
|
extensions: KIND_EXTENSIONS["nix"],
|
|
4171
4500
|
root: createRootDetector(["flake.nix"]),
|
|
@@ -4234,6 +4563,7 @@ var FishServer = {
|
|
|
4234
4563
|
};
|
|
4235
4564
|
var CMakeServer = {
|
|
4236
4565
|
id: "cmake",
|
|
4566
|
+
executesProjectCode: true,
|
|
4237
4567
|
idleEviction: "unmeasured",
|
|
4238
4568
|
role: "language",
|
|
4239
4569
|
name: "CMake Language Server",
|
|
@@ -4404,6 +4734,7 @@ var PrismaServer = {
|
|
|
4404
4734
|
};
|
|
4405
4735
|
var VueServer = {
|
|
4406
4736
|
id: "vue",
|
|
4737
|
+
executesProjectCode: true,
|
|
4407
4738
|
idleEviction: "unmeasured",
|
|
4408
4739
|
role: "language",
|
|
4409
4740
|
name: "Vue Language Server",
|
|
@@ -4426,9 +4757,9 @@ var VueServer = {
|
|
|
4426
4757
|
clientWaitTimeoutMs: 3e4,
|
|
4427
4758
|
initializeTimeoutMs: 3e4,
|
|
4428
4759
|
async spawn(root, options) {
|
|
4429
|
-
const tsserverPath = await findTsserverPath(root, options?.allowInstall);
|
|
4430
|
-
const hasPackageJson = existsSync3(
|
|
4431
|
-
const hasNodeModules = existsSync3(
|
|
4760
|
+
const tsserverPath = await findTsserverPath(root, options?.allowInstall, options);
|
|
4761
|
+
const hasPackageJson = existsSync3(path6.join(root, "package.json"));
|
|
4762
|
+
const hasNodeModules = existsSync3(path6.join(root, "node_modules"));
|
|
4432
4763
|
if (hasPackageJson && !hasNodeModules) {
|
|
4433
4764
|
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
4765
|
}
|
|
@@ -4443,12 +4774,13 @@ var VueServer = {
|
|
|
4443
4774
|
return {
|
|
4444
4775
|
process: proc.process,
|
|
4445
4776
|
source: proc.source,
|
|
4446
|
-
initialization: tsserverPath ? { typescript: { tsdk:
|
|
4777
|
+
initialization: tsserverPath ? { typescript: { tsdk: path6.dirname(tsserverPath) } } : void 0
|
|
4447
4778
|
};
|
|
4448
4779
|
}
|
|
4449
4780
|
};
|
|
4450
4781
|
var SvelteServer = {
|
|
4451
4782
|
id: "svelte",
|
|
4783
|
+
executesProjectCode: true,
|
|
4452
4784
|
idleEviction: "unmeasured",
|
|
4453
4785
|
role: "language",
|
|
4454
4786
|
name: "Svelte Language Server",
|
|
@@ -4469,7 +4801,7 @@ var SvelteServer = {
|
|
|
4469
4801
|
clientWaitTimeoutMs: 2e4,
|
|
4470
4802
|
initializeTimeoutMs: 2e4,
|
|
4471
4803
|
async spawn(root, options) {
|
|
4472
|
-
const tsserverPath = await findTsserverPath(root, options?.allowInstall);
|
|
4804
|
+
const tsserverPath = await findTsserverPath(root, options?.allowInstall, options);
|
|
4473
4805
|
const proc = await resolveAndLaunch({
|
|
4474
4806
|
candidates: [
|
|
4475
4807
|
...nodeBinCandidates(root, "svelteserver"),
|
|
@@ -4484,7 +4816,7 @@ var SvelteServer = {
|
|
|
4484
4816
|
return {
|
|
4485
4817
|
process: proc.process,
|
|
4486
4818
|
source: proc.source,
|
|
4487
|
-
initialization: tsserverPath ? { typescript: { tsdk:
|
|
4819
|
+
initialization: tsserverPath ? { typescript: { tsdk: path6.dirname(tsserverPath) } } : void 0
|
|
4488
4820
|
};
|
|
4489
4821
|
}
|
|
4490
4822
|
};
|
|
@@ -4735,6 +5067,7 @@ var LSP_SERVERS = [
|
|
|
4735
5067
|
FSharpServer,
|
|
4736
5068
|
JavaServer,
|
|
4737
5069
|
KotlinServer,
|
|
5070
|
+
LeanServer,
|
|
4738
5071
|
SwiftServer,
|
|
4739
5072
|
DartServer,
|
|
4740
5073
|
LuaServer,
|
|
@@ -4777,6 +5110,54 @@ function getServerById(id) {
|
|
|
4777
5110
|
return LSP_SERVERS.find((server) => server.id === id);
|
|
4778
5111
|
}
|
|
4779
5112
|
|
|
5113
|
+
// dist/clients/lsp/session-roots.js
|
|
5114
|
+
import path7 from "node:path";
|
|
5115
|
+
var SESSION_ROOT_CAP = 128;
|
|
5116
|
+
var sessionRoots = new BoundedFifoMap(SESSION_ROOT_CAP);
|
|
5117
|
+
function noteEvictedRoots(evicted) {
|
|
5118
|
+
const roots = evicted.map(([root]) => root);
|
|
5119
|
+
if (roots.length > 0) {
|
|
5120
|
+
incrementDegradationCount({
|
|
5121
|
+
kind: "lsp-session-root-evicted",
|
|
5122
|
+
subject: `cap=${SESSION_ROOT_CAP}`,
|
|
5123
|
+
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]})`
|
|
5124
|
+
});
|
|
5125
|
+
}
|
|
5126
|
+
return roots;
|
|
5127
|
+
}
|
|
5128
|
+
function registerSessionRoot(cwd) {
|
|
5129
|
+
const root = path7.resolve(cwd);
|
|
5130
|
+
if (sessionRoots.has(root))
|
|
5131
|
+
return [];
|
|
5132
|
+
return noteEvictedRoots(sessionRoots.set(root, void 0));
|
|
5133
|
+
}
|
|
5134
|
+
function setSessionRootConfig(cwd, config) {
|
|
5135
|
+
return noteEvictedRoots(sessionRoots.set(path7.resolve(cwd), config));
|
|
5136
|
+
}
|
|
5137
|
+
function sessionRootConfigEntries() {
|
|
5138
|
+
return sessionRoots;
|
|
5139
|
+
}
|
|
5140
|
+
function isSessionRootRegistered(cwd) {
|
|
5141
|
+
return sessionRoots.has(path7.resolve(cwd));
|
|
5142
|
+
}
|
|
5143
|
+
function shouldInitializeSessionRoot(cwd, readyRoots) {
|
|
5144
|
+
const normalized = path7.resolve(cwd);
|
|
5145
|
+
return !readyRoots.has(normalized) || !isSessionRootRegistered(normalized);
|
|
5146
|
+
}
|
|
5147
|
+
function isOutsideAllSessionRoots(filePath) {
|
|
5148
|
+
if (sessionRoots.size === 0)
|
|
5149
|
+
return false;
|
|
5150
|
+
const resolved = path7.resolve(filePath);
|
|
5151
|
+
for (const root of sessionRoots.keys()) {
|
|
5152
|
+
if (isSameOrWithin(root, resolved))
|
|
5153
|
+
return false;
|
|
5154
|
+
}
|
|
5155
|
+
return true;
|
|
5156
|
+
}
|
|
5157
|
+
function getSessionRootsForTelemetry(limit = 4) {
|
|
5158
|
+
return [...sessionRoots.keys()].sort((a, b) => Number(a > b) - Number(a < b)).slice(0, limit);
|
|
5159
|
+
}
|
|
5160
|
+
|
|
4780
5161
|
export {
|
|
4781
5162
|
findLocalTyposConfig,
|
|
4782
5163
|
getAstGrepRuleSources,
|
|
@@ -4784,6 +5165,11 @@ export {
|
|
|
4784
5165
|
isAuxiliary,
|
|
4785
5166
|
serverTraits,
|
|
4786
5167
|
registerRunnerId,
|
|
5168
|
+
withLspProjectCodePermission,
|
|
5169
|
+
refuseUntrustedLspExecution,
|
|
5170
|
+
resolveAnalysisRootPath,
|
|
5171
|
+
resolveAnalysisRoot,
|
|
5172
|
+
canWriteAnalysisRoot,
|
|
4787
5173
|
BUILTIN_SERVER_RUNNER_COVERS,
|
|
4788
5174
|
describeRootFallback,
|
|
4789
5175
|
resolveLspServerCwd,
|