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/clean-cache.js
CHANGED
|
@@ -296,7 +296,26 @@ function runMigrations(db2) {
|
|
|
296
296
|
instruction_hash TEXT NOT NULL,
|
|
297
297
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
298
298
|
);
|
|
299
|
+
|
|
300
|
+
CREATE TABLE IF NOT EXISTS account_daily_usage (
|
|
301
|
+
account_id TEXT NOT NULL,
|
|
302
|
+
date_utc TEXT NOT NULL,
|
|
303
|
+
prompt_tokens INTEGER NOT NULL DEFAULT 0,
|
|
304
|
+
completion_tokens INTEGER NOT NULL DEFAULT 0,
|
|
305
|
+
weighted_tokens REAL NOT NULL DEFAULT 0,
|
|
306
|
+
total_tokens INTEGER NOT NULL DEFAULT 0,
|
|
307
|
+
turns_count INTEGER NOT NULL DEFAULT 0,
|
|
308
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
309
|
+
PRIMARY KEY (account_id, date_utc)
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
CREATE INDEX IF NOT EXISTS idx_daily_usage_date ON account_daily_usage(date_utc);
|
|
299
313
|
`);
|
|
314
|
+
try {
|
|
315
|
+
db2.exec(`ALTER TABLE account_daily_usage ADD COLUMN weighted_tokens REAL DEFAULT 0;`);
|
|
316
|
+
} catch (err) {
|
|
317
|
+
if (!isDuplicateColumnError(err)) throw err;
|
|
318
|
+
}
|
|
300
319
|
try {
|
|
301
320
|
db2.exec(
|
|
302
321
|
`ALTER TABLE accounts ADD COLUMN cooldown_until INTEGER DEFAULT 0;`
|
|
@@ -397,7 +416,11 @@ function saveAuthSession(accountId, session) {
|
|
|
397
416
|
) VALUES (
|
|
398
417
|
?, ?, ?, ?, ?, ?,
|
|
399
418
|
?, ?, ?, ?,
|
|
400
|
-
?,
|
|
419
|
+
COALESCE(?, (SELECT user_id FROM qwen_auth_sessions WHERE account_id = ?)),
|
|
420
|
+
?,
|
|
421
|
+
COALESCE(?, (SELECT refresh_token FROM qwen_auth_sessions WHERE account_id = ?)),
|
|
422
|
+
?,
|
|
423
|
+
datetime('now')
|
|
401
424
|
)
|
|
402
425
|
`);
|
|
403
426
|
stmt.run(
|
|
@@ -412,8 +435,10 @@ function saveAuthSession(accountId, session) {
|
|
|
412
435
|
session.secChUaPlatform || null,
|
|
413
436
|
session.version || null,
|
|
414
437
|
session.userId || null,
|
|
438
|
+
accountId,
|
|
415
439
|
session.tokenExpiresAt || null,
|
|
416
440
|
session.refreshToken || null,
|
|
441
|
+
accountId,
|
|
417
442
|
session.capturedAt ?? Date.now()
|
|
418
443
|
);
|
|
419
444
|
}
|
|
@@ -991,11 +1016,11 @@ var init_config = __esm({
|
|
|
991
1016
|
// nothing in this window is dead and should fail fast, retryable).
|
|
992
1017
|
QWEN_FIRST_CHUNK_TIMEOUT: z.string().default("60000"),
|
|
993
1018
|
TOTAL_REQUEST_TIMEOUT: z.string().default("600000"),
|
|
994
|
-
// Mid-stream silence window for thinking models:
|
|
1019
|
+
// Mid-stream silence window for thinking models: 5 min with ZERO upstream
|
|
995
1020
|
// bytes is a dead stream (WAF swallow / dropped connection) — fail fast and
|
|
996
1021
|
// let the retry policy rotate accounts. Flowing reasoning chunks RESET this
|
|
997
1022
|
// timer, so legitimate slow thinking is never cut; only total silence is.
|
|
998
|
-
REASONING_MODEL_TIMEOUT: z.string().default("
|
|
1023
|
+
REASONING_MODEL_TIMEOUT: z.string().default("300000"),
|
|
999
1024
|
CACHE_TTL: z.string().default("3600"),
|
|
1000
1025
|
RESPONSE_TTL: z.string().default("1800"),
|
|
1001
1026
|
CACHE_COMPRESSION_ENABLED: z.string().default("true"),
|
|
@@ -2823,15 +2848,18 @@ function loadStorageState(accountId) {
|
|
|
2823
2848
|
return void 0;
|
|
2824
2849
|
}
|
|
2825
2850
|
}
|
|
2826
|
-
async function saveStorageState(context, accountId, timeoutMs =
|
|
2851
|
+
async function saveStorageState(context, accountId, timeoutMs = 1e4) {
|
|
2827
2852
|
try {
|
|
2828
2853
|
const stateFile = getStorageStatePath(accountId);
|
|
2829
2854
|
const dir = path4.dirname(stateFile);
|
|
2830
2855
|
if (!fs7.existsSync(dir)) {
|
|
2831
2856
|
fs7.mkdirSync(dir, { recursive: true });
|
|
2832
2857
|
}
|
|
2858
|
+
const rawPromise = context.storageState({ path: stateFile }).catch(() => {
|
|
2859
|
+
return void 0;
|
|
2860
|
+
});
|
|
2833
2861
|
await withTimeout(
|
|
2834
|
-
|
|
2862
|
+
rawPromise,
|
|
2835
2863
|
timeoutMs,
|
|
2836
2864
|
`storageState timed out after ${timeoutMs}ms`
|
|
2837
2865
|
);
|
|
@@ -4306,6 +4334,137 @@ async function loginViaUi(page, email, password) {
|
|
|
4306
4334
|
return { success: false, reason: err?.message || String(err) };
|
|
4307
4335
|
}
|
|
4308
4336
|
}
|
|
4337
|
+
async function refreshAccountToken(accountId) {
|
|
4338
|
+
const page = accountPages.get(accountId);
|
|
4339
|
+
if (!page || page.isClosed()) {
|
|
4340
|
+
return { success: false, error: "Account page not active" };
|
|
4341
|
+
}
|
|
4342
|
+
const { getValidAuthSession: getValidAuthSession2, saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4343
|
+
const session = getValidAuthSession2(accountId);
|
|
4344
|
+
let refreshToken = session?.refreshToken;
|
|
4345
|
+
if (!refreshToken) {
|
|
4346
|
+
try {
|
|
4347
|
+
refreshToken = await page.evaluate(() => localStorage.getItem("refresh_token") || "") || void 0;
|
|
4348
|
+
} catch {
|
|
4349
|
+
}
|
|
4350
|
+
}
|
|
4351
|
+
if (refreshToken) {
|
|
4352
|
+
try {
|
|
4353
|
+
const refreshResult = await page.evaluate(
|
|
4354
|
+
async ({ rTok }) => {
|
|
4355
|
+
try {
|
|
4356
|
+
const response = await fetch("https://auth.qwen.ai/api/v2/auths/refresh", {
|
|
4357
|
+
method: "GET",
|
|
4358
|
+
credentials: "include",
|
|
4359
|
+
headers: {
|
|
4360
|
+
accept: "application/json, text/plain, */*",
|
|
4361
|
+
source: "web",
|
|
4362
|
+
version: "0.3.11",
|
|
4363
|
+
"x-request-origin": "https://chat.qwen.ai",
|
|
4364
|
+
timezone: (/* @__PURE__ */ new Date()).toString().split(" (")[0],
|
|
4365
|
+
authorization: `Bearer ${rTok}`
|
|
4366
|
+
}
|
|
4367
|
+
});
|
|
4368
|
+
const json2 = await response.json().catch(() => null);
|
|
4369
|
+
return { ok: response.ok, status: response.status, data: json2 };
|
|
4370
|
+
} catch (e) {
|
|
4371
|
+
return { ok: false, error: e.message };
|
|
4372
|
+
}
|
|
4373
|
+
},
|
|
4374
|
+
{ rTok: refreshToken }
|
|
4375
|
+
);
|
|
4376
|
+
const json = refreshResult?.data;
|
|
4377
|
+
if (json && json.success === true && json.data) {
|
|
4378
|
+
const newAccessToken = json.data.access_token || json.data.token;
|
|
4379
|
+
const newRefreshToken = json.data.refresh_token || refreshToken;
|
|
4380
|
+
if (newAccessToken) {
|
|
4381
|
+
await page.context().addCookies([
|
|
4382
|
+
{
|
|
4383
|
+
name: "token",
|
|
4384
|
+
value: newAccessToken,
|
|
4385
|
+
domain: ".qwen.ai",
|
|
4386
|
+
path: "/",
|
|
4387
|
+
expires: Math.floor(Date.now() / 1e3) + 31536e3,
|
|
4388
|
+
httpOnly: false,
|
|
4389
|
+
secure: true,
|
|
4390
|
+
sameSite: "Lax"
|
|
4391
|
+
}
|
|
4392
|
+
]);
|
|
4393
|
+
await page.evaluate(
|
|
4394
|
+
({ tok, rTok }) => {
|
|
4395
|
+
try {
|
|
4396
|
+
localStorage.removeItem("qwen_token_logged_out_marker");
|
|
4397
|
+
localStorage.setItem("token", tok);
|
|
4398
|
+
localStorage.setItem("access_token", tok);
|
|
4399
|
+
if (rTok) localStorage.setItem("refresh_token", rTok);
|
|
4400
|
+
document.cookie = `token=${encodeURIComponent(tok)}; path=/; domain=.qwen.ai; max-age=31536000`;
|
|
4401
|
+
} catch {
|
|
4402
|
+
}
|
|
4403
|
+
},
|
|
4404
|
+
{ tok: newAccessToken, rTok: newRefreshToken }
|
|
4405
|
+
).catch(() => {
|
|
4406
|
+
});
|
|
4407
|
+
const liveCookies = await page.context().cookies();
|
|
4408
|
+
const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
|
|
4409
|
+
const cache = getHeaderCache(accountId);
|
|
4410
|
+
cache.headers.cookie = cookieStr;
|
|
4411
|
+
cache.lastRefresh = Date.now();
|
|
4412
|
+
markAccountHeadersReady(accountId);
|
|
4413
|
+
saveAuthSession2(accountId, {
|
|
4414
|
+
cookie: cookieStr,
|
|
4415
|
+
userAgent: cache.headers["user-agent"] || session?.userAgent || "",
|
|
4416
|
+
bxV: cache.headers["bx-v"] || session?.bxV || "2.5.37",
|
|
4417
|
+
bxUa: cache.headers["bx-ua"] || session?.bxUa || "",
|
|
4418
|
+
bxUmidtoken: cache.headers["bx-umidtoken"] || session?.bxUmidtoken || "",
|
|
4419
|
+
secChUa: cache.headers["sec-ch-ua"] || session?.secChUa,
|
|
4420
|
+
secChUaMobile: cache.headers["sec-ch-ua-mobile"] || session?.secChUaMobile,
|
|
4421
|
+
secChUaPlatform: cache.headers["sec-ch-ua-platform"] || session?.secChUaPlatform,
|
|
4422
|
+
version: cache.headers["version"] || session?.version,
|
|
4423
|
+
userId: session?.userId,
|
|
4424
|
+
tokenExpiresAt: parseJwtExpiry(newAccessToken) || void 0,
|
|
4425
|
+
refreshToken: newRefreshToken,
|
|
4426
|
+
capturedAt: Date.now()
|
|
4427
|
+
});
|
|
4428
|
+
return { success: true, token: newAccessToken };
|
|
4429
|
+
}
|
|
4430
|
+
}
|
|
4431
|
+
} catch {
|
|
4432
|
+
}
|
|
4433
|
+
}
|
|
4434
|
+
const { getAccountCredentials: getAccountCredentials2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
|
|
4435
|
+
const creds = getAccountCredentials2(accountId);
|
|
4436
|
+
if (creds && creds.email && creds.password) {
|
|
4437
|
+
const apiResult = await loginViaApi(page, creds.email, creds.password);
|
|
4438
|
+
if (apiResult.success) {
|
|
4439
|
+
const liveCookies = await page.context().cookies();
|
|
4440
|
+
const tokenCookie = liveCookies.find((c) => c.name === "token");
|
|
4441
|
+
if (tokenCookie) {
|
|
4442
|
+
const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
|
|
4443
|
+
const cache = getHeaderCache(accountId);
|
|
4444
|
+
cache.headers.cookie = cookieStr;
|
|
4445
|
+
cache.lastRefresh = Date.now();
|
|
4446
|
+
markAccountHeadersReady(accountId);
|
|
4447
|
+
saveAuthSession2(accountId, {
|
|
4448
|
+
cookie: cookieStr,
|
|
4449
|
+
userAgent: cache.headers["user-agent"] || session?.userAgent || "",
|
|
4450
|
+
bxV: cache.headers["bx-v"] || session?.bxV || "2.5.37",
|
|
4451
|
+
bxUa: cache.headers["bx-ua"] || session?.bxUa || "",
|
|
4452
|
+
bxUmidtoken: cache.headers["bx-umidtoken"] || session?.bxUmidtoken || "",
|
|
4453
|
+
secChUa: cache.headers["sec-ch-ua"] || session?.secChUa,
|
|
4454
|
+
secChUaMobile: cache.headers["sec-ch-ua-mobile"] || session?.secChUaMobile,
|
|
4455
|
+
secChUaPlatform: cache.headers["sec-ch-ua-platform"] || session?.secChUaPlatform,
|
|
4456
|
+
version: cache.headers["version"] || session?.version,
|
|
4457
|
+
userId: session?.userId,
|
|
4458
|
+
tokenExpiresAt: parseJwtExpiry(tokenCookie.value) || void 0,
|
|
4459
|
+
refreshToken: apiResult.refreshToken,
|
|
4460
|
+
capturedAt: Date.now()
|
|
4461
|
+
});
|
|
4462
|
+
return { success: true, token: tokenCookie.value };
|
|
4463
|
+
}
|
|
4464
|
+
}
|
|
4465
|
+
}
|
|
4466
|
+
return { success: false, error: "Could not refresh or re-authenticate token" };
|
|
4467
|
+
}
|
|
4309
4468
|
async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.timeouts.headers, triggerGraceMs = HEADER_CAPTURE_TRIGGER_GRACE_MS) {
|
|
4310
4469
|
const page = pageOverride ?? accountPages.get(accountId);
|
|
4311
4470
|
if (!page || page.isClosed()) {
|
|
@@ -4459,6 +4618,11 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
|
|
|
4459
4618
|
const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4460
4619
|
const { parseJwtExpiry: parseJwtExpiry2 } = await Promise.resolve().then(() => (init_jwt(), jwt_exports));
|
|
4461
4620
|
const tokenExpiry = parseJwtExpiry2(capturedHeaders.cookie);
|
|
4621
|
+
let rTok;
|
|
4622
|
+
try {
|
|
4623
|
+
rTok = (await page.evaluate(() => localStorage.getItem("refresh_token") || "")).trim() || void 0;
|
|
4624
|
+
} catch {
|
|
4625
|
+
}
|
|
4462
4626
|
saveAuthSession2(accountId, {
|
|
4463
4627
|
cookie: capturedHeaders.cookie,
|
|
4464
4628
|
userAgent: capturedHeaders["user-agent"],
|
|
@@ -4470,6 +4634,7 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
|
|
|
4470
4634
|
secChUaPlatform: capturedHeaders["sec-ch-ua-platform"],
|
|
4471
4635
|
version: capturedHeaders["version"],
|
|
4472
4636
|
tokenExpiresAt: tokenExpiry || void 0,
|
|
4637
|
+
refreshToken: rTok,
|
|
4473
4638
|
capturedAt: Date.now()
|
|
4474
4639
|
});
|
|
4475
4640
|
} catch {
|
|
@@ -4501,38 +4666,57 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
|
|
|
4501
4666
|
const isAuthUrl = currentUrl.includes("/auth") || currentUrl.includes("/login");
|
|
4502
4667
|
const isSuspectedGuest = isAuthUrl || attempt >= 2 && !await isPageLoggedIn(page, 5e3);
|
|
4503
4668
|
if (isSuspectedGuest) {
|
|
4504
|
-
const
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
`\u26A0\uFE0F [Playwright] Session expired or guest state detected during header capture for ${accountId}; re-authenticating...`
|
|
4669
|
+
const silentRefresh = await refreshAccountToken(accountId);
|
|
4670
|
+
if (silentRefresh.success) {
|
|
4671
|
+
console.log(
|
|
4672
|
+
`\u26A1 [Playwright] Token refreshed silently during header capture for ${accountId}`
|
|
4509
4673
|
);
|
|
4510
|
-
|
|
4511
|
-
const ok = await loginToQwen(accountId, creds.email, creds.password);
|
|
4512
|
-
if (ok) {
|
|
4674
|
+
if (isAuthUrl) {
|
|
4513
4675
|
await page.goto(qwenUrl("/"), {
|
|
4514
4676
|
waitUntil: "domcontentloaded",
|
|
4515
4677
|
timeout: Math.min(config.timeouts.navigation, timeoutMs)
|
|
4516
4678
|
});
|
|
4517
|
-
await sleep2(
|
|
4679
|
+
await sleep2(1500);
|
|
4680
|
+
}
|
|
4681
|
+
if (await isPageLoggedIn(page, 5e3)) {
|
|
4682
|
+
armOverallDeadline();
|
|
4518
4683
|
}
|
|
4519
|
-
|
|
4684
|
+
}
|
|
4685
|
+
const stillSuspected = !silentRefresh.success || !await isPageLoggedIn(page, 2e3);
|
|
4686
|
+
if (stillSuspected) {
|
|
4687
|
+
const { getAccountCredentials: getAccountCredentials2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
|
|
4688
|
+
const creds = getAccountCredentials2(accountId);
|
|
4689
|
+
if (creds && creds.email && creds.password) {
|
|
4690
|
+
console.warn(
|
|
4691
|
+
`\u26A0\uFE0F [Playwright] Session expired or guest state detected during header capture for ${accountId}; re-authenticating...`
|
|
4692
|
+
);
|
|
4693
|
+
armOverallDeadline();
|
|
4694
|
+
const ok = await loginToQwen(accountId, creds.email, creds.password);
|
|
4695
|
+
if (ok) {
|
|
4696
|
+
await page.goto(qwenUrl("/"), {
|
|
4697
|
+
waitUntil: "domcontentloaded",
|
|
4698
|
+
timeout: Math.min(config.timeouts.navigation, timeoutMs)
|
|
4699
|
+
});
|
|
4700
|
+
await sleep2(2e3);
|
|
4701
|
+
}
|
|
4702
|
+
if (!ok || !await isPageLoggedIn(page, 6e3)) {
|
|
4703
|
+
settle(
|
|
4704
|
+
new Error(
|
|
4705
|
+
`Header capture failed for ${accountId}: re-login after session expiry did not succeed`
|
|
4706
|
+
)
|
|
4707
|
+
);
|
|
4708
|
+
return;
|
|
4709
|
+
}
|
|
4710
|
+
armOverallDeadline();
|
|
4711
|
+
if (settled || page.isClosed()) return;
|
|
4712
|
+
} else {
|
|
4520
4713
|
settle(
|
|
4521
4714
|
new Error(
|
|
4522
|
-
`Header capture failed for ${accountId}: re-login
|
|
4715
|
+
`Header capture failed for ${accountId}: session expired and no credentials available for re-login (run 'qpx login')`
|
|
4523
4716
|
)
|
|
4524
4717
|
);
|
|
4525
4718
|
return;
|
|
4526
4719
|
}
|
|
4527
|
-
armOverallDeadline();
|
|
4528
|
-
if (settled || page.isClosed()) return;
|
|
4529
|
-
} else {
|
|
4530
|
-
settle(
|
|
4531
|
-
new Error(
|
|
4532
|
-
`Header capture failed for ${accountId}: session expired and no credentials available for re-login (run 'qpx login')`
|
|
4533
|
-
)
|
|
4534
|
-
);
|
|
4535
|
-
return;
|
|
4536
4720
|
}
|
|
4537
4721
|
}
|
|
4538
4722
|
if (settled || page.isClosed()) return;
|
|
@@ -5022,6 +5206,7 @@ function cleanupPlaywrightAccountState(accountId) {
|
|
|
5022
5206
|
cookieCaches.delete(accountId);
|
|
5023
5207
|
lastAccountActivity.delete(accountId);
|
|
5024
5208
|
lastKeepAliveNavigation.delete(accountId);
|
|
5209
|
+
lastProactiveTokenRefresh.delete(accountId);
|
|
5025
5210
|
clearFingerprintCache(accountId);
|
|
5026
5211
|
unmarkAccountHeadersReady(accountId);
|
|
5027
5212
|
}
|
|
@@ -5096,7 +5281,7 @@ async function closePlaywrightForAccount(accountId) {
|
|
|
5096
5281
|
release();
|
|
5097
5282
|
}
|
|
5098
5283
|
}
|
|
5099
|
-
var requireLocal, contextInitHooks, ACCOUNT_MUTEX_MAX_HOLD_MS, accountMutexes, accountContexts, accountPages, inFlightAccountInits, headerCaches, HEADER_CACHE_TTL, 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;
|
|
5284
|
+
var requireLocal, contextInitHooks, ACCOUNT_MUTEX_MAX_HOLD_MS, accountMutexes, accountContexts, accountPages, inFlightAccountInits, headerCaches, HEADER_CACHE_TTL, 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;
|
|
5100
5285
|
var init_playwright = __esm({
|
|
5101
5286
|
"src/services/playwright.ts"() {
|
|
5102
5287
|
"use strict";
|
|
@@ -5128,6 +5313,7 @@ var init_playwright = __esm({
|
|
|
5128
5313
|
cookieCaches = /* @__PURE__ */ new Map();
|
|
5129
5314
|
lastAccountActivity = /* @__PURE__ */ new Map();
|
|
5130
5315
|
lastKeepAliveNavigation = /* @__PURE__ */ new Map();
|
|
5316
|
+
lastProactiveTokenRefresh = /* @__PURE__ */ new Map();
|
|
5131
5317
|
profileResetQueue = /* @__PURE__ */ new Map();
|
|
5132
5318
|
profileResetChain = Promise.resolve();
|
|
5133
5319
|
closingAllPlaywright = false;
|
|
@@ -5153,6 +5339,44 @@ var init_playwright = __esm({
|
|
|
5153
5339
|
}
|
|
5154
5340
|
});
|
|
5155
5341
|
|
|
5342
|
+
// src/core/process-guard.ts
|
|
5343
|
+
function isPlaywrightAlreadyClosedMessage(message) {
|
|
5344
|
+
if (!message) return false;
|
|
5345
|
+
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");
|
|
5346
|
+
}
|
|
5347
|
+
function isBenignTeardownError(error) {
|
|
5348
|
+
if (!error) return false;
|
|
5349
|
+
const message = error instanceof Error ? error.message : typeof error === "object" && "message" in error ? String(error.message) : String(error);
|
|
5350
|
+
return isPlaywrightAlreadyClosedMessage(message);
|
|
5351
|
+
}
|
|
5352
|
+
function installProcessTeardownGuards(label = "Process") {
|
|
5353
|
+
if (guardsInstalled) return;
|
|
5354
|
+
guardsInstalled = true;
|
|
5355
|
+
process.on("uncaughtException", (error) => {
|
|
5356
|
+
if (isBenignTeardownError(error)) {
|
|
5357
|
+
const msg = error instanceof Error ? error.message : typeof error === "object" && error !== null && "message" in error ? String(error.message) : String(error);
|
|
5358
|
+
console.warn(`\u26A0\uFE0F [${label}] Handled benign driver teardown exception: ${msg}`);
|
|
5359
|
+
return;
|
|
5360
|
+
}
|
|
5361
|
+
console.error(`\u274C [${label}] Uncaught Exception:`, error);
|
|
5362
|
+
});
|
|
5363
|
+
process.on("unhandledRejection", (reason) => {
|
|
5364
|
+
if (isBenignTeardownError(reason)) {
|
|
5365
|
+
const msg = reason instanceof Error ? reason.message : typeof reason === "object" && reason !== null && "message" in reason ? String(reason.message) : String(reason);
|
|
5366
|
+
console.warn(`\u26A0\uFE0F [${label}] Handled benign driver teardown rejection: ${msg}`);
|
|
5367
|
+
return;
|
|
5368
|
+
}
|
|
5369
|
+
console.error(`\u274C [${label}] Unhandled Rejection:`, reason);
|
|
5370
|
+
});
|
|
5371
|
+
}
|
|
5372
|
+
var guardsInstalled;
|
|
5373
|
+
var init_process_guard = __esm({
|
|
5374
|
+
"src/core/process-guard.ts"() {
|
|
5375
|
+
"use strict";
|
|
5376
|
+
guardsInstalled = false;
|
|
5377
|
+
}
|
|
5378
|
+
});
|
|
5379
|
+
|
|
5156
5380
|
// src/clean-cache.ts
|
|
5157
5381
|
var clean_cache_exports = {};
|
|
5158
5382
|
__export(clean_cache_exports, {
|
|
@@ -5320,6 +5544,8 @@ var isDirectRun;
|
|
|
5320
5544
|
var init_clean_cache = __esm({
|
|
5321
5545
|
"src/clean-cache.ts"() {
|
|
5322
5546
|
init_playwright();
|
|
5547
|
+
init_process_guard();
|
|
5548
|
+
installProcessTeardownGuards("CleanCache");
|
|
5323
5549
|
isDirectRun = process.argv[1] && (process.argv[1].endsWith("clean-cache.ts") || process.argv[1].endsWith("clean-cache.js"));
|
|
5324
5550
|
if (isDirectRun) {
|
|
5325
5551
|
main().catch((err) => {
|