M1: composition root and harness run -p debug command
Adds the harness-app composition root wiring config, providers, tools, and the engine loop together, plus the harness run -p "<prompt>" debug command in harness-tui::main for driving a one-shot prompt end-to-end from the CLI.
This commit is contained in:
@@ -1,3 +1,86 @@
|
||||
fn main() {
|
||||
println!("harness {}", env!("CARGO_PKG_VERSION"));
|
||||
use harness_core::event::RunOutcome;
|
||||
|
||||
const DEFAULT_MODEL: &str = "anthropic/claude-sonnet-4-5";
|
||||
|
||||
fn print_usage() {
|
||||
eprintln!("usage: harness run -p \"<prompt>\" [-m provider/model]");
|
||||
}
|
||||
|
||||
fn parse_run_args(args: &[String]) -> Option<(String, Option<String>)> {
|
||||
let mut prompt = None;
|
||||
let mut model = None;
|
||||
let mut i = 0;
|
||||
while i < args.len() {
|
||||
match args[i].as_str() {
|
||||
"-p" | "--prompt" => {
|
||||
prompt = args.get(i + 1).cloned();
|
||||
i += 2;
|
||||
}
|
||||
"-m" | "--model" => {
|
||||
model = args.get(i + 1).cloned();
|
||||
i += 2;
|
||||
}
|
||||
_ => i += 1,
|
||||
}
|
||||
}
|
||||
prompt.map(|p| (p, model))
|
||||
}
|
||||
|
||||
async fn run(args: &[String]) -> i32 {
|
||||
let Some((prompt, model_arg)) = parse_run_args(args) else {
|
||||
print_usage();
|
||||
return 2;
|
||||
};
|
||||
|
||||
let cwd = match std::env::current_dir() {
|
||||
Ok(cwd) => cwd,
|
||||
Err(e) => {
|
||||
eprintln!("error: could not read cwd: {e}");
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
let app = match harness_app::App::init(cwd) {
|
||||
Ok(app) => app,
|
||||
Err(e) => {
|
||||
eprintln!("error: {e}");
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
let model_ref = model_arg
|
||||
.or_else(|| app.config.model.clone())
|
||||
.unwrap_or_else(|| DEFAULT_MODEL.to_string());
|
||||
|
||||
match app.run_prompt(prompt, &model_ref).await {
|
||||
Ok((RunOutcome::Stopped, session_id)) => {
|
||||
let text = app.final_text(&session_id).await.unwrap_or_default();
|
||||
println!("{text}");
|
||||
0
|
||||
}
|
||||
Ok((RunOutcome::Aborted, _)) => {
|
||||
eprintln!("run aborted");
|
||||
1
|
||||
}
|
||||
Ok((RunOutcome::Errored { message }, _)) => {
|
||||
eprintln!("error: {message}");
|
||||
1
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("error: {e}");
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() {
|
||||
let args: Vec<String> = std::env::args().skip(1).collect();
|
||||
let exit_code = if args.first().map(String::as_str) == Some("run") {
|
||||
run(&args[1..]).await
|
||||
} else {
|
||||
println!("harness {}", env!("CARGO_PKG_VERSION"));
|
||||
0
|
||||
};
|
||||
std::process::exit(exit_code);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user