package llm
import (
"strings"
"unicode"
)
// PrettyModel turns an API model id into the name a person uses for it:
// claude-opus-5 becomes "Opus 5", claude-haiku-4-5-20251001 becomes
// "Haiku 4.5". An id that does not fit the shape is returned unchanged, which
// matters because this also runs against gateways serving models we have
// never heard of.
func PrettyModel(id string) string {
s := strings.TrimSuffix(strings.TrimPrefix(id, "claude-"), "-latest")
// Anything bracketed is a variant tag, not part of the name: opus-5[1m].
tag := ""
if i := strings.IndexByte(s, '['); i >= 0 {
tag, s = s[i:], s[:i]
}
parts := strings.Split(s, "-")
if len(parts) < 2 {
return id
}
// A trailing eight-digit date stamp is a build, not a version.
if last := parts[len(parts)-1]; len(last) == 8 && allDigits(last) {
parts = parts[:len(parts)-1]
}
family, rest := parts[0], parts[1:]
if family == "" || !isAlpha(family) {
return id
}
name := strings.ToUpper(family[:1]) + family[1:]
var version []string
for _, p := range rest {
if !allDigits(p) {
return id
}
version = append(version, p)
}
if len(version) > 0 {
name += " " + strings.Join(version, ".")
}
return name + tag
}
func allDigits(s string) bool {
if s == "" {
return false
}
for _, r := range s {
if !unicode.IsDigit(r) {
return false
}
}
return true
}
func isAlpha(s string) bool {
for _, r := range s {
if !unicode.IsLetter(r) {
return false
}
}
return s != ""
}