CUB-123: integrate gateway, wire PostgreSQL repositories, add SSE streaming
All checks were successful
Dev Build / build-test (pull_request) Successful in 2m23s

- Create repository/ package with pgx-backed CRUD for agents, sessions, tasks, projects
- Define AgentRepo/SessionRepo/TaskRepo/ProjectRepo interfaces
- Update handler to use repository interfaces instead of in-memory stores
- Add SSE broker with GET /api/events endpoint (text/event-stream)
- Add gateway client that polls OpenClaw for agent states
- Add GATEWAY_URL and GATEWAY_POLL_INTERVAL config fields
- Seed 5 demo agents (Otto, Rex, Dex, Hex, Pip) on empty DB
- Update router to wire SSE broker
- All 21 handler tests pass with mock repos
This commit is contained in:
2026-05-08 19:58:06 -04:00
parent 4a2e660a4a
commit e8ced74429
16 changed files with 1207 additions and 109 deletions

View File

@@ -3,6 +3,7 @@
package router
import (
"context"
"net/http"
"time"
@@ -13,11 +14,13 @@ import (
"github.com/go-chi/cors"
)
// Dependencies carries the handler and database pool into the router.
// Dependencies carries the handler, database pool, SSE broker, and CORS
// configuration into the router.
type Dependencies struct {
Handler *handler.Handler
DB *db.Pool
Handler *handler.Handler
Pool *db.Pool
CORSOrigin string
Broker *handler.Broker
}
// New creates a fully-configured chi router with all API routes mounted.
@@ -49,8 +52,10 @@ func New(deps *Dependencies) *chi.Mux {
r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
status := "ok"
if deps.DB != nil {
if err := deps.DB.Health(r.Context()); err != nil {
if deps.Pool != nil {
ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
defer cancel()
if err := deps.Pool.Ping(ctx); err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
status = "db_unhealthy"
}
@@ -62,11 +67,11 @@ func New(deps *Dependencies) *chi.Mux {
r.Route("/api", func(api chi.Router) {
// Agents CRUD
api.Route("/agents", func(agents chi.Router) {
agents.Get("/", deps.Handler.ListAgents) // GET /api/agents
agents.Post("/", deps.Handler.CreateAgent) // POST /api/agents
agents.Get("/{id}", deps.Handler.GetAgent) // GET /api/agents/{id}
agents.Put("/{id}", deps.Handler.UpdateAgent) // PUT /api/agents/{id}
agents.Delete("/{id}", deps.Handler.DeleteAgent) // DELETE /api/agents/{id}
agents.Get("/", deps.Handler.ListAgents) // GET /api/agents
agents.Post("/", deps.Handler.CreateAgent) // POST /api/agents
agents.Get("/{id}", deps.Handler.GetAgent) // GET /api/agents/{id}
agents.Put("/{id}", deps.Handler.UpdateAgent) // PUT /api/agents/{id}
agents.Delete("/{id}", deps.Handler.DeleteAgent) // DELETE /api/agents/{id}
agents.Get("/{id}/history", deps.Handler.AgentHistory) // GET /api/agents/{id}/history
})
@@ -78,6 +83,9 @@ func New(deps *Dependencies) *chi.Mux {
// Projects
api.Get("/projects", deps.Handler.ListProjects)
// SSE event stream
api.Get("/events", deps.Broker.ServeHTTP)
})
return r