package api import ( "net/http" "strings" "github.com/ez-api/ez-api/internal/service" "github.com/gin-gonic/gin" ) type ModelRegistryHandler struct { reg *service.ModelRegistryService } func NewModelRegistryHandler(reg *service.ModelRegistryService) *ModelRegistryHandler { return &ModelRegistryHandler{reg: reg} } // GetModelRegistryStatus godoc // @Summary Get model registry status // @Description Returns Redis meta and local last-good cache info for model capability registry // @Tags admin // @Produce json // @Security AdminAuth // @Success 200 {object} ResponseEnvelope{data=service.ModelRegistryStatus} // @Failure 500 {object} ResponseEnvelope{data=gin.H} // @Router /admin/model-registry/status [get] func (h *ModelRegistryHandler) GetStatus(c *gin.Context) { if h == nil || h.reg == nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "model registry not configured"}) return } st, err := h.reg.Status(c.Request.Context()) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get model registry status", "details": err.Error()}) return } c.JSON(http.StatusOK, st) } type refreshModelRegistryRequest struct { Ref string `json:"ref"` } // CheckModelRegistry godoc // @Summary Check model registry upstream version // @Description Checks models.dev commit SHA for a ref and indicates whether refresh is needed (does not apply changes) // @Tags admin // @Accept json // @Produce json // @Security AdminAuth // @Param body body refreshModelRegistryRequest false "optional override ref" // @Success 200 {object} ResponseEnvelope{data=service.ModelRegistryCheckResult} // @Failure 400 {object} ResponseEnvelope{data=gin.H} // @Failure 500 {object} ResponseEnvelope{data=gin.H} // @Router /admin/model-registry/check [post] func (h *ModelRegistryHandler) Check(c *gin.Context) { if h == nil || h.reg == nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "model registry not configured"}) return } var req refreshModelRegistryRequest _ = c.ShouldBindJSON(&req) ref := strings.TrimSpace(req.Ref) out, err := h.reg.Check(c.Request.Context(), ref) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to check model registry", "details": err.Error()}) return } c.JSON(http.StatusOK, out) } // RefreshModelRegistry godoc // @Summary Refresh model registry from models.dev // @Description Fetches models.dev, computes per-binding capabilities, and updates Redis meta:models // @Tags admin // @Accept json // @Produce json // @Security AdminAuth // @Param body body refreshModelRegistryRequest false "optional override ref" // @Success 200 {object} ResponseEnvelope{data=gin.H} // @Failure 400 {object} ResponseEnvelope{data=gin.H} // @Failure 500 {object} ResponseEnvelope{data=gin.H} // @Router /admin/model-registry/refresh [post] func (h *ModelRegistryHandler) Refresh(c *gin.Context) { if h == nil || h.reg == nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "model registry not configured"}) return } var req refreshModelRegistryRequest _ = c.ShouldBindJSON(&req) ref := strings.TrimSpace(req.Ref) if err := h.reg.Refresh(c.Request.Context(), ref); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to refresh model registry", "details": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"status": "refreshed"}) } // RollbackModelRegistry godoc // @Summary Rollback model registry // @Description Rollback meta:models to previous cached last-good version // @Tags admin // @Produce json // @Security AdminAuth // @Success 200 {object} ResponseEnvelope{data=gin.H} // @Failure 500 {object} ResponseEnvelope{data=gin.H} // @Router /admin/model-registry/rollback [post] func (h *ModelRegistryHandler) Rollback(c *gin.Context) { if h == nil || h.reg == nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "model registry not configured"}) return } if err := h.reg.Rollback(c.Request.Context()); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to rollback model registry", "details": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"status": "rolled_back"}) }