rho-coding-agent 0.28.1

A lightweight agent harness inspired by Pi
Documentation
use serde_json::Value;

use super::types::{Snapshot, State, Stream};

pub(super) fn result_lines(content: &str) -> Option<Vec<String>> {
    if let Ok(snapshot) = serde_json::from_str::<Snapshot>(content) {
        return Some(snapshot_lines(&snapshot));
    }

    let value: Value = serde_json::from_str(content).ok()?;
    let process_id = value.get("process_id")?.as_str()?;
    value
        .get("stop_requested")
        .and_then(Value::as_bool)
        .filter(|requested| *requested)
        .map(|_| vec!["process".into(), format!("stop requested: {process_id}")])
}

pub(super) fn snapshot_lines(snapshot: &Snapshot) -> Vec<String> {
    let mut lines = vec!["process".into(), snapshot.command.clone()];
    lines.push(status_line(snapshot));

    if snapshot.truncated {
        lines.push(format!(
            "output before cursor {} is no longer available",
            snapshot.first_cursor
        ));
    }
    for chunk in &snapshot.chunks {
        let label = match chunk.stream {
            Stream::Stdout => "stdout",
            Stream::Stderr => "stderr",
        };
        lines.push(format!("{label}:"));
        lines.push(chunk.text.clone());
    }
    if snapshot.output_pending {
        lines.push(format!(
            "more output available at cursor {}",
            snapshot.next_cursor
        ));
    }
    if let Some(detail) = &snapshot.terminal_detail {
        lines.push(format!("detail: {detail}"));
    }
    lines
}

fn status_line(snapshot: &Snapshot) -> String {
    let state = match snapshot.state {
        State::Starting => "starting",
        State::Running => "running",
        State::Exited => "exited",
        State::Terminated => "terminated",
        State::TimedOut => "timed out",
        State::FailedToStart => "failed to start",
    };
    let exit_code = snapshot
        .exit_code
        .map(|code| format!(", exit code {code}"))
        .unwrap_or_default();
    format!(
        "{state} - {} - {:.1}s{exit_code}",
        snapshot.process_id, snapshot.runtime_seconds
    )
}