diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f9df029..fbbd5d3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -16,8 +16,8 @@ android { applicationId = "com.rainy.token" minSdk = 31 targetSdk = 35 - versionCode = 31 - versionName = "1.7.11" + versionCode = 32 + versionName = "1.7.12" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginViewModel.kt b/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginViewModel.kt index c946738..c7d13bf 100644 --- a/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginViewModel.kt +++ b/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginViewModel.kt @@ -59,6 +59,12 @@ class WebViewLoginViewModel @Inject constructor( private var workBuddyPollingJob: Job? = null /** WorkBuddy 当前基址(决定 auth state/token 用 CN 还是 INTL)。 */ private var workBuddyBase = "https://copilot.tencent.com" + /** WorkBuddy 伪装头:Origin/Referer/Platform/UA 必须与官方客户端一致。 */ + private var workBuddyOrigin = "https://www.codebuddy.cn" + private var workBuddyPlatform = "VSCode" + private var workBuddyUserAgent = "CLI/2.143.1 CodeBuddy/2.143.1" + /** WorkBuddy 授权等待超时:国内 5 分钟(扫码),INTL 15 分钟(邮箱/验证码/SSO)。 */ + private var workBuddyPollTimeoutMs = 300_000L /** 目标账号(多账号服务);null = 新建账号。 */ private var accountId: String? = null @@ -250,10 +256,26 @@ class WebViewLoginViewModel @Inject constructor( private fun bindWorkBuddy() { viewModelScope.launch { try { - workBuddyBase = if (region == "INTL") "https://www.workbuddy.ai" else "https://copilot.tencent.com" + if (region == "INTL") { + workBuddyBase = "https://www.workbuddy.ai" + workBuddyOrigin = "https://www.workbuddy.ai" + workBuddyPlatform = "workbuddy-ai" + workBuddyPollTimeoutMs = 900_000L + } else { + workBuddyBase = "https://copilot.tencent.com" + workBuddyOrigin = "https://www.codebuddy.cn" + workBuddyPlatform = "VSCode" + workBuddyPollTimeoutMs = 300_000L + } + workBuddyUserAgent = "CLI/2.143.1 CodeBuddy/2.143.1" val request = Request.Builder() - .url(workBuddyBase + "/v2/plugin/auth/state?platform=CLI") - .addHeader("User-Agent", "CLI/2.63.2 CodeBuddy/2.63.2") + .url(workBuddyBase + "/v2/plugin/auth/state?platform=" + workBuddyPlatform) + .addHeader("User-Agent", workBuddyUserAgent) + .addHeader("Origin", workBuddyOrigin) + .addHeader("Referer", workBuddyOrigin + "/") + .addHeader("X-Client-ID", "codebuddy-cli") + .addHeader("X-Client-Version", "2.143.1") + .addHeader("X-Product", "SaaS") .addHeader("Content-Type", "application/json") .post("{}".toRequestBody("application/json".toMediaTypeOrNull())) .build() @@ -290,16 +312,22 @@ class WebViewLoginViewModel @Inject constructor( } } - /** 每 2 秒轮询一次 token 接口,120 秒超时。 */ + /** 每 2 秒轮询一次 token 接口,超时按站点 Profile(CN 5 分钟 / INTL 15 分钟)。 */ private suspend fun pollWorkBuddyToken(state: String) { - val timeoutMs = 120_000L + val timeoutMs = workBuddyPollTimeoutMs val startTime = System.currentTimeMillis() while (System.currentTimeMillis() - startTime < timeoutMs) { if (_uiState.value.loginSucceeded) return try { val request = Request.Builder() .url(workBuddyBase + "/v2/plugin/auth/token?state=$state") - .addHeader("User-Agent", "CLI/2.63.2 CodeBuddy/2.63.2") + .addHeader("User-Agent", workBuddyUserAgent) + .addHeader("Origin", workBuddyOrigin) + .addHeader("Referer", workBuddyOrigin + "/") + .addHeader("X-Client-ID", "codebuddy-cli") + .addHeader("X-Client-Version", "2.143.1") + .addHeader("X-Product", "SaaS") + .addHeader("X-No-Authorization", "1") .get() .build() val body = withContext(Dispatchers.IO) {