Skip to content

fix(shared-ui): media lanes dump raw base64 into the trace webview #1610

Description

@asclearuc

Description

The Trace panel in the VS Code extension freezes when a pipeline returns audio,
video, or image media. The final-result renderer cannot recognise the media
result shapes, so it falls through to the raw JsonTree fallback — which prints
the entire base64 payload (a multi-megabyte string for any real video) into a
single DOM text node with no length limit.

Two independent defects combine to cause this:

  1. The type guards never match the result shape. render_final.tsx wraps the
    audio/video lanes as {audio: v} / {video: v}, then calls isAudio / isVideo
    on that envelope. But those guards look for .action / .format at the top
    level — they are the AVI stream-trace guards, reused for the final result,
    which is a different shape. So the guard is undefined and the fallback is
    unconditional for audio and video. (isImage can fire, but only on the
    {format, width} metadata shape, never on {mime_type, image: <base64>}.)

  2. The fallback has no length cap. packages/shared-ui/.../trace/JsonTree.tsx
    renders string leaves as JSON.stringify(value) with wordBreak: 'break-all'
    and defaultExpanded={1}, so the full base64 string lands in the DOM on first
    paint. The sibling component at apps/events-ui/src/components/JsonTree.tsx:43
    already caps strings at 200 chars — the shared-ui copy is simply missing it.

Scope note: the video and image dump is pre-existing on develop (its
writeVideo/writeImage already emit base64). PR #1525 does not cause it and
touches no UI files. PR #1525 only makes the audio lane worse — it changes
that lane from a tiny {url, aviAction, mimeType, size} dict (harmless in the
fallback) to {mime_type, audio: <base64>, metadata}, which then hits the same
uncapped fallback.

Steps to Reproduce

Reproduces on plain develop — no PR branches, no merge required:

  1. git switch develop && ./builder build vscode
  2. Open the VS Code extension → Project view. Load a video pipeline:
    dropper → parse → frame_grabber → detect → video_composer → response_video.
  3. Drop a video file (e.g. testdata/misc/BBC - Tear down this wall.mp4).
  4. Open the Trace panel → final result → the video section.
  5. The section shows a JsonTree with mime_type and a multi-megabyte video
    string; the webview stalls.

For the audio regression specifically (requires the #1525 branch): use a
dropper → parse → audio_tts → response_audio pipeline and observe the base64
dump in the audio section; the same pipe on develop renders a tiny 4-field
dict instead.

Expected vs Actual Behavior

Expected: each media lane renders an inline player — <video controls>,
<audio controls>, or <img> — sourced from the payload, with the descriptor
metadata shown alongside. At an absolute minimum, no unbounded string is ever
written to the DOM.

Actual: the raw base64 payload is dumped into a single DOM text node,
freezing the webview for any real media file.

Severity

P1 - High (major feature broken, no workaround)

Platform

  • Windows (observed)
  • macOS
  • Linux

(The code path is platform-independent; all platforms are affected.)

Version / Environment

Branch develop; VS Code extension webview (shared-ui trace renderers).
Also affects the dropper UI: apps/dropper-ui/src/utils/dropperUtils.ts:202
has no audio/video case, so those lanes hit the default branch and only
console.warn.

Proposed fix (for reference)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions