@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.
- package/CHANGELOG.md +130 -0
- package/LICENSE +21 -0
- package/README.md +152 -2
- package/dist/cjs/ApplyPatch.d.ts +174 -0
- package/dist/cjs/ApplyPatch.d.ts.map +1 -0
- package/dist/cjs/ApplyPatch.js +309 -0
- package/dist/cjs/ApplyPatch.js.map +7 -0
- package/dist/cjs/Bash.d.ts +380 -0
- package/dist/cjs/Bash.d.ts.map +1 -0
- package/dist/cjs/Bash.js +332 -0
- package/dist/cjs/Bash.js.map +7 -0
- package/dist/cjs/Checkpoints.d.ts +279 -0
- package/dist/cjs/Checkpoints.d.ts.map +1 -0
- package/dist/cjs/Checkpoints.js +145 -0
- package/dist/cjs/Checkpoints.js.map +7 -0
- package/dist/cjs/Container.d.ts +132 -0
- package/dist/cjs/Container.d.ts.map +1 -0
- package/dist/cjs/Container.js +113 -0
- package/dist/cjs/Container.js.map +7 -0
- package/dist/cjs/Edit.d.ts +203 -0
- package/dist/cjs/Edit.d.ts.map +1 -0
- package/dist/cjs/Edit.js +258 -0
- package/dist/cjs/Edit.js.map +7 -0
- package/dist/cjs/ExaWebSearch.d.ts +22 -0
- package/dist/cjs/ExaWebSearch.d.ts.map +1 -0
- package/dist/cjs/ExaWebSearch.js +138 -0
- package/dist/cjs/ExaWebSearch.js.map +7 -0
- package/dist/cjs/Explore.d.ts +328 -0
- package/dist/cjs/Explore.d.ts.map +1 -0
- package/dist/cjs/Explore.js +90 -0
- package/dist/cjs/Explore.js.map +7 -0
- package/dist/cjs/Fetch.d.ts +130 -0
- package/dist/cjs/Fetch.d.ts.map +1 -0
- package/dist/cjs/Fetch.js +64 -0
- package/dist/cjs/Fetch.js.map +7 -0
- package/dist/cjs/Glob.d.ts +204 -0
- package/dist/cjs/Glob.d.ts.map +1 -0
- package/dist/cjs/Glob.js +94 -0
- package/dist/cjs/Glob.js.map +7 -0
- package/dist/cjs/Grep.d.ts +347 -0
- package/dist/cjs/Grep.d.ts.map +1 -0
- package/dist/cjs/Grep.js +181 -0
- package/dist/cjs/Grep.js.map +7 -0
- package/dist/cjs/HttpPost.d.ts +130 -0
- package/dist/cjs/HttpPost.d.ts.map +1 -0
- package/dist/cjs/HttpPost.js +72 -0
- package/dist/cjs/HttpPost.js.map +7 -0
- package/dist/cjs/LanguageServer.d.ts +90 -0
- package/dist/cjs/LanguageServer.d.ts.map +1 -0
- package/dist/cjs/LanguageServer.js +60 -0
- package/dist/cjs/LanguageServer.js.map +7 -0
- package/dist/cjs/Ls.d.ts +164 -0
- package/dist/cjs/Ls.d.ts.map +1 -0
- package/dist/cjs/Ls.js +136 -0
- package/dist/cjs/Ls.js.map +7 -0
- package/dist/cjs/Lsp.d.ts +125 -0
- package/dist/cjs/Lsp.d.ts.map +1 -0
- package/dist/cjs/Lsp.js +137 -0
- package/dist/cjs/Lsp.js.map +7 -0
- package/dist/cjs/Manifest.d.ts +918 -0
- package/dist/cjs/Manifest.d.ts.map +1 -0
- package/dist/cjs/Manifest.js +144 -0
- package/dist/cjs/Manifest.js.map +7 -0
- package/dist/cjs/NativeSearch.d.ts +38 -0
- package/dist/cjs/NativeSearch.d.ts.map +1 -0
- package/dist/cjs/NativeSearch.js +326 -0
- package/dist/cjs/NativeSearch.js.map +7 -0
- package/dist/cjs/NodeLanguageServer.d.ts +128 -0
- package/dist/cjs/NodeLanguageServer.d.ts.map +1 -0
- package/dist/cjs/NodeLanguageServer.js +796 -0
- package/dist/cjs/NodeLanguageServer.js.map +7 -0
- package/dist/cjs/PortableSearch.d.ts +24 -0
- package/dist/cjs/PortableSearch.d.ts.map +1 -0
- package/dist/cjs/PortableSearch.js +233 -0
- package/dist/cjs/PortableSearch.js.map +7 -0
- package/dist/cjs/Probe.d.ts +193 -0
- package/dist/cjs/Probe.d.ts.map +1 -0
- package/dist/cjs/Probe.js +134 -0
- package/dist/cjs/Probe.js.map +7 -0
- package/dist/cjs/Read.d.ts +189 -0
- package/dist/cjs/Read.d.ts.map +1 -0
- package/dist/cjs/Read.js +223 -0
- package/dist/cjs/Read.js.map +7 -0
- package/dist/cjs/Relocate.d.ts +73 -0
- package/dist/cjs/Relocate.d.ts.map +1 -0
- package/dist/cjs/Relocate.js +72 -0
- package/dist/cjs/Relocate.js.map +7 -0
- package/dist/cjs/Search.d.ts +163 -0
- package/dist/cjs/Search.d.ts.map +1 -0
- package/dist/cjs/Search.js +51 -0
- package/dist/cjs/Search.js.map +7 -0
- package/dist/cjs/SearchConformance.d.ts +115 -0
- package/dist/cjs/SearchConformance.d.ts.map +1 -0
- package/dist/cjs/SearchConformance.js +172 -0
- package/dist/cjs/SearchConformance.js.map +7 -0
- package/dist/cjs/SearchContract.d.ts +114 -0
- package/dist/cjs/SearchContract.d.ts.map +1 -0
- package/dist/cjs/SearchContract.js +339 -0
- package/dist/cjs/SearchContract.js.map +7 -0
- package/dist/cjs/ShellCommand.d.ts +164 -0
- package/dist/cjs/ShellCommand.d.ts.map +1 -0
- package/dist/cjs/ShellCommand.js +102 -0
- package/dist/cjs/ShellCommand.js.map +7 -0
- package/dist/cjs/StdError.d.ts +55 -0
- package/dist/cjs/StdError.d.ts.map +1 -0
- package/dist/cjs/StdError.js +74 -0
- package/dist/cjs/StdError.js.map +7 -0
- package/dist/cjs/TestRun.d.ts +311 -0
- package/dist/cjs/TestRun.d.ts.map +1 -0
- package/dist/cjs/TestRun.js +228 -0
- package/dist/cjs/TestRun.js.map +7 -0
- package/dist/cjs/TestRunner.d.ts +102 -0
- package/dist/cjs/TestRunner.d.ts.map +1 -0
- package/dist/cjs/TestRunner.js +54 -0
- package/dist/cjs/TestRunner.js.map +7 -0
- package/dist/cjs/TreeFingerprint.d.ts +140 -0
- package/dist/cjs/TreeFingerprint.d.ts.map +1 -0
- package/dist/cjs/TreeFingerprint.js +87 -0
- package/dist/cjs/TreeFingerprint.js.map +7 -0
- package/dist/cjs/UpdatePlan.d.ts +152 -0
- package/dist/cjs/UpdatePlan.d.ts.map +1 -0
- package/dist/cjs/UpdatePlan.js +87 -0
- package/dist/cjs/UpdatePlan.js.map +7 -0
- package/dist/cjs/WebFetch.d.ts +134 -0
- package/dist/cjs/WebFetch.d.ts.map +1 -0
- package/dist/cjs/WebFetch.js +140 -0
- package/dist/cjs/WebFetch.js.map +7 -0
- package/dist/cjs/WebSearch.d.ts +181 -0
- package/dist/cjs/WebSearch.d.ts.map +1 -0
- package/dist/cjs/WebSearch.js +86 -0
- package/dist/cjs/WebSearch.js.map +7 -0
- package/dist/cjs/Write.d.ts +147 -0
- package/dist/cjs/Write.d.ts.map +1 -0
- package/dist/cjs/Write.js +122 -0
- package/dist/cjs/Write.js.map +7 -0
- package/dist/cjs/index.d.ts +127 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +99 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/ApplyPatch.d.ts +145 -0
- package/dist/cjs/internal/ApplyPatch.d.ts.map +1 -0
- package/dist/cjs/internal/ApplyPatch.js +462 -0
- package/dist/cjs/internal/ApplyPatch.js.map +7 -0
- package/dist/cjs/internal/CodexText.d.ts +73 -0
- package/dist/cjs/internal/CodexText.d.ts.map +1 -0
- package/dist/cjs/internal/CodexText.js +108 -0
- package/dist/cjs/internal/CodexText.js.map +7 -0
- package/dist/cjs/internal/Declaration.d.ts +49 -0
- package/dist/cjs/internal/Declaration.d.ts.map +1 -0
- package/dist/cjs/internal/Declaration.js +46 -0
- package/dist/cjs/internal/Declaration.js.map +7 -0
- package/dist/cjs/internal/Diagnostics.d.ts +77 -0
- package/dist/cjs/internal/Diagnostics.d.ts.map +1 -0
- package/dist/cjs/internal/Diagnostics.js +89 -0
- package/dist/cjs/internal/Diagnostics.js.map +7 -0
- package/dist/cjs/internal/EnvelopePrecheck.d.ts +67 -0
- package/dist/cjs/internal/EnvelopePrecheck.d.ts.map +1 -0
- package/dist/cjs/internal/EnvelopePrecheck.js +124 -0
- package/dist/cjs/internal/EnvelopePrecheck.js.map +7 -0
- package/dist/cjs/internal/Exec.d.ts +139 -0
- package/dist/cjs/internal/Exec.d.ts.map +1 -0
- package/dist/cjs/internal/Exec.js +158 -0
- package/dist/cjs/internal/Exec.js.map +7 -0
- package/dist/cjs/internal/FileMutation.d.ts +109 -0
- package/dist/cjs/internal/FileMutation.d.ts.map +1 -0
- package/dist/cjs/internal/FileMutation.js +116 -0
- package/dist/cjs/internal/FileMutation.js.map +7 -0
- package/dist/cjs/internal/FsFailure.d.ts +38 -0
- package/dist/cjs/internal/FsFailure.d.ts.map +1 -0
- package/dist/cjs/internal/FsFailure.js +40 -0
- package/dist/cjs/internal/FsFailure.js.map +7 -0
- package/dist/cjs/internal/GitWorktree.d.ts +108 -0
- package/dist/cjs/internal/GitWorktree.d.ts.map +1 -0
- package/dist/cjs/internal/GitWorktree.js +276 -0
- package/dist/cjs/internal/GitWorktree.js.map +7 -0
- package/dist/cjs/internal/Grouping.d.ts +51 -0
- package/dist/cjs/internal/Grouping.d.ts.map +1 -0
- package/dist/cjs/internal/Grouping.js +83 -0
- package/dist/cjs/internal/Grouping.js.map +7 -0
- package/dist/cjs/internal/Html.d.ts +20 -0
- package/dist/cjs/internal/Html.d.ts.map +1 -0
- package/dist/cjs/internal/Html.js +81 -0
- package/dist/cjs/internal/Html.js.map +7 -0
- package/dist/cjs/internal/Http.d.ts +95 -0
- package/dist/cjs/internal/Http.d.ts.map +1 -0
- package/dist/cjs/internal/Http.js +153 -0
- package/dist/cjs/internal/Http.js.map +7 -0
- package/dist/cjs/internal/HttpNetwork.d.ts +27 -0
- package/dist/cjs/internal/HttpNetwork.d.ts.map +1 -0
- package/dist/cjs/internal/HttpNetwork.js +146 -0
- package/dist/cjs/internal/HttpNetwork.js.map +7 -0
- package/dist/cjs/internal/Ignore.d.ts +37 -0
- package/dist/cjs/internal/Ignore.d.ts.map +1 -0
- package/dist/cjs/internal/Ignore.js +100 -0
- package/dist/cjs/internal/Ignore.js.map +7 -0
- package/dist/cjs/internal/LinearRegex.d.ts +19 -0
- package/dist/cjs/internal/LinearRegex.d.ts.map +1 -0
- package/dist/cjs/internal/LinearRegex.js +166 -0
- package/dist/cjs/internal/LinearRegex.js.map +7 -0
- package/dist/cjs/internal/Match.d.ts +85 -0
- package/dist/cjs/internal/Match.d.ts.map +1 -0
- package/dist/cjs/internal/Match.js +99 -0
- package/dist/cjs/internal/Match.js.map +7 -0
- package/dist/cjs/internal/Paths.d.ts +23 -0
- package/dist/cjs/internal/Paths.d.ts.map +1 -0
- package/dist/cjs/internal/Paths.js +52 -0
- package/dist/cjs/internal/Paths.js.map +7 -0
- package/dist/cjs/internal/Preserve.d.ts +25 -0
- package/dist/cjs/internal/Preserve.d.ts.map +1 -0
- package/dist/cjs/internal/Preserve.js +88 -0
- package/dist/cjs/internal/Preserve.js.map +7 -0
- package/dist/cjs/internal/Prune.d.ts +35 -0
- package/dist/cjs/internal/Prune.d.ts.map +1 -0
- package/dist/cjs/internal/Prune.js +54 -0
- package/dist/cjs/internal/Prune.js.map +7 -0
- package/dist/cjs/internal/SearchContract.d.ts +63 -0
- package/dist/cjs/internal/SearchContract.d.ts.map +1 -0
- package/dist/cjs/internal/SearchContract.js +46 -0
- package/dist/cjs/internal/SearchContract.js.map +7 -0
- package/dist/cjs/internal/Symbols.d.ts +39 -0
- package/dist/cjs/internal/Symbols.d.ts.map +1 -0
- package/dist/cjs/internal/Symbols.js +59 -0
- package/dist/cjs/internal/Symbols.js.map +7 -0
- package/dist/cjs/internal/TestReport.d.ts +52 -0
- package/dist/cjs/internal/TestReport.d.ts.map +1 -0
- package/dist/cjs/internal/TestReport.js +131 -0
- package/dist/cjs/internal/TestReport.js.map +7 -0
- package/dist/cjs/internal/Text.d.ts +114 -0
- package/dist/cjs/internal/Text.d.ts.map +1 -0
- package/dist/cjs/internal/Text.js +82 -0
- package/dist/cjs/internal/Text.js.map +7 -0
- package/dist/cjs/internal/Url.d.ts +13 -0
- package/dist/cjs/internal/Url.d.ts.map +1 -0
- package/dist/cjs/internal/Url.js +35 -0
- package/dist/cjs/internal/Url.js.map +7 -0
- package/dist/cjs/internal/Walk.d.ts +72 -0
- package/dist/cjs/internal/Walk.d.ts.map +1 -0
- package/dist/cjs/internal/Walk.js +108 -0
- package/dist/cjs/internal/Walk.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/ApplyPatch.d.ts +174 -0
- package/dist/esm/ApplyPatch.d.ts.map +1 -0
- package/dist/esm/ApplyPatch.js +346 -0
- package/dist/esm/ApplyPatch.js.map +1 -0
- package/dist/esm/Bash.d.ts +380 -0
- package/dist/esm/Bash.d.ts.map +1 -0
- package/dist/esm/Bash.js +505 -0
- package/dist/esm/Bash.js.map +1 -0
- package/dist/esm/Checkpoints.d.ts +279 -0
- package/dist/esm/Checkpoints.d.ts.map +1 -0
- package/dist/esm/Checkpoints.js +298 -0
- package/dist/esm/Checkpoints.js.map +1 -0
- package/dist/esm/Container.d.ts +132 -0
- package/dist/esm/Container.d.ts.map +1 -0
- package/dist/esm/Container.js +151 -0
- package/dist/esm/Container.js.map +1 -0
- package/dist/esm/Edit.d.ts +203 -0
- package/dist/esm/Edit.d.ts.map +1 -0
- package/dist/esm/Edit.js +296 -0
- package/dist/esm/Edit.js.map +1 -0
- package/dist/esm/ExaWebSearch.d.ts +22 -0
- package/dist/esm/ExaWebSearch.d.ts.map +1 -0
- package/dist/esm/ExaWebSearch.js +107 -0
- package/dist/esm/ExaWebSearch.js.map +1 -0
- package/dist/esm/Explore.d.ts +328 -0
- package/dist/esm/Explore.d.ts.map +1 -0
- package/dist/esm/Explore.js +106 -0
- package/dist/esm/Explore.js.map +1 -0
- package/dist/esm/Fetch.d.ts +130 -0
- package/dist/esm/Fetch.d.ts.map +1 -0
- package/dist/esm/Fetch.js +91 -0
- package/dist/esm/Fetch.js.map +1 -0
- package/dist/esm/Glob.d.ts +204 -0
- package/dist/esm/Glob.d.ts.map +1 -0
- package/dist/esm/Glob.js +177 -0
- package/dist/esm/Glob.js.map +1 -0
- package/dist/esm/Grep.d.ts +347 -0
- package/dist/esm/Grep.d.ts.map +1 -0
- package/dist/esm/Grep.js +289 -0
- package/dist/esm/Grep.js.map +1 -0
- package/dist/esm/HttpPost.d.ts +130 -0
- package/dist/esm/HttpPost.d.ts.map +1 -0
- package/dist/esm/HttpPost.js +89 -0
- package/dist/esm/HttpPost.js.map +1 -0
- package/dist/esm/LanguageServer.d.ts +90 -0
- package/dist/esm/LanguageServer.d.ts.map +1 -0
- package/dist/esm/LanguageServer.js +57 -0
- package/dist/esm/LanguageServer.js.map +1 -0
- package/dist/esm/Ls.d.ts +164 -0
- package/dist/esm/Ls.d.ts.map +1 -0
- package/dist/esm/Ls.js +178 -0
- package/dist/esm/Ls.js.map +1 -0
- package/dist/esm/Lsp.d.ts +125 -0
- package/dist/esm/Lsp.d.ts.map +1 -0
- package/dist/esm/Lsp.js +165 -0
- package/dist/esm/Lsp.js.map +1 -0
- package/dist/esm/Manifest.d.ts +918 -0
- package/dist/esm/Manifest.d.ts.map +1 -0
- package/dist/esm/Manifest.js +153 -0
- package/dist/esm/Manifest.js.map +1 -0
- package/dist/esm/NativeSearch.d.ts +38 -0
- package/dist/esm/NativeSearch.d.ts.map +1 -0
- package/dist/esm/NativeSearch.js +378 -0
- package/dist/esm/NativeSearch.js.map +1 -0
- package/dist/esm/NodeLanguageServer.d.ts +128 -0
- package/dist/esm/NodeLanguageServer.d.ts.map +1 -0
- package/dist/esm/NodeLanguageServer.js +843 -0
- package/dist/esm/NodeLanguageServer.js.map +1 -0
- package/dist/esm/PortableSearch.d.ts +24 -0
- package/dist/esm/PortableSearch.d.ts.map +1 -0
- package/dist/esm/PortableSearch.js +240 -0
- package/dist/esm/PortableSearch.js.map +1 -0
- package/dist/esm/Probe.d.ts +193 -0
- package/dist/esm/Probe.d.ts.map +1 -0
- package/dist/esm/Probe.js +225 -0
- package/dist/esm/Probe.js.map +1 -0
- package/dist/esm/Read.d.ts +189 -0
- package/dist/esm/Read.d.ts.map +1 -0
- package/dist/esm/Read.js +300 -0
- package/dist/esm/Read.js.map +1 -0
- package/dist/esm/Relocate.d.ts +73 -0
- package/dist/esm/Relocate.d.ts.map +1 -0
- package/dist/esm/Relocate.js +153 -0
- package/dist/esm/Relocate.js.map +1 -0
- package/dist/esm/Search.d.ts +163 -0
- package/dist/esm/Search.d.ts.map +1 -0
- package/dist/esm/Search.js +47 -0
- package/dist/esm/Search.js.map +1 -0
- package/dist/esm/SearchConformance.d.ts +115 -0
- package/dist/esm/SearchConformance.d.ts.map +1 -0
- package/dist/esm/SearchConformance.js +193 -0
- package/dist/esm/SearchConformance.js.map +1 -0
- package/dist/esm/SearchContract.d.ts +114 -0
- package/dist/esm/SearchContract.d.ts.map +1 -0
- package/dist/esm/SearchContract.js +461 -0
- package/dist/esm/SearchContract.js.map +1 -0
- package/dist/esm/ShellCommand.d.ts +164 -0
- package/dist/esm/ShellCommand.d.ts.map +1 -0
- package/dist/esm/ShellCommand.js +159 -0
- package/dist/esm/ShellCommand.js.map +1 -0
- package/dist/esm/StdError.d.ts +55 -0
- package/dist/esm/StdError.d.ts.map +1 -0
- package/dist/esm/StdError.js +71 -0
- package/dist/esm/StdError.js.map +1 -0
- package/dist/esm/TestRun.d.ts +311 -0
- package/dist/esm/TestRun.d.ts.map +1 -0
- package/dist/esm/TestRun.js +316 -0
- package/dist/esm/TestRun.js.map +1 -0
- package/dist/esm/TestRunner.d.ts +102 -0
- package/dist/esm/TestRunner.d.ts.map +1 -0
- package/dist/esm/TestRunner.js +68 -0
- package/dist/esm/TestRunner.js.map +1 -0
- package/dist/esm/TreeFingerprint.d.ts +140 -0
- package/dist/esm/TreeFingerprint.d.ts.map +1 -0
- package/dist/esm/TreeFingerprint.js +170 -0
- package/dist/esm/TreeFingerprint.js.map +1 -0
- package/dist/esm/UpdatePlan.d.ts +152 -0
- package/dist/esm/UpdatePlan.d.ts.map +1 -0
- package/dist/esm/UpdatePlan.js +129 -0
- package/dist/esm/UpdatePlan.js.map +1 -0
- package/dist/esm/WebFetch.d.ts +134 -0
- package/dist/esm/WebFetch.d.ts.map +1 -0
- package/dist/esm/WebFetch.js +151 -0
- package/dist/esm/WebFetch.js.map +1 -0
- package/dist/esm/WebSearch.d.ts +181 -0
- package/dist/esm/WebSearch.d.ts.map +1 -0
- package/dist/esm/WebSearch.js +134 -0
- package/dist/esm/WebSearch.js.map +1 -0
- package/dist/esm/Write.d.ts +147 -0
- package/dist/esm/Write.d.ts.map +1 -0
- package/dist/esm/Write.js +144 -0
- package/dist/esm/Write.js.map +1 -0
- package/dist/esm/index.d.ts +127 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +127 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/ApplyPatch.d.ts +145 -0
- package/dist/esm/internal/ApplyPatch.d.ts.map +1 -0
- package/dist/esm/internal/ApplyPatch.js +489 -0
- package/dist/esm/internal/ApplyPatch.js.map +1 -0
- package/dist/esm/internal/CodexText.d.ts +73 -0
- package/dist/esm/internal/CodexText.d.ts.map +1 -0
- package/dist/esm/internal/CodexText.js +156 -0
- package/dist/esm/internal/CodexText.js.map +1 -0
- package/dist/esm/internal/Declaration.d.ts +49 -0
- package/dist/esm/internal/Declaration.d.ts.map +1 -0
- package/dist/esm/internal/Declaration.js +42 -0
- package/dist/esm/internal/Declaration.js.map +1 -0
- package/dist/esm/internal/Diagnostics.d.ts +77 -0
- package/dist/esm/internal/Diagnostics.d.ts.map +1 -0
- package/dist/esm/internal/Diagnostics.js +99 -0
- package/dist/esm/internal/Diagnostics.js.map +1 -0
- package/dist/esm/internal/EnvelopePrecheck.d.ts +67 -0
- package/dist/esm/internal/EnvelopePrecheck.d.ts.map +1 -0
- package/dist/esm/internal/EnvelopePrecheck.js +167 -0
- package/dist/esm/internal/EnvelopePrecheck.js.map +1 -0
- package/dist/esm/internal/Exec.d.ts +139 -0
- package/dist/esm/internal/Exec.d.ts.map +1 -0
- package/dist/esm/internal/Exec.js +193 -0
- package/dist/esm/internal/Exec.js.map +1 -0
- package/dist/esm/internal/FileMutation.d.ts +109 -0
- package/dist/esm/internal/FileMutation.d.ts.map +1 -0
- package/dist/esm/internal/FileMutation.js +123 -0
- package/dist/esm/internal/FileMutation.js.map +1 -0
- package/dist/esm/internal/FsFailure.d.ts +38 -0
- package/dist/esm/internal/FsFailure.d.ts.map +1 -0
- package/dist/esm/internal/FsFailure.js +39 -0
- package/dist/esm/internal/FsFailure.js.map +1 -0
- package/dist/esm/internal/GitWorktree.d.ts +108 -0
- package/dist/esm/internal/GitWorktree.d.ts.map +1 -0
- package/dist/esm/internal/GitWorktree.js +352 -0
- package/dist/esm/internal/GitWorktree.js.map +1 -0
- package/dist/esm/internal/Grouping.d.ts +51 -0
- package/dist/esm/internal/Grouping.d.ts.map +1 -0
- package/dist/esm/internal/Grouping.js +99 -0
- package/dist/esm/internal/Grouping.js.map +1 -0
- package/dist/esm/internal/Html.d.ts +20 -0
- package/dist/esm/internal/Html.d.ts.map +1 -0
- package/dist/esm/internal/Html.js +70 -0
- package/dist/esm/internal/Html.js.map +1 -0
- package/dist/esm/internal/Http.d.ts +95 -0
- package/dist/esm/internal/Http.d.ts.map +1 -0
- package/dist/esm/internal/Http.js +154 -0
- package/dist/esm/internal/Http.js.map +1 -0
- package/dist/esm/internal/HttpNetwork.d.ts +27 -0
- package/dist/esm/internal/HttpNetwork.d.ts.map +1 -0
- package/dist/esm/internal/HttpNetwork.js +114 -0
- package/dist/esm/internal/HttpNetwork.js.map +1 -0
- package/dist/esm/internal/Ignore.d.ts +37 -0
- package/dist/esm/internal/Ignore.d.ts.map +1 -0
- package/dist/esm/internal/Ignore.js +128 -0
- package/dist/esm/internal/Ignore.js.map +1 -0
- package/dist/esm/internal/LinearRegex.d.ts +19 -0
- package/dist/esm/internal/LinearRegex.d.ts.map +1 -0
- package/dist/esm/internal/LinearRegex.js +176 -0
- package/dist/esm/internal/LinearRegex.js.map +1 -0
- package/dist/esm/internal/Match.d.ts +85 -0
- package/dist/esm/internal/Match.d.ts.map +1 -0
- package/dist/esm/internal/Match.js +142 -0
- package/dist/esm/internal/Match.js.map +1 -0
- package/dist/esm/internal/Paths.d.ts +23 -0
- package/dist/esm/internal/Paths.d.ts.map +1 -0
- package/dist/esm/internal/Paths.js +40 -0
- package/dist/esm/internal/Paths.js.map +1 -0
- package/dist/esm/internal/Preserve.d.ts +25 -0
- package/dist/esm/internal/Preserve.d.ts.map +1 -0
- package/dist/esm/internal/Preserve.js +70 -0
- package/dist/esm/internal/Preserve.js.map +1 -0
- package/dist/esm/internal/Prune.d.ts +35 -0
- package/dist/esm/internal/Prune.d.ts.map +1 -0
- package/dist/esm/internal/Prune.js +60 -0
- package/dist/esm/internal/Prune.js.map +1 -0
- package/dist/esm/internal/SearchContract.d.ts +63 -0
- package/dist/esm/internal/SearchContract.d.ts.map +1 -0
- package/dist/esm/internal/SearchContract.js +66 -0
- package/dist/esm/internal/SearchContract.js.map +1 -0
- package/dist/esm/internal/Symbols.d.ts +39 -0
- package/dist/esm/internal/Symbols.d.ts.map +1 -0
- package/dist/esm/internal/Symbols.js +79 -0
- package/dist/esm/internal/Symbols.js.map +1 -0
- package/dist/esm/internal/TestReport.d.ts +52 -0
- package/dist/esm/internal/TestReport.d.ts.map +1 -0
- package/dist/esm/internal/TestReport.js +172 -0
- package/dist/esm/internal/TestReport.js.map +1 -0
- package/dist/esm/internal/Text.d.ts +114 -0
- package/dist/esm/internal/Text.d.ts.map +1 -0
- package/dist/esm/internal/Text.js +130 -0
- package/dist/esm/internal/Text.js.map +1 -0
- package/dist/esm/internal/Url.d.ts +13 -0
- package/dist/esm/internal/Url.d.ts.map +1 -0
- package/dist/esm/internal/Url.js +27 -0
- package/dist/esm/internal/Url.js.map +1 -0
- package/dist/esm/internal/Walk.d.ts +72 -0
- package/dist/esm/internal/Walk.d.ts.map +1 -0
- package/dist/esm/internal/Walk.js +126 -0
- package/dist/esm/internal/Walk.js.map +1 -0
- package/docs/README.md +117 -0
- package/docs/api.md +472 -0
- package/docs/concepts/effects-and-capabilities.md +136 -0
- package/docs/concepts/flows-and-handlers.md +115 -0
- package/docs/concepts/limits-and-disclosure.md +102 -0
- package/docs/concepts/search-contract.md +182 -0
- package/docs/guides/bind-the-standard-flows.md +114 -0
- package/docs/guides/implement-a-search-peer.md +133 -0
- package/docs/guides/pin-a-checkpoint.md +141 -0
- package/docs/guides/query-a-language-server.md +257 -0
- package/docs/guides/reach-the-network.md +141 -0
- package/docs/guides/read-and-edit-a-file.md +240 -0
- package/docs/guides/run-a-shell-command.md +215 -0
- package/docs/guides/run-the-test-suite.md +154 -0
- package/docs/guides/search-a-workspace.md +148 -0
- package/docs/installation.md +111 -0
- package/docs/quickstart.md +125 -0
- package/docs/reference/flows.md +556 -0
- package/docs/troubleshooting.md +322 -0
- package/package.json +439 -3
- package/src/ApplyPatch.ts +458 -0
- package/src/Bash.ts +607 -0
- package/src/Checkpoints.ts +422 -0
- package/src/Container.ts +212 -0
- package/src/Edit.ts +366 -0
- package/src/ExaWebSearch.ts +145 -0
- package/src/Explore.ts +139 -0
- package/src/Fetch.ts +117 -0
- package/src/Glob.ts +200 -0
- package/src/Grep.ts +320 -0
- package/src/HttpPost.ts +120 -0
- package/src/LanguageServer.ts +110 -0
- package/src/Ls.ts +228 -0
- package/src/Lsp.ts +184 -0
- package/src/Manifest.ts +162 -0
- package/src/NativeSearch.ts +457 -0
- package/src/NodeLanguageServer.ts +1148 -0
- package/src/PortableSearch.ts +264 -0
- package/src/Probe.ts +284 -0
- package/src/Read.ts +359 -0
- package/src/Relocate.ts +166 -0
- package/src/Search.ts +185 -0
- package/src/SearchConformance.ts +288 -0
- package/src/SearchContract.ts +489 -0
- package/src/ShellCommand.ts +201 -0
- package/src/StdError.ts +80 -0
- package/src/TestRun.ts +401 -0
- package/src/TestRunner.ts +119 -0
- package/src/TreeFingerprint.ts +200 -0
- package/src/UpdatePlan.ts +171 -0
- package/src/WebFetch.ts +194 -0
- package/src/WebSearch.ts +165 -0
- package/src/Write.ts +195 -0
- package/src/index.ts +154 -0
- package/src/internal/ApplyPatch.ts +601 -0
- package/src/internal/CodexText.ts +182 -0
- package/src/internal/Declaration.ts +60 -0
- package/src/internal/Diagnostics.ts +134 -0
- package/src/internal/EnvelopePrecheck.ts +233 -0
- package/src/internal/Exec.ts +314 -0
- package/src/internal/FileMutation.ts +231 -0
- package/src/internal/FsFailure.ts +51 -0
- package/src/internal/GitWorktree.ts +491 -0
- package/src/internal/Grouping.ts +106 -0
- package/src/internal/Html.ts +87 -0
- package/src/internal/Http.ts +209 -0
- package/src/internal/HttpNetwork.ts +153 -0
- package/src/internal/Ignore.ts +135 -0
- package/src/internal/LinearRegex.ts +173 -0
- package/src/internal/Match.ts +172 -0
- package/src/internal/Paths.ts +42 -0
- package/src/internal/Preserve.ts +108 -0
- package/src/internal/Prune.ts +62 -0
- package/src/internal/SearchContract.ts +77 -0
- package/src/internal/Symbols.ts +88 -0
- package/src/internal/TestReport.ts +194 -0
- package/src/internal/Text.ts +170 -0
- package/src/internal/Url.ts +23 -0
- package/src/internal/Walk.ts +176 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Read and edit a file"
|
|
3
|
+
description: "Page a file with read, anchor an edit by exact text or by an earlier hit's line range, and read what a miss reports back so the next attempt lands."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 2
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Four flows cover a file: `read`, `write`, `edit`, and `apply_patch`. This guide
|
|
9
|
+
is about the loop that matters, which is reading a region and then changing it
|
|
10
|
+
without losing the anchor in between.
|
|
11
|
+
|
|
12
|
+
## Read a page
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import * as Read from "@smthrs/std/Read"
|
|
16
|
+
|
|
17
|
+
const page = Read.run({ path: "/workspace/src/widen.ts", offset: 40, limit: 20 })
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`offset` and `limit` are 1-based lines. With neither, you get the first 2,000
|
|
21
|
+
lines. The result is:
|
|
22
|
+
|
|
23
|
+
| Field | Meaning |
|
|
24
|
+
| ---------------------- | ------------------------------------------------------- |
|
|
25
|
+
| `content` | Raw page text, byte for byte as the file holds it. |
|
|
26
|
+
| `startLine`, `endLine` | The 1-based range this page covers. |
|
|
27
|
+
| `totalLines` | The file's line count. |
|
|
28
|
+
| `truncated` | Whether anything was cut. |
|
|
29
|
+
| `notice` | What was shown out of what there was, when `truncated`. |
|
|
30
|
+
|
|
31
|
+
`content` carries no line-number gutter. That is deliberate: an anchor copied
|
|
32
|
+
out of a numbered read carries the numbers with it, so every `edit` built from
|
|
33
|
+
one misses. Line numbers are facts about the page, so they are page fields.
|
|
34
|
+
|
|
35
|
+
Source lines split on `\n`. A trailing `\r` is part of the line, including in
|
|
36
|
+
CRLF files. Pages omit the final `\n` and retain every `\r`. For example,
|
|
37
|
+
`"one\r\ntwo\r\n"` reads as `"one\r\ntwo\r"`. Copy that text unchanged into
|
|
38
|
+
`oldString` or `expect`. Replacement text is also literal: retain the `\r`
|
|
39
|
+
bytes in `newString` to keep CRLF endings, including the last line of a range.
|
|
40
|
+
A line-range edit leaves the final `\n` outside the replaced span.
|
|
41
|
+
|
|
42
|
+
A page cut by the byte budget ends on a whole line rather than handing back a
|
|
43
|
+
fragment that looks like an anchor and is not one. A line longer than 2,000
|
|
44
|
+
characters is clipped, and the notice says so by name, because a clipped line
|
|
45
|
+
cannot be an anchor either.
|
|
46
|
+
|
|
47
|
+
Reading an empty file returns an empty page with `startLine: 1`, `endLine: 0`,
|
|
48
|
+
and `totalLines: 0`. Only an `offset` past the end is
|
|
49
|
+
`offset_out_of_range`. A directory is `is_directory`; a file holding a NUL byte
|
|
50
|
+
or invalid UTF-8 is `binary_file`.
|
|
51
|
+
|
|
52
|
+
## Edit by exact text
|
|
53
|
+
|
|
54
|
+
The first anchor form is the file's own bytes:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import * as Edit from "@smthrs/std/Edit"
|
|
58
|
+
|
|
59
|
+
const applied = Edit.run({
|
|
60
|
+
path: "/workspace/src/widen.ts",
|
|
61
|
+
oldString: " return value * 2",
|
|
62
|
+
newString: " return value * 3"
|
|
63
|
+
})
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The match is byte exact. There is no fuzzy fallback, because a match that is not
|
|
67
|
+
your bytes is an edit nobody inspected.
|
|
68
|
+
|
|
69
|
+
`oldString` must occur exactly once. When it occurs more than once, the call
|
|
70
|
+
fails with `invalid_input` naming every line the anchor sits on, so you can widen
|
|
71
|
+
it without re-reading the file. Pass `replaceAll: true` to change all of them on
|
|
72
|
+
purpose.
|
|
73
|
+
|
|
74
|
+
When it occurs nowhere, the call fails with `no_match`, and the message carries
|
|
75
|
+
the file's **actual** bytes at the nearest region, with that region's line range:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
oldString does not occur in /workspace/src/widen.ts. Lines 1-3 actually hold this, raw:
|
|
79
|
+
export function widen(value: number): number {
|
|
80
|
+
return value * 2
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
Copy the lines you meant from that text, or anchor by startLine/endLine instead.
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
When not even one line of the anchor occurs in the file, the message says that
|
|
87
|
+
instead: the file is the wrong one, or the region is not what you remember.
|
|
88
|
+
|
|
89
|
+
That is the point of the failure: re-anchor from reality inside the same frame,
|
|
90
|
+
rather than re-reading, re-guessing, and missing again.
|
|
91
|
+
|
|
92
|
+
## Edit by line range
|
|
93
|
+
|
|
94
|
+
The second anchor form reuses a hit you already have from `read` or `grep`,
|
|
95
|
+
instead of retyping the text:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
const applied = Edit.run({
|
|
99
|
+
path: "/workspace/src/widen.ts",
|
|
100
|
+
startLine: 2,
|
|
101
|
+
endLine: 2,
|
|
102
|
+
expect: " return value * 2",
|
|
103
|
+
newString: " return value * 3"
|
|
104
|
+
})
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`startLine` and `endLine` are both required and inclusive. `expect` is optional
|
|
108
|
+
and turns the retyped copy into a checked assertion rather than a search key: if
|
|
109
|
+
those lines hold anything else, the call fails with `no_match` and prints what
|
|
110
|
+
they actually hold, which is what a file that moved under your line numbers looks
|
|
111
|
+
like.
|
|
112
|
+
|
|
113
|
+
The two forms do not mix. Each of these is `invalid_input`:
|
|
114
|
+
|
|
115
|
+
- `oldString` together with `startLine` or `endLine`.
|
|
116
|
+
- Neither `oldString` nor a line range. Use `write` to create a file.
|
|
117
|
+
- An empty `oldString`.
|
|
118
|
+
- `expect` together with `oldString`.
|
|
119
|
+
- `replaceAll` together with a line range.
|
|
120
|
+
- `endLine` before `startLine`.
|
|
121
|
+
|
|
122
|
+
A range past the end of the file is `offset_out_of_range`.
|
|
123
|
+
|
|
124
|
+
## Read the hunk back
|
|
125
|
+
|
|
126
|
+
Every successful edit returns the region it wrote, raw, with two lines of
|
|
127
|
+
context on each side:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
// applied.startLine, applied.endLine: the range of the returned hunk
|
|
131
|
+
// applied.replacements: how many occurrences changed
|
|
132
|
+
// applied.hunk: the edited region as it now stands
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
A mis-indented edit costs one glance at `hunk` instead of an investigation.
|
|
136
|
+
|
|
137
|
+
## Concurrent changes
|
|
138
|
+
|
|
139
|
+
On ordinary filesystem hosts, `edit`, `write`, and `apply_patch` hold exclusive sibling directory locks from
|
|
140
|
+
before reading until their mutation finishes. Existing symlink aliases share
|
|
141
|
+
the resolved file's lock. Case and Unicode normalization variants conservatively
|
|
142
|
+
share a lock, even on a case-sensitive filesystem. Separate hosts and processes using these handlers
|
|
143
|
+
coordinate through the same filesystem; it must implement exclusive directory
|
|
144
|
+
creation. A competing call fails with `no_match` and names the busy file before
|
|
145
|
+
changing it. Re-read and retry after the other writer finishes. Anchors and
|
|
146
|
+
line-range `expect` are checked again on every retry.
|
|
147
|
+
|
|
148
|
+
A patch locks all source and destination paths before reading update contents.
|
|
149
|
+
It may create destination parent directories first. Failure to acquire any lock
|
|
150
|
+
releases the locks already acquired without applying file changes. Locks also
|
|
151
|
+
release on ordinary failure and Effect interruption. Process death leaves a
|
|
152
|
+
`.smithers-*.lock` directory and subsequent calls refuse to write. Stop all
|
|
153
|
+
writers for that file, inspect its contents, and remove only the lock named in
|
|
154
|
+
the refusal before retrying. Locks are never reclaimed by age.
|
|
155
|
+
|
|
156
|
+
These locks coordinate standard handlers sharing a filesystem, including patch
|
|
157
|
+
adds, deletes, and moves. Shell commands, editors, and other programs that do
|
|
158
|
+
not use this protocol are outside that guarantee. Whole-file `write` and patch
|
|
159
|
+
add operations intentionally replace contents; use an anchored edit when a
|
|
160
|
+
previously read version must still match.
|
|
161
|
+
|
|
162
|
+
On versioned hosts, the existing `Read.Preconditions` policy must provide
|
|
163
|
+
`prepare(paths, session)`. It captures immutable read bases for that invocation
|
|
164
|
+
and returns `read(path)` and `commit(changes)` operations. `read` must return
|
|
165
|
+
bytes matching the captured base, or refuse; edits compute only from those bytes. Each handler submits one complete
|
|
166
|
+
batch of writes and removals; a move includes both its destination write and
|
|
167
|
+
source removal. The provider must compare every captured base before applying
|
|
168
|
+
any mutation: a stale preflight leaves the whole batch unchanged. The production
|
|
169
|
+
coding provider follows ADR 0004 protocol 7: an application failure may retain a
|
|
170
|
+
durable prefix and requires fresh reads of every affected path. The host does
|
|
171
|
+
not issue compensating writes. Only a complete validated settlement advances
|
|
172
|
+
the ledger. Missing or malformed receipts and transport failures revoke read
|
|
173
|
+
authority even when the old bytes remain. Tool-internal reads never refresh the
|
|
174
|
+
model's read base.
|
|
175
|
+
|
|
176
|
+
A host semaphore keeps preparation and diagnostics ordered. It does not exclude
|
|
177
|
+
outside writers; that is the provider's responsibility. Versioned handlers create
|
|
178
|
+
no parent or lock directories before commit and never fall back to ordinary
|
|
179
|
+
filesystem writes. Missing providers fail with `provider_unavailable`. Diagnostics
|
|
180
|
+
are updated only after the complete batch succeeds. The production coding host
|
|
181
|
+
currently refuses mutations until its guest provider qualifies.
|
|
182
|
+
|
|
183
|
+
## Write a whole file
|
|
184
|
+
|
|
185
|
+
`write` replaces a file, creating parent directories:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
import * as Write from "@smthrs/std/Write"
|
|
189
|
+
|
|
190
|
+
const written = Write.run({ path: "/workspace/notes.md", content: "# Notes\n" })
|
|
191
|
+
// written.bytesWritten, written.created
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
It preserves the file's mode, and it refuses to write over a directory with
|
|
195
|
+
`command_failed`. Prefer `edit` for a targeted change: a whole-file write of a
|
|
196
|
+
file you only partly know is how an unrelated region disappears.
|
|
197
|
+
|
|
198
|
+
On ordinary filesystem hosts, `write`, `edit`, and `apply_patch` updates stage replacement bytes in a unique
|
|
199
|
+
sibling file, preserve existing permission bits and ownership, then rename it
|
|
200
|
+
over the destination. A failure before rename leaves the original bytes intact.
|
|
201
|
+
Existing symlinks continue to target the same file. Hard links to the old inode
|
|
202
|
+
keep its old contents. The host must support exclusive creation and atomic
|
|
203
|
+
rename; unsupported operations fail without falling back to truncation.
|
|
204
|
+
|
|
205
|
+
Temporary files are removed on failure and Effect interruption. Process death
|
|
206
|
+
can leave an unused temporary file. This is per-file atomicity, not a transaction
|
|
207
|
+
across a whole patch or a promise of persistence after power loss. No `fsync` is
|
|
208
|
+
performed. Timestamps and extended metadata such as ACLs are not copied.
|
|
209
|
+
|
|
210
|
+
## Apply a patch instead
|
|
211
|
+
|
|
212
|
+
`apply_patch` accepts Codex's V4A patch text as one string, so a model trained on
|
|
213
|
+
that tool can use the shape it knows:
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
import * as ApplyPatch from "@smthrs/std/ApplyPatch"
|
|
217
|
+
|
|
218
|
+
const result = ApplyPatch.run({
|
|
219
|
+
input: [
|
|
220
|
+
"*** Begin Patch",
|
|
221
|
+
"*** Update File: src/widen.ts",
|
|
222
|
+
"@@",
|
|
223
|
+
"- return value * 2",
|
|
224
|
+
"+ return value * 3",
|
|
225
|
+
"*** End Patch"
|
|
226
|
+
].join("\n")
|
|
227
|
+
})
|
|
228
|
+
// result.added, result.modified, result.deleted, result.output
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
One rule to know: a patch naming the same file in two sections is refused whole
|
|
232
|
+
rather than applied by halves. Every update hunk is derived from the file as it
|
|
233
|
+
is on disk, so the second section would start from an original the first has
|
|
234
|
+
already replaced. A file needing several changes carries several `@@` chunks
|
|
235
|
+
inside one section.
|
|
236
|
+
|
|
237
|
+
Because a patch names its files inside its own text, `apply_patch` cannot narrow
|
|
238
|
+
its effect envelope for one call, and declares the workspace-wide worst case.
|
|
239
|
+
`edit` narrows to the one path it was given, so prefer `edit` where a scheduler
|
|
240
|
+
is running calls concurrently.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Run a shell command"
|
|
3
|
+
description: "Send a command line or a script that needs no quoting, route it into a container, declare a hermetic envelope, and read the exit code, the bounded output, and the invalid-probe flag."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 4
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
`bash` runs one command. It takes two shapes, and the difference is where the
|
|
9
|
+
payload is parsed.
|
|
10
|
+
|
|
11
|
+
## A command line
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import * as Bash from "@smthrs/std/Bash"
|
|
15
|
+
|
|
16
|
+
const result = Bash.run({
|
|
17
|
+
mode: "unhermetic",
|
|
18
|
+
command: "pnpm vitest run src/widen.test.ts",
|
|
19
|
+
cwd: "/workspace",
|
|
20
|
+
timeoutMs: 120_000
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The line goes to the platform shell exactly as written, and it carries its own
|
|
25
|
+
arguments.
|
|
26
|
+
|
|
27
|
+
## A script, delivered as data
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
const result = Bash.run({
|
|
31
|
+
mode: "unhermetic",
|
|
32
|
+
interpreter: "python3",
|
|
33
|
+
script: "import sys\nprint(sys.argv[1:])\n",
|
|
34
|
+
args: ["alpha", "beta"],
|
|
35
|
+
cwd: "/workspace"
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`script` is program text delivered to the interpreter on standard input. Nothing
|
|
40
|
+
quotes it, escapes it, or terminates it with a heredoc marker, so the class of
|
|
41
|
+
failure that eats a quote out of
|
|
42
|
+
`docker exec c bash -lc '...python - <<EOF...'` cannot happen. `args` reach the
|
|
43
|
+
script as arguments rather than as interpolated text.
|
|
44
|
+
|
|
45
|
+
`interpreter` defaults to `bash`. `bash`, `zsh`, `sh`, and `dash` are told to
|
|
46
|
+
read the program with `-s`; `python` and `python3` with `-`; `node`, `ruby`,
|
|
47
|
+
`perl`, and anything else are given no file, which is how they read a program
|
|
48
|
+
from standard input.
|
|
49
|
+
|
|
50
|
+
Six input combinations are refused with `invalid_input`, each naming the fix:
|
|
51
|
+
`command` with `script`, neither of the two, `script` with `stdin`, `command`
|
|
52
|
+
with `args`, `command` with `interpreter`, and a hermetic containerised call.
|
|
53
|
+
|
|
54
|
+
## Declare the environment
|
|
55
|
+
|
|
56
|
+
Host commands inherit a bootstrap allowlist, not the whole Smithers process
|
|
57
|
+
environment: `PATH`, `HOME`, `USER`, `LANG`, every `LC_*` locale variable,
|
|
58
|
+
`TERM`, `TMPDIR`, and `SHELL`. Add a variable to `env` when the command needs
|
|
59
|
+
it. Caller-declared names are applied last, including credential-shaped names,
|
|
60
|
+
so declaring one is an explicit decision to make its value readable by the
|
|
61
|
+
command. Undeclared provider keys and tokens are withheld.
|
|
62
|
+
|
|
63
|
+
Containerised commands receive the `env` entries through the container
|
|
64
|
+
transport; their remaining environment belongs to the container image. The
|
|
65
|
+
Docker and Podman transport supplies each value to the host child as
|
|
66
|
+
`SMITHERS_CONTAINER_ENV_KEY`, passes `-e SMITHERS_CONTAINER_ENV_KEY`, and renames
|
|
67
|
+
it to `KEY` inside the container with `sh -c`, so the container needs `sh`. A
|
|
68
|
+
requested `PATH` or `LD_PRELOAD` therefore never configures the host `docker`
|
|
69
|
+
process. An `env` name that is not a POSIX shell name is `invalid_input`. Timeout errors show the logical command without
|
|
70
|
+
container transport arguments.
|
|
71
|
+
|
|
72
|
+
## Route it into a container
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
const result = Bash.run({
|
|
76
|
+
mode: "unhermetic",
|
|
77
|
+
container: "testbed",
|
|
78
|
+
command: "python -m pytest tests/test_admin.py",
|
|
79
|
+
cwd: "/testbed"
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`container` names a container the host knows how to reach, and the `Container`
|
|
84
|
+
service turns the request into the argv the host spawns. `Container.layerCommand`
|
|
85
|
+
builds the `docker exec` form, which `podman` shares.
|
|
86
|
+
|
|
87
|
+
The native CLI refuses named-container execution with `provider_unavailable`.
|
|
88
|
+
An existing Docker daemon is outside its OS sandbox. Isolated providers are
|
|
89
|
+
tracked in [#1790](https://github.com/smithersai/smithers/issues/1790).
|
|
90
|
+
|
|
91
|
+
The transport always goes through a login shell, because the images an agent
|
|
92
|
+
meets activate the project's interpreter from `/etc/profile.d`. A program
|
|
93
|
+
spawned directly by `docker exec` gets a different Python from the one that owns
|
|
94
|
+
the repository's dependencies.
|
|
95
|
+
|
|
96
|
+
A host that binds no transport refuses the call with `provider_unavailable` and
|
|
97
|
+
a message telling the caller to drop the `container` field. That is the honest
|
|
98
|
+
answer: this host has no container route.
|
|
99
|
+
|
|
100
|
+
## Declare a hermetic envelope
|
|
101
|
+
|
|
102
|
+
`mode: "hermetic"` requires explicit `reads` and `writes`, and the handler
|
|
103
|
+
checks the command's explicit path tokens against them before spawning:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
const result = Bash.run({
|
|
107
|
+
mode: "hermetic",
|
|
108
|
+
command: "cp /workspace/src/a.ts /workspace/build/a.ts",
|
|
109
|
+
reads: ["/workspace/src/**"],
|
|
110
|
+
writes: ["/workspace/build/**"]
|
|
111
|
+
})
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
A token outside the declaration fails with `outside_declared_reads` or
|
|
115
|
+
`outside_declared_writes` before anything runs, and the narrowed envelope makes
|
|
116
|
+
the call `compensable` instead of `irreversible`, so a scheduler can run it
|
|
117
|
+
beside work that touches other paths.
|
|
118
|
+
|
|
119
|
+
Read [Hermetic mode is a pre-check, not a sandbox](../concepts/effects-and-capabilities.md#hermetic-mode-is-a-pre-check-not-a-sandbox)
|
|
120
|
+
before you rely on this. The check is lexical: it bounds what the caller
|
|
121
|
+
declared it would do, not what the process can do.
|
|
122
|
+
|
|
123
|
+
## Confine approved commands
|
|
124
|
+
|
|
125
|
+
The CLI and native flow hosts use bubblewrap on Linux and seatbelt on macOS.
|
|
126
|
+
Approval to start a command does not open filesystem writes or networking.
|
|
127
|
+
The host derives those permissions from its effective grants, including the
|
|
128
|
+
current capability ceiling. A missing sandbox refuses the command.
|
|
129
|
+
|
|
130
|
+
Matching `fs:read:/workspace/build/**`, `fs:write:/workspace/build`, and
|
|
131
|
+
`fs:write:/workspace/build/**` grants open the `build` tree for writing.
|
|
132
|
+
The directory entry needs its own write authority. Literal writes,
|
|
133
|
+
complex globs, and permissions narrowed by a deny stay closed when the native
|
|
134
|
+
mechanism cannot represent them safely. Egress opens only with unrestricted
|
|
135
|
+
`net:get`, `net:post`, and `net:private` grants. Host-specific network grants
|
|
136
|
+
keep networking closed. Host Unix sockets stay closed with open IP networking,
|
|
137
|
+
except the fixed macOS system DNS resolver endpoint. Commands also receive private temporary storage.
|
|
138
|
+
|
|
139
|
+
`NodeHost` and `BunHost` supply confinement. A custom native host provides
|
|
140
|
+
[`ProcessConfinement.layer()`](/api/platform-node#processconfinement) to the
|
|
141
|
+
kernel spawner. A missing confinement service refuses execution.
|
|
142
|
+
`mode: "hermetic"` continues to check declarations before execution; it does
|
|
143
|
+
not grant additional OS access.
|
|
144
|
+
|
|
145
|
+
## Read the result
|
|
146
|
+
|
|
147
|
+
A non-zero exit code is an ordinary value, not a failure. Only a timeout, a
|
|
148
|
+
spawn failure, a permission refusal, and the hermetic pre-check use the error
|
|
149
|
+
channel.
|
|
150
|
+
|
|
151
|
+
| Field | Meaning |
|
|
152
|
+
| ------------------------------------------ | ----------------------------------------------------------- |
|
|
153
|
+
| `exitCode` | The command's exit code. |
|
|
154
|
+
| `stdout`, `stderr` | The captured streams, tail-first when truncated. |
|
|
155
|
+
| `stdoutTruncated`, `stderrTruncated` | Whether that stream is a fragment. |
|
|
156
|
+
| `stdoutDroppedBytes`, `stderrDroppedBytes` | Bytes omitted from the start. |
|
|
157
|
+
| `invalidProbe` | Present when the shell refused to start the command at all. |
|
|
158
|
+
|
|
159
|
+
Each stream is bounded at 30,000 bytes and the tail is kept, because a failing
|
|
160
|
+
command prints its verdict last. Never write a truncated stream to a file: it is
|
|
161
|
+
the end of a log, not the content it came from. `@smthrs/harness` reads the
|
|
162
|
+
`Truncated` flags to refuse exactly that.
|
|
163
|
+
|
|
164
|
+
`timeoutMs` defaults to `Bash.DEFAULT_TIMEOUT_MS`, ten minutes.
|
|
165
|
+
|
|
166
|
+
## The invalid-probe flag
|
|
167
|
+
|
|
168
|
+
A non-zero exit is a runner's verdict about the code it ran. It is not a verdict
|
|
169
|
+
about the command it was handed. When a command names a test, a file, a module,
|
|
170
|
+
an environment, or a program that does not exist, the runner never reaches any
|
|
171
|
+
code and still exits non-zero.
|
|
172
|
+
|
|
173
|
+
`invalidProbe` names that case, with a `reason` from a closed list
|
|
174
|
+
(`unknown-command`, `unknown-test`, `unknown-path`, `unknown-module`,
|
|
175
|
+
`unknown-environment`), the `evidence` it rests on, and a `message` stating
|
|
176
|
+
what the result does and does not prove.
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
if (result.invalidProbe !== undefined) {
|
|
180
|
+
// The exit code is about the command. Fix the names and run it again
|
|
181
|
+
// before drawing any conclusion from it.
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`bash` does not infer a launch failure from exit code 126 or 127: a launched
|
|
186
|
+
runner can return either status after running a check. It returns the captured
|
|
187
|
+
command result without `invalidProbe` when launch cannot be established. The
|
|
188
|
+
`test` flow asks the attribution judge whether a non-zero exit describes the
|
|
189
|
+
code under test or an unresolved name. See
|
|
190
|
+
[Run the test suite](./run-the-test-suite.md#who-the-failure-belongs-to).
|
|
191
|
+
|
|
192
|
+
## The Codex-shaped alternative
|
|
193
|
+
|
|
194
|
+
`shell_command` is a clone of the Codex CLI tool of the same name, for a model
|
|
195
|
+
trained on that shape. It takes `command`, `workdir`, and `timeout_ms`, and it
|
|
196
|
+
returns Codex's own rendering:
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
import * as ShellCommand from "@smthrs/std/ShellCommand"
|
|
200
|
+
|
|
201
|
+
const result = ShellCommand.run({ command: "ls -la", workdir: "/workspace" })
|
|
202
|
+
// result.output: "Exit code: 0\nWall time: 0.1 seconds\nOutput:\n..."
|
|
203
|
+
// result.exitCode: 124 when the command timed out
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The timeout defaults to 10 seconds, not ten minutes, and a timeout is a
|
|
207
|
+
successful value with exit code `ShellCommand.TIMEOUT_EXIT_CODE`. Output is
|
|
208
|
+
shaped to a 10,000-token budget by truncating the middle rather than the head.
|
|
209
|
+
Codex's `sandbox_permissions`, `justification`, and `prefix_rule` approval
|
|
210
|
+
parameters are deliberately absent: the permission kernel owns sandboxing and
|
|
211
|
+
escalation here.
|
|
212
|
+
|
|
213
|
+
Prefer `bash` for new work. It carries the effect envelope, the container
|
|
214
|
+
transport, the script form, and the per-stream truncation fields that
|
|
215
|
+
`shell_command` does not.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Run the test suite and attribute a failure"
|
|
3
|
+
description: "Declare how the project under test runs its suite, select what to run, and use against:'base' to separate the failures your edit introduced from the ones that were already there."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 5
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
The `test` flow answers three questions a shell command cannot: what the suite
|
|
9
|
+
reported, which of the failures are yours, and whether the run failed about the
|
|
10
|
+
code at all.
|
|
11
|
+
|
|
12
|
+
## Declare the runner once
|
|
13
|
+
|
|
14
|
+
A caller of `test` selects **which** tests, never **how** to run them. The
|
|
15
|
+
invocation is a host declaration, bound through the `TestRunner` service:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import * as TestRunner from "@smthrs/std/TestRunner"
|
|
19
|
+
|
|
20
|
+
const runner = TestRunner.layer({
|
|
21
|
+
command: "python -m pytest -q",
|
|
22
|
+
cwd: "/testbed",
|
|
23
|
+
root: "/workspace/repo",
|
|
24
|
+
container: "testbed",
|
|
25
|
+
env: { PYTHONDONTWRITEBYTECODE: "1" },
|
|
26
|
+
timeoutMs: 900_000
|
|
27
|
+
})
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Field | Meaning |
|
|
31
|
+
| ----------- | -------------------------------------------------------------------- |
|
|
32
|
+
| `command` | The runner command line, with no test selection in it. |
|
|
33
|
+
| `cwd` | Where the runner runs. The container's path when `container` is set. |
|
|
34
|
+
| `root` | The host path of the git repository, when it differs from `cwd`. |
|
|
35
|
+
| `container` | A container to route the run through, via the `Container` transport. |
|
|
36
|
+
| `env` | Environment the runner needs. |
|
|
37
|
+
| `baseRef` | The ref whose commit is the pristine base. |
|
|
38
|
+
| `timeoutMs` | Default wall-clock budget for one run. |
|
|
39
|
+
|
|
40
|
+
`cwd` and `root` differ exactly when the runner runs in a container: the
|
|
41
|
+
container sees the repository at `cwd`, the host sees it at `root`, and a
|
|
42
|
+
baseline checkout created at `<root>/.flows-test-base/run-<lease>` is visible to the runner
|
|
43
|
+
at `<cwd>/.flows-test-base/run-<lease>`, because it is one directory under two names.
|
|
44
|
+
|
|
45
|
+
A host with no runner binds `TestRunner.layerNoop`. The flow then fails with
|
|
46
|
+
`provider_unavailable` and tells the caller to use `bash` with the command the
|
|
47
|
+
project's own documentation gives.
|
|
48
|
+
|
|
49
|
+
## Run a selection
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import * as TestRun from "@smthrs/std/TestRun"
|
|
53
|
+
|
|
54
|
+
const result = TestRun.run({
|
|
55
|
+
selection: ["tests/test_admin.py::AdminViewBasicTest::test_change_list"]
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Selection entries reach the runner as arguments, never as text spliced into the
|
|
60
|
+
command line. The invocation is `bash -lc '<command> "$@"' <command> id...`, so a
|
|
61
|
+
test id holding `::`, `[`, `]`, spaces, or shell metacharacters stays data.
|
|
62
|
+
Omitting `selection` runs everything.
|
|
63
|
+
|
|
64
|
+
The result is a reading, not a log:
|
|
65
|
+
|
|
66
|
+
| Field | Meaning |
|
|
67
|
+
| ----------------------------------- | -------------------------------------------------------------------------- |
|
|
68
|
+
| `command` | The logical invocation, without container transport arguments. |
|
|
69
|
+
| `exitCode` | The runner's exit code. |
|
|
70
|
+
| `passed` | Tests reported passing. Zero when `parsed` is false. |
|
|
71
|
+
| `failed` | Ids of the tests reported failing or erroring. |
|
|
72
|
+
| `parsed` | Whether the runner's complete report could be read. |
|
|
73
|
+
| `tail` | The end of the runner's combined output. |
|
|
74
|
+
| `tailTruncated`, `tailDroppedBytes` | Whether `tail` is a fragment, and by how much. |
|
|
75
|
+
| `invalidProbe` | Present when the exit code describes the command, not the code under test. |
|
|
76
|
+
|
|
77
|
+
When `parsed` is false, `tail` is all there is, and base attribution is omitted
|
|
78
|
+
rather than guessed at.
|
|
79
|
+
|
|
80
|
+
Unittest skips and expected failures, and TAP skips and TODO failures, do not
|
|
81
|
+
count as passing or failing tests. A successful TAP TODO counts as passing.
|
|
82
|
+
Unittest unexpected successes count as failures; attribution requires their
|
|
83
|
+
reported ids. Python 3.10 class-only headers and Python 3.11+ full test ids are
|
|
84
|
+
both supported. Missing failure ids or unknown unittest summary fields leave
|
|
85
|
+
`parsed` false.
|
|
86
|
+
|
|
87
|
+
## Who the failure belongs to
|
|
88
|
+
|
|
89
|
+
A non-zero exit is a runner's verdict about the code it ran, not about the
|
|
90
|
+
command it was handed. A run that names a test, a file, a module, an
|
|
91
|
+
environment, or a program that does not exist never reaches any code and still
|
|
92
|
+
exits non-zero, so it reads the same before and after a correct fix.
|
|
93
|
+
`invalidProbe` is present when this run was one of those, with a `reason` from
|
|
94
|
+
that closed list and a `message` saying what the result does and does not
|
|
95
|
+
prove.
|
|
96
|
+
|
|
97
|
+
Jev makes that attribution. The flow asks the `probe/attribution` classifier
|
|
98
|
+
through the `Evaluator` service of [`@smthrs/model`](/api/model), so a host
|
|
99
|
+
binds an evaluator on a subscription seat. Only a zero exit is attributed without a judge. Exit codes 126 and 127
|
|
100
|
+
also go through attribution: a runner can return them after executing tests.
|
|
101
|
+
A judge that cannot
|
|
102
|
+
be reached, refuses, times out, or answers something unusable fails the call
|
|
103
|
+
with `provider_unavailable`, `timeout`, or `request_failed`, because a guess at
|
|
104
|
+
whether a reproduction reproduced is worth less than no answer at all.
|
|
105
|
+
|
|
106
|
+
## Attribute a failure to your own edit
|
|
107
|
+
|
|
108
|
+
The native CLI supports workspace tests. Baseline comparison refuses before any
|
|
109
|
+
command starts; isolated staging is tracked in
|
|
110
|
+
[#3234](https://github.com/smithersai/smithers/issues/3234). A host declares this
|
|
111
|
+
with `baseline: false`.
|
|
112
|
+
|
|
113
|
+
`against: "base"` runs the same selection a second time against the pristine
|
|
114
|
+
base commit, in a scratch checkout, and differences the two failure sets:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
const result = TestRun.run({
|
|
118
|
+
selection: ["tests/test_admin.py"],
|
|
119
|
+
against: "base"
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
result.introduced // failing here and not on the base tree: yours
|
|
123
|
+
result.preexisting // failing on both: not yours, and not worth investigating
|
|
124
|
+
result.fixed // failing on the base tree and passing here
|
|
125
|
+
result.base // the base run's own outcome, plus its ref and commit
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
That is the whole of attribution, in one call. Without it, the same question
|
|
129
|
+
costs a revert of the very work it was meant to prove.
|
|
130
|
+
|
|
131
|
+
The baseline commit is resolved from the runner's `baseRef`, then from
|
|
132
|
+
`TestRunner.captureBase` (`refs/flows/capture-base`), then from `HEAD`. A
|
|
133
|
+
`baseRef` that does not resolve is an error rather than a fallback, because a
|
|
134
|
+
baseline against the wrong tree answers the attribution question wrong.
|
|
135
|
+
|
|
136
|
+
The baseline is a detached checkout at `<root>/.flows-test-base/run-<lease>`, under
|
|
137
|
+
`TestRun.scratchDirectory`. Each call gets a unique lease. Existing checkouts
|
|
138
|
+
are left alone; a `SIGKILL` can leave one behind. Inside the repository is the only place that works:
|
|
139
|
+
a runner reaching the repository through a container mount sees a scratch
|
|
140
|
+
checkout anywhere else on the host as a path that does not exist. It is removed
|
|
141
|
+
when the call ends, however it ends. It is written from a temporary shadow
|
|
142
|
+
`GIT_DIR`, like a checkpoint, so no hook or filter driver in the workspace's
|
|
143
|
+
`.git` runs on the host and the repository's format is never changed.
|
|
144
|
+
|
|
145
|
+
`against: "base"` needs a repository directory. A runner declaring neither `root`
|
|
146
|
+
nor `cwd` fails with `invalid_input`.
|
|
147
|
+
|
|
148
|
+
## Bound the run
|
|
149
|
+
|
|
150
|
+
`timeoutMs` on the call overrides the runner's own, which overrides
|
|
151
|
+
`TestRun.DEFAULT_TIMEOUT_MS` (ten minutes). The run holds at most
|
|
152
|
+
`TestRun.MAX_CAPTURE_BYTES` of output in memory, and `tail` carries the last
|
|
153
|
+
30,000 bytes of it, so `tail` holds the part of a long run that says what
|
|
154
|
+
failed. A timeout is a `timeout` failure, not a result.
|