feat(tui): replace hard‑coded colors with Theme values and propagate Theme through UI rendering
- Introduce `Theme` import and pass a cloned `theme` instance to UI helpers (e.g., `render_editable_textarea`). - Remove direct `Color` usage; UI now derives colors from `Theme` fields for placeholders, selections, ReAct components (thought, action, input, observation, final answer), status badges, operating mode badges, and model info panel. - Extend `Theme` with new color fields for agent ReAct stages, badge foreground/background, and operating mode colors. - Update rendering logic to apply these theme colors throughout the TUI (input panel, help text, status lines, model selection UI, etc.). - Adjust imports to drop unused `Color` references.
This commit is contained in:
@@ -8,6 +8,8 @@ use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub type ThemePalette = Theme;
|
||||
|
||||
/// A complete theme definition for OWLEN TUI
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Theme {
|
||||
@@ -128,6 +130,84 @@ pub struct Theme {
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub info: Color,
|
||||
|
||||
/// Agent action coloring (ReAct THOUGHT)
|
||||
#[serde(default = "Theme::default_agent_thought")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub agent_thought: Color,
|
||||
|
||||
/// Agent action coloring (ReAct ACTION)
|
||||
#[serde(default = "Theme::default_agent_action")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub agent_action: Color,
|
||||
|
||||
/// Agent action coloring (ReAct ACTION_INPUT)
|
||||
#[serde(default = "Theme::default_agent_action_input")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub agent_action_input: Color,
|
||||
|
||||
/// Agent action coloring (ReAct OBSERVATION)
|
||||
#[serde(default = "Theme::default_agent_observation")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub agent_observation: Color,
|
||||
|
||||
/// Agent action coloring (ReAct FINAL_ANSWER)
|
||||
#[serde(default = "Theme::default_agent_final_answer")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub agent_final_answer: Color,
|
||||
|
||||
/// Status badge foreground when agent is running
|
||||
#[serde(default = "Theme::default_agent_badge_running_fg")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub agent_badge_running_fg: Color,
|
||||
|
||||
/// Status badge background when agent is running
|
||||
#[serde(default = "Theme::default_agent_badge_running_bg")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub agent_badge_running_bg: Color,
|
||||
|
||||
/// Status badge foreground when agent mode is idle
|
||||
#[serde(default = "Theme::default_agent_badge_idle_fg")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub agent_badge_idle_fg: Color,
|
||||
|
||||
/// Status badge background when agent mode is idle
|
||||
#[serde(default = "Theme::default_agent_badge_idle_bg")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub agent_badge_idle_bg: Color,
|
||||
|
||||
/// Operating mode badge foreground (Chat)
|
||||
#[serde(default = "Theme::default_operating_chat_fg")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub operating_chat_fg: Color,
|
||||
|
||||
/// Operating mode badge background (Chat)
|
||||
#[serde(default = "Theme::default_operating_chat_bg")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub operating_chat_bg: Color,
|
||||
|
||||
/// Operating mode badge foreground (Code)
|
||||
#[serde(default = "Theme::default_operating_code_fg")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub operating_code_fg: Color,
|
||||
|
||||
/// Operating mode badge background (Code)
|
||||
#[serde(default = "Theme::default_operating_code_bg")]
|
||||
#[serde(deserialize_with = "deserialize_color")]
|
||||
#[serde(serialize_with = "serialize_color")]
|
||||
pub operating_code_bg: Color,
|
||||
}
|
||||
|
||||
impl Default for Theme {
|
||||
@@ -136,6 +216,60 @@ impl Default for Theme {
|
||||
}
|
||||
}
|
||||
|
||||
impl Theme {
|
||||
const fn default_agent_thought() -> Color {
|
||||
Color::LightBlue
|
||||
}
|
||||
|
||||
const fn default_agent_action() -> Color {
|
||||
Color::Yellow
|
||||
}
|
||||
|
||||
const fn default_agent_action_input() -> Color {
|
||||
Color::LightCyan
|
||||
}
|
||||
|
||||
const fn default_agent_observation() -> Color {
|
||||
Color::LightGreen
|
||||
}
|
||||
|
||||
const fn default_agent_final_answer() -> Color {
|
||||
Color::Magenta
|
||||
}
|
||||
|
||||
const fn default_agent_badge_running_fg() -> Color {
|
||||
Color::Black
|
||||
}
|
||||
|
||||
const fn default_agent_badge_running_bg() -> Color {
|
||||
Color::Yellow
|
||||
}
|
||||
|
||||
const fn default_agent_badge_idle_fg() -> Color {
|
||||
Color::Black
|
||||
}
|
||||
|
||||
const fn default_agent_badge_idle_bg() -> Color {
|
||||
Color::Cyan
|
||||
}
|
||||
|
||||
const fn default_operating_chat_fg() -> Color {
|
||||
Color::Black
|
||||
}
|
||||
|
||||
const fn default_operating_chat_bg() -> Color {
|
||||
Color::Blue
|
||||
}
|
||||
|
||||
const fn default_operating_code_fg() -> Color {
|
||||
Color::Black
|
||||
}
|
||||
|
||||
const fn default_operating_code_bg() -> Color {
|
||||
Color::Magenta
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the default themes directory path
|
||||
pub fn default_themes_dir() -> PathBuf {
|
||||
let config_dir = PathBuf::from(shellexpand::tilde(crate::config::DEFAULT_CONFIG_PATH).as_ref())
|
||||
@@ -294,6 +428,19 @@ fn default_dark() -> Theme {
|
||||
placeholder: Color::DarkGray,
|
||||
error: Color::Red,
|
||||
info: Color::LightGreen,
|
||||
agent_thought: Color::LightBlue,
|
||||
agent_action: Color::Yellow,
|
||||
agent_action_input: Color::LightCyan,
|
||||
agent_observation: Color::LightGreen,
|
||||
agent_final_answer: Color::Magenta,
|
||||
agent_badge_running_fg: Color::Black,
|
||||
agent_badge_running_bg: Color::Yellow,
|
||||
agent_badge_idle_fg: Color::Black,
|
||||
agent_badge_idle_bg: Color::Cyan,
|
||||
operating_chat_fg: Color::Black,
|
||||
operating_chat_bg: Color::Blue,
|
||||
operating_code_fg: Color::Black,
|
||||
operating_code_bg: Color::Magenta,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,6 +471,19 @@ fn default_light() -> Theme {
|
||||
placeholder: Color::Gray,
|
||||
error: Color::Rgb(192, 57, 43),
|
||||
info: Color::Green,
|
||||
agent_thought: Color::Rgb(0, 85, 164),
|
||||
agent_action: Color::Rgb(181, 137, 0),
|
||||
agent_action_input: Color::Rgb(0, 139, 139),
|
||||
agent_observation: Color::Rgb(46, 139, 87),
|
||||
agent_final_answer: Color::Rgb(142, 68, 173),
|
||||
agent_badge_running_fg: Color::White,
|
||||
agent_badge_running_bg: Color::Rgb(241, 196, 15),
|
||||
agent_badge_idle_fg: Color::White,
|
||||
agent_badge_idle_bg: Color::Rgb(0, 150, 136),
|
||||
operating_chat_fg: Color::White,
|
||||
operating_chat_bg: Color::Rgb(0, 85, 164),
|
||||
operating_code_fg: Color::White,
|
||||
operating_code_bg: Color::Rgb(142, 68, 173),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,6 +514,19 @@ fn gruvbox() -> Theme {
|
||||
placeholder: Color::Rgb(102, 92, 84),
|
||||
error: Color::Rgb(251, 73, 52), // #fb4934
|
||||
info: Color::Rgb(184, 187, 38),
|
||||
agent_thought: Color::Rgb(131, 165, 152),
|
||||
agent_action: Color::Rgb(250, 189, 47),
|
||||
agent_action_input: Color::Rgb(142, 192, 124),
|
||||
agent_observation: Color::Rgb(184, 187, 38),
|
||||
agent_final_answer: Color::Rgb(211, 134, 155),
|
||||
agent_badge_running_fg: Color::Rgb(40, 40, 40),
|
||||
agent_badge_running_bg: Color::Rgb(250, 189, 47),
|
||||
agent_badge_idle_fg: Color::Rgb(40, 40, 40),
|
||||
agent_badge_idle_bg: Color::Rgb(131, 165, 152),
|
||||
operating_chat_fg: Color::Rgb(40, 40, 40),
|
||||
operating_chat_bg: Color::Rgb(131, 165, 152),
|
||||
operating_code_fg: Color::Rgb(40, 40, 40),
|
||||
operating_code_bg: Color::Rgb(211, 134, 155),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,6 +557,19 @@ fn dracula() -> Theme {
|
||||
placeholder: Color::Rgb(98, 114, 164),
|
||||
error: Color::Rgb(255, 85, 85), // #ff5555
|
||||
info: Color::Rgb(80, 250, 123),
|
||||
agent_thought: Color::Rgb(139, 233, 253),
|
||||
agent_action: Color::Rgb(241, 250, 140),
|
||||
agent_action_input: Color::Rgb(189, 147, 249),
|
||||
agent_observation: Color::Rgb(80, 250, 123),
|
||||
agent_final_answer: Color::Rgb(255, 121, 198),
|
||||
agent_badge_running_fg: Color::Rgb(40, 42, 54),
|
||||
agent_badge_running_bg: Color::Rgb(241, 250, 140),
|
||||
agent_badge_idle_fg: Color::Rgb(40, 42, 54),
|
||||
agent_badge_idle_bg: Color::Rgb(139, 233, 253),
|
||||
operating_chat_fg: Color::Rgb(40, 42, 54),
|
||||
operating_chat_bg: Color::Rgb(139, 233, 253),
|
||||
operating_code_fg: Color::Rgb(40, 42, 54),
|
||||
operating_code_bg: Color::Rgb(189, 147, 249),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,6 +600,19 @@ fn solarized() -> Theme {
|
||||
placeholder: Color::Rgb(88, 110, 117),
|
||||
error: Color::Rgb(220, 50, 47), // #dc322f (red)
|
||||
info: Color::Rgb(133, 153, 0),
|
||||
agent_thought: Color::Rgb(42, 161, 152),
|
||||
agent_action: Color::Rgb(181, 137, 0),
|
||||
agent_action_input: Color::Rgb(38, 139, 210),
|
||||
agent_observation: Color::Rgb(133, 153, 0),
|
||||
agent_final_answer: Color::Rgb(108, 113, 196),
|
||||
agent_badge_running_fg: Color::Rgb(0, 43, 54),
|
||||
agent_badge_running_bg: Color::Rgb(181, 137, 0),
|
||||
agent_badge_idle_fg: Color::Rgb(0, 43, 54),
|
||||
agent_badge_idle_bg: Color::Rgb(42, 161, 152),
|
||||
operating_chat_fg: Color::Rgb(0, 43, 54),
|
||||
operating_chat_bg: Color::Rgb(42, 161, 152),
|
||||
operating_code_fg: Color::Rgb(0, 43, 54),
|
||||
operating_code_bg: Color::Rgb(108, 113, 196),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,6 +643,19 @@ fn midnight_ocean() -> Theme {
|
||||
placeholder: Color::Rgb(110, 118, 129),
|
||||
error: Color::Rgb(248, 81, 73),
|
||||
info: Color::Rgb(158, 206, 106),
|
||||
agent_thought: Color::Rgb(121, 192, 255),
|
||||
agent_action: Color::Rgb(255, 212, 59),
|
||||
agent_action_input: Color::Rgb(137, 221, 255),
|
||||
agent_observation: Color::Rgb(158, 206, 106),
|
||||
agent_final_answer: Color::Rgb(246, 140, 245),
|
||||
agent_badge_running_fg: Color::Rgb(13, 17, 23),
|
||||
agent_badge_running_bg: Color::Rgb(255, 212, 59),
|
||||
agent_badge_idle_fg: Color::Rgb(13, 17, 23),
|
||||
agent_badge_idle_bg: Color::Rgb(137, 221, 255),
|
||||
operating_chat_fg: Color::Rgb(13, 17, 23),
|
||||
operating_chat_bg: Color::Rgb(121, 192, 255),
|
||||
operating_code_fg: Color::Rgb(13, 17, 23),
|
||||
operating_code_bg: Color::Rgb(246, 140, 245),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,6 +686,19 @@ fn rose_pine() -> Theme {
|
||||
placeholder: Color::Rgb(110, 106, 134),
|
||||
error: Color::Rgb(235, 111, 146),
|
||||
info: Color::Rgb(156, 207, 216),
|
||||
agent_thought: Color::Rgb(156, 207, 216),
|
||||
agent_action: Color::Rgb(246, 193, 119),
|
||||
agent_action_input: Color::Rgb(196, 167, 231),
|
||||
agent_observation: Color::Rgb(235, 188, 186),
|
||||
agent_final_answer: Color::Rgb(235, 111, 146),
|
||||
agent_badge_running_fg: Color::Rgb(25, 23, 36),
|
||||
agent_badge_running_bg: Color::Rgb(246, 193, 119),
|
||||
agent_badge_idle_fg: Color::Rgb(25, 23, 36),
|
||||
agent_badge_idle_bg: Color::Rgb(156, 207, 216),
|
||||
operating_chat_fg: Color::Rgb(25, 23, 36),
|
||||
operating_chat_bg: Color::Rgb(156, 207, 216),
|
||||
operating_code_fg: Color::Rgb(25, 23, 36),
|
||||
operating_code_bg: Color::Rgb(196, 167, 231),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,6 +729,19 @@ fn monokai() -> Theme {
|
||||
placeholder: Color::Rgb(117, 113, 94),
|
||||
error: Color::Rgb(249, 38, 114),
|
||||
info: Color::Rgb(166, 226, 46),
|
||||
agent_thought: Color::Rgb(102, 217, 239),
|
||||
agent_action: Color::Rgb(230, 219, 116),
|
||||
agent_action_input: Color::Rgb(174, 129, 255),
|
||||
agent_observation: Color::Rgb(166, 226, 46),
|
||||
agent_final_answer: Color::Rgb(249, 38, 114),
|
||||
agent_badge_running_fg: Color::Rgb(39, 40, 34),
|
||||
agent_badge_running_bg: Color::Rgb(230, 219, 116),
|
||||
agent_badge_idle_fg: Color::Rgb(39, 40, 34),
|
||||
agent_badge_idle_bg: Color::Rgb(102, 217, 239),
|
||||
operating_chat_fg: Color::Rgb(39, 40, 34),
|
||||
operating_chat_bg: Color::Rgb(102, 217, 239),
|
||||
operating_code_fg: Color::Rgb(39, 40, 34),
|
||||
operating_code_bg: Color::Rgb(174, 129, 255),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,6 +772,19 @@ fn material_dark() -> Theme {
|
||||
placeholder: Color::Rgb(84, 110, 122),
|
||||
error: Color::Rgb(240, 113, 120),
|
||||
info: Color::Rgb(195, 232, 141),
|
||||
agent_thought: Color::Rgb(128, 203, 196),
|
||||
agent_action: Color::Rgb(255, 203, 107),
|
||||
agent_action_input: Color::Rgb(199, 146, 234),
|
||||
agent_observation: Color::Rgb(195, 232, 141),
|
||||
agent_final_answer: Color::Rgb(240, 113, 120),
|
||||
agent_badge_running_fg: Color::Rgb(38, 50, 56),
|
||||
agent_badge_running_bg: Color::Rgb(255, 203, 107),
|
||||
agent_badge_idle_fg: Color::Rgb(38, 50, 56),
|
||||
agent_badge_idle_bg: Color::Rgb(128, 203, 196),
|
||||
operating_chat_fg: Color::Rgb(38, 50, 56),
|
||||
operating_chat_bg: Color::Rgb(130, 170, 255),
|
||||
operating_code_fg: Color::Rgb(38, 50, 56),
|
||||
operating_code_bg: Color::Rgb(199, 146, 234),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,6 +815,19 @@ fn material_light() -> Theme {
|
||||
placeholder: Color::Rgb(144, 164, 174),
|
||||
error: Color::Rgb(211, 47, 47),
|
||||
info: Color::Rgb(56, 142, 60),
|
||||
agent_thought: Color::Rgb(68, 138, 255),
|
||||
agent_action: Color::Rgb(245, 124, 0),
|
||||
agent_action_input: Color::Rgb(124, 77, 255),
|
||||
agent_observation: Color::Rgb(56, 142, 60),
|
||||
agent_final_answer: Color::Rgb(211, 47, 47),
|
||||
agent_badge_running_fg: Color::White,
|
||||
agent_badge_running_bg: Color::Rgb(245, 124, 0),
|
||||
agent_badge_idle_fg: Color::White,
|
||||
agent_badge_idle_bg: Color::Rgb(0, 150, 136),
|
||||
operating_chat_fg: Color::White,
|
||||
operating_chat_bg: Color::Rgb(68, 138, 255),
|
||||
operating_code_fg: Color::White,
|
||||
operating_code_bg: Color::Rgb(124, 77, 255),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user