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