ralph_workflow/json_parser/codex/
parser.rs1use super::printer::{SharedPrinter, StdoutPrinter};
2use crate::json_parser::printer::Printable;
3use io::CodexParserState;
4use std::cell::RefCell;
5use std::rc::Rc;
6
7pub 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}