1use super::config::Seat;
2use std::path::Path;
3use std::process::ExitCode;
4
5#[derive(Clone, Copy, Debug, clap::Subcommand)]
7pub enum AgentCommand {
8 Run,
10 #[command(hide = true)]
12 Tools,
13}
14
15#[must_use]
18pub fn run(path: &Path, command: AgentCommand) -> ExitCode {
19 let result = Seat::load(path).and_then(|seat| match command {
20 AgentCommand::Tools => tools(&seat),
21 AgentCommand::Run => {
22 let runtime = tokio::runtime::Builder::new_multi_thread()
23 .enable_all()
24 .build()?;
25 let outcome = runtime.block_on(super::host::serve(&seat))?;
26 for error in outcome.errors {
27 eprintln!("liminal agent: {error}");
28 }
29 Ok(outcome.status)
30 }
31 });
32 match result {
33 Ok(status) => u8::try_from(status).map_or_else(
34 |_| {
35 eprintln!("liminal agent: harness exit status is outside the process exit range");
36 ExitCode::from(1)
37 },
38 ExitCode::from,
39 ),
40 Err(error) => {
41 eprintln!("liminal agent: {error}");
42 ExitCode::from(1)
43 }
44 }
45}
46
47fn tools(seat: &Seat) -> anyhow::Result<i32> {
48 let live = crate::Live::new(&seat.ticket).map_err(anyhow::Error::msg)?;
49 let mut server = crate::Server::new(live, seat.ticket.limits.frame_bytes);
50 let stdin = std::io::stdin();
51 server.serve(&mut stdin.lock(), &mut std::io::stdout())?;
52 Ok(0)
53}