zynk 0.2.0

Portable protocol and helper CLI for multi-agent collaboration.
use crate::compose::{build_message, ComposeArgs};
use crate::profile::load_profile;
use crate::{CliError, CliResult};
use clap::Args;
use std::io::{self, Write};
use std::process::Command;

#[derive(Debug, Args)]
pub struct SendHerdrArgs {
    #[arg(long, help = "Target herdr pane id.")]
    pub pane: String,
    #[arg(long, help = "Print composed message without sending.")]
    pub dry_run: bool,
    #[arg(long, default_value = "herdr", help = "herdr executable path.")]
    pub herdr_bin: String,
    #[command(flatten)]
    pub compose: ComposeArgs,
}

pub fn run(args: SendHerdrArgs) -> CliResult<()> {
    let profile = load_profile(args.compose.profile.as_deref())?;
    let message = build_message(&args.compose, &profile)?;

    if args.dry_run {
        eprintln!("DRY RUN: message was not sent; do not record delivery_status=sent.");
        println!("{message}");
        return Ok(());
    }

    let output = Command::new(&args.herdr_bin)
        .args(["pane", "run", &args.pane, &message])
        .output();
    let output = match output {
        Ok(output) => output,
        Err(error) if error.kind() == io::ErrorKind::NotFound => {
            return Err(CliError::with_code(
                127,
                format!("herdr CLI not found at {}", args.herdr_bin),
            ))
        }
        Err(error) => return Err(CliError::failure(format!("failed to run herdr: {error}"))),
    };
    io::stdout()
        .write_all(&output.stdout)
        .map_err(|error| CliError::failure(format!("failed to write stdout: {error}")))?;
    io::stderr()
        .write_all(&output.stderr)
        .map_err(|error| CliError::failure(format!("failed to write stderr: {error}")))?;
    if output.status.success() {
        Ok(())
    } else {
        Err(CliError::with_code(
            output.status.code().unwrap_or(1),
            "herdr pane run failed",
        ))
    }
}