qwenproxy-cli 1.6.0 → 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
@@ -150,6 +150,44 @@ var init_paths = __esm({
150
150
  }
151
151
  });
152
152
 
153
+ // src/core/process-guard.ts
154
+ function isPlaywrightAlreadyClosedMessage(message) {
155
+ if (!message) return false;
156
+ return message.includes("Target page, context or browser has been closed") || message.includes("Browser has been closed") || message.includes("Target closed") || message.includes("Target crashed") || message.includes("Page crashed") || message.includes("Assertion error") || message.includes("Cannot find parent object") || message.includes("Connection closed") || message.includes("session closed") || message.includes("Session closed") || message.includes("Network.setCacheDisabled") || message.includes("Protocol error") || message.includes("storageState timed out");
157
+ }
158
+ function isBenignTeardownError(error) {
159
+ if (!error) return false;
160
+ const message = error instanceof Error ? error.message : typeof error === "object" && "message" in error ? String(error.message) : String(error);
161
+ return isPlaywrightAlreadyClosedMessage(message);
162
+ }
163
+ function installProcessTeardownGuards(label = "Process") {
164
+ if (guardsInstalled) return;
165
+ guardsInstalled = true;
166
+ process.on("uncaughtException", (error) => {
167
+ if (isBenignTeardownError(error)) {
168
+ const msg = error instanceof Error ? error.message : typeof error === "object" && error !== null && "message" in error ? String(error.message) : String(error);
169
+ console.warn(`\u26A0\uFE0F [${label}] Handled benign driver teardown exception: ${msg}`);
170
+ return;
171
+ }
172
+ console.error(`\u274C [${label}] Uncaught Exception:`, error);
173
+ });
174
+ process.on("unhandledRejection", (reason) => {
175
+ if (isBenignTeardownError(reason)) {
176
+ const msg = reason instanceof Error ? reason.message : typeof reason === "object" && reason !== null && "message" in reason ? String(reason.message) : String(reason);
177
+ console.warn(`\u26A0\uFE0F [${label}] Handled benign driver teardown rejection: ${msg}`);
178
+ return;
179
+ }
180
+ console.error(`\u274C [${label}] Unhandled Rejection:`, reason);
181
+ });
182
+ }
183
+ var guardsInstalled;
184
+ var init_process_guard = __esm({
185
+ "src/core/process-guard.ts"() {
186
+ "use strict";
187
+ guardsInstalled = false;
188
+ }
189
+ });
190
+
153
191
  // src/core/config.ts
154
192
  import fs2 from "node:fs";
155
193
  import dotenv from "dotenv";
@@ -289,11 +327,11 @@ var init_config = __esm({
289
327
  // nothing in this window is dead and should fail fast, retryable).
290
328
  QWEN_FIRST_CHUNK_TIMEOUT: z.string().default("60000"),
291
329
  TOTAL_REQUEST_TIMEOUT: z.string().default("600000"),
292
- // Mid-stream silence window for thinking models: 3 min with ZERO upstream
330
+ // Mid-stream silence window for thinking models: 5 min with ZERO upstream
293
331
  // bytes is a dead stream (WAF swallow / dropped connection) — fail fast and
294
332
  // let the retry policy rotate accounts. Flowing reasoning chunks RESET this
295
333
  // timer, so legitimate slow thinking is never cut; only total silence is.
296
- REASONING_MODEL_TIMEOUT: z.string().default("180000"),
334
+ REASONING_MODEL_TIMEOUT: z.string().default("300000"),
297
335
  CACHE_TTL: z.string().default("3600"),
298
336
  RESPONSE_TTL: z.string().default("1800"),
299
337
  CACHE_COMPRESSION_ENABLED: z.string().default("true"),
@@ -2152,7 +2190,7 @@ function addAccountsBatch(entries) {
2152
2190
  }
2153
2191
  return { added, skipped, invalid };
2154
2192
  }
2155
- function addAccount(email, password, id) {
2193
+ function addAccount(email, password = "", id) {
2156
2194
  if (!email || typeof email !== "string" || email.trim().length === 0) {
2157
2195
  throw new Error("Email is required");
2158
2196
  }
@@ -4260,6 +4298,8 @@ var init_clean_cache = __esm({
4260
4298
  "src/clean-cache.ts"() {
4261
4299
  "use strict";
4262
4300
  init_playwright();
4301
+ init_process_guard();
4302
+ installProcessTeardownGuards("CleanCache");
4263
4303
  isDirectRun = process.argv[1] && (process.argv[1].endsWith("clean-cache.ts") || process.argv[1].endsWith("clean-cache.js"));
4264
4304
  if (isDirectRun) {
4265
4305
  main().catch((err) => {
@@ -4275,6 +4315,7 @@ var playwright_exports = {};
4275
4315
  __export(playwright_exports, {
4276
4316
  assertAntiBotHeaders: () => assertAntiBotHeaders,
4277
4317
  buildChromiumLaunchArgs: () => buildChromiumLaunchArgs,
4318
+ cancelEmailOtpLogin: () => cancelEmailOtpLogin,
4278
4319
  captureQwenHeaders: () => captureQwenHeaders,
4279
4320
  classifyQwenAuthError: () => classifyQwenAuthError,
4280
4321
  cleanupOrphanProfiles: () => cleanupOrphanProfiles,
@@ -4315,8 +4356,10 @@ __export(playwright_exports, {
4315
4356
  removePlaywrightProfile: () => removePlaywrightProfile,
4316
4357
  saveStorageState: () => saveStorageState,
4317
4358
  schedulePlaywrightProfileReset: () => schedulePlaywrightProfileReset,
4359
+ startEmailOtpLogin: () => startEmailOtpLogin,
4318
4360
  unregisterPlaywrightAccountForTests: () => unregisterPlaywrightAccountForTests,
4319
4361
  validateAccountLogin: () => validateAccountLogin,
4362
+ verifyEmailOtpLogin: () => verifyEmailOtpLogin,
4320
4363
  withAccountPage: () => withAccountPage
4321
4364
  });
4322
4365
  import { chromium as chromium2 } from "patchright";
@@ -4484,15 +4527,18 @@ function loadStorageState(accountId) {
4484
4527
  return void 0;
4485
4528
  }
4486
4529
  }
4487
- async function saveStorageState(context, accountId, timeoutMs = 5e3) {
4530
+ async function saveStorageState(context, accountId, timeoutMs = 1e4) {
4488
4531
  try {
4489
4532
  const stateFile = getStorageStatePath(accountId);
4490
4533
  const dir = path6.dirname(stateFile);
4491
4534
  if (!fs9.existsSync(dir)) {
4492
4535
  fs9.mkdirSync(dir, { recursive: true });
4493
4536
  }
4537
+ const rawPromise = context.storageState({ path: stateFile }).catch(() => {
4538
+ return void 0;
4539
+ });
4494
4540
  await withTimeout(
4495
- context.storageState({ path: stateFile }),
4541
+ rawPromise,
4496
4542
  timeoutMs,
4497
4543
  `storageState timed out after ${timeoutMs}ms`
4498
4544
  );
@@ -4655,6 +4701,10 @@ async function clearVisibleChallenge(page) {
4655
4701
  "button[aria-label*='Close' i]",
4656
4702
  "button[aria-label*='Fechar' i]",
4657
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')",
4658
4708
  "button:has-text('Cancel')",
4659
4709
  "button:has-text('Cancelar')",
4660
4710
  "button:has-text('I understand')",
@@ -5849,6 +5899,292 @@ async function validateAccountLogin(rawAccount, headless = true, browserType = "
5849
5899
  release();
5850
5900
  }
5851
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
+ }
5852
6188
  function classifyQwenAuthError(code, details) {
5853
6189
  const c = (code || "").trim().toLowerCase();
5854
6190
  const d = (details || "").trim().toLowerCase();
@@ -7217,7 +7553,7 @@ async function withAccountPage(accountId, fn, timeoutMs = ACCOUNT_PAGE_OPERATION
7217
7553
  return result;
7218
7554
  } catch (error) {
7219
7555
  const message = getErrorMessage(error);
7220
- if (recoverOnTimeout && message.includes("Playwright page operation timed out")) {
7556
+ if (recoverOnTimeout && message.includes("Playwright page operation timed out") && (!page || page.isClosed())) {
7221
7557
  console.warn(
7222
7558
  `\u23F1\uFE0F [Playwright] Resetting account context after a stuck page operation: ${accountId}`
7223
7559
  );
@@ -7766,7 +8102,7 @@ async function getTokenDiagnostics(accountId) {
7766
8102
  }
7767
8103
  };
7768
8104
  }
7769
- 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;
7770
8106
  var init_playwright = __esm({
7771
8107
  "src/services/playwright.ts"() {
7772
8108
  "use strict";
@@ -7811,11 +8147,13 @@ var init_playwright = __esm({
7811
8147
  PLAYWRIGHT_MUTEX_WAIT_MS = 6e4;
7812
8148
  ACCOUNT_PAGE_OPERATION_TIMEOUT_MS = config.timeouts.page;
7813
8149
  SESSION_PROBE_NAVIGATION_TIMEOUT_MS = 15e3;
7814
- HEADER_CAPTURE_TRIGGER_GRACE_MS = 15e3;
7815
- FIRST_TRIGGER_GRACE_MS = 8e3;
8150
+ HEADER_CAPTURE_TRIGGER_GRACE_MS = 2e4;
8151
+ FIRST_TRIGGER_GRACE_MS = 12e3;
7816
8152
  HEADER_CAPTURE_TRIGGER_ATTEMPTS = 3;
7817
8153
  CHAT_INPUT_APPEAR_TIMEOUT_MS = 15e3;
7818
8154
  CHAT_INPUT_ACTION_TIMEOUT_MS = 1e4;
8155
+ activeOtpSessions = /* @__PURE__ */ new Map();
8156
+ mockOtpSessions = /* @__PURE__ */ new Map();
7819
8157
  PROFILE_RESET_TIMEOUT_MS = Math.max(9e4, config.timeouts.headers);
7820
8158
  setWafContextResetListener((accountId) => {
7821
8159
  if (!accountPages.has(accountId)) return;
@@ -9290,6 +9628,42 @@ var init_helpers = __esm({
9290
9628
  }
9291
9629
  });
9292
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
+
9293
9667
  // src/routes/chat/retry-policy.ts
9294
9668
  function errMessage(err) {
9295
9669
  if (err instanceof Error) return err.message || "";
@@ -9367,6 +9741,7 @@ function isAccountInitializationError(err) {
9367
9741
  function isQuotaLikeError(err) {
9368
9742
  if (isChatNotExistError(err) || isInvalidInputError(err)) return false;
9369
9743
  const code = errCode(err).toLowerCase();
9744
+ if (code === "server_overloaded" || code === "overload") return false;
9370
9745
  const message = errMessage(err).toLowerCase();
9371
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
9372
9747
  code === "rate_limit_exceeded" && (message.includes("quota") || message.includes("rate") || message.includes("limit") || message.includes("membership") || message.includes("demanda") || message.includes("demand"));
@@ -9415,6 +9790,19 @@ function isCorruptedChatHistoryError(err) {
9415
9790
  const message = errMessage(err).toLowerCase();
9416
9791
  return message.includes("first message must not") || message.includes("first message must be") || message.includes("must not assistant message") || message.includes("must not be assistant");
9417
9792
  }
9793
+ function isInternalServerError(err) {
9794
+ const code = errCode(err).toLowerCase();
9795
+ const message = errMessage(err).toLowerCase();
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");
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
+ }
9418
9806
  function makeRetryAction(reason, overrides = {}) {
9419
9807
  return {
9420
9808
  retryable: true,
@@ -9521,6 +9909,26 @@ function classifyRetryAction(err, options) {
9521
9909
  accountCooldownReason: quota.accountCooldownReason
9522
9910
  });
9523
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
+ }
9923
+ if (isInternalServerError(err) && !(err instanceof QwenUpstreamError)) {
9924
+ const typed = err;
9925
+ return makeRetryAction("upstream_internal_error", {
9926
+ switchAccount: typed.switchAccount !== false,
9927
+ forceNewChat: true,
9928
+ retryWithFullPrompt: true,
9929
+ retryAfterMs: typed.retryAfterMs ?? Math.min(baseDelayMs * 2, 3e3)
9930
+ });
9931
+ }
9524
9932
  if (isNetworkLikeError(err) || err instanceof QwenUpstreamUnavailableError || err instanceof QwenUpstreamError || isAbortError(err)) {
9525
9933
  const typed = err;
9526
9934
  return makeRetryAction(
@@ -9535,11 +9943,13 @@ function classifyRetryAction(err, options) {
9535
9943
  }
9536
9944
  if (err instanceof RetryableQwenStreamError) {
9537
9945
  const typed = err;
9538
- return makeRetryAction("explicit_retryable", {
9946
+ return makeRetryAction(typed.reason || "explicit_retryable", {
9539
9947
  switchAccount: typed.switchAccount !== false,
9540
9948
  forceNewChat: typed.forceNewChat === true,
9541
9949
  retryWithFullPrompt: typed.retryWithFullPrompt === true,
9542
- retryAfterMs: typed.retryAfterMs ?? baseDelayMs
9950
+ retryAfterMs: typed.retryAfterMs ?? baseDelayMs,
9951
+ accountCooldownMs: typed.accountCooldownMs,
9952
+ accountCooldownReason: typed.accountCooldownReason
9543
9953
  });
9544
9954
  }
9545
9955
  if (unknownEnabled) {
@@ -9572,6 +9982,9 @@ function toRetryableStreamError(errCode2, errDetails, options) {
9572
9982
  error.retryWithFullPrompt = merged.retryWithFullPrompt;
9573
9983
  error.switchAccount = merged.switchAccount;
9574
9984
  error.dropFiles = merged.dropFiles;
9985
+ error.accountCooldownMs = merged.accountCooldownMs;
9986
+ error.accountCooldownReason = merged.accountCooldownReason;
9987
+ error.reason = merged.reason;
9575
9988
  return error;
9576
9989
  }
9577
9990
  function throwFromSseUpstreamError(errCode2, errDetails) {
@@ -9657,6 +10070,7 @@ var init_retry_policy = __esm({
9657
10070
  init_qwen();
9658
10071
  init_errors();
9659
10072
  init_helpers();
10073
+ init_overload_detector();
9660
10074
  init_account_manager();
9661
10075
  }
9662
10076
  });
@@ -11814,7 +12228,8 @@ async function requestQwenPersonalizationInBrowser(accountId, method, path21, he
11814
12228
  payload === void 0 ? void 0 : JSON.stringify(payload),
11815
12229
  {
11816
12230
  settingsPage: true,
11817
- referrer: qwenUrl("/settings/personalization")
12231
+ referrer: qwenUrl("/settings/personalization"),
12232
+ noMutexRecovery: true
11818
12233
  }
11819
12234
  );
11820
12235
  const { raw, json } = await readJsonTextResponse(response);
@@ -12315,8 +12730,9 @@ async function syncQwenRequestPersonalizationInternal(instruction, accountId, me
12315
12730
  const returnedInstruction = json?.data?.personalization?.instruction;
12316
12731
  const returned = textSize(returnedInstruction);
12317
12732
  let stored = { chars: null, bytes: null, hash: null };
12733
+ const matchReturned = isEmptyInstruction && (!returnedInstruction || returned.chars === 0) || returned.hash !== null && returned.hash === sent.hash;
12318
12734
  let verifyData = null;
12319
- if (config.qwen.personalizationVerifyGet) {
12735
+ if (config.qwen.personalizationVerifyGet && !matchReturned) {
12320
12736
  const { json: verifyJson } = await requestQwenPersonalizationInBrowser(
12321
12737
  accountId,
12322
12738
  "GET",
@@ -12326,7 +12742,6 @@ async function syncQwenRequestPersonalizationInternal(instruction, accountId, me
12326
12742
  verifyData = verifyJson?.data?.personalization;
12327
12743
  stored = textSize(verifyData?.instruction);
12328
12744
  }
12329
- const matchReturned = isEmptyInstruction && (!returnedInstruction || returned.chars === 0) || returned.hash !== null && returned.hash === sent.hash;
12330
12745
  const matchStored = stored.hash === null ? null : isEmptyInstruction && (!verifyData?.instruction || stored.chars === 0) || stored.hash === sent.hash;
12331
12746
  const applied = matchReturned || matchStored === true;
12332
12747
  if (syncHash && applied) {
@@ -12700,6 +13115,17 @@ async function fetchQwenModels(accountId) {
12700
13115
  );
12701
13116
  return cached.models;
12702
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
+ }
12703
13129
  if (accountId && !isAuthMockEnabled() && isAccountBusy(accountId)) {
12704
13130
  try {
12705
13131
  const result = await withAccountPage(
@@ -16063,6 +16489,12 @@ async function deleteChatsForConfiguredAccounts(keepBrowserOpen = false) {
16063
16489
  `\u274C [DeleteChats] [${currentIdx}/${totalCount}] Falha ao apagar conversas de ${maskEmail(account.email)}:`,
16064
16490
  error instanceof Error ? error.message : String(error)
16065
16491
  );
16492
+ } finally {
16493
+ if (!keepBrowserOpen) {
16494
+ const { closePlaywrightForAccount: closePlaywrightForAccount2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
16495
+ await closePlaywrightForAccount2(account.id).catch(() => {
16496
+ });
16497
+ }
16066
16498
  }
16067
16499
  }
16068
16500
  } finally {
@@ -17137,7 +17569,8 @@ ${loopReminder}` : truncation.prompt;
17137
17569
  const checkDeadline = async () => {
17138
17570
  try {
17139
17571
  const { isCaptchaRecoveryActive: isCaptchaRecoveryActive2 } = await Promise.resolve().then(() => (init_captcha_coordinator(), captcha_coordinator_exports));
17140
- if (currentAccountId && isCaptchaRecoveryActive2(currentAccountId)) {
17572
+ const { isPlaywrightInitializing: isPlaywrightInitializing2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
17573
+ if (currentAccountId && (isCaptchaRecoveryActive2(currentAccountId) || isPlaywrightInitializing2(currentAccountId))) {
17141
17574
  acquireDeadlineTimer = setTimeout(checkDeadline, 3e4);
17142
17575
  acquireDeadlineTimer.unref?.();
17143
17576
  return;
@@ -17548,8 +17981,8 @@ var init_account = __esm({
17548
17981
  init_tool_call_guard();
17549
17982
  init_retry_policy();
17550
17983
  MAX_ANTI_BOT_ROTATIONS = 1;
17551
- PERSONALIZATION_SYNC_DEADLINE_MS = 45e3;
17552
- COLD_ACCOUNT_PERSONALIZATION_SYNC_DEADLINE_MS = 6e4;
17984
+ PERSONALIZATION_SYNC_DEADLINE_MS = 9e4;
17985
+ COLD_ACCOUNT_PERSONALIZATION_SYNC_DEADLINE_MS = 12e4;
17553
17986
  chatLocks = /* @__PURE__ */ new Map();
17554
17987
  personalizationLocks = /* @__PURE__ */ new Map();
17555
17988
  }
@@ -20512,6 +20945,19 @@ async function processNonStreamingResponse(params) {
20512
20945
  isThinkingChunk = false;
20513
20946
  if (delta.content !== void 0) {
20514
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
+ }
20515
20961
  const result = getIncrementalDelta(
20516
20962
  lastRawContent,
20517
20963
  newContent,
@@ -20853,6 +21299,7 @@ async function processStreamingResponse(params) {
20853
21299
  let activeReader = null;
20854
21300
  let invalidInputSameAccountRetries = 0;
20855
21301
  let chatInProgressSameAccountRetries = 0;
21302
+ let antiBotSameAccountRetries = 0;
20856
21303
  const totalConfiguredAccounts = loadAccounts().length;
20857
21304
  let quotaRotationsLeft = Math.min(Math.max(1, totalConfiguredAccounts - 1), 6);
20858
21305
  let streamCompletedOk = false;
@@ -21260,7 +21707,16 @@ async function processStreamingResponse(params) {
21260
21707
  );
21261
21708
  return false;
21262
21709
  }
21263
- const switchAccount = policy.switchAccount && !retryInvalidInputOnSameAccount;
21710
+ let switchAccount = policy.switchAccount && !retryInvalidInputOnSameAccount;
21711
+ if (policy.reason === "anti_bot") {
21712
+ if (antiBotSameAccountRetries === 0) {
21713
+ antiBotSameAccountRetries++;
21714
+ switchAccount = false;
21715
+ } else {
21716
+ switchAccount = true;
21717
+ markAccountRateLimited(currentAccountId, 6e4, "AntiBotWafChallenge");
21718
+ }
21719
+ }
21264
21720
  if (switchAccount && (policy.accountCooldownMs ?? 0) > 0) {
21265
21721
  markAccountRateLimited(
21266
21722
  currentAccountId,
@@ -21272,6 +21728,33 @@ async function processStreamingResponse(params) {
21272
21728
  Promise.resolve().then(() => (init_playwright(), playwright_exports)).then(({ refreshAccountToken: refreshAccountToken2 }) => refreshAccountToken2(currentAccountId)).catch(() => {
21273
21729
  });
21274
21730
  }
21731
+ if (currentUiSessionId && targetResponseId) {
21732
+ const streamData = getStream(completionId);
21733
+ const stopHeaders = streamData?.headers;
21734
+ if (stopHeaders?.cookie && stopHeaders["user-agent"]) {
21735
+ void requestQwenTextInBrowser(
21736
+ currentAccountId,
21737
+ "POST",
21738
+ `/api/v2/chat/completions/stop?chat_id=${encodeURIComponent(currentUiSessionId)}`,
21739
+ buildQwenRequestHeaders({
21740
+ cookie: stopHeaders.cookie,
21741
+ userAgent: stopHeaders["user-agent"],
21742
+ bxUa: stopHeaders["bx-ua"],
21743
+ bxUmidtoken: stopHeaders["bx-umidtoken"],
21744
+ bxV: stopHeaders["bx-v"],
21745
+ chatSessionId: currentUiSessionId
21746
+ }),
21747
+ JSON.stringify({
21748
+ chat_id: currentUiSessionId,
21749
+ response_id: targetResponseId
21750
+ }),
21751
+ {
21752
+ referrer: qwenUrl(`/c/${encodeURIComponent(currentUiSessionId)}`),
21753
+ noMutexRecovery: true
21754
+ }
21755
+ ).catch(() => void 0);
21756
+ }
21757
+ }
21275
21758
  retryContext.releaseAccountLease?.();
21276
21759
  retryContext.releaseAccountLease = null;
21277
21760
  await reader.cancel().catch(() => void 0);
@@ -21542,6 +22025,19 @@ async function processStreamingResponse(params) {
21542
22025
  isThinkingChunk = false;
21543
22026
  if (delta.content !== void 0) {
21544
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
+ }
21545
22041
  const result = getIncrementalDelta(
21546
22042
  lastRawContent,
21547
22043
  newContent,
@@ -22346,6 +22842,7 @@ var init_streaming = __esm({
22346
22842
  init_daily_usage();
22347
22843
  init_context_meter();
22348
22844
  init_helpers();
22845
+ init_overload_detector();
22349
22846
  MAX_INITIAL_PROTOCOL_BYTES = 64 * 1024;
22350
22847
  MID_STREAM_FAILURE_WINDOW_MS = 5 * 60 * 1e3;
22351
22848
  midStreamNetworkFailures = /* @__PURE__ */ new Map();
@@ -26285,7 +26782,7 @@ function getAppVersion() {
26285
26782
  }
26286
26783
  } catch {
26287
26784
  }
26288
- cachedVersion = "v1.6.0";
26785
+ cachedVersion = "v1.6.2";
26289
26786
  return cachedVersion;
26290
26787
  }
26291
26788
  var cachedVersion;
@@ -33148,10 +33645,16 @@ var init_accounts_view = __esm({
33148
33645
  isAddModalOpen = false;
33149
33646
  isBatchModalOpen = false;
33150
33647
  isValidatingAccount = false;
33648
+ isOtpRequesting = false;
33649
+ isOtpCodeSent = false;
33650
+ addLoginMode = "password";
33651
+ otpSessionId = null;
33151
33652
  addEmailInput = "";
33152
33653
  addPasswordInput = "";
33654
+ addOtpCodeInput = "";
33153
33655
  addEmailCursor = 0;
33154
33656
  addPasswordCursor = 0;
33657
+ addOtpCodeCursor = 0;
33155
33658
  addActiveField = "email";
33156
33659
  batchInput = "";
33157
33660
  batchCursor = 0;
@@ -33228,22 +33731,113 @@ var init_accounts_view = __esm({
33228
33731
  this.statusMessage = "";
33229
33732
  }, 4e3);
33230
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
+ }
33231
33754
  async saveModalAccount() {
33232
- if (this.isValidatingAccount) return;
33755
+ if (this.isValidatingAccount || this.isOtpRequesting) return;
33233
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
+ }
33234
33832
  const password = this.addPasswordInput.trim();
33235
- if (!email || !password) {
33833
+ if (!password) {
33236
33834
  this.setStatusMessage(theme.yellow("[!] E-mail e senha s\xE3o obrigat\xF3rios"));
33237
33835
  return;
33238
33836
  }
33239
33837
  if (process.env.NODE_TEST_CONTEXT) {
33240
33838
  try {
33241
33839
  const newAcc = addAccount(email, password);
33242
- this.isAddModalOpen = false;
33243
- this.addEmailInput = "";
33244
- this.addPasswordInput = "";
33245
- this.addEmailCursor = 0;
33246
- this.addPasswordCursor = 0;
33840
+ this.resetAddModalState();
33247
33841
  await this.refresh();
33248
33842
  this.setStatusMessage(theme.green(`\u2713 Conta ${email} salva! Conectando...`));
33249
33843
  } catch (err) {
@@ -33270,11 +33864,7 @@ var init_accounts_view = __esm({
33270
33864
  return;
33271
33865
  }
33272
33866
  const newAcc = addAccount(email, password, tempId);
33273
- this.isAddModalOpen = false;
33274
- this.addEmailInput = "";
33275
- this.addPasswordInput = "";
33276
- this.addEmailCursor = 0;
33277
- this.addPasswordCursor = 0;
33867
+ this.resetAddModalState();
33278
33868
  await this.refresh();
33279
33869
  this.setStatusMessage(theme.green(`\u2713 Conta ${email} validada e salva! Conectando...`));
33280
33870
  if (process.stdout.isTTY) {
@@ -33527,29 +34117,40 @@ var init_accounts_view = __esm({
33527
34117
  return true;
33528
34118
  }
33529
34119
  if (this.isAddModalOpen) {
33530
- if (this.isValidatingAccount) return true;
34120
+ if (this.isValidatingAccount || this.isOtpRequesting) return true;
33531
34121
  if (key.name === "escape") {
33532
- this.isAddModalOpen = false;
33533
- this.addEmailInput = "";
33534
- this.addPasswordInput = "";
34122
+ this.resetAddModalState();
33535
34123
  return true;
33536
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
+ }
33537
34137
  if (key.name === "hover" && key.mouse) {
33538
34138
  const { row, col } = key.mouse;
33539
34139
  const leftPad = this.lastModalLeftPad || 0;
33540
34140
  const relCol = col - leftPad;
33541
- if (row === 5 || row === 6) {
34141
+ if (row === 6) {
33542
34142
  if (this.modalHoveredField !== "email") {
33543
34143
  this.modalHoveredField = "email";
33544
34144
  return true;
33545
34145
  }
33546
- } else if (row === 7 || row === 8) {
33547
- if (this.modalHoveredField !== "password") {
33548
- 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;
33549
34150
  return true;
33550
34151
  }
33551
34152
  } else if (row === 9) {
33552
- const btn = relCol <= 24 ? "save" : "cancel";
34153
+ const btn = relCol <= 28 ? "save" : relCol <= 49 ? "cancel" : "mode";
33553
34154
  if (this.modalHoveredField !== btn) {
33554
34155
  this.modalHoveredField = btn;
33555
34156
  return true;
@@ -33563,56 +34164,77 @@ var init_accounts_view = __esm({
33563
34164
  const { row, col } = key.mouse;
33564
34165
  const leftPad = this.lastModalLeftPad || 0;
33565
34166
  const relCol = col - leftPad;
33566
- if (row === 5 || row === 6) {
34167
+ if (row === 6) {
33567
34168
  this.addActiveField = "email";
33568
34169
  return true;
33569
34170
  }
33570
- if (row === 7 || row === 8) {
33571
- 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
+ }
33572
34177
  return true;
33573
34178
  }
33574
34179
  if (row === 9) {
33575
- if (relCol <= 24) {
34180
+ if (relCol <= 28) {
33576
34181
  await this.saveModalAccount();
33577
34182
  return true;
33578
- } else {
33579
- this.isAddModalOpen = false;
33580
- this.addEmailInput = "";
33581
- this.addPasswordInput = "";
33582
- this.addEmailCursor = 0;
33583
- this.addPasswordCursor = 0;
34183
+ } else if (relCol <= 49) {
34184
+ this.resetAddModalState();
33584
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
+ }
33585
34197
  }
33586
34198
  }
33587
34199
  }
33588
34200
  if (key.name === "up" || key.name === "down") {
33589
- 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
+ }
33590
34206
  return true;
33591
34207
  }
33592
34208
  if (key.name === "left") {
33593
34209
  if (this.addActiveField === "email") {
33594
34210
  this.addEmailCursor = Math.max(0, this.addEmailCursor - 1);
33595
- } else {
34211
+ } else if (this.addActiveField === "password") {
33596
34212
  this.addPasswordCursor = Math.max(0, this.addPasswordCursor - 1);
34213
+ } else {
34214
+ this.addOtpCodeCursor = Math.max(0, this.addOtpCodeCursor - 1);
33597
34215
  }
33598
34216
  return true;
33599
34217
  }
33600
34218
  if (key.name === "right") {
33601
34219
  if (this.addActiveField === "email") {
33602
34220
  this.addEmailCursor = Math.min(this.addEmailInput.length, this.addEmailCursor + 1);
33603
- } else {
34221
+ } else if (this.addActiveField === "password") {
33604
34222
  this.addPasswordCursor = Math.min(this.addPasswordInput.length, this.addPasswordCursor + 1);
34223
+ } else {
34224
+ this.addOtpCodeCursor = Math.min(this.addOtpCodeInput.length, this.addOtpCodeCursor + 1);
33605
34225
  }
33606
34226
  return true;
33607
34227
  }
33608
34228
  if (key.name === "home") {
33609
34229
  if (this.addActiveField === "email") this.addEmailCursor = 0;
33610
- else this.addPasswordCursor = 0;
34230
+ else if (this.addActiveField === "password") this.addPasswordCursor = 0;
34231
+ else this.addOtpCodeCursor = 0;
33611
34232
  return true;
33612
34233
  }
33613
34234
  if (key.name === "end") {
33614
34235
  if (this.addActiveField === "email") this.addEmailCursor = this.addEmailInput.length;
33615
- else this.addPasswordCursor = this.addPasswordInput.length;
34236
+ else if (this.addActiveField === "password") this.addPasswordCursor = this.addPasswordInput.length;
34237
+ else this.addOtpCodeCursor = this.addOtpCodeInput.length;
33616
34238
  return true;
33617
34239
  }
33618
34240
  if (key.ctrl && (key.name === "v" || key.raw === "")) {
@@ -33621,9 +34243,12 @@ var init_accounts_view = __esm({
33621
34243
  if (this.addActiveField === "email") {
33622
34244
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor) + pasted + this.addEmailInput.slice(this.addEmailCursor);
33623
34245
  this.addEmailCursor += pasted.length;
33624
- } else {
34246
+ } else if (this.addActiveField === "password") {
33625
34247
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor) + pasted + this.addPasswordInput.slice(this.addPasswordCursor);
33626
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;
33627
34252
  }
33628
34253
  return true;
33629
34254
  }
@@ -33632,9 +34257,12 @@ var init_accounts_view = __esm({
33632
34257
  if (this.addActiveField === "email") {
33633
34258
  this.addEmailInput = "";
33634
34259
  this.addEmailCursor = 0;
33635
- } else {
34260
+ } else if (this.addActiveField === "password") {
33636
34261
  this.addPasswordInput = "";
33637
34262
  this.addPasswordCursor = 0;
34263
+ } else {
34264
+ this.addOtpCodeInput = "";
34265
+ this.addOtpCodeCursor = 0;
33638
34266
  }
33639
34267
  return true;
33640
34268
  }
@@ -33644,11 +34272,16 @@ var init_accounts_view = __esm({
33644
34272
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor - 1) + this.addEmailInput.slice(this.addEmailCursor);
33645
34273
  this.addEmailCursor--;
33646
34274
  }
33647
- } else {
34275
+ } else if (this.addActiveField === "password") {
33648
34276
  if (this.addPasswordCursor > 0) {
33649
34277
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor - 1) + this.addPasswordInput.slice(this.addPasswordCursor);
33650
34278
  this.addPasswordCursor--;
33651
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
+ }
33652
34285
  }
33653
34286
  return true;
33654
34287
  }
@@ -33657,10 +34290,14 @@ var init_accounts_view = __esm({
33657
34290
  if (this.addEmailCursor < this.addEmailInput.length) {
33658
34291
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor) + this.addEmailInput.slice(this.addEmailCursor + 1);
33659
34292
  }
33660
- } else {
34293
+ } else if (this.addActiveField === "password") {
33661
34294
  if (this.addPasswordCursor < this.addPasswordInput.length) {
33662
34295
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor) + this.addPasswordInput.slice(this.addPasswordCursor + 1);
33663
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
+ }
33664
34301
  }
33665
34302
  return true;
33666
34303
  }
@@ -33673,9 +34310,14 @@ var init_accounts_view = __esm({
33673
34310
  if (this.addActiveField === "email") {
33674
34311
  this.addEmailInput = this.addEmailInput.slice(0, this.addEmailCursor) + key.char + this.addEmailInput.slice(this.addEmailCursor);
33675
34312
  this.addEmailCursor += key.char.length;
33676
- } else {
34313
+ } else if (this.addActiveField === "password") {
33677
34314
  this.addPasswordInput = this.addPasswordInput.slice(0, this.addPasswordCursor) + key.char + this.addPasswordInput.slice(this.addPasswordCursor);
33678
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
+ }
33679
34321
  }
33680
34322
  return true;
33681
34323
  }
@@ -33788,13 +34430,13 @@ var init_accounts_view = __esm({
33788
34430
  return true;
33789
34431
  }
33790
34432
  if (col >= leftW) {
33791
- if (row === 15) {
33792
- const actionRow = col < leftW + 18 ? 15 : 21;
34433
+ if (row === 16) {
34434
+ const actionRow = col < leftW + 18 ? 16 : 22;
33793
34435
  if (this.hoveredActionRow !== actionRow) {
33794
34436
  this.hoveredActionRow = actionRow;
33795
34437
  return true;
33796
34438
  }
33797
- } else if (row >= 16 && row <= 20) {
34439
+ } else if (row >= 17 && row <= 21) {
33798
34440
  if (this.hoveredActionRow !== row) {
33799
34441
  this.hoveredActionRow = row;
33800
34442
  return true;
@@ -33820,7 +34462,7 @@ var init_accounts_view = __esm({
33820
34462
  }
33821
34463
  }
33822
34464
  if (col >= leftW) {
33823
- if (row === 15) {
34465
+ if (row === 16) {
33824
34466
  if (col < leftW + 18) {
33825
34467
  await this.handleKey({ name: "a", ctrl: false, shift: false, meta: false });
33826
34468
  } else {
@@ -33828,23 +34470,23 @@ var init_accounts_view = __esm({
33828
34470
  }
33829
34471
  return true;
33830
34472
  }
33831
- if (row === 16) {
34473
+ if (row === 17) {
33832
34474
  await this.handleKey({ name: "d", ctrl: false, shift: false, meta: false });
33833
34475
  return true;
33834
34476
  }
33835
- if (row === 17) {
34477
+ if (row === 18) {
33836
34478
  await this.handleKey({ name: "c", ctrl: false, shift: false, meta: false });
33837
34479
  return true;
33838
34480
  }
33839
- if (row === 18) {
34481
+ if (row === 19) {
33840
34482
  await this.handleKey({ name: "z", ctrl: false, shift: false, meta: false });
33841
34483
  return true;
33842
34484
  }
33843
- if (row === 19) {
34485
+ if (row === 20) {
33844
34486
  await this.handleKey({ name: "x", ctrl: false, shift: false, meta: false });
33845
34487
  return true;
33846
34488
  }
33847
- if (row === 20) {
34489
+ if (row === 21) {
33848
34490
  await this.handleKey({ name: "l", ctrl: false, shift: false, meta: false });
33849
34491
  return true;
33850
34492
  }
@@ -33985,9 +34627,10 @@ var init_accounts_view = __esm({
33985
34627
  rightContent.push("");
33986
34628
  rightContent.push("");
33987
34629
  rightContent.push("");
34630
+ rightContent.push("");
33988
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")}`);
33989
- const btnA = this.hoveredActionRow === 15 ? theme.bgHover(` ${theme.cyan("[ A ] Adicionar")} `) : `${theme.cyan("[ A ]")} Adicionar`;
33990
- 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 `;
33991
34634
  rightContent.push(` ${btnA} ${btnB}`);
33992
34635
  } else {
33993
34636
  const email = truncate(selected.emailOrName, 18);
@@ -34012,14 +34655,14 @@ var init_accounts_view = __esm({
34012
34655
  rightContent.push("");
34013
34656
  }
34014
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")}`);
34015
- const btnA = this.hoveredActionRow === 15 ? theme.bgHover(` ${theme.cyan("[ A ] Adicionar")} `) : `${theme.cyan("[ A ]")} Adicionar`;
34016
- 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 `;
34017
34660
  rightContent.push(` ${btnA} ${btnB}`);
34018
- rightContent.push(` ${this.hoveredActionRow === 16 ? theme.bgHover(` ${theme.red("[ D ] Remover Conta")} `) : `${theme.red("[ D ]")} Remover Conta`}`);
34019
- rightContent.push(` ${this.hoveredActionRow === 17 ? theme.bgHover(` ${theme.yellow("[ C ] Zerar Cooldown")} `) : `${theme.yellow("[ C ]")} Zerar Cooldown`}`);
34020
- rightContent.push(` ${this.hoveredActionRow === 18 ? theme.bgHover(` ${theme.green("[ Z ] Zerar Todas")} `) : `${theme.green("[ Z ]")} Zerar Todas`}`);
34021
- rightContent.push(` ${this.hoveredActionRow === 19 ? theme.bgHover(` ${theme.peach("[ X ] Limpar Chats (Conta)")} `) : `${theme.peach("[ X ]")} Limpar Chats (Conta)`}`);
34022
- 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 `}`);
34023
34666
  }
34024
34667
  const rightBox = drawBox({
34025
34668
  title: "Inspe\xE7\xE3o de Conta",
@@ -34091,12 +34734,11 @@ var init_accounts_view = __esm({
34091
34734
  return modalBox.map((line) => padStr + line);
34092
34735
  }
34093
34736
  if (this.isAddModalOpen) {
34094
- const modalW = Math.min(width - 4, 66);
34737
+ const modalW = Math.min(width - 4, 76);
34095
34738
  this.lastModalLeftPad = Math.max(0, Math.floor((width - modalW) / 2));
34096
34739
  const isEmail = this.addActiveField === "email";
34097
34740
  const isPass = this.addActiveField === "password";
34098
- const emailHover = !isEmail && this.modalHoveredField === "email";
34099
- const passHover = !isPass && this.modalHoveredField === "password";
34741
+ const isCode = this.addActiveField === "code";
34100
34742
  let emailDisplay;
34101
34743
  if (isEmail) {
34102
34744
  if (this.addEmailInput.length === 0) {
@@ -34108,33 +34750,64 @@ var init_accounts_view = __esm({
34108
34750
  emailDisplay = `${theme.cyan(before)}${theme.inverse(at)}${theme.cyan(after)}`;
34109
34751
  }
34110
34752
  } else {
34111
- 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) ");
34112
- }
34113
- let passDisplay;
34114
- const maskedPass = "\u2022".repeat(this.addPasswordInput.length);
34115
- if (isPass) {
34116
- if (this.addPasswordInput.length === 0) {
34117
- 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
+ }
34769
+ } else {
34770
+ secondFieldDisplay = this.addPasswordInput ? theme.cyan(maskedPass) : theme.muted("(digite a senha)");
34771
+ }
34772
+ } else {
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
+ }
34118
34785
  } else {
34119
- const before = maskedPass.slice(0, this.addPasswordCursor);
34120
- const at = maskedPass[this.addPasswordCursor] || " ";
34121
- const after = maskedPass.slice(this.addPasswordCursor + 1);
34122
- passDisplay = `${theme.cyan(before)}${theme.inverse(at)}${theme.cyan(after)}`;
34786
+ secondFieldDisplay = this.addOtpCodeInput ? theme.cyan(this.addOtpCodeInput) : theme.muted("(digite o c\xF3digo de 6 d\xEDgitos)");
34123
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";
34124
34794
  } else {
34125
- passDisplay = this.addPasswordInput ? passHover ? theme.bgHover(` ${maskedPass} `) : theme.cyan(` ${maskedPass} `) : passHover ? theme.bgHover(" (digite a senha) ") : theme.muted(" (digite a senha) ");
34795
+ saveBtnText = "[ Enter ] Confirmar C\xF3digo";
34126
34796
  }
34127
- const saveBtn = this.isValidatingAccount ? theme.yellow(" [ Validando... ] ") : this.modalHoveredField === "save" ? theme.bgHover(theme.green(" [ Enter ] Salvar ")) : theme.green("[ Enter ] Salvar");
34128
- 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)} `;
34129
34801
  const modalContent = [
34130
34802
  "",
34131
- ` ${theme.bold("E-mail:")} ${emailDisplay}`,
34132
- ` ${theme.bold("Senha:")} ${passDisplay}`,
34803
+ ` ${theme.bold("E-mail:")} ${emailDisplay}${this.isOtpCodeSent ? ` ${theme.green("\u2713 C\xF3digo Enviado")}` : ""}`,
34804
+ ` ${theme.bold(secondFieldLabel)} ${secondFieldDisplay}`,
34133
34805
  "",
34134
- ` ${saveBtn} ${cancelBtn} ${theme.dim("(\u2191\u2193/mouse alternar)")}`
34806
+ ` ${saveBtn} ${cancelBtn} ${modeBtn}`
34135
34807
  ];
34808
+ const modalTitle = this.addLoginMode === "password" ? "Adicionar Nova Conta Qwen (Login com Senha)" : "Adicionar Nova Conta Qwen (Login sem Senha - OTP)";
34136
34809
  const modalBox = drawBox({
34137
- title: "Adicionar Nova Conta Qwen (Login)",
34810
+ title: modalTitle,
34138
34811
  width: modalW,
34139
34812
  height: Math.min(contentH, 11),
34140
34813
  borderColor: theme.borderActive,
@@ -34808,6 +35481,7 @@ var init_app = __esm({
34808
35481
 
34809
35482
  // src/index.ts
34810
35483
  init_paths();
35484
+ init_process_guard();
34811
35485
  init_server();
34812
35486
  import dotenv2 from "dotenv";
34813
35487
  import fs26 from "node:fs";
@@ -34823,24 +35497,7 @@ if (fs26.existsSync(envPath)) {
34823
35497
  } else {
34824
35498
  dotenv2.config({ quiet: true });
34825
35499
  }
34826
- process.on("uncaughtException", async (error) => {
34827
- const { isPlaywrightAlreadyClosedError: isPlaywrightAlreadyClosedError2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
34828
- if (isPlaywrightAlreadyClosedError2(error)) {
34829
- const msg = error instanceof Error ? error.message : typeof error === "object" && error !== null && "message" in error ? String(error.message) : String(error);
34830
- console.warn(`\u26A0\uFE0F [Playwright] Handled benign driver teardown exception: ${msg}`);
34831
- return;
34832
- }
34833
- console.error("\u274C [Process] Uncaught Exception:", error);
34834
- });
34835
- process.on("unhandledRejection", async (reason) => {
34836
- const { isPlaywrightAlreadyClosedError: isPlaywrightAlreadyClosedError2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
34837
- if (isPlaywrightAlreadyClosedError2(reason)) {
34838
- const msg = reason instanceof Error ? reason.message : typeof reason === "object" && reason !== null && "message" in reason ? String(reason.message) : String(reason);
34839
- console.warn(`\u26A0\uFE0F [Playwright] Handled benign driver teardown rejection: ${msg}`);
34840
- return;
34841
- }
34842
- console.error("\u274C [Process] Unhandled Rejection:", reason);
34843
- });
35500
+ installProcessTeardownGuards("Playwright");
34844
35501
  var isTui = process.argv.includes("--tui") || process.env.QWEN_TUI === "true";
34845
35502
  if (isTui) {
34846
35503
  const { TuiApp: TuiApp2 } = await Promise.resolve().then(() => (init_app(), app_exports));