From 4cb83bacb740c212a19e1067e1796c316751514c Mon Sep 17 00:00:00 2001 From: "Tommy D. Rossi" Date: Sun, 16 Nov 2025 12:34:36 +0100 Subject: [PATCH] remove files --- multiple-playwrights.md | 113 ---------------------------------------- plan.md | 32 ------------ 2 files changed, 145 deletions(-) delete mode 100644 multiple-playwrights.md delete mode 100644 plan.md diff --git a/multiple-playwrights.md b/multiple-playwrights.md deleted file mode 100644 index 7ede2e6..0000000 --- a/multiple-playwrights.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Multiple Playwright Clients Architecture -description: How the CDP relay server supports multiple isolated Playwright connections -prompt: | - Write a high-level architecture document explaining how the CDP relay server - was modified to support multiple Playwright clients with session isolation. - Reference: @playwriter/src/extension/cdpRelay.ts ---- - -# Multiple Playwright Clients Architecture - -The CDP relay server now supports multiple concurrent Playwright clients, each with isolated browser tab sessions. This enables parallel automation scenarios while maintaining session integrity. - -## Overview - -The relay server acts as a bridge between: -- **Multiple Playwright clients** connecting via WebSocket to `/cdp/` -- **One Chrome Extension** connecting via WebSocket to `/extension` -- **Multiple browser tabs** controlled through Chrome DevTools Protocol (CDP) - -## Client Identification - -Each Playwright client must connect with a unique identifier in the connection path: - -``` -ws://localhost:19988/cdp/client-123 -ws://localhost:19988/cdp/automation-bot-1 -ws://localhost:19988/cdp/test-runner-42 -``` - -If no client ID is provided in the path, the connection is rejected. This ensures every client can be uniquely identified and tracked. - -## Session Ownership Model - -### Tab/Session Lifecycle - -1. **Initial State**: When the Chrome Extension attaches to a browser tab, it creates a CDP session that is initially **unclaimed** -2. **Claiming Ownership**: The first Playwright client to send a command to that session **claims ownership** -3. **Exclusive Access**: Once owned, only that client can send commands to that tab/session -4. **Access Denial**: Other clients receive an error if they attempt to access an owned session -5. **Release on Disconnect**: When a client disconnects, all its owned sessions become available again - -### Example Flow - -``` -1. Extension attaches to Tab A → Session S1 created (unclaimed) -2. Client-1 sends command to S1 → Client-1 owns S1 -3. Client-2 sends command to S1 → Error: "Session S1 is owned by client-1" -4. Extension attaches to Tab B → Session S2 created (unclaimed) -5. Client-2 sends command to S2 → Client-2 owns S2 -6. Client-1 disconnects → S1 becomes unclaimed -7. Client-2 can now claim S1 if needed -``` - -## Message Routing - -### Commands (Playwright → Extension) -- Commands are tagged with the originating client ID -- Responses are routed back only to the requesting client -- Session commands validate ownership before forwarding - -### Events (Extension → Playwright) -- **Session-specific events**: Routed only to the owning client -- **Target.attachedToTarget**: Broadcast to all clients (until claimed) -- **Target.detachedFromTarget**: Sent only to the owning client -- **Global events**: Broadcast to all connected clients - -## Architecture Benefits - -### Isolation -- Each client operates independently without interference -- Prevents accidental cross-contamination of test scenarios -- Clear ownership model prevents command conflicts - -### Scalability -- Multiple test suites can run in parallel against different tabs -- Load can be distributed across multiple automation clients -- No artificial limitation on number of concurrent clients - -### Flexibility -- Clients can dynamically connect and disconnect -- Sessions can be transferred between clients (after disconnect) -- Each client can manage multiple tabs/sessions - -## Implementation Details - -The server maintains: -- `Map` - All connected Playwright clients -- `Map` - All browser sessions with ownership info -- Each `PlaywrightClient` tracks its owned sessions via `Set` - -When a command arrives with a `sessionId`, the server: -1. Checks if the session exists -2. Verifies the requesting client owns it (or claims it if unclaimed) -3. Forwards the command to the extension -4. Routes the response back to only that client - -## Use Cases - -### Parallel Test Execution -Multiple test runners can each control their own set of browser tabs without interference. - -### Monitoring & Automation Split -One client handles user automation while another monitors performance metrics on different tabs. - -### Multi-User Debugging -Multiple developers can connect their own Playwright instances to debug different parts of an application simultaneously. - -## Limitations - -- Each tab can only be controlled by one client at a time -- Session ownership is "sticky" - once claimed, it remains until client disconnect -- No built-in session sharing or handoff mechanism (by design, for safety) diff --git a/plan.md b/plan.md deleted file mode 100644 index bb6e781..0000000 --- a/plan.md +++ /dev/null @@ -1,32 +0,0 @@ - -currently the extension and server code assume there is only one tab attached to debugger only. i want instead to be able to manage multiple tabs. we should update all classes fields that manage tab state to a array {tabId, dsessionId, targetId}[], then we should send relevant commands to the right chrome.debugger debugee tab, finding the right tab for a specific CDP command (based on sessionId or targetId) - ---- - -now see where attachToTab is sent and received. see that we basically attach to the tab as soon as the playwright instance connects. I want to change this: instead attach to the tab when we click on the extension icon, meaning inside onClicked in background.ts. when this happens we should also send also a cdp message from the extension for Target.attachedToTarget after we are connected. so playwright knows of this new page and will list it in browser.pages() - -now see where we already are sending Target.attachedToTarget. this is now sent after setAutoAttach, meaning as soon as playwright connects. let's change this. we should not do anything during setAutoAttach, leave it empty for now. - -at the end the extension should basically: -- let the server know of new pages only when the user clicks one -- support multiple tabs, the extension icon should not be gray if a tab is in the array of tabs. this icon state should be switched also during onActivate so that we know when user changes current tab -- we should remove the code that currently closes the previous tab debugger session. this was there because it assumed there can only be one session at a time -- simplify overall code. for example removing methods that are only used once and inlining them in the parent method. -- remove a tab from the array when playwright sends command Target.closeTarget, based on passed targetId - - -notice that we can know what a command and response is for which target based on sessionId or targetId in the payloads. we can know which messages have these thanks to the d -devtools-protocol package types - - -at the end typecheck. try not to use as any or other as. - -remember: each tab will have different sessionId and targetId. based on these we can associate each CDP command to a specific tab. - - - -playwright usually will basically discover pages thanks to our messages Target.attachedToTarget. those messages will let playwright know what is the sessionId for each target. - -playwright will use Target.createTarget to create a new page. we will return a targetId and right after trigger a Target.attachedToTarget to let playwright know also the session to use. - -remember that we must use same id field for CDP responses. to associate a response to a CDP command, using the same id. this let us send interpolated and concurrent messages