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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (555) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/LICENSE +21 -0
  3. package/README.md +152 -2
  4. package/dist/cjs/ApplyPatch.d.ts +174 -0
  5. package/dist/cjs/ApplyPatch.d.ts.map +1 -0
  6. package/dist/cjs/ApplyPatch.js +309 -0
  7. package/dist/cjs/ApplyPatch.js.map +7 -0
  8. package/dist/cjs/Bash.d.ts +380 -0
  9. package/dist/cjs/Bash.d.ts.map +1 -0
  10. package/dist/cjs/Bash.js +332 -0
  11. package/dist/cjs/Bash.js.map +7 -0
  12. package/dist/cjs/Checkpoints.d.ts +279 -0
  13. package/dist/cjs/Checkpoints.d.ts.map +1 -0
  14. package/dist/cjs/Checkpoints.js +145 -0
  15. package/dist/cjs/Checkpoints.js.map +7 -0
  16. package/dist/cjs/Container.d.ts +132 -0
  17. package/dist/cjs/Container.d.ts.map +1 -0
  18. package/dist/cjs/Container.js +113 -0
  19. package/dist/cjs/Container.js.map +7 -0
  20. package/dist/cjs/Edit.d.ts +203 -0
  21. package/dist/cjs/Edit.d.ts.map +1 -0
  22. package/dist/cjs/Edit.js +258 -0
  23. package/dist/cjs/Edit.js.map +7 -0
  24. package/dist/cjs/ExaWebSearch.d.ts +22 -0
  25. package/dist/cjs/ExaWebSearch.d.ts.map +1 -0
  26. package/dist/cjs/ExaWebSearch.js +138 -0
  27. package/dist/cjs/ExaWebSearch.js.map +7 -0
  28. package/dist/cjs/Explore.d.ts +328 -0
  29. package/dist/cjs/Explore.d.ts.map +1 -0
  30. package/dist/cjs/Explore.js +90 -0
  31. package/dist/cjs/Explore.js.map +7 -0
  32. package/dist/cjs/Fetch.d.ts +130 -0
  33. package/dist/cjs/Fetch.d.ts.map +1 -0
  34. package/dist/cjs/Fetch.js +64 -0
  35. package/dist/cjs/Fetch.js.map +7 -0
  36. package/dist/cjs/Glob.d.ts +204 -0
  37. package/dist/cjs/Glob.d.ts.map +1 -0
  38. package/dist/cjs/Glob.js +94 -0
  39. package/dist/cjs/Glob.js.map +7 -0
  40. package/dist/cjs/Grep.d.ts +347 -0
  41. package/dist/cjs/Grep.d.ts.map +1 -0
  42. package/dist/cjs/Grep.js +181 -0
  43. package/dist/cjs/Grep.js.map +7 -0
  44. package/dist/cjs/HttpPost.d.ts +130 -0
  45. package/dist/cjs/HttpPost.d.ts.map +1 -0
  46. package/dist/cjs/HttpPost.js +72 -0
  47. package/dist/cjs/HttpPost.js.map +7 -0
  48. package/dist/cjs/LanguageServer.d.ts +90 -0
  49. package/dist/cjs/LanguageServer.d.ts.map +1 -0
  50. package/dist/cjs/LanguageServer.js +60 -0
  51. package/dist/cjs/LanguageServer.js.map +7 -0
  52. package/dist/cjs/Ls.d.ts +164 -0
  53. package/dist/cjs/Ls.d.ts.map +1 -0
  54. package/dist/cjs/Ls.js +136 -0
  55. package/dist/cjs/Ls.js.map +7 -0
  56. package/dist/cjs/Lsp.d.ts +125 -0
  57. package/dist/cjs/Lsp.d.ts.map +1 -0
  58. package/dist/cjs/Lsp.js +137 -0
  59. package/dist/cjs/Lsp.js.map +7 -0
  60. package/dist/cjs/Manifest.d.ts +918 -0
  61. package/dist/cjs/Manifest.d.ts.map +1 -0
  62. package/dist/cjs/Manifest.js +144 -0
  63. package/dist/cjs/Manifest.js.map +7 -0
  64. package/dist/cjs/NativeSearch.d.ts +38 -0
  65. package/dist/cjs/NativeSearch.d.ts.map +1 -0
  66. package/dist/cjs/NativeSearch.js +326 -0
  67. package/dist/cjs/NativeSearch.js.map +7 -0
  68. package/dist/cjs/NodeLanguageServer.d.ts +128 -0
  69. package/dist/cjs/NodeLanguageServer.d.ts.map +1 -0
  70. package/dist/cjs/NodeLanguageServer.js +796 -0
  71. package/dist/cjs/NodeLanguageServer.js.map +7 -0
  72. package/dist/cjs/PortableSearch.d.ts +24 -0
  73. package/dist/cjs/PortableSearch.d.ts.map +1 -0
  74. package/dist/cjs/PortableSearch.js +233 -0
  75. package/dist/cjs/PortableSearch.js.map +7 -0
  76. package/dist/cjs/Probe.d.ts +193 -0
  77. package/dist/cjs/Probe.d.ts.map +1 -0
  78. package/dist/cjs/Probe.js +134 -0
  79. package/dist/cjs/Probe.js.map +7 -0
  80. package/dist/cjs/Read.d.ts +189 -0
  81. package/dist/cjs/Read.d.ts.map +1 -0
  82. package/dist/cjs/Read.js +223 -0
  83. package/dist/cjs/Read.js.map +7 -0
  84. package/dist/cjs/Relocate.d.ts +73 -0
  85. package/dist/cjs/Relocate.d.ts.map +1 -0
  86. package/dist/cjs/Relocate.js +72 -0
  87. package/dist/cjs/Relocate.js.map +7 -0
  88. package/dist/cjs/Search.d.ts +163 -0
  89. package/dist/cjs/Search.d.ts.map +1 -0
  90. package/dist/cjs/Search.js +51 -0
  91. package/dist/cjs/Search.js.map +7 -0
  92. package/dist/cjs/SearchConformance.d.ts +115 -0
  93. package/dist/cjs/SearchConformance.d.ts.map +1 -0
  94. package/dist/cjs/SearchConformance.js +172 -0
  95. package/dist/cjs/SearchConformance.js.map +7 -0
  96. package/dist/cjs/SearchContract.d.ts +114 -0
  97. package/dist/cjs/SearchContract.d.ts.map +1 -0
  98. package/dist/cjs/SearchContract.js +339 -0
  99. package/dist/cjs/SearchContract.js.map +7 -0
  100. package/dist/cjs/ShellCommand.d.ts +164 -0
  101. package/dist/cjs/ShellCommand.d.ts.map +1 -0
  102. package/dist/cjs/ShellCommand.js +102 -0
  103. package/dist/cjs/ShellCommand.js.map +7 -0
  104. package/dist/cjs/StdError.d.ts +55 -0
  105. package/dist/cjs/StdError.d.ts.map +1 -0
  106. package/dist/cjs/StdError.js +74 -0
  107. package/dist/cjs/StdError.js.map +7 -0
  108. package/dist/cjs/TestRun.d.ts +311 -0
  109. package/dist/cjs/TestRun.d.ts.map +1 -0
  110. package/dist/cjs/TestRun.js +228 -0
  111. package/dist/cjs/TestRun.js.map +7 -0
  112. package/dist/cjs/TestRunner.d.ts +102 -0
  113. package/dist/cjs/TestRunner.d.ts.map +1 -0
  114. package/dist/cjs/TestRunner.js +54 -0
  115. package/dist/cjs/TestRunner.js.map +7 -0
  116. package/dist/cjs/TreeFingerprint.d.ts +140 -0
  117. package/dist/cjs/TreeFingerprint.d.ts.map +1 -0
  118. package/dist/cjs/TreeFingerprint.js +87 -0
  119. package/dist/cjs/TreeFingerprint.js.map +7 -0
  120. package/dist/cjs/UpdatePlan.d.ts +152 -0
  121. package/dist/cjs/UpdatePlan.d.ts.map +1 -0
  122. package/dist/cjs/UpdatePlan.js +87 -0
  123. package/dist/cjs/UpdatePlan.js.map +7 -0
  124. package/dist/cjs/WebFetch.d.ts +134 -0
  125. package/dist/cjs/WebFetch.d.ts.map +1 -0
  126. package/dist/cjs/WebFetch.js +140 -0
  127. package/dist/cjs/WebFetch.js.map +7 -0
  128. package/dist/cjs/WebSearch.d.ts +181 -0
  129. package/dist/cjs/WebSearch.d.ts.map +1 -0
  130. package/dist/cjs/WebSearch.js +86 -0
  131. package/dist/cjs/WebSearch.js.map +7 -0
  132. package/dist/cjs/Write.d.ts +147 -0
  133. package/dist/cjs/Write.d.ts.map +1 -0
  134. package/dist/cjs/Write.js +122 -0
  135. package/dist/cjs/Write.js.map +7 -0
  136. package/dist/cjs/index.d.ts +127 -0
  137. package/dist/cjs/index.d.ts.map +1 -0
  138. package/dist/cjs/index.js +99 -0
  139. package/dist/cjs/index.js.map +7 -0
  140. package/dist/cjs/internal/ApplyPatch.d.ts +145 -0
  141. package/dist/cjs/internal/ApplyPatch.d.ts.map +1 -0
  142. package/dist/cjs/internal/ApplyPatch.js +462 -0
  143. package/dist/cjs/internal/ApplyPatch.js.map +7 -0
  144. package/dist/cjs/internal/CodexText.d.ts +73 -0
  145. package/dist/cjs/internal/CodexText.d.ts.map +1 -0
  146. package/dist/cjs/internal/CodexText.js +108 -0
  147. package/dist/cjs/internal/CodexText.js.map +7 -0
  148. package/dist/cjs/internal/Declaration.d.ts +49 -0
  149. package/dist/cjs/internal/Declaration.d.ts.map +1 -0
  150. package/dist/cjs/internal/Declaration.js +46 -0
  151. package/dist/cjs/internal/Declaration.js.map +7 -0
  152. package/dist/cjs/internal/Diagnostics.d.ts +77 -0
  153. package/dist/cjs/internal/Diagnostics.d.ts.map +1 -0
  154. package/dist/cjs/internal/Diagnostics.js +89 -0
  155. package/dist/cjs/internal/Diagnostics.js.map +7 -0
  156. package/dist/cjs/internal/EnvelopePrecheck.d.ts +67 -0
  157. package/dist/cjs/internal/EnvelopePrecheck.d.ts.map +1 -0
  158. package/dist/cjs/internal/EnvelopePrecheck.js +124 -0
  159. package/dist/cjs/internal/EnvelopePrecheck.js.map +7 -0
  160. package/dist/cjs/internal/Exec.d.ts +139 -0
  161. package/dist/cjs/internal/Exec.d.ts.map +1 -0
  162. package/dist/cjs/internal/Exec.js +158 -0
  163. package/dist/cjs/internal/Exec.js.map +7 -0
  164. package/dist/cjs/internal/FileMutation.d.ts +109 -0
  165. package/dist/cjs/internal/FileMutation.d.ts.map +1 -0
  166. package/dist/cjs/internal/FileMutation.js +116 -0
  167. package/dist/cjs/internal/FileMutation.js.map +7 -0
  168. package/dist/cjs/internal/FsFailure.d.ts +38 -0
  169. package/dist/cjs/internal/FsFailure.d.ts.map +1 -0
  170. package/dist/cjs/internal/FsFailure.js +40 -0
  171. package/dist/cjs/internal/FsFailure.js.map +7 -0
  172. package/dist/cjs/internal/GitWorktree.d.ts +108 -0
  173. package/dist/cjs/internal/GitWorktree.d.ts.map +1 -0
  174. package/dist/cjs/internal/GitWorktree.js +276 -0
  175. package/dist/cjs/internal/GitWorktree.js.map +7 -0
  176. package/dist/cjs/internal/Grouping.d.ts +51 -0
  177. package/dist/cjs/internal/Grouping.d.ts.map +1 -0
  178. package/dist/cjs/internal/Grouping.js +83 -0
  179. package/dist/cjs/internal/Grouping.js.map +7 -0
  180. package/dist/cjs/internal/Html.d.ts +20 -0
  181. package/dist/cjs/internal/Html.d.ts.map +1 -0
  182. package/dist/cjs/internal/Html.js +81 -0
  183. package/dist/cjs/internal/Html.js.map +7 -0
  184. package/dist/cjs/internal/Http.d.ts +95 -0
  185. package/dist/cjs/internal/Http.d.ts.map +1 -0
  186. package/dist/cjs/internal/Http.js +153 -0
  187. package/dist/cjs/internal/Http.js.map +7 -0
  188. package/dist/cjs/internal/HttpNetwork.d.ts +27 -0
  189. package/dist/cjs/internal/HttpNetwork.d.ts.map +1 -0
  190. package/dist/cjs/internal/HttpNetwork.js +146 -0
  191. package/dist/cjs/internal/HttpNetwork.js.map +7 -0
  192. package/dist/cjs/internal/Ignore.d.ts +37 -0
  193. package/dist/cjs/internal/Ignore.d.ts.map +1 -0
  194. package/dist/cjs/internal/Ignore.js +100 -0
  195. package/dist/cjs/internal/Ignore.js.map +7 -0
  196. package/dist/cjs/internal/LinearRegex.d.ts +19 -0
  197. package/dist/cjs/internal/LinearRegex.d.ts.map +1 -0
  198. package/dist/cjs/internal/LinearRegex.js +166 -0
  199. package/dist/cjs/internal/LinearRegex.js.map +7 -0
  200. package/dist/cjs/internal/Match.d.ts +85 -0
  201. package/dist/cjs/internal/Match.d.ts.map +1 -0
  202. package/dist/cjs/internal/Match.js +99 -0
  203. package/dist/cjs/internal/Match.js.map +7 -0
  204. package/dist/cjs/internal/Paths.d.ts +23 -0
  205. package/dist/cjs/internal/Paths.d.ts.map +1 -0
  206. package/dist/cjs/internal/Paths.js +52 -0
  207. package/dist/cjs/internal/Paths.js.map +7 -0
  208. package/dist/cjs/internal/Preserve.d.ts +25 -0
  209. package/dist/cjs/internal/Preserve.d.ts.map +1 -0
  210. package/dist/cjs/internal/Preserve.js +88 -0
  211. package/dist/cjs/internal/Preserve.js.map +7 -0
  212. package/dist/cjs/internal/Prune.d.ts +35 -0
  213. package/dist/cjs/internal/Prune.d.ts.map +1 -0
  214. package/dist/cjs/internal/Prune.js +54 -0
  215. package/dist/cjs/internal/Prune.js.map +7 -0
  216. package/dist/cjs/internal/SearchContract.d.ts +63 -0
  217. package/dist/cjs/internal/SearchContract.d.ts.map +1 -0
  218. package/dist/cjs/internal/SearchContract.js +46 -0
  219. package/dist/cjs/internal/SearchContract.js.map +7 -0
  220. package/dist/cjs/internal/Symbols.d.ts +39 -0
  221. package/dist/cjs/internal/Symbols.d.ts.map +1 -0
  222. package/dist/cjs/internal/Symbols.js +59 -0
  223. package/dist/cjs/internal/Symbols.js.map +7 -0
  224. package/dist/cjs/internal/TestReport.d.ts +52 -0
  225. package/dist/cjs/internal/TestReport.d.ts.map +1 -0
  226. package/dist/cjs/internal/TestReport.js +131 -0
  227. package/dist/cjs/internal/TestReport.js.map +7 -0
  228. package/dist/cjs/internal/Text.d.ts +114 -0
  229. package/dist/cjs/internal/Text.d.ts.map +1 -0
  230. package/dist/cjs/internal/Text.js +82 -0
  231. package/dist/cjs/internal/Text.js.map +7 -0
  232. package/dist/cjs/internal/Url.d.ts +13 -0
  233. package/dist/cjs/internal/Url.d.ts.map +1 -0
  234. package/dist/cjs/internal/Url.js +35 -0
  235. package/dist/cjs/internal/Url.js.map +7 -0
  236. package/dist/cjs/internal/Walk.d.ts +72 -0
  237. package/dist/cjs/internal/Walk.d.ts.map +1 -0
  238. package/dist/cjs/internal/Walk.js +108 -0
  239. package/dist/cjs/internal/Walk.js.map +7 -0
  240. package/dist/cjs/package.json +1 -0
  241. package/dist/esm/ApplyPatch.d.ts +174 -0
  242. package/dist/esm/ApplyPatch.d.ts.map +1 -0
  243. package/dist/esm/ApplyPatch.js +346 -0
  244. package/dist/esm/ApplyPatch.js.map +1 -0
  245. package/dist/esm/Bash.d.ts +380 -0
  246. package/dist/esm/Bash.d.ts.map +1 -0
  247. package/dist/esm/Bash.js +505 -0
  248. package/dist/esm/Bash.js.map +1 -0
  249. package/dist/esm/Checkpoints.d.ts +279 -0
  250. package/dist/esm/Checkpoints.d.ts.map +1 -0
  251. package/dist/esm/Checkpoints.js +298 -0
  252. package/dist/esm/Checkpoints.js.map +1 -0
  253. package/dist/esm/Container.d.ts +132 -0
  254. package/dist/esm/Container.d.ts.map +1 -0
  255. package/dist/esm/Container.js +151 -0
  256. package/dist/esm/Container.js.map +1 -0
  257. package/dist/esm/Edit.d.ts +203 -0
  258. package/dist/esm/Edit.d.ts.map +1 -0
  259. package/dist/esm/Edit.js +296 -0
  260. package/dist/esm/Edit.js.map +1 -0
  261. package/dist/esm/ExaWebSearch.d.ts +22 -0
  262. package/dist/esm/ExaWebSearch.d.ts.map +1 -0
  263. package/dist/esm/ExaWebSearch.js +107 -0
  264. package/dist/esm/ExaWebSearch.js.map +1 -0
  265. package/dist/esm/Explore.d.ts +328 -0
  266. package/dist/esm/Explore.d.ts.map +1 -0
  267. package/dist/esm/Explore.js +106 -0
  268. package/dist/esm/Explore.js.map +1 -0
  269. package/dist/esm/Fetch.d.ts +130 -0
  270. package/dist/esm/Fetch.d.ts.map +1 -0
  271. package/dist/esm/Fetch.js +91 -0
  272. package/dist/esm/Fetch.js.map +1 -0
  273. package/dist/esm/Glob.d.ts +204 -0
  274. package/dist/esm/Glob.d.ts.map +1 -0
  275. package/dist/esm/Glob.js +177 -0
  276. package/dist/esm/Glob.js.map +1 -0
  277. package/dist/esm/Grep.d.ts +347 -0
  278. package/dist/esm/Grep.d.ts.map +1 -0
  279. package/dist/esm/Grep.js +289 -0
  280. package/dist/esm/Grep.js.map +1 -0
  281. package/dist/esm/HttpPost.d.ts +130 -0
  282. package/dist/esm/HttpPost.d.ts.map +1 -0
  283. package/dist/esm/HttpPost.js +89 -0
  284. package/dist/esm/HttpPost.js.map +1 -0
  285. package/dist/esm/LanguageServer.d.ts +90 -0
  286. package/dist/esm/LanguageServer.d.ts.map +1 -0
  287. package/dist/esm/LanguageServer.js +57 -0
  288. package/dist/esm/LanguageServer.js.map +1 -0
  289. package/dist/esm/Ls.d.ts +164 -0
  290. package/dist/esm/Ls.d.ts.map +1 -0
  291. package/dist/esm/Ls.js +178 -0
  292. package/dist/esm/Ls.js.map +1 -0
  293. package/dist/esm/Lsp.d.ts +125 -0
  294. package/dist/esm/Lsp.d.ts.map +1 -0
  295. package/dist/esm/Lsp.js +165 -0
  296. package/dist/esm/Lsp.js.map +1 -0
  297. package/dist/esm/Manifest.d.ts +918 -0
  298. package/dist/esm/Manifest.d.ts.map +1 -0
  299. package/dist/esm/Manifest.js +153 -0
  300. package/dist/esm/Manifest.js.map +1 -0
  301. package/dist/esm/NativeSearch.d.ts +38 -0
  302. package/dist/esm/NativeSearch.d.ts.map +1 -0
  303. package/dist/esm/NativeSearch.js +378 -0
  304. package/dist/esm/NativeSearch.js.map +1 -0
  305. package/dist/esm/NodeLanguageServer.d.ts +128 -0
  306. package/dist/esm/NodeLanguageServer.d.ts.map +1 -0
  307. package/dist/esm/NodeLanguageServer.js +843 -0
  308. package/dist/esm/NodeLanguageServer.js.map +1 -0
  309. package/dist/esm/PortableSearch.d.ts +24 -0
  310. package/dist/esm/PortableSearch.d.ts.map +1 -0
  311. package/dist/esm/PortableSearch.js +240 -0
  312. package/dist/esm/PortableSearch.js.map +1 -0
  313. package/dist/esm/Probe.d.ts +193 -0
  314. package/dist/esm/Probe.d.ts.map +1 -0
  315. package/dist/esm/Probe.js +225 -0
  316. package/dist/esm/Probe.js.map +1 -0
  317. package/dist/esm/Read.d.ts +189 -0
  318. package/dist/esm/Read.d.ts.map +1 -0
  319. package/dist/esm/Read.js +300 -0
  320. package/dist/esm/Read.js.map +1 -0
  321. package/dist/esm/Relocate.d.ts +73 -0
  322. package/dist/esm/Relocate.d.ts.map +1 -0
  323. package/dist/esm/Relocate.js +153 -0
  324. package/dist/esm/Relocate.js.map +1 -0
  325. package/dist/esm/Search.d.ts +163 -0
  326. package/dist/esm/Search.d.ts.map +1 -0
  327. package/dist/esm/Search.js +47 -0
  328. package/dist/esm/Search.js.map +1 -0
  329. package/dist/esm/SearchConformance.d.ts +115 -0
  330. package/dist/esm/SearchConformance.d.ts.map +1 -0
  331. package/dist/esm/SearchConformance.js +193 -0
  332. package/dist/esm/SearchConformance.js.map +1 -0
  333. package/dist/esm/SearchContract.d.ts +114 -0
  334. package/dist/esm/SearchContract.d.ts.map +1 -0
  335. package/dist/esm/SearchContract.js +461 -0
  336. package/dist/esm/SearchContract.js.map +1 -0
  337. package/dist/esm/ShellCommand.d.ts +164 -0
  338. package/dist/esm/ShellCommand.d.ts.map +1 -0
  339. package/dist/esm/ShellCommand.js +159 -0
  340. package/dist/esm/ShellCommand.js.map +1 -0
  341. package/dist/esm/StdError.d.ts +55 -0
  342. package/dist/esm/StdError.d.ts.map +1 -0
  343. package/dist/esm/StdError.js +71 -0
  344. package/dist/esm/StdError.js.map +1 -0
  345. package/dist/esm/TestRun.d.ts +311 -0
  346. package/dist/esm/TestRun.d.ts.map +1 -0
  347. package/dist/esm/TestRun.js +316 -0
  348. package/dist/esm/TestRun.js.map +1 -0
  349. package/dist/esm/TestRunner.d.ts +102 -0
  350. package/dist/esm/TestRunner.d.ts.map +1 -0
  351. package/dist/esm/TestRunner.js +68 -0
  352. package/dist/esm/TestRunner.js.map +1 -0
  353. package/dist/esm/TreeFingerprint.d.ts +140 -0
  354. package/dist/esm/TreeFingerprint.d.ts.map +1 -0
  355. package/dist/esm/TreeFingerprint.js +170 -0
  356. package/dist/esm/TreeFingerprint.js.map +1 -0
  357. package/dist/esm/UpdatePlan.d.ts +152 -0
  358. package/dist/esm/UpdatePlan.d.ts.map +1 -0
  359. package/dist/esm/UpdatePlan.js +129 -0
  360. package/dist/esm/UpdatePlan.js.map +1 -0
  361. package/dist/esm/WebFetch.d.ts +134 -0
  362. package/dist/esm/WebFetch.d.ts.map +1 -0
  363. package/dist/esm/WebFetch.js +151 -0
  364. package/dist/esm/WebFetch.js.map +1 -0
  365. package/dist/esm/WebSearch.d.ts +181 -0
  366. package/dist/esm/WebSearch.d.ts.map +1 -0
  367. package/dist/esm/WebSearch.js +134 -0
  368. package/dist/esm/WebSearch.js.map +1 -0
  369. package/dist/esm/Write.d.ts +147 -0
  370. package/dist/esm/Write.d.ts.map +1 -0
  371. package/dist/esm/Write.js +144 -0
  372. package/dist/esm/Write.js.map +1 -0
  373. package/dist/esm/index.d.ts +127 -0
  374. package/dist/esm/index.d.ts.map +1 -0
  375. package/dist/esm/index.js +127 -0
  376. package/dist/esm/index.js.map +1 -0
  377. package/dist/esm/internal/ApplyPatch.d.ts +145 -0
  378. package/dist/esm/internal/ApplyPatch.d.ts.map +1 -0
  379. package/dist/esm/internal/ApplyPatch.js +489 -0
  380. package/dist/esm/internal/ApplyPatch.js.map +1 -0
  381. package/dist/esm/internal/CodexText.d.ts +73 -0
  382. package/dist/esm/internal/CodexText.d.ts.map +1 -0
  383. package/dist/esm/internal/CodexText.js +156 -0
  384. package/dist/esm/internal/CodexText.js.map +1 -0
  385. package/dist/esm/internal/Declaration.d.ts +49 -0
  386. package/dist/esm/internal/Declaration.d.ts.map +1 -0
  387. package/dist/esm/internal/Declaration.js +42 -0
  388. package/dist/esm/internal/Declaration.js.map +1 -0
  389. package/dist/esm/internal/Diagnostics.d.ts +77 -0
  390. package/dist/esm/internal/Diagnostics.d.ts.map +1 -0
  391. package/dist/esm/internal/Diagnostics.js +99 -0
  392. package/dist/esm/internal/Diagnostics.js.map +1 -0
  393. package/dist/esm/internal/EnvelopePrecheck.d.ts +67 -0
  394. package/dist/esm/internal/EnvelopePrecheck.d.ts.map +1 -0
  395. package/dist/esm/internal/EnvelopePrecheck.js +167 -0
  396. package/dist/esm/internal/EnvelopePrecheck.js.map +1 -0
  397. package/dist/esm/internal/Exec.d.ts +139 -0
  398. package/dist/esm/internal/Exec.d.ts.map +1 -0
  399. package/dist/esm/internal/Exec.js +193 -0
  400. package/dist/esm/internal/Exec.js.map +1 -0
  401. package/dist/esm/internal/FileMutation.d.ts +109 -0
  402. package/dist/esm/internal/FileMutation.d.ts.map +1 -0
  403. package/dist/esm/internal/FileMutation.js +123 -0
  404. package/dist/esm/internal/FileMutation.js.map +1 -0
  405. package/dist/esm/internal/FsFailure.d.ts +38 -0
  406. package/dist/esm/internal/FsFailure.d.ts.map +1 -0
  407. package/dist/esm/internal/FsFailure.js +39 -0
  408. package/dist/esm/internal/FsFailure.js.map +1 -0
  409. package/dist/esm/internal/GitWorktree.d.ts +108 -0
  410. package/dist/esm/internal/GitWorktree.d.ts.map +1 -0
  411. package/dist/esm/internal/GitWorktree.js +352 -0
  412. package/dist/esm/internal/GitWorktree.js.map +1 -0
  413. package/dist/esm/internal/Grouping.d.ts +51 -0
  414. package/dist/esm/internal/Grouping.d.ts.map +1 -0
  415. package/dist/esm/internal/Grouping.js +99 -0
  416. package/dist/esm/internal/Grouping.js.map +1 -0
  417. package/dist/esm/internal/Html.d.ts +20 -0
  418. package/dist/esm/internal/Html.d.ts.map +1 -0
  419. package/dist/esm/internal/Html.js +70 -0
  420. package/dist/esm/internal/Html.js.map +1 -0
  421. package/dist/esm/internal/Http.d.ts +95 -0
  422. package/dist/esm/internal/Http.d.ts.map +1 -0
  423. package/dist/esm/internal/Http.js +154 -0
  424. package/dist/esm/internal/Http.js.map +1 -0
  425. package/dist/esm/internal/HttpNetwork.d.ts +27 -0
  426. package/dist/esm/internal/HttpNetwork.d.ts.map +1 -0
  427. package/dist/esm/internal/HttpNetwork.js +114 -0
  428. package/dist/esm/internal/HttpNetwork.js.map +1 -0
  429. package/dist/esm/internal/Ignore.d.ts +37 -0
  430. package/dist/esm/internal/Ignore.d.ts.map +1 -0
  431. package/dist/esm/internal/Ignore.js +128 -0
  432. package/dist/esm/internal/Ignore.js.map +1 -0
  433. package/dist/esm/internal/LinearRegex.d.ts +19 -0
  434. package/dist/esm/internal/LinearRegex.d.ts.map +1 -0
  435. package/dist/esm/internal/LinearRegex.js +176 -0
  436. package/dist/esm/internal/LinearRegex.js.map +1 -0
  437. package/dist/esm/internal/Match.d.ts +85 -0
  438. package/dist/esm/internal/Match.d.ts.map +1 -0
  439. package/dist/esm/internal/Match.js +142 -0
  440. package/dist/esm/internal/Match.js.map +1 -0
  441. package/dist/esm/internal/Paths.d.ts +23 -0
  442. package/dist/esm/internal/Paths.d.ts.map +1 -0
  443. package/dist/esm/internal/Paths.js +40 -0
  444. package/dist/esm/internal/Paths.js.map +1 -0
  445. package/dist/esm/internal/Preserve.d.ts +25 -0
  446. package/dist/esm/internal/Preserve.d.ts.map +1 -0
  447. package/dist/esm/internal/Preserve.js +70 -0
  448. package/dist/esm/internal/Preserve.js.map +1 -0
  449. package/dist/esm/internal/Prune.d.ts +35 -0
  450. package/dist/esm/internal/Prune.d.ts.map +1 -0
  451. package/dist/esm/internal/Prune.js +60 -0
  452. package/dist/esm/internal/Prune.js.map +1 -0
  453. package/dist/esm/internal/SearchContract.d.ts +63 -0
  454. package/dist/esm/internal/SearchContract.d.ts.map +1 -0
  455. package/dist/esm/internal/SearchContract.js +66 -0
  456. package/dist/esm/internal/SearchContract.js.map +1 -0
  457. package/dist/esm/internal/Symbols.d.ts +39 -0
  458. package/dist/esm/internal/Symbols.d.ts.map +1 -0
  459. package/dist/esm/internal/Symbols.js +79 -0
  460. package/dist/esm/internal/Symbols.js.map +1 -0
  461. package/dist/esm/internal/TestReport.d.ts +52 -0
  462. package/dist/esm/internal/TestReport.d.ts.map +1 -0
  463. package/dist/esm/internal/TestReport.js +172 -0
  464. package/dist/esm/internal/TestReport.js.map +1 -0
  465. package/dist/esm/internal/Text.d.ts +114 -0
  466. package/dist/esm/internal/Text.d.ts.map +1 -0
  467. package/dist/esm/internal/Text.js +130 -0
  468. package/dist/esm/internal/Text.js.map +1 -0
  469. package/dist/esm/internal/Url.d.ts +13 -0
  470. package/dist/esm/internal/Url.d.ts.map +1 -0
  471. package/dist/esm/internal/Url.js +27 -0
  472. package/dist/esm/internal/Url.js.map +1 -0
  473. package/dist/esm/internal/Walk.d.ts +72 -0
  474. package/dist/esm/internal/Walk.d.ts.map +1 -0
  475. package/dist/esm/internal/Walk.js +126 -0
  476. package/dist/esm/internal/Walk.js.map +1 -0
  477. package/docs/README.md +117 -0
  478. package/docs/api.md +472 -0
  479. package/docs/concepts/effects-and-capabilities.md +136 -0
  480. package/docs/concepts/flows-and-handlers.md +115 -0
  481. package/docs/concepts/limits-and-disclosure.md +102 -0
  482. package/docs/concepts/search-contract.md +182 -0
  483. package/docs/guides/bind-the-standard-flows.md +114 -0
  484. package/docs/guides/implement-a-search-peer.md +133 -0
  485. package/docs/guides/pin-a-checkpoint.md +141 -0
  486. package/docs/guides/query-a-language-server.md +257 -0
  487. package/docs/guides/reach-the-network.md +141 -0
  488. package/docs/guides/read-and-edit-a-file.md +240 -0
  489. package/docs/guides/run-a-shell-command.md +215 -0
  490. package/docs/guides/run-the-test-suite.md +154 -0
  491. package/docs/guides/search-a-workspace.md +148 -0
  492. package/docs/installation.md +111 -0
  493. package/docs/quickstart.md +125 -0
  494. package/docs/reference/flows.md +556 -0
  495. package/docs/troubleshooting.md +322 -0
  496. package/package.json +439 -3
  497. package/src/ApplyPatch.ts +458 -0
  498. package/src/Bash.ts +607 -0
  499. package/src/Checkpoints.ts +422 -0
  500. package/src/Container.ts +212 -0
  501. package/src/Edit.ts +366 -0
  502. package/src/ExaWebSearch.ts +145 -0
  503. package/src/Explore.ts +139 -0
  504. package/src/Fetch.ts +117 -0
  505. package/src/Glob.ts +200 -0
  506. package/src/Grep.ts +320 -0
  507. package/src/HttpPost.ts +120 -0
  508. package/src/LanguageServer.ts +110 -0
  509. package/src/Ls.ts +228 -0
  510. package/src/Lsp.ts +184 -0
  511. package/src/Manifest.ts +162 -0
  512. package/src/NativeSearch.ts +457 -0
  513. package/src/NodeLanguageServer.ts +1148 -0
  514. package/src/PortableSearch.ts +264 -0
  515. package/src/Probe.ts +284 -0
  516. package/src/Read.ts +359 -0
  517. package/src/Relocate.ts +166 -0
  518. package/src/Search.ts +185 -0
  519. package/src/SearchConformance.ts +288 -0
  520. package/src/SearchContract.ts +489 -0
  521. package/src/ShellCommand.ts +201 -0
  522. package/src/StdError.ts +80 -0
  523. package/src/TestRun.ts +401 -0
  524. package/src/TestRunner.ts +119 -0
  525. package/src/TreeFingerprint.ts +200 -0
  526. package/src/UpdatePlan.ts +171 -0
  527. package/src/WebFetch.ts +194 -0
  528. package/src/WebSearch.ts +165 -0
  529. package/src/Write.ts +195 -0
  530. package/src/index.ts +154 -0
  531. package/src/internal/ApplyPatch.ts +601 -0
  532. package/src/internal/CodexText.ts +182 -0
  533. package/src/internal/Declaration.ts +60 -0
  534. package/src/internal/Diagnostics.ts +134 -0
  535. package/src/internal/EnvelopePrecheck.ts +233 -0
  536. package/src/internal/Exec.ts +314 -0
  537. package/src/internal/FileMutation.ts +231 -0
  538. package/src/internal/FsFailure.ts +51 -0
  539. package/src/internal/GitWorktree.ts +491 -0
  540. package/src/internal/Grouping.ts +106 -0
  541. package/src/internal/Html.ts +87 -0
  542. package/src/internal/Http.ts +209 -0
  543. package/src/internal/HttpNetwork.ts +153 -0
  544. package/src/internal/Ignore.ts +135 -0
  545. package/src/internal/LinearRegex.ts +173 -0
  546. package/src/internal/Match.ts +172 -0
  547. package/src/internal/Paths.ts +42 -0
  548. package/src/internal/Preserve.ts +108 -0
  549. package/src/internal/Prune.ts +62 -0
  550. package/src/internal/SearchContract.ts +77 -0
  551. package/src/internal/Symbols.ts +88 -0
  552. package/src/internal/TestReport.ts +194 -0
  553. package/src/internal/Text.ts +170 -0
  554. package/src/internal/Url.ts +23 -0
  555. package/src/internal/Walk.ts +176 -0
package/src/Read.ts ADDED
@@ -0,0 +1,359 @@
1
+ /**
2
+ * Read flow declaration and portable handler.
3
+ *
4
+ * `content` is raw file text. It used to be rendered as `NNN\t<line>`, and that
5
+ * rendering was the single most expensive tool defect measured on the 45-instance
6
+ * SWE-bench trace program: an anchor copied out of a read carried the gutter, so
7
+ * every `edit` built from a read missed, and every cell that wanted a literal
8
+ * line had to strip the prefix in JavaScript first. Two instances (django-13346,
9
+ * django-14351) spent whole frames writing string surgery against text the file
10
+ * does not contain. Line numbers are facts about the page, so they are page
11
+ * fields — `startLine` and `endLine` — and never bytes inside the text.
12
+ *
13
+ * Every line in `content` is a whole line: a page cut short by the byte budget
14
+ * drops its trailing partial line rather than handing back a fragment that looks
15
+ * like an anchor and is not one. CRLF lines retain their trailing CR; only
16
+ * the page's final LF is omitted.
17
+ *
18
+ * @since 1.0.0
19
+ */
20
+
21
+ import * as Effect from "effect/Effect"
22
+ import * as FileSystem from "effect/FileSystem"
23
+ import * as Option from "effect/Option"
24
+ import * as Schema from "effect/Schema"
25
+ import { capability, envelope } from "./internal/Declaration.ts"
26
+ import * as FileMutation from "./internal/FileMutation.ts"
27
+ import * as FsFailure from "./internal/FsFailure.ts"
28
+ import { DEFAULT_READ_LIMIT, MAX_LINE_CHARS, MAX_OUTPUT_BYTES, notice, slice, truncateBytes } from "./internal/Text.ts"
29
+ import * as StdError from "./StdError.ts"
30
+
31
+ export { Preconditions, ReadSession, type VersionedFileSystem } from "./internal/FileMutation.ts"
32
+
33
+ /**
34
+ * Registry name for the read flow.
35
+ *
36
+ * @category identifiers
37
+ * @since 1.0.0
38
+ */
39
+ export const name = "read"
40
+
41
+ /**
42
+ * Model-facing description of the read flow.
43
+ *
44
+ * @category descriptions
45
+ * @since 1.0.0
46
+ */
47
+ export const description =
48
+ "Read a text file by 1-based offset and limit. content is RAW file text with no line-number prefixes, so any line of it is an edit anchor as it stands; the numbers are startLine/endLine."
49
+
50
+ /**
51
+ * Input schema for the read flow.
52
+ *
53
+ * @category schemas
54
+ * @since 1.0.0
55
+ */
56
+ export const Input = Schema.Struct({
57
+ path: Schema.String.annotate({ description: "Path of the text file to read" }),
58
+ offset: Schema.optional(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))).annotate({
59
+ description: "1-based line offset"
60
+ }),
61
+ limit: Schema.optional(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))).annotate({
62
+ description: "Maximum number of lines to return"
63
+ })
64
+ })
65
+
66
+ /**
67
+ * Decoded input accepted by the `read` flow.
68
+ *
69
+ * @category models
70
+ * @since 1.0.0
71
+ */
72
+ export type Input = typeof Input.Type
73
+
74
+ /**
75
+ * Output schema for the read flow.
76
+ *
77
+ * @category schemas
78
+ * @since 1.0.0
79
+ */
80
+ export const Output = Schema.Struct({
81
+ content: Schema.String.annotate({
82
+ description: "Raw page text, preserving CR bytes and omitting the final LF; never line-number prefixed"
83
+ }),
84
+ startLine: Schema.Number.annotate({ description: "First returned 1-based line number" }),
85
+ endLine: Schema.Number.annotate({
86
+ description: "Last returned 1-based line number, or startLine - 1 when no lines are returned"
87
+ }),
88
+ totalLines: Schema.Number.annotate({ description: "Total number of source lines" }),
89
+ truncated: Schema.Boolean.annotate({ description: "Whether displayed output was truncated" }),
90
+ notice: Schema.optional(Schema.String.annotate({ description: "Truncation disclosure" }))
91
+ })
92
+
93
+ /**
94
+ * Decoded output returned by the `read` flow.
95
+ *
96
+ * @category models
97
+ * @since 1.0.0
98
+ */
99
+ export type Output = typeof Output.Type
100
+
101
+ /**
102
+ * Static conservative effect envelope for the read flow.
103
+ *
104
+ * @category effects
105
+ * @since 1.0.0
106
+ */
107
+ export const effects = envelope({
108
+ tier: "sealed",
109
+ mode: "hermetic",
110
+ reads: ["/**"],
111
+ writes: []
112
+ })
113
+
114
+ /**
115
+ * Narrows the read effect envelope to one input path.
116
+ *
117
+ * @category effects
118
+ * @since 1.0.0
119
+ */
120
+ export const effectsFor = (input: typeof Input.Type) =>
121
+ envelope({
122
+ tier: "sealed",
123
+ mode: "hermetic",
124
+ reads: [input.path],
125
+ writes: []
126
+ })
127
+
128
+ /**
129
+ * Capabilities required by the read flow.
130
+ *
131
+ * @category capabilities
132
+ * @since 1.0.0
133
+ */
134
+ export const capabilities = [capability("fs:read", "/**")]
135
+
136
+ /**
137
+ * Declaration-only read flow.
138
+ *
139
+ * @category flows
140
+ * @since 1.0.0
141
+ */
142
+ export const flow = { name, description, input: Input, output: Output, capabilities, effects } as const
143
+
144
+ /**
145
+ * What a call to this flow does, for a reader of a run.
146
+ *
147
+ * Display metadata only. `@smthrs/registry` `Descriptor.FlowActivity` is the
148
+ * governing vocabulary and `StandardFlows` binds this value onto the flow's
149
+ * descriptor, where the binding site checks it. `declarationDigest` excludes
150
+ * it, so declaring it cannot invalidate a call identity or a cached prompt.
151
+ *
152
+ * @category presentation
153
+ * @since 1.0.0-rc.0
154
+ */
155
+ export const activity = "reads" as const
156
+
157
+ /**
158
+ * How one recorded call to this flow reads: the verb for each settlement, the
159
+ * input field that is its subject, and the measured output fields a one-line
160
+ * summary may count.
161
+ *
162
+ * Display metadata only, governed by `@smthrs/registry`
163
+ * `Descriptor.CallPresentation` and checked where `StandardFlows` binds it.
164
+ *
165
+ * @category presentation
166
+ * @since 1.0.0-rc.0
167
+ */
168
+ export const presentation = {
169
+ verb: { pending: "reading", success: "read", failure: "failed to read" },
170
+ subject: "path",
171
+ result: "read"
172
+ } as const
173
+
174
+ const clipLine = (line: string): string => {
175
+ let scalars = 0
176
+ let end = 0
177
+ for (const scalar of line) {
178
+ if (scalars === MAX_LINE_CHARS) return line.slice(0, end)
179
+ scalars++
180
+ end += scalar.length
181
+ }
182
+ return line
183
+ }
184
+
185
+ /**
186
+ * The largest file `read` loads.
187
+ *
188
+ * `read` decodes the whole file to count its lines, so the file is held in
189
+ * memory twice over: its bytes and a UTF-16 string. Past this bound a page
190
+ * read would cost the host gigabytes for a window of a few thousand lines,
191
+ * and past 2 GiB Node cannot load the file at all.
192
+ *
193
+ * @category constants
194
+ * @since 1.0.0
195
+ */
196
+ export const MAX_READ_FILE_BYTES = 64 * 1024 * 1024
197
+
198
+ const fileError = (path: string) => FsFailure.reading(path, `File not found: ${path}`)
199
+
200
+ const sharedPrefix = (left: string, right: string): number => {
201
+ let index = 0
202
+ while (index < left.length && index < right.length && left[index] === right[index]) index++
203
+ return index
204
+ }
205
+
206
+ /**
207
+ * Where a guessed relative path stops existing, and what is there instead.
208
+ *
209
+ * A worker that guesses `packages/smithers/flow/src/Flow.ts` learns nothing
210
+ * from "not found" and guesses again. Naming the nearest directory that exists
211
+ * and its entries, closest name first, turns the next call into a choice.
212
+ * Absolute paths and paths that climb out with `..` get no listing: the call
213
+ * declared one file, and the working tree is the only place a listing is
214
+ * already the caller's to read.
215
+ */
216
+ const nearest = (
217
+ fileSystem: FileSystem.FileSystem,
218
+ path: string
219
+ ): Effect.Effect<string> =>
220
+ Effect.gen(function*() {
221
+ const segments = path.split("/").filter((segment) => segment !== "" && segment !== ".")
222
+ if (path.startsWith("/") || segments.includes("..")) return ""
223
+ for (let depth = segments.length - 1; depth >= 0; depth--) {
224
+ const directory = segments.slice(0, depth).join("/")
225
+ const entries = yield* fileSystem.readDirectory(directory === "" ? "." : directory).pipe(Effect.option)
226
+ if (Option.isNone(entries)) continue
227
+ const missing = segments[depth]!.toLowerCase()
228
+ const ranked = entries.value
229
+ .filter((entry) => !entry.startsWith("."))
230
+ .map((entry) => ({ entry, score: sharedPrefix(entry.toLowerCase(), missing) }))
231
+ .sort((left, right) => right.score - left.score)
232
+ .map(({ entry }) => entry)
233
+ if (ranked.length === 0) return ""
234
+ const shown = ranked.slice(0, 12).join(", ")
235
+ const more = ranked.length > 12 ? ` and ${ranked.length - 12} more` : ""
236
+ return `. ${directory === "" ? "The working directory" : directory} holds: ${shown}${more}.`
237
+ }
238
+ return ""
239
+ })
240
+
241
+ const missingFile = (fileSystem: FileSystem.FileSystem, path: string) =>
242
+ Effect.flatMap(nearest(fileSystem, path), (hint) =>
243
+ Effect.fail(
244
+ new StdError.StdError({
245
+ code: "not_found",
246
+ message: `File not found: ${path}${hint}`,
247
+ path
248
+ })
249
+ ))
250
+
251
+ /**
252
+ * Reads, validates, and renders one page of a UTF-8 text file.
253
+ *
254
+ * The kernel filesystem exposes bytes rather than a guaranteed UTF-8 string,
255
+ * so decoding is deliberately fatal to keep binary input in the typed channel.
256
+ *
257
+ * @category handlers
258
+ * @since 1.0.0
259
+ */
260
+ export const run = Effect.fn("Read.run")(function*(
261
+ input: typeof Input.Type
262
+ ): Effect.fn.Return<typeof Output.Type, StdError.StdError, FileSystem.FileSystem> {
263
+ const fileSystem = yield* FileSystem.FileSystem
264
+ const info = yield* fileSystem.stat(input.path).pipe(
265
+ Effect.catchTag(
266
+ "PlatformError",
267
+ (error) =>
268
+ error.reason._tag === "NotFound"
269
+ ? missingFile(fileSystem, input.path)
270
+ : Effect.fail(fileError(input.path)(error))
271
+ )
272
+ )
273
+ if (info.type === "Directory") {
274
+ return yield* Effect.fail(
275
+ new StdError.StdError({
276
+ code: "is_directory",
277
+ message: `Cannot read a directory: ${input.path}`,
278
+ path: input.path
279
+ })
280
+ )
281
+ }
282
+ if (info.type !== "File") {
283
+ return yield* Effect.fail(
284
+ new StdError.StdError({
285
+ code: "not_found",
286
+ message: `File not found: ${input.path}`,
287
+ path: input.path
288
+ })
289
+ )
290
+ }
291
+ const size = Number(info.size)
292
+ if (size > MAX_READ_FILE_BYTES) {
293
+ return yield* Effect.fail(
294
+ new StdError.StdError({
295
+ code: "response_too_large",
296
+ message:
297
+ `${input.path} is ${size} bytes, over the ${MAX_READ_FILE_BYTES}-byte read limit; search it with grep or print a line range with bash`,
298
+ path: input.path
299
+ })
300
+ )
301
+ }
302
+ const bytes = yield* fileSystem.readFile(input.path).pipe(Effect.mapError(fileError(input.path)))
303
+ if (bytes.includes(0)) {
304
+ return yield* Effect.fail(
305
+ new StdError.StdError({
306
+ code: "binary_file",
307
+ message: `Cannot read binary file: ${input.path}`,
308
+ path: input.path
309
+ })
310
+ )
311
+ }
312
+ const text = yield* Effect.try({
313
+ try: () => new TextDecoder("utf-8", { fatal: true }).decode(bytes),
314
+ catch: () =>
315
+ new StdError.StdError({
316
+ code: "binary_file",
317
+ message: `File is not valid UTF-8: ${input.path}`,
318
+ path: input.path
319
+ })
320
+ })
321
+ const offset = input.offset ?? 1
322
+ const page = slice(text, { offset, limit: input.limit ?? DEFAULT_READ_LIMIT })
323
+ // An empty file has no lines, and reading one is not an out-of-range read:
324
+ // the caller asked for the first page and there is nothing on it. Only an
325
+ // offset past the first line of a file that has none is out of range.
326
+ if (offset > Math.max(page.totalLines, 1)) {
327
+ return yield* Effect.fail(
328
+ new StdError.StdError({
329
+ code: "offset_out_of_range",
330
+ message: `Line offset ${offset} is outside ${input.path}`,
331
+ path: input.path
332
+ })
333
+ )
334
+ }
335
+ const lines = page.lines.map(clipLine)
336
+ const longLinesTruncated = lines.some((line, index) => line !== page.lines[index])
337
+ const rendered = truncateBytes(lines.join("\n"), MAX_OUTPUT_BYTES, { keep: "head" })
338
+ // A byte budget cuts mid-line. A partial line reads like an anchor and is not
339
+ // one, so the page ends at the last whole line it could afford.
340
+ const whole = rendered.truncated
341
+ ? rendered.text.slice(0, Math.max(0, rendered.text.lastIndexOf("\n")))
342
+ : rendered.text
343
+ // Each clipped line fits the byte budget, so a truncated page retains at least one whole line.
344
+ const shown = rendered.truncated ? whole.split("\n").length : lines.length
345
+ const endLine = page.startLine + shown - 1
346
+ const truncated = longLinesTruncated || rendered.truncated || page.endLine < page.totalLines
347
+ const clipped = longLinesTruncated
348
+ ? ` Lines longer than ${MAX_LINE_CHARS} Unicode scalar values are clipped, so such a line is not an edit anchor.`
349
+ : ""
350
+ yield* FileMutation.recordRead(fileSystem, input.path, bytes)
351
+ return {
352
+ content: whole,
353
+ startLine: page.startLine,
354
+ endLine,
355
+ totalLines: page.totalLines,
356
+ truncated,
357
+ ...(truncated ? { notice: `${notice("lines", shown, page.totalLines)}${clipped}` } : {})
358
+ }
359
+ })
@@ -0,0 +1,166 @@
1
+ /**
2
+ * What can be pointed at a checkpoint, and what cannot.
3
+ *
4
+ * {@link relocate} is the closed answer, and it is the half of the checkpoint
5
+ * feature that tracks the flows rather than git: it knows that `bash` carries
6
+ * its working directory in `cwd` and that `read`, `ls`, `grep` and `glob` carry
7
+ * their subject in `path`, `path`, `root` and `root`. `Checkpoints` changes when
8
+ * git does; this changes when one of those five input shapes does, which is why
9
+ * it is a module of its own. `Relocate.test.ts` decodes every rewritten input
10
+ * with the flow's own `Input` schema, so a renamed field fails there rather than
11
+ * silently relocating nothing.
12
+ *
13
+ * `bash` names *where it runs*, so it is relocated by its `cwd` — into the
14
+ * checkpoint, and into the same subdirectory of it the call asked for, because a
15
+ * check declared in `tests/` that silently ran at the top would come back
16
+ * failing for a reason nobody chose. `read`, `ls`, `grep` and `glob` name *what
17
+ * they touch* relative to the workspace root, so they are relocated by prefixing
18
+ * that root — and only when the path they name stays inside the tree, because an
19
+ * absolute path in these runs is a container path the host cannot rebase and a
20
+ * `..` path is the live tree under another name. Every other flow answers
21
+ * `checkpoint_unsupported` through the harness, including `test`, which already
22
+ * has `against: "base"` for exactly this question and would otherwise have two
23
+ * mechanisms that can disagree.
24
+ *
25
+ * @since 1.0.0
26
+ */
27
+
28
+ import type { Schema } from "effect"
29
+ import type { Materialized } from "./Checkpoints.ts"
30
+ import { withoutTrailingSlash } from "./internal/Paths.ts"
31
+
32
+ /**
33
+ * The flows whose input names where they run or what they read, and the field
34
+ * that says so.
35
+ *
36
+ * A closed table rather than a per-flow hook, because the set is small and the
37
+ * rule for admitting one is exact: the field has to name a location the whole
38
+ * call is relative to. `bash` runs in a directory; the four readers resolve
39
+ * their subject against the workspace root. Everything else — an edit, a patch,
40
+ * a web fetch, a memory write — either names no location or writes, and both
41
+ * are refused above this module.
42
+ *
43
+ * `test` is deliberately absent. It answers this exact question already, with
44
+ * `against: "base"`, and a second mechanism pointed at the same tree is a way
45
+ * for two answers to disagree.
46
+ */
47
+ const located: Readonly<Record<string, { readonly field: string; readonly kind: "cwd" | "path" }>> = {
48
+ bash: { field: "cwd", kind: "cwd" },
49
+ read: { field: "path", kind: "path" },
50
+ ls: { field: "path", kind: "path" },
51
+ grep: { field: "root", kind: "path" },
52
+ glob: { field: "root", kind: "path" }
53
+ }
54
+
55
+ /**
56
+ * Why one input could not be pointed at a checkpoint.
57
+ *
58
+ * @category models
59
+ * @since 1.0.0
60
+ */
61
+ export type Relocation =
62
+ | { readonly _tag: "Relocated"; readonly input: Schema.Json }
63
+ | { readonly _tag: "UnsupportedFlow" }
64
+ | { readonly _tag: "AbsolutePath"; readonly path: string }
65
+ | { readonly _tag: "OutsideTree"; readonly path: string }
66
+
67
+ /**
68
+ * Resolves `.` and `..` inside a relative path, or answers `undefined` when the
69
+ * path climbs out of whatever it would be joined under.
70
+ *
71
+ * This is the whole of the isolation the reader rule can enforce, and it is not
72
+ * optional. Prefixing blindly turns `../../mod.py` into
73
+ * `.flows-checkpoints/cp-1-0/../../mod.py`, which is a path back into the live
74
+ * tree — so the cell would read the work it is trying to take a baseline
75
+ * against, the journal would record that reading under the checkpoint it named,
76
+ * and the call key folds the checkpoint in, so the live reading would replay as
77
+ * a pinned one forever. A proof built on it is a proof of nothing, which is the
78
+ * exact failure this module exists to abolish.
79
+ */
80
+ const contained = (path: string): string | undefined => {
81
+ const parts: Array<string> = []
82
+ for (const segment of path.split("/")) {
83
+ if (segment === "" || segment === ".") continue
84
+ if (segment !== "..") {
85
+ parts.push(segment)
86
+ continue
87
+ }
88
+ if (parts.length === 0) return undefined
89
+ parts.pop()
90
+ }
91
+ return parts.join("/")
92
+ }
93
+
94
+ /**
95
+ * The part of `declared` that names a place inside `root`, or `undefined` when
96
+ * it names somewhere the checkpoint does not hold a copy of.
97
+ *
98
+ * A relative path is already workspace-relative. An absolute one is compared
99
+ * against the root on the side that issued it — a container call names the
100
+ * mount, a host call names this machine — because that is the only prefix the
101
+ * store can strip without guessing.
102
+ */
103
+ const within = (root: string, declared: string): string | undefined => {
104
+ if (!declared.startsWith("/")) return contained(declared)
105
+ if (withoutTrailingSlash(declared) === root) return ""
106
+ return declared.startsWith(`${root}/`) ? contained(declared.slice(root.length + 1)) : undefined
107
+ }
108
+
109
+ /**
110
+ * Rewrites one call's input so the call runs against a materialized checkpoint.
111
+ *
112
+ * Returns the rewritten input, or the reason there is none. A `bash` call runs
113
+ * in the checkpoint's directory — from the *guest* side when it names a
114
+ * container, because that is the path the container will be given — and keeps
115
+ * whatever subdirectory it asked for: a check declared in `tests/` runs in the
116
+ * checkpoint's `tests/`. A working directory the checkpoint holds no copy of,
117
+ * such as somewhere else on the machine, becomes the checkpoint's own top,
118
+ * because a tree is all this can offer and there is no subpath in it to keep.
119
+ *
120
+ * A reader takes the checkpoint's workspace-relative directory as the prefix of
121
+ * what it names, because these flows resolve their subject against the
122
+ * workspace root and the checkpoint is a directory under it.
123
+ *
124
+ * Two paths are refused rather than rewritten, and both for the same reason —
125
+ * the host would otherwise hand back a reading of a tree the cell did not name.
126
+ * An absolute path in these runs is a container path, and the host cannot know
127
+ * which prefix of it names the tree. A relative path that climbs past the
128
+ * checkpoint with `..` names the live tree, exactly the tree the reading was
129
+ * taken to avoid.
130
+ *
131
+ * @category conversions
132
+ * @since 1.0.0
133
+ */
134
+ export const relocate = (
135
+ flow: string,
136
+ input: Schema.Json,
137
+ materialized: Materialized
138
+ ): Relocation => {
139
+ const rule = located[flow]
140
+ if (rule === undefined) return { _tag: "UnsupportedFlow" }
141
+ const record = input !== null && typeof input === "object" && !Array.isArray(input)
142
+ ? input as Record<string, Schema.Json>
143
+ : {}
144
+ const declared = record[rule.field]
145
+ if (rule.kind === "cwd") {
146
+ // A container call is given the path the container will resolve; a host
147
+ // call is given the host's. `bash` chooses which by naming a container, so
148
+ // this reads the same field it does.
149
+ const containerised = typeof record["container"] === "string" && record["container"] !== ""
150
+ const base = containerised ? materialized.guest : materialized.host
151
+ const kept = typeof declared === "string" && declared !== ""
152
+ ? within(containerised ? materialized.guestRoot : materialized.root, declared)
153
+ : ""
154
+ return {
155
+ _tag: "Relocated",
156
+ input: { ...record, cwd: kept === undefined || kept === "" ? base : `${base}/${kept}` }
157
+ }
158
+ }
159
+ const relative = materialized.host.slice(withoutTrailingSlash(materialized.root).length + 1)
160
+ if (declared === undefined) return { _tag: "Relocated", input: { ...record, [rule.field]: relative } }
161
+ if (typeof declared !== "string") return { _tag: "UnsupportedFlow" }
162
+ if (declared.startsWith("/")) return { _tag: "AbsolutePath", path: declared }
163
+ const kept = contained(declared)
164
+ if (kept === undefined) return { _tag: "OutsideTree", path: declared }
165
+ return { _tag: "Relocated", input: { ...record, [rule.field]: kept === "" ? relative : `${relative}/${kept}` } }
166
+ }