@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.
- package/README.md +44 -95
- package/assets/dsh-chrome-mcp-social.png +0 -0
- package/assets/icon.svg +71 -0
- package/assets/prelaunch-windows-chrome.html +277 -0
- package/lib/client.js +3005 -568
- package/lib/client.js.map +7 -0
- package/lib/host/apply.d.ts +40 -0
- package/lib/host/apply.d.ts.map +1 -0
- package/lib/host/apply.js +57 -0
- package/lib/host/apply.js.map +1 -0
- package/lib/host/bridge.d.ts +74 -0
- package/lib/host/bridge.d.ts.map +1 -0
- package/lib/host/bridge.js +168 -0
- package/lib/host/bridge.js.map +1 -0
- package/lib/host/catalog.d.ts +31 -0
- package/lib/host/catalog.d.ts.map +1 -0
- package/lib/host/catalog.js +92 -0
- package/lib/host/catalog.js.map +1 -0
- package/lib/host/commands/chrome-path.d.ts +4 -0
- package/lib/host/commands/chrome-path.d.ts.map +1 -0
- package/lib/host/commands/chrome-path.js +65 -0
- package/lib/host/commands/chrome-path.js.map +1 -0
- package/lib/host/commands/chrome-refresh.d.ts +17 -0
- package/lib/host/commands/chrome-refresh.d.ts.map +1 -0
- package/lib/host/commands/chrome-refresh.js +37 -0
- package/lib/host/commands/chrome-refresh.js.map +1 -0
- package/lib/host/commands/index.d.ts +26 -0
- package/lib/host/commands/index.d.ts.map +1 -0
- package/lib/host/commands/index.js +41 -0
- package/lib/host/commands/index.js.map +1 -0
- package/lib/host/constants.d.ts +306 -0
- package/lib/host/constants.d.ts.map +1 -0
- package/lib/host/constants.js +319 -0
- package/lib/host/constants.js.map +1 -0
- package/lib/host/controller/_trace.d.ts +3 -0
- package/lib/host/controller/_trace.d.ts.map +1 -0
- package/lib/host/controller/_trace.js +14 -0
- package/lib/host/controller/_trace.js.map +1 -0
- package/lib/host/controller/bridge-run.d.ts +40 -0
- package/lib/host/controller/bridge-run.d.ts.map +1 -0
- package/lib/host/controller/bridge-run.js +85 -0
- package/lib/host/controller/bridge-run.js.map +1 -0
- package/lib/host/controller/captures.d.ts +15 -0
- package/lib/host/controller/captures.d.ts.map +1 -0
- package/lib/host/controller/captures.js +85 -0
- package/lib/host/controller/captures.js.map +1 -0
- package/lib/host/controller/commits.d.ts +4 -0
- package/lib/host/controller/commits.d.ts.map +1 -0
- package/lib/host/controller/commits.js +131 -0
- package/lib/host/controller/commits.js.map +1 -0
- package/lib/host/controller/connections.d.ts +38 -0
- package/lib/host/controller/connections.d.ts.map +1 -0
- package/lib/host/controller/connections.js +71 -0
- package/lib/host/controller/connections.js.map +1 -0
- package/lib/host/controller/controller.d.ts +35 -0
- package/lib/host/controller/controller.d.ts.map +1 -0
- package/lib/host/controller/controller.js +234 -0
- package/lib/host/controller/controller.js.map +1 -0
- package/lib/host/controller/index.d.ts +30 -0
- package/lib/host/controller/index.d.ts.map +1 -0
- package/lib/host/controller/index.js +27 -0
- package/lib/host/controller/index.js.map +1 -0
- package/lib/host/controller/notes.d.ts +26 -0
- package/lib/host/controller/notes.d.ts.map +1 -0
- package/lib/host/controller/notes.js +44 -0
- package/lib/host/controller/notes.js.map +1 -0
- package/lib/host/controller/persist.d.ts +16 -0
- package/lib/host/controller/persist.d.ts.map +1 -0
- package/lib/host/controller/persist.js +98 -0
- package/lib/host/controller/persist.js.map +1 -0
- package/lib/host/controller/publish.d.ts +4 -0
- package/lib/host/controller/publish.d.ts.map +1 -0
- package/lib/host/controller/publish.js +56 -0
- package/lib/host/controller/publish.js.map +1 -0
- package/lib/host/controller/runs.d.ts +80 -0
- package/lib/host/controller/runs.d.ts.map +1 -0
- package/lib/host/controller/runs.js +394 -0
- package/lib/host/controller/runs.js.map +1 -0
- package/lib/host/controller/state.d.ts +172 -0
- package/lib/host/controller/state.d.ts.map +1 -0
- package/lib/host/controller/state.js +2 -0
- package/lib/host/controller/state.js.map +1 -0
- package/lib/host/controller/windows-run.d.ts +17 -0
- package/lib/host/controller/windows-run.d.ts.map +1 -0
- package/lib/host/controller/windows-run.js +109 -0
- package/lib/host/controller/windows-run.js.map +1 -0
- package/lib/host/discovery/candidates.d.ts +47 -0
- package/lib/host/discovery/candidates.d.ts.map +1 -0
- package/lib/host/discovery/candidates.js +68 -0
- package/lib/host/discovery/candidates.js.map +1 -0
- package/lib/host/discovery/index.d.ts +19 -0
- package/lib/host/discovery/index.d.ts.map +1 -0
- package/lib/host/discovery/index.js +19 -0
- package/lib/host/discovery/index.js.map +1 -0
- package/lib/host/discovery/probe.d.ts +29 -0
- package/lib/host/discovery/probe.d.ts.map +1 -0
- package/lib/host/discovery/probe.js +155 -0
- package/lib/host/discovery/probe.js.map +1 -0
- package/lib/host/discovery/scan.d.ts +72 -0
- package/lib/host/discovery/scan.d.ts.map +1 -0
- package/lib/host/discovery/scan.js +195 -0
- package/lib/host/discovery/scan.js.map +1 -0
- package/lib/host/flags.d.ts +65 -0
- package/lib/host/flags.d.ts.map +1 -0
- package/lib/host/flags.js +186 -0
- package/lib/host/flags.js.map +1 -0
- package/lib/host/kind.d.ts +45 -0
- package/lib/host/kind.d.ts.map +1 -0
- package/lib/host/kind.js +251 -0
- package/lib/host/kind.js.map +1 -0
- package/lib/host/manager.d.ts +21 -0
- package/lib/host/manager.d.ts.map +1 -0
- package/lib/host/manager.js +113 -0
- package/lib/host/manager.js.map +1 -0
- package/lib/host/migration.d.ts +26 -0
- package/lib/host/migration.d.ts.map +1 -0
- package/lib/host/migration.js +127 -0
- package/lib/host/migration.js.map +1 -0
- package/lib/host/platform.d.ts +38 -0
- package/lib/host/platform.d.ts.map +1 -0
- package/lib/host/platform.js +64 -0
- package/lib/host/platform.js.map +1 -0
- package/lib/host/plugin-meta.d.ts +21 -0
- package/lib/host/plugin-meta.d.ts.map +1 -0
- package/lib/host/plugin-meta.js +21 -0
- package/lib/host/plugin-meta.js.map +1 -0
- package/lib/host/schema.d.ts +361 -0
- package/lib/host/schema.d.ts.map +1 -0
- package/lib/host/schema.js +196 -0
- package/lib/host/schema.js.map +1 -0
- package/lib/host/settings.d.ts +28 -0
- package/lib/host/settings.d.ts.map +1 -0
- package/lib/host/settings.js +91 -0
- package/lib/host/settings.js.map +1 -0
- package/lib/host/status.d.ts +25 -0
- package/lib/host/status.d.ts.map +1 -0
- package/lib/host/status.js +45 -0
- package/lib/host/status.js.map +1 -0
- package/lib/host/tool.d.ts +65 -0
- package/lib/host/tool.d.ts.map +1 -0
- package/lib/host/tool.js +52 -0
- package/lib/host/tool.js.map +1 -0
- package/lib/host/types/config.d.ts +101 -0
- package/lib/host/types/config.d.ts.map +1 -0
- package/lib/host/types/config.js +2 -0
- package/lib/host/types/config.js.map +1 -0
- package/lib/host/types/executable.d.ts +35 -0
- package/lib/host/types/executable.d.ts.map +1 -0
- package/lib/host/types/executable.js +9 -0
- package/lib/host/types/executable.js.map +1 -0
- package/lib/host/types/index.d.ts +24 -0
- package/lib/host/types/index.d.ts.map +1 -0
- package/lib/host/types/index.js +2 -0
- package/lib/host/types/index.js.map +1 -0
- package/lib/host/types/plugin.d.ts +38 -0
- package/lib/host/types/plugin.d.ts.map +1 -0
- package/lib/host/types/plugin.js +10 -0
- package/lib/host/types/plugin.js.map +1 -0
- package/lib/host/types/services.d.ts +26 -0
- package/lib/host/types/services.d.ts.map +1 -0
- package/lib/host/types/services.js +9 -0
- package/lib/host/types/services.js.map +1 -0
- package/lib/host/types/settings.d.ts +180 -0
- package/lib/host/types/settings.d.ts.map +1 -0
- package/lib/host/types/settings.js +2 -0
- package/lib/host/types/settings.js.map +1 -0
- package/lib/host/types/stderr.d.ts +51 -0
- package/lib/host/types/stderr.d.ts.map +1 -0
- package/lib/host/types/stderr.js +9 -0
- package/lib/host/types/stderr.js.map +1 -0
- package/lib/host/types/windows.d.ts +39 -0
- package/lib/host/types/windows.d.ts.map +1 -0
- package/lib/host/types/windows.js +9 -0
- package/lib/host/types/windows.js.map +1 -0
- package/lib/host/values.d.ts +204 -0
- package/lib/host/values.d.ts.map +1 -0
- package/lib/host/values.js +404 -0
- package/lib/host/values.js.map +1 -0
- package/lib/host/windows/connect-flags.d.ts +27 -0
- package/lib/host/windows/connect-flags.d.ts.map +1 -0
- package/lib/host/windows/connect-flags.js +97 -0
- package/lib/host/windows/connect-flags.js.map +1 -0
- package/lib/host/windows/index.d.ts +31 -0
- package/lib/host/windows/index.d.ts.map +1 -0
- package/lib/host/windows/index.js +30 -0
- package/lib/host/windows/index.js.map +1 -0
- package/lib/host/windows/landing.d.ts +47 -0
- package/lib/host/windows/landing.d.ts.map +1 -0
- package/lib/host/windows/landing.js +174 -0
- package/lib/host/windows/landing.js.map +1 -0
- package/lib/host/windows/link.d.ts +11 -0
- package/lib/host/windows/link.d.ts.map +1 -0
- package/lib/host/windows/link.js +52 -0
- package/lib/host/windows/link.js.map +1 -0
- package/lib/host/windows/paths.d.ts +64 -0
- package/lib/host/windows/paths.d.ts.map +1 -0
- package/lib/host/windows/paths.js +148 -0
- package/lib/host/windows/paths.js.map +1 -0
- package/lib/host/windows/run.d.ts +74 -0
- package/lib/host/windows/run.d.ts.map +1 -0
- package/lib/host/windows/run.js +211 -0
- package/lib/host/windows/run.js.map +1 -0
- package/lib/host/windows/spawn.d.ts +22 -0
- package/lib/host/windows/spawn.d.ts.map +1 -0
- package/lib/host/windows/spawn.js +73 -0
- package/lib/host/windows/spawn.js.map +1 -0
- package/lib/index.d.ts +102 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +102 -636
- package/lib/index.js.map +1 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +57 -14
- 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"}
|