systemprompt_cli/commands/infrastructure/services/restart/
single.rs1use crate::cli_settings::CliConfig;
2use crate::shared::CommandOutput;
3use anyhow::{Context, Result};
4use std::sync::Arc;
5use systemprompt_logging::CliService;
6use systemprompt_mcp::services::McpOrchestrator;
7use systemprompt_runtime::AppContext;
8use systemprompt_scheduler::ProcessCleanup;
9
10use super::super::types::RestartOutput;
11
12pub async fn execute_api(config: &CliConfig) -> Result<CommandOutput> {
13 let quiet = config.is_json_output();
14
15 if !quiet {
16 CliService::section("Restarting API Server");
17 }
18
19 let port = super::get_api_port();
20 let Some(pid) = ProcessCleanup::check_port(port) else {
21 if !quiet {
22 CliService::warning("API server is not running");
23 CliService::info("Starting API server...");
24 }
25 super::super::serve::execute(true, false, config).await?;
26 let output = RestartOutput {
27 service_type: "api".to_owned(),
28 service_name: None,
29 restarted_count: 1,
30 failed_count: 0,
31 message: "API server started (was not running)".to_owned(),
32 };
33 return Ok(CommandOutput::card_value("Restart API Server", &output));
34 };
35
36 if !quiet {
37 CliService::info(&format!("Stopping API server (PID: {})...", pid));
38 }
39
40 ProcessCleanup::terminate_gracefully(pid, 100).await;
41 ProcessCleanup::kill_port(port, pid);
42
43 ProcessCleanup::wait_for_port_free(port, 5, 500).await?;
44
45 if !quiet {
46 CliService::success("API server stopped");
47 CliService::info("Starting API server...");
48 }
49
50 super::super::serve::execute(true, false, config).await?;
51
52 let message = "API server restarted successfully".to_owned();
53 if !quiet {
54 CliService::success(&message);
55 }
56
57 let output = RestartOutput {
58 service_type: "api".to_owned(),
59 service_name: None,
60 restarted_count: 1,
61 failed_count: 0,
62 message,
63 };
64
65 Ok(CommandOutput::card_value("Restart API Server", &output))
66}
67
68pub async fn execute_agent(
69 ctx: &Arc<AppContext>,
70 agent: &str,
71 config: &CliConfig,
72) -> Result<CommandOutput> {
73 let quiet = config.is_json_output();
74
75 if !quiet {
76 CliService::section(&format!("Restarting Agent: {}", agent));
77 }
78
79 let orchestrator = super::create_orchestrator(ctx).await?;
80 let name = super::resolve_name(agent).await?;
81 let service_id = orchestrator.restart_agent(&name, None).await?;
82
83 let message = format!(
84 "Agent {} restarted successfully (service ID: {})",
85 agent, service_id
86 );
87 if !quiet {
88 CliService::success(&message);
89 }
90
91 let output = RestartOutput {
92 service_type: "agent".to_owned(),
93 service_name: Some(agent.to_owned()),
94 restarted_count: 1,
95 failed_count: 0,
96 message,
97 };
98
99 Ok(CommandOutput::card_value("Restart Agent", &output))
100}
101
102pub async fn execute_mcp(
103 ctx: &Arc<AppContext>,
104 server_name: &str,
105 build: bool,
106 config: &CliConfig,
107) -> Result<CommandOutput> {
108 let quiet = config.is_json_output();
109 let action = if build {
110 "Building and restarting"
111 } else {
112 "Restarting"
113 };
114
115 if !quiet {
116 CliService::section(&format!("{} MCP Server: {}", action, server_name));
117 }
118
119 let manager = McpOrchestrator::new(
120 Arc::clone(ctx.db_pool()),
121 Arc::clone(ctx.app_paths_arc()),
122 ctx.mcp_registry().clone(),
123 )
124 .context("Failed to initialize MCP manager")?;
125
126 if build {
127 manager
128 .build_and_restart_services(Some(server_name.to_owned()))
129 .await?;
130 } else {
131 manager
132 .restart_services_sync(Some(server_name.to_owned()))
133 .await?;
134 }
135
136 let message = format!("MCP server {} restarted successfully", server_name);
137 if !quiet {
138 CliService::success(&message);
139 }
140
141 let output = RestartOutput {
142 service_type: "mcp".to_owned(),
143 service_name: Some(server_name.to_owned()),
144 restarted_count: 1,
145 failed_count: 0,
146 message,
147 };
148
149 Ok(CommandOutput::card_value("Restart MCP Server", &output))
150}