@narumitw/pi-chrome-devtools 0.52.0 → 0.52.1
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 +10 -1
- package/dist/chunks/browser-settings-menu-L4CZINWO.ts +266 -0
- package/dist/chunks/browser-settings-menu-L4CZINWO.ts.map +7 -0
- package/dist/chunks/chunk-RM7OGXVL.ts +1607 -0
- package/dist/chunks/chunk-RM7OGXVL.ts.map +7 -0
- package/dist/chunks/menu-U4AIAN7V.ts +397 -0
- package/dist/chunks/menu-U4AIAN7V.ts.map +7 -0
- package/dist/index.ts +762 -0
- package/dist/index.ts.map +7 -0
- package/package.json +11 -7
package/README.md
CHANGED
|
@@ -51,6 +51,10 @@ Try this package locally from the repository root:
|
|
|
51
51
|
pi -e ./packages/pi-chrome-devtools
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
The package declares `dist/index.ts`, so an unbuilt local checkout must run `npm --workspace @narumitw/pi-chrome-devtools run build` before Pi loads the package directory.
|
|
55
|
+
|
|
56
|
+
`just try chrome-devtools` runs that build automatically.
|
|
57
|
+
|
|
54
58
|
## 🚀 Browser startup
|
|
55
59
|
|
|
56
60
|
Without unpacked extensions, the extension first tries `browser.endpoint`, defaulting to
|
|
@@ -313,6 +317,9 @@ filename is deprecated and will be removed in a future major release.
|
|
|
313
317
|
|
|
314
318
|
```txt
|
|
315
319
|
packages/pi-chrome-devtools/
|
|
320
|
+
├── dist/ # Generated TypeScript runtime loaded by Jiti
|
|
321
|
+
├── scripts/
|
|
322
|
+
│ └── build-runtime.mjs # Deterministic runtime builder and boundary validator
|
|
316
323
|
├── src/
|
|
317
324
|
│ ├── index.ts # Pi package entrypoint
|
|
318
325
|
│ ├── chrome-devtools.ts # Extension registration and command orchestration
|
|
@@ -329,11 +336,13 @@ packages/pi-chrome-devtools/
|
|
|
329
336
|
```json
|
|
330
337
|
{
|
|
331
338
|
"pi": {
|
|
332
|
-
"extensions": ["./
|
|
339
|
+
"extensions": ["./dist/index.ts"]
|
|
333
340
|
}
|
|
334
341
|
}
|
|
335
342
|
```
|
|
336
343
|
|
|
344
|
+
The generated runtime is built from the authoritative `src/index.ts` graph and does not import back into `src`.
|
|
345
|
+
|
|
337
346
|
## 🔎 Keywords
|
|
338
347
|
|
|
339
348
|
Pi extension, Pi coding agent, Chrome DevTools Protocol, CDP, browser automation, web debugging, JavaScript evaluation, screenshot automation, AI coding agent tools.
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// @generated by scripts/build-runtime.mjs; do not edit.
|
|
2
|
+
// @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
|
|
3
|
+
import {
|
|
4
|
+
applyRuntimeBrowserSettings,
|
|
5
|
+
loadSettings,
|
|
6
|
+
parseBrowserEndpoint,
|
|
7
|
+
sanitizeChromeDevtoolsDisplay,
|
|
8
|
+
saveBrowserSettings,
|
|
9
|
+
shutdownManagedBrowser,
|
|
10
|
+
state
|
|
11
|
+
} from "./chunk-RM7OGXVL.js";
|
|
12
|
+
|
|
13
|
+
// src/browser-settings-menu.ts
|
|
14
|
+
import { isAbsolute } from "node:path";
|
|
15
|
+
import { defineMenu, runMenu } from "@narumitw/pi-tui-kit";
|
|
16
|
+
async function showChromeDevtoolsBrowserSettings(ctx, generation) {
|
|
17
|
+
const ownerSignal = state.sessionController.signal;
|
|
18
|
+
const isCurrent2 = () => generation === state.sessionGeneration && !ownerSignal.aborted;
|
|
19
|
+
const projectTrusted = ctx.isProjectTrusted();
|
|
20
|
+
const menu = defineMenu({
|
|
21
|
+
start: "settings",
|
|
22
|
+
screens: {
|
|
23
|
+
settings: ({ state: current }) => {
|
|
24
|
+
if (current.load.userFile.kind === "invalid") return invalidSettingsScreen(current.load);
|
|
25
|
+
const browser = current.load.effectiveBrowser;
|
|
26
|
+
return {
|
|
27
|
+
kind: "settings",
|
|
28
|
+
title: "Chrome DevTools Browser settings",
|
|
29
|
+
lines: settingsContextLines(current.load),
|
|
30
|
+
items: [
|
|
31
|
+
{
|
|
32
|
+
id: "endpoint",
|
|
33
|
+
label: "DevTools endpoint",
|
|
34
|
+
description: 'HTTP origin with an explicit port; enter "default" to restore 127.0.0.1:9222.',
|
|
35
|
+
currentValue: sanitizeChromeDevtoolsDisplay(browser.endpoint),
|
|
36
|
+
action: "open-endpoint"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "auto-launch",
|
|
40
|
+
label: "Auto-launch",
|
|
41
|
+
description: "Launch an isolated managed browser when a local endpoint is unavailable.",
|
|
42
|
+
currentValue: browser.autoLaunchEnabled ? "On" : "Off",
|
|
43
|
+
values: ["On", "Off"],
|
|
44
|
+
action: "set-auto-launch"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "executable",
|
|
48
|
+
label: "Browser executable",
|
|
49
|
+
description: 'Absolute executable path; enter "automatic" to restore browser discovery.',
|
|
50
|
+
currentValue: sanitizeChromeDevtoolsDisplay(browser.executablePath ?? "Automatic"),
|
|
51
|
+
action: "open-executable"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: "extensions",
|
|
55
|
+
label: "Unpacked extensions",
|
|
56
|
+
description: "Inspect trusted extension paths configured in user or project JSON.",
|
|
57
|
+
currentValue: `${browser.extensionPaths.length} configured`,
|
|
58
|
+
action: "show-extensions"
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
endpoint: ({ state: current }) => ({
|
|
64
|
+
kind: "input",
|
|
65
|
+
title: "DevTools endpoint",
|
|
66
|
+
lines: [
|
|
67
|
+
sanitizeChromeDevtoolsDisplay(
|
|
68
|
+
`Current effective endpoint: ${current.load.effectiveBrowser.endpoint}`
|
|
69
|
+
),
|
|
70
|
+
'Enter an HTTP origin with an explicit port, or "default".'
|
|
71
|
+
],
|
|
72
|
+
placeholder: "http://127.0.0.1:9222",
|
|
73
|
+
action: "save-endpoint",
|
|
74
|
+
hint: "back"
|
|
75
|
+
}),
|
|
76
|
+
executable: ({ state: current }) => ({
|
|
77
|
+
kind: "input",
|
|
78
|
+
title: "Browser executable",
|
|
79
|
+
lines: [
|
|
80
|
+
sanitizeChromeDevtoolsDisplay(
|
|
81
|
+
`Current effective executable: ${current.load.effectiveBrowser.executablePath ?? "automatic discovery"}`
|
|
82
|
+
),
|
|
83
|
+
'Enter an absolute path, or "automatic".'
|
|
84
|
+
],
|
|
85
|
+
placeholder: "absolute browser executable path",
|
|
86
|
+
action: "save-executable",
|
|
87
|
+
hint: "back"
|
|
88
|
+
}),
|
|
89
|
+
extensions: ({ state: current }) => ({
|
|
90
|
+
kind: "detail",
|
|
91
|
+
title: "Unpacked extensions",
|
|
92
|
+
lines: extensionDetailLines(current.load),
|
|
93
|
+
hint: "back"
|
|
94
|
+
})
|
|
95
|
+
},
|
|
96
|
+
actions: {
|
|
97
|
+
"open-endpoint": () => ({ kind: "to", screen: "endpoint" }),
|
|
98
|
+
"save-endpoint": async ({ value, signal }) => {
|
|
99
|
+
if (value === void 0) return { kind: "rejected" };
|
|
100
|
+
let endpoint;
|
|
101
|
+
try {
|
|
102
|
+
const trimmed = value.trim();
|
|
103
|
+
endpoint = trimmed.toLowerCase() === "default" ? null : parseBrowserEndpoint(trimmed).endpoint;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
notifySaveFailure(ctx, error);
|
|
106
|
+
return { kind: "rejected" };
|
|
107
|
+
}
|
|
108
|
+
const saved = await saveAndApplyBrowserPatch(
|
|
109
|
+
ctx,
|
|
110
|
+
generation,
|
|
111
|
+
ownerSignal,
|
|
112
|
+
signal,
|
|
113
|
+
projectTrusted,
|
|
114
|
+
{ endpoint }
|
|
115
|
+
);
|
|
116
|
+
if (!saved) return { kind: "rejected" };
|
|
117
|
+
notifyEffectiveSave(
|
|
118
|
+
ctx,
|
|
119
|
+
"endpoint",
|
|
120
|
+
saved.effectiveBrowser.endpoint,
|
|
121
|
+
saved.effectiveBrowser.endpointSource
|
|
122
|
+
);
|
|
123
|
+
return { kind: "back" };
|
|
124
|
+
},
|
|
125
|
+
"set-auto-launch": async ({ value, signal }) => {
|
|
126
|
+
if (value !== "On" && value !== "Off") return { kind: "rejected" };
|
|
127
|
+
const saved = await saveAndApplyBrowserPatch(
|
|
128
|
+
ctx,
|
|
129
|
+
generation,
|
|
130
|
+
ownerSignal,
|
|
131
|
+
signal,
|
|
132
|
+
projectTrusted,
|
|
133
|
+
{ autoLaunch: value === "On" }
|
|
134
|
+
);
|
|
135
|
+
if (!saved) return { kind: "rejected" };
|
|
136
|
+
notifyEffectiveSave(
|
|
137
|
+
ctx,
|
|
138
|
+
"auto-launch",
|
|
139
|
+
saved.effectiveBrowser.autoLaunchEnabled ? "On" : "Off",
|
|
140
|
+
saved.effectiveBrowser.autoLaunchSource
|
|
141
|
+
);
|
|
142
|
+
return { kind: "stay" };
|
|
143
|
+
},
|
|
144
|
+
"open-executable": () => ({ kind: "to", screen: "executable" }),
|
|
145
|
+
"save-executable": async ({ value, signal }) => {
|
|
146
|
+
if (value === void 0) return { kind: "rejected" };
|
|
147
|
+
const trimmed = value.trim();
|
|
148
|
+
const reset = ["automatic", "default", "none"].includes(trimmed.toLowerCase());
|
|
149
|
+
if (!reset && (!trimmed || !isAbsolute(trimmed))) {
|
|
150
|
+
notifySaveFailure(ctx, new Error('Enter an absolute path or "automatic".'));
|
|
151
|
+
return { kind: "rejected" };
|
|
152
|
+
}
|
|
153
|
+
const executablePath = reset ? null : trimmed;
|
|
154
|
+
const saved = await saveAndApplyBrowserPatch(
|
|
155
|
+
ctx,
|
|
156
|
+
generation,
|
|
157
|
+
ownerSignal,
|
|
158
|
+
signal,
|
|
159
|
+
projectTrusted,
|
|
160
|
+
{ executablePath }
|
|
161
|
+
);
|
|
162
|
+
if (!saved) return { kind: "rejected" };
|
|
163
|
+
notifyEffectiveSave(
|
|
164
|
+
ctx,
|
|
165
|
+
"browser executable",
|
|
166
|
+
saved.effectiveBrowser.executablePath ?? "automatic discovery",
|
|
167
|
+
saved.effectiveBrowser.executablePathSource
|
|
168
|
+
);
|
|
169
|
+
return { kind: "back" };
|
|
170
|
+
},
|
|
171
|
+
"show-extensions": () => ({ kind: "to", screen: "extensions" })
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
const result = await runMenu(ctx, menu, {
|
|
175
|
+
getState: async ({ signal }) => {
|
|
176
|
+
signal.throwIfAborted();
|
|
177
|
+
const load = await loadSettings({ cwd: ctx.cwd, projectTrusted });
|
|
178
|
+
signal.throwIfAborted();
|
|
179
|
+
return { load };
|
|
180
|
+
},
|
|
181
|
+
signal: ownerSignal,
|
|
182
|
+
isCurrent: isCurrent2,
|
|
183
|
+
onError: (currentCtx, error) => currentCtx.ui.notify(
|
|
184
|
+
sanitizeChromeDevtoolsDisplay(
|
|
185
|
+
`Chrome DevTools browser settings failed: ${formatError(error)}`
|
|
186
|
+
),
|
|
187
|
+
"error"
|
|
188
|
+
)
|
|
189
|
+
});
|
|
190
|
+
return { closeParent: result.kind === "closed" && result.reason === "close" };
|
|
191
|
+
}
|
|
192
|
+
async function saveAndApplyBrowserPatch(ctx, generation, ownerSignal, actionSignal, projectTrusted, patch) {
|
|
193
|
+
try {
|
|
194
|
+
await ctx.waitForIdle();
|
|
195
|
+
if (!isCurrent(generation, ownerSignal, actionSignal)) return false;
|
|
196
|
+
await saveBrowserSettings(patch);
|
|
197
|
+
if (!isCurrent(generation, ownerSignal, actionSignal)) return false;
|
|
198
|
+
await shutdownManagedBrowser();
|
|
199
|
+
if (!isCurrent(generation, ownerSignal, actionSignal)) return false;
|
|
200
|
+
const loaded = await loadSettings({ cwd: ctx.cwd, projectTrusted });
|
|
201
|
+
if (!isCurrent(generation, ownerSignal, actionSignal)) return false;
|
|
202
|
+
applyRuntimeBrowserSettings(loaded.effectiveBrowser, loaded.paths, projectTrusted);
|
|
203
|
+
state.settingsNotice = loaded.notice;
|
|
204
|
+
return loaded;
|
|
205
|
+
} catch (error) {
|
|
206
|
+
if (isCurrent(generation, ownerSignal, actionSignal)) notifySaveFailure(ctx, error);
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function isCurrent(generation, ownerSignal, actionSignal) {
|
|
211
|
+
return generation === state.sessionGeneration && !ownerSignal.aborted && !actionSignal.aborted;
|
|
212
|
+
}
|
|
213
|
+
function invalidSettingsScreen(load) {
|
|
214
|
+
const reason = load.userFile.kind === "invalid" ? load.userFile.reason : "The user settings file is unavailable.";
|
|
215
|
+
return {
|
|
216
|
+
kind: "detail",
|
|
217
|
+
title: "Chrome DevTools Browser settings \xB7 Read only",
|
|
218
|
+
lines: [
|
|
219
|
+
sanitizeChromeDevtoolsDisplay(
|
|
220
|
+
`Fix the active user settings before saving; the file will not be overwritten. ${reason}`
|
|
221
|
+
)
|
|
222
|
+
],
|
|
223
|
+
hint: "back"
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function settingsContextLines(load) {
|
|
227
|
+
const browser = load.effectiveBrowser;
|
|
228
|
+
return [
|
|
229
|
+
`User settings \xB7 ${load.paths.user}`,
|
|
230
|
+
`Effective sources: endpoint ${browser.endpointSource} \xB7 auto-launch ${browser.autoLaunchSource} \xB7 executable ${browser.executablePathSource}`,
|
|
231
|
+
...load.notice ? [`Warning: ${load.notice}`] : []
|
|
232
|
+
].map((line) => sanitizeChromeDevtoolsDisplay(line));
|
|
233
|
+
}
|
|
234
|
+
function extensionDetailLines(load) {
|
|
235
|
+
const browser = load.effectiveBrowser;
|
|
236
|
+
return [
|
|
237
|
+
`Effective source: ${browser.extensionPathsSource}`,
|
|
238
|
+
...browser.extensionPaths.length > 0 ? browser.extensionPaths.map((extensionPath) => `- ${extensionPath}`) : ["No unpacked extensions are configured."],
|
|
239
|
+
"Edit browser.extensionPaths in the user JSON or a trusted project JSON, then run /reload.",
|
|
240
|
+
"Unpacked extensions execute privileged browser code; load only paths you trust."
|
|
241
|
+
].map((line) => sanitizeChromeDevtoolsDisplay(line));
|
|
242
|
+
}
|
|
243
|
+
function notifyEffectiveSave(ctx, setting, effectiveValue, source) {
|
|
244
|
+
const overrideNotice = source === "environment" ? " The deprecated environment override remains effective." : "";
|
|
245
|
+
ctx.ui.notify(
|
|
246
|
+
sanitizeChromeDevtoolsDisplay(
|
|
247
|
+
`Chrome DevTools ${setting} saved. Effective ${setting}: ${effectiveValue} (${source}).${overrideNotice}`
|
|
248
|
+
),
|
|
249
|
+
"info"
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
function notifySaveFailure(ctx, error) {
|
|
253
|
+
ctx.ui.notify(
|
|
254
|
+
sanitizeChromeDevtoolsDisplay(
|
|
255
|
+
`Chrome DevTools browser settings save failed; previous settings remain active: ${formatError(error)}`
|
|
256
|
+
),
|
|
257
|
+
"warning"
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
function formatError(error) {
|
|
261
|
+
return error instanceof Error ? error.message : String(error);
|
|
262
|
+
}
|
|
263
|
+
export {
|
|
264
|
+
showChromeDevtoolsBrowserSettings
|
|
265
|
+
};
|
|
266
|
+
//# sourceMappingURL=browser-settings-menu-L4CZINWO.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/browser-settings-menu.ts"],
|
|
4
|
+
"sourcesContent": ["import { isAbsolute } from \"node:path\";\nimport type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport { defineMenu, runMenu } from \"@narumitw/pi-tui-kit\";\nimport { shutdownManagedBrowser } from \"./browser-manager.js\";\nimport { applyRuntimeBrowserSettings, state } from \"./runtime.js\";\nimport {\n\ttype BrowserSettingsPatch,\n\ttype BrowserSettingsSource,\n\tloadSettings,\n\tparseBrowserEndpoint,\n\ttype SettingsLoadResult,\n\tsaveBrowserSettings,\n} from \"./settings.js\";\nimport { sanitizeChromeDevtoolsDisplay } from \"./tool-selector.js\";\n\ntype BrowserSettingsScreen = \"settings\" | \"endpoint\" | \"executable\" | \"extensions\";\ntype BrowserSettingsAction =\n\t| \"open-endpoint\"\n\t| \"save-endpoint\"\n\t| \"set-auto-launch\"\n\t| \"open-executable\"\n\t| \"save-executable\"\n\t| \"show-extensions\";\n\ninterface BrowserSettingsMenuState {\n\tload: SettingsLoadResult;\n}\n\ntype CommandContext = ExtensionCommandContext;\n\nexport async function showChromeDevtoolsBrowserSettings(\n\tctx: CommandContext,\n\tgeneration: number,\n): Promise<{ closeParent: boolean }> {\n\tconst ownerSignal = state.sessionController.signal;\n\tconst isCurrent = () => generation === state.sessionGeneration && !ownerSignal.aborted;\n\tconst projectTrusted = ctx.isProjectTrusted();\n\tconst menu = defineMenu<BrowserSettingsMenuState, BrowserSettingsScreen, BrowserSettingsAction>({\n\t\tstart: \"settings\",\n\t\tscreens: {\n\t\t\tsettings: ({ state: current }) => {\n\t\t\t\tif (current.load.userFile.kind === \"invalid\") return invalidSettingsScreen(current.load);\n\t\t\t\tconst browser = current.load.effectiveBrowser;\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"settings\",\n\t\t\t\t\ttitle: \"Chrome DevTools Browser settings\",\n\t\t\t\t\tlines: settingsContextLines(current.load),\n\t\t\t\t\titems: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: \"endpoint\",\n\t\t\t\t\t\t\tlabel: \"DevTools endpoint\",\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t'HTTP origin with an explicit port; enter \"default\" to restore 127.0.0.1:9222.',\n\t\t\t\t\t\t\tcurrentValue: sanitizeChromeDevtoolsDisplay(browser.endpoint),\n\t\t\t\t\t\t\taction: \"open-endpoint\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: \"auto-launch\",\n\t\t\t\t\t\t\tlabel: \"Auto-launch\",\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"Launch an isolated managed browser when a local endpoint is unavailable.\",\n\t\t\t\t\t\t\tcurrentValue: browser.autoLaunchEnabled ? \"On\" : \"Off\",\n\t\t\t\t\t\t\tvalues: [\"On\", \"Off\"],\n\t\t\t\t\t\t\taction: \"set-auto-launch\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: \"executable\",\n\t\t\t\t\t\t\tlabel: \"Browser executable\",\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t'Absolute executable path; enter \"automatic\" to restore browser discovery.',\n\t\t\t\t\t\t\tcurrentValue: sanitizeChromeDevtoolsDisplay(browser.executablePath ?? \"Automatic\"),\n\t\t\t\t\t\t\taction: \"open-executable\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: \"extensions\",\n\t\t\t\t\t\t\tlabel: \"Unpacked extensions\",\n\t\t\t\t\t\t\tdescription: \"Inspect trusted extension paths configured in user or project JSON.\",\n\t\t\t\t\t\t\tcurrentValue: `${browser.extensionPaths.length} configured`,\n\t\t\t\t\t\t\taction: \"show-extensions\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t},\n\t\t\tendpoint: ({ state: current }) => ({\n\t\t\t\tkind: \"input\",\n\t\t\t\ttitle: \"DevTools endpoint\",\n\t\t\t\tlines: [\n\t\t\t\t\tsanitizeChromeDevtoolsDisplay(\n\t\t\t\t\t\t`Current effective endpoint: ${current.load.effectiveBrowser.endpoint}`,\n\t\t\t\t\t),\n\t\t\t\t\t'Enter an HTTP origin with an explicit port, or \"default\".',\n\t\t\t\t],\n\t\t\t\tplaceholder: \"http://127.0.0.1:9222\",\n\t\t\t\taction: \"save-endpoint\",\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t\texecutable: ({ state: current }) => ({\n\t\t\t\tkind: \"input\",\n\t\t\t\ttitle: \"Browser executable\",\n\t\t\t\tlines: [\n\t\t\t\t\tsanitizeChromeDevtoolsDisplay(\n\t\t\t\t\t\t`Current effective executable: ${current.load.effectiveBrowser.executablePath ?? \"automatic discovery\"}`,\n\t\t\t\t\t),\n\t\t\t\t\t'Enter an absolute path, or \"automatic\".',\n\t\t\t\t],\n\t\t\t\tplaceholder: \"absolute browser executable path\",\n\t\t\t\taction: \"save-executable\",\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t\textensions: ({ state: current }) => ({\n\t\t\t\tkind: \"detail\",\n\t\t\t\ttitle: \"Unpacked extensions\",\n\t\t\t\tlines: extensionDetailLines(current.load),\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t},\n\t\tactions: {\n\t\t\t\"open-endpoint\": () => ({ kind: \"to\", screen: \"endpoint\" }),\n\t\t\t\"save-endpoint\": async ({ value, signal }) => {\n\t\t\t\tif (value === undefined) return { kind: \"rejected\" };\n\t\t\t\tlet endpoint: string | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst trimmed = value.trim();\n\t\t\t\t\tendpoint =\n\t\t\t\t\t\ttrimmed.toLowerCase() === \"default\" ? null : parseBrowserEndpoint(trimmed).endpoint;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tnotifySaveFailure(ctx, error);\n\t\t\t\t\treturn { kind: \"rejected\" };\n\t\t\t\t}\n\t\t\t\tconst saved = await saveAndApplyBrowserPatch(\n\t\t\t\t\tctx,\n\t\t\t\t\tgeneration,\n\t\t\t\t\townerSignal,\n\t\t\t\t\tsignal,\n\t\t\t\t\tprojectTrusted,\n\t\t\t\t\t{ endpoint },\n\t\t\t\t);\n\t\t\t\tif (!saved) return { kind: \"rejected\" };\n\t\t\t\tnotifyEffectiveSave(\n\t\t\t\t\tctx,\n\t\t\t\t\t\"endpoint\",\n\t\t\t\t\tsaved.effectiveBrowser.endpoint,\n\t\t\t\t\tsaved.effectiveBrowser.endpointSource,\n\t\t\t\t);\n\t\t\t\treturn { kind: \"back\" };\n\t\t\t},\n\t\t\t\"set-auto-launch\": async ({ value, signal }) => {\n\t\t\t\tif (value !== \"On\" && value !== \"Off\") return { kind: \"rejected\" };\n\t\t\t\tconst saved = await saveAndApplyBrowserPatch(\n\t\t\t\t\tctx,\n\t\t\t\t\tgeneration,\n\t\t\t\t\townerSignal,\n\t\t\t\t\tsignal,\n\t\t\t\t\tprojectTrusted,\n\t\t\t\t\t{ autoLaunch: value === \"On\" },\n\t\t\t\t);\n\t\t\t\tif (!saved) return { kind: \"rejected\" };\n\t\t\t\tnotifyEffectiveSave(\n\t\t\t\t\tctx,\n\t\t\t\t\t\"auto-launch\",\n\t\t\t\t\tsaved.effectiveBrowser.autoLaunchEnabled ? \"On\" : \"Off\",\n\t\t\t\t\tsaved.effectiveBrowser.autoLaunchSource,\n\t\t\t\t);\n\t\t\t\treturn { kind: \"stay\" };\n\t\t\t},\n\t\t\t\"open-executable\": () => ({ kind: \"to\", screen: \"executable\" }),\n\t\t\t\"save-executable\": async ({ value, signal }) => {\n\t\t\t\tif (value === undefined) return { kind: \"rejected\" };\n\t\t\t\tconst trimmed = value.trim();\n\t\t\t\tconst reset = [\"automatic\", \"default\", \"none\"].includes(trimmed.toLowerCase());\n\t\t\t\tif (!reset && (!trimmed || !isAbsolute(trimmed))) {\n\t\t\t\t\tnotifySaveFailure(ctx, new Error('Enter an absolute path or \"automatic\".'));\n\t\t\t\t\treturn { kind: \"rejected\" };\n\t\t\t\t}\n\t\t\t\tconst executablePath = reset ? null : trimmed;\n\t\t\t\tconst saved = await saveAndApplyBrowserPatch(\n\t\t\t\t\tctx,\n\t\t\t\t\tgeneration,\n\t\t\t\t\townerSignal,\n\t\t\t\t\tsignal,\n\t\t\t\t\tprojectTrusted,\n\t\t\t\t\t{ executablePath },\n\t\t\t\t);\n\t\t\t\tif (!saved) return { kind: \"rejected\" };\n\t\t\t\tnotifyEffectiveSave(\n\t\t\t\t\tctx,\n\t\t\t\t\t\"browser executable\",\n\t\t\t\t\tsaved.effectiveBrowser.executablePath ?? \"automatic discovery\",\n\t\t\t\t\tsaved.effectiveBrowser.executablePathSource,\n\t\t\t\t);\n\t\t\t\treturn { kind: \"back\" };\n\t\t\t},\n\t\t\t\"show-extensions\": () => ({ kind: \"to\", screen: \"extensions\" }),\n\t\t},\n\t});\n\tconst result = await runMenu(ctx, menu, {\n\t\tgetState: async ({ signal }) => {\n\t\t\tsignal.throwIfAborted();\n\t\t\tconst load = await loadSettings({ cwd: ctx.cwd, projectTrusted });\n\t\t\tsignal.throwIfAborted();\n\t\t\treturn { load };\n\t\t},\n\t\tsignal: ownerSignal,\n\t\tisCurrent,\n\t\tonError: (currentCtx, error) =>\n\t\t\tcurrentCtx.ui.notify(\n\t\t\t\tsanitizeChromeDevtoolsDisplay(\n\t\t\t\t\t`Chrome DevTools browser settings failed: ${formatError(error)}`,\n\t\t\t\t),\n\t\t\t\t\"error\",\n\t\t\t),\n\t});\n\treturn { closeParent: result.kind === \"closed\" && result.reason === \"close\" };\n}\n\nasync function saveAndApplyBrowserPatch(\n\tctx: CommandContext,\n\tgeneration: number,\n\townerSignal: AbortSignal,\n\tactionSignal: AbortSignal,\n\tprojectTrusted: boolean,\n\tpatch: BrowserSettingsPatch,\n) {\n\ttry {\n\t\tawait ctx.waitForIdle();\n\t\tif (!isCurrent(generation, ownerSignal, actionSignal)) return false;\n\t\tawait saveBrowserSettings(patch);\n\t\tif (!isCurrent(generation, ownerSignal, actionSignal)) return false;\n\t\tawait shutdownManagedBrowser();\n\t\tif (!isCurrent(generation, ownerSignal, actionSignal)) return false;\n\t\tconst loaded = await loadSettings({ cwd: ctx.cwd, projectTrusted });\n\t\tif (!isCurrent(generation, ownerSignal, actionSignal)) return false;\n\t\tapplyRuntimeBrowserSettings(loaded.effectiveBrowser, loaded.paths, projectTrusted);\n\t\tstate.settingsNotice = loaded.notice;\n\t\treturn loaded;\n\t} catch (error) {\n\t\tif (isCurrent(generation, ownerSignal, actionSignal)) notifySaveFailure(ctx, error);\n\t\treturn false;\n\t}\n}\n\nfunction isCurrent(generation: number, ownerSignal: AbortSignal, actionSignal: AbortSignal) {\n\treturn generation === state.sessionGeneration && !ownerSignal.aborted && !actionSignal.aborted;\n}\n\nfunction invalidSettingsScreen(load: SettingsLoadResult) {\n\tconst reason =\n\t\tload.userFile.kind === \"invalid\"\n\t\t\t? load.userFile.reason\n\t\t\t: \"The user settings file is unavailable.\";\n\treturn {\n\t\tkind: \"detail\" as const,\n\t\ttitle: \"Chrome DevTools Browser settings \u00B7 Read only\",\n\t\tlines: [\n\t\t\tsanitizeChromeDevtoolsDisplay(\n\t\t\t\t`Fix the active user settings before saving; the file will not be overwritten. ${reason}`,\n\t\t\t),\n\t\t],\n\t\thint: \"back\" as const,\n\t};\n}\n\nfunction settingsContextLines(load: SettingsLoadResult) {\n\tconst browser = load.effectiveBrowser;\n\treturn [\n\t\t`User settings \u00B7 ${load.paths.user}`,\n\t\t`Effective sources: endpoint ${browser.endpointSource} \u00B7 auto-launch ${browser.autoLaunchSource} \u00B7 executable ${browser.executablePathSource}`,\n\t\t...(load.notice ? [`Warning: ${load.notice}`] : []),\n\t].map((line) => sanitizeChromeDevtoolsDisplay(line));\n}\n\nfunction extensionDetailLines(load: SettingsLoadResult) {\n\tconst browser = load.effectiveBrowser;\n\treturn [\n\t\t`Effective source: ${browser.extensionPathsSource}`,\n\t\t...(browser.extensionPaths.length > 0\n\t\t\t? browser.extensionPaths.map((extensionPath) => `- ${extensionPath}`)\n\t\t\t: [\"No unpacked extensions are configured.\"]),\n\t\t\"Edit browser.extensionPaths in the user JSON or a trusted project JSON, then run /reload.\",\n\t\t\"Unpacked extensions execute privileged browser code; load only paths you trust.\",\n\t].map((line) => sanitizeChromeDevtoolsDisplay(line));\n}\n\nfunction notifyEffectiveSave(\n\tctx: CommandContext,\n\tsetting: string,\n\teffectiveValue: string,\n\tsource: BrowserSettingsSource,\n) {\n\tconst overrideNotice =\n\t\tsource === \"environment\" ? \" The deprecated environment override remains effective.\" : \"\";\n\tctx.ui.notify(\n\t\tsanitizeChromeDevtoolsDisplay(\n\t\t\t`Chrome DevTools ${setting} saved. Effective ${setting}: ${effectiveValue} (${source}).${overrideNotice}`,\n\t\t),\n\t\t\"info\",\n\t);\n}\n\nfunction notifySaveFailure(ctx: CommandContext, error: unknown) {\n\tctx.ui.notify(\n\t\tsanitizeChromeDevtoolsDisplay(\n\t\t\t`Chrome DevTools browser settings save failed; previous settings remain active: ${formatError(error)}`,\n\t\t),\n\t\t\"warning\",\n\t);\n}\n\nfunction formatError(error: unknown) {\n\treturn error instanceof Error ? error.message : String(error);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["isCurrent"]
|
|
7
|
+
}
|