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
package/src/core/crypto-utils.ts
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
import crypto from "crypto";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import path from "path";
|
|
4
|
-
|
|
5
|
-
import { getDbDir, getEncryptionKeyPath } from "./paths.ts";
|
|
6
|
-
|
|
7
|
-
const DATA_DIR = getDbDir();
|
|
8
|
-
const KEY_PATH = getEncryptionKeyPath();
|
|
9
|
-
const ALGORITHM = "aes-256-gcm";
|
|
10
|
-
const IV_LENGTH = 16;
|
|
11
|
-
const KEY_LENGTH = 32;
|
|
12
|
-
|
|
13
|
-
let cachedKey: Buffer | null = null;
|
|
14
|
-
|
|
15
|
-
function getOrCreateKey(): Buffer {
|
|
16
|
-
if (cachedKey) return cachedKey;
|
|
17
|
-
|
|
18
|
-
const envKey = process.env.ENCRYPTION_KEY;
|
|
19
|
-
if (envKey) {
|
|
20
|
-
cachedKey = crypto.scryptSync(envKey, "qwenproxy-salt", KEY_LENGTH);
|
|
21
|
-
return cachedKey;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (fs.existsSync(KEY_PATH)) {
|
|
25
|
-
cachedKey = Buffer.from(fs.readFileSync(KEY_PATH, "utf-8"), "hex");
|
|
26
|
-
return cachedKey;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (!fs.existsSync(DATA_DIR)) {
|
|
30
|
-
fs.mkdirSync(DATA_DIR, { recursive: true, mode: 0o755 });
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const key = crypto.randomBytes(KEY_LENGTH);
|
|
34
|
-
fs.writeFileSync(KEY_PATH, key.toString("hex"), { mode: 0o600 });
|
|
35
|
-
cachedKey = key;
|
|
36
|
-
return cachedKey;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function encrypt(plaintext: string): string {
|
|
40
|
-
if (!plaintext) return "";
|
|
41
|
-
|
|
42
|
-
const key = getOrCreateKey();
|
|
43
|
-
const iv = crypto.randomBytes(IV_LENGTH);
|
|
44
|
-
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
|
|
45
|
-
const encrypted = Buffer.concat([
|
|
46
|
-
cipher.update(plaintext, "utf-8"),
|
|
47
|
-
cipher.final(),
|
|
48
|
-
]);
|
|
49
|
-
const authTag = cipher.getAuthTag();
|
|
50
|
-
|
|
51
|
-
return `${iv.toString("hex")}:${authTag.toString("hex")}:${encrypted.toString("hex")}`;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function decrypt(ciphertext: string): string {
|
|
55
|
-
if (!ciphertext) return "";
|
|
56
|
-
if (!ciphertext.includes(":")) return ciphertext;
|
|
57
|
-
|
|
58
|
-
const parts = ciphertext.split(":");
|
|
59
|
-
if (parts.length !== 3) return ciphertext;
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
const key = getOrCreateKey();
|
|
63
|
-
const iv = Buffer.from(parts[0], "hex");
|
|
64
|
-
const authTag = Buffer.from(parts[1], "hex");
|
|
65
|
-
const encrypted = Buffer.from(parts[2], "hex");
|
|
66
|
-
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
|
|
67
|
-
decipher.setAuthTag(authTag);
|
|
68
|
-
return decipher.update(encrypted).toString("utf-8") + decipher.final("utf-8");
|
|
69
|
-
} catch {
|
|
70
|
-
return ciphertext;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function isEncrypted(value: string): boolean {
|
|
75
|
-
if (!value) return false;
|
|
76
|
-
const parts = value.split(":");
|
|
77
|
-
if (parts.length !== 3) return false;
|
|
78
|
-
return parts.every((part) => /^[0-9a-f]+$/i.test(part));
|
|
79
|
-
}
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
import { getDbDir, getEncryptionKeyPath } from "./paths.ts";
|
|
6
|
+
|
|
7
|
+
const DATA_DIR = getDbDir();
|
|
8
|
+
const KEY_PATH = getEncryptionKeyPath();
|
|
9
|
+
const ALGORITHM = "aes-256-gcm";
|
|
10
|
+
const IV_LENGTH = 16;
|
|
11
|
+
const KEY_LENGTH = 32;
|
|
12
|
+
|
|
13
|
+
let cachedKey: Buffer | null = null;
|
|
14
|
+
|
|
15
|
+
function getOrCreateKey(): Buffer {
|
|
16
|
+
if (cachedKey) return cachedKey;
|
|
17
|
+
|
|
18
|
+
const envKey = process.env.ENCRYPTION_KEY;
|
|
19
|
+
if (envKey) {
|
|
20
|
+
cachedKey = crypto.scryptSync(envKey, "qwenproxy-salt", KEY_LENGTH);
|
|
21
|
+
return cachedKey;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (fs.existsSync(KEY_PATH)) {
|
|
25
|
+
cachedKey = Buffer.from(fs.readFileSync(KEY_PATH, "utf-8"), "hex");
|
|
26
|
+
return cachedKey;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!fs.existsSync(DATA_DIR)) {
|
|
30
|
+
fs.mkdirSync(DATA_DIR, { recursive: true, mode: 0o755 });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const key = crypto.randomBytes(KEY_LENGTH);
|
|
34
|
+
fs.writeFileSync(KEY_PATH, key.toString("hex"), { mode: 0o600 });
|
|
35
|
+
cachedKey = key;
|
|
36
|
+
return cachedKey;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function encrypt(plaintext: string): string {
|
|
40
|
+
if (!plaintext) return "";
|
|
41
|
+
|
|
42
|
+
const key = getOrCreateKey();
|
|
43
|
+
const iv = crypto.randomBytes(IV_LENGTH);
|
|
44
|
+
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
|
|
45
|
+
const encrypted = Buffer.concat([
|
|
46
|
+
cipher.update(plaintext, "utf-8"),
|
|
47
|
+
cipher.final(),
|
|
48
|
+
]);
|
|
49
|
+
const authTag = cipher.getAuthTag();
|
|
50
|
+
|
|
51
|
+
return `${iv.toString("hex")}:${authTag.toString("hex")}:${encrypted.toString("hex")}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function decrypt(ciphertext: string): string {
|
|
55
|
+
if (!ciphertext) return "";
|
|
56
|
+
if (!ciphertext.includes(":")) return ciphertext;
|
|
57
|
+
|
|
58
|
+
const parts = ciphertext.split(":");
|
|
59
|
+
if (parts.length !== 3) return ciphertext;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const key = getOrCreateKey();
|
|
63
|
+
const iv = Buffer.from(parts[0], "hex");
|
|
64
|
+
const authTag = Buffer.from(parts[1], "hex");
|
|
65
|
+
const encrypted = Buffer.from(parts[2], "hex");
|
|
66
|
+
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
|
|
67
|
+
decipher.setAuthTag(authTag);
|
|
68
|
+
return decipher.update(encrypted).toString("utf-8") + decipher.final("utf-8");
|
|
69
|
+
} catch {
|
|
70
|
+
return ciphertext;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function isEncrypted(value: string): boolean {
|
|
75
|
+
if (!value) return false;
|
|
76
|
+
const parts = value.split(":");
|
|
77
|
+
if (parts.length !== 3) return false;
|
|
78
|
+
return parts.every((part) => /^[0-9a-f]+$/i.test(part));
|
|
79
|
+
}
|