Skip to main content

ralph_workflow/json_parser/codex/
parser.rs

1use super::printer::{SharedPrinter, StdoutPrinter};
2use crate::json_parser::printer::Printable;
3use io::CodexParserState;
4use std::cell::RefCell;
5use std::rc::Rc;
6
7/// Codex event parser
8pub struct CodexParser {
9    colors: Colors,
10    verbosity: Verbosity,
11    log_path: Option<PathBuf>,
12    display_name: String,
13    state: CodexParserState,
14    show_streaming_metrics: bool,
15    printer: SharedPrinter,
16}
17
18impl CodexParser {
19    pub(crate) fn new(colors: Colors, verbosity: Verbosity) -> Self {
20        Self::with_printer(
21            colors,
22            verbosity,
23            Rc::new(RefCell::new(StdoutPrinter::new())),
24        )
25    }
26
27    pub(crate) fn with_printer(
28        colors: Colors,
29        verbosity: Verbosity,
30        printer: SharedPrinter,
31    ) -> Self {
32        let verbose_warnings = matches!(verbosity, Verbosity::Debug);
33
34        Self {
35            colors,
36            verbosity,
37            log_path: None,
38            display_name: "Codex".to_string(),
39            state: CodexParserState::new(verbose_warnings),
40            show_streaming_metrics: false,
41            printer,
42        }
43    }
44
45    pub(crate) const fn with_show_streaming_metrics(mut self, show: bool) -> Self {
46        self.show_streaming_metrics = show;
47        self
48    }
49
50    pub(crate) fn with_display_name(mut self, display_name: &str) -> Self {
51        self.display_name = display_name.to_string();
52        self
53    }
54
55    pub(crate) fn with_log_file(mut self, path: &str) -> Self {
56        self.log_path = Some(PathBuf::from(path));
57        self
58    }
59
60    #[cfg(any(test, feature = "test-utils"))]
61    #[must_use]
62    pub fn with_terminal_mode(self, mode: crate::json_parser::TerminalMode) -> Self {
63        *self.state.terminal_mode.borrow_mut() = mode;
64        self
65    }
66
67    #[cfg(any(test, feature = "test-utils"))]
68    pub fn with_printer_for_test(
69        colors: Colors,
70        verbosity: Verbosity,
71        printer: SharedPrinter,
72    ) -> Self {
73        Self::with_printer(colors, verbosity, printer)
74    }
75
76    #[cfg(any(test, feature = "test-utils"))]
77    #[must_use]
78    pub fn with_log_file_for_test(mut self, path: &str) -> Self {
79        self.log_path = Some(PathBuf::from(path));
80        self
81    }
82
83    #[cfg(any(test, feature = "test-utils"))]
84    #[must_use]
85    pub fn with_display_name_for_test(mut self, display_name: &str) -> Self {
86        self.display_name = display_name.to_string();
87        self
88    }
89
90    #[cfg(any(test, feature = "test-utils"))]
91    pub fn parse_stream_for_test<R: std::io::BufRead>(
92        &mut self,
93        reader: R,
94        workspace: &dyn Workspace,
95    ) -> std::io::Result<()> {
96        self.parse_stream(reader, workspace)
97    }
98
99    #[cfg(any(test, feature = "test-utils"))]
100    pub fn printer(&self) -> SharedPrinter {
101        Rc::clone(&self.printer)
102    }
103
104    pub(crate) fn with_printer_mut<R>(&mut self, f: impl FnOnce(&mut dyn Printable) -> R) -> R {
105        let mut printer_ref = self.printer.borrow_mut();
106        f(&mut *printer_ref)
107    }
108
109    #[cfg(any(test, feature = "test-utils"))]
110    pub fn streaming_metrics(&self) -> crate::json_parser::health::StreamingQualityMetrics {
111        self.state
112            .streaming_session
113            .borrow()
114            .get_streaming_quality_metrics()
115    }
116
117    #[inline]
118    fn optional_output(output: String) -> Option<String> {
119        if output.is_empty() {
120            None
121        } else {
122            Some(output)
123        }
124    }
125}