一套命令,驱动 Moli 轻内核
每个动作回读核实;做不到,就显式拒绝 —— 从不假装成功。
不需要 SDK,不需要写 Playwright 脚本。任何能跑 shell 的 agent 都能直接用;每条命令的输出都是机器可读的一行 JSON,出错时还有可执行的 hint。
下面的输出取自本机实测(本地测试页),只做了截短(…)。
下面每一张卡都是实测复现过的「看起来成功」。点卡片翻面,看 moli-control 怎么处理。
Chrome 默认会话里 Extensions.loadUnpacked 照样返回 id,但扩展根本没装上。
ext 只在 start --extensions 会话里可用;默认会话直接拒绝 extensions_disabled。
在轻内核上,编辑命令返回成功,但选区一动没动。
点击翻面 →无效就改走 JS 并标 mode: js;JS 也做不到(如 undo),报 edit_unsupported。
节点号只在子会话里有效,事件按视口中心派发 —— 报 ok,实际点在别处。
点击翻面 →现场挂子会话、按父文档偏移换算,派发前确认最顶层就是目标,被遮挡就拒绝。
冻结布局下 innerText 与几何不刷新,后加的节点点不中。
点击翻面 →读文本、坐标动作之前先重建布局;Chrome 后端恒为真实布局,跳过这一步。
closeTarget 是异步的,紧接着列标签页还能看到它。
直到目标真的消失才返回;超时给出四要素错误。
网络空闲超时、HTTP 404、空壳页,抓取都可能「成功」。
点击翻面 →标 best-effort / rc 22 / rc 5,调用方一眼区分「查过没事」和「根本没查」。
同一条命令,换一个 --backend 就换引擎。两端的差异全部由代码处理,并在输出里如实标注 —— 你不需要记住哪边有什么坑。
agent 只看见一个 CLI。会话管理负责拉起、核身份、到期回收;动作与观察层负责回读与显式拒绝;后端可以是 Moli(上游或自编内核)或受管 Chrome。
从一次性抓取到多步交互、网络拦截、设备仿真、站点原生工具(WebMCP)。外部的 Playwright / Puppeteer / Selenium 也能经 endpoint 直连同一个受管会话。
测试全绿不说明什么 —— 也许测试本身失效了。所以每修一个缺陷,就登记一条「变异」:把缺陷打回去,对应的测试必须变红。整轮全红才发版。
agent 浏览的页面不可信。受管会话默认多层收紧,并且每次体检都带正对照现场验证 —— 防护有没有生效,用打一次来证明,而不是靠相信。
端点只监听本机专用地址、随机端口,不对外暴露。
页面无法连回运行自己的那个实例。
会话到期自动回收,暴露窗口与存活时间成正比。
PID 复用也不会误杀、误连别人的浏览器。
受管会话剥掉代理环境变量,防护不会被隧道绕过。
支持指向自编的 Moli 内核(MOLI_BIN),doctor 报告内核级校验是否在位。
# 安装(需要 uv 与 Python ≥ 3.10) git clone <repo> ~/Code/moli-control && cd ~/Code/moli-control && uv sync bin/moli-ctl install --yes # 没有 moli 时:官方安装器 bin/moli-ctl doctor # 分层体检,期望全 pass # 一次性抓取(零监听端口) bin/moli-ctl fetch https://example.com # 交互会话 bin/moli-ctl --name job start --layout bin/moli-ctl --name job goto https://example.com bin/moli-ctl --name job snap bin/moli-ctl --name job click <ref> && bin/moli-ctl --name job wait-for 已提交 # 换成真 Chrome bin/moli-ctl --name real start --backend chrome --profile work