mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-07-06 22:55:56 +08:00
feat: Add Claude Sonnet 4.6 model support to Anthropic provider (#13016)
<!-- Template from https://github.com/kubevirt/kubevirt/blob/main/.github/PULL_REQUEST_TEMPLATE.md?--> <!-- Thanks for sending a pull request! Here are some tips for you: 1. Consider creating this PR as draft: https://github.com/CherryHQ/cherry-studio/blob/main/CONTRIBUTING.md --> <!-- ⚠️ Important: Redux/IndexedDB Data-Changing Feature PRs Temporarily On Hold ⚠️ Please note: For our current development cycle, we are not accepting feature Pull Requests that introduce changes to Redux data models or IndexedDB schemas. While we value your contributions, PRs of this nature will be blocked without merge. We welcome all other contributions (bug fixes, perf enhancements, docs, etc.). Thank you! Once version 2.0.0 is released, we will resume reviewing feature PRs. --> ### What this PR does Before this PR: - Lack of Sonnet 4.6 related configuration support, not fully available After this PR: - Added Claude Sonnet 4.6 (`claude-sonnet-4-6`) to the Anthropic provider - Added support for reasoning effort (extended thinking) on Claude Sonnet 4.6 models - Added proper regex patterns to detect all Claude 4.6 series models (Opus, Sonnet, Haiku) - Renamed model detection functions to reflect the entire Claude 4.6 series <!-- (optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: --> Fixes # ### Why we need it and why it was done in this way The Claude 4.6 series introduces new models beyond Opus, including Sonnet 4.6 with reasoning capabilities. This PR ensures Cherry Studio fully supports the new Sonnet 4.6 model with proper model detection, token limits, and reasoning effort configuration. The following tradeoffs were made: - Used regex patterns that match the entire Claude 4.6 series for future extensibility - Maintained backward compatibility with existing Opus 4.6 model detection The following alternatives were considered: - Separate detection for each model type (rejected in favor of unified series detection) - Hardcoding model IDs instead of regex patterns (rejected for maintainability) Links to places where the discussion took place: <!-- optional: slack, other GH issue, mailinglist, ... --> ### Breaking changes <!-- optional --> If this PR introduces breaking changes, please describe the changes and the impact on users. N/A ### Special notes for your reviewer <!-- optional --> This PR includes refactoring commits that rename `opus46` to `claude46` for model type detection. The logic remains the same but now applies to the entire Claude 4.6 series. ### Checklist This checklist is not enforcing, but it's a reminder of items that could be relevant to every PR. Approvers are expected to review this list. - [x] PR: The PR description is expressive enough and will help future contributors - [x] Code: [Write code that humans can understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans) and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle) - [x] Refactor: You have [left the code cleaner than you found it (Boy Scout Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html) - [x] Upgrade: Impact of this change on upgrade flows was considered and addressed if required - [x] Documentation: A [user-guide update](https://docs.cherry-ai.com) was considered and is present (link) or not required. You want a user-guide update if it's a user facing feature. ### Release note <!-- Write your release note: 1. Enter your extended release note in the below block. If the PR requires additional action from users switching to the new release, include the string "action required". 2. If no release note is required, just write "NONE". --> ```release-note feat: Add Claude Sonnet 4.6 model support to Anthropic provider with reasoning effort configuration ```
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
findTokenLimit,
|
||||
GEMINI_FLASH_MODEL_REGEX,
|
||||
getModelSupportedReasoningEffortOptions,
|
||||
isClaude46SeriesModel,
|
||||
isDeepSeekHybridInferenceModel,
|
||||
isDoubaoSeed18Model,
|
||||
isDoubaoSeedAfter251015,
|
||||
@@ -18,7 +19,6 @@ import {
|
||||
isOpenAIDeepResearchModel,
|
||||
isOpenAIModel,
|
||||
isOpenAIReasoningModel,
|
||||
isOpus46Model,
|
||||
isQwenAlwaysThinkModel,
|
||||
isQwenReasoningModel,
|
||||
isReasoningModel,
|
||||
@@ -559,7 +559,7 @@ export function getAnthropicThinkingBudget(
|
||||
* Extracted from AnthropicAPIClient logic.
|
||||
*
|
||||
* Returns different parameter shapes depending on the model:
|
||||
* - **Opus 4.6**: `{ thinking: { type: 'adaptive' }, effort: 'low' | 'medium' | 'high' | 'max' }`
|
||||
* - **Claude 4.6**: `{ thinking: { type: 'adaptive' }, effort: 'low' | 'medium' | 'high' | 'max' }`
|
||||
* Uses the new adaptive thinking API with effort-based control.
|
||||
* - **Other Claude models** (4.0, 4.1, 4.5, etc.): `{ thinking: { type: 'enabled', budgetTokens: number } }`
|
||||
* Uses the classic thinking API with explicit token budget.
|
||||
@@ -588,10 +588,10 @@ export function getAnthropicReasoningParams(
|
||||
|
||||
// Claude reasoning parameters
|
||||
if (isSupportedThinkingTokenClaudeModel(model)) {
|
||||
// Opus 4.6 uses adaptive thinking + effort parameters
|
||||
// Map reasoningEffort to Opus 4.6 supported effort values
|
||||
if (isOpus46Model(model)) {
|
||||
// Opus 4.6 supports: low, medium, high, max
|
||||
// Claude 4.6 uses adaptive thinking + effort parameters
|
||||
// Map reasoningEffort to Claude 4.6 supported effort values
|
||||
if (isClaude46SeriesModel(model)) {
|
||||
// Claude 4.6 supports: low, medium, high, max
|
||||
// Mapping rules: default/none -> no effort (uses default high)
|
||||
// minimal/low -> low
|
||||
// medium -> medium
|
||||
@@ -772,8 +772,8 @@ export function getBedrockReasoningParams(
|
||||
return {}
|
||||
}
|
||||
|
||||
// Opus 4.6 uses adaptive thinking + maxReasoningEffort
|
||||
if (isOpus46Model(model)) {
|
||||
// Claude 4.6 uses adaptive thinking + maxReasoningEffort
|
||||
if (isClaude46SeriesModel(model)) {
|
||||
const effortMap = {
|
||||
auto: undefined,
|
||||
minimal: 'low',
|
||||
|
||||
@@ -2379,26 +2379,27 @@ describe('isInterleavedThinkingModel', () => {
|
||||
})
|
||||
|
||||
describe('Claude Models', () => {
|
||||
describe('getThinkModelType for Opus 4.6', () => {
|
||||
it('should return opus46 for Opus 4.6 models', () => {
|
||||
expect(getThinkModelType(createModel({ id: 'claude-opus-4-6' }))).toBe('opus46')
|
||||
expect(getThinkModelType(createModel({ id: 'anthropic.claude-opus-4-6-v1' }))).toBe('opus46')
|
||||
describe('getThinkModelType for Claude 4.6 series models', () => {
|
||||
it('should return claude46 for Claude 4.6 models', () => {
|
||||
expect(getThinkModelType(createModel({ id: 'claude-opus-4-6' }))).toBe('claude46')
|
||||
expect(getThinkModelType(createModel({ id: 'claude-sonnet-4-6' }))).toBe('claude46')
|
||||
expect(getThinkModelType(createModel({ id: 'anthropic.claude-opus-4-6-v1' }))).toBe('claude46')
|
||||
})
|
||||
})
|
||||
|
||||
describe('MODEL_SUPPORTED_OPTIONS for Opus 4.6', () => {
|
||||
it('should have correct options for opus46', () => {
|
||||
expect(MODEL_SUPPORTED_OPTIONS.opus46).toEqual(['default', 'none', 'low', 'medium', 'high', 'xhigh'])
|
||||
describe('MODEL_SUPPORTED_OPTIONS for Claude 4.6', () => {
|
||||
it('should have correct options for claude46', () => {
|
||||
expect(MODEL_SUPPORTED_OPTIONS.claude46).toEqual(['default', 'none', 'low', 'medium', 'high', 'xhigh'])
|
||||
})
|
||||
})
|
||||
|
||||
describe('MODEL_SUPPORTED_REASONING_EFFORT for Opus 4.6', () => {
|
||||
it('should have correct effort levels for opus46', () => {
|
||||
expect(MODEL_SUPPORTED_REASONING_EFFORT.opus46).toEqual(['low', 'medium', 'high', 'xhigh'])
|
||||
describe('MODEL_SUPPORTED_REASONING_EFFORT for Claude 4.6', () => {
|
||||
it('should have correct effort levels for claude46', () => {
|
||||
expect(MODEL_SUPPORTED_REASONING_EFFORT.claude46).toEqual(['low', 'medium', 'high', 'xhigh'])
|
||||
})
|
||||
})
|
||||
|
||||
describe('getModelSupportedReasoningEffortOptions for Opus 4.6', () => {
|
||||
describe('getModelSupportedReasoningEffortOptions for Claude 4.6', () => {
|
||||
it('should return correct options for Opus 4.6 models', () => {
|
||||
expect(getModelSupportedReasoningEffortOptions(createModel({ id: 'claude-opus-4-6' }))).toEqual([
|
||||
'default',
|
||||
@@ -2409,9 +2410,19 @@ describe('Claude Models', () => {
|
||||
'xhigh'
|
||||
])
|
||||
})
|
||||
it('should return correct options for Sonnet 4.6 models', () => {
|
||||
expect(getModelSupportedReasoningEffortOptions(createModel({ id: 'claude-sonnet-4-6' }))).toEqual([
|
||||
'default',
|
||||
'none',
|
||||
'low',
|
||||
'medium',
|
||||
'high',
|
||||
'xhigh'
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('findTokenLimit for Opus 4.6', () => {
|
||||
describe('findTokenLimit for Claude 4.6', () => {
|
||||
it('should return 128K max tokens for Opus 4.6 models', () => {
|
||||
expect(findTokenLimit('claude-opus-4-6')).toEqual({ min: 1024, max: 128_000 })
|
||||
expect(findTokenLimit('claude-opus-4.6')).toEqual({ min: 1024, max: 128_000 })
|
||||
@@ -2419,6 +2430,12 @@ describe('Claude Models', () => {
|
||||
expect(findTokenLimit('claude-opus-4-6@20251201')).toEqual({ min: 1024, max: 128_000 })
|
||||
})
|
||||
|
||||
it('should return 64K max tokens for Sonnet 4.6 models', () => {
|
||||
expect(findTokenLimit('claude-sonnet-4-6')).toEqual({ min: 1024, max: 64_000 })
|
||||
expect(findTokenLimit('claude-sonnet-4.6')).toEqual({ min: 1024, max: 64_000 })
|
||||
expect(findTokenLimit('anthropic.claude-sonnet-4-6')).toEqual({ min: 1024, max: 64_000 })
|
||||
})
|
||||
|
||||
it('should distinguish Opus 4.6 from other Claude models', () => {
|
||||
// Opus 4.5 should have 64K
|
||||
expect(findTokenLimit('claude-opus-4-5')).toEqual({ min: 1024, max: 64_000 })
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
getModelSupportedVerbosity,
|
||||
groupQwenModels,
|
||||
isAnthropicModel,
|
||||
isClaude46SeriesModel,
|
||||
isGemini3FlashModel,
|
||||
isGemini3ProModel,
|
||||
isGeminiModel,
|
||||
@@ -28,7 +29,6 @@ import {
|
||||
isMaxTemperatureOneModel,
|
||||
isNotSupportSystemMessageModel,
|
||||
isNotSupportTextDeltaModel,
|
||||
isOpus46Model,
|
||||
isSupportedFlexServiceTier,
|
||||
isSupportedModel,
|
||||
isSupportFlexServiceTierModel,
|
||||
@@ -674,58 +674,78 @@ describe('model utils', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('Opus 4.6 Model Detection', () => {
|
||||
describe('isOpus46Model', () => {
|
||||
describe('Claude 4.6 Models Detection', () => {
|
||||
describe('isClaude46SeriesModel', () => {
|
||||
it('detects Opus 4.6 in direct API format', () => {
|
||||
expect(isOpus46Model(createModel({ id: 'claude-opus-4-6' }))).toBe(true)
|
||||
expect(isOpus46Model(createModel({ id: 'claude-opus-4.6' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-opus-4-6' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-opus-4.6' }))).toBe(true)
|
||||
})
|
||||
|
||||
it('detects Opus 4.6 with version suffixes', () => {
|
||||
expect(isOpus46Model(createModel({ id: 'claude-opus-4-6-20251201' }))).toBe(true)
|
||||
expect(isOpus46Model(createModel({ id: 'claude-opus-4.6-20251201' }))).toBe(true)
|
||||
expect(isOpus46Model(createModel({ id: 'claude-opus-4-6-preview' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-opus-4-6-20251201' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-opus-4.6-20251201' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-opus-4-6-preview' }))).toBe(true)
|
||||
})
|
||||
|
||||
it('detects Opus 4.6 in AWS Bedrock format', () => {
|
||||
expect(isOpus46Model(createModel({ id: 'anthropic.claude-opus-4-6-v1' }))).toBe(true)
|
||||
expect(isOpus46Model(createModel({ id: 'anthropic.claude-opus-4-6-v2:0' }))).toBe(true)
|
||||
})
|
||||
|
||||
it('detects Opus 4.6 in GCP Vertex AI format', () => {
|
||||
expect(isOpus46Model(createModel({ id: 'claude-opus-4-6@20251201' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'anthropic.claude-opus-4-6-v1' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'anthropic.claude-opus-4-6-v2:0' }))).toBe(true)
|
||||
})
|
||||
|
||||
it('detects Opus 4.6 with provider prefix', () => {
|
||||
expect(isOpus46Model(createModel({ id: 'anthropic/claude-opus-4-6' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'anthropic/claude-opus-4-6' }))).toBe(true)
|
||||
})
|
||||
|
||||
it('handles case insensitivity', () => {
|
||||
expect(isOpus46Model(createModel({ id: 'CLAUDE-OPUS-4-6' }))).toBe(true)
|
||||
expect(isOpus46Model(createModel({ id: 'Claude-Opus-4.6' }))).toBe(true)
|
||||
expect(isOpus46Model(createModel({ id: 'Anthropic.Claude-Opus-4-6-V1' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'CLAUDE-OPUS-4-6' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'Claude-Opus-4.6' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'Anthropic.Claude-Opus-4-6-V1' }))).toBe(true)
|
||||
})
|
||||
|
||||
it('returns false for other Claude models', () => {
|
||||
expect(isOpus46Model(createModel({ id: 'claude-opus-4-5' }))).toBe(false)
|
||||
expect(isOpus46Model(createModel({ id: 'claude-opus-4.5' }))).toBe(false)
|
||||
expect(isOpus46Model(createModel({ id: 'claude-opus-4' }))).toBe(false)
|
||||
expect(isOpus46Model(createModel({ id: 'claude-opus-4-0' }))).toBe(false)
|
||||
expect(isOpus46Model(createModel({ id: 'claude-opus-4-1' }))).toBe(false)
|
||||
expect(isOpus46Model(createModel({ id: 'claude-sonnet-4-6' }))).toBe(false)
|
||||
expect(isOpus46Model(createModel({ id: 'claude-3-opus' }))).toBe(false)
|
||||
expect(isOpus46Model(createModel({ id: 'claude-3.5-sonnet' }))).toBe(false)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-opus-4-5' }))).toBe(false)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-opus-4.5' }))).toBe(false)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-opus-4' }))).toBe(false)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-opus-4-0' }))).toBe(false)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-opus-4-1' }))).toBe(false)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-3-opus' }))).toBe(false)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-3.5-sonnet' }))).toBe(false)
|
||||
})
|
||||
|
||||
it('detects Sonnet 4.6 in direct API format', () => {
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-sonnet-4-6' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-sonnet-4.6' }))).toBe(true)
|
||||
})
|
||||
|
||||
it('detects Sonnet 4.6 with version suffixes', () => {
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-sonnet-4-6-20251201' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-sonnet-4.6-20251201' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'claude-sonnet-4-6-preview' }))).toBe(true)
|
||||
})
|
||||
|
||||
it('detects Sonnet 4.6 in AWS Bedrock format', () => {
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'anthropic.claude-sonnet-4-6' }))).toBe(true)
|
||||
})
|
||||
|
||||
it('detects Sonnet 4.6 with provider prefix', () => {
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'anthropic/claude-sonnet-4-6' }))).toBe(true)
|
||||
})
|
||||
|
||||
it('handles case insensitivity for Sonnet', () => {
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'CLAUDE-SONNET-4-6' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'Claude-Sonnet-4.6' }))).toBe(true)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'Anthropic.Claude-Sonnet-4-6-V1' }))).toBe(true)
|
||||
})
|
||||
|
||||
it('returns false for non-Claude models', () => {
|
||||
expect(isOpus46Model(createModel({ id: 'gpt-4o' }))).toBe(false)
|
||||
expect(isOpus46Model(createModel({ id: 'gemini-pro' }))).toBe(false)
|
||||
expect(isOpus46Model(createModel({ id: 'qwen-max' }))).toBe(false)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'gpt-4o' }))).toBe(false)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'gemini-pro' }))).toBe(false)
|
||||
expect(isClaude46SeriesModel(createModel({ id: 'qwen-max' }))).toBe(false)
|
||||
})
|
||||
|
||||
it('returns false for undefined and null', () => {
|
||||
expect(isOpus46Model(undefined as unknown as Model)).toBe(false)
|
||||
expect(isOpus46Model(null as unknown as Model)).toBe(false)
|
||||
expect(isClaude46SeriesModel(undefined as unknown as Model)).toBe(false)
|
||||
expect(isClaude46SeriesModel(null as unknown as Model)).toBe(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -379,6 +379,12 @@ export const SYSTEM_MODELS: Record<SystemProviderId | 'defaultModel', Model[]> =
|
||||
name: 'Claude Opus 4.6',
|
||||
group: 'Claude 4.6'
|
||||
},
|
||||
{
|
||||
id: 'claude-sonnet-4-6',
|
||||
provider: 'anthropic',
|
||||
name: 'Claude Sonnet 4.6',
|
||||
group: 'Claude 4.6'
|
||||
},
|
||||
{
|
||||
id: 'claude-sonnet-4-5',
|
||||
provider: 'anthropic',
|
||||
|
||||
@@ -22,10 +22,10 @@ import {
|
||||
} from './openai'
|
||||
import {
|
||||
GEMINI_FLASH_MODEL_REGEX,
|
||||
isClaude46SeriesModel,
|
||||
isGemini3FlashModel,
|
||||
isGemini3ProModel,
|
||||
isKimi25Model,
|
||||
isOpus46Model,
|
||||
withModelIdAndNameAsId
|
||||
} from './utils'
|
||||
import { isTextToImageModel } from './vision'
|
||||
@@ -66,8 +66,8 @@ export const MODEL_SUPPORTED_REASONING_EFFORT = {
|
||||
perplexity: ['low', 'medium', 'high'] as const,
|
||||
deepseek_hybrid: ['auto'] as const,
|
||||
kimi_k2_5: ['none', 'auto'] as const,
|
||||
// Opus 4.6 supports low, medium, high, xhigh (xhigh is mapped to max in API)
|
||||
opus46: ['low', 'medium', 'high', 'xhigh'] as const
|
||||
// Claude 4.6 supports low, medium, high, xhigh (xhigh is mapped to max in API)
|
||||
claude46: ['low', 'medium', 'high', 'xhigh'] as const
|
||||
} as const satisfies ReasoningEffortConfig
|
||||
|
||||
// Model type to supported options mapping
|
||||
@@ -101,7 +101,7 @@ export const MODEL_SUPPORTED_OPTIONS: ThinkingOptionConfig = {
|
||||
perplexity: ['default', ...MODEL_SUPPORTED_REASONING_EFFORT.perplexity] as const,
|
||||
deepseek_hybrid: ['default', 'none', ...MODEL_SUPPORTED_REASONING_EFFORT.deepseek_hybrid] as const,
|
||||
kimi_k2_5: ['default', ...MODEL_SUPPORTED_REASONING_EFFORT.kimi_k2_5] as const,
|
||||
opus46: ['default', 'none', ...MODEL_SUPPORTED_REASONING_EFFORT.opus46] as const
|
||||
claude46: ['default', 'none', ...MODEL_SUPPORTED_REASONING_EFFORT.claude46] as const
|
||||
} as const
|
||||
|
||||
// TODO: add ut
|
||||
@@ -176,8 +176,8 @@ const _getThinkModelType = (model: Model): ThinkingModelType => {
|
||||
thinkingModelType = 'mimo'
|
||||
} else if (isSupportedThinkingTokenKimiModel(model)) {
|
||||
thinkingModelType = 'kimi_k2_5'
|
||||
} else if (isOpus46Model(model)) {
|
||||
thinkingModelType = 'opus46'
|
||||
} else if (isClaude46SeriesModel(model)) {
|
||||
thinkingModelType = 'claude46'
|
||||
}
|
||||
return thinkingModelType
|
||||
}
|
||||
@@ -765,9 +765,13 @@ const THINKING_TOKEN_MAP: Record<string, { min: number; max: number }> = {
|
||||
// Claude models (supports AWS Bedrock 'anthropic.' prefix, GCP Vertex AI '@' separator, and '-v1:0' suffix)
|
||||
// Opus 4.6 supports 128K output tokens
|
||||
'(?:anthropic\\.)?claude-opus-4[.-]6(?:[@\\-:][\\w\\-:]+)?$': { min: 1024, max: 128_000 },
|
||||
'(?:anthropic\\.)?claude-3[.-]7.*sonnet.*(?:-v\\d+:\\d+)?$': { min: 1024, max: 64_000 },
|
||||
// Sonnet 4.6, and Haiku is assumed to be also 64k
|
||||
'(?:anthropic\\.)?claude-(:?sonnet|haiku)-4[.-]6.*(?:-v\\d+:\\d+)?$': { min: 1024, max: 64_000 },
|
||||
// 4.5 series
|
||||
'(?:anthropic\\.)?claude-(:?haiku|sonnet|opus)-4[.-]5.*(?:-v\\d+:\\d+)?$': { min: 1024, max: 64_000 },
|
||||
// Opus 4.1
|
||||
'(?:anthropic\\.)?claude-opus-4[.-]1.*(?:-v\\d+:\\d+)?$': { min: 1024, max: 32_000 },
|
||||
// 4.0 series
|
||||
'(?:anthropic\\.)?claude-sonnet-4(?:[.-]0)?(?:[@-](?:\\d{4,}|[a-z][\\w-]*))?(?:-v\\d+:\\d+)?$': {
|
||||
min: 1024,
|
||||
max: 64_000
|
||||
@@ -776,6 +780,8 @@ const THINKING_TOKEN_MAP: Record<string, { min: number; max: number }> = {
|
||||
min: 1024,
|
||||
max: 32_000
|
||||
},
|
||||
// 3.7
|
||||
'(?:anthropic\\.)?claude-3[.-]7.*sonnet.*(?:-v\\d+:\\d+)?$': { min: 1024, max: 64_000 },
|
||||
|
||||
// Baichuan models
|
||||
'baichuan-m2$': { min: 0, max: 30_000 },
|
||||
|
||||
@@ -341,9 +341,9 @@ export const isGemini3ProModel = (model: Model | undefined | null): boolean => {
|
||||
* - AWS Bedrock: anthropic.claude-opus-4-6-v1
|
||||
* - GCP Vertex AI: claude-opus-4-6
|
||||
* @param model - The model to check
|
||||
* @returns true if the model is Claude Opus 4.6
|
||||
* @returns true if the model is Claude 4.6 series model
|
||||
*/
|
||||
export function isOpus46Model(model: Model | undefined | null): boolean {
|
||||
export function isClaude46SeriesModel(model: Model | undefined | null): boolean {
|
||||
if (!model) {
|
||||
return false
|
||||
}
|
||||
@@ -352,6 +352,6 @@ export function isOpus46Model(model: Model | undefined | null): boolean {
|
||||
// - Direct API: claude-opus-4-6, claude-opus-4.6
|
||||
// - AWS Bedrock: anthropic.claude-opus-4-6-v1
|
||||
// - GCP Vertex AI: claude-opus-4-6
|
||||
const regex = /(?:anthropic\.)?claude-opus-4[.-]6(?:[@\-:][\w\-:]+)?$/i
|
||||
const regex = /(?:anthropic\.)?claude-(?:opus|sonnet)-4[.-]6(?:[@\-:][\w\-:]+)?$/i
|
||||
return regex.test(modelId)
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ const ThinkModelTypes = [
|
||||
'perplexity',
|
||||
'deepseek_hybrid',
|
||||
'kimi_k2_5',
|
||||
'opus46'
|
||||
'claude46'
|
||||
] as const
|
||||
|
||||
/** If the model's reasoning effort could be controlled, or its reasoning behavior could be turned on/off.
|
||||
|
||||
Reference in New Issue
Block a user