@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.
Files changed (214) hide show
  1. package/README.md +44 -95
  2. package/assets/dsh-chrome-mcp-social.png +0 -0
  3. package/assets/icon.svg +71 -0
  4. package/assets/prelaunch-windows-chrome.html +277 -0
  5. package/lib/client.js +3005 -568
  6. package/lib/client.js.map +7 -0
  7. package/lib/host/apply.d.ts +40 -0
  8. package/lib/host/apply.d.ts.map +1 -0
  9. package/lib/host/apply.js +57 -0
  10. package/lib/host/apply.js.map +1 -0
  11. package/lib/host/bridge.d.ts +74 -0
  12. package/lib/host/bridge.d.ts.map +1 -0
  13. package/lib/host/bridge.js +168 -0
  14. package/lib/host/bridge.js.map +1 -0
  15. package/lib/host/catalog.d.ts +31 -0
  16. package/lib/host/catalog.d.ts.map +1 -0
  17. package/lib/host/catalog.js +92 -0
  18. package/lib/host/catalog.js.map +1 -0
  19. package/lib/host/commands/chrome-path.d.ts +4 -0
  20. package/lib/host/commands/chrome-path.d.ts.map +1 -0
  21. package/lib/host/commands/chrome-path.js +65 -0
  22. package/lib/host/commands/chrome-path.js.map +1 -0
  23. package/lib/host/commands/chrome-refresh.d.ts +17 -0
  24. package/lib/host/commands/chrome-refresh.d.ts.map +1 -0
  25. package/lib/host/commands/chrome-refresh.js +37 -0
  26. package/lib/host/commands/chrome-refresh.js.map +1 -0
  27. package/lib/host/commands/index.d.ts +26 -0
  28. package/lib/host/commands/index.d.ts.map +1 -0
  29. package/lib/host/commands/index.js +41 -0
  30. package/lib/host/commands/index.js.map +1 -0
  31. package/lib/host/constants.d.ts +306 -0
  32. package/lib/host/constants.d.ts.map +1 -0
  33. package/lib/host/constants.js +319 -0
  34. package/lib/host/constants.js.map +1 -0
  35. package/lib/host/controller/_trace.d.ts +3 -0
  36. package/lib/host/controller/_trace.d.ts.map +1 -0
  37. package/lib/host/controller/_trace.js +14 -0
  38. package/lib/host/controller/_trace.js.map +1 -0
  39. package/lib/host/controller/bridge-run.d.ts +40 -0
  40. package/lib/host/controller/bridge-run.d.ts.map +1 -0
  41. package/lib/host/controller/bridge-run.js +85 -0
  42. package/lib/host/controller/bridge-run.js.map +1 -0
  43. package/lib/host/controller/captures.d.ts +15 -0
  44. package/lib/host/controller/captures.d.ts.map +1 -0
  45. package/lib/host/controller/captures.js +85 -0
  46. package/lib/host/controller/captures.js.map +1 -0
  47. package/lib/host/controller/commits.d.ts +4 -0
  48. package/lib/host/controller/commits.d.ts.map +1 -0
  49. package/lib/host/controller/commits.js +131 -0
  50. package/lib/host/controller/commits.js.map +1 -0
  51. package/lib/host/controller/connections.d.ts +38 -0
  52. package/lib/host/controller/connections.d.ts.map +1 -0
  53. package/lib/host/controller/connections.js +71 -0
  54. package/lib/host/controller/connections.js.map +1 -0
  55. package/lib/host/controller/controller.d.ts +35 -0
  56. package/lib/host/controller/controller.d.ts.map +1 -0
  57. package/lib/host/controller/controller.js +234 -0
  58. package/lib/host/controller/controller.js.map +1 -0
  59. package/lib/host/controller/index.d.ts +30 -0
  60. package/lib/host/controller/index.d.ts.map +1 -0
  61. package/lib/host/controller/index.js +27 -0
  62. package/lib/host/controller/index.js.map +1 -0
  63. package/lib/host/controller/notes.d.ts +26 -0
  64. package/lib/host/controller/notes.d.ts.map +1 -0
  65. package/lib/host/controller/notes.js +44 -0
  66. package/lib/host/controller/notes.js.map +1 -0
  67. package/lib/host/controller/persist.d.ts +16 -0
  68. package/lib/host/controller/persist.d.ts.map +1 -0
  69. package/lib/host/controller/persist.js +98 -0
  70. package/lib/host/controller/persist.js.map +1 -0
  71. package/lib/host/controller/publish.d.ts +4 -0
  72. package/lib/host/controller/publish.d.ts.map +1 -0
  73. package/lib/host/controller/publish.js +56 -0
  74. package/lib/host/controller/publish.js.map +1 -0
  75. package/lib/host/controller/runs.d.ts +80 -0
  76. package/lib/host/controller/runs.d.ts.map +1 -0
  77. package/lib/host/controller/runs.js +394 -0
  78. package/lib/host/controller/runs.js.map +1 -0
  79. package/lib/host/controller/state.d.ts +172 -0
  80. package/lib/host/controller/state.d.ts.map +1 -0
  81. package/lib/host/controller/state.js +2 -0
  82. package/lib/host/controller/state.js.map +1 -0
  83. package/lib/host/controller/windows-run.d.ts +17 -0
  84. package/lib/host/controller/windows-run.d.ts.map +1 -0
  85. package/lib/host/controller/windows-run.js +109 -0
  86. package/lib/host/controller/windows-run.js.map +1 -0
  87. package/lib/host/discovery/candidates.d.ts +47 -0
  88. package/lib/host/discovery/candidates.d.ts.map +1 -0
  89. package/lib/host/discovery/candidates.js +68 -0
  90. package/lib/host/discovery/candidates.js.map +1 -0
  91. package/lib/host/discovery/index.d.ts +19 -0
  92. package/lib/host/discovery/index.d.ts.map +1 -0
  93. package/lib/host/discovery/index.js +19 -0
  94. package/lib/host/discovery/index.js.map +1 -0
  95. package/lib/host/discovery/probe.d.ts +29 -0
  96. package/lib/host/discovery/probe.d.ts.map +1 -0
  97. package/lib/host/discovery/probe.js +155 -0
  98. package/lib/host/discovery/probe.js.map +1 -0
  99. package/lib/host/discovery/scan.d.ts +72 -0
  100. package/lib/host/discovery/scan.d.ts.map +1 -0
  101. package/lib/host/discovery/scan.js +195 -0
  102. package/lib/host/discovery/scan.js.map +1 -0
  103. package/lib/host/flags.d.ts +65 -0
  104. package/lib/host/flags.d.ts.map +1 -0
  105. package/lib/host/flags.js +186 -0
  106. package/lib/host/flags.js.map +1 -0
  107. package/lib/host/kind.d.ts +45 -0
  108. package/lib/host/kind.d.ts.map +1 -0
  109. package/lib/host/kind.js +251 -0
  110. package/lib/host/kind.js.map +1 -0
  111. package/lib/host/manager.d.ts +21 -0
  112. package/lib/host/manager.d.ts.map +1 -0
  113. package/lib/host/manager.js +113 -0
  114. package/lib/host/manager.js.map +1 -0
  115. package/lib/host/migration.d.ts +26 -0
  116. package/lib/host/migration.d.ts.map +1 -0
  117. package/lib/host/migration.js +127 -0
  118. package/lib/host/migration.js.map +1 -0
  119. package/lib/host/platform.d.ts +38 -0
  120. package/lib/host/platform.d.ts.map +1 -0
  121. package/lib/host/platform.js +64 -0
  122. package/lib/host/platform.js.map +1 -0
  123. package/lib/host/plugin-meta.d.ts +21 -0
  124. package/lib/host/plugin-meta.d.ts.map +1 -0
  125. package/lib/host/plugin-meta.js +21 -0
  126. package/lib/host/plugin-meta.js.map +1 -0
  127. package/lib/host/schema.d.ts +361 -0
  128. package/lib/host/schema.d.ts.map +1 -0
  129. package/lib/host/schema.js +196 -0
  130. package/lib/host/schema.js.map +1 -0
  131. package/lib/host/settings.d.ts +28 -0
  132. package/lib/host/settings.d.ts.map +1 -0
  133. package/lib/host/settings.js +91 -0
  134. package/lib/host/settings.js.map +1 -0
  135. package/lib/host/status.d.ts +25 -0
  136. package/lib/host/status.d.ts.map +1 -0
  137. package/lib/host/status.js +45 -0
  138. package/lib/host/status.js.map +1 -0
  139. package/lib/host/tool.d.ts +65 -0
  140. package/lib/host/tool.d.ts.map +1 -0
  141. package/lib/host/tool.js +52 -0
  142. package/lib/host/tool.js.map +1 -0
  143. package/lib/host/types/config.d.ts +101 -0
  144. package/lib/host/types/config.d.ts.map +1 -0
  145. package/lib/host/types/config.js +2 -0
  146. package/lib/host/types/config.js.map +1 -0
  147. package/lib/host/types/executable.d.ts +35 -0
  148. package/lib/host/types/executable.d.ts.map +1 -0
  149. package/lib/host/types/executable.js +9 -0
  150. package/lib/host/types/executable.js.map +1 -0
  151. package/lib/host/types/index.d.ts +24 -0
  152. package/lib/host/types/index.d.ts.map +1 -0
  153. package/lib/host/types/index.js +2 -0
  154. package/lib/host/types/index.js.map +1 -0
  155. package/lib/host/types/plugin.d.ts +38 -0
  156. package/lib/host/types/plugin.d.ts.map +1 -0
  157. package/lib/host/types/plugin.js +10 -0
  158. package/lib/host/types/plugin.js.map +1 -0
  159. package/lib/host/types/services.d.ts +26 -0
  160. package/lib/host/types/services.d.ts.map +1 -0
  161. package/lib/host/types/services.js +9 -0
  162. package/lib/host/types/services.js.map +1 -0
  163. package/lib/host/types/settings.d.ts +180 -0
  164. package/lib/host/types/settings.d.ts.map +1 -0
  165. package/lib/host/types/settings.js +2 -0
  166. package/lib/host/types/settings.js.map +1 -0
  167. package/lib/host/types/stderr.d.ts +51 -0
  168. package/lib/host/types/stderr.d.ts.map +1 -0
  169. package/lib/host/types/stderr.js +9 -0
  170. package/lib/host/types/stderr.js.map +1 -0
  171. package/lib/host/types/windows.d.ts +39 -0
  172. package/lib/host/types/windows.d.ts.map +1 -0
  173. package/lib/host/types/windows.js +9 -0
  174. package/lib/host/types/windows.js.map +1 -0
  175. package/lib/host/values.d.ts +204 -0
  176. package/lib/host/values.d.ts.map +1 -0
  177. package/lib/host/values.js +404 -0
  178. package/lib/host/values.js.map +1 -0
  179. package/lib/host/windows/connect-flags.d.ts +27 -0
  180. package/lib/host/windows/connect-flags.d.ts.map +1 -0
  181. package/lib/host/windows/connect-flags.js +97 -0
  182. package/lib/host/windows/connect-flags.js.map +1 -0
  183. package/lib/host/windows/index.d.ts +31 -0
  184. package/lib/host/windows/index.d.ts.map +1 -0
  185. package/lib/host/windows/index.js +30 -0
  186. package/lib/host/windows/index.js.map +1 -0
  187. package/lib/host/windows/landing.d.ts +47 -0
  188. package/lib/host/windows/landing.d.ts.map +1 -0
  189. package/lib/host/windows/landing.js +174 -0
  190. package/lib/host/windows/landing.js.map +1 -0
  191. package/lib/host/windows/link.d.ts +11 -0
  192. package/lib/host/windows/link.d.ts.map +1 -0
  193. package/lib/host/windows/link.js +52 -0
  194. package/lib/host/windows/link.js.map +1 -0
  195. package/lib/host/windows/paths.d.ts +64 -0
  196. package/lib/host/windows/paths.d.ts.map +1 -0
  197. package/lib/host/windows/paths.js +148 -0
  198. package/lib/host/windows/paths.js.map +1 -0
  199. package/lib/host/windows/run.d.ts +74 -0
  200. package/lib/host/windows/run.d.ts.map +1 -0
  201. package/lib/host/windows/run.js +211 -0
  202. package/lib/host/windows/run.js.map +1 -0
  203. package/lib/host/windows/spawn.d.ts +22 -0
  204. package/lib/host/windows/spawn.d.ts.map +1 -0
  205. package/lib/host/windows/spawn.js +73 -0
  206. package/lib/host/windows/spawn.js.map +1 -0
  207. package/lib/index.d.ts +102 -0
  208. package/lib/index.d.ts.map +1 -0
  209. package/lib/index.js +102 -636
  210. package/lib/index.js.map +1 -0
  211. package/locale/en.json +6 -0
  212. package/locale/zh.json +6 -0
  213. package/package.json +57 -14
  214. package/cordis.patch.yml +0 -5
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Windows Chrome run — path mapping, locate, and profile/profile-root helpers.
3
+ *
4
+ * The pure half of the run: the drive-letter spelling mapped onto the WSL
5
+ * interop mount, the located executable, the Windows-native profile directory
6
+ * (never one rooted in the WSL checkout — 9P cannot carry Chrome's SQLite/
7
+ * singleton locks), the LOCALAPPDATA root the profile hangs under, and the
8
+ * project directory that roots the workspace `.chrome` view. Every one is
9
+ * injectable or takes its own answer so a test never depends on the machine it
10
+ * runs on. The orchestrator lives in ./run.ts; the workspace-view link in
11
+ * ./link.ts; the raw net/spawn seams in ./spawn.ts; the connect address and
12
+ * connect-mode flag in ./connect-flags.ts.
13
+ */
14
+ import { execFileSync } from "node:child_process";
15
+ import { existsSync } from "node:fs";
16
+ import { WINDOWS_CHROME_CANDIDATES, WINDOWS_CHROME_PROFILE_DIRNAME } from "../constants.js";
17
+ /**
18
+ * The Windows spelling mapped onto the interop mount (`C:\Program Files\…` →
19
+ * `/mnt/c/Program Files/…`), which is the form WSL can stat. A path already
20
+ * spelled as the mount maps to itself — the mount spelling is what the WSL side
21
+ * can stat and therefore what a saved row or the row config may carry — and a
22
+ * path that is neither maps nowhere and yields "".
23
+ *
24
+ * A path may have been written or copied shell-style, where a space is escaped
25
+ * (`Program\ Files`). Such a backslash escapes the space that follows it and is
26
+ * not a separator, so it folds away to the plain space first; every other
27
+ * backslash is a Windows separator and folds to a slash. Turning one space
28
+ * escape blindly into a slash produced `Program/ Files` — a path that exists
29
+ * nowhere and answers `not-found` for a Chrome the run had actually located
30
+ * (measured live 2026-10-12 against a saved mount-spelled selection).
31
+ */
32
+ export function windowsPathToMount(path) {
33
+ if (typeof path !== "string")
34
+ return "";
35
+ const candidate = path.trim().replace(/\\ /gu, " ").replace(/\\/gu, "/");
36
+ const windows = candidate.match(/^([a-z]):\/(.*)$/iu);
37
+ if (windows !== null)
38
+ return `/mnt/${windows[1].toLowerCase()}/${windows[2]}`;
39
+ const mounted = candidate.match(/^\/mnt\/([a-z])\/(.*)$/iu);
40
+ if (mounted === null)
41
+ return "";
42
+ return `/mnt/${mounted[1].toLowerCase()}/${mounted[2]}`;
43
+ }
44
+ /**
45
+ * Locate the Windows-side Chrome through the interop mount: the first candidate
46
+ * whose mount path exists, "" when this machine carries none of them. The
47
+ * returned path keeps its **Windows** spelling — it is what the `start`
48
+ * invocation takes and what the card names.
49
+ */
50
+ export function findWindowsChromeExecutable(exists = (path) => existsSync(path), candidates = WINDOWS_CHROME_CANDIDATES) {
51
+ return findWindowsChromeExecutables(exists, candidates)[0] ?? "";
52
+ }
53
+ /**
54
+ * Every Windows-side executable this host carries, in the list's own preference
55
+ * order and in its **Windows** spelling — the whole located set, not only the
56
+ * first. This is what the executable run folds into its candidate list, so the
57
+ * picker offers the Windows browser instead of hiding it. A machine that carries
58
+ * none of them answers nothing, so the list is what is installed here, never a
59
+ * fixed set of install locations. Nothing on the list is ever spawned from WSL
60
+ * (see `blockedForPlatform`); it is offered so that the **Prelaunch Windows
61
+ * Chrome** run can be pointed at the one the picker selected.
62
+ */
63
+ export function findWindowsChromeExecutables(exists = (path) => existsSync(path), candidates = WINDOWS_CHROME_CANDIDATES) {
64
+ const found = [];
65
+ for (const candidate of Array.isArray(candidates) ? candidates : []) {
66
+ const path = typeof candidate === "string" ? candidate.trim() : "";
67
+ if (path === "" || found.includes(path))
68
+ continue;
69
+ if (exists(windowsPathToMount(path)))
70
+ found.push(path);
71
+ }
72
+ return found;
73
+ }
74
+ /** Cached answer of the Windows-side profile root (`windowsChromeLocalAppData`). */
75
+ let cachedLocalAppData;
76
+ /**
77
+ * The Windows-side profile directory: `<localAppData>\<dir>\.chrome[-<port>]`.
78
+ * The profile has to live on the Windows filesystem — Chrome takes real locks
79
+ * for its SQLite tables and its singleton socket, and the WSL-side directories
80
+ * Windows sees through the interop mount (9P) cannot carry them: a profile
81
+ * rooted there creates every table as a zero-byte file, never answers the
82
+ * singleton lock, and shows "an error occurred while opening your profile" on
83
+ * every launch (measured live 2026-10-04 against Chrome 154). "" answers when
84
+ * LOCALAPPDATA is not there.
85
+ */
86
+ export function windowsChromeProfileDir(localAppData, leaf = ".chrome") {
87
+ const root = typeof localAppData === "string" ? localAppData.trim().replace(/[\\/]+$/u, "") : "";
88
+ if (root === "")
89
+ return "";
90
+ const profile = String(leaf ?? "").replace(/[\\/]+/gu, "");
91
+ if (profile === "")
92
+ return "";
93
+ return `${root}\\${WINDOWS_CHROME_PROFILE_DIRNAME}\\${profile}`;
94
+ }
95
+ /**
96
+ * Resolves `%LOCALAPPDATA%` on the Windows side through the Known Folder API
97
+ * (never the inherited environment — the interop hand-off drops it, so
98
+ * `echo %LOCALAPPDATA%` comes back empty), cached across the process:
99
+ * powershell answers it exactly once per host.
100
+ */
101
+ export function windowsChromeLocalAppData() {
102
+ if (typeof cachedLocalAppData === "string")
103
+ return cachedLocalAppData;
104
+ try {
105
+ const out = execFileSync("/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", "[Environment]::GetFolderPath('LocalApplicationData')"], { encoding: "utf8", timeout: 5000 });
106
+ const value = String(out).trim();
107
+ cachedLocalAppData = value;
108
+ return value;
109
+ }
110
+ catch {
111
+ cachedLocalAppData = "";
112
+ return "";
113
+ }
114
+ }
115
+ /**
116
+ * The directory the Windows run roots its profile view under — the project
117
+ * whose checkout the run answers: the row-config `cwd`, else the **live
118
+ * session workspace** (the run answers to the GUI the user is driving, not to
119
+ * whatever directory `dsh web` happened to be launched from — a run rooted at
120
+ * `~` links `~/.chrome` instead of the workspace), else the host's own cwd.
121
+ * @param configCwd - the row-config `cwd`, "" when unset.
122
+ * @param sessions - the sessions service, resolved optionally.
123
+ * @param hostCwd - the host process' cwd.
124
+ */
125
+ export function windowsChromeProjectDir(configCwd, sessions, hostCwd) {
126
+ if (typeof configCwd === "string" && configCwd.trim() !== "")
127
+ return configCwd.trim();
128
+ if (sessions === null || typeof sessions !== "object")
129
+ return hostCwd;
130
+ const list = sessions.list;
131
+ if (typeof list !== "function")
132
+ return hostCwd;
133
+ let live = "";
134
+ let best = -1;
135
+ for (const session of (list.call(sessions) ?? [])) {
136
+ const header = session?.header;
137
+ const cwd = typeof header?.cwd === "string" ? header.cwd.trim() : "";
138
+ if (cwd === "")
139
+ continue;
140
+ const createdAt = Number.isFinite(header?.createdAt) ? Number(header?.createdAt) : 0;
141
+ if (createdAt >= best) {
142
+ best = createdAt;
143
+ live = cwd;
144
+ }
145
+ }
146
+ return live !== "" ? live : hostCwd;
147
+ }
148
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/host/windows/paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import type { WindowsChromeLinkAnswer, WindowsChromeRun } from "../types/index.js";
2
+ /** Everything {@link runWindowsChromeConnect} consults; every field defaults
3
+ * to what the running host actually is. */
4
+ export type WindowsChromeRunOptions = {
5
+ /** Locates the Windows executable through the interop mount. Defaults to
6
+ * `existsSync`. */
7
+ exists?: (path: string) => boolean;
8
+ /** The Windows-side profile root (%LOCALAPPDATA%). Defaults to the Known
9
+ * Folder API answer, cached per host. */
10
+ localAppData?: string;
11
+ /** The workspace `.chrome` view refresh; defaults to `linkWindowsChromeProfile`.
12
+ * Injected so tests never touch the real filesystem. */
13
+ linkProfile?: (linkPath: string, profileWin: string) => WindowsChromeLinkAnswer;
14
+ /** The project directory the Windows-side profile directory hangs under.
15
+ * Defaults to `process.cwd()`. */
16
+ cwd?: string;
17
+ /** The Windows executables to look for, in preference order. */
18
+ candidates?: readonly string[];
19
+ /** The extra-flags list the bridge currently launches with. A live
20
+ * `--browserUrl` entry inside it is re-checked instead of re-launched
21
+ * (idempotency: a second click never opens a second window or duplicates
22
+ * the flag). */
23
+ currentFlags?: readonly string[];
24
+ /** The debugging-port pool: first entry is the preferred port, later
25
+ * entries only used when an earlier one already answers reachable. */
26
+ ports?: readonly number[];
27
+ /** Ports only Windows listens on — the prereq reachability probe. */
28
+ prereqPorts?: readonly number[];
29
+ /** The Windows-side working directory the launch runs with. Omit/skip when
30
+ * it is not there. */
31
+ startCwd?: string;
32
+ /** Answers whether `host:port` accepts a connection right now. */
33
+ reachable?: (host: string, port: number) => Promise<boolean>;
34
+ /** Launches the executable and resolves the moment the OS accepted the
35
+ * process; rejects with the reason when the launch itself failed. */
36
+ start?: (executable: string, args: string[], cwd: string | undefined) => Promise<void>;
37
+ /** Writes the landing page beside the profile directory and answers the
38
+ * `file:///…` URL to open in the launched window ("" = launch with no
39
+ * page). Defaults to the packaged page rendered with this run's answers;
40
+ * injected so a unit run never writes through the interop mount. */
41
+ landing?: (profileDir: string, url: string, port: number) => string;
42
+ /** How long to wait for the launched browser to bind its port. */
43
+ waitMs?: number;
44
+ /** Poll cadence while waiting. */
45
+ pollMs?: number;
46
+ /** One reachability sample's timeout. */
47
+ sampleMs?: number;
48
+ };
49
+ /**
50
+ * The whole **Prelaunch Windows Chrome** run, in order:
51
+ *
52
+ * 1. locate a Windows Chrome/Edge — none answers `not-found`;
53
+ * 2. prove the prereq — one Windows-only port must answer reachable, or
54
+ * nothing is launched and the answer is `unreachable` carrying the one
55
+ * manual step (mirrored networking);
56
+ * 3. pick the port — the preferred one when it is free, else the first free
57
+ * entry of the pool (`WINDOWS_CHROME_PORT_POOL`); a listener already
58
+ * carrying connect mode means the address is live and nothing is launched;
59
+ * 4. launch by exec'ing the located executable through the interop mount,
60
+ * with `--remote-debugging-port=<P>`, a dedicated profile directory under
61
+ * the project (never the default profile: an in-use default profile
62
+ * silently ignores the port), the first-run-page flags and the landing page
63
+ * that states what the window is for ("" = no page, never a reason for the
64
+ * launch not to happen);
65
+ * 5. wait for the port to come up — `connected` when it does, `unreachable`
66
+ * (with its own error) when it never binds.
67
+ *
68
+ * The run never kills what it started: closing the browser belongs to the
69
+ * user, and a bridge in connect mode survives a browser restart.
70
+ *
71
+ * @param options - what to consult (every half injectable).
72
+ */
73
+ export declare function runWindowsChromeConnect(options?: WindowsChromeRunOptions): Promise<WindowsChromeRun>;
74
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/host/windows/run.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAQnF;2CAC2C;AAC3C,MAAM,MAAM,uBAAuB,GAAG;IAClC;uBACmB;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC;6CACyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;4DACwD;IACxD,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,uBAAuB,CAAC;IAChF;sCACkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B;;;oBAGgB;IAChB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;0EACsE;IACtE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,qEAAqE;IACrE,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC;0BACsB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D;yEACqE;IACrE,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvF;;;wEAGoE;IACpE,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpE,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8J9G"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Windows Chrome run — the orchestrator behind the card's **Open Windows
3
+ * Chrome** button (and the `prelaunch_windows_chrome` tool).
4
+ *
5
+ * Driving the Windows browser in connect mode is the only Windows path ever
6
+ * measured to work: launch it with `--remote-debugging-port=<P>` and a dedicated
7
+ * profile, then let the bridge connect to `http://127.0.0.1:<P>` instead of
8
+ * launching anything locally. This module sequences the whole run — locate,
9
+ * prove the prereq (the mirrored-loopback reachability), pick the port, launch,
10
+ * wait for the port to bind — and answers through one state union. The pieces it
11
+ * drives live alongside it: ./paths.ts (map + locate + profile directory),
12
+ * ./link.ts (the workspace `.chrome` view), ./connect-flags.ts (the address +
13
+ * the connect-mode flag), ./spawn.ts (the raw reachability sample + interop
14
+ * launch). Every half is injectable so tests never depend on the machine.
15
+ *
16
+ * Launching the Windows `chrome.exe` in *launch* mode stays out entirely (hard
17
+ * constraint — the debug pipes do not survive the interop boundary), as does
18
+ * the default profile (an in-use one silently ignores the port) and the
19
+ * `cmd.exe /c start` wrapper (it never returns while the browser lives). The run
20
+ * never kills what it started: closing the browser belongs to the user, and a
21
+ * connect-mode bridge survives a browser restart. The field evidence behind each
22
+ * choice is `.probe/windows-chrome-connect-probe.log`.
23
+ *
24
+ * A launched window also carries its own explanation: the launch hands the
25
+ * browser a packaged landing page (./landing.ts) rendered with the run's port,
26
+ * connect address and profile directory. It is not a precondition — every
27
+ * landing failure is "" and the launch goes ahead exactly as it did before — but
28
+ * a window that opens with nothing on screen reads as a malfunction, which is
29
+ * what the page is for.
30
+ */
31
+ import { existsSync } from "node:fs";
32
+ import { WINDOWS_CHROME_CANDIDATES, WINDOWS_CHROME_FIRST_RUN_FLAGS, WINDOWS_CHROME_POLL_MS, WINDOWS_CHROME_PORT, WINDOWS_CHROME_PORT_POOL, WINDOWS_CHROME_PREREQ_ERROR, WINDOWS_CHROME_PREREQ_PORTS, WINDOWS_CHROME_SAMPLE_MS, WINDOWS_CHROME_START_CWD, WINDOWS_CHROME_WAIT_MS } from "../constants.js";
33
+ import { firstLine } from "../status.js";
34
+ import { browserUrlFlagPort, windowsChromeUrl } from "./connect-flags.js";
35
+ import { windowsChromeLandingUrl } from "./landing.js";
36
+ import { linkWindowsChromeProfile } from "./link.js";
37
+ import { findWindowsChromeExecutable, windowsChromeLocalAppData, windowsChromeProfileDir, windowsPathToMount } from "./paths.js";
38
+ import { defaultReachable, defaultStart } from "./spawn.js";
39
+ /**
40
+ * The whole **Prelaunch Windows Chrome** run, in order:
41
+ *
42
+ * 1. locate a Windows Chrome/Edge — none answers `not-found`;
43
+ * 2. prove the prereq — one Windows-only port must answer reachable, or
44
+ * nothing is launched and the answer is `unreachable` carrying the one
45
+ * manual step (mirrored networking);
46
+ * 3. pick the port — the preferred one when it is free, else the first free
47
+ * entry of the pool (`WINDOWS_CHROME_PORT_POOL`); a listener already
48
+ * carrying connect mode means the address is live and nothing is launched;
49
+ * 4. launch by exec'ing the located executable through the interop mount,
50
+ * with `--remote-debugging-port=<P>`, a dedicated profile directory under
51
+ * the project (never the default profile: an in-use default profile
52
+ * silently ignores the port), the first-run-page flags and the landing page
53
+ * that states what the window is for ("" = no page, never a reason for the
54
+ * launch not to happen);
55
+ * 5. wait for the port to come up — `connected` when it does, `unreachable`
56
+ * (with its own error) when it never binds.
57
+ *
58
+ * The run never kills what it started: closing the browser belongs to the
59
+ * user, and a bridge in connect mode survives a browser restart.
60
+ *
61
+ * @param options - what to consult (every half injectable).
62
+ */
63
+ export async function runWindowsChromeConnect(options = {}) {
64
+ const exists = typeof options.exists === "function" ? options.exists : (path) => existsSync(path);
65
+ const cwd = typeof options.cwd === "string" ? options.cwd : process.cwd();
66
+ const candidates = Array.isArray(options.candidates) ? options.candidates : WINDOWS_CHROME_CANDIDATES;
67
+ const ports = (Array.isArray(options.ports) ? options.ports : [...WINDOWS_CHROME_PORT_POOL]).map((port) => Math.trunc(port));
68
+ const prereqPorts = Array.isArray(options.prereqPorts) ? options.prereqPorts : [...WINDOWS_CHROME_PREREQ_PORTS];
69
+ const startCwd = typeof options.startCwd === "string" ? options.startCwd : WINDOWS_CHROME_START_CWD;
70
+ const waitMs = Number.isFinite(options.waitMs) ? Number(options.waitMs) : WINDOWS_CHROME_WAIT_MS;
71
+ const pollMs = Number.isFinite(options.pollMs) ? Number(options.pollMs) : WINDOWS_CHROME_POLL_MS;
72
+ const sampleMs = Number.isFinite(options.sampleMs) ? Number(options.sampleMs) : WINDOWS_CHROME_SAMPLE_MS;
73
+ const reachable = (host, port) => typeof options.reachable === "function"
74
+ ? Promise.resolve(options.reachable(host, port)).then((value) => value === true)
75
+ : defaultReachable(host, port, sampleMs);
76
+ const start = (command, args, cwdValue) => typeof options.start === "function" ? Promise.resolve(options.start(command, args, cwdValue)) : defaultStart(command, args, cwdValue);
77
+ // The profile root (the Windows-side LOCALAPPDATA) is only needed on the
78
+ // branches that connect, so it resolves lazily and stays cached.
79
+ const localAppData = () => typeof options.localAppData === "string" ? options.localAppData : windowsChromeLocalAppData();
80
+ const linkProfile = (linkPath, profileWin) => typeof options.linkProfile === "function" ? options.linkProfile(linkPath, profileWin) : linkWindowsChromeProfile(linkPath, profileWin);
81
+ const landing = (profileWin, connectUrl, portValue) => typeof options.landing === "function" ? options.landing(profileWin, connectUrl, portValue) : windowsChromeLandingUrl(profileWin, connectUrl, portValue);
82
+ // The workspace view the successful run keeps pointing at its profile —
83
+ // the same `<project>/.chrome` the **Flags WSL** recommended flag names.
84
+ const profileLinkPath = `${cwd.replace(/[\\/]+$/gu, "")}/.chrome`;
85
+ if (ports.length === 0)
86
+ ports.push(WINDOWS_CHROME_PORT);
87
+ // 1. locate.
88
+ const executable = findWindowsChromeExecutable(exists, candidates);
89
+ if (executable === "") {
90
+ return {
91
+ state: "not-found",
92
+ port: 0,
93
+ url: "",
94
+ error: `no Windows Chrome found (checked: ${Array.isArray(candidates) ? candidates.join(", ") : ""})`,
95
+ profileDir: ""
96
+ };
97
+ }
98
+ // 2. prereq: the Windows loopback has to be reachable before anything is
99
+ // launched. Nothing reachable means no launch — the window would be dead
100
+ // weight, and the run would have paid for a browser it cannot drive.
101
+ let prereqOk = false;
102
+ for (const port of prereqPorts) {
103
+ if (await reachable("127.0.0.1", port)) {
104
+ prereqOk = true;
105
+ break;
106
+ }
107
+ }
108
+ if (!prereqOk)
109
+ return { state: "unreachable", port: 0, url: "", profileDir: "", error: WINDOWS_CHROME_PREREQ_ERROR };
110
+ // 3. port. A live connect entry already answers — in every spelling
111
+ // `flags.ts` accepts, not only the one the run itself writes — so it is
112
+ // re-checked and settled on without a second launch when it still holds.
113
+ const livePort = browserUrlFlagPort(options.currentFlags);
114
+ if (livePort > 0 && (await reachable("127.0.0.1", livePort))) {
115
+ // The already-live session is profiled in the same per-port directory a
116
+ // launch would have chosen, so the workspace view keeps pointing at
117
+ // whatever is actually running.
118
+ const liveLeaf = livePort === WINDOWS_CHROME_PORT ? ".chrome" : `.chrome-${String(livePort)}`;
119
+ const liveProfileDir = windowsChromeProfileDir(localAppData(), liveLeaf);
120
+ return {
121
+ state: "connected",
122
+ port: livePort,
123
+ url: windowsChromeUrl(livePort),
124
+ error: "",
125
+ profileDir: liveProfileDir,
126
+ profileLink: linkProfile(profileLinkPath, liveProfileDir)
127
+ };
128
+ }
129
+ const pool = livePort > 0 ? [livePort, ...ports.filter((port) => port !== livePort)] : ports;
130
+ let port = 0;
131
+ for (const candidate of pool) {
132
+ if (!(await reachable("127.0.0.1", candidate))) {
133
+ port = candidate;
134
+ break;
135
+ }
136
+ }
137
+ if (port === 0)
138
+ port = pool[pool.length - 1];
139
+ // 4. profile + launch. The profile directory is Windows-side (a profile
140
+ // rooted in the WSL checkout cannot carry Chrome's locks, and a profile
141
+ // that cannot lock answers "an error occurred while opening your profile");
142
+ // it is never the default profile (an in-use one silently ignores the
143
+ // port); and it never goes through the `cmd.exe /c start` wrapper (see
144
+ // ./spawn.ts: under interop that wrapper never returns while the browser
145
+ // lives, and the whole run silently stalls). The locate answer is a Windows
146
+ // spelling (what the card may quote); interop execs through the mount, so
147
+ // the launch maps it back first.
148
+ const leaf = port === WINDOWS_CHROME_PORT ? ".chrome" : `.chrome-${String(port)}`;
149
+ const profileDir = windowsChromeProfileDir(localAppData(), leaf);
150
+ if (profileDir === "") {
151
+ return {
152
+ state: "launch-failed",
153
+ port,
154
+ url: "",
155
+ profileDir: "",
156
+ error: "cannot derive the Windows-side profile directory: LOCALAPPDATA did not answer"
157
+ };
158
+ }
159
+ // The launch's argv: the port, the profile, the first-run flags, and — last
160
+ // — one positional URL, the landing page that says what this window is for.
161
+ // A page that could not be rendered or written answers "" and simply drops
162
+ // out of argv: the run's answer never depends on prose.
163
+ const url = windowsChromeUrl(port);
164
+ const landingUrl = landing(profileDir, url, port);
165
+ try {
166
+ await start(windowsPathToMount(executable) || executable, [
167
+ `--remote-debugging-port=${String(port)}`,
168
+ `--user-data-dir=${profileDir}`,
169
+ // A brand-new profile is a first run: without these, Windows
170
+ // Chrome opens the welcome tab and the search-engine chooser
171
+ // and connect mode never clicks past them.
172
+ ...WINDOWS_CHROME_FIRST_RUN_FLAGS,
173
+ ...(landingUrl === "" ? [] : [landingUrl])
174
+ ], exists(startCwd) ? startCwd : undefined);
175
+ }
176
+ catch (error) {
177
+ return {
178
+ state: "launch-failed",
179
+ port,
180
+ url: "",
181
+ profileDir: "",
182
+ error: `could not start Windows Chrome: ${firstLine(error instanceof Error ? error.message : String(error))}`
183
+ };
184
+ }
185
+ // 5. wait for the browser to bind its port. A browser that never binds it
186
+ // is not reachable, so the answer is the prereq's failure to be useful.
187
+ const deadline = Date.now() + waitMs;
188
+ for (;;) {
189
+ if (await reachable("127.0.0.1", port)) {
190
+ return {
191
+ state: "connected",
192
+ port,
193
+ url,
194
+ error: "",
195
+ profileDir,
196
+ profileLink: linkProfile(profileLinkPath, profileDir)
197
+ };
198
+ }
199
+ if (Date.now() >= deadline) {
200
+ return {
201
+ state: "unreachable",
202
+ port,
203
+ url: "",
204
+ profileDir: "",
205
+ error: `Windows Chrome started but did not open a debugging port on 127.0.0.1:${String(port)} — ${WINDOWS_CHROME_PREREQ_ERROR}`
206
+ };
207
+ }
208
+ await new Promise((resolve) => setTimeout(resolve, pollMs));
209
+ }
210
+ }
211
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/host/windows/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /** One TCP sample: connect success answers reachable; anything else (refusal,
2
+ * timeout) answers unreachable — the NAT host's honest behaviour. */
3
+ export declare function defaultReachable(host: string, port: number, sampleMs?: number): Promise<boolean>;
4
+ /**
5
+ * Launch the Windows-side browser through the interop mount by exec'ing it
6
+ * directly, resolving the moment the OS accepted the process (the browser
7
+ * itself keeps running — the run must never wait for it, and the port wait
8
+ * below is what turns a silently dead launch into `unreachable`).
9
+ *
10
+ * The interop `start` wrapper is deliberately NOT used here even though the
11
+ * plan quoted `cmd.exe /c start`: measured 2026-10-06 against Windows Chrome
12
+ * 154 (see .probe/windows-chrome-connect-probe.log), the WSL interop process
13
+ * for `cmd.exe /c start "" <browser> <args…>` does not exit while the GUI
14
+ * browser lives, so step 4 could never report its answer and the card sat in
15
+ * "launching" until the spawn timed out — a silent 30 s. A direct
16
+ * `execve`/CreateProcess of the executable accepted in 3 ms and bound the
17
+ * port in ~1 s; this is the only launch shape that returns. It also keeps
18
+ * Chrome's working directory out of any UNC path (the old `start` warning),
19
+ * since the launch takes a Windows-side cwd.
20
+ */
21
+ export declare function defaultStart(executable: string, args: string[], cwd: string | undefined): Promise<void>;
22
+ //# sourceMappingURL=spawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../src/host/windows/spawn.ts"],"names":[],"mappings":"AAmBA;qEACqE;AACrE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAiC,GAAG,OAAO,CAAC,OAAO,CAAC,CAe1H;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBvG"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Windows Chrome run — the raw machine seams: a TCP reachability sample and a
3
+ * direct interop launch.
4
+ *
5
+ * The two halves of the run that reach outside the process, injected by
6
+ * ./run.ts (and replaced wholesale by the tests) so a unit run never opens a
7
+ * real socket or spawns through the interop mount. The TCP sample answers
8
+ * reachable only on a genuine connect — a refusal or a timeout both read
9
+ * unreachable, the honest NAT-host behaviour. The launch is the interop exec of
10
+ * the located executable (NOT the `cmd.exe /c start` wrapper the plan quoted:
11
+ * under interop that wrapper never returns while the GUI browser lives, so the
12
+ * whole run silently stalls — measured 2026-10-06 against Chrome 154), resolving
13
+ * the moment the OS accepts the process.
14
+ */
15
+ import { spawn } from "node:child_process";
16
+ import { connect } from "node:net";
17
+ import { WINDOWS_CHROME_SAMPLE_MS } from "../constants.js";
18
+ /** One TCP sample: connect success answers reachable; anything else (refusal,
19
+ * timeout) answers unreachable — the NAT host's honest behaviour. */
20
+ export function defaultReachable(host, port, sampleMs = WINDOWS_CHROME_SAMPLE_MS) {
21
+ return new Promise((resolve) => {
22
+ let settled = false;
23
+ const socket = connect({ host, port });
24
+ const finish = (value) => {
25
+ if (settled)
26
+ return;
27
+ settled = true;
28
+ socket.destroy();
29
+ resolve(value);
30
+ };
31
+ socket.setTimeout(sampleMs);
32
+ socket.on("connect", () => finish(true));
33
+ socket.on("timeout", () => finish(false));
34
+ socket.on("error", () => finish(false));
35
+ });
36
+ }
37
+ /**
38
+ * Launch the Windows-side browser through the interop mount by exec'ing it
39
+ * directly, resolving the moment the OS accepted the process (the browser
40
+ * itself keeps running — the run must never wait for it, and the port wait
41
+ * below is what turns a silently dead launch into `unreachable`).
42
+ *
43
+ * The interop `start` wrapper is deliberately NOT used here even though the
44
+ * plan quoted `cmd.exe /c start`: measured 2026-10-06 against Windows Chrome
45
+ * 154 (see .probe/windows-chrome-connect-probe.log), the WSL interop process
46
+ * for `cmd.exe /c start "" <browser> <args…>` does not exit while the GUI
47
+ * browser lives, so step 4 could never report its answer and the card sat in
48
+ * "launching" until the spawn timed out — a silent 30 s. A direct
49
+ * `execve`/CreateProcess of the executable accepted in 3 ms and bound the
50
+ * port in ~1 s; this is the only launch shape that returns. It also keeps
51
+ * Chrome's working directory out of any UNC path (the old `start` warning),
52
+ * since the launch takes a Windows-side cwd.
53
+ */
54
+ export function defaultStart(executable, args, cwd) {
55
+ return new Promise((resolve, reject) => {
56
+ let child;
57
+ try {
58
+ child = spawn(executable, args, {
59
+ stdio: "ignore",
60
+ ...(cwd === undefined || cwd === "" ? {} : { cwd })
61
+ });
62
+ }
63
+ catch (error) {
64
+ reject(new Error(`could not run "${executable} ${args.join(" ")}": ${String(error)}`));
65
+ return;
66
+ }
67
+ // `spawn` is the OS accepting the process; no other half is waited on.
68
+ child.once("spawn", resolve);
69
+ child.once("error", (error) => reject(new Error(`could not run "${executable} ${args.join(" ")}": ${String(error)}`)));
70
+ child.unref();
71
+ });
72
+ }
73
+ //# sourceMappingURL=spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../../src/host/windows/spawn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3D;qEACqE;AACrE,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,IAAY,EAAE,WAAmB,wBAAwB;IACpG,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,EAAE;YAC9B,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,CAAC;QACF,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACzC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB,EAAE,IAAc,EAAE,GAAuB;IACpF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,IAAI,KAA+B,CAAC;QACpC,IAAI,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE;gBAC5B,KAAK,EAAE,QAAQ;gBACf,GAAG,CAAC,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;aACtD,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YACvF,OAAO;QACX,CAAC;QACD,uEAAuE;QACvE,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAA4B,EAAE,EAAE,CACjD,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5F,KAAK,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;AACP,CAAC"}