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,586 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 浏览器统一管理 —— `legacy-python/src/browser/playwright_manager.py` 的 TypeScript 移植。
|
|
3
|
+
*
|
|
4
|
+
* 提供**全局单例**的 Playwright Firefox 实例,供所有 Provider 共享。
|
|
5
|
+
*
|
|
6
|
+
* ## 与原实现的差异(都是有意为之)
|
|
7
|
+
*
|
|
8
|
+
* 1. **不再显式 `playwright.stop()`**:Node 的 `firefox.launch()` 由模块级单例管理
|
|
9
|
+
* driver 生命周期(进程退出时一并结束),没有 Python 那种「手动 start/stop」API。
|
|
10
|
+
* 这对我们反而更安全 —— 服务重启不会遗留 driver 进程。
|
|
11
|
+
* 2. **`addInitScript({ content })` 而非裸字符串**:Playwright Node 里裸字符串会被
|
|
12
|
+
* 当成**脚本文件路径**,必须显式给 `content`。
|
|
13
|
+
* 3. `asyncio.Lock` → 自实现的 {@link Mutex}(Node 没有内置异步锁)。
|
|
14
|
+
* 4. 凭证读取复用 {@link loadAuth}(Python 在 manager 与 cdp_capture 里各写了一份)。
|
|
15
|
+
*
|
|
16
|
+
* ## 三条必须守住的铁律(都对应真实事故,见 docs/hard-constraints.md)
|
|
17
|
+
*
|
|
18
|
+
* - **健康检查必须廉价**:只用 `isConnected()` / `isClosed()` 读本地状态。
|
|
19
|
+
* ⚠️ 旧实现用 `await browser.version()`(RPC),页面繁忙时超时 → 误判「已断开」
|
|
20
|
+
* → 又 launch 一个新 Firefox,旧的还活着(实测堆到 3 组 / 21 进程 / 3.5GB)。
|
|
21
|
+
* - **重建前必须先释放**:`disposeSharedBrowser()`(close page/context/browser + 清引用)。
|
|
22
|
+
* 只把 `initialized = false` 会留下孤儿进程。
|
|
23
|
+
* - **同一账号同一时刻只能服务一个角色**:账号角色/冷却/busy 原语在这里共享,
|
|
24
|
+
* 但「挑哪个账号」的业务决策留在 provider 与 router 里。
|
|
25
|
+
*/
|
|
26
|
+
import { execFileSync } from 'node:child_process';
|
|
27
|
+
import { writeFileSync, mkdirSync } from 'node:fs';
|
|
28
|
+
import { dirname } from 'node:path';
|
|
29
|
+
import { settings } from '../config.js';
|
|
30
|
+
import { logger } from '../log/logger.js';
|
|
31
|
+
import { iife } from './js-eval.js';
|
|
32
|
+
import { Mutex } from '../utils/mutex.js';
|
|
33
|
+
import { authFilePath, loadAuth, normalizeCookies, } from './credentials.js';
|
|
34
|
+
import { SSE_CAPTURE_JS } from './sse-capture.js';
|
|
35
|
+
import { STEALTH_JS } from './stealth.js';
|
|
36
|
+
/* ------------------------------------------------------------------ */
|
|
37
|
+
/* 全局状态 */
|
|
38
|
+
/* ------------------------------------------------------------------ */
|
|
39
|
+
let browser = null;
|
|
40
|
+
let context = null;
|
|
41
|
+
let page = null;
|
|
42
|
+
let initialized = false;
|
|
43
|
+
const initLock = new Mutex();
|
|
44
|
+
/** 辅助通道:channelKey → Page / BrowserContext。 */
|
|
45
|
+
const channelPages = new Map();
|
|
46
|
+
const channelContexts = new Map();
|
|
47
|
+
/* ------------------------------------------------------------------ */
|
|
48
|
+
/* 账号角色 / 冷却 / busy(跨 provider 共享的「账号基础设施」) */
|
|
49
|
+
/* ------------------------------------------------------------------ */
|
|
50
|
+
/** `{platform}:{accountId}` → 角色(main / aux)。 */
|
|
51
|
+
const accountRole = new Map();
|
|
52
|
+
/** `{platform}:{accountId}` → 冷却截止时间戳(ms)。 */
|
|
53
|
+
const accountCooldown = new Map();
|
|
54
|
+
/** `{platform}:{accountId}` → 正在该账号上干活的重入计数。 */
|
|
55
|
+
const accountBusy = new Map();
|
|
56
|
+
/** 账号在共享状态里的键(约定 `{platform}:{accountId}`)。 */
|
|
57
|
+
export function accountKey(platform, accountId) {
|
|
58
|
+
return `${platform}:${accountId}`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 标记「正在这个账号上干活」(provider 在拿到锁之后调用)。
|
|
62
|
+
*
|
|
63
|
+
* ⚠️ 这是**重入计数**,必须与 {@link exitAccount} 成对(放 `finally`),
|
|
64
|
+
* 否则计数泄漏会让账号被永久当成「正忙」。
|
|
65
|
+
*/
|
|
66
|
+
export function enterAccount(platform, accountId) {
|
|
67
|
+
const key = accountKey(platform, accountId);
|
|
68
|
+
accountBusy.set(key, (accountBusy.get(key) ?? 0) + 1);
|
|
69
|
+
}
|
|
70
|
+
/** 解除「正在这个账号上干活」的标记(与 {@link enterAccount} 配对)。 */
|
|
71
|
+
export function exitAccount(platform, accountId) {
|
|
72
|
+
const key = accountKey(platform, accountId);
|
|
73
|
+
const left = (accountBusy.get(key) ?? 0) - 1;
|
|
74
|
+
if (left > 0)
|
|
75
|
+
accountBusy.set(key, left);
|
|
76
|
+
else
|
|
77
|
+
accountBusy.delete(key);
|
|
78
|
+
}
|
|
79
|
+
/** 该账号此刻是否有人正在用。 */
|
|
80
|
+
export function isAccountBusy(platform, accountId) {
|
|
81
|
+
return (accountBusy.get(accountKey(platform, accountId)) ?? 0) > 0;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 把 busy 占用从旧账号转移到新账号。
|
|
85
|
+
*
|
|
86
|
+
* ⚠️ **换号时必须调用**。原因:`enterAccount()` 是按**进入时**的账号登记 busy 的,
|
|
87
|
+
* 而 `chatStream()` 的 `finally` 只会 `exitAccount(当前账号)` —— 主通道被限流换号后
|
|
88
|
+
* 账号已经变了,两个账号对不上:**旧账号的 busy 计数永远不会归零**
|
|
89
|
+
* (被永久当成「正忙」,辅助通道挑账号、主通道再换号都会一直避开它)。
|
|
90
|
+
* 这里一次性完成「旧的退出 + 新的进入」,使重入计数配平。
|
|
91
|
+
*/
|
|
92
|
+
export function transferAccountBusy(platform, oldAccountId, newAccountId) {
|
|
93
|
+
if (!oldAccountId || !newAccountId)
|
|
94
|
+
return;
|
|
95
|
+
// 同号 = 没有「转移」这回事(否则会多记一次 busy)
|
|
96
|
+
if (oldAccountId === newAccountId)
|
|
97
|
+
return;
|
|
98
|
+
exitAccount(platform, oldAccountId);
|
|
99
|
+
enterAccount(platform, newAccountId);
|
|
100
|
+
}
|
|
101
|
+
/** 登记某账号当前服务的角色(main / aux)。 */
|
|
102
|
+
export function setAccountRole(platform, accountId, role) {
|
|
103
|
+
if (platform && accountId && role)
|
|
104
|
+
accountRole.set(accountKey(platform, accountId), role);
|
|
105
|
+
}
|
|
106
|
+
/** 查询某账号的服务角色(未登记返回 undefined)。 */
|
|
107
|
+
export function getAccountRole(platform, accountId) {
|
|
108
|
+
return accountRole.get(accountKey(platform, accountId));
|
|
109
|
+
}
|
|
110
|
+
/** 释放某账号的角色占用(传了 `role` 时只在匹配时释放)。 */
|
|
111
|
+
export function clearAccountRole(platform, accountId, role) {
|
|
112
|
+
const key = accountKey(platform, accountId);
|
|
113
|
+
if (role === undefined || accountRole.get(key) === role)
|
|
114
|
+
accountRole.delete(key);
|
|
115
|
+
}
|
|
116
|
+
/** 把账号标记为冷却中(例如被平台限流),返回冷却截止时间戳。 */
|
|
117
|
+
export function markAccountCooldown(platform, accountId, seconds, now = Date.now) {
|
|
118
|
+
const until = now() + Math.max(0, seconds) * 1000;
|
|
119
|
+
if (platform && accountId)
|
|
120
|
+
accountCooldown.set(accountKey(platform, accountId), until);
|
|
121
|
+
return until;
|
|
122
|
+
}
|
|
123
|
+
/** 账号剩余冷却秒数(0 表示不在冷却中)。 */
|
|
124
|
+
export function accountCooldownRemaining(platform, accountId, now = Date.now) {
|
|
125
|
+
const until = accountCooldown.get(accountKey(platform, accountId)) ?? 0;
|
|
126
|
+
return Math.max(0, (until - now()) / 1000);
|
|
127
|
+
}
|
|
128
|
+
/** 该账号是否在冷却中。 */
|
|
129
|
+
export function isAccountCooling(platform, accountId, now = Date.now) {
|
|
130
|
+
return accountCooldownRemaining(platform, accountId, now) > 0;
|
|
131
|
+
}
|
|
132
|
+
/** 仅供测试:清空全部账号状态。 */
|
|
133
|
+
export function resetAccountState() {
|
|
134
|
+
accountRole.clear();
|
|
135
|
+
accountCooldown.clear();
|
|
136
|
+
accountBusy.clear();
|
|
137
|
+
}
|
|
138
|
+
/* ------------------------------------------------------------------ */
|
|
139
|
+
/* 辅助通道页面 */
|
|
140
|
+
/* ------------------------------------------------------------------ */
|
|
141
|
+
/** 给页面注入 stealth + SSE 捕获脚本(顺序与 Python 一致)。 */
|
|
142
|
+
async function injectPageScripts(target) {
|
|
143
|
+
await target.addInitScript({ content: STEALTH_JS });
|
|
144
|
+
await target.addInitScript({ content: SSE_CAPTURE_JS });
|
|
145
|
+
}
|
|
146
|
+
/** 关闭并清掉某个通道的 context / page。 */
|
|
147
|
+
async function disposeChannel(channelKey) {
|
|
148
|
+
const ctx = channelContexts.get(channelKey);
|
|
149
|
+
channelContexts.delete(channelKey);
|
|
150
|
+
channelPages.delete(channelKey);
|
|
151
|
+
if (ctx) {
|
|
152
|
+
try {
|
|
153
|
+
await ctx.close();
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
logger.debug(`关闭通道 ${channelKey} 的 context 失败(可忽略): ${String(error)}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* 关闭所有通道。
|
|
162
|
+
*
|
|
163
|
+
* ⚠️ 浏览器重建/关闭时**必须**调用,否则会留下孤儿 context
|
|
164
|
+
* (占内存,且再也无法从 Node 侧关掉)。
|
|
165
|
+
*/
|
|
166
|
+
export async function disposeAllChannels() {
|
|
167
|
+
for (const key of [...channelContexts.keys()]) {
|
|
168
|
+
await disposeChannel(key);
|
|
169
|
+
}
|
|
170
|
+
channelContexts.clear();
|
|
171
|
+
channelPages.clear();
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* 返回(必要时创建)某个「通道」的页面:**独立 context** + 指定账号的 cookie。
|
|
175
|
+
*
|
|
176
|
+
* ⚠️ 与 {@link newWorkPage} 的区别:`newWorkPage()` 是在**同一个 context** 里再开一页
|
|
177
|
+
* (cookie 与主页面共享 → 同一个账号);本函数开的是**另一个 context**
|
|
178
|
+
* (cookie 独立 → 可以换账号,从而绕开「同一账号同时只能有一个对话」的平台限制)。
|
|
179
|
+
*
|
|
180
|
+
* 这是辅助任务能与主对话**真并行**的唯一方式。
|
|
181
|
+
*/
|
|
182
|
+
export async function getChannelPage(channelKey, platform, accountId) {
|
|
183
|
+
if (!channelKey || !accountId)
|
|
184
|
+
return null;
|
|
185
|
+
try {
|
|
186
|
+
const shared = await getBrowser();
|
|
187
|
+
if (!shared.browser)
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
const existing = channelPages.get(channelKey);
|
|
194
|
+
if (existing) {
|
|
195
|
+
try {
|
|
196
|
+
if (!existing.isClosed())
|
|
197
|
+
return existing;
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// 句柄失效 → 重建
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
await disposeChannel(channelKey);
|
|
204
|
+
try {
|
|
205
|
+
const shared = await getBrowser();
|
|
206
|
+
const ctx = await shared.browser.newContext();
|
|
207
|
+
// 注入脚本必须在导航**之前** addInitScript
|
|
208
|
+
try {
|
|
209
|
+
await injectPageScriptsIntoContext(ctx);
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
logger.warn(`辅助通道 ${channelKey} 注入脚本失败: ${String(error)}`);
|
|
213
|
+
}
|
|
214
|
+
const auth = loadAuth(platform, { accountId });
|
|
215
|
+
const cookies = auth?.cookies ?? [];
|
|
216
|
+
if (cookies.length > 0) {
|
|
217
|
+
try {
|
|
218
|
+
await ctx.addCookies(normalizeCookies(cookies));
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
logger.warn(`辅助通道 ${channelKey} 注入 Cookie 失败: ${String(error)}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const newPage = await ctx.newPage();
|
|
225
|
+
channelContexts.set(channelKey, ctx);
|
|
226
|
+
channelPages.set(channelKey, newPage);
|
|
227
|
+
logger.info(`辅助通道页面已创建: ${channelKey}(账号 ${accountId},独立 context,${cookies.length} 个 Cookie)`);
|
|
228
|
+
return newPage;
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
logger.error(`创建辅助通道页面失败 ${channelKey}: ${String(error)}`);
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/** 给一个 context 注入两项 init script(新建 context 时用)。 */
|
|
236
|
+
async function injectPageScriptsIntoContext(ctx) {
|
|
237
|
+
await ctx.addInitScript({ content: STEALTH_JS });
|
|
238
|
+
await ctx.addInitScript({ content: SSE_CAPTURE_JS });
|
|
239
|
+
}
|
|
240
|
+
/* ------------------------------------------------------------------ */
|
|
241
|
+
/* 孤儿进程清理 / 释放 */
|
|
242
|
+
/* ------------------------------------------------------------------ */
|
|
243
|
+
/**
|
|
244
|
+
* 清理**孤儿** playwright Firefox / driver 进程(上一次服务运行留下的)。
|
|
245
|
+
*
|
|
246
|
+
* 只在启动全新实例前调用。判据是「父进程是 init(1)」—— 说明启动它的进程已经退出,
|
|
247
|
+
* 没有任何一方还持有它,属于纯垃圾。
|
|
248
|
+
*
|
|
249
|
+
* ⚠️ 只匹配 `ms-playwright/.../firefox`,不会碰用户自己登录用的系统 Firefox。
|
|
250
|
+
*/
|
|
251
|
+
export function sweepOrphanBrowsers() {
|
|
252
|
+
let killed = 0;
|
|
253
|
+
let out;
|
|
254
|
+
try {
|
|
255
|
+
out = execFileSync('ps', ['-eo', 'pid=,ppid=,cmd='], {
|
|
256
|
+
encoding: 'utf8',
|
|
257
|
+
timeout: 5000,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
logger.debug(`扫描孤儿浏览器进程失败: ${String(error)}`);
|
|
262
|
+
return 0;
|
|
263
|
+
}
|
|
264
|
+
for (const line of out.split('\n')) {
|
|
265
|
+
const parts = line.trim().split(/\s+/, 3);
|
|
266
|
+
if (parts.length < 3)
|
|
267
|
+
continue;
|
|
268
|
+
const pid = Number.parseInt(parts[0], 10);
|
|
269
|
+
const ppid = Number.parseInt(parts[1], 10);
|
|
270
|
+
if (!Number.isFinite(pid) || !Number.isFinite(ppid))
|
|
271
|
+
continue;
|
|
272
|
+
const cmd = parts[2];
|
|
273
|
+
if (ppid !== 1 || pid === process.pid)
|
|
274
|
+
continue;
|
|
275
|
+
if (!cmd.includes('ms-playwright'))
|
|
276
|
+
continue;
|
|
277
|
+
if (!cmd.includes('/firefox/firefox') && !cmd.includes('playwright/driver/node'))
|
|
278
|
+
continue;
|
|
279
|
+
try {
|
|
280
|
+
process.kill(pid, 'SIGTERM');
|
|
281
|
+
killed += 1;
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
// 进程可能已经退出
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (killed > 0) {
|
|
288
|
+
logger.warn(`清理了 ${killed} 个孤儿 playwright 进程(上次服务运行残留)`);
|
|
289
|
+
}
|
|
290
|
+
return killed;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* 释放当前(多半已失效的)浏览器实例。
|
|
294
|
+
*
|
|
295
|
+
* ⚠️ **重建前必须先释放**:旧实现只把 `initialized` 置 false 就 `launch()` 新实例,
|
|
296
|
+
* 旧 Firefox 永远不会退出(Python 侧引用被覆盖后没有任何代码再去关它)。
|
|
297
|
+
*/
|
|
298
|
+
export async function disposeSharedBrowser() {
|
|
299
|
+
// 辅助通道的 context 属于这个浏览器实例,必须先一并释放,
|
|
300
|
+
// 否则重建后会留下孤儿 context。
|
|
301
|
+
try {
|
|
302
|
+
await disposeAllChannels();
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
logger.debug(`释放辅助通道失败(可忽略): ${String(error)}`);
|
|
306
|
+
}
|
|
307
|
+
for (const [obj, name] of [
|
|
308
|
+
[page, 'page'],
|
|
309
|
+
[context, 'context'],
|
|
310
|
+
[browser, 'browser'],
|
|
311
|
+
]) {
|
|
312
|
+
if (!obj)
|
|
313
|
+
continue;
|
|
314
|
+
try {
|
|
315
|
+
await obj.close();
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
logger.debug(`关闭旧 ${name} 失败(连接已断,可忽略): ${String(error)}`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
browser = null;
|
|
322
|
+
context = null;
|
|
323
|
+
page = null;
|
|
324
|
+
initialized = false;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* 获取或创建共享的 Playwright Firefox 实例。
|
|
328
|
+
*
|
|
329
|
+
* 健康检查**只读本地状态**(不发 RPC),见文件头「三条铁律」。
|
|
330
|
+
*/
|
|
331
|
+
export async function getBrowser() {
|
|
332
|
+
return initLock.run(async () => {
|
|
333
|
+
if (initialized && browser) {
|
|
334
|
+
let healthy = false;
|
|
335
|
+
try {
|
|
336
|
+
const pageOk = page !== null && !page.isClosed();
|
|
337
|
+
healthy = browser.isConnected() && pageOk;
|
|
338
|
+
if (!healthy) {
|
|
339
|
+
logger.warn(`共享浏览器已失效(connected=${browser.isConnected()}, ` +
|
|
340
|
+
`page=${page === null ? 'None' : page.isClosed() ? 'closed' : 'open'}),重新初始化`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
logger.warn(`共享浏览器健康检查异常(${error.name}: ${String(error)}),重新初始化`);
|
|
345
|
+
}
|
|
346
|
+
if (healthy)
|
|
347
|
+
return { browser, context: context, page: page };
|
|
348
|
+
initialized = false;
|
|
349
|
+
// 先释放旧实例再建新的,否则孤儿 Firefox 会一直堆积
|
|
350
|
+
await disposeSharedBrowser();
|
|
351
|
+
}
|
|
352
|
+
// 建新实例前清掉「父进程已是 init」的残留进程(服务重启留下的纯垃圾)
|
|
353
|
+
sweepOrphanBrowsers();
|
|
354
|
+
const headless = settings.browserHeadless;
|
|
355
|
+
if (!headless && !process.env['DISPLAY']) {
|
|
356
|
+
logger.warn('BROWSER_HEADLESS=false 但环境里没有 DISPLAY —— ' +
|
|
357
|
+
'无 X 显示时 Firefox 会启动失败,请检查运行服务的环境变量');
|
|
358
|
+
}
|
|
359
|
+
logger.info(`启动 Playwright Firefox: ${headless ? '无头(headless)' : '可见(headed)'}`);
|
|
360
|
+
try {
|
|
361
|
+
const { firefox } = await import('playwright');
|
|
362
|
+
browser = await firefox.launch({ headless, slowMo: 0 });
|
|
363
|
+
context = await browser.newContext({
|
|
364
|
+
viewport: { width: 1920, height: 1080 },
|
|
365
|
+
userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 ' +
|
|
366
|
+
'(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
367
|
+
locale: 'zh-CN',
|
|
368
|
+
});
|
|
369
|
+
page = await context.newPage();
|
|
370
|
+
await page.addInitScript({ content: STEALTH_JS });
|
|
371
|
+
await page.addInitScript({ content: SSE_CAPTURE_JS });
|
|
372
|
+
logger.info('SSE 原始流捕获脚本已注入');
|
|
373
|
+
initialized = true;
|
|
374
|
+
logger.info('Playwright Firefox 浏览器实例已就绪');
|
|
375
|
+
}
|
|
376
|
+
catch (error) {
|
|
377
|
+
logger.error(`启动浏览器失败: ${String(error)}`);
|
|
378
|
+
throw new Error(`无法启动 Playwright Firefox 浏览器: ${String(error)}`);
|
|
379
|
+
}
|
|
380
|
+
return { browser, context, page };
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* 在同一浏览器上下文里再开一个「工作页面」。
|
|
385
|
+
*
|
|
386
|
+
* 用途:需要在**独立对话**里再问一次模型的场景(两轮策略的 reparse)。
|
|
387
|
+
* 若共用主页面,reparse 会把主页面上的会话切走 —— 主会话上下文丢失、
|
|
388
|
+
* 会话复用(只补发增量)失效。
|
|
389
|
+
*
|
|
390
|
+
* ⚠️ 返回的是**新页面**,不会改动共享单例 `page`。
|
|
391
|
+
* Cookie / localStorage 属于 context,页面间共享,登录态自动沿用。
|
|
392
|
+
*/
|
|
393
|
+
export async function newWorkPage() {
|
|
394
|
+
const shared = await getBrowser();
|
|
395
|
+
if (!shared.context)
|
|
396
|
+
return null;
|
|
397
|
+
const newPage = await shared.context.newPage();
|
|
398
|
+
try {
|
|
399
|
+
await injectPageScripts(newPage);
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
logger.warn(`辅助页面注入脚本失败: ${String(error)}`);
|
|
403
|
+
}
|
|
404
|
+
logger.info('辅助工作页面已创建(供两轮策略使用独立对话)');
|
|
405
|
+
return newPage;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* 标记共享浏览器实例已失效,下次 `getBrowser()` 会重建它。
|
|
409
|
+
*
|
|
410
|
+
* 用于「操作时报了连接类错误」的场景:此时 `isConnected()` 可能还没更新,
|
|
411
|
+
* 不主动失效就会一直拿到坏实例、每个请求都失败,只能重启服务。
|
|
412
|
+
*/
|
|
413
|
+
export function invalidateBrowser(reason = '') {
|
|
414
|
+
if (initialized) {
|
|
415
|
+
logger.warn(`标记共享浏览器失效${reason ? `(${reason})` : ''},下次请求将重建`);
|
|
416
|
+
}
|
|
417
|
+
initialized = false;
|
|
418
|
+
}
|
|
419
|
+
/** 关闭共享浏览器(服务优雅退出时调用)。 */
|
|
420
|
+
export async function closeBrowser() {
|
|
421
|
+
try {
|
|
422
|
+
await disposeAllChannels();
|
|
423
|
+
}
|
|
424
|
+
catch {
|
|
425
|
+
// 忽略
|
|
426
|
+
}
|
|
427
|
+
for (const obj of [page, context, browser]) {
|
|
428
|
+
if (!obj)
|
|
429
|
+
continue;
|
|
430
|
+
try {
|
|
431
|
+
await obj.close();
|
|
432
|
+
}
|
|
433
|
+
catch {
|
|
434
|
+
// 忽略
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
browser = null;
|
|
438
|
+
context = null;
|
|
439
|
+
page = null;
|
|
440
|
+
initialized = false;
|
|
441
|
+
logger.info('共享浏览器已关闭');
|
|
442
|
+
}
|
|
443
|
+
/* ------------------------------------------------------------------ */
|
|
444
|
+
/* Cookie / 页面操作 */
|
|
445
|
+
/* ------------------------------------------------------------------ */
|
|
446
|
+
/**
|
|
447
|
+
* 把某账号的 Cookie 注入**主 context**。
|
|
448
|
+
*
|
|
449
|
+
* ⚠️ 注入后**必须重新导航**才生效(调用方负责)。
|
|
450
|
+
* 另外:旧实现把这段嵌在 `if (!page)` 里,导致 `checkLoginStatus()` 先赋好 `page` 之后
|
|
451
|
+
* 整块被跳过 —— 表现为「凭证明明在却永远是访客」。
|
|
452
|
+
* 所以本函数**每次都要独立调用**,不要加任何前置条件。
|
|
453
|
+
*/
|
|
454
|
+
export async function loadCookies(platformName, accountId = 'default', targetContext) {
|
|
455
|
+
const ctx = targetContext ?? context;
|
|
456
|
+
if (!ctx) {
|
|
457
|
+
logger.warn('浏览器上下文未初始化');
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
const auth = loadAuth(platformName, { accountId });
|
|
461
|
+
if (!auth)
|
|
462
|
+
return false;
|
|
463
|
+
const cookies = auth.cookies ?? [];
|
|
464
|
+
if (cookies.length === 0)
|
|
465
|
+
return false;
|
|
466
|
+
try {
|
|
467
|
+
await ctx.addCookies(normalizeCookies(cookies));
|
|
468
|
+
logger.info(`已加载 ${cookies.length} 个 Cookie (${platformName}/${accountId})`);
|
|
469
|
+
return true;
|
|
470
|
+
}
|
|
471
|
+
catch (error) {
|
|
472
|
+
logger.error(`加载 Cookie 失败: ${String(error)}`);
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
/** 获取当前共享页面。 */
|
|
477
|
+
export function getPage() {
|
|
478
|
+
if (!page)
|
|
479
|
+
throw new Error('浏览器未初始化');
|
|
480
|
+
return page;
|
|
481
|
+
}
|
|
482
|
+
/** 当前共享页面(可能为 null,不抛异常)。 */
|
|
483
|
+
export function peekPage() {
|
|
484
|
+
return page;
|
|
485
|
+
}
|
|
486
|
+
/** 导航到指定 URL(主导航一律等 `networkidle`,见 hard-constraints)。 */
|
|
487
|
+
export async function navigateTo(url, timeout = 60000) {
|
|
488
|
+
const target = getPage();
|
|
489
|
+
try {
|
|
490
|
+
await target.goto(url, { timeout, waitUntil: 'networkidle' });
|
|
491
|
+
logger.info(`已导航到: ${url}`);
|
|
492
|
+
}
|
|
493
|
+
catch (error) {
|
|
494
|
+
logger.error(`导航失败: ${String(error)}`);
|
|
495
|
+
throw error;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* 在页面里注册通用的响应提取函数(兜底用)。
|
|
500
|
+
*
|
|
501
|
+
* 注册 `window.__ai_api_get_response()` / `__ai_api_clear_input()` / `__ai_api_set_input()`。
|
|
502
|
+
* ⚠️ ChatGLM 的正文**不用**这个(DOM innerText 已被 Markdown 渲染破坏),
|
|
503
|
+
* 只作为其它场景的兜底。
|
|
504
|
+
*/
|
|
505
|
+
export async function injectResponseJs(targetPage) {
|
|
506
|
+
const target = targetPage ?? page;
|
|
507
|
+
if (!target)
|
|
508
|
+
return;
|
|
509
|
+
const responseJs = `() => {
|
|
510
|
+
window.__ai_api_get_response = function() {
|
|
511
|
+
const selectors = ['.message-content', '[class*="answer"]', '[class*="response"]', '.ai-message'];
|
|
512
|
+
for (const selector of selectors) {
|
|
513
|
+
const el = document.querySelector(selector);
|
|
514
|
+
if (el && el.innerText && el.innerText.trim()) return el.innerText.trim();
|
|
515
|
+
}
|
|
516
|
+
const allElements = document.querySelectorAll('div, p, span');
|
|
517
|
+
for (let i = allElements.length - 1; i >= 0; i--) {
|
|
518
|
+
const text = allElements[i].innerText ? allElements[i].innerText.trim() : '';
|
|
519
|
+
if (text && text.length > 20) return text.substring(0, 5000);
|
|
520
|
+
}
|
|
521
|
+
return '';
|
|
522
|
+
};
|
|
523
|
+
window.__ai_api_clear_input = function() {
|
|
524
|
+
const selectors = ['textarea', '[contenteditable]', 'input[type="text"]'];
|
|
525
|
+
for (const selector of selectors) {
|
|
526
|
+
const el = document.querySelector(selector);
|
|
527
|
+
if (el) {
|
|
528
|
+
if (el.contentEditable === 'true') el.innerHTML = '';
|
|
529
|
+
else el.value = '';
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
window.__ai_api_set_input = function(text) {
|
|
535
|
+
const selectors = ['textarea', '[contenteditable]', 'input[type="text"]'];
|
|
536
|
+
for (const selector of selectors) {
|
|
537
|
+
const el = document.querySelector(selector);
|
|
538
|
+
if (el && el.offsetParent !== null) {
|
|
539
|
+
if (el.contentEditable === 'true') el.innerHTML = text;
|
|
540
|
+
else el.value = text;
|
|
541
|
+
const events = ['input', 'change', 'keyup', 'keydown'];
|
|
542
|
+
events.forEach(function(eventType) {
|
|
543
|
+
el.dispatchEvent(new Event(eventType, { bubbles: true }));
|
|
544
|
+
});
|
|
545
|
+
break;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
return 'AI_API_RESPONSE_JS_LOADED';
|
|
550
|
+
}`;
|
|
551
|
+
try {
|
|
552
|
+
const result = await target.evaluate(iife(responseJs));
|
|
553
|
+
logger.debug(`响应 JS 注入结果: ${String(result)}`);
|
|
554
|
+
}
|
|
555
|
+
catch (error) {
|
|
556
|
+
logger.warn(`注入响应 JS 失败: ${String(error)}`);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
/** 供测试/诊断:当前实例状态。 */
|
|
560
|
+
export function browserState() {
|
|
561
|
+
return {
|
|
562
|
+
initialized,
|
|
563
|
+
hasBrowser: browser !== null,
|
|
564
|
+
hasPage: page !== null,
|
|
565
|
+
channels: [...channelPages.keys()],
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
/** 供测试:把一个假的 page/context/browser 塞进去(不启动真实浏览器)。 */
|
|
569
|
+
export function __setSharedForTest(state) {
|
|
570
|
+
if ('browser' in state)
|
|
571
|
+
browser = state.browser ?? null;
|
|
572
|
+
if ('context' in state)
|
|
573
|
+
context = state.context ?? null;
|
|
574
|
+
if ('page' in state)
|
|
575
|
+
page = state.page ?? null;
|
|
576
|
+
if ('initialized' in state)
|
|
577
|
+
initialized = state.initialized ?? false;
|
|
578
|
+
}
|
|
579
|
+
/** 落盘一份 cookie(供 CLI 复用);目录不存在会自动创建。 */
|
|
580
|
+
export function writeAuthFile(platform, accountId, payload) {
|
|
581
|
+
const file = authFilePath(platform, accountId);
|
|
582
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
583
|
+
writeFileSync(file, JSON.stringify(payload, null, 2), 'utf8');
|
|
584
|
+
return file;
|
|
585
|
+
}
|
|
586
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/browser/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAEL,YAAY,EACZ,QAAQ,EACR,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,wEAAwE;AACxE,qEAAqE;AACrE,wEAAwE;AAExE,IAAI,OAAO,GAAmB,IAAI,CAAC;AACnC,IAAI,OAAO,GAA0B,IAAI,CAAC;AAC1C,IAAI,IAAI,GAAgB,IAAI,CAAC;AAC7B,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,MAAM,QAAQ,GAAG,IAAI,KAAK,EAAE,CAAC;AAE7B,+CAA+C;AAC/C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAgB,CAAC;AAC7C,MAAM,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;AAE1D,wEAAwE;AACxE,uDAAuD;AACvD,wEAAwE;AAExE,iDAAiD;AACjD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;AAC9C,8CAA8C;AAC9C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;AAClD,gDAAgD;AAChD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE9C,+CAA+C;AAC/C,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,SAAiB;IAC5D,OAAO,GAAG,QAAQ,IAAI,SAAS,EAAE,CAAC;AACpC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,SAAiB;IAC9D,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC5C,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,SAAiB;IAC7D,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,IAAI,GAAG,CAAC;QAAE,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;;QACpC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,oBAAoB;AACpB,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,SAAiB;IAC/D,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AACrE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,YAAoB,EACpB,YAAoB;IAEpB,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY;QAAE,OAAO;IAC3C,+BAA+B;IAC/B,IAAI,YAAY,KAAK,YAAY;QAAE,OAAO;IAE1C,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACpC,YAAY,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AACvC,CAAC;AAED,gCAAgC;AAChC,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,SAAiB,EAAE,IAAY;IAC9E,IAAI,QAAQ,IAAI,SAAS,IAAI,IAAI;QAAE,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC;AAC5F,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,SAAiB;IAChE,OAAO,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,SAAiB,EAAE,IAAa;IACjF,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC5C,IAAI,IAAI,KAAK,SAAS,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI;QAAE,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACnF,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,SAAiB,EACjB,OAAe,EACf,GAAG,GAAiB,IAAI,CAAC,GAAG;IAE5B,MAAM,KAAK,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClD,IAAI,QAAQ,IAAI,SAAS;QAAE,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;IACvF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,2BAA2B;AAC3B,MAAM,UAAU,wBAAwB,CACtC,QAAgB,EAChB,SAAiB,EACjB,GAAG,GAAiB,IAAI,CAAC,GAAG;IAE5B,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC;IACxE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,iBAAiB;AACjB,MAAM,UAAU,gBAAgB,CAC9B,QAAgB,EAChB,SAAiB,EACjB,GAAG,GAAiB,IAAI,CAAC,GAAG;IAE5B,OAAO,wBAAwB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;AAChE,CAAC;AAED,qBAAqB;AACrB,MAAM,UAAU,iBAAiB;IAC/B,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,eAAe,CAAC,KAAK,EAAE,CAAC;IACxB,WAAW,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC;AAED,wEAAwE;AACxE,mEAAmE;AACnE,wEAAwE;AAExE,+CAA+C;AAC/C,KAAK,UAAU,iBAAiB,CAAC,MAAY;IAC3C,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;IACpD,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,iCAAiC;AACjC,KAAK,UAAU,cAAc,CAAC,UAAkB;IAC9C,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC5C,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACnC,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAEhC,IAAI,GAAG,EAAE,CAAC;QACR,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,QAAQ,UAAU,uBAAuB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC9C,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IACD,eAAe,CAAC,KAAK,EAAE,CAAC;IACxB,YAAY,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAAkB,EAClB,QAAgB,EAChB,SAAiB;IAEjB,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAE3C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC9C,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;gBAAE,OAAO,QAAQ,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;IACH,CAAC;IACD,MAAM,cAAc,CAAC,UAAU,CAAC,CAAC;IAEjC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAE9C,gCAAgC;QAChC,IAAI,CAAC;YACH,MAAM,4BAA4B,CAAC,GAAG,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,QAAQ,UAAU,YAAY,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC;QACpC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC;gBACH,MAAM,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,OAAO,CAAgD,CAAC,CAAC;YACjG,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,QAAQ,UAAU,kBAAkB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;QACpC,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACrC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACtC,MAAM,CAAC,IAAI,CACT,cAAc,UAAU,OAAO,SAAS,eAAe,OAAO,CAAC,MAAM,YAAY,CAClF,CAAC;QACF,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,cAAc,UAAU,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,mDAAmD;AACnD,KAAK,UAAU,4BAA4B,CAAC,GAAmB;IAC7D,MAAM,GAAG,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;IACjD,MAAM,GAAG,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,wEAAwE;AACxE,iEAAiE;AACjE,wEAAwE;AAExE;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB;IACjC,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,EAAE;YACnD,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,gBAAgB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,CAAC;IACX,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC1C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAE/B,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAW,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAW,EAAE,EAAE,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAS;QAE9D,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAW,CAAC;QAC/B,IAAI,IAAI,KAAK,CAAC,IAAI,GAAG,KAAK,OAAO,CAAC,GAAG;YAAE,SAAS;QAChD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC;YAAE,SAAS;QAC7C,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,wBAAwB,CAAC;YAAE,SAAS;QAE3F,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAC7B,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,WAAW;QACb,CAAC;IACH,CAAC;IAED,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,OAAO,MAAM,8BAA8B,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,mCAAmC;IACnC,sBAAsB;IACtB,IAAI,CAAC;QACH,MAAM,kBAAkB,EAAE,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,kBAAkB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI;QACxB,CAAC,IAAI,EAAE,MAAM,CAAC;QACd,CAAC,OAAO,EAAE,SAAS,CAAC;QACpB,CAAC,OAAO,EAAE,SAAS,CAAC;KACZ,EAAE,CAAC;QACX,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,kBAAkB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,OAAO,GAAG,IAAI,CAAC;IACf,OAAO,GAAG,IAAI,CAAC;IACf,IAAI,GAAG,IAAI,CAAC;IACZ,WAAW,GAAG,KAAK,CAAC;AACtB,CAAC;AAYD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE;QAC7B,IAAI,WAAW,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACjD,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC;gBAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,MAAM,CAAC,IAAI,CACT,sBAAsB,OAAO,CAAC,WAAW,EAAE,IAAI;wBAC7C,QAAQ,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,SAAS,CAChF,CAAC;gBACJ,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CACT,eAAgB,KAAe,CAAC,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,SAAS,CAChE,CAAC;YACJ,CAAC;YAED,IAAI,OAAO;gBAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAyB,EAAE,IAAI,EAAE,IAAY,EAAE,CAAC;YAExF,WAAW,GAAG,KAAK,CAAC;YACpB,gCAAgC;YAChC,MAAM,oBAAoB,EAAE,CAAC;QAC/B,CAAC;QAED,uCAAuC;QACvC,mBAAmB,EAAE,CAAC;QAEtB,MAAM,QAAQ,GAAG,QAAQ,CAAC,eAAe,CAAC;QAC1C,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YACzC,MAAM,CAAC,IAAI,CACT,2CAA2C;gBACzC,oCAAoC,CACvC,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,0BAA0B,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;QAElF,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;YAC/C,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YAExD,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;gBACjC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;gBACvC,SAAS,EACP,qDAAqD;oBACrD,oDAAoD;gBACtD,MAAM,EAAE,OAAO;aAChB,CAAC,CAAC;YAEH,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;YAE/B,MAAM,IAAI,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;YAClD,MAAM,IAAI,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;YACtD,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAE9B,WAAW,GAAG,IAAI,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,gCAAgC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAEjC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IAC/C,IAAI,CAAC;QACH,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACtC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAM,GAAG,EAAE;IAC3C,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IACjE,CAAC;IACD,WAAW,GAAG,KAAK,CAAC;AACtB,CAAC;AAED,0BAA0B;AAC1B,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC;QACH,MAAM,kBAAkB,EAAE,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,KAAK;IACP,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,KAAK;QACP,CAAC;IACH,CAAC;IAED,OAAO,GAAG,IAAI,CAAC;IACf,OAAO,GAAG,IAAI,CAAC;IACf,IAAI,GAAG,IAAI,CAAC;IACZ,WAAW,GAAG,KAAK,CAAC;IACpB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC1B,CAAC;AAED,wEAAwE;AACxE,qEAAqE;AACrE,wEAAwE;AAExE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,YAAoB,EACpB,SAAS,GAAG,SAAS,EACrB,aAA8B;IAE9B,MAAM,GAAG,GAAG,aAAa,IAAI,OAAO,CAAC;IACrC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IACnD,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IAExB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACnC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,OAAO,CAAgD,CAAC,CAAC;QAC/F,MAAM,CAAC,IAAI,CAAC,OAAO,OAAO,CAAC,MAAM,cAAc,YAAY,IAAI,SAAS,GAAG,CAAC,CAAC;QAC7E,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,iBAAiB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/C,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,gBAAgB;AAChB,MAAM,UAAU,OAAO;IACrB,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;IACtC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6BAA6B;AAC7B,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,OAAO,GAAG,KAAK;IAC3D,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,SAAS,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACvC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,UAAiB;IACtD,MAAM,MAAM,GAAG,UAAU,IAAI,IAAI,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyCnB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QACvD,MAAM,CAAC,KAAK,CAAC,eAAe,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,qBAAqB;AACrB,MAAM,UAAU,YAAY;IAM1B,OAAO;QACL,WAAW;QACX,UAAU,EAAE,OAAO,KAAK,IAAI;QAC5B,OAAO,EAAE,IAAI,KAAK,IAAI;QACtB,QAAQ,EAAE,CAAC,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;KACnC,CAAC;AACJ,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,kBAAkB,CAAC,KAKlC;IACC,IAAI,SAAS,IAAI,KAAK;QAAE,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC;IACxD,IAAI,SAAS,IAAI,KAAK;QAAE,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC;IACxD,IAAI,MAAM,IAAI,KAAK;QAAE,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC;IAC/C,IAAI,aAAa,IAAI,KAAK;QAAE,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC;AACvE,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,aAAa,CAC3B,QAAgB,EAChB,SAAiB,EACjB,OAAgC;IAEhC,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC/C,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC9D,OAAO,IAAI,CAAC;AACd,CAAC"}
|