Turn saved Arena.ai Agent-Mode pages into one clean, audit-ready Markdown transcript of the AI's performance.
Drop the saves in → get a .md containing, in chronological order:
- the user brief (with attachment chips),
- every thinking chain ("Thought for N seconds…"),
- every narration line between tool calls,
- every tool call —
used Bash · 295ms,Ran commands · 2,Edit path×7,Write path · 64 lines,Start …— with the command and stdout in full wherever that section was expanded in the saved page, - presented files (file cards + their preview content),
- the final response (headings, lists, tables, code, links),
- an audit summary: think time, tool time, non-zero exits, timeouts, files written/edited, artifacts delivered, code-block count, and an honesty note listing what was saved collapsed (and therefore not in the page save).
Removed by design: sidebar conversation history, account name/e-mail, "New Chat / Leaderboard / Search" chrome, header bars, input boxes, recaptcha frames, workspace panels — everything outside the transcript itself.
Nothing is required — zero dependencies (pure standard library).
Optional, for native drag-and-drop in the GUI:
pip install tkinterdnd2
(Tk itself ships with Python on Windows. On Linux: sudo apt install python3-tk.)
python arena_audit_gui.py
- Drag saves onto the window (or Add files… / Add folder…).
Accepted:
.txt(Blink "webpage, complete" saves),.mhtml,.mht,.eml,.html— folders are scanned recursively. - Toggle what to include (thinking, narration, tool output, previews, stats, emoji markers, e-mail redaction, output-size cap).
- Convert ▸ — each file is marker-verified first
(
data-agent-transcript-message,data-chat-message-id,data-streamdown="code-block", thought count, collapsible count) and the result is logged. Output lands next to each save (or a chosen folder) as<name>-audit.md.
python arena_audit.py save1.txt save2.mhtml -o audit_out/
python arena_audit.py saves_folder/ # scans the folder
python arena_audit.py save.txt --verify # only verify the markers
python arena_audit.py save.txt --no-thinking --redact-emails
Options: --no-thinking --no-narration --no-tools --no-tool-output --no-previews --no-stats --no-emoji --redact-emails --max-output-chars N (0 = unlimited).
from arena_audit import Options, convert_file, describe_save
print(describe_save("MCPDEvelopment.txt")) # marker sanity check
convert_file("MCPDEvelopment.txt", Options(include_stats=True))The converter never scrapes the visible page text. It anchors on Arena's own DOM contract:
| marker | meaning |
|---|---|
data-agent-transcript-message |
one top-level message (user or agent) |
data-chat-message-id |
message id (kept in the audit doc) |
data-user-message-layout / data-user-message-body-row |
user turn + attachments |
data-streamdown="code-block" (+ code-block-header/body) |
rendered fenced code |
data-streamdown="inline-code"/"link"/"strong"/… |
rendered inline markdown |
first <button aria-expanded> of a stream block |
collapsible section (thought / tool / group) |
The chronological stream is reconstructed from the container holding the block sequence; each block is classified (thought / narration / tool / group / edit / write / process / file card / final), then re-rendered to Markdown. Everything outside the transcript containers is ignored, which is what removes the sidebar, the account button and the rest of the chrome structurally rather than by filtering text.
Audit-honesty: collapsed sections in the original page save do not contain
their command/output bodies (the DOM really has only the toggle button). The
archiver marks those explicitly (*(collapsed in save — command body not captured)*) and the summary counts them, so an auditor always knows what is
verbatim and what wasn't captured. Expand sections in the Arena UI and re-save
to capture them.
| file | purpose |
|---|---|
arena_audit.py |
parser + Markdown builder + CLI (stdlib only) |
arena_audit_gui.py |
Tkinter drag-and-drop batch converter |