@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,97 @@
1
+ /**
2
+ * Windows Chrome run — the connect-mode address and flag it writes.
3
+ *
4
+ * The connect half of the run: the `http://127.0.0.1:<P>` address a debugging
5
+ * port answers for, the port one saved `--browserUrl=` entry carries, and the
6
+ * replace-by-key merge that keeps the saved flags at exactly one connect entry
7
+ * (never two, with the local `--user-data-dir` row dropped — upstream refuses
8
+ * `userDataDir` and `browserUrl` in the same argv). The run calls these to
9
+ * answer and to persist its outcome; ./run.ts drives them.
10
+ */
11
+ import { carriesConnectionMode } from "../flags.js";
12
+ import { BROWSER_URL_FLAG_PREFIX } from "../constants.js";
13
+ /** The connect address one debugging port answers for. */
14
+ export function windowsChromeUrl(port) {
15
+ return `http://127.0.0.1:${Math.trunc(port)}`;
16
+ }
17
+ /** The debugging port the live connect entry carries, 0 when the list carries
18
+ * none. The entry's **spelling** is irrelevant: the port is read through the
19
+ * very predicate that decides connect mode (`carriesConnectionMode` in
20
+ * `./flags.ts`), so `--browserUrl=<url>`, `--browserUrl <url>` (the two-entry
21
+ * form the whitespace-split env source produces), one string carrying its
22
+ * value after whitespace, and `--wsEndpoint=<url>` all answer with the live
23
+ * port instead of reading as "no live session". */
24
+ export function browserUrlFlagPort(flags) {
25
+ const list = Array.isArray(flags) ? flags : [];
26
+ for (let index = 0; index < list.length; index += 1) {
27
+ const flag = list[index];
28
+ if (typeof flag !== "string" || !carriesConnectionMode(flag))
29
+ continue;
30
+ const eq = flag.indexOf("=");
31
+ if (eq !== -1) {
32
+ const match = flag.slice(eq + 1).trim().match(/:(\d+)/u);
33
+ return match === null ? 0 : Number.parseInt(match[1], 10);
34
+ }
35
+ const whitespace = flag.slice(2).match(/\s/u);
36
+ if (whitespace?.index !== void 0) {
37
+ const match = flag.slice(whitespace.index + 3).trim().match(/:(\d+)/u);
38
+ return match === null ? 0 : Number.parseInt(match[1], 10);
39
+ }
40
+ const value = list[index + 1];
41
+ const match = typeof value === "string" ? value.trim().match(/:(\d+)/u) : null;
42
+ return match === null ? 0 : Number.parseInt(match[1], 10);
43
+ }
44
+ return 0;
45
+ }
46
+ /** The local-profile row the connect entry makes mutually exclusive with it
47
+ * upstream: a saved `--user-data-dir` next to a `--browserUrl` kills the spawn
48
+ * (`Arguments userDataDir and browserUrl are mutually exclusive`, measured
49
+ * live with chrome-devtools-mcp), so the run drops it when it pins connect. */
50
+ const CONNECT_EXCLUDED_FLAG = "--user-data-dir";
51
+ /**
52
+ * Collapse every connect entry the list carries into the run's own address, so
53
+ * the saved list keeps exactly **one** connect source whatever spelling it was
54
+ * stored in — the same idempotency rule the saved-executable merge follows for
55
+ * a repeated id, keyed now on the whole connect-mode predicate rather than one
56
+ * flag spelling. An entry that carries its value as the *following* entry (the
57
+ * `--browserUrl <url>` form the whitespace-split env source produces) consumes
58
+ * that value with it, so no bare URL survives as a stray argv item.
59
+ *
60
+ * The one thing that does not survive is a `--user-data-dir` row: connect
61
+ * carries no local profile to hand the browser, upstream refuses both at once,
62
+ * so keeping a saved Flags-WSL row would leave the bridge unspawnable
63
+ * (`Arguments userDataDir and browserUrl are mutually exclusive`, measured live
64
+ * with chrome-devtools-mcp).
65
+ */
66
+ export function withBrowserUrlFlag(flags, url) {
67
+ const entry = `${BROWSER_URL_FLAG_PREFIX}${url}`;
68
+ const list = Array.isArray(flags) ? flags : [];
69
+ const next = [];
70
+ let replaced = false;
71
+ let awaitingValue = false;
72
+ for (const flag of list) {
73
+ if (typeof flag !== "string")
74
+ continue;
75
+ if (flag.startsWith(CONNECT_EXCLUDED_FLAG))
76
+ continue;
77
+ if (carriesConnectionMode(flag)) {
78
+ if (!replaced) {
79
+ next.push(entry);
80
+ replaced = true;
81
+ }
82
+ // No inline value (no `=`, no whitespace) means the value is the
83
+ // entry that follows — drop it with the flag, exactly the way
84
+ // `stripExecutablePathFlags` consumes a `--flag <path>` spelling.
85
+ awaitingValue = !flag.includes("=") && !/\s/u.test(flag);
86
+ continue;
87
+ }
88
+ if (awaitingValue && !flag.startsWith("-"))
89
+ continue;
90
+ awaitingValue = false;
91
+ next.push(flag);
92
+ }
93
+ if (!replaced)
94
+ next.push(entry);
95
+ return next;
96
+ }
97
+ //# sourceMappingURL=connect-flags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect-flags.js","sourceRoot":"","sources":["../../../src/host/windows/connect-flags.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Host half — the Windows-side Chrome run behind the card's **Open Windows
3
+ * Chrome** button and the `prelaunch_windows_chrome` tool.
4
+ *
5
+ * The whole Windows path, split the way it reads into one directory:
6
+ *
7
+ * ./paths.ts drive→mount mapping, locate, the Windows-native profile
8
+ * directory + LOCALAPPDATA root, and the project dir the
9
+ * workspace `.chrome` view hangs under
10
+ * ./link.ts the workspace `.chrome` view link (a WSL-side symlink)
11
+ * ./connect-flags.ts the connect address + the replace-by-key `--browserUrl`
12
+ * merge with the local profile flag dropped
13
+ * ./landing.ts the packaged page the launched window opens, rendered
14
+ * with the run's answers, written beside the profile and
15
+ * answered back as a `file:///…` URL
16
+ * ./spawn.ts the raw TCP reachability sample + the interop launch
17
+ * ./run.ts the orchestrator: locate → prereq → port → launch → wait
18
+ *
19
+ * Driving the Windows browser in **connect** mode is the only Windows path ever
20
+ * measured to work (launching `chrome.exe` across the interop boundary cannot —
21
+ * the debug pipes do not survive it); see ./run.ts's header and the field log in
22
+ * `.probe/windows-chrome-connect-probe.log`. Every half is injectable, so the
23
+ * tests never depend on the machine they run on.
24
+ */
25
+ export { findWindowsChromeExecutable, findWindowsChromeExecutables, windowsChromeLocalAppData, windowsChromeProfileDir, windowsChromeProjectDir, windowsPathToMount } from "./paths.js";
26
+ export { linkWindowsChromeProfile } from "./link.js";
27
+ export { browserUrlFlagPort, withBrowserUrlFlag, windowsChromeUrl } from "./connect-flags.js";
28
+ export { windowsChromeLandingAsset, windowsChromeLandingHtml, windowsChromeLandingPath, windowsChromeLandingUrl, windowsFileUrl } from "./landing.js";
29
+ export { runWindowsChromeConnect } from "./run.js";
30
+ export type { WindowsChromeRunOptions } from "./run.js";
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/host/windows/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EACH,2BAA2B,EAC3B,4BAA4B,EAC5B,yBAAyB,EACzB,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC9F,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACtJ,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AACnD,YAAY,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Host half — the Windows-side Chrome run behind the card's **Open Windows
3
+ * Chrome** button and the `prelaunch_windows_chrome` tool.
4
+ *
5
+ * The whole Windows path, split the way it reads into one directory:
6
+ *
7
+ * ./paths.ts drive→mount mapping, locate, the Windows-native profile
8
+ * directory + LOCALAPPDATA root, and the project dir the
9
+ * workspace `.chrome` view hangs under
10
+ * ./link.ts the workspace `.chrome` view link (a WSL-side symlink)
11
+ * ./connect-flags.ts the connect address + the replace-by-key `--browserUrl`
12
+ * merge with the local profile flag dropped
13
+ * ./landing.ts the packaged page the launched window opens, rendered
14
+ * with the run's answers, written beside the profile and
15
+ * answered back as a `file:///…` URL
16
+ * ./spawn.ts the raw TCP reachability sample + the interop launch
17
+ * ./run.ts the orchestrator: locate → prereq → port → launch → wait
18
+ *
19
+ * Driving the Windows browser in **connect** mode is the only Windows path ever
20
+ * measured to work (launching `chrome.exe` across the interop boundary cannot —
21
+ * the debug pipes do not survive it); see ./run.ts's header and the field log in
22
+ * `.probe/windows-chrome-connect-probe.log`. Every half is injectable, so the
23
+ * tests never depend on the machine they run on.
24
+ */
25
+ export { findWindowsChromeExecutable, findWindowsChromeExecutables, windowsChromeLocalAppData, windowsChromeProfileDir, windowsChromeProjectDir, windowsPathToMount } from "./paths.js";
26
+ export { linkWindowsChromeProfile } from "./link.js";
27
+ export { browserUrlFlagPort, withBrowserUrlFlag, windowsChromeUrl } from "./connect-flags.js";
28
+ export { windowsChromeLandingAsset, windowsChromeLandingHtml, windowsChromeLandingPath, windowsChromeLandingUrl, windowsFileUrl } from "./landing.js";
29
+ export { runWindowsChromeConnect } from "./run.js";
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/host/windows/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EACH,2BAA2B,EAC3B,4BAA4B,EAC5B,yBAAyB,EACzB,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC9F,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACtJ,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,47 @@
1
+ /** The run's own tokens in the packaged page, in the shape each one answers. */
2
+ type LandingTokens = {
3
+ url: string;
4
+ port: number;
5
+ profile: string;
6
+ };
7
+ /** The packaged page's path on this host, "" when the package carries none. */
8
+ export declare function windowsChromeLandingAsset(): string;
9
+ /**
10
+ * The packaged page, with the run's answers folded into its `{{TOKEN}}`s —
11
+ * "" when the asset is not there. Values are escaped, tokens the page does not
12
+ * carry are simply left alone, and a page whose write fails downstream is not
13
+ * this function's problem: it answers the *rendered* text, nothing else.
14
+ */
15
+ export declare function windowsChromeLandingHtml(tokens?: Partial<LandingTokens>): string;
16
+ /**
17
+ * The landing file's Windows path beside a profile directory:
18
+ * `…\dsh-chrome-mcp\prelaunch-<port>.html`, a **sibling** of the profile rather
19
+ * than a file inside it — Chrome owns everything inside its own profile
20
+ * directory, and this page is not part of one.
21
+ */
22
+ export declare function windowsChromeLandingPath(profileDir: unknown, port: number): string;
23
+ /**
24
+ * A Windows path as a `file://` URL — the only form the launched browser reads
25
+ * (the interop mount path is Linux-side, invisible to `chrome.exe`). No drive
26
+ * letter answers "" (never a half-formed URL), and every path segment is
27
+ * percent-encoded, since a user profile directory routinely carries spaces.
28
+ */
29
+ export declare function windowsFileUrl(path: unknown): string;
30
+ /**
31
+ * The whole landing-page half of a launch: render the packaged page with this
32
+ * run's answers, write it beside the profile directory through the interop
33
+ * mount, and answer the `file:///…` URL to hand the browser ("" = launch with
34
+ * no page). Every failure is silent on purpose — the page explains the window,
35
+ * it never gates it.
36
+ * @param profileDir - the Windows-side profile directory the launch carries.
37
+ * @param url - the connect address the window answers for.
38
+ * @param port - the debugging port that launch picked.
39
+ * @param write - the filesystem half: place `html` at the **mount** path and
40
+ * answer whether it actually landed. Defaults to creating the directory and
41
+ * writing the file through the interop mount; injected so a test never depends
42
+ * on the machine it runs on (the mount is never inside the checkout, and the
43
+ * agent's own file sandbox denies it outright).
44
+ */
45
+ export declare function windowsChromeLandingUrl(profileDir: unknown, url: unknown, port: unknown, write?: (mountPath: string, html: string) => boolean): string;
46
+ export {};
47
+ //# sourceMappingURL=landing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"landing.d.ts","sourceRoot":"","sources":["../../../src/host/windows/landing.ts"],"names":[],"mappings":"AA6BA,gFAAgF;AAChF,KAAK,aAAa,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AA0BpE,+EAA+E;AAC/E,wBAAgB,yBAAyB,IAAI,MAAM,CAMlD;AAQD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,MAAM,CAmBpF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAOlF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAWpD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CACnC,UAAU,EAAE,OAAO,EACnB,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,OAAO,EACb,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,GACrD,MAAM,CAuBR"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Windows Chrome run — the **landing page** the launched window opens.
3
+ *
4
+ * A window that appears for no visible reason looks like a malfunction, and the
5
+ * honest answer to "why did a Chrome window just open?" is a paragraph of
6
+ * explanation the bridge's argv cannot carry. So the run ships one: a packaged,
7
+ * self-contained HTML page (`assets/prelaunch-windows-chrome.html`, the only
8
+ * asset the plugin carries) rendered with the run's own answers and written next
9
+ * to the Windows-side profile directory, so the window that opens *states* what
10
+ * it is for — opened by the plugin from DSH so the bridge can drive it over the
11
+ * debugging port, never a browsing session the user started.
12
+ *
13
+ * The file has to live on the **Windows** filesystem and be handed to the browser
14
+ * as a `file:///…` URL, exactly like the profile directory it sits beside: the
15
+ * WSL-side path is invisible to a Windows-side process. Nothing depends on it:
16
+ * every answer is "" when the asset cannot be read, the write fails or LOCALAPPDATA
17
+ * never answered, and a run without a landing page launches the same browser it
18
+ * launched before — the page is a description of the window, not a precondition
19
+ * of it. It is never opened on the re-attach branch (nothing was launched, so no
20
+ * window was added), and it is opened exactly once per launch.
21
+ */
22
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
23
+ import { dirname } from "node:path";
24
+ import { fileURLToPath } from "node:url";
25
+ import { WINDOWS_CHROME_LANDING_ASSET, WINDOWS_CHROME_LANDING_BASENAME } from "../constants.js";
26
+ import { windowsPathToMount } from "./paths.js";
27
+ /** The packaged page, resolved once per process (see {@link packageRoot} for why
28
+ * the lookup walks directories instead of trusting a depth). */
29
+ let cachedAsset;
30
+ /**
31
+ * The package root, walked up from this module until a `package.json` shows up:
32
+ * the emit sits under `lib/host/windows/`, so the asset's package-root-relative
33
+ * path is the same whether the plugin was installed or linked from a checkout,
34
+ * and a hard-coded `../../` would break the day the layout moves. "" answers when
35
+ * the lookup runs out of directories (an exotic packaging), which is simply no
36
+ * landing page.
37
+ */
38
+ function packageRoot() {
39
+ let dir = dirname(fileURLToPath(import.meta.url));
40
+ for (let hops = 0; hops < 8; hops += 1) {
41
+ const manifest = `${dir}/package.json`;
42
+ if (existsSync(manifest))
43
+ return dir;
44
+ const parent = dirname(dir);
45
+ if (parent === dir)
46
+ break;
47
+ dir = parent;
48
+ }
49
+ return "";
50
+ }
51
+ /** The packaged page's path on this host, "" when the package carries none. */
52
+ export function windowsChromeLandingAsset() {
53
+ if (typeof cachedAsset === "string")
54
+ return cachedAsset;
55
+ const root = packageRoot();
56
+ const asset = root === "" ? "" : `${root}/${WINDOWS_CHROME_LANDING_ASSET}`;
57
+ cachedAsset = asset !== "" && existsSync(asset) ? asset : "";
58
+ return cachedAsset;
59
+ }
60
+ /** The one HTML entity escape the page needs: the profile path is the only
61
+ * value that can carry markup characters (a user name with `&`, say). */
62
+ function escapeHtml(value) {
63
+ return String(value ?? "").replace(/&/gu, "&amp;").replace(/</gu, "&lt;").replace(/>/gu, "&gt;");
64
+ }
65
+ /**
66
+ * The packaged page, with the run's answers folded into its `{{TOKEN}}`s —
67
+ * "" when the asset is not there. Values are escaped, tokens the page does not
68
+ * carry are simply left alone, and a page whose write fails downstream is not
69
+ * this function's problem: it answers the *rendered* text, nothing else.
70
+ */
71
+ export function windowsChromeLandingHtml(tokens = {}) {
72
+ const asset = windowsChromeLandingAsset();
73
+ if (asset === "")
74
+ return "";
75
+ let html;
76
+ try {
77
+ html = readFileSync(asset, "utf8");
78
+ }
79
+ catch {
80
+ return "";
81
+ }
82
+ const port = Number.isFinite(tokens.port) ? String(Math.trunc(Number(tokens.port))) : "";
83
+ const values = {
84
+ URL: escapeHtml(typeof tokens.url === "string" ? tokens.url : ""),
85
+ PORT: port,
86
+ PROFILE: escapeHtml(typeof tokens.profile === "string" ? tokens.profile : "")
87
+ };
88
+ for (const [token, value] of Object.entries(values)) {
89
+ html = html.split(`{{${token}}}`).join(value);
90
+ }
91
+ return html;
92
+ }
93
+ /**
94
+ * The landing file's Windows path beside a profile directory:
95
+ * `…\dsh-chrome-mcp\prelaunch-<port>.html`, a **sibling** of the profile rather
96
+ * than a file inside it — Chrome owns everything inside its own profile
97
+ * directory, and this page is not part of one.
98
+ */
99
+ export function windowsChromeLandingPath(profileDir, port) {
100
+ const profile = typeof profileDir === "string" ? profileDir.trim().replace(/[\\/]+$/u, "") : "";
101
+ if (profile === "")
102
+ return "";
103
+ const cut = Math.max(profile.lastIndexOf("\\"), profile.lastIndexOf("/"));
104
+ if (cut <= 0)
105
+ return "";
106
+ const leaf = `${WINDOWS_CHROME_LANDING_BASENAME}-${String(Math.trunc(port))}.html`;
107
+ return `${profile.slice(0, cut)}\\${leaf}`;
108
+ }
109
+ /**
110
+ * A Windows path as a `file://` URL — the only form the launched browser reads
111
+ * (the interop mount path is Linux-side, invisible to `chrome.exe`). No drive
112
+ * letter answers "" (never a half-formed URL), and every path segment is
113
+ * percent-encoded, since a user profile directory routinely carries spaces.
114
+ */
115
+ export function windowsFileUrl(path) {
116
+ if (typeof path !== "string")
117
+ return "";
118
+ const candidate = path.trim().replace(/[\\/]+$/u, "");
119
+ const match = candidate.match(/^([a-zA-Z]):[\\/](.*)$/u);
120
+ if (match === null)
121
+ return "";
122
+ const segments = match[2]
123
+ .split(/[\\/]+/u)
124
+ .filter((segment) => segment !== "")
125
+ .map((segment) => encodeURIComponent(segment));
126
+ if (segments.length === 0)
127
+ return "";
128
+ return `file:///${match[1]}:/${segments.join("/")}`;
129
+ }
130
+ /**
131
+ * The whole landing-page half of a launch: render the packaged page with this
132
+ * run's answers, write it beside the profile directory through the interop
133
+ * mount, and answer the `file:///…` URL to hand the browser ("" = launch with
134
+ * no page). Every failure is silent on purpose — the page explains the window,
135
+ * it never gates it.
136
+ * @param profileDir - the Windows-side profile directory the launch carries.
137
+ * @param url - the connect address the window answers for.
138
+ * @param port - the debugging port that launch picked.
139
+ * @param write - the filesystem half: place `html` at the **mount** path and
140
+ * answer whether it actually landed. Defaults to creating the directory and
141
+ * writing the file through the interop mount; injected so a test never depends
142
+ * on the machine it runs on (the mount is never inside the checkout, and the
143
+ * agent's own file sandbox denies it outright).
144
+ */
145
+ export function windowsChromeLandingUrl(profileDir, url, port, write) {
146
+ const number = Number.isFinite(port) ? Math.trunc(Number(port)) : 0;
147
+ const path = windowsChromeLandingPath(profileDir, number);
148
+ if (path === "")
149
+ return "";
150
+ const html = windowsChromeLandingHtml({
151
+ url: typeof url === "string" ? url : "",
152
+ port: number,
153
+ profile: typeof profileDir === "string" ? profileDir : ""
154
+ });
155
+ if (html === "")
156
+ return "";
157
+ const mount = windowsPathToMount(path);
158
+ if (mount === "")
159
+ return "";
160
+ const place = (mountPath, content) => {
161
+ try {
162
+ mkdirSync(dirname(mountPath), { recursive: true });
163
+ writeFileSync(mountPath, content, "utf8");
164
+ }
165
+ catch {
166
+ return false;
167
+ }
168
+ return true;
169
+ };
170
+ if (!(typeof write === "function" ? write(mount, html) : place(mount, html)))
171
+ return "";
172
+ return windowsFileUrl(path);
173
+ }
174
+ //# sourceMappingURL=landing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"landing.js","sourceRoot":"","sources":["../../../src/host/windows/landing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { WindowsChromeLinkAnswer } from "../types/index.js";
2
+ /**
3
+ * Points `linkPath` (the workspace's `.chrome`, a WSL-side path) at the
4
+ * Windows-side profile directory — the link is pure WSL-side, so Windows never
5
+ * sees it, but everything the run profiles reads back from the checkout. The
6
+ * target is Linux-side (`/mnt/c…`): Chrome reads the Windows spelling of the
7
+ * link's own target, not this link at all. A real directory that is already
8
+ * there is kept untouched (it might carry the user's own reading).
9
+ */
10
+ export declare function linkWindowsChromeProfile(linkPath: unknown, profileWin: unknown): WindowsChromeLinkAnswer;
11
+ //# sourceMappingURL=link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/host/windows/link.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAEjE;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,GAAG,uBAAuB,CAwBxG"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Windows Chrome run — the workspace `.chrome` view link.
3
+ *
4
+ * A run profiles a Windows-native directory and keeps the checkout's `.chrome`
5
+ * as a **view** of it: a WSL-side symlink, so Windows never sees the link, but
6
+ * the checkout reads the profile back through it. A real directory already
7
+ * sitting at the view spot is kept — the link never clobbers what is already
8
+ * there. The answer names what happened (`linked`/`updated`/`kept`/`failed`) so
9
+ * the controller states a kept directory exactly once.
10
+ */
11
+ import { lstatSync, readlinkSync, symlinkSync, unlinkSync } from "node:fs";
12
+ import { windowsPathToMount } from "./paths.js";
13
+ /**
14
+ * Points `linkPath` (the workspace's `.chrome`, a WSL-side path) at the
15
+ * Windows-side profile directory — the link is pure WSL-side, so Windows never
16
+ * sees it, but everything the run profiles reads back from the checkout. The
17
+ * target is Linux-side (`/mnt/c…`): Chrome reads the Windows spelling of the
18
+ * link's own target, not this link at all. A real directory that is already
19
+ * there is kept untouched (it might carry the user's own reading).
20
+ */
21
+ export function linkWindowsChromeProfile(linkPath, profileWin) {
22
+ const link = typeof linkPath === "string" ? linkPath.trim().replace(/[\\/]+$/u, "") : "";
23
+ const target = windowsPathToMount(profileWin);
24
+ if (link === "" || target === "")
25
+ return "failed";
26
+ let existing;
27
+ try {
28
+ existing = lstatSync(link);
29
+ }
30
+ catch {
31
+ try {
32
+ symlinkSync(target, link);
33
+ return "linked";
34
+ }
35
+ catch {
36
+ return "failed";
37
+ }
38
+ }
39
+ if (!existing.isSymbolicLink())
40
+ return "kept";
41
+ if (readlinkSync(link) === target)
42
+ return "updated";
43
+ try {
44
+ unlinkSync(link);
45
+ symlinkSync(target, link);
46
+ return "updated";
47
+ }
48
+ catch {
49
+ return "failed";
50
+ }
51
+ }
52
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../../../src/host/windows/link.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGhD;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAiB,EAAE,UAAmB;IAC3E,MAAM,IAAI,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzF,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAC9C,IAAI,IAAI,KAAK,EAAE,IAAI,MAAM,KAAK,EAAE;QAAE,OAAO,QAAQ,CAAC;IAClD,IAAI,QAAsC,CAAC;IAC3C,IAAI,CAAC;QACD,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACL,IAAI,CAAC;YACD,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC1B,OAAO,QAAQ,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,QAAQ,CAAC;QACpB,CAAC;IACL,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC;IACpD,IAAI,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC1B,OAAO,SAAS,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,QAAQ,CAAC;IACpB,CAAC;AACL,CAAC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * The Windows spelling mapped onto the interop mount (`C:\Program Files\…` →
3
+ * `/mnt/c/Program Files/…`), which is the form WSL can stat. A path already
4
+ * spelled as the mount maps to itself — the mount spelling is what the WSL side
5
+ * can stat and therefore what a saved row or the row config may carry — and a
6
+ * path that is neither maps nowhere and yields "".
7
+ *
8
+ * A path may have been written or copied shell-style, where a space is escaped
9
+ * (`Program\ Files`). Such a backslash escapes the space that follows it and is
10
+ * not a separator, so it folds away to the plain space first; every other
11
+ * backslash is a Windows separator and folds to a slash. Turning one space
12
+ * escape blindly into a slash produced `Program/ Files` — a path that exists
13
+ * nowhere and answers `not-found` for a Chrome the run had actually located
14
+ * (measured live 2026-10-12 against a saved mount-spelled selection).
15
+ */
16
+ export declare function windowsPathToMount(path: unknown): string;
17
+ /**
18
+ * Locate the Windows-side Chrome through the interop mount: the first candidate
19
+ * whose mount path exists, "" when this machine carries none of them. The
20
+ * returned path keeps its **Windows** spelling — it is what the `start`
21
+ * invocation takes and what the card names.
22
+ */
23
+ export declare function findWindowsChromeExecutable(exists?: (path: string) => boolean, candidates?: readonly string[]): string;
24
+ /**
25
+ * Every Windows-side executable this host carries, in the list's own preference
26
+ * order and in its **Windows** spelling — the whole located set, not only the
27
+ * first. This is what the executable run folds into its candidate list, so the
28
+ * picker offers the Windows browser instead of hiding it. A machine that carries
29
+ * none of them answers nothing, so the list is what is installed here, never a
30
+ * fixed set of install locations. Nothing on the list is ever spawned from WSL
31
+ * (see `blockedForPlatform`); it is offered so that the **Prelaunch Windows
32
+ * Chrome** run can be pointed at the one the picker selected.
33
+ */
34
+ export declare function findWindowsChromeExecutables(exists?: (path: string) => boolean, candidates?: readonly string[]): string[];
35
+ /**
36
+ * The Windows-side profile directory: `<localAppData>\<dir>\.chrome[-<port>]`.
37
+ * The profile has to live on the Windows filesystem — Chrome takes real locks
38
+ * for its SQLite tables and its singleton socket, and the WSL-side directories
39
+ * Windows sees through the interop mount (9P) cannot carry them: a profile
40
+ * rooted there creates every table as a zero-byte file, never answers the
41
+ * singleton lock, and shows "an error occurred while opening your profile" on
42
+ * every launch (measured live 2026-10-04 against Chrome 154). "" answers when
43
+ * LOCALAPPDATA is not there.
44
+ */
45
+ export declare function windowsChromeProfileDir(localAppData: unknown, leaf?: string): string;
46
+ /**
47
+ * Resolves `%LOCALAPPDATA%` on the Windows side through the Known Folder API
48
+ * (never the inherited environment — the interop hand-off drops it, so
49
+ * `echo %LOCALAPPDATA%` comes back empty), cached across the process:
50
+ * powershell answers it exactly once per host.
51
+ */
52
+ export declare function windowsChromeLocalAppData(): string;
53
+ /**
54
+ * The directory the Windows run roots its profile view under — the project
55
+ * whose checkout the run answers: the row-config `cwd`, else the **live
56
+ * session workspace** (the run answers to the GUI the user is driving, not to
57
+ * whatever directory `dsh web` happened to be launched from — a run rooted at
58
+ * `~` links `~/.chrome` instead of the workspace), else the host's own cwd.
59
+ * @param configCwd - the row-config `cwd`, "" when unset.
60
+ * @param sessions - the sessions service, resolved optionally.
61
+ * @param hostCwd - the host process' cwd.
62
+ */
63
+ export declare function windowsChromeProjectDir(configCwd: unknown, sessions: unknown, hostCwd: string): string;
64
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/host/windows/paths.ts"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAQxD;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACvC,MAAM,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAA4C,EACtE,UAAU,GAAE,SAAS,MAAM,EAA8B,GAC1D,MAAM,CAER;AAED;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CACxC,MAAM,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAA4C,EACtE,UAAU,GAAE,SAAS,MAAM,EAA8B,GAC1D,MAAM,EAAE,CAQV;AAKD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,SAAY,GAAG,MAAM,CAMvF;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAelD;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAmBtG"}