qwenproxy-cli 1.4.0 → 1.4.2

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.
@@ -925,6 +925,8 @@ var init_errors = __esm({
925
925
  });
926
926
 
927
927
  // src/core/config.ts
928
+ import fs6 from "node:fs";
929
+ import dotenv from "dotenv";
928
930
  import { z } from "zod";
929
931
  function isStatelessChatMode(mode) {
930
932
  if (!mode) return false;
@@ -954,6 +956,15 @@ var envSchema, env, config;
954
956
  var init_config = __esm({
955
957
  "src/core/config.ts"() {
956
958
  "use strict";
959
+ init_paths();
960
+ if (!isRunningUnderNodeTest()) {
961
+ const envPath = getEnvFilePath();
962
+ if (fs6.existsSync(envPath)) {
963
+ dotenv.config({ path: envPath, quiet: true });
964
+ } else {
965
+ dotenv.config({ quiet: true });
966
+ }
967
+ }
957
968
  envSchema = z.object({
958
969
  PORT: z.string().regex(/^\d+$/, "PORT must be a number").refine((value) => {
959
970
  const port = Number(value);
@@ -2833,7 +2844,7 @@ __export(clean_cache_exports, {
2833
2844
  getDirStats: () => getDirStats
2834
2845
  });
2835
2846
  import "dotenv/config";
2836
- import fs6 from "node:fs";
2847
+ import fs7 from "node:fs";
2837
2848
  import path4 from "node:path";
2838
2849
  import os3 from "node:os";
2839
2850
  import { chromium } from "patchright";
@@ -2848,14 +2859,14 @@ function getDirStats(dir) {
2848
2859
  let files = 0;
2849
2860
  function walk(d) {
2850
2861
  try {
2851
- const entries = fs6.readdirSync(d, { withFileTypes: true });
2862
+ const entries = fs7.readdirSync(d, { withFileTypes: true });
2852
2863
  for (const e of entries) {
2853
2864
  const full = path4.join(d, e.name);
2854
2865
  if (e.isDirectory()) {
2855
2866
  walk(full);
2856
2867
  } else if (e.isFile()) {
2857
2868
  try {
2858
- bytes += fs6.statSync(full).size;
2869
+ bytes += fs7.statSync(full).size;
2859
2870
  files++;
2860
2871
  } catch {
2861
2872
  }
@@ -2884,17 +2895,17 @@ async function cleanPlaywrightBrowsers(cleanUnused) {
2884
2895
  }
2885
2896
  } catch {
2886
2897
  }
2887
- if (!msPlaywrightDir || !fs6.existsSync(msPlaywrightDir)) {
2898
+ if (!msPlaywrightDir || !fs7.existsSync(msPlaywrightDir)) {
2888
2899
  const defaultPlaywrightDir = process.env.PLAYWRIGHT_BROWSERS_PATH || (process.platform === "win32" ? path4.join(os3.homedir(), "AppData", "Local", "ms-playwright") : process.platform === "darwin" ? path4.join(os3.homedir(), "Library", "Caches", "ms-playwright") : path4.join(os3.homedir(), ".cache", "ms-playwright"));
2889
- if (fs6.existsSync(defaultPlaywrightDir)) {
2900
+ if (fs7.existsSync(defaultPlaywrightDir)) {
2890
2901
  msPlaywrightDir = defaultPlaywrightDir;
2891
2902
  }
2892
2903
  }
2893
2904
  const unusedDirs = [];
2894
2905
  let freedBytes = 0;
2895
- if (msPlaywrightDir && fs6.existsSync(msPlaywrightDir)) {
2906
+ if (msPlaywrightDir && fs7.existsSync(msPlaywrightDir)) {
2896
2907
  try {
2897
- const entries = fs6.readdirSync(msPlaywrightDir, { withFileTypes: true });
2908
+ const entries = fs7.readdirSync(msPlaywrightDir, { withFileTypes: true });
2898
2909
  for (const entry of entries) {
2899
2910
  if (!entry.isDirectory()) continue;
2900
2911
  const folderName = entry.name;
@@ -2917,7 +2928,7 @@ async function cleanPlaywrightBrowsers(cleanUnused) {
2917
2928
  if (cleanUnused && unusedDirs.length > 0) {
2918
2929
  for (const item of unusedDirs) {
2919
2930
  try {
2920
- fs6.rmSync(item.path, { recursive: true, force: true });
2931
+ fs7.rmSync(item.path, { recursive: true, force: true });
2921
2932
  freedBytes += item.bytes;
2922
2933
  } catch (err) {
2923
2934
  console.warn(`[CleanCache] Warning: could not remove ${item.name}:`, err);
@@ -3053,7 +3064,7 @@ __export(playwright_exports, {
3053
3064
  });
3054
3065
  import { chromium as chromium2 } from "patchright";
3055
3066
  import path5 from "path";
3056
- import fs7 from "fs";
3067
+ import fs8 from "fs";
3057
3068
  import crypto3 from "crypto";
3058
3069
  import { spawnSync } from "child_process";
3059
3070
  import { createRequire } from "module";
@@ -3067,7 +3078,7 @@ function autoInstallPlaywrightChromium() {
3067
3078
  try {
3068
3079
  const patchrightEntry = requireLocal.resolve("patchright");
3069
3080
  const cliPath = path5.join(path5.dirname(patchrightEntry), "cli.js");
3070
- if (fs7.existsSync(cliPath)) {
3081
+ if (fs8.existsSync(cliPath)) {
3071
3082
  console.log("\u23F3 [Playwright] Navegador Chromium n\xE3o encontrado. Instalando automaticamente...");
3072
3083
  const res2 = spawnSync(process.execPath, [cliPath, "install", "chromium"], {
3073
3084
  stdio: "inherit",
@@ -3203,10 +3214,10 @@ function getStorageStatePath(accountId) {
3203
3214
  function loadStorageState(accountId) {
3204
3215
  const p1 = getStorageStatePath(accountId);
3205
3216
  const p2 = path5.join(path5.dirname(p1), `${accountId}_state.json`);
3206
- const chosenPath = fs7.existsSync(p1) ? p1 : fs7.existsSync(p2) ? p2 : void 0;
3217
+ const chosenPath = fs8.existsSync(p1) ? p1 : fs8.existsSync(p2) ? p2 : void 0;
3207
3218
  if (!chosenPath) return void 0;
3208
3219
  try {
3209
- const raw = fs7.readFileSync(chosenPath, "utf8");
3220
+ const raw = fs8.readFileSync(chosenPath, "utf8");
3210
3221
  const state = JSON.parse(raw);
3211
3222
  if (!state || typeof state !== "object" || !Array.isArray(state.cookies)) {
3212
3223
  return void 0;
@@ -3220,8 +3231,8 @@ async function saveStorageState(context, accountId, timeoutMs = 5e3) {
3220
3231
  try {
3221
3232
  const stateFile = getStorageStatePath(accountId);
3222
3233
  const dir = path5.dirname(stateFile);
3223
- if (!fs7.existsSync(dir)) {
3224
- fs7.mkdirSync(dir, { recursive: true });
3234
+ if (!fs8.existsSync(dir)) {
3235
+ fs8.mkdirSync(dir, { recursive: true });
3225
3236
  }
3226
3237
  await withTimeout(
3227
3238
  context.storageState({ path: stateFile }),
@@ -3330,7 +3341,7 @@ async function isPageLoggedIn(page, timeoutMs = SESSION_PROBE_NAVIGATION_TIMEOUT
3330
3341
  return false;
3331
3342
  }
3332
3343
  }
3333
- async function getOrLaunchSharedBrowser(browserType = "chromium", headless = true) {
3344
+ async function getOrLaunchSharedBrowser(browserType = "chromium", headless = config.playwright.headless) {
3334
3345
  if (sharedBrowser && sharedBrowser.isConnected()) {
3335
3346
  return sharedBrowser;
3336
3347
  }
@@ -3390,13 +3401,40 @@ async function getOrLaunchSharedBrowser(browserType = "chromium", headless = tru
3390
3401
  }
3391
3402
  }
3392
3403
  async function clearVisibleChallenge(page) {
3393
- if (!config.captcha.enabled) return;
3394
- await solveBaxiaCaptcha(page, {
3395
- waitForMs: 0,
3396
- maxAttempts: config.captcha.maxAttempts,
3397
- retryDelayMs: config.captcha.retryDelayMs,
3398
- settleMs: config.captcha.settleMs
3399
- }).catch(() => false);
3404
+ if (page.isClosed()) return;
3405
+ if (config.captcha.enabled) {
3406
+ await solveBaxiaCaptcha(page, {
3407
+ waitForMs: 0,
3408
+ maxAttempts: config.captcha.maxAttempts,
3409
+ retryDelayMs: config.captcha.retryDelayMs,
3410
+ settleMs: config.captcha.settleMs
3411
+ }).catch(() => false);
3412
+ }
3413
+ try {
3414
+ const modalCloseSelectors = [
3415
+ ".ant-modal-close",
3416
+ ".ant-modal-close-x",
3417
+ "button.ant-modal-close",
3418
+ "button[aria-label*='Close' i]",
3419
+ "button[aria-label*='Fechar' i]",
3420
+ ".index-module__whats-new-modal-close",
3421
+ "button:has-text('Cancel')",
3422
+ "button:has-text('Cancelar')",
3423
+ "button:has-text('I understand')",
3424
+ "button:has-text('Entendi')",
3425
+ "button:has-text('OK')"
3426
+ ];
3427
+ for (const sel of modalCloseSelectors) {
3428
+ if (page.isClosed()) return;
3429
+ const btn = page.locator(sel).first();
3430
+ if (await btn.isVisible({ timeout: 150 }).catch(() => false)) {
3431
+ await btn.click({ timeout: 500 }).catch(() => {
3432
+ });
3433
+ await sleep2(200);
3434
+ }
3435
+ }
3436
+ } catch {
3437
+ }
3400
3438
  }
3401
3439
  function getErrorMessage(error) {
3402
3440
  return error instanceof Error ? error.message : String(error);
@@ -3824,6 +3862,21 @@ function getStealthScript(profile) {
3824
3862
  spoofedFunctions.add(window.performance.getEntriesByType);
3825
3863
  }
3826
3864
  } catch(e) {}
3865
+
3866
+ // --- Auto-resolve birthday compliance & eliminate false logout markers ---
3867
+ try {
3868
+ localStorage.removeItem("qwen_token_logged_out_marker");
3869
+ const b = localStorage.getItem("qwen_account_birthday");
3870
+ if (b) {
3871
+ try {
3872
+ const parsed = JSON.parse(b);
3873
+ if (!parsed.birthday) {
3874
+ parsed.birthday = "1995-06-15";
3875
+ localStorage.setItem("qwen_account_birthday", JSON.stringify(parsed));
3876
+ }
3877
+ } catch {}
3878
+ }
3879
+ } catch(e) {}
3827
3880
  })();
3828
3881
  `;
3829
3882
  }
@@ -4122,7 +4175,7 @@ async function resolveAccountCredentials(account) {
4122
4175
  }
4123
4176
  return account;
4124
4177
  }
4125
- async function initPlaywrightForAccount(rawAccount, headless = true, browserType = "chromium", options = {}) {
4178
+ async function initPlaywrightForAccount(rawAccount, headless = config.playwright.headless, browserType = "chromium", options = {}) {
4126
4179
  const account = await resolveAccountCredentials(rawAccount);
4127
4180
  if (accountPages.has(account.id)) {
4128
4181
  console.log(
@@ -4248,7 +4301,7 @@ async function initPlaywrightForAccount(rawAccount, headless = true, browserType
4248
4301
  const storageState = loadStorageState(account.id);
4249
4302
  if (storageState) {
4250
4303
  try {
4251
- const raw = fs7.readFileSync(storageState, "utf8");
4304
+ const raw = fs8.readFileSync(storageState, "utf8");
4252
4305
  const parsed = JSON.parse(raw);
4253
4306
  if (Array.isArray(parsed.cookies) && parsed.cookies.length > 0) {
4254
4307
  const currentCookies = await acctContext.cookies();
@@ -4335,11 +4388,19 @@ async function initPlaywrightForAccount(rawAccount, headless = true, browserType
4335
4388
  }
4336
4389
  if (restoredFromDb) {
4337
4390
  if (!acctPage.isClosed() && (acctPage.url() === "about:blank" || !acctPage.url().startsWith(qwenOrigin()))) {
4338
- void acctPage.goto(qwenUrl("/"), {
4339
- waitUntil: "domcontentloaded",
4340
- timeout: config.timeouts.navigation
4341
- }).catch(() => {
4342
- });
4391
+ try {
4392
+ await acctPage.goto(qwenUrl("/"), {
4393
+ waitUntil: "domcontentloaded",
4394
+ timeout: config.timeouts.navigation
4395
+ });
4396
+ await sleep2(300);
4397
+ } catch (err) {
4398
+ if (!err?.message?.includes("ERR_ABORTED")) {
4399
+ console.warn(
4400
+ `\u26A0\uFE0F [Playwright] Background navigation warning for ${maskEmail(account.email)}: ${err.message}`
4401
+ );
4402
+ }
4403
+ }
4343
4404
  }
4344
4405
  return;
4345
4406
  }
@@ -4460,7 +4521,7 @@ async function validateAccountLogin(rawAccount, headless = true, browserType = "
4460
4521
  const storageState = loadStorageState(account.id);
4461
4522
  if (storageState) {
4462
4523
  try {
4463
- const raw = fs7.readFileSync(storageState, "utf8");
4524
+ const raw = fs8.readFileSync(storageState, "utf8");
4464
4525
  const parsed = JSON.parse(raw);
4465
4526
  if (Array.isArray(parsed.cookies) && parsed.cookies.length > 0) {
4466
4527
  const currentCookies = await acctContext.cookies();
@@ -4579,18 +4640,34 @@ async function loginToQwen(accountId, email, password) {
4579
4640
  const apiResult = await loginViaApi(page, email, password);
4580
4641
  if (apiResult.success) {
4581
4642
  cookieCaches.delete(accountId);
4582
- const cache = headerCaches.get(accountId);
4583
- if (cache) {
4584
- cache.headers = {};
4585
- cache.lastRefresh = 0;
4586
- }
4587
- unmarkAccountHeadersReady(accountId);
4643
+ await saveStorageState(page.context(), accountId);
4588
4644
  try {
4589
- const { deleteAuthSession: deleteAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
4590
- deleteAuthSession2(accountId);
4645
+ const liveCookies = await page.context().cookies();
4646
+ const tokenCookie = liveCookies.find((c) => c.name === "token");
4647
+ if (tokenCookie) {
4648
+ const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
4649
+ const cache = getHeaderCache(accountId);
4650
+ cache.headers.cookie = cookieStr;
4651
+ cache.lastRefresh = Date.now();
4652
+ markAccountHeadersReady(accountId);
4653
+ const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
4654
+ const exp = parseJwtExpiry(tokenCookie.value);
4655
+ saveAuthSession2(accountId, {
4656
+ cookie: cookieStr,
4657
+ userAgent: cache.headers["user-agent"] || "",
4658
+ bxV: cache.headers["bx-v"] || "2.5.37",
4659
+ bxUa: cache.headers["bx-ua"] || "",
4660
+ bxUmidtoken: cache.headers["bx-umidtoken"] || "",
4661
+ secChUa: cache.headers["sec-ch-ua"] || void 0,
4662
+ secChUaMobile: cache.headers["sec-ch-ua-mobile"] || void 0,
4663
+ secChUaPlatform: cache.headers["sec-ch-ua-platform"] || void 0,
4664
+ version: cache.headers["version"] || void 0,
4665
+ tokenExpiresAt: exp || void 0,
4666
+ capturedAt: Date.now()
4667
+ });
4668
+ }
4591
4669
  } catch {
4592
4670
  }
4593
- await saveStorageState(page.context(), accountId);
4594
4671
  return true;
4595
4672
  }
4596
4673
  if (apiResult.permanentFailure) {
@@ -4607,18 +4684,34 @@ async function loginToQwen(accountId, email, password) {
4607
4684
  const uiResult = await loginViaUi(page, email, password);
4608
4685
  if (uiResult.success) {
4609
4686
  cookieCaches.delete(accountId);
4610
- const cache = headerCaches.get(accountId);
4611
- if (cache) {
4612
- cache.headers = {};
4613
- cache.lastRefresh = 0;
4614
- }
4615
- unmarkAccountHeadersReady(accountId);
4687
+ await saveStorageState(page.context(), accountId);
4616
4688
  try {
4617
- const { deleteAuthSession: deleteAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
4618
- deleteAuthSession2(accountId);
4689
+ const liveCookies = await page.context().cookies();
4690
+ const tokenCookie = liveCookies.find((c) => c.name === "token");
4691
+ if (tokenCookie) {
4692
+ const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
4693
+ const cache = getHeaderCache(accountId);
4694
+ cache.headers.cookie = cookieStr;
4695
+ cache.lastRefresh = Date.now();
4696
+ markAccountHeadersReady(accountId);
4697
+ const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
4698
+ const exp = parseJwtExpiry(tokenCookie.value);
4699
+ saveAuthSession2(accountId, {
4700
+ cookie: cookieStr,
4701
+ userAgent: cache.headers["user-agent"] || "",
4702
+ bxV: cache.headers["bx-v"] || "2.5.37",
4703
+ bxUa: cache.headers["bx-ua"] || "",
4704
+ bxUmidtoken: cache.headers["bx-umidtoken"] || "",
4705
+ secChUa: cache.headers["sec-ch-ua"] || void 0,
4706
+ secChUaMobile: cache.headers["sec-ch-ua-mobile"] || void 0,
4707
+ secChUaPlatform: cache.headers["sec-ch-ua-platform"] || void 0,
4708
+ version: cache.headers["version"] || void 0,
4709
+ tokenExpiresAt: exp || void 0,
4710
+ capturedAt: Date.now()
4711
+ });
4712
+ }
4619
4713
  } catch {
4620
4714
  }
4621
- await saveStorageState(page.context(), accountId);
4622
4715
  return true;
4623
4716
  }
4624
4717
  if (uiResult.permanentFailure) {
@@ -4817,10 +4910,16 @@ async function loginViaUi(page, email, password) {
4817
4910
  );
4818
4911
  return { success: false, reason: "Campo de e-mail n\xE3o encontrado (poss\xEDvel captcha)" };
4819
4912
  }
4913
+ await clearVisibleChallenge(page);
4914
+ const findPasswordModeButton = () => {
4915
+ return page.locator('button, [role="button"], a, div').filter({
4916
+ hasText: /(?:log\s*in\s*with\s*(?:a\s*)?password|fazer\s*login\s*com\s*senha|entrar\s*com\s*(?:uma\s*)?senha|iniciar\s*sesi[oó]n\s*con\s*contrase[nñ]a|密码登录)/i
4917
+ }).first();
4918
+ };
4820
4919
  try {
4821
- const pwdModeBtn = page.getByText(/Log in with a password/i).first();
4822
- if (await pwdModeBtn.isVisible({ timeout: 1500 }).catch(() => false)) {
4823
- await pwdModeBtn.click().catch(() => {
4920
+ const pwdModeBtn = findPasswordModeButton();
4921
+ if (await pwdModeBtn.isVisible({ timeout: 2e3 }).catch(() => false)) {
4922
+ await pwdModeBtn.click({ timeout: 2e3 }).catch(() => {
4824
4923
  });
4825
4924
  await sleep2(500);
4826
4925
  }
@@ -4829,9 +4928,9 @@ async function loginViaUi(page, email, password) {
4829
4928
  await page.fill(emailSelector, email);
4830
4929
  await sleep2(300);
4831
4930
  try {
4832
- const pwdModeBtn = page.getByText(/Log in with a password/i).first();
4833
- if (await pwdModeBtn.isVisible({ timeout: 1e3 }).catch(() => false)) {
4834
- await pwdModeBtn.click().catch(() => {
4931
+ const pwdModeBtn = findPasswordModeButton();
4932
+ if (await pwdModeBtn.isVisible({ timeout: 1500 }).catch(() => false)) {
4933
+ await pwdModeBtn.click({ timeout: 2e3 }).catch(() => {
4835
4934
  });
4836
4935
  await sleep2(500);
4837
4936
  }
@@ -4856,7 +4955,7 @@ async function loginViaUi(page, email, password) {
4856
4955
  }
4857
4956
  await page.fill(passwordSelector, password);
4858
4957
  await sleep2(500);
4859
- const submitSelector = 'button.qwenchat-auth-pc-submit-button, button[type="submit"], button:has-text("Log in"), button:has-text("Sign in")';
4958
+ 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")';
4860
4959
  const submitButton = page.locator(submitSelector).first();
4861
4960
  try {
4862
4961
  await page.waitForSelector('button[type="submit"]:not([disabled])', {
@@ -5461,7 +5560,7 @@ async function refreshHeadersInternal(accountId, timeoutMs = config.timeouts.hea
5461
5560
  await executeReauth();
5462
5561
  }
5463
5562
  }
5464
- if (reauthExecuted && hasRequiredQwenHeaders(cache.headers)) {
5563
+ if (hasRequiredQwenHeaders(cache.headers)) {
5465
5564
  const liveCookies = await page.context().cookies();
5466
5565
  if (liveCookies.some((c) => c.name === "token")) {
5467
5566
  const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
@@ -5577,12 +5676,12 @@ async function resetPlaywrightProfileLocked(accountId) {
5577
5676
  removePlaywrightProfile(profilePath);
5578
5677
  const stateFile2 = path5.join(path5.dirname(profilePath), `${accountId}_state.json`);
5579
5678
  try {
5580
- fs7.rmSync(stateFile2, { force: true });
5679
+ fs8.rmSync(stateFile2, { force: true });
5581
5680
  } catch {
5582
5681
  }
5583
5682
  }
5584
5683
  function removePlaywrightProfile(profilePath, rmSyncOverride) {
5585
- const doRemove = rmSyncOverride ?? ((p, opts) => fs7.rmSync(p, opts));
5684
+ const doRemove = rmSyncOverride ?? ((p, opts) => fs8.rmSync(p, opts));
5586
5685
  try {
5587
5686
  doRemove(profilePath, { recursive: true, force: true });
5588
5687
  } catch (error) {
@@ -5591,7 +5690,7 @@ function removePlaywrightProfile(profilePath, rmSyncOverride) {
5591
5690
  if (message.includes("EPERM") || message.includes("EBUSY") || message.includes("Permission denied")) {
5592
5691
  try {
5593
5692
  const stalePath = `${profilePath}.stale-${Date.now()}`;
5594
- fs7.renameSync(profilePath, stalePath);
5693
+ fs8.renameSync(profilePath, stalePath);
5595
5694
  } catch {
5596
5695
  }
5597
5696
  return;
@@ -5614,23 +5713,23 @@ function prunePlaywrightProfileCaches(profilePath) {
5614
5713
  let freedFiles = 0;
5615
5714
  try {
5616
5715
  const defaultDir = path5.join(profilePath, "Default");
5617
- if (!fs7.existsSync(defaultDir)) {
5716
+ if (!fs8.existsSync(defaultDir)) {
5618
5717
  return { freedBytes, freedFiles };
5619
5718
  }
5620
5719
  for (const dirName of transientDirNames) {
5621
5720
  const targetDir = path5.join(defaultDir, dirName);
5622
- if (fs7.existsSync(targetDir)) {
5721
+ if (fs8.existsSync(targetDir)) {
5623
5722
  try {
5624
5723
  const countAndRemove = (d) => {
5625
5724
  try {
5626
- const entries = fs7.readdirSync(d, { withFileTypes: true });
5725
+ const entries = fs8.readdirSync(d, { withFileTypes: true });
5627
5726
  for (const e of entries) {
5628
5727
  const full = path5.join(d, e.name);
5629
5728
  if (e.isDirectory()) {
5630
5729
  countAndRemove(full);
5631
5730
  } else if (e.isFile()) {
5632
5731
  try {
5633
- freedBytes += fs7.statSync(full).size;
5732
+ freedBytes += fs8.statSync(full).size;
5634
5733
  freedFiles++;
5635
5734
  } catch {
5636
5735
  }
@@ -5640,7 +5739,7 @@ function prunePlaywrightProfileCaches(profilePath) {
5640
5739
  }
5641
5740
  };
5642
5741
  countAndRemove(targetDir);
5643
- fs7.rmSync(targetDir, { recursive: true, force: true });
5742
+ fs8.rmSync(targetDir, { recursive: true, force: true });
5644
5743
  } catch {
5645
5744
  }
5646
5745
  }
@@ -5654,10 +5753,10 @@ function pruneAllPlaywrightProfiles(baseDir = getProfilesDir()) {
5654
5753
  let totalFreedFiles = 0;
5655
5754
  let profilesCleaned = 0;
5656
5755
  try {
5657
- if (!fs7.existsSync(baseDir)) {
5756
+ if (!fs8.existsSync(baseDir)) {
5658
5757
  return { totalFreedBytes, totalFreedFiles, profilesCleaned };
5659
5758
  }
5660
- const entries = fs7.readdirSync(baseDir, { withFileTypes: true });
5759
+ const entries = fs8.readdirSync(baseDir, { withFileTypes: true });
5661
5760
  for (const entry of entries) {
5662
5761
  if (entry.isDirectory()) {
5663
5762
  const profilePath = path5.join(baseDir, entry.name);
@@ -5677,11 +5776,11 @@ function cleanupOrphanProfiles(baseDir = getProfilesDir(), activeAccountIds) {
5677
5776
  let removedCount = 0;
5678
5777
  let freedBytes = 0;
5679
5778
  try {
5680
- if (!fs7.existsSync(baseDir)) {
5779
+ if (!fs8.existsSync(baseDir)) {
5681
5780
  return { removedCount, freedBytes };
5682
5781
  }
5683
5782
  const activeIds = activeAccountIds ?? new Set(loadAccounts().map((a) => a.id));
5684
- const entries = fs7.readdirSync(baseDir, { withFileTypes: true });
5783
+ const entries = fs8.readdirSync(baseDir, { withFileTypes: true });
5685
5784
  for (const entry of entries) {
5686
5785
  if (!entry.isDirectory()) continue;
5687
5786
  const isStale = entry.name.includes(".stale-");
@@ -5692,13 +5791,13 @@ function cleanupOrphanProfiles(baseDir = getProfilesDir(), activeAccountIds) {
5692
5791
  let bytes = 0;
5693
5792
  const countSize = (d) => {
5694
5793
  try {
5695
- const subEntries = fs7.readdirSync(d, { withFileTypes: true });
5794
+ const subEntries = fs8.readdirSync(d, { withFileTypes: true });
5696
5795
  for (const e of subEntries) {
5697
5796
  const full = path5.join(d, e.name);
5698
5797
  if (e.isDirectory()) countSize(full);
5699
5798
  else if (e.isFile()) {
5700
5799
  try {
5701
- bytes += fs7.statSync(full).size;
5800
+ bytes += fs8.statSync(full).size;
5702
5801
  } catch {
5703
5802
  }
5704
5803
  }
@@ -5708,7 +5807,7 @@ function cleanupOrphanProfiles(baseDir = getProfilesDir(), activeAccountIds) {
5708
5807
  };
5709
5808
  countSize(targetPath);
5710
5809
  removePlaywrightProfile(targetPath);
5711
- if (!fs7.existsSync(targetPath)) {
5810
+ if (!fs8.existsSync(targetPath)) {
5712
5811
  removedCount++;
5713
5812
  freedBytes += bytes;
5714
5813
  }
@@ -7871,10 +7970,17 @@ async function withQwenBrowserPage(accountId, fn, targetPath, operationTimeoutMs
7871
7970
  }
7872
7971
  const needsNavigation = currentOrigin !== targetOrigin || normalizedTargetPath !== null && currentPath !== normalizedTargetPath;
7873
7972
  if (needsNavigation) {
7874
- await page.goto(targetUrl, {
7875
- waitUntil: "domcontentloaded",
7876
- timeout: Math.min(config.timeouts.navigation, operationTimeoutMs)
7877
- });
7973
+ try {
7974
+ await page.goto(targetUrl, {
7975
+ waitUntil: "domcontentloaded",
7976
+ timeout: Math.min(config.timeouts.navigation, operationTimeoutMs)
7977
+ });
7978
+ } catch (err) {
7979
+ if (err?.message?.includes("ERR_ABORTED") && page.url().startsWith(targetOrigin)) {
7980
+ } else {
7981
+ throw err;
7982
+ }
7983
+ }
7878
7984
  }
7879
7985
  return fn(page);
7880
7986
  },
@@ -7926,7 +8032,7 @@ async function requestQwenTextInBrowser(accountId, method, path6, headers, body,
7926
8032
  const controller = new AbortController();
7927
8033
  const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
7928
8034
  try {
7929
- const response2 = await fetch(url2, {
8035
+ let response2 = await fetch(url2, {
7930
8036
  method: method2,
7931
8037
  credentials: "include",
7932
8038
  headers: headers2,
@@ -7934,6 +8040,36 @@ async function requestQwenTextInBrowser(accountId, method, path6, headers, body,
7934
8040
  signal: controller.signal,
7935
8041
  ...referrer ? { referrer } : {}
7936
8042
  });
8043
+ if (response2.status === 401) {
8044
+ try {
8045
+ const refreshRes = await fetch("https://auth.qwen.ai/api/v2/auths/refresh", {
8046
+ method: "GET",
8047
+ credentials: "include",
8048
+ signal: AbortSignal.timeout(3e3)
8049
+ });
8050
+ if (refreshRes.status === 200) {
8051
+ const refreshJson = await refreshRes.json().catch(() => null);
8052
+ if (refreshJson && refreshJson.success === true && refreshJson.data?.token) {
8053
+ const freshTok = refreshJson.data.token;
8054
+ localStorage.setItem("token", freshTok);
8055
+ document.cookie = `token=${encodeURIComponent(freshTok)}; path=/; domain=.qwen.ai; max-age=31536000`;
8056
+ if (headers2["authorization"] || headers2["Authorization"]) {
8057
+ headers2["authorization"] = `Bearer ${freshTok}`;
8058
+ headers2["Authorization"] = `Bearer ${freshTok}`;
8059
+ }
8060
+ response2 = await fetch(url2, {
8061
+ method: method2,
8062
+ credentials: "include",
8063
+ headers: headers2,
8064
+ body: body2,
8065
+ signal: controller.signal,
8066
+ ...referrer ? { referrer } : {}
8067
+ });
8068
+ }
8069
+ }
8070
+ } catch {
8071
+ }
8072
+ }
7937
8073
  return {
7938
8074
  status: response2.status,
7939
8075
  contentType: response2.headers.get("content-type") || "",
@@ -8035,18 +8171,6 @@ async function requestQwenSettingsDirectFetch(accountId, method, path6, headers,
8035
8171
  }
8036
8172
  }
8037
8173
  async function requestQwenPersonalizationInBrowser(accountId, method, path6, headers, payload) {
8038
- if (!config.qwen.browserOnlyFetch && !isAuthMockEnabled()) {
8039
- const direct = await requestQwenSettingsDirectFetch(
8040
- accountId,
8041
- method,
8042
- path6,
8043
- headers,
8044
- payload
8045
- );
8046
- if (direct) {
8047
- return direct;
8048
- }
8049
- }
8050
8174
  const response = await requestQwenTextInBrowser(
8051
8175
  accountId,
8052
8176
  method,