Skip to content

Commit 8e6039b

Browse files
author
Apple\Apple
committed
Merge remote-tracking branch 'origin/main' into alpha
2 parents eb81245 + 3665ad6 commit 8e6039b

File tree

4 files changed

+65
-22
lines changed

4 files changed

+65
-22
lines changed

dto/claude.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,18 @@ type ClaudeMetadata struct {
77
}
88

99
type ClaudeMediaMessage struct {
10-
Type string `json:"type,omitempty"`
11-
Text *string `json:"text,omitempty"`
12-
Model string `json:"model,omitempty"`
13-
Source *ClaudeMessageSource `json:"source,omitempty"`
14-
Usage *ClaudeUsage `json:"usage,omitempty"`
15-
StopReason *string `json:"stop_reason,omitempty"`
16-
PartialJson *string `json:"partial_json,omitempty"`
17-
Role string `json:"role,omitempty"`
18-
Thinking string `json:"thinking,omitempty"`
19-
Signature string `json:"signature,omitempty"`
20-
Delta string `json:"delta,omitempty"`
10+
Type string `json:"type,omitempty"`
11+
Text *string `json:"text,omitempty"`
12+
Model string `json:"model,omitempty"`
13+
Source *ClaudeMessageSource `json:"source,omitempty"`
14+
Usage *ClaudeUsage `json:"usage,omitempty"`
15+
StopReason *string `json:"stop_reason,omitempty"`
16+
PartialJson *string `json:"partial_json,omitempty"`
17+
Role string `json:"role,omitempty"`
18+
Thinking string `json:"thinking,omitempty"`
19+
Signature string `json:"signature,omitempty"`
20+
Delta string `json:"delta,omitempty"`
21+
CacheControl json.RawMessage `json:"cache_control,omitempty"`
2122
// tool_calls
2223
Id string `json:"id,omitempty"`
2324
Name string `json:"name,omitempty"`

dto/openai_request.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ type GeneralOpenAIRequest struct {
2929
MaxTokens uint `json:"max_tokens,omitempty"`
3030
MaxCompletionTokens uint `json:"max_completion_tokens,omitempty"`
3131
ReasoningEffort string `json:"reasoning_effort,omitempty"`
32-
//Reasoning json.RawMessage `json:"reasoning,omitempty"`
3332
Temperature *float64 `json:"temperature,omitempty"`
3433
TopP float64 `json:"top_p,omitempty"`
3534
TopK int `json:"top_k,omitempty"`
@@ -56,6 +55,8 @@ type GeneralOpenAIRequest struct {
5655
EnableThinking any `json:"enable_thinking,omitempty"` // ali
5756
ExtraBody any `json:"extra_body,omitempty"`
5857
WebSearchOptions *WebSearchOptions `json:"web_search_options,omitempty"`
58+
// OpenRouter Params
59+
Reasoning json.RawMessage `json:"reasoning,omitempty"`
5960
}
6061

6162
func (r *GeneralOpenAIRequest) ToMap() map[string]any {
@@ -125,6 +126,8 @@ type MediaContent struct {
125126
InputAudio any `json:"input_audio,omitempty"`
126127
File any `json:"file,omitempty"`
127128
VideoUrl any `json:"video_url,omitempty"`
129+
// OpenRouter Params
130+
CacheControl json.RawMessage `json:"cache_control,omitempty"`
128131
}
129132

130133
func (m *MediaContent) GetImageMedia() *MessageImageUrl {

relay/channel/openrouter/dto.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package openrouter
2+
3+
type RequestReasoning struct {
4+
// One of the following (not both):
5+
Effort string `json:"effort,omitempty"` // Can be "high", "medium", or "low" (OpenAI-style)
6+
MaxTokens int `json:"max_tokens,omitempty"` // Specific token limit (Anthropic-style)
7+
// Optional: Default is false. All models support this.
8+
Exclude bool `json:"exclude,omitempty"` // Set to true to exclude reasoning tokens from response
9+
}

service/convert.go

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"one-api/common"
77
"one-api/dto"
8+
"one-api/relay/channel/openrouter"
89
relaycommon "one-api/relay/common"
910
"strings"
1011
)
@@ -18,10 +19,24 @@ func ClaudeToOpenAIRequest(claudeRequest dto.ClaudeRequest, info *relaycommon.Re
1819
Stream: claudeRequest.Stream,
1920
}
2021

22+
isOpenRouter := info.ChannelType == common.ChannelTypeOpenRouter
23+
2124
if claudeRequest.Thinking != nil {
22-
if strings.HasSuffix(info.OriginModelName, "-thinking") &&
23-
!strings.HasSuffix(claudeRequest.Model, "-thinking") {
24-
openAIRequest.Model = openAIRequest.Model + "-thinking"
25+
if isOpenRouter {
26+
reasoning := openrouter.RequestReasoning{
27+
MaxTokens: claudeRequest.Thinking.BudgetTokens,
28+
}
29+
reasoningJSON, err := json.Marshal(reasoning)
30+
if err != nil {
31+
return nil, fmt.Errorf("failed to marshal reasoning: %w", err)
32+
}
33+
openAIRequest.Reasoning = reasoningJSON
34+
} else {
35+
thinkingSuffix := "-thinking"
36+
if strings.HasSuffix(info.OriginModelName, thinkingSuffix) &&
37+
!strings.HasSuffix(openAIRequest.Model, thinkingSuffix) {
38+
openAIRequest.Model = openAIRequest.Model + thinkingSuffix
39+
}
2540
}
2641
}
2742

@@ -62,16 +77,30 @@ func ClaudeToOpenAIRequest(claudeRequest dto.ClaudeRequest, info *relaycommon.Re
6277
} else {
6378
systems := claudeRequest.ParseSystem()
6479
if len(systems) > 0 {
65-
systemStr := ""
6680
openAIMessage := dto.Message{
6781
Role: "system",
6882
}
69-
for _, system := range systems {
70-
if system.Text != nil {
71-
systemStr += *system.Text
83+
isOpenRouterClaude := isOpenRouter && strings.HasPrefix(info.UpstreamModelName, "anthropic/claude")
84+
if isOpenRouterClaude {
85+
systemMediaMessages := make([]dto.MediaContent, 0, len(systems))
86+
for _, system := range systems {
87+
message := dto.MediaContent{
88+
Type: "text",
89+
Text: system.GetText(),
90+
CacheControl: system.CacheControl,
91+
}
92+
systemMediaMessages = append(systemMediaMessages, message)
93+
}
94+
openAIMessage.SetMediaContent(systemMediaMessages)
95+
} else {
96+
systemStr := ""
97+
for _, system := range systems {
98+
if system.Text != nil {
99+
systemStr += *system.Text
100+
}
72101
}
102+
openAIMessage.SetStringContent(systemStr)
73103
}
74-
openAIMessage.SetStringContent(systemStr)
75104
openAIMessages = append(openAIMessages, openAIMessage)
76105
}
77106
}
@@ -97,8 +126,9 @@ func ClaudeToOpenAIRequest(claudeRequest dto.ClaudeRequest, info *relaycommon.Re
97126
switch mediaMsg.Type {
98127
case "text":
99128
message := dto.MediaContent{
100-
Type: "text",
101-
Text: mediaMsg.GetText(),
129+
Type: "text",
130+
Text: mediaMsg.GetText(),
131+
CacheControl: mediaMsg.CacheControl,
102132
}
103133
mediaMessages = append(mediaMessages, message)
104134
case "image":

0 commit comments

Comments
 (0)