qwenproxy-cli 1.5.3 → 1.6.1
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 +252 -26
- package/dist/delete-chats.js +206 -37
- package/dist/index.js +548 -74
- package/dist/login.js +144 -28
- package/dist/reset-cooldowns.js +252 -26
- package/dist/sync-clients.js +2 -2
- package/package.json +3 -3
- package/src/api/server.ts +1 -0
- package/src/clean-cache.ts +3 -0
- package/src/core/config.ts +2 -2
- package/src/core/daily-usage.ts +276 -0
- package/src/core/database.ts +27 -1
- package/src/core/process-guard.ts +77 -0
- package/src/core/version.ts +1 -1
- package/src/delete-chats.ts +3 -0
- package/src/index.ts +3 -29
- package/src/login.ts +2 -0
- package/src/routes/chat/account.ts +33 -5
- package/src/routes/chat/index.ts +1 -1
- package/src/routes/chat/retry-policy.ts +30 -0
- package/src/routes/chat/streaming.ts +72 -4
- package/src/services/captcha-coordinator.ts +12 -7
- package/src/services/chat-cleanup.ts +5 -0
- package/src/services/playwright.ts +82 -26
- package/src/services/qwen.ts +65 -9
- package/src/tui/proxy-client.ts +11 -1
- package/src/tui/types.ts +11 -0
- package/src/tui/views/accounts-view.ts +19 -2
- package/src/tui/views/status-view.ts +37 -4
package/dist/delete-chats.js
CHANGED
|
@@ -13,6 +13,44 @@ var __export = (target, all) => {
|
|
|
13
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
// src/core/process-guard.ts
|
|
17
|
+
function isPlaywrightAlreadyClosedMessage(message) {
|
|
18
|
+
if (!message) return false;
|
|
19
|
+
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");
|
|
20
|
+
}
|
|
21
|
+
function isBenignTeardownError(error) {
|
|
22
|
+
if (!error) return false;
|
|
23
|
+
const message = error instanceof Error ? error.message : typeof error === "object" && "message" in error ? String(error.message) : String(error);
|
|
24
|
+
return isPlaywrightAlreadyClosedMessage(message);
|
|
25
|
+
}
|
|
26
|
+
function installProcessTeardownGuards(label = "Process") {
|
|
27
|
+
if (guardsInstalled) return;
|
|
28
|
+
guardsInstalled = true;
|
|
29
|
+
process.on("uncaughtException", (error) => {
|
|
30
|
+
if (isBenignTeardownError(error)) {
|
|
31
|
+
const msg = error instanceof Error ? error.message : typeof error === "object" && error !== null && "message" in error ? String(error.message) : String(error);
|
|
32
|
+
console.warn(`\u26A0\uFE0F [${label}] Handled benign driver teardown exception: ${msg}`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
console.error(`\u274C [${label}] Uncaught Exception:`, error);
|
|
36
|
+
});
|
|
37
|
+
process.on("unhandledRejection", (reason) => {
|
|
38
|
+
if (isBenignTeardownError(reason)) {
|
|
39
|
+
const msg = reason instanceof Error ? reason.message : typeof reason === "object" && reason !== null && "message" in reason ? String(reason.message) : String(reason);
|
|
40
|
+
console.warn(`\u26A0\uFE0F [${label}] Handled benign driver teardown rejection: ${msg}`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
console.error(`\u274C [${label}] Unhandled Rejection:`, reason);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
var guardsInstalled;
|
|
47
|
+
var init_process_guard = __esm({
|
|
48
|
+
"src/core/process-guard.ts"() {
|
|
49
|
+
"use strict";
|
|
50
|
+
guardsInstalled = false;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
16
54
|
// src/core/paths.ts
|
|
17
55
|
import fs from "node:fs";
|
|
18
56
|
import path from "node:path";
|
|
@@ -296,7 +334,26 @@ function runMigrations(db2) {
|
|
|
296
334
|
instruction_hash TEXT NOT NULL,
|
|
297
335
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
298
336
|
);
|
|
337
|
+
|
|
338
|
+
CREATE TABLE IF NOT EXISTS account_daily_usage (
|
|
339
|
+
account_id TEXT NOT NULL,
|
|
340
|
+
date_utc TEXT NOT NULL,
|
|
341
|
+
prompt_tokens INTEGER NOT NULL DEFAULT 0,
|
|
342
|
+
completion_tokens INTEGER NOT NULL DEFAULT 0,
|
|
343
|
+
weighted_tokens REAL NOT NULL DEFAULT 0,
|
|
344
|
+
total_tokens INTEGER NOT NULL DEFAULT 0,
|
|
345
|
+
turns_count INTEGER NOT NULL DEFAULT 0,
|
|
346
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
347
|
+
PRIMARY KEY (account_id, date_utc)
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
CREATE INDEX IF NOT EXISTS idx_daily_usage_date ON account_daily_usage(date_utc);
|
|
299
351
|
`);
|
|
352
|
+
try {
|
|
353
|
+
db2.exec(`ALTER TABLE account_daily_usage ADD COLUMN weighted_tokens REAL DEFAULT 0;`);
|
|
354
|
+
} catch (err) {
|
|
355
|
+
if (!isDuplicateColumnError(err)) throw err;
|
|
356
|
+
}
|
|
300
357
|
try {
|
|
301
358
|
db2.exec(
|
|
302
359
|
`ALTER TABLE accounts ADD COLUMN cooldown_until INTEGER DEFAULT 0;`
|
|
@@ -397,7 +454,11 @@ function saveAuthSession(accountId, session) {
|
|
|
397
454
|
) VALUES (
|
|
398
455
|
?, ?, ?, ?, ?, ?,
|
|
399
456
|
?, ?, ?, ?,
|
|
400
|
-
?,
|
|
457
|
+
COALESCE(?, (SELECT user_id FROM qwen_auth_sessions WHERE account_id = ?)),
|
|
458
|
+
?,
|
|
459
|
+
COALESCE(?, (SELECT refresh_token FROM qwen_auth_sessions WHERE account_id = ?)),
|
|
460
|
+
?,
|
|
461
|
+
datetime('now')
|
|
401
462
|
)
|
|
402
463
|
`);
|
|
403
464
|
stmt.run(
|
|
@@ -412,8 +473,10 @@ function saveAuthSession(accountId, session) {
|
|
|
412
473
|
session.secChUaPlatform || null,
|
|
413
474
|
session.version || null,
|
|
414
475
|
session.userId || null,
|
|
476
|
+
accountId,
|
|
415
477
|
session.tokenExpiresAt || null,
|
|
416
478
|
session.refreshToken || null,
|
|
479
|
+
accountId,
|
|
417
480
|
session.capturedAt ?? Date.now()
|
|
418
481
|
);
|
|
419
482
|
}
|
|
@@ -1046,11 +1109,11 @@ var init_config = __esm({
|
|
|
1046
1109
|
// nothing in this window is dead and should fail fast, retryable).
|
|
1047
1110
|
QWEN_FIRST_CHUNK_TIMEOUT: z.string().default("60000"),
|
|
1048
1111
|
TOTAL_REQUEST_TIMEOUT: z.string().default("600000"),
|
|
1049
|
-
// Mid-stream silence window for thinking models:
|
|
1112
|
+
// Mid-stream silence window for thinking models: 5 min with ZERO upstream
|
|
1050
1113
|
// bytes is a dead stream (WAF swallow / dropped connection) — fail fast and
|
|
1051
1114
|
// let the retry policy rotate accounts. Flowing reasoning chunks RESET this
|
|
1052
1115
|
// timer, so legitimate slow thinking is never cut; only total silence is.
|
|
1053
|
-
REASONING_MODEL_TIMEOUT: z.string().default("
|
|
1116
|
+
REASONING_MODEL_TIMEOUT: z.string().default("300000"),
|
|
1054
1117
|
CACHE_TTL: z.string().default("3600"),
|
|
1055
1118
|
RESPONSE_TTL: z.string().default("1800"),
|
|
1056
1119
|
CACHE_COMPRESSION_ENABLED: z.string().default("true"),
|
|
@@ -3080,6 +3143,8 @@ var init_clean_cache = __esm({
|
|
|
3080
3143
|
"src/clean-cache.ts"() {
|
|
3081
3144
|
"use strict";
|
|
3082
3145
|
init_playwright();
|
|
3146
|
+
init_process_guard();
|
|
3147
|
+
installProcessTeardownGuards("CleanCache");
|
|
3083
3148
|
isDirectRun = process.argv[1] && (process.argv[1].endsWith("clean-cache.ts") || process.argv[1].endsWith("clean-cache.js"));
|
|
3084
3149
|
if (isDirectRun) {
|
|
3085
3150
|
main().catch((err) => {
|
|
@@ -3304,15 +3369,18 @@ function loadStorageState(accountId) {
|
|
|
3304
3369
|
return void 0;
|
|
3305
3370
|
}
|
|
3306
3371
|
}
|
|
3307
|
-
async function saveStorageState(context, accountId, timeoutMs =
|
|
3372
|
+
async function saveStorageState(context, accountId, timeoutMs = 1e4) {
|
|
3308
3373
|
try {
|
|
3309
3374
|
const stateFile = getStorageStatePath(accountId);
|
|
3310
3375
|
const dir = path5.dirname(stateFile);
|
|
3311
3376
|
if (!fs8.existsSync(dir)) {
|
|
3312
3377
|
fs8.mkdirSync(dir, { recursive: true });
|
|
3313
3378
|
}
|
|
3379
|
+
const rawPromise = context.storageState({ path: stateFile }).catch(() => {
|
|
3380
|
+
return void 0;
|
|
3381
|
+
});
|
|
3314
3382
|
await withTimeout(
|
|
3315
|
-
|
|
3383
|
+
rawPromise,
|
|
3316
3384
|
timeoutMs,
|
|
3317
3385
|
`storageState timed out after ${timeoutMs}ms`
|
|
3318
3386
|
);
|
|
@@ -4039,6 +4107,11 @@ async function getBasicHeaders(accountId) {
|
|
|
4039
4107
|
if (!page) {
|
|
4040
4108
|
throw new Error(`Playwright not initialized for account: ${accountId}`);
|
|
4041
4109
|
}
|
|
4110
|
+
const inFlightInit = inFlightAccountInits.get(accountId);
|
|
4111
|
+
if (inFlightInit) {
|
|
4112
|
+
await inFlightInit.catch(() => {
|
|
4113
|
+
});
|
|
4114
|
+
}
|
|
4042
4115
|
const release = await acquireAccountMutex(
|
|
4043
4116
|
accountId,
|
|
4044
4117
|
`headers:${accountId.substring(0, 12)}`
|
|
@@ -5513,6 +5586,11 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
|
|
|
5513
5586
|
const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
5514
5587
|
const { parseJwtExpiry: parseJwtExpiry2 } = await Promise.resolve().then(() => (init_jwt(), jwt_exports));
|
|
5515
5588
|
const tokenExpiry = parseJwtExpiry2(capturedHeaders.cookie);
|
|
5589
|
+
let rTok;
|
|
5590
|
+
try {
|
|
5591
|
+
rTok = (await page.evaluate(() => localStorage.getItem("refresh_token") || "")).trim() || void 0;
|
|
5592
|
+
} catch {
|
|
5593
|
+
}
|
|
5516
5594
|
saveAuthSession2(accountId, {
|
|
5517
5595
|
cookie: capturedHeaders.cookie,
|
|
5518
5596
|
userAgent: capturedHeaders["user-agent"],
|
|
@@ -5524,6 +5602,7 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
|
|
|
5524
5602
|
secChUaPlatform: capturedHeaders["sec-ch-ua-platform"],
|
|
5525
5603
|
version: capturedHeaders["version"],
|
|
5526
5604
|
tokenExpiresAt: tokenExpiry || void 0,
|
|
5605
|
+
refreshToken: rTok,
|
|
5527
5606
|
capturedAt: Date.now()
|
|
5528
5607
|
});
|
|
5529
5608
|
} catch {
|
|
@@ -5555,38 +5634,57 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
|
|
|
5555
5634
|
const isAuthUrl = currentUrl.includes("/auth") || currentUrl.includes("/login");
|
|
5556
5635
|
const isSuspectedGuest = isAuthUrl || attempt >= 2 && !await isPageLoggedIn(page, 5e3);
|
|
5557
5636
|
if (isSuspectedGuest) {
|
|
5558
|
-
const
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
`\u26A0\uFE0F [Playwright] Session expired or guest state detected during header capture for ${accountId}; re-authenticating...`
|
|
5637
|
+
const silentRefresh = await refreshAccountToken(accountId);
|
|
5638
|
+
if (silentRefresh.success) {
|
|
5639
|
+
console.log(
|
|
5640
|
+
`\u26A1 [Playwright] Token refreshed silently during header capture for ${accountId}`
|
|
5563
5641
|
);
|
|
5564
|
-
|
|
5565
|
-
const ok = await loginToQwen(accountId, creds.email, creds.password);
|
|
5566
|
-
if (ok) {
|
|
5642
|
+
if (isAuthUrl) {
|
|
5567
5643
|
await page.goto(qwenUrl("/"), {
|
|
5568
5644
|
waitUntil: "domcontentloaded",
|
|
5569
5645
|
timeout: Math.min(config.timeouts.navigation, timeoutMs)
|
|
5570
5646
|
});
|
|
5571
|
-
await sleep2(
|
|
5647
|
+
await sleep2(1500);
|
|
5648
|
+
}
|
|
5649
|
+
if (await isPageLoggedIn(page, 5e3)) {
|
|
5650
|
+
armOverallDeadline();
|
|
5572
5651
|
}
|
|
5573
|
-
|
|
5652
|
+
}
|
|
5653
|
+
const stillSuspected = !silentRefresh.success || !await isPageLoggedIn(page, 2e3);
|
|
5654
|
+
if (stillSuspected) {
|
|
5655
|
+
const { getAccountCredentials: getAccountCredentials2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
|
|
5656
|
+
const creds = getAccountCredentials2(accountId);
|
|
5657
|
+
if (creds && creds.email && creds.password) {
|
|
5658
|
+
console.warn(
|
|
5659
|
+
`\u26A0\uFE0F [Playwright] Session expired or guest state detected during header capture for ${accountId}; re-authenticating...`
|
|
5660
|
+
);
|
|
5661
|
+
armOverallDeadline();
|
|
5662
|
+
const ok = await loginToQwen(accountId, creds.email, creds.password);
|
|
5663
|
+
if (ok) {
|
|
5664
|
+
await page.goto(qwenUrl("/"), {
|
|
5665
|
+
waitUntil: "domcontentloaded",
|
|
5666
|
+
timeout: Math.min(config.timeouts.navigation, timeoutMs)
|
|
5667
|
+
});
|
|
5668
|
+
await sleep2(2e3);
|
|
5669
|
+
}
|
|
5670
|
+
if (!ok || !await isPageLoggedIn(page, 6e3)) {
|
|
5671
|
+
settle(
|
|
5672
|
+
new Error(
|
|
5673
|
+
`Header capture failed for ${accountId}: re-login after session expiry did not succeed`
|
|
5674
|
+
)
|
|
5675
|
+
);
|
|
5676
|
+
return;
|
|
5677
|
+
}
|
|
5678
|
+
armOverallDeadline();
|
|
5679
|
+
if (settled || page.isClosed()) return;
|
|
5680
|
+
} else {
|
|
5574
5681
|
settle(
|
|
5575
5682
|
new Error(
|
|
5576
|
-
`Header capture failed for ${accountId}: re-login
|
|
5683
|
+
`Header capture failed for ${accountId}: session expired and no credentials available for re-login (run 'qpx login')`
|
|
5577
5684
|
)
|
|
5578
5685
|
);
|
|
5579
5686
|
return;
|
|
5580
5687
|
}
|
|
5581
|
-
armOverallDeadline();
|
|
5582
|
-
if (settled || page.isClosed()) return;
|
|
5583
|
-
} else {
|
|
5584
|
-
settle(
|
|
5585
|
-
new Error(
|
|
5586
|
-
`Header capture failed for ${accountId}: session expired and no credentials available for re-login (run 'qpx login')`
|
|
5587
|
-
)
|
|
5588
|
-
);
|
|
5589
|
-
return;
|
|
5590
5688
|
}
|
|
5591
5689
|
}
|
|
5592
5690
|
if (settled || page.isClosed()) return;
|
|
@@ -5902,7 +6000,13 @@ async function refreshHeadersInternal(accountId, timeoutMs = config.timeouts.hea
|
|
|
5902
6000
|
`[Playwright] Navigation check failed during refresh for ${accountId}:`,
|
|
5903
6001
|
navErr.message
|
|
5904
6002
|
);
|
|
5905
|
-
await
|
|
6003
|
+
if (await isPageLoggedIn(page, 3e3)) {
|
|
6004
|
+
} else {
|
|
6005
|
+
const refreshed = await refreshAccountToken(accountId);
|
|
6006
|
+
if (!refreshed.success) {
|
|
6007
|
+
await executeReauth();
|
|
6008
|
+
}
|
|
6009
|
+
}
|
|
5906
6010
|
}
|
|
5907
6011
|
}
|
|
5908
6012
|
if (hasRequiredQwenHeaders(cache.headers)) {
|
|
@@ -5916,6 +6020,11 @@ async function refreshHeadersInternal(accountId, timeoutMs = config.timeouts.hea
|
|
|
5916
6020
|
const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
5917
6021
|
const tokenCookie = liveCookies.find((c) => c.name === "token");
|
|
5918
6022
|
const exp = tokenCookie ? parseJwtExpiry(tokenCookie.value) : void 0;
|
|
6023
|
+
let rTok;
|
|
6024
|
+
try {
|
|
6025
|
+
rTok = (await page.evaluate(() => localStorage.getItem("refresh_token") || "")).trim() || void 0;
|
|
6026
|
+
} catch {
|
|
6027
|
+
}
|
|
5919
6028
|
saveAuthSession2(accountId, {
|
|
5920
6029
|
cookie: cookieStr,
|
|
5921
6030
|
userAgent: cache.headers["user-agent"] || "",
|
|
@@ -5927,6 +6036,7 @@ async function refreshHeadersInternal(accountId, timeoutMs = config.timeouts.hea
|
|
|
5927
6036
|
secChUaPlatform: cache.headers["sec-ch-ua-platform"] || void 0,
|
|
5928
6037
|
version: cache.headers["version"] || void 0,
|
|
5929
6038
|
tokenExpiresAt: exp || void 0,
|
|
6039
|
+
refreshToken: rTok,
|
|
5930
6040
|
capturedAt: Date.now()
|
|
5931
6041
|
});
|
|
5932
6042
|
} catch {
|
|
@@ -6313,8 +6423,10 @@ async function keepAlivePlaywrightAccount(accountId) {
|
|
|
6313
6423
|
if (!page || page.isClosed()) return false;
|
|
6314
6424
|
const now = Date.now();
|
|
6315
6425
|
const currentUrl = page.url();
|
|
6426
|
+
const lastRefreshAttempt = lastProactiveTokenRefresh.get(accountId) ?? 0;
|
|
6316
6427
|
const cookie = await getCookies(accountId);
|
|
6317
|
-
if (cookie && isTokenExpiringSoon(cookie, 5)) {
|
|
6428
|
+
if (cookie && isTokenExpiringSoon(cookie, 5) && now - lastRefreshAttempt > 6e4) {
|
|
6429
|
+
lastProactiveTokenRefresh.set(accountId, now);
|
|
6318
6430
|
console.log(
|
|
6319
6431
|
`\u{1F493} [SessionKeeper] Account ${accountId} access token expiring soon (<5m); silently refreshing...`
|
|
6320
6432
|
);
|
|
@@ -6358,6 +6470,7 @@ function cleanupPlaywrightAccountState(accountId) {
|
|
|
6358
6470
|
cookieCaches.delete(accountId);
|
|
6359
6471
|
lastAccountActivity.delete(accountId);
|
|
6360
6472
|
lastKeepAliveNavigation.delete(accountId);
|
|
6473
|
+
lastProactiveTokenRefresh.delete(accountId);
|
|
6361
6474
|
clearFingerprintCache(accountId);
|
|
6362
6475
|
unmarkAccountHeadersReady(accountId);
|
|
6363
6476
|
}
|
|
@@ -6541,7 +6654,7 @@ async function getTokenDiagnostics(accountId) {
|
|
|
6541
6654
|
}
|
|
6542
6655
|
};
|
|
6543
6656
|
}
|
|
6544
|
-
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, 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;
|
|
6657
|
+
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;
|
|
6545
6658
|
var init_playwright = __esm({
|
|
6546
6659
|
"src/services/playwright.ts"() {
|
|
6547
6660
|
"use strict";
|
|
@@ -6577,6 +6690,7 @@ var init_playwright = __esm({
|
|
|
6577
6690
|
cookieCaches = /* @__PURE__ */ new Map();
|
|
6578
6691
|
lastAccountActivity = /* @__PURE__ */ new Map();
|
|
6579
6692
|
lastKeepAliveNavigation = /* @__PURE__ */ new Map();
|
|
6693
|
+
lastProactiveTokenRefresh = /* @__PURE__ */ new Map();
|
|
6580
6694
|
profileResetQueue = /* @__PURE__ */ new Map();
|
|
6581
6695
|
profileResetChain = Promise.resolve();
|
|
6582
6696
|
closingAllPlaywright = false;
|
|
@@ -7112,9 +7226,13 @@ var init_model_registry = __esm({
|
|
|
7112
7226
|
// src/services/captcha-coordinator.ts
|
|
7113
7227
|
var captcha_coordinator_exports = {};
|
|
7114
7228
|
__export(captcha_coordinator_exports, {
|
|
7229
|
+
isCaptchaRecoveryActive: () => isCaptchaRecoveryActive,
|
|
7115
7230
|
recoverBaxiaCaptcha: () => recoverBaxiaCaptcha,
|
|
7116
7231
|
solveChallengeOnPage: () => solveChallengeOnPage
|
|
7117
7232
|
});
|
|
7233
|
+
function isCaptchaRecoveryActive(accountId) {
|
|
7234
|
+
return activeCaptchaRecoveries.has(accountId);
|
|
7235
|
+
}
|
|
7118
7236
|
async function gotoBestEffort(page, url) {
|
|
7119
7237
|
await page.goto(url, {
|
|
7120
7238
|
waitUntil: "domcontentloaded",
|
|
@@ -7157,11 +7275,12 @@ async function recoverBaxiaCaptcha(accountId, label, options = {}) {
|
|
|
7157
7275
|
return false;
|
|
7158
7276
|
}
|
|
7159
7277
|
metrics.increment("captcha.challenges.detected", 1, { solver });
|
|
7160
|
-
const challengeUrl = options.challengeBody ? extractBaxiaChallengeUrl(options.challengeBody, config.qwen.baseUrl) : null;
|
|
7161
7278
|
const solverOperationTimeoutMs = Math.max(
|
|
7162
7279
|
15e3,
|
|
7163
7280
|
config.captcha.timeoutMs + config.captcha.maxAttempts * (3e3 + config.captcha.retryDelayMs + config.captcha.settleMs) + 2 * CHALLENGE_NAVIGATION_TIMEOUT_MS
|
|
7164
7281
|
);
|
|
7282
|
+
const challengeUrl = options.challengeBody ? extractBaxiaChallengeUrl(options.challengeBody, config.qwen.baseUrl) : null;
|
|
7283
|
+
activeCaptchaRecoveries.add(accountId);
|
|
7165
7284
|
try {
|
|
7166
7285
|
const solved = await withAccountPage(
|
|
7167
7286
|
accountId,
|
|
@@ -7194,9 +7313,11 @@ async function recoverBaxiaCaptcha(accountId, label, options = {}) {
|
|
|
7194
7313
|
detail
|
|
7195
7314
|
});
|
|
7196
7315
|
return false;
|
|
7316
|
+
} finally {
|
|
7317
|
+
activeCaptchaRecoveries.delete(accountId);
|
|
7197
7318
|
}
|
|
7198
7319
|
}
|
|
7199
|
-
var CHALLENGE_NAVIGATION_TIMEOUT_MS, CHALLENGE_PATH_MARKER, FAILED_RECOVERY_BACKOFF_MS, lastFailedRecoveryAt;
|
|
7320
|
+
var CHALLENGE_NAVIGATION_TIMEOUT_MS, CHALLENGE_PATH_MARKER, FAILED_RECOVERY_BACKOFF_MS, lastFailedRecoveryAt, activeCaptchaRecoveries;
|
|
7200
7321
|
var init_captcha_coordinator = __esm({
|
|
7201
7322
|
"src/services/captcha-coordinator.ts"() {
|
|
7202
7323
|
"use strict";
|
|
@@ -7209,6 +7330,7 @@ var init_captcha_coordinator = __esm({
|
|
|
7209
7330
|
CHALLENGE_PATH_MARKER = "_____tmd_____";
|
|
7210
7331
|
FAILED_RECOVERY_BACKOFF_MS = 3e4;
|
|
7211
7332
|
lastFailedRecoveryAt = /* @__PURE__ */ new Map();
|
|
7333
|
+
activeCaptchaRecoveries = /* @__PURE__ */ new Set();
|
|
7212
7334
|
}
|
|
7213
7335
|
});
|
|
7214
7336
|
|
|
@@ -7941,6 +8063,7 @@ __export(qwen_exports, {
|
|
|
7941
8063
|
fetchRemoteQwenChats: () => fetchRemoteQwenChats,
|
|
7942
8064
|
flushLogicalThreadState: () => flushLogicalThreadState,
|
|
7943
8065
|
getAnyCachedQwenModels: () => getAnyCachedQwenModels,
|
|
8066
|
+
getInFlightPersonalizationCount: () => getInFlightPersonalizationCount,
|
|
7944
8067
|
getLogicalThreadState: () => getLogicalThreadState,
|
|
7945
8068
|
getQwenErrorCode: () => getQwenErrorCode,
|
|
7946
8069
|
getSessionParent: () => getSessionParent,
|
|
@@ -8873,12 +8996,51 @@ async function createQwenBrowserResponse(accountId, url, method, headers, body,
|
|
|
8873
8996
|
captchaWatcher?.stop();
|
|
8874
8997
|
}
|
|
8875
8998
|
}
|
|
8999
|
+
function getInFlightPersonalizationCount() {
|
|
9000
|
+
return inFlightPersonalizationSyncs.size;
|
|
9001
|
+
}
|
|
8876
9002
|
async function syncQwenRequestPersonalization(instruction, accountId, metadata = {}) {
|
|
8877
|
-
if (isAuthMockEnabled()) {
|
|
8878
|
-
if (process.env.TEST_PERSONALIZATION_SYNC_FAIL === "true") return false;
|
|
8879
|
-
return true;
|
|
8880
|
-
}
|
|
8881
9003
|
const cacheKey = accountId || "global";
|
|
9004
|
+
const sent = textSize(instruction);
|
|
9005
|
+
const syncHash = sent.hash ? `${sent.hash}:${QWEN_SAFE_SETTINGS_HASH}` : null;
|
|
9006
|
+
const inFlightKey = `${cacheKey}:${syncHash || "empty"}`;
|
|
9007
|
+
const existingInFlight = inFlightPersonalizationSyncs.get(inFlightKey);
|
|
9008
|
+
if (existingInFlight) {
|
|
9009
|
+
logger.debug("[Qwen] Personalization sync already in flight, sharing promise", {
|
|
9010
|
+
accountId: cacheKey
|
|
9011
|
+
});
|
|
9012
|
+
return existingInFlight;
|
|
9013
|
+
}
|
|
9014
|
+
let syncPromise;
|
|
9015
|
+
syncPromise = (async () => {
|
|
9016
|
+
await Promise.resolve();
|
|
9017
|
+
try {
|
|
9018
|
+
if (isAuthMockEnabled()) {
|
|
9019
|
+
const delay = parseInt(process.env.TEST_PERSONALIZATION_DELAY_MS || "0", 10);
|
|
9020
|
+
if (delay > 0) {
|
|
9021
|
+
await sleep4(delay);
|
|
9022
|
+
}
|
|
9023
|
+
if (process.env.TEST_PERSONALIZATION_SYNC_FAIL === "true") return false;
|
|
9024
|
+
return true;
|
|
9025
|
+
}
|
|
9026
|
+
return await syncQwenRequestPersonalizationInternal(
|
|
9027
|
+
instruction,
|
|
9028
|
+
accountId,
|
|
9029
|
+
metadata,
|
|
9030
|
+
cacheKey,
|
|
9031
|
+
sent,
|
|
9032
|
+
syncHash
|
|
9033
|
+
);
|
|
9034
|
+
} finally {
|
|
9035
|
+
if (inFlightPersonalizationSyncs.get(inFlightKey) === syncPromise) {
|
|
9036
|
+
inFlightPersonalizationSyncs.delete(inFlightKey);
|
|
9037
|
+
}
|
|
9038
|
+
}
|
|
9039
|
+
})();
|
|
9040
|
+
inFlightPersonalizationSyncs.set(inFlightKey, syncPromise);
|
|
9041
|
+
return syncPromise;
|
|
9042
|
+
}
|
|
9043
|
+
async function syncQwenRequestPersonalizationInternal(instruction, accountId, metadata, cacheKey, sent, syncHash) {
|
|
8882
9044
|
let forceRefresh = false;
|
|
8883
9045
|
try {
|
|
8884
9046
|
const basic = await getBasicHeaders2(accountId);
|
|
@@ -8896,8 +9058,6 @@ async function syncQwenRequestPersonalization(instruction, accountId, metadata =
|
|
|
8896
9058
|
});
|
|
8897
9059
|
let currentSettings = null;
|
|
8898
9060
|
let payload = buildQwenSettingsUpdatePayload(currentSettings, instruction);
|
|
8899
|
-
const sent = textSize(instruction);
|
|
8900
|
-
const syncHash = sent.hash ? `${sent.hash}:${QWEN_SAFE_SETTINGS_HASH}` : null;
|
|
8901
9061
|
const bypassCache = metadata.forceSync === true;
|
|
8902
9062
|
const cachedHash = lastSyncedPersonalizationHashes.get(cacheKey);
|
|
8903
9063
|
if (!bypassCache && syncHash && cachedHash === syncHash) {
|
|
@@ -10242,7 +10402,7 @@ async function createQwenStreamInternal(prompt, enableThinking, modelId, forcedP
|
|
|
10242
10402
|
clearTimeout(timeoutId);
|
|
10243
10403
|
}
|
|
10244
10404
|
}
|
|
10245
|
-
var sleep4, BROWSER_STREAM_BINDING, BROWSER_ABORTERS_KEY, BROWSER_STREAM_FLUSH_BYTES, BROWSER_STREAM_FLUSH_MS, METADATA_TIMEOUT_PER_PAYLOAD_MB_MS, POST_CAPTCHA_METADATA_GRACE_MS, browserStreamStates, browserStreamBindingPages, browserStreamBindingContexts, MODEL_CACHE_TTL_MS, modelsCache, nativeToolsDisabled, disablingNativeToolsInProgress, lastSyncedPersonalizationHashes, directSettingsFetchConsecutiveFailures, DIRECT_SETTINGS_FETCH_BLOCK_THRESHOLD, directSettingsFetchBlocked, DIRECT_SETTINGS_FETCH_TIMEOUT_MS, activePersonalizationByAccount, accountStreamMutexes, QWEN_SAFE_SETTINGS_PATCH, QWEN_SAFE_SETTINGS_HASH, DISABLE_TOOLS_MAX_RETRIES, DISABLE_TOOLS_BACKOFF_MS, UPSTREAM_RESPONSE_PREVIEW_BYTES;
|
|
10405
|
+
var sleep4, BROWSER_STREAM_BINDING, BROWSER_ABORTERS_KEY, BROWSER_STREAM_FLUSH_BYTES, BROWSER_STREAM_FLUSH_MS, METADATA_TIMEOUT_PER_PAYLOAD_MB_MS, POST_CAPTCHA_METADATA_GRACE_MS, browserStreamStates, browserStreamBindingPages, browserStreamBindingContexts, MODEL_CACHE_TTL_MS, modelsCache, nativeToolsDisabled, disablingNativeToolsInProgress, lastSyncedPersonalizationHashes, directSettingsFetchConsecutiveFailures, DIRECT_SETTINGS_FETCH_BLOCK_THRESHOLD, directSettingsFetchBlocked, DIRECT_SETTINGS_FETCH_TIMEOUT_MS, activePersonalizationByAccount, accountStreamMutexes, QWEN_SAFE_SETTINGS_PATCH, QWEN_SAFE_SETTINGS_HASH, inFlightPersonalizationSyncs, DISABLE_TOOLS_MAX_RETRIES, DISABLE_TOOLS_BACKOFF_MS, UPSTREAM_RESPONSE_PREVIEW_BYTES;
|
|
10246
10406
|
var init_qwen = __esm({
|
|
10247
10407
|
"src/services/qwen.ts"() {
|
|
10248
10408
|
"use strict";
|
|
@@ -10329,6 +10489,7 @@ var init_qwen = __esm({
|
|
|
10329
10489
|
}
|
|
10330
10490
|
};
|
|
10331
10491
|
QWEN_SAFE_SETTINGS_HASH = crypto5.createHash("sha256").update(JSON.stringify(QWEN_SAFE_SETTINGS_PATCH)).digest("hex").slice(0, 12);
|
|
10492
|
+
inFlightPersonalizationSyncs = /* @__PURE__ */ new Map();
|
|
10332
10493
|
DISABLE_TOOLS_MAX_RETRIES = 3;
|
|
10333
10494
|
DISABLE_TOOLS_BACKOFF_MS = 2e3;
|
|
10334
10495
|
UPSTREAM_RESPONSE_PREVIEW_BYTES = 8 * 1024;
|
|
@@ -10336,6 +10497,7 @@ var init_qwen = __esm({
|
|
|
10336
10497
|
});
|
|
10337
10498
|
|
|
10338
10499
|
// src/delete-chats.ts
|
|
10500
|
+
init_process_guard();
|
|
10339
10501
|
import "dotenv/config";
|
|
10340
10502
|
|
|
10341
10503
|
// src/services/chat-cleanup.ts
|
|
@@ -10399,6 +10561,12 @@ async function deleteChatsForConfiguredAccounts(keepBrowserOpen = false) {
|
|
|
10399
10561
|
`\u274C [DeleteChats] [${currentIdx}/${totalCount}] Falha ao apagar conversas de ${maskEmail(account.email)}:`,
|
|
10400
10562
|
error instanceof Error ? error.message : String(error)
|
|
10401
10563
|
);
|
|
10564
|
+
} finally {
|
|
10565
|
+
if (!keepBrowserOpen) {
|
|
10566
|
+
const { closePlaywrightForAccount: closePlaywrightForAccount2 } = await Promise.resolve().then(() => (init_playwright(), playwright_exports));
|
|
10567
|
+
await closePlaywrightForAccount2(account.id).catch(() => {
|
|
10568
|
+
});
|
|
10569
|
+
}
|
|
10402
10570
|
}
|
|
10403
10571
|
}
|
|
10404
10572
|
} finally {
|
|
@@ -10419,6 +10587,7 @@ async function deleteChatsForConfiguredAccounts(keepBrowserOpen = false) {
|
|
|
10419
10587
|
}
|
|
10420
10588
|
|
|
10421
10589
|
// src/delete-chats.ts
|
|
10590
|
+
installProcessTeardownGuards("DeleteChats");
|
|
10422
10591
|
async function run() {
|
|
10423
10592
|
console.log("\u{1F5D1}\uFE0F [DeleteChats] Using Playwright sessions");
|
|
10424
10593
|
const result = await deleteChatsForConfiguredAccounts();
|