@comecaramelos/dsh-chrome-mcp 0.0.1 → 1.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 +22 -78
- 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 +1433 -568
- package/lib/client.js.map +7 -0
- package/lib/host/apply.d.ts +3 -0
- package/lib/host/apply.d.ts.map +1 -0
- package/lib/host/apply.js +31 -0
- package/lib/host/apply.js.map +1 -0
- package/lib/host/bridge.d.ts +65 -0
- package/lib/host/bridge.d.ts.map +1 -0
- package/lib/host/bridge.js +176 -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/constants.d.ts +229 -0
- package/lib/host/constants.d.ts.map +1 -0
- package/lib/host/constants.js +242 -0
- package/lib/host/constants.js.map +1 -0
- package/lib/host/controller/bridge-run.d.ts +38 -0
- package/lib/host/controller/bridge-run.d.ts.map +1 -0
- package/lib/host/controller/bridge-run.js +69 -0
- package/lib/host/controller/bridge-run.js.map +1 -0
- package/lib/host/controller/captures.d.ts +22 -0
- package/lib/host/controller/captures.d.ts.map +1 -0
- package/lib/host/controller/captures.js +60 -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 +75 -0
- package/lib/host/controller/commits.js.map +1 -0
- package/lib/host/controller/controller.d.ts +40 -0
- package/lib/host/controller/controller.d.ts.map +1 -0
- package/lib/host/controller/controller.js +167 -0
- package/lib/host/controller/controller.js.map +1 -0
- package/lib/host/controller/index.d.ts +26 -0
- package/lib/host/controller/index.d.ts.map +1 -0
- package/lib/host/controller/index.js +25 -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 +49 -0
- package/lib/host/controller/notes.js.map +1 -0
- package/lib/host/controller/persist.d.ts +9 -0
- package/lib/host/controller/persist.d.ts.map +1 -0
- package/lib/host/controller/persist.js +51 -0
- package/lib/host/controller/persist.js.map +1 -0
- package/lib/host/controller/runs.d.ts +56 -0
- package/lib/host/controller/runs.d.ts.map +1 -0
- package/lib/host/controller/runs.js +211 -0
- package/lib/host/controller/runs.js.map +1 -0
- package/lib/host/controller/state.d.ts +70 -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 +9 -0
- package/lib/host/controller/windows-run.d.ts.map +1 -0
- package/lib/host/controller/windows-run.js +78 -0
- package/lib/host/controller/windows-run.js.map +1 -0
- package/lib/host/discovery/candidates.d.ts +37 -0
- package/lib/host/discovery/candidates.d.ts.map +1 -0
- package/lib/host/discovery/candidates.js +56 -0
- package/lib/host/discovery/candidates.js.map +1 -0
- package/lib/host/discovery/index.d.ts +18 -0
- package/lib/host/discovery/index.d.ts.map +1 -0
- package/lib/host/discovery/index.js +18 -0
- package/lib/host/discovery/index.js.map +1 -0
- package/lib/host/discovery/probe.d.ts +18 -0
- package/lib/host/discovery/probe.d.ts.map +1 -0
- package/lib/host/discovery/probe.js +97 -0
- package/lib/host/discovery/probe.js.map +1 -0
- package/lib/host/discovery/scan.d.ts +67 -0
- package/lib/host/discovery/scan.d.ts.map +1 -0
- package/lib/host/discovery/scan.js +169 -0
- package/lib/host/discovery/scan.js.map +1 -0
- package/lib/host/flags.d.ts +42 -0
- package/lib/host/flags.d.ts.map +1 -0
- package/lib/host/flags.js +118 -0
- package/lib/host/flags.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 +12 -0
- package/lib/host/plugin-meta.d.ts.map +1 -0
- package/lib/host/plugin-meta.js +12 -0
- package/lib/host/plugin-meta.js.map +1 -0
- package/lib/host/schema.d.ts +307 -0
- package/lib/host/schema.d.ts.map +1 -0
- package/lib/host/schema.js +171 -0
- package/lib/host/schema.js.map +1 -0
- package/lib/host/settings.d.ts +9 -0
- package/lib/host/settings.d.ts.map +1 -0
- package/lib/host/settings.js +70 -0
- package/lib/host/settings.js.map +1 -0
- package/lib/host/status.d.ts +28 -0
- package/lib/host/status.d.ts.map +1 -0
- package/lib/host/status.js +60 -0
- package/lib/host/status.js.map +1 -0
- package/lib/host/tool.d.ts +59 -0
- package/lib/host/tool.d.ts.map +1 -0
- package/lib/host/tool.js +51 -0
- package/lib/host/tool.js.map +1 -0
- package/lib/host/types/config.d.ts +47 -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 +30 -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 +23 -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/settings.d.ts +127 -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 +53 -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 +89 -0
- package/lib/host/values.d.ts.map +1 -0
- package/lib/host/values.js +212 -0
- package/lib/host/values.js.map +1 -0
- package/lib/host/windows/connect-flags.d.ts +16 -0
- package/lib/host/windows/connect-flags.d.ts.map +1 -0
- package/lib/host/windows/connect-flags.js +67 -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 +43 -0
- package/lib/host/windows/paths.d.ts.map +1 -0
- package/lib/host/windows/paths.js +121 -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 +210 -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 +86 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +72 -625
- package/lib/index.js.map +1 -0
- package/package.json +26 -4
|
@@ -0,0 +1,176 @@
|
|
|
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 settings base layer.
|
|
5
|
+
*
|
|
6
|
+
* The bridge's *logical* argv is the public contract the tests and the README
|
|
7
|
+
* quote — `npx -y <package> [extraFlags]`, with `--executablePath=<chromePath>`
|
|
8
|
+
* appended only when a path is configured and the flags list does not already
|
|
9
|
+
* pin an executable. In the default "log" stderr mode that argv is not spawned
|
|
10
|
+
* raw: {@link buildBridgeSpawn} wraps it in a `sh -c` whose script `exec`s the
|
|
11
|
+
* argv positionally (so the child never sees the wrapper) and redirects only
|
|
12
|
+
* stderr into a per-spawn log file, leaving stdout to carry the MCP protocol
|
|
13
|
+
* stream. Without this wrapper every startup/progress line npx prints would
|
|
14
|
+
* land directly on the dsh console — exactly what makes the connection feel
|
|
15
|
+
* loud. "console" mode spawns the argv unwrapped (inherited stderr, debug).
|
|
16
|
+
*
|
|
17
|
+
* The logger wrapper exists because dsh-mcp-client reports connection problems
|
|
18
|
+
* only through `ctx.logger`: without it the card would never surface a
|
|
19
|
+
* failed/recovered bridge.
|
|
20
|
+
*/
|
|
21
|
+
import * as fs from "node:fs";
|
|
22
|
+
import * as os from "node:os";
|
|
23
|
+
import * as path from "node:path";
|
|
24
|
+
import { LOG_LEVELS, SH_PATH_CANDIDATES } from "./constants.js";
|
|
25
|
+
import { carriesExecutablePath, flagsSkipCheck } from "./flags.js";
|
|
26
|
+
/**
|
|
27
|
+
* The `sh -c` script behind a redirecting bridge spawn: keep stdout as the MCP
|
|
28
|
+
* protocol stream (only stdout carries it), send stderr to the captured log
|
|
29
|
+
* file, and fail with 127 (and a message ON stderr) if the executable is
|
|
30
|
+
* missing — otherwise the transport would report a bare exit code and the
|
|
31
|
+
* reason would be buried in the log file.
|
|
32
|
+
*/
|
|
33
|
+
const BRIDGE_STDERR_SHELL_SCRIPT = [
|
|
34
|
+
'BRIDGE="$1"',
|
|
35
|
+
'LOG="$2"',
|
|
36
|
+
"shift 2",
|
|
37
|
+
'command -v "$BRIDGE" >/dev/null 2>&1 || { echo "chrome-devtools-mcp: bridge executable not found: $BRIDGE" >&2; exit 127; }',
|
|
38
|
+
'exec "$BRIDGE" "$@" 2>"$LOG"'
|
|
39
|
+
].join("; ");
|
|
40
|
+
/**
|
|
41
|
+
* Build the stdio argv tail for one flags list:
|
|
42
|
+
* `-y <package> [extraFlags]`, the argv tail {@link buildBridgeSpawn} runs, so
|
|
43
|
+
* the logical invocation is `npx -y chrome-devtools-mcp@latest [extraFlags]`.
|
|
44
|
+
* When `chromePath` is set and the flags do not already carry an executable-path
|
|
45
|
+
* option, `--executablePath=<path>` is appended (upstream option:
|
|
46
|
+
* https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/docs/configuration.md).
|
|
47
|
+
* A connect-mode flag takes the whole executable out of the argv: with
|
|
48
|
+
* `--browserUrl` / `--wsEndpoint` present there is nothing local to launch, so
|
|
49
|
+
* the path is never appended next to it — the bridge connects, it does not
|
|
50
|
+
* launch.
|
|
51
|
+
*/
|
|
52
|
+
export function buildServerArgs(entry, extraFlags) {
|
|
53
|
+
const flags = Array.isArray(extraFlags) ? extraFlags.filter((flag) => typeof flag === "string") : [];
|
|
54
|
+
const args = ["-y", entry.package, ...flags];
|
|
55
|
+
const executable = typeof entry.chromePath === "string" ? entry.chromePath.trim() : "";
|
|
56
|
+
if (executable !== "" && !flags.some((flag) => carriesExecutablePath(flag)) && !flagsSkipCheck(flags)) {
|
|
57
|
+
args.push(`--executablePath=${executable}`);
|
|
58
|
+
}
|
|
59
|
+
return args;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Default location of the bridge stderr log:
|
|
63
|
+
* `<tmpdir>/dsh-chrome-mcp-<serverName>-bridge-<pid>.log`. One file per running
|
|
64
|
+
* dsh instance; the wrapper truncates it on every spawn, so it always holds the
|
|
65
|
+
* latest bridge session's output.
|
|
66
|
+
* @param serverName - the bridge server namespace.
|
|
67
|
+
* @param options - tmpdir/pid overrides for tests and diagnostics.
|
|
68
|
+
*/
|
|
69
|
+
export function bridgeStderrLogPath(serverName, options = {}) {
|
|
70
|
+
const tmp = typeof options.tmpdir === "string" && options.tmpdir !== "" ? options.tmpdir : os.tmpdir();
|
|
71
|
+
const pid = options.pid === void 0 ? process.pid : options.pid;
|
|
72
|
+
const safe = typeof serverName === "string" ? serverName.replace(/[^A-Za-z0-9_-]/gu, "-") : "bridge";
|
|
73
|
+
return path.join(tmp, `dsh-chrome-mcp-${safe}-bridge-${pid}.log`);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build the stdio spawn target for one bridge run, honouring the effective
|
|
77
|
+
* stderr mode. The MCP stdio transport spawns the child with the default
|
|
78
|
+
* `stderr: "inherit"`, so every line it prints lands on the dsh console. "log"
|
|
79
|
+
* (default) wraps the spawn in `sh -c`: stdout keeps flowing as the MCP
|
|
80
|
+
* protocol stream, stderr is redirected into a log file. "console" returns the
|
|
81
|
+
* raw command/args (inherited console output). When no POSIX shell is available
|
|
82
|
+
* the redirect is impossible: the raw command is returned with `fallback` set,
|
|
83
|
+
* and the host's {@link noteStderr} warns once.
|
|
84
|
+
* @param target - { command, args, stderr?, logPath?, serverName? }.
|
|
85
|
+
* @param options - platform/exists/tmpdir/pid overrides for tests.
|
|
86
|
+
* @returns { command, args, redirect, fallback } — the log file when redirected
|
|
87
|
+
* ("" otherwise) and why not ("" when redirected or console).
|
|
88
|
+
*/
|
|
89
|
+
export function buildBridgeSpawn(target, options = {}) {
|
|
90
|
+
const raw = { command: target.command, args: [...target.args], redirect: "", fallback: "" };
|
|
91
|
+
const mode = target.stderr === void 0 ? "log" : target.stderr;
|
|
92
|
+
if (mode !== "log")
|
|
93
|
+
return raw;
|
|
94
|
+
const platform = options.platform === void 0 ? process.platform : options.platform;
|
|
95
|
+
if (platform !== "linux" && platform !== "darwin")
|
|
96
|
+
return { ...raw, fallback: "platform" };
|
|
97
|
+
const exists = options.exists === void 0
|
|
98
|
+
? (candidate) => {
|
|
99
|
+
try {
|
|
100
|
+
fs.accessSync(candidate, fs.constants.X_OK);
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
: options.exists;
|
|
108
|
+
const sh = SH_PATH_CANDIDATES.find((candidate) => exists(candidate));
|
|
109
|
+
if (sh === void 0)
|
|
110
|
+
return { ...raw, fallback: "shell" };
|
|
111
|
+
const logPath = typeof target.logPath === "string" && target.logPath !== ""
|
|
112
|
+
? target.logPath
|
|
113
|
+
: bridgeStderrLogPath(target.serverName ?? "bridge", options);
|
|
114
|
+
return {
|
|
115
|
+
command: sh,
|
|
116
|
+
args: ["-c", BRIDGE_STDERR_SHELL_SCRIPT, "chrome-devtools-mcp", target.command, logPath, ...target.args],
|
|
117
|
+
redirect: logPath,
|
|
118
|
+
fallback: ""
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* stdio config for the nested mcp-client bridge for one flags list + effective
|
|
123
|
+
* stderr mode. The args keep the user's original logical invocation shape
|
|
124
|
+
* (`npx -y <package> [extraFlags]`, run as `command`), wrapped through
|
|
125
|
+
* {@link buildBridgeSpawn} so the child's stderr lands in a log file instead of
|
|
126
|
+
* the console when the mode is "log". The returned config carries only
|
|
127
|
+
* dsh-mcp-client fields; `redirect`/`fallback` describe the wrapper for the
|
|
128
|
+
* host's own diagnostics.
|
|
129
|
+
*/
|
|
130
|
+
export function bridgeConfig(entry, extraFlags, stderrMode) {
|
|
131
|
+
const spawned = buildBridgeSpawn({
|
|
132
|
+
command: entry.command,
|
|
133
|
+
args: buildServerArgs(entry, extraFlags),
|
|
134
|
+
stderr: stderrMode === void 0 ? entry.bridgeStderr : stderrMode,
|
|
135
|
+
logPath: entry.bridgeStderrLog,
|
|
136
|
+
serverName: entry.serverName
|
|
137
|
+
}, {});
|
|
138
|
+
const config = {
|
|
139
|
+
serverName: entry.serverName,
|
|
140
|
+
transport: "stdio",
|
|
141
|
+
command: spawned.command,
|
|
142
|
+
args: spawned.args,
|
|
143
|
+
env: entry.env,
|
|
144
|
+
cwd: entry.cwd,
|
|
145
|
+
toolCallTimeoutMs: entry.toolCallTimeoutMs,
|
|
146
|
+
failOnStartupError: entry.failOnStartupError,
|
|
147
|
+
reconnect: entry.reconnect
|
|
148
|
+
};
|
|
149
|
+
return { config, redirect: spawned.redirect, fallback: spawned.fallback };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Wrap a logger so a callback observes every level call before the
|
|
153
|
+
* original runs. Used to capture the nested bridge's own log lines (the only
|
|
154
|
+
* surface dsh-mcp-client exposes for connection failures — reconnect
|
|
155
|
+
* backoff warnings, spawn failures, give-ups) into the settings base layer.
|
|
156
|
+
* The wrapper shares the underlying LoggerService (exporters/buffer included)
|
|
157
|
+
* and only shadows the level methods.
|
|
158
|
+
* @param base - the base logger to wrap (cordis LoggerService).
|
|
159
|
+
* @param note - callback invoked for every log level before the original runs.
|
|
160
|
+
*/
|
|
161
|
+
export function captureLogger(base, note) {
|
|
162
|
+
const wrapper = ((...args) => {
|
|
163
|
+
const callBase = base;
|
|
164
|
+
return callBase(...args);
|
|
165
|
+
});
|
|
166
|
+
Object.setPrototypeOf(wrapper, Object.getPrototypeOf(base));
|
|
167
|
+
Object.assign(wrapper, base);
|
|
168
|
+
for (const level of LOG_LEVELS) {
|
|
169
|
+
wrapper[level] = (...args) => {
|
|
170
|
+
note(level, args);
|
|
171
|
+
return base[level]?.(...args);
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
return wrapper;
|
|
175
|
+
}
|
|
176
|
+
//# 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
|
|
15
|
+
* a settings document 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
|
|
42
|
+
* a settings document 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,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-half fixed identifiers, budgets and validation patterns.
|
|
3
|
+
*
|
|
4
|
+
* The strings are a public contract — the settings namespace is both the
|
|
5
|
+
* persistence key and the Web card's slot key — and the budgets are what the
|
|
6
|
+
* README and the tests quote, so they live here once and every module imports
|
|
7
|
+
* rather than repeats them.
|
|
8
|
+
*/
|
|
9
|
+
/** Fixed settings namespace; also the client card's slot key. */
|
|
10
|
+
export declare const SETTINGS_NAMESPACE = "chrome-mcp";
|
|
11
|
+
/** Environment variable that seeds the launch flags for one dsh run. */
|
|
12
|
+
export declare const FLAGS_ENV_VAR = "DSH_CHROME_MCP_FLAGS";
|
|
13
|
+
/**
|
|
14
|
+
* Flag entries are appended verbatim to the bridge argv and reach Chrome via
|
|
15
|
+
* a direct execve (no shell), so shell metacharacters cannot execute here.
|
|
16
|
+
* What must never reach argv is control characters (newlines, NULs) — they
|
|
17
|
+
* corrupt the argument framing, so entries may not contain any.
|
|
18
|
+
*/
|
|
19
|
+
export declare const CONTROL_PATTERN: RegExp;
|
|
20
|
+
/** Flags every launch carries unless the user overrides them. */
|
|
21
|
+
export declare const DEFAULT_EXTRA_FLAGS: string[];
|
|
22
|
+
/**
|
|
23
|
+
* The flags the card's **Flags WSL** control appends for a WSL ↔ Windows
|
|
24
|
+
* debugging setup — a fixed recommendation, not a setting and never persisted.
|
|
25
|
+
* The shape is what makes it actually reach the browser:
|
|
26
|
+
*
|
|
27
|
+
* - the debug port travels as `--chromeArg=--remote-debugging-port=9222`:
|
|
28
|
+
* the bridge's strict parser knows only its own option names, so a bare
|
|
29
|
+
* `--remote-debugging-port` is reported as `Unknown arguments` and dropped
|
|
30
|
+
* before any browser is launched; as a `chromeArg` it lands in Chrome's own
|
|
31
|
+
* argv and the debugging port opens (see the "Browser switches" hard
|
|
32
|
+
* constraint).
|
|
33
|
+
*
|
|
34
|
+
* A `--user-data-dir` entry is deliberately **not** recommended alongside it.
|
|
35
|
+
* The idea of carrying the profile as a project-rooted `.chrome` was measured
|
|
36
|
+
* to be impossible for the Windows executable: a Windows `chrome.exe` profile
|
|
37
|
+
* directory has to live on a Windows-local path — neither the WSL checkout
|
|
38
|
+
* nor the `\\wsl.localhost` mount can carry its locks (9P) — so the
|
|
39
|
+
* **Prelaunch Windows Chrome** run launches with its own Windows-native
|
|
40
|
+
* profile under `%LOCALAPPDATA%`, and the one entry this list recommends is
|
|
41
|
+
* the debug port the run answers on.
|
|
42
|
+
*/
|
|
43
|
+
export declare const WSL_EXTRA_FLAGS: string[];
|
|
44
|
+
/** Upstream configuration docs surfaced by the client card link. */
|
|
45
|
+
export declare const CONFIGURATION_DOCS_URL = "https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/docs/configuration.md";
|
|
46
|
+
/** Timeout for one check subprocess (chrome executable probe). */
|
|
47
|
+
export declare const CHECK_TIMEOUT_MS = 15000;
|
|
48
|
+
/**
|
|
49
|
+
* Why a Windows `chrome.exe` on a WSL host is **never probed**. The exec answers
|
|
50
|
+
* successfully — which is what makes the selection look healthy — but answering
|
|
51
|
+
* means *attaching to the Windows browser session*, and that brings a browser
|
|
52
|
+
* instance up (measured on WSL2 + Google Chrome 153: `chrome.exe --version`
|
|
53
|
+
* spawns the browser process plus its crashpad handler). No tool call could
|
|
54
|
+
* ever drive what it started (the debug pipes do not cross the interop
|
|
55
|
+
* boundary), so the probe buys nothing and costs a running browser: the check
|
|
56
|
+
* answers nothing, and the scan keeps the entry visible as `unavailable` with
|
|
57
|
+
* this reason.
|
|
58
|
+
*/
|
|
59
|
+
export declare const WSL_WINDOWS_LAUNCH_ERROR = "Windows chrome.exe cannot be launched from WSL \u2014 use connect mode (--browserUrl / --wsEndpoint) against a Chrome started with --remote-debugging-port";
|
|
60
|
+
/** Max length of a reported error line. */
|
|
61
|
+
export declare const ERROR_CAP = 240;
|
|
62
|
+
/**
|
|
63
|
+
* Log lines the bridge emits after a lost connection recovered — clear
|
|
64
|
+
* the captured connection error when one shows up.
|
|
65
|
+
*/
|
|
66
|
+
export declare const BRIDGE_RECONNECTED: RegExp;
|
|
67
|
+
/** One bridge log level: the levels the captured wrapper shadows. */
|
|
68
|
+
export declare const LOG_LEVELS: readonly ["trace", "debug", "info", "warn", "error", "fatal"];
|
|
69
|
+
/**
|
|
70
|
+
* Bridge console-output routing modes (mirrors the reference plugin's gateway
|
|
71
|
+
* stderr modes). "log" redirects the spawned child's stderr into a log file;
|
|
72
|
+
* "console" inherits it onto the dsh console.
|
|
73
|
+
*/
|
|
74
|
+
export declare const BRIDGE_STDERR_MODES: ReadonlyArray<"log" | "console">;
|
|
75
|
+
/** Modes accepted by the `stderrMode` user layer: also the empty string
|
|
76
|
+
* ("" → follow the row config `bridgeStderr`). */
|
|
77
|
+
export declare const STDERR_MODE_FIELD_PATTERN: RegExp;
|
|
78
|
+
/** Row-config `bridgeStderrLog` accepts "" (the per-spawn default) or a
|
|
79
|
+
* POSIX absolute path; nothing else. */
|
|
80
|
+
export declare const OPTIONAL_PATH_PATTERN: RegExp;
|
|
81
|
+
/**
|
|
82
|
+
* Candidate POSIX shells used only to redirect the bridge's stderr (see
|
|
83
|
+
* ./bridge.ts `buildBridgeSpawn`). None found on a bare Windows host → the
|
|
84
|
+
* redirect is impossible and the spawn stays unwrapped with `fallback:
|
|
85
|
+
* "platform"`/`"shell"`.
|
|
86
|
+
*/
|
|
87
|
+
export declare const SH_PATH_CANDIDATES: readonly ["/bin/sh", "/usr/bin/sh"];
|
|
88
|
+
/**
|
|
89
|
+
* `chromePath` user layer: a filesystem path or a PATH-resolved name. Nothing
|
|
90
|
+
* travels through a shell here either, so the only hard constraint is that no
|
|
91
|
+
* control character reaches it; the length cap keeps one absurd value out of
|
|
92
|
+
* argv and out of the settings document.
|
|
93
|
+
*/
|
|
94
|
+
export declare const CHROME_PATH_PATTERN: RegExp;
|
|
95
|
+
/** Upper bound of the **legacy** UI-authored custom-executable MRU (oldest
|
|
96
|
+
* drops off). The MRU is the older shape of the saved-executables list: a host
|
|
97
|
+
* whose settings still carry it folds its paths into the `executables` rows the
|
|
98
|
+
* first time the picker scans (see ./catalog.ts `mergeEntries`), after which the
|
|
99
|
+
* rows are the only source of saved executables. */
|
|
100
|
+
export declare const CUSTOM_PATHS_CAP = 10;
|
|
101
|
+
/** Longest display name a saved-executable row may carry — the `name` half is
|
|
102
|
+
* UI-only (what the pill and the dropdown render), the `id` half is what goes on
|
|
103
|
+
* the wire. */
|
|
104
|
+
export declare const CATALOG_NAME_MAX_LENGTH = 200;
|
|
105
|
+
/** Upper bound of the saved-executable rows, merged-list side: the tail drops
|
|
106
|
+
* off, so a scan that keeps discovering new ids cannot grow the persisted
|
|
107
|
+
* catalog without limit. */
|
|
108
|
+
export declare const CATALOG_MAX_LENGTH = 50;
|
|
109
|
+
/**
|
|
110
|
+
* The Windows-side Chrome/Edge executables the card's **Prelaunch Windows Chrome**
|
|
111
|
+
* button locates through the WSL interop mount. They are NOT local picker
|
|
112
|
+
* candidates — the picker must never offer what cannot be launched from
|
|
113
|
+
* Linux (hard constraint) — the button exists precisely because Windows
|
|
114
|
+
* Chrome is only usable in *connect* mode. The list is host-served logic: the
|
|
115
|
+
* card carries no copy of it.
|
|
116
|
+
*/
|
|
117
|
+
export declare const WINDOWS_CHROME_CANDIDATES: readonly ["C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe", "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe", "C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe", "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"];
|
|
118
|
+
/** The debugging port every Windows Chrome launch carries first — kept
|
|
119
|
+
* coherent with the port the **Flags WSL** control recommends. */
|
|
120
|
+
export declare const WINDOWS_CHROME_PORT = 9222;
|
|
121
|
+
/** The debugging-port pool the run falls through when the first port is already
|
|
122
|
+
* carrying a listener: [first, first+1, …]. A listener answers "reachable",
|
|
123
|
+
* which is what makes the port's own reachability sample its in-use signal. */
|
|
124
|
+
export declare const WINDOWS_CHROME_PORT_POOL: readonly [9222, 9223, 9224];
|
|
125
|
+
/**
|
|
126
|
+
* Ports that **only Windows ever listens on** (RPC endpoint mapper, RDP). The
|
|
127
|
+
* prereq check connects one of them: on a `mirrored` networkingMode host the
|
|
128
|
+
* connect succeeds, on a NAT host it gives up — the sample must discriminate,
|
|
129
|
+
* which is exactly what makes it the prereq (measured: 135/3389 CONNECTED
|
|
130
|
+
* under mirrored, closed ports TIME OUT, never refuse). A port that WSL might
|
|
131
|
+
* hold locally (445 via Samba) must never be used: it would answer reachable
|
|
132
|
+
* even when the Windows loopback is unreachable.
|
|
133
|
+
*/
|
|
134
|
+
export declare const WINDOWS_CHROME_PREREQ_PORTS: readonly [135, 3389];
|
|
135
|
+
/** How long to wait for the launched Windows Chrome to open its port. */
|
|
136
|
+
export declare const WINDOWS_CHROME_WAIT_MS = 10000;
|
|
137
|
+
/** How long one TCP reachability sample waits before calling the port
|
|
138
|
+
* unreachable (a NAT host's closed port times out; it never refuses). */
|
|
139
|
+
export declare const WINDOWS_CHROME_SAMPLE_MS = 1000;
|
|
140
|
+
/** Poll cadence while waiting for a launched Windows Chrome to bind its port. */
|
|
141
|
+
export declare const WINDOWS_CHROME_POLL_MS = 500;
|
|
142
|
+
/**
|
|
143
|
+
* The Windows-side working directory the launch runs with. Nothing depends on
|
|
144
|
+
* it (every argument is absolute), it only keeps relative path resolution off
|
|
145
|
+
* any UNC (WSL-side) path — the shape the old `cmd.exe /c start` form needed
|
|
146
|
+
* too (measured 2026-10-04, see .probe/windows-chrome-connect-probe.log).
|
|
147
|
+
*/
|
|
148
|
+
export declare const WINDOWS_CHROME_START_CWD = "/mnt/c/Windows";
|
|
149
|
+
/** The UNC root modern WSL exports to Windows-side processes. */
|
|
150
|
+
export declare const WSL_UNC_ROOT = "\\\\wsl.localhost\\";
|
|
151
|
+
/**
|
|
152
|
+
* The Windows-side directory name the run profiles under
|
|
153
|
+
* (`%LOCALAPPDATA%\dsh-chrome-mcp\<.chrome|\.chrome-<port>>`). The profile
|
|
154
|
+
* must live on the Windows filesystem: the WSL-side directories, served to
|
|
155
|
+
* Windows through 9P, cannot carry the locks Chrome's SQLite tables and its
|
|
156
|
+
* singleton socket take — a profile rooted there opens every table as a
|
|
157
|
+
* zero-byte file and shows "an error occurred while opening your profile" on
|
|
158
|
+
* every launch (measured live 2026-10-04 against Chrome 154). The workspace
|
|
159
|
+
* keeps a `.chrome` view of this directory through the link the run refreshes
|
|
160
|
+
* (see `linkWindowsChromeProfile`).
|
|
161
|
+
*/
|
|
162
|
+
export declare const WINDOWS_CHROME_PROFILE_DIRNAME = "dsh-chrome-mcp";
|
|
163
|
+
/** The connect-mode flag the button writes; its value is the debugging URL. */
|
|
164
|
+
export declare const BROWSER_URL_FLAG_PREFIX = "--browserUrl=";
|
|
165
|
+
/**
|
|
166
|
+
* The flags a brand-new Windows profile is launched with, beside the port and
|
|
167
|
+
* the profile directory. A fresh `--user-data-dir` IS a first run for the
|
|
168
|
+
* browser: Windows Chrome opens the welcome tab and the default-search-engine
|
|
169
|
+
* chooser on it, and in connect mode nothing clicks through it — the debugging
|
|
170
|
+
* session is left sitting on the FRE page. Both flags suppress that
|
|
171
|
+
* experience, exactly like the manual recipe the button replaces. They travel
|
|
172
|
+
* on the **browser's own** argv (the `start` line), never as `--chromeArg=`:
|
|
173
|
+
* here it is Chrome being told at launch what not to show, not the bridge
|
|
174
|
+
* parser (see the browser-switches bullet under Hard constraints).
|
|
175
|
+
*/
|
|
176
|
+
export declare const WINDOWS_CHROME_FIRST_RUN_FLAGS: readonly ["--no-first-run", "--no-default-browser-check"];
|
|
177
|
+
/**
|
|
178
|
+
* The page the Windows launch opens, package-root-relative. It is the one asset
|
|
179
|
+
* this plugin ships outside `lib`, and it is **read host-side**: the run renders
|
|
180
|
+
* it with its own answers, writes it through the interop mount next to the
|
|
181
|
+
* profile directory (so the Windows-side browser can actually read it), and hands
|
|
182
|
+
* the browser the `file:///…` URL. It exists because the honest answer to "why
|
|
183
|
+
* did a window just open?" is prose the argv cannot carry — and the usual
|
|
184
|
+
* placeholder is not an option: `example.com` carries an explicit notice against
|
|
185
|
+
* being used for automation and tests.
|
|
186
|
+
*/
|
|
187
|
+
export declare const WINDOWS_CHROME_LANDING_ASSET = "assets/prelaunch-windows-chrome.html";
|
|
188
|
+
/** The base name of the landing file written beside each profile directory
|
|
189
|
+
* (`…\dsh-chrome-mcp\prelaunch-<port>.html`) — a sibling of the profile, never a
|
|
190
|
+
* file inside it, so it never reads as profile churn. */
|
|
191
|
+
export declare const WINDOWS_CHROME_LANDING_BASENAME = "prelaunch";
|
|
192
|
+
/** What one Windows Chrome run may currently be doing (the card derives its
|
|
193
|
+
* button state, pill muting and disabled reason from this single field).
|
|
194
|
+
* `"not-applicable"` is the non-WSL answer the plan asks the button to read as
|
|
195
|
+
* disabled-off; `"launch-failed"` and the rest are the §4 failure states. */
|
|
196
|
+
export declare const WINDOWS_CHROME_STATES: readonly ["off", "launching", "connected", "unreachable", "not-found", "launch-failed", "not-applicable"];
|
|
197
|
+
/** Schema pattern for `windowsChromeStatus.state`. */
|
|
198
|
+
export declare const WINDOWS_CHROME_STATE_PATTERN: RegExp;
|
|
199
|
+
/**
|
|
200
|
+
* The prereq answer — the one manual step that is not the button's job
|
|
201
|
+
* (configuring `~/.wslconfig` is out of scope, reading/reaching it is not).
|
|
202
|
+
*/
|
|
203
|
+
export declare const WINDOWS_CHROME_PREREQ_ERROR = "Windows Chrome needs networkingMode=mirrored in %USERPROFILE%\\.wslconfig, then wsl --shutdown: today the Windows loopback is not reachable from this WSL host";
|
|
204
|
+
/** Where the effective selection came from (`effectiveSource`): a `chromePath`
|
|
205
|
+
* written by the card (or seeded once by the host) or the row config. Nothing
|
|
206
|
+
* resolves on its own, so there is no "auto". */
|
|
207
|
+
export declare const EFFECTIVE_SOURCES: readonly ["selected", "row-config"];
|
|
208
|
+
/**
|
|
209
|
+
* Environment variables WSL exports into every distro session. Their presence
|
|
210
|
+
* answers "are we running inside WSL?" — the first one carries the distro name,
|
|
211
|
+
* `WSL_INTEROP` the interop-path directory (`/run/WSL/<pid>`).
|
|
212
|
+
*/
|
|
213
|
+
export declare const WSL_ENV_VARS: readonly ["WSL_DISTRO_NAME", "WSL_DISTRO_LABEL", "WSL_INTEROP"];
|
|
214
|
+
/**
|
|
215
|
+
* The `binfmt_misc` registration WSL installs for PE binaries: its presence
|
|
216
|
+
* marks a WSL kernel. It is only the **fallback** signal — inside a host the
|
|
217
|
+
* launch environment is authoritative, and an empty one is an answer (see
|
|
218
|
+
* ./platform.ts).
|
|
219
|
+
*/
|
|
220
|
+
export declare const WSL_INTEROP_MARKER = "/proc/sys/fs/binfmt_misc/WSLInterop";
|
|
221
|
+
/** Windows executables reachable through the interop mount (`/mnt/c/...`) or by
|
|
222
|
+
* their Windows spelling (UNC, drive letter). */
|
|
223
|
+
export declare const WINDOWS_PATH_PATTERN: RegExp;
|
|
224
|
+
/** The PE suffix. WSL execve's a `.exe` from any path (the Windows loader reads
|
|
225
|
+
* the Linux filesystem over UNC), so the suffix alone marks a Windows binary. */
|
|
226
|
+
export declare const WINDOWS_EXE_PATTERN: RegExp;
|
|
227
|
+
/** Schema pattern for `effectiveSource` ("" = nothing resolved yet). */
|
|
228
|
+
export declare const EFFECTIVE_SOURCE_PATTERN: RegExp;
|
|
229
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/host/constants.ts"],"names":[],"mappings":"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"}
|