qwenproxy-cli 1.5.0 → 1.5.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.
@@ -965,6 +965,7 @@ var init_config = __esm({
965
965
  // own context while serving. Accounts in cooldown (rate-limited) sit idle,
966
966
  // drop out of the warm set and get evicted.
967
967
  PLAYWRIGHT_MAX_ACTIVE_CONTEXTS: z.string().default("2"),
968
+ PLAYWRIGHT_STARTUP_WARM_ACCOUNTS: z.string().default("4"),
968
969
  PLAYWRIGHT_PREPARE_ALL_ON_STARTUP: z.string().default("false"),
969
970
  CAPTCHA_SOLVER_ENABLED: z.string().default("true"),
970
971
  CAPTCHA_SOLVER_MAX_ATTEMPTS: z.string().default("3"),
@@ -1113,6 +1114,7 @@ var init_config = __esm({
1113
1114
  jsHeapMb: Math.max(64, parseInt(env.PLAYWRIGHT_JS_HEAP_MB)),
1114
1115
  lowMemoryFlags: env.PLAYWRIGHT_LOW_MEMORY_FLAGS !== "false",
1115
1116
  maxActiveContexts: Math.max(0, parseInt(env.PLAYWRIGHT_MAX_ACTIVE_CONTEXTS)),
1117
+ startupWarmAccounts: Math.max(1, parseInt(env.PLAYWRIGHT_STARTUP_WARM_ACCOUNTS)),
1116
1118
  prepareAllOnStartup: env.PLAYWRIGHT_PREPARE_ALL_ON_STARTUP !== "false"
1117
1119
  },
1118
1120
  captcha: {
@@ -1967,6 +1969,9 @@ function unmarkAccountHeadersReady(accountId) {
1967
1969
  if (!accountId) return;
1968
1970
  headersReadyAccounts.delete(accountId);
1969
1971
  }
1972
+ function isAccountHeadersReady(accountId) {
1973
+ return headersReadyAccounts.has(accountId);
1974
+ }
1970
1975
  var cooldowns, headersReadyAccounts;
1971
1976
  var init_account_manager = __esm({
1972
1977
  "src/core/account-manager.ts"() {
@@ -2898,26 +2903,6 @@ async function isPageLoggedIn(page, timeoutMs = SESSION_PROBE_NAVIGATION_TIMEOUT
2898
2903
  }
2899
2904
  } catch {
2900
2905
  }
2901
- try {
2902
- const refreshRes = await fetch("https://auth.qwen.ai/api/v2/auths/refresh", {
2903
- method: "GET",
2904
- credentials: "include",
2905
- signal: AbortSignal.timeout(3e3)
2906
- });
2907
- if (refreshRes.status === 200) {
2908
- const refreshJson = await refreshRes.json().catch(() => null);
2909
- if (refreshJson && refreshJson.success === false) {
2910
- const code = refreshJson.data?.code || refreshJson.code;
2911
- const details = String(refreshJson.data?.details || "");
2912
- if (code === "Unauthorized" || details.includes("revogado") || details.includes("revoked")) {
2913
- return false;
2914
- }
2915
- }
2916
- } else if (refreshRes.status === 401 || refreshRes.status === 403) {
2917
- return false;
2918
- }
2919
- } catch {
2920
- }
2921
2906
  return true;
2922
2907
  } catch {
2923
2908
  return false;
@@ -3723,7 +3708,7 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
3723
3708
  `\u26A0\uFE0F [Playwright] Initial navigation check for ${maskEmail(account.email)}: ${err.message}`
3724
3709
  );
3725
3710
  }
3726
- if (!options.skipHeaderCapture) {
3711
+ if (!options.skipHeaderCapture && !isAccountHeadersReady(account.id)) {
3727
3712
  acctPage.__qwenChatHomeLoaded = true;
3728
3713
  await captureQwenHeaders(account.id);
3729
3714
  }
@@ -3933,7 +3918,7 @@ async function loginToQwen(accountId, email, password) {
3933
3918
  );
3934
3919
  markAccountRateLimited(
3935
3920
  accountId,
3936
- 24 * 3600 * 1e3,
3921
+ 300 * 1e3,
3937
3922
  "AuthFailed: All login methods exhausted"
3938
3923
  );
3939
3924
  return false;
@@ -4210,38 +4195,49 @@ async function loginViaUi(page, email, password) {
4210
4195
  try {
4211
4196
  const emailEl = document.querySelector('input[name="email"], input[type="email"], input[type="text"]');
4212
4197
  const passEl = document.querySelector('input[type="password"], input[name="password"]');
4213
- if (emailEl) {
4214
- emailEl.dispatchEvent(new Event("input", { bubbles: true }));
4215
- emailEl.dispatchEvent(new Event("change", { bubbles: true }));
4216
- emailEl.dispatchEvent(new Event("blur", { bubbles: true }));
4217
- }
4218
- if (passEl) {
4219
- passEl.dispatchEvent(new Event("input", { bubbles: true }));
4220
- passEl.dispatchEvent(new Event("change", { bubbles: true }));
4221
- passEl.dispatchEvent(new Event("blur", { bubbles: true }));
4222
- }
4198
+ const setReactValue = (el, val) => {
4199
+ const proto = Object.getPrototypeOf(el);
4200
+ const setter = Object.getOwnPropertyDescriptor(proto, "value")?.set;
4201
+ if (setter) {
4202
+ setter.call(el, val);
4203
+ } else {
4204
+ el.value = val;
4205
+ }
4206
+ el.dispatchEvent(new Event("input", { bubbles: true }));
4207
+ el.dispatchEvent(new Event("change", { bubbles: true }));
4208
+ el.dispatchEvent(new Event("blur", { bubbles: true }));
4209
+ };
4210
+ if (emailEl) setReactValue(emailEl, emailEl.value);
4211
+ if (passEl) setReactValue(passEl, passEl.value);
4223
4212
  } catch {
4224
4213
  }
4225
4214
  }).catch(() => {
4226
4215
  });
4216
+ await sleep2(500);
4227
4217
  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")';
4228
4218
  const submitButton = page.locator(submitSelector).first();
4219
+ await page.evaluate((sel) => {
4220
+ try {
4221
+ const btn = document.querySelector(sel);
4222
+ if (btn) {
4223
+ btn.removeAttribute("disabled");
4224
+ btn.classList.remove("ant-btn-disabled");
4225
+ btn.click();
4226
+ }
4227
+ } catch {
4228
+ }
4229
+ }, submitSelector).catch(() => {
4230
+ });
4229
4231
  try {
4230
- await page.waitForSelector('button[type="submit"]:not([disabled])', {
4231
- timeout: 4e3
4232
- });
4233
- await submitButton.click();
4234
- } catch {
4235
- const isDisabled = await submitButton.isDisabled().catch(() => true);
4236
- if (!isDisabled) {
4237
- await submitButton.click({ force: true }).catch(() => {
4232
+ if (await submitButton.isVisible({ timeout: 2e3 }).catch(() => false)) {
4233
+ await submitButton.click({ force: true, timeout: 2e3 }).catch(() => {
4238
4234
  });
4239
- } else {
4240
- if (!page.url().includes("/auth") && await isPageLoggedIn(page, 2e3)) {
4241
- return { success: true };
4242
- }
4243
4235
  }
4236
+ } catch {
4244
4237
  }
4238
+ const passInput = page.locator(passwordSelector).first();
4239
+ await passInput.press("Enter", { timeout: 2e3 }).catch(() => {
4240
+ });
4245
4241
  const postSubmitDeadline = Date.now() + 15e3;
4246
4242
  while (Date.now() < postSubmitDeadline) {
4247
4243
  if (page.isClosed()) break;
@@ -1020,6 +1020,7 @@ var init_config = __esm({
1020
1020
  // own context while serving. Accounts in cooldown (rate-limited) sit idle,
1021
1021
  // drop out of the warm set and get evicted.
1022
1022
  PLAYWRIGHT_MAX_ACTIVE_CONTEXTS: z.string().default("2"),
1023
+ PLAYWRIGHT_STARTUP_WARM_ACCOUNTS: z.string().default("4"),
1023
1024
  PLAYWRIGHT_PREPARE_ALL_ON_STARTUP: z.string().default("false"),
1024
1025
  CAPTCHA_SOLVER_ENABLED: z.string().default("true"),
1025
1026
  CAPTCHA_SOLVER_MAX_ATTEMPTS: z.string().default("3"),
@@ -1168,6 +1169,7 @@ var init_config = __esm({
1168
1169
  jsHeapMb: Math.max(64, parseInt(env.PLAYWRIGHT_JS_HEAP_MB)),
1169
1170
  lowMemoryFlags: env.PLAYWRIGHT_LOW_MEMORY_FLAGS !== "false",
1170
1171
  maxActiveContexts: Math.max(0, parseInt(env.PLAYWRIGHT_MAX_ACTIVE_CONTEXTS)),
1172
+ startupWarmAccounts: Math.max(1, parseInt(env.PLAYWRIGHT_STARTUP_WARM_ACCOUNTS)),
1171
1173
  prepareAllOnStartup: env.PLAYWRIGHT_PREPARE_ALL_ON_STARTUP !== "false"
1172
1174
  },
1173
1175
  captcha: {
@@ -1901,6 +1903,14 @@ var init_mutex = __esm({
1901
1903
  });
1902
1904
 
1903
1905
  // src/core/account-priority.ts
1906
+ var account_priority_exports = {};
1907
+ __export(account_priority_exports, {
1908
+ ensureAccountInPriority: () => ensureAccountInPriority,
1909
+ getAccountsByPriority: () => getAccountsByPriority,
1910
+ invalidatePriorityCache: () => invalidatePriorityCache,
1911
+ markAccountFailed: () => markAccountFailed,
1912
+ markAccountSuccessful: () => markAccountSuccessful
1913
+ });
1904
1914
  import {
1905
1915
  existsSync,
1906
1916
  mkdirSync,
@@ -1910,6 +1920,9 @@ import {
1910
1920
  function isPersistableAccount(accountId) {
1911
1921
  return accountId !== MOCK_ACCOUNT_ID;
1912
1922
  }
1923
+ function invalidatePriorityCache() {
1924
+ priorityCache = null;
1925
+ }
1913
1926
  function loadPriority() {
1914
1927
  if (priorityCache) return priorityCache;
1915
1928
  try {
@@ -1930,6 +1943,41 @@ function loadPriority() {
1930
1943
  priorityCache = { accountOrder: [], lastUpdated: 0 };
1931
1944
  return priorityCache;
1932
1945
  }
1946
+ function savePriority(data) {
1947
+ try {
1948
+ mkdirSync(DATA_DIR3, { recursive: true });
1949
+ writeFileSync(PRIORITY_FILE, JSON.stringify(data, null, 2), "utf-8");
1950
+ priorityCache = data;
1951
+ } catch (err) {
1952
+ console.error("\u274C [AccountPriority] Failed to save priority file:", err.message);
1953
+ }
1954
+ }
1955
+ function markAccountSuccessful(accountId) {
1956
+ if (!isPersistableAccount(accountId)) return;
1957
+ const data = loadPriority();
1958
+ data.accountOrder = data.accountOrder.filter((id) => id !== accountId);
1959
+ data.accountOrder.unshift(accountId);
1960
+ data.lastUpdated = Date.now();
1961
+ savePriority(data);
1962
+ }
1963
+ function markAccountFailed(accountId) {
1964
+ if (!isPersistableAccount(accountId)) return;
1965
+ const data = loadPriority();
1966
+ data.accountOrder = data.accountOrder.filter((id) => id !== accountId);
1967
+ data.accountOrder.push(accountId);
1968
+ data.lastUpdated = Date.now();
1969
+ savePriority(data);
1970
+ }
1971
+ function ensureAccountInPriority(accountId) {
1972
+ if (!isPersistableAccount(accountId)) return;
1973
+ const data = loadPriority();
1974
+ if (data.accountOrder.includes(accountId)) {
1975
+ return;
1976
+ }
1977
+ data.accountOrder.push(accountId);
1978
+ data.lastUpdated = Date.now();
1979
+ savePriority(data);
1980
+ }
1933
1981
  function getAccountsByPriority(accounts) {
1934
1982
  const data = loadPriority();
1935
1983
  if (data.accountOrder.length === 0) {
@@ -2030,6 +2078,9 @@ function unmarkAccountHeadersReady(accountId) {
2030
2078
  if (!accountId) return;
2031
2079
  headersReadyAccounts.delete(accountId);
2032
2080
  }
2081
+ function isAccountHeadersReady(accountId) {
2082
+ return headersReadyAccounts.has(accountId);
2083
+ }
2033
2084
  var cooldowns, headersReadyAccounts;
2034
2085
  var init_account_manager = __esm({
2035
2086
  "src/core/account-manager.ts"() {
@@ -3333,26 +3384,6 @@ async function isPageLoggedIn(page, timeoutMs = SESSION_PROBE_NAVIGATION_TIMEOUT
3333
3384
  }
3334
3385
  } catch {
3335
3386
  }
3336
- try {
3337
- const refreshRes = await fetch("https://auth.qwen.ai/api/v2/auths/refresh", {
3338
- method: "GET",
3339
- credentials: "include",
3340
- signal: AbortSignal.timeout(3e3)
3341
- });
3342
- if (refreshRes.status === 200) {
3343
- const refreshJson = await refreshRes.json().catch(() => null);
3344
- if (refreshJson && refreshJson.success === false) {
3345
- const code = refreshJson.data?.code || refreshJson.code;
3346
- const details = String(refreshJson.data?.details || "");
3347
- if (code === "Unauthorized" || details.includes("revogado") || details.includes("revoked")) {
3348
- return false;
3349
- }
3350
- }
3351
- } else if (refreshRes.status === 401 || refreshRes.status === 403) {
3352
- return false;
3353
- }
3354
- } catch {
3355
- }
3356
3387
  return true;
3357
3388
  } catch {
3358
3389
  return false;
@@ -4480,7 +4511,7 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
4480
4511
  `\u26A0\uFE0F [Playwright] Initial navigation check for ${maskEmail(account.email)}: ${err.message}`
4481
4512
  );
4482
4513
  }
4483
- if (!options.skipHeaderCapture) {
4514
+ if (!options.skipHeaderCapture && !isAccountHeadersReady(account.id)) {
4484
4515
  acctPage.__qwenChatHomeLoaded = true;
4485
4516
  await captureQwenHeaders(account.id);
4486
4517
  }
@@ -4810,7 +4841,7 @@ async function loginToQwen(accountId, email, password) {
4810
4841
  );
4811
4842
  markAccountRateLimited(
4812
4843
  accountId,
4813
- 24 * 3600 * 1e3,
4844
+ 300 * 1e3,
4814
4845
  "AuthFailed: All login methods exhausted"
4815
4846
  );
4816
4847
  return false;
@@ -5087,38 +5118,49 @@ async function loginViaUi(page, email, password) {
5087
5118
  try {
5088
5119
  const emailEl = document.querySelector('input[name="email"], input[type="email"], input[type="text"]');
5089
5120
  const passEl = document.querySelector('input[type="password"], input[name="password"]');
5090
- if (emailEl) {
5091
- emailEl.dispatchEvent(new Event("input", { bubbles: true }));
5092
- emailEl.dispatchEvent(new Event("change", { bubbles: true }));
5093
- emailEl.dispatchEvent(new Event("blur", { bubbles: true }));
5094
- }
5095
- if (passEl) {
5096
- passEl.dispatchEvent(new Event("input", { bubbles: true }));
5097
- passEl.dispatchEvent(new Event("change", { bubbles: true }));
5098
- passEl.dispatchEvent(new Event("blur", { bubbles: true }));
5099
- }
5121
+ const setReactValue = (el, val) => {
5122
+ const proto = Object.getPrototypeOf(el);
5123
+ const setter = Object.getOwnPropertyDescriptor(proto, "value")?.set;
5124
+ if (setter) {
5125
+ setter.call(el, val);
5126
+ } else {
5127
+ el.value = val;
5128
+ }
5129
+ el.dispatchEvent(new Event("input", { bubbles: true }));
5130
+ el.dispatchEvent(new Event("change", { bubbles: true }));
5131
+ el.dispatchEvent(new Event("blur", { bubbles: true }));
5132
+ };
5133
+ if (emailEl) setReactValue(emailEl, emailEl.value);
5134
+ if (passEl) setReactValue(passEl, passEl.value);
5100
5135
  } catch {
5101
5136
  }
5102
5137
  }).catch(() => {
5103
5138
  });
5139
+ await sleep2(500);
5104
5140
  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")';
5105
5141
  const submitButton = page.locator(submitSelector).first();
5142
+ await page.evaluate((sel) => {
5143
+ try {
5144
+ const btn = document.querySelector(sel);
5145
+ if (btn) {
5146
+ btn.removeAttribute("disabled");
5147
+ btn.classList.remove("ant-btn-disabled");
5148
+ btn.click();
5149
+ }
5150
+ } catch {
5151
+ }
5152
+ }, submitSelector).catch(() => {
5153
+ });
5106
5154
  try {
5107
- await page.waitForSelector('button[type="submit"]:not([disabled])', {
5108
- timeout: 4e3
5109
- });
5110
- await submitButton.click();
5111
- } catch {
5112
- const isDisabled = await submitButton.isDisabled().catch(() => true);
5113
- if (!isDisabled) {
5114
- await submitButton.click({ force: true }).catch(() => {
5155
+ if (await submitButton.isVisible({ timeout: 2e3 }).catch(() => false)) {
5156
+ await submitButton.click({ force: true, timeout: 2e3 }).catch(() => {
5115
5157
  });
5116
- } else {
5117
- if (!page.url().includes("/auth") && await isPageLoggedIn(page, 2e3)) {
5118
- return { success: true };
5119
- }
5120
5158
  }
5159
+ } catch {
5121
5160
  }
5161
+ const passInput = page.locator(passwordSelector).first();
5162
+ await passInput.press("Enter", { timeout: 2e3 }).catch(() => {
5163
+ });
5122
5164
  const postSubmitDeadline = Date.now() + 15e3;
5123
5165
  while (Date.now() < postSubmitDeadline) {
5124
5166
  if (page.isClosed()) break;
@@ -6589,6 +6631,11 @@ async function ensurePlaywrightInitialized(accountId) {
6589
6631
  });
6590
6632
  } catch {
6591
6633
  }
6634
+ try {
6635
+ const { ensureAccountInPriority: ensureAccountInPriority2 } = await Promise.resolve().then(() => (init_account_priority(), account_priority_exports));
6636
+ ensureAccountInPriority2(accountId);
6637
+ } catch {
6638
+ }
6592
6639
  }
6593
6640
  async function getBasicHeaders2(accountId) {
6594
6641
  if (isAuthMockEnabled()) {