qwenproxy-cli 1.2.9 → 1.2.10

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwenproxy-cli",
3
- "version": "1.2.9",
3
+ "version": "1.2.10",
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": {
@@ -30,12 +30,17 @@ export function looksLikeAntiBotChallengeText(text: string): boolean {
30
30
  lower.includes("nocaptcha") ||
31
31
  lower.includes("captcha") ||
32
32
  lower.includes("aliyuncaptcha") ||
33
+ lower.includes("aliyun_waf") ||
34
+ lower.includes("cf_app_waf") ||
35
+ lower.includes("sec.alibaba.com") ||
33
36
  lower.includes("baxia") ||
34
37
  lower.includes("access verification") ||
35
38
  lower.includes("security verification") ||
36
39
  lower.includes("verify you are human") ||
37
40
  lower.includes("human verification") ||
38
- lower.includes("denyfromx5")
41
+ lower.includes("denyfromx5") ||
42
+ /^\s*<!doctype\s+html/i.test(text || "") ||
43
+ /^\s*<html\b/i.test(text || "")
39
44
  );
40
45
  }
41
46
 
@@ -763,7 +768,7 @@ async function createMediaChatSession(
763
768
  },
764
769
  {
765
770
  url: qwenUrl("/api/v2/chats/new"),
766
- headers: buildHeadersFromCaptured(headers),
771
+ headers: filterHeadersForBrowserFetch(buildHeadersFromCaptured(headers)),
767
772
  body: JSON.stringify({
768
773
  title,
769
774
  models: [chatModel],
@@ -774,15 +779,24 @@ async function createMediaChatSession(
774
779
  }),
775
780
  },
776
781
  );
782
+ const rawText = String(result.rawText || "");
783
+ if (looksLikeAntiBotChallengeText(rawText)) {
784
+ const error = new UpstreamError(
785
+ `Qwen anti-bot validation required: ${chatType} chat creation blocked by WAF (FAIL_SYS_USER_VALIDATE)`,
786
+ ) as UpstreamError & { upstreamCode: string; challengeBody?: string };
787
+ error.upstreamCode = "FAIL_SYS_USER_VALIDATE";
788
+ error.challengeBody = rawText;
789
+ throw error;
790
+ }
777
791
  if (!result.ok) {
778
792
  throw new UpstreamError(
779
- `Failed to create ${chatType} chat session: ${result.status} ${String(result.rawText).substring(0, 200)}`,
793
+ `Failed to create ${chatType} chat session: ${result.status} ${rawText.substring(0, 200)}`,
780
794
  );
781
795
  }
782
796
  const chatId = result.data?.data?.id || result.data?.data?.chat_id || result.data?.id;
783
797
  if (!chatId) {
784
798
  throw new UpstreamError(
785
- `Upstream created ${chatType} chat without returning a chat ID`,
799
+ `Upstream created ${chatType} chat without returning a chat ID: ${rawText.substring(0, 200)}`,
786
800
  );
787
801
  }
788
802
  return chatId;
@@ -803,15 +817,26 @@ async function createMediaChatSession(
803
817
  }),
804
818
  signal,
805
819
  });
806
-
820
+ const text = await response.text().catch(() => "");
821
+ if (looksLikeAntiBotChallengeText(text)) {
822
+ const error = new UpstreamError(
823
+ `Qwen anti-bot validation required: ${chatType} chat creation blocked by WAF (FAIL_SYS_USER_VALIDATE)`,
824
+ ) as UpstreamError & { upstreamCode: string; challengeBody?: string };
825
+ error.upstreamCode = "FAIL_SYS_USER_VALIDATE";
826
+ error.challengeBody = text;
827
+ throw error;
828
+ }
807
829
  if (!response.ok) {
808
- const text = await response.text().catch(() => "");
809
830
  throw new UpstreamError(
810
831
  `Failed to create ${chatType} chat session: ${response.status} ${text.substring(0, 200)}`,
811
832
  );
812
833
  }
813
834
 
814
- const json = await response.json();
835
+ let json: any = null;
836
+ try {
837
+ json = JSON.parse(text);
838
+ } catch {}
839
+
815
840
  const chatId =
816
841
  json?.chat_id ||
817
842
  json?.id ||
@@ -821,7 +846,7 @@ async function createMediaChatSession(
821
846
 
822
847
  if (!chatId || typeof chatId !== "string") {
823
848
  throw new UpstreamError(
824
- `Unexpected response when creating ${chatType} chat session`,
849
+ `Unexpected response when creating ${chatType} chat session: ${text.substring(0, 200)}`,
825
850
  );
826
851
  }
827
852
 
@@ -1248,8 +1273,12 @@ export async function generateImage(params: {
1248
1273
  }),
1249
1274
  );
1250
1275
 
1276
+ const isCaptcha =
1277
+ isAntiBotError(lastError) ||
1278
+ looksLikeAntiBotChallengeText(lastError.message);
1279
+
1251
1280
  if (
1252
- isAntiBotError(lastError) &&
1281
+ isCaptcha &&
1253
1282
  !captchaRecoveredAccounts.has(account.id)
1254
1283
  ) {
1255
1284
  logMediaInfo(
@@ -1257,7 +1286,12 @@ export async function generateImage(params: {
1257
1286
  account: shortMediaId(account.id),
1258
1287
  }),
1259
1288
  );
1260
- const recovered = await recoverBaxiaCaptcha(account.id, "media-generation");
1289
+ const challengeBody = (lastError as any)?.challengeBody;
1290
+ const recovered = await recoverBaxiaCaptcha(
1291
+ account.id,
1292
+ "media-generation",
1293
+ challengeBody ? { challengeBody } : {},
1294
+ );
1261
1295
  if (recovered) {
1262
1296
  captchaRecoveredAccounts.add(account.id);
1263
1297
  clearAccountCooldown(account.id);
@@ -1484,8 +1518,12 @@ export async function generateVideo(params: {
1484
1518
  }),
1485
1519
  );
1486
1520
 
1521
+ const isCaptcha =
1522
+ isAntiBotError(lastError) ||
1523
+ looksLikeAntiBotChallengeText(lastError.message);
1524
+
1487
1525
  if (
1488
- isAntiBotError(lastError) &&
1526
+ isCaptcha &&
1489
1527
  !captchaRecoveredAccounts.has(account.id)
1490
1528
  ) {
1491
1529
  logMediaInfo(
@@ -1493,9 +1531,11 @@ export async function generateVideo(params: {
1493
1531
  account: shortMediaId(account.id),
1494
1532
  }),
1495
1533
  );
1534
+ const challengeBody = (lastError as any)?.challengeBody;
1496
1535
  const recovered = await recoverBaxiaCaptcha(
1497
1536
  account.id,
1498
1537
  "media-generation",
1538
+ challengeBody ? { challengeBody } : {},
1499
1539
  );
1500
1540
  if (recovered) {
1501
1541
  captchaRecoveredAccounts.add(account.id);