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