vtcode_llm/
error_display.rs1use anstyle::Style;
7use vtcode_commons::color_policy;
8use vtcode_commons::sanitizer::sanitize_provider_diagnostic;
9use vtcode_commons::styling::Styles;
10
11#[inline]
13fn style_text(style: Style, text: &str) -> String {
14 if !color_policy::color_output_enabled() {
15 return text.to_string();
16 }
17 format!("{}{}{}", Styles::render(&style), text, Styles::render_reset())
18}
19
20#[cold]
22fn style_llm_error(message: &str) -> String {
23 style_text(Styles::error(), message)
24}
25
26#[cold]
28fn style_llm_warning(message: &str) -> String {
29 style_text(Styles::warning(), message)
30}
31
32#[inline]
34fn style_llm_success(message: &str) -> String {
35 style_text(Styles::success(), message)
36}
37
38fn style_provider_name(provider: &str) -> String {
40 let style = match provider.to_lowercase().as_str() {
41 "gemini" => Styles::info(), "openai" => Styles::warning(), "anthropic" => Styles::code(), _ => Styles::debug(), };
46 style_text(style, provider)
47}
48
49#[cold]
51pub fn format_llm_error(provider: &str, error: &str) -> String {
52 let provider_styled = style_provider_name(provider);
53 let safe_error = sanitize_provider_diagnostic(error.as_bytes());
54 let error_styled = style_llm_error(&safe_error);
55 format!("{provider_styled} {error_styled}")
56}
57
58#[cold]
60fn format_llm_warning(provider: &str, warning: &str) -> String {
61 let provider_styled = style_provider_name(provider);
62 let warning_styled = style_llm_warning(warning);
63 format!("{provider_styled} {warning_styled}")
64}
65
66fn format_llm_success(provider: &str, message: &str) -> String {
68 let provider_styled = style_provider_name(provider);
69 let success_styled = style_llm_success(message);
70 format!("{provider_styled} {success_styled}")
71}
72
73#[cold]
76pub fn format_network_error(provider: &str, error: &impl std::fmt::Display) -> String {
77 format_llm_error(provider, &format!("Network error: {error}"))
78}
79
80#[cold]
83pub fn format_parse_error(provider: &str, error: &impl std::fmt::Display) -> String {
84 format_llm_error(provider, &format!("Parse error: {error}"))
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn test_style_llm_error() {
93 let result = style_llm_error("Test error");
94 assert!(!result.is_empty());
95 }
96
97 #[test]
98 fn test_style_llm_warning() {
99 let result = style_llm_warning("Test warning");
100 assert!(!result.is_empty());
101 }
102
103 #[test]
104 fn test_style_llm_success() {
105 let result = style_llm_success("Test success");
106 assert!(!result.is_empty());
107 }
108
109 #[test]
110 fn test_style_provider_name() {
111 let providers = vec!["gemini", "openai", "anthropic", "ollama", "lmstudio", "unknown"];
112 for provider in providers {
113 let result = style_provider_name(provider);
114 assert!(!result.is_empty());
115 }
116 }
117
118 #[test]
119 fn test_format_llm_error() {
120 let result = format_llm_error("gemini", "Connection failed");
121 assert!(result.contains("gemini"));
122 assert!(result.contains("Connection failed"));
123 }
124
125 #[test]
126 fn test_format_llm_warning() {
127 let result = format_llm_warning("openai", "Rate limit approaching");
128 assert!(result.contains("openai"));
129 assert!(result.contains("Rate limit approaching"));
130 }
131
132 #[test]
133 fn test_format_llm_success() {
134 let result = format_llm_success("anthropic", "Request completed");
135 assert!(result.contains("anthropic"));
136 assert!(result.contains("Request completed"));
137 }
138}