@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,319 @@
1
+ /**
2
+ * Host-half fixed identifiers, budgets and validation patterns.
3
+ *
4
+ * The strings are a public contract — the profile entry id is both the
5
+ * persistence key and the Web card's configuration-form key — and the budgets
6
+ * are what the README and the tests quote, so they live here once and every
7
+ * module imports rather than repeats them.
8
+ */
9
+ /**
10
+ * The profile entry id the bundle patch inserts (`cordis.patch.yml`), and the
11
+ * key every read and write of the configuration form goes through. Since dsh
12
+ * 0.2.0 the card addresses the Host through the **entry id**, not a namespace of
13
+ * its own, and `serverName` is not part of that identity. The Host reads the
14
+ * live id off its own fiber (`chromeMcpEntryId`) so a renamed row keeps
15
+ * working; this constant is what the loud failure and the log lines name.
16
+ */
17
+ export const ENTRY_ID = "mcp-chrome";
18
+ /** Environment variable that seeds the launch flags for one dsh run. */
19
+ export const FLAGS_ENV_VAR = "DSH_CHROME_MCP_FLAGS";
20
+ /**
21
+ * Flag entries are appended verbatim to the bridge argv and reach Chrome via
22
+ * a direct execve (no shell), so shell metacharacters cannot execute here.
23
+ * What must never reach argv is control characters (newlines, NULs) — they
24
+ * corrupt the argument framing, so entries may not contain any. This is the
25
+ * `extraFlags` field's own pattern: a form write naming a control character is
26
+ * refused Host-side, by the schema rather than by a `validate` hook.
27
+ */
28
+ export const CONTROL_PATTERN = /[\x00-\x1f\x7f]/u;
29
+ /**
30
+ * One `extraFlags` entry as a form write may land it: non-empty, and no control
31
+ * character. This is the field's own pattern, so the gate that refuses them is
32
+ * the **schema**, not a `validate` hook — the write path runs it Host-side, on
33
+ * every layer (a row config carrying a newline fails to resolve rather than
34
+ * reaching argv as a corrupt entry). Spaces inside a value stay allowed: a
35
+ * Windows-style path in a flag value is one argv item, never a shell word (see
36
+ * ./flags.ts `validateExtraFlags` for what the paths the form never edits —
37
+ * `DSH_CHROME_MCP_FLAGS`, the row config — still check).
38
+ */
39
+ export const EXTRA_FLAG_PATTERN = /^(?:[^\x00-\x1f\x7f]+)$/u;
40
+ /** Flags every launch carries unless the user overrides them. */
41
+ export const DEFAULT_EXTRA_FLAGS = ["--no-usage-statistics", "--no-performance-crux"];
42
+ /**
43
+ * The flags the card's **Flags WSL** control appends for a WSL ↔ Windows
44
+ * debugging setup — a fixed recommendation, not a setting and never persisted.
45
+ * The shape is what makes it actually reach the browser:
46
+ *
47
+ * - the debug port travels as `--chromeArg=--remote-debugging-port=9222`:
48
+ * the bridge's strict parser knows only its own option names, so a bare
49
+ * `--remote-debugging-port` is reported as `Unknown arguments` and dropped
50
+ * before any browser is launched; as a `chromeArg` it lands in Chrome's own
51
+ * argv and the debugging port opens (see the "Browser switches" hard
52
+ * constraint).
53
+ *
54
+ * A `--user-data-dir` entry is deliberately **not** recommended alongside it.
55
+ * The idea of carrying the profile as a project-rooted `.chrome` was measured
56
+ * to be impossible for the Windows executable: a Windows `chrome.exe` profile
57
+ * directory has to live on a Windows-local path — neither the WSL checkout
58
+ * nor the `\\wsl.localhost` mount can carry its locks (9P) — so the
59
+ * **Prelaunch Windows Chrome** run launches with its own Windows-native
60
+ * profile under `%LOCALAPPDATA%`, and the one entry this list recommends is
61
+ * the debug port the run answers on.
62
+ */
63
+ export const WSL_EXTRA_FLAGS = ["--chromeArg=--remote-debugging-port=9222"];
64
+ /** Upstream configuration docs surfaced by the client card link. */
65
+ export const CONFIGURATION_DOCS_URL = "https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/docs/configuration.md";
66
+ /** Timeout for one check subprocess (chrome executable probe). */
67
+ export const CHECK_TIMEOUT_MS = 15000;
68
+ /**
69
+ * What a Windows executable answers when no version folder sits beside it. On
70
+ * Windows a Chromium browser does not answer `--version`: it opens a window
71
+ * (or hands one to the instance already running), so it is never spawned to
72
+ * ask — the version is read off the install's own `<major>.<minor>.<build>.<patch>`
73
+ * folder instead, and an install without one answers this.
74
+ */
75
+ export const WINDOWS_VERSION_UNKNOWN = "version unknown";
76
+ /**
77
+ * How long a failed executable run waits before its one bounded retry. The
78
+ * failure this answers is not "nothing is installed here" — it is a host that
79
+ * is not ready yet at the moment the run fires (a WSL boot whose interop
80
+ * mount has not been served yet, a drive not yet mounted). Without the retry
81
+ * that answer would stand until someone fired the run again by hand.
82
+ */
83
+ export const DISCOVERY_RETRY_DELAY_MS = 15000;
84
+ /** How many retries one run chain may arm. Bounded so a machine with nothing
85
+ * installed is never probed forever — four passes span a boot window, and the
86
+ * manual trigger stays the answer beyond it. */
87
+ export const DISCOVERY_RETRY_MAX = 4;
88
+ /**
89
+ * Why a Windows `chrome.exe` on a WSL host is **never probed** — and, since the
90
+ * Windows executables this host carries *are* offered as candidates, what such a
91
+ * candidate reads as instead of a failure. The exec answers successfully — which
92
+ * is what makes the selection look healthy — but answering means *attaching to
93
+ * the Windows browser session*, and that brings a browser instance up (measured
94
+ * on WSL2 + Google Chrome 153: `chrome.exe --version` spawns the browser process
95
+ * plus its crashpad handler). No tool call could ever drive what it started (the
96
+ * debug pipes do not cross the interop boundary), so the probe buys nothing and
97
+ * costs a running browser: the check answers nothing, and the scan keeps the
98
+ * entry visible carrying this reason — as its **note**, never as a failure,
99
+ * because the **Prelaunch Windows Chrome** run drives it in connect mode.
100
+ */
101
+ export const WSL_WINDOWS_LAUNCH_ERROR = "Windows chrome.exe cannot be launched from WSL — run Prelaunch Windows Chrome to drive it in connect mode";
102
+ /** Max length of a reported error line. */
103
+ export const ERROR_CAP = 240;
104
+ /**
105
+ * Log lines the bridge emits after a lost connection recovered — clear
106
+ * the captured connection error when one shows up.
107
+ */
108
+ export const BRIDGE_RECONNECTED = /reconnected and re-synced tools/u;
109
+ /** One bridge log level: the levels the captured wrapper shadows. */
110
+ export const LOG_LEVELS = ["trace", "debug", "info", "warn", "error", "fatal"];
111
+ /**
112
+ * Bridge console-output routing modes (mirrors the reference plugin's gateway
113
+ * stderr modes). "log" redirects the spawned child's stderr into a log file;
114
+ * "console" inherits it onto the dsh console.
115
+ */
116
+ export const BRIDGE_STDERR_MODES = ["log", "console"];
117
+ /** Modes accepted by the `stderrMode` user layer: also the empty string
118
+ * ("" → follow the row config `bridgeStderr`). */
119
+ export const STDERR_MODE_FIELD_PATTERN = /^(?:log|console)?$/u;
120
+ /** Row-config `bridgeStderrLog` accepts "" (the per-spawn default) or a
121
+ * POSIX absolute path; nothing else. */
122
+ export const OPTIONAL_PATH_PATTERN = /^(?:\/[^\x00-\x1f\x7f]*|)$/u;
123
+ /**
124
+ * The connection kinds this component registers with the manager's
125
+ * `mcpConnections` service. They are the
126
+ * component: the row stands up no bridge of its own any more, every live bridge
127
+ * is one of these connections.
128
+ *
129
+ * `chrome` — the local `chrome-devtools-mcp` bridge, what the row used to start
130
+ * for itself. `chrome-windows` — the Windows browser driven through the WSL
131
+ * interop mount (the run the **Prelaunch Windows Chrome** button answers with),
132
+ * async to launch. The ids are the contract with `servers` entries; the labels
133
+ * are what the picker lists. Neither kind caps its entries and neither carries
134
+ * a composer pill.
135
+ */
136
+ export const KIND_ID_CHROME = "chrome";
137
+ export const KIND_ID_WINDOWS = "chrome-windows";
138
+ export const KIND_CHROME_LABEL = "Chrome MCP";
139
+ export const KIND_CHROME_SUMMARY = "Runs `chrome-devtools-mcp` and launches a local Chrome. The executable and the flags are picked on the connection.";
140
+ export const KIND_WINDOWS_LABEL = "Windows Chrome (WSL debug port)";
141
+ export const KIND_WINDOWS_SUMMARY = "Opens the Windows Chrome through the WSL interop mount and connects to its debugging port. WSL only.";
142
+ /**
143
+ * The keys one entry's `extra` carries for these kinds. They are a contract with
144
+ * the manager's entry editor: what the fields write is exactly what `resolve`
145
+ * reads back. `extraFlags` is a `lines` field, so its value is one flag per
146
+ * line joined by newlines (see ./kind.ts `parseFlagLines`).
147
+ */
148
+ export const KIND_FIELDS = {
149
+ executable: "executable",
150
+ extraFlags: "extraFlags",
151
+ stderrMode: "stderrMode"
152
+ };
153
+ /**
154
+ * Whether the translation of a **standalone** row config has been offered and
155
+ * turned down. It is a volatile field of this
156
+ * row — what was refused is this row's configuration, so the dismissal lives
157
+ * here and nowhere else.
158
+ */
159
+ export const MIGRATION_DISMISSED_FIELD = "migrationDismissed";
160
+ /** One entry's extra flag lines joined the way a `lines` field stores them. */
161
+ export const FLAG_LINE_SEPARATOR = "\n";
162
+ /** Why the `chrome-windows` kind refuses an entry off WSL (spec §2: not-applicable). */
163
+ export const NOT_WSL_ERROR = "This host is not a WSL instance: there is no Windows-side browser to drive — use the Chrome MCP kind instead";
164
+ /**
165
+ * `chromePath` user layer: a filesystem path or a PATH-resolved name. Nothing
166
+ * travels through a shell here either, so the only hard constraint is that no
167
+ * control character reaches it; the length cap keeps one absurd value out of
168
+ * argv and out of the row's own patch layer.
169
+ */
170
+ export const CHROME_PATH_PATTERN = /^[^\x00-\x1f\x7f]{0,4096}$/u;
171
+ /** Upper bound of the **legacy** UI-authored custom-executable MRU (oldest
172
+ * drops off). The MRU is the older shape of the saved-executables list: a host
173
+ * whose settings still carry it folds its paths into the `executables` rows the
174
+ * first time the picker scans (see ./catalog.ts `mergeEntries`), after which the
175
+ * rows are the only source of saved executables. */
176
+ export const CUSTOM_PATHS_CAP = 10;
177
+ /** Longest display name a saved-executable row may carry — the `name` half is
178
+ * UI-only (what the pill and the dropdown render), the `id` half is what goes on
179
+ * the wire. */
180
+ export const CATALOG_NAME_MAX_LENGTH = 200;
181
+ /** Upper bound of the saved-executable rows, merged-list side: the tail drops
182
+ * off, so a scan that keeps discovering new ids cannot grow the persisted
183
+ * catalog without limit. */
184
+ export const CATALOG_MAX_LENGTH = 50;
185
+ /**
186
+ * The Windows-side Chrome/Edge executables this host carries. The
187
+ * **Prelaunch Windows Chrome** button locates through them, and — on a WSL host
188
+ * only — the executable run folds the ones this machine actually carries into its
189
+ * candidate list, so the picker can name the executable the run drives. They are
190
+ * never *probed* from here (`WSL_WINDOWS_LAUNCH_ERROR`): the run drives them in
191
+ * *connect* mode, which is the only Windows path ever measured to work. The list
192
+ * is host-served logic: the card carries no copy of it.
193
+ */
194
+ export const WINDOWS_CHROME_CANDIDATES = [
195
+ "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
196
+ "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
197
+ "C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe",
198
+ "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"
199
+ ];
200
+ /** The debugging port every Windows Chrome launch carries first — kept
201
+ * coherent with the port the **Flags WSL** control recommends. */
202
+ export const WINDOWS_CHROME_PORT = 9222;
203
+ /** The debugging-port pool the run falls through when the first port is already
204
+ * carrying a listener: [first, first+1, …]. A listener answers "reachable",
205
+ * which is what makes the port's own reachability sample its in-use signal. */
206
+ export const WINDOWS_CHROME_PORT_POOL = [9222, 9223, 9224];
207
+ /**
208
+ * Ports that **only Windows ever listens on** (RPC endpoint mapper, RDP). The
209
+ * prereq check connects one of them: on a `mirrored` networkingMode host the
210
+ * connect succeeds, on a NAT host it gives up — the sample must discriminate,
211
+ * which is exactly what makes it the prereq (measured: 135/3389 CONNECTED
212
+ * under mirrored, closed ports TIME OUT, never refuse). A port that WSL might
213
+ * hold locally (445 via Samba) must never be used: it would answer reachable
214
+ * even when the Windows loopback is unreachable.
215
+ */
216
+ export const WINDOWS_CHROME_PREREQ_PORTS = [135, 3389];
217
+ /** How long to wait for the launched Windows Chrome to open its port. */
218
+ export const WINDOWS_CHROME_WAIT_MS = 10000;
219
+ /** How long one TCP reachability sample waits before calling the port
220
+ * unreachable (a NAT host's closed port times out; it never refuses). */
221
+ export const WINDOWS_CHROME_SAMPLE_MS = 1000;
222
+ /** Poll cadence while waiting for a launched Windows Chrome to bind its port. */
223
+ export const WINDOWS_CHROME_POLL_MS = 500;
224
+ /**
225
+ * The Windows-side working directory the launch runs with. Nothing depends on
226
+ * it (every argument is absolute), it only keeps relative path resolution off
227
+ * any UNC (WSL-side) path — the shape the old `cmd.exe /c start` form needed
228
+ * too (measured 2026-10-04, see .probe/windows-chrome-connect-probe.log).
229
+ */
230
+ export const WINDOWS_CHROME_START_CWD = "/mnt/c/Windows";
231
+ /** The UNC root modern WSL exports to Windows-side processes. */
232
+ export const WSL_UNC_ROOT = "\\\\wsl.localhost\\";
233
+ /**
234
+ * The Windows-side directory name the run profiles under
235
+ * (`%LOCALAPPDATA%\dsh-chrome-mcp\<.chrome|\.chrome-<port>>`). The profile
236
+ * must live on the Windows filesystem: the WSL-side directories, served to
237
+ * Windows through 9P, cannot carry the locks Chrome's SQLite tables and its
238
+ * singleton socket take — a profile rooted there opens every table as a
239
+ * zero-byte file and shows "an error occurred while opening your profile" on
240
+ * every launch (measured live 2026-10-04 against Chrome 154). The workspace
241
+ * keeps a `.chrome` view of this directory through the link the run refreshes
242
+ * (see `linkWindowsChromeProfile`).
243
+ */
244
+ export const WINDOWS_CHROME_PROFILE_DIRNAME = "dsh-chrome-mcp";
245
+ /** The connect-mode flag the button writes; its value is the debugging URL. */
246
+ export const BROWSER_URL_FLAG_PREFIX = "--browserUrl=";
247
+ /**
248
+ * The flags a brand-new Windows profile is launched with, beside the port and
249
+ * the profile directory. A fresh `--user-data-dir` IS a first run for the
250
+ * browser: Windows Chrome opens the welcome tab and the default-search-engine
251
+ * chooser on it, and in connect mode nothing clicks through it — the debugging
252
+ * session is left sitting on the FRE page. Both flags suppress that
253
+ * experience, exactly like the manual recipe the button replaces. They travel
254
+ * on the **browser's own** argv (the `start` line), never as `--chromeArg=`:
255
+ * here it is Chrome being told at launch what not to show, not the bridge
256
+ * parser (see the browser-switches bullet under Hard constraints).
257
+ */
258
+ export const WINDOWS_CHROME_FIRST_RUN_FLAGS = ["--no-first-run", "--no-default-browser-check"];
259
+ /**
260
+ * The page the Windows launch opens, package-root-relative. It is the one asset
261
+ * this plugin ships outside `lib`, and it is **read host-side**: the run renders
262
+ * it with its own answers, writes it through the interop mount next to the
263
+ * profile directory (so the Windows-side browser can actually read it), and hands
264
+ * the browser the `file:///…` URL. It exists because the honest answer to "why
265
+ * did a window just open?" is prose the argv cannot carry — and the usual
266
+ * placeholder is not an option: `example.com` carries an explicit notice against
267
+ * being used for automation and tests.
268
+ */
269
+ export const WINDOWS_CHROME_LANDING_ASSET = "assets/prelaunch-windows-chrome.html";
270
+ /** The base name of the landing file written beside each profile directory
271
+ * (`…\dsh-chrome-mcp\prelaunch-<port>.html`) — a sibling of the profile, never a
272
+ * file inside it, so it never reads as profile churn. */
273
+ export const WINDOWS_CHROME_LANDING_BASENAME = "prelaunch";
274
+ /** What one Windows Chrome run may currently be doing (the card derives its
275
+ * button state, pill muting and disabled reason from this single field).
276
+ * `"not-applicable"` is the non-WSL answer the plan asks the button to read as
277
+ * disabled-off; `"launch-failed"` and the rest are the §4 failure states. */
278
+ export const WINDOWS_CHROME_STATES = [
279
+ "off",
280
+ "launching",
281
+ "connected",
282
+ "unreachable",
283
+ "not-found",
284
+ "launch-failed",
285
+ "not-applicable"
286
+ ];
287
+ /** Schema pattern for `windowsChromeStatus.state`. */
288
+ export const WINDOWS_CHROME_STATE_PATTERN = /^(?:off|launching|connected|unreachable|not-found|launch-failed|not-applicable)$/u;
289
+ /**
290
+ * The prereq answer — the one manual step that is not the button's job
291
+ * (configuring `~/.wslconfig` is out of scope, reading/reaching it is not).
292
+ */
293
+ export const WINDOWS_CHROME_PREREQ_ERROR = "Windows Chrome needs networkingMode=mirrored in %USERPROFILE%\\.wslconfig, then wsl --shutdown: today the Windows loopback is not reachable from this WSL host";
294
+ /** Where the effective selection came from (`effectiveSource`): a `chromePath`
295
+ * written by the card (or seeded once by the host) or the row config. Nothing
296
+ * resolves on its own, so there is no "auto". */
297
+ export const EFFECTIVE_SOURCES = ["selected", "row-config"];
298
+ /**
299
+ * Environment variables WSL exports into every distro session. Their presence
300
+ * answers "are we running inside WSL?" — the first one carries the distro name,
301
+ * `WSL_INTEROP` the interop-path directory (`/run/WSL/<pid>`).
302
+ */
303
+ export const WSL_ENV_VARS = ["WSL_DISTRO_NAME", "WSL_DISTRO_LABEL", "WSL_INTEROP"];
304
+ /**
305
+ * The `binfmt_misc` registration WSL installs for PE binaries: its presence
306
+ * marks a WSL kernel. It is only the **fallback** signal — inside a host the
307
+ * launch environment is authoritative, and an empty one is an answer (see
308
+ * ./platform.ts).
309
+ */
310
+ export const WSL_INTEROP_MARKER = "/proc/sys/fs/binfmt_misc/WSLInterop";
311
+ /** Windows executables reachable through the interop mount (`/mnt/c/...`) or by
312
+ * their Windows spelling (UNC, drive letter). */
313
+ export const WINDOWS_PATH_PATTERN = /^(?:\/mnt\/[a-z]\/|\\\\[\w.-]+\\|[a-z]:[\\/])/iu;
314
+ /** The PE suffix. WSL execve's a `.exe` from any path (the Windows loader reads
315
+ * the Linux filesystem over UNC), so the suffix alone marks a Windows binary. */
316
+ export const WINDOWS_EXE_PATTERN = /\.exe$/iu;
317
+ /** Schema pattern for `effectiveSource` ("" = nothing resolved yet). */
318
+ export const EFFECTIVE_SOURCE_PATTERN = /^(?:selected|row-config)?$/u;
319
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/host/constants.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Trace one event. Never throws: diagnostics must not change behavior. */
2
+ export declare function trace(event: Record<string, unknown>): void;
3
+ //# sourceMappingURL=_trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_trace.d.ts","sourceRoot":"","sources":["../../../src/host/controller/_trace.ts"],"names":[],"mappings":"AAMA,2EAA2E;AAC3E,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAM1D"}
@@ -0,0 +1,14 @@
1
+ // TEMPORARY diagnostic: append one JSON line per traced event to a scratch
2
+ // log so a live reproduction can be inspected without a browser console.
3
+ import { appendFileSync } from "node:fs";
4
+ const PATH = "/tmp/dsh-chrome-home/plugin-trace.log";
5
+ /** Trace one event. Never throws: diagnostics must not change behavior. */
6
+ export function trace(event) {
7
+ try {
8
+ appendFileSync(PATH, `${new Date().toISOString()} ${JSON.stringify(event)}\n`);
9
+ }
10
+ catch {
11
+ // Scratch home not writable — nothing to do.
12
+ }
13
+ }
14
+ //# sourceMappingURL=_trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_trace.js","sourceRoot":"","sources":["../../../src/host/controller/_trace.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yEAAyE;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,IAAI,GAAG,uCAAuC,CAAC;AAErD,2EAA2E;AAC3E,MAAM,UAAU,KAAK,CAAC,KAA8B;IAChD,IAAI,CAAC;QACD,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnF,CAAC;IAAC,MAAM,CAAC;QACL,6CAA6C;IACjD,CAAC;AACL,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Controller — bridge switches.
3
+ *
4
+ * How a flag, executable or stderr-mode change reaches the running bridge: the
5
+ * logical argv is rebuilt through `bridgeConfig` for the current state and
6
+ * applied as a `fiber.update()`, chained on the fiber's own readiness so a
7
+ * switch that lands while the first connection is still loading actually takes
8
+ * effect (cordis restarts a fiber only from `ACTIVE`).
9
+ */
10
+ import { bridgeConfig } from "../bridge.js";
11
+ import type { BridgeStderrMode, ChromeMcpConfig } from "../types/index.js";
12
+ import type { Controller } from "./state.js";
13
+ /** The bridge's own view of one config: the ordinary passthroughs ride along
14
+ * verbatim, and the two levers the run owns — the flags list and the resolved
15
+ * selection — are handed in explicitly, so nothing here mistakes a reference for
16
+ * a value. The logical argv shape is unchanged. */
17
+ export declare function configForBridge(controller: Controller, flags: string[]): ChromeMcpConfig;
18
+ /**
19
+ * Restart the bridge connection with one built config.
20
+ *
21
+ * A cordis fiber restarts only from `ACTIVE`: an `update` issued while the
22
+ * bridge's first connection is still loading is stored but never applied (the
23
+ * load in flight resolves with the config it started with), and the update
24
+ * settles `undefined` as if it had worked — so the bridge would silently keep
25
+ * running with the argv it first spawned with. Chaining the update onto the
26
+ * fiber's own readiness (the returned thenable settles with the load) is what
27
+ * makes the switches that land while the bridge is still starting — the first
28
+ * ones the saved connect-mode flags produce — actually take effect.
29
+ */
30
+ export declare function restartBridge(controller: Controller, built: ReturnType<typeof bridgeConfig>, note: string): void;
31
+ /** Re-apply the nested bridge with one flags list; failures logged, never thrown. */
32
+ export declare function applyFlags(controller: Controller, flags: string[]): void;
33
+ /**
34
+ * Switch the effective bridge stderr mode in place — the card's "Reduce log
35
+ * output" toggle. Only the spawn wrapper changes, but that means restarting the
36
+ * bridge connection (the stderr routing is fixed at spawn); the flags and the
37
+ * executable stay exactly as they were.
38
+ */
39
+ export declare function applyStderrMode(controller: Controller, mode: BridgeStderrMode): void;
40
+ //# sourceMappingURL=bridge-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-run.d.ts","sourceRoot":"","sources":["../../../src/host/controller/bridge-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAI3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;mDAGmD;AACnD,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe,CAExF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAgBhH;AAED,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAexE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CASpF"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Controller — bridge switches.
3
+ *
4
+ * How a flag, executable or stderr-mode change reaches the running bridge: the
5
+ * logical argv is rebuilt through `bridgeConfig` for the current state and
6
+ * applied as a `fiber.update()`, chained on the fiber's own readiness so a
7
+ * switch that lands while the first connection is still loading actually takes
8
+ * effect (cordis restarts a fiber only from `ACTIVE`).
9
+ */
10
+ import { bridgeConfig } from "../bridge.js";
11
+ import { flagsSkipCheck } from "../flags.js";
12
+ import { noteStderr } from "./notes.js";
13
+ import { publishLive } from "./publish.js";
14
+ /** The bridge's own view of one config: the ordinary passthroughs ride along
15
+ * verbatim, and the two levers the run owns — the flags list and the resolved
16
+ * selection — are handed in explicitly, so nothing here mistakes a reference for
17
+ * a value. The logical argv shape is unchanged. */
18
+ export function configForBridge(controller, flags) {
19
+ return { ...controller.config, extraFlags: flags, chromePath: controller.state.runningChromePath };
20
+ }
21
+ /**
22
+ * Restart the bridge connection with one built config.
23
+ *
24
+ * A cordis fiber restarts only from `ACTIVE`: an `update` issued while the
25
+ * bridge's first connection is still loading is stored but never applied (the
26
+ * load in flight resolves with the config it started with), and the update
27
+ * settles `undefined` as if it had worked — so the bridge would silently keep
28
+ * running with the argv it first spawned with. Chaining the update onto the
29
+ * fiber's own readiness (the returned thenable settles with the load) is what
30
+ * makes the switches that land while the bridge is still starting — the first
31
+ * ones the saved connect-mode flags produce — actually take effect.
32
+ */
33
+ export function restartBridge(controller, built, note) {
34
+ void Promise.resolve(controller.bridge)
35
+ .then(() => controller.bridge.update(built.config))
36
+ .then(() => {
37
+ // A successful bridge update proves the flags landed and the
38
+ // bridge connected again — it clears the captured *connection*
39
+ // error — but it says nothing about the executable: the known
40
+ // executable-missing answer stands until a probe answers a
41
+ // version or a tool call succeeds.
42
+ if (!controller.state.live.chromeMissing)
43
+ controller.state.live.lastError = "";
44
+ publishLive(controller);
45
+ // Intentionally NOT clearing `chromeMissing`: a successful bridge
46
+ // update proves the flags took but says nothing about the
47
+ // executable.
48
+ })
49
+ .catch((error) => controller.ctx.logger.error(`chrome-devtools-mcp(${controller.config.serverName}): ${note}: ${String(error)}`));
50
+ }
51
+ /** Re-apply the nested bridge with one flags list; failures logged, never thrown. */
52
+ export function applyFlags(controller, flags) {
53
+ const { state } = controller;
54
+ state.runningFlags = flags;
55
+ // No mirror answer here: `publishLive` below re-derives it from the list the
56
+ // bridge launches with (`src/host/controller/publish.ts`), so setting it off
57
+ // this call's argument would be the same answer twice. The known-error gate
58
+ // reads the predicate directly for the same reason.
59
+ // Connect mode launches no local executable, so the known "executable
60
+ // missing" state simply does not apply while it is set.
61
+ if (flagsSkipCheck(flags))
62
+ state.live.chromeMissing = false;
63
+ publishLive(controller);
64
+ controller.ctx.logger.info(`chrome-devtools-mcp(${controller.config.serverName}): relaunching bridge with flags [${flags.join(" ")}]`);
65
+ const built = bridgeConfig(configForBridge(controller, flags), flags, state.runningStderrMode);
66
+ noteStderr(controller, built);
67
+ restartBridge(controller, built, "flags update failed");
68
+ }
69
+ /**
70
+ * Switch the effective bridge stderr mode in place — the card's "Reduce log
71
+ * output" toggle. Only the spawn wrapper changes, but that means restarting the
72
+ * bridge connection (the stderr routing is fixed at spawn); the flags and the
73
+ * executable stay exactly as they were.
74
+ */
75
+ export function applyStderrMode(controller, mode) {
76
+ const { state } = controller;
77
+ state.runningStderrMode = mode;
78
+ state.live.stderrEffective = mode;
79
+ publishLive(controller);
80
+ controller.ctx.logger.info(`chrome-devtools-mcp(${controller.config.serverName}): bridge stderr mode → "${mode}" (restarting the bridge connection)`);
81
+ const built = bridgeConfig(configForBridge(controller, state.runningFlags), state.runningFlags, mode);
82
+ noteStderr(controller, built);
83
+ restartBridge(controller, built, `bridge stderr mode switch to "${mode}" failed`);
84
+ }
85
+ //# sourceMappingURL=bridge-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-run.js","sourceRoot":"","sources":["../../../src/host/controller/bridge-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C;;;mDAGmD;AACnD,MAAM,UAAU,eAAe,CAAC,UAAsB,EAAE,KAAe;IACnE,OAAO,EAAE,GAAG,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC;AACvG,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,UAAsB,EAAE,KAAsC,EAAE,IAAY;IACtG,KAAK,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;SAClC,IAAI,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;SAClD,IAAI,CAAC,GAAG,EAAE;QACP,6DAA6D;QAC7D,+DAA+D;QAC/D,8DAA8D;QAC9D,2DAA2D;QAC3D,mCAAmC;QACnC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa;YAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QAC/E,WAAW,CAAC,UAAU,CAAC,CAAC;QACxB,kEAAkE;QAClE,0DAA0D;QAC1D,cAAc;IAClB,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,UAAU,CAAC,MAAM,CAAC,UAAU,MAAM,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1I,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,UAAU,CAAC,UAAsB,EAAE,KAAe;IAC9D,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC;IAC7B,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;IAC3B,6EAA6E;IAC7E,6EAA6E;IAC7E,4EAA4E;IAC5E,oDAAoD;IACpD,sEAAsE;IACtE,wDAAwD;IACxD,IAAI,cAAc,CAAC,KAAK,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;IAC5D,WAAW,CAAC,UAAU,CAAC,CAAC;IACxB,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,UAAU,CAAC,MAAM,CAAC,UAAU,qCAAqC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvI,MAAM,KAAK,GAAG,YAAY,CAAC,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC/F,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC9B,aAAa,CAAC,UAAU,EAAE,KAAK,EAAE,qBAAqB,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,UAAsB,EAAE,IAAsB;IAC1E,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC;IAC7B,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;IAClC,WAAW,CAAC,UAAU,CAAC,CAAC;IACxB,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,UAAU,CAAC,MAAM,CAAC,UAAU,4BAA4B,IAAI,sCAAsC,CAAC,CAAC;IACtJ,MAAM,KAAK,GAAG,YAAY,CAAC,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACtG,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC9B,aAAa,CAAC,UAAU,EAAE,KAAK,EAAE,iCAAiC,IAAI,UAAU,CAAC,CAAC;AACtF,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Controller } from "./state.js";
2
+ /**
3
+ * Register the tool-call status capture: browser-level failures surface only as
4
+ * the calling agent's tool result, never on a line, so a settled result whose
5
+ * registered name is prefixed `mcp__<id>__` for one of this component's live
6
+ * connections and carries `isError` writes the failure into the live mirror; a
7
+ * successful chrome-tool call clears both, so the card reports current health.
8
+ * A success is *evidence* — what a missing selection never produces — while an
9
+ * unrelated failure line never displaces the known executable-missing answer
10
+ * standing (the rule the old bridge-log capture followed too). The body is
11
+ * wrapped in try/catch (warn only — a capture fault must never break a tool
12
+ * call) and returns `next()` unchanged.
13
+ */
14
+ export declare function registerToolCapture(controller: Controller): void;
15
+ //# sourceMappingURL=captures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captures.d.ts","sourceRoot":"","sources":["../../../src/host/controller/captures.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAkBhE"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Controller — the tool-call result capture that reaches the live mirror.
3
+ *
4
+ * A settled browser-tool result that failed becomes the newest `lastError`,
5
+ * classified into the known "executable missing" flag so the single red status
6
+ * dot keeps its whole story. The write is a live mirror write: published through
7
+ * the references, never persisted.
8
+ *
9
+ * What the bridge-log capture used to be, the connection lines are now: every
10
+ * failure the nested fiber answers with reaches the manager's own line for the
11
+ * entry that spawned it, and the tool-call surface is the one failure path that
12
+ * never reaches any line — a browser-level problem (target closed, dialog stuck,
13
+ * protocol timeout) is returned to the calling agent and lands nowhere else.
14
+ * Hence only the tool capture survives here.
15
+ *
16
+ * The prefix rule changed with the component model: a connection publishes under
17
+ * `mcp__<entry id>__`, where the entry id is the manager's, not the row's old
18
+ * `serverName`. So the capture answers for whichever live connection of this
19
+ * component's own kinds carries the tool; a tool outside this component's
20
+ * namespace never touches the mirror.
21
+ */
22
+ import { captureToolResults } from "@comecaramelos/dsh-ancesters/host";
23
+ import { isChromeMissing } from "../status.js";
24
+ import { publishLive } from "./publish.js";
25
+ /**
26
+ * Register the tool-call status capture: browser-level failures surface only as
27
+ * the calling agent's tool result, never on a line, so a settled result whose
28
+ * registered name is prefixed `mcp__<id>__` for one of this component's live
29
+ * connections and carries `isError` writes the failure into the live mirror; a
30
+ * successful chrome-tool call clears both, so the card reports current health.
31
+ * A success is *evidence* — what a missing selection never produces — while an
32
+ * unrelated failure line never displaces the known executable-missing answer
33
+ * standing (the rule the old bridge-log capture followed too). The body is
34
+ * wrapped in try/catch (warn only — a capture fault must never break a tool
35
+ * call) and returns `next()` unchanged.
36
+ */
37
+ export function registerToolCapture(controller) {
38
+ // The listener, the prefix match, the note and the never-break-a-tool-call
39
+ // wrapping are ancestros' `captureToolResults`; the prefixes are asked on
40
+ // every call, because the live connections come and go.
41
+ captureToolResults(controller.ctx, {
42
+ name: `dsh-chrome-mcp(${controller.config.serverName})`,
43
+ prefix: (name) => ownedToolPrefix(controller).some((prefix) => name.startsWith(prefix)),
44
+ onResult: (note) => {
45
+ if (note === null) {
46
+ controller.state.live.lastError = "";
47
+ controller.state.live.chromeMissing = false;
48
+ }
49
+ else if (isChromeMissing(note) || !controller.state.live.chromeMissing) {
50
+ controller.state.live.lastError = note;
51
+ controller.state.live.chromeMissing = isChromeMissing(note);
52
+ }
53
+ publishLive(controller);
54
+ }
55
+ });
56
+ }
57
+ /** The namespaces whose tool calls belong to this component: every live
58
+ * connection of the component's own kinds answers under its entry id. A tool
59
+ * named anywhere else (another component's connection, a core stdio entry) is
60
+ * simply not this component's business. */
61
+ function ownedToolPrefixes(controller) {
62
+ const service = controller.state.connections;
63
+ if (service === void 0)
64
+ return [];
65
+ const prefixes = [];
66
+ try {
67
+ for (const entry of service.entries()) {
68
+ if (entry.kind !== "chrome" && entry.kind !== "chrome-windows")
69
+ continue;
70
+ prefixes.push(`mcp__${entry.id}__`);
71
+ }
72
+ }
73
+ catch {
74
+ return [];
75
+ }
76
+ return prefixes;
77
+ }
78
+ function ownedToolPrefix(controller) {
79
+ const prefixes = ownedToolPrefixes(controller);
80
+ // The row's own `serverName` still names the tools while the connection was
81
+ // answered under it (the migration-era config), so a captured tool under
82
+ // that namespace is also ours.
83
+ return prefixes.length > 0 ? prefixes : [`mcp__${controller.config.serverName}__`];
84
+ }
85
+ //# sourceMappingURL=captures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captures.js","sourceRoot":"","sources":["../../../src/host/controller/captures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAsB;IACtD,2EAA2E;IAC3E,0EAA0E;IAC1E,wDAAwD;IACxD,kBAAkB,CAAC,UAAU,CAAC,GAAY,EAAE;QACxC,IAAI,EAAE,kBAAkB,UAAU,CAAC,MAAM,CAAC,UAAU,GAAG;QACvD,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/F,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;YACf,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAChB,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;gBACrC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAChD,CAAC;iBAAM,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;gBACvC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;YAChE,CAAC;YACD,WAAW,CAAC,UAAU,CAAC,CAAC;QAC5B,CAAC;KACJ,CAAC,CAAC;AACP,CAAC;AAED;;;2CAG2C;AAC3C,SAAS,iBAAiB,CAAC,UAAsB;IAC7C,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC;IAC7C,IAAI,OAAO,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YACpC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB;gBAAE,SAAS;YACzE,QAAQ,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QACxC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,SAAS,eAAe,CAAC,UAAsB;IAC3C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAC/C,4EAA4E;IAC5E,yEAAyE;IACzE,+BAA+B;IAC/B,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,UAAU,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC;AACvF,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Controller } from "./state.js";
2
+ /** Route one configuration-form commit. */
3
+ export declare function onFormCommit(controller: Controller): void;
4
+ //# sourceMappingURL=commits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commits.d.ts","sourceRoot":"","sources":["../../../src/host/controller/commits.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CA8FzD"}