feat: support disabling image generation globally

- Added `disable-image-generation` configuration flag to disable the `image_generation` tool globally.
- Updated payload handling to remove `image_generation` tools from request payload arrays when the flag is enabled.
- Modified OpenAI image handlers (`ImagesGenerations`, `ImagesEdits`) to return 404 when the feature is disabled.
- Enhanced configuration diff logging to track changes for the `disable-image-generation` flag.
- Added accompanying unit tests for the new feature in payload helpers and image handler logic.
This commit is contained in:
Luis Pater
2026-04-30 03:42:27 +08:00
parent 359ec30d0c
commit e3e60f914b
11 changed files with 284 additions and 126 deletions
@@ -198,6 +198,11 @@ func parseBoolField(raw string, fallback bool) bool {
}
func (h *OpenAIAPIHandler) ImagesGenerations(c *gin.Context) {
if h != nil && h.BaseAPIHandler != nil && h.BaseAPIHandler.Cfg != nil && h.BaseAPIHandler.Cfg.DisableImageGeneration {
c.AbortWithStatus(http.StatusNotFound)
return
}
rawJSON, err := c.GetRawData()
if err != nil {
c.JSON(http.StatusBadRequest, handlers.ErrorResponse{
@@ -281,6 +286,11 @@ func (h *OpenAIAPIHandler) ImagesGenerations(c *gin.Context) {
}
func (h *OpenAIAPIHandler) ImagesEdits(c *gin.Context) {
if h != nil && h.BaseAPIHandler != nil && h.BaseAPIHandler.Cfg != nil && h.BaseAPIHandler.Cfg.DisableImageGeneration {
c.AbortWithStatus(http.StatusNotFound)
return
}
contentType := strings.ToLower(strings.TrimSpace(c.GetHeader("Content-Type")))
if strings.HasPrefix(contentType, "application/json") {
h.imagesEditsFromJSON(c)
@@ -10,6 +10,8 @@ import (
"testing"
"github.com/gin-gonic/gin"
"github.com/router-for-me/CLIProxyAPI/v6/sdk/api/handlers"
sdkconfig "github.com/router-for-me/CLIProxyAPI/v6/sdk/config"
"github.com/tidwall/gjson"
)
@@ -93,3 +95,27 @@ func TestImagesEditsMultipartRejectsUnsupportedModel(t *testing.T) {
assertUnsupportedImagesModelResponse(t, resp, "gpt-5.4-mini")
}
func TestImagesGenerations_DisableImageGeneration_Returns404(t *testing.T) {
base := handlers.NewBaseAPIHandlers(&sdkconfig.SDKConfig{DisableImageGeneration: true}, nil)
handler := NewOpenAIAPIHandler(base)
body := strings.NewReader(`{"prompt":"draw a square"}`)
resp := performImagesEndpointRequest(t, imagesGenerationsPath, "application/json", body, handler.ImagesGenerations)
if resp.Code != http.StatusNotFound {
t.Fatalf("status = %d, want %d: %s", resp.Code, http.StatusNotFound, resp.Body.String())
}
}
func TestImagesEdits_DisableImageGeneration_Returns404(t *testing.T) {
base := handlers.NewBaseAPIHandlers(&sdkconfig.SDKConfig{DisableImageGeneration: true}, nil)
handler := NewOpenAIAPIHandler(base)
body := strings.NewReader(`{"prompt":"edit this","images":[{"image_url":"data:image/png;base64,AA=="}]}`)
resp := performImagesEndpointRequest(t, imagesEditsPath, "application/json", body, handler.ImagesEdits)
if resp.Code != http.StatusNotFound {
t.Fatalf("status = %d, want %d: %s", resp.Code, http.StatusNotFound, resp.Body.String())
}
}