159 lines
4.6 KiB
Go
159 lines
4.6 KiB
Go
// 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)
|
|
}
|