Jev Ultrafast:具备动态索引动作空间的浏览器 Agent
英文标题:🔶 Jev Ultrafast: A browser agent with a dynamic, indexed action space
TypeSafe 的 Jev Ultrafast 是一种浏览器 Agent:它在每次页面观测后生成动态元素表,并在一次 TypeSafe 请求中同时决定操作及其目标元素。项目演示显示,Agent 完成 Google Flights 上“苏黎世至伦敦”航班搜索仅需 7.1 秒;在有限的对照测试中,中位任务时间从 9.450 秒降至 7.092 秒,浏览器协议调用从 1,092 次降至 101 次。该方案默认基于结构化 DOM 状态而非截图运行,并限制模型输出不能直接成为选择器、坐标或可执行 JavaScript,以提升执行效率与安全边界。项目也明确表示,现有结果并非通用可靠性基准,且 Shadow DOM、iframe、Canvas、文件上传等能力仍不在 MVP 支持范围内。
1.1 MB
46.3 KB
中文
一个拥有动态、索引化动作空间的浏览器 Agent。
只需给它一个目标。TypeSafe 的 Jev 会选择一项操作和一个元素。仅当操作是 TYPE_TEXT 时,一个小型 LLM 才会生成文本。
**在 Google Flights 上从苏黎世到伦敦仅需 7.1 秒。**其中包含一个自然语言目标、实际文本生成以及页面加载等待。
每次观测都会生成一个新的元素表:
[1] button Change ticket type · Round trip
[2] combobox Where from? · San Francisco
[3] combobox Where to? · empty
[4] textbox Departure · empty
...
可用操作包括 CLICK、TYPE_TEXT、SELECT、SCROLL_UP、SCROLL_DOWN、WAIT、DONE 和 BLOCKED。系统只提供受支持的操作及目标。
one TypeSafe request
┌───────────────────────────┐
page → element table → operation │
│ click_target │
│ type_text_target │
│ select_target, if present │
└─────────────┬─────────────┘
use the matching target
│
CLICK [7] ─────┤──→ browser
TYPE_TEXT [3] ─────┘
↓
small LLM → text → browser
目标问题是推测性的。如果操作是 CLICK,则只有 click_target 可以执行。两项决策,一次网络往返。每个目标头仅包含兼容的元素。原生下拉菜单的选项带有已观测的元素/选项索引。
策略中没有针对特定网站的动作脚本,也没有预先准备好的字段字符串。Flights 示例只提供一个目标,并独立验证结果。截图渲染器会在事后添加标签;它并不驱动浏览器。
git clone https://github.com/browser-use/jev-ultrafast.git
cd jev-ultrafast
uv sync
cp .env.example .env
# Add TYPESAFE_API_KEY and TEXT_MODEL_API_KEY.
uv run jev
打开 http://127.0.0.1:8766,然后点击 Start demo → Run automatically。检查器会展示带编号的元素、操作概率、目标概率和已执行的动作。Choose next 会在执行前暂停。
Chrome 通过 Browser Harness 连接,该组件会由 uv sync 安装。如果需要建立连接,请运行 uv run browser-harness --doctor。Chrome 出现提示时,请允许远程调试。
示例配置中的 TEXT_MODEL_API_KEY 是 OpenRouter 密钥。当前演示使用禁用推理功能的 inception/mercury-2.5。Gemini、GLM 和 DeepSeek 也可以使用兼容 OpenAI 的文本辅助器;请配置相应的模型、端点和推理设置。
from jev_ultrafast import Agent
with Agent(
"https://www.google.com/travel/flights?hl=en",
"Find one-way flights from Zurich to London on September 20, 2026, "
"for one adult in economy. Stop when matching flight options are visible.",
) as agent:
for state in agent.run():
print(state["elapsed_ms"], state["status"])
使用 uv run --env-file .env python your_script.py 运行。相同策略也可执行不同任务:
uv run --env-file .env python examples/run.py \
--url https://en.wikipedia.org/wiki/Main_Page \
--goal 'Find and open the Wikipedia article about Gödel’s incompleteness theorems.'
uv run --env-file .env python examples/flights.py --keep-open 会执行航班搜索,检查实际航线、日期和结果,并保存其执行轨迹。它不会选择或预订航班。
- **每个决策周期只发起一次请求。**操作头和目标头共享相同的已观测状态。
- **默认 Agent 循环不使用截图。**Jev 消费结构化状态。检查器可选择启用截图;视频使用独立的连续屏幕录制。
- **每个快照只进行一次浏览器调用。**以原子方式读取可见控件及其名称、值和文本,并保留对实际 DOM 节点的引用。
- **验证选定目标。**点击操作会检查文档、表单值、目标及其附近上下文。仅有动画不会强制进行另一次预测。在输入前解析当前几何位置,并拒绝被遮挡的控件。
- **等待有用状态。**在组合框中输入后,最多等待 200 毫秒,以等待可见的建议项。其他交互最多获得两个动画帧或 50 毫秒。这些读取发生在执行被记录之后。
- **保持隐藏标签页持续渲染。**焦点模拟可避免后台动画被限速,而无需切换 Chrome 的可见标签页。
- **发送可见文本。**屏幕外的文章正文和页脚不会填充模型上下文。
- **复用被中断的文本请求。**只有在整个文本辅助器输入保持不变时,生成的值才会在页面过期重试中得以保留。
每个执行目标都从已观测节点中解析得到。执行器会重新检查页面新鲜度和点击遮挡情况。模型输出绝不会变成选择器、坐标、Shell 命令或可执行 JavaScript。文本辅助器输出必须先解析为一个小型 JSON 对象,才能输入。
| 文件 | 职责 |
|---|---|
| agent.py | 完整循环与文本辅助器交接 |
| snapshot.js | 原子 DOM 快照、索引化控件和新鲜度保护 |
| browser.py | 浏览器连接、当前几何信息与执行 |
| model.py | 动态操作/目标头与文本生成 |
| questions.py | 模型指令 |
| demo.py | 本地检查器 |
当前视频展示了一次耗时 7,073 毫秒 的 Google Flights 运行。计时从初始页面观测之后开始,包含模型调用、生成文本、浏览器操作、过期决策以及加载等待。一次全新的独立检查验证了单程设置、苏黎世、伦敦、2026 年 9 月 20 日以及可见的航班选项。视频以 1× 速度播放,没有开场停顿,结尾停顿 0.5 秒。
在使用相同模型和设置的六次交替运行中,两个版本均以 3/3 的成绩通过。中位任务时间从 9.450 秒 → 7.092 秒,即降低 25%;中位浏览器协议调用次数从 1,092 → 101。这只是同一浏览器配置文件上、同一任务的三次重复测试,并非通用可靠性基准。
相同策略还在 2.798 秒 内打开了所请求的 Wikipedia 文章,并以 1.896 秒 完成了本地酒店搜索/筛选任务。运行记录、失败情况、源哈希和测量边界详见 performance.md。
即使选择 DONE,仍然需要独立验证结果。DOM 读取器处理常见的 HTML 和 ARIA 控件,但并未覆盖完整的可访问名称规范。Shadow root、frame、canvas、上传、弹出标签页、嵌套滚动以及任意键盘控件仍不在此 MVP 范围内。受控标签页共享现有 Chrome 配置文件。
uv run ruff check .
uv run pytest
node --check jev_ultrafast/static/app.js
node --check jev_ultrafast/snapshot.js
uv build
测试可离线运行。uv run python scripts/check_guards.py 会在本地浏览器中检查真实控件,但不会调用模型。在线示例和录制脚本会产生付费 API 调用。scripts/record_flights.py <new-folder> 会捕获原始浏览器时间戳;scripts/render_demo.py <recording-folder> 则以 1× 速度渲染这次经验证的运行,并裁去 Google 账号栏。凭据和原始轨迹始终被忽略。
English / 原文
A browser agent with a dynamic, indexed action space.
Give it one goal. TypeSafe's Jev picks an operation and an element. A small LLM writes text only when the operation is TYPE_TEXT.
Zürich → London on Google Flights in 7.1 seconds. One natural-language goal, actual text generation, and loading waits included.
Watch the MP4 · Measurements · Read the loop
Every observation produces a new element table:
[1] button Change ticket type · Round trip
[2] combobox Where from? · San Francisco
[3] combobox Where to? · empty
[4] textbox Departure · empty
...
The operations are CLICK, TYPE_TEXT, SELECT, SCROLL_UP, SCROLL_DOWN, WAIT, DONE, and BLOCKED. Only supported operations and targets are offered.
one TypeSafe request
┌───────────────────────────┐
page → element table → operation │
│ click_target │
│ type_text_target │
│ select_target, if present │
└─────────────┬─────────────┘
use the matching target
│
CLICK [7] ─────┤──→ browser
TYPE_TEXT [3] ─────┘
↓
small LLM → text → browser
Target questions are speculative. If the operation is CLICK, only click_target can execute. Two decisions, one network round trip. Each target head contains only compatible elements. Native dropdown choices carry an observed element/option index.
There are no site-specific action scripts or prepared field strings in the policy. The Flights example supplies a goal and independently verifies the outcome. The screenshot renderer adds labels afterward; it does not drive the browser.
git clone https://github.com/browser-use/jev-ultrafast.git
cd jev-ultrafast
uv sync
cp .env.example .env
# Add TYPESAFE_API_KEY and TEXT_MODEL_API_KEY.
uv run jev
Open http://127.0.0.1:8766 and click Start demo → Run automatically. The inspector shows numbered elements, operation probabilities, target probabilities, and executed actions. Choose next pauses before execution.
Chrome connects through Browser Harness, installed by uv sync. Run uv run browser-harness --doctor if it needs connecting. Allow remote debugging in Chrome when prompted.
TEXT_MODEL_API_KEY is an OpenRouter key in the example configuration. The current demo uses inception/mercury-2.5 with reasoning disabled. Gemini, GLM, and DeepSeek can also use the OpenAI-compatible text helper; configure the appropriate model, endpoint, and reasoning setting.
from jev_ultrafast import Agent
with Agent(
"https://www.google.com/travel/flights?hl=en",
"Find one-way flights from Zurich to London on September 20, 2026, "
"for one adult in economy. Stop when matching flight options are visible.",
) as agent:
for state in agent.run():
print(state["elapsed_ms"], state["status"])
Run with uv run --env-file .env python your_script.py. The same policy can run a different task:
uv run --env-file .env python examples/run.py \
--url https://en.wikipedia.org/wiki/Main_Page \
--goal 'Find and open the Wikipedia article about Gödel’s incompleteness theorems.'
uv run --env-file .env python examples/flights.py --keep-open performs the flight search, checks the actual route/date/results, and saves its trace. It does not select or book a flight.
- One request per decision cycle. Operation and target heads share the same observed state.
- No screenshots in the default agent loop. Jev consumes structured state. The inspector opts into screenshots; the video uses a separate continuous screencast.
- One browser call per snapshot. Read visible controls, their names, values, and text atomically. Keep references to the actual DOM nodes.
- Validate the selected target. Clicks check the document, form values, target, and nearby context. Animation alone does not force another prediction. Resolve current geometry and reject covered controls before input.
- Wait for useful state. After typing into a combobox, wait for visible suggestions, capped at 200 ms. Other interactions get at most two animation frames or 50 ms. These reads happen after execution is logged.
- Keep hidden tabs rendering. Focus emulation prevents background animation throttling without switching Chrome's visible tab.
- Send visible text. Offscreen article bodies and footers do not fill the model context.
- Reuse an interrupted text request. A generated value survives a stale-page retry only if the entire text-helper input is unchanged.
Every executed target is resolved from an observed node. The executor rechecks page freshness and click occlusion. Model output never becomes selectors, coordinates, shell commands, or executable JavaScript. Text-helper output must parse as a small JSON object before typing.
| File | Job |
|---|---|
| agent.py | The complete loop and text-helper handoff |
| snapshot.js | Atomic DOM snapshot, indexed controls, freshness guards |
| browser.py | Browser connection, current geometry, execution |
| model.py | Dynamic operation/target heads and text generation |
| questions.py | Model instructions |
| demo.py | Local inspector |
The current video is a 7,073 ms Google Flights run. Timing starts after initial page observation and includes model calls, generated text, browser work, stale decisions, and loading waits. A fresh independent check verifies the one-way setting, Zürich, London, September 20, 2026, and visible flight options. The video plays at 1×, with no opening hold and a 0.5-second final hold.
In six alternating runs with identical models and settings, both versions passed 3/3. Median task time went from 9.450 s → 7.092 s , a 25% reduction ; median browser protocol calls went from 1,092 → 101. This is three repeats of one task on one browser profile, not a general reliability benchmark.
The same policy opened the requested Wikipedia article in 2.798 s and passed a local hotel search/filter task in 1.896 s. Runs, failures, source hashes, and measurement boundaries are in performance.md.
A DONE choice still requires independent outcome verification. The DOM reader handles common HTML and ARIA controls, not the full accessible-name specification. Shadow roots, frames, canvas, uploads, pop-up tabs, nested scrolling, and arbitrary keyboard widgets remain outside this MVP. Owned tabs share the existing Chrome profile.
uv run ruff check .
uv run pytest
node --check jev_ultrafast/static/app.js
node --check jev_ultrafast/snapshot.js
uv build
Tests are offline. uv run python scripts/check_guards.py checks real controls in a local browser without model calls. Live examples and recording scripts make paid API calls. scripts/record_flights.py <new-folder> captures original browser timestamps; scripts/render_demo.py <recording-folder> renders that verified run at 1× and crops out the Google account strip. Credentials and raw traces stay ignored.
Browser Use · Browser Harness · TypeSafe speculative fan-out
