# NomoE2E

> 通过统一 API 控制桌面应用内的 WebView，支持 CDP 和 WebDriver 双协议

[![Python 3.13+](https://img.shields.io/badge/Python-3.13+-blue.svg)](https://www.python.org/)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-green.svg)](LICENSE)
[![Version: v0.9.1](https://img.shields.io/badge/Version-v0.9.1-blue.svg)](pyproject.toml)

## 🎯 项目目标

为 AI Agent 提供一套可落地、可扩展、跨平台一致的桌面 WebView 自动化能力。

- 🔗 **双协议支持**：CDP 和 WebDriver 自动切换
- 🖱️ **统一 API**：`click`、`type_text`、`screenshot`、`execute_script` 等
- ✅ **开箱即用**：基于 Playwright，无需关心协议差异
- 📸 **可观测性**：错误采集、诊断快照、截图
- 🚀 **全局安装**：像 npm 一样，一行命令即可安装使用

## 📦 支持的场景

| 环境 | 协议 | 说明 |
|------|------|------|
| Electron | CDP | 使用 `--remote-debugging-port` |
| Windows WebView2 | CDP | 启用远程调试 |
| Tauri (tauri-plugin-webdriver) | WebDriver | 标准 WebDriver 端点 |

## 🚀 快速开始

### 安装（推荐方式）

```bash
# 使用 uv 全局安装（类似 npm i -g）
uv tool install -e .

# 安装后即可在任何目录直接使用
nomo-e2e --help
```

### 或使用 pip

```bash
# 从源码安装
pip install -e .

# 或从 PyPI 安装（发布后）
pip install nomo-e2e
```

### 安装 Playwright 浏览器驱动

```bash
# 必须安装浏览器驱动才能使用
playwright install chromium
```

### CLI 快速开始

```bash
# CDP 模式 (Electron/WebView2) - 自动检测 CDP 端点
nomo-e2e open http://localhost:9222
nomo-e2e snapshot
nomo-e2e click "#login"
nomo-e2e fill "#username" "admin"
nomo-e2e screenshot --filename result.png

# WebDriver 模式 (Tauri2) - 需要指定驱动
nomo-e2e open --driver webdriver http://localhost:4445
nomo-e2e click "button.submit"
nomo-e2e eval "document.title"

# 查看所有命令
nomo-e2e --help
```

完整的 CLI 命令列表请参考 [技能包](src/nomo_e2e_skills/)。

### Python API

```python
from nomo_e2e import WebViewController

# CDP 模式 (Electron/WebView2) - 自动检测
controller = WebViewController.connect("http://localhost:9222")

# 或指定驱动
controller = WebViewController.connect(
    "http://localhost:9222",
    driver="cdp"
)

# WebDriver 模式 (Tauri)
controller = WebViewController.connect(
    "http://127.0.0.1:4445",
    driver="webdriver"
)

# 执行操作
controller.click("#submit-btn")
controller.type_text("#username", "admin")
controller.screenshot("/tmp/page.png")

# 获取页面信息
print(controller.title)
print(controller.url)

# 诊断快照
snapshot = controller.diagnostics_snapshot()

# 断开连接
controller.disconnect()
```

### 使用上下文管理器

```python
from nomo_e2e import WebViewController

# 自动管理连接生命周期
with WebViewController.connect("http://localhost:9222") as controller:
    controller.click("#login")
    controller.type_text("#username", "admin")
    controller.screenshot("./login.png")
# 自动断开连接
```

## 🔧 环境配置

### Electron 启用 CDP

Electron 应用只需在启动时添加 `--remote-debugging-port` 参数即可启用 CDP 调试端口。

**启动命令：**

```bash
# macOS/Linux
npx electron . --remote-debugging-port=9222

# Windows
.\node_modules\.bin\electron . --remote-debugging-port=9222
```

**在 package.json 中配置：**

```json
{
  "scripts": {
    "start:dev": "electron . --remote-debugging-port=9222"
  }
}
```

**验证 CDP 端口：**

```bash
# 检查端口是否开启
lsof -i :9222

# 或访问调试端点
curl http://localhost:9222/json
```

**E2E 测试连接：**

```bash
# 自动检测 CDP
nomo-e2e open http://localhost:9222

# 或显式指定
nomo-e2e open --driver cdp http://localhost:9222
```

---

### Tauri2 启用 WebDriver

Tauri2 需要安装 `tauri-plugin-webdriver` 插件并启用 WebDriver 端点。

#### 1. 安装插件

```bash
# 添加插件（交互式）
cd your-tauri-app
cargo tauri add webdriver

# 或手动添加依赖到 Cargo.toml
[dependencies]
tauri-plugin-webdriver = "2"
```

#### 2. 配置插件

**src-tauri/src/lib.rs:**

```rust
use tauri_plugin_webdriver::init;

fn run() {
    tauri::Builder::default()
        .plugin(init())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
```

#### 3. 配置权限

**src-tauri/capabilities/main.json:**

```json
{
  "permissions": [
    "core:default",
    "webdriver:default"
  ]
}
```

#### 4. 启动开发服务器

Tauri2 dev 模式会自动启用 WebDriver 端点：

```bash
# 启动开发服务器（默认端口 4445）
cd your-tauri-app
cargo tauri dev

# 或指定端口
WEBDRIVER_PORT=4445 cargo tauri dev
```

**注意：** WebDriver 端口只在 debug/dev 构建下启用，release 构建不会暴露。

#### 5. 验证 WebDriver 端点

```bash
# 检查端点是否就绪
curl http://127.0.0.1:4445/status

# 预期响应
# {"value":{"ready":true,"message":"Ready."}}
```

#### 6. E2E 测试连接

```bash
nomo-e2e open --driver webdriver http://localhost:4445
```

---

### 快速对照表

| 应用 | 协议 | 启动参数 | 端点 URL | 自动检测 |
|------|------|----------|----------|----------|
| Electron | CDP | `--remote-debugging-port=9222` | `http://localhost:9222` | ✅ |
| Tauri2 | WebDriver | `cargo tauri dev` (自动) | `http://127.0.0.1:4445` | ❌ |
| WebView2 | CDP | `--remote-debugging-port=9222` | `http://localhost:9222` | ✅ |

## 📁 项目结构

```
nomo-e2e/
├── src/
│   └── nomo_e2e/
│       ├── __init__.py          # 公共导出
│       ├── controller.py        # 统一控制器
│       ├── adapters/            # 协议适配器
│       │   ├── base.py         # 抽象基类
│       │   ├── cdp.py          # CDP 适配器
│       │   └── webdriver.py    # WebDriver 适配器
│       ├── cli/                 # CLI 命令
│       ├── exceptions.py        # 异常定义
│       ├── models.py            # 数据模型
│       └── skills/              # 技能包
│           └── nomo_e2e_skills/
│               ├── SKILL.md     # 主技能包
│               └── references/   # 参考文档
├── tests/                      # 测试
├── INSTALL.md                  # 安装指南
├── ROADMAP.md                 # 开发路线图
└── AGENTS.md                  # AI 开发规范
```

## 📖 文档

| 文档 | 说明 |
|------|------|
| [INSTALL.md](INSTALL.md) | 详细的安装和使用指南 |
| [src/nomo_e2e_skills/](src/nomo_e2e_skills/) | 技能包（LLM Agent 使用） |
| [ROADMAP.md](ROADMAP.md) | 开发路线图与阶段目标 |
| [AGENTS.md](AGENTS.md) | AI 开发规范 |

## 🔧 开发

```bash
# 安装开发依赖
uv sync

# 代码检查
uv run ruff check src/ tests/

# 代码格式化
uv run ruff format src/ tests/

# 运行测试
uv run pytest tests/ -v

# 类型检查
uv run mypy src/
```

## ⚠️ 注意事项

- WebDriver 端口只允许在 debug/dev 构建下启用
- Electron 的 `--remote-debugging-port` 可在任何构建下使用
- CDP 端点（如 localhost:9222）会被自动检测为 CDP 协议
- WebDriver 端点需要使用 `--driver webdriver` 参数
- 请确保使用前已获得应用的使用授权
- 部分应用可能有反调试机制

## 📝 许可证

Apache License 2.0 - see [LICENSE](LICENSE) for details.

Copyright (c) 2026 NomoAiT
