mod common;
use std::path::{Path, PathBuf};
use common::GateModel;
use salvor_cli::demo_script::{SUBTOPICS, finding_line, script};
use tempfile::tempdir;
fn workspace_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.ancestors()
.nth(2)
.expect("the crate lives two levels under the workspace root")
.to_owned()
}
fn ensure_demo_server_at_documented_path(root: &Path) {
let built = PathBuf::from(env!("CARGO_BIN_EXE_salvor-demo-research"));
let documented = root.join("target/debug/salvor-demo-research");
if built.canonicalize().ok() == documented.canonicalize().ok() {
return;
}
std::fs::create_dir_all(documented.parent().expect("parent exists"))
.expect("target/debug creates");
std::fs::copy(&built, &documented).expect("demo server copies into place");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn demo_assets_drive_a_twenty_step_run_to_completion() {
let root = workspace_root();
ensure_demo_server_at_documented_path(&root);
let dir = tempdir().expect("tempdir");
let store = dir.path().join("salvor.db");
let findings = dir.path().join("findings.txt");
let model = GateModel::mount(script()).await;
let model_uri = model.uri();
let output = {
let root = root.clone();
let store = store.clone();
let findings = findings.clone();
tokio::task::spawn_blocking(move || {
let mut command =
assert_cmd::Command::cargo_bin("salvor").expect("salvor binary builds");
command
.current_dir(&root)
.arg("--store")
.arg(&store)
.args([
"run",
"--agent",
"demo/agent.toml",
"--input",
"@demo/input.json",
])
.env("RUST_LOG", "warn")
.env("SALVOR_DEMO_BASE_URL", &model_uri)
.env("SALVOR_DEMO_FINDINGS", &findings)
.env_remove("ANTHROPIC_API_KEY");
command.output().expect("salvor runs")
})
.await
.expect("blocking task joins")
};
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
output.status.success(),
"the demo run completes: {output:?}"
);
assert!(
stdout.contains("Research complete"),
"the final summary is printed: {stdout}"
);
let requests = model.received_requests().await.expect("requests recorded");
assert_eq!(requests.len(), 20, "twenty model calls were made");
let expected: String = SUBTOPICS
.iter()
.map(|subtopic| finding_line(subtopic) + "\n")
.collect();
let recorded = std::fs::read_to_string(&findings).expect("findings file exists");
assert_eq!(
recorded, expected,
"the findings file holds exactly the nine expected lines"
);
}