mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-08 03:10:26 +00:00
Fabro advertised Bash while its three backends implemented three different contracts: Daytona evaluated commands through `sh`, and Docker's streaming, stdio, and setup paths used a login shell. Bash-only syntax silently misbehaved depending on provider and code path, and login profiles could change PATH and command behavior per image. Make `bash -c` the enforced interpreter for every command string the Unix sandbox API accepts, on every production backend and through both buffered and streaming execution. This selects the interpreter only — no `errexit`, no `pipefail`, no login mode — so `false | true` still succeeds and a workflow that wants other semantics writes them into its own command. Local resolves `bash` through the worker's PATH (NixOS has no /bin/bash) and reuses that one executable across all three command paths. Docker and Daytona require /bin/bash with no `sh` fallback. Fresh initialization and resume/start now verify Bash through a shared marker-validating probe before reporting the sandbox usable, so a missing or non-Bash interpreter fails at the lifecycle boundary with provider-specific remediation instead of on the first command. The probe also rejects Bash in POSIX mode, which an image whose `bash` is really `sh` would otherwise pass. Sandbox MCP scripts and the detached launch wrapper move under the same contract; host-side stdio MCP scripts, hooks, and interactive terminals are separate executors and keep their existing `sh` behavior. The `shell` tool's name and JSON schema are unchanged across providers; only its prose now identifies `command` as Bash source. BREAKING CHANGE: sandbox commands no longer load login-shell profiles, so environment set in /etc/profile.d/*.sh, ~/.bash_profile, or nvm/rbenv/sdkman initializers is gone. Move those exports into the Dockerfile's ENV or the Daytona snapshot image. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
70 lines
1.9 KiB
TOML
70 lines
1.9 KiB
TOML
[package]
|
|
name = "fabro-agent"
|
|
edition.workspace = true
|
|
version.workspace = true
|
|
publish = false
|
|
license.workspace = true
|
|
description = "A programmable agentic loop for coding agents"
|
|
repository = "https://github.com/brynary/arc"
|
|
readme = "README.md"
|
|
keywords = ["llm", "ai", "agent", "coding"]
|
|
categories = ["api-bindings"]
|
|
|
|
[features]
|
|
default = ["docker"]
|
|
docker = ["fabro-sandbox/docker"]
|
|
quarantine = []
|
|
|
|
[lib]
|
|
doctest = false
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
[dependencies]
|
|
clap.workspace = true
|
|
anyhow.workspace = true
|
|
fabro-auth = { path = "../../foundation/fabro-auth" }
|
|
fabro-config = { path = "../../foundation/fabro-config", features = ["clap"] }
|
|
fabro-types = { path = "../../foundation/fabro-types", features = ["clap"] }
|
|
fabro-llm = { path = "../fabro-llm" }
|
|
fabro-model = { path = "../../foundation/fabro-model" }
|
|
fabro-mcp = { path = "../fabro-mcp" }
|
|
fabro-sandbox = { path = "../fabro-sandbox" }
|
|
fabro-static.workspace = true
|
|
fabro-template = { path = "../../foundation/fabro-template" }
|
|
fabro-util = { path = "../../foundation/fabro-util" }
|
|
fabro-vault = { path = "../../foundation/fabro-vault" }
|
|
fabro-http.workspace = true
|
|
thiserror.workspace = true
|
|
serde.workspace = true
|
|
serde_json.workspace = true
|
|
strum.workspace = true
|
|
tokio.workspace = true
|
|
uuid.workspace = true
|
|
futures.workspace = true
|
|
async-trait.workspace = true
|
|
jsonschema.workspace = true
|
|
chrono.workspace = true
|
|
tokio-util.workspace = true
|
|
tracing.workspace = true
|
|
toml.workspace = true
|
|
dirs = "6"
|
|
glob = "0.3"
|
|
sha2.workspace = true
|
|
shell-escape = "0.1"
|
|
htmd = "0.5"
|
|
|
|
[target.'cfg(unix)'.dependencies]
|
|
libc = "0.2"
|
|
|
|
[dev-dependencies]
|
|
insta.workspace = true
|
|
tokio = { workspace = true, features = ["test-util", "macros"] }
|
|
tempfile = "3"
|
|
paste = "1"
|
|
shlex = "1"
|
|
fabro-sandbox = { path = "../fabro-sandbox", features = ["test-support"] }
|
|
fabro-macros = { path = "../../foundation/fabro-macros" }
|
|
fabro-test = { workspace = true }
|
|
tracing-subscriber.workspace = true
|