steer_tui/tui/widgets/formatters/
external.rs1use super::{ToolFormatter, helpers::*};
2use crate::tui::theme::Theme;
3use ratatui::{
4 style::Style,
5 text::{Line, Span},
6};
7use serde_json::Value;
8use steer_core::app::conversation::ToolResult;
9use textwrap;
10
11pub struct ExternalFormatter;
14
15impl ToolFormatter for ExternalFormatter {
16 fn compact(
17 &self,
18 params: &Value,
19 result: &Option<ToolResult>,
20 _wrap_width: usize,
21 theme: &Theme,
22 ) -> Vec<Line<'static>> {
23 let mut spans = Vec::new();
25
26 let preview = json_preview(params, 30);
28 spans.push(Span::styled(preview.to_string(), theme.dim_text()));
29
30 if let Some(result) = result {
31 match result {
32 ToolResult::External(ext) => {
33 let payload_preview = truncate_middle(&ext.payload, 40);
34 spans.push(Span::raw(" → "));
35 spans.push(Span::styled(payload_preview, Style::default()));
36 }
37 ToolResult::Error(err) => {
38 spans.push(Span::raw(" ✗ "));
39 spans.push(Span::styled(err.to_string(), theme.error_text()));
40 }
41 _ => {}
42 }
43 }
44
45 vec![Line::from(spans)]
46 }
47
48 fn detailed(
49 &self,
50 params: &Value,
51 result: &Option<ToolResult>,
52 wrap_width: usize,
53 theme: &Theme,
54 ) -> Vec<Line<'static>> {
55 let mut lines = Vec::new();
56
57 lines.push(Line::from(Span::styled("Parameters:", theme.text())));
59
60 let pretty_params = serde_json::to_string_pretty(params).unwrap_or_default();
61 for line in wrap_lines(pretty_params.lines(), wrap_width) {
62 lines.push(Line::from(Span::styled(line, theme.dim_text())));
63 }
64
65 if let Some(result) = result {
67 lines.push(separator_line(wrap_width, theme.dim_text()));
68 match result {
69 ToolResult::External(ext) => {
70 if let Ok(json_val) = serde_json::from_str::<serde_json::Value>(&ext.payload) {
72 if let Ok(pretty) = serde_json::to_string_pretty(&json_val) {
73 for ln in wrap_lines(pretty.lines(), wrap_width) {
74 lines.push(Line::from(Span::raw(ln)));
75 }
76 } else {
77 for wrapped in textwrap::wrap(&ext.payload, wrap_width) {
79 lines.push(Line::from(Span::raw(wrapped.to_string())));
80 }
81 }
82 } else {
83 for wrapped in textwrap::wrap(&ext.payload, wrap_width) {
85 lines.push(Line::from(Span::raw(wrapped.to_string())));
86 }
87 }
88 }
89 ToolResult::Error(err) => {
90 for wrapped in textwrap::wrap(&err.to_string(), wrap_width) {
91 lines.push(Line::from(Span::styled(
92 wrapped.to_string(),
93 theme.error_text(),
94 )));
95 }
96 }
97 _ => {}
98 }
99 }
100
101 lines
102 }
103}