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

110 lines
3.8 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.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
"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-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-sonnet-4": "claude-4-sonnet",
"claude-opus-4-6-thinking": "claude-4.6-opus-high-thinking",
"claude-sonnet-4-6-thinking": "claude-4.6-sonnet-medium-thinking",
"claude-opus-4-5-thinking": "claude-4.5-opus-high-thinking",
"claude-sonnet-4-5-thinking": "claude-4.5-sonnet-thinking",
"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.6-opus-high", "claude-opus-4-6", "Claude 4.6 Opus"},
{"claude-4.6-opus-high-thinking", "claude-opus-4-6-thinking", "Claude 4.6 Opus (Thinking)"},
{"claude-4.6-sonnet-medium", "claude-sonnet-4-6", "Claude 4.6 Sonnet"},
{"claude-4.6-sonnet-medium-thinking", "claude-sonnet-4-6-thinking", "Claude 4.6 Sonnet (Thinking)"},
{"claude-4.5-opus-high", "claude-opus-4-5", "Claude 4.5 Opus"},
{"claude-4.5-opus-high-thinking", "claude-opus-4-5-thinking", "Claude 4.5 Opus (Thinking)"},
{"claude-4.5-sonnet", "claude-sonnet-4-5", "Claude 4.5 Sonnet"},
{"claude-4.5-sonnet-thinking", "claude-sonnet-4-5-thinking", "Claude 4.5 Sonnet (Thinking)"},
{"claude-4-sonnet", "claude-sonnet-4", "Claude 4 Sonnet"},
{"claude-4-sonnet-thinking", "claude-sonnet-4-thinking", "Claude 4 Sonnet (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
}