@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,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-half assembly — the wiring file.
|
|
3
|
+
*
|
|
4
|
+
* `apply` is deliberately the only host module that knows the parts exist; each
|
|
5
|
+
* part keeps its own behavior:
|
|
6
|
+
*
|
|
7
|
+
* ./controller/ the live mirror, the executable runs, the Windows run, the
|
|
8
|
+
* capture paths
|
|
9
|
+
* ./manager.ts the `chrome` + `chrome-windows` kinds and the standalone
|
|
10
|
+
* translation — what this component says to the manager
|
|
11
|
+
* ./settings.ts the configuration form's attach + commit routing + id rule
|
|
12
|
+
* ./commands/ the two headless-mirror slash commands
|
|
13
|
+
* ./tool.ts the MCP-side `prelaunch_windows_chrome` trigger
|
|
14
|
+
*
|
|
15
|
+
* The ordering rule that must survive the split: read the live layers through
|
|
16
|
+
* `source()` at commit time, never capture them — cordis starts the `settings`
|
|
17
|
+
* injection callback after `apply` returns, so a captured value would pin every
|
|
18
|
+
* consumer to the row config and no mid-session GUI edit would ever reach a
|
|
19
|
+
* live connection.
|
|
20
|
+
*
|
|
21
|
+
* What changed with the component model: this row **no longer starts a bridge
|
|
22
|
+
* of its own**. It answers live `chrome` / `chrome-windows` connections instead,
|
|
23
|
+
* and answers nothing at all when no manager is mounted. Mounting therefore
|
|
24
|
+
* stands up the machine half (the mirror, the executable catalog, the runs) and
|
|
25
|
+
* registers the kinds; whether anything runs is the pool's decision.
|
|
26
|
+
*
|
|
27
|
+
* @param ctx - plugin context.
|
|
28
|
+
* @param config - validated config (every volatile field a reference).
|
|
29
|
+
*/
|
|
30
|
+
import { type ChromeMcpControllerDeps } from "./controller/index.js";
|
|
31
|
+
import type { ChromeMcpConfig, PluginContext } from "./types/index.js";
|
|
32
|
+
/**
|
|
33
|
+
* @param deps - the controller's optional host overrides, passed straight
|
|
34
|
+
* through. Nothing ordinary supplies them — the wiring reaches the machine
|
|
35
|
+
* through the controller's own defaults, so this parameter is what lets a test
|
|
36
|
+
* or a diagnostic answer the machine half (the Windows run, the Windows-side
|
|
37
|
+
* executables the run folds into a candidate list) with a known list.
|
|
38
|
+
*/
|
|
39
|
+
export declare function apply(ctx: PluginContext, config: ChromeMcpConfig, deps?: ChromeMcpControllerDeps): void;
|
|
40
|
+
//# sourceMappingURL=apply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/host/apply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAA6B,KAAK,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAKhG,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEvE;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI,GAAE,uBAA4B,GAAG,IAAI,CAc3G"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-half assembly — the wiring file.
|
|
3
|
+
*
|
|
4
|
+
* `apply` is deliberately the only host module that knows the parts exist; each
|
|
5
|
+
* part keeps its own behavior:
|
|
6
|
+
*
|
|
7
|
+
* ./controller/ the live mirror, the executable runs, the Windows run, the
|
|
8
|
+
* capture paths
|
|
9
|
+
* ./manager.ts the `chrome` + `chrome-windows` kinds and the standalone
|
|
10
|
+
* translation — what this component says to the manager
|
|
11
|
+
* ./settings.ts the configuration form's attach + commit routing + id rule
|
|
12
|
+
* ./commands/ the two headless-mirror slash commands
|
|
13
|
+
* ./tool.ts the MCP-side `prelaunch_windows_chrome` trigger
|
|
14
|
+
*
|
|
15
|
+
* The ordering rule that must survive the split: read the live layers through
|
|
16
|
+
* `source()` at commit time, never capture them — cordis starts the `settings`
|
|
17
|
+
* injection callback after `apply` returns, so a captured value would pin every
|
|
18
|
+
* consumer to the row config and no mid-session GUI edit would ever reach a
|
|
19
|
+
* live connection.
|
|
20
|
+
*
|
|
21
|
+
* What changed with the component model: this row **no longer starts a bridge
|
|
22
|
+
* of its own**. It answers live `chrome` / `chrome-windows` connections instead,
|
|
23
|
+
* and answers nothing at all when no manager is mounted. Mounting therefore
|
|
24
|
+
* stands up the machine half (the mirror, the executable catalog, the runs) and
|
|
25
|
+
* registers the kinds; whether anything runs is the pool's decision.
|
|
26
|
+
*
|
|
27
|
+
* @param ctx - plugin context.
|
|
28
|
+
* @param config - validated config (every volatile field a reference).
|
|
29
|
+
*/
|
|
30
|
+
import { createChromeMcpController } from "./controller/index.js";
|
|
31
|
+
import { installChromeMcpCommands } from "./commands/index.js";
|
|
32
|
+
import { attachToManager } from "./manager.js";
|
|
33
|
+
import { installChromeMcpForm } from "./settings.js";
|
|
34
|
+
import { installPrelaunchWindowsChromeTool } from "./tool.js";
|
|
35
|
+
/**
|
|
36
|
+
* @param deps - the controller's optional host overrides, passed straight
|
|
37
|
+
* through. Nothing ordinary supplies them — the wiring reaches the machine
|
|
38
|
+
* through the controller's own defaults, so this parameter is what lets a test
|
|
39
|
+
* or a diagnostic answer the machine half (the Windows run, the Windows-side
|
|
40
|
+
* executables the run folds into a candidate list) with a known list.
|
|
41
|
+
*/
|
|
42
|
+
export function apply(ctx, config, deps = {}) {
|
|
43
|
+
const controller = createChromeMcpController(ctx, config, deps);
|
|
44
|
+
// Stand the instance down when the mount goes away: a hot re-apply must not
|
|
45
|
+
// leave the previous instance's late answers (a scheduled retry above all)
|
|
46
|
+
// firing runs no one asked for.
|
|
47
|
+
ctx.effect(() => () => {
|
|
48
|
+
controller.dispose();
|
|
49
|
+
}, "chrome-mcp: controller teardown");
|
|
50
|
+
// The kinds come first, before the form: a connection saved under either
|
|
51
|
+
// kind is answered through them, and a proposal names them by id.
|
|
52
|
+
attachToManager(ctx, controller);
|
|
53
|
+
installChromeMcpForm(ctx, controller);
|
|
54
|
+
installPrelaunchWindowsChromeTool(ctx, controller);
|
|
55
|
+
installChromeMcpCommands(ctx, config, controller);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/host/apply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,yBAAyB,EAAgC,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,iCAAiC,EAAE,MAAM,WAAW,CAAC;AAG9D;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,GAAkB,EAAE,MAAuB,EAAE,OAAgC,EAAE;IACjG,MAAM,UAAU,GAAG,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAChE,4EAA4E;IAC5E,2EAA2E;IAC3E,gCAAgC;IAChC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE;QAClB,UAAU,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC,EAAE,iCAAiC,CAAC,CAAC;IACtC,yEAAyE;IACzE,kEAAkE;IAClE,eAAe,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACjC,oBAAoB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACtC,iCAAiC,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACnD,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type * as McpClient from "@deepseek-ai/dsh-mcp-client";
|
|
2
|
+
import type { BridgeSpawnOptions, BridgeSpawnResult, BridgeSpawnTarget, BridgeStderrLogPathOptions, BridgeStderrMode, ChromeMcpConfig } from "./types/index.js";
|
|
3
|
+
/** The CLI of the `chrome-devtools-mcp` this package depends on (pinned). */
|
|
4
|
+
export declare function pinnedServerCli(): string;
|
|
5
|
+
/** Whether a row runs the pinned server: it names no launcher of its own (the
|
|
6
|
+
* schema defaults, or blanks). */
|
|
7
|
+
export declare function usesPinnedServer(entry: Pick<ChromeMcpConfig, "command" | "package">): boolean;
|
|
8
|
+
/** The executable one row's server runs under: this Node for the pinned
|
|
9
|
+
* server, the row's own `command` otherwise. */
|
|
10
|
+
export declare function serverCommand(entry: Pick<ChromeMcpConfig, "command" | "package">, execPath?: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Build the stdio argv tail for one flags list — `<pinned cli> [extraFlags]`
|
|
13
|
+
* for the pinned server, `-y <package> [extraFlags]` for a row's own launcher;
|
|
14
|
+
* the argv {@link buildBridgeSpawn} runs after {@link serverCommand}.
|
|
15
|
+
* When `chromePath` is set and the flags do not already carry an executable-path
|
|
16
|
+
* option, `--executablePath=<path>` is appended (upstream option:
|
|
17
|
+
* https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/docs/configuration.md).
|
|
18
|
+
* A connect-mode flag takes the whole executable out of the argv: with
|
|
19
|
+
* `--browserUrl` / `--wsEndpoint` present there is nothing local to launch, so
|
|
20
|
+
* the path is never appended next to it — the bridge connects, it does not
|
|
21
|
+
* launch.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildServerArgs(entry: ChromeMcpConfig, extraFlags: string[]): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Default location of the bridge stderr log — `@comecaramelos/dsh-ancesters`'
|
|
26
|
+
* private per-host directory (`mkdtemp`, mode `0700`), one
|
|
27
|
+
* `<serverName>-bridge.log` per bridge, truncated on every spawn. Nothing in it
|
|
28
|
+
* can be planted by another local principal before the first spawn.
|
|
29
|
+
*
|
|
30
|
+
* `options.tmpdir` keeps a flat, deterministic name for tests and diagnostics.
|
|
31
|
+
* @param serverName - the bridge server namespace.
|
|
32
|
+
* @param options - tmpdir/pid overrides for tests and diagnostics.
|
|
33
|
+
*/
|
|
34
|
+
export declare function bridgeStderrLogPath(serverName: unknown, options?: BridgeStderrLogPathOptions): string;
|
|
35
|
+
/**
|
|
36
|
+
* Build the stdio spawn target for one bridge run, honouring the effective
|
|
37
|
+
* stderr mode. The MCP stdio transport spawns the child with the default
|
|
38
|
+
* `stderr: "inherit"`, so every line it prints lands on the dsh console.
|
|
39
|
+
* "log" (default) launches the argv through ancestros' Node wrapper (D5:
|
|
40
|
+
* `process.execPath` + a shipped script, the same route on Linux, WSL and
|
|
41
|
+
* Windows): stdout keeps flowing as the MCP protocol stream, stderr goes to
|
|
42
|
+
* the log file, the argv reaches the child verbatim. "console" returns the raw
|
|
43
|
+
* command/args (inherited console output).
|
|
44
|
+
* @param target - { command, args, stderr?, logPath?, serverName? }.
|
|
45
|
+
* @param options - execPath/tmpdir/pid overrides for tests.
|
|
46
|
+
* @returns { command, args, redirect } — the log file when redirected, "" when
|
|
47
|
+
* the console echoes. There is no fallback left: Node is always there.
|
|
48
|
+
*/
|
|
49
|
+
export declare function buildBridgeSpawn(target: BridgeSpawnTarget, options?: BridgeSpawnOptions): BridgeSpawnResult;
|
|
50
|
+
/**
|
|
51
|
+
* stdio config for the nested mcp-client bridge for one flags list + effective
|
|
52
|
+
* stderr mode. The args keep the user's original logical invocation shape
|
|
53
|
+
* (`npx -y <package> [extraFlags]`, run as `command`), wrapped through
|
|
54
|
+
* {@link buildBridgeSpawn} so the child's stderr lands in a log file instead of
|
|
55
|
+
* the console when the mode is "log". The returned config carries only
|
|
56
|
+
* dsh-mcp-client fields; `redirect` describes the wrapper for the
|
|
57
|
+
* host's own diagnostics.
|
|
58
|
+
*/
|
|
59
|
+
export declare function bridgeConfig(entry: ChromeMcpConfig, extraFlags: string[], stderrMode?: BridgeStderrMode): {
|
|
60
|
+
config: McpClient.StdioConfig;
|
|
61
|
+
redirect: string;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Wrap a logger so a callback observes every level call before the
|
|
65
|
+
* original runs. Used to capture the nested bridge's own log lines (the only
|
|
66
|
+
* surface dsh-mcp-client exposes for connection failures — reconnect
|
|
67
|
+
* backoff warnings, spawn failures, give-ups) into the live mirror.
|
|
68
|
+
* The wrapper shares the underlying LoggerService (exporters/buffer included)
|
|
69
|
+
* and only shadows the level methods.
|
|
70
|
+
* @param base - the base logger to wrap (cordis LoggerService).
|
|
71
|
+
* @param note - callback invoked for every log level before the original runs.
|
|
72
|
+
*/
|
|
73
|
+
export declare function captureLogger(base: Record<string, (...args: unknown[]) => unknown>, note: (level: string, args: unknown[]) => void): Record<string, (...args: unknown[]) => unknown>;
|
|
74
|
+
//# sourceMappingURL=bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/host/bridge.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,KAAK,SAAS,MAAM,6BAA6B,CAAC;AAE9D,OAAO,KAAK,EACR,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,0BAA0B,EAC1B,gBAAgB,EAChB,eAAe,EAClB,MAAM,kBAAkB,CAAC;AAO1B,6EAA6E;AAC7E,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;kCACkC;AAClC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,SAAS,CAAC,GAAG,OAAO,CAI7F;AAED;gDACgD;AAChD,wBAAgB,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,SAAS,CAAC,EAAE,QAAQ,GAAE,MAAyB,GAAG,MAAM,CAE9H;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAUtF;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,GAAE,0BAA+B,GAAG,MAAM,CAEzG;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,GAAE,kBAAuB,GAAG,iBAAiB,CAY/G;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,UAAU,CAAC,EAAE,gBAAgB;;;EAwBvG;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,EACrD,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAC/C,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAcjD"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The nested `dsh-mcp-client` bridge: its stdio argv + config, the stderr
|
|
3
|
+
* capture wrapper, and the logger wrapper that captures its own log lines into
|
|
4
|
+
* the live mirror.
|
|
5
|
+
*
|
|
6
|
+
* The bridge's *logical* argv is the public contract the tests and the README
|
|
7
|
+
* quote. By default it is the `chrome-devtools-mcp` this package depends on,
|
|
8
|
+
* pinned, run by the same Node that runs the host —
|
|
9
|
+
* `<node> <chrome-devtools-mcp cli> [extraFlags]`, the way dsh's own
|
|
10
|
+
* chrome-devtools provider runs it: no `npx`, no registry on every start, the
|
|
11
|
+
* same route on Linux, WSL and Windows (breaking in 2.0). A row that names its
|
|
12
|
+
* own `command` or `package` keeps `<command> -y <package> [extraFlags]`.
|
|
13
|
+
* `--executablePath=<chromePath>` is appended only when a path is configured
|
|
14
|
+
* and the flags list does not already pin an executable. In the default "log"
|
|
15
|
+
* stderr mode that argv is not spawned
|
|
16
|
+
* raw: {@link buildBridgeSpawn} launches it through ancestros' Node wrapper, which
|
|
17
|
+
* hands the argv over verbatim (the child never sees the wrapper) and sends only
|
|
18
|
+
* stderr into a per-spawn log file, leaving stdout to carry the MCP protocol
|
|
19
|
+
* stream. Without this wrapper every startup/progress line npx prints would
|
|
20
|
+
* land directly on the dsh console — exactly what makes the connection feel
|
|
21
|
+
* loud. "console" mode spawns the argv unwrapped (inherited stderr, debug).
|
|
22
|
+
*
|
|
23
|
+
* The logger wrapper exists because dsh-mcp-client reports connection problems
|
|
24
|
+
* only through `ctx.logger`: without it the card would never surface a
|
|
25
|
+
* failed/recovered bridge.
|
|
26
|
+
*/
|
|
27
|
+
import { fileURLToPath } from "node:url";
|
|
28
|
+
import { buildSpawn, stderrLogPath } from "@comecaramelos/dsh-ancesters/host";
|
|
29
|
+
import { LOG_LEVELS } from "./constants.js";
|
|
30
|
+
import { carriesExecutablePath, flagsSkipCheck } from "./flags.js";
|
|
31
|
+
import { readConfigField } from "./values.js";
|
|
32
|
+
/** The row defaults that mean "the pinned server": a row that never named its
|
|
33
|
+
* own launcher. */
|
|
34
|
+
const DEFAULT_COMMAND = "npx";
|
|
35
|
+
const DEFAULT_PACKAGE = "chrome-devtools-mcp@latest";
|
|
36
|
+
/** The CLI of the `chrome-devtools-mcp` this package depends on (pinned). */
|
|
37
|
+
export function pinnedServerCli() {
|
|
38
|
+
return fileURLToPath(import.meta.resolve("chrome-devtools-mcp/build/src/bin/chrome-devtools-mcp.js"));
|
|
39
|
+
}
|
|
40
|
+
/** Whether a row runs the pinned server: it names no launcher of its own (the
|
|
41
|
+
* schema defaults, or blanks). */
|
|
42
|
+
export function usesPinnedServer(entry) {
|
|
43
|
+
const command = String(entry.command ?? "").trim();
|
|
44
|
+
const pkg = String(entry.package ?? "").trim();
|
|
45
|
+
return (command === "" || command === DEFAULT_COMMAND) && (pkg === "" || pkg === DEFAULT_PACKAGE);
|
|
46
|
+
}
|
|
47
|
+
/** The executable one row's server runs under: this Node for the pinned
|
|
48
|
+
* server, the row's own `command` otherwise. */
|
|
49
|
+
export function serverCommand(entry, execPath = process.execPath) {
|
|
50
|
+
return usesPinnedServer(entry) ? execPath : String(entry.command);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Build the stdio argv tail for one flags list — `<pinned cli> [extraFlags]`
|
|
54
|
+
* for the pinned server, `-y <package> [extraFlags]` for a row's own launcher;
|
|
55
|
+
* the argv {@link buildBridgeSpawn} runs after {@link serverCommand}.
|
|
56
|
+
* When `chromePath` is set and the flags do not already carry an executable-path
|
|
57
|
+
* option, `--executablePath=<path>` is appended (upstream option:
|
|
58
|
+
* https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/docs/configuration.md).
|
|
59
|
+
* A connect-mode flag takes the whole executable out of the argv: with
|
|
60
|
+
* `--browserUrl` / `--wsEndpoint` present there is nothing local to launch, so
|
|
61
|
+
* the path is never appended next to it — the bridge connects, it does not
|
|
62
|
+
* launch.
|
|
63
|
+
*/
|
|
64
|
+
export function buildServerArgs(entry, extraFlags) {
|
|
65
|
+
const flags = Array.isArray(extraFlags) ? extraFlags.filter((flag) => typeof flag === "string") : [];
|
|
66
|
+
const args = usesPinnedServer(entry) ? [pinnedServerCli(), ...flags] : ["-y", entry.package, ...flags];
|
|
67
|
+
// `chromePath` is a volatile field, so what it carries is either a reference
|
|
68
|
+
// or the value a caller handed in explicitly (the resolved selection).
|
|
69
|
+
const executable = readConfigField(entry.chromePath, "").trim();
|
|
70
|
+
if (executable !== "" && !flags.some((flag) => carriesExecutablePath(flag)) && !flagsSkipCheck(flags)) {
|
|
71
|
+
args.push(`--executablePath=${executable}`);
|
|
72
|
+
}
|
|
73
|
+
return args;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Default location of the bridge stderr log — `@comecaramelos/dsh-ancesters`'
|
|
77
|
+
* private per-host directory (`mkdtemp`, mode `0700`), one
|
|
78
|
+
* `<serverName>-bridge.log` per bridge, truncated on every spawn. Nothing in it
|
|
79
|
+
* can be planted by another local principal before the first spawn.
|
|
80
|
+
*
|
|
81
|
+
* `options.tmpdir` keeps a flat, deterministic name for tests and diagnostics.
|
|
82
|
+
* @param serverName - the bridge server namespace.
|
|
83
|
+
* @param options - tmpdir/pid overrides for tests and diagnostics.
|
|
84
|
+
*/
|
|
85
|
+
export function bridgeStderrLogPath(serverName, options = {}) {
|
|
86
|
+
return stderrLogPath(serverName, options);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Build the stdio spawn target for one bridge run, honouring the effective
|
|
90
|
+
* stderr mode. The MCP stdio transport spawns the child with the default
|
|
91
|
+
* `stderr: "inherit"`, so every line it prints lands on the dsh console.
|
|
92
|
+
* "log" (default) launches the argv through ancestros' Node wrapper (D5:
|
|
93
|
+
* `process.execPath` + a shipped script, the same route on Linux, WSL and
|
|
94
|
+
* Windows): stdout keeps flowing as the MCP protocol stream, stderr goes to
|
|
95
|
+
* the log file, the argv reaches the child verbatim. "console" returns the raw
|
|
96
|
+
* command/args (inherited console output).
|
|
97
|
+
* @param target - { command, args, stderr?, logPath?, serverName? }.
|
|
98
|
+
* @param options - execPath/tmpdir/pid overrides for tests.
|
|
99
|
+
* @returns { command, args, redirect } — the log file when redirected, "" when
|
|
100
|
+
* the console echoes. There is no fallback left: Node is always there.
|
|
101
|
+
*/
|
|
102
|
+
export function buildBridgeSpawn(target, options = {}) {
|
|
103
|
+
const mode = target.stderr === void 0 ? "log" : target.stderr;
|
|
104
|
+
return buildSpawn({
|
|
105
|
+
command: target.command,
|
|
106
|
+
args: [...target.args],
|
|
107
|
+
stderr: mode,
|
|
108
|
+
...(typeof target.logPath === "string" && target.logPath !== "" ? { logPath: target.logPath } : {}),
|
|
109
|
+
serverName: target.serverName ?? "bridge"
|
|
110
|
+
}, options);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* stdio config for the nested mcp-client bridge for one flags list + effective
|
|
114
|
+
* stderr mode. The args keep the user's original logical invocation shape
|
|
115
|
+
* (`npx -y <package> [extraFlags]`, run as `command`), wrapped through
|
|
116
|
+
* {@link buildBridgeSpawn} so the child's stderr lands in a log file instead of
|
|
117
|
+
* the console when the mode is "log". The returned config carries only
|
|
118
|
+
* dsh-mcp-client fields; `redirect` describes the wrapper for the
|
|
119
|
+
* host's own diagnostics.
|
|
120
|
+
*/
|
|
121
|
+
export function bridgeConfig(entry, extraFlags, stderrMode) {
|
|
122
|
+
const spawned = buildBridgeSpawn({
|
|
123
|
+
command: serverCommand(entry),
|
|
124
|
+
args: buildServerArgs(entry, extraFlags),
|
|
125
|
+
stderr: stderrMode === void 0 ? entry.bridgeStderr : stderrMode,
|
|
126
|
+
logPath: entry.bridgeStderrLog,
|
|
127
|
+
serverName: entry.serverName
|
|
128
|
+
}, {});
|
|
129
|
+
const config = {
|
|
130
|
+
serverName: entry.serverName,
|
|
131
|
+
transport: "stdio",
|
|
132
|
+
command: spawned.command,
|
|
133
|
+
args: spawned.args,
|
|
134
|
+
env: entry.env,
|
|
135
|
+
cwd: entry.cwd,
|
|
136
|
+
toolCallTimeoutMs: entry.toolCallTimeoutMs,
|
|
137
|
+
maxInstructionBytes: entry.maxInstructionBytes,
|
|
138
|
+
failOnStartupError: entry.failOnStartupError,
|
|
139
|
+
reconnect: entry.reconnect
|
|
140
|
+
};
|
|
141
|
+
return { config, redirect: spawned.redirect };
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Wrap a logger so a callback observes every level call before the
|
|
145
|
+
* original runs. Used to capture the nested bridge's own log lines (the only
|
|
146
|
+
* surface dsh-mcp-client exposes for connection failures — reconnect
|
|
147
|
+
* backoff warnings, spawn failures, give-ups) into the live mirror.
|
|
148
|
+
* The wrapper shares the underlying LoggerService (exporters/buffer included)
|
|
149
|
+
* and only shadows the level methods.
|
|
150
|
+
* @param base - the base logger to wrap (cordis LoggerService).
|
|
151
|
+
* @param note - callback invoked for every log level before the original runs.
|
|
152
|
+
*/
|
|
153
|
+
export function captureLogger(base, note) {
|
|
154
|
+
const wrapper = ((...args) => {
|
|
155
|
+
const callBase = base;
|
|
156
|
+
return callBase(...args);
|
|
157
|
+
});
|
|
158
|
+
Object.setPrototypeOf(wrapper, Object.getPrototypeOf(base));
|
|
159
|
+
Object.assign(wrapper, base);
|
|
160
|
+
for (const level of LOG_LEVELS) {
|
|
161
|
+
wrapper[level] = (...args) => {
|
|
162
|
+
note(level, args);
|
|
163
|
+
return base[level]?.(...args);
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
return wrapper;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/host/bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** One catalog row: the path on the wire + the custom UI label. */
|
|
2
|
+
export type ChromeExecutableEntry = {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
};
|
|
6
|
+
/** Whether one id is usable as an executable row (a path with no control
|
|
7
|
+
* characters, capped like the `chromePath` it stands for). */
|
|
8
|
+
export declare function isValidEntryId(id: unknown): boolean;
|
|
9
|
+
/** One row label: the custom name when it has one, else the path. */
|
|
10
|
+
export declare function entryLabel(entry: ChromeExecutableEntry): string;
|
|
11
|
+
/**
|
|
12
|
+
* Coerce anything into well-formed rows: trim both fields, drop ids that cannot
|
|
13
|
+
* go on the wire, keep the first row per id, cap the name, cap the list (the
|
|
14
|
+
* tail drops off). A served array is already normalized; one read straight from a
|
|
15
|
+
* form write is not, so the row writer is the place that makes it safe.
|
|
16
|
+
*/
|
|
17
|
+
export declare function normalizeEntries(value: unknown): ChromeExecutableEntry[];
|
|
18
|
+
/**
|
|
19
|
+
* Merge the ids a scan found into the stored rows: rows keep their order and
|
|
20
|
+
* their custom names, ids that are not represented land last, nameless.
|
|
21
|
+
* @returns the merged rows, plus `changed` so a caller can skip a no-op write.
|
|
22
|
+
*/
|
|
23
|
+
export declare function mergeEntries(stored: unknown, ids: readonly string[]): {
|
|
24
|
+
entries: ChromeExecutableEntry[];
|
|
25
|
+
changed: boolean;
|
|
26
|
+
};
|
|
27
|
+
/** The ids a catalog currently carries, in row order. */
|
|
28
|
+
export declare function entryIds(entries: readonly ChromeExecutableEntry[] | undefined): string[];
|
|
29
|
+
/** One row lookup by id (`undefined` when absent). */
|
|
30
|
+
export declare function findEntry(entries: readonly ChromeExecutableEntry[], id: string): ChromeExecutableEntry | undefined;
|
|
31
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/host/catalog.ts"],"names":[],"mappings":"AAuBA,mEAAmE;AACnE,MAAM,MAAM,qBAAqB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE;8DAC8D;AAC9D,wBAAgB,cAAc,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAKnD;AAED,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAG/D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,qBAAqB,EAAE,CAexE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CACxB,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,SAAS,MAAM,EAAE,GACvB;IAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAYxD;AAED,yDAAyD;AACzD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,SAAS,qBAAqB,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,CAExF;AAED,sDAAsD;AACtD,wBAAgB,SAAS,CACrB,OAAO,EAAE,SAAS,qBAAqB,EAAE,EACzC,EAAE,EAAE,MAAM,GACX,qBAAqB,GAAG,SAAS,CAEnC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host half — the named rows behind the executable picker.
|
|
3
|
+
*
|
|
4
|
+
* One row is `{ id, name }`: the `id` is what goes on the wire (the path the
|
|
5
|
+
* bridge launches with, appended as `--executablePath=<id>`), while `name` is
|
|
6
|
+
* purely the label the user chose for the UI — the same id-is-path / name-is-
|
|
7
|
+
* label split the reference plugin (`dsh-docker-desktop-mcp`) carries for its
|
|
8
|
+
* executables catalog, so the card is one widget shape instead of a bespoke
|
|
9
|
+
* dropdown-plus-text-box.
|
|
10
|
+
*
|
|
11
|
+
* Everything here is pure and total: nothing throws on odd input, so the
|
|
12
|
+
* settings `validate` hook can never stall the settings gate on a malformed
|
|
13
|
+
* row. The browser half mirrors these rules in `src/client/catalog.ts`
|
|
14
|
+
* (separate bundle, one source of truth per rule in each half).
|
|
15
|
+
*
|
|
16
|
+
* Merge rule (the reference's "Fetch executables" behaviour): keep every stored
|
|
17
|
+
* row in order with its custom name, append the ids the scan found that are not
|
|
18
|
+
* represented yet with an empty name. A row the user deleted only comes back if
|
|
19
|
+
* a later source still reports its id, which is why the legacy `chromeCustomPaths`
|
|
20
|
+
* MRU folds in exactly once, before the rows are written by anything else.
|
|
21
|
+
*/
|
|
22
|
+
import { CATALOG_MAX_LENGTH, CATALOG_NAME_MAX_LENGTH, CHROME_PATH_PATTERN } from "./constants.js";
|
|
23
|
+
/** Whether one id is usable as an executable row (a path with no control
|
|
24
|
+
* characters, capped like the `chromePath` it stands for). */
|
|
25
|
+
export function isValidEntryId(id) {
|
|
26
|
+
if (typeof id !== "string")
|
|
27
|
+
return false;
|
|
28
|
+
const path = id.trim();
|
|
29
|
+
if (path === "" || path.length > 1024)
|
|
30
|
+
return false;
|
|
31
|
+
return CHROME_PATH_PATTERN.test(path);
|
|
32
|
+
}
|
|
33
|
+
/** One row label: the custom name when it has one, else the path. */
|
|
34
|
+
export function entryLabel(entry) {
|
|
35
|
+
const name = entry.name.trim();
|
|
36
|
+
return name === "" ? entry.id : name;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Coerce anything into well-formed rows: trim both fields, drop ids that cannot
|
|
40
|
+
* go on the wire, keep the first row per id, cap the name, cap the list (the
|
|
41
|
+
* tail drops off). A served array is already normalized; one read straight from a
|
|
42
|
+
* form write is not, so the row writer is the place that makes it safe.
|
|
43
|
+
*/
|
|
44
|
+
export function normalizeEntries(value) {
|
|
45
|
+
if (!Array.isArray(value))
|
|
46
|
+
return [];
|
|
47
|
+
const out = [];
|
|
48
|
+
const seen = new Set();
|
|
49
|
+
for (const item of value) {
|
|
50
|
+
if (out.length === CATALOG_MAX_LENGTH)
|
|
51
|
+
break;
|
|
52
|
+
if (item === null || typeof item !== "object" || Array.isArray(item))
|
|
53
|
+
continue;
|
|
54
|
+
const raw = item;
|
|
55
|
+
const id = typeof raw.id === "string" ? raw.id.trim() : "";
|
|
56
|
+
if (!isValidEntryId(id) || seen.has(id))
|
|
57
|
+
continue;
|
|
58
|
+
seen.add(id);
|
|
59
|
+
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
60
|
+
out.push({ id, name: name.slice(0, CATALOG_NAME_MAX_LENGTH) });
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Merge the ids a scan found into the stored rows: rows keep their order and
|
|
66
|
+
* their custom names, ids that are not represented land last, nameless.
|
|
67
|
+
* @returns the merged rows, plus `changed` so a caller can skip a no-op write.
|
|
68
|
+
*/
|
|
69
|
+
export function mergeEntries(stored, ids) {
|
|
70
|
+
const entries = normalizeEntries(stored);
|
|
71
|
+
const present = new Set(entries.map((entry) => entry.id));
|
|
72
|
+
const merged = entries.slice();
|
|
73
|
+
for (const id of ids) {
|
|
74
|
+
if (merged.length >= CATALOG_MAX_LENGTH)
|
|
75
|
+
break;
|
|
76
|
+
const path = typeof id === "string" ? id.trim() : "";
|
|
77
|
+
if (!isValidEntryId(path) || present.has(path))
|
|
78
|
+
continue;
|
|
79
|
+
present.add(path);
|
|
80
|
+
merged.push({ id: path, name: "" });
|
|
81
|
+
}
|
|
82
|
+
return { entries: merged, changed: JSON.stringify(merged) !== JSON.stringify(entries) };
|
|
83
|
+
}
|
|
84
|
+
/** The ids a catalog currently carries, in row order. */
|
|
85
|
+
export function entryIds(entries) {
|
|
86
|
+
return (entries === void 0 ? [] : entries).map((entry) => entry.id);
|
|
87
|
+
}
|
|
88
|
+
/** One row lookup by id (`undefined` when absent). */
|
|
89
|
+
export function findEntry(entries, id) {
|
|
90
|
+
return entries.find((entry) => entry.id === id);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/host/catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ChromeMcpController } from "../controller/index.js";
|
|
2
|
+
import type { CommandDefinition } from "../types/index.js";
|
|
3
|
+
export declare function createChromePathCommand(controller: ChromeMcpController): CommandDefinition;
|
|
4
|
+
//# sourceMappingURL=chrome-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chrome-path.d.ts","sourceRoot":"","sources":["../../../src/host/commands/chrome-path.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAI3D,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,mBAAmB,GAAG,iBAAiB,CAgD1F"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/chrome-path` — the headless mirror of the card's executable picker.
|
|
3
|
+
*
|
|
4
|
+
* It answers what the pill states and changes what it changes, reading the saved
|
|
5
|
+
* rows and the live mirror exactly the way the card reads them, and writing the
|
|
6
|
+
* one same persisted `chromePath` field through the controller's write-back
|
|
7
|
+
* channel (`selectChromePath` — `persistChromePath`, i.e. one `settings.mutate`
|
|
8
|
+
* on the row's entry id, the live clear riding along) — never a route of its
|
|
9
|
+
* own. `none` clears the user layer back to what the row config carries under
|
|
10
|
+
* it, which is the same answer a cleared picker reads with. And a path write
|
|
11
|
+
* answers against the same validation gate a GUI write runs through: the
|
|
12
|
+
* field's own schema pattern, so control characters are refused here exactly as
|
|
13
|
+
* they are refused on the card door.
|
|
14
|
+
*/
|
|
15
|
+
import { entryLabel } from "../catalog.js";
|
|
16
|
+
import { CHROME_PATH_PATTERN } from "../constants.js";
|
|
17
|
+
import { readSavedExecutables } from "../values.js";
|
|
18
|
+
const USAGE = "Usage: /chrome-path <path> — select the Chrome executable the row launches by default. Use /chrome-path none to clear the selection back to the row config.";
|
|
19
|
+
export function createChromePathCommand(controller) {
|
|
20
|
+
return {
|
|
21
|
+
name: "chrome-path",
|
|
22
|
+
description: "Show or change the Chrome executable the row launches by default",
|
|
23
|
+
input: { hint: "[<path>|none]" },
|
|
24
|
+
async handler(invocation) {
|
|
25
|
+
const input = invocation.rawInput.trim();
|
|
26
|
+
// No argument answers the question the pill states, with the saved
|
|
27
|
+
// rows the picker would offer beneath it.
|
|
28
|
+
if (input === "") {
|
|
29
|
+
const live = controller.live;
|
|
30
|
+
const saved = readSavedExecutables(controller.source());
|
|
31
|
+
const lines = [
|
|
32
|
+
`Current executable: ${live.effectiveChromePath === "" ? "(nothing)" : live.effectiveChromePath}`,
|
|
33
|
+
`Source: ${live.effectiveSource === "" ? "nothing selected" : live.effectiveSource}.`
|
|
34
|
+
];
|
|
35
|
+
lines.push(saved.length === 0 ? "Saved executables: (none — /chrome-refresh discovers them)." : `Saved executables:\n${saved.map((entry) => ` - ${entryLabel(entry)}`).join("\n")}`);
|
|
36
|
+
lines.push(USAGE);
|
|
37
|
+
return { kind: "success", text: lines.join("\n") };
|
|
38
|
+
}
|
|
39
|
+
// The one cleared write: the user layer answers empty again and the
|
|
40
|
+
// row config's own path stands underneath it.
|
|
41
|
+
if (input === "none") {
|
|
42
|
+
if (controller.live.effectiveChromePath === "" && controller.live.effectiveSource === "") {
|
|
43
|
+
return { kind: "success", text: "No executable is selected — there is nothing to clear." };
|
|
44
|
+
}
|
|
45
|
+
await controller.selectChromePath("");
|
|
46
|
+
return { kind: "success", text: "Executable selection cleared — the row launches by default with whatever the row config carries." };
|
|
47
|
+
}
|
|
48
|
+
// Same gate the field's write runs through (../schema.ts).
|
|
49
|
+
if (!CHROME_PATH_PATTERN.test(input)) {
|
|
50
|
+
return { kind: "error", text: "Invalid executable path: control characters (or a length over the path limit) are never valid." };
|
|
51
|
+
}
|
|
52
|
+
// Already what the bridge runs with: same write the picker makes on
|
|
53
|
+
// a no-change pick — nothing lands anywhere new.
|
|
54
|
+
if (controller.live.effectiveChromePath === input && controller.live.effectiveSource === "selected") {
|
|
55
|
+
return { kind: "success", text: `The row default already stands at ${input}.` };
|
|
56
|
+
}
|
|
57
|
+
await controller.selectChromePath(input);
|
|
58
|
+
return {
|
|
59
|
+
kind: "success",
|
|
60
|
+
text: `Chrome executable selected: ${input} — a default shifts with it: live connections without their own pick re-answer, and the executable run re-runs behind the write.`
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=chrome-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chrome-path.js","sourceRoot":"","sources":["../../../src/host/commands/chrome-path.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/chrome-refresh` — the headless mirror of the card's **Fetch executables**.
|
|
3
|
+
*
|
|
4
|
+
* One executable run on demand: probe every candidate the row config, what this
|
|
5
|
+
* host carries, the saved rows and the selection carry, and merge what exists
|
|
6
|
+
* into the saved rows. The merge already stands inside the run (see
|
|
7
|
+
* ../controller/runs.ts — `runExecutableDiscovery` merges as its own step), so
|
|
8
|
+
* the headless path needs no merge step of its own: it fires the run and reads
|
|
9
|
+
* the answers off the live mirror the run publishes, never more than the run
|
|
10
|
+
* answered. The bump of `executableDiscoveryRevision` around the awaited run is
|
|
11
|
+
* what tells a reportable run from one that never completed — the statuses on
|
|
12
|
+
* the mirror could otherwise be from the last run.
|
|
13
|
+
*/
|
|
14
|
+
import type { ChromeMcpController } from "../controller/index.js";
|
|
15
|
+
import type { CommandDefinition } from "../types/index.js";
|
|
16
|
+
export declare function createChromeRefreshCommand(controller: ChromeMcpController): CommandDefinition;
|
|
17
|
+
//# sourceMappingURL=chrome-refresh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chrome-refresh.d.ts","sourceRoot":"","sources":["../../../src/host/commands/chrome-refresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,mBAAmB,GAAG,iBAAiB,CAgC7F"}
|