removed relayConnection.ts. added diff for ai snapshot. use search param

This commit is contained in:
Tommy D. Rossi
2025-11-25 10:35:39 +01:00
parent 4e3be9b497
commit 0df52a08c0
10 changed files with 664 additions and 903 deletions
+1
View File
@@ -40,6 +40,7 @@
"@modelcontextprotocol/sdk": "^1.21.1",
"chalk": "^5.6.2",
"devtools-protocol": "^0.0.1543509",
"diff": "^8.0.2",
"hono": "^4.10.6",
"playwright-core": "^1.56.1",
"string-dedent": "^3.0.2",
+7 -7
View File
@@ -226,9 +226,9 @@ describe('MCP Server Tests', () => {
const tabs = await chrome.tabs.query({})
const testTab = tabs.find((t: any) => t.url?.includes('mcp-test'))
return {
connected: !!testTab && !!testTab.id && state.connectedTabs.has(testTab.id),
connected: !!testTab && !!testTab.id && state.tabs.has(testTab.id),
tabId: testTab?.id,
tabInfo: testTab?.id ? state.connectedTabs.get(testTab.id) : null,
tabInfo: testTab?.id ? state.tabs.get(testTab.id) : null,
connectionState: state.connectionState
}
})
@@ -581,8 +581,8 @@ describe('MCP Server Tests', () => {
const tabA = tabs.find((t: any) => t.url?.includes('tab-a'))
const tabB = tabs.find((t: any) => t.url?.includes('tab-b'))
return {
idA: state.connectedTabs.get(tabA?.id ?? -1)?.targetId,
idB: state.connectedTabs.get(tabB?.id ?? -1)?.targetId
idA: state.tabs.get(tabA?.id ?? -1)?.targetId,
idB: state.tabs.get(tabB?.id ?? -1)?.targetId
}
})
@@ -667,8 +667,8 @@ describe('MCP Server Tests', () => {
const tabA = tabs.find((t: any) => t.url?.includes('tab-a'))
const tabB = tabs.find((t: any) => t.url?.includes('tab-b'))
return {
idA: state.connectedTabs.get(tabA?.id ?? -1)?.targetId,
idB: state.connectedTabs.get(tabB?.id ?? -1)?.targetId
idA: state.tabs.get(tabA?.id ?? -1)?.targetId,
idB: state.tabs.get(tabB?.id ?? -1)?.targetId
}
})
@@ -961,7 +961,7 @@ describe('MCP Server Tests', () => {
name: 'execute',
arguments: {
code: js`
const logs = await getLatestLogs({ searchFilter: 'error' });
const logs = await getLatestLogs({ search: 'error' });
logs.forEach(log => console.log(log));
`,
},
+24 -1
View File
@@ -8,6 +8,7 @@ import { spawn } from 'node:child_process'
import { createRequire } from 'node:module'
import vm from 'node:vm'
import dedent from 'string-dedent'
import { createPatch } from 'diff'
import { getCdpUrl } from './utils.js'
const require = createRequire(import.meta.url)
@@ -51,6 +52,7 @@ interface VMContext {
page: Page
search?: string | RegExp
contextLines?: number
showDiffSinceLastCall?: boolean
}) => Promise<string>
getLocatorStringForElement: (element: any) => Promise<string>
resetPlaywright: () => Promise<{ page: Page; context: BrowserContext }>
@@ -77,6 +79,9 @@ const userState: Record<string, any> = {}
const browserLogs: Map<string, string[]> = new Map()
const MAX_LOGS_PER_PAGE = 5000
// Store last accessibility snapshot per page for diff feature
const lastSnapshots: WeakMap<Page, string> = new WeakMap()
const RELAY_PORT = 19988
const NO_TABS_ERROR = `No browser tabs are connected. Please install and enable the Playwriter extension on at least one tab: https://chromewebstore.google.com/detail/playwriter-mcp/jfeammnjpkecdekppnclgkkffahnhfhe`
@@ -390,12 +395,30 @@ server.tool(
page: Page
search?: string | RegExp
contextLines?: number
showDiffSinceLastCall?: boolean
}) => {
const { page: targetPage, search, contextLines = 10 } = options
const { page: targetPage, search, contextLines = 10, showDiffSinceLastCall = false } = options
if ((targetPage as any)._snapshotForAI) {
const snapshot = await (targetPage as any)._snapshotForAI()
const snapshotStr = typeof snapshot === 'string' ? snapshot : JSON.stringify(snapshot, null, 2)
if (showDiffSinceLastCall) {
const previousSnapshot = lastSnapshots.get(targetPage)
lastSnapshots.set(targetPage, snapshotStr)
if (!previousSnapshot) {
return 'No previous snapshot available. This is the first call for this page. Full snapshot stored for next diff.'
}
const patch = createPatch('snapshot', previousSnapshot, snapshotStr, 'previous', 'current')
if (patch.split('\n').length <= 4) {
return 'No changes detected since last snapshot'
}
return patch
}
lastSnapshots.set(targetPage, snapshotStr)
if (!search) {
return snapshotStr
}
+2 -1
View File
@@ -72,10 +72,11 @@ always detach event listener you create at the end of a message using `page.remo
you have access to some functions in addition to playwright methods:
- `async accessibilitySnapshot({ page, search, contextLines })`: gets a human readable snapshot of clickable elements on the page. useful to see the overall structure of the page and what elements you can interact with.
- `async accessibilitySnapshot({ page, search, contextLines, showDiffSinceLastCall })`: gets a human readable snapshot of clickable elements on the page. useful to see the overall structure of the page and what elements you can interact with.
- `page`: the page object to snapshot
- `search`: (optional) a string or regex to filter the snapshot. If provided, returns the first 10 matches with surrounding context
- `contextLines`: (optional) number of lines of context to show around each match (default: 10)
- `showDiffSinceLastCall`: (optional) if true, returns a unified diff patch showing only changes since the last snapshot call for this page. Disables search when enabled. Useful to see what changed after an action.
- `getLatestLogs({ page, count, search })`: retrieves browser console logs. The system automatically captures and stores up to 5000 logs per page. Logs are cleared when a page reloads or navigates.
- `page`: (optional) filter logs by a specific page instance. Only returns logs from that page
- `count`: (optional) limit number of logs to return. If not specified, returns all available logs