@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,131 @@
1
+ /**
2
+ * Controller — configuration-form commit routing.
3
+ *
4
+ * One commit may carry any of five changes; this routes them in the reference's
5
+ * order: a flags drift shifts what a connection with no own answer would run
6
+ * with (and hands such live connections back to the pool), an executable change
7
+ * picked by the card does the same plus a re-run of the discovery, a rows change
8
+ * is folded into the same run (never a second one), the stderr toggle shifts the
9
+ * spawn wrapper the next answer builds with, and the two trigger nonces (the
10
+ * fetch button, the Windows button) fire their runs. The first commit read is
11
+ * the registration run — a persisted Windows trigger folds in silently so
12
+ * booting a host never launches a Windows browser by itself.
13
+ *
14
+ * Two things make this routing safe under the config-form model:
15
+ *
16
+ * - It runs only for **user-authored** paths (see ../settings.ts
17
+ * `routesUserCommit`), so the live publish it itself triggers — a volatile
18
+ * commit carrying live fields — never re-enters it.
19
+ * - It re-publishes the live mirror when it finishes. A user write clears the
20
+ * live-only fields out of the running references (the write merge), so without
21
+ * the re-publish the card would read defaults back until the next run.
22
+ *
23
+ * Nothing here restarts anything: what runs lives in the manager's pool, and
24
+ * that pool decides a restart against the config the kind's `resolve` answers
25
+ * with — this side only says what the default answers would be.
26
+ */
27
+ import { normalizeEntries } from "../catalog.js";
28
+ import { KIND_FIELDS } from "../constants.js";
29
+ import { flagsSkipCheck, sameFlags } from "../flags.js";
30
+ import { readPersistedChromePath, resolveLaunchFlags, resolveSelection, resolveStderrModeFromLayers } from "../values.js";
31
+ import { invalidateOwnedForField } from "./connections.js";
32
+ import { applyChromePath, queue, sameEntries } from "./runs.js";
33
+ import { publishLive } from "./publish.js";
34
+ /** Route one configuration-form commit. */
35
+ export function onFormCommit(controller) {
36
+ const { state } = controller;
37
+ try {
38
+ const layers = state.source();
39
+ // Flags: the user layer, then the launch environment, then the row config,
40
+ // then the schema default. Whatever answers is what a connection following
41
+ // the row would run with; the ones carrying their own list are untouched.
42
+ const nextFlags = resolveLaunchFlags(layers, controller.launchFlags);
43
+ if (!sameFlags(nextFlags, state.runningFlags)) {
44
+ state.runningFlags = nextFlags;
45
+ // Connect mode launches no local executable, so the known "executable
46
+ // missing" state simply does not apply while it is set.
47
+ if (flagsSkipCheck(nextFlags))
48
+ state.live.chromeMissing = false;
49
+ publishLive(controller);
50
+ controller.ctx.logger.info(`dsh-chrome-mcp(${controller.config.serverName}): default flags → [${nextFlags.join(" ")}] (connections without own flags re-answer on the next prepare)`);
51
+ invalidateOwnedForField(controller, KIND_FIELDS.extraFlags);
52
+ }
53
+ // Executable changes come from the user layer `chromePath` the card wrote
54
+ // (a row's `id`) or the host seeded. A different executable reads a
55
+ // different machine: mirror the new default and re-run the discovery. A
56
+ // path the host seeded itself keeps standing until the user picks one:
57
+ // the seed is written into the user layer, and until that write is
58
+ // visible a commit must not resolve back to "nothing selected".
59
+ const userLayer = readPersistedChromePath(layers);
60
+ if (userLayer !== "")
61
+ state.seenUserSelection = true;
62
+ const seededCarry = state.seededPath !== "" && !state.seenUserSelection ? state.seededPath : "";
63
+ const selection = resolveSelection(layers);
64
+ const nextChromePath = selection.path !== "" ? selection.path : seededCarry;
65
+ const nextSource = nextChromePath === "" ? "" : selection.source !== "" ? selection.source : "selected";
66
+ // A row config that pinned the executable with a flag answers as the
67
+ // row-config source; say it once, since the fold is invisible to argv and
68
+ // a silent switch would read as the picker having changed.
69
+ if (selection.source === "row-config" && selection.pinned === true && !state.legacyPinAnnounced) {
70
+ state.legacyPinAnnounced = true;
71
+ controller.ctx.logger.warn(`dsh-chrome-mcp(${controller.config.serverName}): an extraFlags "--executablePath" in the row config is now the \`chromePath\` source ("${selection.path}"); the flag itself is dropped from the launched argv`);
72
+ }
73
+ if (nextChromePath !== state.runningChromePath || nextSource !== state.runningChromeSource)
74
+ applyChromePath(controller, nextChromePath, nextSource);
75
+ // Rows changes touch the list, never a connection.
76
+ const nextExecutables = normalizeEntries(layers.user.executables ?? layers.value.executables);
77
+ const rowsChanged = !sameEntries(nextExecutables, state.runningExecutables);
78
+ // The "Reduce log output" toggle lives here too: the effective stderr mode
79
+ // is stated from every commit, not only from a switch — a commit that
80
+ // changes nothing the spawn does must still answer what the spawn *does*
81
+ // do, or the card's own diff against the effective mode would drop every
82
+ // flip it stages. A switch shifts the default and hands the connections
83
+ // that follow it back to the pool (the wrapper is fixed at spawn).
84
+ const nextStderrMode = resolveStderrModeFromLayers(layers, controller.config.bridgeStderr);
85
+ state.live.stderrEffective = nextStderrMode;
86
+ if (nextStderrMode !== state.runningStderrMode) {
87
+ state.runningStderrMode = nextStderrMode;
88
+ publishLive(controller);
89
+ controller.ctx.logger.info(`dsh-chrome-mcp(${controller.config.serverName}): bridge stderr mode → "${nextStderrMode}" (connections re-spawn with the new wrapper)`);
90
+ invalidateOwnedForField(controller, KIND_FIELDS.stderrMode);
91
+ }
92
+ // A persisted trigger must never fire a run just because the Host read
93
+ // it back: the reference pins this with `!== 0` (a stored nonce folds in
94
+ // silently, only a later diff fires). The guard here is the same rule,
95
+ // stated the stronger way: the first commit *is* the fold (booting never
96
+ // launches — see the branch below), and every later diff is real because
97
+ // the card writes `Date.now()` as the trigger value (the client's
98
+ // fetch/openWindowsChrome), so no stored value ever equals a new write.
99
+ const firstCommit = state.lastRefreshNonce === void 0;
100
+ const refreshChanged = !firstCommit && layers.value.refreshExecutablesNonce !== state.lastRefreshNonce;
101
+ const windowsChanged = !firstCommit && layers.value.openWindowsChromeNonce !== state.lastWindowsNonce;
102
+ state.lastRefreshNonce = layers.value.refreshExecutablesNonce;
103
+ state.lastWindowsNonce = layers.value.openWindowsChromeNonce;
104
+ if (firstCommit) {
105
+ // The registration run: discovery + probe, no separate call. A
106
+ // persisted Windows trigger folds in silently — booting a host must
107
+ // never launch a Windows browser by itself.
108
+ queue(controller, "probe");
109
+ }
110
+ else {
111
+ // The card's **Fetch executables** button. A rows change is folded into
112
+ // the same run rather than a second one, so the client waits on exactly
113
+ // one revision bump.
114
+ if (refreshChanged || rowsChanged)
115
+ queue(controller, "probe");
116
+ // The card's **Prelaunch Windows Chrome** button: one Windows run,
117
+ // sharing this chain (one run at a time).
118
+ if (windowsChanged)
119
+ queue(controller, "windows");
120
+ }
121
+ }
122
+ catch (error) {
123
+ controller.ctx.logger.error(`dsh-chrome-mcp(${controller.config.serverName}): ${String(error)}`);
124
+ }
125
+ finally {
126
+ // Every user commit clears the live-only fields, so the mirror goes back
127
+ // out with the answers it carries.
128
+ publishLive(controller);
129
+ }
130
+ }
131
+ //# sourceMappingURL=commits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commits.js","sourceRoot":"","sources":["../../../src/host/controller/commits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { Controller } from "./state.js";
2
+ /** Everything one `resolve` answered with that the live state should carry. */
3
+ export interface RunningAnswers {
4
+ /** The executable the connection launches ("" in connect mode). */
5
+ executable: string;
6
+ /** Where it came from (`"selected"` / `"row-config"` / ""). */
7
+ source: string;
8
+ /** The flags list it launched with. */
9
+ flags: string[];
10
+ /** The console-output mode it spawned with. */
11
+ stderrMode: "log" | "console";
12
+ /** Where the stderr lands when the wrapper redirects ("" otherwise). */
13
+ redirect: string;
14
+ /** The note the answer carries ("" = silent). */
15
+ note: string;
16
+ }
17
+ /**
18
+ * Mirror what a live connection runs with into the live state and say it out
19
+ * loud: publish, then notify that the pickers' answers moved (their Host-served
20
+ * choices read this state off). One log line per resolve names the connection
21
+ * being answered for.
22
+ */
23
+ export declare function noteRunning(controller: Controller, entryId: string, answers: RunningAnswers): void;
24
+ /**
25
+ * Tell the pool to re-answer every live connection whose answer depends on the
26
+ * field the row just changed. A connection carrying its own `extra` answer for
27
+ * the field does not follow the row's default, so it is left standing; every
28
+ * other owned entry is handed back for a re-resolve, live ones included — the
29
+ * diff that decides what the pool actually does with the re-resolve is decided
30
+ * on the **resolved config**, so a connection that would answer with exactly
31
+ * what it runs with is not restarted anyway, and one that would answer with
32
+ * something else switches in place.
33
+ */
34
+ export declare function invalidateOwnedForField(controller: Controller, fieldKey: string): void;
35
+ /** The invalidation key matching one kind-field, shared by the three drift paths
36
+ * in ./commits.ts. */
37
+ export declare const DEFAULT_ANSWER_FIELDS: readonly ["executable", "extraFlags", "stderrMode"];
38
+ //# sourceMappingURL=connections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../../src/host/controller/connections.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC3B,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,+CAA+C;IAC/C,UAAU,EAAE,KAAK,GAAG,SAAS,CAAC;IAC9B,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAalG;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAYtF;AAED;sBACsB;AACtB,eAAO,MAAM,qBAAqB,qDAAoF,CAAC"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Controller — the manager-connection seam.
3
+ *
4
+ * The row starts no bridge of its own any more: every live bridge is one of the
5
+ * manager's connections, answered through ./kind.ts (`resolve`). What this module
6
+ * keeps is the mirror half — when a connection answers with what it runs with,
7
+ * the live state says so (the running executable, the running flags, the stderr
8
+ * destination, the running note) — plus the write paths that change what the
9
+ * **default** answers would be: a row-level flags/executable/stderr edit has to
10
+ * reach the live connections that carry no own answer for that field, which the
11
+ * pool only learns about on the next `invalidate`.
12
+ *
13
+ * The old file this replaces drove the fiber directly (`bridgeConfig` rebuild,
14
+ * `fiber.update()` chained on readiness). The pool does that now, against the
15
+ * config a kind's `resolve` hands it.
16
+ */
17
+ import { KIND_FIELDS } from "../constants.js";
18
+ import { ownedEntries } from "../manager.js";
19
+ import { noteStderr } from "./notes.js";
20
+ import { publishLive } from "./publish.js";
21
+ /**
22
+ * Mirror what a live connection runs with into the live state and say it out
23
+ * loud: publish, then notify that the pickers' answers moved (their Host-served
24
+ * choices read this state off). One log line per resolve names the connection
25
+ * being answered for.
26
+ */
27
+ export function noteRunning(controller, entryId, answers) {
28
+ const { state } = controller;
29
+ state.runningFlags = [...answers.flags];
30
+ state.runningChromePath = answers.executable;
31
+ state.runningChromeSource = answers.source === "row-config" || answers.source === "selected" ? answers.source : "";
32
+ state.runningStderrMode = answers.stderrMode;
33
+ state.live.runningFlags = [...answers.flags];
34
+ state.live.runningNote = answers.note;
35
+ if (answers.redirect !== "")
36
+ noteStderr(controller, { redirect: answers.redirect });
37
+ controller.ctx.logger.info(`dsh-chrome-mcp(${entryId}): connection answers with executable "${answers.executable || "(connect mode)"}", flags [${answers.flags.join(" ")}], stderr → ${answers.stderrMode}${answers.note === "" ? "" : `, ${answers.note}`}`);
38
+ // The publish inside `publishLive` re-notifies the pickers: the answers that
39
+ // just moved are exactly what a `select` offers.
40
+ publishLive(controller);
41
+ }
42
+ /**
43
+ * Tell the pool to re-answer every live connection whose answer depends on the
44
+ * field the row just changed. A connection carrying its own `extra` answer for
45
+ * the field does not follow the row's default, so it is left standing; every
46
+ * other owned entry is handed back for a re-resolve, live ones included — the
47
+ * diff that decides what the pool actually does with the re-resolve is decided
48
+ * on the **resolved config**, so a connection that would answer with exactly
49
+ * what it runs with is not restarted anyway, and one that would answer with
50
+ * something else switches in place.
51
+ */
52
+ export function invalidateOwnedForField(controller, fieldKey) {
53
+ const { state } = controller;
54
+ if (state.connections === void 0)
55
+ return;
56
+ try {
57
+ for (const entry of ownedEntries(state.connections)) {
58
+ if (Object.prototype.hasOwnProperty.call(entry.extra, fieldKey))
59
+ continue;
60
+ state.connections.invalidate(entry.id);
61
+ }
62
+ }
63
+ catch {
64
+ // A manager that has already gone away answers nothing; there is nothing
65
+ // to invalidate.
66
+ }
67
+ }
68
+ /** The invalidation key matching one kind-field, shared by the three drift paths
69
+ * in ./commits.ts. */
70
+ export const DEFAULT_ANSWER_FIELDS = [KIND_FIELDS.executable, KIND_FIELDS.extraFlags, KIND_FIELDS.stderrMode];
71
+ //# sourceMappingURL=connections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connections.js","sourceRoot":"","sources":["../../../src/host/controller/connections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAmB3C;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,UAAsB,EAAE,OAAe,EAAE,OAAuB;IACxF,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC;IAC7B,KAAK,CAAC,YAAY,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACxC,KAAK,CAAC,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAC7C,KAAK,CAAC,mBAAmB,GAAG,OAAO,CAAC,MAAM,KAAK,YAAY,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACnH,KAAK,CAAC,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IACtC,IAAI,OAAO,CAAC,QAAQ,KAAK,EAAE;QAAE,UAAU,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpF,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,OAAO,0CAA0C,OAAO,CAAC,UAAU,IAAI,gBAAgB,aAAa,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC9P,6EAA6E;IAC7E,iDAAiD;IACjD,WAAW,CAAC,UAAU,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAsB,EAAE,QAAgB;IAC5E,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC;IAC7B,IAAI,KAAK,CAAC,WAAW,KAAK,KAAK,CAAC;QAAE,OAAO;IACzC,IAAI,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;YAClD,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC;gBAAE,SAAS;YAC1E,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC3C,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACL,yEAAyE;QACzE,iBAAiB;IACrB,CAAC;AACL,CAAC;AAED;sBACsB;AACtB,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,UAAU,CAAU,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { type WindowsChromeRunOptions } from "../windows/index.js";
2
+ import type { ChromeMcpConfig, PluginContext, WindowsChromeRun } from "../types/index.js";
3
+ import type { Controller } from "./state.js";
4
+ /** Public alias: the controller object the form, commands and kinds work
5
+ * through is the internal `Controller` type itself. */
6
+ export type ChromeMcpController = Controller;
7
+ /**
8
+ * Optional overrides for tests and diagnostics: the Windows Chrome run is the
9
+ * only half that reaches outside the process (it opens TCP sockets and spawns
10
+ * through the interop mount), so a wiring test replaces just this one — the same
11
+ * injectability rule every other platform half follows.
12
+ */
13
+ export type ChromeMcpControllerDeps = {
14
+ runWindowsChrome?: (options: WindowsChromeRunOptions) => Promise<WindowsChromeRun>;
15
+ /** The Windows-side executables this host carries, in preference order. The
16
+ * machine half of the candidate fold — the real one locates through the
17
+ * interop mount; a test supplies the answer list it wants folded. */
18
+ windowsExecutables?: () => string[];
19
+ /** The platform the WSL probe reads; defaults to `process.platform`. A test
20
+ * that simulates a WSL host through its launch environment states `linux`
21
+ * here too — the environment alone never makes a Windows host WSL. */
22
+ platform?: NodeJS.Platform;
23
+ };
24
+ /**
25
+ * Build the live state for one row page. The controller is also the public
26
+ * surface (`ChromeMcpController` — the same object the form, the commands and
27
+ * the kinds work through); what each method does lives in the sibling modules.
28
+ * @param ctx - plugin context.
29
+ * @param config - the validated config `apply` received: every `.volatile()`
30
+ * field a reference rather than a value (read them through `readConfigField`).
31
+ * @param deps - optional host overrides (tests replace the Windows run;
32
+ * everything else resolves from this process).
33
+ */
34
+ export declare function createChromeMcpController(ctx: PluginContext, config: ChromeMcpConfig, deps?: ChromeMcpControllerDeps): Controller;
35
+ //# sourceMappingURL=controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/host/controller/controller.ts"],"names":[],"mappings":"AAmCA,OAAO,EAAyD,KAAK,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAY1H,OAAO,KAAK,EACR,eAAe,EAEf,aAAa,EACb,gBAAgB,EACnB,MAAM,mBAAmB,CAAC;AAU3B,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,YAAY,CAAC;AAE9D;uDACuD;AACvD,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG;IAClC,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnF;;yEAEqE;IACrE,kBAAkB,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IACpC;;0EAEsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC9B,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI,GAAE,uBAA4B,GAAG,UAAU,CAgMrI"}
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Host half — live state: `createChromeMcpController`.
3
+ *
4
+ * One controller per apply(): the live mirror the Host publishes, the serialized
5
+ * executable runs, the Windows run half, and the capture paths — tool-call
6
+ * results reaching the live mirror. Every live answer is written into
7
+ * `state.live` and published through the volatile references (see ./publish.ts);
8
+ * form commits route in through the controller methods, never the other way
9
+ * round.
10
+ *
11
+ * Since the component model, the controller starts nothing: every live bridge is
12
+ * a connection of the manager's, answered through ./kind.ts. What this half owns
13
+ * is the machine — the executable catalog and its runs, the Windows run, the
14
+ * layers, and the mirror — plus the seam the manager reads it through (the
15
+ * connection service sits on `state.connections`, installed by ../manager.ts).
16
+ *
17
+ * The executable state keeps the rule that there is no auto mode: the saved
18
+ * **rows** (`{ id: path, name: label }`) are what every picker lists, the
19
+ * *selection* is what the default answers run with, and a run refreshes both —
20
+ * it probes every candidate the rows and the row config carry, merges what it
21
+ * finds into the rows (names kept), and seeds a never-configured host exactly
22
+ * once. A fixed path that later breaks stays fixed and reads broken instead of
23
+ * being re-resolved.
24
+ *
25
+ * This file is only the assembly: it resolves the config-derived pieces, seeds
26
+ * the live mirror, and wires the public methods to the behavior modules that sit
27
+ * alongside it (see ./index.ts for the layout). Everything that actually *does*
28
+ * something lives there, not here.
29
+ */
30
+ import { existsSync } from "node:fs";
31
+ import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment";
32
+ import { FLAGS_ENV_VAR, WSL_WINDOWS_LAUNCH_ERROR } from "../constants.js";
33
+ import { flagsSkipCheck } from "../flags.js";
34
+ import { isWindowsExecutablePath, isWindowsSubsystemForLinux } from "../platform.js";
35
+ import { findWindowsChromeExecutables, runWindowsChromeConnect } from "../windows/index.js";
36
+ import { createLiveMirror, readConfigForm, readConfigLayers, readDefaultExtraFlags, readWslExtraFlags, resolveEnvFlags, resolveLaunchFlags, resolveSelection, resolveStderrModeFromLayers } from "../values.js";
37
+ import { registerToolCapture } from "./captures.js";
38
+ import { noteRunning as mirrorRunning } from "./connections.js";
39
+ import { onFormCommit } from "./commits.js";
40
+ import { noteSelection } from "./notes.js";
41
+ import { dismissMigration, } from "./persist.js";
42
+ import { cancelDiscoveryRetry, prelaunchWindowsChrome, queue, selectChromePath } from "./runs.js";
43
+ import { prelaunchWindowsForConnection } from "./windows-run.js";
44
+ /**
45
+ * Build the live state for one row page. The controller is also the public
46
+ * surface (`ChromeMcpController` — the same object the form, the commands and
47
+ * the kinds work through); what each method does lives in the sibling modules.
48
+ * @param ctx - plugin context.
49
+ * @param config - the validated config `apply` received: every `.volatile()`
50
+ * field a reference rather than a value (read them through `readConfigField`).
51
+ * @param deps - optional host overrides (tests replace the Windows run;
52
+ * everything else resolves from this process).
53
+ */
54
+ export function createChromeMcpController(ctx, config, deps = {}) {
55
+ // The Windows run half — injectable for tests, default is the real one (TCP
56
+ // samples + the interop launch).
57
+ const windowsChrome = typeof deps.runWindowsChrome === "function" ? deps.runWindowsChrome : runWindowsChromeConnect;
58
+ const launchEnvironment = launchEnvironmentOf(ctx);
59
+ const launchFlags = launchEnvironment.get(FLAGS_ENV_VAR)?.value;
60
+ // Where the plugin runs: a WSL host plus a Windows executable is a selection
61
+ // the local bridge can never launch (its debug pipes do not cross the interop
62
+ // boundary, and its debugging port stays on the Windows loopback). The launch
63
+ // environment is authoritative inside a host, so the answer is deterministic;
64
+ // a bare call falls back to the interop marker.
65
+ const wslHost = isWindowsSubsystemForLinux({ platform: deps.platform, env: (name) => launchEnvironment.get(name)?.value });
66
+ // The Linux half of the host: the executable candidate list models the
67
+ // stable-channel installs a Linux host carries, so this is what keys the
68
+ // executable-missing answer's advice (see runs.ts). WSL is the case with the
69
+ // Windows-side alternative next to it.
70
+ const linuxHost = process.platform === "linux";
71
+ // A path this host must never exec. There is only one: a Windows
72
+ // `chrome.exe` selected on a WSL host. Its `--version` probe answers (so the
73
+ // selection looks healthy) but answering attaches to the Windows browser
74
+ // session, and that **starts a browser instance** no tool call could drive —
75
+ // see WSL_WINDOWS_LAUNCH_ERROR. The runs keep such an entry visible carrying
76
+ // this reason; the probe answers nothing instead of paying for it.
77
+ const blockedForPlatform = (candidate) => wslHost && isWindowsExecutablePath(candidate) ? WSL_WINDOWS_LAUNCH_ERROR : "";
78
+ // The Windows-side executables this host carries, located through the interop
79
+ // mount. An executable run folds them into its candidate list so the picker
80
+ // can name the Windows browser the **Prelaunch Windows Chrome** run drives
81
+ // instead of hiding it. Being offered only, they are never spawned (see
82
+ // `blockedForPlatform`): an entry answers a note, never a version, and never
83
+ // seeds. Locating them is the machine half of the fold, injected the same way
84
+ // the run's own `exists` half is — a host off WSL answers nothing, and a
85
+ // machine that carries none of them answers nothing either.
86
+ const windowsExecutables = typeof deps.windowsExecutables === "function"
87
+ ? deps.windowsExecutables
88
+ : () => (wslHost ? findWindowsChromeExecutables(existsSync) : []);
89
+ // The configuration form's layers as they answer right now. The references
90
+ // resolve the user layer over the row config, so every answer here is the
91
+ // effective one; the two layers the "did the user say this, or is it the row
92
+ // config" distinction reads only answer once the form attaches, and the first
93
+ // commit read settles it.
94
+ const layers = readConfigLayers(config);
95
+ // Default launch flags (highest first): the user layer,
96
+ // `DSH_CHROME_MCP_FLAGS`, the row config, the schema default. What a
97
+ // connection with no own answer is resolved with starts on them.
98
+ const initialFlags = resolveLaunchFlags(layers, launchFlags);
99
+ if (typeof launchFlags === "string" && launchFlags.trim() !== "" && resolveEnvFlags([], launchFlags).length === 0) {
100
+ ctx.logger.warn(`dsh-chrome-mcp(${config.serverName}): ignoring ${FLAGS_ENV_VAR} — invalid flags list; using the resolved configuration`);
101
+ }
102
+ // The initial selection: what the user layer says, else what the row config
103
+ // says (a legacy row-level `--executablePath` folded in — the picker owns that
104
+ // flag, so it becomes the row-config source of the selection and never reaches
105
+ // argv as a second source of truth), else nothing. Nothing here consults
106
+ // discovery: the first run does, and only seeds when both layers are silent.
107
+ const selection = resolveSelection(layers);
108
+ const runningChromePath = selection.path;
109
+ const runningChromeSource = selection.source;
110
+ // The effective console-output mode: what the user layer's toggle says, then
111
+ // what the row config carries, then the row's `bridgeStderr`. Every spawn
112
+ // wrapper reads it.
113
+ const runningStderrMode = resolveStderrModeFromLayers(layers, config.bridgeStderr);
114
+ // The mirror's opening answers: what the default answers would run with, not
115
+ // what a host with no answers would serve. `windowsChromeStatus` in particular
116
+ // reads off this host from the start — the Windows path simply does not exist
117
+ // off WSL.
118
+ const live = createLiveMirror();
119
+ live.effectiveChromePath = runningChromePath;
120
+ live.effectiveSource = runningChromeSource;
121
+ live.stderrEffective = runningStderrMode;
122
+ live.wslWindowsExecutable = wslHost && runningChromePath !== "" && isWindowsExecutablePath(runningChromePath);
123
+ live.carriesConnectionMode = flagsSkipCheck(initialFlags);
124
+ live.windowsChromeStatus = { state: wslHost ? "off" : "not-applicable", port: 0, error: "" };
125
+ live.defaultExtraFlags = readDefaultExtraFlags();
126
+ live.wslExtraFlags = readWslExtraFlags();
127
+ const state = {
128
+ live,
129
+ form: void 0,
130
+ // The live layers read: the references answer what runs now, and once the
131
+ // form is described the two layers answer the distinction with it. This is
132
+ // read live on every commit — cordis starts the `settings` injection
133
+ // callback after `apply` returns, so nothing may be captured here.
134
+ source: () => readConfigLayers(config, state.form?.settings ? readConfigForm(state.form.settings, state.form.entryId) : void 0),
135
+ runningFlags: initialFlags,
136
+ runningStderrMode,
137
+ runningChromePath,
138
+ runningChromeSource,
139
+ runningExecutables: [],
140
+ stderrNotice: "",
141
+ lastRefreshNonce: void 0,
142
+ lastWindowsNonce: void 0,
143
+ seededPath: "",
144
+ seenUserSelection: false,
145
+ runs: Promise.resolve(),
146
+ retryTimer: void 0,
147
+ retriesPending: 0,
148
+ disposed: false,
149
+ wslNoticeShown: false,
150
+ profileLinkKeptShown: false,
151
+ legacyPathsMerged: false,
152
+ legacyPinAnnounced: false,
153
+ mirror: void 0,
154
+ kindsNotifyQueued: false,
155
+ // The manager seam opens empty: `attachToManager` fills it in once the
156
+ // service answers. A component without the manager answers its own page
157
+ // and starts nothing — exactly as a row with no connections should.
158
+ connections: void 0,
159
+ notifyKindsChanged: () => void 0
160
+ };
161
+ const controller = {
162
+ ctx,
163
+ config,
164
+ wslHost,
165
+ linuxHost,
166
+ blockedForPlatform,
167
+ launchFlags,
168
+ windowsChrome,
169
+ windowsExecutables,
170
+ state,
171
+ attachForm(form) {
172
+ state.form = form;
173
+ const nowDescribed = form.settings !== void 0;
174
+ // The first attach is the mount's commit read: no nonce has been
175
+ // observed yet, so its nonce diff fires the registration run. The step
176
+ // where the row starts being *described* is routed too, for the one
177
+ // thing the references cannot answer: which layer a value came from.
178
+ // Until it answers there, the launch environment sits above whatever
179
+ // the references carry, so a saved UI edit has to be re-read against
180
+ // the user layer the moment that layer exists.
181
+ const first = !routed;
182
+ const layersArrived = nowDescribed && !described;
183
+ routed = true;
184
+ described = nowDescribed;
185
+ if (!first && !layersArrived)
186
+ return;
187
+ onFormCommit(controller);
188
+ },
189
+ detachForm() {
190
+ // Only the described row's layers go away: the references keep
191
+ // answering, so nothing else has to be undone.
192
+ state.form = void 0;
193
+ routed = false;
194
+ described = false;
195
+ },
196
+ onFormCommit: () => onFormCommit(controller),
197
+ run: () => queue(controller, "probe"),
198
+ source: () => state.source(),
199
+ // The live mirror, by reference: controller modules write its fields in
200
+ // place, publish reads them off `state.live`, and every other surface
201
+ // (the commands) reads the very same answers out of it.
202
+ get live() {
203
+ return state.live;
204
+ },
205
+ selectChromePath: (path) => selectChromePath(controller, path),
206
+ prelaunchWindowsChrome: () => prelaunchWindowsChrome(controller),
207
+ noteRunning(entry, answers) {
208
+ mirrorRunning(controller, entry.id, answers);
209
+ },
210
+ prelaunchForConnection: () => prelaunchWindowsForConnection(controller),
211
+ dismissMigration: () => dismissMigration(controller),
212
+ dispose: () => {
213
+ // Every late answer stands down: the run chain drains on its own (the
214
+ // chain is per-instance, no shared resource left behind), and the one
215
+ // timer this instance owns is cancelled.
216
+ state.disposed = true;
217
+ cancelDiscoveryRetry(controller);
218
+ }
219
+ };
220
+ // Form routing arrives in two steps — the entry id as soon as this fiber knows
221
+ // its own entry, then the described row once the settings service resolves —
222
+ // and the layers read live off it either way (the two flags above are what
223
+ // mark the difference between "never described" and "described before").
224
+ let routed = false;
225
+ let described = false;
226
+ // Tool-level status: browser-level failures are returned to the calling agent
227
+ // and never reach a line of their own.
228
+ registerToolCapture(controller);
229
+ // Seed the mirror before the first snapshot lands (a card that reads before
230
+ // anything ran still gets the real opening answers, never defaults).
231
+ noteSelection(controller);
232
+ return controller;
233
+ }
234
+ //# sourceMappingURL=controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../../src/host/controller/controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Host half — the controller's live state + behavior.
3
+ *
4
+ * One controller per apply(): the live mirror the Host publishes, the serialized
5
+ * executable runs, the Windows run half, and the tool-call capture path. The
6
+ * public surface is `createChromeMcpController` (the controller object itself);
7
+ * everything behind it is split into concern modules:
8
+ *
9
+ * ./controller.ts the assembly: resolve config, seed the live mirror, wire
10
+ * the public methods
11
+ * ./state.ts the live state + context every helper shares (internal)
12
+ * ./notes.ts live-mirror announcements (selection, stderr)
13
+ * ./connections.ts the manager seam: what answers reach the live state, and
14
+ * how a default answer change reaches live connections
15
+ * ./runs.ts the executable run + serialization + the Windows trigger
16
+ * ./windows-run.ts the one **Prelaunch Windows Chrome** run
17
+ * ./persist.ts the form writes a run makes (seed, rows, dismissal)
18
+ * ./captures.ts tool-call-result capture
19
+ * ./commits.ts configuration-form commit routing (`onFormCommit`)
20
+ *
21
+ * The two rules that must survive the split: read the layers through
22
+ * `state.source()` at commit time, never capture them, and route every live answer
23
+ * out through `publishLive` (./publish.ts) — configuration-form commits route in,
24
+ * never out, and the live mirror is never written by a commit path.
25
+ */
26
+ export { createChromeMcpController } from "./controller.js";
27
+ export type { ChromeMcpController, ChromeMcpControllerDeps } from "./controller.js";
28
+ export type { Controller, ControllerState } from "./state.js";
29
+ export type { RunningAnswers } from "./connections.js";
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/host/controller/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AACpF,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC9D,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Host half — the controller's live state + behavior.
3
+ *
4
+ * One controller per apply(): the live mirror the Host publishes, the serialized
5
+ * executable runs, the Windows run half, and the tool-call capture path. The
6
+ * public surface is `createChromeMcpController` (the controller object itself);
7
+ * everything behind it is split into concern modules:
8
+ *
9
+ * ./controller.ts the assembly: resolve config, seed the live mirror, wire
10
+ * the public methods
11
+ * ./state.ts the live state + context every helper shares (internal)
12
+ * ./notes.ts live-mirror announcements (selection, stderr)
13
+ * ./connections.ts the manager seam: what answers reach the live state, and
14
+ * how a default answer change reaches live connections
15
+ * ./runs.ts the executable run + serialization + the Windows trigger
16
+ * ./windows-run.ts the one **Prelaunch Windows Chrome** run
17
+ * ./persist.ts the form writes a run makes (seed, rows, dismissal)
18
+ * ./captures.ts tool-call-result capture
19
+ * ./commits.ts configuration-form commit routing (`onFormCommit`)
20
+ *
21
+ * The two rules that must survive the split: read the layers through
22
+ * `state.source()` at commit time, never capture them, and route every live answer
23
+ * out through `publishLive` (./publish.ts) — configuration-form commits route in,
24
+ * never out, and the live mirror is never written by a commit path.
25
+ */
26
+ export { createChromeMcpController } from "./controller.js";
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/host/controller/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC"}