Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
0ef4080e
authored
Feb 02, 2026
by
Calcium-Ion
Committed by
GitHub
Feb 02, 2026
Browse files
Options
Browse Files
Download
Plain Diff
fix: claude panic (#2804)
parents
66fc4395
06795ddf
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
52 additions
and
29 deletions
+52
-29
relay/channel/claude/relay-claude.go
+52
-29
No files found.
relay/channel/claude/relay-claude.go
View file @
0ef4080e
...
@@ -437,8 +437,10 @@ func StreamResponseClaude2OpenAI(reqMode int, claudeResponse *dto.ClaudeResponse
...
@@ -437,8 +437,10 @@ func StreamResponseClaude2OpenAI(reqMode int, claudeResponse *dto.ClaudeResponse
}
}
}
else
{
}
else
{
if
claudeResponse
.
Type
==
"message_start"
{
if
claudeResponse
.
Type
==
"message_start"
{
response
.
Id
=
claudeResponse
.
Message
.
Id
if
claudeResponse
.
Message
!=
nil
{
response
.
Model
=
claudeResponse
.
Message
.
Model
response
.
Id
=
claudeResponse
.
Message
.
Id
response
.
Model
=
claudeResponse
.
Message
.
Model
}
//claudeUsage = &claudeResponse.Message.Usage
//claudeUsage = &claudeResponse.Message.Usage
choice
.
Delta
.
SetContentString
(
""
)
choice
.
Delta
.
SetContentString
(
""
)
choice
.
Delta
.
Role
=
"assistant"
choice
.
Delta
.
Role
=
"assistant"
...
@@ -589,35 +591,49 @@ type ClaudeResponseInfo struct {
...
@@ -589,35 +591,49 @@ type ClaudeResponseInfo struct {
}
}
func
FormatClaudeResponseInfo
(
requestMode
int
,
claudeResponse
*
dto
.
ClaudeResponse
,
oaiResponse
*
dto
.
ChatCompletionsStreamResponse
,
claudeInfo
*
ClaudeResponseInfo
)
bool
{
func
FormatClaudeResponseInfo
(
requestMode
int
,
claudeResponse
*
dto
.
ClaudeResponse
,
oaiResponse
*
dto
.
ChatCompletionsStreamResponse
,
claudeInfo
*
ClaudeResponseInfo
)
bool
{
if
claudeInfo
==
nil
{
return
false
}
if
claudeInfo
.
Usage
==
nil
{
claudeInfo
.
Usage
=
&
dto
.
Usage
{}
}
if
requestMode
==
RequestModeCompletion
{
if
requestMode
==
RequestModeCompletion
{
claudeInfo
.
ResponseText
.
WriteString
(
claudeResponse
.
Completion
)
claudeInfo
.
ResponseText
.
WriteString
(
claudeResponse
.
Completion
)
}
else
{
}
else
{
if
claudeResponse
.
Type
==
"message_start"
{
if
claudeResponse
.
Type
==
"message_start"
{
claudeInfo
.
ResponseId
=
claudeResponse
.
Message
.
Id
if
claudeResponse
.
Message
!=
nil
{
claudeInfo
.
Model
=
claudeResponse
.
Message
.
Model
claudeInfo
.
ResponseId
=
claudeResponse
.
Message
.
Id
claudeInfo
.
Model
=
claudeResponse
.
Message
.
Model
}
// message_start, 获取usage
// message_start, 获取usage
claudeInfo
.
Usage
.
PromptTokens
=
claudeResponse
.
Message
.
Usage
.
InputTokens
if
claudeResponse
.
Message
!=
nil
&&
claudeResponse
.
Message
.
Usage
!=
nil
{
claudeInfo
.
Usage
.
PromptTokensDetails
.
CachedTokens
=
claudeResponse
.
Message
.
Usage
.
CacheReadInputTokens
claudeInfo
.
Usage
.
PromptTokens
=
claudeResponse
.
Message
.
Usage
.
InputTokens
claudeInfo
.
Usage
.
PromptTokensDetails
.
CachedCreationTokens
=
claudeResponse
.
Message
.
Usage
.
CacheCreationInputTokens
claudeInfo
.
Usage
.
PromptTokensDetails
.
CachedTokens
=
claudeResponse
.
Message
.
Usage
.
CacheReadInputTokens
claudeInfo
.
Usage
.
ClaudeCacheCreation5mTokens
=
claudeResponse
.
Message
.
Usage
.
GetCacheCreation5mTokens
()
claudeInfo
.
Usage
.
PromptTokensDetails
.
CachedCreationTokens
=
claudeResponse
.
Message
.
Usage
.
CacheCreationInputTokens
claudeInfo
.
Usage
.
ClaudeCacheCreation1hTokens
=
claudeResponse
.
Message
.
Usage
.
GetCacheCreation1hTokens
()
claudeInfo
.
Usage
.
ClaudeCacheCreation5mTokens
=
claudeResponse
.
Message
.
Usage
.
GetCacheCreation5mTokens
()
claudeInfo
.
Usage
.
CompletionTokens
=
claudeResponse
.
Message
.
Usage
.
OutputTokens
claudeInfo
.
Usage
.
ClaudeCacheCreation1hTokens
=
claudeResponse
.
Message
.
Usage
.
GetCacheCreation1hTokens
()
}
else
if
claudeResponse
.
Type
==
"content_block_delta"
{
claudeInfo
.
Usage
.
CompletionTokens
=
claudeResponse
.
Message
.
Usage
.
OutputTokens
if
claudeResponse
.
Delta
.
Text
!=
nil
{
claudeInfo
.
ResponseText
.
WriteString
(
*
claudeResponse
.
Delta
.
Text
)
}
}
if
claudeResponse
.
Delta
.
Thinking
!=
nil
{
}
else
if
claudeResponse
.
Type
==
"content_block_delta"
{
claudeInfo
.
ResponseText
.
WriteString
(
*
claudeResponse
.
Delta
.
Thinking
)
if
claudeResponse
.
Delta
!=
nil
{
if
claudeResponse
.
Delta
.
Text
!=
nil
{
claudeInfo
.
ResponseText
.
WriteString
(
*
claudeResponse
.
Delta
.
Text
)
}
if
claudeResponse
.
Delta
.
Thinking
!=
nil
{
claudeInfo
.
ResponseText
.
WriteString
(
*
claudeResponse
.
Delta
.
Thinking
)
}
}
}
}
else
if
claudeResponse
.
Type
==
"message_delta"
{
}
else
if
claudeResponse
.
Type
==
"message_delta"
{
// 最终的usage获取
// 最终的usage获取
if
claudeResponse
.
Usage
.
InputTokens
>
0
{
if
claudeResponse
.
Usage
!=
nil
{
// 不叠加,只取最新的
if
claudeResponse
.
Usage
.
InputTokens
>
0
{
claudeInfo
.
Usage
.
PromptTokens
=
claudeResponse
.
Usage
.
InputTokens
// 不叠加,只取最新的
claudeInfo
.
Usage
.
PromptTokens
=
claudeResponse
.
Usage
.
InputTokens
}
claudeInfo
.
Usage
.
CompletionTokens
=
claudeResponse
.
Usage
.
OutputTokens
claudeInfo
.
Usage
.
TotalTokens
=
claudeInfo
.
Usage
.
PromptTokens
+
claudeInfo
.
Usage
.
CompletionTokens
}
}
claudeInfo
.
Usage
.
CompletionTokens
=
claudeResponse
.
Usage
.
OutputTokens
claudeInfo
.
Usage
.
TotalTokens
=
claudeInfo
.
Usage
.
PromptTokens
+
claudeInfo
.
Usage
.
CompletionTokens
// 判断是否完整
// 判断是否完整
claudeInfo
.
Done
=
true
claudeInfo
.
Done
=
true
...
@@ -657,7 +673,9 @@ func HandleStreamResponseData(c *gin.Context, info *relaycommon.RelayInfo, claud
...
@@ -657,7 +673,9 @@ func HandleStreamResponseData(c *gin.Context, info *relaycommon.RelayInfo, claud
}
else
{
}
else
{
if
claudeResponse
.
Type
==
"message_start"
{
if
claudeResponse
.
Type
==
"message_start"
{
// message_start, 获取usage
// message_start, 获取usage
info
.
UpstreamModelName
=
claudeResponse
.
Message
.
Model
if
claudeResponse
.
Message
!=
nil
{
info
.
UpstreamModelName
=
claudeResponse
.
Message
.
Model
}
}
else
if
claudeResponse
.
Type
==
"content_block_delta"
{
}
else
if
claudeResponse
.
Type
==
"content_block_delta"
{
}
else
if
claudeResponse
.
Type
==
"message_delta"
{
}
else
if
claudeResponse
.
Type
==
"message_delta"
{
}
}
...
@@ -745,13 +763,18 @@ func HandleClaudeResponseData(c *gin.Context, info *relaycommon.RelayInfo, claud
...
@@ -745,13 +763,18 @@ func HandleClaudeResponseData(c *gin.Context, info *relaycommon.RelayInfo, claud
if
requestMode
==
RequestModeCompletion
{
if
requestMode
==
RequestModeCompletion
{
claudeInfo
.
Usage
=
service
.
ResponseText2Usage
(
c
,
claudeResponse
.
Completion
,
info
.
UpstreamModelName
,
info
.
GetEstimatePromptTokens
())
claudeInfo
.
Usage
=
service
.
ResponseText2Usage
(
c
,
claudeResponse
.
Completion
,
info
.
UpstreamModelName
,
info
.
GetEstimatePromptTokens
())
}
else
{
}
else
{
claudeInfo
.
Usage
.
PromptTokens
=
claudeResponse
.
Usage
.
InputTokens
if
claudeInfo
.
Usage
==
nil
{
claudeInfo
.
Usage
.
CompletionTokens
=
claudeResponse
.
Usage
.
OutputTokens
claudeInfo
.
Usage
=
&
dto
.
Usage
{}
claudeInfo
.
Usage
.
TotalTokens
=
claudeResponse
.
Usage
.
InputTokens
+
claudeResponse
.
Usage
.
OutputTokens
}
claudeInfo
.
Usage
.
PromptTokensDetails
.
CachedTokens
=
claudeResponse
.
Usage
.
CacheReadInputTokens
if
claudeResponse
.
Usage
!=
nil
{
claudeInfo
.
Usage
.
PromptTokensDetails
.
CachedCreationTokens
=
claudeResponse
.
Usage
.
CacheCreationInputTokens
claudeInfo
.
Usage
.
PromptTokens
=
claudeResponse
.
Usage
.
InputTokens
claudeInfo
.
Usage
.
ClaudeCacheCreation5mTokens
=
claudeResponse
.
Usage
.
GetCacheCreation5mTokens
()
claudeInfo
.
Usage
.
CompletionTokens
=
claudeResponse
.
Usage
.
OutputTokens
claudeInfo
.
Usage
.
ClaudeCacheCreation1hTokens
=
claudeResponse
.
Usage
.
GetCacheCreation1hTokens
()
claudeInfo
.
Usage
.
TotalTokens
=
claudeResponse
.
Usage
.
InputTokens
+
claudeResponse
.
Usage
.
OutputTokens
claudeInfo
.
Usage
.
PromptTokensDetails
.
CachedTokens
=
claudeResponse
.
Usage
.
CacheReadInputTokens
claudeInfo
.
Usage
.
PromptTokensDetails
.
CachedCreationTokens
=
claudeResponse
.
Usage
.
CacheCreationInputTokens
claudeInfo
.
Usage
.
ClaudeCacheCreation5mTokens
=
claudeResponse
.
Usage
.
GetCacheCreation5mTokens
()
claudeInfo
.
Usage
.
ClaudeCacheCreation1hTokens
=
claudeResponse
.
Usage
.
GetCacheCreation1hTokens
()
}
}
}
var
responseData
[]
byte
var
responseData
[]
byte
switch
info
.
RelayFormat
{
switch
info
.
RelayFormat
{
...
@@ -766,7 +789,7 @@ func HandleClaudeResponseData(c *gin.Context, info *relaycommon.RelayInfo, claud
...
@@ -766,7 +789,7 @@ func HandleClaudeResponseData(c *gin.Context, info *relaycommon.RelayInfo, claud
responseData
=
data
responseData
=
data
}
}
if
claudeResponse
.
Usage
.
ServerToolUse
!=
nil
&&
claudeResponse
.
Usage
.
ServerToolUse
.
WebSearchRequests
>
0
{
if
claudeResponse
.
Usage
!=
nil
&&
claudeResponse
.
Usage
.
ServerToolUse
!=
nil
&&
claudeResponse
.
Usage
.
ServerToolUse
.
WebSearchRequests
>
0
{
c
.
Set
(
"claude_web_search_requests"
,
claudeResponse
.
Usage
.
ServerToolUse
.
WebSearchRequests
)
c
.
Set
(
"claude_web_search_requests"
,
claudeResponse
.
Usage
.
ServerToolUse
.
WebSearchRequests
)
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment