@smthrs/std 0.0.0-stage → 1.0.0-rc.4

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.
Files changed (555) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/LICENSE +21 -0
  3. package/README.md +152 -2
  4. package/dist/cjs/ApplyPatch.d.ts +174 -0
  5. package/dist/cjs/ApplyPatch.d.ts.map +1 -0
  6. package/dist/cjs/ApplyPatch.js +309 -0
  7. package/dist/cjs/ApplyPatch.js.map +7 -0
  8. package/dist/cjs/Bash.d.ts +380 -0
  9. package/dist/cjs/Bash.d.ts.map +1 -0
  10. package/dist/cjs/Bash.js +332 -0
  11. package/dist/cjs/Bash.js.map +7 -0
  12. package/dist/cjs/Checkpoints.d.ts +279 -0
  13. package/dist/cjs/Checkpoints.d.ts.map +1 -0
  14. package/dist/cjs/Checkpoints.js +145 -0
  15. package/dist/cjs/Checkpoints.js.map +7 -0
  16. package/dist/cjs/Container.d.ts +132 -0
  17. package/dist/cjs/Container.d.ts.map +1 -0
  18. package/dist/cjs/Container.js +113 -0
  19. package/dist/cjs/Container.js.map +7 -0
  20. package/dist/cjs/Edit.d.ts +203 -0
  21. package/dist/cjs/Edit.d.ts.map +1 -0
  22. package/dist/cjs/Edit.js +258 -0
  23. package/dist/cjs/Edit.js.map +7 -0
  24. package/dist/cjs/ExaWebSearch.d.ts +22 -0
  25. package/dist/cjs/ExaWebSearch.d.ts.map +1 -0
  26. package/dist/cjs/ExaWebSearch.js +138 -0
  27. package/dist/cjs/ExaWebSearch.js.map +7 -0
  28. package/dist/cjs/Explore.d.ts +328 -0
  29. package/dist/cjs/Explore.d.ts.map +1 -0
  30. package/dist/cjs/Explore.js +90 -0
  31. package/dist/cjs/Explore.js.map +7 -0
  32. package/dist/cjs/Fetch.d.ts +130 -0
  33. package/dist/cjs/Fetch.d.ts.map +1 -0
  34. package/dist/cjs/Fetch.js +64 -0
  35. package/dist/cjs/Fetch.js.map +7 -0
  36. package/dist/cjs/Glob.d.ts +204 -0
  37. package/dist/cjs/Glob.d.ts.map +1 -0
  38. package/dist/cjs/Glob.js +94 -0
  39. package/dist/cjs/Glob.js.map +7 -0
  40. package/dist/cjs/Grep.d.ts +347 -0
  41. package/dist/cjs/Grep.d.ts.map +1 -0
  42. package/dist/cjs/Grep.js +181 -0
  43. package/dist/cjs/Grep.js.map +7 -0
  44. package/dist/cjs/HttpPost.d.ts +130 -0
  45. package/dist/cjs/HttpPost.d.ts.map +1 -0
  46. package/dist/cjs/HttpPost.js +72 -0
  47. package/dist/cjs/HttpPost.js.map +7 -0
  48. package/dist/cjs/LanguageServer.d.ts +90 -0
  49. package/dist/cjs/LanguageServer.d.ts.map +1 -0
  50. package/dist/cjs/LanguageServer.js +60 -0
  51. package/dist/cjs/LanguageServer.js.map +7 -0
  52. package/dist/cjs/Ls.d.ts +164 -0
  53. package/dist/cjs/Ls.d.ts.map +1 -0
  54. package/dist/cjs/Ls.js +136 -0
  55. package/dist/cjs/Ls.js.map +7 -0
  56. package/dist/cjs/Lsp.d.ts +125 -0
  57. package/dist/cjs/Lsp.d.ts.map +1 -0
  58. package/dist/cjs/Lsp.js +137 -0
  59. package/dist/cjs/Lsp.js.map +7 -0
  60. package/dist/cjs/Manifest.d.ts +918 -0
  61. package/dist/cjs/Manifest.d.ts.map +1 -0
  62. package/dist/cjs/Manifest.js +144 -0
  63. package/dist/cjs/Manifest.js.map +7 -0
  64. package/dist/cjs/NativeSearch.d.ts +38 -0
  65. package/dist/cjs/NativeSearch.d.ts.map +1 -0
  66. package/dist/cjs/NativeSearch.js +326 -0
  67. package/dist/cjs/NativeSearch.js.map +7 -0
  68. package/dist/cjs/NodeLanguageServer.d.ts +128 -0
  69. package/dist/cjs/NodeLanguageServer.d.ts.map +1 -0
  70. package/dist/cjs/NodeLanguageServer.js +796 -0
  71. package/dist/cjs/NodeLanguageServer.js.map +7 -0
  72. package/dist/cjs/PortableSearch.d.ts +24 -0
  73. package/dist/cjs/PortableSearch.d.ts.map +1 -0
  74. package/dist/cjs/PortableSearch.js +233 -0
  75. package/dist/cjs/PortableSearch.js.map +7 -0
  76. package/dist/cjs/Probe.d.ts +193 -0
  77. package/dist/cjs/Probe.d.ts.map +1 -0
  78. package/dist/cjs/Probe.js +134 -0
  79. package/dist/cjs/Probe.js.map +7 -0
  80. package/dist/cjs/Read.d.ts +189 -0
  81. package/dist/cjs/Read.d.ts.map +1 -0
  82. package/dist/cjs/Read.js +223 -0
  83. package/dist/cjs/Read.js.map +7 -0
  84. package/dist/cjs/Relocate.d.ts +73 -0
  85. package/dist/cjs/Relocate.d.ts.map +1 -0
  86. package/dist/cjs/Relocate.js +72 -0
  87. package/dist/cjs/Relocate.js.map +7 -0
  88. package/dist/cjs/Search.d.ts +163 -0
  89. package/dist/cjs/Search.d.ts.map +1 -0
  90. package/dist/cjs/Search.js +51 -0
  91. package/dist/cjs/Search.js.map +7 -0
  92. package/dist/cjs/SearchConformance.d.ts +115 -0
  93. package/dist/cjs/SearchConformance.d.ts.map +1 -0
  94. package/dist/cjs/SearchConformance.js +172 -0
  95. package/dist/cjs/SearchConformance.js.map +7 -0
  96. package/dist/cjs/SearchContract.d.ts +114 -0
  97. package/dist/cjs/SearchContract.d.ts.map +1 -0
  98. package/dist/cjs/SearchContract.js +339 -0
  99. package/dist/cjs/SearchContract.js.map +7 -0
  100. package/dist/cjs/ShellCommand.d.ts +164 -0
  101. package/dist/cjs/ShellCommand.d.ts.map +1 -0
  102. package/dist/cjs/ShellCommand.js +102 -0
  103. package/dist/cjs/ShellCommand.js.map +7 -0
  104. package/dist/cjs/StdError.d.ts +55 -0
  105. package/dist/cjs/StdError.d.ts.map +1 -0
  106. package/dist/cjs/StdError.js +74 -0
  107. package/dist/cjs/StdError.js.map +7 -0
  108. package/dist/cjs/TestRun.d.ts +311 -0
  109. package/dist/cjs/TestRun.d.ts.map +1 -0
  110. package/dist/cjs/TestRun.js +228 -0
  111. package/dist/cjs/TestRun.js.map +7 -0
  112. package/dist/cjs/TestRunner.d.ts +102 -0
  113. package/dist/cjs/TestRunner.d.ts.map +1 -0
  114. package/dist/cjs/TestRunner.js +54 -0
  115. package/dist/cjs/TestRunner.js.map +7 -0
  116. package/dist/cjs/TreeFingerprint.d.ts +140 -0
  117. package/dist/cjs/TreeFingerprint.d.ts.map +1 -0
  118. package/dist/cjs/TreeFingerprint.js +87 -0
  119. package/dist/cjs/TreeFingerprint.js.map +7 -0
  120. package/dist/cjs/UpdatePlan.d.ts +152 -0
  121. package/dist/cjs/UpdatePlan.d.ts.map +1 -0
  122. package/dist/cjs/UpdatePlan.js +87 -0
  123. package/dist/cjs/UpdatePlan.js.map +7 -0
  124. package/dist/cjs/WebFetch.d.ts +134 -0
  125. package/dist/cjs/WebFetch.d.ts.map +1 -0
  126. package/dist/cjs/WebFetch.js +140 -0
  127. package/dist/cjs/WebFetch.js.map +7 -0
  128. package/dist/cjs/WebSearch.d.ts +181 -0
  129. package/dist/cjs/WebSearch.d.ts.map +1 -0
  130. package/dist/cjs/WebSearch.js +86 -0
  131. package/dist/cjs/WebSearch.js.map +7 -0
  132. package/dist/cjs/Write.d.ts +147 -0
  133. package/dist/cjs/Write.d.ts.map +1 -0
  134. package/dist/cjs/Write.js +122 -0
  135. package/dist/cjs/Write.js.map +7 -0
  136. package/dist/cjs/index.d.ts +127 -0
  137. package/dist/cjs/index.d.ts.map +1 -0
  138. package/dist/cjs/index.js +99 -0
  139. package/dist/cjs/index.js.map +7 -0
  140. package/dist/cjs/internal/ApplyPatch.d.ts +145 -0
  141. package/dist/cjs/internal/ApplyPatch.d.ts.map +1 -0
  142. package/dist/cjs/internal/ApplyPatch.js +462 -0
  143. package/dist/cjs/internal/ApplyPatch.js.map +7 -0
  144. package/dist/cjs/internal/CodexText.d.ts +73 -0
  145. package/dist/cjs/internal/CodexText.d.ts.map +1 -0
  146. package/dist/cjs/internal/CodexText.js +108 -0
  147. package/dist/cjs/internal/CodexText.js.map +7 -0
  148. package/dist/cjs/internal/Declaration.d.ts +49 -0
  149. package/dist/cjs/internal/Declaration.d.ts.map +1 -0
  150. package/dist/cjs/internal/Declaration.js +46 -0
  151. package/dist/cjs/internal/Declaration.js.map +7 -0
  152. package/dist/cjs/internal/Diagnostics.d.ts +77 -0
  153. package/dist/cjs/internal/Diagnostics.d.ts.map +1 -0
  154. package/dist/cjs/internal/Diagnostics.js +89 -0
  155. package/dist/cjs/internal/Diagnostics.js.map +7 -0
  156. package/dist/cjs/internal/EnvelopePrecheck.d.ts +67 -0
  157. package/dist/cjs/internal/EnvelopePrecheck.d.ts.map +1 -0
  158. package/dist/cjs/internal/EnvelopePrecheck.js +124 -0
  159. package/dist/cjs/internal/EnvelopePrecheck.js.map +7 -0
  160. package/dist/cjs/internal/Exec.d.ts +139 -0
  161. package/dist/cjs/internal/Exec.d.ts.map +1 -0
  162. package/dist/cjs/internal/Exec.js +158 -0
  163. package/dist/cjs/internal/Exec.js.map +7 -0
  164. package/dist/cjs/internal/FileMutation.d.ts +109 -0
  165. package/dist/cjs/internal/FileMutation.d.ts.map +1 -0
  166. package/dist/cjs/internal/FileMutation.js +116 -0
  167. package/dist/cjs/internal/FileMutation.js.map +7 -0
  168. package/dist/cjs/internal/FsFailure.d.ts +38 -0
  169. package/dist/cjs/internal/FsFailure.d.ts.map +1 -0
  170. package/dist/cjs/internal/FsFailure.js +40 -0
  171. package/dist/cjs/internal/FsFailure.js.map +7 -0
  172. package/dist/cjs/internal/GitWorktree.d.ts +108 -0
  173. package/dist/cjs/internal/GitWorktree.d.ts.map +1 -0
  174. package/dist/cjs/internal/GitWorktree.js +276 -0
  175. package/dist/cjs/internal/GitWorktree.js.map +7 -0
  176. package/dist/cjs/internal/Grouping.d.ts +51 -0
  177. package/dist/cjs/internal/Grouping.d.ts.map +1 -0
  178. package/dist/cjs/internal/Grouping.js +83 -0
  179. package/dist/cjs/internal/Grouping.js.map +7 -0
  180. package/dist/cjs/internal/Html.d.ts +20 -0
  181. package/dist/cjs/internal/Html.d.ts.map +1 -0
  182. package/dist/cjs/internal/Html.js +81 -0
  183. package/dist/cjs/internal/Html.js.map +7 -0
  184. package/dist/cjs/internal/Http.d.ts +95 -0
  185. package/dist/cjs/internal/Http.d.ts.map +1 -0
  186. package/dist/cjs/internal/Http.js +153 -0
  187. package/dist/cjs/internal/Http.js.map +7 -0
  188. package/dist/cjs/internal/HttpNetwork.d.ts +27 -0
  189. package/dist/cjs/internal/HttpNetwork.d.ts.map +1 -0
  190. package/dist/cjs/internal/HttpNetwork.js +146 -0
  191. package/dist/cjs/internal/HttpNetwork.js.map +7 -0
  192. package/dist/cjs/internal/Ignore.d.ts +37 -0
  193. package/dist/cjs/internal/Ignore.d.ts.map +1 -0
  194. package/dist/cjs/internal/Ignore.js +100 -0
  195. package/dist/cjs/internal/Ignore.js.map +7 -0
  196. package/dist/cjs/internal/LinearRegex.d.ts +19 -0
  197. package/dist/cjs/internal/LinearRegex.d.ts.map +1 -0
  198. package/dist/cjs/internal/LinearRegex.js +166 -0
  199. package/dist/cjs/internal/LinearRegex.js.map +7 -0
  200. package/dist/cjs/internal/Match.d.ts +85 -0
  201. package/dist/cjs/internal/Match.d.ts.map +1 -0
  202. package/dist/cjs/internal/Match.js +99 -0
  203. package/dist/cjs/internal/Match.js.map +7 -0
  204. package/dist/cjs/internal/Paths.d.ts +23 -0
  205. package/dist/cjs/internal/Paths.d.ts.map +1 -0
  206. package/dist/cjs/internal/Paths.js +52 -0
  207. package/dist/cjs/internal/Paths.js.map +7 -0
  208. package/dist/cjs/internal/Preserve.d.ts +25 -0
  209. package/dist/cjs/internal/Preserve.d.ts.map +1 -0
  210. package/dist/cjs/internal/Preserve.js +88 -0
  211. package/dist/cjs/internal/Preserve.js.map +7 -0
  212. package/dist/cjs/internal/Prune.d.ts +35 -0
  213. package/dist/cjs/internal/Prune.d.ts.map +1 -0
  214. package/dist/cjs/internal/Prune.js +54 -0
  215. package/dist/cjs/internal/Prune.js.map +7 -0
  216. package/dist/cjs/internal/SearchContract.d.ts +63 -0
  217. package/dist/cjs/internal/SearchContract.d.ts.map +1 -0
  218. package/dist/cjs/internal/SearchContract.js +46 -0
  219. package/dist/cjs/internal/SearchContract.js.map +7 -0
  220. package/dist/cjs/internal/Symbols.d.ts +39 -0
  221. package/dist/cjs/internal/Symbols.d.ts.map +1 -0
  222. package/dist/cjs/internal/Symbols.js +59 -0
  223. package/dist/cjs/internal/Symbols.js.map +7 -0
  224. package/dist/cjs/internal/TestReport.d.ts +52 -0
  225. package/dist/cjs/internal/TestReport.d.ts.map +1 -0
  226. package/dist/cjs/internal/TestReport.js +131 -0
  227. package/dist/cjs/internal/TestReport.js.map +7 -0
  228. package/dist/cjs/internal/Text.d.ts +114 -0
  229. package/dist/cjs/internal/Text.d.ts.map +1 -0
  230. package/dist/cjs/internal/Text.js +82 -0
  231. package/dist/cjs/internal/Text.js.map +7 -0
  232. package/dist/cjs/internal/Url.d.ts +13 -0
  233. package/dist/cjs/internal/Url.d.ts.map +1 -0
  234. package/dist/cjs/internal/Url.js +35 -0
  235. package/dist/cjs/internal/Url.js.map +7 -0
  236. package/dist/cjs/internal/Walk.d.ts +72 -0
  237. package/dist/cjs/internal/Walk.d.ts.map +1 -0
  238. package/dist/cjs/internal/Walk.js +108 -0
  239. package/dist/cjs/internal/Walk.js.map +7 -0
  240. package/dist/cjs/package.json +1 -0
  241. package/dist/esm/ApplyPatch.d.ts +174 -0
  242. package/dist/esm/ApplyPatch.d.ts.map +1 -0
  243. package/dist/esm/ApplyPatch.js +346 -0
  244. package/dist/esm/ApplyPatch.js.map +1 -0
  245. package/dist/esm/Bash.d.ts +380 -0
  246. package/dist/esm/Bash.d.ts.map +1 -0
  247. package/dist/esm/Bash.js +505 -0
  248. package/dist/esm/Bash.js.map +1 -0
  249. package/dist/esm/Checkpoints.d.ts +279 -0
  250. package/dist/esm/Checkpoints.d.ts.map +1 -0
  251. package/dist/esm/Checkpoints.js +298 -0
  252. package/dist/esm/Checkpoints.js.map +1 -0
  253. package/dist/esm/Container.d.ts +132 -0
  254. package/dist/esm/Container.d.ts.map +1 -0
  255. package/dist/esm/Container.js +151 -0
  256. package/dist/esm/Container.js.map +1 -0
  257. package/dist/esm/Edit.d.ts +203 -0
  258. package/dist/esm/Edit.d.ts.map +1 -0
  259. package/dist/esm/Edit.js +296 -0
  260. package/dist/esm/Edit.js.map +1 -0
  261. package/dist/esm/ExaWebSearch.d.ts +22 -0
  262. package/dist/esm/ExaWebSearch.d.ts.map +1 -0
  263. package/dist/esm/ExaWebSearch.js +107 -0
  264. package/dist/esm/ExaWebSearch.js.map +1 -0
  265. package/dist/esm/Explore.d.ts +328 -0
  266. package/dist/esm/Explore.d.ts.map +1 -0
  267. package/dist/esm/Explore.js +106 -0
  268. package/dist/esm/Explore.js.map +1 -0
  269. package/dist/esm/Fetch.d.ts +130 -0
  270. package/dist/esm/Fetch.d.ts.map +1 -0
  271. package/dist/esm/Fetch.js +91 -0
  272. package/dist/esm/Fetch.js.map +1 -0
  273. package/dist/esm/Glob.d.ts +204 -0
  274. package/dist/esm/Glob.d.ts.map +1 -0
  275. package/dist/esm/Glob.js +177 -0
  276. package/dist/esm/Glob.js.map +1 -0
  277. package/dist/esm/Grep.d.ts +347 -0
  278. package/dist/esm/Grep.d.ts.map +1 -0
  279. package/dist/esm/Grep.js +289 -0
  280. package/dist/esm/Grep.js.map +1 -0
  281. package/dist/esm/HttpPost.d.ts +130 -0
  282. package/dist/esm/HttpPost.d.ts.map +1 -0
  283. package/dist/esm/HttpPost.js +89 -0
  284. package/dist/esm/HttpPost.js.map +1 -0
  285. package/dist/esm/LanguageServer.d.ts +90 -0
  286. package/dist/esm/LanguageServer.d.ts.map +1 -0
  287. package/dist/esm/LanguageServer.js +57 -0
  288. package/dist/esm/LanguageServer.js.map +1 -0
  289. package/dist/esm/Ls.d.ts +164 -0
  290. package/dist/esm/Ls.d.ts.map +1 -0
  291. package/dist/esm/Ls.js +178 -0
  292. package/dist/esm/Ls.js.map +1 -0
  293. package/dist/esm/Lsp.d.ts +125 -0
  294. package/dist/esm/Lsp.d.ts.map +1 -0
  295. package/dist/esm/Lsp.js +165 -0
  296. package/dist/esm/Lsp.js.map +1 -0
  297. package/dist/esm/Manifest.d.ts +918 -0
  298. package/dist/esm/Manifest.d.ts.map +1 -0
  299. package/dist/esm/Manifest.js +153 -0
  300. package/dist/esm/Manifest.js.map +1 -0
  301. package/dist/esm/NativeSearch.d.ts +38 -0
  302. package/dist/esm/NativeSearch.d.ts.map +1 -0
  303. package/dist/esm/NativeSearch.js +378 -0
  304. package/dist/esm/NativeSearch.js.map +1 -0
  305. package/dist/esm/NodeLanguageServer.d.ts +128 -0
  306. package/dist/esm/NodeLanguageServer.d.ts.map +1 -0
  307. package/dist/esm/NodeLanguageServer.js +843 -0
  308. package/dist/esm/NodeLanguageServer.js.map +1 -0
  309. package/dist/esm/PortableSearch.d.ts +24 -0
  310. package/dist/esm/PortableSearch.d.ts.map +1 -0
  311. package/dist/esm/PortableSearch.js +240 -0
  312. package/dist/esm/PortableSearch.js.map +1 -0
  313. package/dist/esm/Probe.d.ts +193 -0
  314. package/dist/esm/Probe.d.ts.map +1 -0
  315. package/dist/esm/Probe.js +225 -0
  316. package/dist/esm/Probe.js.map +1 -0
  317. package/dist/esm/Read.d.ts +189 -0
  318. package/dist/esm/Read.d.ts.map +1 -0
  319. package/dist/esm/Read.js +300 -0
  320. package/dist/esm/Read.js.map +1 -0
  321. package/dist/esm/Relocate.d.ts +73 -0
  322. package/dist/esm/Relocate.d.ts.map +1 -0
  323. package/dist/esm/Relocate.js +153 -0
  324. package/dist/esm/Relocate.js.map +1 -0
  325. package/dist/esm/Search.d.ts +163 -0
  326. package/dist/esm/Search.d.ts.map +1 -0
  327. package/dist/esm/Search.js +47 -0
  328. package/dist/esm/Search.js.map +1 -0
  329. package/dist/esm/SearchConformance.d.ts +115 -0
  330. package/dist/esm/SearchConformance.d.ts.map +1 -0
  331. package/dist/esm/SearchConformance.js +193 -0
  332. package/dist/esm/SearchConformance.js.map +1 -0
  333. package/dist/esm/SearchContract.d.ts +114 -0
  334. package/dist/esm/SearchContract.d.ts.map +1 -0
  335. package/dist/esm/SearchContract.js +461 -0
  336. package/dist/esm/SearchContract.js.map +1 -0
  337. package/dist/esm/ShellCommand.d.ts +164 -0
  338. package/dist/esm/ShellCommand.d.ts.map +1 -0
  339. package/dist/esm/ShellCommand.js +159 -0
  340. package/dist/esm/ShellCommand.js.map +1 -0
  341. package/dist/esm/StdError.d.ts +55 -0
  342. package/dist/esm/StdError.d.ts.map +1 -0
  343. package/dist/esm/StdError.js +71 -0
  344. package/dist/esm/StdError.js.map +1 -0
  345. package/dist/esm/TestRun.d.ts +311 -0
  346. package/dist/esm/TestRun.d.ts.map +1 -0
  347. package/dist/esm/TestRun.js +316 -0
  348. package/dist/esm/TestRun.js.map +1 -0
  349. package/dist/esm/TestRunner.d.ts +102 -0
  350. package/dist/esm/TestRunner.d.ts.map +1 -0
  351. package/dist/esm/TestRunner.js +68 -0
  352. package/dist/esm/TestRunner.js.map +1 -0
  353. package/dist/esm/TreeFingerprint.d.ts +140 -0
  354. package/dist/esm/TreeFingerprint.d.ts.map +1 -0
  355. package/dist/esm/TreeFingerprint.js +170 -0
  356. package/dist/esm/TreeFingerprint.js.map +1 -0
  357. package/dist/esm/UpdatePlan.d.ts +152 -0
  358. package/dist/esm/UpdatePlan.d.ts.map +1 -0
  359. package/dist/esm/UpdatePlan.js +129 -0
  360. package/dist/esm/UpdatePlan.js.map +1 -0
  361. package/dist/esm/WebFetch.d.ts +134 -0
  362. package/dist/esm/WebFetch.d.ts.map +1 -0
  363. package/dist/esm/WebFetch.js +151 -0
  364. package/dist/esm/WebFetch.js.map +1 -0
  365. package/dist/esm/WebSearch.d.ts +181 -0
  366. package/dist/esm/WebSearch.d.ts.map +1 -0
  367. package/dist/esm/WebSearch.js +134 -0
  368. package/dist/esm/WebSearch.js.map +1 -0
  369. package/dist/esm/Write.d.ts +147 -0
  370. package/dist/esm/Write.d.ts.map +1 -0
  371. package/dist/esm/Write.js +144 -0
  372. package/dist/esm/Write.js.map +1 -0
  373. package/dist/esm/index.d.ts +127 -0
  374. package/dist/esm/index.d.ts.map +1 -0
  375. package/dist/esm/index.js +127 -0
  376. package/dist/esm/index.js.map +1 -0
  377. package/dist/esm/internal/ApplyPatch.d.ts +145 -0
  378. package/dist/esm/internal/ApplyPatch.d.ts.map +1 -0
  379. package/dist/esm/internal/ApplyPatch.js +489 -0
  380. package/dist/esm/internal/ApplyPatch.js.map +1 -0
  381. package/dist/esm/internal/CodexText.d.ts +73 -0
  382. package/dist/esm/internal/CodexText.d.ts.map +1 -0
  383. package/dist/esm/internal/CodexText.js +156 -0
  384. package/dist/esm/internal/CodexText.js.map +1 -0
  385. package/dist/esm/internal/Declaration.d.ts +49 -0
  386. package/dist/esm/internal/Declaration.d.ts.map +1 -0
  387. package/dist/esm/internal/Declaration.js +42 -0
  388. package/dist/esm/internal/Declaration.js.map +1 -0
  389. package/dist/esm/internal/Diagnostics.d.ts +77 -0
  390. package/dist/esm/internal/Diagnostics.d.ts.map +1 -0
  391. package/dist/esm/internal/Diagnostics.js +99 -0
  392. package/dist/esm/internal/Diagnostics.js.map +1 -0
  393. package/dist/esm/internal/EnvelopePrecheck.d.ts +67 -0
  394. package/dist/esm/internal/EnvelopePrecheck.d.ts.map +1 -0
  395. package/dist/esm/internal/EnvelopePrecheck.js +167 -0
  396. package/dist/esm/internal/EnvelopePrecheck.js.map +1 -0
  397. package/dist/esm/internal/Exec.d.ts +139 -0
  398. package/dist/esm/internal/Exec.d.ts.map +1 -0
  399. package/dist/esm/internal/Exec.js +193 -0
  400. package/dist/esm/internal/Exec.js.map +1 -0
  401. package/dist/esm/internal/FileMutation.d.ts +109 -0
  402. package/dist/esm/internal/FileMutation.d.ts.map +1 -0
  403. package/dist/esm/internal/FileMutation.js +123 -0
  404. package/dist/esm/internal/FileMutation.js.map +1 -0
  405. package/dist/esm/internal/FsFailure.d.ts +38 -0
  406. package/dist/esm/internal/FsFailure.d.ts.map +1 -0
  407. package/dist/esm/internal/FsFailure.js +39 -0
  408. package/dist/esm/internal/FsFailure.js.map +1 -0
  409. package/dist/esm/internal/GitWorktree.d.ts +108 -0
  410. package/dist/esm/internal/GitWorktree.d.ts.map +1 -0
  411. package/dist/esm/internal/GitWorktree.js +352 -0
  412. package/dist/esm/internal/GitWorktree.js.map +1 -0
  413. package/dist/esm/internal/Grouping.d.ts +51 -0
  414. package/dist/esm/internal/Grouping.d.ts.map +1 -0
  415. package/dist/esm/internal/Grouping.js +99 -0
  416. package/dist/esm/internal/Grouping.js.map +1 -0
  417. package/dist/esm/internal/Html.d.ts +20 -0
  418. package/dist/esm/internal/Html.d.ts.map +1 -0
  419. package/dist/esm/internal/Html.js +70 -0
  420. package/dist/esm/internal/Html.js.map +1 -0
  421. package/dist/esm/internal/Http.d.ts +95 -0
  422. package/dist/esm/internal/Http.d.ts.map +1 -0
  423. package/dist/esm/internal/Http.js +154 -0
  424. package/dist/esm/internal/Http.js.map +1 -0
  425. package/dist/esm/internal/HttpNetwork.d.ts +27 -0
  426. package/dist/esm/internal/HttpNetwork.d.ts.map +1 -0
  427. package/dist/esm/internal/HttpNetwork.js +114 -0
  428. package/dist/esm/internal/HttpNetwork.js.map +1 -0
  429. package/dist/esm/internal/Ignore.d.ts +37 -0
  430. package/dist/esm/internal/Ignore.d.ts.map +1 -0
  431. package/dist/esm/internal/Ignore.js +128 -0
  432. package/dist/esm/internal/Ignore.js.map +1 -0
  433. package/dist/esm/internal/LinearRegex.d.ts +19 -0
  434. package/dist/esm/internal/LinearRegex.d.ts.map +1 -0
  435. package/dist/esm/internal/LinearRegex.js +176 -0
  436. package/dist/esm/internal/LinearRegex.js.map +1 -0
  437. package/dist/esm/internal/Match.d.ts +85 -0
  438. package/dist/esm/internal/Match.d.ts.map +1 -0
  439. package/dist/esm/internal/Match.js +142 -0
  440. package/dist/esm/internal/Match.js.map +1 -0
  441. package/dist/esm/internal/Paths.d.ts +23 -0
  442. package/dist/esm/internal/Paths.d.ts.map +1 -0
  443. package/dist/esm/internal/Paths.js +40 -0
  444. package/dist/esm/internal/Paths.js.map +1 -0
  445. package/dist/esm/internal/Preserve.d.ts +25 -0
  446. package/dist/esm/internal/Preserve.d.ts.map +1 -0
  447. package/dist/esm/internal/Preserve.js +70 -0
  448. package/dist/esm/internal/Preserve.js.map +1 -0
  449. package/dist/esm/internal/Prune.d.ts +35 -0
  450. package/dist/esm/internal/Prune.d.ts.map +1 -0
  451. package/dist/esm/internal/Prune.js +60 -0
  452. package/dist/esm/internal/Prune.js.map +1 -0
  453. package/dist/esm/internal/SearchContract.d.ts +63 -0
  454. package/dist/esm/internal/SearchContract.d.ts.map +1 -0
  455. package/dist/esm/internal/SearchContract.js +66 -0
  456. package/dist/esm/internal/SearchContract.js.map +1 -0
  457. package/dist/esm/internal/Symbols.d.ts +39 -0
  458. package/dist/esm/internal/Symbols.d.ts.map +1 -0
  459. package/dist/esm/internal/Symbols.js +79 -0
  460. package/dist/esm/internal/Symbols.js.map +1 -0
  461. package/dist/esm/internal/TestReport.d.ts +52 -0
  462. package/dist/esm/internal/TestReport.d.ts.map +1 -0
  463. package/dist/esm/internal/TestReport.js +172 -0
  464. package/dist/esm/internal/TestReport.js.map +1 -0
  465. package/dist/esm/internal/Text.d.ts +114 -0
  466. package/dist/esm/internal/Text.d.ts.map +1 -0
  467. package/dist/esm/internal/Text.js +130 -0
  468. package/dist/esm/internal/Text.js.map +1 -0
  469. package/dist/esm/internal/Url.d.ts +13 -0
  470. package/dist/esm/internal/Url.d.ts.map +1 -0
  471. package/dist/esm/internal/Url.js +27 -0
  472. package/dist/esm/internal/Url.js.map +1 -0
  473. package/dist/esm/internal/Walk.d.ts +72 -0
  474. package/dist/esm/internal/Walk.d.ts.map +1 -0
  475. package/dist/esm/internal/Walk.js +126 -0
  476. package/dist/esm/internal/Walk.js.map +1 -0
  477. package/docs/README.md +117 -0
  478. package/docs/api.md +472 -0
  479. package/docs/concepts/effects-and-capabilities.md +136 -0
  480. package/docs/concepts/flows-and-handlers.md +115 -0
  481. package/docs/concepts/limits-and-disclosure.md +102 -0
  482. package/docs/concepts/search-contract.md +182 -0
  483. package/docs/guides/bind-the-standard-flows.md +114 -0
  484. package/docs/guides/implement-a-search-peer.md +133 -0
  485. package/docs/guides/pin-a-checkpoint.md +141 -0
  486. package/docs/guides/query-a-language-server.md +257 -0
  487. package/docs/guides/reach-the-network.md +141 -0
  488. package/docs/guides/read-and-edit-a-file.md +240 -0
  489. package/docs/guides/run-a-shell-command.md +215 -0
  490. package/docs/guides/run-the-test-suite.md +154 -0
  491. package/docs/guides/search-a-workspace.md +148 -0
  492. package/docs/installation.md +111 -0
  493. package/docs/quickstart.md +125 -0
  494. package/docs/reference/flows.md +556 -0
  495. package/docs/troubleshooting.md +322 -0
  496. package/package.json +439 -3
  497. package/src/ApplyPatch.ts +458 -0
  498. package/src/Bash.ts +607 -0
  499. package/src/Checkpoints.ts +422 -0
  500. package/src/Container.ts +212 -0
  501. package/src/Edit.ts +366 -0
  502. package/src/ExaWebSearch.ts +145 -0
  503. package/src/Explore.ts +139 -0
  504. package/src/Fetch.ts +117 -0
  505. package/src/Glob.ts +200 -0
  506. package/src/Grep.ts +320 -0
  507. package/src/HttpPost.ts +120 -0
  508. package/src/LanguageServer.ts +110 -0
  509. package/src/Ls.ts +228 -0
  510. package/src/Lsp.ts +184 -0
  511. package/src/Manifest.ts +162 -0
  512. package/src/NativeSearch.ts +457 -0
  513. package/src/NodeLanguageServer.ts +1148 -0
  514. package/src/PortableSearch.ts +264 -0
  515. package/src/Probe.ts +284 -0
  516. package/src/Read.ts +359 -0
  517. package/src/Relocate.ts +166 -0
  518. package/src/Search.ts +185 -0
  519. package/src/SearchConformance.ts +288 -0
  520. package/src/SearchContract.ts +489 -0
  521. package/src/ShellCommand.ts +201 -0
  522. package/src/StdError.ts +80 -0
  523. package/src/TestRun.ts +401 -0
  524. package/src/TestRunner.ts +119 -0
  525. package/src/TreeFingerprint.ts +200 -0
  526. package/src/UpdatePlan.ts +171 -0
  527. package/src/WebFetch.ts +194 -0
  528. package/src/WebSearch.ts +165 -0
  529. package/src/Write.ts +195 -0
  530. package/src/index.ts +154 -0
  531. package/src/internal/ApplyPatch.ts +601 -0
  532. package/src/internal/CodexText.ts +182 -0
  533. package/src/internal/Declaration.ts +60 -0
  534. package/src/internal/Diagnostics.ts +134 -0
  535. package/src/internal/EnvelopePrecheck.ts +233 -0
  536. package/src/internal/Exec.ts +314 -0
  537. package/src/internal/FileMutation.ts +231 -0
  538. package/src/internal/FsFailure.ts +51 -0
  539. package/src/internal/GitWorktree.ts +491 -0
  540. package/src/internal/Grouping.ts +106 -0
  541. package/src/internal/Html.ts +87 -0
  542. package/src/internal/Http.ts +209 -0
  543. package/src/internal/HttpNetwork.ts +153 -0
  544. package/src/internal/Ignore.ts +135 -0
  545. package/src/internal/LinearRegex.ts +173 -0
  546. package/src/internal/Match.ts +172 -0
  547. package/src/internal/Paths.ts +42 -0
  548. package/src/internal/Preserve.ts +108 -0
  549. package/src/internal/Prune.ts +62 -0
  550. package/src/internal/SearchContract.ts +77 -0
  551. package/src/internal/Symbols.ts +88 -0
  552. package/src/internal/TestReport.ts +194 -0
  553. package/src/internal/Text.ts +170 -0
  554. package/src/internal/Url.ts +23 -0
  555. package/src/internal/Walk.ts +176 -0
@@ -0,0 +1,843 @@
1
+ /**
2
+ * Host-backed Language Server Protocol client over the permission-checked
3
+ * process spawner.
4
+ *
5
+ * LSP is framed JSON-RPC over ordinary stdio pipes, so the client spawns
6
+ * through `@smthrs/kernel`'s `ChildProcessSpawner`; a terminal is never
7
+ * involved.
8
+ *
9
+ * @since 1.0.0
10
+ */
11
+ import * as ChildProcessEnvironment from "@smthrs/kernel/ChildProcessEnvironment";
12
+ import * as ChildProcessSpawner from "@smthrs/kernel/ChildProcessSpawner";
13
+ import { Clock, Deferred, Effect, Fiber, Layer, Option, Queue, Semaphore, Stream } from "effect";
14
+ import * as ChildProcess from "effect/unstable/process/ChildProcess";
15
+ import { createHash } from "node:crypto";
16
+ import * as NodeFs from "node:fs";
17
+ import * as NodePath from "node:path";
18
+ import { fileURLToPath, pathToFileURL } from "node:url";
19
+ import * as LanguageServer from "./LanguageServer.js";
20
+ import * as StdError from "./StdError.js";
21
+ /**
22
+ * Maximum frames buffered for a language server's standard input.
23
+ *
24
+ * Bounded offers apply backpressure, and each offer uses the request timeout
25
+ * so a server that stops reading produces a typed timeout instead of an
26
+ * unbounded queue or a new hang.
27
+ *
28
+ * @category constants
29
+ * @since 1.0.0
30
+ */
31
+ export const MAX_QUEUED_FRAMES = 256;
32
+ /**
33
+ * Maximum concurrent JSON-RPC requests awaiting a response.
34
+ *
35
+ * Every entry already has a timeout, and process exit or stdout closure fails
36
+ * all entries. This cap is the last-resort bound for a host that fans out
37
+ * requests without limit.
38
+ *
39
+ * @category constants
40
+ * @since 1.0.0
41
+ */
42
+ export const MAX_PENDING_REQUESTS = 512;
43
+ const DEFAULT_SETTLE_MS = 5_000;
44
+ const DEFAULT_QUIET_MS = 300;
45
+ /**
46
+ * A request every server must refuse at once: the specification has a server
47
+ * answer an unknown `$/` request with MethodNotFound.
48
+ */
49
+ const BARRIER_METHOD = "$/smithers/barrier";
50
+ /** A server that has not answered the barrier in this long is not asked again. */
51
+ const BARRIER_TIMEOUT_MS = 1_000;
52
+ /** JSON-RPC's code for a method the server does not implement. */
53
+ const METHOD_NOT_FOUND = -32601;
54
+ const LANGUAGE_IDS = {
55
+ ".ts": "typescript",
56
+ ".mts": "typescript",
57
+ ".cts": "typescript",
58
+ ".tsx": "typescriptreact",
59
+ ".js": "javascript",
60
+ ".mjs": "javascript",
61
+ ".cjs": "javascript",
62
+ ".jsx": "javascriptreact",
63
+ ".py": "python",
64
+ ".rs": "rust",
65
+ ".go": "go",
66
+ ".rb": "ruby",
67
+ ".sh": "shellscript",
68
+ ".md": "markdown",
69
+ ".yml": "yaml",
70
+ ".cc": "cpp",
71
+ ".cpp": "cpp",
72
+ ".hpp": "cpp",
73
+ ".cs": "csharp"
74
+ };
75
+ const extensionOf = (path) => NodePath.extname(path).toLowerCase();
76
+ const languageId = (path) => {
77
+ const extension = extensionOf(path);
78
+ return LANGUAGE_IDS[extension] ?? (extension.slice(1) || "plaintext");
79
+ };
80
+ const failure = (code, message) => new StdError.StdError({ code, message });
81
+ const maximumHeaderBytes = 8 * 1024;
82
+ const maximumFrameBytes = 8 * 1024 * 1024;
83
+ const headerEnd = new Uint8Array([13, 10, 13, 10]);
84
+ const contentLengthPrefix = new TextEncoder().encode("Content-Length:");
85
+ const concatenate = (left, right) => {
86
+ const combined = new Uint8Array(left.length + right.length);
87
+ combined.set(left);
88
+ combined.set(right, left.length);
89
+ return combined;
90
+ };
91
+ const makeChunkBuffer = () => {
92
+ let chunks = [];
93
+ let head = 0;
94
+ let headOffset = 0;
95
+ let length = 0;
96
+ const compact = () => {
97
+ if (head === chunks.length) {
98
+ chunks = [];
99
+ head = 0;
100
+ headOffset = 0;
101
+ }
102
+ else if (head >= 64 && head * 2 >= chunks.length) {
103
+ chunks = chunks.slice(head);
104
+ head = 0;
105
+ }
106
+ };
107
+ const consume = (count, output) => {
108
+ let remaining = count;
109
+ let outputOffset = 0;
110
+ for (const chunk of chunks.slice(head)) {
111
+ if (remaining === 0)
112
+ break;
113
+ const available = chunk.byteLength - headOffset;
114
+ const consumed = Math.min(available, remaining);
115
+ if (output !== undefined) {
116
+ output.set(chunk.subarray(headOffset, headOffset + consumed), outputOffset);
117
+ outputOffset += consumed;
118
+ }
119
+ headOffset += consumed;
120
+ length -= consumed;
121
+ remaining -= consumed;
122
+ if (headOffset === chunk.byteLength) {
123
+ head++;
124
+ headOffset = 0;
125
+ }
126
+ }
127
+ compact();
128
+ };
129
+ return {
130
+ get length() {
131
+ return length;
132
+ },
133
+ push: (chunk) => {
134
+ if (chunk.byteLength === 0)
135
+ return;
136
+ // Own the bytes so caller mutation or resizing cannot change buffered lengths.
137
+ chunks.push(chunk.slice());
138
+ length += chunk.byteLength;
139
+ },
140
+ indexOf: (needle) => {
141
+ let absolute = 0;
142
+ let matched = 0;
143
+ for (let chunkIndex = head; chunkIndex < chunks.length; chunkIndex++) {
144
+ const chunk = chunks[chunkIndex];
145
+ const start = chunkIndex === head ? headOffset : 0;
146
+ for (let index = start; index < chunk.byteLength; index++) {
147
+ const byte = chunk[index];
148
+ if (byte === needle[matched])
149
+ matched++;
150
+ else
151
+ matched = byte === needle[0] ? 1 : 0;
152
+ if (matched === needle.byteLength)
153
+ return absolute - needle.byteLength + 1;
154
+ absolute++;
155
+ }
156
+ }
157
+ return -1;
158
+ },
159
+ prefix: (count) => {
160
+ if (count > length)
161
+ return undefined;
162
+ return {
163
+ take: () => {
164
+ const output = new Uint8Array(count);
165
+ consume(count, output);
166
+ return output;
167
+ },
168
+ discard: () => consume(count)
169
+ };
170
+ }
171
+ };
172
+ };
173
+ const malformedId = (body) => {
174
+ const match = /"id"\s*:\s*(\d+)/.exec(body);
175
+ if (match === null)
176
+ return undefined;
177
+ const id = Number(match[1]);
178
+ return Number.isSafeInteger(id) ? id : undefined;
179
+ };
180
+ const makeFrameDecoder = () => {
181
+ const pending = makeChunkBuffer();
182
+ let bodyLength;
183
+ let resynchronizing = false;
184
+ return {
185
+ push: (chunk) => {
186
+ pending.push(chunk);
187
+ const events = [];
188
+ while (pending.length > 0 || bodyLength === 0) {
189
+ if (resynchronizing) {
190
+ const nextHeader = pending.indexOf(contentLengthPrefix);
191
+ if (nextHeader < 0) {
192
+ pending.prefix(Math.max(0, pending.length - contentLengthPrefix.byteLength + 1)).discard();
193
+ break;
194
+ }
195
+ pending.prefix(nextHeader).discard();
196
+ resynchronizing = false;
197
+ }
198
+ if (bodyLength !== undefined) {
199
+ const reader = pending.prefix(bodyLength);
200
+ if (reader === undefined)
201
+ break;
202
+ const body = new TextDecoder().decode(reader.take());
203
+ bodyLength = undefined;
204
+ try {
205
+ events.push({ _tag: "Message", value: JSON.parse(body) });
206
+ }
207
+ catch {
208
+ events.push({
209
+ _tag: "Failure",
210
+ error: failure("request_failed", "Language server returned malformed JSON"),
211
+ id: malformedId(body)
212
+ });
213
+ }
214
+ continue;
215
+ }
216
+ const delimiter = pending.indexOf(headerEnd);
217
+ if (delimiter < 0) {
218
+ if (pending.length > maximumHeaderBytes) {
219
+ events.push({
220
+ _tag: "Failure",
221
+ error: failure("request_failed", `Language server frame header exceeded ${maximumHeaderBytes} bytes`)
222
+ });
223
+ pending.prefix(1).discard();
224
+ resynchronizing = true;
225
+ continue;
226
+ }
227
+ break;
228
+ }
229
+ if (delimiter > maximumHeaderBytes) {
230
+ events.push({
231
+ _tag: "Failure",
232
+ error: failure("request_failed", `Language server frame header exceeded ${maximumHeaderBytes} bytes`)
233
+ });
234
+ pending.prefix(delimiter + headerEnd.byteLength).discard();
235
+ resynchronizing = true;
236
+ continue;
237
+ }
238
+ const header = new TextDecoder().decode(pending.prefix(delimiter).take());
239
+ pending.prefix(headerEnd.byteLength).discard();
240
+ const match = /(?:^|\r\n)Content-Length:\s*(\d+)(?:\r\n|$)/i.exec(header);
241
+ if (match === null) {
242
+ events.push({
243
+ _tag: "Failure",
244
+ error: failure("request_failed", "Language server frame omitted Content-Length")
245
+ });
246
+ resynchronizing = true;
247
+ continue;
248
+ }
249
+ const length = Number(match[1]);
250
+ if (!Number.isSafeInteger(length) || length < 0 || length > maximumFrameBytes) {
251
+ events.push({
252
+ _tag: "Failure",
253
+ error: failure("request_failed", `Language server frame exceeded ${maximumFrameBytes} bytes`)
254
+ });
255
+ resynchronizing = true;
256
+ continue;
257
+ }
258
+ bodyLength = length;
259
+ }
260
+ return events;
261
+ }
262
+ };
263
+ };
264
+ const asMessage = (value) => typeof value === "object" && value !== null && !Array.isArray(value)
265
+ ? value
266
+ : undefined;
267
+ const frame = (message) => {
268
+ const body = new TextEncoder().encode(JSON.stringify(message));
269
+ const header = new TextEncoder().encode(`Content-Length: ${body.byteLength}\r\n\r\n`);
270
+ return concatenate(header, body);
271
+ };
272
+ const firstCallHierarchyItem = (value) => Array.isArray(value) ? value[0] : undefined;
273
+ const isFile = (path) => {
274
+ try {
275
+ return NodeFs.statSync(path, { throwIfNoEntry: false })?.isFile() === true;
276
+ }
277
+ catch {
278
+ return false;
279
+ }
280
+ };
281
+ /** Whether anything, a file or a directory, exists at `path`. */
282
+ const exists = (path) => {
283
+ try {
284
+ return NodeFs.statSync(path, { throwIfNoEntry: false }) !== undefined;
285
+ }
286
+ catch {
287
+ return false;
288
+ }
289
+ };
290
+ const realPath = (path) => {
291
+ try {
292
+ return NodeFs.realpathSync(path);
293
+ }
294
+ catch {
295
+ return NodePath.resolve(path);
296
+ }
297
+ };
298
+ const isWithin = (root, path) => {
299
+ const relative = NodePath.relative(root, path);
300
+ return relative === "" || (relative !== ".." && !relative.startsWith(`..${NodePath.sep}`) &&
301
+ !NodePath.isAbsolute(relative));
302
+ };
303
+ /**
304
+ * Resolves the program a spawn would execute: a command containing a path
305
+ * separator against `cwd`, a bare name through the child's `PATH`, where an
306
+ * empty or relative entry is relative to `cwd`.
307
+ */
308
+ const resolveCommand = (command, cwd, path) => {
309
+ if (command.includes("/") || command.includes(NodePath.sep)) {
310
+ const candidate = NodePath.resolve(cwd, command);
311
+ return isFile(candidate) ? candidate : undefined;
312
+ }
313
+ for (const entry of (path ?? "").split(NodePath.delimiter)) {
314
+ const candidate = NodePath.resolve(cwd, entry, command);
315
+ if (!isFile(candidate))
316
+ continue;
317
+ try {
318
+ NodeFs.accessSync(candidate, NodeFs.constants.X_OK);
319
+ return candidate;
320
+ }
321
+ catch {
322
+ continue;
323
+ }
324
+ }
325
+ return undefined;
326
+ };
327
+ /**
328
+ * Refuses a server whose program or any file-naming argument lies in the
329
+ * workspace. The server runs on the host as the host user, so a program the
330
+ * workspace supplies (its `node_modules/.bin`, a `./` script, a symlink it
331
+ * planted) would let workspace files choose what the host executes.
332
+ */
333
+ /**
334
+ * Programs whose job is to run another program named in their arguments or
335
+ * found in the working directory: shells, `env`, and package runners. Their
336
+ * arguments are code or package names, not files, so the workspace check below
337
+ * cannot see what they would execute (`sh -c node_modules/.bin/x`, `npx x`).
338
+ */
339
+ const LAUNCHERS = new Set([
340
+ "sh",
341
+ "bash",
342
+ "zsh",
343
+ "dash",
344
+ "ksh",
345
+ "fish",
346
+ "csh",
347
+ "tcsh",
348
+ "env",
349
+ "npx",
350
+ "pnpx",
351
+ "npm",
352
+ "pnpm",
353
+ "yarn",
354
+ "bunx",
355
+ "deno",
356
+ "cmd",
357
+ "powershell",
358
+ "pwsh"
359
+ ]);
360
+ /** Interpreter flags that take code or a module to load instead of a file path. */
361
+ const CODE_FLAGS = new Set(["-e", "--eval", "-p", "--print", "-r", "--require", "--import", "--loader"]);
362
+ const launcher = (config) => {
363
+ const name = NodePath.basename(config.command).toLowerCase().replace(/\.(?:exe|cmd|bat|ps1)$/, "");
364
+ if (LAUNCHERS.has(name))
365
+ return name;
366
+ if (name !== "node" && name !== "bun" && name !== "nodejs")
367
+ return undefined;
368
+ const args = config.args ?? [];
369
+ if (name === "bun" && ["x", "run", "exec"].includes(args[0] ?? ""))
370
+ return `bun ${args[0]}`;
371
+ const flag = args.find((argument) => CODE_FLAGS.has(argument.split("=")[0]) || argument === "--experimental-loader");
372
+ return flag === undefined ? undefined : `${name} ${flag.split("=")[0]}`;
373
+ };
374
+ const workspaceProgram = (config, path) => {
375
+ const launching = launcher(config);
376
+ if (launching !== undefined) {
377
+ return failure("permission_denied", `Language server command runs ${launching}, which executes a program its arguments or the workspace choose; name the server's own host binary instead`);
378
+ }
379
+ const lexicalRoot = NodePath.resolve(config.cwd);
380
+ const realRoot = realPath(lexicalRoot);
381
+ const inWorkspace = (file) => isWithin(lexicalRoot, file) || isWithin(realRoot, file) || isWithin(realRoot, realPath(file)) ||
382
+ isWithin(lexicalRoot, realPath(file));
383
+ const program = resolveCommand(config.command, lexicalRoot, path);
384
+ if (program !== undefined && inWorkspace(program)) {
385
+ return failure("permission_denied", `Language server program ${program} is inside the workspace ${lexicalRoot}; run a host copy instead`);
386
+ }
387
+ for (const argument of config.args ?? []) {
388
+ for (const value of [argument, argument.slice(argument.indexOf("=") + 1)]) {
389
+ if (value === "")
390
+ continue;
391
+ const candidate = NodePath.resolve(lexicalRoot, value);
392
+ // A directory counts: `node <dir>` runs `<dir>/index.js` or its package main.
393
+ if (exists(candidate) && inWorkspace(candidate)) {
394
+ return failure("permission_denied", `Language server argument names ${candidate}, a path inside the workspace ${lexicalRoot}`);
395
+ }
396
+ }
397
+ }
398
+ return undefined;
399
+ };
400
+ const digestOf = (text) => createHash("sha256").update(text).digest("hex");
401
+ const makeClient = (config) => Effect.gen(function* () {
402
+ const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
403
+ const timeoutMs = config.timeoutMs ?? 30_000;
404
+ const settleMs = config.settleMs ?? DEFAULT_SETTLE_MS;
405
+ const quietMs = config.quietMs ?? DEFAULT_QUIET_MS;
406
+ const env = ChildProcessEnvironment.make(process.env, config.environment);
407
+ const refused = yield* Effect.sync(() => workspaceProgram(config, env.PATH));
408
+ if (refused !== undefined)
409
+ return yield* Effect.fail(refused);
410
+ // The process's stdin is fed from this queue for the client's lifetime, so
411
+ // each request is one offered frame and the pipe never closes between them.
412
+ const input = yield* Queue.bounded(MAX_QUEUED_FRAMES);
413
+ const handle = yield* spawner.spawn(ChildProcess.make(config.command, config.args ?? [], {
414
+ cwd: config.cwd,
415
+ env,
416
+ extendEnv: false,
417
+ stdin: { stream: Stream.fromQueue(input), endOnDone: false }
418
+ })).pipe(Effect.mapError((error) => failure("provider_unavailable", `Language server process could not be started: ${error.message}`)));
419
+ const pending = new Map();
420
+ const decoder = makeFrameDecoder();
421
+ let nextId = 1;
422
+ let terminalError;
423
+ // Keep draining stderr while requests run. Copy retained bytes so a small
424
+ // tail never holds a larger backing buffer alive.
425
+ const maximumStderrBytes = 64 * 1024;
426
+ let stderrTail = new Uint8Array(0);
427
+ const stderrFiber = yield* handle.stderr.pipe(Stream.runForEach((chunk) => Effect.sync(() => {
428
+ stderrTail = chunk.byteLength >= maximumStderrBytes
429
+ ? chunk.slice(-maximumStderrBytes)
430
+ : concatenate(stderrTail.slice(Math.max(0, stderrTail.byteLength + chunk.byteLength - maximumStderrBytes)), chunk);
431
+ })), Effect.catch((cause) => Effect.logWarning("Language server stderr stream failed", cause)), Effect.forkScoped({ startImmediately: true }));
432
+ const stderr = () => {
433
+ let start = 0;
434
+ while (start < stderrTail.byteLength && start < 3 && (stderrTail[start] & 0b1100_0000) === 0b1000_0000)
435
+ start++;
436
+ return new TextDecoder().decode(stderrTail.subarray(start));
437
+ };
438
+ const failPending = (error) => Effect.flatMap(Effect.sync(() => {
439
+ const deferreds = [...pending.values()];
440
+ pending.clear();
441
+ return deferreds;
442
+ }), (deferreds) => Effect.forEach(deferreds, (deferred) => Deferred.fail(deferred, error), { discard: true }));
443
+ const failRequest = (id, error) => {
444
+ const deferred = pending.get(id);
445
+ if (deferred === undefined)
446
+ return Effect.void;
447
+ pending.delete(id);
448
+ return Deferred.fail(deferred, error).pipe(Effect.asVoid);
449
+ };
450
+ const closeWith = (error) => Effect.gen(function* () {
451
+ // stdout EOF and process exit can arrive before the last stderr chunk.
452
+ // A bounded grace also handles servers that close stdout but stay alive.
453
+ yield* Fiber.await(stderrFiber).pipe(Effect.timeoutOption(100));
454
+ terminalError ??= error;
455
+ yield* failPending(terminalError);
456
+ });
457
+ const uriOf = (path) => pathToFileURL(NodePath.resolve(config.cwd, path)).href;
458
+ const documents = new Map();
459
+ // Versions keep climbing across a close and reopen, so a late publish for
460
+ // the closed text never passes for the reopened one.
461
+ const versions = new Map();
462
+ const published = new Map();
463
+ const listeners = new Map();
464
+ let publishSequence = 0;
465
+ let pullUnsupported = false;
466
+ let pullSupported = false;
467
+ let versionedPublishes = false;
468
+ let barrierAnswered = true;
469
+ const publish = (params) => {
470
+ const notification = asMessage(params);
471
+ if (typeof notification?.uri !== "string" || !Array.isArray(notification.diagnostics))
472
+ return Effect.void;
473
+ const uri = notification.uri;
474
+ const version = typeof notification.version === "number" ? notification.version : undefined;
475
+ if (version !== undefined)
476
+ versionedPublishes = true;
477
+ const previous = published.get(uri)?.version;
478
+ // A late publish for an older version never replaces a newer one.
479
+ if (version !== undefined && previous !== undefined && version < previous)
480
+ return Effect.void;
481
+ published.set(uri, {
482
+ version,
483
+ sequence: ++publishSequence,
484
+ diagnostics: notification.diagnostics
485
+ });
486
+ const waiting = listeners.get(uri);
487
+ if (waiting === undefined)
488
+ return Effect.void;
489
+ listeners.delete(uri);
490
+ return Effect.forEach(waiting, (listener) => Deferred.succeed(listener, undefined), { discard: true });
491
+ };
492
+ const receive = (value) => {
493
+ const message = asMessage(value);
494
+ if (message?.method === "textDocument/publishDiagnostics")
495
+ return publish(message.params);
496
+ if (message === undefined || typeof message.id !== "number")
497
+ return Effect.void;
498
+ const deferred = pending.get(message.id);
499
+ if (deferred === undefined)
500
+ return Effect.void;
501
+ pending.delete(message.id);
502
+ if (message.error === undefined)
503
+ return Deferred.succeed(deferred, message.result);
504
+ const error = asMessage(message.error);
505
+ return Deferred.fail(deferred, new StdError.StdError({
506
+ code: "request_failed",
507
+ message: typeof error?.message === "string" ? error.message : "Language server returned a JSON-RPC error",
508
+ ...(typeof error?.code === "number" && typeof error.message === "string"
509
+ ? {
510
+ rpcError: {
511
+ code: error.code,
512
+ message: error.message,
513
+ ...(error.data === undefined ? {} : { data: error.data })
514
+ }
515
+ }
516
+ : {})
517
+ }));
518
+ };
519
+ const receiveFrame = (event) => event._tag === "Message"
520
+ ? receive(event.value)
521
+ // A rejected frame has no trustworthy response id. Failing every
522
+ // waiter prevents another request from hanging behind corrupt framing.
523
+ : event.id === undefined
524
+ ? failPending(event.error)
525
+ : failRequest(event.id, event.error);
526
+ yield* handle.stdout.pipe(Stream.runForEach((chunk) => Effect.forEach(decoder.push(chunk), receiveFrame, { discard: true })), Effect.matchEffect({
527
+ onFailure: () => closeWith(failure("request_failed", "Language server output stream failed")),
528
+ onSuccess: () => closeWith(failure("request_failed", "Language server output stream closed"))
529
+ }), Effect.forkScoped({ startImmediately: true }));
530
+ yield* handle.exitCode.pipe(Effect.flatMap((exitCode) => closeWith(failure("request_failed", `Language server process exited with code ${exitCode}`))), Effect.catch(() => closeWith(failure("request_failed", "Language server process exited"))), Effect.forkScoped({ startImmediately: true }));
531
+ const send = (message) => Effect.suspend(() => terminalError === undefined
532
+ ? Queue.offer(input, frame(message)).pipe(Effect.asVoid, Effect.timeout(timeoutMs), Effect.mapError(() => failure("timeout", `Language server stdin is not being drained; frame offer exceeded ${timeoutMs}ms`)))
533
+ : Effect.fail(terminalError));
534
+ const request = (method, params) => Effect.gen(function* () {
535
+ const deferred = yield* Deferred.make();
536
+ const registered = yield* Effect.sync(() => {
537
+ if (terminalError !== undefined)
538
+ return terminalError;
539
+ if (pending.size >= MAX_PENDING_REQUESTS) {
540
+ return failure("request_failed", `Language server reached the ${MAX_PENDING_REQUESTS} pending-request cap`);
541
+ }
542
+ const id = nextId++;
543
+ pending.set(id, deferred);
544
+ return id;
545
+ });
546
+ if (registered instanceof StdError.StdError)
547
+ return yield* Effect.fail(registered);
548
+ const id = registered;
549
+ return yield* Effect.gen(function* () {
550
+ yield* send({ jsonrpc: "2.0", id, method, params });
551
+ return yield* Deferred.await(deferred).pipe(Effect.timeout(timeoutMs), Effect.mapError((cause) => cause instanceof StdError.StdError
552
+ ? cause
553
+ : failure("timeout", `Language server request timed out: ${method}`)));
554
+ }).pipe(Effect.ensuring(Effect.sync(() => {
555
+ pending.delete(id);
556
+ })));
557
+ }).pipe(Effect.mapError((error) => new StdError.StdError({
558
+ ...error,
559
+ method,
560
+ message: error.rpcError === undefined ? error.message : `${method}: ${error.message}`,
561
+ ...(stderrTail.byteLength === 0 ? {} : { stderr: stderr() })
562
+ })));
563
+ const notify = (method, params) => send({ jsonrpc: "2.0", method, params });
564
+ yield* request("initialize", {
565
+ processId: null,
566
+ rootUri: pathToFileURL(config.cwd).href,
567
+ capabilities: {
568
+ textDocument: {
569
+ synchronization: { dynamicRegistration: false },
570
+ publishDiagnostics: { versionSupport: true },
571
+ diagnostic: { dynamicRegistration: false }
572
+ }
573
+ },
574
+ ...(config.initializationOptions === undefined ? {} : { initializationOptions: config.initializationOptions })
575
+ });
576
+ yield* notify("initialized", {});
577
+ const positionParams = (position) => ({
578
+ textDocument: { uri: uriOf(position.path) },
579
+ position: { line: position.line, character: position.character }
580
+ });
581
+ // A publish without a version is read by arrival: it counts for the text
582
+ // sent before it. Before each sync, a request the server answers at once
583
+ // drains what it wrote earlier, such as the empty report
584
+ // typescript-language-server publishes when a file closes, so that report
585
+ // never passes for the reopened text. Unneeded once the server has pulled
586
+ // or versioned a publish, and dropped if the server does not answer it.
587
+ const barrier = Effect.suspend(() => pullSupported || versionedPublishes || !barrierAnswered
588
+ ? Effect.void
589
+ : request(BARRIER_METHOD, null).pipe(Effect.timeoutOption(Math.min(BARRIER_TIMEOUT_MS, timeoutMs)), Effect.flatMap((answer) => Effect.sync(() => {
590
+ if (Option.isNone(answer))
591
+ barrierAnswered = false;
592
+ })),
593
+ // The answer is MethodNotFound; any answer drains what came before it.
594
+ Effect.ignore));
595
+ // One sync at a time, so versions reach the server in the order they are numbered.
596
+ const syncLock = yield* Semaphore.make(1);
597
+ const sync = (path, text) => syncLock.withPermit(Effect.andThen(barrier, () => {
598
+ const uri = uriOf(path);
599
+ const open = documents.get(uri);
600
+ const version = (versions.get(uri) ?? 0) + 1;
601
+ const sentAt = publishSequence;
602
+ const message = open === undefined
603
+ ? notify("textDocument/didOpen", {
604
+ textDocument: { uri, languageId: languageId(path), version, text }
605
+ })
606
+ : notify("textDocument/didChange", { textDocument: { uri, version }, contentChanges: [{ text }] });
607
+ return message.pipe(Effect.tap(() => Effect.sync(() => {
608
+ versions.set(uri, version);
609
+ documents.set(uri, { version, sentAt, digest: digestOf(text) });
610
+ })));
611
+ }));
612
+ const closeUri = (uri) => Effect.suspend(() => {
613
+ if (!documents.has(uri))
614
+ return Effect.void;
615
+ documents.delete(uri);
616
+ published.delete(uri);
617
+ return notify("textDocument/didClose", { textDocument: { uri } });
618
+ });
619
+ const close = (path) => syncLock.withPermit(closeUri(uriOf(path)));
620
+ // Re-reads every open document: a file changed on disk is resent, and a
621
+ // file that is gone is closed. What changed it (a shell command, say) is
622
+ // not something the server can see.
623
+ const refresh = Effect.suspend(() => Effect.forEach([...documents], ([uri, open]) => {
624
+ const path = fileURLToPath(uri);
625
+ let text;
626
+ try {
627
+ text = NodeFs.readFileSync(path, "utf8");
628
+ }
629
+ catch {
630
+ text = undefined;
631
+ }
632
+ if (text === undefined)
633
+ return syncLock.withPermit(closeUri(uri));
634
+ return digestOf(text) === open.digest ? Effect.void : sync(path, text);
635
+ }, { discard: true }));
636
+ /** What the server published for the document's latest synced text, if it has. */
637
+ const current = (uri) => {
638
+ const entry = published.get(uri);
639
+ const open = documents.get(uri);
640
+ if (entry === undefined || open === undefined)
641
+ return undefined;
642
+ const fresh = entry.version === undefined ? entry.sequence > open.sentAt : entry.version >= open.version;
643
+ return fresh ? entry : undefined;
644
+ };
645
+ /** The first publish for the latest synced text whose sequence is past `after`. */
646
+ const awaitPublished = (uri, after = 0) => Effect.suspend(() => {
647
+ const entry = current(uri);
648
+ if (entry !== undefined && entry.sequence > after)
649
+ return Effect.succeed(entry);
650
+ return Effect.flatMap(Deferred.make(), (listener) => {
651
+ const waiting = listeners.get(uri) ?? new Set();
652
+ waiting.add(listener);
653
+ listeners.set(uri, waiting);
654
+ return Deferred.await(listener).pipe(Effect.ensuring(Effect.sync(() => {
655
+ listeners.get(uri)?.delete(listener);
656
+ })), Effect.flatMap(() => awaitPublished(uri, after)));
657
+ });
658
+ });
659
+ const pushedDiagnostics = (path) => Effect.gen(function* () {
660
+ const uri = uriOf(path);
661
+ if (!documents.has(uri)) {
662
+ // A push-only server publishes only for open documents.
663
+ const text = yield* Effect.try({
664
+ try: () => NodeFs.readFileSync(NodePath.resolve(config.cwd, path), "utf8"),
665
+ catch: () => new StdError.StdError({ code: "not_found", message: `File not found: ${path}`, path })
666
+ });
667
+ yield* sync(path, text);
668
+ }
669
+ const started = yield* Clock.currentTimeMillis;
670
+ const entry = yield* awaitPublished(uri).pipe(Effect.timeoutOption(settleMs));
671
+ if (Option.isNone(entry)) {
672
+ return yield* Effect.fail(new StdError.StdError({
673
+ code: "timeout",
674
+ message: `Language server published no diagnostics for ${path} within ${settleMs}ms`,
675
+ method: "textDocument/publishDiagnostics",
676
+ path
677
+ }));
678
+ }
679
+ // A later publish within the quiet window supersedes this one.
680
+ let latest = entry.value;
681
+ for (;;) {
682
+ const remaining = settleMs - ((yield* Clock.currentTimeMillis) - started);
683
+ if (remaining <= 0)
684
+ break;
685
+ const next = yield* awaitPublished(uri, latest.sequence).pipe(Effect.timeoutOption(Math.min(quietMs, remaining)));
686
+ if (Option.isNone(next))
687
+ break;
688
+ latest = next.value;
689
+ }
690
+ return { kind: "full", items: latest.diagnostics };
691
+ });
692
+ const diagnostics = (path) => pullUnsupported
693
+ ? pushedDiagnostics(path)
694
+ : request("textDocument/diagnostic", { textDocument: { uri: uriOf(path) } }).pipe(Effect.tap(() => Effect.sync(() => {
695
+ pullSupported = true;
696
+ })), Effect.catchIf((error) => error.rpcError?.code === METHOD_NOT_FOUND, () => {
697
+ pullUnsupported = true;
698
+ return pushedDiagnostics(path);
699
+ }));
700
+ const prepareCallHierarchy = (position) => request("textDocument/prepareCallHierarchy", positionParams(position));
701
+ const callHierarchy = (method, position) => prepareCallHierarchy(position).pipe(Effect.flatMap((prepared) => {
702
+ const item = firstCallHierarchyItem(prepared);
703
+ return item === undefined ? Effect.succeed([]) : request(method, { item });
704
+ }));
705
+ return LanguageServer.make({
706
+ hover: (position) => request("textDocument/hover", positionParams(position)),
707
+ definition: (position) => request("textDocument/definition", positionParams(position)),
708
+ references: (position) => request("textDocument/references", {
709
+ ...positionParams(position),
710
+ context: { includeDeclaration: true }
711
+ }),
712
+ implementation: (position) => request("textDocument/implementation", positionParams(position)),
713
+ documentSymbols: (path) => request("textDocument/documentSymbol", { textDocument: { uri: uriOf(path) } }),
714
+ workspaceSymbols: (query) => request("workspace/symbol", { query }),
715
+ prepareCallHierarchy,
716
+ callHierarchyIncoming: (position) => callHierarchy("callHierarchy/incomingCalls", position),
717
+ callHierarchyOutgoing: (position) => callHierarchy("callHierarchy/outgoingCalls", position),
718
+ diagnostics,
719
+ sync,
720
+ close,
721
+ refresh
722
+ });
723
+ });
724
+ const normalizeExtension = (extension) => (extension.startsWith(".") ? extension : `.${extension}`).toLowerCase();
725
+ /**
726
+ * Routes each request to the client for its file's extension. `client`
727
+ * starts, or returns, the client at an index; `started` is that client only
728
+ * if it already runs, so `refresh` never starts a server.
729
+ */
730
+ const routed = (configs, client, started) => {
731
+ const claims = configs.map((entry) => entry.extensions?.map(normalizeExtension));
732
+ const fallback = claims.findIndex((claimed) => claimed === undefined);
733
+ const indexOf = (path) => {
734
+ const extension = extensionOf(path);
735
+ const claimed = claims.findIndex((entry) => entry?.includes(extension) === true);
736
+ const index = claimed >= 0 ? claimed : fallback;
737
+ return index >= 0
738
+ ? Effect.succeed(index)
739
+ : Effect.fail(new StdError.StdError({
740
+ code: "unsupported",
741
+ message: `No language server is configured for ${extension || "extensionless"} files`,
742
+ path
743
+ }));
744
+ };
745
+ const route = (path) => Effect.flatMap(indexOf(path), client);
746
+ const byPosition = (method) => (position) => Effect.flatMap(route(position.path), (server) => server[method](position));
747
+ const indices = configs.map((_, index) => index);
748
+ return LanguageServer.make({
749
+ hover: byPosition("hover"),
750
+ definition: byPosition("definition"),
751
+ references: byPosition("references"),
752
+ implementation: byPosition("implementation"),
753
+ prepareCallHierarchy: byPosition("prepareCallHierarchy"),
754
+ callHierarchyIncoming: byPosition("callHierarchyIncoming"),
755
+ callHierarchyOutgoing: byPosition("callHierarchyOutgoing"),
756
+ documentSymbols: (path) => Effect.flatMap(route(path), (server) => server.documentSymbols(path)),
757
+ diagnostics: (path) => Effect.flatMap(route(path), (server) => server.diagnostics(path)),
758
+ sync: (path, text) => Effect.flatMap(route(path), (server) => server.sync(path, text)),
759
+ // A server that never started holds no open file.
760
+ close: (path) => Effect.flatMap(indexOf(path), (index) => started(index)?.close(path) ?? Effect.void),
761
+ refresh: Effect.suspend(() => Effect.forEach(indices, (index) => started(index)?.refresh ?? Effect.void, { discard: true })),
762
+ workspaceSymbols: (query) => configs.length === 1 ?
763
+ Effect.flatMap(client(0), (server) => server.workspaceSymbols(query)) :
764
+ Effect.forEach(indices, (index) => Effect.flatMap(client(index), (server) => server.workspaceSymbols(query)), { concurrency: "unbounded" }).pipe(Effect.map((answers) => answers.flatMap((answer) => Array.isArray(answer) ? answer : answer == null ? [] : [answer])))
765
+ });
766
+ };
767
+ const configList = (config) => {
768
+ const configs = Array.isArray(config) ? config : [config];
769
+ return configs.length === 0
770
+ ? Effect.fail(failure("invalid_input", "At least one language server must be configured"))
771
+ : Effect.succeed(configs);
772
+ };
773
+ /**
774
+ * Constructs scoped host language-server clients, one process per config, and
775
+ * routes each file to the server whose `extensions` include its extension, or
776
+ * else to the server that declares none. `workspaceSymbols` asks every server
777
+ * and concatenates their answers.
778
+ *
779
+ * Every client opens a file on its first `sync` and sends the full text on
780
+ * each later one. `diagnostics` pulls `textDocument/diagnostic`; a server that
781
+ * answers `MethodNotFound` is read from its `textDocument/publishDiagnostics`
782
+ * notifications instead, waiting up to `settleMs` for the latest synced text.
783
+ *
784
+ * Fails with `permission_denied`, before spawning, when the resolved program or
785
+ * a file or directory named by an argument lies under `config.cwd`, or when the command is a
786
+ * launcher (a shell, `env`, a package runner such as `npx` or `pnpm`, or `node`
787
+ * and `bun` given inline code or a preload) whose arguments choose what runs.
788
+ *
789
+ * @category constructors
790
+ * @since 1.0.0
791
+ */
792
+ export const make = (config) => Effect.gen(function* () {
793
+ const configs = yield* configList(config);
794
+ const clients = yield* Effect.forEach(configs, makeClient);
795
+ return routed(configs, (index) => Effect.succeed(clients[index]), (index) => clients[index]);
796
+ });
797
+ /**
798
+ * {@link make}, starting each server when the first request for one of its
799
+ * files arrives rather than up front, so a host can bind servers it may never
800
+ * need. A server starts with the services and authority of the fiber that
801
+ * built this service, not those of the request that first needs it. A server
802
+ * that fails to start fails that request and every later one for its files.
803
+ * `refresh` and `close` never start a server.
804
+ *
805
+ * The workspace-program refusals of {@link make} still apply up front.
806
+ *
807
+ * @category constructors
808
+ * @since 1.0.0
809
+ */
810
+ export const makeLazy = (config) => Effect.gen(function* () {
811
+ const configs = yield* configList(config);
812
+ for (const entry of configs) {
813
+ const refused = workspaceProgram(entry, ChildProcessEnvironment.make(process.env, entry.environment).PATH);
814
+ if (refused !== undefined)
815
+ return yield* Effect.fail(refused);
816
+ }
817
+ const clients = configs.map(() => undefined);
818
+ // Each server starts in a fiber forked here, so it starts with the
819
+ // services and authority of whoever built this service, never those of
820
+ // the request that first needs it, and lives as long as this scope.
821
+ const starts = yield* Effect.forEach(configs, (entry, index) => Effect.gen(function* () {
822
+ const wanted = yield* Deferred.make();
823
+ const ready = yield* Deferred.make();
824
+ yield* Deferred.await(wanted).pipe(Effect.andThen(makeClient(entry)), Effect.tap((client) => Effect.sync(() => void (clients[index] = client))), Effect.exit, Effect.flatMap((exit) => Deferred.done(ready, exit)), Effect.forkScoped({ startImmediately: true }));
825
+ return Deferred.succeed(wanted, undefined).pipe(Effect.andThen(Deferred.await(ready)));
826
+ }));
827
+ return routed(configs, (index) => starts[index], (index) => clients[index]);
828
+ });
829
+ /**
830
+ * Provides a scoped host language-server implementation.
831
+ *
832
+ * @category layers
833
+ * @since 1.0.0
834
+ */
835
+ export const layer = (config) => Layer.effect(LanguageServer.LanguageServer, make(config));
836
+ /**
837
+ * Provides {@link makeLazy}.
838
+ *
839
+ * @category layers
840
+ * @since 1.0.0
841
+ */
842
+ export const layerLazy = (config) => Layer.effect(LanguageServer.LanguageServer, makeLazy(config));
843
+ //# sourceMappingURL=NodeLanguageServer.js.map