d370d5ec235052aa067bcd4f480b5a05d177408c
The root cause of the initial sync timeout was that connectAndRun called initialSync (which uses Send/RPC) before starting readLoop, but Send's response delivery depends on readLoop→routeFrame→handleResponse. Without the readLoop running, agents.list and sessions.list would always time out. Fix: start readLoop in a goroutine before calling initialSync so that RPC responses are properly routed back to pending Send() calls. After initialSync completes, event handlers are registered and MarkWSReady is called. The connectAndRun function then blocks on the readLoop goroutine's completion. Also added TestConnectAndRun_InitialSyncOrdering which verifies that agents are persisted from initial sync (would hang/timeout under the old ordering).
CUB-200: resolve merge conflicts with dev — adopt dev's consolidated workflows and improved Go gateway code
Control Center
Real-time agent fleet dashboard for the OpenClaw AI development team.
Control Center monitors and controls the full CubeCraft Creations AI agent fleet — Otto, Rex, Dex, Hex, Pip, Nano, Sketch, Bob, Stuart, Norbert, and Flip. It provides live agent status, task progress, session logs, and a command interface, backed by SignalR for push-based updates directly from the OpenClaw gateway.
Tech Stack
| Layer | Technology |
|---|---|
| Backend | ASP.NET Core Web API (.NET 8) |
| Database | PostgreSQL (snake_case via EF Core) |
| ORM | Entity Framework Core |
| Real-time | SignalR (AgentStatusHub) |
| Frontend | Angular (latest), Angular Material, Angular Signals |
| API Client | TypeScript package (api-client/) |
| Deployment | Docker |
Project Structure
Control-Center/
├── backend/
│ ├── ControlCenter/
│ │ ├── Controllers/ # AgentsController, CommandController, LogsController
│ │ ├── Hubs/ # AgentStatusHub, IAgentStatusClient, AgentStatusModels
│ │ ├── Models/ # AgentMinionMapping
│ │ ├── Services/ # AgentMinionMapperService, GatewayEventBridgeService
│ │ ├── Program.cs
│ │ └── appsettings.json
│ ├── Configurations/ # AgentConfiguration
│ ├── Data/ # AppDbContext, AppDbContextFactory
│ ├── Dtos/ # AgentStatusUpdateDto
│ ├── Entities/ # Agent, AgentStatus
│ ├── Migrations/ # EF migrations
│ ├── Models/ # AgentState
│ └── Repositories/ # AgentStateRepository, IAgentStateRepository
├── frontend/
│ └── src/app/
│ ├── layout/ # LayoutShell, HeaderBar, NavRail, BottomNav
│ ├── pages/ # hub, logs, projects, sessions, settings
│ ├── components/ # AgentCard, AgentStatusBadge, TaskProgressBar,
│ │ # QuickJumpButton, QuickJumpDrawer,
│ │ # GlobalActionModal, AdaptiveNavigation
│ ├── command-hub/ # AgentCard command hub view
│ ├── models/ # Agent model, AgentStatus, AgentCardData, Nav
│ └── services/ # AgentStatusService (Angular Signals)
├── api-client/ # Shared TS client (models, SignalR WS, HTTP utils)
├── design/
│ ├── command-hub-spec.md
│ └── mockups/ # Desktop kiosk, mobile, quick-jump drawer
└── README.md
Domain Model
Agent
| Field | Type | Description |
|---|---|---|
Id |
Guid |
Primary key |
Status |
AgentStatus |
Current agent state |
Task |
string? |
Active task description |
Progress |
int? |
Task completion % (0–100) |
SessionKey |
string |
OpenClaw session identifier |
Channel |
string |
Source channel (telegram, slack, etc.) |
LastActivity |
DateTime |
Last event timestamp |
CreatedAt / UpdatedAt |
DateTime |
Audit fields |
AgentStatus enum
| Value | Integer | Meaning |
|---|---|---|
Active |
0 | Agent is executing a task |
Idle |
1 | Agent is waiting for work |
Thinking |
2 | Agent is reasoning/planning |
Error |
3 | Agent hit an unrecoverable state |
Key Design Decisions
- Angular Signals — Reactive state management. No NgRx — kept intentionally simple.
- Adaptive layout — Sidebar nav (NavRail) on desktop/kiosk (≥768px); bottom nav on mobile.
- Tactical Dark Mode — Theme via CSS custom properties in
styles.scss. - SignalR fleet group — Clients call
JoinFleet()to subscribe to all agent updates broadcast by the hub. - Backend push model — Hub uses
IHubContext<AgentStatusHub, IAgentStatusClient>extension methods to push to clients; no polling. - Gateway bridge —
GatewayEventBridgeServiceconnects the OpenClaw gateway WebSocket to the SignalR hub.
Getting Started
Prerequisites
- .NET 8 SDK
- Node.js 20+
- Docker
- PostgreSQL
- Running OpenClaw gateway (for live agent events)
Backend
cd backend
# Restore and build
dotnet restore
dotnet build
# Apply migrations
dotnet ef database update --project ControlCenter
# Run API
dotnet run --project ControlCenter
API runs at http://localhost:5000 · Swagger at http://localhost:5000/swagger
Frontend
cd frontend
npm install
ng serve
Frontend runs at http://localhost:4200
Configuration
backend/ControlCenter/appsettings.json — override in appsettings.Development.json or environment variables:
| Key | Default | Description |
|---|---|---|
ConnectionStrings:DefaultConnection |
(set in dev config) | PostgreSQL connection string |
Gateway:WebSocketUrl |
ws://localhost:3271/ws |
OpenClaw gateway WebSocket URL |
Gateway:AuthToken |
"" |
Gateway auth token |
Cors:AllowedOrigins |
localhost:4200, localhost:5000 |
Frontend origins for CORS |
Real-Time Events
SignalR hub endpoint: /hubs/agent-status
Hub Methods (server → client)
| Method | Payload | Description |
|---|---|---|
ReceiveStatusUpdate |
AgentStatusUpdateDto |
Agent status changed |
ReceiveAgentList |
Agent[] |
Full fleet snapshot on join |
Client → Server
| Method | Description |
|---|---|
JoinFleet() |
Subscribe to all agent updates |
LeaveFleet() |
Unsubscribe |
SendStatusUpdate(dto) |
Push a status update (internal use) |
Pages
| Route | Page | Description |
|---|---|---|
/hub |
Command Hub | Live agent grid — status, task, progress |
/logs |
Logs | Agent session log viewer |
/projects |
Projects | Linear project tracking view |
/sessions |
Sessions | OpenClaw session browser |
/settings |
Settings | App configuration |
Agent Fleet
| Agent | Role |
|---|---|
| Otto | Orchestrator — owns the dev lifecycle |
| Rex | Frontend (Angular) |
| Dex | Backend (ASP.NET Core) |
| Hex | Database (schema, migrations) |
| Pip | Raspberry Pi / Python |
| Nano | Arduino / ESP32 / ESPHome |
| Sketch | UX/UI design |
| Flip | Mobile development |
| Bob | Content & marketing copy |
| Stuart | Concept visualization (images) |
| Norbert | 3D design (OpenSCAD) |
Branch & PR Rules
- All feature branches target
dev— nevermain - Branch naming:
agent/<agent>/CUB-N-short-description - PR titles:
CUB-N: short description - PRs require Otto review before Joshua merges
API Overview
| Route prefix | Resource |
|---|---|
/api/agents |
Agent registry and status |
/api/command |
Issue commands to agents |
/api/logs |
Session log retrieval |
Full schema at /swagger when running in dev.
Built by CubeCraft Creations · Orchestrated by Otto
Description
Languages
TypeScript
34.1%
Go
26.6%
SCSS
17.9%
C#
15.2%
HTML
4.6%
Other
1.6%