chrome-debugger-mcp 1.0.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 +567 -0
- package/dist/chrome-manager.d.ts +167 -0
- package/dist/chrome-manager.d.ts.map +1 -0
- package/dist/chrome-manager.js +719 -0
- package/dist/chrome-manager.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +605 -0
- package/dist/index.js.map +1 -0
- package/package.json +31 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { ChromeDebuggerManager } from "./chrome-manager.js";
|
|
6
|
+
const manager = new ChromeDebuggerManager();
|
|
7
|
+
const server = new McpServer({
|
|
8
|
+
name: "chrome-debugger-mcp",
|
|
9
|
+
version: "1.0.0",
|
|
10
|
+
}, {
|
|
11
|
+
capabilities: {
|
|
12
|
+
logging: {},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
const USER_ACTION_REMINDER_DELAY_MS = 15_000;
|
|
16
|
+
const DEFAULT_SPECIFIC_PAUSE_TIMEOUT_MS = 90_000;
|
|
17
|
+
manager.onPause((info) => {
|
|
18
|
+
void server.server.sendLoggingMessage({
|
|
19
|
+
level: "info",
|
|
20
|
+
data: JSON.stringify({
|
|
21
|
+
event: "debugger/paused",
|
|
22
|
+
reason: info.reason,
|
|
23
|
+
hitBreakpoints: info.hitBreakpoints,
|
|
24
|
+
callStack: info.callFrames.map((f, i) => ({
|
|
25
|
+
index: i,
|
|
26
|
+
functionName: f.functionName || "(anonymous)",
|
|
27
|
+
url: f.url,
|
|
28
|
+
line: f.location.lineNumber,
|
|
29
|
+
column: f.location.columnNumber,
|
|
30
|
+
})),
|
|
31
|
+
}),
|
|
32
|
+
}).catch(() => { });
|
|
33
|
+
});
|
|
34
|
+
// 统一成功返回格式
|
|
35
|
+
function ok(data) {
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// 统一错误返回格式
|
|
41
|
+
function fail(message) {
|
|
42
|
+
return {
|
|
43
|
+
content: [
|
|
44
|
+
{ type: "text", text: JSON.stringify({ error: message }) },
|
|
45
|
+
],
|
|
46
|
+
isError: true,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function buildUserActionMessage(heading, actionHint, timeoutMs, targetDescription) {
|
|
50
|
+
const actionText = actionHint?.trim()
|
|
51
|
+
? actionHint.trim()
|
|
52
|
+
: "Perform the page action that should trigger the breakpoint.";
|
|
53
|
+
const lines = [
|
|
54
|
+
heading,
|
|
55
|
+
"Use the connected Chrome page now.",
|
|
56
|
+
];
|
|
57
|
+
if (targetDescription) {
|
|
58
|
+
lines.push(`Target: ${targetDescription}`);
|
|
59
|
+
}
|
|
60
|
+
lines.push("Required action:", actionText, `Waiting timeout: ${timeoutMs}ms`);
|
|
61
|
+
return lines.join("\n");
|
|
62
|
+
}
|
|
63
|
+
async function sendUserActionPrompt(heading, actionHint, timeoutMs, targetDescription) {
|
|
64
|
+
await server.server.sendLoggingMessage({
|
|
65
|
+
level: "warning",
|
|
66
|
+
data: buildUserActionMessage(heading, actionHint, timeoutMs, targetDescription),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function scheduleUserActionReminder(actionHint, timeoutMs, targetDescription) {
|
|
70
|
+
const reminderDelayMs = Math.min(USER_ACTION_REMINDER_DELAY_MS, Math.max(5_000, Math.floor(timeoutMs / 2)));
|
|
71
|
+
const timer = setTimeout(() => {
|
|
72
|
+
void server.server.sendLoggingMessage({
|
|
73
|
+
level: "warning",
|
|
74
|
+
data: buildUserActionMessage("ACTION STILL REQUIRED", actionHint, timeoutMs, targetDescription),
|
|
75
|
+
}).catch(() => { });
|
|
76
|
+
}, reminderDelayMs);
|
|
77
|
+
return () => clearTimeout(timer);
|
|
78
|
+
}
|
|
79
|
+
// ── startDebuggingSession ──────────────────────────────────
|
|
80
|
+
// 元工具:触发条件描述 + 完整工作流说明,AI 在需要调试时优先调用此工具
|
|
81
|
+
server.tool("startDebuggingSession", `CALL THIS FIRST whenever browser-side debugging is needed — before any other tool.
|
|
82
|
+
|
|
83
|
+
Auto-trigger when user mentions any of:
|
|
84
|
+
debug, breakpoint, debugger, inspect, trace, step through, runtime value,
|
|
85
|
+
variable value, why is this, implement based on API response, bug, error,
|
|
86
|
+
unexpected behavior, not working, check this, confirm this.
|
|
87
|
+
|
|
88
|
+
Returns the complete debugging workflow and critical rules.
|
|
89
|
+
The response contains a "_ui" field — relay it to the user verbatim.`, {}, () => {
|
|
90
|
+
return ok({
|
|
91
|
+
// AI 必须将 _ui 展示给用户
|
|
92
|
+
_ui: {
|
|
93
|
+
status: "Starting debug session",
|
|
94
|
+
message: "I'm starting a Chrome debugging session. I'll guide you through each step.",
|
|
95
|
+
},
|
|
96
|
+
title: "Chrome DevTools Debugging Workflow",
|
|
97
|
+
// 关键规则,AI 必须严格遵守
|
|
98
|
+
critical_rules: [
|
|
99
|
+
"ALWAYS relay the '_ui' field from every tool response to the user immediately.",
|
|
100
|
+
"NEVER skip listTargets. NEVER guess the target URL. ALWAYS wait for user confirmation before connect().",
|
|
101
|
+
"Even if there is only one tab open, you MUST show it to the user and wait for confirmation.",
|
|
102
|
+
"Use waitForSpecificPause (not waitForPause) after inserting debugger; — it uses two-tier matching: line tolerance + debugger-statement reason.",
|
|
103
|
+
"Conclusions MUST cite actual values from getScopeVariables/evaluate. No guessing from static code.",
|
|
104
|
+
"Always call resume() and remove temporary debugger; statements at the end.",
|
|
105
|
+
],
|
|
106
|
+
// 轮次边界规则:明确哪些步骤之间允许结束对话轮次,哪些必须连续执行
|
|
107
|
+
turn_boundary_rules: [
|
|
108
|
+
"ALLOWED turn-end points (steps where user input is truly required):",
|
|
109
|
+
" • After launchChrome(dryRun=true): end turn, show command, wait for user confirmation.",
|
|
110
|
+
" • After listTargets: end turn, show tab list, wait for user to pick a URL.",
|
|
111
|
+
" • That's it — those are the ONLY two points where you may end your turn.",
|
|
112
|
+
"FORBIDDEN turn-end points (NEVER end your turn here):",
|
|
113
|
+
" • After launchChrome() (non-dryRun): immediately call listTargets in the same turn.",
|
|
114
|
+
" • After connect(): immediately add debugger; to source and call reloadPage in the same turn.",
|
|
115
|
+
" • After reloadPage(): IMMEDIATELY call waitForSpecificPause in the SAME turn — do NOT end your turn here. waitForSpecificPause is a blocking call; it will notify the user to trigger the action and wait for the breakpoint internally.",
|
|
116
|
+
" • After waitForSpecificPause returns: immediately call getScopeVariables in the same turn.",
|
|
117
|
+
" • After getScopeVariables: immediately call evaluate/resume as needed in the same turn.",
|
|
118
|
+
"KEY RULE: reloadPage → waitForSpecificPause MUST be two consecutive tool calls in the same AI turn. If you end your turn between them, the session breaks.",
|
|
119
|
+
],
|
|
120
|
+
steps: [
|
|
121
|
+
{
|
|
122
|
+
step: 1,
|
|
123
|
+
tool: "launchChrome",
|
|
124
|
+
action: "launchChrome({ dryRun: true }) → [END TURN] show command to user → wait for confirmation → launchChrome()",
|
|
125
|
+
note: "If alreadyRunning=true, skip to step 2 in the same turn. Add openDevTools=true to auto-open DevTools panel.",
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
step: 2,
|
|
129
|
+
tool: "listTargets",
|
|
130
|
+
action: "listTargets() → [END TURN] show the full tab list to the user → wait for URL reply",
|
|
131
|
+
note: "MANDATORY: show all tabs, ask which URL to debug, wait for reply — even if only one tab.",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
step: 3,
|
|
135
|
+
tool: "connect",
|
|
136
|
+
action: "connect({ targetUrl }) → [SAME TURN] add debugger; to source → reloadPage() → waitForSpecificPause()",
|
|
137
|
+
note: "Do NOT end your turn after connect. Continue immediately to steps 4 and 5 in the same turn.",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
step: 4,
|
|
141
|
+
tool: "(edit source)",
|
|
142
|
+
action: "[SAME TURN as step 3] Add `debugger; // TODO: remove debugger` at the observation point",
|
|
143
|
+
note: "Record exact filename and editor line number — needed for step 5.",
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
step: 5,
|
|
147
|
+
tool: "reloadPage + waitForSpecificPause",
|
|
148
|
+
action: "[SAME TURN] reloadPage() → immediately waitForSpecificPause({ urlFragment, line: editorLine - 1, timeout: 90000, actionHint: 'describe the action' })",
|
|
149
|
+
note: "waitForSpecificPause is BLOCKING with NO auto-resume. Check 'matched' in response: matched=true → go to step 6; matched=false → call resume() then waitForSpecificPause() again.",
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
step: 6,
|
|
153
|
+
tool: "getScopeVariables + evaluate",
|
|
154
|
+
action: "[SAME TURN as step 5, only if matched=true] getScopeVariables({ frameIndex: 0 }) then evaluate({ expression }) for deep inspection",
|
|
155
|
+
note: "Use frameIndex=1,2... to inspect parent call frames.",
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
step: 7,
|
|
159
|
+
tool: "stepOver / stepInto / stepOut",
|
|
160
|
+
action: "[SAME TURN] Step as needed → getScopeVariables() to observe changes",
|
|
161
|
+
note: "Optional — only when tracing variable changes across statements.",
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
step: 8,
|
|
165
|
+
tool: "resume",
|
|
166
|
+
action: "[SAME TURN] resume() → remove all temporary debugger; lines from source code",
|
|
167
|
+
note: "Session complete. Use the real collected values to implement or fix code.",
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
// ── launchChrome ───────────────────────────────────────────
|
|
173
|
+
// 步骤1:启动调试专用 Chrome 实例(双实例,独立 profile)
|
|
174
|
+
server.tool("launchChrome", `[STEP 1] Launch a dedicated Chrome instance with remote debugging enabled (default port 9222).
|
|
175
|
+
Uses --user-data-dir=~/.chrome-debug-profile so your normal Chrome keeps running (dual-instance).
|
|
176
|
+
Auto-detects if the debug port is already active and skips launch (alreadyRunning=true).
|
|
177
|
+
Use dryRun=true to preview the command — show it to the user and ask for confirmation before executing.
|
|
178
|
+
Set openDevTools=true to automatically open DevTools panel for every new tab.
|
|
179
|
+
If automatic launch does not succeed, relay the returned command to the user and ask them to run it manually.
|
|
180
|
+
Relay the "_ui" field from the response to the user.`, {
|
|
181
|
+
port: z.number().int().positive().optional()
|
|
182
|
+
.describe("Remote debugging port (default 9222)"),
|
|
183
|
+
userDataDir: z.string().optional()
|
|
184
|
+
.describe("Profile directory for the debug instance (default ~/.chrome-debug-profile)"),
|
|
185
|
+
chromePath: z.string().optional()
|
|
186
|
+
.describe("Chrome executable path. Overrides platform defaults and CHROME_PATH/GOOGLE_CHROME_BIN."),
|
|
187
|
+
dryRun: z.boolean().optional()
|
|
188
|
+
.describe("If true, return the launch command without executing it"),
|
|
189
|
+
url: z.string().optional()
|
|
190
|
+
.describe("URL to open immediately after launch"),
|
|
191
|
+
// 自动为新标签页打开 DevTools 控制台
|
|
192
|
+
openDevTools: z.boolean().optional()
|
|
193
|
+
.describe("If true, adds --auto-open-devtools-for-tabs so DevTools opens automatically for every new tab"),
|
|
194
|
+
}, async ({ port, userDataDir, chromePath, dryRun, url, openDevTools }) => {
|
|
195
|
+
try {
|
|
196
|
+
const result = await manager.launchChrome({
|
|
197
|
+
port,
|
|
198
|
+
userDataDir,
|
|
199
|
+
chromePath,
|
|
200
|
+
dryRun,
|
|
201
|
+
url,
|
|
202
|
+
openDevTools,
|
|
203
|
+
});
|
|
204
|
+
// 根据返回状态生成用户提示
|
|
205
|
+
let userMessage;
|
|
206
|
+
if (result.alreadyRunning) {
|
|
207
|
+
userMessage = `Chrome debug port ${port ?? 9222} is already active — skipping launch. Proceeding to list tabs.`;
|
|
208
|
+
}
|
|
209
|
+
else if (dryRun) {
|
|
210
|
+
userMessage = `Here is the Chrome launch command. Please confirm and I'll execute it:\n\`\`\`\n${result.command}\n\`\`\``;
|
|
211
|
+
}
|
|
212
|
+
else if (result.requiresManualLaunch) {
|
|
213
|
+
userMessage = `Chrome did not start successfully. Please launch it manually with this command, then continue:\n\`\`\`\n${result.command}\n\`\`\`\n${result.message}`;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
userMessage = result.launched
|
|
217
|
+
? `Chrome launched successfully with remote debugging on port ${port ?? 9222}.${openDevTools ? " DevTools will open automatically for new tabs." : ""}`
|
|
218
|
+
: `Chrome process started — waiting for it to initialize. I'll list available tabs next.`;
|
|
219
|
+
}
|
|
220
|
+
return ok({ ...result, _ui: { status: "Step 1: Chrome launch", message: userMessage } });
|
|
221
|
+
}
|
|
222
|
+
catch (e) {
|
|
223
|
+
return fail(e.message);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
// ── listTargets ────────────────────────────────────────────
|
|
227
|
+
// 步骤2:列出所有可调试的标签页,必须展示给用户并等待确认
|
|
228
|
+
server.tool("listTargets", `[STEP 2] List all open Chrome tabs available for debugging.
|
|
229
|
+
MANDATORY: show the full list to the user and ask "Which URL do you want to debug?"
|
|
230
|
+
NEVER skip this step, NEVER guess — even if only one tab is open.
|
|
231
|
+
Wait for the user's explicit reply before proceeding to connect().
|
|
232
|
+
Relay the "_ui" field from the response to the user.`, {
|
|
233
|
+
port: z.number().int().positive().optional()
|
|
234
|
+
.describe("Chrome remote debugging port (default 9222)"),
|
|
235
|
+
}, async ({ port }) => {
|
|
236
|
+
try {
|
|
237
|
+
const targets = await manager.listTargets(port ?? 9222);
|
|
238
|
+
const list = targets.map((t, i) => ({
|
|
239
|
+
index: i,
|
|
240
|
+
type: t.type,
|
|
241
|
+
title: t.title,
|
|
242
|
+
url: t.url,
|
|
243
|
+
id: t.id,
|
|
244
|
+
}));
|
|
245
|
+
// 构建展示给用户的标签页列表文本
|
|
246
|
+
const tabLines = list
|
|
247
|
+
.filter((t) => t.type === "page")
|
|
248
|
+
.map((t) => ` [${t.index}] ${t.url}${t.title ? ` — ${t.title}` : ""}`)
|
|
249
|
+
.join("\n");
|
|
250
|
+
return ok({
|
|
251
|
+
targets: list,
|
|
252
|
+
_ui: {
|
|
253
|
+
status: "Step 2: Select debug target",
|
|
254
|
+
message: `Available tabs:\n${tabLines || " (none)"}\n\nWhich URL do you want to debug? Please confirm the target.`,
|
|
255
|
+
requiresUserReply: true,
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
catch (e) {
|
|
260
|
+
return fail(`Failed to list targets: ${e.message}`);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
// ── connect ────────────────────────────────────────────────
|
|
264
|
+
// 步骤3:连接到用户确认的标签页,必须等用户回复 listTargets 后才能调用
|
|
265
|
+
server.tool("connect", `[STEP 3] Connect the debugger to a specific Chrome tab.
|
|
266
|
+
MANDATORY: call listTargets first, show the list to the user, wait for their explicit URL confirmation, then call this.
|
|
267
|
+
NEVER guess the URL. NEVER skip user confirmation — even if only one tab is visible.
|
|
268
|
+
targetUrl must be a unique substring of the tab URL the user confirmed (e.g. "localhost:5173").
|
|
269
|
+
Relay the "_ui" field from the response to the user.`, {
|
|
270
|
+
port: z.number().int().positive().optional()
|
|
271
|
+
.describe("Chrome remote debugging port (default 9222)"),
|
|
272
|
+
targetUrl: z.string()
|
|
273
|
+
.describe("Unique substring of the tab URL confirmed by the user (e.g. 'localhost:5173'). REQUIRED — always obtain from user confirmation."),
|
|
274
|
+
}, async ({ port, targetUrl }) => {
|
|
275
|
+
try {
|
|
276
|
+
const msg = await manager.connect(port ?? 9222, targetUrl);
|
|
277
|
+
return ok({
|
|
278
|
+
message: msg,
|
|
279
|
+
_ui: {
|
|
280
|
+
status: "Step 3: Connected",
|
|
281
|
+
message: `Connected to: ${targetUrl}\n\nNext: I'll insert a temporary \`debugger;\` in the source code at the observation point, then reload the page.`,
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
catch (e) {
|
|
286
|
+
return fail(`Failed to connect: ${e.message}`);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
// ── disconnect ─────────────────────────────────────────────
|
|
290
|
+
// 显式断开当前 Chrome 调试连接,释放会话状态
|
|
291
|
+
server.tool("disconnect", "Disconnect the current Chrome debugging session and clear in-memory pause state. Use this to explicitly end a debug session before connecting again.", {}, async () => {
|
|
292
|
+
try {
|
|
293
|
+
await manager.disconnect();
|
|
294
|
+
return ok({
|
|
295
|
+
message: "Disconnected from Chrome",
|
|
296
|
+
_ui: {
|
|
297
|
+
status: "Disconnected",
|
|
298
|
+
message: "Chrome debugging session disconnected. You can reconnect to another tab when needed.",
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
catch (e) {
|
|
303
|
+
return fail(e.message);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
// ── setBreakpoint ──────────────────────────────────────────
|
|
307
|
+
// CDP 断点:无需修改源码,适合无法编辑文件的场景
|
|
308
|
+
server.tool("setBreakpoint", `Set a breakpoint at a specific script URL and line number via CDP — no source code modification needed.
|
|
309
|
+
Use a full URL (https://...) for exact match, or a partial filename/keyword for regex match.
|
|
310
|
+
Alternative to inserting debugger; when you cannot modify the source file.
|
|
311
|
+
After setting, call reloadPage() to ensure the breakpoint resolves correctly.`, {
|
|
312
|
+
url: z.string().describe("Script URL or URL pattern to match"),
|
|
313
|
+
line: z.number().int().nonnegative().describe("0-based line number"),
|
|
314
|
+
column: z.number().int().nonnegative().optional().describe("0-based column number"),
|
|
315
|
+
condition: z.string().optional().describe("Conditional breakpoint expression"),
|
|
316
|
+
}, async ({ url, line, column, condition }) => {
|
|
317
|
+
try {
|
|
318
|
+
const result = await manager.setBreakpoint(url, line, column, condition);
|
|
319
|
+
return ok(result);
|
|
320
|
+
}
|
|
321
|
+
catch (e) {
|
|
322
|
+
return fail(e.message);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
// ── removeBreakpoint ───────────────────────────────────────
|
|
326
|
+
// 移除 setBreakpoint 设置的断点
|
|
327
|
+
server.tool("removeBreakpoint", "Remove a previously set CDP breakpoint by its ID (returned by setBreakpoint).", {
|
|
328
|
+
breakpointId: z.string().describe("The breakpoint ID returned by setBreakpoint"),
|
|
329
|
+
}, async ({ breakpointId }) => {
|
|
330
|
+
try {
|
|
331
|
+
await manager.removeBreakpoint(breakpointId);
|
|
332
|
+
return ok({ message: "Breakpoint removed", breakpointId });
|
|
333
|
+
}
|
|
334
|
+
catch (e) {
|
|
335
|
+
return fail(e.message);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
// ── waitForPause ───────────────────────────────────────────
|
|
339
|
+
// 备用:阻塞等待任意断点命中,不做位置过滤
|
|
340
|
+
// 阻塞开始前同样通知用户去操作页面
|
|
341
|
+
server.tool("waitForPause", `[STEP 5b — FALLBACK] BLOCKING call — waits until ANY debugger pause occurs (breakpoint, debugger; statement, or exception).
|
|
342
|
+
Before blocking, sends a notification to the user to trigger the page action.
|
|
343
|
+
Must be called IMMEDIATELY after reloadPage() in the SAME AI turn — do NOT end your turn before calling this.
|
|
344
|
+
Prefer waitForSpecificPause when you know the exact file and line — it uses smarter two-tier matching.
|
|
345
|
+
Use this only when the target location is unknown or when setBreakpoint is used without a specific line.`, {
|
|
346
|
+
timeout: z.number().int().positive().optional()
|
|
347
|
+
.describe("Timeout in milliseconds (default 30000)"),
|
|
348
|
+
// 可选的操作提示
|
|
349
|
+
actionHint: z.string().optional()
|
|
350
|
+
.describe("Optional hint to tell the user what action to perform on the page (e.g. 'click the button', 'submit the form')."),
|
|
351
|
+
}, async ({ timeout, actionHint }) => {
|
|
352
|
+
const timeoutMs = timeout ?? 30000;
|
|
353
|
+
const clearReminder = scheduleUserActionReminder(actionHint, timeoutMs);
|
|
354
|
+
try {
|
|
355
|
+
await sendUserActionPrompt("ACTION REQUIRED", actionHint, timeoutMs, "any breakpoint");
|
|
356
|
+
const info = await manager.waitForPause(timeoutMs);
|
|
357
|
+
return ok({
|
|
358
|
+
reason: info.reason,
|
|
359
|
+
hitBreakpoints: info.hitBreakpoints,
|
|
360
|
+
callStack: manager.getCallStackSummary(),
|
|
361
|
+
_ui: {
|
|
362
|
+
status: "Breakpoint hit",
|
|
363
|
+
message: "Breakpoint triggered! Reading scope variables now...",
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
catch (e) {
|
|
368
|
+
return fail(e.message);
|
|
369
|
+
}
|
|
370
|
+
finally {
|
|
371
|
+
clearReminder();
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
// ── waitForSpecificPause ────────────────────────────────────
|
|
375
|
+
// 步骤5b(推荐):阻塞等待下一次暂停,检查是否匹配目标位置,不做任何自动 resume
|
|
376
|
+
// matched=true → 立刻调用 getScopeVariables 读取变量
|
|
377
|
+
// matched=false → 调用 resume() 继续执行,再次调用 waitForSpecificPause 等待下次暂停
|
|
378
|
+
server.tool("waitForSpecificPause", `[STEP 5b — PREFERRED] BLOCKING call — waits for the next debugger pause, then checks if it matches the target location.
|
|
379
|
+
|
|
380
|
+
⚠️ NO AUTO-RESUME: execution stays paused after this returns, regardless of matched value.
|
|
381
|
+
You decide what to do based on the "matched" field in the response:
|
|
382
|
+
matched=true → call getScopeVariables() immediately to read variables
|
|
383
|
+
matched=false → the wrong breakpoint fired; call resume() to continue,
|
|
384
|
+
then call waitForSpecificPause() again if you need to wait for the next pause.
|
|
385
|
+
|
|
386
|
+
Must be called IMMEDIATELY after reloadPage() in the SAME AI turn.
|
|
387
|
+
Before blocking, sends a notification to the user to trigger the page action.
|
|
388
|
+
Editor line N → pass line=N-1 (CDP uses 0-based line numbers).
|
|
389
|
+
Relay the "_ui" field from the response to the user once it returns.`, {
|
|
390
|
+
urlFragment: z.string()
|
|
391
|
+
.describe("Substring of the script URL where debugger; was added (e.g. 'LoginForm.vue', 'utils.ts'). Does NOT need to be the full URL."),
|
|
392
|
+
line: z.number().int().nonnegative()
|
|
393
|
+
.describe("0-based line number where debugger; was inserted. Editor line N → pass N-1."),
|
|
394
|
+
timeout: z.number().int().positive().optional()
|
|
395
|
+
.describe("Timeout in ms to wait for any pause (default 90000). Increase for slow interactions."),
|
|
396
|
+
// 行号容差,打包代码可能需要调大
|
|
397
|
+
lineTolerance: z.number().int().nonnegative().optional()
|
|
398
|
+
.describe("±line tolerance for Tier 1 matching (default 10). Increase to 20+ for heavily bundled code."),
|
|
399
|
+
// 可选的操作提示,用于通知用户在页面上执行什么操作来触发断点
|
|
400
|
+
actionHint: z.string().optional()
|
|
401
|
+
.describe("Describe the page action to trigger the breakpoint (e.g. 'click the Search button'). Shown in the waiting notification to the user."),
|
|
402
|
+
}, async ({ urlFragment, line, timeout, lineTolerance, actionHint }) => {
|
|
403
|
+
const timeoutMs = timeout ?? DEFAULT_SPECIFIC_PAUSE_TIMEOUT_MS;
|
|
404
|
+
const targetDescription = `"${urlFragment}" near line ${line}`;
|
|
405
|
+
const clearReminder = scheduleUserActionReminder(actionHint, timeoutMs, targetDescription);
|
|
406
|
+
try {
|
|
407
|
+
await sendUserActionPrompt("ACTION REQUIRED", actionHint, timeoutMs, targetDescription);
|
|
408
|
+
// 阻塞等待下一次暂停(不自动 resume,不循环)
|
|
409
|
+
const result = await manager.waitForSpecificPause(urlFragment, line, timeoutMs, lineTolerance ?? 10);
|
|
410
|
+
// 根据匹配结果给 AI 不同的后续指引
|
|
411
|
+
const uiMessage = result.matched
|
|
412
|
+
? `Breakpoint hit ✓\n${result.note}\nCall getScopeVariables() now.`
|
|
413
|
+
: `Paused at wrong location ✗\n${result.note}`;
|
|
414
|
+
return ok({
|
|
415
|
+
...result,
|
|
416
|
+
_ui: {
|
|
417
|
+
status: result.matched ? "Breakpoint hit" : "Wrong pause location",
|
|
418
|
+
message: uiMessage,
|
|
419
|
+
},
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
catch (e) {
|
|
423
|
+
return fail(e.message);
|
|
424
|
+
}
|
|
425
|
+
finally {
|
|
426
|
+
clearReminder();
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
// ── getScopeVariables ──────────────────────────────────────
|
|
430
|
+
// 步骤6a:读取当前暂停帧的所有作用域变量
|
|
431
|
+
server.tool("getScopeVariables", `[STEP 6a] Read all scope variables (local, closure, module) at the currently paused call frame.
|
|
432
|
+
Call this immediately after waitForSpecificPause or waitForPause returns.
|
|
433
|
+
Results are grouped by scope type; global scope is skipped.
|
|
434
|
+
Use frameIndex=1, 2, ... to inspect variables in parent call frames up the stack.`, {
|
|
435
|
+
frameIndex: z.number().int().nonnegative().optional()
|
|
436
|
+
.describe("Call frame index (default 0, the topmost frame)"),
|
|
437
|
+
}, async ({ frameIndex }) => {
|
|
438
|
+
try {
|
|
439
|
+
const scopes = await manager.getScopeVariables(frameIndex ?? 0);
|
|
440
|
+
return ok({ frameIndex: frameIndex ?? 0, scopes });
|
|
441
|
+
}
|
|
442
|
+
catch (e) {
|
|
443
|
+
return fail(e.message);
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
// ── evaluate ───────────────────────────────────────────────
|
|
447
|
+
// 步骤6b:在断点处执行任意 JS 表达式,深入检查对象
|
|
448
|
+
server.tool("evaluate", `[STEP 6b] Evaluate any JavaScript expression in the context of the currently paused call frame.
|
|
449
|
+
Use this to inspect nested objects, call methods, compute derived values, or verify conditions at runtime.
|
|
450
|
+
Complements getScopeVariables for values not directly visible in scope (e.g. this.state, JSON.stringify(obj)).`, {
|
|
451
|
+
expression: z.string().describe("JavaScript expression to evaluate"),
|
|
452
|
+
frameIndex: z.number().int().nonnegative().optional()
|
|
453
|
+
.describe("Call frame index (default 0)"),
|
|
454
|
+
}, async ({ expression, frameIndex }) => {
|
|
455
|
+
try {
|
|
456
|
+
const result = await manager.evaluate(expression, frameIndex ?? 0);
|
|
457
|
+
return ok(result);
|
|
458
|
+
}
|
|
459
|
+
catch (e) {
|
|
460
|
+
return fail(e.message);
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
// ── resume ─────────────────────────────────────────────────
|
|
464
|
+
// 步骤8:恢复执行,调试结束后清理临时 debugger; 语句
|
|
465
|
+
server.tool("resume", `[STEP 8] Resume script execution after collecting all needed variable data — ends the current pause.
|
|
466
|
+
After calling resume, remove all temporary debugger; statements added to source code during this session.
|
|
467
|
+
Relay the "_ui" field from the response to the user.`, {}, async () => {
|
|
468
|
+
try {
|
|
469
|
+
await manager.resume();
|
|
470
|
+
return ok({
|
|
471
|
+
message: "Execution resumed",
|
|
472
|
+
_ui: {
|
|
473
|
+
status: "Step 8: Session complete",
|
|
474
|
+
message: "Execution resumed. Cleaning up temporary debugger; statements from source code now.",
|
|
475
|
+
},
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
catch (e) {
|
|
479
|
+
return fail(e.message);
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
// ── stepInto ───────────────────────────────────────────────
|
|
483
|
+
// 步骤7选项:单步进入函数内部
|
|
484
|
+
server.tool("stepInto", "[STEP 7] BLOCKING: step into the next function call, then wait until the debugger pauses again. Follow with getScopeVariables() to observe inner-function state.", {
|
|
485
|
+
timeout: z.number().int().positive().optional()
|
|
486
|
+
.describe("Timeout in milliseconds to wait for the next pause (default 30000)"),
|
|
487
|
+
}, async ({ timeout }) => {
|
|
488
|
+
try {
|
|
489
|
+
const info = await manager.stepInto(timeout);
|
|
490
|
+
return ok({
|
|
491
|
+
message: "Stepped into and paused again",
|
|
492
|
+
reason: info.reason,
|
|
493
|
+
callStack: manager.getCallStackSummary(),
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
catch (e) {
|
|
497
|
+
return fail(e.message);
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
// ── stepOver ───────────────────────────────────────────────
|
|
501
|
+
// 步骤7选项:单步跳过,不进入函数调用
|
|
502
|
+
server.tool("stepOver", "[STEP 7] BLOCKING: step over the current statement without entering function calls, then wait until the debugger pauses again. Follow with getScopeVariables() to observe how local variables change.", {
|
|
503
|
+
timeout: z.number().int().positive().optional()
|
|
504
|
+
.describe("Timeout in milliseconds to wait for the next pause (default 30000)"),
|
|
505
|
+
}, async ({ timeout }) => {
|
|
506
|
+
try {
|
|
507
|
+
const info = await manager.stepOver(timeout);
|
|
508
|
+
return ok({
|
|
509
|
+
message: "Stepped over and paused again",
|
|
510
|
+
reason: info.reason,
|
|
511
|
+
callStack: manager.getCallStackSummary(),
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
catch (e) {
|
|
515
|
+
return fail(e.message);
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
// ── stepOut ────────────────────────────────────────────────
|
|
519
|
+
// 步骤7选项:单步跳出当前函数,回到调用处
|
|
520
|
+
server.tool("stepOut", "[STEP 7] BLOCKING: step out of the current function and wait until the debugger pauses again in the caller. Use to observe the return value and the state of the calling context.", {
|
|
521
|
+
timeout: z.number().int().positive().optional()
|
|
522
|
+
.describe("Timeout in milliseconds to wait for the next pause (default 30000)"),
|
|
523
|
+
}, async ({ timeout }) => {
|
|
524
|
+
try {
|
|
525
|
+
const info = await manager.stepOut(timeout);
|
|
526
|
+
return ok({
|
|
527
|
+
message: "Stepped out and paused again",
|
|
528
|
+
reason: info.reason,
|
|
529
|
+
callStack: manager.getCallStackSummary(),
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
catch (e) {
|
|
533
|
+
return fail(e.message);
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
// ── getStatus ──────────────────────────────────────────────
|
|
537
|
+
// 非阻塞状态查询,适用于客户端有短超时限制的轮询场景
|
|
538
|
+
server.tool("getStatus", `Non-blocking: return current connection and pause state immediately without waiting.
|
|
539
|
+
Use this to poll for pause instead of waitForPause when the MCP client has a short request timeout (e.g. MCP Inspector ~10s).
|
|
540
|
+
Returns: connected, paused, targetUrl, pauseReason, hitBreakpoints, callStack.`, {}, () => {
|
|
541
|
+
try {
|
|
542
|
+
return ok(manager.getStatus());
|
|
543
|
+
}
|
|
544
|
+
catch (e) {
|
|
545
|
+
return fail(e.message);
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
// ── reloadPage ─────────────────────────────────────────────
|
|
549
|
+
// 步骤5a:通过 CDP 重载页面,确保断点正确绑定
|
|
550
|
+
// ⚠️ 重要:返回后必须在同一轮次立刻调用 waitForSpecificPause,不能结束对话轮次
|
|
551
|
+
server.tool("reloadPage", `[STEP 5a] Reload the connected page via Chrome DevTools Protocol.
|
|
552
|
+
More reliable than manual browser refresh — maintains the CDP connection and ensures debugger; statements and setBreakpoint() calls resolve correctly when scripts reload.
|
|
553
|
+
Always call this after inserting debugger; in source code or after setBreakpoint(), before waitForSpecificPause/waitForPause.
|
|
554
|
+
|
|
555
|
+
⚠️ CRITICAL TURN RULE: After this tool returns, you MUST immediately call waitForSpecificPause (or waitForPause) in the SAME AI turn — do NOT end your turn here.
|
|
556
|
+
waitForSpecificPause is a blocking call that will notify the user to trigger the page action and wait for the breakpoint internally.
|
|
557
|
+
If you end your turn after reloadPage, the session will break.`, {
|
|
558
|
+
ignoreCache: z.boolean().optional()
|
|
559
|
+
.describe("Hard reload ignoring cache (default false)"),
|
|
560
|
+
}, async ({ ignoreCache }) => {
|
|
561
|
+
try {
|
|
562
|
+
const msg = await manager.reloadPage(ignoreCache ?? false);
|
|
563
|
+
return ok({
|
|
564
|
+
message: msg,
|
|
565
|
+
// _ui 不包含"请操作页面"——那条提示由 waitForSpecificPause 通过 logging 发出
|
|
566
|
+
// 这里只告诉 AI 下一步做什么,促使它立刻继续调用,而不是结束轮次
|
|
567
|
+
_ui: {
|
|
568
|
+
status: "Step 5a: Reload requested — calling waitForSpecificPause now",
|
|
569
|
+
message: "Reload requested. Now calling waitForSpecificPause to block and wait for the breakpoint...",
|
|
570
|
+
nextAction: "IMMEDIATELY call waitForSpecificPause in this same turn — do not end your turn.",
|
|
571
|
+
},
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
catch (e) {
|
|
575
|
+
return fail(e.message);
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
// ── forcePause ─────────────────────────────────────────────
|
|
579
|
+
// 强制在下一条 JS 语句处暂停,适用于无法修改源码的场景
|
|
580
|
+
server.tool("forcePause", "Force the debugger to pause at the very next JavaScript statement. Useful when you cannot modify source code to add debugger; and setBreakpoint is not feasible.", {}, async () => {
|
|
581
|
+
try {
|
|
582
|
+
await manager.pause();
|
|
583
|
+
return ok({
|
|
584
|
+
message: "Pause requested – execution will pause at next statement",
|
|
585
|
+
_ui: {
|
|
586
|
+
status: "Force pause requested",
|
|
587
|
+
message: "Pause requested. The debugger will stop at the next JavaScript statement — please interact with the page to trigger execution.",
|
|
588
|
+
},
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
catch (e) {
|
|
592
|
+
return fail(e.message);
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
// ── 启动服务器 ─────────────────────────────────────────────
|
|
596
|
+
async function main() {
|
|
597
|
+
const transport = new StdioServerTransport();
|
|
598
|
+
await server.connect(transport);
|
|
599
|
+
console.error("chrome-debugger-mcp server running on stdio");
|
|
600
|
+
}
|
|
601
|
+
main().catch((err) => {
|
|
602
|
+
console.error("Fatal error:", err);
|
|
603
|
+
process.exit(1);
|
|
604
|
+
});
|
|
605
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,OAAO,GAAG,IAAI,qBAAqB,EAAE,CAAC;AAE5C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,OAAO,EAAE,OAAO;CACjB,EAAE;IACD,YAAY,EAAE;QACZ,OAAO,EAAE,EAAE;KACZ;CACF,CAAC,CAAC;AAEH,MAAM,6BAA6B,GAAG,MAAM,CAAC;AAC7C,MAAM,iCAAiC,GAAG,MAAM,CAAC;AAEjD,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;IACvB,KAAK,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC;QACpC,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,KAAK,EAAE,iBAAiB;YACxB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;gBACxC,KAAK,EAAE,CAAC;gBACR,YAAY,EAAE,CAAC,CAAC,YAAY,IAAI,aAAa;gBAC7C,GAAG,EAAE,CAAC,CAAC,GAAG;gBACV,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU;gBAC3B,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,YAAY;aAChC,CAAC,CAAC;SACJ,CAAC;KACH,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC;AAEH,WAAW;AACX,SAAS,EAAE,CAAC,IAAa;IACvB,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC;AACJ,CAAC;AAED,WAAW;AACX,SAAS,IAAI,CAAC,OAAe;IAC3B,OAAO;QACL,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE;SACpE;QACD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAC7B,OAAe,EACf,UAA8B,EAC9B,SAAiB,EACjB,iBAA0B;IAE1B,MAAM,UAAU,GAAG,UAAU,EAAE,IAAI,EAAE;QACnC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE;QACnB,CAAC,CAAC,6DAA6D,CAAC;IAClE,MAAM,KAAK,GAAG;QACZ,OAAO;QACP,oCAAoC;KACrC,CAAC;IAEF,IAAI,iBAAiB,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,WAAW,iBAAiB,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,IAAI,CACR,kBAAkB,EAClB,UAAU,EACV,oBAAoB,SAAS,IAAI,CAClC,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,OAAe,EACf,UAA8B,EAC9B,SAAiB,EACjB,iBAA0B;IAE1B,MAAM,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC;QACrC,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,sBAAsB,CAC1B,OAAO,EACP,UAAU,EACV,SAAS,EACT,iBAAiB,CAClB;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,0BAA0B,CACjC,UAA8B,EAC9B,SAAiB,EACjB,iBAA0B;IAE1B,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAC9B,6BAA6B,EAC7B,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAC3C,CAAC;IACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;QAC5B,KAAK,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC;YACpC,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,sBAAsB,CAC1B,uBAAuB,EACvB,UAAU,EACV,SAAS,EACT,iBAAiB,CAClB;SACF,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrB,CAAC,EAAE,eAAe,CAAC,CAAC;IAEpB,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,8DAA8D;AAC9D,wCAAwC;AACxC,MAAM,CAAC,IAAI,CACT,uBAAuB,EACvB;;;;;;;;qEAQmE,EACnE,EAAE,EACF,GAAG,EAAE;IACH,OAAO,EAAE,CAAC;QACR,mBAAmB;QACnB,GAAG,EAAE;YACH,MAAM,EAAE,wBAAwB;YAChC,OAAO,EAAE,4EAA4E;SACtF;QACD,KAAK,EAAE,oCAAoC;QAC3C,iBAAiB;QACjB,cAAc,EAAE;YACd,gFAAgF;YAChF,yGAAyG;YACzG,6FAA6F;YAC7F,gJAAgJ;YAChJ,oGAAoG;YACpG,4EAA4E;SAC7E;QACD,mCAAmC;QACnC,mBAAmB,EAAE;YACnB,qEAAqE;YACrE,0FAA0F;YAC1F,8EAA8E;YAC9E,4EAA4E;YAC5E,uDAAuD;YACvD,uFAAuF;YACvF,gGAAgG;YAChG,4OAA4O;YAC5O,8FAA8F;YAC9F,2FAA2F;YAC3F,4JAA4J;SAC7J;QACD,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,CAAC;gBACP,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,2GAA2G;gBACnH,IAAI,EAAE,6GAA6G;aACpH;YACD;gBACE,IAAI,EAAE,CAAC;gBACP,IAAI,EAAE,aAAa;gBACnB,MAAM,EAAE,oFAAoF;gBAC5F,IAAI,EAAE,0FAA0F;aACjG;YACD;gBACE,IAAI,EAAE,CAAC;gBACP,IAAI,EAAE,SAAS;gBACf,MAAM,EAAE,sGAAsG;gBAC9G,IAAI,EAAE,6FAA6F;aACpG;YACD;gBACE,IAAI,EAAE,CAAC;gBACP,IAAI,EAAE,eAAe;gBACrB,MAAM,EAAE,yFAAyF;gBACjG,IAAI,EAAE,mEAAmE;aAC1E;YACD;gBACE,IAAI,EAAE,CAAC;gBACP,IAAI,EAAE,mCAAmC;gBACzC,MAAM,EAAE,uJAAuJ;gBAC/J,IAAI,EAAE,kLAAkL;aACzL;YACD;gBACE,IAAI,EAAE,CAAC;gBACP,IAAI,EAAE,8BAA8B;gBACpC,MAAM,EAAE,oIAAoI;gBAC5I,IAAI,EAAE,sDAAsD;aAC7D;YACD;gBACE,IAAI,EAAE,CAAC;gBACP,IAAI,EAAE,+BAA+B;gBACrC,MAAM,EAAE,qEAAqE;gBAC7E,IAAI,EAAE,kEAAkE;aACzE;YACD;gBACE,IAAI,EAAE,CAAC;gBACP,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,8EAA8E;gBACtF,IAAI,EAAE,2EAA2E;aAClF;SACF;KACF,CAAC,CAAC;AACL,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,uCAAuC;AACvC,MAAM,CAAC,IAAI,CACT,cAAc,EACd;;;;;;qDAMmD,EACnD;IACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;SACzC,QAAQ,CAAC,sCAAsC,CAAC;IACnD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAC/B,QAAQ,CAAC,4EAA4E,CAAC;IACzF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAC9B,QAAQ,CAAC,wFAAwF,CAAC;IACrG,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;SAC3B,QAAQ,CAAC,yDAAyD,CAAC;IACtE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SACvB,QAAQ,CAAC,sCAAsC,CAAC;IACnD,yBAAyB;IACzB,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;SACjC,QAAQ,CAAC,+FAA+F,CAAC;CAC7G,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,EAAE,EAAE;IACrE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC;YACxC,IAAI;YACJ,WAAW;YACX,UAAU;YACV,MAAM;YACN,GAAG;YACH,YAAY;SACb,CAAC,CAAC;QAEH,eAAe;QACf,IAAI,WAAmB,CAAC;QACxB,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;YAC1B,WAAW,GAAG,qBAAqB,IAAI,IAAI,IAAI,gEAAgE,CAAC;QAClH,CAAC;aAAM,IAAI,MAAM,EAAE,CAAC;YAClB,WAAW,GAAG,mFAAmF,MAAM,CAAC,OAAO,UAAU,CAAC;QAC5H,CAAC;aAAM,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;YACvC,WAAW,GAAG,2GAA2G,MAAM,CAAC,OAAO,aAAa,MAAM,CAAC,OAAO,EAAE,CAAC;QACvK,CAAC;aAAM,CAAC;YACN,WAAW,GAAG,MAAM,CAAC,QAAQ;gBAC3B,CAAC,CAAC,8DAA8D,IAAI,IAAI,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,iDAAiD,CAAC,CAAC,CAAC,EAAE,EAAE;gBACvJ,CAAC,CAAC,uFAAuF,CAAC;QAC9F,CAAC;QAED,OAAO,EAAE,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,uBAAuB,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;IAC3F,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,+BAA+B;AAC/B,MAAM,CAAC,IAAI,CACT,aAAa,EACb;;;;qDAImD,EACnD;IACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;SACzC,QAAQ,CAAC,6CAA6C,CAAC;CAC3D,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YAClC,KAAK,EAAE,CAAC;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,EAAE,EAAE,CAAC,CAAC,EAAE;SACT,CAAC,CAAC,CAAC;QAEJ,kBAAkB;QAClB,MAAM,QAAQ,GAAG,IAAI;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;aAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;aACtE,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,OAAO,EAAE,CAAC;YACR,OAAO,EAAE,IAAI;YACb,GAAG,EAAE;gBACH,MAAM,EAAE,6BAA6B;gBACrC,OAAO,EAAE,oBAAoB,QAAQ,IAAI,UAAU,gEAAgE;gBACnH,iBAAiB,EAAE,IAAI;aACxB;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,2BAA2B,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,4CAA4C;AAC5C,MAAM,CAAC,IAAI,CACT,SAAS,EACT;;;;qDAImD,EACnD;IACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;SACzC,QAAQ,CAAC,6CAA6C,CAAC;IAC1D,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;SAClB,QAAQ,CAAC,iIAAiI,CAAC;CAC/I,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,EAAE,SAAS,CAAC,CAAC;QAE3D,OAAO,EAAE,CAAC;YACR,OAAO,EAAE,GAAG;YACZ,GAAG,EAAE;gBACH,MAAM,EAAE,mBAAmB;gBAC3B,OAAO,EAAE,iBAAiB,SAAS,oHAAoH;aACxJ;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,sBAAsB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,4BAA4B;AAC5B,MAAM,CAAC,IAAI,CACT,YAAY,EACZ,sJAAsJ,EACtJ,EAAE,EACF,KAAK,IAAI,EAAE;IACT,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;YACR,OAAO,EAAE,0BAA0B;YACnC,GAAG,EAAE;gBACH,MAAM,EAAE,cAAc;gBACtB,OAAO,EAAE,sFAAsF;aAChG;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,4BAA4B;AAC5B,MAAM,CAAC,IAAI,CACP,eAAe,EACf;;;gFAG4E,EAC5E;IACE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;IAC9D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IACpE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACnF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;CAC/E,EACD,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QACzE,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,yBAAyB;AACzB,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,+EAA+E,EAC/E;IACE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;CACjF,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE;IACzB,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAC7C,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,uBAAuB;AACvB,mBAAmB;AACnB,MAAM,CAAC,IAAI,CACT,cAAc,EACd;;;;2GAIuG,EACvG;IACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;SAC5C,QAAQ,CAAC,yCAAyC,CAAC;IACtD,UAAU;IACV,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAC9B,QAAQ,CAAC,iHAAiH,CAAC;CAC/H,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE;IAChC,MAAM,SAAS,GAAG,OAAO,IAAI,KAAK,CAAC;IACnC,MAAM,aAAa,GAAG,0BAA0B,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACxE,IAAI,CAAC;QACH,MAAM,oBAAoB,CACxB,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,gBAAgB,CACjB,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QACnD,OAAO,EAAE,CAAC;YACR,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,SAAS,EAAE,OAAO,CAAC,mBAAmB,EAAE;YACxC,GAAG,EAAE;gBACH,MAAM,EAAE,gBAAgB;gBACxB,OAAO,EAAE,sDAAsD;aAChE;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;YAAS,CAAC;QACT,aAAa,EAAE,CAAC;IAClB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,+DAA+D;AAC/D,8CAA8C;AAC9C,8CAA8C;AAC9C,oEAAoE;AACpE,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB;;;;;;;;;;;uEAWmE,EACnE;IACE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;SACpB,QAAQ,CAAC,6HAA6H,CAAC;IAC1I,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;SACjC,QAAQ,CAAC,6EAA6E,CAAC;IAC1F,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;SAC5C,QAAQ,CAAC,sFAAsF,CAAC;IACnG,kBAAkB;IAClB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;SACrD,QAAQ,CAAC,6FAA6F,CAAC;IAC1G,gCAAgC;IAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAC9B,QAAQ,CAAC,qIAAqI,CAAC;CACnJ,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,EAAE,EAAE;IAClE,MAAM,SAAS,GAAG,OAAO,IAAI,iCAAiC,CAAC;IAC/D,MAAM,iBAAiB,GAAG,IAAI,WAAW,eAAe,IAAI,EAAE,CAAC;IAC/D,MAAM,aAAa,GAAG,0BAA0B,CAC9C,UAAU,EACV,SAAS,EACT,iBAAiB,CAClB,CAAC;IACF,IAAI,CAAC;QACH,MAAM,oBAAoB,CACxB,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,iBAAiB,CAClB,CAAC;QAEF,4BAA4B;QAC5B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAC/C,WAAW,EACX,IAAI,EACJ,SAAS,EACT,aAAa,IAAI,EAAE,CACpB,CAAC;QAEF,qBAAqB;QACrB,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO;YAC9B,CAAC,CAAC,qBAAqB,MAAM,CAAC,IAAI,iCAAiC;YACnE,CAAC,CAAC,+BAA+B,MAAM,CAAC,IAAI,EAAE,CAAC;QAEjD,OAAO,EAAE,CAAC;YACR,GAAG,MAAM;YACT,GAAG,EAAE;gBACH,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,sBAAsB;gBAClE,OAAO,EAAE,SAAS;aACnB;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;YAAS,CAAC;QACT,aAAa,EAAE,CAAC;IAClB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,uBAAuB;AACvB,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB;;;oFAGgF,EAChF;IACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;SAClD,QAAQ,CAAC,iDAAiD,CAAC;CAC/D,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,iBAAiB,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;QAChE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,UAAU,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,8BAA8B;AAC9B,MAAM,CAAC,IAAI,CACT,UAAU,EACV;;iHAE6G,EAC7G;IACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IACpE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;SAClD,QAAQ,CAAC,8BAA8B,CAAC;CAC5C,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,EAAE;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,UAAU,EAAE,UAAU,IAAI,CAAC,CAAC,CAAC;QACnE,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,kCAAkC;AAClC,MAAM,CAAC,IAAI,CACT,QAAQ,EACR;;uDAEmD,EACnD,EAAE,EACF,KAAK,IAAI,EAAE;IACT,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;YACR,OAAO,EAAE,mBAAmB;YAC5B,GAAG,EAAE;gBACH,MAAM,EAAE,0BAA0B;gBAClC,OAAO,EAAE,qFAAqF;aAC/F;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,iBAAiB;AACjB,MAAM,CAAC,IAAI,CACT,UAAU,EACV,kKAAkK,EAClK;IACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;SAC5C,QAAQ,CAAC,oEAAoE,CAAC;CAClF,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;IACpB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC7C,OAAO,EAAE,CAAC;YACR,OAAO,EAAE,+BAA+B;YACxC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,OAAO,CAAC,mBAAmB,EAAE;SACzC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,qBAAqB;AACrB,MAAM,CAAC,IAAI,CACT,UAAU,EACV,uMAAuM,EACvM;IACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;SAC5C,QAAQ,CAAC,oEAAoE,CAAC;CAClF,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;IACpB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC7C,OAAO,EAAE,CAAC;YACR,OAAO,EAAE,+BAA+B;YACxC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,OAAO,CAAC,mBAAmB,EAAE;SACzC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,uBAAuB;AACvB,MAAM,CAAC,IAAI,CACT,SAAS,EACT,mLAAmL,EACnL;IACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;SAC5C,QAAQ,CAAC,oEAAoE,CAAC;CAClF,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;IACpB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5C,OAAO,EAAE,CAAC;YACR,OAAO,EAAE,8BAA8B;YACvC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,OAAO,CAAC,mBAAmB,EAAE;SACzC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,4BAA4B;AAC5B,MAAM,CAAC,IAAI,CACT,WAAW,EACX;;iFAE6E,EAC7E,EAAE,EACF,GAAG,EAAE;IACH,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAC9D,4BAA4B;AAC5B,qDAAqD;AACrD,MAAM,CAAC,IAAI,CACT,YAAY,EACZ;;;;;;iEAM6D,EAC7D;IACE,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;SAChC,QAAQ,CAAC,4CAA4C,CAAC;CAC1D,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,WAAW,IAAI,KAAK,CAAC,CAAC;QAC3D,OAAO,EAAE,CAAC;YACR,OAAO,EAAE,GAAG;YACZ,2DAA2D;YAC3D,oCAAoC;YACpC,GAAG,EAAE;gBACH,MAAM,EAAE,8DAA8D;gBACtE,OAAO,EAAE,4FAA4F;gBACrG,UAAU,EAAE,iFAAiF;aAC9F;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,8DAA8D;AAChE,+BAA+B;AAC/B,MAAM,CAAC,IAAI,CACP,YAAY,EACZ,kKAAkK,EAClK,EAAE,EACF,KAAK,IAAI,EAAE;IACT,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;YACR,OAAO,EAAE,0DAA0D;YACnE,GAAG,EAAE;gBACH,MAAM,EAAE,uBAAuB;gBAC/B,OAAO,EAAE,gIAAgI;aAC1I;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CACF,CAAC;AAEF,yDAAyD;AACzD,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;AAC/D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|