using Microsoft.AspNetCore.Mvc; namespace ControlCenter.Controllers; /// /// REST API for sending control commands to agents. /// Provides the Command Hub's action endpoints for agent lifecycle control. /// /// API contract for Rex (Frontend): /// /// POST /api/command/stop/{agentId} — Stop/abort an agent's active session /// POST /api/command/restart/{agentId} — Restart an agent /// POST /api/command/steer/{agentId} — Inject a message into an agent's session /// /// /// Commands are forwarded to the OpenClaw Gateway via the /// WebSocket bridge service. The Gateway handles the actual execution. /// [ApiController] [Route("api/[controller]")] public class CommandController : ControllerBase { private readonly ILogger _logger; public CommandController(ILogger logger) { _logger = logger; } /// /// Stops (aborts) an agent's active session. /// Sends an abort command to the OpenClaw Gateway. /// /// The agent identifier to stop. /// Confirmation of the stop command. /// Stop command sent successfully. /// No active session found for the agent. [HttpPost("stop/{agentId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public IActionResult StopAgent(string agentId) { _logger.LogInformation("Stop command received for agent {AgentId}", agentId); // TODO: Forward to Gateway via bridge service // await _bridgeService.SendRpcAsync("sessions.abort", new { sessionKey = ... }); return Ok(new { agentId, command = "stop", status = "sent", timestamp = DateTime.UtcNow.ToString("o") }); } /// /// Restarts an agent by aborting the current session and allowing /// a new one to start on the next incoming message. /// /// The agent identifier to restart. /// Confirmation of the restart command. /// Restart command sent successfully. [HttpPost("restart/{agentId}")] [ProducesResponseType(StatusCodes.Status200OK)] public IActionResult RestartAgent(string agentId) { _logger.LogInformation("Restart command received for agent {AgentId}", agentId); // TODO: Forward to Gateway — abort current session + signal restart return Ok(new { agentId, command = "restart", status = "sent", timestamp = DateTime.UtcNow.ToString("o") }); } /// /// Steers (injects a message into) an agent's active session. /// Used by operators to redirect an agent's task mid-execution. /// /// The agent identifier to steer. /// The steering message to inject. /// Confirmation of the steer command. /// Steer command sent successfully. /// Missing or empty message. [HttpPost("steer/{agentId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public IActionResult SteerAgent(string agentId, [FromBody] SteerRequest request) { if (string.IsNullOrWhiteSpace(request.Message)) { return BadRequest(new { error = "Message is required" }); } _logger.LogInformation("Steer command received for agent {AgentId}: {Message}", agentId, request.Message.Length > 100 ? request.Message[..100] + "..." : request.Message); // TODO: Forward to Gateway via bridge service // await _bridgeService.SendRpcAsync("sessions.steer", new { sessionKey = ..., message = request.Message }); return Ok(new { agentId, command = "steer", message = request.Message, status = "sent", timestamp = DateTime.UtcNow.ToString("o") }); } } /// /// Request body for the steer command. /// /// The message to inject into the agent's session. public record SteerRequest(string Message);