beam_sandbox
beam_sandbox confines file access to one directory and adds git on top through libgit2 (vendored,
so no system git is needed).
beam_sandbox = { path = "../riverbeam/crates/beam_sandbox" }
SandboxRoot
| Method | Behaviour |
|---|---|
new(root) | Creates the directory if needed and canonicalizes it |
path() | The root |
resolve(rel) | A path inside the root; rejects absolute paths, NUL bytes, .., and anything that escapes (BEM-300 to BEM-305) |
list_tree(rel) | Sorted file list, without .git |
read_file(rel), write_file(rel, body) | write_file creates parent directories |
WorkingTree
WorkingTree::new(sandbox, protected_refs) adds git:
| Method | Behaviour |
|---|---|
init() | Create the repository; running it again on an existing one is safe |
status(), diff(), log(limit), current_branch() | Read state |
add(rel) | Stage a path; "" or "." stages everything |
commit(message) | Commits the index as beam-agent <beam@localhost>; returns the commit id |
checkout_branch(name, create) | Switch branches |
add_origin(url) | Set the origin remote |
push(refname) | Push the current or named branch to origin; protected refs fail with BEM-328, a missing origin with BEM-329 |
use beam_sandbox::{SandboxRoot, WorkingTree};
let tree = WorkingTree::new(SandboxRoot::new("/srv/agent-work/docs")?, vec!["main".into(), "master".into()]);
tree.init()?;
tree.sandbox().write_file("README.md", "hi\n")?;
tree.add("README.md")?;
let commit_id = tree.commit("init")?;
Current limitations
pushsends no credentials, so remotes that require authentication fail withBEM-330. Local paths and bare repositories work.checkout_branchdoes not check protected refs; onlypushdoes.initreturns agit2::Repository, sogit2appears in the public API.