feat: support Claude Sonnet 5.5

This commit is contained in:
haruka
2026-09-29 04:55:07 +08:00
parent 9a62841fd1
commit 8490a81867
40 changed files with 855 additions and 117 deletions
+6
View File
@@ -190,6 +190,12 @@ var DefaultModels = []Model{
DisplayName: "Claude Opus 5",
CreatedAt: "2026-07-25T00:00:00Z",
},
{
ID: "claude-sonnet-5-5",
Type: "model",
DisplayName: "Claude Sonnet 5.5",
CreatedAt: "2026-09-28T00:00:00Z",
},
{
ID: "claude-sonnet-5",
Type: "model",
@@ -30,3 +30,16 @@ func TestDefaultModelsContainsOpus55(t *testing.T) {
}
t.Fatal("claude-opus-5-5 missing")
}
func TestDefaultModelsContainsSonnet55(t *testing.T) {
t.Parallel()
for _, model := range DefaultModels {
if model.ID == "claude-sonnet-5-5" {
require.Equal(t, "Claude Sonnet 5.5", model.DisplayName)
require.Equal(t, "2026-09-28T00:00:00Z", model.CreatedAt)
return
}
}
t.Fatal("claude-sonnet-5-5 missing from DefaultModels")
}
+14 -2
View File
@@ -19,6 +19,7 @@ var effortFamilies = []struct {
{family: "claude-mythos-5", levels: effortLowMediumHighXHighMax},
{family: "claude-fable-5", levels: effortLowMediumHighXHighMax},
{family: "claude-sonnet-4-6", levels: effortLowMediumHighMax},
{family: "claude-sonnet-5-5", levels: effortLowMediumHighXHighMax},
{family: "claude-sonnet-5", levels: effortLowMediumHighXHighMax},
{family: "claude-opus-4-8", levels: effortLowMediumHighXHighMax},
{family: "claude-opus-4-7", levels: effortLowMediumHighXHighMax},
@@ -45,19 +46,30 @@ func IsOpus55(model string) bool {
return normalizeEffortModelID(model) == "claude-opus-5-5"
}
// IsSonnet55 identifies the fixed Sonnet 5.5 ID after provider/local suffix normalization.
func IsSonnet55(model string) bool {
return normalizeEffortModelID(model) == "claude-sonnet-5-5"
}
func normalizeEffortModelID(model string) string {
id := strings.ToLower(strings.TrimSpace(model))
id = strings.TrimPrefix(id, "models/")
if slash := strings.IndexByte(id, '/'); slash >= 0 {
id = strings.TrimPrefix(strings.TrimSpace(id[slash+1:]), "models/")
}
for _, prefix := range []string{"us.", "eu.", "apac.", "jp.", "au.", "us-gov.", "global."} {
id = strings.TrimPrefix(id, prefix)
}
id = strings.TrimPrefix(id, "anthropic.")
id = strings.TrimSuffix(id, "-thinking")
// OpenRouter uses a dotted minor version for this exact Opus 5.5 ID.
// Normalize it before effort, thinking, and billing family lookups.
// OpenRouter uses dotted minor versions for some models. Normalize them
// before effort, thinking, and billing family lookups.
if id == "claude-opus-5.5" {
id = "claude-opus-5-5"
}
if id == "claude-sonnet-5.5" {
id = "claude-sonnet-5-5"
}
if mapped, ok := ModelIDReverseOverrides[id]; ok {
id = mapped
}
@@ -17,6 +17,8 @@ func TestEffortLevelsForModel(t *testing.T) {
{model: "anthropic/claude-sonnet-4-6", want: []string{"low", "medium", "high", "max"}},
{model: "claude-opus-5", want: []string{"low", "medium", "high", "xhigh", "max"}},
{model: "anthropic/claude-opus-5.5", want: []string{"low", "medium", "high", "xhigh", "max"}},
{model: "claude-sonnet-5-5", want: []string{"low", "medium", "high", "xhigh", "max"}},
{model: "us.anthropic.claude-sonnet-5-5", want: []string{"low", "medium", "high", "xhigh", "max"}},
{model: "claude-opus-4-5-20251101", want: []string{"low", "medium", "high"}},
{model: "claude-haiku-4-5-20251001", want: nil},
{model: "gpt-5.6", want: nil},
@@ -38,3 +40,20 @@ func TestIsOpus55OpenRouterExactAlias(t *testing.T) {
require.False(t, IsOpus55(model), model)
}
}
func TestIsSonnet55(t *testing.T) {
t.Parallel()
for _, model := range []string{
"claude-sonnet-5-5",
"anthropic/claude-sonnet-5.5",
"anthropic.claude-sonnet-5-5",
"us.anthropic.claude-sonnet-5-5",
"us-gov.anthropic.claude-sonnet-5-5",
"global.anthropic.claude-sonnet-5-5-thinking",
} {
require.True(t, IsSonnet55(model), model)
}
for _, model := range []string{"claude-sonnet-5", "claude-sonnet-5-5-preview", "claude-opus-5-5"} {
require.False(t, IsSonnet55(model), model)
}
}