@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,196 @@
1
+ /**
2
+ * The single zod `Config` of the plugin row.
3
+ *
4
+ * Since dsh 0.2.0 the Web GUI card edits the **row configuration** through the
5
+ * profile's configuration form — there is no separate `settings.yaml` namespace
6
+ * and no base layer to publish state over. So one schema carries everything the
7
+ * card reads and writes, and every field the card touches is declared
8
+ * `.volatile()`: a volatile field is editable through the form without
9
+ * remounting the plugin, its user layer rides the profile patch instead of
10
+ * `settings.yaml`, and a live value the Host commits never reaches the patch
11
+ * (the form write strips the volatile fields out of the stored layer before
12
+ * merging).
13
+ *
14
+ * Ordinary fields (`serverName`, `command`, `package`, `chromePaths`, `env`,
15
+ * `cwd`, `toolCallTimeoutMs`, `maxInstructionBytes`, `failOnStartupError`,
16
+ * `reconnect`, `bridgeStderrLog`) are composition-only: the card reads them, it
17
+ * never edits them, and a form write naming one of them is refused by
18
+ * dsh-settings.
19
+ *
20
+ * Host-resolved fields carry the live value in the reference, so the Host
21
+ * publishes them through the live mirror (dsh-ancesters `createLiveMirror`) — never with the form.
22
+ */
23
+ import z from "@deepseek-ai/schemastery";
24
+ import { CHROME_PATH_PATTERN, DEFAULT_EXTRA_FLAGS, EFFECTIVE_SOURCE_PATTERN, EXTRA_FLAG_PATTERN, OPTIONAL_PATH_PATTERN, STDERR_MODE_FIELD_PATTERN, WINDOWS_CHROME_STATE_PATTERN, WSL_EXTRA_FLAGS } from "./constants.js";
25
+ import { defaultChromePaths } from "./discovery/index.js";
26
+ /** Reconnect policy passthrough; mirrors dsh-mcp-client's schema. */
27
+ const Reconnect = z.object({
28
+ enabled: z.boolean().default(true),
29
+ initialDelayMs: z.number().min(1).max(600000).default(500),
30
+ maxDelayMs: z.number().min(1).max(600000).default(30000),
31
+ maxAttempts: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER).default(10)
32
+ });
33
+ /**
34
+ * One saved-executable catalog row: `id` is the path that goes on the wire
35
+ * (`--executablePath=<id>`), `name` the label the user chose for the UI
36
+ * ("" = render the path). User layer.
37
+ */
38
+ const ExecutableEntry = z.object({
39
+ id: z.string().default("").pattern(CHROME_PATH_PATTERN),
40
+ name: z.string().default("")
41
+ });
42
+ /** What one saved row's probe answered with, keyed by its id (`path`): the
43
+ * `--version` line, the failure that makes it not runnable, and the note that
44
+ * explains an executable this host offers without probing (`note` is never a
45
+ * failure — the one case is a Windows executable under WSL, driven by the
46
+ * **Prelaunch Windows Chrome** run). */
47
+ const ExecutableStatus = z.object({
48
+ path: z.string().default("").pattern(CHROME_PATH_PATTERN),
49
+ version: z.string().default(""),
50
+ error: z.string().default(""),
51
+ note: z.string().default("")
52
+ });
53
+ /** The served Windows-Chrome state: what the **Prelaunch Windows Chrome** run is
54
+ * doing, the debugging port it settled on (0 = none) and the failure line. */
55
+ const WindowsChromeStatus = z.object({
56
+ state: z.string().pattern(WINDOWS_CHROME_STATE_PATTERN).default("off"),
57
+ port: z.number().default(0),
58
+ error: z.string().default("")
59
+ });
60
+ /**
61
+ * The plugin row's configuration, and the configuration form the Web GUI card
62
+ * edits. Every `.volatile()` field below is live: a user edit lands in the
63
+ * profile patch and commits without a remount, and the Host's own live answers
64
+ * ride the same references without ever being persisted.
65
+ */
66
+ export const Config = z.object({
67
+ serverName: z.string().pattern(/^[A-Za-z0-9_-]{1,32}$/).default("chrome"),
68
+ command: z.string().default("npx"),
69
+ package: z.string().min(1).default("chrome-devtools-mcp@latest"),
70
+ /** Flags appended after `npx -y <package>`; the card's last UI edit. The
71
+ * field's own pattern is what refuses them (an entry that carries a control
72
+ * character never resolves, so a write is refused Host-side rather than
73
+ * landing in argv); an executable-pinning flag is rejected by the Host fold
74
+ * because the executable is picked below. */
75
+ extraFlags: z.array(z.string().pattern(EXTRA_FLAG_PATTERN)).default(DEFAULT_EXTRA_FLAGS).volatile(),
76
+ chromePaths: z.array(String).default(defaultChromePaths()),
77
+ env: z.dict(String).default({}),
78
+ cwd: z.string().default(""),
79
+ toolCallTimeoutMs: z.number().default(60000),
80
+ /** Ceiling for the bridge's server instructions (UTF-8 bytes, attribution
81
+ * included); an oversized description rejects the connection. Mirrors
82
+ * `dsh-mcp-client`'s own field and default (32768) — a passthrough for a
83
+ * server whose instructions run longer than the cap. */
84
+ maxInstructionBytes: z.number().step(1).min(1).default(32768),
85
+ failOnStartupError: z.boolean().default(false),
86
+ reconnect: Reconnect,
87
+ /** Bridge console-output routing: "log" (default) redirects the spawned
88
+ * npx child's inherited stderr into a per-spawn log file so its progress
89
+ * / startup lines stay out of the dsh console; "console" inherits it
90
+ * (debug). The card's "Reduce log output" toggle (`stderrMode`) overrides
91
+ * this. See {@link buildBridgeSpawn}. */
92
+ bridgeStderr: z.union([z.const("log"), z.const("console")]).default("log"),
93
+ /** Log path override for "log" mode; "" = auto (see
94
+ * {@link bridgeStderrLogPath}). Absolute paths only. */
95
+ bridgeStderrLog: z.string().default("").pattern(OPTIONAL_PATH_PATTERN),
96
+ // ---- user-authored, form-editable -------------------------------------
97
+ /**
98
+ * The executable the bridge launches with: picked in the picker (a saved
99
+ * row's `id`) or seeded once by the Host's first scan. "" = nothing
100
+ * resolved yet — there is no auto state to fall back to.
101
+ */
102
+ chromePath: z.string().default("").pattern(CHROME_PATH_PATTERN).volatile(),
103
+ /** The picker's saved rows — `{ id: path, name: label }`, user-authored. The
104
+ * Host re-normalizes (trim, dedupe, caps) on every read, and a scan merges
105
+ * what it discovers into them without dropping a name the user chose. */
106
+ executables: z.array(ExecutableEntry).default([]).volatile(),
107
+ /** The ids of saved rows the user dropped. Every run folds what it found
108
+ * back into the rows, and the found list keeps answering a path the user
109
+ * just deleted, so without this record a dropped row stood back up on the
110
+ * very run the deletion queued (measured live 2026-10-12: the (x86)
111
+ * Windows-executable row read as a delete that never landed). Merge steps
112
+ * skip every id standing here; a list write carrying the id again clears
113
+ * it. Host-authored: the card never edits this field. */
114
+ droppedExecutables: z.array(z.string().default("").pattern(CHROME_PATH_PATTERN)).default([]).volatile(),
115
+ /**
116
+ * **Legacy** MRU of hand-typed executables, newest first. The saved rows
117
+ * replace it: a Host whose profile still carries it folds its paths into
118
+ * the rows during the first scan (see ./catalog.ts `mergeEntries`), so the
119
+ * field is read once and never written again.
120
+ */
121
+ chromeCustomPaths: z.array(z.string().default("").pattern(CHROME_PATH_PATTERN)).default([]).volatile(),
122
+ /**
123
+ * The card's "Reduce log output" toggle: "log" captures the bridge's
124
+ * stderr into the log file, "console" echoes it (debug). "" follows the
125
+ * row-config `bridgeStderr`.
126
+ */
127
+ stderrMode: z.string().default("").pattern(STDERR_MODE_FIELD_PATTERN).volatile(),
128
+ /** The mode the bridge actually routes console output through — the UI
129
+ * toggle when it states one, else the row config. Mirrored live so the
130
+ * toggle never reads a phantom state (see `resolveStderrMode`). */
131
+ stderrEffective: z.union([z.const("log"), z.const("console")]).default("log").volatile(),
132
+ /** Written by the card's **Fetch executables** button; the Host reacts by
133
+ * re-probing the saved rows and merging what it finds back into them. */
134
+ refreshExecutablesNonce: z.number().default(0).volatile(),
135
+ /** Written by the card's **Prelaunch Windows Chrome** button; the Host
136
+ * reacts by running the Windows launch: locate the Windows Chrome, prove
137
+ * the mirrored-loopback prereq, launch it with a debugging port, and write
138
+ * the `--browserUrl` connect entry that leaves the bridge in connect mode. */
139
+ openWindowsChromeNonce: z.number().default(0).volatile(),
140
+ /**
141
+ * Whether the translation of this row's **standalone** configuration was
142
+ * offered and turned down. Host-authored:
143
+ * the card never edits it — only the proposal's dismiss action does.
144
+ */
145
+ migrationDismissed: z.boolean().default(false).volatile(),
146
+ // ---- Host-published live state ----------------------------------------
147
+ /** Last check/connection failure, human-readable; empty when healthy. */
148
+ lastError: z.string().default("").volatile(),
149
+ /** Known error: the last failure was "no Chrome executable detected". */
150
+ chromeMissing: z.boolean().default(false).volatile(),
151
+ /** Executable-run counter (success or failure); completion signal for every
152
+ * executable action the card can take. */
153
+ executableDiscoveryRevision: z.number().default(0).volatile(),
154
+ /** The version the **selected** executable answered with; "" when nothing
155
+ * answered — nothing picked, a connect mode, or a blocked path. */
156
+ chromeVersion: z.string().default("").volatile(),
157
+ /** Per-row probe status keyed by path: the version the row answered with,
158
+ * and the failure for a row that is present but not runnable (or blocked). */
159
+ executableStatus: z.array(ExecutableStatus).default([]).volatile(),
160
+ /** The path the bridge actually launches with ("" when nothing is fixed). */
161
+ effectiveChromePath: z.string().default("").pattern(CHROME_PATH_PATTERN).volatile(),
162
+ /** Where `effectiveChromePath` came from — picked (`"selected"`), row config
163
+ * (`"row-config"`) or nothing yet (""). */
164
+ effectiveSource: z.string().default("").pattern(EFFECTIVE_SOURCE_PATTERN).volatile(),
165
+ /** The canonical default extra-flags list — the list the card's **Restore
166
+ * defaults** control appends to what the editor holds. Mirror of
167
+ * `DEFAULT_EXTRA_FLAGS`, served so the card carries no copy of it. */
168
+ defaultExtraFlags: z.array(String).default(DEFAULT_EXTRA_FLAGS).volatile(),
169
+ /** The recommended WSL ↔ Windows extra-flags list — the list the card's
170
+ * **Flags WSL** control appends, missing entries only. Mirror of
171
+ * `WSL_EXTRA_FLAGS`, served so the card carries no copy of it. */
172
+ wslExtraFlags: z.array(String).default(WSL_EXTRA_FLAGS).volatile(),
173
+ /** True while this Host runs under WSL and the selected executable is a
174
+ * Windows binary — the state the card's notice explains (see ./platform.ts). */
175
+ wslWindowsExecutable: z.boolean().default(false).volatile(),
176
+ /** What the **Prelaunch Windows Chrome** run is doing — the single field
177
+ * the card derives the button's state, its disabled reason and the pill's
178
+ * connect-mode muting from. Every half (locate, prereq, launch, port) lives
179
+ * Host-side (./windows/), so the card carries no list of Windows paths or
180
+ * reachability rules. */
181
+ windowsChromeStatus: WindowsChromeStatus.default({ state: "off", port: 0, error: "" }).volatile(),
182
+ /** True while the bridge launches with a connect-mode flag (`--browserUrl`
183
+ * / `--wsEndpoint`): no local executable is then launched or probed, so the
184
+ * card mutes the picker. */
185
+ carriesConnectionMode: z.boolean().default(false).volatile(),
186
+ /** The flags a live connection of this component's own kinds actually
187
+ * launches with — mirrored from the last `resolve`, not from any layer, so
188
+ * the machine page states what is running rather than what was last
189
+ * configured. Empty while nothing resolves. */
190
+ runningFlags: z.array(String).default([]).volatile(),
191
+ /** The note the last live connection answered with — where its console
192
+ * output goes, or the Windows URL it connected to. "" when the answer was
193
+ * silent. */
194
+ runningNote: z.string().default("").volatile()
195
+ });
196
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/host/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { ChromeMcpController } from "./controller/index.js";
2
+ import type { PluginContext } from "./types/index.js";
3
+ /**
4
+ * The profile entry id this instance is keyed by, read off its own loader entry.
5
+ * Throws when the plugin was not started as a profile entry: the id is the key
6
+ * every read and write goes through, so inventing one would alias (or silently
7
+ * address nothing) instead of failing loud.
8
+ * @param ctx - plugin context.
9
+ */
10
+ export declare function chromeMcpEntryId(ctx: PluginContext): string;
11
+ /**
12
+ * Attach the row's configuration form to one controller: resolve the entry id,
13
+ * keep the auto page off, and route the commits the form produces.
14
+ *
15
+ * Registration rides one fiber effect for the same reason `tool.ts` registers
16
+ * lazily: the disposer has to leave with the instance, and an HMR reload must not
17
+ * leave a prior instance still configuring (the second `configure` for one fiber
18
+ * throws). A host that is not a profile entry gets a loud error and no form; its
19
+ * row config keeps driving the bridge exactly as a row-only config always did.
20
+ * @param ctx - plugin context.
21
+ * @param controller - the live state the form drives.
22
+ */
23
+ export declare function installChromeMcpForm(ctx: PluginContext, controller: ChromeMcpController): void;
24
+ /** Every live-only key a Host write-back clears from the stored row (exported
25
+ * here for the tests and for the write paths that carry the `unset` ops — the
26
+ * same shape the reference's `settings.ts` keeps). */
27
+ export declare const LIVE_MIRROR_KEYS: readonly string[];
28
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/host/settings.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAK,EAAiB,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAoBrE;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAU3D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,mBAAmB,GAAG,IAAI,CAiB9F;AAED;;sDAEsD;AACtD,eAAO,MAAM,gBAAgB,mBAAmB,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Host half — the configuration form.
3
+ *
4
+ * Since dsh 0.2.0 the card edits the **row configuration** through the profile's
5
+ * configuration form: one `Config` (./schema.ts), keyed by the row's profile
6
+ * entry id. So this module no longer installs a namespace — it attaches the row
7
+ * to the form and routes what the form answers into the controller. Three things
8
+ * it owns:
9
+ *
10
+ * - **Identity.** Everything reads and writes by the profile **entry id** read
11
+ * off this fiber's own loader entry (`chromeMcpEntryId`). It is not a namespace
12
+ * and never derived from `serverName`: two instances would collide on the same
13
+ * row, so an instance that is not a profile entry says so loudly rather than
14
+ * inventing a key of its own.
15
+ * - **The auto page stays off.** `settings.configure({ auto: false }, fiber)`
16
+ * keeps the Host from standing up a generated page while the card owns the
17
+ * row's page — and it is a *disposable* call that throws the second time for
18
+ * one fiber, so it rides one fiber effect and disposes with it (verified live,
19
+ * .probe/MIGRATION-CONTRACT.md §2e: `auto` only decides the generated page, and
20
+ * the entry stays fully described either way).
21
+ * - **Commit routing.** A form commit lands as a volatile commit on this fiber,
22
+ * which the loader reports as `loader/volatile-update` carrying the paths it
23
+ * touched. Only the *user-authored* paths mean anything to the running bridge,
24
+ * so those are what route — and that same filter is what keeps a live publish
25
+ * (which only ever commits live fields) from re-entering the router.
26
+ */
27
+ import { attachSettingsForm } from "@comecaramelos/dsh-ancesters/host";
28
+ import { ENTRY_ID } from "./constants.js";
29
+ import { liveMirrorKeys } from "./values.js";
30
+ /** The fields the card edits. A commit that touches nothing here changes nothing
31
+ * the running bridge does, which is what keeps a live publish out of the router. */
32
+ const USER_FIELDS = new Set([
33
+ "extraFlags",
34
+ "chromePath",
35
+ "executables",
36
+ "chromeCustomPaths",
37
+ "stderrMode",
38
+ "refreshExecutablesNonce",
39
+ "openWindowsChromeNonce"
40
+ ]);
41
+ /**
42
+ * The profile entry id this instance is keyed by, read off its own loader entry.
43
+ * Throws when the plugin was not started as a profile entry: the id is the key
44
+ * every read and write goes through, so inventing one would alias (or silently
45
+ * address nothing) instead of failing loud.
46
+ * @param ctx - plugin context.
47
+ */
48
+ export function chromeMcpEntryId(ctx) {
49
+ const fiber = ctx.fiber;
50
+ const id = fiber?.entry?.options?.id;
51
+ if (typeof id !== "string" || id === "") {
52
+ throw new Error(`dsh-chrome-mcp: this instance is not a profile entry, so the configuration form has no entry id to address it by ` +
53
+ `(the bundle patch inserts \`id: "${ENTRY_ID}"\` — a bare ctx.plugin() mount has no form)`);
54
+ }
55
+ return id;
56
+ }
57
+ /**
58
+ * Attach the row's configuration form to one controller: resolve the entry id,
59
+ * keep the auto page off, and route the commits the form produces.
60
+ *
61
+ * Registration rides one fiber effect for the same reason `tool.ts` registers
62
+ * lazily: the disposer has to leave with the instance, and an HMR reload must not
63
+ * leave a prior instance still configuring (the second `configure` for one fiber
64
+ * throws). A host that is not a profile entry gets a loud error and no form; its
65
+ * row config keeps driving the bridge exactly as a row-only config always did.
66
+ * @param ctx - plugin context.
67
+ * @param controller - the live state the form drives.
68
+ */
69
+ export function installChromeMcpForm(ctx, controller) {
70
+ // The mechanics — the entry id read off this fiber (loud when it is not a
71
+ // profile entry), the generated page kept off once per fiber and disposed
72
+ // with it, and the commit filter on `loader/volatile-update` — are
73
+ // ancestros' `attachSettingsForm`. A commit naming a **user** field routes
74
+ // (flags, the executable, the saved rows, the toggle, the two triggers); a
75
+ // commit naming only **live** fields routes nothing. The mirror's own
76
+ // re-assert after a reset is the live mirror's business (./controller/
77
+ // publish.ts), not this router's.
78
+ attachSettingsForm(ctx, {
79
+ name: `dsh-chrome-mcp(${controller.config.serverName})`,
80
+ userFields: [...USER_FIELDS],
81
+ liveKeys: liveMirrorKeys(),
82
+ onAttach: (form) => controller.attachForm(form),
83
+ onDetach: () => controller.detachForm(),
84
+ onCommit: () => controller.onFormCommit()
85
+ });
86
+ }
87
+ /** Every live-only key a Host write-back clears from the stored row (exported
88
+ * here for the tests and for the write paths that carry the `unset` ops — the
89
+ * same shape the reference's `settings.ts` keeps). */
90
+ export const LIVE_MIRROR_KEYS = liveMirrorKeys();
91
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/host/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;oFACoF;AACpF,MAAM,WAAW,GAAG,IAAI,GAAG,CAAS;IAChC,YAAY;IACZ,YAAY;IACZ,aAAa;IACb,mBAAmB;IACnB,YAAY;IACZ,yBAAyB;IACzB,wBAAwB;CAC3B,CAAC,CAAC;AAOH;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAkB;IAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAuD,CAAC;IAC1E,MAAM,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;IACrC,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACX,mHAAmH;YAC/G,oCAAoC,QAAQ,8CAA8C,CACjG,CAAC;IACN,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAkB,EAAE,UAA+B;IACpF,0EAA0E;IAC1E,0EAA0E;IAC1E,mEAAmE;IACnE,2EAA2E;IAC3E,2EAA2E;IAC3E,sEAAsE;IACtE,uEAAuE;IACvE,kCAAkC;IAClC,kBAAkB,CAAC,GAAY,EAAE;QAC7B,IAAI,EAAE,kBAAkB,UAAU,CAAC,MAAM,CAAC,UAAU,GAAG;QACvD,UAAU,EAAE,CAAC,GAAG,WAAW,CAAC;QAC5B,QAAQ,EAAE,cAAc,EAAE;QAC1B,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAgC,CAAC;QAC3E,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE;QACvC,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,YAAY,EAAE;KAC5C,CAAC,CAAC;AACP,CAAC;AAED;;sDAEsD;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,EAAE,CAAC"}
@@ -0,0 +1,25 @@
1
+ /** First non-empty line of a text block, capped. */
2
+ export declare function firstLine(text: unknown, cap?: number): string;
3
+ /**
4
+ * Recognizes the known, developer-actionable error "no Chrome executable was
5
+ * detected": our own ENOENT/discovery lines, the upstream executable-discovery
6
+ * failures ("Could not find Google Chrome executable for channel 'stable'
7
+ * at:", puppeteer's configured-path miss), and the umbrella launch failure
8
+ * chrome-devtools-mcp surfaces when it cannot start a browser binary. Upstream
9
+ * starts the browser lazily (on the first tool call), so the check probe is
10
+ * what surfaces the state without any tool call. Anything else is a generic
11
+ * check or connection error.
12
+ * @param text - an error message (or first line thereof).
13
+ * @returns true when the failure is the known executable-missing state.
14
+ */
15
+ export declare function isChromeMissing(text: unknown): boolean;
16
+ /**
17
+ * Summarize one chrome-tool call result for the card's status line — the rule
18
+ * is ancestros' (`host/status.toolResultNote`): failed calls answer
19
+ * "<tool> failed: <first text line>", successes `null` (the caller clears the
20
+ * stored error). Tool-level errors (browser unreachable, "Target closed", …)
21
+ * are returned to the calling agent and never reach a bridge line, so the
22
+ * tool-call capture is the only place they surface.
23
+ */
24
+ export { toolResultNote } from "@comecaramelos/dsh-ancesters/host";
25
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/host/status.ts"],"names":[],"mappings":"AAUA,oDAAoD;AACpD,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,GAAE,MAAkB,GAAG,MAAM,CAKxE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAQtD;AAED;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Error classification and status notes — the human-readable half.
3
+ *
4
+ * Every capture path (check failure, bridge log line, tool-call result) ends
5
+ * in one capped line written to the live mirror's `lastError`; `isChromeMissing`
6
+ * decides whether that line is the known, developer-actionable "no Chrome
7
+ * executable detected" state (`chromeMissing`) or a generic failure.
8
+ */
9
+ import { ERROR_CAP } from "./constants.js";
10
+ /** First non-empty line of a text block, capped. */
11
+ export function firstLine(text, cap = ERROR_CAP) {
12
+ const line = String(text ?? "")
13
+ .split(/\r?\n/u)
14
+ .find((candidate) => candidate.trim() !== "") ?? "";
15
+ return line.trim().slice(0, cap);
16
+ }
17
+ /**
18
+ * Recognizes the known, developer-actionable error "no Chrome executable was
19
+ * detected": our own ENOENT/discovery lines, the upstream executable-discovery
20
+ * failures ("Could not find Google Chrome executable for channel 'stable'
21
+ * at:", puppeteer's configured-path miss), and the umbrella launch failure
22
+ * chrome-devtools-mcp surfaces when it cannot start a browser binary. Upstream
23
+ * starts the browser lazily (on the first tool call), so the check probe is
24
+ * what surfaces the state without any tool call. Anything else is a generic
25
+ * check or connection error.
26
+ * @param text - an error message (or first line thereof).
27
+ * @returns true when the failure is the known executable-missing state.
28
+ */
29
+ export function isChromeMissing(text) {
30
+ const message = String(text ?? "");
31
+ return (/chrome executable not found/iu.test(message) ||
32
+ /could not find (?:google )?chrome(?: executable)?/iu.test(message) ||
33
+ /browser was not found at the configured executablePath/iu.test(message) ||
34
+ /failed to launch the browser process/iu.test(message));
35
+ }
36
+ /**
37
+ * Summarize one chrome-tool call result for the card's status line — the rule
38
+ * is ancestros' (`host/status.toolResultNote`): failed calls answer
39
+ * "<tool> failed: <first text line>", successes `null` (the caller clears the
40
+ * stored error). Tool-level errors (browser unreachable, "Target closed", …)
41
+ * are returned to the calling agent and never reach a bridge line, so the
42
+ * tool-call capture is the only place they surface.
43
+ */
44
+ export { toolResultNote } from "@comecaramelos/dsh-ancesters/host";
45
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/host/status.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,oDAAoD;AACpD,MAAM,UAAU,SAAS,CAAC,IAAa,EAAE,MAAc,SAAS;IAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;SAC1B,KAAK,CAAC,QAAQ,CAAC;SACf,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;IACxD,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,IAAa;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACnC,OAAO,CACH,+BAA+B,CAAC,IAAI,CAAC,OAAO,CAAC;QAC7C,qDAAqD,CAAC,IAAI,CAAC,OAAO,CAAC;QACnE,0DAA0D,CAAC,IAAI,CAAC,OAAO,CAAC;QACxE,wCAAwC,CAAC,IAAI,CAAC,OAAO,CAAC,CACzD,CAAC;AACN,CAAC;AAED;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Host half — the **prelaunch_windows_chrome** tool.
3
+ *
4
+ * The second trigger of the same Windows Chrome run the card button drives: the
5
+ * run itself lives in ./windows/, the queueing + state mirror in the
6
+ * controller, and registering the tool is plain wiring — the definition adds
7
+ * no logic of its own, it just hands the model the button's action (the run
8
+ * answers through `windowsChromeStatus`, exactly like a click does).
9
+ *
10
+ * With the component model the run feeds connections, not a bridge this row
11
+ * owns: live `chrome-windows` connections are refreshed against the run
12
+ * (idempotent — the live URL rides into the run's `currentFlags`), and a run
13
+ * that connected without one says what would drive it.
14
+ *
15
+ * The two registration rules this module keeps:
16
+ *
17
+ * - The tools service is injected **at mount time**, not statically: the
18
+ * connections' nested mcp-client fibers are what publish the bridge's tools,
19
+ * so a static `inject: ["tools"]` on this plugin would risk the same
20
+ * load-order cycle the tool-result listener bullet warns about. `ctx.inject`
21
+ * resolves the service lazily, which is what the listener idiom already
22
+ * relies on.
23
+ * - The registration lives on one fiber effect. An HMR reload disposes the
24
+ * old instance's effect first, so the tool re-registers cleanly instead of
25
+ * colliding with a still-held global registration; the effect body guards
26
+ * against the tools service resolving twice for one instance.
27
+ */
28
+ import type { ChromeMcpController } from "./controller/index.js";
29
+ import type { PluginContext } from "./types/index.js";
30
+ /** Model-facing name, registered globally by this host half. */
31
+ export declare const PRELAUNCH_WINDOWS_CHROME_NAME = "prelaunch_windows_chrome";
32
+ /** One `{type:"text"}` content block — the only block the render projects. */
33
+ type ToolContent = {
34
+ type: "text";
35
+ text: string;
36
+ };
37
+ /**
38
+ * Structural surface of the harness tools service, typed here the way the
39
+ * shell-module stubs are: the service lives in the loader's module table, and
40
+ * this module only needs to hand it a definition.
41
+ */
42
+ interface ToolDefinitionLike {
43
+ name: string;
44
+ description: string;
45
+ parameters: Record<string, unknown>;
46
+ output: {
47
+ schema: unknown;
48
+ render(args: unknown, value: unknown): ToolContent[];
49
+ };
50
+ execute(): Promise<{
51
+ text: string;
52
+ }>;
53
+ }
54
+ /** The one-argument-free definition: all decisions are the host's. */
55
+ export declare function prelaunchWindowsChromeDefinition(controller: ChromeMcpController): ToolDefinitionLike;
56
+ /**
57
+ * Register the tool on one fiber effect, resolving the tools service lazily. A
58
+ * host without one (no model assembled) simply gets no registration — the card
59
+ * button stays the only trigger.
60
+ * @param ctx - plugin context.
61
+ * @param controller - the live state whose run this tool drives.
62
+ */
63
+ export declare function installPrelaunchWindowsChromeTool(ctx: PluginContext, controller: ChromeMcpController): void;
64
+ export {};
65
+ //# sourceMappingURL=tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/host/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,gEAAgE;AAChE,eAAO,MAAM,6BAA6B,6BAA6B,CAAC;AAExE,8EAA8E;AAC9E,KAAK,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD;;;;GAIG;AACH,UAAU,kBAAkB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,MAAM,EAAE;QACJ,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,WAAW,EAAE,CAAC;KACxD,CAAC;IACF,OAAO,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxC;AAKD,sEAAsE;AACtE,wBAAgB,gCAAgC,CAAC,UAAU,EAAE,mBAAmB,GAAG,kBAAkB,CAqBpG;AAED;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,mBAAmB,GAAG,IAAI,CAgB3G"}
@@ -0,0 +1,52 @@
1
+ /** Model-facing name, registered globally by this host half. */
2
+ export const PRELAUNCH_WINDOWS_CHROME_NAME = "prelaunch_windows_chrome";
3
+ /** The one-argument-free definition: all decisions are the host's. */
4
+ export function prelaunchWindowsChromeDefinition(controller) {
5
+ return {
6
+ name: PRELAUNCH_WINDOWS_CHROME_NAME,
7
+ description: "Open the Windows-side Chrome on WSL — the same run the card's Prelaunch Windows Chrome button drives. " +
8
+ "Takes no arguments: the host launches the Windows executable the picker selected when that selection is a Windows one (otherwise it locates one), " +
9
+ "checks that the Windows loopback is reachable from this WSL host " +
10
+ "(networkingMode=mirrored is a manual Windows-side setting it only reads), picks the first free debugging port, launches with a " +
11
+ "Windows-side profile under LOCALAPPDATA linked into the workspace as .chrome, opens a packaged page in that window explaining " +
12
+ "that it was opened by the plugin so the agent can drive it from WSL, and reports the debugging URL. Live Windows Chrome connections, if any stand, refresh against the run instead of launching a second browser. On a non-WSL host it answers \"not applicable\". " +
13
+ "The browser it started is never closed by the plugin.",
14
+ parameters: { type: "object", properties: {}, additionalProperties: false },
15
+ output: {
16
+ schema: { type: "object", properties: { text: { type: "string" } }, required: ["text"], additionalProperties: false },
17
+ render(_args, value) {
18
+ const text = value === null || typeof value !== "object" ? "" : value.text;
19
+ return [{ type: "text", text: typeof text === "string" ? text : "" }];
20
+ }
21
+ },
22
+ execute: async () => ({ text: await controller.prelaunchWindowsChrome() })
23
+ };
24
+ }
25
+ /**
26
+ * Register the tool on one fiber effect, resolving the tools service lazily. A
27
+ * host without one (no model assembled) simply gets no registration — the card
28
+ * button stays the only trigger.
29
+ * @param ctx - plugin context.
30
+ * @param controller - the live state whose run this tool drives.
31
+ */
32
+ export function installPrelaunchWindowsChromeTool(ctx, controller) {
33
+ ctx.effect(() => {
34
+ let registered = false;
35
+ let unregister;
36
+ ctx.inject(["tools"], (inner) => {
37
+ if (registered)
38
+ return;
39
+ const tools = inner.tools;
40
+ if (!tools)
41
+ return;
42
+ registered = true;
43
+ unregister = tools.register(prelaunchWindowsChromeDefinition(controller));
44
+ });
45
+ return () => {
46
+ if (unregister)
47
+ unregister();
48
+ registered = false;
49
+ };
50
+ }, "chrome-mcp: prelaunch_windows_chrome tool");
51
+ }
52
+ //# sourceMappingURL=tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/host/tool.ts"],"names":[],"mappings":"AA8BA,gEAAgE;AAChE,MAAM,CAAC,MAAM,6BAA6B,GAAG,0BAA0B,CAAC;AAwBxE,sEAAsE;AACtE,MAAM,UAAU,gCAAgC,CAAC,UAA+B;IAC5E,OAAO;QACH,IAAI,EAAE,6BAA6B;QACnC,WAAW,EACP,wGAAwG;YACxG,oJAAoJ;YACpJ,mEAAmE;YACnE,iIAAiI;YACjI,gIAAgI;YAChI,qQAAqQ;YACrQ,uDAAuD;QAC3D,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE;QAC3E,MAAM,EAAE;YACJ,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,oBAAoB,EAAE,KAAK,EAAE;YACrH,MAAM,CAAC,KAAc,EAAE,KAAc;gBACjC,MAAM,IAAI,GAAG,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,KAA4B,CAAC,IAAI,CAAC;gBACnG,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC1E,CAAC;SACJ;QACD,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC,sBAAsB,EAAE,EAAE,CAAC;KAC7E,CAAC;AACN,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iCAAiC,CAAC,GAAkB,EAAE,UAA+B;IACjG,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE;QACZ,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,UAAoC,CAAC;QACzC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,KAAoB,EAAE,EAAE;YAC3C,IAAI,UAAU;gBAAE,OAAO;YACvB,MAAM,KAAK,GAAI,KAAsC,CAAC,KAAK,CAAC;YAC5D,IAAI,CAAC,KAAK;gBAAE,OAAO;YACnB,UAAU,GAAG,IAAI,CAAC;YAClB,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,gCAAgC,CAAC,UAAU,CAAC,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACR,IAAI,UAAU;gBAAE,UAAU,EAAE,CAAC;YAC7B,UAAU,GAAG,KAAK,CAAC;QACvB,CAAC,CAAC;IACN,CAAC,EAAE,2CAA2C,CAAC,CAAC;AACpD,CAAC"}