Skip to main content

acp_cli/output/
json.rs

1use std::io::{self, Write};
2
3use serde_json::json;
4
5use super::{OutputRenderer, is_read_tool};
6
7pub struct JsonRenderer {
8    suppress_reads: bool,
9}
10
11impl JsonRenderer {
12    pub fn new(suppress_reads: bool) -> Self {
13        Self { suppress_reads }
14    }
15
16    fn emit(&self, value: serde_json::Value) {
17        let line = serde_json::to_string(&value).expect("failed to serialize JSON output");
18        println!("{line}");
19        let _ = io::stdout().flush();
20    }
21}
22
23impl OutputRenderer for JsonRenderer {
24    fn text_chunk(&mut self, text: &str) {
25        self.emit(json!({"type": "text", "content": text}));
26    }
27
28    fn tool_status(&mut self, tool: &str) {
29        self.emit(json!({"type": "tool", "name": tool}));
30    }
31
32    fn tool_result(&mut self, tool: &str, output: &str) {
33        if self.suppress_reads && is_read_tool(tool) {
34            self.emit(json!({
35                "type": "tool_result",
36                "name": tool,
37                "output": "[suppressed]",
38                "suppressed": true,
39            }));
40        } else {
41            self.emit(json!({
42                "type": "tool_result",
43                "name": tool,
44                "output": output,
45            }));
46        }
47    }
48
49    fn permission_denied(&mut self, tool: &str) {
50        self.emit(json!({"type": "error", "message": format!("permission denied: {tool}")}));
51    }
52
53    fn error(&mut self, err: &str) {
54        self.emit(json!({"type": "error", "message": err}));
55    }
56
57    fn session_info(&mut self, id: &str) {
58        self.emit(json!({"type": "session", "sessionId": id}));
59    }
60
61    fn done(&mut self) {
62        self.emit(json!({"type": "done"}));
63    }
64}