bashkit 0.3.0__tar.gz → 0.4.0__tar.gz
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.
- {bashkit-0.3.0 → bashkit-0.4.0}/Cargo.lock +20 -9
- {bashkit-0.3.0 → bashkit-0.4.0}/Cargo.toml +1 -1
- {bashkit-0.3.0 → bashkit-0.4.0}/PKG-INFO +1 -1
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/Cargo.toml +12 -2
- bashkit-0.4.0/crates/bashkit/benches/sqlite.rs +424 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/custom_builtins.md +39 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/threat-model.md +38 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/typescript.md +10 -0
- bashkit-0.4.0/crates/bashkit/examples/clap_builtin.rs +54 -0
- bashkit-0.4.0/crates/bashkit/examples/clap_builtin_subcommands.rs +63 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/mod.rs +240 -1
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/python.rs +5 -5
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/sqlite/mod.rs +158 -73
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/sqlite/parser.rs +107 -17
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/sqlite/tests.rs +38 -3
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/sqlite/vfs_io.rs +26 -22
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/typescript.rs +89 -1
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/lib.rs +93 -43
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/scripted_tool/execute.rs +27 -481
- bashkit-0.4.0/crates/bashkit/src/scripted_tool/extension.rs +552 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/scripted_tool/mod.rs +32 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/tool.rs +150 -2
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/custom_builtins_tests.rs +133 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/python_integration_tests.rs +1 -1
- bashkit-0.4.0/crates/bashkit/tests/sqlite_differential_tests.rs +331 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/sqlite_integration_tests.rs +98 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/ssh_supabase_tests.rs +18 -7
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/threat_model_tests.rs +8 -8
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/typescript_security_tests.rs +16 -1
- {bashkit-0.3.0 → bashkit-0.4.0}/README.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/bashkit/__init__.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/bashkit/_bashkit.pyi +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/bashkit/deepagents.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/bashkit/langchain.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/bashkit/py.typed +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/bashkit/pydantic_ai.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/README.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/benches/parallel_execution.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/compatibility.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/credential-injection.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/hooks.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/jq.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/live_mounts.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/logging.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/python.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/sqlite.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/docs/ssh.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/agent_tool.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/basic.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/custom_backend.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/custom_builtins.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/custom_filesystem_impl.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/custom_fs.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/git_workflow.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/live_mounts.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/python_external_functions.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/python_scripts.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/realfs_readonly.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/realfs_readwrite.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/resource_limits.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/scripted_tool.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/show_tool_output.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/sqlite_basic.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/sqlite_workflow.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/ssh_supabase.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/streaming_output.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/text_files.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/text_processing.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/typescript_external_functions.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/typescript_scripts.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/examples/virtual_identity.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/proptest-regressions/builtins/sqlite/tests.txt +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/alias.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/archive.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/arg_parser.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/assert.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/awk.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/base64.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/bc.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/caller.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/cat.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/checksum.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/clear.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/column.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/comm.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/compgen.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/csv.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/curl.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/cuttr.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/date.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/diff.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/dirstack.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/disk.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/dotenv.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/echo.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/environ.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/envsubst.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/expand.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/export.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/expr.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/fc.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/fileops.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/flow.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/fold.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/git/client.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/git/cmd.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/git/config.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/git/mod.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/glob_cmd.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/grep.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/headtail.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/help.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/hextools.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/http.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/iconv.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/inspect.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/introspect.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/join.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/jq/args.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/jq/compat.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/jq/convert.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/jq/errors.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/jq/format.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/jq/mod.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/jq/regex_compat.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/jq/tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/json.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/log.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/ls.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/mapfile.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/mkfifo.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/navigation.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/nl.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/numfmt.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/parallel.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/paste.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/patch.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/path.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/pipeline.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/printf.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/read.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/retry.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/rg.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/search_common.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/sed.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/semver.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/seq.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/sleep.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/sortuniq.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/source.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/split.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/sqlite/dot_commands.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/sqlite/engine.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/sqlite/formatter.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/ssh/allowlist.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/ssh/client.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/ssh/cmd.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/ssh/config.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/ssh/handler.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/ssh/mod.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/ssh/russh_handler.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/strings.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/system.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/template.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/textrev.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/timeout.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/tomlq.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/trap.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/tree.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/vars.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/verify.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/wait.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/wc.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/yaml.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/yes.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/builtins/zip_cmd.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/credential.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/error.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/fs/backend.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/fs/limits.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/fs/memory.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/fs/mod.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/fs/mountable.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/fs/overlay.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/fs/posix.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/fs/realfs.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/fs/search.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/fs/traits.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/hooks.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/interop/fs.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/interop/mod.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/interpreter/glob.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/interpreter/jobs.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/interpreter/mod.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/interpreter/state.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/limits.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/logging_impl.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/network/allowlist.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/network/bot_auth.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/network/client.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/network/mod.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/parser/ast.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/parser/budget.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/parser/lexer.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/parser/mod.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/parser/span.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/parser/tokens.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/scripted_tool/toolset.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/snapshot.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/testing.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/tool_def.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/src/trace.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/allexport_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/awk_fuzz_scaffold_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/awk_newline_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/awk_pattern_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/awk_printf_expr_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/awk_range_pattern_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/background_exec_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/bash_source_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/blackbox_security_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/builtin_error_security_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/byte_range_panic_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/cancellation_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/cmdsub_quote_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/coproc_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/credential_injection_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/custom_fs_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/dev_null_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/final_env_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/find_multi_path_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/git_advanced_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/git_inspection_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/git_integration_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/git_remote_security_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/git_security_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/harness_example_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/history_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_1175_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_274_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_275_279_282_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_276_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_277_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_289_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_290_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_291_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_853_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_872_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_873_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/issue_875_test.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/jq_fuzz_scaffold_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/live_mount_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/logging_security_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/mkfifo_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/nested_subscript_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/network_security_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/output_truncation_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/overlay_path_validation_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/proptest_differential.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/proptest_security.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/python_security_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/realfs_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/regex_limit_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/release_profile_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/script_execution_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/security_audit_pocs.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/security_failpoint_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/set_e_and_or_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/skills_fixtures/azure_discover_rank.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/skills_fixtures/azure_generate_url.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/skills_fixtures/azure_query_capacity.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/skills_fixtures/helm_validate_chart.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/skills_fixtures/jwt_test_setup.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/skills_fixtures/stitch_download_asset.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/skills_fixtures/stitch_fetch.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/skills_fixtures/stitch_verify_setup.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/skills_fixtures/superpowers_find_polluter.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/skills_fixtures/vercel_deploy.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/skills_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/snapshot_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/source_function_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/awk/awk.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/awk/delete-array.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/awk/dev-stderr.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/awk/eval-bugs.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/awk/filename.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/awk/getline-file.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/alias.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/append_redirect.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/arith-dynamic.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/arithmetic-base-expansion.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/arithmetic.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/array-slicing.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/array-splat.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/arrays.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/awk-printf-width.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/background.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/bash-c-exports.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/bash-command.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/bash-flags.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/bash-source-var.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/bash-stdin-pipe.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/bc.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/blackbox-edge-cases.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/blackbox-exploration.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/brace-expansion.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/brace_expansion_lookahead.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/checksum.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/chown-kill.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/cmd-suggestions.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/cmdsub_depth_unquoted.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/column.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/comm.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/command-not-found.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/command-subst.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/command.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/command_v.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/compgen-path.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/conditional-short-circuit.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/conditional.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/control-flow.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/cuttr.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/date.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/declare.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/df.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/diff.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/dirstack.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/du.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/echo.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/empty-bodies.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/env.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/errexit.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/eval-bugs.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/exec-command.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/exec-fd-redirect.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/exec-fd-variable.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/exit-status.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/expr.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/extglob.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/file.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/fileops.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/find.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/functions.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/getopts.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/glob-options.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/glob_match_cap.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/globs.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/gzip.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/headtail.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/help-flag.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/heredoc-edge.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/heredoc.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/herestring.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/hextools.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/history.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/indirect-expansion.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/less.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/ln.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/ls.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/memory_budget_desync.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/nameref-assoc.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/nameref.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/negative-tests.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/nl.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/nounset.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/numfmt.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/parse-errors.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/paste-flags.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/paste.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/path.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/pipes-redirects.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/printenv.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/printf.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/procsub.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/quote.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/read-builtin.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/recursive-cmdsub.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/regex-limit.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/replace_pattern_limit.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/script-exec.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/seq.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/set-allexport.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/shell-grammar.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/sleep.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/sortuniq.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/source.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/stat.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/string-ops.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/strings.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/subprocess-isolation.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/subshell.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/tar.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/tar_create.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/tee.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/temp-binding.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/test-operators.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/test-tty.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/textrev.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/time.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/timeout.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/tree.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/type.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/unicode.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/unset-exported-var.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/var-op-test.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/variables.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/wait.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/watch.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/wc.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/word-split.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/bash/xargs.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/grep/eval-bugs.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/grep/grep.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/grep/rg.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/jq/jq.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/python/env_leak.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/python/python.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/sed/eval-bugs.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/sed/sed.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_cases/typescript/typescript.test.sh +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_runner.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/spec_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/sqlite_compat_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/sqlite_fuzz_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/sqlite_security_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/ssh_builtin_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/stack_overflow_regression_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/subst_depth_limit_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/symlink_overlay_security_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/tty_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/typescript_integration_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/unicode_security_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/unset_function_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit/tests/urandom_tests.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/Cargo.toml +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/README.md +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/examples/bash_basics.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/examples/custom_filesystem_interop.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/examples/data_pipeline.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/examples/fastapi_async_tool.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/examples/jupyter_async_test.ipynb +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/examples/k8s_orchestrator.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/examples/langgraph_async_tool.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/examples/llm_tool.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/src/lib.rs +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/_bashkit_categories.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/_security_advanced.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/_security_core.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_ai_adapters.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_async_callbacks.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_basic.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_builtins.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_control_flow.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_error_handling.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_fastapi_integration.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_filesystem_interop.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_integration.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_jupyter_compat.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_langgraph_integration.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_network_config.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_network_credentials.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_python_security.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_registered_tools.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_scripts.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_security.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_shell_injection.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_sqlite.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_streaming_output.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_strings_and_quoting.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_tool_metadata.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/crates/bashkit-python/tests/test_vfs.py +0 -0
- {bashkit-0.3.0 → bashkit-0.4.0}/pyproject.toml +0 -0
|
@@ -345,12 +345,13 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
|
|
|
345
345
|
|
|
346
346
|
[[package]]
|
|
347
347
|
name = "bashkit"
|
|
348
|
-
version = "0.
|
|
348
|
+
version = "0.4.0"
|
|
349
349
|
dependencies = [
|
|
350
350
|
"anyhow",
|
|
351
351
|
"async-trait",
|
|
352
352
|
"base64",
|
|
353
353
|
"chrono",
|
|
354
|
+
"clap",
|
|
354
355
|
"criterion",
|
|
355
356
|
"ed25519-dalek 2.2.0",
|
|
356
357
|
"fail",
|
|
@@ -392,7 +393,7 @@ dependencies = [
|
|
|
392
393
|
|
|
393
394
|
[[package]]
|
|
394
395
|
name = "bashkit-bench"
|
|
395
|
-
version = "0.
|
|
396
|
+
version = "0.4.0"
|
|
396
397
|
dependencies = [
|
|
397
398
|
"anyhow",
|
|
398
399
|
"bashkit",
|
|
@@ -406,7 +407,7 @@ dependencies = [
|
|
|
406
407
|
|
|
407
408
|
[[package]]
|
|
408
409
|
name = "bashkit-cli"
|
|
409
|
-
version = "0.
|
|
410
|
+
version = "0.4.0"
|
|
410
411
|
dependencies = [
|
|
411
412
|
"anyhow",
|
|
412
413
|
"bashkit",
|
|
@@ -422,7 +423,7 @@ dependencies = [
|
|
|
422
423
|
|
|
423
424
|
[[package]]
|
|
424
425
|
name = "bashkit-eval"
|
|
425
|
-
version = "0.
|
|
426
|
+
version = "0.4.0"
|
|
426
427
|
dependencies = [
|
|
427
428
|
"anyhow",
|
|
428
429
|
"async-trait",
|
|
@@ -439,7 +440,7 @@ dependencies = [
|
|
|
439
440
|
|
|
440
441
|
[[package]]
|
|
441
442
|
name = "bashkit-js"
|
|
442
|
-
version = "0.
|
|
443
|
+
version = "0.4.0"
|
|
443
444
|
dependencies = [
|
|
444
445
|
"bashkit",
|
|
445
446
|
"napi",
|
|
@@ -452,7 +453,7 @@ dependencies = [
|
|
|
452
453
|
|
|
453
454
|
[[package]]
|
|
454
455
|
name = "bashkit-python"
|
|
455
|
-
version = "0.
|
|
456
|
+
version = "0.4.0"
|
|
456
457
|
dependencies = [
|
|
457
458
|
"bashkit",
|
|
458
459
|
"num-bigint",
|
|
@@ -2811,8 +2812,8 @@ dependencies = [
|
|
|
2811
2812
|
|
|
2812
2813
|
[[package]]
|
|
2813
2814
|
name = "monty"
|
|
2814
|
-
version = "0.0.
|
|
2815
|
-
source = "git+https://github.com/pydantic/monty?rev=
|
|
2815
|
+
version = "0.0.17"
|
|
2816
|
+
source = "git+https://github.com/pydantic/monty?rev=49faa4c#49faa4c8ae94490eae286e76259adcc35f64f0a5"
|
|
2816
2817
|
dependencies = [
|
|
2817
2818
|
"ahash",
|
|
2818
2819
|
"bytemuck",
|
|
@@ -2827,11 +2828,12 @@ dependencies = [
|
|
|
2827
2828
|
"num-integer",
|
|
2828
2829
|
"num-traits",
|
|
2829
2830
|
"postcard",
|
|
2830
|
-
"pyo3-build-config",
|
|
2831
2831
|
"ruff_python_ast",
|
|
2832
2832
|
"ruff_python_parser",
|
|
2833
|
+
"ruff_python_stdlib",
|
|
2833
2834
|
"ruff_text_size",
|
|
2834
2835
|
"serde",
|
|
2836
|
+
"serde_json",
|
|
2835
2837
|
"smallvec",
|
|
2836
2838
|
"speedate",
|
|
2837
2839
|
"strum 0.27.2",
|
|
@@ -4246,6 +4248,15 @@ dependencies = [
|
|
|
4246
4248
|
"unicode_names2",
|
|
4247
4249
|
]
|
|
4248
4250
|
|
|
4251
|
+
[[package]]
|
|
4252
|
+
name = "ruff_python_stdlib"
|
|
4253
|
+
version = "0.0.0"
|
|
4254
|
+
source = "git+https://github.com/astral-sh/ruff.git?rev=6ded4bed1651e30b34dd04cdaa50c763036abb0d#6ded4bed1651e30b34dd04cdaa50c763036abb0d"
|
|
4255
|
+
dependencies = [
|
|
4256
|
+
"bitflags",
|
|
4257
|
+
"unicode-ident",
|
|
4258
|
+
]
|
|
4259
|
+
|
|
4249
4260
|
[[package]]
|
|
4250
4261
|
name = "ruff_python_trivia"
|
|
4251
4262
|
version = "0.0.0"
|
|
@@ -77,8 +77,11 @@ hmac = "0.13"
|
|
|
77
77
|
# Logging/tracing (optional)
|
|
78
78
|
tracing = { workspace = true, optional = true }
|
|
79
79
|
|
|
80
|
+
# CLI-style argument parsing for custom builtins.
|
|
81
|
+
clap = { workspace = true, optional = true }
|
|
82
|
+
|
|
80
83
|
# Embedded Python interpreter (optional)
|
|
81
|
-
monty = { git = "https://github.com/pydantic/monty", rev = "
|
|
84
|
+
monty = { git = "https://github.com/pydantic/monty", rev = "49faa4c", optional = true }
|
|
82
85
|
|
|
83
86
|
# Embedded TypeScript interpreter (optional)
|
|
84
87
|
zapcode-core = { version = "1.5", optional = true }
|
|
@@ -88,7 +91,9 @@ zapcode-core = { version = "1.5", optional = true }
|
|
|
88
91
|
turso_core = { workspace = true, optional = true }
|
|
89
92
|
|
|
90
93
|
[features]
|
|
91
|
-
default = []
|
|
94
|
+
default = ["clap-builtins"]
|
|
95
|
+
# Enable `ClapBuiltin` for custom builtins with `#[derive(clap::Parser)]`.
|
|
96
|
+
clap-builtins = ["dep:clap"]
|
|
92
97
|
# Enable jq builtin via embedded jaq interpreter
|
|
93
98
|
# Usage: cargo build --features jq
|
|
94
99
|
jq = ["dep:jaq-core", "dep:jaq-std", "dep:jaq-json"]
|
|
@@ -153,6 +158,11 @@ serial_test = { workspace = true }
|
|
|
153
158
|
name = "parallel_execution"
|
|
154
159
|
harness = false
|
|
155
160
|
|
|
161
|
+
[[bench]]
|
|
162
|
+
name = "sqlite"
|
|
163
|
+
harness = false
|
|
164
|
+
required-features = ["sqlite"]
|
|
165
|
+
|
|
156
166
|
[[example]]
|
|
157
167
|
name = "agent_tool"
|
|
158
168
|
required-features = ["http_client"]
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
//! SQLite builtin benchmark for Bashkit
|
|
2
|
+
//!
|
|
3
|
+
//! Targets the `sqlite` builtin (Turso, in-process) along the dimensions
|
|
4
|
+
//! that actually matter for users:
|
|
5
|
+
//!
|
|
6
|
+
//! - **Workload shapes**: bulk INSERT, batched UPDATE, indexed vs full-scan
|
|
7
|
+
//! SELECT, aggregate (GROUP BY + COUNT/SUM/AVG).
|
|
8
|
+
//! - **Output modes**: list (default), CSV, JSON, markdown — exercise the
|
|
9
|
+
//! formatter on the same row set.
|
|
10
|
+
//! - **Backends**: `Memory` (load whole DB into turso's `MemoryIO`) vs `Vfs`
|
|
11
|
+
//! (custom IO trait talking to bashkit's FileSystem).
|
|
12
|
+
//! - **Persistence cost**: opening a fresh DB per invocation (load + flush)
|
|
13
|
+
//! vs `:memory:` (zero VFS round-trip).
|
|
14
|
+
//! - **Concurrency**: N parallel sqlite sessions over a shared VFS, each
|
|
15
|
+
//! with its own DB file — measures the cooperative-IO path under load.
|
|
16
|
+
//!
|
|
17
|
+
//! Each bench prints a single-row sentinel so successful execution can be
|
|
18
|
+
//! eyeballed in `cargo bench` output without parsing Criterion JSON.
|
|
19
|
+
|
|
20
|
+
use bashkit::{Bash, FileSystem, InMemoryFs, SqliteBackend, SqliteLimits};
|
|
21
|
+
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
|
|
22
|
+
use std::sync::Arc;
|
|
23
|
+
use tokio::runtime::Runtime;
|
|
24
|
+
|
|
25
|
+
/// Row counts to exercise scaling. Kept modest so a full `cargo bench` run
|
|
26
|
+
/// finishes in reasonable time on CI hardware; tune up locally if you need
|
|
27
|
+
/// more signal.
|
|
28
|
+
const ROW_COUNTS: &[usize] = &[100, 1_000, 10_000];
|
|
29
|
+
|
|
30
|
+
/// Concurrency levels for the parallel-sessions group.
|
|
31
|
+
const SESSION_COUNTS: &[usize] = &[4, 16, 64];
|
|
32
|
+
|
|
33
|
+
/// Build a Bash with sqlite enabled and the opt-in env set. Optionally
|
|
34
|
+
/// share a filesystem so multiple sessions hit the same VFS.
|
|
35
|
+
fn make_bash(backend: SqliteBackend, fs: Option<Arc<dyn FileSystem>>) -> Bash {
|
|
36
|
+
let mut builder = Bash::builder()
|
|
37
|
+
.sqlite_with_limits(
|
|
38
|
+
SqliteLimits::default()
|
|
39
|
+
.backend(backend)
|
|
40
|
+
// Lift caps so large-N benches don't trip the defaults.
|
|
41
|
+
.max_rows_per_query(1_000_000)
|
|
42
|
+
.max_statements(1_000_000)
|
|
43
|
+
.max_script_bytes(64 * 1024 * 1024),
|
|
44
|
+
)
|
|
45
|
+
.env("BASHKIT_ALLOW_INPROCESS_SQLITE", "1");
|
|
46
|
+
if let Some(fs) = fs {
|
|
47
|
+
builder = builder.fs(fs);
|
|
48
|
+
}
|
|
49
|
+
builder.build()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// SQL that seeds a `kv(id, k, v)` table with `n` rows using a recursive CTE.
|
|
53
|
+
/// Faster than emitting `n` literal `INSERT` statements through the parser.
|
|
54
|
+
fn seed_kv_sql(n: usize) -> String {
|
|
55
|
+
format!(
|
|
56
|
+
r#"
|
|
57
|
+
CREATE TABLE IF NOT EXISTS kv(id INTEGER PRIMARY KEY, k TEXT, v INTEGER);
|
|
58
|
+
WITH RECURSIVE seq(i) AS (
|
|
59
|
+
SELECT 1 UNION ALL SELECT i+1 FROM seq WHERE i < {n}
|
|
60
|
+
)
|
|
61
|
+
INSERT INTO kv(k, v) SELECT 'key' || i, i*7 % 113 FROM seq;
|
|
62
|
+
"#
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Workload helpers (each takes a fresh Bash, runs the workload, returns).
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
async fn bench_insert(backend: SqliteBackend, n: usize) {
|
|
71
|
+
let mut bash = make_bash(backend, None);
|
|
72
|
+
let script = format!(
|
|
73
|
+
"sqlite /tmp/bench.sqlite \"{}; SELECT count(*) FROM kv\"",
|
|
74
|
+
seed_kv_sql(n).replace('"', "\\\"")
|
|
75
|
+
);
|
|
76
|
+
let _ = bash.exec(&script).await;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async fn bench_update(backend: SqliteBackend, n: usize) {
|
|
80
|
+
let mut bash = make_bash(backend, None);
|
|
81
|
+
let setup = seed_kv_sql(n).replace('"', "\\\"");
|
|
82
|
+
let script = format!(
|
|
83
|
+
"sqlite /tmp/bench.sqlite \"{setup}; UPDATE kv SET v = v + 1 WHERE k LIKE 'key1%'; SELECT changes()\""
|
|
84
|
+
);
|
|
85
|
+
let _ = bash.exec(&script).await;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async fn bench_index_create_and_query(backend: SqliteBackend, n: usize) {
|
|
89
|
+
let mut bash = make_bash(backend, None);
|
|
90
|
+
let setup = seed_kv_sql(n).replace('"', "\\\"");
|
|
91
|
+
// Without index → with index → repeat the same point-query, measuring
|
|
92
|
+
// the combined "schema change + indexed lookup" path. The point-query
|
|
93
|
+
// alone is benched in `bench_query_indexed` below.
|
|
94
|
+
let script = format!(
|
|
95
|
+
"sqlite /tmp/bench.sqlite \"{setup}; CREATE INDEX IF NOT EXISTS idx_kv_k ON kv(k); SELECT v FROM kv WHERE k = 'key42'\""
|
|
96
|
+
);
|
|
97
|
+
let _ = bash.exec(&script).await;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async fn bench_query_indexed(backend: SqliteBackend, n: usize) {
|
|
101
|
+
let mut bash = make_bash(backend, None);
|
|
102
|
+
let setup = seed_kv_sql(n).replace('"', "\\\"");
|
|
103
|
+
let script = format!(
|
|
104
|
+
"sqlite /tmp/bench.sqlite \"{setup}; CREATE INDEX idx_kv_k ON kv(k); SELECT count(*) FROM kv WHERE k IN ('key1','key100','key1000','key9999')\""
|
|
105
|
+
);
|
|
106
|
+
let _ = bash.exec(&script).await;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async fn bench_query_full_scan(backend: SqliteBackend, n: usize) {
|
|
110
|
+
let mut bash = make_bash(backend, None);
|
|
111
|
+
let setup = seed_kv_sql(n).replace('"', "\\\"");
|
|
112
|
+
// No index → forces a full scan with a LIKE predicate that the planner
|
|
113
|
+
// cannot satisfy from sqlite_master.
|
|
114
|
+
let script = format!(
|
|
115
|
+
"sqlite /tmp/bench.sqlite \"{setup}; SELECT count(*) FROM kv WHERE k LIKE '%99%'\""
|
|
116
|
+
);
|
|
117
|
+
let _ = bash.exec(&script).await;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async fn bench_aggregate(backend: SqliteBackend, n: usize) {
|
|
121
|
+
let mut bash = make_bash(backend, None);
|
|
122
|
+
let setup = seed_kv_sql(n).replace('"', "\\\"");
|
|
123
|
+
let script = format!(
|
|
124
|
+
"sqlite /tmp/bench.sqlite \"{setup}; SELECT v % 10 AS bucket, count(*), sum(v), avg(v) FROM kv GROUP BY bucket ORDER BY bucket\""
|
|
125
|
+
);
|
|
126
|
+
let _ = bash.exec(&script).await;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async fn bench_output_mode(backend: SqliteBackend, n: usize, mode_flag: &str) {
|
|
130
|
+
let mut bash = make_bash(backend, None);
|
|
131
|
+
let setup = seed_kv_sql(n).replace('"', "\\\"");
|
|
132
|
+
// Materialise the full row set through the formatter — this is what
|
|
133
|
+
// changes between modes; the underlying scan is identical.
|
|
134
|
+
let script = format!(
|
|
135
|
+
"sqlite {mode_flag} -header /tmp/bench.sqlite \"{setup}; SELECT id, k, v FROM kv ORDER BY id\""
|
|
136
|
+
);
|
|
137
|
+
let _ = bash.exec(&script).await;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async fn bench_persistence_per_invocation(backend: SqliteBackend, n: usize) {
|
|
141
|
+
// Two invocations: write, then read — measures load+flush per call.
|
|
142
|
+
let fs: Arc<dyn FileSystem> = Arc::new(InMemoryFs::new());
|
|
143
|
+
let mut bash = make_bash(backend, Some(Arc::clone(&fs)));
|
|
144
|
+
let setup = seed_kv_sql(n).replace('"', "\\\"");
|
|
145
|
+
let _ = bash
|
|
146
|
+
.exec(&format!("sqlite /tmp/persist.sqlite \"{setup}\""))
|
|
147
|
+
.await;
|
|
148
|
+
let _ = bash
|
|
149
|
+
.exec("sqlite /tmp/persist.sqlite 'SELECT count(*) FROM kv'")
|
|
150
|
+
.await;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async fn bench_in_memory_only(n: usize) {
|
|
154
|
+
let mut bash = make_bash(SqliteBackend::Memory, None);
|
|
155
|
+
let setup = seed_kv_sql(n).replace('"', "\\\"");
|
|
156
|
+
// `:memory:` skips the VFS entirely; isolates pure engine cost.
|
|
157
|
+
let script = format!("sqlite :memory: \"{setup}; SELECT count(*) FROM kv\"");
|
|
158
|
+
let _ = bash.exec(&script).await;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async fn bench_parallel_sessions(sessions: usize, rows: usize, backend: SqliteBackend) {
|
|
162
|
+
// Shared VFS, distinct DB file per session — tests the cooperative-IO
|
|
163
|
+
// path without contending on a single sqlite file (which the builtin
|
|
164
|
+
// doesn't try to coordinate; see `specs/sqlite-builtin.md`).
|
|
165
|
+
let fs: Arc<dyn FileSystem> = Arc::new(InMemoryFs::new());
|
|
166
|
+
let handles: Vec<_> = (0..sessions)
|
|
167
|
+
.map(|i| {
|
|
168
|
+
let fs = Arc::clone(&fs);
|
|
169
|
+
tokio::spawn(async move {
|
|
170
|
+
let mut bash = make_bash(backend, Some(fs));
|
|
171
|
+
let setup = seed_kv_sql(rows).replace('"', "\\\"");
|
|
172
|
+
let script = format!(
|
|
173
|
+
"sqlite /tmp/sess_{i}.sqlite \"{setup}; SELECT count(*), sum(v) FROM kv\""
|
|
174
|
+
);
|
|
175
|
+
let _ = bash.exec(&script).await;
|
|
176
|
+
})
|
|
177
|
+
})
|
|
178
|
+
.collect();
|
|
179
|
+
for h in handles {
|
|
180
|
+
let _ = h.await;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
// Criterion groups
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
|
|
188
|
+
fn bench_crud(c: &mut Criterion) {
|
|
189
|
+
let rt = Runtime::new().unwrap();
|
|
190
|
+
let mut group = c.benchmark_group("sqlite_crud");
|
|
191
|
+
group.sample_size(20);
|
|
192
|
+
|
|
193
|
+
for &n in ROW_COUNTS {
|
|
194
|
+
group.throughput(Throughput::Elements(n as u64));
|
|
195
|
+
|
|
196
|
+
group.bench_with_input(BenchmarkId::new("insert_mem", n), &n, |b, &n| {
|
|
197
|
+
b.to_async(&rt)
|
|
198
|
+
.iter(|| bench_insert(SqliteBackend::Memory, n));
|
|
199
|
+
});
|
|
200
|
+
group.bench_with_input(BenchmarkId::new("insert_vfs", n), &n, |b, &n| {
|
|
201
|
+
b.to_async(&rt).iter(|| bench_insert(SqliteBackend::Vfs, n));
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
group.bench_with_input(BenchmarkId::new("update_mem", n), &n, |b, &n| {
|
|
205
|
+
b.to_async(&rt)
|
|
206
|
+
.iter(|| bench_update(SqliteBackend::Memory, n));
|
|
207
|
+
});
|
|
208
|
+
group.bench_with_input(BenchmarkId::new("update_vfs", n), &n, |b, &n| {
|
|
209
|
+
b.to_async(&rt).iter(|| bench_update(SqliteBackend::Vfs, n));
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
group.finish();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
fn bench_indexing(c: &mut Criterion) {
|
|
217
|
+
let rt = Runtime::new().unwrap();
|
|
218
|
+
let mut group = c.benchmark_group("sqlite_index");
|
|
219
|
+
group.sample_size(20);
|
|
220
|
+
|
|
221
|
+
for &n in ROW_COUNTS {
|
|
222
|
+
group.throughput(Throughput::Elements(n as u64));
|
|
223
|
+
|
|
224
|
+
group.bench_with_input(BenchmarkId::new("create_index_mem", n), &n, |b, &n| {
|
|
225
|
+
b.to_async(&rt)
|
|
226
|
+
.iter(|| bench_index_create_and_query(SqliteBackend::Memory, n));
|
|
227
|
+
});
|
|
228
|
+
group.bench_with_input(BenchmarkId::new("indexed_lookup_mem", n), &n, |b, &n| {
|
|
229
|
+
b.to_async(&rt)
|
|
230
|
+
.iter(|| bench_query_indexed(SqliteBackend::Memory, n));
|
|
231
|
+
});
|
|
232
|
+
group.bench_with_input(BenchmarkId::new("full_scan_mem", n), &n, |b, &n| {
|
|
233
|
+
b.to_async(&rt)
|
|
234
|
+
.iter(|| bench_query_full_scan(SqliteBackend::Memory, n));
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
group.finish();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
fn bench_queries(c: &mut Criterion) {
|
|
242
|
+
let rt = Runtime::new().unwrap();
|
|
243
|
+
let mut group = c.benchmark_group("sqlite_query");
|
|
244
|
+
group.sample_size(20);
|
|
245
|
+
|
|
246
|
+
for &n in ROW_COUNTS {
|
|
247
|
+
group.throughput(Throughput::Elements(n as u64));
|
|
248
|
+
|
|
249
|
+
group.bench_with_input(BenchmarkId::new("aggregate_mem", n), &n, |b, &n| {
|
|
250
|
+
b.to_async(&rt)
|
|
251
|
+
.iter(|| bench_aggregate(SqliteBackend::Memory, n));
|
|
252
|
+
});
|
|
253
|
+
group.bench_with_input(BenchmarkId::new("aggregate_vfs", n), &n, |b, &n| {
|
|
254
|
+
b.to_async(&rt)
|
|
255
|
+
.iter(|| bench_aggregate(SqliteBackend::Vfs, n));
|
|
256
|
+
});
|
|
257
|
+
group.bench_with_input(BenchmarkId::new("aggregate_in_memory", n), &n, |b, &n| {
|
|
258
|
+
b.to_async(&rt).iter(|| bench_in_memory_only(n));
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
group.finish();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
fn bench_output_modes(c: &mut Criterion) {
|
|
266
|
+
let rt = Runtime::new().unwrap();
|
|
267
|
+
let mut group = c.benchmark_group("sqlite_output_mode");
|
|
268
|
+
group.sample_size(20);
|
|
269
|
+
|
|
270
|
+
let n = 1_000;
|
|
271
|
+
group.throughput(Throughput::Elements(n as u64));
|
|
272
|
+
for (label, flag) in [
|
|
273
|
+
("list", ""),
|
|
274
|
+
("csv", "-csv"),
|
|
275
|
+
("json", "-json"),
|
|
276
|
+
("markdown", "-markdown"),
|
|
277
|
+
("box", "-box"),
|
|
278
|
+
] {
|
|
279
|
+
group.bench_function(label, |b| {
|
|
280
|
+
b.to_async(&rt)
|
|
281
|
+
.iter(|| bench_output_mode(SqliteBackend::Memory, n, flag));
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
group.finish();
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
fn bench_persistence(c: &mut Criterion) {
|
|
289
|
+
let rt = Runtime::new().unwrap();
|
|
290
|
+
let mut group = c.benchmark_group("sqlite_persistence");
|
|
291
|
+
group.sample_size(20);
|
|
292
|
+
|
|
293
|
+
let n = 1_000;
|
|
294
|
+
group.throughput(Throughput::Elements(n as u64));
|
|
295
|
+
group.bench_function("two_invocations_mem", |b| {
|
|
296
|
+
b.to_async(&rt)
|
|
297
|
+
.iter(|| bench_persistence_per_invocation(SqliteBackend::Memory, n));
|
|
298
|
+
});
|
|
299
|
+
group.bench_function("two_invocations_vfs", |b| {
|
|
300
|
+
b.to_async(&rt)
|
|
301
|
+
.iter(|| bench_persistence_per_invocation(SqliteBackend::Vfs, n));
|
|
302
|
+
});
|
|
303
|
+
group.bench_function("memory_db_baseline", |b| {
|
|
304
|
+
b.to_async(&rt).iter(|| bench_in_memory_only(n));
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
group.finish();
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
fn bench_parallel(c: &mut Criterion) {
|
|
311
|
+
let rt = Runtime::new().unwrap();
|
|
312
|
+
let mut group = c.benchmark_group("sqlite_parallel");
|
|
313
|
+
group.sample_size(15);
|
|
314
|
+
|
|
315
|
+
let rows = 500;
|
|
316
|
+
for &sessions in SESSION_COUNTS {
|
|
317
|
+
group.throughput(Throughput::Elements((sessions * rows) as u64));
|
|
318
|
+
group.bench_with_input(BenchmarkId::new("mem", sessions), &sessions, |b, &s| {
|
|
319
|
+
b.to_async(&rt)
|
|
320
|
+
.iter(|| bench_parallel_sessions(s, rows, SqliteBackend::Memory));
|
|
321
|
+
});
|
|
322
|
+
group.bench_with_input(BenchmarkId::new("vfs", sessions), &sessions, |b, &s| {
|
|
323
|
+
b.to_async(&rt)
|
|
324
|
+
.iter(|| bench_parallel_sessions(s, rows, SqliteBackend::Vfs));
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
group.finish();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// ---------------------------------------------------------------------------
|
|
332
|
+
// Smoke-test harness — runs as part of `cargo test --features sqlite` so a
|
|
333
|
+
// regression in the benched code path breaks the build, not just a silent
|
|
334
|
+
// 0ns measurement.
|
|
335
|
+
// ---------------------------------------------------------------------------
|
|
336
|
+
|
|
337
|
+
#[test]
|
|
338
|
+
fn verify_insert_and_count() {
|
|
339
|
+
let rt = Runtime::new().unwrap();
|
|
340
|
+
rt.block_on(async {
|
|
341
|
+
let mut bash = make_bash(SqliteBackend::Memory, None);
|
|
342
|
+
let setup = seed_kv_sql(50).replace('"', "\\\"");
|
|
343
|
+
let r = bash
|
|
344
|
+
.exec(&format!(
|
|
345
|
+
"sqlite /tmp/v.sqlite \"{setup}; SELECT count(*) FROM kv\""
|
|
346
|
+
))
|
|
347
|
+
.await
|
|
348
|
+
.unwrap();
|
|
349
|
+
assert_eq!(r.exit_code, 0, "stderr={}", r.stderr);
|
|
350
|
+
assert_eq!(r.stdout.trim(), "50");
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
#[test]
|
|
355
|
+
fn verify_aggregate_groups() {
|
|
356
|
+
let rt = Runtime::new().unwrap();
|
|
357
|
+
rt.block_on(async {
|
|
358
|
+
let mut bash = make_bash(SqliteBackend::Memory, None);
|
|
359
|
+
let setup = seed_kv_sql(100).replace('"', "\\\"");
|
|
360
|
+
let r = bash
|
|
361
|
+
.exec(&format!(
|
|
362
|
+
"sqlite -header /tmp/v.sqlite \"{setup}; SELECT count(DISTINCT v % 10) FROM kv\""
|
|
363
|
+
))
|
|
364
|
+
.await
|
|
365
|
+
.unwrap();
|
|
366
|
+
assert_eq!(r.exit_code, 0, "stderr={}", r.stderr);
|
|
367
|
+
// 10 buckets max — the exact count depends on the v distribution.
|
|
368
|
+
let count: i64 = r.stdout.lines().last().unwrap().trim().parse().unwrap();
|
|
369
|
+
assert!(
|
|
370
|
+
(1..=10).contains(&count),
|
|
371
|
+
"unexpected bucket count: {count}"
|
|
372
|
+
);
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
#[test]
|
|
377
|
+
fn verify_index_lookup_matches_scan() {
|
|
378
|
+
let rt = Runtime::new().unwrap();
|
|
379
|
+
rt.block_on(async {
|
|
380
|
+
let mut bash = make_bash(SqliteBackend::Memory, None);
|
|
381
|
+
let setup = seed_kv_sql(200).replace('"', "\\\"");
|
|
382
|
+
let r = bash
|
|
383
|
+
.exec(&format!(
|
|
384
|
+
"sqlite /tmp/v.sqlite \"{setup}; CREATE INDEX i ON kv(k); SELECT v FROM kv WHERE k='key42'\""
|
|
385
|
+
))
|
|
386
|
+
.await
|
|
387
|
+
.unwrap();
|
|
388
|
+
assert_eq!(r.exit_code, 0, "stderr={}", r.stderr);
|
|
389
|
+
// 42 * 7 % 113 = 294 % 113 = 68.
|
|
390
|
+
assert_eq!(r.stdout.trim(), "68");
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
#[test]
|
|
395
|
+
fn verify_persistence_across_invocations() {
|
|
396
|
+
let rt = Runtime::new().unwrap();
|
|
397
|
+
rt.block_on(async {
|
|
398
|
+
let fs: Arc<dyn FileSystem> = Arc::new(InMemoryFs::new());
|
|
399
|
+
let mut bash = make_bash(SqliteBackend::Memory, Some(Arc::clone(&fs)));
|
|
400
|
+
let setup = seed_kv_sql(25).replace('"', "\\\"");
|
|
401
|
+
let r1 = bash
|
|
402
|
+
.exec(&format!("sqlite /tmp/persist.sqlite \"{setup}\""))
|
|
403
|
+
.await
|
|
404
|
+
.unwrap();
|
|
405
|
+
assert_eq!(r1.exit_code, 0, "stderr={}", r1.stderr);
|
|
406
|
+
let r2 = bash
|
|
407
|
+
.exec("sqlite /tmp/persist.sqlite 'SELECT count(*) FROM kv'")
|
|
408
|
+
.await
|
|
409
|
+
.unwrap();
|
|
410
|
+
assert_eq!(r2.exit_code, 0, "stderr={}", r2.stderr);
|
|
411
|
+
assert_eq!(r2.stdout.trim(), "25");
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
criterion_group!(
|
|
416
|
+
benches,
|
|
417
|
+
bench_crud,
|
|
418
|
+
bench_indexing,
|
|
419
|
+
bench_queries,
|
|
420
|
+
bench_output_modes,
|
|
421
|
+
bench_persistence,
|
|
422
|
+
bench_parallel,
|
|
423
|
+
);
|
|
424
|
+
criterion_main!(benches);
|
|
@@ -7,6 +7,7 @@ virtual filesystem.
|
|
|
7
7
|
|
|
8
8
|
**See also:**
|
|
9
9
|
- [API Documentation](https://docs.rs/bashkit) - Full API reference
|
|
10
|
+
- [Clap Builtins](../../../docs/clap-builtins.md) - Derive parser structs for custom builtin args
|
|
10
11
|
- [Hooks](./hooks.md) - Interceptor hooks for the execution pipeline
|
|
11
12
|
- [Compatibility Reference](./compatibility.md) - Supported bash features
|
|
12
13
|
- [Threat Model](./threat-model.md) - Security considerations
|
|
@@ -113,6 +114,39 @@ let result = bash
|
|
|
113
114
|
assert_eq!(result.stdout, "req-123\n");
|
|
114
115
|
```
|
|
115
116
|
|
|
117
|
+
## Extensions
|
|
118
|
+
|
|
119
|
+
Use an `Extension` when one capability contributes multiple builtins.
|
|
120
|
+
|
|
121
|
+
```rust,ignore
|
|
122
|
+
use bashkit::{Bash, Builtin, BuiltinContext, ExecResult, Extension, async_trait};
|
|
123
|
+
|
|
124
|
+
struct Hello;
|
|
125
|
+
|
|
126
|
+
#[async_trait]
|
|
127
|
+
impl Builtin for Hello {
|
|
128
|
+
async fn execute(&self, _ctx: BuiltinContext<'_>) -> bashkit::Result<ExecResult> {
|
|
129
|
+
Ok(ExecResult::ok("hello\n".to_string()))
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
struct MyExtension;
|
|
134
|
+
|
|
135
|
+
impl Extension for MyExtension {
|
|
136
|
+
fn builtins(&self) -> Vec<(String, Box<dyn Builtin>)> {
|
|
137
|
+
vec![("hello".to_string(), Box::new(Hello))]
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
let mut bash = Bash::builder().extension(MyExtension).build();
|
|
142
|
+
let result = bash.exec("hello").await?;
|
|
143
|
+
assert_eq!(result.stdout, "hello\n");
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The same extension can be added to `BashTool::builder().extension(...)`.
|
|
147
|
+
`TypeScriptExtension` uses this model to register the embedded
|
|
148
|
+
TypeScript/JavaScript builtins.
|
|
149
|
+
|
|
116
150
|
### Arguments
|
|
117
151
|
|
|
118
152
|
Arguments are passed as a slice of strings, excluding the command name itself:
|
|
@@ -122,6 +156,11 @@ Arguments are passed as a slice of strings, excluding the command name itself:
|
|
|
122
156
|
let first_arg = ctx.args.first().map(|s| s.as_str()).unwrap_or("default");
|
|
123
157
|
```
|
|
124
158
|
|
|
159
|
+
For custom builtins with richer flags, options, or subcommands, enable the
|
|
160
|
+
default `clap-builtins` feature and implement `ClapBuiltin` with a
|
|
161
|
+
`#[derive(clap::Parser)]` argument type. See the `clap_builtins_guide` rustdoc
|
|
162
|
+
module for tested examples.
|
|
163
|
+
|
|
125
164
|
### Environment Variables
|
|
126
165
|
|
|
127
166
|
Read-only access to environment variables set via `BashBuilder::env()` or `export`:
|
|
@@ -580,6 +580,43 @@ Monty runs directly in the host process. Resource limits (memory, allocations,
|
|
|
580
580
|
time, recursion) are enforced by Monty's own runtime. All VFS operations are
|
|
581
581
|
bridged through the host process — Python code never touches the real filesystem.
|
|
582
582
|
|
|
583
|
+
### SQLite Security (TM-SQL-*)
|
|
584
|
+
|
|
585
|
+
The `sqlite`/`sqlite3` builtins embed Turso's pure-Rust SQLite-compatible engine.
|
|
586
|
+
This is experimental and **opt-in for now**. Library callers must enable the
|
|
587
|
+
`sqlite` feature, register the builtin with `.sqlite()` or `.sqlite_with_limits(...)`,
|
|
588
|
+
and set `BASHKIT_ALLOW_INPROCESS_SQLITE=1` before SQL executes. Without the
|
|
589
|
+
runtime opt-in, registered commands fail closed with a disabled error.
|
|
590
|
+
|
|
591
|
+
SQLite database files live in Bashkit's virtual filesystem, or in `:memory:`.
|
|
592
|
+
The default backend loads and flushes database bytes through the VFS at command
|
|
593
|
+
boundaries; the VFS backend implements Turso's IO trait over `Arc<dyn FileSystem>`.
|
|
594
|
+
Both paths are tested so SQL cannot intentionally read host files.
|
|
595
|
+
|
|
596
|
+
| Threat | Attack Example | Mitigation | Status |
|
|
597
|
+
|--------|---------------|------------|--------|
|
|
598
|
+
| BETA engine execution (TM-SQL-001) | `sqlite :memory: 'SELECT 1'` without opt-in | Feature + builder registration + runtime opt-in gate | MITIGATED |
|
|
599
|
+
| Host FS escape (TM-SQL-002) | Open `/etc/passwd` as a database | All paths resolve through Bashkit VFS | MITIGATED |
|
|
600
|
+
| Large SQL input (TM-SQL-003) | Multi-MB SQL script | `max_script_bytes` | MITIGATED |
|
|
601
|
+
| Huge result set (TM-SQL-004) | Query returns millions of rows | `max_rows_per_query` | MITIGATED |
|
|
602
|
+
| Huge DB file (TM-SQL-005) | Load or grow oversized `.sqlite` file | `max_db_bytes` on both backends | MITIGATED |
|
|
603
|
+
| Wall-clock burn (TM-SQL-005a) | Expensive query/CTE | Per-step deadline + interrupt | MITIGATED |
|
|
604
|
+
| Statement flood (TM-SQL-005b) | Millions of `;` statements | `max_statements` | MITIGATED |
|
|
605
|
+
| Binary truncation (TM-SQL-006) | BLOB contains NUL bytes | `Vec<u8>` values, tested round-trip | MITIGATED |
|
|
606
|
+
| CSV injection/escape failure (TM-SQL-007) | Blob/text contains separator | RFC-4180 quoting | MITIGATED |
|
|
607
|
+
| Recursive `.read` (TM-SQL-008) | Script `.read`s itself | `MAX_DOT_READ_DEPTH` | MITIGATED |
|
|
608
|
+
| Cross-database access (TM-SQL-009) | `ATTACH DATABASE '/tmp/x'` | `ATTACH`/`DETACH` rejected by policy | MITIGATED |
|
|
609
|
+
| Dangerous PRAGMAs (TM-SQL-010) | `PRAGMA main."cache_size"=...` | Default `pragma_deny` list, including quoted/schema-qualified names | MITIGATED |
|
|
610
|
+
| Host path errors (TM-SQL-011) | Upstream error includes `/rustc/...` | Sanitizer strips host path annotations | MITIGATED |
|
|
611
|
+
|
|
612
|
+
Black-box coverage drives `Bash::exec` through
|
|
613
|
+
`tests/sqlite_integration_tests.rs` and `tests/sqlite_security_tests.rs`.
|
|
614
|
+
White-box coverage in `builtins/sqlite/tests.rs` exercises parser, policy,
|
|
615
|
+
formatter, sanitizer, backend, and dot-command internals directly.
|
|
616
|
+
Exploratory probing found and fixed two policy/limit gaps: quoted
|
|
617
|
+
schema-qualified PRAGMAs bypassed the deny list, and VFS-backed databases did
|
|
618
|
+
not honor custom `max_db_bytes` while growing.
|
|
619
|
+
|
|
583
620
|
### Git Security (TM-GIT-*)
|
|
584
621
|
|
|
585
622
|
Optional virtual git operations via the `git` feature. All operations are confined
|
|
@@ -744,6 +781,7 @@ All threats use stable IDs in the format `TM-<CATEGORY>-<NUMBER>`:
|
|
|
744
781
|
| TM-LOG | Logging Security |
|
|
745
782
|
| TM-GIT | Git Security |
|
|
746
783
|
| TM-PY | Python/Monty Security |
|
|
784
|
+
| TM-SQL | SQLite Security |
|
|
747
785
|
| TM-UNI | Unicode Security |
|
|
748
786
|
|
|
749
787
|
Full threat analysis: [`specs/threat-model.md`][spec]
|