Merge branch 'v3' into v3-t85

This commit is contained in:
2026-11-11 22:51:01 +00:00
142 changed files with 110842 additions and 8097 deletions
+11 -9
View File
@@ -1,4 +1,4 @@
//! Native HTTP smoke test for host pages and the listener's CLI options.
//! Host pages remain reachable. World config replaces listener flags on the CLI.
use anyhow::Result;
use sausage::{
api::{Listener, Options},
@@ -44,14 +44,16 @@ fn listener_serves_host_pages() -> Result<()> {
.output()?;
assert!(help.status.success());
let help = std::str::from_utf8(&help.stdout)?;
for option in [
"--api-listen",
"127.0.0.1:8090",
"--api-rp-id",
"--api-origin",
"http://localhost:8090",
] {
assert!(help.contains(option));
for option in ["--api-listen", "--api-rp-id", "--api-origin"] {
assert!(!help.contains(option));
}
let missing = dir.path().join("missing-world");
let run = std::process::Command::new(env!("CARGO_BIN_EXE_sausage"))
.arg("run")
.arg(&missing)
.output()?;
assert!(!run.status.success());
assert!(std::str::from_utf8(&run.stderr)?.contains("sausage init"));
assert!(!missing.join("world").exists());
Ok(())
}
+6 -4
View File
@@ -79,10 +79,12 @@ fn setup(directory: &Path) -> Result<()> {
&Path::new(env!("CARGO_MANIFEST_DIR")).join("../extensions"),
&repo.join("extensions"),
)?;
std::fs::create_dir_all(repo.join("agents"))?;
std::fs::write(
repo.join("agents/models.json"),
r#"{"default":{"model":"faux/faux-1"}}"#,
crate::common::write_config(
directory,
"standing",
serde_json::json!([
{"name":"standing","description":"Primary","model":"faux/faux-1","prompt":"Primary agent"}
]),
)?;
ensure!(
Command::new("git")
+17 -1
View File
@@ -8,6 +8,22 @@ use std::{
};
pub static BUILD: Mutex<()> = Mutex::new(());
/// Keep the real shared prompt in every roster fixture, with an ephemeral approval port.
pub fn write_config(dir: &Path, standing: &str, roster: serde_json::Value) -> anyhow::Result<()> {
let mut config: serde_json::Value =
serde_yaml_ng::from_str(include_str!("../../../config/config.yaml"))?;
config["standing"] = serde_json::json!(standing);
config["roster"] = roster;
config["listener"]["address"] = serde_json::json!("127.0.0.1:0");
let folder = dir.join("world/etc/sausage");
std::fs::create_dir_all(&folder)?;
std::fs::write(
folder.join("config.yaml"),
serde_yaml_ng::to_string(&config)?,
)?;
Ok(())
}
pub fn copy_tree(source: &Path, destination: &Path) -> anyhow::Result<()> {
std::fs::create_dir_all(destination)?;
for entry in std::fs::read_dir(source)? {
@@ -39,7 +55,7 @@ pub fn bundle_key(repo: &Path) -> anyhow::Result<String> {
"host",
"vfs",
"userland",
"agents",
"config",
"skills",
"extensions",
"Cargo.toml",
+67 -13
View File
@@ -44,6 +44,70 @@ fn write(root: &Path, path: &str, text: &str) -> anyhow::Result<()> {
std::fs::write(path, text)?;
Ok(())
}
#[tokio::test(flavor = "current_thread")]
async fn init_seeds_config_tools_and_one_source_commit() -> anyhow::Result<()> {
let dir = tempfile::tempdir()?;
let bundle = dir.path().join("bundle");
let target = crate::common::build_git();
std::fs::create_dir_all(bundle.join("bin"))?;
std::fs::copy(
target.join("wasm32-wasip2/release/git.wasm"),
bundle.join("bin/git.wasm"),
)?;
write(&bundle, "src/sausage/README.md", "World source")?;
write(
&bundle,
"etc/sausage/config.yaml",
include_str!("../../../config/config.yaml"),
)?;
let destination = dir.path().join("new-world");
let initialized = std::process::Command::new(env!("CARGO_BIN_EXE_sausage"))
.arg("init")
.arg(&destination)
.arg("--userland")
.arg(&bundle)
.env("PI_PROXY_BASE_URL", "https://proxy.test")
.env("PI_PROXY_API_KEY", "fixture-key")
.stdin(std::process::Stdio::null())
.output()?;
assert!(
initialized.status.success(),
"{}",
String::from_utf8_lossy(&initialized.stderr)
);
let world = World::open(&destination)?;
assert!(destination.join("world/bin/git").exists());
let config = sausage::harness::config::Config::read(&world.root).await?;
assert_eq!(config.listener.origin, "http://localhost:8090");
assert_eq!(config.proxy.base_url, "https://proxy.test");
assert_eq!(config.proxy.api_key, "fixture-key");
let source = destination.join("world/src/sausage");
for (args, expected) in [
(vec!["symbolic-ref", "HEAD"], "refs/heads/main"),
(vec!["rev-list", "--count", "HEAD"], "1"),
] {
let result = std::process::Command::new("git")
.args(args)
.current_dir(&source)
.output()?;
assert!(
result.status.success(),
"{}",
String::from_utf8_lossy(&result.stderr)
);
assert_eq!(String::from_utf8(result.stdout)?.trim(), expected);
}
assert!(
World::init(&destination, &bundle)
.await
.err()
.unwrap()
.to_string()
.contains("already exists")
);
Ok(())
}
#[tokio::test(flavor = "current_thread")]
async fn core_extensions() -> anyhow::Result<()> {
let repo = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap();
@@ -66,14 +130,9 @@ async fn core_extensions() -> anyhow::Result<()> {
)?;
}
write(
&source,
"agents/worker.md",
"---\nname: worker\ndescription: Worker\nfamily: fast\ntools: [read]\n---\nWorker body",
)?;
write(
&source,
"agents/models.json",
r#"{"default":{"model":"faux/faux-1"},"fast":{"model":"faux/faux-1","thinking":"low"}}"#,
&disk,
"etc/sausage/config.yaml",
include_str!("../../../config/config.yaml"),
)?;
write(
&source,
@@ -93,11 +152,6 @@ export default host=>{host.implement({name:'models.pin'},{pin:async()=>globalThi
write(&disk, "project/.git/HEAD", "ref: refs/heads/main")?;
write(&disk, "project/AGENTS.md", "Root instructions")?;
write(&disk, "project/sub/AGENTS.md", "Nested instructions")?;
write(
&disk,
"project/.sausage/agents/worker.md",
"---\nname: worker\naddTools: [write]\n---\nProject body",
)?;
write(
&disk,
"project/.sausage/skills/project/SKILL.md",
+17 -27
View File
@@ -50,33 +50,23 @@ fn prepare(dir: &Path) -> anyhow::Result<()> {
repo.join("extensions/probe/server.ts"),
"export default host => { globalThis.dreamHost=host; globalThis.dreamService=host.need({name:'dream'}); globalThis.dreamSubagents=host.need({name:'subagents'}); globalThis.dreamAutomations=host.need({name:'automations'}); return {name:'probe'}; }",
)?;
std::fs::create_dir_all(repo.join("agents"))?;
std::fs::write(
repo.join("agents/models.json"),
r#"{"default":{"model":"faux/faux-1"},"fast":{"model":"faux/faux-1"}}"#,
)?;
for role in ["ultimate", "coordinator", "worker", "reviewer"] {
let denial = if role == "worker" || role == "reviewer" {
"denyTools: [subagent]\n"
} else {
""
};
std::fs::write(
repo.join(format!("agents/{role}.md")),
format!(
"---\nname: {role}\ndescription: P3 {role}\nisolate: none\n{denial}{}---\nP3 role:{role}\n",
if role == "ultimate" {
"resident: true\n"
} else {
""
}
),
)?;
}
std::fs::copy(
source.join("agents/dream-pass.md"),
repo.join("agents/dream-pass.md"),
)?;
let mut roster: Vec<serde_json::Value> = ["standing", "coordinator", "worker", "reviewer"].into_iter().map(|role| serde_json::json!({
"name":role, "description":format!("P3 {role}"), "model":"faux/faux-1",
"isolate":"none", "resident":role == "standing", "prompt":format!("P3 role:{role}"),
"denyTools":if role == "worker" || role == "reviewer" {vec!["subagent"]} else {vec![]}
})).collect();
let defaults: serde_json::Value =
serde_yaml_ng::from_str(include_str!("../../../config/config.yaml"))?;
let mut pass = defaults["roster"]
.as_array()
.unwrap()
.iter()
.find(|entry| entry["name"] == "dream-pass")
.unwrap()
.clone();
pass["model"] = serde_json::json!("faux/faux-1");
roster.push(pass);
crate::common::write_config(dir, "standing", serde_json::json!(roster))?;
let demo = disk.join("src/demo");
std::fs::create_dir_all(&demo)?;
std::fs::write(demo.join("README.md"), "P3 demo\n")?;
+10 -4
View File
@@ -146,7 +146,7 @@ async fn proxy_child() -> anyhow::Result<()> {
};
let dir = std::path::Path::new(&dir);
let source = format!(
"globalThis.proxyOnly = true; const proxy = Deno.core.ops.op_model_proxy(); if (proxy.base_url !== 'https://proxy.invalid' || proxy.api_key !== 'faux-private-token') throw new Error('Wrong proxy item');\n{}",
"globalThis.proxyOnly = true; const proxy = await Deno.core.ops.op_model_proxy(); if (proxy.base_url !== 'https://proxy.invalid' || proxy.api_key !== 'faux-private-token') throw new Error('Wrong proxy config');\n{}",
include_str!("../../js/durable-test-bundle.js")
);
run_module(
@@ -158,7 +158,7 @@ async fn proxy_child() -> anyhow::Result<()> {
let error = run_module(
World::open(dir)?,
sausage::process::exec(World::open(dir)?)?,
"throw new Error(Deno.core.ops.op_model_proxy().api_key)",
"throw new Error((await Deno.core.ops.op_model_proxy()).api_key)",
)
.await
.unwrap_err();
@@ -168,8 +168,14 @@ async fn proxy_child() -> anyhow::Result<()> {
}
#[test]
fn proxy_bootstrap_once() -> anyhow::Result<()> {
fn proxy_config_ignores_environment() -> anyhow::Result<()> {
let dir = std::env::temp_dir().join(format!("sausage-durable-proxy-{}", std::process::id()));
let settings = dir.join("world/etc/sausage");
std::fs::create_dir_all(&settings)?;
std::fs::write(
settings.join("config.yaml"),
"proxy:\n base_url: https://proxy.invalid\n api_key: faux-private-token\n",
)?;
for start in 0..2 {
let status = std::process::Command::new(std::env::current_exe()?)
.args(["--exact", "durable::proxy_child", "--nocapture"])
@@ -199,7 +205,7 @@ fn proxy_bootstrap_once() -> anyhow::Result<()> {
.iter()
.filter(|i| i.name == "llm-proxy")
.count(),
1
0
);
for file in [
"host/cred.sqlite",
+31 -15
View File
@@ -26,21 +26,37 @@ fn prepare(dir: &Path) -> anyhow::Result<()> {
repo.join("extensions/probe/server.ts"),
"export default host => { globalThis.testHost = host; globalThis.subagentService = host.need({name:'subagents'}); globalThis.messageService = host.need({name:'messages'}); globalThis.lineageService = host.need({name:'lineage'}); host.implement({name:'conversations'}, {summaryModel: async () => globalThis.summaryRef, concludedIn: async () => new Set(), generatedTitle: async () => {}, setStanding: async () => {}, setAutomaticSummaries: async () => {}}); return {name:'probe'}; }",
)?;
std::fs::write(
repo.join("agents/models.json"),
r#"{"default":{"model":"faux/faux-1"}}"#,
)?;
std::fs::write(
repo.join("agents/scout.md"),
"---\nname: scout\ndescription: Search\nresident: true\ndenyTools: [subagent]\nisolate: none\n---\nScout instructions\n",
)?;
std::fs::write(
repo.join("agents/ultimate.md"),
"---\nname: ultimate\ndescription: Primary\nresident: true\nisolate: none\n---\nPrimary agent\n",
)?;
std::fs::write(
repo.join("agents/coordinator.md"),
"---\nname: coordinator\ndescription: Coordinate\nisolate: none\n---\nCoordinator agent\n",
crate::common::write_config(
dir,
"standing",
serde_json::json!([
{
"name": "scout",
"description": "Search",
"resident": true,
"denyTools": [
"subagent"
],
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Scout instructions"
},
{
"name": "standing",
"description": "Primary",
"resident": true,
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Primary agent"
},
{
"name": "coordinator",
"description": "Coordinate",
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Coordinator agent"
}
]),
)?;
for args in [
vec!["init", "-b", "main"],
+31 -15
View File
@@ -76,21 +76,37 @@ fn prepare(dir: &Path) -> anyhow::Result<()> {
repo.join("extensions/probe/server.ts"),
"export default host => { globalThis.testHost = host; globalThis.subagentService = host.need({name:'subagents'}); globalThis.messageService = host.need({name:'messages'}); globalThis.lineageService = host.need({name:'lineage'}); host.implement({name:'conversations'}, {summaryModel: async () => globalThis.summaryRef, concludedIn: async () => new Set(), generatedTitle: async () => {}, setStanding: async () => {}, setAutomaticSummaries: async () => {}}); return {name:'probe'}; }",
)?;
std::fs::write(
repo.join("agents/models.json"),
r#"{"default":{"model":"faux/faux-1"}}"#,
)?;
std::fs::write(
repo.join("agents/scout.md"),
"---\nname: scout\ndescription: Search\nresident: true\ndenyTools: [subagent]\nisolate: none\n---\nScout instructions\n",
)?;
std::fs::write(
repo.join("agents/ultimate.md"),
"---\nname: ultimate\ndescription: Primary\nresident: true\nisolate: none\n---\nPrimary agent\n",
)?;
std::fs::write(
repo.join("agents/coordinator.md"),
"---\nname: coordinator\ndescription: Coordinate\nisolate: none\n---\nCoordinator agent\n",
crate::common::write_config(
dir,
"standing",
serde_json::json!([
{
"name": "scout",
"description": "Search",
"resident": true,
"denyTools": [
"subagent"
],
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Scout instructions"
},
{
"name": "standing",
"description": "Primary",
"resident": true,
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Primary agent"
},
{
"name": "coordinator",
"description": "Coordinate",
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Coordinator agent"
}
]),
)?;
for args in [
vec!["init", "-b", "main"],
+43 -4
View File
@@ -114,12 +114,51 @@ fn channel_with_closed_stdin() -> anyhow::Result<()> {
#[test]
fn cli_stays_up_after_stdin_eof() -> anyhow::Result<()> {
let dir = tempfile::tempdir()?;
World::open(dir.path())?;
let disk = dir.path().join("world");
let target = crate::common::build_git();
std::fs::create_dir_all(disk.join("bin"))?;
for binary in ["git", "tar"] {
std::fs::copy(
target.join(format!("wasm32-wasip2/release/{binary}.wasm")),
disk.join(format!("bin/{binary}.wasm")),
)?;
}
let repo = disk.join("src/sausage");
let source = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../extensions");
for extension in ["core", "models", "subagents"] {
crate::common::copy_tree(
&source.join(extension),
&repo.join("extensions").join(extension),
)?;
}
crate::common::write_config(
dir.path(),
"console",
serde_json::json!([
{"name":"console","description":"Standing console","model":"openai/gpt-6.1-sol","prompt":"Keep the user conversation"}
]),
)?;
for args in [
vec!["init", "-b", "main"],
vec!["add", "."],
vec!["commit", "--no-gpg-sign", "-m", "EOF fixture"],
] {
assert!(
Command::new("git")
.args(args)
.current_dir(&repo)
.env("GIT_AUTHOR_NAME", "Test")
.env("GIT_AUTHOR_EMAIL", "test@example.com")
.env("GIT_COMMITTER_NAME", "Test")
.env("GIT_COMMITTER_EMAIL", "test@example.com")
.status()?
.success()
);
}
let mut child = Command::new(env!("CARGO_BIN_EXE_sausage"))
.arg("run")
.arg(dir.path())
.args(["--api-listen", "127.0.0.1:0"])
.env("PI_PROXY_BASE_URL", "https://proxy.invalid")
.env("PI_PROXY_API_KEY", "faux-token")
.env_remove("SAUSAGE_USERLAND")
.stdin(Stdio::null())
.spawn()?;
@@ -134,7 +173,7 @@ fn cli_stays_up_after_stdin_eof() -> anyhow::Result<()> {
r.get::<_, i64>(0)
})
.unwrap_or(0)
> 0
> 1
{
break;
}
+31 -15
View File
@@ -60,21 +60,37 @@ fn prepare(dir: &Path) -> anyhow::Result<()> {
source.join("extensions/core/agents.ts"),
repo.join("extensions/core/agents.ts"),
)?;
std::fs::write(
repo.join("agents/models.json"),
r#"{"default":{"model":"faux/faux-1"}}"#,
)?;
std::fs::write(
repo.join("agents/scout.md"),
"---\nname: scout\ndescription: Search\nresident: true\ndenyTools: [subagent]\nisolate: none\n---\nScout instructions\n",
)?;
std::fs::write(
repo.join("agents/ultimate.md"),
"---\nname: ultimate\ndescription: Primary\nresident: true\nisolate: none\n---\nPrimary agent\n",
)?;
std::fs::write(
repo.join("agents/coordinator.md"),
"---\nname: coordinator\ndescription: Coordinate\nmodel: faux/coordinator\nisolate: none\n---\nCoordinator agent\n",
crate::common::write_config(
dir,
"standing",
serde_json::json!([
{
"name": "scout",
"description": "Search",
"resident": true,
"denyTools": [
"subagent"
],
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Scout instructions"
},
{
"name": "standing",
"description": "Primary",
"resident": true,
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Primary agent"
},
{
"name": "coordinator",
"description": "Coordinate",
"isolate": "none",
"model": "faux/coordinator",
"prompt": "Coordinator agent"
}
]),
)?;
for args in [
vec!["init", "-b", "main"],
+8 -9
View File
@@ -10,7 +10,7 @@ fn bundle() -> anyhow::Result<PathBuf> {
let key = crate::common::bundle_key(&repo)?;
let stamp = bundle.join(".source-key");
if !bundle.join("bin/sh.wasm").exists()
|| !bundle.join("src/sausage/agents/models.json").exists()
|| !bundle.join("etc/sausage/config.yaml").exists()
|| std::fs::read_to_string(&stamp).ok().as_deref() != Some(key.as_str())
{
if stamp.exists() {
@@ -33,12 +33,11 @@ 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))?;
let world = World::init(dir.path(), &bundle).await?;
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",
"config/config.yaml",
"skills/README.md",
"extensions/README.md",
] {
@@ -58,11 +57,11 @@ async fn bundle_copy_and_real_shell() -> anyhow::Result<()> {
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!(message, "Initial world source");
for path in ["config", "skills", "extensions"] {
assert_eq!(
git(&snapshot, &["rev-parse", &format!("HEAD:{path}")])?,
git(&repo, &["rev-parse", &format!("{revision}:{path}")])?,
git(&repo, &["rev-parse", &format!("HEAD:{path}")])?,
"bundled {path} must match the source commit"
);
}
@@ -197,7 +196,7 @@ async fn bundle_copy_and_real_shell() -> anyhow::Result<()> {
);
let history = String::from_utf8(history)?;
assert_eq!(history.lines().count(), 1);
assert!(history.contains("Bundle source "));
assert!(history.contains("Initial world source"));
let mut status = Vec::new();
assert_eq!(
exec.exec(
@@ -312,7 +311,7 @@ impl sausage::exec::Exec for LoaderTiming {
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 world = World::init(dir.path(), &bundle).await?;
let root = world.root.clone();
let exec = sausage::process::exec(World {
root: world.root.clone(),
+6 -23
View File
@@ -61,29 +61,12 @@ fn prepare(dir: &Path, all_extensions: bool) -> anyhow::Result<()> {
repo.join("extensions/probe/server.ts"),
"export default host => { globalThis.p3Models=host.need({name:'models'}); globalThis.p3Subagents=host.need({name:'subagents'}); globalThis.p3Workspaces=host.need({name:'workspaces'}); globalThis.p3Host=host; return {name:'probe'}; }",
)?;
std::fs::create_dir_all(repo.join("agents"))?;
std::fs::write(
repo.join("agents/models.json"),
r#"{"default":{"model":"faux/faux-1"}}"#,
)?;
for role in ["ultimate", "coordinator", "worker", "reviewer"] {
let denial = if role == "worker" || role == "reviewer" {
"denyTools: [subagent]\n"
} else {
""
};
std::fs::write(
repo.join(format!("agents/{role}.md")),
format!(
"---\nname: {role}\ndescription: P3 {role}\nisolate: none\n{denial}{}---\nP3 role:{role}\n",
if role == "ultimate" {
"resident: true\n"
} else {
""
}
),
)?;
}
let roster: Vec<serde_json::Value> = ["standing", "coordinator", "worker", "reviewer"].into_iter().map(|role| serde_json::json!({
"name":role, "description":format!("P3 {role}"), "model":"faux/faux-1",
"isolate":"none", "resident":role == "standing", "prompt":format!("P3 role:{role}"),
"denyTools":if role == "worker" || role == "reviewer" {vec!["subagent"]} else {vec![]}
})).collect();
crate::common::write_config(dir, "standing", serde_json::json!(roster))?;
std::fs::write(
repo.join("settings.json"),
r#"{"lander":{"checks":["sh -c ': > /check-running; until test -f /check-release; do :; done; test -f feature.txt'"]}}"#,
+15 -7
View File
@@ -73,6 +73,19 @@ fn prepare(dir: &Path) -> anyhow::Result<PathBuf> {
}
World::open_with_userland(dir, Some(&bundle))?;
let repo = dir.join("world/src/sausage");
for extension in ["core", "models", "subagents"] {
crate::common::copy_tree(
&source.join("extensions").join(extension),
&repo.join("extensions").join(extension),
)?;
}
crate::common::write_config(
dir,
"console",
serde_json::json!([
{"name":"console","description":"P4 console","model":"openai/gpt-6.1-sol","prompt":"Build the requested programs","tools":["bash"]}
]),
)?;
fs::create_dir_all(repo.join("extensions/p4"))?;
fs::write(
repo.join("extensions/p4/server.ts"),
@@ -102,18 +115,13 @@ impl Drop for Running {
let _ = self.0.wait();
}
}
fn round(dir: &Path, bundle: &Path, number: usize) -> anyhow::Result<()> {
fn round(dir: &Path, number: usize) -> anyhow::Result<()> {
let stdout = dir.join(format!("round-{number}.stdout"));
let stderr = dir.join(format!("round-{number}.stderr"));
let mut child = Running(
Command::new(env!("CARGO_BIN_EXE_sausage"))
.arg("run")
.arg(dir)
.arg("--userland")
.arg(bundle)
.args(["--api-listen", "127.0.0.1:0"])
.env("PI_PROXY_BASE_URL", "https://proxy.invalid")
.env("PI_PROXY_API_KEY", "faux-token")
.env_remove("CREDENTIALS_DIRECTORY")
.stdin(Stdio::piped())
.stdout(fs::File::create(&stdout)?)
@@ -229,7 +237,7 @@ fn agent_builds_rust_and_node_twice() -> anyhow::Result<()> {
let bundle = prepare(dir.path())?;
let mut first_hits = 0;
for number in 1..=2 {
let outcome = round(dir.path(), &bundle, number);
let outcome = round(dir.path(), number);
let cleanup = boxes_removed(dir.path(), &bundle);
if outcome.is_err() {
for stream in ["stdout", "stderr"] {
+6
View File
@@ -96,6 +96,12 @@ async fn provider_transport_and_prices() -> anyhow::Result<()> {
Ok(())
});
let dir = tempfile::tempdir()?;
let config = dir.path().join("world/etc/sausage");
std::fs::create_dir_all(&config)?;
std::fs::write(
config.join("config.yaml"),
serde_json::to_vec(&json!({"proxy":proxy}))?,
)?;
let source = format!(
"globalThis.testProxy = {proxy};\n{}",
include_str!("../../js/proxy-models-test-bundle.js")
+16 -7
View File
@@ -51,13 +51,22 @@ fn prepare(dir: &Path) -> anyhow::Result<()> {
source.join("extensions/core/agents.ts"),
repo.join("extensions/core/agents.ts"),
)?;
std::fs::write(
repo.join("agents/models.json"),
r#"{"default":{"model":"faux/faux-1"}}"#,
)?;
std::fs::write(
repo.join("agents/scout.md"),
"---\nname: scout\ndescription: Search\nresident: true\ndenyTools: [subagent]\nisolate: none\n---\nScout instructions\n",
crate::common::write_config(
dir,
"scout",
serde_json::json!([
{
"name": "scout",
"description": "Search",
"resident": true,
"denyTools": [
"subagent"
],
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Scout instructions"
}
]),
)?;
for args in [
vec!["init", "-b", "main"],
+31 -15
View File
@@ -62,21 +62,37 @@ fn prepare(dir: &Path) -> anyhow::Result<()> {
source.join("extensions/conversations/api.ts"),
repo.join("extensions/conversations/api.ts"),
)?;
std::fs::write(
repo.join("agents/models.json"),
r#"{"default":{"model":"faux/faux-1"}}"#,
)?;
std::fs::write(
repo.join("agents/scout.md"),
"---\nname: scout\ndescription: Search\nresident: true\ndenyTools: [subagent]\nisolate: none\n---\nScout instructions\n",
)?;
std::fs::write(
repo.join("agents/ultimate.md"),
"---\nname: ultimate\ndescription: Primary\nresident: true\nisolate: none\n---\nPrimary agent\n",
)?;
std::fs::write(
repo.join("agents/coordinator.md"),
"---\nname: coordinator\ndescription: Coordinate\nisolate: none\n---\nCoordinator agent\n",
crate::common::write_config(
dir,
"standing",
serde_json::json!([
{
"name": "scout",
"description": "Search",
"resident": true,
"denyTools": [
"subagent"
],
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Scout instructions"
},
{
"name": "standing",
"description": "Primary",
"resident": true,
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Primary agent"
},
{
"name": "coordinator",
"description": "Coordinate",
"isolate": "none",
"model": "faux/faux-1",
"prompt": "Coordinator agent"
}
]),
)?;
for args in [
vec!["init", "-b", "main"],
+6 -8
View File
@@ -70,14 +70,12 @@ fn prepare(dir: &Path) -> anyhow::Result<()> {
repo.join("extensions/probe/server.ts"),
"export default host => { globalThis.workspaceService=host.need({name:'workspaces'}); globalThis.workspaceHost=host; return {name:'probe'}; }",
)?;
std::fs::create_dir_all(repo.join("agents"))?;
std::fs::write(
repo.join("agents/models.json"),
r#"{"default":{"model":"faux/faux-1"}}"#,
)?;
std::fs::write(
repo.join("agents/worker.md"),
"---\nname: worker\ndescription: Implement\nisolate: worktree\n---\nImplement\n",
crate::common::write_config(
dir,
"worker",
serde_json::json!([
{"name":"worker","description":"Implement","model":"faux/faux-1","isolate":"worktree","prompt":"Implement"}
]),
)?;
std::fs::write(
repo.join("settings.json"),