use std::{env, error::Error, time::Duration};
use basis::{
ChildSpec, Event, FnSink, ModelInfo, RunSpec, Runtime, ToolRoster, Workspace, provider,
};
const TRIAGE: &str = "triage:";
const TRIAGE_TOOLS: [&str; 3] = ["read", "grep", "glob"];
const TRIAGE_VOICE: &str = "You are a triage gate. Read only what you need, then answer in one \
short paragraph starting with YES (worth fixing now) or NO, and say why.";
const TRIAGE_WINDOW: usize = 128_000;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let mut args = env::args().skip(1);
let (Some(workspace), Some(task), Some(triage_model)) = (args.next(), args.next(), args.next())
else {
return Err("usage: child_policy <workspace> <task> <triage-model>".into());
};
let provider = provider::resolve(None, None)?.provider;
let triage = ModelInfo::new(triage_model, provider).with_context_window(TRIAGE_WINDOW);
let runtime = Runtime::builder().with_child_policy(move |child| {
if child.prompt().trim_start().starts_with(TRIAGE) {
ChildSpec::inherit()
.with_roster(ToolRoster::only(TRIAGE_TOOLS))
.with_model(triage.clone())
.with_system(TRIAGE_VOICE)
} else {
ChildSpec::inherit()
}
});
let workspace = Workspace::builder(workspace)
.with_runtime_builder(runtime)
.open()
.await?;
let spec = RunSpec::new(format!(
"Investigate this report: {task}\n\n\
First delegate one task whose prompt starts with `{TRIAGE}` asking whether the \
problem is real and worth fixing now — that child is a cheap, read-only gate. \
If it answers YES, delegate the actual fix as an ordinary task (no prefix) and \
then summarise what was done; if NO, explain why and stop."
))
.with_deadline(Duration::from_secs(600));
let report = workspace
.prepare(spec)?
.execute_with_approver(
FnSink::new(|event| {
match event {
Event::TaskUpdated { title, status, .. } => {
println!("[child] {title}: {status:?}");
}
Event::AssistantMessage { text } => println!("{text}"),
_ => {}
}
Ok(())
}),
basis::AllowAll,
)
.await?;
println!(
"\n{} tokens, outcome {:?}",
report.usage.total_tokens(),
report.outcome
);
Ok(())
}