qwenproxy-cli 1.0.0 → 1.0.2
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/LICENSE +14 -14
- package/README.md +906 -906
- package/bin/qwenproxy.js +5 -1
- package/package.json +77 -78
- package/src/api/error-classifier.ts +159 -159
- package/src/api/error-helpers.ts +118 -118
- package/src/api/models.ts +261 -261
- package/src/api/server.ts +860 -859
- package/src/cache/memory-cache.ts +385 -385
- package/src/clean-cache.ts +204 -204
- package/src/core/account-concurrency.ts +671 -671
- package/src/core/account-manager.ts +301 -297
- package/src/core/account-priority.ts +163 -163
- package/src/core/accounts.ts +186 -186
- package/src/core/config.ts +383 -383
- package/src/core/crypto-utils.ts +79 -79
- package/src/core/database.ts +276 -276
- package/src/core/errors.ts +118 -118
- package/src/core/logger.ts +269 -269
- package/src/core/memory-usage.ts +84 -84
- package/src/core/metrics.ts +291 -291
- package/src/core/model-alias.ts +77 -77
- package/src/core/model-registry.ts +544 -544
- package/src/core/mutex.ts +119 -119
- package/src/core/paths.ts +199 -199
- package/src/core/prompt-limits.ts +214 -214
- package/src/core/reasoning-effort.ts +102 -102
- package/src/core/stream-registry.ts +96 -96
- package/src/core/waf-isolation.ts +117 -117
- package/src/core/watchdog.ts +195 -195
- package/src/delete-chats.ts +23 -23
- package/src/index.ts +65 -64
- package/src/login.ts +147 -147
- package/src/reset-cooldowns.ts +11 -11
- package/src/routes/anthropic/index.ts +355 -355
- package/src/routes/anthropic/translate.ts +522 -522
- package/src/routes/anthropic/types.ts +154 -154
- package/src/routes/anthropic/validation.ts +144 -144
- package/src/routes/chat/account.ts +1817 -1817
- package/src/routes/chat/context.ts +241 -241
- package/src/routes/chat/errors.ts +85 -85
- package/src/routes/chat/helpers.ts +268 -268
- package/src/routes/chat/index.ts +618 -618
- package/src/routes/chat/media.ts +285 -285
- package/src/routes/chat/retry-policy.ts +754 -754
- package/src/routes/chat/stop.ts +98 -98
- package/src/routes/chat/streaming.ts +2710 -2710
- package/src/routes/chat/validation.ts +526 -526
- package/src/routes/chat.ts +2 -2
- package/src/routes/completions.ts +290 -290
- package/src/routes/images.ts +139 -139
- package/src/routes/responses/adapter.ts +503 -503
- package/src/routes/responses/index.ts +405 -405
- package/src/routes/responses/state.ts +230 -230
- package/src/routes/responses/streaming.ts +528 -528
- package/src/routes/responses/types.ts +285 -285
- package/src/routes/responses/validation.ts +202 -202
- package/src/routes/upload.ts +731 -731
- package/src/routes/videos.ts +214 -214
- package/src/services/auth-playwright.ts +173 -173
- package/src/services/captcha-coordinator.ts +161 -161
- package/src/services/captcha-solver.ts +553 -553
- package/src/services/chat-cleanup.ts +80 -80
- package/src/services/context-meter.ts +317 -317
- package/src/services/fingerprint.ts +242 -242
- package/src/services/human-behavior.ts +173 -173
- package/src/services/media-generation.ts +1748 -1748
- package/src/services/playwright.ts +2878 -2800
- package/src/services/qwen-chat-pool.ts +345 -345
- package/src/services/qwen-errors.ts +133 -133
- package/src/services/qwen-headers.ts +79 -79
- package/src/services/qwen-thread-state.ts +393 -393
- package/src/services/qwen-url.ts +19 -19
- package/src/services/qwen.ts +3126 -3126
- package/src/services/session-keeper.ts +88 -88
- package/src/services/token-estimation-metrics.ts +118 -118
- package/src/sync/claude-code.ts +75 -75
- package/src/sync/codex.ts +123 -123
- package/src/sync/index.ts +362 -362
- package/src/sync/omp.ts +105 -105
- package/src/sync/opencode.ts +214 -214
- package/src/sync/types.ts +53 -53
- package/src/sync/utils.ts +27 -27
- package/src/sync-clients.ts +189 -189
- package/src/tools/instructions.ts +137 -137
- package/src/tools/manifest.ts +81 -81
- package/src/tools/parser.ts +2989 -2989
- package/src/tools/toolcall-tags.ts +142 -142
- package/src/tui/app.ts +259 -264
- package/src/tui/index.ts +61 -61
- package/src/tui/markdown.ts +258 -258
- package/src/tui/proxy-client.ts +331 -326
- package/src/tui/screen.ts +294 -278
- package/src/tui/server-manager.ts +270 -270
- package/src/tui/theme.ts +432 -432
- package/src/tui/types.ts +33 -33
- package/src/tui/views/accounts-view.ts +656 -656
- package/src/tui/views/chat-view.ts +1018 -823
- package/src/tui/views/logs-view.ts +479 -413
- package/src/tui/views/status-view.ts +204 -204
- package/src/tui/views/storage-view.ts +304 -291
- package/src/tui/views/sync-view.ts +409 -409
- package/src/types/ali-oss.d.ts +32 -32
- package/src/update-cli.ts +121 -0
- package/src/utils/context-truncation.ts +84 -84
- package/src/utils/json.ts +380 -380
- package/src/utils/session-id.ts +37 -37
- package/src/utils/tool-call-guard.ts +84 -84
- package/src/utils/types.ts +109 -109
|
@@ -1,163 +1,163 @@
|
|
|
1
|
-
import {
|
|
2
|
-
existsSync,
|
|
3
|
-
mkdirSync,
|
|
4
|
-
readFileSync,
|
|
5
|
-
writeFileSync,
|
|
6
|
-
} from "fs";
|
|
7
|
-
import { join, resolve } from "path";
|
|
8
|
-
|
|
9
|
-
interface PriorityData {
|
|
10
|
-
accountOrder: string[];
|
|
11
|
-
lastUpdated: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Mock account used by test suites (TEST_MOCK_QWEN_AUTH). Must never be
|
|
16
|
-
* persisted to the real priority file or it pollutes production routing.
|
|
17
|
-
*/
|
|
18
|
-
const MOCK_ACCOUNT_ID = "mock-account";
|
|
19
|
-
|
|
20
|
-
function isPersistableAccount(accountId: string): boolean {
|
|
21
|
-
return accountId !== MOCK_ACCOUNT_ID;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
import { getDataDir, getAccountPriorityPath } from "./paths.ts";
|
|
25
|
-
|
|
26
|
-
const DATA_DIR = getDataDir();
|
|
27
|
-
const PRIORITY_FILE = getAccountPriorityPath();
|
|
28
|
-
|
|
29
|
-
let priorityCache: PriorityData | null = null;
|
|
30
|
-
|
|
31
|
-
/** Invalidate the in-memory priority cache (test isolation). */
|
|
32
|
-
export function invalidatePriorityCache(): void {
|
|
33
|
-
priorityCache = null;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function loadPriority(): PriorityData {
|
|
37
|
-
if (priorityCache) return priorityCache;
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
if (existsSync(PRIORITY_FILE)) {
|
|
41
|
-
const data = JSON.parse(readFileSync(PRIORITY_FILE, "utf-8"));
|
|
42
|
-
// Filter out any mock/test accounts that may have leaked into the file
|
|
43
|
-
const accountOrder: string[] = (data.accountOrder || []).filter(
|
|
44
|
-
isPersistableAccount,
|
|
45
|
-
);
|
|
46
|
-
priorityCache = {
|
|
47
|
-
accountOrder,
|
|
48
|
-
lastUpdated: data.lastUpdated || 0,
|
|
49
|
-
};
|
|
50
|
-
return priorityCache!;
|
|
51
|
-
}
|
|
52
|
-
} catch (err) {
|
|
53
|
-
console.error("❌ [AccountPriority] Failed to load priority file:", (err as Error).message);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
priorityCache = { accountOrder: [], lastUpdated: 0 };
|
|
57
|
-
return priorityCache;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function savePriority(data: PriorityData): void {
|
|
61
|
-
try {
|
|
62
|
-
mkdirSync(DATA_DIR, { recursive: true });
|
|
63
|
-
writeFileSync(PRIORITY_FILE, JSON.stringify(data, null, 2), "utf-8");
|
|
64
|
-
priorityCache = data;
|
|
65
|
-
} catch (err) {
|
|
66
|
-
console.error("❌ [AccountPriority] Failed to save priority file:", (err as Error).message);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Reordena contas: conta que funcionou vai para o topo
|
|
72
|
-
*/
|
|
73
|
-
export function markAccountSuccessful(accountId: string): void {
|
|
74
|
-
if (!isPersistableAccount(accountId)) return;
|
|
75
|
-
const data = loadPriority();
|
|
76
|
-
|
|
77
|
-
// Remove se já existe
|
|
78
|
-
data.accountOrder = data.accountOrder.filter(id => id !== accountId);
|
|
79
|
-
|
|
80
|
-
// Adiciona no topo
|
|
81
|
-
data.accountOrder.unshift(accountId);
|
|
82
|
-
data.lastUpdated = Date.now();
|
|
83
|
-
|
|
84
|
-
savePriority(data);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Reordena contas: conta que falhou vai para o final
|
|
89
|
-
*/
|
|
90
|
-
export function markAccountFailed(accountId: string): void {
|
|
91
|
-
if (!isPersistableAccount(accountId)) return;
|
|
92
|
-
const data = loadPriority();
|
|
93
|
-
|
|
94
|
-
// Remove se já existe
|
|
95
|
-
data.accountOrder = data.accountOrder.filter(id => id !== accountId);
|
|
96
|
-
|
|
97
|
-
// Adiciona no final
|
|
98
|
-
data.accountOrder.push(accountId);
|
|
99
|
-
data.lastUpdated = Date.now();
|
|
100
|
-
|
|
101
|
-
savePriority(data);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Adiciona conta à prioridade se não existir (prioridade inicial).
|
|
106
|
-
* Contas novas entram no final da lista, mantendo a ordem de configuração.
|
|
107
|
-
*/
|
|
108
|
-
export function ensureAccountInPriority(accountId: string): void {
|
|
109
|
-
if (!isPersistableAccount(accountId)) return;
|
|
110
|
-
const data = loadPriority();
|
|
111
|
-
|
|
112
|
-
// Se já existe, não faz nada
|
|
113
|
-
if (data.accountOrder.includes(accountId)) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Adiciona no final (prioridade inicial baixa)
|
|
118
|
-
data.accountOrder.push(accountId);
|
|
119
|
-
data.lastUpdated = Date.now();
|
|
120
|
-
|
|
121
|
-
savePriority(data);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Retorna contas ordenadas por prioridade (melhores primeiro)
|
|
126
|
-
*/
|
|
127
|
-
export function getAccountsByPriority<T extends { id: string }>(accounts: T[]): T[] {
|
|
128
|
-
const data = loadPriority();
|
|
129
|
-
|
|
130
|
-
if (data.accountOrder.length === 0) {
|
|
131
|
-
return accounts;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Cria mapa de prioridade (menor índice = maior prioridade)
|
|
135
|
-
const priorityMap = new Map<string, number>();
|
|
136
|
-
data.accountOrder.forEach((id, index) => {
|
|
137
|
-
priorityMap.set(id, index);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// Ordena: contas na lista de prioridade vêm primeiro, depois as que não estão na lista
|
|
141
|
-
return [...accounts].sort((a, b) => {
|
|
142
|
-
const priorityA = priorityMap.get(a.id);
|
|
143
|
-
const priorityB = priorityMap.get(b.id);
|
|
144
|
-
|
|
145
|
-
// Ambos têm prioridade definida
|
|
146
|
-
if (priorityA !== undefined && priorityB !== undefined) {
|
|
147
|
-
return priorityA - priorityB;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Apenas A tem prioridade
|
|
151
|
-
if (priorityA !== undefined) {
|
|
152
|
-
return -1;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Apenas B tem prioridade
|
|
156
|
-
if (priorityB !== undefined) {
|
|
157
|
-
return 1;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Nenhum tem prioridade, mantém ordem original
|
|
161
|
-
return 0;
|
|
162
|
-
});
|
|
163
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
existsSync,
|
|
3
|
+
mkdirSync,
|
|
4
|
+
readFileSync,
|
|
5
|
+
writeFileSync,
|
|
6
|
+
} from "fs";
|
|
7
|
+
import { join, resolve } from "path";
|
|
8
|
+
|
|
9
|
+
interface PriorityData {
|
|
10
|
+
accountOrder: string[];
|
|
11
|
+
lastUpdated: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Mock account used by test suites (TEST_MOCK_QWEN_AUTH). Must never be
|
|
16
|
+
* persisted to the real priority file or it pollutes production routing.
|
|
17
|
+
*/
|
|
18
|
+
const MOCK_ACCOUNT_ID = "mock-account";
|
|
19
|
+
|
|
20
|
+
function isPersistableAccount(accountId: string): boolean {
|
|
21
|
+
return accountId !== MOCK_ACCOUNT_ID;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
import { getDataDir, getAccountPriorityPath } from "./paths.ts";
|
|
25
|
+
|
|
26
|
+
const DATA_DIR = getDataDir();
|
|
27
|
+
const PRIORITY_FILE = getAccountPriorityPath();
|
|
28
|
+
|
|
29
|
+
let priorityCache: PriorityData | null = null;
|
|
30
|
+
|
|
31
|
+
/** Invalidate the in-memory priority cache (test isolation). */
|
|
32
|
+
export function invalidatePriorityCache(): void {
|
|
33
|
+
priorityCache = null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function loadPriority(): PriorityData {
|
|
37
|
+
if (priorityCache) return priorityCache;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
if (existsSync(PRIORITY_FILE)) {
|
|
41
|
+
const data = JSON.parse(readFileSync(PRIORITY_FILE, "utf-8"));
|
|
42
|
+
// Filter out any mock/test accounts that may have leaked into the file
|
|
43
|
+
const accountOrder: string[] = (data.accountOrder || []).filter(
|
|
44
|
+
isPersistableAccount,
|
|
45
|
+
);
|
|
46
|
+
priorityCache = {
|
|
47
|
+
accountOrder,
|
|
48
|
+
lastUpdated: data.lastUpdated || 0,
|
|
49
|
+
};
|
|
50
|
+
return priorityCache!;
|
|
51
|
+
}
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error("❌ [AccountPriority] Failed to load priority file:", (err as Error).message);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
priorityCache = { accountOrder: [], lastUpdated: 0 };
|
|
57
|
+
return priorityCache;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function savePriority(data: PriorityData): void {
|
|
61
|
+
try {
|
|
62
|
+
mkdirSync(DATA_DIR, { recursive: true });
|
|
63
|
+
writeFileSync(PRIORITY_FILE, JSON.stringify(data, null, 2), "utf-8");
|
|
64
|
+
priorityCache = data;
|
|
65
|
+
} catch (err) {
|
|
66
|
+
console.error("❌ [AccountPriority] Failed to save priority file:", (err as Error).message);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Reordena contas: conta que funcionou vai para o topo
|
|
72
|
+
*/
|
|
73
|
+
export function markAccountSuccessful(accountId: string): void {
|
|
74
|
+
if (!isPersistableAccount(accountId)) return;
|
|
75
|
+
const data = loadPriority();
|
|
76
|
+
|
|
77
|
+
// Remove se já existe
|
|
78
|
+
data.accountOrder = data.accountOrder.filter(id => id !== accountId);
|
|
79
|
+
|
|
80
|
+
// Adiciona no topo
|
|
81
|
+
data.accountOrder.unshift(accountId);
|
|
82
|
+
data.lastUpdated = Date.now();
|
|
83
|
+
|
|
84
|
+
savePriority(data);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Reordena contas: conta que falhou vai para o final
|
|
89
|
+
*/
|
|
90
|
+
export function markAccountFailed(accountId: string): void {
|
|
91
|
+
if (!isPersistableAccount(accountId)) return;
|
|
92
|
+
const data = loadPriority();
|
|
93
|
+
|
|
94
|
+
// Remove se já existe
|
|
95
|
+
data.accountOrder = data.accountOrder.filter(id => id !== accountId);
|
|
96
|
+
|
|
97
|
+
// Adiciona no final
|
|
98
|
+
data.accountOrder.push(accountId);
|
|
99
|
+
data.lastUpdated = Date.now();
|
|
100
|
+
|
|
101
|
+
savePriority(data);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Adiciona conta à prioridade se não existir (prioridade inicial).
|
|
106
|
+
* Contas novas entram no final da lista, mantendo a ordem de configuração.
|
|
107
|
+
*/
|
|
108
|
+
export function ensureAccountInPriority(accountId: string): void {
|
|
109
|
+
if (!isPersistableAccount(accountId)) return;
|
|
110
|
+
const data = loadPriority();
|
|
111
|
+
|
|
112
|
+
// Se já existe, não faz nada
|
|
113
|
+
if (data.accountOrder.includes(accountId)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Adiciona no final (prioridade inicial baixa)
|
|
118
|
+
data.accountOrder.push(accountId);
|
|
119
|
+
data.lastUpdated = Date.now();
|
|
120
|
+
|
|
121
|
+
savePriority(data);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Retorna contas ordenadas por prioridade (melhores primeiro)
|
|
126
|
+
*/
|
|
127
|
+
export function getAccountsByPriority<T extends { id: string }>(accounts: T[]): T[] {
|
|
128
|
+
const data = loadPriority();
|
|
129
|
+
|
|
130
|
+
if (data.accountOrder.length === 0) {
|
|
131
|
+
return accounts;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Cria mapa de prioridade (menor índice = maior prioridade)
|
|
135
|
+
const priorityMap = new Map<string, number>();
|
|
136
|
+
data.accountOrder.forEach((id, index) => {
|
|
137
|
+
priorityMap.set(id, index);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Ordena: contas na lista de prioridade vêm primeiro, depois as que não estão na lista
|
|
141
|
+
return [...accounts].sort((a, b) => {
|
|
142
|
+
const priorityA = priorityMap.get(a.id);
|
|
143
|
+
const priorityB = priorityMap.get(b.id);
|
|
144
|
+
|
|
145
|
+
// Ambos têm prioridade definida
|
|
146
|
+
if (priorityA !== undefined && priorityB !== undefined) {
|
|
147
|
+
return priorityA - priorityB;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Apenas A tem prioridade
|
|
151
|
+
if (priorityA !== undefined) {
|
|
152
|
+
return -1;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Apenas B tem prioridade
|
|
156
|
+
if (priorityB !== undefined) {
|
|
157
|
+
return 1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Nenhum tem prioridade, mantém ordem original
|
|
161
|
+
return 0;
|
|
162
|
+
});
|
|
163
|
+
}
|