Skip to main content

acp_agent/runtime/
stdio.rs

1use std::process::{ExitStatus, Stdio};
2
3use anyhow::{Context, Result};
4use tokio::process::Command;
5
6use crate::registry::fetch_registry;
7use crate::runtime::prepare::{CommandSpec, prepare_agent_command};
8use crate::runtime::process::apply_command_spec;
9
10/// Runs an agent with stdio connected directly to the current terminal.
11///
12/// Keeps the temporary extraction directory alive while the agent process runs so
13/// downloaded binaries do not disappear mid-execution.
14pub async fn run_agent_stdio(agent_id: &str, user_args: &[String]) -> Result<ExitStatus> {
15    let registry = fetch_registry().await?;
16    let agent = registry
17        .get_agent(agent_id)
18        .with_context(|| format!("failed to resolve agent \"{agent_id}\" from registry"))?;
19
20    let prepared = prepare_agent_command(agent, user_args).await?;
21    let _temp_dir = prepared.temp_dir;
22    run_command_stdio(prepared.spec, &agent.id).await
23}
24
25async fn run_command_stdio(spec: CommandSpec, subject: &str) -> Result<ExitStatus> {
26    let program_display = spec.program.to_string_lossy().into_owned();
27    let mut command = Command::new(&spec.program);
28    apply_command_spec(&mut command, &spec);
29    command
30        .stdin(Stdio::inherit())
31        .stdout(Stdio::inherit())
32        .stderr(Stdio::inherit());
33
34    command
35        .status()
36        .await
37        .with_context(|| format!("failed to run {program_display} for {subject}"))
38}