qwenproxy-cli 1.6.1 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/clean-cache.js +7 -3
- package/dist/delete-chats.js +325 -8
- package/dist/index.js +667 -94
- package/dist/login.js +383 -9
- package/dist/reset-cooldowns.js +17 -3
- package/package.json +3 -3
- package/src/core/accounts.ts +1 -1
- package/src/core/version.ts +1 -1
- package/src/login.ts +90 -4
- package/src/routes/chat/account.ts +11 -4
- package/src/routes/chat/retry-policy.ts +45 -3
- package/src/routes/chat/streaming.ts +27 -0
- package/src/services/playwright.ts +378 -4
- package/src/services/qwen.ts +22 -6
- package/src/tui/views/accounts-view.ts +313 -96
- package/src/utils/overload-detector.ts +55 -0
package/dist/login.js
CHANGED
|
@@ -826,7 +826,7 @@ function addAccountsBatch(entries) {
|
|
|
826
826
|
}
|
|
827
827
|
return { added, skipped, invalid };
|
|
828
828
|
}
|
|
829
|
-
function addAccount(email, password, id) {
|
|
829
|
+
function addAccount(email, password = "", id) {
|
|
830
830
|
if (!email || typeof email !== "string" || email.trim().length === 0) {
|
|
831
831
|
throw new Error("Email is required");
|
|
832
832
|
}
|
|
@@ -3182,6 +3182,7 @@ var playwright_exports = {};
|
|
|
3182
3182
|
__export(playwright_exports, {
|
|
3183
3183
|
assertAntiBotHeaders: () => assertAntiBotHeaders,
|
|
3184
3184
|
buildChromiumLaunchArgs: () => buildChromiumLaunchArgs,
|
|
3185
|
+
cancelEmailOtpLogin: () => cancelEmailOtpLogin,
|
|
3185
3186
|
captureQwenHeaders: () => captureQwenHeaders,
|
|
3186
3187
|
classifyQwenAuthError: () => classifyQwenAuthError,
|
|
3187
3188
|
cleanupOrphanProfiles: () => cleanupOrphanProfiles,
|
|
@@ -3222,8 +3223,10 @@ __export(playwright_exports, {
|
|
|
3222
3223
|
removePlaywrightProfile: () => removePlaywrightProfile,
|
|
3223
3224
|
saveStorageState: () => saveStorageState,
|
|
3224
3225
|
schedulePlaywrightProfileReset: () => schedulePlaywrightProfileReset,
|
|
3226
|
+
startEmailOtpLogin: () => startEmailOtpLogin,
|
|
3225
3227
|
unregisterPlaywrightAccountForTests: () => unregisterPlaywrightAccountForTests,
|
|
3226
3228
|
validateAccountLogin: () => validateAccountLogin,
|
|
3229
|
+
verifyEmailOtpLogin: () => verifyEmailOtpLogin,
|
|
3227
3230
|
withAccountPage: () => withAccountPage
|
|
3228
3231
|
});
|
|
3229
3232
|
import { chromium as chromium2 } from "patchright";
|
|
@@ -3565,6 +3568,10 @@ async function clearVisibleChallenge(page) {
|
|
|
3565
3568
|
"button[aria-label*='Close' i]",
|
|
3566
3569
|
"button[aria-label*='Fechar' i]",
|
|
3567
3570
|
".index-module__whats-new-modal-close",
|
|
3571
|
+
".age-confirmation-modal button",
|
|
3572
|
+
".age-confirmation-modal .qwen-chat-v2-btn-black",
|
|
3573
|
+
"button:has-text('Continuar')",
|
|
3574
|
+
"button:has-text('Continue')",
|
|
3568
3575
|
"button:has-text('Cancel')",
|
|
3569
3576
|
"button:has-text('Cancelar')",
|
|
3570
3577
|
"button:has-text('I understand')",
|
|
@@ -4759,6 +4766,292 @@ async function validateAccountLogin(rawAccount, headless = true, browserType = "
|
|
|
4759
4766
|
release();
|
|
4760
4767
|
}
|
|
4761
4768
|
}
|
|
4769
|
+
async function startEmailOtpLogin(email, options = {}) {
|
|
4770
|
+
const normalizedEmail = email.trim().toLowerCase();
|
|
4771
|
+
if (!normalizedEmail || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(normalizedEmail)) {
|
|
4772
|
+
return { success: false, error: "Formato de e-mail inv\xE1lido" };
|
|
4773
|
+
}
|
|
4774
|
+
const { listAccounts: listAccounts2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
|
|
4775
|
+
if (listAccounts2().some((a) => a.email.toLowerCase() === normalizedEmail)) {
|
|
4776
|
+
return {
|
|
4777
|
+
success: false,
|
|
4778
|
+
error: `Uma conta com o e-mail "${normalizedEmail}" j\xE1 est\xE1 cadastrada.`
|
|
4779
|
+
};
|
|
4780
|
+
}
|
|
4781
|
+
if (process.env.TEST_MOCK_QWEN_AUTH === "true" && process.env.NODE_ENV !== "production") {
|
|
4782
|
+
const mockSessionId = "mock-otp-" + Date.now();
|
|
4783
|
+
mockOtpSessions.set(mockSessionId, normalizedEmail);
|
|
4784
|
+
return { success: true, sessionId: mockSessionId };
|
|
4785
|
+
}
|
|
4786
|
+
const accountId = crypto3.randomUUID();
|
|
4787
|
+
const sessionId = accountId;
|
|
4788
|
+
const profilePath = getAccountProfilePath(accountId);
|
|
4789
|
+
const fingerprint = getFingerprintProfile(accountId);
|
|
4790
|
+
const browserType = options.browserType ?? config.playwright.browser;
|
|
4791
|
+
const { engine, channel } = resolveBrowserEngine(browserType);
|
|
4792
|
+
const headless = options.headless ?? config.playwright.headless;
|
|
4793
|
+
const launchOptions = {
|
|
4794
|
+
headless,
|
|
4795
|
+
channel,
|
|
4796
|
+
userAgent: fingerprint.userAgent,
|
|
4797
|
+
locale: fingerprint.locale,
|
|
4798
|
+
timezoneId: fingerprint.timezoneId,
|
|
4799
|
+
viewport: fingerprint.viewport,
|
|
4800
|
+
screen: fingerprint.viewport,
|
|
4801
|
+
deviceScaleFactor: 1,
|
|
4802
|
+
isMobile: false,
|
|
4803
|
+
hasTouch: false,
|
|
4804
|
+
colorScheme: "light",
|
|
4805
|
+
extraHTTPHeaders: {
|
|
4806
|
+
"sec-ch-ua": fingerprint.secChUa,
|
|
4807
|
+
"sec-ch-ua-mobile": "?0",
|
|
4808
|
+
"sec-ch-ua-platform": '"Windows"'
|
|
4809
|
+
},
|
|
4810
|
+
ignoreDefaultArgs: ["--enable-automation", "--enable-blink-features"],
|
|
4811
|
+
args: buildChromiumLaunchArgs(fingerprint.viewport)
|
|
4812
|
+
};
|
|
4813
|
+
let acctContext;
|
|
4814
|
+
try {
|
|
4815
|
+
acctContext = await withTimeout(
|
|
4816
|
+
engine.launchPersistentContext(profilePath, launchOptions),
|
|
4817
|
+
3e4,
|
|
4818
|
+
`O navegador n\xE3o iniciou em 30s para a conta ${maskEmail(normalizedEmail)}.`
|
|
4819
|
+
);
|
|
4820
|
+
} catch (launchErr) {
|
|
4821
|
+
if (launchErr?.message?.includes("Executable doesn't exist")) {
|
|
4822
|
+
autoInstallPlaywrightChromium();
|
|
4823
|
+
acctContext = await withTimeout(
|
|
4824
|
+
engine.launchPersistentContext(profilePath, launchOptions),
|
|
4825
|
+
3e4,
|
|
4826
|
+
`O navegador n\xE3o iniciou em 30s para a conta ${maskEmail(normalizedEmail)}.`
|
|
4827
|
+
);
|
|
4828
|
+
} else {
|
|
4829
|
+
return { success: false, error: launchErr?.message || String(launchErr) };
|
|
4830
|
+
}
|
|
4831
|
+
}
|
|
4832
|
+
try {
|
|
4833
|
+
await acctContext.addInitScript(getStealthScript(fingerprint));
|
|
4834
|
+
const existingPages = acctContext.pages().filter((p) => !p.isClosed());
|
|
4835
|
+
const acctPage = existingPages.find((p) => p.url().startsWith(qwenOrigin())) ?? existingPages[0] ?? await acctContext.newPage();
|
|
4836
|
+
await acctPage.goto(qwenUrl("/auth?mode=register"), {
|
|
4837
|
+
waitUntil: "domcontentloaded",
|
|
4838
|
+
timeout: Math.min(config.timeouts.navigation, 2e4)
|
|
4839
|
+
}).catch(() => {
|
|
4840
|
+
});
|
|
4841
|
+
await sleep2(1e3);
|
|
4842
|
+
await clearVisibleChallenge(acctPage);
|
|
4843
|
+
const requestId = crypto3.randomUUID();
|
|
4844
|
+
const evalRes = await acctPage.evaluate(
|
|
4845
|
+
async ({ email: email2, requestId: requestId2, version, timezone }) => {
|
|
4846
|
+
try {
|
|
4847
|
+
const response = await fetch("https://auth.qwen.ai/api/v2/auths/otp/email/request", {
|
|
4848
|
+
method: "POST",
|
|
4849
|
+
credentials: "include",
|
|
4850
|
+
headers: {
|
|
4851
|
+
accept: "application/json, text/plain, */*",
|
|
4852
|
+
"content-type": "application/json",
|
|
4853
|
+
source: "web",
|
|
4854
|
+
version,
|
|
4855
|
+
"x-request-origin": "https://chat.qwen.ai",
|
|
4856
|
+
timezone,
|
|
4857
|
+
"x-request-id": requestId2
|
|
4858
|
+
},
|
|
4859
|
+
body: JSON.stringify({
|
|
4860
|
+
identifier: email2,
|
|
4861
|
+
accept_terms: true,
|
|
4862
|
+
language: "pt-BR"
|
|
4863
|
+
})
|
|
4864
|
+
});
|
|
4865
|
+
const json = await response.json().catch(() => null);
|
|
4866
|
+
return { ok: response.ok, status: response.status, data: json };
|
|
4867
|
+
} catch (e) {
|
|
4868
|
+
return { ok: false, error: e.message };
|
|
4869
|
+
}
|
|
4870
|
+
},
|
|
4871
|
+
{
|
|
4872
|
+
email: normalizedEmail,
|
|
4873
|
+
requestId,
|
|
4874
|
+
version: getQwenWebVersion() || "0.3.12",
|
|
4875
|
+
timezone: (/* @__PURE__ */ new Date()).toString().split(" (")[0]
|
|
4876
|
+
}
|
|
4877
|
+
).catch((err) => ({ ok: false, error: err?.message || String(err) }));
|
|
4878
|
+
if (!evalRes.ok || evalRes.data?.success !== true) {
|
|
4879
|
+
const errorMsg = evalRes.data?.data?.details || evalRes.data?.data?.message || evalRes.data?.message || evalRes.error || "Falha ao solicitar c\xF3digo de verifica\xE7\xE3o";
|
|
4880
|
+
await closePlaywrightContextBestEffort(accountId, acctContext).catch(() => {
|
|
4881
|
+
});
|
|
4882
|
+
cleanupPlaywrightAccountState(accountId);
|
|
4883
|
+
return { success: false, error: errorMsg };
|
|
4884
|
+
}
|
|
4885
|
+
const timer = setTimeout(async () => {
|
|
4886
|
+
activeOtpSessions.delete(sessionId);
|
|
4887
|
+
await closePlaywrightContextBestEffort(accountId, acctContext).catch(() => {
|
|
4888
|
+
});
|
|
4889
|
+
cleanupPlaywrightAccountState(accountId);
|
|
4890
|
+
}, 5 * 60 * 1e3);
|
|
4891
|
+
timer.unref?.();
|
|
4892
|
+
activeOtpSessions.set(sessionId, {
|
|
4893
|
+
sessionId,
|
|
4894
|
+
accountId,
|
|
4895
|
+
email: normalizedEmail,
|
|
4896
|
+
context: acctContext,
|
|
4897
|
+
page: acctPage,
|
|
4898
|
+
fingerprint,
|
|
4899
|
+
createdAt: Date.now(),
|
|
4900
|
+
timer
|
|
4901
|
+
});
|
|
4902
|
+
return { success: true, sessionId };
|
|
4903
|
+
} catch (err) {
|
|
4904
|
+
await closePlaywrightContextBestEffort(accountId, acctContext).catch(() => {
|
|
4905
|
+
});
|
|
4906
|
+
cleanupPlaywrightAccountState(accountId);
|
|
4907
|
+
return { success: false, error: err?.message || String(err) };
|
|
4908
|
+
}
|
|
4909
|
+
}
|
|
4910
|
+
async function verifyEmailOtpLogin(sessionId, code) {
|
|
4911
|
+
const cleanCode = code.trim();
|
|
4912
|
+
if (!cleanCode) {
|
|
4913
|
+
return { success: false, error: "C\xF3digo de verifica\xE7\xE3o \xE9 obrigat\xF3rio" };
|
|
4914
|
+
}
|
|
4915
|
+
if (process.env.TEST_MOCK_QWEN_AUTH === "true" && process.env.NODE_ENV !== "production") {
|
|
4916
|
+
const mockEmail = mockOtpSessions.get(sessionId);
|
|
4917
|
+
if (!mockEmail) {
|
|
4918
|
+
return { success: false, error: "Sess\xE3o OTP inv\xE1lida ou expirada" };
|
|
4919
|
+
}
|
|
4920
|
+
if (cleanCode === "000000") {
|
|
4921
|
+
return { success: false, error: "C\xF3digo de verifica\xE7\xE3o incorreto ou expirado" };
|
|
4922
|
+
}
|
|
4923
|
+
const { addAccount: addAccount2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
|
|
4924
|
+
const mockAccId = "mock-otp-acc-" + Date.now();
|
|
4925
|
+
const newAccount = addAccount2(mockEmail, "", mockAccId);
|
|
4926
|
+
mockOtpSessions.delete(sessionId);
|
|
4927
|
+
return { success: true, account: newAccount };
|
|
4928
|
+
}
|
|
4929
|
+
const session = activeOtpSessions.get(sessionId);
|
|
4930
|
+
if (!session) {
|
|
4931
|
+
return { success: false, error: "Sess\xE3o OTP expirada ou n\xE3o encontrada. Solicite um novo c\xF3digo." };
|
|
4932
|
+
}
|
|
4933
|
+
if (session.page.isClosed()) {
|
|
4934
|
+
activeOtpSessions.delete(sessionId);
|
|
4935
|
+
return { success: false, error: "Navegador foi fechado. Solicite um novo c\xF3digo." };
|
|
4936
|
+
}
|
|
4937
|
+
const requestId = crypto3.randomUUID();
|
|
4938
|
+
const evalRes = await session.page.evaluate(
|
|
4939
|
+
async ({ email, code: code2, requestId: requestId2, version, timezone }) => {
|
|
4940
|
+
try {
|
|
4941
|
+
const response = await fetch("https://auth.qwen.ai/api/v2/auths/otp/email/verify", {
|
|
4942
|
+
method: "POST",
|
|
4943
|
+
credentials: "include",
|
|
4944
|
+
headers: {
|
|
4945
|
+
accept: "application/json, text/plain, */*",
|
|
4946
|
+
"content-type": "application/json",
|
|
4947
|
+
source: "web",
|
|
4948
|
+
version,
|
|
4949
|
+
"x-request-origin": "https://chat.qwen.ai",
|
|
4950
|
+
timezone,
|
|
4951
|
+
"x-request-id": requestId2
|
|
4952
|
+
},
|
|
4953
|
+
body: JSON.stringify({
|
|
4954
|
+
identifier: email,
|
|
4955
|
+
code: code2,
|
|
4956
|
+
name: null
|
|
4957
|
+
})
|
|
4958
|
+
});
|
|
4959
|
+
const json = await response.json().catch(() => null);
|
|
4960
|
+
return { ok: response.ok, status: response.status, data: json };
|
|
4961
|
+
} catch (e) {
|
|
4962
|
+
return { ok: false, error: e.message };
|
|
4963
|
+
}
|
|
4964
|
+
},
|
|
4965
|
+
{
|
|
4966
|
+
email: session.email,
|
|
4967
|
+
code: cleanCode,
|
|
4968
|
+
requestId,
|
|
4969
|
+
version: getQwenWebVersion() || "0.3.12",
|
|
4970
|
+
timezone: (/* @__PURE__ */ new Date()).toString().split(" (")[0]
|
|
4971
|
+
}
|
|
4972
|
+
).catch((err) => ({ ok: false, error: err?.message || String(err) }));
|
|
4973
|
+
if (!evalRes.ok || evalRes.data?.success !== true || !evalRes.data?.data) {
|
|
4974
|
+
const errorMsg = evalRes.data?.data?.details || evalRes.data?.data?.message || evalRes.data?.message || evalRes.error || "C\xF3digo de verifica\xE7\xE3o incorreto ou expirado";
|
|
4975
|
+
return { success: false, error: errorMsg };
|
|
4976
|
+
}
|
|
4977
|
+
const resData = evalRes.data.data;
|
|
4978
|
+
const accessToken = resData.access_token || resData.token;
|
|
4979
|
+
const refreshToken = resData.refresh_token;
|
|
4980
|
+
const userId = resData.id;
|
|
4981
|
+
try {
|
|
4982
|
+
await session.page.evaluate(({ token, rTok }) => {
|
|
4983
|
+
try {
|
|
4984
|
+
localStorage.setItem("token", token);
|
|
4985
|
+
localStorage.setItem("access_token", token);
|
|
4986
|
+
if (rTok) localStorage.setItem("refresh_token", rTok);
|
|
4987
|
+
document.cookie = `token=${encodeURIComponent(token)}; path=/; domain=.qwen.ai; max-age=31536000`;
|
|
4988
|
+
} catch {
|
|
4989
|
+
}
|
|
4990
|
+
}, { token: accessToken, rTok: refreshToken });
|
|
4991
|
+
await session.context.addCookies([
|
|
4992
|
+
{
|
|
4993
|
+
name: "token",
|
|
4994
|
+
value: accessToken,
|
|
4995
|
+
domain: ".qwen.ai",
|
|
4996
|
+
path: "/",
|
|
4997
|
+
expires: Math.floor(Date.now() / 1e3) + 31536e3,
|
|
4998
|
+
httpOnly: false,
|
|
4999
|
+
secure: true,
|
|
5000
|
+
sameSite: "Lax"
|
|
5001
|
+
}
|
|
5002
|
+
]);
|
|
5003
|
+
await session.page.goto(qwenUrl("/"), {
|
|
5004
|
+
waitUntil: "domcontentloaded",
|
|
5005
|
+
timeout: Math.min(config.timeouts.navigation, 15e3)
|
|
5006
|
+
}).catch(() => {
|
|
5007
|
+
});
|
|
5008
|
+
await sleep2(1e3);
|
|
5009
|
+
await saveStorageState(session.context, session.accountId);
|
|
5010
|
+
const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
5011
|
+
const { parseJwtExpiry: parseJwtExpiry2 } = await Promise.resolve().then(() => (init_jwt(), jwt_exports));
|
|
5012
|
+
const exp = parseJwtExpiry2(accessToken);
|
|
5013
|
+
saveAuthSession2(session.accountId, {
|
|
5014
|
+
cookie: `token=${accessToken}`,
|
|
5015
|
+
userAgent: session.fingerprint.userAgent,
|
|
5016
|
+
bxV: "2.5.37",
|
|
5017
|
+
version: getQwenWebVersion() || "0.3.12",
|
|
5018
|
+
userId: userId || void 0,
|
|
5019
|
+
tokenExpiresAt: exp || void 0,
|
|
5020
|
+
refreshToken: refreshToken || void 0,
|
|
5021
|
+
capturedAt: Date.now()
|
|
5022
|
+
});
|
|
5023
|
+
const { addAccount: addAccount2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
|
|
5024
|
+
const newAccount = addAccount2(session.email, "", session.accountId);
|
|
5025
|
+
clearTimeout(session.timer);
|
|
5026
|
+
activeOtpSessions.delete(sessionId);
|
|
5027
|
+
await closePlaywrightContextBestEffort(session.accountId, session.context).catch(() => {
|
|
5028
|
+
});
|
|
5029
|
+
cleanupPlaywrightAccountState(session.accountId);
|
|
5030
|
+
return { success: true, account: newAccount };
|
|
5031
|
+
} catch (err) {
|
|
5032
|
+
clearTimeout(session.timer);
|
|
5033
|
+
activeOtpSessions.delete(sessionId);
|
|
5034
|
+
await closePlaywrightContextBestEffort(session.accountId, session.context).catch(() => {
|
|
5035
|
+
});
|
|
5036
|
+
cleanupPlaywrightAccountState(session.accountId);
|
|
5037
|
+
return { success: false, error: err?.message || String(err) };
|
|
5038
|
+
}
|
|
5039
|
+
}
|
|
5040
|
+
async function cancelEmailOtpLogin(sessionId) {
|
|
5041
|
+
if (process.env.TEST_MOCK_QWEN_AUTH === "true" && process.env.NODE_ENV !== "production") {
|
|
5042
|
+
mockOtpSessions.delete(sessionId);
|
|
5043
|
+
return;
|
|
5044
|
+
}
|
|
5045
|
+
const session = activeOtpSessions.get(sessionId);
|
|
5046
|
+
if (!session) return;
|
|
5047
|
+
clearTimeout(session.timer);
|
|
5048
|
+
activeOtpSessions.delete(sessionId);
|
|
5049
|
+
await closePlaywrightContextBestEffort(session.accountId, session.context).catch(() => {
|
|
5050
|
+
});
|
|
5051
|
+
cleanupPlaywrightAccountState(session.accountId);
|
|
5052
|
+
const { wipeAccountSessionFiles: wipeAccountSessionFiles2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
|
|
5053
|
+
wipeAccountSessionFiles2(session.accountId);
|
|
5054
|
+
}
|
|
4762
5055
|
function classifyQwenAuthError(code, details) {
|
|
4763
5056
|
const c = (code || "").trim().toLowerCase();
|
|
4764
5057
|
const d = (details || "").trim().toLowerCase();
|
|
@@ -6127,7 +6420,7 @@ async function withAccountPage(accountId, fn, timeoutMs = ACCOUNT_PAGE_OPERATION
|
|
|
6127
6420
|
return result;
|
|
6128
6421
|
} catch (error) {
|
|
6129
6422
|
const message = getErrorMessage(error);
|
|
6130
|
-
if (recoverOnTimeout && message.includes("Playwright page operation timed out")) {
|
|
6423
|
+
if (recoverOnTimeout && message.includes("Playwright page operation timed out") && (!page || page.isClosed())) {
|
|
6131
6424
|
console.warn(
|
|
6132
6425
|
`\u23F1\uFE0F [Playwright] Resetting account context after a stuck page operation: ${accountId}`
|
|
6133
6426
|
);
|
|
@@ -6676,7 +6969,7 @@ async function getTokenDiagnostics(accountId) {
|
|
|
6676
6969
|
}
|
|
6677
6970
|
};
|
|
6678
6971
|
}
|
|
6679
|
-
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;
|
|
6972
|
+
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;
|
|
6680
6973
|
var init_playwright = __esm({
|
|
6681
6974
|
"src/services/playwright.ts"() {
|
|
6682
6975
|
"use strict";
|
|
@@ -6721,11 +7014,13 @@ var init_playwright = __esm({
|
|
|
6721
7014
|
PLAYWRIGHT_MUTEX_WAIT_MS = 6e4;
|
|
6722
7015
|
ACCOUNT_PAGE_OPERATION_TIMEOUT_MS = config.timeouts.page;
|
|
6723
7016
|
SESSION_PROBE_NAVIGATION_TIMEOUT_MS = 15e3;
|
|
6724
|
-
HEADER_CAPTURE_TRIGGER_GRACE_MS =
|
|
6725
|
-
FIRST_TRIGGER_GRACE_MS =
|
|
7017
|
+
HEADER_CAPTURE_TRIGGER_GRACE_MS = 2e4;
|
|
7018
|
+
FIRST_TRIGGER_GRACE_MS = 12e3;
|
|
6726
7019
|
HEADER_CAPTURE_TRIGGER_ATTEMPTS = 3;
|
|
6727
7020
|
CHAT_INPUT_APPEAR_TIMEOUT_MS = 15e3;
|
|
6728
7021
|
CHAT_INPUT_ACTION_TIMEOUT_MS = 1e4;
|
|
7022
|
+
activeOtpSessions = /* @__PURE__ */ new Map();
|
|
7023
|
+
mockOtpSessions = /* @__PURE__ */ new Map();
|
|
6729
7024
|
PROFILE_RESET_TIMEOUT_MS = Math.max(9e4, config.timeouts.headers);
|
|
6730
7025
|
setWafContextResetListener((accountId) => {
|
|
6731
7026
|
if (!accountPages.has(accountId)) return;
|
|
@@ -6779,7 +7074,8 @@ async function showMenu() {
|
|
|
6779
7074
|
console.log("No accounts configured yet.\n");
|
|
6780
7075
|
}
|
|
6781
7076
|
console.log("\nOptions:");
|
|
6782
|
-
console.log(" [A] Add account");
|
|
7077
|
+
console.log(" [A] Add account (Password)");
|
|
7078
|
+
console.log(" [O] Add account (Passwordless / Email OTP)");
|
|
6783
7079
|
if (accounts.length > 0) {
|
|
6784
7080
|
console.log(" [R] Remove an account");
|
|
6785
7081
|
}
|
|
@@ -6790,7 +7086,21 @@ async function showMenu() {
|
|
|
6790
7086
|
process.exit(0);
|
|
6791
7087
|
}
|
|
6792
7088
|
if (choice === "A") {
|
|
6793
|
-
|
|
7089
|
+
clear();
|
|
7090
|
+
console.log("=== Add New Account ===\n");
|
|
7091
|
+
console.log("Authentication method:");
|
|
7092
|
+
console.log(" [1] Traditional Password (Email + Password)");
|
|
7093
|
+
console.log(" [2] Passwordless (Email Verification Code / OTP)\n");
|
|
7094
|
+
const method = (await askQuestion("Select method [1/2] (default 1): ")).trim();
|
|
7095
|
+
if (method === "2") {
|
|
7096
|
+
await addAccountOtpFlow();
|
|
7097
|
+
} else {
|
|
7098
|
+
await addAccountPasswordFlow();
|
|
7099
|
+
}
|
|
7100
|
+
continue;
|
|
7101
|
+
}
|
|
7102
|
+
if (choice === "O") {
|
|
7103
|
+
await addAccountOtpFlow();
|
|
6794
7104
|
continue;
|
|
6795
7105
|
}
|
|
6796
7106
|
if (choice === "R" && accounts.length > 0) {
|
|
@@ -6799,9 +7109,9 @@ async function showMenu() {
|
|
|
6799
7109
|
}
|
|
6800
7110
|
}
|
|
6801
7111
|
}
|
|
6802
|
-
async function
|
|
7112
|
+
async function addAccountPasswordFlow() {
|
|
6803
7113
|
clear();
|
|
6804
|
-
console.log("=== Add New Account ===\n");
|
|
7114
|
+
console.log("=== Add New Account (Password Login) ===\n");
|
|
6805
7115
|
const email = await askQuestion("Email: ");
|
|
6806
7116
|
if (!email || !email.trim()) {
|
|
6807
7117
|
console.log("Email is required.");
|
|
@@ -6870,6 +7180,70 @@ async function addAccountFlow() {
|
|
|
6870
7180
|
}
|
|
6871
7181
|
await askQuestion("\nPress Enter to continue...");
|
|
6872
7182
|
}
|
|
7183
|
+
async function addAccountOtpFlow() {
|
|
7184
|
+
clear();
|
|
7185
|
+
console.log("=== Add New Account (Passwordless / Email OTP) ===\n");
|
|
7186
|
+
const email = await askQuestion("Email: ");
|
|
7187
|
+
if (!email || !email.trim()) {
|
|
7188
|
+
console.log("Email is required.");
|
|
7189
|
+
await askQuestion("Press Enter to continue...");
|
|
7190
|
+
return;
|
|
7191
|
+
}
|
|
7192
|
+
const trimmedEmail = email.trim();
|
|
7193
|
+
const existingAccounts = listAccounts();
|
|
7194
|
+
if (existingAccounts.some(
|
|
7195
|
+
(a) => a.email.toLowerCase() === trimmedEmail.toLowerCase()
|
|
7196
|
+
)) {
|
|
7197
|
+
console.log(
|
|
7198
|
+
`
|
|
7199
|
+
\u274C Error: An account with email "${trimmedEmail}" already exists.`
|
|
7200
|
+
);
|
|
7201
|
+
await askQuestion("Press Enter to continue...");
|
|
7202
|
+
return;
|
|
7203
|
+
}
|
|
7204
|
+
console.log(
|
|
7205
|
+
`
|
|
7206
|
+
\u23F3 Requesting OTP verification code for ${maskEmail(trimmedEmail)}...`
|
|
7207
|
+
);
|
|
7208
|
+
const { startEmailOtpLogin: startEmailOtpLogin2, verifyEmailOtpLogin: verifyEmailOtpLogin2, cancelEmailOtpLogin: cancelEmailOtpLogin2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
|
|
7209
|
+
const startRes = await startEmailOtpLogin2(trimmedEmail, { headless: false });
|
|
7210
|
+
if (!startRes.success || !startRes.sessionId) {
|
|
7211
|
+
console.log(
|
|
7212
|
+
`
|
|
7213
|
+
\u274C Failed to request code: ${startRes.error || "Unknown error"}`
|
|
7214
|
+
);
|
|
7215
|
+
await askQuestion("Press Enter to continue...");
|
|
7216
|
+
return;
|
|
7217
|
+
}
|
|
7218
|
+
console.log(`
|
|
7219
|
+
\u2709\uFE0F Verification code sent to ${trimmedEmail}!`);
|
|
7220
|
+
console.log("Check your email inbox (and spam folder).\n");
|
|
7221
|
+
while (true) {
|
|
7222
|
+
const code = await askQuestion("Enter 6-digit code (or 'C' to cancel): ");
|
|
7223
|
+
if (!code || !code.trim()) continue;
|
|
7224
|
+
if (code.trim().toUpperCase() === "C") {
|
|
7225
|
+
await cancelEmailOtpLogin2(startRes.sessionId);
|
|
7226
|
+
console.log("\nLogin cancelled.");
|
|
7227
|
+
await askQuestion("Press Enter to continue...");
|
|
7228
|
+
return;
|
|
7229
|
+
}
|
|
7230
|
+
console.log("\n\u23F3 Verifying code and establishing 30-day session...");
|
|
7231
|
+
const verifyRes = await verifyEmailOtpLogin2(startRes.sessionId, code.trim());
|
|
7232
|
+
if (verifyRes.success && verifyRes.account) {
|
|
7233
|
+
console.log(
|
|
7234
|
+
`
|
|
7235
|
+
\u2705 Account verified and saved: ${maskEmail(verifyRes.account.email)} (${verifyRes.account.id})`
|
|
7236
|
+
);
|
|
7237
|
+
console.log("Passwordless 30-day session active.");
|
|
7238
|
+
await askQuestion("\nPress Enter to continue...");
|
|
7239
|
+
return;
|
|
7240
|
+
} else {
|
|
7241
|
+
console.log(`
|
|
7242
|
+
\u274C ${verifyRes.error || "Invalid code"}`);
|
|
7243
|
+
console.log("Please try again or enter 'C' to cancel.\n");
|
|
7244
|
+
}
|
|
7245
|
+
}
|
|
7246
|
+
}
|
|
6873
7247
|
async function removeAccountFlow() {
|
|
6874
7248
|
const accounts = listAccounts();
|
|
6875
7249
|
if (accounts.length === 0) return;
|
package/dist/reset-cooldowns.js
CHANGED
|
@@ -781,7 +781,7 @@ function addAccountsBatch(entries) {
|
|
|
781
781
|
}
|
|
782
782
|
return { added, skipped, invalid };
|
|
783
783
|
}
|
|
784
|
-
function addAccount(email, password, id) {
|
|
784
|
+
function addAccount(email, password = "", id) {
|
|
785
785
|
if (!email || typeof email !== "string" || email.trim().length === 0) {
|
|
786
786
|
throw new Error("Email is required");
|
|
787
787
|
}
|
|
@@ -3226,6 +3226,10 @@ async function clearVisibleChallenge(page) {
|
|
|
3226
3226
|
"button[aria-label*='Close' i]",
|
|
3227
3227
|
"button[aria-label*='Fechar' i]",
|
|
3228
3228
|
".index-module__whats-new-modal-close",
|
|
3229
|
+
".age-confirmation-modal button",
|
|
3230
|
+
".age-confirmation-modal .qwen-chat-v2-btn-black",
|
|
3231
|
+
"button:has-text('Continuar')",
|
|
3232
|
+
"button:has-text('Continue')",
|
|
3229
3233
|
"button:has-text('Cancel')",
|
|
3230
3234
|
"button:has-text('Cancelar')",
|
|
3231
3235
|
"button:has-text('I understand')",
|
|
@@ -5585,8 +5589,8 @@ var init_playwright = __esm({
|
|
|
5585
5589
|
PLAYWRIGHT_MUTEX_WAIT_MS = 6e4;
|
|
5586
5590
|
ACCOUNT_PAGE_OPERATION_TIMEOUT_MS = config.timeouts.page;
|
|
5587
5591
|
SESSION_PROBE_NAVIGATION_TIMEOUT_MS = 15e3;
|
|
5588
|
-
HEADER_CAPTURE_TRIGGER_GRACE_MS =
|
|
5589
|
-
FIRST_TRIGGER_GRACE_MS =
|
|
5592
|
+
HEADER_CAPTURE_TRIGGER_GRACE_MS = 2e4;
|
|
5593
|
+
FIRST_TRIGGER_GRACE_MS = 12e3;
|
|
5590
5594
|
HEADER_CAPTURE_TRIGGER_ATTEMPTS = 3;
|
|
5591
5595
|
CHAT_INPUT_APPEAR_TIMEOUT_MS = 15e3;
|
|
5592
5596
|
CHAT_INPUT_ACTION_TIMEOUT_MS = 1e4;
|
|
@@ -5702,6 +5706,15 @@ var init_helpers = __esm({
|
|
|
5702
5706
|
}
|
|
5703
5707
|
});
|
|
5704
5708
|
|
|
5709
|
+
// src/utils/overload-detector.ts
|
|
5710
|
+
var OVERLOAD_COOLDOWN_MS;
|
|
5711
|
+
var init_overload_detector = __esm({
|
|
5712
|
+
"src/utils/overload-detector.ts"() {
|
|
5713
|
+
"use strict";
|
|
5714
|
+
OVERLOAD_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
5715
|
+
}
|
|
5716
|
+
});
|
|
5717
|
+
|
|
5705
5718
|
// src/routes/chat/retry-policy.ts
|
|
5706
5719
|
var init_retry_policy = __esm({
|
|
5707
5720
|
"src/routes/chat/retry-policy.ts"() {
|
|
@@ -5712,6 +5725,7 @@ var init_retry_policy = __esm({
|
|
|
5712
5725
|
init_qwen();
|
|
5713
5726
|
init_errors();
|
|
5714
5727
|
init_helpers();
|
|
5728
|
+
init_overload_detector();
|
|
5715
5729
|
init_account_manager();
|
|
5716
5730
|
}
|
|
5717
5731
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qwenproxy-cli",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"description": "High-performance OpenAI & Anthropic compatible API gateway for Qwen with multi-account rotation, interactive TUI, and resilient tool calling.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"bin": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"reset": "npx tsx src/reset-cooldowns.ts",
|
|
30
30
|
"purge": "npx tsx src/delete-chats.ts",
|
|
31
31
|
"test": "npm run test:mock && npm run test:live",
|
|
32
|
-
"test:mock": "tsx --test --test-concurrency=1 --env-file=.env.test src/tests/account-concurrency.test.ts src/tests/concurrency-latest-wins.test.ts src/tests/mutex.test.ts src/tests/context-truncation.test.ts src/tests/streaming-thinking-summary.test.ts src/tests/tool-call-guard.test.ts src/tests/utils-logger-full.test.ts src/tests/logger-toolcall-errors.test.ts src/tests/logger-toolcall-disabled.test.ts src/tests/utils-json-full.test.ts src/tests/utils-session-guard-full.test.ts src/tests/core-logic-full.test.ts src/tests/core-logic-accounts.test.ts src/tests/chat-validation-full.test.ts src/tests/chat-logic-full.test.ts src/tests/account-stickiness.test.ts src/tests/accounts-security.test.ts src/tests/advanced.test.ts src/tests/auth-playwright.test.ts src/tests/auth-session-persistence.test.ts src/tests/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.test.ts src/tests/chat-cleanup-auto.test.ts src/tests/chromium-args.test.ts src/tests/config-current.test.ts src/tests/context-meter.test.ts src/tests/concurrency.test.ts src/tests/delta.test.ts src/tests/fingerprint.test.ts src/tests/human-behavior.test.ts src/tests/index.test.ts src/tests/json-recovery.test.ts src/tests/jsonFix.test.ts src/tests/memory-cache.test.ts src/tests/model-alias.test.ts src/tests/model-registry-thinking.test.ts src/tests/models-endpoint.test.ts src/tests/multimodal.test.ts src/tests/oss-upload.test.ts src/tests/parser.test.ts src/tests/personalization-flow.test.ts src/tests/personalization-required.test.ts src/tests/retry-policy.test.ts src/tests/rotation.test.ts src/tests/server-lifecycle.test.ts src/tests/session-keeper.test.ts src/tests/session-state.test.ts src/tests/single-account-mode.test.ts src/tests/stream-retry.test.ts src/tests/tool-calls-endpoint.test.ts src/tests/tool-instructions-cache.test.ts src/tests/session-id.test.ts src/tests/watchdog-ram.test.ts src/tests/tool-recovery-t1t2.test.ts src/tests/abort-silent-t4.test.ts src/tests/t3-close-tag-escape.test.ts src/tests/t5-tool-cap.test.ts src/tests/logger-redaction.test.ts src/tests/stall-timeout-retryable.test.ts src/tests/t6-missing-quote-array-close.test.ts src/tests/watchdog-rss.test.ts src/tests/logical-thread-batch.test.ts src/tests/chat-pool-style.test.ts src/tests/queue-wait-cap.test.ts src/tests/context-eviction-order.test.ts src/tests/chat-in-progress-settle.test.ts src/tests/stream-lock-leak.test.ts src/tests/stream-semaphore.test.ts src/tests/waf-isolation.test.ts src/tests/legacy-completions.test.ts src/tests/response-format.test.ts src/tests/cors-headers.test.ts src/tests/local-auth.test.ts src/tests/safe-remote-url.test.ts src/tests/stream-lock-terminal-cancel.test.ts src/tests/parser-truncated-tool-call.test.ts src/tests/metrics-prometheus.test.ts src/tests/context-death-cleanup.test.ts src/tests/personalization-direct-fetch.test.ts src/tests/completion-headers-parity.test.ts src/tests/parallel-escape-repro.test.ts src/tests/chat-in-progress-scale-cost.test.ts src/tests/temp-chat-mode.test.ts src/tests/profile-reset.test.ts src/tests/error-classification.test.ts src/tests/quota-cooldown.test.ts src/tests/account-ready-gate.test.ts src/tests/tool-cap-notice.test.ts src/tests/interaction-flows.test.ts src/tests/headers-gate-cooldown-fallback.test.ts src/tests/unwrapped-tool-calls.test.ts src/tests/anthropic.test.ts src/tests/sync-clients.test.ts src/tests/sync-top10-clients.test.ts src/tests/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts src/tests/tui-settings.test.ts src/tests/personalization-deadline.test.ts src/tests/update-cli.test.ts src/tests/batch-accounts.test.ts src/tests/shared-browser.test.ts src/tests/auth-credential-classification.test.ts src/tests/responses-api.test.ts src/tests/media-generation.test.ts src/tests/infer-tool-name.test.ts src/tests/native-session-headers.test.ts src/tests/omni-thinking.test.ts src/tests/protect-stuck-mutex.test.ts src/tests/stream-error-notice.test.ts src/tests/parser-deep-coverage.test.ts src/tests/tui-logs-copy.test.ts src/tests/auth-jwt-and-validation.test.ts src/tests/tui-port-and-key-modal.test.ts src/tests/verify-zero-fake-cooldown.test.ts src/tests/auth-session-refresh-preservation.test.ts src/tests/personalization-in-flight-dedup.test.ts src/tests/daily-usage.test.ts src/tests/resilience-enhancements.test.ts src/tests/pool-quota-failover.test.ts",
|
|
33
|
-
"test:mock:fast": "tsx --test --test-concurrency=2 --env-file=.env.test src/tests/account-concurrency.test.ts src/tests/concurrency-latest-wins.test.ts src/tests/mutex.test.ts src/tests/context-truncation.test.ts src/tests/streaming-thinking-summary.test.ts src/tests/tool-call-guard.test.ts src/tests/utils-logger-full.test.ts src/tests/logger-toolcall-errors.test.ts src/tests/logger-toolcall-disabled.test.ts src/tests/utils-json-full.test.ts src/tests/utils-session-guard-full.test.ts src/tests/core-logic-full.test.ts src/tests/core-logic-accounts.test.ts src/tests/chat-validation-full.test.ts src/tests/chat-logic-full.test.ts src/tests/account-stickiness.test.ts src/tests/accounts-security.test.ts src/tests/advanced.test.ts src/tests/auth-playwright.test.ts src/tests/auth-session-persistence.test.ts src/tests/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.test.ts src/tests/chat-cleanup-auto.test.ts src/tests/chromium-args.test.ts src/tests/config-current.test.ts src/tests/context-meter.test.ts src/tests/concurrency.test.ts src/tests/delta.test.ts src/tests/fingerprint.test.ts src/tests/human-behavior.test.ts src/tests/index.test.ts src/tests/json-recovery.test.ts src/tests/jsonFix.test.ts src/tests/memory-cache.test.ts src/tests/model-alias.test.ts src/tests/model-registry-thinking.test.ts src/tests/models-endpoint.test.ts src/tests/multimodal.test.ts src/tests/oss-upload.test.ts src/tests/parser.test.ts src/tests/personalization-flow.test.ts src/tests/personalization-required.test.ts src/tests/retry-policy.test.ts src/tests/rotation.test.ts src/tests/server-lifecycle.test.ts src/tests/session-keeper.test.ts src/tests/session-state.test.ts src/tests/single-account-mode.test.ts src/tests/stream-retry.test.ts src/tests/tool-calls-endpoint.test.ts src/tests/tool-instructions-cache.test.ts src/tests/session-id.test.ts src/tests/watchdog-ram.test.ts src/tests/tool-recovery-t1t2.test.ts src/tests/abort-silent-t4.test.ts src/tests/t3-close-tag-escape.test.ts src/tests/t5-tool-cap.test.ts src/tests/logger-redaction.test.ts src/tests/stall-timeout-retryable.test.ts src/tests/t6-missing-quote-array-close.test.ts src/tests/watchdog-rss.test.ts src/tests/logical-thread-batch.test.ts src/tests/chat-pool-style.test.ts src/tests/queue-wait-cap.test.ts src/tests/context-eviction-order.test.ts src/tests/chat-in-progress-settle.test.ts src/tests/stream-lock-leak.test.ts src/tests/stream-semaphore.test.ts src/tests/waf-isolation.test.ts src/tests/legacy-completions.test.ts src/tests/response-format.test.ts src/tests/cors-headers.test.ts src/tests/local-auth.test.ts src/tests/safe-remote-url.test.ts src/tests/stream-lock-terminal-cancel.test.ts src/tests/parser-truncated-tool-call.test.ts src/tests/metrics-prometheus.test.ts src/tests/context-death-cleanup.test.ts src/tests/personalization-direct-fetch.test.ts src/tests/completion-headers-parity.test.ts src/tests/parallel-escape-repro.test.ts src/tests/chat-in-progress-scale-cost.test.ts src/tests/temp-chat-mode.test.ts src/tests/profile-reset.test.ts src/tests/error-classification.test.ts src/tests/quota-cooldown.test.ts src/tests/account-ready-gate.test.ts src/tests/tool-cap-notice.test.ts src/tests/interaction-flows.test.ts src/tests/headers-gate-cooldown-fallback.test.ts src/tests/unwrapped-tool-calls.test.ts src/tests/anthropic.test.ts src/tests/sync-clients.test.ts src/tests/sync-top10-clients.test.ts src/tests/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts src/tests/tui-settings.test.ts src/tests/personalization-deadline.test.ts src/tests/update-cli.test.ts src/tests/batch-accounts.test.ts src/tests/shared-browser.test.ts src/tests/auth-credential-classification.test.ts src/tests/responses-api.test.ts src/tests/media-generation.test.ts src/tests/infer-tool-name.test.ts src/tests/native-session-headers.test.ts src/tests/omni-thinking.test.ts src/tests/protect-stuck-mutex.test.ts src/tests/stream-error-notice.test.ts src/tests/parser-deep-coverage.test.ts src/tests/tui-logs-copy.test.ts src/tests/auth-jwt-and-validation.test.ts src/tests/tui-port-and-key-modal.test.ts src/tests/verify-zero-fake-cooldown.test.ts src/tests/auth-session-refresh-preservation.test.ts src/tests/personalization-in-flight-dedup.test.ts src/tests/daily-usage.test.ts src/tests/resilience-enhancements.test.ts src/tests/pool-quota-failover.test.ts",
|
|
32
|
+
"test:mock": "tsx --test --test-concurrency=1 --env-file=.env.test src/tests/account-concurrency.test.ts src/tests/concurrency-latest-wins.test.ts src/tests/mutex.test.ts src/tests/context-truncation.test.ts src/tests/streaming-thinking-summary.test.ts src/tests/tool-call-guard.test.ts src/tests/utils-logger-full.test.ts src/tests/logger-toolcall-errors.test.ts src/tests/logger-toolcall-disabled.test.ts src/tests/utils-json-full.test.ts src/tests/utils-session-guard-full.test.ts src/tests/core-logic-full.test.ts src/tests/core-logic-accounts.test.ts src/tests/chat-validation-full.test.ts src/tests/chat-logic-full.test.ts src/tests/account-stickiness.test.ts src/tests/accounts-security.test.ts src/tests/advanced.test.ts src/tests/auth-playwright.test.ts src/tests/auth-session-persistence.test.ts src/tests/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.test.ts src/tests/chat-cleanup-auto.test.ts src/tests/chromium-args.test.ts src/tests/config-current.test.ts src/tests/context-meter.test.ts src/tests/concurrency.test.ts src/tests/delta.test.ts src/tests/fingerprint.test.ts src/tests/human-behavior.test.ts src/tests/index.test.ts src/tests/json-recovery.test.ts src/tests/jsonFix.test.ts src/tests/memory-cache.test.ts src/tests/model-alias.test.ts src/tests/model-registry-thinking.test.ts src/tests/models-endpoint.test.ts src/tests/multimodal.test.ts src/tests/oss-upload.test.ts src/tests/parser.test.ts src/tests/personalization-flow.test.ts src/tests/personalization-required.test.ts src/tests/retry-policy.test.ts src/tests/rotation.test.ts src/tests/server-lifecycle.test.ts src/tests/session-keeper.test.ts src/tests/session-state.test.ts src/tests/single-account-mode.test.ts src/tests/stream-retry.test.ts src/tests/tool-calls-endpoint.test.ts src/tests/tool-instructions-cache.test.ts src/tests/session-id.test.ts src/tests/watchdog-ram.test.ts src/tests/tool-recovery-t1t2.test.ts src/tests/abort-silent-t4.test.ts src/tests/t3-close-tag-escape.test.ts src/tests/t5-tool-cap.test.ts src/tests/logger-redaction.test.ts src/tests/stall-timeout-retryable.test.ts src/tests/t6-missing-quote-array-close.test.ts src/tests/watchdog-rss.test.ts src/tests/logical-thread-batch.test.ts src/tests/chat-pool-style.test.ts src/tests/queue-wait-cap.test.ts src/tests/context-eviction-order.test.ts src/tests/chat-in-progress-settle.test.ts src/tests/stream-lock-leak.test.ts src/tests/stream-semaphore.test.ts src/tests/waf-isolation.test.ts src/tests/legacy-completions.test.ts src/tests/response-format.test.ts src/tests/cors-headers.test.ts src/tests/local-auth.test.ts src/tests/safe-remote-url.test.ts src/tests/stream-lock-terminal-cancel.test.ts src/tests/parser-truncated-tool-call.test.ts src/tests/metrics-prometheus.test.ts src/tests/context-death-cleanup.test.ts src/tests/personalization-direct-fetch.test.ts src/tests/completion-headers-parity.test.ts src/tests/parallel-escape-repro.test.ts src/tests/chat-in-progress-scale-cost.test.ts src/tests/temp-chat-mode.test.ts src/tests/profile-reset.test.ts src/tests/error-classification.test.ts src/tests/quota-cooldown.test.ts src/tests/account-ready-gate.test.ts src/tests/tool-cap-notice.test.ts src/tests/interaction-flows.test.ts src/tests/headers-gate-cooldown-fallback.test.ts src/tests/unwrapped-tool-calls.test.ts src/tests/anthropic.test.ts src/tests/sync-clients.test.ts src/tests/sync-top10-clients.test.ts src/tests/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts src/tests/tui-settings.test.ts src/tests/personalization-deadline.test.ts src/tests/update-cli.test.ts src/tests/batch-accounts.test.ts src/tests/shared-browser.test.ts src/tests/auth-credential-classification.test.ts src/tests/responses-api.test.ts src/tests/media-generation.test.ts src/tests/infer-tool-name.test.ts src/tests/native-session-headers.test.ts src/tests/omni-thinking.test.ts src/tests/protect-stuck-mutex.test.ts src/tests/stream-error-notice.test.ts src/tests/parser-deep-coverage.test.ts src/tests/tui-logs-copy.test.ts src/tests/auth-jwt-and-validation.test.ts src/tests/tui-port-and-key-modal.test.ts src/tests/verify-zero-fake-cooldown.test.ts src/tests/auth-session-refresh-preservation.test.ts src/tests/personalization-in-flight-dedup.test.ts src/tests/daily-usage.test.ts src/tests/resilience-enhancements.test.ts src/tests/pool-quota-failover.test.ts src/tests/process-guard-and-resilience.test.ts src/tests/otp-login.test.ts src/tests/overload-detector.test.ts",
|
|
33
|
+
"test:mock:fast": "tsx --test --test-concurrency=2 --env-file=.env.test src/tests/account-concurrency.test.ts src/tests/concurrency-latest-wins.test.ts src/tests/mutex.test.ts src/tests/context-truncation.test.ts src/tests/streaming-thinking-summary.test.ts src/tests/tool-call-guard.test.ts src/tests/utils-logger-full.test.ts src/tests/logger-toolcall-errors.test.ts src/tests/logger-toolcall-disabled.test.ts src/tests/utils-json-full.test.ts src/tests/utils-session-guard-full.test.ts src/tests/core-logic-full.test.ts src/tests/core-logic-accounts.test.ts src/tests/chat-validation-full.test.ts src/tests/chat-logic-full.test.ts src/tests/account-stickiness.test.ts src/tests/accounts-security.test.ts src/tests/advanced.test.ts src/tests/auth-playwright.test.ts src/tests/auth-session-persistence.test.ts src/tests/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.test.ts src/tests/chat-cleanup-auto.test.ts src/tests/chromium-args.test.ts src/tests/config-current.test.ts src/tests/context-meter.test.ts src/tests/concurrency.test.ts src/tests/delta.test.ts src/tests/fingerprint.test.ts src/tests/human-behavior.test.ts src/tests/index.test.ts src/tests/json-recovery.test.ts src/tests/jsonFix.test.ts src/tests/memory-cache.test.ts src/tests/model-alias.test.ts src/tests/model-registry-thinking.test.ts src/tests/models-endpoint.test.ts src/tests/multimodal.test.ts src/tests/oss-upload.test.ts src/tests/parser.test.ts src/tests/personalization-flow.test.ts src/tests/personalization-required.test.ts src/tests/retry-policy.test.ts src/tests/rotation.test.ts src/tests/server-lifecycle.test.ts src/tests/session-keeper.test.ts src/tests/session-state.test.ts src/tests/single-account-mode.test.ts src/tests/stream-retry.test.ts src/tests/tool-calls-endpoint.test.ts src/tests/tool-instructions-cache.test.ts src/tests/session-id.test.ts src/tests/watchdog-ram.test.ts src/tests/tool-recovery-t1t2.test.ts src/tests/abort-silent-t4.test.ts src/tests/t3-close-tag-escape.test.ts src/tests/t5-tool-cap.test.ts src/tests/logger-redaction.test.ts src/tests/stall-timeout-retryable.test.ts src/tests/t6-missing-quote-array-close.test.ts src/tests/watchdog-rss.test.ts src/tests/logical-thread-batch.test.ts src/tests/chat-pool-style.test.ts src/tests/queue-wait-cap.test.ts src/tests/context-eviction-order.test.ts src/tests/chat-in-progress-settle.test.ts src/tests/stream-lock-leak.test.ts src/tests/stream-semaphore.test.ts src/tests/waf-isolation.test.ts src/tests/legacy-completions.test.ts src/tests/response-format.test.ts src/tests/cors-headers.test.ts src/tests/local-auth.test.ts src/tests/safe-remote-url.test.ts src/tests/stream-lock-terminal-cancel.test.ts src/tests/parser-truncated-tool-call.test.ts src/tests/metrics-prometheus.test.ts src/tests/context-death-cleanup.test.ts src/tests/personalization-direct-fetch.test.ts src/tests/completion-headers-parity.test.ts src/tests/parallel-escape-repro.test.ts src/tests/chat-in-progress-scale-cost.test.ts src/tests/temp-chat-mode.test.ts src/tests/profile-reset.test.ts src/tests/error-classification.test.ts src/tests/quota-cooldown.test.ts src/tests/account-ready-gate.test.ts src/tests/tool-cap-notice.test.ts src/tests/interaction-flows.test.ts src/tests/headers-gate-cooldown-fallback.test.ts src/tests/unwrapped-tool-calls.test.ts src/tests/anthropic.test.ts src/tests/sync-clients.test.ts src/tests/sync-top10-clients.test.ts src/tests/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts src/tests/tui-settings.test.ts src/tests/personalization-deadline.test.ts src/tests/update-cli.test.ts src/tests/batch-accounts.test.ts src/tests/shared-browser.test.ts src/tests/auth-credential-classification.test.ts src/tests/responses-api.test.ts src/tests/media-generation.test.ts src/tests/infer-tool-name.test.ts src/tests/native-session-headers.test.ts src/tests/omni-thinking.test.ts src/tests/protect-stuck-mutex.test.ts src/tests/stream-error-notice.test.ts src/tests/parser-deep-coverage.test.ts src/tests/tui-logs-copy.test.ts src/tests/auth-jwt-and-validation.test.ts src/tests/tui-port-and-key-modal.test.ts src/tests/verify-zero-fake-cooldown.test.ts src/tests/auth-session-refresh-preservation.test.ts src/tests/personalization-in-flight-dedup.test.ts src/tests/daily-usage.test.ts src/tests/resilience-enhancements.test.ts src/tests/pool-quota-failover.test.ts src/tests/process-guard-and-resilience.test.ts src/tests/otp-login.test.ts src/tests/overload-detector.test.ts",
|
|
34
34
|
"test:live": "tsx --test src/tests/concurrentChat.test.ts src/tests/agenticStress.test.ts",
|
|
35
35
|
"test:stress": "npx tsx src/benchmarks/stress-test.ts",
|
|
36
36
|
"test:stress:personalization": "npx tsx src/benchmarks/stress-test-personalization.ts",
|
package/src/core/accounts.ts
CHANGED