Skip to content

feat(web): render transcript text as markdown and payloads as JSON - #631

Merged
JeremyFunk merged 3 commits into
mainfrom
feat/transcript-markdown-json-rendering
Aug 25, 2026
Merged

feat(web): render transcript text as markdown and payloads as JSON#631
JeremyFunk merged 3 commits into
mainfrom
feat/transcript-markdown-json-rendering

Conversation

@JeremyFunk

@JeremyFunk JeremyFunk commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #624: the Transcript view rendered every captured body as plain pre-wrapped text. This gives each kind of body the reading it deserves, while keeping the captured bytes one click away.

What changed

Markdown for message text. User, assistant, prompt and (expanded) system bodies render through the existing MessageResponse pipeline (Streamdown + Shiki/KaTeX/Mermaid), so replies with code fences, lists and inline code read the way the chat surfaces already do. The collapsed system preview stays the plain first line — a one-line elision of markdown source reads better raw.

JSON detection for payloads. Tool arguments/results, subagent task prompts/returns and failed-call status messages go through a shared useJsonPayload hook: the same tryParseJson object/array test the log body uses, then pretty-print + sugar-high highlighting on a hit. Everything else stays verbatim — including an emitter-truncated prefix, which fails the parse on purpose rather than being dressed up as a whole document. Each payload gets a copy button that copies what is displayed.

A rendered ↔ raw selector on every rendered body. Rendering is a reading of the capture, and a reading can hide things — whitespace, key order, a literal **. Each rendered body carries a small segment pair (md | raw on message text, json | raw on payloads) where the selected segment is the view you are in; switching to raw shows the captured text verbatim and points the copy button at it. The pair only appears where the two views actually differ, and the choice lives in the existing openRows set so it survives the row scrolling out of the virtualizer.

Tool payloads start collapsed. The "Tool payloads" chip now defaults off; every card opens on its one-line size summary.

ClampedText gained html (highlighted markup) and body (rendered node) modes so all of the above still clamps and "Show full"s identically; text remains the measurement source. The lab fixture's closing replies and investigation system prompt are now markdown so /lab/agent-session exercises the new paths.

Verification

  • All 250 agent-session tests and tsc pass.
  • Verified in the lab harness: markdown replies render and switch to raw source, JSON arguments pretty-print/highlight and switch to the captured one-liner, plain-text payloads show no selector, the failed-call error renders with its copy button, and virtualized rows re-measure cleanly through every switch.

Known trade-off

JSON pretty-printing goes through JSON.parse/stringify — the same accepted pattern as the log body viewer — so an integer above 2^53 inside a payload displays and copies with precision loss. The raw view is the escape hatch; a lexeme-preserving re-indenter is the fix if this bites in practice.

🤖 Generated with Claude Code

User, assistant, prompt and (expanded) system bodies go through the
existing MessageResponse markdown pipeline; tool arguments/results,
subagent task prompts/returns and failed-call status messages are
pretty-printed and highlighted where they parse as JSON (same tryParseJson
test as the log body), each with a copy button that copies what is
displayed. Every rendered body keeps a raw switch back to the captured
text, held in openRows so the choice survives virtualization. Tool
payloads now start collapsed, and the lab fixture gained markdown replies
and a markdown system prompt so the harness exercises the new paths.
A lone pressed icon named either the current view or the one a click
would bring, depending on who read it. The switch is now two labelled
segments — md|raw or json|raw — where the selected segment is the view
the reader is in.
…own-json-rendering

# Conflicts:
#	apps/web/src/components/agent-sessions/session-detail/session-transcript.tsx
@JeremyFunk
JeremyFunk merged commit 818bb70 into main Aug 25, 2026
33 checks passed
@JeremyFunk
JeremyFunk deleted the feat/transcript-markdown-json-rendering branch August 25, 2026 15:15
@github-actions

Copy link
Copy Markdown

🍁 Maple PR preview

Warning

Preview cleanup could not be confirmed. The Alchemy teardown outcome was skipped.

Final commit b92eb3a · View workflow run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant