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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (555) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/LICENSE +21 -0
  3. package/README.md +152 -2
  4. package/dist/cjs/ApplyPatch.d.ts +174 -0
  5. package/dist/cjs/ApplyPatch.d.ts.map +1 -0
  6. package/dist/cjs/ApplyPatch.js +309 -0
  7. package/dist/cjs/ApplyPatch.js.map +7 -0
  8. package/dist/cjs/Bash.d.ts +304 -0
  9. package/dist/cjs/Bash.d.ts.map +1 -0
  10. package/dist/cjs/Bash.js +321 -0
  11. package/dist/cjs/Bash.js.map +7 -0
  12. package/dist/cjs/Checkpoints.d.ts +279 -0
  13. package/dist/cjs/Checkpoints.d.ts.map +1 -0
  14. package/dist/cjs/Checkpoints.js +145 -0
  15. package/dist/cjs/Checkpoints.js.map +7 -0
  16. package/dist/cjs/Container.d.ts +132 -0
  17. package/dist/cjs/Container.d.ts.map +1 -0
  18. package/dist/cjs/Container.js +113 -0
  19. package/dist/cjs/Container.js.map +7 -0
  20. package/dist/cjs/Edit.d.ts +203 -0
  21. package/dist/cjs/Edit.d.ts.map +1 -0
  22. package/dist/cjs/Edit.js +258 -0
  23. package/dist/cjs/Edit.js.map +7 -0
  24. package/dist/cjs/ExaWebSearch.d.ts +22 -0
  25. package/dist/cjs/ExaWebSearch.d.ts.map +1 -0
  26. package/dist/cjs/ExaWebSearch.js +138 -0
  27. package/dist/cjs/ExaWebSearch.js.map +7 -0
  28. package/dist/cjs/Explore.d.ts +328 -0
  29. package/dist/cjs/Explore.d.ts.map +1 -0
  30. package/dist/cjs/Explore.js +90 -0
  31. package/dist/cjs/Explore.js.map +7 -0
  32. package/dist/cjs/Fetch.d.ts +130 -0
  33. package/dist/cjs/Fetch.d.ts.map +1 -0
  34. package/dist/cjs/Fetch.js +64 -0
  35. package/dist/cjs/Fetch.js.map +7 -0
  36. package/dist/cjs/Glob.d.ts +204 -0
  37. package/dist/cjs/Glob.d.ts.map +1 -0
  38. package/dist/cjs/Glob.js +94 -0
  39. package/dist/cjs/Glob.js.map +7 -0
  40. package/dist/cjs/Grep.d.ts +347 -0
  41. package/dist/cjs/Grep.d.ts.map +1 -0
  42. package/dist/cjs/Grep.js +181 -0
  43. package/dist/cjs/Grep.js.map +7 -0
  44. package/dist/cjs/HttpPost.d.ts +130 -0
  45. package/dist/cjs/HttpPost.d.ts.map +1 -0
  46. package/dist/cjs/HttpPost.js +72 -0
  47. package/dist/cjs/HttpPost.js.map +7 -0
  48. package/dist/cjs/LanguageServer.d.ts +90 -0
  49. package/dist/cjs/LanguageServer.d.ts.map +1 -0
  50. package/dist/cjs/LanguageServer.js +60 -0
  51. package/dist/cjs/LanguageServer.js.map +7 -0
  52. package/dist/cjs/Ls.d.ts +164 -0
  53. package/dist/cjs/Ls.d.ts.map +1 -0
  54. package/dist/cjs/Ls.js +136 -0
  55. package/dist/cjs/Ls.js.map +7 -0
  56. package/dist/cjs/Lsp.d.ts +125 -0
  57. package/dist/cjs/Lsp.d.ts.map +1 -0
  58. package/dist/cjs/Lsp.js +137 -0
  59. package/dist/cjs/Lsp.js.map +7 -0
  60. package/dist/cjs/Manifest.d.ts +918 -0
  61. package/dist/cjs/Manifest.d.ts.map +1 -0
  62. package/dist/cjs/Manifest.js +144 -0
  63. package/dist/cjs/Manifest.js.map +7 -0
  64. package/dist/cjs/NativeSearch.d.ts +38 -0
  65. package/dist/cjs/NativeSearch.d.ts.map +1 -0
  66. package/dist/cjs/NativeSearch.js +326 -0
  67. package/dist/cjs/NativeSearch.js.map +7 -0
  68. package/dist/cjs/NodeLanguageServer.d.ts +128 -0
  69. package/dist/cjs/NodeLanguageServer.d.ts.map +1 -0
  70. package/dist/cjs/NodeLanguageServer.js +796 -0
  71. package/dist/cjs/NodeLanguageServer.js.map +7 -0
  72. package/dist/cjs/PortableSearch.d.ts +24 -0
  73. package/dist/cjs/PortableSearch.d.ts.map +1 -0
  74. package/dist/cjs/PortableSearch.js +233 -0
  75. package/dist/cjs/PortableSearch.js.map +7 -0
  76. package/dist/cjs/Probe.d.ts +193 -0
  77. package/dist/cjs/Probe.d.ts.map +1 -0
  78. package/dist/cjs/Probe.js +134 -0
  79. package/dist/cjs/Probe.js.map +7 -0
  80. package/dist/cjs/Read.d.ts +189 -0
  81. package/dist/cjs/Read.d.ts.map +1 -0
  82. package/dist/cjs/Read.js +223 -0
  83. package/dist/cjs/Read.js.map +7 -0
  84. package/dist/cjs/Relocate.d.ts +73 -0
  85. package/dist/cjs/Relocate.d.ts.map +1 -0
  86. package/dist/cjs/Relocate.js +72 -0
  87. package/dist/cjs/Relocate.js.map +7 -0
  88. package/dist/cjs/Search.d.ts +163 -0
  89. package/dist/cjs/Search.d.ts.map +1 -0
  90. package/dist/cjs/Search.js +51 -0
  91. package/dist/cjs/Search.js.map +7 -0
  92. package/dist/cjs/SearchConformance.d.ts +115 -0
  93. package/dist/cjs/SearchConformance.d.ts.map +1 -0
  94. package/dist/cjs/SearchConformance.js +172 -0
  95. package/dist/cjs/SearchConformance.js.map +7 -0
  96. package/dist/cjs/SearchContract.d.ts +114 -0
  97. package/dist/cjs/SearchContract.d.ts.map +1 -0
  98. package/dist/cjs/SearchContract.js +339 -0
  99. package/dist/cjs/SearchContract.js.map +7 -0
  100. package/dist/cjs/ShellCommand.d.ts +164 -0
  101. package/dist/cjs/ShellCommand.d.ts.map +1 -0
  102. package/dist/cjs/ShellCommand.js +102 -0
  103. package/dist/cjs/ShellCommand.js.map +7 -0
  104. package/dist/cjs/StdError.d.ts +55 -0
  105. package/dist/cjs/StdError.d.ts.map +1 -0
  106. package/dist/cjs/StdError.js +74 -0
  107. package/dist/cjs/StdError.js.map +7 -0
  108. package/dist/cjs/TestRun.d.ts +311 -0
  109. package/dist/cjs/TestRun.d.ts.map +1 -0
  110. package/dist/cjs/TestRun.js +228 -0
  111. package/dist/cjs/TestRun.js.map +7 -0
  112. package/dist/cjs/TestRunner.d.ts +102 -0
  113. package/dist/cjs/TestRunner.d.ts.map +1 -0
  114. package/dist/cjs/TestRunner.js +54 -0
  115. package/dist/cjs/TestRunner.js.map +7 -0
  116. package/dist/cjs/TreeFingerprint.d.ts +140 -0
  117. package/dist/cjs/TreeFingerprint.d.ts.map +1 -0
  118. package/dist/cjs/TreeFingerprint.js +87 -0
  119. package/dist/cjs/TreeFingerprint.js.map +7 -0
  120. package/dist/cjs/UpdatePlan.d.ts +152 -0
  121. package/dist/cjs/UpdatePlan.d.ts.map +1 -0
  122. package/dist/cjs/UpdatePlan.js +87 -0
  123. package/dist/cjs/UpdatePlan.js.map +7 -0
  124. package/dist/cjs/WebFetch.d.ts +134 -0
  125. package/dist/cjs/WebFetch.d.ts.map +1 -0
  126. package/dist/cjs/WebFetch.js +140 -0
  127. package/dist/cjs/WebFetch.js.map +7 -0
  128. package/dist/cjs/WebSearch.d.ts +181 -0
  129. package/dist/cjs/WebSearch.d.ts.map +1 -0
  130. package/dist/cjs/WebSearch.js +86 -0
  131. package/dist/cjs/WebSearch.js.map +7 -0
  132. package/dist/cjs/Write.d.ts +147 -0
  133. package/dist/cjs/Write.d.ts.map +1 -0
  134. package/dist/cjs/Write.js +122 -0
  135. package/dist/cjs/Write.js.map +7 -0
  136. package/dist/cjs/index.d.ts +127 -0
  137. package/dist/cjs/index.d.ts.map +1 -0
  138. package/dist/cjs/index.js +99 -0
  139. package/dist/cjs/index.js.map +7 -0
  140. package/dist/cjs/internal/ApplyPatch.d.ts +145 -0
  141. package/dist/cjs/internal/ApplyPatch.d.ts.map +1 -0
  142. package/dist/cjs/internal/ApplyPatch.js +462 -0
  143. package/dist/cjs/internal/ApplyPatch.js.map +7 -0
  144. package/dist/cjs/internal/CodexText.d.ts +73 -0
  145. package/dist/cjs/internal/CodexText.d.ts.map +1 -0
  146. package/dist/cjs/internal/CodexText.js +108 -0
  147. package/dist/cjs/internal/CodexText.js.map +7 -0
  148. package/dist/cjs/internal/Declaration.d.ts +49 -0
  149. package/dist/cjs/internal/Declaration.d.ts.map +1 -0
  150. package/dist/cjs/internal/Declaration.js +46 -0
  151. package/dist/cjs/internal/Declaration.js.map +7 -0
  152. package/dist/cjs/internal/Diagnostics.d.ts +77 -0
  153. package/dist/cjs/internal/Diagnostics.d.ts.map +1 -0
  154. package/dist/cjs/internal/Diagnostics.js +89 -0
  155. package/dist/cjs/internal/Diagnostics.js.map +7 -0
  156. package/dist/cjs/internal/EnvelopePrecheck.d.ts +67 -0
  157. package/dist/cjs/internal/EnvelopePrecheck.d.ts.map +1 -0
  158. package/dist/cjs/internal/EnvelopePrecheck.js +124 -0
  159. package/dist/cjs/internal/EnvelopePrecheck.js.map +7 -0
  160. package/dist/cjs/internal/Exec.d.ts +139 -0
  161. package/dist/cjs/internal/Exec.d.ts.map +1 -0
  162. package/dist/cjs/internal/Exec.js +158 -0
  163. package/dist/cjs/internal/Exec.js.map +7 -0
  164. package/dist/cjs/internal/FileMutation.d.ts +109 -0
  165. package/dist/cjs/internal/FileMutation.d.ts.map +1 -0
  166. package/dist/cjs/internal/FileMutation.js +116 -0
  167. package/dist/cjs/internal/FileMutation.js.map +7 -0
  168. package/dist/cjs/internal/FsFailure.d.ts +38 -0
  169. package/dist/cjs/internal/FsFailure.d.ts.map +1 -0
  170. package/dist/cjs/internal/FsFailure.js +40 -0
  171. package/dist/cjs/internal/FsFailure.js.map +7 -0
  172. package/dist/cjs/internal/GitWorktree.d.ts +98 -0
  173. package/dist/cjs/internal/GitWorktree.d.ts.map +1 -0
  174. package/dist/cjs/internal/GitWorktree.js +270 -0
  175. package/dist/cjs/internal/GitWorktree.js.map +7 -0
  176. package/dist/cjs/internal/Grouping.d.ts +51 -0
  177. package/dist/cjs/internal/Grouping.d.ts.map +1 -0
  178. package/dist/cjs/internal/Grouping.js +83 -0
  179. package/dist/cjs/internal/Grouping.js.map +7 -0
  180. package/dist/cjs/internal/Html.d.ts +20 -0
  181. package/dist/cjs/internal/Html.d.ts.map +1 -0
  182. package/dist/cjs/internal/Html.js +81 -0
  183. package/dist/cjs/internal/Html.js.map +7 -0
  184. package/dist/cjs/internal/Http.d.ts +95 -0
  185. package/dist/cjs/internal/Http.d.ts.map +1 -0
  186. package/dist/cjs/internal/Http.js +153 -0
  187. package/dist/cjs/internal/Http.js.map +7 -0
  188. package/dist/cjs/internal/HttpNetwork.d.ts +27 -0
  189. package/dist/cjs/internal/HttpNetwork.d.ts.map +1 -0
  190. package/dist/cjs/internal/HttpNetwork.js +146 -0
  191. package/dist/cjs/internal/HttpNetwork.js.map +7 -0
  192. package/dist/cjs/internal/Ignore.d.ts +37 -0
  193. package/dist/cjs/internal/Ignore.d.ts.map +1 -0
  194. package/dist/cjs/internal/Ignore.js +100 -0
  195. package/dist/cjs/internal/Ignore.js.map +7 -0
  196. package/dist/cjs/internal/LinearRegex.d.ts +19 -0
  197. package/dist/cjs/internal/LinearRegex.d.ts.map +1 -0
  198. package/dist/cjs/internal/LinearRegex.js +166 -0
  199. package/dist/cjs/internal/LinearRegex.js.map +7 -0
  200. package/dist/cjs/internal/Match.d.ts +85 -0
  201. package/dist/cjs/internal/Match.d.ts.map +1 -0
  202. package/dist/cjs/internal/Match.js +99 -0
  203. package/dist/cjs/internal/Match.js.map +7 -0
  204. package/dist/cjs/internal/Paths.d.ts +23 -0
  205. package/dist/cjs/internal/Paths.d.ts.map +1 -0
  206. package/dist/cjs/internal/Paths.js +52 -0
  207. package/dist/cjs/internal/Paths.js.map +7 -0
  208. package/dist/cjs/internal/Preserve.d.ts +25 -0
  209. package/dist/cjs/internal/Preserve.d.ts.map +1 -0
  210. package/dist/cjs/internal/Preserve.js +88 -0
  211. package/dist/cjs/internal/Preserve.js.map +7 -0
  212. package/dist/cjs/internal/Prune.d.ts +35 -0
  213. package/dist/cjs/internal/Prune.d.ts.map +1 -0
  214. package/dist/cjs/internal/Prune.js +54 -0
  215. package/dist/cjs/internal/Prune.js.map +7 -0
  216. package/dist/cjs/internal/SearchContract.d.ts +63 -0
  217. package/dist/cjs/internal/SearchContract.d.ts.map +1 -0
  218. package/dist/cjs/internal/SearchContract.js +46 -0
  219. package/dist/cjs/internal/SearchContract.js.map +7 -0
  220. package/dist/cjs/internal/Symbols.d.ts +39 -0
  221. package/dist/cjs/internal/Symbols.d.ts.map +1 -0
  222. package/dist/cjs/internal/Symbols.js +59 -0
  223. package/dist/cjs/internal/Symbols.js.map +7 -0
  224. package/dist/cjs/internal/TestReport.d.ts +52 -0
  225. package/dist/cjs/internal/TestReport.d.ts.map +1 -0
  226. package/dist/cjs/internal/TestReport.js +131 -0
  227. package/dist/cjs/internal/TestReport.js.map +7 -0
  228. package/dist/cjs/internal/Text.d.ts +114 -0
  229. package/dist/cjs/internal/Text.d.ts.map +1 -0
  230. package/dist/cjs/internal/Text.js +82 -0
  231. package/dist/cjs/internal/Text.js.map +7 -0
  232. package/dist/cjs/internal/Url.d.ts +13 -0
  233. package/dist/cjs/internal/Url.d.ts.map +1 -0
  234. package/dist/cjs/internal/Url.js +35 -0
  235. package/dist/cjs/internal/Url.js.map +7 -0
  236. package/dist/cjs/internal/Walk.d.ts +72 -0
  237. package/dist/cjs/internal/Walk.d.ts.map +1 -0
  238. package/dist/cjs/internal/Walk.js +108 -0
  239. package/dist/cjs/internal/Walk.js.map +7 -0
  240. package/dist/cjs/package.json +1 -0
  241. package/dist/esm/ApplyPatch.d.ts +174 -0
  242. package/dist/esm/ApplyPatch.d.ts.map +1 -0
  243. package/dist/esm/ApplyPatch.js +346 -0
  244. package/dist/esm/ApplyPatch.js.map +1 -0
  245. package/dist/esm/Bash.d.ts +304 -0
  246. package/dist/esm/Bash.d.ts.map +1 -0
  247. package/dist/esm/Bash.js +469 -0
  248. package/dist/esm/Bash.js.map +1 -0
  249. package/dist/esm/Checkpoints.d.ts +279 -0
  250. package/dist/esm/Checkpoints.d.ts.map +1 -0
  251. package/dist/esm/Checkpoints.js +298 -0
  252. package/dist/esm/Checkpoints.js.map +1 -0
  253. package/dist/esm/Container.d.ts +132 -0
  254. package/dist/esm/Container.d.ts.map +1 -0
  255. package/dist/esm/Container.js +151 -0
  256. package/dist/esm/Container.js.map +1 -0
  257. package/dist/esm/Edit.d.ts +203 -0
  258. package/dist/esm/Edit.d.ts.map +1 -0
  259. package/dist/esm/Edit.js +296 -0
  260. package/dist/esm/Edit.js.map +1 -0
  261. package/dist/esm/ExaWebSearch.d.ts +22 -0
  262. package/dist/esm/ExaWebSearch.d.ts.map +1 -0
  263. package/dist/esm/ExaWebSearch.js +107 -0
  264. package/dist/esm/ExaWebSearch.js.map +1 -0
  265. package/dist/esm/Explore.d.ts +328 -0
  266. package/dist/esm/Explore.d.ts.map +1 -0
  267. package/dist/esm/Explore.js +106 -0
  268. package/dist/esm/Explore.js.map +1 -0
  269. package/dist/esm/Fetch.d.ts +130 -0
  270. package/dist/esm/Fetch.d.ts.map +1 -0
  271. package/dist/esm/Fetch.js +91 -0
  272. package/dist/esm/Fetch.js.map +1 -0
  273. package/dist/esm/Glob.d.ts +204 -0
  274. package/dist/esm/Glob.d.ts.map +1 -0
  275. package/dist/esm/Glob.js +177 -0
  276. package/dist/esm/Glob.js.map +1 -0
  277. package/dist/esm/Grep.d.ts +347 -0
  278. package/dist/esm/Grep.d.ts.map +1 -0
  279. package/dist/esm/Grep.js +289 -0
  280. package/dist/esm/Grep.js.map +1 -0
  281. package/dist/esm/HttpPost.d.ts +130 -0
  282. package/dist/esm/HttpPost.d.ts.map +1 -0
  283. package/dist/esm/HttpPost.js +89 -0
  284. package/dist/esm/HttpPost.js.map +1 -0
  285. package/dist/esm/LanguageServer.d.ts +90 -0
  286. package/dist/esm/LanguageServer.d.ts.map +1 -0
  287. package/dist/esm/LanguageServer.js +57 -0
  288. package/dist/esm/LanguageServer.js.map +1 -0
  289. package/dist/esm/Ls.d.ts +164 -0
  290. package/dist/esm/Ls.d.ts.map +1 -0
  291. package/dist/esm/Ls.js +178 -0
  292. package/dist/esm/Ls.js.map +1 -0
  293. package/dist/esm/Lsp.d.ts +125 -0
  294. package/dist/esm/Lsp.d.ts.map +1 -0
  295. package/dist/esm/Lsp.js +165 -0
  296. package/dist/esm/Lsp.js.map +1 -0
  297. package/dist/esm/Manifest.d.ts +918 -0
  298. package/dist/esm/Manifest.d.ts.map +1 -0
  299. package/dist/esm/Manifest.js +153 -0
  300. package/dist/esm/Manifest.js.map +1 -0
  301. package/dist/esm/NativeSearch.d.ts +38 -0
  302. package/dist/esm/NativeSearch.d.ts.map +1 -0
  303. package/dist/esm/NativeSearch.js +378 -0
  304. package/dist/esm/NativeSearch.js.map +1 -0
  305. package/dist/esm/NodeLanguageServer.d.ts +128 -0
  306. package/dist/esm/NodeLanguageServer.d.ts.map +1 -0
  307. package/dist/esm/NodeLanguageServer.js +843 -0
  308. package/dist/esm/NodeLanguageServer.js.map +1 -0
  309. package/dist/esm/PortableSearch.d.ts +24 -0
  310. package/dist/esm/PortableSearch.d.ts.map +1 -0
  311. package/dist/esm/PortableSearch.js +240 -0
  312. package/dist/esm/PortableSearch.js.map +1 -0
  313. package/dist/esm/Probe.d.ts +193 -0
  314. package/dist/esm/Probe.d.ts.map +1 -0
  315. package/dist/esm/Probe.js +225 -0
  316. package/dist/esm/Probe.js.map +1 -0
  317. package/dist/esm/Read.d.ts +189 -0
  318. package/dist/esm/Read.d.ts.map +1 -0
  319. package/dist/esm/Read.js +300 -0
  320. package/dist/esm/Read.js.map +1 -0
  321. package/dist/esm/Relocate.d.ts +73 -0
  322. package/dist/esm/Relocate.d.ts.map +1 -0
  323. package/dist/esm/Relocate.js +153 -0
  324. package/dist/esm/Relocate.js.map +1 -0
  325. package/dist/esm/Search.d.ts +163 -0
  326. package/dist/esm/Search.d.ts.map +1 -0
  327. package/dist/esm/Search.js +47 -0
  328. package/dist/esm/Search.js.map +1 -0
  329. package/dist/esm/SearchConformance.d.ts +115 -0
  330. package/dist/esm/SearchConformance.d.ts.map +1 -0
  331. package/dist/esm/SearchConformance.js +193 -0
  332. package/dist/esm/SearchConformance.js.map +1 -0
  333. package/dist/esm/SearchContract.d.ts +114 -0
  334. package/dist/esm/SearchContract.d.ts.map +1 -0
  335. package/dist/esm/SearchContract.js +461 -0
  336. package/dist/esm/SearchContract.js.map +1 -0
  337. package/dist/esm/ShellCommand.d.ts +164 -0
  338. package/dist/esm/ShellCommand.d.ts.map +1 -0
  339. package/dist/esm/ShellCommand.js +159 -0
  340. package/dist/esm/ShellCommand.js.map +1 -0
  341. package/dist/esm/StdError.d.ts +55 -0
  342. package/dist/esm/StdError.d.ts.map +1 -0
  343. package/dist/esm/StdError.js +71 -0
  344. package/dist/esm/StdError.js.map +1 -0
  345. package/dist/esm/TestRun.d.ts +311 -0
  346. package/dist/esm/TestRun.d.ts.map +1 -0
  347. package/dist/esm/TestRun.js +316 -0
  348. package/dist/esm/TestRun.js.map +1 -0
  349. package/dist/esm/TestRunner.d.ts +102 -0
  350. package/dist/esm/TestRunner.d.ts.map +1 -0
  351. package/dist/esm/TestRunner.js +68 -0
  352. package/dist/esm/TestRunner.js.map +1 -0
  353. package/dist/esm/TreeFingerprint.d.ts +140 -0
  354. package/dist/esm/TreeFingerprint.d.ts.map +1 -0
  355. package/dist/esm/TreeFingerprint.js +170 -0
  356. package/dist/esm/TreeFingerprint.js.map +1 -0
  357. package/dist/esm/UpdatePlan.d.ts +152 -0
  358. package/dist/esm/UpdatePlan.d.ts.map +1 -0
  359. package/dist/esm/UpdatePlan.js +129 -0
  360. package/dist/esm/UpdatePlan.js.map +1 -0
  361. package/dist/esm/WebFetch.d.ts +134 -0
  362. package/dist/esm/WebFetch.d.ts.map +1 -0
  363. package/dist/esm/WebFetch.js +151 -0
  364. package/dist/esm/WebFetch.js.map +1 -0
  365. package/dist/esm/WebSearch.d.ts +181 -0
  366. package/dist/esm/WebSearch.d.ts.map +1 -0
  367. package/dist/esm/WebSearch.js +134 -0
  368. package/dist/esm/WebSearch.js.map +1 -0
  369. package/dist/esm/Write.d.ts +147 -0
  370. package/dist/esm/Write.d.ts.map +1 -0
  371. package/dist/esm/Write.js +144 -0
  372. package/dist/esm/Write.js.map +1 -0
  373. package/dist/esm/index.d.ts +127 -0
  374. package/dist/esm/index.d.ts.map +1 -0
  375. package/dist/esm/index.js +127 -0
  376. package/dist/esm/index.js.map +1 -0
  377. package/dist/esm/internal/ApplyPatch.d.ts +145 -0
  378. package/dist/esm/internal/ApplyPatch.d.ts.map +1 -0
  379. package/dist/esm/internal/ApplyPatch.js +489 -0
  380. package/dist/esm/internal/ApplyPatch.js.map +1 -0
  381. package/dist/esm/internal/CodexText.d.ts +73 -0
  382. package/dist/esm/internal/CodexText.d.ts.map +1 -0
  383. package/dist/esm/internal/CodexText.js +156 -0
  384. package/dist/esm/internal/CodexText.js.map +1 -0
  385. package/dist/esm/internal/Declaration.d.ts +49 -0
  386. package/dist/esm/internal/Declaration.d.ts.map +1 -0
  387. package/dist/esm/internal/Declaration.js +42 -0
  388. package/dist/esm/internal/Declaration.js.map +1 -0
  389. package/dist/esm/internal/Diagnostics.d.ts +77 -0
  390. package/dist/esm/internal/Diagnostics.d.ts.map +1 -0
  391. package/dist/esm/internal/Diagnostics.js +99 -0
  392. package/dist/esm/internal/Diagnostics.js.map +1 -0
  393. package/dist/esm/internal/EnvelopePrecheck.d.ts +67 -0
  394. package/dist/esm/internal/EnvelopePrecheck.d.ts.map +1 -0
  395. package/dist/esm/internal/EnvelopePrecheck.js +167 -0
  396. package/dist/esm/internal/EnvelopePrecheck.js.map +1 -0
  397. package/dist/esm/internal/Exec.d.ts +139 -0
  398. package/dist/esm/internal/Exec.d.ts.map +1 -0
  399. package/dist/esm/internal/Exec.js +193 -0
  400. package/dist/esm/internal/Exec.js.map +1 -0
  401. package/dist/esm/internal/FileMutation.d.ts +109 -0
  402. package/dist/esm/internal/FileMutation.d.ts.map +1 -0
  403. package/dist/esm/internal/FileMutation.js +123 -0
  404. package/dist/esm/internal/FileMutation.js.map +1 -0
  405. package/dist/esm/internal/FsFailure.d.ts +38 -0
  406. package/dist/esm/internal/FsFailure.d.ts.map +1 -0
  407. package/dist/esm/internal/FsFailure.js +39 -0
  408. package/dist/esm/internal/FsFailure.js.map +1 -0
  409. package/dist/esm/internal/GitWorktree.d.ts +98 -0
  410. package/dist/esm/internal/GitWorktree.d.ts.map +1 -0
  411. package/dist/esm/internal/GitWorktree.js +345 -0
  412. package/dist/esm/internal/GitWorktree.js.map +1 -0
  413. package/dist/esm/internal/Grouping.d.ts +51 -0
  414. package/dist/esm/internal/Grouping.d.ts.map +1 -0
  415. package/dist/esm/internal/Grouping.js +99 -0
  416. package/dist/esm/internal/Grouping.js.map +1 -0
  417. package/dist/esm/internal/Html.d.ts +20 -0
  418. package/dist/esm/internal/Html.d.ts.map +1 -0
  419. package/dist/esm/internal/Html.js +70 -0
  420. package/dist/esm/internal/Html.js.map +1 -0
  421. package/dist/esm/internal/Http.d.ts +95 -0
  422. package/dist/esm/internal/Http.d.ts.map +1 -0
  423. package/dist/esm/internal/Http.js +154 -0
  424. package/dist/esm/internal/Http.js.map +1 -0
  425. package/dist/esm/internal/HttpNetwork.d.ts +27 -0
  426. package/dist/esm/internal/HttpNetwork.d.ts.map +1 -0
  427. package/dist/esm/internal/HttpNetwork.js +114 -0
  428. package/dist/esm/internal/HttpNetwork.js.map +1 -0
  429. package/dist/esm/internal/Ignore.d.ts +37 -0
  430. package/dist/esm/internal/Ignore.d.ts.map +1 -0
  431. package/dist/esm/internal/Ignore.js +128 -0
  432. package/dist/esm/internal/Ignore.js.map +1 -0
  433. package/dist/esm/internal/LinearRegex.d.ts +19 -0
  434. package/dist/esm/internal/LinearRegex.d.ts.map +1 -0
  435. package/dist/esm/internal/LinearRegex.js +176 -0
  436. package/dist/esm/internal/LinearRegex.js.map +1 -0
  437. package/dist/esm/internal/Match.d.ts +85 -0
  438. package/dist/esm/internal/Match.d.ts.map +1 -0
  439. package/dist/esm/internal/Match.js +142 -0
  440. package/dist/esm/internal/Match.js.map +1 -0
  441. package/dist/esm/internal/Paths.d.ts +23 -0
  442. package/dist/esm/internal/Paths.d.ts.map +1 -0
  443. package/dist/esm/internal/Paths.js +40 -0
  444. package/dist/esm/internal/Paths.js.map +1 -0
  445. package/dist/esm/internal/Preserve.d.ts +25 -0
  446. package/dist/esm/internal/Preserve.d.ts.map +1 -0
  447. package/dist/esm/internal/Preserve.js +70 -0
  448. package/dist/esm/internal/Preserve.js.map +1 -0
  449. package/dist/esm/internal/Prune.d.ts +35 -0
  450. package/dist/esm/internal/Prune.d.ts.map +1 -0
  451. package/dist/esm/internal/Prune.js +60 -0
  452. package/dist/esm/internal/Prune.js.map +1 -0
  453. package/dist/esm/internal/SearchContract.d.ts +63 -0
  454. package/dist/esm/internal/SearchContract.d.ts.map +1 -0
  455. package/dist/esm/internal/SearchContract.js +66 -0
  456. package/dist/esm/internal/SearchContract.js.map +1 -0
  457. package/dist/esm/internal/Symbols.d.ts +39 -0
  458. package/dist/esm/internal/Symbols.d.ts.map +1 -0
  459. package/dist/esm/internal/Symbols.js +79 -0
  460. package/dist/esm/internal/Symbols.js.map +1 -0
  461. package/dist/esm/internal/TestReport.d.ts +52 -0
  462. package/dist/esm/internal/TestReport.d.ts.map +1 -0
  463. package/dist/esm/internal/TestReport.js +172 -0
  464. package/dist/esm/internal/TestReport.js.map +1 -0
  465. package/dist/esm/internal/Text.d.ts +114 -0
  466. package/dist/esm/internal/Text.d.ts.map +1 -0
  467. package/dist/esm/internal/Text.js +130 -0
  468. package/dist/esm/internal/Text.js.map +1 -0
  469. package/dist/esm/internal/Url.d.ts +13 -0
  470. package/dist/esm/internal/Url.d.ts.map +1 -0
  471. package/dist/esm/internal/Url.js +27 -0
  472. package/dist/esm/internal/Url.js.map +1 -0
  473. package/dist/esm/internal/Walk.d.ts +72 -0
  474. package/dist/esm/internal/Walk.d.ts.map +1 -0
  475. package/dist/esm/internal/Walk.js +126 -0
  476. package/dist/esm/internal/Walk.js.map +1 -0
  477. package/docs/README.md +117 -0
  478. package/docs/api.md +472 -0
  479. package/docs/concepts/effects-and-capabilities.md +136 -0
  480. package/docs/concepts/flows-and-handlers.md +115 -0
  481. package/docs/concepts/limits-and-disclosure.md +102 -0
  482. package/docs/concepts/search-contract.md +182 -0
  483. package/docs/guides/bind-the-standard-flows.md +114 -0
  484. package/docs/guides/implement-a-search-peer.md +133 -0
  485. package/docs/guides/pin-a-checkpoint.md +141 -0
  486. package/docs/guides/query-a-language-server.md +257 -0
  487. package/docs/guides/reach-the-network.md +141 -0
  488. package/docs/guides/read-and-edit-a-file.md +240 -0
  489. package/docs/guides/run-a-shell-command.md +215 -0
  490. package/docs/guides/run-the-test-suite.md +154 -0
  491. package/docs/guides/search-a-workspace.md +148 -0
  492. package/docs/installation.md +111 -0
  493. package/docs/quickstart.md +125 -0
  494. package/docs/reference/flows.md +556 -0
  495. package/docs/troubleshooting.md +322 -0
  496. package/package.json +439 -3
  497. package/src/ApplyPatch.ts +458 -0
  498. package/src/Bash.ts +549 -0
  499. package/src/Checkpoints.ts +422 -0
  500. package/src/Container.ts +212 -0
  501. package/src/Edit.ts +366 -0
  502. package/src/ExaWebSearch.ts +145 -0
  503. package/src/Explore.ts +139 -0
  504. package/src/Fetch.ts +117 -0
  505. package/src/Glob.ts +200 -0
  506. package/src/Grep.ts +320 -0
  507. package/src/HttpPost.ts +120 -0
  508. package/src/LanguageServer.ts +110 -0
  509. package/src/Ls.ts +228 -0
  510. package/src/Lsp.ts +184 -0
  511. package/src/Manifest.ts +162 -0
  512. package/src/NativeSearch.ts +457 -0
  513. package/src/NodeLanguageServer.ts +1148 -0
  514. package/src/PortableSearch.ts +264 -0
  515. package/src/Probe.ts +284 -0
  516. package/src/Read.ts +359 -0
  517. package/src/Relocate.ts +166 -0
  518. package/src/Search.ts +185 -0
  519. package/src/SearchConformance.ts +288 -0
  520. package/src/SearchContract.ts +489 -0
  521. package/src/ShellCommand.ts +201 -0
  522. package/src/StdError.ts +80 -0
  523. package/src/TestRun.ts +401 -0
  524. package/src/TestRunner.ts +119 -0
  525. package/src/TreeFingerprint.ts +200 -0
  526. package/src/UpdatePlan.ts +171 -0
  527. package/src/WebFetch.ts +194 -0
  528. package/src/WebSearch.ts +165 -0
  529. package/src/Write.ts +195 -0
  530. package/src/index.ts +154 -0
  531. package/src/internal/ApplyPatch.ts +601 -0
  532. package/src/internal/CodexText.ts +182 -0
  533. package/src/internal/Declaration.ts +60 -0
  534. package/src/internal/Diagnostics.ts +134 -0
  535. package/src/internal/EnvelopePrecheck.ts +233 -0
  536. package/src/internal/Exec.ts +314 -0
  537. package/src/internal/FileMutation.ts +231 -0
  538. package/src/internal/FsFailure.ts +51 -0
  539. package/src/internal/GitWorktree.ts +473 -0
  540. package/src/internal/Grouping.ts +106 -0
  541. package/src/internal/Html.ts +87 -0
  542. package/src/internal/Http.ts +209 -0
  543. package/src/internal/HttpNetwork.ts +153 -0
  544. package/src/internal/Ignore.ts +135 -0
  545. package/src/internal/LinearRegex.ts +173 -0
  546. package/src/internal/Match.ts +172 -0
  547. package/src/internal/Paths.ts +42 -0
  548. package/src/internal/Preserve.ts +108 -0
  549. package/src/internal/Prune.ts +62 -0
  550. package/src/internal/SearchContract.ts +77 -0
  551. package/src/internal/Symbols.ts +88 -0
  552. package/src/internal/TestReport.ts +194 -0
  553. package/src/internal/Text.ts +170 -0
  554. package/src/internal/Url.ts +23 -0
  555. package/src/internal/Walk.ts +176 -0
@@ -0,0 +1,489 @@
1
+ /**
2
+ * The validation and matching rules every Search implementation shares.
3
+ *
4
+ * Both peers shipped here match globs through {@link includedByGlobs} and
5
+ * canonicalize them through {@link canonicalGlob}, so the two implementations
6
+ * cannot drift on what a pattern means, and an external peer binding its own
7
+ * `Search` builds on the same functions. {@link unsatisfiableNotice} is the
8
+ * shared explanation for empty answers caused by impossible globs or ignore
9
+ * exclusions.
10
+ *
11
+ * @since 1.0.0
12
+ */
13
+
14
+ import type * as Path from "@smthrs/kernel/Path"
15
+ import { Effect } from "effect"
16
+ import type * as FileSystem from "effect/FileSystem"
17
+ import * as LinearRegex from "./internal/LinearRegex.ts"
18
+ import { escapeRegex, invalidPattern, rejectionPrefix } from "./internal/SearchContract.ts"
19
+ import * as Walk from "./internal/Walk.ts"
20
+ import type * as StdError from "./StdError.ts"
21
+
22
+ /**
23
+ * Validates Smithers Ripgrep ASCII v1. It is deliberately the intersection of
24
+ * Rust regex and JavaScript RegExp: ASCII patterns, captures, alternation,
25
+ * ASCII character classes and ordinary quantifiers. Lookaround,
26
+ * backreferences, named/inline groups, Unicode/shorthand classes and control
27
+ * escapes are rejected before either implementation runs. Patterns are
28
+ * limited to 4096 bytes, counted repetitions to 1000, group nesting to 128
29
+ * and expanded state machines to 8192 states. Both peers share this
30
+ * compilation boundary; portable matching never backtracks over input.
31
+ *
32
+ * @category validation
33
+ * @since 1.0.0
34
+ */
35
+ export const validatePattern = (pattern: string, fixedStrings: boolean): StdError.StdError | undefined => {
36
+ if (pattern.length > 4096) return invalidPattern(pattern, "patterns must not exceed 4096 bytes")
37
+ if (!/^[\x20-\x7e]*$/.test(pattern)) return invalidPattern(pattern, "patterns must contain printable ASCII only")
38
+ if (fixedStrings) return undefined
39
+ if (pattern.includes("(?")) return invalidPattern(pattern, "special groups and lookaround are not supported")
40
+ let inClass = false
41
+ let classCharacters = 0
42
+ for (let index = 0; index < pattern.length; index++) {
43
+ const character = pattern[index]
44
+ if (character === "\\") {
45
+ const escaped = pattern[index + 1]
46
+ if (escaped === undefined || /[A-Za-z0-9]/.test(escaped)) {
47
+ return invalidPattern(pattern, "backreferences, shorthand classes and encoded escapes are not supported")
48
+ }
49
+ index++
50
+ if (inClass) classCharacters++
51
+ continue
52
+ }
53
+ if (character === "[" && inClass) {
54
+ return invalidPattern(pattern, "nested and named character classes are not supported")
55
+ }
56
+ if (character === "[") {
57
+ inClass = true
58
+ classCharacters = 0
59
+ continue
60
+ }
61
+ if (character === "{" && !inClass) {
62
+ const closing = pattern.indexOf("}", index + 1)
63
+ if (closing >= 0) {
64
+ const counts = pattern.slice(index + 1, closing).split(",").filter((value) => value.length > 0)
65
+ if (counts.some((value) => /^\d+$/.test(value) && Number(value) > 1000)) {
66
+ return invalidPattern(pattern, "repetition counts above 1000 are not supported")
67
+ }
68
+ }
69
+ }
70
+ if (character === "]" && inClass) {
71
+ if (classCharacters === 0 || (classCharacters === 1 && pattern[index - 1] === "^")) {
72
+ return invalidPattern(pattern, "empty character classes are not supported")
73
+ }
74
+ inClass = false
75
+ continue
76
+ }
77
+ if (inClass) {
78
+ if (
79
+ (character === "&" && pattern[index + 1] === "&") ||
80
+ (character === "-" && pattern[index + 1] === "-") ||
81
+ (character === "~" && pattern[index + 1] === "~")
82
+ ) {
83
+ return invalidPattern(pattern, "character-class set operations are not supported")
84
+ }
85
+ classCharacters++
86
+ }
87
+ }
88
+ try {
89
+ new RegExp(pattern, "u")
90
+ } catch (error) {
91
+ return invalidPattern(pattern, malformed(pattern) ?? engineReason(error as Error))
92
+ }
93
+ try {
94
+ LinearRegex.compile(pattern, false)
95
+ return undefined
96
+ } catch (error) {
97
+ // LinearRegex.compile throws Error for its nesting and state budgets.
98
+ return invalidPattern(pattern, (error as Error).message)
99
+ }
100
+ }
101
+
102
+ const countedRepetition = /^\{\d+(,\d*)?\}/
103
+
104
+ /**
105
+ * Names the first construct that keeps `pattern` from parsing, with its
106
+ * 1-based column and the escape that makes it literal.
107
+ *
108
+ * A caller told only that a pattern is unsupported guesses at which character
109
+ * broke it; `Rule({` reads as a literal search to its author and as an unclosed
110
+ * group plus a count with no digits to the parser. Only the syntax errors a
111
+ * search author commonly makes are named here; anything else falls back to the
112
+ * engine's own reason.
113
+ */
114
+ const malformed = (pattern: string): string | undefined => {
115
+ const open: Array<number> = []
116
+ let repeatable = false
117
+ for (let index = 0; index < pattern.length; index++) {
118
+ const character = pattern[index]!
119
+ const at = `"${character}" at column ${index + 1}`
120
+ if (character === "\\") {
121
+ index++
122
+ repeatable = true
123
+ continue
124
+ }
125
+ if (character === "[") {
126
+ let end = index + 1
127
+ if (pattern[end] === "^") end++
128
+ while (end < pattern.length && pattern[end] !== "]") end += pattern[end] === "\\" ? 2 : 1
129
+ if (end >= pattern.length) return `${at} is never closed; write \\[ for a literal bracket`
130
+ index = end
131
+ repeatable = true
132
+ continue
133
+ }
134
+ if (character === "(") {
135
+ open.push(index)
136
+ repeatable = false
137
+ continue
138
+ }
139
+ if (character === ")") {
140
+ if (open.pop() === undefined) return `${at} closes nothing; write \\) for a literal parenthesis`
141
+ repeatable = true
142
+ continue
143
+ }
144
+ if (character === "{") {
145
+ const count = countedRepetition.exec(pattern.slice(index))
146
+ if (count === null) return `${at} is not a repetition count; write \\{ for a literal brace`
147
+ if (!repeatable) return `${at} repeats nothing; write \\{ for a literal brace`
148
+ index += count[0].length - 1
149
+ continue
150
+ }
151
+ if (character === "}" || character === "]") {
152
+ return `${at} closes nothing; write \\${character} for a literal ${character === "}" ? "brace" : "bracket"}`
153
+ }
154
+ if (character === "*" || character === "+" || character === "?") {
155
+ if (!repeatable) return `${at} repeats nothing; write \\${character} for a literal ${character}`
156
+ continue
157
+ }
158
+ repeatable = character !== "|" && character !== "^" && character !== "$"
159
+ }
160
+ const unclosed = open.at(-1)
161
+ return unclosed === undefined
162
+ ? undefined
163
+ : `"(" at column ${unclosed + 1} is never closed; write \\( for a literal parenthesis`
164
+ }
165
+
166
+ /** The JavaScript engine's reason, without its prefix or its echo of the pattern. */
167
+ const engineReason = (error: Error): string => {
168
+ const reason = error.message.replace(/^Invalid regular expression: (\/.*\/[a-z]*: )?/, "").trim()
169
+ return `invalid expression: ${reason}`
170
+ }
171
+
172
+ /**
173
+ * Whether `error` is a pattern or glob rejection this contract wrote.
174
+ *
175
+ * Those messages are host-authored and name the construct that broke, so a
176
+ * caller may show them to a model. A peer's `invalid_pattern` built from
177
+ * `rg`'s stderr is not one of them and stays private.
178
+ *
179
+ * @category validation
180
+ * @since 1.0.0
181
+ */
182
+ export const isContractRejection = (error: StdError.StdError): boolean =>
183
+ error.code === "invalid_pattern" && error.message.startsWith(`${rejectionPrefix}"`)
184
+
185
+ /**
186
+ * Validates the portable `-g` grammar before either peer sees it.
187
+ *
188
+ * @category validation
189
+ * @since 1.0.0
190
+ */
191
+ export const validateGlob = (glob: string): StdError.StdError | undefined => {
192
+ const pattern = glob.startsWith("!") ? glob.slice(1) : glob
193
+ // `rg` drops the trailing spaces and then ignores a glob that is left blank,
194
+ // which filters nothing at all. Rejecting it keeps a typo from silently
195
+ // widening the search instead of narrowing it.
196
+ if (pattern.replace(/ +$/, "").length === 0) return invalidPattern(glob, "glob patterns must not be empty")
197
+ if (!/^[\x20-\x7e]*$/.test(pattern)) return invalidPattern(glob, "globs must contain printable ASCII only")
198
+ if (pattern.includes("\\") || pattern.includes("[") || pattern.includes("]")) {
199
+ return invalidPattern(glob, "glob escapes and character classes are not supported")
200
+ }
201
+ let inBrace = false
202
+ let alternatives = 1
203
+ let expansionCount = 1
204
+ for (let index = 0; index < pattern.length; index++) {
205
+ const character = pattern[index]
206
+ if (character === "{") {
207
+ if (inBrace) return invalidPattern(glob, "nested brace alternatives are not supported")
208
+ inBrace = true
209
+ alternatives = 1
210
+ } else if (character === "," && inBrace) {
211
+ alternatives++
212
+ } else if (character === "}") {
213
+ if (!inBrace || alternatives < 2) return invalidPattern(glob, "braces must contain alternatives")
214
+ inBrace = false
215
+ expansionCount *= alternatives
216
+ if (expansionCount > 256) return invalidPattern(glob, "glob brace expansion exceeds 256 patterns")
217
+ }
218
+ }
219
+ if (inBrace) return invalidPattern(glob, "glob braces must be balanced")
220
+ return undefined
221
+ }
222
+
223
+ /**
224
+ * Compiles a pattern after common validation.
225
+ *
226
+ * @category matching
227
+ * @since 1.0.0
228
+ */
229
+ export const expression = (pattern: string, fixedStrings: boolean, insensitive: boolean): RegExp => {
230
+ const input = fixedStrings ? escapeRegex(pattern) : pattern
231
+ let source = ""
232
+ let inClass = false
233
+ for (let index = 0; index < input.length; index++) {
234
+ const character = input[index]
235
+ if (character === "\\") {
236
+ source += `${character}${input[index + 1] ?? ""}`
237
+ index++
238
+ } else if (character === "[") {
239
+ inClass = true
240
+ source += character
241
+ } else if (character === "]" && inClass) {
242
+ inClass = false
243
+ source += character
244
+ } else if (!inClass && character === ".") {
245
+ source += "[^\\n]"
246
+ } else if (!inClass && character === "$") {
247
+ source += "(?![\\s\\S])"
248
+ } else {
249
+ source += character
250
+ }
251
+ }
252
+ return new RegExp(source, insensitive ? "iu" : "u")
253
+ }
254
+
255
+ const expandBraces = (pattern: string): ReadonlyArray<string> => {
256
+ const opening = pattern.indexOf("{")
257
+ if (opening < 0) return [pattern]
258
+ const closing = pattern.indexOf("}", opening + 1)
259
+ if (closing < 0) return [pattern]
260
+ const alternatives = pattern.slice(opening + 1, closing).split(",")
261
+ if (alternatives.length < 2) return [pattern]
262
+ return alternatives.flatMap((alternative) =>
263
+ expandBraces(
264
+ `${pattern.slice(0, opening)}${alternative}${pattern.slice(closing + 1)}`
265
+ )
266
+ )
267
+ }
268
+
269
+ const globExpression = (pattern: string): RegExp => {
270
+ let source = ""
271
+ for (let index = 0; index < pattern.length; index++) {
272
+ const character = pattern[index]!
273
+ const next = pattern[index + 1]
274
+ if (
275
+ character === "*" && next === "*" &&
276
+ (index === 0 || pattern[index - 1] === "/") &&
277
+ (pattern[index + 2] === undefined || pattern[index + 2] === "/")
278
+ ) {
279
+ source += pattern[index + 2] === "/" ? "(?:.*/)?" : ".*"
280
+ index += pattern[index + 2] === "/" ? 2 : 1
281
+ } else if (character === "*") source += "[^/]*"
282
+ else if (character === "?") source += "[^/]"
283
+ else source += character.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&")
284
+ }
285
+ return new RegExp(`^${source}$`)
286
+ }
287
+
288
+ const outsidePrintableAscii = /[^\x20-\x7e]/
289
+
290
+ // Printable ASCII is its own UTF-8 encoding, and paths are overwhelmingly
291
+ // printable ASCII, so the encoder only runs for the paths that need it.
292
+ const utf8ByteString = (value: string): string =>
293
+ outsidePrintableAscii.test(value)
294
+ ? Array.from(new TextEncoder().encode(value), (byte) => String.fromCharCode(byte)).join("")
295
+ : value
296
+
297
+ /**
298
+ * Rewrites a glob into the one spelling both peers match against.
299
+ *
300
+ * `.` is never a path component either peer can produce, so a leading `./` and
301
+ * every interior `/./` would silently make a pattern unmatchable. Both are
302
+ * folded into the root anchor, which is what a caller writing `./src/**` means.
303
+ * Trailing spaces are dropped because `rg` reads `-g` by gitignore's rules and
304
+ * drops them too, so `"a.ts "` finds `a.ts` in the native peer and has to find
305
+ * it in the in-process one. A leading `!` is preserved so exclusion globs
306
+ * canonicalize the same way.
307
+ *
308
+ * @category matching
309
+ * @since 1.0.0
310
+ */
311
+ export const canonicalGlob = (glob: string): string => {
312
+ const excluded = glob.startsWith("!")
313
+ const pattern = excluded ? glob.slice(1) : glob
314
+ const canonical = pattern.replace(/ +$/, "").replace(/\/\.(?=\/)/g, "").replace(/^\.\//, "/")
315
+ return excluded ? `!${canonical}` : canonical
316
+ }
317
+
318
+ interface CompiledGlob {
319
+ readonly byPath: boolean
320
+ readonly expression: RegExp
321
+ }
322
+
323
+ const compiled = new Map<string, ReadonlyArray<CompiledGlob>>()
324
+
325
+ /**
326
+ * Compiles one glob into its alternatives, once per distinct pattern.
327
+ *
328
+ * The in-process peer asks whether a pattern matches for every candidate file
329
+ * in the walk, so canonicalizing, brace expanding and compiling the pattern
330
+ * inside that loop makes the work quadratic in the tree. A pattern compiles to
331
+ * the same matchers every time, so the compilation is cached; the cache is
332
+ * bounded because callers, not the tree, supply the patterns.
333
+ */
334
+ const compileGlob = (pattern: string): ReadonlyArray<CompiledGlob> => {
335
+ const cached = compiled.get(pattern)
336
+ if (cached !== undefined) return cached
337
+ const matchers = expandBraces(canonicalGlob(pattern)).map((expanded) => {
338
+ const rooted = expanded.startsWith("/")
339
+ const normalized = rooted ? expanded.slice(1) : expanded
340
+ return { byPath: rooted || normalized.includes("/"), expression: globExpression(normalized) }
341
+ })
342
+ if (compiled.size >= 256) compiled.clear()
343
+ compiled.set(pattern, matchers)
344
+ return matchers
345
+ }
346
+
347
+ /**
348
+ * Matches the supported `-g` subset against a root-relative candidate path.
349
+ *
350
+ * A pattern without `/` matches the basename at any depth. Every other pattern
351
+ * is matched against the candidate's path relative to the search root, anchored
352
+ * at the root, whether or not it carries the optional leading `/`.
353
+ *
354
+ * @category matching
355
+ * @since 1.0.0
356
+ */
357
+ export const matchesGlob = (pattern: string, relative: string, basename: string): boolean =>
358
+ compileGlob(pattern).some((matcher) => matcher.expression.test(utf8ByteString(matcher.byPath ? relative : basename)))
359
+
360
+ /**
361
+ * Applies ripgrep `-g` ordering: positive globs include and `!` globs exclude.
362
+ *
363
+ * @category matching
364
+ * @since 1.0.0
365
+ */
366
+ export const includedByGlobs = (globs: ReadonlyArray<string>, relative: string, basename: string): boolean => {
367
+ const positives = globs.filter((glob) => !glob.startsWith("!"))
368
+ let included = positives.length === 0
369
+ for (const glob of globs) {
370
+ const excluded = glob.startsWith("!")
371
+ if (matchesGlob(excluded ? glob.slice(1) : glob, relative, basename)) included = !excluded
372
+ }
373
+ return included
374
+ }
375
+
376
+ const wildcard = /[*?{}]/
377
+
378
+ const literalDirectory = (pattern: string): ReadonlyArray<string> => {
379
+ if (!pattern.includes("/")) return []
380
+ const segments = pattern.replace(/^\//, "").split("/").filter((segment) => segment.length > 0)
381
+ const wildcardAt = segments.findIndex((segment) => wildcard.test(segment))
382
+ return wildcardAt < 0 ? segments.slice(0, -1) : segments.slice(0, wildcardAt)
383
+ }
384
+
385
+ const rootRelativeSuffix = (pattern: string, root: string, path: Path.Path): string | undefined => {
386
+ const anchored = pattern.replace(/^\/+/, "")
387
+ const patternRoot = path.sep === "\\" ? root.replaceAll("\\", "/") : root
388
+ const stem = patternRoot.replace(/^\/+/, "").replace(/\/+$/, "")
389
+ return stem.length > 0 && anchored.startsWith(`${stem}/`) ? anchored.slice(stem.length + 1) : undefined
390
+ }
391
+
392
+ const unsatisfiedReason = (
393
+ options: {
394
+ readonly fileSystem: FileSystem.FileSystem
395
+ readonly path: Path.Path
396
+ readonly root: string
397
+ readonly hidden: boolean
398
+ },
399
+ pattern: string
400
+ ): Effect.Effect<string | undefined> =>
401
+ Effect.gen(function*() {
402
+ const reasons: Array<string> = []
403
+ for (const alternative of expandBraces(pattern)) {
404
+ const segments = literalDirectory(alternative)
405
+ if (segments.length === 0) return undefined
406
+ const skipped = segments.find((segment) => Walk.skippedDirectories.has(segment))
407
+ if (skipped !== undefined) {
408
+ reasons.push(`${skipped} is never descended into; name it as the search root to look inside it`)
409
+ continue
410
+ }
411
+ if (!options.hidden && segments.some((segment) => segment.startsWith("."))) {
412
+ reasons.push("hidden paths are excluded unless hidden is true")
413
+ continue
414
+ }
415
+ const directory = segments.join("/")
416
+ const present = yield* options.fileSystem.stat(options.path.join(options.root, directory)).pipe(
417
+ Effect.map((info) => info.type === "Directory"),
418
+ Effect.orElseSucceed(() => false)
419
+ )
420
+ if (present) return undefined
421
+ reasons.push(`there is no ${directory} directory there`)
422
+ }
423
+ return reasons[0]
424
+ })
425
+
426
+ /**
427
+ * Explains the positive globs that no file under the root could ever match.
428
+ *
429
+ * A search that returns nothing is ambiguous: the tree may hold no match, or
430
+ * the pattern may be unsatisfiable — an absolute path written where a
431
+ * root-relative one belongs, a directory that does not exist, a skipped
432
+ * directory, a hidden path with `hidden` left false. Callers attach the result
433
+ * to `notice` when they produced no entries. Ignore exclusions name the
434
+ * `noIgnore: true` escape hatch, while impossible globs explain the correction.
435
+ * This keeps the cases
436
+ * distinguishable. Exclusion globs are ignored: excluding what is not there
437
+ * changes nothing.
438
+ *
439
+ * @category diagnostics
440
+ * @since 1.0.0
441
+ */
442
+ export const unsatisfiableNotice = (options: {
443
+ readonly fileSystem: FileSystem.FileSystem
444
+ readonly path: Path.Path
445
+ readonly root: string
446
+ readonly globs: ReadonlyArray<string>
447
+ readonly noIgnore?: boolean | undefined
448
+ readonly ignored?: boolean | undefined
449
+ readonly hidden: boolean
450
+ }): Effect.Effect<string | undefined> =>
451
+ Effect.gen(function*() {
452
+ // Globs filter a walk. A root that names one file is searched whatever the
453
+ // globs say — `rg` always searches a path given on the command line — so
454
+ // there is no unsatisfiable pattern to report and no directory to stat.
455
+ const walkable = yield* options.fileSystem.stat(options.root).pipe(
456
+ Effect.map((info) => info.type === "Directory"),
457
+ Effect.orElseSucceed(() => false)
458
+ )
459
+ if (!walkable) return undefined
460
+ const sentences: Array<string> = []
461
+ for (const glob of options.globs) {
462
+ if (glob.startsWith("!")) continue
463
+ const canonical = canonicalGlob(glob)
464
+ const reason = yield* unsatisfiedReason(options, canonical)
465
+ if (reason === undefined) continue
466
+ const suffix = rootRelativeSuffix(canonical, options.root, options.path)
467
+ sentences.push(
468
+ `No file under ${options.root} can match "${glob}": ${
469
+ suffix === undefined
470
+ ? reason
471
+ : `glob patterns are relative to the search root, so use "${suffix}" instead`
472
+ }.`
473
+ )
474
+ }
475
+ // An impossible glob cannot be repaired by opting out of ignores.
476
+ if (sentences.length > 0 && sentences.length === options.globs.filter((glob) => !glob.startsWith("!")).length) {
477
+ return sentences.join(" ")
478
+ }
479
+ const included = (relative: string, basename: string) => includedByGlobs(options.globs, relative, basename)
480
+ const ignored = options.noIgnore ? false : options.ignored ??
481
+ (yield* Walk.files(options.fileSystem, options.path, options.root, options.hidden, false, included).pipe(
482
+ Effect.map((walked) => walked.ignored),
483
+ Effect.orElseSucceed(() => false)
484
+ ))
485
+ if (ignored) {
486
+ sentences.push("No results; ignore files excluded paths. Retry with noIgnore: true to include them.")
487
+ }
488
+ return sentences.length === 0 ? undefined : sentences.join(" ")
489
+ })
@@ -0,0 +1,201 @@
1
+ /**
2
+ * shell_command flow declaration and portable handler.
3
+ *
4
+ * A Codex CLI clone of the `shell_command` tool: string command, `workdir`,
5
+ * `timeout_ms`, and the Codex output format (`Exit code:` / `Wall time:` /
6
+ * `Output:` with middle token-budget truncation).
7
+ *
8
+ * Codex's `sandbox_permissions` / `justification` / `prefix_rule` approval
9
+ * parameters are deliberately absent: the permission kernel owns
10
+ * sandboxing and escalation in this harness.
11
+ *
12
+ * @since 1.0.0
13
+ */
14
+
15
+ import type * as ChildProcessSpawner from "@smthrs/kernel/ChildProcessSpawner"
16
+ import * as Effect from "effect/Effect"
17
+ import * as Schema from "effect/Schema"
18
+ import { formatExecOutputForModel } from "./internal/CodexText.ts"
19
+ import { capability, envelope } from "./internal/Declaration.ts"
20
+ import * as Exec from "./internal/Exec.ts"
21
+ import type * as StdError from "./StdError.ts"
22
+
23
+ /**
24
+ * Registry name for the shell_command flow. Matches the Codex CLI tool name.
25
+ *
26
+ * @category identifiers
27
+ * @since 1.0.0
28
+ */
29
+ export const name = "shell_command"
30
+
31
+ /**
32
+ * Model-facing description of the shell_command flow. Matches the Codex CLI
33
+ * (non-Windows) description.
34
+ *
35
+ * @category descriptions
36
+ * @since 1.0.0
37
+ */
38
+ export const description = "Runs a shell command and returns its output.\n" +
39
+ "- Always set the `workdir` param when using the shell_command function. Do not use `cd` unless absolutely necessary."
40
+
41
+ /**
42
+ * Default command timeout in milliseconds, matching Codex.
43
+ *
44
+ * @category constants
45
+ * @since 1.0.0
46
+ */
47
+ export const DEFAULT_TIMEOUT_MS = 10_000
48
+
49
+ /**
50
+ * Maximum bytes retained from each stream while a shell command executes.
51
+ *
52
+ * This is far above the 10,000-token model budget because
53
+ * `formatExecOutputForModel` keeps the head and tail while the capture bound
54
+ * keeps only the tail. Commands below this bound therefore render byte for
55
+ * byte as before, while larger output costs the bound instead of its full size.
56
+ *
57
+ * @category constants
58
+ * @since 1.0.0
59
+ */
60
+ export const MAX_CAPTURE_BYTES = 8_000_000
61
+
62
+ /**
63
+ * Default output token budget, matching Codex.
64
+ *
65
+ * @category constants
66
+ * @since 1.0.0
67
+ */
68
+ export const DEFAULT_MAX_OUTPUT_TOKENS = 10_000
69
+
70
+ /**
71
+ * Timeout exit code reported to the model, matching Codex exec.
72
+ *
73
+ * @category constants
74
+ * @since 1.0.0
75
+ */
76
+ export const TIMEOUT_EXIT_CODE = 124
77
+
78
+ /**
79
+ * Input schema for the shell_command flow.
80
+ *
81
+ * @category schemas
82
+ * @since 1.0.0
83
+ */
84
+ export const Input = Schema.Struct({
85
+ command: Schema.String.annotate({ description: "Shell script to run in the user's default shell." }),
86
+ workdir: Schema.optional(
87
+ Schema.String.annotate({ description: "Working directory for the command. Defaults to the turn cwd." })
88
+ ),
89
+ timeout_ms: Schema.optional(
90
+ Schema.Number.annotate({ description: "Maximum command runtime. Defaults to 10000 ms." })
91
+ )
92
+ })
93
+
94
+ /**
95
+ * Decoded input accepted by the `shell_command` flow.
96
+ *
97
+ * @category models
98
+ * @since 1.0.0
99
+ */
100
+ export type Input = typeof Input.Type
101
+
102
+ /**
103
+ * Output schema for the shell_command flow.
104
+ *
105
+ * @category schemas
106
+ * @since 1.0.0
107
+ */
108
+ export const Output = Schema.Struct({
109
+ output: Schema.String.annotate({
110
+ description: "Codex-formatted result: exit code, wall time, and possibly middle-truncated output"
111
+ }),
112
+ exitCode: Schema.Number.annotate({ description: "Command exit code; 124 when the command timed out" })
113
+ })
114
+
115
+ /**
116
+ * Decoded output returned by the `shell_command` flow.
117
+ *
118
+ * @category models
119
+ * @since 1.0.0
120
+ */
121
+ export type Output = typeof Output.Type
122
+
123
+ /**
124
+ * Static conservative effect envelope for the shell_command flow.
125
+ *
126
+ * @category effects
127
+ * @since 1.0.0
128
+ */
129
+ export const effects = envelope({ tier: "irreversible", mode: "expected", reads: [], writes: [] })
130
+
131
+ /**
132
+ * Narrows the effect envelope for a decoded invocation.
133
+ *
134
+ * A command line carries no declared envelope, so an invocation says nothing
135
+ * the registry-time worst case does not already say.
136
+ *
137
+ * @category effects
138
+ * @since 1.0.0
139
+ */
140
+ export const effectsFor = (_input: typeof Input.Type) => effects
141
+
142
+ /**
143
+ * Capabilities required by the shell_command flow.
144
+ *
145
+ * @category capabilities
146
+ * @since 1.0.0
147
+ */
148
+ export const capabilities = [capability("proc:spawn", "*")]
149
+
150
+ /**
151
+ * Declaration-only shell_command flow.
152
+ *
153
+ * @category flows
154
+ * @since 1.0.0
155
+ */
156
+ export const flow = { name, description, input: Input, output: Output, capabilities, effects } as const
157
+
158
+ /**
159
+ * Executes a shell command through the permission-aware kernel service and
160
+ * renders the Codex model-facing output format.
161
+ *
162
+ * Non-zero exit codes and timeouts remain successful values, exactly as in
163
+ * Codex; only host and permission failures use the typed error channel.
164
+ *
165
+ * @category handlers
166
+ * @since 1.0.0
167
+ */
168
+ export const run = Effect.fn("ShellCommand.run")(function*(
169
+ input: typeof Input.Type
170
+ ): Effect.fn.Return<typeof Output.Type, StdError.StdError, ChildProcessSpawner.ChildProcessSpawner> {
171
+ const timeoutMs = input.timeout_ms ?? DEFAULT_TIMEOUT_MS
172
+ const startedAt = Date.now()
173
+ const result = yield* Exec.exec(input.command, {
174
+ ...(input.workdir === undefined ? {} : { cwd: input.workdir }),
175
+ timeoutMs,
176
+ maxCaptureBytes: MAX_CAPTURE_BYTES
177
+ }).pipe(
178
+ Effect.map((value) => ({ timedOut: false, value })),
179
+ Effect.catch((error) =>
180
+ error.code === "timeout"
181
+ ? Effect.succeed({ timedOut: true, value: { exitCode: TIMEOUT_EXIT_CODE, stderr: "", stdout: "" } })
182
+ : Effect.fail(Exec.toStdError(input.command, error))
183
+ )
184
+ )
185
+ const durationSeconds = (Date.now() - startedAt) / 1_000
186
+ const aggregated = result.value.stderr === ""
187
+ ? result.value.stdout
188
+ : result.value.stdout === ""
189
+ ? result.value.stderr
190
+ : `${result.value.stdout}${result.value.stderr}`
191
+ return {
192
+ exitCode: result.value.exitCode,
193
+ output: formatExecOutputForModel({
194
+ durationSeconds,
195
+ exitCode: result.value.exitCode,
196
+ maxOutputTokens: DEFAULT_MAX_OUTPUT_TOKENS,
197
+ output: aggregated,
198
+ ...(result.timedOut ? { timedOutAfterMs: timeoutMs } : {})
199
+ })
200
+ }
201
+ })