Skip to content

el-pablos/subagent-work-view

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

47 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎯 SubAgent Work View β€” War Room Dashboard

React Laravel TypeScript Tailwind Soketi MySQL

Commits Contributors LOC Version Tests

Dashboard monitoring realtime buat ngawasin AI sub-agent yang jalan di server kamu.

Auto-detect agent dari Claude Code, OpenClaw, dan Copilot CLI β€” semua keliatan live di satu layar.

🌐 Live Demo Β· πŸ› Report Bug Β· πŸ“– Docs


πŸ“ Deskripsi Projek

SubAgent Work View itu war room dashboard buat monitoring AI agent secara realtime. Jadi misal kamu lagi jalanin Claude Code, OpenClaw, atau Copilot CLI di server β€” semua agent, task, dan message mereka bakal muncul otomatis di dashboard ini lewat WebSocket.

Bayangin kayak mission control NASA, tapi buat AI agents πŸš€

Fitur Utama

Fitur Deskripsi
πŸ” Auto-detect Agents Otomatis detect agent dari Claude Code, OpenClaw, dan Copilot CLI
πŸ“‘ Realtime Updates WebSocket live updates via Soketi (Pusher-compatible)
πŸ—ΊοΈ Agent Topology Visualisasi koneksi antar agent dalam circular layout
πŸ“‹ Task Tracker Pantau progress task dengan timeline dan progress bar
πŸ’¬ Communication Log Semua inter-agent message dalam satu panel
πŸ”” Smart Notifications Toast + drawer buat event penting (spawn, complete, error)
πŸŒ™ Dark Glassmorphism Design modern dengan backdrop blur yang keren
πŸ“± Mobile-first Bottom nav di mobile, 12-column grid di desktop
⚑ PWA Ready Bisa di-install sebagai app, offline-capable
πŸ”„ Auto-reconnect WebSocket reconnect otomatis dengan exponential backoff

πŸ—οΈ Arsitektur Sistem

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              INTERNET                                            β”‚
β”‚                                  β”‚                                               β”‚
β”‚                          β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”                                       β”‚
β”‚                          β”‚   CLOUDFLARE   β”‚                                      β”‚
β”‚                          β”‚   (DNS/CDN)    β”‚                                      β”‚
β”‚                          β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                   β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              VPS SERVER                                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚                    NGINX (:443 HTTPS + SSL/TLS)                              β”‚ β”‚
β”‚  β”‚              Let's Encrypt Auto-Renewal Certificate                          β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                            β”‚                                                      β”‚
β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚     β”‚                      β”‚                                      β”‚              β”‚
β”‚     β–Ό                      β–Ό                                      β–Ό              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚ FRONTEND β”‚       β”‚   BACKEND    β”‚                      β”‚   WEBSOCKET  β”‚       β”‚
β”‚  β”‚  (SPA)   β”‚       β”‚     API      β”‚                      β”‚    PROXY     β”‚       β”‚
β”‚  β”‚ /dist/*  β”‚       β”‚ /api/v1/*    β”‚                      β”‚ /app/* /apps β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                      β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β”‚                            β”‚                                      β”‚              β”‚
β”‚                            β–Ό                                      β–Ό              β”‚
β”‚                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚                 β”‚   PHP-FPM 8.3    β”‚                    β”‚     SOKETI       β”‚     β”‚
β”‚                 β”‚   Laravel 11     │◄──── broadcast ────│    (Docker)      β”‚     β”‚
β”‚                 β”‚  :8005 (TCP)     β”‚                    β”‚  :6001 (WS)      β”‚     β”‚
β”‚                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚                          β”‚                                                       β”‚
β”‚           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                       β”‚
β”‚           β”‚              β”‚              β”‚                                        β”‚
β”‚           β–Ό              β–Ό              β–Ό                                        β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                               β”‚
β”‚   β”‚   MySQL 8   β”‚ β”‚    Redis    β”‚ β”‚   Queue     β”‚                               β”‚
β”‚   β”‚  :3306      β”‚ β”‚   :6379     β”‚ β”‚  Worker     β”‚                               β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                               β”‚
β”‚                                                                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β–²                β–²                 β–²
                    β”‚                β”‚                 β”‚
               β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”
               β”‚ Claude  β”‚     β”‚ OpenClaw  β”‚    β”‚ Copilot    β”‚
               β”‚  Code   β”‚     β”‚  Gateway  β”‚    β”‚   CLI      β”‚
               β”‚ (hooks) β”‚     β”‚ (JSONL)   β”‚    β”‚ (webhook)  β”‚
               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”„ Flow Data (Webhook β†’ Realtime)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           DATA FLOW DIAGRAM                                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                                 β”‚
β”‚  β”‚ Claude Code │──┐                                                              β”‚
β”‚  β”‚   (hooks)   β”‚  β”‚                                                              β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚                                                              β”‚
β”‚                   β”‚     POST /api/v1/webhook/{source}                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚  OpenClaw   │──┼────▢│                WEBHOOK CONTROLLER                    β”‚ β”‚
β”‚  β”‚  (JSONL)    β”‚  β”‚     β”‚  β€’ Validate payload                                  β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚     β”‚  β€’ Normalize format (claude/openclaw/copilot)        β”‚ β”‚
β”‚                   β”‚     β”‚  β€’ Extract session_id, agent_id, event_type          β”‚ β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚  β”‚ Copilot CLI β”‚β”€β”€β”˜                            β”‚                                 β”‚
β”‚  β”‚  (webhook)  β”‚                               β–Ό                                 β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                     β”‚
β”‚                                     β”‚  AGENT INGEST SVC   β”‚                     β”‚
β”‚                                     β”‚  β€’ upsertSession()  β”‚                     β”‚
β”‚                                     β”‚  β€’ upsertAgent()    β”‚                     β”‚
β”‚                                     β”‚  β€’ createMessage()  β”‚                     β”‚
β”‚                                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                     β”‚
β”‚                                                β”‚                                 β”‚
β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚
β”‚                           β–Ό                    β–Ό                    β–Ό           β”‚
β”‚                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚                    β”‚   MySQL    β”‚       β”‚  Broadcast β”‚       β”‚   Redis    β”‚    β”‚
β”‚                    β”‚  (store)   β”‚       β”‚   Event    β”‚       β”‚  (cache)   β”‚    β”‚
β”‚                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                               β”‚                                 β”‚
β”‚                                               β–Ό                                 β”‚
β”‚                                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                          β”‚
β”‚                                        β”‚   SOKETI   β”‚                          β”‚
β”‚                                        β”‚ WebSocket  β”‚                          β”‚
β”‚                                        β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚                                               β”‚                                 β”‚
β”‚                                               β–Ό                                 β”‚
β”‚                                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                          β”‚
β”‚                                        β”‚  FRONTEND  β”‚                          β”‚
β”‚                                        β”‚  (React)   β”‚                          β”‚
β”‚                                        β”‚  Realtime! β”‚                          β”‚
β”‚                                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚                                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“Š Entity Relationship Diagram (ERD)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      User       β”‚       β”‚     Session     β”‚       β”‚      Agent      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ id          PK  │──┐    β”‚ id          PK  β”‚    β”Œβ”€β”€β”‚ id          PK  β”‚
β”‚ name            β”‚  β”‚    β”‚ uuid            β”‚    β”‚  β”‚ uuid            β”‚
β”‚ email           β”‚  β”‚    β”‚ external_id     β”‚    β”‚  β”‚ name            β”‚
β”‚ password        β”‚  └───▢│ created_by  FK  β”‚    β”‚  β”‚ type (enum)     β”‚
β”‚ created_at      β”‚       β”‚ status (enum)   │◀───┼──│ session_id  FK  β”‚
β”‚ updated_at      β”‚       β”‚ command_source  β”‚    β”‚  β”‚ status (enum)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚ original_commandβ”‚    β”‚  β”‚ source          β”‚
                          β”‚ context (json)  β”‚    β”‚  β”‚ capabilities    β”‚
                          β”‚ started_at      β”‚    β”‚  β”‚ last_seen_at    β”‚
                          β”‚ ended_at        β”‚    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚           β”‚
                                   β”‚             β”‚           β”‚ has many
                          has many β”‚             β”‚           β–Ό
                                   β–Ό             β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚  β”‚    TaskLog      β”‚
                          β”‚      Task       β”‚   β”‚  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                          β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€   β”‚  β”‚ id          PK  β”‚
                          β”‚ id          PK  │◀──┼──│ task_id     FK  β”‚
                          β”‚ uuid            β”‚   β”‚  β”‚ agent_id    FK  │──┐
                          β”‚ session_id  FK  β”‚   β”‚  β”‚ action          β”‚  β”‚
                          β”‚ title           β”‚   β”‚  β”‚ notes           β”‚  β”‚
                          β”‚ status (enum)   β”‚   β”‚  β”‚ meta (json)     β”‚  β”‚
                          β”‚ agent_id    FK  β”‚β”€β”€β”€β”˜  β”‚ timestamp       β”‚  β”‚
                          β”‚ progress 0-100  β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
                          β”‚ dependencies    β”‚                           β”‚
                          β”‚ payload (json)  β”‚                           β”‚
                          β”‚ result (json)   β”‚                           β”‚
                          β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                           β”‚
                                   β”‚                                    β”‚
                          has many β”‚                                    β”‚
                                   β–Ό                                    β”‚
                          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                           β”‚
                          β”‚    Message      β”‚                           β”‚
                          β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€                           β”‚
                          β”‚ id          PK  β”‚                           β”‚
                          β”‚ session_id  FK  β”‚                           β”‚
                          β”‚ from_agent  FK  │◀───────────────────────────
                          β”‚ to_agent    FK  β”‚β—€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚ content         β”‚
                          β”‚ message_type    β”‚
                          β”‚ channel         β”‚
                          β”‚ timestamp       β”‚
                          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Enum Values

Enum Values
AgentStatus idle, busy, communicating, error, offline
AgentType planner, architect, coder, reviewer, tester, docs, devops
SessionStatus queued, planning, running, completed, failed, cancelled
TaskStatus pending, assigned, running, blocked, completed, failed, cancelled
MessageType agent, system, user, broadcast

πŸ“‘ WebSocket Events

Channel Structure

Channel Scope Events
dashboard.global Global All dashboard updates
session.{id} Session-specific Messages, task updates
agent.{id} Agent-specific Status changes

Event Types

Event Channel Payload Trigger
agent.created dashboard.global {agent: {...}} Agent spawned
agent.status_changed dashboard.global, agent.{id} {agent: {...}} Status update
session.created dashboard.global {session: {...}} New session
session.completed dashboard.global, session.{id} {session: {...}} Session finished
task.created dashboard.global, session.{id} {task: {...}} New task
task.updated dashboard.global, session.{id} {task: {...}} Progress update
task.completed dashboard.global, session.{id} {task: {...}} Task finished
message.created session.{id} {message: {...}} Inter-agent message

πŸ”— API Endpoints

Sessions

Method Endpoint Description
GET /api/v1/sessions List semua sessions (paginated)
POST /api/v1/sessions Buat session baru
GET /api/v1/sessions/{id} Detail session
GET /api/v1/sessions/active Sessions yang lagi running
POST /api/v1/sessions/{id}/start Start session
POST /api/v1/sessions/{id}/cancel Cancel session
GET /api/v1/sessions/{id}/timeline Timeline events

Agents

Method Endpoint Description
GET /api/v1/agents List semua agents
POST /api/v1/agents Register agent baru
PATCH /api/v1/agents/{id}/status Update status agent
POST /api/v1/agents/{id}/heartbeat Heartbeat ping
GET /api/v1/agents/overview/stats Statistik agents

Tasks

Method Endpoint Description
GET /api/v1/tasks List tasks (filterable)
POST /api/v1/tasks Buat task baru
POST /api/v1/tasks/{id}/assign Assign ke agent
POST /api/v1/tasks/{id}/retry Retry failed task

Webhooks

Method Endpoint Description
POST /api/v1/webhook/claude Webhook dari Claude Code
POST /api/v1/webhook/openclaw Webhook dari OpenClaw
POST /api/v1/webhook/copilot-cli Webhook dari Copilot CLI

Dashboard

Method Endpoint Description
GET /api/v1/dashboard/overview Overview stats
GET /api/v1/dashboard/metrics Performance metrics
GET /api/v1/health Health check

πŸ—‚οΈ Struktur Folder

subagent-work-view/
β”œβ”€β”€ πŸ“ frontend/                      # React 19 + Vite 8 + TypeScript
β”‚   β”œβ”€β”€ πŸ“ src/
β”‚   β”‚   β”œβ”€β”€ πŸ“ components/
β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ agents/            # AgentNode, AgentTopologyPanel, StatusRing
β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ command/           # CommandConsole, CommandPalette
β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ common/            # Badge, GlassPanel, Toast, Skeleton
β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ communication/     # MessageBubble, CommunicationLogPanel
β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ layout/            # WarRoomLayout, Header
β”‚   β”‚   β”‚   └── πŸ“ tasks/             # TaskCard, TaskTimeline, ProgressBar
β”‚   β”‚   β”œβ”€β”€ πŸ“ hooks/                 # useWebSocket, useDebounce, useMediaQuery
β”‚   β”‚   β”œβ”€β”€ πŸ“ stores/                # Zustand: agent, task, session, notification
β”‚   β”‚   β”œβ”€β”€ πŸ“ services/              # api.ts, websocket.ts (auto-reconnect)
β”‚   β”‚   β”œβ”€β”€ πŸ“ lib/                   # adapters, animations, utils
β”‚   β”‚   └── πŸ“ types/                 # TypeScript definitions
β”‚   β”œβ”€β”€ πŸ“ e2e/                       # Playwright E2E tests
β”‚   └── πŸ“ dist/                      # Production build
β”‚
β”œβ”€β”€ πŸ“ backend/                       # Laravel 11 + PHP 8.3
β”‚   β”œβ”€β”€ πŸ“ app/
β”‚   β”‚   β”œβ”€β”€ πŸ“ Http/Controllers/Api/  # REST API controllers
β”‚   β”‚   β”œβ”€β”€ πŸ“ Models/                # Agent, Session, Task, Message, TaskLog
β”‚   β”‚   β”œβ”€β”€ πŸ“ Events/                # Broadcasting events
β”‚   β”‚   β”œβ”€β”€ πŸ“ Jobs/                  # Queue jobs
β”‚   β”‚   β”œβ”€β”€ πŸ“ Services/
β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ Orchestration/     # TaskPlanner, TaskDistribution
β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ Webhook/           # AgentIngest, WebhookNormalizer
β”‚   β”‚   β”‚   └── πŸ“ Agent/             # AgentHealth, AgentRegistry
β”‚   β”‚   └── πŸ“ Enums/                 # Status enums
β”‚   β”œβ”€β”€ πŸ“ database/migrations/       # Schema definitions
β”‚   └── πŸ“ routes/api.php             # API routes
β”‚
β”œβ”€β”€ πŸ“ docker/                        # Docker configs
β”‚   β”œβ”€β”€ πŸ“ nginx/                     # Nginx config
β”‚   β”œβ”€β”€ πŸ“ php/                       # PHP-FPM Dockerfile
β”‚   └── πŸ“ supervisor/                # Queue worker config
β”‚
β”œβ”€β”€ πŸ“ claude-hooks/                  # Claude Code integration
β”œβ”€β”€ πŸ“ .github/workflows/             # CI/CD pipeline
β”œβ”€β”€ πŸ“„ docker-compose.yml             # Development stack
└── πŸ“„ README.md                      # You are here!

βš™οΈ Environment Variables

Backend .env

# App
APP_NAME="SubAgent Work View"
APP_ENV=production
APP_URL=https://live-agents.tams.codes

# Database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=subagent_workview
DB_USERNAME=root
DB_PASSWORD=secret

# Broadcasting (Soketi)
BROADCAST_CONNECTION=pusher
PUSHER_APP_ID=subagent-app
PUSHER_APP_KEY=subagent-key
PUSHER_APP_SECRET=subagent-secret
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=http

# Queue
QUEUE_CONNECTION=database

Frontend .env

VITE_API_URL=https://live-agents.tams.codes/api
VITE_PUSHER_APP_KEY=subagent-key
VITE_PUSHER_HOST=live-agents.tams.codes
VITE_PUSHER_PORT=443
VITE_PUSHER_SCHEME=https

πŸš€ Quick Start

Prerequisites

  • Node.js 20+ LTS
  • PHP 8.3+
  • MySQL 8.0+
  • Docker & Docker Compose (optional)

Development

# Clone repo
git clone https://github.com/el-pablos/subagent-work-view.git
cd subagent-work-view

# Frontend
cd frontend
cp .env.example .env
npm install
npm run dev        # http://localhost:5173

# Backend (terminal baru)
cd backend
cp .env.example .env
composer install
php artisan migrate
php artisan serve  # http://localhost:8000

# Soketi WebSocket (terminal baru)
docker run -d --name soketi \
  -p 6001:6001 \
  -e SOKETI_DEFAULT_APP_ID=subagent-app \
  -e SOKETI_DEFAULT_APP_KEY=subagent-key \
  -e SOKETI_DEFAULT_APP_SECRET=subagent-secret \
  quay.io/soketi/soketi:1.6-16-debian

Docker (All-in-one)

# Copy env dan jalankan semua services
cp .env.example .env
docker compose up -d

# Akses di http://localhost

πŸ”Œ Integrasi Agent

Claude Code

Hook scripts di claude-hooks/ yang POST ke webhook setiap ada tool use:

# Install hooks
cp claude-hooks/* ~/.claude/hooks/
chmod +x ~/.claude/hooks/*.sh

Events yang di-track:

  • agent_spawn β€” ketika Task tool dipanggil
  • agent_message β€” ketika SendMessage dipanggil
  • agent_action β€” tool use lainnya

OpenClaw

Daemon watcher yang tail JSONL session files:

# Start watcher
php artisan openclaw:watch

# Auto-detect session baru dan kirim ke webhook

Copilot CLI

Webhook endpoint siap terima payload. Source auto-detect dari agent name/UUID.


πŸ§ͺ Testing

# Frontend Unit Tests (Vitest)
cd frontend && npm test

# Frontend E2E Tests (Playwright)
cd frontend && npm run test:e2e

# Backend Tests (PHPUnit)
cd backend && php artisan test

# Type Check
cd frontend && npm run typecheck

# Lint
cd frontend && npm run lint
cd backend && ./vendor/bin/pint

πŸ“ˆ Statistik Repo

Metric Value
πŸ”’ Total Commits 42+
πŸ‘₯ Contributors 2
πŸ“‚ Source Files 27K+
πŸ“ Lines of Code 677K+
πŸš€ Latest Release v1.0.0
βœ… Unit Tests 39 passed
βœ… E2E Tests 5 passed
πŸ“± Responsive Mobile-first
⚑ PWA Service Worker + Manifest
πŸ”„ CI/CD GitHub Actions + Auto Release

Tech Stack Breakdown

Layer Technologies
Frontend React 19, Vite 8, TypeScript 5.9, Tailwind CSS 4, Zustand 5, Framer Motion 12
Backend Laravel 11, PHP 8.3, MySQL 8, Redis
Realtime Soketi (Pusher-compatible), Laravel Echo, Pusher.js
Testing Vitest, Playwright, PHPUnit
DevOps Docker, Nginx, GitHub Actions, Let's Encrypt

🀝 Kontributor

el-pablos
el-pablos

πŸ§‘β€πŸ’» Creator & Lead Developer
41 commits (97.6%)
Claude
Claude (Anthropic)

πŸ€– AI Pair Programmer
Deep Analysis & Code Gen
Copilot
GitHub Copilot

πŸ€– AI Co-author
1 commit (2.4%)

πŸ“„ Lisensi

MIT License β€” bebas dipake, dimodif, dan didistribusi.

MIT License

Copyright (c) 2026 el-pablos

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Built with ❀️ and πŸ€– AI-powered development

War Room Dashboard β€” karena ngawasin AI agent harusnya gak ribet.


🌐 Live Demo Β· πŸ“– Documentation Β· πŸ› Issues