wai-play
面向 vibe coding 网页游戏作者的自动试玩 + 质量诊断 agent,在真实浏览器里像玩家一样把游戏打通关并出评测报告
§ 01定位
wai-play 是面向"用 vibe coding 快速做网页游戏"的人的自动试玩 + 质量诊断 agent。给它一个游戏 URL(可选传 ZIP 源码),它在真实浏览器里把游戏当作要通关的任务去玩,记状态、截图、录像,最后出五维评分 + 可复现的问题卡片 + 优化建议[1]。它本身就是一个在浏览器里跑的 agent,所以下面几条决策能干净地挂在 Harness 层上——和 goal-flow 一致,与上上篇 Wallfacer(层标签留空)相反。
§ 02它实现了什么 · 怎么运作
- 接入检查(先卡门):开测前它先验游戏能不能测。它要求游戏在页面里暴露一个测试接口
window.GameFlowIntegration,里面有observe()(读当前状态)、availableActions()(有哪些动作)、step(action)(执行一个动作)、evaluate()(返回{done, success, failed, reason})、reset()等函数;checkScenarioPreconditions校验必需的状态字段在不在,缺了就向游戏要一个repairPlan补齐。没有这套绑定,它直接抛错"请接入真实动作处理逻辑",拒绝硬测[5]。 - 建游戏模型:
SourceGameModelBuilder读游戏源码(如果给了 ZIP)抽出通关约束、目标描述、可用动作规则(带ai_used标记说明用了大模型分析源码),配合首屏观察建出一个游戏模型;再由build_completion_plan生成一份带route_plan(通关路线)和replan_when(什么情况该重规划)的通关计划[3]。 - 试玩循环:每一步分观察相位和动作相位。拿到要执行的动作后,经浏览器适配器执行——优先调游戏 API 的
step(action)(动作串如MOVE_RIGHT、ATTACK),没有 API 才退回_fallback_step用 Playwright 的page.keyboard.press/page.click模拟键鼠[2];执行后调evaluate()拿成败,再判断要不要停[3]。 - 感知(它怎么知道现在game怎么样):优先读游戏 API 的
observe()拿血量/分数/进度这些结构化状态;同时截图(page.screenshot)、扫 DOM 里的script、录屏、注入window.__gameflowBrowserMetrics采帧率和卡顿、监听console/pageerror抓报错[2]。接口在时,状态是确定的;接口缺时,只能靠动作前后的视觉差分和 DOM 启发式来近似猜状态变了没[2]。 - 失败重规划:一次尝试没通关,它做两层重规划——中途连续 N 步没进展就重新问 AI planner;整次失败后
_analyze_attempt_failure抽出失败原因、错误签名、最后几个动作,喂给下一次尝试;最多 20 次自适应重试[3]。为省成本,它不是每步都问大模型:决策优先级是"高优 skill 动作 > 还在跑的 AI 计划 > 新叫一次 AI planner > 规则兜底",只有卡住了(_should_consult_ai_planner)才叫 LLM[3]。 - 出报告:整条 trace 跑完,先由 rater 打五维分,再由 reporter 出报告——问题卡片绑证据(状态变化 / 截图 / ≤20 秒录像),同一问题只展示一次[1];评分刻意把"测试可信度"(API 接入、证据完整度、agent 操作可靠性)单列出来,不混进游戏质量分[1]。
打个比方:把它想成一个第一次玩这游戏、手边没有存档、也不能任意重开某一关的玩家——它只能从头打,边打边猜规则,输了复盘再从头来,最多来 20 次。下面三条决策都能对回上面这些机制。
§ 03我的初判 vs 实际
初判(Vivian,两段式): - 产品读:游戏测试复杂、流程长,非专业人士难上手、更难一次测全;它给这群人做游戏产品的自动化测试。 - 推导的花样位置:浏览器操控——操控不够精准/自然,它报的"bug"可能是它自己操控失误、而非游戏的问题;所以必须把操控做到接近人类水平,测试才有意义。
对照下来——这篇的差值很值钱:
- 你把中心风险找对了,这是真本事。 "怎么知道一个报出来的 bug 是游戏的错、而不是测试器操控失误?"——这确实是这类产品的命门,你纯从产品逻辑就推到了它。
- 但你押的解法(把操控做到人类级)恰恰是它故意绕开的路。 浏览器操控这块,它交给了 Playwright——一个成熟的浏览器自动化库,点击按键本身很可靠,不是前沿难题[2]。面对"操控/感知不可靠"这个你担心的风险,它的工程答案不是"把手练到完美",而是从三个方向降低对这只手的依赖:
1. 把成败判定权搬进游戏自己暴露的接口(决策一):要求游戏实现 observe/step/evaluate,"通关没通关"由游戏亲口报,而非 agent 看画面猜;没接口就拒测[5]。
2. 操控分层:有接口时走确定性的 step(action),没有才退回近似的键鼠 + 视觉差分[2]。
3. 把评分设计成对测试器的毛病不敏感(决策三):接口接得好不给游戏加分,只采信玩家能观察到的证据,并把测试器自己的可靠度单列出来[4][1]。
- 所以这篇给你的判断升级是:面对一个不可靠的能力,工程上的第一反应往往不是"把它做准"(常常做不到),而是"减少对它的依赖"——靠契约把活推给环境、靠分层在能确定时就确定、靠稳健的度量让结论不被工具的毛病带偏。 你的产品直觉指对了病灶,拆解补上的是"药方长什么样"。
- 另外,和 goal-flow 那篇同一个规律:这产品真正最难的一块,你的产品视角没推到——是那个"没有存档、不能模拟的环境里,靠观察诊断失败、整体从头重跑"的通关 agent loop(决策二)。
§ 04关键设计决策
要求游戏暴露测试接口,没有绑定就拒测,而非硬做黑盒
- 对回机制
上一节的接入检查——游戏须实现
window.GameFlowIntegration(observe/availableActions/step/evaluate/reset);适配器优先调window.GameFlowAgentAPI.step(action);checkScenarioPreconditions校验状态字段,缺则要repairPlan;无绑定直接抛错"请接入真实动作处理逻辑"[2][5]。 - 证据
[2][5]
- 增量(README 不会直说的)
README 的口径是"给个 URL 就能黑盒试玩,传 ZIP 源码会更准"——把接口/源码说成锦上添花。但代码显示,可靠的那条路要求游戏本身实现测试接口:接口在,状态和成败是确定的;接口不在,只能退到视觉差分 + DOM 启发式的近似模式,再没有动作绑定就干脆拒测[2][5]。也就是说,它真正的可靠性契约是"游戏得配合"。这一步正面回答了你担心的风险:与其让 agent 从画面里猜"我赢没赢"(会把 agent 的误判算成游戏的 bug),不如让游戏用
evaluate()亲口报成败,把 ground truth 从 agent 手里挪到游戏手里。 - 代价
可靠性是拿"能可靠测的游戏范围"换来的——它更适合作者给自己(能改代码、愿意接一个测试接口)的游戏做测试;对一个纯 URL、画面全在 canvas 里、没接口的陌生游戏,它只能退到近似模式,可信度打折。README 里说的"给个网址就能测任何游戏"在这条路上是降级的。
- 可迁移判断
当 agent 对原始环境的感知或操作不可靠时(视觉识别、模拟键鼠),一个稳的做法是把"成没成、对不对"的判定权搬进环境自己暴露的接口契约里,并在没有契约时拒绝硬来。给任何 agent 产品做验证/测试类功能时,先问一句:成败信号是 agent 自己看出来的,还是被测对象亲口报的? 后者才经得起追问。
在没有存档、不能模拟的环境里靠观察诊断失败、整体从头重跑,并把贵的推理藏在便宜的默认后面
- 对回机制
test_game的多次尝试 +_test_single_attempt的步循环;_analyze_attempt_failure把失败原因/错误签名/最后动作传入下一次;_should_consult_ai_planner门控 LLM 调用,决策优先级"高优 skill > 在跑 AI 计划 > 新 AI 计划 > 规则兜底"[3]。 - 证据
[3]
- 增量
README 只有一句"首次路线失败就按真实状态倒推重规划,不盲目重复"。代码里这其实是一套三级重规划:中途停滞时重问 planner、整次失败后把失败分析喂给下次、最多 20 次自适应重试。更关键的一层限制代码自己暴露了——它没有模拟器、没有状态回滚,重规划只能靠从噪声观察里诊断"上次为什么卡住",然后从头再跑一遍,指望游戏够确定、前几步能回到同一个岔路口[3]。所以这产品真正最硬的地方在这儿:让一个陌生游戏被从头打通关,而手里既没有它的世界模型、也不能跳到任意一关。同时它有一层成本设计:不是每步都叫大模型,只有卡住了才升级到 LLM planner,平时走便宜的规则执行[3]。
- 代价
"从头重跑 + 指望确定性"这条路,对带随机性或流程很长的游戏容易失效;20 次尝试 × 每次多步会烧 token 和时间,所以才要那道"卡住才叫大模型"的门控来压成本。
- 可迁移判断
在一个不能存档、不能模拟的环境里让 agent 达成目标,重规划只能建立在"从观察里诊断失败 + 把失败教训带进下一次整体重跑"上,且要接受"能不能回到同一个岔口取决于环境有多确定"。另外那道"贵推理(大模型 planner)藏在便宜默认(规则执行)后面、卡住才升级"的门控,和你 AI Radar 的双模型路由是同一个成本模式——能用规则/小模型先扛的,别每步都惊动大模型。
把评分设计成对测试器自身的毛病不敏感,并把测试器可靠度单列出来
- 对回机制
上一节出报告那步——五维加权评分,加上"测试可信度"被单独拎出来展示、不混进质量分[1][4]。
- 证据
[1][4]
- 增量
这是对你那个风险的第二重、也更隐蔽的回答。它不去假设"测试器是完美的",而是把评分本身设计成经得起测试器不完美:
scoring_standards.py里写死了"API 接入完整度不计分""内部 API 数值变化不能单独作为高分依据",反馈维只采信"玩家可见、可听或可从录像确认"的反馈、排除只在内部 API 里发生的变化[4];再把测试器自己的可靠度(API 接入、证据完整度、agent 操作可靠性)作为一个独立的轴报出来,让你自行打折[1]。一句话:它追求的是一个诚实、会亮出自己置信度的测试器,而不是假装一个完美的测试器。 - 代价
这要一套克制的评分规则去维护;而且"只算玩家可见的证据"会让一些只在内部状态里冒头的真 bug 被折价、甚至漏掉。
- 可迁移判断
当你没法保证测量工具本身准,别只想着把工具修准——①把指标设计成对工具已知的毛病不敏感(只采信玩家能观察到的证据,不让"接口接得好"抬高游戏分),②把工具自己的可靠度作为一个独立的数报出来,让读的人自行打折。这条对任何"用 AI 当裁判"的评测系统都成立,包括你 AI Radar 自己给产品打分那套——一个敢亮出置信度的评测,比一个只给结论的评测更可信。
§ 05市场与需求
- 需求判断和你一致(推断):它服务用 vibe coding 做网页游戏的人,这批人往往不写自动化测试脚本,却要回答"这游戏能不能从头玩到通关、玩法顺不顺"[1]。
- 但它的适用边界被决策一钉住了(推断):要可靠测,前提是游戏接了
GameFlowIntegration接口。所以它更贴合"作者自己(能改代码、愿意接个测试接口)测自己的游戏",而非"随便丢个网址就能测任何游戏"。README 的路线图也承认,要做"多用户隔离、任务队列、远程 URL 安全限制"才谈得上对公众开放[1]——现在它是个本地自测工具。 - 一个更一般的呼应:它把"测试器可靠度"单列给人看,本质是承认自动化评测不完美、并把不确定性透明化。做 AI 产品时,评估任何"AI 自动评测 / AI 打分"类功能,都可以拿这把尺子问一句:它敢不敢把自己的置信度亮出来?
§ 06证据清单
- README(wai-play,已由管线抓取):自动试玩 + 质量诊断 agent;给 URL、可选 ZIP 源码;工作流(选类型→给 URL/源码→检查可测→建游戏模型→真实试玩 + 失败重规划→出报告);测试可信度诊断(API 接入 / 证据完整度 / agent 操作可靠性)单独展示、不混进质量分;问题卡片绑证据、同一问题只展示一次;Playwright/chromium、Streamlit、DeepSeek+Kimi;入口
app.py/agent/orchestrator.py/web/web_game_adapter.py/agent/scoring_standards.py/integration_templates.py— https://github.com/waiterve/wai-play - web/web_game_adapter.py:控制经 Playwright(
page.keyboard.press/page.click),主控路径优先调window.GameFlowAgentAPI.step(action)(动作串MOVE_RIGHT/ATTACK),无则_fallback_step键鼠;感知优先GameFlowAgentAPI(getGameInfo/observe/availableActions/evaluate),另有page.screenshot、DOM/script 扫描、录屏、注入window.__gameflowBrowserMetrics采帧率/长任务、console/pageerror监听;API 在时确定性、缺失时靠视觉差分 + DOM 启发式近似 — https://github.com/waiterve/wai-play/blob/main/web/web_game_adapter.py - agent/orchestrator.py:
test_game多次尝试(baseline + 至多 20 次自适应重试)+_test_single_attempt步循环(观察相位→动作相位→step→evaluate→stop_decision);SourceGameModelBuilder读源码抽约束/目标/动作规则(ai_used);build_completion_plan出route_plan+replan_when;三级重规划(停滞中途重规划、跨尝试_analyze_attempt_failure把failure_reasons/error_signature传入下次);决策优先级 高优 skill > 在跑 AI 计划 > 新 AI 计划 > 规则兜底 > skill 推荐,_should_consult_ai_planner门控 LLM;无模拟器 / 无回滚,靠观察诊断 — https://github.com/waiterve/wai-play/blob/main/agent/orchestrator.py - agent/scoring_standards.py:五维加权(核心流程 0.24 / 核心玩法 0.26 / UI 0.20 / 反馈 0.15 / 技术 0.15);"API 接入完整度不计分""内部 API 数值变化不能单独作为高分依据";反馈维只算"玩家可见 / 可听 / 可录像确认"的反馈、排除内部 API 变化;六档评分带 — https://github.com/waiterve/wai-play/blob/main/agent/scoring_standards.py
- integration_templates.py:游戏须暴露
window.GameFlowIntegration(observe/availableActions/step/evaluate/reset,选配jumpToScenario/evaluateScenario/repairScenario);checkScenarioPreconditions校验前置状态字段,缺则求repairPlan;无绑定则抛错"请接入真实动作处理逻辑",拒绝黑盒模拟 — https://github.com/waiterve/wai-play/blob/main/integration_templates.py