Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions dto/claude.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,11 @@ func ProcessTools(tools []any) ([]*Tool, []*ClaudeWebSearchTool) {
type Thinking struct {
Type string `json:"type,omitempty"`
BudgetTokens *int `json:"budget_tokens,omitempty"`
// Display controls whether thinking content is returned in the response.
// Used with adaptive thinking on Claude Opus 4.7+: "summarized" restores
// the visible summary that was default on Opus 4.6; "omitted" (default on
// 4.7) suppresses it. Pass-through field from upstream Anthropic API.
Display string `json:"display,omitempty"`
Comment on lines 448 to +455

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Make Thinking.Display a pointer field.

Display is an optional scalar on a request DTO that gets parsed from client JSON and re-marshaled upstream. With string,omitempty, an explicit empty value is indistinguishable from unset, which breaks the DTO contract used elsewhere in this layer.

♻️ Suggested shape
 type Thinking struct {
 	Type         string `json:"type,omitempty"`
 	BudgetTokens *int   `json:"budget_tokens,omitempty"`
-	Display      string `json:"display,omitempty"`
+	Display      *string `json:"display,omitempty"`
 }
request.Thinking.Display = common.GetPointer("summarized")

As per coding guidelines, dto/**/*.go: optional scalar fields MUST use pointer types with omitempty, not non-pointer scalars.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dto/claude.go` around lines 448 - 455, The Thinking.Display field is
currently a non-pointer string which makes it impossible to distinguish unset vs
explicit empty when parsing and re-marshaling; change the Display declaration in
the Thinking struct (dto/claude.go) from `Display string` to `Display *string`
with the same `json:"display,omitempty"` tag, and update all call sites that set
or read Thinking.Display (e.g., assignments in request construction or tests) to
use pointer values (e.g., common.GetPointer("summarized") or &val) and nil
checks where appropriate so the DTO preserves the optional scalar semantics.

}

func (c *Thinking) GetBudgetTokens() int {
Expand Down
6 changes: 6 additions & 0 deletions relay/channel/aws/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var awsModelIDMap = map[string]string{
"claude-haiku-4-5-20251001": "anthropic.claude-haiku-4-5-20251001-v1:0",
"claude-opus-4-5-20251101": "anthropic.claude-opus-4-5-20251101-v1:0",
"claude-opus-4-6": "anthropic.claude-opus-4-6-v1",
"claude-opus-4-7": "anthropic.claude-opus-4-7",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

site:docs.aws.amazon.com Bedrock "claude-opus-4-7" model ID

💡 Result:

No Bedrock model ID "claude-opus-4-7" exists. Claude Opus 4.7 is listed as available in Amazon Bedrock (https://docs.aws.amazon.com/bedrock/latest/userguide/model-cards-anthropic.html), but its specific model ID is not explicitly stated in model ID lists or model cards. Similar models use IDs like anthropic.claude-opus-4-6-v1 (for Opus 4.6) or anthropic.claude-opus-4-5-20251101-v1:0 (for Opus 4.5). It may follow the pattern anthropic.claude-opus-4-7-v1, but this is not confirmed in official sources. Check the latest AWS Bedrock console or ListFoundationModels API for the exact ID.

Citations:


🏁 Script executed:

# First, let's check if the file exists and view the relevant sections
if [ -f relay/channel/aws/constants.go ]; then
  echo "=== Lines 15-30 (around line 21) ==="
  sed -n '15,30p' relay/channel/aws/constants.go
  echo ""
  echo "=== Lines 90-105 (around lines 95-99) ==="
  sed -n '90,105p' relay/channel/aws/constants.go
  echo ""
  echo "=== Total line count ==="
  wc -l relay/channel/aws/constants.go
else
  echo "File not found"
fi

Repository: QuantumNous/new-api

Length of output: 1387


Replace model ID with documented versioned format or remove unpublished entry.

The Bedrock model ID anthropic.claude-opus-4-7 breaks the established pattern—all other Opus models in this file use versioned formats (anthropic.claude-opus-4-6-v1, anthropic.claude-opus-4-5-20251101-v1:0). AWS Bedrock documentation lists Opus 4.7 as available but does not explicitly publish the model ID. This unversioned ID will cause API requests to fail. Either use the documented versioned format (likely anthropic.claude-opus-4-7-v1, though unconfirmed) by checking the latest AWS Bedrock ListFoundationModels API, or remove this entry until the official model ID is published.

Affected locations: line 21 (awsModelIDMap) and lines 95–99 (awsModelCanCrossRegionMap).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@relay/channel/aws/constants.go` at line 21, The entry for "claude-opus-4-7"
in awsModelIDMap and its corresponding key in awsModelCanCrossRegionMap uses an
unversioned Bedrock model ID ("anthropic.claude-opus-4-7") which will fail;
update these maps by either replacing that value with the official versioned
model ID (e.g., "anthropic.claude-opus-4-7-v1") after confirming via the AWS
Bedrock ListFoundationModels API, or remove the "claude-opus-4-7" entries from
awsModelIDMap and awsModelCanCrossRegionMap until the published model ID is
confirmed to avoid broken API calls.

// Nova models
"nova-micro-v1:0": "amazon.nova-micro-v1:0",
"nova-lite-v1:0": "amazon.nova-lite-v1:0",
Expand Down Expand Up @@ -91,6 +92,11 @@ var awsModelCanCrossRegionMap = map[string]map[string]bool{
"ap": true,
"eu": true,
},
"anthropic.claude-opus-4-7": {
"us": true,
"ap": true,
"eu": true,
},
"anthropic.claude-haiku-4-5-20251001-v1:0": {
"us": true,
"ap": true,
Expand Down
7 changes: 7 additions & 0 deletions relay/channel/claude/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ var ModelList = []string{
"claude-opus-4-6-medium",
"claude-opus-4-6-low",
"claude-sonnet-4-6",
"claude-opus-4-7",
"claude-opus-4-7-max",
"claude-opus-4-7-xhigh",
"claude-opus-4-7-high",
"claude-opus-4-7-medium",
"claude-opus-4-7-low",
"claude-opus-4-7-thinking",
}

var ChannelName = "claude"
51 changes: 35 additions & 16 deletions relay/channel/claude/relay-claude.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,33 +154,52 @@ func RequestOpenAI2ClaudeMessage(c *gin.Context, textRequest dto.GeneralOpenAIRe
}

if baseModel, effortLevel, ok := reasoning.TrimEffortSuffix(textRequest.Model); ok && effortLevel != "" &&
strings.HasPrefix(textRequest.Model, "claude-opus-4-6") {
(strings.HasPrefix(textRequest.Model, "claude-opus-4-6") || strings.HasPrefix(textRequest.Model, "claude-opus-4-7")) {
claudeRequest.Model = baseModel
claudeRequest.Thinking = &dto.Thinking{
Type: "adaptive",
}
claudeRequest.OutputConfig = json.RawMessage(fmt.Sprintf(`{"effort":"%s"}`, effortLevel))
claudeRequest.TopP = nil
claudeRequest.Temperature = common.GetPointer[float64](1.0)
if strings.HasPrefix(baseModel, "claude-opus-4-7") {
// Opus 4.7 rejects non-default temperature/top_p/top_k with 400
// and defaults display to "omitted"; restore the 4.6 visible summary.
claudeRequest.Thinking.Display = "summarized"
claudeRequest.Temperature = nil
claudeRequest.TopP = nil
claudeRequest.TopK = nil
} else {
claudeRequest.TopP = nil
claudeRequest.Temperature = common.GetPointer[float64](1.0)
}
} else if model_setting.GetClaudeSettings().ThinkingAdapterEnabled &&
strings.HasSuffix(textRequest.Model, "-thinking") {

// 因为BudgetTokens 必须大于1024
if claudeRequest.MaxTokens == nil || *claudeRequest.MaxTokens < 1280 {
claudeRequest.MaxTokens = common.GetPointer[uint](1280)
}
trimmedModel := strings.TrimSuffix(textRequest.Model, "-thinking")
if strings.HasPrefix(trimmedModel, "claude-opus-4-7") {
// Opus 4.7 rejects thinking.type="enabled"; use adaptive at high effort.
claudeRequest.Thinking = &dto.Thinking{Type: "adaptive", Display: "summarized"}
claudeRequest.OutputConfig = json.RawMessage(`{"effort":"high"}`)
claudeRequest.Temperature = nil
claudeRequest.TopP = nil
claudeRequest.TopK = nil
Comment on lines +163 to +184

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Keep Opus 4.7 on adaptive thinking when reasoning overrides are present.

Lines 163-184 switch Opus 4.7 to thinking.type="adaptive" because "enabled" is rejected, but Lines 206-239 still overwrite that with {type:"enabled", budget_tokens:...} for reasoning_effort / reasoning.max_tokens. claude-opus-4-7 and claude-opus-4-7-thinking requests with those fields will still hit the same 400 this branch is trying to avoid. Route those overrides through OutputConfig.effort for 4.7 instead of reusing the older budget-token path.

Possible direction
+isOpus47 := strings.HasPrefix(strings.TrimSuffix(claudeRequest.Model, "-thinking"), "claude-opus-4-7")
+
 if textRequest.ReasoningEffort != "" {
 	switch textRequest.ReasoningEffort {
 	case "low":
-		claudeRequest.Thinking = &dto.Thinking{
-			Type:         "enabled",
-			BudgetTokens: common.GetPointer[int](1280),
-		}
+		if isOpus47 {
+			claudeRequest.Thinking = &dto.Thinking{Type: "adaptive", Display: "summarized"}
+			claudeRequest.OutputConfig = json.RawMessage(`{"effort":"low"}`)
+			claudeRequest.Temperature = nil
+			claudeRequest.TopP = nil
+			claudeRequest.TopK = nil
+		} else {
+			claudeRequest.Thinking = &dto.Thinking{
+				Type:         "enabled",
+				BudgetTokens: common.GetPointer[int](1280),
+			}
+		}
 	}
 }

Apply the same branching to the medium, high, and explicit Reasoning.MaxTokens path.

Also applies to: 206-239

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@relay/channel/claude/relay-claude.go` around lines 163 - 184, The current
branch correctly sets claudeRequest.Thinking to adaptive and OutputConfig.effort
for claude-opus-4-7 when enabling the Thinking adapter, but later logic that
maps reasoning overrides (reasoning_effort, Reasoning.MaxTokens or the
medium/high branches) still writes thinking.Type="enabled" and budget_tokens,
which will cause 400s for Opus 4.7; update the downstream mapping so when
trimmedModel or textRequest.Model matches the "claude-opus-4-7" prefix you route
reasoning overrides into claudeRequest.OutputConfig (set effort to
"medium"/"high" or include the appropriate effort JSON) and do NOT set
Thinking.Type="enabled" or budget_tokens/Reasoning.MaxTokens on claudeRequest;
keep the existing behavior for non-4.7 models (i.e., preserve the existing
branches that set Thinking.Type="enabled" and budget_tokens for other models).

} else {
// 因为BudgetTokens 必须大于1024
if claudeRequest.MaxTokens == nil || *claudeRequest.MaxTokens < 1280 {
claudeRequest.MaxTokens = common.GetPointer[uint](1280)
}

// BudgetTokens 为 max_tokens 的 80%
claudeRequest.Thinking = &dto.Thinking{
Type: "enabled",
BudgetTokens: common.GetPointer[int](int(float64(*claudeRequest.MaxTokens) * model_setting.GetClaudeSettings().ThinkingAdapterBudgetTokensPercentage)),
// BudgetTokens 为 max_tokens 的 80%
claudeRequest.Thinking = &dto.Thinking{
Type: "enabled",
BudgetTokens: common.GetPointer[int](int(float64(*claudeRequest.MaxTokens) * model_setting.GetClaudeSettings().ThinkingAdapterBudgetTokensPercentage)),
}
// TODO: 临时处理
// https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking#important-considerations-when-using-extended-thinking
claudeRequest.TopP = nil
claudeRequest.Temperature = common.GetPointer[float64](1.0)
}
// TODO: 临时处理
// https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking#important-considerations-when-using-extended-thinking
claudeRequest.TopP = nil
claudeRequest.Temperature = common.GetPointer[float64](1.0)
if !model_setting.ShouldPreserveThinkingSuffix(textRequest.Model) {
claudeRequest.Model = strings.TrimSuffix(textRequest.Model, "-thinking")
claudeRequest.Model = trimmedModel
}
}

Expand Down
1 change: 1 addition & 0 deletions relay/channel/vertex/adaptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ var claudeModelMap = map[string]string{
"claude-haiku-4-5-20251001": "claude-haiku-4-5@20251001",
"claude-opus-4-5-20251101": "claude-opus-4-5@20251101",
"claude-opus-4-6": "claude-opus-4-6",
"claude-opus-4-7": "claude-opus-4-7",
}

const anthropicVersion = "vertex-2023-10-16"
Expand Down
45 changes: 32 additions & 13 deletions relay/claude_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,30 +53,49 @@ func ClaudeHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *typ
}

if baseModel, effortLevel, ok := reasoning.TrimEffortSuffix(request.Model); ok && effortLevel != "" &&
strings.HasPrefix(request.Model, "claude-opus-4-6") {
(strings.HasPrefix(request.Model, "claude-opus-4-6") || strings.HasPrefix(request.Model, "claude-opus-4-7")) {
request.Model = baseModel
request.Thinking = &dto.Thinking{
Type: "adaptive",
}
request.OutputConfig = json.RawMessage(fmt.Sprintf(`{"effort":"%s"}`, effortLevel))
request.Temperature = common.GetPointer[float64](1.0)
if strings.HasPrefix(request.Model, "claude-opus-4-7") {
// Opus 4.7 rejects non-default temperature/top_p/top_k with 400
// and defaults display to "omitted"; restore the 4.6 visible summary.
request.Thinking.Display = "summarized"
request.Temperature = nil
request.TopP = nil
request.TopK = nil
} else {
request.Temperature = common.GetPointer[float64](1.0)
}
info.UpstreamModelName = request.Model
} else if model_setting.GetClaudeSettings().ThinkingAdapterEnabled &&
strings.HasSuffix(request.Model, "-thinking") {
if request.Thinking == nil {
// 因为BudgetTokens 必须大于1024
if request.MaxTokens == nil || *request.MaxTokens < 1280 {
request.MaxTokens = common.GetPointer[uint](1280)
}
baseModel := strings.TrimSuffix(request.Model, "-thinking")
if strings.HasPrefix(baseModel, "claude-opus-4-7") {
// Opus 4.7 rejects thinking.type="enabled"; use adaptive at high effort.
request.Thinking = &dto.Thinking{Type: "adaptive", Display: "summarized"}
request.OutputConfig = json.RawMessage(`{"effort":"high"}`)
request.Temperature = nil
request.TopP = nil
request.TopK = nil
} else {
// 因为BudgetTokens 必须大于1024
if request.MaxTokens == nil || *request.MaxTokens < 1280 {
request.MaxTokens = common.GetPointer[uint](1280)
}

// BudgetTokens 为 max_tokens 的 80%
request.Thinking = &dto.Thinking{
Type: "enabled",
BudgetTokens: common.GetPointer[int](int(float64(*request.MaxTokens) * model_setting.GetClaudeSettings().ThinkingAdapterBudgetTokensPercentage)),
// BudgetTokens 为 max_tokens 的 80%
request.Thinking = &dto.Thinking{
Type: "enabled",
BudgetTokens: common.GetPointer[int](int(float64(*request.MaxTokens) * model_setting.GetClaudeSettings().ThinkingAdapterBudgetTokensPercentage)),
}
// TODO: 临时处理
// https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking#important-considerations-when-using-extended-thinking
request.Temperature = common.GetPointer[float64](1.0)
}
Comment on lines 75 to 98

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Apply the Opus 4.7 normalization even when thinking is already present.

The 4.7-specific rewrite only runs inside if request.Thinking == nil. A request like claude-opus-4-7-thinking with a client-supplied thinking object skips the adaptive/display conversion and leaves temperature/top_p/top_k untouched, so the alias can still hit the upstream 400s this branch is trying to avoid.

🐛 Minimal fix sketch
-		if request.Thinking == nil {
-			baseModel := strings.TrimSuffix(request.Model, "-thinking")
-			if strings.HasPrefix(baseModel, "claude-opus-4-7") {
-				request.Thinking = &dto.Thinking{Type: "adaptive", Display: "summarized"}
-				request.OutputConfig = json.RawMessage(`{"effort":"high"}`)
-				request.Temperature = nil
-				request.TopP = nil
-				request.TopK = nil
-			} else {
+		baseModel := strings.TrimSuffix(request.Model, "-thinking")
+		if strings.HasPrefix(baseModel, "claude-opus-4-7") {
+			if request.Thinking == nil {
+				request.Thinking = &dto.Thinking{}
+			}
+			request.Thinking.Type = "adaptive"
+			request.Thinking.Display = "summarized"
+			request.OutputConfig = json.RawMessage(`{"effort":"high"}`)
+			request.Temperature = nil
+			request.TopP = nil
+			request.TopK = nil
+		} else if request.Thinking == nil {
 				// 因为BudgetTokens 必须大于1024
 				if request.MaxTokens == nil || *request.MaxTokens < 1280 {
 					request.MaxTokens = common.GetPointer[uint](1280)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if request.Thinking == nil {
// 因为BudgetTokens 必须大于1024
if request.MaxTokens == nil || *request.MaxTokens < 1280 {
request.MaxTokens = common.GetPointer[uint](1280)
}
baseModel := strings.TrimSuffix(request.Model, "-thinking")
if strings.HasPrefix(baseModel, "claude-opus-4-7") {
// Opus 4.7 rejects thinking.type="enabled"; use adaptive at high effort.
request.Thinking = &dto.Thinking{Type: "adaptive", Display: "summarized"}
request.OutputConfig = json.RawMessage(`{"effort":"high"}`)
request.Temperature = nil
request.TopP = nil
request.TopK = nil
} else {
// 因为BudgetTokens 必须大于1024
if request.MaxTokens == nil || *request.MaxTokens < 1280 {
request.MaxTokens = common.GetPointer[uint](1280)
}
// BudgetTokens 为 max_tokens 的 80%
request.Thinking = &dto.Thinking{
Type: "enabled",
BudgetTokens: common.GetPointer[int](int(float64(*request.MaxTokens) * model_setting.GetClaudeSettings().ThinkingAdapterBudgetTokensPercentage)),
// BudgetTokens 为 max_tokens 的 80%
request.Thinking = &dto.Thinking{
Type: "enabled",
BudgetTokens: common.GetPointer[int](int(float64(*request.MaxTokens) * model_setting.GetClaudeSettings().ThinkingAdapterBudgetTokensPercentage)),
}
// TODO: 临时处理
// https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking#important-considerations-when-using-extended-thinking
request.Temperature = common.GetPointer[float64](1.0)
}
baseModel := strings.TrimSuffix(request.Model, "-thinking")
if strings.HasPrefix(baseModel, "claude-opus-4-7") {
if request.Thinking == nil {
request.Thinking = &dto.Thinking{}
}
request.Thinking.Type = "adaptive"
request.Thinking.Display = "summarized"
request.OutputConfig = json.RawMessage(`{"effort":"high"}`)
request.Temperature = nil
request.TopP = nil
request.TopK = nil
} else if request.Thinking == nil {
// 因为BudgetTokens 必须大于1024
if request.MaxTokens == nil || *request.MaxTokens < 1280 {
request.MaxTokens = common.GetPointer[uint](1280)
}
// BudgetTokens 为 max_tokens 的 80%
request.Thinking = &dto.Thinking{
Type: "enabled",
BudgetTokens: common.GetPointer[int](int(float64(*request.MaxTokens) * model_setting.GetClaudeSettings().ThinkingAdapterBudgetTokensPercentage)),
}
// TODO: 临时处理
// https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking#important-considerations-when-using-extended-thinking
request.Temperature = common.GetPointer[float64](1.0)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@relay/claude_handler.go` around lines 75 - 98, The Opus 4.7 normalization
must run regardless of whether request.Thinking is nil: detect baseModel via
strings.TrimSuffix(request.Model, "-thinking") and if
strings.HasPrefix(baseModel, "claude-opus-4-7") always set request.Thinking =
&dto.Thinking{Type:"adaptive", Display:"summarized"}, set request.OutputConfig =
json.RawMessage(`{"effort":"high"}`) and clear
request.Temperature/request.TopP/request.TopK; otherwise preserve any
client-supplied request.Thinking but keep the existing fallback logic that when
request.Thinking == nil sets request.MaxTokens (use common.GetPointer), computes
BudgetTokens using
model_setting.GetClaudeSettings().ThinkingAdapterBudgetTokensPercentage and
assigns request.Thinking accordingly, and sets default Temperature to
common.GetPointer[float64](1.0).

// TODO: 临时处理
// https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking#important-considerations-when-using-extended-thinking
request.Temperature = common.GetPointer[float64](1.0)
}
if !model_setting.ShouldPreserveThinkingSuffix(info.OriginModelName) {
request.Model = strings.TrimSuffix(request.Model, "-thinking")
Expand Down
14 changes: 14 additions & 0 deletions setting/ratio_setting/cache_ratio.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ var defaultCacheRatio = map[string]float64{
"claude-opus-4-6-high": 0.1,
"claude-opus-4-6-medium": 0.1,
"claude-opus-4-6-low": 0.1,
"claude-opus-4-7": 0.1,
"claude-opus-4-7-thinking": 0.1,
"claude-opus-4-7-max": 0.1,
"claude-opus-4-7-xhigh": 0.1,
"claude-opus-4-7-high": 0.1,
"claude-opus-4-7-medium": 0.1,
"claude-opus-4-7-low": 0.1,
}

var defaultCreateCacheRatio = map[string]float64{
Expand Down Expand Up @@ -92,6 +99,13 @@ var defaultCreateCacheRatio = map[string]float64{
"claude-opus-4-6-high": 1.25,
"claude-opus-4-6-medium": 1.25,
"claude-opus-4-6-low": 1.25,
"claude-opus-4-7": 1.25,
"claude-opus-4-7-thinking": 1.25,
"claude-opus-4-7-max": 1.25,
"claude-opus-4-7-xhigh": 1.25,
"claude-opus-4-7-high": 1.25,
"claude-opus-4-7-medium": 1.25,
"claude-opus-4-7-low": 1.25,
}

//var defaultCreateCacheRatio = map[string]float64{}
Expand Down
6 changes: 6 additions & 0 deletions setting/ratio_setting/model_ratio.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ var defaultModelRatio = map[string]float64{
"claude-opus-4-6-high": 2.5,
"claude-opus-4-6-medium": 2.5,
"claude-opus-4-6-low": 2.5,
"claude-opus-4-7": 2.5,
"claude-opus-4-7-max": 2.5,
"claude-opus-4-7-xhigh": 2.5,
"claude-opus-4-7-high": 2.5,
"claude-opus-4-7-medium": 2.5,
"claude-opus-4-7-low": 2.5,
"claude-3-opus-20240229": 7.5, // $15 / 1M tokens
"claude-opus-4-20250514": 7.5,
"claude-opus-4-1-20250805": 7.5,
Expand Down
2 changes: 1 addition & 1 deletion setting/reasoning/suffix.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/samber/lo"
)

var EffortSuffixes = []string{"-max", "-high", "-medium", "-low", "-minimal"}
var EffortSuffixes = []string{"-max", "-xhigh", "-high", "-medium", "-low", "-minimal"}

// TrimEffortSuffix -> modelName level(low) exists
func TrimEffortSuffix(modelName string) (string, string, bool) {
Expand Down