webaiapi 0.0.0-stage → 0.1.0
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 +21 -0
- package/README.md +184 -2
- package/bin/webapi.mjs +45 -0
- package/dist/browser/auth-capture.d.ts +110 -0
- package/dist/browser/auth-capture.d.ts.map +1 -0
- package/dist/browser/auth-capture.js +487 -0
- package/dist/browser/auth-capture.js.map +1 -0
- package/dist/browser/credentials.d.ts +102 -0
- package/dist/browser/credentials.d.ts.map +1 -0
- package/dist/browser/credentials.js +209 -0
- package/dist/browser/credentials.js.map +1 -0
- package/dist/browser/js-eval.d.ts +44 -0
- package/dist/browser/js-eval.d.ts.map +1 -0
- package/dist/browser/js-eval.js +20 -0
- package/dist/browser/js-eval.js.map +1 -0
- package/dist/browser/login-flow.d.ts +171 -0
- package/dist/browser/login-flow.d.ts.map +1 -0
- package/dist/browser/login-flow.js +606 -0
- package/dist/browser/login-flow.js.map +1 -0
- package/dist/browser/manager.d.ts +144 -0
- package/dist/browser/manager.d.ts.map +1 -0
- package/dist/browser/manager.js +586 -0
- package/dist/browser/manager.js.map +1 -0
- package/dist/browser/platforms.d.ts +96 -0
- package/dist/browser/platforms.d.ts.map +1 -0
- package/dist/browser/platforms.js +288 -0
- package/dist/browser/platforms.js.map +1 -0
- package/dist/browser/sse-capture.d.ts +23 -0
- package/dist/browser/sse-capture.d.ts.map +1 -0
- package/dist/browser/sse-capture.js +199 -0
- package/dist/browser/sse-capture.js.map +1 -0
- package/dist/browser/stealth.d.ts +12 -0
- package/dist/browser/stealth.d.ts.map +1 -0
- package/dist/browser/stealth.js +12 -0
- package/dist/browser/stealth.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +441 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +90 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +246 -0
- package/dist/config.js.map +1 -0
- package/dist/controllers/history-db.d.ts +56 -0
- package/dist/controllers/history-db.d.ts.map +1 -0
- package/dist/controllers/history-db.js +260 -0
- package/dist/controllers/history-db.js.map +1 -0
- package/dist/controllers/request-pool.d.ts +78 -0
- package/dist/controllers/request-pool.d.ts.map +1 -0
- package/dist/controllers/request-pool.js +222 -0
- package/dist/controllers/request-pool.js.map +1 -0
- package/dist/controllers/router.d.ts +172 -0
- package/dist/controllers/router.d.ts.map +1 -0
- package/dist/controllers/router.js +569 -0
- package/dist/controllers/router.js.map +1 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/log/api-logger.d.ts +55 -0
- package/dist/log/api-logger.d.ts.map +1 -0
- package/dist/log/api-logger.js +264 -0
- package/dist/log/api-logger.js.map +1 -0
- package/dist/log/debug-logger.d.ts +49 -0
- package/dist/log/debug-logger.d.ts.map +1 -0
- package/dist/log/debug-logger.js +285 -0
- package/dist/log/debug-logger.js.map +1 -0
- package/dist/log/logger.d.ts +16 -0
- package/dist/log/logger.d.ts.map +1 -0
- package/dist/log/logger.js +35 -0
- package/dist/log/logger.js.map +1 -0
- package/dist/postinstall.d.ts +3 -0
- package/dist/postinstall.d.ts.map +1 -0
- package/dist/postinstall.js +90 -0
- package/dist/postinstall.js.map +1 -0
- package/dist/providers/base.d.ts +83 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +51 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/chatglm-dom-extract.d.ts +24 -0
- package/dist/providers/chatglm-dom-extract.d.ts.map +1 -0
- package/dist/providers/chatglm-dom-extract.js +175 -0
- package/dist/providers/chatglm-dom-extract.js.map +1 -0
- package/dist/providers/chatglm-dom.d.ts +110 -0
- package/dist/providers/chatglm-dom.d.ts.map +1 -0
- package/dist/providers/chatglm-dom.js +384 -0
- package/dist/providers/chatglm-dom.js.map +1 -0
- package/dist/providers/chatglm-sse.d.ts +119 -0
- package/dist/providers/chatglm-sse.d.ts.map +1 -0
- package/dist/providers/chatglm-sse.js +241 -0
- package/dist/providers/chatglm-sse.js.map +1 -0
- package/dist/providers/chatglm.d.ts +288 -0
- package/dist/providers/chatglm.d.ts.map +1 -0
- package/dist/providers/chatglm.js +1631 -0
- package/dist/providers/chatglm.js.map +1 -0
- package/dist/routes/chat.d.ts +117 -0
- package/dist/routes/chat.d.ts.map +1 -0
- package/dist/routes/chat.js +1346 -0
- package/dist/routes/chat.js.map +1 -0
- package/dist/routes/compress.d.ts +142 -0
- package/dist/routes/compress.d.ts.map +1 -0
- package/dist/routes/compress.js +551 -0
- package/dist/routes/compress.js.map +1 -0
- package/dist/routes/failover.d.ts +34 -0
- package/dist/routes/failover.d.ts.map +1 -0
- package/dist/routes/failover.js +221 -0
- package/dist/routes/failover.js.map +1 -0
- package/dist/routes/helpers.d.ts +174 -0
- package/dist/routes/helpers.d.ts.map +1 -0
- package/dist/routes/helpers.js +525 -0
- package/dist/routes/helpers.js.map +1 -0
- package/dist/routes/meta.d.ts +31 -0
- package/dist/routes/meta.d.ts.map +1 -0
- package/dist/routes/meta.js +184 -0
- package/dist/routes/meta.js.map +1 -0
- package/dist/routes/sse.d.ts +82 -0
- package/dist/routes/sse.d.ts.map +1 -0
- package/dist/routes/sse.js +77 -0
- package/dist/routes/sse.js.map +1 -0
- package/dist/server/app.d.ts +24 -0
- package/dist/server/app.d.ts.map +1 -0
- package/dist/server/app.js +292 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/middleware/api-key.d.ts +61 -0
- package/dist/server/middleware/api-key.d.ts.map +1 -0
- package/dist/server/middleware/api-key.js +95 -0
- package/dist/server/middleware/api-key.js.map +1 -0
- package/dist/server/middleware/rate-limit.d.ts +67 -0
- package/dist/server/middleware/rate-limit.d.ts.map +1 -0
- package/dist/server/middleware/rate-limit.js +134 -0
- package/dist/server/middleware/rate-limit.js.map +1 -0
- package/dist/server/middleware/timeout.d.ts +34 -0
- package/dist/server/middleware/timeout.d.ts.map +1 -0
- package/dist/server/middleware/timeout.js +64 -0
- package/dist/server/middleware/timeout.js.map +1 -0
- package/dist/server/types.d.ts +20 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +2 -0
- package/dist/server/types.js.map +1 -0
- package/dist/tools/build.d.ts +14 -0
- package/dist/tools/build.d.ts.map +1 -0
- package/dist/tools/build.js +105 -0
- package/dist/tools/build.js.map +1 -0
- package/dist/tools/clean.d.ts +32 -0
- package/dist/tools/clean.d.ts.map +1 -0
- package/dist/tools/clean.js +65 -0
- package/dist/tools/clean.js.map +1 -0
- package/dist/tools/convert.d.ts +50 -0
- package/dist/tools/convert.d.ts.map +1 -0
- package/dist/tools/convert.js +289 -0
- package/dist/tools/convert.js.map +1 -0
- package/dist/tools/names.d.ts +138 -0
- package/dist/tools/names.d.ts.map +1 -0
- package/dist/tools/names.js +578 -0
- package/dist/tools/names.js.map +1 -0
- package/dist/tools/parse.d.ts +31 -0
- package/dist/tools/parse.d.ts.map +1 -0
- package/dist/tools/parse.js +273 -0
- package/dist/tools/parse.js.map +1 -0
- package/dist/tools/placeholder.d.ts +21 -0
- package/dist/tools/placeholder.d.ts.map +1 -0
- package/dist/tools/placeholder.js +135 -0
- package/dist/tools/placeholder.js.map +1 -0
- package/dist/tools/prompts.d.ts +42 -0
- package/dist/tools/prompts.d.ts.map +1 -0
- package/dist/tools/prompts.js +69 -0
- package/dist/tools/prompts.js.map +1 -0
- package/dist/tools/protocol.d.ts +58 -0
- package/dist/tools/protocol.d.ts.map +1 -0
- package/dist/tools/protocol.js +287 -0
- package/dist/tools/protocol.js.map +1 -0
- package/dist/tools/repair.d.ts +83 -0
- package/dist/tools/repair.d.ts.map +1 -0
- package/dist/tools/repair.js +510 -0
- package/dist/tools/repair.js.map +1 -0
- package/dist/tools/workspace.d.ts +40 -0
- package/dist/tools/workspace.d.ts.map +1 -0
- package/dist/tools/workspace.js +224 -0
- package/dist/tools/workspace.js.map +1 -0
- package/dist/types/message.d.ts +87 -0
- package/dist/types/message.d.ts.map +1 -0
- package/dist/types/message.js +85 -0
- package/dist/types/message.js.map +1 -0
- package/dist/types/openai.d.ts +100 -0
- package/dist/types/openai.d.ts.map +1 -0
- package/dist/types/openai.js +66 -0
- package/dist/types/openai.js.map +1 -0
- package/dist/utils/errors.d.ts +82 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +115 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/mutex.d.ts +31 -0
- package/dist/utils/mutex.d.ts.map +1 -0
- package/dist/utils/mutex.js +61 -0
- package/dist/utils/mutex.js.map +1 -0
- package/dist/utils/prompt.d.ts +150 -0
- package/dist/utils/prompt.d.ts.map +1 -0
- package/dist/utils/prompt.js +514 -0
- package/dist/utils/prompt.js.map +1 -0
- package/dist/utils/text.d.ts +30 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +70 -0
- package/dist/utils/text.js.map +1 -0
- package/package.json +67 -4
- package/postinstall.mjs +34 -0
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模型路由器 —— `legacy-python/src/controllers/router.py` 的 TypeScript 移植。
|
|
3
|
+
*
|
|
4
|
+
* 职责:
|
|
5
|
+
* - 注册 Provider,把「模型名 → Provider」映射起来;
|
|
6
|
+
* - `mix` 模型的候选挑选(跨平台);
|
|
7
|
+
* - **辅助通道**:给辅助任务(后台预压缩、两轮转换)挑一个「与主通道不同账号」的
|
|
8
|
+
* Provider 实例,从而能与主对话真正并行(不同账号 → 不同并发额度;不同页面 → 不抢锁)。
|
|
9
|
+
*
|
|
10
|
+
* ## 与原实现的差异
|
|
11
|
+
* - Python 里到处 `from src.browser.cdp_capture import list_accounts, load_auth`
|
|
12
|
+
* (函数内 import,为了绕开循环依赖)。TS 用正常的顶层 import,
|
|
13
|
+
* `credentials.ts` 不依赖 router,不存在循环。
|
|
14
|
+
* - Python 版用 `if platform == "chatglm": ... else: continue` 建 Provider;
|
|
15
|
+
* TS 改成 {@link PROVIDER_FACTORIES} 工厂表,新增平台只改一行
|
|
16
|
+
* (并把它加进 {@link PLATFORM_MODEL_NAMES})。
|
|
17
|
+
* - `getattr(provider, "_account_id")` → `provider.getAccountId()`(显式接口)。
|
|
18
|
+
* - `_identity_of` / `_cookie_fingerprint` 直接复用 `credentials.ts` 的实现
|
|
19
|
+
* (`cookieFingerprint` 用 sha256 取前 32 位;Python 是 sha1——两者都是稳定摘要,
|
|
20
|
+
* 只用于「两凭证是否相同」的**相等比较**,不对外暴露,因此无需逐字节对齐)。
|
|
21
|
+
*/
|
|
22
|
+
import { accountCooldownRemaining, clearAccountRole, getAccountRole, isAccountBusy, setAccountRole, } from '../browser/manager.js';
|
|
23
|
+
import { cookieFingerprint, listAccounts, loadAuth, } from '../browser/credentials.js';
|
|
24
|
+
import { PLATFORMS_WITH_PROVIDER } from '../browser/platforms.js';
|
|
25
|
+
import { logger } from '../log/logger.js';
|
|
26
|
+
import { getAvailableModelsList } from '../config.js';
|
|
27
|
+
import { ChatGLMBrowserProvider } from '../providers/chatglm.js';
|
|
28
|
+
import {} from '../providers/base.js';
|
|
29
|
+
import { ModelNotFoundError } from '../utils/errors.js';
|
|
30
|
+
/**
|
|
31
|
+
* 平台名作为独立模型暴露给用户:调用 `model=<平台名>` 时只调度该平台的 Provider,
|
|
32
|
+
* 不跨平台(与 `mix` 不同)。
|
|
33
|
+
*
|
|
34
|
+
* ⚠️ **本列表由 `browser/platforms.ts` 派生**(`providerImplemented: true` 的平台),
|
|
35
|
+
* 不再手写 —— 手写一份必然会和注册表写岔,而写岔的表现是
|
|
36
|
+
* 「菜单里有这个平台、但 `model=xxx` 报找不到模型」这类难查的问题。
|
|
37
|
+
*
|
|
38
|
+
* 目前只有 chatglm。DeepSeek/Kimi/Qianwen/Doubao/Zhipu 五个 Provider 已于
|
|
39
|
+
* 2026-10-12 删除(它们的 `_ensure_browser()` 调用从不存在的
|
|
40
|
+
* `browser_utils.ensure_browser_page()` → 一调用就 AttributeError,跨平台
|
|
41
|
+
* failover 实际上一直是失效的)。将来要加平台:实现 Provider →
|
|
42
|
+
* 在 `platforms.ts` 里把 `providerImplemented` 翻成 `true` →
|
|
43
|
+
* 在 {@link PROVIDER_FACTORIES} 加一行。有单测核对三者一致。
|
|
44
|
+
*/
|
|
45
|
+
export const PLATFORM_MODEL_NAMES = PLATFORMS_WITH_PROVIDER;
|
|
46
|
+
/**
|
|
47
|
+
* 平台 → Provider 工厂。
|
|
48
|
+
*
|
|
49
|
+
* `channelKey` 非空时创建的是**辅助通道**实例(独立 context + 指定账号,见
|
|
50
|
+
* `ChatGLMBrowserProvider` 的 `channelKey` 参数说明)。
|
|
51
|
+
*/
|
|
52
|
+
const PROVIDER_FACTORIES = {
|
|
53
|
+
chatglm: (accountId, channelKey) => new ChatGLMBrowserProvider({ accountId, channelKey }),
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* **真的**实现了工厂的平台。
|
|
57
|
+
*
|
|
58
|
+
* 存在的唯一理由:让「注册表的 `providerImplemented`」与「工厂表」能被**自动核对**
|
|
59
|
+
* (`PLATFORM_MODEL_NAMES` 是从 `providerImplemented` 派生的,拿它比对是自说自话)。
|
|
60
|
+
* 两者写岔的表现很难查:菜单里能看到这个平台、`model=xxx` 却报找不到模型。
|
|
61
|
+
*
|
|
62
|
+
* ⚠️ 不要在业务逻辑里用它挑平台 —— 那是 {@link PLATFORM_MODEL_NAMES} 的职责。
|
|
63
|
+
*/
|
|
64
|
+
export const PROVIDER_IMPLEMENTED_PLATFORMS = Object.keys(PROVIDER_FACTORIES);
|
|
65
|
+
export class ModelRouter {
|
|
66
|
+
/** Provider 注册表(键 = 平台名)。 */
|
|
67
|
+
providers = new Map();
|
|
68
|
+
/** 模型名 → Provider 名。 */
|
|
69
|
+
modelToProvider = new Map();
|
|
70
|
+
/**
|
|
71
|
+
* 辅助通道 Provider(**平台 → 实例**)。
|
|
72
|
+
*
|
|
73
|
+
* 辅助任务(后台预压缩等)用的「另一个账号 + 独立 context 的专用页面」。
|
|
74
|
+
* 有了它辅助任务才能与主对话**同时**跑。为空时辅助任务回落到主通道(串行,原行为)。
|
|
75
|
+
*/
|
|
76
|
+
auxProviders = new Map();
|
|
77
|
+
auxLastScan = 0;
|
|
78
|
+
/* ---------------- 辅助通道常量 ---------------- */
|
|
79
|
+
/**
|
|
80
|
+
* 目前只有 ChatGLM 的 Provider 实现了「通道页面」(`channelKey`)。
|
|
81
|
+
* 其他平台为什么没启用,见 {@link getAuxCandidates} 的说明。
|
|
82
|
+
*/
|
|
83
|
+
static AUX_CHANNEL_PLATFORMS = ['chatglm'];
|
|
84
|
+
/** 运行中惰性重扫辅助通道的最小间隔(秒):登录完第二个账号后**免重启**。 */
|
|
85
|
+
static AUX_RESCAN_INTERVAL = 30;
|
|
86
|
+
constructor(options = {}) {
|
|
87
|
+
this.registerProviders();
|
|
88
|
+
this.setupAuxChannels(options.verbose ?? true);
|
|
89
|
+
}
|
|
90
|
+
/* ================================================================== */
|
|
91
|
+
/* 主通道账号分配 */
|
|
92
|
+
/* ================================================================== */
|
|
93
|
+
/**
|
|
94
|
+
* 启动时**随机**挑一个账号做主通道(另一个留给辅助通道)。
|
|
95
|
+
*
|
|
96
|
+
* 为什么要随机:主通道是用户对话的主力。如果永远固定用 `default`,
|
|
97
|
+
* 那个账号会先被限流/耗尽额度,而另一个账号一直闲着。随机分配把负载摊到两个账号上。
|
|
98
|
+
*
|
|
99
|
+
* 可用 `CHATGLM_MAIN_ACCOUNT=<id>` 钉死(运维需要时避免每次重启换主力账号)。
|
|
100
|
+
*/
|
|
101
|
+
static pickRandomMainAccount(platform) {
|
|
102
|
+
const pinned = (process.env['CHATGLM_MAIN_ACCOUNT'] ?? '').trim();
|
|
103
|
+
if (pinned) {
|
|
104
|
+
logger.info(`[main] 环境变量 CHATGLM_MAIN_ACCOUNT=${pinned},主通道固定使用该账号`);
|
|
105
|
+
return pinned;
|
|
106
|
+
}
|
|
107
|
+
let usable = [];
|
|
108
|
+
try {
|
|
109
|
+
usable = listAccounts(platform).filter((acc) => (loadAuth(platform, { accountId: acc })?.cookies?.length ?? 0) > 0);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
logger.warn(`[main] 枚举 ${platform} 账号失败: ${String(error)}`);
|
|
113
|
+
}
|
|
114
|
+
if (usable.length === 0)
|
|
115
|
+
return 'default';
|
|
116
|
+
const first = usable[0];
|
|
117
|
+
if (usable.length === 1)
|
|
118
|
+
return first;
|
|
119
|
+
const picked = usable[Math.floor(Math.random() * usable.length)];
|
|
120
|
+
logger.info(`[main] 随机分配主通道账号: ${picked}(候选 ${usable.join(',')})`);
|
|
121
|
+
return picked;
|
|
122
|
+
}
|
|
123
|
+
/** 注册所有 Browser Provider。 */
|
|
124
|
+
registerProviders() {
|
|
125
|
+
// 主通道账号**随机**分配(另一个账号自动成为辅助通道,见 setupAuxChannels)
|
|
126
|
+
const accountId = ModelRouter.pickRandomMainAccount('chatglm');
|
|
127
|
+
this.registerProvider('chatglm', new ChatGLMBrowserProvider({ accountId }));
|
|
128
|
+
logger.info(`已注册 ${this.providers.size} 个 Browser Provider`);
|
|
129
|
+
}
|
|
130
|
+
/** 注册 Provider,并把它声明的所有模型登记进 `modelToProvider`。 */
|
|
131
|
+
registerProvider(name, provider) {
|
|
132
|
+
this.providers.set(name, provider);
|
|
133
|
+
for (const model of provider.getModels()) {
|
|
134
|
+
this.modelToProvider.set(model, name);
|
|
135
|
+
logger.info(`注册模型: ${model} -> ${name}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/* ================================================================== */
|
|
139
|
+
/* 辅助通道 */
|
|
140
|
+
/* ================================================================== */
|
|
141
|
+
/** 取凭证的账号身份标识(用于判断「是不是同一个账号」)。 */
|
|
142
|
+
static identityOf(auth) {
|
|
143
|
+
const info = auth?.account_info ?? {};
|
|
144
|
+
return String(info.identifier ?? '') || String(info.label ?? '');
|
|
145
|
+
}
|
|
146
|
+
/** Cookie 指纹(把两个凭证文件其实是同一登录会话的情况识别出来)。 */
|
|
147
|
+
static cookieFingerprintOf(auth) {
|
|
148
|
+
return cookieFingerprint(auth?.cookies);
|
|
149
|
+
}
|
|
150
|
+
/** 主通道**当前**用的账号(provider 被限流换号后这里会跟着变)。 */
|
|
151
|
+
currentMainAccount(platform) {
|
|
152
|
+
return this.providers.get(platform)?.getAccountId() || 'default';
|
|
153
|
+
}
|
|
154
|
+
/** 该账号是否归主通道使用(避免辅助通道和主通道撞同一个账号)。 */
|
|
155
|
+
isAccountOwnedByMain(platform, accountId) {
|
|
156
|
+
if (accountId === this.currentMainAccount(platform))
|
|
157
|
+
return true;
|
|
158
|
+
return getAccountRole(platform, accountId) === 'main';
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* 为辅助通道挑选「与主通道**不同账号**」的凭证。
|
|
162
|
+
*
|
|
163
|
+
* 策略:**优先同平台的第二个账号**;没有则暂不启用
|
|
164
|
+
* (其他平台的独立通道尚未实现,原因见 {@link getAuxCandidates})。
|
|
165
|
+
*
|
|
166
|
+
* @param verbose 没有通道时是否打日志。启动时 true;运行中惰性重扫时 false,
|
|
167
|
+
* 避免每分钟刷一条「未启用」。
|
|
168
|
+
*/
|
|
169
|
+
setupAuxChannels(verbose = false) {
|
|
170
|
+
for (const platform of ModelRouter.AUX_CHANNEL_PLATFORMS) {
|
|
171
|
+
const provider = this.providers.get(platform);
|
|
172
|
+
if (!provider)
|
|
173
|
+
continue;
|
|
174
|
+
const mainAccount = provider.getAccountId() || 'default';
|
|
175
|
+
const mainAuth = loadAuth(platform, { accountId: mainAccount });
|
|
176
|
+
const mainIdentity = ModelRouter.identityOf(mainAuth);
|
|
177
|
+
const mainFp = ModelRouter.cookieFingerprintOf(mainAuth);
|
|
178
|
+
let accounts;
|
|
179
|
+
try {
|
|
180
|
+
accounts = listAccounts(platform);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
logger.warn(`[aux] 列出 ${platform} 账号失败: ${String(error)}`);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
for (const acc of accounts) {
|
|
187
|
+
if (acc === mainAccount)
|
|
188
|
+
continue;
|
|
189
|
+
// 主通道被限流后会**换账号**:换过去之后那个账号就成了主账号。
|
|
190
|
+
// 这里必须按「当前角色」过滤,不能只看 mainAccount:
|
|
191
|
+
// - 角色是 main → 主通道在用,辅助不能碰;
|
|
192
|
+
// - 正在被主通道干活(busy)→ 更不能用;
|
|
193
|
+
// - 在冷却中(刚被限流)→ 辅助用了也会被拒。
|
|
194
|
+
if (this.isAccountOwnedByMain(platform, acc))
|
|
195
|
+
continue;
|
|
196
|
+
if (isAccountBusy(platform, acc)) {
|
|
197
|
+
logger.info(`[aux] 账号 ${acc} 正被主通道使用,跳过`);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const cooldown = accountCooldownRemaining(platform, acc);
|
|
201
|
+
if (cooldown > 0) {
|
|
202
|
+
logger.info(`[aux] 账号 ${acc} 仍在冷却中(剩余 ${cooldown.toFixed(0)}s),跳过`);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const auth = loadAuth(platform, { accountId: acc });
|
|
206
|
+
if (!auth?.cookies?.length)
|
|
207
|
+
continue;
|
|
208
|
+
const identity = ModelRouter.identityOf(auth);
|
|
209
|
+
if (mainIdentity && identity && identity === mainIdentity) {
|
|
210
|
+
// 同一账号换个文件名:并行会立刻触发「请等待其他对话生成完毕」
|
|
211
|
+
logger.warn(`[aux] 账号 ${acc} 与主账号身份相同(${identity}),不能用于并行辅助通道,跳过`);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (mainFp && ModelRouter.cookieFingerprintOf(auth) === mainFp) {
|
|
215
|
+
logger.warn(`[aux] 账号 ${acc} 的 Cookie 与主账号**完全相同**(同一个登录会话),` +
|
|
216
|
+
'不能用于并行辅助通道,跳过');
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
const factory = PROVIDER_FACTORIES[platform];
|
|
220
|
+
if (!factory)
|
|
221
|
+
continue;
|
|
222
|
+
let auxProvider;
|
|
223
|
+
try {
|
|
224
|
+
auxProvider = factory(acc, `${platform}:${acc}`);
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
logger.warn(`[aux] 创建 ${platform}/${acc} 辅助通道失败: ${String(error)}`);
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
this.auxProviders.set(platform, auxProvider);
|
|
231
|
+
// 登记角色:主通道换号时靠它避开这个账号
|
|
232
|
+
setAccountRole(platform, acc, 'aux');
|
|
233
|
+
logger.info(`[aux] 辅助通道已启用: ${platform}/${acc}` +
|
|
234
|
+
`(身份 ${identity || '未知'},主账号 ${mainAccount}/` +
|
|
235
|
+
`${mainIdentity || '未知'} → 与主通道不同账号,可并行)`);
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (this.auxProviders.size === 0 && verbose) {
|
|
240
|
+
logger.info('[aux] 未启用辅助通道(同平台只有一个账号)→ 辅助任务与主对话串行');
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* 辅助任务(压缩 / 两轮转换等)可用的通道列表。
|
|
245
|
+
*
|
|
246
|
+
* 顺序与理由:
|
|
247
|
+
* 1. **同平台的第二个账号**(独立通道)—— 不同账号、不同页面、不同锁,
|
|
248
|
+
* 可以与主对话真正并行,且不占用主账号的并发额度。
|
|
249
|
+
* 2. 其他平台 —— **当前不存在**:原先那批 Provider 都用**全局共享页面**
|
|
250
|
+
* (`playwright_manager._page`),与主通道并行会互相劫持页面(这是架构问题,
|
|
251
|
+
* 不是额度问题),且实现差异很大(例如会把消息截断到 8000 字符,
|
|
252
|
+
* 而压缩动辄几万字符 → 必然被截断损坏)。它们已于 2026-10-12 整体删除。
|
|
253
|
+
* 将来新增平台要启用辅助通道:先实现 `channelKey` 独立 context 页面,
|
|
254
|
+
* 再把平台名加进 {@link AUX_CHANNEL_PLATFORMS}。
|
|
255
|
+
* 3. 调用方拿不到候选时**回落到主候选**(同账号同页面 → 与主对话串行),
|
|
256
|
+
* 保证功能不退化。
|
|
257
|
+
*
|
|
258
|
+
* @returns 三元组列表;空列表表示没有独立通道可用,调用方应回落主候选。
|
|
259
|
+
*/
|
|
260
|
+
getAuxCandidates() {
|
|
261
|
+
const platform = ModelRouter.AUX_CHANNEL_PLATFORMS[0];
|
|
262
|
+
const now = Date.now() / 1000;
|
|
263
|
+
if (!this.auxProviders.has(platform)) {
|
|
264
|
+
// 惰性重扫:用户刚登录完第二个账号时**不需要重启服务**
|
|
265
|
+
// (每 30s 最多重扫一次,成本只是读几个 json 文件)
|
|
266
|
+
if (now - this.auxLastScan > ModelRouter.AUX_RESCAN_INTERVAL) {
|
|
267
|
+
this.auxLastScan = now;
|
|
268
|
+
try {
|
|
269
|
+
this.setupAuxChannels(false);
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
logger.warn(`[aux] 重扫辅助通道失败: ${String(error)}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
// 已有通道:每次使用前做一次廉价校验,以下几种情况必须**撤销**通道
|
|
278
|
+
// (辅助任务回落主通道串行执行,功能不退化,只是慢):
|
|
279
|
+
// 1) 凭证文件消失 / 没有 Cookie;
|
|
280
|
+
// 2) **账号已被主通道接管** —— 主通道被限流后会换到这个账号,
|
|
281
|
+
// 两边同时用同一个账号会立刻触发「请等待其他对话生成完毕」;
|
|
282
|
+
// 3) 账号正在冷却(刚被限流),用了也只会被拒。
|
|
283
|
+
const provider = this.auxProviders.get(platform);
|
|
284
|
+
const acc = provider?.getAccountId();
|
|
285
|
+
let revoke = null;
|
|
286
|
+
try {
|
|
287
|
+
const auth = acc ? loadAuth(platform, { accountId: acc }) : null;
|
|
288
|
+
if (!acc) {
|
|
289
|
+
revoke = '账号未知';
|
|
290
|
+
}
|
|
291
|
+
else if (this.isAccountOwnedByMain(platform, acc)) {
|
|
292
|
+
revoke = '该账号已被主通道接管(主通道被限流后切到了这里)';
|
|
293
|
+
}
|
|
294
|
+
else if (accountCooldownRemaining(platform, acc) > 0) {
|
|
295
|
+
revoke = `该账号在冷却中(剩余 ${accountCooldownRemaining(platform, acc).toFixed(0)}s)`;
|
|
296
|
+
}
|
|
297
|
+
else if (!auth?.cookies?.length) {
|
|
298
|
+
revoke = '凭证不可用(文件缺失或无 Cookie)';
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
// 校验失败不影响主流程(保守起见不撤销)
|
|
303
|
+
}
|
|
304
|
+
if (revoke) {
|
|
305
|
+
logger.warn(`[aux] 撤销辅助通道 ${platform}/${acc}:${revoke} → 辅助任务回落主通道`);
|
|
306
|
+
clearAccountRole(platform, acc ?? '', 'aux');
|
|
307
|
+
this.auxProviders.delete(platform);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const provider = this.auxProviders.get(platform);
|
|
311
|
+
if (!provider)
|
|
312
|
+
return [];
|
|
313
|
+
return [[platform, provider, 1]];
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* 账号总览:每个平台的账号、身份、以及它被用作 main / aux 还是闲置。
|
|
317
|
+
*
|
|
318
|
+
* 用途:把「多账号到底有没有生效」变成可验证的事实(`/v1/status`)。
|
|
319
|
+
* 实测踩坑:登录了两个账号但其实是同一个(浏览器里还是旧账号的登录态),
|
|
320
|
+
* 只看「账号数」看不出来,看身份才能。
|
|
321
|
+
*/
|
|
322
|
+
getAccountsSummary() {
|
|
323
|
+
const out = {};
|
|
324
|
+
for (const platform of PLATFORM_MODEL_NAMES) {
|
|
325
|
+
let accounts = [];
|
|
326
|
+
try {
|
|
327
|
+
accounts = listAccounts(platform);
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
accounts = [];
|
|
331
|
+
}
|
|
332
|
+
if (accounts.length === 0)
|
|
333
|
+
continue;
|
|
334
|
+
const auxAccount = this.auxProviders.get(platform)?.getAccountId();
|
|
335
|
+
const mainAccount = this.providers.get(platform)?.getAccountId() || 'default';
|
|
336
|
+
out[platform] = accounts.map((acc) => {
|
|
337
|
+
const auth = loadAuth(platform, { accountId: acc }) ?? {};
|
|
338
|
+
const info = auth.account_info ?? {};
|
|
339
|
+
const roles = [];
|
|
340
|
+
if (acc === mainAccount)
|
|
341
|
+
roles.push('main');
|
|
342
|
+
if (auxAccount && acc === auxAccount)
|
|
343
|
+
roles.push('aux');
|
|
344
|
+
return {
|
|
345
|
+
account_id: acc,
|
|
346
|
+
identity: String(info.label ?? '') || String(info.identifier ?? ''),
|
|
347
|
+
cookies: auth.cookies?.length ?? 0,
|
|
348
|
+
roles: roles.length > 0 ? roles : ['unused'],
|
|
349
|
+
// 被平台限流过的账号会进入冷却,冷却期内主通道不再优先用它
|
|
350
|
+
cooldown_seconds: Math.round(accountCooldownRemaining(platform, acc) * 10) / 10,
|
|
351
|
+
busy: isAccountBusy(platform, acc),
|
|
352
|
+
};
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
return out;
|
|
356
|
+
}
|
|
357
|
+
/* ================================================================== */
|
|
358
|
+
/* 模型 → Provider 路由 */
|
|
359
|
+
/* ================================================================== */
|
|
360
|
+
/**
|
|
361
|
+
* 根据模型名取 Provider。
|
|
362
|
+
*
|
|
363
|
+
* 策略:
|
|
364
|
+
* - `mix`:跨平台调度,按优先级依次尝试各平台;
|
|
365
|
+
* - 平台名(如 `chatglm`):直接返回该平台的 Provider;
|
|
366
|
+
* - 具体模型名(如 `glm-4`):映射到对应平台的 Provider。
|
|
367
|
+
*
|
|
368
|
+
* @throws {ModelNotFoundError} 模型不可用 / 凭证失效
|
|
369
|
+
*/
|
|
370
|
+
async getProvider(model) {
|
|
371
|
+
if (!this.isModelAvailable(model)) {
|
|
372
|
+
throw new ModelNotFoundError(model);
|
|
373
|
+
}
|
|
374
|
+
if (model === 'mix') {
|
|
375
|
+
return this.getBestProvider();
|
|
376
|
+
}
|
|
377
|
+
// 平台名作为模型:直接返回对应平台的 Provider
|
|
378
|
+
if (PLATFORM_MODEL_NAMES.includes(model)) {
|
|
379
|
+
const provider = this.providers.get(model);
|
|
380
|
+
if (!provider) {
|
|
381
|
+
throw new ModelNotFoundError(model);
|
|
382
|
+
}
|
|
383
|
+
// 检查登录状态。注意 `checkLoginStatus()` 失败只作为**错误**抛出,
|
|
384
|
+
// 不参与 mix 候选排序(见 getMixCandidates 的说明)。
|
|
385
|
+
try {
|
|
386
|
+
const usable = await provider.checkLoginStatus();
|
|
387
|
+
if (!usable) {
|
|
388
|
+
throw new ModelNotFoundError(model);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
catch (error) {
|
|
392
|
+
if (error instanceof ModelNotFoundError)
|
|
393
|
+
throw error;
|
|
394
|
+
logger.warn(`检查 ${model} 登录状态失败: ${String(error)}`);
|
|
395
|
+
}
|
|
396
|
+
return provider;
|
|
397
|
+
}
|
|
398
|
+
const providerName = this.modelToProvider.get(model);
|
|
399
|
+
if (!providerName) {
|
|
400
|
+
throw new ModelNotFoundError(model);
|
|
401
|
+
}
|
|
402
|
+
const provider = this.providers.get(providerName);
|
|
403
|
+
if (!provider) {
|
|
404
|
+
throw new ModelNotFoundError(model);
|
|
405
|
+
}
|
|
406
|
+
try {
|
|
407
|
+
const usable = await provider.checkLoginStatus();
|
|
408
|
+
if (!usable) {
|
|
409
|
+
throw new ModelNotFoundError(model);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
if (error instanceof ModelNotFoundError)
|
|
414
|
+
throw error;
|
|
415
|
+
logger.warn(`检查 ${model} 登录状态失败: ${String(error)}`);
|
|
416
|
+
}
|
|
417
|
+
return provider;
|
|
418
|
+
}
|
|
419
|
+
/** 自动选择最优 Provider(`mix`:按优先级取第一个候选)。 */
|
|
420
|
+
async getBestProvider() {
|
|
421
|
+
const candidates = await this.getMixCandidates();
|
|
422
|
+
const best = candidates[0];
|
|
423
|
+
if (best) {
|
|
424
|
+
logger.info(`使用 ${best[0]} (浏览器自动化, ${best[2]} 个账号)`);
|
|
425
|
+
return best[1];
|
|
426
|
+
}
|
|
427
|
+
throw new ModelNotFoundError('mix(没有可用的 Provider,请先运行 `npx webaiapi login chatglm` 捕获凭证)');
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* `mix` 模式的候选 Provider 列表。
|
|
431
|
+
*
|
|
432
|
+
* ## ⚠️ 排序与兜底(2026-09-29 修正,不可回退)
|
|
433
|
+
* 1. **平台优先顺序固定按 {@link PLATFORM_MODEL_NAMES}**(chatglm 第一)。
|
|
434
|
+
* 登录检查的结果**只用来告警,不决定谁先谁后,更不能把平台整体剔除**。
|
|
435
|
+
* 原因:chatglm 的 `checkLoginStatus()` 是**整页 DOM 探测**,刚重启 / 页面未就绪
|
|
436
|
+
* 时会误判「未登录」。若按「已验证优先」排序,一次探测抖动就会把 chatglm
|
|
437
|
+
* 排到后面甚至完全丢失 —— 2026-09-29 22:46 实测:`model=mix` 直接打到了
|
|
438
|
+
* (当时还注册着、但从来不可用的)deepseek/kimi,报
|
|
439
|
+
* `browser_utils has no attribute ensure_browser_page`,chatglm 压根没被尝试。
|
|
440
|
+
* (那批坏 Provider 已于 2026-10-12 删除,但这条规则仍要遵守:将来新增平台时
|
|
441
|
+
* 同样的抖动还会发生。)
|
|
442
|
+
* 2. **有账号的平台全部保留**(未通过登录检查的排在同优先级之后),
|
|
443
|
+
* 避免一次误判导致「所有平台均不可用」。
|
|
444
|
+
*/
|
|
445
|
+
async getMixCandidates() {
|
|
446
|
+
const candidates = [];
|
|
447
|
+
// 登录检查未通过但有账号的平台(兜底候选)
|
|
448
|
+
const unverified = [];
|
|
449
|
+
logger.info('[_get_mix_candidates] 开始扫描所有平台...');
|
|
450
|
+
for (const platform of PLATFORM_MODEL_NAMES) {
|
|
451
|
+
const provider = this.providers.get(platform);
|
|
452
|
+
if (!provider) {
|
|
453
|
+
logger.debug(`[_get_mix_candidates] 平台 ${platform} 无 Provider,跳过`);
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
try {
|
|
457
|
+
const accounts = listAccounts(platform);
|
|
458
|
+
logger.info(`[_get_mix_candidates] 平台 ${platform}: ${accounts.length} 个账号`);
|
|
459
|
+
if (accounts.length === 0) {
|
|
460
|
+
logger.debug(`[_get_mix_candidates] 平台 ${platform} 无可用账号,跳过`);
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
logger.info(`[_get_mix_candidates] 平台 ${platform}: 检查登录状态...`);
|
|
464
|
+
const usable = await provider.checkLoginStatus();
|
|
465
|
+
if (usable) {
|
|
466
|
+
candidates.push([platform, provider, accounts.length]);
|
|
467
|
+
logger.info(`[_get_mix_candidates] 平台 ${platform} 可用,加入候选列表`);
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
// 不直接淘汰:登录检查可能因页面正在重建/DOM 未就绪而误判,
|
|
471
|
+
// 若因此把唯一平台剔除,会出现「聊着聊着突然全平台不可用」。
|
|
472
|
+
unverified.push([platform, provider, accounts.length]);
|
|
473
|
+
logger.warn(`[_get_mix_candidates] 平台 ${platform} 登录检查未通过,记为兜底候选`);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
catch (error) {
|
|
477
|
+
logger.warn(`[_get_mix_candidates] 检查平台 ${platform} 时异常: ` +
|
|
478
|
+
`${error instanceof Error ? error.name : 'Error'}: ${String(error)}`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
const priority = new Map(PLATFORM_MODEL_NAMES.map((name, i) => [name, i]));
|
|
482
|
+
if (unverified.length > 0) {
|
|
483
|
+
logger.warn(`[_get_mix_candidates] 登录检查未通过但仍保留为候选: ` +
|
|
484
|
+
`[${unverified.map((c) => c[0]).join(', ')}]`);
|
|
485
|
+
}
|
|
486
|
+
const all = [...candidates, ...unverified];
|
|
487
|
+
all.sort((a, b) => {
|
|
488
|
+
const pa = priority.get(a[0]) ?? 999;
|
|
489
|
+
const pb = priority.get(b[0]) ?? 999;
|
|
490
|
+
if (pa !== pb)
|
|
491
|
+
return pa - pb;
|
|
492
|
+
return b[2] - a[2]; // 账号多的优先(-x[2] 升序 = 账号数降序)
|
|
493
|
+
});
|
|
494
|
+
logger.info(`[_get_mix_candidates] 最终候选列表: [${all.map((c) => c[0]).join(', ')}]`);
|
|
495
|
+
return all;
|
|
496
|
+
}
|
|
497
|
+
/** 所有已注册的模型名(来自各 Provider 的 `getModels()`)。 */
|
|
498
|
+
getAllModels() {
|
|
499
|
+
return [...this.modelToProvider.keys()];
|
|
500
|
+
}
|
|
501
|
+
/** 模型别名对应的平台名(未登记返回 `undefined`)。 */
|
|
502
|
+
platformOfModel(model) {
|
|
503
|
+
return this.modelToProvider.get(model);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* 检查模型是否可用。
|
|
507
|
+
*
|
|
508
|
+
* ## ⚠️ 这里曾与 {@link registerProvider} 自相矛盾(实测踩过)
|
|
509
|
+
* 启动日志明明打了「注册模型: glm-4 -> chatglm」,请求 `model=glm-4` 却报
|
|
510
|
+
* 「模型 'glm-4' 不存在或不可用」—— 因为旧实现只看 `mix` / 平台名 /
|
|
511
|
+
* `AVAILABLE_MODELS`,而 `AVAILABLE_MODELS` 的**默认值是 `'mix'`**,
|
|
512
|
+
* 别名根本不在清单里。修复后以**登记表为准**:启动时真的注册了的模型就能路由。
|
|
513
|
+
*/
|
|
514
|
+
isModelAvailable(modelId) {
|
|
515
|
+
// `mix` 总是可用(真正的可用性在候选挑选时判断)
|
|
516
|
+
if (modelId === 'mix')
|
|
517
|
+
return true;
|
|
518
|
+
// 平台名作为模型:检查该平台是否有凭证
|
|
519
|
+
if (PLATFORM_MODEL_NAMES.includes(modelId)) {
|
|
520
|
+
try {
|
|
521
|
+
return listAccounts(modelId).length > 0;
|
|
522
|
+
}
|
|
523
|
+
catch {
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
// 从配置里取可用模型列表(支持 `model:platform` 格式)
|
|
528
|
+
for (const availableModel of getAvailableModelsList()) {
|
|
529
|
+
const model = availableModel.includes(':')
|
|
530
|
+
? availableModel.split(':', 1)[0]
|
|
531
|
+
: availableModel;
|
|
532
|
+
if (model === modelId)
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
// Provider 启动时登记过的模型别名(glm-4 / glm-3 → chatglm)
|
|
536
|
+
if (this.modelToProvider.has(modelId))
|
|
537
|
+
return true;
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
/** 已登录(有凭证)的平台名列表,作为可调用的独立模型。 */
|
|
541
|
+
getAvailablePlatformModels() {
|
|
542
|
+
const available = [];
|
|
543
|
+
for (const platform of PLATFORM_MODEL_NAMES) {
|
|
544
|
+
try {
|
|
545
|
+
if (listAccounts(platform).length > 0)
|
|
546
|
+
available.push(platform);
|
|
547
|
+
}
|
|
548
|
+
catch {
|
|
549
|
+
// 忽略
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
return available;
|
|
553
|
+
}
|
|
554
|
+
/** 所有 Provider(键 = 平台名)。 */
|
|
555
|
+
getAllProviders() {
|
|
556
|
+
return this.providers;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
let modelRouter = null;
|
|
560
|
+
/** 获取全局模型路由器实例(单例)。 */
|
|
561
|
+
export function getModelRouter() {
|
|
562
|
+
modelRouter ??= new ModelRouter();
|
|
563
|
+
return modelRouter;
|
|
564
|
+
}
|
|
565
|
+
/** 重置单例(测试用)。 */
|
|
566
|
+
export function __setModelRouterForTest(router) {
|
|
567
|
+
modelRouter = router;
|
|
568
|
+
}
|
|
569
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/controllers/router.ts"],"names":[],"mappings":"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"}
|