feat: publish sanitized custom.97 source
This commit is contained in:
1022 files changed
+69903
-19207
No files matched your search
@@ -85,7 +85,7 @@ func OaiResponsesToChatBufferedStreamHandler(c *gin.Context, info *relaycommon.R
|
||||
|
||||
var streamResp dto.ResponsesStreamResponse
|
||||
if err := common.UnmarshalJsonStr(data, &streamResp); err != nil {
|
||||
logger.LogError(c, "failed to unmarshal buffered responses stream event: "+err.Error())
|
||||
logger.LogError(c, common.LogText("failed to unmarshal buffered responses stream event: %s", err.Error()))
|
||||
streamErr = types.NewOpenAIError(err, types.ErrorCodeBadResponseBody, http.StatusInternalServerError)
|
||||
break
|
||||
}
|
||||
@@ -187,11 +187,27 @@ func OaiResponsesToChatStreamHandler(c *gin.Context, info *relaycommon.RelayInfo
|
||||
return nil, types.NewOpenAIError(err, types.ErrorCodeBadResponse, http.StatusInternalServerError)
|
||||
}
|
||||
streamErr := (*types.NewAPIError)(nil)
|
||||
// upstreamFailed records a response.failed / response.error event and
|
||||
// failedUsage the usage it reported, if any.
|
||||
upstreamFailed := false
|
||||
var failedUsage *dto.Usage
|
||||
|
||||
if info.RelayFormat == types.RelayFormatClaude && info.ClaudeConvertInfo == nil {
|
||||
info.ClaudeConvertInfo = &relaycommon.ClaudeConvertInfo{LastMessagesType: relaycommon.LastMessageTypeNone}
|
||||
}
|
||||
|
||||
// writeFailed stops the stream after a failed client write. When the client
|
||||
// went away the upstream already produced output, so the request settles
|
||||
// normally instead of failing; any other write error stays a server error.
|
||||
writeFailed := func(err error) bool {
|
||||
if c.Request.Context().Err() != nil {
|
||||
info.StreamStatus.SetEndReason(relaycommon.StreamEndReasonClientGone, err)
|
||||
return false
|
||||
}
|
||||
streamErr = types.NewOpenAIError(err, types.ErrorCodeBadResponse, http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
sendGeminiResponse := func(geminiResponse *dto.GeminiChatResponse) bool {
|
||||
if geminiResponse == nil {
|
||||
return true
|
||||
@@ -213,8 +229,7 @@ func OaiResponsesToChatStreamHandler(c *gin.Context, info *relaycommon.RelayInfo
|
||||
return true
|
||||
}
|
||||
if err := helper.ObjectData(c, &value); err != nil {
|
||||
streamErr = types.NewOpenAIError(err, types.ErrorCodeBadResponse, http.StatusInternalServerError)
|
||||
return false
|
||||
return writeFailed(err)
|
||||
}
|
||||
return true
|
||||
case *dto.ChatCompletionsStreamResponse:
|
||||
@@ -222,14 +237,12 @@ func OaiResponsesToChatStreamHandler(c *gin.Context, info *relaycommon.RelayInfo
|
||||
return true
|
||||
}
|
||||
if err := helper.ObjectData(c, value); err != nil {
|
||||
streamErr = types.NewOpenAIError(err, types.ErrorCodeBadResponse, http.StatusInternalServerError)
|
||||
return false
|
||||
return writeFailed(err)
|
||||
}
|
||||
return true
|
||||
case dto.ClaudeResponse:
|
||||
if err := helper.ClaudeData(c, value); err != nil {
|
||||
streamErr = types.NewOpenAIError(err, types.ErrorCodeBadResponse, http.StatusInternalServerError)
|
||||
return false
|
||||
return writeFailed(err)
|
||||
}
|
||||
return true
|
||||
case *dto.ClaudeResponse:
|
||||
@@ -237,8 +250,7 @@ func OaiResponsesToChatStreamHandler(c *gin.Context, info *relaycommon.RelayInfo
|
||||
return true
|
||||
}
|
||||
if err := helper.ClaudeData(c, *value); err != nil {
|
||||
streamErr = types.NewOpenAIError(err, types.ErrorCodeBadResponse, http.StatusInternalServerError)
|
||||
return false
|
||||
return writeFailed(err)
|
||||
}
|
||||
return true
|
||||
case dto.GeminiChatResponse:
|
||||
@@ -253,13 +265,13 @@ func OaiResponsesToChatStreamHandler(c *gin.Context, info *relaycommon.RelayInfo
|
||||
|
||||
helper.StreamScannerHandler(c, resp, info, func(data string, sr *helper.StreamResult) {
|
||||
if streamErr != nil {
|
||||
sr.Stop(streamErr)
|
||||
stopStream(sr, streamErr)
|
||||
return
|
||||
}
|
||||
|
||||
var streamResp dto.ResponsesStreamResponse
|
||||
if err := common.UnmarshalJsonStr(data, &streamResp); err != nil {
|
||||
logger.LogError(c, "failed to unmarshal responses stream event: "+err.Error())
|
||||
logger.LogError(c, common.LogText("failed to unmarshal responses stream event: %s", err.Error()))
|
||||
sr.Error(err)
|
||||
return
|
||||
}
|
||||
@@ -268,34 +280,72 @@ func OaiResponsesToChatStreamHandler(c *gin.Context, info *relaycommon.RelayInfo
|
||||
info.ObserveResponseModel(streamResp.Response.Model)
|
||||
}
|
||||
if streamResp.Type == "response.error" || streamResp.Type == "response.failed" {
|
||||
upstreamFailed = true
|
||||
if streamResp.Response != nil {
|
||||
failedUsage = streamResp.Response.Usage
|
||||
if oaiErr := streamResp.Response.GetOpenAIError(); oaiErr != nil && oaiErr.Type != "" {
|
||||
streamErr = types.WithOpenAIError(*oaiErr, http.StatusInternalServerError)
|
||||
sr.Stop(streamErr)
|
||||
stopStream(sr, streamErr)
|
||||
return
|
||||
}
|
||||
}
|
||||
streamErr = types.NewOpenAIError(fmt.Errorf("responses stream error: %s", streamResp.Type), types.ErrorCodeBadResponse, http.StatusInternalServerError)
|
||||
sr.Stop(streamErr)
|
||||
stopStream(sr, streamErr)
|
||||
return
|
||||
}
|
||||
|
||||
results, err := service.ConvertStreamResponseChunk(c, info, state, &streamResp)
|
||||
if err != nil {
|
||||
streamErr = types.NewOpenAIError(err, types.ErrorCodeBadResponse, http.StatusInternalServerError)
|
||||
sr.Stop(streamErr)
|
||||
stopStream(sr, streamErr)
|
||||
return
|
||||
}
|
||||
for _, result := range results {
|
||||
if !sendStreamResult(result) {
|
||||
sr.Stop(streamErr)
|
||||
stopStream(sr, streamErr)
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if streamErr != nil {
|
||||
return nil, streamErr
|
||||
if !upstreamFailed || state.UsageText() == "" {
|
||||
return nil, streamErr
|
||||
}
|
||||
// The upstream failed after output reached the client: bill the
|
||||
// delivered output (upstream usage when reported, otherwise the
|
||||
// estimate) and send the client the same error the failed request
|
||||
// path writes. stream_status already records the failure.
|
||||
usage := relayconvert.UsageFromResponsesUsage(failedUsage)
|
||||
if usage.TotalTokens == 0 {
|
||||
usage = state.Usage()
|
||||
}
|
||||
if usage == nil || usage.TotalTokens == 0 {
|
||||
usage = service.ResponseText2Usage(c, state.UsageText(), info.UpstreamModelName, info.GetEstimatePromptTokens())
|
||||
} else if usage.CompletionTokens == 0 || usage.PromptTokens == 0 {
|
||||
// As in the native Responses accumulator, reported usage that
|
||||
// omits the output or the prompt is completed from the estimate of
|
||||
// the delivered output and the prompt.
|
||||
estimate := service.ResponseText2Usage(c, state.UsageText(), info.UpstreamModelName, info.GetEstimatePromptTokens())
|
||||
if usage.CompletionTokens == 0 {
|
||||
usage.CompletionTokens = estimate.CompletionTokens
|
||||
}
|
||||
if usage.PromptTokens == 0 {
|
||||
usage.PromptTokens = estimate.PromptTokens
|
||||
}
|
||||
usage.TotalTokens = usage.PromptTokens + usage.CompletionTokens
|
||||
if usage.BillingUsage != nil {
|
||||
usage.BillingUsage = dto.CloneBillingUsageWithEstimatedCompletion(usage.BillingUsage, usage.CompletionTokens)
|
||||
}
|
||||
}
|
||||
logger.LogError(c, common.LogText("responses stream failed after output was delivered, billing the delivered output: %s", streamErr.Error()))
|
||||
streamErr.SetMessage(common.MessageWithRequestId(streamErr.Error(), c.GetString(common.RequestIdKey)))
|
||||
if info.RelayFormat == types.RelayFormatClaude {
|
||||
c.JSON(streamErr.StatusCode, gin.H{"type": "error", "error": streamErr.ToClaudeError(common.UpstreamAddresses(c)...)})
|
||||
} else {
|
||||
c.JSON(streamErr.StatusCode, gin.H{"error": streamErr.ToOpenAIError(common.UpstreamAddresses(c)...)})
|
||||
}
|
||||
return usage, nil
|
||||
}
|
||||
|
||||
usage := state.Usage()
|
||||
@@ -303,6 +353,9 @@ func OaiResponsesToChatStreamHandler(c *gin.Context, info *relaycommon.RelayInfo
|
||||
usage = service.ResponseText2Usage(c, state.UsageText(), info.UpstreamModelName, info.GetEstimatePromptTokens())
|
||||
state.SetUsage(usage)
|
||||
}
|
||||
if info.StreamStatus.EndReason == relaycommon.StreamEndReasonClientGone {
|
||||
return usage, nil
|
||||
}
|
||||
|
||||
if info.RelayFormat == types.RelayFormatClaude && info.ClaudeConvertInfo != nil {
|
||||
info.ClaudeConvertInfo.Usage = usage
|
||||
@@ -313,12 +366,19 @@ func OaiResponsesToChatStreamHandler(c *gin.Context, info *relaycommon.RelayInfo
|
||||
}
|
||||
for _, result := range finalResults {
|
||||
if !sendStreamResult(result) {
|
||||
return nil, streamErr
|
||||
if streamErr != nil {
|
||||
return nil, streamErr
|
||||
}
|
||||
return usage, nil
|
||||
}
|
||||
}
|
||||
if info.RelayFormat == types.RelayFormatOpenAI && info.ShouldIncludeUsage && usage != nil {
|
||||
if err := helper.ObjectData(c, helper.GenerateFinalUsageResponse(responseId, createAt, info.UpstreamModelName, *usage)); err != nil {
|
||||
return nil, types.NewOpenAIError(err, types.ErrorCodeBadResponse, http.StatusInternalServerError)
|
||||
writeFailed(err)
|
||||
if streamErr != nil {
|
||||
return nil, streamErr
|
||||
}
|
||||
return usage, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user