qwenproxy-cli 1.4.0 → 1.4.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/README.pt-BR.md +7 -5
- package/dist/clean-cache.js +167 -68
- package/dist/delete-chats.js +212 -88
- package/dist/index.js +392 -267
- package/dist/login.js +172 -73
- package/dist/reset-cooldowns.js +167 -68
- package/dist/sync-clients.js +136 -126
- package/package.json +8 -6
- package/src/core/config.ts +13 -0
- package/src/core/version.ts +1 -1
- package/src/routes/chat/index.ts +1 -0
- package/src/services/playwright.ts +137 -43
- package/src/services/qwen.ts +47 -19
package/README.pt-BR.md
CHANGED
|
@@ -980,11 +980,13 @@ QwenProxy/
|
|
|
980
980
|
A pasta `scripts/` contém atalhos para instalar, iniciar e atualizar o projeto sem digitar os comandos manualmente.
|
|
981
981
|
|
|
982
982
|
|
|
983
|
-
| Script
|
|
984
|
-
|
|
|
985
|
-
| Instalador
|
|
986
|
-
| Iniciador
|
|
987
|
-
| Atualizador
|
|
983
|
+
| Script | Windows | Linux/macOS | O que faz |
|
|
984
|
+
| -------------- | --------------------- | ---------------------- | -------------------------------------------------------------------------------------------- |
|
|
985
|
+
| Instalador | `scripts\install.bat` | `./scripts/install.sh` | Verifica Node 22+, roda `npm install`, cria `.env` a partir de `.env.example` se não existir |
|
|
986
|
+
| Iniciador | `scripts\start.bat` | `./scripts/start.sh` | Verifica dependências e `.env`, inicia o servidor com `npm start` |
|
|
987
|
+
| Atualizador | `scripts\update.bat` | `./scripts/update.sh` | `git pull` (se for repositório), `npm install` e `npx playwright install chromium` |
|
|
988
|
+
| Login | `scripts\login.bat` | `./scripts/login.sh` | Abre navegador visual para autenticar contas no Qwen Web |
|
|
989
|
+
| Sincronizador | `scripts\sync.bat` | `./scripts/sync.sh` | Sincroniza e configura automaticamente clientes de IA (Claude Code, Codex, Cursor, etc.) |
|
|
988
990
|
|
|
989
991
|
|
|
990
992
|
No Linux/macOS, dê permissão de execução na primeira vez:
|
package/dist/clean-cache.js
CHANGED
|
@@ -880,6 +880,8 @@ var init_accounts = __esm({
|
|
|
880
880
|
});
|
|
881
881
|
|
|
882
882
|
// src/core/config.ts
|
|
883
|
+
import fs6 from "node:fs";
|
|
884
|
+
import dotenv from "dotenv";
|
|
883
885
|
import { z } from "zod";
|
|
884
886
|
function normalizeChatMode(mode) {
|
|
885
887
|
if (!mode) return "thread";
|
|
@@ -899,6 +901,15 @@ var envSchema, env, config;
|
|
|
899
901
|
var init_config = __esm({
|
|
900
902
|
"src/core/config.ts"() {
|
|
901
903
|
"use strict";
|
|
904
|
+
init_paths();
|
|
905
|
+
if (!isRunningUnderNodeTest()) {
|
|
906
|
+
const envPath = getEnvFilePath();
|
|
907
|
+
if (fs6.existsSync(envPath)) {
|
|
908
|
+
dotenv.config({ path: envPath, quiet: true });
|
|
909
|
+
} else {
|
|
910
|
+
dotenv.config({ quiet: true });
|
|
911
|
+
}
|
|
912
|
+
}
|
|
902
913
|
envSchema = z.object({
|
|
903
914
|
PORT: z.string().regex(/^\d+$/, "PORT must be a number").refine((value) => {
|
|
904
915
|
const port = Number(value);
|
|
@@ -2626,7 +2637,7 @@ var init_jwt = __esm({
|
|
|
2626
2637
|
// src/services/playwright.ts
|
|
2627
2638
|
import { chromium } from "patchright";
|
|
2628
2639
|
import path4 from "path";
|
|
2629
|
-
import
|
|
2640
|
+
import fs7 from "fs";
|
|
2630
2641
|
import crypto3 from "crypto";
|
|
2631
2642
|
import { spawnSync } from "child_process";
|
|
2632
2643
|
import { createRequire } from "module";
|
|
@@ -2640,7 +2651,7 @@ function autoInstallPlaywrightChromium() {
|
|
|
2640
2651
|
try {
|
|
2641
2652
|
const patchrightEntry = requireLocal.resolve("patchright");
|
|
2642
2653
|
const cliPath = path4.join(path4.dirname(patchrightEntry), "cli.js");
|
|
2643
|
-
if (
|
|
2654
|
+
if (fs7.existsSync(cliPath)) {
|
|
2644
2655
|
console.log("\u23F3 [Playwright] Navegador Chromium n\xE3o encontrado. Instalando automaticamente...");
|
|
2645
2656
|
const res2 = spawnSync(process.execPath, [cliPath, "install", "chromium"], {
|
|
2646
2657
|
stdio: "inherit",
|
|
@@ -2770,10 +2781,10 @@ function getStorageStatePath(accountId) {
|
|
|
2770
2781
|
function loadStorageState(accountId) {
|
|
2771
2782
|
const p1 = getStorageStatePath(accountId);
|
|
2772
2783
|
const p2 = path4.join(path4.dirname(p1), `${accountId}_state.json`);
|
|
2773
|
-
const chosenPath =
|
|
2784
|
+
const chosenPath = fs7.existsSync(p1) ? p1 : fs7.existsSync(p2) ? p2 : void 0;
|
|
2774
2785
|
if (!chosenPath) return void 0;
|
|
2775
2786
|
try {
|
|
2776
|
-
const raw =
|
|
2787
|
+
const raw = fs7.readFileSync(chosenPath, "utf8");
|
|
2777
2788
|
const state = JSON.parse(raw);
|
|
2778
2789
|
if (!state || typeof state !== "object" || !Array.isArray(state.cookies)) {
|
|
2779
2790
|
return void 0;
|
|
@@ -2787,8 +2798,8 @@ async function saveStorageState(context, accountId, timeoutMs = 5e3) {
|
|
|
2787
2798
|
try {
|
|
2788
2799
|
const stateFile = getStorageStatePath(accountId);
|
|
2789
2800
|
const dir = path4.dirname(stateFile);
|
|
2790
|
-
if (!
|
|
2791
|
-
|
|
2801
|
+
if (!fs7.existsSync(dir)) {
|
|
2802
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
2792
2803
|
}
|
|
2793
2804
|
await withTimeout(
|
|
2794
2805
|
context.storageState({ path: stateFile }),
|
|
@@ -2898,13 +2909,40 @@ async function isPageLoggedIn(page, timeoutMs = SESSION_PROBE_NAVIGATION_TIMEOUT
|
|
|
2898
2909
|
}
|
|
2899
2910
|
}
|
|
2900
2911
|
async function clearVisibleChallenge(page) {
|
|
2901
|
-
if (
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2912
|
+
if (page.isClosed()) return;
|
|
2913
|
+
if (config.captcha.enabled) {
|
|
2914
|
+
await solveBaxiaCaptcha(page, {
|
|
2915
|
+
waitForMs: 0,
|
|
2916
|
+
maxAttempts: config.captcha.maxAttempts,
|
|
2917
|
+
retryDelayMs: config.captcha.retryDelayMs,
|
|
2918
|
+
settleMs: config.captcha.settleMs
|
|
2919
|
+
}).catch(() => false);
|
|
2920
|
+
}
|
|
2921
|
+
try {
|
|
2922
|
+
const modalCloseSelectors = [
|
|
2923
|
+
".ant-modal-close",
|
|
2924
|
+
".ant-modal-close-x",
|
|
2925
|
+
"button.ant-modal-close",
|
|
2926
|
+
"button[aria-label*='Close' i]",
|
|
2927
|
+
"button[aria-label*='Fechar' i]",
|
|
2928
|
+
".index-module__whats-new-modal-close",
|
|
2929
|
+
"button:has-text('Cancel')",
|
|
2930
|
+
"button:has-text('Cancelar')",
|
|
2931
|
+
"button:has-text('I understand')",
|
|
2932
|
+
"button:has-text('Entendi')",
|
|
2933
|
+
"button:has-text('OK')"
|
|
2934
|
+
];
|
|
2935
|
+
for (const sel of modalCloseSelectors) {
|
|
2936
|
+
if (page.isClosed()) return;
|
|
2937
|
+
const btn = page.locator(sel).first();
|
|
2938
|
+
if (await btn.isVisible({ timeout: 150 }).catch(() => false)) {
|
|
2939
|
+
await btn.click({ timeout: 500 }).catch(() => {
|
|
2940
|
+
});
|
|
2941
|
+
await sleep2(200);
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
} catch {
|
|
2945
|
+
}
|
|
2908
2946
|
}
|
|
2909
2947
|
function getErrorMessage(error) {
|
|
2910
2948
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -3332,6 +3370,21 @@ function getStealthScript(profile) {
|
|
|
3332
3370
|
spoofedFunctions.add(window.performance.getEntriesByType);
|
|
3333
3371
|
}
|
|
3334
3372
|
} catch(e) {}
|
|
3373
|
+
|
|
3374
|
+
// --- Auto-resolve birthday compliance & eliminate false logout markers ---
|
|
3375
|
+
try {
|
|
3376
|
+
localStorage.removeItem("qwen_token_logged_out_marker");
|
|
3377
|
+
const b = localStorage.getItem("qwen_account_birthday");
|
|
3378
|
+
if (b) {
|
|
3379
|
+
try {
|
|
3380
|
+
const parsed = JSON.parse(b);
|
|
3381
|
+
if (!parsed.birthday) {
|
|
3382
|
+
parsed.birthday = "1995-06-15";
|
|
3383
|
+
localStorage.setItem("qwen_account_birthday", JSON.stringify(parsed));
|
|
3384
|
+
}
|
|
3385
|
+
} catch {}
|
|
3386
|
+
}
|
|
3387
|
+
} catch(e) {}
|
|
3335
3388
|
})();
|
|
3336
3389
|
`;
|
|
3337
3390
|
}
|
|
@@ -3367,7 +3420,7 @@ async function resolveAccountCredentials(account) {
|
|
|
3367
3420
|
}
|
|
3368
3421
|
return account;
|
|
3369
3422
|
}
|
|
3370
|
-
async function initPlaywrightForAccount(rawAccount, headless =
|
|
3423
|
+
async function initPlaywrightForAccount(rawAccount, headless = config.playwright.headless, browserType = "chromium", options = {}) {
|
|
3371
3424
|
const account = await resolveAccountCredentials(rawAccount);
|
|
3372
3425
|
if (accountPages.has(account.id)) {
|
|
3373
3426
|
console.log(
|
|
@@ -3493,7 +3546,7 @@ async function initPlaywrightForAccount(rawAccount, headless = true, browserType
|
|
|
3493
3546
|
const storageState = loadStorageState(account.id);
|
|
3494
3547
|
if (storageState) {
|
|
3495
3548
|
try {
|
|
3496
|
-
const raw =
|
|
3549
|
+
const raw = fs7.readFileSync(storageState, "utf8");
|
|
3497
3550
|
const parsed = JSON.parse(raw);
|
|
3498
3551
|
if (Array.isArray(parsed.cookies) && parsed.cookies.length > 0) {
|
|
3499
3552
|
const currentCookies = await acctContext.cookies();
|
|
@@ -3580,11 +3633,19 @@ async function initPlaywrightForAccount(rawAccount, headless = true, browserType
|
|
|
3580
3633
|
}
|
|
3581
3634
|
if (restoredFromDb) {
|
|
3582
3635
|
if (!acctPage.isClosed() && (acctPage.url() === "about:blank" || !acctPage.url().startsWith(qwenOrigin()))) {
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3636
|
+
try {
|
|
3637
|
+
await acctPage.goto(qwenUrl("/"), {
|
|
3638
|
+
waitUntil: "domcontentloaded",
|
|
3639
|
+
timeout: config.timeouts.navigation
|
|
3640
|
+
});
|
|
3641
|
+
await sleep2(300);
|
|
3642
|
+
} catch (err) {
|
|
3643
|
+
if (!err?.message?.includes("ERR_ABORTED")) {
|
|
3644
|
+
console.warn(
|
|
3645
|
+
`\u26A0\uFE0F [Playwright] Background navigation warning for ${maskEmail(account.email)}: ${err.message}`
|
|
3646
|
+
);
|
|
3647
|
+
}
|
|
3648
|
+
}
|
|
3588
3649
|
}
|
|
3589
3650
|
return;
|
|
3590
3651
|
}
|
|
@@ -3704,18 +3765,34 @@ async function loginToQwen(accountId, email, password) {
|
|
|
3704
3765
|
const apiResult = await loginViaApi(page, email, password);
|
|
3705
3766
|
if (apiResult.success) {
|
|
3706
3767
|
cookieCaches.delete(accountId);
|
|
3707
|
-
|
|
3708
|
-
if (cache) {
|
|
3709
|
-
cache.headers = {};
|
|
3710
|
-
cache.lastRefresh = 0;
|
|
3711
|
-
}
|
|
3712
|
-
unmarkAccountHeadersReady(accountId);
|
|
3768
|
+
await saveStorageState(page.context(), accountId);
|
|
3713
3769
|
try {
|
|
3714
|
-
const
|
|
3715
|
-
|
|
3770
|
+
const liveCookies = await page.context().cookies();
|
|
3771
|
+
const tokenCookie = liveCookies.find((c) => c.name === "token");
|
|
3772
|
+
if (tokenCookie) {
|
|
3773
|
+
const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
|
|
3774
|
+
const cache = getHeaderCache(accountId);
|
|
3775
|
+
cache.headers.cookie = cookieStr;
|
|
3776
|
+
cache.lastRefresh = Date.now();
|
|
3777
|
+
markAccountHeadersReady(accountId);
|
|
3778
|
+
const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3779
|
+
const exp = parseJwtExpiry(tokenCookie.value);
|
|
3780
|
+
saveAuthSession2(accountId, {
|
|
3781
|
+
cookie: cookieStr,
|
|
3782
|
+
userAgent: cache.headers["user-agent"] || "",
|
|
3783
|
+
bxV: cache.headers["bx-v"] || "2.5.37",
|
|
3784
|
+
bxUa: cache.headers["bx-ua"] || "",
|
|
3785
|
+
bxUmidtoken: cache.headers["bx-umidtoken"] || "",
|
|
3786
|
+
secChUa: cache.headers["sec-ch-ua"] || void 0,
|
|
3787
|
+
secChUaMobile: cache.headers["sec-ch-ua-mobile"] || void 0,
|
|
3788
|
+
secChUaPlatform: cache.headers["sec-ch-ua-platform"] || void 0,
|
|
3789
|
+
version: cache.headers["version"] || void 0,
|
|
3790
|
+
tokenExpiresAt: exp || void 0,
|
|
3791
|
+
capturedAt: Date.now()
|
|
3792
|
+
});
|
|
3793
|
+
}
|
|
3716
3794
|
} catch {
|
|
3717
3795
|
}
|
|
3718
|
-
await saveStorageState(page.context(), accountId);
|
|
3719
3796
|
return true;
|
|
3720
3797
|
}
|
|
3721
3798
|
if (apiResult.permanentFailure) {
|
|
@@ -3732,18 +3809,34 @@ async function loginToQwen(accountId, email, password) {
|
|
|
3732
3809
|
const uiResult = await loginViaUi(page, email, password);
|
|
3733
3810
|
if (uiResult.success) {
|
|
3734
3811
|
cookieCaches.delete(accountId);
|
|
3735
|
-
|
|
3736
|
-
if (cache) {
|
|
3737
|
-
cache.headers = {};
|
|
3738
|
-
cache.lastRefresh = 0;
|
|
3739
|
-
}
|
|
3740
|
-
unmarkAccountHeadersReady(accountId);
|
|
3812
|
+
await saveStorageState(page.context(), accountId);
|
|
3741
3813
|
try {
|
|
3742
|
-
const
|
|
3743
|
-
|
|
3814
|
+
const liveCookies = await page.context().cookies();
|
|
3815
|
+
const tokenCookie = liveCookies.find((c) => c.name === "token");
|
|
3816
|
+
if (tokenCookie) {
|
|
3817
|
+
const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
|
|
3818
|
+
const cache = getHeaderCache(accountId);
|
|
3819
|
+
cache.headers.cookie = cookieStr;
|
|
3820
|
+
cache.lastRefresh = Date.now();
|
|
3821
|
+
markAccountHeadersReady(accountId);
|
|
3822
|
+
const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3823
|
+
const exp = parseJwtExpiry(tokenCookie.value);
|
|
3824
|
+
saveAuthSession2(accountId, {
|
|
3825
|
+
cookie: cookieStr,
|
|
3826
|
+
userAgent: cache.headers["user-agent"] || "",
|
|
3827
|
+
bxV: cache.headers["bx-v"] || "2.5.37",
|
|
3828
|
+
bxUa: cache.headers["bx-ua"] || "",
|
|
3829
|
+
bxUmidtoken: cache.headers["bx-umidtoken"] || "",
|
|
3830
|
+
secChUa: cache.headers["sec-ch-ua"] || void 0,
|
|
3831
|
+
secChUaMobile: cache.headers["sec-ch-ua-mobile"] || void 0,
|
|
3832
|
+
secChUaPlatform: cache.headers["sec-ch-ua-platform"] || void 0,
|
|
3833
|
+
version: cache.headers["version"] || void 0,
|
|
3834
|
+
tokenExpiresAt: exp || void 0,
|
|
3835
|
+
capturedAt: Date.now()
|
|
3836
|
+
});
|
|
3837
|
+
}
|
|
3744
3838
|
} catch {
|
|
3745
3839
|
}
|
|
3746
|
-
await saveStorageState(page.context(), accountId);
|
|
3747
3840
|
return true;
|
|
3748
3841
|
}
|
|
3749
3842
|
if (uiResult.permanentFailure) {
|
|
@@ -3942,10 +4035,16 @@ async function loginViaUi(page, email, password) {
|
|
|
3942
4035
|
);
|
|
3943
4036
|
return { success: false, reason: "Campo de e-mail n\xE3o encontrado (poss\xEDvel captcha)" };
|
|
3944
4037
|
}
|
|
4038
|
+
await clearVisibleChallenge(page);
|
|
4039
|
+
const findPasswordModeButton = () => {
|
|
4040
|
+
return page.locator('button, [role="button"], a, div').filter({
|
|
4041
|
+
hasText: /(?:log\s*in\s*with\s*(?:a\s*)?password|fazer\s*login\s*com\s*senha|entrar\s*com\s*(?:uma\s*)?senha|iniciar\s*sesi[oó]n\s*con\s*contrase[nñ]a|密码登录)/i
|
|
4042
|
+
}).first();
|
|
4043
|
+
};
|
|
3945
4044
|
try {
|
|
3946
|
-
const pwdModeBtn =
|
|
3947
|
-
if (await pwdModeBtn.isVisible({ timeout:
|
|
3948
|
-
await pwdModeBtn.click().catch(() => {
|
|
4045
|
+
const pwdModeBtn = findPasswordModeButton();
|
|
4046
|
+
if (await pwdModeBtn.isVisible({ timeout: 2e3 }).catch(() => false)) {
|
|
4047
|
+
await pwdModeBtn.click({ timeout: 2e3 }).catch(() => {
|
|
3949
4048
|
});
|
|
3950
4049
|
await sleep2(500);
|
|
3951
4050
|
}
|
|
@@ -3954,9 +4053,9 @@ async function loginViaUi(page, email, password) {
|
|
|
3954
4053
|
await page.fill(emailSelector, email);
|
|
3955
4054
|
await sleep2(300);
|
|
3956
4055
|
try {
|
|
3957
|
-
const pwdModeBtn =
|
|
3958
|
-
if (await pwdModeBtn.isVisible({ timeout:
|
|
3959
|
-
await pwdModeBtn.click().catch(() => {
|
|
4056
|
+
const pwdModeBtn = findPasswordModeButton();
|
|
4057
|
+
if (await pwdModeBtn.isVisible({ timeout: 1500 }).catch(() => false)) {
|
|
4058
|
+
await pwdModeBtn.click({ timeout: 2e3 }).catch(() => {
|
|
3960
4059
|
});
|
|
3961
4060
|
await sleep2(500);
|
|
3962
4061
|
}
|
|
@@ -3981,7 +4080,7 @@ async function loginViaUi(page, email, password) {
|
|
|
3981
4080
|
}
|
|
3982
4081
|
await page.fill(passwordSelector, password);
|
|
3983
4082
|
await sleep2(500);
|
|
3984
|
-
const submitSelector = 'button.qwenchat-auth-pc-submit-button, button[type="submit"], button:has-text("Log in"), button:has-text("Sign in")';
|
|
4083
|
+
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")';
|
|
3985
4084
|
const submitButton = page.locator(submitSelector).first();
|
|
3986
4085
|
try {
|
|
3987
4086
|
await page.waitForSelector('button[type="submit"]:not([disabled])', {
|
|
@@ -4508,12 +4607,12 @@ async function resetPlaywrightProfileLocked(accountId) {
|
|
|
4508
4607
|
removePlaywrightProfile(profilePath);
|
|
4509
4608
|
const stateFile2 = path4.join(path4.dirname(profilePath), `${accountId}_state.json`);
|
|
4510
4609
|
try {
|
|
4511
|
-
|
|
4610
|
+
fs7.rmSync(stateFile2, { force: true });
|
|
4512
4611
|
} catch {
|
|
4513
4612
|
}
|
|
4514
4613
|
}
|
|
4515
4614
|
function removePlaywrightProfile(profilePath, rmSyncOverride) {
|
|
4516
|
-
const doRemove = rmSyncOverride ?? ((p, opts) =>
|
|
4615
|
+
const doRemove = rmSyncOverride ?? ((p, opts) => fs7.rmSync(p, opts));
|
|
4517
4616
|
try {
|
|
4518
4617
|
doRemove(profilePath, { recursive: true, force: true });
|
|
4519
4618
|
} catch (error) {
|
|
@@ -4522,7 +4621,7 @@ function removePlaywrightProfile(profilePath, rmSyncOverride) {
|
|
|
4522
4621
|
if (message.includes("EPERM") || message.includes("EBUSY") || message.includes("Permission denied")) {
|
|
4523
4622
|
try {
|
|
4524
4623
|
const stalePath = `${profilePath}.stale-${Date.now()}`;
|
|
4525
|
-
|
|
4624
|
+
fs7.renameSync(profilePath, stalePath);
|
|
4526
4625
|
} catch {
|
|
4527
4626
|
}
|
|
4528
4627
|
return;
|
|
@@ -4545,23 +4644,23 @@ function prunePlaywrightProfileCaches(profilePath) {
|
|
|
4545
4644
|
let freedFiles = 0;
|
|
4546
4645
|
try {
|
|
4547
4646
|
const defaultDir = path4.join(profilePath, "Default");
|
|
4548
|
-
if (!
|
|
4647
|
+
if (!fs7.existsSync(defaultDir)) {
|
|
4549
4648
|
return { freedBytes, freedFiles };
|
|
4550
4649
|
}
|
|
4551
4650
|
for (const dirName of transientDirNames) {
|
|
4552
4651
|
const targetDir = path4.join(defaultDir, dirName);
|
|
4553
|
-
if (
|
|
4652
|
+
if (fs7.existsSync(targetDir)) {
|
|
4554
4653
|
try {
|
|
4555
4654
|
const countAndRemove = (d) => {
|
|
4556
4655
|
try {
|
|
4557
|
-
const entries =
|
|
4656
|
+
const entries = fs7.readdirSync(d, { withFileTypes: true });
|
|
4558
4657
|
for (const e of entries) {
|
|
4559
4658
|
const full = path4.join(d, e.name);
|
|
4560
4659
|
if (e.isDirectory()) {
|
|
4561
4660
|
countAndRemove(full);
|
|
4562
4661
|
} else if (e.isFile()) {
|
|
4563
4662
|
try {
|
|
4564
|
-
freedBytes +=
|
|
4663
|
+
freedBytes += fs7.statSync(full).size;
|
|
4565
4664
|
freedFiles++;
|
|
4566
4665
|
} catch {
|
|
4567
4666
|
}
|
|
@@ -4571,7 +4670,7 @@ function prunePlaywrightProfileCaches(profilePath) {
|
|
|
4571
4670
|
}
|
|
4572
4671
|
};
|
|
4573
4672
|
countAndRemove(targetDir);
|
|
4574
|
-
|
|
4673
|
+
fs7.rmSync(targetDir, { recursive: true, force: true });
|
|
4575
4674
|
} catch {
|
|
4576
4675
|
}
|
|
4577
4676
|
}
|
|
@@ -4585,10 +4684,10 @@ function pruneAllPlaywrightProfiles(baseDir = getProfilesDir()) {
|
|
|
4585
4684
|
let totalFreedFiles = 0;
|
|
4586
4685
|
let profilesCleaned = 0;
|
|
4587
4686
|
try {
|
|
4588
|
-
if (!
|
|
4687
|
+
if (!fs7.existsSync(baseDir)) {
|
|
4589
4688
|
return { totalFreedBytes, totalFreedFiles, profilesCleaned };
|
|
4590
4689
|
}
|
|
4591
|
-
const entries =
|
|
4690
|
+
const entries = fs7.readdirSync(baseDir, { withFileTypes: true });
|
|
4592
4691
|
for (const entry of entries) {
|
|
4593
4692
|
if (entry.isDirectory()) {
|
|
4594
4693
|
const profilePath = path4.join(baseDir, entry.name);
|
|
@@ -4608,11 +4707,11 @@ function cleanupOrphanProfiles(baseDir = getProfilesDir(), activeAccountIds) {
|
|
|
4608
4707
|
let removedCount = 0;
|
|
4609
4708
|
let freedBytes = 0;
|
|
4610
4709
|
try {
|
|
4611
|
-
if (!
|
|
4710
|
+
if (!fs7.existsSync(baseDir)) {
|
|
4612
4711
|
return { removedCount, freedBytes };
|
|
4613
4712
|
}
|
|
4614
4713
|
const activeIds = activeAccountIds ?? new Set(loadAccounts().map((a) => a.id));
|
|
4615
|
-
const entries =
|
|
4714
|
+
const entries = fs7.readdirSync(baseDir, { withFileTypes: true });
|
|
4616
4715
|
for (const entry of entries) {
|
|
4617
4716
|
if (!entry.isDirectory()) continue;
|
|
4618
4717
|
const isStale = entry.name.includes(".stale-");
|
|
@@ -4623,13 +4722,13 @@ function cleanupOrphanProfiles(baseDir = getProfilesDir(), activeAccountIds) {
|
|
|
4623
4722
|
let bytes = 0;
|
|
4624
4723
|
const countSize = (d) => {
|
|
4625
4724
|
try {
|
|
4626
|
-
const subEntries =
|
|
4725
|
+
const subEntries = fs7.readdirSync(d, { withFileTypes: true });
|
|
4627
4726
|
for (const e of subEntries) {
|
|
4628
4727
|
const full = path4.join(d, e.name);
|
|
4629
4728
|
if (e.isDirectory()) countSize(full);
|
|
4630
4729
|
else if (e.isFile()) {
|
|
4631
4730
|
try {
|
|
4632
|
-
bytes +=
|
|
4731
|
+
bytes += fs7.statSync(full).size;
|
|
4633
4732
|
} catch {
|
|
4634
4733
|
}
|
|
4635
4734
|
}
|
|
@@ -4639,7 +4738,7 @@ function cleanupOrphanProfiles(baseDir = getProfilesDir(), activeAccountIds) {
|
|
|
4639
4738
|
};
|
|
4640
4739
|
countSize(targetPath);
|
|
4641
4740
|
removePlaywrightProfile(targetPath);
|
|
4642
|
-
if (!
|
|
4741
|
+
if (!fs7.existsSync(targetPath)) {
|
|
4643
4742
|
removedCount++;
|
|
4644
4743
|
freedBytes += bytes;
|
|
4645
4744
|
}
|
|
@@ -4900,7 +4999,7 @@ __export(clean_cache_exports, {
|
|
|
4900
4999
|
getDirStats: () => getDirStats
|
|
4901
5000
|
});
|
|
4902
5001
|
import "dotenv/config";
|
|
4903
|
-
import
|
|
5002
|
+
import fs8 from "node:fs";
|
|
4904
5003
|
import path5 from "node:path";
|
|
4905
5004
|
import os3 from "node:os";
|
|
4906
5005
|
import { chromium as chromium2 } from "patchright";
|
|
@@ -4915,14 +5014,14 @@ function getDirStats(dir) {
|
|
|
4915
5014
|
let files = 0;
|
|
4916
5015
|
function walk(d) {
|
|
4917
5016
|
try {
|
|
4918
|
-
const entries =
|
|
5017
|
+
const entries = fs8.readdirSync(d, { withFileTypes: true });
|
|
4919
5018
|
for (const e of entries) {
|
|
4920
5019
|
const full = path5.join(d, e.name);
|
|
4921
5020
|
if (e.isDirectory()) {
|
|
4922
5021
|
walk(full);
|
|
4923
5022
|
} else if (e.isFile()) {
|
|
4924
5023
|
try {
|
|
4925
|
-
bytes +=
|
|
5024
|
+
bytes += fs8.statSync(full).size;
|
|
4926
5025
|
files++;
|
|
4927
5026
|
} catch {
|
|
4928
5027
|
}
|
|
@@ -4951,17 +5050,17 @@ async function cleanPlaywrightBrowsers(cleanUnused) {
|
|
|
4951
5050
|
}
|
|
4952
5051
|
} catch {
|
|
4953
5052
|
}
|
|
4954
|
-
if (!msPlaywrightDir || !
|
|
5053
|
+
if (!msPlaywrightDir || !fs8.existsSync(msPlaywrightDir)) {
|
|
4955
5054
|
const defaultPlaywrightDir = process.env.PLAYWRIGHT_BROWSERS_PATH || (process.platform === "win32" ? path5.join(os3.homedir(), "AppData", "Local", "ms-playwright") : process.platform === "darwin" ? path5.join(os3.homedir(), "Library", "Caches", "ms-playwright") : path5.join(os3.homedir(), ".cache", "ms-playwright"));
|
|
4956
|
-
if (
|
|
5055
|
+
if (fs8.existsSync(defaultPlaywrightDir)) {
|
|
4957
5056
|
msPlaywrightDir = defaultPlaywrightDir;
|
|
4958
5057
|
}
|
|
4959
5058
|
}
|
|
4960
5059
|
const unusedDirs = [];
|
|
4961
5060
|
let freedBytes = 0;
|
|
4962
|
-
if (msPlaywrightDir &&
|
|
5061
|
+
if (msPlaywrightDir && fs8.existsSync(msPlaywrightDir)) {
|
|
4963
5062
|
try {
|
|
4964
|
-
const entries =
|
|
5063
|
+
const entries = fs8.readdirSync(msPlaywrightDir, { withFileTypes: true });
|
|
4965
5064
|
for (const entry of entries) {
|
|
4966
5065
|
if (!entry.isDirectory()) continue;
|
|
4967
5066
|
const folderName = entry.name;
|
|
@@ -4984,7 +5083,7 @@ async function cleanPlaywrightBrowsers(cleanUnused) {
|
|
|
4984
5083
|
if (cleanUnused && unusedDirs.length > 0) {
|
|
4985
5084
|
for (const item of unusedDirs) {
|
|
4986
5085
|
try {
|
|
4987
|
-
|
|
5086
|
+
fs8.rmSync(item.path, { recursive: true, force: true });
|
|
4988
5087
|
freedBytes += item.bytes;
|
|
4989
5088
|
} catch (err) {
|
|
4990
5089
|
console.warn(`[CleanCache] Warning: could not remove ${item.name}:`, err);
|