Skip to main content

systemprompt_runtime/startup_validation/
display.rs

1//! CLI rendering of [`StartupValidationReport`] errors and warnings.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use systemprompt_logging::services::cli::BrandColors;
7use systemprompt_logging::{CliService, is_structured_output};
8use systemprompt_traits::{StartupValidationReport, ValidationReport};
9
10pub fn display_validation_report(report: &StartupValidationReport) {
11    CliService::output("");
12    CliService::output(&format!(
13        "{} {}",
14        BrandColors::stopped("✗"),
15        BrandColors::white_bold("Validation Failed")
16    ));
17
18    if let Some(ref path) = report.profile_path {
19        CliService::output(&format!(
20            "  {} {}",
21            BrandColors::dim("Profile:"),
22            BrandColors::highlight(&path.display().to_string())
23        ));
24    }
25
26    CliService::output("");
27    CliService::output(&format!(
28        "  {} error(s) found:",
29        BrandColors::stopped(&report.error_count().to_string())
30    ));
31
32    for domain in &report.domains {
33        display_domain_errors(domain);
34    }
35
36    for ext in &report.extensions {
37        display_extension_errors(ext);
38    }
39
40    CliService::output("");
41}
42
43fn display_domain_errors(domain: &ValidationReport) {
44    if !domain.has_errors() {
45        return;
46    }
47
48    CliService::output("");
49    CliService::output(&format!(
50        "  {} {}",
51        BrandColors::stopped("▸"),
52        BrandColors::white_bold(&domain.domain)
53    ));
54
55    for error in &domain.errors {
56        CliService::output(&format!(
57            "    {} {}",
58            BrandColors::dim("field:"),
59            error.field
60        ));
61        CliService::output(&format!(
62            "    {} {}",
63            BrandColors::dim("error:"),
64            error.message
65        ));
66        if let Some(ref path) = error.path {
67            CliService::output(&format!(
68                "    {} {}",
69                BrandColors::dim("path:"),
70                path.display()
71            ));
72        }
73        if let Some(ref suggestion) = error.suggestion {
74            CliService::output(&format!(
75                "    {} {}",
76                BrandColors::highlight("fix:"),
77                suggestion
78            ));
79        }
80    }
81}
82
83fn display_extension_errors(ext: &ValidationReport) {
84    if !ext.has_errors() {
85        return;
86    }
87
88    CliService::output("");
89    CliService::output(&format!(
90        "  {} {}",
91        BrandColors::stopped("▸"),
92        BrandColors::white_bold(&ext.domain)
93    ));
94
95    for error in &ext.errors {
96        CliService::output(&format!(
97            "    {} {}",
98            BrandColors::dim("field:"),
99            error.field
100        ));
101        CliService::output(&format!(
102            "    {} {}",
103            BrandColors::dim("error:"),
104            error.message
105        ));
106    }
107}
108
109pub fn display_validation_warnings(report: &StartupValidationReport) {
110    if report.warning_count() == 0 {
111        return;
112    }
113
114    if is_structured_output() {
115        buffer_validation_warnings(report);
116        return;
117    }
118
119    CliService::output(&format!(
120        "  {} warning(s):",
121        BrandColors::starting(&report.warning_count().to_string())
122    ));
123
124    for domain in &report.domains {
125        for warning in &domain.warnings {
126            CliService::output("");
127            CliService::output(&format!(
128                "  {} [{}] {}",
129                BrandColors::starting("⚠"),
130                domain.domain,
131                warning.field
132            ));
133            CliService::output(&format!("    {}", warning.message));
134            if let Some(ref suggestion) = warning.suggestion {
135                CliService::output(&format!(
136                    "    {} {}",
137                    BrandColors::highlight("fix:"),
138                    suggestion
139                ));
140            }
141        }
142    }
143
144    CliService::output("");
145}
146
147fn buffer_validation_warnings(report: &StartupValidationReport) {
148    for domain in &report.domains {
149        for warning in &domain.warnings {
150            let suggestion = warning
151                .suggestion
152                .as_ref()
153                .map_or_else(String::new, |fix| format!(" (fix: {fix})"));
154            CliService::warning(&format!(
155                "[{}] {}: {}{suggestion}",
156                domain.domain, warning.field, warning.message
157            ));
158        }
159    }
160}