opencode-cursor-agent/internal/models/cursormap.go

124 lines
3.7 KiB
Go
Raw Normal View History

2026-03-30 14:09:15 +00:00
package models
2026-04-01 00:53:34 +00:00
import (
"regexp"
"strings"
)
2026-03-30 14:09:15 +00:00
var anthropicToCursor = map[string]string{
2026-04-01 00:53:34 +00:00
"claude-opus-4-6": "opus-4.6",
"claude-opus-4.6": "opus-4.6",
"claude-sonnet-4-6": "sonnet-4.6",
"claude-sonnet-4.6": "sonnet-4.6",
"claude-opus-4-5": "opus-4.5",
"claude-opus-4.5": "opus-4.5",
"claude-sonnet-4-5": "sonnet-4.5",
"claude-sonnet-4.5": "sonnet-4.5",
"claude-opus-4": "opus-4.6",
"claude-sonnet-4": "sonnet-4.6",
"claude-haiku-4-5-20251001": "sonnet-4.5",
"claude-haiku-4-5": "sonnet-4.5",
"claude-haiku-4-6": "sonnet-4.6",
"claude-haiku-4": "sonnet-4.5",
"claude-opus-4-6-thinking": "opus-4.6-thinking",
"claude-sonnet-4-6-thinking": "sonnet-4.6-thinking",
"claude-opus-4-5-thinking": "opus-4.5-thinking",
"claude-sonnet-4-5-thinking": "sonnet-4.5-thinking",
2026-03-30 14:09:15 +00:00
}
type ModelAlias struct {
CursorID string
AnthropicID string
Name string
}
var cursorToAnthropicAlias = []ModelAlias{
{"opus-4.6", "claude-opus-4-6", "Claude 4.6 Opus"},
{"opus-4.6-thinking", "claude-opus-4-6-thinking", "Claude 4.6 Opus (Thinking)"},
{"sonnet-4.6", "claude-sonnet-4-6", "Claude 4.6 Sonnet"},
{"sonnet-4.6-thinking", "claude-sonnet-4-6-thinking", "Claude 4.6 Sonnet (Thinking)"},
{"opus-4.5", "claude-opus-4-5", "Claude 4.5 Opus"},
{"opus-4.5-thinking", "claude-opus-4-5-thinking", "Claude 4.5 Opus (Thinking)"},
{"sonnet-4.5", "claude-sonnet-4-5", "Claude 4.5 Sonnet"},
{"sonnet-4.5-thinking", "claude-sonnet-4-5-thinking", "Claude 4.5 Sonnet (Thinking)"},
}
2026-04-01 00:53:34 +00:00
// cursorModelPattern matches cursor model IDs like "opus-4.6", "sonnet-4.7-thinking".
var cursorModelPattern = regexp.MustCompile(`^([a-zA-Z]+)-(\d+)\.(\d+)(-thinking)?$`)
// reverseDynamicPattern matches dynamically generated anthropic aliases
// like "claude-opus-4-7", "claude-sonnet-4-7-thinking".
var reverseDynamicPattern = regexp.MustCompile(`^claude-([a-zA-Z]+)-(\d+)-(\d+)(-thinking)?$`)
func generateDynamicAlias(cursorID string) (AnthropicAlias, bool) {
m := cursorModelPattern.FindStringSubmatch(cursorID)
if m == nil {
return AnthropicAlias{}, false
}
family := m[1]
major := m[2]
minor := m[3]
thinking := m[4]
anthropicID := "claude-" + family + "-" + major + "-" + minor + thinking
capFamily := strings.ToUpper(family[:1]) + family[1:]
name := capFamily + " " + major + "." + minor
if thinking == "-thinking" {
name += " (Thinking)"
}
return AnthropicAlias{ID: anthropicID, Name: name}, true
}
func reverseDynamicAlias(anthropicID string) (string, bool) {
m := reverseDynamicPattern.FindStringSubmatch(anthropicID)
if m == nil {
return "", false
}
return m[1] + "-" + m[2] + "." + m[3] + m[4], true
}
2026-03-30 14:09:15 +00:00
func ResolveToCursorModel(requested string) string {
if strings.TrimSpace(requested) == "" {
return ""
}
key := strings.ToLower(strings.TrimSpace(requested))
if v, ok := anthropicToCursor[key]; ok {
return v
}
2026-04-01 00:53:34 +00:00
if v, ok := reverseDynamicAlias(key); ok {
return v
}
2026-03-30 14:09:15 +00:00
return strings.TrimSpace(requested)
}
type AnthropicAlias struct {
ID string
Name string
}
func GetAnthropicModelAliases(availableCursorIDs []string) []AnthropicAlias {
set := make(map[string]bool, len(availableCursorIDs))
for _, id := range availableCursorIDs {
set[id] = true
}
2026-04-01 00:53:34 +00:00
staticSet := make(map[string]bool, len(cursorToAnthropicAlias))
2026-03-30 14:09:15 +00:00
var result []AnthropicAlias
for _, a := range cursorToAnthropicAlias {
if set[a.CursorID] {
2026-04-01 00:53:34 +00:00
staticSet[a.CursorID] = true
2026-03-30 14:09:15 +00:00
result = append(result, AnthropicAlias{ID: a.AnthropicID, Name: a.Name})
}
}
2026-04-01 00:53:34 +00:00
for _, id := range availableCursorIDs {
if staticSet[id] {
continue
}
if alias, ok := generateDynamicAlias(id); ok {
result = append(result, alias)
}
}
2026-03-30 14:09:15 +00:00
return result
}