Files
coder/aibridge/client.go
T

68 lines
2.6 KiB
Go

package aibridge
import (
"net/http"
"strings"
)
type Client string
const (
// Possible values for the "client" field in interception records.
// Must be kept in sync with documentation: https://github.com/coder/coder/blob/3cf867f84aa32d2febf7a26dc7e52be6beb8a2ac/docs/ai-coder/ai-gateway/monitoring.md?plain=1#L47-L57
ClientClaudeCode Client = "Claude Code"
ClientCodex Client = "Codex"
ClientZed Client = "Zed"
ClientCopilotVSC Client = "GitHub Copilot (VS Code)"
ClientCopilotCLI Client = "GitHub Copilot (CLI)"
ClientKilo Client = "Kilo Code"
ClientCoderAgents Client = "Coder Agents"
ClientCrush Client = "Charm Crush"
ClientXum Client = "Xum"
ClientRoo Client = "Roo Code"
ClientCursor Client = "Cursor"
ClientOpenCode Client = "OpenCode"
ClientJunie Client = "Junie"
ClientUnknown Client = "Unknown"
)
// GuessClient attempts to guess the client application from the request headers.
// Not all clients set proper user agent headers, so this is a best-effort approach.
// Based on https://github.com/coder/aibridge/issues/20#issuecomment-3769444101.
func GuessClient(r *http.Request) Client {
userAgent := strings.ToLower(r.UserAgent())
originator := r.Header.Get("originator")
// Must be kept in sync with documentation: https://github.com/coder/coder/blob/3cf867f84aa32d2febf7a26dc7e52be6beb8a2ac/docs/ai-coder/ai-gateway/monitoring.md?plain=1#L47-L57
switch {
case strings.HasPrefix(userAgent, "xum/") || strings.HasPrefix(userAgent, "mux/"):
// Mux was renamed to Xum; "mux/" is kept for older, unupgraded clients.
return ClientXum
case strings.HasPrefix(userAgent, "claude"):
return ClientClaudeCode
case strings.HasPrefix(userAgent, "codex"):
return ClientCodex
case strings.HasPrefix(userAgent, "zed/"):
return ClientZed
case strings.HasPrefix(userAgent, "githubcopilotchat/"):
return ClientCopilotVSC
case strings.HasPrefix(userAgent, "copilot/"):
return ClientCopilotCLI
case strings.HasPrefix(userAgent, "kilo-code/") || originator == "kilo-code":
return ClientKilo
case strings.HasPrefix(userAgent, "roo-code/") || originator == "roo-code":
return ClientRoo
case strings.HasPrefix(userAgent, "coder-agents/"):
return ClientCoderAgents
case strings.HasPrefix(userAgent, "charm crush/") || strings.HasPrefix(userAgent, "charm-crush/"):
return ClientCrush
case r.Header.Get("x-cursor-client-version") != "":
return ClientCursor
case strings.HasPrefix(userAgent, "opencode/"):
return ClientOpenCode
case strings.HasPrefix(userAgent, "junie:"):
return ClientJunie
}
return ClientUnknown
}