@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,489 @@
1
+ /**
2
+ * The hermetic pre-check: a lexical scan of shell text for the paths it names,
3
+ * and the refusal when one of them falls outside the declared envelope.
4
+ *
5
+ * The scan is fail-closed over explicit path tokens and nothing more. It
6
+ * cannot prove confinement — a shell can name a path no lexer sees, through a
7
+ * variable, a substitution, or a program that opens a file of its own — so a
8
+ * kernel or host sandbox must eventually enforce and report the complete read
9
+ * and write sets.
10
+ *
11
+ * It lives beside the flow rather than inside it because it is its own
12
+ * concept, with its own vocabulary (Access, PathReference) and its own
13
+ * security history: three independent bypasses, each sufficient on its own to
14
+ * defeat it, are closed here.
15
+ *
16
+ * @since 1.0.0
17
+ */
18
+
19
+ import type * as Path from "@smthrs/kernel/Path"
20
+ import * as StdError from "../StdError.ts"
21
+ import { withinEnvelope } from "./Paths.ts"
22
+
23
+ /**
24
+ * The filesystem envelope one invocation declared.
25
+ *
26
+ * Structural rather than the hermetic `Bash.Input` itself: the scan needs the
27
+ * three fields and none of the rest, and depending on the flow module would
28
+ * make the flow and its pre-check import each other.
29
+ *
30
+ * @category models
31
+ * @since 1.0.0
32
+ */
33
+ export interface Envelope {
34
+ readonly cwd?: string | undefined
35
+ readonly reads: ReadonlyArray<string>
36
+ readonly writes: ReadonlyArray<string>
37
+ }
38
+
39
+ /**
40
+ * How a command touches a path it names.
41
+ *
42
+ * @category models
43
+ * @since 1.0.0
44
+ */
45
+ export type Access = "read" | "write"
46
+
47
+ /**
48
+ * One path a command names, and how it touches it.
49
+ *
50
+ * @category models
51
+ * @since 1.0.0
52
+ */
53
+ export interface PathReference {
54
+ readonly access: Access
55
+ readonly value: string
56
+ }
57
+
58
+ const commandSeparators = new Set(["&&", "||", ";", ";;", ";&", ";;&", "|", "|&", "&", "\n", "(", ")"])
59
+ const writeRedirections = new Set([">", ">>", ">|", "&>", "&>>", ">&", "<>"])
60
+ const readRedirections = new Set(["<", "<&"])
61
+ // A here-document delimiter and a here-string are text, not file names.
62
+ const textRedirections = new Set(["<<", "<<-", "<<<"])
63
+ const isRedirection = (token: Token): boolean =>
64
+ token.operator &&
65
+ (writeRedirections.has(token.text) || readRedirections.has(token.text) || textRedirections.has(token.text))
66
+ // Longest first, so `&>>` is not read as `&` then `>>`.
67
+ const operators = [
68
+ ";;&",
69
+ "&>>",
70
+ "<<<",
71
+ "<<-",
72
+ ";;",
73
+ ";&",
74
+ "&&",
75
+ "||",
76
+ "|&",
77
+ "&>",
78
+ ">>",
79
+ ">|",
80
+ ">&",
81
+ "<>",
82
+ "<<",
83
+ "<&",
84
+ "\n",
85
+ ";",
86
+ "|",
87
+ "&",
88
+ "(",
89
+ ")",
90
+ ">",
91
+ "<"
92
+ ]
93
+ // Reserved words and grouping braces open or close a compound command; the
94
+ // command they wrap stands after them.
95
+ const reservedWords = new Set([
96
+ "!",
97
+ "{",
98
+ "}",
99
+ "case",
100
+ "do",
101
+ "done",
102
+ "elif",
103
+ "else",
104
+ "esac",
105
+ "fi",
106
+ "for",
107
+ "function",
108
+ "if",
109
+ "in",
110
+ "select",
111
+ "then",
112
+ "until",
113
+ "while"
114
+ ])
115
+ const writeCommands = new Set(["chmod", "chown", "mkdir", "rm", "rmdir", "tee", "touch", "truncate", "unlink"])
116
+ const destinationCommands = new Set(["cp", "install", "mv"])
117
+ const prefixWrappers = new Set(["env", "nice", "time", "sudo", "nohup", "xargs", "command", "exec"])
118
+ // A shell runs the argument of its `-c` flag as shell text of its own.
119
+ const shells = new Set(["ash", "bash", "dash", "fish", "ksh", "mksh", "sh", "zsh"])
120
+ const commandFlag = /^-[A-Za-z]*c[A-Za-z]*$/
121
+
122
+ /**
123
+ * One lexical unit of shell text: an operator, or a word with its quotes
124
+ * removed. A command substitution inside a word stands as `$()` in the word;
125
+ * its body is scanned as a command of its own.
126
+ */
127
+ interface Token {
128
+ readonly operator: boolean
129
+ readonly text: string
130
+ }
131
+
132
+ interface Lexed {
133
+ readonly tokens: ReadonlyArray<Token>
134
+ readonly substitutions: ReadonlyArray<string>
135
+ }
136
+
137
+ // The end of a `$(` body that starts at `from`: the index of its closing
138
+ // parenthesis, skipping quoted spans and nested parentheses. An unclosed body
139
+ // runs to the end of the text, which is how a fail-closed scan must read it.
140
+ // Substitutions and quotes nest without limit in a shell, but each level
141
+ // costs this scan a pass over the rest of the text and a stack frame. Fifty
142
+ // thousand `$(` used to run for half a minute and then overflow the stack, so
143
+ // past this depth the text is refused rather than scanned.
144
+ const maxNesting = 32
145
+
146
+ const tooDeep = (): StdError.StdError =>
147
+ new StdError.StdError({
148
+ code: "invalid_input",
149
+ message: `Command nests substitutions or quotes deeper than ${maxNesting} levels`
150
+ })
151
+
152
+ const substitutionEnd = (text: string, from: number, nesting: number): number => {
153
+ if (nesting > maxNesting) throw tooDeep()
154
+ let depth = 1
155
+ let index = from
156
+ while (index < text.length) {
157
+ const char = text[index]!
158
+ if (char === "\\") {
159
+ index += 2
160
+ } else if (char === "'") {
161
+ const close = text.indexOf("'", index + 1)
162
+ index = close === -1 ? text.length : close + 1
163
+ } else if (char === "\"") {
164
+ index = doubleQuoteEnd(text, index + 1, nesting + 1) + 1
165
+ } else if (char === "`") {
166
+ index = backtickEnd(text, index + 1) + 1
167
+ } else {
168
+ if (char === "(") depth++
169
+ if (char === ")" && --depth === 0) return index
170
+ index++
171
+ }
172
+ }
173
+ return text.length
174
+ }
175
+
176
+ const backtickEnd = (text: string, from: number): number => {
177
+ let index = from
178
+ while (index < text.length && text[index] !== "`") index += text[index] === "\\" ? 2 : 1
179
+ return Math.min(index, text.length)
180
+ }
181
+
182
+ const doubleQuoteEnd = (text: string, from: number, nesting: number): number => {
183
+ if (nesting > maxNesting) throw tooDeep()
184
+ let index = from
185
+ while (index < text.length && text[index] !== "\"") {
186
+ const char = text[index]!
187
+ if (char === "\\") index += 2
188
+ else if (char === "`") index = backtickEnd(text, index + 1) + 1
189
+ else if (char === "$" && text[index + 1] === "(") index = substitutionEnd(text, index + 2, nesting + 1) + 1
190
+ else index++
191
+ }
192
+ return Math.min(index, text.length)
193
+ }
194
+
195
+ // A hand-rolled lexer rather than one regular expression: a word is any run
196
+ // of bare characters, quoted spans, and substitutions, and a substitution can
197
+ // hold quotes and operators of its own. Splitting on operator characters
198
+ // alone let `echo "$(rm /work/target)"` hide a delete inside one quoted word,
199
+ // read `>|` as a pipe that turned the target into the next command's name,
200
+ // and read `(rm /work/target)` as a command named `(rm`.
201
+ //
202
+ // Quotes are removed from a word's text, because `"/outs"ide/x` names
203
+ // `/outside/x`; keeping the quotes made it a relative path under the
204
+ // working directory.
205
+ // Sticky, so the match starts at `lastIndex` without copying the rest of the
206
+ // text for every word.
207
+ const descriptorPattern = /\d+(?=[<>])/y
208
+
209
+ const lex = (command: string, nesting: number): Lexed => {
210
+ const tokens: Array<Token> = []
211
+ const substitutions: Array<string> = []
212
+ let index = 0
213
+ const substitution = (from: number, to: number): string => {
214
+ substitutions.push(command.slice(from, to))
215
+ return "$()"
216
+ }
217
+ while (index < command.length) {
218
+ const char = command[index]!
219
+ // Every blank the word loop stops at must be skipped here, or the lexer
220
+ // would push an empty word without advancing.
221
+ if (char !== "\n" && /\s/.test(char)) {
222
+ index++
223
+ continue
224
+ }
225
+ if (char === "\\" && command[index + 1] === "\n") {
226
+ index += 2
227
+ continue
228
+ }
229
+ if (char === "#") {
230
+ while (index < command.length && command[index] !== "\n") index++
231
+ continue
232
+ }
233
+ // A file-descriptor number belongs to the redirection after it: in
234
+ // `2>/dev/null rm /work/target` the command is `rm`, not `2`.
235
+ descriptorPattern.lastIndex = index
236
+ const descriptor = descriptorPattern.exec(command)
237
+ if (descriptor !== null) {
238
+ index += descriptor[0].length
239
+ continue
240
+ }
241
+ const operator = operators.find((candidate) => command.startsWith(candidate, index))
242
+ if (operator !== undefined) {
243
+ tokens.push({ operator: true, text: operator })
244
+ index += operator.length
245
+ continue
246
+ }
247
+ let text = ""
248
+ while (index < command.length) {
249
+ const next = command[index]!
250
+ if (/[\s<>;|&()]/.test(next)) break
251
+ if (next === "\\") {
252
+ // A backslash escapes shell syntax. Before any other character it is
253
+ // kept, so `C:\work\input` stays the path it names on Windows rather
254
+ // than collapsing to a word the scan cannot see as a path.
255
+ const escaped = command[index + 1] ?? ""
256
+ if (escaped !== "\n") text += /[\s<>;|&()'"`$\\#]/.test(escaped) ? escaped : `\\${escaped}`
257
+ index += 2
258
+ } else if (next === "'") {
259
+ const close = command.indexOf("'", index + 1)
260
+ const end = close === -1 ? command.length : close
261
+ text += command.slice(index + 1, end)
262
+ index = end + 1
263
+ } else if (next === "\"") {
264
+ const end = doubleQuoteEnd(command, index + 1, nesting + 1)
265
+ let inner = index + 1
266
+ while (inner < end) {
267
+ const quoted = command[inner]!
268
+ if (quoted === "\\" && /[$`"\\\n]/.test(command[inner + 1] ?? "")) {
269
+ if (command[inner + 1] !== "\n") text += command[inner + 1]
270
+ inner += 2
271
+ } else if (quoted === "`") {
272
+ const close = backtickEnd(command, inner + 1)
273
+ text += substitution(inner + 1, close)
274
+ inner = close + 1
275
+ } else if (quoted === "$" && command[inner + 1] === "(") {
276
+ const close = substitutionEnd(command, inner + 2, nesting + 2)
277
+ text += substitution(inner + 2, close)
278
+ inner = close + 1
279
+ } else {
280
+ text += quoted
281
+ inner++
282
+ }
283
+ }
284
+ index = end + 1
285
+ } else if (next === "`") {
286
+ const close = backtickEnd(command, index + 1)
287
+ text += substitution(index + 1, close)
288
+ index = close + 1
289
+ } else if (next === "$" && command[index + 1] === "(") {
290
+ const close = substitutionEnd(command, index + 2, nesting + 1)
291
+ text += substitution(index + 2, close)
292
+ index = close + 1
293
+ } else {
294
+ text += next
295
+ index++
296
+ }
297
+ }
298
+ tokens.push({ operator: false, text })
299
+ }
300
+ return { tokens, substitutions }
301
+ }
302
+
303
+ // A parenthesis is an operator to the lexer, so one left in a word was quoted
304
+ // and is part of the name; only a trailing comma is punctuation.
305
+ const pathValue = (token: string): string => token.replace(/,+$/, "")
306
+
307
+ const isPathToken = (path: Path.Path, token: string): boolean =>
308
+ token === "." ||
309
+ token === ".." ||
310
+ token.startsWith("./") ||
311
+ token.startsWith("../") ||
312
+ path.isAbsolute(token) ||
313
+ /^[A-Za-z]:[\\/]/.test(token) ||
314
+ token.includes("/")
315
+
316
+ const segmentReferences = (
317
+ path: Path.Path,
318
+ tokens: ReadonlyArray<Token>,
319
+ nesting: number
320
+ ): ReadonlyArray<PathReference> => {
321
+ // The word after a redirection operator is its target, never the command.
322
+ const isTarget = (index: number): boolean => index > 0 && isRedirection(tokens[index - 1]!)
323
+ const isWord = (index: number): boolean => !tokens[index]!.operator && !isTarget(index)
324
+ const name = (index: number): string => path.basename(pathValue(tokens[index]!.text))
325
+ const hasWrapper = tokens.some((_, index) => isWord(index) && prefixWrappers.has(name(index)))
326
+ let commandIndex = tokens.findIndex((token, index) =>
327
+ isWord(index) &&
328
+ !token.text.includes("=") &&
329
+ !prefixWrappers.has(name(index)) &&
330
+ !reservedWords.has(token.text) &&
331
+ !token.text.startsWith("-") &&
332
+ token.text !== ""
333
+ )
334
+ if (hasWrapper) {
335
+ // Wrapper options can carry their own values. Prefer a later known
336
+ // mutating command so an option value cannot lend it a read classification.
337
+ const mutatingIndex = tokens.findIndex((_, index) =>
338
+ isWord(index) && (writeCommands.has(name(index)) || destinationCommands.has(name(index)))
339
+ )
340
+ if (mutatingIndex !== -1) commandIndex = mutatingIndex
341
+ }
342
+
343
+ const command = commandIndex === -1 ? "" : name(commandIndex)
344
+ // Shell text handed to `eval` or to a shell's `-c` flag is a command, not a
345
+ // path: reading `sh -c 'rm /work/target'` as one quoted word let a delete
346
+ // pass as a read of a file named `rm /work/target`.
347
+ const scripts = new Set<number>()
348
+ if (command === "eval") {
349
+ for (let index = commandIndex + 1; index < tokens.length; index++) if (isWord(index)) scripts.add(index)
350
+ } else if (shells.has(command)) {
351
+ const flag = tokens.findIndex((token, index) =>
352
+ index > commandIndex && isWord(index) && commandFlag.test(token.text)
353
+ )
354
+ if (flag !== -1 && flag + 1 < tokens.length && isWord(flag + 1)) scripts.add(flag + 1)
355
+ }
356
+ const candidates: Array<{ readonly index: number; readonly value: string }> = []
357
+ for (let index = 0; index < tokens.length; index++) {
358
+ const token = tokens[index]!
359
+ if (index === commandIndex || scripts.has(index) || token.operator) continue
360
+ if (!isTarget(index) && token.text.startsWith("-")) continue
361
+ if (isTarget(index) && textRedirections.has(tokens[index - 1]!.text)) continue
362
+ const value = pathValue(token.text)
363
+ if (value !== "" && isPathToken(path, value)) candidates.push({ index, value })
364
+ }
365
+
366
+ const destinationIndex = destinationCommands.has(command)
367
+ ? candidates.filter(({ index }) => !isTarget(index)).at(-1)?.index
368
+ : undefined
369
+
370
+ const script = [...scripts].map((index) => tokens[index]!.text).join(" ")
371
+ const nested = script === "" ? [] : references(path, script, nesting + 1)
372
+ const named = candidates.map(({ index, value }): PathReference => {
373
+ const access: Access = isTarget(index)
374
+ ? writeRedirections.has(tokens[index - 1]!.text) ? "write" : "read"
375
+ : writeCommands.has(command) || destinationIndex === index
376
+ ? "write"
377
+ : "read"
378
+ return { access, value }
379
+ })
380
+ return [...named, ...nested]
381
+ }
382
+
383
+ const references = (path: Path.Path, command: string, nesting: number): ReadonlyArray<PathReference> => {
384
+ if (nesting > maxNesting) throw tooDeep()
385
+ const { substitutions, tokens } = lex(command, nesting)
386
+ const found: Array<PathReference> = []
387
+ let segment: Array<Token> = []
388
+ for (const token of tokens) {
389
+ if (token.operator && commandSeparators.has(token.text)) {
390
+ found.push(...segmentReferences(path, segment, nesting))
391
+ segment = []
392
+ } else {
393
+ segment.push(token)
394
+ }
395
+ }
396
+ found.push(...segmentReferences(path, segment, nesting))
397
+ // A substitution runs its body as a command; its paths count like any other.
398
+ for (const body of substitutions) found.push(...references(path, body, nesting + 1))
399
+ return found
400
+ }
401
+
402
+ /**
403
+ * Every path token the shell text names, one segment at a time.
404
+ *
405
+ * @throws {StdError.StdError} `invalid_input` when substitutions or quotes nest
406
+ * deeper than the scan reads.
407
+ * @category pre-check
408
+ * @since 1.0.0
409
+ */
410
+ export const commandReferences = (path: Path.Path, command: string): ReadonlyArray<PathReference> =>
411
+ references(path, command, 0)
412
+
413
+ const resolvePath = (
414
+ path: Path.Path,
415
+ cwd: string,
416
+ value: string
417
+ ): string => path.isAbsolute(value) ? path.normalize(value) : path.resolve(cwd, value)
418
+
419
+ const isDeclared = (
420
+ path: Path.Path,
421
+ cwd: string,
422
+ declared: ReadonlyArray<string>,
423
+ source: string
424
+ ): boolean =>
425
+ withinEnvelope(
426
+ declared.map((entry) => resolvePath(path, cwd, entry)),
427
+ resolvePath(path, cwd, source)
428
+ )
429
+
430
+ /**
431
+ * The refusal shell text earns by naming a path outside its declared
432
+ * envelope, or `undefined` when every path it names is declared.
433
+ *
434
+ * @category pre-check
435
+ * @since 1.0.0
436
+ */
437
+ export const outsideEnvelope = (
438
+ input: Envelope,
439
+ text: string,
440
+ path: Path.Path
441
+ ): StdError.StdError | undefined => {
442
+ const base = path.resolve(".")
443
+ const cwd = path.resolve(input.cwd ?? ".")
444
+ // Passing the default explicitly is not a declaration the caller owes. A
445
+ // working directory is where the command runs, not a file it reads, and
446
+ // `cwd: "."` names exactly what omitting `cwd` names — so refusing it asked
447
+ // the caller to list the workspace root among its reads to say nothing at
448
+ // all. Agents hit this constantly: one SWE-bench run spent ten of its
449
+ // forty-eight tool calls re-issuing the same command after
450
+ // "Working directory is outside declared reads: <the workspace root>". A
451
+ // cwd that points somewhere else is still declared or refused.
452
+ if (input.cwd !== undefined && cwd !== base && !isDeclared(path, cwd, input.reads, cwd)) {
453
+ return new StdError.StdError({
454
+ code: "outside_declared_reads",
455
+ message: `Working directory is outside declared reads: ${cwd}`,
456
+ path: cwd
457
+ })
458
+ }
459
+
460
+ // The Shell contract currently has no sandbox or access-reporting surface.
461
+ // This lexical scan is intentionally only a fail-closed pre-check for
462
+ // explicit path tokens. It cannot prove confinement; a kernel/host sandbox
463
+ // must eventually enforce and report the complete read and write sets.
464
+ let named: ReadonlyArray<PathReference>
465
+ try {
466
+ named = commandReferences(path, text)
467
+ } catch {
468
+ // The depth bound is the one failure the scan raises, and a text the scan
469
+ // cannot read is refused whatever the reason, never run unchecked.
470
+ return tooDeep()
471
+ }
472
+ for (const reference of named) {
473
+ const resolved = resolvePath(path, cwd, reference.value)
474
+ // /dev/* is the process plumbing every shell one-liner leans on:
475
+ // `2>/dev/null`, `cat /dev/stdin`. Normalize first so a dot-dot segment
476
+ // cannot disguise an ordinary filesystem path as process plumbing.
477
+ if (resolved.startsWith("/dev/")) continue
478
+ const declared = reference.access === "write" ? input.writes : input.reads
479
+ if (!isDeclared(path, cwd, declared, resolved)) {
480
+ const code = reference.access === "write" ? "outside_declared_writes" : "outside_declared_reads"
481
+ return new StdError.StdError({
482
+ code,
483
+ message: `Command path is outside declared ${reference.access}s: ${resolved}`,
484
+ path: resolved
485
+ })
486
+ }
487
+ }
488
+ return undefined
489
+ }