diff --git a/backend/ControlCenter/ControlCenter.csproj b/backend/ControlCenter/ControlCenter.csproj new file mode 100644 index 0000000..66ebc83 --- /dev/null +++ b/backend/ControlCenter/ControlCenter.csproj @@ -0,0 +1,17 @@ + + + + net9.0 + enable + enable + true + CS1591 + ControlCenter + ControlCenter + + + + + + + \ No newline at end of file diff --git a/backend/ControlCenter/Controllers/AgentsController.cs b/backend/ControlCenter/Controllers/AgentsController.cs new file mode 100644 index 0000000..92da9b3 --- /dev/null +++ b/backend/ControlCenter/Controllers/AgentsController.cs @@ -0,0 +1,71 @@ +using Microsoft.AspNetCore.Mvc; +using ControlCenter.Services; + +namespace ControlCenter.Controllers; + +/// +/// REST API for querying agent fleet status. +/// Provides the initial data load for the Command Hub, +/// while real-time updates flow through the AgentStatus SignalR hub. +/// +/// API contract for Rex (Frontend): +/// +/// GET /api/agents — Returns all known agents with current status +/// GET /api/agents/{agentId} — Returns a specific agent's status +/// +/// +[ApiController] +[Route("api/[controller]")] +public class AgentsController : ControllerBase +{ + private readonly ILogger _logger; + private readonly GatewayEventBridgeService _bridgeService; + + public AgentsController( + ILogger logger, + GatewayEventBridgeService bridgeService) + { + _logger = logger; + _bridgeService = bridgeService; + } + + /// + /// Gets the current fleet status — all known agents with their latest state. + /// This is the initial load endpoint; subsequent updates arrive via SignalR. + /// + /// An array of agent card data for the entire fleet. + /// Returns the fleet snapshot. + [HttpGet] + [ProducesResponseType(typeof(AgentCardData[]), StatusCodes.Status200OK)] + public IActionResult GetAgents() + { + var snapshot = _bridgeService.GetFleetSnapshot(); + _logger.LogDebug("Fleet snapshot requested: {Count} agents", snapshot.Length); + return Ok(snapshot); + } + + /// + /// Gets the current status of a specific agent. + /// + /// The agent identifier, e.g. "otto", "dex". + /// The agent's current card data. + /// Returns the agent's status. + /// Agent not found in the fleet state. + [HttpGet("{agentId}")] + [ProducesResponseType(typeof(AgentCardData), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public IActionResult GetAgent(string agentId) + { + var snapshot = _bridgeService.GetFleetSnapshot(); + var agent = snapshot.FirstOrDefault(a => + a.Id.Equals(agentId, StringComparison.OrdinalIgnoreCase)); + + if (agent is null) + { + _logger.LogWarning("Agent not found: {AgentId}", agentId); + return NotFound(new { error = $"Agent '{agentId}' not found" }); + } + + return Ok(agent); + } +} \ No newline at end of file diff --git a/backend/ControlCenter/Controllers/CommandController.cs b/backend/ControlCenter/Controllers/CommandController.cs new file mode 100644 index 0000000..0dc75bc --- /dev/null +++ b/backend/ControlCenter/Controllers/CommandController.cs @@ -0,0 +1,122 @@ +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); \ No newline at end of file diff --git a/backend/ControlCenter/Controllers/LogsController.cs b/backend/ControlCenter/Controllers/LogsController.cs new file mode 100644 index 0000000..238c345 --- /dev/null +++ b/backend/ControlCenter/Controllers/LogsController.cs @@ -0,0 +1,87 @@ +using Microsoft.AspNetCore.Mvc; + +namespace ControlCenter.Controllers; + +/// +/// REST API for querying agent session logs. +/// Provides historical message and tool call logs for a specific agent. +/// +/// API contract for Rex (Frontend): +/// +/// GET /api/logs/{agentId} — Returns recent logs for an agent +/// GET /api/logs/{agentId}/tools — Returns recent tool calls for an agent +/// +/// +/// Log data is sourced from the OpenClaw Gateway's transcript files. +/// The Gateway's logs.tail RPC provides the raw data, and this +/// controller formats it for the frontend. +/// +[ApiController] +[Route("api/[controller]")] +public class LogsController : ControllerBase +{ + private readonly ILogger _logger; + + public LogsController(ILogger logger) + { + _logger = logger; + } + + /// + /// Gets recent session logs for a specific agent. + /// Returns the last N messages from the agent's active session transcript. + /// + /// The agent identifier, e.g. "otto", "dex". + /// Maximum number of log entries to return (default: 50, max: 200). + /// An array of log entries for the agent. + /// Returns the agent's recent logs. + /// No active session found for the agent. + [HttpGet("{agentId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public IActionResult GetLogs(string agentId, [FromQuery] int limit = 50) + { + limit = Math.Clamp(limit, 1, 200); + + _logger.LogDebug("Logs requested for agent {AgentId}, limit {Limit}", agentId, limit); + + // TODO: Implement log retrieval by calling the Gateway's logs.tail RPC + // or reading transcript files. For now, return an empty array as the + // bridge service will provide this data when fully integrated. + return Ok(new + { + agentId, + logs = Array.Empty(), + count = 0, + hasMore = false + }); + } + + /// + /// Gets recent tool call logs for a specific agent. + /// Returns the last N tool invocations from the agent's session. + /// + /// The agent identifier. + /// Maximum number of tool entries to return (default: 20, max: 100). + /// An array of tool call entries for the agent. + /// Returns the agent's recent tool calls. + /// No active session found for the agent. + [HttpGet("{agentId}/tools")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public IActionResult GetToolLogs(string agentId, [FromQuery] int limit = 20) + { + limit = Math.Clamp(limit, 1, 100); + + _logger.LogDebug("Tool logs requested for agent {AgentId}, limit {Limit}", agentId, limit); + + // TODO: Implement tool log retrieval. Return empty for now. + return Ok(new + { + agentId, + tools = Array.Empty(), + count = 0, + hasMore = false + }); + } +} \ No newline at end of file diff --git a/backend/ControlCenter/Hubs/AgentStatusHub.cs b/backend/ControlCenter/Hubs/AgentStatusHub.cs new file mode 100644 index 0000000..f0d4497 --- /dev/null +++ b/backend/ControlCenter/Hubs/AgentStatusHub.cs @@ -0,0 +1,184 @@ +using Microsoft.AspNetCore.SignalR; + +namespace ControlCenter.Hubs; + +/// +/// SignalR hub for real-time agent status updates in the Command Hub. +/// +/// Usage flow: +/// +/// Client connects to /hubs/agent-status +/// Client calls to subscribe to all agent updates +/// Client calls to subscribe to a specific agent +/// Server pushes +/// and events +/// Client calls for initial state on connect +/// +/// +/// Group naming: +/// +/// Fleet group: fleet — receives all agent updates +/// Agent group: agent:{agentId} — receives updates for one agent +/// +/// +/// Typed client: — all server-to-client +/// calls go through this interface for compile-time safety. +/// +/// Architecture note: This hub bridges OpenClaw Gateway WebSocket events +/// to SignalR clients. A background service () +/// subscribes to Gateway events and pushes them through this hub's extension methods. +/// +public class AgentStatusHub : Hub +{ + private readonly ILogger _logger; + + public AgentStatusHub(ILogger logger) + { + _logger = logger; + } + + /// + /// Adds the calling connection to the fleet group. + /// Once joined, the client will receive all agent status changes + /// and task progress updates across the entire fleet. + /// + public async Task JoinFleet() + { + await Groups.AddToGroupAsync(Context.ConnectionId, FleetGroupName); + _logger.LogDebug("Connection {ConnectionId} joined fleet group", Context.ConnectionId); + } + + /// + /// Removes the calling connection from the fleet group. + /// + public async Task LeaveFleet() + { + await Groups.RemoveFromGroupAsync(Context.ConnectionId, FleetGroupName); + _logger.LogDebug("Connection {ConnectionId} left fleet group", Context.ConnectionId); + } + + /// + /// Adds the calling connection to a specific agent's group. + /// Once joined, the client will receive updates only for that agent. + /// + /// The agent identifier, e.g. "otto", "dex". + /// Thrown if agentId is null or empty. + public async Task JoinAgentGroup(string agentId) + { + if (string.IsNullOrWhiteSpace(agentId)) + throw new HubException("agentId is required"); + + var groupName = AgentGroupName(agentId); + await Groups.AddToGroupAsync(Context.ConnectionId, groupName); + _logger.LogDebug("Connection {ConnectionId} joined agent group {GroupName}", + Context.ConnectionId, groupName); + } + + /// + /// Removes the calling connection from a specific agent's group. + /// + /// The agent identifier. + public async Task LeaveAgentGroup(string agentId) + { + if (string.IsNullOrWhiteSpace(agentId)) return; + + var groupName = AgentGroupName(agentId); + await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName); + } + + /// + /// Returns a snapshot of the current fleet state. + /// Called by clients on initial connection to get the full picture + /// before incremental updates begin arriving. + /// + /// An array of representing all known agents. + public Task GetFleetSnapshot() + { + // The fleet state is managed by the GatewayEventBridgeService. + // For now, return an empty array — the bridge service will push + // updates as they arrive from the Gateway. + _logger.LogDebug("Fleet snapshot requested by {ConnectionId}", Context.ConnectionId); + return Task.FromResult(Array.Empty()); + } + + /// + /// Overrides to perform cleanup. + /// SignalR automatically removes disconnected connections from all groups. + /// + /// Exception that caused the disconnection, if any. + public override Task OnDisconnectedAsync(Exception? exception) + { + _logger.LogDebug("Connection {ConnectionId} disconnected", Context.ConnectionId); + return base.OnDisconnectedAsync(exception); + } + + /// + /// The SignalR group name for the entire fleet (all agents). + /// + internal const string FleetGroupName = "fleet"; + + /// + /// Returns the SignalR group name for a specific agent. + /// Format: agent:{agentId} (lowercase for consistency). + /// + /// The agent identifier. + internal static string AgentGroupName(string agentId) => + $"agent:{agentId.ToLowerInvariant()}"; +} + +/// +/// Extension methods for pushing real-time agent updates through +/// the of . +/// +/// These methods are intended to be called from background services +/// (e.g., ) or other +/// server-side code that detects an agent state change. +/// +public static class AgentStatusHubExtensions +{ + /// + /// Pushes an agent status change to all clients subscribed to + /// the fleet group and the specific agent's group. + /// + /// Call this from any background service when an agent's + /// operational status changes (e.g., the Gateway reports a + /// session transition from "running" to "done"). + /// + /// The hub context injected via DI. + /// The agent status update payload. + /// A Task that completes when the message has been sent to all group members. + public static async Task PushAgentStatusAsync( + this IHubContext hubContext, + AgentStatusUpdate update) + { + // Broadcast to the fleet group (all subscribers) + await hubContext.Clients.Group(AgentStatusHub.FleetGroupName) + .AgentStatusChanged(update); + + // Also push to the specific agent's group + var agentGroup = AgentStatusHub.AgentGroupName(update.AgentId); + await hubContext.Clients.Group(agentGroup) + .AgentStatusChanged(update); + } + + /// + /// Pushes a task progress update to all clients subscribed to + /// the fleet group and the specific agent's group. + /// + /// The hub context injected via DI. + /// The task progress update payload. + /// A Task that completes when the message has been sent to all group members. + public static async Task PushTaskProgressAsync( + this IHubContext hubContext, + TaskProgressUpdate progress) + { + // Broadcast to the fleet group + await hubContext.Clients.Group(AgentStatusHub.FleetGroupName) + .AgentTaskProgress(progress); + + // Also push to the specific agent's group + var agentGroup = AgentStatusHub.AgentGroupName(progress.AgentId); + await hubContext.Clients.Group(agentGroup) + .AgentTaskProgress(progress); + } +} \ No newline at end of file diff --git a/backend/ControlCenter/Hubs/IAgentStatusClient.cs b/backend/ControlCenter/Hubs/IAgentStatusClient.cs new file mode 100644 index 0000000..4f3e1ea --- /dev/null +++ b/backend/ControlCenter/Hubs/IAgentStatusClient.cs @@ -0,0 +1,30 @@ +namespace ControlCenter.Hubs; + +/// +/// Strongly-typed client interface for the AgentStatus SignalR hub. +/// Defines the methods the server can invoke on connected clients +/// to push real-time agent status and task progress updates. +/// +/// All server-to-client calls go through this interface for +/// compile-time safety — matching the pattern used by the +/// Extrudex PrinterHub. +/// +public interface IAgentStatusClient +{ + /// + /// Pushes an agent status change to all subscribed clients. + /// Fired whenever an agent's operational status changes + /// (e.g., idle → active, active → thinking, active → error). + /// + /// The full status update payload. + /// A Task that completes when the client has processed the update. + Task AgentStatusChanged(AgentStatusUpdate update); + + /// + /// Pushes a task progress update to all subscribed clients. + /// Fired when an agent reports progress on its current task. + /// + /// The task progress update payload. + /// A Task that completes when the client has processed the update. + Task AgentTaskProgress(TaskProgressUpdate progress); +} \ No newline at end of file diff --git a/backend/ControlCenter/Hubs/Models/AgentStatusModels.cs b/backend/ControlCenter/Hubs/Models/AgentStatusModels.cs new file mode 100644 index 0000000..3c9c97d --- /dev/null +++ b/backend/ControlCenter/Hubs/Models/AgentStatusModels.cs @@ -0,0 +1,92 @@ +namespace ControlCenter; + +/// +/// Agent operational status derived from OpenClaw Gateway session activity. +/// Maps to the frontend AgentStatus type: 'active' | 'idle' | 'thinking' | 'error'. +/// +public enum AgentStatus +{ + /// Agent is currently processing a turn. + Active, + + /// Agent completed its last turn; no active work. + Idle, + + /// LLM call in flight; tokens streaming. + Thinking, + + /// Agent encountered an unhandled error. + Error +} + +/// +/// Extended lifecycle status including offline — not all agents have active sessions. +/// Used internally; clients only see (offline maps to idle). +/// +public enum AgentLifecycleStatus +{ + Active, + Idle, + Thinking, + Error, + Offline +} + +/// +/// Pushed to SignalR clients when an agent's status changes. +/// Matches the TypeScript AgentStatusUpdate interface from the design spec. +/// +/// Agent identifier, e.g. "otto", "dex". +/// Human-readable name, e.g. "Otto". +/// Role description, e.g. "Orchestrator Agent". +/// Current operational status. +/// Description of the current task, if any. +/// Full session key, e.g. "agent:otto:telegram:direct:8787451565". +/// Channel the agent is operating on, e.g. "telegram". +/// ISO 8601 timestamp of last activity. +/// Error message when status is 'error'. +public record AgentStatusUpdate( + string AgentId, + string DisplayName, + string Role, + string Status, + string? CurrentTask, + string SessionKey, + string Channel, + string LastActivity, + string? ErrorMessage = null +); + +/// +/// Pushed to SignalR clients when an agent's task progress updates. +/// Matches the TypeScript TaskProgressUpdate interface from the design spec. +/// +/// Agent identifier. +/// Description of the current task. +/// Task progress percentage (0–100), if trackable. +/// Elapsed time string, e.g. "04m 12s". +public record TaskProgressUpdate( + string AgentId, + string TaskDescription, + int? Progress, + string? Elapsed +); + +/// +/// Snapshot of an agent's full card data, sent on initial connection +/// or when the fleet state is requested. +/// Matches the TypeScript AgentCardData interface from the design spec. +/// +public record AgentCardData( + string Id, + string DisplayName, + string Role, + string Status, + string? CurrentTask, + int? TaskProgress, + string? TaskElapsed, + string SessionKey, + string Channel, + string LastActivity, + string? ErrorMessage +); \ No newline at end of file diff --git a/backend/ControlCenter/Program.cs b/backend/ControlCenter/Program.cs new file mode 100644 index 0000000..757b20a --- /dev/null +++ b/backend/ControlCenter/Program.cs @@ -0,0 +1,72 @@ +using System.Reflection; +using ControlCenter.Hubs; +using ControlCenter.Services; + +var builder = WebApplication.CreateBuilder(args); + +// ── API Services ─────────────────────────────────────────── +builder.Services.AddControllers(); +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(c => +{ + c.SwaggerDoc("v1", new() + { + Title = "Control Center API", + Version = "v1", + Description = "OpenClaw Control Center — Command Hub backend with SignalR real-time updates" + }); + + // Include XML doc comments in Swagger output + var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + if (File.Exists(xmlPath)) + { + c.IncludeXmlComments(xmlPath); + } +}); + +// ── CORS (kiosk + remote browser) ───────────────────────── +// The Control Center frontend runs on a different origin than the backend. +// SignalR requires credentials for WebSocket transport, so we use +// specific origins rather than AllowAnyOrigin. +var corsOrigins = builder.Configuration.GetSection("Cors:AllowedOrigins") + .Get() ?? new[] { "http://localhost:4200", "http://localhost:5000" }; + +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy(policy => + { + policy.WithOrigins(corsOrigins) + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials(); // Required for SignalR WebSocket + }); +}); + +// ── SignalR (real-time agent status updates) ─────────────── +builder.Services.AddSignalR(); + +// ── Gateway Bridge Service ──────────────────────────────── +// Background service that connects to the OpenClaw Gateway WebSocket +// and bridges events to the AgentStatus SignalR hub. +builder.Services.AddSingleton(); +builder.Services.AddHostedService(sp => sp.GetRequiredService()); + +var app = builder.Build(); + +// ── Middleware ────────────────────────────────────────────── +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseCors(); +app.UseAuthorization(); +app.MapControllers(); + +// ── Hub Endpoints ─────────────────────────────────────────── +// Agent status hub at /hubs/agent-status (matches the design spec) +app.MapHub("/hubs/agent-status"); + +app.Run(); \ No newline at end of file diff --git a/backend/ControlCenter/Properties/launchSettings.json b/backend/ControlCenter/Properties/launchSettings.json new file mode 100644 index 0000000..5596756 --- /dev/null +++ b/backend/ControlCenter/Properties/launchSettings.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5053", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/backend/ControlCenter/Services/GatewayEventBridgeService.cs b/backend/ControlCenter/Services/GatewayEventBridgeService.cs new file mode 100644 index 0000000..0f37285 --- /dev/null +++ b/backend/ControlCenter/Services/GatewayEventBridgeService.cs @@ -0,0 +1,523 @@ +using System.Collections.Concurrent; +using System.Net.WebSockets; +using System.Text; +using System.Text.Json; +using ControlCenter.Hubs; +using Microsoft.AspNetCore.SignalR; + +namespace ControlCenter.Services; + +/// +/// Background service that connects to the OpenClaw Gateway WebSocket +/// and bridges Gateway events to the . +/// +/// Architecture: +/// +/// Connects to the Gateway WS endpoint (configurable via appsettings) +/// Handles the v3 protocol handshake (challenge → connect → hello-ok) +/// Subscribes to sessions.changed and related events +/// Translates session state changes into +/// and objects +/// Pushes updates through the SignalR hub +/// +/// +/// This is the server-side bridge that allows Angular clients to +/// receive real-time updates via SignalR instead of connecting directly +/// to the Gateway WebSocket. +/// +public class GatewayEventBridgeService : BackgroundService +{ + private readonly ILogger _logger; + private readonly IHubContext _hubContext; + private readonly IConfiguration _configuration; + + /// + /// In-memory fleet state — maps agent IDs to their latest card data. + /// Updated on every sessions.changed event from the Gateway. + /// + private readonly ConcurrentDictionary _fleetState = new(); + + /// + /// Known agent roles for display in the Command Hub. + /// Maps agent IDs to their functional descriptions. + /// + private static readonly Dictionary AgentRoles = new() + { + ["main"] = "Primary Assistant", + ["otto"] = "Orchestrator Agent", + ["dave"] = "Network Admin Agent", + ["bob"] = "Content Writer Agent", + ["stuart"] = "Image & Creative Agent", + ["phil"] = "Home Automation Agent", + ["carl"] = "Security Agent", + ["larry"] = "Business Agent", + ["mel"] = "E-Commerce Agent", + ["norbert"] = "Product Agent", + ["jerry"] = "Market Research Agent", + ["rex"] = "Frontend Dev Agent", + ["dex"] = "Backend Dev Agent", + ["hex"] = "Database Agent", + ["pip"] = "Raspberry Pi Agent", + ["nano"] = "ESP32/Firmware Agent", + ["axiom"] = "Utility Agent", + ["bonnie"] = "Music Agent", + ["sketch"] = "UI/UX Design Agent", + ["flip"] = "Mobile Dev Agent", + ["buzz"] = "SEO Agent", + ["aries"] = "Companion Agent" + }; + + /// + /// Maps OpenClaw session status to . + /// + private static string MapSessionStatus(string? sessionStatus) => sessionStatus switch + { + "running" => "active", + "streaming" => "thinking", + "error" or "aborted" => "error", + "done" => "idle", + _ => "idle" + }; + + public GatewayEventBridgeService( + ILogger logger, + IHubContext hubContext, + IConfiguration configuration) + { + _logger = logger; + _hubContext = hubContext; + _configuration = configuration; + } + + /// + /// Returns the current fleet state snapshot. + /// Used by the hub's GetFleetSnapshot method and by the + /// AgentsController REST endpoint. + /// + public AgentCardData[] GetFleetSnapshot() => + _fleetState.Values.ToArray(); + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + _logger.LogInformation("Gateway Event Bridge service starting"); + + while (!stoppingToken.IsCancellationRequested) + { + try + { + await ConnectAndListenAsync(stoppingToken); + } + catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested) + { + _logger.LogInformation("Gateway Event Bridge service stopping"); + break; + } + catch (Exception ex) + { + _logger.LogError(ex, "Gateway connection lost, reconnecting in 5 seconds..."); + await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken); + } + } + } + + /// + /// Connects to the OpenClaw Gateway WebSocket and processes events + /// until the connection is lost or cancellation is requested. + /// + private async Task ConnectAndListenAsync(CancellationToken stoppingToken) + { + var gatewayUrl = _configuration["Gateway:WebSocketUrl"] + ?? "ws://localhost:3271/ws"; + var authToken = _configuration["Gateway:AuthToken"] ?? string.Empty; + + _logger.LogInformation("Connecting to Gateway at {Url}", gatewayUrl); + + using var ws = new ClientWebSocket(); + + // Set auth header if available + if (!string.IsNullOrEmpty(authToken)) + { + ws.Options.SetRequestHeader("Authorization", $"Bearer {authToken}"); + } + + await ws.ConnectAsync(new Uri(gatewayUrl), stoppingToken); + _logger.LogInformation("Connected to Gateway WebSocket"); + + // Start receiving messages + await ReceiveMessagesAsync(ws, stoppingToken); + } + + /// + /// Receives and processes WebSocket messages from the Gateway. + /// Handles the v3 protocol handshake and dispatches events. + /// + private async Task ReceiveMessagesAsync(ClientWebSocket ws, CancellationToken stoppingToken) + { + var buffer = new byte[8192]; + var messageBuilder = new StringBuilder(); + + while (ws.State == WebSocketState.Open && !stoppingToken.IsCancellationRequested) + { + WebSocketReceiveResult result; + try + { + result = await ws.ReceiveAsync(buffer, stoppingToken); + } + catch (WebSocketException ex) + { + _logger.LogWarning(ex, "WebSocket receive error"); + break; + } + + if (result.MessageType == WebSocketMessageType.Close) + { + _logger.LogInformation("Gateway WebSocket closed by server"); + break; + } + + messageBuilder.Append(Encoding.UTF8.GetString(buffer, 0, result.Count)); + + if (result.EndOfMessage) + { + var message = messageBuilder.ToString(); + messageBuilder.Clear(); + await ProcessMessageAsync(ws, message, stoppingToken); + } + } + } + + /// + /// Processes a single WebSocket message from the Gateway. + /// Routes based on the message type: event, response, or challenge. + /// + private async Task ProcessMessageAsync( + ClientWebSocket ws, string message, CancellationToken stoppingToken) + { + try + { + using var doc = JsonDocument.Parse(message); + var root = doc.RootElement; + + var type = root.GetProperty("type").GetString(); + + switch (type) + { + case "event": + await HandleGatewayEventAsync(root); + break; + + case "res": + HandleGatewayResponse(root); + break; + } + + // Special handling for connect.challenge events + if (root.TryGetProperty("event", out var eventName) && + eventName.GetString() == "connect.challenge") + { + await HandleConnectChallengeAsync(ws, root, stoppingToken); + } + } + catch (JsonException ex) + { + _logger.LogWarning(ex, "Failed to parse Gateway message: {Message}", + message.Length > 200 ? message[..200] + "..." : message); + } + } + + /// + /// Handles the Gateway connect.challenge event by sending + /// a connect request with authentication credentials. + /// + private async Task HandleConnectChallengeAsync( + ClientWebSocket ws, JsonElement root, CancellationToken stoppingToken) + { + _logger.LogInformation("Received connect.challenge from Gateway"); + + var connectRequest = new + { + type = "req", + id = $"bridge-{Guid.NewGuid():N}", + method = "connect", + @params = new + { + minProtocol = 3, + maxProtocol = 3, + client = new + { + id = "control-center-backend", + version = "1.0.0", + platform = "server", + mode = "operator" + }, + role = "operator", + scopes = new[] { "operator.read", "operator.write" }, + auth = new + { + token = _configuration["Gateway:AuthToken"] ?? string.Empty + }, + locale = "en-US", + userAgent = "control-center-backend/1.0.0" + } + }; + + var json = JsonSerializer.Serialize(connectRequest); + var bytes = Encoding.UTF8.GetBytes(json); + await ws.SendAsync(bytes, WebSocketMessageType.Text, true, stoppingToken); + } + + /// + /// Handles a Gateway event message by dispatching to the + /// appropriate handler based on event name. + /// + private async Task HandleGatewayEventAsync(JsonElement root) + { + if (!root.TryGetProperty("event", out var eventProp)) return; + var eventName = eventProp.GetString(); + + _logger.LogDebug("Gateway event: {Event}", eventName); + + switch (eventName) + { + case "sessions.changed": + await HandleSessionsChangedAsync(root); + break; + + case "session.message": + HandleSessionMessage(root); + break; + + case "session.tool": + HandleSessionTool(root); + break; + + case "health": + HandleHealthEvent(root); + break; + } + } + + /// + /// Handles a sessions.changed event from the Gateway. + /// Updates the fleet state and pushes status changes through SignalR. + /// + private async Task HandleSessionsChangedAsync(JsonElement root) + { + if (!root.TryGetProperty("payload", out var payload)) return; + + // The payload may contain a snapshot of all sessions + if (payload.TryGetProperty("snapshot", out var snapshot) && + snapshot.ValueKind == JsonValueKind.Array) + { + foreach (var session in snapshot.EnumerateArray()) + { + var cardData = SessionToCardData(session); + if (cardData is null) continue; + + _fleetState[cardData.Id] = cardData; + + var update = new AgentStatusUpdate( + AgentId: cardData.Id, + DisplayName: cardData.DisplayName, + Role: cardData.Role, + Status: cardData.Status, + CurrentTask: cardData.CurrentTask, + SessionKey: cardData.SessionKey, + Channel: cardData.Channel, + LastActivity: cardData.LastActivity, + ErrorMessage: cardData.ErrorMessage + ); + + await _hubContext.PushAgentStatusAsync(update); + } + } + + // Handle individual updates/added/removed + if (payload.TryGetProperty("updated", out var updated) && + updated.ValueKind == JsonValueKind.Array) + { + foreach (var sessionKey in updated.EnumerateArray()) + { + _logger.LogDebug("Session updated: {Key}", sessionKey.GetString()); + } + } + } + + /// + /// Handles a session.message event. Updates the agent's last activity + /// and pushes a status update if the status changed. + /// + private void HandleSessionMessage(JsonElement root) + { + if (!root.TryGetProperty("payload", out var payload)) return; + if (!payload.TryGetProperty("sessionKey", out var sessionKeyProp)) return; + + var sessionKey = sessionKeyProp.GetString() ?? string.Empty; + var agentId = ExtractAgentId(sessionKey); + + if (string.IsNullOrEmpty(agentId)) return; + + // Update last activity timestamp + if (_fleetState.TryGetValue(agentId, out var existing)) + { + _fleetState[agentId] = existing with + { + LastActivity = DateTime.UtcNow.ToString("o"), + Status = "active" + }; + } + } + + /// + /// Handles a session.tool event. Extracts tool progress information + /// and pushes a through SignalR. + /// + private void HandleSessionTool(JsonElement root) + { + if (!root.TryGetProperty("payload", out var payload)) return; + if (!payload.TryGetProperty("sessionKey", out var sessionKeyProp)) return; + + var sessionKey = sessionKeyProp.GetString() ?? string.Empty; + var agentId = ExtractAgentId(sessionKey); + + if (string.IsNullOrEmpty(agentId)) return; + + var toolName = payload.TryGetProperty("toolName", out var tn) ? tn.GetString() : null; + var toolStatus = payload.TryGetProperty("status", out var ts) ? ts.GetString() : null; + + if (toolName is null || toolStatus is null) return; + + var progress = toolStatus switch + { + "started" => 0, + "completed" => 100, + _ => (int?)null + }; + + var update = new TaskProgressUpdate( + AgentId: agentId, + TaskDescription: $"{toolName} ({toolStatus})", + Progress: progress, + Elapsed: null + ); + + // Fire and forget — don't block the event loop + _ = _hubContext.PushTaskProgressAsync(update); + } + + /// + /// Handles a health event from the Gateway. + /// Logs the health status for diagnostics. + /// + private void HandleHealthEvent(JsonElement root) + { + if (!root.TryGetProperty("payload", out var payload)) return; + + var ok = payload.TryGetProperty("ok", out var okProp) && okProp.GetBoolean(); + var status = payload.TryGetProperty("status", out var s) ? s.GetString() : "unknown"; + + _logger.LogInformation("Gateway health: ok={Ok}, status={Status}", ok, status); + } + + /// + /// Handles a Gateway response message. Currently only logs for diagnostics. + /// + private void HandleGatewayResponse(JsonElement root) + { + if (root.TryGetProperty("ok", out var okProp) && okProp.GetBoolean()) + { + _logger.LogDebug("Gateway RPC response OK"); + + // Check for hello-ok after connect + if (root.TryGetProperty("payload", out var payload) && + payload.TryGetProperty("type", out var typeProp) && + typeProp.GetString() == "hello-ok") + { + _logger.LogInformation("Gateway handshake complete (hello-ok received)"); + } + } + else if (root.TryGetProperty("error", out var error)) + { + var errorMsg = error.TryGetProperty("message", out var msg) + ? msg.GetString() : "unknown error"; + _logger.LogWarning("Gateway RPC error: {Error}", errorMsg); + } + } + + /// + /// Converts a raw Gateway session JSON element into an + /// record. + /// + private AgentCardData? SessionToCardData(JsonElement session) + { + // Extract agent ID from session key or agentId field + string? agentId = null; + if (session.TryGetProperty("agentId", out var aid)) + agentId = aid.GetString(); + else if (session.TryGetProperty("key", out var key)) + agentId = ExtractAgentId(key.GetString() ?? string.Empty); + + if (string.IsNullOrEmpty(agentId)) return null; + + var sessionKey = session.TryGetProperty("key", out var sk) + ? sk.GetString() ?? string.Empty : string.Empty; + + var status = session.TryGetProperty("status", out var s) + ? MapSessionStatus(s.GetString()) : "idle"; + + var channel = ExtractChannel(session); + + var lastActivity = session.TryGetProperty("updatedAt", out var ua) + ? DateTimeOffset.FromUnixTimeMilliseconds(ua.GetInt64()).ToString("o") + : DateTime.UtcNow.ToString("o"); + + var displayName = char.ToUpperInvariant(agentId![0]) + agentId[1..]; + var role = AgentRoles.GetValueOrDefault(agentId!, "Agent"); + + return new AgentCardData( + Id: agentId!, + DisplayName: displayName, + Role: role, + Status: status, + CurrentTask: null, + TaskProgress: null, + TaskElapsed: null, + SessionKey: sessionKey, + Channel: channel, + LastActivity: lastActivity, + ErrorMessage: status == "error" ? "Agent encountered an error" : null + ); + } + + /// + /// Extracts the agent ID from a session key. + /// Session key format: "agent:{agentId}:{channel}:..." + /// + private static string? ExtractAgentId(string sessionKey) + { + if (string.IsNullOrEmpty(sessionKey)) return null; + + var parts = sessionKey.Split(':'); + if (parts.Length >= 2 && parts[0] == "agent") + return parts[1]; + + return null; + } + + /// + /// Extracts the channel from a session element. + /// + private static string ExtractChannel(JsonElement session) + { + // Try direct "channel" property + if (session.TryGetProperty("channel", out var ch)) + return ch.GetString() ?? "unknown"; + + // Try origin.provider + if (session.TryGetProperty("origin", out var origin) && + origin.TryGetProperty("provider", out var provider)) + return provider.GetString() ?? "unknown"; + + return "unknown"; + } +} \ No newline at end of file diff --git a/backend/ControlCenter/appsettings.Development.json b/backend/ControlCenter/appsettings.Development.json new file mode 100644 index 0000000..626b82e --- /dev/null +++ b/backend/ControlCenter/appsettings.Development.json @@ -0,0 +1,19 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "Microsoft.AspNetCore": "Information", + "ControlCenter": "Debug" + } + }, + "Gateway": { + "WebSocketUrl": "ws://localhost:3271/ws", + "AuthToken": "" + }, + "Cors": { + "AllowedOrigins": [ + "http://localhost:4200", + "http://localhost:5000" + ] + } +} \ No newline at end of file diff --git a/backend/ControlCenter/appsettings.json b/backend/ControlCenter/appsettings.json new file mode 100644 index 0000000..60f801d --- /dev/null +++ b/backend/ControlCenter/appsettings.json @@ -0,0 +1,22 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "ControlCenter": "Debug" + } + }, + "AllowedHosts": "*", + + "Gateway": { + "WebSocketUrl": "ws://localhost:3271/ws", + "AuthToken": "" + }, + + "Cors": { + "AllowedOrigins": [ + "http://localhost:4200", + "http://localhost:5000" + ] + } +} \ No newline at end of file diff --git a/backend/ControlCenter/bin/Debug/net9.0/ControlCenter b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter new file mode 100755 index 0000000..ef5779a Binary files /dev/null and b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter differ diff --git a/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.deps.json b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.deps.json new file mode 100644 index 0000000..d8d7dee --- /dev/null +++ b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.deps.json @@ -0,0 +1,126 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v9.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v9.0": { + "ControlCenter/1.0.0": { + "dependencies": { + "Swashbuckle.AspNetCore": "10.1.7" + }, + "runtime": { + "ControlCenter.dll": {} + } + }, + "Microsoft.Extensions.ApiDescription.Server/9.0.0": {}, + "Microsoft.OpenApi/2.4.1": { + "dependencies": { + "System.Text.Json": "8.0.5" + }, + "runtime": { + "lib/net8.0/Microsoft.OpenApi.dll": { + "assemblyVersion": "2.4.1.0", + "fileVersion": "2.4.1.0" + } + } + }, + "Swashbuckle.AspNetCore/10.1.7": { + "dependencies": { + "Microsoft.Extensions.ApiDescription.Server": "9.0.0", + "Swashbuckle.AspNetCore.Swagger": "10.1.7", + "Swashbuckle.AspNetCore.SwaggerGen": "10.1.7", + "Swashbuckle.AspNetCore.SwaggerUI": "10.1.7" + } + }, + "Swashbuckle.AspNetCore.Swagger/10.1.7": { + "dependencies": { + "Microsoft.OpenApi": "2.4.1" + }, + "runtime": { + "lib/net9.0/Swashbuckle.AspNetCore.Swagger.dll": { + "assemblyVersion": "10.1.7.0", + "fileVersion": "10.1.7.2427" + } + } + }, + "Swashbuckle.AspNetCore.SwaggerGen/10.1.7": { + "dependencies": { + "Swashbuckle.AspNetCore.Swagger": "10.1.7" + }, + "runtime": { + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll": { + "assemblyVersion": "10.1.7.0", + "fileVersion": "10.1.7.2427" + } + } + }, + "Swashbuckle.AspNetCore.SwaggerUI/10.1.7": { + "runtime": { + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll": { + "assemblyVersion": "10.1.7.0", + "fileVersion": "10.1.7.2427" + } + } + }, + "System.Text.Json/8.0.5": {} + } + }, + "libraries": { + "ControlCenter/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "Microsoft.Extensions.ApiDescription.Server/9.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-1Kzzf7pRey40VaUkHN9/uWxrKVkLu2AQjt+GVeeKLLpiEHAJ1xZRsLSh4ZZYEnyS7Kt2OBOPmsXNdU+wbcOl5w==", + "path": "microsoft.extensions.apidescription.server/9.0.0", + "hashPath": "microsoft.extensions.apidescription.server.9.0.0.nupkg.sha512" + }, + "Microsoft.OpenApi/2.4.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-u7QhXCISMQuab3flasb1hoaiERmUqyWsW7tmQODyILoQ7mJV5IRGM+2KKZYo0QUfC13evEOcHAb6TPWgqEQtrw==", + "path": "microsoft.openapi/2.4.1", + "hashPath": "microsoft.openapi.2.4.1.nupkg.sha512" + }, + "Swashbuckle.AspNetCore/10.1.7": { + "type": "package", + "serviceable": true, + "sha512": "sha512-vgef8DPT411JU5JjHiDbr0WOxsIVuAvegPGtqmm4Na4JRl/264dfBJcGkiPHsAr5P+Vda+qN1rZKRtBl1rF9aA==", + "path": "swashbuckle.aspnetcore/10.1.7", + "hashPath": "swashbuckle.aspnetcore.10.1.7.nupkg.sha512" + }, + "Swashbuckle.AspNetCore.Swagger/10.1.7": { + "type": "package", + "serviceable": true, + "sha512": "sha512-EjLibt/d/QuRv170GoihTbcPUpgzSFm2WKHhnGJFZQ03JYzfuitsM79azaAR8NBwRunU7yScSX6HRE5JUlrEMQ==", + "path": "swashbuckle.aspnetcore.swagger/10.1.7", + "hashPath": "swashbuckle.aspnetcore.swagger.10.1.7.nupkg.sha512" + }, + "Swashbuckle.AspNetCore.SwaggerGen/10.1.7": { + "type": "package", + "serviceable": true, + "sha512": "sha512-PuubO9BjvNn6U3D9kLpuWKY1JtziWw7SsGBq0age1E50uQjQ8Fzl8s0EwzrLfANqYJNgDnJi9l7N1QxcGVB2Zw==", + "path": "swashbuckle.aspnetcore.swaggergen/10.1.7", + "hashPath": "swashbuckle.aspnetcore.swaggergen.10.1.7.nupkg.sha512" + }, + "Swashbuckle.AspNetCore.SwaggerUI/10.1.7": { + "type": "package", + "serviceable": true, + "sha512": "sha512-iJo3ODyUb/M8Vm8AH1r9y9iAba0w95xsCn3zFVl96ISRHbTDWxi+l7oFVCZqUEdjd97B8VMDPnMliWAdomR8uw==", + "path": "swashbuckle.aspnetcore.swaggerui/10.1.7", + "hashPath": "swashbuckle.aspnetcore.swaggerui.10.1.7.nupkg.sha512" + }, + "System.Text.Json/8.0.5": { + "type": "package", + "serviceable": true, + "sha512": "sha512-0f1B50Ss7rqxXiaBJyzUu9bWFOO2/zSlifZ/UNMdiIpDYe4cY4LQQicP4nirK1OS31I43rn062UIJ1Q9bpmHpg==", + "path": "system.text.json/8.0.5", + "hashPath": "system.text.json.8.0.5.nupkg.sha512" + } + } +} \ No newline at end of file diff --git a/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.dll b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.dll new file mode 100644 index 0000000..5a464c3 Binary files /dev/null and b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.dll differ diff --git a/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.pdb b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.pdb new file mode 100644 index 0000000..f73d4c4 Binary files /dev/null and b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.pdb differ diff --git a/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.runtimeconfig.json b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.runtimeconfig.json new file mode 100644 index 0000000..6925b65 --- /dev/null +++ b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.runtimeconfig.json @@ -0,0 +1,19 @@ +{ + "runtimeOptions": { + "tfm": "net9.0", + "frameworks": [ + { + "name": "Microsoft.NETCore.App", + "version": "9.0.0" + }, + { + "name": "Microsoft.AspNetCore.App", + "version": "9.0.0" + } + ], + "configProperties": { + "System.GC.Server": true, + "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false + } + } +} \ No newline at end of file diff --git a/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.staticwebassets.endpoints.json b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.staticwebassets.endpoints.json new file mode 100644 index 0000000..5576e88 --- /dev/null +++ b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.staticwebassets.endpoints.json @@ -0,0 +1 @@ +{"Version":1,"ManifestType":"Build","Endpoints":[]} \ No newline at end of file diff --git a/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.xml b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.xml new file mode 100644 index 0000000..6335700 --- /dev/null +++ b/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.xml @@ -0,0 +1,525 @@ + + + + ControlCenter + + + + + REST API for querying agent fleet status. + Provides the initial data load for the Command Hub, + while real-time updates flow through the AgentStatus SignalR hub. + + API contract for Rex (Frontend): + + GET /api/agents — Returns all known agents with current status + GET /api/agents/{agentId} — Returns a specific agent's status + + + + + + Gets the current fleet status — all known agents with their latest state. + This is the initial load endpoint; subsequent updates arrive via SignalR. + + An array of agent card data for the entire fleet. + Returns the fleet snapshot. + + + + Gets the current status of a specific agent. + + The agent identifier, e.g. "otto", "dex". + The agent's current card data. + Returns the agent's status. + Agent not found in the fleet state. + + + + 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. + + + + + 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. + + + + 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. + + + + 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. + + + + Request body for the steer command. + + The message to inject into the agent's session. + + + + Request body for the steer command. + + The message to inject into the agent's session. + + + The message to inject into the agent's session. + + + + REST API for querying agent session logs. + Provides historical message and tool call logs for a specific agent. + + API contract for Rex (Frontend): + + GET /api/logs/{agentId} — Returns recent logs for an agent + GET /api/logs/{agentId}/tools — Returns recent tool calls for an agent + + + Log data is sourced from the OpenClaw Gateway's transcript files. + The Gateway's logs.tail RPC provides the raw data, and this + controller formats it for the frontend. + + + + + Gets recent session logs for a specific agent. + Returns the last N messages from the agent's active session transcript. + + The agent identifier, e.g. "otto", "dex". + Maximum number of log entries to return (default: 50, max: 200). + An array of log entries for the agent. + Returns the agent's recent logs. + No active session found for the agent. + + + + Gets recent tool call logs for a specific agent. + Returns the last N tool invocations from the agent's session. + + The agent identifier. + Maximum number of tool entries to return (default: 20, max: 100). + An array of tool call entries for the agent. + Returns the agent's recent tool calls. + No active session found for the agent. + + + + SignalR hub for real-time agent status updates in the Command Hub. + + Usage flow: + + Client connects to /hubs/agent-status + Client calls to subscribe to all agent updates + Client calls to subscribe to a specific agent + Server pushes + and events + Client calls for initial state on connect + + + Group naming: + + Fleet group: fleet — receives all agent updates + Agent group: agent:{agentId} — receives updates for one agent + + + Typed client: — all server-to-client + calls go through this interface for compile-time safety. + + Architecture note: This hub bridges OpenClaw Gateway WebSocket events + to SignalR clients. A background service () + subscribes to Gateway events and pushes them through this hub's extension methods. + + + + + Adds the calling connection to the fleet group. + Once joined, the client will receive all agent status changes + and task progress updates across the entire fleet. + + + + + Removes the calling connection from the fleet group. + + + + + Adds the calling connection to a specific agent's group. + Once joined, the client will receive updates only for that agent. + + The agent identifier, e.g. "otto", "dex". + Thrown if agentId is null or empty. + + + + Removes the calling connection from a specific agent's group. + + The agent identifier. + + + + Returns a snapshot of the current fleet state. + Called by clients on initial connection to get the full picture + before incremental updates begin arriving. + + An array of representing all known agents. + + + + Overrides to perform cleanup. + SignalR automatically removes disconnected connections from all groups. + + Exception that caused the disconnection, if any. + + + + The SignalR group name for the entire fleet (all agents). + + + + + Returns the SignalR group name for a specific agent. + Format: agent:{agentId} (lowercase for consistency). + + The agent identifier. + + + + Extension methods for pushing real-time agent updates through + the of . + + These methods are intended to be called from background services + (e.g., ) or other + server-side code that detects an agent state change. + + + + + Pushes an agent status change to all clients subscribed to + the fleet group and the specific agent's group. + + Call this from any background service when an agent's + operational status changes (e.g., the Gateway reports a + session transition from "running" to "done"). + + The hub context injected via DI. + The agent status update payload. + A Task that completes when the message has been sent to all group members. + + + + Pushes a task progress update to all clients subscribed to + the fleet group and the specific agent's group. + + The hub context injected via DI. + The task progress update payload. + A Task that completes when the message has been sent to all group members. + + + + Strongly-typed client interface for the AgentStatus SignalR hub. + Defines the methods the server can invoke on connected clients + to push real-time agent status and task progress updates. + + All server-to-client calls go through this interface for + compile-time safety — matching the pattern used by the + Extrudex PrinterHub. + + + + + Pushes an agent status change to all subscribed clients. + Fired whenever an agent's operational status changes + (e.g., idle → active, active → thinking, active → error). + + The full status update payload. + A Task that completes when the client has processed the update. + + + + Pushes a task progress update to all subscribed clients. + Fired when an agent reports progress on its current task. + + The task progress update payload. + A Task that completes when the client has processed the update. + + + + Agent operational status derived from OpenClaw Gateway session activity. + Maps to the frontend AgentStatus type: 'active' | 'idle' | 'thinking' | 'error'. + + + + Agent is currently processing a turn. + + + Agent completed its last turn; no active work. + + + LLM call in flight; tokens streaming. + + + Agent encountered an unhandled error. + + + + Extended lifecycle status including offline — not all agents have active sessions. + Used internally; clients only see (offline maps to idle). + + + + + Pushed to SignalR clients when an agent's status changes. + Matches the TypeScript AgentStatusUpdate interface from the design spec. + + Agent identifier, e.g. "otto", "dex". + Human-readable name, e.g. "Otto". + Role description, e.g. "Orchestrator Agent". + Current operational status. + Description of the current task, if any. + Full session key, e.g. "agent:otto:telegram:direct:8787451565". + Channel the agent is operating on, e.g. "telegram". + ISO 8601 timestamp of last activity. + Error message when status is 'error'. + + + + Pushed to SignalR clients when an agent's status changes. + Matches the TypeScript AgentStatusUpdate interface from the design spec. + + Agent identifier, e.g. "otto", "dex". + Human-readable name, e.g. "Otto". + Role description, e.g. "Orchestrator Agent". + Current operational status. + Description of the current task, if any. + Full session key, e.g. "agent:otto:telegram:direct:8787451565". + Channel the agent is operating on, e.g. "telegram". + ISO 8601 timestamp of last activity. + Error message when status is 'error'. + + + Agent identifier, e.g. "otto", "dex". + + + Human-readable name, e.g. "Otto". + + + Role description, e.g. "Orchestrator Agent". + + + Current operational status. + + + Description of the current task, if any. + + + Full session key, e.g. "agent:otto:telegram:direct:8787451565". + + + Channel the agent is operating on, e.g. "telegram". + + + ISO 8601 timestamp of last activity. + + + Error message when status is 'error'. + + + + Pushed to SignalR clients when an agent's task progress updates. + Matches the TypeScript TaskProgressUpdate interface from the design spec. + + Agent identifier. + Description of the current task. + Task progress percentage (0–100), if trackable. + Elapsed time string, e.g. "04m 12s". + + + + Pushed to SignalR clients when an agent's task progress updates. + Matches the TypeScript TaskProgressUpdate interface from the design spec. + + Agent identifier. + Description of the current task. + Task progress percentage (0–100), if trackable. + Elapsed time string, e.g. "04m 12s". + + + Agent identifier. + + + Description of the current task. + + + Task progress percentage (0–100), if trackable. + + + Elapsed time string, e.g. "04m 12s". + + + + Snapshot of an agent's full card data, sent on initial connection + or when the fleet state is requested. + Matches the TypeScript AgentCardData interface from the design spec. + + + + + Snapshot of an agent's full card data, sent on initial connection + or when the fleet state is requested. + Matches the TypeScript AgentCardData interface from the design spec. + + + + + Background service that connects to the OpenClaw Gateway WebSocket + and bridges Gateway events to the . + + Architecture: + + Connects to the Gateway WS endpoint (configurable via appsettings) + Handles the v3 protocol handshake (challenge → connect → hello-ok) + Subscribes to sessions.changed and related events + Translates session state changes into + and objects + Pushes updates through the SignalR hub + + + This is the server-side bridge that allows Angular clients to + receive real-time updates via SignalR instead of connecting directly + to the Gateway WebSocket. + + + + + In-memory fleet state — maps agent IDs to their latest card data. + Updated on every sessions.changed event from the Gateway. + + + + + Known agent roles for display in the Command Hub. + Maps agent IDs to their functional descriptions. + + + + + Maps OpenClaw session status to . + + + + + Returns the current fleet state snapshot. + Used by the hub's GetFleetSnapshot method and by the + AgentsController REST endpoint. + + + + + Connects to the OpenClaw Gateway WebSocket and processes events + until the connection is lost or cancellation is requested. + + + + + Receives and processes WebSocket messages from the Gateway. + Handles the v3 protocol handshake and dispatches events. + + + + + Processes a single WebSocket message from the Gateway. + Routes based on the message type: event, response, or challenge. + + + + + Handles the Gateway connect.challenge event by sending + a connect request with authentication credentials. + + + + + Handles a Gateway event message by dispatching to the + appropriate handler based on event name. + + + + + Handles a sessions.changed event from the Gateway. + Updates the fleet state and pushes status changes through SignalR. + + + + + Handles a session.message event. Updates the agent's last activity + and pushes a status update if the status changed. + + + + + Handles a session.tool event. Extracts tool progress information + and pushes a through SignalR. + + + + + Handles a health event from the Gateway. + Logs the health status for diagnostics. + + + + + Handles a Gateway response message. Currently only logs for diagnostics. + + + + + Converts a raw Gateway session JSON element into an + record. + + + + + Extracts the agent ID from a session key. + Session key format: "agent:{agentId}:{channel}:..." + + + + + Extracts the channel from a session element. + + + + diff --git a/backend/ControlCenter/bin/Debug/net9.0/Microsoft.OpenApi.dll b/backend/ControlCenter/bin/Debug/net9.0/Microsoft.OpenApi.dll new file mode 100755 index 0000000..58b6245 Binary files /dev/null and b/backend/ControlCenter/bin/Debug/net9.0/Microsoft.OpenApi.dll differ diff --git a/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.Swagger.dll b/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.Swagger.dll new file mode 100755 index 0000000..f9c8108 Binary files /dev/null and b/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.Swagger.dll differ diff --git a/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll b/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll new file mode 100755 index 0000000..a29b341 Binary files /dev/null and b/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll differ diff --git a/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll b/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll new file mode 100755 index 0000000..1d440e2 Binary files /dev/null and b/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll differ diff --git a/backend/ControlCenter/bin/Debug/net9.0/appsettings.Development.json b/backend/ControlCenter/bin/Debug/net9.0/appsettings.Development.json new file mode 100644 index 0000000..626b82e --- /dev/null +++ b/backend/ControlCenter/bin/Debug/net9.0/appsettings.Development.json @@ -0,0 +1,19 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "Microsoft.AspNetCore": "Information", + "ControlCenter": "Debug" + } + }, + "Gateway": { + "WebSocketUrl": "ws://localhost:3271/ws", + "AuthToken": "" + }, + "Cors": { + "AllowedOrigins": [ + "http://localhost:4200", + "http://localhost:5000" + ] + } +} \ No newline at end of file diff --git a/backend/ControlCenter/bin/Debug/net9.0/appsettings.json b/backend/ControlCenter/bin/Debug/net9.0/appsettings.json new file mode 100644 index 0000000..60f801d --- /dev/null +++ b/backend/ControlCenter/bin/Debug/net9.0/appsettings.json @@ -0,0 +1,22 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "ControlCenter": "Debug" + } + }, + "AllowedHosts": "*", + + "Gateway": { + "WebSocketUrl": "ws://localhost:3271/ws", + "AuthToken": "" + }, + + "Cors": { + "AllowedOrigins": [ + "http://localhost:4200", + "http://localhost:5000" + ] + } +} \ No newline at end of file diff --git a/backend/ControlCenter/obj/ControlCenter.csproj.nuget.dgspec.json b/backend/ControlCenter/obj/ControlCenter.csproj.nuget.dgspec.json new file mode 100644 index 0000000..5eb989c --- /dev/null +++ b/backend/ControlCenter/obj/ControlCenter.csproj.nuget.dgspec.json @@ -0,0 +1,76 @@ +{ + "format": 1, + "restore": { + "/home/overseer/projects/control-center/backend/ControlCenter/ControlCenter.csproj": {} + }, + "projects": { + "/home/overseer/projects/control-center/backend/ControlCenter/ControlCenter.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/home/overseer/projects/control-center/backend/ControlCenter/ControlCenter.csproj", + "projectName": "ControlCenter", + "projectPath": "/home/overseer/projects/control-center/backend/ControlCenter/ControlCenter.csproj", + "packagesPath": "/home/overseer/.nuget/packages/", + "outputPath": "/home/overseer/projects/control-center/backend/ControlCenter/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/home/overseer/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "net9.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "dependencies": { + "Swashbuckle.AspNetCore": { + "target": "Package", + "version": "[10.1.7, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "/home/overseer/.dotnet/sdk/9.0.312/PortableRuntimeIdentifierGraph.json" + } + } + } + } +} \ No newline at end of file diff --git a/backend/ControlCenter/obj/ControlCenter.csproj.nuget.g.props b/backend/ControlCenter/obj/ControlCenter.csproj.nuget.g.props new file mode 100644 index 0000000..8920d2b --- /dev/null +++ b/backend/ControlCenter/obj/ControlCenter.csproj.nuget.g.props @@ -0,0 +1,22 @@ + + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + /home/overseer/.nuget/packages/ + /home/overseer/.nuget/packages/ + PackageReference + 6.14.0 + + + + + + + + + + /home/overseer/.nuget/packages/microsoft.extensions.apidescription.server/9.0.0 + + \ No newline at end of file diff --git a/backend/ControlCenter/obj/ControlCenter.csproj.nuget.g.targets b/backend/ControlCenter/obj/ControlCenter.csproj.nuget.g.targets new file mode 100644 index 0000000..60f4bac --- /dev/null +++ b/backend/ControlCenter/obj/ControlCenter.csproj.nuget.g.targets @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/backend/ControlCenter/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs b/backend/ControlCenter/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs new file mode 100644 index 0000000..9e76325 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")] diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlC.8BE8DDC1.Up2Date b/backend/ControlCenter/obj/Debug/net9.0/ControlC.8BE8DDC1.Up2Date new file mode 100644 index 0000000..e69de29 diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.AssemblyInfo.cs b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.AssemblyInfo.cs new file mode 100644 index 0000000..6c04b97 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.AssemblyInfo.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("ControlCenter")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+f490098af681d324519c399c3e75ade058357531")] +[assembly: System.Reflection.AssemblyProductAttribute("ControlCenter")] +[assembly: System.Reflection.AssemblyTitleAttribute("ControlCenter")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.AssemblyInfoInputs.cache b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.AssemblyInfoInputs.cache new file mode 100644 index 0000000..87ee5f5 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +d9ac725746244a0c1e0ff1bcede0c898e3615303f498e39aec65b74e6488388a diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.GeneratedMSBuildEditorConfig.editorconfig b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..c342709 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,21 @@ +is_global = true +build_property.TargetFramework = net9.0 +build_property.TargetPlatformMinVersion = +build_property.UsingMicrosoftNETSdkWeb = true +build_property.ProjectTypeGuids = +build_property.InvariantGlobalization = +build_property.PlatformNeutralAssembly = +build_property.EnforceExtendedAnalyzerRules = +build_property._SupportedPlatformList = Linux,macOS,Windows +build_property.RootNamespace = ControlCenter +build_property.RootNamespace = ControlCenter +build_property.ProjectDir = /home/overseer/projects/control-center/backend/ControlCenter/ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.RazorLangVersion = 9.0 +build_property.SupportLocalizedComponentNames = +build_property.GenerateRazorMetadataSourceChecksumAttributes = +build_property.MSBuildProjectDirectory = /home/overseer/projects/control-center/backend/ControlCenter +build_property._RazorSourceGeneratorDebug = +build_property.EffectiveAnalysisLevelStyle = 9.0 +build_property.EnableCodeStyleSeverity = diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.GlobalUsings.g.cs b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.GlobalUsings.g.cs new file mode 100644 index 0000000..025530a --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.GlobalUsings.g.cs @@ -0,0 +1,17 @@ +// +global using global::Microsoft.AspNetCore.Builder; +global using global::Microsoft.AspNetCore.Hosting; +global using global::Microsoft.AspNetCore.Http; +global using global::Microsoft.AspNetCore.Routing; +global using global::Microsoft.Extensions.Configuration; +global using global::Microsoft.Extensions.DependencyInjection; +global using global::Microsoft.Extensions.Hosting; +global using global::Microsoft.Extensions.Logging; +global using global::System; +global using global::System.Collections.Generic; +global using global::System.IO; +global using global::System.Linq; +global using global::System.Net.Http; +global using global::System.Net.Http.Json; +global using global::System.Threading; +global using global::System.Threading.Tasks; diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.MvcApplicationPartsAssemblyInfo.cache b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.MvcApplicationPartsAssemblyInfo.cache new file mode 100644 index 0000000..e69de29 diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.MvcApplicationPartsAssemblyInfo.cs b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.MvcApplicationPartsAssemblyInfo.cs new file mode 100644 index 0000000..5c337f8 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.MvcApplicationPartsAssemblyInfo.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute("Swashbuckle.AspNetCore.SwaggerGen")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.assets.cache b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.assets.cache new file mode 100644 index 0000000..5564151 Binary files /dev/null and b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.assets.cache differ diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.csproj.AssemblyReference.cache b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.csproj.AssemblyReference.cache new file mode 100644 index 0000000..f1f28b0 Binary files /dev/null and b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.csproj.AssemblyReference.cache differ diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.csproj.CoreCompileInputs.cache b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..87abb78 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +5a149a9be81d0d785f401346061a83ced0347895d02923e2209cde8264498329 diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.csproj.FileListAbsolute.txt b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..680dfeb --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.csproj.FileListAbsolute.txt @@ -0,0 +1,36 @@ +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/rpswa.dswa.cache.json +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.GeneratedMSBuildEditorConfig.editorconfig +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.AssemblyInfoInputs.cache +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.AssemblyInfo.cs +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.csproj.CoreCompileInputs.cache +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.MvcApplicationPartsAssemblyInfo.cache +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/appsettings.Development.json +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/appsettings.json +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.staticwebassets.endpoints.json +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/ControlCenter +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.deps.json +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.runtimeconfig.json +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.dll +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.pdb +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/ControlCenter.xml +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/Microsoft.OpenApi.dll +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.Swagger.dll +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll +/home/overseer/projects/control-center/backend/ControlCenter/bin/Debug/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.csproj.AssemblyReference.cache +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.MvcApplicationPartsAssemblyInfo.cs +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/rjimswa.dswa.cache.json +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/rjsmrazor.dswa.cache.json +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/scopedcss/bundle/ControlCenter.styles.css +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.json +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.json.cache +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.development.json +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.endpoints.json +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlC.8BE8DDC1.Up2Date +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.dll +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/refint/ControlCenter.dll +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.xml +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.pdb +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.genruntimeconfig.cache +/home/overseer/projects/control-center/backend/ControlCenter/obj/Debug/net9.0/ref/ControlCenter.dll diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.dll b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.dll new file mode 100644 index 0000000..5a464c3 Binary files /dev/null and b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.dll differ diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.genruntimeconfig.cache b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.genruntimeconfig.cache new file mode 100644 index 0000000..1706e2e --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.genruntimeconfig.cache @@ -0,0 +1 @@ +fb735db4022e3ab26c1abd1408be390500bd48ea8b05809d0deadb8a6cf1b3d1 diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.pdb b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.pdb new file mode 100644 index 0000000..f73d4c4 Binary files /dev/null and b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.pdb differ diff --git a/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.xml b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.xml new file mode 100644 index 0000000..6335700 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/ControlCenter.xml @@ -0,0 +1,525 @@ + + + + ControlCenter + + + + + REST API for querying agent fleet status. + Provides the initial data load for the Command Hub, + while real-time updates flow through the AgentStatus SignalR hub. + + API contract for Rex (Frontend): + + GET /api/agents — Returns all known agents with current status + GET /api/agents/{agentId} — Returns a specific agent's status + + + + + + Gets the current fleet status — all known agents with their latest state. + This is the initial load endpoint; subsequent updates arrive via SignalR. + + An array of agent card data for the entire fleet. + Returns the fleet snapshot. + + + + Gets the current status of a specific agent. + + The agent identifier, e.g. "otto", "dex". + The agent's current card data. + Returns the agent's status. + Agent not found in the fleet state. + + + + 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. + + + + + 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. + + + + 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. + + + + 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. + + + + Request body for the steer command. + + The message to inject into the agent's session. + + + + Request body for the steer command. + + The message to inject into the agent's session. + + + The message to inject into the agent's session. + + + + REST API for querying agent session logs. + Provides historical message and tool call logs for a specific agent. + + API contract for Rex (Frontend): + + GET /api/logs/{agentId} — Returns recent logs for an agent + GET /api/logs/{agentId}/tools — Returns recent tool calls for an agent + + + Log data is sourced from the OpenClaw Gateway's transcript files. + The Gateway's logs.tail RPC provides the raw data, and this + controller formats it for the frontend. + + + + + Gets recent session logs for a specific agent. + Returns the last N messages from the agent's active session transcript. + + The agent identifier, e.g. "otto", "dex". + Maximum number of log entries to return (default: 50, max: 200). + An array of log entries for the agent. + Returns the agent's recent logs. + No active session found for the agent. + + + + Gets recent tool call logs for a specific agent. + Returns the last N tool invocations from the agent's session. + + The agent identifier. + Maximum number of tool entries to return (default: 20, max: 100). + An array of tool call entries for the agent. + Returns the agent's recent tool calls. + No active session found for the agent. + + + + SignalR hub for real-time agent status updates in the Command Hub. + + Usage flow: + + Client connects to /hubs/agent-status + Client calls to subscribe to all agent updates + Client calls to subscribe to a specific agent + Server pushes + and events + Client calls for initial state on connect + + + Group naming: + + Fleet group: fleet — receives all agent updates + Agent group: agent:{agentId} — receives updates for one agent + + + Typed client: — all server-to-client + calls go through this interface for compile-time safety. + + Architecture note: This hub bridges OpenClaw Gateway WebSocket events + to SignalR clients. A background service () + subscribes to Gateway events and pushes them through this hub's extension methods. + + + + + Adds the calling connection to the fleet group. + Once joined, the client will receive all agent status changes + and task progress updates across the entire fleet. + + + + + Removes the calling connection from the fleet group. + + + + + Adds the calling connection to a specific agent's group. + Once joined, the client will receive updates only for that agent. + + The agent identifier, e.g. "otto", "dex". + Thrown if agentId is null or empty. + + + + Removes the calling connection from a specific agent's group. + + The agent identifier. + + + + Returns a snapshot of the current fleet state. + Called by clients on initial connection to get the full picture + before incremental updates begin arriving. + + An array of representing all known agents. + + + + Overrides to perform cleanup. + SignalR automatically removes disconnected connections from all groups. + + Exception that caused the disconnection, if any. + + + + The SignalR group name for the entire fleet (all agents). + + + + + Returns the SignalR group name for a specific agent. + Format: agent:{agentId} (lowercase for consistency). + + The agent identifier. + + + + Extension methods for pushing real-time agent updates through + the of . + + These methods are intended to be called from background services + (e.g., ) or other + server-side code that detects an agent state change. + + + + + Pushes an agent status change to all clients subscribed to + the fleet group and the specific agent's group. + + Call this from any background service when an agent's + operational status changes (e.g., the Gateway reports a + session transition from "running" to "done"). + + The hub context injected via DI. + The agent status update payload. + A Task that completes when the message has been sent to all group members. + + + + Pushes a task progress update to all clients subscribed to + the fleet group and the specific agent's group. + + The hub context injected via DI. + The task progress update payload. + A Task that completes when the message has been sent to all group members. + + + + Strongly-typed client interface for the AgentStatus SignalR hub. + Defines the methods the server can invoke on connected clients + to push real-time agent status and task progress updates. + + All server-to-client calls go through this interface for + compile-time safety — matching the pattern used by the + Extrudex PrinterHub. + + + + + Pushes an agent status change to all subscribed clients. + Fired whenever an agent's operational status changes + (e.g., idle → active, active → thinking, active → error). + + The full status update payload. + A Task that completes when the client has processed the update. + + + + Pushes a task progress update to all subscribed clients. + Fired when an agent reports progress on its current task. + + The task progress update payload. + A Task that completes when the client has processed the update. + + + + Agent operational status derived from OpenClaw Gateway session activity. + Maps to the frontend AgentStatus type: 'active' | 'idle' | 'thinking' | 'error'. + + + + Agent is currently processing a turn. + + + Agent completed its last turn; no active work. + + + LLM call in flight; tokens streaming. + + + Agent encountered an unhandled error. + + + + Extended lifecycle status including offline — not all agents have active sessions. + Used internally; clients only see (offline maps to idle). + + + + + Pushed to SignalR clients when an agent's status changes. + Matches the TypeScript AgentStatusUpdate interface from the design spec. + + Agent identifier, e.g. "otto", "dex". + Human-readable name, e.g. "Otto". + Role description, e.g. "Orchestrator Agent". + Current operational status. + Description of the current task, if any. + Full session key, e.g. "agent:otto:telegram:direct:8787451565". + Channel the agent is operating on, e.g. "telegram". + ISO 8601 timestamp of last activity. + Error message when status is 'error'. + + + + Pushed to SignalR clients when an agent's status changes. + Matches the TypeScript AgentStatusUpdate interface from the design spec. + + Agent identifier, e.g. "otto", "dex". + Human-readable name, e.g. "Otto". + Role description, e.g. "Orchestrator Agent". + Current operational status. + Description of the current task, if any. + Full session key, e.g. "agent:otto:telegram:direct:8787451565". + Channel the agent is operating on, e.g. "telegram". + ISO 8601 timestamp of last activity. + Error message when status is 'error'. + + + Agent identifier, e.g. "otto", "dex". + + + Human-readable name, e.g. "Otto". + + + Role description, e.g. "Orchestrator Agent". + + + Current operational status. + + + Description of the current task, if any. + + + Full session key, e.g. "agent:otto:telegram:direct:8787451565". + + + Channel the agent is operating on, e.g. "telegram". + + + ISO 8601 timestamp of last activity. + + + Error message when status is 'error'. + + + + Pushed to SignalR clients when an agent's task progress updates. + Matches the TypeScript TaskProgressUpdate interface from the design spec. + + Agent identifier. + Description of the current task. + Task progress percentage (0–100), if trackable. + Elapsed time string, e.g. "04m 12s". + + + + Pushed to SignalR clients when an agent's task progress updates. + Matches the TypeScript TaskProgressUpdate interface from the design spec. + + Agent identifier. + Description of the current task. + Task progress percentage (0–100), if trackable. + Elapsed time string, e.g. "04m 12s". + + + Agent identifier. + + + Description of the current task. + + + Task progress percentage (0–100), if trackable. + + + Elapsed time string, e.g. "04m 12s". + + + + Snapshot of an agent's full card data, sent on initial connection + or when the fleet state is requested. + Matches the TypeScript AgentCardData interface from the design spec. + + + + + Snapshot of an agent's full card data, sent on initial connection + or when the fleet state is requested. + Matches the TypeScript AgentCardData interface from the design spec. + + + + + Background service that connects to the OpenClaw Gateway WebSocket + and bridges Gateway events to the . + + Architecture: + + Connects to the Gateway WS endpoint (configurable via appsettings) + Handles the v3 protocol handshake (challenge → connect → hello-ok) + Subscribes to sessions.changed and related events + Translates session state changes into + and objects + Pushes updates through the SignalR hub + + + This is the server-side bridge that allows Angular clients to + receive real-time updates via SignalR instead of connecting directly + to the Gateway WebSocket. + + + + + In-memory fleet state — maps agent IDs to their latest card data. + Updated on every sessions.changed event from the Gateway. + + + + + Known agent roles for display in the Command Hub. + Maps agent IDs to their functional descriptions. + + + + + Maps OpenClaw session status to . + + + + + Returns the current fleet state snapshot. + Used by the hub's GetFleetSnapshot method and by the + AgentsController REST endpoint. + + + + + Connects to the OpenClaw Gateway WebSocket and processes events + until the connection is lost or cancellation is requested. + + + + + Receives and processes WebSocket messages from the Gateway. + Handles the v3 protocol handshake and dispatches events. + + + + + Processes a single WebSocket message from the Gateway. + Routes based on the message type: event, response, or challenge. + + + + + Handles the Gateway connect.challenge event by sending + a connect request with authentication credentials. + + + + + Handles a Gateway event message by dispatching to the + appropriate handler based on event name. + + + + + Handles a sessions.changed event from the Gateway. + Updates the fleet state and pushes status changes through SignalR. + + + + + Handles a session.message event. Updates the agent's last activity + and pushes a status update if the status changed. + + + + + Handles a session.tool event. Extracts tool progress information + and pushes a through SignalR. + + + + + Handles a health event from the Gateway. + Logs the health status for diagnostics. + + + + + Handles a Gateway response message. Currently only logs for diagnostics. + + + + + Converts a raw Gateway session JSON element into an + record. + + + + + Extracts the agent ID from a session key. + Session key format: "agent:{agentId}:{channel}:..." + + + + + Extracts the channel from a session element. + + + + diff --git a/backend/ControlCenter/obj/Debug/net9.0/apphost b/backend/ControlCenter/obj/Debug/net9.0/apphost new file mode 100755 index 0000000..ef5779a Binary files /dev/null and b/backend/ControlCenter/obj/Debug/net9.0/apphost differ diff --git a/backend/ControlCenter/obj/Debug/net9.0/ref/ControlCenter.dll b/backend/ControlCenter/obj/Debug/net9.0/ref/ControlCenter.dll new file mode 100644 index 0000000..489ecc2 Binary files /dev/null and b/backend/ControlCenter/obj/Debug/net9.0/ref/ControlCenter.dll differ diff --git a/backend/ControlCenter/obj/Debug/net9.0/refint/ControlCenter.dll b/backend/ControlCenter/obj/Debug/net9.0/refint/ControlCenter.dll new file mode 100644 index 0000000..489ecc2 Binary files /dev/null and b/backend/ControlCenter/obj/Debug/net9.0/refint/ControlCenter.dll differ diff --git a/backend/ControlCenter/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json b/backend/ControlCenter/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json new file mode 100644 index 0000000..3818895 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json @@ -0,0 +1 @@ +{"GlobalPropertiesHash":"fP6C7NMofulnBE1eej8XjOwRkTKI5k6NpzaQX80fX8s=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["RLHkEsLEvNvl8jLrrAgVApLy6dxoK6XfbeV9mw/9T7o=","rgcVP\u002BVr5KxJyslAN\u002ByJcFCRZcRu6\u002B1l2pjhD4NaFdw=","FFbGWElm3cdQZsLW1ACMByZe8G8gDhCtEJQz38GZLOQ=","59/k\u002BS6qSaOYsxQEpqPfNdLtDHcGS8jaZQOh\u002BdsAjCc="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/backend/ControlCenter/obj/Debug/net9.0/rjsmrazor.dswa.cache.json b/backend/ControlCenter/obj/Debug/net9.0/rjsmrazor.dswa.cache.json new file mode 100644 index 0000000..b8901b0 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/rjsmrazor.dswa.cache.json @@ -0,0 +1 @@ +{"GlobalPropertiesHash":"CM6+tGqDGZSCMIjvZW43Mig+XGvvGPauYcFS9pFbVbU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["RLHkEsLEvNvl8jLrrAgVApLy6dxoK6XfbeV9mw/9T7o=","rgcVP\u002BVr5KxJyslAN\u002ByJcFCRZcRu6\u002B1l2pjhD4NaFdw=","FFbGWElm3cdQZsLW1ACMByZe8G8gDhCtEJQz38GZLOQ=","59/k\u002BS6qSaOYsxQEpqPfNdLtDHcGS8jaZQOh\u002BdsAjCc="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/backend/ControlCenter/obj/Debug/net9.0/rpswa.dswa.cache.json b/backend/ControlCenter/obj/Debug/net9.0/rpswa.dswa.cache.json new file mode 100644 index 0000000..ead65fe --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/rpswa.dswa.cache.json @@ -0,0 +1 @@ +{"GlobalPropertiesHash":"a1GQyj11k+1oHxZebIKZqb47X6WAtT1QozrGrmX2GLs=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["RLHkEsLEvNvl8jLrrAgVApLy6dxoK6XfbeV9mw/9T7o=","rgcVP\u002BVr5KxJyslAN\u002ByJcFCRZcRu6\u002B1l2pjhD4NaFdw="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.endpoints.json b/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.endpoints.json new file mode 100644 index 0000000..5576e88 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.endpoints.json @@ -0,0 +1 @@ +{"Version":1,"ManifestType":"Build","Endpoints":[]} \ No newline at end of file diff --git a/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.json b/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.json new file mode 100644 index 0000000..1ca3228 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.json @@ -0,0 +1 @@ +{"Version":1,"Hash":"VtMlOCwFm0Ev666s2/hr1q6JK4feLZLPBJxH6XDSLFM=","Source":"ControlCenter","BasePath":"_content/ControlCenter","Mode":"Default","ManifestType":"Build","ReferencedProjectsConfiguration":[],"DiscoveryPatterns":[],"Assets":[],"Endpoints":[]} \ No newline at end of file diff --git a/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.json.cache b/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.json.cache new file mode 100644 index 0000000..00ea1d6 --- /dev/null +++ b/backend/ControlCenter/obj/Debug/net9.0/staticwebassets.build.json.cache @@ -0,0 +1 @@ +VtMlOCwFm0Ev666s2/hr1q6JK4feLZLPBJxH6XDSLFM= \ No newline at end of file diff --git a/backend/ControlCenter/obj/project.assets.json b/backend/ControlCenter/obj/project.assets.json new file mode 100644 index 0000000..61811bf --- /dev/null +++ b/backend/ControlCenter/obj/project.assets.json @@ -0,0 +1,619 @@ +{ + "version": 3, + "targets": { + "net9.0": { + "Microsoft.Extensions.ApiDescription.Server/9.0.0": { + "type": "package", + "build": { + "build/Microsoft.Extensions.ApiDescription.Server.props": {}, + "build/Microsoft.Extensions.ApiDescription.Server.targets": {} + }, + "buildMultiTargeting": { + "buildMultiTargeting/Microsoft.Extensions.ApiDescription.Server.props": {}, + "buildMultiTargeting/Microsoft.Extensions.ApiDescription.Server.targets": {} + } + }, + "Microsoft.OpenApi/2.4.1": { + "type": "package", + "dependencies": { + "System.Text.Json": "8.0.5" + }, + "compile": { + "lib/net8.0/Microsoft.OpenApi.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net8.0/Microsoft.OpenApi.dll": { + "related": ".pdb;.xml" + } + } + }, + "Swashbuckle.AspNetCore/10.1.7": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.ApiDescription.Server": "9.0.0", + "Swashbuckle.AspNetCore.Swagger": "10.1.7", + "Swashbuckle.AspNetCore.SwaggerGen": "10.1.7", + "Swashbuckle.AspNetCore.SwaggerUI": "10.1.7" + }, + "build": { + "build/Swashbuckle.AspNetCore.props": {} + }, + "buildMultiTargeting": { + "buildMultiTargeting/Swashbuckle.AspNetCore.props": {} + } + }, + "Swashbuckle.AspNetCore.Swagger/10.1.7": { + "type": "package", + "dependencies": { + "Microsoft.OpenApi": "2.4.1" + }, + "compile": { + "lib/net9.0/Swashbuckle.AspNetCore.Swagger.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net9.0/Swashbuckle.AspNetCore.Swagger.dll": { + "related": ".pdb;.xml" + } + }, + "frameworkReferences": [ + "Microsoft.AspNetCore.App" + ] + }, + "Swashbuckle.AspNetCore.SwaggerGen/10.1.7": { + "type": "package", + "dependencies": { + "Swashbuckle.AspNetCore.Swagger": "10.1.7" + }, + "compile": { + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll": { + "related": ".pdb;.xml" + } + } + }, + "Swashbuckle.AspNetCore.SwaggerUI/10.1.7": { + "type": "package", + "compile": { + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll": { + "related": ".pdb;.xml" + } + }, + "frameworkReferences": [ + "Microsoft.AspNetCore.App" + ] + }, + "System.Text.Json/8.0.5": { + "type": "package", + "compile": { + "lib/net8.0/System.Text.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/System.Text.Json.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/System.Text.Json.targets": {} + } + } + } + }, + "libraries": { + "Microsoft.Extensions.ApiDescription.Server/9.0.0": { + "sha512": "1Kzzf7pRey40VaUkHN9/uWxrKVkLu2AQjt+GVeeKLLpiEHAJ1xZRsLSh4ZZYEnyS7Kt2OBOPmsXNdU+wbcOl5w==", + "type": "package", + "path": "microsoft.extensions.apidescription.server/9.0.0", + "hasTools": true, + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "build/Microsoft.Extensions.ApiDescription.Server.props", + "build/Microsoft.Extensions.ApiDescription.Server.targets", + "buildMultiTargeting/Microsoft.Extensions.ApiDescription.Server.props", + "buildMultiTargeting/Microsoft.Extensions.ApiDescription.Server.targets", + "microsoft.extensions.apidescription.server.9.0.0.nupkg.sha512", + "microsoft.extensions.apidescription.server.nuspec", + "tools/Newtonsoft.Json.dll", + "tools/dotnet-getdocument.deps.json", + "tools/dotnet-getdocument.dll", + "tools/dotnet-getdocument.runtimeconfig.json", + "tools/net462-x86/GetDocument.Insider.exe", + "tools/net462-x86/GetDocument.Insider.exe.config", + "tools/net462-x86/Microsoft.OpenApi.dll", + "tools/net462-x86/Microsoft.Win32.Primitives.dll", + "tools/net462-x86/System.AppContext.dll", + "tools/net462-x86/System.Buffers.dll", + "tools/net462-x86/System.Collections.Concurrent.dll", + "tools/net462-x86/System.Collections.NonGeneric.dll", + "tools/net462-x86/System.Collections.Specialized.dll", + "tools/net462-x86/System.Collections.dll", + "tools/net462-x86/System.ComponentModel.EventBasedAsync.dll", + "tools/net462-x86/System.ComponentModel.Primitives.dll", + "tools/net462-x86/System.ComponentModel.TypeConverter.dll", + "tools/net462-x86/System.ComponentModel.dll", + "tools/net462-x86/System.Console.dll", + "tools/net462-x86/System.Data.Common.dll", + "tools/net462-x86/System.Diagnostics.Contracts.dll", + "tools/net462-x86/System.Diagnostics.Debug.dll", + "tools/net462-x86/System.Diagnostics.DiagnosticSource.dll", + "tools/net462-x86/System.Diagnostics.FileVersionInfo.dll", + "tools/net462-x86/System.Diagnostics.Process.dll", + "tools/net462-x86/System.Diagnostics.StackTrace.dll", + "tools/net462-x86/System.Diagnostics.TextWriterTraceListener.dll", + "tools/net462-x86/System.Diagnostics.Tools.dll", + "tools/net462-x86/System.Diagnostics.TraceSource.dll", + "tools/net462-x86/System.Diagnostics.Tracing.dll", + "tools/net462-x86/System.Drawing.Primitives.dll", + "tools/net462-x86/System.Dynamic.Runtime.dll", + "tools/net462-x86/System.Globalization.Calendars.dll", + "tools/net462-x86/System.Globalization.Extensions.dll", + "tools/net462-x86/System.Globalization.dll", + "tools/net462-x86/System.IO.Compression.ZipFile.dll", + "tools/net462-x86/System.IO.Compression.dll", + "tools/net462-x86/System.IO.FileSystem.DriveInfo.dll", + "tools/net462-x86/System.IO.FileSystem.Primitives.dll", + "tools/net462-x86/System.IO.FileSystem.Watcher.dll", + "tools/net462-x86/System.IO.FileSystem.dll", + "tools/net462-x86/System.IO.IsolatedStorage.dll", + "tools/net462-x86/System.IO.MemoryMappedFiles.dll", + "tools/net462-x86/System.IO.Pipes.dll", + "tools/net462-x86/System.IO.UnmanagedMemoryStream.dll", + "tools/net462-x86/System.IO.dll", + "tools/net462-x86/System.Linq.Expressions.dll", + "tools/net462-x86/System.Linq.Parallel.dll", + "tools/net462-x86/System.Linq.Queryable.dll", + "tools/net462-x86/System.Linq.dll", + "tools/net462-x86/System.Memory.dll", + "tools/net462-x86/System.Net.Http.dll", + "tools/net462-x86/System.Net.NameResolution.dll", + "tools/net462-x86/System.Net.NetworkInformation.dll", + "tools/net462-x86/System.Net.Ping.dll", + "tools/net462-x86/System.Net.Primitives.dll", + "tools/net462-x86/System.Net.Requests.dll", + "tools/net462-x86/System.Net.Security.dll", + "tools/net462-x86/System.Net.Sockets.dll", + "tools/net462-x86/System.Net.WebHeaderCollection.dll", + "tools/net462-x86/System.Net.WebSockets.Client.dll", + "tools/net462-x86/System.Net.WebSockets.dll", + "tools/net462-x86/System.Numerics.Vectors.dll", + "tools/net462-x86/System.ObjectModel.dll", + "tools/net462-x86/System.Reflection.Extensions.dll", + "tools/net462-x86/System.Reflection.Primitives.dll", + "tools/net462-x86/System.Reflection.dll", + "tools/net462-x86/System.Resources.Reader.dll", + "tools/net462-x86/System.Resources.ResourceManager.dll", + "tools/net462-x86/System.Resources.Writer.dll", + "tools/net462-x86/System.Runtime.CompilerServices.Unsafe.dll", + "tools/net462-x86/System.Runtime.CompilerServices.VisualC.dll", + "tools/net462-x86/System.Runtime.Extensions.dll", + "tools/net462-x86/System.Runtime.Handles.dll", + "tools/net462-x86/System.Runtime.InteropServices.RuntimeInformation.dll", + "tools/net462-x86/System.Runtime.InteropServices.dll", + "tools/net462-x86/System.Runtime.Numerics.dll", + "tools/net462-x86/System.Runtime.Serialization.Formatters.dll", + "tools/net462-x86/System.Runtime.Serialization.Json.dll", + "tools/net462-x86/System.Runtime.Serialization.Primitives.dll", + "tools/net462-x86/System.Runtime.Serialization.Xml.dll", + "tools/net462-x86/System.Runtime.dll", + "tools/net462-x86/System.Security.Claims.dll", + "tools/net462-x86/System.Security.Cryptography.Algorithms.dll", + "tools/net462-x86/System.Security.Cryptography.Csp.dll", + "tools/net462-x86/System.Security.Cryptography.Encoding.dll", + "tools/net462-x86/System.Security.Cryptography.Primitives.dll", + "tools/net462-x86/System.Security.Cryptography.X509Certificates.dll", + "tools/net462-x86/System.Security.Principal.dll", + "tools/net462-x86/System.Security.SecureString.dll", + "tools/net462-x86/System.Text.Encoding.Extensions.dll", + "tools/net462-x86/System.Text.Encoding.dll", + "tools/net462-x86/System.Text.RegularExpressions.dll", + "tools/net462-x86/System.Threading.Overlapped.dll", + "tools/net462-x86/System.Threading.Tasks.Parallel.dll", + "tools/net462-x86/System.Threading.Tasks.dll", + "tools/net462-x86/System.Threading.Thread.dll", + "tools/net462-x86/System.Threading.ThreadPool.dll", + "tools/net462-x86/System.Threading.Timer.dll", + "tools/net462-x86/System.Threading.dll", + "tools/net462-x86/System.ValueTuple.dll", + "tools/net462-x86/System.Xml.ReaderWriter.dll", + "tools/net462-x86/System.Xml.XDocument.dll", + "tools/net462-x86/System.Xml.XPath.XDocument.dll", + "tools/net462-x86/System.Xml.XPath.dll", + "tools/net462-x86/System.Xml.XmlDocument.dll", + "tools/net462-x86/System.Xml.XmlSerializer.dll", + "tools/net462-x86/netstandard.dll", + "tools/net462/GetDocument.Insider.exe", + "tools/net462/GetDocument.Insider.exe.config", + "tools/net462/Microsoft.OpenApi.dll", + "tools/net462/Microsoft.Win32.Primitives.dll", + "tools/net462/System.AppContext.dll", + "tools/net462/System.Buffers.dll", + "tools/net462/System.Collections.Concurrent.dll", + "tools/net462/System.Collections.NonGeneric.dll", + "tools/net462/System.Collections.Specialized.dll", + "tools/net462/System.Collections.dll", + "tools/net462/System.ComponentModel.EventBasedAsync.dll", + "tools/net462/System.ComponentModel.Primitives.dll", + "tools/net462/System.ComponentModel.TypeConverter.dll", + "tools/net462/System.ComponentModel.dll", + "tools/net462/System.Console.dll", + "tools/net462/System.Data.Common.dll", + "tools/net462/System.Diagnostics.Contracts.dll", + "tools/net462/System.Diagnostics.Debug.dll", + "tools/net462/System.Diagnostics.DiagnosticSource.dll", + "tools/net462/System.Diagnostics.FileVersionInfo.dll", + "tools/net462/System.Diagnostics.Process.dll", + "tools/net462/System.Diagnostics.StackTrace.dll", + "tools/net462/System.Diagnostics.TextWriterTraceListener.dll", + "tools/net462/System.Diagnostics.Tools.dll", + "tools/net462/System.Diagnostics.TraceSource.dll", + "tools/net462/System.Diagnostics.Tracing.dll", + "tools/net462/System.Drawing.Primitives.dll", + "tools/net462/System.Dynamic.Runtime.dll", + "tools/net462/System.Globalization.Calendars.dll", + "tools/net462/System.Globalization.Extensions.dll", + "tools/net462/System.Globalization.dll", + "tools/net462/System.IO.Compression.ZipFile.dll", + "tools/net462/System.IO.Compression.dll", + "tools/net462/System.IO.FileSystem.DriveInfo.dll", + "tools/net462/System.IO.FileSystem.Primitives.dll", + "tools/net462/System.IO.FileSystem.Watcher.dll", + "tools/net462/System.IO.FileSystem.dll", + "tools/net462/System.IO.IsolatedStorage.dll", + "tools/net462/System.IO.MemoryMappedFiles.dll", + "tools/net462/System.IO.Pipes.dll", + "tools/net462/System.IO.UnmanagedMemoryStream.dll", + "tools/net462/System.IO.dll", + "tools/net462/System.Linq.Expressions.dll", + "tools/net462/System.Linq.Parallel.dll", + "tools/net462/System.Linq.Queryable.dll", + "tools/net462/System.Linq.dll", + "tools/net462/System.Memory.dll", + "tools/net462/System.Net.Http.dll", + "tools/net462/System.Net.NameResolution.dll", + "tools/net462/System.Net.NetworkInformation.dll", + "tools/net462/System.Net.Ping.dll", + "tools/net462/System.Net.Primitives.dll", + "tools/net462/System.Net.Requests.dll", + "tools/net462/System.Net.Security.dll", + "tools/net462/System.Net.Sockets.dll", + "tools/net462/System.Net.WebHeaderCollection.dll", + "tools/net462/System.Net.WebSockets.Client.dll", + "tools/net462/System.Net.WebSockets.dll", + "tools/net462/System.Numerics.Vectors.dll", + "tools/net462/System.ObjectModel.dll", + "tools/net462/System.Reflection.Extensions.dll", + "tools/net462/System.Reflection.Primitives.dll", + "tools/net462/System.Reflection.dll", + "tools/net462/System.Resources.Reader.dll", + "tools/net462/System.Resources.ResourceManager.dll", + "tools/net462/System.Resources.Writer.dll", + "tools/net462/System.Runtime.CompilerServices.Unsafe.dll", + "tools/net462/System.Runtime.CompilerServices.VisualC.dll", + "tools/net462/System.Runtime.Extensions.dll", + "tools/net462/System.Runtime.Handles.dll", + "tools/net462/System.Runtime.InteropServices.RuntimeInformation.dll", + "tools/net462/System.Runtime.InteropServices.dll", + "tools/net462/System.Runtime.Numerics.dll", + "tools/net462/System.Runtime.Serialization.Formatters.dll", + "tools/net462/System.Runtime.Serialization.Json.dll", + "tools/net462/System.Runtime.Serialization.Primitives.dll", + "tools/net462/System.Runtime.Serialization.Xml.dll", + "tools/net462/System.Runtime.dll", + "tools/net462/System.Security.Claims.dll", + "tools/net462/System.Security.Cryptography.Algorithms.dll", + "tools/net462/System.Security.Cryptography.Csp.dll", + "tools/net462/System.Security.Cryptography.Encoding.dll", + "tools/net462/System.Security.Cryptography.Primitives.dll", + "tools/net462/System.Security.Cryptography.X509Certificates.dll", + "tools/net462/System.Security.Principal.dll", + "tools/net462/System.Security.SecureString.dll", + "tools/net462/System.Text.Encoding.Extensions.dll", + "tools/net462/System.Text.Encoding.dll", + "tools/net462/System.Text.RegularExpressions.dll", + "tools/net462/System.Threading.Overlapped.dll", + "tools/net462/System.Threading.Tasks.Parallel.dll", + "tools/net462/System.Threading.Tasks.dll", + "tools/net462/System.Threading.Thread.dll", + "tools/net462/System.Threading.ThreadPool.dll", + "tools/net462/System.Threading.Timer.dll", + "tools/net462/System.Threading.dll", + "tools/net462/System.ValueTuple.dll", + "tools/net462/System.Xml.ReaderWriter.dll", + "tools/net462/System.Xml.XDocument.dll", + "tools/net462/System.Xml.XPath.XDocument.dll", + "tools/net462/System.Xml.XPath.dll", + "tools/net462/System.Xml.XmlDocument.dll", + "tools/net462/System.Xml.XmlSerializer.dll", + "tools/net462/netstandard.dll", + "tools/net9.0/GetDocument.Insider.deps.json", + "tools/net9.0/GetDocument.Insider.dll", + "tools/net9.0/GetDocument.Insider.exe", + "tools/net9.0/GetDocument.Insider.runtimeconfig.json", + "tools/net9.0/Microsoft.AspNetCore.Connections.Abstractions.dll", + "tools/net9.0/Microsoft.AspNetCore.Connections.Abstractions.xml", + "tools/net9.0/Microsoft.AspNetCore.Hosting.Server.Abstractions.dll", + "tools/net9.0/Microsoft.AspNetCore.Hosting.Server.Abstractions.xml", + "tools/net9.0/Microsoft.AspNetCore.Http.Features.dll", + "tools/net9.0/Microsoft.AspNetCore.Http.Features.xml", + "tools/net9.0/Microsoft.Extensions.Configuration.Abstractions.dll", + "tools/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "tools/net9.0/Microsoft.Extensions.Diagnostics.Abstractions.dll", + "tools/net9.0/Microsoft.Extensions.Features.dll", + "tools/net9.0/Microsoft.Extensions.Features.xml", + "tools/net9.0/Microsoft.Extensions.FileProviders.Abstractions.dll", + "tools/net9.0/Microsoft.Extensions.Hosting.Abstractions.dll", + "tools/net9.0/Microsoft.Extensions.Logging.Abstractions.dll", + "tools/net9.0/Microsoft.Extensions.Options.dll", + "tools/net9.0/Microsoft.Extensions.Primitives.dll", + "tools/net9.0/Microsoft.Net.Http.Headers.dll", + "tools/net9.0/Microsoft.Net.Http.Headers.xml", + "tools/net9.0/Microsoft.OpenApi.dll", + "tools/netcoreapp2.1/GetDocument.Insider.deps.json", + "tools/netcoreapp2.1/GetDocument.Insider.dll", + "tools/netcoreapp2.1/GetDocument.Insider.runtimeconfig.json", + "tools/netcoreapp2.1/Microsoft.OpenApi.dll", + "tools/netcoreapp2.1/System.Diagnostics.DiagnosticSource.dll" + ] + }, + "Microsoft.OpenApi/2.4.1": { + "sha512": "u7QhXCISMQuab3flasb1hoaiERmUqyWsW7tmQODyILoQ7mJV5IRGM+2KKZYo0QUfC13evEOcHAb6TPWgqEQtrw==", + "type": "package", + "path": "microsoft.openapi/2.4.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "lib/net8.0/Microsoft.OpenApi.dll", + "lib/net8.0/Microsoft.OpenApi.pdb", + "lib/net8.0/Microsoft.OpenApi.xml", + "lib/netstandard2.0/Microsoft.OpenApi.dll", + "lib/netstandard2.0/Microsoft.OpenApi.pdb", + "lib/netstandard2.0/Microsoft.OpenApi.xml", + "microsoft.openapi.2.4.1.nupkg.sha512", + "microsoft.openapi.nuspec" + ] + }, + "Swashbuckle.AspNetCore/10.1.7": { + "sha512": "vgef8DPT411JU5JjHiDbr0WOxsIVuAvegPGtqmm4Na4JRl/264dfBJcGkiPHsAr5P+Vda+qN1rZKRtBl1rF9aA==", + "type": "package", + "path": "swashbuckle.aspnetcore/10.1.7", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/Swashbuckle.AspNetCore.props", + "buildMultiTargeting/Swashbuckle.AspNetCore.props", + "docs/package-readme.md", + "swashbuckle.aspnetcore.10.1.7.nupkg.sha512", + "swashbuckle.aspnetcore.nuspec" + ] + }, + "Swashbuckle.AspNetCore.Swagger/10.1.7": { + "sha512": "EjLibt/d/QuRv170GoihTbcPUpgzSFm2WKHhnGJFZQ03JYzfuitsM79azaAR8NBwRunU7yScSX6HRE5JUlrEMQ==", + "type": "package", + "path": "swashbuckle.aspnetcore.swagger/10.1.7", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net10.0/Swashbuckle.AspNetCore.Swagger.dll", + "lib/net10.0/Swashbuckle.AspNetCore.Swagger.pdb", + "lib/net10.0/Swashbuckle.AspNetCore.Swagger.xml", + "lib/net8.0/Swashbuckle.AspNetCore.Swagger.dll", + "lib/net8.0/Swashbuckle.AspNetCore.Swagger.pdb", + "lib/net8.0/Swashbuckle.AspNetCore.Swagger.xml", + "lib/net9.0/Swashbuckle.AspNetCore.Swagger.dll", + "lib/net9.0/Swashbuckle.AspNetCore.Swagger.pdb", + "lib/net9.0/Swashbuckle.AspNetCore.Swagger.xml", + "package-readme.md", + "swashbuckle.aspnetcore.swagger.10.1.7.nupkg.sha512", + "swashbuckle.aspnetcore.swagger.nuspec" + ] + }, + "Swashbuckle.AspNetCore.SwaggerGen/10.1.7": { + "sha512": "PuubO9BjvNn6U3D9kLpuWKY1JtziWw7SsGBq0age1E50uQjQ8Fzl8s0EwzrLfANqYJNgDnJi9l7N1QxcGVB2Zw==", + "type": "package", + "path": "swashbuckle.aspnetcore.swaggergen/10.1.7", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net10.0/Swashbuckle.AspNetCore.SwaggerGen.dll", + "lib/net10.0/Swashbuckle.AspNetCore.SwaggerGen.pdb", + "lib/net10.0/Swashbuckle.AspNetCore.SwaggerGen.xml", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerGen.dll", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerGen.pdb", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerGen.xml", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerGen.pdb", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerGen.xml", + "package-readme.md", + "swashbuckle.aspnetcore.swaggergen.10.1.7.nupkg.sha512", + "swashbuckle.aspnetcore.swaggergen.nuspec" + ] + }, + "Swashbuckle.AspNetCore.SwaggerUI/10.1.7": { + "sha512": "iJo3ODyUb/M8Vm8AH1r9y9iAba0w95xsCn3zFVl96ISRHbTDWxi+l7oFVCZqUEdjd97B8VMDPnMliWAdomR8uw==", + "type": "package", + "path": "swashbuckle.aspnetcore.swaggerui/10.1.7", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net10.0/Swashbuckle.AspNetCore.SwaggerUI.dll", + "lib/net10.0/Swashbuckle.AspNetCore.SwaggerUI.pdb", + "lib/net10.0/Swashbuckle.AspNetCore.SwaggerUI.xml", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerUI.dll", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerUI.pdb", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerUI.xml", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerUI.pdb", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerUI.xml", + "package-readme.md", + "swashbuckle.aspnetcore.swaggerui.10.1.7.nupkg.sha512", + "swashbuckle.aspnetcore.swaggerui.nuspec" + ] + }, + "System.Text.Json/8.0.5": { + "sha512": "0f1B50Ss7rqxXiaBJyzUu9bWFOO2/zSlifZ/UNMdiIpDYe4cY4LQQicP4nirK1OS31I43rn062UIJ1Q9bpmHpg==", + "type": "package", + "path": "system.text.json/8.0.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "analyzers/dotnet/roslyn3.11/cs/System.Text.Json.SourceGeneration.dll", + "analyzers/dotnet/roslyn3.11/cs/cs/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/de/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/es/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/fr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/it/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ja/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ko/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pl/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pt-BR/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ru/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/tr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hans/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hant/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/System.Text.Json.SourceGeneration.dll", + "analyzers/dotnet/roslyn4.0/cs/cs/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/de/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/es/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/fr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/it/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ja/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ko/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pl/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pt-BR/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ru/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/tr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hans/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hant/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/System.Text.Json.SourceGeneration.dll", + "analyzers/dotnet/roslyn4.4/cs/cs/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/de/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/es/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/fr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/it/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ja/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ko/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pl/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pt-BR/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ru/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/tr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hans/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hant/System.Text.Json.SourceGeneration.resources.dll", + "buildTransitive/net461/System.Text.Json.targets", + "buildTransitive/net462/System.Text.Json.targets", + "buildTransitive/net6.0/System.Text.Json.targets", + "buildTransitive/netcoreapp2.0/System.Text.Json.targets", + "buildTransitive/netstandard2.0/System.Text.Json.targets", + "lib/net462/System.Text.Json.dll", + "lib/net462/System.Text.Json.xml", + "lib/net6.0/System.Text.Json.dll", + "lib/net6.0/System.Text.Json.xml", + "lib/net7.0/System.Text.Json.dll", + "lib/net7.0/System.Text.Json.xml", + "lib/net8.0/System.Text.Json.dll", + "lib/net8.0/System.Text.Json.xml", + "lib/netstandard2.0/System.Text.Json.dll", + "lib/netstandard2.0/System.Text.Json.xml", + "system.text.json.8.0.5.nupkg.sha512", + "system.text.json.nuspec", + "useSharedDesignerContext.txt" + ] + } + }, + "projectFileDependencyGroups": { + "net9.0": [ + "Swashbuckle.AspNetCore >= 10.1.7" + ] + }, + "packageFolders": { + "/home/overseer/.nuget/packages/": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/home/overseer/projects/control-center/backend/ControlCenter/ControlCenter.csproj", + "projectName": "ControlCenter", + "projectPath": "/home/overseer/projects/control-center/backend/ControlCenter/ControlCenter.csproj", + "packagesPath": "/home/overseer/.nuget/packages/", + "outputPath": "/home/overseer/projects/control-center/backend/ControlCenter/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/home/overseer/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "net9.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "dependencies": { + "Swashbuckle.AspNetCore": { + "target": "Package", + "version": "[10.1.7, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "/home/overseer/.dotnet/sdk/9.0.312/PortableRuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/backend/ControlCenter/obj/project.nuget.cache b/backend/ControlCenter/obj/project.nuget.cache new file mode 100644 index 0000000..1ebfc14 --- /dev/null +++ b/backend/ControlCenter/obj/project.nuget.cache @@ -0,0 +1,16 @@ +{ + "version": 2, + "dgSpecHash": "MT3Qf7m9RtI=", + "success": true, + "projectFilePath": "/home/overseer/projects/control-center/backend/ControlCenter/ControlCenter.csproj", + "expectedPackageFiles": [ + "/home/overseer/.nuget/packages/microsoft.extensions.apidescription.server/9.0.0/microsoft.extensions.apidescription.server.9.0.0.nupkg.sha512", + "/home/overseer/.nuget/packages/microsoft.openapi/2.4.1/microsoft.openapi.2.4.1.nupkg.sha512", + "/home/overseer/.nuget/packages/swashbuckle.aspnetcore/10.1.7/swashbuckle.aspnetcore.10.1.7.nupkg.sha512", + "/home/overseer/.nuget/packages/swashbuckle.aspnetcore.swagger/10.1.7/swashbuckle.aspnetcore.swagger.10.1.7.nupkg.sha512", + "/home/overseer/.nuget/packages/swashbuckle.aspnetcore.swaggergen/10.1.7/swashbuckle.aspnetcore.swaggergen.10.1.7.nupkg.sha512", + "/home/overseer/.nuget/packages/swashbuckle.aspnetcore.swaggerui/10.1.7/swashbuckle.aspnetcore.swaggerui.10.1.7.nupkg.sha512", + "/home/overseer/.nuget/packages/system.text.json/8.0.5/system.text.json.8.0.5.nupkg.sha512" + ], + "logs": [] +} \ No newline at end of file