qwenproxy-cli 1.6.11 → 1.6.12

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/login.js CHANGED
@@ -1228,7 +1228,7 @@ var init_config = __esm({
1228
1228
  // Version header on Qwen API requests = the deployed web bundle version
1229
1229
  // (fallback when dynamic DOM detection is not yet completed).
1230
1230
  // Override via env when Qwen ships a new bundle.
1231
- QWEN_WEB_VERSION: z.string().default("0.3.26"),
1231
+ QWEN_WEB_VERSION: z.string().default("0.3.43"),
1232
1232
  // Controls bx-ua/bx-umidtoken injection on the GENERAL API paths
1233
1233
  // (chats/new, settings): those work without them (live-probed). The
1234
1234
  // completions path is the exception — the 0.2.86 HAR shows the real
@@ -1271,6 +1271,7 @@ var init_config = __esm({
1271
1271
  CAPTCHA_SOLVER_ENABLED: z.string().default("true"),
1272
1272
  CAPTCHA_SOLVER_MAX_ATTEMPTS: z.string().default("3"),
1273
1273
  CAPTCHA_SOLVER_TIMEOUT_MS: z.string().default("15000"),
1274
+ CAPTCHA_SLIDER_TIMEOUT_MS: z.string().default("8000"),
1274
1275
  CAPTCHA_SOLVER_RETRY_DELAY_MS: z.string().default("1000"),
1275
1276
  CAPTCHA_SOLVER_SETTLE_MS: z.string().default("2000"),
1276
1277
  CAPTCHA_ACCOUNT_COOLDOWN_MS: z.string().default("120000"),
@@ -1422,6 +1423,8 @@ var init_config = __esm({
1422
1423
  enabled: env.CAPTCHA_SOLVER_ENABLED === "true",
1423
1424
  maxAttempts: Math.max(1, Math.min(5, parseInt(env.CAPTCHA_SOLVER_MAX_ATTEMPTS))),
1424
1425
  timeoutMs: Math.max(0, parseInt(env.CAPTCHA_SOLVER_TIMEOUT_MS)),
1426
+ /** Max wait for a challenge slider to become visible (slow WAF renders). */
1427
+ sliderTimeoutMs: Math.max(500, parseInt(env.CAPTCHA_SLIDER_TIMEOUT_MS)),
1425
1428
  retryDelayMs: Math.max(0, parseInt(env.CAPTCHA_SOLVER_RETRY_DELAY_MS)),
1426
1429
  settleMs: Math.max(0, parseInt(env.CAPTCHA_SOLVER_SETTLE_MS)),
1427
1430
  /** Rest an account whose challenge could not be cleared before reusing it. */
@@ -2612,6 +2615,294 @@ function logBaxiaCaptcha(event, fields = {}, important = false) {
2612
2615
  console.log(line);
2613
2616
  }
2614
2617
  }
2618
+ async function findVisibleLocatorWithin(page, selectors, timeoutMs) {
2619
+ const deadline = Date.now() + Math.max(0, timeoutMs);
2620
+ while (true) {
2621
+ const found = await findVisibleLocator(page, selectors);
2622
+ if (found) return found;
2623
+ if (Date.now() >= deadline) return null;
2624
+ await sleep(Math.min(150, Math.max(1, deadline - Date.now())));
2625
+ }
2626
+ }
2627
+ async function waitForHidden(locator, timeoutMs) {
2628
+ const deadline = Date.now() + Math.max(0, timeoutMs);
2629
+ while (true) {
2630
+ if (!await isVisible(locator)) return true;
2631
+ if (Date.now() >= deadline) return false;
2632
+ await sleep(Math.min(100, Math.max(1, deadline - Date.now())));
2633
+ }
2634
+ }
2635
+ async function computeAliyunPuzzleOffset(page) {
2636
+ return page.evaluate(() => {
2637
+ const background = document.querySelector(
2638
+ "#aliyunCaptcha-img"
2639
+ );
2640
+ const piece = document.querySelector(
2641
+ "#aliyunCaptcha-puzzle"
2642
+ );
2643
+ if (!background || !piece) {
2644
+ return Promise.resolve({ ok: false, reason: "missing puzzle images" });
2645
+ }
2646
+ const compute = () => {
2647
+ try {
2648
+ const width = background.naturalWidth;
2649
+ const height = background.naturalHeight;
2650
+ const pieceWidth = piece.naturalWidth;
2651
+ const pieceHeight = piece.naturalHeight;
2652
+ if (!width || !height || !pieceWidth || !pieceHeight) {
2653
+ return { ok: false, reason: "image dimensions unavailable" };
2654
+ }
2655
+ const backgroundCanvas = document.createElement("canvas");
2656
+ backgroundCanvas.id = "captcha-solver-canvas";
2657
+ backgroundCanvas.width = width;
2658
+ backgroundCanvas.height = height;
2659
+ const backgroundContext = backgroundCanvas.getContext("2d");
2660
+ if (!backgroundContext) {
2661
+ return { ok: false, reason: "no background context" };
2662
+ }
2663
+ const pieceCanvas = document.createElement("canvas");
2664
+ pieceCanvas.id = "captcha-solver-canvas";
2665
+ pieceCanvas.width = pieceWidth;
2666
+ pieceCanvas.height = pieceHeight;
2667
+ const pieceContext = pieceCanvas.getContext("2d");
2668
+ if (!pieceContext) {
2669
+ return { ok: false, reason: "no piece context" };
2670
+ }
2671
+ try {
2672
+ backgroundContext.drawImage(background, 0, 0);
2673
+ } catch {
2674
+ return { ok: false, reason: "background canvas tainted" };
2675
+ }
2676
+ try {
2677
+ pieceContext.drawImage(piece, 0, 0);
2678
+ } catch {
2679
+ return { ok: false, reason: "puzzle canvas tainted" };
2680
+ }
2681
+ const backgroundData = backgroundContext.getImageData(
2682
+ 0,
2683
+ 0,
2684
+ width,
2685
+ height
2686
+ ).data;
2687
+ const pieceData = pieceContext.getImageData(
2688
+ 0,
2689
+ 0,
2690
+ pieceWidth,
2691
+ pieceHeight
2692
+ ).data;
2693
+ let pieceMinX = pieceWidth;
2694
+ let pieceMaxX = -1;
2695
+ let pieceMinY = pieceHeight;
2696
+ let pieceMaxY = -1;
2697
+ for (let y = 0; y < pieceHeight; y++) {
2698
+ for (let x = 0; x < pieceWidth; x++) {
2699
+ if (pieceData[(y * pieceWidth + x) * 4 + 3] > 100) {
2700
+ if (x < pieceMinX) pieceMinX = x;
2701
+ if (x > pieceMaxX) pieceMaxX = x;
2702
+ if (y < pieceMinY) pieceMinY = y;
2703
+ if (y > pieceMaxY) pieceMaxY = y;
2704
+ }
2705
+ }
2706
+ }
2707
+ const puzzleWidth = pieceMaxX - pieceMinX + 1;
2708
+ if (puzzleWidth <= 0) {
2709
+ return { ok: false, reason: "empty puzzle piece" };
2710
+ }
2711
+ const yStart = Math.max(1, Math.min(height - 2, pieceMinY + 5));
2712
+ const yEnd = Math.max(
2713
+ yStart,
2714
+ Math.min(height - 2, pieceMaxY - 5)
2715
+ );
2716
+ const columnGradients = new Float32Array(width);
2717
+ for (let x = 1; x < width - 1; x++) {
2718
+ let gradient = 0;
2719
+ for (let y = yStart; y <= yEnd; y++) {
2720
+ const left = (y * width + x - 1) * 4;
2721
+ const right = (y * width + x + 1) * 4;
2722
+ gradient += Math.abs(backgroundData[right] - backgroundData[left]) + Math.abs(backgroundData[right + 1] - backgroundData[left + 1]) + Math.abs(backgroundData[right + 2] - backgroundData[left + 2]);
2723
+ }
2724
+ columnGradients[x] = gradient;
2725
+ }
2726
+ let bestX = 0;
2727
+ let bestScore = 0;
2728
+ const minCandidateX = 30;
2729
+ const maxCandidateX = width - puzzleWidth - 20;
2730
+ for (let candidateX = minCandidateX; candidateX <= maxCandidateX; candidateX++) {
2731
+ let leftMax = 0;
2732
+ for (let dx = -2; dx <= 2; dx++) {
2733
+ const value = columnGradients[candidateX + pieceMinX + dx] || 0;
2734
+ if (value > leftMax) leftMax = value;
2735
+ }
2736
+ let rightMax = 0;
2737
+ for (let dx = -3; dx <= 1; dx++) {
2738
+ const value = columnGradients[candidateX + pieceMaxX + dx] || 0;
2739
+ if (value > rightMax) rightMax = value;
2740
+ }
2741
+ const score = Math.sqrt(leftMax * rightMax);
2742
+ if (score > bestScore) {
2743
+ bestScore = score;
2744
+ bestX = candidateX;
2745
+ }
2746
+ }
2747
+ if (bestScore <= 0) {
2748
+ return { ok: false, reason: "no matching hole edge" };
2749
+ }
2750
+ return {
2751
+ ok: true,
2752
+ offsetX: bestX - pieceMinX,
2753
+ naturalWidth: width
2754
+ };
2755
+ } catch (error) {
2756
+ return {
2757
+ ok: false,
2758
+ reason: error instanceof Error ? error.message : String(error)
2759
+ };
2760
+ }
2761
+ };
2762
+ return new Promise((resolve) => {
2763
+ if (background.complete && piece.complete) {
2764
+ resolve(compute());
2765
+ return;
2766
+ }
2767
+ let settled = false;
2768
+ const finish = () => {
2769
+ if (settled) return;
2770
+ settled = true;
2771
+ resolve(compute());
2772
+ };
2773
+ const fail = () => {
2774
+ if (settled) return;
2775
+ settled = true;
2776
+ resolve({ ok: false, reason: "puzzle image load error" });
2777
+ };
2778
+ background.addEventListener("load", finish, { once: true });
2779
+ piece.addEventListener("load", finish, { once: true });
2780
+ background.addEventListener("error", fail, { once: true });
2781
+ piece.addEventListener("error", fail, { once: true });
2782
+ setTimeout(() => {
2783
+ if (settled) return;
2784
+ settled = true;
2785
+ resolve({ ok: false, reason: "puzzle image load timeout" });
2786
+ }, 2e3);
2787
+ });
2788
+ });
2789
+ }
2790
+ async function solveAliyunWafCaptcha(page, options = {}) {
2791
+ const waitForMs = Math.max(0, options.waitForMs ?? 0);
2792
+ const maxAttempts = Math.max(
2793
+ 1,
2794
+ Math.min(5, options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS)
2795
+ );
2796
+ const retryDelayMs = Math.max(
2797
+ 0,
2798
+ options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS
2799
+ );
2800
+ const settleMs = Math.max(0, options.settleMs ?? DEFAULT_SETTLE_MS);
2801
+ const sliderTimeoutMs = Math.max(
2802
+ 500,
2803
+ options.sliderTimeoutMs ?? DEFAULT_SLIDER_TIMEOUT_MS
2804
+ );
2805
+ const detected = await findVisibleLocatorWithin(
2806
+ page,
2807
+ ALIYUN_WAF_BLOCK_SELECTORS,
2808
+ waitForMs
2809
+ );
2810
+ if (!detected) return false;
2811
+ return withCaptchaMouseLock(async () => {
2812
+ const block = detected.locator;
2813
+ if (!await isVisible(block)) return false;
2814
+ logBaxiaCaptcha("aliyun_detected", { selector: detected.selector });
2815
+ let lastReason = "unknown";
2816
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
2817
+ try {
2818
+ const offset = await computeAliyunPuzzleOffset(page);
2819
+ if (!offset.ok || typeof offset.offsetX !== "number" || typeof offset.naturalWidth !== "number" || offset.naturalWidth <= 0) {
2820
+ lastReason = offset.reason || "offset_unavailable";
2821
+ logBaxiaCaptcha("aliyun_offset_failed", {
2822
+ attempt,
2823
+ reason: lastReason
2824
+ });
2825
+ } else {
2826
+ const slider = page.locator(ALIYUN_PUZZLE_SLIDER_SELECTOR).first();
2827
+ const track = page.locator(ALIYUN_PUZZLE_TRACK_SELECTOR).first();
2828
+ await slider.waitFor({ state: "visible", timeout: sliderTimeoutMs });
2829
+ const [sliderBox, trackBox] = await Promise.all([
2830
+ slider.boundingBox(),
2831
+ track.boundingBox()
2832
+ ]);
2833
+ if (!sliderBox || !trackBox || trackBox.width <= 0) {
2834
+ lastReason = "bounds_unavailable";
2835
+ logBaxiaCaptcha("aliyun_offset_failed", {
2836
+ attempt,
2837
+ reason: lastReason
2838
+ });
2839
+ } else {
2840
+ const scale = trackBox.width / offset.naturalWidth;
2841
+ const dragDistance = Math.round(offset.offsetX * scale);
2842
+ logBaxiaCaptcha("aliyun_geometry", {
2843
+ attempt,
2844
+ offset: offset.offsetX,
2845
+ scale: Number(scale.toFixed(2)),
2846
+ distance: dragDistance
2847
+ });
2848
+ if (dragDistance <= 0) {
2849
+ lastReason = "non_positive_distance";
2850
+ } else {
2851
+ const startX = sliderBox.x + sliderBox.width / 2;
2852
+ const startY = sliderBox.y + sliderBox.height / 2;
2853
+ await humanDrag(
2854
+ page,
2855
+ startX,
2856
+ startY,
2857
+ startX + dragDistance,
2858
+ startY
2859
+ );
2860
+ if (await waitForHidden(block, settleMs)) {
2861
+ logBaxiaCaptcha(
2862
+ "aliyun_solve_succeeded",
2863
+ { attempt, distance: dragDistance },
2864
+ true
2865
+ );
2866
+ return true;
2867
+ }
2868
+ lastReason = "not_solved";
2869
+ }
2870
+ }
2871
+ }
2872
+ } catch (error) {
2873
+ lastReason = error instanceof Error ? error.name : "UnknownError";
2874
+ logBaxiaCaptcha("aliyun_offset_failed", {
2875
+ attempt,
2876
+ error: lastReason,
2877
+ detail: sanitizeCaptchaErrorDetail(error)
2878
+ });
2879
+ }
2880
+ if (attempt < maxAttempts && retryDelayMs > 0) {
2881
+ await sleep(retryDelayMs);
2882
+ }
2883
+ }
2884
+ logBaxiaCaptcha(
2885
+ "aliyun_solve_failed",
2886
+ { attempts: maxAttempts, reason: lastReason },
2887
+ true
2888
+ );
2889
+ return false;
2890
+ });
2891
+ }
2892
+ async function solveVisibleCaptcha(page, options = {}) {
2893
+ if (typeof page.isClosed === "function" && page.isClosed()) return false;
2894
+ const totalWaitMs = Math.max(0, options.waitForMs ?? 0);
2895
+ const aliyunWaitMs = Math.min(totalWaitMs, ALIYUN_PROBE_MAX_WAIT_MS);
2896
+ const startedAt = Date.now();
2897
+ if (await solveAliyunWafCaptcha(page, { ...options, waitForMs: aliyunWaitMs })) {
2898
+ return true;
2899
+ }
2900
+ const remainingWaitMs = Math.max(
2901
+ 0,
2902
+ totalWaitMs - (Date.now() - startedAt)
2903
+ );
2904
+ return solveBaxiaCaptcha(page, { ...options, waitForMs: remainingWaitMs });
2905
+ }
2615
2906
  async function isVisible(locator) {
2616
2907
  return locator.isVisible().catch(() => false);
2617
2908
  }
@@ -2854,7 +3145,7 @@ async function solveBaxiaCaptchaUnlocked(page, options = {}) {
2854
3145
  );
2855
3146
  return false;
2856
3147
  }
2857
- var BAXIA_DIALOG_SELECTOR, BAXIA_CONTENT_SELECTOR, CAPTCHA_EVENT_EMOJI, captchaDebugEnabled, BAXIA_IFRAME_SELECTORS, BAXIA_DOCUMENT_SELECTORS, BAXIA_IFRAME_SELECTOR, BAXIA_SLIDER_SELECTOR, BAXIA_TRACK_SELECTOR, BAXIA_SUCCESS_SELECTOR, BAXIA_RELOAD_SELECTOR, DEFAULT_MAX_ATTEMPTS, DEFAULT_RETRY_DELAY_MS, DEFAULT_SETTLE_MS, DEFAULT_SLIDER_TIMEOUT_MS, captchaMouseLock;
3148
+ var BAXIA_DIALOG_SELECTOR, BAXIA_CONTENT_SELECTOR, CAPTCHA_EVENT_EMOJI, captchaDebugEnabled, BAXIA_IFRAME_SELECTORS, BAXIA_DOCUMENT_SELECTORS, BAXIA_IFRAME_SELECTOR, BAXIA_SLIDER_SELECTOR, BAXIA_TRACK_SELECTOR, BAXIA_SUCCESS_SELECTOR, BAXIA_RELOAD_SELECTOR, DEFAULT_MAX_ATTEMPTS, DEFAULT_RETRY_DELAY_MS, DEFAULT_SETTLE_MS, DEFAULT_SLIDER_TIMEOUT_MS, ALIYUN_WAF_CAPTCHA_SELECTOR, ALIYUN_WAF_CAPTCHA_WIDGET, ALIYUN_WAF_BLOCK_SELECTORS, ALIYUN_PUZZLE_SLIDER_SELECTOR, ALIYUN_PUZZLE_TRACK_SELECTOR, ALIYUN_PROBE_MAX_WAIT_MS, captchaMouseLock;
2858
3149
  var init_captcha_solver = __esm({
2859
3150
  "src/services/captcha-solver.ts"() {
2860
3151
  "use strict";
@@ -2880,14 +3171,20 @@ var init_captcha_solver = __esm({
2880
3171
  solve_failed: "\u274C",
2881
3172
  recovery_succeeded: "\u2705",
2882
3173
  recovery_not_solved: "\u26A0\uFE0F",
2883
- recovery_failed: "\u274C"
3174
+ recovery_failed: "\u274C",
3175
+ aliyun_detected: "\u{1F9E9}",
3176
+ aliyun_offset_failed: "\u{1F4D0}",
3177
+ aliyun_geometry: "\u{1F4D0}",
3178
+ aliyun_solve_succeeded: "\u2705",
3179
+ aliyun_solve_failed: "\u274C"
2884
3180
  };
2885
3181
  captchaDebugEnabled = process.env.CAPTCHA_DEBUG === "true";
2886
3182
  BAXIA_IFRAME_SELECTORS = [
2887
3183
  `${BAXIA_DIALOG_SELECTOR} ${BAXIA_CONTENT_SELECTOR} iframe`,
2888
3184
  `${BAXIA_CONTENT_SELECTOR} iframe`,
2889
3185
  "iframe#baxia-dialog-content",
2890
- 'iframe[src*="_____tmd_____/punish"]'
3186
+ 'iframe[src*="_____tmd_____/punish"]',
3187
+ 'iframe[src*="nocaptcha"]'
2891
3188
  ];
2892
3189
  BAXIA_DOCUMENT_SELECTORS = [
2893
3190
  "#nocaptcha",
@@ -2895,14 +3192,23 @@ var init_captcha_solver = __esm({
2895
3192
  "#baxia-punish"
2896
3193
  ];
2897
3194
  BAXIA_IFRAME_SELECTOR = BAXIA_IFRAME_SELECTORS.join(", ");
2898
- BAXIA_SLIDER_SELECTOR = "#nc_1_n1z, .nc_1_n1z, .btn_slide, .nc_wrapper .btn_slide, ._nc .btn_slide, .nc-container .btn_slide";
2899
- BAXIA_TRACK_SELECTOR = "#nc_1_n1t, .nc_scale, .nc_wrapper .nc_scale, ._nc .nc_scale, .nc-container .nc_scale";
3195
+ BAXIA_SLIDER_SELECTOR = '#nc_1_n1z, .nc_1_n1z, .btn_slide, .nc_iconfont.btn_slide, span[id*="_n1z"], .nc_wrapper .btn_slide, ._nc .btn_slide, .nc-container .btn_slide';
3196
+ BAXIA_TRACK_SELECTOR = '#nc_1_n1t, .nc_scale, span[id*="_n1t"], .nc_wrapper .nc_scale, ._nc .nc_scale, .nc-container .nc_scale';
2900
3197
  BAXIA_SUCCESS_SELECTOR = '.btn_ok, .nc_ok, .nc_success, .nc_result, .nc_wrapper.nc-success, .nc_wrapper.success, [data-nc-lang="SUCCESS"], [data-nc-lang="success"], #nc-loading-circle';
2901
3198
  BAXIA_RELOAD_SELECTOR = '#nc_1_refresh1, .errloading a, .nc-container .errloading a, .btn_refresh, .clickCaptcha_text .btn_refresh, [data-nc-lang="REFRESH"], a[id*="refresh"]';
2902
3199
  DEFAULT_MAX_ATTEMPTS = 3;
2903
3200
  DEFAULT_RETRY_DELAY_MS = 1e3;
2904
3201
  DEFAULT_SETTLE_MS = 2e3;
2905
3202
  DEFAULT_SLIDER_TIMEOUT_MS = 8e3;
3203
+ ALIYUN_WAF_CAPTCHA_SELECTOR = "#waf_nc_block";
3204
+ ALIYUN_WAF_CAPTCHA_WIDGET = "#aliyunCaptcha-window-embed";
3205
+ ALIYUN_WAF_BLOCK_SELECTORS = [
3206
+ ALIYUN_WAF_CAPTCHA_SELECTOR,
3207
+ ALIYUN_WAF_CAPTCHA_WIDGET
3208
+ ];
3209
+ ALIYUN_PUZZLE_SLIDER_SELECTOR = "#aliyunCaptcha-sliding-slider";
3210
+ ALIYUN_PUZZLE_TRACK_SELECTOR = "#aliyunCaptcha-sliding-body";
3211
+ ALIYUN_PROBE_MAX_WAIT_MS = 2e3;
2906
3212
  captchaMouseLock = Promise.resolve();
2907
3213
  }
2908
3214
  });
@@ -2993,7 +3299,15 @@ function updateQwenWebVersion(version) {
2993
3299
  function getQwenWebVersion() {
2994
3300
  return dynamicWebVersion || config.qwen.webVersion;
2995
3301
  }
2996
- var dynamicWebVersion, QWEN_WEB_VERSION, DEFAULT_QWEN_USER_AGENT, QWEN_TIMEZONE_HEADER;
3302
+ function updateQwenBxVersion(version) {
3303
+ if (version && typeof version === "string" && /^\d+\.\d+\.\d+/.test(version)) {
3304
+ dynamicBxVersion = version.trim();
3305
+ }
3306
+ }
3307
+ function getQwenBxVersion() {
3308
+ return dynamicBxVersion || config.auth.bxV;
3309
+ }
3310
+ var dynamicWebVersion, dynamicBxVersion, QWEN_WEB_VERSION, DEFAULT_QWEN_USER_AGENT, QWEN_TIMEZONE_HEADER;
2997
3311
  var init_qwen_headers = __esm({
2998
3312
  "src/services/qwen-headers.ts"() {
2999
3313
  "use strict";
@@ -3002,6 +3316,7 @@ var init_qwen_headers = __esm({
3002
3316
  init_fingerprint();
3003
3317
  init_timezone();
3004
3318
  dynamicWebVersion = null;
3319
+ dynamicBxVersion = null;
3005
3320
  QWEN_WEB_VERSION = config.qwen.webVersion;
3006
3321
  DEFAULT_QWEN_USER_AGENT = getDefaultQwenUserAgent(151);
3007
3322
  QWEN_TIMEZONE_HEADER = (/* @__PURE__ */ new Date()).toString().split(" (")[0];
@@ -3615,11 +3930,12 @@ async function getOrLaunchSharedBrowser(browserType = "chromium", headless = con
3615
3930
  async function clearVisibleChallenge(page) {
3616
3931
  if (page.isClosed()) return;
3617
3932
  if (config.captcha.enabled) {
3618
- await solveBaxiaCaptcha(page, {
3933
+ await solveVisibleCaptcha(page, {
3619
3934
  waitForMs: 0,
3620
3935
  maxAttempts: config.captcha.maxAttempts,
3621
3936
  retryDelayMs: config.captcha.retryDelayMs,
3622
- settleMs: config.captcha.settleMs
3937
+ settleMs: config.captcha.settleMs,
3938
+ sliderTimeoutMs: config.captcha.sliderTimeoutMs
3623
3939
  }).catch(() => false);
3624
3940
  }
3625
3941
  try {
@@ -4232,6 +4548,7 @@ async function getBasicHeaders(accountId) {
4232
4548
  mobile = data.mobile ? "?1" : "?0";
4233
4549
  }
4234
4550
  let bundleVersion = null;
4551
+ let baxiaVersion = null;
4235
4552
  try {
4236
4553
  const el = document.querySelector('link[href*="qwen-chat-fe"], script[src*="qwen-chat-fe"], img[src*="qwen-chat-fe"]');
4237
4554
  const src = el ? el.getAttribute("href") || el.getAttribute("src") || "" : "";
@@ -4239,7 +4556,14 @@ async function getBasicHeaders(accountId) {
4239
4556
  if (match) bundleVersion = match[1];
4240
4557
  } catch {
4241
4558
  }
4242
- return { ua, secChUa, platform, mobile, bundleVersion };
4559
+ try {
4560
+ const baxia = window.baxiaCommon;
4561
+ if (typeof baxia?.version === "string") {
4562
+ baxiaVersion = baxia.version;
4563
+ }
4564
+ } catch {
4565
+ }
4566
+ return { ua, secChUa, platform, mobile, bundleVersion, baxiaVersion };
4243
4567
  }),
4244
4568
  config.timeouts.page,
4245
4569
  `User-agent lookup timed out for ${accountId}`
@@ -4248,6 +4572,9 @@ async function getBasicHeaders(accountId) {
4248
4572
  if (nav.bundleVersion) {
4249
4573
  updateQwenWebVersion(nav.bundleVersion);
4250
4574
  }
4575
+ if (nav.baxiaVersion) {
4576
+ updateQwenBxVersion(nav.baxiaVersion);
4577
+ }
4251
4578
  cachedUserAgents.set(accountId, userAgent);
4252
4579
  const hints = getHeaderCache(accountId).headers;
4253
4580
  clientHints = {
@@ -4279,7 +4606,7 @@ async function getBasicHeaders(accountId) {
4279
4606
  markAccountHeadersReady(accountId);
4280
4607
  const bxUa2 = cache.headers["bx-ua"];
4281
4608
  const bxUmidtoken2 = cache.headers["bx-umidtoken"];
4282
- const bxV2 = cache.headers["bx-v"] || "2.5.37";
4609
+ const bxV2 = cache.headers["bx-v"] || getQwenBxVersion();
4283
4610
  const cookie2 = await getCookies(accountId);
4284
4611
  return { cookie: cookie2, userAgent, bxV: bxV2, bxUa: bxUa2, bxUmidtoken: bxUmidtoken2, ...clientHints };
4285
4612
  }
@@ -4290,7 +4617,7 @@ async function getBasicHeaders(accountId) {
4290
4617
  cookieCaches.set(accountId, { cookie: cookie2, timestamp: Date.now() });
4291
4618
  const bxUa2 = cache.headers["bx-ua"];
4292
4619
  const bxUmidtoken2 = cache.headers["bx-umidtoken"];
4293
- const bxV2 = cache.headers["bx-v"] || "2.5.37";
4620
+ const bxV2 = cache.headers["bx-v"] || getQwenBxVersion();
4294
4621
  cache.lastRefresh = Date.now();
4295
4622
  markAccountHeadersReady(accountId);
4296
4623
  console.log(
@@ -4365,6 +4692,9 @@ async function getBasicHeaders(accountId) {
4365
4692
  if (persisted.version) {
4366
4693
  updateQwenWebVersion(persisted.version);
4367
4694
  }
4695
+ if (persisted.bxV) {
4696
+ updateQwenBxVersion(persisted.bxV);
4697
+ }
4368
4698
  cache.lastRefresh = persisted.capturedAt;
4369
4699
  markAccountHeadersReady(accountId);
4370
4700
  }
@@ -4392,7 +4722,7 @@ async function getBasicHeaders(accountId) {
4392
4722
  markAccountHeadersReady(accountId);
4393
4723
  const bxUa = cache.headers["bx-ua"];
4394
4724
  const bxUmidtoken = cache.headers["bx-umidtoken"];
4395
- const bxV = cache.headers["bx-v"] || "2.5.37";
4725
+ const bxV = cache.headers["bx-v"] || getQwenBxVersion();
4396
4726
  cookieCaches.delete(accountId);
4397
4727
  const cookie = await getCookies(accountId, true);
4398
4728
  if (cache.headers) {
@@ -4637,6 +4967,9 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
4637
4967
  if (persisted.version) {
4638
4968
  updateQwenWebVersion(persisted.version);
4639
4969
  }
4970
+ if (persisted.bxV) {
4971
+ updateQwenBxVersion(persisted.bxV);
4972
+ }
4640
4973
  cache.lastRefresh = persisted.capturedAt;
4641
4974
  markAccountHeadersReady(account.id);
4642
4975
  restoredFromDb = true;
@@ -4986,7 +5319,7 @@ async function startEmailOtpLogin(email, options = {}) {
4986
5319
  {
4987
5320
  email: normalizedEmail,
4988
5321
  requestId,
4989
- version: getQwenWebVersion() || "0.3.26",
5322
+ version: getQwenWebVersion(),
4990
5323
  timezone: formatAsciiTimezone()
4991
5324
  }
4992
5325
  ).catch((err) => ({ ok: false, error: err?.message || String(err) }));
@@ -5081,7 +5414,7 @@ async function verifyEmailOtpLogin(sessionId, code) {
5081
5414
  email: session.email,
5082
5415
  code: cleanCode,
5083
5416
  requestId,
5084
- version: getQwenWebVersion() || "0.3.26",
5417
+ version: getQwenWebVersion(),
5085
5418
  timezone: formatAsciiTimezone()
5086
5419
  }
5087
5420
  ).catch((err) => ({ ok: false, error: err?.message || String(err) }));
@@ -5128,8 +5461,8 @@ async function verifyEmailOtpLogin(sessionId, code) {
5128
5461
  saveAuthSession2(session.accountId, {
5129
5462
  cookie: `token=${accessToken}`,
5130
5463
  userAgent: session.fingerprint.userAgent,
5131
- bxV: "2.5.37",
5132
- version: getQwenWebVersion() || "0.3.26",
5464
+ bxV: getQwenBxVersion(),
5465
+ version: getQwenWebVersion(),
5133
5466
  userId: userId || void 0,
5134
5467
  tokenExpiresAt: exp || void 0,
5135
5468
  refreshToken: refreshToken || void 0,
@@ -5239,7 +5572,7 @@ async function loginToQwen(accountId, email, password) {
5239
5572
  saveAuthSession2(accountId, {
5240
5573
  cookie: cookieStr,
5241
5574
  userAgent: cache.headers["user-agent"] || "",
5242
- bxV: cache.headers["bx-v"] || "2.5.37",
5575
+ bxV: cache.headers["bx-v"] || getQwenBxVersion(),
5243
5576
  bxUa: cache.headers["bx-ua"] || "",
5244
5577
  bxUmidtoken: cache.headers["bx-umidtoken"] || "",
5245
5578
  secChUa: cache.headers["sec-ch-ua"] || void 0,
@@ -5311,7 +5644,7 @@ async function loginToQwen(accountId, email, password) {
5311
5644
  saveAuthSession2(accountId, {
5312
5645
  cookie: cookieStr,
5313
5646
  userAgent: cache.headers["user-agent"] || "",
5314
- bxV: cache.headers["bx-v"] || "2.5.37",
5647
+ bxV: cache.headers["bx-v"] || getQwenBxVersion(),
5315
5648
  bxUa: cache.headers["bx-ua"] || "",
5316
5649
  bxUmidtoken: cache.headers["bx-umidtoken"] || "",
5317
5650
  secChUa: cache.headers["sec-ch-ua"] || void 0,
@@ -5382,7 +5715,7 @@ async function loginViaApi(page, email, password) {
5382
5715
  }
5383
5716
  const signinUrl = "https://auth.qwen.ai/api/v2/auths/signin";
5384
5717
  const requestId = crypto3.randomUUID();
5385
- const webVersion = getQwenWebVersion() || "0.3.26";
5718
+ const webVersion = getQwenWebVersion();
5386
5719
  const evalRes = await page.evaluate(
5387
5720
  async ({ email: email2, password: password2, signinUrl: signinUrl2, requestId: requestId2, tz, version }) => {
5388
5721
  try {
@@ -5554,6 +5887,15 @@ async function loginViaUi(page, email, password) {
5554
5887
  if (!page.url().includes("/auth") && await isPageLoggedIn(page, 3e3).catch(() => false)) {
5555
5888
  return { success: true };
5556
5889
  }
5890
+ if (config.captcha.enabled) {
5891
+ await solveVisibleCaptcha(page, {
5892
+ waitForMs: 1500,
5893
+ maxAttempts: config.captcha.maxAttempts,
5894
+ retryDelayMs: config.captcha.retryDelayMs,
5895
+ settleMs: config.captcha.settleMs,
5896
+ sliderTimeoutMs: config.captcha.sliderTimeoutMs
5897
+ }).catch(() => false);
5898
+ }
5557
5899
  const emailSelector = [
5558
5900
  'input[type="email"]',
5559
5901
  'input[name="email"]',
@@ -5709,10 +6051,11 @@ async function loginViaUi(page, email, password) {
5709
6051
  while (Date.now() < postSubmitDeadline) {
5710
6052
  if (page.isClosed()) break;
5711
6053
  if (config.captcha.enabled) {
5712
- await solveBaxiaCaptcha(page, {
6054
+ await solveVisibleCaptcha(page, {
5713
6055
  waitForMs: 1500,
5714
6056
  maxAttempts: config.captcha.maxAttempts,
5715
- retryDelayMs: config.captcha.retryDelayMs
6057
+ retryDelayMs: config.captcha.retryDelayMs,
6058
+ sliderTimeoutMs: config.captcha.sliderTimeoutMs
5716
6059
  }).catch(() => {
5717
6060
  });
5718
6061
  }
@@ -5835,7 +6178,7 @@ async function refreshAccountToken(accountId) {
5835
6178
  }
5836
6179
  if (refreshToken) {
5837
6180
  try {
5838
- const webVersion = getQwenWebVersion() || "0.3.26";
6181
+ const webVersion = getQwenWebVersion();
5839
6182
  const refreshResult = await page.evaluate(
5840
6183
  async ({ rTok, tz, version }) => {
5841
6184
  try {
@@ -5900,7 +6243,7 @@ async function refreshAccountToken(accountId) {
5900
6243
  saveAuthSession2(accountId, {
5901
6244
  cookie: cookieStr,
5902
6245
  userAgent: cache.headers["user-agent"] || session?.userAgent || "",
5903
- bxV: cache.headers["bx-v"] || session?.bxV || "2.5.37",
6246
+ bxV: cache.headers["bx-v"] || session?.bxV || getQwenBxVersion(),
5904
6247
  bxUa: cache.headers["bx-ua"] || session?.bxUa || "",
5905
6248
  bxUmidtoken: cache.headers["bx-umidtoken"] || session?.bxUmidtoken || "",
5906
6249
  secChUa: cache.headers["sec-ch-ua"] || session?.secChUa,
@@ -5935,7 +6278,7 @@ async function refreshAccountToken(accountId) {
5935
6278
  saveAuthSession2(accountId, {
5936
6279
  cookie: cookieStr,
5937
6280
  userAgent: cache.headers["user-agent"] || session?.userAgent || "",
5938
- bxV: cache.headers["bx-v"] || session?.bxV || "2.5.37",
6281
+ bxV: cache.headers["bx-v"] || session?.bxV || getQwenBxVersion(),
5939
6282
  bxUa: cache.headers["bx-ua"] || session?.bxUa || "",
5940
6283
  bxUmidtoken: cache.headers["bx-umidtoken"] || session?.bxUmidtoken || "",
5941
6284
  secChUa: cache.headers["sec-ch-ua"] || session?.secChUa,
@@ -6083,7 +6426,7 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
6083
6426
  cookie: reqHeaders["cookie"] || "",
6084
6427
  "bx-ua": reqHeaders["bx-ua"] || "",
6085
6428
  "bx-umidtoken": reqHeaders["bx-umidtoken"] || "",
6086
- "bx-v": reqHeaders["bx-v"] || "2.5.37",
6429
+ "bx-v": reqHeaders["bx-v"] || getQwenBxVersion(),
6087
6430
  "user-agent": reqHeaders["user-agent"] || "",
6088
6431
  "x-request-id": reqHeaders["x-request-id"] || "",
6089
6432
  "version": reqHeaders["version"] || "",
@@ -6115,6 +6458,9 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
6115
6458
  if (capturedHeaders["version"]) {
6116
6459
  updateQwenWebVersion(capturedHeaders["version"]);
6117
6460
  }
6461
+ if (capturedHeaders["bx-v"]) {
6462
+ updateQwenBxVersion(capturedHeaders["bx-v"]);
6463
+ }
6118
6464
  markAccountHeadersReady(accountId);
6119
6465
  cache.lastRefresh = Date.now();
6120
6466
  cookieCaches.delete(accountId);
@@ -6572,7 +6918,7 @@ async function refreshHeadersInternal(accountId, timeoutMs = config.timeouts.hea
6572
6918
  saveAuthSession2(accountId, {
6573
6919
  cookie: cookieStr,
6574
6920
  userAgent: cache.headers["user-agent"] || "",
6575
- bxV: cache.headers["bx-v"] || "2.5.37",
6921
+ bxV: cache.headers["bx-v"] || getQwenBxVersion(),
6576
6922
  bxUa: cache.headers["bx-ua"] || "",
6577
6923
  bxUmidtoken: cache.headers["bx-umidtoken"] || "",
6578
6924
  secChUa: cache.headers["sec-ch-ua"] || void 0,