mcpField
S
screen-control-operator

screen-control-operator

github.com/breverdbidderAgent 工作流57 次安装
代码仓库

关于 screen-control-operator

screen-control-operator 是供 Claude 自主操作和检查浏览器的技能,使用 Playwright、CDP 命令与无障碍树读取页面状态,而非截图。它包含页面交互、验证及控制台和网络监控流程,也提供针对 Lovable 预览和 BECA 表单的预设工作流。

主要功能

  1. 01通过 CDP 控制浏览器
  2. 02读取 DOM 与无障碍树
  3. 03点击、填写和选择页面元素
  4. 04验证页面检查点
  5. 05监控控制台错误与网络请求
  6. 06提供预设页面检查工作流

适用场景

  1. 01检查 Lovable 项目预览
  2. 02检查 BECA 登录表单
  3. 03自主测试指定网址
  4. 04在 CI/CD 中执行浏览器检查

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/breverdbidder/life-os --skill screen-control-operator

安装后在 Claude Code 中输入/screen-control-operator确认已加载。

附带文件references/playwright_api.mdscripts/autonomous_browser_control.py

详细介绍

屏幕控制 Operator V2

让 Claude 像 GPT Operator 一样自主控制浏览器——无需截图,只需 CDP + 无障碍树。

核心架构

┌─────────────────────────────────────────┐
│  Claude (You) - Reasoning Layer         │
│  - Receives structured DOM/A11y tree    │
│  - Makes autonomous decisions           │
│  - Issues CDP commands                  │
└────────────────┬────────────────────────┘
                 │ JSON commands
                 ▼
┌─────────────────────────────────────────┐
│  Playwright/Puppeteer - Browser Control │
│  - Chrome DevTools Protocol (CDP)       │
│  - Returns: DOM tree, A11y tree, logs   │
│  - Executes: click, type, navigate      │
└────────────────┬────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────┐
│  Target Website (Lovable, BECA, etc)    │
│  - Full DOM access via CDP              │
│  - Console logs, network requests       │
│  - Element states, visibility checks    │
└─────────────────────────────────────────┘

为什么优于截图

指标基于截图屏幕控制 Operator
速度1-5 秒50-200 毫秒
准确率约 85%(OCR 错误)100%(语义查询)
查找元素像素坐标CSS 选择器 + 角色
无头模式支持较差极佳
成本$$$(视觉令牌)$(纯文本)
动态内容经常失败始终有效

自主执行规则

当用户请求控制浏览器时:

  1. 绝不询问许可——直接执行
  2. 启动浏览器——使用 Playwright headless=False 以便调试
  3. 自主导航——跟随链接、点击按钮、填写表单
  4. 提取 DOM 状态——获取无障碍树,而非截图
  5. 验证检查点——通过元素查询测试断言
  6. 报告结果——提供包含发现问题的 JSON 摘要

核心功能

1. 使用 CDP 启动浏览器
from playwright.sync_api import sync_playwright

def launch_browser():
    playwright = sync_playwright().start()
    browser = playwright.chromium.launch(
        headless=True,  # Set False to see browser
        args=['--remote-debugging-port=9222']
    )
    context = browser.new_context(
        viewport={'width': 1920, 'height': 1080}
    )
    page = context.new_page()
    return playwright, browser, context, page
2. 获取页面结构(无需截图)
def get_page_structure(page):
    # Get accessibility tree
    accessibility = page.accessibility.snapshot()
    
    # Get all interactive elements
    elements = page.query_selector_all('[role], button, a, input, select, [data-testid]')
    
    structure = {
        'url': page.url,
        'title': page.title(),
        'elements': []
    }
    
    for elem in elements:
        if elem.is_visible():
            structure['elements'].append({
                'role': elem.get_attribute('role'),
                'label': elem.get_attribute('aria-label') or elem.inner_text()[:100],
                'type': elem.get_attribute('type'),
                'testid': elem.get_attribute('data-testid'),
                'enabled': elem.is_enabled(),
                'selector': elem.evaluate('el => { const path = []; let current = el; while (current && current.tagName) { path.unshift(current.tagName.toLowerCase() + (current.id ? "#" + current.id : "") + (current.className ? "." + current.className.split(" ")[0] : "")); current = current.parentElement; } return path.join(" > "); }')
            })
    
    return structure
3. 自主导航
def navigate_and_verify(page, url, checkpoints):
    print(f"🌐 Navigating to {url}")
    page.goto(url, wait_until='networkidle')
    page.wait_for_timeout(2000)
    
    results = {
        'url': page.url,
        'title': page.title(),
        'checkpoints': {},
        'issues': []
    }
    
    for checkpoint_name, selector in checkpoints.items():
        try:
            elem = page.locator(selector)
            visible = elem.is_visible()
            results['checkpoints'][checkpoint_name] = {
                'found': True,
                'visible': visible,
                'text': elem.inner_text()[:100] if visible else None
            }
            if not visible:
                results['issues'].append(f"{checkpoint_name} not visible")
        except:
            results['checkpoints'][checkpoint_name] = {'found': False}
            results['issues'].append(f"{checkpoint_name} not found")
    
    return results
4. 元素交互
def interact_with_element(page, selector, action, value=None):
    elem = page.locator(selector)
    
    if action == 'click':
        elem.click()
    elif action == 'type':
        elem.fill(value)
    elif action == 'select':
        elem.select_option(value)
    elif action == 'hover':
        elem.hover()
    
    page.wait_for_timeout(500)  # Wait for effects
5. 控制台和网络监控
def monitor_console_and_network(page):
    errors = []
    requests = []
    
    page.on('console', lambda msg: 
        errors.append(msg.text) if msg.type == 'error' else None
    )
    
    page.on('request', lambda req:
        requests.append({'url': req.url, 'method': req.method})
    )
    
    return errors, requests

预构建工作流

Lovable 预览验证
def verify_lovable_preview(project_id):
    playwright, browser, context, page = launch_browser()
    
    # Navigate to Lovable
    url = f"https://lovable.dev/projects/{project_id}"
    page.goto(url, wait_until='networkidle')
    
    # Click Preview button
    preview_btn = page.get_by_role("button", name="Preview")
    if preview_btn.is_visible():
        preview_btn.click()
        page.wait_for_timeout(2000)
    
    # Get preview page
    pages = context.pages
    preview_page = pages[-1] if len(pages) > 1 else page
    
    # Verify checkpoints
    checkpoints = {
        'map_container': '[data-testid="map-container"], #map, .mapboxgl-map',
        'header': 'header, [role="banner"], nav',
        'markers': '[data-testid="marker"], .marker, .mapboxgl-marker',
        'search': '[data-testid="search"], input[type="search"]'
    }
    
    results = navigate_and_verify(preview_page, preview_page.url, checkpoints)
    
    # Test interactions
    try:
        map_elem = preview_page.locator('[data-testid="map-container"]')
        if map_elem.is_visible():
            # Zoom in
            preview_page.keyboard.press('+')
            page.wait_for_timeout(500)
            
            # Zoom out
            preview_page.keyboard.press('-')
            page.wait_for_timeout(500)
            
            results['interactions'] = {'zoom': 'SUCCESS'}
    except Exception as e:
        results['interactions'] = {'zoom': f'FAILED: {str(e)}'}
    
    browser.close()
    playwright.stop()
    
    return results
BECA 抓取器 DOM 检查
def inspect_beca_login_form():
    playwright, browser, context, page = launch_browser()
    
    page.goto('https://beca.v3.target-url.com', wait_until='networkidle')
    page.wait_for_timeout(3000)
    
    # Get all form elements
    forms = page.query_selector_all('form')
    inputs = page.query_selector_all('input')
    buttons = page.query_selector_all('button, input[type="submit"]')
    
    results = {
        'url': page.url,
        'forms': [],
        'inputs': [],
        'buttons': []
    }
    
    for form in forms:
        results['forms'].append({
            'id': form.get_attribute('id'),
            'class': form.get_attribute('class'),
            'action': form.get_attribute('action'),
            'method': form.get_attribute('method')
        })
    
    for inp in inputs:
        if inp.is_visible():
            results['inputs'].append({
                'name': inp.get_attribute('name'),
                'id': inp.get_attribute('id'),
                'type': inp.get_attribute('type'),
                'placeholder': inp.get_attribute('placeholder'),
                'required': inp.get_attribute('required'),
                'selector': f"input[name='{inp.get_attribute('name')}']" if inp.get_attribute('name') else f"input[id='{inp.get_attribute('id')}']"
            })
    
    for btn in buttons:
        if btn.is_visible():
            results['buttons'].append({
                'text': btn.inner_text(),
                'type': btn.get_attribute('type'),
                'id': btn.get_attribute('id'),
                'class': btn.get_attribute('class'),
                'selector': f"button:has-text('{btn.inner_text()}')" if btn.tag_name == 'button' else f"input[type='{btn.get_attribute('type')}']"
            })
    
    browser.close()
    playwright.stop()
    
    return results

部署

安装依赖项
pip install playwright --break-system-packages
playwright install chromium
GitHub Actions 工作流

创建 .github/workflows/screen_control_operator.yml:

name: Screen Control Operator

on:
  workflow_dispatch:
    inputs:
      task:
        description: 'Task to execute'
        required: true
        type: choice
        options:
          - verify_lovable
          - inspect_beca
          - test_scrapers
      target_url:
        description: 'Target URL (optional)'
        required: false

jobs:
  execute:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      
      - name: Install Playwright
        run: |
          pip install playwright
          playwright install chromium
      
      - name: Execute Screen Control Task
        run: |
          python scripts/screen_control_operator.py             --task ${{ github.event.inputs.task }}             --url "${{ github.event.inputs.target_url }}"
      
      - name: Upload Results
        uses: actions/upload-artifact@v4
        with:
          name: screen-control-results
          path: results.json

使用示例

在 Claude Chat 中使用
"Use screen-control-operator to verify Lovable preview"

"Inspect BECA login form with screen-control-operator"

"Test brevard-bidder-landing.pages.dev autonomously"
在命令行中使用
# Verify Lovable
python scripts/screen_control_operator.py verify-lovable fe59383e-3396-49f3-9cb9-5fea97dce977

# Inspect BECA
python scripts/screen_control_operator.py inspect-beca

# Test any URL
python scripts/screen_control_operator.py test-url https://brevard-bidder-landing.pages.dev
以编程方式使用
from scripts.screen_control_operator import verify_lovable_preview, inspect_beca_login_form

# Verify Lovable
results = verify_lovable_preview('fe59383e-3396-49f3-9cb9-5fea97dce977')
print(json.dumps(results, indent=2))

# Inspect BECA
beca_dom = inspect_beca_login_form()
print(f"Found {len(beca_dom['inputs'])} inputs, {len(beca_dom['buttons'])} buttons")

主要优势

  1. 无需截图——速度快 10 倍,可在无头 CI/CD 中运行
  2. 100% 可靠——语义查询不会因元素位置而失败
  3. 完整 DOM 访问——控制台日志、网络请求、元素状态
  4. 自主运行——无需人工介入,就像 GPT Operator 一样
  5. 支持 GitHub Actions——部署到云端,按计划运行

参考资料

有关实现细节:

  • scripts/screen_control_operator.py - 自主控制主脚本
  • scripts/verify_lovable.py - Lovable 预览验证
  • scripts/inspect_beca.py - BECA DOM 检查
  • references/playwright_api.md - Playwright API 快速参考

评论

支持 Markdown