mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-04-26 06:46:09 +00:00
fix(claude): keep configured baseline above older fingerprints
This commit is contained in:
@@ -158,6 +158,19 @@ func parseClaudeCLIVersion(userAgent string) (claudeCLIVersion, bool) {
|
|||||||
return claudeCLIVersion{major: major, minor: minor, patch: patch}, true
|
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) {
|
func extractClaudeDeviceProfile(headers http.Header, cfg *config.Config) (claudeDeviceProfile, bool) {
|
||||||
if headers == nil {
|
if headers == nil {
|
||||||
return claudeDeviceProfile{}, false
|
return claudeDeviceProfile{}, false
|
||||||
@@ -235,13 +248,16 @@ func resolveClaudeDeviceProfile(auth *cliproxyauth.Auth, apiKey string, headers
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
baseline := defaultClaudeDeviceProfile(cfg)
|
baseline := defaultClaudeDeviceProfile(cfg)
|
||||||
candidate, hasCandidate := extractClaudeDeviceProfile(headers, cfg)
|
candidate, hasCandidate := extractClaudeDeviceProfile(headers, cfg)
|
||||||
|
if hasCandidate && !shouldUpgradeClaudeDeviceProfile(candidate, baseline) {
|
||||||
|
hasCandidate = false
|
||||||
|
}
|
||||||
|
|
||||||
claudeDeviceProfileCacheMu.RLock()
|
claudeDeviceProfileCacheMu.RLock()
|
||||||
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 != ""
|
||||||
claudeDeviceProfileCacheMu.RUnlock()
|
claudeDeviceProfileCacheMu.RUnlock()
|
||||||
|
|
||||||
if hasCandidate && (!cachedValid || candidate.Version.Compare(entry.profile.Version) > 0) {
|
if hasCandidate && (!cachedValid || shouldUpgradeClaudeDeviceProfile(candidate, entry.profile)) {
|
||||||
newEntry := claudeDeviceProfileCacheEntry{
|
newEntry := claudeDeviceProfileCacheEntry{
|
||||||
profile: candidate,
|
profile: candidate,
|
||||||
expire: now.Add(claudeDeviceProfileTTL),
|
expire: now.Add(claudeDeviceProfileTTL),
|
||||||
|
|||||||
@@ -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")
|
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) {
|
func TestApplyClaudeHeaders_DisableDeviceProfileStabilization(t *testing.T) {
|
||||||
resetClaudeDeviceProfileCache()
|
resetClaudeDeviceProfileCache()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user