mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-04-25 19:47:47 +00:00
fix(claude): refresh cached fingerprint after baseline upgrades
This commit is contained in:
@@ -179,6 +179,19 @@ func pinClaudeDeviceProfilePlatform(profile, baseline claudeDeviceProfile) claud
|
|||||||
return profile
|
return profile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// normalizeClaudeDeviceProfile keeps stabilized profiles pinned to the current
|
||||||
|
// baseline platform and enforces the baseline software fingerprint as a floor.
|
||||||
|
func normalizeClaudeDeviceProfile(profile, baseline claudeDeviceProfile) claudeDeviceProfile {
|
||||||
|
profile = pinClaudeDeviceProfilePlatform(profile, baseline)
|
||||||
|
if profile.UserAgent == "" || profile.Version == (claudeCLIVersion{}) || shouldUpgradeClaudeDeviceProfile(baseline, profile) {
|
||||||
|
profile.UserAgent = baseline.UserAgent
|
||||||
|
profile.PackageVersion = baseline.PackageVersion
|
||||||
|
profile.RuntimeVersion = baseline.RuntimeVersion
|
||||||
|
profile.Version = baseline.Version
|
||||||
|
}
|
||||||
|
return profile
|
||||||
|
}
|
||||||
|
|
||||||
func extractClaudeDeviceProfile(headers http.Header, cfg *config.Config) (claudeDeviceProfile, bool) {
|
func extractClaudeDeviceProfile(headers http.Header, cfg *config.Config) (claudeDeviceProfile, bool) {
|
||||||
if headers == nil {
|
if headers == nil {
|
||||||
return claudeDeviceProfile{}, false
|
return claudeDeviceProfile{}, false
|
||||||
@@ -277,7 +290,7 @@ func resolveClaudeDeviceProfile(auth *cliproxyauth.Auth, apiKey string, headers
|
|||||||
entry, hasCached = claudeDeviceProfileCache[cacheKey]
|
entry, hasCached = claudeDeviceProfileCache[cacheKey]
|
||||||
cachedValid = hasCached && entry.expire.After(now) && entry.profile.UserAgent != ""
|
cachedValid = hasCached && entry.expire.After(now) && entry.profile.UserAgent != ""
|
||||||
if cachedValid {
|
if cachedValid {
|
||||||
entry.profile = pinClaudeDeviceProfilePlatform(entry.profile, baseline)
|
entry.profile = normalizeClaudeDeviceProfile(entry.profile, baseline)
|
||||||
}
|
}
|
||||||
if cachedValid && !shouldUpgradeClaudeDeviceProfile(candidate, entry.profile) {
|
if cachedValid && !shouldUpgradeClaudeDeviceProfile(candidate, entry.profile) {
|
||||||
entry.expire = now.Add(claudeDeviceProfileTTL)
|
entry.expire = now.Add(claudeDeviceProfileTTL)
|
||||||
@@ -298,7 +311,7 @@ func resolveClaudeDeviceProfile(auth *cliproxyauth.Auth, apiKey string, headers
|
|||||||
claudeDeviceProfileCacheMu.Lock()
|
claudeDeviceProfileCacheMu.Lock()
|
||||||
entry = claudeDeviceProfileCache[cacheKey]
|
entry = claudeDeviceProfileCache[cacheKey]
|
||||||
if entry.expire.After(now) && entry.profile.UserAgent != "" {
|
if entry.expire.After(now) && entry.profile.UserAgent != "" {
|
||||||
entry.profile = pinClaudeDeviceProfilePlatform(entry.profile, baseline)
|
entry.profile = normalizeClaudeDeviceProfile(entry.profile, baseline)
|
||||||
entry.expire = now.Add(claudeDeviceProfileTTL)
|
entry.expire = now.Add(claudeDeviceProfileTTL)
|
||||||
claudeDeviceProfileCache[cacheKey] = entry
|
claudeDeviceProfileCache[cacheKey] = entry
|
||||||
claudeDeviceProfileCacheMu.Unlock()
|
claudeDeviceProfileCacheMu.Unlock()
|
||||||
|
|||||||
@@ -208,6 +208,58 @@ func TestApplyClaudeHeaders_DoesNotDowngradeConfiguredBaselineOnFirstClaudeClien
|
|||||||
assertClaudeFingerprint(t, newerClaudeReq.Header, "claude-cli/2.1.71 (external, cli)", "0.81.0", "v24.6.0", "MacOS", "arm64")
|
assertClaudeFingerprint(t, newerClaudeReq.Header, "claude-cli/2.1.71 (external, cli)", "0.81.0", "v24.6.0", "MacOS", "arm64")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApplyClaudeHeaders_UpgradesCachedSoftwareFingerprintWhenBaselineAdvances(t *testing.T) {
|
||||||
|
resetClaudeDeviceProfileCache()
|
||||||
|
stabilize := true
|
||||||
|
|
||||||
|
oldCfg := &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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
newCfg := &config.Config{
|
||||||
|
ClaudeHeaderDefaults: config.ClaudeHeaderDefaults{
|
||||||
|
UserAgent: "claude-cli/2.1.77 (external, cli)",
|
||||||
|
PackageVersion: "0.87.0",
|
||||||
|
RuntimeVersion: "v24.8.0",
|
||||||
|
OS: "MacOS",
|
||||||
|
Arch: "arm64",
|
||||||
|
StabilizeDeviceProfile: &stabilize,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
auth := &cliproxyauth.Auth{
|
||||||
|
ID: "auth-baseline-reload",
|
||||||
|
Attributes: map[string]string{
|
||||||
|
"api_key": "key-baseline-reload",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
officialReq := 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(officialReq, auth, "key-baseline-reload", false, nil, oldCfg)
|
||||||
|
assertClaudeFingerprint(t, officialReq.Header, "claude-cli/2.1.71 (external, cli)", "0.81.0", "v24.6.0", "MacOS", "arm64")
|
||||||
|
|
||||||
|
thirdPartyReq := newClaudeHeaderTestRequest(t, http.Header{
|
||||||
|
"User-Agent": []string{"curl/8.7.1"},
|
||||||
|
"X-Stainless-Package-Version": []string{"0.10.0"},
|
||||||
|
"X-Stainless-Runtime-Version": []string{"v18.0.0"},
|
||||||
|
"X-Stainless-Os": []string{"Linux"},
|
||||||
|
"X-Stainless-Arch": []string{"x64"},
|
||||||
|
})
|
||||||
|
applyClaudeHeaders(thirdPartyReq, auth, "key-baseline-reload", false, nil, newCfg)
|
||||||
|
assertClaudeFingerprint(t, thirdPartyReq.Header, "claude-cli/2.1.77 (external, cli)", "0.87.0", "v24.8.0", "MacOS", "arm64")
|
||||||
|
}
|
||||||
|
|
||||||
func TestResolveClaudeDeviceProfile_RechecksCacheBeforeStoringCandidate(t *testing.T) {
|
func TestResolveClaudeDeviceProfile_RechecksCacheBeforeStoringCandidate(t *testing.T) {
|
||||||
resetClaudeDeviceProfileCache()
|
resetClaudeDeviceProfileCache()
|
||||||
stabilize := true
|
stabilize := true
|
||||||
|
|||||||
Reference in New Issue
Block a user