| 270 | } |
| 271 | |
| 272 | fn render_reasoning( |
| 273 | &self, |
| 274 | content: &str, |
| 275 | duration_ms: Option<u64>, |
| 276 | theme: &Theme, |
| 277 | ) -> Vec<Line<'static>> { |
| 278 | let mut lines = Vec::new(); |
| 279 | |
| 280 | // Strip [REDACTED] markers |
| 281 | let cleaned = content.replace("[REDACTED]", "").trim().to_string(); |
| 282 | if cleaned.is_empty() { |
| 283 | return lines; |
| 284 | } |
| 285 | |
| 286 | let title = if let Some(ms) = duration_ms { |
| 287 | if ms < 1000 { |
| 288 | format!("Thinking ({}ms)", ms) |
| 289 | } else { |
| 290 | format!("Thinking ({:.1}s)", ms as f64 / 1000.0) |
| 291 | } |
| 292 | } else { |
| 293 | "Thinking".to_string() |
| 294 | }; |
| 295 | |
| 296 | lines.push(Line::from(vec![ |
| 297 | Span::styled("▼ ", Style::default().fg(theme.primary)), |
| 298 | Span::styled( |
| 299 | title, |
| 300 | Style::default() |
| 301 | .fg(theme.primary) |
| 302 | .add_modifier(Modifier::BOLD), |
| 303 | ), |
| 304 | ])); |
| 305 | |
| 306 | for line in cleaned.lines() { |
| 307 | lines.push(Line::from(Span::styled( |
| 308 | line.to_string(), |
| 309 | Style::default().fg(theme.text_muted), |
| 310 | ))); |
| 311 | } |
| 312 | |
| 313 | lines.push(Line::from("")); |
| 314 | lines |
| 315 | } |
| 316 | } |