qwenproxy-cli 1.6.1 → 1.6.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.
package/dist/index.js CHANGED
@@ -2190,7 +2190,7 @@ function addAccountsBatch(entries) {
2190
2190
  }
2191
2191
  return { added, skipped, invalid };
2192
2192
  }
2193
- function addAccount(email, password, id) {
2193
+ function addAccount(email, password = "", id) {
2194
2194
  if (!email || typeof email !== "string" || email.trim().length === 0) {
2195
2195
  throw new Error("Email is required");
2196
2196
  }
@@ -4315,6 +4315,7 @@ var playwright_exports = {};
4315
4315
  __export(playwright_exports, {
4316
4316
  assertAntiBotHeaders: () => assertAntiBotHeaders,
4317
4317
  buildChromiumLaunchArgs: () => buildChromiumLaunchArgs,
4318
+ cancelEmailOtpLogin: () => cancelEmailOtpLogin,
4318
4319
  captureQwenHeaders: () => captureQwenHeaders,
4319
4320
  classifyQwenAuthError: () => classifyQwenAuthError,
4320
4321
  cleanupOrphanProfiles: () => cleanupOrphanProfiles,
@@ -4355,8 +4356,10 @@ __export(playwright_exports, {
4355
4356
  removePlaywrightProfile: () => removePlaywrightProfile,
4356
4357
  saveStorageState: () => saveStorageState,
4357
4358
  schedulePlaywrightProfileReset: () => schedulePlaywrightProfileReset,
4359
+ startEmailOtpLogin: () => startEmailOtpLogin,
4358
4360
  unregisterPlaywrightAccountForTests: () => unregisterPlaywrightAccountForTests,
4359
4361
  validateAccountLogin: () => validateAccountLogin,
4362
+ verifyEmailOtpLogin: () => verifyEmailOtpLogin,
4360
4363
  withAccountPage: () => withAccountPage
4361
4364
  });
4362
4365
  import { chromium as chromium2 } from "patchright";
@@ -4698,6 +4701,10 @@ async function clearVisibleChallenge(page) {
4698
4701
  "button[aria-label*='Close' i]",
4699
4702
  "button[aria-label*='Fechar' i]",
4700
4703
  ".index-module__whats-new-modal-close",
4704
+ ".age-confirmation-modal button",
4705
+ ".age-confirmation-modal .qwen-chat-v2-btn-black",
4706
+ "button:has-text('Continuar')",
4707
+ "button:has-text('Continue')",
4701
4708
  "button:has-text('Cancel')",
4702
4709
  "button:has-text('Cancelar')",
4703
4710
  "button:has-text('I understand')",
@@ -5892,6 +5899,292 @@ async function validateAccountLogin(rawAccount, headless = true, browserType = "
5892
5899
  release();
5893
5900
  }
5894
5901
  }
5902
+ async function startEmailOtpLogin(email, options = {}) {
5903
+ const normalizedEmail = email.trim().toLowerCase();
5904
+ if (!normalizedEmail || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(normalizedEmail)) {
5905
+ return { success: false, error: "Formato de e-mail inv\xE1lido" };
5906
+ }
5907
+ const { listAccounts: listAccounts2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
5908
+ if (listAccounts2().some((a) => a.email.toLowerCase() === normalizedEmail)) {
5909
+ return {
5910
+ success: false,
5911
+ error: `Uma conta com o e-mail "${normalizedEmail}" j\xE1 est\xE1 cadastrada.`
5912
+ };
5913
+ }
5914
+ if (process.env.TEST_MOCK_QWEN_AUTH === "true" && process.env.NODE_ENV !== "production") {
5915
+ const mockSessionId = "mock-otp-" + Date.now();
5916
+ mockOtpSessions.set(mockSessionId, normalizedEmail);
5917
+ return { success: true, sessionId: mockSessionId };
5918
+ }
5919
+ const accountId = crypto5.randomUUID();
5920
+ const sessionId = accountId;
5921
+ const profilePath = getAccountProfilePath(accountId);
5922
+ const fingerprint = getFingerprintProfile(accountId);
5923
+ const browserType = options.browserType ?? config.playwright.browser;
5924
+ const { engine, channel } = resolveBrowserEngine(browserType);
5925
+ const headless = options.headless ?? config.playwright.headless;
5926
+ const launchOptions = {
5927
+ headless,
5928
+ channel,
5929
+ userAgent: fingerprint.userAgent,
5930
+ locale: fingerprint.locale,
5931
+ timezoneId: fingerprint.timezoneId,
5932
+ viewport: fingerprint.viewport,
5933
+ screen: fingerprint.viewport,
5934
+ deviceScaleFactor: 1,
5935
+ isMobile: false,
5936
+ hasTouch: false,
5937
+ colorScheme: "light",
5938
+ extraHTTPHeaders: {
5939
+ "sec-ch-ua": fingerprint.secChUa,
5940
+ "sec-ch-ua-mobile": "?0",
5941
+ "sec-ch-ua-platform": '"Windows"'
5942
+ },
5943
+ ignoreDefaultArgs: ["--enable-automation", "--enable-blink-features"],
5944
+ args: buildChromiumLaunchArgs(fingerprint.viewport)
5945
+ };
5946
+ let acctContext;
5947
+ try {
5948
+ acctContext = await withTimeout(
5949
+ engine.launchPersistentContext(profilePath, launchOptions),
5950
+ 3e4,
5951
+ `O navegador n\xE3o iniciou em 30s para a conta ${maskEmail(normalizedEmail)}.`
5952
+ );
5953
+ } catch (launchErr) {
5954
+ if (launchErr?.message?.includes("Executable doesn't exist")) {
5955
+ autoInstallPlaywrightChromium();
5956
+ acctContext = await withTimeout(
5957
+ engine.launchPersistentContext(profilePath, launchOptions),
5958
+ 3e4,
5959
+ `O navegador n\xE3o iniciou em 30s para a conta ${maskEmail(normalizedEmail)}.`
5960
+ );
5961
+ } else {
5962
+ return { success: false, error: launchErr?.message || String(launchErr) };
5963
+ }
5964
+ }
5965
+ try {
5966
+ await acctContext.addInitScript(getStealthScript(fingerprint));
5967
+ const existingPages = acctContext.pages().filter((p) => !p.isClosed());
5968
+ const acctPage = existingPages.find((p) => p.url().startsWith(qwenOrigin())) ?? existingPages[0] ?? await acctContext.newPage();
5969
+ await acctPage.goto(qwenUrl("/auth?mode=register"), {
5970
+ waitUntil: "domcontentloaded",
5971
+ timeout: Math.min(config.timeouts.navigation, 2e4)
5972
+ }).catch(() => {
5973
+ });
5974
+ await sleep2(1e3);
5975
+ await clearVisibleChallenge(acctPage);
5976
+ const requestId = crypto5.randomUUID();
5977
+ const evalRes = await acctPage.evaluate(
5978
+ async ({ email: email2, requestId: requestId2, version, timezone }) => {
5979
+ try {
5980
+ const response = await fetch("https://auth.qwen.ai/api/v2/auths/otp/email/request", {
5981
+ method: "POST",
5982
+ credentials: "include",
5983
+ headers: {
5984
+ accept: "application/json, text/plain, */*",
5985
+ "content-type": "application/json",
5986
+ source: "web",
5987
+ version,
5988
+ "x-request-origin": "https://chat.qwen.ai",
5989
+ timezone,
5990
+ "x-request-id": requestId2
5991
+ },
5992
+ body: JSON.stringify({
5993
+ identifier: email2,
5994
+ accept_terms: true,
5995
+ language: "pt-BR"
5996
+ })
5997
+ });
5998
+ const json = await response.json().catch(() => null);
5999
+ return { ok: response.ok, status: response.status, data: json };
6000
+ } catch (e) {
6001
+ return { ok: false, error: e.message };
6002
+ }
6003
+ },
6004
+ {
6005
+ email: normalizedEmail,
6006
+ requestId,
6007
+ version: getQwenWebVersion() || "0.3.12",
6008
+ timezone: (/* @__PURE__ */ new Date()).toString().split(" (")[0]
6009
+ }
6010
+ ).catch((err) => ({ ok: false, error: err?.message || String(err) }));
6011
+ if (!evalRes.ok || evalRes.data?.success !== true) {
6012
+ const errorMsg = evalRes.data?.data?.details || evalRes.data?.data?.message || evalRes.data?.message || evalRes.error || "Falha ao solicitar c\xF3digo de verifica\xE7\xE3o";
6013
+ await closePlaywrightContextBestEffort(accountId, acctContext).catch(() => {
6014
+ });
6015
+ cleanupPlaywrightAccountState(accountId);
6016
+ return { success: false, error: errorMsg };
6017
+ }
6018
+ const timer = setTimeout(async () => {
6019
+ activeOtpSessions.delete(sessionId);
6020
+ await closePlaywrightContextBestEffort(accountId, acctContext).catch(() => {
6021
+ });
6022
+ cleanupPlaywrightAccountState(accountId);
6023
+ }, 5 * 60 * 1e3);
6024
+ timer.unref?.();
6025
+ activeOtpSessions.set(sessionId, {
6026
+ sessionId,
6027
+ accountId,
6028
+ email: normalizedEmail,
6029
+ context: acctContext,
6030
+ page: acctPage,
6031
+ fingerprint,
6032
+ createdAt: Date.now(),
6033
+ timer
6034
+ });
6035
+ return { success: true, sessionId };
6036
+ } catch (err) {
6037
+ await closePlaywrightContextBestEffort(accountId, acctContext).catch(() => {
6038
+ });
6039
+ cleanupPlaywrightAccountState(accountId);
6040
+ return { success: false, error: err?.message || String(err) };
6041
+ }
6042
+ }
6043
+ async function verifyEmailOtpLogin(sessionId, code) {
6044
+ const cleanCode = code.trim();
6045
+ if (!cleanCode) {
6046
+ return { success: false, error: "C\xF3digo de verifica\xE7\xE3o \xE9 obrigat\xF3rio" };
6047
+ }
6048
+ if (process.env.TEST_MOCK_QWEN_AUTH === "true" && process.env.NODE_ENV !== "production") {
6049
+ const mockEmail = mockOtpSessions.get(sessionId);
6050
+ if (!mockEmail) {
6051
+ return { success: false, error: "Sess\xE3o OTP inv\xE1lida ou expirada" };
6052
+ }
6053
+ if (cleanCode === "000000") {
6054
+ return { success: false, error: "C\xF3digo de verifica\xE7\xE3o incorreto ou expirado" };
6055
+ }
6056
+ const { addAccount: addAccount2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
6057
+ const mockAccId = "mock-otp-acc-" + Date.now();
6058
+ const newAccount = addAccount2(mockEmail, "", mockAccId);
6059
+ mockOtpSessions.delete(sessionId);
6060
+ return { success: true, account: newAccount };
6061
+ }
6062
+ const session = activeOtpSessions.get(sessionId);
6063
+ if (!session) {
6064
+ return { success: false, error: "Sess\xE3o OTP expirada ou n\xE3o encontrada. Solicite um novo c\xF3digo." };
6065
+ }
6066
+ if (session.page.isClosed()) {
6067
+ activeOtpSessions.delete(sessionId);
6068
+ return { success: false, error: "Navegador foi fechado. Solicite um novo c\xF3digo." };
6069
+ }
6070
+ const requestId = crypto5.randomUUID();
6071
+ const evalRes = await session.page.evaluate(
6072
+ async ({ email, code: code2, requestId: requestId2, version, timezone }) => {
6073
+ try {
6074
+ const response = await fetch("https://auth.qwen.ai/api/v2/auths/otp/email/verify", {
6075
+ method: "POST",
6076
+ credentials: "include",
6077
+ headers: {
6078
+ accept: "application/json, text/plain, */*",
6079
+ "content-type": "application/json",
6080
+ source: "web",
6081
+ version,
6082
+ "x-request-origin": "https://chat.qwen.ai",
6083
+ timezone,
6084
+ "x-request-id": requestId2
6085
+ },
6086
+ body: JSON.stringify({
6087
+ identifier: email,
6088
+ code: code2,
6089
+ name: null
6090
+ })
6091
+ });
6092
+ const json = await response.json().catch(() => null);
6093
+ return { ok: response.ok, status: response.status, data: json };
6094
+ } catch (e) {
6095
+ return { ok: false, error: e.message };
6096
+ }
6097
+ },
6098
+ {
6099
+ email: session.email,
6100
+ code: cleanCode,
6101
+ requestId,
6102
+ version: getQwenWebVersion() || "0.3.12",
6103
+ timezone: (/* @__PURE__ */ new Date()).toString().split(" (")[0]
6104
+ }
6105
+ ).catch((err) => ({ ok: false, error: err?.message || String(err) }));
6106
+ if (!evalRes.ok || evalRes.data?.success !== true || !evalRes.data?.data) {
6107
+ const errorMsg = evalRes.data?.data?.details || evalRes.data?.data?.message || evalRes.data?.message || evalRes.error || "C\xF3digo de verifica\xE7\xE3o incorreto ou expirado";
6108
+ return { success: false, error: errorMsg };
6109
+ }
6110
+ const resData = evalRes.data.data;
6111
+ const accessToken = resData.access_token || resData.token;
6112
+ const refreshToken = resData.refresh_token;
6113
+ const userId = resData.id;
6114
+ try {
6115
+ await session.page.evaluate(({ token, rTok }) => {
6116
+ try {
6117
+ localStorage.setItem("token", token);
6118
+ localStorage.setItem("access_token", token);
6119
+ if (rTok) localStorage.setItem("refresh_token", rTok);
6120
+ document.cookie = `token=${encodeURIComponent(token)}; path=/; domain=.qwen.ai; max-age=31536000`;
6121
+ } catch {
6122
+ }
6123
+ }, { token: accessToken, rTok: refreshToken });
6124
+ await session.context.addCookies([
6125
+ {
6126
+ name: "token",
6127
+ value: accessToken,
6128
+ domain: ".qwen.ai",
6129
+ path: "/",
6130
+ expires: Math.floor(Date.now() / 1e3) + 31536e3,
6131
+ httpOnly: false,
6132
+ secure: true,
6133
+ sameSite: "Lax"
6134
+ }
6135
+ ]);
6136
+ await session.page.goto(qwenUrl("/"), {
6137
+ waitUntil: "domcontentloaded",
6138
+ timeout: Math.min(config.timeouts.navigation, 15e3)
6139
+ }).catch(() => {
6140
+ });
6141
+ await sleep2(1e3);
6142
+ await saveStorageState(session.context, session.accountId);
6143
+ const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
6144
+ const { parseJwtExpiry: parseJwtExpiry2 } = await Promise.resolve().then(() => (init_jwt(), jwt_exports));
6145
+ const exp = parseJwtExpiry2(accessToken);
6146
+ saveAuthSession2(session.accountId, {
6147
+ cookie: `token=${accessToken}`,
6148
+ userAgent: session.fingerprint.userAgent,
6149
+ bxV: "2.5.37",
6150
+ version: getQwenWebVersion() || "0.3.12",
6151
+ userId: userId || void 0,
6152
+ tokenExpiresAt: exp || void 0,
6153
+ refreshToken: refreshToken || void 0,
6154
+ capturedAt: Date.now()
6155
+ });
6156
+ const { addAccount: addAccount2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
6157
+ const newAccount = addAccount2(session.email, "", session.accountId);
6158
+ clearTimeout(session.timer);
6159
+ activeOtpSessions.delete(sessionId);
6160
+ await closePlaywrightContextBestEffort(session.accountId, session.context).catch(() => {
6161
+ });
6162
+ cleanupPlaywrightAccountState(session.accountId);
6163
+ return { success: true, account: newAccount };
6164
+ } catch (err) {
6165
+ clearTimeout(session.timer);
6166
+ activeOtpSessions.delete(sessionId);
6167
+ await closePlaywrightContextBestEffort(session.accountId, session.context).catch(() => {
6168
+ });
6169
+ cleanupPlaywrightAccountState(session.accountId);
6170
+ return { success: false, error: err?.message || String(err) };
6171
+ }
6172
+ }
6173
+ async function cancelEmailOtpLogin(sessionId) {
6174
+ if (process.env.TEST_MOCK_QWEN_AUTH === "true" && process.env.NODE_ENV !== "production") {
6175
+ mockOtpSessions.delete(sessionId);
6176
+ return;
6177
+ }
6178
+ const session = activeOtpSessions.get(sessionId);
6179
+ if (!session) return;
6180
+ clearTimeout(session.timer);
6181
+ activeOtpSessions.delete(sessionId);
6182
+ await closePlaywrightContextBestEffort(session.accountId, session.context).catch(() => {
6183
+ });
6184
+ cleanupPlaywrightAccountState(session.accountId);
6185
+ const { wipeAccountSessionFiles: wipeAccountSessionFiles2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
6186
+ wipeAccountSessionFiles2(session.accountId);
6187
+ }
5895
6188
  function classifyQwenAuthError(code, details) {
5896
6189
  const c = (code || "").trim().toLowerCase();
5897
6190
  const d = (details || "").trim().toLowerCase();
@@ -7260,7 +7553,7 @@ async function withAccountPage(accountId, fn, timeoutMs = ACCOUNT_PAGE_OPERATION
7260
7553
  return result;
7261
7554
  } catch (error) {
7262
7555
  const message = getErrorMessage(error);
7263
- if (recoverOnTimeout && message.includes("Playwright page operation timed out")) {
7556
+ if (recoverOnTimeout && message.includes("Playwright page operation timed out") && (!page || page.isClosed())) {
7264
7557
  console.warn(
7265
7558
  `\u23F1\uFE0F [Playwright] Resetting account context after a stuck page operation: ${accountId}`
7266
7559
  );
@@ -7809,7 +8102,7 @@ async function getTokenDiagnostics(accountId) {
7809
8102
  }
7810
8103
  };
7811
8104
  }
7812
- var requireLocal, contextInitHooks, ACCOUNT_MUTEX_MAX_HOLD_MS, accountMutexes, accountContexts, accountPages, cachedUserAgents, inFlightAccountInits, sharedBrowser, sharedBrowserPromise, headerCaches, HEADER_CACHE_TTL, HEADER_REFRESH_THRESHOLD, COOKIE_CACHE_TTL, cookieCaches, lastAccountActivity, lastKeepAliveNavigation, lastProactiveTokenRefresh, profileResetQueue, profileResetChain, closingAllPlaywright, sleep2, HEADER_CAPTURE_SETTLE_MS, PLAYWRIGHT_MUTEX_WAIT_MS, ACCOUNT_PAGE_OPERATION_TIMEOUT_MS, SESSION_PROBE_NAVIGATION_TIMEOUT_MS, HEADER_CAPTURE_TRIGGER_GRACE_MS, FIRST_TRIGGER_GRACE_MS, HEADER_CAPTURE_TRIGGER_ATTEMPTS, CHAT_INPUT_APPEAR_TIMEOUT_MS, CHAT_INPUT_ACTION_TIMEOUT_MS, PROFILE_RESET_TIMEOUT_MS;
8105
+ var requireLocal, contextInitHooks, ACCOUNT_MUTEX_MAX_HOLD_MS, accountMutexes, accountContexts, accountPages, cachedUserAgents, inFlightAccountInits, sharedBrowser, sharedBrowserPromise, headerCaches, HEADER_CACHE_TTL, HEADER_REFRESH_THRESHOLD, COOKIE_CACHE_TTL, cookieCaches, lastAccountActivity, lastKeepAliveNavigation, lastProactiveTokenRefresh, profileResetQueue, profileResetChain, closingAllPlaywright, sleep2, HEADER_CAPTURE_SETTLE_MS, PLAYWRIGHT_MUTEX_WAIT_MS, ACCOUNT_PAGE_OPERATION_TIMEOUT_MS, SESSION_PROBE_NAVIGATION_TIMEOUT_MS, HEADER_CAPTURE_TRIGGER_GRACE_MS, FIRST_TRIGGER_GRACE_MS, HEADER_CAPTURE_TRIGGER_ATTEMPTS, CHAT_INPUT_APPEAR_TIMEOUT_MS, CHAT_INPUT_ACTION_TIMEOUT_MS, activeOtpSessions, mockOtpSessions, PROFILE_RESET_TIMEOUT_MS;
7813
8106
  var init_playwright = __esm({
7814
8107
  "src/services/playwright.ts"() {
7815
8108
  "use strict";
@@ -7854,11 +8147,13 @@ var init_playwright = __esm({
7854
8147
  PLAYWRIGHT_MUTEX_WAIT_MS = 6e4;
7855
8148
  ACCOUNT_PAGE_OPERATION_TIMEOUT_MS = config.timeouts.page;
7856
8149
  SESSION_PROBE_NAVIGATION_TIMEOUT_MS = 15e3;
7857
- HEADER_CAPTURE_TRIGGER_GRACE_MS = 15e3;
7858
- FIRST_TRIGGER_GRACE_MS = 8e3;
8150
+ HEADER_CAPTURE_TRIGGER_GRACE_MS = 2e4;
8151
+ FIRST_TRIGGER_GRACE_MS = 12e3;
7859
8152
  HEADER_CAPTURE_TRIGGER_ATTEMPTS = 3;
7860
8153
  CHAT_INPUT_APPEAR_TIMEOUT_MS = 15e3;
7861
8154
  CHAT_INPUT_ACTION_TIMEOUT_MS = 1e4;
8155
+ activeOtpSessions = /* @__PURE__ */ new Map();
8156
+ mockOtpSessions = /* @__PURE__ */ new Map();
7862
8157
  PROFILE_RESET_TIMEOUT_MS = Math.max(9e4, config.timeouts.headers);
7863
8158
  setWafContextResetListener((accountId) => {
7864
8159
  if (!accountPages.has(accountId)) return;
@@ -9333,6 +9628,42 @@ var init_helpers = __esm({
9333
9628
  }
9334
9629
  });
9335
9630
 
9631
+ // src/utils/overload-detector.ts
9632
+ function isOverloadMessage(content) {
9633
+ if (!content) return false;
9634
+ const text = content.trim();
9635
+ if (!text || text.length > 500) return false;
9636
+ if (text.includes("```") || text.includes("<tool_call") || text.includes("<qpx_call") || text.includes("</")) {
9637
+ return false;
9638
+ }
9639
+ return OVERLOAD_PATTERNS.some((pattern) => pattern.test(text));
9640
+ }
9641
+ var OVERLOAD_PATTERNS, OVERLOAD_COOLDOWN_MS;
9642
+ var init_overload_detector = __esm({
9643
+ "src/utils/overload-detector.ts"() {
9644
+ "use strict";
9645
+ OVERLOAD_PATTERNS = [
9646
+ /high\s+demand/i,
9647
+ /problem\s+connecting/i,
9648
+ /try\s+again\s+later/i,
9649
+ /temporarily\s+unavailable/i,
9650
+ /service\s+(is\s+)?overloaded/i,
9651
+ /too\s+many\s+requests/i,
9652
+ /server\s+is\s+busy/i,
9653
+ /experiencing\s+high\s+(traffic|volume|load)/i,
9654
+ /unable\s+to\s+connect/i,
9655
+ /connection\s+(problem|error|issue)/i,
9656
+ /alta\s+demanda/i,
9657
+ /problema\s+de\s+conex/i,
9658
+ /tente\s+novamente\s+mais\s+tarde/i,
9659
+ /servidor\s+ocupado/i,
9660
+ /indispon[íi]vel\s+no\s+momento/i,
9661
+ /servi[çc]o\s+est[áa]\s+com\s+alta\s+demanda/i
9662
+ ];
9663
+ OVERLOAD_COOLDOWN_MS = 5 * 60 * 1e3;
9664
+ }
9665
+ });
9666
+
9336
9667
  // src/routes/chat/retry-policy.ts
9337
9668
  function errMessage(err) {
9338
9669
  if (err instanceof Error) return err.message || "";
@@ -9410,6 +9741,7 @@ function isAccountInitializationError(err) {
9410
9741
  function isQuotaLikeError(err) {
9411
9742
  if (isChatNotExistError(err) || isInvalidInputError(err)) return false;
9412
9743
  const code = errCode(err).toLowerCase();
9744
+ if (code === "server_overloaded" || code === "overload") return false;
9413
9745
  const message = errMessage(err).toLowerCase();
9414
9746
  return code === "quota_limit" || code === "ratelimited" || code === "membership_limit" || code === "membershiplimit" || message.includes("quota_limit") || message.includes("quota exceeded") || message.includes("allocated quota") || message.includes("token-limit") || message.includes("insufficient quota") || message.includes("alta demanda") || message.includes("high demand") || message.includes("request rate increased too quickly") || message.includes("rate increased too quickly") || message.includes("upper limit for today's usage") || message.includes("you've reached the upper limit") || message.includes("membership_limit") || message.includes("membership limit") || message.includes("update_member") || message.includes("update member") || // Accept local rate_limit code only when message also looks like quota/rate
9415
9747
  code === "rate_limit_exceeded" && (message.includes("quota") || message.includes("rate") || message.includes("limit") || message.includes("membership") || message.includes("demanda") || message.includes("demand"));
@@ -9463,6 +9795,14 @@ function isInternalServerError(err) {
9463
9795
  const message = errMessage(err).toLowerCase();
9464
9796
  return code === "internal_error" || code === "internal_server_error" || code === "server_error" || code === "server_busy" || code === "busy" || message.includes("internal_error") || message.includes("ocorreu um erro inesperado") || message.includes("unexpected error") || message.includes("internal server error");
9465
9797
  }
9798
+ function isOverloadError(err) {
9799
+ const code = errCode(err).toLowerCase();
9800
+ if (code === "quota_limit" || code === "ratelimited" || code === "rate_limit" || code === "rate_limit_exceeded" || code === "membership_limit" || code === "internal_error" || code === "internal_server_error") {
9801
+ return false;
9802
+ }
9803
+ if (code === "server_overloaded" || code === "overload") return true;
9804
+ return !code && isOverloadMessage(errMessage(err));
9805
+ }
9466
9806
  function makeRetryAction(reason, overrides = {}) {
9467
9807
  return {
9468
9808
  retryable: true,
@@ -9569,6 +9909,17 @@ function classifyRetryAction(err, options) {
9569
9909
  accountCooldownReason: quota.accountCooldownReason
9570
9910
  });
9571
9911
  }
9912
+ if (isOverloadError(err)) {
9913
+ const typed = err;
9914
+ return makeRetryAction("server_busy", {
9915
+ switchAccount: true,
9916
+ forceNewChat: true,
9917
+ retryWithFullPrompt: true,
9918
+ retryAfterMs: typed.retryAfterMs ?? 3e3,
9919
+ accountCooldownMs: OVERLOAD_COOLDOWN_MS,
9920
+ accountCooldownReason: "ServerOverloaded"
9921
+ });
9922
+ }
9572
9923
  if (isInternalServerError(err) && !(err instanceof QwenUpstreamError)) {
9573
9924
  const typed = err;
9574
9925
  return makeRetryAction("upstream_internal_error", {
@@ -9592,11 +9943,13 @@ function classifyRetryAction(err, options) {
9592
9943
  }
9593
9944
  if (err instanceof RetryableQwenStreamError) {
9594
9945
  const typed = err;
9595
- return makeRetryAction("explicit_retryable", {
9946
+ return makeRetryAction(typed.reason || "explicit_retryable", {
9596
9947
  switchAccount: typed.switchAccount !== false,
9597
9948
  forceNewChat: typed.forceNewChat === true,
9598
9949
  retryWithFullPrompt: typed.retryWithFullPrompt === true,
9599
- retryAfterMs: typed.retryAfterMs ?? baseDelayMs
9950
+ retryAfterMs: typed.retryAfterMs ?? baseDelayMs,
9951
+ accountCooldownMs: typed.accountCooldownMs,
9952
+ accountCooldownReason: typed.accountCooldownReason
9600
9953
  });
9601
9954
  }
9602
9955
  if (unknownEnabled) {
@@ -9629,6 +9982,9 @@ function toRetryableStreamError(errCode2, errDetails, options) {
9629
9982
  error.retryWithFullPrompt = merged.retryWithFullPrompt;
9630
9983
  error.switchAccount = merged.switchAccount;
9631
9984
  error.dropFiles = merged.dropFiles;
9985
+ error.accountCooldownMs = merged.accountCooldownMs;
9986
+ error.accountCooldownReason = merged.accountCooldownReason;
9987
+ error.reason = merged.reason;
9632
9988
  return error;
9633
9989
  }
9634
9990
  function throwFromSseUpstreamError(errCode2, errDetails) {
@@ -9714,6 +10070,7 @@ var init_retry_policy = __esm({
9714
10070
  init_qwen();
9715
10071
  init_errors();
9716
10072
  init_helpers();
10073
+ init_overload_detector();
9717
10074
  init_account_manager();
9718
10075
  }
9719
10076
  });
@@ -11871,7 +12228,8 @@ async function requestQwenPersonalizationInBrowser(accountId, method, path21, he
11871
12228
  payload === void 0 ? void 0 : JSON.stringify(payload),
11872
12229
  {
11873
12230
  settingsPage: true,
11874
- referrer: qwenUrl("/settings/personalization")
12231
+ referrer: qwenUrl("/settings/personalization"),
12232
+ noMutexRecovery: true
11875
12233
  }
11876
12234
  );
11877
12235
  const { raw, json } = await readJsonTextResponse(response);
@@ -12372,8 +12730,9 @@ async function syncQwenRequestPersonalizationInternal(instruction, accountId, me
12372
12730
  const returnedInstruction = json?.data?.personalization?.instruction;
12373
12731
  const returned = textSize(returnedInstruction);
12374
12732
  let stored = { chars: null, bytes: null, hash: null };
12733
+ const matchReturned = isEmptyInstruction && (!returnedInstruction || returned.chars === 0) || returned.hash !== null && returned.hash === sent.hash;
12375
12734
  let verifyData = null;
12376
- if (config.qwen.personalizationVerifyGet) {
12735
+ if (config.qwen.personalizationVerifyGet && !matchReturned) {
12377
12736
  const { json: verifyJson } = await requestQwenPersonalizationInBrowser(
12378
12737
  accountId,
12379
12738
  "GET",
@@ -12383,7 +12742,6 @@ async function syncQwenRequestPersonalizationInternal(instruction, accountId, me
12383
12742
  verifyData = verifyJson?.data?.personalization;
12384
12743
  stored = textSize(verifyData?.instruction);
12385
12744
  }
12386
- const matchReturned = isEmptyInstruction && (!returnedInstruction || returned.chars === 0) || returned.hash !== null && returned.hash === sent.hash;
12387
12745
  const matchStored = stored.hash === null ? null : isEmptyInstruction && (!verifyData?.instruction || stored.chars === 0) || stored.hash === sent.hash;
12388
12746
  const applied = matchReturned || matchStored === true;
12389
12747
  if (syncHash && applied) {
@@ -12757,6 +13115,17 @@ async function fetchQwenModels(accountId) {
12757
13115
  );
12758
13116
  return cached.models;
12759
13117
  }
13118
+ if (accountId && !isAuthMockEnabled() && !isPlaywrightInitialized(accountId)) {
13119
+ for (const [, entry] of modelsCache.entries()) {
13120
+ if (entry && now - entry.fetchedAt < MODEL_CACHE_TTL_MS * 4) {
13121
+ syncModelMetadata(
13122
+ entry.models,
13123
+ accountId
13124
+ );
13125
+ return entry.models;
13126
+ }
13127
+ }
13128
+ }
12760
13129
  if (accountId && !isAuthMockEnabled() && isAccountBusy(accountId)) {
12761
13130
  try {
12762
13131
  const result = await withAccountPage(
@@ -17200,7 +17569,8 @@ ${loopReminder}` : truncation.prompt;
17200
17569
  const checkDeadline = async () => {
17201
17570
  try {
17202
17571
  const { isCaptchaRecoveryActive: isCaptchaRecoveryActive2 } = await Promise.resolve().then(() => (init_captcha_coordinator(), captcha_coordinator_exports));
17203
- if (currentAccountId && isCaptchaRecoveryActive2(currentAccountId)) {
17572
+ const { isPlaywrightInitializing: isPlaywrightInitializing2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
17573
+ if (currentAccountId && (isCaptchaRecoveryActive2(currentAccountId) || isPlaywrightInitializing2(currentAccountId))) {
17204
17574
  acquireDeadlineTimer = setTimeout(checkDeadline, 3e4);
17205
17575
  acquireDeadlineTimer.unref?.();
17206
17576
  return;
@@ -17611,8 +17981,8 @@ var init_account = __esm({
17611
17981
  init_tool_call_guard();
17612
17982
  init_retry_policy();
17613
17983
  MAX_ANTI_BOT_ROTATIONS = 1;
17614
- PERSONALIZATION_SYNC_DEADLINE_MS = 45e3;
17615
- COLD_ACCOUNT_PERSONALIZATION_SYNC_DEADLINE_MS = 6e4;
17984
+ PERSONALIZATION_SYNC_DEADLINE_MS = 9e4;
17985
+ COLD_ACCOUNT_PERSONALIZATION_SYNC_DEADLINE_MS = 12e4;
17616
17986
  chatLocks = /* @__PURE__ */ new Map();
17617
17987
  personalizationLocks = /* @__PURE__ */ new Map();
17618
17988
  }
@@ -20575,6 +20945,19 @@ async function processNonStreamingResponse(params) {
20575
20945
  isThinkingChunk = false;
20576
20946
  if (delta.content !== void 0) {
20577
20947
  const newContent = delta.content || "";
20948
+ if (isOverloadMessage(newContent)) {
20949
+ throw toRetryableStreamError(
20950
+ "server_overloaded",
20951
+ newContent,
20952
+ {
20953
+ switchAccount: true,
20954
+ forceNewChat: true,
20955
+ reason: "server_busy",
20956
+ accountCooldownMs: OVERLOAD_COOLDOWN_MS,
20957
+ accountCooldownReason: "ServerOverloaded"
20958
+ }
20959
+ );
20960
+ }
20578
20961
  const result = getIncrementalDelta(
20579
20962
  lastRawContent,
20580
20963
  newContent,
@@ -21642,6 +22025,19 @@ async function processStreamingResponse(params) {
21642
22025
  isThinkingChunk = false;
21643
22026
  if (delta.content !== void 0) {
21644
22027
  const newContent = delta.content || "";
22028
+ if (!emittedModelOutput && isOverloadMessage(newContent)) {
22029
+ throw toRetryableStreamError(
22030
+ "server_overloaded",
22031
+ newContent,
22032
+ {
22033
+ switchAccount: true,
22034
+ forceNewChat: true,
22035
+ reason: "server_busy",
22036
+ accountCooldownMs: OVERLOAD_COOLDOWN_MS,
22037
+ accountCooldownReason: "ServerOverloaded"
22038
+ }
22039
+ );
22040
+ }
21645
22041
  const result = getIncrementalDelta(
21646
22042
  lastRawContent,
21647
22043
  newContent,
@@ -22446,6 +22842,7 @@ var init_streaming = __esm({
22446
22842
  init_daily_usage();
22447
22843
  init_context_meter();
22448
22844
  init_helpers();
22845
+ init_overload_detector();
22449
22846
  MAX_INITIAL_PROTOCOL_BYTES = 64 * 1024;
22450
22847
  MID_STREAM_FAILURE_WINDOW_MS = 5 * 60 * 1e3;
22451
22848
  midStreamNetworkFailures = /* @__PURE__ */ new Map();
@@ -26385,7 +26782,7 @@ function getAppVersion() {
26385
26782
  }
26386
26783
  } catch {
26387
26784
  }
26388
- cachedVersion = "v1.6.1";
26785
+ cachedVersion = "v1.6.2";
26389
26786
  return cachedVersion;
26390
26787
  }
26391
26788
  var cachedVersion;
@@ -33248,10 +33645,16 @@ var init_accounts_view = __esm({
33248
33645
  isAddModalOpen = false;
33249
33646
  isBatchModalOpen = false;
33250
33647
  isValidatingAccount = false;
33648
+ isOtpRequesting = false;
33649
+ isOtpCodeSent = false;
33650
+ addLoginMode = "password";
33651
+ otpSessionId = null;
33251
33652
  addEmailInput = "";
33252
33653
  addPasswordInput = "";
33654
+ addOtpCodeInput = "";
33253
33655
  addEmailCursor = 0;
33254
33656
  addPasswordCursor = 0;
33657
+ addOtpCodeCursor = 0;
33255
33658
  addActiveField = "email";
33256
33659
  batchInput = "";
33257
33660
  batchCursor = 0;
@@ -33328,22 +33731,113 @@ var init_accounts_view = __esm({
33328
33731
  this.statusMessage = "";
33329
33732
  }, 4e3);
33330
33733
  }
33734
+ resetAddModalState() {
33735
+ if (this.otpSessionId && !process.env.NODE_TEST_CONTEXT) {
33736
+ const sid = this.otpSessionId;
33737
+ Promise.resolve().then(() => (init_playwright(), playwright_exports)).then(({ cancelEmailOtpLogin: cancelEmailOtpLogin2 }) => cancelEmailOtpLogin2(sid)).catch(() => {
33738
+ });
33739
+ }
33740
+ this.isAddModalOpen = false;
33741
+ this.isValidatingAccount = false;
33742
+ this.isOtpRequesting = false;
33743
+ this.isOtpCodeSent = false;
33744
+ this.otpSessionId = null;
33745
+ this.addEmailInput = "";
33746
+ this.addPasswordInput = "";
33747
+ this.addOtpCodeInput = "";
33748
+ this.addEmailCursor = 0;
33749
+ this.addPasswordCursor = 0;
33750
+ this.addOtpCodeCursor = 0;
33751
+ this.addActiveField = "email";
33752
+ this.addLoginMode = "password";
33753
+ }
33331
33754
  async saveModalAccount() {
33332
- if (this.isValidatingAccount) return;
33755
+ if (this.isValidatingAccount || this.isOtpRequesting) return;
33333
33756
  const email = this.addEmailInput.trim();
33757
+ if (!email) {
33758
+ this.setStatusMessage(theme.yellow("[!] E-mail \xE9 obrigat\xF3rio"));
33759
+ return;
33760
+ }
33761
+ if (this.addLoginMode === "otp") {
33762
+ if (!this.isOtpCodeSent) {
33763
+ if (process.env.NODE_TEST_CONTEXT) {
33764
+ this.isOtpCodeSent = true;
33765
+ this.addActiveField = "code";
33766
+ this.otpSessionId = "mock-otp-" + Date.now();
33767
+ this.setStatusMessage(theme.green("\u2713 C\xF3digo enviado para o e-mail!"));
33768
+ return;
33769
+ }
33770
+ this.isOtpRequesting = true;
33771
+ this.setStatusMessage(theme.yellow(`[...] Enviando c\xF3digo OTP para ${email}...`));
33772
+ try {
33773
+ const { startEmailOtpLogin: startEmailOtpLogin2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
33774
+ const res = await startEmailOtpLogin2(email, { headless: config.playwright.headless });
33775
+ this.isOtpRequesting = false;
33776
+ if (!res.success || !res.sessionId) {
33777
+ this.setStatusMessage(theme.red(`\u2717 Falha ao enviar c\xF3digo: ${res.error || "Erro desconhecido"}`));
33778
+ return;
33779
+ }
33780
+ this.otpSessionId = res.sessionId;
33781
+ this.isOtpCodeSent = true;
33782
+ this.addActiveField = "code";
33783
+ this.setStatusMessage(theme.green("\u2713 C\xF3digo enviado! Digite os 6 d\xEDgitos abaixo."));
33784
+ } catch (err) {
33785
+ this.isOtpRequesting = false;
33786
+ this.setStatusMessage(theme.red(`\u2717 Erro: ${err?.message || String(err)}`));
33787
+ }
33788
+ return;
33789
+ }
33790
+ const code = this.addOtpCodeInput.trim();
33791
+ if (!code) {
33792
+ this.setStatusMessage(theme.yellow("[!] Digite o c\xF3digo de 6 d\xEDgitos recebido por e-mail"));
33793
+ return;
33794
+ }
33795
+ if (process.env.NODE_TEST_CONTEXT) {
33796
+ try {
33797
+ const newAcc = addAccount(email, "");
33798
+ this.resetAddModalState();
33799
+ await this.refresh();
33800
+ this.setStatusMessage(theme.green(`\u2713 Conta ${email} salva via c\xF3digo OTP!`));
33801
+ } catch (err) {
33802
+ this.setStatusMessage(theme.red(`\u2717 Erro ao salvar: ${err?.message || String(err)}`));
33803
+ }
33804
+ return;
33805
+ }
33806
+ this.isValidatingAccount = true;
33807
+ this.setStatusMessage(theme.yellow("[...] Validando c\xF3digo e capturando sess\xE3o de 30 dias..."));
33808
+ try {
33809
+ const { verifyEmailOtpLogin: verifyEmailOtpLogin2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
33810
+ const res = await verifyEmailOtpLogin2(this.otpSessionId, code);
33811
+ this.isValidatingAccount = false;
33812
+ if (!res.success || !res.account) {
33813
+ this.setStatusMessage(theme.red(`\u2717 C\xF3digo inv\xE1lido: ${res.error || "Verifica\xE7\xE3o falhou"}`));
33814
+ return;
33815
+ }
33816
+ this.resetAddModalState();
33817
+ await this.refresh();
33818
+ this.setStatusMessage(theme.green(`\u2713 Conta ${res.account.email} autenticada via c\xF3digo OTP!`));
33819
+ if (process.stdout.isTTY) {
33820
+ const sManager = ServerManager.getInstance();
33821
+ const sState = sManager.getState();
33822
+ if (sState !== "online" && sState !== "warming") {
33823
+ void sManager.ensureStarted().then(() => this.refresh());
33824
+ }
33825
+ }
33826
+ } catch (err) {
33827
+ this.isValidatingAccount = false;
33828
+ this.setStatusMessage(theme.red(`\u2717 Erro de verifica\xE7\xE3o: ${err?.message || String(err)}`));
33829
+ }
33830
+ return;
33831
+ }
33334
33832
  const password = this.addPasswordInput.trim();
33335
- if (!email || !password) {
33833
+ if (!password) {
33336
33834
  this.setStatusMessage(theme.yellow("[!] E-mail e senha s\xE3o obrigat\xF3rios"));
33337
33835
  return;
33338
33836
  }
33339
33837
  if (process.env.NODE_TEST_CONTEXT) {
33340
33838
  try {
33341
33839
  const newAcc = addAccount(email, password);
33342
- this.isAddModalOpen = false;
33343
- this.addEmailInput = "";
33344
- this.addPasswordInput = "";
33345
- this.addEmailCursor = 0;
33346
- this.addPasswordCursor = 0;
33840
+ this.resetAddModalState();
33347
33841
  await this.refresh();
33348
33842
  this.setStatusMessage(theme.green(`\u2713 Conta ${email} salva! Conectando...`));
33349
33843
  } catch (err) {
@@ -33370,11 +33864,7 @@ var init_accounts_view = __esm({
33370
33864
  return;
33371
33865
  }
33372
33866
  const newAcc = addAccount(email, password, tempId);
33373
- this.isAddModalOpen = false;
33374
- this.addEmailInput = "";
33375
- this.addPasswordInput = "";
33376
- this.addEmailCursor = 0;
33377
- this.addPasswordCursor = 0;
33867
+ this.resetAddModalState();
33378
33868
  await this.refresh();
33379
33869
  this.setStatusMessage(theme.green(`\u2713 Conta ${email} validada e salva! Conectando...`));
33380
33870
  if (process.stdout.isTTY) {
@@ -33627,29 +34117,40 @@ var init_accounts_view = __esm({
33627
34117
  return true;
33628
34118
  }
33629
34119
  if (this.isAddModalOpen) {
33630
- if (this.isValidatingAccount) return true;
34120
+ if (this.isValidatingAccount || this.isOtpRequesting) return true;
33631
34121
  if (key.name === "escape") {
33632
- this.isAddModalOpen = false;
33633
- this.addEmailInput = "";
33634
- this.addPasswordInput = "";
34122
+ this.resetAddModalState();
33635
34123
  return true;
33636
34124
  }
34125
+ if (key.name === "tab") {
34126
+ if (!this.isOtpCodeSent) {
34127
+ this.addLoginMode = this.addLoginMode === "password" ? "otp" : "password";
34128
+ this.addActiveField = "email";
34129
+ this.setStatusMessage(
34130
+ theme.cyan(
34131
+ `Modo alterado para: ${this.addLoginMode === "password" ? "Senha" : "C\xF3digo E-mail (Sem Senha)"}`
34132
+ )
34133
+ );
34134
+ return true;
34135
+ }
34136
+ }
33637
34137
  if (key.name === "hover" && key.mouse) {
33638
34138
  const { row, col } = key.mouse;
33639
34139
  const leftPad = this.lastModalLeftPad || 0;
33640
34140
  const relCol = col - leftPad;
33641
- if (row === 5 || row === 6) {
34141
+ if (row === 6) {
33642
34142
  if (this.modalHoveredField !== "email") {
33643
34143
  this.modalHoveredField = "email";
33644
34144
  return true;
33645
34145
  }
33646
- } else if (row === 7 || row === 8) {
33647
- if (this.modalHoveredField !== "password") {
33648
- this.modalHoveredField = "password";
34146
+ } else if (row === 7) {
34147
+ const field = this.addLoginMode === "password" ? "password" : "code";
34148
+ if (this.modalHoveredField !== field) {
34149
+ this.modalHoveredField = field;
33649
34150
  return true;
33650
34151
  }
33651
34152
  } else if (row === 9) {
33652
- const btn = relCol <= 24 ? "save" : "cancel";
34153
+ const btn = relCol <= 28 ? "save" : relCol <= 49 ? "cancel" : "mode";
33653
34154
  if (this.modalHoveredField !== btn) {
33654
34155
  this.modalHoveredField = btn;
33655
34156
  return true;
@@ -33663,56 +34164,77 @@ var init_accounts_view = __esm({
33663
34164
  const { row, col } = key.mouse;
33664
34165
  const leftPad = this.lastModalLeftPad || 0;
33665
34166
  const relCol = col - leftPad;
33666
- if (row === 5 || row === 6) {
34167
+ if (row === 6) {
33667
34168
  this.addActiveField = "email";
33668
34169
  return true;
33669
34170
  }
33670
- if (row === 7 || row === 8) {
33671
- this.addActiveField = "password";
34171
+ if (row === 7) {
34172
+ if (this.addLoginMode === "password") {
34173
+ this.addActiveField = "password";
34174
+ } else if (this.isOtpCodeSent) {
34175
+ this.addActiveField = "code";
34176
+ }
33672
34177
  return true;
33673
34178
  }
33674
34179
  if (row === 9) {
33675
- if (relCol <= 24) {
34180
+ if (relCol <= 28) {
33676
34181
  await this.saveModalAccount();
33677
34182
  return true;
33678
- } else {
33679
- this.isAddModalOpen = false;
33680
- this.addEmailInput = "";
33681
- this.addPasswordInput = "";
33682
- this.addEmailCursor = 0;
33683
- this.addPasswordCursor = 0;
34183
+ } else if (relCol <= 49) {
34184
+ this.resetAddModalState();
33684
34185
  return true;
34186
+ } else {
34187
+ if (!this.isOtpCodeSent) {
34188
+ this.addLoginMode = this.addLoginMode === "password" ? "otp" : "password";
34189
+ this.addActiveField = "email";
34190
+ this.setStatusMessage(
34191
+ theme.cyan(
34192
+ `Modo alterado para: ${this.addLoginMode === "password" ? "Senha" : "C\xF3digo E-mail (Sem Senha)"}`
34193
+ )
34194
+ );
34195
+ return true;
34196
+ }
33685
34197
  }
33686
34198
  }
33687
34199
  }
33688
34200
  if (key.name === "up" || key.name === "down") {
33689
- this.addActiveField = this.addActiveField === "email" ? "password" : "email";
34201
+ if (this.addLoginMode === "password") {
34202
+ this.addActiveField = this.addActiveField === "email" ? "password" : "email";
34203
+ } else if (this.isOtpCodeSent) {
34204
+ this.addActiveField = this.addActiveField === "email" ? "code" : "email";
34205
+ }
33690
34206
  return true;
33691
34207
  }
33692
34208
  if (key.name === "left") {
33693
34209
  if (this.addActiveField === "email") {
33694
34210
  this.addEmailCursor = Math.max(0, this.addEmailCursor - 1);
33695
- } else {
34211
+ } else if (this.addActiveField === "password") {
33696
34212
  this.addPasswordCursor = Math.max(0, this.addPasswordCursor - 1);
34213
+ } else {
34214
+ this.addOtpCodeCursor = Math.max(0, this.addOtpCodeCursor - 1);
33697
34215
  }
33698
34216
  return true;
33699
34217
  }
33700
34218
  if (key.name === "right") {
33701
34219
  if (this.addActiveField === "email") {
33702
34220
  this.addEmailCursor = Math.min(this.addEmailInput.length, this.addEmailCursor + 1);
33703
- } else {
34221
+ } else if (this.addActiveField === "password") {
33704
34222
  this.addPasswordCursor = Math.min(this.addPasswordInput.length, this.addPasswordCursor + 1);
34223
+ } else {
34224
+ this.addOtpCodeCursor = Math.min(this.addOtpCodeInput.length, this.addOtpCodeCursor + 1);
33705
34225
  }
33706
34226
  return true;
33707
34227
  }
33708
34228
  if (key.name === "home") {
33709
34229
  if (this.addActiveField === "email") this.addEmailCursor = 0;
33710
- else this.addPasswordCursor = 0;
34230
+ else if (this.addActiveField === "password") this.addPasswordCursor = 0;
34231
+ else this.addOtpCodeCursor = 0;
33711
34232
  return true;
33712
34233
  }
33713
34234
  if (key.name === "end") {
33714
34235
  if (this.addActiveField === "email") this.addEmailCursor = this.addEmailInput.length;
33715
- else this.addPasswordCursor = this.addPasswordInput.length;
34236
+ else if (this.addActiveField === "password") this.addPasswordCursor = this.addPasswordInput.length;
34237
+ else this.addOtpCodeCursor = this.addOtpCodeInput.length;
33716
34238
  return true;
33717
34239
  }
33718
34240
  if (key.ctrl && (key.name === "v" || key.raw === "")) {
@@ -33721,9 +34243,12 @@ var init_accounts_view = __esm({
33721
34243
  if (this.addActiveField === "email") {
33722
34244
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor) + pasted + this.addEmailInput.slice(this.addEmailCursor);
33723
34245
  this.addEmailCursor += pasted.length;
33724
- } else {
34246
+ } else if (this.addActiveField === "password") {
33725
34247
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor) + pasted + this.addPasswordInput.slice(this.addPasswordCursor);
33726
34248
  this.addPasswordCursor += pasted.length;
34249
+ } else {
34250
+ this.addOtpCodeInput = this.addOtpCodeInput.slice(0, this.addOtpCodeCursor) + pasted + this.addOtpCodeInput.slice(this.addOtpCodeCursor);
34251
+ this.addOtpCodeCursor += pasted.length;
33727
34252
  }
33728
34253
  return true;
33729
34254
  }
@@ -33732,9 +34257,12 @@ var init_accounts_view = __esm({
33732
34257
  if (this.addActiveField === "email") {
33733
34258
  this.addEmailInput = "";
33734
34259
  this.addEmailCursor = 0;
33735
- } else {
34260
+ } else if (this.addActiveField === "password") {
33736
34261
  this.addPasswordInput = "";
33737
34262
  this.addPasswordCursor = 0;
34263
+ } else {
34264
+ this.addOtpCodeInput = "";
34265
+ this.addOtpCodeCursor = 0;
33738
34266
  }
33739
34267
  return true;
33740
34268
  }
@@ -33744,11 +34272,16 @@ var init_accounts_view = __esm({
33744
34272
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor - 1) + this.addEmailInput.slice(this.addEmailCursor);
33745
34273
  this.addEmailCursor--;
33746
34274
  }
33747
- } else {
34275
+ } else if (this.addActiveField === "password") {
33748
34276
  if (this.addPasswordCursor > 0) {
33749
34277
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor - 1) + this.addPasswordInput.slice(this.addPasswordCursor);
33750
34278
  this.addPasswordCursor--;
33751
34279
  }
34280
+ } else {
34281
+ if (this.addOtpCodeCursor > 0) {
34282
+ this.addOtpCodeInput = this.addOtpCodeInput.slice(0, this.addOtpCodeCursor - 1) + this.addOtpCodeInput.slice(this.addOtpCodeCursor);
34283
+ this.addOtpCodeCursor--;
34284
+ }
33752
34285
  }
33753
34286
  return true;
33754
34287
  }
@@ -33757,10 +34290,14 @@ var init_accounts_view = __esm({
33757
34290
  if (this.addEmailCursor < this.addEmailInput.length) {
33758
34291
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor) + this.addEmailInput.slice(this.addEmailCursor + 1);
33759
34292
  }
33760
- } else {
34293
+ } else if (this.addActiveField === "password") {
33761
34294
  if (this.addPasswordCursor < this.addPasswordInput.length) {
33762
34295
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor) + this.addPasswordInput.slice(this.addPasswordCursor + 1);
33763
34296
  }
34297
+ } else {
34298
+ if (this.addOtpCodeCursor < this.addOtpCodeInput.length) {
34299
+ this.addOtpCodeInput = this.addOtpCodeInput.slice(0, this.addOtpCodeCursor) + this.addOtpCodeInput.slice(this.addOtpCodeCursor + 1);
34300
+ }
33764
34301
  }
33765
34302
  return true;
33766
34303
  }
@@ -33773,9 +34310,14 @@ var init_accounts_view = __esm({
33773
34310
  if (this.addActiveField === "email") {
33774
34311
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor) + key.char + this.addEmailInput.slice(this.addEmailCursor);
33775
34312
  this.addEmailCursor += key.char.length;
33776
- } else {
34313
+ } else if (this.addActiveField === "password") {
33777
34314
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor) + key.char + this.addPasswordInput.slice(this.addPasswordCursor);
33778
34315
  this.addPasswordCursor += key.char.length;
34316
+ } else if (this.addActiveField === "code") {
34317
+ if (this.addOtpCodeInput.length < 10) {
34318
+ this.addOtpCodeInput = this.addOtpCodeInput.slice(0, this.addOtpCodeCursor) + key.char + this.addOtpCodeInput.slice(this.addOtpCodeCursor);
34319
+ this.addOtpCodeCursor += key.char.length;
34320
+ }
33779
34321
  }
33780
34322
  return true;
33781
34323
  }
@@ -33888,13 +34430,13 @@ var init_accounts_view = __esm({
33888
34430
  return true;
33889
34431
  }
33890
34432
  if (col >= leftW) {
33891
- if (row === 15) {
33892
- const actionRow = col < leftW + 18 ? 15 : 21;
34433
+ if (row === 16) {
34434
+ const actionRow = col < leftW + 18 ? 16 : 22;
33893
34435
  if (this.hoveredActionRow !== actionRow) {
33894
34436
  this.hoveredActionRow = actionRow;
33895
34437
  return true;
33896
34438
  }
33897
- } else if (row >= 16 && row <= 20) {
34439
+ } else if (row >= 17 && row <= 21) {
33898
34440
  if (this.hoveredActionRow !== row) {
33899
34441
  this.hoveredActionRow = row;
33900
34442
  return true;
@@ -33920,7 +34462,7 @@ var init_accounts_view = __esm({
33920
34462
  }
33921
34463
  }
33922
34464
  if (col >= leftW) {
33923
- if (row === 15) {
34465
+ if (row === 16) {
33924
34466
  if (col < leftW + 18) {
33925
34467
  await this.handleKey({ name: "a", ctrl: false, shift: false, meta: false });
33926
34468
  } else {
@@ -33928,23 +34470,23 @@ var init_accounts_view = __esm({
33928
34470
  }
33929
34471
  return true;
33930
34472
  }
33931
- if (row === 16) {
34473
+ if (row === 17) {
33932
34474
  await this.handleKey({ name: "d", ctrl: false, shift: false, meta: false });
33933
34475
  return true;
33934
34476
  }
33935
- if (row === 17) {
34477
+ if (row === 18) {
33936
34478
  await this.handleKey({ name: "c", ctrl: false, shift: false, meta: false });
33937
34479
  return true;
33938
34480
  }
33939
- if (row === 18) {
34481
+ if (row === 19) {
33940
34482
  await this.handleKey({ name: "z", ctrl: false, shift: false, meta: false });
33941
34483
  return true;
33942
34484
  }
33943
- if (row === 19) {
34485
+ if (row === 20) {
33944
34486
  await this.handleKey({ name: "x", ctrl: false, shift: false, meta: false });
33945
34487
  return true;
33946
34488
  }
33947
- if (row === 20) {
34489
+ if (row === 21) {
33948
34490
  await this.handleKey({ name: "l", ctrl: false, shift: false, meta: false });
33949
34491
  return true;
33950
34492
  }
@@ -34085,9 +34627,10 @@ var init_accounts_view = __esm({
34085
34627
  rightContent.push("");
34086
34628
  rightContent.push("");
34087
34629
  rightContent.push("");
34630
+ rightContent.push("");
34088
34631
  rightContent.push(` ${theme.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}`);
34089
- const btnA = this.hoveredActionRow === 15 ? theme.bgHover(` ${theme.cyan("[ A ] Adicionar")} `) : `${theme.cyan("[ A ]")} Adicionar`;
34090
- const btnB = this.hoveredActionRow === 21 ? theme.bgHover(` ${theme.cyan("[ B ] Em Lote")} `) : `${theme.cyan("[ B ]")} Em Lote`;
34632
+ const btnA = this.hoveredActionRow === 16 ? theme.bgHover(` ${theme.cyan("[ A ] Adicionar")} `) : ` ${theme.cyan("[ A ]")} Adicionar `;
34633
+ const btnB = this.hoveredActionRow === 22 ? theme.bgHover(` ${theme.cyan("[ B ] Em Lote")} `) : ` ${theme.cyan("[ B ]")} Em Lote `;
34091
34634
  rightContent.push(` ${btnA} ${btnB}`);
34092
34635
  } else {
34093
34636
  const email = truncate(selected.emailOrName, 18);
@@ -34112,14 +34655,14 @@ var init_accounts_view = __esm({
34112
34655
  rightContent.push("");
34113
34656
  }
34114
34657
  rightContent.push(` ${theme.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}`);
34115
- const btnA = this.hoveredActionRow === 15 ? theme.bgHover(` ${theme.cyan("[ A ] Adicionar")} `) : `${theme.cyan("[ A ]")} Adicionar`;
34116
- const btnB = this.hoveredActionRow === 21 ? theme.bgHover(` ${theme.cyan("[ B ] Em Lote")} `) : `${theme.cyan("[ B ]")} Em Lote`;
34658
+ const btnA = this.hoveredActionRow === 16 ? theme.bgHover(` ${theme.cyan("[ A ] Adicionar")} `) : ` ${theme.cyan("[ A ]")} Adicionar `;
34659
+ const btnB = this.hoveredActionRow === 22 ? theme.bgHover(` ${theme.cyan("[ B ] Em Lote")} `) : ` ${theme.cyan("[ B ]")} Em Lote `;
34117
34660
  rightContent.push(` ${btnA} ${btnB}`);
34118
- rightContent.push(` ${this.hoveredActionRow === 16 ? theme.bgHover(` ${theme.red("[ D ] Remover Conta")} `) : `${theme.red("[ D ]")} Remover Conta`}`);
34119
- rightContent.push(` ${this.hoveredActionRow === 17 ? theme.bgHover(` ${theme.yellow("[ C ] Zerar Cooldown")} `) : `${theme.yellow("[ C ]")} Zerar Cooldown`}`);
34120
- rightContent.push(` ${this.hoveredActionRow === 18 ? theme.bgHover(` ${theme.green("[ Z ] Zerar Todas")} `) : `${theme.green("[ Z ]")} Zerar Todas`}`);
34121
- rightContent.push(` ${this.hoveredActionRow === 19 ? theme.bgHover(` ${theme.peach("[ X ] Limpar Chats (Conta)")} `) : `${theme.peach("[ X ]")} Limpar Chats (Conta)`}`);
34122
- rightContent.push(` ${this.hoveredActionRow === 20 ? theme.bgHover(` ${theme.red("[ L ] Limpar Todos os Chats")} `) : `${theme.red("[ L ]")} Limpar Todos os Chats`}`);
34661
+ rightContent.push(` ${this.hoveredActionRow === 17 ? theme.bgHover(` ${theme.red("[ D ] Remover Conta")} `) : ` ${theme.red("[ D ]")} Remover Conta `}`);
34662
+ rightContent.push(` ${this.hoveredActionRow === 18 ? theme.bgHover(` ${theme.yellow("[ C ] Zerar Cooldown")} `) : ` ${theme.yellow("[ C ]")} Zerar Cooldown `}`);
34663
+ rightContent.push(` ${this.hoveredActionRow === 19 ? theme.bgHover(` ${theme.green("[ Z ] Zerar Todas")} `) : ` ${theme.green("[ Z ]")} Zerar Todas `}`);
34664
+ rightContent.push(` ${this.hoveredActionRow === 20 ? theme.bgHover(` ${theme.peach("[ X ] Limpar Chats (Conta)")} `) : ` ${theme.peach("[ X ]")} Limpar Chats (Conta) `}`);
34665
+ rightContent.push(` ${this.hoveredActionRow === 21 ? theme.bgHover(` ${theme.red("[ L ] Limpar Todos os Chats")} `) : ` ${theme.red("[ L ]")} Limpar Todos os Chats `}`);
34123
34666
  }
34124
34667
  const rightBox = drawBox({
34125
34668
  title: "Inspe\xE7\xE3o de Conta",
@@ -34191,12 +34734,11 @@ var init_accounts_view = __esm({
34191
34734
  return modalBox.map((line) => padStr + line);
34192
34735
  }
34193
34736
  if (this.isAddModalOpen) {
34194
- const modalW = Math.min(width - 4, 66);
34737
+ const modalW = Math.min(width - 4, 76);
34195
34738
  this.lastModalLeftPad = Math.max(0, Math.floor((width - modalW) / 2));
34196
34739
  const isEmail = this.addActiveField === "email";
34197
34740
  const isPass = this.addActiveField === "password";
34198
- const emailHover = !isEmail && this.modalHoveredField === "email";
34199
- const passHover = !isPass && this.modalHoveredField === "password";
34741
+ const isCode = this.addActiveField === "code";
34200
34742
  let emailDisplay;
34201
34743
  if (isEmail) {
34202
34744
  if (this.addEmailInput.length === 0) {
@@ -34208,33 +34750,64 @@ var init_accounts_view = __esm({
34208
34750
  emailDisplay = `${theme.cyan(before)}${theme.inverse(at)}${theme.cyan(after)}`;
34209
34751
  }
34210
34752
  } else {
34211
- emailDisplay = this.addEmailInput ? emailHover ? theme.bgHover(` ${this.addEmailInput} `) : theme.cyan(` ${this.addEmailInput} `) : emailHover ? theme.bgHover(" (digite o e-mail) ") : theme.muted(" (digite o e-mail) ");
34212
- }
34213
- let passDisplay;
34214
- const maskedPass = "\u2022".repeat(this.addPasswordInput.length);
34215
- if (isPass) {
34216
- if (this.addPasswordInput.length === 0) {
34217
- passDisplay = `${theme.inverse(" ")} ${theme.dim("(digite a senha)")}`;
34753
+ emailDisplay = this.addEmailInput ? theme.cyan(this.addEmailInput) : theme.muted("(digite o e-mail)");
34754
+ }
34755
+ let secondFieldLabel;
34756
+ let secondFieldDisplay;
34757
+ if (this.addLoginMode === "password") {
34758
+ secondFieldLabel = "Senha:";
34759
+ const maskedPass = "\u2022".repeat(this.addPasswordInput.length);
34760
+ if (isPass) {
34761
+ if (this.addPasswordInput.length === 0) {
34762
+ secondFieldDisplay = `${theme.inverse(" ")} ${theme.dim("(digite a senha)")}`;
34763
+ } else {
34764
+ const before = maskedPass.slice(0, this.addPasswordCursor);
34765
+ const at = maskedPass[this.addPasswordCursor] || " ";
34766
+ const after = maskedPass.slice(this.addPasswordCursor + 1);
34767
+ secondFieldDisplay = `${theme.cyan(before)}${theme.inverse(at)}${theme.cyan(after)}`;
34768
+ }
34218
34769
  } else {
34219
- const before = maskedPass.slice(0, this.addPasswordCursor);
34220
- const at = maskedPass[this.addPasswordCursor] || " ";
34221
- const after = maskedPass.slice(this.addPasswordCursor + 1);
34222
- passDisplay = `${theme.cyan(before)}${theme.inverse(at)}${theme.cyan(after)}`;
34770
+ secondFieldDisplay = this.addPasswordInput ? theme.cyan(maskedPass) : theme.muted("(digite a senha)");
34223
34771
  }
34224
34772
  } else {
34225
- passDisplay = this.addPasswordInput ? passHover ? theme.bgHover(` ${maskedPass} `) : theme.cyan(` ${maskedPass} `) : passHover ? theme.bgHover(" (digite a senha) ") : theme.muted(" (digite a senha) ");
34773
+ secondFieldLabel = "C\xF3digo:";
34774
+ if (!this.isOtpCodeSent) {
34775
+ secondFieldDisplay = theme.dim("(ser\xE1 enviado p/ seu e-mail)");
34776
+ } else if (isCode) {
34777
+ if (this.addOtpCodeInput.length === 0) {
34778
+ secondFieldDisplay = `${theme.inverse(" ")} ${theme.dim("(digite o c\xF3digo de 6 d\xEDgitos)")}`;
34779
+ } else {
34780
+ const before = this.addOtpCodeInput.slice(0, this.addOtpCodeCursor);
34781
+ const at = this.addOtpCodeInput[this.addOtpCodeCursor] || " ";
34782
+ const after = this.addOtpCodeInput.slice(this.addOtpCodeCursor + 1);
34783
+ secondFieldDisplay = `${theme.cyan(before)}${theme.inverse(at)}${theme.cyan(after)}`;
34784
+ }
34785
+ } else {
34786
+ secondFieldDisplay = this.addOtpCodeInput ? theme.cyan(this.addOtpCodeInput) : theme.muted("(digite o c\xF3digo de 6 d\xEDgitos)");
34787
+ }
34788
+ }
34789
+ let saveBtnText;
34790
+ if (this.addLoginMode === "password") {
34791
+ saveBtnText = "[ Enter ] Salvar";
34792
+ } else if (!this.isOtpCodeSent) {
34793
+ saveBtnText = "[ Enter ] Enviar C\xF3digo";
34794
+ } else {
34795
+ saveBtnText = "[ Enter ] Confirmar C\xF3digo";
34226
34796
  }
34227
- const saveBtn = this.isValidatingAccount ? theme.yellow(" [ Validando... ] ") : this.modalHoveredField === "save" ? theme.bgHover(theme.green(" [ Enter ] Salvar ")) : theme.green("[ Enter ] Salvar");
34228
- const cancelBtn = this.modalHoveredField === "cancel" ? theme.bgHover(theme.red(" [ Esc ] Cancelar ")) : theme.muted("[ Esc ] Cancelar");
34797
+ const saveBtn = this.isValidatingAccount || this.isOtpRequesting ? theme.yellow(" [ Aguarde... ] ") : this.modalHoveredField === "save" ? theme.bgHover(` ${saveBtnText} `) : ` ${theme.green(saveBtnText)} `;
34798
+ const cancelBtn = this.modalHoveredField === "cancel" ? theme.bgHover(" [ Esc ] Cancelar ") : ` ${theme.muted("[ Esc ] Cancelar")} `;
34799
+ const modeBtnText = this.addLoginMode === "password" ? "[ Tab ] Sem Senha (OTP)" : "[ Tab ] Modo Senha";
34800
+ const modeBtn = this.modalHoveredField === "mode" ? theme.bgHover(` ${modeBtnText} `) : ` ${theme.cyan(modeBtnText)} `;
34229
34801
  const modalContent = [
34230
34802
  "",
34231
- ` ${theme.bold("E-mail:")} ${emailDisplay}`,
34232
- ` ${theme.bold("Senha:")} ${passDisplay}`,
34803
+ ` ${theme.bold("E-mail:")} ${emailDisplay}${this.isOtpCodeSent ? ` ${theme.green("\u2713 C\xF3digo Enviado")}` : ""}`,
34804
+ ` ${theme.bold(secondFieldLabel)} ${secondFieldDisplay}`,
34233
34805
  "",
34234
- ` ${saveBtn} ${cancelBtn} ${theme.dim("(\u2191\u2193/mouse alternar)")}`
34806
+ ` ${saveBtn} ${cancelBtn} ${modeBtn}`
34235
34807
  ];
34808
+ const modalTitle = this.addLoginMode === "password" ? "Adicionar Nova Conta Qwen (Login com Senha)" : "Adicionar Nova Conta Qwen (Login sem Senha - OTP)";
34236
34809
  const modalBox = drawBox({
34237
- title: "Adicionar Nova Conta Qwen (Login)",
34810
+ title: modalTitle,
34238
34811
  width: modalW,
34239
34812
  height: Math.min(contentH, 11),
34240
34813
  borderColor: theme.borderActive,