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