systemprompt_cli/commands/cloud/profile/
show_display.rs1use std::collections::HashMap;
10use std::hash::BuildHasher;
11use systemprompt_logging::CliService;
12use systemprompt_manifest::{AgentConfig, AiConfig, SkillsConfig, WebConfig};
13use systemprompt_models::{ContentConfigRaw, Deployment};
14
15use super::show_types::{EnvironmentConfig, FullConfig, SettingsOutput};
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub enum DisplayLine {
19 Section(String),
20 Info(String),
21 KeyValue(String, String),
22}
23
24impl DisplayLine {
25 fn section(title: impl Into<String>) -> Self {
26 Self::Section(title.into())
27 }
28
29 fn info(text: impl Into<String>) -> Self {
30 Self::Info(text.into())
31 }
32
33 fn key_value(label: impl Into<String>, value: impl Into<String>) -> Self {
34 Self::KeyValue(label.into(), value.into())
35 }
36}
37
38pub(super) fn print_formatted_config(config: &FullConfig) {
39 for line in render_formatted_config(config) {
40 match line {
41 DisplayLine::Section(title) => CliService::section(&title),
42 DisplayLine::Info(text) => CliService::info(&text),
43 DisplayLine::KeyValue(label, value) => CliService::key_value(&label, &value),
44 }
45 }
46}
47
48pub fn render_formatted_config(config: &FullConfig) -> Vec<DisplayLine> {
49 let mut lines = Vec::new();
50 if let Some(env) = &config.environment {
51 lines.extend(render_environment_section(env));
52 }
53 if let Some(settings) = &config.settings {
54 lines.extend(render_settings_section(settings));
55 }
56 if let Some(agents) = &config.agents {
57 lines.extend(render_agents_section(agents));
58 }
59 if let Some(mcp_servers) = &config.mcp_servers {
60 lines.extend(render_mcp_section(mcp_servers));
61 }
62 if let Some(skills) = &config.skills {
63 lines.extend(render_skills_section(skills));
64 }
65 if let Some(ai) = &config.ai {
66 lines.extend(render_ai_section(ai));
67 }
68 if let Some(web) = &config.web {
69 lines.extend(render_web_section(web));
70 }
71 if let Some(content) = &config.content {
72 lines.extend(render_content_section(content));
73 }
74 lines
75}
76
77pub fn render_environment_section(env: &EnvironmentConfig) -> Vec<DisplayLine> {
78 vec![
79 DisplayLine::section("Environment Configuration"),
80 DisplayLine::info("Core Settings:"),
81 DisplayLine::key_value(" sitename", &env.core.sitename),
82 DisplayLine::key_value(" host", &env.core.host),
83 DisplayLine::key_value(" port", env.core.port.to_string()),
84 DisplayLine::key_value(" api_server_url", &env.core.api_server_url),
85 DisplayLine::key_value(" api_external_url", &env.core.api_external_url),
86 DisplayLine::key_value(" use_https", env.core.use_https.to_string()),
87 DisplayLine::info("Database:"),
88 DisplayLine::key_value(" type", &env.database.database_type),
89 DisplayLine::key_value(" url", &env.database.database_url),
90 DisplayLine::info("JWT:"),
91 DisplayLine::key_value(" issuer", &env.jwt.issuer),
92 DisplayLine::key_value(" secret", &env.jwt.secret),
93 ]
94}
95
96pub fn render_settings_section(settings: &SettingsOutput) -> Vec<DisplayLine> {
97 vec![
98 DisplayLine::section("Services Settings"),
99 DisplayLine::key_value(
100 " agent_port_range",
101 format!(
102 "{}-{}",
103 settings.agent_port_range.0, settings.agent_port_range.1
104 ),
105 ),
106 DisplayLine::key_value(
107 " mcp_port_range",
108 format!(
109 "{}-{}",
110 settings.mcp_port_range.0, settings.mcp_port_range.1
111 ),
112 ),
113 DisplayLine::key_value(
114 " auto_start_enabled",
115 settings.auto_start_enabled.to_string(),
116 ),
117 ]
118}
119
120pub fn render_agents_section<S: BuildHasher>(
121 agents: &HashMap<String, AgentConfig, S>,
122) -> Vec<DisplayLine> {
123 let mut lines = vec![DisplayLine::section(format!("Agents ({})", agents.len()))];
124 for (name, agent) in agents {
125 lines.push(DisplayLine::info(format!(
126 " {} (port: {}, enabled: {})",
127 name, agent.port, agent.enabled
128 )));
129 lines.push(DisplayLine::key_value(" endpoint", &agent.endpoint));
130 lines.push(DisplayLine::key_value(
131 " display_name",
132 &agent.card.display_name,
133 ));
134 }
135 lines
136}
137
138pub fn render_mcp_section<S: BuildHasher>(
139 mcp_servers: &HashMap<String, Deployment, S>,
140) -> Vec<DisplayLine> {
141 let mut lines = vec![DisplayLine::section(format!(
142 "MCP Servers ({})",
143 mcp_servers.len()
144 ))];
145 for (name, mcp) in mcp_servers {
146 lines.push(DisplayLine::info(format!(
147 " {} ({}, enabled: {})",
148 name,
149 mcp.server_type.as_str(),
150 mcp.enabled
151 )));
152 lines.push(DisplayLine::key_value(
153 " endpoint",
154 mcp.endpoint
155 .as_deref()
156 .unwrap_or("<derived from api_external_url>"),
157 ));
158 if let Some(port) = mcp.port {
159 lines.push(DisplayLine::key_value(" port", port.to_string()));
160 }
161 if let Some(binary) = mcp.binary.as_deref() {
162 lines.push(DisplayLine::key_value(" binary", binary));
163 }
164 }
165 lines
166}
167
168pub fn render_skills_section(skills: &SkillsConfig) -> Vec<DisplayLine> {
169 let mut lines = vec![
170 DisplayLine::section(format!("Skills ({})", skills.skills.len())),
171 DisplayLine::key_value(" enabled", skills.enabled.to_string()),
172 ];
173 for (name, skill) in &skills.skills {
174 lines.push(DisplayLine::info(format!(
175 " {} (enabled: {})",
176 name, skill.enabled
177 )));
178 lines.push(DisplayLine::key_value(" id", skill.id.as_str()));
179 lines.push(DisplayLine::key_value(" name", &skill.name));
180 }
181 lines
182}
183
184pub fn render_ai_section(ai: &AiConfig) -> Vec<DisplayLine> {
185 let mut lines = vec![DisplayLine::section("AI Configuration")];
186 if !ai.default_provider.is_empty() {
187 lines.push(DisplayLine::key_value(
188 " default_provider",
189 &ai.default_provider,
190 ));
191 }
192 for (name, provider) in &ai.providers {
193 lines.push(DisplayLine::info(format!(
194 " {} (enabled: {})",
195 name, provider.enabled
196 )));
197 if !provider.default_model.is_empty() {
198 lines.push(DisplayLine::key_value(
199 " default_model",
200 &provider.default_model,
201 ));
202 }
203 }
204 lines
205}
206
207pub fn render_web_section(web: &WebConfig) -> Vec<DisplayLine> {
208 vec![
209 DisplayLine::section("Web Configuration"),
210 DisplayLine::key_value(" site_name", &web.branding.name),
211 DisplayLine::key_value(" title", &web.branding.title),
212 ]
213}
214
215pub fn render_content_section(content: &ContentConfigRaw) -> Vec<DisplayLine> {
216 let mut lines = vec![DisplayLine::section(format!(
217 "Content Sources ({})",
218 content.content_sources.len()
219 ))];
220 for (name, source) in &content.content_sources {
221 lines.push(DisplayLine::info(format!(
222 " {} (enabled: {})",
223 name, source.enabled
224 )));
225 lines.push(DisplayLine::key_value(" path", &source.path));
226 }
227 lines
228}