Skip to content

feat: support claude-opus-4-7 - #4293

Merged
Calcium-Ion merged 2 commits into
QuantumNous:mainfrom
prnake:claude-opus-4-7
Apr 17, 2026
Merged

feat: support claude-opus-4-7#4293
Calcium-Ion merged 2 commits into
QuantumNous:mainfrom
prnake:claude-opus-4-7

Conversation

@prnake

@prnake prnake commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

⚠️ 提交说明 / PR Notice

📝 变更描述 / Description

support claude-opus-4-7

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

  • Closes # (如有)

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

(请在此粘贴截图、关键日志或测试报告,以证明变更生效)

Summary by CodeRabbit

Release Notes

  • New Features
    • Added support for Claude Opus 4.7 models and variants, including thinking-enabled options
    • Extended thinking display controls for improved configuration
    • Introduced new effort level option for model variants
    • Enabled multi-region availability for Opus 4.7 on supported platforms

@coderabbitai

coderabbitai Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR adds support for Claude Opus 4.7 model family across the system by registering new model identifiers, extending cloud provider mappings (AWS and Vertex), updating configuration ratios for caching and model pricing, adding the -xhigh effort suffix to the reasoning system, extending the DTO to support thinking display control, and implementing model-specific thinking adapter logic with adaptive thinking configuration and summarized display settings.

Changes

Cohort / File(s) Summary
DTO Extension
dto/claude.go
Added Display string field to Thinking struct to support upstream thinking display control in Claude request payloads.
Model Registration
relay/channel/claude/constants.go
Extended ModelList with Claude Opus 4.7 variants: base, -max, -xhigh, -high, -medium, -low, and -thinking suffixes.
Cloud Provider Mappings
relay/channel/aws/constants.go, relay/channel/vertex/adaptor.go
Added claude-opus-4-7 mappings to AWS (anthropic.claude-opus-4-7 with cross-region support in us, ap, eu) and Vertex model maps.
Relay Logic & Thinking Adapter
relay/channel/claude/relay-claude.go, relay/claude_handler.go
Extended effort-suffix handling and -thinking adapter path to support claude-opus-4-7 with adaptive thinking type, summarized display, forced high effort output config, and cleared temperature/sampling parameters; refactored model trimming to avoid re-trimming.
Configuration Ratios
setting/ratio_setting/cache_ratio.go, setting/ratio_setting/model_ratio.go
Added cache and model ratio entries for claude-opus-4-7 and its variants, using consistent ratio values (0.1 and 1.25 for cache, 2.5 for model).
Reasoning Suffixes
setting/reasoning/suffix.go
Extended EffortSuffixes to include -xhigh suffix alongside existing -max, -high, -medium, -low, -minimal values.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Handler as Claude Handler
    participant RelayAdapter as Relay Adapter
    participant CloudProvider as Cloud Provider (AWS/Vertex)

    Client->>Handler: Send request (model=claude-opus-4-7-thinking)
    
    Handler->>Handler: Detect model name & thinking suffix
    Handler->>Handler: Trim model to base (claude-opus-4-7)
    
    alt Is Opus 4.7 with Thinking
        Handler->>Handler: Set Thinking.Type="adaptive"
        Handler->>Handler: Set Thinking.Display="summarized"
        Handler->>Handler: Set OutputConfig={"effort":"high"}
        Handler->>Handler: Clear Temperature, TopP, TopK
    else Other Opus Models
        Handler->>Handler: Set Thinking.Type="enabled"
        Handler->>Handler: Set BudgetTokens per constraints
        Handler->>Handler: Set Temperature=1.0
    end
    
    Handler->>RelayAdapter: Forward modified request
    RelayAdapter->>CloudProvider: Map model & send request
    CloudProvider-->>RelayAdapter: Return response
    RelayAdapter-->>Handler: Return response
    Handler-->>Client: Return final response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested reviewers

  • seefs001
  • Calcium-Ion

Poem

🐰 A fluffy hop through models new,
Opus 4.7 shines so true,
With thinking set to summarized grace,
And adaptive effort in every case! 🎯✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat: support claude-opus-4-7' directly and clearly summarizes the main change across all modified files, which collectively add support for the new Claude Opus 4.7 model.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 4

🧹 Nitpick comments (1)
relay/channel/claude/relay-claude.go (1)

156-203: Extract the Opus thinking normalization into one helper.

This block now duplicates relay/claude_handler.go:44-104, and the two paths have already drifted: Line 171 clears TopP for claude-opus-4-6 here, while the handler path keeps the caller value. A shared helper would keep OpenAI and Claude relay behavior aligned for future Claude model/suffix additions.

🤖 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 156 - 203, Summary:
Duplicate Opus "thinking" normalization logic should be extracted into a single
helper and the 4.6/4.7 drift resolved by matching the handler behavior. Create a
helper (e.g. NormalizeOpusThinking(model string, req *dto.ClaudeRequest)
(newModel string)) and move the duplicated logic that inspects TrimEffortSuffix,
"-thinking" suffix, sets claudeRequest.Thinking, OutputConfig, Temperature,
TopP, TopK, MaxTokens and Model into it; replace both call sites
(relay/channel/claude/relay-claude.go and relay/claude_handler.go) to call this
helper, and ensure the helper preserves the caller's TopP for claude-opus-4-6
(i.e., do not unconditionally clear TopP for 4.6) so behavior matches the
handler path. Ensure the helper uses model_setting.GetClaudeSettings() and
ShouldPreserveThinkingSuffix where currently referenced and returns the possibly
trimmed model to assign back to claudeRequest.Model.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@dto/claude.go`:
- Around line 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.

In `@relay/channel/aws/constants.go`:
- 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.

In `@relay/channel/claude/relay-claude.go`:
- Around line 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).

In `@relay/claude_handler.go`:
- Around line 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).

---

Nitpick comments:
In `@relay/channel/claude/relay-claude.go`:
- Around line 156-203: Summary: Duplicate Opus "thinking" normalization logic
should be extracted into a single helper and the 4.6/4.7 drift resolved by
matching the handler behavior. Create a helper (e.g. NormalizeOpusThinking(model
string, req *dto.ClaudeRequest) (newModel string)) and move the duplicated logic
that inspects TrimEffortSuffix, "-thinking" suffix, sets claudeRequest.Thinking,
OutputConfig, Temperature, TopP, TopK, MaxTokens and Model into it; replace both
call sites (relay/channel/claude/relay-claude.go and relay/claude_handler.go) to
call this helper, and ensure the helper preserves the caller's TopP for
claude-opus-4-6 (i.e., do not unconditionally clear TopP for 4.6) so behavior
matches the handler path. Ensure the helper uses
model_setting.GetClaudeSettings() and ShouldPreserveThinkingSuffix where
currently referenced and returns the possibly trimmed model to assign back to
claudeRequest.Model.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 658bee7a-47c1-4a66-bbc4-c43b14c8927c

📥 Commits

Reviewing files that changed from the base of the PR and between 22e509c and 7a0cd78.

📒 Files selected for processing (9)
  • dto/claude.go
  • relay/channel/aws/constants.go
  • relay/channel/claude/constants.go
  • relay/channel/claude/relay-claude.go
  • relay/channel/vertex/adaptor.go
  • relay/claude_handler.go
  • setting/ratio_setting/cache_ratio.go
  • setting/ratio_setting/model_ratio.go
  • setting/reasoning/suffix.go

Comment thread dto/claude.go
Comment on lines 448 to +455
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"`

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.

"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.

Comment on lines +163 to +184
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

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).

Comment thread relay/claude_handler.go
Comment on lines 75 to 98
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)
}

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).

@Calcium-Ion
Calcium-Ion merged commit 47d7bca into QuantumNous:main Apr 17, 2026
2 checks passed
prnake added a commit to prnake/new-api that referenced this pull request Apr 17, 2026
xyfacai pushed a commit to xyfacai/new-api that referenced this pull request Apr 20, 2026
* feat: support claude-opus-4-7

* feat: summarized display for opus 4.7
mygoda pushed a commit to mygoda/new-api that referenced this pull request Apr 20, 2026
* feat: support claude-opus-4-7

* feat: summarized display for opus 4.7
liuyaaixxa pushed a commit to liuyaaixxa/xnew-api that referenced this pull request Apr 23, 2026
* feat: support claude-opus-4-7

* feat: summarized display for opus 4.7
isboyjc pushed a commit to isboyjc/amux-api that referenced this pull request Apr 29, 2026
* feat: support claude-opus-4-7

* feat: summarized display for opus 4.7
Jinxuans referenced this pull request in TokFlux-Org/TokFlux May 9, 2026
* feat: support claude-opus-4-7

* feat: summarized display for opus 4.7
ljdzxx pushed a commit to ljdzxx/new-api that referenced this pull request May 9, 2026
* feat: support claude-opus-4-7

* feat: summarized display for opus 4.7
@coderabbitai coderabbitai Bot mentioned this pull request May 29, 2026
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants