Skip to content

About

Pluggable decision layer for the ego lite browser: one System One (Jev) call per step replaces the per-step LLM turn, and the backend can be swapped for a local OpenAI-compatible model. Fail-closed execution guards. The measured one — raw bench data, 16 suites, changelog with corrections.

Topics

Resources

Security policy

Stars

28 stars

Watchers

0 watching

Forks

Latest commit

 

History

101 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ego-decision-layer

skills.sh

English · 简体中文

给 ego lite 的可插拔决策层:默认 System One(Jev),可换本地 / 其他 OpenAI 兼容后端;执行层带 fail-closed 护栏。

当前能力:线性操作闭环、结构化抽取、动作缓存、批处理和 Canvas/SVG 图形区域兜底。 各能力都有对应测试,见功能验证;历史性能数据的条件与复跑脚本见测量与复跑基准。 CHANGELOG.md 保留修复记录和被实测推翻的旧结论,代码级溯源见 THIRD-PARTY.md。 最新版 v0.12.0:P2 第二批受控集扩至 12 项,新增真实 Jev 的 HN / Wikipedia 双宿主测量入口,并补齐超时、启动失败和资源清理的异常路径回归。首批十二次试验为 10 次达成、错误成功 0;复跑命令、原始记录与小样本限制见测量说明。发布页提供源码下载;不同安装方式的更新规则见下载与更新渠道。

English summary: ego-decision-layer replaces the per-step LLM round trip in browser automation with TypeSafe's System One model Jev. Jev reads one indexed element table and answers, in a single request, both the operation (click / type_text / select / scroll_up / scroll_down / wait / done / blocked) and the target element. Code owns observation, execution, verification and exit conditions. The engine also provides schema-validated extraction, guarded action replay, action batches, and a Canvas/SVG region fallback with an injectable grounder. Region detection alone does not interpret image pixels.

Measured after the engine rebuild: HN two-step navigation 4569ms → 1916ms on the same task, and against browser-harness + jev-ultrafast over 100 pre-registered paired rounds — click chain −378ms, wiki search −819ms (using 1 Jev decision instead of 3), form filling no difference, native select +248ms in their favour. Raw data in bench/raw/ via VERIFY-REPORT.md.


为什么需要它

用 ego-browser 做多步任务时,典型写法是每一步都退出浏览器上下文、回到大模型问一句「下一步点哪里」, 拿到答案再开一步。贵在三处:

  • 模型往返:一次大模型判断实测 1.6–4.5s(kimi-k3 1.8s、minimax-m3 1.6s、glm-5.3 3.2s、 qwen3.8-max 3.5s、deepseek-v4-pro 4.5s),每一步都要付一次。
  • 上下文开销:每步一个新进程 / 新会话,进程启动本身 250–350ms,还要重新把页面状态讲一遍。
  • 不确定性:退出条件写在模型嘴里,判没判对没法核对。

ego-decision-layer 把「下一步做什么、点哪个」换成一个小模型(默认 Jev / System One,可换本地 OpenAI 兼容后端),一次请求就答完;观测、执行、 陈旧校验、退出条件全部由代码负责。它不替代大模型:Jev 不生成文本、不做业务判断, 需要写内容时再调一个小文本模型。

能做什么

当前能力与边界如下;性能数字来自特定历史运行,测量条件见测量与复跑基准。

能力 入口 行为与边界
页面稳定等待 settle() 用 MutationObserver 辅助判断 DOM 静默,并保留有界导航等待;不保证未来不会出现延迟渲染
结构化抽取 --extract、--schema、extract() 主文档语义流交给文本模型,结果按 Schema 子集校验;关键内容仍需业务核验
动作缓存 --cache / --no-cache、ActionCache CLI 默认开启;完整 URL、控件状态、输入候选与任务上下文参与身份校验,命中跳过模型请求;无可验证进展时作废并停止
多动作批处理 --batch / --no-batch 执行后端返回的动作序列,批次末尾统一等待;默认 Jev 不会因开启选项就自动生成多动作序列
图形区域兜底 --visual-fallback / --no-visual-fallback、visualGrounder DOM 无目标时扫描 Canvas/SVG 等区域;定位器可注入。默认单区域点击中心,不内置图像识别模型
Windows 路径兼容 main,PR #2 处理 Git Bash/MSYS/Cygwin 的引擎导入、临时目录和缓存路径,保留 UNC authority;UNC 共享端到端未验证

缓存命中的 decideMs = 0 仅表示跳过模型决策,整步仍有观测、校验和派发开销。

  • 多步线性任务一条命令闭环:连续点击、翻页、搜索表单提交、导航跳转。Hacker News 两步导航 A/B 对照中位 4.9s(1 进程)对经典循环 9.7s(3 进程)。
  • 决策比大模型快:Jev 决策请求 0.35–0.52s/次(10 次采样,中位 434ms),大模型 1.6–4.5s/次。
  • 观测便宜:一次 page.evaluate 自建元素表,2–4ms / ~2k 字符;旧路径 page.snapshot() 是 110–130ms / 27484 字符。
  • 动作便宜:裸 CDP 派发 13–16ms;旧路径 page.click(ref) 788–1005ms。
  • 元素表覆盖原生控件之外:无 role 的容器型可点元素(<div onclick>、tabindex、 cursor:pointer 块级容器)补成 clickable-region;实测 YouTube 首页 3 个、X 首页 5 个, 真实 Jev 能选中它。同源 iframe 与开放 shadow root 里的元素也进表。
  • 执行期护栏:陈旧 ref、被遮挡、不可用、跨 frame 命中失败一律拒绝执行(0 次派发), 另有危险动作前置拦截——目标命中「支付 / 删除 / 退订」词表(我们自己的中英词表)时不执行。
  • 退出条件由代码判定:--until <substr> 或脚本里的 check,不依赖模型自评。
  • 每一步可核对:分阶段耗时(观测 / 决策 / 执行 / 校验)与服务端实际模型版本由 renderJevSummary 打印;请求里写的是浮动别名,只有响应里的 model 字段能说明当时服务的是哪版。
  • 凭证链 + 后端可降级:凭证按文件链查找(含已有 rc 里的 export),后端地址可覆盖, 主后端失败有一条可关闭的降级端点。
  • 没凭证也能先自测:bench/test-offline-e2e.mjs 在 about:blank 上注入 DOM, 用注入判定器跑真实的观测 → 裸 CDP 派发 → 真实 DOM 断言,不联网、不需要 key。

Demo

真实运行录屏

上面这段是真实运行录的:docs/capture-demo.mjs 跑 hacker news 首页 → new → comments, 每步动作后注入的说明条取自真实的 runJevStep 结果(不是写死「成功」)。重做命令见 docs/README.md。

Usage

怎么用:装好后,给出起始网址、操作目标和成功条件即可。首次使用先完成安装;默认 Jev 后端需要 ego lite / ego-browser 和 TypeSafe 凭证,也可切换本地决策模型。

交给 Agent:安装技能后,直接发送下面这段话:

用 ego-decision-layer 打开 https://en.wikipedia.org/wiki/Main_Page,在搜索框输入 Jev 并提交。 输入候选用 --text "Jev",成功条件用 --until "/wiki/Jev",最多 5 步。 完成后报告最终 URL、reason 和退出码。

自己运行:以下以用户级安装到 ~/.agents/skills/ego-decision-layer/ 为例;装在其他目录时替换该路径。 克隆仓库的用户可在仓库根目录改用 ./scripts/ego-decision-layer;已加入 PATH 时直接用 ego-decision-layer。

"$HOME/.agents/skills/ego-decision-layer/scripts/ego-decision-layer" \
  --url "https://en.wikipedia.org/wiki/Main_Page" \
  --text "Jev" --until "/wiki/Jev" --steps 5 \
  "在顶部搜索框输入 Jev 并提交"

输入内容由 --text 提供,这个例子无需另配文本生成模型。要换成连续点击任务,可以运行:

"$HOME/.agents/skills/ego-decision-layer/scripts/ego-decision-layer" \
  --url "https://news.ycombinator.com" \
  --until "/newcomments" --steps 5 \
  "先打开 new 页面,再打开 comments 页面"
参数 填什么
--url 起始页面的网址
--text 要填入的文本;多个候选可重复传入
--until 最终 URL 应包含的子串,例如 /wiki/Jev
--steps 最大操作步数,默认 10

怎么看结果:命令末尾打印结果 JSON。搜索例子应同时满足 success: true、url 包含 /wiki/Jev,且 reason 为 check_passed 或 check_passed_after_step。 单独的 jev_done 表示模型判断完成,仍需核对最终 URL。退出码 0 表示运行成功,1 表示未达成,2 表示参数错误,3 表示缺少 Jev 凭证。 成功后默认关闭本次 TaskSpace;需要查看页面时加 --keep-space。失败时保留 TaskSpace,可用结果中的 spaceId 排查。

更多示例:复用已有页面与 JS API、结构化数据抽取、文本生成配置。完整参数运行 ego-decision-layer --help 查看。

外部 Chrome(v0.11.0 起)

--cdp-endpoint 让普通 Node 连接已启用远程调试的外部 Chrome;需要 Node 22+。 默认 ego lite 入口继续使用 ego-browser。CDP 模式不需要 ego lite,也不刷新 Agent 的 ego-browser 路由。

./scripts/ego-decision-layer --cdp-endpoint http://127.0.0.1:9222 \
  --url "https://en.wikipedia.org/wiki/Main_Page" \
  --text "Jev" --until "/wiki/Jev" --steps 5 \
  "type Jev into the search box and submit"

CDP 连接创建自己的页面,保留外部浏览器及其原有标签页。--space / --keep 属于 ego TaskSpace,不能与 --cdp-endpoint 混用;需要保留新页面供检查时使用 --keep-space。默认 Jev 仍需 TypeSafe 凭证, 也可使用已有的 OpenAI 兼容决策配置。此入口已完成双宿主受控任务验收,自 v0.11.0 起随版本发布。

开发验证入口为 node bench/test-host-integration-live.mjs --suite(Node 22+、Chrome、Jev 凭证)。 它创建临时 Chrome 与受控表单,跑共同任务集、真实 Jev 的 HN 导航和表单提交,再验证共享 CLI 与资源清理。 Chrome 路径用 EGO_CDP_CHROME 覆盖。加 --wiki 可测 Wikipedia 搜索;该站在 5 步预算下实测有成功也有失败, 目前不作为稳定验收门槛。共同任务集使用注入判定器,其通过数不能当成模型或真实站点成功率。

安装

方式 1:skills CLI(推荐,一行)

npx skills add jiangkoumo/ego-decision-layer

装完技能落在 Agent 的技能目录里(如 ~/.agents/skills/ego-decision-layer/),引擎和 CLI 一起带过去。

方式 2:Claude Code 插件市场

仓库根有 .claude-plugin/plugin.json 与 .claude-plugin/marketplace.json,技能本体在 skills/ego-decision-layer/(里面是指向仓库根的相对软链,不复制正文)。在 Claude Code 里:

/plugin marketplace add jiangkoumo/ego-decision-layer
/plugin install ego-decision-layer@ego-decision-layer

方式 3:克隆后跑安装脚本

git clone https://github.com/jiangkoumo/ego-decision-layer.git
cd ego-decision-layer
./install.sh            # 链接 CLI 进 ~/.local/bin、准备凭证,并**默认接管**官方 ego-browser 入口
./install.sh --no-wire  # 只装 CLI,不接管(旧行为)
./install.sh --test     # 顺带跑一次端到端冒烟测试

方式 4:把这段 prompt 丢给你的 Agent

帮我安装 https://github.com/jiangkoumo/ego-decision-layer :

  1. 执行 npx skills add jiangkoumo/ego-decision-layer(skills CLI 不可用就改成克隆仓库跑 ./install.sh);
  2. 确认 ego-browser --version 正常,没有 ego lite 就先让我装;
  3. 确认 ~/.config/typesafe/api_key 存在且权限 600,缺了就问我要 Key——不要自己编,也不要回显它;
  4. 跑下面「验证安装」里的命令,把真实输出和退出码报给我;
  5. 接管官方 ego-browser 入口(让多步任务默认走 ego-decision-layer):bash scripts/wire-agent-skills.sh, 再用 --check 确认 exit 0。只写 Agent 技能目录,不要改 /Applications/ego lite.app 里的任何文件。

下载与更新渠道

metadata.version 当前为 0.12.0。ego-decision-layer update [--test] 与 --version 自 0.10.0 起提供。 Git 安装按当前分支上游 fast-forward,skills 拷贝按安装记录定向更新并保留原作用域; ZIP / 插件安装没有匹配记录时需走原渠道。旧版本先按原渠道更新一次,才能获得新子命令。 已跟踪文件有未提交改动时更新停止并非零退出,普通未跟踪文件保留,冲突由 Git 拒绝覆盖。

Windows 路径修复来自 PR #2(合并提交 76ee335),已包含在 v0.9.1 及之后的版本。 标签对应固定提交;main 会继续演进,后续修复合并后可能先于下一个标签提供。

ego-decision-layer --version
ego-decision-layer update          # 更新当前安装
ego-decision-layer update --test   # 更新后运行真实浏览器冒烟
获取方式 是否包含 PR #2 的 Windows 修复
新 git clone,默认分支 main 是
跟踪 main 的克隆执行 git pull --ff-only / ego-decision-layer update 更新成功后包含;已跟踪文件有未提交改动时更新会停止并非零退出
GitHub 下载 main 的 ZIP 是,内容以下载时的 main 为准
下载 v0.12.0、v0.11.0、v0.10.0 或 v0.9.1 发布页或标签的 ZIP/tar.gz 是
下载 v0.9.0 标签的 ZIP/tar.gz,或固定该标签/更早提交 否,需要更新到 v0.9.1 或含修复的提交
npx skills add jiangkoumo/ego-decision-layer 未固定 ref 时获取仓库默认分支;已有拷贝需要重新安装更新,不会随合并自动变化
Claude Code 插件市场安装 已安装的插件可能仍使用缓存;需更新 marketplace 和已安装插件,再核对其实际代码

克隆安装可查看实际提交:

git branch --show-current
git log -1 --oneline
git merge-base --is-ancestor 76ee335 HEAD  # exit 0 表示当前提交包含该 Windows 修复

Windows 使用 Bash(Git Bash / MSYS / Cygwin)运行 CLI 和安装脚本;这些 .sh 脚本不是原生 PowerShell 命令。 PR #2 的贡献者在 Windows 11、Node v24.20.0、ego-browser 0.6.0.16 上验证了路径测试、默认缓存复用和自定义缓存位置。 UNC 路径转换及 Windows Node 解析已验证,但没有可达网络共享用于端到端测试。

从 ego-jev 迁移(0.4.0)

0.3.x 旧名叫 ego-jev。0.4.0 改名为 ego-decision-layer(名字不再绑死某个厂商的决策后端)。仓库内改名 全部自动:跑一次迁移脚本即可,旧 CLI ego-jev 仍可用(保留为兼容垫片,自动转发到新 CLI)。

bash scripts/rename-self.sh --dry-run   # 1. 先看它会做什么(不写任何文件)
bash scripts/rename-self.sh             # 2. 执行:还原旧接管 → 重建新技能软链 → 迁移配置目录 → 用新名重接管
# 3. 重开 Agent 会话(技能列表是启动时快照的)

迁移脚本是幂等的:再跑一次是 no-op。它做这些事:

  • 旧接管状态先用旧路径 --restore 清掉(路由层 + always-on 块 + 启用标记);
  • 删除旧技能软链(~/.agents/skills/ego-jev 等),按新名重建;
  • ~/.local/bin:ego-decision-layer → 新 CLI,ego-jev → 兼容垫片;
  • 配置目录 ~/.config/ego-jev 兼容迁移到 ~/.config/ego-decision-layer(新目录已存在则合并并留 .bak);
  • 用新名重新接管,并把记下的 always-on 文件原样重新插块;
  • 自检(--check exit 0、--route-status)并 grep 公开界面确认旧名只在白名单里。

环境变量名 EGO_JEV_* 保持不变(历史名,继续可用);引擎导出名(askJev / runJevStep / runJevAutonomousLoop …)也一个没改。

让 Agent 默认走 ego-decision-layer(默认接管)

ego lite 会把官方 ego-browser 技能写进每个 Agent 的技能目录 (~/.agents/skills/ego-browser、~/.claude/skills/ego-browser …,由 App 在安装/升级时重建), 而官方正文不知道 ego-decision-layer 存在——不管的话,Agent 默认照它写逐步脚本,ego-decision-layer 根本不会被启动。

scripts/wire-agent-skills.sh 把这个入口接管成一层路由层(包外):Agent 先看到的 「先路由、再决定写不写脚本」那一节是本技能加的,技能正文仍然软链到 App 的当前版本(升级自动跟随)。 技能列表里的 description 也把路由句排到厂商描述之前(描述被按预算压缩、优先丢尾部,排在末尾 等于最先被砍掉);厂商文本一字不改,只是挪到后面。 install.sh 默认就会做这件事,ego-decision-layer CLI 首次运行时也会在检测到官方入口时补一次:

bash scripts/wire-agent-skills.sh              # 接管 / 刷新(幂等;只写 Agent 技能目录,不碰应用包)
bash scripts/wire-agent-skills.sh --check      # 只读检查:已接管 N / 无需接管 M / 漂移 K(漂移则 exit 1)
bash scripts/wire-agent-skills.sh --restore    # 还原成官方软链 + 记下「不接管」(粘性,见下)

退出码:0 正常 / 1 需要处理(--check 发现漂移;或本次一个都没接管到)/ 2 用法或环境错误。 --vendor(或 EGO_JEV_VENDOR)显式指定时就是权威:目录里没有 SKILL.md 直接报错,不回退自动探测。 --check 对每个目录给出结论(本机实测):

OK    ~/.agents/skills/ego-browser(路由层,生成物最新)
OK    ~/.claude/skills/ego-browser(路由层,生成物最新)
无需接管  ~/.codex/skills(没有官方 ego-browser 入口;该 Agent 通过自身的 ego-decision-layer 技能被发现)

==> 路由: 已接管 2 / 无需接管 3 / 漂移 0

--check 是只读的(不写启用标记、不改 mtime);--restore 不需要 ego lite 还在(不会自锁)。 接管会在 ~/.config/ego-decision-layer/wire-enabled.json 留下启用标记;./update.sh 与 ego-decision-layer CLI 都会据此自动重接管(EGO_JEV_NO_WIRE=1,旧名 EGO_JEV_NO_HEAL=1 仍接受)。 路由只影响新开的 Agent 会话(技能列表是启动时快照的)。

--restore 是粘性的:它会记下「用户已明确选择不接管」(~/.config/ego-decision-layer/opted-out), 之后 CLI 首跑不会再把入口接管回去(--ensure 见到该标记就什么都不做);--check 在该状态下 输出「已按用户选择不接管」并 exit 0(健康状态,不是漂移)。重新启用必须显式跑一次接管 (上面的 bash scripts/wire-agent-skills.sh,或 ./install.sh 的接管步骤)—— 自动路径(--ensure / --if-enabled)永远不会解除这个选择。

让 Agent 在读任何技能之前就看到路由(always-on,显式开关)

接管只覆盖「Agent 去读 ego-browser 技能」这条路径。若想让它在读技能之前就知道 「多步线性浏览器任务先走 ego-decision-layer」,可以把一段带标记的说明块写进常驻指令文件:

bash scripts/wire-agent-skills.sh --always-on AGENTS.md              # 项目级:只覆盖这个仓库,随仓库共享(最安全)
bash scripts/wire-agent-skills.sh --always-on ~/.claude/CLAUDE.md    # 本机所有 Claude Code 项目
# 只撤掉某一个文件的那块(不碰接管层):
bash scripts/wire-agent-skills.sh --always-on --remove ~/.claude/CLAUDE.md

块用 <!-- ego-decision-layer:route begin --> / <!-- ego-decision-layer:route end --> 标记,幂等(重复跑只替换自己那一块), 首次写入前备份到同目录 .bak。 只移除某一个文件的块用 --always-on --remove <file>(别名 --always-on-remove <file>):有 .bak 就按备份 逐字节还原,没有就只删标记区及其自带分隔空行;同步从记录列表里去掉;不碰接管层;幂等(没有块 → exit 0)。 --restore 则是全量:连同接管层一起精确移除(块外内容一字不动)。 默认不会写任何用户文件——只有你显式传 --always-on <file> 才写。

三种放法各覆盖谁:

放法 覆盖范围
项目 AGENTS.md 只覆盖该仓库(开放标准,Codex / Cursor / Amp / Copilot 等都会读),随仓库共享
~/.claude/CLAUDE.md 本机所有 Claude Code 项目(常驻指令文件)
个人作用域技能(~/.agents/skills、~/.claude/skills) 该 Agent 的技能列表;在 Cowork / 云会话里不加载,always-on 那行也一样受会话类型限制

路由可审计:--route-status

ego-decision-layer --route-status        # 只读 JSON:接管情况 / always-on / 官方技能路径 / 生成物哈希

不起浏览器、不需要凭证、不建 TaskSpace。同一份信息也会作为 route 段写进每次任务的结果 JSON, renderJevSummary 收尾还会带一行:路由: 已接管 2 / 无需 1 / 漂移 0 · always-on 1。

让 Agent 真的用上它:三档手段与实测差异

「装了就真的被用上」是分层的,到这一版也没法一刀切。用全新会话做决策探针(中立 cwd、 只让它报「打算怎么做」、不许执行),三档的实测差异如下(n 很小,只说明方向):

手段 覆盖谁 实测(决策探针:计划里是否走本技能)
接管 + 自身技能(默认安装) 交互式会话 5/5 主动走本技能(含两条不含「点击/翻页」字眼的问法)
显式指派 --handoff-prompt 子代理 / 一次性无会话上下文 不指派 0/6;这类上下文里既没有技能清单、也没有任何 AGENTS.md 内容,--always-on 那行也到不了它们——必须显式点名
常驻兜底 --always-on <file> 读常驻指令文件的会话 开 always-on 后交互式复测 2/2,无回归;对子代理仍无效

子代理怎么点名:把 --handoff-prompt 的整段输出贴进派活消息即可(路由判据 + 解析后的技能目录、 CLI、SKILL.md 真实路径 + 可照抄的命令模板 + 收尾的 --route-status 核对):

ego-decision-layer --handoff-prompt              # 纯文本,直接粘贴给子代理
ego-decision-layer --handoff-prompt --json       # 机器可读:{prompt, skillDir, cliPath, skillMdPath}

只读选项:不起浏览器、不需要凭证、不写任何文件,也不触发首跑接管。

边界(如实):

  • 不读技能的 Agent 绕不过去:上面三档都不改变「Agent 是否愿意读技能 / 常驻指令文件」这件事; 探针只测「计划里是否走本技能」,不是真实执行成功率。
  • 个人作用域技能在 Cowork / 云会话里不加载(会话类型限制,不是配置问题);--always-on 写进 常驻指令文件的那行也一样受会话类型限制。
  • 个人作用域同名技能可以替换内置命令,但替换不了它的别名;插件作用域技能是命名空间的, 所以插件渠道天然不会覆盖内置技能。
  • hooks(SessionStart / UserPromptSubmit 注入 additionalContext)是唯一「必须发生」的强制层, 本轮没做——它要写用户的 Agent settings。

更新

ego-decision-layer update          # 在任意目录更新当前安装,刷新命令入口与已启用的路由
ego-decision-layer update --test   # 更新后再跑浏览器冒烟(需要浏览器、网络与凭证)
ego-decision-layer --version       # 查看版本号;Git 克隆还显示实际提交

克隆安装按当前分支的上游执行 git pull --ff-only,也支持 Git worktree。 skills 管理的拷贝会根据安装记录执行 npx --yes skills update ego-decision-layer --global/--project --yes, 只更新本技能并保留全局或项目作用域,不顺带更新其他技能。更新后刷新 PATH 入口及已经启用的路由, 新开的 Agent 会话会读取新的技能说明。

已跟踪文件有未提交改动、固定在标签/提交、没有上游、网络失败或缺少安装记录时,命令会非零退出并说明原因; 不会重置本地 Git 改动,也不会把失败报告成“已是最新”。普通未跟踪文件会保留;若与上游新文件冲突,Git 会拒绝覆盖。 自定义命令目录可用 BINDIR=/your/bin ego-decision-layer update;目录不在 PATH 时会提示。 ZIP 或插件安装请继续通过原渠道更新。新更新器已在 macOS 与隔离 Git/skills 环境验证,Windows 真机更新尚待验证。

旧版本首次升级:没有 update 子命令时,克隆用户先运行一次 cd ego-decision-layer && ./update.sh; skills 用户运行 npx skills update ego-decision-layer(按原安装作用域选择)。之后即可使用上面的统一命令。 根目录 ./update.sh 仍保留为兼容入口。

验证安装(别只看代码,跑起来)

ego-browser --version                                        # 前置条件
"<技能目录>/scripts/ego-decision-layer" \
  --url "https://en.wikipedia.org/wiki/Main_Page" \
  --text "Jev" --until "/wiki/Jev" --steps 5 \
  "在搜索框输入 Jev 并提交"
# 期望:exit 0,且输出里 "success": true

# 接管过官方入口的话(默认就会接管),看它是否还生效:
bash "<技能目录>/scripts/wire-agent-skills.sh" --check   # 期望:exit 0(漂移则 exit 1)
grep -l "先路由" ~/.agents/skills/ego-browser/SKILL.md     # 期望:打印出路径

核对结果时:success: true 可能来自 jev_done,不能单凭 exit 0 认定 --until 已命中。 上面的搜索任务还应确认输出 url 包含 /wiki/Jev,并查看 reason 是否为 check_passed / check_passed_after_step。 Windows 贡献者报告某些环境下英文首页搜索框为 0×0;可尝试 https://www.wikipedia.org/,但可能进入搜索结果页,仍需核对最终 URL。

没凭证也能先自测:ego-browser nodejs < bench/test-offline-e2e.mjs 在 about:blank 上注入 DOM, 用 options.ask 注入确定性判定器(不联网、不需要 key),但观测、locate、裸 CDP 派发、结果断言 全走真实路径;失败时能分清是引擎坏了还是凭证/网络问题。

凭证:必须落盘成文件

这是最容易踩的坑:ego-browser nodejs 内嵌运行时只继承最小化登录环境(HOME/PATH 等), 父进程 export 的环境变量(含 TYPESAFE_API_KEY)不会传进去。所以凭证必须写成文件。

mkdir -p ~/.config/typesafe && printf '%s\n' 'YOUR_TYPESAFE_API_KEY' > ~/.config/typesafe/api_key
chmod 600 ~/.config/typesafe/api_key

从 TypeSafe 获取 API Key。也可用 TYPESAFE_API_KEY_FILE 指定别的路径, 或 --api-key 直接传入。

查找顺序(全部是文件,因为 ego 运行时拿不到父进程环境变量): --api-key > TYPESAFE_API_KEY(仅普通 node 进程可见)> TYPESAFE_API_KEY_FILE > ~/.config/ego-decision-layer/credentials > ~/.config/typesafe/api_key > ~/.zshrc / ~/.bashrc / ~/.bash_profile / ~/.profile 里的 export TYPESAFE_API_KEY=…。 所以已经 export 过 key 的机器不必再落盘一次。后端地址可用 TYPESAFE_BASE_URL 覆盖, 主后端失败时的降级端点用 TYPESAFE_FALLBACK_BASE_URL(不设即不降级,fallback: false 可关)—— CLI 会在父进程读这两个变量并写进配置传给子进程(ego 运行时自身读不到自定义环境变量); 直接写 ego-browser nodejs 脚本时请改用 options.baseUrl / options.fallbackBaseUrl。

用法

命令行:

# 简单目标
ego-decision-layer --url "https://example.com" "点击登录按钮并聚焦输入框"

# 推荐:给确定性成功条件(URL 包含该子串即判成功)
ego-decision-layer --url "https://news.ycombinator.com" --until "/newcomments" \
  "先打开 new 页面,再打开 comments 页面"

# 需要输入文本:候选由调用方给,Jev 只选字段和选哪段文本
ego-decision-layer --url "https://en.wikipedia.org/wiki/Main_Page" --text "Jev" \
  --until "/wiki/Jev" "在顶部搜索框输入 Jev 并提交"

# 复用已有 taskSpace,完成后保留供人工检查
ego-decision-layer --space 3 --keep-space --steps 15 "点击未发送帖子并保存"

--until 给的是确定性退出条件,比依赖 Jev 自评 done 可靠得多,强烈建议带上。 退出码:0 达成 / 1 未达成(此时 taskSpace 被保留供排查)/ 2 参数错误 / 3 缺凭证。 CLI 收尾会打印一行分阶段耗时与服务端实际模型版本(renderJevSummary)。

在 ego-browser nodejs 脚本里复用引擎:

const { runJevAutonomousLoop } = await import("/absolute/path/to/ego-decision-layer/scripts/decider-loop.mjs");

const result = await runJevAutonomousLoop(page, "先打开 new 页面,再打开 comments 页面", {
  maxSteps: 8,
  text: ["Jev"],                                                  // 可填文本候选(可选)
  check: async (p) => (await p.url()).includes("/newcomments"),    // 确定性成功条件(推荐)
});
console.log(result); // { success, reason, steps, history, phases, serverModels, usage }

配套导出:askJev、runJevStep、parseActionTargets、enrichTargets、buildQuestions、 validateChoice、generateText、loadTextModelConfig、resolveTextApiKey、loadApiKey、 renderJevSummary(分阶段耗时 + 服务端模型)。判定器可注入:options.ask(state, questions), 与 askJev 同签名,用于离线自测或接入别的判定器(优先级最高)。决策后端抽象层另导出 resolveDecider / loadDeciderConfig / createOpenAICompatibleDecider / validateAnswer / confidenceGate(见下节)。

把「自动驾驶」作为独立技能装给 Agent(可选):

npx skills add jiangkoumo/ego-decision-layer          # 推荐
# 或本地链接:
mkdir -p ~/.agents/skills/ego-decision-layer && ln -sfn "$PWD/SKILL.md" ~/.agents/skills/ego-decision-layer/SKILL.md

不要把 Jev 章节加进 ego lite 应用包里的 SKILL.md。那是供应商受签名的应用包, 升级会替换 Resources/ego-skills/ 目录(版本号目录都会换),改动必然丢失。 本技能刻意放在包外,升级后无需重做。

结构化抽取、缓存与批处理

抽取可以独立运行,也可接在操作任务之后。纯抽取需要文本模型配置,无需单独提供 Jev Key;操作加抽取则需要对应的两个后端可用。

# 从当前加载的页面抽取严格 3 项 JSON
ego-decision-layer --url "https://news.ycombinator.com" \
  --extract "提取前3条新闻的标题和绝对链接" \
  --schema '{"type":"array","minItems":3,"maxItems":3,"items":{"type":"object","properties":{"title":{"type":"string"},"url":{"type":"string"}},"required":["title","url"]}}'

# 操作成功后再抽取;--schema 也接受 JSON 文件路径
ego-decision-layer --url "https://news.ycombinator.com" --until "/newcomments" \
  "先打开 new 页面,再打开 comments 页面" \
  --extract "提取前3条评论的正文" --schema '[{"text":"string"}]'

# 关闭缓存、批处理和图形区域兜底,排查单动作路径
ego-decision-layer --no-cache --no-batch --no-visual-fallback \
  --url "https://news.ycombinator.com" --until "/newcomments" "打开 comments 页面"

Schema 支持 type、properties、items、required、enum、minItems、maxItems、布尔型 additionalProperties, 以及 {title: "string"} / [{title: "string"}] 等简写。不支持的特性会显式失败。 抽取数据类型正确不等于条目完整或事实正确;需要固定数量时写明 minItems / maxItems,重要字段用同页 DOM 或业务数据核验。 JS 接口 extract(page, instruction, {schema, selector}) 可限定区域;选择器无效或不存在时失败,不会扩大到整个页面。

CLI 缓存默认位于 ~/.config/ego-decision-layer/action-cache.json,用 EGO_JEV_CACHE_FILE 覆盖。 --no-cache 禁止本次回放。缓存动作仍受执行层护栏约束;回放后结果不明时会停止,避免重复副作用。

批处理需要自定义 ask / decider 返回 {action: "batch", subActions: [...]},子动作可填入本次观测得到的 ref 与文本。 它不是事务:预检发现危险动作会整批拒绝,但中途失败时已经执行的输入不会回滚。 检查结果中的 executedSubActions 和 failedSubActionIndex,再决定后续操作;不要整批盲重试。 接口和注入示例见 SKILL.md 与 bench/test-multi-action-batch.mjs。

图形区域兜底的 visualGrounder(page, goal, context) 可返回 {action: "click_visual", x, y, label}。 调用方负责图像理解与坐标定位;仅扫描区域几何信息无法识别 Canvas 内部按钮。没有定位器时,单区域会点击中心,多区域会等待。 可用 --no-visual-fallback 关闭;当前坐标通道的视口检查与标签词表不等同于语义动作的完整 DOM 命中护栏。

功能验证

从仓库根目录执行。纯 Node 测试不需要浏览器或凭证:

node bench/test-windows-paths.mjs       # Windows 路径与缓存转换分支
node bench/test-extract-http.mjs        # 抽取 HTTP 协议、Schema、错误响应
node bench/test-guardrails.mjs
node bench/test-release-consistency.mjs

浏览器离线测试需要已运行的 ego lite,用合成 DOM 和注入决策器,不调用外部模型:

ego-browser nodejs < bench/test-settle-mutation.mjs
ego-browser nodejs < bench/test-extract.mjs
ego-browser nodejs < bench/test-action-cache.mjs
ego-browser nodejs < bench/test-multi-action-batch.mjs
ego-browser nodejs < bench/test-visual-fallback.mjs
ego-browser nodejs < bench/test-offline-e2e.mjs

这些脚本的默认导入路径指向 ~/.agents/skills/ego-decision-layer,应先确认该技能指向待测代码。 PR #2 只修复 CLI;部分浏览器 bench 脚本仍使用 POSIX 导入路径,尚未统一适配 Windows。 真实网络的冷/热缓存及更换输入测试见 bench/test-action-cache-live.mjs,需要浏览器、网络和 Jev 凭证。 离线测试通过不能替代真实后端、真实站点或 UNC 网络共享上的验证。

文本生成(可选)

--text 的候选文本由调用方给出时,Jev 只做选择。若想让模型自己写文本(例如「搜索哥德尔不完备定理」 需要生成搜索词),配置一个 OpenAI 兼容端点:

// ~/.config/typesafe/text_model.json
{
  "baseUrl": "https://your-endpoint/v1",
  "apiKeyJson": { "file": "~/.pi/agent/auth.json", "path": "opencode-go.key" },
  "model": "deepseek-v4.1-flash",
  "sessionHeader": "x-opencode-session",
  "sessionId": "ego-decision-layer",
  "userAgent": "ego-decision-layer/1.0"
}
  • apiKeyJson 引用已有凭证文件而不复制密钥;也可直接写 apiKey
  • 生成结果严格校验:只接受恰好一个非空 text 字段的 JSON,不合格判 text_model_failed 而不猜值
  • 也可在脚本里把 textModel 传成自定义 async (input) => string 函数接入任意模型
  • textModel: null 显式禁用
  • 实测某网关的 deepseek-v4.1-flash 会输出 reasoning_content,reasoning:{enabled:false} 无效, 生成约 1.3–1.9s

决策后端(decider):默认 System One,可换本地模型

引擎把「谁来回答这张问题表」抽成了一层。默认后端就是 TypeSafe System One(askJev,行为与从前 完全一致);也可以切到本地 / 自建的 OpenAI 兼容端点(POST /v1/chat/completions,llama.cpp / ollama / vLLM / LM Studio 都提供)。契约:

decide({ state, questions, options }) → { answers, meta }
  answers  与 questions 同形:每个问题头给出 { choice },值必须来自该头的 criteria 键
  meta     { model, usage, endpoint, kind }

questions 与给 System One 的完全一样(operation + 各操作的兼容元素),本地后端只是换个渲染方式: 问题头与候选按稳定顺序(不掺时间戳/随机数)写成一段文本,要求模型返回严格 JSON;返回非 JSON、 缺问题头、或选了不存在的候选 → 一律按 invalid_response 失败,不猜、不执行任何动作。

配置放在文件里(ego-browser 内嵌运行时拿不到自定义环境变量;与路由层同一配置目录, 可用 EGO_JEV_DECIDER_FILE 覆盖路径):

// ~/.config/ego-decision-layer/decider.json
{
  "kind": "openai-compatible",
  "baseUrl": "http://127.0.0.1:11434/v1",
  "model": "qwen2.5:7b",
  "apiKey": "ollama",
  "apiKeyFile": "~/.config/ego-decision-layer/local.key",
  "timeoutMs": 30000,
  "headers": { "X-My-Gateway": "1" }
}
  • kind:systemone(默认)或 openai-compatible;字段 baseUrl / model / apiKey / apiKeyFile / timeoutMs / headers
  • apiKey 与 apiKeyFile 二选一;本地端点常不校验,两者都可以不写(不会回退去读 TypeSafe 凭证)
  • CLI 覆盖:--decider <kind>、--base-url <url>、--model <name>;未配置时行为与从前完全一致
  • 脚本里也可注入:options.ask(state, questions, options)(优先级最高,压过任何配置),或 options.deciderConfig / options.decider

能力差异(诚实处理置信度):文本 LLM 没有校准过的概率。适配器声明 capabilities: { confidence: false },引擎据此跳过所有基于置信度阈值的升级 (minOpConfidence / minTargetConfidence / doneThreshold / stuckThreshold,默认都是关), 也绝不伪造概率或置信度数字。但执行层护栏一条不少:陈旧校验(结构指纹)、guardRejected、 跨 frame fail-closed、危险动作拦截,以及 validateChoice 的候选合法性校验(choice 必须来自本次 给出的候选集合)。System One 后端能力为 confidence: true,语义与从前完全一致。

接一个本地端点(不写 --decider 就仍走 System One,只有显式指定时才切):

ego-decision-layer --decider openai-compatible \
  --base-url "http://127.0.0.1:11434/v1" --model "qwen2.5:7b" \
  --url "https://en.wikipedia.org/wiki/Main_Page" --until "/wiki/Jev" --text "Jev" \
  "在搜索框输入 Jev 并提交"

退出原因

reason 含义
check_passed / check_passed_after_step 确定性检查命中
jev_done 模型判断完成;仍应核对业务条件
extracted 抽取结果通过结构校验;内容仍需核验
schema_validation_failed 抽取结果不满足 Schema,例如类型或条目数不符
cache_replay_unverified / action_outcome_unknown 缓存回放无可验证进展或动作结果未知;作废并停止,核验后再继续
blocked Jev 判定验证码/登录墙/无可用推进手段
no_progress 连续 5 次变更类动作页面无变化
stuck 同一动作连续 3 次无变化(含反复滚动;原生下拉重问仍失败也归这里)
target_missing 选了需要目标的动作却没解析出目标(连续 2 次)
no_targets 连续 3 次空快照(页面可能仍在加载)
viewport_degraded 视口退化(0×0)且自动撑起失败(CDP 报错),或显式 --no-force-viewport / options.strictViewport:steps: 0、不派发、不问模型。默认在 0×0 时会自动 Emulation.setDeviceMetricsOverride 撑起 1280×900@1 后照常跑(视口正常时零额外 CDP),不报此因;见「已知限制」与 SKILL.md 的「边界(实测)」
guard_rejected 执行前守卫拒绝(陈旧/遮挡/不可用/跨 frame 命中失败,或命中危险动作词表 dangerous_action),该步未执行
invalid_response 决策响应不通过校验(System One:非 argmax / 概率和不一致;本地后端:非 JSON / 缺问题头 / 候选非法),未执行
low_confidence 有校准置信度的后端上,置信度低于 minOpConfidence / doneThreshold / minTargetConfidence 阈值(阈值默认关;无置信度的本地后端不受影响)
text_model_failed / no_text_source 输入操作拿不到文本,不会猜一个值填进去
action_failed / max_steps_reached 执行异常 / 超出步数预算

失败时先看 reason 再决定是否重试;不要盲目重跑同一目标。

已知限制(实测)

  • 「装完就默认走 ego-decision-layer」能到哪一步(这些是别人踩过的坑,不是我们的猜测):
    • 个人作用域的同名技能可以替换内置命令,但替换不了它的别名——别名仍指向内置版本。
    • 个人作用域技能在 Cowork / 云会话里不加载(会话类型限制,不是配置问题);always-on 那行也一样。
    • 插件作用域技能是命名空间的(插件名:技能名),所以插件渠道天然不会覆盖内置技能。
    • 想「让冲突源消失」可以用官方的 disable-model-invocation: true(把某技能整个移出上下文) 或 Skill(name) 权限 deny 规则;我们只文档说明,不自动改用户设置。
    • hooks(SessionStart / UserPromptSubmit 注入 additionalContext)是唯一「必须发生」的强制层; 本轮没做——它要写用户的 Agent settings,代价是侵入用户配置。
  • 路由触发率:已分层量化,但样本很小(决策探针,不是执行成功率)——方法:起全新会话(中立 cwd, 不读本仓库),给真实口吻的多步浏览器任务,只让它报「打算怎么做」、不许执行;判定「计划里是否走 ego-decision-layer」。
    • 交互式会话:5/5 主动走 ego-decision-layer(当时只有同名接管 + 自身技能两层,没开 always-on; 含两条不含「点击/翻页」字眼的问法)。开启 always-on 后复测 2/2,无回归。
    • 子代理 / 一次性无会话上下文:0/6(开 always-on 之前是 0/4)。探针确认这类上下文里 既没有技能清单、也没有任何 AGENTS.md 内容——always-on 那行到不了它们。所以把浏览器活 派给子代理时,必须在 handoff 里显式写「用 ego-decision-layer CLI」,否则它不会自己选。
    • 注意事项:n=5/6、单机单模型、探针只报计划;这不能外推成「真实执行成功率」。
  • 跨域 iframe 不处理:读不到 contentDocument,这类树不在观测范围内。
  • 新建标签页视口 0×0 是本机常态,引擎默认自动撑起:本机 ego lite 0.5.1.13 上,taskSpace 新建的标签页在未导航 / domcontentloaded / load 之后 innerWidth/innerHeight 都是 0×0, page.info() 也为空;覆盖是 per-space/per-page 的,新开的 space 仍是 0×0(不跨运行生效)。 元素表按视口可见性构建 → 0×0 时恒为空,所以循环入口检测到 0×0 会自动 Emulation.setDeviceMetricsOverride 撑起 1280×900@1 后照常跑(视口正常时零额外 CDP); --force-viewport <宽x高>[@缩放] 指定尺寸,--no-force-viewport(库 strictViewport)才改为 直接以 viewport_degraded 失败。症状与来源由另一个 Agent harness(Hermes Agent)在本机真实运行中发现, 细节见 SKILL.md 的「边界(实测)」。 Emulation.clearDeviceMetricsOverride 在本机 0.5.1.13 上实测不把视口回退(同进程调过之后仍显示覆盖值); CLI 退出时会再读一次视口并如实报告,不谎报“已清除”。
  • frame 祖先带缩放/旋转时直接拒绝:frame 内坐标换算会失真,所以宁可不点。 frame 元素到文档根的祖先链上有非 identity 的 2D 线性变换(scale/rotate/skew)或 zoom !== 1 时记 frame_transformed;纯平移、translateZ(0) 这类只影响合成的写法放行。 跨 frame 命中测试逐层做:每层 elementFromPoint 必须严格命中承载下一层的 <iframe> 自身, 任一层被遮挡即 covered、0 次派发;frame 链断记 frame_unresolved。这是有意的 fail-closed 取舍。
  • 危险动作词表是启发式:命中「支付/删除/退订」一类目标时不执行并直接停(dangerous_action), 但词表是我们自己拟的中英词表,remove / pay 这类词可能误伤,站点改版后可能要调; dangerGuard: false 可整体关闭。
  • 降级路径默认关闭,且没有真实第二后端验证:TYPESAFE_FALLBACK_BASE_URL 不设就不降级, 机制只用假端点验证过。
  • 真实验证码/登录墙未测(只在合成拦截页上验证过 blocked 分支)。
  • 旧的「维基语言选择器 2/3」基线元素已变:www.wikipedia.org 的 77 项 #searchLanguage 现在是 opacity:0(被自定义语言列表 UI 取代),引擎按可见性规则跳过它。同类任务在 DDG 设置页 语言下拉实测 6/6(bench/test-native-select.mjs)。
  • 原生下拉的「选中项不在当前 options 里」有了一次重问:选项在观测与执行之间被 JS 重建/重排时, 不再当失败/无进展,而是一次带新选项的重问(maxOptionRetries 默认 1),重问仍失败才报 stuck。
  • 默认的自建 DOM 元素表覆盖自定义控件,旧快照路径不覆盖:实测 DuckDuckGo 设置页 DOM 有 18 个复选框,默认 observe: "dom" 路径下 18 个全部进元素表(视口内 5 个;拉高视口后 18 个); observe: "snapshot" 路径仍是 0 个(1×1 的自定义样式 input 不进辅助树)。 部分站点的复选框在快照里既无定位器也无名称,只能按文档顺序兜底补齐; 仅当数量完全一致时才敢用,否则显示「勾选态未知」而不会谎报。
  • 浏览器自动翻译会影响判断:实测页面被译成中文后,元素名与选项名与目标语言不一致。 Jev 跨语言选择正常,但 --until / check 用 UI 字符串比较会误判——请比对 URL 路径或 DOM 状态。
  • ego 运行时会静默吞掉两件事(排查时很坑): 静态 import ... from "node:http" 会让整个脚本无输出、exit 0(必须用 await import()); 运行时不能起服务也不能访问 loopback(fetch("http://127.0.0.1:...") 会挂起后 exit 0)。
  • 运行时拿不到自定义环境变量,且 process.cwd() 是 /:export FOO=bar 在脚本里读不到, 相对路径也不能用。要传配置只能在父进程把值替换进脚本文本(本项目的 CLI 就是这么做的)。
  • Jev 走完不等于业务正确,最终页面状态仍要按 ego-browser skill 的观察纪律复核。

测量与复跑基准

所有数字都来自本机真实运行(macOS + ego lite 0.5.0.32)。请求里写的是浮动别名 jev-latest,服务端实际服务哪个版本只有响应里的 model 字段能回答——每次测量都要记下它 (renderJevSummary 会打印)。2026-09-26 曾出现约 5 分钟 403 RBAC: access denied (凭证文件完好、随后自愈):环境本身会变,只记「能跑通」不够。

方法:同任务、同元素表、同验证器,「交替 3 轮取中位数」。 A = ego-decision-layer 单进程闭环;B = 经典循环(每步一个独立进程 + 大模型 kimi-k3 思考)。 测于 2026-09-19。

任务 A(ego-decision-layer) B(经典循环) 结果
Hacker News 两步复合导航 中位 4.9s(1 进程,12 次浏览器调用) 中位 9.7s(3 进程) 约 2.0×
维基百科搜索(两组都要生成文本) 中位 5.4s(1 步) 中位 10.1s(2 进程) 约 1.9×

样本只有 3 对/任务且方差很大(经典组单轮 7.3s–22s,上表是不同批次里更好的那批),不构成基准; 只能说量级上 Jev 闭环约为经典循环的一半时间。

省在哪里(实测分解):

  • ✅ 决策往返:Jev 决策请求约 0.35–0.52s/次(2026-09-26 实测,服务端 jev-1.13.0, 10 次采样 352–524ms、中位 434ms),可用大模型 1.6–4.5s/次。整步(观测+决策+执行+校验)约 1.0–1.4s。
  • ✅ 每步退出浏览器上下文:B 每步一个新进程,A 全程 1 个(进程启动实测仅 250–350ms/次,不是主要成本)
  • ✅ 省浏览器动作(引擎重建后新增,现在是最大收益项):观测是一次 page.evaluate 自建 DOM 元素表(约 2–4ms / ~2k 字符),动作走裸 CDP(13–16ms); 旧路径是 page.snapshot() 110–130ms / 27484 字符、page.click(ref) 788–1005ms

分阶段数据显示当前单步的大头是「派发 + 稳定等待」0.56–0.99s,而不是决策(0.35–0.52s)。 目标能用选择器写死时,直接写代码比两者都快。

引擎重建后(2026-09-22)

按剖析结果重建,不是按猜测——真实瓶颈是 ego 的语义动作通道,不是快照。 同任务隔离实验(5 臂 × 3 任务 × 3 次,全部 3/3 成功):

任务 重建前 重建后
Hacker News 两步导航 4569ms 1916ms
httpbin 表单(填写+勾选+提交) 6782ms 3607ms
维基搜索(含文本生成) 3663ms 3634ms(受模型延迟主导,无变化)

HN 那一行是 A4 臂(含响应校验/提示词规则/执行前守卫);只加「自建元素表 + 裸 CDP 动作」的 A3 臂 是 1675ms。两档都记在 PORT-REPORT.md,原始数据在 bench/raw/。

与 browser-harness + jev-ultrafast 的预登记配对验证(5 任务 × 2 栈 × 10 轮 = 100 轮, bootstrap 95% CI,判定规则跑前写死):

任务 结论
HN 点击链 本体更快 −378ms,CI[−1453,−313],10/0
维基搜索 本体更快 −819ms,CI[−1314,−195];且只需 1 次 Jev 决策(对方 3 次)
表单填写 无差异(CI 跨 0)
原生下拉 对方更快 +248ms,CI[163,426]
翻页(目标在文档序 110/119) 两栈都完不成 —— 能力边界,非速度问题

另外:滚动若真的移动了视口或露出新元素就算进展 —— X 上必须连滚 >3 次的深帖任务 0/6 → 6/6。 详见 VERIFY-REPORT.md,每个数字都能追到 bench/raw/。

复跑

cd examples/bench
# 编辑 task.json(目标/URL/验证子串),然后:
./run-pair.sh A                 # ego-decision-layer 单进程闭环
./run-pair.sh B kimi-k3         # 经典循环:每步一个进程 + 大模型

基准脚本需要 OpenCode Go(或任何 OpenAI 兼容网关)的凭证,路径写在脚本里,按需修改。

历史 A/B 对照的报告(VERIFY-REPORT.md、PORT-REPORT.md、REVEAL-REPORT.md、BH-PORT-REPORT.md)里, B 臂是 browser-harness + jev-ultrafast。它的引擎已经移植进 scripts/decider-loop.mjs,宿主 bh 也已移除, 所以驱动脚本已撤出仓库(在 git 历史里,如 git show 599a49b:bench/run-b.py)。 已发布的 B 栈数字仍可复算:原始数据在 bench/raw/,bench/analyze-*.mjs 会从它重算表格。

现在只剩 A 臂,编排脚本与它自带的预检:

bash bench/verify.sh --check-env        # 预检(0 = ego-browser 就绪)
bash bench/verify.sh 10                 # 5 任务 × 10 轮,结果落 bench/raw/
--a-only                               # 旧命令,仍接受(现在只有 A 臂)
BENCH_OUT_DIR=/tmp/x bash bench/verify.sh 1   # 或写到别处,不污染仓库

仓库结构

SKILL.md                 技能本体(刻意放在根目录——`npx skills add` 就是找它;也是版本号唯一来源)
CHANGELOG.md             版本历史(顶部条目必须与 SKILL.md 的 metadata.version 一致)
AGENTS.md                给其他 Agent 的安装/验证指令(可直接粘贴的 prompt 在里面)
scripts/decider-loop.mjs  引擎
scripts/ego-decision-layer CLI(任务操作、抽取;update 更新当前安装,--version 查看版本)
scripts/update.sh        更新器(Git fast-forward / skills 定向更新,带退出码与本地修改保护)
ROADMAP.md               演进规划、阶段实现与验证边界
scripts/wire-agent-skills.sh   接管/刷新官方 ego-browser 入口;--check / --restore / --ensure / --status-json / --always-on
overlay/ego-browser/     路由层的模板(接管时渲染到 Agent 技能目录)
.claude-plugin/          Claude Code 插件元数据(plugin.json / marketplace.json)
skills/ego-decision-layer/  插件技能目录(SKILL.md / scripts / overlay 都指向仓库根的软链)
docs/                    demo 素材与重做脚本(banner.svg / demo.gif / capture-demo.mjs …)
examples/bench/          A/B 对照基准脚本(CLI 闭环 vs 每步大模型)
bench/verify.sh          A 臂验证编排(--check-env 预检;结果落 bench/raw/ 或 BENCH_OUT_DIR)
bench/test-*.mjs         离线/在线测试(含 test-release-consistency.mjs、test-no-bh-dependency.mjs)
install.sh               手工安装(接 CLI 进 PATH、准备凭证;**默认接管入口**,--no-wire 跳过)
update.sh                兼容更新入口(转发到 scripts/update.sh)

致谢

  • citrolabs/ego-lite(MIT)—— 本项目的运行基础。 根目录的 SKILL.md 是本项目自带的附加技能,装在应用包之外,不是对它的文档做的修改
  • browser-use/jev-ultrafast(MIT, Copyright (c) 2026 Browser Use) —— 本项目的响应校验、动作执行器、观测层元素表、提示词规则与整体架构部分由该项目翻译/改写而来。 许可声明见 THIRD-PARTY.md;分级依据与并排证据见 THIRD-PARTY-ASSESSMENT.md 与 bench/raw/third-party-excerpts.md
  • TypeSafe —— Jev / System One
  • 同类项目与上游一览:docs/ECOSYSTEM.md(中立清单,只引用各项目自己的 GitHub About 与同一套 API 可复算的公开计数)

本项目没有再分发 ego-lite 的任何文档或代码;skill/ 目录下的历史章节草稿仅包含我们自己撰写的内容。

License

MIT,见 LICENSE。

About

Pluggable decision layer for the ego lite browser: one System One (Jev) call per step replaces the per-step LLM turn, and the backend can be swapped for a local OpenAI-compatible model. Fail-closed execution guards. The measured one — raw bench data, 16 suites, changelog with corrections.

Topics

Resources

Security policy

Stars

28 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages