Skip to main content

vs_cli/commands/
render.rs

1//! Render a [`Response`] to stdout as either canonical wire form
2//! (default) or strict RFC-8259 JSON (`--json`).
3
4use crate::client::Response;
5
6/// `--json` emits strict RFC-8259 JSON via `serde_json` (escaping,
7/// surrogates, control characters all handled). The default is the
8/// canonical wire form that an agent would consume directly.
9#[must_use]
10pub fn render(resp: &Response, json: bool) -> String {
11    if json {
12        let warnings: Vec<serde_json::Value> = resp
13            .warnings
14            .iter()
15            .map(|w| {
16                serde_json::json!({
17                    "code": w.code.to_string(),
18                    "args": w.args,
19                })
20            })
21            .collect();
22        let envelope = match &resp.envelope {
23            vs_protocol::Envelope::Success(t) => serde_json::json!({
24                "kind": "success",
25                "token": t.to_string(),
26            }),
27            vs_protocol::Envelope::Error { code, args } => serde_json::json!({
28                "kind": "error",
29                "code": code.to_string(),
30                "args": args,
31            }),
32        };
33        let value = serde_json::json!({
34            "warnings": warnings,
35            "envelope": envelope,
36            "body": resp.body,
37        });
38        let mut out =
39            serde_json::to_string_pretty(&value).expect("serde_json never fails on owned strings");
40        out.push('\n');
41        out
42    } else {
43        resp.render_wire()
44    }
45}