bundle: seed agent definitions and skills in the source snapshot

This commit is contained in:
2026-11-08 02:51:38 +00:00
parent de351919dd
commit 1b6cac325c
2 changed files with 91 additions and 8 deletions
+89 -6
View File
@@ -1,14 +1,15 @@
//! P1 integration: independent bundle copies and real shell calls from the durable harness.
//! P1 integration: bundle contents, source commits, extension loading, and real shell calls.
use sausage::{harness::run_module, world::World};
use sausage_vfs::Open;
use std::path::PathBuf;
#[tokio::test(flavor = "current_thread")]
async fn bundle_copy_and_real_shell() -> anyhow::Result<()> {
fn bundle() -> anyhow::Result<PathBuf> {
let repo = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..");
let bundle = PathBuf::from(std::env::var("CARGO_TARGET_DIR").unwrap()).join("bundle");
if !bundle.join("bin/sh.wasm").exists() {
let _guard = crate::common::BUILD.lock().unwrap();
let bundle = crate::common::target_dir().join("bundle");
let _guard = crate::common::BUILD.lock().unwrap();
if !bundle.join("bin/sh.wasm").exists()
|| !bundle.join("src/sausage/agents/models.json").exists()
{
assert!(
std::process::Command::new("nu")
.arg(repo.join("userland/bundle.nu"))
@@ -17,9 +18,47 @@ async fn bundle_copy_and_real_shell() -> anyhow::Result<()> {
.success()
);
}
Ok(bundle)
}
#[tokio::test(flavor = "current_thread")]
async fn bundle_copy_and_real_shell() -> anyhow::Result<()> {
let repo = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..");
let bundle = bundle()?;
let dir = tempfile::tempdir()?;
let world = World::open_with_userland(dir.path(), Some(&bundle))?;
assert!(world.root.stat("/bin/sh.wasm", true).await?.size > 0);
let snapshot = dir.path().join("world/src/sausage");
for path in [
"agents/models.json",
"agents/ultimate.md",
"skills/README.md",
"extensions/README.md",
] {
assert!(snapshot.join(path).is_file(), "missing bundled {path}");
}
let git = |path: &std::path::Path, args: &[&str]| -> anyhow::Result<String> {
let output = std::process::Command::new("git")
.arg("-C")
.arg(path)
.args(args)
.output()?;
anyhow::ensure!(
output.status.success(),
"git {args:?}: {}",
String::from_utf8_lossy(&output.stderr)
);
Ok(String::from_utf8(output.stdout)?.trim().to_owned())
};
let message = git(&snapshot, &["log", "-1", "--format=%s"])?;
let revision = message.strip_prefix("Bundle source ").unwrap();
for path in ["agents", "skills", "extensions"] {
assert_eq!(
git(&snapshot, &["rev-parse", &format!("HEAD:{path}")])?,
git(&repo, &["rev-parse", &format!("{revision}:{path}")])?,
"bundled {path} must match the source commit"
);
}
use std::os::unix::fs::MetadataExt;
for entry in std::fs::read_dir(dir.path().join("world/bin"))? {
let entry = entry?;
@@ -203,3 +242,47 @@ async fn bundle_copy_and_real_shell() -> anyhow::Result<()> {
assert!(world.root.stat("/bin/sh", true).await.is_err());
Ok(())
}
#[tokio::test(flavor = "current_thread")]
async fn bundled_extensions_load() -> anyhow::Result<()> {
let bundle = bundle()?;
let dir = tempfile::tempdir()?;
let world = World::open_with_userland(dir.path(), Some(&bundle))?;
let root = world.root.clone();
let exec = sausage::process::exec(World {
root: world.root.clone(),
host_dir: world.host_dir.clone(),
processes: world.processes.clone(),
})?;
// Use the compiled production loader without the console entrypoint or model proxy.
let (library, _) = include_str!("../../js/bundle.js")
.split_once("// main.ts")
.expect("console bundle entrypoint");
let source = format!(
r#"{library}
const bundleModels = createModels();
const bundleRegistry = createRegistry();
bundleRegistry.install(CodingTools2);
bundleRegistry.install(CredentialRequests);
const bundleStorage = await openStorage(globalThis.storagePath);
const bundleHarness = await Harness.open(bundleStorage, {{
models: bundleModels, registry: bundleRegistry,
settings: {{ get extensions() {{ return bundleRegistry.snapshot().installed(); }} }}
}}, BACKGROUND_CONTEXT);
await bundleHarness.root(BACKGROUND_CONTEXT);
const bundleLoader = await loadExtensions(bundleHarness, bundleRegistry, bundleStorage,
bundleModels, BACKGROUND_CONTEXT, [CodingTools2, CredentialRequests]);
if (bundleLoader.state().error) throw new Error(bundleLoader.state().error);
await bundleLoader.close();
await bundleHarness.close(BACKGROUND_CONTEXT);
"#
);
run_module(world, exec, &source).await?;
let status = root.open("/proc/extensions", Open::default()).await?;
let status: serde_json::Value = serde_json::from_slice(&status.read(0, 65536).await?)?;
let commit =
std::fs::read_to_string(dir.path().join("world/src/sausage/.git/refs/heads/main"))?;
assert_eq!(status["good"].as_str(), Some(commit.trim()), "{status}");
assert!(status["error"].is_null(), "{status}");
Ok(())
}
+2 -2
View File
@@ -41,14 +41,14 @@ def main [destination?: path] {
if ($snapshot | path exists) { rm --recursive --force $snapshot }
mkdir $snapshot
let archive = ($destination | path join source.tar)
^git -C $repo archive --output $archive HEAD host vfs userland extensions Cargo.toml Cargo.lock flake.nix flake.lock README.md AGENTS.md .gitignore
^git -C $repo archive --output $archive HEAD host vfs userland agents skills extensions Cargo.toml Cargo.lock flake.nix flake.lock README.md AGENTS.md .gitignore
if $env.LAST_EXIT_CODE != 0 { error make {msg: 'source archive failed'} }
^tar -xf $archive -C $snapshot
if $env.LAST_EXIT_CODE != 0 { error make {msg: 'source extraction failed'} }
rm $archive
^git -C $snapshot init --quiet --initial-branch=main
if $env.LAST_EXIT_CODE != 0 { error make {msg: 'source git init failed'} }
^git -C $snapshot add host vfs userland extensions Cargo.toml Cargo.lock flake.nix flake.lock README.md AGENTS.md .gitignore
^git -C $snapshot add host vfs userland agents skills extensions Cargo.toml Cargo.lock flake.nix flake.lock README.md AGENTS.md .gitignore
if $env.LAST_EXIT_CODE != 0 { error make {msg: 'source git add failed'} }
with-env {
GIT_AUTHOR_NAME: 'Sausage', GIT_AUTHOR_EMAIL: 'sausage@localhost',