qwenproxy-cli 1.6.9 → 1.6.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/clean-cache.js +199 -55
- package/dist/delete-chats.js +269 -78
- package/dist/index.js +290 -88
- package/dist/login.js +203 -67
- package/dist/reset-cooldowns.js +199 -55
- package/package.json +2 -2
- package/src/api/server.ts +8 -4
- package/src/core/version.ts +1 -1
- package/src/core/watchdog.ts +4 -3
- package/src/routes/chat/account.ts +12 -0
- package/src/routes/chat/streaming.ts +18 -2
- package/src/services/captcha-coordinator.ts +36 -8
- package/src/services/chat-cleanup.ts +11 -2
- package/src/services/playwright.ts +244 -74
- package/src/services/qwen.ts +29 -3
package/dist/clean-cache.js
CHANGED
|
@@ -2035,6 +2035,26 @@ function clearAccountCooldown(accountId) {
|
|
|
2035
2035
|
}
|
|
2036
2036
|
}
|
|
2037
2037
|
}
|
|
2038
|
+
function getAccountCooldownInfo(accountId) {
|
|
2039
|
+
const entry = cooldowns.get(accountId);
|
|
2040
|
+
if (!entry) return null;
|
|
2041
|
+
const remaining = entry.until - Date.now();
|
|
2042
|
+
if (remaining <= 0) {
|
|
2043
|
+
cooldowns.delete(accountId);
|
|
2044
|
+
if (accountId !== "global") {
|
|
2045
|
+
try {
|
|
2046
|
+
updateAccountCooldown(accountId, 0, null);
|
|
2047
|
+
} catch (err) {
|
|
2048
|
+
console.error(
|
|
2049
|
+
`\u274C [AccountManager] Failed to clear expired cooldown in DB:`,
|
|
2050
|
+
err.message
|
|
2051
|
+
);
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
return null;
|
|
2055
|
+
}
|
|
2056
|
+
return { onCooldown: true, remainingMs: remaining, reason: entry.reason };
|
|
2057
|
+
}
|
|
2038
2058
|
function markAccountHeadersReady(accountId) {
|
|
2039
2059
|
if (!accountId || accountId === "global") return;
|
|
2040
2060
|
headersReadyAccounts.add(accountId);
|
|
@@ -2990,7 +3010,19 @@ async function isPageLoggedIn(page, timeoutMs = SESSION_PROBE_NAVIGATION_TIMEOUT
|
|
|
2990
3010
|
if (localStorage.getItem("qwen_token_logged_out_marker")) {
|
|
2991
3011
|
return false;
|
|
2992
3012
|
}
|
|
2993
|
-
const
|
|
3013
|
+
const lsToken = (localStorage.getItem("token") || "").trim();
|
|
3014
|
+
if (lsToken && !/(?:^|;\s*)token=/.test(document.cookie || "")) {
|
|
3015
|
+
try {
|
|
3016
|
+
document.cookie = `token=${encodeURIComponent(lsToken)}; path=/; domain=.qwen.ai; max-age=31536000`;
|
|
3017
|
+
} catch {
|
|
3018
|
+
}
|
|
3019
|
+
}
|
|
3020
|
+
const authHeaders = lsToken ? { Authorization: `Bearer ${lsToken}` } : {};
|
|
3021
|
+
const res = await fetch("/api/v1/auths/", {
|
|
3022
|
+
method: "GET",
|
|
3023
|
+
headers: authHeaders,
|
|
3024
|
+
credentials: "include"
|
|
3025
|
+
});
|
|
2994
3026
|
if (res.status !== 200) return false;
|
|
2995
3027
|
const json = await res.json().catch(() => null);
|
|
2996
3028
|
if (!json) return false;
|
|
@@ -3008,6 +3040,7 @@ async function isPageLoggedIn(page, timeoutMs = SESSION_PROBE_NAVIGATION_TIMEOUT
|
|
|
3008
3040
|
try {
|
|
3009
3041
|
const settingsRes = await fetch("/api/v2/users/user/settings", {
|
|
3010
3042
|
method: "GET",
|
|
3043
|
+
headers: authHeaders,
|
|
3011
3044
|
credentials: "include",
|
|
3012
3045
|
signal: AbortSignal.timeout(3e3)
|
|
3013
3046
|
});
|
|
@@ -3610,8 +3643,12 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
3610
3643
|
if (accountPages.has(account.id)) {
|
|
3611
3644
|
return;
|
|
3612
3645
|
}
|
|
3613
|
-
|
|
3614
|
-
|
|
3646
|
+
if (config.playwright.maxActiveContexts > 0) {
|
|
3647
|
+
await evictIdlePlaywrightContextsToLimit(
|
|
3648
|
+
Math.max(1, config.playwright.maxActiveContexts - 1)
|
|
3649
|
+
).catch(() => {
|
|
3650
|
+
});
|
|
3651
|
+
}
|
|
3615
3652
|
const profilePath = getAccountProfilePath(account.id);
|
|
3616
3653
|
const fingerprint = getFingerprintProfile(account.id);
|
|
3617
3654
|
const { engine, channel } = resolveBrowserEngine(browserType);
|
|
@@ -3836,8 +3873,15 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
3836
3873
|
const hasAuthCookie = cookies.some(
|
|
3837
3874
|
(c) => c.name.toLowerCase().includes("token") || c.name.toLowerCase().includes("session")
|
|
3838
3875
|
);
|
|
3876
|
+
let initialLoginAttempted = false;
|
|
3839
3877
|
if (!hasAuthCookie && account.email && account.password) {
|
|
3840
|
-
|
|
3878
|
+
initialLoginAttempted = true;
|
|
3879
|
+
const loggedIn = await loginToQwen(account.id, account.email, account.password);
|
|
3880
|
+
if (!loggedIn) {
|
|
3881
|
+
throw new Error(
|
|
3882
|
+
`Authentication failed for account ${maskEmail(account.email)}`
|
|
3883
|
+
);
|
|
3884
|
+
}
|
|
3841
3885
|
}
|
|
3842
3886
|
try {
|
|
3843
3887
|
await acctPage.goto(qwenUrl("/"), {
|
|
@@ -3847,13 +3891,21 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
3847
3891
|
await sleep2(1500);
|
|
3848
3892
|
const currentUrl = acctPage.url();
|
|
3849
3893
|
const isAuthUrl = currentUrl.includes("/auth") || currentUrl.includes("/login");
|
|
3850
|
-
if (isAuthUrl && account.email && account.password) {
|
|
3894
|
+
if (isAuthUrl && !initialLoginAttempted && account.email && account.password) {
|
|
3851
3895
|
console.log(
|
|
3852
3896
|
`[Playwright] Initial login needed for ${maskEmail(account.email)}, authenticating...`
|
|
3853
3897
|
);
|
|
3854
|
-
await loginToQwen(account.id, account.email, account.password);
|
|
3898
|
+
const loggedIn = await loginToQwen(account.id, account.email, account.password);
|
|
3899
|
+
if (!loggedIn) {
|
|
3900
|
+
throw new Error(
|
|
3901
|
+
`Authentication failed for account ${maskEmail(account.email)}`
|
|
3902
|
+
);
|
|
3903
|
+
}
|
|
3855
3904
|
}
|
|
3856
3905
|
} catch (err) {
|
|
3906
|
+
if (err?.message?.includes("Authentication failed for account")) {
|
|
3907
|
+
throw err;
|
|
3908
|
+
}
|
|
3857
3909
|
console.warn(
|
|
3858
3910
|
`\u26A0\uFE0F [Playwright] Initial navigation check for ${maskEmail(account.email)}: ${err.message}`
|
|
3859
3911
|
);
|
|
@@ -3865,7 +3917,7 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
3865
3917
|
if (!acctPage.isClosed()) {
|
|
3866
3918
|
try {
|
|
3867
3919
|
const currentUrl = new URL(acctPage.url());
|
|
3868
|
-
if (currentUrl.origin !== qwenOrigin() || currentUrl.pathname
|
|
3920
|
+
if (currentUrl.origin !== qwenOrigin() || currentUrl.pathname.includes("/auth") || currentUrl.pathname.includes("/login") || currentUrl.pathname.includes("_____tmd_____")) {
|
|
3869
3921
|
await acctPage.goto(qwenUrl("/"), {
|
|
3870
3922
|
waitUntil: "domcontentloaded",
|
|
3871
3923
|
timeout: config.timeouts.navigation
|
|
@@ -3883,6 +3935,8 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
3883
3935
|
} finally {
|
|
3884
3936
|
release();
|
|
3885
3937
|
}
|
|
3938
|
+
await evictIdlePlaywrightContextsToLimit().catch(() => {
|
|
3939
|
+
});
|
|
3886
3940
|
})();
|
|
3887
3941
|
try {
|
|
3888
3942
|
await initPromise;
|
|
@@ -3996,10 +4050,30 @@ async function loginToQwen(accountId, email, password) {
|
|
|
3996
4050
|
const uiResult = await loginViaUi(page, email, password);
|
|
3997
4051
|
if (uiResult.success) {
|
|
3998
4052
|
cookieCaches.delete(accountId);
|
|
3999
|
-
await saveStorageState(page.context(), accountId);
|
|
4000
4053
|
try {
|
|
4001
|
-
|
|
4002
|
-
|
|
4054
|
+
let liveCookies = await page.context().cookies();
|
|
4055
|
+
let tokenCookie = liveCookies.find((c) => c.name === "token");
|
|
4056
|
+
if (!tokenCookie) {
|
|
4057
|
+
const lsTok = uiResult.token || await page.evaluate(() => (localStorage.getItem("token") || "").trim()).catch(() => "");
|
|
4058
|
+
if (lsTok) {
|
|
4059
|
+
await page.context().addCookies([
|
|
4060
|
+
{
|
|
4061
|
+
name: "token",
|
|
4062
|
+
value: lsTok,
|
|
4063
|
+
domain: ".qwen.ai",
|
|
4064
|
+
path: "/",
|
|
4065
|
+
expires: Math.floor(Date.now() / 1e3) + 31536e3,
|
|
4066
|
+
httpOnly: false,
|
|
4067
|
+
secure: true,
|
|
4068
|
+
sameSite: "Lax"
|
|
4069
|
+
}
|
|
4070
|
+
]).catch(() => {
|
|
4071
|
+
});
|
|
4072
|
+
liveCookies = await page.context().cookies();
|
|
4073
|
+
tokenCookie = liveCookies.find((c) => c.name === "token");
|
|
4074
|
+
}
|
|
4075
|
+
}
|
|
4076
|
+
await saveStorageState(page.context(), accountId);
|
|
4003
4077
|
if (tokenCookie) {
|
|
4004
4078
|
const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
|
|
4005
4079
|
const cache = getHeaderCache(accountId);
|
|
@@ -4008,7 +4082,7 @@ async function loginToQwen(accountId, email, password) {
|
|
|
4008
4082
|
markAccountHeadersReady(accountId);
|
|
4009
4083
|
const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4010
4084
|
const exp = parseJwtExpiry(tokenCookie.value);
|
|
4011
|
-
let rTok = uiResult.refreshToken;
|
|
4085
|
+
let rTok = uiResult.refreshToken || liveCookies.find((c) => c.name === "refresh_token")?.value;
|
|
4012
4086
|
if (!rTok) {
|
|
4013
4087
|
try {
|
|
4014
4088
|
rTok = await page.evaluate(() => localStorage.getItem("refresh_token") || "") || void 0;
|
|
@@ -4089,8 +4163,9 @@ async function loginViaApi(page, email, password) {
|
|
|
4089
4163
|
}
|
|
4090
4164
|
const signinUrl = "https://auth.qwen.ai/api/v2/auths/signin";
|
|
4091
4165
|
const requestId = crypto3.randomUUID();
|
|
4166
|
+
const webVersion = getQwenWebVersion() || "0.3.26";
|
|
4092
4167
|
const evalRes = await page.evaluate(
|
|
4093
|
-
async ({ email: email2, password: password2, signinUrl: signinUrl2, requestId: requestId2, tz }) => {
|
|
4168
|
+
async ({ email: email2, password: password2, signinUrl: signinUrl2, requestId: requestId2, tz, version }) => {
|
|
4094
4169
|
try {
|
|
4095
4170
|
const response = await fetch(signinUrl2, {
|
|
4096
4171
|
method: "POST",
|
|
@@ -4100,7 +4175,7 @@ async function loginViaApi(page, email, password) {
|
|
|
4100
4175
|
accept: "application/json, text/plain, */*",
|
|
4101
4176
|
"content-type": "application/json",
|
|
4102
4177
|
source: "web",
|
|
4103
|
-
version
|
|
4178
|
+
version,
|
|
4104
4179
|
"x-request-origin": "https://chat.qwen.ai",
|
|
4105
4180
|
timezone: tz,
|
|
4106
4181
|
"x-request-id": requestId2
|
|
@@ -4113,7 +4188,14 @@ async function loginViaApi(page, email, password) {
|
|
|
4113
4188
|
return { ok: false, error: e.message };
|
|
4114
4189
|
}
|
|
4115
4190
|
},
|
|
4116
|
-
{
|
|
4191
|
+
{
|
|
4192
|
+
email,
|
|
4193
|
+
password: hashedPassword,
|
|
4194
|
+
signinUrl,
|
|
4195
|
+
requestId,
|
|
4196
|
+
tz: formatAsciiTimezone(),
|
|
4197
|
+
version: webVersion
|
|
4198
|
+
}
|
|
4117
4199
|
).catch(() => null);
|
|
4118
4200
|
let data = evalRes?.data;
|
|
4119
4201
|
let signinSuccess = Boolean(
|
|
@@ -4122,7 +4204,7 @@ async function loginViaApi(page, email, password) {
|
|
|
4122
4204
|
if (!signinSuccess && !data?.data?.code) {
|
|
4123
4205
|
const fallbackUrl = qwenUrl("/api/v2/auths/signin");
|
|
4124
4206
|
const fallbackRes = await page.evaluate(
|
|
4125
|
-
async ({ email: email2, password: password2, fallbackUrl: fallbackUrl2, requestId: requestId2, tz }) => {
|
|
4207
|
+
async ({ email: email2, password: password2, fallbackUrl: fallbackUrl2, requestId: requestId2, tz, version }) => {
|
|
4126
4208
|
try {
|
|
4127
4209
|
const response = await fetch(fallbackUrl2, {
|
|
4128
4210
|
method: "POST",
|
|
@@ -4132,7 +4214,7 @@ async function loginViaApi(page, email, password) {
|
|
|
4132
4214
|
accept: "application/json, text/plain, */*",
|
|
4133
4215
|
"content-type": "application/json",
|
|
4134
4216
|
source: "web",
|
|
4135
|
-
version
|
|
4217
|
+
version,
|
|
4136
4218
|
timezone: tz,
|
|
4137
4219
|
"x-request-id": requestId2
|
|
4138
4220
|
},
|
|
@@ -4144,7 +4226,14 @@ async function loginViaApi(page, email, password) {
|
|
|
4144
4226
|
return { ok: false, error: e.message };
|
|
4145
4227
|
}
|
|
4146
4228
|
},
|
|
4147
|
-
{
|
|
4229
|
+
{
|
|
4230
|
+
email,
|
|
4231
|
+
password: hashedPassword,
|
|
4232
|
+
fallbackUrl,
|
|
4233
|
+
requestId,
|
|
4234
|
+
tz: formatAsciiTimezone(),
|
|
4235
|
+
version: webVersion
|
|
4236
|
+
}
|
|
4148
4237
|
).catch(() => null);
|
|
4149
4238
|
if (fallbackRes?.data) {
|
|
4150
4239
|
data = fallbackRes.data;
|
|
@@ -4369,28 +4458,34 @@ async function loginViaUi(page, email, password) {
|
|
|
4369
4458
|
await sleep2(500);
|
|
4370
4459
|
const submitSelector = 'button.qwenchat-auth-pc-submit-button, button[type="submit"], button:has-text("Log in"), button:has-text("Sign in"), button:has-text("Fazer login"), button:has-text("Entrar"), button:has-text("Iniciar sesi\xF3n"), button:has-text("\u767B\u5F55")';
|
|
4371
4460
|
const submitButton = page.locator(submitSelector).first();
|
|
4372
|
-
|
|
4373
|
-
try {
|
|
4374
|
-
const btn = document.querySelector(sel);
|
|
4375
|
-
if (btn) {
|
|
4376
|
-
btn.removeAttribute("disabled");
|
|
4377
|
-
btn.classList.remove("ant-btn-disabled");
|
|
4378
|
-
btn.click();
|
|
4379
|
-
}
|
|
4380
|
-
} catch {
|
|
4381
|
-
}
|
|
4382
|
-
}, submitSelector).catch(() => {
|
|
4383
|
-
});
|
|
4461
|
+
let submitted = false;
|
|
4384
4462
|
try {
|
|
4385
4463
|
if (await submitButton.isVisible({ timeout: 2e3 }).catch(() => false)) {
|
|
4386
|
-
await submitButton.click({
|
|
4464
|
+
await submitButton.click({ timeout: 2e3 }).catch(() => {
|
|
4387
4465
|
});
|
|
4466
|
+
submitted = true;
|
|
4388
4467
|
}
|
|
4389
4468
|
} catch {
|
|
4390
4469
|
}
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4470
|
+
if (!submitted) {
|
|
4471
|
+
await page.evaluate(() => {
|
|
4472
|
+
try {
|
|
4473
|
+
const btn = document.querySelector(
|
|
4474
|
+
'button.qwenchat-auth-pc-submit-button, button[type="submit"]'
|
|
4475
|
+
);
|
|
4476
|
+
if (btn) {
|
|
4477
|
+
btn.removeAttribute("disabled");
|
|
4478
|
+
btn.classList.remove("ant-btn-disabled");
|
|
4479
|
+
btn.click();
|
|
4480
|
+
}
|
|
4481
|
+
} catch {
|
|
4482
|
+
}
|
|
4483
|
+
}).catch(() => {
|
|
4484
|
+
});
|
|
4485
|
+
const passInput = page.locator(passwordSelector).first();
|
|
4486
|
+
await passInput.press("Enter", { timeout: 2e3 }).catch(() => {
|
|
4487
|
+
});
|
|
4488
|
+
}
|
|
4394
4489
|
const postSubmitDeadline = Date.now() + 15e3;
|
|
4395
4490
|
while (Date.now() < postSubmitDeadline) {
|
|
4396
4491
|
if (page.isClosed()) break;
|
|
@@ -4408,9 +4503,12 @@ async function loginViaUi(page, email, password) {
|
|
|
4408
4503
|
".ant-form-item-explain-error",
|
|
4409
4504
|
".ant-message-error",
|
|
4410
4505
|
".ant-message-notice",
|
|
4506
|
+
".ant-message-custom-content",
|
|
4507
|
+
".ant-notification-notice",
|
|
4411
4508
|
'[role="alert"]',
|
|
4412
4509
|
".qwenchat-auth-error",
|
|
4413
|
-
".auth-error-message"
|
|
4510
|
+
".auth-error-message",
|
|
4511
|
+
".qwenchat-toast"
|
|
4414
4512
|
].join(", ");
|
|
4415
4513
|
const errorEl = page.locator(errorSelector).first();
|
|
4416
4514
|
if (await errorEl.isVisible().catch(() => false)) {
|
|
@@ -4424,7 +4522,15 @@ async function loginViaUi(page, email, password) {
|
|
|
4424
4522
|
};
|
|
4425
4523
|
}
|
|
4426
4524
|
}
|
|
4427
|
-
const codeSelector =
|
|
4525
|
+
const codeSelector = [
|
|
4526
|
+
'input[placeholder*="code" i]',
|
|
4527
|
+
'input[placeholder*="c\xF3digo" i]',
|
|
4528
|
+
'input[name*="code" i]',
|
|
4529
|
+
".qwenchat-verification-code-input",
|
|
4530
|
+
".qwenchat-verification-code-input-cell",
|
|
4531
|
+
'[aria-label*="Verification code" i]',
|
|
4532
|
+
'[aria-label*="c\xF3digo de verifica\xE7\xE3o" i]'
|
|
4533
|
+
].join(", ");
|
|
4428
4534
|
const codeInput = page.locator(codeSelector).first();
|
|
4429
4535
|
if (await codeInput.isVisible().catch(() => false)) {
|
|
4430
4536
|
return {
|
|
@@ -4434,16 +4540,44 @@ async function loginViaUi(page, email, password) {
|
|
|
4434
4540
|
}
|
|
4435
4541
|
try {
|
|
4436
4542
|
const liveCookies = await page.context().cookies();
|
|
4437
|
-
|
|
4438
|
-
|
|
4543
|
+
const rTokCookie = liveCookies.find((c) => c.name === "refresh_token")?.value;
|
|
4544
|
+
const tokCookie = liveCookies.find((c) => c.name === "token")?.value;
|
|
4545
|
+
if (tokCookie) {
|
|
4546
|
+
return { success: true, token: tokCookie, refreshToken: rTokCookie };
|
|
4439
4547
|
}
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4548
|
+
const currentUrl = page.url();
|
|
4549
|
+
if (!currentUrl.includes("/auth") && !currentUrl.includes("/login")) {
|
|
4550
|
+
const lsTok = await page.evaluate(() => {
|
|
4551
|
+
const t = (localStorage.getItem("token") || "").trim();
|
|
4552
|
+
if (t) {
|
|
4553
|
+
try {
|
|
4554
|
+
document.cookie = `token=${encodeURIComponent(t)}; path=/; domain=.qwen.ai; max-age=31536000`;
|
|
4555
|
+
} catch {
|
|
4556
|
+
}
|
|
4557
|
+
}
|
|
4558
|
+
return t;
|
|
4559
|
+
}).catch(() => "");
|
|
4560
|
+
if (lsTok) {
|
|
4561
|
+
await page.context().addCookies([
|
|
4562
|
+
{
|
|
4563
|
+
name: "token",
|
|
4564
|
+
value: lsTok,
|
|
4565
|
+
domain: ".qwen.ai",
|
|
4566
|
+
path: "/",
|
|
4567
|
+
expires: Math.floor(Date.now() / 1e3) + 31536e3,
|
|
4568
|
+
httpOnly: false,
|
|
4569
|
+
secure: true,
|
|
4570
|
+
sameSite: "Lax"
|
|
4571
|
+
}
|
|
4572
|
+
]).catch(() => {
|
|
4573
|
+
});
|
|
4574
|
+
return { success: true, token: lsTok, refreshToken: rTokCookie };
|
|
4575
|
+
}
|
|
4576
|
+
if (await isPageLoggedIn(page, 3e3)) {
|
|
4577
|
+
return { success: true, refreshToken: rTokCookie };
|
|
4578
|
+
}
|
|
4446
4579
|
}
|
|
4580
|
+
} catch {
|
|
4447
4581
|
}
|
|
4448
4582
|
await sleep2(1e3);
|
|
4449
4583
|
}
|
|
@@ -4473,10 +4607,18 @@ async function refreshAccountToken(accountId) {
|
|
|
4473
4607
|
} catch {
|
|
4474
4608
|
}
|
|
4475
4609
|
}
|
|
4610
|
+
if (!refreshToken) {
|
|
4611
|
+
try {
|
|
4612
|
+
const liveCookies = await page.context().cookies();
|
|
4613
|
+
refreshToken = liveCookies.find((c) => c.name === "refresh_token")?.value;
|
|
4614
|
+
} catch {
|
|
4615
|
+
}
|
|
4616
|
+
}
|
|
4476
4617
|
if (refreshToken) {
|
|
4477
4618
|
try {
|
|
4619
|
+
const webVersion = getQwenWebVersion() || "0.3.26";
|
|
4478
4620
|
const refreshResult = await page.evaluate(
|
|
4479
|
-
async ({ rTok, tz }) => {
|
|
4621
|
+
async ({ rTok, tz, version }) => {
|
|
4480
4622
|
try {
|
|
4481
4623
|
const response = await fetch("https://auth.qwen.ai/api/v2/auths/refresh", {
|
|
4482
4624
|
method: "GET",
|
|
@@ -4484,7 +4626,7 @@ async function refreshAccountToken(accountId) {
|
|
|
4484
4626
|
headers: {
|
|
4485
4627
|
accept: "application/json, text/plain, */*",
|
|
4486
4628
|
source: "web",
|
|
4487
|
-
version
|
|
4629
|
+
version,
|
|
4488
4630
|
"x-request-origin": "https://chat.qwen.ai",
|
|
4489
4631
|
timezone: tz,
|
|
4490
4632
|
authorization: `Bearer ${rTok}`
|
|
@@ -4496,7 +4638,7 @@ async function refreshAccountToken(accountId) {
|
|
|
4496
4638
|
return { ok: false, error: e.message };
|
|
4497
4639
|
}
|
|
4498
4640
|
},
|
|
4499
|
-
{ rTok: refreshToken, tz: formatAsciiTimezone() }
|
|
4641
|
+
{ rTok: refreshToken, tz: formatAsciiTimezone(), version: webVersion }
|
|
4500
4642
|
);
|
|
4501
4643
|
const json = refreshResult?.data;
|
|
4502
4644
|
if (json && json.success === true && json.data) {
|
|
@@ -5297,7 +5439,11 @@ function priorityOrderForEviction(accountIds) {
|
|
|
5297
5439
|
const ranked = getAccountsByPriority(accountIds.map((id) => ({ id })));
|
|
5298
5440
|
const rank = /* @__PURE__ */ new Map();
|
|
5299
5441
|
for (const [index, account] of ranked.entries()) {
|
|
5300
|
-
|
|
5442
|
+
if (getAccountCooldownInfo(account.id)) {
|
|
5443
|
+
rank.set(account.id, Number.MAX_SAFE_INTEGER);
|
|
5444
|
+
} else {
|
|
5445
|
+
rank.set(account.id, index);
|
|
5446
|
+
}
|
|
5301
5447
|
}
|
|
5302
5448
|
return orderContextsForEviction(
|
|
5303
5449
|
accountIds,
|
|
@@ -5305,14 +5451,15 @@ function priorityOrderForEviction(accountIds) {
|
|
|
5305
5451
|
(id) => lastAccountActivity.get(id) ?? 0
|
|
5306
5452
|
);
|
|
5307
5453
|
}
|
|
5308
|
-
async function evictIdlePlaywrightContextsToLimit() {
|
|
5309
|
-
const
|
|
5310
|
-
if (
|
|
5454
|
+
async function evictIdlePlaywrightContextsToLimit(targetLimit) {
|
|
5455
|
+
const configuredMax = config.playwright.maxActiveContexts;
|
|
5456
|
+
if (configuredMax <= 0) return 0;
|
|
5457
|
+
const max = targetLimit !== void 0 ? Math.max(0, targetLimit) : configuredMax;
|
|
5311
5458
|
if (accountPages.size <= max) return 0;
|
|
5312
5459
|
const candidates = priorityOrderForEviction(
|
|
5313
5460
|
Array.from(accountPages.keys()).filter((accountId) => {
|
|
5314
5461
|
if (isAccountServingStream(accountId)) return false;
|
|
5315
|
-
if (
|
|
5462
|
+
if (hasActiveAccountLease(accountId)) return false;
|
|
5316
5463
|
const mutex = accountMutexes.get(accountId);
|
|
5317
5464
|
return mutex?.isIdle();
|
|
5318
5465
|
})
|
|
@@ -5325,6 +5472,7 @@ async function evictIdlePlaywrightContextsToLimit() {
|
|
|
5325
5472
|
for (const candidate of candidates) {
|
|
5326
5473
|
if (accountPages.size <= max) break;
|
|
5327
5474
|
if (isAccountServingStream(candidate.accountId)) continue;
|
|
5475
|
+
if (hasActiveAccountLease(candidate.accountId)) continue;
|
|
5328
5476
|
const mutex = accountMutexes.get(candidate.accountId);
|
|
5329
5477
|
if (!mutex?.isIdle()) continue;
|
|
5330
5478
|
await closePlaywrightForAccount(candidate.accountId).catch((error) => {
|
|
@@ -5427,10 +5575,6 @@ async function closePlaywrightForAccount(accountId) {
|
|
|
5427
5575
|
release();
|
|
5428
5576
|
}
|
|
5429
5577
|
}
|
|
5430
|
-
function isAccountRecentlyActive(accountId, maxIdleMs = 3e5) {
|
|
5431
|
-
const last = lastAccountActivity.get(accountId) ?? 0;
|
|
5432
|
-
return last > 0 && Date.now() - last < maxIdleMs;
|
|
5433
|
-
}
|
|
5434
5578
|
var requireLocal, contextInitHooks, ACCOUNT_MUTEX_MAX_HOLD_MS, accountMutexes, accountContexts, accountPages, inFlightAccountInits, headerCaches, HEADER_CACHE_TTL, COOKIE_CACHE_TTL, cookieCaches, lastAccountActivity, lastKeepAliveNavigation, lastProactiveTokenRefresh, profileResetQueue, profileResetChain, closingAllPlaywright, sleep2, HEADER_CAPTURE_SETTLE_MS, PLAYWRIGHT_MUTEX_WAIT_MS, ACCOUNT_PAGE_OPERATION_TIMEOUT_MS, SESSION_PROBE_NAVIGATION_TIMEOUT_MS, HEADER_CAPTURE_TRIGGER_GRACE_MS, FIRST_TRIGGER_GRACE_MS, HEADER_CAPTURE_TRIGGER_ATTEMPTS, CHAT_INPUT_APPEAR_TIMEOUT_MS, CHAT_INPUT_ACTION_TIMEOUT_MS, PROFILE_RESET_TIMEOUT_MS;
|
|
5435
5579
|
var init_playwright = __esm({
|
|
5436
5580
|
"src/services/playwright.ts"() {
|