@comecaramelos/dsh-chrome-mcp 1.0.0 → 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 -39
- package/lib/client.js +2186 -614
- package/lib/client.js.map +4 -4
- package/lib/host/apply.d.ts +38 -1
- package/lib/host/apply.d.ts.map +1 -1
- package/lib/host/apply.js +43 -17
- package/lib/host/apply.js.map +1 -1
- package/lib/host/bridge.d.ts +28 -19
- package/lib/host/bridge.d.ts.map +1 -1
- package/lib/host/bridge.js +71 -79
- package/lib/host/bridge.js.map +1 -1
- package/lib/host/catalog.d.ts +2 -2
- package/lib/host/catalog.js +2 -2
- 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 +107 -30
- package/lib/host/constants.d.ts.map +1 -1
- package/lib/host/constants.js +107 -30
- package/lib/host/constants.js.map +1 -1
- 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 +4 -2
- package/lib/host/controller/bridge-run.d.ts.map +1 -1
- package/lib/host/controller/bridge-run.js +24 -8
- package/lib/host/controller/bridge-run.js.map +1 -1
- package/lib/host/controller/captures.d.ts +9 -16
- package/lib/host/controller/captures.d.ts.map +1 -1
- package/lib/host/controller/captures.js +73 -48
- package/lib/host/controller/captures.js.map +1 -1
- package/lib/host/controller/commits.d.ts +2 -2
- package/lib/host/controller/commits.d.ts.map +1 -1
- package/lib/host/controller/commits.js +97 -41
- package/lib/host/controller/commits.js.map +1 -1
- 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 +19 -24
- package/lib/host/controller/controller.d.ts.map +1 -1
- package/lib/host/controller/controller.js +181 -114
- package/lib/host/controller/controller.js.map +1 -1
- package/lib/host/controller/index.d.ts +18 -14
- package/lib/host/controller/index.d.ts.map +1 -1
- package/lib/host/controller/index.js +16 -14
- package/lib/host/controller/index.js.map +1 -1
- package/lib/host/controller/notes.d.ts +9 -9
- package/lib/host/controller/notes.d.ts.map +1 -1
- package/lib/host/controller/notes.js +16 -21
- package/lib/host/controller/notes.js.map +1 -1
- package/lib/host/controller/persist.d.ts +10 -3
- package/lib/host/controller/persist.d.ts.map +1 -1
- package/lib/host/controller/persist.js +89 -42
- package/lib/host/controller/persist.js.map +1 -1
- 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 +34 -10
- package/lib/host/controller/runs.d.ts.map +1 -1
- package/lib/host/controller/runs.js +241 -58
- package/lib/host/controller/runs.js.map +1 -1
- package/lib/host/controller/state.d.ts +122 -20
- package/lib/host/controller/state.d.ts.map +1 -1
- package/lib/host/controller/windows-run.d.ts +10 -2
- package/lib/host/controller/windows-run.d.ts.map +1 -1
- package/lib/host/controller/windows-run.js +66 -35
- package/lib/host/controller/windows-run.js.map +1 -1
- package/lib/host/discovery/candidates.d.ts +23 -13
- package/lib/host/discovery/candidates.d.ts.map +1 -1
- package/lib/host/discovery/candidates.js +20 -8
- package/lib/host/discovery/candidates.js.map +1 -1
- package/lib/host/discovery/index.d.ts +1 -0
- package/lib/host/discovery/index.d.ts.map +1 -1
- package/lib/host/discovery/index.js +1 -0
- package/lib/host/discovery/index.js.map +1 -1
- package/lib/host/discovery/probe.d.ts +16 -5
- package/lib/host/discovery/probe.d.ts.map +1 -1
- package/lib/host/discovery/probe.js +68 -10
- package/lib/host/discovery/probe.js.map +1 -1
- package/lib/host/discovery/scan.d.ts +14 -9
- package/lib/host/discovery/scan.d.ts.map +1 -1
- package/lib/host/discovery/scan.js +56 -30
- package/lib/host/discovery/scan.js.map +1 -1
- package/lib/host/flags.d.ts +28 -5
- package/lib/host/flags.d.ts.map +1 -1
- package/lib/host/flags.js +75 -7
- package/lib/host/flags.js.map +1 -1
- 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/plugin-meta.d.ts +12 -3
- package/lib/host/plugin-meta.d.ts.map +1 -1
- package/lib/host/plugin-meta.js +13 -4
- package/lib/host/plugin-meta.js.map +1 -1
- package/lib/host/schema.d.ts +301 -247
- package/lib/host/schema.d.ts.map +1 -1
- package/lib/host/schema.js +145 -120
- package/lib/host/schema.js.map +1 -1
- package/lib/host/settings.d.ts +22 -3
- package/lib/host/settings.d.ts.map +1 -1
- package/lib/host/settings.js +81 -60
- package/lib/host/settings.js.map +1 -1
- package/lib/host/status.d.ts +7 -10
- package/lib/host/status.d.ts.map +1 -1
- package/lib/host/status.js +8 -23
- package/lib/host/status.js.map +1 -1
- package/lib/host/tool.d.ts +13 -7
- package/lib/host/tool.d.ts.map +1 -1
- package/lib/host/tool.js +4 -3
- package/lib/host/tool.js.map +1 -1
- package/lib/host/types/config.d.ts +66 -12
- package/lib/host/types/config.d.ts.map +1 -1
- package/lib/host/types/executable.d.ts +8 -3
- package/lib/host/types/executable.d.ts.map +1 -1
- package/lib/host/types/index.d.ts +5 -4
- package/lib/host/types/index.d.ts.map +1 -1
- 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 +118 -65
- package/lib/host/types/settings.d.ts.map +1 -1
- package/lib/host/types/stderr.d.ts +3 -5
- package/lib/host/types/stderr.d.ts.map +1 -1
- package/lib/host/values.d.ts +152 -37
- package/lib/host/values.d.ts.map +1 -1
- package/lib/host/values.js +304 -112
- package/lib/host/values.js.map +1 -1
- package/lib/host/windows/connect-flags.d.ts +19 -8
- package/lib/host/windows/connect-flags.d.ts.map +1 -1
- package/lib/host/windows/connect-flags.js +50 -20
- package/lib/host/windows/connect-flags.js.map +1 -1
- package/lib/host/windows/index.d.ts +1 -1
- package/lib/host/windows/index.d.ts.map +1 -1
- package/lib/host/windows/index.js +1 -1
- package/lib/host/windows/index.js.map +1 -1
- package/lib/host/windows/paths.d.ts +27 -6
- package/lib/host/windows/paths.d.ts.map +1 -1
- package/lib/host/windows/paths.js +40 -13
- package/lib/host/windows/paths.js.map +1 -1
- package/lib/host/windows/run.d.ts.map +1 -1
- package/lib/host/windows/run.js +3 -2
- package/lib/host/windows/run.js.map +1 -1
- package/lib/index.d.ts +72 -56
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +74 -55
- package/lib/index.js.map +1 -1
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +35 -14
- package/cordis.patch.yml +0 -5
|
@@ -10,8 +10,11 @@
|
|
|
10
10
|
import { bridgeConfig } from "../bridge.js";
|
|
11
11
|
import { flagsSkipCheck } from "../flags.js";
|
|
12
12
|
import { noteStderr } from "./notes.js";
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
import { publishLive } from "./publish.js";
|
|
14
|
+
/** The bridge's own view of one config: the ordinary passthroughs ride along
|
|
15
|
+
* verbatim, and the two levers the run owns — the flags list and the resolved
|
|
16
|
+
* selection — are handed in explicitly, so nothing here mistakes a reference for
|
|
17
|
+
* a value. The logical argv shape is unchanged. */
|
|
15
18
|
export function configForBridge(controller, flags) {
|
|
16
19
|
return { ...controller.config, extraFlags: flags, chromePath: controller.state.runningChromePath };
|
|
17
20
|
}
|
|
@@ -31,10 +34,17 @@ export function restartBridge(controller, built, note) {
|
|
|
31
34
|
void Promise.resolve(controller.bridge)
|
|
32
35
|
.then(() => controller.bridge.update(built.config))
|
|
33
36
|
.then(() => {
|
|
34
|
-
|
|
37
|
+
// A successful bridge update proves the flags landed and the
|
|
38
|
+
// bridge connected again — it clears the captured *connection*
|
|
39
|
+
// error — but it says nothing about the executable: the known
|
|
40
|
+
// executable-missing answer stands until a probe answers a
|
|
41
|
+
// version or a tool call succeeds.
|
|
42
|
+
if (!controller.state.live.chromeMissing)
|
|
43
|
+
controller.state.live.lastError = "";
|
|
44
|
+
publishLive(controller);
|
|
35
45
|
// Intentionally NOT clearing `chromeMissing`: a successful bridge
|
|
36
|
-
// update proves the flags took
|
|
37
|
-
//
|
|
46
|
+
// update proves the flags took but says nothing about the
|
|
47
|
+
// executable.
|
|
38
48
|
})
|
|
39
49
|
.catch((error) => controller.ctx.logger.error(`chrome-devtools-mcp(${controller.config.serverName}): ${note}: ${String(error)}`));
|
|
40
50
|
}
|
|
@@ -42,11 +52,15 @@ export function restartBridge(controller, built, note) {
|
|
|
42
52
|
export function applyFlags(controller, flags) {
|
|
43
53
|
const { state } = controller;
|
|
44
54
|
state.runningFlags = flags;
|
|
45
|
-
|
|
55
|
+
// No mirror answer here: `publishLive` below re-derives it from the list the
|
|
56
|
+
// bridge launches with (`src/host/controller/publish.ts`), so setting it off
|
|
57
|
+
// this call's argument would be the same answer twice. The known-error gate
|
|
58
|
+
// reads the predicate directly for the same reason.
|
|
46
59
|
// Connect mode launches no local executable, so the known "executable
|
|
47
60
|
// missing" state simply does not apply while it is set.
|
|
48
|
-
if (
|
|
49
|
-
state.
|
|
61
|
+
if (flagsSkipCheck(flags))
|
|
62
|
+
state.live.chromeMissing = false;
|
|
63
|
+
publishLive(controller);
|
|
50
64
|
controller.ctx.logger.info(`chrome-devtools-mcp(${controller.config.serverName}): relaunching bridge with flags [${flags.join(" ")}]`);
|
|
51
65
|
const built = bridgeConfig(configForBridge(controller, flags), flags, state.runningStderrMode);
|
|
52
66
|
noteStderr(controller, built);
|
|
@@ -61,6 +75,8 @@ export function applyFlags(controller, flags) {
|
|
|
61
75
|
export function applyStderrMode(controller, mode) {
|
|
62
76
|
const { state } = controller;
|
|
63
77
|
state.runningStderrMode = mode;
|
|
78
|
+
state.live.stderrEffective = mode;
|
|
79
|
+
publishLive(controller);
|
|
64
80
|
controller.ctx.logger.info(`chrome-devtools-mcp(${controller.config.serverName}): bridge stderr mode → "${mode}" (restarting the bridge connection)`);
|
|
65
81
|
const built = bridgeConfig(configForBridge(controller, state.runningFlags), state.runningFlags, mode);
|
|
66
82
|
noteStderr(controller, built);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-run.js","sourceRoot":"","sources":["../../../src/host/controller/bridge-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"bridge-run.js","sourceRoot":"","sources":["../../../src/host/controller/bridge-run.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
import type { Controller } from "./state.js";
|
|
2
|
-
/**
|
|
3
|
-
* Fold bridge log lines into the base layer. dsh-mcp-client reports connection
|
|
4
|
-
* problems only through its logger (reconnect warnings with "connection
|
|
5
|
-
* failed/lost", give-up errors, spawn failures), and a module plugin has no
|
|
6
|
-
* push channel to clients — so the newest failure line becomes `lastError`, and
|
|
7
|
-
* the "reconnected and re-synced tools" success line clears it. The wrapper
|
|
8
|
-
* lives only on the bridge scope; our own logs bypass it, so our own warns never
|
|
9
|
-
* masquerade as connection errors.
|
|
10
|
-
*/
|
|
11
|
-
export declare function noteBridgeLog(controller: Controller, level: string, args: unknown[]): void;
|
|
12
2
|
/**
|
|
13
3
|
* Register the tool-call status capture: browser-level failures surface only as
|
|
14
|
-
* the calling agent's tool result, never on
|
|
15
|
-
*
|
|
16
|
-
* `isError` writes the failure into the
|
|
17
|
-
* clears both, so the card reports current health.
|
|
18
|
-
*
|
|
19
|
-
*
|
|
4
|
+
* the calling agent's tool result, never on a line, so a settled result whose
|
|
5
|
+
* registered name is prefixed `mcp__<id>__` for one of this component's live
|
|
6
|
+
* connections and carries `isError` writes the failure into the live mirror; a
|
|
7
|
+
* successful chrome-tool call clears both, so the card reports current health.
|
|
8
|
+
* A success is *evidence* — what a missing selection never produces — while an
|
|
9
|
+
* unrelated failure line never displaces the known executable-missing answer
|
|
10
|
+
* standing (the rule the old bridge-log capture followed too). The body is
|
|
11
|
+
* wrapped in try/catch (warn only — a capture fault must never break a tool
|
|
12
|
+
* call) and returns `next()` unchanged.
|
|
20
13
|
*/
|
|
21
14
|
export declare function registerToolCapture(controller: Controller): void;
|
|
22
15
|
//# sourceMappingURL=captures.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captures.d.ts","sourceRoot":"","sources":["../../../src/host/controller/captures.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"captures.d.ts","sourceRoot":"","sources":["../../../src/host/controller/captures.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAkBhE"}
|
|
@@ -1,60 +1,85 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Controller — the
|
|
2
|
+
* Controller — the tool-call result capture that reaches the live mirror.
|
|
3
3
|
*
|
|
4
|
-
* A
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* the
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
4
|
+
* A settled browser-tool result that failed becomes the newest `lastError`,
|
|
5
|
+
* classified into the known "executable missing" flag so the single red status
|
|
6
|
+
* dot keeps its whole story. The write is a live mirror write: published through
|
|
7
|
+
* the references, never persisted.
|
|
8
|
+
*
|
|
9
|
+
* What the bridge-log capture used to be, the connection lines are now: every
|
|
10
|
+
* failure the nested fiber answers with reaches the manager's own line for the
|
|
11
|
+
* entry that spawned it, and the tool-call surface is the one failure path that
|
|
12
|
+
* never reaches any line — a browser-level problem (target closed, dialog stuck,
|
|
13
|
+
* protocol timeout) is returned to the calling agent and lands nowhere else.
|
|
14
|
+
* Hence only the tool capture survives here.
|
|
15
|
+
*
|
|
16
|
+
* The prefix rule changed with the component model: a connection publishes under
|
|
17
|
+
* `mcp__<entry id>__`, where the entry id is the manager's, not the row's old
|
|
18
|
+
* `serverName`. So the capture answers for whichever live connection of this
|
|
19
|
+
* component's own kinds carries the tool; a tool outside this component's
|
|
20
|
+
* namespace never touches the mirror.
|
|
21
21
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
.join(" ");
|
|
26
|
-
if (level === "error" || level === "warn") {
|
|
27
|
-
controller.state.entry.lastError = firstLine(message);
|
|
28
|
-
controller.state.entry.chromeMissing = isChromeMissing(message);
|
|
29
|
-
}
|
|
30
|
-
else if (level === "info" && BRIDGE_RECONNECTED.test(message)) {
|
|
31
|
-
controller.state.entry.lastError = "";
|
|
32
|
-
controller.state.entry.chromeMissing = false;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
22
|
+
import { captureToolResults } from "@comecaramelos/dsh-ancesters/host";
|
|
23
|
+
import { isChromeMissing } from "../status.js";
|
|
24
|
+
import { publishLive } from "./publish.js";
|
|
35
25
|
/**
|
|
36
26
|
* Register the tool-call status capture: browser-level failures surface only as
|
|
37
|
-
* the calling agent's tool result, never on
|
|
38
|
-
*
|
|
39
|
-
* `isError` writes the failure into the
|
|
40
|
-
* clears both, so the card reports current health.
|
|
41
|
-
*
|
|
42
|
-
*
|
|
27
|
+
* the calling agent's tool result, never on a line, so a settled result whose
|
|
28
|
+
* registered name is prefixed `mcp__<id>__` for one of this component's live
|
|
29
|
+
* connections and carries `isError` writes the failure into the live mirror; a
|
|
30
|
+
* successful chrome-tool call clears both, so the card reports current health.
|
|
31
|
+
* A success is *evidence* — what a missing selection never produces — while an
|
|
32
|
+
* unrelated failure line never displaces the known executable-missing answer
|
|
33
|
+
* standing (the rule the old bridge-log capture followed too). The body is
|
|
34
|
+
* wrapped in try/catch (warn only — a capture fault must never break a tool
|
|
35
|
+
* call) and returns `next()` unchanged.
|
|
43
36
|
*/
|
|
44
37
|
export function registerToolCapture(controller) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
38
|
+
// The listener, the prefix match, the note and the never-break-a-tool-call
|
|
39
|
+
// wrapping are ancestros' `captureToolResults`; the prefixes are asked on
|
|
40
|
+
// every call, because the live connections come and go.
|
|
41
|
+
captureToolResults(controller.ctx, {
|
|
42
|
+
name: `dsh-chrome-mcp(${controller.config.serverName})`,
|
|
43
|
+
prefix: (name) => ownedToolPrefix(controller).some((prefix) => name.startsWith(prefix)),
|
|
44
|
+
onResult: (note) => {
|
|
45
|
+
if (note === null) {
|
|
46
|
+
controller.state.live.lastError = "";
|
|
47
|
+
controller.state.live.chromeMissing = false;
|
|
52
48
|
}
|
|
49
|
+
else if (isChromeMissing(note) || !controller.state.live.chromeMissing) {
|
|
50
|
+
controller.state.live.lastError = note;
|
|
51
|
+
controller.state.live.chromeMissing = isChromeMissing(note);
|
|
52
|
+
}
|
|
53
|
+
publishLive(controller);
|
|
53
54
|
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
controller.ctx.logger.warn(`chrome-devtools-mcp(${controller.config.serverName}): tool status capture failed: ${String(error)}`);
|
|
56
|
-
}
|
|
57
|
-
return next();
|
|
58
55
|
});
|
|
59
56
|
}
|
|
57
|
+
/** The namespaces whose tool calls belong to this component: every live
|
|
58
|
+
* connection of the component's own kinds answers under its entry id. A tool
|
|
59
|
+
* named anywhere else (another component's connection, a core stdio entry) is
|
|
60
|
+
* simply not this component's business. */
|
|
61
|
+
function ownedToolPrefixes(controller) {
|
|
62
|
+
const service = controller.state.connections;
|
|
63
|
+
if (service === void 0)
|
|
64
|
+
return [];
|
|
65
|
+
const prefixes = [];
|
|
66
|
+
try {
|
|
67
|
+
for (const entry of service.entries()) {
|
|
68
|
+
if (entry.kind !== "chrome" && entry.kind !== "chrome-windows")
|
|
69
|
+
continue;
|
|
70
|
+
prefixes.push(`mcp__${entry.id}__`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
return prefixes;
|
|
77
|
+
}
|
|
78
|
+
function ownedToolPrefix(controller) {
|
|
79
|
+
const prefixes = ownedToolPrefixes(controller);
|
|
80
|
+
// The row's own `serverName` still names the tools while the connection was
|
|
81
|
+
// answered under it (the migration-era config), so a captured tool under
|
|
82
|
+
// that namespace is also ours.
|
|
83
|
+
return prefixes.length > 0 ? prefixes : [`mcp__${controller.config.serverName}__`];
|
|
84
|
+
}
|
|
60
85
|
//# sourceMappingURL=captures.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captures.js","sourceRoot":"","sources":["../../../src/host/controller/captures.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"captures.js","sourceRoot":"","sources":["../../../src/host/controller/captures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAsB;IACtD,2EAA2E;IAC3E,0EAA0E;IAC1E,wDAAwD;IACxD,kBAAkB,CAAC,UAAU,CAAC,GAAY,EAAE;QACxC,IAAI,EAAE,kBAAkB,UAAU,CAAC,MAAM,CAAC,UAAU,GAAG;QACvD,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/F,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;YACf,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAChB,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;gBACrC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAChD,CAAC;iBAAM,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;gBACvC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;YAChE,CAAC;YACD,WAAW,CAAC,UAAU,CAAC,CAAC;QAC5B,CAAC;KACJ,CAAC,CAAC;AACP,CAAC;AAED;;;2CAG2C;AAC3C,SAAS,iBAAiB,CAAC,UAAsB;IAC7C,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC;IAC7C,IAAI,OAAO,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YACpC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB;gBAAE,SAAS;YACzE,QAAQ,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QACxC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,SAAS,eAAe,CAAC,UAAsB;IAC3C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAC/C,4EAA4E;IAC5E,yEAAyE;IACzE,+BAA+B;IAC/B,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,UAAU,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC;AACvF,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Controller } from "./state.js";
|
|
2
|
-
/** Route one
|
|
3
|
-
export declare function
|
|
2
|
+
/** Route one configuration-form commit. */
|
|
3
|
+
export declare function onFormCommit(controller: Controller): void;
|
|
4
4
|
//# sourceMappingURL=commits.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commits.d.ts","sourceRoot":"","sources":["../../../src/host/controller/commits.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"commits.d.ts","sourceRoot":"","sources":["../../../src/host/controller/commits.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CA8FzD"}
|
|
@@ -1,55 +1,106 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Controller —
|
|
2
|
+
* Controller — configuration-form commit routing.
|
|
3
3
|
*
|
|
4
|
-
* One
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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.
|
|
12
26
|
*/
|
|
13
27
|
import { normalizeEntries } from "../catalog.js";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
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";
|
|
17
32
|
import { applyChromePath, queue, sameEntries } from "./runs.js";
|
|
18
|
-
|
|
19
|
-
|
|
33
|
+
import { publishLive } from "./publish.js";
|
|
34
|
+
/** Route one configuration-form commit. */
|
|
35
|
+
export function onFormCommit(controller) {
|
|
20
36
|
const { state } = controller;
|
|
21
37
|
try {
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
28
56
|
// path the host seeded itself keeps standing until the user picks one:
|
|
29
|
-
// the seed is written into the
|
|
57
|
+
// the seed is written into the user layer, and until that write is
|
|
30
58
|
// visible a commit must not resolve back to "nothing selected".
|
|
31
|
-
const userLayer =
|
|
59
|
+
const userLayer = readPersistedChromePath(layers);
|
|
32
60
|
if (userLayer !== "")
|
|
33
61
|
state.seenUserSelection = true;
|
|
34
62
|
const seededCarry = state.seededPath !== "" && !state.seenUserSelection ? state.seededPath : "";
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
|
|
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)
|
|
38
74
|
applyChromePath(controller, nextChromePath, nextSource);
|
|
39
|
-
// Rows changes touch the list, never
|
|
40
|
-
const nextExecutables = normalizeEntries(
|
|
75
|
+
// Rows changes touch the list, never a connection.
|
|
76
|
+
const nextExecutables = normalizeEntries(layers.user.executables ?? layers.value.executables);
|
|
41
77
|
const rowsChanged = !sameEntries(nextExecutables, state.runningExecutables);
|
|
42
|
-
// The "Reduce log output" toggle lives here too:
|
|
43
|
-
//
|
|
44
|
-
// the
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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.
|
|
48
99
|
const firstCommit = state.lastRefreshNonce === void 0;
|
|
49
|
-
const refreshChanged = !firstCommit &&
|
|
50
|
-
const windowsChanged = !firstCommit &&
|
|
51
|
-
state.lastRefreshNonce =
|
|
52
|
-
state.lastWindowsNonce =
|
|
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;
|
|
53
104
|
if (firstCommit) {
|
|
54
105
|
// The registration run: discovery + probe, no separate call. A
|
|
55
106
|
// persisted Windows trigger folds in silently — booting a host must
|
|
@@ -57,9 +108,9 @@ export function onSettingsChange(controller) {
|
|
|
57
108
|
queue(controller, "probe");
|
|
58
109
|
}
|
|
59
110
|
else {
|
|
60
|
-
// The card's **
|
|
61
|
-
//
|
|
62
|
-
//
|
|
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.
|
|
63
114
|
if (refreshChanged || rowsChanged)
|
|
64
115
|
queue(controller, "probe");
|
|
65
116
|
// The card's **Prelaunch Windows Chrome** button: one Windows run,
|
|
@@ -69,7 +120,12 @@ export function onSettingsChange(controller) {
|
|
|
69
120
|
}
|
|
70
121
|
}
|
|
71
122
|
catch (error) {
|
|
72
|
-
controller.ctx.logger.error(`chrome-
|
|
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);
|
|
73
129
|
}
|
|
74
130
|
}
|
|
75
131
|
//# sourceMappingURL=commits.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commits.js","sourceRoot":"","sources":["../../../src/host/controller/commits.ts"],"names":[],"mappings":"AAAA
|
|
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"}
|