工作原理

natural-language task ──▶ planner (LLM, 1 call) ──▶ JSON action plan

       trajectory cache ◀── cheap verification ◀── deterministic executor

             └──▶ subsequent runs: zero LLM, ~1s, $0

最昂贵的部分 —— 弄清楚该执行哪些浏览器操作 —— 只发生一次,并被转化为缓存的、可验证的数据。

  • 计划是数据,而非代码 —— 经过 schema 校验的 JSON;没有生成的脚本,没有条件分支。
  • 廉价验证 —— 每个操作之后检查 DOM/URL 后置条件。验证失败会使缓存的计划失效,并触发一次自动重新规划。
  • 站点地图 —— 每次执行都会补充一张页面与跳转的图;windup scan 在首次运行前就直接从你的源代码为这张图播种,因此规划器使用的是你应用的真实选择器,而不是靠猜。
  • 片段(Fragments) —— 经过验证的操作块(例如登录),规划器通过 { "type": "use" } 组合它们,而非重新生成。
  • 零硬编码的站点知识 —— 引擎懂的是各类框架和 Web 平台,从不懂你的站点。所有站点知识都作为输入(场景、配置、清单)到来,或在运行时被发现。

为什么选 Windup

手写脚本运行成本低,但维护成本高。每次运行都调用 AI 的智能体易于编写,但速度慢且不确定。Windup 各取二者之长。

手写脚本每次运行都用 AI 智能体Windup
编写方式手写代码 + 选择器纯自然语言纯自然语言
运行成本$0每次运行都调用 LLM首次运行调用 LLM
运行速度慢(模型在回路中)~1s 回放
确定性低 —— 每次即兴发挥高 —— 每次回放都是同一份计划
应用发生变化你去修脚本可能悄无声息地做别的事验证失败 → 自动重新规划

缓存买到的是 $0,而不是”瞬时”。 一次缓存命中会跳过 LLM 的规划plan=0msllm_calls=0)—— 但计划中的 Playwright 动作仍然会运行,任何 depends_on 链路也仍然会执行,因此实际耗时是真实的浏览器时间,而不是一次查表。每次运行都会报告明细 —— total=… (plan=… deps=… exec=… setup=…) —— 其中 deps 是依赖链路,exec 是本场景的动作,setup 是浏览器上下文。HTML 报告将每个场景的耗时拆分为一条可对账的条形图(setup · deps · plan · nav · actions),其中 nav 是首个动作之前的 goto + 页面加载/水合 —— 通常是 SPA 中真正的时间消耗点(所以一个显示为 “3.6 s” 的 113 ms 动作,实际上是 setup + nav)。Windup 一旦页面渲染出可交互元素网络空闲便会继续推进,因此纯展示型页面不会卡在就绪超时上。套件标题显示的是实际耗时(wall-clock,真实经过时间),而不是各场景总耗时之和 —— 后者在 --concurrency N 下会膨胀约 N×。在并发下,每个场景的剩余时间会被标注为 contention(即”争用”:该场景在兄弟场景运行时等待 CPU/浏览器槽位所花的时间 —— 空闲,而非工作),并会显示一个 active ms 数值(它自身的活跃工作量,在不同并发下大致稳定),以便各场景保持可比。最大的杠杆是会话快照:一个依赖的认证状态(storageState)只捕获一次,并在之后的回放中恢复,因此登录流程不必为每个依赖它的场景重新运行(deps≈0)。

想深入了解运行机制 —— 模块边界、数据格式、成本与安全态势 —— 参见架构与规范