qwenproxy-cli 1.0.2 → 1.0.3
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 +1 -1
- package/src/api/server.ts +1 -0
- package/src/tui/app.ts +13 -1
- package/src/tui/proxy-client.ts +11 -1
- package/src/tui/types.ts +1 -0
- package/src/tui/views/accounts-view.ts +6 -2
- package/src/tui/views/status-view.ts +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qwenproxy-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
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": {
|
package/src/api/server.ts
CHANGED
|
@@ -269,6 +269,7 @@ app.get("/health", async (c) => {
|
|
|
269
269
|
: undefined,
|
|
270
270
|
timestamp: Date.now(),
|
|
271
271
|
readyAccounts: (await import("../core/account-manager.js")).getHeadersReadyAccountIds(),
|
|
272
|
+
activeAccounts: (await import("../services/playwright.js")).getActivePlaywrightAccountIds(),
|
|
272
273
|
metrics: {
|
|
273
274
|
cache: await cache?.getStats(),
|
|
274
275
|
},
|
package/src/tui/app.ts
CHANGED
|
@@ -7,7 +7,19 @@ import type { TuiView, ProxyStatusSnapshot } from "./types.ts";
|
|
|
7
7
|
import { theme, glyphs, drawBox, stringWidth } from "./theme.ts";
|
|
8
8
|
import { fetchProxyStatus } from "./proxy-client.ts";
|
|
9
9
|
import { ServerManager } from "./server-manager.ts";
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
10
13
|
|
|
14
|
+
let cachedAppVersion = "v1.0.2";
|
|
15
|
+
try {
|
|
16
|
+
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const pkgPath = path.resolve(currentDir, "../../package.json");
|
|
18
|
+
if (fs.existsSync(pkgPath)) {
|
|
19
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
20
|
+
if (pkg.version) cachedAppVersion = `v${pkg.version}`;
|
|
21
|
+
}
|
|
22
|
+
} catch {}
|
|
11
23
|
import { StatusView } from "./views/status-view.ts";
|
|
12
24
|
import { ChatView } from "./views/chat-view.ts";
|
|
13
25
|
import { SyncView } from "./views/sync-view.ts";
|
|
@@ -240,7 +252,7 @@ export class TuiApp {
|
|
|
240
252
|
|
|
241
253
|
const headerContent = [` ${tabsBar}`];
|
|
242
254
|
const headerBox = drawBox({
|
|
243
|
-
title: `QwenProxy
|
|
255
|
+
title: `QwenProxy ${cachedAppVersion} ${statusChip}`,
|
|
244
256
|
width: cols,
|
|
245
257
|
height: 3,
|
|
246
258
|
borderColor: theme.borderActive,
|
package/src/tui/proxy-client.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
clearAccountCooldown,
|
|
11
11
|
isAccountHeadersReady,
|
|
12
12
|
} from "../core/account-manager.ts";
|
|
13
|
+
import { isPlaywrightInitialized } from "../services/playwright.ts";
|
|
13
14
|
import { getAccountConcurrencySnapshot } from "../core/account-concurrency.ts";
|
|
14
15
|
import { getRssUsageSnapshot } from "../core/memory-usage.ts";
|
|
15
16
|
import type { ProxyStatusSnapshot } from "./types.ts";
|
|
@@ -46,12 +47,14 @@ let cachedAccounts: Array<{
|
|
|
46
47
|
onCooldown: boolean;
|
|
47
48
|
remainingCooldownMs: number;
|
|
48
49
|
headersReady: boolean;
|
|
50
|
+
isInitialized: boolean;
|
|
49
51
|
}> = [];
|
|
50
52
|
let lastAccountsFetch = 0;
|
|
51
53
|
let isHealthCheckPending = false;
|
|
52
54
|
let lastOnlineState = false;
|
|
53
55
|
let lastOverallStatus = "offline";
|
|
54
56
|
let lastServerReadyAccounts: Set<string> | null = null;
|
|
57
|
+
let lastServerActiveAccounts: Set<string> | null = null;
|
|
55
58
|
export async function fetchProxyStatus(): Promise<ProxyStatusSnapshot> {
|
|
56
59
|
const port = config.server?.port || 7936;
|
|
57
60
|
const configuredHost = config.server?.host;
|
|
@@ -73,9 +76,13 @@ export async function fetchProxyStatus(): Promise<ProxyStatusSnapshot> {
|
|
|
73
76
|
if (Array.isArray(data.readyAccounts)) {
|
|
74
77
|
lastServerReadyAccounts = new Set(data.readyAccounts);
|
|
75
78
|
}
|
|
79
|
+
if (Array.isArray(data.activeAccounts)) {
|
|
80
|
+
lastServerActiveAccounts = new Set(data.activeAccounts);
|
|
81
|
+
}
|
|
76
82
|
} else {
|
|
77
83
|
lastOnlineState = false;
|
|
78
84
|
lastServerReadyAccounts = null;
|
|
85
|
+
lastServerActiveAccounts = null;
|
|
79
86
|
}
|
|
80
87
|
})
|
|
81
88
|
.catch(() => {
|
|
@@ -104,6 +111,9 @@ export async function fetchProxyStatus(): Promise<ProxyStatusSnapshot> {
|
|
|
104
111
|
const headersReady = lastServerReadyAccounts !== null
|
|
105
112
|
? lastServerReadyAccounts.has(acc.id)
|
|
106
113
|
: isAccountHeadersReady(acc.id);
|
|
114
|
+
const isInitialized = lastServerActiveAccounts !== null
|
|
115
|
+
? lastServerActiveAccounts.has(acc.id)
|
|
116
|
+
: isPlaywrightInitialized(acc.id);
|
|
107
117
|
return {
|
|
108
118
|
id: acc.id,
|
|
109
119
|
emailOrName: maskAccountIdentifier(acc.email || acc.id),
|
|
@@ -112,10 +122,10 @@ export async function fetchProxyStatus(): Promise<ProxyStatusSnapshot> {
|
|
|
112
122
|
onCooldown,
|
|
113
123
|
remainingCooldownMs,
|
|
114
124
|
headersReady,
|
|
125
|
+
isInitialized,
|
|
115
126
|
};
|
|
116
127
|
});
|
|
117
128
|
}
|
|
118
|
-
|
|
119
129
|
const accounts = cachedAccounts;
|
|
120
130
|
const online = lastOnlineState;
|
|
121
131
|
const overallStatus = lastOverallStatus;
|
package/src/tui/types.ts
CHANGED
|
@@ -497,7 +497,9 @@ export class AccountsView implements TuiView {
|
|
|
497
497
|
const mins = Math.max(1, Math.round(acc.remainingCooldownMs / 60000));
|
|
498
498
|
status = theme.yellow(`⚠ ${mins}m cd `);
|
|
499
499
|
} else if (!acc.headersReady) {
|
|
500
|
-
status =
|
|
500
|
+
status = acc.isInitialized
|
|
501
|
+
? theme.yellow(`◐ Aquecendo...`)
|
|
502
|
+
: theme.muted(`○ Standby `);
|
|
501
503
|
}
|
|
502
504
|
|
|
503
505
|
const line = `${pointer}${num}${name}${status}`;
|
|
@@ -550,7 +552,9 @@ export class AccountsView implements TuiView {
|
|
|
550
552
|
|
|
551
553
|
const hStatus = selected.headersReady
|
|
552
554
|
? theme.green(`${glyphs.check} Capturados`)
|
|
553
|
-
:
|
|
555
|
+
: selected.isInitialized
|
|
556
|
+
? theme.yellow(`◐ Aquecendo...`)
|
|
557
|
+
: theme.muted(`${glyphs.circle} Standby (Sob Demanda)`);
|
|
554
558
|
rightContent.push(` ${theme.bold("Headers:")} ${hStatus}`);
|
|
555
559
|
rightContent.push("");
|
|
556
560
|
rightContent.push(` ${theme.dim("─────────────────────────────────")}`);
|
|
@@ -175,7 +175,9 @@ export class StatusView implements TuiView {
|
|
|
175
175
|
const mins = Math.max(1, Math.round(acc.remainingCooldownMs / 60000));
|
|
176
176
|
status = theme.yellow(`⚠ Cooldown ${mins}m`);
|
|
177
177
|
} else if (!acc.headersReady) {
|
|
178
|
-
status =
|
|
178
|
+
status = acc.isInitialized
|
|
179
|
+
? theme.yellow(`◐ Aquecendo...`)
|
|
180
|
+
: theme.muted(`○ Standby`);
|
|
179
181
|
}
|
|
180
182
|
rightContent.push(` ${num} ${name} ${status}`);
|
|
181
183
|
});
|