@smthrs/std 0.0.0-stage → 1.0.0-rc.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.
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 +304 -0
  9. package/dist/cjs/Bash.d.ts.map +1 -0
  10. package/dist/cjs/Bash.js +321 -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 +98 -0
  173. package/dist/cjs/internal/GitWorktree.d.ts.map +1 -0
  174. package/dist/cjs/internal/GitWorktree.js +270 -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 +304 -0
  246. package/dist/esm/Bash.d.ts.map +1 -0
  247. package/dist/esm/Bash.js +469 -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 +98 -0
  410. package/dist/esm/internal/GitWorktree.d.ts.map +1 -0
  411. package/dist/esm/internal/GitWorktree.js +345 -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 +549 -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 +473 -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,209 @@
1
+ /**
2
+ * Shared HTTP response limits, error mapping, and request deadlines.
3
+ *
4
+ * @since 1.0.0
5
+ */
6
+
7
+ import type { GrantStore } from "@smthrs/kernel/GrantStore"
8
+ import * as HttpClient from "@smthrs/kernel/HttpClient"
9
+ import * as Effect from "effect/Effect"
10
+ import * as Schema from "effect/Schema"
11
+ import * as Stream from "effect/Stream"
12
+ import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
13
+ import * as StdError from "../StdError.ts"
14
+ import { guarded, refusal } from "./HttpNetwork.ts"
15
+ import { MAX_OUTPUT_BYTES, notice, truncateBytes } from "./Text.ts"
16
+ import { parseHttpUrl } from "./Url.ts"
17
+
18
+ /**
19
+ * Maximum captured response bytes before decoding.
20
+ *
21
+ * @category http
22
+ * @since 1.0.0
23
+ */
24
+ export const MAX_RESPONSE_BYTES = 5 * 1024 * 1024
25
+
26
+ interface BodyState {
27
+ readonly chunks: Array<Uint8Array>
28
+ size: number
29
+ }
30
+
31
+ /**
32
+ * Reads a response up to the shared byte limit and finalizes the stream on failure.
33
+ *
34
+ * @category http
35
+ * @since 1.0.0
36
+ */
37
+ export const readBounded = <E, R>(
38
+ stream: Stream.Stream<Uint8Array, E, R>,
39
+ url: string
40
+ ): Effect.Effect<Uint8Array, E | StdError.StdError, R> =>
41
+ Stream.runFoldEffect(
42
+ stream,
43
+ (): BodyState => ({ chunks: [], size: 0 }),
44
+ (state, chunk) => {
45
+ const size = state.size + chunk.byteLength
46
+ if (size > MAX_RESPONSE_BYTES) {
47
+ return Effect.fail(
48
+ new StdError.StdError({
49
+ code: "response_too_large",
50
+ message: "Response exceeds the 5 MiB limit",
51
+ path: url
52
+ })
53
+ )
54
+ }
55
+ state.chunks.push(chunk)
56
+ state.size = size
57
+ return Effect.succeed(state)
58
+ }
59
+ ).pipe(
60
+ Effect.map((state) => {
61
+ const output = new Uint8Array(state.size)
62
+ let offset = 0
63
+ for (const chunk of state.chunks) {
64
+ output.set(chunk, offset)
65
+ offset += chunk.byteLength
66
+ }
67
+ return output
68
+ })
69
+ )
70
+
71
+ /**
72
+ * Maps transport failures while preserving standard HTTP failure codes.
73
+ *
74
+ * @category http
75
+ * @since 1.0.0
76
+ */
77
+ export const requestError = (url: string, error: unknown): StdError.StdError =>
78
+ error instanceof StdError.StdError ? error : refusal(error) ?? new StdError.StdError({
79
+ code: "request_failed",
80
+ message: `Request failed: ${url}${error instanceof Error ? ` (${error.message})` : ""}`
81
+ })
82
+
83
+ /**
84
+ * Looks up a response header without depending on transport normalization.
85
+ *
86
+ * @category http
87
+ * @since 1.0.0
88
+ */
89
+ export const header = (headers: Readonly<Record<string, string | undefined>>, name: string): string | undefined => {
90
+ const lower = name.toLowerCase()
91
+ return Object.entries(headers).find(([key]) => key.toLowerCase() === lower)?.[1]
92
+ }
93
+
94
+ /**
95
+ * Seconds; the runtime caps valid overrides at 120.
96
+ *
97
+ * @category http
98
+ * @since 1.0.0
99
+ */
100
+ export const Timeout = Schema.Number.check(Schema.isFinite(), Schema.isGreaterThan(0))
101
+
102
+ /**
103
+ * Bounds the entire request and body read with one timer. Interruption reaches
104
+ * HttpClient.execute and response.stream so Effect aborts the transport and
105
+ * finalizes the body reader before returning the timeout failure.
106
+ * `timeoutError` preserves a tool's own timeout message while sharing the
107
+ * validation, duration cap, and interruption behavior.
108
+ *
109
+ * @category http
110
+ * @since 1.0.0
111
+ */
112
+ export const withDeadline = <A, E, R>(
113
+ effect: Effect.Effect<A, E, R>,
114
+ url: string,
115
+ timeout = 30,
116
+ timeoutError?: (seconds: number) => StdError.StdError
117
+ ): Effect.Effect<A, E | StdError.StdError, R> => {
118
+ if (!Schema.is(Timeout)(timeout)) {
119
+ return Effect.fail(
120
+ new StdError.StdError({
121
+ code: "invalid_input",
122
+ message: "Timeout must be a finite number greater than zero seconds",
123
+ path: url
124
+ })
125
+ )
126
+ }
127
+ const seconds = Math.min(timeout, 120)
128
+ return Effect.timeoutOrElse(effect, {
129
+ duration: seconds * 1_000,
130
+ orElse: () =>
131
+ Effect.fail(
132
+ timeoutError?.(seconds) ?? new StdError.StdError({
133
+ code: "timeout",
134
+ message: `Request timed out after ${seconds} seconds`,
135
+ path: url
136
+ })
137
+ )
138
+ })
139
+ }
140
+
141
+ /**
142
+ * Keeps the head of rendered response text within the shared output budget and
143
+ * discloses the cut.
144
+ *
145
+ * @since 1.0.0
146
+ * @private
147
+ */
148
+ export const capOutput = (
149
+ text: string
150
+ ): { readonly text: string; readonly truncated: boolean; readonly notice?: string } => {
151
+ const rendered = truncateBytes(text, MAX_OUTPUT_BYTES, { keep: "head" })
152
+ return {
153
+ text: rendered.text,
154
+ truncated: rendered.truncated,
155
+ ...(rendered.truncated
156
+ ? { notice: notice("bytes", rendered.keptBytes, rendered.keptBytes + rendered.droppedBytes) }
157
+ : {})
158
+ }
159
+ }
160
+
161
+ /** Shared response contract for the GET and POST tools.
162
+ * @since 1.0.0
163
+ * @private
164
+ */
165
+ export const Response = Schema.Struct({
166
+ status: Schema.Number.annotate({ description: "HTTP status code, including error statuses" }),
167
+ body: Schema.String.annotate({ description: "Response body as text" }),
168
+ truncated: Schema.Boolean.annotate({ description: "Whether the body exceeded the display budget" }),
169
+ notice: Schema.optional(Schema.String.annotate({ description: "Truncation disclosure" }))
170
+ })
171
+
172
+ /** Validate, execute, and render one bounded HTTP request.
173
+ * @since 1.0.0
174
+ * @private
175
+ */
176
+ export const execute = Effect.fn("Http.execute")(function*(
177
+ input: {
178
+ readonly url: string
179
+ readonly headers?: Readonly<Record<string, string>> | undefined
180
+ readonly timeout?: number | undefined
181
+ },
182
+ makeRequest: (url: string) => HttpClientRequest.HttpClientRequest
183
+ ): Effect.fn.Return<typeof Response.Type, StdError.StdError, HttpClient.HttpClient | GrantStore> {
184
+ const url = parseHttpUrl(input.url)
185
+ if (url === undefined) {
186
+ return yield* Effect.fail(
187
+ new StdError.StdError({
188
+ code: "invalid_input",
189
+ message: `URL must use http or https without user information: ${input.url}`,
190
+ path: input.url
191
+ })
192
+ )
193
+ }
194
+ const client = guarded(yield* HttpClient.HttpClient)
195
+ const request = makeRequest(url.toString())
196
+ const { status, bytes } = yield* withDeadline(
197
+ Effect.gen(function*() {
198
+ const response = yield* client.execute(
199
+ input.headers === undefined ? request : HttpClientRequest.setHeaders(request, input.headers)
200
+ )
201
+ const bytes = yield* readBounded(response.stream, input.url)
202
+ return { status: response.status, bytes }
203
+ }).pipe(Effect.mapError((error) => requestError(input.url, error))),
204
+ input.url,
205
+ input.timeout
206
+ )
207
+ const { text, ...disclosure } = capOutput(new TextDecoder().decode(bytes))
208
+ return { status, body: text, ...disclosure }
209
+ })
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Destination policy shared by the web tools, including every redirect hop.
3
+ *
4
+ * @since 1.0.0
5
+ */
6
+
7
+ import * as Capability from "@smthrs/capability/Capability"
8
+ import { GrantStore } from "@smthrs/kernel/GrantStore"
9
+ import {
10
+ authorizePreflight,
11
+ Destination,
12
+ fromHttpClientError,
13
+ supportsDestinationPinning
14
+ } from "@smthrs/kernel/HttpClient"
15
+ import { Context, Effect, Option } from "effect"
16
+ import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient"
17
+ import * as HttpClient from "effect/unstable/http/HttpClient"
18
+ import * as HttpClientError from "effect/unstable/http/HttpClientError"
19
+ import { lookup } from "node:dns/promises"
20
+ import { BlockList, isIP } from "node:net"
21
+ import * as StdError from "../StdError.ts"
22
+ import { parseHttpUrl } from "./Url.ts"
23
+
24
+ /** Resolver seam: all addresses must be public before an unprivileged request.
25
+ * @since 1.0.0
26
+ * @private
27
+ */
28
+ export const ResolveHost = Context.Reference<
29
+ (hostname: string) => Effect.Effect<ReadonlyArray<string>, unknown>
30
+ >("@smthrs/std/HttpNetwork/ResolveHost", {
31
+ defaultValue: () => (hostname) =>
32
+ Effect.tryPromise(async () => (await lookup(hostname, { all: true })).map((a) => a.address))
33
+ })
34
+
35
+ const blocked = new BlockList()
36
+ for (
37
+ const [address, prefix] of [
38
+ ["0.0.0.0", 8],
39
+ ["10.0.0.0", 8],
40
+ ["127.0.0.0", 8],
41
+ ["169.254.0.0", 16],
42
+ ["172.16.0.0", 12],
43
+ ["192.168.0.0", 16],
44
+ ["192.0.0.0", 24],
45
+ ["100.64.0.0", 10],
46
+ ["198.18.0.0", 15],
47
+ ["224.0.0.0", 4],
48
+ ["240.0.0.0", 4]
49
+ ] as const
50
+ ) blocked.addSubnet(address, prefix, "ipv4")
51
+ // Allow global IPv6 and mapped IPv4 only, excluding transition tunnels.
52
+ const publicV6 = new BlockList()
53
+ publicV6.addSubnet("2000::", 3, "ipv6")
54
+ publicV6.addSubnet("::ffff:0:0", 96, "ipv6")
55
+ blocked.addSubnet("2002::", 16, "ipv6")
56
+ blocked.addSubnet("2001::", 32, "ipv6")
57
+
58
+ const isPublic = (address: string): boolean => {
59
+ const family = isIP(address)
60
+ if (family === 4) return !blocked.check(address, "ipv4")
61
+ return family === 6 && publicV6.check(address, "ipv6") && !blocked.check(address, "ipv6")
62
+ }
63
+
64
+ const failure = (code: StdError.Code, message: string, path: string) => new StdError.StdError({ code, message, path })
65
+
66
+ const check = Effect.fn("HttpNetwork.check")(function*(value: string, client: HttpClient.HttpClient) {
67
+ const url = parseHttpUrl(value)
68
+ if (url === undefined) {
69
+ return yield* Effect.fail(failure("invalid_input", "URL must use http or https without user information", value))
70
+ }
71
+ if (!supportsDestinationPinning(client)) {
72
+ return yield* Effect.fail(failure("unsupported", "HTTP host must support destination pinning", value))
73
+ }
74
+ const hostname = url.hostname.replace(/^\[|\]$/g, "")
75
+ const local = hostname.replace(/\.$/, "").toLowerCase()
76
+ const literal = isIP(hostname) !== 0
77
+ const localhost = local === "localhost" || local.endsWith(".localhost")
78
+ const resolve = yield* ResolveHost
79
+ // Refuse localhost before DNS unless the origin is explicitly authorized.
80
+ const privateGrant = Effect.gen(function*() {
81
+ const store = yield* GrantStore
82
+ const capability = yield* Effect.try({
83
+ try: () => Capability.make("net:private", url.origin),
84
+ catch: () => failure("invalid_input", "Private HTTP origin exceeds the capability resource limit", value)
85
+ })
86
+ yield* store.check(capability).pipe(
87
+ Effect.mapError(() =>
88
+ failure("permission_denied", "Private HTTP destination requires a net:private grant", value)
89
+ )
90
+ )
91
+ })
92
+ if (localhost) yield* privateGrant
93
+ const addresses = literal ? [hostname] : [
94
+ ...yield* resolve(hostname).pipe(
95
+ Effect.mapError(() => failure("request_failed", "Could not resolve HTTP destination", value))
96
+ )
97
+ ]
98
+ if (addresses.length === 0 || addresses.some((address) => isIP(address) === 0)) {
99
+ return yield* Effect.fail(failure("request_failed", "HTTP destination has no valid addresses", value))
100
+ }
101
+ if (!localhost && !addresses.every(isPublic)) yield* privateGrant
102
+ return Object.freeze({ origin: url.origin, addresses: Object.freeze(addresses) })
103
+ })
104
+
105
+ /** Decorates the supplied client before following redirects through the guard.
106
+ * The transport must honor manual redirects, as required by the kernel client.
107
+ * @since 1.0.0
108
+ * @private
109
+ */
110
+ export const guarded = (
111
+ client: HttpClient.HttpClient,
112
+ follow = true
113
+ ): HttpClient.HttpClient.With<HttpClientError.HttpClientError, GrantStore> => {
114
+ const checked = HttpClient.transform(
115
+ client,
116
+ (execute, request) =>
117
+ authorizePreflight(
118
+ request,
119
+ check(request.url, client).pipe(
120
+ Effect.mapError((cause) =>
121
+ new HttpClientError.HttpClientError({
122
+ reason: new HttpClientError.TransportError({ request, cause, description: cause.message })
123
+ })
124
+ ),
125
+ Effect.flatMap((destination) =>
126
+ Effect.updateContext(execute, (context: Context.Context<never>) =>
127
+ Context.add(Context.add(context, Destination, destination), FetchHttpClient.RequestInit, {
128
+ ...Context.getOrUndefined(context, FetchHttpClient.RequestInit),
129
+ redirect: "manual"
130
+ }))
131
+ )
132
+ )
133
+ )
134
+ )
135
+ return follow ? HttpClient.followRedirects(checked) : checked
136
+ }
137
+
138
+ /** Recovers the typed refusal carried through Effect's HTTP error channel.
139
+ * @since 1.0.0
140
+ * @private
141
+ */
142
+ export const refusal = (error: unknown): StdError.StdError | undefined => {
143
+ if (!(error instanceof HttpClientError.HttpClientError) || error.reason._tag !== "TransportError") return undefined
144
+ if (error.reason.cause instanceof StdError.StdError) return error.reason.cause
145
+ if (Option.isSome(fromHttpClientError(error))) {
146
+ return failure(
147
+ "permission_denied",
148
+ error.reason.description ?? "HTTP permission was refused",
149
+ error.reason.request.url
150
+ )
151
+ }
152
+ return undefined
153
+ }
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Root-scoped gitignore rules, compiled once per visited directory.
3
+ *
4
+ * @since 1.0.0
5
+ */
6
+
7
+ import { escapeRegex } from "./SearchContract.ts"
8
+
9
+ interface Rule {
10
+ readonly expression: RegExp
11
+ readonly directoryOnly: boolean
12
+ readonly negated: boolean
13
+ readonly byPath: boolean
14
+ }
15
+
16
+ /**
17
+ * Rules belonging to one visited directory.
18
+ *
19
+ * @private
20
+ * @since 1.0.0
21
+ */
22
+ export interface Scope {
23
+ readonly directory: string
24
+ readonly rules: ReadonlyArray<Rule>
25
+ }
26
+
27
+ // Like the search glob contract, rg's globset matches UTF-8 bytes, not code points.
28
+ const bytes = (value: string): string =>
29
+ /[^\x20-\x7e]/.test(value)
30
+ ? Array.from(new TextEncoder().encode(value), (byte) => String.fromCharCode(byte)).join("")
31
+ : value
32
+
33
+ // The caller-glob subset cannot parse ignore files: escapes and classes are
34
+ // intentionally refused there. Keep their richer grammar here, including rg's
35
+ // brace alternatives. Invalid lines are skipped without discarding valid rules.
36
+ const expression = (pattern: string): RegExp => {
37
+ let source = ""
38
+ const groups: Array<{ prefix: string; alternatives: Array<string> }> = []
39
+ for (let index = 0; index < pattern.length; index++) {
40
+ const character = pattern[index]!
41
+ if (character === "\\") {
42
+ if (++index === pattern.length) throw new Error("dangling escape")
43
+ source += escapeRegex(pattern[index]!)
44
+ } else if (character === "[") {
45
+ let end = index + 1
46
+ const negated = pattern[end] === "!" || pattern[end] === "^"
47
+ if (negated) end++
48
+ if (pattern[end] === "]") end++
49
+ end = pattern.indexOf("]", end)
50
+ if (end < 0) source += "\\["
51
+ else {
52
+ const content = pattern.slice(index + (negated ? 2 : 1), end)
53
+ source += `[${negated ? "^" : ""}${content.replace(/[\\[\]^]/g, "\\$&")}]`
54
+ index = end
55
+ }
56
+ } else if (character === "{") {
57
+ groups.push({ prefix: source, alternatives: [] })
58
+ source = ""
59
+ } else if (character === "," && groups.length > 0) {
60
+ groups[groups.length - 1]!.alternatives.push(source)
61
+ source = ""
62
+ } else if (character === "}") {
63
+ const group = groups.pop()
64
+ if (group === undefined) throw new Error("unopened alternatives")
65
+ const alternatives = [...group.alternatives, source].filter((part) => part.length > 0)
66
+ source = group.prefix + (alternatives.length > 0 ? `(?:${alternatives.join("|")})` : "")
67
+ } else if (
68
+ character === "*" && pattern[index + 1] === "*" &&
69
+ (index === 0 || "/{,".includes(pattern[index - 1]!)) &&
70
+ (pattern[index + 2] === undefined || "/},".includes(pattern[index + 2]!))
71
+ ) {
72
+ source += pattern[index + 2] === "/" ? "(?:.*/)?" : ".*"
73
+ index += pattern[index + 2] === "/" ? 2 : 1
74
+ } else if (character === "*") source += "[^/]*"
75
+ else if (character === "?") source += "[^/]"
76
+ else source += escapeRegex(character)
77
+ }
78
+ if (groups.length > 0) throw new Error("unclosed alternatives")
79
+ return new RegExp(`^(?:${source})$`)
80
+ }
81
+
82
+ /**
83
+ * Parses gitignore lines without widening the caller-glob grammar.
84
+ *
85
+ * @private
86
+ * @since 1.0.0
87
+ */
88
+ export const parse = (directory: string, content: string): Scope => {
89
+ const rules: Array<Rule> = []
90
+ for (let line of content.replace(/^\uFEFF/, "").split(/\r?\n/)) {
91
+ if (line.startsWith("#")) continue
92
+ // Match rg's gitignore parser: an escaped final space preserves whitespace.
93
+ if (!line.endsWith("\\ ")) line = line.trimEnd()
94
+ if (line.length === 0) continue
95
+ const negated = line.startsWith("!")
96
+ if (negated) line = line.slice(1)
97
+ const rooted = line.startsWith("/")
98
+ if (rooted) line = line.slice(1)
99
+ const directoryOnly = line.endsWith("/")
100
+ if (directoryOnly) line = line.slice(0, -1).replace(/\\$/, "")
101
+ const byPath = rooted || line.includes("/")
102
+ try {
103
+ rules.push({ expression: expression(bytes(line)), negated, directoryOnly, byPath })
104
+ } catch {
105
+ // rg --no-messages also tolerates malformed rules and unreadable files.
106
+ }
107
+ }
108
+ return { directory, rules }
109
+ }
110
+
111
+ /**
112
+ * Tests an entry before descent; deeper scopes and later rules take priority.
113
+ *
114
+ * @private
115
+ * @since 1.0.0
116
+ */
117
+ export const ignored = (
118
+ scopes: ReadonlyArray<Scope>,
119
+ candidate: string,
120
+ basename: string,
121
+ directory: boolean,
122
+ relative: (from: string, to: string) => string
123
+ ): boolean => {
124
+ // The nearest ignore file wins; within a file, the last matching line wins.
125
+ for (let scopeIndex = scopes.length - 1; scopeIndex >= 0; scopeIndex--) {
126
+ const scope = scopes[scopeIndex]!
127
+ const scoped = bytes(relative(scope.directory, candidate))
128
+ for (let index = scope.rules.length - 1; index >= 0; index--) {
129
+ const rule = scope.rules[index]!
130
+ if (rule.directoryOnly && !directory) continue
131
+ if (rule.expression.test(rule.byPath ? scoped : bytes(basename))) return !rule.negated
132
+ }
133
+ }
134
+ return false
135
+ }
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Thompson matching for the validated ASCII search grammar. Each state is
3
+ * visited once per input position; alternatives never backtrack over input.
4
+ *
5
+ * @since 1.0.0
6
+ */
7
+
8
+ type Term =
9
+ | { readonly kind: "atom"; readonly source: string }
10
+ | { readonly kind: "sequence" | "alternative"; readonly terms: ReadonlyArray<Term> }
11
+ | { readonly kind: "repeat"; readonly term: Term; readonly min: number; readonly max: number }
12
+
13
+ type State =
14
+ | { readonly kind: "atom"; readonly expression: RegExp; readonly next: number }
15
+ | { readonly kind: "start" | "end"; readonly next: number }
16
+ | { readonly kind: "split"; readonly next: ReadonlyArray<number> }
17
+ | { readonly kind: "accept" }
18
+
19
+ /**
20
+ * Compiles an already syntax-validated pattern. Compilation is bounded to
21
+ * 8192 states and 128 nested groups, including expanded counted repetitions.
22
+ * The iterator yields every 4096 state visits so the host can dispatch timers
23
+ * and interruption even for long lines and expensive linear matches.
24
+ *
25
+ * @private
26
+ * @since 1.0.0
27
+ */
28
+ export const compile = (
29
+ pattern: string,
30
+ insensitive: boolean
31
+ ): { readonly test: (line: string) => Generator<void, boolean> } => {
32
+ let offset = 0
33
+ const parse = (depth: number): Term => {
34
+ if (depth > 128) throw new Error("patterns must not exceed 128 nested groups")
35
+ const alternatives: Array<Term> = []
36
+ let sequence: Array<Term> = []
37
+ while (offset < pattern.length && pattern[offset] !== ")") {
38
+ const start = offset
39
+ const character = pattern[offset++]!
40
+ if (character === "|") {
41
+ alternatives.push({ kind: "sequence", terms: sequence })
42
+ sequence = []
43
+ continue
44
+ }
45
+ let term: Term
46
+ if (character === "(") {
47
+ term = parse(depth + 1)
48
+ offset++
49
+ } else {
50
+ if (character === "\\") offset++
51
+ if (character === "[") {
52
+ while (pattern[offset] !== "]") {
53
+ if (pattern[offset++] === "\\") offset++
54
+ }
55
+ offset++
56
+ }
57
+ term = { kind: "atom", source: pattern.slice(start, offset) }
58
+ }
59
+ const quantifier = pattern[offset]
60
+ if (quantifier === "*" || quantifier === "+" || quantifier === "?" || quantifier === "{") {
61
+ offset++
62
+ let min = quantifier === "+" ? 1 : 0
63
+ let max = quantifier === "?" ? 1 : Infinity
64
+ if (quantifier === "{") {
65
+ const end = pattern.indexOf("}", offset)
66
+ const counts = pattern.slice(offset, end).split(",")
67
+ min = Number(counts[0])
68
+ max = counts.length === 1 ? min : counts[1] === "" ? Infinity : Number(counts[1])
69
+ offset = end + 1
70
+ }
71
+ // Greediness affects captures, not whether a line contains a match.
72
+ if (pattern[offset] === "?") offset++
73
+ term = { kind: "repeat", term, min, max }
74
+ }
75
+ sequence.push(term)
76
+ }
77
+ alternatives.push({ kind: "sequence", terms: sequence })
78
+ return { kind: "alternative", terms: alternatives }
79
+ }
80
+ const tree = parse(0)
81
+ const states: Array<State> = [{ kind: "accept" }]
82
+ const append = (state: State): number => {
83
+ if (states.length >= 8192) throw new Error("patterns must not exceed 8192 compiled states")
84
+ states.push(state)
85
+ return states.length - 1
86
+ }
87
+ const build = (term: Term, next: number): number => {
88
+ switch (term.kind) {
89
+ case "atom":
90
+ if (term.source === "^") return append({ kind: "start", next })
91
+ if (term.source === "$") return append({ kind: "end", next })
92
+ return append({
93
+ kind: "atom",
94
+ expression: new RegExp(term.source === "." ? "[^\\n]" : term.source, insensitive ? "iu" : "u"),
95
+ next
96
+ })
97
+ case "sequence": {
98
+ let head = next
99
+ for (let index = term.terms.length - 1; index >= 0; index--) head = build(term.terms[index]!, head)
100
+ return head
101
+ }
102
+ case "alternative":
103
+ return append({ kind: "split", next: term.terms.map((child) => build(child, next)) })
104
+ case "repeat": {
105
+ let head = next
106
+ if (term.max === Infinity) {
107
+ const loop = append({ kind: "split", next: [] })
108
+ states[loop] = { kind: "split", next: [next, build(term.term, loop)] }
109
+ head = loop
110
+ } else {
111
+ for (let index = term.min; index < term.max; index++) {
112
+ head = append({ kind: "split", next: [head, build(term.term, head)] })
113
+ }
114
+ }
115
+ for (let index = 0; index < term.min; index++) head = build(term.term, head)
116
+ return head
117
+ }
118
+ }
119
+ }
120
+ const start = build(tree, 0)
121
+ return {
122
+ *test(line) {
123
+ let current: Array<number> = []
124
+ let position = 0
125
+ let work = 0
126
+ const seen = new Int32Array(states.length)
127
+ let generation = 0
128
+ while (true) {
129
+ generation++
130
+ const pending = [...current, start]
131
+ const consuming: Array<number> = []
132
+ while (pending.length > 0) {
133
+ if (++work === 4096) {
134
+ work = 0
135
+ yield
136
+ }
137
+ const id = pending.pop()!
138
+ if (seen[id] === generation) continue
139
+ seen[id] = generation
140
+ const state = states[id]!
141
+ switch (state.kind) {
142
+ case "accept":
143
+ return true
144
+ case "atom":
145
+ consuming.push(id)
146
+ break
147
+ case "split":
148
+ for (const next of state.next) pending.push(next)
149
+ break
150
+ case "start":
151
+ if (position === 0) pending.push(state.next)
152
+ break
153
+ case "end":
154
+ if (position === line.length) pending.push(state.next)
155
+ break
156
+ }
157
+ }
158
+ if (position === line.length) return false
159
+ const character = String.fromCodePoint(line.codePointAt(position)!)
160
+ position += character.length
161
+ current = []
162
+ for (const id of consuming) {
163
+ if (++work === 4096) {
164
+ work = 0
165
+ yield
166
+ }
167
+ const state = states[id]!
168
+ if (state.kind === "atom" && state.expression.test(character)) current.push(state.next)
169
+ }
170
+ }
171
+ }
172
+ }
173
+ }