Skip to content

feat(web): show inline previews for images agents refer to - #216

Merged
badcuban merged 4 commits into
mainfrom
feat/inline-image-previews
Sep 3, 2026
Merged

feat(web): show inline previews for images agents refer to#216
badcuban merged 4 commits into
mainfrom
feat/inline-image-previews

Conversation

@badcuban

@badcuban badcuban commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Problem

When an agent takes a screenshot, the user only gets a path. A path in prose stays plain text, ![alt](C:\...\shot.png) renders as a broken file:// image, and "Viewed image" tool rows show a name box instead of a picture. Files saved outside the project root (temp dirs, where agents usually put screenshots) could not be opened at all.

Fix

One loader turns any local image reference into a thumbnail, with the existing file chip kept underneath as the caption. A missing or unreadable file leaves the chip exactly as it looked before; there is no error state.

  • Prose, inline code, links, markdown images in ChatMarkdown all render the thumbnail. Bare prose paths are detected only for unambiguous forms (drive, absolute, ~/, ./, ../) and only once a block has settled, so a half-streamed path never triggers a fetch.
  • Tool rows (Claude Read of an image, Codex view_image, MCP screenshot tools) read the base64 image blocks already stored on the raw tool result, or lazily load the named path when the row renders in the virtualized list.
  • Server: projects.readFile now serves a target outside the workspace root only when its bytes sniff as a raster image (PNG/JPEG/GIF/WebP/BMP/AVIF). Text, SVG, and mis-named files stay refused exactly as before.
  • File viewer opens outside-root images instead of bouncing to an external editor.

Bytes travel over the existing projects.readFile WebSocket RPC and nothing else, so relay-paired (phonelink) and direct remote clients need no special handling; relay frame chunking already covers the base64 response.

Tests

  • WorkspaceFileSystem.test.ts: outside-root PNG served, outside-root text rejected, .png with script bytes rejected.
  • markdown-links.test.ts: bare image path detection and boundaries.
  • session-logic.test.ts: path-only tool image, inline image blocks on a tool result.
  • ChatMarkdown.browser.tsx: thumbnail from a mocked read, chip-only when the file is missing.

Gates: fmt, lint, server/web typecheck, targeted unit suites, and the ChatMarkdown / MessagesTimeline / ChatView browser suites are green.

An agent that took a screenshot could only hand the user a path. Paths in
prose stayed plain text, markdown images rendered as a broken file:// img,
and "Viewed image" tool rows showed a name box because Claude's Read, Codex's
view_image and MCP screenshot tools only name the file or bury the bytes in
the raw tool result. Files outside the project root could not be opened at
all.

Every surface now goes through one loader that fetches the file over the
existing projects.readFile WebSocket RPC (so relay-paired and remote clients
work unchanged) and shows a thumbnail with the file chip beneath it; a
missing file leaves the chip exactly as before. The server serves a file
outside the workspace root only when its bytes are a verified raster image.
Tool rows read image blocks already stored on the tool result, or load the
named path lazily when the row renders.
@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
threadlines Ready Ready Preview Sep 3, 2026 6:12pm UTC

Request Review

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL labels Sep 3, 2026
@badcuban
badcuban merged commit 2d4fa2c into main Sep 3, 2026
16 checks passed
@badcuban
badcuban deleted the feat/inline-image-previews branch September 3, 2026 18:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant