Merge pull request #1819 from jonasherr/feat/add-playwright-cli-provider
feat(browser-automation): add playwright-cli as browser automation provider
This commit is contained in:
@@ -553,6 +553,18 @@ describe("BrowserAutomationProviderSchema", () => {
|
|||||||
// then
|
// then
|
||||||
expect(result.success).toBe(false)
|
expect(result.success).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("accepts 'playwright-cli' as valid provider", () => {
|
||||||
|
// given
|
||||||
|
const input = "playwright-cli"
|
||||||
|
|
||||||
|
// when
|
||||||
|
const result = BrowserAutomationProviderSchema.safeParse(input)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
expect(result.data).toBe("playwright-cli")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("BrowserAutomationConfigSchema", () => {
|
describe("BrowserAutomationConfigSchema", () => {
|
||||||
@@ -577,6 +589,17 @@ describe("BrowserAutomationConfigSchema", () => {
|
|||||||
// then
|
// then
|
||||||
expect(result.provider).toBe("agent-browser")
|
expect(result.provider).toBe("agent-browser")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("accepts playwright-cli provider in config", () => {
|
||||||
|
// given
|
||||||
|
const input = { provider: "playwright-cli" }
|
||||||
|
|
||||||
|
// when
|
||||||
|
const result = BrowserAutomationConfigSchema.parse(input)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(result.provider).toBe("playwright-cli")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("OhMyOpenCodeConfigSchema - browser_automation_engine", () => {
|
describe("OhMyOpenCodeConfigSchema - browser_automation_engine", () => {
|
||||||
@@ -607,6 +630,18 @@ describe("OhMyOpenCodeConfigSchema - browser_automation_engine", () => {
|
|||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
expect(result.data?.browser_automation_engine).toBeUndefined()
|
expect(result.data?.browser_automation_engine).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("accepts browser_automation_engine with playwright-cli", () => {
|
||||||
|
// given
|
||||||
|
const input = { browser_automation_engine: { provider: "playwright-cli" } }
|
||||||
|
|
||||||
|
// when
|
||||||
|
const result = OhMyOpenCodeConfigSchema.safeParse(input)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
expect(result.data?.browser_automation_engine?.provider).toBe("playwright-cli")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("ExperimentalConfigSchema feature flags", () => {
|
describe("ExperimentalConfigSchema feature flags", () => {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export const BrowserAutomationProviderSchema = z.enum([
|
|||||||
"playwright",
|
"playwright",
|
||||||
"agent-browser",
|
"agent-browser",
|
||||||
"dev-browser",
|
"dev-browser",
|
||||||
|
"playwright-cli",
|
||||||
])
|
])
|
||||||
|
|
||||||
export const BrowserAutomationConfigSchema = z.object({
|
export const BrowserAutomationConfigSchema = z.object({
|
||||||
@@ -12,6 +13,7 @@ export const BrowserAutomationConfigSchema = z.object({
|
|||||||
* - "playwright": Uses Playwright MCP server (@playwright/mcp) - default
|
* - "playwright": Uses Playwright MCP server (@playwright/mcp) - default
|
||||||
* - "agent-browser": Uses Vercel's agent-browser CLI (requires: bun add -g agent-browser)
|
* - "agent-browser": Uses Vercel's agent-browser CLI (requires: bun add -g agent-browser)
|
||||||
* - "dev-browser": Uses dev-browser skill with persistent browser state
|
* - "dev-browser": Uses dev-browser skill with persistent browser state
|
||||||
|
* - "playwright-cli": Uses Playwright CLI (@playwright/cli) - token-efficient CLI alternative
|
||||||
*/
|
*/
|
||||||
provider: BrowserAutomationProviderSchema.default("playwright"),
|
provider: BrowserAutomationProviderSchema.default("playwright"),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -140,4 +140,35 @@ describe("createBuiltinSkills", () => {
|
|||||||
// #then
|
// #then
|
||||||
expect(skills.length).toBe(4)
|
expect(skills.length).toBe(4)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("returns playwright-cli skill when browserProvider is 'playwright-cli'", () => {
|
||||||
|
// given
|
||||||
|
const options = { browserProvider: "playwright-cli" as const }
|
||||||
|
|
||||||
|
// when
|
||||||
|
const skills = createBuiltinSkills(options)
|
||||||
|
|
||||||
|
// then
|
||||||
|
const playwrightSkill = skills.find((s) => s.name === "playwright")
|
||||||
|
const agentBrowserSkill = skills.find((s) => s.name === "agent-browser")
|
||||||
|
expect(playwrightSkill).toBeDefined()
|
||||||
|
expect(playwrightSkill!.description).toContain("browser")
|
||||||
|
expect(playwrightSkill!.allowedTools).toContain("Bash(playwright-cli:*)")
|
||||||
|
expect(playwrightSkill!.mcpConfig).toBeUndefined()
|
||||||
|
expect(agentBrowserSkill).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("playwright-cli skill template contains CLI commands", () => {
|
||||||
|
// given
|
||||||
|
const options = { browserProvider: "playwright-cli" as const }
|
||||||
|
|
||||||
|
// when
|
||||||
|
const skills = createBuiltinSkills(options)
|
||||||
|
const skill = skills.find((s) => s.name === "playwright")
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(skill!.template).toContain("playwright-cli open")
|
||||||
|
expect(skill!.template).toContain("playwright-cli snapshot")
|
||||||
|
expect(skill!.template).toContain("playwright-cli click")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { BrowserAutomationProvider } from "../../config/schema"
|
|||||||
import {
|
import {
|
||||||
playwrightSkill,
|
playwrightSkill,
|
||||||
agentBrowserSkill,
|
agentBrowserSkill,
|
||||||
|
playwrightCliSkill,
|
||||||
frontendUiUxSkill,
|
frontendUiUxSkill,
|
||||||
gitMasterSkill,
|
gitMasterSkill,
|
||||||
devBrowserSkill,
|
devBrowserSkill,
|
||||||
@@ -17,7 +18,14 @@ export interface CreateBuiltinSkillsOptions {
|
|||||||
export function createBuiltinSkills(options: CreateBuiltinSkillsOptions = {}): BuiltinSkill[] {
|
export function createBuiltinSkills(options: CreateBuiltinSkillsOptions = {}): BuiltinSkill[] {
|
||||||
const { browserProvider = "playwright", disabledSkills } = options
|
const { browserProvider = "playwright", disabledSkills } = options
|
||||||
|
|
||||||
const browserSkill = browserProvider === "agent-browser" ? agentBrowserSkill : playwrightSkill
|
let browserSkill: BuiltinSkill
|
||||||
|
if (browserProvider === "agent-browser") {
|
||||||
|
browserSkill = agentBrowserSkill
|
||||||
|
} else if (browserProvider === "playwright-cli") {
|
||||||
|
browserSkill = playwrightCliSkill
|
||||||
|
} else {
|
||||||
|
browserSkill = playwrightSkill
|
||||||
|
}
|
||||||
|
|
||||||
const skills = [browserSkill, frontendUiUxSkill, gitMasterSkill, devBrowserSkill]
|
const skills = [browserSkill, frontendUiUxSkill, gitMasterSkill, devBrowserSkill]
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export { playwrightSkill, agentBrowserSkill } from "./playwright"
|
export { playwrightSkill, agentBrowserSkill } from "./playwright"
|
||||||
|
export { playwrightCliSkill } from "./playwright-cli"
|
||||||
export { frontendUiUxSkill } from "./frontend-ui-ux"
|
export { frontendUiUxSkill } from "./frontend-ui-ux"
|
||||||
export { gitMasterSkill } from "./git-master"
|
export { gitMasterSkill } from "./git-master"
|
||||||
export { devBrowserSkill } from "./dev-browser"
|
export { devBrowserSkill } from "./dev-browser"
|
||||||
|
|||||||
268
src/features/builtin-skills/skills/playwright-cli.ts
Normal file
268
src/features/builtin-skills/skills/playwright-cli.ts
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
import type { BuiltinSkill } from "../types"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Playwright CLI skill — token-efficient CLI alternative to the MCP-based playwright skill.
|
||||||
|
*
|
||||||
|
* Uses name "playwright" (not "playwright-cli") because agents hardcode "playwright" as the
|
||||||
|
* canonical browser skill name. The browserProvider config swaps the implementation behind
|
||||||
|
* the same name: "playwright" gives MCP, "playwright-cli" gives this CLI variant.
|
||||||
|
* The binary is still called `playwright-cli` (see allowedTools).
|
||||||
|
*/
|
||||||
|
export const playwrightCliSkill: BuiltinSkill = {
|
||||||
|
name: "playwright",
|
||||||
|
description: "MUST USE for any browser-related tasks. Browser automation via playwright-cli - verification, browsing, information gathering, web scraping, testing, screenshots, and all browser interactions.",
|
||||||
|
template: `# Browser Automation with playwright-cli
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
# open new browser
|
||||||
|
playwright-cli open
|
||||||
|
# navigate to a page
|
||||||
|
playwright-cli goto https://playwright.dev
|
||||||
|
# interact with the page using refs from the snapshot
|
||||||
|
playwright-cli click e15
|
||||||
|
playwright-cli type "page.click"
|
||||||
|
playwright-cli press Enter
|
||||||
|
# take a screenshot
|
||||||
|
playwright-cli screenshot
|
||||||
|
# close the browser
|
||||||
|
playwright-cli close
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
### Core
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli open
|
||||||
|
# open and navigate right away
|
||||||
|
playwright-cli open https://example.com/
|
||||||
|
playwright-cli goto https://playwright.dev
|
||||||
|
playwright-cli type "search query"
|
||||||
|
playwright-cli click e3
|
||||||
|
playwright-cli dblclick e7
|
||||||
|
playwright-cli fill e5 "user@example.com"
|
||||||
|
playwright-cli drag e2 e8
|
||||||
|
playwright-cli hover e4
|
||||||
|
playwright-cli select e9 "option-value"
|
||||||
|
playwright-cli upload ./document.pdf
|
||||||
|
playwright-cli check e12
|
||||||
|
playwright-cli uncheck e12
|
||||||
|
playwright-cli snapshot
|
||||||
|
playwright-cli snapshot --filename=after-click.yaml
|
||||||
|
playwright-cli eval "document.title"
|
||||||
|
playwright-cli eval "el => el.textContent" e5
|
||||||
|
playwright-cli dialog-accept
|
||||||
|
playwright-cli dialog-accept "confirmation text"
|
||||||
|
playwright-cli dialog-dismiss
|
||||||
|
playwright-cli resize 1920 1080
|
||||||
|
playwright-cli close
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Navigation
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli go-back
|
||||||
|
playwright-cli go-forward
|
||||||
|
playwright-cli reload
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Keyboard
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli press Enter
|
||||||
|
playwright-cli press ArrowDown
|
||||||
|
playwright-cli keydown Shift
|
||||||
|
playwright-cli keyup Shift
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Mouse
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli mousemove 150 300
|
||||||
|
playwright-cli mousedown
|
||||||
|
playwright-cli mousedown right
|
||||||
|
playwright-cli mouseup
|
||||||
|
playwright-cli mouseup right
|
||||||
|
playwright-cli mousewheel 0 100
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Save as
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli screenshot
|
||||||
|
playwright-cli screenshot e5
|
||||||
|
playwright-cli screenshot --filename=page.png
|
||||||
|
playwright-cli pdf --filename=page.pdf
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Tabs
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli tab-list
|
||||||
|
playwright-cli tab-new
|
||||||
|
playwright-cli tab-new https://example.com/page
|
||||||
|
playwright-cli tab-close
|
||||||
|
playwright-cli tab-close 2
|
||||||
|
playwright-cli tab-select 0
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Storage
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli state-save
|
||||||
|
playwright-cli state-save auth.json
|
||||||
|
playwright-cli state-load auth.json
|
||||||
|
|
||||||
|
# Cookies
|
||||||
|
playwright-cli cookie-list
|
||||||
|
playwright-cli cookie-list --domain=example.com
|
||||||
|
playwright-cli cookie-get session_id
|
||||||
|
playwright-cli cookie-set session_id abc123
|
||||||
|
playwright-cli cookie-set session_id abc123 --domain=example.com --httpOnly --secure
|
||||||
|
playwright-cli cookie-delete session_id
|
||||||
|
playwright-cli cookie-clear
|
||||||
|
|
||||||
|
# LocalStorage
|
||||||
|
playwright-cli localstorage-list
|
||||||
|
playwright-cli localstorage-get theme
|
||||||
|
playwright-cli localstorage-set theme dark
|
||||||
|
playwright-cli localstorage-delete theme
|
||||||
|
playwright-cli localstorage-clear
|
||||||
|
|
||||||
|
# SessionStorage
|
||||||
|
playwright-cli sessionstorage-list
|
||||||
|
playwright-cli sessionstorage-get step
|
||||||
|
playwright-cli sessionstorage-set step 3
|
||||||
|
playwright-cli sessionstorage-delete step
|
||||||
|
playwright-cli sessionstorage-clear
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Network
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli route "**/*.jpg" --status=404
|
||||||
|
playwright-cli route "https://api.example.com/**" --body='{"mock": true}'
|
||||||
|
playwright-cli route-list
|
||||||
|
playwright-cli unroute "**/*.jpg"
|
||||||
|
playwright-cli unroute
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### DevTools
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli console
|
||||||
|
playwright-cli console warning
|
||||||
|
playwright-cli network
|
||||||
|
playwright-cli run-code "async page => await page.context().grantPermissions(['geolocation'])"
|
||||||
|
playwright-cli tracing-start
|
||||||
|
playwright-cli tracing-stop
|
||||||
|
playwright-cli video-start
|
||||||
|
playwright-cli video-stop video.webm
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli install --skills
|
||||||
|
playwright-cli install-browser
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
\`\`\`bash
|
||||||
|
# Use specific browser when creating session
|
||||||
|
playwright-cli open --browser=chrome
|
||||||
|
playwright-cli open --browser=firefox
|
||||||
|
playwright-cli open --browser=webkit
|
||||||
|
playwright-cli open --browser=msedge
|
||||||
|
# Connect to browser via extension
|
||||||
|
playwright-cli open --extension
|
||||||
|
|
||||||
|
# Use persistent profile (by default profile is in-memory)
|
||||||
|
playwright-cli open --persistent
|
||||||
|
# Use persistent profile with custom directory
|
||||||
|
playwright-cli open --profile=/path/to/profile
|
||||||
|
|
||||||
|
# Start with config file
|
||||||
|
playwright-cli open --config=my-config.json
|
||||||
|
|
||||||
|
# Close the browser
|
||||||
|
playwright-cli close
|
||||||
|
# Delete user data for the default session
|
||||||
|
playwright-cli delete-data
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Browser Sessions
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
# create new browser session named "mysession" with persistent profile
|
||||||
|
playwright-cli -s=mysession open example.com --persistent
|
||||||
|
# same with manually specified profile directory (use when requested explicitly)
|
||||||
|
playwright-cli -s=mysession open example.com --profile=/path/to/profile
|
||||||
|
playwright-cli -s=mysession click e6
|
||||||
|
playwright-cli -s=mysession close # stop a named browser
|
||||||
|
playwright-cli -s=mysession delete-data # delete user data for persistent session
|
||||||
|
|
||||||
|
playwright-cli list
|
||||||
|
# Close all browsers
|
||||||
|
playwright-cli close-all
|
||||||
|
# Forcefully kill all browser processes
|
||||||
|
playwright-cli kill-all
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Example: Form submission
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli open https://example.com/form
|
||||||
|
playwright-cli snapshot
|
||||||
|
|
||||||
|
playwright-cli fill e1 "user@example.com"
|
||||||
|
playwright-cli fill e2 "password123"
|
||||||
|
playwright-cli click e3
|
||||||
|
playwright-cli snapshot
|
||||||
|
playwright-cli close
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Example: Multi-tab workflow
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli open https://example.com
|
||||||
|
playwright-cli tab-new https://example.com/other
|
||||||
|
playwright-cli tab-list
|
||||||
|
playwright-cli tab-select 0
|
||||||
|
playwright-cli snapshot
|
||||||
|
playwright-cli close
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Example: Debugging with DevTools
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli open https://example.com
|
||||||
|
playwright-cli click e4
|
||||||
|
playwright-cli fill e7 "test"
|
||||||
|
playwright-cli console
|
||||||
|
playwright-cli network
|
||||||
|
playwright-cli close
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
playwright-cli open https://example.com
|
||||||
|
playwright-cli tracing-start
|
||||||
|
playwright-cli click e4
|
||||||
|
playwright-cli fill e7 "test"
|
||||||
|
playwright-cli tracing-stop
|
||||||
|
playwright-cli close
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Specific tasks
|
||||||
|
|
||||||
|
* **Request mocking** [references/request-mocking.md](references/request-mocking.md)
|
||||||
|
* **Running Playwright code** [references/running-code.md](references/running-code.md)
|
||||||
|
* **Browser session management** [references/session-management.md](references/session-management.md)
|
||||||
|
* **Storage state (cookies, localStorage)** [references/storage-state.md](references/storage-state.md)
|
||||||
|
* **Test generation** [references/test-generation.md](references/test-generation.md)
|
||||||
|
* **Tracing** [references/tracing.md](references/tracing.md)
|
||||||
|
* **Video recording** [references/video-recording.md](references/video-recording.md)`,
|
||||||
|
allowedTools: ["Bash(playwright-cli:*)"],
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user