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.
@@ -997,7 +997,7 @@ var init_config = __esm({
997
997
  // Version header on Qwen API requests = the deployed web bundle version
998
998
  // (fallback when dynamic DOM detection is not yet completed).
999
999
  // Override via env when Qwen ships a new bundle.
1000
- QWEN_WEB_VERSION: z.string().default("0.3.26"),
1000
+ QWEN_WEB_VERSION: z.string().default("0.3.43"),
1001
1001
  // Controls bx-ua/bx-umidtoken injection on the GENERAL API paths
1002
1002
  // (chats/new, settings): those work without them (live-probed). The
1003
1003
  // completions path is the exception — the 0.2.86 HAR shows the real
@@ -1040,6 +1040,7 @@ var init_config = __esm({
1040
1040
  CAPTCHA_SOLVER_ENABLED: z.string().default("true"),
1041
1041
  CAPTCHA_SOLVER_MAX_ATTEMPTS: z.string().default("3"),
1042
1042
  CAPTCHA_SOLVER_TIMEOUT_MS: z.string().default("15000"),
1043
+ CAPTCHA_SLIDER_TIMEOUT_MS: z.string().default("8000"),
1043
1044
  CAPTCHA_SOLVER_RETRY_DELAY_MS: z.string().default("1000"),
1044
1045
  CAPTCHA_SOLVER_SETTLE_MS: z.string().default("2000"),
1045
1046
  CAPTCHA_ACCOUNT_COOLDOWN_MS: z.string().default("120000"),
@@ -1191,6 +1192,8 @@ var init_config = __esm({
1191
1192
  enabled: env.CAPTCHA_SOLVER_ENABLED === "true",
1192
1193
  maxAttempts: Math.max(1, Math.min(5, parseInt(env.CAPTCHA_SOLVER_MAX_ATTEMPTS))),
1193
1194
  timeoutMs: Math.max(0, parseInt(env.CAPTCHA_SOLVER_TIMEOUT_MS)),
1195
+ /** Max wait for a challenge slider to become visible (slow WAF renders). */
1196
+ sliderTimeoutMs: Math.max(500, parseInt(env.CAPTCHA_SLIDER_TIMEOUT_MS)),
1194
1197
  retryDelayMs: Math.max(0, parseInt(env.CAPTCHA_SOLVER_RETRY_DELAY_MS)),
1195
1198
  settleMs: Math.max(0, parseInt(env.CAPTCHA_SOLVER_SETTLE_MS)),
1196
1199
  /** Rest an account whose challenge could not be cleared before reusing it. */
@@ -2368,6 +2371,294 @@ function logBaxiaCaptcha(event, fields = {}, important = false) {
2368
2371
  console.log(line);
2369
2372
  }
2370
2373
  }
2374
+ async function findVisibleLocatorWithin(page, selectors, timeoutMs) {
2375
+ const deadline = Date.now() + Math.max(0, timeoutMs);
2376
+ while (true) {
2377
+ const found = await findVisibleLocator(page, selectors);
2378
+ if (found) return found;
2379
+ if (Date.now() >= deadline) return null;
2380
+ await sleep(Math.min(150, Math.max(1, deadline - Date.now())));
2381
+ }
2382
+ }
2383
+ async function waitForHidden(locator, timeoutMs) {
2384
+ const deadline = Date.now() + Math.max(0, timeoutMs);
2385
+ while (true) {
2386
+ if (!await isVisible(locator)) return true;
2387
+ if (Date.now() >= deadline) return false;
2388
+ await sleep(Math.min(100, Math.max(1, deadline - Date.now())));
2389
+ }
2390
+ }
2391
+ async function computeAliyunPuzzleOffset(page) {
2392
+ return page.evaluate(() => {
2393
+ const background = document.querySelector(
2394
+ "#aliyunCaptcha-img"
2395
+ );
2396
+ const piece = document.querySelector(
2397
+ "#aliyunCaptcha-puzzle"
2398
+ );
2399
+ if (!background || !piece) {
2400
+ return Promise.resolve({ ok: false, reason: "missing puzzle images" });
2401
+ }
2402
+ const compute = () => {
2403
+ try {
2404
+ const width = background.naturalWidth;
2405
+ const height = background.naturalHeight;
2406
+ const pieceWidth = piece.naturalWidth;
2407
+ const pieceHeight = piece.naturalHeight;
2408
+ if (!width || !height || !pieceWidth || !pieceHeight) {
2409
+ return { ok: false, reason: "image dimensions unavailable" };
2410
+ }
2411
+ const backgroundCanvas = document.createElement("canvas");
2412
+ backgroundCanvas.id = "captcha-solver-canvas";
2413
+ backgroundCanvas.width = width;
2414
+ backgroundCanvas.height = height;
2415
+ const backgroundContext = backgroundCanvas.getContext("2d");
2416
+ if (!backgroundContext) {
2417
+ return { ok: false, reason: "no background context" };
2418
+ }
2419
+ const pieceCanvas = document.createElement("canvas");
2420
+ pieceCanvas.id = "captcha-solver-canvas";
2421
+ pieceCanvas.width = pieceWidth;
2422
+ pieceCanvas.height = pieceHeight;
2423
+ const pieceContext = pieceCanvas.getContext("2d");
2424
+ if (!pieceContext) {
2425
+ return { ok: false, reason: "no piece context" };
2426
+ }
2427
+ try {
2428
+ backgroundContext.drawImage(background, 0, 0);
2429
+ } catch {
2430
+ return { ok: false, reason: "background canvas tainted" };
2431
+ }
2432
+ try {
2433
+ pieceContext.drawImage(piece, 0, 0);
2434
+ } catch {
2435
+ return { ok: false, reason: "puzzle canvas tainted" };
2436
+ }
2437
+ const backgroundData = backgroundContext.getImageData(
2438
+ 0,
2439
+ 0,
2440
+ width,
2441
+ height
2442
+ ).data;
2443
+ const pieceData = pieceContext.getImageData(
2444
+ 0,
2445
+ 0,
2446
+ pieceWidth,
2447
+ pieceHeight
2448
+ ).data;
2449
+ let pieceMinX = pieceWidth;
2450
+ let pieceMaxX = -1;
2451
+ let pieceMinY = pieceHeight;
2452
+ let pieceMaxY = -1;
2453
+ for (let y = 0; y < pieceHeight; y++) {
2454
+ for (let x = 0; x < pieceWidth; x++) {
2455
+ if (pieceData[(y * pieceWidth + x) * 4 + 3] > 100) {
2456
+ if (x < pieceMinX) pieceMinX = x;
2457
+ if (x > pieceMaxX) pieceMaxX = x;
2458
+ if (y < pieceMinY) pieceMinY = y;
2459
+ if (y > pieceMaxY) pieceMaxY = y;
2460
+ }
2461
+ }
2462
+ }
2463
+ const puzzleWidth = pieceMaxX - pieceMinX + 1;
2464
+ if (puzzleWidth <= 0) {
2465
+ return { ok: false, reason: "empty puzzle piece" };
2466
+ }
2467
+ const yStart = Math.max(1, Math.min(height - 2, pieceMinY + 5));
2468
+ const yEnd = Math.max(
2469
+ yStart,
2470
+ Math.min(height - 2, pieceMaxY - 5)
2471
+ );
2472
+ const columnGradients = new Float32Array(width);
2473
+ for (let x = 1; x < width - 1; x++) {
2474
+ let gradient = 0;
2475
+ for (let y = yStart; y <= yEnd; y++) {
2476
+ const left = (y * width + x - 1) * 4;
2477
+ const right = (y * width + x + 1) * 4;
2478
+ gradient += Math.abs(backgroundData[right] - backgroundData[left]) + Math.abs(backgroundData[right + 1] - backgroundData[left + 1]) + Math.abs(backgroundData[right + 2] - backgroundData[left + 2]);
2479
+ }
2480
+ columnGradients[x] = gradient;
2481
+ }
2482
+ let bestX = 0;
2483
+ let bestScore = 0;
2484
+ const minCandidateX = 30;
2485
+ const maxCandidateX = width - puzzleWidth - 20;
2486
+ for (let candidateX = minCandidateX; candidateX <= maxCandidateX; candidateX++) {
2487
+ let leftMax = 0;
2488
+ for (let dx = -2; dx <= 2; dx++) {
2489
+ const value = columnGradients[candidateX + pieceMinX + dx] || 0;
2490
+ if (value > leftMax) leftMax = value;
2491
+ }
2492
+ let rightMax = 0;
2493
+ for (let dx = -3; dx <= 1; dx++) {
2494
+ const value = columnGradients[candidateX + pieceMaxX + dx] || 0;
2495
+ if (value > rightMax) rightMax = value;
2496
+ }
2497
+ const score = Math.sqrt(leftMax * rightMax);
2498
+ if (score > bestScore) {
2499
+ bestScore = score;
2500
+ bestX = candidateX;
2501
+ }
2502
+ }
2503
+ if (bestScore <= 0) {
2504
+ return { ok: false, reason: "no matching hole edge" };
2505
+ }
2506
+ return {
2507
+ ok: true,
2508
+ offsetX: bestX - pieceMinX,
2509
+ naturalWidth: width
2510
+ };
2511
+ } catch (error) {
2512
+ return {
2513
+ ok: false,
2514
+ reason: error instanceof Error ? error.message : String(error)
2515
+ };
2516
+ }
2517
+ };
2518
+ return new Promise((resolve) => {
2519
+ if (background.complete && piece.complete) {
2520
+ resolve(compute());
2521
+ return;
2522
+ }
2523
+ let settled = false;
2524
+ const finish = () => {
2525
+ if (settled) return;
2526
+ settled = true;
2527
+ resolve(compute());
2528
+ };
2529
+ const fail = () => {
2530
+ if (settled) return;
2531
+ settled = true;
2532
+ resolve({ ok: false, reason: "puzzle image load error" });
2533
+ };
2534
+ background.addEventListener("load", finish, { once: true });
2535
+ piece.addEventListener("load", finish, { once: true });
2536
+ background.addEventListener("error", fail, { once: true });
2537
+ piece.addEventListener("error", fail, { once: true });
2538
+ setTimeout(() => {
2539
+ if (settled) return;
2540
+ settled = true;
2541
+ resolve({ ok: false, reason: "puzzle image load timeout" });
2542
+ }, 2e3);
2543
+ });
2544
+ });
2545
+ }
2546
+ async function solveAliyunWafCaptcha(page, options = {}) {
2547
+ const waitForMs = Math.max(0, options.waitForMs ?? 0);
2548
+ const maxAttempts = Math.max(
2549
+ 1,
2550
+ Math.min(5, options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS)
2551
+ );
2552
+ const retryDelayMs = Math.max(
2553
+ 0,
2554
+ options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS
2555
+ );
2556
+ const settleMs = Math.max(0, options.settleMs ?? DEFAULT_SETTLE_MS);
2557
+ const sliderTimeoutMs = Math.max(
2558
+ 500,
2559
+ options.sliderTimeoutMs ?? DEFAULT_SLIDER_TIMEOUT_MS
2560
+ );
2561
+ const detected = await findVisibleLocatorWithin(
2562
+ page,
2563
+ ALIYUN_WAF_BLOCK_SELECTORS,
2564
+ waitForMs
2565
+ );
2566
+ if (!detected) return false;
2567
+ return withCaptchaMouseLock(async () => {
2568
+ const block = detected.locator;
2569
+ if (!await isVisible(block)) return false;
2570
+ logBaxiaCaptcha("aliyun_detected", { selector: detected.selector });
2571
+ let lastReason = "unknown";
2572
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
2573
+ try {
2574
+ const offset = await computeAliyunPuzzleOffset(page);
2575
+ if (!offset.ok || typeof offset.offsetX !== "number" || typeof offset.naturalWidth !== "number" || offset.naturalWidth <= 0) {
2576
+ lastReason = offset.reason || "offset_unavailable";
2577
+ logBaxiaCaptcha("aliyun_offset_failed", {
2578
+ attempt,
2579
+ reason: lastReason
2580
+ });
2581
+ } else {
2582
+ const slider = page.locator(ALIYUN_PUZZLE_SLIDER_SELECTOR).first();
2583
+ const track = page.locator(ALIYUN_PUZZLE_TRACK_SELECTOR).first();
2584
+ await slider.waitFor({ state: "visible", timeout: sliderTimeoutMs });
2585
+ const [sliderBox, trackBox] = await Promise.all([
2586
+ slider.boundingBox(),
2587
+ track.boundingBox()
2588
+ ]);
2589
+ if (!sliderBox || !trackBox || trackBox.width <= 0) {
2590
+ lastReason = "bounds_unavailable";
2591
+ logBaxiaCaptcha("aliyun_offset_failed", {
2592
+ attempt,
2593
+ reason: lastReason
2594
+ });
2595
+ } else {
2596
+ const scale = trackBox.width / offset.naturalWidth;
2597
+ const dragDistance = Math.round(offset.offsetX * scale);
2598
+ logBaxiaCaptcha("aliyun_geometry", {
2599
+ attempt,
2600
+ offset: offset.offsetX,
2601
+ scale: Number(scale.toFixed(2)),
2602
+ distance: dragDistance
2603
+ });
2604
+ if (dragDistance <= 0) {
2605
+ lastReason = "non_positive_distance";
2606
+ } else {
2607
+ const startX = sliderBox.x + sliderBox.width / 2;
2608
+ const startY = sliderBox.y + sliderBox.height / 2;
2609
+ await humanDrag(
2610
+ page,
2611
+ startX,
2612
+ startY,
2613
+ startX + dragDistance,
2614
+ startY
2615
+ );
2616
+ if (await waitForHidden(block, settleMs)) {
2617
+ logBaxiaCaptcha(
2618
+ "aliyun_solve_succeeded",
2619
+ { attempt, distance: dragDistance },
2620
+ true
2621
+ );
2622
+ return true;
2623
+ }
2624
+ lastReason = "not_solved";
2625
+ }
2626
+ }
2627
+ }
2628
+ } catch (error) {
2629
+ lastReason = error instanceof Error ? error.name : "UnknownError";
2630
+ logBaxiaCaptcha("aliyun_offset_failed", {
2631
+ attempt,
2632
+ error: lastReason,
2633
+ detail: sanitizeCaptchaErrorDetail(error)
2634
+ });
2635
+ }
2636
+ if (attempt < maxAttempts && retryDelayMs > 0) {
2637
+ await sleep(retryDelayMs);
2638
+ }
2639
+ }
2640
+ logBaxiaCaptcha(
2641
+ "aliyun_solve_failed",
2642
+ { attempts: maxAttempts, reason: lastReason },
2643
+ true
2644
+ );
2645
+ return false;
2646
+ });
2647
+ }
2648
+ async function solveVisibleCaptcha(page, options = {}) {
2649
+ if (typeof page.isClosed === "function" && page.isClosed()) return false;
2650
+ const totalWaitMs = Math.max(0, options.waitForMs ?? 0);
2651
+ const aliyunWaitMs = Math.min(totalWaitMs, ALIYUN_PROBE_MAX_WAIT_MS);
2652
+ const startedAt = Date.now();
2653
+ if (await solveAliyunWafCaptcha(page, { ...options, waitForMs: aliyunWaitMs })) {
2654
+ return true;
2655
+ }
2656
+ const remainingWaitMs = Math.max(
2657
+ 0,
2658
+ totalWaitMs - (Date.now() - startedAt)
2659
+ );
2660
+ return solveBaxiaCaptcha(page, { ...options, waitForMs: remainingWaitMs });
2661
+ }
2371
2662
  async function isVisible(locator) {
2372
2663
  return locator.isVisible().catch(() => false);
2373
2664
  }
@@ -2610,7 +2901,7 @@ async function solveBaxiaCaptchaUnlocked(page, options = {}) {
2610
2901
  );
2611
2902
  return false;
2612
2903
  }
2613
- 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;
2904
+ 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;
2614
2905
  var init_captcha_solver = __esm({
2615
2906
  "src/services/captcha-solver.ts"() {
2616
2907
  "use strict";
@@ -2636,14 +2927,20 @@ var init_captcha_solver = __esm({
2636
2927
  solve_failed: "\u274C",
2637
2928
  recovery_succeeded: "\u2705",
2638
2929
  recovery_not_solved: "\u26A0\uFE0F",
2639
- recovery_failed: "\u274C"
2930
+ recovery_failed: "\u274C",
2931
+ aliyun_detected: "\u{1F9E9}",
2932
+ aliyun_offset_failed: "\u{1F4D0}",
2933
+ aliyun_geometry: "\u{1F4D0}",
2934
+ aliyun_solve_succeeded: "\u2705",
2935
+ aliyun_solve_failed: "\u274C"
2640
2936
  };
2641
2937
  captchaDebugEnabled = process.env.CAPTCHA_DEBUG === "true";
2642
2938
  BAXIA_IFRAME_SELECTORS = [
2643
2939
  `${BAXIA_DIALOG_SELECTOR} ${BAXIA_CONTENT_SELECTOR} iframe`,
2644
2940
  `${BAXIA_CONTENT_SELECTOR} iframe`,
2645
2941
  "iframe#baxia-dialog-content",
2646
- 'iframe[src*="_____tmd_____/punish"]'
2942
+ 'iframe[src*="_____tmd_____/punish"]',
2943
+ 'iframe[src*="nocaptcha"]'
2647
2944
  ];
2648
2945
  BAXIA_DOCUMENT_SELECTORS = [
2649
2946
  "#nocaptcha",
@@ -2651,14 +2948,23 @@ var init_captcha_solver = __esm({
2651
2948
  "#baxia-punish"
2652
2949
  ];
2653
2950
  BAXIA_IFRAME_SELECTOR = BAXIA_IFRAME_SELECTORS.join(", ");
2654
- BAXIA_SLIDER_SELECTOR = "#nc_1_n1z, .nc_1_n1z, .btn_slide, .nc_wrapper .btn_slide, ._nc .btn_slide, .nc-container .btn_slide";
2655
- BAXIA_TRACK_SELECTOR = "#nc_1_n1t, .nc_scale, .nc_wrapper .nc_scale, ._nc .nc_scale, .nc-container .nc_scale";
2951
+ 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';
2952
+ BAXIA_TRACK_SELECTOR = '#nc_1_n1t, .nc_scale, span[id*="_n1t"], .nc_wrapper .nc_scale, ._nc .nc_scale, .nc-container .nc_scale';
2656
2953
  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';
2657
2954
  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"]';
2658
2955
  DEFAULT_MAX_ATTEMPTS = 3;
2659
2956
  DEFAULT_RETRY_DELAY_MS = 1e3;
2660
2957
  DEFAULT_SETTLE_MS = 2e3;
2661
2958
  DEFAULT_SLIDER_TIMEOUT_MS = 8e3;
2959
+ ALIYUN_WAF_CAPTCHA_SELECTOR = "#waf_nc_block";
2960
+ ALIYUN_WAF_CAPTCHA_WIDGET = "#aliyunCaptcha-window-embed";
2961
+ ALIYUN_WAF_BLOCK_SELECTORS = [
2962
+ ALIYUN_WAF_CAPTCHA_SELECTOR,
2963
+ ALIYUN_WAF_CAPTCHA_WIDGET
2964
+ ];
2965
+ ALIYUN_PUZZLE_SLIDER_SELECTOR = "#aliyunCaptcha-sliding-slider";
2966
+ ALIYUN_PUZZLE_TRACK_SELECTOR = "#aliyunCaptcha-sliding-body";
2967
+ ALIYUN_PROBE_MAX_WAIT_MS = 2e3;
2662
2968
  captchaMouseLock = Promise.resolve();
2663
2969
  }
2664
2970
  });
@@ -2749,7 +3055,15 @@ function updateQwenWebVersion(version) {
2749
3055
  function getQwenWebVersion() {
2750
3056
  return dynamicWebVersion || config.qwen.webVersion;
2751
3057
  }
2752
- var dynamicWebVersion, QWEN_WEB_VERSION, DEFAULT_QWEN_USER_AGENT, QWEN_TIMEZONE_HEADER;
3058
+ function updateQwenBxVersion(version) {
3059
+ if (version && typeof version === "string" && /^\d+\.\d+\.\d+/.test(version)) {
3060
+ dynamicBxVersion = version.trim();
3061
+ }
3062
+ }
3063
+ function getQwenBxVersion() {
3064
+ return dynamicBxVersion || config.auth.bxV;
3065
+ }
3066
+ var dynamicWebVersion, dynamicBxVersion, QWEN_WEB_VERSION, DEFAULT_QWEN_USER_AGENT, QWEN_TIMEZONE_HEADER;
2753
3067
  var init_qwen_headers = __esm({
2754
3068
  "src/services/qwen-headers.ts"() {
2755
3069
  "use strict";
@@ -2758,6 +3072,7 @@ var init_qwen_headers = __esm({
2758
3072
  init_fingerprint();
2759
3073
  init_timezone();
2760
3074
  dynamicWebVersion = null;
3075
+ dynamicBxVersion = null;
2761
3076
  QWEN_WEB_VERSION = config.qwen.webVersion;
2762
3077
  DEFAULT_QWEN_USER_AGENT = getDefaultQwenUserAgent(151);
2763
3078
  QWEN_TIMEZONE_HEADER = (/* @__PURE__ */ new Date()).toString().split(" (")[0];
@@ -3074,11 +3389,12 @@ async function isPageLoggedIn(page, timeoutMs = SESSION_PROBE_NAVIGATION_TIMEOUT
3074
3389
  async function clearVisibleChallenge(page) {
3075
3390
  if (page.isClosed()) return;
3076
3391
  if (config.captcha.enabled) {
3077
- await solveBaxiaCaptcha(page, {
3392
+ await solveVisibleCaptcha(page, {
3078
3393
  waitForMs: 0,
3079
3394
  maxAttempts: config.captcha.maxAttempts,
3080
3395
  retryDelayMs: config.captcha.retryDelayMs,
3081
- settleMs: config.captcha.settleMs
3396
+ settleMs: config.captcha.settleMs,
3397
+ sliderTimeoutMs: config.captcha.sliderTimeoutMs
3082
3398
  }).catch(() => false);
3083
3399
  }
3084
3400
  try {
@@ -3824,6 +4140,9 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
3824
4140
  if (persisted.version) {
3825
4141
  updateQwenWebVersion(persisted.version);
3826
4142
  }
4143
+ if (persisted.bxV) {
4144
+ updateQwenBxVersion(persisted.bxV);
4145
+ }
3827
4146
  cache.lastRefresh = persisted.capturedAt;
3828
4147
  markAccountHeadersReady(account.id);
3829
4148
  restoredFromDb = true;
@@ -4020,7 +4339,7 @@ async function loginToQwen(accountId, email, password) {
4020
4339
  saveAuthSession2(accountId, {
4021
4340
  cookie: cookieStr,
4022
4341
  userAgent: cache.headers["user-agent"] || "",
4023
- bxV: cache.headers["bx-v"] || "2.5.37",
4342
+ bxV: cache.headers["bx-v"] || getQwenBxVersion(),
4024
4343
  bxUa: cache.headers["bx-ua"] || "",
4025
4344
  bxUmidtoken: cache.headers["bx-umidtoken"] || "",
4026
4345
  secChUa: cache.headers["sec-ch-ua"] || void 0,
@@ -4092,7 +4411,7 @@ async function loginToQwen(accountId, email, password) {
4092
4411
  saveAuthSession2(accountId, {
4093
4412
  cookie: cookieStr,
4094
4413
  userAgent: cache.headers["user-agent"] || "",
4095
- bxV: cache.headers["bx-v"] || "2.5.37",
4414
+ bxV: cache.headers["bx-v"] || getQwenBxVersion(),
4096
4415
  bxUa: cache.headers["bx-ua"] || "",
4097
4416
  bxUmidtoken: cache.headers["bx-umidtoken"] || "",
4098
4417
  secChUa: cache.headers["sec-ch-ua"] || void 0,
@@ -4163,7 +4482,7 @@ async function loginViaApi(page, email, password) {
4163
4482
  }
4164
4483
  const signinUrl = "https://auth.qwen.ai/api/v2/auths/signin";
4165
4484
  const requestId = crypto3.randomUUID();
4166
- const webVersion = getQwenWebVersion() || "0.3.26";
4485
+ const webVersion = getQwenWebVersion();
4167
4486
  const evalRes = await page.evaluate(
4168
4487
  async ({ email: email2, password: password2, signinUrl: signinUrl2, requestId: requestId2, tz, version }) => {
4169
4488
  try {
@@ -4335,6 +4654,15 @@ async function loginViaUi(page, email, password) {
4335
4654
  if (!page.url().includes("/auth") && await isPageLoggedIn(page, 3e3).catch(() => false)) {
4336
4655
  return { success: true };
4337
4656
  }
4657
+ if (config.captcha.enabled) {
4658
+ await solveVisibleCaptcha(page, {
4659
+ waitForMs: 1500,
4660
+ maxAttempts: config.captcha.maxAttempts,
4661
+ retryDelayMs: config.captcha.retryDelayMs,
4662
+ settleMs: config.captcha.settleMs,
4663
+ sliderTimeoutMs: config.captcha.sliderTimeoutMs
4664
+ }).catch(() => false);
4665
+ }
4338
4666
  const emailSelector = [
4339
4667
  'input[type="email"]',
4340
4668
  'input[name="email"]',
@@ -4490,10 +4818,11 @@ async function loginViaUi(page, email, password) {
4490
4818
  while (Date.now() < postSubmitDeadline) {
4491
4819
  if (page.isClosed()) break;
4492
4820
  if (config.captcha.enabled) {
4493
- await solveBaxiaCaptcha(page, {
4821
+ await solveVisibleCaptcha(page, {
4494
4822
  waitForMs: 1500,
4495
4823
  maxAttempts: config.captcha.maxAttempts,
4496
- retryDelayMs: config.captcha.retryDelayMs
4824
+ retryDelayMs: config.captcha.retryDelayMs,
4825
+ sliderTimeoutMs: config.captcha.sliderTimeoutMs
4497
4826
  }).catch(() => {
4498
4827
  });
4499
4828
  }
@@ -4616,7 +4945,7 @@ async function refreshAccountToken(accountId) {
4616
4945
  }
4617
4946
  if (refreshToken) {
4618
4947
  try {
4619
- const webVersion = getQwenWebVersion() || "0.3.26";
4948
+ const webVersion = getQwenWebVersion();
4620
4949
  const refreshResult = await page.evaluate(
4621
4950
  async ({ rTok, tz, version }) => {
4622
4951
  try {
@@ -4681,7 +5010,7 @@ async function refreshAccountToken(accountId) {
4681
5010
  saveAuthSession2(accountId, {
4682
5011
  cookie: cookieStr,
4683
5012
  userAgent: cache.headers["user-agent"] || session?.userAgent || "",
4684
- bxV: cache.headers["bx-v"] || session?.bxV || "2.5.37",
5013
+ bxV: cache.headers["bx-v"] || session?.bxV || getQwenBxVersion(),
4685
5014
  bxUa: cache.headers["bx-ua"] || session?.bxUa || "",
4686
5015
  bxUmidtoken: cache.headers["bx-umidtoken"] || session?.bxUmidtoken || "",
4687
5016
  secChUa: cache.headers["sec-ch-ua"] || session?.secChUa,
@@ -4716,7 +5045,7 @@ async function refreshAccountToken(accountId) {
4716
5045
  saveAuthSession2(accountId, {
4717
5046
  cookie: cookieStr,
4718
5047
  userAgent: cache.headers["user-agent"] || session?.userAgent || "",
4719
- bxV: cache.headers["bx-v"] || session?.bxV || "2.5.37",
5048
+ bxV: cache.headers["bx-v"] || session?.bxV || getQwenBxVersion(),
4720
5049
  bxUa: cache.headers["bx-ua"] || session?.bxUa || "",
4721
5050
  bxUmidtoken: cache.headers["bx-umidtoken"] || session?.bxUmidtoken || "",
4722
5051
  secChUa: cache.headers["sec-ch-ua"] || session?.secChUa,
@@ -4864,7 +5193,7 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
4864
5193
  cookie: reqHeaders["cookie"] || "",
4865
5194
  "bx-ua": reqHeaders["bx-ua"] || "",
4866
5195
  "bx-umidtoken": reqHeaders["bx-umidtoken"] || "",
4867
- "bx-v": reqHeaders["bx-v"] || "2.5.37",
5196
+ "bx-v": reqHeaders["bx-v"] || getQwenBxVersion(),
4868
5197
  "user-agent": reqHeaders["user-agent"] || "",
4869
5198
  "x-request-id": reqHeaders["x-request-id"] || "",
4870
5199
  "version": reqHeaders["version"] || "",
@@ -4896,6 +5225,9 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
4896
5225
  if (capturedHeaders["version"]) {
4897
5226
  updateQwenWebVersion(capturedHeaders["version"]);
4898
5227
  }
5228
+ if (capturedHeaders["bx-v"]) {
5229
+ updateQwenBxVersion(capturedHeaders["bx-v"]);
5230
+ }
4899
5231
  markAccountHeadersReady(accountId);
4900
5232
  cache.lastRefresh = Date.now();
4901
5233
  cookieCaches.delete(accountId);