@comecaramelos/dsh-chrome-mcp 0.0.1 → 2.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/README.md +44 -95
- package/assets/dsh-chrome-mcp-social.png +0 -0
- package/assets/icon.svg +71 -0
- package/assets/prelaunch-windows-chrome.html +277 -0
- package/lib/client.js +3005 -568
- package/lib/client.js.map +7 -0
- package/lib/host/apply.d.ts +40 -0
- package/lib/host/apply.d.ts.map +1 -0
- package/lib/host/apply.js +57 -0
- package/lib/host/apply.js.map +1 -0
- package/lib/host/bridge.d.ts +74 -0
- package/lib/host/bridge.d.ts.map +1 -0
- package/lib/host/bridge.js +168 -0
- package/lib/host/bridge.js.map +1 -0
- package/lib/host/catalog.d.ts +31 -0
- package/lib/host/catalog.d.ts.map +1 -0
- package/lib/host/catalog.js +92 -0
- package/lib/host/catalog.js.map +1 -0
- package/lib/host/commands/chrome-path.d.ts +4 -0
- package/lib/host/commands/chrome-path.d.ts.map +1 -0
- package/lib/host/commands/chrome-path.js +65 -0
- package/lib/host/commands/chrome-path.js.map +1 -0
- package/lib/host/commands/chrome-refresh.d.ts +17 -0
- package/lib/host/commands/chrome-refresh.d.ts.map +1 -0
- package/lib/host/commands/chrome-refresh.js +37 -0
- package/lib/host/commands/chrome-refresh.js.map +1 -0
- package/lib/host/commands/index.d.ts +26 -0
- package/lib/host/commands/index.d.ts.map +1 -0
- package/lib/host/commands/index.js +41 -0
- package/lib/host/commands/index.js.map +1 -0
- package/lib/host/constants.d.ts +306 -0
- package/lib/host/constants.d.ts.map +1 -0
- package/lib/host/constants.js +319 -0
- package/lib/host/constants.js.map +1 -0
- package/lib/host/controller/_trace.d.ts +3 -0
- package/lib/host/controller/_trace.d.ts.map +1 -0
- package/lib/host/controller/_trace.js +14 -0
- package/lib/host/controller/_trace.js.map +1 -0
- package/lib/host/controller/bridge-run.d.ts +40 -0
- package/lib/host/controller/bridge-run.d.ts.map +1 -0
- package/lib/host/controller/bridge-run.js +85 -0
- package/lib/host/controller/bridge-run.js.map +1 -0
- package/lib/host/controller/captures.d.ts +15 -0
- package/lib/host/controller/captures.d.ts.map +1 -0
- package/lib/host/controller/captures.js +85 -0
- package/lib/host/controller/captures.js.map +1 -0
- package/lib/host/controller/commits.d.ts +4 -0
- package/lib/host/controller/commits.d.ts.map +1 -0
- package/lib/host/controller/commits.js +131 -0
- package/lib/host/controller/commits.js.map +1 -0
- package/lib/host/controller/connections.d.ts +38 -0
- package/lib/host/controller/connections.d.ts.map +1 -0
- package/lib/host/controller/connections.js +71 -0
- package/lib/host/controller/connections.js.map +1 -0
- package/lib/host/controller/controller.d.ts +35 -0
- package/lib/host/controller/controller.d.ts.map +1 -0
- package/lib/host/controller/controller.js +234 -0
- package/lib/host/controller/controller.js.map +1 -0
- package/lib/host/controller/index.d.ts +30 -0
- package/lib/host/controller/index.d.ts.map +1 -0
- package/lib/host/controller/index.js +27 -0
- package/lib/host/controller/index.js.map +1 -0
- package/lib/host/controller/notes.d.ts +26 -0
- package/lib/host/controller/notes.d.ts.map +1 -0
- package/lib/host/controller/notes.js +44 -0
- package/lib/host/controller/notes.js.map +1 -0
- package/lib/host/controller/persist.d.ts +16 -0
- package/lib/host/controller/persist.d.ts.map +1 -0
- package/lib/host/controller/persist.js +98 -0
- package/lib/host/controller/persist.js.map +1 -0
- package/lib/host/controller/publish.d.ts +4 -0
- package/lib/host/controller/publish.d.ts.map +1 -0
- package/lib/host/controller/publish.js +56 -0
- package/lib/host/controller/publish.js.map +1 -0
- package/lib/host/controller/runs.d.ts +80 -0
- package/lib/host/controller/runs.d.ts.map +1 -0
- package/lib/host/controller/runs.js +394 -0
- package/lib/host/controller/runs.js.map +1 -0
- package/lib/host/controller/state.d.ts +172 -0
- package/lib/host/controller/state.d.ts.map +1 -0
- package/lib/host/controller/state.js +2 -0
- package/lib/host/controller/state.js.map +1 -0
- package/lib/host/controller/windows-run.d.ts +17 -0
- package/lib/host/controller/windows-run.d.ts.map +1 -0
- package/lib/host/controller/windows-run.js +109 -0
- package/lib/host/controller/windows-run.js.map +1 -0
- package/lib/host/discovery/candidates.d.ts +47 -0
- package/lib/host/discovery/candidates.d.ts.map +1 -0
- package/lib/host/discovery/candidates.js +68 -0
- package/lib/host/discovery/candidates.js.map +1 -0
- package/lib/host/discovery/index.d.ts +19 -0
- package/lib/host/discovery/index.d.ts.map +1 -0
- package/lib/host/discovery/index.js +19 -0
- package/lib/host/discovery/index.js.map +1 -0
- package/lib/host/discovery/probe.d.ts +29 -0
- package/lib/host/discovery/probe.d.ts.map +1 -0
- package/lib/host/discovery/probe.js +155 -0
- package/lib/host/discovery/probe.js.map +1 -0
- package/lib/host/discovery/scan.d.ts +72 -0
- package/lib/host/discovery/scan.d.ts.map +1 -0
- package/lib/host/discovery/scan.js +195 -0
- package/lib/host/discovery/scan.js.map +1 -0
- package/lib/host/flags.d.ts +65 -0
- package/lib/host/flags.d.ts.map +1 -0
- package/lib/host/flags.js +186 -0
- package/lib/host/flags.js.map +1 -0
- package/lib/host/kind.d.ts +45 -0
- package/lib/host/kind.d.ts.map +1 -0
- package/lib/host/kind.js +251 -0
- package/lib/host/kind.js.map +1 -0
- package/lib/host/manager.d.ts +21 -0
- package/lib/host/manager.d.ts.map +1 -0
- package/lib/host/manager.js +113 -0
- package/lib/host/manager.js.map +1 -0
- package/lib/host/migration.d.ts +26 -0
- package/lib/host/migration.d.ts.map +1 -0
- package/lib/host/migration.js +127 -0
- package/lib/host/migration.js.map +1 -0
- package/lib/host/platform.d.ts +38 -0
- package/lib/host/platform.d.ts.map +1 -0
- package/lib/host/platform.js +64 -0
- package/lib/host/platform.js.map +1 -0
- package/lib/host/plugin-meta.d.ts +21 -0
- package/lib/host/plugin-meta.d.ts.map +1 -0
- package/lib/host/plugin-meta.js +21 -0
- package/lib/host/plugin-meta.js.map +1 -0
- package/lib/host/schema.d.ts +361 -0
- package/lib/host/schema.d.ts.map +1 -0
- package/lib/host/schema.js +196 -0
- package/lib/host/schema.js.map +1 -0
- package/lib/host/settings.d.ts +28 -0
- package/lib/host/settings.d.ts.map +1 -0
- package/lib/host/settings.js +91 -0
- package/lib/host/settings.js.map +1 -0
- package/lib/host/status.d.ts +25 -0
- package/lib/host/status.d.ts.map +1 -0
- package/lib/host/status.js +45 -0
- package/lib/host/status.js.map +1 -0
- package/lib/host/tool.d.ts +65 -0
- package/lib/host/tool.d.ts.map +1 -0
- package/lib/host/tool.js +52 -0
- package/lib/host/tool.js.map +1 -0
- package/lib/host/types/config.d.ts +101 -0
- package/lib/host/types/config.d.ts.map +1 -0
- package/lib/host/types/config.js +2 -0
- package/lib/host/types/config.js.map +1 -0
- package/lib/host/types/executable.d.ts +35 -0
- package/lib/host/types/executable.d.ts.map +1 -0
- package/lib/host/types/executable.js +9 -0
- package/lib/host/types/executable.js.map +1 -0
- package/lib/host/types/index.d.ts +24 -0
- package/lib/host/types/index.d.ts.map +1 -0
- package/lib/host/types/index.js +2 -0
- package/lib/host/types/index.js.map +1 -0
- package/lib/host/types/plugin.d.ts +38 -0
- package/lib/host/types/plugin.d.ts.map +1 -0
- package/lib/host/types/plugin.js +10 -0
- package/lib/host/types/plugin.js.map +1 -0
- package/lib/host/types/services.d.ts +26 -0
- package/lib/host/types/services.d.ts.map +1 -0
- package/lib/host/types/services.js +9 -0
- package/lib/host/types/services.js.map +1 -0
- package/lib/host/types/settings.d.ts +180 -0
- package/lib/host/types/settings.d.ts.map +1 -0
- package/lib/host/types/settings.js +2 -0
- package/lib/host/types/settings.js.map +1 -0
- package/lib/host/types/stderr.d.ts +51 -0
- package/lib/host/types/stderr.d.ts.map +1 -0
- package/lib/host/types/stderr.js +9 -0
- package/lib/host/types/stderr.js.map +1 -0
- package/lib/host/types/windows.d.ts +39 -0
- package/lib/host/types/windows.d.ts.map +1 -0
- package/lib/host/types/windows.js +9 -0
- package/lib/host/types/windows.js.map +1 -0
- package/lib/host/values.d.ts +204 -0
- package/lib/host/values.d.ts.map +1 -0
- package/lib/host/values.js +404 -0
- package/lib/host/values.js.map +1 -0
- package/lib/host/windows/connect-flags.d.ts +27 -0
- package/lib/host/windows/connect-flags.d.ts.map +1 -0
- package/lib/host/windows/connect-flags.js +97 -0
- package/lib/host/windows/connect-flags.js.map +1 -0
- package/lib/host/windows/index.d.ts +31 -0
- package/lib/host/windows/index.d.ts.map +1 -0
- package/lib/host/windows/index.js +30 -0
- package/lib/host/windows/index.js.map +1 -0
- package/lib/host/windows/landing.d.ts +47 -0
- package/lib/host/windows/landing.d.ts.map +1 -0
- package/lib/host/windows/landing.js +174 -0
- package/lib/host/windows/landing.js.map +1 -0
- package/lib/host/windows/link.d.ts +11 -0
- package/lib/host/windows/link.d.ts.map +1 -0
- package/lib/host/windows/link.js +52 -0
- package/lib/host/windows/link.js.map +1 -0
- package/lib/host/windows/paths.d.ts +64 -0
- package/lib/host/windows/paths.d.ts.map +1 -0
- package/lib/host/windows/paths.js +148 -0
- package/lib/host/windows/paths.js.map +1 -0
- package/lib/host/windows/run.d.ts +74 -0
- package/lib/host/windows/run.d.ts.map +1 -0
- package/lib/host/windows/run.js +211 -0
- package/lib/host/windows/run.js.map +1 -0
- package/lib/host/windows/spawn.d.ts +22 -0
- package/lib/host/windows/spawn.d.ts.map +1 -0
- package/lib/host/windows/spawn.js +73 -0
- package/lib/host/windows/spawn.js.map +1 -0
- package/lib/index.d.ts +102 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +102 -636
- package/lib/index.js.map +1 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +57 -14
- package/cordis.patch.yml +0 -5
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chrome discovery — the scan and the check run that tie it together.
|
|
3
|
+
*
|
|
4
|
+
* What one executable run does: probe every candidate it has (the row-config
|
|
5
|
+
* list, the saved rows' ids, the selection), publish the per-path answer, and
|
|
6
|
+
* report the first runnable one. The candidate ordering lives in
|
|
7
|
+
* ./candidates.ts; the `--version` probe + presence + identity helpers in
|
|
8
|
+
* ./probe.ts.
|
|
9
|
+
*
|
|
10
|
+
* Upstream (`chrome-devtools-mcp`, via puppeteer) starts the browser only
|
|
11
|
+
* LAZILY, on the first tool call — so without a probe of our own, a
|
|
12
|
+
* Chrome-less host would show nothing until somebody called a tool. The scan
|
|
13
|
+
* therefore probes eagerly: there is no "auto" mode, the scan lists what exists,
|
|
14
|
+
* the card picks one of them, and what is picked stays picked.
|
|
15
|
+
*
|
|
16
|
+
* WSL NOTE: the executable the bridge *launches* has to be a Linux binary.
|
|
17
|
+
* Launching the Windows chrome.exe through the WSL interop layer fails:
|
|
18
|
+
* chrome-devtools-mcp connects with `pipe: true` (inherited fd 3/4), and
|
|
19
|
+
* Windows-side processes cannot receive those pipes from WSL; the WebSocket
|
|
20
|
+
* fallback hard-codes 127.0.0.1 in the DevToolsActivePort file, unreachable
|
|
21
|
+
* across the WSL2 NAT bridge. Verified empirically 2025-09-19 (.probe/). What
|
|
22
|
+
* the Windows side *is* good for is connect mode, so on a WSL host the Windows
|
|
23
|
+
* executables join the candidate list as `blockedForPlatform` answers it —
|
|
24
|
+
* visible, selectable, never spawned — and the run that drives them is the
|
|
25
|
+
* **Prelaunch Windows Chrome** one. Never spawn a blocked candidate.
|
|
26
|
+
*/
|
|
27
|
+
import { flagsSkipProbe } from "../flags.js";
|
|
28
|
+
import { firstLine } from "../status.js";
|
|
29
|
+
import { readConfigField } from "../values.js";
|
|
30
|
+
import { windowsPathToMount } from "../windows/paths.js";
|
|
31
|
+
import { defaultChromePaths } from "./candidates.js";
|
|
32
|
+
import { identity, presentOnDisk, probeExecutable } from "./probe.js";
|
|
33
|
+
/**
|
|
34
|
+
* What one run probes: every candidate it has — the row-config candidate list,
|
|
35
|
+
* the paths the saved rows carry, and the current selection (see
|
|
36
|
+
* {@link chromeExecutableCandidates}) — probed in that order.
|
|
37
|
+
*
|
|
38
|
+
* A candidate that runs answers with its `--version` line; one that is present
|
|
39
|
+
* but not runnable (bad binary, a probe that timed out) keeps its place in the
|
|
40
|
+
* list carrying the failure, so a broken pin stays visible instead of vanishing
|
|
41
|
+
* into a red dot.
|
|
42
|
+
*
|
|
43
|
+
* - absent / not executable → dropped without a spawn,
|
|
44
|
+
* - `blockedForPlatform` answers non-empty → **no spawn**: the candidate keeps
|
|
45
|
+
* its place carrying that reason as a `note`, never as a failure (the one case
|
|
46
|
+
* is a Windows `chrome.exe` on a WSL host, whose probe would start a browser
|
|
47
|
+
* instance it can never drive — see {@link WSL_WINDOWS_LAUNCH_ERROR}),
|
|
48
|
+
* - two spellings of the same binary collapse into the first one seen.
|
|
49
|
+
*
|
|
50
|
+
* An empty candidate list resolves `[]` (nothing probed: unknown platform, or a
|
|
51
|
+
* host patched down to nothing).
|
|
52
|
+
*
|
|
53
|
+
* @param candidates - candidate executable paths.
|
|
54
|
+
* @param blockedForPlatform - answers a reason for a candidate this host must
|
|
55
|
+
* never exec, `""` for one it may probe.
|
|
56
|
+
*/
|
|
57
|
+
export async function scanChromeExecutables(candidates, blockedForPlatform = () => "") {
|
|
58
|
+
const list = Array.isArray(candidates) ? candidates : [];
|
|
59
|
+
const statuses = [];
|
|
60
|
+
const seen = new Set();
|
|
61
|
+
for (const candidate of list) {
|
|
62
|
+
const path = String(candidate ?? "").trim();
|
|
63
|
+
if (path === "")
|
|
64
|
+
continue;
|
|
65
|
+
const blocked = blockedForPlatform(path);
|
|
66
|
+
if (blocked !== "") {
|
|
67
|
+
// Never spawned: what a blocked candidate would do is start a
|
|
68
|
+
// browser this host could not drive. It keeps its place on the list
|
|
69
|
+
// carrying that reason as a **note** — what gets reported is what
|
|
70
|
+
// this host could not do with the path, not whether it is there, and
|
|
71
|
+
// reporting it as a failure would read as a broken executable.
|
|
72
|
+
//
|
|
73
|
+
// The seen key folds through the interop mount, because the same
|
|
74
|
+
// executable reaches this list in either spelling: the Windows one
|
|
75
|
+
// the locate answers, and the mount one a saved row or the row config
|
|
76
|
+
// can carry (the only spelling the WSL side can stat). One executable
|
|
77
|
+
// answers once, under the first spelling seen.
|
|
78
|
+
const mounted = windowsPathToMount(path);
|
|
79
|
+
const key = `blocked\u0000${identity(mounted !== "" ? mounted : path)}`;
|
|
80
|
+
if (seen.has(key))
|
|
81
|
+
continue;
|
|
82
|
+
seen.add(key);
|
|
83
|
+
statuses.push({ path, version: "", error: "", note: blocked });
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (!presentOnDisk(path))
|
|
87
|
+
continue;
|
|
88
|
+
try {
|
|
89
|
+
const version = await probeExecutable(path);
|
|
90
|
+
const key = `${identity(path)}\u0000${version}`;
|
|
91
|
+
if (seen.has(key))
|
|
92
|
+
continue;
|
|
93
|
+
seen.add(key);
|
|
94
|
+
statuses.push({ path, version, error: "", note: "" });
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
const code = (error instanceof Error && typeof error.code === "string")
|
|
98
|
+
? error.code
|
|
99
|
+
: "";
|
|
100
|
+
if (code === "ENOENT")
|
|
101
|
+
continue;
|
|
102
|
+
const key = identity(path);
|
|
103
|
+
if (seen.has(key))
|
|
104
|
+
continue;
|
|
105
|
+
seen.add(key);
|
|
106
|
+
statuses.push({
|
|
107
|
+
path,
|
|
108
|
+
version: "",
|
|
109
|
+
error: firstLine(error instanceof Error ? error.message : String(error)),
|
|
110
|
+
note: ""
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return statuses;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Discover usable Google Chrome executables when nothing is fixed: probe every
|
|
118
|
+
* candidate and report the first runnable one. Kept for its `Promise<string>`
|
|
119
|
+
* contract (`src/index.ts` re-export, tests, diagnostics).
|
|
120
|
+
* @param candidatePaths - candidate executable paths (default: platform list).
|
|
121
|
+
* @param blockedForPlatform - answers a reason for a candidate this host must
|
|
122
|
+
* never exec, `""` for one it may probe.
|
|
123
|
+
* @returns the discovered executable version line.
|
|
124
|
+
*/
|
|
125
|
+
export async function discoverChrome(candidatePaths, blockedForPlatform = () => "") {
|
|
126
|
+
const candidates = (Array.isArray(candidatePaths) ? candidatePaths : defaultChromePaths())
|
|
127
|
+
.map((candidate) => String(candidate ?? "").trim())
|
|
128
|
+
.filter((candidate) => candidate !== "");
|
|
129
|
+
if (candidates.length === 0)
|
|
130
|
+
return "";
|
|
131
|
+
const found = await scanChromeExecutables(candidates, blockedForPlatform);
|
|
132
|
+
for (const status of found) {
|
|
133
|
+
if (status.version !== "" && status.error === "")
|
|
134
|
+
return status.version;
|
|
135
|
+
}
|
|
136
|
+
const broken = found.find((status) => status.error !== "");
|
|
137
|
+
if (broken !== void 0)
|
|
138
|
+
throw new Error(broken.error);
|
|
139
|
+
// A note is the other half of "nothing answered": the candidate is there, it
|
|
140
|
+
// is simply not launchable as a local executable from this host (the one
|
|
141
|
+
// case is a Windows executable under WSL), and the note names the run that
|
|
142
|
+
// drives it.
|
|
143
|
+
const noted = found.find((status) => status.note !== "");
|
|
144
|
+
if (noted !== void 0) {
|
|
145
|
+
throw new Error(`Chrome executable not found: no executable detected for this host (checked: ${candidates.join(", ")}); ${noted.note}`);
|
|
146
|
+
}
|
|
147
|
+
throw new Error(`Chrome executable not found: no executable detected (checked: ${candidates.join(", ")})`);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* One check run — the public "did we find a runnable Chrome?" question:
|
|
151
|
+
*
|
|
152
|
+
* - `chromePath` non-empty → probe that executable (ENOENT → "Chrome
|
|
153
|
+
* executable not found: <path>"; non-zero → first stderr/stdout line;
|
|
154
|
+
* success → the version line).
|
|
155
|
+
* - `chromePath` empty → run the scan over the candidate list (row config
|
|
156
|
+
* `chromePaths`, default {@link defaultChromePaths}) and report the first
|
|
157
|
+
* runnable entry. Nothing usable → the known executable-missing error;
|
|
158
|
+
* only-present-but-broken entries → that entry's failure.
|
|
159
|
+
* - the extra flags leave the check mute: they declare a connect mode
|
|
160
|
+
* (`--browserUrl` / `--browser-url` / `-u`, `--wsEndpoint` /
|
|
161
|
+
* `--ws-endpoint` / `-w`, `--autoConnect` / `--auto-connect`), name a
|
|
162
|
+
* config file (`--config`), or fix another `--channel` than the `stable`
|
|
163
|
+
* the candidate list models → resolve "": there is no local executable
|
|
164
|
+
* this check could honestly answer for.
|
|
165
|
+
* - `blockedForPlatform` answers non-empty for what is selected → resolve "" with
|
|
166
|
+
* **no spawn**. A Windows `chrome.exe` on a WSL host is the case: its
|
|
167
|
+
* `--version` probe answers (which is why the selection looks healthy) but
|
|
168
|
+
* answering means attaching to the Windows browser session, and that *starts*
|
|
169
|
+
* a browser instance no tool call could drive
|
|
170
|
+
* ({@link WSL_WINDOWS_LAUNCH_ERROR}).
|
|
171
|
+
*
|
|
172
|
+
* A run that probes **nothing** (no candidates, a connect mode, a config file
|
|
173
|
+
* or another channel standing in for the local executable, or a blocked path)
|
|
174
|
+
* resolves "" — callers must treat that as "no evidence", never as health.
|
|
175
|
+
*
|
|
176
|
+
* @param entry - validated {@link ChromeMcpConfig}.
|
|
177
|
+
* @param extraFlags - the flags list the bridge currently launches with;
|
|
178
|
+
* inspected for the entries that leave the check mute.
|
|
179
|
+
* @param blockedForPlatform - answers a reason for a path this host must never
|
|
180
|
+
* exec, `""` for one it may probe.
|
|
181
|
+
* @returns the executable version line, or "" when nothing is probed.
|
|
182
|
+
*/
|
|
183
|
+
export function checkChrome(entry, extraFlags, blockedForPlatform = () => "") {
|
|
184
|
+
// The two config fields read here are volatile, so what they carry is either a
|
|
185
|
+
// reference or the value a caller handed in explicitly.
|
|
186
|
+
const target = readConfigField(entry.chromePath, "").trim();
|
|
187
|
+
if (target !== "")
|
|
188
|
+
return blockedForPlatform(target) !== "" ? Promise.resolve("") : probeExecutable(target);
|
|
189
|
+
const flags = extraFlags === void 0 ? readConfigField(entry.extraFlags, []) : extraFlags;
|
|
190
|
+
if (flagsSkipProbe(flags)) {
|
|
191
|
+
return Promise.resolve("");
|
|
192
|
+
}
|
|
193
|
+
return discoverChrome(entry.chromePaths, blockedForPlatform);
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/host/discovery/scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate a user-authored extraFlags list: a plain array of flag strings
|
|
3
|
+
* carrying no control characters (argv is execve'd without a shell), and no
|
|
4
|
+
* executable-path flag — the executable is picked in the card's selector, so
|
|
5
|
+
* letting a flag pin one would put a second source of truth over the bridge
|
|
6
|
+
* argv. Throws with the offending entry so the settings layer can surface it.
|
|
7
|
+
* @param value - candidate flags array.
|
|
8
|
+
* @returns true when valid.
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateExtraFlags(value: unknown): true;
|
|
11
|
+
/** True when a flag selects the Chrome executable (upstream flags:
|
|
12
|
+
* `--executablePath` / `--executable-path` / `-e`, with or without `=`).
|
|
13
|
+
* No longer an accepted user flag (see {@link validateExtraFlags}): it stays
|
|
14
|
+
* here for the row-config fold ({@link extractExecutablePathFlag}) and the
|
|
15
|
+
* argv guard. */
|
|
16
|
+
export declare function carriesExecutablePath(flag: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Read the path a legacy `--executablePath` carries in the **row-config** flags
|
|
19
|
+
* list: the `=` spelling and the separated spelling both count, first entry
|
|
20
|
+
* wins, "" when nothing pins a path.
|
|
21
|
+
*
|
|
22
|
+
* The card's picker owns the executable now, so a row-config pin is not
|
|
23
|
+
* honored as a flag: it becomes the row-config source of the selection and gets
|
|
24
|
+
* stripped out of argv (see {@link stripExecutablePathFlags}).
|
|
25
|
+
*/
|
|
26
|
+
export declare function extractExecutablePathFlag(flags: unknown): string;
|
|
27
|
+
/** Drop every entry that pins an executable from a flags list — paired with
|
|
28
|
+
* {@link extractExecutablePathFlag} so a legacy profile keeps its path as a
|
|
29
|
+
* selection source instead of reaching argv as a second source of truth.
|
|
30
|
+
* A `--flag <path>` spelling consumes the following entry; a flag-looking next
|
|
31
|
+
* entry keeps it (nothing was meant as the value). */
|
|
32
|
+
export declare function stripExecutablePathFlags(flags: unknown): string[];
|
|
33
|
+
/**
|
|
34
|
+
* True when one extraFlag declares a connect mode (the bridge will not launch a
|
|
35
|
+
* local executable). Upstream spellings (docs/configuration.md): the two URL
|
|
36
|
+
* options — `--browserUrl`/`--browser-url`/`-u` and
|
|
37
|
+
* `--wsEndpoint`/`--ws-endpoint`/`-w` — plus `--autoConnect`/`--auto-connect`,
|
|
38
|
+
* which attaches to an already-running Chrome (Chrome 144+) instead of starting
|
|
39
|
+
* one. Each form counts with its value inline (`=`), carried as the following
|
|
40
|
+
* entry (the whitespace-split env source's spelling), or bare.
|
|
41
|
+
*/
|
|
42
|
+
export declare function carriesConnectionMode(flag: string): boolean;
|
|
43
|
+
/** True when one extraFlag names a config file. */
|
|
44
|
+
export declare function carriesConfigFile(flag: unknown): boolean;
|
|
45
|
+
/** True when one extraFlag fixes the update channel to something other than
|
|
46
|
+
* `stable` (the default the candidate list models). `next` is the entry that
|
|
47
|
+
* follows a bare `--channel`; a value equal to the default is not a skip. */
|
|
48
|
+
export declare function carriesOtherChannel(flag: unknown, next?: unknown): boolean;
|
|
49
|
+
/** True when an executable probe could not answer here, whatever the host
|
|
50
|
+
* carries: the bridge connects instead of launching (connect mode), the
|
|
51
|
+
* executable it runs came from a config file, or the channel it looks in is
|
|
52
|
+
* not the `stable` one the candidate list models. A check that ran **no**
|
|
53
|
+
* probe answers `""` — *no evidence*, never health: it must not clear
|
|
54
|
+
* `lastError` nor the known `chromeMissing` state. */
|
|
55
|
+
export declare function flagsSkipProbe(flags: unknown): boolean;
|
|
56
|
+
/** True when any entry of a flags list declares connect mode — the connect
|
|
57
|
+
* half that answers the live `carriesConnectionMode` mirror, keys the pill
|
|
58
|
+
* relabel on, and drops `--executablePath` from the argv. For what spares the
|
|
59
|
+
* *executable check* there is the wider {@link flagsSkipProbe}: a config file
|
|
60
|
+
* and a non-`stable` channel also leave the probe mute, while the bridge still
|
|
61
|
+
* launches a local executable. */
|
|
62
|
+
export declare function flagsSkipCheck(flags: unknown): boolean;
|
|
63
|
+
/** True when two flags lists are element-wise equal (flags are arrays). */
|
|
64
|
+
export declare function sameFlags(a: unknown, b: unknown): boolean;
|
|
65
|
+
//# sourceMappingURL=flags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../../src/host/flags.ts"],"names":[],"mappings":"AAsBA;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAkBvD;AAED;;;;iBAIiB;AACjB,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAWhE;AAED;;;;sDAIsD;AACtD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAejE;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAQD,mDAAmD;AACnD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAExD;AAQD;;6EAE6E;AAC7E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAa1E;AAED;;;;;sDAKsD;AACtD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAStD;AAED;;;;;kCAKkC;AAClC,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEtD;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAGzD"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extra-flags helpers shared by the bridge argv builder, the executable scan
|
|
3
|
+
* and the settings validation hook.
|
|
4
|
+
*
|
|
5
|
+
* Flags are execve'd as argv entries — never through a shell — so validation
|
|
6
|
+
* rejects control characters only, and the executable pin / connect-mode
|
|
7
|
+
* options are matched against their upstream spellings (`--executablePath`,
|
|
8
|
+
* `--executable-path`, `-e`; the connect group `--browserUrl`/`--browser-url`/
|
|
9
|
+
* `-u`, `--wsEndpoint`/`--ws-endpoint`/`-w`, `--autoConnect`/`--auto-connect`;
|
|
10
|
+
* plus the probe-skipping `--config` and `--channel`).
|
|
11
|
+
*
|
|
12
|
+
* One rule has since hardened: pinning the executable by flag is a second
|
|
13
|
+
* source of truth for the same lever the executable picker owns, so a
|
|
14
|
+
* user-authored list may not carry it (`validateExtraFlags` rejects it), and
|
|
15
|
+
* the row config's copy gets folded into `chromePath` instead of reaching argv
|
|
16
|
+
* as a second opinion.
|
|
17
|
+
*/
|
|
18
|
+
import { CONTROL_PATTERN } from "./constants.js";
|
|
19
|
+
/** One executable-path flag, upstream spellings, with or without `=`. */
|
|
20
|
+
const EXECUTABLE_PATH_FLAG = /^(?:--executablePath|--executable-path|-e)(?:=|(?=\s)|$)/iu;
|
|
21
|
+
/**
|
|
22
|
+
* Validate a user-authored extraFlags list: a plain array of flag strings
|
|
23
|
+
* carrying no control characters (argv is execve'd without a shell), and no
|
|
24
|
+
* executable-path flag — the executable is picked in the card's selector, so
|
|
25
|
+
* letting a flag pin one would put a second source of truth over the bridge
|
|
26
|
+
* argv. Throws with the offending entry so the settings layer can surface it.
|
|
27
|
+
* @param value - candidate flags array.
|
|
28
|
+
* @returns true when valid.
|
|
29
|
+
*/
|
|
30
|
+
export function validateExtraFlags(value) {
|
|
31
|
+
if (!Array.isArray(value)) {
|
|
32
|
+
throw new Error("extraFlags must be an array of strings");
|
|
33
|
+
}
|
|
34
|
+
for (const flag of value) {
|
|
35
|
+
if (typeof flag !== "string" || flag === "") {
|
|
36
|
+
throw new Error("extraFlags entries must be non-empty strings");
|
|
37
|
+
}
|
|
38
|
+
if (CONTROL_PATTERN.test(flag)) {
|
|
39
|
+
throw new Error(`extraFlags entry "${flag}" contains control characters`);
|
|
40
|
+
}
|
|
41
|
+
if (carriesExecutablePath(flag)) {
|
|
42
|
+
throw new Error(`extraFlags entry "${flag}" selects the Chrome executable — pick it in the Chrome executable picker instead`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
/** True when a flag selects the Chrome executable (upstream flags:
|
|
48
|
+
* `--executablePath` / `--executable-path` / `-e`, with or without `=`).
|
|
49
|
+
* No longer an accepted user flag (see {@link validateExtraFlags}): it stays
|
|
50
|
+
* here for the row-config fold ({@link extractExecutablePathFlag}) and the
|
|
51
|
+
* argv guard. */
|
|
52
|
+
export function carriesExecutablePath(flag) {
|
|
53
|
+
return typeof flag === "string" && EXECUTABLE_PATH_FLAG.test(flag);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Read the path a legacy `--executablePath` carries in the **row-config** flags
|
|
57
|
+
* list: the `=` spelling and the separated spelling both count, first entry
|
|
58
|
+
* wins, "" when nothing pins a path.
|
|
59
|
+
*
|
|
60
|
+
* The card's picker owns the executable now, so a row-config pin is not
|
|
61
|
+
* honored as a flag: it becomes the row-config source of the selection and gets
|
|
62
|
+
* stripped out of argv (see {@link stripExecutablePathFlags}).
|
|
63
|
+
*/
|
|
64
|
+
export function extractExecutablePathFlag(flags) {
|
|
65
|
+
if (!Array.isArray(flags))
|
|
66
|
+
return "";
|
|
67
|
+
for (let index = 0; index < flags.length; index++) {
|
|
68
|
+
const flag = flags[index];
|
|
69
|
+
if (typeof flag !== "string" || !carriesExecutablePath(flag))
|
|
70
|
+
continue;
|
|
71
|
+
const eq = flag.indexOf("=");
|
|
72
|
+
if (eq !== -1)
|
|
73
|
+
return flag.slice(eq + 1).trim();
|
|
74
|
+
const next = flags[index + 1];
|
|
75
|
+
return typeof next === "string" && next.trim() !== "" ? next.trim() : "";
|
|
76
|
+
}
|
|
77
|
+
return "";
|
|
78
|
+
}
|
|
79
|
+
/** Drop every entry that pins an executable from a flags list — paired with
|
|
80
|
+
* {@link extractExecutablePathFlag} so a legacy profile keeps its path as a
|
|
81
|
+
* selection source instead of reaching argv as a second source of truth.
|
|
82
|
+
* A `--flag <path>` spelling consumes the following entry; a flag-looking next
|
|
83
|
+
* entry keeps it (nothing was meant as the value). */
|
|
84
|
+
export function stripExecutablePathFlags(flags) {
|
|
85
|
+
if (!Array.isArray(flags))
|
|
86
|
+
return [];
|
|
87
|
+
const stripped = [];
|
|
88
|
+
let awaitingValue = false;
|
|
89
|
+
for (const flag of flags) {
|
|
90
|
+
if (typeof flag !== "string")
|
|
91
|
+
continue;
|
|
92
|
+
if (carriesExecutablePath(flag)) {
|
|
93
|
+
awaitingValue = !flag.includes("=");
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (awaitingValue && !flag.startsWith("-"))
|
|
97
|
+
continue;
|
|
98
|
+
awaitingValue = false;
|
|
99
|
+
stripped.push(flag);
|
|
100
|
+
}
|
|
101
|
+
return stripped;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* True when one extraFlag declares a connect mode (the bridge will not launch a
|
|
105
|
+
* local executable). Upstream spellings (docs/configuration.md): the two URL
|
|
106
|
+
* options — `--browserUrl`/`--browser-url`/`-u` and
|
|
107
|
+
* `--wsEndpoint`/`--ws-endpoint`/`-w` — plus `--autoConnect`/`--auto-connect`,
|
|
108
|
+
* which attaches to an already-running Chrome (Chrome 144+) instead of starting
|
|
109
|
+
* one. Each form counts with its value inline (`=`), carried as the following
|
|
110
|
+
* entry (the whitespace-split env source's spelling), or bare.
|
|
111
|
+
*/
|
|
112
|
+
export function carriesConnectionMode(flag) {
|
|
113
|
+
return /^(?:--(?:auto[-]?connect|browser[-]?url|ws[-]?endpoint)(?:=|(?=\s)|$)|-[uw]\b)/iu.test(flag);
|
|
114
|
+
}
|
|
115
|
+
/** One config-file flag, `--config <file>` (also matched for the
|
|
116
|
+
* `--config-path` spelling). A JSON config can fix the executable and the
|
|
117
|
+
* connect mode itself, so the bridge argv no longer states locally what will
|
|
118
|
+
* run — the check would only guess. */
|
|
119
|
+
const CONFIG_FILE_FLAG = /^--config(?:-path)?(?:=|(?=\s)|$)/iu;
|
|
120
|
+
/** True when one extraFlag names a config file. */
|
|
121
|
+
export function carriesConfigFile(flag) {
|
|
122
|
+
return typeof flag === "string" && CONFIG_FILE_FLAG.test(flag);
|
|
123
|
+
}
|
|
124
|
+
/** One `--channel` flag. Its value picks where upstream looks for a browser
|
|
125
|
+
* (`canary`/`dev`/`beta`/`stable`); the check's own candidate list models only
|
|
126
|
+
* `stable`, so any other value makes it answer "not found" about a browser
|
|
127
|
+
* living in another channel. */
|
|
128
|
+
const CHANNEL_FLAG = /^--channel(?:=|(?=\s)|$)/iu;
|
|
129
|
+
/** True when one extraFlag fixes the update channel to something other than
|
|
130
|
+
* `stable` (the default the candidate list models). `next` is the entry that
|
|
131
|
+
* follows a bare `--channel`; a value equal to the default is not a skip. */
|
|
132
|
+
export function carriesOtherChannel(flag, next) {
|
|
133
|
+
if (typeof flag !== "string" || !CHANNEL_FLAG.test(flag))
|
|
134
|
+
return false;
|
|
135
|
+
const eq = flag.indexOf("=");
|
|
136
|
+
let value;
|
|
137
|
+
if (eq !== -1) {
|
|
138
|
+
value = flag.slice(eq + 1).trim();
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
const whitespace = /\s/u.exec(flag);
|
|
142
|
+
if (whitespace !== null)
|
|
143
|
+
value = flag.slice(whitespace.index + 1).trim();
|
|
144
|
+
else if (typeof next === "string" && !next.startsWith("-"))
|
|
145
|
+
value = next.trim();
|
|
146
|
+
else
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
return value !== "" && value.toLowerCase() !== "stable";
|
|
150
|
+
}
|
|
151
|
+
/** True when an executable probe could not answer here, whatever the host
|
|
152
|
+
* carries: the bridge connects instead of launching (connect mode), the
|
|
153
|
+
* executable it runs came from a config file, or the channel it looks in is
|
|
154
|
+
* not the `stable` one the candidate list models. A check that ran **no**
|
|
155
|
+
* probe answers `""` — *no evidence*, never health: it must not clear
|
|
156
|
+
* `lastError` nor the known `chromeMissing` state. */
|
|
157
|
+
export function flagsSkipProbe(flags) {
|
|
158
|
+
if (!Array.isArray(flags))
|
|
159
|
+
return false;
|
|
160
|
+
for (let index = 0; index < flags.length; index += 1) {
|
|
161
|
+
const flag = flags[index];
|
|
162
|
+
if (typeof flag !== "string")
|
|
163
|
+
continue;
|
|
164
|
+
if (carriesConnectionMode(flag) || carriesConfigFile(flag))
|
|
165
|
+
return true;
|
|
166
|
+
if (CHANNEL_FLAG.test(flag) && carriesOtherChannel(flag, flags[index + 1]))
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
/** True when any entry of a flags list declares connect mode — the connect
|
|
172
|
+
* half that answers the live `carriesConnectionMode` mirror, keys the pill
|
|
173
|
+
* relabel on, and drops `--executablePath` from the argv. For what spares the
|
|
174
|
+
* *executable check* there is the wider {@link flagsSkipProbe}: a config file
|
|
175
|
+
* and a non-`stable` channel also leave the probe mute, while the bridge still
|
|
176
|
+
* launches a local executable. */
|
|
177
|
+
export function flagsSkipCheck(flags) {
|
|
178
|
+
return Array.isArray(flags) && flags.some((flag) => typeof flag === "string" && carriesConnectionMode(flag));
|
|
179
|
+
}
|
|
180
|
+
/** True when two flags lists are element-wise equal (flags are arrays). */
|
|
181
|
+
export function sameFlags(a, b) {
|
|
182
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)
|
|
183
|
+
return false;
|
|
184
|
+
return a.every((flag, index) => flag === b[index]);
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=flags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flags.js","sourceRoot":"","sources":["../../src/host/flags.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { KindOption, McpKind, ServerEntry } from "@comecaramelos/dsh-mcp-manager/api";
|
|
2
|
+
import type { Controller } from "./controller/index.js";
|
|
3
|
+
/** Split one `lines` field's value into its flags. Missing/blank answers nothing
|
|
4
|
+
* — the entry carries no own answer, so the caller falls through to the row. */
|
|
5
|
+
export declare function parseFlagLines(value: unknown): string[] | undefined;
|
|
6
|
+
/** Join one flags list back into a `lines` field value (round-trips with
|
|
7
|
+
* {@link parseFlagLines}). */
|
|
8
|
+
export declare function joinFlagLines(flags: readonly string[]): string;
|
|
9
|
+
/**
|
|
10
|
+
* What the executable field offers: the saved rows first, then every path the
|
|
11
|
+
* last scan reported, then the Windows-side executables a WSL host carries, then
|
|
12
|
+
* the path a live connection actually launches with — the running path is the
|
|
13
|
+
* answer the Host knows best, and it may not be a saved row yet. A stored pick
|
|
14
|
+
* the choices stop carrying stays offered by the card itself, so it never
|
|
15
|
+
* silently becomes another one.
|
|
16
|
+
*/
|
|
17
|
+
export declare function executableChoices(controller: Controller): readonly KindOption[];
|
|
18
|
+
/** The executable one entry launches with: its own pick, else what the row's
|
|
19
|
+
* layers resolve (the user layer, then the row config with a legacy
|
|
20
|
+
* `--executablePath` folded in) — never a scan answer and never a re-resolve. */
|
|
21
|
+
export declare function entryExecutable(entry: ServerEntry, controller: Controller): string;
|
|
22
|
+
/** The flags one entry launches with: its own `lines` field, else the row's
|
|
23
|
+
* resolved precedence (user layer > `DSH_CHROME_MCP_FLAGS` > row config > the
|
|
24
|
+
* schema default). */
|
|
25
|
+
export declare function entryExtraFlags(entry: ServerEntry, controller: Controller): string[];
|
|
26
|
+
/** The console-output mode one entry runs with: its own pick, else the row's
|
|
27
|
+
* answer. Never a third state. The field is a toggle (`"true"` = reduce = log
|
|
28
|
+
* file); the `log`/`console` it stored while it was a choice still read. */
|
|
29
|
+
export declare function entryStderrMode(entry: ServerEntry, controller: Controller): "log" | "console";
|
|
30
|
+
/** The `chrome` kind: the local `chrome-devtools-mcp` bridge — what the row used
|
|
31
|
+
* to start for itself, now as one of the manager's connections. */
|
|
32
|
+
export declare function createChromeKind(controller: Controller): McpKind;
|
|
33
|
+
/** The `chrome-windows` kind: the Windows browser driven through the WSL interop
|
|
34
|
+
* mount. `resolve` runs the prelaunch itself — locate, prereq, free port,
|
|
35
|
+
* launch, wait for the bind — and answers the local `chrome-devtools-mcp` in
|
|
36
|
+
* connect mode against that port. The port speaks no MCP; the MCP stays the
|
|
37
|
+
* local process. Off WSL the entry is refused, with the answer the card shows. */
|
|
38
|
+
export declare function createChromeWindowsKind(controller: Controller): McpKind;
|
|
39
|
+
/** The kinds this host can answer, in registration order — `chrome` first,
|
|
40
|
+
* because it is the answer a standalone config translates into by default
|
|
41
|
+
* (./migration.ts). `chrome-windows` is offered on WSL only: anywhere else its
|
|
42
|
+
* `resolve` could only refuse, so the picker never lists it there (a native
|
|
43
|
+
* Windows host drives its own Chrome through `chrome`). */
|
|
44
|
+
export declare function createChromeKinds(controller: Controller): McpKind[];
|
|
45
|
+
//# sourceMappingURL=kind.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kind.d.ts","sourceRoot":"","sources":["../../src/host/kind.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAsB,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAC/G,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD;gFACgF;AAChF,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAInE;AAED;8BAC8B;AAC9B,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAE9D;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,UAAU,EAAE,CAe/E;AAED;;iFAEiF;AACjF,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,CAIlF;AAED;;sBAEsB;AACtB,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,EAAE,CAIpF;AAED;;4EAE4E;AAC5E,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,GAAG,KAAK,GAAG,SAAS,CAM7F;AAwCD;mEACmE;AACnE,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAgDhE;AAED;;;;kFAIkF;AAClF,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CA8CvE;AAED;;;;2DAI2D;AAC3D,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,EAAE,CAEnE"}
|