Files
wehub-resource-sync f3d80b4628
Auto Release / auto-release (push) Failing after 1s
CI / lint (push) Failing after 0s
CI / screenshot-quality (push) Failing after 3s
CI / pr-policy (push) Has been skipped
CI / test (3.11) (push) Failing after 0s
CI / test (3.12) (push) Failing after 0s
CI / test (3.13) (push) Failing after 3s
CI / coverage (push) Failing after 1s
Legibility / legibility (push) Failing after 3s
chore: import upstream snapshot with attribution
2026-07-13 12:31:48 +08:00

172 lines
5.5 KiB
Python

"""Record a walkthrough of the claude-tap trace viewer using Playwright.
Produces:
- Video at 1440x900 in .agents/recordings/video/
- 10+ high-quality screenshots in .agents/recordings/
"""
from __future__ import annotations
import pathlib
import time
from playwright.sync_api import sync_playwright
TRACE_HTML = "/tmp/codex-tap-demo/.traces/trace_20260228_004827.html"
REPO_ROOT = pathlib.Path(__file__).resolve().parent.parent
SCREENSHOT_DIR = REPO_ROOT / ".agents" / "recordings"
VIDEO_DIR = SCREENSHOT_DIR / "video"
WIDTH, HEIGHT = 1440, 900
def _wait(ms: int = 600) -> None:
time.sleep(ms / 1000)
def _screenshot(page, name: str) -> None:
path = SCREENSHOT_DIR / f"{name}.png"
page.screenshot(path=str(path), full_page=False)
print(f" screenshot: {path.name}")
def main() -> None:
VIDEO_DIR.mkdir(parents=True, exist_ok=True)
with sync_playwright() as pw:
browser = pw.chromium.launch(headless=True)
context = browser.new_context(
viewport={"width": WIDTH, "height": HEIGHT},
record_video_dir=str(VIDEO_DIR),
record_video_size={"width": WIDTH, "height": HEIGHT},
)
page = context.new_page()
page.goto(f"file://{TRACE_HTML}")
page.wait_for_load_state("networkidle")
_wait(800)
# --- Step 1: Click Turn 1 -> expand Tools & SSE Events ---
print("Step 1: Turn 1 + expand Tools & SSE Events")
page.mouse.click(150, 125)
_wait(500)
_screenshot(page, "viewer-01-turn1-overview")
# Expand "Tools" section
page.evaluate("""() => {
const headers = document.querySelectorAll('.section-header');
for (const h of headers) {
if (h.textContent.includes('Tools')) { h.click(); break; }
}
}""")
_wait(400)
# Expand "SSE Events" section
page.evaluate("""() => {
const headers = document.querySelectorAll('.section-header');
for (const h of headers) {
if (h.textContent.includes('SSE Events')) { h.click(); break; }
}
}""")
_wait(400)
_screenshot(page, "viewer-02-tools-sse-expanded")
# --- Step 2: Click "Request JSON" -> expand "Full JSON" -> scroll ---
print("Step 2: Request JSON + Full JSON + scroll")
page.evaluate("""() => {
const btns = document.querySelectorAll('.act-btn');
for (const b of btns) {
if (b.textContent.includes('Request')) { b.click(); break; }
}
}""")
_wait(400)
# Expand "Full JSON"
page.evaluate("""() => {
const headers = document.querySelectorAll('.section-header');
for (const h of headers) {
if (h.textContent.includes('Full JSON')) { h.click(); break; }
}
}""")
_wait(400)
# Scroll detail panel down
page.evaluate("document.getElementById('detail').scrollTop = 500")
_wait(400)
_screenshot(page, "viewer-03-request-json-scrolled")
# --- Step 3: Click Turn 5 ---
print("Step 3: Turn 5")
page.mouse.click(150, 401)
_wait(500)
_screenshot(page, "viewer-04-turn5")
# --- Step 4: Click "Diff with Prev" ---
print("Step 4: Diff with Prev")
page.evaluate("""() => {
const btns = document.querySelectorAll('.act-btn');
for (const b of btns) {
if (b.textContent.includes('Diff')) { b.click(); break; }
}
}""")
_wait(600)
_screenshot(page, "viewer-05-diff")
# Close diff overlay
page.evaluate("document.querySelector('.diff-close')?.click()")
_wait(300)
# --- Step 5: Click "cURL" ---
print("Step 5: cURL")
page.evaluate("""() => {
const btns = document.querySelectorAll('.act-btn');
for (const b of btns) {
if (b.textContent.includes('cURL')) { b.click(); break; }
}
}""")
_wait(400)
_screenshot(page, "viewer-06-curl")
# --- Step 6: Click Turn 10 ---
print("Step 6: Turn 10")
page.mouse.click(150, 746)
_wait(500)
_screenshot(page, "viewer-07-turn10")
# --- Step 7: Toggle dark mode ---
print("Step 7: Dark mode toggle")
# Dismiss any overlay that might be blocking
page.evaluate("document.querySelector('.diff-overlay')?.remove()")
_wait(200)
page.click("#theme-toggle")
_wait(500)
_screenshot(page, "viewer-08-dark-mode")
# --- Step 8: Scroll sidebar down ---
print("Step 8: Scroll sidebar to show turns 11-18")
page.evaluate("document.getElementById('sidebar').scrollTop = 700")
_wait(400)
_screenshot(page, "viewer-09-sidebar-scrolled")
# --- Step 9: Click last visible sidebar item ---
print("Step 9: Click last visible turn")
page.evaluate("""() => {
const items = document.querySelectorAll('.sidebar-item');
if (items.length > 0) items[items.length - 1].click();
}""")
_wait(500)
_screenshot(page, "viewer-10-last-turn")
# --- Step 10: Final wide screenshot ---
print("Step 10: Final wide screenshot")
_screenshot(page, "viewer-11-final-wide")
# Close to finalize video
context.close()
browser.close()
print(f"\nDone. Video saved to {VIDEO_DIR}/")
print(f"Screenshots saved to {SCREENSHOT_DIR}/")
if __name__ == "__main__":
main()