feat: sync deployed v1.0.0-rc.38-custom.42

Sync production source including routing, billing, Astra detection and public uptime. Update custom build instructions and license packaging.
This commit is contained in:
cneicy committed 2026-09-26 04:49:11 +08:00
1 parent aa6c3f50f4
commit ceddfd3d6b
828 files changed
+122253 -13702

No files matched your search

+31 -25
View File
@@ -1,6 +1,7 @@
package helper
import (
"encoding/json"
"errors"
"fmt"
"math"
@@ -9,6 +10,7 @@ import (
"strings"
"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/constant"
"github.com/QuantumNous/new-api/logger"
relayconstant "github.com/QuantumNous/new-api/relay/constant"
"github.com/QuantumNous/new-api/relaykit/dto"
@@ -121,7 +123,8 @@ func GetAndValidateEmbeddingRequest(c *gin.Context, relayMode int) (*dto.Embeddi
// overflow the conversion and corrupt billing.
const maxTokensLimit = math.MaxInt32 / 2
func exceedsMaxTokensLimit(values ...*uint) bool {
// ExceedsMaxTokensLimit checks token limits before they reach billing arithmetic.
func ExceedsMaxTokensLimit(values ...*uint) bool {
for _, v := range values {
if lo.FromPtrOr(v, uint(0)) > maxTokensLimit {
return true
@@ -142,7 +145,7 @@ func GetAndValidateResponsesRequest(c *gin.Context) (*dto.OpenAIResponsesRequest
if request.Input == nil {
return nil, errors.New("input is required")
}
if exceedsMaxTokensLimit(request.MaxOutputTokens) {
if ExceedsMaxTokensLimit(request.MaxOutputTokens) {
return nil, errors.New("max_output_tokens is invalid")
}
return request, nil
@@ -203,6 +206,9 @@ func GetAndValidOpenAIImageRequest(c *gin.Context, relayMode int) (*dto.ImageReq
}
imageRequest.Quality = formData.Get("quality")
imageRequest.Size = formData.Get("size")
if parameters := formData.Get("parameters"); parameters != "" {
imageRequest.Extra = map[string]json.RawMessage{"parameters": json.RawMessage(parameters)}
}
if streamValue := strings.TrimSpace(formData.Get("stream")); streamValue != "" {
stream, err := strconv.ParseBool(streamValue)
if err != nil {
@@ -238,7 +244,6 @@ func GetAndValidOpenAIImageRequest(c *gin.Context, relayMode int) (*dto.ImageReq
}
if imageRequest.Model == "" {
//imageRequest.Model = "dall-e-3"
return nil, errors.New("model is required")
}
@@ -250,25 +255,10 @@ func GetAndValidOpenAIImageRequest(c *gin.Context, relayMode int) (*dto.ImageReq
return nil, fmt.Errorf("n must be an integer between 1 and %d", dto.MaxImageN)
}
// Not "256x256", "512x512", or "1024x1024"
if imageRequest.Model == "dall-e-2" || imageRequest.Model == "dall-e" {
if imageRequest.Size != "" && imageRequest.Size != "256x256" && imageRequest.Size != "512x512" && imageRequest.Size != "1024x1024" {
return nil, errors.New("size must be one of 256x256, 512x512, or 1024x1024 for dall-e-2 or dall-e")
}
if imageRequest.Size == "" {
imageRequest.Size = "1024x1024"
}
} else if imageRequest.Model == "dall-e-3" {
if imageRequest.Size != "" && imageRequest.Size != "1024x1024" && imageRequest.Size != "1024x1792" && imageRequest.Size != "1792x1024" {
return nil, errors.New("size must be one of 1024x1024, 1024x1792 or 1792x1024 for dall-e-3")
}
if imageRequest.Quality == "" {
imageRequest.Quality = "standard"
}
if imageRequest.Size == "" {
imageRequest.Size = "1024x1024"
}
} else if imageRequest.Model == "gpt-image-1" {
if err := imageRequest.NormalizeLegacyDalleImageRequest(); err != nil {
return nil, err
}
if imageRequest.Model == "gpt-image-1" {
if imageRequest.Quality == "" {
imageRequest.Quality = "auto"
}
@@ -283,6 +273,19 @@ func GetAndValidOpenAIImageRequest(c *gin.Context, relayMode int) (*dto.ImageReq
}
}
// Provider parameters can override the top-level count. Validate before
// pricing so malformed multipliers return a client error, not a pricing
// failure after reservation has started.
if raw, exists := imageRequest.Extra["parameters"]; exists {
parameters := &dto.ImageBillingParameters{}
if err := common.Unmarshal(raw, parameters); err != nil {
return nil, fmt.Errorf("invalid image parameters: %w", err)
}
imageRequest.BillingParameters = parameters
}
if _, err := imageRequest.ImageCount(common.GetContextKeyInt(c, constant.ContextKeyChannelType) == constant.ChannelTypeAli); err != nil {
return nil, err
}
return imageRequest, nil
}
@@ -298,7 +301,7 @@ func GetAndValidateClaudeRequest(c *gin.Context) (textRequest *dto.ClaudeRequest
if textRequest.Model == "" {
return nil, errors.New("field model is required")
}
if exceedsMaxTokensLimit(textRequest.MaxTokens, textRequest.MaxTokensToSample) {
if ExceedsMaxTokensLimit(textRequest.MaxTokens, textRequest.MaxTokensToSample) {
return nil, errors.New("max_tokens is invalid")
}
@@ -323,9 +326,12 @@ func GetAndValidateTextRequest(c *gin.Context, relayMode int) (*dto.GeneralOpenA
textRequest.Model = c.Param("model")
}
if exceedsMaxTokensLimit(textRequest.MaxTokens, textRequest.MaxCompletionTokens) {
if ExceedsMaxTokensLimit(textRequest.MaxTokens, textRequest.MaxCompletionTokens) {
return nil, errors.New("max_tokens is invalid")
}
if ExceedsMaxTokensLimit(textRequest.MinTokens) {
return nil, errors.New("min_tokens is invalid")
}
if textRequest.Model == "" {
return nil, errors.New("model is required")
}
@@ -376,7 +382,7 @@ func GetAndValidateGeminiRequest(c *gin.Context) (*dto.GeminiChatRequest, error)
if len(request.Contents) == 0 && len(request.Requests) == 0 {
return nil, errors.New("contents is required")
}
if exceedsMaxTokensLimit(request.GenerationConfig.MaxOutputTokens) {
if ExceedsMaxTokensLimit(request.GenerationConfig.MaxOutputTokens) {
return nil, errors.New("maxOutputTokens is invalid")
}