关于 jevnav
jevnav 是面向 Agent、测试和 CI 的浏览器自动化层。它依据结构化页面信息定位元素,对风险或不确定操作设置人工审核,并记录可离线重放的决策轨迹。
主要功能
- 01依据页面结构和样式定位元素
- 02对风险或不确定操作设置审核
- 03记录可审计的决策轨迹
- 04在 CI 中离线重放轨迹
- 05执行浏览器流程并验证结果
适用场景
- 01在 CI 中发现浏览器流程回归
- 02通过人工审核门控自动执行网页任务
- 03比较设计稿与运行中的页面
- 04编写可重放决策的 Playwright 测试
MCP 相关
其 MCP 服务向 Claude Code、Cursor 等客户端提供页面导航、目标驱动交互、页面检查及其他操作工具。会话会写入轨迹文件,MCP 注解会标明可能改变状态的调用。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
jevnav
为浏览器 Agent 提供页面真实信息,并记录可重放、可测试、可审计的决策。
https://github.com/user-attachments/assets/502550ec-77d4-439e-b334-fe7007f946b9
jevnav 是面向 Agent 和测试的浏览器层。它将页面读取为事实
(结构、计算样式、屏幕上的控件),让
Jev —— TypeSafe 用于结构化
问题的模型 —— 以校准后的概率为意图选择元素,对高风险或不确定的操作
设置关卡,并将每项决策记录到追踪记录中,供 replay 在 CI 中
离线重新检查。
- 页面真实信息,而非像素。
outline、styles和diff会返回浏览器 解析出的内容——例如,模型稿与运行中的应用之间的font-size 32px → 28px, Agent 可以据此修复问题。决策循环中不使用屏幕截图。 - 证据,而非信心。 每项决策都包含其概率、关卡判定和成本。网站变更若导致
已记录的决策失效,
replay就会以状态码 1 退出——无需调用模型,也无需 API 密钥。 - 适用于 Agent 工作的场景。 提供 CLI、Python/pytest、供 Claude Code、Cursor、Codex 等使用的 MCP 服务,以及 GitHub Action。
它为何存在——选择器测试会因标签变更而失效;LLM 浏览器 Agent 往往过度自信、
无法审计,而且偶尔会出错:docs/why.md。
安装
uv tool install jevnav # or: pip install jevnav (the MCP server is included)
playwright install chromium # one-time browser download
需要 Python 3.10 及以上版本。决策操作(go、run、browse、goal)需要
在 TYPESAFE_API_KEY 或 ~/.config/typesafe/apikey.txt 中配置 TypeSafe
API 密钥。replay、diff、outline 和 styles 无需密钥——这正是重点。
快速入门
1. 让 Jev 来操作——描述目标,以及用于证明目标达成的结果:
jevnav go --goal "sign in with the demo account and open the pricing page" \
--start https://app.example.com/login \
--context [email protected] --context password="${ACME_PASSWORD}" \
--success "#pricing.visible" \
--report goal.md
status: done — outcome verified against the page
steps: 5 — auto 4, review 0, blocked 0
每个步骤都会发送一次 Jev 请求;每一步都会经过关卡并记录追踪。满足目标、
页面上没有任何操作可以推动进展(stuck)、关卡要求人工介入(review)、
页面停止变化(no_progress),或达到 --max-steps 时,循环就会停止。
done 只是一个声明——--success 会将其转化为证据(verified;如果
unverified,则运行失败)。--dry-run 只做决策,不执行操作。
2. 或者编写脚本来控制流程,让 Jev 解析每个意图:
# flows/acme-login/flow.yaml
id: acme-login
start: https://app.example.com/login
steps:
- intent: "Sign in to the existing account"
action: click
- intent: "Type the password"
action: fill
value: "${ACME_PASSWORD}" # read from the environment, never written to the trace
- intent: "Submit the login form"
action: click
jevnav run flows/acme-login/flow.yaml --report run.md
3. 在 CI 中重放——离线、确定性、无需密钥:
jevnav replay acme-login.trace.jsonl # re-resolve every recorded decision
jevnav replay acme-login.trace.jsonl --execute # also re-run the actions + check --success
steps 3 verdicts: ok 3
将网站上的 Sign in 改为 Log in,相同的重放就会失败:
[01] changed Sign in to the existing account
no element now has 'button|sign in' (was 'Sign in' / 'button')
退出码为 1,并附带失败原因。这就是回归测试。
为 Agent 提供页面事实
编码 Agent 需要了解的渲染页面事实,无需截图:
outline(selector) 用于查看区域结构(标签、标题、文本、框),
styles(selector, props) 用于查看计算后的值,page_state() 用于查看
jevnav 可以操作的控件。
jevnav diff 将模型图与运行中的应用作为事实进行比较,发现偏差时以状态码 1 退出:
jevnav diff new-ui.html http://localhost:3000 --report ui-diff.md
| 元素 | 属性 | 模型图 | 应用 |
|---|---|---|---|
| h1 [Pricing] | font-size | 32px | 28px |
| button#cta [Start free] | border-radius | 8px | 4px |
报告还会列出结构差异(缺失、新增和移动的元素;框的比较使用 4px 的 --tolerance)。对于“这是一个新 UI,请更新代码库”这一循环:Agent 使用 jevnav 读取两个页面,自行编辑代码,然后重新运行 diff,直到以状态码 0 退出,接着用 goal(..., success="<selector>") 固定结果,让 replay --execute 持续检查。jevnav 只报告结果;它从不编辑你的代码仓库,也从不比较像素。
门控
每个决策都会得到以下三种判定之一:
| 判定 | 含义 |
|---|---|
auto | 置信度达到或超过阈值,且没有风险——执行操作 |
review | 先由人工确认:p 较低、意图存在风险,或候选列表已截断 |
blocked | 无法作出决策(模型回答 none,或调用失败) |
review 和 blocked 永远不会执行。阈值和风险模式位于可选的 gates.yaml 中;默认配置支持九种语言:
# flows/acme-login/gates.yaml
min_confidence: 0.9 # scripted flows: one question per step, well calibrated
loop_min_confidence: 0.5 # goal loop: four questions at once, p runs lower
risky:
- "\\b(delete|remove|purchase|pay)\\b" # matched against intent + element name + role
intents:
"delete the *": { min_confidence: 0.99 }
truncated: review # the page had more than 255 candidates
目标循环会刻意使用较低的阈值:测得的正确循环决策为 p 0.41–0.99,错误决策为 0.39–0.47,因此其安全性依赖确定性检查——拒绝对按钮执行 fill,缺少上下文值的字段会被阻止,两步操作均未产生变化时会停止运行,风险模式始终会转交审核,且结果会与 --success 进行验证。
MCP 服务
claude mcp add --scope user jevnav -- uvx jevnav mcp
或者,适用于 Cursor、Claude Desktop、VS Code 和其他客户端:
{
"mcpServers": {
"jevnav": {
"command": "uvx",
"args": ["jevnav", "mcp"],
"env": { "TYPESAFE_API_KEY": "..." }
}
}
}
无需 URL 或标志:Agent 使用 goto 打开页面,一个服务即可服务所有网站,每个会话都会写入可审计的 jevnav-session.trace.jsonl(使用 --no-trace 可选择不记录)。这些决策工具是其他浏览器 MCP 所没有的:
| 工具 | 功能 |
|---|---|
browse(intent, action, value, min_confidence) | 单步操作:Jev 选择元素,门控作出判定,只有 auto 才会执行 |
goal(goal, context_json, max_steps, success) | 执行完整流程;返回 done / stuck / review 以及验证结果 |
goto(url) · page_state() · summary() | 打开页面、列出 jevnav 可以操作的内容、查看会话汇总 |
此外还有 28 个用于操作和检查的工具(表单、按键、上传、标签页、控制台、网络、样式、轮廓、模拟、跟踪、Lighthouse),每个工具都带有 MCP 注释,让宿主了解哪些调用会改变状态。每次决策的成本约为 $0.00004,耗时约 330ms,页面绝不会进入大模型的上下文。完整工具参考、安全标志,以及何时选择 jevnav 而非 Playwright 或 chrome-devtools-mcp,请参阅:docs/mcp.md。
CI — GitHub Action
- uses: dtduc-git/jevnav@v0
with:
trace: examples/local-demo/demo.trace.jsonl
execute: "true" # also re-run the recorded actions
report: replay.md
无需模型调用,无需 API 密钥,约 30 秒。当录制的目标发生变化、变得模糊不清,或录制的 --success 选择器不再可见时,检查会失败。输入项:trace、report、execute、json、version(默认为 PyPI 中的 latest,或在检出代码时使用 local)。@v0 会随版本浮动;若要确保 CI 完全可复现,请固定到某个发布标签,例如 @v0.2.2。
pytest
该软件包自带 jev fixture:普通的 Playwright 测试也能获得 Jev 决策,而且每个测试都会写入可在 CI 中重放的跟踪记录。
def test_sign_in(jev):
jev.goto("https://app.example.com/login")
jev.fill("the email address", "[email protected]")
jev.fill("the password field", "${DEMO_PASSWORD}")
jev.click("the sign-in button")
jev.expect("#welcome")
DEMO_PASSWORD=... pytest --jev-trace-dir=traces
DEMO_PASSWORD=... jevnav replay --execute traces/test_sign_in.trace.jsonl # offline, no key
review 判定会在操作执行前使测试失败,${VAR} 值只会按名称记录,而 jev.page 是真实的 Playwright 页面,可用于其他所有操作。可运行示例及其已提交的跟踪记录:
examples/pytest-interop/。
你自己的浏览器
jevnav go --goal "..." # fresh headless Chromium (default)
jevnav go --goal "..." --user-data-dir ~/.cache/jevnav-profile --headed # persistent profile
jevnav go --goal "..." --cdp http://127.0.0.1:9222 # attach to a running Chrome
使用 --headed 登录一次,之后每次运行都会复用该配置文件;--cdp
会驱动你已打开的 Chrome,保留其自身设置(因此不接受
--user-data-dir、--locale、--timezone 和 --user-agent),并且不会
关闭它。这两种方式都适用于 run、
go、replay 和 mcp,--browser 也同样适用,可选择 firefox 或 webkit(以及
--locale、--timezone、--user-agent)。配置文件路径和 Cookie 永远不会进入
追踪记录。
证据
| 内容 | 结果 | 来源 |
|---|---|---|
真实网站上的元素选择(9 个网站,jev-1.13.0) | 41/41 个评分案例正确;30/30 个案例通过 p ≥ 0.9 门槛 | research/browser-element-selection.md |
| 决策延迟和成本 | p50 为 365ms,每次决策 $0.000153 | 同上 |
| 目标循环(本地测试页面,4 个目标 × 2 种表述) | 8/8 个目标正确,包括无法完成的目标(stuck) | docs/evidence.md |
| 与 chrome-devtools-mcp 的任务驱动对比(相同大模型,n=2) | jevnav 为 8/8,chrome-devtools-mcp 为 6/8;端到端速度快 2.4× | research/driving-benchmark.md |
| 回放 | 确定性:离线运行、无需密钥,遇到错误决策时退出码为 1 | 使用你自己的追踪记录运行 |
样本量较小且只有一位标注者:应将结果视为趋势,而非证明。
jevnav 的优势在于决策成本和证据,而不是在小型页面上的实际运行速度。方法、注意事项和工具层面的比较:
docs/evidence.md。
工作原理
- 候选列表,而非整个页面。 收集所有 frame 和开放的 shadow root 中可见的交互元素,按人类可能采取操作的概率排序,最多列出 120 个(
--max-candidates,硬上限为 254)。每个元素都带有角色、可访问名称、类型、href、占位文本和作用范围,因此三个名为“Email”的字段仍可区分。 - 每一步只问一个问题。 候选列表加上
none会构成一道选择题;Jev 会回答一个元素及其概率。 - 使用指纹,不使用位置。 元素的身份为
role|name。追踪记录会保存模型看到的每个候选项的指纹;操作和回放都会根据指纹解析元素并检查其唯一性,因此页面发生偏移时也不会误点其他元素。 - 回放判定。
ok、moved、changed、ambiguous、error——后三种会导致失败。--normalize REGEX可放宽已知的动态变化,例如Cart (3)→Cart (4);默认采用严格模式。
追踪记录格式是公开契约:SPEC.md。交互式架构图:docs/architecture.html。
网页之外的应用:docs/games.md(Jev 根据结构化状态玩游戏,并与随机对照组进行测量比较)。
非目标
- 不是规划器。
go/goal会朝你指定的目标前进;决定做什么由你或你的 Agent 负责——jevnav 决定去哪里,并记录原因。 - 不做像素级决策。 决策循环中不使用屏幕截图或 canvas 视觉识别(
screenshot供人类使用),也不生成文本——fill的值来自你的流程、上下文或环境。 - 没有托管服务,也没有遥测。 除了发送到你配置的 Jev 端点的问题外,不会有任何数据离开本机。
隐私
追踪记录包含页面 URL、元素名称和你的操作,但不包含屏幕截图。
目标循环还会发送页面可见文本的简短摘要和当前表单值(密码会遮盖);脚本化流程两者都不会发送。${ENV} 的值仅按名称记录。将 *.trace.jsonl 添加到你的 .gitignore,并在分享追踪记录前进行审查。有关 MCP 服务的权限边界,请参阅 SECURITY.md。
套件
jevnav 是验证技术栈中的浏览器组件: mcplint(MCP 配置)、 harnessguard(Agent 测试框架)、 jevassert + jev-packs(经校准的决策包), 以及 jev-table。
许可证
Apache-2.0 · 版本发布与更新日志
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。
