qwenproxy-cli 1.0.13 → 1.0.14
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 +3 -3
- package/src/api/server.ts +16 -9
- package/src/routes/chat/account.ts +16 -4
- package/src/services/playwright.ts +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qwenproxy-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
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": {
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"reset": "npx tsx src/reset-cooldowns.ts",
|
|
25
25
|
"purge": "npx tsx src/delete-chats.ts",
|
|
26
26
|
"test": "npm run test:mock && npm run test:live",
|
|
27
|
-
"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/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.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/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/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts",
|
|
28
|
-
"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/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.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/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/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts",
|
|
27
|
+
"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/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.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/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/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts src/tests/personalization-deadline.test.ts",
|
|
28
|
+
"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/captcha-solver.test.ts src/tests/cache-scan-regex.test.ts src/tests/chat-cleanup.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/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/cli.test.ts src/tests/paths.test.ts src/tests/tool-manifest.test.ts src/tests/tui.test.ts src/tests/personalization-deadline.test.ts",
|
|
29
29
|
"test:live": "tsx --test src/tests/concurrentChat.test.ts src/tests/agenticStress.test.ts",
|
|
30
30
|
"benchmark:proxy": "npx tsx src/benchmarks/proxy-baseline.ts",
|
|
31
31
|
"typecheck": "tsc --noEmit"
|
package/src/api/server.ts
CHANGED
|
@@ -650,15 +650,20 @@ export async function startServer(options?: {
|
|
|
650
650
|
const BATCH_SIZE = config.playwright.initBatchSize;
|
|
651
651
|
|
|
652
652
|
if (accounts.length > 0) {
|
|
653
|
-
let readyAccountId: string | null = null;
|
|
654
653
|
const totalAccounts = accounts.length;
|
|
655
654
|
|
|
656
655
|
// Warm accounts in priority order (recently successful accounts first),
|
|
657
|
-
// skipping accounts still on cooldown
|
|
658
|
-
//
|
|
656
|
+
// skipping accounts still on cooldown. Warm up to maxActiveContexts
|
|
657
|
+
// accounts (default 2: main + reserve) so an immediate failover has a
|
|
658
|
+
// live browser ready instead of incurring a cold start.
|
|
659
659
|
const warmOrder = getAccountsByPriority(accounts).filter(
|
|
660
660
|
(account) => !getAccountCooldownInfo(account.id),
|
|
661
661
|
);
|
|
662
|
+
const targetWarmCount = Math.min(
|
|
663
|
+
warmOrder.length,
|
|
664
|
+
Math.max(1, config.playwright.maxActiveContexts),
|
|
665
|
+
);
|
|
666
|
+
const readyAccountIds = new Set<string>();
|
|
662
667
|
|
|
663
668
|
for (let i = 0; i < warmOrder.length; i++) {
|
|
664
669
|
const ok = await prepareAccountRuntime(
|
|
@@ -669,24 +674,26 @@ export async function startServer(options?: {
|
|
|
669
674
|
warmQwenChatPool,
|
|
670
675
|
);
|
|
671
676
|
if (ok) {
|
|
677
|
+
readyAccountIds.add(warmOrder[i].id);
|
|
672
678
|
console.log(
|
|
673
|
-
`✅ [Server] Account ready (${
|
|
679
|
+
`✅ [Server] Account ready (${readyAccountIds.size}/${totalAccounts}): ${maskEmail(warmOrder[i].email)}`,
|
|
674
680
|
);
|
|
675
|
-
|
|
676
|
-
|
|
681
|
+
if (readyAccountIds.size >= targetWarmCount) {
|
|
682
|
+
break;
|
|
683
|
+
}
|
|
677
684
|
}
|
|
678
685
|
}
|
|
679
686
|
|
|
680
687
|
const remainingAccounts = accounts.filter(
|
|
681
|
-
(account) => account.id
|
|
688
|
+
(account) => !readyAccountIds.has(account.id),
|
|
682
689
|
);
|
|
683
|
-
if (
|
|
690
|
+
if (readyAccountIds.size === 0) {
|
|
684
691
|
console.warn(
|
|
685
692
|
`⚠️ [Server] No account ready during startup; continuing in background`,
|
|
686
693
|
);
|
|
687
694
|
}
|
|
688
695
|
|
|
689
|
-
if (config.playwright.prepareAllOnStartup ||
|
|
696
|
+
if (config.playwright.prepareAllOnStartup || readyAccountIds.size === 0) {
|
|
690
697
|
if (config.playwright.prepareAllOnStartup && remainingAccounts.length > 0) {
|
|
691
698
|
console.log(
|
|
692
699
|
`🪶 [Server] Preparing ${remainingAccounts.length} standby account(s) in background`,
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
type AccountLease,
|
|
36
36
|
} from "../../core/account-concurrency.ts";
|
|
37
37
|
import { isAuthMockEnabled } from "../../services/auth-playwright.ts";
|
|
38
|
-
import { refreshHeaders } from "../../services/playwright.ts";
|
|
38
|
+
import { isPlaywrightInitialized, refreshHeaders } from "../../services/playwright.ts";
|
|
39
39
|
import {
|
|
40
40
|
clearAllSessionsForAccount,
|
|
41
41
|
createQwenStream,
|
|
@@ -77,7 +77,18 @@ const MAX_ANTI_BOT_ROTATIONS = 1;
|
|
|
77
77
|
* a stuck account page (closed context / WAF) can otherwise hold each browser
|
|
78
78
|
* op for 60s and keep the personalization mutex blocked for minutes.
|
|
79
79
|
*/
|
|
80
|
-
const PERSONALIZATION_SYNC_DEADLINE_MS = 30_000;
|
|
80
|
+
export const PERSONALIZATION_SYNC_DEADLINE_MS = 30_000;
|
|
81
|
+
export const COLD_ACCOUNT_PERSONALIZATION_SYNC_DEADLINE_MS = 60_000;
|
|
82
|
+
|
|
83
|
+
export function computePersonalizationDeadlineMs(
|
|
84
|
+
accountId: string | undefined,
|
|
85
|
+
navigationTimeoutMs = config.timeouts.navigation,
|
|
86
|
+
): number {
|
|
87
|
+
if (accountId && accountId !== "global" && isPlaywrightInitialized(accountId)) {
|
|
88
|
+
return PERSONALIZATION_SYNC_DEADLINE_MS;
|
|
89
|
+
}
|
|
90
|
+
return Math.max(COLD_ACCOUNT_PERSONALIZATION_SYNC_DEADLINE_MS, navigationTimeoutMs);
|
|
91
|
+
}
|
|
81
92
|
|
|
82
93
|
/**
|
|
83
94
|
* Hard deadline for a single stream-acquire attempt (models sync + truncation
|
|
@@ -1183,15 +1194,16 @@ async function tryCreateStreamWithRetry(
|
|
|
1183
1194
|
return false;
|
|
1184
1195
|
},
|
|
1185
1196
|
);
|
|
1197
|
+
const syncDeadlineMs = computePersonalizationDeadlineMs(currentAccountId);
|
|
1186
1198
|
personalizationApplied = await Promise.race([
|
|
1187
1199
|
syncPromise,
|
|
1188
1200
|
new Promise<boolean>((resolve) => {
|
|
1189
1201
|
personalizationDeadlineTimer = setTimeout(() => {
|
|
1190
1202
|
if (!syncSettled) {
|
|
1191
|
-
syncFailure = `sync timed out after ${
|
|
1203
|
+
syncFailure = `sync timed out after ${syncDeadlineMs}ms`;
|
|
1192
1204
|
}
|
|
1193
1205
|
resolve(false);
|
|
1194
|
-
},
|
|
1206
|
+
}, syncDeadlineMs);
|
|
1195
1207
|
}),
|
|
1196
1208
|
]);
|
|
1197
1209
|
// The sync won the race: stop the deadline so it cannot keep the
|
|
@@ -3157,6 +3157,12 @@ export function registerPlaywrightAccountForTests(
|
|
|
3157
3157
|
lastAccountActivity.set(accountId, lastActivityAt);
|
|
3158
3158
|
}
|
|
3159
3159
|
|
|
3160
|
+
export function unregisterPlaywrightAccountForTests(accountId: string): void {
|
|
3161
|
+
accountPages.delete(accountId);
|
|
3162
|
+
accountContexts.delete(accountId);
|
|
3163
|
+
lastAccountActivity.delete(accountId);
|
|
3164
|
+
}
|
|
3165
|
+
|
|
3160
3166
|
// ─── Token TTL Diagnostics ───────────────────────────────────────────────────
|
|
3161
3167
|
|
|
3162
3168
|
export interface CookieDiagnostic {
|