package xai import ( "net/http" "os" "strings" "golang.org/x/mod/semver" ) // Fixed Grok Build / CLI-chat-proxy client identity. // These values are intentionally pinned in-binary (not scraped from live CLI). // Operators may bump the version via XAI_GROK_CLI_VERSION without a release. const ( // CLIProxyHost is the hostname that requires the official CLI identity headers. CLIProxyHost = "cli-chat-proxy.grok.com" // CLIStableVersion is the known-good minimum client version accepted by cli-chat-proxy. CLIStableVersion = "0.2.93" // CLIVersionEnv is the optional operator override for CLIStableVersion. CLIVersionEnv = "XAI_GROK_CLI_VERSION" // CLITokenAuth is required by cli-chat-proxy for Grok Build OAuth tokens. CLITokenAuth = "xai-grok-cli" // CLIClientIdentifier is the x-grok-client-identifier value used by Grok shell/CLI. CLIClientIdentifier = "grok-shell" // CLIClientMode is used by billing / quota probes on the CLI surface. CLIClientMode = "cli" ) // ResolveCLIVersion returns a supported CLI client version. // Empty or invalid overrides fall back to CLIClientVersion (the pinned // preferred client pin in billing.go). CLIStableVersion is only the minimum // accepted by IsSupportedCLIVersion, not the default identity we advertise. func ResolveCLIVersion() string { version := strings.TrimSpace(os.Getenv(CLIVersionEnv)) if !IsSupportedCLIVersion(version) { return CLIClientVersion } return version } // IsSupportedCLIVersion reports whether version is a valid semver string at or // above CLIStableVersion (prereleases below a higher release are rejected when // they compare less than the stable pin). func IsSupportedCLIVersion(version string) bool { canonical := "v" + version minimum := "v" + CLIStableVersion return semver.IsValid(canonical) && semver.Canonical(canonical) == canonical && semver.Compare(canonical, minimum) >= 0 } // CLIUserAgent builds the workspace-style User-Agent for a CLI client version. func CLIUserAgent(version string) string { if strings.TrimSpace(version) == "" { version = CLIClientVersion } return "xai-grok-workspace/" + version } // ApplyCLIProxyHeaders stamps the fixed Grok CLI identity when the request // targets cli-chat-proxy. Direct api.x.ai traffic is left unchanged. func ApplyCLIProxyHeaders(req *http.Request) { if req == nil || req.URL == nil || !strings.EqualFold(strings.TrimSpace(req.URL.Hostname()), CLIProxyHost) { return } if req.Header == nil { req.Header = make(http.Header) } version := ResolveCLIVersion() req.Header.Set("X-XAI-Token-Auth", CLITokenAuth) req.Header.Set("x-grok-client-version", version) req.Header.Set("x-grok-client-identifier", CLIClientIdentifier) req.Header.Set("User-Agent", CLIUserAgent(version)) }