dev、start、preview 和 build 运行,都会在每次编译时原子地写入 dist/extension-js/<browser>/ready.json。当前契约是 schemaVersion: 2。
状态
两阶段就绪
status: "ready" 只意味着编译完成,仅此而已。浏览器可能还在启动,service worker 也可能还没有连上。
act 类工具(eval、storage、reload、open、inspect)需要第二个阶段。要等到契约里带上 runtime: "attached" 和一个 executorAttachedAt 时间戳之后,再去驱动扩展。
attach 这个戳是幂等的,并且能挺过重新编译。一次 attach 也会清除之前的 extension_load_refused 状态,因为执行器就跑在被托管的浏览器里面。
字段参考(schema v2)
始终存在的字段:
在已知时才出现的字段:
错误状态
code 字段给失败类别命名。对自动化来说有三个代码要紧:
一次加载被拒会活过下一次成功编译。只有一次新的运行(
starting)或者一次真正的执行器 attach 才能把它清掉。
用 —wait 等待
extension dev --wait 和 extension start --wait 每 250 毫秒轮询一次契约,并在它报告 ready 时退出。配合 --output json 可以拿到机器可读的结果。
等待循环拒绝相信过期文件。每次读取都会跑三项检查:
command字段必须与正在等待的命令一致。pid必须还活着。对dev来说,生产者已死就一定意味着文件过期,所以轮询会继续。- 对
start来说,只有当契约足够新鲜时,才接受一个已死的 pid。新鲜的意思是ts、compiledAt或startedAt在最近 60 秒之内。
E_READY_TIMEOUT 退出。处于 error 状态的契约会带着它的 message 让等待失败。
把会话文件连起来
同一个目录里还放着events.ndjson(编译时间线)和 logs.ndjson(扩展的控制台输出)。这两个文件里的每一行都带着来自 ready.json 的 runId。
events.ndjson 在每次运行开始时被清空,所以它永远只描述当前这次运行。事件类型有 compile_start、compile_success、compile_error 和 shutdown。
示例
下一步
- 用结果信封读取命令结果。
- 用生命周期流把同一个会话作为帧来流式读取。
- 用 Playwright E2E 把整套流程接进测试。

