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