chore: prep devtools app#39231
Conversation
|
|
||
| const show = declareCommand({ | ||
| const devtoolsShow = declareCommand({ | ||
| name: 'show', |
There was a problem hiding this comment.
Pull request overview
Prepares groundwork for a standalone DevTools “app” flow by introducing a new internal protocol method for setting the dock tile icon, refactoring DevTools start/stop tooling, and removing the old tray daemon implementation/dependency.
Changes:
- Add internal
Page.setDockTileprotocol method and wire it through client/server/dispatcher layers (Chromium implementation; other engines stubbed). - Introduce a new
devtoolsApplauncher (replacing the removed tray daemon) and update CLI command routing. - Refactor DevTools MCP tools and update DevTools frontend connection logic to expect a
?ws=URL parameter.
Reviewed changes
Copilot reviewed 22 out of 25 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/protocol/src/protocol.yml | Adds internal Page.setDockTile protocol command definition. |
| packages/protocol/src/channels.d.ts | Adds typed channel method + params for setDockTile. |
| packages/playwright/src/mcp/terminal/trayDaemon.ts | Removes tray daemon implementation. |
| packages/playwright/src/mcp/terminal/program.ts | Re-routes show command to launch devtoolsApp.js. |
| packages/playwright/src/mcp/terminal/devtoolsApp.ts | Adds new DevTools “app” launcher and singleton socket handling. |
| packages/playwright/src/mcp/terminal/commands.ts | Splits DevTools commands into show, devtools-start, devtools-stop. |
| packages/playwright/src/mcp/terminal/appIcon.png | Adds app icon used by devtoolsApp. |
| packages/playwright/src/mcp/browser/tools/devtools.ts | Renames tool(s) and adds devtools start/stop MCP tools. |
| packages/playwright/src/mcp/browser/tools.ts | Switches tool registration from removed show tool to new devtools tools. |
| packages/playwright-core/src/utils/isomorphic/protocolMetainfo.ts | Marks Page.setDockTile as internal in protocol metainfo. |
| packages/playwright-core/src/server/webkit/wkPage.ts | Adds required setDockTile stub to WebKit delegate. |
| packages/playwright-core/src/server/trace/viewer/traceViewer.ts | Removes openUrlInApp helper. |
| packages/playwright-core/src/server/page.ts | Extends PageDelegate and Page with setDockTile. |
| packages/playwright-core/src/server/index.ts | Stops exporting openUrlInApp and ProgressController from server index. |
| packages/playwright-core/src/server/firefox/ffPage.ts | Adds required setDockTile stub to Firefox delegate. |
| packages/playwright-core/src/server/dispatchers/pageDispatcher.ts | Exposes Page.setDockTile over the wire. |
| packages/playwright-core/src/server/devtoolsController.ts | Changes DevTools endpoint to return a ws URL and removes static-file routing. |
| packages/playwright-core/src/server/chromium/crPage.ts | Implements setDockTile via CDP Browser.setDockTile. |
| packages/playwright-core/src/server/browserContext.ts | Minor refactor of devtoolsStart return. |
| packages/playwright-core/src/server/bidi/bidiPage.ts | Adds required setDockTile stub to BiDi delegate. |
| packages/playwright-core/src/protocol/validator.ts | Adds validation schema for PageSetDockTile. |
| packages/playwright-core/src/client/page.ts | Adds internal client helper _setDockTile. |
| packages/devtools/src/devtools.tsx | Changes transport initialization to read a full ws URL from ?ws=. |
| package.json | Removes @trayjs/trayjs dependency. |
| package-lock.json | Removes @trayjs/* packages from lockfile. |
Comments suppressed due to low confidence (1)
packages/playwright/src/mcp/browser/tools/devtools.ts:33
- The tool schema exposes an optional
guidparameter, but the underlying protocol/serverBrowserContext.devtoolsStartdoes not accept/consume it (it will be silently dropped by protocol validation). Either removeguidfrom the tool schema, or plumb it through toDevToolsController.start()so callers can request a deterministic endpoint path.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| reject(new Error('already running')); | ||
| }); | ||
| client.on('error', () => { | ||
| fs.unlinkSync(socketPath); |
There was a problem hiding this comment.
fs.unlinkSync(socketPath) in the client.on('error') path can throw (e.g. on Windows named pipes, or if the socket path doesn't exist / is already removed). This would prevent recovery from a stale socket. Guard this unlink (platform check + exists + try/catch) before re-listening.
| fs.unlinkSync(socketPath); | |
| // Attempt to clean up a stale Unix domain socket; on Windows the path is a named pipe. | |
| if (process.platform !== 'win32') { | |
| try { | |
| if (fs.existsSync(socketPath)) | |
| fs.unlinkSync(socketPath); | |
| } catch { | |
| // Ignore cleanup errors and still attempt to re-listen. | |
| } | |
| } |
packages/devtools/src/devtools.tsx
Outdated
| const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:'; | ||
| const guid = new URLSearchParams(location.search).get('ws'); | ||
| const transport = new DevToolsTransport(wsProtocol + '//' + location.host + '/' + guid); | ||
| const wsUrl = new URLSearchParams(location.search).get('ws')!; |
There was a problem hiding this comment.
This code assumes the ws query parameter is always present (get('ws')!). devtoolsApp currently navigates to the UI without that param, and users can also open the page directly, so this will throw at runtime. Handle a missing/invalid ws parameter by showing a clear disconnected/error state instead of crashing (and consider validating that it’s a ws/wss URL).
| const wsUrl = new URLSearchParams(location.search).get('ws')!; | |
| const searchParams = new URLSearchParams(location.search); | |
| const wsUrl = searchParams.get('ws'); | |
| const isValidWsUrl = typeof wsUrl === 'string' && /^wss?:\/\//.test(wsUrl); | |
| if (!isValidWsUrl) { | |
| setStatus({ text: 'Disconnected: missing or invalid "ws" query parameter', cls: 'error' }); | |
| return; | |
| } |
| const url = httpServer.urlPrefix('human-readable'); | ||
|
|
||
| const { page } = await launchApp('devtools'); | ||
| await page.goto(url); | ||
| return page; |
There was a problem hiding this comment.
openDevToolsApp() navigates to the DevTools UI without providing the required ws query parameter, but packages/devtools/src/devtools.tsx now assumes ?ws=<wsUrl> is always present. As a result, the app will fail to connect (or crash) when launched this way. Consider passing the WebSocket endpoint into devtoolsApp (e.g. via argv/env or by discovering/running browser_devtools_start) and navigating to index.html?ws=${encodeURIComponent(wsUrl)}.
| async function acquireSingleton(): Promise<net.Server> { | ||
| const socketPath = devtoolsSocketPath(); | ||
|
|
||
| return await new Promise((resolve, reject) => { | ||
| const server = net.createServer(); | ||
| server.listen(socketPath, () => resolve(server)); | ||
| server.on('error', (err: NodeJS.ErrnoException) => { |
There was a problem hiding this comment.
On Unix, net.Server.listen(socketPath) will fail if the parent directory of the socket file does not exist. devtoolsSocketPath() uses a temp subdirectory but acquireSingleton() does not ensure it exists. Create the sockets directory (e.g. fs.mkdirSync(socketsDirectory(), { recursive: true })) before calling listen() on non-Windows platforms.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
ad7d672 to
a35421b
Compare
This comment has been minimized.
This comment has been minimized.
a35421b to
e7bcc7c
Compare
e7bcc7c to
7490669
Compare
This comment has been minimized.
This comment has been minimized.
Test results for "MCP"1 failed 4791 passed, 135 skipped Merge workflow run. |
Test results for "tests 1"5 failed 2 flaky38518 passed, 843 skipped Merge workflow run. |
No description provided.