fix(claude): keep configured baseline above older fingerprints

This commit is contained in:
tpob
2026-03-19 01:02:04 +08:00
parent dd64adbeeb
commit 6fa7abe434
2 changed files with 59 additions and 1 deletions

View File

@@ -158,6 +158,19 @@ func parseClaudeCLIVersion(userAgent string) (claudeCLIVersion, bool) {
return claudeCLIVersion{major: major, minor: minor, patch: patch}, true
}
func shouldUpgradeClaudeDeviceProfile(candidate, current claudeDeviceProfile) bool {
if candidate.UserAgent == "" {
return false
}
if current.UserAgent == "" {
return true
}
if current.Version == (claudeCLIVersion{}) {
return false
}
return candidate.Version.Compare(current.Version) > 0
}
func extractClaudeDeviceProfile(headers http.Header, cfg *config.Config) (claudeDeviceProfile, bool) {
if headers == nil {
return claudeDeviceProfile{}, false
@@ -235,13 +248,16 @@ func resolveClaudeDeviceProfile(auth *cliproxyauth.Auth, apiKey string, headers
now := time.Now()
baseline := defaultClaudeDeviceProfile(cfg)
candidate, hasCandidate := extractClaudeDeviceProfile(headers, cfg)
if hasCandidate && !shouldUpgradeClaudeDeviceProfile(candidate, baseline) {
hasCandidate = false
}
claudeDeviceProfileCacheMu.RLock()
entry, hasCached := claudeDeviceProfileCache[cacheKey]
cachedValid := hasCached && entry.expire.After(now) && entry.profile.UserAgent != ""
claudeDeviceProfileCacheMu.RUnlock()
if hasCandidate && (!cachedValid || candidate.Version.Compare(entry.profile.Version) > 0) {
if hasCandidate && (!cachedValid || shouldUpgradeClaudeDeviceProfile(candidate, entry.profile)) {
newEntry := claudeDeviceProfileCacheEntry{
profile: candidate,
expire: now.Add(claudeDeviceProfileTTL),

View File

@@ -164,6 +164,48 @@ func TestApplyClaudeHeaders_TracksHighestClaudeCLIFingerprint(t *testing.T) {
assertClaudeFingerprint(t, lowerReq.Header, "claude-cli/2.1.63 (external, cli)", "0.75.0", "v24.4.0", "MacOS", "arm64")
}
func TestApplyClaudeHeaders_DoesNotDowngradeConfiguredBaselineOnFirstClaudeClient(t *testing.T) {
resetClaudeDeviceProfileCache()
stabilize := true
cfg := &config.Config{
ClaudeHeaderDefaults: config.ClaudeHeaderDefaults{
UserAgent: "claude-cli/2.1.70 (external, cli)",
PackageVersion: "0.80.0",
RuntimeVersion: "v24.5.0",
OS: "MacOS",
Arch: "arm64",
StabilizeDeviceProfile: &stabilize,
},
}
auth := &cliproxyauth.Auth{
ID: "auth-baseline-floor",
Attributes: map[string]string{
"api_key": "key-baseline-floor",
},
}
olderClaudeReq := newClaudeHeaderTestRequest(t, http.Header{
"User-Agent": []string{"claude-cli/2.1.62 (external, cli)"},
"X-Stainless-Package-Version": []string{"0.74.0"},
"X-Stainless-Runtime-Version": []string{"v24.3.0"},
"X-Stainless-Os": []string{"Linux"},
"X-Stainless-Arch": []string{"x64"},
})
applyClaudeHeaders(olderClaudeReq, auth, "key-baseline-floor", false, nil, cfg)
assertClaudeFingerprint(t, olderClaudeReq.Header, "claude-cli/2.1.70 (external, cli)", "0.80.0", "v24.5.0", "MacOS", "arm64")
newerClaudeReq := newClaudeHeaderTestRequest(t, http.Header{
"User-Agent": []string{"claude-cli/2.1.71 (external, cli)"},
"X-Stainless-Package-Version": []string{"0.81.0"},
"X-Stainless-Runtime-Version": []string{"v24.6.0"},
"X-Stainless-Os": []string{"Linux"},
"X-Stainless-Arch": []string{"x64"},
})
applyClaudeHeaders(newerClaudeReq, auth, "key-baseline-floor", false, nil, cfg)
assertClaudeFingerprint(t, newerClaudeReq.Header, "claude-cli/2.1.71 (external, cli)", "0.81.0", "v24.6.0", "Linux", "x64")
}
func TestApplyClaudeHeaders_DisableDeviceProfileStabilization(t *testing.T) {
resetClaudeDeviceProfileCache()