Skip to main content

haematite_cli/assistant/
cli.rs

1use std::path::PathBuf;
2use std::process::ExitCode;
3
4/// Builds the production harness command for an isolated adapter probe.
5///
6/// # Errors
7/// Returns the same seat, home, environment and executable refusals as a launch.
8#[cfg(feature = "test-support")]
9pub fn probe_command(path: &std::path::Path) -> anyhow::Result<tokio::process::Command> {
10    super::host::command(&super::config::Seat::load(path)?)
11}
12
13/// Run the Lys-launched assistant seat.
14pub fn run(mut args: impl Iterator<Item = String>) -> ExitCode {
15    let result = (|| {
16        anyhow::ensure!(
17            args.next().as_deref() == Some("run") && args.next().as_deref() == Some("--config"),
18            "usage: haematite assistant run --config <seat.json>"
19        );
20        let path = PathBuf::from(
21            args.next()
22                .ok_or_else(|| anyhow::anyhow!("seat_config_required"))?,
23        );
24        anyhow::ensure!(args.next().is_none(), "assistant_unexpected_argument");
25        let seat = super::config::Seat::load(&path)?;
26        let runtime = tokio::runtime::Builder::new_current_thread()
27            .enable_all()
28            .build()?;
29        let result = runtime.block_on(super::host::serve(&seat));
30        runtime.shutdown_timeout(std::time::Duration::from_secs(2));
31        result
32    })();
33    match result {
34        Ok(status) => ExitCode::from(u8::try_from(status).unwrap_or(1)),
35        Err(error) => {
36            eprintln!("haematite assistant: {error}");
37            ExitCode::FAILURE
38        }
39    }
40}