qwenproxy-cli 1.6.1 → 1.6.3

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();
@@ -6589,7 +6882,24 @@ async function refreshAccountToken(accountId) {
6589
6882
  return { success: false, error: "Could not refresh or re-authenticate token" };
6590
6883
  }
6591
6884
  async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.timeouts.headers, triggerGraceMs = HEADER_CAPTURE_TRIGGER_GRACE_MS) {
6592
- const page = pageOverride ?? accountPages.get(accountId);
6885
+ let page = pageOverride ?? accountPages.get(accountId);
6886
+ if (!page || page.isClosed()) {
6887
+ const { isRunningUnderNodeTest: isRunningUnderNodeTest4 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
6888
+ if (!isRunningUnderNodeTest4()) {
6889
+ const { getAccountCredentials: getAccountCredentials2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
6890
+ const creds = getAccountCredentials2(accountId);
6891
+ if (creds) {
6892
+ await initPlaywrightForAccount(
6893
+ creds,
6894
+ config.playwright.headless,
6895
+ config.playwright.browser,
6896
+ { skipHeaderCapture: true }
6897
+ ).catch(() => {
6898
+ });
6899
+ page = accountPages.get(accountId);
6900
+ }
6901
+ }
6902
+ }
6593
6903
  if (!page || page.isClosed()) {
6594
6904
  throw new Error(`Playwright page unavailable for header capture: ${accountId}`);
6595
6905
  }
@@ -7232,16 +7542,38 @@ async function refreshHeaders(accountId, timeoutMs = config.timeouts.headers, fo
7232
7542
  release();
7233
7543
  }
7234
7544
  }
7235
- async function withAccountPage(accountId, fn, timeoutMs = ACCOUNT_PAGE_OPERATION_TIMEOUT_MS, mutexTimeoutMs = PLAYWRIGHT_MUTEX_WAIT_MS, recoverOnTimeout = true) {
7545
+ async function ensureAccountPageAvailable(accountId) {
7236
7546
  const inFlightInit = inFlightAccountInits.get(accountId);
7237
7547
  if (inFlightInit) {
7238
7548
  await inFlightInit.catch(() => {
7239
7549
  });
7240
7550
  }
7241
- const page = accountPages.get(accountId);
7551
+ let page = accountPages.get(accountId);
7552
+ if (page && !page.isClosed()) {
7553
+ return page;
7554
+ }
7555
+ const { isRunningUnderNodeTest: isRunningUnderNodeTest4 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
7556
+ if (isRunningUnderNodeTest4()) {
7557
+ throw new Error(`Playwright page unavailable for account: ${accountId}`);
7558
+ }
7559
+ const { getAccountCredentials: getAccountCredentials2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
7560
+ const creds = getAccountCredentials2(accountId);
7561
+ if (!creds) {
7562
+ throw new Error(`Playwright page unavailable for account: ${accountId}`);
7563
+ }
7564
+ await initPlaywrightForAccount(
7565
+ creds,
7566
+ config.playwright.headless,
7567
+ config.playwright.browser
7568
+ );
7569
+ page = accountPages.get(accountId);
7242
7570
  if (!page || page.isClosed()) {
7243
7571
  throw new Error(`Playwright page unavailable for account: ${accountId}`);
7244
7572
  }
7573
+ return page;
7574
+ }
7575
+ async function withAccountPage(accountId, fn, timeoutMs = ACCOUNT_PAGE_OPERATION_TIMEOUT_MS, mutexTimeoutMs = PLAYWRIGHT_MUTEX_WAIT_MS, recoverOnTimeout = true) {
7576
+ const page = await ensureAccountPageAvailable(accountId);
7245
7577
  const release = await acquireAccountMutex(
7246
7578
  accountId,
7247
7579
  `page:${accountId.substring(0, 12)}`,
@@ -7260,7 +7592,7 @@ async function withAccountPage(accountId, fn, timeoutMs = ACCOUNT_PAGE_OPERATION
7260
7592
  return result;
7261
7593
  } catch (error) {
7262
7594
  const message = getErrorMessage(error);
7263
- if (recoverOnTimeout && message.includes("Playwright page operation timed out")) {
7595
+ if (recoverOnTimeout && message.includes("Playwright page operation timed out") && (!page || page.isClosed())) {
7264
7596
  console.warn(
7265
7597
  `\u23F1\uFE0F [Playwright] Resetting account context after a stuck page operation: ${accountId}`
7266
7598
  );
@@ -7542,8 +7874,10 @@ async function evictIdlePlaywrightContextsToLimit() {
7542
7874
  if (accountPages.size <= max) return 0;
7543
7875
  const candidates = priorityOrderForEviction(
7544
7876
  Array.from(accountPages.keys()).filter((accountId) => {
7877
+ if (isAccountServingStream(accountId)) return false;
7878
+ if (isAccountRecentlyActive(accountId, 3e4)) return false;
7545
7879
  const mutex = accountMutexes.get(accountId);
7546
- return mutex?.isIdle() && !isAccountServingStream(accountId);
7880
+ return mutex?.isIdle();
7547
7881
  })
7548
7882
  ).map((accountId) => ({
7549
7883
  accountId,
@@ -7809,7 +8143,7 @@ async function getTokenDiagnostics(accountId) {
7809
8143
  }
7810
8144
  };
7811
8145
  }
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;
8146
+ 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
8147
  var init_playwright = __esm({
7814
8148
  "src/services/playwright.ts"() {
7815
8149
  "use strict";
@@ -7854,11 +8188,13 @@ var init_playwright = __esm({
7854
8188
  PLAYWRIGHT_MUTEX_WAIT_MS = 6e4;
7855
8189
  ACCOUNT_PAGE_OPERATION_TIMEOUT_MS = config.timeouts.page;
7856
8190
  SESSION_PROBE_NAVIGATION_TIMEOUT_MS = 15e3;
7857
- HEADER_CAPTURE_TRIGGER_GRACE_MS = 15e3;
7858
- FIRST_TRIGGER_GRACE_MS = 8e3;
8191
+ HEADER_CAPTURE_TRIGGER_GRACE_MS = 2e4;
8192
+ FIRST_TRIGGER_GRACE_MS = 12e3;
7859
8193
  HEADER_CAPTURE_TRIGGER_ATTEMPTS = 3;
7860
8194
  CHAT_INPUT_APPEAR_TIMEOUT_MS = 15e3;
7861
8195
  CHAT_INPUT_ACTION_TIMEOUT_MS = 1e4;
8196
+ activeOtpSessions = /* @__PURE__ */ new Map();
8197
+ mockOtpSessions = /* @__PURE__ */ new Map();
7862
8198
  PROFILE_RESET_TIMEOUT_MS = Math.max(9e4, config.timeouts.headers);
7863
8199
  setWafContextResetListener((accountId) => {
7864
8200
  if (!accountPages.has(accountId)) return;
@@ -9333,6 +9669,42 @@ var init_helpers = __esm({
9333
9669
  }
9334
9670
  });
9335
9671
 
9672
+ // src/utils/overload-detector.ts
9673
+ function isOverloadMessage(content) {
9674
+ if (!content) return false;
9675
+ const text = content.trim();
9676
+ if (!text || text.length > 500) return false;
9677
+ if (text.includes("```") || text.includes("<tool_call") || text.includes("<qpx_call") || text.includes("</")) {
9678
+ return false;
9679
+ }
9680
+ return OVERLOAD_PATTERNS.some((pattern) => pattern.test(text));
9681
+ }
9682
+ var OVERLOAD_PATTERNS, OVERLOAD_COOLDOWN_MS;
9683
+ var init_overload_detector = __esm({
9684
+ "src/utils/overload-detector.ts"() {
9685
+ "use strict";
9686
+ OVERLOAD_PATTERNS = [
9687
+ /high\s+demand/i,
9688
+ /problem\s+connecting/i,
9689
+ /try\s+again\s+later/i,
9690
+ /temporarily\s+unavailable/i,
9691
+ /service\s+(is\s+)?overloaded/i,
9692
+ /too\s+many\s+requests/i,
9693
+ /server\s+is\s+busy/i,
9694
+ /experiencing\s+high\s+(traffic|volume|load)/i,
9695
+ /unable\s+to\s+connect/i,
9696
+ /connection\s+(problem|error|issue)/i,
9697
+ /alta\s+demanda/i,
9698
+ /problema\s+de\s+conex/i,
9699
+ /tente\s+novamente\s+mais\s+tarde/i,
9700
+ /servidor\s+ocupado/i,
9701
+ /indispon[íi]vel\s+no\s+momento/i,
9702
+ /servi[çc]o\s+est[áa]\s+com\s+alta\s+demanda/i
9703
+ ];
9704
+ OVERLOAD_COOLDOWN_MS = 5 * 60 * 1e3;
9705
+ }
9706
+ });
9707
+
9336
9708
  // src/routes/chat/retry-policy.ts
9337
9709
  function errMessage(err) {
9338
9710
  if (err instanceof Error) return err.message || "";
@@ -9410,6 +9782,7 @@ function isAccountInitializationError(err) {
9410
9782
  function isQuotaLikeError(err) {
9411
9783
  if (isChatNotExistError(err) || isInvalidInputError(err)) return false;
9412
9784
  const code = errCode(err).toLowerCase();
9785
+ if (code === "server_overloaded" || code === "overload") return false;
9413
9786
  const message = errMessage(err).toLowerCase();
9414
9787
  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
9788
  code === "rate_limit_exceeded" && (message.includes("quota") || message.includes("rate") || message.includes("limit") || message.includes("membership") || message.includes("demanda") || message.includes("demand"));
@@ -9463,6 +9836,14 @@ function isInternalServerError(err) {
9463
9836
  const message = errMessage(err).toLowerCase();
9464
9837
  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
9838
  }
9839
+ function isOverloadError(err) {
9840
+ const code = errCode(err).toLowerCase();
9841
+ if (code === "quota_limit" || code === "ratelimited" || code === "rate_limit" || code === "rate_limit_exceeded" || code === "membership_limit" || code === "internal_error" || code === "internal_server_error") {
9842
+ return false;
9843
+ }
9844
+ if (code === "server_overloaded" || code === "overload") return true;
9845
+ return !code && isOverloadMessage(errMessage(err));
9846
+ }
9466
9847
  function makeRetryAction(reason, overrides = {}) {
9467
9848
  return {
9468
9849
  retryable: true,
@@ -9487,6 +9868,15 @@ function classifyRetryAction(err, options) {
9487
9868
  if (isTerminalLocalError(err)) {
9488
9869
  return makeRetryAction("terminal_local", { retryable: false });
9489
9870
  }
9871
+ if (err instanceof PersonalizationSyncError) {
9872
+ return makeRetryAction("personalization_sync_failed", {
9873
+ switchAccount: true,
9874
+ forceNewChat: true,
9875
+ retryAfterMs: baseDelayMs,
9876
+ accountCooldownMs: 0,
9877
+ accountCooldownReason: "PersonalizationFailed"
9878
+ });
9879
+ }
9490
9880
  const message = errMessage(err).toLowerCase();
9491
9881
  const code = errCode(err).toLowerCase();
9492
9882
  if (isAccountInitializationError(err)) {
@@ -9503,15 +9893,6 @@ function classifyRetryAction(err, options) {
9503
9893
  retryAfterMs: Math.min(baseDelayMs, 1e3)
9504
9894
  });
9505
9895
  }
9506
- if (err instanceof PersonalizationSyncError) {
9507
- return makeRetryAction("personalization_sync_failed", {
9508
- switchAccount: true,
9509
- forceNewChat: true,
9510
- retryAfterMs: baseDelayMs,
9511
- accountCooldownMs: 0,
9512
- accountCooldownReason: "PersonalizationFailed"
9513
- });
9514
- }
9515
9896
  if (code === "createchatinvalidresponse" || code === "createchatfailed" || code === "unauthorized" || message.includes("401 n\xE3o autorizado") || message.includes("n\xE3o tem permiss\xE3o para acessar") || message.includes("401 unauthorized") || message.includes('"code":"unauthorized"') || message.includes('"code": "unauthorized"') || message.includes("token has expired")) {
9516
9897
  return makeRetryAction("account_initialization_failed", {
9517
9898
  switchAccount: true,
@@ -9569,6 +9950,17 @@ function classifyRetryAction(err, options) {
9569
9950
  accountCooldownReason: quota.accountCooldownReason
9570
9951
  });
9571
9952
  }
9953
+ if (isOverloadError(err)) {
9954
+ const typed = err;
9955
+ return makeRetryAction("server_busy", {
9956
+ switchAccount: true,
9957
+ forceNewChat: true,
9958
+ retryWithFullPrompt: true,
9959
+ retryAfterMs: typed.retryAfterMs ?? 3e3,
9960
+ accountCooldownMs: OVERLOAD_COOLDOWN_MS,
9961
+ accountCooldownReason: "ServerOverloaded"
9962
+ });
9963
+ }
9572
9964
  if (isInternalServerError(err) && !(err instanceof QwenUpstreamError)) {
9573
9965
  const typed = err;
9574
9966
  return makeRetryAction("upstream_internal_error", {
@@ -9592,11 +9984,13 @@ function classifyRetryAction(err, options) {
9592
9984
  }
9593
9985
  if (err instanceof RetryableQwenStreamError) {
9594
9986
  const typed = err;
9595
- return makeRetryAction("explicit_retryable", {
9987
+ return makeRetryAction(typed.reason || "explicit_retryable", {
9596
9988
  switchAccount: typed.switchAccount !== false,
9597
9989
  forceNewChat: typed.forceNewChat === true,
9598
9990
  retryWithFullPrompt: typed.retryWithFullPrompt === true,
9599
- retryAfterMs: typed.retryAfterMs ?? baseDelayMs
9991
+ retryAfterMs: typed.retryAfterMs ?? baseDelayMs,
9992
+ accountCooldownMs: typed.accountCooldownMs,
9993
+ accountCooldownReason: typed.accountCooldownReason
9600
9994
  });
9601
9995
  }
9602
9996
  if (unknownEnabled) {
@@ -9629,6 +10023,9 @@ function toRetryableStreamError(errCode2, errDetails, options) {
9629
10023
  error.retryWithFullPrompt = merged.retryWithFullPrompt;
9630
10024
  error.switchAccount = merged.switchAccount;
9631
10025
  error.dropFiles = merged.dropFiles;
10026
+ error.accountCooldownMs = merged.accountCooldownMs;
10027
+ error.accountCooldownReason = merged.accountCooldownReason;
10028
+ error.reason = merged.reason;
9632
10029
  return error;
9633
10030
  }
9634
10031
  function throwFromSseUpstreamError(errCode2, errDetails) {
@@ -9714,6 +10111,7 @@ var init_retry_policy = __esm({
9714
10111
  init_qwen();
9715
10112
  init_errors();
9716
10113
  init_helpers();
10114
+ init_overload_detector();
9717
10115
  init_account_manager();
9718
10116
  }
9719
10117
  });
@@ -11871,7 +12269,8 @@ async function requestQwenPersonalizationInBrowser(accountId, method, path21, he
11871
12269
  payload === void 0 ? void 0 : JSON.stringify(payload),
11872
12270
  {
11873
12271
  settingsPage: true,
11874
- referrer: qwenUrl("/settings/personalization")
12272
+ referrer: qwenUrl("/settings/personalization"),
12273
+ noMutexRecovery: true
11875
12274
  }
11876
12275
  );
11877
12276
  const { raw, json } = await readJsonTextResponse(response);
@@ -12372,8 +12771,9 @@ async function syncQwenRequestPersonalizationInternal(instruction, accountId, me
12372
12771
  const returnedInstruction = json?.data?.personalization?.instruction;
12373
12772
  const returned = textSize(returnedInstruction);
12374
12773
  let stored = { chars: null, bytes: null, hash: null };
12774
+ const matchReturned = isEmptyInstruction && (!returnedInstruction || returned.chars === 0) || returned.hash !== null && returned.hash === sent.hash;
12375
12775
  let verifyData = null;
12376
- if (config.qwen.personalizationVerifyGet) {
12776
+ if (config.qwen.personalizationVerifyGet && !matchReturned) {
12377
12777
  const { json: verifyJson } = await requestQwenPersonalizationInBrowser(
12378
12778
  accountId,
12379
12779
  "GET",
@@ -12383,7 +12783,6 @@ async function syncQwenRequestPersonalizationInternal(instruction, accountId, me
12383
12783
  verifyData = verifyJson?.data?.personalization;
12384
12784
  stored = textSize(verifyData?.instruction);
12385
12785
  }
12386
- const matchReturned = isEmptyInstruction && (!returnedInstruction || returned.chars === 0) || returned.hash !== null && returned.hash === sent.hash;
12387
12786
  const matchStored = stored.hash === null ? null : isEmptyInstruction && (!verifyData?.instruction || stored.chars === 0) || stored.hash === sent.hash;
12388
12787
  const applied = matchReturned || matchStored === true;
12389
12788
  if (syncHash && applied) {
@@ -12757,6 +13156,17 @@ async function fetchQwenModels(accountId) {
12757
13156
  );
12758
13157
  return cached.models;
12759
13158
  }
13159
+ if (accountId && !isAuthMockEnabled() && !isPlaywrightInitialized(accountId)) {
13160
+ for (const [, entry] of modelsCache.entries()) {
13161
+ if (entry && now - entry.fetchedAt < MODEL_CACHE_TTL_MS * 4) {
13162
+ syncModelMetadata(
13163
+ entry.models,
13164
+ accountId
13165
+ );
13166
+ return entry.models;
13167
+ }
13168
+ }
13169
+ }
12760
13170
  if (accountId && !isAuthMockEnabled() && isAccountBusy(accountId)) {
12761
13171
  try {
12762
13172
  const result = await withAccountPage(
@@ -17200,7 +17610,8 @@ ${loopReminder}` : truncation.prompt;
17200
17610
  const checkDeadline = async () => {
17201
17611
  try {
17202
17612
  const { isCaptchaRecoveryActive: isCaptchaRecoveryActive2 } = await Promise.resolve().then(() => (init_captcha_coordinator(), captcha_coordinator_exports));
17203
- if (currentAccountId && isCaptchaRecoveryActive2(currentAccountId)) {
17613
+ const { isPlaywrightInitializing: isPlaywrightInitializing2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
17614
+ if (currentAccountId && (isCaptchaRecoveryActive2(currentAccountId) || isPlaywrightInitializing2(currentAccountId))) {
17204
17615
  acquireDeadlineTimer = setTimeout(checkDeadline, 3e4);
17205
17616
  acquireDeadlineTimer.unref?.();
17206
17617
  return;
@@ -17611,8 +18022,8 @@ var init_account = __esm({
17611
18022
  init_tool_call_guard();
17612
18023
  init_retry_policy();
17613
18024
  MAX_ANTI_BOT_ROTATIONS = 1;
17614
- PERSONALIZATION_SYNC_DEADLINE_MS = 45e3;
17615
- COLD_ACCOUNT_PERSONALIZATION_SYNC_DEADLINE_MS = 6e4;
18025
+ PERSONALIZATION_SYNC_DEADLINE_MS = 9e4;
18026
+ COLD_ACCOUNT_PERSONALIZATION_SYNC_DEADLINE_MS = 12e4;
17616
18027
  chatLocks = /* @__PURE__ */ new Map();
17617
18028
  personalizationLocks = /* @__PURE__ */ new Map();
17618
18029
  }
@@ -20575,6 +20986,19 @@ async function processNonStreamingResponse(params) {
20575
20986
  isThinkingChunk = false;
20576
20987
  if (delta.content !== void 0) {
20577
20988
  const newContent = delta.content || "";
20989
+ if (isOverloadMessage(newContent)) {
20990
+ throw toRetryableStreamError(
20991
+ "server_overloaded",
20992
+ newContent,
20993
+ {
20994
+ switchAccount: true,
20995
+ forceNewChat: true,
20996
+ reason: "server_busy",
20997
+ accountCooldownMs: OVERLOAD_COOLDOWN_MS,
20998
+ accountCooldownReason: "ServerOverloaded"
20999
+ }
21000
+ );
21001
+ }
20578
21002
  const result = getIncrementalDelta(
20579
21003
  lastRawContent,
20580
21004
  newContent,
@@ -21642,6 +22066,19 @@ async function processStreamingResponse(params) {
21642
22066
  isThinkingChunk = false;
21643
22067
  if (delta.content !== void 0) {
21644
22068
  const newContent = delta.content || "";
22069
+ if (!emittedModelOutput && isOverloadMessage(newContent)) {
22070
+ throw toRetryableStreamError(
22071
+ "server_overloaded",
22072
+ newContent,
22073
+ {
22074
+ switchAccount: true,
22075
+ forceNewChat: true,
22076
+ reason: "server_busy",
22077
+ accountCooldownMs: OVERLOAD_COOLDOWN_MS,
22078
+ accountCooldownReason: "ServerOverloaded"
22079
+ }
22080
+ );
22081
+ }
21645
22082
  const result = getIncrementalDelta(
21646
22083
  lastRawContent,
21647
22084
  newContent,
@@ -22446,6 +22883,7 @@ var init_streaming = __esm({
22446
22883
  init_daily_usage();
22447
22884
  init_context_meter();
22448
22885
  init_helpers();
22886
+ init_overload_detector();
22449
22887
  MAX_INITIAL_PROTOCOL_BYTES = 64 * 1024;
22450
22888
  MID_STREAM_FAILURE_WINDOW_MS = 5 * 60 * 1e3;
22451
22889
  midStreamNetworkFailures = /* @__PURE__ */ new Map();
@@ -26385,7 +26823,7 @@ function getAppVersion() {
26385
26823
  }
26386
26824
  } catch {
26387
26825
  }
26388
- cachedVersion = "v1.6.1";
26826
+ cachedVersion = "v1.6.3";
26389
26827
  return cachedVersion;
26390
26828
  }
26391
26829
  var cachedVersion;
@@ -33248,10 +33686,16 @@ var init_accounts_view = __esm({
33248
33686
  isAddModalOpen = false;
33249
33687
  isBatchModalOpen = false;
33250
33688
  isValidatingAccount = false;
33689
+ isOtpRequesting = false;
33690
+ isOtpCodeSent = false;
33691
+ addLoginMode = "password";
33692
+ otpSessionId = null;
33251
33693
  addEmailInput = "";
33252
33694
  addPasswordInput = "";
33695
+ addOtpCodeInput = "";
33253
33696
  addEmailCursor = 0;
33254
33697
  addPasswordCursor = 0;
33698
+ addOtpCodeCursor = 0;
33255
33699
  addActiveField = "email";
33256
33700
  batchInput = "";
33257
33701
  batchCursor = 0;
@@ -33328,22 +33772,113 @@ var init_accounts_view = __esm({
33328
33772
  this.statusMessage = "";
33329
33773
  }, 4e3);
33330
33774
  }
33775
+ resetAddModalState() {
33776
+ if (this.otpSessionId && !process.env.NODE_TEST_CONTEXT) {
33777
+ const sid = this.otpSessionId;
33778
+ Promise.resolve().then(() => (init_playwright(), playwright_exports)).then(({ cancelEmailOtpLogin: cancelEmailOtpLogin2 }) => cancelEmailOtpLogin2(sid)).catch(() => {
33779
+ });
33780
+ }
33781
+ this.isAddModalOpen = false;
33782
+ this.isValidatingAccount = false;
33783
+ this.isOtpRequesting = false;
33784
+ this.isOtpCodeSent = false;
33785
+ this.otpSessionId = null;
33786
+ this.addEmailInput = "";
33787
+ this.addPasswordInput = "";
33788
+ this.addOtpCodeInput = "";
33789
+ this.addEmailCursor = 0;
33790
+ this.addPasswordCursor = 0;
33791
+ this.addOtpCodeCursor = 0;
33792
+ this.addActiveField = "email";
33793
+ this.addLoginMode = "password";
33794
+ }
33331
33795
  async saveModalAccount() {
33332
- if (this.isValidatingAccount) return;
33796
+ if (this.isValidatingAccount || this.isOtpRequesting) return;
33333
33797
  const email = this.addEmailInput.trim();
33798
+ if (!email) {
33799
+ this.setStatusMessage(theme.yellow("[!] E-mail \xE9 obrigat\xF3rio"));
33800
+ return;
33801
+ }
33802
+ if (this.addLoginMode === "otp") {
33803
+ if (!this.isOtpCodeSent) {
33804
+ if (process.env.NODE_TEST_CONTEXT) {
33805
+ this.isOtpCodeSent = true;
33806
+ this.addActiveField = "code";
33807
+ this.otpSessionId = "mock-otp-" + Date.now();
33808
+ this.setStatusMessage(theme.green("\u2713 C\xF3digo enviado para o e-mail!"));
33809
+ return;
33810
+ }
33811
+ this.isOtpRequesting = true;
33812
+ this.setStatusMessage(theme.yellow(`[...] Enviando c\xF3digo OTP para ${email}...`));
33813
+ try {
33814
+ const { startEmailOtpLogin: startEmailOtpLogin2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
33815
+ const res = await startEmailOtpLogin2(email, { headless: config.playwright.headless });
33816
+ this.isOtpRequesting = false;
33817
+ if (!res.success || !res.sessionId) {
33818
+ this.setStatusMessage(theme.red(`\u2717 Falha ao enviar c\xF3digo: ${res.error || "Erro desconhecido"}`));
33819
+ return;
33820
+ }
33821
+ this.otpSessionId = res.sessionId;
33822
+ this.isOtpCodeSent = true;
33823
+ this.addActiveField = "code";
33824
+ this.setStatusMessage(theme.green("\u2713 C\xF3digo enviado! Digite os 6 d\xEDgitos abaixo."));
33825
+ } catch (err) {
33826
+ this.isOtpRequesting = false;
33827
+ this.setStatusMessage(theme.red(`\u2717 Erro: ${err?.message || String(err)}`));
33828
+ }
33829
+ return;
33830
+ }
33831
+ const code = this.addOtpCodeInput.trim();
33832
+ if (!code) {
33833
+ this.setStatusMessage(theme.yellow("[!] Digite o c\xF3digo de 6 d\xEDgitos recebido por e-mail"));
33834
+ return;
33835
+ }
33836
+ if (process.env.NODE_TEST_CONTEXT) {
33837
+ try {
33838
+ const newAcc = addAccount(email, "");
33839
+ this.resetAddModalState();
33840
+ await this.refresh();
33841
+ this.setStatusMessage(theme.green(`\u2713 Conta ${email} salva via c\xF3digo OTP!`));
33842
+ } catch (err) {
33843
+ this.setStatusMessage(theme.red(`\u2717 Erro ao salvar: ${err?.message || String(err)}`));
33844
+ }
33845
+ return;
33846
+ }
33847
+ this.isValidatingAccount = true;
33848
+ this.setStatusMessage(theme.yellow("[...] Validando c\xF3digo e capturando sess\xE3o de 30 dias..."));
33849
+ try {
33850
+ const { verifyEmailOtpLogin: verifyEmailOtpLogin2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
33851
+ const res = await verifyEmailOtpLogin2(this.otpSessionId, code);
33852
+ this.isValidatingAccount = false;
33853
+ if (!res.success || !res.account) {
33854
+ this.setStatusMessage(theme.red(`\u2717 C\xF3digo inv\xE1lido: ${res.error || "Verifica\xE7\xE3o falhou"}`));
33855
+ return;
33856
+ }
33857
+ this.resetAddModalState();
33858
+ await this.refresh();
33859
+ this.setStatusMessage(theme.green(`\u2713 Conta ${res.account.email} autenticada via c\xF3digo OTP!`));
33860
+ if (process.stdout.isTTY) {
33861
+ const sManager = ServerManager.getInstance();
33862
+ const sState = sManager.getState();
33863
+ if (sState !== "online" && sState !== "warming") {
33864
+ void sManager.ensureStarted().then(() => this.refresh());
33865
+ }
33866
+ }
33867
+ } catch (err) {
33868
+ this.isValidatingAccount = false;
33869
+ this.setStatusMessage(theme.red(`\u2717 Erro de verifica\xE7\xE3o: ${err?.message || String(err)}`));
33870
+ }
33871
+ return;
33872
+ }
33334
33873
  const password = this.addPasswordInput.trim();
33335
- if (!email || !password) {
33874
+ if (!password) {
33336
33875
  this.setStatusMessage(theme.yellow("[!] E-mail e senha s\xE3o obrigat\xF3rios"));
33337
33876
  return;
33338
33877
  }
33339
33878
  if (process.env.NODE_TEST_CONTEXT) {
33340
33879
  try {
33341
33880
  const newAcc = addAccount(email, password);
33342
- this.isAddModalOpen = false;
33343
- this.addEmailInput = "";
33344
- this.addPasswordInput = "";
33345
- this.addEmailCursor = 0;
33346
- this.addPasswordCursor = 0;
33881
+ this.resetAddModalState();
33347
33882
  await this.refresh();
33348
33883
  this.setStatusMessage(theme.green(`\u2713 Conta ${email} salva! Conectando...`));
33349
33884
  } catch (err) {
@@ -33370,11 +33905,7 @@ var init_accounts_view = __esm({
33370
33905
  return;
33371
33906
  }
33372
33907
  const newAcc = addAccount(email, password, tempId);
33373
- this.isAddModalOpen = false;
33374
- this.addEmailInput = "";
33375
- this.addPasswordInput = "";
33376
- this.addEmailCursor = 0;
33377
- this.addPasswordCursor = 0;
33908
+ this.resetAddModalState();
33378
33909
  await this.refresh();
33379
33910
  this.setStatusMessage(theme.green(`\u2713 Conta ${email} validada e salva! Conectando...`));
33380
33911
  if (process.stdout.isTTY) {
@@ -33627,29 +34158,40 @@ var init_accounts_view = __esm({
33627
34158
  return true;
33628
34159
  }
33629
34160
  if (this.isAddModalOpen) {
33630
- if (this.isValidatingAccount) return true;
34161
+ if (this.isValidatingAccount || this.isOtpRequesting) return true;
33631
34162
  if (key.name === "escape") {
33632
- this.isAddModalOpen = false;
33633
- this.addEmailInput = "";
33634
- this.addPasswordInput = "";
34163
+ this.resetAddModalState();
33635
34164
  return true;
33636
34165
  }
34166
+ if (key.name === "tab") {
34167
+ if (!this.isOtpCodeSent) {
34168
+ this.addLoginMode = this.addLoginMode === "password" ? "otp" : "password";
34169
+ this.addActiveField = "email";
34170
+ this.setStatusMessage(
34171
+ theme.cyan(
34172
+ `Modo alterado para: ${this.addLoginMode === "password" ? "Senha" : "C\xF3digo E-mail (Sem Senha)"}`
34173
+ )
34174
+ );
34175
+ return true;
34176
+ }
34177
+ }
33637
34178
  if (key.name === "hover" && key.mouse) {
33638
34179
  const { row, col } = key.mouse;
33639
34180
  const leftPad = this.lastModalLeftPad || 0;
33640
34181
  const relCol = col - leftPad;
33641
- if (row === 5 || row === 6) {
34182
+ if (row === 6) {
33642
34183
  if (this.modalHoveredField !== "email") {
33643
34184
  this.modalHoveredField = "email";
33644
34185
  return true;
33645
34186
  }
33646
- } else if (row === 7 || row === 8) {
33647
- if (this.modalHoveredField !== "password") {
33648
- this.modalHoveredField = "password";
34187
+ } else if (row === 7) {
34188
+ const field = this.addLoginMode === "password" ? "password" : "code";
34189
+ if (this.modalHoveredField !== field) {
34190
+ this.modalHoveredField = field;
33649
34191
  return true;
33650
34192
  }
33651
34193
  } else if (row === 9) {
33652
- const btn = relCol <= 24 ? "save" : "cancel";
34194
+ const btn = relCol <= 28 ? "save" : relCol <= 49 ? "cancel" : "mode";
33653
34195
  if (this.modalHoveredField !== btn) {
33654
34196
  this.modalHoveredField = btn;
33655
34197
  return true;
@@ -33663,56 +34205,77 @@ var init_accounts_view = __esm({
33663
34205
  const { row, col } = key.mouse;
33664
34206
  const leftPad = this.lastModalLeftPad || 0;
33665
34207
  const relCol = col - leftPad;
33666
- if (row === 5 || row === 6) {
34208
+ if (row === 6) {
33667
34209
  this.addActiveField = "email";
33668
34210
  return true;
33669
34211
  }
33670
- if (row === 7 || row === 8) {
33671
- this.addActiveField = "password";
34212
+ if (row === 7) {
34213
+ if (this.addLoginMode === "password") {
34214
+ this.addActiveField = "password";
34215
+ } else if (this.isOtpCodeSent) {
34216
+ this.addActiveField = "code";
34217
+ }
33672
34218
  return true;
33673
34219
  }
33674
34220
  if (row === 9) {
33675
- if (relCol <= 24) {
34221
+ if (relCol <= 28) {
33676
34222
  await this.saveModalAccount();
33677
34223
  return true;
33678
- } else {
33679
- this.isAddModalOpen = false;
33680
- this.addEmailInput = "";
33681
- this.addPasswordInput = "";
33682
- this.addEmailCursor = 0;
33683
- this.addPasswordCursor = 0;
34224
+ } else if (relCol <= 49) {
34225
+ this.resetAddModalState();
33684
34226
  return true;
34227
+ } else {
34228
+ if (!this.isOtpCodeSent) {
34229
+ this.addLoginMode = this.addLoginMode === "password" ? "otp" : "password";
34230
+ this.addActiveField = "email";
34231
+ this.setStatusMessage(
34232
+ theme.cyan(
34233
+ `Modo alterado para: ${this.addLoginMode === "password" ? "Senha" : "C\xF3digo E-mail (Sem Senha)"}`
34234
+ )
34235
+ );
34236
+ return true;
34237
+ }
33685
34238
  }
33686
34239
  }
33687
34240
  }
33688
34241
  if (key.name === "up" || key.name === "down") {
33689
- this.addActiveField = this.addActiveField === "email" ? "password" : "email";
34242
+ if (this.addLoginMode === "password") {
34243
+ this.addActiveField = this.addActiveField === "email" ? "password" : "email";
34244
+ } else if (this.isOtpCodeSent) {
34245
+ this.addActiveField = this.addActiveField === "email" ? "code" : "email";
34246
+ }
33690
34247
  return true;
33691
34248
  }
33692
34249
  if (key.name === "left") {
33693
34250
  if (this.addActiveField === "email") {
33694
34251
  this.addEmailCursor = Math.max(0, this.addEmailCursor - 1);
33695
- } else {
34252
+ } else if (this.addActiveField === "password") {
33696
34253
  this.addPasswordCursor = Math.max(0, this.addPasswordCursor - 1);
34254
+ } else {
34255
+ this.addOtpCodeCursor = Math.max(0, this.addOtpCodeCursor - 1);
33697
34256
  }
33698
34257
  return true;
33699
34258
  }
33700
34259
  if (key.name === "right") {
33701
34260
  if (this.addActiveField === "email") {
33702
34261
  this.addEmailCursor = Math.min(this.addEmailInput.length, this.addEmailCursor + 1);
33703
- } else {
34262
+ } else if (this.addActiveField === "password") {
33704
34263
  this.addPasswordCursor = Math.min(this.addPasswordInput.length, this.addPasswordCursor + 1);
34264
+ } else {
34265
+ this.addOtpCodeCursor = Math.min(this.addOtpCodeInput.length, this.addOtpCodeCursor + 1);
33705
34266
  }
33706
34267
  return true;
33707
34268
  }
33708
34269
  if (key.name === "home") {
33709
34270
  if (this.addActiveField === "email") this.addEmailCursor = 0;
33710
- else this.addPasswordCursor = 0;
34271
+ else if (this.addActiveField === "password") this.addPasswordCursor = 0;
34272
+ else this.addOtpCodeCursor = 0;
33711
34273
  return true;
33712
34274
  }
33713
34275
  if (key.name === "end") {
33714
34276
  if (this.addActiveField === "email") this.addEmailCursor = this.addEmailInput.length;
33715
- else this.addPasswordCursor = this.addPasswordInput.length;
34277
+ else if (this.addActiveField === "password") this.addPasswordCursor = this.addPasswordInput.length;
34278
+ else this.addOtpCodeCursor = this.addOtpCodeInput.length;
33716
34279
  return true;
33717
34280
  }
33718
34281
  if (key.ctrl && (key.name === "v" || key.raw === "")) {
@@ -33721,9 +34284,12 @@ var init_accounts_view = __esm({
33721
34284
  if (this.addActiveField === "email") {
33722
34285
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor) + pasted + this.addEmailInput.slice(this.addEmailCursor);
33723
34286
  this.addEmailCursor += pasted.length;
33724
- } else {
34287
+ } else if (this.addActiveField === "password") {
33725
34288
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor) + pasted + this.addPasswordInput.slice(this.addPasswordCursor);
33726
34289
  this.addPasswordCursor += pasted.length;
34290
+ } else {
34291
+ this.addOtpCodeInput = this.addOtpCodeInput.slice(0, this.addOtpCodeCursor) + pasted + this.addOtpCodeInput.slice(this.addOtpCodeCursor);
34292
+ this.addOtpCodeCursor += pasted.length;
33727
34293
  }
33728
34294
  return true;
33729
34295
  }
@@ -33732,9 +34298,12 @@ var init_accounts_view = __esm({
33732
34298
  if (this.addActiveField === "email") {
33733
34299
  this.addEmailInput = "";
33734
34300
  this.addEmailCursor = 0;
33735
- } else {
34301
+ } else if (this.addActiveField === "password") {
33736
34302
  this.addPasswordInput = "";
33737
34303
  this.addPasswordCursor = 0;
34304
+ } else {
34305
+ this.addOtpCodeInput = "";
34306
+ this.addOtpCodeCursor = 0;
33738
34307
  }
33739
34308
  return true;
33740
34309
  }
@@ -33744,11 +34313,16 @@ var init_accounts_view = __esm({
33744
34313
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor - 1) + this.addEmailInput.slice(this.addEmailCursor);
33745
34314
  this.addEmailCursor--;
33746
34315
  }
33747
- } else {
34316
+ } else if (this.addActiveField === "password") {
33748
34317
  if (this.addPasswordCursor > 0) {
33749
34318
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor - 1) + this.addPasswordInput.slice(this.addPasswordCursor);
33750
34319
  this.addPasswordCursor--;
33751
34320
  }
34321
+ } else {
34322
+ if (this.addOtpCodeCursor > 0) {
34323
+ this.addOtpCodeInput = this.addOtpCodeInput.slice(0, this.addOtpCodeCursor - 1) + this.addOtpCodeInput.slice(this.addOtpCodeCursor);
34324
+ this.addOtpCodeCursor--;
34325
+ }
33752
34326
  }
33753
34327
  return true;
33754
34328
  }
@@ -33757,10 +34331,14 @@ var init_accounts_view = __esm({
33757
34331
  if (this.addEmailCursor < this.addEmailInput.length) {
33758
34332
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor) + this.addEmailInput.slice(this.addEmailCursor + 1);
33759
34333
  }
33760
- } else {
34334
+ } else if (this.addActiveField === "password") {
33761
34335
  if (this.addPasswordCursor < this.addPasswordInput.length) {
33762
34336
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor) + this.addPasswordInput.slice(this.addPasswordCursor + 1);
33763
34337
  }
34338
+ } else {
34339
+ if (this.addOtpCodeCursor < this.addOtpCodeInput.length) {
34340
+ this.addOtpCodeInput = this.addOtpCodeInput.slice(0, this.addOtpCodeCursor) + this.addOtpCodeInput.slice(this.addOtpCodeCursor + 1);
34341
+ }
33764
34342
  }
33765
34343
  return true;
33766
34344
  }
@@ -33773,9 +34351,14 @@ var init_accounts_view = __esm({
33773
34351
  if (this.addActiveField === "email") {
33774
34352
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor) + key.char + this.addEmailInput.slice(this.addEmailCursor);
33775
34353
  this.addEmailCursor += key.char.length;
33776
- } else {
34354
+ } else if (this.addActiveField === "password") {
33777
34355
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor) + key.char + this.addPasswordInput.slice(this.addPasswordCursor);
33778
34356
  this.addPasswordCursor += key.char.length;
34357
+ } else if (this.addActiveField === "code") {
34358
+ if (this.addOtpCodeInput.length < 10) {
34359
+ this.addOtpCodeInput = this.addOtpCodeInput.slice(0, this.addOtpCodeCursor) + key.char + this.addOtpCodeInput.slice(this.addOtpCodeCursor);
34360
+ this.addOtpCodeCursor += key.char.length;
34361
+ }
33779
34362
  }
33780
34363
  return true;
33781
34364
  }
@@ -33888,13 +34471,13 @@ var init_accounts_view = __esm({
33888
34471
  return true;
33889
34472
  }
33890
34473
  if (col >= leftW) {
33891
- if (row === 15) {
33892
- const actionRow = col < leftW + 18 ? 15 : 21;
34474
+ if (row === 16) {
34475
+ const actionRow = col < leftW + 18 ? 16 : 22;
33893
34476
  if (this.hoveredActionRow !== actionRow) {
33894
34477
  this.hoveredActionRow = actionRow;
33895
34478
  return true;
33896
34479
  }
33897
- } else if (row >= 16 && row <= 20) {
34480
+ } else if (row >= 17 && row <= 21) {
33898
34481
  if (this.hoveredActionRow !== row) {
33899
34482
  this.hoveredActionRow = row;
33900
34483
  return true;
@@ -33920,7 +34503,7 @@ var init_accounts_view = __esm({
33920
34503
  }
33921
34504
  }
33922
34505
  if (col >= leftW) {
33923
- if (row === 15) {
34506
+ if (row === 16) {
33924
34507
  if (col < leftW + 18) {
33925
34508
  await this.handleKey({ name: "a", ctrl: false, shift: false, meta: false });
33926
34509
  } else {
@@ -33928,23 +34511,23 @@ var init_accounts_view = __esm({
33928
34511
  }
33929
34512
  return true;
33930
34513
  }
33931
- if (row === 16) {
34514
+ if (row === 17) {
33932
34515
  await this.handleKey({ name: "d", ctrl: false, shift: false, meta: false });
33933
34516
  return true;
33934
34517
  }
33935
- if (row === 17) {
34518
+ if (row === 18) {
33936
34519
  await this.handleKey({ name: "c", ctrl: false, shift: false, meta: false });
33937
34520
  return true;
33938
34521
  }
33939
- if (row === 18) {
34522
+ if (row === 19) {
33940
34523
  await this.handleKey({ name: "z", ctrl: false, shift: false, meta: false });
33941
34524
  return true;
33942
34525
  }
33943
- if (row === 19) {
34526
+ if (row === 20) {
33944
34527
  await this.handleKey({ name: "x", ctrl: false, shift: false, meta: false });
33945
34528
  return true;
33946
34529
  }
33947
- if (row === 20) {
34530
+ if (row === 21) {
33948
34531
  await this.handleKey({ name: "l", ctrl: false, shift: false, meta: false });
33949
34532
  return true;
33950
34533
  }
@@ -34085,9 +34668,10 @@ var init_accounts_view = __esm({
34085
34668
  rightContent.push("");
34086
34669
  rightContent.push("");
34087
34670
  rightContent.push("");
34671
+ rightContent.push("");
34088
34672
  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`;
34673
+ const btnA = this.hoveredActionRow === 16 ? theme.bgHover(` ${theme.cyan("[ A ] Adicionar")} `) : ` ${theme.cyan("[ A ]")} Adicionar `;
34674
+ const btnB = this.hoveredActionRow === 22 ? theme.bgHover(` ${theme.cyan("[ B ] Em Lote")} `) : ` ${theme.cyan("[ B ]")} Em Lote `;
34091
34675
  rightContent.push(` ${btnA} ${btnB}`);
34092
34676
  } else {
34093
34677
  const email = truncate(selected.emailOrName, 18);
@@ -34112,14 +34696,14 @@ var init_accounts_view = __esm({
34112
34696
  rightContent.push("");
34113
34697
  }
34114
34698
  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`;
34699
+ const btnA = this.hoveredActionRow === 16 ? theme.bgHover(` ${theme.cyan("[ A ] Adicionar")} `) : ` ${theme.cyan("[ A ]")} Adicionar `;
34700
+ const btnB = this.hoveredActionRow === 22 ? theme.bgHover(` ${theme.cyan("[ B ] Em Lote")} `) : ` ${theme.cyan("[ B ]")} Em Lote `;
34117
34701
  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`}`);
34702
+ rightContent.push(` ${this.hoveredActionRow === 17 ? theme.bgHover(` ${theme.red("[ D ] Remover Conta")} `) : ` ${theme.red("[ D ]")} Remover Conta `}`);
34703
+ rightContent.push(` ${this.hoveredActionRow === 18 ? theme.bgHover(` ${theme.yellow("[ C ] Zerar Cooldown")} `) : ` ${theme.yellow("[ C ]")} Zerar Cooldown `}`);
34704
+ rightContent.push(` ${this.hoveredActionRow === 19 ? theme.bgHover(` ${theme.green("[ Z ] Zerar Todas")} `) : ` ${theme.green("[ Z ]")} Zerar Todas `}`);
34705
+ rightContent.push(` ${this.hoveredActionRow === 20 ? theme.bgHover(` ${theme.peach("[ X ] Limpar Chats (Conta)")} `) : ` ${theme.peach("[ X ]")} Limpar Chats (Conta) `}`);
34706
+ rightContent.push(` ${this.hoveredActionRow === 21 ? theme.bgHover(` ${theme.red("[ L ] Limpar Todos os Chats")} `) : ` ${theme.red("[ L ]")} Limpar Todos os Chats `}`);
34123
34707
  }
34124
34708
  const rightBox = drawBox({
34125
34709
  title: "Inspe\xE7\xE3o de Conta",
@@ -34191,12 +34775,11 @@ var init_accounts_view = __esm({
34191
34775
  return modalBox.map((line) => padStr + line);
34192
34776
  }
34193
34777
  if (this.isAddModalOpen) {
34194
- const modalW = Math.min(width - 4, 66);
34778
+ const modalW = Math.min(width - 4, 76);
34195
34779
  this.lastModalLeftPad = Math.max(0, Math.floor((width - modalW) / 2));
34196
34780
  const isEmail = this.addActiveField === "email";
34197
34781
  const isPass = this.addActiveField === "password";
34198
- const emailHover = !isEmail && this.modalHoveredField === "email";
34199
- const passHover = !isPass && this.modalHoveredField === "password";
34782
+ const isCode = this.addActiveField === "code";
34200
34783
  let emailDisplay;
34201
34784
  if (isEmail) {
34202
34785
  if (this.addEmailInput.length === 0) {
@@ -34208,33 +34791,64 @@ var init_accounts_view = __esm({
34208
34791
  emailDisplay = `${theme.cyan(before)}${theme.inverse(at)}${theme.cyan(after)}`;
34209
34792
  }
34210
34793
  } 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)")}`;
34794
+ emailDisplay = this.addEmailInput ? theme.cyan(this.addEmailInput) : theme.muted("(digite o e-mail)");
34795
+ }
34796
+ let secondFieldLabel;
34797
+ let secondFieldDisplay;
34798
+ if (this.addLoginMode === "password") {
34799
+ secondFieldLabel = "Senha:";
34800
+ const maskedPass = "\u2022".repeat(this.addPasswordInput.length);
34801
+ if (isPass) {
34802
+ if (this.addPasswordInput.length === 0) {
34803
+ secondFieldDisplay = `${theme.inverse(" ")} ${theme.dim("(digite a senha)")}`;
34804
+ } else {
34805
+ const before = maskedPass.slice(0, this.addPasswordCursor);
34806
+ const at = maskedPass[this.addPasswordCursor] || " ";
34807
+ const after = maskedPass.slice(this.addPasswordCursor + 1);
34808
+ secondFieldDisplay = `${theme.cyan(before)}${theme.inverse(at)}${theme.cyan(after)}`;
34809
+ }
34810
+ } else {
34811
+ secondFieldDisplay = this.addPasswordInput ? theme.cyan(maskedPass) : theme.muted("(digite a senha)");
34812
+ }
34813
+ } else {
34814
+ secondFieldLabel = "C\xF3digo:";
34815
+ if (!this.isOtpCodeSent) {
34816
+ secondFieldDisplay = theme.dim("(ser\xE1 enviado p/ seu e-mail)");
34817
+ } else if (isCode) {
34818
+ if (this.addOtpCodeInput.length === 0) {
34819
+ secondFieldDisplay = `${theme.inverse(" ")} ${theme.dim("(digite o c\xF3digo de 6 d\xEDgitos)")}`;
34820
+ } else {
34821
+ const before = this.addOtpCodeInput.slice(0, this.addOtpCodeCursor);
34822
+ const at = this.addOtpCodeInput[this.addOtpCodeCursor] || " ";
34823
+ const after = this.addOtpCodeInput.slice(this.addOtpCodeCursor + 1);
34824
+ secondFieldDisplay = `${theme.cyan(before)}${theme.inverse(at)}${theme.cyan(after)}`;
34825
+ }
34218
34826
  } 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)}`;
34827
+ secondFieldDisplay = this.addOtpCodeInput ? theme.cyan(this.addOtpCodeInput) : theme.muted("(digite o c\xF3digo de 6 d\xEDgitos)");
34223
34828
  }
34829
+ }
34830
+ let saveBtnText;
34831
+ if (this.addLoginMode === "password") {
34832
+ saveBtnText = "[ Enter ] Salvar";
34833
+ } else if (!this.isOtpCodeSent) {
34834
+ saveBtnText = "[ Enter ] Enviar C\xF3digo";
34224
34835
  } else {
34225
- passDisplay = this.addPasswordInput ? passHover ? theme.bgHover(` ${maskedPass} `) : theme.cyan(` ${maskedPass} `) : passHover ? theme.bgHover(" (digite a senha) ") : theme.muted(" (digite a senha) ");
34836
+ saveBtnText = "[ Enter ] Confirmar C\xF3digo";
34226
34837
  }
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");
34838
+ const saveBtn = this.isValidatingAccount || this.isOtpRequesting ? theme.yellow(" [ Aguarde... ] ") : this.modalHoveredField === "save" ? theme.bgHover(` ${saveBtnText} `) : ` ${theme.green(saveBtnText)} `;
34839
+ const cancelBtn = this.modalHoveredField === "cancel" ? theme.bgHover(" [ Esc ] Cancelar ") : ` ${theme.muted("[ Esc ] Cancelar")} `;
34840
+ const modeBtnText = this.addLoginMode === "password" ? "[ Tab ] Sem Senha (OTP)" : "[ Tab ] Modo Senha";
34841
+ const modeBtn = this.modalHoveredField === "mode" ? theme.bgHover(` ${modeBtnText} `) : ` ${theme.cyan(modeBtnText)} `;
34229
34842
  const modalContent = [
34230
34843
  "",
34231
- ` ${theme.bold("E-mail:")} ${emailDisplay}`,
34232
- ` ${theme.bold("Senha:")} ${passDisplay}`,
34844
+ ` ${theme.bold("E-mail:")} ${emailDisplay}${this.isOtpCodeSent ? ` ${theme.green("\u2713 C\xF3digo Enviado")}` : ""}`,
34845
+ ` ${theme.bold(secondFieldLabel)} ${secondFieldDisplay}`,
34233
34846
  "",
34234
- ` ${saveBtn} ${cancelBtn} ${theme.dim("(\u2191\u2193/mouse alternar)")}`
34847
+ ` ${saveBtn} ${cancelBtn} ${modeBtn}`
34235
34848
  ];
34849
+ const modalTitle = this.addLoginMode === "password" ? "Adicionar Nova Conta Qwen (Login com Senha)" : "Adicionar Nova Conta Qwen (Login sem Senha - OTP)";
34236
34850
  const modalBox = drawBox({
34237
- title: "Adicionar Nova Conta Qwen (Login)",
34851
+ title: modalTitle,
34238
34852
  width: modalW,
34239
34853
  height: Math.min(contentH, 11),
34240
34854
  borderColor: theme.borderActive,