From 7afa47677054612e5bcccb7bb25f9eef6d68e2d1 Mon Sep 17 00:00:00 2001 From: Seefs Date: Sun, 25 Jan 2026 15:21:31 +0800 Subject: [PATCH] feat: claude refusal reason --- relay/channel/claude/relay-claude.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/relay/channel/claude/relay-claude.go b/relay/channel/claude/relay-claude.go index d3986236a..f5872011c 100644 --- a/relay/channel/claude/relay-claude.go +++ b/relay/channel/claude/relay-claude.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/constant" "github.com/QuantumNous/new-api/dto" "github.com/QuantumNous/new-api/logger" "github.com/QuantumNous/new-api/relay/channel/openrouter" @@ -41,6 +42,15 @@ func stopReasonClaude2OpenAI(reason string) string { } } +func maybeMarkClaudeRefusal(c *gin.Context, stopReason string) { + if c == nil { + return + } + if strings.EqualFold(stopReason, "refusal") { + common.SetContextKey(c, constant.ContextKeyAdminRejectReason, "claude_stop_reason=refusal") + } +} + func RequestOpenAI2ClaudeComplete(textRequest dto.GeneralOpenAIRequest) *dto.ClaudeRequest { claudeRequest := dto.ClaudeRequest{ @@ -644,6 +654,12 @@ func HandleStreamResponseData(c *gin.Context, info *relaycommon.RelayInfo, claud if claudeError := claudeResponse.GetClaudeError(); claudeError != nil && claudeError.Type != "" { return types.WithClaudeError(*claudeError, http.StatusInternalServerError) } + if claudeResponse.StopReason != "" { + maybeMarkClaudeRefusal(c, claudeResponse.StopReason) + } + if claudeResponse.Delta != nil && claudeResponse.Delta.StopReason != nil { + maybeMarkClaudeRefusal(c, *claudeResponse.Delta.StopReason) + } if info.RelayFormat == types.RelayFormatClaude { FormatClaudeResponseInfo(requestMode, &claudeResponse, nil, claudeInfo) @@ -735,6 +751,7 @@ func HandleClaudeResponseData(c *gin.Context, info *relaycommon.RelayInfo, claud if claudeError := claudeResponse.GetClaudeError(); claudeError != nil && claudeError.Type != "" { return types.WithClaudeError(*claudeError, http.StatusInternalServerError) } + maybeMarkClaudeRefusal(c, claudeResponse.StopReason) if requestMode == RequestModeCompletion { claudeInfo.Usage = service.ResponseText2Usage(c, claudeResponse.Completion, info.UpstreamModelName, info.GetEstimatePromptTokens()) } else {