qwenproxy-cli 1.6.4 → 1.6.6
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 +84 -11
- package/dist/delete-chats.js +183 -45
- package/dist/index.js +267 -77
- package/dist/login.js +92 -16
- package/dist/reset-cooldowns.js +87 -12
- package/package.json +1 -1
- package/src/core/mutex.ts +4 -0
- package/src/core/version.ts +1 -1
- package/src/routes/anthropic/translate.ts +15 -7
- package/src/routes/chat/helpers.ts +4 -2
- package/src/routes/chat/streaming.ts +66 -31
- package/src/routes/responses/adapter.ts +4 -1
- package/src/services/context-meter.ts +1 -1
- package/src/services/playwright.ts +57 -20
- package/src/services/qwen-headers.ts +3 -2
- package/src/services/qwen.ts +87 -30
- package/src/tools/tool-call-heuristics.ts +88 -0
- package/src/utils/timezone.ts +56 -0
package/dist/clean-cache.js
CHANGED
|
@@ -1814,6 +1814,7 @@ var init_mutex = __esm({
|
|
|
1814
1814
|
locked = false;
|
|
1815
1815
|
lockedAt = 0;
|
|
1816
1816
|
lockedByKey = "";
|
|
1817
|
+
epoch = 0;
|
|
1817
1818
|
async acquire(timeoutMs = 3e5, key = "") {
|
|
1818
1819
|
const holdLimitMs = this.maxHoldMs;
|
|
1819
1820
|
if (this.locked && Date.now() - this.lockedAt > holdLimitMs) {
|
|
@@ -1824,6 +1825,7 @@ var init_mutex = __esm({
|
|
|
1824
1825
|
this.locked = false;
|
|
1825
1826
|
this.lockedAt = 0;
|
|
1826
1827
|
this.lockedByKey = "";
|
|
1828
|
+
this.epoch++;
|
|
1827
1829
|
}
|
|
1828
1830
|
if (!this.locked) {
|
|
1829
1831
|
this.locked = true;
|
|
@@ -1862,10 +1864,12 @@ var init_mutex = __esm({
|
|
|
1862
1864
|
}
|
|
1863
1865
|
}
|
|
1864
1866
|
createRelease() {
|
|
1867
|
+
const epoch = this.epoch;
|
|
1865
1868
|
let released = false;
|
|
1866
1869
|
return () => {
|
|
1867
1870
|
if (released) return;
|
|
1868
1871
|
released = true;
|
|
1872
|
+
if (epoch !== this.epoch) return;
|
|
1869
1873
|
this.release();
|
|
1870
1874
|
};
|
|
1871
1875
|
}
|
|
@@ -2673,6 +2677,45 @@ var init_waf_isolation = __esm({
|
|
|
2673
2677
|
}
|
|
2674
2678
|
});
|
|
2675
2679
|
|
|
2680
|
+
// src/utils/timezone.ts
|
|
2681
|
+
function formatAsciiTimezone(date = /* @__PURE__ */ new Date()) {
|
|
2682
|
+
const dayName = DAYS[date.getDay()];
|
|
2683
|
+
const monthName = MONTHS[date.getMonth()];
|
|
2684
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
2685
|
+
const year = date.getFullYear();
|
|
2686
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
2687
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
2688
|
+
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
2689
|
+
const offsetMinutes = -date.getTimezoneOffset();
|
|
2690
|
+
const sign = offsetMinutes >= 0 ? "+" : "-";
|
|
2691
|
+
const absOffset = Math.abs(offsetMinutes);
|
|
2692
|
+
const offsetHours = String(Math.floor(absOffset / 60)).padStart(2, "0");
|
|
2693
|
+
const offsetMins = String(absOffset % 60).padStart(2, "0");
|
|
2694
|
+
const tzOffset = `GMT${sign}${offsetHours}${offsetMins}`;
|
|
2695
|
+
return `${dayName} ${monthName} ${day} ${year} ${hours}:${minutes}:${seconds} ${tzOffset}`;
|
|
2696
|
+
}
|
|
2697
|
+
var DAYS, MONTHS;
|
|
2698
|
+
var init_timezone = __esm({
|
|
2699
|
+
"src/utils/timezone.ts"() {
|
|
2700
|
+
"use strict";
|
|
2701
|
+
DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
2702
|
+
MONTHS = [
|
|
2703
|
+
"Jan",
|
|
2704
|
+
"Feb",
|
|
2705
|
+
"Mar",
|
|
2706
|
+
"Apr",
|
|
2707
|
+
"May",
|
|
2708
|
+
"Jun",
|
|
2709
|
+
"Jul",
|
|
2710
|
+
"Aug",
|
|
2711
|
+
"Sep",
|
|
2712
|
+
"Oct",
|
|
2713
|
+
"Nov",
|
|
2714
|
+
"Dec"
|
|
2715
|
+
];
|
|
2716
|
+
}
|
|
2717
|
+
});
|
|
2718
|
+
|
|
2676
2719
|
// src/services/qwen-headers.ts
|
|
2677
2720
|
import { v4 as uuidv4 } from "uuid";
|
|
2678
2721
|
function getDefaultQwenUserAgent(major = getChromeMajor()) {
|
|
@@ -2690,6 +2733,7 @@ var init_qwen_headers = __esm({
|
|
|
2690
2733
|
init_qwen_url();
|
|
2691
2734
|
init_config();
|
|
2692
2735
|
init_fingerprint();
|
|
2736
|
+
init_timezone();
|
|
2693
2737
|
dynamicWebVersion = null;
|
|
2694
2738
|
QWEN_WEB_VERSION = config.qwen.webVersion;
|
|
2695
2739
|
DEFAULT_QWEN_USER_AGENT = getDefaultQwenUserAgent(151);
|
|
@@ -3544,6 +3588,13 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
3544
3588
|
await existingInit;
|
|
3545
3589
|
return;
|
|
3546
3590
|
}
|
|
3591
|
+
let resolveInit;
|
|
3592
|
+
let rejectInit;
|
|
3593
|
+
const inFlightDeferred = new Promise((res, rej) => {
|
|
3594
|
+
resolveInit = res;
|
|
3595
|
+
rejectInit = rej;
|
|
3596
|
+
});
|
|
3597
|
+
inFlightAccountInits.set(account.id, inFlightDeferred);
|
|
3547
3598
|
const initPromise = (async () => {
|
|
3548
3599
|
const release = await acquireAccountMutex(
|
|
3549
3600
|
account.id,
|
|
@@ -3758,6 +3809,22 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
3758
3809
|
}
|
|
3759
3810
|
}
|
|
3760
3811
|
}
|
|
3812
|
+
const currentCache = getHeaderCache(account.id);
|
|
3813
|
+
const currentCookie = currentCache?.headers?.cookie || "";
|
|
3814
|
+
if (currentCookie && isTokenExpiringSoon(currentCookie, 5)) {
|
|
3815
|
+
try {
|
|
3816
|
+
const refreshRes = await refreshAccountToken(account.id);
|
|
3817
|
+
if (refreshRes.success) {
|
|
3818
|
+
console.log(
|
|
3819
|
+
`\u26A1 [Playwright] Silently refreshed expired token restored from DB for ${maskEmail(account.email)}`
|
|
3820
|
+
);
|
|
3821
|
+
}
|
|
3822
|
+
} catch (err) {
|
|
3823
|
+
console.warn(
|
|
3824
|
+
`\u26A0\uFE0F [Playwright] Failed to proactively refresh expired token from DB for ${maskEmail(account.email)}: ${err?.message || err}`
|
|
3825
|
+
);
|
|
3826
|
+
}
|
|
3827
|
+
}
|
|
3761
3828
|
return;
|
|
3762
3829
|
}
|
|
3763
3830
|
const cookies = await acctContext.cookies();
|
|
@@ -3812,9 +3879,12 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
3812
3879
|
release();
|
|
3813
3880
|
}
|
|
3814
3881
|
})();
|
|
3815
|
-
inFlightAccountInits.set(account.id, initPromise);
|
|
3816
3882
|
try {
|
|
3817
3883
|
await initPromise;
|
|
3884
|
+
resolveInit();
|
|
3885
|
+
} catch (error) {
|
|
3886
|
+
rejectInit(error);
|
|
3887
|
+
throw error;
|
|
3818
3888
|
} finally {
|
|
3819
3889
|
inFlightAccountInits.delete(account.id);
|
|
3820
3890
|
}
|
|
@@ -4015,7 +4085,7 @@ async function loginViaApi(page, email, password) {
|
|
|
4015
4085
|
const signinUrl = "https://auth.qwen.ai/api/v2/auths/signin";
|
|
4016
4086
|
const requestId = crypto3.randomUUID();
|
|
4017
4087
|
const evalRes = await page.evaluate(
|
|
4018
|
-
async ({ email: email2, password: password2, signinUrl: signinUrl2, requestId: requestId2 }) => {
|
|
4088
|
+
async ({ email: email2, password: password2, signinUrl: signinUrl2, requestId: requestId2, tz }) => {
|
|
4019
4089
|
try {
|
|
4020
4090
|
const response = await fetch(signinUrl2, {
|
|
4021
4091
|
method: "POST",
|
|
@@ -4027,7 +4097,7 @@ async function loginViaApi(page, email, password) {
|
|
|
4027
4097
|
source: "web",
|
|
4028
4098
|
version: "0.3.11",
|
|
4029
4099
|
"x-request-origin": "https://chat.qwen.ai",
|
|
4030
|
-
timezone:
|
|
4100
|
+
timezone: tz,
|
|
4031
4101
|
"x-request-id": requestId2
|
|
4032
4102
|
},
|
|
4033
4103
|
body: JSON.stringify({ email: email2, password: password2 })
|
|
@@ -4038,7 +4108,7 @@ async function loginViaApi(page, email, password) {
|
|
|
4038
4108
|
return { ok: false, error: e.message };
|
|
4039
4109
|
}
|
|
4040
4110
|
},
|
|
4041
|
-
{ email, password: hashedPassword, signinUrl, requestId }
|
|
4111
|
+
{ email, password: hashedPassword, signinUrl, requestId, tz: formatAsciiTimezone() }
|
|
4042
4112
|
).catch(() => null);
|
|
4043
4113
|
let data = evalRes?.data;
|
|
4044
4114
|
let signinSuccess = Boolean(
|
|
@@ -4047,7 +4117,7 @@ async function loginViaApi(page, email, password) {
|
|
|
4047
4117
|
if (!signinSuccess && !data?.data?.code) {
|
|
4048
4118
|
const fallbackUrl = qwenUrl("/api/v2/auths/signin");
|
|
4049
4119
|
const fallbackRes = await page.evaluate(
|
|
4050
|
-
async ({ email: email2, password: password2, fallbackUrl: fallbackUrl2, requestId: requestId2 }) => {
|
|
4120
|
+
async ({ email: email2, password: password2, fallbackUrl: fallbackUrl2, requestId: requestId2, tz }) => {
|
|
4051
4121
|
try {
|
|
4052
4122
|
const response = await fetch(fallbackUrl2, {
|
|
4053
4123
|
method: "POST",
|
|
@@ -4058,7 +4128,7 @@ async function loginViaApi(page, email, password) {
|
|
|
4058
4128
|
"content-type": "application/json",
|
|
4059
4129
|
source: "web",
|
|
4060
4130
|
version: "0.3.11",
|
|
4061
|
-
timezone:
|
|
4131
|
+
timezone: tz,
|
|
4062
4132
|
"x-request-id": requestId2
|
|
4063
4133
|
},
|
|
4064
4134
|
body: JSON.stringify({ email: email2, password: password2 })
|
|
@@ -4069,7 +4139,7 @@ async function loginViaApi(page, email, password) {
|
|
|
4069
4139
|
return { ok: false, error: e.message };
|
|
4070
4140
|
}
|
|
4071
4141
|
},
|
|
4072
|
-
{ email, password: hashedPassword, fallbackUrl, requestId }
|
|
4142
|
+
{ email, password: hashedPassword, fallbackUrl, requestId, tz: formatAsciiTimezone() }
|
|
4073
4143
|
).catch(() => null);
|
|
4074
4144
|
if (fallbackRes?.data) {
|
|
4075
4145
|
data = fallbackRes.data;
|
|
@@ -4401,7 +4471,7 @@ async function refreshAccountToken(accountId) {
|
|
|
4401
4471
|
if (refreshToken) {
|
|
4402
4472
|
try {
|
|
4403
4473
|
const refreshResult = await page.evaluate(
|
|
4404
|
-
async ({ rTok }) => {
|
|
4474
|
+
async ({ rTok, tz }) => {
|
|
4405
4475
|
try {
|
|
4406
4476
|
const response = await fetch("https://auth.qwen.ai/api/v2/auths/refresh", {
|
|
4407
4477
|
method: "GET",
|
|
@@ -4411,7 +4481,7 @@ async function refreshAccountToken(accountId) {
|
|
|
4411
4481
|
source: "web",
|
|
4412
4482
|
version: "0.3.11",
|
|
4413
4483
|
"x-request-origin": "https://chat.qwen.ai",
|
|
4414
|
-
timezone:
|
|
4484
|
+
timezone: tz,
|
|
4415
4485
|
authorization: `Bearer ${rTok}`
|
|
4416
4486
|
}
|
|
4417
4487
|
});
|
|
@@ -4421,7 +4491,7 @@ async function refreshAccountToken(accountId) {
|
|
|
4421
4491
|
return { ok: false, error: e.message };
|
|
4422
4492
|
}
|
|
4423
4493
|
},
|
|
4424
|
-
{ rTok: refreshToken }
|
|
4494
|
+
{ rTok: refreshToken, tz: formatAsciiTimezone() }
|
|
4425
4495
|
);
|
|
4426
4496
|
const json = refreshResult?.data;
|
|
4427
4497
|
if (json && json.success === true && json.data) {
|
|
@@ -4459,6 +4529,7 @@ async function refreshAccountToken(accountId) {
|
|
|
4459
4529
|
const cache = getHeaderCache(accountId);
|
|
4460
4530
|
cache.headers.cookie = cookieStr;
|
|
4461
4531
|
cache.lastRefresh = Date.now();
|
|
4532
|
+
cookieCaches.set(accountId, { cookie: cookieStr, timestamp: Date.now() });
|
|
4462
4533
|
markAccountHeadersReady(accountId);
|
|
4463
4534
|
saveAuthSession2(accountId, {
|
|
4464
4535
|
cookie: cookieStr,
|
|
@@ -4493,6 +4564,7 @@ async function refreshAccountToken(accountId) {
|
|
|
4493
4564
|
const cache = getHeaderCache(accountId);
|
|
4494
4565
|
cache.headers.cookie = cookieStr;
|
|
4495
4566
|
cache.lastRefresh = Date.now();
|
|
4567
|
+
cookieCaches.set(accountId, { cookie: cookieStr, timestamp: Date.now() });
|
|
4496
4568
|
markAccountHeadersReady(accountId);
|
|
4497
4569
|
saveAuthSession2(accountId, {
|
|
4498
4570
|
cookie: cookieStr,
|
|
@@ -5373,6 +5445,7 @@ var init_playwright = __esm({
|
|
|
5373
5445
|
init_qwen_headers();
|
|
5374
5446
|
init_paths();
|
|
5375
5447
|
init_jwt();
|
|
5448
|
+
init_timezone();
|
|
5376
5449
|
requireLocal = createRequire(import.meta.url);
|
|
5377
5450
|
contextInitHooks = [];
|
|
5378
5451
|
ACCOUNT_MUTEX_MAX_HOLD_MS = 18e4;
|
|
@@ -5382,7 +5455,7 @@ var init_playwright = __esm({
|
|
|
5382
5455
|
inFlightAccountInits = /* @__PURE__ */ new Map();
|
|
5383
5456
|
headerCaches = /* @__PURE__ */ new Map();
|
|
5384
5457
|
HEADER_CACHE_TTL = 24 * 60 * 60 * 1e3;
|
|
5385
|
-
COOKIE_CACHE_TTL =
|
|
5458
|
+
COOKIE_CACHE_TTL = 60 * 1e3;
|
|
5386
5459
|
cookieCaches = /* @__PURE__ */ new Map();
|
|
5387
5460
|
lastAccountActivity = /* @__PURE__ */ new Map();
|
|
5388
5461
|
lastKeepAliveNavigation = /* @__PURE__ */ new Map();
|