qwenproxy-cli 1.0.22 → 1.0.23
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/package.json +1 -1
- package/src/services/chat-cleanup.ts +34 -11
- package/src/services/playwright.ts +24 -5
- package/src/services/qwen.ts +21 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qwenproxy-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"description": "High-performance OpenAI & Anthropic compatible API gateway for Qwen with multi-account rotation, interactive TUI, and resilient tool calling.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"bin": {
|
|
@@ -10,32 +10,52 @@ import {
|
|
|
10
10
|
closeAllPlaywright,
|
|
11
11
|
} from "./playwright.ts";
|
|
12
12
|
import { isAuthMockEnabled } from "./auth-playwright.ts";
|
|
13
|
+
import { maskEmail } from "../core/logger.ts";
|
|
13
14
|
export interface DeleteChatsResult {
|
|
14
15
|
attempted: number;
|
|
15
16
|
succeeded: number;
|
|
16
17
|
mode: "accounts";
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
async function ensurePlaywrightSession(
|
|
20
|
+
async function ensurePlaywrightSession(
|
|
21
|
+
account: QwenAccount,
|
|
22
|
+
index = 1,
|
|
23
|
+
total = 1,
|
|
24
|
+
): Promise<void> {
|
|
20
25
|
if (isPlaywrightInitialized(account.id) || isAuthMockEnabled()) return;
|
|
21
26
|
|
|
22
27
|
const credentials = getAccountCredentials(account.id);
|
|
23
28
|
if (!credentials) {
|
|
24
|
-
throw new Error(`
|
|
29
|
+
throw new Error(`Credenciais da conta ${account.id} não encontradas.`);
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
console.log(
|
|
28
|
-
`[DeleteChats]
|
|
33
|
+
`[DeleteChats] [${index}/${total}] Abrindo navegador para ${maskEmail(account.email)}...`,
|
|
29
34
|
);
|
|
30
|
-
await initPlaywrightForAccount(credentials
|
|
35
|
+
await initPlaywrightForAccount(credentials, true, "chromium", {
|
|
36
|
+
skipHeaderCapture: true,
|
|
37
|
+
});
|
|
31
38
|
console.log(
|
|
32
|
-
`✅ [DeleteChats]
|
|
39
|
+
`✅ [DeleteChats] [${index}/${total}] Sessão pronta para ${maskEmail(account.email)}.`,
|
|
33
40
|
);
|
|
34
41
|
}
|
|
35
42
|
|
|
36
|
-
export async function deleteChatsForAccount(
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
export async function deleteChatsForAccount(
|
|
44
|
+
account: QwenAccount,
|
|
45
|
+
index = 1,
|
|
46
|
+
total = 1,
|
|
47
|
+
): Promise<boolean> {
|
|
48
|
+
await ensurePlaywrightSession(account, index, total);
|
|
49
|
+
console.log(
|
|
50
|
+
`🗑️ [DeleteChats] [${index}/${total}] Apagando conversas remotas de ${maskEmail(account.email)}...`,
|
|
51
|
+
);
|
|
52
|
+
const ok = await deleteAllQwenChats(account.id);
|
|
53
|
+
if (ok) {
|
|
54
|
+
console.log(
|
|
55
|
+
`✅ [DeleteChats] [${index}/${total}] Conversas apagadas com sucesso para ${maskEmail(account.email)}.`,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return ok;
|
|
39
59
|
}
|
|
40
60
|
|
|
41
61
|
export async function deleteChatsForAccountId(accountId: string): Promise<boolean> {
|
|
@@ -65,13 +85,16 @@ export async function deleteChatsForConfiguredAccounts(keepBrowserOpen = false):
|
|
|
65
85
|
let succeeded = 0;
|
|
66
86
|
|
|
67
87
|
try {
|
|
68
|
-
for (
|
|
88
|
+
for (let i = 0; i < accounts.length; i++) {
|
|
89
|
+
const account = accounts[i];
|
|
90
|
+
const currentIdx = i + 1;
|
|
91
|
+
const totalCount = accounts.length;
|
|
69
92
|
try {
|
|
70
|
-
const ok = await deleteChatsForAccount(account);
|
|
93
|
+
const ok = await deleteChatsForAccount(account, currentIdx, totalCount);
|
|
71
94
|
if (ok) succeeded++;
|
|
72
95
|
} catch (error) {
|
|
73
96
|
console.error(
|
|
74
|
-
|
|
97
|
+
`❌ [DeleteChats] [${currentIdx}/${totalCount}] Falha ao apagar conversas de ${maskEmail(account.email)}:`,
|
|
75
98
|
error instanceof Error ? error.message : String(error),
|
|
76
99
|
);
|
|
77
100
|
}
|
|
@@ -1290,6 +1290,7 @@ export async function initPlaywrightForAccount(
|
|
|
1290
1290
|
rawAccount: QwenAccount,
|
|
1291
1291
|
headless = true,
|
|
1292
1292
|
browserType: BrowserType = "chromium",
|
|
1293
|
+
options: { skipHeaderCapture?: boolean } = {},
|
|
1293
1294
|
): Promise<void> {
|
|
1294
1295
|
const account = await resolveAccountCredentials(rawAccount);
|
|
1295
1296
|
if (accountPages.has(account.id)) {
|
|
@@ -1346,11 +1347,19 @@ export async function initPlaywrightForAccount(
|
|
|
1346
1347
|
|
|
1347
1348
|
let acctContext: BrowserContext;
|
|
1348
1349
|
try {
|
|
1349
|
-
acctContext = await
|
|
1350
|
+
acctContext = await withTimeout(
|
|
1351
|
+
engine.launchPersistentContext(profilePath, launchOptions),
|
|
1352
|
+
30_000,
|
|
1353
|
+
`O navegador não iniciou em 30s para a conta ${maskEmail(account.email)}. Se o QwenProxy estiver rodando em outro terminal, feche-o antes de executar este comando.`,
|
|
1354
|
+
);
|
|
1350
1355
|
} catch (launchErr: any) {
|
|
1351
1356
|
if (launchErr?.message?.includes("Executable doesn't exist")) {
|
|
1352
1357
|
autoInstallPlaywrightChromium();
|
|
1353
|
-
acctContext = await
|
|
1358
|
+
acctContext = await withTimeout(
|
|
1359
|
+
engine.launchPersistentContext(profilePath, launchOptions),
|
|
1360
|
+
30_000,
|
|
1361
|
+
`O navegador não iniciou em 30s para a conta ${maskEmail(account.email)}.`,
|
|
1362
|
+
);
|
|
1354
1363
|
} else {
|
|
1355
1364
|
throw launchErr;
|
|
1356
1365
|
}
|
|
@@ -1472,7 +1481,9 @@ export async function initPlaywrightForAccount(
|
|
|
1472
1481
|
);
|
|
1473
1482
|
throw validationError;
|
|
1474
1483
|
}
|
|
1475
|
-
|
|
1484
|
+
if (!options.skipHeaderCapture) {
|
|
1485
|
+
await captureQwenHeaders(account.id);
|
|
1486
|
+
}
|
|
1476
1487
|
|
|
1477
1488
|
// Header capture may leave the UI on a generated chat page. Return the
|
|
1478
1489
|
// primary tab to the canonical chat home.
|
|
@@ -1559,11 +1570,19 @@ export async function validateAccountLogin(
|
|
|
1559
1570
|
|
|
1560
1571
|
let acctContext: BrowserContext;
|
|
1561
1572
|
try {
|
|
1562
|
-
acctContext = await
|
|
1573
|
+
acctContext = await withTimeout(
|
|
1574
|
+
engine.launchPersistentContext(profilePath, launchOptions),
|
|
1575
|
+
30_000,
|
|
1576
|
+
`O navegador não iniciou em 30s para a conta ${maskEmail(account.email)}. Se o QwenProxy estiver rodando em outro terminal, feche-o antes de executar este comando.`,
|
|
1577
|
+
);
|
|
1563
1578
|
} catch (launchErr: any) {
|
|
1564
1579
|
if (launchErr?.message?.includes("Executable doesn't exist")) {
|
|
1565
1580
|
autoInstallPlaywrightChromium();
|
|
1566
|
-
acctContext = await
|
|
1581
|
+
acctContext = await withTimeout(
|
|
1582
|
+
engine.launchPersistentContext(profilePath, launchOptions),
|
|
1583
|
+
30_000,
|
|
1584
|
+
`O navegador não iniciou em 30s para a conta ${maskEmail(account.email)}.`,
|
|
1585
|
+
);
|
|
1567
1586
|
} else {
|
|
1568
1587
|
throw launchErr;
|
|
1569
1588
|
}
|
package/src/services/qwen.ts
CHANGED
|
@@ -1916,14 +1916,31 @@ function formatPublicQwenModel(model: Record<string, unknown>): PublicQwenModel
|
|
|
1916
1916
|
}
|
|
1917
1917
|
|
|
1918
1918
|
export async function deleteAllQwenChats(accountId?: string): Promise<boolean> {
|
|
1919
|
-
|
|
1919
|
+
let requestHeaders: Record<string, string>;
|
|
1920
|
+
if (isAuthMockEnabled()) {
|
|
1921
|
+
const { headers } = await getQwenHeaders(false, accountId);
|
|
1922
|
+
requestHeaders = buildCapturedQwenHeaders(headers, {
|
|
1923
|
+
referer: qwenUrl("/settings/chats"),
|
|
1924
|
+
});
|
|
1925
|
+
} else {
|
|
1926
|
+
// In live mode, requestQwenTextInBrowser executes inside the authenticated
|
|
1927
|
+
// browser page where session cookies are attached automatically.
|
|
1928
|
+
// Bypassing getQwenHeaders avoids triggering captureQwenHeaders (which sends
|
|
1929
|
+
// a dummy chat completion to intercept anti-fraud tokens not needed for deletions).
|
|
1930
|
+
requestHeaders = {
|
|
1931
|
+
source: "web",
|
|
1932
|
+
version: "0.2.89",
|
|
1933
|
+
timezone: new Date().toString().split(" (")[0],
|
|
1934
|
+
"x-request-id": crypto.randomUUID(),
|
|
1935
|
+
Referer: qwenUrl("/settings/chats"),
|
|
1936
|
+
};
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1920
1939
|
const response = await requestQwenTextInBrowser(
|
|
1921
1940
|
accountId,
|
|
1922
1941
|
"DELETE",
|
|
1923
1942
|
"/api/v2/chats/",
|
|
1924
|
-
|
|
1925
|
-
referer: qwenUrl("/settings/chats"),
|
|
1926
|
-
}),
|
|
1943
|
+
requestHeaders,
|
|
1927
1944
|
undefined,
|
|
1928
1945
|
{ referrer: qwenUrl("/settings/chats") },
|
|
1929
1946
|
);
|