opencode-cursor-agent/internal/converter/modelmap.go

143 lines
5.7 KiB
Go

package converter
import "strings"
// Short-name aliases → actual Cursor model IDs.
// Allows users to configure friendly names in OpenCode instead of memorising
// exact Cursor IDs like "claude-4.6-sonnet-medium".
var shortAlias = map[string]string{
// Claude 4.7
"opus-4.7": "claude-opus-4-7-high",
"opus-4.7-thinking": "claude-opus-4-7-thinking-high",
"opus-4.7-low": "claude-opus-4-7-low",
"opus-4.7-medium": "claude-opus-4-7-medium",
"opus-4.7-high": "claude-opus-4-7-high",
"opus-4.7-xhigh": "claude-opus-4-7-xhigh",
"opus-4.7-max": "claude-opus-4-7-max",
// Claude 4.6
"sonnet-4.6": "claude-4.6-sonnet-medium",
"sonnet-4.6-thinking": "claude-4.6-sonnet-medium-thinking",
"opus-4.6": "claude-4.6-opus-high",
"opus-4.6-thinking": "claude-4.6-opus-high-thinking",
"opus-4.6-max": "claude-4.6-opus-max",
// Claude 4.5
"sonnet-4.5": "claude-4.5-sonnet",
"sonnet-4.5-thinking": "claude-4.5-sonnet-thinking",
"opus-4.5": "claude-4.5-opus-high",
"opus-4.5-thinking": "claude-4.5-opus-high-thinking",
// Claude 4
"sonnet-4": "claude-4-sonnet",
"sonnet-4-thinking": "claude-4-sonnet-thinking",
// Anthropic API-style names → Cursor IDs
// Claude 4.7
"claude-opus-4-7": "claude-opus-4-7-high",
"claude-opus-4.7": "claude-opus-4-7-high",
"claude-opus-4-7-thinking": "claude-opus-4-7-thinking-high",
"claude-opus-4.7-thinking": "claude-opus-4-7-thinking-high",
// Claude 4.6
"claude-opus-4-6": "claude-4.6-opus-high",
"claude-opus-4.6": "claude-4.6-opus-high",
"claude-sonnet-4-6": "claude-4.6-sonnet-medium",
"claude-sonnet-4.6": "claude-4.6-sonnet-medium",
"claude-opus-4-6-thinking": "claude-4.6-opus-high-thinking",
"claude-sonnet-4-6-thinking": "claude-4.6-sonnet-medium-thinking",
// Claude 4.5
"claude-opus-4-5": "claude-4.5-opus-high",
"claude-opus-4.5": "claude-4.5-opus-high",
"claude-sonnet-4-5": "claude-4.5-sonnet",
"claude-sonnet-4.5": "claude-4.5-sonnet",
"claude-opus-4-5-thinking": "claude-4.5-opus-high-thinking",
"claude-sonnet-4-5-thinking": "claude-4.5-sonnet-thinking",
// Claude 4
"claude-sonnet-4": "claude-4-sonnet",
"claude-sonnet-4-thinking": "claude-4-sonnet-thinking",
// Old Anthropic date-based names
"claude-sonnet-4-20250514": "claude-4-sonnet",
"claude-opus-4-20250514": "claude-4.5-opus-high",
// GPT shortcuts
"gpt-5.4": "gpt-5.4-medium",
"gpt-5.4-fast": "gpt-5.4-medium-fast",
// Gemini
"gemini-3.1": "gemini-3.1-pro",
}
// ResolveToCursorModel maps a user-supplied model name to its Cursor model ID.
// If the name is already a valid Cursor ID, it passes through unchanged.
func ResolveToCursorModel(requested string) string {
if requested == "" {
return ""
}
key := strings.ToLower(strings.TrimSpace(requested))
if mapped, ok := shortAlias[key]; ok {
return mapped
}
return requested
}
type aliasEntry struct {
CursorID string
AliasID string
Name string
}
var reverseAliases = []aliasEntry{
// Claude 4.7 — Cursor uses "claude-opus-4-7-*" natively, add friendly aliases
{"claude-opus-4-7-low", "claude-opus-4.7-low", "Claude Opus 4.7 (Low)"},
{"claude-opus-4-7-medium", "claude-opus-4.7-medium", "Claude Opus 4.7 (Medium)"},
{"claude-opus-4-7-high", "claude-opus-4.7-high", "Claude Opus 4.7"},
{"claude-opus-4-7-xhigh", "claude-opus-4.7-xhigh", "Claude Opus 4.7 (XHigh)"},
{"claude-opus-4-7-max", "claude-opus-4.7-max", "Claude Opus 4.7 (Max)"},
{"claude-opus-4-7-thinking-low", "claude-opus-4.7-thinking-low", "Claude Opus 4.7 Thinking (Low)"},
{"claude-opus-4-7-thinking-medium", "claude-opus-4.7-thinking-medium", "Claude Opus 4.7 Thinking (Medium)"},
{"claude-opus-4-7-thinking-high", "claude-opus-4.7-thinking-high", "Claude Opus 4.7 Thinking"},
{"claude-opus-4-7-thinking-xhigh", "claude-opus-4.7-thinking-xhigh", "Claude Opus 4.7 Thinking (XHigh)"},
{"claude-opus-4-7-thinking-max", "claude-opus-4.7-thinking-max", "Claude Opus 4.7 Thinking (Max)"},
// Claude 4.6
{"claude-4.6-opus-high", "claude-opus-4-6", "Claude Opus 4.6"},
{"claude-4.6-opus-high-thinking", "claude-opus-4-6-thinking", "Claude Opus 4.6 (Thinking)"},
{"claude-4.6-opus-max", "claude-opus-4-6-max", "Claude Opus 4.6 (Max)"},
{"claude-4.6-opus-max-thinking", "claude-opus-4-6-max-thinking", "Claude Opus 4.6 Max (Thinking)"},
{"claude-4.6-sonnet-medium", "claude-sonnet-4-6", "Claude Sonnet 4.6"},
{"claude-4.6-sonnet-medium-thinking", "claude-sonnet-4-6-thinking", "Claude Sonnet 4.6 (Thinking)"},
// Claude 4.5
{"claude-4.5-opus-high", "claude-opus-4-5", "Claude Opus 4.5"},
{"claude-4.5-opus-high-thinking", "claude-opus-4-5-thinking", "Claude Opus 4.5 (Thinking)"},
{"claude-4.5-sonnet", "claude-sonnet-4-5", "Claude Sonnet 4.5"},
{"claude-4.5-sonnet-thinking", "claude-sonnet-4-5-thinking", "Claude Sonnet 4.5 (Thinking)"},
// Claude 4
{"claude-4-sonnet", "claude-sonnet-4", "Claude Sonnet 4"},
{"claude-4-sonnet-thinking", "claude-sonnet-4-thinking", "Claude Sonnet 4 (Thinking)"},
}
// GetAnthropicModelAliases returns alias entries for models available in Cursor,
// so that /v1/models shows both Cursor IDs and friendly Anthropic-style names.
func GetAnthropicModelAliases(availableCursorIDs []string) []struct {
ID string
Name string
} {
set := make(map[string]bool, len(availableCursorIDs))
for _, id := range availableCursorIDs {
set[id] = true
}
var result []struct {
ID string
Name string
}
for _, a := range reverseAliases {
if set[a.CursorID] {
result = append(result, struct {
ID string
Name string
}{ID: a.AliasID, Name: a.Name})
}
}
return result
}