Recorder
Recorder 记录 Lynx 页面的运行时状态,用于确定性回放。产物包含模板加载、运行时输入和环境数据,方便在脱离原始应用环境后复现页面。它与性能 Trace 互补:Trace 用来分析执行过程和耗时,Recorder 用来重建当时的页面与运行过程。
agent-lynx 自带的 lynx-recorder skill 指导采集;lynx-recorder-fixture 则提供产物检查、解码和编辑工具。agent 可以先完成录制,再按需要继续检查文件。
从页面状态到回放产物
下面沿用 Tailwind CSS 的 Settings 页面,在打开页面后切换到 Ocean 主题。示例已连接应用,$CLIENT_ID 指选定的应用,bundle URL 可由设备访问。
对话重点是采集边界和产物检查:先开始 Recorder,再打开页面,才能把回放需要的 loadTemplate 一并保存。主题切换只是这次需要重现的页面状态。
把 Settings 页面打开后切换到 Ocean 的过程保存成 Recorder 回放文件,我要用它复现这个页面状态。
思路:先读取录制 skill,确认回放需要的初始化数据从什么时候开始采集。
agent-lynx skills list找到两个相关 skill
# 节选录制与产物检查 skill:先创建回放文件,再检查其内容。
agent-lynx skills list<available_skills>
<skill>
<name>lynx-recorder</name>
<description>Record Lynx page interactions into a TestBench replay file using agent-lynx. Use when asked to start or stop a recording, capture page interactions for replay, or troubleshoot recording capture. For inspecting or editing an existing fixture, use lynx-recorder-fixture.</description>
<location>/tmp/agent-lynx-perf-docs-20261030/node_modules/@lynx-js/skill-lynx-recorder/SKILL.md</location>
</skill>
<skill>
<name>lynx-recorder-fixture</name>
<description>Inspect, decode, edit, and re-encode existing Lynx Recorder / TestBench fixtures. Use to analyze recordings, change mock responses, Action List, Callback, or Config, and troubleshoot replay inputs. Use lynx-recorder to create a new recording.</description>
<location>/tmp/agent-lynx-perf-docs-20261030/node_modules/@lynx-js/skill-lynx-recorder-fixture/SKILL.md</location>
</skill>
</available_skills>agent-lynx skills get lynx-recorder需要包含 loadTemplate
# 节选录制流程:先 start,再打开页面,最后检查 savedFiles。
agent-lynx skills get lynx-recorder## Workflow
1. **Start before opening the page.** Run `recorder start`. Capture must begin *before* the target page loads so the recording includes `loadTemplate`.
2. **If `start` reports `restartRequired: true`**, `enable_debug_mode` was just enabled — restart the app and run `recorder start` again (see Notes).
3. **Open and interact.** Open (or reload) the target Lynx page and perform the interactions to capture.
4. **Stop and save.** Run `recorder end --output ./my-recording.json`. Report the absolute path(s) returned in `savedFiles` to the user.
…
Skill directory: /tmp/agent-lynx-perf-docs-20261030/node_modules/@lynx-js/skill-lynx-recorderagent-lynx recorder start录制已开始
# 先开始 Recorder,确保随后打开页面时的模板加载进入录制。
agent-lynx recorder start --client "$CLIENT_ID"{
"success": true,
"started": true,
"restartRequired": false,
"message": "Recording started successfully. Open or reload a Lynx page before `recorder end`."
}agent-lynx open新页面 session 3
# 录制开始后打开 Settings;从响应中提取新页面的 session 3。
agent-lynx open 'http://127.0.0.1:33227/main.lynx.bundle?fullscreen=true' --client "$CLIENT_ID" | jq '.data.data'[
{
"session_id": 2,
"type": "",
"url": "http://127.0.0.1:33227/main.lynx.bundle?fullscreen=true"
},
{
"session_id": 3,
"type": "",
"url": "http://127.0.0.1:33227/main.lynx.bundle?fullscreen=true"
}
]agent-lynx snapshotOcean 是 @e15
# 读取新页面中的元素引用;这里节选包含 Ocean 按钮的主题区域。
agent-lynx snapshot --client "$CLIENT_ID" --session 3@e1 [scroll-view] @(207,450) {scrollable}
└─ @e2 [view] @(207,460)
├─ @e3 [view] @(207,70)
│ ├─ @e4 [text] "Settings" @(207,59)
│ └─ @e5 [text] "Manage your account and preferences." @(207,86)
├─ @e6 [view] @(207,177)
│ ├─ @e7 [view] @(207,153)
│ │ ├─ @e8 [text] "Theme" @(207,143)
│ │ └─ @e9 [text] "Switch design tokens at runtime via CSS variables." @(207,167)
│ └─ @e10 [view] @(207,207)
│ ├─ @e11 [view] @(91,206)
│ │ └─ @e12 [text] "Dark" @(91,206)
│ ├─ @e13 [view] @(207,206)
│ │ └─ @e14 [text] "Light" @(208,206)
│ └─ @e15 [view] @(324,206)
│ └─ @e16 [text] "Ocean" @(323,206)agent-lynx tap @e15已点击 Ocean
# 在录制期间触发主题切换,让运行时输入进入回放数据。
agent-lynx tap @e15 --client "$CLIENT_ID" --session 3Tapped @e15 at (324,206). Re-run `agent-lynx snapshot` before using refs again.agent-lynx recorder end含模板加载的回放产物
# 结束录制,并读取实际返回的 savedFiles;运行时可能按 session 拆分文件。jq 保留文件路径和完整诊断。
agent-lynx recorder end --client "$CLIENT_ID" -o ./settings-recording.json | jq '{success, savedFiles, diagnostics}'{
"success": true,
"savedFiles": [
"/tmp/agent-lynx-perf-docs-20261030/settings-recording-session3.json"
],
"diagnostics": [
{
"file": "/tmp/agent-lynx-perf-docs-20261030/settings-recording-session3.json",
"fileSizeBytes": 80792,
"healthy": true,
"actions": 13,
"hasTemplate": true,
"functionDistribution": {
"setThreadStrategy": 1,
"updateViewPort": 2,
"setGlobalProps": 1,
"loadTemplate": 1,
"SendCustomEvent": 1,
"sendGlobalEvent": 2,
"SendTouchEvent": 3,
"sendEventAndroid": 2
},
"verdict": "Valid recording — includes template load and interaction data"
}
]
}思路:诊断确认文件包含模板和运行时输入。再加载 fixture skill,检查保存下来的文件结构。
agent-lynx skills get lynx-recorder-fixture使用 fixture 摘要脚本
# 节选 fixture 检查入口;该 skill 提供本地解码与摘要脚本。
agent-lynx skills get lynx-recorder-fixture## Inspect and edit
The tool requires Python 3 and uses only the standard library. `decode`, `summary`, and `roundtrip` accept a local file or HTTP(S) URL; `encode` accepts a local decoded JSON file.
```bash
SKILL_DIR="<directory containing this SKILL.md>"
SOURCE="./recording.json"
# Start with a summary to identify the sections to inspect.
python3 "$SKILL_DIR/scripts/fixture_tool.py" summary "$SOURCE"
# Decode when you need to inspect or edit the contents.
python3 "$SKILL_DIR/scripts/fixture_tool.py" decode "$SOURCE" -o decoded.json
# After editing decoded.json as requested, write a new encoded file.
python3 "$SKILL_DIR/scripts/fixture_tool.py" encode decoded.json -o edited.fixture
```
…
Skill directory: /tmp/agent-lynx-perf-docs-20261030/node_modules/@lynx-js/skill-lynx-recorder-fixturepython3 · fixture_tool.py summary13 条运行时操作
# FIXTURE_SKILL_DIR 是上一步返回的目录;使用 savedFiles 中的实际文件名,兼容编码后的 TestBench 文件。
python3 "$FIXTURE_SKILL_DIR/scripts/fixture_tool.py" summary ./settings-recording-session3.json=== TestBench Fixture Summary ===
Top-level keys: ['Action List', 'Invoked Method Data', 'Callback', 'Component List', 'Debug Info', 'SharedData', 'Scripts', 'Config']
Config:
Screen: 1280.0 x 2707.0
JSB Settings: {'strict': True}
Action List: 13 entries
SendTouchEvent: 3
updateViewPort: 2
sendGlobalEvent: 2
sendEventAndroid: 2
setThreadStrategy: 1
setGlobalProps: 1
loadTemplate: 1
SendCustomEvent: 1
Invoked Method Data: 0 entries
Callback: 0 entries
Component List: ['scroll-view', 'view', 'text', 'raw-text']已保存 settings-recording-session3.json。产物检查为 healthy: true,包含 1 次 loadTemplate 和 13 条运行时操作;其中 SendTouchEvent 有 3 条。模板加载与这次操作的输入都已进入录制。
fixture 摘要也确认了这些内容。可以继续把该文件交给支持 Recorder 的宿主回放;如果需要调整回放输入,再使用 fixture skill 检查和编辑相应 section。
recorder end 的 savedFiles 是实际输出路径,可能带有 session 后缀,也可能包含多个文件。上面的 $FIXTURE_SKILL_DIR 来自 skills get lynx-recorder-fixture 返回的目录;摘要脚本读取实际保存的文件,而不是假定 -o 的名字就是最终文件名。
录制与产物处理能力
录制要求宿主具备 Recorder 能力。如果开始时返回 restartRequired: true,重启应用、重新确认 client 并再次开始,之后再打开目标页面。
.json 后缀不一定代表明文 JSON:Recorder 产物可能是 base64(zlib(JSON))。fixture skill 的工具可以处理这种编码;编辑时需要保持操作顺序、调用与回调关联,以及模板内容。healthy 和 hasTemplate 用于确认产物结构与必要数据,实际回放仍由支持 Recorder 的宿主执行。