Files
2026-07-13 12:35:43 +08:00

64 lines
1.9 KiB
Go

package util
import "strings"
// IsClaudeThinkingModel checks if the model is a Claude thinking model
// that requires the interleaved-thinking beta header.
func IsClaudeThinkingModel(model string) bool {
lower := strings.ToLower(model)
return strings.Contains(lower, "claude") && strings.Contains(lower, "thinking")
}
const claudeDDModelPrefix = "claude-fable-5-dd-"
// EnsureClaudeModelIDPrefix rewrites model IDs for Anthropic /models listings.
// IDs that already start with "claude-" are returned unchanged; all other IDs
// become "claude-fable-5-dd-" plus the original ID with its characters reversed.
func EnsureClaudeModelIDPrefix(id string) string {
if id == "" {
return id
}
if strings.HasPrefix(id, "claude-") {
return id
}
return claudeDDModelPrefix + reverseModelID(id)
}
// ResolveClaudeModelIDPrefix reverses EnsureClaudeModelIDPrefix for request routing.
// IDs that start with "claude-fable-5-dd-" are decoded by stripping the prefix and reversing
// the remainder. Optional thinking suffixes in model(value) form are preserved.
func ResolveClaudeModelIDPrefix(id string) string {
if id == "" {
return id
}
base, suffix, hasSuffix := splitModelThinkingSuffix(id)
if !strings.HasPrefix(base, claudeDDModelPrefix) {
return id
}
encoded := base[len(claudeDDModelPrefix):]
if encoded == "" {
return id
}
resolved := reverseModelID(encoded)
if hasSuffix {
return resolved + "(" + suffix + ")"
}
return resolved
}
func splitModelThinkingSuffix(model string) (base, suffix string, hasSuffix bool) {
lastOpen := strings.LastIndex(model, "(")
if lastOpen == -1 || !strings.HasSuffix(model, ")") {
return model, "", false
}
return model[:lastOpen], model[lastOpen+1 : len(model)-1], true
}
func reverseModelID(id string) string {
runes := []rune(id)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}