cargo.build: a persistent build cache shared by all worlds

- The cargo target folder is <cache>/cargo-target, next to Wasmtime's
  cache, which moves to <cache>/wasmtime: Wasmtime's cleanup worker
  deletes unknown entries in its folder, also Cargo's artifacts.
- Builds use the SDK at <cache>/sdk/<content hash>/, so cargo reuses
  the compiled SDK in every world. /plugins/cargo/sdk/ stays for agents.
- Tests run in the release profile and share compiled crates with the
  release build.
- The cargo and cli tests use a persistent cache in CARGO_TARGET_TMPDIR:
  warm, the cargo suite takes 11 s (was 235 s) and the cli suite 6 s
  (was 149 s).
- nix flake check runs ignored stress tests. AGENTS.md: rules for fast
  tests.
This commit is contained in:
2026-10-23 08:05:15 +01:00
parent a090e1fd57
commit 93f092e02b
11 changed files with 155 additions and 48 deletions
+12 -4
View File
@@ -79,7 +79,7 @@ fn setting(var: &str, question: &str, default: Option<&str>) -> Result<String> {
}
}
/// Creates a configured world and builds its embedded agent through the standalone builder.
async fn init(dir: &Path) -> Result<()> {
async fn init(dir: &Path, cache: Option<&Path>) -> Result<()> {
let api = setting("SAUSAGE_API", "API shape", Some("openai-responses"))?;
if api != "openai-responses" && api != "anthropic-messages" {
bail!("unknown API shape {api:?}");
@@ -105,7 +105,15 @@ async fn init(dir: &Path) -> Result<()> {
&json!({"api":api,"base_url":base_url.trim_end_matches('/'),"model":model,"token":token}),
)?,
)?;
let builder = sausage::cargo::Cargo::new(world.clone())?;
let cache = cache.map(Path::to_path_buf).unwrap_or_else(|| {
let base = std::env::var_os("XDG_CACHE_HOME")
.map(PathBuf::from)
.unwrap_or_else(|| {
PathBuf::from(std::env::var_os("HOME").unwrap_or_default()).join(".cache")
});
base.join("sausage")
});
let builder = sausage::cargo::Cargo::new(world.clone(), &cache)?;
let source = world.plugin_dir("agent").join("source");
std::fs::create_dir_all(source.join("src"))?;
AGENT.extract(source.join("src"))?;
@@ -133,7 +141,7 @@ async fn main() -> Result<std::process::ExitCode> {
None => {
let dir = PathBuf::from("world");
if !dir.join("config/boot.json").is_file() {
init(&dir).await?;
init(&dir, cli.cache_dir.as_deref()).await?;
}
Cmd::Run { dir }
}
@@ -144,7 +152,7 @@ async fn main() -> Result<std::process::ExitCode> {
return Ok(std::process::ExitCode::FAILURE);
}
}
Cmd::Init { dir } => init(&dir).await?,
Cmd::Init { dir } => init(&dir, cli.cache_dir.as_deref()).await?,
Cmd::Run { dir } => {
let mut term =
tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())?;