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/reset-cooldowns.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
|
}
|
|
@@ -1328,11 +1353,11 @@ var init_config = __esm({
|
|
|
1328
1353
|
// nothing in this window is dead and should fail fast, retryable).
|
|
1329
1354
|
QWEN_FIRST_CHUNK_TIMEOUT: z.string().default("60000"),
|
|
1330
1355
|
TOTAL_REQUEST_TIMEOUT: z.string().default("600000"),
|
|
1331
|
-
// Mid-stream silence window for thinking models:
|
|
1356
|
+
// Mid-stream silence window for thinking models: 5 min with ZERO upstream
|
|
1332
1357
|
// bytes is a dead stream (WAF swallow / dropped connection) — fail fast and
|
|
1333
1358
|
// let the retry policy rotate accounts. Flowing reasoning chunks RESET this
|
|
1334
1359
|
// timer, so legitimate slow thinking is never cut; only total silence is.
|
|
1335
|
-
REASONING_MODEL_TIMEOUT: z.string().default("
|
|
1360
|
+
REASONING_MODEL_TIMEOUT: z.string().default("300000"),
|
|
1336
1361
|
CACHE_TTL: z.string().default("3600"),
|
|
1337
1362
|
RESPONSE_TTL: z.string().default("1800"),
|
|
1338
1363
|
CACHE_COMPRESSION_ENABLED: z.string().default("true"),
|
|
@@ -2705,6 +2730,44 @@ var init_jwt = __esm({
|
|
|
2705
2730
|
}
|
|
2706
2731
|
});
|
|
2707
2732
|
|
|
2733
|
+
// src/core/process-guard.ts
|
|
2734
|
+
function isPlaywrightAlreadyClosedMessage(message) {
|
|
2735
|
+
if (!message) return false;
|
|
2736
|
+
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");
|
|
2737
|
+
}
|
|
2738
|
+
function isBenignTeardownError(error) {
|
|
2739
|
+
if (!error) return false;
|
|
2740
|
+
const message = error instanceof Error ? error.message : typeof error === "object" && "message" in error ? String(error.message) : String(error);
|
|
2741
|
+
return isPlaywrightAlreadyClosedMessage(message);
|
|
2742
|
+
}
|
|
2743
|
+
function installProcessTeardownGuards(label = "Process") {
|
|
2744
|
+
if (guardsInstalled) return;
|
|
2745
|
+
guardsInstalled = true;
|
|
2746
|
+
process.on("uncaughtException", (error) => {
|
|
2747
|
+
if (isBenignTeardownError(error)) {
|
|
2748
|
+
const msg = error instanceof Error ? error.message : typeof error === "object" && error !== null && "message" in error ? String(error.message) : String(error);
|
|
2749
|
+
console.warn(`\u26A0\uFE0F [${label}] Handled benign driver teardown exception: ${msg}`);
|
|
2750
|
+
return;
|
|
2751
|
+
}
|
|
2752
|
+
console.error(`\u274C [${label}] Uncaught Exception:`, error);
|
|
2753
|
+
});
|
|
2754
|
+
process.on("unhandledRejection", (reason) => {
|
|
2755
|
+
if (isBenignTeardownError(reason)) {
|
|
2756
|
+
const msg = reason instanceof Error ? reason.message : typeof reason === "object" && reason !== null && "message" in reason ? String(reason.message) : String(reason);
|
|
2757
|
+
console.warn(`\u26A0\uFE0F [${label}] Handled benign driver teardown rejection: ${msg}`);
|
|
2758
|
+
return;
|
|
2759
|
+
}
|
|
2760
|
+
console.error(`\u274C [${label}] Unhandled Rejection:`, reason);
|
|
2761
|
+
});
|
|
2762
|
+
}
|
|
2763
|
+
var guardsInstalled;
|
|
2764
|
+
var init_process_guard = __esm({
|
|
2765
|
+
"src/core/process-guard.ts"() {
|
|
2766
|
+
"use strict";
|
|
2767
|
+
guardsInstalled = false;
|
|
2768
|
+
}
|
|
2769
|
+
});
|
|
2770
|
+
|
|
2708
2771
|
// src/clean-cache.ts
|
|
2709
2772
|
var clean_cache_exports = {};
|
|
2710
2773
|
__export(clean_cache_exports, {
|
|
@@ -2873,6 +2936,8 @@ var init_clean_cache = __esm({
|
|
|
2873
2936
|
"src/clean-cache.ts"() {
|
|
2874
2937
|
"use strict";
|
|
2875
2938
|
init_playwright();
|
|
2939
|
+
init_process_guard();
|
|
2940
|
+
installProcessTeardownGuards("CleanCache");
|
|
2876
2941
|
isDirectRun = process.argv[1] && (process.argv[1].endsWith("clean-cache.ts") || process.argv[1].endsWith("clean-cache.js"));
|
|
2877
2942
|
if (isDirectRun) {
|
|
2878
2943
|
main().catch((err) => {
|
|
@@ -3046,15 +3111,18 @@ function loadStorageState(accountId) {
|
|
|
3046
3111
|
return void 0;
|
|
3047
3112
|
}
|
|
3048
3113
|
}
|
|
3049
|
-
async function saveStorageState(context, accountId, timeoutMs =
|
|
3114
|
+
async function saveStorageState(context, accountId, timeoutMs = 1e4) {
|
|
3050
3115
|
try {
|
|
3051
3116
|
const stateFile = getStorageStatePath(accountId);
|
|
3052
3117
|
const dir = path5.dirname(stateFile);
|
|
3053
3118
|
if (!fs8.existsSync(dir)) {
|
|
3054
3119
|
fs8.mkdirSync(dir, { recursive: true });
|
|
3055
3120
|
}
|
|
3121
|
+
const rawPromise = context.storageState({ path: stateFile }).catch(() => {
|
|
3122
|
+
return void 0;
|
|
3123
|
+
});
|
|
3056
3124
|
await withTimeout(
|
|
3057
|
-
|
|
3125
|
+
rawPromise,
|
|
3058
3126
|
timeoutMs,
|
|
3059
3127
|
`storageState timed out after ${timeoutMs}ms`
|
|
3060
3128
|
);
|
|
@@ -4529,6 +4597,137 @@ async function loginViaUi(page, email, password) {
|
|
|
4529
4597
|
return { success: false, reason: err?.message || String(err) };
|
|
4530
4598
|
}
|
|
4531
4599
|
}
|
|
4600
|
+
async function refreshAccountToken(accountId) {
|
|
4601
|
+
const page = accountPages.get(accountId);
|
|
4602
|
+
if (!page || page.isClosed()) {
|
|
4603
|
+
return { success: false, error: "Account page not active" };
|
|
4604
|
+
}
|
|
4605
|
+
const { getValidAuthSession: getValidAuthSession2, saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4606
|
+
const session = getValidAuthSession2(accountId);
|
|
4607
|
+
let refreshToken = session?.refreshToken;
|
|
4608
|
+
if (!refreshToken) {
|
|
4609
|
+
try {
|
|
4610
|
+
refreshToken = await page.evaluate(() => localStorage.getItem("refresh_token") || "") || void 0;
|
|
4611
|
+
} catch {
|
|
4612
|
+
}
|
|
4613
|
+
}
|
|
4614
|
+
if (refreshToken) {
|
|
4615
|
+
try {
|
|
4616
|
+
const refreshResult = await page.evaluate(
|
|
4617
|
+
async ({ rTok }) => {
|
|
4618
|
+
try {
|
|
4619
|
+
const response = await fetch("https://auth.qwen.ai/api/v2/auths/refresh", {
|
|
4620
|
+
method: "GET",
|
|
4621
|
+
credentials: "include",
|
|
4622
|
+
headers: {
|
|
4623
|
+
accept: "application/json, text/plain, */*",
|
|
4624
|
+
source: "web",
|
|
4625
|
+
version: "0.3.11",
|
|
4626
|
+
"x-request-origin": "https://chat.qwen.ai",
|
|
4627
|
+
timezone: (/* @__PURE__ */ new Date()).toString().split(" (")[0],
|
|
4628
|
+
authorization: `Bearer ${rTok}`
|
|
4629
|
+
}
|
|
4630
|
+
});
|
|
4631
|
+
const json2 = await response.json().catch(() => null);
|
|
4632
|
+
return { ok: response.ok, status: response.status, data: json2 };
|
|
4633
|
+
} catch (e) {
|
|
4634
|
+
return { ok: false, error: e.message };
|
|
4635
|
+
}
|
|
4636
|
+
},
|
|
4637
|
+
{ rTok: refreshToken }
|
|
4638
|
+
);
|
|
4639
|
+
const json = refreshResult?.data;
|
|
4640
|
+
if (json && json.success === true && json.data) {
|
|
4641
|
+
const newAccessToken = json.data.access_token || json.data.token;
|
|
4642
|
+
const newRefreshToken = json.data.refresh_token || refreshToken;
|
|
4643
|
+
if (newAccessToken) {
|
|
4644
|
+
await page.context().addCookies([
|
|
4645
|
+
{
|
|
4646
|
+
name: "token",
|
|
4647
|
+
value: newAccessToken,
|
|
4648
|
+
domain: ".qwen.ai",
|
|
4649
|
+
path: "/",
|
|
4650
|
+
expires: Math.floor(Date.now() / 1e3) + 31536e3,
|
|
4651
|
+
httpOnly: false,
|
|
4652
|
+
secure: true,
|
|
4653
|
+
sameSite: "Lax"
|
|
4654
|
+
}
|
|
4655
|
+
]);
|
|
4656
|
+
await page.evaluate(
|
|
4657
|
+
({ tok, rTok }) => {
|
|
4658
|
+
try {
|
|
4659
|
+
localStorage.removeItem("qwen_token_logged_out_marker");
|
|
4660
|
+
localStorage.setItem("token", tok);
|
|
4661
|
+
localStorage.setItem("access_token", tok);
|
|
4662
|
+
if (rTok) localStorage.setItem("refresh_token", rTok);
|
|
4663
|
+
document.cookie = `token=${encodeURIComponent(tok)}; path=/; domain=.qwen.ai; max-age=31536000`;
|
|
4664
|
+
} catch {
|
|
4665
|
+
}
|
|
4666
|
+
},
|
|
4667
|
+
{ tok: newAccessToken, rTok: newRefreshToken }
|
|
4668
|
+
).catch(() => {
|
|
4669
|
+
});
|
|
4670
|
+
const liveCookies = await page.context().cookies();
|
|
4671
|
+
const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
|
|
4672
|
+
const cache = getHeaderCache(accountId);
|
|
4673
|
+
cache.headers.cookie = cookieStr;
|
|
4674
|
+
cache.lastRefresh = Date.now();
|
|
4675
|
+
markAccountHeadersReady(accountId);
|
|
4676
|
+
saveAuthSession2(accountId, {
|
|
4677
|
+
cookie: cookieStr,
|
|
4678
|
+
userAgent: cache.headers["user-agent"] || session?.userAgent || "",
|
|
4679
|
+
bxV: cache.headers["bx-v"] || session?.bxV || "2.5.37",
|
|
4680
|
+
bxUa: cache.headers["bx-ua"] || session?.bxUa || "",
|
|
4681
|
+
bxUmidtoken: cache.headers["bx-umidtoken"] || session?.bxUmidtoken || "",
|
|
4682
|
+
secChUa: cache.headers["sec-ch-ua"] || session?.secChUa,
|
|
4683
|
+
secChUaMobile: cache.headers["sec-ch-ua-mobile"] || session?.secChUaMobile,
|
|
4684
|
+
secChUaPlatform: cache.headers["sec-ch-ua-platform"] || session?.secChUaPlatform,
|
|
4685
|
+
version: cache.headers["version"] || session?.version,
|
|
4686
|
+
userId: session?.userId,
|
|
4687
|
+
tokenExpiresAt: parseJwtExpiry(newAccessToken) || void 0,
|
|
4688
|
+
refreshToken: newRefreshToken,
|
|
4689
|
+
capturedAt: Date.now()
|
|
4690
|
+
});
|
|
4691
|
+
return { success: true, token: newAccessToken };
|
|
4692
|
+
}
|
|
4693
|
+
}
|
|
4694
|
+
} catch {
|
|
4695
|
+
}
|
|
4696
|
+
}
|
|
4697
|
+
const { getAccountCredentials: getAccountCredentials2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
|
|
4698
|
+
const creds = getAccountCredentials2(accountId);
|
|
4699
|
+
if (creds && creds.email && creds.password) {
|
|
4700
|
+
const apiResult = await loginViaApi(page, creds.email, creds.password);
|
|
4701
|
+
if (apiResult.success) {
|
|
4702
|
+
const liveCookies = await page.context().cookies();
|
|
4703
|
+
const tokenCookie = liveCookies.find((c) => c.name === "token");
|
|
4704
|
+
if (tokenCookie) {
|
|
4705
|
+
const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
|
|
4706
|
+
const cache = getHeaderCache(accountId);
|
|
4707
|
+
cache.headers.cookie = cookieStr;
|
|
4708
|
+
cache.lastRefresh = Date.now();
|
|
4709
|
+
markAccountHeadersReady(accountId);
|
|
4710
|
+
saveAuthSession2(accountId, {
|
|
4711
|
+
cookie: cookieStr,
|
|
4712
|
+
userAgent: cache.headers["user-agent"] || session?.userAgent || "",
|
|
4713
|
+
bxV: cache.headers["bx-v"] || session?.bxV || "2.5.37",
|
|
4714
|
+
bxUa: cache.headers["bx-ua"] || session?.bxUa || "",
|
|
4715
|
+
bxUmidtoken: cache.headers["bx-umidtoken"] || session?.bxUmidtoken || "",
|
|
4716
|
+
secChUa: cache.headers["sec-ch-ua"] || session?.secChUa,
|
|
4717
|
+
secChUaMobile: cache.headers["sec-ch-ua-mobile"] || session?.secChUaMobile,
|
|
4718
|
+
secChUaPlatform: cache.headers["sec-ch-ua-platform"] || session?.secChUaPlatform,
|
|
4719
|
+
version: cache.headers["version"] || session?.version,
|
|
4720
|
+
userId: session?.userId,
|
|
4721
|
+
tokenExpiresAt: parseJwtExpiry(tokenCookie.value) || void 0,
|
|
4722
|
+
refreshToken: apiResult.refreshToken,
|
|
4723
|
+
capturedAt: Date.now()
|
|
4724
|
+
});
|
|
4725
|
+
return { success: true, token: tokenCookie.value };
|
|
4726
|
+
}
|
|
4727
|
+
}
|
|
4728
|
+
}
|
|
4729
|
+
return { success: false, error: "Could not refresh or re-authenticate token" };
|
|
4730
|
+
}
|
|
4532
4731
|
async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.timeouts.headers, triggerGraceMs = HEADER_CAPTURE_TRIGGER_GRACE_MS) {
|
|
4533
4732
|
const page = pageOverride ?? accountPages.get(accountId);
|
|
4534
4733
|
if (!page || page.isClosed()) {
|
|
@@ -4682,6 +4881,11 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
|
|
|
4682
4881
|
const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4683
4882
|
const { parseJwtExpiry: parseJwtExpiry2 } = await Promise.resolve().then(() => (init_jwt(), jwt_exports));
|
|
4684
4883
|
const tokenExpiry = parseJwtExpiry2(capturedHeaders.cookie);
|
|
4884
|
+
let rTok;
|
|
4885
|
+
try {
|
|
4886
|
+
rTok = (await page.evaluate(() => localStorage.getItem("refresh_token") || "")).trim() || void 0;
|
|
4887
|
+
} catch {
|
|
4888
|
+
}
|
|
4685
4889
|
saveAuthSession2(accountId, {
|
|
4686
4890
|
cookie: capturedHeaders.cookie,
|
|
4687
4891
|
userAgent: capturedHeaders["user-agent"],
|
|
@@ -4693,6 +4897,7 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
|
|
|
4693
4897
|
secChUaPlatform: capturedHeaders["sec-ch-ua-platform"],
|
|
4694
4898
|
version: capturedHeaders["version"],
|
|
4695
4899
|
tokenExpiresAt: tokenExpiry || void 0,
|
|
4900
|
+
refreshToken: rTok,
|
|
4696
4901
|
capturedAt: Date.now()
|
|
4697
4902
|
});
|
|
4698
4903
|
} catch {
|
|
@@ -4724,38 +4929,57 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
|
|
|
4724
4929
|
const isAuthUrl = currentUrl.includes("/auth") || currentUrl.includes("/login");
|
|
4725
4930
|
const isSuspectedGuest = isAuthUrl || attempt >= 2 && !await isPageLoggedIn(page, 5e3);
|
|
4726
4931
|
if (isSuspectedGuest) {
|
|
4727
|
-
const
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
`\u26A0\uFE0F [Playwright] Session expired or guest state detected during header capture for ${accountId}; re-authenticating...`
|
|
4932
|
+
const silentRefresh = await refreshAccountToken(accountId);
|
|
4933
|
+
if (silentRefresh.success) {
|
|
4934
|
+
console.log(
|
|
4935
|
+
`\u26A1 [Playwright] Token refreshed silently during header capture for ${accountId}`
|
|
4732
4936
|
);
|
|
4733
|
-
|
|
4734
|
-
const ok = await loginToQwen(accountId, creds.email, creds.password);
|
|
4735
|
-
if (ok) {
|
|
4937
|
+
if (isAuthUrl) {
|
|
4736
4938
|
await page.goto(qwenUrl("/"), {
|
|
4737
4939
|
waitUntil: "domcontentloaded",
|
|
4738
4940
|
timeout: Math.min(config.timeouts.navigation, timeoutMs)
|
|
4739
4941
|
});
|
|
4740
|
-
await sleep2(
|
|
4942
|
+
await sleep2(1500);
|
|
4943
|
+
}
|
|
4944
|
+
if (await isPageLoggedIn(page, 5e3)) {
|
|
4945
|
+
armOverallDeadline();
|
|
4741
4946
|
}
|
|
4742
|
-
|
|
4947
|
+
}
|
|
4948
|
+
const stillSuspected = !silentRefresh.success || !await isPageLoggedIn(page, 2e3);
|
|
4949
|
+
if (stillSuspected) {
|
|
4950
|
+
const { getAccountCredentials: getAccountCredentials2 } = await Promise.resolve().then(() => (init_accounts(), accounts_exports));
|
|
4951
|
+
const creds = getAccountCredentials2(accountId);
|
|
4952
|
+
if (creds && creds.email && creds.password) {
|
|
4953
|
+
console.warn(
|
|
4954
|
+
`\u26A0\uFE0F [Playwright] Session expired or guest state detected during header capture for ${accountId}; re-authenticating...`
|
|
4955
|
+
);
|
|
4956
|
+
armOverallDeadline();
|
|
4957
|
+
const ok = await loginToQwen(accountId, creds.email, creds.password);
|
|
4958
|
+
if (ok) {
|
|
4959
|
+
await page.goto(qwenUrl("/"), {
|
|
4960
|
+
waitUntil: "domcontentloaded",
|
|
4961
|
+
timeout: Math.min(config.timeouts.navigation, timeoutMs)
|
|
4962
|
+
});
|
|
4963
|
+
await sleep2(2e3);
|
|
4964
|
+
}
|
|
4965
|
+
if (!ok || !await isPageLoggedIn(page, 6e3)) {
|
|
4966
|
+
settle(
|
|
4967
|
+
new Error(
|
|
4968
|
+
`Header capture failed for ${accountId}: re-login after session expiry did not succeed`
|
|
4969
|
+
)
|
|
4970
|
+
);
|
|
4971
|
+
return;
|
|
4972
|
+
}
|
|
4973
|
+
armOverallDeadline();
|
|
4974
|
+
if (settled || page.isClosed()) return;
|
|
4975
|
+
} else {
|
|
4743
4976
|
settle(
|
|
4744
4977
|
new Error(
|
|
4745
|
-
`Header capture failed for ${accountId}: re-login
|
|
4978
|
+
`Header capture failed for ${accountId}: session expired and no credentials available for re-login (run 'qpx login')`
|
|
4746
4979
|
)
|
|
4747
4980
|
);
|
|
4748
4981
|
return;
|
|
4749
4982
|
}
|
|
4750
|
-
armOverallDeadline();
|
|
4751
|
-
if (settled || page.isClosed()) return;
|
|
4752
|
-
} else {
|
|
4753
|
-
settle(
|
|
4754
|
-
new Error(
|
|
4755
|
-
`Header capture failed for ${accountId}: session expired and no credentials available for re-login (run 'qpx login')`
|
|
4756
|
-
)
|
|
4757
|
-
);
|
|
4758
|
-
return;
|
|
4759
4983
|
}
|
|
4760
4984
|
}
|
|
4761
4985
|
if (settled || page.isClosed()) return;
|
|
@@ -5245,6 +5469,7 @@ function cleanupPlaywrightAccountState(accountId) {
|
|
|
5245
5469
|
cookieCaches.delete(accountId);
|
|
5246
5470
|
lastAccountActivity.delete(accountId);
|
|
5247
5471
|
lastKeepAliveNavigation.delete(accountId);
|
|
5472
|
+
lastProactiveTokenRefresh.delete(accountId);
|
|
5248
5473
|
clearFingerprintCache(accountId);
|
|
5249
5474
|
unmarkAccountHeadersReady(accountId);
|
|
5250
5475
|
}
|
|
@@ -5319,7 +5544,7 @@ async function closePlaywrightForAccount(accountId) {
|
|
|
5319
5544
|
release();
|
|
5320
5545
|
}
|
|
5321
5546
|
}
|
|
5322
|
-
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;
|
|
5547
|
+
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;
|
|
5323
5548
|
var init_playwright = __esm({
|
|
5324
5549
|
"src/services/playwright.ts"() {
|
|
5325
5550
|
"use strict";
|
|
@@ -5351,6 +5576,7 @@ var init_playwright = __esm({
|
|
|
5351
5576
|
cookieCaches = /* @__PURE__ */ new Map();
|
|
5352
5577
|
lastAccountActivity = /* @__PURE__ */ new Map();
|
|
5353
5578
|
lastKeepAliveNavigation = /* @__PURE__ */ new Map();
|
|
5579
|
+
lastProactiveTokenRefresh = /* @__PURE__ */ new Map();
|
|
5354
5580
|
profileResetQueue = /* @__PURE__ */ new Map();
|
|
5355
5581
|
profileResetChain = Promise.resolve();
|
|
5356
5582
|
closingAllPlaywright = false;
|
package/dist/sync-clients.js
CHANGED
|
@@ -183,11 +183,11 @@ var envSchema = z.object({
|
|
|
183
183
|
// nothing in this window is dead and should fail fast, retryable).
|
|
184
184
|
QWEN_FIRST_CHUNK_TIMEOUT: z.string().default("60000"),
|
|
185
185
|
TOTAL_REQUEST_TIMEOUT: z.string().default("600000"),
|
|
186
|
-
// Mid-stream silence window for thinking models:
|
|
186
|
+
// Mid-stream silence window for thinking models: 5 min with ZERO upstream
|
|
187
187
|
// bytes is a dead stream (WAF swallow / dropped connection) — fail fast and
|
|
188
188
|
// let the retry policy rotate accounts. Flowing reasoning chunks RESET this
|
|
189
189
|
// timer, so legitimate slow thinking is never cut; only total silence is.
|
|
190
|
-
REASONING_MODEL_TIMEOUT: z.string().default("
|
|
190
|
+
REASONING_MODEL_TIMEOUT: z.string().default("300000"),
|
|
191
191
|
CACHE_TTL: z.string().default("3600"),
|
|
192
192
|
RESPONSE_TTL: z.string().default("1800"),
|
|
193
193
|
CACHE_COMPRESSION_ENABLED: z.string().default("true"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qwenproxy-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
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": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"reset": "npx tsx src/reset-cooldowns.ts",
|
|
30
30
|
"purge": "npx tsx src/delete-chats.ts",
|
|
31
31
|
"test": "npm run test:mock && npm run test:live",
|
|
32
|
-
"test:mock": "tsx --test --test-concurrency=1 --env-file=.env.test src/tests/account-concurrency.test.ts src/tests/concurrency-latest-wins.test.ts src/tests/mutex.test.ts src/tests/context-truncation.test.ts src/tests/streaming-thinking-summary.test.ts src/tests/tool-call-guard.test.ts src/tests/utils-logger-full.test.ts src/tests/logger-toolcall-errors.test.ts src/tests/logger-toolcall-disabled.test.ts src/tests/utils-json-full.test.ts src/tests/utils-session-guard-full.test.ts src/tests/core-logic-full.test.ts src/tests/core-logic-accounts.test.ts src/tests/chat-validation-full.test.ts src/tests/chat-logic-full.test.ts src/tests/account-stickiness.test.ts src/tests/accounts-security.test.ts src/tests/advanced.test.ts src/tests/auth-playwright.test.ts src/tests/auth-session-persistence.test.ts src/tests/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.test.ts src/tests/chat-cleanup-auto.test.ts src/tests/chromium-args.test.ts src/tests/config-current.test.ts src/tests/context-meter.test.ts src/tests/concurrency.test.ts src/tests/delta.test.ts src/tests/fingerprint.test.ts src/tests/human-behavior.test.ts src/tests/index.test.ts src/tests/json-recovery.test.ts src/tests/jsonFix.test.ts src/tests/memory-cache.test.ts src/tests/model-alias.test.ts src/tests/model-registry-thinking.test.ts src/tests/models-endpoint.test.ts src/tests/multimodal.test.ts src/tests/oss-upload.test.ts src/tests/parser.test.ts src/tests/personalization-flow.test.ts src/tests/personalization-required.test.ts src/tests/retry-policy.test.ts src/tests/rotation.test.ts src/tests/server-lifecycle.test.ts src/tests/session-keeper.test.ts src/tests/session-state.test.ts src/tests/single-account-mode.test.ts src/tests/stream-retry.test.ts src/tests/tool-calls-endpoint.test.ts src/tests/tool-instructions-cache.test.ts src/tests/session-id.test.ts src/tests/watchdog-ram.test.ts src/tests/tool-recovery-t1t2.test.ts src/tests/abort-silent-t4.test.ts src/tests/t3-close-tag-escape.test.ts src/tests/t5-tool-cap.test.ts src/tests/logger-redaction.test.ts src/tests/stall-timeout-retryable.test.ts src/tests/t6-missing-quote-array-close.test.ts src/tests/watchdog-rss.test.ts src/tests/logical-thread-batch.test.ts src/tests/chat-pool-style.test.ts src/tests/queue-wait-cap.test.ts src/tests/context-eviction-order.test.ts src/tests/chat-in-progress-settle.test.ts src/tests/stream-lock-leak.test.ts src/tests/stream-semaphore.test.ts src/tests/waf-isolation.test.ts src/tests/legacy-completions.test.ts src/tests/response-format.test.ts src/tests/cors-headers.test.ts src/tests/local-auth.test.ts src/tests/safe-remote-url.test.ts src/tests/stream-lock-terminal-cancel.test.ts src/tests/parser-truncated-tool-call.test.ts src/tests/metrics-prometheus.test.ts src/tests/context-death-cleanup.test.ts src/tests/personalization-direct-fetch.test.ts src/tests/completion-headers-parity.test.ts src/tests/parallel-escape-repro.test.ts src/tests/chat-in-progress-scale-cost.test.ts src/tests/temp-chat-mode.test.ts src/tests/profile-reset.test.ts src/tests/error-classification.test.ts src/tests/quota-cooldown.test.ts src/tests/account-ready-gate.test.ts src/tests/tool-cap-notice.test.ts src/tests/interaction-flows.test.ts src/tests/headers-gate-cooldown-fallback.test.ts src/tests/unwrapped-tool-calls.test.ts src/tests/anthropic.test.ts src/tests/sync-clients.test.ts src/tests/sync-top10-clients.test.ts src/tests/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts src/tests/tui-settings.test.ts src/tests/personalization-deadline.test.ts src/tests/update-cli.test.ts src/tests/batch-accounts.test.ts src/tests/shared-browser.test.ts src/tests/auth-credential-classification.test.ts src/tests/responses-api.test.ts src/tests/media-generation.test.ts src/tests/infer-tool-name.test.ts src/tests/native-session-headers.test.ts src/tests/omni-thinking.test.ts src/tests/protect-stuck-mutex.test.ts src/tests/stream-error-notice.test.ts src/tests/parser-deep-coverage.test.ts src/tests/tui-logs-copy.test.ts src/tests/auth-jwt-and-validation.test.ts src/tests/tui-port-and-key-modal.test.ts src/tests/verify-zero-fake-cooldown.test.ts",
|
|
33
|
-
"test:mock:fast": "tsx --test --test-concurrency=2 --env-file=.env.test src/tests/account-concurrency.test.ts src/tests/concurrency-latest-wins.test.ts src/tests/mutex.test.ts src/tests/context-truncation.test.ts src/tests/streaming-thinking-summary.test.ts src/tests/tool-call-guard.test.ts src/tests/utils-logger-full.test.ts src/tests/logger-toolcall-errors.test.ts src/tests/logger-toolcall-disabled.test.ts src/tests/utils-json-full.test.ts src/tests/utils-session-guard-full.test.ts src/tests/core-logic-full.test.ts src/tests/core-logic-accounts.test.ts src/tests/chat-validation-full.test.ts src/tests/chat-logic-full.test.ts src/tests/account-stickiness.test.ts src/tests/accounts-security.test.ts src/tests/advanced.test.ts src/tests/auth-playwright.test.ts src/tests/auth-session-persistence.test.ts src/tests/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.test.ts src/tests/chat-cleanup-auto.test.ts src/tests/chromium-args.test.ts src/tests/config-current.test.ts src/tests/context-meter.test.ts src/tests/concurrency.test.ts src/tests/delta.test.ts src/tests/fingerprint.test.ts src/tests/human-behavior.test.ts src/tests/index.test.ts src/tests/json-recovery.test.ts src/tests/jsonFix.test.ts src/tests/memory-cache.test.ts src/tests/model-alias.test.ts src/tests/model-registry-thinking.test.ts src/tests/models-endpoint.test.ts src/tests/multimodal.test.ts src/tests/oss-upload.test.ts src/tests/parser.test.ts src/tests/personalization-flow.test.ts src/tests/personalization-required.test.ts src/tests/retry-policy.test.ts src/tests/rotation.test.ts src/tests/server-lifecycle.test.ts src/tests/session-keeper.test.ts src/tests/session-state.test.ts src/tests/single-account-mode.test.ts src/tests/stream-retry.test.ts src/tests/tool-calls-endpoint.test.ts src/tests/tool-instructions-cache.test.ts src/tests/session-id.test.ts src/tests/watchdog-ram.test.ts src/tests/tool-recovery-t1t2.test.ts src/tests/abort-silent-t4.test.ts src/tests/t3-close-tag-escape.test.ts src/tests/t5-tool-cap.test.ts src/tests/logger-redaction.test.ts src/tests/stall-timeout-retryable.test.ts src/tests/t6-missing-quote-array-close.test.ts src/tests/watchdog-rss.test.ts src/tests/logical-thread-batch.test.ts src/tests/chat-pool-style.test.ts src/tests/queue-wait-cap.test.ts src/tests/context-eviction-order.test.ts src/tests/chat-in-progress-settle.test.ts src/tests/stream-lock-leak.test.ts src/tests/stream-semaphore.test.ts src/tests/waf-isolation.test.ts src/tests/legacy-completions.test.ts src/tests/response-format.test.ts src/tests/cors-headers.test.ts src/tests/local-auth.test.ts src/tests/safe-remote-url.test.ts src/tests/stream-lock-terminal-cancel.test.ts src/tests/parser-truncated-tool-call.test.ts src/tests/metrics-prometheus.test.ts src/tests/context-death-cleanup.test.ts src/tests/personalization-direct-fetch.test.ts src/tests/completion-headers-parity.test.ts src/tests/parallel-escape-repro.test.ts src/tests/chat-in-progress-scale-cost.test.ts src/tests/temp-chat-mode.test.ts src/tests/profile-reset.test.ts src/tests/error-classification.test.ts src/tests/quota-cooldown.test.ts src/tests/account-ready-gate.test.ts src/tests/tool-cap-notice.test.ts src/tests/interaction-flows.test.ts src/tests/headers-gate-cooldown-fallback.test.ts src/tests/unwrapped-tool-calls.test.ts src/tests/anthropic.test.ts src/tests/sync-clients.test.ts src/tests/sync-top10-clients.test.ts src/tests/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts src/tests/tui-settings.test.ts src/tests/personalization-deadline.test.ts src/tests/update-cli.test.ts src/tests/batch-accounts.test.ts src/tests/shared-browser.test.ts src/tests/auth-credential-classification.test.ts src/tests/responses-api.test.ts src/tests/media-generation.test.ts src/tests/infer-tool-name.test.ts src/tests/native-session-headers.test.ts src/tests/omni-thinking.test.ts src/tests/protect-stuck-mutex.test.ts src/tests/stream-error-notice.test.ts src/tests/parser-deep-coverage.test.ts src/tests/tui-logs-copy.test.ts src/tests/auth-jwt-and-validation.test.ts src/tests/tui-port-and-key-modal.test.ts src/tests/verify-zero-fake-cooldown.test.ts",
|
|
32
|
+
"test:mock": "tsx --test --test-concurrency=1 --env-file=.env.test src/tests/account-concurrency.test.ts src/tests/concurrency-latest-wins.test.ts src/tests/mutex.test.ts src/tests/context-truncation.test.ts src/tests/streaming-thinking-summary.test.ts src/tests/tool-call-guard.test.ts src/tests/utils-logger-full.test.ts src/tests/logger-toolcall-errors.test.ts src/tests/logger-toolcall-disabled.test.ts src/tests/utils-json-full.test.ts src/tests/utils-session-guard-full.test.ts src/tests/core-logic-full.test.ts src/tests/core-logic-accounts.test.ts src/tests/chat-validation-full.test.ts src/tests/chat-logic-full.test.ts src/tests/account-stickiness.test.ts src/tests/accounts-security.test.ts src/tests/advanced.test.ts src/tests/auth-playwright.test.ts src/tests/auth-session-persistence.test.ts src/tests/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.test.ts src/tests/chat-cleanup-auto.test.ts src/tests/chromium-args.test.ts src/tests/config-current.test.ts src/tests/context-meter.test.ts src/tests/concurrency.test.ts src/tests/delta.test.ts src/tests/fingerprint.test.ts src/tests/human-behavior.test.ts src/tests/index.test.ts src/tests/json-recovery.test.ts src/tests/jsonFix.test.ts src/tests/memory-cache.test.ts src/tests/model-alias.test.ts src/tests/model-registry-thinking.test.ts src/tests/models-endpoint.test.ts src/tests/multimodal.test.ts src/tests/oss-upload.test.ts src/tests/parser.test.ts src/tests/personalization-flow.test.ts src/tests/personalization-required.test.ts src/tests/retry-policy.test.ts src/tests/rotation.test.ts src/tests/server-lifecycle.test.ts src/tests/session-keeper.test.ts src/tests/session-state.test.ts src/tests/single-account-mode.test.ts src/tests/stream-retry.test.ts src/tests/tool-calls-endpoint.test.ts src/tests/tool-instructions-cache.test.ts src/tests/session-id.test.ts src/tests/watchdog-ram.test.ts src/tests/tool-recovery-t1t2.test.ts src/tests/abort-silent-t4.test.ts src/tests/t3-close-tag-escape.test.ts src/tests/t5-tool-cap.test.ts src/tests/logger-redaction.test.ts src/tests/stall-timeout-retryable.test.ts src/tests/t6-missing-quote-array-close.test.ts src/tests/watchdog-rss.test.ts src/tests/logical-thread-batch.test.ts src/tests/chat-pool-style.test.ts src/tests/queue-wait-cap.test.ts src/tests/context-eviction-order.test.ts src/tests/chat-in-progress-settle.test.ts src/tests/stream-lock-leak.test.ts src/tests/stream-semaphore.test.ts src/tests/waf-isolation.test.ts src/tests/legacy-completions.test.ts src/tests/response-format.test.ts src/tests/cors-headers.test.ts src/tests/local-auth.test.ts src/tests/safe-remote-url.test.ts src/tests/stream-lock-terminal-cancel.test.ts src/tests/parser-truncated-tool-call.test.ts src/tests/metrics-prometheus.test.ts src/tests/context-death-cleanup.test.ts src/tests/personalization-direct-fetch.test.ts src/tests/completion-headers-parity.test.ts src/tests/parallel-escape-repro.test.ts src/tests/chat-in-progress-scale-cost.test.ts src/tests/temp-chat-mode.test.ts src/tests/profile-reset.test.ts src/tests/error-classification.test.ts src/tests/quota-cooldown.test.ts src/tests/account-ready-gate.test.ts src/tests/tool-cap-notice.test.ts src/tests/interaction-flows.test.ts src/tests/headers-gate-cooldown-fallback.test.ts src/tests/unwrapped-tool-calls.test.ts src/tests/anthropic.test.ts src/tests/sync-clients.test.ts src/tests/sync-top10-clients.test.ts src/tests/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts src/tests/tui-settings.test.ts src/tests/personalization-deadline.test.ts src/tests/update-cli.test.ts src/tests/batch-accounts.test.ts src/tests/shared-browser.test.ts src/tests/auth-credential-classification.test.ts src/tests/responses-api.test.ts src/tests/media-generation.test.ts src/tests/infer-tool-name.test.ts src/tests/native-session-headers.test.ts src/tests/omni-thinking.test.ts src/tests/protect-stuck-mutex.test.ts src/tests/stream-error-notice.test.ts src/tests/parser-deep-coverage.test.ts src/tests/tui-logs-copy.test.ts src/tests/auth-jwt-and-validation.test.ts src/tests/tui-port-and-key-modal.test.ts src/tests/verify-zero-fake-cooldown.test.ts src/tests/auth-session-refresh-preservation.test.ts src/tests/personalization-in-flight-dedup.test.ts src/tests/daily-usage.test.ts src/tests/resilience-enhancements.test.ts src/tests/pool-quota-failover.test.ts",
|
|
33
|
+
"test:mock:fast": "tsx --test --test-concurrency=2 --env-file=.env.test src/tests/account-concurrency.test.ts src/tests/concurrency-latest-wins.test.ts src/tests/mutex.test.ts src/tests/context-truncation.test.ts src/tests/streaming-thinking-summary.test.ts src/tests/tool-call-guard.test.ts src/tests/utils-logger-full.test.ts src/tests/logger-toolcall-errors.test.ts src/tests/logger-toolcall-disabled.test.ts src/tests/utils-json-full.test.ts src/tests/utils-session-guard-full.test.ts src/tests/core-logic-full.test.ts src/tests/core-logic-accounts.test.ts src/tests/chat-validation-full.test.ts src/tests/chat-logic-full.test.ts src/tests/account-stickiness.test.ts src/tests/accounts-security.test.ts src/tests/advanced.test.ts src/tests/auth-playwright.test.ts src/tests/auth-session-persistence.test.ts src/tests/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.test.ts src/tests/chat-cleanup-auto.test.ts src/tests/chromium-args.test.ts src/tests/config-current.test.ts src/tests/context-meter.test.ts src/tests/concurrency.test.ts src/tests/delta.test.ts src/tests/fingerprint.test.ts src/tests/human-behavior.test.ts src/tests/index.test.ts src/tests/json-recovery.test.ts src/tests/jsonFix.test.ts src/tests/memory-cache.test.ts src/tests/model-alias.test.ts src/tests/model-registry-thinking.test.ts src/tests/models-endpoint.test.ts src/tests/multimodal.test.ts src/tests/oss-upload.test.ts src/tests/parser.test.ts src/tests/personalization-flow.test.ts src/tests/personalization-required.test.ts src/tests/retry-policy.test.ts src/tests/rotation.test.ts src/tests/server-lifecycle.test.ts src/tests/session-keeper.test.ts src/tests/session-state.test.ts src/tests/single-account-mode.test.ts src/tests/stream-retry.test.ts src/tests/tool-calls-endpoint.test.ts src/tests/tool-instructions-cache.test.ts src/tests/session-id.test.ts src/tests/watchdog-ram.test.ts src/tests/tool-recovery-t1t2.test.ts src/tests/abort-silent-t4.test.ts src/tests/t3-close-tag-escape.test.ts src/tests/t5-tool-cap.test.ts src/tests/logger-redaction.test.ts src/tests/stall-timeout-retryable.test.ts src/tests/t6-missing-quote-array-close.test.ts src/tests/watchdog-rss.test.ts src/tests/logical-thread-batch.test.ts src/tests/chat-pool-style.test.ts src/tests/queue-wait-cap.test.ts src/tests/context-eviction-order.test.ts src/tests/chat-in-progress-settle.test.ts src/tests/stream-lock-leak.test.ts src/tests/stream-semaphore.test.ts src/tests/waf-isolation.test.ts src/tests/legacy-completions.test.ts src/tests/response-format.test.ts src/tests/cors-headers.test.ts src/tests/local-auth.test.ts src/tests/safe-remote-url.test.ts src/tests/stream-lock-terminal-cancel.test.ts src/tests/parser-truncated-tool-call.test.ts src/tests/metrics-prometheus.test.ts src/tests/context-death-cleanup.test.ts src/tests/personalization-direct-fetch.test.ts src/tests/completion-headers-parity.test.ts src/tests/parallel-escape-repro.test.ts src/tests/chat-in-progress-scale-cost.test.ts src/tests/temp-chat-mode.test.ts src/tests/profile-reset.test.ts src/tests/error-classification.test.ts src/tests/quota-cooldown.test.ts src/tests/account-ready-gate.test.ts src/tests/tool-cap-notice.test.ts src/tests/interaction-flows.test.ts src/tests/headers-gate-cooldown-fallback.test.ts src/tests/unwrapped-tool-calls.test.ts src/tests/anthropic.test.ts src/tests/sync-clients.test.ts src/tests/sync-top10-clients.test.ts src/tests/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts src/tests/tui-settings.test.ts src/tests/personalization-deadline.test.ts src/tests/update-cli.test.ts src/tests/batch-accounts.test.ts src/tests/shared-browser.test.ts src/tests/auth-credential-classification.test.ts src/tests/responses-api.test.ts src/tests/media-generation.test.ts src/tests/infer-tool-name.test.ts src/tests/native-session-headers.test.ts src/tests/omni-thinking.test.ts src/tests/protect-stuck-mutex.test.ts src/tests/stream-error-notice.test.ts src/tests/parser-deep-coverage.test.ts src/tests/tui-logs-copy.test.ts src/tests/auth-jwt-and-validation.test.ts src/tests/tui-port-and-key-modal.test.ts src/tests/verify-zero-fake-cooldown.test.ts src/tests/auth-session-refresh-preservation.test.ts src/tests/personalization-in-flight-dedup.test.ts src/tests/daily-usage.test.ts src/tests/resilience-enhancements.test.ts src/tests/pool-quota-failover.test.ts",
|
|
34
34
|
"test:live": "tsx --test src/tests/concurrentChat.test.ts src/tests/agenticStress.test.ts",
|
|
35
35
|
"test:stress": "npx tsx src/benchmarks/stress-test.ts",
|
|
36
36
|
"test:stress:personalization": "npx tsx src/benchmarks/stress-test-personalization.ts",
|
package/src/api/server.ts
CHANGED
|
@@ -371,6 +371,7 @@ app.get("/health", async (c) => {
|
|
|
371
371
|
captchasSolved: Number(metrics.get("captcha.solves.succeeded")?.value ?? 0),
|
|
372
372
|
chatsCleaned: Number(metrics.get("chats.cleaned")?.value ?? 0),
|
|
373
373
|
},
|
|
374
|
+
dailyUsage: (await import("../core/daily-usage.ts")).getPoolDailyUsageSummary(),
|
|
374
375
|
});
|
|
375
376
|
});
|
|
376
377
|
|
package/src/clean-cache.ts
CHANGED
|
@@ -4,6 +4,9 @@ import path from "node:path";
|
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import { chromium } from "patchright";
|
|
6
6
|
import { pruneAllPlaywrightProfiles, cleanupOrphanProfiles } from "./services/playwright.ts";
|
|
7
|
+
import { installProcessTeardownGuards } from "./core/process-guard.ts";
|
|
8
|
+
|
|
9
|
+
installProcessTeardownGuards("CleanCache");
|
|
7
10
|
|
|
8
11
|
export function formatBytes(bytes: number): string {
|
|
9
12
|
if (bytes < 1024) return `${bytes} B`;
|
package/src/core/config.ts
CHANGED
|
@@ -102,11 +102,11 @@ const envSchema = z
|
|
|
102
102
|
// nothing in this window is dead and should fail fast, retryable).
|
|
103
103
|
QWEN_FIRST_CHUNK_TIMEOUT: z.string().default("60000"),
|
|
104
104
|
TOTAL_REQUEST_TIMEOUT: z.string().default("600000"),
|
|
105
|
-
// Mid-stream silence window for thinking models:
|
|
105
|
+
// Mid-stream silence window for thinking models: 5 min with ZERO upstream
|
|
106
106
|
// bytes is a dead stream (WAF swallow / dropped connection) — fail fast and
|
|
107
107
|
// let the retry policy rotate accounts. Flowing reasoning chunks RESET this
|
|
108
108
|
// timer, so legitimate slow thinking is never cut; only total silence is.
|
|
109
|
-
REASONING_MODEL_TIMEOUT: z.string().default("
|
|
109
|
+
REASONING_MODEL_TIMEOUT: z.string().default("300000"),
|
|
110
110
|
CACHE_TTL: z.string().default("3600"),
|
|
111
111
|
RESPONSE_TTL: z.string().default("1800"),
|
|
112
112
|
CACHE_COMPRESSION_ENABLED: z.string().default("true"),
|