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

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 (582) hide show
  1. package/CHANGELOG.md +148 -0
  2. package/LICENSE +21 -0
  3. package/README.md +156 -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 +390 -0
  9. package/dist/cjs/Bash.d.ts.map +1 -0
  10. package/dist/cjs/Bash.js +333 -0
  11. package/dist/cjs/Bash.js.map +7 -0
  12. package/dist/cjs/Checkpoints.d.ts +322 -0
  13. package/dist/cjs/Checkpoints.d.ts.map +1 -0
  14. package/dist/cjs/Checkpoints.js +233 -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 +36 -0
  73. package/dist/cjs/PortableSearch.d.ts.map +1 -0
  74. package/dist/cjs/PortableSearch.js +240 -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/RemoteSearch.d.ts +54 -0
  89. package/dist/cjs/RemoteSearch.d.ts.map +1 -0
  90. package/dist/cjs/RemoteSearch.js +134 -0
  91. package/dist/cjs/RemoteSearch.js.map +7 -0
  92. package/dist/cjs/Search.d.ts +163 -0
  93. package/dist/cjs/Search.d.ts.map +1 -0
  94. package/dist/cjs/Search.js +51 -0
  95. package/dist/cjs/Search.js.map +7 -0
  96. package/dist/cjs/SearchConformance.d.ts +115 -0
  97. package/dist/cjs/SearchConformance.d.ts.map +1 -0
  98. package/dist/cjs/SearchConformance.js +172 -0
  99. package/dist/cjs/SearchConformance.js.map +7 -0
  100. package/dist/cjs/SearchContract.d.ts +114 -0
  101. package/dist/cjs/SearchContract.d.ts.map +1 -0
  102. package/dist/cjs/SearchContract.js +339 -0
  103. package/dist/cjs/SearchContract.js.map +7 -0
  104. package/dist/cjs/ShellCommand.d.ts +164 -0
  105. package/dist/cjs/ShellCommand.d.ts.map +1 -0
  106. package/dist/cjs/ShellCommand.js +102 -0
  107. package/dist/cjs/ShellCommand.js.map +7 -0
  108. package/dist/cjs/StdError.d.ts +55 -0
  109. package/dist/cjs/StdError.d.ts.map +1 -0
  110. package/dist/cjs/StdError.js +74 -0
  111. package/dist/cjs/StdError.js.map +7 -0
  112. package/dist/cjs/TestRun.d.ts +311 -0
  113. package/dist/cjs/TestRun.d.ts.map +1 -0
  114. package/dist/cjs/TestRun.js +228 -0
  115. package/dist/cjs/TestRun.js.map +7 -0
  116. package/dist/cjs/TestRunner.d.ts +102 -0
  117. package/dist/cjs/TestRunner.d.ts.map +1 -0
  118. package/dist/cjs/TestRunner.js +54 -0
  119. package/dist/cjs/TestRunner.js.map +7 -0
  120. package/dist/cjs/TreeFingerprint.d.ts +140 -0
  121. package/dist/cjs/TreeFingerprint.d.ts.map +1 -0
  122. package/dist/cjs/TreeFingerprint.js +87 -0
  123. package/dist/cjs/TreeFingerprint.js.map +7 -0
  124. package/dist/cjs/UpdatePlan.d.ts +152 -0
  125. package/dist/cjs/UpdatePlan.d.ts.map +1 -0
  126. package/dist/cjs/UpdatePlan.js +87 -0
  127. package/dist/cjs/UpdatePlan.js.map +7 -0
  128. package/dist/cjs/WebFetch.d.ts +134 -0
  129. package/dist/cjs/WebFetch.d.ts.map +1 -0
  130. package/dist/cjs/WebFetch.js +140 -0
  131. package/dist/cjs/WebFetch.js.map +7 -0
  132. package/dist/cjs/WebSearch.d.ts +181 -0
  133. package/dist/cjs/WebSearch.d.ts.map +1 -0
  134. package/dist/cjs/WebSearch.js +86 -0
  135. package/dist/cjs/WebSearch.js.map +7 -0
  136. package/dist/cjs/Write.d.ts +147 -0
  137. package/dist/cjs/Write.d.ts.map +1 -0
  138. package/dist/cjs/Write.js +122 -0
  139. package/dist/cjs/Write.js.map +7 -0
  140. package/dist/cjs/index.d.ts +129 -0
  141. package/dist/cjs/index.d.ts.map +1 -0
  142. package/dist/cjs/index.js +101 -0
  143. package/dist/cjs/index.js.map +7 -0
  144. package/dist/cjs/internal/ApplyPatch.d.ts +145 -0
  145. package/dist/cjs/internal/ApplyPatch.d.ts.map +1 -0
  146. package/dist/cjs/internal/ApplyPatch.js +462 -0
  147. package/dist/cjs/internal/ApplyPatch.js.map +7 -0
  148. package/dist/cjs/internal/CodexText.d.ts +73 -0
  149. package/dist/cjs/internal/CodexText.d.ts.map +1 -0
  150. package/dist/cjs/internal/CodexText.js +108 -0
  151. package/dist/cjs/internal/CodexText.js.map +7 -0
  152. package/dist/cjs/internal/Declaration.d.ts +49 -0
  153. package/dist/cjs/internal/Declaration.d.ts.map +1 -0
  154. package/dist/cjs/internal/Declaration.js +46 -0
  155. package/dist/cjs/internal/Declaration.js.map +7 -0
  156. package/dist/cjs/internal/Diagnostics.d.ts +77 -0
  157. package/dist/cjs/internal/Diagnostics.d.ts.map +1 -0
  158. package/dist/cjs/internal/Diagnostics.js +89 -0
  159. package/dist/cjs/internal/Diagnostics.js.map +7 -0
  160. package/dist/cjs/internal/EnvelopePrecheck.d.ts +69 -0
  161. package/dist/cjs/internal/EnvelopePrecheck.d.ts.map +1 -0
  162. package/dist/cjs/internal/EnvelopePrecheck.js +323 -0
  163. package/dist/cjs/internal/EnvelopePrecheck.js.map +7 -0
  164. package/dist/cjs/internal/Exec.d.ts +151 -0
  165. package/dist/cjs/internal/Exec.d.ts.map +1 -0
  166. package/dist/cjs/internal/Exec.js +207 -0
  167. package/dist/cjs/internal/Exec.js.map +7 -0
  168. package/dist/cjs/internal/FileMutation.d.ts +109 -0
  169. package/dist/cjs/internal/FileMutation.d.ts.map +1 -0
  170. package/dist/cjs/internal/FileMutation.js +116 -0
  171. package/dist/cjs/internal/FileMutation.js.map +7 -0
  172. package/dist/cjs/internal/FsFailure.d.ts +38 -0
  173. package/dist/cjs/internal/FsFailure.d.ts.map +1 -0
  174. package/dist/cjs/internal/FsFailure.js +40 -0
  175. package/dist/cjs/internal/FsFailure.js.map +7 -0
  176. package/dist/cjs/internal/GitWorktree.d.ts +108 -0
  177. package/dist/cjs/internal/GitWorktree.d.ts.map +1 -0
  178. package/dist/cjs/internal/GitWorktree.js +276 -0
  179. package/dist/cjs/internal/GitWorktree.js.map +7 -0
  180. package/dist/cjs/internal/Grouping.d.ts +51 -0
  181. package/dist/cjs/internal/Grouping.d.ts.map +1 -0
  182. package/dist/cjs/internal/Grouping.js +83 -0
  183. package/dist/cjs/internal/Grouping.js.map +7 -0
  184. package/dist/cjs/internal/Html.d.ts +20 -0
  185. package/dist/cjs/internal/Html.d.ts.map +1 -0
  186. package/dist/cjs/internal/Html.js +81 -0
  187. package/dist/cjs/internal/Html.js.map +7 -0
  188. package/dist/cjs/internal/Http.d.ts +95 -0
  189. package/dist/cjs/internal/Http.d.ts.map +1 -0
  190. package/dist/cjs/internal/Http.js +153 -0
  191. package/dist/cjs/internal/Http.js.map +7 -0
  192. package/dist/cjs/internal/HttpNetwork.d.ts +27 -0
  193. package/dist/cjs/internal/HttpNetwork.d.ts.map +1 -0
  194. package/dist/cjs/internal/HttpNetwork.js +146 -0
  195. package/dist/cjs/internal/HttpNetwork.js.map +7 -0
  196. package/dist/cjs/internal/Ignore.d.ts +37 -0
  197. package/dist/cjs/internal/Ignore.d.ts.map +1 -0
  198. package/dist/cjs/internal/Ignore.js +100 -0
  199. package/dist/cjs/internal/Ignore.js.map +7 -0
  200. package/dist/cjs/internal/LinearRegex.d.ts +19 -0
  201. package/dist/cjs/internal/LinearRegex.d.ts.map +1 -0
  202. package/dist/cjs/internal/LinearRegex.js +166 -0
  203. package/dist/cjs/internal/LinearRegex.js.map +7 -0
  204. package/dist/cjs/internal/Match.d.ts +85 -0
  205. package/dist/cjs/internal/Match.d.ts.map +1 -0
  206. package/dist/cjs/internal/Match.js +99 -0
  207. package/dist/cjs/internal/Match.js.map +7 -0
  208. package/dist/cjs/internal/Paths.d.ts +23 -0
  209. package/dist/cjs/internal/Paths.d.ts.map +1 -0
  210. package/dist/cjs/internal/Paths.js +52 -0
  211. package/dist/cjs/internal/Paths.js.map +7 -0
  212. package/dist/cjs/internal/Preserve.d.ts +25 -0
  213. package/dist/cjs/internal/Preserve.d.ts.map +1 -0
  214. package/dist/cjs/internal/Preserve.js +88 -0
  215. package/dist/cjs/internal/Preserve.js.map +7 -0
  216. package/dist/cjs/internal/Prune.d.ts +35 -0
  217. package/dist/cjs/internal/Prune.d.ts.map +1 -0
  218. package/dist/cjs/internal/Prune.js +54 -0
  219. package/dist/cjs/internal/Prune.js.map +7 -0
  220. package/dist/cjs/internal/RemoteTree.d.ts +60 -0
  221. package/dist/cjs/internal/RemoteTree.d.ts.map +1 -0
  222. package/dist/cjs/internal/RemoteTree.js +123 -0
  223. package/dist/cjs/internal/RemoteTree.js.map +7 -0
  224. package/dist/cjs/internal/SearchContract.d.ts +63 -0
  225. package/dist/cjs/internal/SearchContract.d.ts.map +1 -0
  226. package/dist/cjs/internal/SearchContract.js +46 -0
  227. package/dist/cjs/internal/SearchContract.js.map +7 -0
  228. package/dist/cjs/internal/Symbols.d.ts +39 -0
  229. package/dist/cjs/internal/Symbols.d.ts.map +1 -0
  230. package/dist/cjs/internal/Symbols.js +59 -0
  231. package/dist/cjs/internal/Symbols.js.map +7 -0
  232. package/dist/cjs/internal/Tar.d.ts +23 -0
  233. package/dist/cjs/internal/Tar.d.ts.map +1 -0
  234. package/dist/cjs/internal/Tar.js +86 -0
  235. package/dist/cjs/internal/Tar.js.map +7 -0
  236. package/dist/cjs/internal/TestReport.d.ts +52 -0
  237. package/dist/cjs/internal/TestReport.d.ts.map +1 -0
  238. package/dist/cjs/internal/TestReport.js +131 -0
  239. package/dist/cjs/internal/TestReport.js.map +7 -0
  240. package/dist/cjs/internal/Text.d.ts +125 -0
  241. package/dist/cjs/internal/Text.d.ts.map +1 -0
  242. package/dist/cjs/internal/Text.js +85 -0
  243. package/dist/cjs/internal/Text.js.map +7 -0
  244. package/dist/cjs/internal/Url.d.ts +13 -0
  245. package/dist/cjs/internal/Url.d.ts.map +1 -0
  246. package/dist/cjs/internal/Url.js +35 -0
  247. package/dist/cjs/internal/Url.js.map +7 -0
  248. package/dist/cjs/internal/Walk.d.ts +72 -0
  249. package/dist/cjs/internal/Walk.d.ts.map +1 -0
  250. package/dist/cjs/internal/Walk.js +108 -0
  251. package/dist/cjs/internal/Walk.js.map +7 -0
  252. package/dist/cjs/package.json +1 -0
  253. package/dist/esm/ApplyPatch.d.ts +174 -0
  254. package/dist/esm/ApplyPatch.d.ts.map +1 -0
  255. package/dist/esm/ApplyPatch.js +346 -0
  256. package/dist/esm/ApplyPatch.js.map +1 -0
  257. package/dist/esm/Bash.d.ts +390 -0
  258. package/dist/esm/Bash.d.ts.map +1 -0
  259. package/dist/esm/Bash.js +514 -0
  260. package/dist/esm/Bash.js.map +1 -0
  261. package/dist/esm/Checkpoints.d.ts +322 -0
  262. package/dist/esm/Checkpoints.d.ts.map +1 -0
  263. package/dist/esm/Checkpoints.js +396 -0
  264. package/dist/esm/Checkpoints.js.map +1 -0
  265. package/dist/esm/Container.d.ts +132 -0
  266. package/dist/esm/Container.d.ts.map +1 -0
  267. package/dist/esm/Container.js +151 -0
  268. package/dist/esm/Container.js.map +1 -0
  269. package/dist/esm/Edit.d.ts +203 -0
  270. package/dist/esm/Edit.d.ts.map +1 -0
  271. package/dist/esm/Edit.js +296 -0
  272. package/dist/esm/Edit.js.map +1 -0
  273. package/dist/esm/ExaWebSearch.d.ts +22 -0
  274. package/dist/esm/ExaWebSearch.d.ts.map +1 -0
  275. package/dist/esm/ExaWebSearch.js +107 -0
  276. package/dist/esm/ExaWebSearch.js.map +1 -0
  277. package/dist/esm/Explore.d.ts +328 -0
  278. package/dist/esm/Explore.d.ts.map +1 -0
  279. package/dist/esm/Explore.js +106 -0
  280. package/dist/esm/Explore.js.map +1 -0
  281. package/dist/esm/Fetch.d.ts +130 -0
  282. package/dist/esm/Fetch.d.ts.map +1 -0
  283. package/dist/esm/Fetch.js +91 -0
  284. package/dist/esm/Fetch.js.map +1 -0
  285. package/dist/esm/Glob.d.ts +204 -0
  286. package/dist/esm/Glob.d.ts.map +1 -0
  287. package/dist/esm/Glob.js +177 -0
  288. package/dist/esm/Glob.js.map +1 -0
  289. package/dist/esm/Grep.d.ts +347 -0
  290. package/dist/esm/Grep.d.ts.map +1 -0
  291. package/dist/esm/Grep.js +289 -0
  292. package/dist/esm/Grep.js.map +1 -0
  293. package/dist/esm/HttpPost.d.ts +130 -0
  294. package/dist/esm/HttpPost.d.ts.map +1 -0
  295. package/dist/esm/HttpPost.js +89 -0
  296. package/dist/esm/HttpPost.js.map +1 -0
  297. package/dist/esm/LanguageServer.d.ts +90 -0
  298. package/dist/esm/LanguageServer.d.ts.map +1 -0
  299. package/dist/esm/LanguageServer.js +57 -0
  300. package/dist/esm/LanguageServer.js.map +1 -0
  301. package/dist/esm/Ls.d.ts +164 -0
  302. package/dist/esm/Ls.d.ts.map +1 -0
  303. package/dist/esm/Ls.js +178 -0
  304. package/dist/esm/Ls.js.map +1 -0
  305. package/dist/esm/Lsp.d.ts +125 -0
  306. package/dist/esm/Lsp.d.ts.map +1 -0
  307. package/dist/esm/Lsp.js +165 -0
  308. package/dist/esm/Lsp.js.map +1 -0
  309. package/dist/esm/Manifest.d.ts +918 -0
  310. package/dist/esm/Manifest.d.ts.map +1 -0
  311. package/dist/esm/Manifest.js +153 -0
  312. package/dist/esm/Manifest.js.map +1 -0
  313. package/dist/esm/NativeSearch.d.ts +38 -0
  314. package/dist/esm/NativeSearch.d.ts.map +1 -0
  315. package/dist/esm/NativeSearch.js +378 -0
  316. package/dist/esm/NativeSearch.js.map +1 -0
  317. package/dist/esm/NodeLanguageServer.d.ts +128 -0
  318. package/dist/esm/NodeLanguageServer.d.ts.map +1 -0
  319. package/dist/esm/NodeLanguageServer.js +843 -0
  320. package/dist/esm/NodeLanguageServer.js.map +1 -0
  321. package/dist/esm/PortableSearch.d.ts +36 -0
  322. package/dist/esm/PortableSearch.d.ts.map +1 -0
  323. package/dist/esm/PortableSearch.js +256 -0
  324. package/dist/esm/PortableSearch.js.map +1 -0
  325. package/dist/esm/Probe.d.ts +193 -0
  326. package/dist/esm/Probe.d.ts.map +1 -0
  327. package/dist/esm/Probe.js +225 -0
  328. package/dist/esm/Probe.js.map +1 -0
  329. package/dist/esm/Read.d.ts +189 -0
  330. package/dist/esm/Read.d.ts.map +1 -0
  331. package/dist/esm/Read.js +300 -0
  332. package/dist/esm/Read.js.map +1 -0
  333. package/dist/esm/Relocate.d.ts +73 -0
  334. package/dist/esm/Relocate.d.ts.map +1 -0
  335. package/dist/esm/Relocate.js +153 -0
  336. package/dist/esm/Relocate.js.map +1 -0
  337. package/dist/esm/RemoteSearch.d.ts +54 -0
  338. package/dist/esm/RemoteSearch.d.ts.map +1 -0
  339. package/dist/esm/RemoteSearch.js +162 -0
  340. package/dist/esm/RemoteSearch.js.map +1 -0
  341. package/dist/esm/Search.d.ts +163 -0
  342. package/dist/esm/Search.d.ts.map +1 -0
  343. package/dist/esm/Search.js +47 -0
  344. package/dist/esm/Search.js.map +1 -0
  345. package/dist/esm/SearchConformance.d.ts +115 -0
  346. package/dist/esm/SearchConformance.d.ts.map +1 -0
  347. package/dist/esm/SearchConformance.js +193 -0
  348. package/dist/esm/SearchConformance.js.map +1 -0
  349. package/dist/esm/SearchContract.d.ts +114 -0
  350. package/dist/esm/SearchContract.d.ts.map +1 -0
  351. package/dist/esm/SearchContract.js +461 -0
  352. package/dist/esm/SearchContract.js.map +1 -0
  353. package/dist/esm/ShellCommand.d.ts +164 -0
  354. package/dist/esm/ShellCommand.d.ts.map +1 -0
  355. package/dist/esm/ShellCommand.js +159 -0
  356. package/dist/esm/ShellCommand.js.map +1 -0
  357. package/dist/esm/StdError.d.ts +55 -0
  358. package/dist/esm/StdError.d.ts.map +1 -0
  359. package/dist/esm/StdError.js +71 -0
  360. package/dist/esm/StdError.js.map +1 -0
  361. package/dist/esm/TestRun.d.ts +311 -0
  362. package/dist/esm/TestRun.d.ts.map +1 -0
  363. package/dist/esm/TestRun.js +316 -0
  364. package/dist/esm/TestRun.js.map +1 -0
  365. package/dist/esm/TestRunner.d.ts +102 -0
  366. package/dist/esm/TestRunner.d.ts.map +1 -0
  367. package/dist/esm/TestRunner.js +68 -0
  368. package/dist/esm/TestRunner.js.map +1 -0
  369. package/dist/esm/TreeFingerprint.d.ts +140 -0
  370. package/dist/esm/TreeFingerprint.d.ts.map +1 -0
  371. package/dist/esm/TreeFingerprint.js +170 -0
  372. package/dist/esm/TreeFingerprint.js.map +1 -0
  373. package/dist/esm/UpdatePlan.d.ts +152 -0
  374. package/dist/esm/UpdatePlan.d.ts.map +1 -0
  375. package/dist/esm/UpdatePlan.js +129 -0
  376. package/dist/esm/UpdatePlan.js.map +1 -0
  377. package/dist/esm/WebFetch.d.ts +134 -0
  378. package/dist/esm/WebFetch.d.ts.map +1 -0
  379. package/dist/esm/WebFetch.js +151 -0
  380. package/dist/esm/WebFetch.js.map +1 -0
  381. package/dist/esm/WebSearch.d.ts +181 -0
  382. package/dist/esm/WebSearch.d.ts.map +1 -0
  383. package/dist/esm/WebSearch.js +134 -0
  384. package/dist/esm/WebSearch.js.map +1 -0
  385. package/dist/esm/Write.d.ts +147 -0
  386. package/dist/esm/Write.d.ts.map +1 -0
  387. package/dist/esm/Write.js +144 -0
  388. package/dist/esm/Write.js.map +1 -0
  389. package/dist/esm/index.d.ts +129 -0
  390. package/dist/esm/index.d.ts.map +1 -0
  391. package/dist/esm/index.js +129 -0
  392. package/dist/esm/index.js.map +1 -0
  393. package/dist/esm/internal/ApplyPatch.d.ts +145 -0
  394. package/dist/esm/internal/ApplyPatch.d.ts.map +1 -0
  395. package/dist/esm/internal/ApplyPatch.js +489 -0
  396. package/dist/esm/internal/ApplyPatch.js.map +1 -0
  397. package/dist/esm/internal/CodexText.d.ts +73 -0
  398. package/dist/esm/internal/CodexText.d.ts.map +1 -0
  399. package/dist/esm/internal/CodexText.js +156 -0
  400. package/dist/esm/internal/CodexText.js.map +1 -0
  401. package/dist/esm/internal/Declaration.d.ts +49 -0
  402. package/dist/esm/internal/Declaration.d.ts.map +1 -0
  403. package/dist/esm/internal/Declaration.js +42 -0
  404. package/dist/esm/internal/Declaration.js.map +1 -0
  405. package/dist/esm/internal/Diagnostics.d.ts +77 -0
  406. package/dist/esm/internal/Diagnostics.d.ts.map +1 -0
  407. package/dist/esm/internal/Diagnostics.js +99 -0
  408. package/dist/esm/internal/Diagnostics.js.map +1 -0
  409. package/dist/esm/internal/EnvelopePrecheck.d.ts +69 -0
  410. package/dist/esm/internal/EnvelopePrecheck.d.ts.map +1 -0
  411. package/dist/esm/internal/EnvelopePrecheck.js +426 -0
  412. package/dist/esm/internal/EnvelopePrecheck.js.map +1 -0
  413. package/dist/esm/internal/Exec.d.ts +151 -0
  414. package/dist/esm/internal/Exec.d.ts.map +1 -0
  415. package/dist/esm/internal/Exec.js +285 -0
  416. package/dist/esm/internal/Exec.js.map +1 -0
  417. package/dist/esm/internal/FileMutation.d.ts +109 -0
  418. package/dist/esm/internal/FileMutation.d.ts.map +1 -0
  419. package/dist/esm/internal/FileMutation.js +123 -0
  420. package/dist/esm/internal/FileMutation.js.map +1 -0
  421. package/dist/esm/internal/FsFailure.d.ts +38 -0
  422. package/dist/esm/internal/FsFailure.d.ts.map +1 -0
  423. package/dist/esm/internal/FsFailure.js +39 -0
  424. package/dist/esm/internal/FsFailure.js.map +1 -0
  425. package/dist/esm/internal/GitWorktree.d.ts +108 -0
  426. package/dist/esm/internal/GitWorktree.d.ts.map +1 -0
  427. package/dist/esm/internal/GitWorktree.js +352 -0
  428. package/dist/esm/internal/GitWorktree.js.map +1 -0
  429. package/dist/esm/internal/Grouping.d.ts +51 -0
  430. package/dist/esm/internal/Grouping.d.ts.map +1 -0
  431. package/dist/esm/internal/Grouping.js +99 -0
  432. package/dist/esm/internal/Grouping.js.map +1 -0
  433. package/dist/esm/internal/Html.d.ts +20 -0
  434. package/dist/esm/internal/Html.d.ts.map +1 -0
  435. package/dist/esm/internal/Html.js +70 -0
  436. package/dist/esm/internal/Html.js.map +1 -0
  437. package/dist/esm/internal/Http.d.ts +95 -0
  438. package/dist/esm/internal/Http.d.ts.map +1 -0
  439. package/dist/esm/internal/Http.js +154 -0
  440. package/dist/esm/internal/Http.js.map +1 -0
  441. package/dist/esm/internal/HttpNetwork.d.ts +27 -0
  442. package/dist/esm/internal/HttpNetwork.d.ts.map +1 -0
  443. package/dist/esm/internal/HttpNetwork.js +114 -0
  444. package/dist/esm/internal/HttpNetwork.js.map +1 -0
  445. package/dist/esm/internal/Ignore.d.ts +37 -0
  446. package/dist/esm/internal/Ignore.d.ts.map +1 -0
  447. package/dist/esm/internal/Ignore.js +128 -0
  448. package/dist/esm/internal/Ignore.js.map +1 -0
  449. package/dist/esm/internal/LinearRegex.d.ts +19 -0
  450. package/dist/esm/internal/LinearRegex.d.ts.map +1 -0
  451. package/dist/esm/internal/LinearRegex.js +176 -0
  452. package/dist/esm/internal/LinearRegex.js.map +1 -0
  453. package/dist/esm/internal/Match.d.ts +85 -0
  454. package/dist/esm/internal/Match.d.ts.map +1 -0
  455. package/dist/esm/internal/Match.js +142 -0
  456. package/dist/esm/internal/Match.js.map +1 -0
  457. package/dist/esm/internal/Paths.d.ts +23 -0
  458. package/dist/esm/internal/Paths.d.ts.map +1 -0
  459. package/dist/esm/internal/Paths.js +40 -0
  460. package/dist/esm/internal/Paths.js.map +1 -0
  461. package/dist/esm/internal/Preserve.d.ts +25 -0
  462. package/dist/esm/internal/Preserve.d.ts.map +1 -0
  463. package/dist/esm/internal/Preserve.js +70 -0
  464. package/dist/esm/internal/Preserve.js.map +1 -0
  465. package/dist/esm/internal/Prune.d.ts +35 -0
  466. package/dist/esm/internal/Prune.d.ts.map +1 -0
  467. package/dist/esm/internal/Prune.js +60 -0
  468. package/dist/esm/internal/Prune.js.map +1 -0
  469. package/dist/esm/internal/RemoteTree.d.ts +60 -0
  470. package/dist/esm/internal/RemoteTree.d.ts.map +1 -0
  471. package/dist/esm/internal/RemoteTree.js +132 -0
  472. package/dist/esm/internal/RemoteTree.js.map +1 -0
  473. package/dist/esm/internal/SearchContract.d.ts +63 -0
  474. package/dist/esm/internal/SearchContract.d.ts.map +1 -0
  475. package/dist/esm/internal/SearchContract.js +66 -0
  476. package/dist/esm/internal/SearchContract.js.map +1 -0
  477. package/dist/esm/internal/Symbols.d.ts +39 -0
  478. package/dist/esm/internal/Symbols.d.ts.map +1 -0
  479. package/dist/esm/internal/Symbols.js +79 -0
  480. package/dist/esm/internal/Symbols.js.map +1 -0
  481. package/dist/esm/internal/Tar.d.ts +23 -0
  482. package/dist/esm/internal/Tar.d.ts.map +1 -0
  483. package/dist/esm/internal/Tar.js +97 -0
  484. package/dist/esm/internal/Tar.js.map +1 -0
  485. package/dist/esm/internal/TestReport.d.ts +52 -0
  486. package/dist/esm/internal/TestReport.d.ts.map +1 -0
  487. package/dist/esm/internal/TestReport.js +172 -0
  488. package/dist/esm/internal/TestReport.js.map +1 -0
  489. package/dist/esm/internal/Text.d.ts +125 -0
  490. package/dist/esm/internal/Text.d.ts.map +1 -0
  491. package/dist/esm/internal/Text.js +141 -0
  492. package/dist/esm/internal/Text.js.map +1 -0
  493. package/dist/esm/internal/Url.d.ts +13 -0
  494. package/dist/esm/internal/Url.d.ts.map +1 -0
  495. package/dist/esm/internal/Url.js +27 -0
  496. package/dist/esm/internal/Url.js.map +1 -0
  497. package/dist/esm/internal/Walk.d.ts +72 -0
  498. package/dist/esm/internal/Walk.d.ts.map +1 -0
  499. package/dist/esm/internal/Walk.js +126 -0
  500. package/dist/esm/internal/Walk.js.map +1 -0
  501. package/docs/README.md +119 -0
  502. package/docs/api.md +499 -0
  503. package/docs/concepts/effects-and-capabilities.md +138 -0
  504. package/docs/concepts/flows-and-handlers.md +115 -0
  505. package/docs/concepts/limits-and-disclosure.md +105 -0
  506. package/docs/concepts/search-contract.md +182 -0
  507. package/docs/guides/bind-the-standard-flows.md +116 -0
  508. package/docs/guides/implement-a-search-peer.md +133 -0
  509. package/docs/guides/pin-a-checkpoint.md +161 -0
  510. package/docs/guides/query-a-language-server.md +257 -0
  511. package/docs/guides/reach-the-network.md +141 -0
  512. package/docs/guides/read-and-edit-a-file.md +240 -0
  513. package/docs/guides/run-a-shell-command.md +236 -0
  514. package/docs/guides/run-the-test-suite.md +154 -0
  515. package/docs/guides/search-a-workspace.md +148 -0
  516. package/docs/installation.md +115 -0
  517. package/docs/quickstart.md +125 -0
  518. package/docs/reference/flows.md +556 -0
  519. package/docs/troubleshooting.md +347 -0
  520. package/package.json +449 -3
  521. package/src/ApplyPatch.ts +458 -0
  522. package/src/Bash.ts +619 -0
  523. package/src/Checkpoints.ts +589 -0
  524. package/src/Container.ts +212 -0
  525. package/src/Edit.ts +366 -0
  526. package/src/ExaWebSearch.ts +145 -0
  527. package/src/Explore.ts +139 -0
  528. package/src/Fetch.ts +117 -0
  529. package/src/Glob.ts +200 -0
  530. package/src/Grep.ts +320 -0
  531. package/src/HttpPost.ts +120 -0
  532. package/src/LanguageServer.ts +110 -0
  533. package/src/Ls.ts +228 -0
  534. package/src/Lsp.ts +184 -0
  535. package/src/Manifest.ts +162 -0
  536. package/src/NativeSearch.ts +457 -0
  537. package/src/NodeLanguageServer.ts +1148 -0
  538. package/src/PortableSearch.ts +284 -0
  539. package/src/Probe.ts +284 -0
  540. package/src/Read.ts +359 -0
  541. package/src/Relocate.ts +166 -0
  542. package/src/RemoteSearch.ts +199 -0
  543. package/src/Search.ts +185 -0
  544. package/src/SearchConformance.ts +288 -0
  545. package/src/SearchContract.ts +489 -0
  546. package/src/ShellCommand.ts +201 -0
  547. package/src/StdError.ts +80 -0
  548. package/src/TestRun.ts +401 -0
  549. package/src/TestRunner.ts +119 -0
  550. package/src/TreeFingerprint.ts +200 -0
  551. package/src/UpdatePlan.ts +171 -0
  552. package/src/WebFetch.ts +194 -0
  553. package/src/WebSearch.ts +165 -0
  554. package/src/Write.ts +195 -0
  555. package/src/index.ts +157 -0
  556. package/src/internal/ApplyPatch.ts +601 -0
  557. package/src/internal/CodexText.ts +182 -0
  558. package/src/internal/Declaration.ts +60 -0
  559. package/src/internal/Diagnostics.ts +134 -0
  560. package/src/internal/EnvelopePrecheck.ts +489 -0
  561. package/src/internal/Exec.ts +427 -0
  562. package/src/internal/FileMutation.ts +231 -0
  563. package/src/internal/FsFailure.ts +51 -0
  564. package/src/internal/GitWorktree.ts +491 -0
  565. package/src/internal/Grouping.ts +106 -0
  566. package/src/internal/Html.ts +87 -0
  567. package/src/internal/Http.ts +209 -0
  568. package/src/internal/HttpNetwork.ts +153 -0
  569. package/src/internal/Ignore.ts +135 -0
  570. package/src/internal/LinearRegex.ts +173 -0
  571. package/src/internal/Match.ts +172 -0
  572. package/src/internal/Paths.ts +42 -0
  573. package/src/internal/Preserve.ts +108 -0
  574. package/src/internal/Prune.ts +62 -0
  575. package/src/internal/RemoteTree.ts +159 -0
  576. package/src/internal/SearchContract.ts +77 -0
  577. package/src/internal/Symbols.ts +88 -0
  578. package/src/internal/Tar.ts +95 -0
  579. package/src/internal/TestReport.ts +194 -0
  580. package/src/internal/Text.ts +185 -0
  581. package/src/internal/Url.ts +23 -0
  582. package/src/internal/Walk.ts +176 -0
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Small, dependency-free HTML renderers for web retrieval.
3
+ *
4
+ * @since 1.0.0
5
+ */
6
+
7
+ const comments = /<!--[\s\S]*?-->/g
8
+ const entities: Readonly<Record<string, string>> = { amp: "&", lt: "<", gt: ">", quot: "\"", apos: "'", nbsp: " " }
9
+
10
+ const dropSkipped = (html: string): string => {
11
+ const lower = html.replace(/[A-Z]/g, (letter) => letter.toLowerCase())
12
+ const opening = /<(head|script|style|noscript|iframe|object|embed)\b/gi
13
+ let output = ""
14
+ let cursor = 0
15
+ let match: RegExpExecArray | null
16
+ while ((match = opening.exec(html)) !== null) {
17
+ output += html.slice(cursor, match.index)
18
+ const marker = `</${match[1]!.toLowerCase()}`
19
+ let close = lower.indexOf(marker, opening.lastIndex)
20
+ while (close !== -1) {
21
+ let end = close + marker.length
22
+ while (/\s/.test(lower[end] ?? "")) end++
23
+ if (lower[end] === ">") {
24
+ cursor = end + 1
25
+ opening.lastIndex = cursor
26
+ break
27
+ }
28
+ close = lower.indexOf(marker, close + marker.length)
29
+ }
30
+ if (close === -1) return output
31
+ }
32
+ return output + html.slice(cursor)
33
+ }
34
+
35
+ const decode = (value: string): string =>
36
+ value.replace(/&(#x[\da-f]+|#\d+|[a-z]+);/gi, (match, entity: string) => {
37
+ if (entity[0] === "#") {
38
+ const number = Number.parseInt(
39
+ entity.slice(entity[1]!.toLowerCase() === "x" ? 2 : 1),
40
+ entity[1]!.toLowerCase() === "x" ? 16 : 10
41
+ )
42
+ return number <= 0x10ffff
43
+ && !(number >= 0xd800 && number <= 0xdfff)
44
+ ? String.fromCodePoint(number)
45
+ : match
46
+ }
47
+ const key = entity.toLowerCase()
48
+ return Object.hasOwn(entities, key) ? entities[key]! : match
49
+ })
50
+
51
+ const source = (html: string): string => dropSkipped(html.replace(comments, ""))
52
+
53
+ /**
54
+ * Extracts readable text while dropping executable and presentation-only elements.
55
+ *
56
+ * @category rendering
57
+ * @since 1.0.0
58
+ */
59
+ export const toText = (html: string): string =>
60
+ decode(source(html).replace(/<(br|\/p|\/div|\/li|\/h[1-6]|\/tr)\b[^>]*>/gi, "\n").replace(/<[^>]*>/g, " "))
61
+ .replace(/[ \t]+\n/g, "\n").replace(/\n[ \t]+/g, "\n").replace(/\n{3,}/g, "\n\n").replace(/[ \t]{2,}/g, " ").trim()
62
+
63
+ /**
64
+ * Converts a conservative subset of HTML into readable Markdown.
65
+ *
66
+ * @category rendering
67
+ * @since 1.0.0
68
+ */
69
+ export const toMarkdown = (html: string): string => {
70
+ const markdown = source(html)
71
+ .replace(
72
+ /<h([1-6])\b[^>]*>([\s\S]*?)<\/h\1>/gi,
73
+ (_all, level: string, text: string) => `\n\n${"#".repeat(Number(level))} ${toText(text)}\n\n`
74
+ )
75
+ .replace(/<(strong|b)\b[^>]*>([\s\S]*?)<\/\1>/gi, "**$2**")
76
+ .replace(/<(em|i)\b[^>]*>([\s\S]*?)<\/\1>/gi, "*$2*")
77
+ .replace(
78
+ /<a\b[^>]*href=["']([^"']+)["'][^>]*>([\s\S]*?)<\/a>/gi,
79
+ (_all, href: string, text: string) => `[${toText(text)}](${href})`
80
+ )
81
+ .replace(/<li\b[^>]*>/gi, "\n- ").replace(
82
+ /<\/?(ul|ol|p|div|section|article|main|blockquote|pre|tr)\b[^>]*>/gi,
83
+ "\n"
84
+ )
85
+ .replace(/<br\b[^>]*>/gi, "\n").replace(/<[^>]*>/g, "")
86
+ return decode(markdown).replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n").trim()
87
+ }
@@ -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 HttpClientRequest from "effect/http/HttpClientRequest"
11
+ import * as Schema from "effect/Schema"
12
+ import * as Stream from "effect/Stream"
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/http/FetchHttpClient"
17
+ import * as HttpClient from "effect/http/HttpClient"
18
+ import * as HttpClientError from "effect/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
+ }