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 != "" }