Files
bifrost/core/schemas/useragents.go
Beyhan Oğur 880f412e2c first commit
2026-04-26 21:52:23 +03:00

73 lines
1.9 KiB
Go

package schemas
import "strings"
// UserAgentIdentifiers lists substrings that may appear in User-Agent for a given integration.
// Versions of the same client may use different strings; Matches checks any of them.
type UserAgentIdentifiers []string
var (
// ClaudeCLI — Anthropic Claude Code / Claude CLI (identifiers vary by release).
ClaudeCLI = UserAgentIdentifiers{"claude-cli", "claude-code", "claude-vscode"}
GeminiCLI = UserAgentIdentifiers{"geminicli"}
CodexCLI = UserAgentIdentifiers{"codex-tui"}
QwenCodeCLI = UserAgentIdentifiers{"qwencode"}
OpenCode = UserAgentIdentifiers{"opencode"}
Cursor = UserAgentIdentifiers{"cursor"}
)
// integrationUserAgents is the set of known client User-Agent patterns we persist on the context.
var integrationUserAgents = []UserAgentIdentifiers{
ClaudeCLI, GeminiCLI, CodexCLI, QwenCodeCLI, OpenCode, Cursor,
}
// Matches reports whether userAgent contains any identifier (case-insensitive substring match).
func (ids UserAgentIdentifiers) Matches(userAgent string) bool {
if len(ids) == 0 || userAgent == "" {
return false
}
ua := strings.ToLower(userAgent)
for _, id := range ids {
if id == "" {
continue
}
if strings.Contains(ua, strings.ToLower(id)) {
return true
}
}
return false
}
// String returns the first identifier for logging and tests that need a canonical sample value.
func (ids UserAgentIdentifiers) String() string {
if len(ids) == 0 {
return ""
}
return ids[0]
}
func ExtractAndSetUserAgentFromHeaders(headers map[string][]string, bifrostCtx *BifrostContext) {
if len(headers) == 0 {
return
}
if bifrostCtx == nil {
return
}
var userAgent []string
for key, value := range headers {
if strings.EqualFold(key, "user-agent") {
userAgent = value
break
}
}
if len(userAgent) > 0 {
ua := userAgent[0]
for _, ids := range integrationUserAgents {
if ids.Matches(ua) {
bifrostCtx.SetValue(BifrostContextKeyUserAgent, ua)
break
}
}
}
}