// Package handler contains HTTP handlers for the Control Center API. // Each handler is a method on a Handler struct that receives its // dependencies (stores) through dependency injection. package handler import ( "encoding/json" "net/http" "time" "code.cubecraftcreations.com/CubeCraft-Creations/Control-Center/go-backend/internal/models" "code.cubecraftcreations.com/CubeCraft-Creations/Control-Center/go-backend/internal/store" "github.com/go-chi/chi/v5" "github.com/go-playground/validator/v10" ) // Handler groups all route handlers and their dependencies. type Handler struct { AgentStore *store.AgentStore SessionStore *store.SessionStore TaskStore *store.TaskStore ProjectStore *store.ProjectStore validate *validator.Validate } // NewHandler returns a fully wired Handler. func NewHandler( as *store.AgentStore, ss *store.SessionStore, ts *store.TaskStore, ps *store.ProjectStore, ) *Handler { v := validator.New() v.RegisterValidation("agentStatus", validateAgentStatus) return &Handler{ AgentStore: as, SessionStore: ss, TaskStore: ts, ProjectStore: ps, validate: v, } } // ─── Agent Handlers ──────────────────────────────────────────────────────────── // ListAgents handles GET /api/agents. func (h *Handler) ListAgents(w http.ResponseWriter, r *http.Request) { statusFilter := models.AgentStatus(r.URL.Query().Get("status")) allAgents := h.AgentStore.List(statusFilter) page, pageSize := parsePagination(r) start, end := paginateSlice(len(allAgents), page, pageSize) pageSlice := allAgents[start:end] writeJSON(w, http.StatusOK, models.PaginatedResponse{ Data: pageSlice, TotalCount: h.AgentStore.Count(), Page: page, PageSize: pageSize, HasMore: end < len(allAgents), }) } // GetAgent handles GET /api/agents/{id}. func (h *Handler) GetAgent(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") agent, ok := h.AgentStore.Get(id) if !ok { writeJSON(w, http.StatusNotFound, models.ErrorResponse{Error: "agent not found"}) return } writeJSON(w, http.StatusOK, agent) } // CreateAgent handles POST /api/agents. func (h *Handler) CreateAgent(w http.ResponseWriter, r *http.Request) { var req models.CreateAgentRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeJSON(w, http.StatusBadRequest, models.ErrorResponse{Error: "invalid request body"}) return } if err := h.validate.Struct(req); err != nil { writeJSON(w, http.StatusUnprocessableEntity, models.ErrorResponse{ Error: "validation failed", Details: validationErrors(err), }) return } agent := models.AgentCardData{ ID: req.ID, DisplayName: req.DisplayName, Role: req.Role, Status: req.Status, CurrentTask: req.CurrentTask, SessionKey: req.SessionKey, Channel: req.Channel, LastActivity: time.Now().UTC().Format(time.RFC3339), } if ok := h.AgentStore.Create(agent); !ok { writeJSON(w, http.StatusConflict, models.ErrorResponse{Error: "agent with this ID already exists"}) return } writeJSON(w, http.StatusCreated, agent) } // UpdateAgent handles PUT /api/agents/{id}. func (h *Handler) UpdateAgent(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") var req models.UpdateAgentRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeJSON(w, http.StatusBadRequest, models.ErrorResponse{Error: "invalid request body"}) return } if err := h.validate.Struct(req); err != nil { writeJSON(w, http.StatusUnprocessableEntity, models.ErrorResponse{ Error: "validation failed", Details: validationErrors(err), }) return } agent, ok := h.AgentStore.Update(id, req) if !ok { writeJSON(w, http.StatusNotFound, models.ErrorResponse{Error: "agent not found"}) return } writeJSON(w, http.StatusOK, agent) } // DeleteAgent handles DELETE /api/agents/{id}. func (h *Handler) DeleteAgent(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") if ok := h.AgentStore.Delete(id); !ok { writeJSON(w, http.StatusNotFound, models.ErrorResponse{Error: "agent not found"}) return } w.WriteHeader(http.StatusNoContent) } // AgentHistory handles GET /api/agents/{id}/history. func (h *Handler) AgentHistory(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") if _, ok := h.AgentStore.Get(id); !ok { writeJSON(w, http.StatusNotFound, models.ErrorResponse{Error: "agent not found"}) return } history := h.AgentStore.History(id) if history == nil { history = []models.AgentStatusHistoryEntry{} } writeJSON(w, http.StatusOK, history) }