Skip to main content

browser_automation_cli/
envelope.rs

1//! JSON envelope helpers (`schema_version = 1`).
2//!
3//! Success and error envelopes are written to **stdout** for agent parsing.
4//! Human diagnostics stay on stderr.
5//!
6//! # Success shape
7//!
8//! ```json
9//! {"schema_version":1,"ok":true,"data":{}}
10//! ```
11//!
12//! # Error shape
13//!
14//! ```json
15//! {"schema_version":1,"ok":false,"error":{"kind":"unavailable","message":"...","exit_code":69}}
16//! ```
17
18use serde_json::{json, Value};
19
20use crate::error::CliError;
21
22/// Print a success envelope with arbitrary JSON `data` and flush a single line.
23pub fn print_success_json(data: Value) -> Result<(), CliError> {
24    let env = json!({
25        "schema_version": 1,
26        "ok": true,
27        "data": data,
28    });
29    println!(
30        "{}",
31        serde_json::to_string(&env).map_err(|e| {
32            CliError::new(
33                crate::error::ErrorKind::Software,
34                format!("json encode: {e}"),
35            )
36        })?
37    );
38    Ok(())
39}
40
41/// Print an error envelope derived from [`CliError`].
42pub fn print_error_json(err: &CliError) -> Result<(), CliError> {
43    let mut env = json!({
44        "schema_version": 1,
45        "ok": false,
46        "error": {
47            "kind": err.kind().as_str(),
48            "message": err.message(),
49            "exit_code": err.exit_code(),
50        }
51    });
52    if let Some(s) = err.suggestion() {
53        env["error"]["suggestion"] = json!(s);
54    }
55    println!(
56        "{}",
57        serde_json::to_string(&env).map_err(|e| {
58            CliError::new(
59                crate::error::ErrorKind::Software,
60                format!("json encode: {e}"),
61            )
62        })?
63    );
64    Ok(())
65}