use dedent. use search simpler param name
This commit is contained in:
+21
-22
@@ -7,6 +7,7 @@ import path from 'node:path'
|
|||||||
import { spawn } from 'node:child_process'
|
import { spawn } from 'node:child_process'
|
||||||
import { createRequire } from 'node:module'
|
import { createRequire } from 'node:module'
|
||||||
import vm from 'node:vm'
|
import vm from 'node:vm'
|
||||||
|
import dedent from 'string-dedent'
|
||||||
import { getCdpUrl } from './utils.js'
|
import { getCdpUrl } from './utils.js'
|
||||||
|
|
||||||
const require = createRequire(import.meta.url)
|
const require = createRequire(import.meta.url)
|
||||||
@@ -48,12 +49,12 @@ interface VMContext {
|
|||||||
}
|
}
|
||||||
accessibilitySnapshot: (options: {
|
accessibilitySnapshot: (options: {
|
||||||
page: Page
|
page: Page
|
||||||
searchString?: string | RegExp
|
search?: string | RegExp
|
||||||
contextLines?: number
|
contextLines?: number
|
||||||
}) => Promise<string>
|
}) => Promise<string>
|
||||||
getLocatorStringForElement: (element: any) => Promise<string>
|
getLocatorStringForElement: (element: any) => Promise<string>
|
||||||
resetPlaywright: () => Promise<{ page: Page; context: BrowserContext }>
|
resetPlaywright: () => Promise<{ page: Page; context: BrowserContext }>
|
||||||
getLatestLogs: (options?: { page?: Page; count?: number; searchFilter?: string | RegExp }) => Promise<string[]>
|
getLatestLogs: (options?: { page?: Page; count?: number; search?: string | RegExp }) => Promise<string[]>
|
||||||
clearAllLogs: () => void
|
clearAllLogs: () => void
|
||||||
require: NodeRequire
|
require: NodeRequire
|
||||||
import: (specifier: string) => Promise<any>
|
import: (specifier: string) => Promise<any>
|
||||||
@@ -387,15 +388,15 @@ server.tool(
|
|||||||
|
|
||||||
const accessibilitySnapshot = async (options: {
|
const accessibilitySnapshot = async (options: {
|
||||||
page: Page
|
page: Page
|
||||||
searchString?: string | RegExp
|
search?: string | RegExp
|
||||||
contextLines?: number
|
contextLines?: number
|
||||||
}) => {
|
}) => {
|
||||||
const { page: targetPage, searchString, contextLines = 10 } = options
|
const { page: targetPage, search, contextLines = 10 } = options
|
||||||
if ((targetPage as any)._snapshotForAI) {
|
if ((targetPage as any)._snapshotForAI) {
|
||||||
const snapshot = await (targetPage as any)._snapshotForAI()
|
const snapshot = await (targetPage as any)._snapshotForAI()
|
||||||
const snapshotStr = typeof snapshot === 'string' ? snapshot : JSON.stringify(snapshot, null, 2)
|
const snapshotStr = typeof snapshot === 'string' ? snapshot : JSON.stringify(snapshot, null, 2)
|
||||||
|
|
||||||
if (!searchString) {
|
if (!search) {
|
||||||
return snapshotStr
|
return snapshotStr
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,10 +406,10 @@ server.tool(
|
|||||||
for (let i = 0; i < lines.length; i++) {
|
for (let i = 0; i < lines.length; i++) {
|
||||||
const line = lines[i]
|
const line = lines[i]
|
||||||
let isMatch = false
|
let isMatch = false
|
||||||
if (isRegExp(searchString)) {
|
if (isRegExp(search)) {
|
||||||
isMatch = searchString.test(line)
|
isMatch = search.test(line)
|
||||||
} else {
|
} else {
|
||||||
isMatch = line.includes(searchString)
|
isMatch = line.includes(search)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMatch) {
|
if (isMatch) {
|
||||||
@@ -456,36 +457,32 @@ server.tool(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const getLatestLogs = async (options?: { page?: Page; count?: number; searchFilter?: string | RegExp }) => {
|
const getLatestLogs = async (options?: { page?: Page; count?: number; search?: string | RegExp }) => {
|
||||||
const { page: filterPage, count, searchFilter } = options || {}
|
const { page: filterPage, count, search } = options || {}
|
||||||
|
|
||||||
let allLogs: string[] = []
|
let allLogs: string[] = []
|
||||||
|
|
||||||
// Get logs from specific page or all pages
|
|
||||||
if (filterPage) {
|
if (filterPage) {
|
||||||
const targetId = await getPageTargetId(filterPage)
|
const targetId = await getPageTargetId(filterPage)
|
||||||
const pageLogs = browserLogs.get(targetId) || []
|
const pageLogs = browserLogs.get(targetId) || []
|
||||||
allLogs = [...pageLogs]
|
allLogs = [...pageLogs]
|
||||||
} else {
|
} else {
|
||||||
// Combine logs from all pages
|
|
||||||
for (const pageLogs of browserLogs.values()) {
|
for (const pageLogs of browserLogs.values()) {
|
||||||
allLogs.push(...pageLogs)
|
allLogs.push(...pageLogs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by search string or regex
|
if (search) {
|
||||||
if (searchFilter) {
|
|
||||||
allLogs = allLogs.filter((log) => {
|
allLogs = allLogs.filter((log) => {
|
||||||
if (typeof searchFilter === 'string') {
|
if (typeof search === 'string') {
|
||||||
return log.includes(searchFilter)
|
return log.includes(search)
|
||||||
} else if (isRegExp(searchFilter)) {
|
} else if (isRegExp(search)) {
|
||||||
return searchFilter.test(log)
|
return search.test(log)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return all logs or limited count
|
|
||||||
return count !== undefined ? allLogs.slice(-count) : allLogs
|
return count !== undefined ? allLogs.slice(-count) : allLogs
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,11 +619,13 @@ server.tool(
|
|||||||
|
|
||||||
server.tool(
|
server.tool(
|
||||||
'reset',
|
'reset',
|
||||||
`Recreates the CDP connection and resets the browser/page/context. Use this when the MCP stops responding, you get connection errors, assertion failures, page closed, or timeout issues.
|
dedent`
|
||||||
|
Recreates the CDP connection and resets the browser/page/context. Use this when the MCP stops responding, you get connection errors, assertion failures, page closed, or timeout issues.
|
||||||
|
|
||||||
After calling this tool, the page and context variables are automatically updated in the execution environment.
|
After calling this tool, the page and context variables are automatically updated in the execution environment.
|
||||||
|
|
||||||
IMPORTANT: this completely resets the execution context, removing any custom properties you may have added to the global scope AND clearing all keys from the \`state\` object. Only \`page\`, \`context\`, \`state\` (empty), \`console\`, and utility functions will remain.`,
|
IMPORTANT: this completely resets the execution context, removing any custom properties you may have added to the global scope AND clearing all keys from the \`state\` object. Only \`page\`, \`context\`, \`state\` (empty), \`console\`, and utility functions will remain.
|
||||||
|
`,
|
||||||
{},
|
{},
|
||||||
async () => {
|
async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -72,14 +72,14 @@ 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:
|
you have access to some functions in addition to playwright methods:
|
||||||
|
|
||||||
- `async accessibilitySnapshot({ page, searchString, 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 })`: 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
|
- `page`: the page object to snapshot
|
||||||
- `searchString`: (optional) a string or regex to filter the snapshot. If provided, returns the first 10 matches with surrounding context
|
- `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)
|
- `contextLines`: (optional) number of lines of context to show around each match (default: 10)
|
||||||
- `getLatestLogs({ page, count, searchFilter })`: 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.
|
- `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
|
- `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
|
- `count`: (optional) limit number of logs to return. If not specified, returns all available logs
|
||||||
- `searchFilter`: (optional) string or regex to filter logs. Only returns logs that match
|
- `search`: (optional) string or regex to filter logs. Only returns logs that match
|
||||||
|
|
||||||
To bring a tab to front and focus it, use the standard Playwright method `await page.bringToFront()`
|
To bring a tab to front and focus it, use the standard Playwright method `await page.bringToFront()`
|
||||||
|
|
||||||
@@ -119,19 +119,19 @@ console.log(await getLocatorStringForElement(loc));
|
|||||||
|
|
||||||
## finding specific elements with snapshot
|
## finding specific elements with snapshot
|
||||||
|
|
||||||
You can use `searchString` to find specific elements in the snapshot without reading the whole page structure. This is useful for finding forms, textareas, or specific text.
|
You can use `search` to find specific elements in the snapshot without reading the whole page structure. This is useful for finding forms, textareas, or specific text.
|
||||||
|
|
||||||
Example: find a textarea or form using case-insensitive regex:
|
Example: find a textarea or form using case-insensitive regex:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const snapshot = await accessibilitySnapshot({ page, searchString: /textarea|form/i })
|
const snapshot = await accessibilitySnapshot({ page, search: /textarea|form/i })
|
||||||
console.log(snapshot)
|
console.log(snapshot)
|
||||||
```
|
```
|
||||||
|
|
||||||
Example: find elements containing "Login":
|
Example: find elements containing "Login":
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const snapshot = await accessibilitySnapshot({ page, searchString: "Login" })
|
const snapshot = await accessibilitySnapshot({ page, search: "Login" })
|
||||||
console.log(snapshot)
|
console.log(snapshot)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ const allLogs = await getLatestLogs()
|
|||||||
console.log(allLogs)
|
console.log(allLogs)
|
||||||
|
|
||||||
// Get last 50 browser error logs
|
// Get last 50 browser error logs
|
||||||
const errorLogs = await getLatestLogs({ count: 50, searchFilter: /\[error\]/ })
|
const errorLogs = await getLatestLogs({ count: 50, search: /\[error\]/ })
|
||||||
console.log(errorLogs)
|
console.log(errorLogs)
|
||||||
|
|
||||||
// Get all browser logs from the current page only
|
// Get all browser logs from the current page only
|
||||||
@@ -193,7 +193,7 @@ const pageLogs = await getLatestLogs({ page })
|
|||||||
console.log(pageLogs)
|
console.log(pageLogs)
|
||||||
|
|
||||||
// Find browser logs containing specific text
|
// Find browser logs containing specific text
|
||||||
const authLogs = await getLatestLogs({ searchFilter: 'authentication failed' })
|
const authLogs = await getLatestLogs({ search: 'authentication failed' })
|
||||||
console.log(authLogs)
|
console.log(authLogs)
|
||||||
|
|
||||||
// Example output format:
|
// Example output format:
|
||||||
|
|||||||
Reference in New Issue
Block a user