feat: initial built-in sandboxing support powered by Docker sbx

This commit is contained in:
2026-06-17 14:11:04 -06:00
parent ee100eef96
commit 587df087ed
7 changed files with 783 additions and 3 deletions
+2
View File
@@ -143,6 +143,8 @@ const MEMORY_DIR_NAME: &str = "memory";
const MEMORY_INDEX_FILE_NAME: &str = "MEMORY.md";
const WORKSPACE_MEMORY_FILE_NAME: &str = "COYOTE.md";
const WORKSPACE_MEMORY_DIR_NAME: &str = ".coyote";
const SBX_KIT_DIR_NAME: &str = "sbx-kit";
const SBX_KIT_HASH_FILE: &str = "kit.sha256";
const GIT_DIR_NAME: &str = ".git";
const GITIGNORE_FILE_NAME: &str = ".gitignore";
const DEFAULT_VISIBLE_TOOLS: [&str; 18] = [
+38 -2
View File
@@ -3,8 +3,8 @@ use super::{
AGENT_GRAPH_FILE_NAME, AGENTS_DIR_NAME, BASH_PROMPT_UTILS_FILE_NAME, CONFIG_FILE_NAME,
ENV_FILE_NAME, FUNCTIONS_BIN_DIR_NAME, FUNCTIONS_DIR_NAME, GLOBAL_TOOLS_DIR_NAME,
GLOBAL_TOOLS_UTILS_DIR_NAME, MACROS_DIR_NAME, MCP_FILE_NAME, MEMORY_DIR_NAME,
MEMORY_INDEX_FILE_NAME, ModelsOverride, RAGS_DIR_NAME, ROLES_DIR_NAME, SKILLS_DIR_NAME,
WORKSPACE_MEMORY_DIR_NAME,
MEMORY_INDEX_FILE_NAME, ModelsOverride, RAGS_DIR_NAME, ROLES_DIR_NAME, SBX_KIT_DIR_NAME,
SBX_KIT_HASH_FILE, SKILLS_DIR_NAME, WORKSPACE_MEMORY_DIR_NAME,
};
use crate::client::ProviderModels;
use crate::utils::{get_env_name, list_file_names, normalize_env_name};
@@ -36,6 +36,10 @@ pub fn cache_path() -> PathBuf {
base_dir.join(env!("CARGO_CRATE_NAME"))
}
pub fn sandbox_kit_override() -> Option<PathBuf> {
env::var_os(get_env_name("sandbox_kit")).map(PathBuf::from)
}
pub fn oauth_tokens_path() -> PathBuf {
cache_path().join("oauth")
}
@@ -48,6 +52,14 @@ pub fn log_path() -> PathBuf {
cache_path().join(format!("{}.log", env!("CARGO_CRATE_NAME")))
}
pub fn sbx_kit_dir() -> PathBuf {
cache_path().join(SBX_KIT_DIR_NAME)
}
pub fn sbx_kit_hash_file() -> PathBuf {
sbx_kit_dir().join(SBX_KIT_HASH_FILE)
}
pub fn config_file() -> PathBuf {
match env::var(get_env_name("config_file")) {
Ok(value) => PathBuf::from(value),
@@ -365,6 +377,30 @@ mod tests {
}
}
#[test]
fn sandbox_kit_override_reflects_env_var_state() {
let env_name = get_env_name("sandbox_kit");
let prev = env::var_os(&env_name);
unsafe {
env::remove_var(&env_name);
}
assert_eq!(sandbox_kit_override(), None);
let probe = PathBuf::from("/tmp/coyote-sandbox-kit-probe");
unsafe {
env::set_var(&env_name, &probe);
}
assert_eq!(sandbox_kit_override(), Some(probe));
unsafe {
match prev {
Some(v) => env::set_var(&env_name, v),
None => env::remove_var(&env_name),
}
}
}
#[test]
fn list_skills_skips_invalid_directory_names() {
let unique = time::SystemTime::now()