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/api/error-helpers.ts
CHANGED
|
@@ -1,118 +1,118 @@
|
|
|
1
|
-
import type { Context } from "hono";
|
|
2
|
-
import type { QwenProxyStatusCode } from "../core/errors.js";
|
|
3
|
-
import {
|
|
4
|
-
QwenProxyError,
|
|
5
|
-
ValidationError,
|
|
6
|
-
AuthError,
|
|
7
|
-
ForbiddenError,
|
|
8
|
-
NotFoundError,
|
|
9
|
-
UpstreamRateLimit,
|
|
10
|
-
UpstreamError,
|
|
11
|
-
UpstreamTimeout,
|
|
12
|
-
InternalError,
|
|
13
|
-
ClientAbortedError,
|
|
14
|
-
ServiceUnavailable,
|
|
15
|
-
} from "../core/errors.js";
|
|
16
|
-
import { classifyError } from "./error-classifier.js";
|
|
17
|
-
|
|
18
|
-
const VALID_STATUSES: ReadonlySet<number> = new Set([
|
|
19
|
-
400, 401, 403, 404, 429, 499, 500, 502, 503, 504,
|
|
20
|
-
]);
|
|
21
|
-
|
|
22
|
-
function isValidStatus(code: number): code is QwenProxyStatusCode {
|
|
23
|
-
return VALID_STATUSES.has(code);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function errorForStatus(
|
|
27
|
-
status: QwenProxyStatusCode,
|
|
28
|
-
message: string,
|
|
29
|
-
): QwenProxyError {
|
|
30
|
-
switch (status) {
|
|
31
|
-
case 400:
|
|
32
|
-
return new ValidationError(message);
|
|
33
|
-
case 401:
|
|
34
|
-
return new AuthError(message);
|
|
35
|
-
case 403:
|
|
36
|
-
return new ForbiddenError(message);
|
|
37
|
-
case 404:
|
|
38
|
-
return new NotFoundError(message);
|
|
39
|
-
case 429:
|
|
40
|
-
return new UpstreamRateLimit(message);
|
|
41
|
-
case 499:
|
|
42
|
-
return new ClientAbortedError(message);
|
|
43
|
-
case 500:
|
|
44
|
-
return new InternalError(message);
|
|
45
|
-
case 502:
|
|
46
|
-
return new UpstreamError(message);
|
|
47
|
-
case 503:
|
|
48
|
-
return new ServiceUnavailable(message);
|
|
49
|
-
case 504:
|
|
50
|
-
return new UpstreamTimeout(message);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Sends a standardized OpenAI-compatible error response.
|
|
56
|
-
* Handles QwenProxyError directly, checks upstreamStatus hints on plain errors,
|
|
57
|
-
* and falls back to the error classifier.
|
|
58
|
-
*/
|
|
59
|
-
export function sendOpenAIError(
|
|
60
|
-
c: Context,
|
|
61
|
-
err: unknown,
|
|
62
|
-
fallbackStatus?: QwenProxyStatusCode,
|
|
63
|
-
): Response {
|
|
64
|
-
let qwenProxyErr: QwenProxyError;
|
|
65
|
-
|
|
66
|
-
if (err instanceof QwenProxyError) {
|
|
67
|
-
qwenProxyErr = err;
|
|
68
|
-
} else {
|
|
69
|
-
const hint = (err as Record<string, unknown>)?.upstreamStatus;
|
|
70
|
-
if (typeof hint === "number" && isValidStatus(hint)) {
|
|
71
|
-
qwenProxyErr = errorForStatus(
|
|
72
|
-
hint,
|
|
73
|
-
err instanceof Error ? err.message : String(err),
|
|
74
|
-
);
|
|
75
|
-
} else if (fallbackStatus) {
|
|
76
|
-
qwenProxyErr = errorForStatus(
|
|
77
|
-
fallbackStatus,
|
|
78
|
-
err instanceof Error ? err.message : String(err),
|
|
79
|
-
);
|
|
80
|
-
} else {
|
|
81
|
-
qwenProxyErr = classifyError(err);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const inner = qwenProxyErr.toOpenAI().error;
|
|
86
|
-
const body = {
|
|
87
|
-
error: {
|
|
88
|
-
message: inner.message,
|
|
89
|
-
type: inner.type,
|
|
90
|
-
code: inner.code,
|
|
91
|
-
param: inner.param ?? null,
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
// 499 (Client Closed Request) is not part of Hono's ContentfulStatusCode
|
|
95
|
-
// union. The abort is intercepted before sendOpenAIError in the chat route,
|
|
96
|
-
// but keep the fallback type-safe by building the Response directly.
|
|
97
|
-
if (qwenProxyErr.statusCode === 499) {
|
|
98
|
-
return new Response(JSON.stringify(body), {
|
|
99
|
-
status: 499,
|
|
100
|
-
headers: { "content-type": "application/json" },
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
return c.json(body, qwenProxyErr.statusCode);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Creates a QwenProxyError mapped to the given HTTP status code.
|
|
108
|
-
* Useful for inline error returns without throwing.
|
|
109
|
-
*/
|
|
110
|
-
export function createError(
|
|
111
|
-
status: QwenProxyStatusCode,
|
|
112
|
-
message: string,
|
|
113
|
-
param?: string,
|
|
114
|
-
): QwenProxyError {
|
|
115
|
-
const err = errorForStatus(status, message);
|
|
116
|
-
if (param) err.param = param;
|
|
117
|
-
return err;
|
|
118
|
-
}
|
|
1
|
+
import type { Context } from "hono";
|
|
2
|
+
import type { QwenProxyStatusCode } from "../core/errors.js";
|
|
3
|
+
import {
|
|
4
|
+
QwenProxyError,
|
|
5
|
+
ValidationError,
|
|
6
|
+
AuthError,
|
|
7
|
+
ForbiddenError,
|
|
8
|
+
NotFoundError,
|
|
9
|
+
UpstreamRateLimit,
|
|
10
|
+
UpstreamError,
|
|
11
|
+
UpstreamTimeout,
|
|
12
|
+
InternalError,
|
|
13
|
+
ClientAbortedError,
|
|
14
|
+
ServiceUnavailable,
|
|
15
|
+
} from "../core/errors.js";
|
|
16
|
+
import { classifyError } from "./error-classifier.js";
|
|
17
|
+
|
|
18
|
+
const VALID_STATUSES: ReadonlySet<number> = new Set([
|
|
19
|
+
400, 401, 403, 404, 429, 499, 500, 502, 503, 504,
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
function isValidStatus(code: number): code is QwenProxyStatusCode {
|
|
23
|
+
return VALID_STATUSES.has(code);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function errorForStatus(
|
|
27
|
+
status: QwenProxyStatusCode,
|
|
28
|
+
message: string,
|
|
29
|
+
): QwenProxyError {
|
|
30
|
+
switch (status) {
|
|
31
|
+
case 400:
|
|
32
|
+
return new ValidationError(message);
|
|
33
|
+
case 401:
|
|
34
|
+
return new AuthError(message);
|
|
35
|
+
case 403:
|
|
36
|
+
return new ForbiddenError(message);
|
|
37
|
+
case 404:
|
|
38
|
+
return new NotFoundError(message);
|
|
39
|
+
case 429:
|
|
40
|
+
return new UpstreamRateLimit(message);
|
|
41
|
+
case 499:
|
|
42
|
+
return new ClientAbortedError(message);
|
|
43
|
+
case 500:
|
|
44
|
+
return new InternalError(message);
|
|
45
|
+
case 502:
|
|
46
|
+
return new UpstreamError(message);
|
|
47
|
+
case 503:
|
|
48
|
+
return new ServiceUnavailable(message);
|
|
49
|
+
case 504:
|
|
50
|
+
return new UpstreamTimeout(message);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Sends a standardized OpenAI-compatible error response.
|
|
56
|
+
* Handles QwenProxyError directly, checks upstreamStatus hints on plain errors,
|
|
57
|
+
* and falls back to the error classifier.
|
|
58
|
+
*/
|
|
59
|
+
export function sendOpenAIError(
|
|
60
|
+
c: Context,
|
|
61
|
+
err: unknown,
|
|
62
|
+
fallbackStatus?: QwenProxyStatusCode,
|
|
63
|
+
): Response {
|
|
64
|
+
let qwenProxyErr: QwenProxyError;
|
|
65
|
+
|
|
66
|
+
if (err instanceof QwenProxyError) {
|
|
67
|
+
qwenProxyErr = err;
|
|
68
|
+
} else {
|
|
69
|
+
const hint = (err as Record<string, unknown>)?.upstreamStatus;
|
|
70
|
+
if (typeof hint === "number" && isValidStatus(hint)) {
|
|
71
|
+
qwenProxyErr = errorForStatus(
|
|
72
|
+
hint,
|
|
73
|
+
err instanceof Error ? err.message : String(err),
|
|
74
|
+
);
|
|
75
|
+
} else if (fallbackStatus) {
|
|
76
|
+
qwenProxyErr = errorForStatus(
|
|
77
|
+
fallbackStatus,
|
|
78
|
+
err instanceof Error ? err.message : String(err),
|
|
79
|
+
);
|
|
80
|
+
} else {
|
|
81
|
+
qwenProxyErr = classifyError(err);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const inner = qwenProxyErr.toOpenAI().error;
|
|
86
|
+
const body = {
|
|
87
|
+
error: {
|
|
88
|
+
message: inner.message,
|
|
89
|
+
type: inner.type,
|
|
90
|
+
code: inner.code,
|
|
91
|
+
param: inner.param ?? null,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
// 499 (Client Closed Request) is not part of Hono's ContentfulStatusCode
|
|
95
|
+
// union. The abort is intercepted before sendOpenAIError in the chat route,
|
|
96
|
+
// but keep the fallback type-safe by building the Response directly.
|
|
97
|
+
if (qwenProxyErr.statusCode === 499) {
|
|
98
|
+
return new Response(JSON.stringify(body), {
|
|
99
|
+
status: 499,
|
|
100
|
+
headers: { "content-type": "application/json" },
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return c.json(body, qwenProxyErr.statusCode);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Creates a QwenProxyError mapped to the given HTTP status code.
|
|
108
|
+
* Useful for inline error returns without throwing.
|
|
109
|
+
*/
|
|
110
|
+
export function createError(
|
|
111
|
+
status: QwenProxyStatusCode,
|
|
112
|
+
message: string,
|
|
113
|
+
param?: string,
|
|
114
|
+
): QwenProxyError {
|
|
115
|
+
const err = errorForStatus(status, message);
|
|
116
|
+
if (param) err.param = param;
|
|
117
|
+
return err;
|
|
118
|
+
}
|