Files
new-api/service/relayconvert/request_compat.go
T
Calcium-Ion c36418c863 feat: enhance text protocol conversion and advanced custom routing (#5825)
* refactor: consolidate relay protocol converters

* refactor relayconvert text converters

* feat: refine relay converters and advanced custom routing

* refactor: enhance logging and add thought signature handling for Gemini requests

* refactor: enhance channel cache and pricing endpoint handling for advanced custom models

* feat: preserve billing usage semantics

* feat: add protocol-aware billing usage

* Delete useless files

* chore: update action versions in workflow files

* chore: update Docker action versions in workflow files

* fix: harden billing usage settlement and hot-path route matching

- estimate Gemini completion tokens locally when billable usageMetadata is
  prompt-only but output content was received (e.g. client aborts the stream
  before the final chunk), and rebuild the attached billing_usage as estimated
  so settlement does not bill zero output tokens
- guard NewClaudeMessagesBillingUsage against all-zero ClaudeUsage, matching
  the OpenAI/Gemini constructors, so a zero billing_usage cannot override a
  non-zero top-level usage during settlement
- cache compiled advanced-custom route model regexes; they run on the request
  hot path and were recompiled per request
- move the effectiveBillingUsage remap to PostTextConsumeQuota only, and
  document that calculateTextQuotaSummary expects remapped usage
- document the updatePricingLock -> channelSyncLock lock ordering that
  InitChannelCache/CacheUpdateChannel rely on, and the aux-struct pitfall in
  GeminiChatResponse.UnmarshalJSON
2026-07-11 20:44:12 +08:00

58 lines
2.9 KiB
Go

package relayconvert
import (
"github.com/QuantumNous/new-api/dto"
relaycommon "github.com/QuantumNous/new-api/relay/common"
claudemessages "github.com/QuantumNous/new-api/service/relayconvert/internal/claude_messages"
geminichat "github.com/QuantumNous/new-api/service/relayconvert/internal/gemini_chat"
oaichat "github.com/QuantumNous/new-api/service/relayconvert/internal/oai_chat"
oairesponses "github.com/QuantumNous/new-api/service/relayconvert/internal/oai_responses"
sharedgemini "github.com/QuantumNous/new-api/service/relayconvert/internal/shared/gemini"
"github.com/QuantumNous/new-api/setting/model_setting"
"github.com/gin-gonic/gin"
)
func ClaudeMessagesRequestToOpenAIChat(claudeRequest dto.ClaudeRequest, info *relaycommon.RelayInfo) (*dto.GeneralOpenAIRequest, error) {
return claudemessages.ClaudeMessagesRequestToOpenAIChat(claudeRequest, info)
}
func OpenAIChatRequestToClaudeMessages(c *gin.Context, textRequest dto.GeneralOpenAIRequest) (*dto.ClaudeRequest, error) {
return oaichat.OpenAIChatRequestToClaudeMessages(c, textRequest)
}
func GeminiGenerateContentRequestToOpenAIChat(geminiRequest *dto.GeminiChatRequest, info *relaycommon.RelayInfo) (*dto.GeneralOpenAIRequest, error) {
return geminichat.GeminiGenerateContentRequestToOpenAIChat(geminiRequest, info)
}
func OpenAIChatRequestToGeminiGenerateContent(c *gin.Context, textRequest dto.GeneralOpenAIRequest, info *relaycommon.RelayInfo) (*dto.GeminiChatRequest, error) {
return oaichat.OpenAIChatRequestToGeminiGenerateContent(c, textRequest, info)
}
func ApplyGeminiThinkingConfig(geminiRequest *dto.GeminiChatRequest, info *relaycommon.RelayInfo, oaiRequest ...dto.GeneralOpenAIRequest) {
sharedgemini.ApplyThinkingConfig(geminiRequest, info, oaiRequest...)
}
func ChatCompletionsRequestToResponsesRequest(req *dto.GeneralOpenAIRequest) (*dto.OpenAIResponsesRequest, error) {
return oaichat.ChatCompletionsRequestToResponsesRequest(req)
}
func ResponsesRequestToChatCompletionsRequest(req *dto.OpenAIResponsesRequest) (*dto.GeneralOpenAIRequest, error) {
return oairesponses.ResponsesRequestToChatCompletionsRequest(req)
}
func OpenAIResponsesRequestToClaudeMessages(c *gin.Context, req *dto.OpenAIResponsesRequest) (*dto.ClaudeRequest, error) {
return oairesponses.OpenAIResponsesRequestToClaudeMessages(c, req)
}
func OpenAIResponsesRequestToGeminiChat(c *gin.Context, req *dto.OpenAIResponsesRequest, info *relaycommon.RelayInfo) (*dto.GeminiChatRequest, error) {
return oairesponses.OpenAIResponsesRequestToGeminiChat(c, req, info)
}
func ShouldChatCompletionsUseResponsesPolicy(policy model_setting.ChatCompletionsToResponsesPolicy, channelID int, channelType int, model string) bool {
return oaichat.ShouldChatCompletionsUseResponsesPolicy(policy, channelID, channelType, model)
}
func ShouldChatCompletionsUseResponsesGlobal(channelID int, channelType int, model string) bool {
return oaichat.ShouldChatCompletionsUseResponsesGlobal(channelID, channelType, model)
}