rab/agent/ui/components/
message_components.rs1use crate::agent::ui::components::AssistantMessageComponent;
2use crate::agent::ui::components::UserMessageComponent;
3use crate::agent::ui::components::bash_execution::{BashExecution, BashStatus};
4use crate::agent::ui::components::info_message::InfoMessageComponent;
5use crate::agent::ui::messages::DisplayMsg;
6use crate::agent::ui::theme::{RabTheme, current_theme};
7use crate::tui::Component;
8use crate::tui::components::Spacer;
9use crate::tui::components::Text;
10use crate::tui::components::r#box::TuiBox;
11
12pub fn display_msg_to_component(msg: &DisplayMsg) -> Option<std::boxed::Box<dyn Component>> {
16 let theme: RabTheme = current_theme().clone();
18 match msg {
19 DisplayMsg::User(text) => Some(std::boxed::Box::new(UserMessageComponent::new(
20 text.clone(),
21 ))),
22 DisplayMsg::AssistantText(text) => {
23 if text.is_empty() {
24 return None;
25 }
26 Some(std::boxed::Box::new(AssistantMessageComponent::new(
27 text.clone(),
28 )))
29 }
30 DisplayMsg::Thinking { text, level: _ } => {
31 let styled = theme.fg("thinkingText", &theme.italic(text));
32 Some(std::boxed::Box::new(Text::new(styled, 0, 0, None)))
33 }
34 DisplayMsg::ToolCall { name: _, args: _ } => {
35 None
37 }
38 DisplayMsg::ToolResult {
39 content,
40 compact: _,
41 is_error,
42 } => {
43 let color = if *is_error { "error" } else { "toolOutput" };
44 let styled = theme.fg(color, content);
45 let bg_key = if *is_error {
46 "toolErrorBg"
47 } else {
48 "toolSuccessBg"
49 };
50 let bg_ansi = theme.bg_ansi(bg_key).to_string();
51 let mut msg_box = TuiBox::new(
52 1,
53 1,
54 Some(std::boxed::Box::new(move |s: &str| -> String {
55 format!("{}{}\x1b[49m", bg_ansi, s)
56 })),
57 );
58 msg_box.add_child(std::boxed::Box::new(Text::new(styled, 0, 0, None)));
59 Some(std::boxed::Box::new(msg_box))
60 }
61 DisplayMsg::BashCommand {
62 command,
63 output_lines,
64 status,
65 expanded: _,
66 } => {
67 let mut bash = BashExecution::new(command.clone());
68 for line in output_lines {
69 bash.append_output(line.clone());
70 }
71 match status {
72 BashStatus::Running => {}
73 BashStatus::Complete { exit_code } => {
74 bash.set_complete(*exit_code);
75 }
76 BashStatus::Cancelled => {
77 bash.set_cancelled();
78 }
79 BashStatus::Error(msg) => {
80 bash.set_error(msg.clone());
81 }
82 }
83 Some(std::boxed::Box::new(bash))
84 }
85 DisplayMsg::Info(text) => Some(std::boxed::Box::new(InfoMessageComponent::new(text))),
86 DisplayMsg::Separator => Some(std::boxed::Box::new(Spacer::new(1))),
87 }
88}